Leaked source code of windows server 2003
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.

1281 lines
45 KiB

  1. /*==========================================================================;
  2. *
  3. * Copyright (C) 1997, 1998 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: haldrv.cpp
  6. * Content: Direct3D HAL Driver
  7. *
  8. ***************************************************************************/
  9. #include "pch.cpp"
  10. #pragma hdrstop
  11. #include "commdrv.hpp"
  12. #include "genpick.hpp"
  13. #include "d3dfei.h"
  14. #include "span.h"
  15. #ifndef WIN95
  16. #include <ntgdistr.h>
  17. #endif
  18. void Destroy(LPDIRECT3DDEVICEI lpDevI);
  19. //---------------------------------------------------------------------
  20. int
  21. GenGetExtraVerticesNumber( LPDIRECT3DDEVICEI lpDevI )
  22. {
  23. LPD3DHAL_GLOBALDRIVERDATA lpGlob = lpDevI->lpD3DHALGlobalDriverData;
  24. return (int)(lpGlob->dwNumVertices ?
  25. lpGlob->dwNumVertices : D3DHAL_DEFAULT_TL_NUM);
  26. }
  27. //---------------------------------------------------------------------
  28. HRESULT CalcDDSurfInfo(LPDIRECT3DDEVICEI lpDevI, BOOL bUpdateZBufferFields)
  29. {
  30. DDSURFACEDESC ddsd;
  31. HRESULT ddrval;
  32. DWORD dwWidth, dwHeight;
  33. unsigned long m;
  34. int s;
  35. // Get info from the surface
  36. memset(&ddsd, 0, sizeof(DDSURFACEDESC));
  37. ddsd.dwSize = sizeof(DDSURFACEDESC);
  38. ddrval = lpDevI->lpDDSTarget->GetSurfaceDesc(&ddsd);
  39. if (ddrval != DD_OK) {
  40. return ddrval;
  41. }
  42. dwWidth = ddsd.dwWidth;
  43. dwHeight = ddsd.dwHeight;
  44. if ((ddsd.ddpfPixelFormat.dwFlags & (DDPF_PALETTEINDEXED4 | DDPF_PALETTEINDEXED8)) == 0) {
  45. // palettized pixfmts will not have valid RGB Bitmasks, so avoid computing this for them
  46. lpDevI->red_mask = ddsd.ddpfPixelFormat.dwRBitMask;
  47. lpDevI->green_mask = ddsd.ddpfPixelFormat.dwGBitMask;
  48. lpDevI->blue_mask = ddsd.ddpfPixelFormat.dwBBitMask;
  49. if ((lpDevI->red_mask == 0x0) ||
  50. (lpDevI->green_mask == 0x0) ||
  51. (lpDevI->blue_mask == 0x0))
  52. {
  53. D3D_ERR("All the color masks in the Render target's pixel-format must be non-zero");
  54. return DDERR_INVALIDPIXELFORMAT;
  55. }
  56. // these are used by Clear
  57. for (s = 0, m = lpDevI->red_mask; !(m & 1); s++, m >>= 1) ;
  58. lpDevI->red_shift = s;
  59. lpDevI->red_scale = 255 / (lpDevI->red_mask >> s);
  60. for (s = 0, m = lpDevI->green_mask; !(m & 1); s++, m >>= 1) ;
  61. lpDevI->green_shift = s;
  62. lpDevI->green_scale = 255 / (lpDevI->green_mask >> s);
  63. for (s = 0, m = lpDevI->blue_mask; !(m & 1); s++, m >>= 1) ;
  64. lpDevI->blue_shift = s;
  65. lpDevI->blue_scale = 255 / (lpDevI->blue_mask >> s);
  66. DDASSERT(lpDevI->red_scale!=0);
  67. DDASSERT(lpDevI->green_scale!=0);
  68. DDASSERT(lpDevI->blue_scale!=0);
  69. lpDevI->bDDSTargetIsPalettized=FALSE;
  70. } else
  71. lpDevI->bDDSTargetIsPalettized=TRUE;
  72. if (lpDevI->lpDDSZBuffer_DDS4 && bUpdateZBufferFields) {
  73. // Get info from the surface
  74. DDSURFACEDESC2 ddsd2;
  75. memset(&ddsd2, 0, sizeof(ddsd2));
  76. ddsd2.dwSize = sizeof(ddsd2);
  77. ddrval = lpDevI->lpDDSZBuffer_DDS4->GetSurfaceDesc(&ddsd2);
  78. if (ddrval != DD_OK) {
  79. return ddrval;
  80. }
  81. if( ddsd2.ddpfPixelFormat.dwZBitMask!=0x0) {
  82. for (s = 0, m = ddsd2.ddpfPixelFormat.dwZBitMask; !(m & 0x1); s++, m >>= 1) ;
  83. lpDevI->zmask_shift=s;
  84. } else {
  85. lpDevI->zmask_shift=0; // if ZBitMask isn't being set, then Clear2 will never be used,
  86. // so zbuf_shift/stencil_shift wont be needed anyway
  87. }
  88. if( ddsd2.ddpfPixelFormat.dwStencilBitMask!=0x0) {
  89. for (s = 0, m = ddsd2.ddpfPixelFormat.dwStencilBitMask; !(m & 0x1); s++, m >>= 1) ;
  90. lpDevI->stencilmask_shift=s;
  91. } else {
  92. lpDevI->stencilmask_shift=0;
  93. }
  94. }
  95. return D3D_OK;
  96. }
  97. // called by DDRAW
  98. extern "C" HRESULT __stdcall Direct3D_HALCleanUp(LPD3DHAL_CALLBACKS lpD3DHALCallbacks, DWORD dwPID)
  99. {
  100. D3DHAL_CONTEXTDESTROYALLDATA data;
  101. HRESULT ret;
  102. DDASSERT(lpD3DHALCallbacks!=NULL);
  103. if (lpD3DHALCallbacks->ContextDestroyAll==NULL) {
  104. // no cleanup necessary (running on d3d hel)
  105. return D3D_OK;
  106. }
  107. memset(&data, 0, sizeof(D3DHAL_CONTEXTDESTROYALLDATA));
  108. data.dwPID = dwPID;
  109. // I'd prefer to use CALL_HALONLY() to do the locking (to avoid doing it for the SW rasterizers),
  110. // but that requires a pDevI which I can't get to from the caller, which is a ddraw cleanup routine
  111. #ifdef WIN95
  112. _EnterSysLevel(lpWin16Lock);
  113. #endif
  114. ret = (*lpD3DHALCallbacks->ContextDestroyAll)(&data);
  115. #ifdef WIN95
  116. _LeaveSysLevel(lpWin16Lock);
  117. #endif
  118. return ret;
  119. }
  120. // ATTENTION - These two functions should be combined into one as soon
  121. // as ContextCreate has the new private data mechanism built in.
  122. #ifdef WIN95
  123. HRESULT halCreateContext(LPDIRECT3DDEVICEI lpDevI)
  124. {
  125. D3DHAL_CONTEXTCREATEDATA data;
  126. HRESULT ret;
  127. D3D_INFO(6, "in halCreateContext. Creating Context for driver = %08lx", lpDevI);
  128. LIST_INITIALIZE(&lpDevI->bufferHandles);
  129. memset(&data, 0, sizeof(D3DHAL_CONTEXTCREATEDATA));
  130. //
  131. // From DX7 onwards, drivers should be accepting
  132. // Surface Locals instead of the Surface interfaces
  133. // this future-proofs the drivers
  134. //
  135. if (IS_DX7HAL_DEVICE(lpDevI))
  136. {
  137. if (lpDevI->lpDD)
  138. data.lpDDLcl = ((LPDDRAWI_DIRECTDRAW_INT)(lpDevI->lpDD))->lpLcl;
  139. else
  140. data.lpDDLcl = NULL;
  141. if (lpDevI->lpDDSTarget)
  142. data.lpDDSLcl = ((LPDDRAWI_DDRAWSURFACE_INT)lpDevI->lpDDSTarget)->lpLcl;
  143. else
  144. data.lpDDSLcl = NULL;
  145. if (lpDevI->lpDDSZBuffer)
  146. data.lpDDSZLcl = ((LPDDRAWI_DDRAWSURFACE_INT)lpDevI->lpDDSZBuffer)->lpLcl;
  147. else
  148. data.lpDDSZLcl = NULL;
  149. }
  150. else
  151. {
  152. data.lpDDGbl = lpDevI->lpDDGbl;
  153. data.lpDDS = lpDevI->lpDDSTarget;
  154. data.lpDDSZ = lpDevI->lpDDSZBuffer;
  155. }
  156. data.dwPID = GetCurrentProcessId();
  157. if (lpDevI->d3dHWDevDesc.dwFlags == 0)
  158. {
  159. // The new software rasterizers want to share IM's state vector so
  160. // we need to pass them the rstates pointer. They don't
  161. // care about dwPID so stick the pointer in there.
  162. data.dwPID = (DWORD)lpDevI->rstates;
  163. }
  164. /* 0 for pre-DX5 devices.
  165. * 1 for DX5 devices.
  166. * 2 for DX6 devices.
  167. */
  168. data.dwhContext = lpDevI->dwVersion - 1;
  169. CALL_HALONLY(ret, lpDevI, ContextCreate, &data);
  170. if (ret != DDHAL_DRIVER_HANDLED || data.ddrval != DD_OK) {
  171. D3D_ERR("HAL context create failed");
  172. return (DDERR_GENERIC);
  173. }
  174. lpDevI->dwhContext = data.dwhContext;
  175. if (D3DMalloc ((void**)&lpDevI->lpwDPBufferAlloced,
  176. max(dwD3DTriBatchSize*4*sizeof(WORD),
  177. dwHWBufferSize) +32) != DD_OK)
  178. {
  179. D3D_ERR( "Out of memory in DeviceCreate" );
  180. return (DDERR_OUTOFMEMORY);
  181. }
  182. lpDevI->lpwDPBuffer =
  183. (LPWORD) (((DWORD) lpDevI->lpwDPBufferAlloced+31) & (~31));
  184. lpDevI->lpDPPrimCounts =
  185. (LPD3DHAL_DRAWPRIMCOUNTS) lpDevI->lpwDPBuffer;
  186. memset( (char *)lpDevI->lpwDPBuffer, 0,
  187. sizeof(D3DHAL_DRAWPRIMCOUNTS)); //Clear header also
  188. lpDevI->dwDPOffset = sizeof(D3DHAL_DRAWPRIMCOUNTS);
  189. lpDevI->dwDPMaxOffset = dwD3DTriBatchSize * sizeof(D3DTRIANGLE)-sizeof(D3DTLVERTEX);
  190. // save the surface handle for later checks
  191. lpDevI->hSurfaceTarget = ((LPDDRAWI_DDRAWSURFACE_INT)lpDevI->lpDDSTarget)->lpLcl->lpSurfMore->dwSurfaceHandle;
  192. D3D_INFO(6, "in halCreateContext. Succeeded. dwhContext = %d", data.dwhContext);
  193. return (D3D_OK);
  194. }
  195. #else
  196. /*
  197. * On NT the kernel code creates the buffer to be used
  198. * for DrawPrim batching and returns it as extra data
  199. * in the ContextCreate request.
  200. */
  201. HRESULT halCreateContext(LPDIRECT3DDEVICEI lpDevI)
  202. {
  203. D3DNTHAL_CONTEXTCREATEI ntData;
  204. D3DHAL_CONTEXTCREATEDATA *lpData =
  205. (D3DHAL_CONTEXTCREATEDATA *)&ntData;
  206. HRESULT ret;
  207. D3D_INFO(6, "in halCreateContext. Creating Context for driver = %08lx", lpDevI);
  208. LIST_INITIALIZE(&lpDevI->bufferHandles);
  209. /*
  210. * AnanKan: Assert here that the D3DNTHAL_CONTEXTCREATEI structure is
  211. * 2 DWORDS bigger than D3DHAL_CONTEXTCREATEDATA. This will be a good
  212. * consistency check for NT kernel updates.
  213. */
  214. memset(&ntData, 0, sizeof(ntData));
  215. if (lpDevI->dwFEFlags & D3DFE_REALHAL)
  216. {
  217. if (lpDevI->lpDD)
  218. lpData->lpDDLcl = ((LPDDRAWI_DIRECTDRAW_INT)(lpDevI->lpDD))->lpLcl;
  219. else
  220. lpData->lpDDLcl = NULL;
  221. if (lpDevI->lpDDSTarget)
  222. lpData->lpDDSLcl = ((LPDDRAWI_DDRAWSURFACE_INT)lpDevI->lpDDSTarget)->lpLcl;
  223. else
  224. lpData->lpDDSLcl = NULL;
  225. if (lpDevI->lpDDSZBuffer)
  226. lpData->lpDDSZLcl = ((LPDDRAWI_DDRAWSURFACE_INT)lpDevI->lpDDSZBuffer)->lpLcl;
  227. else
  228. lpData->lpDDSZLcl = NULL;
  229. }
  230. else
  231. {
  232. lpData->lpDDGbl = lpDevI->lpDDGbl;
  233. lpData->lpDDS = lpDevI->lpDDSTarget;
  234. lpData->lpDDSZ = lpDevI->lpDDSZBuffer;
  235. }
  236. lpData->dwPID = GetCurrentProcessId();
  237. if (lpDevI->d3dHWDevDesc.dwFlags == 0)
  238. {
  239. // The new software rasterizers want to share IM's state vector so
  240. // we need to pass them the rstates pointer. They don't
  241. // care about dwPID so stick the pointer in there.
  242. // Sundown: was lpData->dwPID, but added a union in d3dhal.h
  243. lpData->dwrstates = (ULONG_PTR)lpDevI->rstates;
  244. }
  245. /* 0 for pre-DX5 devices.
  246. * 1 for DX5 devices.
  247. * 2 for DX6 devices.
  248. */
  249. lpData->dwhContext = lpDevI->dwVersion - 1;
  250. ntData.cjBuffer = lpDevI->dwDPBufferSize;
  251. ntData.pvBuffer = NULL;
  252. CALL_HALONLY(ret, lpDevI, ContextCreate, lpData);
  253. if (ret != DDHAL_DRIVER_HANDLED || lpData->ddrval != DD_OK) {
  254. D3D_ERR("HAL context create failed");
  255. return (DDERR_GENERIC);
  256. }
  257. lpDevI->dwhContext = lpData->dwhContext;
  258. // If the lpDevI chose not to allocate a DrawPrim buffer do
  259. // it for them.
  260. if (ntData.pvBuffer == NULL)
  261. {
  262. lpDevI->dwDPBufferSize =
  263. dwD3DTriBatchSize * 4 * sizeof(WORD);
  264. if (lpDevI->dwDPBufferSize < dwHWBufferSize)
  265. {
  266. lpDevI->dwDPBufferSize = dwHWBufferSize;
  267. }
  268. ret = D3DMalloc((void**)&lpDevI->lpwDPBufferAlloced,
  269. lpDevI->dwDPBufferSize + 32);
  270. if (ret != DD_OK)
  271. {
  272. D3D_ERR("halCreateContext D3DMalloc");
  273. return ret;
  274. }
  275. ntData.pvBuffer = (LPVOID)
  276. (((ULONG_PTR)lpDevI->lpwDPBufferAlloced + 31) & ~31);
  277. ntData.cjBuffer = lpDevI->dwDPBufferSize + 32 -
  278. (DWORD)((ULONG_PTR)ntData.pvBuffer -
  279. (ULONG_PTR)lpDevI->lpwDPBufferAlloced);
  280. }
  281. else if( (lpDevI->dwDPBufferSize &&
  282. ntData.cjBuffer < lpDevI->dwDPBufferSize) ||
  283. ntData.cjBuffer < sizeof(D3DHAL_DRAWPRIMCOUNTS) )
  284. {
  285. D3D_ERR("halCreateContext buffer stuff");
  286. return (DDERR_GENERIC);
  287. }
  288. // Need to save the buffer space provided and its size
  289. lpDevI->lpwDPBuffer = (LPWORD)ntData.pvBuffer;
  290. lpDevI->lpDPPrimCounts =
  291. (LPD3DHAL_DRAWPRIMCOUNTS)ntData.pvBuffer;
  292. //Clear header also
  293. memset( (char *)ntData.pvBuffer, 0, sizeof(D3DHAL_DRAWPRIMCOUNTS));
  294. lpDevI->dwDPOffset = sizeof(D3DHAL_DRAWPRIMCOUNTS);
  295. lpDevI->dwDPMaxOffset = ntData.cjBuffer-sizeof(D3DTLVERTEX);
  296. // save the surface handle for later checks
  297. lpDevI->hSurfaceTarget = ((LPDDRAWI_DDRAWSURFACE_INT)lpDevI->lpDDSTarget)->lpLcl->hDDSurface;
  298. D3D_INFO(6, "in halCreateContext. Succeeded. dwhContext = %d", lpData->dwhContext);
  299. return (D3D_OK);
  300. }
  301. #endif
  302. void halDestroyContext(LPDIRECT3DDEVICEI lpDevI)
  303. {
  304. D3DHAL_CONTEXTDESTROYDATA data;
  305. HRESULT ret;
  306. D3D_INFO(6, "in halCreateDestroy. Destroying Context for driver = %08lx", lpDevI);
  307. D3D_INFO(6, " dwhContext = %d", lpDevI->dwhContext);
  308. if(lpDevI->dwhContext!=NULL) {
  309. memset(&data, 0, sizeof(D3DHAL_CONTEXTDESTROYDATA));
  310. data.dwhContext = lpDevI->dwhContext;
  311. CALL_HALONLY(ret, lpDevI, ContextDestroy, &data);
  312. if (ret != DDHAL_DRIVER_HANDLED || data.ddrval != DD_OK) {
  313. D3D_WARN(0,"Failed ContextDestroy HAL call in halDestroyContext");
  314. return;
  315. }
  316. }
  317. D3DHAL_DeallocateBuffers(lpDevI);
  318. }
  319. //---------------------------------------------------------------------
  320. HRESULT D3DFE_Create(LPDIRECT3DDEVICEI lpDevI,
  321. LPDIRECTDRAW lpDD,
  322. LPDIRECTDRAWSURFACE lpDDS,
  323. LPDIRECTDRAWSURFACE lpZ,
  324. LPDIRECTDRAWPALETTE lpPal)
  325. {
  326. DDSURFACEDESC ddsd;
  327. HRESULT hr;
  328. LPD3DHAL_GLOBALDRIVERDATA lpGlob;
  329. /*
  330. * Allocate and check validity of DirectDraw surfaces
  331. */
  332. lpDevI->lpDD = lpDD;
  333. lpDevI->lpDDGbl = ((LPDDRAWI_DIRECTDRAW_INT)lpDD)->lpLcl->lpGbl;
  334. lpDevI->lpDDSTarget = lpDDS;
  335. // For DX3 we do not keep references to Render target to avoid
  336. // circular references in the aggregation model. But for DX5 we
  337. // need to AddRef lpDDS. For DX6 we need to AddRef lpDDS4 which
  338. // is done later below
  339. if (lpDevI->dwVersion == 2) // DX5
  340. lpDDS->AddRef();
  341. // Get DDS4 Interfaces for RenderTarget/ZBuffer
  342. HRESULT ret = lpDDS->QueryInterface(IID_IDirectDrawSurface4, (LPVOID*)&lpDevI->lpDDSTarget_DDS4);
  343. if(FAILED(ret)) {
  344. D3D_ERR("QI for RenderTarget DDS4 Interface failed ");
  345. return ret;
  346. }
  347. // An implicit AddRef for lpDDSTarget_DDS4 in case of DX6
  348. if (lpDevI->dwVersion < 3) // DX3, DX5
  349. lpDevI->lpDDSTarget_DDS4->Release();
  350. if(lpZ!=NULL) {
  351. ret = lpZ->QueryInterface(IID_IDirectDrawSurface4, (LPVOID*)&lpDevI->lpDDSZBuffer_DDS4);
  352. if(FAILED(ret)) {
  353. D3D_ERR("QI for ZBuffer DDS4 Interface failed ");
  354. return ret;
  355. }
  356. lpDevI->lpDDSZBuffer_DDS4->Release();
  357. }
  358. LPD3DHAL_D3DEXTENDEDCAPS lpCaps = lpDevI->lpD3DExtendedCaps;
  359. if (NULL == lpCaps || 0.0f == lpCaps->dvExtentsAdjust)
  360. {
  361. lpDevI->dvExtentsAdjust = 1.0f;
  362. }
  363. else
  364. {
  365. lpDevI->dvExtentsAdjust = lpCaps->dvExtentsAdjust;
  366. }
  367. if (lpCaps != NULL)
  368. if (lpCaps->dvGuardBandLeft != 0.0f ||
  369. lpCaps->dvGuardBandRight != 0.0f ||
  370. lpCaps->dvGuardBandTop != 0.0f ||
  371. lpCaps->dvGuardBandBottom != 0.0f)
  372. {
  373. lpDevI->dwDeviceFlags |= D3DDEV_GUARDBAND;
  374. DWORD v;
  375. if (GetD3DRegValue(REG_DWORD, "DisableGB", &v, 4) &&
  376. v != 0)
  377. {
  378. lpDevI->dwDeviceFlags &= ~D3DDEV_GUARDBAND;
  379. }
  380. #if DBG
  381. // Try to get test values for the guard band
  382. char value[80];
  383. if (GetD3DRegValue(REG_SZ, "GuardBandLeft", &value, 80) &&
  384. value[0] != 0)
  385. sscanf(value, "%f", &lpCaps->dvGuardBandLeft);
  386. if (GetD3DRegValue(REG_SZ, "GuardBandRight", &value, 80) &&
  387. value[0] != 0)
  388. sscanf(value, "%f", &lpCaps->dvGuardBandRight);
  389. if (GetD3DRegValue(REG_SZ, "GuardBandTop", &value, 80) &&
  390. value[0] != 0)
  391. sscanf(value, "%f", &lpCaps->dvGuardBandTop);
  392. if (GetD3DRegValue(REG_SZ, "GuardBandBottom", &value, 80) &&
  393. value[0] != 0)
  394. sscanf(value, "%f", &lpCaps->dvGuardBandBottom);
  395. #endif // DBG
  396. }
  397. if (lpDevI->dwVersion < 2)
  398. lpDevI->dwDeviceFlags |= D3DDEV_PREDX5DEVICE;
  399. if (lpDevI->dwVersion < 3)
  400. lpDevI->dwDeviceFlags |= D3DDEV_PREDX6DEVICE;
  401. if (!lpDevI->lpD3DHALCallbacks || ! lpDevI->lpD3DHALGlobalDriverData)
  402. {
  403. D3D_ERR("CB NULL or GBD NULL %x %x",lpDevI->lpD3DHALGlobalDriverData,lpDevI->lpD3DHALCallbacks);
  404. return DDERR_INVALIDOBJECT;
  405. }
  406. // Helpful Note: for Device2 and Device3, lpDevI->guid is only guaranteed to be
  407. // the device type (HAL/RGB/etc) while init is happening. At end of DX5/DX6 CreateDevice,
  408. // guid is reset to be IID_IDirect3DDevice2 or IID_IDirect3DDevice3, so don't try this sort
  409. // of device type determination outside of initialization.
  410. if (IsEqualIID((lpDevI->guid), IID_IDirect3DHALDevice))
  411. {
  412. lpDevI->dwFEFlags |= D3DFE_REALHAL;
  413. // We do texture management (and hence clipped Blts) only for a real HAL.
  414. hr = lpDD->CreateClipper(0, &lpDevI->lpClipper, NULL);
  415. if(hr != DD_OK)
  416. {
  417. D3D_ERR("Failed to create a clipper");
  418. return hr;
  419. }
  420. }
  421. else
  422. {
  423. lpDevI->lpClipper = 0;
  424. }
  425. if (lpDevI->pfnRampService != NULL)
  426. lpDevI->dwDeviceFlags |= D3DDEV_RAMP;
  427. lpGlob = lpDevI->lpD3DHALGlobalDriverData;
  428. memset(&ddsd, 0, sizeof(DDSURFACEDESC));
  429. ddsd.dwSize = sizeof(DDSURFACEDESC);
  430. if (lpZ)
  431. {
  432. if ((hr = lpZ->GetSurfaceDesc(&ddsd)) != DD_OK)
  433. {
  434. D3D_ERR("Failed to getsurfacedesc on z");
  435. return hr;
  436. }
  437. if (ddsd.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)
  438. {
  439. D3D_INFO(1, "Z buffer is in system memory.");
  440. }
  441. else if (ddsd.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)
  442. {
  443. D3D_INFO(1, "Z buffer is in video memory.");
  444. }
  445. else
  446. {
  447. D3D_ERR("Z buffer not in video or system?");
  448. }
  449. }
  450. memset(&ddsd, 0, sizeof(DDSURFACEDESC));
  451. ddsd.dwSize = sizeof(DDSURFACEDESC);
  452. if (lpDDS)
  453. {
  454. if ((hr = lpDDS->GetSurfaceDesc(&ddsd)) != DD_OK)
  455. {
  456. D3D_ERR("Failed to getsurfacedesc on back buffer");
  457. return hr;
  458. }
  459. if (ddsd.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)
  460. {
  461. D3D_INFO(1, "back buffer is in system memory.");
  462. }
  463. else if (ddsd.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)
  464. {
  465. D3D_INFO(1, "back buffer is in video memory.");
  466. }
  467. else
  468. {
  469. D3D_ERR("back buffer not in video or system?");
  470. }
  471. if (!(lpGlob->hwCaps.dwDeviceRenderBitDepth &
  472. BitDepthToDDBD(ddsd.ddpfPixelFormat.dwRGBBitCount)))
  473. {
  474. D3D_ERR("Rendering surface's RGB bit count not supported "
  475. "by hardware device");
  476. return DDERR_INVALIDOBJECT;
  477. }
  478. }
  479. if (lpGlob->dwNumVertices &&
  480. (lpGlob->hwCaps.dwMaxVertexCount != lpGlob->dwNumVertices))
  481. {
  482. D3D_ERR("In global driver data, hwCaps.dwMaxVertexCount != "
  483. "dwNumVertices");
  484. lpGlob->hwCaps.dwMaxVertexCount = lpGlob->dwNumVertices;
  485. }
  486. if (lpGlob->dwNumVertices
  487. && lpGlob->dwNumClipVertices < D3DHAL_NUMCLIPVERTICES)
  488. {
  489. D3D_ERR("In global driver data, dwNumClipVertices "
  490. "< D3DHAL_NUMCLIPVERTICES");
  491. lpGlob->dwNumClipVertices = D3DHAL_NUMCLIPVERTICES;
  492. }
  493. if ((hr = CalcDDSurfInfo(lpDevI,TRUE)) != DD_OK)
  494. {
  495. D3D_ERR("CalcDDSurfInfo failed");
  496. return hr;
  497. }
  498. RESET_HAL_CALLS(lpDevI);
  499. /*
  500. * Create our context in the HAL driver
  501. */
  502. if ((hr = halCreateContext(lpDevI)) != D3D_OK)
  503. {
  504. D3D_ERR("halCreateContext failed");
  505. return hr;
  506. }
  507. STATESET_INIT(lpDevI->renderstate_overrides);
  508. if ((hr = D3DFE_InitTransform(lpDevI)) != D3D_OK)
  509. {
  510. D3D_ERR("D3DFE_InitTransform failed");
  511. return hr;
  512. }
  513. if (hr = (D3DFE_InitRGBLighting(lpDevI)) != D3D_OK)
  514. {
  515. D3D_ERR("D3DFE_InitRGBLighting failed");
  516. return hr;
  517. }
  518. lpDevI->dwFEFlags |= D3DFE_VALID;
  519. lpDevI->iClipStatus = D3DSTATUS_DEFAULT;
  520. lpDevI->rExtents.x1 = D3DVAL(2048);
  521. lpDevI->rExtents.x2 = D3DVAL(0);
  522. lpDevI->rExtents.y1 = D3DVAL(2048);
  523. lpDevI->rExtents.y2 = D3DVAL(0);
  524. return S_OK;
  525. }
  526. void D3DFE_Destroy(LPDIRECT3DDEVICEI lpDevI)
  527. {
  528. if (lpDevI->dwFEFlags & D3DFE_VALID)
  529. {
  530. D3DFE_DestroyTransform(lpDevI);
  531. D3DFE_DestroyRGBLighting(lpDevI);
  532. }
  533. if(lpDevI->lpClipper)
  534. {
  535. lpDevI->lpClipper->Release();
  536. }
  537. if (lpDevI->lpD3DHALCallbacks) {
  538. halDestroyContext(lpDevI);
  539. }
  540. #ifdef TRACK_HAL_CALLS
  541. D3D_INFO(0, "Made %d HAL calls", lpDevI->hal_calls);
  542. #endif
  543. // If any picks were done the pick records need to be freed.
  544. // They are allocated in D3DHAL_AddPickRecord in halpick.c
  545. if (lpDevI->pick_data.records) {
  546. D3DFree(lpDevI->pick_data.records);
  547. }
  548. }
  549. void TriFillRectsTex(LPDIRECT3DDEVICEI lpDevI, DWORD count, LPD3DRECT rect,D3DTEXTUREHANDLE hTex)
  550. {
  551. LPDIRECT3DDEVICE3 lpD3DDev = static_cast<LPDIRECT3DDEVICE3>(lpDevI);
  552. LPD3DVIEWPORT2 lpCurrentView = &((LPDIRECT3DVIEWPORTI)(lpDevI->lpCurrentViewport))->v_data;
  553. DWORD i;
  554. float width = (float)lpCurrentView->dwWidth;
  555. float height = (float)lpCurrentView->dwHeight;
  556. // ~.5 offset makes the result stable for even scales which are common.
  557. // since this offset is not scaled by texture size, need to make it a bit smaller
  558. float x = (float)lpCurrentView->dwX - .41f;
  559. float y = (float)lpCurrentView->dwY - .41f;
  560. DWORD dwZEnable;
  561. DWORD dwStencilEnable;
  562. DWORD dwZWriteEnable;
  563. DWORD dwZFunc;
  564. DWORD dwWrapU;
  565. DWORD dwWrapV;
  566. DWORD dwFillMode;
  567. DWORD dwFogEnable;
  568. DWORD dwFogMode;
  569. DWORD dwBlendEnable;
  570. DWORD dwColorKeyEnable;
  571. DWORD dwAlphaBlendEnable;
  572. DWORD dwTexture;
  573. DWORD dwTexturePers;
  574. DWORD dwDither;
  575. DWORD pdwWrap[D3DDP_MAXTEXCOORD];
  576. D3DTLVERTEX v[4];
  577. BOOL bWasInScene = FALSE;
  578. D3DMATERIALHANDLE hMat;
  579. if (!(lpDevI->dwHintFlags & D3DDEVBOOL_HINTFLAGS_INSCENE))
  580. {
  581. lpDevI->dwHintFlags |= D3DDEVBOOL_HINTFLAGS_INTERNAL_BEGIN_END;
  582. bWasInScene = TRUE;
  583. lpD3DDev->BeginScene();
  584. }
  585. // save current renderstate we need to reset to draw textured rect
  586. lpD3DDev->GetRenderState(D3DRENDERSTATE_ZENABLE, &dwZEnable);
  587. lpD3DDev->GetRenderState(D3DRENDERSTATE_ZWRITEENABLE, &dwZWriteEnable);
  588. lpD3DDev->GetRenderState(D3DRENDERSTATE_ZFUNC, &dwZFunc);
  589. lpD3DDev->GetRenderState(D3DRENDERSTATE_WRAPU, &dwWrapU);
  590. lpD3DDev->GetRenderState(D3DRENDERSTATE_WRAPV, &dwWrapV);
  591. lpD3DDev->GetRenderState(D3DRENDERSTATE_FILLMODE, &dwFillMode);
  592. lpD3DDev->GetRenderState(D3DRENDERSTATE_FOGENABLE, &dwFogEnable);
  593. lpD3DDev->GetRenderState(D3DRENDERSTATE_FOGTABLEMODE, &dwFogMode);
  594. lpD3DDev->GetRenderState(D3DRENDERSTATE_BLENDENABLE, &dwBlendEnable);
  595. lpD3DDev->GetRenderState(D3DRENDERSTATE_COLORKEYENABLE, &dwColorKeyEnable);
  596. lpD3DDev->GetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, &dwAlphaBlendEnable);
  597. lpD3DDev->GetRenderState(D3DRENDERSTATE_TEXTUREHANDLE, &dwTexture);
  598. lpD3DDev->GetRenderState(D3DRENDERSTATE_STENCILENABLE, &dwStencilEnable);
  599. lpD3DDev->GetRenderState(D3DRENDERSTATE_TEXTUREPERSPECTIVE, &dwTexturePers);
  600. lpD3DDev->GetRenderState(D3DRENDERSTATE_DITHERENABLE, &dwDither);
  601. // Save WRAPi
  602. for (i = 0; i < D3DDP_MAXTEXCOORD; i++)
  603. {
  604. lpD3DDev->GetRenderState((D3DRENDERSTATETYPE)(D3DRENDERSTATE_WRAP0 + i),
  605. pdwWrap + i);
  606. }
  607. lpD3DDev->SetRenderState(D3DRENDERSTATE_ZENABLE, FALSE);
  608. lpD3DDev->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, FALSE);
  609. lpD3DDev->SetRenderState(D3DRENDERSTATE_ZFUNC, D3DCMP_ALWAYS);
  610. lpD3DDev->SetRenderState(D3DRENDERSTATE_WRAPU, FALSE);
  611. lpD3DDev->SetRenderState(D3DRENDERSTATE_WRAPV, FALSE);
  612. lpD3DDev->SetRenderState(D3DRENDERSTATE_FILLMODE, D3DFILL_SOLID);
  613. lpD3DDev->SetRenderState(D3DRENDERSTATE_FOGTABLEMODE, D3DFOG_NONE);
  614. lpD3DDev->SetRenderState(D3DRENDERSTATE_FOGENABLE, FALSE);
  615. lpD3DDev->SetRenderState(D3DRENDERSTATE_BLENDENABLE, FALSE);
  616. lpD3DDev->SetRenderState(D3DRENDERSTATE_COLORKEYENABLE, FALSE);
  617. lpD3DDev->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, FALSE);
  618. lpD3DDev->SetRenderState(D3DRENDERSTATE_TEXTUREHANDLE, hTex);
  619. lpD3DDev->SetRenderState(D3DRENDERSTATE_STENCILENABLE, FALSE);
  620. lpD3DDev->SetRenderState(D3DRENDERSTATE_TEXTUREPERSPECTIVE, FALSE);
  621. lpD3DDev->SetRenderState(D3DRENDERSTATE_DITHERENABLE, FALSE);
  622. // Disable WRAPi
  623. for (i = 0; i < D3DDP_MAXTEXCOORD; i++)
  624. {
  625. lpD3DDev->SetRenderState((D3DRENDERSTATETYPE)(D3DRENDERSTATE_WRAP0 + i),
  626. 0);
  627. }
  628. BOOL bRampServiceClear = FALSE;
  629. if(lpDevI->pfnRampService!=NULL) {
  630. lpD3DDev->GetLightState(D3DLIGHTSTATE_MATERIAL, &hMat);
  631. lpD3DDev->SetLightState(D3DLIGHTSTATE_MATERIAL,
  632. lpDevI->lpCurrentViewport->hBackgndMat);
  633. PD3DI_SPANTEX pTex = *(PD3DI_SPANTEX *)ULongToPtr(hTex);
  634. if (pTex->Format == D3DI_SPTFMT_PALETTE8)
  635. {
  636. // if it is Ramp, and if the texture is PALETTE8,
  637. // then we should use the new service that handles
  638. // non-power of 2 textures
  639. bRampServiceClear = TRUE;
  640. }
  641. }
  642. if (bRampServiceClear)
  643. {
  644. for (i = 0; i < count; i++, rect++) {
  645. CallRampService(lpDevI, RAMP_SERVICE_CLEAR_TEX_RECT,
  646. lpDevI->lpCurrentViewport->hBackgndMat,rect);
  647. }
  648. }
  649. else
  650. {
  651. for (i = 0; i < count; i++, rect++) {
  652. D3DVALUE tu1, tv1, tu2, tv2;
  653. tu1 = ((D3DVALUE)(rect->x1 - x))/width;
  654. tv1 = ((D3DVALUE)(rect->y1 - y))/height;
  655. tu2 = ((D3DVALUE)(rect->x2 - x))/width;
  656. tv2 = ((D3DVALUE)(rect->y2 - y))/height;
  657. v[0].sx = (D3DVALUE) rect->x1;
  658. v[0].sy = (D3DVALUE) rect->y1;
  659. v[0].sz = (D3DVALUE) 0;
  660. v[0].rhw = (D3DVALUE) 1;
  661. v[0].color = (D3DCOLOR) ~0UL;
  662. v[0].specular = (D3DCOLOR) 0;
  663. v[0].tu = tu1;
  664. v[0].tv = tv1;
  665. v[1].sx = (D3DVALUE) rect->x2;
  666. v[1].sy = (D3DVALUE) rect->y1;
  667. v[1].sz = (D3DVALUE) 0;
  668. v[1].rhw = (D3DVALUE) 1;
  669. v[1].color = (D3DCOLOR) ~0UL;
  670. v[1].specular = (D3DCOLOR) 0;
  671. v[1].tu = tu2;
  672. v[1].tv = tv1;
  673. v[2].sx = (D3DVALUE) rect->x2;
  674. v[2].sy = (D3DVALUE) rect->y2;
  675. v[2].sz = (D3DVALUE) 0;
  676. v[2].rhw = (D3DVALUE) 1;
  677. v[2].color = (D3DCOLOR) ~0UL;
  678. v[2].specular = (D3DCOLOR) 0;
  679. v[2].tu = tu2;
  680. v[2].tv = tv2;
  681. v[3].sx = (D3DVALUE) rect->x1;
  682. v[3].sy = (D3DVALUE) rect->y2;
  683. v[3].sz = (D3DVALUE) 0;
  684. v[3].rhw = (D3DVALUE) 1;
  685. v[3].color = (D3DCOLOR) ~0UL;
  686. v[3].specular = (D3DCOLOR) 0;
  687. v[3].tu = tu1;
  688. v[3].tv = tv2;
  689. lpD3DDev->DrawPrimitive(D3DPT_TRIANGLEFAN,
  690. D3DFVF_TLVERTEX, v, 4,
  691. D3DDP_WAIT | D3DDP_DONOTCLIP);
  692. }
  693. }
  694. // restore saved renderstate
  695. lpD3DDev->SetRenderState(D3DRENDERSTATE_ZENABLE, dwZEnable);
  696. lpD3DDev->SetRenderState(D3DRENDERSTATE_ZWRITEENABLE, dwZWriteEnable);
  697. lpD3DDev->SetRenderState(D3DRENDERSTATE_ZFUNC, dwZFunc);
  698. lpD3DDev->SetRenderState(D3DRENDERSTATE_WRAPU, dwWrapU);
  699. lpD3DDev->SetRenderState(D3DRENDERSTATE_WRAPV, dwWrapV);
  700. lpD3DDev->SetRenderState(D3DRENDERSTATE_FILLMODE, dwFillMode);
  701. lpD3DDev->SetRenderState(D3DRENDERSTATE_FOGENABLE, dwFogEnable);
  702. lpD3DDev->SetRenderState(D3DRENDERSTATE_FOGTABLEMODE, dwFogMode);
  703. lpD3DDev->SetRenderState(D3DRENDERSTATE_BLENDENABLE, dwBlendEnable);
  704. lpD3DDev->SetRenderState(D3DRENDERSTATE_COLORKEYENABLE, dwColorKeyEnable);
  705. lpD3DDev->SetRenderState(D3DRENDERSTATE_ALPHABLENDENABLE, dwAlphaBlendEnable);
  706. lpD3DDev->SetRenderState(D3DRENDERSTATE_TEXTUREHANDLE, dwTexture);
  707. lpD3DDev->SetRenderState(D3DRENDERSTATE_STENCILENABLE, dwStencilEnable);
  708. lpD3DDev->SetRenderState(D3DRENDERSTATE_TEXTUREPERSPECTIVE, dwTexturePers);
  709. lpD3DDev->SetRenderState(D3DRENDERSTATE_DITHERENABLE, dwDither);
  710. // Restore WRAPi
  711. for (i = 0; i < D3DDP_MAXTEXCOORD; i++)
  712. {
  713. lpD3DDev->SetRenderState((D3DRENDERSTATETYPE)(D3DRENDERSTATE_WRAP0 + i),
  714. pdwWrap[i]);
  715. }
  716. if(lpDevI->pfnRampService!=NULL) {
  717. lpD3DDev->SetLightState(D3DLIGHTSTATE_MATERIAL, hMat);
  718. }
  719. if (bWasInScene)
  720. {
  721. lpD3DDev->EndScene();
  722. lpDevI->dwHintFlags &= ~D3DDEVBOOL_HINTFLAGS_INTERNAL_BEGIN_END;
  723. }
  724. }
  725. void BltFillRects(LPDIRECT3DDEVICEI lpDevI, DWORD count, LPD3DRECT rect, D3DCOLORVALUE *pFillColor)
  726. {
  727. LPDIRECTDRAWSURFACE lpDDS = lpDevI->lpDDSTarget;
  728. HRESULT ddrval;
  729. DDBLTFX bltfx;
  730. RECT tr;
  731. DWORD i;
  732. DWORD r, g, b;
  733. // Fill with background color
  734. memset(&bltfx, 0, sizeof(bltfx));
  735. bltfx.dwSize = sizeof(bltfx);
  736. // unlike clear callback, which just takes pure 32-bit ARGB word and forces the driver to scale it for
  737. // the pixelformat, here we need to compute the exact fill word, depending on surface's R,G,B bitmasks
  738. if(lpDevI->pfnRampService!=NULL) {
  739. // DX5 allowed the background material to be NULL. For this case, will clear to index 0
  740. // which is usually black in ramp mode
  741. if(lpDevI->lpCurrentViewport->hBackgndMat!=0) {
  742. CallRampService(lpDevI, RAMP_SERVICE_MATERIAL_TO_PIXEL,lpDevI->lpCurrentViewport->hBackgndMat,&bltfx.dwFillColor);
  743. } else {
  744. bltfx.dwFillColor=0; // index 0 is usually black in ramp mode.
  745. }
  746. } else {
  747. if(lpDevI->bDDSTargetIsPalettized) {
  748. // map 24-bit color to 8-bit index used by 8bit RGB rasterizer
  749. CallRastService(lpDevI, RAST_SERVICE_RGB8COLORTOPIXEL, CVAL_TO_RGBA(*pFillColor), &bltfx.dwFillColor);
  750. } else {
  751. if((lpDevI->red_scale == 0) || (lpDevI->green_scale == 0) ||
  752. (lpDevI->blue_scale == 0))
  753. {
  754. DPF(1, "(ERROR) BltFillRects Failed one of the scales is zero" );
  755. return;
  756. }
  757. r = (DWORD)(255.0 * pFillColor->r) / lpDevI->red_scale;
  758. g = (DWORD)(255.0 * pFillColor->g) / lpDevI->green_scale;
  759. b = (DWORD)(255.0 * pFillColor->b) / lpDevI->blue_scale;
  760. bltfx.dwFillColor = (r << lpDevI->red_shift) | (g << lpDevI->green_shift) | (b << lpDevI->blue_shift);
  761. }
  762. }
  763. for (i = 0; i < count; i++,rect++) {
  764. tr.left = rect->x1;
  765. tr.right = rect->x2;
  766. tr.top = rect->y1;
  767. tr.bottom = rect->y2;
  768. do {
  769. ddrval = lpDDS->Blt(&tr, NULL, NULL, DDBLT_COLORFILL, &bltfx);
  770. } while (ddrval == DDERR_WASSTILLDRAWING);
  771. }
  772. }
  773. void BltFillZRects(LPDIRECT3DDEVICEI lpDevI, unsigned long Zpixel,
  774. DWORD count, LPD3DRECT rect, DWORD dwWriteMask)
  775. {
  776. HRESULT ddrval;
  777. DDBLTFX bltfx;
  778. DWORD i;
  779. RECT tr;
  780. DWORD dwExtraFlags=0;
  781. #if DBG
  782. if (lpDevI->lpDDSZBuffer == NULL) // should be checked prior to call
  783. return;
  784. #endif
  785. memset(&bltfx, 0, sizeof(DDBLTFX));
  786. bltfx.dwSize = sizeof(DDBLTFX);
  787. bltfx.dwFillDepth = Zpixel;
  788. // hack to pass DepthBlt WriteMask through ddraw/ddhel to blitlib
  789. if(dwWriteMask!=0) {
  790. bltfx.dwZDestConstBitDepth=dwWriteMask;
  791. dwExtraFlags = DDBLT_DEPTHFILLWRITEMASK;
  792. }
  793. for(i=0;i<count;i++,rect++) {
  794. D3D_INFO(4, "Z Clearing x1 = %d, y1 = %d, x2 = %d, y2 = %d, WriteMask %X", rect->x1, rect->y1, rect->x2, rect->y2, bltfx.dwReserved);
  795. tr.left = rect->x1;
  796. tr.right = rect->x2;
  797. tr.top = rect->y1;
  798. tr.bottom = rect->y2;
  799. do {
  800. ddrval = lpDevI->lpDDSZBuffer->Blt(&tr, NULL, NULL, DDBLT_DEPTHFILL | dwExtraFlags, &bltfx);
  801. } while (ddrval == DDERR_WASSTILLDRAWING);
  802. }
  803. }
  804. #undef DPF_MODNAME
  805. #define DPF_MODNAME "D3DFE_Clear"
  806. HRESULT D3DFE_Clear(LPDIRECT3DDEVICEI lpDevI, DWORD dwFlags,
  807. DWORD numRect, LPD3DRECT lpRect,
  808. D3DCOLORVALUE *pFillColor,
  809. D3DTEXTUREHANDLE dwTexture)
  810. {
  811. HRESULT ret;
  812. BOOL bDoRGBClear,bDoZClear,bDoHALRGBClear,bDoHALZClear;
  813. D3DHAL_CLEARDATA ClearData;
  814. LPDIRECTDRAWSURFACE lpDDSBackDepth;
  815. // Flush any outstanding geometry to put framebuffer/Zbuffer in a known state for Clears that
  816. // don't use tris (i.e. HAL Clears and Blts). Note this doesn't work for tiled architectures
  817. // outside of Begin/EndScene, this will be fixed later
  818. ret = lpDevI->FlushStates();
  819. if (ret != D3D_OK)
  820. {
  821. D3D_ERR("Error trying to render batched commands in D3DFE_Clear");
  822. return ret;
  823. }
  824. ClearData.ddrval=D3D_OK;
  825. bDoRGBClear=((dwFlags & D3DCLEAR_TARGET)!=0); // must convert to pure bool so bDoHALRGBClear==bDoRGBClear works
  826. bDoZClear=((dwFlags & D3DCLEAR_ZBUFFER)!=0);
  827. lpDDSBackDepth=((LPDIRECT3DVIEWPORTI)(lpDevI->lpCurrentViewport))->lpDDSBackgndDepth;
  828. // note: textured clears and clears to background depth buffer must be handled explicitly
  829. // using Blt calls and not be passed to driver
  830. bDoHALRGBClear = bDoRGBClear && (dwTexture==0) && (lpDevI->lpD3DHALCallbacks2->Clear!=NULL);
  831. bDoHALZClear = bDoZClear && (lpDDSBackDepth==NULL) && (lpDevI->lpD3DHALCallbacks2->Clear!=NULL);
  832. if(bDoHALRGBClear || bDoHALZClear) {
  833. ClearData.dwhContext = lpDevI->dwhContext;
  834. ClearData.dwFillColor = ClearData.dwFillDepth = 0;
  835. ClearData.dwFlags = 0x0;
  836. if(bDoHALRGBClear) {
  837. // original Clear DDI Spec had dwFillColor being dependent on the surface RGB bit depths
  838. // like the COLORFILL Blt in SetRectangles. But the dx5 implementation always passed a
  839. // 32-bit ARGB to the driver for all surface depths. So that's the way it stays.
  840. ClearData.dwFillColor = CVAL_TO_RGBA(*pFillColor);
  841. ClearData.dwFlags = D3DCLEAR_TARGET;
  842. }
  843. if(bDoHALZClear) {
  844. // must clear to 0xffffffff because legacy drivers expect this
  845. // should be using (1<<lpDevI->lpDDSZBuffer->ddpfSurface.dwZBufferBitDepth)-1;
  846. ClearData.dwFillDepth = 0xffffffff;
  847. ClearData.dwFlags |= D3DCLEAR_ZBUFFER;
  848. }
  849. ClearData.lpRects = lpRect;
  850. ClearData.dwNumRects = numRect;
  851. #ifndef WIN95
  852. if((ret = CheckContextSurface(lpDevI)) != D3D_OK)
  853. return ret;
  854. #endif
  855. CALL_HAL2ONLY(ret, lpDevI, Clear, &ClearData);
  856. if (ret != DDHAL_DRIVER_HANDLED)
  857. return DDERR_UNSUPPORTED;
  858. // if all requested clears were done by HAL, can return now
  859. if((bDoRGBClear==bDoHALRGBClear) && (bDoZClear==bDoHALZClear))
  860. return ClearData.ddrval;
  861. }
  862. if((lpDevI->lpD3DHALCallbacks3->Clear2!=NULL) && (lpDevI->lpD3DHALCallbacks2->Clear==NULL)) {
  863. DWORD dwFlagsLeft=dwFlags;
  864. DWORD dwClear2Flags=0x0;
  865. // driver implemented Clear2 callback but not Clear
  866. // call Clear2 for as many items as we can, and leave the rest for SW
  867. if(bDoRGBClear && (dwTexture==0)) {
  868. dwClear2Flags |= D3DCLEAR_TARGET;
  869. dwFlagsLeft &= ~D3DCLEAR_TARGET;
  870. bDoRGBClear=FALSE;
  871. }
  872. if(bDoZClear && (lpDDSBackDepth==NULL)) {
  873. dwClear2Flags |= D3DCLEAR_ZBUFFER;
  874. dwFlagsLeft &= ~D3DCLEAR_ZBUFFER;
  875. bDoZClear=FALSE;
  876. }
  877. if(dwClear2Flags!=0x0) {
  878. ClearData.ddrval = D3DFE_Clear2(lpDevI,dwClear2Flags,numRect,lpRect,CVAL_TO_RGBA(*pFillColor),1.0,0);
  879. }
  880. if(dwFlagsLeft==0x0)
  881. return ClearData.ddrval;
  882. dwFlags=dwFlagsLeft;
  883. }
  884. // otherwise do clears using SW, since no HW method exists or using textured background for RGBclear
  885. // or background depth buffer for Zclear
  886. // clear RGB using Blt
  887. if (bDoRGBClear && (!bDoHALRGBClear)) {
  888. if(dwTexture == 0)
  889. BltFillRects(lpDevI, numRect, lpRect, pFillColor);
  890. else TriFillRectsTex(lpDevI, numRect, lpRect, dwTexture);
  891. }
  892. // clear Z using Blt
  893. if (bDoZClear && (!bDoHALZClear)) {
  894. if (lpDDSBackDepth!=NULL) {
  895. RECT src, dest;
  896. DDSURFACEDESC ddsd;
  897. HRESULT ret;
  898. D3D_INFO(2, "Z Clearing using depth background");
  899. ddsd.dwSize = sizeof ddsd;
  900. ddsd.dwFlags = 0;
  901. if (ret = lpDDSBackDepth->GetSurfaceDesc(&ddsd)) {
  902. D3D_ERR("GetSurfaceDesc failed trying to clear to depth background");
  903. return ret;
  904. }
  905. D3D_INFO(3, "Depth background width=%d, height=%d", ddsd.dwWidth, ddsd.dwHeight);
  906. SetRect(&src, 0, 0, ddsd.dwWidth, ddsd.dwHeight);
  907. LPD3DVIEWPORT2 lpCurrentView = &((LPDIRECT3DVIEWPORTI)(lpDevI->lpCurrentViewport))->v_data;
  908. SetRect(&dest,
  909. lpCurrentView->dwX,
  910. lpCurrentView->dwY,
  911. lpCurrentView->dwX + lpCurrentView->dwWidth,
  912. lpCurrentView->dwY + lpCurrentView->dwHeight );
  913. // copy from background depth buffer to zbuffer
  914. if (ret = lpDevI->lpDDSZBuffer->Blt(
  915. &dest, lpDDSBackDepth, &src, DDBLT_WAIT, NULL)) {
  916. D3D_ERR("Blt failed clearing depth background");
  917. return ret;
  918. }
  919. } else {
  920. // Clear to maximum Z value. Presence of stencil buffer ignored, depthfill blt
  921. // can overwrite any existing stencil bits with 1's. Clear2 should be used to
  922. // clear z while preserving stencil buffer
  923. BltFillZRects(lpDevI, 0xffffffff, numRect, lpRect, 0x0);
  924. }
  925. }
  926. if(ClearData.ddrval!=D3D_OK)
  927. return ClearData.ddrval;
  928. else
  929. {
  930. return CallRampService(lpDevI, RAMP_SERVICE_CLEAR, 0, 0);
  931. }
  932. }
  933. #undef DPF_MODNAME
  934. #define DPF_MODNAME "D3DFE_Clear2"
  935. HRESULT D3DFE_Clear2(LPDIRECT3DDEVICEI lpDevI, DWORD dwFlags,
  936. DWORD numRect, LPD3DRECT lpRect,
  937. D3DCOLOR dwColor, D3DVALUE dvZ, DWORD dwStencil) {
  938. DWORD dwDepthClearVal,dwStencilClearVal;
  939. HRESULT ret;
  940. BOOL bDoRGBClear,bDoZClear,bDoStencilClear;
  941. BOOL bIsStencilSurface = FALSE;
  942. D3DHAL_CLEAR2DATA Clear2Data;
  943. DDPIXELFORMAT *pZPixFmt;
  944. D3DCOLORVALUE vFillColor;
  945. DDASSERT(lpDevI->pfnRampService==NULL); // Device3 ramp not allowed, so dont have to handle this case
  946. // Flush any outstanding geometry to put framebuffer/Zbuffer in a known state for Clears that
  947. // don't use tris (i.e. HAL Clears and Blts). Note this doesn't work for tiled architectures
  948. // outside of Begin/EndScene, this will be fixed later
  949. ret = lpDevI->FlushStates();
  950. if (ret != D3D_OK)
  951. {
  952. D3D_ERR("Error trying to render batched commands in D3DFE_Clear2");
  953. return ret;
  954. }
  955. bDoRGBClear=((dwFlags & D3DCLEAR_TARGET)!=0);
  956. bDoZClear=((dwFlags & D3DCLEAR_ZBUFFER)!=0); //make these true boolean so XOR below works
  957. bDoStencilClear=((dwFlags & D3DCLEAR_STENCIL)!=0);
  958. if (lpDevI->lpD3DHALCallbacks3->Clear2)
  959. {
  960. // Clear2 HAL Callback exists
  961. Clear2Data.dwhContext = lpDevI->dwhContext;
  962. Clear2Data.lpRects = lpRect;
  963. Clear2Data.dwNumRects = numRect;
  964. Clear2Data.dwFillColor = Clear2Data.dwFillStencil = 0;
  965. Clear2Data.dvFillDepth = 0.0f;
  966. Clear2Data.dwFlags = dwFlags;
  967. if(bDoRGBClear) {
  968. // Here I will follow the ClearData.dwFillColor convention that
  969. // color word is raw 32bit ARGB, unadjusted for surface bit depth
  970. Clear2Data.dwFillColor = dwColor;
  971. }
  972. // depth/stencil values both passed straight from user args
  973. if(bDoZClear)
  974. Clear2Data.dvFillDepth = dvZ;
  975. if(bDoStencilClear)
  976. Clear2Data.dwFillStencil = dwStencil;
  977. #ifndef WIN95
  978. if((ret = CheckContextSurface(lpDevI)) != D3D_OK)
  979. return ret;
  980. #endif
  981. CALL_HAL3ONLY(ret, lpDevI, Clear2, &Clear2Data);
  982. if (ret != DDHAL_DRIVER_HANDLED)
  983. return DDERR_UNSUPPORTED;
  984. return Clear2Data.ddrval;
  985. }
  986. if(bDoRGBClear) {
  987. const float fScalor=(float)(1.0/255.0);
  988. vFillColor.a = RGBA_GETALPHA(dwColor)*fScalor;
  989. vFillColor.r = RGBA_GETRED(dwColor)*fScalor;
  990. vFillColor.g = RGBA_GETGREEN(dwColor)*fScalor;
  991. vFillColor.b = RGBA_GETBLUE(dwColor)*fScalor;
  992. }
  993. if((bDoZClear || bDoStencilClear) && (lpDevI->lpDDSZBuffer!=NULL)) { //PowerVR need no Zbuffer
  994. pZPixFmt=&((LPDDRAWI_DDRAWSURFACE_INT) lpDevI->lpDDSZBuffer)->lpLcl->lpGbl->ddpfSurface;
  995. // if surface has stencil bits, must verify either Clear2 callback exists or
  996. // we're using SW rasterizers (which require the special WriteMask DDHEL blt)
  997. bIsStencilSurface=(pZPixFmt->dwFlags & DDPF_STENCILBUFFER);
  998. }
  999. if(bDoZClear || bDoStencilClear) {
  1000. // if Clear2 callback doesnt exist and it's a z-only surface and not doing zclear to
  1001. // non-max value then Clear2 is attempting to do no more than Clear could do, so it's
  1002. // safe to call Clear() instead of Clear2(), which will take advantage of older
  1003. // drivers that implement Clear but not Clear2
  1004. if((!bIsStencilSurface) && (!(bDoZClear && (dvZ!=1.0)))) {
  1005. return D3DFE_Clear(lpDevI,dwFlags,numRect,lpRect,&vFillColor,0);
  1006. }
  1007. if(bIsStencilSurface) {
  1008. DDSCAPS *pDDSCaps;
  1009. pDDSCaps=&((LPDDRAWI_DDRAWSURFACE_INT) lpDevI->lpDDSZBuffer)->lpLcl->ddsCaps;
  1010. // This case should not be hit since we check right at the
  1011. // driver initialization time if the driver doesnt report Clear2
  1012. // yet it supports stencils
  1013. if(!(pDDSCaps->dwCaps & DDSCAPS_SYSTEMMEMORY)) {
  1014. D3D_ERR("Driver HAL doesn't provide Clear2 callback, cannot use Clear2 with HW stencil surfaces");
  1015. return DDERR_INVALIDPIXELFORMAT;
  1016. }
  1017. }
  1018. } else {
  1019. // we're just clearing RGB, so since Clear2 callback doesn't exist, try calling Clear
  1020. return D3DFE_Clear(lpDevI,dwFlags,numRect,lpRect,&vFillColor,0);
  1021. }
  1022. dwDepthClearVal=dwStencilClearVal=0;
  1023. if(bDoZClear) {
  1024. LPDDPIXELFORMAT pPixFmt=&((LPDDRAWI_DDRAWSURFACE_INT) lpDevI->lpDDSZBuffer)->lpLcl->lpGbl->ddpfSurface;
  1025. DDASSERT(pPixFmt->dwZBufferBitDepth<=32);
  1026. if((dvZ!=1.0)&&(lpDevI->lpD3DHALCallbacks3->Clear2==NULL)&&(pPixFmt->dwZBitMask==0x0)) {
  1027. // I have no way to emulate ZClears to non-maxZ values without a ZBitMask, so must fail call
  1028. D3D_ERR("cant ZClear to non-maxz value without Clear2 HAL callback or valid ZBuffer pixfmt ZBitMask");
  1029. return DDERR_INVALIDPIXELFORMAT;
  1030. }
  1031. // special case the common cases
  1032. if(dvZ==1.0) {
  1033. dwDepthClearVal=pPixFmt->dwZBitMask;
  1034. } else if(dvZ==0.0) {
  1035. dwDepthClearVal=0;
  1036. } else {
  1037. dwDepthClearVal=((DWORD)((dvZ*(pPixFmt->dwZBitMask >> lpDevI->zmask_shift))+0.5)) << lpDevI->zmask_shift;
  1038. }
  1039. }
  1040. if(bDoStencilClear) {
  1041. LPDDPIXELFORMAT pPixFmt=&((LPDDRAWI_DDRAWSURFACE_INT) lpDevI->lpDDSZBuffer)->lpLcl->lpGbl->ddpfSurface;
  1042. DDASSERT(pPixFmt->dwStencilBitDepth<32);
  1043. DDASSERT(pPixFmt->dwStencilBitMask!=0x0);
  1044. // special case the common case
  1045. if(dwStencil==0) {
  1046. dwStencilClearVal=0;
  1047. } else {
  1048. dwStencilClearVal=(dwStencil & ((1<<pPixFmt->dwStencilBitDepth)-1))
  1049. << lpDevI->stencilmask_shift;
  1050. }
  1051. }
  1052. // Fall back to Emulation using Blt
  1053. if(bDoRGBClear) {
  1054. BltFillRects(lpDevI, numRect, lpRect, &vFillColor); //ok to not return possible errors from Blt?
  1055. }
  1056. if(bDoZClear||bDoStencilClear) {
  1057. if((bDoZClear!=bDoStencilClear) && bIsStencilSurface) {
  1058. // have to worry about using writemask to screen out writing the stencil or z buffer
  1059. if(bDoZClear) {
  1060. // WriteMask enabled Z bits only
  1061. DDASSERT(pZPixFmt->dwZBitMask!=0x0);
  1062. BltFillZRects(lpDevI,dwDepthClearVal, numRect, lpRect, pZPixFmt->dwZBitMask);
  1063. } else {
  1064. DDASSERT(pZPixFmt->dwStencilBitMask!=0x0);
  1065. BltFillZRects(lpDevI,dwStencilClearVal, numRect, lpRect, pZPixFmt->dwStencilBitMask);
  1066. }
  1067. } else {
  1068. // do Stencil & Z Blt together, using regular DepthFill blt which will be faster
  1069. // than the writemask blt because its write-only, instead of read-modify-write
  1070. // Note we're passing non-0xffffffff values to DepthFill Blt here
  1071. // not absolutely guaranteed to work on legacy drivers
  1072. BltFillZRects(lpDevI,(dwDepthClearVal | dwStencilClearVal), numRect, lpRect, 0x0);
  1073. }
  1074. }
  1075. return D3D_OK;
  1076. }
  1077. #undef DPF_MODNAME