7 Copyright (c) 1989 X Consortium
9 Permission is hereby granted, free of charge, to any person obtaining a copy
10 of this software and associated documentation files (the "Software"), to deal
11 in the Software without restriction, including without limitation the rights
12 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 copies of the Software, and to permit persons to whom the Software is
14 furnished to do so, subject to the following conditions:
16 The above copyright notice and this permission notice shall be included in
17 all copies or substantial portions of the Software.
19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 Except as contained in this notice, the name of the X Consortium shall not be
27 used in advertising or otherwise to promote the sale, use or other dealings
28 in this Software without prior written authorization from the X Consortium.
33 /* $XConsortium: cfbbitblt.c,v 5.51 94/05/27 11:00:56 dpw Exp $ */
39 #include "windowstr.h"
40 #include "scrnintstr.h"
41 #include "pixmapstr.h"
42 #include "regionstr.h"
44 #include "cfbmskbits.h"
47 #define MFB_CONSTS_ONLY
51 cfbBitBlt (pSrcDrawable, pDstDrawable,
52 pGC, srcx, srcy, width, height, dstx, dsty, doBitBlt, bitPlane)
53 register DrawablePtr pSrcDrawable;
54 register DrawablePtr pDstDrawable;
60 unsigned long bitPlane;
62 RegionPtr prgnSrcClip; /* may be a new region, or just a copy */
63 Bool freeSrcClip = FALSE;
65 RegionPtr prgnExposed;
68 register DDXPointPtr ppt;
73 xRectangle origSource;
77 int fastClip = 0; /* for fast clipping with pixmap source */
78 int fastExpose = 0; /* for fast exposures with pixmap source */
82 origSource.width = width;
83 origSource.height = height;
87 if ((pSrcDrawable != pDstDrawable) &&
88 pSrcDrawable->pScreen->SourceValidate)
90 (*pSrcDrawable->pScreen->SourceValidate) (pSrcDrawable, srcx, srcy, width, height);
93 srcx += pSrcDrawable->x;
94 srcy += pSrcDrawable->y;
98 if (pSrcDrawable->type == DRAWABLE_PIXMAP)
100 if ((pSrcDrawable == pDstDrawable) &&
101 (pGC->clientClipType == CT_NONE))
103 prgnSrcClip = cfbGetCompositeClip(pGC);
112 if (pGC->subWindowMode == IncludeInferiors)
114 if (!((WindowPtr) pSrcDrawable)->parent)
117 * special case bitblt from root window in
118 * IncludeInferiors mode; just like from a pixmap
122 else if ((pSrcDrawable == pDstDrawable) &&
123 (pGC->clientClipType == CT_NONE))
125 prgnSrcClip = cfbGetCompositeClip(pGC);
129 prgnSrcClip = NotClippedByChildren((WindowPtr)pSrcDrawable);
135 prgnSrcClip = &((WindowPtr)pSrcDrawable)->clipList;
141 fastBox.x2 = srcx + width;
142 fastBox.y2 = srcy + height;
144 /* Don't create a source region if we are doing a fast clip */
149 * clip the source; if regions extend beyond the source size,
150 * make sure exposure events get sent
152 if (fastBox.x1 < pSrcDrawable->x)
154 fastBox.x1 = pSrcDrawable->x;
157 if (fastBox.y1 < pSrcDrawable->y)
159 fastBox.y1 = pSrcDrawable->y;
162 if (fastBox.x2 > pSrcDrawable->x + (int) pSrcDrawable->width)
164 fastBox.x2 = pSrcDrawable->x + (int) pSrcDrawable->width;
167 if (fastBox.y2 > pSrcDrawable->y + (int) pSrcDrawable->height)
169 fastBox.y2 = pSrcDrawable->y + (int) pSrcDrawable->height;
175 REGION_INIT(pGC->pScreen, &rgnDst, &fastBox, 1);
176 REGION_INTERSECT(pGC->pScreen, &rgnDst, &rgnDst, prgnSrcClip);
179 dstx += pDstDrawable->x;
180 dsty += pDstDrawable->y;
182 if (pDstDrawable->type == DRAWABLE_WINDOW)
184 if (!((WindowPtr)pDstDrawable)->realized)
187 REGION_UNINIT(pGC->pScreen, &rgnDst);
189 REGION_DESTROY(pGC->pScreen, prgnSrcClip);
197 /* Translate and clip the dst to the destination composite clip */
202 /* Translate the region directly */
208 /* If the destination composite clip is one rectangle we can
209 do the clip directly. Otherwise we have to create a full
210 blown region and call intersect */
212 /* XXX because CopyPlane uses this routine for 8-to-1 bit
213 * copies, this next line *must* also correctly fetch the
214 * composite clip from an mfb gc
217 cclip = cfbGetCompositeClip(pGC);
218 if (REGION_NUM_RECTS(cclip) == 1)
220 BoxPtr pBox = REGION_RECTS(cclip);
222 if (fastBox.x1 < pBox->x1) fastBox.x1 = pBox->x1;
223 if (fastBox.x2 > pBox->x2) fastBox.x2 = pBox->x2;
224 if (fastBox.y1 < pBox->y1) fastBox.y1 = pBox->y1;
225 if (fastBox.y2 > pBox->y2) fastBox.y2 = pBox->y2;
227 /* Check to see if the region is empty */
228 if (fastBox.x1 >= fastBox.x2 || fastBox.y1 >= fastBox.y2)
230 REGION_INIT(pGC->pScreen, &rgnDst, NullBox, 0);
234 REGION_INIT(pGC->pScreen, &rgnDst, &fastBox, 1);
239 /* We must turn off fastClip now, since we must create
240 a full blown region. It is intersected with the
241 composite clip below. */
243 REGION_INIT(pGC->pScreen, &rgnDst, &fastBox,1);
248 REGION_TRANSLATE(pGC->pScreen, &rgnDst, -dx, -dy);
253 REGION_INTERSECT(pGC->pScreen, &rgnDst,
255 cfbGetCompositeClip(pGC));
258 /* Do bit blitting */
259 numRects = REGION_NUM_RECTS(&rgnDst);
260 if (numRects && width && height)
262 if(!(pptSrc = (DDXPointPtr)ALLOCATE_LOCAL(numRects *
263 sizeof(DDXPointRec))))
265 REGION_UNINIT(pGC->pScreen, &rgnDst);
267 REGION_DESTROY(pGC->pScreen, prgnSrcClip);
270 pbox = REGION_RECTS(&rgnDst);
272 for (i = numRects; --i >= 0; pbox++, ppt++)
274 ppt->x = pbox->x1 + dx;
275 ppt->y = pbox->y1 + dy;
278 (*doBitBlt) (pSrcDrawable, pDstDrawable, pGC->alu, &rgnDst, pptSrc, pGC->planemask, bitPlane);
279 DEALLOCATE_LOCAL(pptSrc);
283 if ( cfbGetGCPrivate(pGC)->fExpose)
285 extern RegionPtr miHandleExposures();
287 /* Pixmap sources generate a NoExposed (we return NULL to do this) */
290 miHandleExposures(pSrcDrawable, pDstDrawable, pGC,
291 origSource.x, origSource.y,
292 (int)origSource.width,
293 (int)origSource.height,
294 origDest.x, origDest.y, bitPlane);
296 REGION_UNINIT(pGC->pScreen, &rgnDst);
298 REGION_DESTROY(pGC->pScreen, prgnSrcClip);
304 cfbDoBitblt (pSrc, pDst, alu, prgnDst, pptSrc, planemask)
305 DrawablePtr pSrc, pDst;
309 unsigned long planemask;
311 void (*blt)() = cfbDoBitbltGeneral;
312 if ((planemask & PMSK) == PMSK) {
315 blt = cfbDoBitbltCopy;
318 blt = cfbDoBitbltXor;
325 (*blt) (pSrc, pDst, alu, prgnDst, pptSrc, planemask);
329 cfbCopyArea(pSrcDrawable, pDstDrawable,
330 pGC, srcx, srcy, width, height, dstx, dsty)
331 register DrawablePtr pSrcDrawable;
332 register DrawablePtr pDstDrawable;
340 doBitBlt = cfbDoBitbltCopy;
341 if (pGC->alu != GXcopy || (pGC->planemask & PMSK) != PMSK)
343 doBitBlt = cfbDoBitbltGeneral;
344 if ((pGC->planemask & PMSK) == PMSK)
348 doBitBlt = cfbDoBitbltXor;
351 doBitBlt = cfbDoBitbltOr;
356 return cfbBitBlt (pSrcDrawable, pDstDrawable,
357 pGC, srcx, srcy, width, height, dstx, dsty, doBitBlt, 0L);
362 cfbCopyPlane1to8 (pSrcDrawable, pDstDrawable, rop, prgnDst, pptSrc, planemask, bitPlane)
363 DrawablePtr pSrcDrawable; /* must be a bitmap */
364 DrawablePtr pDstDrawable; /* must be depth 8 drawable */
365 int rop; /* not used; caller must call cfb8CheckOpaqueStipple
366 * beforehand to get cfb8StippleRRop set correctly */
367 unsigned long planemask; /* to apply to destination writes */
368 RegionPtr prgnDst; /* region in destination to draw to;
369 * screen relative coords. if dest is a window;
370 * drawable relative if dest is a pixmap */
371 DDXPointPtr pptSrc; /* drawable relative src coords to copy from;
372 * must be one point for each box in prgnDst */
373 unsigned long bitPlane; /* not used; assumed always to be 1 */
375 int srcx, srcy; /* upper left corner of box being copied in source */
376 int dstx, dsty; /* upper left corner of box being copied in dest */
377 int width, height; /* in pixels, unpadded, of box being copied */
378 int xoffSrc; /* bit # in leftmost word of row from which copying starts */
379 int xoffDst; /* byte # in leftmost word of row from which copying starts */
380 unsigned long *psrcBase, *pdstBase; /* start of drawable's pixel data */
381 int widthSrc; /* # of groups of 32 pixels (1 bit/pixel) in src bitmap*/
382 int widthDst; /* # of groups of 4 pixels (8 bits/pixel) in dst */
383 unsigned long *psrcLine, *pdstLine; /* steps a row at a time thru src/dst;
384 * may point into middle of row */
385 register unsigned long *psrc, *pdst; /* steps within the row */
386 register unsigned long bits, tmp; /* bits from source */
387 register int leftShift;
388 register int rightShift;
389 unsigned long startmask; /* left edge pixel mask */
390 unsigned long endmask; /* right edge pixel mask */
391 register int nlMiddle; /* number of words in middle of the row to draw */
396 int nbox; /* number of boxes in region to copy */
397 BoxPtr pbox; /* steps thru boxes in region */
398 int pixelsRemainingOnRightEdge; /* # pixels to be drawn on a row after
399 * the main "middle" loop */
401 cfbGetLongWidthAndPointer (pSrcDrawable, widthSrc, psrcBase)
402 cfbGetLongWidthAndPointer (pDstDrawable, widthDst, pdstBase)
404 nbox = REGION_NUM_RECTS(prgnDst);
405 pbox = REGION_RECTS(prgnDst);
412 width = pbox->x2 - pbox->x1;
413 height = pbox->y2 - pbox->y1;
417 psrcLine = psrcBase + srcy * widthSrc + (srcx >> MFB_PWSH);
418 pdstLine = pdstBase + dsty * widthDst + (dstx >> PWSH);
419 xoffSrc = srcx & MFB_PIM; /* finds starting bit in src */
420 xoffDst = dstx & PIM; /* finds starting byte in dst */
422 /* compute startmask, endmask, nlMiddle */
424 if (xoffDst + width < PPW) /* XXX should this be '<= PPW' ? */
425 { /* the copy only affects one word per row in destination */
426 maskpartialbits(dstx, width, startmask);
427 endmask = 0; /* nothing on right edge */
428 nlMiddle = 0; /* nothing in middle */
431 { /* the copy will affect multiple words per row in destination */
432 maskbits(dstx, width, startmask, endmask, nlMiddle);
436 * compute constants for the first four bits to be
437 * copied. This avoids troubles with partial first
438 * writes, and difficult shift computation
442 firstoff = xoffSrc - xoffDst;
443 if (firstoff > (MFB_PPW-PPW))
444 secondoff = MFB_PPW - firstoff;
447 srcx += (PPW-xoffDst);
448 xoffSrc = srcx & MFB_PIM;
452 rightShift = MFB_PPW - leftShift;
454 pixelsRemainingOnRightEdge = (nlMiddle & 7) * PPW +
455 ((dstx + width) & PIM);
457 /* setup is done; now let's move some bits */
459 /* caller must call cfb8CheckOpaqueStipple before this function
460 * to set cfb8StippleRRop!
463 if (cfb8StippleRRop == GXcopy)
466 { /* one iteration of this loop copies one row */
469 psrcLine += widthSrc;
470 pdstLine += widthDst;
475 tmp = BitRight (bits, -firstoff);
478 tmp = BitLeft (bits, firstoff);
480 * need a more cautious test for partialmask
483 if (firstoff >= (MFB_PPW-PPW))
486 if (firstoff != (MFB_PPW-PPW))
487 tmp |= BitRight (bits, secondoff);
490 *pdst = (*pdst & ~startmask) | (GetPixelGroup(tmp) & startmask);
497 tmp = BitLeft(bits, leftShift);
499 if (rightShift != MFB_PPW)
500 tmp |= BitRight(bits, rightShift);
502 #ifdef FAST_CONSTANT_OFFSET_MODE
503 # define StorePixels(pdst,o,pixels) (pdst)[o] = (pixels)
504 # define EndStep(pdst,o) (pdst) += (o)
505 # define StoreRopPixels(pdst,o,and,xor) (pdst)[o] = DoRRop((pdst)[o],and,xor);
507 # define StorePixels(pdst,o,pixels) *(pdst)++ = (pixels)
508 # define EndStep(pdst,o)
509 # define StoreRopPixels(pdst,o,and,xor) *(pdst) = DoRRop(*(pdst),and,xor); (pdst)++;
512 #define Step(c) NextBitGroup(c);
513 #define StoreBitsPlain(o,c) StorePixels(pdst,o,GetPixelGroup(c))
514 #define StoreRopBitsPlain(o,c) StoreRopPixels(pdst,o,\
515 cfb8StippleAnd[GetBitGroup(c)], \
516 cfb8StippleXor[GetBitGroup(c)])
517 #define StoreBits0(c) StoreBitsPlain(0,c)
518 #define StoreRopBits0(c) StoreRopBitsPlain(0,c)
520 #if (BITMAP_BIT_ORDER == MSBFirst)
521 # define StoreBits(o,c) StoreBitsPlain(o,c)
522 # define StoreRopBits(o,c) StoreRopBitsPlain(o,c)
523 # define FirstStep(c) Step(c)
524 #else /* BITMAP_BIT_ORDER == LSBFirst */
526 # define StoreBits(o,c) StorePixels(pdst,o, (cfb8Pixels[c & 0xff]))
527 # define StoreRopBits(o,c) StoreRopPixels(pdst,o, \
528 (cfb8StippleAnd[c & 0xff]), \
529 (cfb8StippleXor[c & 0xff]))
530 # define FirstStep(c) c = BitLeft (c, 8);
532 /* 0x3c is 0xf << 2 (4 bits, long word) */
533 # define StoreBits(o,c) StorePixels(pdst,o,*((unsigned long *)\
534 (((char *) cfb8Pixels) + (c & 0x3c))))
535 # define StoreRopBits(o,c) StoreRopPixels(pdst,o, \
536 *((unsigned long *) (((char *) cfb8StippleAnd) + (c & 0x3c))), \
537 *((unsigned long *) (((char *) cfb8StippleXor) + (c & 0x3c))))
538 # define FirstStep(c) c = BitLeft (c, 2);
540 #endif /* BITMAP_BIT_ORDER */
542 StoreBits0(tmp); FirstStep(tmp);
543 StoreBits(1,tmp); Step(tmp);
544 StoreBits(2,tmp); Step(tmp);
545 StoreBits(3,tmp); Step(tmp);
546 StoreBits(4,tmp); Step(tmp);
547 StoreBits(5,tmp); Step(tmp);
548 StoreBits(6,tmp); Step(tmp);
549 StoreBits(7,tmp); EndStep (pdst,8);
552 /* do rest of middle and partial word on right edge */
554 if (pixelsRemainingOnRightEdge)
556 tmp = BitLeft(bits, leftShift);
558 if (pixelsRemainingOnRightEdge > rightShift)
561 tmp |= BitRight (bits, rightShift);
567 StoreBitsPlain(-7,tmp); Step(tmp);
569 StoreBitsPlain(-6,tmp); Step(tmp);
571 StoreBitsPlain(-5,tmp); Step(tmp);
573 StoreBitsPlain(-4,tmp); Step(tmp);
575 StoreBitsPlain(-3,tmp); Step(tmp);
577 StoreBitsPlain(-2,tmp); Step(tmp);
579 StoreBitsPlain(-1,tmp); Step(tmp);
582 *pdst = (*pdst & ~endmask) | (GetPixelGroup(tmp) & endmask);
586 else /* cfb8StippleRRop != GXcopy */
589 { /* one iteration of this loop copies one row */
592 psrcLine += widthSrc;
593 pdstLine += widthDst;
596 /* do partial word on left edge */
601 tmp = BitRight (bits, -firstoff);
604 tmp = BitLeft (bits, firstoff);
605 if (firstoff >= (MFB_PPW-PPW))
608 if (firstoff != (MFB_PPW-PPW))
609 tmp |= BitRight (bits, secondoff);
612 src = GetBitGroup(tmp);
613 *pdst = MaskRRopPixels (*pdst, src, startmask);
617 /* do middle of row */
623 tmp = BitLeft(bits, leftShift);
625 if (rightShift != MFB_PPW)
626 tmp |= BitRight(bits, rightShift);
627 StoreRopBits0(tmp); FirstStep(tmp);
628 StoreRopBits(1,tmp); Step(tmp);
629 StoreRopBits(2,tmp); Step(tmp);
630 StoreRopBits(3,tmp); Step(tmp);
631 StoreRopBits(4,tmp); Step(tmp);
632 StoreRopBits(5,tmp); Step(tmp);
633 StoreRopBits(6,tmp); Step(tmp);
634 StoreRopBits(7,tmp); EndStep(pdst,8);
637 /* do rest of middle and partial word on right edge */
639 if (pixelsRemainingOnRightEdge)
641 tmp = BitLeft(bits, leftShift);
643 if (pixelsRemainingOnRightEdge > rightShift)
645 bits = *psrc++; /* XXX purify abr here */
646 tmp |= BitRight (bits, rightShift);
650 src = GetBitGroup (tmp);
651 *pdst = RRopPixels (*pdst, src);
657 src = GetBitGroup (tmp);
658 *pdst = MaskRRopPixels (*pdst, src, endmask);
661 } /* end copy one row */
662 } /* end alu is non-copy-mode case */
663 } /* end iteration over region boxes */
668 /* shared among all different cfb depths through linker magic */
669 RegionPtr (*cfbPuntCopyPlane)();
671 RegionPtr cfbCopyPlane(pSrcDrawable, pDstDrawable,
672 pGC, srcx, srcy, width, height, dstx, dsty, bitPlane)
673 DrawablePtr pSrcDrawable;
674 DrawablePtr pDstDrawable;
679 unsigned long bitPlane;
682 extern RegionPtr miHandleExposures();
687 if (pSrcDrawable->bitsPerPixel == 1 && pDstDrawable->bitsPerPixel == 8)
691 doBitBlt = cfbCopyPlane1to8;
692 cfb8CheckOpaqueStipple (pGC->alu,
693 pGC->fgPixel, pGC->bgPixel,
695 ret = cfbBitBlt (pSrcDrawable, pDstDrawable,
696 pGC, srcx, srcy, width, height, dstx, dsty, doBitBlt, bitPlane);
699 ret = miHandleExposures (pSrcDrawable, pDstDrawable,
700 pGC, srcx, srcy, width, height, dstx, dsty, bitPlane);
702 else if (pSrcDrawable->bitsPerPixel == 8 && pDstDrawable->bitsPerPixel == 1)
704 extern int InverseAlu[16];
708 if ((pGC->fgPixel & 1) == 0 && (pGC->bgPixel&1) == 1)
709 pGC->alu = InverseAlu[pGC->alu];
710 else if ((pGC->fgPixel & 1) == (pGC->bgPixel & 1))
711 pGC->alu = mfbReduceRop(pGC->alu, pGC->fgPixel);
712 ret = cfbBitBlt (pSrcDrawable, pDstDrawable,
713 pGC, srcx, srcy, width, height, dstx, dsty,
714 cfbCopyPlane8to1, bitPlane);
717 else if (pSrcDrawable->bitsPerPixel == 8 && pDstDrawable->bitsPerPixel == 8)
720 ScreenPtr pScreen = pSrcDrawable->pScreen;
723 pBitmap = (*pScreen->CreatePixmap) (pScreen, width, height, 1);
726 pGC1 = GetScratchGC (1, pScreen);
729 (*pScreen->DestroyPixmap) (pBitmap);
733 * don't need to set pGC->fgPixel,bgPixel as copyPlane8to1
734 * ignores pixel values, expecting the rop to "do the
735 * right thing", which GXcopy will.
737 ValidateGC ((DrawablePtr) pBitmap, pGC1);
738 /* no exposures here, scratch GC's don't get graphics expose */
739 (void) cfbBitBlt (pSrcDrawable, (DrawablePtr) pBitmap,
740 pGC1, srcx, srcy, width, height, 0, 0,
741 cfbCopyPlane8to1, bitPlane);
742 cfb8CheckOpaqueStipple (pGC->alu,
743 pGC->fgPixel, pGC->bgPixel,
745 /* no exposures here, copy bits from inside a pixmap */
746 (void) cfbBitBlt ((DrawablePtr) pBitmap, pDstDrawable, pGC,
747 0, 0, width, height, dstx, dsty, cfbCopyPlane1to8, 1);
748 FreeScratchGC (pGC1);
749 (*pScreen->DestroyPixmap) (pBitmap);
750 /* compute resultant exposures */
751 ret = miHandleExposures (pSrcDrawable, pDstDrawable, pGC,
752 srcx, srcy, width, height,
753 dstx, dsty, bitPlane);
757 ret = (*cfbPuntCopyPlane) (pSrcDrawable, pDstDrawable,
758 pGC, srcx, srcy, width, height, dstx, dsty, bitPlane);