https://git.reactos.org/?p=reactos.git;a=commitdiff;h=2d2824f1b98b772eb36e4…
commit 2d2824f1b98b772eb36e4e2b75185b48cbeed618
Author: Hervé Poussineau <hpoussin(a)reactos.org>
AuthorDate: Sun Mar 20 17:38:16 2022 +0100
Commit: hpoussin <32227662+hpoussin(a)users.noreply.github.com>
CommitDate: Fri Apr 15 23:09:16 2022 +0200
[WIN32SS] Implement PDEVOBJ_lChangeDisplaySettings to create initial MDEV
This function can create a MDEV for the whole display (maybe containing multiple
PDEVs), or update settings of a specific PDEV.
- call PDEVOBJ_lChangeDisplaySettings when switching to graphics mode.
- modify EngpGetPDEV to search requested PDEV only in current MDEV
---
win32ss/gdi/eng/pdevobj.c | 181 ++++++++++++++++++++++++++++++++++++++-----
win32ss/gdi/eng/pdevobj.h | 16 ++++
win32ss/user/ntuser/winsta.c | 5 +-
3 files changed, 180 insertions(+), 22 deletions(-)
diff --git a/win32ss/gdi/eng/pdevobj.c b/win32ss/gdi/eng/pdevobj.c
index a24a8c05dee..1642b94763e 100644
--- a/win32ss/gdi/eng/pdevobj.c
+++ b/win32ss/gdi/eng/pdevobj.c
@@ -643,8 +643,9 @@ EngpGetPDEV(
_In_opt_ PUNICODE_STRING pustrDeviceName)
{
UNICODE_STRING ustrCurrent;
- PPDEVOBJ ppdev;
+ PPDEVOBJ ppdev = NULL;
PGRAPHICS_DEVICE pGraphicsDevice;
+ ULONG i;
/* Acquire PDEV lock */
EngAcquireSemaphore(ghsemPDEV);
@@ -653,16 +654,17 @@ EngpGetPDEV(
if (pustrDeviceName)
{
/* Loop all present PDEVs */
- for (ppdev = gppdevList; ppdev; ppdev = ppdev->ppdevNext)
+ for (i = 0; i < gpmdev->cDev; i++)
{
/* Get a pointer to the GRAPHICS_DEVICE */
- pGraphicsDevice = ppdev->pGraphicsDevice;
+ pGraphicsDevice = gpmdev->dev[i].ppdev->pGraphicsDevice;
/* Compare the name */
RtlInitUnicodeString(&ustrCurrent, pGraphicsDevice->szWinDeviceName);
if (RtlEqualUnicodeString(pustrDeviceName, &ustrCurrent, FALSE))
{
/* Found! */
+ ppdev = gpmdev->dev[i].ppdev;
break;
}
}
@@ -679,32 +681,173 @@ EngpGetPDEV(
/* Yes, reference the PDEV */
PDEVOBJ_vReference(ppdev);
}
- else
+
+ /* Release PDEV lock */
+ EngReleaseSemaphore(ghsemPDEV);
+
+ return ppdev;
+}
+
+LONG
+PDEVOBJ_lChangeDisplaySettings(
+ _In_opt_ PUNICODE_STRING pustrDeviceName,
+ _In_opt_ PDEVMODEW RequestedMode,
+ _In_opt_ PMDEVOBJ pmdevOld,
+ _Out_ PMDEVOBJ *ppmdevNew,
+ _In_ BOOL bSearchClosestMode)
+{
+ PGRAPHICS_DEVICE pGraphicsDevice;
+ PMDEVOBJ pmdev = NULL;
+ PDEVMODEW pdm = NULL;
+ ULONG lRet = DISP_CHANGE_SUCCESSFUL;
+ ULONG i, j;
+
+ TRACE("PDEVOBJ_lChangeDisplaySettings('%wZ' '%dx%dx%d (%d Hz)'
%p %p)\n",
+ pustrDeviceName,
+ RequestedMode ? RequestedMode->dmPelsWidth : 0,
+ RequestedMode ? RequestedMode->dmPelsHeight : 0,
+ RequestedMode ? RequestedMode->dmBitsPerPel : 0,
+ RequestedMode ? RequestedMode->dmDisplayFrequency : 0,
+ pmdevOld, ppmdevNew);
+
+ if (pustrDeviceName)
{
- if (pustrDeviceName)
- pGraphicsDevice = EngpFindGraphicsDevice(pustrDeviceName, 0);
+ pGraphicsDevice = EngpFindGraphicsDevice(pustrDeviceName, 0);
if (!pGraphicsDevice)
- pGraphicsDevice = gpPrimaryGraphicsDevice;
+ {
+ ERR("Wrong device name provided: '%wZ'\n",
pustrDeviceName);
+ lRet = DISP_CHANGE_BADPARAM;
+ goto cleanup;
+ }
+ }
+ else if (RequestedMode)
+ {
+ pGraphicsDevice = gpPrimaryGraphicsDevice;
+ if (!pGraphicsDevice)
+ {
+ ERR("Wrong device'\n");
+ lRet = DISP_CHANGE_BADPARAM;
+ goto cleanup;
+ }
+ }
+
+ if (pGraphicsDevice)
+ {
+ if (!LDEVOBJ_bProbeAndCaptureDevmode(pGraphicsDevice, RequestedMode, &pdm,
bSearchClosestMode))
+ {
+ ERR("DrvProbeAndCaptureDevmode() failed\n");
+ lRet = DISP_CHANGE_BADMODE;
+ goto cleanup;
+ }
+ }
+
+ /* Here, we know that input parameters were correct */
+
+ {
+ /* Create new MDEV. Note that if we provide a device name,
+ * MDEV will only contain one device.
+ * */
+
+ if (pmdevOld)
+ {
+ /* Disable old MDEV */
+ if (MDEVOBJ_bDisable(pmdevOld))
+ {
+ /* Create new MDEV. On failure, reenable old MDEV */
+ pmdev = MDEVOBJ_Create(pustrDeviceName, pdm);
+ if (!pmdev)
+ MDEVOBJ_vEnable(pmdevOld);
+ }
+ }
+ else
+ {
+ pmdev = MDEVOBJ_Create(pustrDeviceName, pdm);
+ }
- /* No, create a new PDEV for the given device */
- ppdev = PDEVOBJ_Create(pGraphicsDevice,
-
pGraphicsDevice->pDevModeList[pGraphicsDevice->iDefaultMode].pdm,
- LDEV_DEVICE_DISPLAY);
- if (ppdev)
+ if (!pmdev)
{
- /* Set as primary PDEV, if we don't have one yet */
- if (!gpmdev->ppdevGlobal)
+ ERR("Failed to create new MDEV\n");
+ lRet = DISP_CHANGE_FAILED;
+ goto cleanup;
+ }
+
+ lRet = DISP_CHANGE_SUCCESSFUL;
+ *ppmdevNew = pmdev;
+
+ /* We now have to do the mode switch */
+
+ if (pustrDeviceName && pmdevOld)
+ {
+ /* We changed settings of one device. Add other devices which were already
present */
+ for (i = 0; i < pmdevOld->cDev; i++)
{
- gpmdev->ppdevGlobal = ppdev;
- ppdev->pGraphicsDevice->StateFlags |=
DISPLAY_DEVICE_PRIMARY_DEVICE;
+ for (j = 0; j < pmdev->cDev; j++)
+ {
+ if (pmdev->dev[j].ppdev->pGraphicsDevice ==
pmdevOld->dev[i].ppdev->pGraphicsDevice)
+ {
+ if (PDEVOBJ_bDynamicModeChange(pmdevOld->dev[i].ppdev,
pmdev->dev[j].ppdev))
+ {
+ PPDEVOBJ tmp = pmdevOld->dev[i].ppdev;
+ pmdevOld->dev[i].ppdev = pmdev->dev[j].ppdev;
+ pmdev->dev[j].ppdev = tmp;
+ }
+ else
+ {
+ ERR("Failed to apply new settings\n");
+ UNIMPLEMENTED;
+ ASSERT(FALSE);
+ }
+ break;
+ }
+ }
+ if (j == pmdev->cDev)
+ {
+ PDEVOBJ_vReference(pmdevOld->dev[i].ppdev);
+ pmdev->dev[pmdev->cDev].ppdev = pmdevOld->dev[i].ppdev;
+ pmdev->cDev++;
+ }
+ }
+ }
+
+ if (pmdev->cDev == 1)
+ {
+ pmdev->ppdevGlobal = pmdev->dev[0].ppdev;
+ }
+ else
+ {
+ /* FIXME: currently, only use the first display */
+ UNIMPLEMENTED;
+ PDEVOBJ_vReference(pmdev->dev[0].ppdev);
+ pmdev->ppdevGlobal = pmdev->dev[0].ppdev;
+ }
+
+ if (pmdevOld)
+ {
+ /* Search PDEVs which were in pmdevOld, but are not anymore in pmdev, and
disable them */
+ for (i = 0; i < pmdevOld->cDev; i++)
+ {
+ for (j = 0; j < pmdev->cDev; j++)
+ {
+ if (pmdev->dev[j].ppdev->pGraphicsDevice ==
pmdevOld->dev[i].ppdev->pGraphicsDevice)
+ break;
+ }
+ if (j == pmdev->cDev)
+ PDEVOBJ_bDisableDisplay(pmdevOld->dev[i].ppdev);
}
}
}
- /* Release PDEV lock */
- EngReleaseSemaphore(ghsemPDEV);
+cleanup:
+ if (lRet != DISP_CHANGE_SUCCESSFUL)
+ {
+ *ppmdevNew = NULL;
+ if (pmdev)
+ MDEVOBJ_vDestroy(pmdev);
+ if (pdm && pdm != RequestedMode)
+ ExFreePoolWithTag(pdm, GDITAG_DEVMODE);
+ }
- return ppdev;
+ return lRet;
}
INT
diff --git a/win32ss/gdi/eng/pdevobj.h b/win32ss/gdi/eng/pdevobj.h
index 5590ac9548f..c5b63b56e7d 100644
--- a/win32ss/gdi/eng/pdevobj.h
+++ b/win32ss/gdi/eng/pdevobj.h
@@ -228,4 +228,20 @@ PDEVOBJ_Create(
_In_opt_ PDEVMODEW pdm,
_In_ ULONG ldevtype);
+/* Change display settings:
+ * - pustrDeviceName: name of the device to change settings. Can be NULL to specify whole
display surface
+ * - RequestedMode: new parameters for device. Ignored if pstrDeviceName is NULL
+ * - pmdevOld: old MDEVOBJ. Can be NULL if we are creating the first one
+ * - ppdevNew: MDEVOBJ created by this function, with the new settings
+ * - bSearchClosestMode: do we need to search exact requested mode, or a mostly similar
one
+ * Return value: a DISP_CHANGE_* value
+ */
+LONG
+PDEVOBJ_lChangeDisplaySettings(
+ _In_opt_ PUNICODE_STRING pustrDeviceName,
+ _In_opt_ PDEVMODEW RequestedMode,
+ _In_opt_ PMDEVOBJ pmdevOld,
+ _Out_ PMDEVOBJ *ppmdevNew,
+ _In_ BOOL bSearchClosestMode);
+
#endif /* !__WIN32K_PDEVOBJ_H */
diff --git a/win32ss/user/ntuser/winsta.c b/win32ss/user/ntuser/winsta.c
index ba1db88a6bd..88266ad5bb0 100644
--- a/win32ss/user/ntuser/winsta.c
+++ b/win32ss/user/ntuser/winsta.c
@@ -263,10 +263,9 @@ co_IntInitializeDesktopGraphics(VOID)
UNICODE_STRING DriverName = RTL_CONSTANT_STRING(L"DISPLAY");
PDESKTOP pdesk;
- gpmdev = ExAllocatePoolZero(PagedPool, sizeof(MDEVOBJ), GDITAG_MDEV);
- if (!gpmdev)
+ if (PDEVOBJ_lChangeDisplaySettings(NULL, NULL, NULL, &gpmdev, TRUE) !=
DISP_CHANGE_SUCCESSFUL)
{
- ERR("Failed to allocate MDEV.\n");
+ ERR("PDEVOBJ_lChangeDisplaySettings() failed.\n");
return FALSE;
}