Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

530 lines
16 KiB

  1. #include "ddrawpr.h"
  2. #include <ddrawint.h>
  3. #include "ddithunk.h"
  4. #include <d3d8sddi.h>
  5. typedef struct
  6. {
  7. DDRAWI_DDRAWSURFACE_LCL Lcl;
  8. DDRAWI_DDRAWSURFACE_GBL Gbl;
  9. DDRAWI_DDRAWSURFACE_MORE More;
  10. ATTACHLIST From;
  11. ATTACHLIST To;
  12. } SWDDIDDRAWI_LCL;
  13. LPDDRAWI_DDRAWSURFACE_LCL
  14. SwDDIBuildHeavyWeightSurface (
  15. LPDDRAWI_DIRECTDRAW_LCL pDDrawLocal,
  16. PD3D8_CREATESURFACEDATA pCreateSurface,
  17. DD_SURFACE_LOCAL* pSurfaceLocal,
  18. DD_SURFACE_GLOBAL* pSurfaceGlobal,
  19. DD_SURFACE_MORE* pSurfaceMore,
  20. DWORD index)
  21. {
  22. SWDDIDDRAWI_LCL *pSWDDILcl;
  23. LPDDRAWI_DDRAWSURFACE_LCL pLcl;
  24. pSWDDILcl = MemAlloc(sizeof(*pSWDDILcl));
  25. if (pSWDDILcl == NULL)
  26. {
  27. return NULL;
  28. }
  29. pLcl = &pSWDDILcl->Lcl;
  30. pLcl->lpGbl = &pSWDDILcl->Gbl;
  31. pLcl->lpSurfMore = &pSWDDILcl->More;
  32. memcpy(&pLcl->lpGbl->ddpfSurface, &pSurfaceGlobal->ddpfSurface, sizeof(DDPIXELFORMAT));
  33. pLcl->lpGbl->wWidth = (WORD) pSurfaceGlobal->wWidth;
  34. pLcl->lpGbl->wHeight = (WORD) pSurfaceGlobal->wHeight;
  35. pLcl->ddsCaps = pSurfaceLocal->ddsCaps;
  36. pLcl->lpSurfMore->ddsCapsEx = pSurfaceMore->ddsCapsEx;
  37. pLcl->lpSurfMore->dwSurfaceHandle = pSurfaceMore->dwSurfaceHandle;
  38. pLcl->lpSurfMore->lpDD_lcl = pDDrawLocal;
  39. pLcl->dwFlags = pSurfaceLocal->dwFlags;
  40. pLcl->lpGbl->fpVidMem = (FLATPTR) pCreateSurface->pSList[index].pbPixels;
  41. pLcl->lpGbl->lPitch = pCreateSurface->pSList[index].iPitch;
  42. if ((pCreateSurface->Type == D3DRTYPE_VOLUME) ||
  43. (pCreateSurface->Type == D3DRTYPE_VOLUMETEXTURE))
  44. {
  45. pLcl->lpGbl->lSlicePitch = pCreateSurface->pSList[index].iSlicePitch;
  46. }
  47. return pLcl;
  48. }
  49. void
  50. SwDDICreateSurfaceEx(LPDDRAWI_DIRECTDRAW_LCL pDrv,
  51. LPDDRAWI_DDRAWSURFACE_LCL pLcl)
  52. {
  53. PD3D8_SWCALLBACKS pCallbacks = (PD3D8_SWCALLBACKS)pDrv->lpGbl->lpDDCBtmp;
  54. DDHAL_CREATESURFACEEXDATA CreateExData;
  55. if ((pLcl != NULL) &&
  56. (pCallbacks->CreateSurfaceEx != NULL))
  57. {
  58. CreateExData.dwFlags = 0;
  59. CreateExData.lpDDLcl = pDrv;
  60. CreateExData.lpDDSLcl = pLcl;
  61. pCallbacks->CreateSurfaceEx(&CreateExData);
  62. }
  63. }
  64. HRESULT
  65. SwDDICreateSurface(PD3D8_CREATESURFACEDATA pCreateSurface,
  66. DD_SURFACE_LOCAL* pDDSurfaceLocal,
  67. DD_SURFACE_GLOBAL* pDDSurfaceGlobal,
  68. DD_SURFACE_MORE* pDDSurfaceMore)
  69. {
  70. LPDDRAWI_DIRECTDRAW_LCL pDrv =
  71. ((PDDDEVICEHANDLE)pCreateSurface->hDD)->pDD;
  72. DDHAL_CREATESURFACEDATA CreateSurfaceData;
  73. PD3D8_SWCALLBACKS pCallbacks =
  74. (PD3D8_SWCALLBACKS)pDrv->lpGbl->lpDDCBtmp;
  75. DWORD dwRet = DDHAL_DRIVER_NOTHANDLED;
  76. DDSURFACEDESC2 SurfaceDesc;
  77. DWORD i;
  78. if (pCallbacks->CreateSurface)
  79. {
  80. memset(&CreateSurfaceData, 0, sizeof(CreateSurfaceData));
  81. CreateSurfaceData.lpDD = pDrv->lpGbl;
  82. CreateSurfaceData.lpDDSurfaceDesc = (DDSURFACEDESC*) &SurfaceDesc;
  83. CreateSurfaceData.lplpSList = NULL;
  84. CreateSurfaceData.dwSCnt = pCreateSurface->dwSCnt;
  85. CreateSurfaceData.lplpSList = (LPDDRAWI_DDRAWSURFACE_LCL*)
  86. MemAlloc(sizeof(LPDDRAWI_DDRAWSURFACE_LCL) * CreateSurfaceData.dwSCnt);
  87. if (CreateSurfaceData.lplpSList == NULL)
  88. {
  89. return E_OUTOFMEMORY;
  90. }
  91. // Build a surface desc
  92. RtlZeroMemory(&SurfaceDesc, sizeof(SurfaceDesc));
  93. SurfaceDesc.dwSize = sizeof(SurfaceDesc);
  94. SurfaceDesc.ddsCaps.dwCaps = pDDSurfaceLocal[0].ddsCaps.dwCaps;
  95. SurfaceDesc.ddpfPixelFormat = pDDSurfaceGlobal[0].ddpfSurface;
  96. if (pCreateSurface->Type == D3DRTYPE_TEXTURE)
  97. {
  98. SurfaceDesc.dwMipMapCount = pCreateSurface->dwSCnt;
  99. }
  100. else if (pCreateSurface->dwSCnt > 1)
  101. {
  102. SurfaceDesc.dwBackBufferCount = pCreateSurface->dwSCnt - 1;
  103. SurfaceDesc.dwFlags |= DDSD_BACKBUFFERCOUNT;
  104. }
  105. SurfaceDesc.dwHeight = pDDSurfaceGlobal[0].wHeight;
  106. SurfaceDesc.dwWidth = pDDSurfaceGlobal[0].wWidth;
  107. SurfaceDesc.dwFlags |= DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
  108. if (pDDSurfaceLocal[0].dwFlags & DDRAWISURF_HASPIXELFORMAT)
  109. {
  110. SurfaceDesc.dwFlags |= DDSD_PIXELFORMAT;
  111. }
  112. if (pCreateSurface->Type == D3DRTYPE_VERTEXBUFFER)
  113. {
  114. SurfaceDesc.dwFVF = pCreateSurface->dwFVF;
  115. SurfaceDesc.dwFlags |= DDSD_FVF;
  116. }
  117. // Have to build a heavy weight surface structure that the driver
  118. // can understand
  119. for (i = 0; i < CreateSurfaceData.dwSCnt; i++)
  120. {
  121. CreateSurfaceData.lplpSList[i] =
  122. ((PDDSURFHANDLE)pCreateSurface->pSList[i].hKernelHandle)->pLcl;
  123. }
  124. dwRet = pCallbacks->CreateSurface(&CreateSurfaceData);
  125. // Now copy the fpVidMem and the pitch that the driver setup
  126. // back to the permanent structures
  127. for (i = 0; i < CreateSurfaceData.dwSCnt; i++)
  128. {
  129. pCreateSurface->pSList[i].pbPixels = (BYTE*)
  130. CreateSurfaceData.lplpSList[i]->lpGbl->fpVidMem;
  131. pCreateSurface->pSList[i].iPitch =
  132. CreateSurfaceData.lplpSList[i]->lpGbl->lPitch;
  133. if ((pCreateSurface->Type == D3DRTYPE_VOLUME) ||
  134. (pCreateSurface->Type == D3DRTYPE_VOLUMETEXTURE))
  135. {
  136. pCreateSurface->pSList[i].iSlicePitch =
  137. CreateSurfaceData.lplpSList[i]->lpGbl->lSlicePitch;
  138. }
  139. }
  140. // Now clean everything up
  141. MemFree(CreateSurfaceData.lplpSList);
  142. if (dwRet == DDHAL_DRIVER_NOTHANDLED)
  143. {
  144. DPF_ERR("Software Driver failed creation of surface");
  145. return E_FAIL;
  146. }
  147. return CreateSurfaceData.ddRVal;
  148. }
  149. else
  150. {
  151. DPF_ERR("Software Driver doesn't support creation of surfaces");
  152. return DDERR_UNSUPPORTED;
  153. }
  154. }
  155. void
  156. SwDDIAttachSurfaces(LPDDRAWI_DDRAWSURFACE_LCL psurf_from_lcl, LPDDRAWI_DDRAWSURFACE_LCL psurf_to_lcl)
  157. {
  158. LPATTACHLIST pal_from;
  159. LPATTACHLIST pal_to;
  160. /*
  161. * allocate attachment structures
  162. */
  163. pal_from = & (((SWDDIDDRAWI_LCL*) psurf_to_lcl)->From);
  164. pal_to = & (((SWDDIDDRAWI_LCL*) psurf_to_lcl)->To);
  165. /*
  166. * connect the surfaces
  167. */
  168. pal_from->lpAttached = psurf_to_lcl;
  169. pal_from->dwFlags = DDAL_IMPLICIT;
  170. pal_from->lpLink = psurf_from_lcl->lpAttachList;
  171. psurf_from_lcl->lpAttachList = pal_from;
  172. psurf_from_lcl->dwFlags |= DDRAWISURF_ATTACHED;
  173. pal_to->lpAttached = psurf_from_lcl;
  174. pal_to->dwFlags = DDAL_IMPLICIT;
  175. pal_to->lpLink = psurf_to_lcl->lpAttachListFrom;
  176. psurf_to_lcl->lpAttachListFrom = pal_to;
  177. psurf_to_lcl->dwFlags |= DDRAWISURF_ATTACHED_FROM;
  178. }
  179. DWORD WINAPI
  180. SwContextCreate(PD3D8_CONTEXTCREATEDATA pCreateContext)
  181. {
  182. LPDDRAWI_DIRECTDRAW_LCL pDrv = ((PDDDEVICEHANDLE)pCreateContext->hDD)->pDD;
  183. PD3D8_SWCALLBACKS pCallbacks = (PD3D8_SWCALLBACKS)pDrv->lpGbl->lpDDCBtmp;
  184. D3DHAL_CONTEXTCREATEDATA ContextData;
  185. DWORD dwRet = DDHAL_DRIVER_NOTHANDLED;
  186. if (pCallbacks->CreateContext != NULL)
  187. {
  188. ContextData.lpDDLcl = pDrv;
  189. ContextData.lpDDSLcl = ((PDDSURFHANDLE)pCreateContext->hSurface)->pLcl;
  190. if (pCreateContext->hDDSZ == NULL)
  191. {
  192. ContextData.lpDDSZLcl = NULL;
  193. }
  194. else
  195. {
  196. ContextData.lpDDSZLcl = ((PDDSURFHANDLE)pCreateContext->hDDSZ)->pLcl;
  197. }
  198. ContextData.dwPID = pCreateContext->dwPID;
  199. ContextData.dwhContext = pCreateContext->dwhContext;
  200. dwRet = pCallbacks->CreateContext(&ContextData);
  201. pCreateContext->dwhContext = ContextData.dwhContext;
  202. pCreateContext->ddrval = MapLegacyResult(ContextData.ddrval);
  203. }
  204. return dwRet;
  205. }
  206. DWORD WINAPI
  207. SwDrawPrimitives2(PD3D8_DRAWPRIMITIVES2DATA pdp2data)
  208. {
  209. LPDDRAWI_DIRECTDRAW_LCL pDrv = ((PDDSURFHANDLE)pdp2data->hDDCommands)->pDevice->pDD;
  210. PD3D8_SWCALLBACKS pCallbacks = (PD3D8_SWCALLBACKS)pDrv->lpGbl->lpDDCBtmp;
  211. D3DHAL_DRAWPRIMITIVES2DATA DP2Data;
  212. HRESULT hr;
  213. DWORD dwRet;
  214. dwRet = DDHAL_DRIVER_NOTHANDLED;
  215. if (pCallbacks->DrawPrimitives2 != NULL)
  216. {
  217. memcpy(&DP2Data, pdp2data, sizeof(DP2Data));
  218. DP2Data.lpDDCommands = ((PDDSURFHANDLE)pdp2data->hDDCommands)->pLcl;
  219. if (!(DP2Data.dwFlags & D3DHALDP2_USERMEMVERTICES))
  220. {
  221. DP2Data.lpDDVertex = ((PDDSURFHANDLE)pdp2data->hDDVertex)->pLcl;
  222. }
  223. dwRet = pCallbacks->DrawPrimitives2(&DP2Data);
  224. pdp2data->ddrval = DP2Data.ddrval;
  225. pdp2data->dwErrorOffset = DP2Data.dwErrorOffset;
  226. // If the call to the driver succeded, swap the buffers if needed and
  227. // perform GetAliasVidmem
  228. if (dwRet == DDHAL_DRIVER_HANDLED && (DP2Data.ddrval == S_OK))
  229. {
  230. pdp2data->fpVidMem_CB = 0;
  231. pdp2data->dwLinearSize_CB = 0;
  232. pdp2data->fpVidMem_VB = 0;
  233. pdp2data->dwLinearSize_VB = 0;
  234. if (DP2Data.dwFlags & D3DHALDP2_SWAPCOMMANDBUFFER)
  235. {
  236. // CONSIDER: Implement VidMem command buffer
  237. }
  238. if ((DP2Data.dwFlags & D3DHALDP2_SWAPVERTEXBUFFER) && !(DP2Data.dwFlags & D3DHALDP2_USERMEMVERTICES))
  239. {
  240. pdp2data->fpVidMem_VB = ((PDDSURFHANDLE)pdp2data->hDDVertex)->fpVidMem;
  241. pdp2data->dwLinearSize_VB = ((PDDSURFHANDLE)pdp2data->hDDVertex)->dwLinearSize;
  242. }
  243. }
  244. }
  245. return dwRet;
  246. }
  247. DWORD
  248. SwDDILock(HANDLE hDD, PDDSURFHANDLE pSurf, DD_LOCKDATA* pLockData)
  249. {
  250. LPDDRAWI_DIRECTDRAW_LCL pDrv = ((PDDDEVICEHANDLE)hDD)->pDD;
  251. PD3D8_SWCALLBACKS pCallbacks = (PD3D8_SWCALLBACKS)pDrv->lpGbl->lpDDCBtmp;
  252. DDHAL_LOCKDATA LockData;
  253. DWORD dwRet = DDHAL_DRIVER_HANDLED;
  254. LockData.lpDD = pDrv->lpGbl;
  255. LockData.lpDDSurface = pSurf->pLcl;
  256. LockData.bHasRect = pLockData->bHasRect;
  257. LockData.rArea = pLockData->rArea;
  258. LockData.dwFlags = pLockData->dwFlags;
  259. LockData.ddRVal = DDERR_WASSTILLDRAWING;
  260. LockData.lpSurfData = NULL;
  261. pSurf->pLcl->lpGbl->dwUsageCount++;
  262. while (LockData.ddRVal == DDERR_WASSTILLDRAWING)
  263. {
  264. if (pCallbacks->Lock != NULL)
  265. {
  266. dwRet = pCallbacks->Lock(&LockData);
  267. }
  268. else
  269. {
  270. LockData.ddRVal = E_FAIL;
  271. }
  272. }
  273. if (LockData.ddRVal != S_OK)
  274. {
  275. pSurf->pLcl->lpGbl->dwUsageCount--;
  276. }
  277. pLockData->ddRVal = LockData.ddRVal;
  278. pLockData->lpSurfData = LockData.lpSurfData;
  279. return dwRet;
  280. }
  281. DWORD
  282. SwDDIUnlock(HANDLE hDD, PDDSURFHANDLE pSurf, DD_UNLOCKDATA* pUnlockData)
  283. {
  284. LPDDRAWI_DIRECTDRAW_LCL pDrv = ((PDDDEVICEHANDLE)hDD)->pDD;
  285. PD3D8_SWCALLBACKS pCallbacks = (PD3D8_SWCALLBACKS)pDrv->lpGbl->lpDDCBtmp;
  286. DDHAL_UNLOCKDATA UnlockData;
  287. DWORD dwRet = DDHAL_DRIVER_HANDLED;
  288. UnlockData.lpDD = pDrv->lpGbl;
  289. UnlockData.lpDDSurface = pSurf->pLcl;
  290. UnlockData.ddRVal = S_OK;
  291. pSurf->pLcl->lpGbl->dwUsageCount--;
  292. if (pCallbacks->Unlock != NULL)
  293. {
  294. dwRet = pCallbacks->Unlock(&UnlockData);
  295. }
  296. pUnlockData->ddRVal = UnlockData.ddRVal;
  297. return dwRet;
  298. }
  299. void BreakOutstandingLocks(PDDSURFHANDLE pSurf)
  300. {
  301. DD_UNLOCKDATA UnlockData;
  302. while (pSurf->pLcl->lpGbl->dwUsageCount > 0)
  303. {
  304. SwDDIUnlock(pSurf->pDevice, pSurf, &UnlockData);
  305. }
  306. }
  307. DWORD
  308. SwDDIDestroySurface(HANDLE hDD, PDDSURFHANDLE pSurf)
  309. {
  310. LPDDRAWI_DIRECTDRAW_LCL pDrv = ((PDDDEVICEHANDLE)hDD)->pDD;
  311. PD3D8_SWCALLBACKS pCallbacks = (PD3D8_SWCALLBACKS)pDrv->lpGbl->lpDDCBtmp;
  312. DDHAL_DESTROYSURFACEDATA DestroyData;
  313. DestroyData.lpDD = pDrv->lpGbl;
  314. DestroyData.lpDDSurface = pSurf->pLcl;
  315. DestroyData.ddRVal = S_OK;
  316. BreakOutstandingLocks(pSurf);
  317. if (pCallbacks->DestroySurface != NULL)
  318. {
  319. pCallbacks->DestroySurface(&DestroyData);
  320. }
  321. return DestroyData.ddRVal;
  322. }
  323. LPDDRAWI_DIRECTDRAW_LCL
  324. SwDDICreateDirectDraw(void)
  325. {
  326. LPDDRAWI_DIRECTDRAW_LCL pLcl;
  327. LPDDRAWI_DIRECTDRAW_GBL pGbl;
  328. BYTE* pTemp;
  329. pLcl = (LPDDRAWI_DIRECTDRAW_LCL)MemAlloc(sizeof(DDRAWI_DIRECTDRAW_LCL) +
  330. sizeof(DDRAWI_DIRECTDRAW_GBL));
  331. if (pLcl == NULL)
  332. {
  333. return NULL;
  334. }
  335. pTemp = (BYTE*)pLcl;
  336. pTemp += sizeof(DDRAWI_DIRECTDRAW_LCL);
  337. pGbl = (LPDDRAWI_DIRECTDRAW_GBL) pTemp;
  338. pLcl->lpGbl = pGbl;
  339. pLcl->dwLocalRefCnt = 1;
  340. pGbl->dwRefCnt = 1;
  341. return pLcl;
  342. }
  343. extern HRESULT WINAPI
  344. D3D8GetSWInfo( D3DCAPS8* pCaps, PD3D8_SWCALLBACKS pCallbacks,
  345. DWORD* pNumTextures, DDSURFACEDESC** ppTexList );
  346. void
  347. SwDDIMungeCaps(HINSTANCE hLibrary, HANDLE hDD,
  348. PD3D8_DRIVERCAPS pDriverCaps,
  349. PD3D8_CALLBACKS pCallbacks,
  350. LPDDSURFACEDESC pTextureFormats,
  351. UINT* pcTextureFormats,
  352. VOID* pInitFunction
  353. )
  354. {
  355. PD3D8GetSWInfo pfnGetSWInfo = NULL;
  356. D3DCAPS8 swCaps;
  357. D3D8_SWCALLBACKS swCallbacks;
  358. LPDDRAWI_DIRECTDRAW_LCL pLcl;
  359. LPDDRAWI_DIRECTDRAW_GBL pGbl;
  360. PDDDEVICEHANDLE pDevice = (PDDDEVICEHANDLE) hDD;
  361. DWORD i;
  362. DWORD NumTex = 0;
  363. DDSURFACEDESC* pTexList = NULL;
  364. // Get the info from the software driver
  365. memset (&swCaps, 0, sizeof(swCaps));
  366. memset (&swCallbacks, 0, sizeof(swCallbacks));
  367. if (hLibrary != NULL)
  368. {
  369. pfnGetSWInfo = (PD3D8GetSWInfo)GetProcAddress (hLibrary, D3D8HOOK_GETSWINFOPROCNAME);
  370. }
  371. else
  372. {
  373. pfnGetSWInfo = (PD3D8GetSWInfo)pInitFunction;
  374. }
  375. if ((hLibrary == NULL) && (pDevice->DeviceType == D3DDEVTYPE_REF))
  376. {
  377. // No hLibrary means time to fall back on defeatured ref.
  378. DPF(0,"Could not find d3dref8.dll, loading internal defeatured ReferenceDevice, no rendering will take place\n");
  379. D3D8GetSWInfo (&swCaps, &swCallbacks, &NumTex, &pTexList);
  380. }
  381. else if (pfnGetSWInfo != NULL)
  382. {
  383. (*pfnGetSWInfo)(&swCaps, &swCallbacks, &NumTex, &pTexList);
  384. }
  385. // Fill in out DDraw structure with the info that we have
  386. pLcl = pDevice->pDD;
  387. pGbl = pLcl->lpGbl;
  388. strcpy (pGbl->cDriverName, pDevice->szDeviceName);
  389. pGbl->vmiData.dwDisplayWidth = pDriverCaps->DisplayWidth;
  390. pGbl->vmiData.dwDisplayHeight = pDriverCaps->DisplayHeight;
  391. ConvertToOldFormat(&pGbl->vmiData.ddpfDisplay, pDriverCaps->DisplayFormatWithAlpha);
  392. // Overwite the hardware caps w/ the software caps
  393. memcpy (&pDriverCaps->D3DCaps, &swCaps, sizeof(swCaps));
  394. pDriverCaps->dwFlags |= DDIFLAG_D3DCAPS8;
  395. // Copy over our texture format list if required.
  396. *pcTextureFormats = NumTex;
  397. if (pTextureFormats && pTexList)
  398. {
  399. memcpy(
  400. pTextureFormats,
  401. pTexList,
  402. sizeof (*pTexList) * NumTex);
  403. }
  404. // Now change the callback table to point to the ones for the SW drivers
  405. if (swCallbacks.CreateContext == NULL)
  406. {
  407. pCallbacks->CreateContext = NULL;
  408. }
  409. else
  410. {
  411. pCallbacks->CreateContext = SwContextCreate;
  412. }
  413. pCallbacks->ContextDestroy = (PD3D8DDI_CONTEXTDESTROY) swCallbacks.ContextDestroy;
  414. pCallbacks->ContextDestroyAll = (PD3D8DDI_CONTEXTDESTROYALL) swCallbacks.ContextDestroyAll;
  415. pCallbacks->RenderState = (PD3D8DDI_RENDERSTATE) swCallbacks.RenderState;
  416. pCallbacks->RenderPrimitive = (PD3D8DDI_RENDERPRIMITIVE) swCallbacks.RenderPrimitive;
  417. if (swCallbacks.DrawPrimitives2 == NULL)
  418. {
  419. pCallbacks->DrawPrimitives2 = NULL;
  420. }
  421. else
  422. {
  423. pCallbacks->DrawPrimitives2 = SwDrawPrimitives2;
  424. }
  425. pCallbacks->GetDriverState = (PD3D8DDI_GETDRIVERSTATE) swCallbacks.GetDriverState;
  426. pCallbacks->ValidateTextureStageState = (PD3D8DDI_VALIDATETEXTURESTAGESTATE) swCallbacks.ValidateTextureStageState;
  427. pCallbacks->SceneCapture = (PD3D8DDI_SCENECAPTURE) swCallbacks.SceneCapture;
  428. pCallbacks->Clear2 = (PD3D8DDI_CLEAR2) swCallbacks.Clear2;
  429. // Save the original software callbacks so we can call the software driver later
  430. if (pGbl->lpDDCBtmp == NULL)
  431. {
  432. pGbl->lpDDCBtmp = (LPDDHAL_CALLBACKS) MemAlloc(sizeof(D3D8_SWCALLBACKS));
  433. }
  434. if (pGbl->lpDDCBtmp != NULL)
  435. {
  436. memcpy(pGbl->lpDDCBtmp, &swCallbacks, sizeof(swCallbacks));
  437. }
  438. }