|
|
1.1 root 1: /******************************Module*Header*******************************\
2: * Module Name: Brush.c
3: *
4: * Brush support.
5: *
6: * Copyright (c) 1992-1993 Microsoft Corporation
7: *
8: \**************************************************************************/
9:
10: #include "driver.h"
11:
12: /****************************************************************************
13: * DrvRealizeBrush
14: ***************************************************************************/
15:
16: BOOL DrvRealizeBrush(
17: BRUSHOBJ* pbo,
18: SURFOBJ* psoTarget,
19: SURFOBJ* psoPattern,
20: SURFOBJ* psoMask,
21: XLATEOBJ* pxlo,
22: ULONG iHatch)
23: {
24: RBRUSH* prb; // Pointer to where realization goes
25: ULONG* pulSrc; // Temporary pointer
26: ULONG* pulDst; // Temporary pointer
27: BYTE* pjSrc;
28: BYTE* pjDst;
29: ULONG* pulRBits; // Points to RBRUSH pattern bits
30: BYTE jBkColor;
31: BYTE jFgColor;
32: LONG i;
33: LONG j;
34:
35: PPDEV ppdev = (PPDEV) psoTarget->dhsurf;
36:
37: // For now, we only accelerate patterns using the latches, and we
38: // sometimes need offscreen memory as a temporary work space to
39: // initialize the latches for 2-color patterns:
40:
41: if ((ppdev->fl & (DRIVER_PLANAR_CAPABLE | DRIVER_HAS_OFFSCREEN)) !=
42: (DRIVER_PLANAR_CAPABLE | DRIVER_HAS_OFFSCREEN) )
43: {
44: return(FALSE);
45: }
46:
47: // See if it's a default hatch brush:
48:
49: if (iHatch < HS_DDI_MAX)
50: {
51: DISPDBG((1, "\n RBrush: Default"));
52:
53: prb = BRUSHOBJ_pvAllocRbrush(pbo, sizeof(RBRUSH));
54: if (prb == NULL)
55: return(FALSE);
56:
57: prb->xBrush = 0;
58: prb->ulBkColor = (pxlo->pulXlate[0] & 0xff);
59: prb->ulFgColor = (pxlo->pulXlate[1] & 0xff);
60:
61: if (prb->ulFgColor == 0xff && prb->ulBkColor == 0x00)
62: {
63: prb->fl = RBRUSH_BLACKWHITE;
64: memcpy(&prb->aulPattern[0],
65: &gaaulPlanarPat[iHatch][0],
66: 8 * sizeof(DWORD));
67: }
68: else if (prb->ulFgColor == 0x00 && prb->ulBkColor == 0xff)
69: {
70: // We have to invert the brush:
71:
72: prb->fl = RBRUSH_BLACKWHITE;
73: for (i = 0; i < 8; i++)
74: {
75: prb->aulPattern[i] = ~gaaulPlanarPat[iHatch][i];
76: }
77: }
78: else
79: {
80: prb->fl = RBRUSH_2COLOR;
81: memmove(&prb->aulPattern[0], &gaaulPlanarPat[iHatch][0], 32);
82: }
83:
84: return(TRUE);
85: }
86:
87: // We only accelerate 8x8 patterns:
88:
89: if (psoPattern->sizlBitmap.cx != 8 || psoPattern->sizlBitmap.cy != 8)
90: return(FALSE);
91:
92: // We only implement n-color patterns on devices that have multiple
93: // or separate read/write banks:
94:
95: if (ppdev->vbtPlanarType == VideoBanked1RW)
96: return(FALSE);
97:
98: // We also only handle 1bpp, 4bpp and 8bpp patterns:
99:
100: if (psoPattern->iBitmapFormat > BMF_8BPP)
101: return(FALSE);
102:
103: // At this point, we're definitely going to realize the brush:
104:
105: prb = BRUSHOBJ_pvAllocRbrush(pbo, sizeof(RBRUSH));
106: if (prb == NULL)
107: return(FALSE);
108:
109: pulRBits = &prb->aulPattern[0];
110:
111: DISPDBG((1, "\n RBrush: "));
112:
113: // If 8bpp or 4bpp, copy the bitmap to our local buffer:
114:
115: if (psoPattern->iBitmapFormat == BMF_1BPP)
116: {
117: ULONG ulFlippedGlyph;
118:
119: DISPDBG((1, "1bpp "));
120:
121: // First, convert the bits to our desired format:
122:
123: pjSrc = psoPattern->pvScan0;
124: pulDst = pulRBits;
125: for (i = 8; i > 0; i--)
126: {
127: // We want to take the byte with bits 76543210 and convert it
128: // to the word 4567012301234567. The pjGlyphFlipTable gives
129: // us 45670123 from 76543210.
130:
131: ulFlippedGlyph = (ULONG) ppdev->pjGlyphFlipTable[*pjSrc];
132: *pulDst = (ulFlippedGlyph << 8) | ((ulFlippedGlyph & 15) << 4) |
133: (ulFlippedGlyph >> 4);
134:
135: pulDst++;
136: pjSrc += psoPattern->lDelta;
137: }
138:
139: // Now initialize the rest of the RBrush fields:
140:
141: prb->xBrush = 0;
142: prb->ulBkColor = (pxlo->pulXlate[0] & 0xff);
143: prb->ulFgColor = (pxlo->pulXlate[1] & 0xff);
144:
145: if (prb->ulFgColor == 0xff && prb->ulBkColor == 0x00)
146: {
147: prb->fl = RBRUSH_BLACKWHITE;
148: }
149: else if (prb->ulFgColor == 0x00 && prb->ulBkColor == 0xff)
150: {
151: // We have to invert the brush:
152:
153: prb->fl = RBRUSH_BLACKWHITE;
154: for (i = 0; i < 8; i++)
155: {
156: prb->aulPattern[i] = ~prb->aulPattern[i];
157: }
158: }
159: else
160: {
161: prb->fl = RBRUSH_2COLOR;
162: }
163:
164: return(TRUE);
165: }
166: else if (psoPattern->iBitmapFormat == BMF_8BPP)
167: {
168:
169: if (pxlo == NULL || pxlo->flXlate & XO_TRIVIAL)
170: {
171: pulSrc = psoPattern->pvScan0;
172: pulDst = pulRBits;
173:
174: DISPDBG((1, "8bpp noxlate "));
175:
176: // 8bpp no translate case:
177:
178: for (i = 4; i > 0; i--)
179: {
180: *(pulDst) = *(pulSrc);
181: *(pulDst + 1) = *(pulSrc + 1);
182: pulSrc = (ULONG*) ((BYTE*) pulSrc + psoPattern->lDelta);
183:
184: *(pulDst + 2) = *(pulSrc);
185: *(pulDst + 3) = *(pulSrc + 1);
186:
187: pulSrc = (ULONG*) ((BYTE*) pulSrc + psoPattern->lDelta);
188: pulDst += 4;
189: }
190: }
191: else
192: {
193: pjSrc = (BYTE*) psoPattern->pvScan0;
194: pjDst = (BYTE*) pulRBits;
195:
196: DISPDBG((1, "8bpp xlate "));
197:
198: // 8bpp translate case:
199:
200: for (i = 8; i > 0; i--)
201: {
202: for (j = 8; j > 0; j--)
203: {
204: *pjDst++ = (BYTE) pxlo->pulXlate[*pjSrc++];
205: }
206:
207: pjSrc += psoPattern->lDelta - 8;
208: }
209: }
210: }
211: else
212: {
213: DISPDBG((1, "4bpp xlate "));
214:
215: ASSERTVGA(psoPattern->iBitmapFormat == BMF_4BPP, "Extra case added?");
216:
217: // 4bpp case:
218:
219: pjSrc = (BYTE*) psoPattern->pvScan0;
220: pjDst = (BYTE*) pulRBits;
221:
222: for (i = 8; i > 0; i--)
223: {
224: // Inner loop is repeated only 4 times because each loop handles
225: // 2 pixels:
226:
227: for (j = 4; j > 0; j--)
228: {
229: *pjDst++ = (BYTE) pxlo->pulXlate[*pjSrc >> 4];
230: *pjDst++ = (BYTE) pxlo->pulXlate[*pjSrc & 15];
231: pjSrc++;
232: }
233:
234: pjSrc += psoPattern->lDelta - 4;
235: }
236: }
237:
238: // We want to check if the 4bpp or 8bpp patterns are actually
239: // only two colors:
240:
241: if (b2ColorBrush(pulRBits, &jFgColor, &jBkColor))
242: {
243: DISPDBG((1, "2 color "));
244:
245: // ??? We could actually also handle this case even if we have only
246: // 1 r/w window in planar format:
247:
248: prb->xBrush = 0;
249: prb->ulBkColor = (ULONG) jBkColor;
250: prb->ulFgColor = (ULONG) jFgColor;
251: prb->fl = RBRUSH_2COLOR;
252:
253: if (jFgColor == 0x00 && jBkColor == 0xff)
254: {
255: // Monochrome brushes always have to have the '0' bits
256: // as black and the '1' bits as white, so we'll have to
257: // invert the 1bpp pattern:
258:
259: prb->fl = RBRUSH_BLACKWHITE;
260: for (i = 0; i < 8; i++)
261: {
262: prb->aulPattern[i] = ~prb->aulPattern[i];
263: }
264: }
265:
266: return(TRUE);
267: }
268:
269: // For n-color brushes, we maintain a brush cache in offscreen memory.
270: // If the DRIVER_USE_OFFSCREEN flag isn't set (i.e., the offscreen
271: // memory isn't being refreshed), the cache is pretty useless. In that
272: // case, we simply disable n-color patterns:
273:
274: if ((ppdev->fl & DRIVER_USE_OFFSCREEN) == 0)
275: {
276: return(FALSE);
277: }
278:
279: prb->fl = RBRUSH_NCOLOR;
280: prb->cy = 8;
281: prb->cyLog2 = 3;
282:
283: // xBrush is the brush alignment for the cached brush, and this value
284: // will get compared to (pptlBrush->x & 7) to see if the cache brush
285: // is correctly aligned with the brush requested. Since it will never
286: // match with -1, the brush will be correctly aligned and placed in
287: // the cache (which, of course, is what we want to finish our
288: // initialization):
289:
290: prb->xBrush = -1;
291:
292: // Copy those bitmap bits:
293:
294: // See if pattern is really only 4 scans long:
295:
296: if (pulRBits[0] == pulRBits[8] && pulRBits[1] == pulRBits[9] &&
297: pulRBits[2] == pulRBits[10] && pulRBits[3] == pulRBits[11] &&
298: pulRBits[4] == pulRBits[12] && pulRBits[5] == pulRBits[13] &&
299: pulRBits[6] == pulRBits[14] && pulRBits[7] == pulRBits[15])
300: {
301: prb->cy = 4;
302: prb->cyLog2 = 2;
303:
304: // See if pattern is really only 2 scans long:
305:
306: if (pulRBits[0] == pulRBits[4] && pulRBits[1] == pulRBits[5] &&
307: pulRBits[2] == pulRBits[6] && pulRBits[3] == pulRBits[7])
308: {
309: DISPDBG((1, "cy = 2 "));
310:
311: prb->cy = 2;
312: prb->cyLog2 = 1;
313: }
314: else
315: {
316: DISPDBG((1, "cy = 4 "));
317: }
318: }
319:
320: // See if pattern is really only 4 pels wide:
321:
322: pulDst = pulRBits;
323: for (i = prb->cy / 2; i > 0; i--)
324: {
325: if (*(pulDst ) != *(pulDst + 1) ||
326: *(pulDst + 2) != *(pulDst + 3))
327: goto done_this_realize_brush_stuff;
328:
329: pulDst += 4;
330: }
331:
332: DISPDBG((1, "4pels wide"));
333:
334: prb->fl |= RBRUSH_4PELS_WIDE;
335:
336: done_this_realize_brush_stuff:
337:
338: return(TRUE);
339: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.