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.

827 lines
25 KiB

  1. //----------------------------------------------------------------------------
  2. //
  3. // drawprim.cpp
  4. //
  5. // Implements DrawOnePrimitive, DrawOneIndexedPrimitive and
  6. // DrawPrimitives.
  7. //
  8. // Copyright (C) Microsoft Corporation, 1997.
  9. //
  10. //----------------------------------------------------------------------------
  11. #include "pch.cpp"
  12. #pragma hdrstop
  13. //----------------------------------------------------------------------------
  14. //
  15. // CheckFVF
  16. //
  17. // Check a FVF control word and then init m_fvfData accordingly
  18. //
  19. //----------------------------------------------------------------------------
  20. HRESULT FASTCALL
  21. D3DContext::CheckFVF(DWORD dwFVF)
  22. {
  23. // check if FVF controls have changed
  24. if ( (m_fvfData.preFVF == dwFVF) &&
  25. (m_fvfData.TexIdx[0] == (INT)m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_TEXCOORDINDEX)]) &&
  26. (m_fvfData.TexIdx[1] == (INT)m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(1,D3DTSS_TEXCOORDINDEX)]) &&
  27. (m_fvfData.cActTex == m_RastCtx.cActTex) )
  28. {
  29. return D3D_OK;
  30. }
  31. #if DBG
  32. // This is added here per Iouri's request. It will make it easier for him
  33. // to test his code for legacy drivers.
  34. if (dwFVF == 0)
  35. {
  36. dwFVF = D3DFVF_TLVERTEX;
  37. }
  38. #endif
  39. memset(&m_fvfData, 0, sizeof(FVFDATA));
  40. m_fvfData.preFVF = dwFVF;
  41. m_fvfData.TexIdx[0] = m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_TEXCOORDINDEX)];
  42. m_fvfData.TexIdx[1] = m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(1,D3DTSS_TEXCOORDINDEX)];
  43. m_fvfData.cActTex = m_RastCtx.cActTex;
  44. #if DBG
  45. // We only support max 8 texture coords
  46. if (m_fvfData.TexIdx[0] > 7 || m_fvfData.TexIdx[1] > 7)
  47. {
  48. D3D_WARN(0, "(Rast) Texture coord index bigger than max supported.");
  49. return DDERR_INVALIDPARAMS;
  50. }
  51. #endif
  52. // Update the copy of wrap states in RastCtx
  53. m_RastCtx.pdwWrap[0] = m_RastCtx.pdwRenderState[
  54. (D3DRENDERSTATETYPE)(D3DRENDERSTATE_WRAP0+m_fvfData.TexIdx[0])];
  55. m_RastCtx.pdwWrap[1] = m_RastCtx.pdwRenderState[
  56. (D3DRENDERSTATETYPE)(D3DRENDERSTATE_WRAP0+m_fvfData.TexIdx[1])];
  57. // do either true FVF parsing or legacy TLVERTEX handling
  58. if ( (m_RastCtx.BeadSet != D3DIBS_RAMP) &&
  59. ( (dwFVF != D3DFVF_TLVERTEX) ||
  60. (0 != m_fvfData.TexIdx[0]) ||
  61. (m_RastCtx.cActTex > 1) ) )
  62. { // New (non TL)FVF vertex
  63. // XYZ
  64. if ( (dwFVF & (D3DFVF_RESERVED0 | D3DFVF_RESERVED1 | D3DFVF_RESERVED2 |
  65. D3DFVF_NORMAL)) ||
  66. ((dwFVF & (D3DFVF_XYZ | D3DFVF_XYZRHW)) == 0) )
  67. {
  68. // can't set reserved bits, shouldn't have normals in
  69. // output to rasterizers, and must have coordinates
  70. return DDERR_INVALIDPARAMS;
  71. }
  72. m_fvfData.stride = sizeof(D3DVALUE) * 3;
  73. if (dwFVF & D3DFVF_XYZRHW)
  74. {
  75. m_fvfData.offsetRHW = m_fvfData.stride;
  76. m_fvfData.stride += sizeof(D3DVALUE);
  77. }
  78. if (dwFVF & D3DFVF_DIFFUSE)
  79. {
  80. m_fvfData.offsetDiff = m_fvfData.stride;
  81. m_fvfData.stride += sizeof(D3DCOLOR);
  82. }
  83. if (dwFVF & D3DFVF_SPECULAR)
  84. {
  85. m_fvfData.offsetSpec = m_fvfData.stride;
  86. m_fvfData.stride += sizeof(D3DCOLOR);
  87. }
  88. INT iTexCount = (dwFVF & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
  89. #if DBG
  90. INT iTexIdx0 = m_fvfData.TexIdx[0], iTexIdx1 = m_fvfData.TexIdx[1];
  91. if (iTexCount > 0)
  92. {
  93. if ( iTexIdx0 >= iTexCount)
  94. {
  95. D3D_WARN(1, "(Rast)Texture coord index bigger than texture coord count.");
  96. iTexIdx0 = 0;
  97. }
  98. if ( iTexIdx1 >= iTexCount)
  99. {
  100. D3D_WARN(1, "(Rast)Texture coord index bigger than texture coord count.");
  101. iTexIdx1 = 0;
  102. }
  103. // set offset for Textures 0 and 1
  104. m_fvfData.offsetTex0 = (INT16)(m_fvfData.stride +
  105. 2*sizeof(D3DVALUE)*iTexIdx0);
  106. m_fvfData.offsetTex1 = (INT16)(m_fvfData.stride +
  107. 2*sizeof(D3DVALUE)*iTexIdx1);
  108. // update stride
  109. m_fvfData.stride += (INT16)(iTexCount * (sizeof(D3DVALUE) * 2));
  110. }
  111. #else
  112. if (iTexCount > 0)
  113. {
  114. // set offset for Textures 0 and 1
  115. m_fvfData.offsetTex0 = (INT16)(m_fvfData.stride +
  116. 2*sizeof(D3DVALUE)*m_fvfData.TexIdx[0]);
  117. m_fvfData.offsetTex1 = (INT16)(m_fvfData.stride +
  118. 2*sizeof(D3DVALUE)*m_fvfData.TexIdx[1]);
  119. // update stride
  120. m_fvfData.stride += (INT16)(iTexCount * (sizeof(D3DVALUE) * 2));
  121. }
  122. #endif
  123. m_fvfData.vtxType = RAST_GENVERTEX;
  124. }
  125. else
  126. {
  127. // (Legacy) TL vertex
  128. if (0 < m_fvfData.TexIdx[0])
  129. {
  130. D3D_ERR("(Rast) Texture coord index bigger than 0 for legacy TL vertex.");
  131. return DDERR_INVALIDPARAMS;
  132. }
  133. m_fvfData.stride = sizeof(D3DTLVERTEX);
  134. m_fvfData.vtxType = RAST_TLVERTEX;
  135. }
  136. UpdatePrimFunctionTbl();
  137. return D3D_OK;
  138. }
  139. //----------------------------------------------------------------------------
  140. //
  141. // PackGenVertex
  142. //
  143. // Pack a FvFVertex into RAST_GENERIC_VERTEX. This is called for every non TL
  144. // FVF vertex. It can be optimized for speed later.
  145. //
  146. //----------------------------------------------------------------------------
  147. void FASTCALL
  148. D3DContext::PackGenVertex(PUINT8 pFvfVtx, RAST_GENERIC_VERTEX *pGenVtx)
  149. {
  150. pGenVtx->sx = *((D3DVALUE *)pFvfVtx);
  151. pGenVtx->sy = *((D3DVALUE *)pFvfVtx + 1);
  152. pGenVtx->sz = *((D3DVALUE *)pFvfVtx + 2);
  153. if (m_fvfData.offsetRHW)
  154. {
  155. pGenVtx->rhw = *((D3DVALUE *)(pFvfVtx + m_fvfData.offsetRHW));
  156. }
  157. else
  158. {
  159. pGenVtx->rhw = 1.0f;
  160. }
  161. if (m_fvfData.offsetDiff)
  162. {
  163. pGenVtx->color = *((D3DCOLOR *)(pFvfVtx + m_fvfData.offsetDiff));
  164. }
  165. else
  166. {
  167. pGenVtx->color = __DEFAULT_DIFFUSE;
  168. }
  169. if (m_fvfData.offsetSpec)
  170. {
  171. pGenVtx->specular = *((D3DCOLOR *)(pFvfVtx + m_fvfData.offsetSpec));
  172. }
  173. else
  174. {
  175. pGenVtx->specular = __DEFAULT_SPECULAR;
  176. }
  177. if (m_fvfData.offsetTex0)
  178. {
  179. pGenVtx->tu = *((D3DVALUE *)(pFvfVtx + m_fvfData.offsetTex0));
  180. pGenVtx->tv = *((D3DVALUE *)(pFvfVtx + m_fvfData.offsetTex0) + 1);
  181. }
  182. else
  183. {
  184. pGenVtx->tu = 0.0f;
  185. pGenVtx->tv = 0.0f;
  186. }
  187. if (m_fvfData.offsetTex1)
  188. {
  189. pGenVtx->tu2 = *((D3DVALUE *)(pFvfVtx + m_fvfData.offsetTex1));
  190. pGenVtx->tv2 = *((D3DVALUE *)(pFvfVtx + m_fvfData.offsetTex1) + 1);
  191. }
  192. else
  193. {
  194. pGenVtx->tu2 = 0.0f;
  195. pGenVtx->tv2 = 0.0f;
  196. }
  197. }
  198. //----------------------------------------------------------------------------
  199. //
  200. // DoDrawOnePrimitive
  201. //
  202. // Draw one list of primitives. It's called by both RastDrawOnePrimitive and
  203. // RastDrawPrimitives.
  204. //
  205. //----------------------------------------------------------------------------
  206. HRESULT FASTCALL
  207. DoDrawOnePrimitive(LPVOID pCtx,
  208. PRIMITIVE_FUNTIONS *pfnPrims,
  209. UINT16 FvfStride,
  210. PUINT8 pVtx,
  211. D3DPRIMITIVETYPE PrimType,
  212. UINT cVertices)
  213. {
  214. INT i;
  215. PUINT8 pV0, pV1, pV2;
  216. HRESULT hr;
  217. switch (PrimType)
  218. {
  219. case D3DPT_POINTLIST:
  220. for (i = (INT)cVertices; i > 0; i--)
  221. {
  222. HR_RET(pfnPrims->pfnPoint(pCtx, pVtx));
  223. pVtx += FvfStride;
  224. }
  225. break;
  226. case D3DPT_LINELIST:
  227. for (i = (INT)cVertices / 2; i > 0; i--)
  228. {
  229. pV0 = pVtx;
  230. pVtx += FvfStride;
  231. pV1 = pVtx;
  232. pVtx += FvfStride;
  233. HR_RET(pfnPrims->pfnLine(pCtx, pV0, pV1));
  234. }
  235. break;
  236. case D3DPT_LINESTRIP:
  237. {
  238. pV1 = pVtx;
  239. // Disable last-pixel setting for shared verties and store prestate.
  240. pfnPrims->pfnStoreLastPixelState(pCtx, 1);
  241. // Initial pV0.
  242. for (i = (INT)cVertices - 1; i > 1; i--)
  243. {
  244. pV0 = pV1;
  245. pVtx += FvfStride;
  246. pV1 = pVtx;
  247. HR_RET(pfnPrims->pfnLine(pCtx, pV0, pV1));
  248. }
  249. // Restore last-pixel setting.
  250. pfnPrims->pfnStoreLastPixelState(pCtx, 0);
  251. // Draw last line with last-pixel setting from state.
  252. if (i == 1)
  253. {
  254. pV0 = pVtx + FvfStride;
  255. HR_RET(pfnPrims->pfnLine(pCtx, pV1, pV0));
  256. }
  257. }
  258. break;
  259. case D3DPT_TRIANGLELIST:
  260. for (i = (INT)cVertices; i > 0; i -= 3)
  261. {
  262. pV0 = pVtx;
  263. pVtx += FvfStride;
  264. pV1 = pVtx;
  265. pVtx += FvfStride;
  266. pV2 = pVtx;
  267. pVtx += FvfStride;
  268. HR_RET(pfnPrims->pfnTri(pCtx, pV0, pV1, pV2, PFN_TRIANGLE_5ARG_DEFAULT));
  269. }
  270. break;
  271. case D3DPT_TRIANGLESTRIP:
  272. {
  273. // Get initial vertex values.
  274. pV1 = pVtx;
  275. pVtx += FvfStride;
  276. pV2 = pVtx;
  277. pVtx += FvfStride;
  278. for (i = (INT)cVertices - 2; i > 1; i -= 2)
  279. {
  280. pV0 = pV1;
  281. pV1 = pV2;
  282. pV2 = pVtx;
  283. pVtx += FvfStride;
  284. HR_RET(pfnPrims->pfnTri(pCtx, pV0, pV1, pV2, PFN_TRIANGLE_5ARG_DEFAULT));
  285. pV0 = pV1;
  286. pV1 = pV2;
  287. pV2 = pVtx;
  288. pVtx += FvfStride;
  289. HR_RET(pfnPrims->pfnTri(pCtx, pV0, pV2, pV1, PFN_TRIANGLE_5ARG_DEFAULT));
  290. }
  291. if (i > 0)
  292. {
  293. pV0 = pV1;
  294. pV1 = pV2;
  295. pV2 = pVtx;
  296. HR_RET(pfnPrims->pfnTri(pCtx, pV0, pV1, pV2, PFN_TRIANGLE_5ARG_DEFAULT));
  297. }
  298. }
  299. break;
  300. case D3DPT_TRIANGLEFAN:
  301. {
  302. pV2 = pVtx;
  303. pVtx += FvfStride;
  304. // Preload initial pV0.
  305. pV1 = pVtx;
  306. pVtx += FvfStride;
  307. for (i = (INT)cVertices - 2; i > 0; i--)
  308. {
  309. pV0 = pV1;
  310. pV1 = pVtx;
  311. pVtx += FvfStride;
  312. HR_RET(pfnPrims->pfnTri(pCtx, pV0, pV1, pV2, PFN_TRIANGLE_5ARG_DEFAULT));
  313. }
  314. }
  315. break;
  316. default:
  317. D3D_ERR("(Rast) Unknown or unsupported primitive type "
  318. "requested of DrawOnePrimitive");
  319. return DDERR_INVALIDPARAMS;
  320. }
  321. return D3D_OK;
  322. }
  323. //----------------------------------------------------------------------------
  324. //
  325. // DoDrawOneIndexedPrimitive
  326. //
  327. // Draw one list of indexed primitives. It's called by
  328. // RastDrawOneIndexedPrimitive.
  329. //
  330. //----------------------------------------------------------------------------
  331. HRESULT FASTCALL
  332. DoDrawOneIndexedPrimitive(LPVOID pCtx,
  333. PRIMITIVE_FUNTIONS *pfnPrims,
  334. UINT16 FvfStride,
  335. PUINT8 pVtx,
  336. LPWORD puIndices,
  337. D3DPRIMITIVETYPE PrimType,
  338. UINT cIndices)
  339. {
  340. INT i;
  341. PUINT8 pV0, pV1, pV2;
  342. HRESULT hr;
  343. switch(PrimType)
  344. {
  345. case D3DPT_POINTLIST:
  346. for (i = (INT)cIndices; i > 0; i--)
  347. {
  348. pV0 = pVtx + FvfStride * (*puIndices++);
  349. HR_RET(pfnPrims->pfnPoint(pCtx, pV0));
  350. }
  351. break;
  352. case D3DPT_LINELIST:
  353. for (i = (INT)cIndices / 2; i > 0; i--)
  354. {
  355. pV0 = pVtx + FvfStride * (*puIndices++);
  356. pV1 = pVtx + FvfStride * (*puIndices++);
  357. HR_RET(pfnPrims->pfnLine(pCtx, pV0, pV1));
  358. }
  359. break;
  360. case D3DPT_LINESTRIP:
  361. {
  362. // Disable last-pixel setting for shared verties and store prestate.
  363. pfnPrims->pfnStoreLastPixelState(pCtx, 1);
  364. // Initial pV1.
  365. pV1 = pVtx + FvfStride * (*puIndices++);
  366. for (i = (INT)cIndices - 1; i > 1; i--)
  367. {
  368. pV0 = pV1;
  369. pV1 = pVtx + FvfStride * (*puIndices++);
  370. HR_RET(pfnPrims->pfnLine(pCtx, pV0, pV1));
  371. }
  372. // Restore last-pixel setting.
  373. pfnPrims->pfnStoreLastPixelState(pCtx, 0);
  374. // Draw last line with last-pixel setting from state.
  375. if (i == 1)
  376. {
  377. pV0 = pVtx + FvfStride * (*puIndices);
  378. HR_RET(pfnPrims->pfnLine(pCtx, pV1, pV0));
  379. }
  380. }
  381. break;
  382. case D3DPT_TRIANGLELIST:
  383. for (i = (INT)cIndices; i > 0; i -= 3)
  384. {
  385. pV0 = pVtx + FvfStride * (*puIndices++);
  386. pV1 = pVtx + FvfStride * (*puIndices++);
  387. pV2 = pVtx + FvfStride * (*puIndices++);
  388. HR_RET(pfnPrims->pfnTri(pCtx, pV0, pV1, pV2, PFN_TRIANGLE_5ARG_DEFAULT));
  389. }
  390. break;
  391. case D3DPT_TRIANGLESTRIP:
  392. {
  393. // Get initial vertex values.
  394. pV1 = pVtx + FvfStride * (*puIndices++);
  395. pV2 = pVtx + FvfStride * (*puIndices++);
  396. for (i = (INT)cIndices - 2; i > 1; i -= 2)
  397. {
  398. pV0 = pV1;
  399. pV1 = pV2;
  400. pV2 = pVtx + FvfStride * (*puIndices++);
  401. HR_RET(pfnPrims->pfnTri(pCtx, pV0, pV1, pV2, PFN_TRIANGLE_5ARG_DEFAULT));
  402. pV0 = pV1;
  403. pV1 = pV2;
  404. pV2 = pVtx + FvfStride * (*puIndices++);
  405. HR_RET(pfnPrims->pfnTri(pCtx, pV0, pV2, pV1, PFN_TRIANGLE_5ARG_DEFAULT));
  406. }
  407. if (i > 0)
  408. {
  409. pV0 = pV1;
  410. pV1 = pV2;
  411. pV2 = pVtx + FvfStride * (*puIndices++);
  412. HR_RET(pfnPrims->pfnTri(pCtx, pV0, pV1, pV2, PFN_TRIANGLE_5ARG_DEFAULT));
  413. }
  414. }
  415. break;
  416. case D3DPT_TRIANGLEFAN:
  417. {
  418. pV2 = pVtx + FvfStride * (*puIndices++);
  419. // Preload initial pV0.
  420. pV1 = pVtx + FvfStride * (*puIndices++);
  421. for (i = (INT)cIndices - 2; i > 0; i--)
  422. {
  423. pV0 = pV1;
  424. pV1 = pVtx + FvfStride * (*puIndices++);
  425. HR_RET(pfnPrims->pfnTri(pCtx, pV0, pV1, pV2, PFN_TRIANGLE_5ARG_DEFAULT));
  426. }
  427. }
  428. break;
  429. default:
  430. D3D_ERR("(Rast) Unknown or unsupported primitive type "
  431. "requested of DrawOneIndexedPrimitive");
  432. return DDERR_INVALIDPARAMS;
  433. }
  434. return D3D_OK;
  435. }
  436. //----------------------------------------------------------------------------
  437. //
  438. // DoDrawOneEdgeFlagTriangleFan
  439. //
  440. // Draw one list of triangle fans. It's called by both RastDrawOnePrimitive and
  441. // RastDrawPrimitives.
  442. //
  443. //----------------------------------------------------------------------------
  444. HRESULT FASTCALL
  445. DoDrawOneEdgeFlagTriangleFan(LPVOID pCtx,
  446. PRIMITIVE_FUNTIONS *pfnPrims,
  447. UINT16 FvfStride,
  448. PUINT8 pVtx,
  449. UINT cVertices,
  450. UINT32 dwEdgeFlags)
  451. {
  452. INT i;
  453. PUINT8 pV0, pV1, pV2;
  454. HRESULT hr;
  455. pV2 = pVtx;
  456. pVtx += FvfStride;
  457. pV0 = pVtx;
  458. pVtx += FvfStride;
  459. pV1 = pVtx;
  460. pVtx += FvfStride;
  461. WORD wFlags = 0;
  462. if(dwEdgeFlags & 0x2)
  463. wFlags |= D3DTRIFLAG_EDGEENABLE1;
  464. if(dwEdgeFlags & 0x1)
  465. wFlags |= D3DTRIFLAG_EDGEENABLE3;
  466. if(cVertices == 3) {
  467. if(dwEdgeFlags & 0x4)
  468. wFlags |= D3DTRIFLAG_EDGEENABLE2;
  469. HR_RET(pfnPrims->pfnTri(pCtx, pV0, pV1, pV2, wFlags));
  470. return D3D_OK;
  471. }
  472. HR_RET(pfnPrims->pfnTri(pCtx, pV0, pV1, pV2, wFlags));
  473. UINT32 dwMask = 0x4;
  474. for (i = (INT)cVertices - 4; i > 0; i--)
  475. {
  476. pV0 = pV1;
  477. pV1 = pVtx;
  478. pVtx += FvfStride;
  479. if(dwEdgeFlags & dwMask)
  480. {
  481. HR_RET(pfnPrims->pfnTri(pCtx, pV0, pV1, pV2, D3DTRIFLAG_EDGEENABLE1));
  482. }
  483. else
  484. {
  485. HR_RET(pfnPrims->pfnTri(pCtx, pV0, pV1, pV2, 0));
  486. }
  487. dwMask <<= 1;
  488. }
  489. pV0 = pV1;
  490. pV1 = pVtx;
  491. wFlags = 0;
  492. if(dwEdgeFlags & dwMask)
  493. wFlags |= D3DTRIFLAG_EDGEENABLE1;
  494. dwMask <<= 1;
  495. if(dwEdgeFlags & dwMask)
  496. wFlags |= D3DTRIFLAG_EDGEENABLE2;
  497. HR_RET(pfnPrims->pfnTri(pCtx, pV0, pV1, pV2, wFlags));
  498. return D3D_OK;
  499. }
  500. #if DBG
  501. //----------------------------------------------------------------------------
  502. //
  503. // ValidatePrimType
  504. //
  505. // Check if the primitive type is supported. We could remove this function
  506. // after we have implemented all primitive types and then depend on D3DIM
  507. // to check if the primitive type is valid.
  508. //
  509. //----------------------------------------------------------------------------
  510. inline HRESULT
  511. D3DContext::ValidatePrimType(D3DPRIMITIVETYPE PrimitiveType)
  512. {
  513. switch(PrimitiveType)
  514. {
  515. case D3DPT_POINTLIST:
  516. case D3DPT_LINELIST:
  517. case D3DPT_LINESTRIP:
  518. case D3DPT_TRIANGLELIST:
  519. case D3DPT_TRIANGLEFAN:
  520. case D3DPT_TRIANGLESTRIP:
  521. break;
  522. default:
  523. D3D_ERR("(Rast) PrimitiveType not supported by the new rasterizer.");
  524. return DDERR_INVALIDPARAMS;
  525. }
  526. return D3D_OK;
  527. }
  528. #endif
  529. //----------------------------------------------------------------------------
  530. //
  531. // CheckDrawOnePrimitive
  532. //
  533. // Check if the DRAWONEPRIMITIVEDATA is valid.
  534. //
  535. //----------------------------------------------------------------------------
  536. inline HRESULT
  537. D3DContext::CheckDrawOnePrimitive(LPD3DHAL_DRAWONEPRIMITIVEDATA pOnePrimData)
  538. {
  539. #if DBG
  540. HRESULT hr;
  541. if (pOnePrimData == NULL ||
  542. pOnePrimData->dwhContext == 0 ||
  543. pOnePrimData->lpvVertices == NULL)
  544. {
  545. D3D_ERR("(Rast) Invalid data passed to the new rasterizer.");
  546. return DDERR_INVALIDPARAMS;
  547. }
  548. HR_RET(ValidatePrimType(pOnePrimData->PrimitiveType));
  549. #endif
  550. return D3D_OK;
  551. }
  552. //----------------------------------------------------------------------------
  553. //
  554. // CheckDrawOneIndexedPrimitive
  555. //
  556. // Check if the DRAWONEINDEXEDPRIMITIVEDATA is valid.
  557. //
  558. //----------------------------------------------------------------------------
  559. inline HRESULT
  560. D3DContext::CheckDrawOneIndexedPrimitive(
  561. LPD3DHAL_DRAWONEINDEXEDPRIMITIVEDATA pOneIdxPrimData)
  562. {
  563. #if DBG
  564. HRESULT hr;
  565. if (pOneIdxPrimData == NULL ||
  566. pOneIdxPrimData->dwhContext == 0 ||
  567. pOneIdxPrimData->lpvVertices == NULL ||
  568. pOneIdxPrimData->lpwIndices == NULL)
  569. {
  570. D3D_ERR("(Rast) Invalid data passed to the new rasterizer.");
  571. return DDERR_INVALIDPARAMS;
  572. }
  573. HR_RET(ValidatePrimType(pOneIdxPrimData->PrimitiveType));
  574. #endif
  575. return D3D_OK;
  576. }
  577. //----------------------------------------------------------------------------
  578. //
  579. // RastDrawOnePrimitive
  580. //
  581. // Draw one list of primitives. This is called by D3DIM for API DrawPrimitive.
  582. //
  583. //----------------------------------------------------------------------------
  584. DWORD __stdcall
  585. RastDrawOnePrimitive(LPD3DHAL_DRAWONEPRIMITIVEDATA pOnePrimData)
  586. {
  587. HRESULT hr;
  588. D3DContext *pDCtx;
  589. VALIDATE_D3DCONTEXT("RastDrawOnePrimitive", pOnePrimData);
  590. if ((pOnePrimData->ddrval =
  591. pDCtx->CheckDrawOnePrimitive(pOnePrimData)) != DD_OK)
  592. {
  593. return DDHAL_DRIVER_HANDLED;
  594. }
  595. // Check for FVF vertex, and init FVF related fileds if necessary
  596. // Assume the control word is passed in through dwFlags
  597. CHECK_FVF(pOnePrimData->ddrval, pDCtx, (DWORD)pOnePrimData->dwFVFControl);
  598. pOnePrimData->ddrval = pDCtx->Begin();
  599. if (pOnePrimData->ddrval != D3D_OK)
  600. {
  601. return DDHAL_DRIVER_HANDLED;
  602. }
  603. pOnePrimData->ddrval =
  604. pDCtx->DrawOnePrimitive((PUINT8)pOnePrimData->lpvVertices,
  605. pOnePrimData->PrimitiveType,
  606. pOnePrimData->dwNumVertices);
  607. hr = pDCtx->End();
  608. if (pOnePrimData->ddrval == D3D_OK)
  609. {
  610. pOnePrimData->ddrval = hr;
  611. }
  612. return DDHAL_DRIVER_HANDLED;
  613. }
  614. //----------------------------------------------------------------------------
  615. //
  616. // RastDrawOneIndexedPrimitive
  617. //
  618. // Draw one list of primitives. This is called by D3DIM for API
  619. // DrawIndexedPrimitive.
  620. //
  621. //----------------------------------------------------------------------------
  622. DWORD __stdcall
  623. RastDrawOneIndexedPrimitive(LPD3DHAL_DRAWONEINDEXEDPRIMITIVEDATA
  624. pOneIdxPrimData)
  625. {
  626. HRESULT hr;
  627. D3DContext *pDCtx;
  628. VALIDATE_D3DCONTEXT("RastDrawOneIndexedPrimitive", pOneIdxPrimData);
  629. if ((pOneIdxPrimData->ddrval =
  630. pDCtx->CheckDrawOneIndexedPrimitive(pOneIdxPrimData)) != DD_OK)
  631. {
  632. return DDHAL_DRIVER_HANDLED;
  633. }
  634. // Check for FVF vertex, and init FVF related fileds if necessary
  635. // Assume the control word is passed in through dwFlags
  636. CHECK_FVF(pOneIdxPrimData->ddrval, pDCtx, (DWORD)pOneIdxPrimData->dwFVFControl);
  637. pOneIdxPrimData->ddrval = pDCtx->Begin();
  638. if (pOneIdxPrimData->ddrval != D3D_OK)
  639. {
  640. return DDHAL_DRIVER_HANDLED;
  641. }
  642. pOneIdxPrimData->ddrval =
  643. pDCtx->DrawOneIndexedPrimitive((PUINT8)pOneIdxPrimData->lpvVertices,
  644. pOneIdxPrimData->lpwIndices,
  645. pOneIdxPrimData->PrimitiveType,
  646. pOneIdxPrimData->dwNumIndices);
  647. hr = pDCtx->End();
  648. if (pOneIdxPrimData->ddrval == D3D_OK)
  649. {
  650. pOneIdxPrimData->ddrval = hr;
  651. }
  652. return DDHAL_DRIVER_HANDLED;
  653. }
  654. //----------------------------------------------------------------------------
  655. //
  656. // RastDrawPrimitives
  657. //
  658. // This is called by D3DIM for a list of batched API DrawPrimitive calls.
  659. //
  660. //----------------------------------------------------------------------------
  661. DWORD __stdcall
  662. RastDrawPrimitives(LPD3DHAL_DRAWPRIMITIVESDATA pDrawPrimData)
  663. {
  664. PUINT8 pData = (PUINT8)pDrawPrimData->lpvData;
  665. LPD3DHAL_DRAWPRIMCOUNTS pDrawPrimitiveCounts;
  666. D3DContext *pDCtx;
  667. VALIDATE_D3DCONTEXT("RastDrawPrimitives", pDrawPrimData);
  668. pDrawPrimitiveCounts = (LPD3DHAL_DRAWPRIMCOUNTS)pData;
  669. // Check for FVF vertex when there are actually something to be drawn, and
  670. // init FVF related fileds if necessary Assume the control word is passed
  671. // in through dwReserved
  672. if (pDrawPrimitiveCounts->wNumVertices > 0)
  673. {
  674. CHECK_FVF(pDrawPrimData->ddrval, pDCtx, pDrawPrimData->dwFVFControl);
  675. }
  676. // Skip state check and texture lock if the first thing is state change
  677. if (pDrawPrimitiveCounts->wNumStateChanges == 0)
  678. {
  679. pDrawPrimData->ddrval =pDCtx->Begin();
  680. if (pDrawPrimData->ddrval != D3D_OK)
  681. {
  682. goto EH_Exit;
  683. }
  684. }
  685. // Loop through the data, update render states
  686. // and then draw the primitive
  687. for (;;)
  688. {
  689. pDrawPrimitiveCounts = (LPD3DHAL_DRAWPRIMCOUNTS)pData;
  690. pData += sizeof(D3DHAL_DRAWPRIMCOUNTS);
  691. //
  692. // Update render states
  693. //
  694. if (pDrawPrimitiveCounts->wNumStateChanges > 0)
  695. {
  696. // Flush the prim proc before any state changs
  697. pDrawPrimData->ddrval = pDCtx->End(FALSE);
  698. if (pDrawPrimData->ddrval != D3D_OK)
  699. {
  700. return DDHAL_DRIVER_HANDLED;
  701. }
  702. pDrawPrimData->ddrval =
  703. pDCtx->UpdateRenderStates((LPDWORD)pData,
  704. pDrawPrimitiveCounts->wNumStateChanges);
  705. if (pDrawPrimData->ddrval != D3D_OK)
  706. {
  707. goto EH_Exit;
  708. }
  709. pData += pDrawPrimitiveCounts->wNumStateChanges *
  710. sizeof(DWORD) * 2;
  711. }
  712. // Check for exit
  713. if (pDrawPrimitiveCounts->wNumVertices == 0)
  714. {
  715. break;
  716. }
  717. // Align pointer to vertex data
  718. pData = (PUINT8)
  719. ((UINT_PTR)(pData + (DP_VTX_ALIGN - 1)) & ~(DP_VTX_ALIGN - 1));
  720. // Delayed change until we really need to render something
  721. if (pDrawPrimitiveCounts->wNumStateChanges > 0)
  722. {
  723. // We might have a new texture so lock.
  724. pDrawPrimData->ddrval = pDCtx->Begin();
  725. if (pDrawPrimData->ddrval != D3D_OK)
  726. {
  727. goto EH_Exit;
  728. }
  729. }
  730. //
  731. // Primitives
  732. //
  733. pDrawPrimData->ddrval =
  734. pDCtx->DrawOnePrimitive((PUINT8)pData,
  735. (D3DPRIMITIVETYPE)pDrawPrimitiveCounts->wPrimitiveType,
  736. pDrawPrimitiveCounts->wNumVertices);
  737. if (pDrawPrimData->ddrval != DD_OK)
  738. {
  739. goto EH_Exit;
  740. }
  741. pData += pDrawPrimitiveCounts->wNumVertices * pDCtx->GetFvfStride();
  742. }
  743. EH_Exit:
  744. HRESULT hr;
  745. hr = pDCtx->End();
  746. if (pDrawPrimData->ddrval == D3D_OK)
  747. {
  748. pDrawPrimData->ddrval = hr;
  749. }
  750. return DDHAL_DRIVER_HANDLED;
  751. }