From 333ce14dad9697eece92641a8d86650a19af660e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herm=C3=A8s=20B=C3=A9lusca-Ma=C3=AFto?= Date: Wed, 2 Jan 2019 20:55:40 +0100 Subject: [PATCH] [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 | 67 +++++++++++++++++++++-------------- 2 files changed, 57 insertions(+), 32 deletions(-) diff --git a/win32ss/gdi/eng/pdevobj.c b/win32ss/gdi/eng/pdevobj.c index 64d18320872..85098a58437 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 8ef37c9c4b9..6abe5c84a5c 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; - } - - UserUpdateFullscreen(flags); - - /* Update the system metrics */ - InitMetrics(); - - /* 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; + /* Set the correct return value */ + if ((flags & CDS_UPDATEREGISTRY) && (lResult != DISP_CHANGE_NOTUPDATED)) + lResult = DISP_CHANGE_RESTART; + else + lResult = DISP_CHANGE_FAILED; } 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; + { + /* Setting mode succeeded */ + lResult = DISP_CHANGE_SUCCESSFUL; + + UserUpdateFullscreen(flags); + + /* Update the system metrics */ + InitMetrics(); + + /* 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; + } + 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);