https://git.reactos.org/?p=reactos.git;a=commitdiff;h=333ce14dad9697eece926…
commit 333ce14dad9697eece92641a8d86650a19af660e
Author: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org>
AuthorDate: Wed Jan 2 20:55:40 2019 +0100
Commit: Hermès Bélusca-Maïto <hermes.belusca-maito(a)reactos.org>
CommitDate: Wed Jan 2 21:12:22 2019 +0100
[WIN32SS] Try to recover display when changing the display mode fails for whatever
reason.
This helps when e.g. changing the resolution on the Dell Latitude D531,
which reports that it supports large resolutions (e.g. 1920x1440x32 and
others larger than 1024x768x32) but fails to apply these.
This usually happens because PDEVOBJ_pSurface(), and more precisely
ppdev->pldev->pfn.EnableSurface(), fails for these resolutions.
- PDEVOBJ_bSwitchMode(): Set the new video mode, or restore the original
one in case of failure + release the allocated ppdevTmp if previous
calls fail. Also unlock in reverse order of locking order.
- UserChangeDisplaySettings(): In case PDEVOBJ_pSurface() fails (but has
reverted the original video mode), we still need to refresh the
display since the display may have been messed up.
---
win32ss/gdi/eng/pdevobj.c | 22 +++++++++++-----
win32ss/user/ntuser/display.c | 59 +++++++++++++++++++++++++++----------------
2 files changed, 53 insertions(+), 28 deletions(-)
diff --git a/win32ss/gdi/eng/pdevobj.c b/win32ss/gdi/eng/pdevobj.c
index 64d1832087..85098a5843 100644
--- a/win32ss/gdi/eng/pdevobj.c
+++ b/win32ss/gdi/eng/pdevobj.c
@@ -522,10 +522,10 @@ PDEVOBJ_bSwitchMode(
// Lookup the GraphicsDevice + select DEVMODE
// pdm = PDEVOBJ_pdmMatchDevMode(ppdev, pdm);
- /* 1. Temporarily disable the current PDEV */
+ /* 1. Temporarily disable the current PDEV and reset video to its default mode */
if (!ppdev->pfn.AssertMode(ppdev->dhpdev, FALSE))
{
- DPRINT1("DrvAssertMode failed\n");
+ DPRINT1("DrvAssertMode(FALSE) failed\n");
goto leave;
}
@@ -535,7 +535,7 @@ PDEVOBJ_bSwitchMode(
if (!ppdevTmp)
{
DPRINT1("Failed to create a new PDEV\n");
- goto leave;
+ goto leave2;
}
/* 3. Create a new surface */
@@ -543,7 +543,8 @@ PDEVOBJ_bSwitchMode(
if (!pSurface)
{
DPRINT1("PDEVOBJ_pSurface failed\n");
- goto leave;
+ PDEVOBJ_vRelease(ppdevTmp);
+ goto leave2;
}
/* 4. Get DirectDraw information */
@@ -565,10 +566,19 @@ PDEVOBJ_bSwitchMode(
/* Success! */
retval = TRUE;
+
+leave2:
+ /* Set the new video mode, or restore the original one in case of failure */
+ if (!ppdev->pfn.AssertMode(ppdev->dhpdev, TRUE))
+ {
+ DPRINT1("DrvAssertMode(TRUE) failed\n");
+ }
+
leave:
- /* Unlock PDEV */
- EngReleaseSemaphore(ppdev->hsemDevLock);
+ /* Unlock everything else */
EngReleaseSemaphore(ghsemPDEV);
+ /* Unlock the PDEV */
+ EngReleaseSemaphore(ppdev->hsemDevLock);
DPRINT1("leave, ppdev = %p, pSurface = %p\n", ppdev, ppdev->pSurface);
diff --git a/win32ss/user/ntuser/display.c b/win32ss/user/ntuser/display.c
index 8ef37c9c4b..6abe5c84a5 100644
--- a/win32ss/user/ntuser/display.c
+++ b/win32ss/user/ntuser/display.c
@@ -800,38 +800,53 @@ UserChangeDisplaySettings(
pvOldCursor = UserSetCursor(pvOldCursor, TRUE);
ASSERT(pvOldCursor == NULL);
- /* Check for failure */
+ /* Check for success or failure */
if (!ulResult)
{
+ /* Setting mode failed */
ERR("Failed to set mode\n");
- lResult = (lResult == DISP_CHANGE_NOTUPDATED) ?
- DISP_CHANGE_FAILED : DISP_CHANGE_RESTART;
- goto leave;
+ /* Set the correct return value */
+ if ((flags & CDS_UPDATEREGISTRY) && (lResult !=
DISP_CHANGE_NOTUPDATED))
+ lResult = DISP_CHANGE_RESTART;
+ else
+ lResult = DISP_CHANGE_FAILED;
}
+ else
+ {
+ /* Setting mode succeeded */
+ lResult = DISP_CHANGE_SUCCESSFUL;
- UserUpdateFullscreen(flags);
+ UserUpdateFullscreen(flags);
- /* Update the system metrics */
- InitMetrics();
+ /* Update the system metrics */
+ InitMetrics();
- /* Set new size of the monitor */
- UserUpdateMonitorSize((HDEV)ppdev);
+ /* Set new size of the monitor */
+ UserUpdateMonitorSize((HDEV)ppdev);
- /* Update the SERVERINFO */
- gpsi->dmLogPixels = ppdev->gdiinfo.ulLogPixelsY;
- gpsi->Planes = ppdev->gdiinfo.cPlanes;
- gpsi->BitsPixel = ppdev->gdiinfo.cBitsPixel;
- gpsi->BitCount = gpsi->Planes * gpsi->BitsPixel;
- if (ppdev->gdiinfo.flRaster & RC_PALETTE)
- {
- gpsi->PUSIFlags |= PUSIF_PALETTEDISPLAY;
+ /* Update the SERVERINFO */
+ gpsi->dmLogPixels = ppdev->gdiinfo.ulLogPixelsY;
+ gpsi->Planes = ppdev->gdiinfo.cPlanes;
+ gpsi->BitsPixel = ppdev->gdiinfo.cBitsPixel;
+ gpsi->BitCount = gpsi->Planes * gpsi->BitsPixel;
+ if (ppdev->gdiinfo.flRaster & RC_PALETTE)
+ {
+ gpsi->PUSIFlags |= PUSIF_PALETTEDISPLAY;
+ }
+ else
+ {
+ gpsi->PUSIFlags &= ~PUSIF_PALETTEDISPLAY;
+ }
+ // Font is realized and this dc was previously set to internal DC_ATTR.
+ gpsi->cxSysFontChar = IntGetCharDimensions(hSystemBM, &tmw,
(DWORD*)&gpsi->cySysFontChar);
+ gpsi->tmSysFont = tmw;
}
- else
- gpsi->PUSIFlags &= ~PUSIF_PALETTEDISPLAY;
- // Font is realized and this dc was previously set to internal DC_ATTR.
- gpsi->cxSysFontChar = IntGetCharDimensions(hSystemBM, &tmw,
(DWORD*)&gpsi->cySysFontChar);
- gpsi->tmSysFont = tmw;
+
+ /*
+ * Refresh the display on success and even on failure,
+ * since the display may have been messed up.
+ */
/* Remove all cursor clipping */
UserClipCursor(NULL);