xserver

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

micopy.c (9895B)


      1 /*
      2  * Copyright © 1998 Keith Packard
      3  *
      4  * Permission to use, copy, modify, distribute, and sell this software and its
      5  * documentation for any purpose is hereby granted without fee, provided that
      6  * the above copyright notice appear in all copies and that both that
      7  * copyright notice and this permission notice appear in supporting
      8  * documentation, and that the name of Keith Packard not be used in
      9  * advertising or publicity pertaining to distribution of the software without
     10  * specific, written prior permission.  Keith Packard makes no
     11  * representations about the suitability of this software for any purpose.  It
     12  * is provided "as is" without express or implied warranty.
     13  *
     14  * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
     15  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
     16  * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
     17  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
     18  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
     19  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
     20  * PERFORMANCE OF THIS SOFTWARE.
     21  */
     22 
     23 #ifdef HAVE_DIX_CONFIG_H
     24 #include <dix-config.h>
     25 #endif
     26 
     27 #include "mi.h"
     28 #include "scrnintstr.h"
     29 #include "gcstruct.h"
     30 #include "pixmap.h"
     31 #include "pixmapstr.h"
     32 #include "windowstr.h"
     33 
     34 void
     35 miCopyRegion(DrawablePtr pSrcDrawable,
     36              DrawablePtr pDstDrawable,
     37              GCPtr pGC,
     38              RegionPtr pDstRegion,
     39              int dx, int dy, miCopyProc copyProc, Pixel bitPlane, void *closure)
     40 {
     41     int careful;
     42     Bool reverse;
     43     Bool upsidedown;
     44     BoxPtr pbox;
     45     int nbox;
     46     BoxPtr pboxNew1, pboxNew2, pboxBase, pboxNext, pboxTmp;
     47 
     48     pbox = RegionRects(pDstRegion);
     49     nbox = RegionNumRects(pDstRegion);
     50 
     51     /* XXX we have to err on the side of safety when both are windows,
     52      * because we don't know if IncludeInferiors is being used.
     53      */
     54     careful = ((pSrcDrawable == pDstDrawable) ||
     55                ((pSrcDrawable->type == DRAWABLE_WINDOW) &&
     56                 (pDstDrawable->type == DRAWABLE_WINDOW)));
     57 
     58     pboxNew1 = NULL;
     59     pboxNew2 = NULL;
     60     if (careful && dy < 0) {
     61         upsidedown = TRUE;
     62 
     63         if (nbox > 1) {
     64             /* keep ordering in each band, reverse order of bands */
     65             pboxNew1 = xallocarray(nbox, sizeof(BoxRec));
     66             if (!pboxNew1)
     67                 return;
     68             pboxBase = pboxNext = pbox + nbox - 1;
     69             while (pboxBase >= pbox) {
     70                 while ((pboxNext >= pbox) && (pboxBase->y1 == pboxNext->y1))
     71                     pboxNext--;
     72                 pboxTmp = pboxNext + 1;
     73                 while (pboxTmp <= pboxBase) {
     74                     *pboxNew1++ = *pboxTmp++;
     75                 }
     76                 pboxBase = pboxNext;
     77             }
     78             pboxNew1 -= nbox;
     79             pbox = pboxNew1;
     80         }
     81     }
     82     else {
     83         /* walk source top to bottom */
     84         upsidedown = FALSE;
     85     }
     86 
     87     if (careful && dx < 0) {
     88         /* walk source right to left */
     89         if (dy <= 0)
     90             reverse = TRUE;
     91         else
     92             reverse = FALSE;
     93 
     94         if (nbox > 1) {
     95             /* reverse order of rects in each band */
     96             pboxNew2 = xallocarray(nbox, sizeof(BoxRec));
     97             if (!pboxNew2) {
     98                 free(pboxNew1);
     99                 return;
    100             }
    101             pboxBase = pboxNext = pbox;
    102             while (pboxBase < pbox + nbox) {
    103                 while ((pboxNext < pbox + nbox) &&
    104                        (pboxNext->y1 == pboxBase->y1))
    105                     pboxNext++;
    106                 pboxTmp = pboxNext;
    107                 while (pboxTmp != pboxBase) {
    108                     *pboxNew2++ = *--pboxTmp;
    109                 }
    110                 pboxBase = pboxNext;
    111             }
    112             pboxNew2 -= nbox;
    113             pbox = pboxNew2;
    114         }
    115     }
    116     else {
    117         /* walk source left to right */
    118         reverse = FALSE;
    119     }
    120 
    121     (*copyProc) (pSrcDrawable,
    122                  pDstDrawable,
    123                  pGC,
    124                  pbox, nbox, dx, dy, reverse, upsidedown, bitPlane, closure);
    125 
    126     free(pboxNew1);
    127     free(pboxNew2);
    128 }
    129 
    130 RegionPtr
    131 miDoCopy(DrawablePtr pSrcDrawable,
    132          DrawablePtr pDstDrawable,
    133          GCPtr pGC,
    134          int xIn,
    135          int yIn,
    136          int widthSrc,
    137          int heightSrc,
    138          int xOut, int yOut, miCopyProc copyProc, Pixel bitPlane, void *closure)
    139 {
    140     RegionPtr prgnSrcClip = NULL;       /* may be a new region, or just a copy */
    141     Bool freeSrcClip = FALSE;
    142     RegionPtr prgnExposed = NULL;
    143     RegionRec rgnDst;
    144     int dx;
    145     int dy;
    146     int numRects;
    147     int box_x1;
    148     int box_y1;
    149     int box_x2;
    150     int box_y2;
    151     Bool fastSrc = FALSE;       /* for fast clipping with pixmap source */
    152     Bool fastDst = FALSE;       /* for fast clipping with one rect dest */
    153     Bool fastExpose = FALSE;    /* for fast exposures with pixmap source */
    154 
    155     /* Short cut for unmapped windows */
    156 
    157     if (pDstDrawable->type == DRAWABLE_WINDOW &&
    158         !((WindowPtr) pDstDrawable)->realized) {
    159         return NULL;
    160     }
    161 
    162     (*pSrcDrawable->pScreen->SourceValidate) (pSrcDrawable, xIn, yIn,
    163                                               widthSrc, heightSrc,
    164                                               pGC->subWindowMode);
    165 
    166     /* Compute source clip region */
    167     if (pSrcDrawable->type == DRAWABLE_PIXMAP) {
    168         if ((pSrcDrawable == pDstDrawable) && (!pGC->clientClip))
    169             prgnSrcClip = miGetCompositeClip(pGC);
    170         else
    171             fastSrc = TRUE;
    172     }
    173     else {
    174         if (pGC->subWindowMode == IncludeInferiors) {
    175             /*
    176              * XFree86 DDX empties the border clip when the
    177              * VT is inactive, make sure the region isn't empty
    178              */
    179             if (!((WindowPtr) pSrcDrawable)->parent &&
    180                 RegionNotEmpty(&((WindowPtr) pSrcDrawable)->borderClip)) {
    181                 /*
    182                  * special case bitblt from root window in
    183                  * IncludeInferiors mode; just like from a pixmap
    184                  */
    185                 fastSrc = TRUE;
    186             }
    187             else if ((pSrcDrawable == pDstDrawable) && (!pGC->clientClip)) {
    188                 prgnSrcClip = miGetCompositeClip(pGC);
    189             }
    190             else {
    191                 prgnSrcClip = NotClippedByChildren((WindowPtr) pSrcDrawable);
    192                 freeSrcClip = TRUE;
    193             }
    194         }
    195         else {
    196             prgnSrcClip = &((WindowPtr) pSrcDrawable)->clipList;
    197         }
    198     }
    199 
    200     xIn += pSrcDrawable->x;
    201     yIn += pSrcDrawable->y;
    202 
    203     xOut += pDstDrawable->x;
    204     yOut += pDstDrawable->y;
    205 
    206     box_x1 = xIn;
    207     box_y1 = yIn;
    208     box_x2 = xIn + widthSrc;
    209     box_y2 = yIn + heightSrc;
    210 
    211     dx = xIn - xOut;
    212     dy = yIn - yOut;
    213 
    214     /* Don't create a source region if we are doing a fast clip */
    215     if (fastSrc) {
    216         RegionPtr cclip;
    217 
    218         fastExpose = TRUE;
    219         /*
    220          * clip the source; if regions extend beyond the source size,
    221          * make sure exposure events get sent
    222          */
    223         if (box_x1 < pSrcDrawable->x) {
    224             box_x1 = pSrcDrawable->x;
    225             fastExpose = FALSE;
    226         }
    227         if (box_y1 < pSrcDrawable->y) {
    228             box_y1 = pSrcDrawable->y;
    229             fastExpose = FALSE;
    230         }
    231         if (box_x2 > pSrcDrawable->x + (int) pSrcDrawable->width) {
    232             box_x2 = pSrcDrawable->x + (int) pSrcDrawable->width;
    233             fastExpose = FALSE;
    234         }
    235         if (box_y2 > pSrcDrawable->y + (int) pSrcDrawable->height) {
    236             box_y2 = pSrcDrawable->y + (int) pSrcDrawable->height;
    237             fastExpose = FALSE;
    238         }
    239 
    240         /* Translate and clip the dst to the destination composite clip */
    241         box_x1 -= dx;
    242         box_x2 -= dx;
    243         box_y1 -= dy;
    244         box_y2 -= dy;
    245 
    246         /* If the destination composite clip is one rectangle we can
    247            do the clip directly.  Otherwise we have to create a full
    248            blown region and call intersect */
    249 
    250         cclip = miGetCompositeClip(pGC);
    251         if (RegionNumRects(cclip) == 1) {
    252             BoxPtr pBox = RegionRects(cclip);
    253 
    254             if (box_x1 < pBox->x1)
    255                 box_x1 = pBox->x1;
    256             if (box_x2 > pBox->x2)
    257                 box_x2 = pBox->x2;
    258             if (box_y1 < pBox->y1)
    259                 box_y1 = pBox->y1;
    260             if (box_y2 > pBox->y2)
    261                 box_y2 = pBox->y2;
    262             fastDst = TRUE;
    263         }
    264     }
    265 
    266     /* Check to see if the region is empty */
    267     if (box_x1 >= box_x2 || box_y1 >= box_y2) {
    268         RegionNull(&rgnDst);
    269     }
    270     else {
    271         BoxRec box;
    272 
    273         box.x1 = box_x1;
    274         box.y1 = box_y1;
    275         box.x2 = box_x2;
    276         box.y2 = box_y2;
    277         RegionInit(&rgnDst, &box, 1);
    278     }
    279 
    280     /* Clip against complex source if needed */
    281     if (!fastSrc) {
    282         RegionIntersect(&rgnDst, &rgnDst, prgnSrcClip);
    283         RegionTranslate(&rgnDst, -dx, -dy);
    284     }
    285 
    286     /* Clip against complex dest if needed */
    287     if (!fastDst) {
    288         RegionIntersect(&rgnDst, &rgnDst, miGetCompositeClip(pGC));
    289     }
    290 
    291     /* Do bit blitting */
    292     numRects = RegionNumRects(&rgnDst);
    293     if (numRects && widthSrc && heightSrc)
    294         miCopyRegion(pSrcDrawable, pDstDrawable, pGC,
    295                      &rgnDst, dx, dy, copyProc, bitPlane, closure);
    296 
    297     /* Pixmap sources generate a NoExposed (we return NULL to do this) */
    298     if (!fastExpose && pGC->fExpose)
    299         prgnExposed = miHandleExposures(pSrcDrawable, pDstDrawable, pGC,
    300                                         xIn - pSrcDrawable->x,
    301                                         yIn - pSrcDrawable->y,
    302                                         widthSrc, heightSrc,
    303                                         xOut - pDstDrawable->x,
    304                                         yOut - pDstDrawable->y);
    305     RegionUninit(&rgnDst);
    306     if (freeSrcClip)
    307         RegionDestroy(prgnSrcClip);
    308     return prgnExposed;
    309 }