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.

417 lines
13 KiB

  1. ///////////////////////////////////////////////////////////////////////////////
  2. // Copyright (C) Microsoft Corporation, 2000.
  3. //
  4. // setup.cpp
  5. //
  6. // Direct3D Reference Device - Primitive Setup
  7. //
  8. ///////////////////////////////////////////////////////////////////////////////
  9. #include "pch.cpp"
  10. #pragma hdrstop
  11. //-----------------------------------------------------------------------------
  12. //
  13. //-----------------------------------------------------------------------------
  14. // texture coordinates for use in point sprite mode
  15. static const
  16. FLOAT g_PSTexCoord[3][4] =
  17. {
  18. { 0., 0., 0., 1. },
  19. { 1., 0., 0., 1. },
  20. { 0., 1., 0., 1. },
  21. };
  22. void
  23. RefRast::SetAttributeFunctions(
  24. const RDVertex& Vtx0,
  25. const RDVertex& Vtx1,
  26. const RDVertex& Vtx2 )
  27. {
  28. _ASSERT( Vtx0.m_qwFVF, "0x0 FVF code in setup" );
  29. // compute depth function
  30. if ( D3DZB_USEW == m_pRD->GetRS()[D3DRS_ZENABLE] )
  31. {
  32. FLOAT fW0 = 1./Vtx0.GetRHW();
  33. FLOAT fW1 = 1./Vtx1.GetRHW();
  34. FLOAT fW2 = 1./Vtx2.GetRHW();
  35. m_Attr[RDATTR_DEPTH].Setup( &fW0, &fW1, &fW2 );
  36. }
  37. else
  38. {
  39. FLOAT z0 = Vtx0.GetZ();
  40. FLOAT z1 = Vtx1.GetZ();
  41. FLOAT z2 = Vtx2.GetZ();
  42. m_Attr[RDATTR_DEPTH].Setup( &z0, &z1, &z2 );
  43. }
  44. if( m_pRD->GetRS()[D3DRS_SHADEMODE] == D3DSHADE_FLAT )
  45. {
  46. m_Attr[RDATTR_COLOR].m_bFlatShade = TRUE;
  47. m_Attr[RDATTR_SPECULAR].m_bFlatShade = TRUE;
  48. }
  49. else
  50. {
  51. m_Attr[RDATTR_COLOR].m_bFlatShade = FALSE;
  52. m_Attr[RDATTR_SPECULAR].m_bFlatShade = FALSE;
  53. }
  54. // compute color functions
  55. m_Attr[RDATTR_COLOR].Setup(
  56. Vtx0.GetDiffuse(), Vtx1.GetDiffuse(), Vtx2.GetDiffuse() );
  57. m_Attr[RDATTR_SPECULAR].Setup(
  58. Vtx0.GetSpecular(), Vtx1.GetSpecular(), Vtx2.GetSpecular() );
  59. // compute vertex fog function
  60. if ( m_pRD->GetRS()[D3DRS_FOGENABLE] &&
  61. ( m_pRD->GetRS()[D3DRS_FOGTABLEMODE] == D3DFOG_NONE ) )
  62. {
  63. FLOAT fF0 = Vtx0.GetFog();
  64. FLOAT fF1 = Vtx1.GetFog();
  65. FLOAT fF2 = Vtx2.GetFog();
  66. m_Attr[RDATTR_FOG].Setup( &fF0, &fF1, &fF2 );
  67. }
  68. for (INT32 iStage = 0; iStage < D3DHAL_TSS_MAXSTAGES; iStage++)
  69. {
  70. FLOAT TexCrd0[4];
  71. FLOAT TexCrd1[4];
  72. FLOAT TexCrd2[4];
  73. if( !(m_pRD->m_ReferencedTexCoordMask & (1<<iStage) ) )
  74. continue;
  75. if (m_pRD->m_bPointSprite)
  76. {
  77. // set texture coords to map full range
  78. m_Attr[RDATTR_TEXTURE0+iStage].Setup( &g_PSTexCoord[0][0],
  79. &g_PSTexCoord[1][0],
  80. &g_PSTexCoord[2][0]);
  81. }
  82. else
  83. {
  84. // TCI pass through
  85. UINT CoordSet;
  86. if( m_pRD->m_bOverrideTCI )
  87. {
  88. CoordSet = iStage;
  89. }
  90. else
  91. {
  92. CoordSet = (UINT)m_pRD->GetTSS(iStage)[D3DTSS_TEXCOORDINDEX] & 0x0000FFFF;
  93. }
  94. for( UINT i=0; i<4; i++)
  95. {
  96. TexCrd0[i] = Vtx0.GetTexCrd( i, CoordSet );
  97. TexCrd1[i] = Vtx1.GetTexCrd( i, CoordSet );
  98. TexCrd2[i] = Vtx2.GetTexCrd( i, CoordSet );
  99. }
  100. if( m_pRD->GetTSS(iStage)[D3DTSS_TEXTURETRANSFORMFLAGS] &
  101. D3DTTFF_PROJECTED )
  102. {
  103. // Always divide by the 4th coordinate while projecting.
  104. m_Attr[RDATTR_TEXTURE0+iStage].SetProjection(3);
  105. // For the projection, fix up the 4th coordinate
  106. // for the fixed function vertex-shaders.
  107. if( m_pRD->m_pCurrentVShader->IsFixedFunction() )
  108. {
  109. TexCrd0[3] = Vtx0.GetLastTexCrd( CoordSet );
  110. TexCrd1[3] = Vtx1.GetLastTexCrd( CoordSet );
  111. TexCrd2[3] = Vtx2.GetLastTexCrd( CoordSet );
  112. }
  113. }
  114. else
  115. {
  116. m_Attr[RDATTR_TEXTURE0+iStage].SetProjection(0);
  117. }
  118. m_Attr[RDATTR_TEXTURE0+iStage].SetWrapFlags(
  119. m_pRD->GetRS()[D3DRS_WRAP0+CoordSet] );
  120. m_Attr[RDATTR_TEXTURE0+iStage].Setup( TexCrd0, TexCrd1, TexCrd2 );
  121. }
  122. }
  123. }
  124. ///////////////////////////////////////////////////////////////////////////////
  125. //
  126. // Triangle Drawing
  127. //
  128. ///////////////////////////////////////////////////////////////////////////////
  129. //-----------------------------------------------------------------------------
  130. //
  131. // DrawTriangle - Takes three vertices and does triangle setup, setting the
  132. // primitive, attribute, and edge structures which are input to the triangle
  133. // scanner, then invokes the scan conversion.
  134. //
  135. // wFlags - Edge (and other) flags.
  136. //
  137. //-----------------------------------------------------------------------------
  138. void
  139. RefDev::DrawTriangle(
  140. RDVertex* pV0, RDVertex* pV1, RDVertex* pV2, WORD wFlags )
  141. {
  142. if (m_pDbgMon) m_pDbgMon->NextEvent(D3DDM_EVENT_PRIMITIVE);
  143. UpdateRastState();
  144. // sort to ensure consistent attribute evaluation
  145. // for identical vertices passed in different order
  146. RDVertex* pV[3];
  147. {
  148. FLOAT fD0 = *(pV0->GetPtrXYZ()+0) + *(pV0->GetPtrXYZ()+1);
  149. FLOAT fD1 = *(pV1->GetPtrXYZ()+0) + *(pV1->GetPtrXYZ()+1);
  150. FLOAT fD2 = *(pV2->GetPtrXYZ()+0) + *(pV2->GetPtrXYZ()+1);
  151. UINT MinVtx = 0;
  152. if ( (fD1 < fD0) ) MinVtx = 1;
  153. if ( (fD2 < fD0) && (fD2 < fD1) ) MinVtx = 2;
  154. switch (MinVtx)
  155. {
  156. case 0: pV[0] = pV0; pV[1] = pV1; pV[2] = pV2; m_Rast.m_iFlatVtx = 0; break;
  157. case 1: pV[0] = pV1; pV[1] = pV2; pV[2] = pV0; m_Rast.m_iFlatVtx = 2; break;
  158. case 2: pV[0] = pV2; pV[1] = pV0; pV[2] = pV1; m_Rast.m_iFlatVtx = 1; break;
  159. }
  160. }
  161. if ( m_Rast.PerTriangleSetup(
  162. pV[0]->GetPtrXYZ(), pV[1]->GetPtrXYZ(), pV[2]->GetPtrXYZ(),
  163. m_dwRenderState[D3DRS_CULLMODE],
  164. &(m_pRenderTarget->m_Clip)) )
  165. {
  166. return; // discarded due to degenerate, cull, or no viewport overlap
  167. }
  168. // process point and wireframe fill mode
  169. if ( m_dwRenderState[D3DRS_FILLMODE] == D3DFILL_POINT )
  170. {
  171. if( m_dwRenderState[D3DRS_SHADEMODE] == D3DSHADE_FLAT )
  172. {
  173. // Colors from the first vertex are used for all vertices in flat
  174. // shading mode
  175. RDCOLOR4 diffuse1 = pV1->m_diffuse;
  176. RDCOLOR4 diffuse2 = pV2->m_diffuse;
  177. RDCOLOR4 specular1 = pV1->m_specular;
  178. RDCOLOR4 specular2 = pV2->m_specular;
  179. // Colors are modified in place
  180. pV1->m_diffuse = pV0->m_diffuse;
  181. pV1->m_specular = pV0->m_specular;
  182. pV2->m_diffuse = pV0->m_diffuse;
  183. pV2->m_specular = pV0->m_specular;
  184. DrawPoint( pV0 );
  185. DrawPoint( pV1 );
  186. DrawPoint( pV2 );
  187. // Restore old color values
  188. pV1->m_diffuse = diffuse1;
  189. pV2->m_diffuse = diffuse2;
  190. pV1->m_specular = specular1;
  191. pV2->m_specular = specular2;
  192. }
  193. else
  194. {
  195. DrawPoint( pV0 );
  196. DrawPoint( pV1 );
  197. DrawPoint( pV2 );
  198. }
  199. return;
  200. }
  201. else if ( m_dwRenderState[D3DRS_FILLMODE] == D3DFILL_WIREFRAME )
  202. {
  203. // use original vertex pointers for lines so edge enables line up
  204. if ( wFlags & D3DTRIFLAG_EDGEENABLE1 ) { DrawLine( pV0, pV1, pV0 ); }
  205. if ( wFlags & D3DTRIFLAG_EDGEENABLE2 ) { DrawLine( pV1, pV2, pV0 ); }
  206. if ( wFlags & D3DTRIFLAG_EDGEENABLE3 ) { DrawLine( pV2, pV0, pV0 ); }
  207. return;
  208. }
  209. // compute edge functions
  210. m_Rast.m_Edge[0].Set( m_Rast.m_iDet > 0,
  211. m_Rast.m_iX0, m_Rast.m_iY0, m_Rast.m_iX1, m_Rast.m_iY1 );
  212. m_Rast.m_Edge[1].Set( m_Rast.m_iDet > 0,
  213. m_Rast.m_iX1, m_Rast.m_iY1, m_Rast.m_iX2, m_Rast.m_iY2 );
  214. m_Rast.m_Edge[2].Set( m_Rast.m_iDet > 0,
  215. m_Rast.m_iX2, m_Rast.m_iY2, m_Rast.m_iX0, m_Rast.m_iY0 );
  216. // compute attribute functions
  217. m_Rast.SetAttributeFunctions( *pV[0], *pV[1], *pV[2] );
  218. // not culled, so rasterize it
  219. m_Rast.DoScanCnvTri(3);
  220. }
  221. ///////////////////////////////////////////////////////////////////////////////
  222. //
  223. // Point Drawing
  224. //
  225. ///////////////////////////////////////////////////////////////////////////////
  226. void
  227. RefDev::DrawPoint(
  228. RDVertex* pvV0Public )
  229. {
  230. if (m_pDbgMon) m_pDbgMon->NextEvent(D3DDM_EVENT_PRIMITIVE);
  231. UpdateRastState();
  232. // copy pointsprite enable for duration of point rendering (only)
  233. m_bPointSprite = m_dwRenderState[D3DRS_POINTSPRITEENABLE];
  234. RDVertex V0, V1, V2;
  235. V0 = V1 = V2 = *pvV0Public;
  236. FLOAT fS = 1.0f;
  237. if (pvV0Public->m_qwFVF & D3DFVF_PSIZE)
  238. {
  239. fS = V0.GetPointSize();
  240. }
  241. else
  242. {
  243. fS = m_fRenderState[D3DRS_POINTSIZE];
  244. }
  245. fS = MAX( m_fRenderState[D3DRS_POINTSIZE_MIN], fS );
  246. fS = MIN( MIN(m_fRenderState[D3DRS_POINTSIZE_MAX], RD_MAX_POINT_SIZE), fS );
  247. // divide point size by 2 to get delta
  248. fS *= .5f;
  249. // Move points based on point size
  250. FLOAT *pXY = V0.GetPtrXYZ();
  251. FLOAT fX3 = pXY[0] + fS;
  252. FLOAT fY3 = pXY[1] + fS;
  253. pXY[0] += -fS;
  254. pXY[1] += -fS;
  255. pXY = V1.GetPtrXYZ();
  256. pXY[0] += fS;
  257. pXY[1] += -fS;
  258. pXY = V2.GetPtrXYZ();
  259. pXY[0] += -fS;
  260. pXY[1] += fS;
  261. if ( m_Rast.PerTriangleSetup(
  262. V0.GetPtrXYZ(), V1.GetPtrXYZ(), V2.GetPtrXYZ(),
  263. D3DCULL_NONE, // never cull points
  264. &(m_pRenderTarget->m_Clip)) )
  265. {
  266. m_bPointSprite = FALSE;
  267. return;
  268. }
  269. // compute edge functions
  270. INT32 iX3 = FloatToNdot4( fX3 );
  271. INT32 iY3 = FloatToNdot4( fY3 );
  272. #define DP_POINT_UL m_Rast.m_iX0, m_Rast.m_iY0 // upper left
  273. #define DP_POINT_UR m_Rast.m_iX1, m_Rast.m_iY1 // upper right
  274. #define DP_POINT_LL m_Rast.m_iX2, m_Rast.m_iY2 // lower left
  275. #define DP_POINT_LR iX3, iY3 // lower right
  276. m_Rast.m_Edge[0].Set( m_Rast.m_iDet > 0, DP_POINT_UL, DP_POINT_UR );
  277. m_Rast.m_Edge[1].Set( m_Rast.m_iDet > 0, DP_POINT_UR, DP_POINT_LR );
  278. m_Rast.m_Edge[2].Set( m_Rast.m_iDet > 0, DP_POINT_LR, DP_POINT_LL );
  279. m_Rast.m_Edge[3].Set( m_Rast.m_iDet > 0, DP_POINT_LL, DP_POINT_UL );
  280. // compute attribute functions
  281. m_Rast.SetAttributeFunctions( V0, V1, V2 );
  282. // not culled, so rasterize it
  283. m_Rast.DoScanCnvTri(4);
  284. m_bPointSprite = FALSE;
  285. return;
  286. }
  287. ///////////////////////////////////////////////////////////////////////////////
  288. //
  289. // Line Drawing
  290. //
  291. ///////////////////////////////////////////////////////////////////////////////
  292. //-----------------------------------------------------------------------------
  293. //
  294. // DrawLine - Takes two vertices and draws a line.
  295. //
  296. //-----------------------------------------------------------------------------
  297. void
  298. RefDev::DrawLine(
  299. RDVertex* pV0, RDVertex* pV1, RDVertex* pVFlat )
  300. {
  301. if (m_pDbgMon) m_pDbgMon->NextEvent(D3DDM_EVENT_PRIMITIVE);
  302. UpdateRastState();
  303. if( m_Rast.m_SampleCount > 1 )
  304. {
  305. // if multisampling draw quad
  306. D3DVALUE Perp[2];
  307. RDVertex Quad[4];
  308. Perp[0] = pV1->m_pos.y - pV0->m_pos.y;
  309. Perp[1] = -(pV1->m_pos.x - pV0->m_pos.x);
  310. float Length = SQRTF(Perp[0]*Perp[0] + Perp[1]*Perp[1]);
  311. if( 0 == Length )
  312. return;
  313. float Scale = 0.7f / Length; // 0.7 makes the line width 1.4.
  314. // (arbitrary "nice looking" choice)
  315. // Dividing by Length to normalize perp. vector.
  316. Perp[0] *= Scale;
  317. Perp[1] *= Scale;
  318. Quad[0] = *pV0;
  319. Quad[0].m_pos.x -= Perp[0];
  320. Quad[0].m_pos.y -= Perp[1];
  321. Quad[1] = *pV0;
  322. Quad[1].m_pos.x += Perp[0];
  323. Quad[1].m_pos.y += Perp[1];
  324. Quad[2] = *pV1;
  325. Quad[2].m_pos.x += Perp[0];
  326. Quad[2].m_pos.y += Perp[1];
  327. Quad[3] = *pV1;
  328. Quad[3].m_pos.x -= Perp[0];
  329. Quad[3].m_pos.y -= Perp[1];
  330. DWORD dwCull = m_dwRenderState[D3DRS_CULLMODE];
  331. DWORD dwFill = m_dwRenderState[D3DRS_FILLMODE];
  332. m_dwRenderState[D3DRS_CULLMODE] = D3DCULL_NONE;
  333. m_dwRenderState[D3DRS_FILLMODE] = D3DFILL_SOLID;
  334. DrawTriangle(&Quad[0],&Quad[1],&Quad[2],0 );
  335. DrawTriangle(&Quad[0],&Quad[2],&Quad[3],0 );
  336. m_dwRenderState[D3DRS_CULLMODE] = dwCull;
  337. m_dwRenderState[D3DRS_FILLMODE] = dwFill;
  338. return;
  339. }
  340. if ( m_Rast.PerLineSetup(
  341. pV0->GetPtrXYZ(), pV1->GetPtrXYZ(),
  342. m_dwRenderState[D3DRS_LASTPIXEL],
  343. &(m_pRenderTarget->m_Clip)) )
  344. {
  345. return; // discarded due to degenerate or no viewport overlap
  346. }
  347. // compute attribute functions
  348. m_Rast.SetAttributeFunctions( *pV0, *pV1, pVFlat ? (*pVFlat) : (*pV0) );
  349. // rasterize it
  350. m_Rast.DoScanCnvLine();
  351. }
  352. ///////////////////////////////////////////////////////////////////////////////
  353. // end