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.

1362 lines
42 KiB

  1. /******************************Module*Header*******************************\
  2. *
  3. * *******************
  4. * * GDI SAMPLE CODE *
  5. * *******************
  6. *
  7. * Module Name: fastfill.c
  8. *
  9. * Fast routine for drawing polygons that aren't complex in shape.
  10. *
  11. * Copyright (c) 1993-1998 Microsoft Corporation
  12. \**************************************************************************/
  13. #include "precomp.h"
  14. #define RIGHT 0
  15. #define LEFT 1
  16. typedef struct _TRAPEZOIDDATA TRAPEZOIDDATA; // Handy forward declaration
  17. typedef VOID (FNTRAPEZOID)(TRAPEZOIDDATA*, LONG, LONG);
  18. // Prototype for trapezoid
  19. // drawing routines
  20. typedef struct _EDGEDATA {
  21. LONG x; // Current x position
  22. LONG dx; // # pixels to advance x on each scan
  23. LONG lError; // Current DDA error
  24. LONG lErrorUp; // DDA error increment on each scan
  25. LONG dN; // Signed delta-y in fixed point form (also known
  26. // as the DDA error adjustment, and used to be
  27. // called 'lErrorDown')
  28. LONG dM; // Signed delta-x in fixed point form
  29. POINTFIX* pptfx; // Points to start of current edge
  30. LONG dptfx; // Delta (in bytes) from pptfx to next point
  31. LONG cy; // Number of scans to go for this edge
  32. LONG bNew; // Set to TRUE when a new DDA must be started
  33. // for the edge.
  34. } EDGEDATA; /* ed, ped */
  35. typedef struct _TRAPEZOIDDATA {
  36. FNTRAPEZOID* pfnTrap; // Pointer to appropriate trapezoid drawing routine,
  37. // or trapezoid clip routine
  38. FNTRAPEZOID* pfnTrapClip;// Pointer to appropriate trapezoid drawing routine
  39. // if doing clipping
  40. PDEV* ppdev; // Pointer to PDEV
  41. EDGEDATA aed[2]; // DDA information for both edges
  42. POINTL ptlBrush; // Brush alignment
  43. LONG yClipTop; // Top of clip rectangle
  44. LONG yClipBottom;// Bottom of clip rectangle
  45. } TRAPEZOIDDATA; /* td, ptd */
  46. /******************************Public*Routine******************************\
  47. * VOID vClipTrapezoid
  48. *
  49. * Clips a trapezoid.
  50. *
  51. * NOTE: This routine assumes that the polygon's dimensions are small
  52. * enough that its QUOTIENT_REMAINDER calculations won't overflow.
  53. * This means that large polygons must never make it here.
  54. *
  55. \**************************************************************************/
  56. VOID vClipTrapezoid(
  57. TRAPEZOIDDATA* ptd,
  58. LONG yTrapTop,
  59. LONG cyTrapezoid)
  60. {
  61. LONG yTrapBottom;
  62. LONG dN;
  63. LONG lNum;
  64. LONG xDelta;
  65. LONG lError;
  66. yTrapBottom = yTrapTop + cyTrapezoid;
  67. if (yTrapTop < ptd->yClipTop)
  68. {
  69. if ((ptd->aed[LEFT].bNew) &&
  70. (yTrapBottom + ptd->aed[LEFT].cy > ptd->yClipTop))
  71. {
  72. dN = ptd->aed[LEFT].dN;
  73. lNum = ptd->aed[LEFT].dM * (ptd->yClipTop - yTrapTop)
  74. + (ptd->aed[LEFT].lError + dN);
  75. if (lNum >= 0)
  76. {
  77. QUOTIENT_REMAINDER(lNum, dN, xDelta, lError);
  78. }
  79. else
  80. {
  81. lNum = -lNum;
  82. QUOTIENT_REMAINDER(lNum, dN, xDelta, lError);
  83. xDelta = -xDelta;
  84. if (lError != 0)
  85. {
  86. xDelta--;
  87. lError = dN - lError;
  88. }
  89. }
  90. ptd->aed[LEFT].x += xDelta;
  91. ptd->aed[LEFT].lError = lError - dN;
  92. }
  93. if ((ptd->aed[RIGHT].bNew) &&
  94. (yTrapBottom + ptd->aed[RIGHT].cy > ptd->yClipTop))
  95. {
  96. dN = ptd->aed[RIGHT].dN;
  97. lNum = ptd->aed[RIGHT].dM * (ptd->yClipTop - yTrapTop)
  98. + (ptd->aed[RIGHT].lError + dN);
  99. if (lNum >= 0)
  100. {
  101. QUOTIENT_REMAINDER(lNum, dN, xDelta, lError);
  102. }
  103. else
  104. {
  105. lNum = -lNum;
  106. QUOTIENT_REMAINDER(lNum, dN, xDelta, lError);
  107. xDelta = -xDelta;
  108. if (lError != 0)
  109. {
  110. xDelta--;
  111. lError = dN - lError;
  112. }
  113. }
  114. ptd->aed[RIGHT].x += xDelta;
  115. ptd->aed[RIGHT].lError = lError - dN;
  116. }
  117. }
  118. // If this trapezoid vertically intersects our clip rectangle, draw it:
  119. if ((yTrapBottom > ptd->yClipTop) &&
  120. (yTrapTop < ptd->yClipBottom))
  121. {
  122. if (yTrapTop <= ptd->yClipTop)
  123. {
  124. yTrapTop = ptd->yClipTop;
  125. // Have to let trapezoid drawer know that it has to load
  126. // its DDAs for very first trapezoid drawn:
  127. ptd->aed[RIGHT].bNew = TRUE;
  128. ptd->aed[LEFT].bNew = TRUE;
  129. }
  130. if (yTrapBottom >= ptd->yClipBottom)
  131. {
  132. yTrapBottom = ptd->yClipBottom;
  133. }
  134. ptd->pfnTrapClip(ptd, yTrapTop, yTrapBottom - yTrapTop);
  135. }
  136. }
  137. /******************************Public*Routine******************************\
  138. * VOID vIoSolidTrapezoid
  139. *
  140. * Draws a solid trapezoid using a software DDA.
  141. *
  142. \**************************************************************************/
  143. VOID vIoSolidTrapezoid(
  144. TRAPEZOIDDATA* ptd,
  145. LONG yTrapezoid,
  146. LONG cyTrapezoid)
  147. {
  148. PDEV* ppdev;
  149. LONG xOffset;
  150. LONG lLeftError;
  151. LONG xLeft;
  152. LONG lRightError;
  153. LONG xRight;
  154. LONG lTmp;
  155. EDGEDATA edTmp;
  156. ppdev = ptd->ppdev;
  157. xOffset = ppdev->xOffset;
  158. yTrapezoid += ppdev->yOffset;
  159. // If the left and right edges are vertical, simply output as
  160. // a rectangle:
  161. if (((ptd->aed[LEFT].lErrorUp | ptd->aed[RIGHT].lErrorUp) == 0) &&
  162. ((ptd->aed[LEFT].dx | ptd->aed[RIGHT].dx) == 0))
  163. {
  164. /////////////////////////////////////////////////////////////////
  165. // Vertical-edge special case
  166. xLeft = ptd->aed[LEFT].x + xOffset;
  167. xRight = ptd->aed[RIGHT].x + xOffset;
  168. if (xLeft > xRight)
  169. {
  170. SWAP(xLeft, xRight, lTmp);
  171. SWAP(ptd->aed[LEFT], ptd->aed[RIGHT], edTmp);
  172. }
  173. if (xLeft < xRight)
  174. {
  175. IO_FIFO_WAIT(ppdev, 6);
  176. IO_MAJ_AXIS_PCNT(ppdev, xRight - xLeft - 1);
  177. IO_MIN_AXIS_PCNT(ppdev, cyTrapezoid - 1);
  178. IO_ABS_CUR_Y(ppdev, yTrapezoid);
  179. IO_ABS_CUR_X(ppdev, xLeft); // Already absolute
  180. IO_CMD(ppdev, (RECTANGLE_FILL | DRAWING_DIR_TBLRXM |
  181. DRAW | DIR_TYPE_XY |
  182. LAST_PIXEL_ON | MULTIPLE_PIXELS |
  183. WRITE));
  184. IO_MIN_AXIS_PCNT(ppdev, 0);
  185. }
  186. }
  187. else
  188. {
  189. IO_FIFO_WAIT(ppdev, 1);
  190. IO_ABS_CUR_Y(ppdev, yTrapezoid);
  191. yTrapezoid += cyTrapezoid + 1; // One past end scan
  192. lLeftError = ptd->aed[LEFT].lError;
  193. xLeft = ptd->aed[LEFT].x + xOffset;
  194. lRightError = ptd->aed[RIGHT].lError;
  195. xRight = ptd->aed[RIGHT].x + xOffset;
  196. while (TRUE)
  197. {
  198. /////////////////////////////////////////////////////////////////
  199. // Run the DDAs
  200. if (xLeft < xRight)
  201. {
  202. IO_FIFO_WAIT(ppdev, 3);
  203. IO_MAJ_AXIS_PCNT(ppdev, xRight - xLeft - 1);
  204. IO_ABS_CUR_X(ppdev, xLeft);
  205. IO_CMD(ppdev, (RECTANGLE_FILL | DRAWING_DIR_TBLRXM |
  206. DRAW | DIR_TYPE_XY |
  207. LAST_PIXEL_ON | MULTIPLE_PIXELS |
  208. WRITE));
  209. }
  210. else if (xLeft > xRight)
  211. {
  212. // We don't bother optimizing this case because we should
  213. // rarely get self-intersecting polygons (if we're slow,
  214. // the app gets what it deserves).
  215. SWAP(xLeft, xRight, lTmp);
  216. SWAP(lLeftError, lRightError, lTmp);
  217. SWAP(ptd->aed[LEFT], ptd->aed[RIGHT], edTmp);
  218. continue;
  219. }
  220. else
  221. {
  222. IO_FIFO_WAIT(ppdev, 1);
  223. IO_ABS_CUR_Y(ppdev, yTrapezoid - cyTrapezoid);
  224. }
  225. // Advance the right wall:
  226. xRight += ptd->aed[RIGHT].dx;
  227. lRightError += ptd->aed[RIGHT].lErrorUp;
  228. if (lRightError >= 0)
  229. {
  230. lRightError -= ptd->aed[RIGHT].dN;
  231. xRight++;
  232. }
  233. // Advance the left wall:
  234. xLeft += ptd->aed[LEFT].dx;
  235. lLeftError += ptd->aed[LEFT].lErrorUp;
  236. if (lLeftError >= 0)
  237. {
  238. lLeftError -= ptd->aed[LEFT].dN;
  239. xLeft++;
  240. }
  241. cyTrapezoid--;
  242. if (cyTrapezoid == 0)
  243. break;
  244. }
  245. ptd->aed[LEFT].lError = lLeftError;
  246. ptd->aed[LEFT].x = xLeft - xOffset;
  247. ptd->aed[RIGHT].lError = lRightError;
  248. ptd->aed[RIGHT].x = xRight - xOffset;
  249. }
  250. }
  251. /******************************Public*Routine******************************\
  252. * VOID vIoPatternTrapezoid
  253. *
  254. * Draws a patterned trapezoid using a software DDA.
  255. *
  256. \**************************************************************************/
  257. VOID vIoPatternTrapezoid(
  258. TRAPEZOIDDATA* ptd,
  259. LONG yTrapezoid,
  260. LONG cyTrapezoid)
  261. {
  262. PDEV* ppdev;
  263. LONG xOffset;
  264. LONG lLeftError;
  265. LONG xLeft;
  266. LONG lRightError;
  267. LONG xRight;
  268. LONG lTmp;
  269. EDGEDATA edTmp;
  270. ppdev = ptd->ppdev;
  271. xOffset = ppdev->xOffset;
  272. yTrapezoid += ppdev->yOffset;
  273. // If the left and right edges are vertical, simply output as
  274. // a rectangle:
  275. if (((ptd->aed[LEFT].lErrorUp | ptd->aed[RIGHT].lErrorUp) == 0) &&
  276. ((ptd->aed[LEFT].dx | ptd->aed[RIGHT].dx) == 0))
  277. {
  278. /////////////////////////////////////////////////////////////////
  279. // Vertical-edge special case
  280. xLeft = ptd->aed[LEFT].x + xOffset;
  281. xRight = ptd->aed[RIGHT].x + xOffset;
  282. if (xLeft > xRight)
  283. {
  284. SWAP(xLeft, xRight, lTmp);
  285. SWAP(ptd->aed[LEFT], ptd->aed[RIGHT], edTmp);
  286. }
  287. if (xLeft < xRight)
  288. {
  289. IO_FIFO_WAIT(ppdev, 6);
  290. IO_MAJ_AXIS_PCNT(ppdev, xRight - xLeft - 1);
  291. IO_MIN_AXIS_PCNT(ppdev, cyTrapezoid - 1);
  292. IO_ABS_DEST_Y(ppdev, yTrapezoid);
  293. IO_ABS_DEST_X(ppdev, xLeft); // Already absolute
  294. IO_CMD(ppdev, (PATTERN_FILL | DRAWING_DIR_TBLRXM |
  295. DRAW | WRITE));
  296. IO_MIN_AXIS_PCNT(ppdev, 0);
  297. }
  298. }
  299. else
  300. {
  301. IO_FIFO_WAIT(ppdev, 1);
  302. IO_ABS_DEST_Y(ppdev, yTrapezoid);
  303. yTrapezoid += cyTrapezoid + 1; // One past end scan
  304. lLeftError = ptd->aed[LEFT].lError;
  305. xLeft = ptd->aed[LEFT].x + xOffset;
  306. lRightError = ptd->aed[RIGHT].lError;
  307. xRight = ptd->aed[RIGHT].x + xOffset;
  308. while (TRUE)
  309. {
  310. /////////////////////////////////////////////////////////////////
  311. // Run the DDAs
  312. if (xLeft < xRight)
  313. {
  314. IO_FIFO_WAIT(ppdev, 3);
  315. IO_MAJ_AXIS_PCNT(ppdev, xRight - xLeft - 1);
  316. IO_ABS_DEST_X(ppdev, xLeft);
  317. IO_CMD(ppdev, (PATTERN_FILL | DRAWING_DIR_TBLRXM |
  318. DRAW | WRITE));
  319. }
  320. else if (xLeft > xRight)
  321. {
  322. // We don't bother optimizing this case because we should
  323. // rarely get self-intersecting polygons (if we're slow,
  324. // the app gets what it deserves).
  325. SWAP(xLeft, xRight, lTmp);
  326. SWAP(lLeftError, lRightError, lTmp);
  327. SWAP(ptd->aed[LEFT], ptd->aed[RIGHT], edTmp);
  328. continue;
  329. }
  330. else
  331. {
  332. IO_FIFO_WAIT(ppdev, 1);
  333. IO_ABS_DEST_Y(ppdev, yTrapezoid - cyTrapezoid);
  334. }
  335. // Advance the right wall:
  336. xRight += ptd->aed[RIGHT].dx;
  337. lRightError += ptd->aed[RIGHT].lErrorUp;
  338. if (lRightError >= 0)
  339. {
  340. lRightError -= ptd->aed[RIGHT].dN;
  341. xRight++;
  342. }
  343. // Advance the left wall:
  344. xLeft += ptd->aed[LEFT].dx;
  345. lLeftError += ptd->aed[LEFT].lErrorUp;
  346. if (lLeftError >= 0)
  347. {
  348. lLeftError -= ptd->aed[LEFT].dN;
  349. xLeft++;
  350. }
  351. cyTrapezoid--;
  352. if (cyTrapezoid == 0)
  353. break;
  354. }
  355. ptd->aed[LEFT].lError = lLeftError;
  356. ptd->aed[LEFT].x = xLeft - xOffset;
  357. ptd->aed[RIGHT].lError = lRightError;
  358. ptd->aed[RIGHT].x = xRight - xOffset;
  359. }
  360. }
  361. /******************************Public*Routine******************************\
  362. * VOID vIoTrapezoidSetup
  363. *
  364. * Initialize the hardware and some state for doing trapezoids.
  365. *
  366. \**************************************************************************/
  367. VOID vIoTrapezoidSetup(
  368. PDEV* ppdev,
  369. ULONG rop4,
  370. ULONG iSolidColor,
  371. RBRUSH* prb,
  372. POINTL* pptlBrush,
  373. TRAPEZOIDDATA* ptd,
  374. RECTL* prclClip) // NULL if no clipping
  375. {
  376. ULONG ulHwForeMix;
  377. BRUSHENTRY* pbe;
  378. ptd->ppdev = ppdev;
  379. ulHwForeMix = gaulHwMixFromRop2[(rop4 >> 2) & 0xf];
  380. if (iSolidColor != -1)
  381. {
  382. /////////////////////////////////////////////////////////////////
  383. // Setup the hardware for solid colours
  384. ptd->pfnTrap = vIoSolidTrapezoid;
  385. // We initialize the hardware for the colour, mix, pixel operation,
  386. // rectangle height of one, and the y position for the first scan:
  387. if (DEPTH32(ppdev))
  388. {
  389. IO_FIFO_WAIT(ppdev, 5);
  390. IO_FRGD_COLOR32(ppdev, iSolidColor);
  391. }
  392. else
  393. {
  394. IO_FIFO_WAIT(ppdev, 4);
  395. IO_FRGD_COLOR(ppdev, iSolidColor);
  396. }
  397. IO_FRGD_MIX(ppdev, FOREGROUND_COLOR | ulHwForeMix);
  398. IO_PIX_CNTL(ppdev, ALL_ONES);
  399. IO_MIN_AXIS_PCNT(ppdev, 0);
  400. }
  401. else
  402. {
  403. /////////////////////////////////////////////////////////////////
  404. // Setup for patterns
  405. BOOL bNotTransparent = (((rop4 >> 8) & 0xff) == (rop4 & 0xff));
  406. ptd->pfnTrap = vIoPatternTrapezoid;
  407. pbe = prb->pbe;
  408. if (bNotTransparent)
  409. {
  410. // Force normal brush at 24bpp on s3 968
  411. // Normal brush:
  412. IO_FIFO_WAIT(ppdev, 5);
  413. IO_ABS_CUR_X(ppdev, pbe->x);
  414. IO_ABS_CUR_Y(ppdev, pbe->y);
  415. IO_PIX_CNTL(ppdev, ALL_ONES);
  416. IO_FRGD_MIX(ppdev, SRC_DISPLAY_MEMORY | ulHwForeMix);
  417. IO_MIN_AXIS_PCNT(ppdev, 0);
  418. }
  419. else
  420. {
  421. // Transparent brush:
  422. if (DEPTH32(ppdev))
  423. {
  424. IO_FIFO_WAIT(ppdev, 4);
  425. IO_FRGD_COLOR32(ppdev, prb->ulForeColor);
  426. IO_RD_MASK32(ppdev, 1); // Pick a plane, any plane
  427. IO_FIFO_WAIT(ppdev, 6);
  428. }
  429. else
  430. {
  431. IO_FIFO_WAIT(ppdev, 8);
  432. IO_FRGD_COLOR(ppdev, prb->ulForeColor);
  433. IO_RD_MASK(ppdev, 1); // Pick a plane, any plane
  434. }
  435. IO_ABS_CUR_X(ppdev, pbe->x);
  436. IO_ABS_CUR_Y(ppdev, pbe->y);
  437. IO_PIX_CNTL(ppdev, DISPLAY_MEMORY);
  438. IO_FRGD_MIX(ppdev, FOREGROUND_COLOR | ulHwForeMix);
  439. IO_BKGD_MIX(ppdev, BACKGROUND_COLOR | LEAVE_ALONE);
  440. IO_MIN_AXIS_PCNT(ppdev, 0);
  441. }
  442. }
  443. if (prclClip != NULL)
  444. {
  445. ptd->pfnTrapClip = ptd->pfnTrap;
  446. ptd->pfnTrap = vClipTrapezoid;
  447. ptd->yClipTop = prclClip->top;
  448. ptd->yClipBottom = prclClip->bottom;
  449. IO_FIFO_WAIT(ppdev, 2);
  450. IO_ABS_SCISSORS_L(ppdev, ppdev->xOffset + prclClip->left);
  451. IO_ABS_SCISSORS_R(ppdev, ppdev->xOffset + prclClip->right - 1);
  452. }
  453. }
  454. /******************************Public*Routine******************************\
  455. * VOID vMmSolidTrapezoid
  456. *
  457. * Draws a solid trapezoid using a software DDA.
  458. *
  459. \**************************************************************************/
  460. VOID vMmSolidTrapezoid(
  461. TRAPEZOIDDATA* ptd,
  462. LONG yTrapezoid,
  463. LONG cyTrapezoid)
  464. {
  465. PDEV* ppdev;
  466. BYTE* pjMmBase;
  467. LONG xOffset;
  468. LONG lLeftError;
  469. LONG xLeft;
  470. LONG lRightError;
  471. LONG xRight;
  472. LONG lTmp;
  473. EDGEDATA edTmp;
  474. LONG cFifo;
  475. ppdev = ptd->ppdev;
  476. pjMmBase = ppdev->pjMmBase;
  477. xOffset = ppdev->xOffset;
  478. yTrapezoid += ppdev->yOffset;
  479. // If the left and right edges are vertical, simply output as
  480. // a rectangle:
  481. if (((ptd->aed[LEFT].lErrorUp | ptd->aed[RIGHT].lErrorUp) == 0) &&
  482. ((ptd->aed[LEFT].dx | ptd->aed[RIGHT].dx) == 0))
  483. {
  484. /////////////////////////////////////////////////////////////////
  485. // Vertical-edge special case
  486. xLeft = ptd->aed[LEFT].x + xOffset;
  487. xRight = ptd->aed[RIGHT].x + xOffset;
  488. if (xLeft > xRight)
  489. {
  490. SWAP(xLeft, xRight, lTmp);
  491. SWAP(ptd->aed[LEFT], ptd->aed[RIGHT], edTmp);
  492. }
  493. if (xLeft < xRight)
  494. {
  495. // Bliter doesn't handle negative X's with clipping
  496. // (at least at 24BPP on the 968).
  497. // So do SW clipping at X=0
  498. if (xRight > 0)
  499. {
  500. IO_FIFO_WAIT(ppdev, 6);
  501. if (xLeft <= 0)
  502. {
  503. MM_MAJ_AXIS_PCNT(ppdev, pjMmBase, xRight - 1);
  504. MM_ABS_CUR_X(ppdev, pjMmBase, 0);
  505. }
  506. else
  507. {
  508. MM_MAJ_AXIS_PCNT(ppdev, pjMmBase, xRight - xLeft - 1);
  509. MM_ABS_CUR_X(ppdev, pjMmBase, xLeft); // Already absolute
  510. }
  511. MM_MIN_AXIS_PCNT(ppdev, pjMmBase, cyTrapezoid - 1);
  512. MM_ABS_CUR_Y(ppdev, pjMmBase, yTrapezoid);
  513. MM_CMD(ppdev, pjMmBase, (RECTANGLE_FILL | DRAWING_DIR_TBLRXM |
  514. DRAW | DIR_TYPE_XY |
  515. LAST_PIXEL_ON | MULTIPLE_PIXELS |
  516. WRITE));
  517. MM_MIN_AXIS_PCNT(ppdev, pjMmBase, 0);
  518. }
  519. }
  520. }
  521. else
  522. {
  523. IO_ALL_EMPTY(ppdev);
  524. MM_ABS_CUR_Y(ppdev, pjMmBase, yTrapezoid);
  525. cFifo = MM_ALL_EMPTY_FIFO_COUNT - 1;
  526. yTrapezoid += cyTrapezoid + 1; // One past end scan
  527. lLeftError = ptd->aed[LEFT].lError;
  528. xLeft = ptd->aed[LEFT].x + xOffset;
  529. lRightError = ptd->aed[RIGHT].lError;
  530. xRight = ptd->aed[RIGHT].x + xOffset;
  531. while (TRUE)
  532. {
  533. /////////////////////////////////////////////////////////////////
  534. // Run the DDAs
  535. if (xLeft < xRight)
  536. {
  537. // Bliter doesn't handle negative X's with clipping
  538. // (at least at 24BPP on the 968).
  539. // So do SW clipping at X=0
  540. if (xRight > 0)
  541. {
  542. // We get a little tricky here and try to amortize the cost
  543. // of the read for checking the FIFO count on the S3.
  544. cFifo -= 3;
  545. if (cFifo < 0)
  546. {
  547. IO_ALL_EMPTY(ppdev);
  548. cFifo = MM_ALL_EMPTY_FIFO_COUNT - 3;
  549. }
  550. if (xLeft <= 0)
  551. {
  552. MM_MAJ_AXIS_PCNT(ppdev, pjMmBase, xRight - 1);
  553. MM_ABS_CUR_X(ppdev, pjMmBase, 0);
  554. }
  555. else
  556. {
  557. MM_MAJ_AXIS_PCNT(ppdev, pjMmBase, xRight - xLeft - 1);
  558. MM_ABS_CUR_X(ppdev, pjMmBase, xLeft); // Already absolute
  559. }
  560. MM_CMD(ppdev, pjMmBase, (RECTANGLE_FILL | DRAWING_DIR_TBLRXM |
  561. DRAW | DIR_TYPE_XY |
  562. LAST_PIXEL_ON | MULTIPLE_PIXELS |
  563. WRITE));
  564. }
  565. else
  566. {
  567. // SW clipping at X==0 skipped the blit completely but
  568. // the Y value must still be updated
  569. cFifo -= 1;
  570. if (cFifo < 0)
  571. {
  572. IO_ALL_EMPTY(ppdev);
  573. cFifo = MM_ALL_EMPTY_FIFO_COUNT - 1;
  574. }
  575. MM_ABS_CUR_Y(ppdev, pjMmBase, yTrapezoid - cyTrapezoid);
  576. }
  577. }
  578. else if (xLeft > xRight)
  579. {
  580. // We don't bother optimizing this case because we should
  581. // rarely get self-intersecting polygons (if we're slow,
  582. // the app gets what it deserves).
  583. SWAP(xLeft, xRight, lTmp);
  584. SWAP(lLeftError, lRightError, lTmp);
  585. SWAP(ptd->aed[LEFT], ptd->aed[RIGHT], edTmp);
  586. continue;
  587. }
  588. else
  589. {
  590. cFifo -= 1;
  591. if (cFifo < 0)
  592. {
  593. IO_ALL_EMPTY(ppdev);
  594. cFifo = MM_ALL_EMPTY_FIFO_COUNT - 1;
  595. }
  596. MM_ABS_CUR_Y(ppdev, pjMmBase, yTrapezoid - cyTrapezoid);
  597. }
  598. // Advance the right wall:
  599. xRight += ptd->aed[RIGHT].dx;
  600. lRightError += ptd->aed[RIGHT].lErrorUp;
  601. if (lRightError >= 0)
  602. {
  603. lRightError -= ptd->aed[RIGHT].dN;
  604. xRight++;
  605. }
  606. // Advance the left wall:
  607. xLeft += ptd->aed[LEFT].dx;
  608. lLeftError += ptd->aed[LEFT].lErrorUp;
  609. if (lLeftError >= 0)
  610. {
  611. lLeftError -= ptd->aed[LEFT].dN;
  612. xLeft++;
  613. }
  614. cyTrapezoid--;
  615. if (cyTrapezoid == 0)
  616. break;
  617. }
  618. ptd->aed[LEFT].lError = lLeftError;
  619. ptd->aed[LEFT].x = xLeft - xOffset;
  620. ptd->aed[RIGHT].lError = lRightError;
  621. ptd->aed[RIGHT].x = xRight - xOffset;
  622. }
  623. }
  624. /******************************Public*Routine******************************\
  625. * VOID vMmPatternTrapezoid
  626. *
  627. * Draws a patterned trapezoid using a software DDA.
  628. *
  629. \**************************************************************************/
  630. VOID vMmPatternTrapezoid(
  631. TRAPEZOIDDATA* ptd,
  632. LONG yTrapezoid,
  633. LONG cyTrapezoid)
  634. {
  635. PDEV* ppdev;
  636. BYTE* pjMmBase;
  637. LONG xOffset;
  638. LONG lLeftError;
  639. LONG xLeft;
  640. LONG lRightError;
  641. LONG xRight;
  642. LONG lTmp;
  643. EDGEDATA edTmp;
  644. LONG cFifo;
  645. ppdev = ptd->ppdev;
  646. pjMmBase = ppdev->pjMmBase;
  647. xOffset = ppdev->xOffset;
  648. yTrapezoid += ppdev->yOffset;
  649. // If the left and right edges are vertical, simply output as
  650. // a rectangle:
  651. if (((ptd->aed[LEFT].lErrorUp | ptd->aed[RIGHT].lErrorUp) == 0) &&
  652. ((ptd->aed[LEFT].dx | ptd->aed[RIGHT].dx) == 0))
  653. {
  654. /////////////////////////////////////////////////////////////////
  655. // Vertical-edge special case
  656. xLeft = ptd->aed[LEFT].x + xOffset;
  657. xRight = ptd->aed[RIGHT].x + xOffset;
  658. if (xLeft > xRight)
  659. {
  660. SWAP(xLeft, xRight, lTmp);
  661. SWAP(ptd->aed[LEFT], ptd->aed[RIGHT], edTmp);
  662. }
  663. if (xLeft < xRight)
  664. {
  665. // Bliter doesn't handle negative X's with clipping
  666. // (at least at 24BPP on the 968).
  667. // So do SW clipping at X=0
  668. if (xRight > 0)
  669. {
  670. IO_FIFO_WAIT(ppdev, 6);
  671. if (xLeft <= 0)
  672. {
  673. MM_MAJ_AXIS_PCNT(ppdev, pjMmBase, xRight - 1);
  674. MM_ABS_DEST_X(ppdev, pjMmBase, 0);
  675. }
  676. else
  677. {
  678. MM_MAJ_AXIS_PCNT(ppdev, pjMmBase, xRight - xLeft - 1);
  679. MM_ABS_DEST_X(ppdev, pjMmBase, xLeft); // Already absolute
  680. }
  681. MM_MIN_AXIS_PCNT(ppdev, pjMmBase, cyTrapezoid - 1);
  682. MM_ABS_DEST_Y(ppdev, pjMmBase, yTrapezoid);
  683. MM_CMD(ppdev, pjMmBase, (PATTERN_FILL | DRAWING_DIR_TBLRXM |
  684. DRAW | WRITE));
  685. MM_MIN_AXIS_PCNT(ppdev, pjMmBase, 0);
  686. }
  687. }
  688. }
  689. else
  690. {
  691. IO_ALL_EMPTY(ppdev);
  692. MM_ABS_DEST_Y(ppdev, pjMmBase, yTrapezoid);
  693. cFifo = MM_ALL_EMPTY_FIFO_COUNT - 1;
  694. yTrapezoid += cyTrapezoid + 1; // One past end scan
  695. lLeftError = ptd->aed[LEFT].lError;
  696. xLeft = ptd->aed[LEFT].x + xOffset;
  697. lRightError = ptd->aed[RIGHT].lError;
  698. xRight = ptd->aed[RIGHT].x + xOffset;
  699. while (TRUE)
  700. {
  701. /////////////////////////////////////////////////////////////////
  702. // Run the DDAs
  703. if (xLeft < xRight)
  704. {
  705. // Bliter doesn't handle negative X's with clipping
  706. // (at least at 24BPP on the 968).
  707. // So do SW clipping at X=0
  708. if (xRight > 0)
  709. {
  710. // We get a little tricky here and try to amortize the cost
  711. // of the read for checking the FIFO count on the S3.
  712. cFifo -= 3;
  713. if (cFifo < 0)
  714. {
  715. IO_ALL_EMPTY(ppdev);
  716. cFifo = MM_ALL_EMPTY_FIFO_COUNT - 3;
  717. }
  718. if (xLeft <= 0)
  719. {
  720. MM_MAJ_AXIS_PCNT(ppdev, pjMmBase, xRight - 1);
  721. MM_ABS_DEST_X(ppdev, pjMmBase, 0);
  722. }
  723. else
  724. {
  725. MM_MAJ_AXIS_PCNT(ppdev, pjMmBase, xRight - xLeft - 1);
  726. MM_ABS_DEST_X(ppdev, pjMmBase, xLeft);
  727. }
  728. MM_CMD(ppdev, pjMmBase, (PATTERN_FILL | DRAWING_DIR_TBLRXM |
  729. DRAW | WRITE));
  730. }
  731. else
  732. {
  733. // SW clipping at X==0 skipped the blit completely but
  734. // the Y value must still be updated
  735. cFifo -= 1;
  736. if (cFifo < 0)
  737. {
  738. IO_ALL_EMPTY(ppdev);
  739. cFifo = MM_ALL_EMPTY_FIFO_COUNT - 1;
  740. }
  741. MM_ABS_DEST_Y(ppdev, pjMmBase, yTrapezoid - cyTrapezoid);
  742. }
  743. }
  744. else if (xLeft > xRight)
  745. {
  746. // We don't bother optimizing this case because we should
  747. // rarely get self-intersecting polygons (if we're slow,
  748. // the app gets what it deserves).
  749. SWAP(xLeft, xRight, lTmp);
  750. SWAP(lLeftError, lRightError, lTmp);
  751. SWAP(ptd->aed[LEFT], ptd->aed[RIGHT], edTmp);
  752. continue;
  753. }
  754. else
  755. {
  756. cFifo -= 1;
  757. if (cFifo < 0)
  758. {
  759. IO_ALL_EMPTY(ppdev);
  760. cFifo = MM_ALL_EMPTY_FIFO_COUNT - 1;
  761. }
  762. MM_ABS_DEST_Y(ppdev, pjMmBase, yTrapezoid - cyTrapezoid);
  763. }
  764. // Advance the right wall:
  765. xRight += ptd->aed[RIGHT].dx;
  766. lRightError += ptd->aed[RIGHT].lErrorUp;
  767. if (lRightError >= 0)
  768. {
  769. lRightError -= ptd->aed[RIGHT].dN;
  770. xRight++;
  771. }
  772. // Advance the left wall:
  773. xLeft += ptd->aed[LEFT].dx;
  774. lLeftError += ptd->aed[LEFT].lErrorUp;
  775. if (lLeftError >= 0)
  776. {
  777. lLeftError -= ptd->aed[LEFT].dN;
  778. xLeft++;
  779. }
  780. cyTrapezoid--;
  781. if (cyTrapezoid == 0)
  782. break;
  783. }
  784. ptd->aed[LEFT].lError = lLeftError;
  785. ptd->aed[LEFT].x = xLeft - xOffset;
  786. ptd->aed[RIGHT].lError = lRightError;
  787. ptd->aed[RIGHT].x = xRight - xOffset;
  788. }
  789. }
  790. /******************************Public*Routine******************************\
  791. * VOID vMmTrapezoidSetup
  792. *
  793. * Initialize the hardware and some state for doing trapezoids.
  794. *
  795. \**************************************************************************/
  796. VOID vMmTrapezoidSetup(
  797. PDEV* ppdev,
  798. ULONG rop4,
  799. ULONG iSolidColor,
  800. RBRUSH* prb,
  801. POINTL* pptlBrush,
  802. TRAPEZOIDDATA* ptd,
  803. RECTL* prclClip) // NULL if no clipping
  804. {
  805. BYTE* pjMmBase;
  806. ULONG ulHwForeMix;
  807. BRUSHENTRY* pbe;
  808. ptd->ppdev = ppdev;
  809. pjMmBase = ppdev->pjMmBase;
  810. ulHwForeMix = gaulHwMixFromRop2[(rop4 >> 2) & 0xf];
  811. if (iSolidColor != -1)
  812. {
  813. /////////////////////////////////////////////////////////////////
  814. // Setup the hardware for solid colours
  815. ptd->pfnTrap = vMmSolidTrapezoid;
  816. // We initialize the hardware for the colour, mix, pixel operation,
  817. // rectangle height of one, and the y position for the first scan:
  818. IO_FIFO_WAIT(ppdev, 4);
  819. MM_FRGD_COLOR(ppdev, pjMmBase, iSolidColor);
  820. MM_FRGD_MIX(ppdev, pjMmBase, FOREGROUND_COLOR | ulHwForeMix);
  821. MM_PIX_CNTL(ppdev, pjMmBase, ALL_ONES);
  822. MM_MIN_AXIS_PCNT(ppdev, pjMmBase, 0);
  823. }
  824. else
  825. {
  826. /////////////////////////////////////////////////////////////////
  827. // Setup for patterns
  828. ptd->pfnTrap = vMmPatternTrapezoid;
  829. pbe = prb->pbe;
  830. if (((rop4 >> 8) & 0xff) == (rop4 & 0xff))
  831. {
  832. // Normal brush:
  833. IO_FIFO_WAIT(ppdev, 5);
  834. MM_ABS_CUR_X(ppdev, pjMmBase, pbe->x);
  835. MM_ABS_CUR_Y(ppdev, pjMmBase, pbe->y);
  836. MM_PIX_CNTL(ppdev, pjMmBase, ALL_ONES);
  837. MM_FRGD_MIX(ppdev, pjMmBase, SRC_DISPLAY_MEMORY | ulHwForeMix);
  838. MM_MIN_AXIS_PCNT(ppdev, pjMmBase, 0);
  839. }
  840. else
  841. {
  842. // Transparent brush:
  843. IO_FIFO_WAIT(ppdev, 8);
  844. MM_FRGD_COLOR(ppdev, pjMmBase, prb->ulForeColor);
  845. MM_RD_MASK(ppdev, pjMmBase, 1); // Pick a plane, any plane
  846. MM_ABS_CUR_X(ppdev, pjMmBase, pbe->x);
  847. MM_ABS_CUR_Y(ppdev, pjMmBase, pbe->y);
  848. MM_PIX_CNTL(ppdev, pjMmBase, DISPLAY_MEMORY);
  849. MM_FRGD_MIX(ppdev, pjMmBase, FOREGROUND_COLOR | ulHwForeMix);
  850. MM_BKGD_MIX(ppdev, pjMmBase, BACKGROUND_COLOR | LEAVE_ALONE);
  851. MM_MIN_AXIS_PCNT(ppdev, pjMmBase, 0);
  852. }
  853. }
  854. if (prclClip != NULL)
  855. {
  856. ptd->pfnTrapClip = ptd->pfnTrap;
  857. ptd->pfnTrap = vClipTrapezoid;
  858. ptd->yClipTop = prclClip->top;
  859. ptd->yClipBottom = prclClip->bottom;
  860. IO_FIFO_WAIT(ppdev, 2);
  861. MM_ABS_SCISSORS_L(ppdev, pjMmBase, ppdev->xOffset + prclClip->left);
  862. MM_ABS_SCISSORS_R(ppdev, pjMmBase, ppdev->xOffset + prclClip->right - 1);
  863. }
  864. }
  865. /******************************Public*Routine******************************\
  866. * BOOL bFastFill
  867. *
  868. * Draws a non-complex, unclipped polygon. 'Non-complex' is defined as
  869. * having only two edges that are monotonic increasing in 'y'. That is,
  870. * the polygon cannot have more than one disconnected segment on any given
  871. * scan. Note that the edges of the polygon can self-intersect, so hourglass
  872. * shapes are permissible. This restriction permits this routine to run two
  873. * simultaneous DDAs, and no sorting of the edges is required.
  874. *
  875. * Note that NT's fill convention is different from that of Win 3.1 or Win95.
  876. * With the additional complication of fractional end-points, our convention
  877. * is the same as in 'X-Windows'. But a DDA is a DDA is a DDA, so once you
  878. * figure out how we compute the DDA terms for NT, you're golden.
  879. *
  880. * This routine handles patterns only when the S3 hardware patterns can be
  881. * used. The reason for this is that once the S3 pattern initialization is
  882. * done, pattern fills appear to the programmer exactly the same as solid
  883. * fills (with the slight difference that different registers and commands
  884. * are used). Handling 'vIoFillPatSlow' style patterns in this routine
  885. * would be non-trivial...
  886. *
  887. * We take advantage of the fact that the S3 automatically advances the
  888. * current 'y' to the following scan whenever a rectangle is output so that
  889. * we have to write to the accelerator three times for every scan: one for
  890. * the new 'x', one for the new 'width', and one for the drawing command.
  891. *
  892. * Returns TRUE if the polygon was drawn; FALSE if the polygon was complex.
  893. *
  894. \**************************************************************************/
  895. BOOL bFastFill(
  896. PDEV* ppdev,
  897. LONG cEdges, // Includes close figure edge
  898. POINTFIX* pptfxFirst,
  899. ULONG rop4,
  900. ULONG iSolidColor,
  901. RBRUSH* prb,
  902. POINTL* pptlBrush,
  903. RECTL* prclClip) // NULL if no clipping
  904. {
  905. LONG yTrapezoid; // Top scan for next trapezoid
  906. LONG cyTrapezoid; // Number of scans in current trapezoid
  907. LONG yStart; // y-position of start point in current edge
  908. LONG dM; // Edge delta in FIX units in x direction
  909. LONG dN; // Edge delta in FIX units in y direction
  910. LONG i;
  911. POINTFIX* pptfxLast; // Points to the last point in the polygon array
  912. POINTFIX* pptfxTop; // Points to the top-most point in the polygon
  913. POINTFIX* pptfxOld; // Start point in current edge
  914. POINTFIX* pptfxScan; // Current edge pointer for finding pptfxTop
  915. LONG cScanEdges; // Number of edges scanned to find pptfxTop
  916. // (doesn't include the closefigure edge)
  917. LONG iEdge;
  918. LONG lQuotient;
  919. LONG lRemainder;
  920. BYTE* pjBase;
  921. TRAPEZOIDDATA td; // Edge data and stuff
  922. EDGEDATA* ped; // Points to current edge being processed
  923. /////////////////////////////////////////////////////////////////
  924. // See if the polygon is convex
  925. pptfxScan = pptfxFirst;
  926. pptfxTop = pptfxFirst; // Assume for now that the first
  927. // point in path is the topmost
  928. pptfxLast = pptfxFirst + cEdges - 1;
  929. if (cEdges <= 2)
  930. goto ReturnTrue;
  931. // 'pptfxScan' will always point to the first point in the current
  932. // edge, and 'cScanEdges' will the number of edges remaining, including
  933. // the current one:
  934. cScanEdges = cEdges - 1; // The number of edges, not counting close figure
  935. if ((pptfxScan + 1)->y > pptfxScan->y)
  936. {
  937. // Collect all downs:
  938. do {
  939. if (--cScanEdges == 0)
  940. goto SetUpForFilling;
  941. pptfxScan++;
  942. } while ((pptfxScan + 1)->y >= pptfxScan->y);
  943. // Collect all ups:
  944. do {
  945. if (--cScanEdges == 0)
  946. goto SetUpForFillingCheck;
  947. pptfxScan++;
  948. } while ((pptfxScan + 1)->y <= pptfxScan->y);
  949. // Collect all downs:
  950. pptfxTop = pptfxScan;
  951. do {
  952. if ((pptfxScan + 1)->y > pptfxFirst->y)
  953. break;
  954. if (--cScanEdges == 0)
  955. goto SetUpForFilling;
  956. pptfxScan++;
  957. } while ((pptfxScan + 1)->y >= pptfxScan->y);
  958. goto ReturnFalse;
  959. }
  960. else
  961. {
  962. // Collect all ups:
  963. do {
  964. pptfxTop++; // We increment this now because we
  965. // want it to point to the very last
  966. // point if we early out in the next
  967. // statement...
  968. if (--cScanEdges == 0)
  969. goto SetUpForFilling;
  970. } while ((pptfxTop + 1)->y <= pptfxTop->y);
  971. // Collect all downs:
  972. pptfxScan = pptfxTop;
  973. do {
  974. if (--cScanEdges == 0)
  975. goto SetUpForFilling;
  976. pptfxScan++;
  977. } while ((pptfxScan + 1)->y >= pptfxScan->y);
  978. // Collect all ups:
  979. do {
  980. if ((pptfxScan + 1)->y < pptfxFirst->y)
  981. break;
  982. if (--cScanEdges == 0)
  983. goto SetUpForFilling;
  984. pptfxScan++;
  985. } while ((pptfxScan + 1)->y <= pptfxScan->y);
  986. goto ReturnFalse;
  987. }
  988. SetUpForFillingCheck:
  989. // We check to see if the end of the current edge is higher
  990. // than the top edge we've found so far:
  991. if ((pptfxScan + 1)->y < pptfxTop->y)
  992. pptfxTop = pptfxScan + 1;
  993. SetUpForFilling:
  994. /////////////////////////////////////////////////////////////////
  995. // Some Initialization
  996. td.aed[LEFT].pptfx = pptfxTop;
  997. td.aed[RIGHT].pptfx = pptfxTop;
  998. yTrapezoid = (pptfxTop->y + 15) >> 4;
  999. // Make sure we initialize the DDAs appropriately:
  1000. td.aed[LEFT].cy = 0;
  1001. td.aed[RIGHT].cy = 0;
  1002. // Guess as to the ordering of the points:
  1003. td.aed[LEFT].dptfx = sizeof(POINTFIX);
  1004. td.aed[RIGHT].dptfx = -(LONG) sizeof(POINTFIX);
  1005. if ((ppdev->flCaps & (CAPS_MM_IO | CAPS_16_ENTRY_FIFO))
  1006. == (CAPS_MM_IO | CAPS_16_ENTRY_FIFO))
  1007. {
  1008. vMmTrapezoidSetup(ppdev, rop4, iSolidColor, prb, pptlBrush, &td,
  1009. prclClip);
  1010. }
  1011. else
  1012. {
  1013. vIoTrapezoidSetup(ppdev, rop4, iSolidColor, prb, pptlBrush, &td,
  1014. prclClip);
  1015. }
  1016. NewTrapezoid:
  1017. /////////////////////////////////////////////////////////////////
  1018. // DDA initialization
  1019. for (iEdge = 1; iEdge >= 0; iEdge--)
  1020. {
  1021. ped = &td.aed[iEdge];
  1022. ped->bNew = FALSE;
  1023. if (ped->cy == 0)
  1024. {
  1025. // Our trapezoid drawing routine may want to be notified when
  1026. // it will have to reset its DDA to start a new edge:
  1027. ped->bNew = TRUE;
  1028. // Need a new DDA:
  1029. do {
  1030. cEdges--;
  1031. if (cEdges < 0)
  1032. goto ResetClippingAndReturnTrue;
  1033. // Find the next left edge, accounting for wrapping:
  1034. pptfxOld = ped->pptfx;
  1035. ped->pptfx = (POINTFIX*) ((BYTE*) ped->pptfx + ped->dptfx);
  1036. if (ped->pptfx < pptfxFirst)
  1037. ped->pptfx = pptfxLast;
  1038. else if (ped->pptfx > pptfxLast)
  1039. ped->pptfx = pptfxFirst;
  1040. // Have to find the edge that spans yTrapezoid:
  1041. ped->cy = ((ped->pptfx->y + 15) >> 4) - yTrapezoid;
  1042. // With fractional coordinate end points, we may get edges
  1043. // that don't cross any scans, in which case we try the
  1044. // next one:
  1045. } while (ped->cy <= 0);
  1046. // 'pptfx' now points to the end point of the edge spanning
  1047. // the scan 'yTrapezoid'.
  1048. dN = ped->pptfx->y - pptfxOld->y;
  1049. dM = ped->pptfx->x - pptfxOld->x;
  1050. ASSERTDD(dN > 0, "Should be going down only");
  1051. // Compute the DDA increment terms:
  1052. ped->dM = dM; // Not used for software trapezoid
  1053. if (dM < 0)
  1054. {
  1055. dM = -dM;
  1056. if (dM < dN) // Can't be '<='
  1057. {
  1058. ped->dx = -1;
  1059. ped->lErrorUp = dN - dM;
  1060. }
  1061. else
  1062. {
  1063. QUOTIENT_REMAINDER(dM, dN, lQuotient, lRemainder);
  1064. ped->dx = -lQuotient; // - dM / dN
  1065. ped->lErrorUp = lRemainder; // dM % dN
  1066. if (ped->lErrorUp > 0)
  1067. {
  1068. ped->dx--;
  1069. ped->lErrorUp = dN - ped->lErrorUp;
  1070. }
  1071. }
  1072. }
  1073. else
  1074. {
  1075. if (dM < dN) // Can't be '<='
  1076. {
  1077. ped->dx = 0;
  1078. ped->lErrorUp = dM;
  1079. }
  1080. else
  1081. {
  1082. QUOTIENT_REMAINDER(dM, dN, lQuotient, lRemainder);
  1083. ped->dx = lQuotient; // dM / dN
  1084. ped->lErrorUp = lRemainder; // dM % dN
  1085. }
  1086. }
  1087. ped->dN = dN; // DDA limit
  1088. ped->lError = -1; // Error is initially zero (add dN - 1 for
  1089. // the ceiling, but subtract off dN so that
  1090. // we can check the sign instead of comparing
  1091. // to dN)
  1092. ped->x = pptfxOld->x;
  1093. yStart = pptfxOld->y;
  1094. if ((yStart & 15) != 0)
  1095. {
  1096. // Advance to the next integer y coordinate
  1097. for (i = 16 - (yStart & 15); i != 0; i--)
  1098. {
  1099. ped->x += ped->dx;
  1100. ped->lError += ped->lErrorUp;
  1101. if (ped->lError >= 0)
  1102. {
  1103. ped->lError -= ped->dN;
  1104. ped->x++;
  1105. }
  1106. }
  1107. }
  1108. if ((ped->x & 15) != 0)
  1109. {
  1110. ped->lError -= ped->dN * (16 - (ped->x & 15));
  1111. ped->x += 15; // We'll want the ceiling in just a bit...
  1112. }
  1113. // Chop off those fractional bits:
  1114. ped->x >>= 4;
  1115. ped->lError >>= 4;
  1116. }
  1117. }
  1118. cyTrapezoid = min(td.aed[LEFT].cy, td.aed[RIGHT].cy); // # of scans in this trap
  1119. td.aed[LEFT].cy -= cyTrapezoid;
  1120. td.aed[RIGHT].cy -= cyTrapezoid;
  1121. td.pfnTrap(&td, yTrapezoid, cyTrapezoid);
  1122. yTrapezoid += cyTrapezoid;
  1123. goto NewTrapezoid;
  1124. ResetClippingAndReturnTrue:
  1125. if (prclClip != NULL)
  1126. {
  1127. vResetClipping(ppdev);
  1128. }
  1129. ReturnTrue:
  1130. return(TRUE);
  1131. ReturnFalse:
  1132. return(FALSE);
  1133. }