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.

2259 lines
83 KiB

  1. /*==========================================================================;
  2. *
  3. * Copyright (C) 1995 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: halexe.c
  6. * Content: Direct3D HAL execute calles
  7. *@@BEGIN_MSINTERNAL
  8. *
  9. * $Id: halexe.c,v 1.1 1995/11/21 15:12:37 sjl Exp $
  10. *
  11. * History:
  12. * Date By Reason
  13. * ==== == ======
  14. * 07/11/95 stevela Initial rev.
  15. * 12/11/95 stevela Lock surface before calling HAL's execute.
  16. * 29/08/96 stevela Just bit test instead of calling IsLost()
  17. *@@END_MSINTERNAL
  18. *
  19. ***************************************************************************/
  20. #include "pch.cpp"
  21. #pragma hdrstop
  22. #include "commdrv.hpp"
  23. #include "genpick.hpp"
  24. #include "d3dfei.h"
  25. #include "clipfunc.h"
  26. //---------------------------------------------------------------------
  27. #define CHECK(ddrval, str) \
  28. if (ddrval != DD_OK) \
  29. { \
  30. D3D_ERR(str); \
  31. return (ddrval); \
  32. }
  33. //---------------------------------------------------------------------
  34. __inline BOOL DDSurfaceLost(LPDIRECTDRAWSURFACE s)
  35. {
  36. return ((LPDDRAWI_DDRAWSURFACE_INT)s)->lpLcl->dwFlags & DDRAWISURF_INVALID;
  37. }
  38. #ifdef USE_INTERNAL_LOCK
  39. __inline HRESULT DDLockSurface(LPDIRECTDRAWSURFACE s)
  40. {
  41. LPDDRAWI_DDRAWSURFACE_INT lpInt;
  42. lpInt = (LPDDRAWI_DDRAWSURFACE_INT)s;
  43. return DDInternalLock(lpInt->lpLcl);
  44. }
  45. __inline HRESULT DDUnockSurface(LPDIRECTDRAWSURFACE s)
  46. {
  47. LPDDRAWI_DDRAWSURFACE_INT lpInt;
  48. lpInt = (LPDDRAWI_DDRAWSURFACE_INT)s;
  49. return DDInternalUnlock(lpInt->lpLcl);
  50. }
  51. #endif
  52. __inline BOOL DDCheckSurfaceCaps(LPDIRECTDRAWSURFACE s, DWORD flag)
  53. {
  54. LPDDRAWI_DDRAWSURFACE_INT lpInt = (LPDDRAWI_DDRAWSURFACE_INT)s;
  55. return lpInt->lpLcl->ddsCaps.dwCaps & flag;
  56. }
  57. //---------------------------------------------------------------------
  58. #define CHECKLOST(lpDevI) \
  59. { \
  60. if (DDSurfaceLost(lpDevI->lpDDSTarget) || \
  61. (lpDevI->lpDDSZBuffer && DDSurfaceLost(lpDevI->lpDDSZBuffer))) \
  62. { \
  63. D3D_WARN(0, "Render-target or ZBuffer surface lost"); \
  64. lpDevI->dwFEFlags |= D3DFE_LOSTSURFACES; \
  65. return DDERR_SURFACELOST; \
  66. } \
  67. }
  68. #define NEXTINSTRUCTION(ptr, type, num) \
  69. ptr = (LPD3DINSTRUCTION)((LPBYTE)ptr + sizeof(D3DINSTRUCTION) + \
  70. (num * sizeof(type)))
  71. //---------------------------------------------------------------------
  72. #ifdef DBG
  73. int
  74. validateTriangleFlags(LPD3DINSTRUCTION ins,
  75. LPD3DTRIANGLE tri)
  76. {
  77. int count = ins->wCount;
  78. int v1,v2,v3;
  79. int flat;
  80. int flat_count;
  81. unsigned flags;
  82. D3D_INFO(5, "Start %d triangle instruction", count);
  83. flat = 0;
  84. flat_count = 0;
  85. for (; count; count--)
  86. {
  87. flags = tri->wFlags;
  88. flags &= 0x1f;
  89. switch (flags)
  90. {
  91. case D3DTRIFLAG_START:
  92. v1 = tri->v1;
  93. v2 = tri->v2;
  94. v3 = tri->v3;
  95. D3D_INFO(9, " triangle %d is START", ins->wCount - count);
  96. break;
  97. case D3DTRIFLAG_ODD:
  98. v1 = v3;
  99. v2 = v2;
  100. v3 = tri->v3;
  101. if ((v1 != tri->v1) || (v2 != tri->v2))
  102. {
  103. D3D_WARN(1, " triangle %d is not an odd triangle",
  104. ins->wCount - count);
  105. return FALSE;
  106. }
  107. break;
  108. case D3DTRIFLAG_EVEN:
  109. v1 = v1;
  110. v2 = v3;
  111. v3 = tri->v3;
  112. if ((v1 != tri->v1) || (v2 != tri->v2))
  113. {
  114. D3D_WARN(1, " triangle %d is not an even triangle",
  115. ins->wCount - count);
  116. return FALSE;
  117. }
  118. break;
  119. default:
  120. /* (flags > 0) && (flags < 30) */
  121. v1 = tri->v1;
  122. v2 = tri->v2;
  123. v3 = tri->v3;
  124. D3D_INFO(9, " triangle %d is START FLAT of %d", ins->wCount - count, flags);
  125. flat_count = flags;
  126. break;
  127. }
  128. tri = (D3DTRIANGLE*) ((char*) tri + ins->bSize);
  129. }
  130. return TRUE;
  131. }
  132. //---------------------------------------------------------------------
  133. D3DVERTEXTYPE GetVertexType(LPDIRECT3DDEVICEI lpDevI)
  134. {
  135. if (lpDevI->dwFEFlags & D3DFE_TLVERTEX)
  136. return D3DVT_TLVERTEX;
  137. else
  138. if (lpDevI->dwFlags & D3DPV_LIGHTING)
  139. return D3DVT_VERTEX;
  140. else
  141. return D3DVT_LVERTEX;
  142. }
  143. #endif // DBG
  144. //---------------------------------------------------------------------
  145. // Returns TRUE, if driver should be notified about the state
  146. BOOL
  147. trackState(LPDIRECT3DDEVICEI lpDevI, LPD3DSTATE state)
  148. {
  149. DWORD type = (DWORD) state->drstRenderStateType;
  150. D3D_INFO(9, "trackState: state = %d", state->drstRenderStateType);
  151. if (IS_OVERRIDE(type))
  152. {
  153. DWORD override = GET_OVERRIDE(type);
  154. if (state->dwArg[0])
  155. {
  156. D3D_INFO(9, "trackState: setting override for state %d", override);
  157. STATESET_SET(lpDevI->renderstate_overrides, override);
  158. }
  159. else
  160. {
  161. D3D_INFO(9, "trackState: clearing override for state %d", override);
  162. STATESET_CLEAR(lpDevI->renderstate_overrides, override);
  163. }
  164. return TRUE;
  165. }
  166. if (STATESET_ISSET(lpDevI->renderstate_overrides, type))
  167. {
  168. D3D_INFO(9, "trackState: state %d is overridden, ignoring", type);
  169. return FALSE;
  170. }
  171. /* Save latest state for GetRenderState(). This will break if
  172. someone actually implements the Execute in DDI i.e. when
  173. D3DHAL_Execute{Un}Clipped calls us. */
  174. SetDeviceRenderState(lpDevI, state->drstRenderStateType, state->dwArg[0]);
  175. return TRUE;
  176. }
  177. //----------------------------------------------------------------------
  178. // This function does not copy the data if pIn = pOut
  179. //
  180. void ConvertColorsToRamp(LPDIRECT3DDEVICEI lpDevI, D3DTLVERTEX *pIn,
  181. D3DTLVERTEX *pOut, DWORD count)
  182. {
  183. RAMP_RANGE_INFO RampInfo;
  184. BOOL theSameInAndOut = pIn == pOut;
  185. CallRampService(lpDevI, RAMP_SERVICE_FIND_LIGHTINGRANGE,
  186. (ULONG_PTR)&RampInfo, 0);
  187. D3DVALUE colorScale = D3DVAL(max(min((INT32)RampInfo.size - 1, 0x7fff), 0));
  188. for (DWORD i=count; i; i--)
  189. {
  190. const D3DVALUE B_SCALE = 1.000f / 255.0f;
  191. // Convert diffuse color to shade value
  192. D3DVALUE color = RGBA_GETBLUE (pIn->color)*B_SCALE;
  193. if (RampInfo.specular)
  194. {
  195. // Convert specular color to shade value
  196. D3DVALUE specular = RGBA_GETBLUE (pIn->specular)*B_SCALE;
  197. color = 0.75f*color*(1.0f - specular) + specular;
  198. }
  199. DWORD outColor = (DWORD)(color * colorScale) + RampInfo.base;
  200. if (theSameInAndOut)
  201. {
  202. pIn->color = CI_MAKE(RGBA_GETALPHA(pIn->color), outColor, 0);
  203. pIn->specular = PtrToUlong(RampInfo.pTexRampMap);
  204. }
  205. else
  206. {
  207. pOut->color = CI_MAKE(RGBA_GETALPHA(pIn->color), outColor, 0);
  208. pOut->specular = PtrToUlong(RampInfo.pTexRampMap);
  209. pOut->sx = pIn->sx;
  210. pOut->sy = pIn->sy;
  211. pOut->sz = pIn->sz;
  212. pOut->rhw = pIn->rhw;
  213. pOut->tu = pIn->tu;
  214. pOut->tv = pIn->tv;
  215. pOut++;
  216. }
  217. pIn++;
  218. }
  219. }
  220. //---------------------------------------------------------------------
  221. void WaitForFlip(LPDIRECTDRAWSURFACE lpDDS)
  222. {
  223. if (DDCheckSurfaceCaps(lpDDS, DDSCAPS_FLIP))
  224. {
  225. HRESULT ret;
  226. D3D_WARN(4, "Waiting for flip");
  227. do
  228. {
  229. ret = lpDDS->GetFlipStatus(DDGFS_ISFLIPDONE);
  230. } while (ret == DDERR_WASSTILLDRAWING);
  231. }
  232. }
  233. //---------------------------------------------------------------------
  234. // DrawPrim for execute buffers using RenderPrimitive
  235. // This function is called by the clipper
  236. //
  237. HRESULT CDirect3DDeviceIHW::DrawExeBuf()
  238. {
  239. D3DHAL_RENDERPRIMITIVEDATA data;
  240. LPDIRECTDRAWSURFACE lpDDS = this->lpDDSTarget;
  241. HRESULT ret;
  242. WORD wFirstPointIndex;
  243. memset(&data, 0, sizeof data);
  244. data.dwhContext = this->dwhContext;
  245. data.dwStatus = this->iClipStatus;
  246. data.dwTLOffset = 0;
  247. if (this->dwFlags & D3DPV_CLIPPERPRIM)
  248. {
  249. // For clipped primitive vertices are generated in ClipperState.clipBuf
  250. data.lpTLBuf = this->ClipperState.clipBuf.GetDDS();
  251. data.lpExeBuf = this->ClipperState.clipBufPrim.GetDDS();
  252. data.dwOffset = 0;
  253. wFirstPointIndex = 0;
  254. }
  255. else
  256. {
  257. data.lpTLBuf = this->TLVbuf.GetDDS();
  258. if (this->primType == D3DPT_POINTLIST)
  259. {
  260. data.lpExeBuf = this->ClipperState.clipBufPrim.GetDDS();
  261. data.dwOffset = 0;
  262. wFirstPointIndex = (WORD)(((BYTE*)this->lpvOut -
  263. (BYTE*)this->TLVbuf.GetAddress()) >> 5);
  264. }
  265. else
  266. {
  267. data.lpExeBuf = this->ClipperState.lpDDExeBuf;
  268. data.dwOffset = (DWORD)
  269. ((BYTE*)this->lpwIndices - (BYTE*)this->ClipperState.lpvExeBufMem);
  270. }
  271. }
  272. switch (this->primType)
  273. {
  274. case D3DPT_POINTLIST:
  275. {
  276. D3DPOINT *pPoint = (D3DPOINT*)this->ClipperState.clipBufPrim.GetAddress();
  277. // Size of TLVERTEX is 32
  278. pPoint->wFirst = wFirstPointIndex;
  279. pPoint->wCount = (WORD)this->dwNumVertices;
  280. data.diInstruction.bOpcode = D3DOP_POINT;
  281. data.diInstruction.bSize = sizeof(D3DPOINT);
  282. data.diInstruction.wCount = 1;
  283. break;
  284. }
  285. case D3DPT_LINELIST:
  286. {
  287. data.diInstruction.bOpcode = D3DOP_LINE;
  288. data.diInstruction.bSize = sizeof(D3DLINE);
  289. D3DLINE *pLine= (D3DLINE*)this->ClipperState.clipBufPrim.GetAddress();
  290. if (this->dwFlags & D3DPV_CLIPPERPRIM)
  291. {
  292. // Clipped line is not indexed
  293. pLine->v1 = 0;
  294. pLine->v2 = 1;
  295. data.diInstruction.wCount = 1;
  296. }
  297. else
  298. data.diInstruction.wCount = (WORD)(this->dwNumIndices >> 1);
  299. break;
  300. }
  301. case D3DPT_TRIANGLEFAN:
  302. case D3DPT_TRIANGLELIST:
  303. {
  304. data.diInstruction.bOpcode = D3DOP_TRIANGLE;
  305. data.diInstruction.bSize = sizeof(D3DTRIANGLE);
  306. D3DTRIANGLE *pTri = (D3DTRIANGLE*)
  307. this->ClipperState.clipBufPrim.GetAddress();
  308. if (this->dwFlags & D3DPV_CLIPPERPRIM)
  309. {
  310. // Clipped triangle is non-indexed triangle fan
  311. // We have to convert it to indexed triangle list and compute
  312. // edge flags
  313. ClipVertex **clip = this->ClipperState.current_vbuf;
  314. pTri->wFlags = D3DTRIFLAG_STARTFLAT((WORD)this->dwNumPrimitives);
  315. if (clip[0]->clip & CLIPPED_ENABLE)
  316. pTri->wFlags |= D3DTRIFLAG_EDGEENABLE1;
  317. DWORD i;
  318. for (i=1; i <= this->dwNumPrimitives; i++)
  319. {
  320. pTri->v1 = 0;
  321. pTri->v2 = (WORD)i;
  322. pTri->v3 = (WORD)(i+1);
  323. if (clip[i]->clip & CLIPPED_ENABLE)
  324. pTri->wFlags |= D3DTRIFLAG_EDGEENABLE2;
  325. pTri++;
  326. pTri->wFlags = D3DTRIFLAG_EVEN; // All except first are EVEN
  327. }
  328. pTri--;
  329. // Edge 3 is enabled only for the last triangle in the fan
  330. // Not that "i" points to the last clip vertex
  331. if (clip[i]->clip & CLIPPED_ENABLE)
  332. pTri->wFlags |= D3DTRIFLAG_EDGEENABLE3;
  333. data.diInstruction.wCount = (WORD)this->dwNumPrimitives;
  334. }
  335. else
  336. data.diInstruction.wCount = (WORD)this->dwNumPrimitives;
  337. break;
  338. }
  339. }
  340. #ifndef WIN95
  341. if((ret = CheckContextSurfaceNOLOCK(this)) != D3D_OK)
  342. return (D3DERR_EXECUTE_FAILED);
  343. #endif //WIN95
  344. #if _D3D_FORCEDOUBLE
  345. CD3DForceFPUDouble ForceFPUDouble(this);
  346. #endif //_D3D_FORCEDOUBLE
  347. CALL_HALONLY_NOLOCK(ret, this, RenderPrimitive, &data);
  348. if (ret != DDHAL_DRIVER_HANDLED)
  349. {
  350. D3D_ERR("HAL failed to handle RenderPrimitive call from Execute API");
  351. return (D3DERR_EXECUTE_FAILED);
  352. }
  353. this->iClipStatus = data.dwStatus;
  354. if (data.ddrval != DD_OK)
  355. {
  356. D3D_ERR("HAL error in RenderPrimitive call from Execute API");
  357. return (data.ddrval);
  358. }
  359. return (D3D_OK);
  360. }
  361. //---------------------------------------------------------------------
  362. HRESULT DIRECT3DDEVICEI::PickExeBuf()
  363. {
  364. LPD3DTRIANGLE tri;
  365. DWORD i;
  366. LPD3DRECT pick_region = &this->pick_data.pick;
  367. D3DVALUE result;
  368. LPD3DTLVERTEX lpTLV;
  369. HRESULT ret;
  370. if (this->dwFlags & D3DPV_CLIPPERPRIM)
  371. {
  372. // For clipped primitive vertices are generated in ClipperState.clipBuf
  373. lpTLV = (D3DTLVERTEX*)this->ClipperState.clipBuf.GetAddress();
  374. D3DTRIANGLE tri;
  375. tri.v1 = 0;
  376. for (i=1; i <= this->dwNumPrimitives; i++)
  377. {
  378. tri.v2 = (WORD)i;
  379. tri.v3 = (WORD)(i+1);
  380. tri.wFlags = D3DTRIFLAG_EDGEENABLETRIANGLE;
  381. if (GenPickTriangle(this, lpTLV, &tri, pick_region, &result))
  382. {
  383. if ((ret = GenAddPickRecord(this,
  384. D3DOP_TRIANGLE,
  385. this->dwClipIns_offset,
  386. result)) != D3D_OK)
  387. return ret;
  388. }
  389. }
  390. }
  391. else
  392. {
  393. lpTLV = (D3DTLVERTEX*)this->TLVbuf.GetAddress();
  394. tri = (LPD3DTRIANGLE)this->lpwIndices;
  395. for (i = this->dwNumPrimitives; i; i--, tri++)
  396. {
  397. if (GenPickTriangle(this, lpTLV, tri, pick_region, &result))
  398. {
  399. if ((ret = GenAddPickRecord(this,
  400. D3DOP_TRIANGLE,
  401. (DWORD)((BYTE*)tri - (BYTE*)this->lpbClipIns_base),
  402. result)) != D3D_OK)
  403. return ret;
  404. }
  405. }
  406. }
  407. return D3D_OK;
  408. }
  409. /*************************************************************************/
  410. /* Points */
  411. /*************************************************************************/
  412. HRESULT D3DFEClipPointsHW(LPDIRECT3DDEVICEI lpDevI, D3DPOINT *point, DWORD dwCount)
  413. {
  414. DWORD icount = dwCount;
  415. HRESULT ret;
  416. lpDevI->primType = D3DPT_LINELIST;
  417. lpDevI->lpwIndices = 0; // Points are not indexed
  418. for (; icount; icount--)
  419. {
  420. lpDevI->dwNumVertices = point->wCount;
  421. lpDevI->lpvOut = &((D3DTLVERTEX*)lpDevI->TLVbuf.GetAddress())[point->wFirst];
  422. WORD *lpClipFlagsOld = lpDevI->lpClipFlags;
  423. lpDevI->lpClipFlags = &lpDevI->lpClipFlags[point->wFirst];
  424. ret = ProcessClippedPoints(lpDevI);
  425. if (ret != D3D_OK)
  426. {
  427. D3D_ERR("ProcessClippedPoints failed!");
  428. return ret;
  429. }
  430. lpDevI->lpClipFlags = lpClipFlagsOld;
  431. point++;
  432. }
  433. return D3D_OK;
  434. }
  435. /*************************************************************************/
  436. /* Lines */
  437. /*************************************************************************/
  438. inline HRESULT D3DFEClipLinesHW(LPDIRECT3DDEVICEI lpDevI, D3DLINE *line, DWORD dwCount)
  439. {
  440. HRESULT ret;
  441. lpDevI->primType = D3DPT_LINELIST;
  442. lpDevI->dwNumIndices = dwCount << 1;
  443. lpDevI->dwNumPrimitives = dwCount;
  444. lpDevI->lpvOut = lpDevI->TLVbuf.GetAddress();
  445. lpDevI->lpwIndices = (WORD*)line;
  446. ret = ProcessClippedIndexedLine(lpDevI);
  447. return ret;
  448. }
  449. /*************************************************************************/
  450. /* Triangles */
  451. /*************************************************************************/
  452. inline HRESULT D3DFEClipTrianglesHW(LPDIRECT3DDEVICEI lpDevI, D3DTRIANGLE *tri, DWORD dwCount)
  453. {
  454. HRESULT ret;
  455. lpDevI->primType = D3DPT_TRIANGLELIST;
  456. lpDevI->dwNumPrimitives = dwCount;
  457. lpDevI->lpvOut = lpDevI->TLVbuf.GetAddress();
  458. lpDevI->dwNumIndices = dwCount * 3;
  459. lpDevI->lpwIndices = (WORD*)tri;
  460. ret = ProcessClippedIndexedTriangleList(lpDevI);
  461. return ret;
  462. }
  463. /*************************************************************************/
  464. /* Pick triangles */
  465. /*************************************************************************/
  466. inline HRESULT GenPickTriangles(LPDIRECT3DDEVICEI lpDevI, D3DTRIANGLE *tri, DWORD dwCount)
  467. {
  468. HRESULT ret;
  469. lpDevI->primType = D3DPT_TRIANGLELIST;
  470. lpDevI->dwNumIndices = dwCount * 3;
  471. lpDevI->dwNumPrimitives = dwCount;
  472. lpDevI->lpvOut = lpDevI->TLVbuf.GetAddress();
  473. lpDevI->lpwIndices = (WORD*)tri;
  474. ret = ProcessClippedIndexedTriangleList(lpDevI);
  475. return ret;
  476. }/*----------------------------------------------------------------------------
  477. *
  478. * Instruction emulation.
  479. */
  480. HRESULT D3DHELInst_D3DOP_MATRIXLOAD(LPDIRECT3DDEVICEI lpDevI,
  481. DWORD dwCount,
  482. LPD3DMATRIXLOAD lpMatLoad)
  483. {
  484. LPD3DMATRIXI lpSrcMat;
  485. LPD3DMATRIXI lpDestMat;
  486. DWORD i;
  487. HRESULT ret;
  488. D3DFE_TRANSFORM& TRANSFORM = lpDevI->transform;
  489. for (i = 0; i < dwCount; i++)
  490. {
  491. D3DMATRIXHANDLE hSrc = lpMatLoad[i].hSrcMatrix;
  492. D3DMATRIXHANDLE hDst = lpMatLoad[i].hDestMatrix;
  493. lpSrcMat = HANDLE_TO_MAT(lpDevI, hSrc);
  494. lpDestMat = HANDLE_TO_MAT(lpDevI, hDst);
  495. if (lpSrcMat == NULL || lpDestMat == NULL)
  496. return (DDERR_INVALIDPARAMS);
  497. memcpy (lpDestMat, lpSrcMat, offsetof(D3DMATRIXI, link));
  498. if (hDst == TRANSFORM.hWorld)
  499. ret = D3DFE_SetMatrixWorld(lpDevI, (D3DMATRIX*)lpSrcMat);
  500. else
  501. if (hDst == TRANSFORM.hView)
  502. ret = D3DFE_SetMatrixView(lpDevI, (D3DMATRIX*)lpSrcMat);
  503. else
  504. if (hDst == TRANSFORM.hProj)
  505. ret = D3DFE_SetMatrixProj(lpDevI, (D3DMATRIX*)lpSrcMat);
  506. if (ret != D3D_OK)
  507. return (DDERR_GENERIC);
  508. }
  509. return (D3D_OK);
  510. }
  511. //---------------------------------------------------------------------
  512. HRESULT D3DHELInst_D3DOP_MATRIXMULTIPLY(LPDIRECT3DDEVICEI lpDevI,
  513. DWORD dwCount,
  514. LPD3DMATRIXMULTIPLY lpMmult)
  515. {
  516. LPD3DMATRIXI lpMat1, lpMat2;
  517. LPD3DMATRIXI result;
  518. DWORD i;
  519. D3DFE_TRANSFORM& TRANSFORM = lpDevI->transform;
  520. for (i = 0; i < dwCount; i++)
  521. {
  522. D3DMATRIXHANDLE hSrc1 = lpMmult[i].hSrcMatrix1;
  523. D3DMATRIXHANDLE hSrc2 = lpMmult[i].hSrcMatrix2;
  524. D3DMATRIXHANDLE hDst = lpMmult[i].hDestMatrix;
  525. lpMat1 = HANDLE_TO_MAT(lpDevI, hSrc1);
  526. lpMat2 = HANDLE_TO_MAT(lpDevI, hSrc2);
  527. result = HANDLE_TO_MAT(lpDevI, hDst);
  528. if (!lpMat1 || !lpMat2)
  529. {
  530. return (DDERR_GENERIC);
  531. }
  532. MatrixProduct(result, lpMat1, lpMat2);
  533. if (hDst == TRANSFORM.hWorld)
  534. {
  535. D3DFE_SetMatrixWorld(lpDevI, (D3DMATRIX*)result);
  536. }
  537. else
  538. if (hDst == TRANSFORM.hView)
  539. {
  540. D3DFE_SetMatrixView(lpDevI, (D3DMATRIX*)result);
  541. }
  542. else
  543. if (hDst == TRANSFORM.hProj)
  544. {
  545. D3DFE_SetMatrixProj(lpDevI, (D3DMATRIX*)result);
  546. }
  547. }
  548. return (D3D_OK);
  549. }
  550. //---------------------------------------------------------------------
  551. HRESULT D3DHELInst_D3DOP_STATETRANSFORM(LPDIRECT3DDEVICEI lpDevI,
  552. DWORD count,
  553. LPD3DSTATE lpMset)
  554. {
  555. DWORD i;
  556. D3DFE_TRANSFORM& TRANSFORM = lpDevI->transform;
  557. for (i = 0; i < count; i++)
  558. {
  559. DWORD type = (DWORD) lpMset[i].dtstTransformStateType;
  560. D3D_INFO(9, "HEL D3DOP_STATETRANSFORM: state = %d", type);
  561. if (IS_OVERRIDE(type))
  562. {
  563. DWORD override = GET_OVERRIDE(type);
  564. if (lpMset[i].dwArg[0])
  565. {
  566. D3D_WARN(5, "HEL D3DOP_STATETRANSFORM: setting override for state %d", override);
  567. STATESET_SET(lpDevI->transformstate_overrides, override);
  568. } else
  569. {
  570. D3D_WARN(5, "HEL D3DOP_STATETRANSFORM: clearing override for state %d", override);
  571. STATESET_CLEAR(lpDevI->transformstate_overrides, override);
  572. }
  573. continue;
  574. }
  575. if (STATESET_ISSET(lpDevI->transformstate_overrides, type))
  576. {
  577. D3D_WARN(5, "HEL D3DOP_STATETRANSFORM: state %d is overridden, ignoring", type);
  578. continue;
  579. }
  580. D3DMATRIXHANDLE hSrc = lpMset[i].dwArg[0];
  581. D3DMATRIX *lpSrcMat = (D3DMATRIX*)HANDLE_TO_MAT(lpDevI, hSrc);
  582. if (lpSrcMat == NULL)
  583. {
  584. // In DX5 days, this error was not propagated back.
  585. if (lpDevI->dwVersion <= 2)
  586. return D3D_OK;
  587. else
  588. {
  589. D3D_ERR("NULL srcMat in D3DHELInst_D3DOP_STATETRANSFORM");
  590. return (DDERR_INVALIDPARAMS);
  591. }
  592. }
  593. switch (type)
  594. {
  595. case D3DTRANSFORMSTATE_WORLD:
  596. D3DFE_SetMatrixWorld(lpDevI, lpSrcMat);
  597. TRANSFORM.hWorld = hSrc;
  598. break;
  599. case D3DTRANSFORMSTATE_VIEW:
  600. D3DFE_SetMatrixView(lpDevI, lpSrcMat);
  601. TRANSFORM.hView = hSrc;
  602. break;
  603. case D3DTRANSFORMSTATE_PROJECTION:
  604. D3DFE_SetMatrixProj(lpDevI, lpSrcMat);
  605. TRANSFORM.hProj = hSrc;
  606. break;
  607. default:
  608. D3D_ERR("Bad State in D3DopStateTransform emulation.");
  609. return DDERR_GENERIC;
  610. }
  611. }
  612. return (D3D_OK);
  613. }
  614. //---------------------------------------------------------------------
  615. #if DBG
  616. HRESULT validateProcessVertices(LPDIRECT3DDEVICEI lpDevI,
  617. LPD3DPROCESSVERTICES data)
  618. {
  619. LPD3DHAL_GLOBALDRIVERDATA lpGlob = lpDevI->lpD3DHALGlobalDriverData;
  620. unsigned int vnum;
  621. vnum = (unsigned int)(lpGlob->dwNumVertices ? lpGlob->dwNumVertices :
  622. D3DHAL_DEFAULT_TL_NUM);
  623. if (data->wDest >= vnum) {
  624. D3D_ERR("Dest index to large for Execute Buffer.");
  625. return DDERR_INVALIDPARAMS;
  626. } else if ((data->wDest + data->dwCount) > vnum) {
  627. D3D_ERR("Process vertices exceeds Execute Buffer size.");
  628. return DDERR_INVALIDPARAMS;
  629. }
  630. return D3D_OK;
  631. }
  632. #endif
  633. //---------------------------------------------------------------------
  634. HRESULT D3DHELInst_D3DOP_TRANSFORM(LPDIRECT3DDEVICEI lpDevI,
  635. DWORD count,
  636. LPD3DPROCESSVERTICES data,
  637. LPD3DEXECUTEBUFFERDESC eb)
  638. {
  639. LPD3DTLVERTEX lpTlv;
  640. DWORD i;
  641. DWORD op;
  642. HRESULT ret = DD_OK;
  643. lpDevI->primType = D3DPT_TRIANGLELIST;
  644. lpDevI->dwOutputSize = sizeof(D3DVERTEX);
  645. lpDevI->position.dwStride = sizeof(D3DVERTEX);
  646. lpDevI->nTexCoord = 1;
  647. for (i = 0; i < count; i++)
  648. {
  649. #if DBG
  650. if ((ret = validateProcessVertices(lpDevI, data)))
  651. return ret;
  652. #endif
  653. int nVertices = data->wDest+data->dwCount;
  654. lpTlv = (LPD3DTLVERTEX)lpDevI->TLVbuf.GetAddress();
  655. lpDevI->dwNumVertices = data->dwCount;
  656. lpDevI->position.lpvData = ((char*)eb->lpData) +
  657. data->wStart * sizeof(D3DVERTEX);
  658. lpDevI->lpvOut = lpTlv + data->wDest;
  659. /*
  660. * Transform the vertices
  661. */
  662. op = data->dwFlags & D3DPROCESSVERTICES_OPMASK;
  663. if (op == D3DPROCESSVERTICES_COPY)
  664. {
  665. lpDevI->dwVIDIn = d3dVertexToFVF[D3DVT_TLVERTEX];
  666. memcpy(lpDevI->lpvOut, lpDevI->position.lpvData,
  667. data->dwCount * sizeof(D3DVERTEX));
  668. D3DFE_updateExtents(lpDevI);
  669. D3D_INFO(4, "TLVERTEX encountered. Will not clip.");
  670. lpDevI->dwFEFlags |= D3DFE_TLVERTEX;
  671. // Apply ramp post-lighting stuff only for D3DTLVERTEX.
  672. // For other vertex types this is done in the transformation loop
  673. //
  674. if (lpDevI->pfnRampService != NULL)
  675. {
  676. ConvertColorsToRamp(lpDevI, (D3DTLVERTEX*)lpDevI->lpvOut,
  677. (D3DTLVERTEX*)lpDevI->lpvOut, data->dwCount);
  678. }
  679. lpDevI->iClipStatus &= ~D3DSTATUS_CLIPINTERSECTIONALL;
  680. }
  681. else
  682. {
  683. if (op == D3DPROCESSVERTICES_TRANSFORMLIGHT)
  684. {
  685. lpDevI->dwVIDIn = d3dVertexToFVF[D3DVT_VERTEX];
  686. lpDevI->dwFlags |= D3DPV_LIGHTING;
  687. }
  688. else
  689. {
  690. lpDevI->dwVIDIn = d3dVertexToFVF[D3DVT_LVERTEX];
  691. }
  692. if (lpDevI->dwFlags & D3DDP_DONOTCLIP)
  693. {
  694. D3DFE_ProcessVertices(lpDevI);
  695. lpDevI->iClipStatus &= ~D3DSTATUS_CLIPINTERSECTIONALL;
  696. }
  697. else
  698. {
  699. lpDevI->lpClipFlags = (D3DFE_CLIPCODE*)lpDevI->HVbuf.GetAddress() +
  700. data->wDest;
  701. D3DFE_ProcessVertices(lpDevI);
  702. D3DFE_UpdateClipStatus(lpDevI);
  703. D3D_INFO(4, "Status Change -> Clip flags. status = %08x", lpDevI->iClipStatus);
  704. // Restore initial value for lpClipFlags
  705. lpDevI->lpClipFlags = (D3DFE_CLIPCODE*)lpDevI->HVbuf.GetAddress();
  706. }
  707. }
  708. /* update stats
  709. */
  710. lpDevI->D3DStats.dwVerticesProcessed += data->dwCount;
  711. data++;
  712. }
  713. //out_of_here:
  714. return (ret);
  715. }
  716. //--------------------------------------------------------------------
  717. inline HRESULT GrowTLandHbuffers(LPDIRECT3DDEVICEI lpDevI, DWORD dwUsedVertexCount)
  718. {
  719. HRESULT ddrval;
  720. if (dwUsedVertexCount > 4096)
  721. dwUsedVertexCount = 4096;
  722. else
  723. if (dwUsedVertexCount < lpDevI->lpD3DHALGlobalDriverData->hwCaps.dwMaxVertexCount)
  724. dwUsedVertexCount = lpDevI->lpD3DHALGlobalDriverData->hwCaps.dwMaxVertexCount;
  725. ddrval = lpDevI->TLVbuf.CheckAndGrow(lpDevI, dwUsedVertexCount << 5);
  726. if (ddrval != D3D_OK)
  727. {
  728. D3D_ERR("Failed to check and grow TLVbuf in Execute");
  729. return ddrval;
  730. }
  731. ddrval = lpDevI->HVbuf.CheckAndGrow(dwUsedVertexCount*sizeof(D3DFE_CLIPCODE));
  732. if (ddrval != D3D_OK)
  733. {
  734. D3D_ERR("Failed to check and grow HVbuf in Execute");
  735. return ddrval;
  736. }
  737. return D3D_OK;
  738. }
  739. //--------------------------------------------------------------------
  740. //
  741. #define WAIT_FOR_FLIP() \
  742. if (!waitedForFlip) \
  743. { \
  744. WaitForFlip(lpDDS); \
  745. waitedForFlip = TRUE; \
  746. }
  747. HRESULT
  748. CDirect3DDeviceIHW::ExecuteI(LPD3DI_EXECUTEDATA lpExData, DWORD mode)
  749. {
  750. BOOL waitedForFlip = FALSE;
  751. D3DINSTRUCTION* lpIns;
  752. D3DHAL_RENDERSTATEDATA stateData;
  753. D3DHAL_RENDERPRIMITIVEDATA primitiveData;
  754. D3DEXECUTEBUFFERDESC debDesc;
  755. LPDIRECTDRAWSURFACE lpDDS = this->lpDDSTarget;
  756. LPBYTE prim;
  757. D3DFE_TRANSFORM *transform = &this->transform;
  758. LPDIRECTDRAWSURFACE lpDDExeBuf;
  759. HRESULT ddrval;
  760. CHECKLOST(this);
  761. // Do we need to map new texture stage operations to DX5 renderstates?
  762. if(this->dwFEFlags & D3DFE_MAP_TSS_TO_RS) {
  763. MapTSSToRS();
  764. this->dwFEFlags &= ~D3DFE_MAP_TSS_TO_RS; // Reset request bit
  765. }
  766. /* Update textures */
  767. UpdateTextures();
  768. if (mode == D3DEXECUTE_UNCLIPPED)
  769. this->dwFlags |= D3DDP_DONOTCLIP;
  770. else if (mode != D3DEXECUTE_CLIPPED)
  771. return DDERR_INVALIDPARAMS;
  772. /*
  773. * If the driver can process triangles while the hardware has a
  774. * pending page-flip such as the 3Dfx voodoo chipset, then we
  775. * don't need to call WaitForFlip. We pretend that it has already
  776. * been called to keep the code simple.
  777. */
  778. if (this->lpD3DHALGlobalDriverData->hwCaps.dwDevCaps &
  779. D3DDEVCAPS_CANRENDERAFTERFLIP)
  780. {
  781. waitedForFlip = TRUE;
  782. }
  783. /*
  784. * Lock the HAL for the duration.
  785. */
  786. LOCK_HAL(ddrval, this);
  787. if (ddrval != DD_OK)
  788. {
  789. D3D_ERR("Failed to lock HAL in Execute");
  790. return (ddrval);
  791. }
  792. #if _D3D_FORCEDOUBLE
  793. CD3DForceFPUDouble ForceFPUDouble(this);
  794. #endif //_D3D_FORCEDOUBLE
  795. /*
  796. * Execute the buffer through the HAL
  797. */
  798. {
  799. LPD3DHAL_EXDATA hexData = (LPD3DHAL_EXDATA) lpExData->dwHandle;
  800. debDesc.lpData = SURFACE_MEMORY(hexData->lpDDS);
  801. lpDDExeBuf = hexData->lpDDS;
  802. }
  803. memset(&stateData, 0, sizeof(D3DHAL_RENDERSTATEDATA));
  804. stateData.dwhContext = this->dwhContext;
  805. stateData.lpExeBuf = lpDDExeBuf;
  806. memset(&primitiveData, 0, sizeof(D3DHAL_RENDERPRIMITIVEDATA));
  807. primitiveData.dwhContext = this->dwhContext;
  808. primitiveData.lpExeBuf = lpDDExeBuf;
  809. primitiveData.dwTLOffset = 0L;
  810. this->ClipperState.lpDDExeBuf = lpDDExeBuf;
  811. this->ClipperState.lpvExeBufMem = debDesc.lpData;
  812. // Modify driver funcs for EB case
  813. PFN_DRAWPRIM pfnOldDrawPrim = this->pfnDrawPrim;
  814. PFN_DRAWPRIM pfnOldDrawIndexedPrim = this->pfnDrawIndexedPrim;
  815. this->pfnDrawPrim = &DIRECT3DDEVICEI::DrawExeBuf;
  816. this->pfnDrawIndexedPrim = &DIRECT3DDEVICEI::DrawExeBuf;
  817. /*
  818. * The first instruction.
  819. */
  820. lpIns = (LPD3DINSTRUCTION)((LPBYTE)debDesc.lpData +
  821. lpExData->dwInstructionOffset);
  822. ddrval = GrowTLandHbuffers(this, lpExData->dwVertexCount);
  823. if (ddrval != D3D_OK)
  824. goto execute_failed;
  825. // do this after CheckAndGrow, because TL buffer could be re-created
  826. primitiveData.lpTLBuf = this->TLVbuf.GetDDS();
  827. while (lpIns->bOpcode != D3DOP_EXIT)
  828. {
  829. prim = (LPBYTE)lpIns + sizeof(D3DINSTRUCTION);
  830. D3D_INFO(5, "HAL parsing instruction %d", lpIns->bOpcode);
  831. /*
  832. * Parse the instruction.
  833. */
  834. switch (lpIns->bOpcode)
  835. {
  836. case D3DOP_MATRIXLOAD:
  837. {
  838. D3D_INFO(5, "Emulating D3DOP_MATRIXLOAD for HAL");
  839. ddrval = D3DHELInst_D3DOP_MATRIXLOAD(this,
  840. lpIns->wCount,
  841. (LPD3DMATRIXLOAD)prim);
  842. if (ddrval != D3D_OK)
  843. {
  844. D3D_ERR("Emulated D3DOP_MATRIXLOAD failed.");
  845. goto execute_failed;
  846. }
  847. NEXTINSTRUCTION(lpIns, D3DMATRIXLOAD, lpIns->wCount);
  848. break;
  849. }
  850. case D3DOP_MATRIXMULTIPLY:
  851. {
  852. D3D_INFO(5, "Emulating D3DOP_MATRIXMULTIPLY for HAL");
  853. ddrval = D3DHELInst_D3DOP_MATRIXMULTIPLY(this,
  854. lpIns->wCount,
  855. (LPD3DMATRIXMULTIPLY)prim);
  856. if (ddrval != D3D_OK)
  857. {
  858. D3D_ERR("Emulated D3DOP_MATRIXMULTIPLY failed.");
  859. goto execute_failed;
  860. }
  861. NEXTINSTRUCTION(lpIns, D3DMATRIXMULTIPLY, lpIns->wCount);
  862. break;
  863. }
  864. case D3DOP_PROCESSVERTICES:
  865. {
  866. D3D_INFO(5, "Emulating D3DOP_PROCESSVERTICES for HAL");
  867. ddrval = D3DHELInst_D3DOP_TRANSFORM
  868. (this, lpIns->wCount, (LPD3DPROCESSVERTICES)prim,
  869. &debDesc);
  870. if (ddrval != D3D_OK)
  871. {
  872. D3D_ERR("Emulated D3DOP_PROCESSVERTICES failed.");
  873. goto execute_failed;
  874. }
  875. NEXTINSTRUCTION(lpIns, D3DPROCESSVERTICES, lpIns->wCount);
  876. break;
  877. }
  878. case D3DOP_STATETRANSFORM:
  879. {
  880. D3D_INFO(5, "Emulating D3DOP_STATETRANSFORM for HAL");
  881. ddrval = D3DHELInst_D3DOP_STATETRANSFORM(this,
  882. lpIns->wCount,
  883. (LPD3DSTATE)prim);
  884. if (ddrval != D3D_OK)
  885. {
  886. D3D_ERR("Emulated D3DOP_STATETRANSFORM failed.");
  887. goto execute_failed;
  888. }
  889. NEXTINSTRUCTION(lpIns, D3DSTATE, lpIns->wCount);
  890. break;
  891. }
  892. case D3DOP_STATELIGHT:
  893. {
  894. D3D_INFO(5, "Emulating D3DOP_STATELIGHT for HAL");
  895. ddrval = D3DHELInst_D3DOP_STATELIGHT(this,
  896. lpIns->wCount,
  897. (LPD3DSTATE)prim);
  898. if (ddrval != D3D_OK) {
  899. D3D_ERR("Emulated D3DOP_STATELIGHT failed.");
  900. goto execute_failed;
  901. }
  902. NEXTINSTRUCTION(lpIns, D3DSTATE, lpIns->wCount);
  903. break;
  904. }
  905. case D3DOP_BRANCHFORWARD:
  906. {
  907. D3DBRANCH* branch = (D3DBRANCH*)prim;
  908. LPBYTE target;
  909. BOOL isTaken = FALSE;
  910. D3D_INFO(5, "Emulating D3DOP_BRANCHFORWARD");
  911. if (branch->bNegate)
  912. {
  913. if ((branch->dwMask & this->iClipStatus) != branch->dwValue)
  914. {
  915. D3D_INFO(4, "Taking forward branch");
  916. if (branch->dwOffset)
  917. {
  918. isTaken = TRUE;
  919. target = (LPBYTE)lpIns + branch->dwOffset;
  920. }
  921. else
  922. {
  923. D3D_INFO(4, "branch says to exit.");
  924. goto execute_done;
  925. }
  926. }
  927. }
  928. else
  929. {
  930. if ((branch->dwMask & this->iClipStatus) == branch->dwValue)
  931. {
  932. D3D_INFO(4, "Taking forward branch");
  933. if (branch->dwOffset)
  934. {
  935. isTaken = TRUE;
  936. target = (LPBYTE)lpIns + branch->dwOffset;
  937. } else
  938. {
  939. D3D_INFO(2, "branch says to exit.");
  940. goto execute_done;
  941. }
  942. }
  943. }
  944. if (isTaken)
  945. {
  946. D3D_INFO(5, "D3DOP_BRANCHFORWARD instruction: branch taken");
  947. lpIns = (LPD3DINSTRUCTION) target;
  948. }
  949. else
  950. {
  951. D3D_INFO(5, "D3DOP_BRANCHFORWARD instruction: branch not taken");
  952. NEXTINSTRUCTION(lpIns, D3DBRANCH, lpIns->wCount);
  953. }
  954. break;
  955. }
  956. case D3DOP_TEXTURELOAD:
  957. {
  958. D3D_INFO(5, "Emulating D3DOP_TEXTURELOAD for HAL");
  959. ddrval = D3DHELInst_D3DOP_TEXTURELOAD(this,
  960. lpIns->wCount,
  961. (LPD3DTEXTURELOAD)prim);
  962. if (ddrval != D3D_OK)
  963. {
  964. D3D_ERR("Emulated D3DOP_TEXTURELOAD failed.");
  965. goto execute_failed;
  966. }
  967. NEXTINSTRUCTION(lpIns, D3DTEXTURELOAD, lpIns->wCount);
  968. break;
  969. }
  970. case D3DOP_STATERENDER:
  971. {
  972. LPD3DSTATE lpState;
  973. DWORD i,j,statek,valuek;
  974. lpState = (LPD3DSTATE) (lpIns + 1);
  975. for (i = 0,j=0,statek=(DWORD)-1; i < lpIns->wCount; i++)
  976. {
  977. trackState(this, &lpState[i]);
  978. }
  979. stateData.dwOffset = (DWORD)(prim - (LPBYTE) debDesc.lpData);
  980. stateData.dwCount = lpIns->wCount;
  981. CALL_HALONLY_NOLOCK(ddrval, this, RenderState, &stateData);
  982. if (stateData.ddrval != DD_OK)
  983. {
  984. D3D_ERR("HAL error in RenderState call from Execute API");
  985. ddrval = stateData.ddrval;
  986. goto execute_failed;
  987. }
  988. NEXTINSTRUCTION(lpIns, D3DSTATE, lpIns->wCount);
  989. break;
  990. }
  991. case D3DOP_SETSTATUS:
  992. {
  993. LPD3DSTATUS status = (LPD3DSTATUS)prim;
  994. if (status->dwFlags & D3DSETSTATUS_STATUS)
  995. this->iClipStatus = status->dwStatus;
  996. if (status->dwFlags & D3DSETSTATUS_EXTENTS)
  997. {
  998. this->rExtents.x1 = D3DVAL(status->drExtent.x1);
  999. this->rExtents.y1 = D3DVAL(status->drExtent.y1);
  1000. this->rExtents.x2 = D3DVAL(status->drExtent.x2);
  1001. this->rExtents.y2 = D3DVAL(status->drExtent.y2);
  1002. }
  1003. NEXTINSTRUCTION(lpIns, D3DSTATUS, lpIns->wCount);
  1004. break;
  1005. }
  1006. default:
  1007. if (mode == D3DEXECUTE_UNCLIPPED || this->dwFEFlags & D3DFE_TLVERTEX)
  1008. {
  1009. switch (lpIns->bOpcode)
  1010. {
  1011. case D3DOP_POINT:
  1012. case D3DOP_LINE:
  1013. case D3DOP_SPAN:
  1014. case D3DOP_TRIANGLE:
  1015. {
  1016. if (lpIns->wCount == 0)
  1017. goto noprim;
  1018. #if DBG
  1019. switch (lpIns->bOpcode)
  1020. {
  1021. case D3DOP_POINT:
  1022. Profile(PROF_EXECUTE, D3DPT_POINTLIST, GetVertexType(this));
  1023. break;
  1024. case D3DOP_LINE:
  1025. Profile(PROF_EXECUTE, D3DPT_LINELIST, GetVertexType(this));
  1026. break;
  1027. case D3DOP_TRIANGLE:
  1028. Profile(PROF_EXECUTE, D3DPT_TRIANGLELIST, GetVertexType(this));
  1029. break;
  1030. }
  1031. #endif // DBG
  1032. if (!waitedForFlip)
  1033. {
  1034. WaitForFlip(lpDDS);
  1035. waitedForFlip = TRUE;
  1036. }
  1037. primitiveData.dwOffset = (DWORD)(prim - (LPBYTE) debDesc.lpData);
  1038. primitiveData.dwStatus = this->iClipStatus;
  1039. primitiveData.diInstruction = *lpIns;
  1040. #ifndef WIN95
  1041. if((ddrval = CheckContextSurfaceNOLOCK (this)) != D3D_OK)
  1042. {
  1043. goto execute_failed;
  1044. }
  1045. #endif //WIN95
  1046. CALL_HALONLY_NOLOCK(ddrval, this, RenderPrimitive,
  1047. &primitiveData);
  1048. if (primitiveData.ddrval != DD_OK)
  1049. {
  1050. D3D_ERR("HAL error in RenderPrimitive call from Execute API");
  1051. ddrval = primitiveData.ddrval;
  1052. goto execute_failed;
  1053. }
  1054. switch (lpIns->bOpcode)
  1055. {
  1056. int i;
  1057. case D3DOP_LINE:
  1058. this->D3DStats.dwLinesDrawn += lpIns->wCount;
  1059. break;
  1060. case D3DOP_TRIANGLE:
  1061. #if DBG
  1062. if (!validateTriangleFlags(lpIns, (LPD3DTRIANGLE) prim))
  1063. {
  1064. ddrval = DDERR_INVALIDPARAMS;
  1065. goto execute_failed;
  1066. }
  1067. #endif
  1068. this->D3DStats.dwTrianglesDrawn += lpIns->wCount;
  1069. break;
  1070. case D3DOP_POINT:
  1071. {
  1072. LPD3DPOINT point = (LPD3DPOINT)prim;
  1073. for (i = 0; i < lpIns->wCount; i++)
  1074. {
  1075. this->D3DStats.dwPointsDrawn += point->wCount;
  1076. point++;
  1077. }
  1078. }
  1079. break;
  1080. case D3DOP_SPAN:
  1081. {
  1082. LPD3DSPAN span = (LPD3DSPAN)prim;
  1083. for (i = 0; i < lpIns->wCount; i++)
  1084. {
  1085. this->D3DStats.dwSpansDrawn += span->wCount;
  1086. span++;
  1087. }
  1088. }
  1089. break;
  1090. }
  1091. this->iClipStatus = primitiveData.dwStatus;
  1092. noprim:
  1093. lpIns = (LPD3DINSTRUCTION)((LPBYTE)lpIns +
  1094. sizeof(D3DINSTRUCTION) +
  1095. (lpIns->bSize * lpIns->wCount));
  1096. break;
  1097. }
  1098. default:
  1099. D3D_ERR("HAL detected invalid instruction opcode in Execute");
  1100. goto execute_failed;
  1101. }
  1102. }
  1103. else
  1104. {
  1105. switch (lpIns->bOpcode)
  1106. {
  1107. case D3DOP_TRIANGLE:
  1108. if (lpIns->wCount == 0)
  1109. {
  1110. NEXTINSTRUCTION(lpIns, D3DTRIANGLE, lpIns->wCount);
  1111. break;
  1112. }
  1113. Profile(PROF_EXECUTE, D3DPT_TRIANGLELIST, GetVertexType(this));
  1114. WAIT_FOR_FLIP();
  1115. #if DBG
  1116. if (!validateTriangleFlags(lpIns, (LPD3DTRIANGLE) prim))
  1117. {
  1118. ddrval = DDERR_INVALIDPARAMS;
  1119. goto execute_failed;
  1120. }
  1121. #endif
  1122. this->D3DStats.dwTrianglesDrawn += lpIns->wCount;
  1123. D3D_INFO(5, "Emulating D3DOP_TRIANGLE for HAL and clipping");
  1124. ddrval = D3DFEClipTrianglesHW(this, (LPD3DTRIANGLE)prim, lpIns->wCount);
  1125. if (ddrval != D3D_OK)
  1126. {
  1127. D3D_ERR("D3DFEClipTrianglesHW failed");
  1128. goto execute_failed;
  1129. }
  1130. NEXTINSTRUCTION(lpIns, D3DTRIANGLE, lpIns->wCount);
  1131. break;
  1132. case D3DOP_LINE:
  1133. if (lpIns->wCount == 0)
  1134. {
  1135. NEXTINSTRUCTION(lpIns, D3DLINE, lpIns->wCount);
  1136. break;
  1137. }
  1138. Profile(PROF_EXECUTE, D3DPT_LINELIST, GetVertexType(this));
  1139. WAIT_FOR_FLIP();
  1140. D3D_INFO(5, "Emulating D3DOP_LINE for HAL and clipping");
  1141. this->D3DStats.dwLinesDrawn += lpIns->wCount;
  1142. ddrval = D3DFEClipLinesHW(this, (LPD3DLINE)prim, lpIns->wCount);
  1143. if (ddrval != D3D_OK)
  1144. {
  1145. D3D_ERR("D3DFEClipLinesHW failed");
  1146. goto execute_failed;
  1147. }
  1148. NEXTINSTRUCTION(lpIns, D3DLINE, lpIns->wCount);
  1149. break;
  1150. case D3DOP_POINT:
  1151. WAIT_FOR_FLIP();
  1152. Profile(PROF_EXECUTE, D3DPT_POINTLIST, GetVertexType(this));
  1153. D3D_INFO(5, "Emulating D3DOP_POINT for HAL and clipping");
  1154. {
  1155. LPD3DPOINT point = (LPD3DPOINT) prim;
  1156. int i;
  1157. for (i = 0; i < lpIns->wCount; i++)
  1158. {
  1159. this->D3DStats.dwPointsDrawn += point->wCount;
  1160. point++;
  1161. }
  1162. }
  1163. if ((ddrval = D3DFEClipPointsHW(this, (LPD3DPOINT)prim, lpIns->wCount)) != D3D_OK)
  1164. {
  1165. D3D_ERR("Failed D3DFEClipPointsHW");
  1166. goto execute_failed;
  1167. }
  1168. NEXTINSTRUCTION(lpIns, D3DPOINT, lpIns->wCount);
  1169. break;
  1170. case D3DOP_SPAN:
  1171. {
  1172. LPD3DSPAN span = (LPD3DSPAN)prim;
  1173. D3DHAL_RENDERPRIMITIVEDATA primitiveData;
  1174. int i;
  1175. WAIT_FOR_FLIP();
  1176. memset(&primitiveData, 0, sizeof(D3DHAL_RENDERPRIMITIVEDATA));
  1177. primitiveData.dwhContext = this->dwhContext;
  1178. primitiveData.lpExeBuf = lpDDExeBuf;
  1179. primitiveData.dwTLOffset = 0L;
  1180. primitiveData.lpTLBuf = this->TLVbuf.GetDDS();
  1181. primitiveData.dwOffset = (DWORD)(prim - (LPBYTE) debDesc.lpData);
  1182. primitiveData.dwStatus = this->iClipStatus;
  1183. primitiveData.diInstruction = *lpIns;
  1184. #ifndef WIN95
  1185. if((ddrval = CheckContextSurfaceNOLOCK(this)) != D3D_OK)
  1186. goto execute_failed;
  1187. #endif //WIN95
  1188. CALL_HALONLY_NOLOCK(ddrval, this, RenderPrimitive,
  1189. &primitiveData);
  1190. if (primitiveData.ddrval != DD_OK)
  1191. {
  1192. D3D_ERR("HAL error in RenderPrimitive call from Execute API");
  1193. ddrval = primitiveData.ddrval;
  1194. goto execute_failed;
  1195. }
  1196. for (i = 0; i < lpIns->wCount; i++)
  1197. {
  1198. this->D3DStats.dwSpansDrawn += span->wCount;
  1199. span++;
  1200. }
  1201. this->iClipStatus = primitiveData.dwStatus;
  1202. lpIns = (LPD3DINSTRUCTION)((LPBYTE)lpIns
  1203. + sizeof(D3DINSTRUCTION)
  1204. + (lpIns->bSize * lpIns->wCount));
  1205. break;
  1206. }
  1207. default:
  1208. D3D_ERR("HAL detected invalid instruction opcode in Execute");
  1209. goto execute_failed;
  1210. }
  1211. ClampExtents(this);
  1212. }
  1213. }
  1214. }
  1215. execute_done:
  1216. ddrval = D3D_OK;
  1217. D3DFE_ConvertExtent(this, &this->rExtents, &lpExData->dsStatus.drExtent);
  1218. lpExData->dsStatus.dwStatus = this->iClipStatus;
  1219. execute_failed:
  1220. UNLOCK_HAL(this);
  1221. // Restore driver funcs
  1222. this->pfnDrawIndexedPrim = pfnOldDrawIndexedPrim;
  1223. this->pfnDrawPrim = pfnOldDrawPrim;
  1224. return ddrval;
  1225. }
  1226. //-------------------------------------------------------------------------------------------------
  1227. void TrackAllStates(LPDIRECT3DDEVICEI lpDevI, LPD3DINSTRUCTION lpIns, LPD3DINSTRUCTION lpEnd)
  1228. {
  1229. while (lpIns->bOpcode != D3DOP_EXIT && (lpEnd == NULL || lpIns < lpEnd))
  1230. {
  1231. LPBYTE prim = (LPBYTE)lpIns + sizeof(D3DINSTRUCTION);
  1232. switch (lpIns->bOpcode)
  1233. {
  1234. case D3DOP_MATRIXLOAD:
  1235. {
  1236. NEXTINSTRUCTION(lpIns, D3DMATRIXLOAD, lpIns->wCount);
  1237. break;
  1238. }
  1239. case D3DOP_MATRIXMULTIPLY:
  1240. {
  1241. NEXTINSTRUCTION(lpIns, D3DMATRIXMULTIPLY, lpIns->wCount);
  1242. break;
  1243. }
  1244. case D3DOP_PROCESSVERTICES:
  1245. {
  1246. NEXTINSTRUCTION(lpIns, D3DPROCESSVERTICES, lpIns->wCount);
  1247. break;
  1248. }
  1249. case D3DOP_STATETRANSFORM:
  1250. {
  1251. NEXTINSTRUCTION(lpIns, D3DSTATE, lpIns->wCount);
  1252. break;
  1253. }
  1254. case D3DOP_STATELIGHT:
  1255. {
  1256. NEXTINSTRUCTION(lpIns, D3DSTATE, lpIns->wCount);
  1257. break;
  1258. }
  1259. case D3DOP_BRANCHFORWARD:
  1260. {
  1261. D3DBRANCH* branch = (D3DBRANCH*)prim;
  1262. LPBYTE target;
  1263. BOOL isTaken = FALSE;
  1264. if (branch->bNegate)
  1265. {
  1266. if ((branch->dwMask & lpDevI->iClipStatus) != branch->dwValue)
  1267. {
  1268. if (branch->dwOffset)
  1269. {
  1270. isTaken = TRUE;
  1271. target = (LPBYTE)lpIns + branch->dwOffset;
  1272. }
  1273. else
  1274. {
  1275. D3D_INFO(5, "D3DOP_BRANCHFORWARD instruction: branch says to exit.");
  1276. break;
  1277. }
  1278. }
  1279. }
  1280. else
  1281. {
  1282. if ((branch->dwMask & lpDevI->iClipStatus) == branch->dwValue)
  1283. {
  1284. if (branch->dwOffset)
  1285. {
  1286. isTaken = TRUE;
  1287. target = (LPBYTE)lpIns + branch->dwOffset;
  1288. } else
  1289. {
  1290. break;
  1291. }
  1292. }
  1293. }
  1294. if (isTaken)
  1295. {
  1296. lpIns = (LPD3DINSTRUCTION) target;
  1297. }
  1298. else
  1299. {
  1300. NEXTINSTRUCTION(lpIns, D3DBRANCH, lpIns->wCount);
  1301. }
  1302. break;
  1303. }
  1304. case D3DOP_TEXTURELOAD:
  1305. {
  1306. NEXTINSTRUCTION(lpIns, D3DTEXTURELOAD, lpIns->wCount);
  1307. break;
  1308. }
  1309. case D3DOP_SETSTATUS:
  1310. {
  1311. NEXTINSTRUCTION(lpIns, D3DSTATUS, lpIns->wCount);
  1312. break;
  1313. }
  1314. case D3DOP_STATERENDER:
  1315. {
  1316. LPD3DSTATE lpState;
  1317. DWORD i,j,statek,valuek;
  1318. lpState = (LPD3DSTATE) (lpIns + 1);
  1319. for (i = 0,j=0,statek=(DWORD)-1; i < lpIns->wCount; i++)
  1320. {
  1321. trackState(lpDevI, &lpState[i]);
  1322. }
  1323. NEXTINSTRUCTION(lpIns, D3DSTATE, lpIns->wCount);
  1324. }
  1325. break;
  1326. case D3DOP_TRIANGLE:
  1327. NEXTINSTRUCTION(lpIns, D3DTRIANGLE, lpIns->wCount);
  1328. break;
  1329. case D3DOP_LINE:
  1330. NEXTINSTRUCTION(lpIns, D3DLINE, lpIns->wCount);
  1331. break;
  1332. case D3DOP_POINT:
  1333. NEXTINSTRUCTION(lpIns, D3DPOINT, lpIns->wCount);
  1334. break;
  1335. case D3DOP_SPAN:
  1336. // This case is NOOP since we do not implement spans in DP2 DDI
  1337. {
  1338. lpIns = (LPD3DINSTRUCTION)((LPBYTE)lpIns
  1339. + sizeof(D3DINSTRUCTION)
  1340. + (lpIns->bSize * lpIns->wCount));
  1341. break;
  1342. }
  1343. default:
  1344. D3D_ERR("Invalid instruction opcode in TrackAllStates");
  1345. break;
  1346. } // switch
  1347. } // while
  1348. }
  1349. //-------------------------------------------------------------------------------------------------
  1350. // New execute for DP2 HAL
  1351. //
  1352. HRESULT
  1353. CDirect3DDeviceIDP2::ExecuteI(LPD3DI_EXECUTEDATA lpExData, DWORD mode)
  1354. {
  1355. BOOL waitedForFlip = FALSE;
  1356. D3DINSTRUCTION* lpIns;
  1357. D3DEXECUTEBUFFERDESC debDesc;
  1358. LPDIRECTDRAWSURFACE lpDDS = this->lpDDSTarget;
  1359. LPBYTE prim;
  1360. D3DFE_TRANSFORM *transform = &this->transform;
  1361. LPDIRECTDRAWSURFACE lpDDExeBuf;
  1362. HRESULT ddrval, dp2dataddrval;
  1363. CHECKLOST(this);
  1364. /* Update textures */
  1365. UpdateTextures();
  1366. if (mode == D3DEXECUTE_UNCLIPPED)
  1367. this->dwFlags |= D3DDP_DONOTCLIP;
  1368. else if (mode != D3DEXECUTE_CLIPPED)
  1369. return DDERR_INVALIDPARAMS;
  1370. /*
  1371. * If the driver can process triangles while the hardware has a
  1372. * pending page-flip such as the 3Dfx voodoo chipset, then we
  1373. * don't need to call WaitForFlip. We pretend that it has already
  1374. * been called to keep the code simple.
  1375. */
  1376. if (this->lpD3DHALGlobalDriverData->hwCaps.dwDevCaps &
  1377. D3DDEVCAPS_CANRENDERAFTERFLIP)
  1378. {
  1379. waitedForFlip = TRUE;
  1380. }
  1381. /*
  1382. * Lock the HAL for the duration.
  1383. */
  1384. LOCK_HAL(ddrval, this);
  1385. if (ddrval != DD_OK)
  1386. {
  1387. D3D_ERR("Failed to lock HAL in Execute");
  1388. return (ddrval);
  1389. }
  1390. /*
  1391. * Execute the buffer through the HAL
  1392. */
  1393. LPD3DHAL_EXDATA hexData = (LPD3DHAL_EXDATA) lpExData->dwHandle;
  1394. debDesc.lpData = SURFACE_MEMORY(hexData->lpDDS);
  1395. lpDDExeBuf = hexData->lpDDS;
  1396. /*
  1397. * The first instruction.
  1398. */
  1399. lpIns = (LPD3DINSTRUCTION)((LPBYTE)debDesc.lpData +
  1400. lpExData->dwInstructionOffset);
  1401. // Fill up common part of dp2Data
  1402. this->dp2data.dwVertexType = D3DFVF_TLVERTEX;
  1403. this->dp2data.dwVertexSize = sizeof(D3DTLVERTEX);
  1404. this->dp2data.dwVertexOffset = 0;
  1405. ddrval = GrowTLandHbuffers(this, lpExData->dwVertexCount);
  1406. if (ddrval != D3D_OK)
  1407. goto execute_failed;
  1408. this->dwOutputSize = sizeof(D3DTLVERTEX);
  1409. // Start new primitive batch
  1410. ddrval= StartPrimVB(this->TLVbuf.GetVBI(), 0);
  1411. if (ddrval != D3D_OK)
  1412. {
  1413. UNLOCK_HAL(this);
  1414. D3D_ERR("Failed to start new primitve batch in Execute");
  1415. return ddrval;
  1416. }
  1417. // Since many legacy apps do not bother to set the dwVertexLength correctly, we estimate
  1418. // the vertex length here to be thse size of buffer allocated. This atleast guarantees
  1419. // that the memory is valid. It may still contain garbage data which the driver needs
  1420. // to protect itself from
  1421. this->dp2data.dwVertexLength = this->TLVbuf.GetSize() >> 5; // divide by sizeof(D3DTLVERTEX)
  1422. this->ClipperState.lpDDExeBuf = lpDDExeBuf;
  1423. this->ClipperState.lpvExeBufMem = debDesc.lpData;
  1424. while (lpIns->bOpcode != D3DOP_EXIT)
  1425. {
  1426. prim = (LPBYTE)lpIns + sizeof(D3DINSTRUCTION);
  1427. D3D_INFO(5, "HAL parsing instruction %d", lpIns->bOpcode);
  1428. /*
  1429. * Parse the instruction.
  1430. */
  1431. switch (lpIns->bOpcode)
  1432. {
  1433. case D3DOP_MATRIXLOAD:
  1434. {
  1435. D3D_INFO(5, "Emulating D3DOP_MATRIXLOAD for HAL");
  1436. ddrval = D3DHELInst_D3DOP_MATRIXLOAD(this,
  1437. lpIns->wCount,
  1438. (LPD3DMATRIXLOAD)prim);
  1439. if (ddrval != D3D_OK)
  1440. {
  1441. D3D_ERR("Emulated D3DOP_MATRIXLOAD failed.");
  1442. goto execute_failed;
  1443. }
  1444. NEXTINSTRUCTION(lpIns, D3DMATRIXLOAD, lpIns->wCount);
  1445. break;
  1446. }
  1447. case D3DOP_MATRIXMULTIPLY:
  1448. {
  1449. D3D_INFO(5, "Emulating D3DOP_MATRIXMULTIPLY for HAL");
  1450. ddrval = D3DHELInst_D3DOP_MATRIXMULTIPLY(this,
  1451. lpIns->wCount,
  1452. (LPD3DMATRIXMULTIPLY)prim);
  1453. if (ddrval != D3D_OK)
  1454. {
  1455. D3D_ERR("Emulated D3DOP_MATRIXMULTIPLY failed.");
  1456. goto execute_failed;
  1457. }
  1458. NEXTINSTRUCTION(lpIns, D3DMATRIXMULTIPLY, lpIns->wCount);
  1459. break;
  1460. }
  1461. case D3DOP_PROCESSVERTICES:
  1462. {
  1463. D3D_INFO(5, "Emulating D3DOP_PROCESSVERTICES for HAL");
  1464. ddrval = D3DHELInst_D3DOP_TRANSFORM
  1465. (this, lpIns->wCount, (LPD3DPROCESSVERTICES)prim,
  1466. &debDesc);
  1467. if (ddrval != D3D_OK)
  1468. {
  1469. D3D_ERR("Emulated D3DOP_PROCESSVERTICES failed.");
  1470. goto execute_failed;
  1471. }
  1472. NEXTINSTRUCTION(lpIns, D3DPROCESSVERTICES, lpIns->wCount);
  1473. break;
  1474. }
  1475. case D3DOP_STATETRANSFORM:
  1476. {
  1477. D3D_INFO(5, "Emulating D3DOP_STATETRANSFORM for HAL");
  1478. ddrval = D3DHELInst_D3DOP_STATETRANSFORM(this,
  1479. lpIns->wCount,
  1480. (LPD3DSTATE)prim);
  1481. if (ddrval != D3D_OK)
  1482. {
  1483. D3D_ERR("Emulated D3DOP_STATETRANSFORM failed.");
  1484. goto execute_failed;
  1485. }
  1486. NEXTINSTRUCTION(lpIns, D3DSTATE, lpIns->wCount);
  1487. break;
  1488. }
  1489. case D3DOP_STATELIGHT:
  1490. {
  1491. D3D_INFO(5, "Emulating D3DOP_STATELIGHT for HAL");
  1492. ddrval = D3DHELInst_D3DOP_STATELIGHT(this,
  1493. lpIns->wCount,
  1494. (LPD3DSTATE)prim);
  1495. if (ddrval != D3D_OK) {
  1496. D3D_ERR("Emulated D3DOP_STATELIGHT failed.");
  1497. goto execute_failed;
  1498. }
  1499. NEXTINSTRUCTION(lpIns, D3DSTATE, lpIns->wCount);
  1500. break;
  1501. }
  1502. case D3DOP_BRANCHFORWARD:
  1503. {
  1504. D3DBRANCH* branch = (D3DBRANCH*)prim;
  1505. LPBYTE target;
  1506. BOOL isTaken = FALSE;
  1507. D3D_INFO(5, "Emulating D3DOP_BRANCHFORWARD");
  1508. if (branch->bNegate)
  1509. {
  1510. if ((branch->dwMask & this->iClipStatus) != branch->dwValue)
  1511. {
  1512. D3D_INFO(5, "D3DOP_BRANCHFORWARD instruction: Taking forward branch");
  1513. if (branch->dwOffset)
  1514. {
  1515. isTaken = TRUE;
  1516. target = (LPBYTE)lpIns + branch->dwOffset;
  1517. }
  1518. else
  1519. {
  1520. D3D_INFO(5, "D3DOP_BRANCHFORWARD instruction: branch says to exit.");
  1521. goto execute_done;
  1522. }
  1523. }
  1524. }
  1525. else
  1526. {
  1527. D3D_INFO(5, "dwMask = %lx, iClipStatus = %lx, dwValue = %lx", branch->dwMask, this->iClipStatus, branch->dwValue);
  1528. if ((branch->dwMask & this->iClipStatus) == branch->dwValue)
  1529. {
  1530. D3D_INFO(5, "D3DOP_BRANCHFORWARD instruction: Taking forward branch");
  1531. if (branch->dwOffset)
  1532. {
  1533. isTaken = TRUE;
  1534. target = (LPBYTE)lpIns + branch->dwOffset;
  1535. } else
  1536. {
  1537. D3D_INFO(5, "D3DOP_BRANCHFORWARD instruction: branch says to exit.");
  1538. goto execute_done;
  1539. }
  1540. }
  1541. }
  1542. if (isTaken)
  1543. {
  1544. D3D_INFO(5, "D3DOP_BRANCHFORWARD instruction: branch taken");
  1545. lpIns = (LPD3DINSTRUCTION) target;
  1546. }
  1547. else
  1548. {
  1549. D3D_INFO(5, "D3DOP_BRANCHFORWARD instruction: branch not taken");
  1550. NEXTINSTRUCTION(lpIns, D3DBRANCH, lpIns->wCount);
  1551. }
  1552. break;
  1553. }
  1554. case D3DOP_TEXTURELOAD:
  1555. {
  1556. D3D_INFO(5, "Emulating D3DOP_TEXTURELOAD for HAL");
  1557. ddrval = D3DHELInst_D3DOP_TEXTURELOAD(this,
  1558. lpIns->wCount,
  1559. (LPD3DTEXTURELOAD)prim);
  1560. if (ddrval != D3D_OK)
  1561. {
  1562. D3D_ERR("Emulated D3DOP_TEXTURELOAD failed.");
  1563. goto execute_failed;
  1564. }
  1565. NEXTINSTRUCTION(lpIns, D3DTEXTURELOAD, lpIns->wCount);
  1566. break;
  1567. }
  1568. case D3DOP_SETSTATUS:
  1569. {
  1570. LPD3DSTATUS status = (LPD3DSTATUS)prim;
  1571. if (status->dwFlags & D3DSETSTATUS_STATUS)
  1572. this->iClipStatus = status->dwStatus;
  1573. if (status->dwFlags & D3DSETSTATUS_EXTENTS)
  1574. {
  1575. this->rExtents.x1 = D3DVAL(status->drExtent.x1);
  1576. this->rExtents.y1 = D3DVAL(status->drExtent.y1);
  1577. this->rExtents.x2 = D3DVAL(status->drExtent.x2);
  1578. this->rExtents.y2 = D3DVAL(status->drExtent.y2);
  1579. }
  1580. NEXTINSTRUCTION(lpIns, D3DSTATUS, lpIns->wCount);
  1581. break;
  1582. }
  1583. default:
  1584. if ((this->dwFEFlags & D3DFE_TLVERTEX) || (mode == D3DEXECUTE_UNCLIPPED))
  1585. {
  1586. switch (lpIns->bOpcode)
  1587. {
  1588. case D3DOP_STATERENDER:
  1589. case D3DOP_POINT:
  1590. case D3DOP_LINE:
  1591. case D3DOP_SPAN:
  1592. // ATTENTION
  1593. // We need to disallow SPAN from going through since the new DDI spec
  1594. // does not account for spans. We probably want to deprecate spans in
  1595. // any case so them being slower might not be too bad. Right now, though
  1596. // we are passing them to the driver.
  1597. case D3DOP_TRIANGLE:
  1598. #if DBG
  1599. switch (lpIns->bOpcode)
  1600. {
  1601. case D3DOP_POINT:
  1602. Profile(PROF_EXECUTE, D3DPT_POINTLIST, GetVertexType(this));
  1603. break;
  1604. case D3DOP_LINE:
  1605. Profile(PROF_EXECUTE, D3DPT_LINELIST, GetVertexType(this));
  1606. break;
  1607. case D3DOP_TRIANGLE:
  1608. Profile(PROF_EXECUTE, D3DPT_TRIANGLELIST, GetVertexType(this));
  1609. break;
  1610. }
  1611. #endif // DBG
  1612. if (lpIns->wCount == 0)
  1613. {
  1614. lpIns = (LPD3DINSTRUCTION)((LPBYTE)lpIns +
  1615. sizeof(D3DINSTRUCTION) +
  1616. (lpIns->bSize * lpIns->wCount));
  1617. break;
  1618. }
  1619. if (!waitedForFlip)
  1620. {
  1621. WaitForFlip(lpDDS);
  1622. waitedForFlip = TRUE;
  1623. }
  1624. this->dp2data.dwVertexType = D3DFVF_TLVERTEX;
  1625. this->dp2data.dwVertexSize = sizeof(D3DTLVERTEX);
  1626. this->dp2data.lpDDCommands = ((LPDDRAWI_DDRAWSURFACE_INT)lpDDExeBuf)->lpLcl;
  1627. this->dp2data.dwCommandOffset = (DWORD)((LPBYTE)lpIns - (LPBYTE) debDesc.lpData);
  1628. this->dp2data.dwCommandLength = lpExData->dwInstructionOffset + lpExData->dwInstructionLength -
  1629. this->dp2data.dwCommandOffset;
  1630. // Can't swap command buffer in this case
  1631. this->dp2data.dwFlags &= ~(D3DHALDP2_SWAPCOMMANDBUFFER | D3DHALDP2_SWAPVERTEXBUFFER);
  1632. this->dp2data.lpdwRStates = this->rstates;
  1633. #ifndef WIN95
  1634. if (!IS_DX7HAL_DEVICE(this))
  1635. {
  1636. if((ddrval = CheckContextSurfaceNOLOCK (this)) != D3D_OK)
  1637. {
  1638. goto execute_failed;
  1639. }
  1640. }
  1641. #endif //WIN95
  1642. // and tell driver to update lpdwRStates
  1643. this->dp2data.dwFlags |= D3DHALDP2_EXECUTEBUFFER;
  1644. // Spin waiting on the driver
  1645. do {
  1646. CALL_HAL3ONLY_NOLOCK(ddrval, this, DrawPrimitives2, &this->dp2data);
  1647. if (ddrval != DDHAL_DRIVER_HANDLED)
  1648. {
  1649. D3D_ERR ( "Driver not handled in DrawPrimitives2" );
  1650. // Need sensible return value in this case,
  1651. // currently we return whatever the driver stuck in here.
  1652. goto execute_failed;
  1653. }
  1654. } while (dp2data.ddrval == DDERR_WASSTILLDRAWING);
  1655. // restore right value of dwVertexSize as it is a union with ddrval
  1656. dp2dataddrval = this->dp2data.ddrval;
  1657. #if _WIN32_WINNT >= 0x0501
  1658. this->dp2data.dwVertexSize = sizeof(D3DTLVERTEX);
  1659. #endif
  1660. // clear this bit in case drawprimitive calls after this
  1661. this->dp2data.dwFlags &= ~D3DHALDP2_EXECUTEBUFFER;
  1662. if (dp2dataddrval != DD_OK)
  1663. {
  1664. if (dp2dataddrval == D3DERR_COMMAND_UNPARSED)
  1665. {
  1666. LPD3DINSTRUCTION lpStart = lpIns;
  1667. lpIns = (LPD3DINSTRUCTION)(this->dp2data.dwErrorOffset + (LPBYTE)debDesc.lpData);
  1668. TrackAllStates(this, lpStart, lpIns);
  1669. break; // Continue parsing
  1670. }
  1671. else
  1672. {
  1673. D3D_ERR("HAL error in DrawPrimitives2 call from Execute API");
  1674. ddrval = dp2dataddrval;
  1675. goto execute_failed;
  1676. }
  1677. }
  1678. else
  1679. {
  1680. TrackAllStates(this, lpIns, NULL);
  1681. goto execute_done;
  1682. }
  1683. default:
  1684. D3D_ERR("HAL detected invalid instruction opcode in Execute");
  1685. goto execute_failed;
  1686. } // switch
  1687. } // if unclipped
  1688. else
  1689. { // Execute Clipped
  1690. switch (lpIns->bOpcode)
  1691. {
  1692. case D3DOP_STATERENDER:
  1693. // We do not track state. This means GetRenderState needs a DDI to
  1694. // work. More importantly, state overrides will get ignored. To fix
  1695. // this, the ParseUnknownCommand function needs to be called by the
  1696. // driver if it cannot understand the state change value.
  1697. // This function should examine if the renderstate had an override,
  1698. // and if so, inform the driver to request the runtime to parse the EB
  1699. {
  1700. LPD3DSTATE lpState;
  1701. DWORD i,j,statek,valuek;
  1702. lpState = (LPD3DSTATE) (lpIns + 1);
  1703. for (i = 0,j=0,statek=(DWORD)-1; i < lpIns->wCount; i++)
  1704. {
  1705. // This call also calls SetDeviceRenderState which
  1706. // is not required. But this is an optimization which
  1707. // can wait till later (if required)
  1708. if (trackState(this, &lpState[i]))
  1709. this->SetRenderStateI(lpState[i].drstRenderStateType, lpState[i].dwArg[0]);
  1710. }
  1711. NEXTINSTRUCTION(lpIns, D3DSTATE, lpIns->wCount);
  1712. }
  1713. break;
  1714. case D3DOP_TRIANGLE:
  1715. if (lpIns->wCount == 0)
  1716. {
  1717. NEXTINSTRUCTION(lpIns, D3DTRIANGLE, lpIns->wCount);
  1718. break;
  1719. }
  1720. Profile(PROF_EXECUTE, D3DPT_TRIANGLELIST, GetVertexType(this));
  1721. WAIT_FOR_FLIP();
  1722. #if DBG
  1723. if (!validateTriangleFlags(lpIns, (LPD3DTRIANGLE) prim))
  1724. {
  1725. ddrval = DDERR_INVALIDPARAMS;
  1726. goto execute_failed;
  1727. }
  1728. #endif
  1729. this->D3DStats.dwTrianglesDrawn += lpIns->wCount;
  1730. D3D_INFO(5, "Emulating D3DOP_TRIANGLE for HAL and clipping");
  1731. if (this->rstates[D3DRENDERSTATE_ZVISIBLE])
  1732. {
  1733. this->iClipStatus &= ~D3DSTATUS_ZNOTVISIBLE;
  1734. }
  1735. else
  1736. {
  1737. ddrval = D3DFEClipTrianglesHW(this, (LPD3DTRIANGLE)prim, lpIns->wCount);
  1738. if (ddrval != D3D_OK)
  1739. {
  1740. D3D_ERR("D3DFEClipLinesHW failed");
  1741. goto execute_failed;
  1742. }
  1743. }
  1744. NEXTINSTRUCTION(lpIns, D3DTRIANGLE, lpIns->wCount);
  1745. break;
  1746. case D3DOP_LINE:
  1747. if (lpIns->wCount == 0)
  1748. {
  1749. NEXTINSTRUCTION(lpIns, D3DLINE, lpIns->wCount);
  1750. break;
  1751. }
  1752. Profile(PROF_EXECUTE, D3DPT_LINELIST, GetVertexType(this));
  1753. WAIT_FOR_FLIP();
  1754. D3D_INFO(5, "Emulating D3DOP_LINE for HAL and clipping");
  1755. this->D3DStats.dwLinesDrawn += lpIns->wCount;
  1756. if (this->rstates[D3DRENDERSTATE_ZVISIBLE])
  1757. {
  1758. this->iClipStatus &= ~D3DSTATUS_ZNOTVISIBLE;
  1759. }
  1760. else
  1761. {
  1762. ddrval = D3DFEClipLinesHW(this, (LPD3DLINE)prim, lpIns->wCount);
  1763. if (ddrval != D3D_OK)
  1764. {
  1765. D3D_ERR("D3DFEClipLinesHW failed");
  1766. goto execute_failed;
  1767. }
  1768. }
  1769. NEXTINSTRUCTION(lpIns, D3DLINE, lpIns->wCount);
  1770. break;
  1771. case D3DOP_POINT:
  1772. WAIT_FOR_FLIP();
  1773. Profile(PROF_EXECUTE, D3DPT_POINTLIST, GetVertexType(this));
  1774. D3D_INFO(5, "Emulating D3DOP_POINT for HAL and clipping");
  1775. {
  1776. LPD3DPOINT point = (LPD3DPOINT) prim;
  1777. int i;
  1778. for (i = 0; i < lpIns->wCount; i++)
  1779. {
  1780. this->D3DStats.dwPointsDrawn += point->wCount;
  1781. point++;
  1782. }
  1783. }
  1784. if (this->rstates[D3DRENDERSTATE_ZVISIBLE])
  1785. {
  1786. this->iClipStatus &= ~D3DSTATUS_ZNOTVISIBLE;
  1787. }
  1788. else
  1789. {
  1790. ddrval = D3DFEClipPointsHW(this, (LPD3DPOINT)prim, lpIns->wCount);
  1791. if (ddrval != D3D_OK)
  1792. {
  1793. D3D_ERR("D3DFEClipPointsHW failed");
  1794. goto execute_failed;
  1795. }
  1796. }
  1797. NEXTINSTRUCTION(lpIns, D3DPOINT, lpIns->wCount);
  1798. break;
  1799. case D3DOP_SPAN:
  1800. // This case is NOOP since we do not implement spans in DP2 DDI
  1801. {
  1802. lpIns = (LPD3DINSTRUCTION)((LPBYTE)lpIns
  1803. + sizeof(D3DINSTRUCTION)
  1804. + (lpIns->bSize * lpIns->wCount));
  1805. break;
  1806. }
  1807. default:
  1808. D3D_ERR("HAL detected invalid instruction opcode in Execute");
  1809. goto execute_failed;
  1810. } // switch
  1811. ClampExtents(this);
  1812. } // Execute Clipped
  1813. } // switch
  1814. } // while
  1815. execute_done:
  1816. D3DFE_ConvertExtent(this, &this->rExtents, &lpExData->dsStatus.drExtent);
  1817. lpExData->dsStatus.dwStatus = this->iClipStatus;
  1818. ddrval = D3D_OK;
  1819. execute_failed:
  1820. // Restore Command Buffer in case of Unclipped EB
  1821. if ((this->dwFEFlags & D3DFE_TLVERTEX) || (mode == D3DEXECUTE_UNCLIPPED))
  1822. {
  1823. this->dp2data.lpDDCommands = ((LPDDRAWI_DDRAWSURFACE_INT)this->lpDDSCB1)->lpLcl;
  1824. this->dp2data.dwCommandOffset = 0;
  1825. this->dp2data.dwCommandLength = 0;
  1826. this->dp2data.dwFlags |= D3DHALDP2_SWAPCOMMANDBUFFER;
  1827. }
  1828. this->dwFlags &= ~D3DPV_WITHINPRIMITIVE;
  1829. UNLOCK_HAL(this);
  1830. return ddrval;
  1831. #undef WAIT_FOR_FLIP
  1832. }
  1833. //---------------------------------------------------------------------
  1834. HRESULT D3DHAL_ExecutePick(LPDIRECT3DDEVICEI lpDevI,
  1835. LPD3DI_PICKDATA lpPickData)
  1836. {
  1837. LPD3DI_EXECUTEDATA lpExData = lpPickData->exe;
  1838. D3DRECT* pick_rect = &lpPickData->pick;
  1839. D3DINSTRUCTION* lpIns;
  1840. D3DEXECUTEBUFFERDESC debDesc;
  1841. LPBYTE prim;
  1842. LPD3DDEVICEDESC_V1 halCaps = &lpDevI->lpD3DHALGlobalDriverData->hwCaps;
  1843. BOOL bMustDoTransform = halCaps->dwFlags & D3DDD_TRANSFORMCAPS;
  1844. D3DI_PICKDATA* pdata = &lpDevI->pick_data;
  1845. LPDIRECTDRAWSURFACE lpDDExeBuf;
  1846. HRESULT ddrval;
  1847. D3DFE_TRANSFORM *transform = &lpDevI->transform;
  1848. DWORD i;
  1849. LPD3DSTATE lpState;
  1850. D3D_INFO(3, "ExecutePick called.%d");
  1851. /*
  1852. * Clear all the old pick records.
  1853. */
  1854. pdata->pick_count = 0;
  1855. if (pdata->records)
  1856. D3DFree(pdata->records);
  1857. pdata->records = NULL;
  1858. //Flush the cached states
  1859. ddrval = lpDevI->FlushStates();
  1860. if (ddrval != D3D_OK)
  1861. {
  1862. D3D_ERR("Error trying to render batched commands in D3DHAL_ExecutePick");
  1863. return ddrval;
  1864. }
  1865. // Grow internal buffers to hold vertices
  1866. ddrval = lpDevI->TLVbuf.CheckAndGrow
  1867. (lpDevI, lpDevI->lpD3DHALGlobalDriverData->hwCaps.dwMaxVertexCount << 5);
  1868. if (ddrval != D3D_OK)
  1869. {
  1870. D3D_ERR("Failed to check and grow TLVbuf in ExecutePick");
  1871. return ddrval;
  1872. }
  1873. ddrval = lpDevI->HVbuf.CheckAndGrow
  1874. (lpDevI->lpD3DHALGlobalDriverData->hwCaps.dwMaxVertexCount*sizeof(D3DFE_CLIPCODE));
  1875. if (ddrval != D3D_OK)
  1876. {
  1877. D3D_ERR("Failed to check and grow HVbuf in ExecutePick");
  1878. return ddrval;
  1879. }
  1880. /*
  1881. * Execute the buffer through the HAL
  1882. */
  1883. D3D_INFO(4, "Locking execute buffer for execution");
  1884. memset(&debDesc, 0, sizeof(D3DEXECUTEBUFFERDESC));
  1885. debDesc.dwSize = sizeof(D3DEXECUTEBUFFERDESC);
  1886. ddrval = D3DHAL_LockBuffer(lpDevI, lpExData->dwHandle, &debDesc, &lpDDExeBuf);
  1887. CHECK(ddrval, "Lock of execute buffer for execution failed");
  1888. // Modify driver funcs for EB pick case
  1889. PFN_DRAWPRIM pfnOldDrawPrim = lpDevI->pfnDrawPrim;
  1890. PFN_DRAWPRIM pfnOldDrawIndexedPrim = lpDevI->pfnDrawIndexedPrim;
  1891. lpDevI->pfnDrawPrim = &DIRECT3DDEVICEI::PickExeBuf;
  1892. lpDevI->pfnDrawIndexedPrim = &DIRECT3DDEVICEI::PickExeBuf;
  1893. /*
  1894. * Calculate the instruction that could not be handled.
  1895. */
  1896. lpIns = (LPD3DINSTRUCTION)((LPBYTE)debDesc.lpData + lpExData->dwInstructionOffset);
  1897. lpDevI->lpbClipIns_base = (unsigned char*)lpIns;
  1898. while (lpIns->bOpcode != D3DOP_EXIT)
  1899. {
  1900. prim = (LPBYTE)(lpIns + 1);
  1901. /*
  1902. * Parse the instruction, passing rasterisation calls to HAL.
  1903. */
  1904. switch (lpIns->bOpcode)
  1905. {
  1906. /*
  1907. * Instructions that must be emulated.
  1908. */
  1909. case D3DOP_MATRIXLOAD:
  1910. D3D_INFO(5, "Emulating D3DOP_MATRIXLOAD for HAL");
  1911. ddrval = D3DHELInst_D3DOP_MATRIXLOAD(lpDevI,
  1912. lpIns->wCount,
  1913. (LPD3DMATRIXLOAD)prim);
  1914. if (ddrval != D3D_OK)
  1915. {
  1916. D3D_ERR("Emulated D3DOP_MATRIXLOAD failed.");
  1917. goto executePick_failed;
  1918. }
  1919. NEXTINSTRUCTION(lpIns, D3DMATRIXLOAD, lpIns->wCount);
  1920. break;
  1921. case D3DOP_MATRIXMULTIPLY:
  1922. D3D_INFO(5, "Emulating D3DOP_MATRIXMULTIPLY for HAL");
  1923. ddrval = D3DHELInst_D3DOP_MATRIXMULTIPLY(lpDevI,
  1924. lpIns->wCount,
  1925. (LPD3DMATRIXMULTIPLY)prim);
  1926. if (ddrval != D3D_OK)
  1927. {
  1928. D3D_ERR("Emulated D3DOP_MATRIXMULTIPLY failed.");
  1929. goto executePick_failed;
  1930. }
  1931. NEXTINSTRUCTION(lpIns, D3DMATRIXMULTIPLY, lpIns->wCount);
  1932. break;
  1933. case D3DOP_STATERENDER:
  1934. lpState = (LPD3DSTATE) (lpIns + 1);
  1935. {
  1936. D3DHAL_RENDERSTATEDATA stateData;
  1937. DWORD j,statek,valuek;
  1938. stateData.dwhContext = lpDevI->dwhContext;
  1939. stateData.lpExeBuf = lpDDExeBuf;
  1940. stateData.dwOffset = (DWORD)((ULONG_PTR)lpIns - (ULONG_PTR)debDesc.lpData +
  1941. sizeof(D3DINSTRUCTION));
  1942. stateData.dwCount = lpIns->wCount;
  1943. CALL_HALONLY(ddrval, lpDevI, RenderState, &stateData);
  1944. if (stateData.ddrval != DD_OK)
  1945. {
  1946. D3D_ERR("HAL error in RenderState call from ExecutePick API");
  1947. ddrval = stateData.ddrval;
  1948. goto executePick_failed;
  1949. }
  1950. }
  1951. for (i = 0; i < lpIns->wCount; i++)
  1952. {
  1953. trackState(lpDevI, &lpState[i]);
  1954. }
  1955. NEXTINSTRUCTION(lpIns, D3DSTATE, lpIns->wCount);
  1956. break;
  1957. case D3DOP_STATETRANSFORM:
  1958. D3D_INFO(5, "Emulating D3DOP_STATETRANSFORM for HAL");
  1959. ddrval = D3DHELInst_D3DOP_STATETRANSFORM(lpDevI, lpIns->wCount,
  1960. (LPD3DSTATE)prim);
  1961. if (ddrval != D3D_OK)
  1962. {
  1963. D3D_ERR("Emulated D3DOP_STATETRANSFORM failed.");
  1964. goto executePick_failed;
  1965. }
  1966. NEXTINSTRUCTION(lpIns, D3DSTATE, lpIns->wCount);
  1967. break;
  1968. /*
  1969. * Operations that require clipping.
  1970. */
  1971. case D3DOP_PROCESSVERTICES:
  1972. D3D_INFO(5, "Emulating D3DOP_PROCESSVERTICES for HAL and clipping");
  1973. ddrval = D3DHELInst_D3DOP_TRANSFORM
  1974. (lpDevI, lpIns->wCount, (LPD3DPROCESSVERTICES)prim, &debDesc);
  1975. if (ddrval != D3D_OK)
  1976. {
  1977. D3D_ERR("Emulated D3DOP_PROCESSVERTICES failed.");
  1978. goto executePick_failed;
  1979. }
  1980. NEXTINSTRUCTION(lpIns, D3DPROCESSVERTICES, lpIns->wCount);
  1981. break;
  1982. case D3DOP_TRIANGLE:
  1983. if (!lpDevI->rstates[D3DRENDERSTATE_ZVISIBLE])
  1984. {
  1985. D3D_INFO(5, "Picking D3DOP_TRIANGLE for HAL and clipping");
  1986. lpDevI->pick_data.pick = *pick_rect;
  1987. HRESULT ret;
  1988. if (lpDevI->dwFEFlags & D3DFE_TLVERTEX)
  1989. {
  1990. lpDevI->primType = D3DPT_TRIANGLELIST;
  1991. lpDevI->dwNumIndices = lpIns->wCount * 3;
  1992. lpDevI->dwNumPrimitives = lpIns->wCount;
  1993. lpDevI->lpvOut = lpDevI->TLVbuf.GetAddress();
  1994. lpDevI->lpwIndices = (WORD*)prim;
  1995. ret = lpDevI->PickExeBuf();
  1996. }
  1997. else
  1998. ret = GenPickTriangles(lpDevI, (LPD3DTRIANGLE)prim, lpIns->wCount);
  1999. if (ret != D3D_OK)
  2000. goto executePick_failed;
  2001. }
  2002. NEXTINSTRUCTION(lpIns, D3DTRIANGLE, lpIns->wCount);
  2003. break;
  2004. case D3DOP_SETSTATUS:
  2005. {
  2006. LPD3DSTATUS status = (LPD3DSTATUS)prim;
  2007. if (status->dwFlags & D3DSETSTATUS_STATUS)
  2008. lpDevI->iClipStatus = status->dwStatus;
  2009. if (status->dwFlags & D3DSETSTATUS_EXTENTS)
  2010. {
  2011. lpDevI->rExtents.x1 = D3DVAL(status->drExtent.x1);
  2012. lpDevI->rExtents.y1 = D3DVAL(status->drExtent.y1);
  2013. lpDevI->rExtents.x2 = D3DVAL(status->drExtent.x2);
  2014. lpDevI->rExtents.y2 = D3DVAL(status->drExtent.y2);
  2015. }
  2016. }
  2017. NEXTINSTRUCTION(lpIns, D3DSTATUS, lpIns->wCount);
  2018. break;
  2019. case D3DOP_BRANCHFORWARD:
  2020. {
  2021. D3DBRANCH* branch = (D3DBRANCH*)prim;
  2022. LPBYTE target;
  2023. BOOL isTaken = FALSE;
  2024. D3D_INFO(5, "Emulating D3DOP_BRANCHFORWARD for HAL.");
  2025. if (branch->bNegate)
  2026. {
  2027. if ((branch->dwMask & lpDevI->iClipStatus) != branch->dwValue)
  2028. {
  2029. D3D_INFO(5, "D3DOP_BRANCHFORWARD instruction: Taking forward branch");
  2030. if (branch->dwOffset)
  2031. {
  2032. isTaken = TRUE;
  2033. target = (LPBYTE)lpIns + branch->dwOffset;
  2034. } else
  2035. goto early_out;
  2036. }
  2037. }
  2038. else
  2039. {
  2040. if ((branch->dwMask & lpDevI->iClipStatus) == branch->dwValue)
  2041. {
  2042. D3D_INFO(5, "D3DOP_BRANCHFORWARD instruction: Taking forward branch");
  2043. if (branch->dwOffset)
  2044. {
  2045. isTaken = TRUE;
  2046. target = (LPBYTE)lpIns + branch->dwOffset;
  2047. }
  2048. else
  2049. goto early_out;
  2050. }
  2051. }
  2052. if (isTaken)
  2053. lpIns = (LPD3DINSTRUCTION)target;
  2054. else
  2055. {
  2056. NEXTINSTRUCTION(lpIns, D3DBRANCH, lpIns->wCount);
  2057. }
  2058. }
  2059. break;
  2060. default:
  2061. D3D_INFO(4, "Skipping instruction %d in ExecutePick",
  2062. lpIns->bOpcode);
  2063. lpIns = (LPD3DINSTRUCTION)((LPBYTE)lpIns +
  2064. sizeof(D3DINSTRUCTION) +
  2065. (lpIns->wCount * lpIns->bSize));
  2066. break;
  2067. }
  2068. }
  2069. early_out:
  2070. D3DHAL_UnlockBuffer(lpDevI, lpExData->dwHandle);
  2071. D3DFE_ConvertExtent(lpDevI, &lpDevI->rExtents, &lpExData->dsStatus.drExtent);
  2072. lpExData->dsStatus.dwStatus = lpDevI->iClipStatus;
  2073. // Restore driver funcs
  2074. lpDevI->pfnDrawIndexedPrim = pfnOldDrawIndexedPrim;
  2075. lpDevI->pfnDrawPrim = pfnOldDrawPrim;
  2076. return (D3D_OK);
  2077. executePick_failed:
  2078. D3D_ERR("ExecutePick Failed.");
  2079. D3DHAL_UnlockBuffer(lpDevI, lpExData->dwHandle);
  2080. // Restore driver funcs
  2081. lpDevI->pfnDrawIndexedPrim = pfnOldDrawIndexedPrim;
  2082. lpDevI->pfnDrawPrim = pfnOldDrawPrim;
  2083. return ddrval;
  2084. }