8 Copyright 1989, 1998 The Open Group
10 Permission to use, copy, modify, distribute, and sell this software and its
11 documentation for any purpose is hereby granted without fee, provided that
12 the above copyright notice appear in all copies and that both that
13 copyright notice and this permission notice appear in supporting
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 OPEN GROUP 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 Open Group 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 Open Group.
34 #ifdef HAVE_DIX_CONFIG_H
35 #include <dix-config.h>
42 #include <X11/Xproto.h>
44 #include "windowstr.h"
45 #include "scrnintstr.h"
46 #include "pixmapstr.h"
47 #include "regionstr.h"
50 #include "cfbmskbits.h"
53 #define MFB_CONSTS_ONLY
57 #define cfbCopyPlane1toN cfbCopyPlane1to8
58 #define cfbCopyPlaneNto1 cfbCopyPlane8to1
60 static unsigned int FgPixel
, BgPixel
;
62 #define cfbCopyPlane1toN cfbCopyPlane1to16
63 #define cfbCopyPlaneNto1 cfbCopyPlane16to1
66 #define cfbCopyPlane1toN cfbCopyPlane1to24
67 #define cfbCopyPlaneNto1 cfbCopyPlane24to1
70 #define cfbCopyPlane1toN cfbCopyPlane1to32
71 #define cfbCopyPlaneNto1 cfbCopyPlane32to1
75 /* cfbBitBltcfb == cfbCopyPlaneExpand */
78 register DrawablePtr pSrcDrawable
,
79 register DrawablePtr pDstDrawable
,
82 int width
, int height
,
88 RegionPtr
/*prgnDst*/,
89 DDXPointPtr
/*pptSrc*/,
90 unsigned long /*planemask*/),
91 unsigned long bitPlane
)
93 RegionPtr prgnSrcClip
= NULL
; /* may be a new region, or just a copy */
94 Bool freeSrcClip
= FALSE
;
96 RegionPtr prgnExposed
;
99 register DDXPointPtr ppt
;
100 register BoxPtr pbox
;
104 xRectangle origSource
;
105 DDXPointRec origDest
;
108 int fastClip
= 0; /* for fast clipping with pixmap source */
109 int fastExpose
= 0; /* for fast exposures with pixmap source */
113 origSource
.width
= width
;
114 origSource
.height
= height
;
118 if ((pSrcDrawable
!= pDstDrawable
) &&
119 pSrcDrawable
->pScreen
->SourceValidate
)
121 (*pSrcDrawable
->pScreen
->SourceValidate
) (pSrcDrawable
, srcx
, srcy
, width
, height
);
124 srcx
+= pSrcDrawable
->x
;
125 srcy
+= pSrcDrawable
->y
;
127 /* clip the source */
129 if (pSrcDrawable
->type
== DRAWABLE_PIXMAP
)
131 if ((pSrcDrawable
== pDstDrawable
) &&
132 (pGC
->clientClipType
== CT_NONE
))
134 prgnSrcClip
= cfbGetCompositeClip(pGC
);
143 if (pGC
->subWindowMode
== IncludeInferiors
)
146 * XFree86 DDX empties the border clip when the
149 if (!((WindowPtr
) pSrcDrawable
)->parent
&&
150 REGION_NOTEMPTY (pSrcDrawable
->pScreen
,
151 &((WindowPtr
) pSrcDrawable
)->borderClip
))
154 * special case bitblt from root window in
155 * IncludeInferiors mode; just like from a pixmap
159 else if ((pSrcDrawable
== pDstDrawable
) &&
160 (pGC
->clientClipType
== CT_NONE
))
162 prgnSrcClip
= cfbGetCompositeClip(pGC
);
166 prgnSrcClip
= NotClippedByChildren((WindowPtr
)pSrcDrawable
);
172 prgnSrcClip
= &((WindowPtr
)pSrcDrawable
)->clipList
;
178 fastBox
.x2
= srcx
+ width
;
179 fastBox
.y2
= srcy
+ height
;
181 /* Don't create a source region if we are doing a fast clip */
186 * clip the source; if regions extend beyond the source size,
187 * make sure exposure events get sent
189 if (fastBox
.x1
< pSrcDrawable
->x
)
191 fastBox
.x1
= pSrcDrawable
->x
;
194 if (fastBox
.y1
< pSrcDrawable
->y
)
196 fastBox
.y1
= pSrcDrawable
->y
;
199 if (fastBox
.x2
> pSrcDrawable
->x
+ (int) pSrcDrawable
->width
)
201 fastBox
.x2
= pSrcDrawable
->x
+ (int) pSrcDrawable
->width
;
204 if (fastBox
.y2
> pSrcDrawable
->y
+ (int) pSrcDrawable
->height
)
206 fastBox
.y2
= pSrcDrawable
->y
+ (int) pSrcDrawable
->height
;
212 REGION_INIT(pGC
->pScreen
, &rgnDst
, &fastBox
, 1);
213 REGION_INTERSECT(pGC
->pScreen
, &rgnDst
, &rgnDst
, prgnSrcClip
);
216 dstx
+= pDstDrawable
->x
;
217 dsty
+= pDstDrawable
->y
;
219 if (pDstDrawable
->type
== DRAWABLE_WINDOW
)
221 if (!((WindowPtr
)pDstDrawable
)->realized
)
224 REGION_UNINIT(pGC
->pScreen
, &rgnDst
);
226 REGION_DESTROY(pGC
->pScreen
, prgnSrcClip
);
234 /* Translate and clip the dst to the destination composite clip */
239 /* Translate the region directly */
245 /* If the destination composite clip is one rectangle we can
246 do the clip directly. Otherwise we have to create a full
247 blown region and call intersect */
249 /* XXX because CopyPlane uses this routine for 8-to-1 bit
250 * copies, this next line *must* also correctly fetch the
251 * composite clip from an mfb gc
254 cclip
= cfbGetCompositeClip(pGC
);
255 if (REGION_NUM_RECTS(cclip
) == 1)
257 BoxPtr pBox
= REGION_RECTS(cclip
);
259 if (fastBox
.x1
< pBox
->x1
) fastBox
.x1
= pBox
->x1
;
260 if (fastBox
.x2
> pBox
->x2
) fastBox
.x2
= pBox
->x2
;
261 if (fastBox
.y1
< pBox
->y1
) fastBox
.y1
= pBox
->y1
;
262 if (fastBox
.y2
> pBox
->y2
) fastBox
.y2
= pBox
->y2
;
264 /* Check to see if the region is empty */
265 if (fastBox
.x1
>= fastBox
.x2
|| fastBox
.y1
>= fastBox
.y2
)
267 REGION_NULL(pGC
->pScreen
, &rgnDst
);
271 REGION_INIT(pGC
->pScreen
, &rgnDst
, &fastBox
, 1);
276 /* We must turn off fastClip now, since we must create
277 a full blown region. It is intersected with the
278 composite clip below. */
280 REGION_INIT(pGC
->pScreen
, &rgnDst
, &fastBox
,1);
285 REGION_TRANSLATE(pGC
->pScreen
, &rgnDst
, -dx
, -dy
);
290 REGION_INTERSECT(pGC
->pScreen
, &rgnDst
,
292 cfbGetCompositeClip(pGC
));
295 /* Do bit blitting */
296 numRects
= REGION_NUM_RECTS(&rgnDst
);
297 if (numRects
&& width
&& height
)
299 if(!(pptSrc
= (DDXPointPtr
)ALLOCATE_LOCAL(numRects
*
300 sizeof(DDXPointRec
))))
302 REGION_UNINIT(pGC
->pScreen
, &rgnDst
);
304 REGION_DESTROY(pGC
->pScreen
, prgnSrcClip
);
307 pbox
= REGION_RECTS(&rgnDst
);
309 for (i
= numRects
; --i
>= 0; pbox
++, ppt
++)
311 ppt
->x
= pbox
->x1
+ dx
;
312 ppt
->y
= pbox
->y1
+ dy
;
315 (*doBitBlt
) (pSrcDrawable
, pDstDrawable
, pGC
->alu
, &rgnDst
, pptSrc
, pGC
->planemask
);
316 DEALLOCATE_LOCAL(pptSrc
);
322 /* Pixmap sources generate a NoExposed (we return NULL to do this) */
325 miHandleExposures(pSrcDrawable
, pDstDrawable
, pGC
,
326 origSource
.x
, origSource
.y
,
327 (int)origSource
.width
,
328 (int)origSource
.height
,
329 origDest
.x
, origDest
.y
, bitPlane
);
331 REGION_UNINIT(pGC
->pScreen
, &rgnDst
);
333 REGION_DESTROY(pGC
->pScreen
, prgnSrcClip
);
340 register DrawablePtr pSrcDrawable
,
341 register DrawablePtr pDstDrawable
,
344 int width
, int height
,
347 DrawablePtr
/*pSrc*/,
348 DrawablePtr
/*pDst*/,
350 RegionPtr
/*prgnDst*/,
351 DDXPointPtr
/*pptSrc*/,
352 unsigned long /*planemask*/,
353 unsigned long /*bitPlane*/),
354 unsigned long bitPlane
)
356 RegionPtr prgnSrcClip
= NULL
; /* may be a new region, or just a copy */
357 Bool freeSrcClip
= FALSE
;
359 RegionPtr prgnExposed
;
362 register DDXPointPtr ppt
;
363 register BoxPtr pbox
;
367 xRectangle origSource
;
368 DDXPointRec origDest
;
371 int fastClip
= 0; /* for fast clipping with pixmap source */
372 int fastExpose
= 0; /* for fast exposures with pixmap source */
376 origSource
.width
= width
;
377 origSource
.height
= height
;
381 if ((pSrcDrawable
!= pDstDrawable
) &&
382 pSrcDrawable
->pScreen
->SourceValidate
)
384 (*pSrcDrawable
->pScreen
->SourceValidate
) (pSrcDrawable
, srcx
, srcy
, width
, height
);
387 srcx
+= pSrcDrawable
->x
;
388 srcy
+= pSrcDrawable
->y
;
390 /* clip the source */
392 if (pSrcDrawable
->type
== DRAWABLE_PIXMAP
)
394 if ((pSrcDrawable
== pDstDrawable
) &&
395 (pGC
->clientClipType
== CT_NONE
))
397 prgnSrcClip
= cfbGetCompositeClip(pGC
);
406 if (pGC
->subWindowMode
== IncludeInferiors
)
409 * XFree86 DDX empties the border clip when the
412 if (!((WindowPtr
) pSrcDrawable
)->parent
&&
413 REGION_NOTEMPTY (pSrcDrawable
->pScreen
,
414 &((WindowPtr
) pSrcDrawable
)->borderClip
))
417 * special case bitblt from root window in
418 * IncludeInferiors mode; just like from a pixmap
422 else if ((pSrcDrawable
== pDstDrawable
) &&
423 (pGC
->clientClipType
== CT_NONE
))
425 prgnSrcClip
= cfbGetCompositeClip(pGC
);
429 prgnSrcClip
= NotClippedByChildren((WindowPtr
)pSrcDrawable
);
435 prgnSrcClip
= &((WindowPtr
)pSrcDrawable
)->clipList
;
441 fastBox
.x2
= srcx
+ width
;
442 fastBox
.y2
= srcy
+ height
;
444 /* Don't create a source region if we are doing a fast clip */
449 * clip the source; if regions extend beyond the source size,
450 * make sure exposure events get sent
452 if (fastBox
.x1
< pSrcDrawable
->x
)
454 fastBox
.x1
= pSrcDrawable
->x
;
457 if (fastBox
.y1
< pSrcDrawable
->y
)
459 fastBox
.y1
= pSrcDrawable
->y
;
462 if (fastBox
.x2
> pSrcDrawable
->x
+ (int) pSrcDrawable
->width
)
464 fastBox
.x2
= pSrcDrawable
->x
+ (int) pSrcDrawable
->width
;
467 if (fastBox
.y2
> pSrcDrawable
->y
+ (int) pSrcDrawable
->height
)
469 fastBox
.y2
= pSrcDrawable
->y
+ (int) pSrcDrawable
->height
;
475 REGION_INIT(pGC
->pScreen
, &rgnDst
, &fastBox
, 1);
476 REGION_INTERSECT(pGC
->pScreen
, &rgnDst
, &rgnDst
, prgnSrcClip
);
479 dstx
+= pDstDrawable
->x
;
480 dsty
+= pDstDrawable
->y
;
482 if (pDstDrawable
->type
== DRAWABLE_WINDOW
)
484 if (!((WindowPtr
)pDstDrawable
)->realized
)
487 REGION_UNINIT(pGC
->pScreen
, &rgnDst
);
489 REGION_DESTROY(pGC
->pScreen
, prgnSrcClip
);
497 /* Translate and clip the dst to the destination composite clip */
502 /* Translate the region directly */
508 /* If the destination composite clip is one rectangle we can
509 do the clip directly. Otherwise we have to create a full
510 blown region and call intersect */
512 /* XXX because CopyPlane uses this routine for 8-to-1 bit
513 * copies, this next line *must* also correctly fetch the
514 * composite clip from an mfb gc
517 cclip
= cfbGetCompositeClip(pGC
);
518 if (REGION_NUM_RECTS(cclip
) == 1)
520 BoxPtr pBox
= REGION_RECTS(cclip
);
522 if (fastBox
.x1
< pBox
->x1
) fastBox
.x1
= pBox
->x1
;
523 if (fastBox
.x2
> pBox
->x2
) fastBox
.x2
= pBox
->x2
;
524 if (fastBox
.y1
< pBox
->y1
) fastBox
.y1
= pBox
->y1
;
525 if (fastBox
.y2
> pBox
->y2
) fastBox
.y2
= pBox
->y2
;
527 /* Check to see if the region is empty */
528 if (fastBox
.x1
>= fastBox
.x2
|| fastBox
.y1
>= fastBox
.y2
)
530 REGION_NULL(pGC
->pScreen
, &rgnDst
);
534 REGION_INIT(pGC
->pScreen
, &rgnDst
, &fastBox
, 1);
539 /* We must turn off fastClip now, since we must create
540 a full blown region. It is intersected with the
541 composite clip below. */
543 REGION_INIT(pGC
->pScreen
, &rgnDst
, &fastBox
, 1);
548 REGION_TRANSLATE(pGC
->pScreen
, &rgnDst
, -dx
, -dy
);
553 REGION_INTERSECT(pGC
->pScreen
, &rgnDst
,
555 cfbGetCompositeClip(pGC
));
558 /* Do bit blitting */
559 numRects
= REGION_NUM_RECTS(&rgnDst
);
560 if (numRects
&& width
&& height
)
562 if(!(pptSrc
= (DDXPointPtr
)ALLOCATE_LOCAL(numRects
*
563 sizeof(DDXPointRec
))))
565 REGION_UNINIT(pGC
->pScreen
, &rgnDst
);
567 REGION_DESTROY(pGC
->pScreen
, prgnSrcClip
);
570 pbox
= REGION_RECTS(&rgnDst
);
572 for (i
= numRects
; --i
>= 0; pbox
++, ppt
++)
574 ppt
->x
= pbox
->x1
+ dx
;
575 ppt
->y
= pbox
->y1
+ dy
;
578 (*doCopyPlane
) (pSrcDrawable
, pDstDrawable
, pGC
->alu
, &rgnDst
, pptSrc
, pGC
->planemask
, bitPlane
);
579 DEALLOCATE_LOCAL(pptSrc
);
585 /* Pixmap sources generate a NoExposed (we return NULL to do this) */
588 miHandleExposures(pSrcDrawable
, pDstDrawable
, pGC
,
589 origSource
.x
, origSource
.y
,
590 (int)origSource
.width
,
591 (int)origSource
.height
,
592 origDest
.x
, origDest
.y
, bitPlane
);
594 REGION_UNINIT(pGC
->pScreen
, &rgnDst
);
596 REGION_DESTROY(pGC
->pScreen
, prgnSrcClip
);
602 cfbDoBitblt (pSrc
, pDst
, alu
, prgnDst
, pptSrc
, planemask
)
603 DrawablePtr pSrc
, pDst
;
607 unsigned long planemask
;
610 DrawablePtr
/*pSrc*/,
611 DrawablePtr
/*pDst*/,
613 RegionPtr
/*prgnDst*/,
614 DDXPointPtr
/*pptSrc*/,
615 unsigned long /*planemask*/)
616 = cfbDoBitbltGeneral
;
618 if ((planemask
& PMSK
) == PMSK
) {
621 doBitBlt
= cfbDoBitbltCopy
;
624 doBitBlt
= cfbDoBitbltXor
;
627 doBitBlt
= cfbDoBitbltOr
;
631 (*doBitBlt
) (pSrc
, pDst
, alu
, prgnDst
, pptSrc
, planemask
);
635 cfbCopyArea(pSrcDrawable
, pDstDrawable
,
636 pGC
, srcx
, srcy
, width
, height
, dstx
, dsty
)
637 register DrawablePtr pSrcDrawable
;
638 register DrawablePtr pDstDrawable
;
645 DrawablePtr
/*pSrc*/,
646 DrawablePtr
/*pDst*/,
648 RegionPtr
/*prgnDst*/,
649 DDXPointPtr
/*pptSrc*/,
650 unsigned long /*planemask*/);
652 doBitBlt
= cfbDoBitbltCopy
;
653 if (pGC
->alu
!= GXcopy
|| (pGC
->planemask
& PMSK
) != PMSK
)
655 doBitBlt
= cfbDoBitbltGeneral
;
656 if ((pGC
->planemask
& PMSK
) == PMSK
)
660 doBitBlt
= cfbDoBitbltXor
;
663 doBitBlt
= cfbDoBitbltOr
;
668 return cfbBitBlt (pSrcDrawable
, pDstDrawable
,
669 pGC
, srcx
, srcy
, width
, height
, dstx
, dsty
, doBitBlt
, 0L);
674 cfbCopyPlane1to8 (pSrcDrawable
, pDstDrawable
, rop
, prgnDst
, pptSrc
, planemask
)
675 DrawablePtr pSrcDrawable
; /* must be a bitmap */
676 DrawablePtr pDstDrawable
; /* must be depth 8 drawable */
677 int rop
; /* not used; caller must call cfb8CheckOpaqueStipple
678 * beforehand to get cfb8StippleRRop set correctly */
679 RegionPtr prgnDst
; /* region in destination to draw to;
680 * screen relative coords. if dest is a window;
681 * drawable relative if dest is a pixmap */
682 DDXPointPtr pptSrc
; /* drawable relative src coords to copy from;
683 * must be one point for each box in prgnDst */
684 unsigned long planemask
; /* to apply to destination writes */
686 int srcx
, srcy
; /* upper left corner of box being copied in source */
687 int dstx
, dsty
; /* upper left corner of box being copied in dest */
688 int width
, height
; /* in pixels, unpadded, of box being copied */
689 int xoffSrc
; /* bit # in leftmost word of row from which copying starts */
690 int xoffDst
; /* byte # in leftmost word of row from which copying starts */
691 CfbBits
*psrcBase
, *pdstBase
; /* start of drawable's pixel data */
692 int widthSrc
; /* # of groups of 32 pixels (1 bit/pixel) in src bitmap*/
693 int widthDst
; /* # of groups of 4 pixels (8 bits/pixel) in dst */
694 CfbBits
*psrcLine
, *pdstLine
; /* steps a row at a time thru src/dst;
695 * may point into middle of row */
696 register CfbBits
*psrc
, *pdst
; /* steps within the row */
697 register CfbBits bits
, tmp
; /* bits from source */
698 register int leftShift
;
699 register int rightShift
;
700 CfbBits startmask
; /* left edge pixel mask */
701 CfbBits endmask
; /* right edge pixel mask */
702 register int nlMiddle
; /* number of words in middle of the row to draw */
707 int nbox
; /* number of boxes in region to copy */
708 BoxPtr pbox
; /* steps thru boxes in region */
709 int pixelsRemainingOnRightEdge
; /* # pixels to be drawn on a row after
710 * the main "middle" loop */
712 cfbGetLongWidthAndPointer (pSrcDrawable
, widthSrc
, psrcBase
)
713 cfbGetLongWidthAndPointer (pDstDrawable
, widthDst
, pdstBase
)
715 nbox
= REGION_NUM_RECTS(prgnDst
);
716 pbox
= REGION_RECTS(prgnDst
);
723 width
= pbox
->x2
- pbox
->x1
;
724 height
= pbox
->y2
- pbox
->y1
;
728 psrcLine
= psrcBase
+ srcy
* widthSrc
+ (srcx
>> MFB_PWSH
);
729 pdstLine
= pdstBase
+ dsty
* widthDst
+ (dstx
>> PWSH
);
730 xoffSrc
= srcx
& MFB_PIM
; /* finds starting bit in src */
731 xoffDst
= dstx
& PIM
; /* finds starting byte in dst */
733 /* compute startmask, endmask, nlMiddle */
735 if (xoffDst
+ width
< PPW
) /* XXX should this be '<= PPW' ? */
736 { /* the copy only affects one word per row in destination */
737 maskpartialbits(dstx
, width
, startmask
);
738 endmask
= 0; /* nothing on right edge */
739 nlMiddle
= 0; /* nothing in middle */
742 { /* the copy will affect multiple words per row in destination */
743 maskbits(dstx
, width
, startmask
, endmask
, nlMiddle
);
747 * compute constants for the first four bits to be
748 * copied. This avoids troubles with partial first
749 * writes, and difficult shift computation
753 firstoff
= xoffSrc
- xoffDst
;
754 if (firstoff
> (MFB_PPW
-PPW
))
755 secondoff
= MFB_PPW
- firstoff
;
758 srcx
+= (PPW
-xoffDst
);
759 xoffSrc
= srcx
& MFB_PIM
;
763 rightShift
= MFB_PPW
- leftShift
;
765 pixelsRemainingOnRightEdge
= (nlMiddle
& 7) * PPW
+
766 ((dstx
+ width
) & PIM
);
768 /* setup is done; now let's move some bits */
770 /* caller must call cfb8CheckOpaqueStipple before this function
771 * to set cfb8StippleRRop!
774 if (cfb8StippleRRop
== GXcopy
)
777 { /* one iteration of this loop copies one row */
780 psrcLine
+= widthSrc
;
781 pdstLine
+= widthDst
;
786 tmp
= BitRight (bits
, -firstoff
);
789 tmp
= BitLeft (bits
, firstoff
);
791 * need a more cautious test for partialmask
794 if (firstoff
>= (MFB_PPW
-PPW
))
797 if (firstoff
!= (MFB_PPW
-PPW
))
798 tmp
|= BitRight (bits
, secondoff
);
801 *pdst
= (*pdst
& ~startmask
) | (GetPixelGroup(tmp
) & startmask
);
808 tmp
= BitLeft(bits
, leftShift
);
810 if (rightShift
!= MFB_PPW
)
811 tmp
|= BitRight(bits
, rightShift
);
813 #ifdef FAST_CONSTANT_OFFSET_MODE
814 # define StorePixels(pdst,o,pixels) (pdst)[o] = (pixels)
815 # define EndStep(pdst,o) (pdst) += (o)
816 # define StoreRopPixels(pdst,o,and,xor) (pdst)[o] = DoRRop((pdst)[o],and,xor);
818 # define StorePixels(pdst,o,pixels) *(pdst)++ = (pixels)
819 # define EndStep(pdst,o)
820 # define StoreRopPixels(pdst,o,and,xor) *(pdst) = DoRRop(*(pdst),and,xor); (pdst)++;
823 #define Step(c) NextBitGroup(c);
824 #define StoreBitsPlain(o,c) StorePixels(pdst,o,GetPixelGroup(c))
825 #define StoreRopBitsPlain(o,c) StoreRopPixels(pdst,o,\
826 cfb8StippleAnd[GetBitGroup(c)], \
827 cfb8StippleXor[GetBitGroup(c)])
828 #define StoreBits0(c) StoreBitsPlain(0,c)
829 #define StoreRopBits0(c) StoreRopBitsPlain(0,c)
831 #if (BITMAP_BIT_ORDER == MSBFirst)
832 # define StoreBits(o,c) StoreBitsPlain(o,c)
833 # define StoreRopBits(o,c) StoreRopBitsPlain(o,c)
834 # define FirstStep(c) Step(c)
835 #else /* BITMAP_BIT_ORDER == LSBFirst */
837 # define StoreBits(o,c) StorePixels(pdst,o, (cfb8Pixels[c & 0xff]))
838 # define StoreRopBits(o,c) StoreRopPixels(pdst,o, \
839 (cfb8StippleAnd[c & 0xff]), \
840 (cfb8StippleXor[c & 0xff]))
841 # define FirstStep(c) c = BitLeft (c, 8);
843 /* 0x3c is 0xf << 2 (4 bits, long word) */
844 # define StoreBits(o,c) StorePixels(pdst,o,*((CfbBits *)\
845 (((char *) cfb8Pixels) + (c & 0x3c))))
846 # define StoreRopBits(o,c) StoreRopPixels(pdst,o, \
847 *((CfbBits *) (((char *) cfb8StippleAnd) + (c & 0x3c))), \
848 *((CfbBits *) (((char *) cfb8StippleXor) + (c & 0x3c))))
849 # define FirstStep(c) c = BitLeft (c, 2);
851 #endif /* BITMAP_BIT_ORDER */
853 StoreBits0(tmp
); FirstStep(tmp
);
854 StoreBits(1,tmp
); Step(tmp
);
855 StoreBits(2,tmp
); Step(tmp
);
856 StoreBits(3,tmp
); Step(tmp
);
857 StoreBits(4,tmp
); Step(tmp
);
858 StoreBits(5,tmp
); Step(tmp
);
859 StoreBits(6,tmp
); Step(tmp
);
860 StoreBits(7,tmp
); EndStep (pdst
,8);
863 /* do rest of middle and partial word on right edge */
865 if (pixelsRemainingOnRightEdge
)
867 tmp
= BitLeft(bits
, leftShift
);
869 if (pixelsRemainingOnRightEdge
> rightShift
)
872 tmp
|= BitRight (bits
, rightShift
);
878 StoreBitsPlain(-7,tmp
); Step(tmp
);
880 StoreBitsPlain(-6,tmp
); Step(tmp
);
882 StoreBitsPlain(-5,tmp
); Step(tmp
);
884 StoreBitsPlain(-4,tmp
); Step(tmp
);
886 StoreBitsPlain(-3,tmp
); Step(tmp
);
888 StoreBitsPlain(-2,tmp
); Step(tmp
);
890 StoreBitsPlain(-1,tmp
); Step(tmp
);
893 *pdst
= (*pdst
& ~endmask
) | (GetPixelGroup(tmp
) & endmask
);
897 else /* cfb8StippleRRop != GXcopy */
900 { /* one iteration of this loop copies one row */
903 psrcLine
+= widthSrc
;
904 pdstLine
+= widthDst
;
907 /* do partial word on left edge */
912 tmp
= BitRight (bits
, -firstoff
);
915 tmp
= BitLeft (bits
, firstoff
);
916 if (firstoff
>= (MFB_PPW
-PPW
))
919 if (firstoff
!= (MFB_PPW
-PPW
))
920 tmp
|= BitRight (bits
, secondoff
);
923 src
= GetBitGroup(tmp
);
924 *pdst
= MaskRRopPixels (*pdst
, src
, startmask
);
928 /* do middle of row */
934 tmp
= BitLeft(bits
, leftShift
);
936 if (rightShift
!= MFB_PPW
)
937 tmp
|= BitRight(bits
, rightShift
);
938 StoreRopBits0(tmp
); FirstStep(tmp
);
939 StoreRopBits(1,tmp
); Step(tmp
);
940 StoreRopBits(2,tmp
); Step(tmp
);
941 StoreRopBits(3,tmp
); Step(tmp
);
942 StoreRopBits(4,tmp
); Step(tmp
);
943 StoreRopBits(5,tmp
); Step(tmp
);
944 StoreRopBits(6,tmp
); Step(tmp
);
945 StoreRopBits(7,tmp
); EndStep(pdst
,8);
948 /* do rest of middle and partial word on right edge */
950 if (pixelsRemainingOnRightEdge
)
952 tmp
= BitLeft(bits
, leftShift
);
954 if (pixelsRemainingOnRightEdge
> rightShift
)
956 bits
= *psrc
++; /* XXX purify abr here */
957 tmp
|= BitRight (bits
, rightShift
);
961 src
= GetBitGroup (tmp
);
962 *pdst
= RRopPixels (*pdst
, src
);
968 src
= GetBitGroup (tmp
);
969 *pdst
= MaskRRopPixels (*pdst
, src
, endmask
);
972 } /* end copy one row */
973 } /* end alu is non-copy-mode case */
974 } /* end iteration over region boxes */
979 #define mfbmaskbits(x, w, startmask, endmask, nlw) \
980 startmask = mfbGetstarttab((x)&0x1f); \
981 endmask = mfbGetendtab(((x)+(w)) & 0x1f); \
983 nlw = (((w) - (32 - ((x)&0x1f))) >> 5); \
987 #define mfbmaskpartialbits(x, w, mask) \
988 mask = mfbGetpartmasks((x)&0x1f,(w)&0x1f);
991 #define StepBit(bit, inc) ((bit) += (inc))
994 #define GetBits(psrc, nBits, curBit, bitPos, bits) {\
998 bits |= ((*psrc++ >> bitPos) & 1) << curBit; \
999 StepBit (curBit, 1); \
1003 /******************************************************************/
1016 DrawablePtr pSrcDrawable
,
1017 DrawablePtr pDstDrawable
,
1021 unsigned long planemask
)
1023 int srcx
, srcy
, dstx
, dsty
;
1026 CfbBits
*psrcBase
, *pdstBase
;
1027 int widthSrc
, widthDst
;
1028 unsigned int *psrcLine
;
1029 register unsigned int *psrc
;
1031 unsigned short *pdstLine
;
1032 register unsigned short *pdst
;
1035 unsigned int *pdstLine
;
1036 register unsigned int *pdst
;
1039 unsigned char *pdstLine
;
1040 register unsigned char *pdst
;
1042 register unsigned int bits
, tmp
;
1043 register unsigned int fgpixel
, bgpixel
;
1044 register unsigned int src
;
1046 register unsigned int dst
;
1048 register int leftShift
, rightShift
;
1055 unsigned int doublet
[4]; /* Pixel values for 16bpp expansion. */
1058 unsigned int doublet
[8]; /* Pixel values for 32bpp expansion */
1061 fgpixel
= FgPixel
& planemask
;
1062 bgpixel
= BgPixel
& planemask
;
1065 if (rop
== GXcopy
&& (planemask
& PMSK
) == PMSK
) {
1066 doublet
[0] = bgpixel
| (bgpixel
<< 16);
1067 doublet
[1] = fgpixel
| (bgpixel
<< 16);
1068 doublet
[2] = bgpixel
| (fgpixel
<< 16);
1069 doublet
[3] = fgpixel
| (fgpixel
<< 16);
1073 if (rop
== GXcopy
&& (planemask
& PMSK
) == PMSK
) {
1074 doublet
[0] = bgpixel
; doublet
[1] = bgpixel
;
1075 doublet
[2] = fgpixel
; doublet
[3] = bgpixel
;
1076 doublet
[4] = bgpixel
; doublet
[5] = fgpixel
;
1077 doublet
[6] = fgpixel
; doublet
[7] = fgpixel
;
1081 /* must explicitly ask for "int" widths, as code below expects it */
1082 /* on some machines (Alpha), "long" and "int" are not the same size */
1083 cfbGetTypedWidthAndPointer (pSrcDrawable
, widthSrc
, psrcBase
, int, CfbBits
)
1084 cfbGetTypedWidthAndPointer (pDstDrawable
, widthDst
, pdstBase
, int, CfbBits
)
1093 nbox
= REGION_NUM_RECTS(prgnDst
);
1094 pbox
= REGION_RECTS(prgnDst
);
1102 width
= pbox
->x2
- pbox
->x1
;
1103 height
= pbox
->y2
- pbox
->y1
;
1106 psrcLine
= (unsigned int *)psrcBase
+ srcy
* widthSrc
+ (srcx
>> 5);
1108 pdstLine
= (unsigned short *)pdstBase
+ dsty
* widthDst
+ dstx
;
1111 pdstLine
= (unsigned char *)pdstBase
+ dsty
* widthDst
+ dstx
* 3;
1114 pdstLine
= (unsigned int *)pdstBase
+ dsty
* widthDst
+ dstx
;
1116 xoffSrc
= srcx
& 0x1f;
1119 * compute constants for the first four bits to be
1120 * copied. This avoids troubles with partial first
1121 * writes, and difficult shift computation
1123 leftShift
= xoffSrc
;
1124 rightShift
= 32 - leftShift
;
1126 if (rop
== GXcopy
&& (planemask
& PMSK
) == PMSK
)
1132 psrcLine
+= widthSrc
;
1133 pdstLine
+= widthDst
;
1138 tmp
= BitLeft(bits
, leftShift
);
1140 if (rightShift
!= 32)
1141 tmp
|= BitRight(bits
, rightShift
);
1145 * I've thrown in some optimization to at least write
1146 * some aligned 32-bit words instead of 16-bit shorts.
1148 if ((unsigned long)psrc
& 2) {
1149 /* Write unaligned 16-bit word at left edge. */
1159 unsigned tmpbits
= tmp
>> i
;
1160 *(unsigned int *)pdst
= doublet
[tmpbits
& 0x03];
1161 *(unsigned int *)(pdst
+ 2) =
1162 doublet
[(tmpbits
>> 2) & 0x03];
1163 *(unsigned int *)(pdst
+ 4) =
1164 doublet
[(tmpbits
>> 4) & 0x03];
1165 *(unsigned int *)(pdst
+ 6) =
1166 doublet
[(tmpbits
>> 6) & 0x03];
1167 pdst
+= 8; /* Advance four 32-bit words. */
1172 *(unsigned int *)pdst
=
1173 doublet
[(tmp
>> i
) & 0x03];
1174 pdst
+= 2; /* Advance one 32-bit word. */
1178 if ((tmp
>> 31) & 0x01)
1187 if ((tmp
>> i
) & 0x01) {
1189 *(pdst
+ 1) = fgpixel
>> 8;
1190 *(pdst
+ 2) = fgpixel
>> 16;
1194 *(pdst
+ 1) = bgpixel
>> 8;
1195 *(pdst
+ 2) = bgpixel
>> 16;
1204 pair
= (tmp
>> i
) & 0x03;
1205 *pdst
= doublet
[pair
* 2];
1206 *(pdst
+ 1) = doublet
[pair
* 2 + 1];
1207 pair
= (tmp
>> (i
+ 2)) & 0x03;
1208 *(pdst
+ 2) = doublet
[pair
* 2];
1209 *(pdst
+ 3) = doublet
[pair
* 2 + 1];
1214 *pdst
= ((tmp
>> i
) & 0x01) ? fgpixel
: bgpixel
;
1224 tmp
= BitLeft(bits
, leftShift
);
1226 * better condition needed -- mustn't run
1227 * off the end of the source...
1229 if (rightShift
!= 32)
1232 tmp
|= BitRight (bits
, rightShift
);
1239 if ((tmp
>> (31 - i
)) & 0x01) {
1241 *(pdst
+ 1) = fgpixel
>> 8;
1242 *(pdst
+ 2) = fgpixel
>> 16;
1246 *(pdst
+ 1) = bgpixel
>> 8;
1247 *(pdst
+ 2) = bgpixel
>> 16;
1251 *pdst
= ((tmp
>> (31 - i
)) & 0x01) ? fgpixel
: bgpixel
;
1264 psrcLine
+= widthSrc
;
1265 pdstLine
+= widthDst
;
1270 tmp
= BitLeft(bits
, leftShift
);
1272 if (rightShift
!= 32)
1273 tmp
|= BitRight(bits
, rightShift
);
1277 src
= ((tmp
>> (31 - i
)) & 0x01) ? fgpixel
: bgpixel
;
1280 dst
|= (*(pdst
+ 1)) << 8;
1281 dst
|= (*(pdst
+ 2)) << 16;
1282 DoRop (result
, rop
, src
, dst
);
1283 *pdst
= (dst
& ~planemask
) |
1284 (result
& planemask
);
1285 *(pdst
+1) = ((dst
& ~planemask
) >> 8) |
1286 ((result
& planemask
) >> 8);
1287 *(pdst
+2) = ((dst
& ~planemask
) >> 16) |
1288 ((result
& planemask
) >> 16);
1291 DoRop (result
, rop
, src
, *pdst
);
1293 *pdst
= (*pdst
& ~planemask
) |
1294 (result
& planemask
);
1303 tmp
= BitLeft(bits
, leftShift
);
1305 * better condition needed -- mustn't run
1306 * off the end of the source...
1308 if (rightShift
!= 32)
1311 tmp
|= BitRight (bits
, rightShift
);
1317 src
= ((tmp
>> (31 - i
)) & 0x01) ? fgpixel
: bgpixel
;
1320 dst
|= (*(pdst
+ 1)) << 8;
1321 dst
|= (*(pdst
+ 2)) << 16;
1322 DoRop (result
, rop
, src
, dst
);
1323 *pdst
= (dst
& ~planemask
) |
1324 (result
& planemask
);
1325 *(pdst
+1) = ((dst
& ~planemask
) >> 8) |
1326 ((result
& planemask
) >> 8);
1327 *(pdst
+2) = ((dst
& ~planemask
) >> 16) |
1328 ((result
& planemask
) >> 16);
1331 DoRop (result
, rop
, src
, *pdst
);
1333 *pdst
= (*pdst
& ~planemask
) |
1334 (result
& planemask
);
1344 #endif /* PSZ == 8 */
1346 /* shared among all different cfb depths through linker magic */
1348 RegionPtr
cfbCopyPlane(pSrcDrawable
, pDstDrawable
,
1349 pGC
, srcx
, srcy
, width
, height
, dstx
, dsty
, bitPlane
)
1350 DrawablePtr pSrcDrawable
;
1351 DrawablePtr pDstDrawable
;
1356 unsigned long bitPlane
;
1360 #if IMAGE_BYTE_ORDER == LSBFirst
1362 void (*doCopyPlaneExpand
)(
1363 DrawablePtr
/*pSrc*/,
1364 DrawablePtr
/*pDst*/,
1366 RegionPtr
/*prgnDst*/,
1367 DDXPointPtr
/*pptSrc*/,
1368 unsigned long /*planemask*/);
1370 if (pSrcDrawable
->bitsPerPixel
== 1 && pDstDrawable
->bitsPerPixel
== PSZ
)
1374 doCopyPlaneExpand
= cfbCopyPlane1toN
;
1376 cfb8CheckOpaqueStipple (pGC
->alu
,
1377 pGC
->fgPixel
, pGC
->bgPixel
,
1380 FgPixel
= pGC
->fgPixel
;
1381 BgPixel
= pGC
->bgPixel
;
1383 ret
= cfbCopyPlaneExpand (pSrcDrawable
, pDstDrawable
,
1384 pGC
, srcx
, srcy
, width
, height
, dstx
, dsty
, doCopyPlaneExpand
, bitPlane
);
1387 ret
= miHandleExposures (pSrcDrawable
, pDstDrawable
,
1388 pGC
, srcx
, srcy
, width
, height
, dstx
, dsty
, bitPlane
);
1390 else if (pSrcDrawable
->bitsPerPixel
== PSZ
&& pDstDrawable
->bitsPerPixel
== 1)
1395 if ((pGC
->fgPixel
& 1) == 0 && (pGC
->bgPixel
&1) == 1)
1396 pGC
->alu
= mfbGetInverseAlu(pGC
->alu
);
1397 else if ((pGC
->fgPixel
& 1) == (pGC
->bgPixel
& 1))
1398 pGC
->alu
= mfbReduceRop(pGC
->alu
, pGC
->fgPixel
);
1399 ret
= cfbCopyPlaneReduce(pSrcDrawable
, pDstDrawable
,
1400 pGC
, srcx
, srcy
, width
, height
, dstx
, dsty
,
1401 cfbCopyPlaneNto1
, bitPlane
);
1404 else if (pSrcDrawable
->bitsPerPixel
== PSZ
&& pDstDrawable
->bitsPerPixel
== PSZ
)
1407 ScreenPtr pScreen
= pSrcDrawable
->pScreen
;
1410 pBitmap
= (*pScreen
->CreatePixmap
) (pScreen
, width
, height
, 1);
1413 pGC1
= GetScratchGC (1, pScreen
);
1416 (*pScreen
->DestroyPixmap
) (pBitmap
);
1420 * don't need to set pGC->fgPixel,bgPixel as copyPlaneNto1
1421 * ignores pixel values, expecting the rop to "do the
1422 * right thing", which GXcopy will.
1424 ValidateGC ((DrawablePtr
) pBitmap
, pGC1
);
1425 /* no exposures here, scratch GC's don't get graphics expose */
1426 cfbCopyPlaneReduce(pSrcDrawable
, (DrawablePtr
) pBitmap
,
1427 pGC1
, srcx
, srcy
, width
, height
, 0, 0,
1428 cfbCopyPlaneNto1
, bitPlane
);
1430 cfb8CheckOpaqueStipple (pGC
->alu
,
1431 pGC
->fgPixel
, pGC
->bgPixel
,
1434 FgPixel
= pGC
->fgPixel
;
1435 BgPixel
= pGC
->bgPixel
;
1437 /* no exposures here, copy bits from inside a pixmap */
1438 cfbCopyPlaneExpand((DrawablePtr
) pBitmap
, pDstDrawable
, pGC
,
1439 0, 0, width
, height
, dstx
, dsty
, cfbCopyPlane1toN
, 1);
1440 FreeScratchGC (pGC1
);
1441 (*pScreen
->DestroyPixmap
) (pBitmap
);
1442 /* compute resultant exposures */
1443 ret
= miHandleExposures (pSrcDrawable
, pDstDrawable
, pGC
,
1444 srcx
, srcy
, width
, height
,
1445 dstx
, dsty
, bitPlane
);
1449 ret
= miCopyPlane (pSrcDrawable
, pDstDrawable
,
1450 pGC
, srcx
, srcy
, width
, height
, dstx
, dsty
, bitPlane
);