]> git.sesse.net Git - rdpsrv/blob - Xserver/programs/Xserver/cfb/cfbbitblt.c
Import X server from vnc-3.3.7.
[rdpsrv] / Xserver / programs / Xserver / cfb / cfbbitblt.c
1 /*
2  * cfb copy area
3  */
4
5 /*
6
7 Copyright (c) 1989  X Consortium
8
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:
15
16 The above copyright notice and this permission notice shall be included in
17 all copies or substantial portions of the Software.
18
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.
25
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.
29
30 Author: Keith Packard
31
32 */
33 /* $XConsortium: cfbbitblt.c,v 5.51 94/05/27 11:00:56 dpw Exp $ */
34
35 #include        "X.h"
36 #include        "Xmd.h"
37 #include        "Xproto.h"
38 #include        "gcstruct.h"
39 #include        "windowstr.h"
40 #include        "scrnintstr.h"
41 #include        "pixmapstr.h"
42 #include        "regionstr.h"
43 #include        "cfb.h"
44 #include        "cfbmskbits.h"
45 #include        "cfb8bit.h"
46 #include        "fastblt.h"
47 #define MFB_CONSTS_ONLY
48 #include        "maskbits.h"
49
50 RegionPtr
51 cfbBitBlt (pSrcDrawable, pDstDrawable,
52             pGC, srcx, srcy, width, height, dstx, dsty, doBitBlt, bitPlane)
53     register DrawablePtr pSrcDrawable;
54     register DrawablePtr pDstDrawable;
55     GC *pGC;
56     int srcx, srcy;
57     int width, height;
58     int dstx, dsty;
59     void (*doBitBlt)();
60     unsigned long bitPlane;
61 {
62     RegionPtr prgnSrcClip;      /* may be a new region, or just a copy */
63     Bool freeSrcClip = FALSE;
64
65     RegionPtr prgnExposed;
66     RegionRec rgnDst;
67     DDXPointPtr pptSrc;
68     register DDXPointPtr ppt;
69     register BoxPtr pbox;
70     int i;
71     register int dx;
72     register int dy;
73     xRectangle origSource;
74     DDXPointRec origDest;
75     int numRects;
76     BoxRec fastBox;
77     int fastClip = 0;           /* for fast clipping with pixmap source */
78     int fastExpose = 0;         /* for fast exposures with pixmap source */
79
80     origSource.x = srcx;
81     origSource.y = srcy;
82     origSource.width = width;
83     origSource.height = height;
84     origDest.x = dstx;
85     origDest.y = dsty;
86
87     if ((pSrcDrawable != pDstDrawable) &&
88         pSrcDrawable->pScreen->SourceValidate)
89     {
90         (*pSrcDrawable->pScreen->SourceValidate) (pSrcDrawable, srcx, srcy, width, height);
91     }
92
93     srcx += pSrcDrawable->x;
94     srcy += pSrcDrawable->y;
95
96     /* clip the source */
97
98     if (pSrcDrawable->type == DRAWABLE_PIXMAP)
99     {
100         if ((pSrcDrawable == pDstDrawable) &&
101             (pGC->clientClipType == CT_NONE))
102         {
103             prgnSrcClip = cfbGetCompositeClip(pGC);
104         }
105         else
106         {
107             fastClip = 1;
108         }
109     }
110     else
111     {
112         if (pGC->subWindowMode == IncludeInferiors)
113         {
114             if (!((WindowPtr) pSrcDrawable)->parent)
115             {
116                 /*
117                  * special case bitblt from root window in
118                  * IncludeInferiors mode; just like from a pixmap
119                  */
120                 fastClip = 1;
121             }
122             else if ((pSrcDrawable == pDstDrawable) &&
123                 (pGC->clientClipType == CT_NONE))
124             {
125                 prgnSrcClip = cfbGetCompositeClip(pGC);
126             }
127             else
128             {
129                 prgnSrcClip = NotClippedByChildren((WindowPtr)pSrcDrawable);
130                 freeSrcClip = TRUE;
131             }
132         }
133         else
134         {
135             prgnSrcClip = &((WindowPtr)pSrcDrawable)->clipList;
136         }
137     }
138
139     fastBox.x1 = srcx;
140     fastBox.y1 = srcy;
141     fastBox.x2 = srcx + width;
142     fastBox.y2 = srcy + height;
143
144     /* Don't create a source region if we are doing a fast clip */
145     if (fastClip)
146     {
147         fastExpose = 1;
148         /*
149          * clip the source; if regions extend beyond the source size,
150          * make sure exposure events get sent
151          */
152         if (fastBox.x1 < pSrcDrawable->x)
153         {
154             fastBox.x1 = pSrcDrawable->x;
155             fastExpose = 0;
156         }
157         if (fastBox.y1 < pSrcDrawable->y)
158         {
159             fastBox.y1 = pSrcDrawable->y;
160             fastExpose = 0;
161         }
162         if (fastBox.x2 > pSrcDrawable->x + (int) pSrcDrawable->width)
163         {
164             fastBox.x2 = pSrcDrawable->x + (int) pSrcDrawable->width;
165             fastExpose = 0;
166         }
167         if (fastBox.y2 > pSrcDrawable->y + (int) pSrcDrawable->height)
168         {
169             fastBox.y2 = pSrcDrawable->y + (int) pSrcDrawable->height;
170             fastExpose = 0;
171         }
172     }
173     else
174     {
175         REGION_INIT(pGC->pScreen, &rgnDst, &fastBox, 1);
176         REGION_INTERSECT(pGC->pScreen, &rgnDst, &rgnDst, prgnSrcClip);
177     }
178
179     dstx += pDstDrawable->x;
180     dsty += pDstDrawable->y;
181
182     if (pDstDrawable->type == DRAWABLE_WINDOW)
183     {
184         if (!((WindowPtr)pDstDrawable)->realized)
185         {
186             if (!fastClip)
187                 REGION_UNINIT(pGC->pScreen, &rgnDst);
188             if (freeSrcClip)
189                 REGION_DESTROY(pGC->pScreen, prgnSrcClip);
190             return NULL;
191         }
192     }
193
194     dx = srcx - dstx;
195     dy = srcy - dsty;
196
197     /* Translate and clip the dst to the destination composite clip */
198     if (fastClip)
199     {
200         RegionPtr cclip;
201
202         /* Translate the region directly */
203         fastBox.x1 -= dx;
204         fastBox.x2 -= dx;
205         fastBox.y1 -= dy;
206         fastBox.y2 -= dy;
207
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 */
211
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
215          */
216
217         cclip = cfbGetCompositeClip(pGC);
218         if (REGION_NUM_RECTS(cclip) == 1)
219         {
220             BoxPtr pBox = REGION_RECTS(cclip);
221
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;
226
227             /* Check to see if the region is empty */
228             if (fastBox.x1 >= fastBox.x2 || fastBox.y1 >= fastBox.y2)
229             {
230                 REGION_INIT(pGC->pScreen, &rgnDst, NullBox, 0);
231             }
232             else
233             {
234                 REGION_INIT(pGC->pScreen, &rgnDst, &fastBox, 1);
235             }
236         }
237         else
238         {
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. */
242             fastClip = 0;
243             REGION_INIT(pGC->pScreen, &rgnDst, &fastBox,1);
244         }
245     }
246     else
247     {
248         REGION_TRANSLATE(pGC->pScreen, &rgnDst, -dx, -dy);
249     }
250
251     if (!fastClip)
252     {
253         REGION_INTERSECT(pGC->pScreen, &rgnDst,
254                                    &rgnDst,
255                                    cfbGetCompositeClip(pGC));
256     }
257
258     /* Do bit blitting */
259     numRects = REGION_NUM_RECTS(&rgnDst);
260     if (numRects && width && height)
261     {
262         if(!(pptSrc = (DDXPointPtr)ALLOCATE_LOCAL(numRects *
263                                                   sizeof(DDXPointRec))))
264         {
265             REGION_UNINIT(pGC->pScreen, &rgnDst);
266             if (freeSrcClip)
267                 REGION_DESTROY(pGC->pScreen, prgnSrcClip);
268             return NULL;
269         }
270         pbox = REGION_RECTS(&rgnDst);
271         ppt = pptSrc;
272         for (i = numRects; --i >= 0; pbox++, ppt++)
273         {
274             ppt->x = pbox->x1 + dx;
275             ppt->y = pbox->y1 + dy;
276         }
277
278         (*doBitBlt) (pSrcDrawable, pDstDrawable, pGC->alu, &rgnDst, pptSrc, pGC->planemask, bitPlane);
279         DEALLOCATE_LOCAL(pptSrc);
280     }
281
282     prgnExposed = NULL;
283     if ( cfbGetGCPrivate(pGC)->fExpose)
284     {
285         extern RegionPtr    miHandleExposures();
286
287         /* Pixmap sources generate a NoExposed (we return NULL to do this) */
288         if (!fastExpose)
289             prgnExposed =
290                 miHandleExposures(pSrcDrawable, pDstDrawable, pGC,
291                                   origSource.x, origSource.y,
292                                   (int)origSource.width,
293                                   (int)origSource.height,
294                                   origDest.x, origDest.y, bitPlane);
295     }
296     REGION_UNINIT(pGC->pScreen, &rgnDst);
297     if (freeSrcClip)
298         REGION_DESTROY(pGC->pScreen, prgnSrcClip);
299     return prgnExposed;
300 }
301
302
303 void
304 cfbDoBitblt (pSrc, pDst, alu, prgnDst, pptSrc, planemask)
305     DrawablePtr     pSrc, pDst;
306     int             alu;
307     RegionPtr       prgnDst;
308     DDXPointPtr     pptSrc;
309     unsigned long   planemask;
310 {
311     void (*blt)() = cfbDoBitbltGeneral;
312     if ((planemask & PMSK) == PMSK) {
313         switch (alu) {
314         case GXcopy:
315             blt = cfbDoBitbltCopy;
316             break;
317         case GXxor:
318             blt = cfbDoBitbltXor;
319             break;
320         case GXor:
321             blt = cfbDoBitbltOr;
322             break;
323         }
324     }
325     (*blt) (pSrc, pDst, alu, prgnDst, pptSrc, planemask);
326 }
327
328 RegionPtr
329 cfbCopyArea(pSrcDrawable, pDstDrawable,
330             pGC, srcx, srcy, width, height, dstx, dsty)
331     register DrawablePtr pSrcDrawable;
332     register DrawablePtr pDstDrawable;
333     GC *pGC;
334     int srcx, srcy;
335     int width, height;
336     int dstx, dsty;
337 {
338     void (*doBitBlt) ();
339     
340     doBitBlt = cfbDoBitbltCopy;
341     if (pGC->alu != GXcopy || (pGC->planemask & PMSK) != PMSK)
342     {
343         doBitBlt = cfbDoBitbltGeneral;
344         if ((pGC->planemask & PMSK) == PMSK)
345         {
346             switch (pGC->alu) {
347             case GXxor:
348                 doBitBlt = cfbDoBitbltXor;
349                 break;
350             case GXor:
351                 doBitBlt = cfbDoBitbltOr;
352                 break;
353             }
354         }
355     }
356     return cfbBitBlt (pSrcDrawable, pDstDrawable,
357             pGC, srcx, srcy, width, height, dstx, dsty, doBitBlt, 0L);
358 }
359
360 #if PSZ == 8
361 void
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 */
374 {
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 */
392     register int nl;
393     int firstoff;
394     int secondoff;
395     unsigned long src;
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 */
400
401     cfbGetLongWidthAndPointer (pSrcDrawable, widthSrc, psrcBase)
402     cfbGetLongWidthAndPointer (pDstDrawable, widthDst, pdstBase)
403
404     nbox = REGION_NUM_RECTS(prgnDst);
405     pbox = REGION_RECTS(prgnDst);
406     while (nbox--)
407     {
408         dstx = pbox->x1;
409         dsty = pbox->y1;
410         srcx = pptSrc->x;
411         srcy = pptSrc->y;
412         width = pbox->x2 - pbox->x1;
413         height = pbox->y2 - pbox->y1;
414         pbox++;
415         pptSrc++;
416
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 */
421
422         /* compute startmask, endmask, nlMiddle */
423
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 */
429         }
430         else
431         { /* the copy will affect multiple words per row in destination */
432             maskbits(dstx, width, startmask, endmask, nlMiddle);
433         }
434
435         /*
436          * compute constants for the first four bits to be
437          * copied.  This avoids troubles with partial first
438          * writes, and difficult shift computation
439          */
440         if (startmask)
441         {
442             firstoff = xoffSrc - xoffDst;
443             if (firstoff > (MFB_PPW-PPW))
444                 secondoff = MFB_PPW - firstoff;
445             if (xoffDst)
446             {
447                 srcx += (PPW-xoffDst);
448                 xoffSrc = srcx & MFB_PIM;
449             }
450         }
451         leftShift = xoffSrc;
452         rightShift = MFB_PPW - leftShift;
453
454         pixelsRemainingOnRightEdge = (nlMiddle & 7) * PPW +
455                                         ((dstx + width) & PIM);
456
457         /* setup is done; now let's move some bits */
458
459         /* caller must call cfb8CheckOpaqueStipple before this function
460          * to set cfb8StippleRRop!
461          */
462
463         if (cfb8StippleRRop == GXcopy)
464         {
465             while (height--)
466             { /* one iteration of this loop copies one row */
467                 psrc = psrcLine;
468                 pdst = pdstLine;
469                 psrcLine += widthSrc;
470                 pdstLine += widthDst;
471                 bits = *psrc++;
472                 if (startmask)
473                 {
474                     if (firstoff < 0)
475                         tmp = BitRight (bits, -firstoff);
476                     else
477                     {
478                         tmp = BitLeft (bits, firstoff);
479                         /*
480                          * need a more cautious test for partialmask
481                          * case...
482                          */
483                         if (firstoff >= (MFB_PPW-PPW))
484                         {
485                             bits = *psrc++;
486                             if (firstoff != (MFB_PPW-PPW))
487                                 tmp |= BitRight (bits, secondoff);
488                         }
489                     }
490                     *pdst = (*pdst & ~startmask) | (GetPixelGroup(tmp) & startmask);
491                     pdst++;
492                 }
493                 nl = nlMiddle;
494                 while (nl >= 8)
495                 {
496                     nl -= 8;
497                     tmp = BitLeft(bits, leftShift);
498                     bits = *psrc++;
499                     if (rightShift != MFB_PPW)
500                         tmp |= BitRight(bits, rightShift);
501
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);
506 #else
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)++;
510 #endif
511
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)
519
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 */
525 #if PGSZ == 64
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);
531 #else
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);
539 #endif /* PGSZ */
540 #endif /* BITMAP_BIT_ORDER */
541
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);
550                 }
551
552                 /* do rest of middle and partial word on right edge */
553
554                 if (pixelsRemainingOnRightEdge)
555                 {
556                     tmp = BitLeft(bits, leftShift);
557
558                     if (pixelsRemainingOnRightEdge > rightShift)
559                     {
560                         bits = *psrc++;
561                         tmp |= BitRight (bits, rightShift);
562                     }
563                     EndStep (pdst, nl);
564                     switch (nl)
565                     {
566                     case 7:
567                         StoreBitsPlain(-7,tmp); Step(tmp);
568                     case 6:
569                         StoreBitsPlain(-6,tmp); Step(tmp);
570                     case 5:
571                         StoreBitsPlain(-5,tmp); Step(tmp);
572                     case 4:
573                         StoreBitsPlain(-4,tmp); Step(tmp);
574                     case 3:
575                         StoreBitsPlain(-3,tmp); Step(tmp);
576                     case 2:
577                         StoreBitsPlain(-2,tmp); Step(tmp);
578                     case 1:
579                         StoreBitsPlain(-1,tmp); Step(tmp);
580                     }
581                     if (endmask)
582                         *pdst = (*pdst & ~endmask) | (GetPixelGroup(tmp) & endmask);
583                 }
584             }
585         }
586         else /* cfb8StippleRRop != GXcopy */
587         {
588             while (height--)
589             { /* one iteration of this loop copies one row */
590                 psrc = psrcLine;
591                 pdst = pdstLine;
592                 psrcLine += widthSrc;
593                 pdstLine += widthDst;
594                 bits = *psrc++;
595
596                 /* do partial word on left edge */
597
598                 if (startmask)
599                 {
600                     if (firstoff < 0)
601                         tmp = BitRight (bits, -firstoff);
602                     else
603                     {
604                         tmp = BitLeft (bits, firstoff);
605                         if (firstoff >= (MFB_PPW-PPW))
606                         {
607                             bits = *psrc++;
608                             if (firstoff != (MFB_PPW-PPW))
609                                 tmp |= BitRight (bits, secondoff);
610                         }
611                     }
612                     src = GetBitGroup(tmp);
613                     *pdst = MaskRRopPixels (*pdst, src, startmask);
614                     pdst++;
615                 }
616
617                 /* do middle of row */
618
619                 nl = nlMiddle;
620                 while (nl >= 8)
621                 {
622                     nl -= 8;
623                     tmp = BitLeft(bits, leftShift);
624                     bits = *psrc++;
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);
635                 }
636
637                 /* do rest of middle and partial word on right edge */
638
639                 if (pixelsRemainingOnRightEdge)
640                 {
641                     tmp = BitLeft(bits, leftShift);
642
643                     if (pixelsRemainingOnRightEdge > rightShift)
644                     {
645                         bits = *psrc++; /* XXX purify abr here */
646                         tmp |= BitRight (bits, rightShift);
647                     }
648                     while (nl--)
649                     {
650                         src = GetBitGroup (tmp);
651                         *pdst = RRopPixels (*pdst, src);
652                         pdst++;
653                         NextBitGroup(tmp);
654                     }
655                     if (endmask)
656                     {
657                         src = GetBitGroup (tmp);
658                         *pdst = MaskRRopPixels (*pdst, src, endmask);
659                     }
660                 }
661             } /* end copy one row */
662         } /* end alu is non-copy-mode case */
663     } /* end iteration over region boxes */
664 }
665
666 #endif
667
668 /* shared among all different cfb depths through linker magic */
669 RegionPtr   (*cfbPuntCopyPlane)();
670
671 RegionPtr cfbCopyPlane(pSrcDrawable, pDstDrawable,
672             pGC, srcx, srcy, width, height, dstx, dsty, bitPlane)
673     DrawablePtr         pSrcDrawable;
674     DrawablePtr         pDstDrawable;
675     GCPtr               pGC;
676     int                 srcx, srcy;
677     int                 width, height;
678     int                 dstx, dsty;
679     unsigned long       bitPlane;
680 {
681     RegionPtr   ret;
682     extern RegionPtr    miHandleExposures();
683     void                (*doBitBlt)();
684
685 #if PSZ == 8
686
687     if (pSrcDrawable->bitsPerPixel == 1 && pDstDrawable->bitsPerPixel == 8)
688     {
689         if (bitPlane == 1)
690         {
691             doBitBlt = cfbCopyPlane1to8;
692             cfb8CheckOpaqueStipple (pGC->alu,
693                                     pGC->fgPixel, pGC->bgPixel,
694                                     pGC->planemask);
695             ret = cfbBitBlt (pSrcDrawable, pDstDrawable,
696                     pGC, srcx, srcy, width, height, dstx, dsty, doBitBlt, bitPlane);
697         }
698         else
699             ret = miHandleExposures (pSrcDrawable, pDstDrawable,
700                 pGC, srcx, srcy, width, height, dstx, dsty, bitPlane);
701     }
702     else if (pSrcDrawable->bitsPerPixel == 8 && pDstDrawable->bitsPerPixel == 1)
703     {
704         extern  int InverseAlu[16];
705         int oldalu;
706
707         oldalu = pGC->alu;
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);
715         pGC->alu = oldalu;
716     }
717     else if (pSrcDrawable->bitsPerPixel == 8 && pDstDrawable->bitsPerPixel == 8)
718     {
719         PixmapPtr       pBitmap;
720         ScreenPtr       pScreen = pSrcDrawable->pScreen;
721         GCPtr           pGC1;
722
723         pBitmap = (*pScreen->CreatePixmap) (pScreen, width, height, 1);
724         if (!pBitmap)
725             return NULL;
726         pGC1 = GetScratchGC (1, pScreen);
727         if (!pGC1)
728         {
729             (*pScreen->DestroyPixmap) (pBitmap);
730             return NULL;
731         }
732         /*
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.
736          */
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,
744                                 pGC->planemask);
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);
754     }
755     else
756 #endif
757     ret = (*cfbPuntCopyPlane) (pSrcDrawable, pDstDrawable,
758             pGC, srcx, srcy, width, height, dstx, dsty, bitPlane);
759     return ret;
760 }