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.

794 lines
25 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 "d3dfei.h"
  13. #include "tlhal.h"
  14. #ifndef WIN95
  15. #include <ntgdistr.h>
  16. #endif
  17. void Destroy(LPDIRECT3DDEVICEI lpDevI);
  18. //---------------------------------------------------------------------
  19. int
  20. GenGetExtraVerticesNumber( LPDIRECT3DDEVICEI lpDevI )
  21. {
  22. LPD3DHAL_GLOBALDRIVERDATA lpGlob = lpDevI->lpD3DHALGlobalDriverData;
  23. return (int)(lpGlob->dwNumVertices ?
  24. lpGlob->dwNumVertices : D3DHAL_DEFAULT_TL_NUM);
  25. }
  26. //---------------------------------------------------------------------
  27. HRESULT CalcDDSurfInfo(LPDIRECT3DDEVICEI lpDevI, BOOL bUpdateZBufferFields)
  28. {
  29. DDSURFACEDESC ddsd;
  30. HRESULT ddrval;
  31. DWORD dwWidth, dwHeight;
  32. unsigned long m;
  33. int s;
  34. // Get info from the surface
  35. memset(&ddsd, 0, sizeof(DDSURFACEDESC));
  36. ddsd.dwSize = sizeof(DDSURFACEDESC);
  37. ddrval = lpDevI->lpDDSTarget->GetSurfaceDesc(&ddsd);
  38. if (ddrval != DD_OK) {
  39. return ddrval;
  40. }
  41. dwWidth = ddsd.dwWidth;
  42. dwHeight = ddsd.dwHeight;
  43. if ((ddsd.ddpfPixelFormat.dwFlags & (DDPF_PALETTEINDEXED4 | DDPF_PALETTEINDEXED8)) == 0) {
  44. // palettized pixfmts will not have valid RGB Bitmasks, so avoid computing this for them
  45. lpDevI->red_mask = ddsd.ddpfPixelFormat.dwRBitMask;
  46. lpDevI->green_mask = ddsd.ddpfPixelFormat.dwGBitMask;
  47. lpDevI->blue_mask = ddsd.ddpfPixelFormat.dwBBitMask;
  48. if ((lpDevI->red_mask == 0x0) ||
  49. (lpDevI->green_mask == 0x0) ||
  50. (lpDevI->blue_mask == 0x0))
  51. {
  52. D3D_ERR("All the color masks in the Render target's pixel-format must be non-zero");
  53. return DDERR_INVALIDPIXELFORMAT;
  54. }
  55. // these are used by Clear
  56. for (s = 0, m = lpDevI->red_mask; !(m & 1); s++, m >>= 1) ;
  57. lpDevI->red_shift = s;
  58. lpDevI->red_scale = 255 / (lpDevI->red_mask >> s);
  59. for (s = 0, m = lpDevI->green_mask; !(m & 1); s++, m >>= 1) ;
  60. lpDevI->green_shift = s;
  61. lpDevI->green_scale = 255 / (lpDevI->green_mask >> s);
  62. for (s = 0, m = lpDevI->blue_mask; !(m & 1); s++, m >>= 1) ;
  63. lpDevI->blue_shift = s;
  64. lpDevI->blue_scale = 255 / (lpDevI->blue_mask >> s);
  65. if ( (lpDevI->red_scale==0) ||
  66. (lpDevI->green_scale==0) ||
  67. (lpDevI->blue_scale==0) )
  68. return DDERR_INVALIDPIXELFORMAT;
  69. // If there is Alpha in this format
  70. if (ddsd.ddpfPixelFormat.dwFlags & DDPF_ALPHAPIXELS)
  71. {
  72. lpDevI->alpha_mask = ddsd.ddpfPixelFormat.dwRGBAlphaBitMask;
  73. for (s = 0, m = lpDevI->alpha_mask; !(m & 1); s++, m >>= 1) ;
  74. lpDevI->alpha_shift = s;
  75. lpDevI->alpha_scale = 255 / (lpDevI->alpha_mask >> s);
  76. }
  77. else
  78. {
  79. lpDevI->alpha_shift = lpDevI->alpha_scale = lpDevI->alpha_mask = 0;
  80. }
  81. lpDevI->bDDSTargetIsPalettized=FALSE;
  82. } else
  83. lpDevI->bDDSTargetIsPalettized=TRUE;
  84. if (lpDevI->lpDDSZBuffer_DDS7 && bUpdateZBufferFields) {
  85. // Get info from the surface
  86. DDSURFACEDESC2 ddsd2;
  87. memset(&ddsd2, 0, sizeof(ddsd2));
  88. ddsd2.dwSize = sizeof(ddsd2);
  89. ddrval = lpDevI->lpDDSZBuffer_DDS7->GetSurfaceDesc(&ddsd2);
  90. if (ddrval != DD_OK) {
  91. return ddrval;
  92. }
  93. if( ddsd2.ddpfPixelFormat.dwZBitMask!=0x0) {
  94. for (s = 0, m = ddsd2.ddpfPixelFormat.dwZBitMask; !(m & 0x1); s++, m >>= 1) ;
  95. lpDevI->zmask_shift=s;
  96. } else {
  97. lpDevI->zmask_shift=0; // if ZBitMask isn't being set, then Clear2 will never be used,
  98. // so zbuf_shift/stencil_shift wont be needed anyway
  99. }
  100. if( ddsd2.ddpfPixelFormat.dwStencilBitMask!=0x0) {
  101. for (s = 0, m = ddsd2.ddpfPixelFormat.dwStencilBitMask; !(m & 0x1); s++, m >>= 1) ;
  102. lpDevI->stencilmask_shift=s;
  103. } else {
  104. lpDevI->stencilmask_shift=0;
  105. }
  106. }
  107. return D3D_OK;
  108. }
  109. // called by DDRAW
  110. extern "C" HRESULT __stdcall Direct3D_HALCleanUp(LPD3DHAL_CALLBACKS lpD3DHALCallbacks, DWORD dwPID)
  111. {
  112. D3DHAL_CONTEXTDESTROYALLDATA data;
  113. HRESULT ret;
  114. DDASSERT(lpD3DHALCallbacks!=NULL);
  115. if (lpD3DHALCallbacks->ContextDestroyAll==NULL) {
  116. // no cleanup necessary (running on d3d hel)
  117. return D3D_OK;
  118. }
  119. memset(&data, 0, sizeof(D3DHAL_CONTEXTDESTROYALLDATA));
  120. data.dwPID = dwPID;
  121. // I'd prefer to use CALL_HALONLY() to do the locking (to avoid doing it for the SW rasterizers),
  122. // but that requires a pDevI which I can't get to from the caller, which is a ddraw cleanup routine
  123. #ifdef WIN95
  124. _EnterSysLevel(lpWin16Lock);
  125. #endif
  126. ret = (*lpD3DHALCallbacks->ContextDestroyAll)(&data);
  127. #ifdef WIN95
  128. _LeaveSysLevel(lpWin16Lock);
  129. #endif
  130. return ret;
  131. }
  132. // ATTENTION - These two functions should be combined into one as soon
  133. // as ContextCreate has the new private data mechanism built in.
  134. #ifdef WIN95
  135. HRESULT DIRECT3DDEVICEI::halCreateContext()
  136. {
  137. D3DHAL_CONTEXTCREATEDATA data;
  138. HRESULT ret;
  139. D3D_INFO(6, "in halCreateContext. Creating Context for driver = %08lx", this);
  140. memset(&data, 0, sizeof(D3DHAL_CONTEXTCREATEDATA));
  141. //
  142. // From DX7 onwards, drivers should be accepting
  143. // Surface Locals instead of the Surface interfaces
  144. // this future-proofs the drivers
  145. //
  146. if (IS_DX7HAL_DEVICE(this))
  147. {
  148. if (this->lpDD)
  149. data.lpDDLcl = ((LPDDRAWI_DIRECTDRAW_INT)(this->lpDD))->lpLcl;
  150. else
  151. data.lpDDLcl = NULL;
  152. if (lpDDSTarget)
  153. data.lpDDSLcl = ((LPDDRAWI_DDRAWSURFACE_INT)lpDDSTarget)->lpLcl;
  154. else
  155. data.lpDDSLcl = NULL;
  156. if (lpDDSZBuffer)
  157. data.lpDDSZLcl = ((LPDDRAWI_DDRAWSURFACE_INT)lpDDSZBuffer)->lpLcl;
  158. else
  159. data.lpDDSZLcl = NULL;
  160. }
  161. else
  162. {
  163. data.lpDDGbl = this->lpDDGbl;
  164. data.lpDDS = this->lpDDSTarget;
  165. data.lpDDSZ = this->lpDDSZBuffer;
  166. }
  167. // Hack Alert!! dwhContext is used to inform the driver which version
  168. // of the D3D interface is calling it.
  169. data.dwhContext = 3;
  170. data.dwPID = GetCurrentProcessId();
  171. // Hack Alert!! ddrval is used to inform the driver which driver type
  172. // the runtime thinks it is (DriverStyle registry setting)
  173. data.ddrval = this->deviceType;
  174. if (!IS_HW_DEVICE(this))
  175. {
  176. // The new software rasterizers want to share IM's state vector so
  177. // we need to pass them the rstates pointer. They don't
  178. // care about dwPID so stick the pointer in there.
  179. data.dwPID = (DWORD)this->rstates;
  180. }
  181. /* 0 for pre-DX5 devices.
  182. * 1 for DX5 devices.
  183. * 2 for DX6 devices.
  184. * 3 for DX7 devices.
  185. */
  186. CALL_HALONLY(ret, this, ContextCreate, &data);
  187. if (ret != DDHAL_DRIVER_HANDLED || data.ddrval != DD_OK) {
  188. D3D_ERR( "Driver did not handle ContextCreate" );
  189. return (DDERR_GENERIC);
  190. }
  191. this->dwhContext = data.dwhContext;
  192. if (D3DMalloc ((void**)&this->lpwDPBufferAlloced,
  193. max(dwD3DTriBatchSize*4*sizeof(WORD),
  194. dwHWBufferSize) +32) != DD_OK)
  195. {
  196. D3D_ERR( "Out of memory in DeviceCreate" );
  197. return (DDERR_OUTOFMEMORY);
  198. }
  199. this->lpwDPBuffer = (LPWORD) (((DWORD) this->lpwDPBufferAlloced+31) & (~31));
  200. // save the surface handle for later checks
  201. this->hSurfaceTarget = ((LPDDRAWI_DDRAWSURFACE_INT)this->lpDDSTarget)->lpLcl->lpSurfMore->dwSurfaceHandle;
  202. D3D_INFO(6, "in halCreateContext. Succeeded. dwhContext = %d", data.dwhContext);
  203. return (D3D_OK);
  204. }
  205. #else
  206. /*
  207. * On NT the kernel code creates the buffer to be used
  208. * for DrawPrim batching and returns it as extra data
  209. * in the ContextCreate request.
  210. */
  211. HRESULT DIRECT3DDEVICEI::halCreateContext()
  212. {
  213. D3DNTHAL_CONTEXTCREATEI ntData;
  214. D3DHAL_CONTEXTCREATEDATA *lpData =
  215. (D3DHAL_CONTEXTCREATEDATA *)&ntData;
  216. HRESULT ret;
  217. D3D_INFO(6, "in halCreateContext. Creating Context for driver = %08lx", this);
  218. /*
  219. * AnanKan: Assert here that the D3DNTHAL_CONTEXTCREATEI structure is
  220. * 2 DWORDS bigger than D3DHAL_CONTEXTCREATEDATA. This will be a good
  221. * consistency check for NT kernel updates.
  222. */
  223. memset(&ntData, 0, sizeof(ntData));
  224. if (IS_DX7HAL_DEVICE(this) || (dwFEFlags & D3DFE_REALHAL))
  225. {
  226. if (this->lpDD)
  227. lpData->lpDDLcl = ((LPDDRAWI_DIRECTDRAW_INT)(this->lpDD))->lpLcl;
  228. else
  229. lpData->lpDDLcl = NULL;
  230. if (lpDDSTarget)
  231. lpData->lpDDSLcl = ((LPDDRAWI_DDRAWSURFACE_INT)lpDDSTarget)->lpLcl;
  232. else
  233. lpData->lpDDSLcl = NULL;
  234. if (lpDDSZBuffer)
  235. lpData->lpDDSZLcl = ((LPDDRAWI_DDRAWSURFACE_INT)lpDDSZBuffer)->lpLcl;
  236. else
  237. lpData->lpDDSZLcl = NULL;
  238. }
  239. else
  240. {
  241. lpData->lpDDGbl = lpDDGbl;
  242. lpData->lpDDS = lpDDSTarget;
  243. lpData->lpDDSZ = lpDDSZBuffer;
  244. }
  245. // Hack Alert!! dwhContext is used to inform the driver which version
  246. // of the D3D interface is calling it.
  247. lpData->dwhContext = 3;
  248. lpData->dwPID = GetCurrentProcessId();
  249. // Hack Alert!! ddrval is used to inform the driver which driver type
  250. // the runtime thinks it is (DriverStyle registry setting)
  251. lpData->ddrval = this->deviceType;
  252. if (IS_HW_DEVICE(this))
  253. {
  254. // The new software rasterizers want to share IM's state vector so
  255. // we need to pass them the rstates pointer. They don't
  256. // care about dwPID so stick the pointer in there.
  257. lpData->dwPID = (DWORD)((ULONG_PTR)this->rstates);
  258. }
  259. /* 0 for pre-DX5 devices.
  260. * 1 for DX5 devices.
  261. * 2 for DX6 devices.
  262. * 3 for DX7 devices.
  263. */
  264. ntData.cjBuffer = this->dwDPBufferSize;
  265. ntData.pvBuffer = NULL;
  266. CALL_HALONLY(ret, this, ContextCreate, lpData);
  267. if (ret != DDHAL_DRIVER_HANDLED || lpData->ddrval != DD_OK) {
  268. D3D_ERR( "Driver did not handle ContextCreate" );
  269. return (DDERR_GENERIC);
  270. }
  271. this->dwhContext = (DWORD)((ULONG_PTR)lpData->dwhContext);
  272. // If the this chose not to allocate a DrawPrim buffer do
  273. // it for them.
  274. if (ntData.pvBuffer == NULL)
  275. {
  276. this->dwDPBufferSize =
  277. dwD3DTriBatchSize * 4 * sizeof(WORD);
  278. if (this->dwDPBufferSize < dwHWBufferSize)
  279. {
  280. this->dwDPBufferSize = dwHWBufferSize;
  281. }
  282. ret = D3DMalloc((void**)&this->lpwDPBufferAlloced,
  283. this->dwDPBufferSize + 32);
  284. if (ret != DD_OK)
  285. {
  286. return ret;
  287. }
  288. ntData.pvBuffer = (LPVOID)
  289. (((ULONG_PTR)this->lpwDPBufferAlloced + 31) & ~31);
  290. ntData.cjBuffer = this->dwDPBufferSize + 32 -
  291. (DWORD)((ULONG_PTR)ntData.pvBuffer -
  292. (ULONG_PTR)this->lpwDPBufferAlloced);
  293. }
  294. else if( (this->dwDPBufferSize &&
  295. ntData.cjBuffer < this->dwDPBufferSize) ||
  296. ntData.cjBuffer < sizeof(D3DHAL_DRAWPRIMCOUNTS) )
  297. {
  298. D3D_ERR( "Driver did not correctly allocate DrawPrim buffer");
  299. return (DDERR_GENERIC);
  300. }
  301. // Need to save the buffer space provided and its size
  302. this->lpwDPBuffer = (LPWORD)ntData.pvBuffer;
  303. // save the surface handle for later checks
  304. this->hSurfaceTarget = (DWORD)(((LPDDRAWI_DDRAWSURFACE_INT)this->lpDDSTarget)->lpLcl->hDDSurface);
  305. D3D_INFO(6, "in halCreateContext. Succeeded. dwhContext = %d", lpData->dwhContext);
  306. return (D3D_OK);
  307. }
  308. #endif //WIN95
  309. void halDestroyContext(LPDIRECT3DDEVICEI lpDevI)
  310. {
  311. D3DHAL_CONTEXTDESTROYDATA data;
  312. HRESULT ret;
  313. D3D_INFO(6, "in halCreateDestroy. Destroying Context for driver = %08lx", lpDevI);
  314. D3D_INFO(6, " dwhContext = %d", lpDevI->dwhContext);
  315. if(lpDevI->dwhContext!=NULL) {
  316. memset(&data, 0, sizeof(D3DHAL_CONTEXTDESTROYDATA));
  317. data.dwhContext = lpDevI->dwhContext;
  318. CALL_HALONLY(ret, lpDevI, ContextDestroy, &data);
  319. if (ret != DDHAL_DRIVER_HANDLED || data.ddrval != DD_OK) {
  320. D3D_WARN(0,"Failed ContextDestroy HAL call in halDestroyContext");
  321. return;
  322. }
  323. }
  324. }
  325. //---------------------------------------------------------------------
  326. HRESULT D3DFE_Create(LPDIRECT3DDEVICEI lpDevI,
  327. LPDIRECTDRAW lpDD,
  328. LPDIRECTDRAW7 lpDD7,
  329. LPDIRECTDRAWSURFACE lpDDS,
  330. LPDIRECTDRAWSURFACE lpZ,
  331. LPDIRECTDRAWPALETTE lpPal)
  332. {
  333. DDSURFACEDESC ddsd;
  334. HRESULT hr;
  335. LPD3DHAL_GLOBALDRIVERDATA lpGlob;
  336. /*
  337. * Allocate and check validity of DirectDraw surfaces
  338. */
  339. lpDevI->lpDD = lpDD;
  340. lpDevI->lpDDGbl = ((LPDDRAWI_DIRECTDRAW_INT)lpDD)->lpLcl->lpGbl;
  341. lpDevI->lpDDSTarget = lpDDS;
  342. // Get DDS7 Interfaces for RenderTarget/ZBuffer
  343. HRESULT ret = lpDDS->QueryInterface(IID_IDirectDrawSurface7, (LPVOID*)&lpDevI->lpDDSTarget_DDS7);
  344. if(FAILED(ret)) {
  345. D3D_ERR("QI for RenderTarget DDS7 Interface failed ");
  346. return ret;
  347. }
  348. if(lpZ!=NULL) {
  349. ret = lpZ->QueryInterface(IID_IDirectDrawSurface7, (LPVOID*)&lpDevI->lpDDSZBuffer_DDS7);
  350. if(FAILED(ret)) {
  351. D3D_ERR("QI for ZBuffer DDS7 Interface failed ");
  352. return ret;
  353. }
  354. lpDevI->lpDDSZBuffer_DDS7->Release();
  355. }
  356. LPD3DHAL_D3DEXTENDEDCAPS lpCaps = lpDevI->lpD3DExtendedCaps;
  357. if (NULL == lpCaps || 0.0f == lpCaps->dvExtentsAdjust)
  358. {
  359. lpDevI->dvExtentsAdjust = 1.0f;
  360. }
  361. else
  362. {
  363. lpDevI->dvExtentsAdjust = lpCaps->dvExtentsAdjust;
  364. }
  365. lpDevI->dwClipMaskOffScreen = 0xFFFFFFFF;
  366. if (lpCaps != NULL)
  367. {
  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. lpDevI->dwClipMaskOffScreen = ~__D3DCLIP_INGUARDBAND;
  375. DWORD v;
  376. if (GetD3DRegValue(REG_DWORD, "DisableGB", &v, 4) &&
  377. v != 0)
  378. {
  379. lpDevI->dwDeviceFlags &= ~D3DDEV_GUARDBAND;
  380. lpDevI->dwClipMaskOffScreen = 0xFFFFFFFF;
  381. }
  382. #if DBG
  383. // Try to get test values for the guard band
  384. char value[80];
  385. if (GetD3DRegValue(REG_SZ, "GuardBandLeft", &value, 80) &&
  386. value[0] != 0)
  387. sscanf(value, "%f", &lpCaps->dvGuardBandLeft);
  388. if (GetD3DRegValue(REG_SZ, "GuardBandRight", &value, 80) &&
  389. value[0] != 0)
  390. sscanf(value, "%f", &lpCaps->dvGuardBandRight);
  391. if (GetD3DRegValue(REG_SZ, "GuardBandTop", &value, 80) &&
  392. value[0] != 0)
  393. sscanf(value, "%f", &lpCaps->dvGuardBandTop);
  394. if (GetD3DRegValue(REG_SZ, "GuardBandBottom", &value, 80) &&
  395. value[0] != 0)
  396. sscanf(value, "%f", &lpCaps->dvGuardBandBottom);
  397. #endif // DBG
  398. }
  399. }
  400. if (!lpDevI->lpD3DHALCallbacks || ! lpDevI->lpD3DHALGlobalDriverData)
  401. {
  402. return DDERR_INVALIDOBJECT;
  403. }
  404. if (IS_HW_DEVICE(lpDevI))
  405. {
  406. // We do texture management (and hence clipped Blts) only for a real HAL.
  407. hr = lpDD7->CreateClipper(0, &lpDevI->lpClipper, NULL);
  408. if(hr != DD_OK)
  409. {
  410. D3D_ERR("Failed to create a clipper");
  411. return hr;
  412. }
  413. }
  414. else
  415. {
  416. lpDevI->lpClipper = 0;
  417. }
  418. lpGlob = lpDevI->lpD3DHALGlobalDriverData;
  419. memset(&ddsd, 0, sizeof(DDSURFACEDESC));
  420. ddsd.dwSize = sizeof(DDSURFACEDESC);
  421. if (lpZ)
  422. {
  423. if ((hr = lpZ->GetSurfaceDesc(&ddsd)) != DD_OK)
  424. {
  425. D3D_ERR("Failed to getsurfacedesc on z");
  426. return hr;
  427. }
  428. if (ddsd.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)
  429. {
  430. D3D_INFO(1, "Z buffer is in system memory.");
  431. }
  432. else if (ddsd.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)
  433. {
  434. D3D_INFO(1, "Z buffer is in video memory.");
  435. }
  436. else
  437. {
  438. D3D_ERR("Z buffer not in video or system?");
  439. }
  440. }
  441. memset(&ddsd, 0, sizeof(DDSURFACEDESC));
  442. ddsd.dwSize = sizeof(DDSURFACEDESC);
  443. if (lpDDS)
  444. {
  445. if ((hr = lpDDS->GetSurfaceDesc(&ddsd)) != DD_OK)
  446. {
  447. D3D_ERR("Failed to getsurfacedesc on back buffer");
  448. return hr;
  449. }
  450. if (ddsd.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)
  451. {
  452. D3D_INFO(1, "back buffer is in system memory.");
  453. }
  454. else if (ddsd.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY)
  455. {
  456. D3D_INFO(1, "back buffer is in video memory.");
  457. }
  458. else
  459. {
  460. D3D_ERR("back buffer not in video or system?");
  461. }
  462. if (!(lpGlob->hwCaps.dwDeviceRenderBitDepth &
  463. BitDepthToDDBD(ddsd.ddpfPixelFormat.dwRGBBitCount)))
  464. {
  465. D3D_ERR("Rendering surface's RGB bit count not supported "
  466. "by hardware device");
  467. return DDERR_INVALIDOBJECT;
  468. }
  469. }
  470. if (lpGlob->dwNumVertices
  471. && lpGlob->dwNumClipVertices < D3DHAL_NUMCLIPVERTICES)
  472. {
  473. D3D_ERR("In global driver data, dwNumClipVertices "
  474. "< D3DHAL_NUMCLIPVERTICES");
  475. lpGlob->dwNumClipVertices = D3DHAL_NUMCLIPVERTICES;
  476. }
  477. if ((hr = CalcDDSurfInfo(lpDevI,TRUE)) != DD_OK)
  478. {
  479. return hr;
  480. }
  481. RESET_HAL_CALLS(lpDevI);
  482. /*
  483. * Create our context in the HAL driver
  484. */
  485. if ((hr = lpDevI->halCreateContext()) != D3D_OK)
  486. {
  487. return hr;
  488. }
  489. // Initialize the transform and lighting state
  490. D3DMATRIXI m;
  491. setIdentity(&m);
  492. lpDevI->SetTransformI(D3DTRANSFORMSTATE_VIEW, (D3DMATRIX*)&m);
  493. lpDevI->SetTransformI(D3DTRANSFORMSTATE_PROJECTION, (D3DMATRIX*)&m);
  494. lpDevI->SetTransformI(D3DTRANSFORMSTATE_WORLD, (D3DMATRIX*)&m);
  495. lpDevI->SetTransformI(D3DTRANSFORMSTATE_WORLD1, (D3DMATRIX*)&m);
  496. lpDevI->SetTransformI(D3DTRANSFORMSTATE_WORLD2, (D3DMATRIX*)&m);
  497. lpDevI->SetTransformI(D3DTRANSFORMSTATE_WORLD3, (D3DMATRIX*)&m);
  498. lpDevI->SetTransformI(D3DTRANSFORMSTATE_TEXTURE0, (D3DMATRIX*)&m);
  499. lpDevI->SetTransformI(D3DTRANSFORMSTATE_TEXTURE1, (D3DMATRIX*)&m);
  500. lpDevI->SetTransformI(D3DTRANSFORMSTATE_TEXTURE2, (D3DMATRIX*)&m);
  501. lpDevI->SetTransformI(D3DTRANSFORMSTATE_TEXTURE3, (D3DMATRIX*)&m);
  502. lpDevI->SetTransformI(D3DTRANSFORMSTATE_TEXTURE4, (D3DMATRIX*)&m);
  503. lpDevI->SetTransformI(D3DTRANSFORMSTATE_TEXTURE5, (D3DMATRIX*)&m);
  504. lpDevI->SetTransformI(D3DTRANSFORMSTATE_TEXTURE6, (D3DMATRIX*)&m);
  505. lpDevI->SetTransformI(D3DTRANSFORMSTATE_TEXTURE7, (D3DMATRIX*)&m);
  506. LIST_INITIALIZE(&lpDevI->specular_tables);
  507. lpDevI->specular_table = NULL;
  508. lpDevI->lightVertexFuncTable = &lightVertexTable;
  509. lpDevI->lighting.activeLights = NULL;
  510. lpDevI->iClipStatus = D3DSTATUS_DEFAULT;
  511. lpDevI->rExtents.x1 = D3DVAL(2048);
  512. lpDevI->rExtents.x2 = D3DVAL(0);
  513. lpDevI->rExtents.y1 = D3DVAL(2048);
  514. lpDevI->rExtents.y2 = D3DVAL(0);
  515. return S_OK;
  516. }
  517. void D3DFE_Destroy(LPDIRECT3DDEVICEI lpDevI)
  518. {
  519. // Destroy lighting data
  520. SpecularTable *spec;
  521. SpecularTable *spec_next;
  522. for (spec = LIST_FIRST(&lpDevI->specular_tables); spec; spec = spec_next)
  523. {
  524. spec_next = LIST_NEXT(spec,list);
  525. D3DFree(spec);
  526. }
  527. if(lpDevI->lpClipper)
  528. {
  529. lpDevI->lpClipper->Release();
  530. }
  531. delete [] lpDevI->m_pLights;
  532. if (lpDevI->lpD3DHALCallbacks) {
  533. halDestroyContext(lpDevI);
  534. }
  535. #ifdef TRACK_HAL_CALLS
  536. D3D_INFO(0, "Made %d HAL calls", lpDevI->hal_calls);
  537. #endif
  538. }
  539. void BltFillRects(LPDIRECT3DDEVICEI lpDevI, DWORD count, LPD3DRECT rect, D3DCOLOR dwFillColor)
  540. {
  541. LPDIRECTDRAWSURFACE lpDDS = lpDevI->lpDDSTarget;
  542. HRESULT ddrval;
  543. DDBLTFX bltfx;
  544. RECT tr;
  545. DWORD i;
  546. DWORD r, g, b, a;
  547. // Fill with background color
  548. memset(&bltfx, 0, sizeof(bltfx));
  549. bltfx.dwSize = sizeof(bltfx);
  550. // unlike clear callback, which just takes pure 32-bit ARGB word and forces the driver to scale it for
  551. // the pixelformat, here we need to compute the exact fill word, depending on surface's R,G,B bitmasks
  552. if(lpDevI->bDDSTargetIsPalettized)
  553. {
  554. // map 24-bit color to 8-bit index used by 8bit RGB rasterizer
  555. CallRastService(lpDevI, RAST_SERVICE_RGB8COLORTOPIXEL, dwFillColor, &bltfx.dwFillColor);
  556. }
  557. else
  558. {
  559. DDASSERT((lpDevI->red_scale!=0)&&(lpDevI->green_scale!=0)&&(lpDevI->blue_scale!=0));
  560. r = RGB_GETRED(dwFillColor) / lpDevI->red_scale;
  561. g = RGB_GETGREEN(dwFillColor) / lpDevI->green_scale;
  562. b = RGB_GETBLUE(dwFillColor) / lpDevI->blue_scale;
  563. bltfx.dwFillColor = (r << lpDevI->red_shift) | (g << lpDevI->green_shift) | (b << lpDevI->blue_shift);
  564. if( lpDevI->alpha_scale!=0 )
  565. {
  566. a = RGBA_GETALPHA(dwFillColor) / lpDevI->alpha_scale;
  567. bltfx.dwFillColor |= (a << lpDevI->alpha_shift);
  568. }
  569. }
  570. for (i = 0; i < count; i++,rect++) {
  571. tr.left = rect->x1;
  572. tr.right = rect->x2;
  573. tr.top = rect->y1;
  574. tr.bottom = rect->y2;
  575. do {
  576. ddrval = lpDDS->Blt(&tr, NULL, NULL, DDBLT_COLORFILL, &bltfx);
  577. } while (ddrval == DDERR_WASSTILLDRAWING);
  578. }
  579. }
  580. void BltFillZRects(LPDIRECT3DDEVICEI lpDevI, unsigned long Zpixel,
  581. DWORD count, LPD3DRECT rect, DWORD dwWriteMask)
  582. {
  583. HRESULT ddrval;
  584. DDBLTFX bltfx;
  585. DWORD i;
  586. RECT tr;
  587. DWORD dwExtraFlags=0;
  588. #if DBG
  589. if (lpDevI->lpDDSZBuffer == NULL) // should be checked prior to call
  590. return;
  591. #endif
  592. memset(&bltfx, 0, sizeof(DDBLTFX));
  593. bltfx.dwSize = sizeof(DDBLTFX);
  594. bltfx.dwFillDepth = Zpixel;
  595. // hack to pass DepthBlt WriteMask through ddraw/ddhel to blitlib
  596. if(dwWriteMask!=0) {
  597. bltfx.dwZDestConstBitDepth=dwWriteMask;
  598. dwExtraFlags = DDBLT_DEPTHFILLWRITEMASK;
  599. }
  600. for(i=0;i<count;i++,rect++) {
  601. 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);
  602. tr.left = rect->x1;
  603. tr.right = rect->x2;
  604. tr.top = rect->y1;
  605. tr.bottom = rect->y2;
  606. do {
  607. ddrval = lpDevI->lpDDSZBuffer->Blt(&tr, NULL, NULL, DDBLT_DEPTHFILL | dwExtraFlags, &bltfx);
  608. } while (ddrval == DDERR_WASSTILLDRAWING);
  609. }
  610. }
  611. //---------------------------------------------------------------------
  612. struct CHandle
  613. {
  614. DWORD m_Next; // Used to make list of free handles
  615. #if DBG
  616. DWORD m_Tag; // 1 - empty; 2 = taken
  617. #endif
  618. };
  619. CHandleFactory::~CHandleFactory()
  620. {
  621. if (m_Handles)
  622. delete m_Handles;
  623. }
  624. HRESULT CHandleFactory::Init(DWORD dwInitialSize, DWORD dwGrowSize)
  625. {
  626. m_Handles = CreateHandleArray(dwInitialSize);
  627. if (m_Handles == NULL)
  628. return DDERR_OUTOFMEMORY;
  629. m_dwArraySize = dwInitialSize;
  630. m_dwGrowSize = dwGrowSize;
  631. m_Free = 0;
  632. return D3D_OK;
  633. }
  634. DWORD CHandleFactory::CreateNewHandle()
  635. {
  636. DWORD handle = m_Free;
  637. if (m_Free != __INVALIDHANDLE)
  638. {
  639. m_Free = m_Handles[m_Free].m_Next;
  640. }
  641. else
  642. {
  643. handle = m_dwArraySize;
  644. m_Free = m_dwArraySize + 1;
  645. m_dwArraySize += m_dwGrowSize;
  646. CHandle * newHandles = CreateHandleArray(m_dwArraySize);
  647. #if DBG
  648. memcpy(newHandles, m_Handles,
  649. (m_dwArraySize - m_dwGrowSize)*sizeof(CHandle));
  650. #endif
  651. delete m_Handles;
  652. m_Handles = newHandles;
  653. }
  654. DDASSERT(m_Handles[handle].m_Tag == 1);
  655. #if DBG
  656. m_Handles[handle].m_Tag = 2; // Mark as taken
  657. #endif
  658. return handle;
  659. }
  660. void CHandleFactory::ReleaseHandle(DWORD handle)
  661. {
  662. DDASSERT(handle < m_dwArraySize);
  663. DDASSERT(m_Handles[handle].m_Tag == 2);
  664. #if DBG
  665. m_Handles[handle].m_Tag = 1; // Mark as empty
  666. #endif
  667. m_Handles[handle].m_Next = m_Free;
  668. m_Free = handle;
  669. }
  670. CHandle* CHandleFactory::CreateHandleArray(DWORD dwSize)
  671. {
  672. CHandle *handles = new CHandle[dwSize];
  673. DDASSERT(handles != NULL);
  674. if ( NULL == handles ) return NULL;
  675. for (DWORD i=0; i < dwSize; i++)
  676. {
  677. handles[i].m_Next = i+1;
  678. #if DBG
  679. handles[i].m_Tag = 1; // Mark as empty
  680. #endif
  681. }
  682. handles[dwSize-1].m_Next = __INVALIDHANDLE;
  683. return handles;
  684. }