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.

961 lines
37 KiB

  1. //----------------------------------------------------------------------------
  2. //
  3. // dprim2.cpp
  4. //
  5. // Implements DrawPrimitives2.
  6. //
  7. // Copyright (C) Microsoft Corporation, 1997.
  8. //
  9. //----------------------------------------------------------------------------
  10. #include "pch.cpp"
  11. #pragma hdrstop
  12. //---------------------------------------------------------------------
  13. // Entry is texture count. Clears all texture format bits in the FVF DWORD,
  14. // that correspond to the texture count
  15. // for this count
  16. //---------------------------------------------------------------------
  17. const DWORD g_TextureFormatMask[9] = {
  18. ~0x0000FFFF,
  19. ~0x0003FFFF,
  20. ~0x000FFFFF,
  21. ~0x003FFFFF,
  22. ~0x00FFFFFF,
  23. ~0x03FFFFFF,
  24. ~0x0FFFFFFF,
  25. ~0x3FFFFFFF,
  26. ~0xFFFFFFFF
  27. };
  28. HRESULT
  29. RRFVFCheckAndStride( DWORD dwFVF, DWORD* pdwStride )
  30. {
  31. if( NULL == pdwStride )
  32. {
  33. return DDERR_INVALIDPARAMS;
  34. }
  35. DWORD dwTexCoord = FVF_TEXCOORD_NUMBER(dwFVF);
  36. DWORD vertexType = dwFVF & D3DFVF_POSITION_MASK;
  37. // Texture format bits above texture count should be zero
  38. // Reserved field 0 and 2 should be 0
  39. // Reserved 1 should be set only for LVERTEX
  40. // Only two vertex position types allowed
  41. if( dwFVF & g_TextureFormatMask[dwTexCoord] )
  42. {
  43. DPFM( 0, TNL, ("FVF has incorrect texture format") );
  44. return DDERR_INVALIDPARAMS;
  45. }
  46. if( dwFVF & (D3DFVF_RESERVED2 | D3DFVF_RESERVED0) ||
  47. ((dwFVF & D3DFVF_RESERVED1) && !(dwFVF & D3DFVF_LVERTEX)) )
  48. {
  49. DPFM( 0, TNL, ("FVF has reserved bit(s) set") );
  50. return DDERR_INVALIDPARAMS;
  51. }
  52. if( !(vertexType == D3DFVF_XYZRHW ||
  53. vertexType == D3DFVF_XYZ ||
  54. vertexType == D3DFVF_XYZB1 ||
  55. vertexType == D3DFVF_XYZB2 ||
  56. vertexType == D3DFVF_XYZB3 ||
  57. vertexType == D3DFVF_XYZB4 ||
  58. vertexType == D3DFVF_XYZB5) )
  59. {
  60. DPFM( 0, TNL, ("FVF has incorrect position type") );
  61. return DDERR_INVALIDPARAMS;
  62. }
  63. if( (vertexType == D3DFVF_XYZRHW) && (dwFVF & D3DFVF_NORMAL) )
  64. {
  65. DPFM( 0, TNL, ("Normal should not be used with XYZRHW position type"));
  66. return DDERR_INVALIDPARAMS;
  67. }
  68. *pdwStride = GetFVFVertexSize( dwFVF );
  69. return D3D_OK;
  70. }
  71. inline D3DPRIMITIVETYPE ConvertDP2OPToPrimType(D3DHAL_DP2OPERATION Dp2Op)
  72. {
  73. switch (Dp2Op)
  74. {
  75. case D3DDP2OP_POINTS :
  76. return D3DPT_POINTLIST;
  77. case D3DDP2OP_INDEXEDLINELIST :
  78. case D3DDP2OP_INDEXEDLINELIST2 :
  79. case D3DDP2OP_LINELIST_IMM :
  80. case D3DDP2OP_LINELIST :
  81. return D3DPT_LINELIST;
  82. case D3DDP2OP_TRIANGLELIST :
  83. case D3DDP2OP_INDEXEDTRIANGLELIST :
  84. case D3DDP2OP_INDEXEDTRIANGLELIST2:
  85. return D3DPT_TRIANGLELIST;
  86. case D3DDP2OP_LINESTRIP :
  87. case D3DDP2OP_INDEXEDLINESTRIP :
  88. return D3DPT_LINESTRIP;
  89. case D3DDP2OP_TRIANGLESTRIP :
  90. case D3DDP2OP_INDEXEDTRIANGLESTRIP:
  91. return D3DPT_TRIANGLESTRIP;
  92. case D3DDP2OP_TRIANGLEFAN :
  93. case D3DDP2OP_INDEXEDTRIANGLEFAN :
  94. case D3DDP2OP_TRIANGLEFAN_IMM :
  95. return D3DPT_TRIANGLEFAN;
  96. case D3DDP2OP_RENDERSTATE :
  97. case D3DDP2OP_TEXTURESTAGESTATE :
  98. case D3DDP2OP_VIEWPORTINFO :
  99. case D3DDP2OP_WINFO :
  100. default:
  101. DPFM(4, DRV, ("(RefRast)Non primitive operation operation in DrawPrimitives2"));
  102. return (D3DPRIMITIVETYPE)0;
  103. }
  104. }
  105. //----------------------------------------------------------------------------
  106. //
  107. // RefRastDrawPrimitives2
  108. //
  109. // This is called by D3DIM for API DrawPrimitives2 to draw a set of primitives
  110. // using a vertex buffer.
  111. //
  112. //----------------------------------------------------------------------------
  113. DWORD __stdcall
  114. RefRastDrawPrimitives2(LPD3DHAL_DRAWPRIMITIVES2DATA pDPrim2Data)
  115. {
  116. HRESULT hr = D3D_OK;
  117. ReferenceRasterizer *pRefRast;
  118. DWORD dwStride;
  119. PUINT8 pVtData = NULL;
  120. VALIDATE_REFRAST_CONTEXT("RefRastDrawPrimitives", pDPrim2Data);
  121. if( pDPrim2Data->lpVertices )
  122. {
  123. if (pDPrim2Data->dwFlags & D3DHALDP2_USERMEMVERTICES)
  124. pVtData = (PUINT8)pDPrim2Data->lpVertices +
  125. pDPrim2Data->dwVertexOffset;
  126. else
  127. pVtData = (PUINT8)pDPrim2Data->lpDDVertex->lpGbl->fpVidMem +
  128. pDPrim2Data->dwVertexOffset;
  129. }
  130. LPD3DHAL_DP2COMMAND pCmd = (LPD3DHAL_DP2COMMAND)
  131. ((PUINT8)pDPrim2Data->lpDDCommands->lpGbl->fpVidMem +
  132. pDPrim2Data->dwCommandOffset);
  133. UINT_PTR CmdBoundary = (UINT_PTR)pCmd +
  134. pDPrim2Data->dwCommandLength;
  135. // Unconditionally get the vertex stride, since it can not change
  136. if ((pDPrim2Data->ddrval = RRFVFCheckAndStride(
  137. (DWORD)pDPrim2Data->dwVertexType, &dwStride)) != D3D_OK)
  138. {
  139. return DDHAL_DRIVER_HANDLED;
  140. }
  141. if ((pDPrim2Data->ddrval=RefRastLockTarget(pRefRast)) != D3D_OK)
  142. {
  143. return DDHAL_DRIVER_HANDLED;
  144. }
  145. // Skip state check and texture lock if the first thing is state change
  146. //
  147. // WINFO is excluded here because it currently does not affect RGB/MMX
  148. // and refrast does not care if it changes between begin/endrendering.
  149. //
  150. // VIEWPORTINFO is excluded here because it is OK to change the viewport
  151. // between begin/endrendering on both RGB/MMX and Ref.
  152. //
  153. // Loop through the data, update render states
  154. // and then draw the primitive
  155. for (;;)
  156. {
  157. LPDWORD lpdwRStates;
  158. if (pDPrim2Data->dwFlags & D3DHALDP2_EXECUTEBUFFER)
  159. lpdwRStates = pDPrim2Data->lpdwRStates;
  160. else
  161. lpdwRStates = NULL;
  162. BOOL bWireframe = pRefRast->GetRenderState()[D3DRENDERSTATE_FILLMODE]
  163. == D3DFILL_WIREFRAME;
  164. pDPrim2Data->ddrval = DoDrawPrimitives2(pRefRast,
  165. (UINT16)dwStride,
  166. (DWORD)pDPrim2Data->dwVertexType,
  167. pVtData,
  168. pDPrim2Data->dwVertexLength,
  169. &pCmd,
  170. lpdwRStates,
  171. bWireframe
  172. );
  173. if (pDPrim2Data->ddrval != D3D_OK)
  174. {
  175. if (pDPrim2Data->ddrval == D3DERR_COMMAND_UNPARSED)
  176. {
  177. pDPrim2Data->dwErrorOffset = (UINT32)((ULONG_PTR)pCmd -
  178. (UINT_PTR)(pDPrim2Data->lpDDCommands->lpGbl->fpVidMem));
  179. }
  180. goto EH_Exit;
  181. }
  182. if ((UINT_PTR)pCmd >= CmdBoundary)
  183. break;
  184. }
  185. EH_Exit:
  186. // As an optimization a check could be made here to see if it has
  187. // locked
  188. if (pRefRast->TexturesAreLocked())
  189. {
  190. hr = pRefRast->EndRendering();
  191. RefRastUnlockTexture(pRefRast);
  192. pRefRast->ClearTexturesLocked();
  193. }
  194. RefRastUnlockTarget(pRefRast);
  195. if (pDPrim2Data->ddrval == D3D_OK)
  196. {
  197. pDPrim2Data->ddrval = hr;
  198. }
  199. return DDHAL_DRIVER_HANDLED;
  200. }
  201. HRESULT FASTCALL
  202. DoDrawIndexedTriList2(ReferenceRasterizer *pCtx,
  203. DWORD dwStride,
  204. PUINT8 pVtx,
  205. WORD cPrims,
  206. D3DHAL_DP2INDEXEDTRIANGLELIST *pTriList)
  207. {
  208. INT i;
  209. D3DHAL_DP2INDEXEDTRIANGLELIST *pTri = pTriList;
  210. for (i = 0; i < cPrims; i ++)
  211. {
  212. HRESULT hr;
  213. PUINT8 pVtx0, pVtx1, pVtx2;
  214. pVtx0 = pVtx + dwStride * pTri->wV1;
  215. pVtx1 = pVtx + dwStride * pTri->wV2;
  216. pVtx2 = pVtx + dwStride * pTri->wV3;
  217. pCtx->DrawTriangle(pVtx0, pVtx1, pVtx2, pTri->wFlags);
  218. pTri ++;
  219. }
  220. return D3D_OK;
  221. }
  222. //----------------------------------------------------------------------------
  223. //
  224. // DoDrawPrimitives2
  225. //
  226. // It's called by RefRastDrawPrimitives2. .
  227. //
  228. //----------------------------------------------------------------------------
  229. HRESULT FASTCALL
  230. DoDrawPrimitives2(ReferenceRasterizer *pCtx,
  231. UINT16 dwStride,
  232. DWORD dwFvf,
  233. PUINT8 pVtx,
  234. DWORD dwNumVertices,
  235. LPD3DHAL_DP2COMMAND *ppCmd,
  236. LPDWORD lpdwRStates,
  237. BOOL bWireframe
  238. )
  239. {
  240. LPD3DHAL_DP2COMMAND pCmd = *ppCmd;
  241. HRESULT hr;
  242. DPFM(7, DRV, ("(RefRast)Read Ins: %08lx", *(LPDWORD)pCmd));
  243. //
  244. // Lock textures and setup the floating point state if the
  245. // command is a drawing command, only if it has not been locked before
  246. //
  247. switch(pCmd->bCommand)
  248. {
  249. case D3DDP2OP_POINTS:
  250. case D3DDP2OP_LINELIST:
  251. case D3DDP2OP_LINESTRIP:
  252. case D3DDP2OP_TRIANGLELIST:
  253. case D3DDP2OP_TRIANGLESTRIP:
  254. case D3DDP2OP_TRIANGLEFAN:
  255. case D3DDP2OP_INDEXEDLINELIST:
  256. case D3DDP2OP_INDEXEDLINELIST2:
  257. case D3DDP2OP_INDEXEDLINESTRIP:
  258. case D3DDP2OP_INDEXEDTRIANGLELIST:
  259. case D3DDP2OP_INDEXEDTRIANGLELIST2:
  260. case D3DDP2OP_INDEXEDTRIANGLESTRIP:
  261. case D3DDP2OP_INDEXEDTRIANGLEFAN:
  262. // If there is no vertex information, then we cannot draw, quit
  263. // with an error.
  264. if( NULL == pVtx )
  265. return DDERR_OUTOFMEMORY; // The most likely cause
  266. // Fall through
  267. case D3DDP2OP_TRIANGLEFAN_IMM:
  268. case D3DDP2OP_LINELIST_IMM:
  269. if (!pCtx->TexturesAreLocked())
  270. {
  271. HR_RET(RefRastLockTexture( pCtx ));
  272. HR_RET(pCtx->BeginRendering( dwFvf ));
  273. pCtx->SetTexturesLocked();
  274. }
  275. }
  276. switch(pCmd->bCommand)
  277. {
  278. case D3DDP2OP_STATESET:
  279. {
  280. LPD3DHAL_DP2STATESET pStateSetOp = (LPD3DHAL_DP2STATESET)(pCmd + 1);
  281. switch (pStateSetOp->dwOperation)
  282. {
  283. case D3DHAL_STATESETBEGIN :
  284. hr = pCtx->BeginStateSet(pStateSetOp->dwParam);
  285. break;
  286. case D3DHAL_STATESETEND :
  287. hr = pCtx->EndStateSet();
  288. break;
  289. case D3DHAL_STATESETDELETE :
  290. hr = pCtx->DeleteStateSet(pStateSetOp->dwParam);
  291. break;
  292. case D3DHAL_STATESETEXECUTE:
  293. hr = pCtx->ExecuteStateSet(pStateSetOp->dwParam);
  294. break;
  295. case D3DHAL_STATESETCAPTURE:
  296. hr = pCtx->CaptureStateSet(pStateSetOp->dwParam);
  297. break;
  298. default :
  299. hr = DDERR_INVALIDPARAMS;
  300. }
  301. // Update the command buffer pointer
  302. *ppCmd = (LPD3DHAL_DP2COMMAND)(pStateSetOp + pCmd->wStateCount);
  303. }
  304. break;
  305. case D3DDP2OP_VIEWPORTINFO:
  306. {
  307. HR_RET(pCtx->pStateSetFuncTbl->pfnDp2SetViewport(pCtx, pCmd));
  308. // Update the command buffer pointer
  309. *ppCmd = (LPD3DHAL_DP2COMMAND)
  310. ((D3DHAL_DP2VIEWPORTINFO *)(pCmd + 1) + pCmd->wStateCount);
  311. }
  312. break;
  313. case D3DDP2OP_WINFO:
  314. {
  315. HR_RET(pCtx->pStateSetFuncTbl->pfnDp2SetWRange(pCtx, pCmd));
  316. // Update the command buffer pointer
  317. *ppCmd = (LPD3DHAL_DP2COMMAND)
  318. ((D3DHAL_DP2WINFO *)(pCmd + 1) + pCmd->wStateCount);
  319. }
  320. break;
  321. case D3DDP2OP_RENDERSTATE:
  322. {
  323. HR_RET(pCtx->pStateSetFuncTbl->pfnDp2SetRenderStates(pCtx, dwFvf, pCmd, lpdwRStates));
  324. // Update the command buffer pointer
  325. *ppCmd = (LPD3DHAL_DP2COMMAND)
  326. ((D3DHAL_DP2RENDERSTATE *)(pCmd + 1) + pCmd->wStateCount);
  327. }
  328. break;
  329. case D3DDP2OP_TEXTURESTAGESTATE:
  330. {
  331. HR_RET(pCtx->pStateSetFuncTbl->pfnDp2TextureStageState(pCtx, dwFvf, pCmd));
  332. // Update the command buffer pointer
  333. *ppCmd = (LPD3DHAL_DP2COMMAND)
  334. ((LPD3DHAL_DP2TEXTURESTAGESTATE)(pCmd + 1) + pCmd->wStateCount);
  335. }
  336. break;
  337. // This is a special case because it has edge flags. Other D3DDP2OP
  338. // can actually make use of DoDrawOneIndexedPrimitive/DoDrawOnePrimitive.
  339. case D3DDP2OP_INDEXEDTRIANGLELIST:
  340. {
  341. // This command is used in execute buffers. So untransformed
  342. // vertices are not expected by this refrast.
  343. _ASSERT( FVF_TRANSFORMED(dwFvf),
  344. "Untransformed vertices in D3DDP2OP_INDEXEDTRIANGLELIST" );
  345. WORD cPrims = pCmd->wPrimitiveCount;
  346. HR_RET(DoDrawIndexedTriList2(pCtx,
  347. dwStride,
  348. pVtx,
  349. cPrims,
  350. (D3DHAL_DP2INDEXEDTRIANGLELIST *)(pCmd + 1)));
  351. // Update the command buffer pointer
  352. *ppCmd = (LPD3DHAL_DP2COMMAND)((PUINT8)(pCmd + 1) +
  353. sizeof(D3DHAL_DP2INDEXEDTRIANGLELIST) * cPrims);
  354. }
  355. break;
  356. case D3DDP2OP_INDEXEDLINELIST:
  357. {
  358. // This command is used in execute buffers. So untransformed
  359. // vertices are not expected by this refrast.
  360. _ASSERT( FVF_TRANSFORMED(dwFvf),
  361. "Untransformed vertices in D3DDP2OP_INDEXEDLINELIST" );
  362. HR_RET(DoDrawOneIndexedPrimitive(pCtx,
  363. dwStride,
  364. pVtx,
  365. (LPWORD)(pCmd + 1),
  366. D3DPT_LINELIST,
  367. pCmd->wPrimitiveCount * 2));
  368. // Update the command buffer pointer
  369. *ppCmd = (LPD3DHAL_DP2COMMAND)((PUINT8)(pCmd + 1) +
  370. pCmd->wPrimitiveCount * sizeof(D3DHAL_DP2INDEXEDLINELIST));
  371. }
  372. break;
  373. // Following ops All use DoDrawOneIndexedPrimitive/DoDrawOnePrimitive.
  374. // There are some extra overheads introduced because those two functions
  375. // need to switch over the PrimTypes while we already know it here.
  376. // Striping out the code to add inline functions for each PrimType means
  377. // adding about twenty functions(considering the types of prim times types
  378. // of vertex). So I have used DoDrawOneIndexedPrimitive/DoDrawOnePrimitive
  379. // here anyway. We can later change it if necessary.
  380. case D3DDP2OP_POINTS:
  381. {
  382. WORD cPrims = pCmd->wPrimitiveCount;
  383. D3DHAL_DP2POINTS *pPt = (D3DHAL_DP2POINTS *)(pCmd + 1);
  384. WORD i;
  385. // Check if the primitive is transformed or not
  386. if (!FVF_TRANSFORMED(dwFvf))
  387. {
  388. for (i = 0; i < cPrims; i++)
  389. {
  390. pCtx->SavePrimitiveData( dwFvf,
  391. (LPVOID) (pVtx +
  392. pPt->wVStart * dwStride),
  393. pPt->wCount,
  394. D3DPT_POINTLIST );
  395. HR_RET(pCtx->ProcessPrimitive( FALSE ));
  396. pPt ++;
  397. }
  398. }
  399. else
  400. {
  401. for (i = 0; i < cPrims; i++)
  402. {
  403. pCtx->SavePrimitiveData( dwFvf,
  404. (LPVOID) (pVtx +
  405. pPt->wVStart * dwStride),
  406. pPt->wCount,
  407. D3DPT_POINTLIST );
  408. HR_RET(DoDrawOnePrimitive(pCtx,
  409. dwStride,
  410. (PUINT8) (pVtx +
  411. pPt->wVStart * dwStride),
  412. D3DPT_POINTLIST,
  413. pPt->wCount));
  414. pPt ++;
  415. }
  416. }
  417. // Update the command buffer pointer
  418. *ppCmd = (LPD3DHAL_DP2COMMAND)pPt;
  419. }
  420. break;
  421. case D3DDP2OP_LINELIST:
  422. {
  423. D3DHAL_DP2LINELIST *pLine = (D3DHAL_DP2LINELIST *)(pCmd + 1);
  424. // Save all the DP2 data passed, irregardless whether it is
  425. // already transformed or not
  426. pCtx->SavePrimitiveData( dwFvf,
  427. (LPVOID) (pVtx +
  428. pLine->wVStart * dwStride),
  429. pCmd->wPrimitiveCount * 2,
  430. D3DPT_LINELIST );
  431. // Check if the primitive is transformed or not
  432. if (!FVF_TRANSFORMED(dwFvf))
  433. {
  434. HR_RET(pCtx->ProcessPrimitive( FALSE ));
  435. }
  436. else
  437. {
  438. HR_RET(DoDrawOnePrimitive(pCtx,
  439. dwStride,
  440. (pVtx + pLine->wVStart * dwStride),
  441. D3DPT_LINELIST,
  442. pCmd->wPrimitiveCount * 2));
  443. }
  444. // Update the command buffer pointer
  445. *ppCmd = (LPD3DHAL_DP2COMMAND)(pLine + 1);
  446. }
  447. break;
  448. case D3DDP2OP_INDEXEDLINELIST2:
  449. {
  450. DWORD dwNumIndices = pCmd->wPrimitiveCount*2;
  451. LPD3DHAL_DP2STARTVERTEX lpStartVertex =
  452. (LPD3DHAL_DP2STARTVERTEX)(pCmd + 1);
  453. // Save all the DP2 data passed, irregardless whether it is
  454. // already transformed or not
  455. pCtx->SavePrimitiveData( dwFvf,
  456. (LPVOID)(pVtx +
  457. lpStartVertex->wVStart*dwStride),
  458. dwNumVertices-lpStartVertex->wVStart,
  459. D3DPT_LINELIST,
  460. (LPWORD)(lpStartVertex + 1),
  461. dwNumIndices );
  462. // Check if the primitive is transformed or not
  463. if (!FVF_TRANSFORMED(dwFvf))
  464. {
  465. HR_RET(pCtx->ProcessPrimitive( TRUE ));
  466. }
  467. else
  468. {
  469. HR_RET(DoDrawOneIndexedPrimitive(pCtx,
  470. dwStride,
  471. pVtx + lpStartVertex->wVStart*dwStride,
  472. (LPWORD)(lpStartVertex + 1),
  473. D3DPT_LINELIST,
  474. dwNumIndices));
  475. }
  476. // Update the command buffer pointer
  477. *ppCmd = (LPD3DHAL_DP2COMMAND)((PUINT8)(lpStartVertex + 1) +
  478. pCmd->wPrimitiveCount * sizeof(D3DHAL_DP2INDEXEDLINELIST));
  479. }
  480. break;
  481. case D3DDP2OP_LINESTRIP:
  482. {
  483. D3DHAL_DP2LINESTRIP *pLine = (D3DHAL_DP2LINESTRIP *)(pCmd + 1);
  484. // Save all the DP2 data passed, irregardless whether it is
  485. // already transformed or not
  486. pCtx->SavePrimitiveData( dwFvf,
  487. (LPVOID) (pVtx +
  488. pLine->wVStart * dwStride),
  489. pCmd->wPrimitiveCount + 1,
  490. D3DPT_LINESTRIP );
  491. // Check if the primitive is transformed or not
  492. if (!FVF_TRANSFORMED(dwFvf))
  493. {
  494. HR_RET(pCtx->ProcessPrimitive( FALSE ));
  495. }
  496. else
  497. {
  498. HR_RET(DoDrawOnePrimitive(pCtx,
  499. dwStride,
  500. (pVtx + pLine->wVStart * dwStride),
  501. D3DPT_LINESTRIP,
  502. pCmd->wPrimitiveCount + 1));
  503. }
  504. // Update the command buffer pointer
  505. *ppCmd = (LPD3DHAL_DP2COMMAND)(pLine + 1);
  506. }
  507. break;
  508. case D3DDP2OP_INDEXEDLINESTRIP:
  509. {
  510. DWORD dwNumIndices = pCmd->wPrimitiveCount + 1;
  511. LPD3DHAL_DP2STARTVERTEX lpStartVertex =
  512. (LPD3DHAL_DP2STARTVERTEX)(pCmd + 1);
  513. // Save all the DP2 data passed, irregardless whether it is
  514. // already transformed or not
  515. pCtx->SavePrimitiveData( dwFvf,
  516. (LPVOID)(pVtx +
  517. lpStartVertex->wVStart*dwStride),
  518. dwNumVertices-lpStartVertex->wVStart,
  519. D3DPT_LINESTRIP,
  520. (LPWORD)(lpStartVertex + 1),
  521. dwNumIndices );
  522. // Check if the primitive is transformed or not
  523. if (!FVF_TRANSFORMED(dwFvf))
  524. {
  525. HR_RET(pCtx->ProcessPrimitive( TRUE ));
  526. }
  527. else
  528. {
  529. HR_RET(DoDrawOneIndexedPrimitive(pCtx,
  530. dwStride,
  531. pVtx + lpStartVertex->wVStart*dwStride,
  532. (LPWORD)(lpStartVertex + 1),
  533. D3DPT_LINESTRIP,
  534. dwNumIndices));
  535. }
  536. // Update the command buffer pointer
  537. *ppCmd = (LPD3DHAL_DP2COMMAND)((PUINT8)(lpStartVertex + 1) +
  538. dwNumIndices * sizeof(WORD));
  539. }
  540. break;
  541. case D3DDP2OP_TRIANGLELIST:
  542. {
  543. D3DHAL_DP2TRIANGLELIST *pTri = (D3DHAL_DP2TRIANGLELIST *)(pCmd + 1);
  544. // Save all the DP2 data passed, irregardless whether it is
  545. // already transformed or not
  546. pCtx->SavePrimitiveData( dwFvf,
  547. (LPVOID)(pVtx + pTri->wVStart * dwStride),
  548. pCmd->wPrimitiveCount * 3,
  549. D3DPT_TRIANGLELIST );
  550. // Check if the primitive is transformed or not
  551. if (!FVF_TRANSFORMED(dwFvf))
  552. {
  553. HR_RET(pCtx->ProcessPrimitive( FALSE ));
  554. }
  555. else
  556. {
  557. HR_RET(DoDrawOnePrimitive(pCtx,
  558. dwStride,
  559. (pVtx + pTri->wVStart * dwStride),
  560. D3DPT_TRIANGLELIST,
  561. pCmd->wPrimitiveCount * 3));
  562. }
  563. // Update the command buffer pointer
  564. *ppCmd = (LPD3DHAL_DP2COMMAND)(pTri + 1);
  565. }
  566. break;
  567. case D3DDP2OP_INDEXEDTRIANGLELIST2:
  568. {
  569. DWORD dwNumIndices = pCmd->wPrimitiveCount*3;
  570. LPD3DHAL_DP2STARTVERTEX lpStartVertex =
  571. (LPD3DHAL_DP2STARTVERTEX)(pCmd + 1);
  572. // Save all the DP2 data passed, irregardless whether it is
  573. // already transformed or not
  574. pCtx->SavePrimitiveData( dwFvf,
  575. (LPVOID)(pVtx +
  576. lpStartVertex->wVStart*dwStride),
  577. dwNumVertices-lpStartVertex->wVStart,
  578. D3DPT_TRIANGLELIST,
  579. (LPWORD)(lpStartVertex + 1),
  580. dwNumIndices );
  581. // Check if the primitive is transformed or not
  582. if (!FVF_TRANSFORMED(dwFvf))
  583. {
  584. HR_RET(pCtx->ProcessPrimitive( TRUE ));
  585. }
  586. else
  587. {
  588. HR_RET(DoDrawOneIndexedPrimitive(pCtx,
  589. dwStride,
  590. pVtx + lpStartVertex->wVStart*dwStride,
  591. (LPWORD)(lpStartVertex + 1),
  592. D3DPT_TRIANGLELIST,
  593. dwNumIndices));
  594. }
  595. // Update the command buffer pointer
  596. *ppCmd = (LPD3DHAL_DP2COMMAND)((PUINT8)(lpStartVertex + 1) +
  597. dwNumIndices * sizeof(WORD));
  598. }
  599. break;
  600. case D3DDP2OP_TRIANGLESTRIP:
  601. {
  602. D3DHAL_DP2TRIANGLESTRIP *pTri = (D3DHAL_DP2TRIANGLESTRIP *)(pCmd + 1);
  603. // Save all the DP2 data passed, irregardless whether it is
  604. // already transformed or not
  605. pCtx->SavePrimitiveData( dwFvf,
  606. (pVtx + pTri->wVStart * dwStride),
  607. pCmd->wPrimitiveCount + 2,
  608. D3DPT_TRIANGLESTRIP );
  609. // Check if the primitive is transformed or not
  610. if (!FVF_TRANSFORMED(dwFvf))
  611. {
  612. HR_RET(pCtx->ProcessPrimitive( FALSE ));
  613. }
  614. else
  615. {
  616. HR_RET(DoDrawOnePrimitive(pCtx,
  617. dwStride,
  618. (pVtx + pTri->wVStart * dwStride),
  619. D3DPT_TRIANGLESTRIP,
  620. pCmd->wPrimitiveCount + 2));
  621. }
  622. // Update the command buffer pointer
  623. *ppCmd = (LPD3DHAL_DP2COMMAND)(pTri + 1);
  624. }
  625. break;
  626. case D3DDP2OP_INDEXEDTRIANGLESTRIP:
  627. {
  628. DWORD dwNumIndices = pCmd->wPrimitiveCount+2;
  629. LPD3DHAL_DP2STARTVERTEX lpStartVertex =
  630. (LPD3DHAL_DP2STARTVERTEX)(pCmd + 1);
  631. // Save all the DP2 data passed, irregardless whether it is
  632. // already transformed or not
  633. pCtx->SavePrimitiveData( dwFvf,
  634. (LPVOID)(pVtx +
  635. lpStartVertex->wVStart*dwStride),
  636. dwNumVertices-lpStartVertex->wVStart,
  637. D3DPT_TRIANGLESTRIP,
  638. (LPWORD)(lpStartVertex + 1),
  639. dwNumIndices );
  640. // Check if the primitive is transformed or not
  641. if (!FVF_TRANSFORMED(dwFvf))
  642. {
  643. HR_RET(pCtx->ProcessPrimitive( TRUE ));
  644. }
  645. else
  646. {
  647. HR_RET(DoDrawOneIndexedPrimitive(pCtx,
  648. dwStride,
  649. pVtx + lpStartVertex->wVStart*dwStride,
  650. (LPWORD)(lpStartVertex + 1),
  651. D3DPT_TRIANGLESTRIP,
  652. dwNumIndices));
  653. }
  654. // Update the command buffer pointer
  655. *ppCmd = (LPD3DHAL_DP2COMMAND)((PUINT8)(lpStartVertex + 1) +
  656. dwNumIndices * sizeof(WORD));
  657. }
  658. break;
  659. case D3DDP2OP_TRIANGLEFAN:
  660. {
  661. D3DHAL_DP2TRIANGLEFAN *pTri = (D3DHAL_DP2TRIANGLEFAN *)(pCmd + 1);
  662. // Save all the DP2 data passed, irregardless whether it is
  663. // already transformed or not
  664. pCtx->SavePrimitiveData( dwFvf,
  665. (LPVOID) (pVtx +
  666. pTri->wVStart * dwStride),
  667. pCmd->wPrimitiveCount + 2,
  668. D3DPT_TRIANGLEFAN );
  669. // Check if the primitive is transformed or not
  670. if (!FVF_TRANSFORMED(dwFvf))
  671. {
  672. HR_RET(pCtx->ProcessPrimitive( FALSE ));
  673. }
  674. else
  675. {
  676. HR_RET(DoDrawOnePrimitive(pCtx,
  677. dwStride,
  678. (pVtx + pTri->wVStart * dwStride),
  679. D3DPT_TRIANGLEFAN,
  680. pCmd->wPrimitiveCount + 2));
  681. }
  682. // Update the command buffer pointer
  683. *ppCmd = (LPD3DHAL_DP2COMMAND)(pTri + 1);
  684. }
  685. break;
  686. case D3DDP2OP_INDEXEDTRIANGLEFAN:
  687. {
  688. DWORD dwNumIndices = pCmd->wPrimitiveCount + 2;
  689. LPD3DHAL_DP2STARTVERTEX lpStartVertex =
  690. (LPD3DHAL_DP2STARTVERTEX)(pCmd + 1);
  691. // Save all the DP2 data passed, irregardless whether it is
  692. // already transformed or not
  693. pCtx->SavePrimitiveData( dwFvf,
  694. (LPVOID)(pVtx +
  695. lpStartVertex->wVStart*dwStride),
  696. dwNumVertices-lpStartVertex->wVStart,
  697. D3DPT_TRIANGLEFAN,
  698. (LPWORD)(lpStartVertex + 1),
  699. dwNumIndices );
  700. // Check if the primitive is transformed or not
  701. if (!FVF_TRANSFORMED(dwFvf))
  702. {
  703. HR_RET(pCtx->ProcessPrimitive( TRUE ));
  704. }
  705. else
  706. {
  707. HR_RET(DoDrawOneIndexedPrimitive(pCtx,
  708. dwStride,
  709. pVtx + lpStartVertex->wVStart*dwStride,
  710. (LPWORD)(lpStartVertex + 1),
  711. D3DPT_TRIANGLEFAN,
  712. dwNumIndices));
  713. }
  714. // Update the command buffer pointer
  715. *ppCmd = (LPD3DHAL_DP2COMMAND)((PUINT8)(lpStartVertex + 1) +
  716. dwNumIndices * sizeof(WORD));
  717. }
  718. break;
  719. case D3DDP2OP_TRIANGLEFAN_IMM:
  720. {
  721. DWORD vertexCount = pCmd->wPrimitiveCount + 2;
  722. // Make sure the pFanVtx pointer is DWORD aligned:
  723. // (pFanVtx +3) % 4
  724. PUINT8 pFanVtx = (PUINT8)(((ULONG_PTR)(pCmd + 1) +
  725. sizeof(D3DHAL_DP2TRIANGLEFAN_IMM) + 3) & ~3);
  726. // Save all the DP2 data passed, irregardless whether it is
  727. // already transformed or not. Only the dwFVF is interesting
  728. // so the rest of the stuff is NULL/0
  729. pCtx->SavePrimitiveData( dwFvf,
  730. NULL,
  731. 0,
  732. D3DPT_TRIANGLEFAN,
  733. 0,
  734. 0 );
  735. // Assert here. This case should never be reached.
  736. // This command is used by front end to give clipped
  737. // primitives inside the command itself. Since TL Hals
  738. // do their own clipping untransformed vertices but yet
  739. // clipped are not expected here.
  740. // Assert that only transformed vertices can reach here
  741. _ASSERT( FVF_TRANSFORMED(dwFvf),
  742. "Untransformed vertices in D3DDP2OP_TRIANGLEFAN_IMM" );
  743. if (bWireframe)
  744. {
  745. // Read edge flags
  746. UINT32 dwEdgeFlags =
  747. ((LPD3DHAL_DP2TRIANGLEFAN_IMM)(pCmd + 1))->dwEdgeFlags;
  748. HR_RET(DoDrawOneEdgeFlagTriangleFan(pCtx,
  749. dwStride,
  750. pFanVtx,
  751. vertexCount,
  752. dwEdgeFlags));
  753. }
  754. else
  755. {
  756. HR_RET(DoDrawOnePrimitive(pCtx,
  757. dwStride,
  758. pFanVtx,
  759. D3DPT_TRIANGLEFAN,
  760. vertexCount));
  761. }
  762. // Update the command buffer pointer
  763. *ppCmd = (LPD3DHAL_DP2COMMAND)((PUINT8)pFanVtx +
  764. vertexCount * dwStride);
  765. }
  766. break;
  767. case D3DDP2OP_LINELIST_IMM:
  768. {
  769. DWORD vertexCount = pCmd->wPrimitiveCount * 2;
  770. // Make sure the pLineVtx pointer is DWORD aligned:
  771. // (pLineVtx +3) % 4
  772. PUINT8 pLineVtx = (PUINT8)(((ULONG_PTR)(pCmd + 1) + 3) & ~3);
  773. // Save all the DP2 data passed, irregardless whether it is
  774. // already transformed or not. Only the dwFVF is interesting
  775. // so the rest of the stuff is NULL/0
  776. pCtx->SavePrimitiveData( dwFvf,
  777. NULL,
  778. 0,
  779. D3DPT_LINELIST,
  780. 0,
  781. 0 );
  782. // Assert here. This case should never be reached.
  783. // This command is used by front end to give clipped
  784. // primitives inside the command itself. Since TL Hals
  785. // do their own clipping untransformed vertices but yet
  786. // clipped are not expected here.
  787. // Assert that only transformed vertices can reach here
  788. _ASSERT( FVF_TRANSFORMED(dwFvf),
  789. "Untransformed vertices in D3DDP2OP_LINELIST_IMM" );
  790. HR_RET(DoDrawOnePrimitive(pCtx,
  791. dwStride,
  792. pLineVtx,
  793. D3DPT_LINELIST,
  794. vertexCount));
  795. // Update the command buffer pointer
  796. *ppCmd = (LPD3DHAL_DP2COMMAND)((PUINT8)pLineVtx +
  797. vertexCount * dwStride);
  798. }
  799. break;
  800. case D3DDP2OP_ZRANGE:
  801. {
  802. HR_RET(pCtx->pStateSetFuncTbl->pfnDp2SetZRange(pCtx, pCmd));
  803. // Update the command buffer pointer
  804. *ppCmd = (LPD3DHAL_DP2COMMAND)
  805. ((D3DHAL_DP2ZRANGE *)(pCmd + 1) + pCmd->wStateCount);
  806. }
  807. break;
  808. case D3DDP2OP_SETMATERIAL:
  809. {
  810. HR_RET(pCtx->pStateSetFuncTbl->pfnDp2SetMaterial(pCtx, pCmd));
  811. // Update the command buffer pointer
  812. *ppCmd = (LPD3DHAL_DP2COMMAND)
  813. ((D3DHAL_DP2SETMATERIAL *)(pCmd + 1) + pCmd->wStateCount);
  814. }
  815. break;
  816. case D3DDP2OP_SETLIGHT:
  817. {
  818. DWORD dwSLStride = 0;
  819. HR_RET(pCtx->pStateSetFuncTbl->pfnDp2SetLight(pCtx, pCmd,
  820. &dwSLStride));
  821. *ppCmd = (LPD3DHAL_DP2COMMAND)((LPBYTE)pCmd + dwSLStride);
  822. }
  823. break;
  824. case D3DDP2OP_CREATELIGHT:
  825. {
  826. HR_RET(pCtx->pStateSetFuncTbl->pfnDp2CreateLight(pCtx, pCmd));
  827. // Update the command buffer pointer
  828. *ppCmd = (LPD3DHAL_DP2COMMAND)
  829. ((D3DHAL_DP2CREATELIGHT *)(pCmd + 1) + pCmd->wStateCount);
  830. }
  831. break;
  832. case D3DDP2OP_SETTRANSFORM:
  833. {
  834. HR_RET(pCtx->pStateSetFuncTbl->pfnDp2SetTransform(pCtx, pCmd));
  835. // Update the command buffer pointer
  836. *ppCmd = (LPD3DHAL_DP2COMMAND)
  837. ((D3DHAL_DP2SETTRANSFORM *)(pCmd + 1) + pCmd->wStateCount);
  838. }
  839. break;
  840. case D3DDP2OP_EXT:
  841. {
  842. HR_RET(pCtx->pStateSetFuncTbl->pfnDp2SetExtention(pCtx, pCmd));
  843. // Update the command buffer pointer
  844. *ppCmd = (LPD3DHAL_DP2COMMAND)
  845. ((D3DHAL_DP2EXT *)(pCmd + 1) + pCmd->wStateCount);
  846. }
  847. break;
  848. case D3DDP2OP_SETRENDERTARGET:
  849. {
  850. HR_RET(pCtx->Dp2SetRenderTarget(pCmd));
  851. // Update the command buffer pointer
  852. *ppCmd = (LPD3DHAL_DP2COMMAND)
  853. ((D3DHAL_DP2SETRENDERTARGET*)(pCmd + 1) + pCmd->wStateCount);
  854. }
  855. break;
  856. case D3DDP2OP_CLEAR:
  857. {
  858. HR_RET(pCtx->Clear(pCmd));
  859. // Update the command buffer pointer
  860. *ppCmd = (LPD3DHAL_DP2COMMAND)((LPBYTE)(pCmd + 1) +
  861. sizeof(D3DHAL_DP2CLEAR) + (pCmd->wStateCount - 1) * sizeof(RECT));
  862. }
  863. break;
  864. case D3DDP2OP_SETCLIPPLANE:
  865. {
  866. HR_RET(pCtx->pStateSetFuncTbl->pfnDp2SetClipPlane(pCtx, pCmd));
  867. // Update the command buffer pointer
  868. *ppCmd = (LPD3DHAL_DP2COMMAND)
  869. ((D3DHAL_DP2SETCLIPPLANE *)(pCmd + 1) + pCmd->wStateCount);
  870. }
  871. break;
  872. default :
  873. hr = D3DParseUnknownCommand((LPVOID)pCmd, (LPVOID*)ppCmd);
  874. break;
  875. }
  876. return hr;
  877. }