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.

1796 lines
53 KiB

  1. #include "pch.cpp"
  2. #pragma hdrstop
  3. #define GET_NEW_CLIP_VERTEX \
  4. &clip_vertices[clip_vertices_used++];
  5. //---------------------------------------------------------------------
  6. inline void
  7. InterpolateColor(RDClipVertex *out,
  8. RDClipVertex *p1,
  9. RDClipVertex *p2,
  10. D3DVALUE num_denom )
  11. {
  12. FLOAT r1, g1, b1, a1;
  13. FLOAT r2, g2, b2, a2;
  14. r1 = p1->m_diffuse.r;
  15. g1 = p1->m_diffuse.g;
  16. b1 = p1->m_diffuse.b;
  17. a1 = p1->m_diffuse.a;
  18. r2 = p2->m_diffuse.r;
  19. g2 = p2->m_diffuse.g;
  20. b2 = p2->m_diffuse.b;
  21. a2 = p2->m_diffuse.a;
  22. out->m_diffuse.r = (r1 + (r2 - r1) * num_denom);
  23. out->m_diffuse.g = (g1 + (g2 - g1) * num_denom);
  24. out->m_diffuse.b = (b1 + (b2 - b1) * num_denom);
  25. out->m_diffuse.a = (a1 + (a2 - a1) * num_denom);
  26. }
  27. //---------------------------------------------------------------------
  28. inline void
  29. InterpolateSpecular(RDClipVertex *out,
  30. RDClipVertex *p1,
  31. RDClipVertex *p2,
  32. D3DVALUE num_denom )
  33. {
  34. FLOAT r1, g1, b1, a1;
  35. FLOAT r2, g2, b2, a2;
  36. r1 = p1->m_specular.r;
  37. g1 = p1->m_specular.g;
  38. b1 = p1->m_specular.b;
  39. a1 = p1->m_specular.a;
  40. r2 = p2->m_specular.r;
  41. g2 = p2->m_specular.g;
  42. b2 = p2->m_specular.b;
  43. a2 = p2->m_specular.a;
  44. out->m_specular.r = (r1 + (r2 - r1) * num_denom);
  45. out->m_specular.g = (g1 + (g2 - g1) * num_denom);
  46. out->m_specular.b = (b1 + (b2 - b1) * num_denom);
  47. out->m_specular.a = (a1 + (a2 - a1) * num_denom);
  48. }
  49. //---------------------------------------------------------------------
  50. // Inline texture coordinate difference.
  51. __inline FLOAT
  52. TextureDiff(FLOAT fTb, FLOAT fTa, INT iMode)
  53. {
  54. FLOAT fDiff1 = fTb - fTa;
  55. if( iMode == 0 )
  56. {
  57. // Wrap not set, return plain difference.
  58. return fDiff1;
  59. }
  60. else
  61. {
  62. FLOAT fDiff2;
  63. // Wrap set, compute shortest distance of plain difference
  64. // and wrap difference.
  65. fDiff2 = fDiff1;
  66. if( FLOAT_LTZ(fDiff1) )
  67. {
  68. fDiff2 += g_fOne;
  69. }
  70. else if( FLOAT_GTZ(fDiff1) )
  71. {
  72. fDiff2 -= g_fOne;
  73. }
  74. if( ABSF(fDiff1) < ABSF(fDiff2) )
  75. {
  76. return fDiff1;
  77. }
  78. else
  79. {
  80. return fDiff2;
  81. }
  82. }
  83. }
  84. //---------------------------------------------------------------------
  85. inline D3DVALUE
  86. InterpolateTexture(D3DVALUE t1,
  87. D3DVALUE t2,
  88. D3DVALUE num_denom,
  89. DWORD bWrap)
  90. {
  91. if( !bWrap )
  92. {
  93. return ((t2 - t1) * num_denom + t1);
  94. }
  95. else
  96. {
  97. D3DVALUE t = (TextureDiff(t2, t1, 1) * num_denom + t1);
  98. if( t > 1.0f ) t -= 1.0f;
  99. return t;
  100. }
  101. }
  102. //////////////////////////////////////////////////////////////////////////////
  103. //
  104. // RefClipper implementation
  105. //
  106. //////////////////////////////////////////////////////////////////////////////
  107. const DWORD RefClipper::RCLIP_DIRTY_ZRANGE = (1 << 0);
  108. const DWORD RefClipper::RCLIP_DIRTY_VIEWRECT = (1 << 1);
  109. const DWORD RefClipper::RCLIP_DO_FLATSHADING = (1 << 2);
  110. const DWORD RefClipper::RCLIP_DO_WIREFRAME = (1 << 3);
  111. const DWORD RefClipper::RCLIP_DO_ADJUSTWRAP = (1 << 4);
  112. const DWORD RefClipper::RCLIP_Z_ENABLE = (1 << 5);
  113. RefClipper::RefClipper()
  114. {
  115. m_dwFlags = 0;
  116. memset( &m_Viewport, 0, sizeof( m_Viewport) );
  117. dvX = dvY = dvWidth = dvHeight = 0.0f;
  118. scaleX = scaleY = scaleZ = 0.0f;
  119. offsetX = offsetY = offsetZ = 0.0f;
  120. scaleXi = scaleYi = scaleZi = 0.0f;
  121. minX = minY = maxX = maxY = 0.0f;
  122. minXgb = minYgb = maxXgb = maxYgb = 0.0f;
  123. gb11 = gb22 = gb41 = gb42 = 0.0f;
  124. Kgbx1 = Kgby1 = Kgbx2 = Kgby2 = 0.0f;
  125. memset( clip_vbuf1, 0, sizeof(RDClipVertex*)*RD_MAX_CLIP_VERTICES );
  126. memset( clip_vbuf2, 0, sizeof(RDClipVertex*)*RD_MAX_CLIP_VERTICES );
  127. current_vbuf = 0;
  128. memset( clip_vertices, 0, sizeof(RDClipVertex)*RD_MAX_CLIP_VERTICES );
  129. m_dwInterpolate = 0;
  130. clip_vertices_used = 0;
  131. m_clipUnion = 0;
  132. m_clipIntersection = 0;
  133. // By default enable Guardband and set the extents equal
  134. // to the default RefRast parameters
  135. m_bUseGB = TRUE;
  136. minXgb = (RD_GB_LEFT);
  137. maxXgb = RD_GB_RIGHT;
  138. minYgb = (RD_GB_TOP);
  139. maxYgb = RD_GB_BOTTOM;
  140. memset( m_userClipPlanes, 0, sizeof(RDVECTOR4)*RD_MAX_USER_CLIPPLANES );
  141. #if DBG
  142. DWORD v = 0;
  143. // Guardband parameters
  144. if( GetD3DRegValue(REG_DWORD, "DisableGB", &v, 4) && v != 0 )
  145. {
  146. m_bUseGB = FALSE;
  147. }
  148. // Try to get test values for the guard band
  149. char value[80];
  150. if( GetD3DRegValue(REG_SZ, "GuardBandLeft", &value, 80) &&
  151. value[0] != 0 )
  152. sscanf(value, "%f", &minXgb);
  153. if( GetD3DRegValue(REG_SZ, "GuardBandRight", &value, 80) &&
  154. value[0] != 0 )
  155. sscanf(value, "%f", &maxXgb);
  156. if( GetD3DRegValue(REG_SZ, "GuardBandTop", &value, 80) &&
  157. value[0] != 0 )
  158. sscanf(value, "%f", &minYgb);
  159. if( GetD3DRegValue(REG_SZ, "GuardBandBottom", &value, 80) &&
  160. value[0] != 0 )
  161. sscanf(value, "%f", &maxYgb);
  162. #endif // DBG
  163. }
  164. //---------------------------------------------------------------------
  165. // RefClipper::UpdateViewData
  166. // Updates View data used by ProcessVertices[VVM]
  167. //---------------------------------------------------------------------
  168. HRESULT
  169. RefClipper::UpdateViewData()
  170. {
  171. HRESULT hr = D3D_OK;
  172. // Update viewport information
  173. if( m_dwFlags & RCLIP_DIRTY_ZRANGE )
  174. {
  175. scaleZ = m_Viewport.dvMaxZ - m_Viewport.dvMinZ;
  176. offsetZ = m_Viewport.dvMinZ;
  177. // ATTENTION: This could be a Divide by Zero here if
  178. // the dvMaxZ == dvMinZ. Fix it later.
  179. scaleZi = D3DVAL(1) / scaleZ;
  180. }
  181. if( m_dwFlags & RCLIP_DIRTY_VIEWRECT )
  182. {
  183. // Bail if we are going to cause any divide by zero exceptions.
  184. // The likely reason is that we have a bogus viewport set by
  185. // TLVertex execute buffer app.
  186. if(m_Viewport.dwWidth == 0 || m_Viewport.dwHeight == 0 )
  187. return DDERR_GENERIC;
  188. dvX = D3DVAL(m_Viewport.dwX);
  189. dvY = D3DVAL(m_Viewport.dwY);
  190. dvWidth = D3DVAL(m_Viewport.dwWidth);
  191. dvHeight = D3DVAL(m_Viewport.dwHeight);
  192. // Coefficients to compute screen coordinates from normalized window
  193. // coordinates
  194. scaleX = dvWidth;
  195. scaleY = - dvHeight;
  196. offsetX = dvX;
  197. offsetY = dvY + dvHeight;
  198. #if 0
  199. // Small offset is added to prevent generation of negative screen
  200. // coordinates (this could happen because of precision errors).
  201. // Not needed (or wanted) for devices which do guardband.
  202. offsetX += SMALL_NUMBER;
  203. offsetY += SMALL_NUMBER;
  204. #endif
  205. scaleXi = D3DVAL(1) / scaleX;
  206. scaleYi = D3DVAL(1) / scaleY;
  207. minX = dvX;
  208. maxX = dvX + dvWidth;
  209. minY = dvY;
  210. maxY = dvY + dvHeight;
  211. if( m_bUseGB )
  212. {
  213. // Because we clip by guard band window we have to use its extents
  214. D3DVALUE w = 2.0f / dvWidth;
  215. D3DVALUE h = 2.0f / dvHeight;
  216. D3DVALUE ax1 = -(minXgb - dvX) * w + 1.0f;
  217. D3DVALUE ax2 = (maxXgb - dvX) * w - 1.0f;
  218. D3DVALUE ay1 = (maxYgb - dvY) * h - 1.0f;
  219. D3DVALUE ay2 = -(minYgb - dvY) * h + 1.0f;
  220. gb11 = 2.0f / (ax1 + ax2);
  221. gb41 = gb11 * (ax1 - 1.0f) * 0.5f;
  222. gb22 = 2.0f / (ay1 + ay2);
  223. gb42 = gb22 * (ay1 - 1.0f) * 0.5f;
  224. Kgbx1 = 0.5f * (1.0f - ax1);
  225. Kgbx2 = 0.5f * (1.0f + ax2);
  226. Kgby1 = 0.5f * (1.0f - ay1);
  227. Kgby2 = 0.5f * (1.0f + ay2);
  228. }
  229. else
  230. {
  231. minXgb = minX;
  232. maxXgb = maxX;
  233. minYgb = minY;
  234. maxYgb = maxY;
  235. }
  236. }
  237. // Clear the dirty transform flags
  238. m_dwFlags &= ~(RCLIP_DIRTY_VIEWRECT | RCLIP_DIRTY_ZRANGE);
  239. return hr;
  240. }
  241. //---------------------------------------------------------------------
  242. // Make clip vertex from RDVertex
  243. //
  244. // cv - clipVertex
  245. // v - a TL vertex
  246. // qwFVF - FVF of the input TL vertex
  247. //---------------------------------------------------------------------
  248. void
  249. RefClipper::MakeClipVertexFromVertex( RDClipVertex& cv, RDVertex& v,
  250. DWORD dwClipMask )
  251. {
  252. DWORD dwClipFlag = (DWORD) v.m_clip;
  253. memcpy( &cv, &v, sizeof( RDVertex ) );
  254. // If the clip flag for this vertex is set, that means that the
  255. // transformation loop has not computed the screen coordinates for
  256. // this vertex, it has simply stored the clip coordinates for this
  257. // vertex
  258. #if 0
  259. if( v.m_clip & dwClipMask )
  260. {
  261. // This is a clipped vertex, simply no screen coordinates
  262. cv.m_pos.x = D3DVALUE(0);
  263. cv.m_pos.y = D3DVALUE(0);
  264. cv.m_pos.z = D3DVALUE(0);
  265. cv.m_rhw = D3DVALUE(0);
  266. // Since this vertex has been clipped, the transformation loop
  267. // has put in the clip coordinates instead
  268. cv.hx = v.m_pos.x;
  269. cv.hy = v.m_pos.y;
  270. cv.hz = v.m_pos.z;
  271. cv.hw = v.m_rhw;
  272. }
  273. else
  274. {
  275. // This vertex is not clipped, so its screen coordinates have been
  276. // computed
  277. // Transform the screen coordinate back to the clipping space
  278. cv.hw = 1.0f / cv.m_rhw;
  279. cv.hx = (cv.m_pos.x - offsetX) * cv.hw * scaleXi;
  280. cv.hy = (cv.m_pos.y - offsetY) * cv.hw * scaleYi;
  281. cv.hz = (cv.m_pos.z - offsetZ) * cv.hw * scaleZi;
  282. }
  283. #endif
  284. }
  285. //---------------------------------------------------------------------
  286. // RefVP::ComputeClipCodes
  287. //---------------------------------------------------------------------
  288. RDCLIPCODE
  289. RefClipper::ComputeClipCodes(RDCLIPCODE* pclipIntersection,
  290. RDCLIPCODE* pclipUnion,
  291. FLOAT x_clip, FLOAT y_clip,
  292. FLOAT z_clip, FLOAT w_clip)
  293. {
  294. D3DVALUE xx = w_clip - x_clip;
  295. D3DVALUE yy = w_clip - y_clip;
  296. D3DVALUE zz = w_clip - z_clip;
  297. // if( x < 0 ) clip |= RDCLIP_LEFTBIT;
  298. // if( x >= we ) clip |= RDCLIP_RIGHTBIT;
  299. // if( y < 0 ) clip |= RDCLIP_BOTTOMBIT;
  300. // if( y >= we ) clip |= RDCLIP_TOPBIT;
  301. // if( z < 0 ) clip |= RDCLIP_FRONTBIT;
  302. // if( z >= we ) clip |= RDCLIP_BACKBIT;
  303. RDCLIPCODE clip =
  304. ((AS_INT32(x_clip) & 0x80000000) >> (32-RDCLIP_LEFTBIT)) |
  305. ((AS_INT32(y_clip) & 0x80000000) >> (32-RDCLIP_BOTTOMBIT))|
  306. ((AS_INT32(z_clip) & 0x80000000) >> (32-RDCLIP_FRONTBIT)) |
  307. ((AS_INT32(xx) & 0x80000000) >> (32-RDCLIP_RIGHTBIT)) |
  308. ((AS_INT32(yy) & 0x80000000) >> (32-RDCLIP_TOPBIT)) |
  309. ((AS_INT32(zz) & 0x80000000) >> (32-RDCLIP_BACKBIT));
  310. RDCLIPCODE clipBit = RDCLIP_USERCLIPPLANE0;
  311. for( DWORD j=0; j<RD_MAX_USER_CLIPPLANES; j++)
  312. {
  313. if( m_xfmUserClipPlanes[j].bActive )
  314. {
  315. RDVECTOR4& plane = m_xfmUserClipPlanes[j].plane;
  316. FLOAT fComp = 0.0f;
  317. if( (x_clip*plane.x +
  318. y_clip*plane.y +
  319. z_clip*plane.z +
  320. w_clip*plane.w) < fComp )
  321. {
  322. clip |= clipBit;
  323. }
  324. }
  325. clipBit <<= 1;
  326. }
  327. if( clip == 0 )
  328. {
  329. *pclipIntersection = 0;
  330. return clip;
  331. }
  332. else
  333. {
  334. if( m_bUseGB )
  335. {
  336. // We do guardband check in the projection space, so
  337. // we transform X and Y of the vertex there
  338. D3DVALUE xnew = x_clip * gb11 +
  339. w_clip * gb41;
  340. D3DVALUE ynew = y_clip * gb22 +
  341. w_clip * gb42;
  342. D3DVALUE xx = w_clip - xnew;
  343. D3DVALUE yy = w_clip - ynew;
  344. clip |= ((AS_INT32(xnew) & 0x80000000) >> (32-RDCLIPGB_LEFTBIT)) |
  345. ((AS_INT32(ynew) & 0x80000000) >> (32-RDCLIPGB_BOTTOMBIT)) |
  346. ((AS_INT32(xx) & 0x80000000) >> (32-RDCLIPGB_RIGHTBIT)) |
  347. ((AS_INT32(yy) & 0x80000000) >> (32-RDCLIPGB_TOPBIT));
  348. }
  349. *pclipIntersection &= clip;
  350. *pclipUnion |= clip;
  351. return clip;
  352. }
  353. }
  354. //---------------------------------------------------------------------
  355. // RefVP::ComputeClipCodesTL
  356. //---------------------------------------------------------------------
  357. void
  358. RefClipper::ComputeClipCodesTL( RDVertex* pVtx )
  359. {
  360. FLOAT x, y, z;
  361. DWORD clip = 0;
  362. _ASSERT( FVF_TRANSFORMED( pVtx->m_qwFVF ),
  363. "Can compute clipcodes only for Transformed vertices." );
  364. DWORD clipZF = (m_dwFlags & RCLIP_Z_ENABLE) ? RDCLIP_FRONT : 0;
  365. DWORD clipZB = (m_dwFlags & RCLIP_Z_ENABLE) ? RDCLIP_BACK : 0;
  366. // Invert to compenstate for the sign during the
  367. // divide by w.
  368. if( pVtx->m_rhw < 0 )
  369. {
  370. x = -pVtx->m_pos.x;
  371. y = -pVtx->m_pos.y;
  372. z = -pVtx->m_pos.z;
  373. }
  374. else
  375. {
  376. x = pVtx->m_pos.x;
  377. y = pVtx->m_pos.y;
  378. z = pVtx->m_pos.z;
  379. }
  380. if( x < minX )
  381. clip |= RDCLIP_LEFT;
  382. else if( x >= maxX )
  383. clip |= RDCLIP_RIGHT;
  384. if (y < minY)
  385. clip |= RDCLIP_TOP;
  386. else if (y >= maxY)
  387. clip |= RDCLIP_BOTTOM;
  388. if (z < 0.0f)
  389. clip |= clipZF;
  390. else if (z >= 1.0f)
  391. clip |= clipZB;
  392. if( m_bUseGB )
  393. {
  394. if( x < minXgb )
  395. clip |= RDCLIPGB_LEFT;
  396. else if( x >= maxXgb )
  397. clip |= RDCLIPGB_RIGHT;
  398. if( y < minYgb )
  399. clip |= RDCLIPGB_TOP;
  400. else if( y >= maxYgb )
  401. clip |= RDCLIPGB_BOTTOM;
  402. }
  403. pVtx->m_clip = clip;
  404. // Back transform to obtain the clip-coordinates
  405. pVtx->m_clip_w = 1.0f / pVtx->m_rhw; // This is w_clip
  406. pVtx->m_clip_x = (pVtx->m_pos.x - offsetX) * pVtx->m_clip_w * scaleXi;
  407. pVtx->m_clip_y = (pVtx->m_pos.y - offsetY) * pVtx->m_clip_w * scaleYi;
  408. pVtx->m_clip_z = (pVtx->m_pos.z - offsetZ) * pVtx->m_clip_w * scaleZi;
  409. return;
  410. }
  411. //---------------------------------------------------------------------
  412. // Clipping a triangle by a plane
  413. //
  414. // Returns number of vertices in the clipped triangle
  415. //---------------------------------------------------------------------
  416. int
  417. RefClipper::ClipByPlane( RDClipVertex **inv, RDClipVertex **outv,
  418. RDVECTOR4 *plane, DWORD dwClipFlag, int count )
  419. {
  420. int i;
  421. int out_count = 0;
  422. RDClipVertex *curr, *prev;
  423. D3DVALUE curr_inside;
  424. D3DVALUE prev_inside;
  425. prev = inv[count-1];
  426. curr = *inv++;
  427. prev_inside = prev->m_clip_x*plane->x + prev->m_clip_y*plane->y +
  428. prev->m_clip_z*plane->z + prev->m_clip_w*plane->w;
  429. for (i = count; i; i--)
  430. {
  431. curr_inside = curr->m_clip_x*plane->x + curr->m_clip_y*plane->y +
  432. curr->m_clip_z*plane->z + curr->m_clip_w*plane->w;
  433. // We interpolate always from the inside vertex to the outside vertex
  434. // to reduce precision problems
  435. if( FLOAT_LTZ(prev_inside) )
  436. { // first point is outside
  437. if( FLOAT_GEZ(curr_inside) )
  438. { // second point is inside
  439. // Find intersection and insert in into the output buffer
  440. outv[out_count] = GET_NEW_CLIP_VERTEX;
  441. outv[out_count]->m_qwFVF = prev->m_qwFVF;
  442. Interpolate( outv[out_count],
  443. curr, prev,
  444. (prev->m_clip & CLIPPED_ENABLE) | dwClipFlag,
  445. curr_inside, curr_inside - prev_inside);
  446. out_count++;
  447. }
  448. } else
  449. { // first point is inside - put it to the output buffer first
  450. outv[out_count++] = prev;
  451. if( FLOAT_LTZ(curr_inside) )
  452. { // second point is outside
  453. // Find intersection and put it to the output buffer
  454. outv[out_count] = GET_NEW_CLIP_VERTEX;
  455. outv[out_count]->m_qwFVF = prev->m_qwFVF;
  456. Interpolate( outv[out_count],
  457. prev, curr,
  458. dwClipFlag,
  459. prev_inside, prev_inside - curr_inside);
  460. out_count++;
  461. }
  462. }
  463. prev = curr;
  464. curr = *inv++;
  465. prev_inside = curr_inside;
  466. }
  467. return out_count;
  468. }
  469. //-------------------------------------------------------------------------
  470. // Clips a line by a plane
  471. //
  472. // Returns 1 if the line is outside the frustum, 0 otherwise
  473. //
  474. int
  475. RefClipper::ClipLineByPlane( RDCLIPTRIANGLE *line, RDVECTOR4 *plane,
  476. DWORD dwClipBit )
  477. {
  478. D3DVALUE in1, in2;
  479. RDClipVertex outv;
  480. in1 = line->v[0]->m_clip_x * plane->x +
  481. line->v[0]->m_clip_y * plane->y +
  482. line->v[0]->m_clip_z * plane->z +
  483. line->v[0]->m_clip_w * plane->w;
  484. in2 = line->v[1]->m_clip_x * plane->x +
  485. line->v[1]->m_clip_y * plane->y +
  486. line->v[1]->m_clip_z * plane->z +
  487. line->v[1]->m_clip_w * plane->w;
  488. if( in1 < 0 )
  489. {
  490. if( in2 < 0 )
  491. return 1;
  492. Interpolate( &outv, line->v[0], line->v[1],
  493. dwClipBit, in1, in1 - in2);
  494. *line->v[0] = outv;
  495. }
  496. else
  497. {
  498. if( in2 < 0 )
  499. {
  500. Interpolate( &outv, line->v[0], line->v[1],
  501. dwClipBit, in1, in1 - in2);
  502. *line->v[1] = outv;
  503. }
  504. }
  505. return 0;
  506. }
  507. /*------------------------------------------------------------------------
  508. * Calculate the screen coords for any new vertices
  509. * introduced into the polygon.
  510. */
  511. void
  512. RefClipper::ComputeScreenCoordinates( RDClipVertex **inv, int count )
  513. {
  514. int i;
  515. for (i = 0; i < count; i++)
  516. {
  517. RDClipVertex *p;
  518. p = inv[i];
  519. //
  520. // Catch any vertices that need screen co-ordinates generated.
  521. // There are two possibilities
  522. // 1) Vertices generated during interpolation
  523. // 2) Vertices marked for clipping by the transform but
  524. // not clipped here due to the finite precision
  525. // of the floating point unit.
  526. //
  527. if( p->m_clip & ~CLIPPED_ENABLE )
  528. {
  529. D3DVALUE inv_w;
  530. inv_w = D3DVAL(1.0)/p->m_clip_w;
  531. switch ((int)p->m_clip & (CLIPPED_LEFT|CLIPPED_RIGHT))
  532. {
  533. case CLIPPED_LEFT: p->m_pos.x = minXgb; break;
  534. case CLIPPED_RIGHT: p->m_pos.x = maxXgb; break;
  535. default:
  536. p->m_pos.x = p->m_clip_x * scaleX * inv_w + offsetX;
  537. if( p->m_pos.x < minXgb )
  538. p->m_pos.x = minXgb;
  539. if( p->m_pos.x > maxXgb )
  540. p->m_pos.x = maxXgb;
  541. }
  542. switch ((int)p->m_clip & (CLIPPED_TOP|CLIPPED_BOTTOM))
  543. {
  544. case CLIPPED_BOTTOM: p->m_pos.y = maxYgb; break;
  545. case CLIPPED_TOP: p->m_pos.y = minYgb; break;
  546. default:
  547. p->m_pos.y = p->m_clip_y * scaleY * inv_w + offsetY;
  548. if( p->m_pos.y < minYgb )
  549. p->m_pos.y = minYgb;
  550. if( p->m_pos.y > maxYgb )
  551. p->m_pos.y = maxYgb;
  552. }
  553. p->m_pos.z = p->m_clip_z * scaleZ * inv_w + offsetZ;
  554. p->m_rhw = inv_w;
  555. }
  556. }
  557. }
  558. //---------------------------------------------------------------------
  559. void
  560. RefClipper::Interpolate( RDClipVertex *out, RDClipVertex *p1, RDClipVertex *p2,
  561. int code, D3DVALUE num, D3DVALUE denom )
  562. {
  563. DWORD dwInterpolate = m_dwInterpolate;
  564. D3DVALUE num_denom = num / denom;
  565. out->m_clip = (((int)p1->m_clip & (int)p2->m_clip) & ~CLIPPED_ENABLE) | code;
  566. out->m_clip_x = p1->m_clip_x + (p2->m_clip_x - p1->m_clip_x) * num_denom;
  567. out->m_clip_y = p1->m_clip_y + (p2->m_clip_y - p1->m_clip_y) * num_denom;
  568. out->m_clip_z = p1->m_clip_z + (p2->m_clip_z - p1->m_clip_z) * num_denom;
  569. out->m_clip_w = p1->m_clip_w + (p2->m_clip_w - p1->m_clip_w) * num_denom;
  570. out->m_diffuse = clip_color;
  571. out->m_specular = clip_specular;
  572. /*
  573. * Interpolate any other color model or quality dependent values.
  574. */
  575. if( dwInterpolate & RDCLIP_INTERPOLATE_COLOR )
  576. {
  577. InterpolateColor(out, p1, p2, num_denom);
  578. }
  579. if( dwInterpolate & RDCLIP_INTERPOLATE_SPECULAR )
  580. {
  581. InterpolateSpecular(out, p1, p2, num_denom);
  582. }
  583. if( dwInterpolate & RDCLIP_INTERPOLATE_TEXTURE )
  584. {
  585. UINT64 qwFVF = p1->m_qwFVF;
  586. // Assume that D3DRENDERSTATE_WRAPi are sequential
  587. DWORD numTex = FVF_TEXCOORD_NUMBER(qwFVF);
  588. for (DWORD i = 0; i < numTex; i++)
  589. {
  590. FLOAT* pTexture1 = (FLOAT *)&p1->m_tex[i];
  591. FLOAT* pTexture2 = (FLOAT *)&p2->m_tex[i];
  592. FLOAT* pTexture = (FLOAT *)&out->m_tex[i];
  593. DWORD wrapState;
  594. if( m_dwFlags & RCLIP_DO_ADJUSTWRAP )
  595. {
  596. DWORD TCI = m_pDev->GetTSS(i)[D3DTSS_TEXCOORDINDEX] & 0xffff;
  597. wrapState = m_pDev->GetRS()[D3DRENDERSTATE_WRAP0 + TCI];
  598. }
  599. else
  600. {
  601. wrapState = m_pDev->GetRS()[D3DRENDERSTATE_WRAP0 + i];
  602. }
  603. DWORD n = GetTexCoordDim(qwFVF, i);
  604. // DWORD n = (DWORD)(m_dwTexCoordSizeArray[i] >> 2);
  605. DWORD dwWrapBit = 1;
  606. for (DWORD j=0; j < n; j++)
  607. {
  608. pTexture[j] = InterpolateTexture(pTexture1[j], pTexture2[j],
  609. num_denom,
  610. wrapState & dwWrapBit);
  611. dwWrapBit <<= 1;
  612. }
  613. }
  614. }
  615. if( dwInterpolate & RDCLIP_INTERPOLATE_S )
  616. {
  617. out->m_pointsize = p1->m_pointsize +
  618. (p2->m_pointsize - p1->m_pointsize) * num_denom;
  619. }
  620. if( dwInterpolate & RDCLIP_INTERPOLATE_FOG )
  621. {
  622. out->m_fog = p1->m_fog + (p2->m_fog - p1->m_fog) * num_denom;
  623. }
  624. }
  625. //------------------------------------------------------------------------------
  626. // Functions for clipping by frustum window
  627. //
  628. #define __CLIP_NAME ClipLeft
  629. #define __CLIP_LINE_NAME ClipLineLeft
  630. #define __CLIP_FLAG CLIPPED_LEFT
  631. #define __CLIP_COORD m_clip_x
  632. #include "clip.h"
  633. #define __CLIP_NAME ClipRight
  634. #define __CLIP_LINE_NAME ClipLineRight
  635. #define __CLIP_W
  636. #define __CLIP_FLAG CLIPPED_RIGHT
  637. #define __CLIP_COORD m_clip_x
  638. #include "clip.h"
  639. #define __CLIP_NAME ClipBottom
  640. #define __CLIP_LINE_NAME ClipLineBottom
  641. #define __CLIP_FLAG CLIPPED_BOTTOM
  642. #define __CLIP_COORD m_clip_y
  643. #include "clip.h"
  644. #define __CLIP_NAME ClipTop
  645. #define __CLIP_LINE_NAME ClipLineTop
  646. #define __CLIP_W
  647. #define __CLIP_FLAG CLIPPED_TOP
  648. #define __CLIP_COORD m_clip_y
  649. #include "clip.h"
  650. #define __CLIP_NAME ClipBack
  651. #define __CLIP_LINE_NAME ClipLineBack
  652. #define __CLIP_W
  653. #define __CLIP_FLAG CLIPPED_BACK
  654. #define __CLIP_COORD m_clip_z
  655. #include "clip.h"
  656. #define __CLIP_NAME ClipFront
  657. #define __CLIP_LINE_NAME ClipLineFront
  658. #define __CLIP_FLAG CLIPPED_FRONT
  659. #define __CLIP_COORD m_clip_z
  660. #include "clip.h"
  661. //------------------------------------------------------------------------------
  662. // Functions for guard band clipping
  663. //
  664. #define __CLIP_GUARDBAND
  665. #define __CLIP_NAME ClipLeftGB
  666. #define __CLIP_LINE_NAME ClipLineLeftGB
  667. #define __CLIP_FLAG CLIPPED_LEFT
  668. #define __CLIP_COORD m_clip_x
  669. #define __CLIP_SIGN -
  670. #define __CLIP_GBCOEF Kgbx1
  671. #include "clip.h"
  672. #define __CLIP_NAME ClipRightGB
  673. #define __CLIP_LINE_NAME ClipLineRightGB
  674. #define __CLIP_FLAG CLIPPED_RIGHT
  675. #define __CLIP_COORD m_clip_x
  676. #define __CLIP_GBCOEF Kgbx2
  677. #define __CLIP_SIGN +
  678. #include "clip.h"
  679. #define __CLIP_NAME ClipBottomGB
  680. #define __CLIP_LINE_NAME ClipLineBottomGB
  681. #define __CLIP_FLAG CLIPPED_BOTTOM
  682. #define __CLIP_COORD m_clip_y
  683. #define __CLIP_SIGN -
  684. #define __CLIP_GBCOEF Kgby1
  685. #include "clip.h"
  686. #define __CLIP_NAME ClipTopGB
  687. #define __CLIP_LINE_NAME ClipLineTopGB
  688. #define __CLIP_FLAG CLIPPED_TOP
  689. #define __CLIP_COORD m_clip_y
  690. #define __CLIP_GBCOEF Kgby2
  691. #define __CLIP_SIGN +
  692. #include "clip.h"
  693. #undef __CLIP_GUARDBAND
  694. //---------------------------------------------------------------------
  695. inline DWORD
  696. ComputeClipCodeUserPlanes( RDUSERCLIPPLANE *UserPlanes, RDClipVertex *p)
  697. {
  698. DWORD clip = 0;
  699. DWORD dwClipBit = RDCLIP_USERCLIPPLANE0;
  700. for( DWORD j=0; j<RD_MAX_USER_CLIPPLANES; j++)
  701. {
  702. if( UserPlanes[j].bActive )
  703. {
  704. RDVECTOR4& plane = UserPlanes[j].plane;
  705. if( (p->m_clip_x*plane.x +
  706. p->m_clip_y*plane.y +
  707. p->m_clip_z*plane.z +
  708. p->m_clip_w*plane.w) < 0 )
  709. {
  710. clip |= dwClipBit;
  711. }
  712. }
  713. dwClipBit <<= 1;
  714. }
  715. return clip;
  716. }
  717. //---------------------------------------------------------------------
  718. inline DWORD
  719. RefClipper::ComputeClipCodeGB( RDClipVertex *p )
  720. {
  721. DWORD clip = 0;
  722. if( p->m_clip_x < p->m_clip_w * Kgbx1 )
  723. clip |= RDCLIPGB_LEFT;
  724. if( p->m_clip_x > p->m_clip_w * Kgbx2 )
  725. clip |= RDCLIPGB_RIGHT;
  726. if( p->m_clip_y < p->m_clip_w * Kgby1 )
  727. clip |= RDCLIPGB_BOTTOM;
  728. if( p->m_clip_y > p->m_clip_w * Kgby2 )
  729. clip |= RDCLIPGB_TOP;
  730. if( p->m_clip_z > p->m_clip_w )
  731. clip |= RDCLIP_BACK;
  732. clip |= ComputeClipCodeUserPlanes( m_xfmUserClipPlanes, p );
  733. p->m_clip = (p->m_clip & (CLIPPED_ENABLE | CLIPPED_FRONT)) | clip;
  734. return clip;
  735. }
  736. //---------------------------------------------------------------------
  737. inline DWORD
  738. RefClipper::ComputeClipCode( RDClipVertex *p )
  739. {
  740. DWORD clip = 0;
  741. if( FLOAT_LTZ(p->m_clip_x) )
  742. clip |= RDCLIP_LEFT;
  743. if( p->m_clip_x > p->m_clip_w )
  744. clip |= RDCLIP_RIGHT;
  745. if( FLOAT_LTZ(p->m_clip_y) )
  746. clip |= RDCLIP_BOTTOM;
  747. if( p->m_clip_y > p->m_clip_w )
  748. clip |= RDCLIP_TOP;
  749. if( p->m_clip_z > p->m_clip_w )
  750. clip |= RDCLIP_BACK;
  751. clip |= ComputeClipCodeUserPlanes( m_xfmUserClipPlanes, p );
  752. p->m_clip = (p->m_clip & (CLIPPED_ENABLE | CLIPPED_FRONT)) | clip;
  753. return clip;
  754. }
  755. //---------------------------------------------------------------------
  756. // RefDev::UpdateClipper
  757. // Updates clipping data used by ProcessVertices
  758. // BOOL bProgrammablePipeLine: If this is true, it means that the
  759. // programmable vertex machine is invoking
  760. // this method.
  761. //---------------------------------------------------------------------
  762. HRESULT
  763. RefDev::UpdateClipper()
  764. {
  765. HRESULT hr = D3D_OK;
  766. HR_RET( m_Clipper.UpdateViewData() );
  767. DWORD dwClipPlanesEnable =
  768. GetRS()[D3DRENDERSTATE_CLIPPLANEENABLE];
  769. if( !GetRS()[D3DRENDERSTATE_CLIPPING] )
  770. return S_OK;
  771. m_Clipper.m_dwFlags &= ~RefClipper::RCLIP_DO_ADJUSTWRAP;
  772. if( (m_RefVP.m_dwTLState & (RDPV_DOTEXXFORM | RDPV_DOTEXGEN)) &&
  773. m_pCurrentVShader->IsFixedFunction() )
  774. m_Clipper.m_dwFlags |= RefClipper::RCLIP_DO_ADJUSTWRAP;
  775. // Figure out which pieces need to be interpolated in new vertices.
  776. m_Clipper.m_dwInterpolate = 0;
  777. if( GetRS()[D3DRENDERSTATE_SHADEMODE] == D3DSHADE_GOURAUD )
  778. {
  779. m_Clipper.m_dwInterpolate |= RDCLIP_INTERPOLATE_COLOR;
  780. if( m_qwFVFOut & D3DFVF_SPECULAR )
  781. {
  782. m_Clipper.m_dwInterpolate |= RDCLIP_INTERPOLATE_SPECULAR;
  783. }
  784. }
  785. // if( GetRS()[D3DRENDERSTATE_FOGENABLE] )
  786. if( m_qwFVFOut & D3DFVFP_FOG )
  787. {
  788. m_Clipper.m_dwInterpolate |= RDCLIP_INTERPOLATE_FOG;
  789. }
  790. if( FVF_TEXCOORD_NUMBER(m_qwFVFOut) != 0 )
  791. {
  792. m_Clipper.m_dwInterpolate |= RDCLIP_INTERPOLATE_TEXTURE;
  793. }
  794. if( m_qwFVFOut & D3DFVF_PSIZE ) // m_primType == D3DPT_POINTLIST
  795. {
  796. m_Clipper.m_dwInterpolate |= RDCLIP_INTERPOLATE_S;
  797. }
  798. // Clear clip union and intersection flags
  799. m_Clipper.m_clipIntersection = 0;
  800. m_Clipper.m_clipUnion = 0;
  801. // The matrix to transform user clip planes depends on whether it is a
  802. // fixed function pipeline or a programmable pipeline.
  803. // Programmable pipeline: the clip-planes are transformed by the
  804. // Inverse(Mshift) to adjust for clipping in the clipper. The user is
  805. // assumed to have pre-transformed the clip-planes to the clipping
  806. // space.
  807. // Fixed function pipeline: the clip-planes are transformed to the clipping
  808. // space by the Inverse(Mview * Mproj * Mshift).
  809. RDMATRIX* pUserClipPlaneMatrix = NULL;
  810. RDMATRIX matProgPipe =
  811. {
  812. 2, 0, 0, 0,
  813. 0, 2, 0, 0,
  814. 0, 0, 1, 0,
  815. -1,-1, 0, 1
  816. };
  817. if( m_pCurrentVShader->IsFixedFunction() )
  818. {
  819. pUserClipPlaneMatrix = &(m_RefVP.m_TransformData.m_VPSInv);
  820. }
  821. else
  822. {
  823. pUserClipPlaneMatrix = &matProgPipe;
  824. }
  825. // Update the user defined clip plane data
  826. for( DWORD i=0; i<RD_MAX_USER_CLIPPLANES; i++ )
  827. {
  828. // Figure out if it is active
  829. m_Clipper.m_xfmUserClipPlanes[i].bActive =
  830. (BOOL)(dwClipPlanesEnable & 0x1);
  831. dwClipPlanesEnable >>= 1;
  832. // If it is active, transform it into eye-space using the
  833. // view transform. The clip planes are defined in the
  834. // world space.
  835. if( m_Clipper.m_xfmUserClipPlanes[i].bActive )
  836. {
  837. XformPlaneBy4x4Transposed( &(m_Clipper.m_userClipPlanes[i]),
  838. pUserClipPlaneMatrix,
  839. &(m_Clipper.m_xfmUserClipPlanes[i].plane) );
  840. }
  841. }
  842. return hr;
  843. }
  844. //----------------------------------------------------------------------------
  845. //
  846. // DrawOnePrimitive
  847. //
  848. // Draw one clipped primitive.
  849. //
  850. //----------------------------------------------------------------------------
  851. HRESULT
  852. RefClipper::DrawOnePrimitive( GArrayT<RDVertex>& VtxArray,
  853. DWORD dwStartVertex,
  854. D3DPRIMITIVETYPE PrimType,
  855. UINT cVertices )
  856. {
  857. INT i;
  858. RDVertex* pV0;
  859. RDVertex* pV1;
  860. RDVertex* pV2;
  861. HRESULT hr;
  862. DWORD dwCurrVtx = dwStartVertex;
  863. switch( PrimType )
  864. {
  865. case D3DPT_POINTLIST:
  866. for (i = 0; i < (INT)cVertices; i++)
  867. {
  868. DrawPoint(&VtxArray[i]);
  869. }
  870. break;
  871. case D3DPT_LINELIST:
  872. for (i = (INT)cVertices / 2; i > 0; i--)
  873. {
  874. pV0 = &VtxArray[dwCurrVtx++];
  875. pV1 = &VtxArray[dwCurrVtx++];
  876. DrawLine(pV0, pV1);
  877. }
  878. break;
  879. case D3DPT_LINESTRIP:
  880. {
  881. pV1 = &VtxArray[dwCurrVtx];
  882. // Disable last-pixel setting for shared verties and store prestate.
  883. m_pDev->StoreLastPixelState(TRUE);
  884. // Initial pV0.
  885. for (i = (INT)cVertices - 1; i > 1; i--)
  886. {
  887. pV0 = pV1;
  888. dwCurrVtx++;
  889. pV1 = &VtxArray[dwCurrVtx];
  890. DrawLine(pV0, pV1);
  891. }
  892. // Restore last-pixel setting.
  893. m_pDev->StoreLastPixelState(FALSE);
  894. // Draw last line with last-pixel setting from state.
  895. if( i == 1 )
  896. {
  897. dwCurrVtx++;
  898. pV0 = &VtxArray[dwCurrVtx];
  899. DrawLine(pV1, pV0);
  900. }
  901. }
  902. break;
  903. case D3DPT_TRIANGLELIST:
  904. for (i = (INT)cVertices; i > 0; i -= 3)
  905. {
  906. pV0 = &VtxArray[dwCurrVtx++];
  907. pV1 = &VtxArray[dwCurrVtx++];
  908. pV2 = &VtxArray[dwCurrVtx++];
  909. DrawTriangle(pV0, pV1, pV2);
  910. }
  911. break;
  912. case D3DPT_TRIANGLESTRIP:
  913. {
  914. // Get initial vertex values.
  915. pV1 = &VtxArray[dwCurrVtx++];
  916. pV2 = &VtxArray[dwCurrVtx++];
  917. for (i = (INT)cVertices - 2; i > 1; i -= 2)
  918. {
  919. pV0 = pV1;
  920. pV1 = pV2;
  921. pV2 = &VtxArray[dwCurrVtx++];
  922. DrawTriangle(pV0, pV1, pV2);
  923. pV0 = pV1;
  924. pV1 = pV2;
  925. pV2 = &VtxArray[dwCurrVtx++];
  926. DrawTriangle(pV0, pV2, pV1);
  927. }
  928. if( i > 0 )
  929. {
  930. pV0 = pV1;
  931. pV1 = pV2;
  932. pV2 = &VtxArray[dwCurrVtx];
  933. DrawTriangle(pV0, pV1, pV2);
  934. }
  935. }
  936. break;
  937. case D3DPT_TRIANGLEFAN:
  938. {
  939. RDCLIPCODE c0, c1, c2;
  940. pV2 = &VtxArray[dwCurrVtx++];
  941. // Preload initial pV0.
  942. pV1 = &VtxArray[dwCurrVtx++];
  943. for (i = (INT)cVertices - 2; i > 0; i--)
  944. {
  945. pV0 = pV1;
  946. pV1 = &VtxArray[dwCurrVtx++];
  947. DrawTriangle(pV0, pV1, pV2);
  948. }
  949. }
  950. break;
  951. default:
  952. DPFERR("Refrast Error: Unknown or unsupported primitive type "
  953. "requested of DrawOnePrimitive");
  954. return DDERR_INVALIDPARAMS;
  955. }
  956. return D3D_OK;
  957. }
  958. //----------------------------------------------------------------------------
  959. //
  960. // DrawOneIndexedPrimitive
  961. //
  962. // Draw one list of clipped indexed primitives.
  963. //
  964. //----------------------------------------------------------------------------
  965. HRESULT
  966. RefClipper::DrawOneIndexedPrimitive( GArrayT<RDVertex>& VtxArray,
  967. int StartVertexIndex,
  968. LPWORD pIndices,
  969. DWORD StartIndex,
  970. UINT cIndices,
  971. D3DPRIMITIVETYPE PrimType )
  972. {
  973. INT i;
  974. RDVertex* pV0;
  975. RDVertex* pV1;
  976. RDVertex* pV2;
  977. LPWORD puIndices = pIndices + StartIndex;
  978. DWORD dwCurrIndex;
  979. HRESULT hr;
  980. switch( PrimType )
  981. {
  982. case D3DPT_POINTLIST:
  983. for (i = (INT)cIndices; i > 0; i--)
  984. {
  985. pV0 = &VtxArray[StartVertexIndex + *puIndices++];
  986. DrawPoint( pV0 );
  987. }
  988. break;
  989. case D3DPT_LINELIST:
  990. for (i = (INT)cIndices / 2; i > 0; i--)
  991. {
  992. pV0 = &VtxArray[StartVertexIndex + *puIndices++];
  993. pV1 = &VtxArray[StartVertexIndex + *puIndices++];
  994. DrawLine(pV0, pV1);
  995. }
  996. break;
  997. case D3DPT_LINESTRIP:
  998. {
  999. // Disable last-pixel setting for shared verties and store prestate.
  1000. m_pDev->StoreLastPixelState(TRUE);
  1001. // Initial pV1.
  1002. pV1 = &VtxArray[StartVertexIndex + *puIndices++];
  1003. for (i = (INT)cIndices - 1; i > 1; i--)
  1004. {
  1005. pV0 = pV1;
  1006. pV1 = &VtxArray[StartVertexIndex + *puIndices++];
  1007. DrawLine(pV0, pV1);
  1008. }
  1009. // Restore last-pixel setting.
  1010. m_pDev->StoreLastPixelState(FALSE);
  1011. // Draw last line with last-pixel setting from state.
  1012. if( i == 1 )
  1013. {
  1014. pV0 = &VtxArray[StartVertexIndex + *puIndices];
  1015. DrawLine(pV1, pV0);
  1016. }
  1017. }
  1018. break;
  1019. case D3DPT_TRIANGLELIST:
  1020. for (i = (INT)cIndices; i > 0; i -= 3)
  1021. {
  1022. pV0 = &VtxArray[StartVertexIndex + *puIndices++];
  1023. pV1 = &VtxArray[StartVertexIndex + *puIndices++];
  1024. pV2 = &VtxArray[StartVertexIndex + *puIndices++];
  1025. DrawTriangle(pV0, pV1, pV2);
  1026. }
  1027. break;
  1028. case D3DPT_TRIANGLESTRIP:
  1029. {
  1030. // Get initial vertex values.
  1031. pV1 = &VtxArray[StartVertexIndex + *puIndices++];
  1032. pV2 = &VtxArray[StartVertexIndex + *puIndices++];
  1033. for (i = (INT)cIndices - 2; i > 1; i -= 2)
  1034. {
  1035. pV0 = pV1;
  1036. pV1 = pV2;
  1037. pV2 = &VtxArray[StartVertexIndex + *puIndices++];
  1038. DrawTriangle(pV0, pV1, pV2);
  1039. pV0 = pV1;
  1040. pV1 = pV2;
  1041. pV2 = &VtxArray[StartVertexIndex + *puIndices++];
  1042. DrawTriangle(pV0, pV2, pV1);
  1043. }
  1044. if( i > 0 )
  1045. {
  1046. pV0 = pV1;
  1047. pV1 = pV2;
  1048. pV2 = &VtxArray[StartVertexIndex + *puIndices++];
  1049. DrawTriangle(pV0, pV1, pV2);
  1050. }
  1051. }
  1052. break;
  1053. case D3DPT_TRIANGLEFAN:
  1054. {
  1055. pV2 = &VtxArray[StartVertexIndex + *puIndices++];
  1056. // Preload initial pV0.
  1057. pV1 = &VtxArray[StartVertexIndex + *puIndices++];
  1058. for (i = (INT)cIndices - 2; i > 0; i--)
  1059. {
  1060. pV0 = pV1;
  1061. pV1 = &VtxArray[StartVertexIndex + *puIndices++];
  1062. DrawTriangle(pV0, pV1, pV2);
  1063. }
  1064. }
  1065. break;
  1066. default:
  1067. DPFERR("Refrast Error: Unknown or unsupported primitive type "
  1068. "requested of DrawOneIndexedPrimitive");
  1069. return DDERR_INVALIDPARAMS;
  1070. }
  1071. return D3D_OK;
  1072. }
  1073. HRESULT
  1074. RefClipper::DrawOneIndexedPrimitive( GArrayT<RDVertex>& VtxArray,
  1075. int StartVertexIndex,
  1076. LPDWORD pIndices,
  1077. DWORD StartIndex,
  1078. UINT cIndices,
  1079. D3DPRIMITIVETYPE PrimType )
  1080. {
  1081. INT i;
  1082. RDVertex* pV0;
  1083. RDVertex* pV1;
  1084. RDVertex* pV2;
  1085. LPDWORD puIndices = pIndices + StartIndex;
  1086. HRESULT hr;
  1087. switch( PrimType )
  1088. {
  1089. case D3DPT_POINTLIST:
  1090. for (i = (INT)cIndices; i > 0; i--)
  1091. {
  1092. pV0 = &VtxArray[StartVertexIndex + *puIndices++];
  1093. DrawPoint(pV0);
  1094. }
  1095. break;
  1096. case D3DPT_LINELIST:
  1097. for (i = (INT)cIndices / 2; i > 0; i--)
  1098. {
  1099. pV0 = &VtxArray[StartVertexIndex + *puIndices++];
  1100. pV1 = &VtxArray[StartVertexIndex + *puIndices++];
  1101. DrawLine(pV0, pV1);
  1102. }
  1103. break;
  1104. case D3DPT_LINESTRIP:
  1105. {
  1106. // Disable last-pixel setting for shared verties and store prestate.
  1107. m_pDev->StoreLastPixelState(TRUE);
  1108. // Initial pV1.
  1109. pV1 = &VtxArray[StartVertexIndex + *puIndices++];
  1110. for (i = (INT)cIndices - 1; i > 1; i--)
  1111. {
  1112. pV0 = pV1;
  1113. pV1 = &VtxArray[StartVertexIndex + *puIndices++];
  1114. DrawLine(pV0, pV1);
  1115. }
  1116. // Restore last-pixel setting.
  1117. m_pDev->StoreLastPixelState(FALSE);
  1118. // Draw last line with last-pixel setting from state.
  1119. if( i == 1 )
  1120. {
  1121. pV0 = &VtxArray[StartVertexIndex + *puIndices];
  1122. DrawLine(pV1, pV0);
  1123. }
  1124. }
  1125. break;
  1126. case D3DPT_TRIANGLELIST:
  1127. for (i = (INT)cIndices; i > 0; i -= 3)
  1128. {
  1129. pV0 = &VtxArray[StartVertexIndex + *puIndices++];
  1130. pV1 = &VtxArray[StartVertexIndex + *puIndices++];
  1131. pV2 = &VtxArray[StartVertexIndex + *puIndices++];
  1132. DrawTriangle(pV0, pV1, pV2);
  1133. }
  1134. break;
  1135. case D3DPT_TRIANGLESTRIP:
  1136. {
  1137. // Get initial vertex values.
  1138. pV1 = &VtxArray[StartVertexIndex + *puIndices++];
  1139. pV2 = &VtxArray[StartVertexIndex + *puIndices++];
  1140. for (i = (INT)cIndices - 2; i > 1; i -= 2)
  1141. {
  1142. pV0 = pV1;
  1143. pV1 = pV2;
  1144. pV2 = &VtxArray[StartVertexIndex + *puIndices++];
  1145. DrawTriangle(pV0, pV1, pV2);
  1146. pV0 = pV1;
  1147. pV1 = pV2;
  1148. pV2 = &VtxArray[StartVertexIndex + *puIndices++];
  1149. DrawTriangle(pV0, pV2, pV1);
  1150. }
  1151. if( i > 0 )
  1152. {
  1153. pV0 = pV1;
  1154. pV1 = pV2;
  1155. pV2 = &VtxArray[StartVertexIndex + *puIndices++];
  1156. DrawTriangle(pV0, pV1, pV2);
  1157. }
  1158. }
  1159. break;
  1160. case D3DPT_TRIANGLEFAN:
  1161. {
  1162. pV2 = &VtxArray[StartVertexIndex + *puIndices++];
  1163. // Preload initial pV0.
  1164. pV1 = &VtxArray[StartVertexIndex + *puIndices++];
  1165. for (i = (INT)cIndices - 2; i > 0; i--)
  1166. {
  1167. pV0 = pV1;
  1168. pV1 = &VtxArray[StartVertexIndex + *puIndices++];
  1169. DrawTriangle(pV0, pV1, pV2);
  1170. }
  1171. }
  1172. break;
  1173. default:
  1174. DPFERR("Refrast Error: Unknown or unsupported primitive type "
  1175. "requested of DrawOneIndexedPrimitive");
  1176. return DDERR_INVALIDPARAMS;
  1177. }
  1178. return D3D_OK;
  1179. }
  1180. ///////////////////////////////////////////////////////////////////////////////
  1181. //
  1182. ///////////////////////////////////////////////////////////////////////////////
  1183. void
  1184. RefClipper::DrawTriangle( RDVertex* pV0, RDVertex* pV1, RDVertex* pV2,
  1185. WORD wFlags )
  1186. {
  1187. // If the clip-codes dont exist then compute them. This happens only
  1188. // for Transformed vertices that are directly passed in to be rasterized.
  1189. if( (pV0->m_qwFVF & D3DFVFP_CLIP) == 0 ) ComputeClipCodesTL( pV0 );
  1190. if( (pV1->m_qwFVF & D3DFVFP_CLIP) == 0 ) ComputeClipCodesTL( pV1 );
  1191. if( (pV2->m_qwFVF & D3DFVFP_CLIP) == 0 ) ComputeClipCodesTL( pV2 );
  1192. RDCLIPCODE c0 = pV0->m_clip;
  1193. RDCLIPCODE c1 = pV1->m_clip;
  1194. RDCLIPCODE c2 = pV2->m_clip;
  1195. DWORD dwInter = (c0 & c1 & c2);
  1196. DWORD dwUnion = (c0 | c1 | c2);
  1197. DWORD dwMask = (UseGuardBand()) ? RDCLIPGB_ALL : RDCLIP_ALL;
  1198. // All vertices outside the frustum or guardband,
  1199. // return without drawing
  1200. if( dwInter )
  1201. {
  1202. return;
  1203. }
  1204. // If all the vertices are in, draw and return
  1205. if( (dwUnion & dwMask) == 0 )
  1206. {
  1207. m_pDev->DrawTriangle( pV0, pV1, pV2, wFlags );
  1208. return;
  1209. }
  1210. // Do Clipping
  1211. RDCLIPTRIANGLE newtri;
  1212. RDClipVertex cv[3];
  1213. MakeClipVertexFromVertex( cv[0], *pV0, dwMask);
  1214. MakeClipVertexFromVertex( cv[1], *pV1, dwMask);
  1215. MakeClipVertexFromVertex( cv[2], *pV2, dwMask);
  1216. newtri.v[0] = &cv[0]; cv[0].next = &cv[1];
  1217. newtri.v[1] = &cv[1]; cv[1].next = &cv[2];
  1218. newtri.v[2] = &cv[2]; cv[2].next = NULL;
  1219. int count;
  1220. RDClipVertex **ver;
  1221. cv[0].m_clip |= CLIPPED_ENABLE;
  1222. cv[1].m_clip |= CLIPPED_ENABLE;
  1223. cv[2].m_clip |= CLIPPED_ENABLE;
  1224. if( count = ClipSingleTriangle( &newtri, &ver ) )
  1225. {
  1226. int i;
  1227. // Temporary Byte Array
  1228. if( FAILED( ClipBuf.Grow(count) ) ) return;
  1229. for (i = 0; i < count; i++)
  1230. {
  1231. MakeVertexFromClipVertex( ClipBuf[i], *(ver[i]) );
  1232. ClipBuf[i].SetFVF( pV0->m_qwFVF );
  1233. }
  1234. // If it is in wireframe mode, convert the clipper output to
  1235. // a line list.
  1236. if( m_dwFlags & RCLIP_DO_WIREFRAME )
  1237. {
  1238. DWORD dwEdgeFlags = 0;
  1239. for (i = 0; i < count; i++)
  1240. {
  1241. if( ver[i]->m_clip & CLIPPED_ENABLE ) dwEdgeFlags |= (1 << i);
  1242. }
  1243. m_pDev->DrawOneEdgeFlagTriangleFan( ClipBuf, count, dwEdgeFlags );
  1244. }
  1245. else
  1246. {
  1247. m_pDev->DrawOnePrimitive( ClipBuf, 0, D3DPT_TRIANGLEFAN, count );
  1248. }
  1249. }
  1250. }
  1251. void
  1252. RefClipper::DrawLine( RDVertex* pV0, RDVertex* pV1 )
  1253. {
  1254. // If the clip-codes dont exist then compute them. This happens only
  1255. // for Transformed vertices that are directly passed in to be rasterized.
  1256. if( (pV0->m_qwFVF & D3DFVFP_CLIP) == 0 ) ComputeClipCodesTL( pV0 );
  1257. if( (pV1->m_qwFVF & D3DFVFP_CLIP) == 0 ) ComputeClipCodesTL( pV1 );
  1258. RDCLIPCODE c0 = pV0->m_clip;
  1259. RDCLIPCODE c1 = pV1->m_clip;
  1260. DWORD dwInter = (c0 & c1);
  1261. DWORD dwUnion = (c0 | c1);
  1262. DWORD dwMask = (UseGuardBand()) ? RDCLIPGB_ALL : RDCLIP_ALL;
  1263. // All vertices outside the frustum or guardband,
  1264. // return without drawing
  1265. if( dwInter )
  1266. {
  1267. return;
  1268. }
  1269. // If all the vertices are in, draw and return
  1270. if( (dwUnion & dwMask) == 0 )
  1271. {
  1272. m_pDev->DrawLine( pV0, pV1 );
  1273. return;
  1274. }
  1275. RDCLIPTRIANGLE newline;
  1276. RDClipVertex cv[2];
  1277. MakeClipVertexFromVertex( cv[0], *pV0, dwMask );
  1278. MakeClipVertexFromVertex( cv[1], *pV1, dwMask );
  1279. newline.v[0] = &cv[0];
  1280. newline.v[1] = &cv[1];
  1281. if( ClipSingleLine( &newline ) )
  1282. {
  1283. // Temporary Byte Array
  1284. if( FAILED(ClipBuf.Grow( 2 )) ) return;
  1285. MakeVertexFromClipVertex( ClipBuf[0], *(newline.v[0]) );
  1286. MakeVertexFromClipVertex( ClipBuf[1], *(newline.v[1]) );
  1287. ClipBuf[0].SetFVF( pV0->m_qwFVF );
  1288. ClipBuf[1].SetFVF( pV0->m_qwFVF );
  1289. m_pDev->DrawLine( &ClipBuf[0], &ClipBuf[1] );
  1290. }
  1291. }
  1292. void
  1293. RefClipper::DrawPoint( RDVertex* pV0 )
  1294. {
  1295. // If the clip-codes dont exist then compute them. This happens only
  1296. // for Transformed vertices that are directly passed in to be rasterized.
  1297. if( (pV0->m_qwFVF & D3DFVFP_CLIP) == 0 ) ComputeClipCodesTL( pV0 );
  1298. RDCLIPCODE c0 = pV0->m_clip;
  1299. DWORD dwMask = (UseGuardBand()) ? RDCLIPGB_ALL : RDCLIP_ALL;
  1300. // if definitely out
  1301. #if 0
  1302. if( c0 & (RDCLIP_FRONT | RDCLIP_BACK |
  1303. (1<<RDCLIPGB_LEFTBIT) | (1<<RDCLIPGB_RIGHTBIT) |
  1304. (1<<RDCLIPGB_TOPBIT) | (1<<RDCLIPGB_BOTTOMBIT)) )
  1305. return;
  1306. #else
  1307. if( c0 & dwMask ) return;
  1308. #endif
  1309. // is completely in, just draw it
  1310. m_pDev->DrawPoint( pV0 );
  1311. }
  1312. ////////////////////////////////////////////////////////////////////////////
  1313. //
  1314. // Returns 0, if triangle is clipped. Number of vertices otherwise.
  1315. //
  1316. // Original vertices should not be modified inside the function
  1317. ////////////////////////////////////////////////////////////////////////////
  1318. int
  1319. RefClipper::ClipSingleTriangle( RDCLIPTRIANGLE *tri,
  1320. RDClipVertex ***clipVertexPointer )
  1321. {
  1322. int accept;
  1323. int i, j;
  1324. int count;
  1325. RDClipVertex **inv;
  1326. RDClipVertex **outv;
  1327. RDClipVertex *p;
  1328. ULONG_PTR swapv;
  1329. RDCOLOR4 diffuse1; // Original colors
  1330. RDCOLOR4 specular1;
  1331. RDCOLOR4 diffuse2;
  1332. RDCOLOR4 specular2;
  1333. DWORD dwClipBit;
  1334. DWORD dwClippedBit;
  1335. if( m_dwFlags & RCLIP_DO_FLATSHADING )
  1336. {
  1337. // It is easier to set all vertices to the same color here
  1338. RDCOLOR4 diffuse = tri->v[0]->m_diffuse;
  1339. RDCOLOR4 specular = tri->v[0]->m_specular;
  1340. //Save original colors
  1341. diffuse1 = tri->v[1]->m_diffuse;
  1342. specular1 = tri->v[1]->m_specular;
  1343. diffuse2 = tri->v[2]->m_diffuse;
  1344. specular2 = tri->v[2]->m_specular;
  1345. tri->v[1]->m_diffuse = diffuse;
  1346. tri->v[1]->m_specular = specular;
  1347. tri->v[2]->m_diffuse = diffuse;
  1348. tri->v[2]->m_specular = specular;
  1349. }
  1350. accept = (tri->v[0]->m_clip | tri->v[1]->m_clip | tri->v[2]->m_clip);
  1351. inv = tri->v;
  1352. count = 3;
  1353. outv = clip_vbuf1;
  1354. clip_color = tri->v[0]->m_diffuse;
  1355. clip_specular = tri->v[0]->m_specular;
  1356. /*
  1357. * XXX assumes sizeof(void*) == sizeof(unsigned long)
  1358. */
  1359. {
  1360. ULONG_PTR tmp1;
  1361. ULONG_PTR tmp2;
  1362. tmp1 = (ULONG_PTR)clip_vbuf1;
  1363. tmp2 = (ULONG_PTR)clip_vbuf2;
  1364. swapv = tmp1 + tmp2;
  1365. }
  1366. clip_vertices_used = 0;
  1367. #define SWAP(inv, outv) \
  1368. inv = outv; \
  1369. outv = (RDClipVertex**) (swapv - (ULONG_PTR) outv)
  1370. if( accept & RDCLIP_FRONT )
  1371. {
  1372. count = ClipFront( inv, outv, count );
  1373. if( count < 3 )
  1374. goto out_of_here;
  1375. SWAP(inv, outv);
  1376. }
  1377. if( UseGuardBand() )
  1378. {
  1379. // If there was clipping by the front plane it is better to
  1380. // compute clip code for new vertices and re-compute accept.
  1381. // Otherwise we will try to clip by sides when it is not necessary
  1382. if( accept & RDCLIP_FRONT )
  1383. {
  1384. accept = 0;
  1385. for (i = 0; i < count; i++)
  1386. {
  1387. RDClipVertex *p;
  1388. p = inv[i];
  1389. if( p->m_clip & CLIPPED_FRONT )
  1390. accept |= ComputeClipCodeGB( p );
  1391. else
  1392. accept |= p->m_clip;
  1393. }
  1394. }
  1395. if( accept & RDCLIP_BACK )
  1396. {
  1397. count = ClipBack( inv, outv, count );
  1398. if( count < 3 )
  1399. goto out_of_here;
  1400. SWAP(inv, outv);
  1401. }
  1402. if( accept & RDCLIPGB_LEFT )
  1403. {
  1404. count = ClipLeftGB( inv, outv, count );
  1405. if( count < 3 )
  1406. goto out_of_here;
  1407. SWAP(inv, outv);
  1408. }
  1409. if( accept & RDCLIPGB_RIGHT )
  1410. {
  1411. count = ClipRightGB( inv, outv, count );
  1412. if( count < 3 )
  1413. goto out_of_here;
  1414. SWAP(inv, outv);
  1415. }
  1416. if( accept & RDCLIPGB_BOTTOM )
  1417. {
  1418. count = ClipBottomGB( inv, outv, count );
  1419. if( count < 3 )
  1420. goto out_of_here;
  1421. SWAP(inv, outv);
  1422. }
  1423. if( accept & RDCLIPGB_TOP )
  1424. {
  1425. count = ClipTopGB( inv, outv, count );
  1426. if( count < 3 )
  1427. goto out_of_here;
  1428. SWAP(inv, outv);
  1429. }
  1430. }
  1431. else
  1432. {
  1433. // If there was clipping by the front plane it is better to
  1434. // compute clip code for new vertices and re-compute accept.
  1435. // Otherwise we will try to clip by sides when it is not necessary
  1436. if( accept & RDCLIP_FRONT )
  1437. {
  1438. accept = 0;
  1439. for (i = 0; i < count; i++)
  1440. {
  1441. RDClipVertex *p;
  1442. p = inv[i];
  1443. if( p->m_clip & (CLIPPED_FRONT) )
  1444. accept |= ComputeClipCode( p );
  1445. else
  1446. accept |= p->m_clip;
  1447. }
  1448. }
  1449. if( accept & RDCLIP_BACK )
  1450. {
  1451. count = ClipBack( inv, outv, count );
  1452. if( count < 3 )
  1453. goto out_of_here;
  1454. SWAP(inv, outv);
  1455. }
  1456. if( accept & RDCLIP_LEFT )
  1457. {
  1458. count = ClipLeft( inv, outv, count );
  1459. if( count < 3 )
  1460. goto out_of_here;
  1461. SWAP(inv, outv);
  1462. }
  1463. if( accept & RDCLIP_RIGHT )
  1464. {
  1465. count = ClipRight( inv, outv, count );
  1466. if( count < 3 )
  1467. goto out_of_here;
  1468. SWAP(inv, outv);
  1469. }
  1470. if( accept & RDCLIP_BOTTOM )
  1471. {
  1472. count = ClipBottom( inv, outv, count );
  1473. if( count < 3 )
  1474. goto out_of_here;
  1475. SWAP(inv, outv);
  1476. }
  1477. if( accept & RDCLIP_TOP )
  1478. {
  1479. count = ClipTop( inv, outv, count );
  1480. if( count < 3 )
  1481. goto out_of_here;
  1482. SWAP(inv, outv);
  1483. }
  1484. }
  1485. dwClipBit = RDCLIP_USERCLIPPLANE0;
  1486. dwClippedBit = CLIPPED_USERCLIPPLANE0;
  1487. // User Clip Planes
  1488. for( j=0; j<RD_MAX_USER_CLIPPLANES; j++)
  1489. {
  1490. if( accept & dwClipBit )
  1491. {
  1492. count = ClipByPlane( inv, outv, &(m_xfmUserClipPlanes[j].plane),
  1493. dwClippedBit, count);
  1494. if( count < 3 )
  1495. goto out_of_here;
  1496. SWAP(inv, outv);
  1497. }
  1498. dwClipBit <<= 1;
  1499. dwClippedBit <<= 1;
  1500. }
  1501. #undef SWAP
  1502. ComputeScreenCoordinates( inv, count );
  1503. *clipVertexPointer = inv;
  1504. current_vbuf = inv;
  1505. return count;
  1506. out_of_here:
  1507. *clipVertexPointer = NULL;
  1508. return 0;
  1509. }
  1510. //-----------------------------------------------------------------------
  1511. //
  1512. int
  1513. RefClipper::ClipSingleLine( RDCLIPTRIANGLE *line )
  1514. {
  1515. int accept;
  1516. int j;
  1517. D3DVALUE in1, in2;
  1518. DWORD dwClipBit;
  1519. DWORD dwClippedBit;
  1520. accept = (line->v[0]->m_clip | line->v[1]->m_clip);
  1521. clip_color = line->v[0]->m_diffuse;
  1522. clip_specular = line->v[0]->m_specular;
  1523. if( accept & D3DCS_FRONT )
  1524. if( ClipLineFront(line) )
  1525. goto out_of_here;
  1526. if( UseGuardBand() )
  1527. {
  1528. // If there was clipping by the front plane it is better to
  1529. // compute clip code for new vertices and re-compute accept.
  1530. // Otherwise we will try to clip by sides when it is not necessary
  1531. if( accept & D3DCS_FRONT )
  1532. {
  1533. RDClipVertex * p;
  1534. accept = 0;
  1535. p = line->v[0];
  1536. if( p->m_clip & CLIPPED_FRONT )
  1537. accept |= ComputeClipCodeGB( p );
  1538. else
  1539. accept |= p->m_clip;
  1540. p = line->v[1];
  1541. if( p->m_clip & CLIPPED_FRONT )
  1542. accept |= ComputeClipCodeGB( p );
  1543. else
  1544. accept |= p->m_clip;
  1545. }
  1546. if( accept & D3DCS_BACK )
  1547. if( ClipLineBack( line ) )
  1548. goto out_of_here;
  1549. if( accept & RDCLIPGB_LEFT )
  1550. if( ClipLineLeftGB( line ) )
  1551. goto out_of_here;
  1552. if( accept & RDCLIPGB_RIGHT )
  1553. if( ClipLineRightGB( line ) )
  1554. goto out_of_here;
  1555. if( accept & RDCLIPGB_TOP )
  1556. if( ClipLineTopGB( line ) )
  1557. goto out_of_here;
  1558. if( accept & RDCLIPGB_BOTTOM )
  1559. if( ClipLineBottomGB( line ) )
  1560. goto out_of_here;
  1561. }
  1562. else
  1563. {
  1564. // If there was clipping by the front plane it is better to
  1565. // compute clip code for new vertices and re-compute accept.
  1566. // Otherwise we will try to clip by sides when it is not necessary
  1567. if( accept & D3DCS_FRONT )
  1568. {
  1569. RDClipVertex * p;
  1570. accept = 0;
  1571. p = line->v[0];
  1572. if( p->m_clip & CLIPPED_FRONT )
  1573. accept |= ComputeClipCode( p );
  1574. else
  1575. accept |= p->m_clip;
  1576. p = line->v[1];
  1577. if( p->m_clip & CLIPPED_FRONT )
  1578. accept |= ComputeClipCode( p );
  1579. else
  1580. accept |= p->m_clip;
  1581. }
  1582. if( accept & D3DCS_BACK )
  1583. if( ClipLineBack( line ) )
  1584. goto out_of_here;
  1585. if( accept & D3DCS_LEFT )
  1586. if( ClipLineLeft( line ) )
  1587. goto out_of_here;
  1588. if( accept & D3DCS_RIGHT )
  1589. if( ClipLineRight( line ) )
  1590. goto out_of_here;
  1591. if( accept & D3DCS_TOP )
  1592. if( ClipLineTop( line ) )
  1593. goto out_of_here;
  1594. if( accept & D3DCS_BOTTOM )
  1595. if( ClipLineBottom( line ) )
  1596. goto out_of_here;
  1597. }
  1598. // User Clip Planes
  1599. dwClipBit = RDCLIP_USERCLIPPLANE0;
  1600. dwClippedBit = CLIPPED_USERCLIPPLANE0;
  1601. for( j=0; j<RD_MAX_USER_CLIPPLANES; j++)
  1602. {
  1603. if( accept & dwClipBit )
  1604. {
  1605. if( ClipLineByPlane( line, &m_xfmUserClipPlanes[j].plane,
  1606. dwClippedBit ))
  1607. goto out_of_here;
  1608. }
  1609. dwClipBit <<= 1;
  1610. dwClippedBit <<= 1;
  1611. }
  1612. ComputeScreenCoordinates( line->v, 2 );
  1613. return 1;
  1614. out_of_here:
  1615. return 0;
  1616. }