xserver

xserver with xephyr scale patch
git clone https://git.neptards.moe/u3shit/xserver.git
Log | Files | Refs | README | LICENSE

mibitblt.c (27383B)


      1 /***********************************************************
      2 
      3 Copyright 1987, 1998  The Open Group
      4 
      5 Permission to use, copy, modify, distribute, and sell this software and its
      6 documentation for any purpose is hereby granted without fee, provided that
      7 the above copyright notice appear in all copies and that both that
      8 copyright notice and this permission notice appear in supporting
      9 documentation.
     10 
     11 The above copyright notice and this permission notice shall be included in
     12 all copies or substantial portions of the Software.
     13 
     14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
     17 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
     18 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
     19 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     20 
     21 Except as contained in this notice, the name of The Open Group shall not be
     22 used in advertising or otherwise to promote the sale, use or other dealings
     23 in this Software without prior written authorization from The Open Group.
     24 
     25 Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
     26 
     27                         All Rights Reserved
     28 
     29 Permission to use, copy, modify, and distribute this software and its
     30 documentation for any purpose and without fee is hereby granted,
     31 provided that the above copyright notice appear in all copies and that
     32 both that copyright notice and this permission notice appear in
     33 supporting documentation, and that the name of Digital not be
     34 used in advertising or publicity pertaining to distribution of the
     35 software without specific, written prior permission.
     36 
     37 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
     38 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
     39 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
     40 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
     41 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
     42 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
     43 SOFTWARE.
     44 
     45 ******************************************************************/
     46 /* Author: Todd Newman  (aided and abetted by Mr. Drewry) */
     47 
     48 #ifdef HAVE_DIX_CONFIG_H
     49 #include <dix-config.h>
     50 #endif
     51 
     52 #include <X11/X.h>
     53 #include <X11/Xprotostr.h>
     54 
     55 #include "misc.h"
     56 #include "gcstruct.h"
     57 #include "pixmapstr.h"
     58 #include "windowstr.h"
     59 #include "scrnintstr.h"
     60 #include "mi.h"
     61 #include "regionstr.h"
     62 #include <X11/Xmd.h>
     63 #include "servermd.h"
     64 
     65 #ifdef __MINGW32__
     66 #define ffs __builtin_ffs
     67 #endif
     68 
     69 /* MICOPYAREA -- public entry for the CopyArea request
     70  * For each rectangle in the source region
     71  *     get the pixels with GetSpans
     72  *     set them in the destination with SetSpans
     73  * We let SetSpans worry about clipping to the destination.
     74  */
     75 _X_COLD RegionPtr
     76 miCopyArea(DrawablePtr pSrcDrawable,
     77            DrawablePtr pDstDrawable,
     78            GCPtr pGC,
     79            int xIn, int yIn, int widthSrc, int heightSrc, int xOut, int yOut)
     80 {
     81     DDXPointPtr ppt, pptFirst;
     82     unsigned int *pwidthFirst, *pwidth, *pbits;
     83     BoxRec srcBox, *prect;
     84 
     85     /* may be a new region, or just a copy */
     86     RegionPtr prgnSrcClip;
     87 
     88     /* non-0 if we've created a src clip */
     89     RegionPtr prgnExposed;
     90     int realSrcClip = 0;
     91     int srcx, srcy, dstx, dsty, i, j, y, width, height, xMin, xMax, yMin, yMax;
     92     unsigned int *ordering;
     93     int numRects;
     94     BoxPtr boxes;
     95 
     96     srcx = xIn + pSrcDrawable->x;
     97     srcy = yIn + pSrcDrawable->y;
     98 
     99     /* If the destination isn't realized, this is easy */
    100     if (pDstDrawable->type == DRAWABLE_WINDOW &&
    101         !((WindowPtr) pDstDrawable)->realized)
    102         return NULL;
    103 
    104     /* clip the source */
    105     if (pSrcDrawable->type == DRAWABLE_PIXMAP) {
    106         BoxRec box;
    107 
    108         box.x1 = pSrcDrawable->x;
    109         box.y1 = pSrcDrawable->y;
    110         box.x2 = pSrcDrawable->x + (int) pSrcDrawable->width;
    111         box.y2 = pSrcDrawable->y + (int) pSrcDrawable->height;
    112 
    113         prgnSrcClip = RegionCreate(&box, 1);
    114         realSrcClip = 1;
    115     }
    116     else {
    117         if (pGC->subWindowMode == IncludeInferiors) {
    118             prgnSrcClip = NotClippedByChildren((WindowPtr) pSrcDrawable);
    119             realSrcClip = 1;
    120         }
    121         else
    122             prgnSrcClip = &((WindowPtr) pSrcDrawable)->clipList;
    123     }
    124 
    125     /* If the src drawable is a window, we need to translate the srcBox so
    126      * that we can compare it with the window's clip region later on. */
    127     srcBox.x1 = srcx;
    128     srcBox.y1 = srcy;
    129     srcBox.x2 = srcx + widthSrc;
    130     srcBox.y2 = srcy + heightSrc;
    131 
    132     dstx = xOut;
    133     dsty = yOut;
    134     if (pGC->miTranslate) {
    135         dstx += pDstDrawable->x;
    136         dsty += pDstDrawable->y;
    137     }
    138 
    139     pptFirst = ppt = xallocarray(heightSrc, sizeof(DDXPointRec));
    140     pwidthFirst = pwidth = xallocarray(heightSrc, sizeof(unsigned int));
    141     numRects = RegionNumRects(prgnSrcClip);
    142     boxes = RegionRects(prgnSrcClip);
    143     ordering = xallocarray(numRects, sizeof(unsigned int));
    144     if (!pptFirst || !pwidthFirst || !ordering) {
    145         free(ordering);
    146         free(pwidthFirst);
    147         free(pptFirst);
    148         if (realSrcClip)
    149             RegionDestroy(prgnSrcClip);
    150         return NULL;
    151     }
    152 
    153     /* If not the same drawable then order of move doesn't matter.
    154        Following assumes that boxes are sorted from top
    155        to bottom and left to right.
    156      */
    157     if ((pSrcDrawable != pDstDrawable) &&
    158         ((pGC->subWindowMode != IncludeInferiors) ||
    159          (pSrcDrawable->type == DRAWABLE_PIXMAP) ||
    160          (pDstDrawable->type == DRAWABLE_PIXMAP)))
    161         for (i = 0; i < numRects; i++)
    162             ordering[i] = i;
    163     else {                      /* within same drawable, must sequence moves carefully! */
    164         if (dsty <= srcBox.y1) {        /* Scroll up or stationary vertical.
    165                                            Vertical order OK */
    166             if (dstx <= srcBox.x1)      /* Scroll left or stationary horizontal.
    167                                            Horizontal order OK as well */
    168                 for (i = 0; i < numRects; i++)
    169                     ordering[i] = i;
    170             else {              /* scroll right. must reverse horizontal banding of rects. */
    171                 for (i = 0, j = 1, xMax = 0; i < numRects; j = i + 1, xMax = i) {
    172                     /* find extent of current horizontal band */
    173                     y = boxes[i].y1;    /* band has this y coordinate */
    174                     while ((j < numRects) && (boxes[j].y1 == y))
    175                         j++;
    176                     /* reverse the horizontal band in the output ordering */
    177                     for (j--; j >= xMax; j--, i++)
    178                         ordering[i] = j;
    179                 }
    180             }
    181         }
    182         else {                  /* Scroll down. Must reverse vertical banding. */
    183             if (dstx < srcBox.x1) {     /* Scroll left. Horizontal order OK. */
    184                 for (i = numRects - 1, j = i - 1, yMin = i, yMax = 0;
    185                      i >= 0; j = i - 1, yMin = i) {
    186                     /* find extent of current horizontal band */
    187                     y = boxes[i].y1;    /* band has this y coordinate */
    188                     while ((j >= 0) && (boxes[j].y1 == y))
    189                         j--;
    190                     /* reverse the horizontal band in the output ordering */
    191                     for (j++; j <= yMin; j++, i--, yMax++)
    192                         ordering[yMax] = j;
    193                 }
    194             }
    195             else                /* Scroll right or horizontal stationary.
    196                                    Reverse horizontal order as well (if stationary, horizontal
    197                                    order can be swapped without penalty and this is faster
    198                                    to compute). */
    199                 for (i = 0, j = numRects - 1; i < numRects; i++, j--)
    200                     ordering[i] = j;
    201         }
    202     }
    203 
    204     for (i = 0; i < numRects; i++) {
    205         prect = &boxes[ordering[i]];
    206         xMin = max(prect->x1, srcBox.x1);
    207         xMax = min(prect->x2, srcBox.x2);
    208         yMin = max(prect->y1, srcBox.y1);
    209         yMax = min(prect->y2, srcBox.y2);
    210         /* is there anything visible here? */
    211         if (xMax <= xMin || yMax <= yMin)
    212             continue;
    213 
    214         ppt = pptFirst;
    215         pwidth = pwidthFirst;
    216         y = yMin;
    217         height = yMax - yMin;
    218         width = xMax - xMin;
    219 
    220         for (j = 0; j < height; j++) {
    221             /* We must untranslate before calling GetSpans */
    222             ppt->x = xMin;
    223             ppt++->y = y++;
    224             *pwidth++ = width;
    225         }
    226         pbits = xallocarray(height, PixmapBytePad(width, pSrcDrawable->depth));
    227         if (pbits) {
    228             (*pSrcDrawable->pScreen->GetSpans) (pSrcDrawable, width, pptFirst,
    229                                                 (int *) pwidthFirst, height,
    230                                                 (char *) pbits);
    231             ppt = pptFirst;
    232             pwidth = pwidthFirst;
    233             xMin -= (srcx - dstx);
    234             y = yMin - (srcy - dsty);
    235             for (j = 0; j < height; j++) {
    236                 ppt->x = xMin;
    237                 ppt++->y = y++;
    238                 *pwidth++ = width;
    239             }
    240 
    241             (*pGC->ops->SetSpans) (pDstDrawable, pGC, (char *) pbits, pptFirst,
    242                                    (int *) pwidthFirst, height, TRUE);
    243             free(pbits);
    244         }
    245     }
    246     prgnExposed = miHandleExposures(pSrcDrawable, pDstDrawable, pGC, xIn, yIn,
    247                                     widthSrc, heightSrc, xOut, yOut);
    248     if (realSrcClip)
    249         RegionDestroy(prgnSrcClip);
    250 
    251     free(ordering);
    252     free(pwidthFirst);
    253     free(pptFirst);
    254     return prgnExposed;
    255 }
    256 
    257 /* MIGETPLANE -- gets a bitmap representing one plane of pDraw
    258  * A helper used for CopyPlane and XY format GetImage
    259  * No clever strategy here, we grab a scanline at a time, pull out the
    260  * bits and then stuff them in a 1 bit deep map.
    261  */
    262 /*
    263  * This should be replaced with something more general.  mi shouldn't have to
    264  * care about such things as scanline padding et alia.
    265  */
    266 _X_COLD static MiBits *
    267 miGetPlane(DrawablePtr pDraw, int planeNum,     /* number of the bitPlane */
    268            int sx, int sy, int w, int h, MiBits * result)
    269 {
    270     int i, j, k, width, bitsPerPixel, widthInBytes;
    271     DDXPointRec pt = { 0, 0 };
    272     MiBits pixel;
    273     MiBits bit;
    274     unsigned char *pCharsOut = NULL;
    275 
    276 #if BITMAP_SCANLINE_UNIT == 8
    277 #define OUT_TYPE unsigned char
    278 #endif
    279 #if BITMAP_SCANLINE_UNIT == 16
    280 #define OUT_TYPE CARD16
    281 #endif
    282 #if BITMAP_SCANLINE_UNIT == 32
    283 #define OUT_TYPE CARD32
    284 #endif
    285 #if BITMAP_SCANLINE_UNIT == 64
    286 #define OUT_TYPE CARD64
    287 #endif
    288 
    289     OUT_TYPE *pOut;
    290     int delta = 0;
    291 
    292     sx += pDraw->x;
    293     sy += pDraw->y;
    294     widthInBytes = BitmapBytePad(w);
    295     if (!result)
    296         result = calloc(h, widthInBytes);
    297     if (!result)
    298         return NULL;
    299     bitsPerPixel = pDraw->bitsPerPixel;
    300     pOut = (OUT_TYPE *) result;
    301     if (bitsPerPixel == 1) {
    302         pCharsOut = (unsigned char *) result;
    303         width = w;
    304     }
    305     else {
    306         delta = (widthInBytes / (BITMAP_SCANLINE_UNIT / 8)) -
    307             (w / BITMAP_SCANLINE_UNIT);
    308         width = 1;
    309 #if IMAGE_BYTE_ORDER == MSBFirst
    310         planeNum += (32 - bitsPerPixel);
    311 #endif
    312     }
    313     pt.y = sy;
    314     for (i = h; --i >= 0; pt.y++) {
    315         pt.x = sx;
    316         if (bitsPerPixel == 1) {
    317             (*pDraw->pScreen->GetSpans) (pDraw, width, &pt, &width, 1,
    318                                          (char *) pCharsOut);
    319             pCharsOut += widthInBytes;
    320         }
    321         else {
    322             k = 0;
    323             for (j = w; --j >= 0; pt.x++) {
    324                 /* Fetch the next pixel */
    325                 (*pDraw->pScreen->GetSpans) (pDraw, width, &pt, &width, 1,
    326                                              (char *) &pixel);
    327                 /*
    328                  * Now get the bit and insert into a bitmap in XY format.
    329                  */
    330                 bit = (pixel >> planeNum) & 1;
    331 #if 0
    332                 /* XXX assuming bit order == byte order */
    333 #if BITMAP_BIT_ORDER == LSBFirst
    334                 bit <<= k;
    335 #else
    336                 bit <<= ((BITMAP_SCANLINE_UNIT - 1) - k);
    337 #endif
    338 #else
    339                 /* XXX assuming byte order == LSBFirst */
    340                 if (screenInfo.bitmapBitOrder == LSBFirst)
    341                     bit <<= k;
    342                 else
    343                     bit <<= ((screenInfo.bitmapScanlineUnit - 1) -
    344                              (k % screenInfo.bitmapScanlineUnit)) +
    345                         ((k / screenInfo.bitmapScanlineUnit) *
    346                          screenInfo.bitmapScanlineUnit);
    347 #endif
    348                 *pOut |= (OUT_TYPE) bit;
    349                 k++;
    350                 if (k == BITMAP_SCANLINE_UNIT) {
    351                     pOut++;
    352                     k = 0;
    353                 }
    354             }
    355             pOut += delta;
    356         }
    357     }
    358     return result;
    359 
    360 }
    361 
    362 /* MIOPQSTIPDRAWABLE -- use pbits as an opaque stipple for pDraw.
    363  * Drawing through the clip mask we SetSpans() the bits into a
    364  * bitmap and stipple those bits onto the destination drawable by doing a
    365  * PolyFillRect over the whole drawable,
    366  * then we invert the bitmap by copying it onto itself with an alu of
    367  * GXinvert, invert the foreground/background colors of the gc, and draw
    368  * the background bits.
    369  * Note how the clipped out bits of the bitmap are always the background
    370  * color so that the stipple never causes FillRect to draw them.
    371  */
    372 _X_COLD static void
    373 miOpqStipDrawable(DrawablePtr pDraw, GCPtr pGC, RegionPtr prgnSrc,
    374                   MiBits * pbits, int srcx, int w, int h, int dstx, int dsty)
    375 {
    376     int oldfill, i;
    377     unsigned long oldfg;
    378     int *pwidth, *pwidthFirst;
    379     ChangeGCVal gcv[6];
    380     PixmapPtr pStipple, pPixmap;
    381     DDXPointRec oldOrg;
    382     GCPtr pGCT;
    383     DDXPointPtr ppt, pptFirst;
    384     xRectangle rect;
    385     RegionPtr prgnSrcClip;
    386 
    387     pPixmap = (*pDraw->pScreen->CreatePixmap)
    388         (pDraw->pScreen, w + srcx, h, 1, CREATE_PIXMAP_USAGE_SCRATCH);
    389     if (!pPixmap)
    390         return;
    391 
    392     /* Put the image into a 1 bit deep pixmap */
    393     pGCT = GetScratchGC(1, pDraw->pScreen);
    394     if (!pGCT) {
    395         (*pDraw->pScreen->DestroyPixmap) (pPixmap);
    396         return;
    397     }
    398     /* First set the whole pixmap to 0 */
    399     gcv[0].val = 0;
    400     ChangeGC(NullClient, pGCT, GCBackground, gcv);
    401     ValidateGC((DrawablePtr) pPixmap, pGCT);
    402     miClearDrawable((DrawablePtr) pPixmap, pGCT);
    403     ppt = pptFirst = xallocarray(h, sizeof(DDXPointRec));
    404     pwidth = pwidthFirst = xallocarray(h, sizeof(int));
    405     if (!pptFirst || !pwidthFirst) {
    406         free(pwidthFirst);
    407         free(pptFirst);
    408         FreeScratchGC(pGCT);
    409         return;
    410     }
    411 
    412     /* we need a temporary region because ChangeClip must be assumed
    413        to destroy what it's sent.  note that this means we don't
    414        have to free prgnSrcClip ourselves.
    415      */
    416     prgnSrcClip = RegionCreate(NULL, 0);
    417     RegionCopy(prgnSrcClip, prgnSrc);
    418     RegionTranslate(prgnSrcClip, srcx, 0);
    419     (*pGCT->funcs->ChangeClip) (pGCT, CT_REGION, prgnSrcClip, 0);
    420     ValidateGC((DrawablePtr) pPixmap, pGCT);
    421 
    422     /* Since we know pDraw is always a pixmap, we never need to think
    423      * about translation here */
    424     for (i = 0; i < h; i++) {
    425         ppt->x = 0;
    426         ppt++->y = i;
    427         *pwidth++ = w + srcx;
    428     }
    429 
    430     (*pGCT->ops->SetSpans) ((DrawablePtr) pPixmap, pGCT, (char *) pbits,
    431                             pptFirst, pwidthFirst, h, TRUE);
    432     free(pwidthFirst);
    433     free(pptFirst);
    434 
    435     /* Save current values from the client GC */
    436     oldfill = pGC->fillStyle;
    437     pStipple = pGC->stipple;
    438     if (pStipple)
    439         pStipple->refcnt++;
    440     oldOrg = pGC->patOrg;
    441 
    442     /* Set a new stipple in the drawable */
    443     gcv[0].val = FillStippled;
    444     gcv[1].ptr = pPixmap;
    445     gcv[2].val = dstx - srcx;
    446     gcv[3].val = dsty;
    447 
    448     ChangeGC(NullClient, pGC,
    449              GCFillStyle | GCStipple | GCTileStipXOrigin | GCTileStipYOrigin,
    450              gcv);
    451     ValidateGC(pDraw, pGC);
    452 
    453     /* Fill the drawable with the stipple.  This will draw the
    454      * foreground color wherever 1 bits are set, leaving everything
    455      * with 0 bits untouched.  Note that the part outside the clip
    456      * region is all 0s.  */
    457     rect.x = dstx;
    458     rect.y = dsty;
    459     rect.width = w;
    460     rect.height = h;
    461     (*pGC->ops->PolyFillRect) (pDraw, pGC, 1, &rect);
    462 
    463     /* Invert the tiling pixmap. This sets 0s for 1s and 1s for 0s, only
    464      * within the clipping region, the part outside is still all 0s */
    465     gcv[0].val = GXinvert;
    466     ChangeGC(NullClient, pGCT, GCFunction, gcv);
    467     ValidateGC((DrawablePtr) pPixmap, pGCT);
    468     (*pGCT->ops->CopyArea) ((DrawablePtr) pPixmap, (DrawablePtr) pPixmap,
    469                             pGCT, 0, 0, w + srcx, h, 0, 0);
    470 
    471     /* Swap foreground and background colors on the GC for the drawable.
    472      * Now when we fill the drawable, we will fill in the "Background"
    473      * values */
    474     oldfg = pGC->fgPixel;
    475     gcv[0].val = pGC->bgPixel;
    476     gcv[1].val = oldfg;
    477     gcv[2].ptr = pPixmap;
    478     ChangeGC(NullClient, pGC, GCForeground | GCBackground | GCStipple, gcv);
    479     ValidateGC(pDraw, pGC);
    480     /* PolyFillRect might have bashed the rectangle */
    481     rect.x = dstx;
    482     rect.y = dsty;
    483     rect.width = w;
    484     rect.height = h;
    485     (*pGC->ops->PolyFillRect) (pDraw, pGC, 1, &rect);
    486 
    487     /* Now put things back */
    488     if (pStipple)
    489         pStipple->refcnt--;
    490     gcv[0].val = oldfg;
    491     gcv[1].val = pGC->fgPixel;
    492     gcv[2].val = oldfill;
    493     gcv[3].ptr = pStipple;
    494     gcv[4].val = oldOrg.x;
    495     gcv[5].val = oldOrg.y;
    496     ChangeGC(NullClient, pGC,
    497              GCForeground | GCBackground | GCFillStyle | GCStipple |
    498              GCTileStipXOrigin | GCTileStipYOrigin, gcv);
    499 
    500     ValidateGC(pDraw, pGC);
    501     /* put what we hope is a smaller clip region back in the scratch gc */
    502     (*pGCT->funcs->ChangeClip) (pGCT, CT_NONE, NULL, 0);
    503     FreeScratchGC(pGCT);
    504     (*pDraw->pScreen->DestroyPixmap) (pPixmap);
    505 
    506 }
    507 
    508 /* MICOPYPLANE -- public entry for the CopyPlane request.
    509  * strategy:
    510  * First build up a bitmap out of the bits requested
    511  * build a source clip
    512  * Use the bitmap we've built up as a Stipple for the destination
    513  */
    514 _X_COLD RegionPtr
    515 miCopyPlane(DrawablePtr pSrcDrawable,
    516             DrawablePtr pDstDrawable,
    517             GCPtr pGC,
    518             int srcx,
    519             int srcy,
    520             int width, int height, int dstx, int dsty, unsigned long bitPlane)
    521 {
    522     MiBits *ptile;
    523     BoxRec box;
    524     RegionPtr prgnSrc, prgnExposed;
    525 
    526     /* incorporate the source clip */
    527 
    528     box.x1 = srcx + pSrcDrawable->x;
    529     box.y1 = srcy + pSrcDrawable->y;
    530     box.x2 = box.x1 + width;
    531     box.y2 = box.y1 + height;
    532     /* clip to visible drawable */
    533     if (box.x1 < pSrcDrawable->x)
    534         box.x1 = pSrcDrawable->x;
    535     if (box.y1 < pSrcDrawable->y)
    536         box.y1 = pSrcDrawable->y;
    537     if (box.x2 > pSrcDrawable->x + (int) pSrcDrawable->width)
    538         box.x2 = pSrcDrawable->x + (int) pSrcDrawable->width;
    539     if (box.y2 > pSrcDrawable->y + (int) pSrcDrawable->height)
    540         box.y2 = pSrcDrawable->y + (int) pSrcDrawable->height;
    541     if (box.x1 > box.x2)
    542         box.x2 = box.x1;
    543     if (box.y1 > box.y2)
    544         box.y2 = box.y1;
    545     prgnSrc = RegionCreate(&box, 1);
    546 
    547     if (pSrcDrawable->type != DRAWABLE_PIXMAP) {
    548         /* clip to visible drawable */
    549 
    550         if (pGC->subWindowMode == IncludeInferiors) {
    551             RegionPtr clipList = NotClippedByChildren((WindowPtr) pSrcDrawable);
    552 
    553             RegionIntersect(prgnSrc, prgnSrc, clipList);
    554             RegionDestroy(clipList);
    555         }
    556         else
    557             RegionIntersect(prgnSrc, prgnSrc,
    558                             &((WindowPtr) pSrcDrawable)->clipList);
    559     }
    560 
    561     box = *RegionExtents(prgnSrc);
    562     RegionTranslate(prgnSrc, -box.x1, -box.y1);
    563 
    564     if ((box.x2 > box.x1) && (box.y2 > box.y1)) {
    565         /* minimize the size of the data extracted */
    566         /* note that we convert the plane mask bitPlane into a plane number */
    567         box.x1 -= pSrcDrawable->x;
    568         box.x2 -= pSrcDrawable->x;
    569         box.y1 -= pSrcDrawable->y;
    570         box.y2 -= pSrcDrawable->y;
    571         ptile = miGetPlane(pSrcDrawable, ffs(bitPlane) - 1,
    572                            box.x1, box.y1,
    573                            box.x2 - box.x1, box.y2 - box.y1, (MiBits *) NULL);
    574         if (ptile) {
    575             miOpqStipDrawable(pDstDrawable, pGC, prgnSrc, ptile, 0,
    576                               box.x2 - box.x1, box.y2 - box.y1,
    577                               dstx + box.x1 - srcx, dsty + box.y1 - srcy);
    578             free(ptile);
    579         }
    580     }
    581     prgnExposed = miHandleExposures(pSrcDrawable, pDstDrawable, pGC, srcx, srcy,
    582                                     width, height, dstx, dsty);
    583     RegionDestroy(prgnSrc);
    584     return prgnExposed;
    585 }
    586 
    587 /* MIGETIMAGE -- public entry for the GetImage Request
    588  * We're getting the image into a memory buffer. While we have to use GetSpans
    589  * to read a line from the device (since we don't know what that looks like),
    590  * we can just write into the destination buffer
    591  *
    592  * two different strategies are used, depending on whether we're getting the
    593  * image in Z format or XY format
    594  * Z format:
    595  * Line at a time, GetSpans a line into the destination buffer, then if the
    596  * planemask is not all ones, we do a SetSpans into a temporary buffer (to get
    597  * bits turned off) and then another GetSpans to get stuff back (because
    598  * pixmaps are opaque, and we are passed in the memory to write into).  This is
    599  * pretty ugly and slow but works.  Life is hard.
    600  * XY format:
    601  * get the single plane specified in planemask
    602  */
    603 _X_COLD void
    604 miGetImage(DrawablePtr pDraw, int sx, int sy, int w, int h,
    605            unsigned int format, unsigned long planeMask, char *pDst)
    606 {
    607     unsigned char depth;
    608     int i, linelength, width, srcx, srcy;
    609     DDXPointRec pt = { 0, 0 };
    610     PixmapPtr pPixmap = NULL;
    611     GCPtr pGC = NULL;
    612 
    613     depth = pDraw->depth;
    614     if (format == ZPixmap) {
    615         if ((((1LL << depth) - 1) & planeMask) != (1LL << depth) - 1) {
    616             ChangeGCVal gcv;
    617             xPoint xpt;
    618 
    619             pGC = GetScratchGC(depth, pDraw->pScreen);
    620             if (!pGC)
    621                 return;
    622             pPixmap = (*pDraw->pScreen->CreatePixmap)
    623                 (pDraw->pScreen, w, 1, depth, CREATE_PIXMAP_USAGE_SCRATCH);
    624             if (!pPixmap) {
    625                 FreeScratchGC(pGC);
    626                 return;
    627             }
    628             /*
    629              * Clear the pixmap before doing anything else
    630              */
    631             ValidateGC((DrawablePtr) pPixmap, pGC);
    632             xpt.x = xpt.y = 0;
    633             width = w;
    634             (*pGC->ops->FillSpans) ((DrawablePtr) pPixmap, pGC, 1, &xpt, &width,
    635                                     TRUE);
    636 
    637             /* alu is already GXCopy */
    638             gcv.val = (XID) planeMask;
    639             ChangeGC(NullClient, pGC, GCPlaneMask, &gcv);
    640             ValidateGC((DrawablePtr) pPixmap, pGC);
    641         }
    642 
    643         linelength = PixmapBytePad(w, depth);
    644         srcx = sx + pDraw->x;
    645         srcy = sy + pDraw->y;
    646         for (i = 0; i < h; i++) {
    647             pt.x = srcx;
    648             pt.y = srcy + i;
    649             width = w;
    650             (*pDraw->pScreen->GetSpans) (pDraw, w, &pt, &width, 1, pDst);
    651             if (pPixmap) {
    652                 pt.x = 0;
    653                 pt.y = 0;
    654                 width = w;
    655                 (*pGC->ops->SetSpans) ((DrawablePtr) pPixmap, pGC, pDst,
    656                                        &pt, &width, 1, TRUE);
    657                 (*pDraw->pScreen->GetSpans) ((DrawablePtr) pPixmap, w, &pt,
    658                                              &width, 1, pDst);
    659             }
    660             pDst += linelength;
    661         }
    662         if (pPixmap) {
    663             (*pGC->pScreen->DestroyPixmap) (pPixmap);
    664             FreeScratchGC(pGC);
    665         }
    666     }
    667     else {
    668         (void) miGetPlane(pDraw, ffs(planeMask) - 1, sx, sy, w, h,
    669                           (MiBits *) pDst);
    670     }
    671 }
    672 
    673 /* MIPUTIMAGE -- public entry for the PutImage request
    674  * Here we benefit from knowing the format of the bits pointed to by pImage,
    675  * even if we don't know how pDraw represents them.
    676  * Three different strategies are used depending on the format
    677  * XYBitmap Format:
    678  * 	we just use the Opaque Stipple helper function to cover the destination
    679  * 	Note that this covers all the planes of the drawable with the
    680  *	foreground color (masked with the GC planemask) where there are 1 bits
    681  *	and the background color (masked with the GC planemask) where there are
    682  *	0 bits
    683  * XYPixmap format:
    684  *	what we're called with is a series of XYBitmaps, but we only want
    685  *	each XYPixmap to update 1 plane, instead of updating all of them.
    686  * 	we set the foreground color to be all 1s and the background to all 0s
    687  *	then for each plane, we set the plane mask to only effect that one
    688  *	plane and recursive call ourself with the format set to XYBitmap
    689  *	(This clever idea courtesy of RGD.)
    690  * ZPixmap format:
    691  *	This part is simple, just call SetSpans
    692  */
    693 _X_COLD void
    694 miPutImage(DrawablePtr pDraw, GCPtr pGC, int depth,
    695            int x, int y, int w, int h, int leftPad, int format, char *pImage)
    696 {
    697     DDXPointPtr pptFirst, ppt;
    698     int *pwidthFirst, *pwidth;
    699     RegionPtr prgnSrc;
    700     BoxRec box;
    701     unsigned long oldFg, oldBg;
    702     ChangeGCVal gcv[3];
    703     unsigned long oldPlanemask;
    704     unsigned long i;
    705     long bytesPer;
    706 
    707     if (!w || !h)
    708         return;
    709     switch (format) {
    710     case XYBitmap:
    711 
    712         box.x1 = 0;
    713         box.y1 = 0;
    714         box.x2 = w;
    715         box.y2 = h;
    716         prgnSrc = RegionCreate(&box, 1);
    717 
    718         miOpqStipDrawable(pDraw, pGC, prgnSrc, (MiBits *) pImage,
    719                           leftPad, w, h, x, y);
    720         RegionDestroy(prgnSrc);
    721         break;
    722 
    723     case XYPixmap:
    724         depth = pGC->depth;
    725         oldPlanemask = pGC->planemask;
    726         oldFg = pGC->fgPixel;
    727         oldBg = pGC->bgPixel;
    728         gcv[0].val = (XID) ~0;
    729         gcv[1].val = (XID) 0;
    730         ChangeGC(NullClient, pGC, GCForeground | GCBackground, gcv);
    731         bytesPer = (long) h *BitmapBytePad(w + leftPad);
    732 
    733         for (i = (unsigned long) 1 << (depth - 1); i != 0; i >>= 1, pImage += bytesPer) {
    734             if (i & oldPlanemask) {
    735                 gcv[0].val = (XID) i;
    736                 ChangeGC(NullClient, pGC, GCPlaneMask, gcv);
    737                 ValidateGC(pDraw, pGC);
    738                 (*pGC->ops->PutImage) (pDraw, pGC, 1, x, y, w, h, leftPad,
    739                                        XYBitmap, (char *) pImage);
    740             }
    741         }
    742         gcv[0].val = (XID) oldPlanemask;
    743         gcv[1].val = (XID) oldFg;
    744         gcv[2].val = (XID) oldBg;
    745         ChangeGC(NullClient, pGC, GCPlaneMask | GCForeground | GCBackground,
    746                  gcv);
    747         ValidateGC(pDraw, pGC);
    748         break;
    749 
    750     case ZPixmap:
    751         ppt = pptFirst = xallocarray(h, sizeof(DDXPointRec));
    752         pwidth = pwidthFirst = xallocarray(h, sizeof(int));
    753         if (!pptFirst || !pwidthFirst) {
    754             free(pwidthFirst);
    755             free(pptFirst);
    756             return;
    757         }
    758         if (pGC->miTranslate) {
    759             x += pDraw->x;
    760             y += pDraw->y;
    761         }
    762 
    763         for (i = 0; i < h; i++) {
    764             ppt->x = x;
    765             ppt->y = y + i;
    766             ppt++;
    767             *pwidth++ = w;
    768         }
    769 
    770         (*pGC->ops->SetSpans) (pDraw, pGC, (char *) pImage, pptFirst,
    771                                pwidthFirst, h, TRUE);
    772         free(pwidthFirst);
    773         free(pptFirst);
    774         break;
    775     }
    776 }