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.

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