* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* PURPOSE: Support for physical devices
- * FILE: subsystems/win32/win32k/eng/pdevobj.c
+ * FILE: win32ss/gdi/eng/pdevobj.c
* PROGRAMER: Timo Kreuzer (timo.kreuzer@reactos.org)
*/
INIT_FUNCTION
NTSTATUS
NTAPI
-InitPDEVImpl()
+InitPDEVImpl(VOID)
{
ghsemPDEV = EngCreateSemaphore();
if (!ghsemPDEV) return STATUS_INSUFFICIENT_RESOURCES;
#endif
PPDEVOBJ
-PDEVOBJ_AllocPDEV()
+PDEVOBJ_AllocPDEV(VOID)
{
PPDEVOBJ ppdev;
RtlZeroMemory(ppdev, sizeof(PDEVOBJ));
+ ppdev->hsemDevLock = EngCreateSemaphore();
+ if (ppdev->hsemDevLock == NULL)
+ {
+ ExFreePoolWithTag(ppdev, GDITAG_PDEV);
+ return NULL;
+ }
+
+ /* Allocate EDD_DIRECTDRAW_GLOBAL for our ReactX driver */
+ ppdev->pEDDgpl = ExAllocatePoolWithTag(PagedPool, sizeof(EDD_DIRECTDRAW_GLOBAL), GDITAG_PDEV);
+ if (ppdev->pEDDgpl)
+ RtlZeroMemory(ppdev->pEDDgpl, sizeof(EDD_DIRECTDRAW_GLOBAL));
+
ppdev->cPdevRefs = 1;
return ppdev;
}
+static
+VOID
+PDEVOBJ_vDeletePDEV(
+ PPDEVOBJ ppdev)
+{
+ EngDeleteSemaphore(ppdev->hsemDevLock);
+ if (ppdev->pEDDgpl)
+ ExFreePoolWithTag(ppdev->pEDDgpl, GDITAG_PDEV);
+ ExFreePoolWithTag(ppdev, GDITAG_PDEV);
+}
+
VOID
NTAPI
PDEVOBJ_vRelease(PPDEVOBJ ppdev)
if (ppdev->cPdevRefs == 0)
{
/* Do we have a surface? */
- if(ppdev->pSurface)
+ if (ppdev->pSurface)
{
/* Release the surface and let the driver free it */
SURFACE_ShareUnlockSurface(ppdev->pSurface);
PALETTE_ShareUnlockPalette(ppdev->ppalSurf);
}
- /* Disable PDEV */
- ppdev->pfn.DisablePDEV(ppdev->dhpdev);
+ /* Check if the PDEV was enabled */
+ if (ppdev->dhpdev != NULL)
+ {
+ /* Disable the PDEV */
+ ppdev->pfn.DisablePDEV(ppdev->dhpdev);
+ }
/* Remove it from list */
if( ppdev == gppdevList )
gppdevPrimary = NULL;
/* Free it */
- ExFreePoolWithTag(ppdev, GDITAG_PDEV );
+ PDEVOBJ_vDeletePDEV(ppdev);
}
/* Unlock loader */
(HDEV)ppdev,
ppdev->pGraphicsDevice->pwszDescription,
ppdev->pGraphicsDevice->DeviceObject);
+ if (ppdev->dhpdev == NULL)
+ {
+ DPRINT1("Failed to enable PDEV\n");
+ return FALSE;
+ }
/* Fix up some values */
if (ppdev->gdiinfo.ulLogPixelsX == 0)
if (ppdev->gdiinfo.ulLogPixelsY == 0)
ppdev->gdiinfo.ulLogPixelsY = 96;
+ /* Set raster caps */
+ ppdev->gdiinfo.flRaster = RC_OP_DX_OUTPUT | RC_GDI20_OUTPUT | RC_BIGFONT;
+ if ((ppdev->gdiinfo.ulTechnology != DT_PLOTTER) && (ppdev->gdiinfo.ulTechnology != DT_CHARSTREAM))
+ ppdev->gdiinfo.flRaster |= RC_STRETCHDIB | RC_STRETCHBLT | RC_DIBTODEV | RC_DI_BITMAP | RC_BITMAP64 | RC_BITBLT;
+ if (ppdev->gdiinfo.ulTechnology == DT_RASDISPLAY)
+ ppdev->gdiinfo.flRaster |= RC_FLOODFILL;
+ if (ppdev->devinfo.flGraphicsCaps & GCAPS_PALMANAGED)
+ ppdev->gdiinfo.flRaster |= RC_PALETTE;
+
/* Setup Palette */
ppdev->ppalSurf = PALETTE_ShareLockPalette(ppdev->devinfo.hpalDefault);
{
HSURF hsurf;
- /* Check if we already have a surface */
- if (ppdev->pSurface)
- {
- /* Increment reference count */
- GDIOBJ_vReferenceObjectByPointer(&ppdev->pSurface->BaseObject);
- }
- else
+ /* Check if there is no surface for this PDEV yet */
+ if (ppdev->pSurface == NULL)
{
/* Call the drivers DrvEnableSurface */
hsurf = ppdev->pldev->pfn.EnableSurface(ppdev->dhpdev);
+ if (hsurf== NULL)
+ {
+ DPRINT1("Failed to create PDEV surface!\n");
+ return NULL;
+ }
- /* Lock the surface */
+ /* Get a reference to the surface */
ppdev->pSurface = SURFACE_ShareLockSurface(hsurf);
+ NT_ASSERT(ppdev->pSurface != NULL);
}
+ /* Increment reference count */
+ GDIOBJ_vReferenceObjectByPointer(&ppdev->pSurface->BaseObject);
+
DPRINT("PDEVOBJ_pSurface() returning %p\n", ppdev->pSurface);
return ppdev->pSurface;
}
+VOID
+NTAPI
+PDEVOBJ_vRefreshModeList(
+ PPDEVOBJ ppdev)
+{
+ PGRAPHICS_DEVICE pGraphicsDevice;
+ PDEVMODEINFO pdminfo, pdmiNext;
+ DEVMODEW dmDefault;
+ DEVMODEW dmCurrent;
+
+ /* Lock the PDEV */
+ EngAcquireSemaphore(ppdev->hsemDevLock);
+
+ pGraphicsDevice = ppdev->pGraphicsDevice;
+
+ /* Remember our default mode */
+ dmDefault = *pGraphicsDevice->pDevModeList[pGraphicsDevice->iDefaultMode].pdm;
+ dmCurrent = *ppdev->pdmwDev;
+
+ /* Clear out the modes */
+ for (pdminfo = pGraphicsDevice->pdevmodeInfo;
+ pdminfo;
+ pdminfo = pdmiNext)
+ {
+ pdmiNext = pdminfo->pdmiNext;
+ ExFreePoolWithTag(pdminfo, GDITAG_DEVMODE);
+ }
+ pGraphicsDevice->pdevmodeInfo = NULL;
+ ExFreePoolWithTag(pGraphicsDevice->pDevModeList, GDITAG_GDEVICE);
+ pGraphicsDevice->pDevModeList = NULL;
+
+ /* Now re-populate the list */
+ if (!EngpPopulateDeviceModeList(pGraphicsDevice, &dmDefault))
+ {
+ DPRINT1("FIXME: EngpPopulateDeviceModeList failed, we just destroyed a perfectly good mode list\n");
+ }
+
+ ppdev->pdmwDev = PDEVOBJ_pdmMatchDevMode(ppdev, &dmCurrent);
+
+ /* Unlock PDEV */
+ EngReleaseSemaphore(ppdev->hsemDevLock);
+}
+
PDEVMODEW
NTAPI
PDEVOBJ_pdmMatchDevMode(
DPRINT1("Could not load display driver '%ls', '%ls'\n",
pGraphicsDevice->pDiplayDrivers,
pdm->dmDeviceName);
- ExFreePoolWithTag(ppdev, GDITAG_PDEV);
+ PDEVOBJ_vRelease(ppdev);
return NULL;
}
ppdev->pfnMovePointer = EngMovePointer;
ppdev->pGraphicsDevice = pGraphicsDevice;
- ppdev->hsemDevLock = EngCreateSemaphore();
+
+ // DxEngGetHdevData asks for Graphics DeviceObject in hSpooler field
+ ppdev->hSpooler = ppdev->pGraphicsDevice->DeviceObject;
+
// Should we change the ative mode of pGraphicsDevice ?
ppdev->pdmwDev = PDEVOBJ_pdmMatchDevMode(ppdev, pdm) ;
if (!PDEVOBJ_bEnablePDEV(ppdev, pdm, NULL))
{
DPRINT1("Failed to enable PDEV!\n");
- ASSERT(FALSE);
+ PDEVOBJ_vRelease(ppdev);
+ return NULL;
}
/* FIXME: this must be done in a better way */
return ppdev;
}
+FORCEINLINE
+VOID
+SwitchPointer(
+ _Inout_ PVOID pvPointer1,
+ _Inout_ PVOID pvPointer2)
+{
+ PVOID *ppvPointer1 = pvPointer1;
+ PVOID *ppvPointer2 = pvPointer2;
+ PVOID pvTemp;
+
+ pvTemp = *ppvPointer1;
+ *ppvPointer1 = *ppvPointer2;
+ *ppvPointer2 = pvTemp;
+}
+
VOID
NTAPI
PDEVOBJ_vSwitchPdev(
PPDEVOBJ ppdev,
PPDEVOBJ ppdev2)
{
- PDEVOBJ pdevTmp;
- DWORD tmpStateFlags;
-
- /* Exchange data */
- pdevTmp = *ppdev;
+ union
+ {
+ DRIVER_FUNCTIONS pfn;
+ GDIINFO gdiinfo;
+ DEVINFO devinfo;
+ DWORD StateFlags;
+ } temp;
/* Exchange driver functions */
+ temp.pfn = ppdev->pfn;
ppdev->pfn = ppdev2->pfn;
- ppdev2->pfn = pdevTmp.pfn;
+ ppdev2->pfn = temp.pfn;
/* Exchange LDEVs */
- ppdev->pldev = ppdev2->pldev;
- ppdev2->pldev = pdevTmp.pldev;
+ SwitchPointer(&ppdev->pldev, &ppdev2->pldev);
/* Exchange DHPDEV */
- ppdev->dhpdev = ppdev2->dhpdev;
- ppdev2->dhpdev = pdevTmp.dhpdev;
+ SwitchPointer(&ppdev->dhpdev, &ppdev2->dhpdev);
/* Exchange surfaces and associate them with their new PDEV */
- ppdev->pSurface = ppdev2->pSurface;
- ppdev2->pSurface = pdevTmp.pSurface;
+ SwitchPointer(&ppdev->pSurface, &ppdev2->pSurface);
ppdev->pSurface->SurfObj.hdev = (HDEV)ppdev;
ppdev2->pSurface->SurfObj.hdev = (HDEV)ppdev2;
/* Exchange devinfo */
+ temp.devinfo = ppdev->devinfo;
ppdev->devinfo = ppdev2->devinfo;
- ppdev2->devinfo = pdevTmp.devinfo;
+ ppdev2->devinfo = temp.devinfo;
/* Exchange gdiinfo */
+ temp.gdiinfo = ppdev->gdiinfo;
ppdev->gdiinfo = ppdev2->gdiinfo;
- ppdev2->gdiinfo = pdevTmp.gdiinfo;
+ ppdev2->gdiinfo = temp.gdiinfo;
/* Exchange DEVMODE */
- ppdev->pdmwDev = ppdev2->pdmwDev;
- ppdev2->pdmwDev = pdevTmp.pdmwDev;
+ SwitchPointer(&ppdev->pdmwDev, &ppdev2->pdmwDev);
/* Exchange state flags */
- tmpStateFlags = ppdev->pGraphicsDevice->StateFlags;
+ temp.StateFlags = ppdev->pGraphicsDevice->StateFlags;
ppdev->pGraphicsDevice->StateFlags = ppdev2->pGraphicsDevice->StateFlags;
- ppdev2->pGraphicsDevice->StateFlags = tmpStateFlags;
+ ppdev2->pGraphicsDevice->StateFlags = temp.StateFlags;
/* Notify each driver instance of its new HDEV association */
ppdev->pfn.CompletePDEV(ppdev->dhpdev, (HDEV)ppdev);
/* Lock the PDEV */
EngAcquireSemaphore(ppdev->hsemDevLock);
+
/* And everything else */
EngAcquireSemaphore(ghsemPDEV);
// 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;
}
if (!ppdevTmp)
{
DPRINT1("Failed to create a new PDEV\n");
- goto leave;
+ goto leave2;
}
/* 3. Create a new surface */
pSurface = PDEVOBJ_pSurface(ppdevTmp);
if (!pSurface)
{
- DPRINT1("DrvEnableSurface failed\n");
- goto leave;
+ DPRINT1("PDEVOBJ_pSurface failed\n");
+ PDEVOBJ_vRelease(ppdevTmp);
+ goto leave2;
}
/* 4. Get DirectDraw information */
/* 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);
PPDEVOBJ
NTAPI
EngpGetPDEV(
- PUNICODE_STRING pustrDeviceName)
+ _In_opt_ PUNICODE_STRING pustrDeviceName)
{
UNICODE_STRING ustrCurrent;
PPDEVOBJ ppdev;
/* Acquire PDEV lock */
EngAcquireSemaphore(ghsemPDEV);
- /* If no device name is given, ... */
- if (!pustrDeviceName && gppdevPrimary)
+ /* Did the caller pass a device name? */
+ if (pustrDeviceName)
{
- /* ... use the primary PDEV */
- ppdev = gppdevPrimary;
+ /* Loop all present PDEVs */
+ for (ppdev = gppdevList; ppdev; ppdev = ppdev->ppdevNext)
+ {
+ /* Get a pointer to the GRAPHICS_DEVICE */
+ pGraphicsDevice = ppdev->pGraphicsDevice;
- /* Reference the pdev */
- InterlockedIncrement(&ppdev->cPdevRefs);
- goto leave;
+ /* Compare the name */
+ RtlInitUnicodeString(&ustrCurrent, pGraphicsDevice->szWinDeviceName);
+ if (RtlEqualUnicodeString(pustrDeviceName, &ustrCurrent, FALSE))
+ {
+ /* Found! */
+ break;
+ }
+ }
}
-
- /* Loop all present PDEVs */
- for (ppdev = gppdevList; ppdev; ppdev = ppdev->ppdevNext)
+ else
{
- /* Get a pointer to the GRAPHICS_DEVICE */
- pGraphicsDevice = ppdev->pGraphicsDevice;
-
- /* Compare the name */
- RtlInitUnicodeString(&ustrCurrent, pGraphicsDevice->szWinDeviceName);
- if (RtlEqualUnicodeString(pustrDeviceName, &ustrCurrent, FALSE))
- {
- /* Found! Reference the PDEV */
- InterlockedIncrement(&ppdev->cPdevRefs);
- break;
- }
+ /* Otherwise use the primary PDEV */
+ ppdev = gppdevPrimary;
}
/* Did we find one? */
- if (!ppdev)
+ if (ppdev)
{
- /* No, create a new PDEV */
+ /* Yes, reference the PDEV */
+ InterlockedIncrement(&ppdev->cPdevRefs);
+ }
+ else
+ {
+ /* No, create a new PDEV for the given device */
ppdev = EngpCreatePDEV(pustrDeviceName, NULL);
if (ppdev)
{
}
}
-leave:
/* Release PDEV lock */
EngReleaseSemaphore(ghsemPDEV);
/** Exported functions ********************************************************/
+_Must_inspect_result_ _Ret_z_
LPWSTR
APIENTRY
-EngGetDriverName(IN HDEV hdev)
+EngGetDriverName(_In_ HDEV hdev)
{
PPDEVOBJ ppdev = (PPDEVOBJ)hdev;
return 0;
}
-
+_Success_(return!=FALSE)
BOOL
APIENTRY
NtGdiGetDeviceCapsAll(