[WIN32SS] Rewrite PDEVOBJ_pdmMatchDevMode to LDEVOBJ_bProbeAndCaptureDevmode

- make it return a new allocated PDEVMODEW instead of a pointer into
  existing PGRAPHICS_DEVICE (usefull when available display modes can
  dynamically change: VirtualBox, RDP, ...)
- update all callers
This commit is contained in:
Hervé Poussineau 2022-01-09 10:44:53 +01:00 committed by hpoussin
parent 21ddeb76d9
commit 3cb1dd8ab2
6 changed files with 114 additions and 83 deletions

View file

@ -130,25 +130,18 @@ EngpPopulateDeviceModeList(
_In_ PDEVMODEW pdmDefault)
{
PDEVMODEINFO pdminfo;
PDEVMODEW pdm;
PDEVMODEW pdm, pdmSelected;
ULONG i;
BOOLEAN bModeMatch = FALSE;
ASSERT(pGraphicsDevice->pdevmodeInfo == NULL);
ASSERT(pGraphicsDevice->pDevModeList == NULL);
if (!LDEVOBJ_bBuildDevmodeList(pGraphicsDevice))
if (!LDEVOBJ_bProbeAndCaptureDevmode(pGraphicsDevice, pdmDefault, &pdmSelected, TRUE))
{
ERR("LDEVOBJ_bBuildDevmodeList() failed\n");
ERR("LDEVOBJ_bProbeAndCaptureDevmode() failed\n");
return FALSE;
}
TRACE("Looking for mode %lux%lux%lu(%lu Hz)\n",
pdmDefault->dmPelsWidth,
pdmDefault->dmPelsHeight,
pdmDefault->dmBitsPerPel,
pdmDefault->dmDisplayFrequency);
/* Loop through all DEVMODEINFOs */
for (pdminfo = pGraphicsDevice->pdevmodeInfo, i = 0;
pdminfo;
@ -159,20 +152,14 @@ EngpPopulateDeviceModeList(
{
pdm = pGraphicsDevice->pDevModeList[i].pdm;
/* Compare with the default entry */
if (!bModeMatch &&
pdm->dmBitsPerPel == pdmDefault->dmBitsPerPel &&
pdm->dmPelsWidth == pdmDefault->dmPelsWidth &&
pdm->dmPelsHeight == pdmDefault->dmPelsHeight)
/* Compare with the selected entry */
if (pdm->dmSize == pdmSelected->dmSize &&
RtlCompareMemory(pdm, pdmSelected, pdm->dmSize) == pdm->dmSize)
{
pGraphicsDevice->iDefaultMode = i;
pGraphicsDevice->iCurrentMode = i;
TRACE("Found default entry: %lu '%ls'\n", i, pdm->dmDeviceName);
if (pdm->dmDisplayFrequency == pdmDefault->dmDisplayFrequency)
{
/* Uh oh, even the display frequency matches. */
bModeMatch = TRUE;
}
break;
}
}
}

View file

@ -558,6 +558,77 @@ LDEVOBJ_bBuildDevmodeList(
return TRUE;
}
BOOL
LDEVOBJ_bProbeAndCaptureDevmode(
_Inout_ PGRAPHICS_DEVICE pGraphicsDevice,
_In_ PDEVMODEW RequestedMode,
_Out_ PDEVMODEW *pSelectedMode,
_In_ BOOL bSearchClosestMode)
{
PDEVMODEW pdmCurrent, pdm, pdmSelected = NULL;
ULONG i;
DWORD dwFields;
if (!LDEVOBJ_bBuildDevmodeList(pGraphicsDevice))
return FALSE;
/* Search if requested mode exists */
for (i = 0; i < pGraphicsDevice->cDevModes; i++)
{
pdmCurrent = pGraphicsDevice->pDevModeList[i].pdm;
/* Compare asked DEVMODE fields
* Only compare those that are valid in both DEVMODE structs */
dwFields = pdmCurrent->dmFields & RequestedMode->dmFields;
/* For now, we only need those */
if ((dwFields & DM_BITSPERPEL) &&
(pdmCurrent->dmBitsPerPel != RequestedMode->dmBitsPerPel)) continue;
if ((dwFields & DM_PELSWIDTH) &&
(pdmCurrent->dmPelsWidth != RequestedMode->dmPelsWidth)) continue;
if ((dwFields & DM_PELSHEIGHT) &&
(pdmCurrent->dmPelsHeight != RequestedMode->dmPelsHeight)) continue;
if ((dwFields & DM_DISPLAYFREQUENCY) &&
(pdmCurrent->dmDisplayFrequency != RequestedMode->dmDisplayFrequency)) continue;
pdmSelected = pdmCurrent;
break;
}
if (!pdmSelected)
{
WARN("Requested mode not found (%dx%dx%d %d Hz)\n",
RequestedMode->dmFields & DM_PELSWIDTH ? RequestedMode->dmPelsWidth : 0,
RequestedMode->dmFields & DM_PELSHEIGHT ? RequestedMode->dmPelsHeight : 0,
RequestedMode->dmFields & DM_BITSPERPEL ? RequestedMode->dmBitsPerPel : 0,
RequestedMode->dmFields & DM_DISPLAYFREQUENCY ? RequestedMode->dmDisplayFrequency : 0);
if (!bSearchClosestMode || pGraphicsDevice->cDevModes == 0)
return FALSE;
/* FIXME: need to search the closest mode instead of taking the first one */
pdmSelected = pGraphicsDevice->pDevModeList[0].pdm;
WARN("Replacing it by %dx%dx%d %d Hz\n",
pdmSelected->dmFields & DM_PELSWIDTH ? pdmSelected->dmPelsWidth : 0,
pdmSelected->dmFields & DM_PELSHEIGHT ? pdmSelected->dmPelsHeight : 0,
pdmSelected->dmFields & DM_BITSPERPEL ? pdmSelected->dmBitsPerPel : 0,
pdmSelected->dmFields & DM_DISPLAYFREQUENCY ? pdmSelected->dmDisplayFrequency : 0);
}
/* Allocate memory for output */
pdm = ExAllocatePoolZero(PagedPool, pdmSelected->dmSize + pdmSelected->dmDriverExtra, GDITAG_DEVMODE);
if (!pdm)
return FALSE;
/* Copy selected mode */
RtlCopyMemory(pdm, pdmSelected, pdmSelected->dmSize);
RtlCopyMemory((PVOID)((ULONG_PTR)pdm + pdm->dmSize),
(PVOID)((ULONG_PTR)pdmSelected + pdmSelected->dmSize),
pdmSelected->dmDriverExtra);
*pSelectedMode = pdm;
return TRUE;
}
/** Exported functions ********************************************************/
HANDLE

View file

@ -56,6 +56,14 @@ BOOL
LDEVOBJ_bBuildDevmodeList(
_Inout_ PGRAPHICS_DEVICE pGraphicsDevice);
/* This function selects the best available mode corresponding to requested mode */
BOOL
LDEVOBJ_bProbeAndCaptureDevmode(
_Inout_ PGRAPHICS_DEVICE pGraphicsDevice,
_In_ PDEVMODEW RequestedMode,
_Out_ PDEVMODEW *pSelectedMode,
_In_ BOOL bSearchClosestMode);
PLDEVOBJ
NTAPI
EngGetLDEV(

View file

@ -83,6 +83,8 @@ PDEVOBJ_vDeletePDEV(
PPDEVOBJ ppdev)
{
EngDeleteSemaphore(ppdev->hsemDevLock);
if (ppdev->pdmwDev)
ExFreePoolWithTag(ppdev->pdmwDev, GDITAG_DEVMODE);
if (ppdev->pEDDgpl)
ExFreePoolWithTag(ppdev->pEDDgpl, GDITAG_PDEV);
ExFreePoolWithTag(ppdev, GDITAG_PDEV);
@ -266,18 +268,13 @@ PDEVOBJ_vRefreshModeList(
{
PGRAPHICS_DEVICE pGraphicsDevice;
PDEVMODEINFO pdminfo, pdmiNext;
DEVMODEW dmDefault;
DEVMODEW dmCurrent;
PDEVMODEW newDevMode;
/* Lock the PDEV */
EngAcquireSemaphore(ppdev->hsemDevLock);
pGraphicsDevice = ppdev->pGraphicsDevice;
/* Remember our default mode */
dmDefault = *pGraphicsDevice->pDevModeList[pGraphicsDevice->iDefaultMode].pdm;
dmCurrent = *ppdev->pdmwDev;
/* Clear out the modes */
for (pdminfo = pGraphicsDevice->pdevmodeInfo;
pdminfo;
@ -290,57 +287,17 @@ PDEVOBJ_vRefreshModeList(
ExFreePoolWithTag(pGraphicsDevice->pDevModeList, GDITAG_GDEVICE);
pGraphicsDevice->pDevModeList = NULL;
/* Now re-populate the list */
if (!EngpPopulateDeviceModeList(pGraphicsDevice, &dmDefault))
/* Search an available display mode */
if (LDEVOBJ_bProbeAndCaptureDevmode(pGraphicsDevice, ppdev->pdmwDev, &newDevMode, TRUE))
{
DPRINT1("FIXME: EngpPopulateDeviceModeList failed, we just destroyed a perfectly good mode list\n");
ExFreePoolWithTag(ppdev->pdmwDev, GDITAG_DEVMODE);
ppdev->pdmwDev = newDevMode;
}
ppdev->pdmwDev = PDEVOBJ_pdmMatchDevMode(ppdev, &dmCurrent);
/* Unlock PDEV */
EngReleaseSemaphore(ppdev->hsemDevLock);
}
PDEVMODEW
NTAPI
PDEVOBJ_pdmMatchDevMode(
PPDEVOBJ ppdev,
PDEVMODEW pdm)
{
PGRAPHICS_DEVICE pGraphicsDevice;
PDEVMODEW pdmCurrent;
ULONG i;
DWORD dwFields;
pGraphicsDevice = ppdev->pGraphicsDevice;
for (i = 0; i < pGraphicsDevice->cDevModes; i++)
{
pdmCurrent = pGraphicsDevice->pDevModeList[i].pdm;
/* Compare asked DEVMODE fields
* Only compare those that are valid in both DEVMODE structs */
dwFields = pdmCurrent->dmFields & pdm->dmFields;
/* For now, we only need those */
if ((dwFields & DM_BITSPERPEL) &&
(pdmCurrent->dmBitsPerPel != pdm->dmBitsPerPel)) continue;
if ((dwFields & DM_PELSWIDTH) &&
(pdmCurrent->dmPelsWidth != pdm->dmPelsWidth)) continue;
if ((dwFields & DM_PELSHEIGHT) &&
(pdmCurrent->dmPelsHeight != pdm->dmPelsHeight)) continue;
if ((dwFields & DM_DISPLAYFREQUENCY) &&
(pdmCurrent->dmDisplayFrequency != pdm->dmDisplayFrequency)) continue;
/* Match! Return the DEVMODE */
return pdmCurrent;
}
/* Nothing found */
return NULL;
}
static
PPDEVOBJ
EngpCreatePDEV(
@ -349,6 +306,7 @@ EngpCreatePDEV(
{
PGRAPHICS_DEVICE pGraphicsDevice;
PPDEVOBJ ppdev;
PDEVMODEW newDevMode;
DPRINT("EngpCreatePDEV(%wZ, %p)\n", pustrDeviceName, pdm);
@ -410,7 +368,13 @@ EngpCreatePDEV(
ppdev->hSpooler = ppdev->pGraphicsDevice->DeviceObject;
// Should we change the ative mode of pGraphicsDevice ?
ppdev->pdmwDev = PDEVOBJ_pdmMatchDevMode(ppdev, pdm);
if (!LDEVOBJ_bProbeAndCaptureDevmode(pGraphicsDevice, pdm, &newDevMode, TRUE))
{
DPRINT1("LDEVOBJ_bProbeAndCaptureDevmode() failed\n");
PDEVOBJ_vRelease(ppdev);
return NULL;
}
ppdev->pdmwDev = newDevMode;
/* FIXME! */
ppdev->flFlags = PDEV_DISPLAY;
@ -525,7 +489,7 @@ PDEVOBJ_bSwitchMode(
DPRINT1("PDEVOBJ_bSwitchMode, ppdev = %p, pSurface = %p\n", ppdev, ppdev->pSurface);
// Lookup the GraphicsDevice + select DEVMODE
// pdm = PDEVOBJ_pdmMatchDevMode(ppdev, pdm);
// pdm = LDEVOBJ_bProbeAndCaptureDevmode(ppdev, pdm);
/* 1. Temporarily disable the current PDEV and reset video to its default mode */
if (!ppdev->pfn.AssertMode(ppdev->dhpdev, FALSE))

View file

@ -213,10 +213,4 @@ PDEVOBJ_bSwitchMode(
PPDEVOBJ ppdev,
PDEVMODEW pdm);
PDEVMODEW
NTAPI
PDEVOBJ_pdmMatchDevMode(
PPDEVOBJ ppdev,
PDEVMODEW pdm);
#endif /* !__WIN32K_PDEVOBJ_H */

View file

@ -657,6 +657,7 @@ UserChangeDisplaySettings(
PPDEVOBJ ppdev;
WORD OrigBC;
//PDESKTOP pdesk;
PDEVMODEW newDevMode = NULL;
/* If no DEVMODE is given, use registry settings */
if (!pdm)
@ -707,8 +708,7 @@ UserChangeDisplaySettings(
dm.dmDisplayFrequency = ppdev->pdmwDev->dmDisplayFrequency;
/* Look for the requested DEVMODE */
pdm = PDEVOBJ_pdmMatchDevMode(ppdev, &dm);
if (!pdm)
if (!LDEVOBJ_bProbeAndCaptureDevmode(ppdev->pGraphicsDevice, &dm, &newDevMode, FALSE))
{
ERR("Could not find a matching DEVMODE\n");
lResult = DISP_CHANGE_BADMODE;
@ -729,7 +729,7 @@ UserChangeDisplaySettings(
if (NT_SUCCESS(Status))
{
/* Store the settings */
RegWriteDisplaySettings(hkey, pdm);
RegWriteDisplaySettings(hkey, newDevMode);
/* Close the registry key */
ZwClose(hkey);
@ -742,7 +742,9 @@ UserChangeDisplaySettings(
}
/* Check if DEVMODE matches the current mode */
if (pdm == ppdev->pdmwDev && !(flags & CDS_RESET))
if (newDevMode->dmSize == ppdev->pdmwDev->dmSize &&
RtlCompareMemory(newDevMode, ppdev->pdmwDev, newDevMode->dmSize) == newDevMode->dmSize &&
!(flags & CDS_RESET))
{
ERR("DEVMODE matches, nothing to do\n");
goto leave;
@ -759,7 +761,7 @@ UserChangeDisplaySettings(
pvOldCursor = UserSetCursor(NULL, TRUE);
/* Do the mode switch */
ulResult = PDEVOBJ_bSwitchMode(ppdev, pdm);
ulResult = PDEVOBJ_bSwitchMode(ppdev, newDevMode);
/* Restore mouse pointer, no hooks called */
pvOldCursor = UserSetCursor(pvOldCursor, TRUE);
@ -781,6 +783,8 @@ UserChangeDisplaySettings(
{
/* Setting mode succeeded */
lResult = DISP_CHANGE_SUCCESSFUL;
ExFreePoolWithTag(ppdev->pdmwDev, GDITAG_DEVMODE);
ppdev->pdmwDev = newDevMode;
UserUpdateFullscreen(flags);
@ -847,6 +851,9 @@ UserChangeDisplaySettings(
}
leave:
if (newDevMode && newDevMode != ppdev->pdmwDev)
ExFreePoolWithTag(newDevMode, GDITAG_DEVMODE);
/* Release the PDEV */
PDEVOBJ_vRelease(ppdev);