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.

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