https://git.reactos.org/?p=reactos.git;a=commitdiff;h=3cb1dd8ab20c8b29ed4975...
commit 3cb1dd8ab20c8b29ed497518b5abb8656ac8354e Author: Hervé Poussineau hpoussin@reactos.org AuthorDate: Sun Jan 9 10:44:53 2022 +0100 Commit: hpoussin 32227662+hpoussin@users.noreply.github.com CommitDate: Fri Apr 15 23:09:16 2022 +0200
[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 --- win32ss/gdi/eng/device.c | 27 +++++----------- win32ss/gdi/eng/ldevobj.c | 71 +++++++++++++++++++++++++++++++++++++++++++ win32ss/gdi/eng/ldevobj.h | 8 +++++ win32ss/gdi/eng/pdevobj.c | 68 ++++++++++------------------------------- win32ss/gdi/eng/pdevobj.h | 6 ---- win32ss/user/ntuser/display.c | 17 ++++++++--- 6 files changed, 114 insertions(+), 83 deletions(-)
diff --git a/win32ss/gdi/eng/device.c b/win32ss/gdi/eng/device.c index 8ad49ed5fd1..4f2284fa1e6 100644 --- a/win32ss/gdi/eng/device.c +++ b/win32ss/gdi/eng/device.c @@ -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; } } } diff --git a/win32ss/gdi/eng/ldevobj.c b/win32ss/gdi/eng/ldevobj.c index e2079da8178..db46a0dfbb6 100644 --- a/win32ss/gdi/eng/ldevobj.c +++ b/win32ss/gdi/eng/ldevobj.c @@ -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 diff --git a/win32ss/gdi/eng/ldevobj.h b/win32ss/gdi/eng/ldevobj.h index cac2ec8f5e0..7b2fc2065ee 100644 --- a/win32ss/gdi/eng/ldevobj.h +++ b/win32ss/gdi/eng/ldevobj.h @@ -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( diff --git a/win32ss/gdi/eng/pdevobj.c b/win32ss/gdi/eng/pdevobj.c index e764dea384c..77b9a9fafc3 100644 --- a/win32ss/gdi/eng/pdevobj.c +++ b/win32ss/gdi/eng/pdevobj.c @@ -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)) diff --git a/win32ss/gdi/eng/pdevobj.h b/win32ss/gdi/eng/pdevobj.h index 4d22c270aa7..af4973b60f6 100644 --- a/win32ss/gdi/eng/pdevobj.h +++ b/win32ss/gdi/eng/pdevobj.h @@ -213,10 +213,4 @@ PDEVOBJ_bSwitchMode( PPDEVOBJ ppdev, PDEVMODEW pdm);
-PDEVMODEW -NTAPI -PDEVOBJ_pdmMatchDevMode( - PPDEVOBJ ppdev, - PDEVMODEW pdm); - #endif /* !__WIN32K_PDEVOBJ_H */ diff --git a/win32ss/user/ntuser/display.c b/win32ss/user/ntuser/display.c index df00c0e3974..81ed1bdb402 100644 --- a/win32ss/user/ntuser/display.c +++ b/win32ss/user/ntuser/display.c @@ -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);