[WIN32K] Improve finding the best matching display mode

Search the display mode having the smallest difference with the requested one.
We can then remove the hardcoded values of 60 Hz and 32 bpp by default.

CORE-18189
This commit is contained in:
Hervé Poussineau 2022-05-22 22:47:20 +02:00
parent 63e59e10f3
commit d2a87f1b7f

View file

@ -669,6 +669,8 @@ LDEVOBJ_bBuildDevmodeList(
return TRUE;
}
/* Search the closest display mode according to some settings.
* Note that we don't care about the DM_* flags in dmFields, but check if value != 0 instead */
static
BOOL
LDEVOBJ_bGetClosestMode(
@ -676,31 +678,57 @@ LDEVOBJ_bGetClosestMode(
_In_ PDEVMODEW RequestedMode,
_Out_ PDEVMODEW *pSelectedMode)
{
if (pGraphicsDevice->cDevModes == 0)
return FALSE;
DEVMODEW dmDiff;
PDEVMODEW pdmCurrent, pdmBest = NULL;
ULONG i;
/* Search a 32bit mode (if not already specified) */
if (!(RequestedMode->dmFields & DM_BITSPERPEL))
/* Use a DEVMODE to keep the differences between best mode found and expected mode.
* Initialize fields to max value so we can find better modes. */
dmDiff.dmPelsWidth = 0xffffffff;
dmDiff.dmPelsHeight = 0xffffffff;
dmDiff.dmBitsPerPel = 0xffffffff;
dmDiff.dmDisplayFrequency = 0xffffffff;
/* Search the closest mode */
#define DM_DIFF(field) (RequestedMode->field > pdmCurrent->field ? (RequestedMode->field - pdmCurrent->field) : (pdmCurrent->field - RequestedMode->field))
for (i = 0; i < pGraphicsDevice->cDevModes; i++)
{
RequestedMode->dmBitsPerPel = 32;
RequestedMode->dmFields |= DM_BITSPERPEL;
pdmCurrent = pGraphicsDevice->pDevModeList[i].pdm;
/* Skip current mode if it is worse than best mode found */
if (RequestedMode->dmPelsWidth != 0 && DM_DIFF(dmPelsWidth) > dmDiff.dmPelsWidth)
continue;
if (RequestedMode->dmPelsHeight != 0 && DM_DIFF(dmPelsHeight) > dmDiff.dmPelsHeight)
continue;
if (RequestedMode->dmBitsPerPel != 0 && DM_DIFF(dmBitsPerPel) > dmDiff.dmBitsPerPel)
continue;
if (RequestedMode->dmDisplayFrequency != 0 && DM_DIFF(dmDisplayFrequency) > dmDiff.dmDisplayFrequency)
continue;
/* Better (or equivalent) mode found. Update differences */
dmDiff.dmPelsWidth = DM_DIFF(dmPelsWidth);
dmDiff.dmPelsHeight = DM_DIFF(dmPelsHeight);
dmDiff.dmBitsPerPel = DM_DIFF(dmBitsPerPel);
dmDiff.dmDisplayFrequency = DM_DIFF(dmDisplayFrequency);
pdmBest = pdmCurrent;
}
if (LDEVOBJ_bProbeAndCaptureDevmode(pGraphicsDevice, RequestedMode, pSelectedMode, FALSE))
return TRUE;
#undef DM_DIFF
/* Search 60 Hz (if not already specified) */
if (!(RequestedMode->dmFields & DM_DISPLAYFREQUENCY))
if (pdmBest)
{
RequestedMode->dmDisplayFrequency = 60;
RequestedMode->dmFields |= DM_DISPLAYFREQUENCY;
if (LDEVOBJ_bProbeAndCaptureDevmode(pGraphicsDevice, RequestedMode, pSelectedMode, FALSE))
return TRUE;
TRACE("Closest display mode to '%dx%dx%d %d Hz' is '%dx%dx%d %d Hz'\n",
RequestedMode->dmPelsWidth,
RequestedMode->dmPelsHeight,
RequestedMode->dmBitsPerPel,
RequestedMode->dmDisplayFrequency,
pdmBest->dmPelsWidth,
pdmBest->dmPelsHeight,
pdmBest->dmBitsPerPel,
pdmBest->dmDisplayFrequency);
}
/* Fall back to first mode */
WARN("Fall back to first available mode\n");
*pSelectedMode = pGraphicsDevice->pDevModeList[0].pdm;
return TRUE;
*pSelectedMode = pdmBest;
return pdmBest != NULL;
}
BOOL