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