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.

1416 lines
48 KiB

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