reactos/win32ss/reactx/dxg/ddraw.c

677 lines
22 KiB
C
Raw Normal View History

/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* PURPOSE: Native driver for dxg implementation
* FILE: win32ss/reactx/dxg/eng.c
* PROGRAMER: Magnus olsen (magnus@greatlord.com)
* Sebastian Gasiorek (sebastian.gasiorek@reactos.org)
* REVISION HISTORY:
* 30/12-2007 Magnus Olsen
*/
#include <dxg_int.h>
/*++
* @name intDdGetDriverInfo
* @implemented
*
* The function intDdGetDriverInfo is used internally in dxg.sys
* It retrieves driver information structures
*
* @param PEDD_DIRECTDRAW_GLOBAL peDdGl
* DirectDraw global structure
*
* @param GUID guid
* GUID of InfoData to read
*
* @param PVOID callbackStruct
* Callback structure pointer
*
* @param ULONG callbackSize
* Size of allocated callback structure
*
* @param ULONG *returnSize
* Desired structure size returned by driver
*
* @return
* Returns true on successful execution, false when error.
*
* @remarks.
* Only used internally in dxg.sys
*--*/
BOOL intDdGetDriverInfo(PEDD_DIRECTDRAW_GLOBAL peDdGl, GUID guid, PVOID callbackStruct, ULONG callbackSize, ULONG *returnSize)
{
DD_GETDRIVERINFODATA ddGetDriverInfoData;
if (peDdGl->ddHalInfo.dwFlags & DDHALINFO_GETDRIVERINFOSET && peDdGl->ddHalInfo.GetDriverInfo)
{
memset(&ddGetDriverInfoData, 0, sizeof(DD_GETDRIVERINFODATA));
ddGetDriverInfoData.dwSize = sizeof(DD_GETDRIVERINFODATA);
ddGetDriverInfoData.dhpdev = peDdGl->dhpdev;
memcpy(&ddGetDriverInfoData.guidInfo, &guid, sizeof(GUID));
ddGetDriverInfoData.dwExpectedSize = callbackSize;
ddGetDriverInfoData.lpvData = callbackStruct;
ddGetDriverInfoData.ddRVal = DDERR_CURRENTLYNOTAVAIL;
if (peDdGl->ddHalInfo.GetDriverInfo(&ddGetDriverInfoData) && !ddGetDriverInfoData.ddRVal)
{
if (returnSize)
*returnSize = ddGetDriverInfoData.dwActualSize;
return TRUE;
}
}
/* cleanup on error */
memset(callbackStruct, 0, callbackSize);
if (returnSize)
*returnSize = 0;
return FALSE;
}
/*++
* @name intDdGetAllDriverInfo
* @implemented
*
* The function intDdGetAllDriverInfo is used internally in dxg.sys
* It retrieves all possible driver information structures
*
* @param PEDD_DIRECTDRAW_GLOBAL peDdGl
* Pointer to destination DirectDrawGlobal structure
*
* @remarks.
* Only used internally in dxg.sys
* Missing some callbacks (VideoPort, DxApi, AGP)
*--*/
VOID intDdGetAllDriverInfo(PEDD_DIRECTDRAW_GLOBAL peDdGl)
{
if (peDdGl->ddHalInfo.GetDriverInfo && peDdGl->ddHalInfo.dwFlags & DDHALINFO_GETDRIVERINFOSET)
{
intDdGetDriverInfo(peDdGl, GUID_KernelCaps, &peDdGl->ddKernelCaps, sizeof(peDdGl->ddKernelCaps), 0);
intDdGetDriverInfo(peDdGl, GUID_KernelCallbacks, &peDdGl->ddKernelCallbacks, sizeof(peDdGl->ddKernelCallbacks), 0);
if (intDdGetDriverInfo(peDdGl, GUID_D3DCallbacks3, &peDdGl->d3dNtHalCallbacks3, sizeof(peDdGl->d3dNtHalCallbacks3), 0))
peDdGl->dwCallbackFlags |= EDDDGBL_D3DCALLBACKS3;
if (intDdGetDriverInfo(peDdGl, GUID_ColorControlCallbacks, &peDdGl->ddColorControlCallbacks, sizeof(peDdGl->ddColorControlCallbacks), 0))
peDdGl->dwCallbackFlags |= EDDDGBL_COLORCONTROLCALLBACKS;
if (intDdGetDriverInfo(peDdGl, GUID_MiscellaneousCallbacks, &peDdGl->ddMiscellanousCallbacks, sizeof(peDdGl->ddMiscellanousCallbacks), 0))
peDdGl->dwCallbackFlags |= EDDDGBL_MISCCALLBACKS;
if (intDdGetDriverInfo(peDdGl, GUID_Miscellaneous2Callbacks, &peDdGl->ddMiscellanous2Callbacks, sizeof(peDdGl->ddMiscellanous2Callbacks), 0))
peDdGl->dwCallbackFlags |= EDDDGBL_MISC2CALLBACKS;
if (intDdGetDriverInfo(peDdGl, GUID_NTCallbacks, &peDdGl->ddNtCallbacks, sizeof(peDdGl->ddNtCallbacks), 0) )
peDdGl->dwCallbackFlags |= EDDDGBL_NTCALLBACKS;
if (intDdGetDriverInfo(peDdGl, GUID_DDMoreCaps, &peDdGl->ddMoreCaps, sizeof(peDdGl->ddMoreCaps), 0) )
peDdGl->dwCallbackFlags |= EDDDGBL_DDMORECAPS;
if (intDdGetDriverInfo(peDdGl, GUID_NTPrivateDriverCaps, &peDdGl->ddNtPrivateDriverCaps, sizeof(peDdGl->ddNtPrivateDriverCaps), 0) )
peDdGl->dwCallbackFlags |= EDDDGBL_PRIVATEDRIVERCAPS;
if (intDdGetDriverInfo(peDdGl, GUID_MotionCompCallbacks, &peDdGl->ddMotionCompCallbacks, sizeof(peDdGl->ddMotionCompCallbacks), 0) )
peDdGl->dwCallbackFlags |= EDDDGBL_MOTIONCOMPCALLBACKS;
}
}
/*++
* @name intDdEnableDriver
* @implemented
*
* The function intDdEnableDriver is used internally in dxg.sys
* Fills in all EDD_DIRECTDRAW_GLOBAL structures and enables DirectDraw acceleration when possible
*
* @param PEDD_DIRECTDRAW_GLOBAL peDdGl
* Pointer to destination DirectDrawGlobal structure
*
* @remarks.
* Only used internally in dxg.sys
*--*/
VOID intDdEnableDriver(PEDD_DIRECTDRAW_GLOBAL peDdGl)
{
PDRIVER_FUNCTIONS DriverFunctions;
LPD3DNTHAL_GLOBALDRIVERDATA GlobalDriverData;
LPD3DNTHAL_CALLBACKS HalCallbacks;
PDD_D3DBUFCALLBACKS D3DBufCallbacks;
gpEngFuncs.DxEngLockHdev(peDdGl->hDev);
DriverFunctions = (PDRIVER_FUNCTIONS)gpEngFuncs.DxEngGetHdevData(peDdGl->hDev, DxEGShDevData_DrvFuncs);
// check if driver has DirectDraw functions
if ((!DriverFunctions->GetDirectDrawInfo)||(!DriverFunctions->EnableDirectDraw)||(!DriverFunctions->DisableDirectDraw))
peDdGl->dhpdev = 0;
// reset acceleration flag
peDdGl->fl = peDdGl->fl & 0xFFFFFFFE;
// ask for structure sizes
if ((peDdGl->dhpdev)&&(DriverFunctions->GetDirectDrawInfo(peDdGl->dhpdev, &peDdGl->ddHalInfo, &peDdGl->dwNumHeaps, NULL, &peDdGl->dwNumFourCC, NULL)))
{
// allocate memory for DX data
if (peDdGl->dwNumHeaps)
peDdGl->pvmList = EngAllocMem(FL_ZERO_MEMORY, peDdGl->dwNumHeaps*sizeof(VIDEOMEMORY), TAG_GDDV);
if (peDdGl->dwNumFourCC)
peDdGl->pdwFourCC = EngAllocMem(FL_ZERO_MEMORY, peDdGl->dwNumFourCC * 4, TAG_GDDF);
// get data from driver
if (!DriverFunctions->GetDirectDrawInfo(peDdGl->dhpdev, &peDdGl->ddHalInfo, &peDdGl->dwNumHeaps, peDdGl->pvmList, &peDdGl->dwNumFourCC, peDdGl->pdwFourCC))
{
// failed - cleanup and exit
if (peDdGl->pvmList)
EngFreeMem(peDdGl->pvmList);
if (peDdGl->pdwFourCC)
EngFreeMem(peDdGl->pdwFourCC);
gpEngFuncs.DxEngUnlockHdev(peDdGl->hDev);
return;
}
// check if we can enable DirectDraw acceleration
if ((peDdGl->ddHalInfo.vmiData.pvPrimary) &&
(DriverFunctions->EnableDirectDraw(peDdGl->dhpdev, &peDdGl->ddCallbacks, &peDdGl->ddSurfaceCallbacks, &peDdGl->ddPaletteCallbacks))&&
!(gpEngFuncs.DxEngGetHdevData(peDdGl->hDev, DxEGShDevData_dd_flags) & CapOver_DisableD3DAccel)&&
(peDdGl->ddHalInfo.dwSize == sizeof(DD_HALINFO)))
{
GlobalDriverData = peDdGl->ddHalInfo.lpD3DGlobalDriverData;
HalCallbacks = peDdGl->ddHalInfo.lpD3DHALCallbacks;
D3DBufCallbacks = peDdGl->ddHalInfo.lpD3DHALCallbacks;
if (GlobalDriverData && GlobalDriverData->dwSize == sizeof(D3DNTHAL_GLOBALDRIVERDATA))
memcpy(&peDdGl->d3dNtGlobalDriverData, GlobalDriverData, sizeof(D3DNTHAL_GLOBALDRIVERDATA));
if (HalCallbacks && HalCallbacks->dwSize == sizeof(D3DNTHAL_CALLBACKS))
memcpy(&peDdGl->d3dNtHalCallbacks, HalCallbacks, sizeof(D3DNTHAL_CALLBACKS));
if (D3DBufCallbacks && D3DBufCallbacks->dwSize == sizeof(DD_D3DBUFCALLBACKS))
memcpy(&peDdGl->d3dBufCallbacks, D3DBufCallbacks, sizeof(DD_D3DBUFCALLBACKS));
intDdGetAllDriverInfo(peDdGl);
// enable DirectDraw acceleration
peDdGl->fl |= 1;
}
else
{
// failed - cleanup and exit
if (peDdGl->pvmList)
EngFreeMem(peDdGl->pvmList);
if (peDdGl->pdwFourCC)
EngFreeMem(peDdGl->pdwFourCC);
}
}
gpEngFuncs.DxEngUnlockHdev(peDdGl->hDev);
}
PVOID
FASTCALL
intDdCreateDirectDrawLocal(HDEV hDev)
{
PEDD_DIRECTDRAW_GLOBAL peDdGl = NULL;
PEDD_DIRECTDRAW_LOCAL peDdL = NULL;
PDD_ENTRY AllocRet;
peDdGl = (PEDD_DIRECTDRAW_GLOBAL)gpEngFuncs.DxEngGetHdevData(hDev, DxEGShDevData_eddg);
AllocRet = DdHmgAlloc(sizeof(EDD_DIRECTDRAW_LOCAL), ObjType_DDLOCAL_TYPE, TRUE);
if (!AllocRet)
return NULL;
peDdL = (PEDD_DIRECTDRAW_LOCAL)AllocRet->pobj;
/* initialize DIRECTDRAW_LOCAL */
peDdL->peDirectDrawLocal_prev = peDdGl->peDirectDrawLocalList;
peDdL->hCreatorProcess = PsGetCurrentThreadProcessId();
peDdL->Process = PsGetCurrentProcess();
// link DirectDrawGlobal and DirectDrawLocal
peDdGl->peDirectDrawLocalList = peDdL;
peDdL->peDirectDrawGlobal = peDdGl;
peDdL->peDirectDrawGlobal2 = peDdGl;
gpEngFuncs.DxEngReferenceHdev(hDev);
InterlockedDecrement((VOID*)&peDdL->pobj.cExclusiveLock);
return peDdL->pobj.hHmgr;
}
/*++
* @name DxDdCreateDirectDrawObject
* @implemented
*
* Function creates new DirectDraw object
*
* @param HDC hDC
* Device context handle
*
* @return
* Newly created DirectDraw object handle.
*
* @remarks.
* Missing all AGP stuff
*--*/
DWORD
NTAPI
DxDdCreateDirectDrawObject(
HDC hDC)
{
PDC pDC = NULL;
HDEV hDev = NULL;
2018-03-04 20:58:15 +00:00
DWORD_PTR retVal = 0;
pDC = gpEngFuncs.DxEngLockDC(hDC);
if (!pDC)
return 0;
// get driver hDev from DC
hDev = (HDEV)gpEngFuncs.DxEngGetDCState(hDC, 3);
if (!hDev) {
gpEngFuncs.DxEngUnlockDC(pDC);
return 0;
}
// is this primary display?
if (!gpEngFuncs.DxEngGetHdevData(hDev, DxEGShDevData_display))
{
gpEngFuncs.DxEngUnlockDC(pDC);
return 0;
}
gpEngFuncs.DxEngLockHdev(hDev);
// create object only for 8BPP and more
if (gpEngFuncs.DxEngGetHdevData(hDev, DxEGShDevData_DitherFmt) >= BMF_8BPP)
2018-03-04 20:58:15 +00:00
retVal = (DWORD_PTR)intDdCreateDirectDrawLocal(hDev);
gpEngFuncs.DxEngUnlockHdev(hDev);
gpEngFuncs.DxEngUnlockDC(pDC);
return retVal;
}
/*++
* @name DxDdGetDriverInfo
* @implemented
*
* Function queries the driver for DirectDraw and Direct3D functionality
*
* @param HANDLE DdHandle
* Handle to DirectDraw object
*
* @param PDD_GETDRIVERINFODATA drvInfoData
* Pointer to in/out driver info data structure
*--*/
DWORD
NTAPI
DxDdGetDriverInfo(HANDLE DdHandle, PDD_GETDRIVERINFODATA drvInfoData)
{
PEDD_DIRECTDRAW_LOCAL peDdL;
PEDD_DIRECTDRAW_GLOBAL peDdGl;
PVOID pInfo = NULL;
DWORD dwInfoSize = 0;
BYTE callbackStruct[1024];
DWORD RetVal = FALSE;
peDdL = (PEDD_DIRECTDRAW_LOCAL)DdHmgLock(DdHandle, ObjType_DDLOCAL_TYPE, FALSE);
if (!peDdL)
return RetVal;
peDdGl = peDdL->peDirectDrawGlobal2;
// check VideoPort related callbacks
if (peDdGl->dwCallbackFlags & EDDDGBL_VIDEOPORTCALLBACKS)
{
if (InlineIsEqualGUID(&drvInfoData->guidInfo, &GUID_VideoPortCallbacks))
{
dwInfoSize = sizeof(DD_VIDEOPORTCALLBACKS);
pInfo = (VOID*)&peDdGl->ddVideoPortCallback;
}
if (InlineIsEqualGUID(&drvInfoData->guidInfo, &GUID_VideoPortCaps))
{
pInfo = (VOID*)peDdGl->lpDDVideoPortCaps;
dwInfoSize = 72 * peDdGl->ddHalInfo.ddCaps.dwMaxVideoPorts;
}
if (InlineIsEqualGUID(&drvInfoData->guidInfo, &GUID_D3DCallbacks3))
{
dwInfoSize = sizeof(D3DNTHAL_CALLBACKS3);
pInfo = (VOID*)&peDdGl->d3dNtHalCallbacks3;
}
}
// check ColorControl related callbacks
if (peDdGl->dwCallbackFlags & EDDDGBL_COLORCONTROLCALLBACKS)
{
if (InlineIsEqualGUID(&drvInfoData->guidInfo, &GUID_ColorControlCallbacks))
{
dwInfoSize = sizeof(DD_COLORCONTROLCALLBACKS);
pInfo = (VOID*)&peDdGl->ddColorControlCallbacks;
}
if (InlineIsEqualGUID(&drvInfoData->guidInfo, &GUID_NTCallbacks))
{
dwInfoSize = sizeof(DD_NTCALLBACKS);
pInfo = (VOID*)&peDdGl->ddNtCallbacks;
}
}
// check Miscellaneous callbacks
if (peDdGl->dwCallbackFlags & EDDDGBL_MISCCALLBACKS)
{
if (InlineIsEqualGUID(&drvInfoData->guidInfo, &GUID_MiscellaneousCallbacks))
{
dwInfoSize = sizeof(DD_MISCELLANEOUSCALLBACKS);
pInfo = (VOID*)&peDdGl->ddMiscellanousCallbacks;
}
if (InlineIsEqualGUID(&drvInfoData->guidInfo, &GUID_DDMoreCaps))
{
dwInfoSize = sizeof(DD_MORECAPS);
pInfo = &peDdGl->ddMoreCaps;
}
}
if (peDdGl->dwCallbackFlags & EDDDGBL_MISC2CALLBACKS &&
InlineIsEqualGUID(&drvInfoData->guidInfo, &GUID_Miscellaneous2Callbacks))
{
dwInfoSize = sizeof(DD_MISCELLANEOUS2CALLBACKS);
pInfo = (VOID*)&peDdGl->ddMiscellanous2Callbacks;
}
if (peDdGl->dwCallbackFlags & EDDDGBL_MOTIONCOMPCALLBACKS &&
InlineIsEqualGUID(&drvInfoData->guidInfo, &GUID_MotionCompCallbacks))
{
dwInfoSize = sizeof(DD_MOTIONCOMPCALLBACKS);
pInfo = (VOID*)&peDdGl->ddMotionCompCallbacks;
}
if (InlineIsEqualGUID(&drvInfoData->guidInfo, &GUID_KernelCaps) )
{
dwInfoSize = sizeof(DD_KERNELCALLBACKS);
pInfo = &peDdGl->ddKernelCaps;
}
if (InlineIsEqualGUID(&drvInfoData->guidInfo, &GUID_DDMoreSurfaceCaps))
{
dwInfoSize = sizeof(DDMORESURFACECAPS);
pInfo = &peDdGl->ddMoreSurfaceCaps;
}
if (dwInfoSize && pInfo)
{
gpEngFuncs.DxEngLockHdev(peDdGl->hDev);
intDdGetDriverInfo(peDdGl, drvInfoData->guidInfo, &callbackStruct, dwInfoSize, &dwInfoSize);
gpEngFuncs.DxEngUnlockHdev(peDdGl->hDev);
memcpy(drvInfoData->lpvData, callbackStruct, dwInfoSize);
}
InterlockedDecrement((VOID*)&peDdL->pobj.cExclusiveLock);
return TRUE;
}
/*++
* @name DxDdQueryDirectDrawObject
* @implemented
*
* Function queries the DirectDraw object for its functionality
*
* @return
* TRUE on success.
*--*/
BOOL
NTAPI
DxDdQueryDirectDrawObject(
HANDLE DdHandle,
DD_HALINFO* pDdHalInfo,
DWORD* pCallBackFlags,
LPD3DNTHAL_CALLBACKS pd3dNtHalCallbacks,
LPD3DNTHAL_GLOBALDRIVERDATA pd3dNtGlobalDriverData,
PDD_D3DBUFCALLBACKS pd3dBufCallbacks,
LPDDSURFACEDESC pTextureFormats,
DWORD* p8,
VIDEOMEMORY* p9,
DWORD* pdwNumFourCC,
DWORD* pdwFourCC)
{
PEDD_DIRECTDRAW_LOCAL peDdL;
PEDD_DIRECTDRAW_GLOBAL peDdGl;
BOOL RetVal = FALSE;
if (!DdHandle)
return RetVal;
if (!pDdHalInfo)
return RetVal;
if (!gpEngFuncs.DxEngScreenAccessCheck())
return RetVal;
peDdL = (PEDD_DIRECTDRAW_LOCAL)DdHmgLock(DdHandle, ObjType_DDLOCAL_TYPE, FALSE);
if (peDdL)
{
peDdGl = peDdL->peDirectDrawGlobal2;
gpEngFuncs.DxEngLockHdev(peDdGl->hDev);
memcpy(pDdHalInfo, &peDdGl->ddHalInfo, sizeof(DD_HALINFO));
if (pCallBackFlags)
{
*(DWORD*)pCallBackFlags = peDdGl->ddCallbacks.dwFlags;
2018-03-04 20:58:15 +00:00
*(DWORD*)((ULONG_PTR)pCallBackFlags + 4) = peDdGl->ddSurfaceCallbacks.dwFlags;
*(DWORD*)((ULONG_PTR)pCallBackFlags + 8) = peDdGl->ddPaletteCallbacks.dwFlags;
}
if (pd3dNtHalCallbacks)
memcpy(pd3dNtHalCallbacks, &peDdGl->d3dNtHalCallbacks, sizeof(peDdGl->d3dNtHalCallbacks));
if (pd3dNtGlobalDriverData)
memcpy(pd3dNtGlobalDriverData, &peDdGl->d3dNtGlobalDriverData, sizeof(peDdGl->d3dNtGlobalDriverData));
if (pd3dBufCallbacks)
memcpy(pd3dBufCallbacks, &peDdGl->d3dBufCallbacks, sizeof(peDdGl->d3dBufCallbacks));
if (pTextureFormats)
memcpy(pTextureFormats, &peDdGl->d3dNtGlobalDriverData.lpTextureFormats, peDdGl->d3dNtGlobalDriverData.dwNumTextureFormats * sizeof(DDSURFACEDESC2));
if (pdwNumFourCC)
*pdwNumFourCC = peDdGl->dwNumFourCC;
if (pdwFourCC)
memcpy(pdwFourCC, &peDdGl->pdwFourCC, 4 * peDdGl->dwNumFourCC);
RetVal = TRUE;
gpEngFuncs.DxEngUnlockHdev(peDdGl->hDev);
InterlockedDecrement((VOID*)&peDdL->pobj.cExclusiveLock);
}
return RetVal;
}
/*++
* @name DxDdEnableDirectDraw
* @implemented
*
* Function enables DirectDraw
*
* @param PEDD_DIRECTDRAW_GLOBAL peDdGl
* Pointer to destination DirectDrawGlobal structure
*--*/
BOOL
NTAPI
DxDdEnableDirectDraw(HANDLE hDev, BOOL arg2/*What for?*/)
{
PEDD_DIRECTDRAW_GLOBAL peDdGl = NULL;
if (gpEngFuncs.DxEngGetHdevData(hDev, DxEGShDevData_display))
{
peDdGl = (PEDD_DIRECTDRAW_GLOBAL)gpEngFuncs.DxEngGetHdevData(hDev, DxEGShDevData_eddg);
peDdGl->hDev = hDev;
peDdGl->bSuspended = FALSE;
peDdGl->dhpdev = (PVOID)gpEngFuncs.DxEngGetHdevData(hDev, DxEGShDevData_dhpdev);
intDdEnableDriver(peDdGl);
return TRUE;
}
return FALSE;
}
/*++
* @name DxDdReenableDirectDrawObject
* @implemented
*
* Function re-enables DirectDraw object after mode switch
*
* @param HANDLE DdHandle
* DirectDraw object handle
*
* @param PVOID p2
* ???
*
* @return
* TRUE on success.
*
* @remarks
* Missing all AGP stuff and second parameter handling
*--*/
DWORD
NTAPI
DxDdReenableDirectDrawObject(
HANDLE DdHandle,
PVOID p2)
{
PEDD_DIRECTDRAW_LOCAL peDdL;
PEDD_DIRECTDRAW_GLOBAL peDdGl;
HDC hDC;
DWORD RetVal = FALSE;
peDdL = (PEDD_DIRECTDRAW_LOCAL)DdHmgLock(DdHandle, ObjType_DDLOCAL_TYPE, FALSE);
if (!peDdL)
return RetVal;
peDdGl = peDdL->peDirectDrawGlobal2;
hDC = gpEngFuncs.DxEngGetDesktopDC(0, FALSE, FALSE);
gpEngFuncs.DxEngLockShareSem();
gpEngFuncs.DxEngLockHdev(peDdGl->hDev);
if (peDdGl->fl & 1 &&
gpEngFuncs.DxEngGetDCState(hDC, 2) != 1 &&
!(gpEngFuncs.DxEngGetHdevData(peDdGl->hDev, DxEGShDevData_OpenRefs)) &&
!(gpEngFuncs.DxEngGetHdevData(peDdGl->hDev, DxEGShDevData_disable)) &&
[WIN32SS][ENG][NTDDRAW] Manage DirectDraw instances when switching display mode (#4519) CORE-17932 [ENG] Implement DirectDraw management in switch display mode functions (e.g. resolution change, color depth, display frequency etc.): - Switch DirectDraw instances between the two PDEVs (the current one and the new one allocated by ourselves) by calling dxg!DxDdDynamicModeChange function. - Suspend them before and resume after the display mode switch, by calling dxg!DxDdsuspendDirectDraw and dxg!DxDdResumeDirectDraw appropriately. We currently don't have these functions implemented, but MS DXG has, so it allows to properly manage DirectDraw PDEVs using this driver, similarly to Windows. My analysis confirms that these functions are always called in XP/2k3 on display mode switch, even when there is no any DirectX app running at the moment. Analyzing their prototypes show that my guesses are correct. - Initialize hDev and dhpdev members for EDD_DIRECTDRAW_GLOBAL for newly created surfaces, switch them during mode change and re-initialize after it also. They are commonly used by DirectDraw stack. In addition, enable DirectDraw for old and new PDEVs, by calling dxg!DxDdEnableDirectDraw function. [NTDDRAW] Additionally, fix usage of DirectDraw lock count in the PDEVOBJ structure. - Enable cDirectDrawDisableLocks member for storing its value, instead of DxDd_nCount, which is marked as ROS-specific. - Use it in win32k!DxEngGet/SetHdevData for getting/setting DirectDraw count appropriately. My analysis also shows that in Windows, the PDEVOBJ::cDirectDrawDisableLocks method calls DxEngGetHdevData with type 8, which corresponds to our DxDd_nCount. So there are no doubts that this member is used there. - Rename DxEngGetHdevData_dd_count alias of type 8 to DxEngGetHdevData_dd_locks, to match more accurately an actual member name. Update the enumeration and fix all code parts appropriately. All these changes allow to properly change display mode during executing DirectDraw applications, when they try to switch in full-screen mode. At least a bugcheck that happened before my changes, does no longer appear. There are still some games that don't run correctly, as if there is no 3D acceleration (which actually exists). This requires further investigations.
2023-06-21 16:00:24 +00:00
!(gpEngFuncs.DxEngGetHdevData(peDdGl->hDev, DxEGShDevData_dd_locks)) &&
gpEngFuncs.DxEngGetHdevData(peDdGl->hDev, DxEGShDevData_DitherFmt) >= BMF_8BPP)
{
// reset acceleration and suspend flags
peDdGl->fl &= 0xFFFFFFFD;
peDdGl->bSuspended = 0;
peDdGl->dhpdev = (PVOID)gpEngFuncs.DxEngGetHdevData(peDdGl->hDev, DxEGShDevData_dhpdev);
RetVal = TRUE;
// FIXME AGP Stuff
}
gpEngFuncs.DxEngUnlockHdev(peDdGl->hDev);
gpEngFuncs.DxEngUnlockShareSem();
InterlockedDecrement((VOID*)&peDdL->pobj.cExclusiveLock);
return RetVal;
}
PEDD_SURFACE
NTAPI
intDdCreateNewSurfaceObject(PEDD_DIRECTDRAW_LOCAL peDdL, HANDLE hDirectDrawLocal, PDD_SURFACE_GLOBAL pDdSurfGlob, PDD_SURFACE_LOCAL pDdSurfLoc, PDD_SURFACE_MORE pDdSurfMore)
{
PEDD_SURFACE pSurface = NULL;
// first check if we can assign it from current ddHandle
if (hDirectDrawLocal)
{
pSurface = (PEDD_SURFACE)DdHmgLock(hDirectDrawLocal, ObjType_DDSURFACE_TYPE, FALSE);
// check if surface is locked and belongs to correct DirectDrawLocal
if ((pSurface)&&((pSurface->peDirectDrawLocal != peDdL)||(!pSurface->hSecure)))
{
InterlockedDecrement((VOID*)&peDdL->pobj.cExclusiveLock);
return NULL;
}
}
// if surface not found from ddHandle or ddHandle not provided
if (!pSurface)
{
// create new surface object
pSurface = (PEDD_SURFACE)DdHmgAlloc(sizeof(EDD_SURFACE), ObjType_DDSURFACE_TYPE, TRUE);
if (pSurface)
{
pSurface->ddsSurfaceLocal.lpGbl = &pSurface->ddsSurfaceGlobal;
pSurface->ddsSurfaceLocal.lpSurfMore = &pSurface->ddsSurfaceMore;
pSurface->ddsSurfaceInt.lpLcl = &pSurface->ddsSurfaceLocal;
pSurface->peDirectDrawLocal = peDdL;
pSurface->peDirectDrawGlobalNext = peDdL->peDirectDrawGlobal2;
pSurface->ldev = gpEngFuncs.DxEngGetHdevData(pSurface->peDirectDrawGlobalNext->hDev, DxEGShDevData_ldev);
pSurface->gdev = gpEngFuncs.DxEngGetHdevData(pSurface->peDirectDrawGlobalNext->hDev, DxEGShDevData_GDev);
pSurface->hSecure = (VOID*)1;
}
}
if (pSurface)
{
pSurface->ddsSurfaceGlobal.fpVidMem = pDdSurfGlob->fpVidMem;
pSurface->ddsSurfaceGlobal.lPitch = pDdSurfGlob->lPitch;
pSurface->ddsSurfaceGlobal.wWidth = pDdSurfGlob->wWidth;
pSurface->ddsSurfaceGlobal.wHeight = pDdSurfGlob->wHeight;
pSurface->wWidth = pDdSurfGlob->wWidth;
pSurface->wHeight = pDdSurfGlob->wHeight;
memcpy(&pSurface->ddsSurfaceGlobal.ddpfSurface, &pDdSurfGlob->ddpfSurface, sizeof(pSurface->ddsSurfaceGlobal.ddpfSurface));
pSurface->ddsSurfaceLocal.ddsCaps.dwCaps = pDdSurfLoc->ddsCaps.dwCaps;
pSurface->ddsSurfaceMore.ddsCapsEx.dwCaps2 = pDdSurfMore->ddsCapsEx.dwCaps2;
pSurface->ddsSurfaceMore.ddsCapsEx.dwCaps3 = pDdSurfMore->ddsCapsEx.dwCaps3;
pSurface->ddsSurfaceMore.ddsCapsEx.dwCaps4 = pDdSurfMore->ddsCapsEx.dwCaps4;
pSurface->ddsSurfaceMore.dwSurfaceHandle = pDdSurfMore->dwSurfaceHandle;
pSurface->hSecure = (VOID*)1;
peDdL->peSurface_DdList = pSurface;
2018-03-04 20:58:15 +00:00
peDdL->hSurface = (ULONG_PTR)pSurface->pobj.hHmgr;
}
return pSurface;
}
HANDLE
NTAPI
DxDdCreateSurfaceObject(HANDLE hDirectDrawLocal,
HANDLE hSurface,
PDD_SURFACE_LOCAL puSurfaceLocal,
PDD_SURFACE_MORE puSurfaceMore,
PDD_SURFACE_GLOBAL puSurfaceGlobal,
BOOL bComplete)
{
HANDLE RetVal = FALSE;
PEDD_DIRECTDRAW_LOCAL peDdL = NULL;
PEDD_SURFACE pDdSurface = NULL;
peDdL = (PEDD_DIRECTDRAW_LOCAL)DdHmgLock(hDirectDrawLocal, ObjType_DDLOCAL_TYPE, FALSE);
if (!peDdL)
return RetVal;
pDdSurface = intDdCreateNewSurfaceObject(peDdL, hSurface, puSurfaceGlobal, puSurfaceLocal, puSurfaceMore);
if (!pDdSurface)
{
InterlockedDecrement((VOID*)&peDdL->pobj.cExclusiveLock);
return RetVal;
}
RetVal = pDdSurface->pobj.hHmgr;
InterlockedDecrement((VOID*)&pDdSurface->pobj.cExclusiveLock);
InterlockedDecrement((VOID*)&peDdL->pobj.cExclusiveLock);
return RetVal;
}