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.

2507 lines
89 KiB

  1. /*************************************************************************\
  2. * Module Name: Lines.c
  3. *
  4. * Contains most of the required GDI line support. Supports drawing
  5. * lines in short 'strips' when clipping is complex or coordinates
  6. * are too large to be drawn by the line hardware.
  7. *
  8. * Copyright (c) 1990-1995 Microsoft Corporation
  9. \**************************************************************************/
  10. #include "precomp.h"
  11. ///////////////////////////////////////////////////////////////////////
  12. // We have to be careful of arithmetic overflow in a number of places.
  13. // Fortunately, the compiler is guaranteed to natively support 64-bit
  14. // signed LONGLONGs and 64-bit unsigned DWORDLONGs.
  15. //
  16. // UUInt32x32To64(a, b) is a macro defined in 'winnt.h' that multiplies
  17. // two 32-bit ULONGs to produce a 64-bit DWORDLONG result.
  18. //
  19. // UInt64By32To32 is our own macro to divide a 64-bit DWORDLONG by
  20. // a 32-bit ULONG to produce a 32-bit ULONG result.
  21. //
  22. // UInt64Mod32To32 is our own macro to modulus a 64-bit DWORDLONG by
  23. // a 32-bit ULONG to produce a 32-bit ULONG result.
  24. //
  25. // 64 bit divides are usually very expensive. Since it's very rare
  26. // that we'll get lines where the upper 32 bits of the 64 bit result
  27. // are used, we can almost always use 32-bit ULONG divides. We still
  28. // must correctly handle the larger cases:
  29. #define UInt64Div32To32(a, b) \
  30. ((((DWORDLONG)(a)) > ULONG_MAX) ? \
  31. (ULONG)((DWORDLONG)(a) / (ULONG)(b)) : \
  32. (ULONG)((ULONG)(a) / (ULONG)(b)))
  33. #define UInt64Mod32To32(a, b) \
  34. ((((DWORDLONG)(a)) > ULONG_MAX) ? \
  35. (ULONG)((DWORDLONG)(a) % (ULONG)(b)) : \
  36. (ULONG)((ULONG)(a) % (ULONG)(b)))
  37. #define SWAPL(x,y,t) {t = x; x = y; y = t;}
  38. FLONG gaflRound[] = {
  39. FL_H_ROUND_DOWN | FL_V_ROUND_DOWN, // no flips
  40. FL_H_ROUND_DOWN | FL_V_ROUND_DOWN, // FL_FLIP_D
  41. FL_H_ROUND_DOWN, // FL_FLIP_V
  42. FL_V_ROUND_DOWN, // FL_FLIP_V | FL_FLIP_D
  43. FL_V_ROUND_DOWN, // FL_FLIP_SLOPE_ONE
  44. 0xbaadf00d, // FL_FLIP_SLOPE_ONE | FL_FLIP_D
  45. FL_H_ROUND_DOWN, // FL_FLIP_SLOPE_ONE | FL_FLIP_V
  46. 0xbaadf00d // FL_FLIP_SLOPE_ONE | FL_FLIP_V | FL_FLIP_D
  47. };
  48. //////////////////////////////////////////////////////////////////////////
  49. // General defines for bHardwareLine
  50. BOOL bHardwareLine(PDEV*, POINTFIX*, POINTFIX*, LONG, MIX, RECTL*);
  51. #define HW_FLIP_D 0x0001L // Diagonal flip
  52. #define HW_FLIP_V 0x0002L // Vertical flip
  53. #define HW_FLIP_H 0x0004L // Horizontal flip
  54. #define HW_FLIP_SLOPE_ONE 0x0008L // Normalized line has exactly slope one
  55. #define HW_FLIP_MASK (HW_FLIP_D | HW_FLIP_V | HW_FLIP_H)
  56. #define HW_X_ROUND_DOWN 0x0100L // x = 1/2 rounds down in value
  57. #define HW_Y_ROUND_DOWN 0x0200L // y = 1/2 rounds down in value
  58. LONG gaiDir[] = { 0, 1, 7, 6, 3, 2, 4, 5 };
  59. FLONG gaflHardwareRound[] = {
  60. HW_X_ROUND_DOWN | HW_Y_ROUND_DOWN, // | | |
  61. HW_X_ROUND_DOWN | HW_Y_ROUND_DOWN, // | | | FLIP_D
  62. HW_X_ROUND_DOWN, // | | FLIP_V |
  63. HW_Y_ROUND_DOWN, // | | FLIP_V | FLIP_D
  64. HW_Y_ROUND_DOWN, // | FLIP_H | |
  65. HW_X_ROUND_DOWN, // | FLIP_H | | FLIP_D
  66. 0, // | FLIP_H | FLIP_V |
  67. 0, // | FLIP_H | FLIP_V | FLIP_D
  68. HW_Y_ROUND_DOWN, // SLOPE_ONE | | |
  69. 0xffffffff, // SLOPE_ONE | | | FLIP_D
  70. HW_X_ROUND_DOWN, // SLOPE_ONE | | FLIP_V |
  71. 0xffffffff, // SLOPE_ONE | | FLIP_V | FLIP_D
  72. HW_Y_ROUND_DOWN, // SLOPE_ONE | FLIP_H | |
  73. 0xffffffff, // SLOPE_ONE | FLIP_H | | FLIP_D
  74. HW_X_ROUND_DOWN, // SLOPE_ONE | FLIP_H | FLIP_V |
  75. 0xffffffff // SLOPE_ONE | FLIP_H | FLIP_V | FLIP_D
  76. };
  77. //////////////////////////////////////////////////////////////////////////
  78. // ATI specific defines
  79. // The Mach32 hardware can have 12 bits of significance for the error and
  80. // step terms:
  81. #define NUM_DDA_BITS 12
  82. LONG gai32Direction[] = {
  83. LAST_PEL_OFF | XPOSITIVE | YPOSITIVE | 0, // Octant 0
  84. LAST_PEL_OFF | XPOSITIVE | YPOSITIVE | YMAJOR, // Octant 1
  85. LAST_PEL_OFF | XPOSITIVE | 0 | 0, // Octant 7
  86. LAST_PEL_OFF | XPOSITIVE | 0 | YMAJOR, // Octant 6
  87. LAST_PEL_OFF | 0 | YPOSITIVE | 0, // Octant 3
  88. LAST_PEL_OFF | 0 | YPOSITIVE | YMAJOR, // Octant 2
  89. LAST_PEL_OFF | 0 | 0 | 0, // Octant 4
  90. LAST_PEL_OFF | 0 | 0 | YMAJOR, // Octant 5
  91. };
  92. LONG gai64Direction[] = {
  93. DST_CNTL_LastPel | DST_CNTL_XDir | DST_CNTL_YDir | 0,
  94. DST_CNTL_LastPel | DST_CNTL_XDir | DST_CNTL_YDir | DST_CNTL_YMajor,
  95. DST_CNTL_LastPel | DST_CNTL_XDir | 0 | 0,
  96. DST_CNTL_LastPel | DST_CNTL_XDir | 0 | DST_CNTL_YMajor,
  97. DST_CNTL_LastPel | 0 | DST_CNTL_YDir | 0,
  98. DST_CNTL_LastPel | 0 | DST_CNTL_YDir | DST_CNTL_YMajor,
  99. DST_CNTL_LastPel | 0 | 0 | 0,
  100. DST_CNTL_LastPel | 0 | 0 | DST_CNTL_YMajor,
  101. };
  102. /******************************Public*Routine******************************\
  103. * BOOL bLines(ppdev, pptfxFirst, pptfxBuf, cptfx, pls,
  104. * prclClip, apfn[], flStart)
  105. *
  106. * Computes the DDA for the line and gets ready to draw it. Puts the
  107. * pixel data into an array of strips, and calls a strip routine to
  108. * do the actual drawing.
  109. *
  110. * Doing NT Lines Right
  111. * --------------------
  112. *
  113. * In NT, all lines are given to the device driver in fractional
  114. * coordinates, in a 28.4 fixed point format. The lower 4 bits are
  115. * fractional for sub-pixel positioning.
  116. *
  117. * Note that you CANNOT! just round the coordinates to integers
  118. * and pass the results to your favorite integer Bresenham routine!!
  119. * (Unless, of course, you have such a high resolution device that
  120. * nobody will notice -- not likely for a display device.) The
  121. * fractions give a more accurate rendering of the line -- this is
  122. * important for things like our Bezier curves, which would have 'kinks'
  123. * if the points in its polyline approximation were rounded to integers.
  124. *
  125. * Unfortunately, for fractional lines there is more setup work to do
  126. * a DDA than for integer lines. However, the main loop is exactly
  127. * the same (and can be done entirely with 32 bit math).
  128. *
  129. * If You've Got Hardware That Does Bresenham
  130. * ------------------------------------------
  131. *
  132. * A lot of hardware limits DDA error terms to 'n' bits. With fractional
  133. * coordinates, 4 bits are given to the fractional part, letting
  134. * you draw in hardware only those lines that lie entirely in a 2^(n-4)
  135. * by 2^(n-4) pixel space.
  136. *
  137. * And you still have to correctly draw those lines with coordinates
  138. * outside that space! Remember that the screen is only a viewport
  139. * onto a 28.4 by 28.4 space -- if any part of the line is visible
  140. * you MUST render it precisely, regardless of where the end points lie.
  141. * So even if you do it in software, somewhere you'll have to have a
  142. * 32 bit DDA routine.
  143. *
  144. * Our Implementation
  145. * ------------------
  146. *
  147. * We employ a run length slice algorithm: our DDA calculates the
  148. * number of pixels that are in each row (or 'strip') of pixels.
  149. *
  150. * We've separated the running of the DDA and the drawing of pixels:
  151. * we run the DDA for several iterations and store the results in
  152. * a 'strip' buffer (which are the lengths of consecutive pixel rows of
  153. * the line), then we crank up a 'strip drawer' that will draw all the
  154. * strips in the buffer.
  155. *
  156. * We also employ a 'half-flip' to reduce the number of strip
  157. * iterations we need to do in the DDA and strip drawing loops: when a
  158. * (normalized) line's slope is more than 1/2, we do a final flip
  159. * about the line y = (1/2)x. So now, instead of each strip being
  160. * consecutive horizontal or vertical pixel rows, each strip is composed
  161. * of those pixels aligned in 45 degree rows. So a line like (0, 0) to
  162. * (128, 128) would generate only one strip.
  163. *
  164. * We also always draw only left-to-right.
  165. *
  166. * Styled lines may have arbitrary style patterns. We specially
  167. * optimize the default patterns (and call them 'masked' styles).
  168. *
  169. * The DDA Derivation
  170. * ------------------
  171. *
  172. * Here is how I like to think of the DDA calculation.
  173. *
  174. * We employ Knuth's "diamond rule": rendering a one-pixel-wide line
  175. * can be thought of as dragging a one-pixel-wide by one-pixel-high
  176. * diamond along the true line. Pixel centers lie on the integer
  177. * coordinates, and so we light any pixel whose center gets covered
  178. * by the "drag" region (John D. Hobby, Journal of the Association
  179. * for Computing Machinery, Vol. 36, No. 2, April 1989, pp. 209-229).
  180. *
  181. * We must define which pixel gets lit when the true line falls
  182. * exactly half-way between two pixels. In this case, we follow
  183. * the rule: when two pels are equidistant, the upper or left pel
  184. * is illuminated, unless the slope is exactly one, in which case
  185. * the upper or right pel is illuminated. (So we make the edges
  186. * of the diamond exclusive, except for the top and left vertices,
  187. * which are inclusive, unless we have slope one.)
  188. *
  189. * This metric decides what pixels should be on any line BEFORE it is
  190. * flipped around for our calculation. Having a consistent metric
  191. * this way will let our lines blend nicely with our curves. The
  192. * metric also dictates that we will never have one pixel turned on
  193. * directly above another that's turned on. We will also never have
  194. * a gap; i.e., there will be exactly one pixel turned on for each
  195. * column between the start and end points. All that remains to be
  196. * done is to decide how many pixels should be turned on for each row.
  197. *
  198. * So lines we draw will consist of varying numbers of pixels on
  199. * successive rows, for example:
  200. *
  201. * ******
  202. * *****
  203. * ******
  204. * *****
  205. *
  206. * We'll call each set of pixels on a row a "strip".
  207. *
  208. * (Please remember that our coordinate space has the origin as the
  209. * upper left pixel on the screen; postive y is down and positive x
  210. * is right.)
  211. *
  212. * Device coordinates are specified as fixed point 28.4 numbers,
  213. * where the first 28 bits are the integer coordinate, and the last
  214. * 4 bits are the fraction. So coordinates may be thought of as
  215. * having the form (x, y) = (M/F, N/F) where F is the constant scaling
  216. * factor F = 2^4 = 16, and M and N are 32 bit integers.
  217. *
  218. * Consider the line from (M0/F, N0/F) to (M1/F, N1/F) which runs
  219. * left-to-right and whose slope is in the first octant, and let
  220. * dM = M1 - M0 and dN = N1 - N0. Then dM >= 0, dN >= 0 and dM >= dN.
  221. *
  222. * Since the slope of the line is less than 1, the edges of the
  223. * drag region are created by the top and bottom vertices of the
  224. * diamond. At any given pixel row y of the line, we light those
  225. * pixels whose centers are between the left and right edges.
  226. *
  227. * Let mL(n) denote the line representing the left edge of the drag
  228. * region. On pixel row j, the column of the first pixel to be
  229. * lit is
  230. *
  231. * iL(j) = ceiling( mL(j * F) / F)
  232. *
  233. * Since the line's slope is less than one:
  234. *
  235. * iL(j) = ceiling( mL([j + 1/2] F) / F )
  236. *
  237. * Recall the formula for our line:
  238. *
  239. * n(m) = (dN / dM) (m - M0) + N0
  240. *
  241. * m(n) = (dM / dN) (n - N0) + M0
  242. *
  243. * Since the line's slope is less than one, the line representing
  244. * the left edge of the drag region is the original line offset
  245. * by 1/2 pixel in the y direction:
  246. *
  247. * mL(n) = (dM / dN) (n - F/2 - N0) + M0
  248. *
  249. * From this we can figure out the column of the first pixel that
  250. * will be lit on row j, being careful of rounding (if the left
  251. * edge lands exactly on an integer point, the pixel at that
  252. * point is not lit because of our rounding convention):
  253. *
  254. * iL(j) = floor( mL(j F) / F ) + 1
  255. *
  256. * = floor( ((dM / dN) (j F - F/2 - N0) + M0) / F ) + 1
  257. *
  258. * = floor( F dM j - F/2 dM - N0 dM + dN M0) / F dN ) + 1
  259. *
  260. * F dM j - [ dM (N0 + F/2) - dN M0 ]
  261. * = floor( ---------------------------------- ) + 1
  262. * F dN
  263. *
  264. * dM j - [ dM (N0 + F/2) - dN M0 ] / F
  265. * = floor( ------------------------------------ ) + 1 (1)
  266. * dN
  267. *
  268. * = floor( (dM j + alpha) / dN ) + 1
  269. *
  270. * where
  271. *
  272. * alpha = - [ dM (N0 + F/2) - dN M0 ] / F
  273. *
  274. * We use equation (1) to calculate the DDA: there are iL(j+1) - iL(j)
  275. * pixels in row j. Because we are always calculating iL(j) for
  276. * integer quantities of j, we note that the only fractional term
  277. * is constant, and so we can 'throw away' the fractional bits of
  278. * alpha:
  279. *
  280. * beta = floor( - [ dM (N0 + F/2) - dN M0 ] / F ) (2)
  281. *
  282. * so
  283. *
  284. * iL(j) = floor( (dM j + beta) / dN ) + 1 (3)
  285. *
  286. * for integers j.
  287. *
  288. * Note if iR(j) is the line's rightmost pixel on row j, that
  289. * iR(j) = iL(j + 1) - 1.
  290. *
  291. * Similarly, rewriting equation (1) as a function of column i,
  292. * we can determine, given column i, on which pixel row j is the line
  293. * lit:
  294. *
  295. * dN i + [ dM (N0 + F/2) - dN M0 ] / F
  296. * j(i) = ceiling( ------------------------------------ ) - 1
  297. * dM
  298. *
  299. * Floors are easier to compute, so we can rewrite this:
  300. *
  301. * dN i + [ dM (N0 + F/2) - dN M0 ] / F + dM - 1/F
  302. * j(i) = floor( ----------------------------------------------- ) - 1
  303. * dM
  304. *
  305. * dN i + [ dM (N0 + F/2) - dN M0 ] / F + dM - 1/F - dM
  306. * = floor( ---------------------------------------------------- )
  307. * dM
  308. *
  309. * dN i + [ dM (N0 + F/2) - dN M0 - 1 ] / F
  310. * = floor( ---------------------------------------- )
  311. * dM
  312. *
  313. * We can once again wave our hands and throw away the fractional bits
  314. * of the remainder term:
  315. *
  316. * j(i) = floor( (dN i + gamma) / dM ) (4)
  317. *
  318. * where
  319. *
  320. * gamma = floor( [ dM (N0 + F/2) - dN M0 - 1 ] / F ) (5)
  321. *
  322. * We now note that
  323. *
  324. * beta = -gamma - 1 = ~gamma (6)
  325. *
  326. * To draw the pixels of the line, we could evaluate (3) on every scan
  327. * line to determine where the strip starts. Of course, we don't want
  328. * to do that because that would involve a multiply and divide for every
  329. * scan. So we do everything incrementally.
  330. *
  331. * We would like to easily compute c , the number of pixels on scan j:
  332. * j
  333. *
  334. * c = iL(j + 1) - iL(j)
  335. * j
  336. *
  337. * = floor((dM (j + 1) + beta) / dN) - floor((dM j + beta) / dN) (7)
  338. *
  339. * This may be rewritten as
  340. *
  341. * c = floor(i + r / dN) - floor(i + r / dN) (8)
  342. * j j+1 j+1 j j
  343. *
  344. * where i , i are integers and r < dN, r < dN.
  345. * j j+1 j j+1
  346. *
  347. * Rewriting (7) again:
  348. *
  349. * c = floor(i + r / dN + dM / dN) - floor(i + r / dN)
  350. * j j j j j
  351. *
  352. *
  353. * = floor((r + dM) / dN) - floor(r / dN)
  354. * j j
  355. *
  356. * This may be rewritten as
  357. *
  358. * c = dI + floor((r + dR) / dN) - floor(r / dN)
  359. * j j j
  360. *
  361. * where dI + dR / dN = dM / dN, dI is an integer and dR < dN.
  362. *
  363. * r is the remainder (or "error") term in the DDA loop: r / dN
  364. * j j
  365. * is the exact fraction of a pixel at which the strip ends. To go
  366. * on to the next scan and compute c we need to know r .
  367. * j+1 j+1
  368. *
  369. * So in the main loop of the DDA:
  370. *
  371. * c = dI + floor((r + dR) / dN) and r = (r + dR) % dN
  372. * j j j+1 j
  373. *
  374. * and we know r < dN, r < dN, and dR < dN.
  375. * j j+1
  376. *
  377. * We have derived the DDA only for lines in the first octant; to
  378. * handle other octants we do the common trick of flipping the line
  379. * to the first octant by first making the line left-to-right by
  380. * exchanging the end-points, then flipping about the lines y = 0 and
  381. * y = x, as necessary. We must record the transformation so we can
  382. * undo them later.
  383. *
  384. * We must also be careful of how the flips affect our rounding. If
  385. * to get the line to the first octant we flipped about x = 0, we now
  386. * have to be careful to round a y value of 1/2 up instead of down as
  387. * we would for a line originally in the first octant (recall that
  388. * "In the case where two pels are equidistant, the upper or left
  389. * pel is illuminated...").
  390. *
  391. * To account for this rounding when running the DDA, we shift the line
  392. * (or not) in the y direction by the smallest amount possible. That
  393. * takes care of rounding for the DDA, but we still have to be careful
  394. * about the rounding when determining the first and last pixels to be
  395. * lit in the line.
  396. *
  397. * Determining The First And Last Pixels In The Line
  398. * -------------------------------------------------
  399. *
  400. * Fractional coordinates also make it harder to determine which pixels
  401. * will be the first and last ones in the line. We've already taken
  402. * the fractional coordinates into account in calculating the DDA, but
  403. * the DDA cannot tell us which are the end pixels because it is quite
  404. * happy to calculate pixels on the line from minus infinity to positive
  405. * infinity.
  406. *
  407. * The diamond rule determines the start and end pixels. (Recall that
  408. * the sides are exclusive except for the left and top vertices.)
  409. * This convention can be thought of in another way: there are diamonds
  410. * around the pixels, and wherever the true line crosses a diamond,
  411. * that pel is illuminated.
  412. *
  413. * Consider a line where we've done the flips to the first octant, and the
  414. * floor of the start coordinates is the origin:
  415. *
  416. * +-----------------------> +x
  417. * |
  418. * | 0 1
  419. * | 0123456789abcdef
  420. * |
  421. * | 0 00000000?1111111
  422. * | 1 00000000 1111111
  423. * | 2 0000000 111111
  424. * | 3 000000 11111
  425. * | 4 00000 ** 1111
  426. * | 5 0000 ****1
  427. * | 6 000 1***
  428. * | 7 00 1 ****
  429. * | 8 ? ***
  430. * | 9 22 3 ****
  431. * | a 222 33 ***
  432. * | b 2222 333 ****
  433. * | c 22222 3333 **
  434. * | d 222222 33333
  435. * | e 2222222 333333
  436. * | f 22222222 3333333
  437. * |
  438. * | 2 3
  439. * v
  440. * +y
  441. *
  442. * If the start of the line lands on the diamond around pixel 0 (shown by
  443. * the '0' region here), pixel 0 is the first pel in the line. The same
  444. * is true for the other pels.
  445. *
  446. * A little more work has to be done if the line starts in the
  447. * 'nether-land' between the diamonds (as illustrated by the '*' line):
  448. * the first pel lit is the first diamond crossed by the line (pixel 1 in
  449. * our example). This calculation is determined by the DDA or slope of
  450. * the line.
  451. *
  452. * If the line starts exactly half way between two adjacent pixels
  453. * (denoted here by the '?' spots), the first pixel is determined by our
  454. * round-down convention (and is dependent on the flips done to
  455. * normalize the line).
  456. *
  457. * Last Pel Exclusive
  458. * ------------------
  459. *
  460. * To eliminate repeatedly lit pels between continuous connected lines,
  461. * we employ a last-pel exclusive convention: if the line ends exactly on
  462. * the diamond around a pel, that pel is not lit. (This eliminates the
  463. * checks we had in the old code to see if we were re-lighting pels.)
  464. *
  465. * The Half Flip
  466. * -------------
  467. *
  468. * To make our run length algorithm more efficient, we employ a "half
  469. * flip". If after normalizing to the first octant, the slope is more
  470. * than 1/2, we subtract the y coordinate from the x coordinate. This
  471. * has the effect of reflecting the coordinates through the line of slope
  472. * 1/2. Note that the diagonal gets mapped into the x-axis after a half
  473. * flip.
  474. *
  475. * How Many Bits Do We Need, Anyway?
  476. * ---------------------------------
  477. *
  478. * Note that if the line is visible on your screen, you must light up
  479. * exactly the correct pixels, no matter where in the 28.4 x 28.4 device
  480. * space the end points of the line lie (meaning you must handle 32 bit
  481. * DDAs, you can certainly have optimized cases for lesser DDAs).
  482. *
  483. * We move the origin to (floor(M0 / F), floor(N0 / F)), so when we
  484. * calculate gamma from (5), we know that 0 <= M0, N0 < F. And we
  485. * are in the first octant, so dM >= dN. Then we know that gamma can
  486. * be in the range [(-1/2)dM, (3/2)dM]. The DDI guarantees us that
  487. * valid lines will have dM and dN values at most 31 bits (unsigned)
  488. * of significance. So gamma requires 33 bits of significance (we store
  489. * this as a 64 bit number for convenience).
  490. *
  491. * When running through the DDA loop, r + dR can have a value in the
  492. * j
  493. * range 0 <= r < 2 dN; thus the result must be a 32 bit unsigned value.
  494. * j
  495. *
  496. * Testing Lines
  497. * -------------
  498. *
  499. * To be NT compliant, a display driver must exactly adhere to GIQ,
  500. * which means that for any given line, the driver must light exactly
  501. * the same pels as does GDI. This can be tested using the Guiman tool
  502. * provided elsewhere in the DDK, and 'ZTest', which draws random lines
  503. * on the screen and to a bitmap, and compares the results.
  504. *
  505. * If You've Got Line Hardware
  506. * ---------------------------
  507. *
  508. * If your hardware already adheres to GIQ, you're all set. Otherwise
  509. * you'll want to look at the sample code and read the following:
  510. *
  511. * 1) You'll want to special case integer-only lines, since they require
  512. * less processing time and are more common (CAD programs will probably
  513. * only ever give integer lines). GDI does not provide a flag saying
  514. * that all lines in a path are integer lines; consequently, you will
  515. * have to explicitly check every line.
  516. *
  517. * 2) You are required to correctly draw any line in the 28.4 device
  518. * space that intersects the viewport. If you have less than 32 bits
  519. * of significance in the hardware for the Bresenham terms, extremely
  520. * long lines would overflow the hardware. For such (rare) cases, you
  521. * can fall back to strip-drawing code (or if your display is a frame
  522. * buffer, fall back to the engine).
  523. *
  524. * 3) If you can explicitly set the Bresenham terms in your hardware, you
  525. * can draw non-integer lines using the hardware. If your hardware has
  526. * 'n' bits of precision, you can draw GIQ lines that are up to 2^(n-5)
  527. * pels long (4 bits are required for the fractional part, and one bit is
  528. * used as a sign bit). Note that integer lines don't require the 4
  529. * fractional bits, so if you special case them as in 1), you can do
  530. * integer lines that are up to 2^(n - 1) pels long. See the
  531. * 'bHardwareLine' routine for an example.
  532. *
  533. \**************************************************************************/
  534. BOOL bLines(
  535. PDEV* ppdev,
  536. POINTFIX* pptfxFirst, // Start of first line
  537. POINTFIX* pptfxBuf, // Pointer to buffer of all remaining lines
  538. RUN* prun, // Pointer to runs if doing complex clipping
  539. ULONG cptfx, // Number of points in pptfxBuf or number of runs
  540. // in prun
  541. LINESTATE* pls, // Colour and style info
  542. RECTL* prclClip, // Pointer to clip rectangle if doing simple clipping
  543. PFNSTRIP apfn[], // Array of strip functions
  544. FLONG flStart, // Flags for each line, which is a combination of:
  545. // FL_SIMPLE_CLIP
  546. // FL_COMPLEX_CLIP
  547. // FL_STYLED
  548. // FL_LAST_PEL_INCLUSIVE
  549. // - Should be set only for all integer lines,
  550. // and can't be used with FL_COMPLEX_CLIP
  551. LONG iSolidColor,
  552. MIX mix)
  553. {
  554. ULONG M0;
  555. ULONG dM;
  556. ULONG N0;
  557. ULONG dN;
  558. ULONG dN_Original;
  559. FLONG fl;
  560. LONG x;
  561. LONG y;
  562. LONGLONG llBeta;
  563. LONGLONG llGamma;
  564. LONGLONG dl;
  565. LONGLONG ll;
  566. ULONG ulDelta;
  567. ULONG x0;
  568. ULONG y0;
  569. ULONG x1;
  570. ULONG cStylePels; // Major length of line in pixels for styling
  571. ULONG xStart;
  572. POINTL ptlStart;
  573. STRIP strip;
  574. PFNSTRIP pfn;
  575. LONG cPels;
  576. LONG* plStrip;
  577. LONG* plStripEnd;
  578. LONG cStripsInNextRun;
  579. POINTFIX* pptfxBufEnd = pptfxBuf + cptfx; // Last point in path record
  580. STYLEPOS spThis; // Style pos for this line
  581. do {
  582. /***********************************************************************\
  583. * Start the DDA calculations. *
  584. \***********************************************************************/
  585. M0 = (LONG) pptfxFirst->x;
  586. dM = (LONG) pptfxBuf->x;
  587. N0 = (LONG) pptfxFirst->y;
  588. dN = (LONG) pptfxBuf->y;
  589. fl = flStart;
  590. // Check for non-clipped, non-styled integer endpoint lines.
  591. //
  592. // 24bpp mach64 lines, clipped or otherwise, must always be handled here!
  593. // Can't use the strip drawer.
  594. if ((fl & (FL_CLIP | FL_STYLED)) == 0 || ppdev->iBitmapFormat == BMF_24BPP)
  595. {
  596. // Integer end-point lines will probably account for 90% of
  597. // all lines drawn (curves rendered by GDI will be an
  598. // exception, and will have fractional GIQ coordinates).
  599. //
  600. // As such, we try to special-case integer lines as soon as
  601. // possible.
  602. //
  603. // Unfortunately, the ATI's point-to-point line capability has
  604. // a rounding convention for rendering tie-breaker pixels that
  605. // doesn't match that of GDI's, so we can't use it for
  606. // arbitrary integer lines, otherwise we would fail HCTs. But
  607. // since horizontal and vertical lines have no tie-breakers,
  608. // and probably account for 60% of all lines drawn, we special
  609. // case them here. (The 'bHardwareLine' special case a little
  610. // lower down will handle arbitrary direction lines.)
  611. //
  612. // Note: If your hardware can't handle GIQ lines ala
  613. // 'bHardwareLine,' but can handle the correct rounding
  614. // convention, I strongly recommend special-casing
  615. // integer lines of arbitrary slope here, too.
  616. //
  617. // How can you tell if you have the correct rounding convention?
  618. // Implement integer lines (they're easy), run Guiman and draw a
  619. // bunch of Polyline lines in random directions, and then press
  620. // the 'X' xor button -- if you see random pixels lit up, you've
  621. // got the wrong convention...
  622. if (((M0 | dM | N0 | dN) & (F - 1)) == 0 && (fl & FL_CLIP) == 0)
  623. {
  624. // -1 for 'iSolidColor' denotes that the currently set
  625. // colour and mix should be kept:
  626. ppdev->pfnLineToTrivial(ppdev,
  627. (M0 >> 4) + ppdev->xOffset,
  628. (N0 >> 4) + ppdev->yOffset,
  629. (dM >> 4) + ppdev->xOffset,
  630. (dN >> 4) + ppdev->yOffset,
  631. // 24bpp is only available on the mach64:
  632. (ppdev->iBitmapFormat == BMF_24BPP)? iSolidColor:(ULONG) -1,
  633. mix,
  634. NULL);
  635. goto Next_Line;
  636. }
  637. // Check for fractional endpoint lines that are small enough
  638. // to use the hardware DDA:
  639. if (bHardwareLine(ppdev, pptfxFirst, pptfxBuf, iSolidColor, mix, prclClip))
  640. goto Next_Line;
  641. }
  642. if ((LONG) M0 > (LONG) dM)
  643. {
  644. // Ensure that we run left-to-right:
  645. register ULONG ulTmp;
  646. SWAPL(M0, dM, ulTmp);
  647. SWAPL(N0, dN, ulTmp);
  648. fl |= FL_FLIP_H;
  649. }
  650. // Compute the delta dx. The DDI says we can never have a valid delta
  651. // with a magnitued more than 2^31 - 1, but GDI never actually checks
  652. // its transforms. So we have to check for this case to avoid overflow:
  653. dM -= M0;
  654. if ((LONG) dM < 0)
  655. {
  656. goto Next_Line;
  657. }
  658. if ((LONG) dN < (LONG) N0)
  659. {
  660. // Line runs from bottom to top, so flip across y = 0:
  661. N0 = -(LONG) N0;
  662. dN = -(LONG) dN;
  663. fl |= FL_FLIP_V;
  664. }
  665. dN -= N0;
  666. if ((LONG) dN < 0)
  667. {
  668. goto Next_Line;
  669. }
  670. // We now have a line running left-to-right, top-to-bottom from (M0, N0)
  671. // to (M0 + dM, N0 + dN):
  672. if (dN >= dM)
  673. {
  674. if (dN == dM)
  675. {
  676. // Have to special case slopes of one:
  677. fl |= FL_FLIP_SLOPE_ONE;
  678. }
  679. else
  680. {
  681. // Since line has slope greater than 1, flip across x = y:
  682. register ULONG ulTmp;
  683. SWAPL(dM, dN, ulTmp);
  684. SWAPL(M0, N0, ulTmp);
  685. fl |= FL_FLIP_D;
  686. }
  687. }
  688. fl |= gaflRound[(fl & FL_ROUND_MASK) >> FL_ROUND_SHIFT];
  689. x = LFLOOR((LONG) M0);
  690. y = LFLOOR((LONG) N0);
  691. M0 = FXFRAC(M0);
  692. N0 = FXFRAC(N0);
  693. // Calculate the remainder term [ dM * (N0 + F/2) - M0 * dN ]:
  694. llGamma = UInt32x32To64(dM, N0 + F/2) - UInt32x32To64(M0, dN);
  695. if (fl & FL_V_ROUND_DOWN) // Adjust so y = 1/2 rounds down
  696. {
  697. llGamma--;
  698. }
  699. llGamma >>= FLOG2;
  700. llBeta = ~llGamma;
  701. /***********************************************************************\
  702. * Figure out which pixels are at the ends of the line. *
  703. \***********************************************************************/
  704. // The toughest part of GIQ is determining the start and end pels.
  705. //
  706. // Our approach here is to calculate x0 and x1 (the inclusive start
  707. // and end columns of the line respectively, relative to our normalized
  708. // origin). Then x1 - x0 + 1 is the number of pels in the line. The
  709. // start point is easily calculated by plugging x0 into our line equation
  710. // (which takes care of whether y = 1/2 rounds up or down in value)
  711. // getting y0, and then undoing the normalizing flips to get back
  712. // into device space.
  713. //
  714. // We look at the fractional parts of the coordinates of the start and
  715. // end points, and call them (M0, N0) and (M1, N1) respectively, where
  716. // 0 <= M0, N0, M1, N1 < 16. We plot (M0, N0) on the following grid
  717. // to determine x0:
  718. //
  719. // +-----------------------> +x
  720. // |
  721. // | 0 1
  722. // | 0123456789abcdef
  723. // |
  724. // | 0 ........?xxxxxxx
  725. // | 1 ..........xxxxxx
  726. // | 2 ...........xxxxx
  727. // | 3 ............xxxx
  728. // | 4 .............xxx
  729. // | 5 ..............xx
  730. // | 6 ...............x
  731. // | 7 ................
  732. // | 8 ................
  733. // | 9 ......**........
  734. // | a ........****...x
  735. // | b ............****
  736. // | c .............xxx****
  737. // | d ............xxxx ****
  738. // | e ...........xxxxx ****
  739. // | f ..........xxxxxx
  740. // |
  741. // | 2 3
  742. // v
  743. //
  744. // +y
  745. //
  746. // This grid accounts for the appropriate rounding of GIQ and last-pel
  747. // exclusion. If (M0, N0) lands on an 'x', x0 = 2. If (M0, N0) lands
  748. // on a '.', x0 = 1. If (M0, N0) lands on a '?', x0 rounds up or down,
  749. // depending on what flips have been done to normalize the line.
  750. //
  751. // For the end point, if (M1, N1) lands on an 'x', x1 =
  752. // floor((M0 + dM) / 16) + 1. If (M1, N1) lands on a '.', x1 =
  753. // floor((M0 + dM)). If (M1, N1) lands on a '?', x1 rounds up or down,
  754. // depending on what flips have been done to normalize the line.
  755. //
  756. // Lines of exactly slope one require a special case for both the start
  757. // and end. For example, if the line ends such that (M1, N1) is (9, 1),
  758. // the line has gone exactly through (8, 0) -- which may be considered
  759. // to be part of 'x' because of rounding! So slopes of exactly slope
  760. // one going through (8, 0) must also be considered as belonging in 'x'.
  761. //
  762. // For lines that go left-to-right, we have the following grid:
  763. //
  764. // +-----------------------> +x
  765. // |
  766. // | 0 1
  767. // | 0123456789abcdef
  768. // |
  769. // | 0 xxxxxxxx?.......
  770. // | 1 xxxxxxx.........
  771. // | 2 xxxxxx..........
  772. // | 3 xxxxx...........
  773. // | 4 xxxx............
  774. // | 5 xxx.............
  775. // | 6 xx..............
  776. // | 7 x...............
  777. // | 8 x...............
  778. // | 9 x.....**........
  779. // | a xx......****....
  780. // | b xxx.........****
  781. // | c xxxx............****
  782. // | d xxxxx........... ****
  783. // | e xxxxxx.......... ****
  784. // | f xxxxxxx.........
  785. // |
  786. // | 2 3
  787. // v
  788. //
  789. // +y
  790. //
  791. // This grid accounts for the appropriate rounding of GIQ and last-pel
  792. // exclusion. If (M0, N0) lands on an 'x', x0 = 0. If (M0, N0) lands
  793. // on a '.', x0 = 1. If (M0, N0) lands on a '?', x0 rounds up or down,
  794. // depending on what flips have been done to normalize the line.
  795. //
  796. // For the end point, if (M1, N1) lands on an 'x', x1 =
  797. // floor((M0 + dM) / 16) - 1. If (M1, N1) lands on a '.', x1 =
  798. // floor((M0 + dM)). If (M1, N1) lands on a '?', x1 rounds up or down,
  799. // depending on what flips have been done to normalize the line.
  800. //
  801. // Lines of exactly slope one must be handled similarly to the right-to-
  802. // left case.
  803. {
  804. // Calculate x0, x1
  805. ULONG N1 = FXFRAC(N0 + dN);
  806. ULONG M1 = FXFRAC(M0 + dM);
  807. x1 = LFLOOR(M0 + dM);
  808. if (fl & FL_LAST_PEL_INCLUSIVE)
  809. {
  810. // It sure is easy to compute the first pel when lines have only
  811. // integer coordinates and are last-pel inclusive:
  812. x0 = 0;
  813. y0 = 0;
  814. // Last-pel inclusive lines that are exactly one pixel long
  815. // have a 'delta-x' and 'delta-y' equal to zero. The problem is
  816. // that our clip code assumes that 'delta-x' is always non-zero
  817. // (since it never happens with last-pel exclusive lines). As
  818. // an inelegant solution, we simply modify 'delta-x' in this
  819. // case -- because the line is exactly one pixel long, changing
  820. // the slope will obviously have no effect on rasterization.
  821. if (x1 == 0)
  822. {
  823. dM = 1;
  824. llGamma = 0;
  825. llBeta = ~llGamma;
  826. }
  827. }
  828. else
  829. {
  830. if (fl & FL_FLIP_H)
  831. {
  832. // ---------------------------------------------------------------
  833. // Line runs right-to-left: <----
  834. // Compute x1:
  835. if (N1 == 0)
  836. {
  837. if (LROUND(M1, fl & FL_H_ROUND_DOWN))
  838. {
  839. x1++;
  840. }
  841. }
  842. else if (abs((LONG) (N1 - F/2)) + M1 > F)
  843. {
  844. x1++;
  845. }
  846. if ((fl & (FL_FLIP_SLOPE_ONE | FL_H_ROUND_DOWN))
  847. == (FL_FLIP_SLOPE_ONE))
  848. {
  849. // Have to special-case diagonal lines going through our
  850. // the point exactly equidistant between two horizontal
  851. // pixels, if we're supposed to round x=1/2 down:
  852. if ((N1 > 0) && (M1 == N1 + 8))
  853. x1++;
  854. // Don't you love special cases? Is this a rhetorical question?
  855. if ((N0 > 0) && (M0 == N0 + 8))
  856. {
  857. x0 = 2;
  858. ulDelta = dN;
  859. goto right_to_left_compute_y0;
  860. }
  861. }
  862. // Compute x0:
  863. x0 = 1;
  864. ulDelta = 0;
  865. if (N0 == 0)
  866. {
  867. if (LROUND(M0, fl & FL_H_ROUND_DOWN))
  868. {
  869. x0 = 2;
  870. ulDelta = dN;
  871. }
  872. }
  873. else if (abs((LONG) (N0 - F/2)) + M0 > F)
  874. {
  875. x0 = 2;
  876. ulDelta = dN;
  877. }
  878. // Compute y0:
  879. right_to_left_compute_y0:
  880. y0 = 0;
  881. ll = llGamma + (LONGLONG) ulDelta;
  882. if (ll >= (LONGLONG) (2 * dM - dN))
  883. y0 = 2;
  884. else if (ll >= (LONGLONG) (dM - dN))
  885. y0 = 1;
  886. }
  887. else
  888. {
  889. // ---------------------------------------------------------------
  890. // Line runs left-to-right: ---->
  891. // Compute x1:
  892. if (!(fl & FL_LAST_PEL_INCLUSIVE))
  893. x1--;
  894. if (M1 > 0)
  895. {
  896. if (N1 == 0)
  897. {
  898. if (LROUND(M1, fl & FL_H_ROUND_DOWN))
  899. x1++;
  900. }
  901. else if (abs((LONG) (N1 - F/2)) <= (LONG) M1)
  902. {
  903. x1++;
  904. }
  905. }
  906. if ((fl & (FL_FLIP_SLOPE_ONE | FL_H_ROUND_DOWN))
  907. == (FL_FLIP_SLOPE_ONE | FL_H_ROUND_DOWN))
  908. {
  909. // Have to special-case diagonal lines going through our
  910. // the point exactly equidistant between two horizontal
  911. // pixels, if we're supposed to round x=1/2 down:
  912. if ((M1 > 0) && (N1 == M1 + 8))
  913. x1--;
  914. if ((M0 > 0) && (N0 == M0 + 8))
  915. {
  916. x0 = 0;
  917. goto left_to_right_compute_y0;
  918. }
  919. }
  920. // Compute x0:
  921. x0 = 0;
  922. if (M0 > 0)
  923. {
  924. if (N0 == 0)
  925. {
  926. if (LROUND(M0, fl & FL_H_ROUND_DOWN))
  927. x0 = 1;
  928. }
  929. else if (abs((LONG) (N0 - F/2)) <= (LONG) M0)
  930. {
  931. x0 = 1;
  932. }
  933. }
  934. // Compute y0:
  935. left_to_right_compute_y0:
  936. y0 = 0;
  937. if (llGamma >= (LONGLONG) (dM - (dN & (-(LONG) x0))))
  938. {
  939. y0 = 1;
  940. }
  941. }
  942. }
  943. }
  944. cStylePels = x1 - x0 + 1;
  945. if ((LONG) cStylePels <= 0)
  946. goto Next_Line;
  947. xStart = x0;
  948. /***********************************************************************\
  949. * Complex clipping. *
  950. \***********************************************************************/
  951. if (fl & FL_COMPLEX_CLIP)
  952. {
  953. dN_Original = dN;
  954. Continue_Complex_Clipping:
  955. if (fl & FL_FLIP_H)
  956. {
  957. // Line runs right-to-left <-----
  958. x0 = xStart + cStylePels - prun->iStop - 1;
  959. x1 = xStart + cStylePels - prun->iStart - 1;
  960. }
  961. else
  962. {
  963. // Line runs left-to-right ----->
  964. x0 = xStart + prun->iStart;
  965. x1 = xStart + prun->iStop;
  966. }
  967. prun++;
  968. // Reset some variables we'll nuke a little later:
  969. dN = dN_Original;
  970. pls->spNext = pls->spComplex;
  971. // No overflow since large integer math is used. Both values
  972. // will be positive:
  973. dl = UInt32x32To64(x0, dN) + llGamma;
  974. // y0 = dl / dM:
  975. y0 = UInt64Div32To32(dl, dM);
  976. ASSERTDD((LONG) y0 >= 0, "y0 weird: Goofed up end pel calc?");
  977. }
  978. /***********************************************************************\
  979. * Simple rectangular clipping. *
  980. \***********************************************************************/
  981. if (fl & FL_SIMPLE_CLIP)
  982. {
  983. ULONG y1;
  984. LONG xRight;
  985. LONG xLeft;
  986. LONG yBottom;
  987. LONG yTop;
  988. // Note that y0 and y1 are actually the lower and upper bounds,
  989. // respectively, of the y coordinates of the line (the line may
  990. // have actually shrunk due to first/last pel clipping).
  991. //
  992. // Also note that x0, y0 are not necessarily zero.
  993. RECTL* prcl = &prclClip[(fl & FL_RECTLCLIP_MASK) >>
  994. FL_RECTLCLIP_SHIFT];
  995. // Normalize to the same point we've normalized for the DDA
  996. // calculations:
  997. xRight = prcl->right - x;
  998. xLeft = prcl->left - x;
  999. yBottom = prcl->bottom - y;
  1000. yTop = prcl->top - y;
  1001. if (yBottom <= (LONG) y0 ||
  1002. xRight <= (LONG) x0 ||
  1003. xLeft > (LONG) x1)
  1004. {
  1005. Totally_Clipped:
  1006. if (fl & FL_STYLED)
  1007. {
  1008. pls->spNext += cStylePels;
  1009. if (pls->spNext >= pls->spTotal2)
  1010. pls->spNext %= pls->spTotal2;
  1011. }
  1012. goto Next_Line;
  1013. }
  1014. if ((LONG) x1 >= xRight)
  1015. x1 = xRight - 1;
  1016. // We have to know the correct y1, which we haven't bothered to
  1017. // calculate up until now. This multiply and divide is quite
  1018. // expensive; we could replace it with code similar to that which
  1019. // we used for computing y0.
  1020. //
  1021. // The reason why we need the actual value, and not an upper
  1022. // bounds guess like y1 = LFLOOR(dM) + 2 is that we have to be
  1023. // careful when calculating x(y) that y0 <= y <= y1, otherwise
  1024. // we can overflow on the divide (which, needless to say, is very
  1025. // bad).
  1026. dl = UInt32x32To64(x1, dN) + llGamma;
  1027. // y1 = dl / dM:
  1028. y1 = UInt64Div32To32(dl, dM);
  1029. if (yTop > (LONG) y1)
  1030. goto Totally_Clipped;
  1031. if (yBottom <= (LONG) y1)
  1032. {
  1033. y1 = yBottom;
  1034. dl = UInt32x32To64(y1, dM) + llBeta;
  1035. // x1 = dl / dN:
  1036. x1 = UInt64Div32To32(dl, dN);
  1037. }
  1038. // At this point, we've taken care of calculating the intercepts
  1039. // with the right and bottom edges. Now we work on the left and
  1040. // top edges:
  1041. if (xLeft > (LONG) x0)
  1042. {
  1043. x0 = xLeft;
  1044. dl = UInt32x32To64(x0, dN) + llGamma;
  1045. // y0 = dl / dM;
  1046. y0 = UInt64Div32To32(dl, dM);
  1047. if (yBottom <= (LONG) y0)
  1048. goto Totally_Clipped;
  1049. }
  1050. if (yTop > (LONG) y0)
  1051. {
  1052. y0 = yTop;
  1053. dl = UInt32x32To64(y0, dM) + llBeta;
  1054. // x0 = dl / dN + 1;
  1055. x0 = UInt64Div32To32(dl, dN) + 1;
  1056. if (xRight <= (LONG) x0)
  1057. goto Totally_Clipped;
  1058. }
  1059. ASSERTDD(x0 <= x1, "Improper rectangle clip");
  1060. }
  1061. /***********************************************************************\
  1062. * Done clipping. Unflip if necessary. *
  1063. \***********************************************************************/
  1064. ptlStart.x = x + x0;
  1065. ptlStart.y = y + y0;
  1066. if (fl & FL_FLIP_D)
  1067. {
  1068. register LONG lTmp;
  1069. SWAPL(ptlStart.x, ptlStart.y, lTmp);
  1070. }
  1071. if (fl & FL_FLIP_V)
  1072. {
  1073. ptlStart.y = -ptlStart.y;
  1074. }
  1075. cPels = x1 - x0 + 1;
  1076. /***********************************************************************\
  1077. * Style calculations. *
  1078. \***********************************************************************/
  1079. if (fl & FL_STYLED)
  1080. {
  1081. STYLEPOS sp;
  1082. spThis = pls->spNext;
  1083. pls->spNext += cStylePels;
  1084. {
  1085. if (pls->spNext >= pls->spTotal2)
  1086. pls->spNext %= pls->spTotal2;
  1087. if (fl & FL_FLIP_H)
  1088. sp = pls->spNext - x0 + xStart;
  1089. else
  1090. sp = spThis + x0 - xStart;
  1091. ASSERTDD(fl & FL_STYLED, "Oops");
  1092. // Normalize our target style position:
  1093. if ((sp < 0) || (sp >= pls->spTotal2))
  1094. {
  1095. sp %= pls->spTotal2;
  1096. // The modulus of a negative number is not well-defined
  1097. // in C -- if it's negative we'll adjust it so that it's
  1098. // back in the range [0, spTotal2):
  1099. if (sp < 0)
  1100. sp += pls->spTotal2;
  1101. }
  1102. // Since we always draw the line left-to-right, but styling is
  1103. // always done in the direction of the original line, we have
  1104. // to figure out where we are in the style array for the left
  1105. // edge of this line.
  1106. if (fl & FL_FLIP_H)
  1107. {
  1108. // Line originally ran right-to-left:
  1109. sp = -sp;
  1110. if (sp < 0)
  1111. sp += pls->spTotal2;
  1112. pls->ulStyleMask = ~pls->ulStartMask;
  1113. pls->pspStart = &pls->aspRtoL[0];
  1114. pls->pspEnd = &pls->aspRtoL[pls->cStyle - 1];
  1115. }
  1116. else
  1117. {
  1118. // Line originally ran left-to-right:
  1119. pls->ulStyleMask = pls->ulStartMask;
  1120. pls->pspStart = &pls->aspLtoR[0];
  1121. pls->pspEnd = &pls->aspLtoR[pls->cStyle - 1];
  1122. }
  1123. if (sp >= pls->spTotal)
  1124. {
  1125. sp -= pls->spTotal;
  1126. if (pls->cStyle & 1)
  1127. pls->ulStyleMask = ~pls->ulStyleMask;
  1128. }
  1129. pls->psp = pls->pspStart;
  1130. while (sp >= *pls->psp)
  1131. sp -= *pls->psp++;
  1132. ASSERTDD(pls->psp <= pls->pspEnd,
  1133. "Flew off into NeverNeverLand");
  1134. pls->spRemaining = *pls->psp - sp;
  1135. if ((pls->psp - pls->pspStart) & 1)
  1136. pls->ulStyleMask = ~pls->ulStyleMask;
  1137. }
  1138. }
  1139. plStrip = &strip.alStrips[0];
  1140. plStripEnd = &strip.alStrips[STRIP_MAX]; // Is exclusive
  1141. cStripsInNextRun = 0x7fffffff;
  1142. strip.ptlStart = ptlStart;
  1143. if (2 * dN > dM &&
  1144. !(fl & FL_STYLED))
  1145. {
  1146. // Do a half flip! Remember that we may doing this on the
  1147. // same line multiple times for complex clipping (meaning the
  1148. // affected variables should be reset for every clip run):
  1149. fl |= FL_FLIP_HALF;
  1150. llBeta = llGamma - (LONGLONG) ((LONG) dM);
  1151. dN = dM - dN;
  1152. y0 = x0 - y0; // Note this may overflow, but that's okay
  1153. }
  1154. // Now, run the DDA starting at (ptlStart.x, ptlStart.y)!
  1155. strip.flFlips = fl;
  1156. pfn = apfn[(fl & FL_STRIP_MASK) >> FL_STRIP_SHIFT];
  1157. // Now calculate the DDA variables needed to figure out how many pixels
  1158. // go in the very first strip:
  1159. {
  1160. register LONG i;
  1161. register ULONG dI;
  1162. register ULONG dR;
  1163. ULONG r;
  1164. if (dN == 0)
  1165. i = 0x7fffffff;
  1166. else
  1167. {
  1168. dl = UInt32x32To64(y0 + 1, dM) + llBeta;
  1169. ASSERTDD(dl >= 0, "Oops!");
  1170. // i = (dl / dN) - x0 + 1;
  1171. // r = (dl % dN);
  1172. i = UInt64Div32To32(dl, dN);
  1173. r = UInt64Mod32To32(dl, dN);
  1174. i = i - x0 + 1;
  1175. dI = dM / dN;
  1176. dR = dM % dN; // 0 <= dR < dN
  1177. ASSERTDD(dI > 0, "Weird dI");
  1178. }
  1179. ASSERTDD(i > 0 && i <= 0x7fffffff, "Weird initial strip length");
  1180. ASSERTDD(cPels > 0, "Zero pel line");
  1181. /***********************************************************************\
  1182. * Run the DDA! *
  1183. \***********************************************************************/
  1184. while(TRUE)
  1185. {
  1186. cPels -= i;
  1187. if (cPels <= 0)
  1188. break;
  1189. *plStrip++ = i;
  1190. if (plStrip == plStripEnd)
  1191. {
  1192. strip.cStrips = (LONG)(plStrip - &strip.alStrips[0]);
  1193. (*pfn)(ppdev, &strip, pls);
  1194. plStrip = &strip.alStrips[0];
  1195. }
  1196. i = dI;
  1197. r += dR;
  1198. if (r >= dN)
  1199. {
  1200. r -= dN;
  1201. i++;
  1202. }
  1203. }
  1204. *plStrip++ = cPels + i;
  1205. strip.cStrips = (LONG)(plStrip - &strip.alStrips[0]);
  1206. (*pfn)(ppdev, &strip, pls);
  1207. }
  1208. Next_Line:
  1209. if (fl & FL_COMPLEX_CLIP)
  1210. {
  1211. cptfx--;
  1212. if (cptfx != 0)
  1213. goto Continue_Complex_Clipping;
  1214. break;
  1215. }
  1216. else
  1217. {
  1218. pptfxFirst = pptfxBuf;
  1219. pptfxBuf++;
  1220. }
  1221. } while (pptfxBuf < pptfxBufEnd);
  1222. return(TRUE);
  1223. }
  1224. /******************************Public*Routine******************************\
  1225. * BOOL bHardwareLine(ppdev, pptfxStart, pptfxEnd, iSolidColor, mix, prclClip)
  1226. *
  1227. * This routine is useful for folks who have line drawing hardware where
  1228. * they can explicitly set the Bresenham terms -- they can use this routine
  1229. * to draw fractional coordinate GIQ lines with the hardware.
  1230. *
  1231. * Fractional coordinate lines require an extra 4 bits of precision in the
  1232. * Bresenham terms. For example, if your hardware has 13 bits of precision
  1233. * for the terms, you can only draw GIQ lines up to 255 pels long using this
  1234. * routine.
  1235. *
  1236. * Input:
  1237. * pptfxStart - Points to GIQ coordinate of start of line
  1238. * pptfxEnd - Points to GIQ coordinate of end of line
  1239. * NUM_DDA_BITS- The number of bits of precision your hardware can support.
  1240. *
  1241. * Output:
  1242. * returns - TRUE if the line was drawn.
  1243. * FALSE if the line is too long, and the strips code must be
  1244. * used.
  1245. *
  1246. * DDALINE:
  1247. * iDir - Direction of the line, as an octant numbered as follows:
  1248. *
  1249. * \ 5 | 6 /
  1250. * \ | /
  1251. * 4 \ | / 7
  1252. * \ /
  1253. * -----+-----
  1254. * /|\
  1255. * 3 / | \ 0
  1256. * / | \
  1257. * / 2 | 1 \
  1258. *
  1259. * ptlStart - Start pixel of line.
  1260. * cPels - # of pels in line. *NOTE* You must check if this is <= 0!
  1261. * dMajor - Major axis delta.
  1262. * dMinor - Minor axis delta.
  1263. * lErrorTerm - Error term.
  1264. *
  1265. * What you do with the last 3 terms may be a little tricky. They are
  1266. * actually the terms for the formula of the normalized line
  1267. *
  1268. * dMinor * x + (lErrorTerm + dMajor)
  1269. * y(x) = floor( ---------------------------------- )
  1270. * dMajor
  1271. *
  1272. * where y(x) is the y coordinate of the pixel to be lit as a function of
  1273. * the x-coordinate.
  1274. *
  1275. * Every time the line advances one in the major direction 'x', dMinor
  1276. * gets added to the current error term. If the resulting value is >= 0,
  1277. * we know we have to move one pixel in the minor direction 'y', and
  1278. * dMajor must be subtracted from the current error term.
  1279. *
  1280. * If you're trying to figure out what this means for your hardware, you can
  1281. * think of the DDALINE terms as having been computed equivalently as
  1282. * follows:
  1283. *
  1284. * dMinor = 2 * (minor axis delta)
  1285. * dMajor = 2 * (major axis delta)
  1286. * lErrorTerm = - (major axis delta) - fixup
  1287. *
  1288. * That is, if your documentation tells you that for integer lines, a
  1289. * register is supposed to be initialized with the value
  1290. * '2 * (minor axis delta)', you'll actually use dMinor.
  1291. *
  1292. * Example: Setting up the 8514
  1293. *
  1294. * AXSTPSIGN is supposed to be the axial step constant register, defined
  1295. * as 2 * (minor axis delta). You set:
  1296. *
  1297. * AXSTPSIGN = dMinor
  1298. *
  1299. * DGSTPSIGN is supposed to be the diagonal step constant register,
  1300. * defined as 2 * (minor axis delta) - 2 * (major axis delta). You set:
  1301. *
  1302. * DGSTPSIGN = dMinor - dMajor
  1303. *
  1304. * ERR_TERM is supposed to be the adjusted error term, defined as
  1305. * 2 * (minor axis delta) - (major axis delta) - fixup. You set:
  1306. *
  1307. * ERR_TERM = lErrorTerm + dMinor
  1308. *
  1309. * Implementation:
  1310. *
  1311. * You'll want to special case integer lines before calling this routine
  1312. * (since they're very common, take less time to the computation of line
  1313. * terms, and can handle longer lines than this routine because 4 bits
  1314. * aren't being given to the fraction).
  1315. *
  1316. * If a GIQ line is too long to be handled by this routine, you can just
  1317. * use the slower strip routines for that line. Note that you cannot
  1318. * just fail the call -- you must be able to accurately draw any line
  1319. * in the 28.4 device space when it intersects the viewport.
  1320. *
  1321. * Testing:
  1322. *
  1323. * Use Guiman, or some other test that draws random fractional coordinate
  1324. * lines and compares them to what GDI itself draws to a bitmap.
  1325. *
  1326. \**************************************************************************/
  1327. BOOL bHardwareLine(
  1328. PDEV* ppdev,
  1329. POINTFIX* pptfxStart, // Start of line
  1330. POINTFIX* pptfxEnd, // End of line
  1331. LONG iSolidColor, // 24bpp solid color
  1332. MIX mix, // 24bpp mix
  1333. RECTL* prclClip) // 24bpp clipping rectangle
  1334. {
  1335. FLONG fl; // Various flags
  1336. ULONG M0; // Normalized fractional unit x start coordinate (0 <= M0 < F)
  1337. ULONG N0; // Normalized fractional unit y start coordinate (0 <= N0 < F)
  1338. ULONG M1; // Normalized fractional unit x end coordinate (0 <= M1 < F)
  1339. ULONG N1; // Normalized fractional unit x end coordinate (0 <= N1 < F)
  1340. ULONG dM; // Normalized fractional unit x-delta (0 <= dM)
  1341. ULONG dN; // Normalized fractional unit y-delta (0 <= dN <= dM)
  1342. LONG x; // Normalized x coordinate of origin
  1343. LONG y; // Normalized y coordinate of origin
  1344. LONG x0; // Normalized x offset from origin to start pixel (inclusive)
  1345. LONG y0; // Normalized y offset from origin to start pixel (inclusive)
  1346. LONG x1; // Normalized x offset from origin to end pixel (inclusive)
  1347. LONG lGamma;// Bresenham error term at origin
  1348. LONG cPels; // Number of pixels in line
  1349. BYTE* pjMmBase;
  1350. BYTE* pjIoBase;
  1351. /***********************************************************************\
  1352. * Normalize line to the first octant.
  1353. \***********************************************************************/
  1354. fl = 0;
  1355. M0 = pptfxStart->x;
  1356. dM = pptfxEnd->x;
  1357. if ((LONG) dM < (LONG) M0)
  1358. {
  1359. // Line runs from right to left, so flip across x = 0:
  1360. M0 = -(LONG) M0;
  1361. dM = -(LONG) dM;
  1362. fl |= HW_FLIP_H;
  1363. }
  1364. // Compute the delta. The DDI says we can never have a valid delta
  1365. // with a magnitude more than 2^31 - 1, but the engine never actually
  1366. // checks its transforms. To ensure that we'll never puke on our shoes,
  1367. // we check for that case and simply refuse to draw the line:
  1368. dM -= M0;
  1369. // 24bpp Bresenham is guaranteed to draw ALL lines.
  1370. if (ppdev->iBitmapFormat != BMF_24BPP)
  1371. {
  1372. if ((LONG) dM < 0)
  1373. return(FALSE);
  1374. }
  1375. N0 = pptfxStart->y;
  1376. dN = pptfxEnd->y;
  1377. if ((LONG) dN < (LONG) N0)
  1378. {
  1379. // Line runs from bottom to top, so flip across y = 0:
  1380. N0 = -(LONG) N0;
  1381. dN = -(LONG) dN;
  1382. fl |= HW_FLIP_V;
  1383. }
  1384. // Compute another delta:
  1385. dN -= N0;
  1386. // 24bpp Bresenham is guaranteed to draw ALL lines.
  1387. if (ppdev->iBitmapFormat != BMF_24BPP)
  1388. {
  1389. if ((LONG) dN < 0)
  1390. return(FALSE);
  1391. }
  1392. if (dN >= dM)
  1393. {
  1394. if (dN == dM)
  1395. {
  1396. // Have to special case slopes of one:
  1397. fl |= HW_FLIP_SLOPE_ONE;
  1398. }
  1399. else
  1400. {
  1401. // Since line has slope greater than 1, flip across x = y:
  1402. register ULONG ulTmp;
  1403. ulTmp = dM; dM = dN; dN = ulTmp;
  1404. ulTmp = M0; M0 = N0; N0 = ulTmp;
  1405. fl |= HW_FLIP_D;
  1406. }
  1407. }
  1408. // Figure out if we can do the line in hardware, given that we have a
  1409. // limited number of bits of precision for the Bresenham terms.
  1410. //
  1411. // Remember that one bit has to be kept as a sign bit:
  1412. // 24bpp Bresenham is guaranteed to draw ALL lines.
  1413. if (ppdev->iBitmapFormat != BMF_24BPP)
  1414. {
  1415. if ((LONG) dM >= (1L << (NUM_DDA_BITS - 1)))
  1416. return(FALSE);
  1417. }
  1418. fl |= gaflHardwareRound[fl];
  1419. /***********************************************************************\
  1420. * Calculate the error term at pixel 0.
  1421. \***********************************************************************/
  1422. x = LFLOOR((LONG) M0);
  1423. y = LFLOOR((LONG) N0);
  1424. M0 = FXFRAC(M0);
  1425. N0 = FXFRAC(N0);
  1426. // NOTE NOTE NOTE: If this routine were to handle any line in the 28.4
  1427. // space, it will overflow its math (the following part requires 36 bits
  1428. // of precision)! But we get here for lines that the hardware can handle
  1429. // (see the expression (dM >= (1L << (NUM_DDA_BITS - 1))) above?), so if
  1430. // cBits is less than 28, we're safe.
  1431. //
  1432. // If you're going to use this routine to handle all lines in the 28.4
  1433. // device space, you will HAVE to make sure the math doesn't overflow,
  1434. // otherwise you won't be NT compliant! (See 'bHardwareLine' for an example
  1435. // how to do that. You don't have to worry about this if you simply
  1436. // default to the strips code for long lines, because those routines
  1437. // already do the math correctly.)
  1438. // Calculate the remainder term [ dM * (N0 + F/2) - M0 * dN ]. Note
  1439. // that M0 and N0 have at most 4 bits of significance (and if the
  1440. // arguments are properly ordered, on a 486 each multiply would be no
  1441. // more than 13 cycles):
  1442. lGamma = (N0 + F/2) * dM - M0 * dN;
  1443. if (fl & HW_Y_ROUND_DOWN)
  1444. lGamma--;
  1445. lGamma >>= FLOG2;
  1446. /***********************************************************************\
  1447. * Figure out which pixels are at the ends of the line.
  1448. \***********************************************************************/
  1449. // The toughest part of GIQ is determining the start and end pels.
  1450. //
  1451. // Our approach here is to calculate x0 and x1 (the inclusive start
  1452. // and end columns of the line respectively, relative to our normalized
  1453. // origin). Then x1 - x0 + 1 is the number of pels in the line. The
  1454. // start point is easily calculated by plugging x0 into our line equation
  1455. // (which takes care of whether y = 1/2 rounds up or down in value)
  1456. // getting y0, and then undoing the normalizing flips to get back
  1457. // into device space.
  1458. //
  1459. // We look at the fractional parts of the coordinates of the start and
  1460. // end points, and call them (M0, N0) and (M1, N1) respectively, where
  1461. // 0 <= M0, N0, M1, N1 < 16. We plot (M0, N0) on the following grid
  1462. // to determine x0:
  1463. //
  1464. // +-----------------------> +x
  1465. // |
  1466. // | 0 1
  1467. // | 0123456789abcdef
  1468. // |
  1469. // | 0 ........?xxxxxxx
  1470. // | 1 ..........xxxxxx
  1471. // | 2 ...........xxxxx
  1472. // | 3 ............xxxx
  1473. // | 4 .............xxx
  1474. // | 5 ..............xx
  1475. // | 6 ...............x
  1476. // | 7 ................
  1477. // | 8 ................
  1478. // | 9 ......**........
  1479. // | a ........****...x
  1480. // | b ............****
  1481. // | c .............xxx****
  1482. // | d ............xxxx ****
  1483. // | e ...........xxxxx ****
  1484. // | f ..........xxxxxx
  1485. // |
  1486. // | 2 3
  1487. // v
  1488. //
  1489. // +y
  1490. //
  1491. // This grid accounts for the appropriate rounding of GIQ and last-pel
  1492. // exclusion. If (M0, N0) lands on an 'x', x0 = 2. If (M0, N0) lands
  1493. // on a '.', x0 = 1. If (M0, N0) lands on a '?', x0 rounds up or down,
  1494. // depending on what flips have been done to normalize the line.
  1495. //
  1496. // For the end point, if (M1, N1) lands on an 'x', x1 =
  1497. // floor((M0 + dM) / 16) + 1. If (M1, N1) lands on a '.', x1 =
  1498. // floor((M0 + dM)). If (M1, N1) lands on a '?', x1 rounds up or down,
  1499. // depending on what flips have been done to normalize the line.
  1500. //
  1501. // Lines of exactly slope one require a special case for both the start
  1502. // and end. For example, if the line ends such that (M1, N1) is (9, 1),
  1503. // the line has gone exactly through (8, 0) -- which may be considered
  1504. // to be part of 'x' because of rounding! So slopes of exactly slope
  1505. // one going through (8, 0) must also be considered as belonging in 'x'
  1506. // when an x value of 1/2 is supposed to round up in value.
  1507. // Calculate x0, x1:
  1508. N1 = FXFRAC(N0 + dN);
  1509. M1 = FXFRAC(M0 + dM);
  1510. x1 = LFLOOR(M0 + dM);
  1511. // Line runs left-to-right:
  1512. // Compute x1:
  1513. x1--;
  1514. if (M1 > 0)
  1515. {
  1516. if (N1 == 0)
  1517. {
  1518. if (LROUND(M1, fl & HW_X_ROUND_DOWN))
  1519. x1++;
  1520. }
  1521. else if (abs((LONG) (N1 - F/2)) <= (LONG) M1)
  1522. {
  1523. x1++;
  1524. }
  1525. }
  1526. if ((fl & (HW_FLIP_SLOPE_ONE | HW_X_ROUND_DOWN))
  1527. == (HW_FLIP_SLOPE_ONE | HW_X_ROUND_DOWN))
  1528. {
  1529. // Have to special-case diagonal lines going through our
  1530. // the point exactly equidistant between two horizontal
  1531. // pixels, if we're supposed to round x=1/2 down:
  1532. if ((M1 > 0) && (N1 == M1 + 8))
  1533. x1--;
  1534. if ((M0 > 0) && (N0 == M0 + 8))
  1535. {
  1536. x0 = 0;
  1537. goto left_to_right_compute_y0;
  1538. }
  1539. }
  1540. // Compute x0:
  1541. x0 = 0;
  1542. if (M0 > 0)
  1543. {
  1544. if (N0 == 0)
  1545. {
  1546. if (LROUND(M0, fl & HW_X_ROUND_DOWN))
  1547. x0 = 1;
  1548. }
  1549. else if (abs((LONG) (N0 - F/2)) <= (LONG) M0)
  1550. {
  1551. x0 = 1;
  1552. }
  1553. }
  1554. left_to_right_compute_y0:
  1555. /***********************************************************************\
  1556. * Calculate the start pixel.
  1557. \***********************************************************************/
  1558. // We now compute y0 and adjust the error term. We know x0, and we know
  1559. // the current formula for the pixels to be lit on the line:
  1560. //
  1561. // dN * x + lGamma
  1562. // y(x) = floor( --------------- )
  1563. // dM
  1564. //
  1565. // The remainder of this expression is the new error term at (x0, y0).
  1566. // Since x0 is going to be either 0 or 1, we don't actually have to do a
  1567. // multiply or divide to compute y0. Finally, we subtract dM from the
  1568. // new error term so that it is in the range [-dM, 0).
  1569. y0 = 0;
  1570. lGamma += (dN & (-x0));
  1571. lGamma -= dM;
  1572. if (lGamma >= 0)
  1573. {
  1574. y0 = 1;
  1575. lGamma -= dM;
  1576. }
  1577. // Undo our flips to get the start coordinate:
  1578. x += x0;
  1579. y += y0;
  1580. if (fl & HW_FLIP_D)
  1581. {
  1582. register LONG lTmp;
  1583. lTmp = x; x = y; y = lTmp;
  1584. }
  1585. if (fl & HW_FLIP_V)
  1586. {
  1587. y = -y;
  1588. }
  1589. if (fl & HW_FLIP_H)
  1590. {
  1591. x = -x;
  1592. }
  1593. /***********************************************************************\
  1594. * Return the Bresenham terms:
  1595. \***********************************************************************/
  1596. // iDir = gaiDir[fl & HW_FLIP_MASK];
  1597. // ptlStart.x = x;
  1598. // ptlStart.y = y;
  1599. // cPels = x1 - x0 + 1; // NOTE: You'll have to check if cPels <= 0!
  1600. // dMajor = dM;
  1601. // dMinor = dN;
  1602. // lErrorTerm = lGamma;
  1603. /***********************************************************************\
  1604. * Draw the line. ATI specific code follows:
  1605. \***********************************************************************/
  1606. cPels = x1 - x0 + 1;
  1607. if (cPels > 0)
  1608. {
  1609. pjMmBase = ppdev->pjMmBase;
  1610. x += ppdev->xOffset;
  1611. y += ppdev->yOffset;
  1612. if (ppdev->iMachType == MACH_MM_64)
  1613. {
  1614. if (ppdev->iBitmapFormat != BMF_24BPP)
  1615. {
  1616. M64_CHECK_FIFO_SPACE(ppdev, pjMmBase, 6);
  1617. M64_OD(pjMmBase, DST_Y_X, PACKXY(x, y));
  1618. M64_OD(pjMmBase, DST_CNTL, gai64Direction[fl & HW_FLIP_MASK]);
  1619. M64_OD(pjMmBase, DST_BRES_ERR, dN + lGamma);
  1620. M64_OD(pjMmBase, DST_BRES_INC, dN);
  1621. M64_OD(pjMmBase, DST_BRES_DEC, dN - dM);
  1622. M64_OD(pjMmBase, DST_BRES_LNTH, cPels);
  1623. }
  1624. else
  1625. {
  1626. FLONG flQuadrant;
  1627. flQuadrant = gai64Direction[fl & HW_FLIP_MASK];
  1628. if (pptfxStart->y == pptfxEnd->y &&
  1629. cPels < 0x2000 && x >= 0 && y > 0 && y < 0x4000) // Horizontal line
  1630. {
  1631. flQuadrant &= 3; // clean the flags of Bresenham
  1632. x *= 3;
  1633. cPels *= 3;
  1634. if (! (flQuadrant & DST_CNTL_XDir))
  1635. x += 2; // From right to left, start with the Blue byte.
  1636. if (prclClip) vSetClipping(ppdev, prclClip);
  1637. M64_CHECK_FIFO_SPACE(ppdev, pjMmBase, 4);
  1638. M64_OD(pjMmBase, DP_SRC, DP_SRC_FrgdClr << 8 );
  1639. M64_OD(pjMmBase, DST_CNTL, flQuadrant | DST_CNTL_24_RotEna | ((x/4 % 6) << 8) );
  1640. M64_OD(pjMmBase, DST_Y_X, PACKXY(x, y) );
  1641. M64_OD(pjMmBase, DST_HEIGHT_WIDTH, PACKPAIR(1, cPels) );
  1642. if (prclClip) vResetClipping(ppdev);
  1643. }
  1644. else if (pptfxStart->x == pptfxEnd->x &&
  1645. cPels < 0x8000 && y > 0 && y < 0x4000) // Vertical line
  1646. {
  1647. flQuadrant &= 3; // clean the flags of Bresenham
  1648. x *= 3;
  1649. if (prclClip) vSetClipping(ppdev, prclClip);
  1650. M64_CHECK_FIFO_SPACE(ppdev, pjMmBase, 4);
  1651. M64_OD(pjMmBase, DP_SRC, DP_SRC_FrgdClr << 8 );
  1652. M64_OD(pjMmBase, DST_CNTL, flQuadrant | DST_CNTL_24_RotEna | ((x/4 % 6) << 8) );
  1653. M64_OD(pjMmBase, DST_Y_X, PACKXY(x, y) );
  1654. M64_OD(pjMmBase, DST_HEIGHT_WIDTH, PACKPAIR(cPels, 3) );
  1655. if (prclClip) vResetClipping(ppdev);
  1656. }
  1657. else
  1658. {
  1659. BYTE *pjDest, *pjScreen;
  1660. BYTE red, green, blue;
  1661. LONG bres_err, bres_inc, bres_dec, bres_len;
  1662. LONG lDelta;
  1663. MIX hw_mix;
  1664. pjScreen = ppdev->pjScreen;
  1665. lDelta = ppdev->lDelta;
  1666. hw_mix = gaul64HwMixFromMix[mix & 0xf] >> 16;
  1667. bres_err = dN + lGamma;
  1668. bres_inc = dN;
  1669. bres_dec = dN - dM;
  1670. bres_len = cPels;
  1671. // Separate into color bytes.
  1672. red = (BYTE) ((iSolidColor & ppdev->flRed) >> REDSHIFT);
  1673. green = (BYTE) ((iSolidColor & ppdev->flGreen) >> GREENSHIFT);
  1674. blue = (BYTE) ((iSolidColor & ppdev->flBlue) >> BLUESHIFT);
  1675. vM64QuietDown(ppdev, pjMmBase);
  1676. // Execute 24bpp Bresenham algorithm.
  1677. while (bres_len-- > 0)
  1678. {
  1679. // Write pel. Check for clipping. Last pel enabled.
  1680. if (prclClip == NULL
  1681. || x >= prclClip->left
  1682. && x < prclClip->right
  1683. && y >= prclClip->top
  1684. && y < prclClip->bottom )
  1685. {
  1686. pjDest = pjScreen + y*lDelta + x*3;
  1687. switch (hw_mix)
  1688. {
  1689. case 0: // NOT dst
  1690. *pjDest = ~*pjDest++;
  1691. *pjDest = ~*pjDest++;
  1692. *pjDest = ~*pjDest;
  1693. break;
  1694. case 1: // "0"
  1695. *pjDest++ = 0;
  1696. *pjDest++ = 0;
  1697. *pjDest = 0;
  1698. break;
  1699. case 2: // "1"
  1700. *pjDest++ = 0xFF;
  1701. *pjDest++ = 0xFF;
  1702. *pjDest = 0xFF;
  1703. break;
  1704. case 3: // dst
  1705. break;
  1706. case 4: // NOT src
  1707. *pjDest++ = ~blue;
  1708. *pjDest++ = ~green;
  1709. *pjDest = ~red;
  1710. break;
  1711. case 5: // dst XOR src
  1712. *pjDest++ ^= blue;
  1713. *pjDest++ ^= green;
  1714. *pjDest ^= red;
  1715. break;
  1716. case 6: // NOT dst XOR src
  1717. *pjDest = ~*pjDest++ ^ blue;
  1718. *pjDest = ~*pjDest++ ^ green;
  1719. *pjDest = ~*pjDest ^ red;
  1720. break;
  1721. case 7: // src
  1722. *pjDest++ = blue;
  1723. *pjDest++ = green;
  1724. *pjDest = red;
  1725. break;
  1726. case 8: // NOT dst OR NOT src
  1727. *pjDest = ~*pjDest++ | ~blue;
  1728. *pjDest = ~*pjDest++ | ~green;
  1729. *pjDest = ~*pjDest | ~red;
  1730. break;
  1731. case 9: // dst OR NOT src
  1732. *pjDest++ |= ~blue;
  1733. *pjDest++ |= ~green;
  1734. *pjDest |= ~red;
  1735. break;
  1736. case 0xA: // NOT dst OR src
  1737. *pjDest = ~*pjDest++ | blue;
  1738. *pjDest = ~*pjDest++ | green;
  1739. *pjDest = ~*pjDest | red;
  1740. break;
  1741. case 0xB: // dst OR src
  1742. *pjDest++ |= blue;
  1743. *pjDest++ |= green;
  1744. *pjDest |= red;
  1745. break;
  1746. case 0xC: // dst AND src
  1747. *pjDest++ &= blue;
  1748. *pjDest++ &= green;
  1749. *pjDest &= red;
  1750. break;
  1751. case 0xD: // NOT dst AND src
  1752. *pjDest = ~*pjDest++ & blue;
  1753. *pjDest = ~*pjDest++ & green;
  1754. *pjDest = ~*pjDest & red;
  1755. break;
  1756. case 0xE: // dst AND NOT src
  1757. *pjDest++ &= ~blue;
  1758. *pjDest++ &= ~green;
  1759. *pjDest &= ~red;
  1760. break;
  1761. case 0xF: // NOT dst AND NOT src
  1762. *pjDest = ~*pjDest++ & ~blue;
  1763. *pjDest = ~*pjDest++ & ~green;
  1764. *pjDest = ~*pjDest & ~red;
  1765. break;
  1766. case 0x17:
  1767. *pjDest = ((*pjDest++) + blue)/2;
  1768. *pjDest = ((*pjDest++) + green)/2;
  1769. *pjDest = (*pjDest + red)/2;
  1770. break;
  1771. }
  1772. }
  1773. if (flQuadrant & DST_CNTL_YMajor)
  1774. {
  1775. if (flQuadrant & DST_CNTL_YDir)
  1776. y++;
  1777. else
  1778. y--;
  1779. if (bres_err >= 0)
  1780. {
  1781. bres_err += bres_dec;
  1782. if (flQuadrant & DST_CNTL_XDir)
  1783. x++;
  1784. else
  1785. x--;
  1786. }
  1787. else
  1788. bres_err += bres_inc;
  1789. }
  1790. else
  1791. {
  1792. if (flQuadrant & DST_CNTL_XDir)
  1793. x++;
  1794. else
  1795. x--;
  1796. if (bres_err >= 0)
  1797. {
  1798. bres_err += bres_dec;
  1799. if (flQuadrant & DST_CNTL_YDir)
  1800. y++;
  1801. else
  1802. y--;
  1803. }
  1804. else
  1805. bres_err += bres_inc;
  1806. }
  1807. }
  1808. }
  1809. }
  1810. }
  1811. else if (ppdev->iMachType == MACH_MM_32)
  1812. {
  1813. M32_CHECK_FIFO_SPACE(ppdev, pjMmBase, 7);
  1814. // Note that gai32Direction must have 'LAST_PEL_OFF' set so
  1815. // that we don't change the state for the strip drawers:
  1816. M32_OW(pjMmBase, CUR_X, x);
  1817. M32_OW(pjMmBase, CUR_Y, y);
  1818. M32_OW(pjMmBase, LINEDRAW_OPT, gai32Direction[fl & HW_FLIP_MASK]);
  1819. M32_OW(pjMmBase, ERR_TERM, dN + lGamma);
  1820. M32_OW(pjMmBase, AXSTP, dN);
  1821. M32_OW(pjMmBase, DIASTP, dN - dM);
  1822. M32_OW(pjMmBase, BRES_COUNT, cPels);
  1823. }
  1824. else
  1825. {
  1826. pjIoBase = ppdev->pjIoBase;
  1827. I32_CHECK_FIFO_SPACE(ppdev, pjIoBase, 7);
  1828. // Note that gai32Direction must have 'LAST_PEL_OFF' set so
  1829. // that we don't change the state for the strip drawers:
  1830. I32_OW(pjIoBase, CUR_X, x);
  1831. I32_OW(pjIoBase, CUR_Y, y);
  1832. I32_OW(pjIoBase, LINEDRAW_OPT, gai32Direction[fl & HW_FLIP_MASK]);
  1833. I32_OW(pjIoBase, ERR_TERM, dN + lGamma);
  1834. I32_OW(pjIoBase, AXSTP, dN);
  1835. I32_OW(pjIoBase, DIASTP, dN - dM);
  1836. I32_OW(pjIoBase, BRES_COUNT, cPels);
  1837. }
  1838. }
  1839. return(TRUE);
  1840. }
  1841. /*******************************Public*Table*******************************\
  1842. * gapfnI32Strip
  1843. *
  1844. * Look-up table for DrvStrokePath to find which strip routines to call.
  1845. *
  1846. \**************************************************************************/
  1847. VOID (*gapfnI32Strip[])(PDEV*, STRIP*, LINESTATE*) = {
  1848. vI32StripSolidHorizontal,
  1849. vI32StripSolidVertical,
  1850. vI32StripSolidDiagonal,
  1851. vI32StripSolidDiagonal,
  1852. vI32StripStyledHorizontal,
  1853. vI32StripStyledVertical,
  1854. NULL,
  1855. NULL,
  1856. };
  1857. VOID (*gapfnM64Strip[])(PDEV*, STRIP*, LINESTATE*) = {
  1858. vM64StripSolidHorizontal,
  1859. vM64StripSolidVertical,
  1860. vM64StripSolidDiagonal,
  1861. vM64StripSolidDiagonal,
  1862. vM64StripStyledHorizontal,
  1863. vM64StripStyledVertical,
  1864. NULL,
  1865. NULL,
  1866. };
  1867. // Style array for alternate style (alternates one pixel on, one pixel off):
  1868. STYLEPOS gaspAlternateStyle[] = { 1 };
  1869. /******************************Public*Routine******************************\
  1870. * BOOL DrvStrokePath(pso, ppo, pco, pxo, pbo, pptlBrush, pla, mix)
  1871. *
  1872. * Strokes the path.
  1873. *
  1874. \**************************************************************************/
  1875. BOOL DrvStrokePath(
  1876. SURFOBJ* pso,
  1877. PATHOBJ* ppo,
  1878. CLIPOBJ* pco,
  1879. XFORMOBJ* pxo,
  1880. BRUSHOBJ* pbo,
  1881. POINTL* pptlBrush,
  1882. LINEATTRS* pla,
  1883. MIX mix)
  1884. {
  1885. STYLEPOS aspLtoR[STYLE_MAX_COUNT];
  1886. STYLEPOS aspRtoL[STYLE_MAX_COUNT];
  1887. LINESTATE ls;
  1888. PFNSTRIP* apfn;
  1889. FLONG fl;
  1890. PDEV* ppdev;
  1891. DSURF* pdsurf;
  1892. OH* poh;
  1893. RECTL arclClip[4]; // For rectangular clipping
  1894. BYTE* pjMmBase;
  1895. BYTE* pjIoBase;
  1896. RECTL* prclClip;
  1897. ULONG ulLinePattern;
  1898. BOOL bRet;
  1899. // for punting 24bpp:
  1900. BANK bnk;
  1901. RECTFX rectfx;
  1902. RECTL rclTrg;
  1903. ASSERTDD(((mix >> 8) & 0xff) == (mix & 0xff),
  1904. "GDI gave us an improper mix");
  1905. // Pass the surface off to GDI if it's a device bitmap that we've
  1906. // converted to a DIB:
  1907. pdsurf = (DSURF*) pso->dhsurf;
  1908. if (pdsurf->dt == DT_DIB)
  1909. {
  1910. return(EngStrokePath(pdsurf->pso, ppo, pco, pxo, pbo, pptlBrush,
  1911. pla, mix));
  1912. }
  1913. // We'll be drawing to the screen or an off-screen DFB; copy the surface's
  1914. // offset now so that we won't need to refer to the DSURF again:
  1915. poh = pdsurf->poh;
  1916. ppdev = (PDEV*) pso->dhpdev;
  1917. ppdev->xOffset = poh->x;
  1918. ppdev->yOffset = poh->y;
  1919. bRet = TRUE;
  1920. pjMmBase = ppdev->pjMmBase;
  1921. pjIoBase = ppdev->pjIoBase;
  1922. //goto Punt_It; //RKE:
  1923. prclClip = NULL;
  1924. fl = 0;
  1925. ulLinePattern = (ULONG) -1;
  1926. // Look after styling initialization:
  1927. if (pla->fl & LA_ALTERNATE)
  1928. {
  1929. if (ppdev->iAsic == ASIC_88800GX && ppdev->iBitmapFormat == BMF_24BPP)
  1930. {
  1931. goto Punt_It;
  1932. }
  1933. ls.cStyle = 1;
  1934. ls.spTotal = 1;
  1935. ls.spTotal2 = 2;
  1936. ls.spRemaining = 1;
  1937. ls.aspRtoL = &gaspAlternateStyle[0];
  1938. ls.aspLtoR = &gaspAlternateStyle[0];
  1939. ls.spNext = HIWORD(pla->elStyleState.l);
  1940. ls.xyDensity = 1;
  1941. fl |= FL_STYLED;
  1942. ls.ulStartMask = 0L;
  1943. }
  1944. else if (pla->pstyle != (FLOAT_LONG*) NULL)
  1945. {
  1946. PFLOAT_LONG pstyle;
  1947. STYLEPOS* pspDown;
  1948. STYLEPOS* pspUp;
  1949. if (ppdev->iAsic == ASIC_88800GX && ppdev->iBitmapFormat == BMF_24BPP)
  1950. {
  1951. goto Punt_It;
  1952. }
  1953. pstyle = &pla->pstyle[pla->cstyle];
  1954. ls.xyDensity = STYLE_DENSITY;
  1955. ls.spTotal = 0;
  1956. while (pstyle-- > pla->pstyle)
  1957. {
  1958. ls.spTotal += pstyle->l;
  1959. }
  1960. ls.spTotal *= STYLE_DENSITY;
  1961. ls.spTotal2 = 2 * ls.spTotal;
  1962. // Compute starting style position (this is guaranteed not to overflow):
  1963. ls.spNext = HIWORD(pla->elStyleState.l) * STYLE_DENSITY +
  1964. LOWORD(pla->elStyleState.l);
  1965. fl |= FL_STYLED;
  1966. ls.cStyle = pla->cstyle;
  1967. ls.aspRtoL = aspRtoL;
  1968. ls.aspLtoR = aspLtoR;
  1969. if (pla->fl & LA_STARTGAP)
  1970. ls.ulStartMask = 0xffffffffL;
  1971. else
  1972. ls.ulStartMask = 0L;
  1973. pstyle = pla->pstyle;
  1974. pspDown = &ls.aspRtoL[ls.cStyle - 1];
  1975. pspUp = &ls.aspLtoR[0];
  1976. while (pspDown >= &ls.aspRtoL[0])
  1977. {
  1978. *pspDown = pstyle->l * STYLE_DENSITY;
  1979. *pspUp = *pspDown;
  1980. pspUp++;
  1981. pspDown--;
  1982. pstyle++;
  1983. }
  1984. }
  1985. if (pco->iDComplexity == DC_RECT)
  1986. {
  1987. fl |= FL_SIMPLE_CLIP;
  1988. arclClip[0] = pco->rclBounds;
  1989. // FL_FLIP_D:
  1990. arclClip[1].top = pco->rclBounds.left;
  1991. arclClip[1].left = pco->rclBounds.top;
  1992. arclClip[1].bottom = pco->rclBounds.right;
  1993. arclClip[1].right = pco->rclBounds.bottom;
  1994. // FL_FLIP_V:
  1995. arclClip[2].top = -pco->rclBounds.bottom + 1;
  1996. arclClip[2].left = pco->rclBounds.left;
  1997. arclClip[2].bottom = -pco->rclBounds.top + 1;
  1998. arclClip[2].right = pco->rclBounds.right;
  1999. // FL_FLIP_V | FL_FLIP_D:
  2000. arclClip[3].top = pco->rclBounds.left;
  2001. arclClip[3].left = -pco->rclBounds.bottom + 1;
  2002. arclClip[3].bottom = pco->rclBounds.right;
  2003. arclClip[3].right = -pco->rclBounds.top + 1;
  2004. prclClip = arclClip;
  2005. }
  2006. //////////////////////////////////////////////////////////////////////
  2007. // ATI specific initialization:
  2008. if (ppdev->iMachType == MACH_MM_64)
  2009. {
  2010. //
  2011. // gmvideo9.scr fails guiman if this path is executed at 24bpp, so punt.
  2012. //
  2013. if (ppdev->iBitmapFormat == BMF_24BPP)
  2014. goto Punt_It;
  2015. apfn = &gapfnM64Strip[4 * ((fl & FL_STYLE_MASK) >> FL_STYLE_SHIFT)];
  2016. M64_CHECK_FIFO_SPACE(ppdev, pjMmBase, 3);
  2017. //M64_OD(pjMmBase, CONTEXT_LOAD_CNTL, CONTEXT_LOAD_CmdLoad | iDefContext );
  2018. M64_OD(pjMmBase, DP_MIX, gaul64HwMixFromMix[mix & 0xf]);
  2019. M64_OD(pjMmBase, DP_FRGD_CLR, pbo->iSolidColor);
  2020. M64_OD(pjMmBase, DP_SRC, DP_SRC_Always1 | DP_SRC_FrgdClr << 8);
  2021. }
  2022. else if (ppdev->iMachType == MACH_MM_32)
  2023. {
  2024. apfn = &gapfnI32Strip[4 * ((fl & FL_STYLE_MASK) >> FL_STYLE_SHIFT)];
  2025. M32_CHECK_FIFO_SPACE(ppdev, pjMmBase, 5);
  2026. M32_OW(pjMmBase, DP_CONFIG, FG_COLOR_SRC_FG | DRAW | WRITE);
  2027. M32_OW(pjMmBase, FRGD_MIX, FOREGROUND_COLOR | gaul32HwMixFromMix[mix & 0xf]);
  2028. M32_OW(pjMmBase, FRGD_COLOR, pbo->iSolidColor);
  2029. M32_OW(pjMmBase, MULTIFUNC_CNTL, DATA_EXTENSION | ALL_ONES);
  2030. M32_OW(pjMmBase, LINEDRAW_OPT, LAST_PEL_OFF); // For strip drawers
  2031. }
  2032. else
  2033. {
  2034. apfn = &gapfnI32Strip[4 * ((fl & FL_STYLE_MASK) >> FL_STYLE_SHIFT)];
  2035. I32_CHECK_FIFO_SPACE(ppdev, pjIoBase, 5);
  2036. I32_OW(pjIoBase, DP_CONFIG, FG_COLOR_SRC_FG | DRAW | WRITE);
  2037. I32_OW(pjIoBase, FRGD_MIX, FOREGROUND_COLOR | gaul32HwMixFromMix[mix & 0xf]);
  2038. I32_OW(pjIoBase, FRGD_COLOR, pbo->iSolidColor);
  2039. I32_OW(pjIoBase, MULTIFUNC_CNTL, DATA_EXTENSION | ALL_ONES);
  2040. I32_OW(pjIoBase, LINEDRAW_OPT, LAST_PEL_OFF); // For strip drawers
  2041. }
  2042. //////////////////////////////////////////////////////////////////////
  2043. // Set up to enumerate the path:
  2044. if (pco->iDComplexity != DC_COMPLEX)
  2045. {
  2046. PATHDATA pd;
  2047. BOOL bMore;
  2048. ULONG cptfx;
  2049. POINTFIX ptfxStartFigure;
  2050. POINTFIX ptfxLast;
  2051. POINTFIX* pptfxFirst;
  2052. POINTFIX* pptfxBuf;
  2053. pd.flags = 0;
  2054. do {
  2055. bMore = PATHOBJ_bEnum(ppo, &pd);
  2056. cptfx = pd.count;
  2057. if (cptfx == 0)
  2058. break;
  2059. if (pd.flags & PD_BEGINSUBPATH)
  2060. {
  2061. ptfxStartFigure = *pd.pptfx;
  2062. pptfxFirst = pd.pptfx;
  2063. pptfxBuf = pd.pptfx + 1;
  2064. cptfx--;
  2065. }
  2066. else
  2067. {
  2068. pptfxFirst = &ptfxLast;
  2069. pptfxBuf = pd.pptfx;
  2070. }
  2071. if (pd.flags & PD_RESETSTYLE)
  2072. ls.spNext = 0;
  2073. if (cptfx > 0)
  2074. {
  2075. bRet &= bLines(ppdev,
  2076. pptfxFirst,
  2077. pptfxBuf,
  2078. (RUN*) NULL,
  2079. cptfx,
  2080. &ls,
  2081. prclClip,
  2082. apfn,
  2083. fl, pbo->iSolidColor, mix);
  2084. }
  2085. ptfxLast = pd.pptfx[pd.count - 1];
  2086. if (pd.flags & PD_CLOSEFIGURE)
  2087. {
  2088. bRet &= bLines(ppdev,
  2089. &ptfxLast,
  2090. &ptfxStartFigure,
  2091. (RUN*) NULL,
  2092. 1,
  2093. &ls,
  2094. prclClip,
  2095. apfn,
  2096. fl, pbo->iSolidColor, mix);
  2097. }
  2098. } while (bMore);
  2099. if (fl & FL_STYLED)
  2100. {
  2101. // Save the style state:
  2102. ULONG ulHigh;
  2103. ULONG ulLow;
  2104. // Masked styles don't normalize the style state. It's a good
  2105. // thing to do, so let's do it now:
  2106. if ((ULONG) ls.spNext >= (ULONG) ls.spTotal2)
  2107. ls.spNext = (ULONG) ls.spNext % (ULONG) ls.spTotal2;
  2108. ulHigh = ls.spNext / ls.xyDensity;
  2109. ulLow = ls.spNext % ls.xyDensity;
  2110. pla->elStyleState.l = MAKELONG(ulLow, ulHigh);
  2111. }
  2112. }
  2113. else if (ppdev->iBitmapFormat != BMF_24BPP)
  2114. {
  2115. // Local state for path enumeration:
  2116. BOOL bMore;
  2117. union {
  2118. BYTE aj[offsetof(CLIPLINE, arun) + RUN_MAX * sizeof(RUN)];
  2119. CLIPLINE cl;
  2120. } cl;
  2121. fl |= FL_COMPLEX_CLIP;
  2122. // We use the clip object when non-simple clipping is involved:
  2123. PATHOBJ_vEnumStartClipLines(ppo, pco, pso, pla);
  2124. do {
  2125. bMore = PATHOBJ_bEnumClipLines(ppo, sizeof(cl), &cl.cl);
  2126. if (cl.cl.c != 0)
  2127. {
  2128. if (fl & FL_STYLED)
  2129. {
  2130. ls.spComplex = HIWORD(cl.cl.lStyleState) * ls.xyDensity
  2131. + LOWORD(cl.cl.lStyleState);
  2132. }
  2133. bRet &= bLines(ppdev,
  2134. &cl.cl.ptfxA,
  2135. &cl.cl.ptfxB,
  2136. &cl.cl.arun[0],
  2137. cl.cl.c,
  2138. &ls,
  2139. (RECTL*) NULL,
  2140. apfn,
  2141. fl, pbo->iSolidColor, mix);
  2142. }
  2143. } while (bMore);
  2144. }
  2145. else // punt complex clipping in 24bpp
  2146. {
  2147. Punt_It:
  2148. PATHOBJ_vGetBounds( ppo, &rectfx );
  2149. rclTrg.left = (rectfx.xLeft >> 4);
  2150. rclTrg.top = (rectfx.yTop >> 4);
  2151. rclTrg.right = min( ((rectfx.xRight + 0xF) >> 4) + 1, (LONG) ppdev->cxMemory );
  2152. rclTrg.bottom = min( ((rectfx.yBottom + 0xF) >> 4) + 1, (LONG) ppdev->cyMemory );
  2153. vBankStart(ppdev, &rclTrg, pco, &bnk);
  2154. do {
  2155. bRet &= EngStrokePath(bnk.pso, ppo, bnk.pco, pxo, pbo, pptlBrush, pla, mix);
  2156. } while (bBankEnum(&bnk));
  2157. }
  2158. if (ppdev->iMachType == MACH_MM_64)
  2159. {
  2160. // Since we don't use a default context, we must restore registers:
  2161. M64_CHECK_FIFO_SPACE(ppdev, pjMmBase, 1);
  2162. M64_OD(pjMmBase, DST_CNTL, DST_CNTL_XDir | DST_CNTL_YDir);
  2163. }
  2164. return(bRet);
  2165. }