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.

289 lines
8.0 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: Brush.c
  3. *
  4. * Brush support.
  5. *
  6. * Copyright (c) 1992-1993 Microsoft Corporation
  7. *
  8. \**************************************************************************/
  9. #include "driver.h"
  10. /****************************************************************************
  11. * DrvRealizeBrush
  12. ***************************************************************************/
  13. BOOL DrvRealizeBrush(
  14. BRUSHOBJ* pbo,
  15. SURFOBJ* psoTarget,
  16. SURFOBJ* psoPattern,
  17. SURFOBJ* psoMask,
  18. XLATEOBJ* pxlo,
  19. ULONG iHatch)
  20. {
  21. RBRUSH* prb; // Pointer to where realization goes
  22. ULONG* pulSrc; // Temporary pointer
  23. ULONG* pulDst; // Temporary pointer
  24. BYTE* pjSrc;
  25. BYTE* pjDst;
  26. ULONG* pulRBits; // Points to RBRUSH pattern bits
  27. BYTE jBkColor;
  28. BYTE jFgColor;
  29. LONG i;
  30. LONG j;
  31. PPDEV ppdev = (PPDEV) psoTarget->dhsurf;
  32. // For now, we only accelerate patterns using the latches, and we
  33. // sometimes need offscreen memory as a temporary work space to
  34. // initialize the latches for 2-color patterns:
  35. if ((ppdev->fl & (DRIVER_PLANAR_CAPABLE | DRIVER_HAS_OFFSCREEN)) !=
  36. (DRIVER_PLANAR_CAPABLE | DRIVER_HAS_OFFSCREEN) )
  37. {
  38. return(FALSE);
  39. }
  40. // We only accelerate 8x8 patterns:
  41. if (psoPattern->sizlBitmap.cx != 8 || psoPattern->sizlBitmap.cy != 8)
  42. return(FALSE);
  43. // We only implement n-color patterns on devices that have multiple
  44. // or separate read/write banks:
  45. if (ppdev->vbtPlanarType == VideoBanked1RW)
  46. return(FALSE);
  47. // We also only handle 1bpp, 4bpp and 8bpp patterns:
  48. if (psoPattern->iBitmapFormat > BMF_8BPP)
  49. return(FALSE);
  50. // At this point, we're definitely going to realize the brush:
  51. prb = BRUSHOBJ_pvAllocRbrush(pbo, sizeof(RBRUSH));
  52. if (prb == NULL)
  53. return(FALSE);
  54. pulRBits = &prb->aulPattern[0];
  55. DISPDBG((2, "\n RBrush: "));
  56. // If 8bpp or 4bpp, copy the bitmap to our local buffer:
  57. if (psoPattern->iBitmapFormat == BMF_1BPP)
  58. {
  59. ULONG ulFlippedGlyph;
  60. DISPDBG((2, "1bpp "));
  61. // First, convert the bits to our desired format:
  62. pjSrc = psoPattern->pvScan0;
  63. pulDst = pulRBits;
  64. for (i = 8; i > 0; i--)
  65. {
  66. // We want to take the byte with bits 76543210 and convert it
  67. // to the word 4567012301234567. The pjGlyphFlipTable gives
  68. // us 45670123 from 76543210.
  69. ulFlippedGlyph = (ULONG) ppdev->pjGlyphFlipTable[*pjSrc];
  70. *pulDst = (ulFlippedGlyph << 8) | ((ulFlippedGlyph & 15) << 4) |
  71. (ulFlippedGlyph >> 4);
  72. pulDst++;
  73. pjSrc += psoPattern->lDelta;
  74. }
  75. // Now initialize the rest of the RBrush fields:
  76. prb->xBrush = 0;
  77. prb->ulBkColor = (pxlo->pulXlate[0] & 0xff);
  78. prb->ulFgColor = (pxlo->pulXlate[1] & 0xff);
  79. if (prb->ulFgColor == 0xff && prb->ulBkColor == 0x00)
  80. {
  81. prb->fl = RBRUSH_BLACKWHITE;
  82. }
  83. else if (prb->ulFgColor == 0x00 && prb->ulBkColor == 0xff)
  84. {
  85. // We have to invert the brush:
  86. prb->fl = RBRUSH_BLACKWHITE;
  87. for (i = 0; i < 8; i++)
  88. {
  89. prb->aulPattern[i] = ~prb->aulPattern[i];
  90. }
  91. }
  92. else
  93. {
  94. prb->fl = RBRUSH_2COLOR;
  95. }
  96. return(TRUE);
  97. }
  98. else if (psoPattern->iBitmapFormat == BMF_8BPP)
  99. {
  100. if (pxlo == NULL || pxlo->flXlate & XO_TRIVIAL)
  101. {
  102. pulSrc = psoPattern->pvScan0;
  103. pulDst = pulRBits;
  104. DISPDBG((2, "8bpp noxlate "));
  105. // 8bpp no translate case:
  106. for (i = 4; i > 0; i--)
  107. {
  108. *(pulDst) = *(pulSrc);
  109. *(pulDst + 1) = *(pulSrc + 1);
  110. pulSrc = (ULONG*) ((BYTE*) pulSrc + psoPattern->lDelta);
  111. *(pulDst + 2) = *(pulSrc);
  112. *(pulDst + 3) = *(pulSrc + 1);
  113. pulSrc = (ULONG*) ((BYTE*) pulSrc + psoPattern->lDelta);
  114. pulDst += 4;
  115. }
  116. }
  117. else
  118. {
  119. pjSrc = (BYTE*) psoPattern->pvScan0;
  120. pjDst = (BYTE*) pulRBits;
  121. DISPDBG((2, "8bpp xlate "));
  122. // 8bpp translate case:
  123. for (i = 8; i > 0; i--)
  124. {
  125. for (j = 8; j > 0; j--)
  126. {
  127. *pjDst++ = (BYTE) pxlo->pulXlate[*pjSrc++];
  128. }
  129. pjSrc += psoPattern->lDelta - 8;
  130. }
  131. }
  132. }
  133. else
  134. {
  135. DISPDBG((2, "4bpp xlate "));
  136. ASSERTVGA(psoPattern->iBitmapFormat == BMF_4BPP, "Extra case added?");
  137. // 4bpp case:
  138. pjSrc = (BYTE*) psoPattern->pvScan0;
  139. pjDst = (BYTE*) pulRBits;
  140. for (i = 8; i > 0; i--)
  141. {
  142. // Inner loop is repeated only 4 times because each loop handles
  143. // 2 pixels:
  144. for (j = 4; j > 0; j--)
  145. {
  146. *pjDst++ = (BYTE) pxlo->pulXlate[*pjSrc >> 4];
  147. *pjDst++ = (BYTE) pxlo->pulXlate[*pjSrc & 15];
  148. pjSrc++;
  149. }
  150. pjSrc += psoPattern->lDelta - 4;
  151. }
  152. }
  153. // We want to check if the 4bpp or 8bpp patterns are actually
  154. // only two colors:
  155. if (b2ColorBrush(pulRBits, &jFgColor, &jBkColor))
  156. {
  157. DISPDBG((2, "2 color "));
  158. // ??? We could actually also handle this case even if we have only
  159. // 1 r/w window in planar format:
  160. prb->xBrush = 0;
  161. prb->ulBkColor = (ULONG) jBkColor;
  162. prb->ulFgColor = (ULONG) jFgColor;
  163. prb->fl = RBRUSH_2COLOR;
  164. if (jFgColor == 0x00 && jBkColor == 0xff)
  165. {
  166. // Monochrome brushes always have to have the '0' bits
  167. // as black and the '1' bits as white, so we'll have to
  168. // invert the 1bpp pattern:
  169. prb->fl = RBRUSH_BLACKWHITE;
  170. for (i = 0; i < 8; i++)
  171. {
  172. prb->aulPattern[i] = ~prb->aulPattern[i];
  173. }
  174. }
  175. return(TRUE);
  176. }
  177. prb->fl = RBRUSH_NCOLOR;
  178. prb->cy = 8;
  179. prb->cyLog2 = 3;
  180. // xBrush is the brush alignment for the cached brush, and this value
  181. // will get compared to (pptlBrush->x & 7) to see if the cache brush
  182. // is correctly aligned with the brush requested. Since it will never
  183. // match with -1, the brush will be correctly aligned and placed in
  184. // the cache (which, of course, is what we want to finish our
  185. // initialization):
  186. prb->xBrush = -1;
  187. // Copy those bitmap bits:
  188. // See if pattern is really only 4 scans long:
  189. if (pulRBits[0] == pulRBits[8] && pulRBits[1] == pulRBits[9] &&
  190. pulRBits[2] == pulRBits[10] && pulRBits[3] == pulRBits[11] &&
  191. pulRBits[4] == pulRBits[12] && pulRBits[5] == pulRBits[13] &&
  192. pulRBits[6] == pulRBits[14] && pulRBits[7] == pulRBits[15])
  193. {
  194. prb->cy = 4;
  195. prb->cyLog2 = 2;
  196. // See if pattern is really only 2 scans long:
  197. if (pulRBits[0] == pulRBits[4] && pulRBits[1] == pulRBits[5] &&
  198. pulRBits[2] == pulRBits[6] && pulRBits[3] == pulRBits[7])
  199. {
  200. DISPDBG((2, "cy = 2 "));
  201. prb->cy = 2;
  202. prb->cyLog2 = 1;
  203. }
  204. else
  205. {
  206. DISPDBG((2, "cy = 4 "));
  207. }
  208. }
  209. // See if pattern is really only 4 pels wide:
  210. pulDst = pulRBits;
  211. for (i = prb->cy / 2; i > 0; i--)
  212. {
  213. if (*(pulDst ) != *(pulDst + 1) ||
  214. *(pulDst + 2) != *(pulDst + 3))
  215. goto done_this_realize_brush_stuff;
  216. pulDst += 4;
  217. }
  218. DISPDBG((2, "4pels wide"));
  219. prb->fl |= RBRUSH_4PELS_WIDE;
  220. done_this_realize_brush_stuff:
  221. return(TRUE);
  222. }