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.

1521 lines
51 KiB

  1. #include "pch.cpp"
  2. #pragma hdrstop
  3. #define GET_NEW_CLIP_VERTEX \
  4. &m_clipping.clip_vertices[m_clipping.clip_vertices_used++];
  5. //---------------------------------------------------------------------
  6. inline void
  7. InterpolateColor(RRCLIPVTX *out,
  8. RRCLIPVTX *p1,
  9. RRCLIPVTX *p2,
  10. D3DVALUE num_denom )
  11. {
  12. int r1, g1, b1, a1;
  13. int r2, g2, b2, a2;
  14. r1 = RGBA_GETRED(p1->color);
  15. g1 = RGBA_GETGREEN(p1->color);
  16. b1 = RGBA_GETBLUE(p1->color);
  17. a1 = RGBA_GETALPHA(p1->color);
  18. r2 = RGBA_GETRED(p2->color);
  19. g2 = RGBA_GETGREEN(p2->color);
  20. b2 = RGBA_GETBLUE(p2->color);
  21. a2 = RGBA_GETALPHA(p2->color);
  22. out->color = RGBA_MAKE((WORD)(r1 + (r2 - r1) * num_denom),
  23. (WORD)(g1 + (g2 - g1) * num_denom),
  24. (WORD)(b1 + (b2 - b1) * num_denom),
  25. (WORD)(a1 + (a2 - a1) * num_denom));
  26. }
  27. //---------------------------------------------------------------------
  28. inline void
  29. InterpolateSpecular(RRCLIPVTX *out,
  30. RRCLIPVTX *p1,
  31. RRCLIPVTX *p2,
  32. D3DVALUE num_denom )
  33. {
  34. int r1, g1, b1, a1;
  35. int r2, g2, b2, a2;
  36. r1 = RGBA_GETRED(p1->specular);
  37. g1 = RGBA_GETGREEN(p1->specular);
  38. b1 = RGBA_GETBLUE(p1->specular);
  39. a1 = RGBA_GETALPHA(p1->specular);
  40. r2 = RGBA_GETRED(p2->specular);
  41. g2 = RGBA_GETGREEN(p2->specular);
  42. b2 = RGBA_GETBLUE(p2->specular);
  43. a2 = RGBA_GETALPHA(p2->specular);
  44. out->specular = RGBA_MAKE((WORD)(r1 + (r2 - r1) * num_denom),
  45. (WORD)(g1 + (g2 - g1) * num_denom),
  46. (WORD)(b1 + (b2 - b1) * num_denom),
  47. (WORD)(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. // Clipping a triangle by a plane
  104. //
  105. // Returns number of vertices in the clipped triangle
  106. //
  107. int
  108. RRProcessVertices::ClipByPlane( RRCLIPVTX **inv,
  109. RRCLIPVTX **outv,
  110. RRVECTOR4 *plane,
  111. DWORD dwClipFlag,
  112. int count )
  113. {
  114. int i;
  115. int out_count = 0;
  116. RRCLIPVTX *curr, *prev;
  117. D3DVALUE curr_inside;
  118. D3DVALUE prev_inside;
  119. prev = inv[count-1];
  120. curr = *inv++;
  121. prev_inside = prev->hx*plane->x + prev->hy*plane->y +
  122. prev->hz*plane->z + prev->hw*plane->w;
  123. for (i = count; i; i--)
  124. {
  125. curr_inside = curr->hx*plane->x + curr->hy*plane->y +
  126. curr->hz*plane->z + curr->hw*plane->w;
  127. // We interpolate always from the inside vertex to the outside vertex
  128. // to reduce precision problems
  129. if (FLOAT_LTZ(prev_inside))
  130. { // first point is outside
  131. if (FLOAT_GEZ(curr_inside))
  132. { // second point is inside
  133. // Find intersection and insert in into the output buffer
  134. outv[out_count] = GET_NEW_CLIP_VERTEX;
  135. Interpolate( outv[out_count],
  136. curr, prev,
  137. (prev->clip & CLIPPED_ENABLE) | dwClipFlag,
  138. curr_inside, curr_inside - prev_inside);
  139. out_count++;
  140. }
  141. } else
  142. { // first point is inside - put it to the output buffer first
  143. outv[out_count++] = prev;
  144. if (FLOAT_LTZ(curr_inside))
  145. { // second point is outside
  146. // Find intersection and put it to the output buffer
  147. outv[out_count] = GET_NEW_CLIP_VERTEX;
  148. Interpolate( outv[out_count],
  149. prev, curr,
  150. dwClipFlag,
  151. prev_inside, prev_inside - curr_inside);
  152. out_count++;
  153. }
  154. }
  155. prev = curr;
  156. curr = *inv++;
  157. prev_inside = curr_inside;
  158. }
  159. return out_count;
  160. }
  161. //-------------------------------------------------------------------------
  162. // Clips a line by a plane
  163. //
  164. // Returns 1 if the line is outside the frustum, 0 otherwise
  165. //
  166. int
  167. RRProcessVertices::ClipLineByPlane(RRCLIPTRIANGLE *line,
  168. RRVECTOR4 *plane,
  169. DWORD dwClipBit)
  170. {
  171. D3DVALUE in1, in2;
  172. RRCLIPVTX outv;
  173. in1 = line->v[0]->hx * plane->x +
  174. line->v[0]->hy * plane->y +
  175. line->v[0]->hz * plane->z +
  176. line->v[0]->hw * plane->w;
  177. in2 = line->v[1]->hx * plane->x +
  178. line->v[1]->hy * plane->y +
  179. line->v[1]->hz * plane->z +
  180. line->v[1]->hw * plane->w;
  181. if (in1 < 0)
  182. {
  183. if (in2 < 0)
  184. return 1;
  185. Interpolate( &outv, line->v[0], line->v[1],
  186. dwClipBit, in1, in1 - in2);
  187. *line->v[0] = outv;
  188. }
  189. else
  190. {
  191. if (in2 < 0)
  192. {
  193. Interpolate( &outv, line->v[0], line->v[1],
  194. dwClipBit, in1, in1 - in2);
  195. *line->v[1] = outv;
  196. }
  197. }
  198. return 0;
  199. }
  200. /*------------------------------------------------------------------------
  201. * Calculate the screen coords for any new vertices
  202. * introduced into the polygon.
  203. */
  204. void
  205. ComputeScreenCoordinates(const RRVIEWPORTDATA& VData,
  206. RRCLIPVTX **inv, int count)
  207. {
  208. int i;
  209. for (i = 0; i < count; i++)
  210. {
  211. RRCLIPVTX *p;
  212. p = inv[i];
  213. /*
  214. * Catch any vertices that need screen co-ordinates generated.
  215. * There are two possibilities
  216. * 1) Vertices generated during interpolation
  217. * 2) Vertices marked for clipping by the transform but
  218. * not clipped here due to the finite precision
  219. * of the floating point unit.
  220. */
  221. if (p->clip & ~CLIPPED_ENABLE)
  222. {
  223. D3DVALUE w;
  224. w = D3DVAL(1.0)/p->hw;
  225. switch ((int)p->clip & (CLIPPED_LEFT|CLIPPED_RIGHT))
  226. {
  227. case CLIPPED_LEFT: p->sx = VData.minXgb; break;
  228. case CLIPPED_RIGHT: p->sx = VData.maxXgb; break;
  229. default:
  230. p->sx = p->hx * VData.scaleX * w + VData.offsetX;
  231. if (p->sx < VData.minXgb)
  232. p->sx = VData.minXgb;
  233. if (p->sx > VData.maxXgb)
  234. p->sx = VData.maxXgb;
  235. }
  236. switch ((int)p->clip & (CLIPPED_TOP|CLIPPED_BOTTOM))
  237. {
  238. case CLIPPED_BOTTOM: p->sy = VData.maxYgb; break;
  239. case CLIPPED_TOP: p->sy = VData.minYgb; break;
  240. default:
  241. p->sy = p->hy * VData.scaleY * w + VData.offsetY;
  242. if (p->sy < VData.minYgb)
  243. p->sy = VData.minYgb;
  244. if (p->sy > VData.maxYgb)
  245. p->sy = VData.maxYgb;
  246. }
  247. p->sz = p->hz * VData.scaleZ * w + VData.offsetZ;
  248. p->rhw = w;
  249. }
  250. }
  251. }
  252. //---------------------------------------------------------------------
  253. void
  254. RRProcessVertices::Interpolate(RRCLIPVTX *out,
  255. RRCLIPVTX *p1,
  256. RRCLIPVTX *p2,
  257. int code,
  258. D3DVALUE num,
  259. D3DVALUE denom)
  260. {
  261. DWORD dwInterpolate = m_clipping.dwInterpolate;
  262. D3DVALUE num_denom = num / denom;
  263. out->clip = (((int)p1->clip & (int)p2->clip) & ~CLIPPED_ENABLE) | code;
  264. out->hx = p1->hx + (p2->hx - p1->hx) * num_denom;
  265. out->hy = p1->hy + (p2->hy - p1->hy) * num_denom;
  266. out->hz = p1->hz + (p2->hz - p1->hz) * num_denom;
  267. out->hw = p1->hw + (p2->hw - p1->hw) * num_denom;
  268. out->color = m_clipping.clip_color;
  269. out->specular = m_clipping.clip_specular;
  270. /*
  271. * Interpolate any other color model or quality dependent values.
  272. */
  273. if (dwInterpolate & RRCLIP_INTERPOLATE_COLOR)
  274. {
  275. InterpolateColor(out, p1, p2, num_denom);
  276. }
  277. if (dwInterpolate & RRCLIP_INTERPOLATE_SPECULAR)
  278. {
  279. InterpolateSpecular(out, p1, p2, num_denom);
  280. }
  281. if (dwInterpolate & RRCLIP_INTERPOLATE_TEXTURE)
  282. {
  283. // Assume that D3DRENDERSTATE_WRAPi are sequential
  284. D3DVALUE *pTexture1 = p1->tex;
  285. D3DVALUE *pTexture2 = p2->tex;
  286. D3DVALUE *pTexture = out->tex;
  287. for (DWORD i = 0; i < m_dwNumTexCoords; i++)
  288. {
  289. DWORD wrapState = ((ReferenceRasterizer *)this)->GetRenderState()[D3DRENDERSTATE_WRAP0 + i];
  290. DWORD n = (DWORD)(m_dwTexCoordSize[i] >> 2);
  291. DWORD dwWrapBit = 1;
  292. for (DWORD j=0; j < n; j++)
  293. {
  294. *pTexture = InterpolateTexture(*pTexture1, *pTexture2,
  295. num_denom,
  296. wrapState & dwWrapBit);
  297. dwWrapBit <<= 1;
  298. pTexture ++;
  299. pTexture1++;
  300. pTexture2++;
  301. }
  302. }
  303. }
  304. if (dwInterpolate & RRCLIP_INTERPOLATE_S)
  305. {
  306. out->s = p1->s + (p2->s - p1->s) * num_denom;
  307. }
  308. if (dwInterpolate & RRCLIP_INTERPOLATE_EYENORMAL)
  309. {
  310. out->eyenx = p1->eyenx + (p2->eyenx - p1->eyenx) * num_denom;
  311. out->eyeny = p1->eyeny + (p2->eyeny - p1->eyeny) * num_denom;
  312. out->eyenz = p1->eyenz + (p2->eyenz - p1->eyenz) * num_denom;
  313. }
  314. if (dwInterpolate & RRCLIP_INTERPOLATE_EYEXYZ)
  315. {
  316. out->eyex = p1->eyex + (p2->eyex - p1->eyex) * num_denom;
  317. out->eyey = p1->eyey + (p2->eyey - p1->eyey) * num_denom;
  318. out->eyez = p1->eyez + (p2->eyez - p1->eyez) * num_denom;
  319. }
  320. }
  321. //------------------------------------------------------------------------------
  322. // Functions for clipping by frustum window
  323. //
  324. #define __CLIP_NAME ClipLeft
  325. #define __CLIP_LINE_NAME ClipLineLeft
  326. #define __CLIP_FLAG CLIPPED_LEFT
  327. #define __CLIP_COORD hx
  328. #include "clip.h"
  329. #define __CLIP_NAME ClipRight
  330. #define __CLIP_LINE_NAME ClipLineRight
  331. #define __CLIP_W
  332. #define __CLIP_FLAG CLIPPED_RIGHT
  333. #define __CLIP_COORD hx
  334. #include "clip.h"
  335. #define __CLIP_NAME ClipBottom
  336. #define __CLIP_LINE_NAME ClipLineBottom
  337. #define __CLIP_FLAG CLIPPED_BOTTOM
  338. #define __CLIP_COORD hy
  339. #include "clip.h"
  340. #define __CLIP_NAME ClipTop
  341. #define __CLIP_LINE_NAME ClipLineTop
  342. #define __CLIP_W
  343. #define __CLIP_FLAG CLIPPED_TOP
  344. #define __CLIP_COORD hy
  345. #include "clip.h"
  346. #define __CLIP_NAME ClipBack
  347. #define __CLIP_LINE_NAME ClipLineBack
  348. #define __CLIP_W
  349. #define __CLIP_FLAG CLIPPED_BACK
  350. #define __CLIP_COORD hz
  351. #include "clip.h"
  352. #define __CLIP_NAME ClipFront
  353. #define __CLIP_LINE_NAME ClipLineFront
  354. #define __CLIP_FLAG CLIPPED_FRONT
  355. #define __CLIP_COORD hz
  356. #include "clip.h"
  357. //------------------------------------------------------------------------------
  358. // Functions for guard band clipping
  359. //
  360. #define __CLIP_GUARDBAND
  361. #define __CLIP_NAME ClipLeftGB
  362. #define __CLIP_LINE_NAME ClipLineLeftGB
  363. #define __CLIP_FLAG CLIPPED_LEFT
  364. #define __CLIP_COORD hx
  365. #define __CLIP_SIGN -
  366. #define __CLIP_GBCOEF Kgbx1
  367. #include "clip.h"
  368. #define __CLIP_NAME ClipRightGB
  369. #define __CLIP_LINE_NAME ClipLineRightGB
  370. #define __CLIP_FLAG CLIPPED_RIGHT
  371. #define __CLIP_COORD hx
  372. #define __CLIP_GBCOEF Kgbx2
  373. #define __CLIP_SIGN +
  374. #include "clip.h"
  375. #define __CLIP_NAME ClipBottomGB
  376. #define __CLIP_LINE_NAME ClipLineBottomGB
  377. #define __CLIP_FLAG CLIPPED_BOTTOM
  378. #define __CLIP_COORD hy
  379. #define __CLIP_SIGN -
  380. #define __CLIP_GBCOEF Kgby1
  381. #include "clip.h"
  382. #define __CLIP_NAME ClipTopGB
  383. #define __CLIP_LINE_NAME ClipLineTopGB
  384. #define __CLIP_FLAG CLIPPED_TOP
  385. #define __CLIP_COORD hy
  386. #define __CLIP_GBCOEF Kgby2
  387. #define __CLIP_SIGN +
  388. #include "clip.h"
  389. #undef __CLIP_GUARDBAND
  390. //---------------------------------------------------------------------
  391. inline DWORD ComputeClipCodeUserPlanes( RRUSERCLIPPLANE *UserPlanes,
  392. RRCLIPVTX *p)
  393. {
  394. DWORD clip = 0;
  395. DWORD dwClipBit = RRCLIP_USERCLIPPLANE0;
  396. for( DWORD j=0; j<RRMAX_USER_CLIPPLANES; j++)
  397. {
  398. if( UserPlanes[j].bActive )
  399. {
  400. RRVECTOR4& plane = UserPlanes[j].plane;
  401. if( (p->hx*plane.x +
  402. p->hy*plane.y +
  403. p->hz*plane.z +
  404. p->hw*plane.w) < 0 )
  405. {
  406. clip |= dwClipBit;
  407. }
  408. }
  409. dwClipBit <<= 1;
  410. }
  411. return clip;
  412. }
  413. //---------------------------------------------------------------------
  414. inline DWORD ComputeClipCodeGB(const RRVIEWPORTDATA& VData,
  415. RRUSERCLIPPLANE *UserPlanes, RRCLIPVTX *p)
  416. {
  417. DWORD clip = 0;
  418. if (p->hx < p->hw * VData.Kgbx1)
  419. clip |= RRCLIPGB_LEFT;
  420. if (p->hx > p->hw * VData.Kgbx2)
  421. clip |= RRCLIPGB_RIGHT;
  422. if (p->hy < p->hw * VData.Kgby1)
  423. clip |= RRCLIPGB_BOTTOM;
  424. if (p->hy > p->hw * VData.Kgby2)
  425. clip |= RRCLIPGB_TOP;
  426. if (p->hz > p->hw)
  427. clip |= RRCLIP_BACK;
  428. clip |= ComputeClipCodeUserPlanes(UserPlanes, p);
  429. p->clip = (p->clip & (CLIPPED_ENABLE | CLIPPED_FRONT)) | clip;
  430. return clip;
  431. }
  432. //---------------------------------------------------------------------
  433. inline DWORD ComputeClipCode(RRUSERCLIPPLANE *UserPlanes, RRCLIPVTX *p)
  434. {
  435. DWORD clip = 0;
  436. if (FLOAT_LTZ(p->hx))
  437. clip |= RRCLIP_LEFT;
  438. if (p->hx > p->hw)
  439. clip |= RRCLIP_RIGHT;
  440. if (FLOAT_LTZ(p->hy))
  441. clip |= RRCLIP_BOTTOM;
  442. if (p->hy > p->hw)
  443. clip |= RRCLIP_TOP;
  444. if (p->hz > p->hw)
  445. clip |= RRCLIP_BACK;
  446. clip |= ComputeClipCodeUserPlanes(UserPlanes, p);
  447. p->clip = (p->clip & (CLIPPED_ENABLE | CLIPPED_FRONT)) | clip;
  448. return clip;
  449. }
  450. //---------------------------------------------------------------------
  451. // RRProcessVertices::UpdateClippingData
  452. // Updates clipping data used by ProcessVertices
  453. //---------------------------------------------------------------------
  454. HRESULT
  455. RRProcessVertices::UpdateClippingData( DWORD dwClipPlanesEnable )
  456. {
  457. HRESULT hr = D3D_OK;
  458. // Update the user defined clip plane data
  459. for( DWORD i=0; i<RRMAX_USER_CLIPPLANES; i++ )
  460. {
  461. // Figure out if it is active
  462. m_xfmUserClipPlanes[i].bActive = (BOOL)(dwClipPlanesEnable & 0x1);
  463. dwClipPlanesEnable >>= 1;
  464. // If it is active, transform it into eye-space using the
  465. // view transform. The clip planes are defined in the
  466. // world space.
  467. if( m_xfmUserClipPlanes[i].bActive )
  468. {
  469. XformPlaneBy4x4Transposed( &m_userClipPlanes[i],
  470. &m_TransformData.m_VPSInv,
  471. &m_xfmUserClipPlanes[i].plane );
  472. }
  473. }
  474. m_dwDirtyFlags &= ~(RRPV_DIRTY_CLIPPLANES);
  475. return hr;
  476. }
  477. //----------------------------------------------------------------------------
  478. //
  479. // DrawOneClippedPrimitive
  480. //
  481. // Draw one clipped primitive.
  482. //
  483. //----------------------------------------------------------------------------
  484. HRESULT
  485. RRProcessVertices::DrawOneClippedPrimitive()
  486. {
  487. INT i;
  488. PUINT8 pV0, pV1, pV2;
  489. HRESULT hr;
  490. PUINT8 pVtx = (PUINT8) m_pvOut;
  491. RRCLIPCODE *pClip = m_pClipBuf;
  492. RRCLIPCODE c0, c1, c2;
  493. switch (m_primType)
  494. {
  495. case D3DPT_POINTLIST:
  496. for (i = (INT)m_dwNumVertices; i > 0; i--)
  497. {
  498. c0 = *pClip++;
  499. ((ReferenceRasterizer *)this)->DrawClippedPoint(pVtx, c0);
  500. pVtx += m_dwOutputVtxSize;
  501. }
  502. break;
  503. case D3DPT_LINELIST:
  504. for (i = (INT)m_dwNumVertices / 2; i > 0; i--)
  505. {
  506. pV0 = pVtx;
  507. pVtx += m_dwOutputVtxSize;
  508. c0 = *pClip++;
  509. pV1 = pVtx;
  510. pVtx += m_dwOutputVtxSize;
  511. c1 = *pClip++;
  512. ((ReferenceRasterizer *)this)->DrawClippedLine(pV0, c0,
  513. pV1, c1);
  514. }
  515. break;
  516. case D3DPT_LINESTRIP:
  517. {
  518. pV1 = pVtx;
  519. c1 = *pClip;
  520. // Disable last-pixel setting for shared verties and store prestate.
  521. ((ReferenceRasterizer *)this)->StoreLastPixelState(TRUE);
  522. // Initial pV0.
  523. for (i = (INT)m_dwNumVertices - 1; i > 1; i--)
  524. {
  525. pV0 = pV1;
  526. c0 = c1;
  527. pVtx += m_dwOutputVtxSize;
  528. pV1 = pVtx;
  529. c1 = *(++pClip);
  530. ((ReferenceRasterizer *)this)->DrawClippedLine(pV0, c0,
  531. pV1, c1);
  532. }
  533. // Restore last-pixel setting.
  534. ((ReferenceRasterizer *)this)->StoreLastPixelState(FALSE);
  535. // Draw last line with last-pixel setting from state.
  536. if (i == 1)
  537. {
  538. pV0 = pVtx + m_dwOutputVtxSize;
  539. c0 = *(++pClip);
  540. ((ReferenceRasterizer *)this)->DrawClippedLine(pV1, c1,
  541. pV0, c0);
  542. }
  543. }
  544. break;
  545. case D3DPT_TRIANGLELIST:
  546. for (i = (INT)m_dwNumVertices; i > 0; i -= 3)
  547. {
  548. pV0 = pVtx;
  549. pVtx += m_dwOutputVtxSize;
  550. c0 = *pClip++;
  551. pV1 = pVtx;
  552. pVtx += m_dwOutputVtxSize;
  553. c1 = *pClip++;
  554. pV2 = pVtx;
  555. pVtx += m_dwOutputVtxSize;
  556. c2 = *pClip++;
  557. ((ReferenceRasterizer *)this)->DrawClippedTriangle(pV0, c0,
  558. pV1, c1,
  559. pV2, c2);
  560. }
  561. break;
  562. case D3DPT_TRIANGLESTRIP:
  563. {
  564. // Get initial vertex values.
  565. pV1 = pVtx;
  566. pVtx += m_dwOutputVtxSize;
  567. c1 = *pClip++;
  568. pV2 = pVtx;
  569. pVtx += m_dwOutputVtxSize;
  570. c2 = *pClip++;
  571. for (i = (INT)m_dwNumVertices - 2; i > 1; i -= 2)
  572. {
  573. pV0 = pV1; c0 = c1;
  574. pV1 = pV2; c1 = c2;
  575. pV2 = pVtx;
  576. pVtx += m_dwOutputVtxSize;
  577. c2 = *pClip++;
  578. ((ReferenceRasterizer *)this)->DrawClippedTriangle(pV0, c0,
  579. pV1, c1,
  580. pV2, c2);
  581. pV0 = pV1; c0 = c1;
  582. pV1 = pV2; c1 = c2;
  583. pV2 = pVtx;
  584. pVtx += m_dwOutputVtxSize;
  585. c2 = *pClip++;
  586. ((ReferenceRasterizer *)this)->DrawClippedTriangle(pV0, c0,
  587. pV2, c2,
  588. pV1, c1);
  589. }
  590. if (i > 0)
  591. {
  592. pV0 = pV1; c0 = c1;
  593. pV1 = pV2; c1 = c2;
  594. pV2 = pVtx; c2 = *pClip;
  595. ((ReferenceRasterizer *)this)->DrawClippedTriangle(pV0, c0,
  596. pV1, c1,
  597. pV2, c2);
  598. }
  599. }
  600. break;
  601. case D3DPT_TRIANGLEFAN:
  602. {
  603. RRCLIPCODE c0, c1, c2;
  604. pV2 = pVtx;
  605. pVtx += m_dwOutputVtxSize;
  606. c2 = *pClip++;
  607. // Preload initial pV0.
  608. pV1 = pVtx;
  609. pVtx += m_dwOutputVtxSize;
  610. c1 = *pClip++;
  611. for (i = (INT)m_dwNumVertices - 2; i > 0; i--)
  612. {
  613. pV0 = pV1; c0 = c1;
  614. pV1 = pVtx;
  615. pVtx += m_dwOutputVtxSize;
  616. c1 = *pClip++;
  617. ((ReferenceRasterizer *)this)->DrawClippedTriangle(pV0, c0,
  618. pV1, c1,
  619. pV2, c2);
  620. }
  621. }
  622. break;
  623. default:
  624. DPFM(0, DRV, ("Refrast Error: Unknown or unsupported primitive type "
  625. "requested of DrawOnePrimitive"));
  626. return DDERR_INVALIDPARAMS;
  627. }
  628. return D3D_OK;
  629. }
  630. //----------------------------------------------------------------------------
  631. //
  632. // DrawOneClippedIndexedPrimitive
  633. //
  634. // Draw one list of clipped indexed primitives.
  635. //
  636. //----------------------------------------------------------------------------
  637. HRESULT
  638. RRProcessVertices::DrawOneClippedIndexedPrimitive()
  639. {
  640. INT i;
  641. PUINT8 pVtx = (PUINT8) m_pvOut;
  642. LPWORD puIndices = m_pIndices;
  643. PUINT8 pV0, pV1, pV2;
  644. RRCLIPCODE *pClip = m_pClipBuf;
  645. RRCLIPCODE c0, c1, c2;
  646. HRESULT hr;
  647. switch(m_primType)
  648. {
  649. case D3DPT_POINTLIST:
  650. for (i = (INT)m_dwNumIndices; i > 0; i--)
  651. {
  652. c0 = pClip[*puIndices];
  653. pV0 = pVtx + m_dwOutputVtxSize * (*puIndices++);
  654. ((ReferenceRasterizer *)this)->DrawClippedPoint(pV0, c0);
  655. }
  656. break;
  657. case D3DPT_LINELIST:
  658. for (i = (INT)m_dwNumIndices / 2; i > 0; i--)
  659. {
  660. c0 = pClip[*puIndices];
  661. pV0 = pVtx + m_dwOutputVtxSize * (*puIndices++);
  662. c1 = pClip[*puIndices];
  663. pV1 = pVtx + m_dwOutputVtxSize * (*puIndices++);
  664. ((ReferenceRasterizer *)this)->DrawClippedLine(pV0, c0,
  665. pV1, c1);
  666. }
  667. break;
  668. case D3DPT_LINESTRIP:
  669. {
  670. // Disable last-pixel setting for shared verties and store prestate.
  671. ((ReferenceRasterizer *)this)->StoreLastPixelState(TRUE);
  672. // Initial pV1.
  673. c1 = pClip[*puIndices];
  674. pV1 = pVtx + m_dwOutputVtxSize * (*puIndices++);
  675. for (i = (INT)m_dwNumIndices - 1; i > 1; i--)
  676. {
  677. c0 = c1;
  678. pV0 = pV1;
  679. c1 = pClip[*puIndices];
  680. pV1 = pVtx + m_dwOutputVtxSize * (*puIndices++);
  681. ((ReferenceRasterizer *)this)->DrawClippedLine(pV0, c0,
  682. pV1, c1);
  683. }
  684. // Restore last-pixel setting.
  685. ((ReferenceRasterizer *)this)->StoreLastPixelState(FALSE);
  686. // Draw last line with last-pixel setting from state.
  687. if (i == 1)
  688. {
  689. c0 = pClip[*puIndices];
  690. pV0 = pVtx + m_dwOutputVtxSize * (*puIndices);
  691. ((ReferenceRasterizer *)this)->DrawClippedLine(pV1, c1,
  692. pV0, c0);
  693. }
  694. }
  695. break;
  696. case D3DPT_TRIANGLELIST:
  697. for (i = (INT)m_dwNumIndices; i > 0; i -= 3)
  698. {
  699. c0 = pClip[*puIndices];
  700. pV0 = pVtx + m_dwOutputVtxSize * (*puIndices++);
  701. c1 = pClip[*puIndices];
  702. pV1 = pVtx + m_dwOutputVtxSize * (*puIndices++);
  703. c2 = pClip[*puIndices];
  704. pV2 = pVtx + m_dwOutputVtxSize * (*puIndices++);
  705. ((ReferenceRasterizer *)this)->DrawClippedTriangle(pV0, c0,
  706. pV1, c1,
  707. pV2, c2);
  708. }
  709. break;
  710. case D3DPT_TRIANGLESTRIP:
  711. {
  712. // Get initial vertex values.
  713. c1 = pClip[*puIndices];
  714. pV1 = pVtx + m_dwOutputVtxSize * (*puIndices++);
  715. c2 = pClip[*puIndices];
  716. pV2 = pVtx + m_dwOutputVtxSize * (*puIndices++);
  717. for (i = (INT)m_dwNumIndices - 2; i > 1; i -= 2)
  718. {
  719. c0 = c1; pV0 = pV1;
  720. c1 = c2; pV1 = pV2;
  721. c2 = pClip[*puIndices];
  722. pV2 = pVtx + m_dwOutputVtxSize * (*puIndices++);
  723. ((ReferenceRasterizer *)this)->DrawClippedTriangle(pV0, c0,
  724. pV1, c1,
  725. pV2, c2);
  726. c0 = c1; pV0 = pV1;
  727. c1 = c2; pV1 = pV2;
  728. c2 = pClip[*puIndices];
  729. pV2 = pVtx + m_dwOutputVtxSize * (*puIndices++);
  730. ((ReferenceRasterizer *)this)->DrawClippedTriangle(pV0, c0,
  731. pV2, c2,
  732. pV1, c1);
  733. }
  734. if (i > 0)
  735. {
  736. c0 = c1; pV0 = pV1;
  737. c1 = c2; pV1 = pV2;
  738. c2 = pClip[*puIndices];
  739. pV2 = pVtx + m_dwOutputVtxSize * (*puIndices++);
  740. ((ReferenceRasterizer *)this)->DrawClippedTriangle(pV0, c0,
  741. pV1, c1,
  742. pV2, c2);
  743. }
  744. }
  745. break;
  746. case D3DPT_TRIANGLEFAN:
  747. {
  748. c2 = pClip[*puIndices];
  749. pV2 = pVtx + m_dwOutputVtxSize * (*puIndices++);
  750. // Preload initial pV0.
  751. c1 = pClip[*puIndices];
  752. pV1 = pVtx + m_dwOutputVtxSize * (*puIndices++);
  753. for (i = (INT)m_dwNumIndices - 2; i > 0; i--)
  754. {
  755. c0 = c1; pV0 = pV1;
  756. c1 = pClip[*puIndices];
  757. pV1 = pVtx + m_dwOutputVtxSize * (*puIndices++);
  758. ((ReferenceRasterizer *)this)->DrawClippedTriangle(pV0, c0,
  759. pV1, c1,
  760. pV2, c2);
  761. }
  762. }
  763. break;
  764. default:
  765. DPFM(0, DRV, ("Refrast Error: Unknown or unsupported primitive type "
  766. "requested of DrawOneClippedIndexedPrimitive"));
  767. return DDERR_INVALIDPARAMS;
  768. }
  769. return D3D_OK;
  770. }
  771. ///////////////////////////////////////////////////////////////////////////////
  772. //
  773. ///////////////////////////////////////////////////////////////////////////////
  774. void
  775. ReferenceRasterizer::DrawClippedTriangle( void* pvV0, RRCLIPCODE c0,
  776. void* pvV1, RRCLIPCODE c1,
  777. void* pvV2, RRCLIPCODE c2,
  778. WORD wFlags )
  779. {
  780. DWORD dwInter = (c0 & c1 & c2);
  781. DWORD dwUnion = (c0 | c1 | c2);
  782. DWORD dwMask = (m_dwTLState & RRPV_GUARDBAND) ? RRCLIPGB_ALL : RRCLIP_ALL;
  783. // All vertices outside the frustum or guardband,
  784. // return without drawing
  785. if (dwInter)
  786. {
  787. return;
  788. }
  789. // If all the vertices are in, draw and return
  790. if ((dwUnion & dwMask) == 0)
  791. {
  792. DrawTriangle( pvV0, pvV1, pvV2, wFlags );
  793. return;
  794. }
  795. // Do Clipping
  796. RRCLIPTRIANGLE newtri;
  797. RRCLIPVTX cv[3];
  798. MakeClipVertexFromFVF( cv[0], pvV0, m_ViewData,
  799. m_dwTextureCoordSizeTotal, m_qwFVFOut, c0,
  800. dwMask);
  801. MakeClipVertexFromFVF( cv[1], pvV1, m_ViewData,
  802. m_dwTextureCoordSizeTotal, m_qwFVFOut, c1,
  803. dwMask);
  804. MakeClipVertexFromFVF( cv[2], pvV2, m_ViewData,
  805. m_dwTextureCoordSizeTotal, m_qwFVFOut, c2,
  806. dwMask);
  807. newtri.v[0] = &cv[0]; cv[0].next = &cv[1];
  808. newtri.v[1] = &cv[1]; cv[1].next = &cv[2];
  809. newtri.v[2] = &cv[2]; cv[2].next = NULL;
  810. int count;
  811. RRCLIPVTX **ver;
  812. cv[0].clip |= CLIPPED_ENABLE;
  813. cv[1].clip |= CLIPPED_ENABLE;
  814. cv[2].clip |= CLIPPED_ENABLE;
  815. if (count = ClipSingleTriangle( &newtri, &ver ))
  816. {
  817. int i;
  818. // Temporary Byte Array
  819. if (m_clipping.ClipBuf.GetSize() < m_dwOutputVtxSize*count)
  820. {
  821. m_clipping.ClipBuf.Grow( m_dwOutputVtxSize*count );
  822. }
  823. LPBYTE pTLV = (LPBYTE)m_clipping.ClipBuf.GetAddress();
  824. LPBYTE p = pTLV;
  825. for (i = 0; i < count; i++)
  826. {
  827. MakeFVFVertexFromClip( p, ver[i], m_qwFVFOut,
  828. m_dwTextureCoordSizeTotal);
  829. p += m_dwOutputVtxSize;
  830. }
  831. // If it is in wireframe mode, convert the clipper output to
  832. // a line list.
  833. if (!m_bPointSprite && (GetRenderState()[D3DRENDERSTATE_FILLMODE] == D3DFILL_WIREFRAME))
  834. {
  835. DWORD dwEdgeFlags = 0;
  836. for (i = 0; i < count; i++)
  837. {
  838. if (ver[i]->clip & CLIPPED_ENABLE) dwEdgeFlags |= (1 << i);
  839. p += m_dwOutputVtxSize;
  840. }
  841. DoDrawOneEdgeFlagTriangleFan( this, m_dwOutputVtxSize,
  842. (PUINT8) pTLV, count,
  843. dwEdgeFlags );
  844. }
  845. else
  846. {
  847. DoDrawOnePrimitive( this, m_dwOutputVtxSize, (PUINT8) pTLV,
  848. D3DPT_TRIANGLEFAN, count);
  849. }
  850. }
  851. }
  852. void
  853. ReferenceRasterizer::DrawClippedLine( void* pvV0, RRCLIPCODE c0,
  854. void* pvV1, RRCLIPCODE c1,
  855. void* pvVFlat )
  856. {
  857. DWORD dwInter = (c0 & c1);
  858. DWORD dwUnion = (c0 | c1);
  859. DWORD dwMask = (m_dwTLState & RRPV_GUARDBAND) ? RRCLIPGB_ALL : RRCLIP_ALL;
  860. // All vertices outside the frustum or guardband,
  861. // return without drawing
  862. if (dwInter)
  863. {
  864. return;
  865. }
  866. // If all the vertices are in, draw and return
  867. if ((dwUnion & dwMask) == 0)
  868. {
  869. DrawLine( pvV0, pvV1, pvVFlat );
  870. return;
  871. }
  872. RRCLIPTRIANGLE newline;
  873. RRCLIPVTX cv[2];
  874. MakeClipVertexFromFVF( cv[0], pvV0, m_ViewData,
  875. m_dwTextureCoordSizeTotal, m_qwFVFOut, c0,
  876. dwMask);
  877. MakeClipVertexFromFVF( cv[1], pvV1, m_ViewData,
  878. m_dwTextureCoordSizeTotal, m_qwFVFOut, c1,
  879. dwMask);
  880. newline.v[0] = &cv[0];
  881. newline.v[1] = &cv[1];
  882. if (ClipSingleLine( &newline ))
  883. {
  884. // Temporary Byte Array
  885. if (m_clipping.ClipBuf.GetSize() < m_dwOutputVtxSize*2)
  886. {
  887. m_clipping.ClipBuf.Grow( m_dwOutputVtxSize*3 );
  888. }
  889. LPBYTE pTLV = (LPBYTE)m_clipping.ClipBuf.GetAddress();
  890. LPBYTE p = pTLV;
  891. MakeFVFVertexFromClip( p, newline.v[0], m_qwFVFOut,
  892. m_dwTextureCoordSizeTotal);
  893. p += m_dwOutputVtxSize;
  894. MakeFVFVertexFromClip( p, newline.v[1], m_qwFVFOut,
  895. m_dwTextureCoordSizeTotal);
  896. DrawLine( pTLV, p, pvVFlat );
  897. }
  898. }
  899. void
  900. ReferenceRasterizer::DrawClippedPoint( void* pvV0, RRCLIPCODE c0,
  901. void* pvVFlat )
  902. {
  903. // if definitely out
  904. if (c0 & (RRCLIP_FRONT | RRCLIP_BACK | (1<<RRCLIPGB_LEFTBIT) | (1<<RRCLIPGB_RIGHTBIT) |
  905. (1<<RRCLIPGB_TOPBIT) | (1<<RRCLIPGB_BOTTOMBIT)))
  906. return;
  907. // otherwise, could be in
  908. if (c0 == 0)
  909. {
  910. // is completely in, just draw it
  911. DrawPoint( pvV0, pvVFlat );
  912. }
  913. else
  914. {
  915. // use per vertex S if it exists, otherwise use D3DRENDERSTATE_POINTSIZE
  916. BOOL bAlreadyXfmd = FVF_TRANSFORMED( m_dwFVFIn );
  917. RRFVFExtractor Vtx0( pvV0, m_qwFVFControl, m_dwRenderState[D3DRENDERSTATE_TEXTUREPERSPECTIVE] );
  918. FLOAT fS = 1.0f;
  919. #ifdef __POINTSPRITES
  920. if (m_qwFVFControl & D3DFVF_S)
  921. {
  922. fS = Vtx0.GetS();
  923. }
  924. else if( m_dwDriverType > RRTYPE_DP2HAL )
  925. {
  926. fS = m_fRenderState[D3DRENDERSTATE_POINTSIZE];
  927. }
  928. #endif
  929. if (fS <= 1.0f)
  930. {
  931. // too small and out
  932. return;
  933. }
  934. #ifdef __POINTSPRITES
  935. if (c0 & (RRCLIP_USERCLIPPLANE0 | RRCLIP_USERCLIPPLANE1 | RRCLIP_USERCLIPPLANE2 |
  936. RRCLIP_USERCLIPPLANE3 | RRCLIP_USERCLIPPLANE4 | RRCLIP_USERCLIPPLANE5))
  937. {
  938. // large and potentially clipped, expand point sprite to quad and clip traditionally
  939. fS *= 0.5f; // turn size into screen space offset to quad points from center
  940. FLOAT w_clip = Vtx0.GetRHW(); // not really the reciprocal
  941. FLOAT x_clip_size = fS*w_clip/m_ViewData.scaleX;
  942. FLOAT y_clip_size = fS*w_clip/m_ViewData.scaleY;
  943. UINT64 qwFVFControlSave = m_qwFVFControl;
  944. UINT64 qwFVFOutSave = m_qwFVFOut;
  945. DWORD dwOutputVtxSizeSave = m_dwOutputVtxSize;
  946. DWORD dwTextureCoordSizeTotalSave = m_dwTextureCoordSizeTotal;
  947. DWORD dwTexCoordSizeSave[D3DDP_MAXTEXCOORD];
  948. memcpy(dwTexCoordSizeSave, m_dwTexCoordSize, sizeof(DWORD)*D3DDP_MAXTEXCOORD);
  949. DWORD dwInterpolateSave = m_clipping.dwInterpolate;
  950. DWORD dwNumTexCoordsSave = m_dwNumTexCoords;
  951. INT32 iTexCount = 0;
  952. if (m_dwRenderState[D3DRENDERSTATE_POINTSPRITEENABLE] && m_cActiveTextureStages)
  953. {
  954. // look through texture stages to see how many texture indices are needed
  955. // since for POINTSPRITE mode, the input vertices don't even have to have any
  956. // texture coordinates. Since this is an important advantage of using point
  957. // sprites, we have to deal with it.
  958. for ( INT32 iStage=0; iStage<m_cActiveTextureStages; iStage++ )
  959. {
  960. if (m_pTexture[iStage])
  961. {
  962. INT32 iCoordSet = m_pTexture[iStage]->m_pStageState[iStage].m_dwVal[D3DTSS_TEXCOORDINDEX];
  963. iCoordSet &= 0xffff;
  964. iTexCount = max(iCoordSet+1, iTexCount);
  965. m_clipping.dwInterpolate |= RRCLIP_INTERPOLATE_TEXTURE;
  966. }
  967. }
  968. }
  969. m_qwFVFOut &= ~(D3DFVF_TEXCOUNT_MASK | 0xffff0000);
  970. m_qwFVFOut |= (iTexCount << D3DFVF_TEXCOUNT_SHIFT) & D3DFVF_TEXCOUNT_MASK;
  971. m_qwFVFControl = m_qwFVFOut;
  972. m_dwNumTexCoords = FVF_TEXCOORD_NUMBER((DWORD)m_qwFVFOut);
  973. m_dwOutputVtxSize = GetFVFVertexSize( m_qwFVFOut );
  974. m_dwTextureCoordSizeTotal = 0;
  975. ComputeTextureCoordSize((DWORD)m_qwFVFOut, m_dwTexCoordSize,
  976. &m_dwTextureCoordSizeTotal);
  977. void *pvVT0, *pvVT1, *pvVT2, *pvVT3;
  978. {
  979. pvVT0 = MEMALLOC( m_dwOutputVtxSize );
  980. pvVT1 = MEMALLOC( m_dwOutputVtxSize );
  981. pvVT2 = MEMALLOC( m_dwOutputVtxSize );
  982. pvVT3 = MEMALLOC( m_dwOutputVtxSize );
  983. _ASSERTa( ( NULL != pvVT0 ) && ( NULL != pvVT1 ) && ( NULL != pvVT2) && (NULL != pvVT2),
  984. "malloc failure on ReferenceRasterizer::DrawClippedPoint", return; );
  985. // only copy as much data as we have
  986. DWORD dwStride = GetFVFVertexSize(qwFVFControlSave);
  987. memcpy(pvVT0, pvV0, dwStride);
  988. memcpy(pvVT1, pvV0, dwStride);
  989. memcpy(pvVT2, pvV0, dwStride);
  990. memcpy(pvVT3, pvV0, dwStride);
  991. }
  992. // encase FVF vertex pointer and control in class to extract fields
  993. RRFVFExtractor VtxT0( pvVT0, m_qwFVFControl, m_dwRenderState[D3DRENDERSTATE_TEXTUREPERSPECTIVE] );
  994. RRFVFExtractor VtxT1( pvVT1, m_qwFVFControl, m_dwRenderState[D3DRENDERSTATE_TEXTUREPERSPECTIVE] );
  995. RRFVFExtractor VtxT2( pvVT2, m_qwFVFControl, m_dwRenderState[D3DRENDERSTATE_TEXTUREPERSPECTIVE] );
  996. RRFVFExtractor VtxT3( pvVT3, m_qwFVFControl, m_dwRenderState[D3DRENDERSTATE_TEXTUREPERSPECTIVE] );
  997. FLOAT *pXY = VtxT0.GetPtrXYZ();
  998. pXY[0] += -x_clip_size;
  999. pXY[1] += -y_clip_size;
  1000. pXY = VtxT1.GetPtrXYZ();
  1001. pXY[0] += x_clip_size;
  1002. pXY[1] += -y_clip_size;
  1003. pXY = VtxT2.GetPtrXYZ();
  1004. pXY[0] += -x_clip_size;
  1005. pXY[1] += y_clip_size;
  1006. pXY = VtxT3.GetPtrXYZ();
  1007. pXY[0] += x_clip_size;
  1008. pXY[1] += y_clip_size;
  1009. if (m_dwRenderState[D3DRENDERSTATE_POINTSPRITEENABLE] && m_cActiveTextureStages)
  1010. {
  1011. // compute functions for texture coordinates
  1012. if (m_cActiveTextureStages)
  1013. {
  1014. for ( INT32 iStage=0; iStage<m_cActiveTextureStages; iStage++ )
  1015. {
  1016. if (m_pTexture[iStage])
  1017. {
  1018. INT32 iCoordSet = m_pTexture[iStage]->m_pStageState[iStage].m_dwVal[D3DTSS_TEXCOORDINDEX];
  1019. iCoordSet &= 0xffff;
  1020. FLOAT *pUV = VtxT0.GetPtrTexCrd(0, iCoordSet);
  1021. pUV[0] = 0.0f;
  1022. pUV[1] = 0.0f;
  1023. pUV = VtxT1.GetPtrTexCrd(0, iCoordSet);
  1024. pUV[0] = SPRITETEXCOORDMAX;
  1025. pUV[1] = 0.0f;
  1026. pUV = VtxT2.GetPtrTexCrd(0, iCoordSet);
  1027. pUV[0] = 0.0f;
  1028. pUV[1] = SPRITETEXCOORDMAX;
  1029. pUV = VtxT3.GetPtrTexCrd(0, iCoordSet);
  1030. pUV[0] = SPRITETEXCOORDMAX;
  1031. pUV[1] = SPRITETEXCOORDMAX;
  1032. }
  1033. }
  1034. }
  1035. }
  1036. RRCLIPCODE clipIntersection, clipUnion;
  1037. RRCLIPCODE c[4];
  1038. RRFVFExtractor* pVtxTs[4] = {&VtxT0, &VtxT1, &VtxT2, &VtxT3};
  1039. for ( INT32 i= 0; i < 4; i++)
  1040. {
  1041. FLOAT x_clip = pVtxTs[i]->GetX();
  1042. FLOAT y_clip = pVtxTs[i]->GetY();
  1043. FLOAT z_clip = pVtxTs[i]->GetZ();
  1044. FLOAT w_clip = pVtxTs[i]->GetRHW();
  1045. c[i] = ComputeClipCodes(&clipIntersection, &clipUnion, x_clip, y_clip,
  1046. z_clip, w_clip, 0.0f);
  1047. if (c[i] == 0 || ((m_dwTLState & RRPV_GUARDBAND) && ((c[i] & ~RRCLIP_INGUARDBAND) == 0)))
  1048. {
  1049. // need to compute screen coordinates
  1050. FLOAT inv_w_clip = 1.0f/w_clip;
  1051. FLOAT *pXYZW = pVtxTs[i]->GetPtrXYZ();
  1052. pXYZW[0] = x_clip * inv_w_clip * m_ViewData.scaleX +
  1053. m_ViewData.offsetX;
  1054. pXYZW[1] = y_clip * inv_w_clip * m_ViewData.scaleY +
  1055. m_ViewData.offsetY;
  1056. pXYZW[2] = z_clip * inv_w_clip * m_ViewData.scaleZ +
  1057. m_ViewData.offsetZ;
  1058. pXYZW[3] = inv_w_clip;
  1059. }
  1060. }
  1061. // set point sprite mode in rasterizer
  1062. m_bPointSprite = TRUE;
  1063. DrawClippedTriangle(pvVT0, c[0], pvVT1, c[1], pvVT2, c[2], 0);
  1064. DrawClippedTriangle(pvVT1, c[1], pvVT3, c[3], pvVT2, c[2], 0);
  1065. // clear point sprite mode in rasterizer
  1066. m_bPointSprite = FALSE;
  1067. m_qwFVFControl = qwFVFControlSave;
  1068. m_dwOutputVtxSize = dwOutputVtxSizeSave;
  1069. m_qwFVFOut = qwFVFOutSave;
  1070. m_dwTextureCoordSizeTotal = dwTextureCoordSizeTotalSave;
  1071. memcpy(m_dwTexCoordSize, dwTexCoordSizeSave, sizeof(DWORD)*D3DDP_MAXTEXCOORD);
  1072. m_clipping.dwInterpolate = dwInterpolateSave;
  1073. m_dwNumTexCoords = dwNumTexCoordsSave;
  1074. MEMFREE( pvVT0 );
  1075. MEMFREE( pvVT1 );
  1076. MEMFREE( pvVT2 );
  1077. MEMFREE( pvVT3 );
  1078. }
  1079. else
  1080. {
  1081. // Just x y clipped. Let bounding box handle it
  1082. DrawPoint( pvV0, pvVFlat );
  1083. }
  1084. #endif
  1085. }
  1086. }
  1087. ////////////////////////////////////////////////////////////////////////////
  1088. //
  1089. // Returns 0, if triangle is clipped. Number of vertices otherwise.
  1090. //
  1091. // Original vertices should not be modified inside the function
  1092. ////////////////////////////////////////////////////////////////////////////
  1093. #undef DPF_MODNAME
  1094. #define DPF_MODNAME "ClipSingleTriangle"
  1095. int
  1096. ReferenceRasterizer::ClipSingleTriangle(RRCLIPTRIANGLE *tri,
  1097. RRCLIPVTX ***clipVertexPointer)
  1098. {
  1099. int accept;
  1100. int i, j;
  1101. int count;
  1102. RRCLIPVTX **inv;
  1103. RRCLIPVTX **outv;
  1104. RRCLIPVTX *p;
  1105. ULONG_PTR swapv;
  1106. D3DCOLOR diffuse1; // Original colors
  1107. D3DCOLOR specular1;
  1108. D3DCOLOR diffuse2;
  1109. D3DCOLOR specular2;
  1110. DWORD dwClipBit;
  1111. DWORD dwClippedBit;
  1112. if (GetRenderState()[D3DRENDERSTATE_SHADEMODE] == D3DSHADE_FLAT)
  1113. {
  1114. // It is easier to set all vertices to the same color here
  1115. D3DCOLOR diffuse = tri->v[0]->color;
  1116. D3DCOLOR specular = tri->v[0]->specular;
  1117. //Save original colors
  1118. diffuse1 = tri->v[1]->color;
  1119. specular1 = tri->v[1]->specular;
  1120. diffuse2 = tri->v[2]->color;
  1121. specular2 = tri->v[2]->specular;
  1122. // copy all but fog intensity
  1123. tri->v[1]->color= diffuse;
  1124. tri->v[1]->specular &= 0xFF000000; tri->v[1]->specular |= (0x00FFFFFF & specular);
  1125. tri->v[2]->color = diffuse;
  1126. tri->v[2]->specular &= 0xFF000000; tri->v[2]->specular |= (0x00FFFFFF & specular);
  1127. }
  1128. accept = (tri->v[0]->clip | tri->v[1]->clip | tri->v[2]->clip);
  1129. inv = tri->v;
  1130. count = 3;
  1131. outv = m_clipping.clip_vbuf1;
  1132. m_clipping.clip_color = tri->v[0]->color;
  1133. m_clipping.clip_specular = tri->v[0]->specular;
  1134. /*
  1135. * XXX assumes sizeof(void*) == sizeof(unsigned long)
  1136. */
  1137. {
  1138. ULONG_PTR tmp1;
  1139. ULONG_PTR tmp2;
  1140. tmp1 = (ULONG_PTR)m_clipping.clip_vbuf1;
  1141. tmp2 = (ULONG_PTR)m_clipping.clip_vbuf2;
  1142. swapv = tmp1 + tmp2;
  1143. }
  1144. m_clipping.clip_vertices_used = 0;
  1145. #define SWAP(inv, outv) \
  1146. inv = outv; \
  1147. outv = (RRCLIPVTX**) (swapv - (ULONG_PTR) outv)
  1148. if (accept & RRCLIP_FRONT)
  1149. {
  1150. count = ClipFront( inv, outv, count );
  1151. if (count < 3)
  1152. goto out_of_here;
  1153. SWAP(inv, outv);
  1154. }
  1155. if (m_dwTLState & RRPV_GUARDBAND)
  1156. {
  1157. // If there was clipping by the front plane it is better to
  1158. // compute clip code for new vertices and re-compute accept.
  1159. // Otherwise we will try to clip by sides when it is not necessary
  1160. if (accept & RRCLIP_FRONT)
  1161. {
  1162. accept = 0;
  1163. for (i = 0; i < count; i++)
  1164. {
  1165. RRCLIPVTX *p;
  1166. p = inv[i];
  1167. if (p->clip & CLIPPED_FRONT)
  1168. accept |= ComputeClipCodeGB(m_ViewData,
  1169. m_xfmUserClipPlanes, p);
  1170. else
  1171. accept |= p->clip;
  1172. }
  1173. }
  1174. if (accept & RRCLIP_BACK)
  1175. {
  1176. count = ClipBack( inv, outv, count );
  1177. if (count < 3)
  1178. goto out_of_here;
  1179. SWAP(inv, outv);
  1180. }
  1181. if (accept & RRCLIPGB_LEFT)
  1182. {
  1183. count = ClipLeftGB( inv, outv, count );
  1184. if (count < 3)
  1185. goto out_of_here;
  1186. SWAP(inv, outv);
  1187. }
  1188. if (accept & RRCLIPGB_RIGHT)
  1189. {
  1190. count = ClipRightGB( inv, outv, count );
  1191. if (count < 3)
  1192. goto out_of_here;
  1193. SWAP(inv, outv);
  1194. }
  1195. if (accept & RRCLIPGB_BOTTOM)
  1196. {
  1197. count = ClipBottomGB( inv, outv, count );
  1198. if (count < 3)
  1199. goto out_of_here;
  1200. SWAP(inv, outv);
  1201. }
  1202. if (accept & RRCLIPGB_TOP)
  1203. {
  1204. count = ClipTopGB( inv, outv, count );
  1205. if (count < 3)
  1206. goto out_of_here;
  1207. SWAP(inv, outv);
  1208. }
  1209. }
  1210. else
  1211. {
  1212. // If there was clipping by the front plane it is better to
  1213. // compute clip code for new vertices and re-compute accept.
  1214. // Otherwise we will try to clip by sides when it is not necessary
  1215. if (accept & RRCLIP_FRONT)
  1216. {
  1217. accept = 0;
  1218. for (i = 0; i < count; i++)
  1219. {
  1220. RRCLIPVTX *p;
  1221. p = inv[i];
  1222. if (p->clip & (CLIPPED_FRONT))
  1223. accept |= ComputeClipCode( m_xfmUserClipPlanes, p );
  1224. else
  1225. accept |= p->clip;
  1226. }
  1227. }
  1228. if (accept & RRCLIP_BACK)
  1229. {
  1230. count = ClipBack( inv, outv, count );
  1231. if (count < 3)
  1232. goto out_of_here;
  1233. SWAP(inv, outv);
  1234. }
  1235. if (accept & RRCLIP_LEFT)
  1236. {
  1237. count = ClipLeft( inv, outv, count );
  1238. if (count < 3)
  1239. goto out_of_here;
  1240. SWAP(inv, outv);
  1241. }
  1242. if (accept & RRCLIP_RIGHT)
  1243. {
  1244. count = ClipRight( inv, outv, count );
  1245. if (count < 3)
  1246. goto out_of_here;
  1247. SWAP(inv, outv);
  1248. }
  1249. if (accept & RRCLIP_BOTTOM)
  1250. {
  1251. count = ClipBottom( inv, outv, count );
  1252. if (count < 3)
  1253. goto out_of_here;
  1254. SWAP(inv, outv);
  1255. }
  1256. if (accept & RRCLIP_TOP)
  1257. {
  1258. count = ClipTop( inv, outv, count );
  1259. if (count < 3)
  1260. goto out_of_here;
  1261. SWAP(inv, outv);
  1262. }
  1263. }
  1264. dwClipBit = RRCLIP_USERCLIPPLANE0;
  1265. dwClippedBit = CLIPPED_USERCLIPPLANE0;
  1266. // User Clip Planes
  1267. for( j=0; j<RRMAX_USER_CLIPPLANES; j++)
  1268. {
  1269. if (accept & dwClipBit)
  1270. {
  1271. count = ClipByPlane( inv, outv, &m_xfmUserClipPlanes[j].plane,
  1272. dwClippedBit, count);
  1273. if (count < 3)
  1274. goto out_of_here;
  1275. SWAP(inv, outv);
  1276. }
  1277. dwClipBit <<= 1;
  1278. dwClippedBit <<= 1;
  1279. }
  1280. #undef SWAP
  1281. ComputeScreenCoordinates( m_ViewData, inv, count );
  1282. *clipVertexPointer = inv;
  1283. m_clipping.current_vbuf = inv;
  1284. return count;
  1285. out_of_here:
  1286. *clipVertexPointer = NULL;
  1287. return 0;
  1288. }
  1289. //-----------------------------------------------------------------------
  1290. //
  1291. int
  1292. ReferenceRasterizer::ClipSingleLine( RRCLIPTRIANGLE *line )
  1293. {
  1294. int accept;
  1295. int j;
  1296. D3DVALUE in1, in2;
  1297. DWORD dwClipBit;
  1298. DWORD dwClippedBit;
  1299. accept = (line->v[0]->clip | line->v[1]->clip);
  1300. m_clipping.clip_color = line->v[0]->color;
  1301. m_clipping.clip_specular = line->v[0]->specular;
  1302. if (accept & D3DCLIP_FRONT)
  1303. if (ClipLineFront(line))
  1304. goto out_of_here;
  1305. if (m_dwTLState & RRPV_GUARDBAND)
  1306. {
  1307. // If there was clipping by the front plane it is better to
  1308. // compute clip code for new vertices and re-compute accept.
  1309. // Otherwise we will try to clip by sides when it is not necessary
  1310. if (accept & D3DCLIP_FRONT)
  1311. {
  1312. RRCLIPVTX * p;
  1313. accept = 0;
  1314. p = line->v[0];
  1315. if (p->clip & CLIPPED_FRONT)
  1316. accept |= ComputeClipCodeGB(m_ViewData, m_xfmUserClipPlanes, p);
  1317. else
  1318. accept |= p->clip;
  1319. p = line->v[1];
  1320. if (p->clip & CLIPPED_FRONT)
  1321. accept |= ComputeClipCodeGB(m_ViewData, m_xfmUserClipPlanes, p);
  1322. else
  1323. accept |= p->clip;
  1324. }
  1325. if (accept & D3DCLIP_BACK)
  1326. if (ClipLineBack( line ))
  1327. goto out_of_here;
  1328. if (accept & RRCLIPGB_LEFT)
  1329. if (ClipLineLeftGB( line ))
  1330. goto out_of_here;
  1331. if (accept & RRCLIPGB_RIGHT)
  1332. if (ClipLineRightGB( line ))
  1333. goto out_of_here;
  1334. if (accept & RRCLIPGB_TOP)
  1335. if (ClipLineTopGB( line ))
  1336. goto out_of_here;
  1337. if (accept & RRCLIPGB_BOTTOM)
  1338. if (ClipLineBottomGB( line ))
  1339. goto out_of_here;
  1340. }
  1341. else
  1342. {
  1343. // If there was clipping by the front plane it is better to
  1344. // compute clip code for new vertices and re-compute accept.
  1345. // Otherwise we will try to clip by sides when it is not necessary
  1346. if (accept & D3DCLIP_FRONT)
  1347. {
  1348. RRCLIPVTX * p;
  1349. accept = 0;
  1350. p = line->v[0];
  1351. if (p->clip & CLIPPED_FRONT)
  1352. accept |= ComputeClipCode( m_xfmUserClipPlanes, p );
  1353. else
  1354. accept |= p->clip;
  1355. p = line->v[1];
  1356. if (p->clip & CLIPPED_FRONT)
  1357. accept |= ComputeClipCode( m_xfmUserClipPlanes, p );
  1358. else
  1359. accept |= p->clip;
  1360. }
  1361. if (accept & D3DCLIP_BACK)
  1362. if (ClipLineBack( line ))
  1363. goto out_of_here;
  1364. if (accept & D3DCLIP_LEFT)
  1365. if (ClipLineLeft( line ))
  1366. goto out_of_here;
  1367. if (accept & D3DCLIP_RIGHT)
  1368. if (ClipLineRight( line ))
  1369. goto out_of_here;
  1370. if (accept & D3DCLIP_TOP)
  1371. if (ClipLineTop( line ))
  1372. goto out_of_here;
  1373. if (accept & D3DCLIP_BOTTOM)
  1374. if (ClipLineBottom( line ))
  1375. goto out_of_here;
  1376. }
  1377. // User Clip Planes
  1378. dwClipBit = RRCLIP_USERCLIPPLANE0;
  1379. dwClippedBit = CLIPPED_USERCLIPPLANE0;
  1380. for( j=0; j<RRMAX_USER_CLIPPLANES; j++)
  1381. {
  1382. if (accept & dwClipBit)
  1383. {
  1384. if( ClipLineByPlane( line, &m_xfmUserClipPlanes[j].plane,
  1385. dwClippedBit ))
  1386. goto out_of_here;
  1387. }
  1388. dwClipBit <<= 1;
  1389. dwClippedBit <<= 1;
  1390. }
  1391. ComputeScreenCoordinates(m_ViewData, line->v, 2);
  1392. return 1;
  1393. out_of_here:
  1394. return 0;
  1395. }