xserver

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

panoramiX.c (38706B)


      1 /*****************************************************************
      2 Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts.
      3 Permission is hereby granted, free of charge, to any person obtaining a copy
      4 of this software and associated documentation files (the "Software"), to deal
      5 in the Software without restriction, including without limitation the rights
      6 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      7 copies of the Software.
      8 
      9 The above copyright notice and this permission notice shall be included in
     10 all copies or substantial portions of the Software.
     11 
     12 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     13 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     14 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     15 DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING,
     16 BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY,
     17 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
     18 IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     19 
     20 Except as contained in this notice, the name of Digital Equipment Corporation
     21 shall not be used in advertising or otherwise to promote the sale, use or other
     22 dealings in this Software without prior written authorization from Digital
     23 Equipment Corporation.
     24 ******************************************************************/
     25 
     26 #ifdef HAVE_DIX_CONFIG_H
     27 #include <dix-config.h>
     28 #endif
     29 
     30 #ifdef HAVE_DMX_CONFIG_H
     31 #include <dmx-config.h>
     32 #endif
     33 
     34 #include <stdio.h>
     35 #include <X11/X.h>
     36 #include <X11/Xproto.h>
     37 #include <X11/Xarch.h>
     38 #include "misc.h"
     39 #include "cursor.h"
     40 #include "cursorstr.h"
     41 #include "extnsionst.h"
     42 #include "dixstruct.h"
     43 #include "gc.h"
     44 #include "gcstruct.h"
     45 #include "scrnintstr.h"
     46 #include "window.h"
     47 #include "windowstr.h"
     48 #include "pixmapstr.h"
     49 #include "panoramiX.h"
     50 #include <X11/extensions/panoramiXproto.h>
     51 #include "panoramiXsrv.h"
     52 #include "globals.h"
     53 #include "servermd.h"
     54 #include "resource.h"
     55 #include "picturestr.h"
     56 #include "xfixesint.h"
     57 #include "damageextint.h"
     58 #ifdef COMPOSITE
     59 #include "compint.h"
     60 #endif
     61 #include "extinit.h"
     62 #include "protocol-versions.h"
     63 
     64 #ifdef GLXPROXY
     65 extern VisualPtr glxMatchVisual(ScreenPtr pScreen,
     66                                 VisualPtr pVisual, ScreenPtr pMatchScreen);
     67 #endif
     68 
     69 /*
     70  *	PanoramiX data declarations
     71  */
     72 
     73 int PanoramiXPixWidth = 0;
     74 int PanoramiXPixHeight = 0;
     75 int PanoramiXNumScreens = 0;
     76 
     77 _X_EXPORT RegionRec PanoramiXScreenRegion = { {0, 0, 0, 0}, NULL };
     78 
     79 static int PanoramiXNumDepths;
     80 static DepthPtr PanoramiXDepths;
     81 static int PanoramiXNumVisuals;
     82 static VisualPtr PanoramiXVisuals;
     83 
     84 RESTYPE XRC_DRAWABLE;
     85 RESTYPE XRT_WINDOW;
     86 RESTYPE XRT_PIXMAP;
     87 RESTYPE XRT_GC;
     88 RESTYPE XRT_COLORMAP;
     89 
     90 static Bool VisualsEqual(VisualPtr, ScreenPtr, VisualPtr);
     91 XineramaVisualsEqualProcPtr XineramaVisualsEqualPtr = &VisualsEqual;
     92 
     93 /*
     94  *	Function prototypes
     95  */
     96 
     97 static int panoramiXGeneration;
     98 static int ProcPanoramiXDispatch(ClientPtr client);
     99 
    100 static void PanoramiXResetProc(ExtensionEntry *);
    101 
    102 /*
    103  *	External references for functions and data variables
    104  */
    105 
    106 #include "panoramiXh.h"
    107 
    108 int (*SavedProcVector[256]) (ClientPtr client) = {
    109 NULL,};
    110 
    111 static DevPrivateKeyRec PanoramiXGCKeyRec;
    112 
    113 #define PanoramiXGCKey (&PanoramiXGCKeyRec)
    114 static DevPrivateKeyRec PanoramiXScreenKeyRec;
    115 
    116 #define PanoramiXScreenKey (&PanoramiXScreenKeyRec)
    117 
    118 typedef struct {
    119     DDXPointRec clipOrg;
    120     DDXPointRec patOrg;
    121     const GCFuncs *wrapFuncs;
    122 } PanoramiXGCRec, *PanoramiXGCPtr;
    123 
    124 typedef struct {
    125     CreateGCProcPtr CreateGC;
    126     CloseScreenProcPtr CloseScreen;
    127 } PanoramiXScreenRec, *PanoramiXScreenPtr;
    128 
    129 static void XineramaValidateGC(GCPtr, unsigned long, DrawablePtr);
    130 static void XineramaChangeGC(GCPtr, unsigned long);
    131 static void XineramaCopyGC(GCPtr, unsigned long, GCPtr);
    132 static void XineramaDestroyGC(GCPtr);
    133 static void XineramaChangeClip(GCPtr, int, void *, int);
    134 static void XineramaDestroyClip(GCPtr);
    135 static void XineramaCopyClip(GCPtr, GCPtr);
    136 
    137 static const GCFuncs XineramaGCFuncs = {
    138     XineramaValidateGC, XineramaChangeGC, XineramaCopyGC, XineramaDestroyGC,
    139     XineramaChangeClip, XineramaDestroyClip, XineramaCopyClip
    140 };
    141 
    142 #define Xinerama_GC_FUNC_PROLOGUE(pGC)\
    143     PanoramiXGCPtr  pGCPriv = (PanoramiXGCPtr) \
    144 	dixLookupPrivate(&(pGC)->devPrivates, PanoramiXGCKey); \
    145     (pGC)->funcs = pGCPriv->wrapFuncs;
    146 
    147 #define Xinerama_GC_FUNC_EPILOGUE(pGC)\
    148     pGCPriv->wrapFuncs = (pGC)->funcs;\
    149     (pGC)->funcs = &XineramaGCFuncs;
    150 
    151 static Bool
    152 XineramaCloseScreen(ScreenPtr pScreen)
    153 {
    154     PanoramiXScreenPtr pScreenPriv = (PanoramiXScreenPtr)
    155         dixLookupPrivate(&pScreen->devPrivates, PanoramiXScreenKey);
    156 
    157     pScreen->CloseScreen = pScreenPriv->CloseScreen;
    158     pScreen->CreateGC = pScreenPriv->CreateGC;
    159 
    160     if (pScreen->myNum == 0)
    161         RegionUninit(&PanoramiXScreenRegion);
    162 
    163     free(pScreenPriv);
    164 
    165     return (*pScreen->CloseScreen) (pScreen);
    166 }
    167 
    168 static Bool
    169 XineramaCreateGC(GCPtr pGC)
    170 {
    171     ScreenPtr pScreen = pGC->pScreen;
    172     PanoramiXScreenPtr pScreenPriv = (PanoramiXScreenPtr)
    173         dixLookupPrivate(&pScreen->devPrivates, PanoramiXScreenKey);
    174     Bool ret;
    175 
    176     pScreen->CreateGC = pScreenPriv->CreateGC;
    177     if ((ret = (*pScreen->CreateGC) (pGC))) {
    178         PanoramiXGCPtr pGCPriv = (PanoramiXGCPtr)
    179             dixLookupPrivate(&pGC->devPrivates, PanoramiXGCKey);
    180 
    181         pGCPriv->wrapFuncs = pGC->funcs;
    182         pGC->funcs = &XineramaGCFuncs;
    183 
    184         pGCPriv->clipOrg.x = pGC->clipOrg.x;
    185         pGCPriv->clipOrg.y = pGC->clipOrg.y;
    186         pGCPriv->patOrg.x = pGC->patOrg.x;
    187         pGCPriv->patOrg.y = pGC->patOrg.y;
    188     }
    189     pScreen->CreateGC = XineramaCreateGC;
    190 
    191     return ret;
    192 }
    193 
    194 static void
    195 XineramaValidateGC(GCPtr pGC, unsigned long changes, DrawablePtr pDraw)
    196 {
    197     Xinerama_GC_FUNC_PROLOGUE(pGC);
    198 
    199     if ((pDraw->type == DRAWABLE_WINDOW) && !(((WindowPtr) pDraw)->parent)) {
    200         /* the root window */
    201         int x_off = pGC->pScreen->x;
    202         int y_off = pGC->pScreen->y;
    203         int new_val;
    204 
    205         new_val = pGCPriv->clipOrg.x - x_off;
    206         if (pGC->clipOrg.x != new_val) {
    207             pGC->clipOrg.x = new_val;
    208             changes |= GCClipXOrigin;
    209         }
    210         new_val = pGCPriv->clipOrg.y - y_off;
    211         if (pGC->clipOrg.y != new_val) {
    212             pGC->clipOrg.y = new_val;
    213             changes |= GCClipYOrigin;
    214         }
    215         new_val = pGCPriv->patOrg.x - x_off;
    216         if (pGC->patOrg.x != new_val) {
    217             pGC->patOrg.x = new_val;
    218             changes |= GCTileStipXOrigin;
    219         }
    220         new_val = pGCPriv->patOrg.y - y_off;
    221         if (pGC->patOrg.y != new_val) {
    222             pGC->patOrg.y = new_val;
    223             changes |= GCTileStipYOrigin;
    224         }
    225     }
    226     else {
    227         if (pGC->clipOrg.x != pGCPriv->clipOrg.x) {
    228             pGC->clipOrg.x = pGCPriv->clipOrg.x;
    229             changes |= GCClipXOrigin;
    230         }
    231         if (pGC->clipOrg.y != pGCPriv->clipOrg.y) {
    232             pGC->clipOrg.y = pGCPriv->clipOrg.y;
    233             changes |= GCClipYOrigin;
    234         }
    235         if (pGC->patOrg.x != pGCPriv->patOrg.x) {
    236             pGC->patOrg.x = pGCPriv->patOrg.x;
    237             changes |= GCTileStipXOrigin;
    238         }
    239         if (pGC->patOrg.y != pGCPriv->patOrg.y) {
    240             pGC->patOrg.y = pGCPriv->patOrg.y;
    241             changes |= GCTileStipYOrigin;
    242         }
    243     }
    244 
    245     (*pGC->funcs->ValidateGC) (pGC, changes, pDraw);
    246     Xinerama_GC_FUNC_EPILOGUE(pGC);
    247 }
    248 
    249 static void
    250 XineramaDestroyGC(GCPtr pGC)
    251 {
    252     Xinerama_GC_FUNC_PROLOGUE(pGC);
    253     (*pGC->funcs->DestroyGC) (pGC);
    254     Xinerama_GC_FUNC_EPILOGUE(pGC);
    255 }
    256 
    257 static void
    258 XineramaChangeGC(GCPtr pGC, unsigned long mask)
    259 {
    260     Xinerama_GC_FUNC_PROLOGUE(pGC);
    261 
    262     if (mask & GCTileStipXOrigin)
    263         pGCPriv->patOrg.x = pGC->patOrg.x;
    264     if (mask & GCTileStipYOrigin)
    265         pGCPriv->patOrg.y = pGC->patOrg.y;
    266     if (mask & GCClipXOrigin)
    267         pGCPriv->clipOrg.x = pGC->clipOrg.x;
    268     if (mask & GCClipYOrigin)
    269         pGCPriv->clipOrg.y = pGC->clipOrg.y;
    270 
    271     (*pGC->funcs->ChangeGC) (pGC, mask);
    272     Xinerama_GC_FUNC_EPILOGUE(pGC);
    273 }
    274 
    275 static void
    276 XineramaCopyGC(GCPtr pGCSrc, unsigned long mask, GCPtr pGCDst)
    277 {
    278     PanoramiXGCPtr pSrcPriv = (PanoramiXGCPtr)
    279         dixLookupPrivate(&pGCSrc->devPrivates, PanoramiXGCKey);
    280 
    281     Xinerama_GC_FUNC_PROLOGUE(pGCDst);
    282 
    283     if (mask & GCTileStipXOrigin)
    284         pGCPriv->patOrg.x = pSrcPriv->patOrg.x;
    285     if (mask & GCTileStipYOrigin)
    286         pGCPriv->patOrg.y = pSrcPriv->patOrg.y;
    287     if (mask & GCClipXOrigin)
    288         pGCPriv->clipOrg.x = pSrcPriv->clipOrg.x;
    289     if (mask & GCClipYOrigin)
    290         pGCPriv->clipOrg.y = pSrcPriv->clipOrg.y;
    291 
    292     (*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst);
    293     Xinerama_GC_FUNC_EPILOGUE(pGCDst);
    294 }
    295 
    296 static void
    297 XineramaChangeClip(GCPtr pGC, int type, void *pvalue, int nrects)
    298 {
    299     Xinerama_GC_FUNC_PROLOGUE(pGC);
    300     (*pGC->funcs->ChangeClip) (pGC, type, pvalue, nrects);
    301     Xinerama_GC_FUNC_EPILOGUE(pGC);
    302 }
    303 
    304 static void
    305 XineramaCopyClip(GCPtr pgcDst, GCPtr pgcSrc)
    306 {
    307     Xinerama_GC_FUNC_PROLOGUE(pgcDst);
    308     (*pgcDst->funcs->CopyClip) (pgcDst, pgcSrc);
    309     Xinerama_GC_FUNC_EPILOGUE(pgcDst);
    310 }
    311 
    312 static void
    313 XineramaDestroyClip(GCPtr pGC)
    314 {
    315     Xinerama_GC_FUNC_PROLOGUE(pGC);
    316     (*pGC->funcs->DestroyClip) (pGC);
    317     Xinerama_GC_FUNC_EPILOGUE(pGC);
    318 }
    319 
    320 int
    321 XineramaDeleteResource(void *data, XID id)
    322 {
    323     free(data);
    324     return 1;
    325 }
    326 
    327 typedef struct {
    328     int screen;
    329     int id;
    330 } PanoramiXSearchData;
    331 
    332 static Bool
    333 XineramaFindIDByScrnum(void *resource, XID id, void *privdata)
    334 {
    335     PanoramiXRes *res = (PanoramiXRes *) resource;
    336     PanoramiXSearchData *data = (PanoramiXSearchData *) privdata;
    337 
    338     return res->info[data->screen].id == data->id;
    339 }
    340 
    341 PanoramiXRes *
    342 PanoramiXFindIDByScrnum(RESTYPE type, XID id, int screen)
    343 {
    344     PanoramiXSearchData data;
    345     void *val;
    346 
    347     if (!screen) {
    348         dixLookupResourceByType(&val, id, type, serverClient, DixReadAccess);
    349         return val;
    350     }
    351 
    352     data.screen = screen;
    353     data.id = id;
    354 
    355     return LookupClientResourceComplex(clients[CLIENT_ID(id)], type,
    356                                        XineramaFindIDByScrnum, &data);
    357 }
    358 
    359 typedef struct _connect_callback_list {
    360     void (*func) (void);
    361     struct _connect_callback_list *next;
    362 } XineramaConnectionCallbackList;
    363 
    364 static XineramaConnectionCallbackList *ConnectionCallbackList = NULL;
    365 
    366 Bool
    367 XineramaRegisterConnectionBlockCallback(void (*func) (void))
    368 {
    369     XineramaConnectionCallbackList *newlist;
    370 
    371     if (!(newlist = malloc(sizeof(XineramaConnectionCallbackList))))
    372         return FALSE;
    373 
    374     newlist->next = ConnectionCallbackList;
    375     newlist->func = func;
    376     ConnectionCallbackList = newlist;
    377 
    378     return TRUE;
    379 }
    380 
    381 static void
    382 XineramaInitData(void)
    383 {
    384     int i, w, h;
    385 
    386     RegionNull(&PanoramiXScreenRegion);
    387     FOR_NSCREENS(i) {
    388         BoxRec TheBox;
    389         RegionRec ScreenRegion;
    390 
    391         ScreenPtr pScreen = screenInfo.screens[i];
    392 
    393         TheBox.x1 = pScreen->x;
    394         TheBox.x2 = TheBox.x1 + pScreen->width;
    395         TheBox.y1 = pScreen->y;
    396         TheBox.y2 = TheBox.y1 + pScreen->height;
    397 
    398         RegionInit(&ScreenRegion, &TheBox, 1);
    399         RegionUnion(&PanoramiXScreenRegion, &PanoramiXScreenRegion,
    400                     &ScreenRegion);
    401         RegionUninit(&ScreenRegion);
    402     }
    403 
    404     PanoramiXPixWidth = screenInfo.screens[0]->x + screenInfo.screens[0]->width;
    405     PanoramiXPixHeight =
    406         screenInfo.screens[0]->y + screenInfo.screens[0]->height;
    407 
    408     FOR_NSCREENS_FORWARD_SKIP(i) {
    409         ScreenPtr pScreen = screenInfo.screens[i];
    410 
    411         w = pScreen->x + pScreen->width;
    412         h = pScreen->y + pScreen->height;
    413 
    414         if (PanoramiXPixWidth < w)
    415             PanoramiXPixWidth = w;
    416         if (PanoramiXPixHeight < h)
    417             PanoramiXPixHeight = h;
    418     }
    419 }
    420 
    421 void
    422 XineramaReinitData(void)
    423 {
    424     RegionUninit(&PanoramiXScreenRegion);
    425     XineramaInitData();
    426 }
    427 
    428 /*
    429  *	PanoramiXExtensionInit():
    430  *		Called from InitExtensions in main().
    431  *		Register PanoramiXeen Extension
    432  *		Initialize global variables.
    433  */
    434 
    435 void
    436 PanoramiXExtensionInit(void)
    437 {
    438     int i;
    439     Bool success = FALSE;
    440     ExtensionEntry *extEntry;
    441     ScreenPtr pScreen = screenInfo.screens[0];
    442     PanoramiXScreenPtr pScreenPriv;
    443 
    444     if (noPanoramiXExtension)
    445         return;
    446 
    447     if (!dixRegisterPrivateKey(&PanoramiXScreenKeyRec, PRIVATE_SCREEN, 0)) {
    448         noPanoramiXExtension = TRUE;
    449         return;
    450     }
    451 
    452     if (!dixRegisterPrivateKey
    453         (&PanoramiXGCKeyRec, PRIVATE_GC, sizeof(PanoramiXGCRec))) {
    454         noPanoramiXExtension = TRUE;
    455         return;
    456     }
    457 
    458     PanoramiXNumScreens = screenInfo.numScreens;
    459     if (PanoramiXNumScreens == 1) {     /* Only 1 screen        */
    460         noPanoramiXExtension = TRUE;
    461         return;
    462     }
    463 
    464     while (panoramiXGeneration != serverGeneration) {
    465         extEntry = AddExtension(PANORAMIX_PROTOCOL_NAME, 0, 0,
    466                                 ProcPanoramiXDispatch,
    467                                 SProcPanoramiXDispatch, PanoramiXResetProc,
    468                                 StandardMinorOpcode);
    469         if (!extEntry)
    470             break;
    471 
    472         /*
    473          *      First make sure all the basic allocations succeed.  If not,
    474          *      run in non-PanoramiXeen mode.
    475          */
    476 
    477         FOR_NSCREENS(i) {
    478             pScreen = screenInfo.screens[i];
    479             pScreenPriv = malloc(sizeof(PanoramiXScreenRec));
    480             dixSetPrivate(&pScreen->devPrivates, PanoramiXScreenKey,
    481                           pScreenPriv);
    482             if (!pScreenPriv) {
    483                 noPanoramiXExtension = TRUE;
    484                 return;
    485             }
    486 
    487             pScreenPriv->CreateGC = pScreen->CreateGC;
    488             pScreenPriv->CloseScreen = pScreen->CloseScreen;
    489 
    490             pScreen->CreateGC = XineramaCreateGC;
    491             pScreen->CloseScreen = XineramaCloseScreen;
    492         }
    493 
    494         XRC_DRAWABLE = CreateNewResourceClass();
    495         XRT_WINDOW = CreateNewResourceType(XineramaDeleteResource,
    496                                            "XineramaWindow");
    497         if (XRT_WINDOW)
    498             XRT_WINDOW |= XRC_DRAWABLE;
    499         XRT_PIXMAP = CreateNewResourceType(XineramaDeleteResource,
    500                                            "XineramaPixmap");
    501         if (XRT_PIXMAP)
    502             XRT_PIXMAP |= XRC_DRAWABLE;
    503         XRT_GC = CreateNewResourceType(XineramaDeleteResource, "XineramaGC");
    504         XRT_COLORMAP = CreateNewResourceType(XineramaDeleteResource,
    505                                              "XineramaColormap");
    506 
    507         if (XRT_WINDOW && XRT_PIXMAP && XRT_GC && XRT_COLORMAP) {
    508             panoramiXGeneration = serverGeneration;
    509             success = TRUE;
    510         }
    511         SetResourceTypeErrorValue(XRT_WINDOW, BadWindow);
    512         SetResourceTypeErrorValue(XRT_PIXMAP, BadPixmap);
    513         SetResourceTypeErrorValue(XRT_GC, BadGC);
    514         SetResourceTypeErrorValue(XRT_COLORMAP, BadColor);
    515     }
    516 
    517     if (!success) {
    518         noPanoramiXExtension = TRUE;
    519         ErrorF(PANORAMIX_PROTOCOL_NAME " extension failed to initialize\n");
    520         return;
    521     }
    522 
    523     XineramaInitData();
    524 
    525     /*
    526      *  Put our processes into the ProcVector
    527      */
    528 
    529     for (i = 256; i--;)
    530         SavedProcVector[i] = ProcVector[i];
    531 
    532     ProcVector[X_CreateWindow] = PanoramiXCreateWindow;
    533     ProcVector[X_ChangeWindowAttributes] = PanoramiXChangeWindowAttributes;
    534     ProcVector[X_DestroyWindow] = PanoramiXDestroyWindow;
    535     ProcVector[X_DestroySubwindows] = PanoramiXDestroySubwindows;
    536     ProcVector[X_ChangeSaveSet] = PanoramiXChangeSaveSet;
    537     ProcVector[X_ReparentWindow] = PanoramiXReparentWindow;
    538     ProcVector[X_MapWindow] = PanoramiXMapWindow;
    539     ProcVector[X_MapSubwindows] = PanoramiXMapSubwindows;
    540     ProcVector[X_UnmapWindow] = PanoramiXUnmapWindow;
    541     ProcVector[X_UnmapSubwindows] = PanoramiXUnmapSubwindows;
    542     ProcVector[X_ConfigureWindow] = PanoramiXConfigureWindow;
    543     ProcVector[X_CirculateWindow] = PanoramiXCirculateWindow;
    544     ProcVector[X_GetGeometry] = PanoramiXGetGeometry;
    545     ProcVector[X_TranslateCoords] = PanoramiXTranslateCoords;
    546     ProcVector[X_CreatePixmap] = PanoramiXCreatePixmap;
    547     ProcVector[X_FreePixmap] = PanoramiXFreePixmap;
    548     ProcVector[X_CreateGC] = PanoramiXCreateGC;
    549     ProcVector[X_ChangeGC] = PanoramiXChangeGC;
    550     ProcVector[X_CopyGC] = PanoramiXCopyGC;
    551     ProcVector[X_SetDashes] = PanoramiXSetDashes;
    552     ProcVector[X_SetClipRectangles] = PanoramiXSetClipRectangles;
    553     ProcVector[X_FreeGC] = PanoramiXFreeGC;
    554     ProcVector[X_ClearArea] = PanoramiXClearToBackground;
    555     ProcVector[X_CopyArea] = PanoramiXCopyArea;
    556     ProcVector[X_CopyPlane] = PanoramiXCopyPlane;
    557     ProcVector[X_PolyPoint] = PanoramiXPolyPoint;
    558     ProcVector[X_PolyLine] = PanoramiXPolyLine;
    559     ProcVector[X_PolySegment] = PanoramiXPolySegment;
    560     ProcVector[X_PolyRectangle] = PanoramiXPolyRectangle;
    561     ProcVector[X_PolyArc] = PanoramiXPolyArc;
    562     ProcVector[X_FillPoly] = PanoramiXFillPoly;
    563     ProcVector[X_PolyFillRectangle] = PanoramiXPolyFillRectangle;
    564     ProcVector[X_PolyFillArc] = PanoramiXPolyFillArc;
    565     ProcVector[X_PutImage] = PanoramiXPutImage;
    566     ProcVector[X_GetImage] = PanoramiXGetImage;
    567     ProcVector[X_PolyText8] = PanoramiXPolyText8;
    568     ProcVector[X_PolyText16] = PanoramiXPolyText16;
    569     ProcVector[X_ImageText8] = PanoramiXImageText8;
    570     ProcVector[X_ImageText16] = PanoramiXImageText16;
    571     ProcVector[X_CreateColormap] = PanoramiXCreateColormap;
    572     ProcVector[X_FreeColormap] = PanoramiXFreeColormap;
    573     ProcVector[X_CopyColormapAndFree] = PanoramiXCopyColormapAndFree;
    574     ProcVector[X_InstallColormap] = PanoramiXInstallColormap;
    575     ProcVector[X_UninstallColormap] = PanoramiXUninstallColormap;
    576     ProcVector[X_AllocColor] = PanoramiXAllocColor;
    577     ProcVector[X_AllocNamedColor] = PanoramiXAllocNamedColor;
    578     ProcVector[X_AllocColorCells] = PanoramiXAllocColorCells;
    579     ProcVector[X_AllocColorPlanes] = PanoramiXAllocColorPlanes;
    580     ProcVector[X_FreeColors] = PanoramiXFreeColors;
    581     ProcVector[X_StoreColors] = PanoramiXStoreColors;
    582     ProcVector[X_StoreNamedColor] = PanoramiXStoreNamedColor;
    583 
    584     PanoramiXRenderInit();
    585     PanoramiXFixesInit();
    586     PanoramiXDamageInit();
    587 #ifdef COMPOSITE
    588     PanoramiXCompositeInit();
    589 #endif
    590 
    591 }
    592 
    593 Bool
    594 PanoramiXCreateConnectionBlock(void)
    595 {
    596     int i, j, length;
    597     Bool disable_backing_store = FALSE;
    598     int old_width, old_height;
    599     float width_mult, height_mult;
    600     xWindowRoot *root;
    601     xVisualType *visual;
    602     xDepth *depth;
    603     VisualPtr pVisual;
    604     ScreenPtr pScreen;
    605 
    606     /*
    607      *  Do normal CreateConnectionBlock but faking it for only one screen
    608      */
    609 
    610     if (!PanoramiXNumDepths) {
    611         ErrorF("Xinerama error: No common visuals\n");
    612         return FALSE;
    613     }
    614 
    615     for (i = 1; i < screenInfo.numScreens; i++) {
    616         pScreen = screenInfo.screens[i];
    617         if (pScreen->rootDepth != screenInfo.screens[0]->rootDepth) {
    618             ErrorF("Xinerama error: Root window depths differ\n");
    619             return FALSE;
    620         }
    621         if (pScreen->backingStoreSupport !=
    622             screenInfo.screens[0]->backingStoreSupport)
    623             disable_backing_store = TRUE;
    624     }
    625 
    626     if (disable_backing_store) {
    627         for (i = 0; i < screenInfo.numScreens; i++) {
    628             pScreen = screenInfo.screens[i];
    629             pScreen->backingStoreSupport = NotUseful;
    630         }
    631     }
    632 
    633     i = screenInfo.numScreens;
    634     screenInfo.numScreens = 1;
    635     if (!CreateConnectionBlock()) {
    636         screenInfo.numScreens = i;
    637         return FALSE;
    638     }
    639 
    640     screenInfo.numScreens = i;
    641 
    642     root = (xWindowRoot *) (ConnectionInfo + connBlockScreenStart);
    643     length = connBlockScreenStart + sizeof(xWindowRoot);
    644 
    645     /* overwrite the connection block */
    646     root->nDepths = PanoramiXNumDepths;
    647 
    648     for (i = 0; i < PanoramiXNumDepths; i++) {
    649         depth = (xDepth *) (ConnectionInfo + length);
    650         depth->depth = PanoramiXDepths[i].depth;
    651         depth->nVisuals = PanoramiXDepths[i].numVids;
    652         length += sizeof(xDepth);
    653         visual = (xVisualType *) (ConnectionInfo + length);
    654 
    655         for (j = 0; j < depth->nVisuals; j++, visual++) {
    656             visual->visualID = PanoramiXDepths[i].vids[j];
    657 
    658             for (pVisual = PanoramiXVisuals;
    659                  pVisual->vid != visual->visualID; pVisual++);
    660 
    661             visual->class = pVisual->class;
    662             visual->bitsPerRGB = pVisual->bitsPerRGBValue;
    663             visual->colormapEntries = pVisual->ColormapEntries;
    664             visual->redMask = pVisual->redMask;
    665             visual->greenMask = pVisual->greenMask;
    666             visual->blueMask = pVisual->blueMask;
    667         }
    668 
    669         length += (depth->nVisuals * sizeof(xVisualType));
    670     }
    671 
    672     connSetupPrefix.length = bytes_to_int32(length);
    673 
    674     for (i = 0; i < PanoramiXNumDepths; i++)
    675         free(PanoramiXDepths[i].vids);
    676     free(PanoramiXDepths);
    677     PanoramiXDepths = NULL;
    678 
    679     /*
    680      *  OK, change some dimensions so it looks as if it were one big screen
    681      */
    682 
    683     old_width = root->pixWidth;
    684     old_height = root->pixHeight;
    685 
    686     root->pixWidth = PanoramiXPixWidth;
    687     root->pixHeight = PanoramiXPixHeight;
    688     width_mult = (1.0 * root->pixWidth) / old_width;
    689     height_mult = (1.0 * root->pixHeight) / old_height;
    690     root->mmWidth *= width_mult;
    691     root->mmHeight *= height_mult;
    692 
    693     while (ConnectionCallbackList) {
    694         void *tmp;
    695 
    696         tmp = (void *) ConnectionCallbackList;
    697         (*ConnectionCallbackList->func) ();
    698         ConnectionCallbackList = ConnectionCallbackList->next;
    699         free(tmp);
    700     }
    701 
    702     return TRUE;
    703 }
    704 
    705 /*
    706  * This isn't just memcmp(), bitsPerRGBValue is skipped.  markv made that
    707  * change way back before xf86 4.0, but the comment for _why_ is a bit
    708  * opaque, so I'm not going to question it for now.
    709  *
    710  * This is probably better done as a screen hook so DBE/EVI/GLX can add
    711  * their own tests, and adding privates to VisualRec so they don't have to
    712  * do their own back-mapping.
    713  */
    714 static Bool
    715 VisualsEqual(VisualPtr a, ScreenPtr pScreenB, VisualPtr b)
    716 {
    717     return ((a->class == b->class) &&
    718             (a->ColormapEntries == b->ColormapEntries) &&
    719             (a->nplanes == b->nplanes) &&
    720             (a->redMask == b->redMask) &&
    721             (a->greenMask == b->greenMask) &&
    722             (a->blueMask == b->blueMask) &&
    723             (a->offsetRed == b->offsetRed) &&
    724             (a->offsetGreen == b->offsetGreen) &&
    725             (a->offsetBlue == b->offsetBlue));
    726 }
    727 
    728 static void
    729 PanoramiXMaybeAddDepth(DepthPtr pDepth)
    730 {
    731     ScreenPtr pScreen;
    732     int j, k;
    733     Bool found = FALSE;
    734 
    735     FOR_NSCREENS_FORWARD_SKIP(j) {
    736         pScreen = screenInfo.screens[j];
    737         for (k = 0; k < pScreen->numDepths; k++) {
    738             if (pScreen->allowedDepths[k].depth == pDepth->depth) {
    739                 found = TRUE;
    740                 break;
    741             }
    742         }
    743     }
    744 
    745     if (!found)
    746         return;
    747 
    748     j = PanoramiXNumDepths;
    749     PanoramiXNumDepths++;
    750     PanoramiXDepths = reallocarray(PanoramiXDepths,
    751                                    PanoramiXNumDepths, sizeof(DepthRec));
    752     PanoramiXDepths[j].depth = pDepth->depth;
    753     PanoramiXDepths[j].numVids = 0;
    754     PanoramiXDepths[j].vids = NULL;
    755 }
    756 
    757 static void
    758 PanoramiXMaybeAddVisual(VisualPtr pVisual)
    759 {
    760     ScreenPtr pScreen;
    761     int j, k;
    762     Bool found = FALSE;
    763 
    764     FOR_NSCREENS_FORWARD_SKIP(j) {
    765         pScreen = screenInfo.screens[j];
    766         found = FALSE;
    767 
    768         for (k = 0; k < pScreen->numVisuals; k++) {
    769             VisualPtr candidate = &pScreen->visuals[k];
    770 
    771             if ((*XineramaVisualsEqualPtr) (pVisual, pScreen, candidate)
    772 #ifdef GLXPROXY
    773                 && glxMatchVisual(screenInfo.screens[0], pVisual, pScreen)
    774 #endif
    775                 ) {
    776                 found = TRUE;
    777                 break;
    778             }
    779         }
    780 
    781         if (!found)
    782             return;
    783     }
    784 
    785     /* found a matching visual on all screens, add it to the subset list */
    786     j = PanoramiXNumVisuals;
    787     PanoramiXNumVisuals++;
    788     PanoramiXVisuals = reallocarray(PanoramiXVisuals,
    789                                     PanoramiXNumVisuals, sizeof(VisualRec));
    790 
    791     memcpy(&PanoramiXVisuals[j], pVisual, sizeof(VisualRec));
    792 
    793     for (k = 0; k < PanoramiXNumDepths; k++) {
    794         if (PanoramiXDepths[k].depth == pVisual->nplanes) {
    795             PanoramiXDepths[k].vids = reallocarray(PanoramiXDepths[k].vids,
    796                                                    PanoramiXDepths[k].numVids + 1,
    797                                                    sizeof(VisualID));
    798             PanoramiXDepths[k].vids[PanoramiXDepths[k].numVids] = pVisual->vid;
    799             PanoramiXDepths[k].numVids++;
    800             break;
    801         }
    802     }
    803 }
    804 
    805 extern void
    806 PanoramiXConsolidate(void)
    807 {
    808     int i;
    809     PanoramiXRes *root, *defmap, *saver;
    810     ScreenPtr pScreen = screenInfo.screens[0];
    811     DepthPtr pDepth = pScreen->allowedDepths;
    812     VisualPtr pVisual = pScreen->visuals;
    813 
    814     PanoramiXNumDepths = 0;
    815     PanoramiXNumVisuals = 0;
    816 
    817     for (i = 0; i < pScreen->numDepths; i++)
    818         PanoramiXMaybeAddDepth(pDepth++);
    819 
    820     for (i = 0; i < pScreen->numVisuals; i++)
    821         PanoramiXMaybeAddVisual(pVisual++);
    822 
    823     root = malloc(sizeof(PanoramiXRes));
    824     root->type = XRT_WINDOW;
    825     defmap = malloc(sizeof(PanoramiXRes));
    826     defmap->type = XRT_COLORMAP;
    827     saver = malloc(sizeof(PanoramiXRes));
    828     saver->type = XRT_WINDOW;
    829 
    830     FOR_NSCREENS(i) {
    831         ScreenPtr scr = screenInfo.screens[i];
    832 
    833         root->info[i].id = scr->root->drawable.id;
    834         root->u.win.class = InputOutput;
    835         root->u.win.root = TRUE;
    836         saver->info[i].id = scr->screensaver.wid;
    837         saver->u.win.class = InputOutput;
    838         saver->u.win.root = TRUE;
    839         defmap->info[i].id = scr->defColormap;
    840     }
    841 
    842     AddResource(root->info[0].id, XRT_WINDOW, root);
    843     AddResource(saver->info[0].id, XRT_WINDOW, saver);
    844     AddResource(defmap->info[0].id, XRT_COLORMAP, defmap);
    845 }
    846 
    847 VisualID
    848 PanoramiXTranslateVisualID(int screen, VisualID orig)
    849 {
    850     ScreenPtr pOtherScreen = screenInfo.screens[screen];
    851     VisualPtr pVisual = NULL;
    852     int i;
    853 
    854     for (i = 0; i < PanoramiXNumVisuals; i++) {
    855         if (orig == PanoramiXVisuals[i].vid) {
    856             pVisual = &PanoramiXVisuals[i];
    857             break;
    858         }
    859     }
    860 
    861     if (!pVisual)
    862         return 0;
    863 
    864     /* if screen is 0, orig is already the correct visual ID */
    865     if (screen == 0)
    866         return orig;
    867 
    868     /* found the original, now translate it relative to the backend screen */
    869     for (i = 0; i < pOtherScreen->numVisuals; i++) {
    870         VisualPtr pOtherVisual = &pOtherScreen->visuals[i];
    871 
    872         if ((*XineramaVisualsEqualPtr) (pVisual, pOtherScreen, pOtherVisual))
    873             return pOtherVisual->vid;
    874     }
    875 
    876     return 0;
    877 }
    878 
    879 /*
    880  *	PanoramiXResetProc()
    881  *		Exit, deallocating as needed.
    882  */
    883 
    884 static void
    885 PanoramiXResetProc(ExtensionEntry * extEntry)
    886 {
    887     int i;
    888 
    889     PanoramiXRenderReset();
    890     PanoramiXFixesReset();
    891     PanoramiXDamageReset();
    892 #ifdef COMPOSITE
    893     PanoramiXCompositeReset ();
    894 #endif
    895     screenInfo.numScreens = PanoramiXNumScreens;
    896     for (i = 256; i--;)
    897         ProcVector[i] = SavedProcVector[i];
    898 }
    899 
    900 int
    901 ProcPanoramiXQueryVersion(ClientPtr client)
    902 {
    903     /* REQUEST(xPanoramiXQueryVersionReq); */
    904     xPanoramiXQueryVersionReply rep = {
    905         .type = X_Reply,
    906         .sequenceNumber = client->sequence,
    907         .length = 0,
    908         .majorVersion = SERVER_PANORAMIX_MAJOR_VERSION,
    909         .minorVersion = SERVER_PANORAMIX_MINOR_VERSION
    910     };
    911 
    912     REQUEST_SIZE_MATCH(xPanoramiXQueryVersionReq);
    913     if (client->swapped) {
    914         swaps(&rep.sequenceNumber);
    915         swapl(&rep.length);
    916         swaps(&rep.majorVersion);
    917         swaps(&rep.minorVersion);
    918     }
    919     WriteToClient(client, sizeof(xPanoramiXQueryVersionReply), &rep);
    920     return Success;
    921 }
    922 
    923 int
    924 ProcPanoramiXGetState(ClientPtr client)
    925 {
    926     REQUEST(xPanoramiXGetStateReq);
    927     WindowPtr pWin;
    928     xPanoramiXGetStateReply rep;
    929     int rc;
    930 
    931     REQUEST_SIZE_MATCH(xPanoramiXGetStateReq);
    932     rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
    933     if (rc != Success)
    934         return rc;
    935 
    936     rep = (xPanoramiXGetStateReply) {
    937         .type = X_Reply,
    938         .state = !noPanoramiXExtension,
    939         .sequenceNumber = client->sequence,
    940         .length = 0,
    941         .window = stuff->window
    942     };
    943     if (client->swapped) {
    944         swaps(&rep.sequenceNumber);
    945         swapl(&rep.length);
    946         swapl(&rep.window);
    947     }
    948     WriteToClient(client, sizeof(xPanoramiXGetStateReply), &rep);
    949     return Success;
    950 
    951 }
    952 
    953 int
    954 ProcPanoramiXGetScreenCount(ClientPtr client)
    955 {
    956     REQUEST(xPanoramiXGetScreenCountReq);
    957     WindowPtr pWin;
    958     xPanoramiXGetScreenCountReply rep;
    959     int rc;
    960 
    961     REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq);
    962     rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
    963     if (rc != Success)
    964         return rc;
    965 
    966     rep = (xPanoramiXGetScreenCountReply) {
    967         .type = X_Reply,
    968         .ScreenCount = PanoramiXNumScreens,
    969         .sequenceNumber = client->sequence,
    970         .length = 0,
    971         .window = stuff->window
    972     };
    973     if (client->swapped) {
    974         swaps(&rep.sequenceNumber);
    975         swapl(&rep.length);
    976         swapl(&rep.window);
    977     }
    978     WriteToClient(client, sizeof(xPanoramiXGetScreenCountReply), &rep);
    979     return Success;
    980 }
    981 
    982 int
    983 ProcPanoramiXGetScreenSize(ClientPtr client)
    984 {
    985     REQUEST(xPanoramiXGetScreenSizeReq);
    986     WindowPtr pWin;
    987     xPanoramiXGetScreenSizeReply rep;
    988     int rc;
    989 
    990     REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq);
    991 
    992     if (stuff->screen >= PanoramiXNumScreens)
    993         return BadMatch;
    994 
    995     rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
    996     if (rc != Success)
    997         return rc;
    998 
    999     rep = (xPanoramiXGetScreenSizeReply) {
   1000         .type = X_Reply,
   1001         .sequenceNumber = client->sequence,
   1002         .length = 0,
   1003     /* screen dimensions */
   1004         .width = screenInfo.screens[stuff->screen]->width,
   1005         .height = screenInfo.screens[stuff->screen]->height,
   1006         .window = stuff->window,
   1007         .screen = stuff->screen
   1008     };
   1009     if (client->swapped) {
   1010         swaps(&rep.sequenceNumber);
   1011         swapl(&rep.length);
   1012         swapl(&rep.width);
   1013         swapl(&rep.height);
   1014         swapl(&rep.window);
   1015         swapl(&rep.screen);
   1016     }
   1017     WriteToClient(client, sizeof(xPanoramiXGetScreenSizeReply), &rep);
   1018     return Success;
   1019 }
   1020 
   1021 int
   1022 ProcXineramaIsActive(ClientPtr client)
   1023 {
   1024     /* REQUEST(xXineramaIsActiveReq); */
   1025     xXineramaIsActiveReply rep;
   1026 
   1027     REQUEST_SIZE_MATCH(xXineramaIsActiveReq);
   1028 
   1029     rep = (xXineramaIsActiveReply) {
   1030         .type = X_Reply,
   1031         .sequenceNumber = client->sequence,
   1032         .length = 0,
   1033 #if 1
   1034         /* The following hack fools clients into thinking that Xinerama
   1035          * is disabled even though it is not. */
   1036         .state = !noPanoramiXExtension && !PanoramiXExtensionDisabledHack
   1037 #else
   1038         .state = !noPanoramiXExtension;
   1039 #endif
   1040     };
   1041     if (client->swapped) {
   1042         swaps(&rep.sequenceNumber);
   1043         swapl(&rep.length);
   1044         swapl(&rep.state);
   1045     }
   1046     WriteToClient(client, sizeof(xXineramaIsActiveReply), &rep);
   1047     return Success;
   1048 }
   1049 
   1050 int
   1051 ProcXineramaQueryScreens(ClientPtr client)
   1052 {
   1053     /* REQUEST(xXineramaQueryScreensReq); */
   1054     CARD32 number = (noPanoramiXExtension) ? 0 : PanoramiXNumScreens;
   1055     xXineramaQueryScreensReply rep = {
   1056         .type = X_Reply,
   1057         .sequenceNumber = client->sequence,
   1058         .length = bytes_to_int32(number * sz_XineramaScreenInfo),
   1059         .number = number
   1060     };
   1061 
   1062     REQUEST_SIZE_MATCH(xXineramaQueryScreensReq);
   1063 
   1064     if (client->swapped) {
   1065         swaps(&rep.sequenceNumber);
   1066         swapl(&rep.length);
   1067         swapl(&rep.number);
   1068     }
   1069     WriteToClient(client, sizeof(xXineramaQueryScreensReply), &rep);
   1070 
   1071     if (!noPanoramiXExtension) {
   1072         xXineramaScreenInfo scratch;
   1073         int i;
   1074 
   1075         FOR_NSCREENS(i) {
   1076             scratch.x_org = screenInfo.screens[i]->x;
   1077             scratch.y_org = screenInfo.screens[i]->y;
   1078             scratch.width = screenInfo.screens[i]->width;
   1079             scratch.height = screenInfo.screens[i]->height;
   1080 
   1081             if (client->swapped) {
   1082                 swaps(&scratch.x_org);
   1083                 swaps(&scratch.y_org);
   1084                 swaps(&scratch.width);
   1085                 swaps(&scratch.height);
   1086             }
   1087             WriteToClient(client, sz_XineramaScreenInfo, &scratch);
   1088         }
   1089     }
   1090 
   1091     return Success;
   1092 }
   1093 
   1094 static int
   1095 ProcPanoramiXDispatch(ClientPtr client)
   1096 {
   1097     REQUEST(xReq);
   1098     switch (stuff->data) {
   1099     case X_PanoramiXQueryVersion:
   1100         return ProcPanoramiXQueryVersion(client);
   1101     case X_PanoramiXGetState:
   1102         return ProcPanoramiXGetState(client);
   1103     case X_PanoramiXGetScreenCount:
   1104         return ProcPanoramiXGetScreenCount(client);
   1105     case X_PanoramiXGetScreenSize:
   1106         return ProcPanoramiXGetScreenSize(client);
   1107     case X_XineramaIsActive:
   1108         return ProcXineramaIsActive(client);
   1109     case X_XineramaQueryScreens:
   1110         return ProcXineramaQueryScreens(client);
   1111     }
   1112     return BadRequest;
   1113 }
   1114 
   1115 #if X_BYTE_ORDER == X_LITTLE_ENDIAN
   1116 #define SHIFT_L(v,s) (v) << (s)
   1117 #define SHIFT_R(v,s) (v) >> (s)
   1118 #else
   1119 #define SHIFT_L(v,s) (v) >> (s)
   1120 #define SHIFT_R(v,s) (v) << (s)
   1121 #endif
   1122 
   1123 static void
   1124 CopyBits(char *dst, int shiftL, char *src, int bytes)
   1125 {
   1126     /* Just get it to work.  Worry about speed later */
   1127     int shiftR = 8 - shiftL;
   1128 
   1129     while (bytes--) {
   1130         *dst |= SHIFT_L(*src, shiftL);
   1131         *(dst + 1) |= SHIFT_R(*src, shiftR);
   1132         dst++;
   1133         src++;
   1134     }
   1135 }
   1136 
   1137 /* Caution.  This doesn't support 2 and 4 bpp formats.  We expect
   1138    1 bpp and planar data to be already cleared when presented
   1139    to this function */
   1140 
   1141 void
   1142 XineramaGetImageData(DrawablePtr *pDrawables,
   1143                      int left,
   1144                      int top,
   1145                      int width,
   1146                      int height,
   1147                      unsigned int format,
   1148                      unsigned long planemask,
   1149                      char *data, int pitch, Bool isRoot)
   1150 {
   1151     RegionRec SrcRegion, ScreenRegion, GrabRegion;
   1152     BoxRec SrcBox, *pbox;
   1153     int x, y, w, h, i, j, nbox, size, sizeNeeded, ScratchPitch, inOut, depth;
   1154     DrawablePtr pDraw = pDrawables[0];
   1155     char *ScratchMem = NULL;
   1156 
   1157     size = 0;
   1158 
   1159     /* find box in logical screen space */
   1160     SrcBox.x1 = left;
   1161     SrcBox.y1 = top;
   1162     if (!isRoot) {
   1163         SrcBox.x1 += pDraw->x + screenInfo.screens[0]->x;
   1164         SrcBox.y1 += pDraw->y + screenInfo.screens[0]->y;
   1165     }
   1166     SrcBox.x2 = SrcBox.x1 + width;
   1167     SrcBox.y2 = SrcBox.y1 + height;
   1168 
   1169     RegionInit(&SrcRegion, &SrcBox, 1);
   1170     RegionNull(&GrabRegion);
   1171 
   1172     depth = (format == XYPixmap) ? 1 : pDraw->depth;
   1173 
   1174     FOR_NSCREENS(i) {
   1175         BoxRec TheBox;
   1176         ScreenPtr pScreen;
   1177 
   1178         pDraw = pDrawables[i];
   1179         pScreen = pDraw->pScreen;
   1180 
   1181         TheBox.x1 = pScreen->x;
   1182         TheBox.x2 = TheBox.x1 + pScreen->width;
   1183         TheBox.y1 = pScreen->y;
   1184         TheBox.y2 = TheBox.y1 + pScreen->height;
   1185 
   1186         RegionInit(&ScreenRegion, &TheBox, 1);
   1187         inOut = RegionContainsRect(&ScreenRegion, &SrcBox);
   1188         if (inOut == rgnPART)
   1189             RegionIntersect(&GrabRegion, &SrcRegion, &ScreenRegion);
   1190         RegionUninit(&ScreenRegion);
   1191 
   1192         if (inOut == rgnIN) {
   1193             (*pScreen->GetImage) (pDraw,
   1194                                   SrcBox.x1 - pDraw->x -
   1195                                   screenInfo.screens[i]->x,
   1196                                   SrcBox.y1 - pDraw->y -
   1197                                   screenInfo.screens[i]->y, width, height,
   1198                                   format, planemask, data);
   1199             break;
   1200         }
   1201         else if (inOut == rgnOUT)
   1202             continue;
   1203 
   1204         nbox = RegionNumRects(&GrabRegion);
   1205 
   1206         if (nbox) {
   1207             pbox = RegionRects(&GrabRegion);
   1208 
   1209             while (nbox--) {
   1210                 w = pbox->x2 - pbox->x1;
   1211                 h = pbox->y2 - pbox->y1;
   1212                 ScratchPitch = PixmapBytePad(w, depth);
   1213                 sizeNeeded = ScratchPitch * h;
   1214 
   1215                 if (sizeNeeded > size) {
   1216                     char *tmpdata = ScratchMem;
   1217 
   1218                     ScratchMem = realloc(ScratchMem, sizeNeeded);
   1219                     if (ScratchMem)
   1220                         size = sizeNeeded;
   1221                     else {
   1222                         ScratchMem = tmpdata;
   1223                         break;
   1224                     }
   1225                 }
   1226 
   1227                 x = pbox->x1 - pDraw->x - screenInfo.screens[i]->x;
   1228                 y = pbox->y1 - pDraw->y - screenInfo.screens[i]->y;
   1229 
   1230                 (*pScreen->GetImage) (pDraw, x, y, w, h,
   1231                                       format, planemask, ScratchMem);
   1232 
   1233                 /* copy the memory over */
   1234 
   1235                 if (depth == 1) {
   1236                     int k, shift, leftover, index, index2;
   1237 
   1238                     x = pbox->x1 - SrcBox.x1;
   1239                     y = pbox->y1 - SrcBox.y1;
   1240                     shift = x & 7;
   1241                     x >>= 3;
   1242                     leftover = w & 7;
   1243                     w >>= 3;
   1244 
   1245                     /* clean up the edge */
   1246                     if (leftover) {
   1247                         int mask = (1 << leftover) - 1;
   1248 
   1249                         for (j = h, k = w; j--; k += ScratchPitch)
   1250                             ScratchMem[k] &= mask;
   1251                     }
   1252 
   1253                     for (j = 0, index = (pitch * y) + x, index2 = 0; j < h;
   1254                          j++, index += pitch, index2 += ScratchPitch) {
   1255                         if (w) {
   1256                             if (!shift)
   1257                                 memcpy(data + index, ScratchMem + index2, w);
   1258                             else
   1259                                 CopyBits(data + index, shift,
   1260                                          ScratchMem + index2, w);
   1261                         }
   1262 
   1263                         if (leftover) {
   1264                             data[index + w] |=
   1265                                 SHIFT_L(ScratchMem[index2 + w], shift);
   1266                             if ((shift + leftover) > 8)
   1267                                 data[index + w + 1] |=
   1268                                     SHIFT_R(ScratchMem[index2 + w],
   1269                                             (8 - shift));
   1270                         }
   1271                     }
   1272                 }
   1273                 else {
   1274                     j = BitsPerPixel(depth) >> 3;
   1275                     x = (pbox->x1 - SrcBox.x1) * j;
   1276                     y = pbox->y1 - SrcBox.y1;
   1277                     w *= j;
   1278 
   1279                     for (j = 0; j < h; j++) {
   1280                         memcpy(data + (pitch * (y + j)) + x,
   1281                                ScratchMem + (ScratchPitch * j), w);
   1282                     }
   1283                 }
   1284                 pbox++;
   1285             }
   1286 
   1287             RegionSubtract(&SrcRegion, &SrcRegion, &GrabRegion);
   1288             if (!RegionNotEmpty(&SrcRegion))
   1289                 break;
   1290         }
   1291 
   1292     }
   1293 
   1294     free(ScratchMem);
   1295 
   1296     RegionUninit(&SrcRegion);
   1297     RegionUninit(&GrabRegion);
   1298 }