|
|
1.1 root 1: /******************************Module*Header*******************************\
2: * Module Name: bitblt.c
3: *
4: * Banked Frame Buffer bitblit
5: *
6: * Copyright (c) 1992 Microsoft Corporation
7: *
8: \**************************************************************************/
9:
10: #include "driver.h"
11:
12: /************************************************************************\
13: * bIntersectRect
14: *
15: * Calculates the intersection between *prcSrc1 and *prcSrc2,
16: * returning the resulting rect in *prcDst. Returns TRUE if
17: * *prcSrc1 intersects *prcSrc2, FALSE otherwise. If there is no
18: * intersection, an empty rect is returned in *prcDst.
19: \************************************************************************/
20:
21: static const RECTL rclEmpty = { 0, 0, 0, 0 };
22:
23: BOOL bIntersectRect(
24: PRECTL prcDst,
25: PRECTL prcSrc1,
26: PRECTL prcSrc2)
27:
28: {
29: prcDst->left = max(prcSrc1->left, prcSrc2->left);
30: prcDst->right = min(prcSrc1->right, prcSrc2->right);
31:
32: // check for empty rect
33:
34: if (prcDst->left < prcDst->right)
35: {
36: prcDst->top = max(prcSrc1->top, prcSrc2->top);
37: prcDst->bottom = min(prcSrc1->bottom, prcSrc2->bottom);
38:
39: // check for empty rect
40:
41: if (prcDst->top < prcDst->bottom)
42: return(TRUE); // not empty
43: }
44:
45: // empty rect
46:
47: *prcDst = rclEmpty;
48:
49: return(FALSE);
50: }
51:
52: /******************************Public*Routine******************************\
53: * BOOL bPuntScreenToScreenCopyBits(ppdev, pco, pxlo, prclDest, pptlSrc)
54: *
55: * Performs a screen-to-screen CopyBits entirely using an intermediate
56: * temporary buffer and GDI.
57: *
58: * We found that on most machines it was faster to have the engine copy
59: * the source to a buffer, then blit the buffer to the destination, than
60: * to have optimized ASM code that copies a word at a time. The reason?
61: * The engine does d-word moves, which are faster than word moves even
62: * going over the bus to a 16 bit display device.
63: *
64: * We could also write optimized ASM code that does d-word moves, but the
65: * win will be marginal, we're time constrained, we also need a routine
66: * like this to handle complex clip objects and palette translates, and
67: * most of the other times we can use planar copies for important things
68: * like scrolls, anyways.
69: *
70: \**************************************************************************/
71:
72: BOOL bPuntScreenToScreenCopyBits(
73: PPDEV ppdev,
74: CLIPOBJ* pco,
75: XLATEOBJ* pxlo,
76: RECTL* prclDest,
77: POINTL* pptlSrc)
78: {
79: RECTL rclDest;
80: POINTL ptlSrc;
81: BOOL b = TRUE;
82:
83: SURFOBJ* pso = ppdev->pSurfObj;
84: SURFOBJ* psoTmp = ppdev->psoTmp;
85:
86: if (prclDest->top < pptlSrc->y)
87: {
88: ////////////////////////////////////////////////////////////////
89: // Do a top-to-bottom copy:
90: ////////////////////////////////////////////////////////////////
91:
92: LONG ySrcBottom;
93: LONG yDestBottom;
94:
95: LONG yDestTop = prclDest->top;
96: LONG ySrcTop = pptlSrc->y;
97: LONG ySrcLast = ySrcTop + (prclDest->bottom - prclDest->top);
98:
99: if (ySrcTop < ppdev->rcl1WindowClip.top ||
100: ySrcTop >= ppdev->rcl1WindowClip.bottom)
101: {
102: ppdev->pfnBankControl(ppdev, ySrcTop, JustifyTop);
103: }
104:
105: pso->pvScan0 = ppdev->pvBitmapStart;
106:
107: while (TRUE)
108: {
109: // Copy an entire source bank into the temporary buffer:
110:
111: ySrcBottom = min(ySrcLast, ppdev->rcl1WindowClip.bottom);
112:
113: ptlSrc.x = pptlSrc->x;
114: ptlSrc.y = ySrcTop;
115:
116: rclDest.left = prclDest->left;
117: rclDest.top = 0;
118: rclDest.right = prclDest->right;
119: rclDest.bottom = ySrcBottom - ySrcTop;
120:
121: b &= EngCopyBits(psoTmp, pso, NULL, NULL, &rclDest, &ptlSrc);
122:
123: yDestBottom = yDestTop + rclDest.bottom;
124:
125: if (ppdev->rcl1WindowClip.top >= yDestBottom)
126: {
127: ppdev->pfnBankControl(ppdev, yDestBottom - 1, JustifyBottom);
128: pso->pvScan0 = ppdev->pvBitmapStart;
129: }
130:
131: while (TRUE)
132: {
133: // Copy the temporary buffer into one or more destination
134: // banks:
135:
136: LONG yThisTop;
137: LONG yThisBottom;
138: LONG yOffset;
139:
140: yThisBottom = min(yDestBottom, ppdev->rcl1WindowClip.bottom);
141: yThisTop = max(yDestTop, ppdev->rcl1WindowClip.top);
142: yOffset = yThisTop - yDestTop;
143:
144: ptlSrc.x = prclDest->left;
145: ptlSrc.y = yOffset;
146:
147: rclDest.left = prclDest->left;
148: rclDest.top = yThisTop;
149: rclDest.right = prclDest->right;
150: rclDest.bottom = yThisBottom;
151:
152: b &= EngCopyBits(pso, psoTmp, pco, pxlo, &rclDest, &ptlSrc);
153:
154: if (yOffset == 0)
155: break;
156:
157: ppdev->pfnBankControl(ppdev, yThisTop - 1, JustifyBottom);
158: pso->pvScan0 = ppdev->pvBitmapStart;
159: }
160:
161: if (ySrcBottom >= ySrcLast)
162: break;
163:
164: yDestTop = yDestBottom;
165: ySrcTop = ySrcBottom;
166:
167: ppdev->pfnBankControl(ppdev, ySrcTop, JustifyTop);
168: pso->pvScan0 = ppdev->pvBitmapStart;
169: }
170: }
171: else
172: {
173: ////////////////////////////////////////////////////////////////
174: // Do a bottom-to-top copy:
175: ////////////////////////////////////////////////////////////////
176:
177: LONG ySrcTop;
178: LONG yDestTop;
179:
180: LONG yDestBottom = prclDest->bottom;
181: LONG ySrcFirst = pptlSrc->y;
182: LONG ySrcBottom = ySrcFirst + (prclDest->bottom - prclDest->top);
183:
184: if (ySrcBottom <= ppdev->rcl1WindowClip.top ||
185: ySrcBottom > ppdev->rcl1WindowClip.bottom)
186: {
187: ppdev->pfnBankControl(ppdev, ySrcBottom - 1, JustifyBottom);
188: }
189:
190: pso->pvScan0 = ppdev->pvBitmapStart;
191:
192: while (TRUE)
193: {
194: // Copy an entire source bank into the temporary buffer:
195:
196: ySrcTop = max(ySrcFirst, ppdev->rcl1WindowClip.top);
197:
198: ptlSrc.x = pptlSrc->x;
199: ptlSrc.y = ySrcTop;
200:
201: rclDest.left = prclDest->left;
202: rclDest.top = 0;
203: rclDest.right = prclDest->right;
204: rclDest.bottom = ySrcBottom - ySrcTop;
205:
206: b &= EngCopyBits(psoTmp, pso, NULL, NULL, &rclDest, &ptlSrc);
207:
208: yDestTop = yDestBottom - rclDest.bottom;
209:
210: if (ppdev->rcl1WindowClip.bottom <= yDestTop)
211: {
212: ppdev->pfnBankControl(ppdev, yDestTop, JustifyTop);
213: pso->pvScan0 = ppdev->pvBitmapStart;
214: }
215:
216: while (TRUE)
217: {
218: // Copy the temporary buffer into one or more destination
219: // banks:
220:
221: LONG yThisTop;
222: LONG yThisBottom;
223: LONG yOffset;
224:
225: yThisTop = max(yDestTop, ppdev->rcl1WindowClip.top);
226: yThisBottom = min(yDestBottom, ppdev->rcl1WindowClip.bottom);
227: yOffset = yThisTop - yDestTop;
228:
229: ptlSrc.x = prclDest->left;
230: ptlSrc.y = yOffset;
231:
232: rclDest.left = prclDest->left;
233: rclDest.top = yThisTop;
234: rclDest.right = prclDest->right;
235: rclDest.bottom = yThisBottom;
236:
237: b &= EngCopyBits(pso, psoTmp, pco, pxlo, &rclDest, &ptlSrc);
238:
239: if (yThisBottom == yDestBottom)
240: break;
241:
242: ppdev->pfnBankControl(ppdev, yThisBottom, JustifyTop);
243: pso->pvScan0 = ppdev->pvBitmapStart;
244: }
245:
246: if (ySrcTop <= ySrcFirst)
247: break;
248:
249: yDestBottom = yDestTop;
250: ySrcBottom = ySrcTop;
251:
252: ppdev->pfnBankControl(ppdev, ySrcBottom - 1, JustifyBottom);
253: pso->pvScan0 = ppdev->pvBitmapStart;
254: }
255: }
256:
257: return(b);
258: }
259:
260: /******************************Public*Routine******************************\
261: * BOOL bPuntScreenToScreenBitBlt(...)
262: *
263: * Performs a screen-to-screen BitBlt entirely using an intermediate temporary
264: * buffer and GDI.
265: *
266: * This function is basically a clone of bPuntScreenToScreenCopyBits,
267: * except that it can handle funky ROPs and stuff.
268: \**************************************************************************/
269:
270: BOOL bPuntScreenToScreenBitBlt(
271: PPDEV ppdev,
272: SURFOBJ* psoMask,
273: CLIPOBJ* pco,
274: XLATEOBJ* pxlo,
275: RECTL* prclDest,
276: POINTL* pptlSrc,
277: POINTL* pptlMask,
278: BRUSHOBJ* pbo,
279: POINTL* pptlBrush,
280: ROP4 rop4)
281: {
282: RECTL rclDest; // Temporary destination rectangle
283: POINTL ptlSrc; // Temporary source point
284: POINTL ptlMask; // Temporary mask offset
285: POINTL ptlMaskAdjust; // Adjustment for mask offset
286: BOOL b = TRUE;
287:
288: SURFOBJ* pso = ppdev->pSurfObj;
289: SURFOBJ* psoTmp = ppdev->psoTmp;
290:
291: if (psoMask != NULL)
292: {
293: ptlMaskAdjust.x = prclDest->left - pptlMask->x;
294: ptlMaskAdjust.y = prclDest->top - pptlMask->y;
295: }
296:
297: if (prclDest->top < pptlSrc->y)
298: {
299: ////////////////////////////////////////////////////////////////
300: // Do a top-to-bottom copy:
301: ////////////////////////////////////////////////////////////////
302:
303: LONG ySrcBottom;
304: LONG yDestBottom;
305:
306: LONG yDestTop = prclDest->top;
307: LONG ySrcTop = pptlSrc->y;
308: LONG ySrcLast = ySrcTop + (prclDest->bottom - prclDest->top);
309:
310: if (ySrcTop < ppdev->rcl1WindowClip.top ||
311: ySrcTop >= ppdev->rcl1WindowClip.bottom)
312: {
313: ppdev->pfnBankControl(ppdev, ySrcTop, JustifyTop);
314: }
315:
316: pso->pvScan0 = ppdev->pvBitmapStart;
317:
318: while (TRUE)
319: {
320: // Copy an entire source bank into the temporary buffer:
321:
322: ySrcBottom = min(ySrcLast, ppdev->rcl1WindowClip.bottom);
323:
324: ptlSrc.x = pptlSrc->x;
325: ptlSrc.y = ySrcTop;
326:
327: rclDest.left = prclDest->left;
328: rclDest.top = 0;
329: rclDest.right = prclDest->right;
330: rclDest.bottom = ySrcBottom - ySrcTop;
331:
332: b &= EngCopyBits(psoTmp, pso, NULL, NULL, &rclDest, &ptlSrc);
333:
334: yDestBottom = yDestTop + rclDest.bottom;
335:
336: if (ppdev->rcl1WindowClip.top >= yDestBottom)
337: {
338: ppdev->pfnBankControl(ppdev, yDestBottom - 1, JustifyBottom);
339: pso->pvScan0 = ppdev->pvBitmapStart;
340: }
341:
342: while (TRUE)
343: {
344: // Copy the temporary buffer into one or more destination
345: // banks:
346:
347: LONG yThisTop;
348: LONG yThisBottom;
349: LONG yOffset;
350:
351: yThisBottom = min(yDestBottom, ppdev->rcl1WindowClip.bottom);
352: yThisTop = max(yDestTop, ppdev->rcl1WindowClip.top);
353: yOffset = yThisTop - yDestTop;
354:
355: ptlSrc.x = prclDest->left;
356: ptlSrc.y = yOffset;
357:
358: rclDest.left = prclDest->left;
359: rclDest.top = yThisTop;
360: rclDest.right = prclDest->right;
361: rclDest.bottom = yThisBottom;
362:
363: ptlMask.x = rclDest.left - ptlMaskAdjust.x;
364: ptlMask.y = rclDest.top - ptlMaskAdjust.y;
365:
366: b &= EngBitBlt(pso, psoTmp, psoMask, pco, pxlo, &rclDest,
367: &ptlSrc, &ptlMask, pbo, pptlBrush, rop4);
368:
369: if (yOffset == 0)
370: break;
371:
372: ppdev->pfnBankControl(ppdev, yThisTop - 1, JustifyBottom);
373: pso->pvScan0 = ppdev->pvBitmapStart;
374: }
375:
376: if (ySrcBottom >= ySrcLast)
377: break;
378:
379: yDestTop = yDestBottom;
380: ySrcTop = ySrcBottom;
381:
382: ppdev->pfnBankControl(ppdev, ySrcTop, JustifyTop);
383: pso->pvScan0 = ppdev->pvBitmapStart;
384: }
385: }
386: else
387: {
388: ////////////////////////////////////////////////////////////////
389: // Do a bottom-to-top copy:
390: ////////////////////////////////////////////////////////////////
391:
392: LONG ySrcTop;
393: LONG yDestTop;
394:
395: LONG yDestBottom = prclDest->bottom;
396: LONG ySrcFirst = pptlSrc->y;
397: LONG ySrcBottom = ySrcFirst + (prclDest->bottom - prclDest->top);
398:
399: if (ySrcBottom <= ppdev->rcl1WindowClip.top ||
400: ySrcBottom > ppdev->rcl1WindowClip.bottom)
401: {
402: ppdev->pfnBankControl(ppdev, ySrcBottom - 1, JustifyBottom);
403: }
404:
405: pso->pvScan0 = ppdev->pvBitmapStart;
406:
407: while (TRUE)
408: {
409: // Copy an entire source bank into the temporary buffer:
410:
411: ySrcTop = max(ySrcFirst, ppdev->rcl1WindowClip.top);
412:
413: ptlSrc.x = pptlSrc->x;
414: ptlSrc.y = ySrcTop;
415:
416: rclDest.left = prclDest->left;
417: rclDest.top = 0;
418: rclDest.right = prclDest->right;
419: rclDest.bottom = ySrcBottom - ySrcTop;
420:
421: b &= EngCopyBits(psoTmp, pso, NULL, NULL, &rclDest, &ptlSrc);
422:
423: yDestTop = yDestBottom - rclDest.bottom;
424:
425: if (ppdev->rcl1WindowClip.bottom <= yDestTop)
426: {
427: ppdev->pfnBankControl(ppdev, yDestTop, JustifyTop);
428: pso->pvScan0 = ppdev->pvBitmapStart;
429: }
430:
431: while (TRUE)
432: {
433: // Copy the temporary buffer into one or more destination
434: // banks:
435:
436: LONG yThisTop;
437: LONG yThisBottom;
438: LONG yOffset;
439:
440: yThisTop = max(yDestTop, ppdev->rcl1WindowClip.top);
441: yThisBottom = min(yDestBottom, ppdev->rcl1WindowClip.bottom);
442: yOffset = yThisTop - yDestTop;
443:
444: ptlSrc.x = prclDest->left;
445: ptlSrc.y = yOffset;
446:
447: rclDest.left = prclDest->left;
448: rclDest.top = yThisTop;
449: rclDest.right = prclDest->right;
450: rclDest.bottom = yThisBottom;
451:
452: ptlMask.x = rclDest.left - ptlMaskAdjust.x;
453: ptlMask.y = rclDest.top - ptlMaskAdjust.y;
454:
455: b &= EngBitBlt(pso, psoTmp, psoMask, pco, pxlo, &rclDest,
456: &ptlSrc, &ptlMask, pbo, pptlBrush, rop4);
457:
458: if (yThisBottom == yDestBottom)
459: break;
460:
461: ppdev->pfnBankControl(ppdev, yThisBottom, JustifyTop);
462: pso->pvScan0 = ppdev->pvBitmapStart;
463: }
464:
465: if (ySrcTop <= ySrcFirst)
466: break;
467:
468: yDestBottom = yDestTop;
469: ySrcBottom = ySrcTop;
470:
471: ppdev->pfnBankControl(ppdev, ySrcBottom - 1, JustifyBottom);
472: pso->pvScan0 = ppdev->pvBitmapStart;
473: }
474: }
475:
476: return(b);
477: }
478:
479: /******************************Public*Data*********************************\
480: * ROP to mix translation table
481: *
482: * Table to translate ternary raster ops to mixes (binary raster ops). Ternary
483: * raster ops that can't be translated to mixes are translated to 0 (0 is not
484: * a valid mix).
485: *
486: \**************************************************************************/
487:
488: UCHAR jRop3ToMix[256] = {
489: R2_BLACK, 0, 0, 0, 0, R2_NOTMERGEPEN, 0, 0,
490: 0, 0, R2_MASKNOTPEN, 0, 0, 0, 0, R2_NOTCOPYPEN,
491: 0, 0, 0, 0, 0, 0, 0, 0,
492: 0, 0, 0, 0, 0, 0, 0, 0,
493: 0, 0, 0, 0, 0, 0, 0, 0,
494: 0, 0, 0, 0, 0, 0, 0, 0,
495: 0, 0, 0, 0, 0, 0, 0, 0,
496: 0, 0, 0, 0, 0, 0, 0, 0,
497: 0, 0, 0, 0, 0, 0, 0, 0,
498: 0, 0, 0, 0, 0, 0, 0, 0,
499: R2_MASKPENNOT, 0, 0, 0, 0, R2_NOT, 0, 0,
500: 0, 0, R2_XORPEN, 0, 0, 0, 0, R2_NOTMASKPEN,
501: 0, 0, 0, 0, 0, 0, 0, 0,
502: 0, 0, 0, 0, 0, 0, 0, 0,
503: 0, 0, 0, 0, 0, 0, 0, 0,
504: 0, 0, 0, 0, 0, 0, 0, 0,
505: 0, 0, 0, 0, 0, 0, 0, 0,
506: 0, 0, 0, 0, 0, 0, 0, 0,
507: 0, 0, 0, 0, 0, 0, 0, 0,
508: 0, 0, 0, 0, 0, 0, 0, 0,
509: R2_MASKPEN, 0, 0, 0, 0, R2_NOTXORPEN, 0, 0,
510: 0, 0, R2_NOP, 0, 0, 0, 0, R2_MERGENOTPEN,
511: 0, 0, 0, 0, 0, 0, 0, 0,
512: 0, 0, 0, 0, 0, 0, 0, 0,
513: 0, 0, 0, 0, 0, 0, 0, 0,
514: 0, 0, 0, 0, 0, 0, 0, 0,
515: 0, 0, 0, 0, 0, 0, 0, 0,
516: 0, 0, 0, 0, 0, 0, 0, 0,
517: 0, 0, 0, 0, 0, 0, 0, 0,
518: 0, 0, 0, 0, 0, 0, 0, 0,
519: R2_COPYPEN, 0, 0, 0, 0, R2_MERGEPENNOT, 0, 0,
520: 0, 0, R2_MERGEPEN, 0, 0, 0, 0, R2_WHITE
521: };
522:
523: /******************************Public*Routine******************************\
524: * BOOL DrvBitBlt(psoDest, psoSrc, psoMask, pco, pxlo, prclDest, pptlSrc,
525: * pptlMask, pbo, pptlBrush, rop4)
526: *
527: * This routine will handle any blit. Perhaps glacially, but it will be
528: * handled.
529: \**************************************************************************/
530:
531: BOOL DrvBitBlt(
532: SURFOBJ* psoDest,
533: SURFOBJ* psoSrc,
534: SURFOBJ* psoMask,
535: CLIPOBJ* pco,
536: XLATEOBJ* pxlo,
537: RECTL* prclDest,
538: POINTL* pptlSrc,
539: POINTL* pptlMask,
540: BRUSHOBJ* pbo,
541: POINTL* pptlBrush,
542: ROP4 rop4)
543: {
544: BOOL b;
545: POINTL ptlSrc;
546: RECTL rclDest;
547: PPDEV ppdev;
548: SURFOBJ* pso;
549: MIX mix; // Mix, when solid fill performed
550: BYTE jClipping;
551: RECTL rclTmp;
552: POINTL ptlTmp;
553: BBENUM bben; // Clip enumerator
554: BOOL bMore; // Clip continuation flag
555: POINTL ptlMask; // Temporary mask for engine call-backs
556: POINTL ptlMaskAdjust; // Adjustment for mask
557: INT iCopyDir;
558:
559: RBRUSH_COLOR rbc; // Pointer to RBRUSH or iSolidColor value
560: PFNFILL pfnFill = vTrgBlt; // Pointer to appropriate fill routine
561: // (solid color by default)
562:
563: // Set up the clipping type
564: if (pco == (CLIPOBJ *) NULL) {
565: // No CLIPOBJ provided, so we don't have to worry about clipping
566: jClipping = DC_TRIVIAL;
567: } else {
568: // Use the CLIPOBJ-provided clipping
569: jClipping = pco->iDComplexity;
570: }
571:
572: // Handle solid fills to the VGA surface with special-case code if planar
573: // mode is supported.
574: // LATER handle non-planar also
575:
576: if (psoDest->iType == STYPE_DEVICE) {
577:
578: // Destination is the VGA surface
579:
580: // Masked cases must be handled differently
581:
582: if ((((PPDEV) psoDest->dhsurf)->fl & DRIVER_PLANAR_CAPABLE) &&
583: ((rop4 & 0xFF) == ((rop4 >> 8) & 0xFF))) {
584:
585: // Special-case static code for no-mask cases
586:
587: // Calculate mix from ROP if possible (not possible if it's truly a
588: // ternary rop or a real rop4, but we can treat all pure binary
589: // rops as mixes rather than rop4s)
590: mix = jRop3ToMix[rop4 & 0xFF];
591:
592: switch (mix) {
593: case R2_MASKNOTPEN:
594: case R2_NOTCOPYPEN:
595: case R2_XORPEN:
596: case R2_MASKPEN:
597: case R2_NOTXORPEN:
598: case R2_MERGENOTPEN:
599: case R2_COPYPEN:
600: case R2_MERGEPEN:
601: case R2_NOTMERGEPEN:
602: case R2_MASKPENNOT:
603: case R2_NOTMASKPEN:
604: case R2_MERGEPENNOT:
605:
606: // vTrgBlt can only handle solid color fills
607:
608: if (pbo->iSolidColor != 0xffffffff)
609: {
610: rbc.iSolidColor = pbo->iSolidColor;
611: }
612: else
613: {
614: rbc.prb = (RBRUSH*) pbo->pvRbrush;
615: if (rbc.prb == NULL)
616: {
617: rbc.prb = (RBRUSH*) BRUSHOBJ_pvGetRbrush(pbo);
618: if (rbc.prb == NULL)
619: {
620: // If we haven't realized the brush, punt the call
621: // to the engine:
622:
623: break;
624: }
625: }
626: if (!(rbc.prb->fl & RBRUSH_BLACKWHITE) &&
627: (mix != R2_COPYPEN))
628: {
629: // Only black/white brushes can handle ROPs other
630: // than COPYPEN:
631:
632: break;
633: }
634:
635: if (rbc.prb->fl & RBRUSH_NCOLOR)
636: pfnFill = vColorPat;
637: else
638: pfnFill = vMonoPat;
639: }
640:
641: // Rops that are implicit solid colors
642:
643: case R2_NOT:
644: case R2_WHITE:
645: case R2_BLACK:
646: // We can do a special-case solid fill
647:
648: switch(jClipping) {
649: case DC_TRIVIAL:
650:
651: // Just fill the rectangle:
652:
653: (*pfnFill)((PPDEV) psoDest->dhsurf, 1,
654: prclDest, mix, rbc, pptlBrush);
655:
656: break;
657:
658: case DC_RECT:
659:
660: // Clip the solid fill to the clip rectangle
661: if (!bIntersectRect(&rclTmp, prclDest,
662: &pco->rclBounds))
663: return(TRUE);
664:
665: // Fill the clipped rectangle
666:
667: (*pfnFill)((PPDEV) psoDest->dhsurf, 1,
668: &rclTmp, mix, rbc, pptlBrush);
669:
670: break;
671:
672: case DC_COMPLEX:
673:
674: ppdev = (PPDEV) psoDest->dhsurf;
675:
676: CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES,
677: CD_ANY, BB_RECT_LIMIT);
678:
679: do {
680: bMore = CLIPOBJ_bEnum(pco,(ULONG) sizeof(bben),
681: (PVOID) &bben);
682:
683: if (bben.c > 0)
684: {
685: RECTL* prclEnd = &bben.arcl[bben.c];
686: RECTL* prcl = &bben.arcl[0];
687:
688: do {
689: bIntersectRect(prcl, prcl, prclDest);
690: prcl++;
691:
692: } while (prcl < prclEnd);
693:
694: (*pfnFill)(ppdev, bben.c, bben.arcl,
695: mix, rbc, pptlBrush);
696: }
697:
698: } while(bMore);
699: }
700:
701: case R2_NOP:
702: return(TRUE);
703:
704: default:
705: break;
706: }
707: }
708: }
709:
710: // Get the correct surface object for the target and the source
711:
712: if (psoDest->iType == STYPE_DEVICE) {
713:
714: if ((psoSrc != NULL) && (psoSrc->iType == STYPE_DEVICE)) {
715:
716: ////////////////////////////////////////////////////////////////
717: // BitBlt screen-to-screen:
718: ////////////////////////////////////////////////////////////////
719:
720: ppdev = (PPDEV) psoDest->dhsurf;
721:
722: // See if we can do a simple CopyBits:
723:
724: if (rop4 == 0x0000CCCC)
725: {
726: ppdev = (PPDEV) psoDest->dhsurf;
727:
728: // We can handle quadpixel-aligned screen-to-screen blts with
729: // no translation:
730:
731: if ((((pptlSrc->x ^ prclDest->left) & 3) == 0) &&
732: (ppdev->fl & DRIVER_PLANAR_CAPABLE) &&
733: ((pxlo == NULL) || (pxlo->flXlate & XO_TRIVIAL)))
734: {
735: switch(jClipping)
736: {
737: case DC_TRIVIAL:
738: vPlanarCopyBits(ppdev, prclDest, pptlSrc);
739: return(TRUE);
740:
741: case DC_RECT:
742:
743: // Clip the target rectangle to the clip rectangle:
744:
745: if (!bIntersectRect(&rclTmp, prclDest, &pco->rclBounds))
746: {
747: DISPDBG((0, "DrvBitBlt: Nothing to draw."));
748: return(TRUE);
749: }
750:
751: ptlTmp.x = pptlSrc->x + rclTmp.left - prclDest->left;
752: ptlTmp.y = pptlSrc->y + rclTmp.top - prclDest->top;
753:
754: vPlanarCopyBits(ppdev, &rclTmp, &ptlTmp);
755: return(TRUE);
756:
757: case DC_COMPLEX:
758: if (pptlSrc->y >= prclDest->top)
759: {
760: if (pptlSrc->x >= prclDest->left)
761: iCopyDir = CD_RIGHTDOWN;
762: else
763: iCopyDir = CD_LEFTDOWN;
764: }
765: else
766: {
767: if (pptlSrc->x >= prclDest->left)
768: iCopyDir = CD_RIGHTUP;
769: else
770: iCopyDir = CD_LEFTUP;
771: }
772:
773: CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, iCopyDir, 0);
774:
775: do {
776: RECTL* prcl;
777: RECTL* prclEnd;
778:
779: bMore = CLIPOBJ_bEnum(pco, (ULONG) sizeof(bben),
780: (PVOID) &bben);
781:
782: prclEnd = &bben.arcl[bben.c];
783: for (prcl = bben.arcl; prcl < prclEnd; prcl++)
784: {
785: if (bIntersectRect(prcl, prclDest, prcl))
786: {
787: ptlTmp.x = pptlSrc->x + prcl->left - prclDest->left;
788: ptlTmp.y = pptlSrc->y + prcl->top - prclDest->top;
789:
790: vPlanarCopyBits(ppdev, prcl, &ptlTmp);
791: }
792: }
793: } while (bMore);
794:
795: return(TRUE);
796: }
797: }
798:
799: // Can't handle in hardware, so punt:
800:
801: return(bPuntScreenToScreenCopyBits(ppdev,
802: pco,
803: pxlo,
804: prclDest,
805: pptlSrc));
806: }
807:
808: // It's more complicated than a CopyBits, so punt it:
809:
810: return(bPuntScreenToScreenBitBlt(ppdev,
811: psoMask,
812: pco,
813: pxlo,
814: prclDest,
815: pptlSrc,
816: pptlMask,
817: pbo,
818: pptlBrush,
819: rop4));
820: }
821:
822: ////////////////////////////////////////////////////////////////
823: // BitBlt to screen:
824: ////////////////////////////////////////////////////////////////
825:
826: ppdev = (PPDEV) psoDest->dhsurf;
827:
828: if ((rop4 == 0x0000CCCC) &&
829: (psoSrc->iBitmapFormat == BMF_8BPP) &&
830: ((pxlo == NULL) || (pxlo->flXlate == XO_TRIVIAL)))
831: {
832: // We have special code for the common 8bpp from memory to screen
833: // with no ROPs:
834:
835: switch(jClipping)
836: {
837: case DC_TRIVIAL:
838: vSrcCopy8bpp(ppdev, prclDest, pptlSrc,
839: psoSrc->lDelta, psoSrc->pvScan0);
840: return(TRUE);
841:
842: case DC_RECT:
843:
844: // Clip the blt to the clip rectangle
845:
846: bIntersectRect(&rclTmp, prclDest, &pco->rclBounds);
847:
848: ptlTmp.x = pptlSrc->x + rclTmp.left - prclDest->left;
849: ptlTmp.y = pptlSrc->y + rclTmp.top - prclDest->top;
850:
851: vSrcCopy8bpp(ppdev, &rclTmp, &ptlTmp,
852: psoSrc->lDelta, psoSrc->pvScan0);
853:
854: return(TRUE);
855:
856: case DC_COMPLEX:
857:
858: CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES,
859: CD_ANY, BB_RECT_LIMIT);
860:
861: do {
862: bMore = CLIPOBJ_bEnum(pco,(ULONG) sizeof(bben),
863: (PVOID) &bben);
864:
865: if (bben.c > 0)
866: {
867: RECTL* prclEnd = &bben.arcl[bben.c];
868: RECTL* prcl = &bben.arcl[0];
869:
870: do {
871: bIntersectRect(prcl, prcl, prclDest);
872:
873: ptlTmp.x = pptlSrc->x + prcl->left
874: - prclDest->left;
875: ptlTmp.y = pptlSrc->y + prcl->top
876: - prclDest->top;
877:
878: vSrcCopy8bpp(ppdev, prcl, &ptlTmp,
879: psoSrc->lDelta, psoSrc->pvScan0);
880:
881: prcl++;
882:
883: } while (prcl < prclEnd);
884: }
885:
886: } while(bMore);
887:
888: return(TRUE);
889: }
890: }
891:
892: // Punt the memory-to-screen call back to the engine:
893:
894: if (psoMask != NULL)
895: {
896: ptlMaskAdjust.x = prclDest->left - pptlMask->x;
897: ptlMaskAdjust.y = prclDest->top - pptlMask->y;
898: }
899:
900: pso = ppdev->pSurfObj;
901:
902: vBankStartBltDest(ppdev, pso, pptlSrc, prclDest, &ptlSrc, &rclDest);
903:
904: do {
905: ptlMask.x = rclDest.left - ptlMaskAdjust.x;
906: ptlMask.y = rclDest.top - ptlMaskAdjust.y;
907:
908: b = EngBitBlt(pso,
909: psoSrc,
910: psoMask,
911: pco,
912: pxlo,
913: &rclDest,
914: &ptlSrc,
915: &ptlMask,
916: pbo,
917: pptlBrush,
918: rop4);
919:
920: } while (b && bBankEnumBltDest(ppdev, pso, pptlSrc, prclDest,
921: &ptlSrc, &rclDest));
922:
923: return(b);
924: }
925: else if ((psoSrc != NULL) && (psoSrc->iType == STYPE_DEVICE))
926: {
927: ////////////////////////////////////////////////////////////////
928: // BitBlt from screen:
929: ////////////////////////////////////////////////////////////////
930:
931: if (psoMask != NULL)
932: {
933: ptlMaskAdjust.x = prclDest->left - pptlMask->x;
934: ptlMaskAdjust.y = prclDest->top - pptlMask->y;
935: }
936:
937: ppdev = (PPDEV) psoSrc->dhsurf;
938: pso = ppdev->pSurfObj;
939:
940: vBankStartBltSrc(ppdev, pso, pptlSrc, prclDest, &ptlSrc, &rclDest);
941:
942: do {
943: ptlMask.x = rclDest.left - ptlMaskAdjust.x;
944: ptlMask.y = rclDest.top - ptlMaskAdjust.y;
945:
946: b = EngBitBlt(psoDest,
947: pso,
948: psoMask,
949: pco,
950: pxlo,
951: &rclDest,
952: &ptlSrc,
953: &ptlMask,
954: pbo,
955: pptlBrush,
956: rop4);
957:
958: } while (b && bBankEnumBltSrc(ppdev, pso, pptlSrc, prclDest,
959: &ptlSrc, &rclDest));
960:
961: return(b);
962: }
963:
964: RIP("Got a funky format?");
965: return(FALSE);
966: }
967:
968: /***************************************************************************\
969: * DrvCopyBits
970: \***************************************************************************/
971:
972: BOOL DrvCopyBits(
973: SURFOBJ* psoDest,
974: SURFOBJ* psoSrc,
975: CLIPOBJ* pco,
976: XLATEOBJ* pxlo,
977: RECTL* prclDest,
978: POINTL* pptlSrc)
979: {
980: BOOL b;
981: POINTL ptlSrc;
982: RECTL rclDest;
983: PPDEV ppdev;
984: SURFOBJ* pso;
985: BBENUM bben;
986: BOOL bMore;
987: BYTE jClipping;
988: POINTL ptlTmp;
989: RECTL rclTmp;
990: INT iCopyDir;
991:
992: // Get the correct surface object for the target and the source
993:
994: if (psoDest->iType == STYPE_DEVICE)
995: {
996: // We have to special case screen-to-screen operations:
997:
998: if ((psoSrc != NULL) && (psoSrc->iType == STYPE_DEVICE))
999: {
1000:
1001: ////////////////////////////////////////////////////////////////
1002: // CopyBits screen-to-screen:
1003: ////////////////////////////////////////////////////////////////
1004:
1005: ppdev = (PPDEV) psoDest->dhsurf;
1006:
1007: // We check to see if we can do a planar copy, because usually
1008: // it will be faster. But the hardware has to be capable of
1009: // doing it, and the source and destination must be 4-pel
1010: // aligned.
1011:
1012: if ((((pptlSrc->x ^ prclDest->left) & 3) == 0) &&
1013: (ppdev->fl & DRIVER_PLANAR_CAPABLE) &&
1014: ((pxlo == NULL) || (pxlo->flXlate & XO_TRIVIAL)))
1015: {
1016: jClipping = (pco != NULL) ? pco->iDComplexity : DC_TRIVIAL;
1017:
1018: switch(jClipping)
1019: {
1020: case DC_TRIVIAL:
1021: vPlanarCopyBits(ppdev, prclDest, pptlSrc);
1022: return(TRUE);
1023:
1024: case DC_RECT:
1025: // Clip the target rectangle to the clip rectangle:
1026:
1027: if (!bIntersectRect(&rclTmp, prclDest, &pco->rclBounds))
1028: {
1029: DISPDBG((0, "DrvCopyBits: Nothing to draw."));
1030: return(TRUE);
1031: }
1032:
1033: ptlTmp.x = pptlSrc->x + rclTmp.left - prclDest->left;
1034: ptlTmp.y = pptlSrc->y + rclTmp.top - prclDest->top;
1035:
1036: vPlanarCopyBits(ppdev, &rclTmp, &ptlTmp);
1037: return(TRUE);
1038:
1039: case DC_COMPLEX:
1040: if (pptlSrc->y >= prclDest->top)
1041: {
1042: if (pptlSrc->x >= prclDest->left)
1043: iCopyDir = CD_RIGHTDOWN;
1044: else
1045: iCopyDir = CD_LEFTDOWN;
1046: }
1047: else
1048: {
1049: if (pptlSrc->x >= prclDest->left)
1050: iCopyDir = CD_RIGHTUP;
1051: else
1052: iCopyDir = CD_LEFTUP;
1053: }
1054:
1055: CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, iCopyDir, 0);
1056:
1057: do {
1058: RECTL* prcl;
1059: RECTL* prclEnd;
1060:
1061: bMore = CLIPOBJ_bEnum(pco, (ULONG) sizeof(bben),
1062: (PVOID) &bben);
1063:
1064: prclEnd = &bben.arcl[bben.c];
1065: for (prcl = bben.arcl; prcl < prclEnd; prcl++)
1066: {
1067: if (bIntersectRect(prcl, prclDest, prcl))
1068: {
1069: ptlTmp.x = pptlSrc->x + prcl->left - prclDest->left;
1070: ptlTmp.y = pptlSrc->y + prcl->top - prclDest->top;
1071:
1072: vPlanarCopyBits(ppdev, prcl, &ptlTmp);
1073: }
1074: }
1075: } while (bMore);
1076:
1077: return(TRUE);
1078: }
1079: }
1080:
1081: return(bPuntScreenToScreenCopyBits(ppdev,
1082: pco,
1083: pxlo,
1084: prclDest,
1085: pptlSrc));
1086: }
1087:
1088: ////////////////////////////////////////////////////////////////
1089: // CopyBits to screen:
1090: ////////////////////////////////////////////////////////////////
1091:
1092: ppdev = (PPDEV) psoDest->dhsurf;
1093:
1094: if ((psoSrc->iBitmapFormat == BMF_8BPP) &&
1095: ((pxlo == NULL) || (pxlo->flXlate == XO_TRIVIAL)))
1096: {
1097: // We have special code for the common 8bpp from memory to screen
1098: // with no ROPs:
1099:
1100: jClipping = (pco != NULL) ? pco->iDComplexity : DC_TRIVIAL;
1101:
1102: switch(jClipping)
1103: {
1104: case DC_TRIVIAL:
1105: vSrcCopy8bpp(ppdev, prclDest, pptlSrc,
1106: psoSrc->lDelta, psoSrc->pvScan0);
1107: return(TRUE);
1108:
1109: case DC_RECT:
1110:
1111: // Clip the blt to the clip rectangle
1112:
1113: bIntersectRect(&rclTmp, prclDest, &pco->rclBounds);
1114:
1115: ptlTmp.x = pptlSrc->x + rclTmp.left - prclDest->left;
1116: ptlTmp.y = pptlSrc->y + rclTmp.top - prclDest->top;
1117:
1118: vSrcCopy8bpp(ppdev, &rclTmp, &ptlTmp,
1119: psoSrc->lDelta, psoSrc->pvScan0);
1120:
1121: return(TRUE);
1122:
1123: case DC_COMPLEX:
1124:
1125: CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES,
1126: CD_ANY, BB_RECT_LIMIT);
1127:
1128: do {
1129: bMore = CLIPOBJ_bEnum(pco,(ULONG) sizeof(bben),
1130: (PVOID) &bben);
1131:
1132: if (bben.c > 0)
1133: {
1134: RECTL* prclEnd = &bben.arcl[bben.c];
1135: RECTL* prcl = &bben.arcl[0];
1136:
1137: do {
1138: bIntersectRect(prcl, prcl, prclDest);
1139:
1140: ptlTmp.x = pptlSrc->x + prcl->left
1141: - prclDest->left;
1142: ptlTmp.y = pptlSrc->y + prcl->top
1143: - prclDest->top;
1144:
1145: vSrcCopy8bpp(ppdev, prcl, &ptlTmp,
1146: psoSrc->lDelta, psoSrc->pvScan0);
1147:
1148: prcl++;
1149:
1150: } while (prcl < prclEnd);
1151: }
1152:
1153: } while(bMore);
1154:
1155: return(TRUE);
1156: }
1157: }
1158:
1159: // Fall back to the engine:
1160:
1161: pso = ppdev->pSurfObj;
1162: vBankStartBltDest(ppdev, pso, pptlSrc, prclDest, &ptlSrc, &rclDest);
1163:
1164: do {
1165: b = EngCopyBits(pso,
1166: psoSrc,
1167: pco,
1168: pxlo,
1169: &rclDest,
1170: &ptlSrc);
1171:
1172: } while (b && bBankEnumBltDest(ppdev, pso, pptlSrc, prclDest,
1173: &ptlSrc, &rclDest));
1174:
1175: return(b);
1176: }
1177: else if ((psoSrc != NULL) && (psoSrc->iType == STYPE_DEVICE))
1178: {
1179: ////////////////////////////////////////////////////////////////
1180: // CopyBits from screen:
1181: ////////////////////////////////////////////////////////////////
1182:
1183: ppdev = (PPDEV) psoSrc->dhsurf;
1184: pso = ppdev->pSurfObj;
1185:
1186: vBankStartBltSrc(ppdev, pso, pptlSrc, prclDest, &ptlSrc, &rclDest);
1187:
1188: do {
1189: b = EngCopyBits(psoDest,
1190: pso,
1191: pco,
1192: pxlo,
1193: &rclDest,
1194: &ptlSrc);
1195:
1196: } while (b && bBankEnumBltSrc(ppdev, pso, pptlSrc, prclDest,
1197: &ptlSrc, &rclDest));
1198:
1199: return(b);
1200: }
1201: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.