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.

855 lines
27 KiB

  1. /*==========================================================================;
  2. *
  3. * Copyright (C) 1997 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: clipper.c
  6. * Content: Clipper
  7. *
  8. ***************************************************************************/
  9. #include "pch.cpp"
  10. #pragma hdrstop
  11. #include "clipper.h"
  12. #include "d3dfei.h"
  13. #define GET_NEW_CLIP_VERTEX \
  14. &pv->ClipperState.clip_vertices[pv->ClipperState.clip_vertices_used++];
  15. //---------------------------------------------------------------------
  16. int SetInterpolationFlags(D3DFE_PROCESSVERTICES *pv)
  17. {
  18. // Figure out which pieces need to be interpolated in new vertices.
  19. int interpolate = 0;
  20. if (pv->lpdwRStates[D3DRENDERSTATE_SHADEMODE] == D3DSHADE_GOURAUD)
  21. {
  22. if (pv->dwDeviceFlags & D3DDEV_RAMP)
  23. {
  24. interpolate |= INTERPOLATE_RCOLOR;
  25. }
  26. else
  27. {
  28. interpolate |= INTERPOLATE_COLOR;
  29. if (pv->lpdwRStates[D3DRENDERSTATE_SPECULARENABLE] ||
  30. pv->lpdwRStates[D3DRENDERSTATE_FOGENABLE])
  31. {
  32. interpolate |= INTERPOLATE_SPECULAR;
  33. }
  34. }
  35. }
  36. if (pv->dwDeviceFlags & D3DDEV_LEGACYTEXTURE)
  37. {
  38. interpolate |= INTERPOLATE_TEXTUREL;
  39. }
  40. else
  41. for(DWORD i = 0; i < pv->dwMaxTextureIndices; ++i)
  42. {
  43. if(pv->pD3DMappedTexI[i])
  44. {
  45. interpolate |= INTERPOLATE_TEXTURE3;
  46. return interpolate;
  47. }
  48. }
  49. return interpolate;
  50. }
  51. //---------------------------------------------------------------------
  52. __inline void
  53. InterpolateColor(ClipVertex *p,
  54. ClipVertex *p1,
  55. ClipVertex *p2,
  56. D3DVALUE num_denom )
  57. {
  58. int r1, g1, b1, a1;
  59. int r2, g2, b2, a2;
  60. r1 = RGBA_GETRED(p1->color);
  61. g1 = RGBA_GETGREEN(p1->color);
  62. b1 = RGBA_GETBLUE(p1->color);
  63. a1 = RGBA_GETALPHA(p1->color);
  64. r2 = RGBA_GETRED(p2->color);
  65. g2 = RGBA_GETGREEN(p2->color);
  66. b2 = RGBA_GETBLUE(p2->color);
  67. a2 = RGBA_GETALPHA(p2->color);
  68. p->color = RGBA_MAKE((WORD)(r1 + (r2 - r1) * num_denom),
  69. (WORD)(g1 + (g2 - g1) * num_denom),
  70. (WORD)(b1 + (b2 - b1) * num_denom),
  71. (WORD)(a1 + (a2 - a1) * num_denom));
  72. }
  73. //---------------------------------------------------------------------
  74. void InterpolateRampColor(ClipVertex* p,
  75. ClipVertex* p1,
  76. ClipVertex* p2,
  77. D3DVALUE num_denom )
  78. {
  79. int a, c, c1, c2;
  80. int a1, a2;
  81. c1 = CI_MASKALPHA(p1->color);
  82. a1 = CI_GETALPHA(p1->color);
  83. c2 = CI_MASKALPHA(p2->color);
  84. a2 = CI_GETALPHA(p2->color);
  85. c = (int)(c1 + (c2 - c1) * num_denom);
  86. a = (int)(a1 + (a2 - a1) * num_denom);
  87. p->color = CI_MAKE( a, CI_GETINDEX(c), CI_GETFRACTION(c) );
  88. }
  89. //---------------------------------------------------------------------
  90. __inline void
  91. InterpolateSpecular(ClipVertex *p,
  92. ClipVertex *p1,
  93. ClipVertex *p2,
  94. D3DVALUE num_denom )
  95. {
  96. int r1, g1, b1, a1;
  97. int r2, g2, b2, a2;
  98. r1 = RGBA_GETRED(p1->specular);
  99. g1 = RGBA_GETGREEN(p1->specular);
  100. b1 = RGBA_GETBLUE(p1->specular);
  101. a1 = RGBA_GETALPHA(p1->specular);
  102. r2 = RGBA_GETRED(p2->specular);
  103. g2 = RGBA_GETGREEN(p2->specular);
  104. b2 = RGBA_GETBLUE(p2->specular);
  105. a2 = RGBA_GETALPHA(p2->specular);
  106. p->specular = RGBA_MAKE((WORD)(r1 + (r2 - r1) * num_denom),
  107. (WORD)(g1 + (g2 - g1) * num_denom),
  108. (WORD)(b1 + (b2 - b1) * num_denom),
  109. (WORD)(a1 + (a2 - a1) * num_denom));
  110. }
  111. //---------------------------------------------------------------------
  112. __inline D3DVALUE
  113. InterpolateTexture(D3DVALUE t1,
  114. D3DVALUE t2,
  115. D3DVALUE num_denom,
  116. DWORD bWrap)
  117. {
  118. if (!bWrap)
  119. return ((t2 - t1) * num_denom + t1);
  120. else
  121. {
  122. D3DVALUE t = (TextureDiff(t2, t1, 1) * num_denom + t1);
  123. if (t > 1.0f)
  124. t -= 1.0f;
  125. return t;
  126. }
  127. }
  128. //---------------------------------------------------------------------
  129. void
  130. Interpolate(D3DFE_PROCESSVERTICES *pv,
  131. ClipVertex *p,
  132. ClipVertex *p1,
  133. ClipVertex *p2,
  134. int code,
  135. int interpolate,
  136. D3DVALUE num, D3DVALUE denom)
  137. {
  138. D3DVALUE num_denom = num / denom;
  139. p->clip = (((int)p1->clip & (int)p2->clip) & ~CLIPPED_ENABLE) | code;
  140. p->hx = p1->hx + (p2->hx - p1->hx) * num_denom;
  141. p->hy = p1->hy + (p2->hy - p1->hy) * num_denom;
  142. p->hz = p1->hz + (p2->hz - p1->hz) * num_denom;
  143. p->hw = p1->hw + (p2->hw - p1->hw) * num_denom;
  144. p->color = pv->ClipperState.clip_color;
  145. p->specular = pv->ClipperState.clip_specular;
  146. /*
  147. * Interpolate any other color model or quality dependent values.
  148. */
  149. if (interpolate & INTERPOLATE_COLOR)
  150. {
  151. InterpolateColor(p, p1, p2, num_denom);
  152. }
  153. else
  154. if (interpolate & INTERPOLATE_RCOLOR)
  155. {
  156. InterpolateRampColor(p, p1, p2, num_denom);
  157. }
  158. if (interpolate & INTERPOLATE_SPECULAR)
  159. {
  160. InterpolateSpecular(p, p1, p2, num_denom);
  161. }
  162. if (interpolate & INTERPOLATE_TEXTUREL)
  163. {
  164. p->tex[0].u = InterpolateTexture(p1->tex[0].u, p2->tex[0].u,
  165. num_denom,
  166. pv->lpdwRStates[D3DRENDERSTATE_WRAPU]);
  167. p->tex[0].v = InterpolateTexture(p1->tex[0].v, p2->tex[0].v,
  168. num_denom,
  169. pv->lpdwRStates[D3DRENDERSTATE_WRAPV]);
  170. }
  171. else
  172. if (interpolate & INTERPOLATE_TEXTURE3)
  173. {
  174. // Assume that D3DRENDERSTATE_WRAPi are sequential
  175. for (DWORD i = 0; i < pv->nTexCoord; i++)
  176. {
  177. DWORD wrapState = pv->lpdwRStates[D3DRENDERSTATE_WRAP0 + i];
  178. p->tex[i].u = InterpolateTexture(p1->tex[i].u, p2->tex[i].u,
  179. num_denom, wrapState & D3DWRAP_U);
  180. p->tex[i].v = InterpolateTexture(p1->tex[i].v, p2->tex[i].v,
  181. num_denom, wrapState & D3DWRAP_V);
  182. }
  183. }
  184. }
  185. //------------------------------------------------------------------------------
  186. // Functions for clipping by frustum window
  187. //
  188. #define __CLIP_NAME ClipLeft
  189. #define __CLIP_LINE_NAME ClipLineLeft
  190. #define __CLIP_FLAG CLIPPED_LEFT
  191. #define __CLIP_COORD hx
  192. #include "clip.h"
  193. #define __CLIP_NAME ClipRight
  194. #define __CLIP_LINE_NAME ClipLineRight
  195. #define __CLIP_W
  196. #define __CLIP_FLAG CLIPPED_RIGHT
  197. #define __CLIP_COORD hx
  198. #include "clip.h"
  199. #define __CLIP_NAME ClipBottom
  200. #define __CLIP_LINE_NAME ClipLineBottom
  201. #define __CLIP_FLAG CLIPPED_BOTTOM
  202. #define __CLIP_COORD hy
  203. #include "clip.h"
  204. #define __CLIP_NAME ClipTop
  205. #define __CLIP_LINE_NAME ClipLineTop
  206. #define __CLIP_W
  207. #define __CLIP_FLAG CLIPPED_TOP
  208. #define __CLIP_COORD hy
  209. #include "clip.h"
  210. #define __CLIP_NAME ClipBack
  211. #define __CLIP_LINE_NAME ClipLineBack
  212. #define __CLIP_W
  213. #define __CLIP_FLAG CLIPPED_BACK
  214. #define __CLIP_COORD hz
  215. #include "clip.h"
  216. #define __CLIP_NAME ClipFront
  217. #define __CLIP_LINE_NAME ClipLineFront
  218. #define __CLIP_FLAG CLIPPED_FRONT
  219. #define __CLIP_COORD hz
  220. #include "clip.h"
  221. //------------------------------------------------------------------------------
  222. // Functions for guard band clipping
  223. //
  224. #define __CLIP_GUARDBAND
  225. #define __CLIP_NAME ClipLeftGB
  226. #define __CLIP_LINE_NAME ClipLineLeftGB
  227. #define __CLIP_FLAG CLIPPED_LEFT
  228. #define __CLIP_COORD hx
  229. #define __CLIP_SIGN -
  230. #define __CLIP_GBCOEF Kgbx1
  231. #include "clip.h"
  232. #define __CLIP_NAME ClipRightGB
  233. #define __CLIP_LINE_NAME ClipLineRightGB
  234. #define __CLIP_FLAG CLIPPED_RIGHT
  235. #define __CLIP_COORD hx
  236. #define __CLIP_GBCOEF Kgbx2
  237. #define __CLIP_SIGN +
  238. #include "clip.h"
  239. #define __CLIP_NAME ClipBottomGB
  240. #define __CLIP_LINE_NAME ClipLineBottomGB
  241. #define __CLIP_FLAG CLIPPED_BOTTOM
  242. #define __CLIP_COORD hy
  243. #define __CLIP_SIGN -
  244. #define __CLIP_GBCOEF Kgby1
  245. #include "clip.h"
  246. #define __CLIP_NAME ClipTopGB
  247. #define __CLIP_LINE_NAME ClipLineTopGB
  248. #define __CLIP_FLAG CLIPPED_TOP
  249. #define __CLIP_COORD hy
  250. #define __CLIP_GBCOEF Kgby2
  251. #define __CLIP_SIGN +
  252. #include "clip.h"
  253. #undef __CLIP_GUARDBAND
  254. /*------------------------------------------------------------------------
  255. * Calculate the screen coords for any new vertices
  256. * introduced into the polygon.
  257. */
  258. void ComputeScreenCoordinates(D3DFE_PROCESSVERTICES *pv,
  259. ClipVertex **inv,
  260. int count, D3DRECTV *extent)
  261. {
  262. int i;
  263. BOOL updateExtent = !(pv->dwFlags & D3DDP_DONOTUPDATEEXTENTS);
  264. D3DFE_VIEWPORTCACHE& VPORT = pv->vcache;
  265. for (i = 0; i < count; i++)
  266. {
  267. ClipVertex *p;
  268. p = inv[i];
  269. /*
  270. * Catch any vertices that need screen co-ordinates generated.
  271. * There are two possibilities
  272. * 1) Vertices generated during interpolation
  273. * 2) Vertices marked for clipping by the transform but
  274. * not clipped here due to the finite precision
  275. * of the floating point unit.
  276. */
  277. if (p->clip & ~CLIPPED_ENABLE)
  278. {
  279. D3DVALUE w;
  280. w = D3DVAL(1.0)/p->hw;
  281. switch ((int)p->clip & (CLIPPED_LEFT|CLIPPED_RIGHT))
  282. {
  283. case CLIPPED_LEFT: p->sx = VPORT.minXgb; break;
  284. case CLIPPED_RIGHT: p->sx = VPORT.maxXgb; break;
  285. default:
  286. p->sx = p->hx * VPORT.scaleX * w + VPORT.offsetX;
  287. if (p->sx < VPORT.minXgb)
  288. p->sx = VPORT.minXgb;
  289. if (p->sx > VPORT.maxXgb)
  290. p->sx = VPORT.maxXgb;
  291. }
  292. switch ((int)p->clip & (CLIPPED_TOP|CLIPPED_BOTTOM))
  293. {
  294. case CLIPPED_BOTTOM: p->sy = VPORT.maxYgb; break;
  295. case CLIPPED_TOP: p->sy = VPORT.minYgb; break;
  296. default:
  297. p->sy = p->hy * VPORT.scaleY * w + VPORT.offsetY;
  298. if (p->sy < VPORT.minYgb)
  299. p->sy = VPORT.minYgb;
  300. if (p->sy > VPORT.maxYgb)
  301. p->sy = VPORT.maxYgb;
  302. }
  303. p->sz = p->hz * w;
  304. if (updateExtent)
  305. {
  306. if (p->sx < extent->x1)
  307. extent->x1 = p->sx;
  308. if (p->sy < extent->y1)
  309. extent->y1 = p->sy;
  310. if (p->sx > extent->x2)
  311. extent->x2 = p->sx;
  312. if (p->sy > extent->y2)
  313. extent->y2 = p->sy;
  314. }
  315. }
  316. }
  317. }
  318. //---------------------------------------------------------------------
  319. inline DWORD ComputeClipCodeGB(D3DFE_PROCESSVERTICES *pv, ClipVertex *p)
  320. {
  321. DWORD clip = 0;
  322. if (p->hx < p->hw * pv->vcache.Kgbx1)
  323. clip |= __D3DCLIPGB_LEFT;
  324. if (p->hx > p->hw * pv->vcache.Kgbx2)
  325. clip |= __D3DCLIPGB_RIGHT;
  326. if (p->hy < p->hw * pv->vcache.Kgby1)
  327. clip |= __D3DCLIPGB_BOTTOM;
  328. if (p->hy > p->hw * pv->vcache.Kgby2)
  329. clip |= __D3DCLIPGB_TOP;
  330. if (p->hz > p->hw)
  331. clip |= D3DCLIP_BACK;
  332. p->clip = (p->clip & (CLIPPED_ENABLE | CLIPPED_FRONT)) | clip;
  333. return clip;
  334. }
  335. //---------------------------------------------------------------------
  336. inline DWORD ComputeClipCode(D3DFE_PROCESSVERTICES *pv, ClipVertex *p)
  337. {
  338. DWORD clip = 0;
  339. if (FLOAT_LTZ(p->hx))
  340. clip |= D3DCLIP_LEFT;
  341. if (p->hx > p->hw)
  342. clip |= D3DCLIP_RIGHT;
  343. if (FLOAT_LTZ(p->hy))
  344. clip |= D3DCLIP_BOTTOM;
  345. if (p->hy > p->hw)
  346. clip |= D3DCLIP_TOP;
  347. if (p->hz > p->hw)
  348. clip |= D3DCLIP_BACK;
  349. p->clip = (p->clip & (CLIPPED_ENABLE | CLIPPED_FRONT)) | clip;
  350. return clip;
  351. }
  352. //***********************************************************************
  353. //
  354. // Returns 0, if triangle is clipped. Number of vertices otherwise.
  355. //
  356. #undef DPF_MODNAME
  357. #define DPF_MODNAME "ClipSingleTriangle"
  358. int D3DFE_PVFUNCS::ClipSingleTriangle(D3DFE_PROCESSVERTICES *pv,
  359. ClipTriangle *tri,
  360. ClipVertex ***clipVertexPointer,
  361. int interpolate)
  362. {
  363. int accept;
  364. int i;
  365. int count;
  366. ClipVertex **inv;
  367. ClipVertex **outv;
  368. ClipVertex *p;
  369. ULONG_PTR swapv;
  370. CD3DFPstate D3DFPstate; // Sets optimal FPU state for D3D.
  371. if (pv->lpdwRStates[D3DRENDERSTATE_SHADEMODE] == D3DSHADE_FLAT)
  372. {
  373. // It is easier to set all vertices to the same color here
  374. D3DCOLOR diffuse = tri->v[0]->color;
  375. D3DCOLOR specular = tri->v[0]->specular;
  376. tri->v[1]->color= diffuse;
  377. tri->v[1]->specular = specular;
  378. tri->v[2]->color = diffuse;
  379. tri->v[2]->specular = specular;
  380. }
  381. accept = (tri->v[0]->clip | tri->v[1]->clip | tri->v[2]->clip);
  382. inv = tri->v;
  383. if (tri->flags & D3DTRIFLAG_EDGEENABLE1)
  384. tri->v[0]->clip |= CLIPPED_ENABLE;
  385. if (tri->flags & D3DTRIFLAG_EDGEENABLE2)
  386. tri->v[1]->clip |= CLIPPED_ENABLE;
  387. if (tri->flags & D3DTRIFLAG_EDGEENABLE3)
  388. tri->v[2]->clip |= CLIPPED_ENABLE;
  389. count = 3;
  390. outv = pv->ClipperState.clip_vbuf1;
  391. pv->ClipperState.clip_color = tri->v[0]->color;
  392. pv->ClipperState.clip_specular = tri->v[0]->specular;
  393. /*
  394. * XXX assumes sizeof(void*) == sizeof(unsigned long)
  395. */
  396. {
  397. ULONG_PTR tmp1;
  398. ULONG_PTR tmp2;
  399. tmp1 = (ULONG_PTR)pv->ClipperState.clip_vbuf1;
  400. tmp2 = (ULONG_PTR)pv->ClipperState.clip_vbuf2;
  401. swapv = tmp1 + tmp2;
  402. }
  403. pv->ClipperState.clip_vertices_used = 0;
  404. #define SWAP(inv, outv) \
  405. inv = outv; \
  406. outv = (ClipVertex**) (swapv - (ULONG_PTR) outv)
  407. if (accept & D3DCLIP_FRONT)
  408. {
  409. count = ClipFront(pv, inv, outv, count, interpolate);
  410. if (count < 3)
  411. goto out_of_here;
  412. SWAP(inv, outv);
  413. }
  414. if (pv->dwDeviceFlags & D3DDEV_GUARDBAND)
  415. {
  416. // If there was clipping by the front plane it is better to
  417. // compute clip code for new vertices and re-compute accept.
  418. // Otherwise we will try to clip by sides when it is not necessary
  419. if (accept & D3DCLIP_FRONT)
  420. {
  421. accept = 0;
  422. for (i = 0; i < count; i++)
  423. {
  424. ClipVertex *p;
  425. p = inv[i];
  426. if (p->clip & CLIPPED_FRONT)
  427. accept |= ComputeClipCodeGB(pv, p);
  428. else
  429. accept |= p->clip;
  430. }
  431. }
  432. if (accept & D3DCLIP_BACK)
  433. {
  434. count = ClipBack(pv, inv, outv, count, interpolate);
  435. if (count < 3)
  436. goto out_of_here;
  437. SWAP(inv, outv);
  438. }
  439. if (accept & __D3DCLIPGB_LEFT)
  440. {
  441. count = ClipLeftGB(pv, inv, outv, count, interpolate);
  442. if (count < 3)
  443. goto out_of_here;
  444. SWAP(inv, outv);
  445. }
  446. if (accept & __D3DCLIPGB_RIGHT)
  447. {
  448. count = ClipRightGB(pv, inv, outv, count, interpolate);
  449. if (count < 3)
  450. goto out_of_here;
  451. SWAP(inv, outv);
  452. }
  453. if (accept & __D3DCLIPGB_BOTTOM)
  454. {
  455. count = ClipBottomGB(pv, inv, outv, count, interpolate);
  456. if (count < 3)
  457. goto out_of_here;
  458. SWAP(inv, outv);
  459. }
  460. if (accept & __D3DCLIPGB_TOP)
  461. {
  462. count = ClipTopGB(pv, inv, outv, count, interpolate);
  463. if (count < 3)
  464. goto out_of_here;
  465. SWAP(inv, outv);
  466. }
  467. }
  468. else
  469. {
  470. // If there was clipping by the front plane it is better to
  471. // compute clip code for new vertices and re-compute accept.
  472. // Otherwise we will try to clip by sides when it is not necessary
  473. if (accept & D3DCLIP_FRONT)
  474. {
  475. accept = 0;
  476. for (i = 0; i < count; i++)
  477. {
  478. ClipVertex *p;
  479. p = inv[i];
  480. if (p->clip & (CLIPPED_FRONT))
  481. accept |= ComputeClipCode(pv, p);
  482. else
  483. accept |= p->clip;
  484. }
  485. }
  486. if (accept & D3DCLIP_BACK)
  487. {
  488. count = ClipBack(pv, inv, outv, count, interpolate);
  489. if (count < 3)
  490. goto out_of_here;
  491. SWAP(inv, outv);
  492. }
  493. if (accept & D3DCLIP_LEFT)
  494. {
  495. count = ClipLeft(pv, inv, outv, count, interpolate);
  496. if (count < 3)
  497. goto out_of_here;
  498. SWAP(inv, outv);
  499. }
  500. if (accept & D3DCLIP_RIGHT)
  501. {
  502. count = ClipRight(pv, inv, outv, count, interpolate);
  503. if (count < 3)
  504. goto out_of_here;
  505. SWAP(inv, outv);
  506. }
  507. if (accept & D3DCLIP_BOTTOM)
  508. {
  509. count = ClipBottom(pv, inv, outv, count, interpolate);
  510. if (count < 3)
  511. goto out_of_here;
  512. SWAP(inv, outv);
  513. }
  514. if (accept & D3DCLIP_TOP)
  515. {
  516. count = ClipTop(pv, inv, outv, count, interpolate);
  517. if (count < 3)
  518. goto out_of_here;
  519. SWAP(inv, outv);
  520. }
  521. }
  522. #undef SWAP
  523. ComputeScreenCoordinates(pv, inv, count, &pv->rExtents);
  524. *clipVertexPointer = inv;
  525. pv->ClipperState.current_vbuf = inv;
  526. return count;
  527. out_of_here:
  528. *clipVertexPointer = NULL;
  529. return 0;
  530. }
  531. //*************************************************************************
  532. //
  533. #undef DPF_MODNAME
  534. #define DPF_MODNAME "ClipSingleLine"
  535. int
  536. ClipSingleLine(D3DFE_PROCESSVERTICES *pv,
  537. ClipTriangle *line,
  538. D3DRECTV *extent,
  539. int interpolate)
  540. {
  541. int accept;
  542. D3DVALUE in1, in2;
  543. CD3DFPstate D3DFPstate; // Sets optimal FPU state for D3D.
  544. accept = (line->v[0]->clip | line->v[1]->clip);
  545. pv->ClipperState.clip_color = line->v[0]->color;
  546. pv->ClipperState.clip_specular = line->v[0]->specular;
  547. if (accept & D3DCLIP_FRONT)
  548. if (ClipLineFront(pv, line, interpolate))
  549. goto out_of_here;
  550. if (pv->dwDeviceFlags & D3DDEV_GUARDBAND)
  551. {
  552. // If there was clipping by the front plane it is better to
  553. // compute clip code for new vertices and re-compute accept.
  554. // Otherwise we will try to clip by sides when it is not necessary
  555. if (accept & D3DCLIP_FRONT)
  556. {
  557. ClipVertex * p;
  558. accept = 0;
  559. p = line->v[0];
  560. if (p->clip & CLIPPED_FRONT)
  561. accept |= ComputeClipCodeGB(pv, p);
  562. else
  563. accept |= p->clip;
  564. p = line->v[1];
  565. if (p->clip & CLIPPED_FRONT)
  566. accept |= ComputeClipCodeGB(pv, p);
  567. else
  568. accept |= p->clip;
  569. }
  570. if (accept & D3DCLIP_BACK)
  571. if (ClipLineBack(pv, line, interpolate))
  572. goto out_of_here;
  573. if (accept & __D3DCLIPGB_LEFT)
  574. if (ClipLineLeftGB(pv, line, interpolate))
  575. goto out_of_here;
  576. if (accept & __D3DCLIPGB_RIGHT)
  577. if (ClipLineRightGB(pv, line, interpolate))
  578. goto out_of_here;
  579. if (accept & __D3DCLIPGB_TOP)
  580. if (ClipLineTopGB(pv, line, interpolate))
  581. goto out_of_here;
  582. if (accept & __D3DCLIPGB_BOTTOM)
  583. if (ClipLineBottomGB(pv, line, interpolate))
  584. goto out_of_here;
  585. }
  586. else
  587. {
  588. // If there was clipping by the front plane it is better to
  589. // compute clip code for new vertices and re-compute accept.
  590. // Otherwise we will try to clip by sides when it is not necessary
  591. if (accept & D3DCLIP_FRONT)
  592. {
  593. ClipVertex * p;
  594. accept = 0;
  595. p = line->v[0];
  596. if (p->clip & CLIPPED_FRONT)
  597. accept |= ComputeClipCode(pv, p);
  598. else
  599. accept |= p->clip;
  600. p = line->v[1];
  601. if (p->clip & CLIPPED_FRONT)
  602. accept |= ComputeClipCode(pv, p);
  603. else
  604. accept |= p->clip;
  605. }
  606. if (accept & D3DCLIP_BACK)
  607. if (ClipLineBack(pv, line, interpolate))
  608. goto out_of_here;
  609. if (accept & D3DCLIP_LEFT)
  610. if (ClipLineLeft(pv, line, interpolate))
  611. goto out_of_here;
  612. if (accept & D3DCLIP_RIGHT)
  613. if (ClipLineRight(pv, line, interpolate))
  614. goto out_of_here;
  615. if (accept & D3DCLIP_TOP)
  616. if (ClipLineTop(pv, line, interpolate))
  617. goto out_of_here;
  618. if (accept & D3DCLIP_BOTTOM)
  619. if (ClipLineBottom(pv, line, interpolate))
  620. goto out_of_here;
  621. }
  622. ComputeScreenCoordinates(pv, line->v, 2, extent);
  623. return 1;
  624. out_of_here:
  625. return 0;
  626. } // ClipSingleLine
  627. //----------------------------------------------------------------------
  628. // GenClipFlags() Generates clip flags for a set of FVF
  629. //
  630. #undef DPF_MODNAME
  631. #define DPF_MODNAME "GenClipFlags"
  632. DWORD D3DFE_GenClipFlags(D3DFE_PROCESSVERTICES *pv)
  633. {
  634. DWORD clip_intersection, clip_union;
  635. float left = pv->vcache.minX;
  636. float top = pv->vcache.minY;
  637. float right = pv->vcache.maxX;
  638. float bottom = pv->vcache.maxY;
  639. float leftgb ; // Guard band window
  640. float topgb ;
  641. float rightgb ;
  642. float bottomgb;
  643. DWORD clipZF, clipZB;
  644. DWORD stride = pv->position.dwStride;
  645. clipZF = pv->lpdwRStates[D3DRENDERSTATE_ZENABLE] ? D3DCLIP_FRONT : 0;
  646. clipZB = pv->lpdwRStates[D3DRENDERSTATE_ZENABLE] ? D3DCLIP_BACK : 0;
  647. clip_intersection = (DWORD)~0;
  648. clip_union = (DWORD)0;
  649. if (pv->dwDeviceFlags & D3DDEV_GUARDBAND)
  650. {
  651. leftgb = pv->vcache.minXgb;
  652. topgb = pv->vcache.minYgb;
  653. rightgb = pv->vcache.maxXgb;
  654. bottomgb = pv->vcache.maxYgb;
  655. }
  656. if (pv->dwFlags & D3DDP_DONOTUPDATEEXTENTS)
  657. { /* Only generate clip flags */
  658. D3DTLVERTEX *lpVertices = (D3DTLVERTEX*)pv->position.lpvData;
  659. D3DFE_CLIPCODE *clipCode = pv->lpClipFlags;
  660. DWORD i;
  661. for (i = pv->dwNumVertices; i; i--)
  662. {
  663. DWORD clip = 0;
  664. D3DVALUE x,y,z;
  665. if (lpVertices->rhw < 0)
  666. {
  667. x = -lpVertices->sx;
  668. y = -lpVertices->sy;
  669. z = -lpVertices->sz;
  670. }
  671. else
  672. {
  673. x = lpVertices->sx;
  674. y = lpVertices->sy;
  675. z = lpVertices->sz;
  676. }
  677. if (x < left)
  678. clip |= D3DCLIP_LEFT;
  679. else
  680. if (x >= right)
  681. clip |= D3DCLIP_RIGHT;
  682. if (y < top)
  683. clip |= D3DCLIP_TOP;
  684. else
  685. if (y >= bottom)
  686. clip |= D3DCLIP_BOTTOM;
  687. if (z < 0.0f)
  688. clip |= clipZF;
  689. else
  690. if (z >= 1.0f)
  691. clip |= clipZB;
  692. if (pv->dwDeviceFlags & D3DDEV_GUARDBAND && clip)
  693. {
  694. if (x < leftgb)
  695. clip |= __D3DCLIPGB_LEFT;
  696. else
  697. if (x >= rightgb)
  698. clip |= __D3DCLIPGB_RIGHT;
  699. if (y < topgb)
  700. clip |= __D3DCLIPGB_TOP;
  701. else
  702. if (y >= bottomgb)
  703. clip |= __D3DCLIPGB_BOTTOM;
  704. }
  705. clip_intersection &= clip;
  706. clip_union |= clip;
  707. *clipCode++ = (D3DFE_CLIPCODE)clip;
  708. lpVertices = (D3DTLVERTEX*)((char*)lpVertices + stride);
  709. }
  710. }
  711. else
  712. { /* Generate Clip Flags and Update Extents */
  713. DWORD i;
  714. float minx = pv->rExtents.x1;
  715. float miny = pv->rExtents.y1;
  716. float maxx = pv->rExtents.x2;
  717. float maxy = pv->rExtents.y2;
  718. D3DTLVERTEX *lpVertices = (D3DTLVERTEX*)pv->position.lpvData;
  719. D3DFE_CLIPCODE *clipCode = pv->lpClipFlags;
  720. for (i = pv->dwNumVertices; i; i--)
  721. {
  722. DWORD clip = 0;
  723. D3DVALUE x,y,z;
  724. if (lpVertices->rhw < 0)
  725. {
  726. x = -lpVertices->sx;
  727. y = -lpVertices->sy;
  728. z = -lpVertices->sz;
  729. }
  730. else
  731. {
  732. x = lpVertices->sx;
  733. y = lpVertices->sy;
  734. z = lpVertices->sz;
  735. }
  736. if (x < left)
  737. clip |= D3DCLIP_LEFT;
  738. else
  739. if (x >= right)
  740. clip |= D3DCLIP_RIGHT;
  741. if (y < top)
  742. clip |= D3DCLIP_TOP;
  743. else
  744. if (y >= bottom)
  745. clip |= D3DCLIP_BOTTOM;
  746. if (z < 0.0f)
  747. clip |= clipZF;
  748. else
  749. if (z >= 1.0f)
  750. clip |= clipZB;
  751. if (pv->dwDeviceFlags & D3DDEV_GUARDBAND && clip)
  752. {
  753. if (x < leftgb)
  754. clip |= __D3DCLIPGB_LEFT;
  755. else
  756. if (x >= rightgb)
  757. clip |= __D3DCLIPGB_RIGHT;
  758. if (y < topgb)
  759. clip |= __D3DCLIPGB_TOP;
  760. else
  761. if (y >= bottomgb)
  762. clip |= __D3DCLIPGB_BOTTOM;
  763. }
  764. // Update extents only if the vertex is inside
  765. if (clip == 0 ||
  766. ((pv->dwDeviceFlags & D3DDEV_GUARDBAND) &&
  767. ((clip & ~__D3DCLIP_INGUARDBAND) == 0)))
  768. {
  769. if (x < minx)
  770. minx = x;
  771. if (x > maxx)
  772. maxx = x;
  773. if (y < miny)
  774. miny = y;
  775. if (y > maxy)
  776. maxy = y;
  777. }
  778. clip_intersection &= clip;
  779. clip_union |= clip;
  780. *clipCode++ = (D3DFE_CLIPCODE)clip;
  781. lpVertices = (D3DTLVERTEX*)((char*)lpVertices + stride);
  782. }
  783. pv->rExtents.x1 = minx;
  784. pv->rExtents.y1 = miny;
  785. pv->rExtents.x2 = maxx;
  786. pv->rExtents.y2 = maxy;
  787. }
  788. pv->dwClipIntersection = clip_intersection;
  789. pv->dwClipUnion = clip_union;
  790. return clip_intersection;
  791. } // end of GenClipFlags()