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.

1698 lines
60 KiB

  1. /*============================================================================
  2. *
  3. * Copyright (C) 1999-2000 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: drawgrid.cpp
  6. * Content: Implementation for high order surfaces
  7. *
  8. ****************************************************************************/
  9. #include "pch.cpp"
  10. #pragma hdrstop
  11. //-----------------------------------------------------------------------------
  12. // RDHOCoeffs::operator=
  13. //-----------------------------------------------------------------------------
  14. RDHOCoeffs& RDHOCoeffs::operator=(const RDHOCoeffs &coeffs)
  15. {
  16. m_Width = coeffs.m_Width;
  17. m_Height = coeffs.m_Height;
  18. m_Stride = coeffs.m_Stride;
  19. m_Basis = coeffs.m_Basis;
  20. m_Order = coeffs.m_Order;
  21. if(coeffs.m_pNumSegs != 0)
  22. {
  23. m_pNumSegs = new FLOAT[4];
  24. if(m_pNumSegs != 0)
  25. {
  26. memcpy(m_pNumSegs, coeffs.m_pNumSegs, sizeof(FLOAT) * 4);
  27. }
  28. }
  29. else
  30. {
  31. m_pNumSegs = 0;
  32. }
  33. for(unsigned i = 0; i < RD_MAX_NUMSTREAMS; ++i)
  34. {
  35. if(coeffs.m_pData[i] != 0)
  36. {
  37. m_DataSize[i] = coeffs.m_DataSize[i];
  38. m_pData[i] = new BYTE[m_DataSize[i]];
  39. if(m_pData[i] != 0)
  40. {
  41. memcpy(m_pData[i], coeffs.m_pData[i], m_DataSize[i]);
  42. }
  43. }
  44. else
  45. {
  46. m_pData[i] = 0;
  47. }
  48. }
  49. return *this;
  50. }
  51. //-----------------------------------------------------------------------------
  52. // RefDev::DrawRectPatch
  53. //-----------------------------------------------------------------------------
  54. HRESULT
  55. RefDev::DrawRectPatch( LPD3DHAL_DP2DRAWRECTPATCH pDP )
  56. {
  57. HRESULT hr = S_OK;
  58. if( RDVSD_ISLEGACY( m_CurrentVShaderHandle ) )
  59. {
  60. //
  61. // The legacy FVF style: The Zero'th Stream is implied
  62. //
  63. DWORD dwFVF = m_CurrentVShaderHandle;
  64. RDVStream& Stream = m_VStream[0];
  65. DWORD dwStride = Stream.m_dwStride;
  66. DWORD dwFVFSize = GetFVFVertexSize( dwFVF );
  67. if( Stream.m_pData == NULL || dwStride == 0 )
  68. {
  69. DPFERR("Zero'th stream doesnt have valid VB set");
  70. return DDERR_INVALIDPARAMS;
  71. }
  72. if( dwStride < dwFVFSize )
  73. {
  74. DPFERR("The stride set for the vertex stream is less than the FVF vertex size");
  75. return E_FAIL;
  76. }
  77. }
  78. FLOAT *pSegs;
  79. D3DRECTPATCH_INFO Info, *pInfo;
  80. BYTE *TempData[RD_MAX_NUMSTREAMS + 1];
  81. if(pDP->Handle != 0)
  82. {
  83. if((pDP->Flags & RTPATCHFLAG_HASINFO) != 0) // Is either a first time or a recompute
  84. {
  85. HR_RET( m_HOSCoeffs.Grow(pDP->Handle) );
  86. if((pDP->Flags & RTPATCHFLAG_HASSEGS) != 0)
  87. {
  88. pInfo = (D3DRECTPATCH_INFO*)(((BYTE*)(pDP + 1) + sizeof(FLOAT) * 4));
  89. pSegs = (FLOAT*)(pDP + 1);
  90. }
  91. else
  92. {
  93. pInfo = (D3DRECTPATCH_INFO*)(pDP + 1);
  94. pSegs = 0;
  95. }
  96. RDHOCoeffs &coeffs = m_HOSCoeffs[pDP->Handle];
  97. coeffs.m_Width = pInfo->Width;
  98. coeffs.m_Height = pInfo->Height;
  99. coeffs.m_Stride = pInfo->Width;
  100. coeffs.m_Basis = pInfo->Basis;
  101. coeffs.m_Order = pInfo->Order;
  102. delete[] coeffs.m_pNumSegs;
  103. if(pSegs != 0)
  104. {
  105. coeffs.m_pNumSegs = new FLOAT[4];
  106. if(coeffs.m_pNumSegs == 0)
  107. {
  108. return E_OUTOFMEMORY;
  109. }
  110. memcpy(coeffs.m_pNumSegs, pSegs, sizeof(FLOAT) * 4);
  111. }
  112. else
  113. {
  114. coeffs.m_pNumSegs = 0;
  115. }
  116. RDVDeclaration &Decl = m_pCurrentVShader->m_Declaration;
  117. for(unsigned i = 0; i < Decl.m_dwNumActiveStreams; ++i)
  118. {
  119. RDVStreamDecl &StreamDecl = Decl.m_StreamArray[i];
  120. if(StreamDecl.m_dwStreamIndex < RD_MAX_NUMSTREAMS) // ignore the implicit stream
  121. {
  122. RDVStream &Stream = m_VStream[StreamDecl.m_dwStreamIndex];
  123. delete[] coeffs.m_pData[StreamDecl.m_dwStreamIndex];
  124. coeffs.m_DataSize[StreamDecl.m_dwStreamIndex] = pInfo->Width * pInfo->Height * Stream.m_dwStride;
  125. coeffs.m_pData[StreamDecl.m_dwStreamIndex] = new BYTE[coeffs.m_DataSize[StreamDecl.m_dwStreamIndex]];
  126. if(coeffs.m_pData[StreamDecl.m_dwStreamIndex] == 0)
  127. {
  128. return E_OUTOFMEMORY;
  129. }
  130. for(unsigned k = 0; k < pInfo->Height; ++k)
  131. {
  132. memcpy(&coeffs.m_pData[StreamDecl.m_dwStreamIndex][k * pInfo->Width * Stream.m_dwStride],
  133. &Stream.m_pData[((pInfo->StartVertexOffsetHeight + k) * pInfo->Stride + pInfo->StartVertexOffsetWidth) * Stream.m_dwStride],
  134. pInfo->Width * Stream.m_dwStride);
  135. }
  136. }
  137. }
  138. }
  139. // Guard against bad handles
  140. if(pDP->Handle >= m_HOSCoeffs.GetSize())
  141. {
  142. DPFERR("Invalid patch handle specified in Draw*Patch call");
  143. return E_FAIL;
  144. }
  145. RDHOCoeffs &coeffs = m_HOSCoeffs[pDP->Handle];
  146. Info.StartVertexOffsetWidth = 0;
  147. Info.StartVertexOffsetHeight = 0;
  148. Info.Width = coeffs.m_Width;
  149. Info.Height = coeffs.m_Height;
  150. Info.Stride = coeffs.m_Stride;
  151. Info.Basis = coeffs.m_Basis;
  152. Info.Order = coeffs.m_Order;
  153. pInfo = &Info;
  154. if((pDP->Flags & RTPATCHFLAG_HASSEGS) != 0)
  155. {
  156. pSegs = (FLOAT*)(pDP + 1);
  157. }
  158. else
  159. {
  160. pSegs = coeffs.m_pNumSegs;
  161. }
  162. // Save current data stream pointers and replace with
  163. // pointer to tessellation output
  164. hr = LinkCachedTessellatorOutput(pDP->Handle, TempData);
  165. }
  166. else
  167. {
  168. if((pDP->Flags & RTPATCHFLAG_HASINFO) == 0)
  169. {
  170. DPFERR("Need patch info if handle is zero");
  171. return DDERR_INVALIDPARAMS;
  172. }
  173. if((pDP->Flags & RTPATCHFLAG_HASSEGS) != 0)
  174. {
  175. pInfo = (D3DRECTPATCH_INFO*)(((BYTE*)(pDP + 1) + sizeof(FLOAT) * 4));
  176. pSegs = (FLOAT*)(pDP + 1);
  177. }
  178. else
  179. {
  180. pInfo = (D3DRECTPATCH_INFO*)(pDP + 1);
  181. pSegs = 0;
  182. }
  183. // Save current data stream pointers and replace with
  184. // pointer to tessellation output
  185. hr = LinkTessellatorOutput();
  186. }
  187. if( SUCCEEDED(hr) )
  188. {
  189. switch(pInfo->Basis)
  190. {
  191. case D3DBASIS_BSPLINE:
  192. hr = ProcessBSpline(pInfo->StartVertexOffsetWidth, pInfo->StartVertexOffsetHeight,
  193. pInfo->Width, pInfo->Height,
  194. pInfo->Stride, pInfo->Order,
  195. pSegs);
  196. break;
  197. case D3DBASIS_BEZIER:
  198. hr = ProcessBezier(pInfo->StartVertexOffsetWidth, pInfo->StartVertexOffsetHeight,
  199. pInfo->Width, pInfo->Height,
  200. pInfo->Stride, pInfo->Order,
  201. pSegs,
  202. false);
  203. break;
  204. case D3DBASIS_INTERPOLATE:
  205. hr = ProcessCatRomSpline(pInfo->StartVertexOffsetWidth, pInfo->StartVertexOffsetHeight,
  206. pInfo->Width, pInfo->Height,
  207. pInfo->Stride,
  208. pSegs);
  209. break;
  210. default:
  211. hr = E_NOTIMPL;
  212. }
  213. }
  214. if(pDP->Handle != 0)
  215. {
  216. // Restore back saved pointer
  217. UnlinkCachedTessellatorOutput(TempData);
  218. }
  219. else
  220. {
  221. // Restore back saved pointer
  222. UnlinkTessellatorOutput();
  223. }
  224. return hr;
  225. }
  226. //-----------------------------------------------------------------------------
  227. // RefDev::ConvertLinearTriBezierToRectBezier
  228. //-----------------------------------------------------------------------------
  229. HRESULT
  230. RefDev::ConvertLinearTriBezierToRectBezier(DWORD dwDataType, const BYTE *B, DWORD dwStride, BYTE *Q)
  231. {
  232. DWORD dwElements = 0;
  233. switch(dwDataType)
  234. {
  235. case D3DVSDT_FLOAT4:
  236. ++dwElements;
  237. case D3DVSDT_FLOAT3:
  238. ++dwElements;
  239. case D3DVSDT_FLOAT2:
  240. ++dwElements;
  241. case D3DVSDT_FLOAT1:
  242. ++dwElements;
  243. {
  244. // Replicate first point twice to get a singular edge
  245. for(unsigned i = 0; i < 2; ++i)
  246. {
  247. memcpy(Q, B, sizeof(FLOAT) * dwElements);
  248. Q += dwStride;
  249. }
  250. B += dwStride;
  251. // Finally we just copy the last row
  252. for(i = 0; i < 2; ++i)
  253. {
  254. memcpy(Q, B, sizeof(FLOAT) * dwElements);
  255. Q += dwStride;
  256. B += dwStride;
  257. }
  258. }
  259. break;
  260. case D3DVSDT_D3DCOLOR:
  261. case D3DVSDT_UBYTE4:
  262. dwElements = 4;
  263. {
  264. // Replicate first point twice to get a singular edge
  265. for(unsigned i = 0; i < 2; ++i)
  266. {
  267. memcpy(Q, B, sizeof(BYTE) * dwElements);
  268. Q += dwStride;
  269. }
  270. B += dwStride;
  271. // Finally we just copy the last row
  272. for(i = 0; i < 2; ++i)
  273. {
  274. memcpy(Q, B, sizeof(BYTE) * dwElements);
  275. Q += dwStride;
  276. B += dwStride;
  277. }
  278. }
  279. break;
  280. case D3DVSDT_SHORT4:
  281. dwElements += 2;
  282. case D3DVSDT_SHORT2:
  283. dwElements += 2;
  284. {
  285. // Replicate first point twice to get a singular edge
  286. for(unsigned i = 0; i < 2; ++i)
  287. {
  288. memcpy(Q, B, sizeof(SHORT) * dwElements);
  289. Q += dwStride;
  290. }
  291. B += dwStride;
  292. // Finally we just copy the last row
  293. for(i = 0; i < 2; ++i)
  294. {
  295. memcpy(Q, B, sizeof(SHORT) * dwElements);
  296. Q += dwStride;
  297. B += dwStride;
  298. }
  299. }
  300. break;
  301. default:
  302. _ASSERT(FALSE, "Ununderstood vertex element data type");
  303. return DDERR_INVALIDPARAMS;
  304. }
  305. return S_OK;
  306. }
  307. //-----------------------------------------------------------------------------
  308. // RefDev::ConvertCubicTriBezierToRectBezier
  309. //-----------------------------------------------------------------------------
  310. HRESULT
  311. RefDev::ConvertCubicTriBezierToRectBezier(DWORD dwDataType, const BYTE *B, DWORD dwStride, BYTE *Q)
  312. {
  313. DWORD dwElements = 0;
  314. switch(dwDataType)
  315. {
  316. case D3DVSDT_FLOAT4:
  317. ++dwElements;
  318. case D3DVSDT_FLOAT3:
  319. ++dwElements;
  320. case D3DVSDT_FLOAT2:
  321. ++dwElements;
  322. case D3DVSDT_FLOAT1:
  323. ++dwElements;
  324. {
  325. // Replicate first point four times to get a singular edge
  326. for(unsigned i = 0; i < 4; ++i)
  327. {
  328. memcpy(Q, B, sizeof(FLOAT) * dwElements);
  329. Q += dwStride;
  330. }
  331. B += dwStride;
  332. // For the next row, we simply copy the second point
  333. // followed by two interpolated control points
  334. // followed by the third point
  335. memcpy(Q, B, sizeof(FLOAT) * dwElements);
  336. Q += dwStride;
  337. FLOAT *B021 = (FLOAT*)B, *B120 = (FLOAT*)(B + dwStride);
  338. for(i = 0; i < dwElements; ++i)
  339. {
  340. ((FLOAT*)Q)[i] = FLOAT((B021[i] * 2.0 + B120[i]) / 3.0);
  341. }
  342. Q += dwStride;
  343. for(i = 0; i < dwElements; ++i)
  344. {
  345. ((FLOAT*)Q)[i] = FLOAT((B021[i] + B120[i] * 2.0) / 3.0);
  346. }
  347. Q += dwStride;
  348. B += dwStride;
  349. memcpy(Q, B, sizeof(FLOAT) * dwElements);
  350. Q += dwStride;
  351. B += dwStride;
  352. // Again, we copy the edge points and interpolate
  353. // the central ones
  354. memcpy(Q, B, sizeof(FLOAT) * dwElements);
  355. Q += dwStride;
  356. FLOAT *B012 = (FLOAT*)B, *B111 = (FLOAT*)(B + dwStride);
  357. for(i = 0; i < dwElements; ++i)
  358. {
  359. ((FLOAT*)Q)[i] = FLOAT((B012[i] + B111[i] * 2.0) / 3.0);
  360. }
  361. Q += dwStride;
  362. B += dwStride;
  363. FLOAT *B210 = (FLOAT*)(B + dwStride);
  364. for(i = 0; i < dwElements; ++i)
  365. {
  366. ((FLOAT*)Q)[i] = FLOAT((B111[i] * 2.0 + B210[i]) / 3.0);
  367. }
  368. Q += dwStride;
  369. B += dwStride;
  370. memcpy(Q, B, sizeof(FLOAT) * dwElements);
  371. Q += dwStride;
  372. B += dwStride;
  373. // Finally we just copy the last row
  374. for(i = 0; i < 4; ++i)
  375. {
  376. memcpy(Q, B, sizeof(FLOAT) * dwElements);
  377. Q += dwStride;
  378. B += dwStride;
  379. }
  380. }
  381. break;
  382. case D3DVSDT_D3DCOLOR:
  383. case D3DVSDT_UBYTE4:
  384. dwElements = 4;
  385. {
  386. // Replicate first point four times to get a singular edge
  387. for(unsigned i = 0; i < 4; ++i)
  388. {
  389. memcpy(Q, B, sizeof(BYTE) * dwElements);
  390. Q += dwStride;
  391. }
  392. B += dwStride;
  393. // For the next row, we simply copy the second point
  394. // followed by two interpolated control points
  395. // followed by the third point
  396. memcpy(Q, B, sizeof(BYTE) * dwElements);
  397. Q += dwStride;
  398. BYTE *B021 = (BYTE*)B, *B120 = (BYTE*)(B + dwStride);
  399. for(i = 0; i < dwElements; ++i)
  400. {
  401. ((BYTE*)Q)[i] = BYTE((B021[i] * 2.0 + B120[i]) / 3.0);
  402. }
  403. Q += dwStride;
  404. for(i = 0; i < dwElements; ++i)
  405. {
  406. ((BYTE*)Q)[i] = BYTE((B021[i] + B120[i] * 2.0) / 3.0);
  407. }
  408. Q += dwStride;
  409. B += dwStride;
  410. memcpy(Q, B, sizeof(BYTE) * dwElements);
  411. Q += dwStride;
  412. B += dwStride;
  413. // Again, we copy the edge points and interpolate
  414. // the central ones
  415. memcpy(Q, B, sizeof(BYTE) * dwElements);
  416. Q += dwStride;
  417. BYTE *B012 = (BYTE*)B, *B111 = (BYTE*)(B + dwStride);
  418. for(i = 0; i < dwElements; ++i)
  419. {
  420. ((BYTE*)Q)[i] = BYTE((B012[i] + B111[i] * 2.0) / 3.0);
  421. }
  422. Q += dwStride;
  423. B += dwStride;
  424. BYTE *B210 = (BYTE*)(B + dwStride);
  425. for(i = 0; i < dwElements; ++i)
  426. {
  427. ((BYTE*)Q)[i] = BYTE((B111[i] * 2.0 + B210[i]) / 3.0);
  428. }
  429. Q += dwStride;
  430. B += dwStride;
  431. memcpy(Q, B, sizeof(BYTE) * dwElements);
  432. Q += dwStride;
  433. B += dwStride;
  434. // Finally we just copy the last row
  435. for(i = 0; i < 4; ++i)
  436. {
  437. memcpy(Q, B, sizeof(BYTE) * dwElements);
  438. Q += dwStride;
  439. B += dwStride;
  440. }
  441. }
  442. break;
  443. case D3DVSDT_SHORT4:
  444. dwElements += 2;
  445. case D3DVSDT_SHORT2:
  446. dwElements += 2;
  447. {
  448. // Replicate first point four times to get a singular edge
  449. for(unsigned i = 0; i < 4; ++i)
  450. {
  451. memcpy(Q, B, sizeof(SHORT) * dwElements);
  452. Q += dwStride;
  453. }
  454. B += dwStride;
  455. // For the next row, we simply copy the second point
  456. // followed by two interpolated control points
  457. // followed by the third point
  458. memcpy(Q, B, sizeof(SHORT) * dwElements);
  459. Q += dwStride;
  460. SHORT *B021 = (SHORT*)B, *B120 = (SHORT*)(B + dwStride);
  461. for(i = 0; i < dwElements; ++i)
  462. {
  463. ((SHORT*)Q)[i] = SHORT((B021[i] * 2.0 + B120[i]) / 3.0);
  464. }
  465. Q += dwStride;
  466. for(i = 0; i < dwElements; ++i)
  467. {
  468. ((SHORT*)Q)[i] = SHORT((B021[i] + B120[i] * 2.0) / 3.0);
  469. }
  470. Q += dwStride;
  471. B += dwStride;
  472. memcpy(Q, B, sizeof(SHORT) * dwElements);
  473. Q += dwStride;
  474. B += dwStride;
  475. // Again, we copy the edge points and interpolate
  476. // the central ones
  477. memcpy(Q, B, sizeof(SHORT) * dwElements);
  478. Q += dwStride;
  479. SHORT *B012 = (SHORT*)B, *B111 = (SHORT*)(B + dwStride);
  480. for(i = 0; i < dwElements; ++i)
  481. {
  482. ((SHORT*)Q)[i] = SHORT((B012[i] + B111[i] * 2.0) / 3.0);
  483. }
  484. Q += dwStride;
  485. B += dwStride;
  486. SHORT *B210 = (SHORT*)(B + dwStride);
  487. for(i = 0; i < dwElements; ++i)
  488. {
  489. ((SHORT*)Q)[i] = SHORT((B111[i] * 2.0 + B210[i]) / 3.0);
  490. }
  491. Q += dwStride;
  492. B += dwStride;
  493. memcpy(Q, B, sizeof(SHORT) * dwElements);
  494. Q += dwStride;
  495. B += dwStride;
  496. // Finally we just copy the last row
  497. for(i = 0; i < 4; ++i)
  498. {
  499. memcpy(Q, B, sizeof(SHORT) * dwElements);
  500. Q += dwStride;
  501. B += dwStride;
  502. }
  503. }
  504. break;
  505. default:
  506. _ASSERT(FALSE, "Ununderstood vertex element data type");
  507. return DDERR_INVALIDPARAMS;
  508. }
  509. return S_OK;
  510. }
  511. //-----------------------------------------------------------------------------
  512. // RefDev::ConvertQuinticTriBezierToRectBezier
  513. //-----------------------------------------------------------------------------
  514. HRESULT
  515. RefDev::ConvertQuinticTriBezierToRectBezier(DWORD dwDataType, const BYTE *B, DWORD dwStride, BYTE *Q)
  516. {
  517. DWORD dwElements = 0;
  518. switch(dwDataType)
  519. {
  520. case D3DVSDT_FLOAT4:
  521. ++dwElements;
  522. case D3DVSDT_FLOAT3:
  523. ++dwElements;
  524. case D3DVSDT_FLOAT2:
  525. ++dwElements;
  526. case D3DVSDT_FLOAT1:
  527. ++dwElements;
  528. {
  529. // Replicate first point six times to get a singular edge
  530. for(unsigned i = 0; i < 6; ++i)
  531. {
  532. memcpy(Q, B, sizeof(FLOAT) * dwElements);
  533. Q += dwStride;
  534. }
  535. B += dwStride;
  536. // For the next row, we simply copy the second point
  537. // followed by four interpolated control points
  538. // followed by the fifth point
  539. memcpy(Q, B, sizeof(FLOAT) * dwElements);
  540. Q += dwStride;
  541. FLOAT *B041 = (FLOAT*)B, *B140 = (FLOAT*)(B + dwStride);
  542. for(i = 0; i < dwElements; ++i)
  543. {
  544. ((FLOAT*)Q)[i] = FLOAT((B041[i] * 4.0 + B140[i]) / 5.0);
  545. }
  546. Q += dwStride;
  547. for(i = 0; i < dwElements; ++i)
  548. {
  549. ((FLOAT*)Q)[i] = FLOAT((B041[i] * 3.0 + B140[i] * 2.0) / 5.0);
  550. }
  551. Q += dwStride;
  552. for(i = 0; i < dwElements; ++i)
  553. {
  554. ((FLOAT*)Q)[i] = FLOAT((B041[i] * 2.0 + B140[i] * 3.0) / 5.0);
  555. }
  556. Q += dwStride;
  557. for(i = 0; i < dwElements; ++i)
  558. {
  559. ((FLOAT*)Q)[i] = FLOAT((B041[i] + B140[i] * 4.0) / 5.0);
  560. }
  561. Q += dwStride;
  562. B += dwStride;
  563. memcpy(Q, B, sizeof(FLOAT) * dwElements);
  564. Q += dwStride;
  565. B += dwStride;
  566. // Again, we copy the edge points and interpolate
  567. // the central ones
  568. memcpy(Q, B, sizeof(FLOAT) * dwElements);
  569. Q += dwStride;
  570. FLOAT *B032 = (FLOAT*)B, *B131 = (FLOAT*)(B + dwStride);
  571. for(i = 0; i < dwElements; ++i)
  572. {
  573. ((FLOAT*)Q)[i] = FLOAT((B032[i] * 3.0 + B131[i] * 2.0) / 5.0);
  574. }
  575. Q += dwStride;
  576. B += dwStride;
  577. FLOAT *B230 = (FLOAT*)(B + dwStride);
  578. for(i = 0; i < dwElements; ++i)
  579. {
  580. ((FLOAT*)Q)[i] = FLOAT((B032[i] * 3.0 + B131[i] * 6.0 + B230[i]) / 10.0);
  581. }
  582. Q += dwStride;
  583. for(i = 0; i < dwElements; ++i)
  584. {
  585. ((FLOAT*)Q)[i] = FLOAT((B032[i] + B131[i] * 6.0 + B230[i] * 3.0) / 10.0);
  586. }
  587. Q += dwStride;
  588. for(i = 0; i < dwElements; ++i)
  589. {
  590. ((FLOAT*)Q)[i] = FLOAT((B131[i] * 2.0 + B230[i] * 3.0) / 5.0);
  591. }
  592. Q += dwStride;
  593. B += dwStride;
  594. memcpy(Q, B, sizeof(FLOAT) * dwElements);
  595. Q += dwStride;
  596. B += dwStride;
  597. // Again, we copy the edge points and interpolate
  598. // the central ones
  599. memcpy(Q, B, sizeof(FLOAT) * dwElements);
  600. Q += dwStride;
  601. FLOAT *B023 = (FLOAT*)B, *B122 = (FLOAT*)(B + dwStride);
  602. for(i = 0; i < dwElements; ++i)
  603. {
  604. ((FLOAT*)Q)[i] = FLOAT((B023[i] * 2.0 + B122[i] * 3.0) / 5.0);
  605. }
  606. Q += dwStride;
  607. B += dwStride;
  608. FLOAT *B221 = (FLOAT*)(B + dwStride);
  609. for(i = 0; i < dwElements; ++i)
  610. {
  611. ((FLOAT*)Q)[i] = FLOAT((B023[i] + B122[i] * 6.0 + B221[i] * 3.0) / 10.0);
  612. }
  613. Q += dwStride;
  614. B += dwStride;
  615. FLOAT *B320 = (FLOAT*)(B + dwStride);
  616. for(i = 0; i < dwElements; ++i)
  617. {
  618. ((FLOAT*)Q)[i] = FLOAT((B122[i] * 3.0 + B221[i] * 6.0 + B320[i]) / 10.0);
  619. }
  620. Q += dwStride;
  621. for(i = 0; i < dwElements; ++i)
  622. {
  623. ((FLOAT*)Q)[i] = FLOAT((B221[i] * 3.0 + B320[i] * 2.0) / 5.0);
  624. }
  625. Q += dwStride;
  626. B += dwStride;
  627. memcpy(Q, B, sizeof(FLOAT) * dwElements);
  628. Q += dwStride;
  629. B += dwStride;
  630. // Again, we copy the edge points and interpolate
  631. // the central ones
  632. memcpy(Q, B, sizeof(FLOAT) * dwElements);
  633. Q += dwStride;
  634. FLOAT *B014 = (FLOAT*)B, *B113 = (FLOAT*)(B + dwStride);
  635. for(i = 0; i < dwElements; ++i)
  636. {
  637. ((FLOAT*)Q)[i] = FLOAT((B014[i] + B113[i] * 4.0) / 5.0);
  638. }
  639. Q += dwStride;
  640. B += dwStride;
  641. FLOAT *B212 = (FLOAT*)(B + dwStride);
  642. for(i = 0; i < dwElements; ++i)
  643. {
  644. ((FLOAT*)Q)[i] = FLOAT((B113[i] * 2.0 + B212[i] * 3.0) / 5.0);
  645. }
  646. Q += dwStride;
  647. B += dwStride;
  648. FLOAT *B311 = (FLOAT*)(B + dwStride);
  649. for(i = 0; i < dwElements; ++i)
  650. {
  651. ((FLOAT*)Q)[i] = FLOAT((B212[i] * 3.0 + B311[i] * 2.0) / 5.0);
  652. }
  653. Q += dwStride;
  654. B += dwStride;
  655. FLOAT *B410 = (FLOAT*)(B + dwStride);
  656. for(i = 0; i < dwElements; ++i)
  657. {
  658. ((FLOAT*)Q)[i] = FLOAT((B311[i] * 4.0 + B410[i]) / 5.0);
  659. }
  660. Q += dwStride;
  661. B += dwStride;
  662. memcpy(Q, B, sizeof(FLOAT) * dwElements);
  663. Q += dwStride;
  664. B += dwStride;
  665. // Finally we just copy the last row
  666. for(i = 0; i < 6; ++i)
  667. {
  668. memcpy(Q, B, sizeof(FLOAT) * dwElements);
  669. Q += dwStride;
  670. B += dwStride;
  671. }
  672. }
  673. break;
  674. case D3DVSDT_UBYTE4:
  675. case D3DVSDT_D3DCOLOR:
  676. dwElements = 4;
  677. {
  678. // Replicate first point six times to get a singular edge
  679. for(unsigned i = 0; i < 6; ++i)
  680. {
  681. memcpy(Q, B, sizeof(BYTE) * dwElements);
  682. Q += dwStride;
  683. }
  684. B += dwStride;
  685. // For the next row, we simply copy the second point
  686. // followed by four interpolated control points
  687. // followed by the fifth point
  688. memcpy(Q, B, sizeof(BYTE) * dwElements);
  689. Q += dwStride;
  690. BYTE *B041 = (BYTE*)B, *B140 = (BYTE*)(B + dwStride);
  691. for(i = 0; i < dwElements; ++i)
  692. {
  693. ((BYTE*)Q)[i] = BYTE((B041[i] * 4.0 + B140[i]) / 5.0);
  694. }
  695. Q += dwStride;
  696. for(i = 0; i < dwElements; ++i)
  697. {
  698. ((BYTE*)Q)[i] = BYTE((B041[i] * 3.0 + B140[i] * 2.0) / 5.0);
  699. }
  700. Q += dwStride;
  701. for(i = 0; i < dwElements; ++i)
  702. {
  703. ((BYTE*)Q)[i] = BYTE((B041[i] * 2.0 + B140[i] * 3.0) / 5.0);
  704. }
  705. Q += dwStride;
  706. for(i = 0; i < dwElements; ++i)
  707. {
  708. ((BYTE*)Q)[i] = BYTE((B041[i] + B140[i] * 4.0) / 5.0);
  709. }
  710. Q += dwStride;
  711. B += dwStride;
  712. memcpy(Q, B, sizeof(BYTE) * dwElements);
  713. Q += dwStride;
  714. B += dwStride;
  715. // Again, we copy the edge points and interpolate
  716. // the central ones
  717. memcpy(Q, B, sizeof(BYTE) * dwElements);
  718. Q += dwStride;
  719. BYTE *B032 = (BYTE*)B, *B131 = (BYTE*)(B + dwStride);
  720. for(i = 0; i < dwElements; ++i)
  721. {
  722. ((BYTE*)Q)[i] = BYTE((B032[i] * 3.0 + B131[i] * 2.0) / 5.0);
  723. }
  724. Q += dwStride;
  725. B += dwStride;
  726. BYTE *B230 = (BYTE*)(B + dwStride);
  727. for(i = 0; i < dwElements; ++i)
  728. {
  729. ((BYTE*)Q)[i] = BYTE((B032[i] * 3.0 + B131[i] * 6.0 + B230[i]) / 10.0);
  730. }
  731. Q += dwStride;
  732. for(i = 0; i < dwElements; ++i)
  733. {
  734. ((BYTE*)Q)[i] = BYTE((B032[i] + B131[i] * 6.0 + B230[i] * 3.0) / 10.0);
  735. }
  736. Q += dwStride;
  737. for(i = 0; i < dwElements; ++i)
  738. {
  739. ((BYTE*)Q)[i] = BYTE((B131[i] * 2.0 + B230[i] * 3.0) / 5.0);
  740. }
  741. Q += dwStride;
  742. B += dwStride;
  743. memcpy(Q, B, sizeof(BYTE) * dwElements);
  744. Q += dwStride;
  745. B += dwStride;
  746. // Again, we copy the edge points and interpolate
  747. // the central ones
  748. memcpy(Q, B, sizeof(BYTE) * dwElements);
  749. Q += dwStride;
  750. BYTE *B023 = (BYTE*)B, *B122 = (BYTE*)(B + dwStride);
  751. for(i = 0; i < dwElements; ++i)
  752. {
  753. ((BYTE*)Q)[i] = BYTE((B023[i] * 2.0 + B122[i] * 3.0) / 5.0);
  754. }
  755. Q += dwStride;
  756. B += dwStride;
  757. BYTE *B221 = (BYTE*)(B + dwStride);
  758. for(i = 0; i < dwElements; ++i)
  759. {
  760. ((BYTE*)Q)[i] = BYTE((B023[i] + B122[i] * 6.0 + B221[i] * 3.0) / 10.0);
  761. }
  762. Q += dwStride;
  763. B += dwStride;
  764. BYTE *B320 = (BYTE*)(B + dwStride);
  765. for(i = 0; i < dwElements; ++i)
  766. {
  767. ((BYTE*)Q)[i] = BYTE((B122[i] * 3.0 + B221[i] * 6.0 + B320[i]) / 10.0);
  768. }
  769. Q += dwStride;
  770. for(i = 0; i < dwElements; ++i)
  771. {
  772. ((BYTE*)Q)[i] = BYTE((B221[i] * 3.0 + B320[i] * 2.0) / 5.0);
  773. }
  774. Q += dwStride;
  775. B += dwStride;
  776. memcpy(Q, B, sizeof(BYTE) * dwElements);
  777. Q += dwStride;
  778. B += dwStride;
  779. // Again, we copy the edge points and interpolate
  780. // the central ones
  781. memcpy(Q, B, sizeof(BYTE) * dwElements);
  782. Q += dwStride;
  783. BYTE *B014 = (BYTE*)B, *B113 = (BYTE*)(B + dwStride);
  784. for(i = 0; i < dwElements; ++i)
  785. {
  786. ((BYTE*)Q)[i] = BYTE((B014[i] + B113[i] * 4.0) / 5.0);
  787. }
  788. Q += dwStride;
  789. B += dwStride;
  790. BYTE *B212 = (BYTE*)(B + dwStride);
  791. for(i = 0; i < dwElements; ++i)
  792. {
  793. ((BYTE*)Q)[i] = BYTE((B113[i] * 2.0 + B212[i] * 3.0) / 5.0);
  794. }
  795. Q += dwStride;
  796. B += dwStride;
  797. BYTE *B311 = (BYTE*)(B + dwStride);
  798. for(i = 0; i < dwElements; ++i)
  799. {
  800. ((BYTE*)Q)[i] = BYTE((B212[i] * 3.0 + B311[i] * 2.0) / 5.0);
  801. }
  802. Q += dwStride;
  803. B += dwStride;
  804. BYTE *B410 = (BYTE*)(B + dwStride);
  805. for(i = 0; i < dwElements; ++i)
  806. {
  807. ((BYTE*)Q)[i] = BYTE((B311[i] * 4.0 + B410[i]) / 5.0);
  808. }
  809. Q += dwStride;
  810. B += dwStride;
  811. memcpy(Q, B, sizeof(BYTE) * dwElements);
  812. Q += dwStride;
  813. B += dwStride;
  814. // Finally we just copy the last row
  815. for(i = 0; i < 6; ++i)
  816. {
  817. memcpy(Q, B, sizeof(BYTE) * dwElements);
  818. Q += dwStride;
  819. B += dwStride;
  820. }
  821. }
  822. break;
  823. case D3DVSDT_SHORT4:
  824. dwElements += 2;
  825. case D3DVSDT_SHORT2:
  826. dwElements += 2;
  827. {
  828. // Replicate first point six times to get a singular edge
  829. for(unsigned i = 0; i < 6; ++i)
  830. {
  831. memcpy(Q, B, sizeof(SHORT) * dwElements);
  832. Q += dwStride;
  833. }
  834. B += dwStride;
  835. // For the next row, we simply copy the second point
  836. // followed by four interpolated control points
  837. // followed by the fifth point
  838. memcpy(Q, B, sizeof(SHORT) * dwElements);
  839. Q += dwStride;
  840. SHORT *B041 = (SHORT*)B, *B140 = (SHORT*)(B + dwStride);
  841. for(i = 0; i < dwElements; ++i)
  842. {
  843. ((SHORT*)Q)[i] = SHORT((B041[i] * 4.0 + B140[i]) / 5.0);
  844. }
  845. Q += dwStride;
  846. for(i = 0; i < dwElements; ++i)
  847. {
  848. ((SHORT*)Q)[i] = SHORT((B041[i] * 3.0 + B140[i] * 2.0) / 5.0);
  849. }
  850. Q += dwStride;
  851. for(i = 0; i < dwElements; ++i)
  852. {
  853. ((SHORT*)Q)[i] = SHORT((B041[i] * 2.0 + B140[i] * 3.0) / 5.0);
  854. }
  855. Q += dwStride;
  856. for(i = 0; i < dwElements; ++i)
  857. {
  858. ((SHORT*)Q)[i] = SHORT((B041[i] + B140[i] * 4.0) / 5.0);
  859. }
  860. Q += dwStride;
  861. B += dwStride;
  862. memcpy(Q, B, sizeof(SHORT) * dwElements);
  863. Q += dwStride;
  864. B += dwStride;
  865. // Again, we copy the edge points and interpolate
  866. // the central ones
  867. memcpy(Q, B, sizeof(SHORT) * dwElements);
  868. Q += dwStride;
  869. SHORT *B032 = (SHORT*)B, *B131 = (SHORT*)(B + dwStride);
  870. for(i = 0; i < dwElements; ++i)
  871. {
  872. ((SHORT*)Q)[i] = SHORT((B032[i] * 3.0 + B131[i] * 2.0) / 5.0);
  873. }
  874. Q += dwStride;
  875. B += dwStride;
  876. SHORT *B230 = (SHORT*)(B + dwStride);
  877. for(i = 0; i < dwElements; ++i)
  878. {
  879. ((SHORT*)Q)[i] = SHORT((B032[i] * 3.0 + B131[i] * 6.0 + B230[i]) / 10.0);
  880. }
  881. Q += dwStride;
  882. for(i = 0; i < dwElements; ++i)
  883. {
  884. ((SHORT*)Q)[i] = SHORT((B032[i] + B131[i] * 6.0 + B230[i] * 3.0) / 10.0);
  885. }
  886. Q += dwStride;
  887. for(i = 0; i < dwElements; ++i)
  888. {
  889. ((SHORT*)Q)[i] = SHORT((B131[i] * 2.0 + B230[i] * 3.0) / 5.0);
  890. }
  891. Q += dwStride;
  892. B += dwStride;
  893. memcpy(Q, B, sizeof(SHORT) * dwElements);
  894. Q += dwStride;
  895. B += dwStride;
  896. // Again, we copy the edge points and interpolate
  897. // the central ones
  898. memcpy(Q, B, sizeof(SHORT) * dwElements);
  899. Q += dwStride;
  900. SHORT *B023 = (SHORT*)B, *B122 = (SHORT*)(B + dwStride);
  901. for(i = 0; i < dwElements; ++i)
  902. {
  903. ((SHORT*)Q)[i] = SHORT((B023[i] * 2.0 + B122[i] * 3.0) / 5.0);
  904. }
  905. Q += dwStride;
  906. B += dwStride;
  907. SHORT *B221 = (SHORT*)(B + dwStride);
  908. for(i = 0; i < dwElements; ++i)
  909. {
  910. ((SHORT*)Q)[i] = SHORT((B023[i] + B122[i] * 6.0 + B221[i] * 3.0) / 10.0);
  911. }
  912. Q += dwStride;
  913. B += dwStride;
  914. SHORT *B320 = (SHORT*)(B + dwStride);
  915. for(i = 0; i < dwElements; ++i)
  916. {
  917. ((SHORT*)Q)[i] = SHORT((B122[i] * 3.0 + B221[i] * 6.0 + B320[i]) / 10.0);
  918. }
  919. Q += dwStride;
  920. for(i = 0; i < dwElements; ++i)
  921. {
  922. ((SHORT*)Q)[i] = SHORT((B221[i] * 3.0 + B320[i] * 2.0) / 5.0);
  923. }
  924. Q += dwStride;
  925. B += dwStride;
  926. memcpy(Q, B, sizeof(SHORT) * dwElements);
  927. Q += dwStride;
  928. B += dwStride;
  929. // Again, we copy the edge points and interpolate
  930. // the central ones
  931. memcpy(Q, B, sizeof(SHORT) * dwElements);
  932. Q += dwStride;
  933. SHORT *B014 = (SHORT*)B, *B113 = (SHORT*)(B + dwStride);
  934. for(i = 0; i < dwElements; ++i)
  935. {
  936. ((SHORT*)Q)[i] = SHORT((B014[i] + B113[i] * 4.0) / 5.0);
  937. }
  938. Q += dwStride;
  939. B += dwStride;
  940. SHORT *B212 = (SHORT*)(B + dwStride);
  941. for(i = 0; i < dwElements; ++i)
  942. {
  943. ((SHORT*)Q)[i] = SHORT((B113[i] * 2.0 + B212[i] * 3.0) / 5.0);
  944. }
  945. Q += dwStride;
  946. B += dwStride;
  947. SHORT *B311 = (SHORT*)(B + dwStride);
  948. for(i = 0; i < dwElements; ++i)
  949. {
  950. ((SHORT*)Q)[i] = SHORT((B212[i] * 3.0 + B311[i] * 2.0) / 5.0);
  951. }
  952. Q += dwStride;
  953. B += dwStride;
  954. SHORT *B410 = (SHORT*)(B + dwStride);
  955. for(i = 0; i < dwElements; ++i)
  956. {
  957. ((SHORT*)Q)[i] = SHORT((B311[i] * 4.0 + B410[i]) / 5.0);
  958. }
  959. Q += dwStride;
  960. B += dwStride;
  961. memcpy(Q, B, sizeof(SHORT) * dwElements);
  962. Q += dwStride;
  963. B += dwStride;
  964. // Finally we just copy the last row
  965. for(i = 0; i < 6; ++i)
  966. {
  967. memcpy(Q, B, sizeof(SHORT) * dwElements);
  968. Q += dwStride;
  969. B += dwStride;
  970. }
  971. }
  972. break;
  973. default:
  974. _ASSERT(FALSE, "Ununderstood vertex element data type");
  975. return DDERR_INVALIDPARAMS;
  976. }
  977. return S_OK;
  978. }
  979. //-----------------------------------------------------------------------------
  980. // RefDev::DrawTriPatch
  981. //-----------------------------------------------------------------------------
  982. HRESULT
  983. RefDev::DrawTriPatch( LPD3DHAL_DP2DRAWTRIPATCH pDP )
  984. {
  985. HRESULT hr = S_OK;
  986. if( RDVSD_ISLEGACY( m_CurrentVShaderHandle ) )
  987. {
  988. //
  989. // The legacy FVF style: The Zero'th Stream is implied
  990. //
  991. DWORD dwFVF = m_CurrentVShaderHandle;
  992. RDVStream& Stream = m_VStream[0];
  993. DWORD dwStride = Stream.m_dwStride;
  994. DWORD dwFVFSize = GetFVFVertexSize( dwFVF );
  995. if( Stream.m_pData == NULL || dwStride == 0 )
  996. {
  997. DPFERR("Zero'th stream doesnt have valid VB set");
  998. return DDERR_INVALIDPARAMS;
  999. }
  1000. if( dwStride < dwFVFSize )
  1001. {
  1002. DPFERR("The stride set for the vertex stream is less than the FVF vertex size");
  1003. return E_FAIL;
  1004. }
  1005. }
  1006. FLOAT *pSegs;
  1007. D3DRECTPATCH_INFO Info;
  1008. BYTE *TempData[RD_MAX_NUMSTREAMS + 1];
  1009. if(pDP->Handle == 0 && (pDP->Flags & RTPATCHFLAG_HASINFO) == 0)
  1010. {
  1011. DPFERR("Need patch info if handle is zero");
  1012. return DDERR_INVALIDPARAMS;
  1013. }
  1014. if((pDP->Flags & RTPATCHFLAG_HASINFO) != 0) // Is either a first time or a recompute
  1015. {
  1016. HR_RET( m_HOSCoeffs.Grow(pDP->Handle) );
  1017. D3DTRIPATCH_INFO *pInfo;
  1018. if((pDP->Flags & RTPATCHFLAG_HASSEGS) != 0)
  1019. {
  1020. pInfo = (D3DTRIPATCH_INFO*)(((BYTE*)(pDP + 1) + sizeof(FLOAT) * 3));
  1021. pSegs = (FLOAT*)(pDP + 1);
  1022. }
  1023. else
  1024. {
  1025. pInfo = (D3DTRIPATCH_INFO*)(pDP + 1);
  1026. pSegs = 0;
  1027. }
  1028. RDHOCoeffs &coeffs = m_HOSCoeffs[pDP->Handle];
  1029. coeffs.m_Width = (DWORD)pInfo->Order + 1;
  1030. coeffs.m_Height = (DWORD)pInfo->Order + 1;
  1031. coeffs.m_Stride = (DWORD)pInfo->Order + 1;
  1032. coeffs.m_Basis = pInfo->Basis;
  1033. coeffs.m_Order = pInfo->Order;
  1034. delete[] coeffs.m_pNumSegs;
  1035. if(pSegs != 0)
  1036. {
  1037. coeffs.m_pNumSegs = new FLOAT[4];
  1038. if(coeffs.m_pNumSegs == 0)
  1039. {
  1040. return E_OUTOFMEMORY;
  1041. }
  1042. coeffs.m_pNumSegs[0] = pSegs[2];
  1043. memcpy(&coeffs.m_pNumSegs[1], pSegs, sizeof(FLOAT) * 3);
  1044. }
  1045. else
  1046. {
  1047. coeffs.m_pNumSegs = 0;
  1048. }
  1049. RDVDeclaration &Decl = m_pCurrentVShader->m_Declaration;
  1050. // Allocate memory to hold rect patches rather than tri patches
  1051. for(unsigned i = 0; i < Decl.m_dwNumActiveStreams; ++i)
  1052. {
  1053. RDVStreamDecl &StreamDecl = Decl.m_StreamArray[i];
  1054. if(StreamDecl.m_dwStreamIndex < RD_MAX_NUMSTREAMS) // ignore the implicit stream
  1055. {
  1056. RDVStream &Stream = m_VStream[StreamDecl.m_dwStreamIndex];
  1057. delete[] coeffs.m_pData[StreamDecl.m_dwStreamIndex];
  1058. coeffs.m_DataSize[StreamDecl.m_dwStreamIndex] = coeffs.m_Width * coeffs.m_Height * Stream.m_dwStride;
  1059. coeffs.m_pData[StreamDecl.m_dwStreamIndex] = new BYTE[coeffs.m_DataSize[StreamDecl.m_dwStreamIndex]];
  1060. if(coeffs.m_pData[StreamDecl.m_dwStreamIndex] == 0)
  1061. {
  1062. return E_OUTOFMEMORY;
  1063. }
  1064. }
  1065. }
  1066. // Now go through tri patch data, convert it to rect patch and store it in
  1067. // in the space that we allocated above
  1068. for(unsigned e = 0; e < Decl.m_dwNumElements; ++e)
  1069. {
  1070. RDVElement &velem = Decl.m_VertexElements[e];
  1071. if(!velem.m_bIsTessGen)
  1072. {
  1073. RDVStream &vstream = m_VStream[velem.m_dwStreamIndex];
  1074. LPBYTE Q = coeffs.m_pData[velem.m_dwStreamIndex] + velem.m_dwOffset;
  1075. LPBYTE B = vstream.m_pData + pInfo->StartVertexOffset * vstream.m_dwStride + velem.m_dwOffset;
  1076. if(pInfo->Order == D3DORDER_LINEAR)
  1077. {
  1078. hr = ConvertLinearTriBezierToRectBezier(velem.m_dwDataType, B, vstream.m_dwStride, Q);
  1079. if(FAILED(hr))
  1080. {
  1081. DPFERR("Conversion from Linear Tri Patch to Rect Patch failed");
  1082. return E_FAIL;
  1083. }
  1084. }
  1085. else if(pInfo->Order == D3DORDER_CUBIC)
  1086. {
  1087. hr = ConvertCubicTriBezierToRectBezier(velem.m_dwDataType, B, vstream.m_dwStride, Q);
  1088. if(FAILED(hr))
  1089. {
  1090. DPFERR("Conversion from Cubic Tri Patch to Rect Patch failed");
  1091. return E_FAIL;
  1092. }
  1093. }
  1094. else if(pInfo->Order == D3DORDER_QUINTIC)
  1095. {
  1096. hr = ConvertQuinticTriBezierToRectBezier(velem.m_dwDataType, B, vstream.m_dwStride, Q);
  1097. if(FAILED(hr))
  1098. {
  1099. DPFERR("Conversion from Quintic Tri Patch to Rect Patch failed");
  1100. return E_FAIL;
  1101. }
  1102. }
  1103. else
  1104. {
  1105. DPFERR("Only cubic Bezier patches currently supported");
  1106. return E_FAIL;
  1107. }
  1108. }
  1109. }
  1110. }
  1111. // Guard against bad handles
  1112. if(pDP->Handle >= m_HOSCoeffs.GetSize())
  1113. {
  1114. DPFERR("Invalid patch handle specified in Draw*Patch call");
  1115. return E_FAIL;
  1116. }
  1117. RDHOCoeffs &coeffs = m_HOSCoeffs[pDP->Handle];
  1118. Info.StartVertexOffsetWidth = 0;
  1119. Info.StartVertexOffsetHeight = 0;
  1120. Info.Width = coeffs.m_Width;
  1121. Info.Height = coeffs.m_Height;
  1122. Info.Stride = coeffs.m_Stride;
  1123. Info.Basis = coeffs.m_Basis;
  1124. Info.Order = coeffs.m_Order;
  1125. D3DRECTPATCH_INFO *pInfo = &Info;
  1126. FLOAT Segs[4];
  1127. if((pDP->Flags & RTPATCHFLAG_HASSEGS) != 0)
  1128. {
  1129. Segs[0] = ((FLOAT*)(pDP + 1))[2];
  1130. memcpy(&Segs[1], pDP + 1, sizeof(FLOAT) * 3);
  1131. pSegs = &Segs[0];
  1132. }
  1133. else
  1134. {
  1135. pSegs = coeffs.m_pNumSegs;
  1136. }
  1137. // Save current data stream pointers and replace with
  1138. // pointer to tessellation output
  1139. hr = LinkCachedTessellatorOutput(pDP->Handle, TempData);
  1140. if( SUCCEEDED(hr) )
  1141. {
  1142. switch(pInfo->Basis)
  1143. {
  1144. case D3DBASIS_BEZIER:
  1145. hr = ProcessBezier(pInfo->StartVertexOffsetWidth, pInfo->StartVertexOffsetHeight,
  1146. pInfo->Width, pInfo->Height,
  1147. pInfo->Stride, pInfo->Order,
  1148. pSegs,
  1149. true);
  1150. break;
  1151. default:
  1152. hr = E_NOTIMPL;
  1153. }
  1154. }
  1155. // Restore back saved pointer
  1156. UnlinkCachedTessellatorOutput(TempData);
  1157. return hr;
  1158. }
  1159. //---------------------------------------------------------------------
  1160. // RefDev::LinkTessellatorOutput
  1161. //---------------------------------------------------------------------
  1162. HRESULT RefDev::LinkTessellatorOutput()
  1163. {
  1164. HRESULT hr = S_OK;
  1165. RDVDeclaration &Decl = m_pCurrentVShader->m_Declaration;
  1166. for(unsigned i = 0; i < Decl.m_dwNumActiveStreams; ++i)
  1167. {
  1168. RDVStreamDecl &StreamDecl = Decl.m_StreamArray[i];
  1169. RDVStream &Stream = m_VStream[StreamDecl.m_dwStreamIndex];
  1170. // Make space for four vertices
  1171. hr |= Stream.m_TessOut.Grow(StreamDecl.m_dwStride * 4);
  1172. Stream.m_pSavedData = Stream.m_pData;
  1173. Stream.m_pData = &Stream.m_TessOut[0];
  1174. }
  1175. return hr;
  1176. }
  1177. //---------------------------------------------------------------------
  1178. // RefDev::LinkCachedTessellatorOutput
  1179. //---------------------------------------------------------------------
  1180. HRESULT RefDev::LinkCachedTessellatorOutput(DWORD Handle, BYTE **pTempData)
  1181. {
  1182. HRESULT hr = S_OK;
  1183. RDVDeclaration &Decl = m_pCurrentVShader->m_Declaration;
  1184. for(unsigned i = 0; i < Decl.m_dwNumActiveStreams; ++i)
  1185. {
  1186. RDVStreamDecl &StreamDecl = Decl.m_StreamArray[i];
  1187. RDVStream &Stream = m_VStream[StreamDecl.m_dwStreamIndex];
  1188. // Make space for four vertices
  1189. hr |= Stream.m_TessOut.Grow(StreamDecl.m_dwStride * 4);
  1190. if(StreamDecl.m_dwStreamIndex < RD_MAX_NUMSTREAMS) // ignore the implicit stream
  1191. {
  1192. Stream.m_pSavedData = m_HOSCoeffs[Handle].m_pData[StreamDecl.m_dwStreamIndex];
  1193. if(Stream.m_pSavedData == 0)
  1194. {
  1195. DPFERR("Deleted or unspecified patch was requested to be drawn");
  1196. hr |= E_FAIL;
  1197. }
  1198. }
  1199. else
  1200. {
  1201. Stream.m_pSavedData = 0;
  1202. }
  1203. pTempData[StreamDecl.m_dwStreamIndex] = Stream.m_pData;
  1204. Stream.m_pData = &Stream.m_TessOut[0];
  1205. }
  1206. return hr;
  1207. }
  1208. //---------------------------------------------------------------------
  1209. // RefDev::UnlinkTessellatorOuput
  1210. //---------------------------------------------------------------------
  1211. void RefDev::UnlinkTessellatorOutput()
  1212. {
  1213. RDVDeclaration &Decl = m_pCurrentVShader->m_Declaration;
  1214. for(unsigned i = 0; i < Decl.m_dwNumActiveStreams; ++i)
  1215. {
  1216. RDVStreamDecl &StreamDecl = Decl.m_StreamArray[i];
  1217. RDVStream &Stream = m_VStream[StreamDecl.m_dwStreamIndex];
  1218. Stream.m_pData = Stream.m_pSavedData;
  1219. Stream.m_pSavedData = NULL;
  1220. }
  1221. }
  1222. //---------------------------------------------------------------------
  1223. // RefDev::UnlinkTessellatorOuput
  1224. //---------------------------------------------------------------------
  1225. void RefDev::UnlinkCachedTessellatorOutput(BYTE **pTempData)
  1226. {
  1227. RDVDeclaration &Decl = m_pCurrentVShader->m_Declaration;
  1228. for(unsigned i = 0; i < Decl.m_dwNumActiveStreams; ++i)
  1229. {
  1230. RDVStreamDecl &StreamDecl = Decl.m_StreamArray[i];
  1231. RDVStream &Stream = m_VStream[StreamDecl.m_dwStreamIndex];
  1232. Stream.m_pData = pTempData[StreamDecl.m_dwStreamIndex];
  1233. Stream.m_pSavedData = NULL;
  1234. }
  1235. }
  1236. //---------------------------------------------------------------------
  1237. // RefDev::DrawTessQuad
  1238. //---------------------------------------------------------------------
  1239. HRESULT RefDev::DrawTessQuad( const RDBSpline &Surf, DWORD dwOffW, DWORD dwOffH, DWORD dwStride,
  1240. const unsigned *m, const unsigned *n,
  1241. double u0, double v0, double u1, double v1,
  1242. double tu0, double tv0, double tu1, double tv1,
  1243. bool bDegenerate )
  1244. {
  1245. RDVDeclaration &Decl = m_pCurrentVShader->m_Declaration;
  1246. for(unsigned e = 0; e < Decl.m_dwNumElements; ++e)
  1247. {
  1248. RDVElement &velem = Decl.m_VertexElements[e];
  1249. if(velem.m_bIsTessGen)
  1250. {
  1251. if((velem.m_dwToken & 0x10000000) == 0) // Check if token is D3DVSD_TESSNORMAL
  1252. {
  1253. RDVStream &vstrmin = m_VStream[velem.m_dwStreamIndexIn];
  1254. RDVStream &vstream = m_VStream[velem.m_dwStreamIndex];
  1255. LPBYTE Q = &vstream.m_pData[velem.m_dwOffset];
  1256. LPBYTE B = vstrmin.m_pSavedData + ((dwOffH + n[0]) * dwStride + (dwOffW + m[0])) * vstrmin.m_dwStride + velem.m_dwOffsetIn;
  1257. Surf.SampleNormal(velem.m_dwDataType, u0, v0, B, vstrmin.m_dwStride, dwStride * vstrmin.m_dwStride, Q);
  1258. Q += vstream.m_dwStride;
  1259. B = vstrmin.m_pSavedData + ((dwOffH + n[1]) * dwStride + (dwOffW + m[1])) * vstrmin.m_dwStride + velem.m_dwOffsetIn;
  1260. Surf.SampleNormal(velem.m_dwDataType, u1, v0, B, vstrmin.m_dwStride, dwStride * vstrmin.m_dwStride, Q);
  1261. Q += vstream.m_dwStride;
  1262. B = vstrmin.m_pSavedData + ((dwOffH + n[2]) * dwStride + (dwOffW + m[2])) * vstrmin.m_dwStride + velem.m_dwOffsetIn;
  1263. Surf.SampleNormal(velem.m_dwDataType, u1, v1, B, vstrmin.m_dwStride, dwStride * vstrmin.m_dwStride, Q);
  1264. Q += vstream.m_dwStride;
  1265. B = vstrmin.m_pSavedData + ((dwOffH + n[3]) * dwStride + (dwOffW + m[3])) * vstrmin.m_dwStride + velem.m_dwOffsetIn;
  1266. Surf.SampleNormal(velem.m_dwDataType, u0, v1, B, vstrmin.m_dwStride, dwStride * vstrmin.m_dwStride, Q);
  1267. }
  1268. else // it is D3DVSD_TESSUV
  1269. {
  1270. RDVStream &vstream = m_VStream[velem.m_dwStreamIndex];
  1271. LPBYTE Q = &vstream.m_pData[velem.m_dwOffset];
  1272. if(bDegenerate)
  1273. {
  1274. ((FLOAT*)Q)[0] = (FLOAT)(tu0 * tv0);
  1275. ((FLOAT*)Q)[1] = (FLOAT)tv0;
  1276. }
  1277. else
  1278. {
  1279. ((FLOAT*)Q)[0] = (FLOAT)tu0;
  1280. ((FLOAT*)Q)[1] = (FLOAT)tv0;
  1281. }
  1282. Q += vstream.m_dwStride;
  1283. if(bDegenerate)
  1284. {
  1285. ((FLOAT*)Q)[0] = (FLOAT)(tu1 * tv0);
  1286. ((FLOAT*)Q)[1] = (FLOAT)tv0;
  1287. }
  1288. else
  1289. {
  1290. ((FLOAT*)Q)[0] = (FLOAT)tu1;
  1291. ((FLOAT*)Q)[1] = (FLOAT)tv0;
  1292. }
  1293. Q += vstream.m_dwStride;
  1294. if(bDegenerate)
  1295. {
  1296. ((FLOAT*)Q)[0] = (FLOAT)(tu1 * tv1);
  1297. ((FLOAT*)Q)[1] = (FLOAT)tv1;
  1298. }
  1299. else
  1300. {
  1301. ((FLOAT*)Q)[0] = (FLOAT)tu1;
  1302. ((FLOAT*)Q)[1] = (FLOAT)tv1;
  1303. }
  1304. Q += vstream.m_dwStride;
  1305. if(bDegenerate)
  1306. {
  1307. ((FLOAT*)Q)[0] = (FLOAT)(tu0 * tv1);
  1308. ((FLOAT*)Q)[1] = (FLOAT)tv1;
  1309. }
  1310. else
  1311. {
  1312. ((FLOAT*)Q)[0] = (FLOAT)tu0;
  1313. ((FLOAT*)Q)[1] = (FLOAT)tv1;
  1314. }
  1315. }
  1316. }
  1317. else
  1318. {
  1319. RDVStream &vstream = m_VStream[velem.m_dwStreamIndex];
  1320. LPBYTE B = vstream.m_pSavedData + ((dwOffH + n[0]) * dwStride + (dwOffW + m[0])) * vstream.m_dwStride + velem.m_dwOffset;
  1321. LPBYTE Q = &vstream.m_pData[velem.m_dwOffset];
  1322. Surf.Sample(velem.m_dwDataType, u0, v0, B, vstream.m_dwStride, dwStride * vstream.m_dwStride, Q);
  1323. Q += vstream.m_dwStride;
  1324. B = vstream.m_pSavedData + ((dwOffH + n[1]) * dwStride + (dwOffW + m[1])) * vstream.m_dwStride + velem.m_dwOffset;
  1325. Surf.Sample(velem.m_dwDataType, u1, v0, B, vstream.m_dwStride, dwStride * vstream.m_dwStride, Q);
  1326. Q += vstream.m_dwStride;
  1327. B = vstream.m_pSavedData + ((dwOffH + n[2]) * dwStride + (dwOffW + m[2])) * vstream.m_dwStride + velem.m_dwOffset;
  1328. Surf.Sample(velem.m_dwDataType, u1, v1, B, vstream.m_dwStride, dwStride * vstream.m_dwStride, Q);
  1329. Q += vstream.m_dwStride;
  1330. B = vstream.m_pSavedData + ((dwOffH + n[3]) * dwStride + (dwOffW + m[3])) * vstream.m_dwStride + velem.m_dwOffset;
  1331. Surf.Sample(velem.m_dwDataType, u0, v1, B, vstream.m_dwStride, dwStride * vstream.m_dwStride, Q);
  1332. }
  1333. }
  1334. HRESULT hr;
  1335. if( m_pCurrentVShader->IsFixedFunction() )
  1336. {
  1337. //
  1338. // With declaration for Fixed Function pipeline, DX8 style
  1339. //
  1340. hr = ProcessPrimitive( D3DPT_TRIANGLEFAN, 0, 4, 0, 0 );
  1341. }
  1342. else
  1343. {
  1344. //
  1345. // Pure Vertex Shader
  1346. //
  1347. hr = ProcessPrimitiveVVM( D3DPT_TRIANGLEFAN, 0, 4, 0, 0 );
  1348. }
  1349. return hr;
  1350. }
  1351. //---------------------------------------------------------------------
  1352. // RefDev::DrawTessTri
  1353. //---------------------------------------------------------------------
  1354. HRESULT RefDev::DrawTessTri( const RDBSpline &Surf, DWORD dwOffW, DWORD dwOffH, DWORD dwStride,
  1355. const unsigned *m, const unsigned *n,
  1356. double u0, double v0, double u1, double v1, double u2, double v2,
  1357. double tu0, double tv0, double tu1, double tv1, double tu2, double tv2,
  1358. bool bDegenerate0, bool bDegenerate1, bool bDegenerate2 )
  1359. {
  1360. RDVDeclaration &Decl = m_pCurrentVShader->m_Declaration;
  1361. for(unsigned e = 0; e < Decl.m_dwNumElements; ++e)
  1362. {
  1363. RDVElement &velem = Decl.m_VertexElements[e];
  1364. if(velem.m_bIsTessGen)
  1365. {
  1366. if((velem.m_dwToken & 0x10000000) == 0) // Check if token is D3DVSD_TESSNORMAL
  1367. {
  1368. RDVStream &vstrmin = m_VStream[velem.m_dwStreamIndexIn];
  1369. RDVStream &vstream = m_VStream[velem.m_dwStreamIndex];
  1370. LPBYTE Q = &vstream.m_pData[velem.m_dwOffset];
  1371. LPBYTE B = vstrmin.m_pSavedData + ((dwOffH + n[0]) * dwStride + (dwOffW + m[0])) * vstrmin.m_dwStride + velem.m_dwOffsetIn;
  1372. if(bDegenerate0)
  1373. {
  1374. Surf.SampleDegenerateNormal(velem.m_dwDataType, B, vstrmin.m_dwStride, dwStride * vstrmin.m_dwStride, Q);
  1375. }
  1376. else
  1377. {
  1378. Surf.SampleNormal(velem.m_dwDataType, u0, v0, B, vstrmin.m_dwStride, dwStride * vstrmin.m_dwStride, Q);
  1379. }
  1380. Q += vstream.m_dwStride;
  1381. B = vstrmin.m_pSavedData + ((dwOffH + n[1]) * dwStride + (dwOffW + m[1])) * vstrmin.m_dwStride + velem.m_dwOffsetIn;
  1382. if(bDegenerate1)
  1383. {
  1384. Surf.SampleDegenerateNormal(velem.m_dwDataType, B, vstrmin.m_dwStride, dwStride * vstrmin.m_dwStride, Q);
  1385. }
  1386. else
  1387. {
  1388. Surf.SampleNormal(velem.m_dwDataType, u1, v1, B, vstrmin.m_dwStride, dwStride * vstrmin.m_dwStride, Q);
  1389. }
  1390. Q += vstream.m_dwStride;
  1391. B = vstrmin.m_pSavedData + ((dwOffH + n[2]) * dwStride + (dwOffW + m[2])) * vstrmin.m_dwStride + velem.m_dwOffsetIn;
  1392. if(bDegenerate2)
  1393. {
  1394. Surf.SampleDegenerateNormal(velem.m_dwDataType, B, vstrmin.m_dwStride, dwStride * vstrmin.m_dwStride, Q);
  1395. }
  1396. else
  1397. {
  1398. Surf.SampleNormal(velem.m_dwDataType, u2, v2, B, vstrmin.m_dwStride, dwStride * vstrmin.m_dwStride, Q);
  1399. }
  1400. }
  1401. else // it is D3DVSD_TESSUV
  1402. {
  1403. RDVStream &vstream = m_VStream[velem.m_dwStreamIndex];
  1404. LPBYTE Q = &vstream.m_pData[velem.m_dwOffset];
  1405. ((FLOAT*)Q)[0] = (FLOAT)tu0;
  1406. ((FLOAT*)Q)[1] = (FLOAT)tv0;
  1407. Q += vstream.m_dwStride;
  1408. ((FLOAT*)Q)[0] = (FLOAT)tu1;
  1409. ((FLOAT*)Q)[1] = (FLOAT)tv1;
  1410. Q += vstream.m_dwStride;
  1411. ((FLOAT*)Q)[0] = (FLOAT)tu2;
  1412. ((FLOAT*)Q)[1] = (FLOAT)tv2;
  1413. }
  1414. }
  1415. else
  1416. {
  1417. RDVStream &vstream = m_VStream[velem.m_dwStreamIndex];
  1418. LPBYTE B = vstream.m_pSavedData + ((dwOffH + n[0]) * dwStride + (dwOffW + m[0])) * vstream.m_dwStride + velem.m_dwOffset;
  1419. LPBYTE Q = &vstream.m_pData[velem.m_dwOffset];
  1420. Surf.Sample(velem.m_dwDataType, u0, v0, B, vstream.m_dwStride, dwStride * vstream.m_dwStride, Q);
  1421. Q += vstream.m_dwStride;
  1422. B = vstream.m_pSavedData + ((dwOffH + n[1]) * dwStride + (dwOffW + m[1])) * vstream.m_dwStride + velem.m_dwOffset;
  1423. Surf.Sample(velem.m_dwDataType, u1, v1, B, vstream.m_dwStride, dwStride * vstream.m_dwStride, Q);
  1424. Q += vstream.m_dwStride;
  1425. B = vstream.m_pSavedData + ((dwOffH + n[2]) * dwStride + (dwOffW + m[2])) * vstream.m_dwStride + velem.m_dwOffset;
  1426. Surf.Sample(velem.m_dwDataType, u2, v2, B, vstream.m_dwStride, dwStride * vstream.m_dwStride, Q);
  1427. }
  1428. }
  1429. HRESULT hr;
  1430. if( m_pCurrentVShader->IsFixedFunction() )
  1431. {
  1432. //
  1433. // With declaration for Fixed Function pipeline, DX8 style
  1434. //
  1435. hr = ProcessPrimitive( D3DPT_TRIANGLELIST, 0, 3, 0, 0 );
  1436. }
  1437. else
  1438. {
  1439. //
  1440. // Pure Vertex Shader
  1441. //
  1442. hr = ProcessPrimitiveVVM( D3DPT_TRIANGLELIST, 0, 3, 0, 0 );
  1443. }
  1444. return hr;
  1445. }
  1446. //---------------------------------------------------------------------
  1447. // RefDev::DrawNPatch
  1448. //---------------------------------------------------------------------
  1449. HRESULT RefDev::DrawNPatch(const RDNPatch &Patch, DWORD dwStride,
  1450. const unsigned *m, const unsigned *n, unsigned segs)
  1451. {
  1452. for(unsigned i = 0; i < segs; ++i)
  1453. {
  1454. double v0 = double(i) / double(segs);
  1455. double v1 = v0;
  1456. double v2 = double(i + 1) / double(segs);
  1457. double v3 = v2;
  1458. for(unsigned j = 0; j < segs - i; ++j)
  1459. {
  1460. double u0 = double(j + 1) / double(segs);
  1461. double u1 = double(j) / double(segs);
  1462. double u2 = u1;
  1463. double u3 = u0;
  1464. RDVDeclaration &Decl = m_pCurrentVShader->m_Declaration;
  1465. for(unsigned e = 0; e < Decl.m_dwNumElements; ++e)
  1466. {
  1467. RDVElement &velem = Decl.m_VertexElements[e];
  1468. RDVStream &vstream = m_VStream[velem.m_dwStreamIndex];
  1469. LPBYTE Q = &vstream.m_pData[velem.m_dwOffset];
  1470. if(velem.m_dwRegister == D3DVSDE_POSITION)
  1471. {
  1472. Patch.SamplePosition(u0, v0, (FLOAT*)Q);
  1473. Q += vstream.m_dwStride;
  1474. Patch.SamplePosition(u1, v1, (FLOAT*)Q);
  1475. Q += vstream.m_dwStride;
  1476. Patch.SamplePosition(u2, v2, (FLOAT*)Q);
  1477. if(j != segs - i - 1)
  1478. {
  1479. Q += vstream.m_dwStride;
  1480. Patch.SamplePosition(u3, v3, (FLOAT*)Q);
  1481. }
  1482. }
  1483. else
  1484. if(velem.m_dwRegister == D3DVSDE_NORMAL)
  1485. {
  1486. BYTE* B[3];
  1487. B[0] = vstream.m_pSavedData + (n[0] * dwStride + m[0]) * vstream.m_dwStride + velem.m_dwOffset;
  1488. B[1] = vstream.m_pSavedData + (n[1] * dwStride + m[1]) * vstream.m_dwStride + velem.m_dwOffset;
  1489. B[2] = vstream.m_pSavedData + (n[2] * dwStride + m[2]) * vstream.m_dwStride + velem.m_dwOffset;
  1490. Patch.SampleNormal(u0, v0, B, (FLOAT*)Q);
  1491. Q += vstream.m_dwStride;
  1492. Patch.SampleNormal(u1, v1, B, (FLOAT*)Q);
  1493. Q += vstream.m_dwStride;
  1494. Patch.SampleNormal(u2, v2, B, (FLOAT*)Q);
  1495. if(j != segs - i - 1)
  1496. {
  1497. Q += vstream.m_dwStride;
  1498. Patch.SampleNormal(u3, v3, B, (FLOAT*)Q);
  1499. }
  1500. }
  1501. else
  1502. {
  1503. BYTE *B[3];
  1504. B[0] = vstream.m_pSavedData + (n[0] * dwStride + m[0]) * vstream.m_dwStride + velem.m_dwOffset;
  1505. B[1] = vstream.m_pSavedData + (n[1] * dwStride + m[1]) * vstream.m_dwStride + velem.m_dwOffset;
  1506. B[2] = vstream.m_pSavedData + (n[2] * dwStride + m[2]) * vstream.m_dwStride + velem.m_dwOffset;
  1507. Patch.Sample(velem.m_dwDataType, u0, v0, B, Q);
  1508. Q += vstream.m_dwStride;
  1509. Patch.Sample(velem.m_dwDataType, u1, v1, B, Q);
  1510. Q += vstream.m_dwStride;
  1511. Patch.Sample(velem.m_dwDataType, u2, v2, B, Q);
  1512. if(j != segs - i - 1)
  1513. {
  1514. Q += vstream.m_dwStride;
  1515. Patch.Sample(velem.m_dwDataType, u3, v3, B, Q);
  1516. }
  1517. }
  1518. }
  1519. DWORD cVerts = (j != segs - i - 1) ? 4 : 3;
  1520. HRESULT hr;
  1521. if( m_pCurrentVShader->IsFixedFunction() )
  1522. {
  1523. //
  1524. // With declaration for Fixed Function pipeline, DX8 style
  1525. //
  1526. hr = ProcessPrimitive( D3DPT_TRIANGLEFAN, 0, cVerts, 0, 0 );
  1527. }
  1528. else
  1529. {
  1530. //
  1531. // Pure Vertex Shader
  1532. //
  1533. hr = ProcessPrimitiveVVM( D3DPT_TRIANGLEFAN, 0, cVerts, 0, 0 );
  1534. }
  1535. if(FAILED(hr))
  1536. {
  1537. return hr;
  1538. }
  1539. }
  1540. }
  1541. return S_OK;
  1542. }