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.

560 lines
22 KiB

  1. //----------------------------------------------------------------------------
  2. //
  3. // dprim2.cpp
  4. //
  5. // Implements DrawPrimitives2.
  6. //
  7. // Copyright (C) Microsoft Corporation, 1997.
  8. //
  9. //----------------------------------------------------------------------------
  10. include(`m4hdr.mh')dnl
  11. #include "pch.cpp"
  12. #pragma hdrstop
  13. inline D3DPRIMITIVETYPE ConvertDP2OPToPrimType(D3DHAL_DP2OPERATION Dp2Op)
  14. {
  15. switch (Dp2Op)
  16. {
  17. case D3DDP2OP_POINTS :
  18. return D3DPT_POINTLIST;
  19. case D3DDP2OP_INDEXEDLINELIST :
  20. case D3DDP2OP_INDEXEDLINELIST2 :
  21. case D3DDP2OP_LINELIST_IMM :
  22. case D3DDP2OP_LINELIST :
  23. return D3DPT_LINELIST;
  24. case D3DDP2OP_TRIANGLELIST :
  25. case D3DDP2OP_INDEXEDTRIANGLELIST :
  26. case D3DDP2OP_INDEXEDTRIANGLELIST2:
  27. return D3DPT_TRIANGLELIST;
  28. case D3DDP2OP_LINESTRIP :
  29. case D3DDP2OP_INDEXEDLINESTRIP :
  30. return D3DPT_LINESTRIP;
  31. case D3DDP2OP_TRIANGLESTRIP :
  32. case D3DDP2OP_INDEXEDTRIANGLESTRIP:
  33. return D3DPT_TRIANGLESTRIP;
  34. case D3DDP2OP_TRIANGLEFAN :
  35. case D3DDP2OP_INDEXEDTRIANGLEFAN :
  36. case D3DDP2OP_TRIANGLEFAN_IMM :
  37. return D3DPT_TRIANGLEFAN;
  38. case D3DDP2OP_RENDERSTATE :
  39. case D3DDP2OP_TEXTURESTAGESTATE :
  40. case D3DDP2OP_VIEWPORTINFO :
  41. case D3DDP2OP_WINFO :
  42. default:
  43. D3D_INFO(4, "(Rast)Non primitive operation operation in DrawPrimitives2");
  44. return (D3DPRIMITIVETYPE)0;
  45. }
  46. }
  47. define(`d_DrawPrim2', `
  48. //----------------------------------------------------------------------------
  49. //
  50. // $1DrawPrimitives2
  51. //
  52. // This is called by D3DIM for API DrawPrimitives2 to draw a set of primitives
  53. // using a vertex buffer.
  54. //
  55. //----------------------------------------------------------------------------
  56. DWORD __stdcall
  57. $1DrawPrimitives2(LPD3DHAL_DRAWPRIMITIVES2DATA pDPrim2Data)
  58. {
  59. HRESULT hr;
  60. ifelse(`$1', `Rast',`
  61. D3DContext *pDCtx;', `
  62. ReferenceRasterizer *pRefRast;
  63. DWORD dwStride;')
  64. PUINT8 pVtData = NULL;
  65. ifelse(`$1', `Rast',`
  66. VALIDATE_D3DCONTEXT("RastDrawPrimitives2", pDPrim2Data);', `
  67. VALIDATE_REFRAST_CONTEXT("RefRastDrawPrimitives", pDPrim2Data);')
  68. if( pDPrim2Data->lpVertices )
  69. {
  70. if (pDPrim2Data->dwFlags & D3DHALDP2_USERMEMVERTICES)
  71. pVtData = (PUINT8)pDPrim2Data->lpVertices + pDPrim2Data->dwVertexOffset;
  72. else
  73. pVtData = (PUINT8)pDPrim2Data->lpDDVertex->lpGbl->fpVidMem + pDPrim2Data->dwVertexOffset;
  74. }
  75. LPD3DHAL_DP2COMMAND pCmd = (LPD3DHAL_DP2COMMAND)
  76. ((PUINT8)pDPrim2Data->lpDDCommands->lpGbl->fpVidMem +
  77. pDPrim2Data->dwCommandOffset);
  78. UINT_PTR CmdBoundary = (UINT_PTR)pCmd +
  79. pDPrim2Data->dwCommandLength;
  80. ifelse(`$1', `Rast', `
  81. // Check for FVF vertex, and init FVF related fileds if necessary
  82. CHECK_FVF(pDPrim2Data->ddrval, pDCtx, (DWORD)pDPrim2Data->dwVertexType);', `
  83. // Unconditionally get the vertex stride, since it can not change
  84. if ((pDPrim2Data->ddrval = FVFCheckAndStride(
  85. (DWORD)pDPrim2Data->dwVertexType, &dwStride)) != D3D_OK)
  86. {
  87. return DDHAL_DRIVER_HANDLED;
  88. }
  89. if ((pDPrim2Data->ddrval=RefRastLockTarget(pRefRast)) != D3D_OK)
  90. {
  91. return DDHAL_DRIVER_HANDLED;
  92. }')dnl
  93. // Skip state check and texture lock if the first thing is state change
  94. //
  95. // WINFO is excluded here because it currently does not affect RGB/MMX
  96. // and refrast does not care if it changes between begin/endrendering.
  97. //
  98. // VIEWPORTINFO is excluded here because it is OK to change the viewport
  99. // between begin/endrendering on both RGB/MMX and Ref.
  100. //
  101. if (pCmd->bCommand != D3DDP2OP_RENDERSTATE &&
  102. pCmd->bCommand != D3DDP2OP_TEXTURESTAGESTATE)
  103. {
  104. ifelse(`$1', `Rast', `
  105. pDPrim2Data->ddrval = pDCtx->Begin();
  106. if (pDPrim2Data->ddrval != D3D_OK)
  107. {
  108. return DDHAL_DRIVER_HANDLED;
  109. }', `
  110. if ((pDPrim2Data->ddrval=RefRastLockTexture(pRefRast)) != D3D_OK)
  111. {
  112. return DDHAL_DRIVER_HANDLED;
  113. }
  114. if ((pDPrim2Data->ddrval =
  115. pRefRast->BeginRendering((DWORD)pDPrim2Data->dwVertexType)) != D3D_OK)
  116. {
  117. return DDHAL_DRIVER_HANDLED;
  118. }')
  119. }
  120. // Loop through the data, update render states
  121. // and then draw the primitive
  122. for (;;)
  123. {
  124. LPDWORD lpdwRStates;
  125. if (pDPrim2Data->dwFlags & D3DHALDP2_EXECUTEBUFFER)
  126. lpdwRStates = pDPrim2Data->lpdwRStates;
  127. else
  128. lpdwRStates = NULL;
  129. ifelse(`$1', `Rast', `
  130. D3DPRIMITIVETYPE Primtype =
  131. ConvertDP2OPToPrimType((D3DHAL_DP2OPERATION)pCmd->bCommand);
  132. if (Primtype > 0)
  133. {
  134. pDCtx->BeginPrimSet(Primtype, pDCtx->GetFvfVertexType());
  135. }
  136. BOOL bWireframe =
  137. (pDCtx->GetRastCtx())->pdwRenderState[D3DRENDERSTATE_FILLMODE]
  138. == D3DFILL_WIREFRAME;
  139. pDPrim2Data->ddrval = DoDrawPrimitives2((LPVOID)pDCtx,
  140. pDCtx->GetFunsTbl(),
  141. (UINT16)pDCtx->GetFvfStride(),
  142. (DWORD)pDPrim2Data->dwVertexType,
  143. pVtData,
  144. &pCmd,
  145. lpdwRStates,
  146. bWireframe
  147. );', `
  148. BOOL bWireframe = pRefRast->GetRenderState()[D3DRENDERSTATE_FILLMODE]
  149. == D3DFILL_WIREFRAME;
  150. pDPrim2Data->ddrval = DoDrawPrimitives2((LPVOID)pRefRast,
  151. (PRIMITIVE_FUNTIONS *)
  152. (((PUINT8)pRefRast->GetUserPrivate())+sizeof(D3DFE_STATESET)),
  153. (UINT16)dwStride,
  154. (DWORD)pDPrim2Data->dwVertexType,
  155. pVtData,
  156. &pCmd,
  157. lpdwRStates,
  158. bWireframe
  159. );')
  160. if (pDPrim2Data->ddrval != D3D_OK)
  161. {
  162. if (pDPrim2Data->ddrval == D3DERR_COMMAND_UNPARSED)
  163. {
  164. pDPrim2Data->dwErrorOffset = (UINT32)((ULONG_PTR)pCmd -
  165. (UINT_PTR)(pDPrim2Data->lpDDCommands->lpGbl->fpVidMem));
  166. }
  167. goto EH_Exit;
  168. }
  169. if ((UINT_PTR)pCmd >= CmdBoundary)
  170. break;
  171. }
  172. EH_Exit:
  173. ifelse(`$1', `Rast', `
  174. hr = pDCtx->End();', `
  175. hr = pRefRast->EndRendering();
  176. RefRastUnlockTexture(pRefRast);
  177. RefRastUnlockTarget(pRefRast);')
  178. if (pDPrim2Data->ddrval == D3D_OK)
  179. {
  180. pDPrim2Data->ddrval = hr;
  181. }
  182. return DDHAL_DRIVER_HANDLED;
  183. }')
  184. d_DrawPrim2(`Rast')
  185. HRESULT FASTCALL
  186. DoDrawIndexedTriList2(LPVOID pCtx,
  187. PRIMITIVE_FUNTIONS *pfnPrims,
  188. DWORD dwStride,
  189. PUINT8 pVtx,
  190. WORD cPrims,
  191. D3DHAL_DP2INDEXEDTRIANGLELIST *pTriList)
  192. {
  193. INT i;
  194. D3DHAL_DP2INDEXEDTRIANGLELIST *pTri = pTriList;
  195. for (i = 0; i < cPrims; i ++)
  196. {
  197. HRESULT hr;
  198. PUINT8 pVtx0, pVtx1, pVtx2;
  199. pVtx0 = pVtx + dwStride * pTri->wV1;
  200. pVtx1 = pVtx + dwStride * pTri->wV2;
  201. pVtx2 = pVtx + dwStride * pTri->wV3;
  202. HR_RET(pfnPrims->pfnTri(pCtx,
  203. pVtx0,
  204. pVtx1,
  205. pVtx2,
  206. pTri->wFlags));
  207. pTri ++;
  208. }
  209. return D3D_OK;
  210. }
  211. //----------------------------------------------------------------------------
  212. //
  213. // DoDrawPrimitives2
  214. //
  215. // It's called by RastDrawPrimitives2. .
  216. //
  217. //----------------------------------------------------------------------------
  218. HRESULT FASTCALL
  219. DoDrawPrimitives2(LPVOID pCtx,
  220. PRIMITIVE_FUNTIONS *pfnPrims,
  221. UINT16 dwStride,
  222. DWORD dwFvf,
  223. PUINT8 pVtx,
  224. LPD3DHAL_DP2COMMAND *ppCmd,
  225. LPDWORD lpdwRStates,
  226. BOOL bWireframe
  227. )
  228. {
  229. LPD3DHAL_DP2COMMAND pCmd = *ppCmd;
  230. HRESULT hr;
  231. // If there is no vertex information for a drawing command,
  232. // then we cannot draw, quit with an error.
  233. switch(pCmd->bCommand)
  234. {
  235. case D3DDP2OP_POINTS:
  236. case D3DDP2OP_LINELIST:
  237. case D3DDP2OP_LINESTRIP:
  238. case D3DDP2OP_TRIANGLELIST:
  239. case D3DDP2OP_TRIANGLESTRIP:
  240. case D3DDP2OP_TRIANGLEFAN:
  241. case D3DDP2OP_INDEXEDLINELIST:
  242. case D3DDP2OP_INDEXEDLINELIST2:
  243. case D3DDP2OP_INDEXEDLINESTRIP:
  244. case D3DDP2OP_INDEXEDTRIANGLELIST:
  245. case D3DDP2OP_INDEXEDTRIANGLELIST2:
  246. case D3DDP2OP_INDEXEDTRIANGLESTRIP:
  247. case D3DDP2OP_INDEXEDTRIANGLEFAN:
  248. if( NULL == pVtx )
  249. return DDERR_OUTOFMEMORY; // The most likely cause
  250. }
  251. D3D_INFO(7, "(Rast)Read Ins: %08lx", *(LPDWORD)pCmd);
  252. switch(pCmd->bCommand)
  253. {
  254. case D3DDP2OP_VIEWPORTINFO:
  255. {
  256. HR_RET(pfnPrims->pfnDp2SetViewport(pCtx, pCmd));
  257. // Update the command buffer pointer
  258. *ppCmd = (LPD3DHAL_DP2COMMAND)
  259. ((D3DHAL_DP2VIEWPORTINFO *)(pCmd + 1) + pCmd->wStateCount);
  260. }
  261. break;
  262. case D3DDP2OP_WINFO:
  263. {
  264. HR_RET(pfnPrims->pfnDp2SetWRange(pCtx, pCmd));
  265. // Update the command buffer pointer
  266. *ppCmd = (LPD3DHAL_DP2COMMAND)
  267. ((D3DHAL_DP2WINFO *)(pCmd + 1) + pCmd->wStateCount);
  268. }
  269. break;
  270. case D3DDP2OP_RENDERSTATE:
  271. {
  272. HR_RET(pfnPrims->pfnDp2SetRenderStates(pCtx, dwFvf, pCmd, lpdwRStates));
  273. // Update the command buffer pointer
  274. *ppCmd = (LPD3DHAL_DP2COMMAND)
  275. ((D3DHAL_DP2RENDERSTATE *)(pCmd + 1) + pCmd->wStateCount);
  276. }
  277. break;
  278. case D3DDP2OP_TEXTURESTAGESTATE:
  279. {
  280. HR_RET(pfnPrims->pfnDp2TextureStageState(pCtx, dwFvf, pCmd));
  281. // Update the command buffer pointer
  282. *ppCmd = (LPD3DHAL_DP2COMMAND)
  283. ((LPD3DHAL_DP2TEXTURESTAGESTATE)(pCmd + 1) + pCmd->wStateCount);
  284. }
  285. break;
  286. // This is a special case because it has edge flags. Other D3DDP2OP
  287. // can actually make use of DoDrawOneIndexedPrimitive/DoDrawOnePrimitive.
  288. case D3DDP2OP_INDEXEDTRIANGLELIST:
  289. {
  290. WORD cPrims = pCmd->wPrimitiveCount;
  291. HR_RET(DoDrawIndexedTriList2(pCtx,
  292. pfnPrims,
  293. dwStride,
  294. pVtx,
  295. cPrims,
  296. (D3DHAL_DP2INDEXEDTRIANGLELIST *)(pCmd + 1)));
  297. // Update the command buffer pointer
  298. *ppCmd = (LPD3DHAL_DP2COMMAND)((PUINT8)(pCmd + 1) +
  299. sizeof(D3DHAL_DP2INDEXEDTRIANGLELIST) * cPrims);
  300. }
  301. break;
  302. case D3DDP2OP_INDEXEDLINELIST:
  303. {
  304. HR_RET(DoDrawOneIndexedPrimitive(pCtx,
  305. pfnPrims,
  306. dwStride,
  307. pVtx,
  308. (LPWORD)(pCmd + 1),
  309. D3DPT_LINELIST,
  310. pCmd->wPrimitiveCount * 2));
  311. // Update the command buffer pointer
  312. *ppCmd = (LPD3DHAL_DP2COMMAND)((PUINT8)(pCmd + 1) +
  313. pCmd->wPrimitiveCount * sizeof(D3DHAL_DP2INDEXEDLINELIST));
  314. }
  315. break;
  316. // Following ops All use DoDrawOneIndexedPrimitive/DoDrawOnePrimitive.
  317. // There are some extra overheads introduced because those two functions
  318. // need to switch over the PrimTypes while we already know it here.
  319. // Striping out the code to add inline functions for each PrimType means
  320. // adding about twenty functions(considering the types of prim times types
  321. // of vertex). So I have used DoDrawOneIndexedPrimitive/DoDrawOnePrimitive
  322. // here anyway. We can later change it if necessary.
  323. case D3DDP2OP_POINTS:
  324. {
  325. WORD cPrims = pCmd->wPrimitiveCount;
  326. WORD i;
  327. D3DHAL_DP2POINTS *pPt = (D3DHAL_DP2POINTS *)(pCmd + 1);
  328. for (i = 0; i < cPrims; i++)
  329. {
  330. HR_RET(DoDrawOnePrimitive(pCtx,
  331. pfnPrims,
  332. dwStride,
  333. (pVtx + pPt->wVStart * dwStride),
  334. D3DPT_POINTLIST,
  335. pPt->wCount));
  336. pPt ++;
  337. }
  338. // Update the command buffer pointer
  339. *ppCmd = (LPD3DHAL_DP2COMMAND)pPt;
  340. }
  341. break;
  342. case D3DDP2OP_LINELIST:
  343. {
  344. D3DHAL_DP2LINELIST *pLine = (D3DHAL_DP2LINELIST *)(pCmd + 1);
  345. HR_RET(DoDrawOnePrimitive(pCtx,
  346. pfnPrims,
  347. dwStride,
  348. (pVtx + pLine->wVStart * dwStride),
  349. D3DPT_LINELIST,
  350. pCmd->wPrimitiveCount * 2));
  351. // Update the command buffer pointer
  352. *ppCmd = (LPD3DHAL_DP2COMMAND)(pLine + 1);
  353. }
  354. break;
  355. case D3DDP2OP_INDEXEDLINELIST2:
  356. {
  357. LPD3DHAL_DP2STARTVERTEX lpStartVertex;
  358. lpStartVertex = (LPD3DHAL_DP2STARTVERTEX)(pCmd + 1);
  359. HR_RET(DoDrawOneIndexedPrimitive(pCtx,
  360. pfnPrims,
  361. dwStride,
  362. pVtx + lpStartVertex->wVStart*dwStride,
  363. (LPWORD)(lpStartVertex + 1),
  364. D3DPT_LINELIST,
  365. pCmd->wPrimitiveCount * 2));
  366. // Update the command buffer pointer
  367. *ppCmd = (LPD3DHAL_DP2COMMAND)((PUINT8)(lpStartVertex + 1) +
  368. pCmd->wPrimitiveCount * sizeof(D3DHAL_DP2INDEXEDLINELIST));
  369. }
  370. break;
  371. case D3DDP2OP_LINESTRIP:
  372. {
  373. D3DHAL_DP2LINESTRIP *pLine = (D3DHAL_DP2LINESTRIP *)(pCmd + 1);
  374. HR_RET(DoDrawOnePrimitive(pCtx,
  375. pfnPrims,
  376. dwStride,
  377. (pVtx + pLine->wVStart * dwStride),
  378. D3DPT_LINESTRIP,
  379. pCmd->wPrimitiveCount + 1));
  380. // Update the command buffer pointer
  381. *ppCmd = (LPD3DHAL_DP2COMMAND)(pLine + 1);
  382. }
  383. break;
  384. case D3DDP2OP_INDEXEDLINESTRIP:
  385. {
  386. DWORD vertexCount = pCmd->wPrimitiveCount + 1;
  387. LPD3DHAL_DP2STARTVERTEX lpStartVertex;
  388. lpStartVertex = (LPD3DHAL_DP2STARTVERTEX)(pCmd + 1);
  389. HR_RET(DoDrawOneIndexedPrimitive(pCtx,
  390. pfnPrims,
  391. dwStride,
  392. pVtx + lpStartVertex->wVStart*dwStride,
  393. (LPWORD)(lpStartVertex + 1),
  394. D3DPT_LINESTRIP,
  395. vertexCount));
  396. // Update the command buffer pointer
  397. *ppCmd = (LPD3DHAL_DP2COMMAND)((PUINT8)(lpStartVertex + 1) +
  398. vertexCount * sizeof(WORD));
  399. }
  400. break;
  401. case D3DDP2OP_TRIANGLELIST:
  402. {
  403. D3DHAL_DP2TRIANGLELIST *pTri = (D3DHAL_DP2TRIANGLELIST *)(pCmd + 1);
  404. HR_RET(DoDrawOnePrimitive(pCtx,
  405. pfnPrims,
  406. dwStride,
  407. (pVtx + pTri->wVStart * dwStride),
  408. D3DPT_TRIANGLELIST,
  409. pCmd->wPrimitiveCount * 3));
  410. // Update the command buffer pointer
  411. *ppCmd = (LPD3DHAL_DP2COMMAND)(pTri + 1);
  412. }
  413. break;
  414. case D3DDP2OP_INDEXEDTRIANGLELIST2:
  415. {
  416. DWORD vertexCount = pCmd->wPrimitiveCount*3;
  417. LPD3DHAL_DP2STARTVERTEX lpStartVertex;
  418. lpStartVertex = (LPD3DHAL_DP2STARTVERTEX)(pCmd + 1);
  419. HR_RET(DoDrawOneIndexedPrimitive(pCtx,
  420. pfnPrims,
  421. dwStride,
  422. pVtx + lpStartVertex->wVStart*dwStride,
  423. (LPWORD)(lpStartVertex + 1),
  424. D3DPT_TRIANGLELIST,
  425. vertexCount));
  426. // Update the command buffer pointer
  427. *ppCmd = (LPD3DHAL_DP2COMMAND)((PUINT8)(lpStartVertex + 1) +
  428. vertexCount * sizeof(WORD));
  429. }
  430. break;
  431. case D3DDP2OP_TRIANGLESTRIP:
  432. {
  433. D3DHAL_DP2TRIANGLESTRIP *pTri = (D3DHAL_DP2TRIANGLESTRIP *)(pCmd + 1);
  434. HR_RET(DoDrawOnePrimitive(pCtx,
  435. pfnPrims,
  436. dwStride,
  437. (pVtx + pTri->wVStart * dwStride),
  438. D3DPT_TRIANGLESTRIP,
  439. pCmd->wPrimitiveCount + 2));
  440. // Update the command buffer pointer
  441. *ppCmd = (LPD3DHAL_DP2COMMAND)(pTri + 1);
  442. }
  443. break;
  444. case D3DDP2OP_INDEXEDTRIANGLESTRIP:
  445. {
  446. DWORD vertexCount = pCmd->wPrimitiveCount+2;
  447. LPD3DHAL_DP2STARTVERTEX lpStartVertex;
  448. lpStartVertex = (LPD3DHAL_DP2STARTVERTEX)(pCmd + 1);
  449. HR_RET(DoDrawOneIndexedPrimitive(pCtx,
  450. pfnPrims,
  451. dwStride,
  452. pVtx + lpStartVertex->wVStart*dwStride,
  453. (LPWORD)(lpStartVertex + 1),
  454. D3DPT_TRIANGLESTRIP,
  455. vertexCount));
  456. // Update the command buffer pointer
  457. *ppCmd = (LPD3DHAL_DP2COMMAND)((PUINT8)(lpStartVertex + 1) +
  458. vertexCount * sizeof(WORD));
  459. }
  460. break;
  461. case D3DDP2OP_TRIANGLEFAN:
  462. {
  463. D3DHAL_DP2TRIANGLEFAN *pTri = (D3DHAL_DP2TRIANGLEFAN *)(pCmd + 1);
  464. HR_RET(DoDrawOnePrimitive(pCtx,
  465. pfnPrims,
  466. dwStride,
  467. (pVtx + pTri->wVStart * dwStride),
  468. D3DPT_TRIANGLEFAN,
  469. pCmd->wPrimitiveCount + 2));
  470. // Update the command buffer pointer
  471. *ppCmd = (LPD3DHAL_DP2COMMAND)(pTri + 1);
  472. }
  473. break;
  474. case D3DDP2OP_INDEXEDTRIANGLEFAN:
  475. {
  476. DWORD vertexCount = pCmd->wPrimitiveCount + 2;
  477. LPD3DHAL_DP2STARTVERTEX lpStartVertex;
  478. lpStartVertex = (LPD3DHAL_DP2STARTVERTEX)(pCmd + 1);
  479. HR_RET(DoDrawOneIndexedPrimitive(pCtx,
  480. pfnPrims,
  481. dwStride,
  482. pVtx + lpStartVertex->wVStart*dwStride,
  483. (LPWORD)(lpStartVertex + 1),
  484. D3DPT_TRIANGLEFAN,
  485. vertexCount));
  486. // Update the command buffer pointer
  487. *ppCmd = (LPD3DHAL_DP2COMMAND)((PUINT8)(lpStartVertex + 1) +
  488. vertexCount * sizeof(WORD));
  489. }
  490. break;
  491. case D3DDP2OP_TRIANGLEFAN_IMM:
  492. {
  493. DWORD vertexCount = pCmd->wPrimitiveCount + 2;
  494. // Make sure the pFanVtx pointer is DWORD aligned: (pFanVtx +3) % 4
  495. PUINT8 pFanVtx = (PUINT8)(((ULONG_PTR)(pCmd + 1) +
  496. sizeof(D3DHAL_DP2TRIANGLEFAN_IMM) + 3) & ~3);
  497. if (bWireframe)
  498. {
  499. // Read edge flags
  500. UINT32 dwEdgeFlags =
  501. ((LPD3DHAL_DP2TRIANGLEFAN_IMM)(pCmd + 1))->dwEdgeFlags;
  502. HR_RET(DoDrawOneEdgeFlagTriangleFan(pCtx,
  503. pfnPrims,
  504. dwStride,
  505. pFanVtx,
  506. vertexCount,
  507. dwEdgeFlags));
  508. }
  509. else
  510. {
  511. HR_RET(DoDrawOnePrimitive(pCtx,
  512. pfnPrims,
  513. dwStride,
  514. pFanVtx,
  515. D3DPT_TRIANGLEFAN,
  516. vertexCount));
  517. }
  518. // Update the command buffer pointer
  519. *ppCmd = (LPD3DHAL_DP2COMMAND)((PUINT8)pFanVtx +
  520. vertexCount * dwStride);
  521. }
  522. break;
  523. case D3DDP2OP_LINELIST_IMM:
  524. {
  525. DWORD vertexCount = pCmd->wPrimitiveCount * 2;
  526. // Make sure the pLineVtx pointer is DWORD aligned: (pLineVtx +3) % 4
  527. PUINT8 pLineVtx = (PUINT8)(((ULONG_PTR)(pCmd + 1) + 3) & ~3);
  528. HR_RET(DoDrawOnePrimitive(pCtx,
  529. pfnPrims,
  530. dwStride,
  531. pLineVtx,
  532. D3DPT_LINELIST,
  533. vertexCount));
  534. // Update the command buffer pointer
  535. *ppCmd = (LPD3DHAL_DP2COMMAND)((PUINT8)pLineVtx +
  536. vertexCount * dwStride);
  537. }
  538. break;
  539. default :
  540. hr = D3DParseUnknownCommand((LPVOID)pCmd, (LPVOID*)ppCmd);
  541. break;
  542. }
  543. return hr;
  544. }