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.

306 lines
8.8 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: Brush.c
  3. *
  4. * Handles all brush/pattern initialization and realization.
  5. *
  6. * Copyright (c) 1992-1995 Microsoft Corporation
  7. *
  8. \**************************************************************************/
  9. #include "precomp.h"
  10. /******************************Public*Routine******************************\
  11. * VOID vRealizeDitherPattern
  12. *
  13. * Generates an 8x8 dither pattern, in our internal realization format, for
  14. * the colour ulRGBToDither. Note that the high byte of ulRGBToDither does
  15. * not need to be set to zero, because vComputeSubspaces ignores it.
  16. \**************************************************************************/
  17. VOID vRealizeDitherPattern(
  18. RBRUSH* prb,
  19. ULONG ulRGBToDither)
  20. {
  21. ULONG ulNumVertices;
  22. VERTEX_DATA vVertexData[4];
  23. VERTEX_DATA* pvVertexData;
  24. // Calculate what colour subspaces are involved in the dither:
  25. pvVertexData = vComputeSubspaces(ulRGBToDither, vVertexData);
  26. // Now that we have found the bounding vertices and the number of
  27. // pixels to dither for each vertex, we can create the dither pattern
  28. ulNumVertices = (ULONG)(pvVertexData - vVertexData);
  29. // # of vertices with more than zero pixels in the dither
  30. // Do the actual dithering:
  31. vDitherColor(&prb->aulPattern[0], vVertexData, pvVertexData, ulNumVertices);
  32. // Initialize the fields we need:
  33. prb->fl = 0;
  34. }
  35. /******************************Public*Routine******************************\
  36. * BOOL DrvRealizeBrush
  37. *
  38. * This function allows us to convert GDI brushes into an internal form
  39. * we can use. It may be called directly by GDI at SelectObject time, or
  40. * it may be called by GDI as a result of us calling BRUSHOBJ_pvGetRbrush
  41. * to create a realized brush in a function like DrvBitBlt.
  42. *
  43. * Note that we have no way of determining what the current Rop or brush
  44. * alignment are at this point.
  45. *
  46. \**************************************************************************/
  47. BOOL DrvRealizeBrush(
  48. BRUSHOBJ* pbo,
  49. SURFOBJ* psoDst,
  50. SURFOBJ* psoPattern,
  51. SURFOBJ* psoMask,
  52. XLATEOBJ* pxlo,
  53. ULONG iHatch)
  54. {
  55. PDEV* ppdev;
  56. ULONG iPatternFormat;
  57. BYTE* pjSrc;
  58. BYTE* pjDst;
  59. LONG lSrcDelta;
  60. LONG cj;
  61. LONG i;
  62. LONG j;
  63. RBRUSH* prb;
  64. ULONG* pulXlate;
  65. ULONG* pulRBits;
  66. ppdev = (PDEV*) psoDst->dhpdev;
  67. // We don't do brushes in high-colour modes:
  68. if (ppdev->flStat & STAT_UNACCELERATED)
  69. goto ReturnFalse;
  70. // We have a fast path for dithers when we set GCAPS_DITHERONREALIZE:
  71. if (iHatch & RB_DITHERCOLOR)
  72. {
  73. // Implementing DITHERONREALIZE increased our score on a certain
  74. // unmentionable benchmark by 0.4 million 'megapixels'. Too bad
  75. // this didn't work in the first version of NT.
  76. prb = BRUSHOBJ_pvAllocRbrush(pbo,
  77. sizeof(RBRUSH) + (TOTAL_BRUSH_SIZE * ppdev->cjPel));
  78. if (prb == NULL)
  79. goto ReturnFalse;
  80. vRealizeDitherPattern(prb, iHatch);
  81. goto ReturnTrue;
  82. }
  83. // We only accelerate 8x8 patterns. Since Win3.1 and Chicago don't
  84. // support patterns of any other size, it's a safe bet that 99.9%
  85. // of the patterns we'll ever get will be 8x8:
  86. if ((psoPattern->sizlBitmap.cx != 8) ||
  87. (psoPattern->sizlBitmap.cy != 8))
  88. goto ReturnFalse;
  89. // At 8bpp, we handle patterns at 1bpp and 8bpp with/without an xlate.
  90. iPatternFormat = psoPattern->iBitmapFormat;
  91. if ((iPatternFormat == BMF_1BPP) ||
  92. (iPatternFormat == ppdev->iBitmapFormat))
  93. {
  94. prb = BRUSHOBJ_pvAllocRbrush(pbo,
  95. sizeof(RBRUSH) + (TOTAL_BRUSH_SIZE * ppdev->cjPel));
  96. if (prb == NULL)
  97. goto ReturnFalse;
  98. // Initialize the fields we need:
  99. prb->fl = 0;
  100. lSrcDelta = psoPattern->lDelta;
  101. pjSrc = (BYTE*) psoPattern->pvScan0;
  102. pjDst = (BYTE*) &prb->aulPattern[0];
  103. if (ppdev->iBitmapFormat == iPatternFormat)
  104. {
  105. if ((pxlo == NULL) || (pxlo->flXlate & XO_TRIVIAL))
  106. {
  107. DISPDBG((1, "Realizing un-translated brush"));
  108. // The pattern is the same colour depth as the screen, and
  109. // there's no translation to be done:
  110. cj = (8 * ppdev->cjPel); // Every pattern is 8 pels wide
  111. for (i = 8; i != 0; i--)
  112. {
  113. RtlCopyMemory(pjDst, pjSrc, cj);
  114. pjSrc += lSrcDelta;
  115. pjDst += cj;
  116. }
  117. }
  118. else if (ppdev->iBitmapFormat == BMF_8BPP)
  119. {
  120. DISPDBG((1, "Realizing 8bpp translated brush"));
  121. // The screen is 8bpp, and there's translation to be done:
  122. pulXlate = pxlo->pulXlate;
  123. for (i = 8; i != 0; i--)
  124. {
  125. for (j = 8; j != 0; j--)
  126. {
  127. *pjDst++ = (BYTE) pulXlate[*pjSrc++];
  128. }
  129. pjSrc += lSrcDelta - 8;
  130. }
  131. }
  132. else
  133. {
  134. // I don't feel like writing code to handle translations
  135. // when our screen is 16bpp or higher (although I probably
  136. // should; we could allocate a temporary buffer and use
  137. // GDI to convert, like is done in the VGA driver).
  138. goto ReturnFalse;
  139. }
  140. }
  141. else
  142. {
  143. ASSERTDD(iPatternFormat == BMF_1BPP, "Expected 1bpp only");
  144. for (i = 8; i != 0; i--)
  145. {
  146. *pjDst = *pjSrc;
  147. pjSrc += lSrcDelta;
  148. pjDst += 1;
  149. }
  150. pulXlate = pxlo->pulXlate;
  151. prb->fl = RBRUSH_2COLOR;
  152. prb->ulBackColor = pulXlate[0];
  153. prb->ulForeColor = pulXlate[1];
  154. }
  155. ReturnTrue:
  156. if (!(prb->fl & RBRUSH_2COLOR))
  157. {
  158. pulRBits = (ULONG*) &prb->aulPattern[0];
  159. prb->cy = 8;
  160. prb->cyLog2 = 3;
  161. prb->xBlockAlign = -1;
  162. // See if pattern is really only 4 scans long:
  163. ASSERTDD(ppdev->iBitmapFormat == BMF_8BPP,
  164. "This only works at 8bpp");
  165. if (pulRBits[0] == pulRBits[8] && pulRBits[1] == pulRBits[9] &&
  166. pulRBits[2] == pulRBits[10] && pulRBits[3] == pulRBits[11] &&
  167. pulRBits[4] == pulRBits[12] && pulRBits[5] == pulRBits[13] &&
  168. pulRBits[6] == pulRBits[14] && pulRBits[7] == pulRBits[15])
  169. {
  170. prb->cy = 4;
  171. prb->cyLog2 = 2;
  172. // See if pattern is really only 2 scans long:
  173. if (pulRBits[0] == pulRBits[4] && pulRBits[1] == pulRBits[5] &&
  174. pulRBits[2] == pulRBits[6] && pulRBits[3] == pulRBits[7])
  175. {
  176. DISPDBG((2, "cy = 2 "));
  177. prb->cy = 2;
  178. prb->cyLog2 = 1;
  179. }
  180. else
  181. {
  182. DISPDBG((2, "cy = 4 "));
  183. }
  184. }
  185. else
  186. {
  187. DISPDBG((2, "cy = 8 "));
  188. }
  189. // See if pattern is really only 4 pels wide:
  190. for (i = prb->cy / 2; i > 0; i--)
  191. {
  192. if (*(pulRBits ) != *(pulRBits + 1) ||
  193. *(pulRBits + 2) != *(pulRBits + 3))
  194. goto Not_4_Wide;
  195. pulRBits += 4;
  196. }
  197. DISPDBG((2, "4pels wide"));
  198. Not_4_Wide:
  199. ;
  200. }
  201. return(TRUE);
  202. }
  203. ReturnFalse:
  204. if (psoPattern != NULL)
  205. {
  206. DISPDBG((1, "Failed realization -- Type: %li Format: %li cx: %li cy: %li",
  207. psoPattern->iType, psoPattern->iBitmapFormat,
  208. psoPattern->sizlBitmap.cx, psoPattern->sizlBitmap.cy));
  209. }
  210. return(FALSE);
  211. }
  212. /******************************Public*Routine******************************\
  213. * VOID vAssertModeBrushCache
  214. *
  215. * Resets the brush cache when we exit out of full-screen.
  216. \**************************************************************************/
  217. VOID vAssertModeBrushCache(
  218. PDEV* ppdev,
  219. BOOL bEnable)
  220. {
  221. }
  222. /******************************Public*Routine******************************\
  223. * BOOL bEnableBrushCache
  224. *
  225. * Allocates off-screen memory for storing the brush cache.
  226. \**************************************************************************/
  227. BOOL bEnableBrushCache(
  228. PDEV* ppdev)
  229. {
  230. return(TRUE);
  231. }
  232. /******************************Public*Routine******************************\
  233. * VOID vDisableBrushCache
  234. *
  235. * Cleans up anything done in bEnableBrushCache.
  236. \**************************************************************************/
  237. VOID vDisableBrushCache(PDEV* ppdev)
  238. {
  239. // We ain't gotta do nothin'
  240. }