[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.
This commit is contained in:
Hermès Bélusca-Maïto 2019-01-02 20:55:40 +01:00
parent fb4a6e38c7
commit 333ce14dad
No known key found for this signature in database
GPG key ID: 3B2539C65E7B93D0
2 changed files with 57 additions and 32 deletions

View file

@ -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);

View file

@ -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);