|
|
1.1 root 1: /******************************Module*Header*******************************\
2: * Module Name: bitblt.c
3: *
4: * BitBlt
5: *
6: * Copyright (c) 1992 Microsoft Corporation
7: \**************************************************************************/
8: #include "driver.h"
9: #include "bitblt.h"
10:
11: BOOL bConvertBrush(BRUSHINST *pbri);
12: VOID vCompiledBlt(PDEVSURF,LONG,LONG,PDEVSURF,LONG,LONG,
13: LONG,LONG,ULONG,BRUSHINST *,ULONG,ULONG,ULONG *,POINTL *);
14:
15: /******************************Public*Data*********************************\
16: * ROP translation table
17: *
18: * Translates the usual ternary rop into A-vector notation. Each bit in
19: * this new notation corresponds to a term in a polynomial translation of
20: * the rop.
21: *
22: * Rop(D,S,P) = a + a D + a S + a P + a DS + a DP + a SP + a DSP
23: * 0 d s p ds dp sp dsp
24: *
25: * History:
26: * 24-Aug-1990 -by- Donald Sidoroff [donalds]
27: * Added it as a global table for the VGA driver.
28: \**************************************************************************/
29:
30: BYTE gajRop[] =
31: {
32: 0x00, 0xff, 0xb2, 0x4d, 0xd4, 0x2b, 0x66, 0x99,
33: 0x90, 0x6f, 0x22, 0xdd, 0x44, 0xbb, 0xf6, 0x09,
34: 0xe8, 0x17, 0x5a, 0xa5, 0x3c, 0xc3, 0x8e, 0x71,
35: 0x78, 0x87, 0xca, 0x35, 0xac, 0x53, 0x1e, 0xe1,
36: 0xa0, 0x5f, 0x12, 0xed, 0x74, 0x8b, 0xc6, 0x39,
37: 0x30, 0xcf, 0x82, 0x7d, 0xe4, 0x1b, 0x56, 0xa9,
38: 0x48, 0xb7, 0xfa, 0x05, 0x9c, 0x63, 0x2e, 0xd1,
39: 0xd8, 0x27, 0x6a, 0x95, 0x0c, 0xf3, 0xbe, 0x41,
40: 0xc0, 0x3f, 0x72, 0x8d, 0x14, 0xeb, 0xa6, 0x59,
41: 0x50, 0xaf, 0xe2, 0x1d, 0x84, 0x7b, 0x36, 0xc9,
42: 0x28, 0xd7, 0x9a, 0x65, 0xfc, 0x03, 0x4e, 0xb1,
43: 0xb8, 0x47, 0x0a, 0xf5, 0x6c, 0x93, 0xde, 0x21,
44: 0x60, 0x9f, 0xd2, 0x2d, 0xb4, 0x4b, 0x06, 0xf9,
45: 0xf0, 0x0f, 0x42, 0xbd, 0x24, 0xdb, 0x96, 0x69,
46: 0x88, 0x77, 0x3a, 0xc5, 0x5c, 0xa3, 0xee, 0x11,
47: 0x18, 0xe7, 0xaa, 0x55, 0xcc, 0x33, 0x7e, 0x81,
48: 0x80, 0x7f, 0x32, 0xcd, 0x54, 0xab, 0xe6, 0x19,
49: 0x10, 0xef, 0xa2, 0x5d, 0xc4, 0x3b, 0x76, 0x89,
50: 0x68, 0x97, 0xda, 0x25, 0xbc, 0x43, 0x0e, 0xf1,
51: 0xf8, 0x07, 0x4a, 0xb5, 0x2c, 0xd3, 0x9e, 0x61,
52: 0x20, 0xdf, 0x92, 0x6d, 0xf4, 0x0b, 0x46, 0xb9,
53: 0xb0, 0x4f, 0x02, 0xfd, 0x64, 0x9b, 0xd6, 0x29,
54: 0xc8, 0x37, 0x7a, 0x85, 0x1c, 0xe3, 0xae, 0x51,
55: 0x58, 0xa7, 0xea, 0x15, 0x8c, 0x73, 0x3e, 0xc1,
56: 0x40, 0xbf, 0xf2, 0x0d, 0x94, 0x6b, 0x26, 0xd9,
57: 0xd0, 0x2f, 0x62, 0x9d, 0x04, 0xfb, 0xb6, 0x49,
58: 0xa8, 0x57, 0x1a, 0xe5, 0x7c, 0x83, 0xce, 0x31,
59: 0x38, 0xc7, 0x8a, 0x75, 0xec, 0x13, 0x5e, 0xa1,
60: 0xe0, 0x1f, 0x52, 0xad, 0x34, 0xcb, 0x86, 0x79,
61: 0x70, 0x8f, 0xc2, 0x3d, 0xa4, 0x5b, 0x16, 0xe9,
62: 0x08, 0xf7, 0xba, 0x45, 0xdc, 0x23, 0x6e, 0x91,
63: 0x98, 0x67, 0x2a, 0xd5, 0x4c, 0xb3, 0xfe, 0x01
64: };
65:
66:
67: /******************************Public*Data*********************************\
68: * ROP to mix translation table
69: *
70: * Table to translate ternary raster ops to mixes (binary raster ops). Ternary
71: * raster ops that can't be translated to mixes are translated to 0 (0 is not
72: * a valid mix).
73: *
74: \**************************************************************************/
75:
76: UCHAR jRop3ToMix[256] = {
77: R2_BLACK, 0, 0, 0, 0, R2_NOTMERGEPEN, 0, 0,
78: 0, 0, R2_MASKNOTPEN, 0, 0, 0, 0, R2_NOTCOPYPEN,
79: 0, 0, 0, 0, 0, 0, 0, 0,
80: 0, 0, 0, 0, 0, 0, 0, 0,
81: 0, 0, 0, 0, 0, 0, 0, 0,
82: 0, 0, 0, 0, 0, 0, 0, 0,
83: 0, 0, 0, 0, 0, 0, 0, 0,
84: 0, 0, 0, 0, 0, 0, 0, 0,
85: 0, 0, 0, 0, 0, 0, 0, 0,
86: 0, 0, 0, 0, 0, 0, 0, 0,
87: R2_MASKPENNOT, 0, 0, 0, 0, R2_NOT, 0, 0,
88: 0, 0, R2_XORPEN, 0, 0, 0, 0, R2_NOTMASKPEN,
89: 0, 0, 0, 0, 0, 0, 0, 0,
90: 0, 0, 0, 0, 0, 0, 0, 0,
91: 0, 0, 0, 0, 0, 0, 0, 0,
92: 0, 0, 0, 0, 0, 0, 0, 0,
93: 0, 0, 0, 0, 0, 0, 0, 0,
94: 0, 0, 0, 0, 0, 0, 0, 0,
95: 0, 0, 0, 0, 0, 0, 0, 0,
96: 0, 0, 0, 0, 0, 0, 0, 0,
97: R2_MASKPEN, 0, 0, 0, 0, R2_NOTXORPEN, 0, 0,
98: 0, 0, R2_NOP, 0, 0, 0, 0, R2_MERGENOTPEN,
99: 0, 0, 0, 0, 0, 0, 0, 0,
100: 0, 0, 0, 0, 0, 0, 0, 0,
101: 0, 0, 0, 0, 0, 0, 0, 0,
102: 0, 0, 0, 0, 0, 0, 0, 0,
103: 0, 0, 0, 0, 0, 0, 0, 0,
104: 0, 0, 0, 0, 0, 0, 0, 0,
105: 0, 0, 0, 0, 0, 0, 0, 0,
106: 0, 0, 0, 0, 0, 0, 0, 0,
107: R2_COPYPEN, 0, 0, 0, 0, R2_MERGEPENNOT, 0, 0,
108: 0, 0, R2_MERGEPEN, 0, 0, 0, 0, R2_WHITE
109: };
110:
111:
112: /******************************Public*Routine******************************\
113: * VOID DrvBitBlt(pso,pso,pso,pco,pxlo,prcl,pptl,pptl,pdbrush,pptl,rop4)
114: *
115: * Bitblt.
116: *
117: \**************************************************************************/
118:
119: BOOL DrvBitBlt
120: (
121: SURFOBJ *psoTrg, // Target surface
122: SURFOBJ *psoSrc, // Source surface
123: SURFOBJ *psoMask, // Mask
124: CLIPOBJ *pco, // Clip through this
125: XLATEOBJ *pxlo, // Color translation
126: RECTL *prclTrg, // Target offset and extent
127: POINTL *pptlSrc, // Source offset
128: POINTL *pptlMask, // Mask offset
129: BRUSHOBJ *pbo, // Pointer to brush object
130: POINTL *pptlBrush, // Brush offset
131: ROP4 rop4 // Raster operation
132: )
133: {
134: BYTE jForeRop; // Foreground rop in A-vector notation
135: BYTE jBackRop; // Background rop in A-vector notation
136: BYTE jORedRops; // jForeRop | jBackRop
137: BRUSHINST bri; // Instance of a brush
138: BRUSHINST *pbri; // Pointer to a brush instance
139:
140: DEVSURF dsurfSrc; // For source if a DIB
141: PDEVSURF pdsurfTrg; // Pointer for target
142: PDEVSURF pdsurfSrc; // Pointer for source if present
143:
144: ULONG iSolidColor; // Solid color for solid brushes
145: BOOL bMore; // Clip continuation flag
146: ULONG ircl; // Clip enumeration rectangle index
147: RECT_ENUM bben; // Clip enumerator
148: ULONG *pulXlate; // Pointer to color xlate vector
149: BYTE jClipping;
150: MIX mix; // Mix, when solid fill performed
151: RECTL rclTemp;
152: ULONG ulBkColor;
153: ULONG ulFgColor;
154: PRECTL prcl;
155: POINTL ptlTemp;
156: UCHAR *pucDIB4ToVGAConvTables;
157: VOID (*pfnPatBlt)(PDEVSURF,ULONG,PRECTL,MIX, BRUSHINST *,PPOINTL);
158:
159:
160: // Let the engine handle the stuff we can't yet do.
161: if (psoSrc != (SURFOBJ *) NULL) {
162: if ((psoSrc->iBitmapFormat != BMF_1BPP) &&
163: (psoSrc->iBitmapFormat != BMF_4BPP) &&
164: (psoSrc->iBitmapFormat != BMF_8BPP)) {
165:
166: return(EngBitBlt(psoTrg,psoSrc,psoMask,
167: pco,pxlo,prclTrg,pptlSrc,pptlMask,
168: pbo,pptlBrush,rop4));
169:
170: } else {
171: // We only handle SRCCOPY screen-to-screen blts right now
172: if ((psoSrc->dhsurf == psoTrg->dhsurf) && (rop4 != 0x0000CCCC)) {
173:
174: return(EngBitBlt(psoTrg,psoSrc,psoMask,
175: pco,pxlo,prclTrg,pptlSrc,pptlMask,
176: pbo,pptlBrush,rop4));
177: }
178: }
179: }
180:
181: if ((rop4 & 0x000000FF) != ((rop4 >> 8) & 0x000000FF)) {
182:
183: return(EngBitBlt(psoTrg,psoSrc,psoMask,
184: pco,pxlo,prclTrg,pptlSrc,pptlMask,
185: pbo,pptlBrush,rop4));
186: }
187:
188: // Get the target surface's pointer. The target must always be a device
189: // surface
190:
191: pdsurfTrg = (PDEVSURF) psoTrg->dhsurf;
192:
193: // Set up the clipping type
194: if (pco == (CLIPOBJ *) NULL) {
195: // No CLIPOBJ provided, so we don't have to worry about clipping
196: jClipping = DC_TRIVIAL;
197: } else {
198: // Use the CLIPOBJ-provided clipping
199: jClipping = pco->iDComplexity;
200: }
201:
202:
203: // Break the rops with the VGA as the destination surface into two classes,
204: // those that can call special case static code (currently: vTrgBlt(solid
205: // fills) and vAlignedSrcCopy (aligned srccopy blts)), and those that must
206: // call the compiled blt code
207:
208: if (pdsurfTrg->iFormat == BMF_PHYSDEVICE) {
209:
210: // Masked cases must be handled differently
211:
212: if ((rop4 & 0xFF) == ((rop4 >> 8) & 0xFF)) {
213:
214: // Special case static code for no-mask cases
215:
216: // Calculate mix from ROP if possible (not possible if it's truly a
217: // ternary rop or a real rop4, but we can treat all pure binary
218: // rops as mixes rather than rop4s)
219: mix = jRop3ToMix[rop4 & 0xFF];
220: pbri = (BRUSHINST *)NULL;
221:
222: switch (mix) {
223: case R2_MASKNOTPEN:
224: case R2_NOTCOPYPEN:
225: case R2_XORPEN:
226: case R2_MASKPEN:
227: case R2_NOTXORPEN:
228: case R2_MERGENOTPEN:
229: case R2_COPYPEN:
230: case R2_MERGEPEN:
231: case R2_NOTMERGEPEN:
232: case R2_MASKPENNOT:
233: case R2_NOTMASKPEN:
234: case R2_MERGEPENNOT:
235: // vTrgBlt can only handle solid color fills
236: if (pbo->iSolidColor != 0xffffffff)
237: {
238: iSolidColor = pbo->iSolidColor;
239: }
240: else
241: {
242: // TrgBlt can only handle solid brushes, but let's
243: // see if we can use our special case pattern code.
244: //
245: pbri = (BRUSHINST *)pbo->pvRbrush;
246: if (pbri == (BRUSHINST *)NULL)
247: {
248: pbri = (BRUSHINST *)BRUSHOBJ_pvGetRbrush(pbo);
249:
250: if (pbri == (BRUSHINST *)NULL)
251: {
252: return(EngBitBlt(psoTrg, psoSrc, psoMask, pco,
253: pxlo, prclTrg, pptlSrc, pptlMask, pbo,
254: pptlBrush, rop4));
255: }
256: }
257:
258: // We currently only do mono patterns.
259:
260: pfnPatBlt = vMonoPatBlt;
261:
262: if (pbri->usStyle != BRI_MONO_PATTERN)
263: pfnPatBlt = vClrPatBlt;
264:
265: // We only support non-8 wide brushes with R2_COPYPEN
266:
267: if ((mix != R2_COPYPEN) && (pbri->RealWidth != 8))
268: break;
269:
270: }
271: // Rops that are implicit solid colors
272:
273: case R2_NOT:
274: case R2_WHITE:
275: case R2_BLACK:
276: // We can do a special-case solid fill
277:
278: switch(jClipping) {
279: case DC_TRIVIAL:
280:
281: // Just fill the rectangle with a solid color
282: if (pbri == (BRUSHINST *)NULL)
283: {
284: vTrgBlt(pdsurfTrg, 1, prclTrg, mix,
285: iSolidColor);
286: }
287: else
288: {
289: (*pfnPatBlt)(pdsurfTrg, 1, prclTrg, mix,
290: pbri, pptlBrush);
291: }
292: break;
293:
294: case DC_RECT:
295:
296: // Clip the solid fill to the clip rectangle
297: if (!DrvIntersectRect(&rclTemp, prclTrg,
298: &pco->rclBounds)) {
299: return(TRUE);
300: }
301:
302: // Fill the clipped rectangle
303: if (pbri == (BRUSHINST *)NULL)
304: {
305: vTrgBlt(pdsurfTrg, 1, &rclTemp, mix,
306: iSolidColor);
307: }
308: else
309: {
310: (*pfnPatBlt)(pdsurfTrg, 1, &rclTemp, mix,
311: pbri, pptlBrush);
312: }
313: break;
314:
315: case DC_COMPLEX:
316:
317: CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES,
318: CD_ANY, ENUM_RECT_LIMIT);
319:
320: do {
321: bMore = CLIPOBJ_bEnum(pco,(ULONG) sizeof(bben),
322: (PVOID) &bben);
323:
324: for (ircl = 0; ircl < bben.c; ircl++) {
325: PRECTL prcl = &bben.arcl[ircl];
326:
327: DrvIntersectRect(prcl,prcl,prclTrg);
328:
329: if (pbri == (BRUSHINST *)NULL) {
330:
331: vTrgBlt(pdsurfTrg, 1, prcl, mix,
332: iSolidColor);
333: } else {
334:
335: (*pfnPatBlt)(pdsurfTrg, 1, prcl, mix,
336: pbri, pptlBrush);
337: }
338: }
339: } while(bMore);
340: }
341:
342: case R2_NOP:
343: return TRUE;
344:
345: default:
346: break;
347: }
348:
349: // Not a special-case solid fill; see if it's a screen-to-screen
350: // SRCCOPY blt, another of our special cases
351:
352: if (rop4 == 0x0000CCCC) {
353:
354: // SRCCOPY blt
355:
356: if (psoSrc->dhsurf == psoTrg->dhsurf) {
357:
358: INT iCopyDir;
359: PFN_ScreenToScreenBlt pfn_Blt;
360:
361: // It's a screen-to-screen SRCCOPY; special-case it
362:
363: // Determine the direction in which the copy must proceed
364: // Note that although we could detect cases where the source
365: // and dest don't overlap and handle them top to bottom, all
366: // copy directions are equally fast, so there's no reason to go
367: // top to bottom except possibly that it looks better. But it
368: // also takes time to detect non-overlap, so I'm not doing it
369:
370: if (pptlSrc->y >= prclTrg->top) {
371: if (pptlSrc->x >= prclTrg->left) {
372: iCopyDir = CD_RIGHTDOWN;
373: } else {
374: iCopyDir = CD_LEFTDOWN;
375: }
376: } else {
377: if (pptlSrc->x >= prclTrg->left) {
378: iCopyDir = CD_RIGHTUP;
379: } else {
380: iCopyDir = CD_LEFTUP;
381: }
382: }
383:
384: // These values are expected by vAlignedSrcCopy
385:
386: switch(jClipping) {
387:
388: case DC_TRIVIAL:
389: // Just copy the rectangle
390: if ((((prclTrg->left ^ pptlSrc->x) & 0x07) == 0)) {
391: vAlignedSrcCopy(pdsurfTrg, prclTrg,
392: pptlSrc, iCopyDir);
393: } else {
394: vNonAlignedSrcCopy(pdsurfTrg, prclTrg,
395: pptlSrc, iCopyDir);
396: }
397: break;
398:
399: case DC_RECT:
400: // Clip the solid fill to the clip rectangle
401: if (!DrvIntersectRect(&rclTemp, prclTrg, &pco->rclBounds))
402: {
403: return(TRUE);
404: }
405:
406: // Adjust the source point for clipping too
407: ptlTemp.x = pptlSrc->x + rclTemp.left - prclTrg->left;
408: ptlTemp.y = pptlSrc->y + rclTemp.top - prclTrg->top;
409:
410: // Copy the clipped rectangle
411: if ((((prclTrg->left ^ pptlSrc->x) & 0x07) == 0)) {
412: vAlignedSrcCopy(pdsurfTrg, &rclTemp, &ptlTemp,
413: iCopyDir);
414: } else {
415: vNonAlignedSrcCopy(pdsurfTrg, &rclTemp, &ptlTemp,
416: iCopyDir);
417: }
418: break;
419:
420: case DC_COMPLEX:
421:
422: if ((((prclTrg->left ^ pptlSrc->x) & 0x07) == 0)) {
423: pfn_Blt = vAlignedSrcCopy;
424: } else {
425: pfn_Blt = vNonAlignedSrcCopy;
426: }
427:
428: CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES,
429: iCopyDir, ENUM_RECT_LIMIT);
430:
431: do {
432: bMore = CLIPOBJ_bEnum(pco,(ULONG) sizeof(bben),
433: (PVOID) &bben);
434:
435: for (ircl = 0; ircl < bben.c; ircl++) {
436: PRECTL prcl = &bben.arcl[ircl];
437:
438: DrvIntersectRect(prcl,prcl,prclTrg);
439:
440: // Adjust the source point for clipping too
441: ptlTemp.x = pptlSrc->x + prcl->left -
442: prclTrg->left;
443: ptlTemp.y = pptlSrc->y + prcl->top -
444: prclTrg->top;
445: pfn_Blt(pdsurfTrg, prcl,
446: &ptlTemp, iCopyDir);
447: }
448: } while(bMore);
449: break;
450: }
451:
452: return TRUE;
453:
454: } else if ((psoSrc->iType == STYPE_BITMAP) &&
455: (psoSrc->iBitmapFormat == BMF_4BPP) &&
456: ((pxlo == NULL) || (pxlo->flXlate == XO_TRIVIAL))) {
457:
458: // Special case DIB4 to VGA copy if no translation
459:
460: pucDIB4ToVGAConvTables =
461: ((PDEVSURF) psoTrg->dhsurf)->ppdev->
462: pucDIB4ToVGAConvTables;
463:
464: // Make just enough of a fake DEVSURF for the source so
465: // that the DIB to VGA code can work
466:
467: dsurfSrc.lNextScan = psoSrc->lDelta;
468: dsurfSrc.pvBitmapStart = psoSrc->pvScan0;
469:
470: // Clip as needed
471:
472: if ((pco == NULL) || (pco->iDComplexity == DC_TRIVIAL)) {
473:
474: // No clipping, just copy the DIB to the VGA
475:
476: vDIB2VGA((PDEVSURF) psoTrg->dhsurf, &dsurfSrc,
477: prclTrg, pptlSrc, pucDIB4ToVGAConvTables);
478:
479: } else if (pco->iDComplexity == DC_RECT) {
480:
481: // Clip the destination to the clip rectangle; we
482: // should never get a NULL result
483: if (DrvIntersectRect(&rclTemp, prclTrg, &pco->rclBounds)) {
484:
485: // Adjust the source point for clipping too
486: ptlTemp.x = pptlSrc->x + rclTemp.left - prclTrg->left;
487: ptlTemp.y = pptlSrc->y + rclTemp.top - prclTrg->top;
488:
489: // Blt the clipped rectangle
490: vDIB2VGA((PDEVSURF) psoTrg->dhsurf, &dsurfSrc,
491: &rclTemp, &ptlTemp, pucDIB4ToVGAConvTables);
492: }
493: return(TRUE);
494:
495: } else { // DC_COMPLEX:
496:
497: CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES,
498: CD_ANY, ENUM_RECT_LIMIT);
499:
500: do {
501: bMore = CLIPOBJ_bEnum(pco,(ULONG) sizeof(bben),
502: (PVOID) &bben);
503: prcl = bben.arcl;
504: for (ircl = 0; ircl < bben.c; ircl++, prcl++) {
505:
506: // Clip the destination to the clip rectangle;
507: // we should never get a NULL result
508:
509: DrvIntersectRect(prcl,prcl,prclTrg);
510:
511: // Adjust the source point for clipping too
512: ptlTemp.x = pptlSrc->x + prcl->left -
513: prclTrg->left;
514: ptlTemp.y = pptlSrc->y + prcl->top -
515: prclTrg->top;
516:
517: // Blt the clipped rectangle
518: vDIB2VGA((PDEVSURF) psoTrg->dhsurf,
519: &dsurfSrc, prcl, &ptlTemp,
520: pucDIB4ToVGAConvTables);
521: }
522: } while(bMore);
523: }
524:
525: return(TRUE);
526:
527: }
528: }
529: }
530: }
531:
532:
533: // Couldn't be special cased. Set up to call the old kludged compiling code.
534:
535:
536: {
537: LONG xSrc;
538: LONG ySrc;
539: RECTL *prcl;
540:
541:
542: // Translate the rop from old notation into two A-vector rops
543:
544: jForeRop = gajRop[rop4 & 0xff];
545: jBackRop = gajRop[(rop4 >> 8) & 0xff];
546: jORedRops = jForeRop | jBackRop;
547:
548:
549: // Get the source surface if a source is needed. The source may be any of
550: // 1) the screen, 2) a device managed bitmap, 3) an engine bitmap
551:
552: if (jORedRops & AVEC_NEED_SOURCE) {
553:
554: if (psoSrc->dhsurf == (DHSURF) 0) {
555: // Source is an engine bitmap
556: #ifdef FIREWALLS
557: dsurfSrc.ident = 0x46525354; // "TSRF"
558: #endif
559: dsurfSrc.flSurf = DS_DIB; // Supporting a DIB
560: dsurfSrc.iFormat = (BYTE)psoSrc->iBitmapFormat;
561: dsurfSrc.sizlSurf = psoSrc->sizlBitmap;
562: dsurfSrc.lNextScan = psoSrc->lDelta;
563: dsurfSrc.pvScan0 = psoSrc->pvScan0;
564: dsurfSrc.pvBitmapStart = psoSrc->pvScan0;
565: dsurfSrc.pvConv = pdsurfTrg->pvConv;
566:
567: pdsurfSrc = &dsurfSrc; // Construct source into here
568:
569: } else {
570: // Source is a device format bitmap or the device itself
571: pdsurfSrc = (PDEVSURF) psoSrc->dhsurf;
572: }
573: } else {
574: pdsurfSrc = (PDEVSURF) NULL; // Assume no source
575: }
576:
577:
578: // If a brush is required, do what is necessary to get it. We might be
579: // able to just use the solid color accelerator, we might have to force it
580: // to be realized (which could fail).
581:
582: if (jORedRops & AVEC_NEED_PATTERN) {
583:
584: // See if there is a solid color accelerator for the brush. If so
585: // we can just pick it up and use it.
586:
587: if (pbo->iSolidColor != 0xffffffff) {
588: bri.usStyle = BRI_SOLID;
589: bri.fjAccel =
590: (BYTE)((pbo->iSolidColor & COLOR_BITS) | SOLID_BRUSH);
591: pbri = &bri;
592: } else {
593: // If there is no realization of the brush, we must force it
594:
595: if (pbo->pvRbrush == (PVOID)NULL)
596: {
597: pbri = (BRUSHINST *)BRUSHOBJ_pvGetRbrush(pbo);
598:
599: if (pbri == (BRUSHINST *)NULL)
600: {
601: return(EngBitBlt(psoTrg, psoSrc, psoMask, pco, pxlo,
602: prclTrg, pptlSrc, pptlMask, pbo, pptlBrush,
603: rop4));
604: }
605: }
606: else
607: {
608: pbri = (BRUSHINST *)pbo->pvRbrush;
609: }
610:
611: if (!bConvertBrush(pbri)) {
612: return(EngBitBlt(psoTrg, psoSrc, psoMask, pco, pxlo,
613: prclTrg, pptlSrc, pptlMask, pbo, pptlBrush, rop4));
614: }
615: }
616: }
617:
618:
619:
620: // Determine if color translation is required. If so, then get the
621: // color translation vector. if no source is involved, then no
622: // xlateobj will have been passed.
623:
624: if ((jORedRops & AVEC_NEED_SOURCE) &&
625: (pxlo != NULL) &&
626: (pxlo->flXlate & XO_TABLE))
627: {
628: pulXlate = pxlo->pulXlate;
629: ulFgColor = pulXlate[0] << 24; // Mono --> color translation
630: ulBkColor = pulXlate[1] << 24;
631: }
632: else
633: {
634: pulXlate = (PULONG) NULL; // No xlate vector
635: }
636:
637:
638: // Note: blts where VGA memory is both the source and the destination
639: // should never make it to this point; it's assumed that the VGA is the
640: // destination and the destination only
641: // BUGBUG this must be changed when we support DFBs, to make VGAs
642: // possibly neither source nor destination, and (maybe?) source but DFB
643: // dest
644:
645: // Perform blt with specified clipping.
646: // BUGBUG only top->bottom blts are currently supported
647:
648: switch(jClipping) {
649:
650: RECTL rclTemp;
651:
652: case DC_RECT:
653: if (!DrvIntersectRect(&rclTemp, prclTrg, &pco->rclBounds)) {
654: break;
655: }
656:
657: // Adjust the source (if any) accordingly
658: if (jORedRops & AVEC_NEED_SOURCE) {
659: pptlSrc->x += rclTemp.left - prclTrg->left;
660: pptlSrc->y += rclTemp.top - prclTrg->top;
661: }
662:
663: *prclTrg = rclTemp;
664:
665: case DC_TRIVIAL:
666:
667: // Cycle through all banks that the blt dest spans
668:
669: // If the proper bank for the top scan line of
670: // the blt dest isn't mapped in, map it in
671: if ((prclTrg->top < pdsurfTrg->rcl1WindowClip.top) ||
672: (prclTrg->top >= pdsurfTrg->rcl1WindowClip.bottom)) {
673:
674: // Map in the bank containing the top line of the blt dest
675: pdsurfTrg->pfnBankControl(pdsurfTrg,
676: prclTrg->top,
677: JustifyTop);
678: }
679:
680: // Now draw the part of the rect that's in each bank
681: for (;;) {
682:
683: // Clip the blt dest to the bank
684: DrvIntersectRect(&rclTemp, prclTrg,
685: &pdsurfTrg->rcl1WindowClip);
686:
687: // Adjust the source (if any) accordingly
688: if (jORedRops & AVEC_NEED_SOURCE) {
689: xSrc = pptlSrc->x + rclTemp.left - prclTrg->left;
690: ySrc = pptlSrc->y + rclTemp.top - prclTrg->top;
691: }
692:
693: vCompiledBlt(pdsurfTrg,
694: rclTemp.left,
695: rclTemp.top,
696: pdsurfSrc,
697: xSrc,
698: ySrc,
699: rclTemp.right - rclTemp.left,
700: rclTemp.bottom - rclTemp.top,
701: rop4,
702: pbri,
703: ulBkColor,
704: ulFgColor,
705: pulXlate,
706: pptlBrush);
707:
708: // Done if this bank contains the last line of the blt
709: if (prclTrg->bottom <=
710: pdsurfTrg->rcl1WindowClip.bottom) {
711: break;
712: }
713:
714: // Map in the next bank
715: pdsurfTrg->pfnBankControl(pdsurfTrg,
716: pdsurfTrg->rcl1WindowClip.bottom,
717: JustifyTop);
718: }
719:
720: break;
721:
722:
723: case DC_COMPLEX:
724:
725: CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, CD_ANY, ENUM_RECT_LIMIT);
726: bMore = TRUE;
727:
728: do {
729: if (bMore) {
730: // Enumerate more clip rects
731: bMore = CLIPOBJ_bEnum(pco,(ULONG) sizeof(bben),
732: (PVOID) &bben);
733: }
734:
735: // Draw the portion of the blt dest that intersects each
736: // clip rect in turn
737: for (ircl = 0; ircl < bben.c; ircl++) {
738:
739: prcl = &bben.arcl[ircl];
740:
741: // Find the intersection of the target rect and the
742: // current clip rect, then draw all banks of the
743: // clipped target rect, if it's not NULL
744: DrvIntersectRect(prcl, prcl, prclTrg);
745:
746: // Cycle through all banks that the blt dest spans
747:
748: // If the proper bank for the top scan line of
749: // the blt dest isn't mapped in, map it in
750: if ((prcl->top <
751: pdsurfTrg->rcl1WindowClip.top) ||
752: (prcl->top >=
753: pdsurfTrg->rcl1WindowClip.bottom)) {
754:
755: // Map in the bank containing the top line of
756: // the blt dest
757: pdsurfTrg->pfnBankControl(pdsurfTrg,
758: prcl->top,
759: JustifyTop);
760: }
761:
762: // Now draw the part of the clipped rect that's in
763: // each bank
764: for (;;) {
765:
766: RECTL rclTemp;
767:
768: // Clip the blt dest to the bank
769: DrvIntersectRect(&rclTemp, prcl,
770: &pdsurfTrg->rcl1WindowClip);
771:
772: // Adjust the source (if any) accordingly
773: if (jORedRops & AVEC_NEED_SOURCE) {
774: xSrc = pptlSrc->x + rclTemp.left -
775: prclTrg->left;
776: ySrc = pptlSrc->y + rclTemp.top -
777: prclTrg->top;
778: }
779:
780: vCompiledBlt(pdsurfTrg,
781: rclTemp.left,
782: rclTemp.top,
783: pdsurfSrc,
784: xSrc,
785: ySrc,
786: rclTemp.right - rclTemp.left,
787: rclTemp.bottom - rclTemp.top,
788: rop4,
789: pbri,
790: ulBkColor,
791: ulFgColor,
792: pulXlate,
793: pptlBrush);
794:
795: // Done if this bank contains the last line of
796: // the blt
797: if (prcl->bottom <=
798: pdsurfTrg->rcl1WindowClip.bottom) {
799: break;
800: }
801:
802: // Map in the next bank
803: pdsurfTrg->pfnBankControl(pdsurfTrg,
804: pdsurfTrg->rcl1WindowClip.bottom,
805: JustifyTop);
806: }
807: }
808: } while(bMore);
809:
810: break;
811:
812: } // switch(jClipping);
813:
814: }
815:
816: return TRUE;
817: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.