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.

241 lines
6.4 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: Lineto.c
  3. *
  4. * DrvLineTo for the driver.
  5. *
  6. * Copyright (c) 1995-1996 Microsoft Corporation
  7. \**************************************************************************/
  8. #include "precomp.h"
  9. // The MGA's hardware coordinates are limited to 16-bit signed values:
  10. #define MIN_INTEGER_BOUND (-32767)
  11. #define MAX_INTEGER_BOUND (32767)
  12. /**************************************************************************
  13. * Line Rasterization
  14. *
  15. * The 3D DDI's line rasterization rules are not as strict as are GDI's.
  16. * In particular, the 3D DDI doesn't care how we handle 'tie-breakers,'
  17. * where the true line falls exactly mid-way between two pixels, as long
  18. * as we're consistent, particularly between unclipped and clipped lines.
  19. *
  20. * For this implementation, I've chosen to match GDI's convention so that
  21. * I can share clipping code with the GDI line drawing routines.
  22. *
  23. * For integer lines, GDI's rule is that when a line falls exactly mid-way
  24. * between two pixels, the upper or left pixel should be left. For
  25. * standard Bresenham, this means that we should bias the error term down
  26. * by an infinitesimal amount in the following octants:
  27. *
  28. * \ 0 | 1 /
  29. * \ | /
  30. * 0 \ | / 0
  31. * ------------- 1 - Indicates the quadrants in which
  32. * 1 / | \ 1 the error term should be biased
  33. * / | \
  34. * / 0 | 1 \
  35. *
  36. * The MGA's convention for numbering the qudrants is as follows, where
  37. * 'sdydxl_MAJOR_X' = 1, 'sdxl_SUB' = 2, 'sdy_SUB' = 4:
  38. *
  39. * \ 2 | 0 /
  40. * \ | /
  41. * 3 \ | / 1
  42. * -------------
  43. * 7 / | \ 5
  44. * / | \
  45. * / 6 | 4 \
  46. *
  47. **************************************************************************/
  48. LONG gaiLineBias[] = { 1, 1, 0, 1, 1, 0, 0, 0 };
  49. /******************************Public*Routine******************************\
  50. * VOID vLineToTrivial
  51. *
  52. * Draws a single solid integer-only unclipped cosmetic line.
  53. *
  54. * We can't use the point-to-point capabilities of the MGA because its
  55. * tie-breaker convention doesn't match that of NT's in two octants,
  56. * and would cause us to fail HCTs.
  57. *
  58. \**************************************************************************/
  59. VOID vLineToTrivial(
  60. PDEV* ppdev,
  61. LONG x, // Passed in x1
  62. LONG y, // Passed in y1
  63. LONG dx, // Passed in x2
  64. LONG dy, // Passed in y2
  65. ULONG iSolidColor,
  66. MIX mix)
  67. {
  68. BYTE* pjBase;
  69. FLONG flQuadrant;
  70. ULONG ulHwMix;
  71. pjBase = ppdev->pjBase;
  72. CHECK_FIFO_SPACE(pjBase, 13);
  73. if (mix == 0x0d0d) // R2_COPYPEN
  74. {
  75. CP_WRITE(pjBase, DWG_DWGCTL, blockm_OFF + pattern_OFF + bltmod_BFCOL +
  76. transc_BG_TRANSP + atype_RPL + bop_SRCCOPY);
  77. }
  78. else
  79. {
  80. ulHwMix = (mix & 0xff) - 1;
  81. CP_WRITE(pjBase, DWG_DWGCTL, blockm_OFF + pattern_OFF + bltmod_BFCOL +
  82. transc_BG_TRANSP + atype_RSTR + (ulHwMix << 16));
  83. }
  84. CP_WRITE(pjBase, DWG_FCOL, COLOR_REPLICATE(ppdev, iSolidColor));
  85. if (!(GET_CACHE_FLAGS(ppdev, PATTERN_CACHE)))
  86. {
  87. CP_WRITE(pjBase, DWG_SRC0, 0xFFFFFFFF);
  88. CP_WRITE(pjBase, DWG_SRC1, 0xFFFFFFFF);
  89. CP_WRITE(pjBase, DWG_SRC2, 0xFFFFFFFF);
  90. CP_WRITE(pjBase, DWG_SRC3, 0xFFFFFFFF);
  91. }
  92. ppdev->HopeFlags = PATTERN_CACHE;
  93. CP_START(pjBase, DWG_XDST, x);
  94. CP_START(pjBase, DWG_YDST, y);
  95. flQuadrant = sdydxl_MAJOR_X;
  96. dx -= x;
  97. if (dx < 0)
  98. {
  99. dx = -dx;
  100. flQuadrant |= sdxl_SUB;
  101. }
  102. dy -= y;
  103. if (dy < 0)
  104. {
  105. dy = -dy;
  106. flQuadrant |= sdy_SUB;
  107. }
  108. if (dy > dx)
  109. {
  110. register LONG l;
  111. l = dy;
  112. dy = dx;
  113. dx = l; // Swap 'dx' and 'dy'
  114. flQuadrant &= ~sdydxl_MAJOR_X;
  115. }
  116. CP_WRITE(pjBase, DWG_SGN, flQuadrant);
  117. CP_WRITE(pjBase, DWG_LEN, dx);
  118. CP_WRITE(pjBase, DWG_AR0, dy);
  119. CP_WRITE(pjBase, DWG_AR2, dy - dx);
  120. CP_START(pjBase, DWG_AR1, (dy + dy - dx - gaiLineBias[flQuadrant]) >> 1);
  121. }
  122. /******************************Public*Routine******************************\
  123. * VOID vLineToClipped
  124. *
  125. * Draws a single solid integer-only clipped cosmetic line using
  126. * 'New MM I/O'.
  127. *
  128. \**************************************************************************/
  129. VOID vLineToClipped(
  130. PDEV* ppdev,
  131. LONG x1,
  132. LONG y1,
  133. LONG x2,
  134. LONG y2,
  135. ULONG iSolidColor,
  136. MIX mix,
  137. RECTL* prclClip)
  138. {
  139. vSetClipping(ppdev, prclClip);
  140. vLineToTrivial(ppdev, x1, y1, x2, y2, iSolidColor, mix);
  141. vResetClipping(ppdev);
  142. }
  143. /******************************Public*Routine******************************\
  144. * BOOL DrvLineTo(pso, pco, pbo, x1, y1, x2, y2, prclBounds, mix)
  145. *
  146. * Draws a single solid integer-only cosmetic line.
  147. *
  148. \**************************************************************************/
  149. BOOL DrvLineTo(
  150. SURFOBJ* pso,
  151. CLIPOBJ* pco,
  152. BRUSHOBJ* pbo,
  153. LONG x1,
  154. LONG y1,
  155. LONG x2,
  156. LONG y2,
  157. RECTL* prclBounds,
  158. MIX mix)
  159. {
  160. PDEV* ppdev;
  161. DSURF* pdsurf;
  162. OH* poh;
  163. LONG xOffset;
  164. LONG yOffset;
  165. BOOL bRet;
  166. // Pass the surface off to GDI if it's a device bitmap that we've
  167. // converted to a DIB:
  168. pdsurf = (DSURF*) pso->dhsurf;
  169. if (pdsurf->dt == DT_DIB)
  170. {
  171. return(EngLineTo(pdsurf->pso, pco, pbo, x1, y1, x2, y2, prclBounds, mix));
  172. }
  173. // We'll be drawing to the screen or an off-screen DFB; copy the surface's
  174. // offset now so that we won't need to refer to the DSURF again:
  175. poh = pdsurf->poh;
  176. ppdev = (PDEV*) pso->dhpdev;
  177. xOffset = poh->x;
  178. yOffset = poh->y;
  179. x1 += xOffset;
  180. x2 += xOffset;
  181. y1 += yOffset;
  182. y2 += yOffset;
  183. bRet = TRUE;
  184. if (pco == NULL)
  185. {
  186. vLineToTrivial(ppdev, x1, y1, x2, y2, pbo->iSolidColor, mix);
  187. }
  188. else if ((pco->iDComplexity <= DC_RECT) &&
  189. (prclBounds->left >= MIN_INTEGER_BOUND) &&
  190. (prclBounds->top >= MIN_INTEGER_BOUND) &&
  191. (prclBounds->right <= MAX_INTEGER_BOUND) &&
  192. (prclBounds->bottom <= MAX_INTEGER_BOUND))
  193. {
  194. ppdev->xOffset = xOffset;
  195. ppdev->yOffset = yOffset;
  196. vLineToClipped(ppdev, x1, y1, x2, y2, pbo->iSolidColor, mix,
  197. &pco->rclBounds);
  198. }
  199. else
  200. {
  201. bRet = FALSE;
  202. }
  203. return(bRet);
  204. }