Source code of Windows XP (NT5)
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.

1420 lines
43 KiB

  1. /*============================================================================
  2. *
  3. * Copyright (C) 1999 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: vshader.cpp
  6. * Content: SetStreamSource and VertexShader
  7. * software implementation.
  8. *
  9. ****************************************************************************/
  10. #include "pch.cpp"
  11. #pragma hdrstop
  12. /////////////////////////////////////////////////////////////////////////
  13. //
  14. // Helper functions
  15. //
  16. /////////////////////////////////////////////////////////////////////////
  17. void
  18. Copy_FLOAT1( LPVOID pInputStream, RDVECTOR4* pVertexRegister )
  19. {
  20. pVertexRegister->x = *(float*)pInputStream;
  21. pVertexRegister->y = 0;
  22. pVertexRegister->z = 0;
  23. pVertexRegister->w = 1;
  24. }
  25. void
  26. Copy_FLOAT2( LPVOID pInputStream, RDVECTOR4* pVertexRegister )
  27. {
  28. pVertexRegister->x = ((float*)pInputStream)[0];
  29. pVertexRegister->y = ((float*)pInputStream)[1];
  30. pVertexRegister->z = 0;
  31. pVertexRegister->w = 1;
  32. }
  33. void
  34. Copy_FLOAT3( LPVOID pInputStream, RDVECTOR4* pVertexRegister )
  35. {
  36. pVertexRegister->x = ((float*)pInputStream)[0];
  37. pVertexRegister->y = ((float*)pInputStream)[1];
  38. pVertexRegister->z = ((float*)pInputStream)[2];
  39. pVertexRegister->w = 1;
  40. }
  41. void
  42. Copy_FLOAT4( LPVOID pInputStream, RDVECTOR4* pVertexRegister )
  43. {
  44. pVertexRegister->x = ((float*)pInputStream)[0];
  45. pVertexRegister->y = ((float*)pInputStream)[1];
  46. pVertexRegister->z = ((float*)pInputStream)[2];
  47. pVertexRegister->w = ((float*)pInputStream)[3];
  48. }
  49. void
  50. Copy_D3DCOLOR( LPVOID pInputStream, RDVECTOR4* pVertexRegister )
  51. {
  52. const float scale = 1.0f/255.f;
  53. const DWORD v = ((DWORD*)pInputStream)[0];
  54. pVertexRegister->a = scale * RGBA_GETALPHA(v);
  55. pVertexRegister->r = scale * RGBA_GETRED(v);
  56. pVertexRegister->g = scale * RGBA_GETGREEN(v);
  57. pVertexRegister->b = scale * RGBA_GETBLUE(v);
  58. }
  59. void
  60. Copy_UBYTE4( LPVOID pInputStream, RDVECTOR4* pVertexRegister )
  61. {
  62. const BYTE* v = (BYTE *)pInputStream;
  63. pVertexRegister->x = v[0];
  64. pVertexRegister->y = v[1];
  65. pVertexRegister->z = v[2];
  66. pVertexRegister->w = v[3];
  67. }
  68. void
  69. Copy_SHORT2( LPVOID pInputStream, RDVECTOR4* pVertexRegister )
  70. {
  71. const SHORT* v = ((SHORT*)pInputStream);
  72. pVertexRegister->x = v[0];
  73. pVertexRegister->y = v[1];
  74. pVertexRegister->z = 0;
  75. pVertexRegister->w = 1;
  76. }
  77. void
  78. Copy_SHORT4( LPVOID pInputStream, RDVECTOR4* pVertexRegister )
  79. {
  80. const SHORT* v = ((SHORT*)pInputStream);
  81. pVertexRegister->x = v[0];
  82. pVertexRegister->y = v[1];
  83. pVertexRegister->z = v[2];
  84. pVertexRegister->w = v[3];
  85. }
  86. inline HRESULT
  87. SetVElement( RDVElement& ve, DWORD dwReg, DWORD dwDataType, DWORD dwOffset )
  88. {
  89. ve.m_dwOffset = dwOffset;
  90. ve.m_dwRegister = dwReg;
  91. ve.m_dwDataType = dwDataType;
  92. switch( dwDataType )
  93. {
  94. case D3DVSDT_FLOAT1:
  95. ve.m_pfnCopy = Copy_FLOAT1;
  96. break;
  97. case D3DVSDT_FLOAT2:
  98. ve.m_pfnCopy = Copy_FLOAT2;
  99. break;
  100. case D3DVSDT_FLOAT3:
  101. ve.m_pfnCopy = Copy_FLOAT3;
  102. break;
  103. case D3DVSDT_FLOAT4:
  104. ve.m_pfnCopy = Copy_FLOAT4;
  105. break;
  106. case D3DVSDT_D3DCOLOR:
  107. ve.m_pfnCopy = Copy_D3DCOLOR;
  108. break;
  109. case D3DVSDT_UBYTE4:
  110. ve.m_pfnCopy = Copy_UBYTE4;
  111. break;
  112. case D3DVSDT_SHORT2:
  113. ve.m_pfnCopy = Copy_SHORT2;
  114. break;
  115. case D3DVSDT_SHORT4:
  116. ve.m_pfnCopy = Copy_SHORT4;
  117. break;
  118. default:
  119. return E_FAIL;
  120. }
  121. return S_OK;
  122. }
  123. //-----------------------------------------------------------------------------
  124. // Based on register and data type the function computes FVF dword and texture
  125. // presence bits:
  126. // - bits 0 - 7 in the qwFVF2 are used as texture presence bits
  127. // - bits 12 - 14 in the qwFVF are used as count of blend weights
  128. //-----------------------------------------------------------------------------
  129. HRESULT
  130. UpdateFVF( DWORD dwRegister, DWORD dwDataType, UINT64* pqwFVF,
  131. UINT64* pqwFVF2, DWORD* pdwNumBetas )
  132. {
  133. DWORD dwNumFloats = 0;
  134. switch( dwRegister )
  135. {
  136. case D3DVSDE_POSITION:
  137. if( dwDataType != D3DVSDT_FLOAT3 )
  138. {
  139. DPFERR( "Position register must be FLOAT3 for"
  140. "fixed-function pipeline" );
  141. return DDERR_GENERIC;
  142. }
  143. *pqwFVF |= D3DFVF_XYZ;
  144. break;
  145. case D3DVSDE_POSITION2:
  146. if( dwDataType != D3DVSDT_FLOAT3 )
  147. {
  148. DPFERR( "Position register must be FLOAT3 for"
  149. "fixed-function pipeline" );
  150. return DDERR_GENERIC;
  151. }
  152. *pqwFVF |= D3DFVFP_POSITION2;
  153. break;
  154. case D3DVSDE_BLENDWEIGHT:
  155. {
  156. int n = 0;
  157. switch (dwDataType)
  158. {
  159. case D3DVSDT_FLOAT1:
  160. n = 1;
  161. break;
  162. case D3DVSDT_FLOAT2:
  163. n = 2;
  164. break;
  165. case D3DVSDT_FLOAT3:
  166. n = 3;
  167. break;
  168. case D3DVSDT_FLOAT4:
  169. n = 4;
  170. break;
  171. default:
  172. DPFERR( "Invalid data type set for vertex blends" );
  173. return DDERR_GENERIC;
  174. }
  175. // Update number of floats after position
  176. *pdwNumBetas = *pdwNumBetas + n;
  177. break;
  178. }
  179. case D3DVSDE_NORMAL:
  180. if( dwDataType != D3DVSDT_FLOAT3 )
  181. {
  182. DPFERR( "Normal register must be FLOAT3 for fixed-function"
  183. "pipeline" );
  184. return DDERR_GENERIC;
  185. }
  186. *pqwFVF |= D3DFVF_NORMAL;
  187. break;
  188. case D3DVSDE_NORMAL2:
  189. if( dwDataType != D3DVSDT_FLOAT3 )
  190. {
  191. DPFERR( "Normal register must be FLOAT3 for fixed-function"
  192. "pipeline" );
  193. return DDERR_GENERIC;
  194. }
  195. *pqwFVF |= D3DFVFP_NORMAL2;
  196. break;
  197. case D3DVSDE_PSIZE:
  198. if( dwDataType != D3DVSDT_FLOAT1 )
  199. {
  200. DPFERR( "Point size register must be FLOAT1 for fixed-function"
  201. "pipeline" );
  202. return DDERR_GENERIC;
  203. }
  204. *pqwFVF |= D3DFVF_PSIZE;
  205. break;
  206. case D3DVSDE_DIFFUSE:
  207. if( dwDataType != D3DVSDT_D3DCOLOR )
  208. {
  209. DPFERR( "Diffuse register must be D3DCOLOR for"
  210. "fixed-function pipeline" );
  211. return DDERR_GENERIC;
  212. }
  213. *pqwFVF |= D3DFVF_DIFFUSE;
  214. break;
  215. case D3DVSDE_SPECULAR:
  216. if( dwDataType != D3DVSDT_D3DCOLOR )
  217. {
  218. DPFERR( "Specular register must be PACKEDBYTE for"
  219. "fixed-function pipeline" );
  220. return DDERR_GENERIC;
  221. }
  222. *pqwFVF |= D3DFVF_SPECULAR;
  223. break;
  224. case D3DVSDE_BLENDINDICES:
  225. if ( dwDataType != D3DVSDT_UBYTE4 )
  226. {
  227. DPFERR( "Blend Indicex register must be UBYTE4 for"
  228. "fixed-function pipeline" );
  229. return DDERR_GENERIC;
  230. }
  231. *pqwFVF |= D3DFVFP_BLENDINDICES;
  232. break;
  233. case D3DVSDE_TEXCOORD0:
  234. case D3DVSDE_TEXCOORD1:
  235. case D3DVSDE_TEXCOORD2:
  236. case D3DVSDE_TEXCOORD3:
  237. case D3DVSDE_TEXCOORD4:
  238. case D3DVSDE_TEXCOORD5:
  239. case D3DVSDE_TEXCOORD6:
  240. case D3DVSDE_TEXCOORD7:
  241. {
  242. DWORD dwTextureIndex = dwRegister - D3DVSDE_TEXCOORD0;
  243. DWORD dwBit = 1 << dwTextureIndex;
  244. if( *pqwFVF2 & dwBit )
  245. {
  246. DPFERR( "Texture register is set second time" );
  247. return DDERR_GENERIC;
  248. }
  249. *pqwFVF2 |= dwBit;
  250. switch( dwDataType )
  251. {
  252. case D3DVSDT_FLOAT1:
  253. *pqwFVF |= D3DFVF_TEXCOORDSIZE1(dwTextureIndex);
  254. break;
  255. case D3DVSDT_FLOAT2:
  256. *pqwFVF |= D3DFVF_TEXCOORDSIZE2(dwTextureIndex);
  257. break;
  258. case D3DVSDT_FLOAT3:
  259. *pqwFVF |= D3DFVF_TEXCOORDSIZE3(dwTextureIndex);
  260. break;
  261. case D3DVSDT_FLOAT4:
  262. *pqwFVF |= D3DFVF_TEXCOORDSIZE4(dwTextureIndex);
  263. break;
  264. default:
  265. DPFERR( "Invalid data type set for texture register" );
  266. return DDERR_GENERIC;
  267. break;
  268. }
  269. break;
  270. }
  271. default:
  272. DPFERR( "Invalid register set for fixed-function pipeline" );
  273. return DDERR_GENERIC;
  274. break;
  275. }
  276. return S_OK;
  277. }
  278. /////////////////////////////////////////////////////////////////////////
  279. //
  280. // class RDVStreamDecl
  281. //
  282. /////////////////////////////////////////////////////////////////////////
  283. //-----------------------------------------------------------------------------
  284. // RDVStreamDecl::Constructor
  285. //-----------------------------------------------------------------------------
  286. RDVStreamDecl::RDVStreamDecl()
  287. {
  288. m_dwNumElements = 0;
  289. m_dwStride = 0;
  290. m_dwStreamIndex = 0;
  291. m_bIsStreamTess = FALSE;
  292. }
  293. //-----------------------------------------------------------------------------
  294. // RDVStreamDecl::MakeVElementArray
  295. //-----------------------------------------------------------------------------
  296. HRESULT
  297. RDVStreamDecl::MakeVElementArray( UINT64 qwFVF )
  298. {
  299. HRESULT hr = S_OK;
  300. DWORD dwOffset = 0; // In Bytes
  301. m_dwStride = GetFVFVertexSize( qwFVF );
  302. m_dwStreamIndex = 0;
  303. m_dwNumElements = 0;
  304. dwOffset = 0 + ( qwFVF & D3DFVF_RESERVED0 ? 4 : 0 );
  305. //
  306. // Position and Blend Weights
  307. //
  308. switch( qwFVF & D3DFVF_POSITION_MASK )
  309. {
  310. case D3DFVF_XYZ:
  311. SetVElement( m_Elements[m_dwNumElements], D3DVSDE_POSITION,
  312. D3DVSDT_FLOAT3, dwOffset );
  313. m_dwNumElements++;
  314. dwOffset += 4*3;
  315. break;
  316. case D3DFVF_XYZRHW:
  317. SetVElement( m_Elements[m_dwNumElements], D3DVSDE_POSITION,
  318. D3DVSDT_FLOAT4, dwOffset );
  319. m_dwNumElements++;
  320. dwOffset += 4*4;
  321. break;
  322. case D3DFVF_XYZB1:
  323. SetVElement( m_Elements[m_dwNumElements], D3DVSDE_POSITION,
  324. D3DVSDT_FLOAT3, dwOffset );
  325. m_dwNumElements++;
  326. dwOffset += 4*3;
  327. SetVElement( m_Elements[m_dwNumElements], D3DVSDE_BLENDWEIGHT,
  328. D3DVSDT_FLOAT1, dwOffset );
  329. dwOffset += 4*1;
  330. m_dwNumElements++;
  331. break;
  332. case D3DFVF_XYZB2:
  333. SetVElement( m_Elements[m_dwNumElements], D3DVSDE_POSITION,
  334. D3DVSDT_FLOAT3, dwOffset );
  335. m_dwNumElements++;
  336. dwOffset += 4*3;
  337. SetVElement( m_Elements[m_dwNumElements], D3DVSDE_BLENDWEIGHT,
  338. D3DVSDT_FLOAT2, dwOffset );
  339. dwOffset += 4*2;
  340. m_dwNumElements++;
  341. break;
  342. case D3DFVF_XYZB3:
  343. SetVElement( m_Elements[m_dwNumElements], D3DVSDE_POSITION,
  344. D3DVSDT_FLOAT3, dwOffset );
  345. m_dwNumElements++;
  346. dwOffset += 4*3;
  347. SetVElement( m_Elements[m_dwNumElements], D3DVSDE_BLENDWEIGHT,
  348. D3DVSDT_FLOAT3, dwOffset );
  349. dwOffset += 4*3;
  350. m_dwNumElements++;
  351. break;
  352. case D3DFVF_XYZB4:
  353. SetVElement( m_Elements[m_dwNumElements], D3DVSDE_POSITION,
  354. D3DVSDT_FLOAT3, dwOffset );
  355. m_dwNumElements++;
  356. dwOffset += 4*3;
  357. SetVElement( m_Elements[m_dwNumElements], D3DVSDE_BLENDWEIGHT,
  358. D3DVSDT_FLOAT4, dwOffset );
  359. dwOffset += 4*4;
  360. m_dwNumElements++;
  361. break;
  362. case D3DFVF_XYZB5:
  363. SetVElement( m_Elements[m_dwNumElements], D3DVSDE_POSITION,
  364. D3DVSDT_FLOAT3, dwOffset );
  365. m_dwNumElements++;
  366. dwOffset += 4*3;
  367. SetVElement( m_Elements[m_dwNumElements], D3DVSDE_BLENDWEIGHT,
  368. D3DVSDT_FLOAT4, dwOffset );
  369. dwOffset += 4*5; // Even though the velement is float4, skip 5 floats.
  370. m_dwNumElements++;
  371. break;
  372. default:
  373. DPFERR( "Unable to compute offsets, strange FVF bits set" );
  374. return E_FAIL;
  375. }
  376. //
  377. // Normal
  378. //
  379. if( qwFVF & D3DFVF_NORMAL )
  380. {
  381. SetVElement( m_Elements[m_dwNumElements], D3DVSDE_NORMAL,
  382. D3DVSDT_FLOAT3, dwOffset );
  383. m_dwNumElements++;
  384. dwOffset += 4*3;
  385. }
  386. //
  387. // Point Size
  388. //
  389. if( qwFVF & D3DFVF_PSIZE )
  390. {
  391. SetVElement( m_Elements[m_dwNumElements], D3DVSDE_PSIZE,
  392. D3DVSDT_FLOAT1, dwOffset );
  393. m_dwNumElements++;
  394. dwOffset += 4;
  395. }
  396. //
  397. // Diffuse Color
  398. //
  399. if( qwFVF & D3DFVF_DIFFUSE )
  400. {
  401. SetVElement( m_Elements[m_dwNumElements], D3DVSDE_DIFFUSE,
  402. D3DVSDT_D3DCOLOR, dwOffset );
  403. m_dwNumElements++;
  404. dwOffset += 4;
  405. }
  406. //
  407. // Specular Color
  408. //
  409. if( qwFVF & D3DFVF_SPECULAR )
  410. {
  411. SetVElement( m_Elements[m_dwNumElements], D3DVSDE_SPECULAR,
  412. D3DVSDT_D3DCOLOR, dwOffset );
  413. m_dwNumElements++;
  414. dwOffset += 4;
  415. }
  416. //
  417. // Texture coordinates
  418. //
  419. DWORD dwNumTexCoord = (DWORD)(FVF_TEXCOORD_NUMBER(qwFVF));
  420. DWORD dwTextureFormats = (DWORD)((qwFVF >> 16) & 0xffff);
  421. // Texture formats size 00 01 10 11
  422. static DWORD dwTextureSize[4] = {2*4, 3*4, 4*4, 4};
  423. static DWORD dwTextureType[4] = {D3DVSDT_FLOAT2, D3DVSDT_FLOAT3,
  424. D3DVSDT_FLOAT4, D3DVSDT_FLOAT1};
  425. for (DWORD i=0; i < dwNumTexCoord; i++)
  426. {
  427. SetVElement( m_Elements[m_dwNumElements], D3DVSDE_TEXCOORD0 + i,
  428. dwTextureType[dwTextureFormats & 3], dwOffset );
  429. dwOffset += dwTextureSize[dwTextureFormats & 3];
  430. dwTextureFormats >>= 2;
  431. m_dwNumElements++;
  432. }
  433. return hr;
  434. }
  435. //-----------------------------------------------------------------------------
  436. // RDVStreamDecl::Parse
  437. //-----------------------------------------------------------------------------
  438. HRESULT
  439. RDVStreamDecl::Parse( DWORD ** ppToken,
  440. BOOL bFixedFunction,
  441. BOOL bStreamTess,
  442. UINT64* pqwFVF,
  443. UINT64* pqwFVF2,
  444. DWORD* pdwNumBetas)
  445. {
  446. HRESULT hr = S_OK;
  447. m_bIsStreamTess = bStreamTess;
  448. DWORD* pToken = *ppToken;
  449. DWORD dwCurrentOffset = 0;
  450. while( TRUE )
  451. {
  452. DWORD dwToken = *pToken++;
  453. const DWORD dwTokenType = RDVSD_GETTOKENTYPE( dwToken );
  454. switch( dwTokenType )
  455. {
  456. case D3DVSD_TOKEN_NOP: break;
  457. case D3DVSD_TOKEN_TESSELLATOR:
  458. {
  459. if( bStreamTess == FALSE )
  460. {
  461. DPFERR( "Unexpected Tesselator Token for this stream" );
  462. return E_FAIL;
  463. }
  464. if( m_dwNumElements >= RD_MAX_NUMELEMENTS )
  465. {
  466. DPFERR( "Tesselator Stream Token:" );
  467. DPFERR( " Number of vertex elements generated"
  468. " is greater than max supported" );
  469. return DDERR_GENERIC;
  470. }
  471. RDVElement& Element = m_Elements[m_dwNumElements++];
  472. const DWORD dwDataType = RDVSD_GETDATATYPE(dwToken);
  473. const DWORD dwRegister = RDVSD_GETVERTEXREG(dwToken);
  474. const DWORD dwRegisterIn = RDVSD_GETVERTEXREGIN(dwToken);
  475. Element.m_dwToken = dwToken;
  476. Element.m_dwOffset = dwCurrentOffset;
  477. Element.m_dwRegister = dwRegister;
  478. Element.m_dwDataType = dwDataType;
  479. Element.m_dwStreamIndex = m_dwStreamIndex;
  480. Element.m_dwRegisterIn = dwRegisterIn;
  481. Element.m_bIsTessGen = TRUE;
  482. switch (dwDataType)
  483. {
  484. case D3DVSDT_FLOAT2:
  485. dwCurrentOffset += sizeof(float) * 2;
  486. Element.m_pfnCopy = Copy_FLOAT2;
  487. break;
  488. case D3DVSDT_FLOAT3:
  489. dwCurrentOffset += sizeof(float) * 3;
  490. Element.m_pfnCopy = Copy_FLOAT3;
  491. break;
  492. default:
  493. DPFERR( "Invalid element data type in a Tesselator token" );
  494. return DDERR_GENERIC;
  495. }
  496. // Compute input FVF for fixed-function pipeline
  497. if( bFixedFunction )
  498. {
  499. hr = UpdateFVF( dwRegister, dwDataType, pqwFVF, pqwFVF2,
  500. pdwNumBetas );
  501. if( FAILED( hr ) )
  502. {
  503. DPFERR( "UpdateFVF failed" );
  504. return DDERR_INVALIDPARAMS;
  505. }
  506. }
  507. else
  508. {
  509. if( dwRegister >= RD_MAX_NUMINPUTREG )
  510. {
  511. DPFERR( "D3DVSD_TOKEN_STREAMDATA:"
  512. "Invalid register number" );
  513. return DDERR_GENERIC;
  514. }
  515. }
  516. break;
  517. }
  518. case D3DVSD_TOKEN_STREAMDATA:
  519. {
  520. switch( RDVSD_GETDATALOADTYPE( dwToken ) )
  521. {
  522. case RDVSD_LOADREGISTER:
  523. {
  524. if( m_dwNumElements >= RD_MAX_NUMELEMENTS )
  525. {
  526. DPFERR( "D3DVSD_TOKEN_STREAMDATA:" );
  527. DPFERR( " Number of vertex elements in a stream"
  528. "is greater than max supported" );
  529. return DDERR_GENERIC;
  530. }
  531. RDVElement& Element = m_Elements[m_dwNumElements++];
  532. const DWORD dwDataType = RDVSD_GETDATATYPE(dwToken);
  533. const DWORD dwRegister = RDVSD_GETVERTEXREG(dwToken);
  534. Element.m_dwToken = dwToken;
  535. Element.m_dwOffset = dwCurrentOffset;
  536. Element.m_dwRegister = dwRegister;
  537. Element.m_dwDataType = dwDataType;
  538. Element.m_dwStreamIndex = m_dwStreamIndex;
  539. switch( dwDataType )
  540. {
  541. case D3DVSDT_FLOAT1:
  542. dwCurrentOffset += sizeof(float);
  543. Element.m_pfnCopy = Copy_FLOAT1;
  544. break;
  545. case D3DVSDT_FLOAT2:
  546. dwCurrentOffset += sizeof(float) * 2;
  547. Element.m_pfnCopy = Copy_FLOAT2;
  548. break;
  549. case D3DVSDT_FLOAT3:
  550. dwCurrentOffset += sizeof(float) * 3;
  551. Element.m_pfnCopy = Copy_FLOAT3;
  552. break;
  553. case D3DVSDT_FLOAT4:
  554. dwCurrentOffset += sizeof(float) * 4;
  555. Element.m_pfnCopy = Copy_FLOAT4;
  556. break;
  557. case D3DVSDT_D3DCOLOR:
  558. dwCurrentOffset += sizeof(DWORD);
  559. Element.m_pfnCopy = Copy_D3DCOLOR;
  560. break;
  561. case D3DVSDT_UBYTE4:
  562. dwCurrentOffset += sizeof(DWORD);
  563. Element.m_pfnCopy = Copy_UBYTE4;
  564. break;
  565. case D3DVSDT_SHORT2:
  566. dwCurrentOffset += sizeof(SHORT) * 2;
  567. Element.m_pfnCopy = Copy_SHORT2;
  568. break;
  569. case D3DVSDT_SHORT4:
  570. dwCurrentOffset += sizeof(SHORT) * 4;
  571. Element.m_pfnCopy = Copy_SHORT4;
  572. break;
  573. default:
  574. DPFERR( "D3DVSD_TOKEN_STREAMDATA:"
  575. "Invalid element data type" );
  576. return DDERR_GENERIC;
  577. }
  578. // Compute input FVF for fixed-function pipeline
  579. if( bFixedFunction )
  580. {
  581. hr = UpdateFVF( dwRegister, dwDataType, pqwFVF, pqwFVF2,
  582. pdwNumBetas );
  583. if( FAILED( hr ) )
  584. {
  585. DPFERR( "UpdateFVF failed" );
  586. return DDERR_INVALIDPARAMS;
  587. }
  588. }
  589. else
  590. {
  591. if( dwRegister >= RD_MAX_NUMINPUTREG )
  592. {
  593. DPFERR( "D3DVSD_TOKEN_STREAMDATA:"
  594. "Invalid register number" );
  595. return DDERR_GENERIC;
  596. }
  597. }
  598. break;
  599. }
  600. case RDVSD_SKIP:
  601. {
  602. const DWORD dwCount = RDVSD_GETSKIPCOUNT( dwToken );
  603. dwCurrentOffset += dwCount * sizeof(DWORD);
  604. break;
  605. }
  606. default:
  607. DPFERR( "Invalid data load type" );
  608. return DDERR_GENERIC;
  609. }
  610. break;
  611. }
  612. default:
  613. {
  614. *ppToken = pToken - 1;
  615. m_dwStride = dwCurrentOffset;
  616. return S_OK;
  617. }
  618. } // switch
  619. } // while
  620. return S_OK;
  621. }
  622. /////////////////////////////////////////////////////////////////////////
  623. //
  624. // class RDVDeclaration
  625. //
  626. /////////////////////////////////////////////////////////////////////////
  627. //-----------------------------------------------------------------------------
  628. // RDVDeclaration::Destructor
  629. //-----------------------------------------------------------------------------
  630. RDVDeclaration::~RDVDeclaration()
  631. {
  632. RDVConstantData* pConst = m_pConstants;
  633. while( pConst )
  634. {
  635. RDVConstantData* pNext =
  636. static_cast<RDVConstantData *>(pConst->m_pNext);
  637. delete pConst;
  638. pConst = pNext;
  639. }
  640. }
  641. //-----------------------------------------------------------------------------
  642. // RDVDeclaration::MakeVElementArray
  643. //-----------------------------------------------------------------------------
  644. HRESULT
  645. RDVDeclaration::MakeVElementArray( UINT64 qwFVF )
  646. {
  647. HRESULT hr = S_OK;
  648. m_qwInputFVF = qwFVF;
  649. m_dwNumActiveStreams = 1;
  650. // Go through the FVF and make the elements
  651. RDVStreamDecl& Stream = m_StreamArray[0];
  652. hr = Stream.MakeVElementArray( qwFVF );
  653. if( FAILED( hr ) )
  654. {
  655. return hr;
  656. }
  657. m_dwNumElements = Stream.m_dwNumElements;
  658. memcpy( &m_VertexElements, &Stream.m_Elements,
  659. sizeof( RDVElement ) * m_dwNumElements );
  660. return hr;
  661. }
  662. //-----------------------------------------------------------------------------
  663. // RDVDeclaration::Parse
  664. //-----------------------------------------------------------------------------
  665. HRESULT
  666. RDVDeclaration::Parse( DWORD* pDecl, BOOL bFixedFunction )
  667. {
  668. HRESULT hr = S_OK;
  669. UINT64 qwFVF = 0; // FVF for fixed-function pipeline
  670. UINT64 qwFVF2 = 0; // Texture presence bits (8 bits)
  671. DWORD dwNumBetas = 0; // The number of betas.
  672. DWORD dwStreamPresent = 0; // Bit is set if a stream is used
  673. DWORD* pToken = pDecl;
  674. BOOL bStreamTess = FALSE;
  675. while( TRUE )
  676. {
  677. DWORD dwToken = *pToken++;
  678. const DWORD dwTokenType = RDVSD_GETTOKENTYPE(dwToken);
  679. switch( dwTokenType )
  680. {
  681. case D3DVSD_TOKEN_NOP:
  682. break;
  683. case D3DVSD_TOKEN_STREAM:
  684. {
  685. DWORD dwStream;
  686. if( RDVSD_ISSTREAMTESS(dwToken) )
  687. {
  688. if( RDVSD_GETSTREAMNUMBER(dwToken) )
  689. {
  690. DPFERR( "No stream number should be specified for a"
  691. " Tesselator stream" );
  692. return E_FAIL;
  693. }
  694. dwStream = RDVSD_STREAMTESS;
  695. bStreamTess = TRUE;
  696. }
  697. else
  698. {
  699. dwStream = RDVSD_GETSTREAMNUMBER(dwToken);
  700. bStreamTess = FALSE;
  701. }
  702. if( dwStream > RDVSD_STREAMTESS )
  703. {
  704. DPFERR( "Stream number is too big" );
  705. return DDERR_INVALIDPARAMS;
  706. }
  707. // Has this stream already been declared ?
  708. if( dwStreamPresent & (1 << dwStream) )
  709. {
  710. DPFERR( "Stream already defined in this declaration" );
  711. return DDERR_INVALIDPARAMS;
  712. }
  713. // Mark the stream as seen
  714. dwStreamPresent |= 1 << dwStream;
  715. RDVStreamDecl& Stream = m_StreamArray[m_dwNumActiveStreams];
  716. Stream.m_dwStreamIndex = dwStream;
  717. hr = Stream.Parse(&pToken, bFixedFunction, bStreamTess,
  718. &qwFVF, &qwFVF2, &dwNumBetas);
  719. if( FAILED( hr ) )
  720. {
  721. return hr;
  722. }
  723. //
  724. // Save the stride computed for the tesselator stream
  725. //
  726. if( bStreamTess )
  727. {
  728. m_dwStreamTessStride = Stream.m_dwStride;
  729. }
  730. m_dwNumActiveStreams++;
  731. break;
  732. }
  733. case D3DVSD_TOKEN_STREAMDATA:
  734. {
  735. DPFERR( "D3DVSD_TOKEN_STREAMDATA could only be used"
  736. "after D3DVSD_TOKEN_STREAM" );
  737. return DDERR_GENERIC;
  738. }
  739. case D3DVSD_TOKEN_CONSTMEM:
  740. {
  741. RDVConstantData * cd = new RDVConstantData;
  742. if( cd == NULL )
  743. {
  744. return E_OUTOFMEMORY;
  745. }
  746. cd->m_dwCount = RDVSD_GETCONSTCOUNT(dwToken);
  747. cd->m_dwAddress = RDVSD_GETCONSTADDRESS(dwToken);
  748. if( cd->m_dwCount + cd->m_dwAddress > RD_MAX_NUMCONSTREG )
  749. {
  750. delete cd;
  751. DPFERR( "D3DVSD_TOKEN_CONSTMEM writes outside"
  752. "constant memory" );
  753. return DDERR_GENERIC;
  754. }
  755. const DWORD dwSize = cd->m_dwCount << 2; // number of DWORDs
  756. cd->m_pData = new DWORD[dwSize];
  757. if( cd->m_pData == NULL )
  758. {
  759. return E_OUTOFMEMORY;
  760. }
  761. memcpy( cd->m_pData, pToken, dwSize << 2 );
  762. if( m_pConstants == NULL )
  763. m_pConstants = cd;
  764. else
  765. m_pConstants->Append(cd);
  766. pToken += dwSize;
  767. break;
  768. }
  769. case D3DVSD_TOKEN_EXT:
  770. {
  771. // Skip extension info
  772. DWORD dwCount = RDVSD_GETEXTCOUNT(dwToken);
  773. pToken += dwCount;
  774. break;
  775. }
  776. case D3DVSD_TOKEN_END:
  777. {
  778. goto l_End;
  779. }
  780. default:
  781. {
  782. DPFERR( "Invalid declaration token: %10x", dwToken );
  783. return DDERR_INVALIDPARAMS;
  784. }
  785. }
  786. }
  787. l_End:
  788. // Now accumulate all the vertex elements into the declaration
  789. DWORD dwCurrElement = 0;
  790. m_dwNumElements = 0;
  791. // Build a VElement List in the Declaration.
  792. for( DWORD i=0; i<m_dwNumActiveStreams; i++ )
  793. {
  794. RDVStreamDecl& Stream = m_StreamArray[i];
  795. for( DWORD j=0; j<Stream.m_dwNumElements; j++ )
  796. {
  797. m_VertexElements[dwCurrElement] = Stream.m_Elements[j];
  798. dwCurrElement++;
  799. }
  800. m_dwNumElements += Stream.m_dwNumElements;
  801. }
  802. // If any tesselator tokens were present, then translate the m_dwRegisterIn
  803. // in the the StreamIndex and Offset for the tesselator tokens.
  804. if( bStreamTess )
  805. {
  806. for( i=0; i<m_dwNumElements; i++ )
  807. {
  808. RDVElement& ve = m_VertexElements[i];
  809. if( ve.m_bIsTessGen )
  810. {
  811. for( DWORD j=0; j<m_dwNumElements; j++ )
  812. {
  813. if( m_VertexElements[j].m_dwRegister == ve.m_dwRegisterIn )
  814. {
  815. ve.m_dwStreamIndexIn =
  816. m_VertexElements[j].m_dwStreamIndex;
  817. ve.m_dwOffsetIn = m_VertexElements[j].m_dwOffsetIn;
  818. break;
  819. }
  820. }
  821. if( j == m_dwNumElements )
  822. {
  823. DPFERR( "Tesselator input register is not defined in the"
  824. " declaration" );
  825. return E_FAIL;
  826. }
  827. }
  828. }
  829. }
  830. // Validate input for the fixed-function pipeline
  831. if( bFixedFunction )
  832. {
  833. // Pull out the number of blend weights
  834. BOOL bIsTransformed = (qwFVF & D3DFVF_XYZRHW);
  835. if( bIsTransformed )
  836. {
  837. if( dwNumBetas != 0 )
  838. {
  839. DPFERR( "Cannot have blend weights along with "
  840. "transformed position" );
  841. return E_FAIL;
  842. }
  843. }
  844. else if( (qwFVF & D3DFVF_XYZ) == 0 )
  845. {
  846. // Position must be set
  847. DPFERR( "Position register must be set" );
  848. return E_FAIL;
  849. }
  850. DWORD dwPosMask = bIsTransformed ? 0x2 : 0x1;
  851. if( dwNumBetas )
  852. {
  853. dwPosMask += (dwNumBetas + 1);
  854. }
  855. m_qwInputFVF |= (qwFVF |
  856. ((DWORD)(D3DFVF_POSITION_MASK) & (dwPosMask << 1)));
  857. // Compute number of texture coordinates
  858. DWORD nTexCoord = 0;
  859. DWORD dwTexturePresenceBits = qwFVF2 & 0xFF;
  860. while( dwTexturePresenceBits & 1 )
  861. {
  862. dwTexturePresenceBits >>= 1;
  863. nTexCoord++;
  864. }
  865. // There should be no gaps in texture coordinates
  866. if( dwTexturePresenceBits )
  867. {
  868. DPFERR( "Texture coordinates should have no gaps" );
  869. return E_FAIL;
  870. }
  871. m_qwInputFVF |= (nTexCoord << D3DFVF_TEXCOUNT_SHIFT);
  872. }
  873. return hr;
  874. }
  875. /////////////////////////////////////////////////////////////////////////
  876. //
  877. // class RDVShader
  878. //
  879. /////////////////////////////////////////////////////////////////////////
  880. RDVShader::RDVShader()
  881. {
  882. m_pCode = NULL;
  883. }
  884. //-----------------------------------------------------------------------------
  885. // RDVShader::Destructor
  886. //-----------------------------------------------------------------------------
  887. RDVShader::~RDVShader()
  888. {
  889. delete m_pCode;
  890. }
  891. /////////////////////////////////////////////////////////////////////////
  892. //
  893. // class RefDev
  894. //
  895. /////////////////////////////////////////////////////////////////////////
  896. //-----------------------------------------------------------------------------
  897. // RefDev::DrawDX8Prim
  898. //-----------------------------------------------------------------------------
  899. HRESULT
  900. RefDev::DrawDX8Prim( LPD3DHAL_DP2DRAWPRIMITIVE pDP )
  901. {
  902. HRESULT hr = S_OK;
  903. // Ignore D3DRS_PATCHSEGMENTS for non-triangle primitive types
  904. if( GetRSf()[D3DRS_PATCHSEGMENTS] > 1.f &&
  905. pDP->primType >= D3DPT_TRIANGLELIST)
  906. {
  907. // Save current data stream pointers and replace with
  908. // pointer to tessellation output
  909. hr = LinkTessellatorOutput();
  910. if(FAILED(hr))
  911. {
  912. return hr;
  913. }
  914. hr = ProcessTessPrimitive( pDP );
  915. // Restore back saved pointer
  916. UnlinkTessellatorOutput();
  917. return hr;
  918. }
  919. // If there is any tesselator output in this vertex-shader
  920. // then you cannot use DrawPrim. DrawRect/Tri is required.
  921. if( m_pCurrentVShader->m_Declaration.m_dwStreamTessStride != 0 )
  922. {
  923. DPFERR( "Cannot call DrawPrim when the current vertex shader has"
  924. " tesselator output." );
  925. return D3DERR_INVALIDCALL;
  926. }
  927. DWORD cVertices = GetVertexCount( pDP->primType, pDP->PrimitiveCount );
  928. if( RDVSD_ISLEGACY( m_CurrentVShaderHandle ) )
  929. {
  930. //
  931. // The legacy FVF style: The Zero'th Stream is implied
  932. //
  933. UINT64 qwFVF = m_CurrentVShaderHandle;
  934. RDVStream& Stream = m_VStream[0];
  935. DWORD dwStride = Stream.m_dwStride;
  936. DWORD dwFVFSize = GetFVFVertexSize( qwFVF );
  937. if( Stream.m_pData == NULL || dwStride == 0 )
  938. {
  939. DPFERR( "Zero'th stream doesnt have valid VB set" );
  940. return DDERR_INVALIDPARAMS;
  941. }
  942. if( dwStride < dwFVFSize )
  943. {
  944. DPFERR( "The stride set for the vertex stream is less than"
  945. " the FVF vertex size" );
  946. return E_FAIL;
  947. }
  948. if( FVF_TRANSFORMED(m_CurrentVShaderHandle) )
  949. {
  950. HR_RET( GrowTLVArray( cVertices ) );
  951. FvfToRDVertex( (Stream.m_pData + pDP->VStart * dwStride),
  952. GetTLVArray(), qwFVF, dwStride, cVertices );
  953. if( GetRS()[D3DRENDERSTATE_CLIPPING] )
  954. {
  955. m_qwFVFOut = qwFVF;
  956. HR_RET( UpdateClipper() );
  957. HR_RET(m_Clipper.DrawOnePrimitive( GetTLVArray(),
  958. 0,
  959. pDP->primType,
  960. cVertices ));
  961. }
  962. else
  963. {
  964. HR_RET(DrawOnePrimitive( GetTLVArray(),
  965. 0,
  966. pDP->primType,
  967. cVertices ));
  968. }
  969. return S_OK;
  970. }
  971. }
  972. if( m_pCurrentVShader->IsFixedFunction() )
  973. {
  974. //
  975. // With declaration for Fixed Function pipeline, DX8 style
  976. //
  977. HR_RET(ProcessPrimitive( pDP->primType, pDP->VStart,
  978. cVertices, 0, 0 ));
  979. }
  980. else
  981. {
  982. //
  983. // Pure Vertex Shader
  984. //
  985. HR_RET(ProcessPrimitiveVVM( pDP->primType, pDP->VStart,
  986. cVertices, 0, 0 ));
  987. }
  988. return hr;
  989. }
  990. //-----------------------------------------------------------------------------
  991. // RefDev::DrawDX8Prim2
  992. //-----------------------------------------------------------------------------
  993. HRESULT
  994. RefDev::DrawDX8Prim2( LPD3DHAL_DP2DRAWPRIMITIVE2 pDP )
  995. {
  996. HRESULT hr = S_OK;
  997. DWORD cVertices = GetVertexCount( pDP->primType, pDP->PrimitiveCount );
  998. if( !RDVSD_ISLEGACY ( m_CurrentVShaderHandle ) ||
  999. !FVF_TRANSFORMED( m_CurrentVShaderHandle ) )
  1000. {
  1001. DPFERR( "DrawPrimitives2 should be called with transformed legacy vertices" );
  1002. return E_FAIL;
  1003. }
  1004. //
  1005. // The legacy FVF style: The Zero'th Stream is implied
  1006. //
  1007. UINT64 qwFVF = m_CurrentVShaderHandle;
  1008. RDVStream& Stream = m_VStream[0];
  1009. DWORD dwStride = Stream.m_dwStride;
  1010. DWORD dwFVFSize = GetFVFVertexSize( qwFVF );
  1011. if( Stream.m_pData == NULL || dwStride == 0 )
  1012. {
  1013. DPFERR( "Zero'th stream doesnt have valid VB set" );
  1014. return DDERR_INVALIDPARAMS;
  1015. }
  1016. if( dwStride < dwFVFSize )
  1017. {
  1018. DPFERR( "The stride set for the vertex stream is less than"
  1019. " the FVF vertex size" );
  1020. return E_FAIL;
  1021. }
  1022. HR_RET( GrowTLVArray( cVertices ) );
  1023. FvfToRDVertex( (Stream.m_pData + pDP->FirstVertexOffset),
  1024. GetTLVArray(), qwFVF, dwStride, cVertices );
  1025. HR_RET(DrawOnePrimitive( GetTLVArray(), 0, pDP->primType,
  1026. cVertices ));
  1027. return S_OK;
  1028. }
  1029. //-----------------------------------------------------------------------------
  1030. // RefVP::DrawDX8IndexedPrim
  1031. //-----------------------------------------------------------------------------
  1032. HRESULT
  1033. RefDev::DrawDX8IndexedPrim(
  1034. LPD3DHAL_DP2DRAWINDEXEDPRIMITIVE pDIP )
  1035. {
  1036. HRESULT hr = S_OK;
  1037. if( GetRSf()[D3DRS_PATCHSEGMENTS] > 1.f )
  1038. {
  1039. // Save current data stream pointers and replace with
  1040. // pointer to tessellation output
  1041. hr = LinkTessellatorOutput();
  1042. if(FAILED(hr))
  1043. {
  1044. return hr;
  1045. }
  1046. hr = ProcessTessIndexedPrimitive( pDIP );
  1047. // Restore back saved pointer
  1048. UnlinkTessellatorOutput();
  1049. return hr;
  1050. }
  1051. // If there is any tesselator output in this vertex-shader
  1052. // then you cannot use DrawPrim. DrawRect/Tri is required.
  1053. if( m_pCurrentVShader->m_Declaration.m_dwStreamTessStride != 0 )
  1054. {
  1055. DPFERR( "Cannot call DrawIndexedPrim when the current vertex shader"
  1056. " has tesselator output." );
  1057. return D3DERR_INVALIDCALL;
  1058. }
  1059. DWORD cIndices = GetVertexCount( pDIP->primType, pDIP->PrimitiveCount );
  1060. if( RDVSD_ISLEGACY( m_CurrentVShaderHandle ) )
  1061. {
  1062. //
  1063. // The legacy FVF style: The Zero'th Stream is implied
  1064. //
  1065. UINT64 qwFVF = m_CurrentVShaderHandle;
  1066. RDVStream& Stream = m_VStream[0];
  1067. DWORD dwStride = Stream.m_dwStride;
  1068. DWORD dwFVFSize = GetFVFVertexSize( qwFVF );
  1069. if( Stream.m_pData == NULL || dwStride == 0 )
  1070. {
  1071. DPFERR( "Zero'th stream doesnt have valid VB set" );
  1072. return DDERR_INVALIDPARAMS;
  1073. }
  1074. if( dwStride < dwFVFSize )
  1075. {
  1076. DPFERR( "The stride set for the vertex stream is less than"
  1077. " the FVF vertex size" );
  1078. return E_FAIL;
  1079. }
  1080. if( m_IndexStream.m_pData == NULL )
  1081. {
  1082. DPFERR( "Indices are not available" );
  1083. return E_FAIL;
  1084. }
  1085. if( FVF_TRANSFORMED(m_CurrentVShaderHandle) )
  1086. {
  1087. DWORD cVertices = pDIP->NumVertices + pDIP->MinIndex;
  1088. HR_RET( GrowTLVArray( cVertices ) );
  1089. FvfToRDVertex( (Stream.m_pData + pDIP->BaseVertexIndex * dwStride),
  1090. GetTLVArray(), qwFVF, dwStride, cVertices );
  1091. if( GetRS()[D3DRENDERSTATE_CLIPPING] )
  1092. {
  1093. m_qwFVFOut = qwFVF;
  1094. HR_RET( UpdateClipper() );
  1095. if( m_IndexStream.m_dwStride == 4 )
  1096. {
  1097. HR_RET( m_Clipper.DrawOneIndexedPrimitive(
  1098. GetTLVArray(),
  1099. 0,
  1100. (LPDWORD)m_IndexStream.m_pData,
  1101. pDIP->StartIndex,
  1102. cIndices,
  1103. pDIP->primType ));
  1104. }
  1105. else
  1106. {
  1107. HR_RET( m_Clipper.DrawOneIndexedPrimitive(
  1108. GetTLVArray(),
  1109. 0,
  1110. (LPWORD)m_IndexStream.m_pData,
  1111. pDIP->StartIndex,
  1112. cIndices,
  1113. pDIP->primType ));
  1114. }
  1115. }
  1116. else
  1117. {
  1118. if( m_IndexStream.m_dwStride == 4 )
  1119. {
  1120. HR_RET(DrawOneIndexedPrimitive(
  1121. GetTLVArray(),
  1122. 0,
  1123. (LPDWORD)m_IndexStream.m_pData,
  1124. pDIP->StartIndex,
  1125. cIndices,
  1126. pDIP->primType ));
  1127. }
  1128. else
  1129. {
  1130. HR_RET(DrawOneIndexedPrimitive(
  1131. GetTLVArray(),
  1132. 0,
  1133. (LPWORD)m_IndexStream.m_pData,
  1134. pDIP->StartIndex,
  1135. cIndices,
  1136. pDIP->primType ));
  1137. }
  1138. }
  1139. return S_OK;
  1140. }
  1141. }
  1142. if( m_pCurrentVShader->IsFixedFunction() )
  1143. {
  1144. //
  1145. // With declaration for Fixed Function pipeline, DX8 style
  1146. //
  1147. HR_RET(ProcessPrimitive( pDIP->primType,
  1148. pDIP->BaseVertexIndex,
  1149. pDIP->NumVertices + pDIP->MinIndex,
  1150. pDIP->StartIndex,
  1151. cIndices ));
  1152. }
  1153. else
  1154. {
  1155. //
  1156. // Pure Vertex Shader
  1157. //
  1158. HR_RET(ProcessPrimitiveVVM( pDIP->primType,
  1159. pDIP->BaseVertexIndex,
  1160. pDIP->NumVertices + pDIP->MinIndex,
  1161. pDIP->StartIndex,
  1162. cIndices ));
  1163. }
  1164. return hr;
  1165. }
  1166. //-----------------------------------------------------------------------------
  1167. // RefVP::DrawDX8IndexedPrim2
  1168. //-----------------------------------------------------------------------------
  1169. HRESULT
  1170. RefDev::DrawDX8IndexedPrim2(
  1171. LPD3DHAL_DP2DRAWINDEXEDPRIMITIVE2 pDIP )
  1172. {
  1173. HRESULT hr = S_OK;
  1174. DWORD cIndices = GetVertexCount( pDIP->primType, pDIP->PrimitiveCount );
  1175. if( !RDVSD_ISLEGACY ( m_CurrentVShaderHandle ) ||
  1176. !FVF_TRANSFORMED( m_CurrentVShaderHandle ) )
  1177. {
  1178. DPFERR( "DrawIndexedPrimitive2 should be called with transformed legacy vertices" );
  1179. return E_FAIL;
  1180. }
  1181. //
  1182. // The legacy FVF style: The Zero'th Stream is implied
  1183. //
  1184. UINT64 qwFVF = m_CurrentVShaderHandle;
  1185. RDVStream& Stream = m_VStream[0];
  1186. DWORD dwStride = Stream.m_dwStride;
  1187. DWORD dwFVFSize = GetFVFVertexSize( qwFVF );
  1188. if( Stream.m_pData == NULL || dwStride == 0)
  1189. {
  1190. DPFERR( "Zero'th stream doesnt have valid VB set" );
  1191. return DDERR_INVALIDPARAMS;
  1192. }
  1193. if( dwStride < dwFVFSize )
  1194. {
  1195. DPFERR( "The stride set for the vertex stream is less than"
  1196. " the FVF vertex size" );
  1197. return E_FAIL;
  1198. }
  1199. if( m_IndexStream.m_pData == NULL )
  1200. {
  1201. DPFERR( "Indices are not available" );
  1202. return E_FAIL;
  1203. }
  1204. DWORD cVertices = pDIP->NumVertices;
  1205. HR_RET( GrowTLVArray( cVertices ) );
  1206. FvfToRDVertex( (Stream.m_pData + pDIP->BaseVertexOffset +
  1207. pDIP->MinIndex * dwStride),
  1208. GetTLVArray(),
  1209. qwFVF, dwStride,
  1210. cVertices );
  1211. if( m_IndexStream.m_dwStride == 4 )
  1212. {
  1213. HR_RET(DrawOneIndexedPrimitive(
  1214. GetTLVArray(),
  1215. -(int)pDIP->MinIndex,
  1216. (LPDWORD)( m_IndexStream.m_pData + pDIP->StartIndexOffset),
  1217. 0,
  1218. cIndices,
  1219. pDIP->primType ));
  1220. }
  1221. else
  1222. {
  1223. HR_RET(DrawOneIndexedPrimitive(
  1224. GetTLVArray(),
  1225. -(int)pDIP->MinIndex,
  1226. (LPWORD)( m_IndexStream.m_pData + pDIP->StartIndexOffset),
  1227. 0,
  1228. cIndices,
  1229. pDIP->primType ));
  1230. }
  1231. return S_OK;
  1232. }
  1233. //-----------------------------------------------------------------------------
  1234. // RefVP::DrawDX8ClippedTriangleFan
  1235. //-----------------------------------------------------------------------------
  1236. HRESULT
  1237. RefDev::DrawDX8ClippedTriFan(
  1238. LPD3DHAL_CLIPPEDTRIANGLEFAN pCTF )
  1239. {
  1240. BOOL bWireframe =
  1241. GetRS()[D3DRENDERSTATE_FILLMODE] == D3DFILL_WIREFRAME;
  1242. HRESULT hr = S_OK;
  1243. DWORD cVertices = GetVertexCount( D3DPT_TRIANGLEFAN,
  1244. pCTF->PrimitiveCount );
  1245. if( !RDVSD_ISLEGACY ( m_CurrentVShaderHandle ) ||
  1246. !FVF_TRANSFORMED( m_CurrentVShaderHandle ) )
  1247. {
  1248. DPFERR( "DrawPrimitives2 should be called with transformed legacy"
  1249. " vertices" );
  1250. return E_FAIL;
  1251. }
  1252. //
  1253. // The legacy FVF style: The Zero'th Stream is implied
  1254. //
  1255. UINT64 qwFVF = m_CurrentVShaderHandle;
  1256. RDVStream& Stream = m_VStream[0];
  1257. DWORD dwStride = Stream.m_dwStride;
  1258. DWORD dwFVFSize = GetFVFVertexSize( qwFVF );
  1259. if( Stream.m_pData == NULL || dwStride == 0 )
  1260. {
  1261. DPFERR( "Zero'th stream doesnt have valid VB set" );
  1262. return DDERR_INVALIDPARAMS;
  1263. }
  1264. if( dwStride < dwFVFSize )
  1265. {
  1266. DPFERR( "The stride set for the vertex stream is less than"
  1267. " the FVF vertex size" );
  1268. return E_FAIL;
  1269. }
  1270. HR_RET( GrowTLVArray( cVertices ) );
  1271. FvfToRDVertex( (Stream.m_pData + pCTF->FirstVertexOffset),
  1272. GetTLVArray(), qwFVF, dwStride, cVertices );
  1273. if( bWireframe )
  1274. {
  1275. HR_RET(DrawOneEdgeFlagTriangleFan( GetTLVArray(), cVertices,
  1276. pCTF->dwEdgeFlags ));
  1277. }
  1278. else
  1279. {
  1280. HR_RET(DrawOnePrimitive( GetTLVArray(), 0, D3DPT_TRIANGLEFAN,
  1281. cVertices ));
  1282. }
  1283. return S_OK;
  1284. }