105b261ecSmrg/*****************************************************************
205b261ecSmrgCopyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts.
305b261ecSmrgPermission is hereby granted, free of charge, to any person obtaining a copy
405b261ecSmrgof this software and associated documentation files (the "Software"), to deal
505b261ecSmrgin the Software without restriction, including without limitation the rights
605b261ecSmrgto use, copy, modify, merge, publish, distribute, sublicense, and/or sell
705b261ecSmrgcopies of the Software.
805b261ecSmrg
905b261ecSmrgThe above copyright notice and this permission notice shall be included in
1005b261ecSmrgall copies or substantial portions of the Software.
1105b261ecSmrg
1205b261ecSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1305b261ecSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1405b261ecSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
1505b261ecSmrgDIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING,
1605b261ecSmrgBUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY,
1705b261ecSmrgWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
1805b261ecSmrgIN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1905b261ecSmrg
2005b261ecSmrgExcept as contained in this notice, the name of Digital Equipment Corporation
2105b261ecSmrgshall not be used in advertising or otherwise to promote the sale, use or other
2205b261ecSmrgdealings in this Software without prior written authorization from Digital
2305b261ecSmrgEquipment Corporation.
2405b261ecSmrg******************************************************************/
2505b261ecSmrg
2605b261ecSmrg#ifdef HAVE_DIX_CONFIG_H
2705b261ecSmrg#include <dix-config.h>
2805b261ecSmrg#endif
2905b261ecSmrg
3005b261ecSmrg#ifdef HAVE_DMX_CONFIG_H
3105b261ecSmrg#include <dmx-config.h>
3205b261ecSmrg#endif
3305b261ecSmrg
3405b261ecSmrg#include <stdio.h>
3505b261ecSmrg#include <X11/X.h>
3605b261ecSmrg#include <X11/Xproto.h>
3705b261ecSmrg#include <X11/Xarch.h>
3805b261ecSmrg#include "misc.h"
3905b261ecSmrg#include "cursor.h"
4005b261ecSmrg#include "cursorstr.h"
4105b261ecSmrg#include "extnsionst.h"
4205b261ecSmrg#include "dixstruct.h"
4305b261ecSmrg#include "gc.h"
4405b261ecSmrg#include "gcstruct.h"
4505b261ecSmrg#include "scrnintstr.h"
4605b261ecSmrg#include "window.h"
4705b261ecSmrg#include "windowstr.h"
4805b261ecSmrg#include "pixmapstr.h"
4905b261ecSmrg#include "panoramiX.h"
5005b261ecSmrg#include <X11/extensions/panoramiXproto.h>
5105b261ecSmrg#include "panoramiXsrv.h"
5205b261ecSmrg#include "globals.h"
5305b261ecSmrg#include "servermd.h"
5405b261ecSmrg#include "resource.h"
5505b261ecSmrg#include "picturestr.h"
569ace9065Smrg#include "xfixesint.h"
5735c4bbdfSmrg#include "damageextint.h"
589ace9065Smrg#ifdef COMPOSITE
599ace9065Smrg#include "compint.h"
609ace9065Smrg#endif
6135c4bbdfSmrg#include "extinit.h"
626747b715Smrg#include "protocol-versions.h"
6305b261ecSmrg
6405b261ecSmrg#ifdef GLXPROXY
6505b261ecSmrgextern VisualPtr glxMatchVisual(ScreenPtr pScreen,
6635c4bbdfSmrg                                VisualPtr pVisual, ScreenPtr pMatchScreen);
6705b261ecSmrg#endif
6805b261ecSmrg
6905b261ecSmrg/*
7005b261ecSmrg *	PanoramiX data declarations
7105b261ecSmrg */
7205b261ecSmrg
7335c4bbdfSmrgint PanoramiXPixWidth = 0;
7435c4bbdfSmrgint PanoramiXPixHeight = 0;
7535c4bbdfSmrgint PanoramiXNumScreens = 0;
7605b261ecSmrg
7735c4bbdfSmrg_X_EXPORT RegionRec PanoramiXScreenRegion = { {0, 0, 0, 0}, NULL };
7805b261ecSmrg
7935c4bbdfSmrgstatic int PanoramiXNumDepths;
8035c4bbdfSmrgstatic DepthPtr PanoramiXDepths;
8135c4bbdfSmrgstatic int PanoramiXNumVisuals;
8235c4bbdfSmrgstatic VisualPtr PanoramiXVisuals;
8305b261ecSmrg
8435c4bbdfSmrgRESTYPE XRC_DRAWABLE;
8535c4bbdfSmrgRESTYPE XRT_WINDOW;
8635c4bbdfSmrgRESTYPE XRT_PIXMAP;
8735c4bbdfSmrgRESTYPE XRT_GC;
8835c4bbdfSmrgRESTYPE XRT_COLORMAP;
8905b261ecSmrg
904642e01fSmrgstatic Bool VisualsEqual(VisualPtr, ScreenPtr, VisualPtr);
916747b715SmrgXineramaVisualsEqualProcPtr XineramaVisualsEqualPtr = &VisualsEqual;
924642e01fSmrg
9305b261ecSmrg/*
9405b261ecSmrg *	Function prototypes
9505b261ecSmrg */
9605b261ecSmrg
9705b261ecSmrgstatic int panoramiXGeneration;
9835c4bbdfSmrgstatic int ProcPanoramiXDispatch(ClientPtr client);
9905b261ecSmrg
10035c4bbdfSmrgstatic void PanoramiXResetProc(ExtensionEntry *);
10105b261ecSmrg
10205b261ecSmrg/*
10305b261ecSmrg *	External references for functions and data variables
10405b261ecSmrg */
10505b261ecSmrg
10605b261ecSmrg#include "panoramiXh.h"
10705b261ecSmrg
10835c4bbdfSmrgint (*SavedProcVector[256]) (ClientPtr client) = {
10935c4bbdfSmrgNULL,};
11005b261ecSmrg
1116747b715Smrgstatic DevPrivateKeyRec PanoramiXGCKeyRec;
11235c4bbdfSmrg
1136747b715Smrg#define PanoramiXGCKey (&PanoramiXGCKeyRec)
1146747b715Smrgstatic DevPrivateKeyRec PanoramiXScreenKeyRec;
11535c4bbdfSmrg
1166747b715Smrg#define PanoramiXScreenKey (&PanoramiXScreenKeyRec)
11705b261ecSmrg
11805b261ecSmrgtypedef struct {
11935c4bbdfSmrg    DDXPointRec clipOrg;
12035c4bbdfSmrg    DDXPointRec patOrg;
12135c4bbdfSmrg    const GCFuncs *wrapFuncs;
12205b261ecSmrg} PanoramiXGCRec, *PanoramiXGCPtr;
12305b261ecSmrg
12405b261ecSmrgtypedef struct {
12535c4bbdfSmrg    CreateGCProcPtr CreateGC;
12635c4bbdfSmrg    CloseScreenProcPtr CloseScreen;
12705b261ecSmrg} PanoramiXScreenRec, *PanoramiXScreenPtr;
12805b261ecSmrg
12905b261ecSmrgstatic void XineramaValidateGC(GCPtr, unsigned long, DrawablePtr);
13005b261ecSmrgstatic void XineramaChangeGC(GCPtr, unsigned long);
13105b261ecSmrgstatic void XineramaCopyGC(GCPtr, unsigned long, GCPtr);
13205b261ecSmrgstatic void XineramaDestroyGC(GCPtr);
13335c4bbdfSmrgstatic void XineramaChangeClip(GCPtr, int, void *, int);
13405b261ecSmrgstatic void XineramaDestroyClip(GCPtr);
13505b261ecSmrgstatic void XineramaCopyClip(GCPtr, GCPtr);
13605b261ecSmrg
13735c4bbdfSmrgstatic const GCFuncs XineramaGCFuncs = {
13805b261ecSmrg    XineramaValidateGC, XineramaChangeGC, XineramaCopyGC, XineramaDestroyGC,
13905b261ecSmrg    XineramaChangeClip, XineramaDestroyClip, XineramaCopyClip
14005b261ecSmrg};
14105b261ecSmrg
14205b261ecSmrg#define Xinerama_GC_FUNC_PROLOGUE(pGC)\
1434642e01fSmrg    PanoramiXGCPtr  pGCPriv = (PanoramiXGCPtr) \
1444642e01fSmrg	dixLookupPrivate(&(pGC)->devPrivates, PanoramiXGCKey); \
14505b261ecSmrg    (pGC)->funcs = pGCPriv->wrapFuncs;
14605b261ecSmrg
14705b261ecSmrg#define Xinerama_GC_FUNC_EPILOGUE(pGC)\
14805b261ecSmrg    pGCPriv->wrapFuncs = (pGC)->funcs;\
14905b261ecSmrg    (pGC)->funcs = &XineramaGCFuncs;
15005b261ecSmrg
15105b261ecSmrgstatic Bool
15235c4bbdfSmrgXineramaCloseScreen(ScreenPtr pScreen)
15305b261ecSmrg{
1544642e01fSmrg    PanoramiXScreenPtr pScreenPriv = (PanoramiXScreenPtr)
15535c4bbdfSmrg        dixLookupPrivate(&pScreen->devPrivates, PanoramiXScreenKey);
15605b261ecSmrg
15705b261ecSmrg    pScreen->CloseScreen = pScreenPriv->CloseScreen;
15805b261ecSmrg    pScreen->CreateGC = pScreenPriv->CreateGC;
15905b261ecSmrg
16005b261ecSmrg    if (pScreen->myNum == 0)
16135c4bbdfSmrg        RegionUninit(&PanoramiXScreenRegion);
16205b261ecSmrg
16335c4bbdfSmrg    free(pScreenPriv);
16405b261ecSmrg
16535c4bbdfSmrg    return (*pScreen->CloseScreen) (pScreen);
16605b261ecSmrg}
16705b261ecSmrg
16805b261ecSmrgstatic Bool
16905b261ecSmrgXineramaCreateGC(GCPtr pGC)
17005b261ecSmrg{
17105b261ecSmrg    ScreenPtr pScreen = pGC->pScreen;
1724642e01fSmrg    PanoramiXScreenPtr pScreenPriv = (PanoramiXScreenPtr)
17335c4bbdfSmrg        dixLookupPrivate(&pScreen->devPrivates, PanoramiXScreenKey);
17405b261ecSmrg    Bool ret;
17505b261ecSmrg
17605b261ecSmrg    pScreen->CreateGC = pScreenPriv->CreateGC;
17735c4bbdfSmrg    if ((ret = (*pScreen->CreateGC) (pGC))) {
17835c4bbdfSmrg        PanoramiXGCPtr pGCPriv = (PanoramiXGCPtr)
17935c4bbdfSmrg            dixLookupPrivate(&pGC->devPrivates, PanoramiXGCKey);
18005b261ecSmrg
18135c4bbdfSmrg        pGCPriv->wrapFuncs = pGC->funcs;
18205b261ecSmrg        pGC->funcs = &XineramaGCFuncs;
18305b261ecSmrg
18435c4bbdfSmrg        pGCPriv->clipOrg.x = pGC->clipOrg.x;
18535c4bbdfSmrg        pGCPriv->clipOrg.y = pGC->clipOrg.y;
18635c4bbdfSmrg        pGCPriv->patOrg.x = pGC->patOrg.x;
18735c4bbdfSmrg        pGCPriv->patOrg.y = pGC->patOrg.y;
18805b261ecSmrg    }
18905b261ecSmrg    pScreen->CreateGC = XineramaCreateGC;
19005b261ecSmrg
19105b261ecSmrg    return ret;
19205b261ecSmrg}
19305b261ecSmrg
19405b261ecSmrgstatic void
19535c4bbdfSmrgXineramaValidateGC(GCPtr pGC, unsigned long changes, DrawablePtr pDraw)
19635c4bbdfSmrg{
19735c4bbdfSmrg    Xinerama_GC_FUNC_PROLOGUE(pGC);
19835c4bbdfSmrg
19935c4bbdfSmrg    if ((pDraw->type == DRAWABLE_WINDOW) && !(((WindowPtr) pDraw)->parent)) {
20035c4bbdfSmrg        /* the root window */
20135c4bbdfSmrg        int x_off = pGC->pScreen->x;
20235c4bbdfSmrg        int y_off = pGC->pScreen->y;
20335c4bbdfSmrg        int new_val;
20435c4bbdfSmrg
20535c4bbdfSmrg        new_val = pGCPriv->clipOrg.x - x_off;
20635c4bbdfSmrg        if (pGC->clipOrg.x != new_val) {
20735c4bbdfSmrg            pGC->clipOrg.x = new_val;
20835c4bbdfSmrg            changes |= GCClipXOrigin;
20935c4bbdfSmrg        }
21035c4bbdfSmrg        new_val = pGCPriv->clipOrg.y - y_off;
21135c4bbdfSmrg        if (pGC->clipOrg.y != new_val) {
21235c4bbdfSmrg            pGC->clipOrg.y = new_val;
21335c4bbdfSmrg            changes |= GCClipYOrigin;
21435c4bbdfSmrg        }
21535c4bbdfSmrg        new_val = pGCPriv->patOrg.x - x_off;
21635c4bbdfSmrg        if (pGC->patOrg.x != new_val) {
21735c4bbdfSmrg            pGC->patOrg.x = new_val;
21835c4bbdfSmrg            changes |= GCTileStipXOrigin;
21935c4bbdfSmrg        }
22035c4bbdfSmrg        new_val = pGCPriv->patOrg.y - y_off;
22135c4bbdfSmrg        if (pGC->patOrg.y != new_val) {
22235c4bbdfSmrg            pGC->patOrg.y = new_val;
22335c4bbdfSmrg            changes |= GCTileStipYOrigin;
22435c4bbdfSmrg        }
22535c4bbdfSmrg    }
22635c4bbdfSmrg    else {
22735c4bbdfSmrg        if (pGC->clipOrg.x != pGCPriv->clipOrg.x) {
22835c4bbdfSmrg            pGC->clipOrg.x = pGCPriv->clipOrg.x;
22935c4bbdfSmrg            changes |= GCClipXOrigin;
23035c4bbdfSmrg        }
23135c4bbdfSmrg        if (pGC->clipOrg.y != pGCPriv->clipOrg.y) {
23235c4bbdfSmrg            pGC->clipOrg.y = pGCPriv->clipOrg.y;
23335c4bbdfSmrg            changes |= GCClipYOrigin;
23435c4bbdfSmrg        }
23535c4bbdfSmrg        if (pGC->patOrg.x != pGCPriv->patOrg.x) {
23635c4bbdfSmrg            pGC->patOrg.x = pGCPriv->patOrg.x;
23735c4bbdfSmrg            changes |= GCTileStipXOrigin;
23835c4bbdfSmrg        }
23935c4bbdfSmrg        if (pGC->patOrg.y != pGCPriv->patOrg.y) {
24035c4bbdfSmrg            pGC->patOrg.y = pGCPriv->patOrg.y;
24135c4bbdfSmrg            changes |= GCTileStipYOrigin;
24235c4bbdfSmrg        }
24305b261ecSmrg    }
24435c4bbdfSmrg
24535c4bbdfSmrg    (*pGC->funcs->ValidateGC) (pGC, changes, pDraw);
24635c4bbdfSmrg    Xinerama_GC_FUNC_EPILOGUE(pGC);
24705b261ecSmrg}
24805b261ecSmrg
24905b261ecSmrgstatic void
25005b261ecSmrgXineramaDestroyGC(GCPtr pGC)
25105b261ecSmrg{
25235c4bbdfSmrg    Xinerama_GC_FUNC_PROLOGUE(pGC);
25335c4bbdfSmrg    (*pGC->funcs->DestroyGC) (pGC);
25435c4bbdfSmrg    Xinerama_GC_FUNC_EPILOGUE(pGC);
25505b261ecSmrg}
25605b261ecSmrg
25705b261ecSmrgstatic void
25835c4bbdfSmrgXineramaChangeGC(GCPtr pGC, unsigned long mask)
25935c4bbdfSmrg{
26035c4bbdfSmrg    Xinerama_GC_FUNC_PROLOGUE(pGC);
26135c4bbdfSmrg
26235c4bbdfSmrg    if (mask & GCTileStipXOrigin)
26335c4bbdfSmrg        pGCPriv->patOrg.x = pGC->patOrg.x;
26435c4bbdfSmrg    if (mask & GCTileStipYOrigin)
26535c4bbdfSmrg        pGCPriv->patOrg.y = pGC->patOrg.y;
26635c4bbdfSmrg    if (mask & GCClipXOrigin)
26735c4bbdfSmrg        pGCPriv->clipOrg.x = pGC->clipOrg.x;
26835c4bbdfSmrg    if (mask & GCClipYOrigin)
26935c4bbdfSmrg        pGCPriv->clipOrg.y = pGC->clipOrg.y;
27005b261ecSmrg
27105b261ecSmrg    (*pGC->funcs->ChangeGC) (pGC, mask);
27235c4bbdfSmrg    Xinerama_GC_FUNC_EPILOGUE(pGC);
27305b261ecSmrg}
27405b261ecSmrg
27505b261ecSmrgstatic void
27635c4bbdfSmrgXineramaCopyGC(GCPtr pGCSrc, unsigned long mask, GCPtr pGCDst)
27735c4bbdfSmrg{
2784642e01fSmrg    PanoramiXGCPtr pSrcPriv = (PanoramiXGCPtr)
27935c4bbdfSmrg        dixLookupPrivate(&pGCSrc->devPrivates, PanoramiXGCKey);
28005b261ecSmrg
28135c4bbdfSmrg    Xinerama_GC_FUNC_PROLOGUE(pGCDst);
28235c4bbdfSmrg
28335c4bbdfSmrg    if (mask & GCTileStipXOrigin)
28405b261ecSmrg        pGCPriv->patOrg.x = pSrcPriv->patOrg.x;
28535c4bbdfSmrg    if (mask & GCTileStipYOrigin)
28605b261ecSmrg        pGCPriv->patOrg.y = pSrcPriv->patOrg.y;
28735c4bbdfSmrg    if (mask & GCClipXOrigin)
28805b261ecSmrg        pGCPriv->clipOrg.x = pSrcPriv->clipOrg.x;
28935c4bbdfSmrg    if (mask & GCClipYOrigin)
29005b261ecSmrg        pGCPriv->clipOrg.y = pSrcPriv->clipOrg.y;
29105b261ecSmrg
29205b261ecSmrg    (*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst);
29335c4bbdfSmrg    Xinerama_GC_FUNC_EPILOGUE(pGCDst);
29405b261ecSmrg}
29505b261ecSmrg
29605b261ecSmrgstatic void
29735c4bbdfSmrgXineramaChangeClip(GCPtr pGC, int type, void *pvalue, int nrects)
29835c4bbdfSmrg{
29935c4bbdfSmrg    Xinerama_GC_FUNC_PROLOGUE(pGC);
30005b261ecSmrg    (*pGC->funcs->ChangeClip) (pGC, type, pvalue, nrects);
30135c4bbdfSmrg    Xinerama_GC_FUNC_EPILOGUE(pGC);
30205b261ecSmrg}
30305b261ecSmrg
30405b261ecSmrgstatic void
30505b261ecSmrgXineramaCopyClip(GCPtr pgcDst, GCPtr pgcSrc)
30605b261ecSmrg{
30735c4bbdfSmrg    Xinerama_GC_FUNC_PROLOGUE(pgcDst);
30835c4bbdfSmrg    (*pgcDst->funcs->CopyClip) (pgcDst, pgcSrc);
30935c4bbdfSmrg    Xinerama_GC_FUNC_EPILOGUE(pgcDst);
31005b261ecSmrg}
31105b261ecSmrg
31205b261ecSmrgstatic void
31305b261ecSmrgXineramaDestroyClip(GCPtr pGC)
31405b261ecSmrg{
31535c4bbdfSmrg    Xinerama_GC_FUNC_PROLOGUE(pGC);
31635c4bbdfSmrg    (*pGC->funcs->DestroyClip) (pGC);
31735c4bbdfSmrg    Xinerama_GC_FUNC_EPILOGUE(pGC);
31805b261ecSmrg}
31905b261ecSmrg
3206747b715Smrgint
32135c4bbdfSmrgXineramaDeleteResource(void *data, XID id)
32205b261ecSmrg{
3236747b715Smrg    free(data);
32405b261ecSmrg    return 1;
32505b261ecSmrg}
32605b261ecSmrg
32705b261ecSmrgtypedef struct {
32835c4bbdfSmrg    int screen;
32935c4bbdfSmrg    int id;
33035c4bbdfSmrg} PanoramiXSearchData;
33105b261ecSmrg
33235c4bbdfSmrgstatic Bool
33335c4bbdfSmrgXineramaFindIDByScrnum(void *resource, XID id, void *privdata)
33405b261ecSmrg{
33535c4bbdfSmrg    PanoramiXRes *res = (PanoramiXRes *) resource;
33635c4bbdfSmrg    PanoramiXSearchData *data = (PanoramiXSearchData *) privdata;
33735c4bbdfSmrg
3386747b715Smrg    return res->info[data->screen].id == data->id;
33905b261ecSmrg}
34005b261ecSmrg
34105b261ecSmrgPanoramiXRes *
34205b261ecSmrgPanoramiXFindIDByScrnum(RESTYPE type, XID id, int screen)
34305b261ecSmrg{
34405b261ecSmrg    PanoramiXSearchData data;
34535c4bbdfSmrg    void *val;
34605b261ecSmrg
34735c4bbdfSmrg    if (!screen) {
34835c4bbdfSmrg        dixLookupResourceByType(&val, id, type, serverClient, DixReadAccess);
34935c4bbdfSmrg        return val;
3506747b715Smrg    }
35105b261ecSmrg
35205b261ecSmrg    data.screen = screen;
35305b261ecSmrg    data.id = id;
35405b261ecSmrg
35505b261ecSmrg    return LookupClientResourceComplex(clients[CLIENT_ID(id)], type,
35635c4bbdfSmrg                                       XineramaFindIDByScrnum, &data);
35705b261ecSmrg}
35805b261ecSmrg
35905b261ecSmrgtypedef struct _connect_callback_list {
36035c4bbdfSmrg    void (*func) (void);
36105b261ecSmrg    struct _connect_callback_list *next;
36205b261ecSmrg} XineramaConnectionCallbackList;
36305b261ecSmrg
36405b261ecSmrgstatic XineramaConnectionCallbackList *ConnectionCallbackList = NULL;
36505b261ecSmrg
3666747b715SmrgBool
36735c4bbdfSmrgXineramaRegisterConnectionBlockCallback(void (*func) (void))
36805b261ecSmrg{
36905b261ecSmrg    XineramaConnectionCallbackList *newlist;
37005b261ecSmrg
37135c4bbdfSmrg    if (!(newlist = malloc(sizeof(XineramaConnectionCallbackList))))
37235c4bbdfSmrg        return FALSE;
37305b261ecSmrg
37405b261ecSmrg    newlist->next = ConnectionCallbackList;
37505b261ecSmrg    newlist->func = func;
37605b261ecSmrg    ConnectionCallbackList = newlist;
37705b261ecSmrg
37805b261ecSmrg    return TRUE;
37905b261ecSmrg}
38005b261ecSmrg
38135c4bbdfSmrgstatic void
38235c4bbdfSmrgXineramaInitData(void)
38305b261ecSmrg{
38405b261ecSmrg    int i, w, h;
38505b261ecSmrg
3866747b715Smrg    RegionNull(&PanoramiXScreenRegion);
38735c4bbdfSmrg    FOR_NSCREENS(i) {
38835c4bbdfSmrg        BoxRec TheBox;
38935c4bbdfSmrg        RegionRec ScreenRegion;
39005b261ecSmrg
39135c4bbdfSmrg        ScreenPtr pScreen = screenInfo.screens[i];
39205b261ecSmrg
39335c4bbdfSmrg        TheBox.x1 = pScreen->x;
39435c4bbdfSmrg        TheBox.x2 = TheBox.x1 + pScreen->width;
39535c4bbdfSmrg        TheBox.y1 = pScreen->y;
39635c4bbdfSmrg        TheBox.y2 = TheBox.y1 + pScreen->height;
39705b261ecSmrg
39835c4bbdfSmrg        RegionInit(&ScreenRegion, &TheBox, 1);
39935c4bbdfSmrg        RegionUnion(&PanoramiXScreenRegion, &PanoramiXScreenRegion,
40035c4bbdfSmrg                    &ScreenRegion);
40135c4bbdfSmrg        RegionUninit(&ScreenRegion);
40205b261ecSmrg    }
40305b261ecSmrg
4046747b715Smrg    PanoramiXPixWidth = screenInfo.screens[0]->x + screenInfo.screens[0]->width;
40535c4bbdfSmrg    PanoramiXPixHeight =
40635c4bbdfSmrg        screenInfo.screens[0]->y + screenInfo.screens[0]->height;
40705b261ecSmrg
40835c4bbdfSmrg    FOR_NSCREENS_FORWARD_SKIP(i) {
40935c4bbdfSmrg        ScreenPtr pScreen = screenInfo.screens[i];
41005b261ecSmrg
41135c4bbdfSmrg        w = pScreen->x + pScreen->width;
41235c4bbdfSmrg        h = pScreen->y + pScreen->height;
41335c4bbdfSmrg
41435c4bbdfSmrg        if (PanoramiXPixWidth < w)
41535c4bbdfSmrg            PanoramiXPixWidth = w;
41635c4bbdfSmrg        if (PanoramiXPixHeight < h)
41735c4bbdfSmrg            PanoramiXPixHeight = h;
41805b261ecSmrg    }
41905b261ecSmrg}
42005b261ecSmrg
42135c4bbdfSmrgvoid
42235c4bbdfSmrgXineramaReinitData(void)
42305b261ecSmrg{
4246747b715Smrg    RegionUninit(&PanoramiXScreenRegion);
42535c4bbdfSmrg    XineramaInitData();
42605b261ecSmrg}
42705b261ecSmrg
42805b261ecSmrg/*
42905b261ecSmrg *	PanoramiXExtensionInit():
43035c4bbdfSmrg *		Called from InitExtensions in main().
43105b261ecSmrg *		Register PanoramiXeen Extension
43205b261ecSmrg *		Initialize global variables.
43335c4bbdfSmrg */
43405b261ecSmrg
43535c4bbdfSmrgvoid
43635c4bbdfSmrgPanoramiXExtensionInit(void)
43705b261ecSmrg{
43835c4bbdfSmrg    int i;
43935c4bbdfSmrg    Bool success = FALSE;
44035c4bbdfSmrg    ExtensionEntry *extEntry;
44135c4bbdfSmrg    ScreenPtr pScreen = screenInfo.screens[0];
44235c4bbdfSmrg    PanoramiXScreenPtr pScreenPriv;
44305b261ecSmrg
44435c4bbdfSmrg    if (noPanoramiXExtension)
44535c4bbdfSmrg        return;
44605b261ecSmrg
4476747b715Smrg    if (!dixRegisterPrivateKey(&PanoramiXScreenKeyRec, PRIVATE_SCREEN, 0)) {
44835c4bbdfSmrg        noPanoramiXExtension = TRUE;
44935c4bbdfSmrg        return;
4506747b715Smrg    }
4516747b715Smrg
45235c4bbdfSmrg    if (!dixRegisterPrivateKey
45335c4bbdfSmrg        (&PanoramiXGCKeyRec, PRIVATE_GC, sizeof(PanoramiXGCRec))) {
45435c4bbdfSmrg        noPanoramiXExtension = TRUE;
45535c4bbdfSmrg        return;
4566747b715Smrg    }
4576747b715Smrg
45805b261ecSmrg    PanoramiXNumScreens = screenInfo.numScreens;
45935c4bbdfSmrg    if (PanoramiXNumScreens == 1) {     /* Only 1 screen        */
46035c4bbdfSmrg        noPanoramiXExtension = TRUE;
46135c4bbdfSmrg        return;
46205b261ecSmrg    }
46305b261ecSmrg
46405b261ecSmrg    while (panoramiXGeneration != serverGeneration) {
46535c4bbdfSmrg        extEntry = AddExtension(PANORAMIX_PROTOCOL_NAME, 0, 0,
46635c4bbdfSmrg                                ProcPanoramiXDispatch,
46735c4bbdfSmrg                                SProcPanoramiXDispatch, PanoramiXResetProc,
46835c4bbdfSmrg                                StandardMinorOpcode);
46935c4bbdfSmrg        if (!extEntry)
47035c4bbdfSmrg            break;
47135c4bbdfSmrg
47235c4bbdfSmrg        /*
47335c4bbdfSmrg         *      First make sure all the basic allocations succeed.  If not,
47435c4bbdfSmrg         *      run in non-PanoramiXeen mode.
47535c4bbdfSmrg         */
47635c4bbdfSmrg
47735c4bbdfSmrg        FOR_NSCREENS(i) {
47835c4bbdfSmrg            pScreen = screenInfo.screens[i];
47935c4bbdfSmrg            pScreenPriv = malloc(sizeof(PanoramiXScreenRec));
48035c4bbdfSmrg            dixSetPrivate(&pScreen->devPrivates, PanoramiXScreenKey,
48135c4bbdfSmrg                          pScreenPriv);
48235c4bbdfSmrg            if (!pScreenPriv) {
48335c4bbdfSmrg                noPanoramiXExtension = TRUE;
48435c4bbdfSmrg                return;
48535c4bbdfSmrg            }
48635c4bbdfSmrg
48735c4bbdfSmrg            pScreenPriv->CreateGC = pScreen->CreateGC;
48835c4bbdfSmrg            pScreenPriv->CloseScreen = pScreen->CloseScreen;
48935c4bbdfSmrg
49035c4bbdfSmrg            pScreen->CreateGC = XineramaCreateGC;
49135c4bbdfSmrg            pScreen->CloseScreen = XineramaCloseScreen;
49235c4bbdfSmrg        }
49335c4bbdfSmrg
49435c4bbdfSmrg        XRC_DRAWABLE = CreateNewResourceClass();
49535c4bbdfSmrg        XRT_WINDOW = CreateNewResourceType(XineramaDeleteResource,
49635c4bbdfSmrg                                           "XineramaWindow");
49735c4bbdfSmrg        if (XRT_WINDOW)
49835c4bbdfSmrg            XRT_WINDOW |= XRC_DRAWABLE;
49935c4bbdfSmrg        XRT_PIXMAP = CreateNewResourceType(XineramaDeleteResource,
50035c4bbdfSmrg                                           "XineramaPixmap");
50135c4bbdfSmrg        if (XRT_PIXMAP)
50235c4bbdfSmrg            XRT_PIXMAP |= XRC_DRAWABLE;
50335c4bbdfSmrg        XRT_GC = CreateNewResourceType(XineramaDeleteResource, "XineramaGC");
50435c4bbdfSmrg        XRT_COLORMAP = CreateNewResourceType(XineramaDeleteResource,
50535c4bbdfSmrg                                             "XineramaColormap");
50635c4bbdfSmrg
50735c4bbdfSmrg        if (XRT_WINDOW && XRT_PIXMAP && XRT_GC && XRT_COLORMAP) {
50835c4bbdfSmrg            panoramiXGeneration = serverGeneration;
50935c4bbdfSmrg            success = TRUE;
51035c4bbdfSmrg        }
51135c4bbdfSmrg        SetResourceTypeErrorValue(XRT_WINDOW, BadWindow);
51235c4bbdfSmrg        SetResourceTypeErrorValue(XRT_PIXMAP, BadPixmap);
51335c4bbdfSmrg        SetResourceTypeErrorValue(XRT_GC, BadGC);
51435c4bbdfSmrg        SetResourceTypeErrorValue(XRT_COLORMAP, BadColor);
51505b261ecSmrg    }
51605b261ecSmrg
51705b261ecSmrg    if (!success) {
51835c4bbdfSmrg        noPanoramiXExtension = TRUE;
51935c4bbdfSmrg        ErrorF(PANORAMIX_PROTOCOL_NAME " extension failed to initialize\n");
52035c4bbdfSmrg        return;
52105b261ecSmrg    }
52235c4bbdfSmrg
52335c4bbdfSmrg    XineramaInitData();
52405b261ecSmrg
52505b261ecSmrg    /*
52635c4bbdfSmrg     *  Put our processes into the ProcVector
52705b261ecSmrg     */
52805b261ecSmrg
52935c4bbdfSmrg    for (i = 256; i--;)
53035c4bbdfSmrg        SavedProcVector[i] = ProcVector[i];
53105b261ecSmrg
53205b261ecSmrg    ProcVector[X_CreateWindow] = PanoramiXCreateWindow;
53305b261ecSmrg    ProcVector[X_ChangeWindowAttributes] = PanoramiXChangeWindowAttributes;
53405b261ecSmrg    ProcVector[X_DestroyWindow] = PanoramiXDestroyWindow;
53505b261ecSmrg    ProcVector[X_DestroySubwindows] = PanoramiXDestroySubwindows;
53605b261ecSmrg    ProcVector[X_ChangeSaveSet] = PanoramiXChangeSaveSet;
53705b261ecSmrg    ProcVector[X_ReparentWindow] = PanoramiXReparentWindow;
53805b261ecSmrg    ProcVector[X_MapWindow] = PanoramiXMapWindow;
53905b261ecSmrg    ProcVector[X_MapSubwindows] = PanoramiXMapSubwindows;
54005b261ecSmrg    ProcVector[X_UnmapWindow] = PanoramiXUnmapWindow;
54105b261ecSmrg    ProcVector[X_UnmapSubwindows] = PanoramiXUnmapSubwindows;
54205b261ecSmrg    ProcVector[X_ConfigureWindow] = PanoramiXConfigureWindow;
54305b261ecSmrg    ProcVector[X_CirculateWindow] = PanoramiXCirculateWindow;
54405b261ecSmrg    ProcVector[X_GetGeometry] = PanoramiXGetGeometry;
54505b261ecSmrg    ProcVector[X_TranslateCoords] = PanoramiXTranslateCoords;
54605b261ecSmrg    ProcVector[X_CreatePixmap] = PanoramiXCreatePixmap;
54705b261ecSmrg    ProcVector[X_FreePixmap] = PanoramiXFreePixmap;
54805b261ecSmrg    ProcVector[X_CreateGC] = PanoramiXCreateGC;
54905b261ecSmrg    ProcVector[X_ChangeGC] = PanoramiXChangeGC;
55005b261ecSmrg    ProcVector[X_CopyGC] = PanoramiXCopyGC;
55105b261ecSmrg    ProcVector[X_SetDashes] = PanoramiXSetDashes;
55205b261ecSmrg    ProcVector[X_SetClipRectangles] = PanoramiXSetClipRectangles;
55305b261ecSmrg    ProcVector[X_FreeGC] = PanoramiXFreeGC;
55405b261ecSmrg    ProcVector[X_ClearArea] = PanoramiXClearToBackground;
5554642e01fSmrg    ProcVector[X_CopyArea] = PanoramiXCopyArea;
5564642e01fSmrg    ProcVector[X_CopyPlane] = PanoramiXCopyPlane;
55705b261ecSmrg    ProcVector[X_PolyPoint] = PanoramiXPolyPoint;
55805b261ecSmrg    ProcVector[X_PolyLine] = PanoramiXPolyLine;
55905b261ecSmrg    ProcVector[X_PolySegment] = PanoramiXPolySegment;
56005b261ecSmrg    ProcVector[X_PolyRectangle] = PanoramiXPolyRectangle;
56105b261ecSmrg    ProcVector[X_PolyArc] = PanoramiXPolyArc;
56205b261ecSmrg    ProcVector[X_FillPoly] = PanoramiXFillPoly;
56305b261ecSmrg    ProcVector[X_PolyFillRectangle] = PanoramiXPolyFillRectangle;
56405b261ecSmrg    ProcVector[X_PolyFillArc] = PanoramiXPolyFillArc;
56505b261ecSmrg    ProcVector[X_PutImage] = PanoramiXPutImage;
56605b261ecSmrg    ProcVector[X_GetImage] = PanoramiXGetImage;
56705b261ecSmrg    ProcVector[X_PolyText8] = PanoramiXPolyText8;
56805b261ecSmrg    ProcVector[X_PolyText16] = PanoramiXPolyText16;
56905b261ecSmrg    ProcVector[X_ImageText8] = PanoramiXImageText8;
57005b261ecSmrg    ProcVector[X_ImageText16] = PanoramiXImageText16;
57105b261ecSmrg    ProcVector[X_CreateColormap] = PanoramiXCreateColormap;
57205b261ecSmrg    ProcVector[X_FreeColormap] = PanoramiXFreeColormap;
57305b261ecSmrg    ProcVector[X_CopyColormapAndFree] = PanoramiXCopyColormapAndFree;
57405b261ecSmrg    ProcVector[X_InstallColormap] = PanoramiXInstallColormap;
57505b261ecSmrg    ProcVector[X_UninstallColormap] = PanoramiXUninstallColormap;
57605b261ecSmrg    ProcVector[X_AllocColor] = PanoramiXAllocColor;
57705b261ecSmrg    ProcVector[X_AllocNamedColor] = PanoramiXAllocNamedColor;
57805b261ecSmrg    ProcVector[X_AllocColorCells] = PanoramiXAllocColorCells;
5794642e01fSmrg    ProcVector[X_AllocColorPlanes] = PanoramiXAllocColorPlanes;
58005b261ecSmrg    ProcVector[X_FreeColors] = PanoramiXFreeColors;
5814642e01fSmrg    ProcVector[X_StoreColors] = PanoramiXStoreColors;
5824642e01fSmrg    ProcVector[X_StoreNamedColor] = PanoramiXStoreNamedColor;
58305b261ecSmrg
58435c4bbdfSmrg    PanoramiXRenderInit();
58535c4bbdfSmrg    PanoramiXFixesInit();
58635c4bbdfSmrg    PanoramiXDamageInit();
5879ace9065Smrg#ifdef COMPOSITE
58835c4bbdfSmrg    PanoramiXCompositeInit();
5899ace9065Smrg#endif
5909ace9065Smrg
59105b261ecSmrg}
59205b261ecSmrg
59335c4bbdfSmrgBool
59435c4bbdfSmrgPanoramiXCreateConnectionBlock(void)
59505b261ecSmrg{
59605b261ecSmrg    int i, j, length;
59735c4bbdfSmrg    Bool disable_backing_store = FALSE;
59805b261ecSmrg    int old_width, old_height;
59905b261ecSmrg    float width_mult, height_mult;
60005b261ecSmrg    xWindowRoot *root;
60105b261ecSmrg    xVisualType *visual;
60205b261ecSmrg    xDepth *depth;
60305b261ecSmrg    VisualPtr pVisual;
60405b261ecSmrg    ScreenPtr pScreen;
60505b261ecSmrg
60605b261ecSmrg    /*
60735c4bbdfSmrg     *  Do normal CreateConnectionBlock but faking it for only one screen
60805b261ecSmrg     */
60905b261ecSmrg
61035c4bbdfSmrg    if (!PanoramiXNumDepths) {
61135c4bbdfSmrg        ErrorF("Xinerama error: No common visuals\n");
61235c4bbdfSmrg        return FALSE;
61305b261ecSmrg    }
61405b261ecSmrg
61535c4bbdfSmrg    for (i = 1; i < screenInfo.numScreens; i++) {
61635c4bbdfSmrg        pScreen = screenInfo.screens[i];
61735c4bbdfSmrg        if (pScreen->rootDepth != screenInfo.screens[0]->rootDepth) {
61835c4bbdfSmrg            ErrorF("Xinerama error: Root window depths differ\n");
61935c4bbdfSmrg            return FALSE;
62035c4bbdfSmrg        }
62135c4bbdfSmrg        if (pScreen->backingStoreSupport !=
62235c4bbdfSmrg            screenInfo.screens[0]->backingStoreSupport)
62335c4bbdfSmrg            disable_backing_store = TRUE;
62405b261ecSmrg    }
62505b261ecSmrg
62635c4bbdfSmrg    if (disable_backing_store) {
62735c4bbdfSmrg        for (i = 0; i < screenInfo.numScreens; i++) {
62835c4bbdfSmrg            pScreen = screenInfo.screens[i];
62935c4bbdfSmrg            pScreen->backingStoreSupport = NotUseful;
63035c4bbdfSmrg        }
63105b261ecSmrg    }
63205b261ecSmrg
63305b261ecSmrg    i = screenInfo.numScreens;
63405b261ecSmrg    screenInfo.numScreens = 1;
63505b261ecSmrg    if (!CreateConnectionBlock()) {
63635c4bbdfSmrg        screenInfo.numScreens = i;
63735c4bbdfSmrg        return FALSE;
63805b261ecSmrg    }
63905b261ecSmrg
64005b261ecSmrg    screenInfo.numScreens = i;
64135c4bbdfSmrg
64205b261ecSmrg    root = (xWindowRoot *) (ConnectionInfo + connBlockScreenStart);
64305b261ecSmrg    length = connBlockScreenStart + sizeof(xWindowRoot);
64405b261ecSmrg
64505b261ecSmrg    /* overwrite the connection block */
64605b261ecSmrg    root->nDepths = PanoramiXNumDepths;
64705b261ecSmrg
64805b261ecSmrg    for (i = 0; i < PanoramiXNumDepths; i++) {
64935c4bbdfSmrg        depth = (xDepth *) (ConnectionInfo + length);
65035c4bbdfSmrg        depth->depth = PanoramiXDepths[i].depth;
65135c4bbdfSmrg        depth->nVisuals = PanoramiXDepths[i].numVids;
65235c4bbdfSmrg        length += sizeof(xDepth);
65335c4bbdfSmrg        visual = (xVisualType *) (ConnectionInfo + length);
65435c4bbdfSmrg
65535c4bbdfSmrg        for (j = 0; j < depth->nVisuals; j++, visual++) {
65635c4bbdfSmrg            visual->visualID = PanoramiXDepths[i].vids[j];
65735c4bbdfSmrg
65835c4bbdfSmrg            for (pVisual = PanoramiXVisuals;
65935c4bbdfSmrg                 pVisual->vid != visual->visualID; pVisual++);
66035c4bbdfSmrg
66135c4bbdfSmrg            visual->class = pVisual->class;
66235c4bbdfSmrg            visual->bitsPerRGB = pVisual->bitsPerRGBValue;
66335c4bbdfSmrg            visual->colormapEntries = pVisual->ColormapEntries;
66435c4bbdfSmrg            visual->redMask = pVisual->redMask;
66535c4bbdfSmrg            visual->greenMask = pVisual->greenMask;
66635c4bbdfSmrg            visual->blueMask = pVisual->blueMask;
66735c4bbdfSmrg        }
66835c4bbdfSmrg
66935c4bbdfSmrg        length += (depth->nVisuals * sizeof(xVisualType));
67005b261ecSmrg    }
67105b261ecSmrg
6726747b715Smrg    connSetupPrefix.length = bytes_to_int32(length);
67305b261ecSmrg
67405b261ecSmrg    for (i = 0; i < PanoramiXNumDepths; i++)
67535c4bbdfSmrg        free(PanoramiXDepths[i].vids);
6766747b715Smrg    free(PanoramiXDepths);
6774642e01fSmrg    PanoramiXDepths = NULL;
67805b261ecSmrg
67905b261ecSmrg    /*
68005b261ecSmrg     *  OK, change some dimensions so it looks as if it were one big screen
68105b261ecSmrg     */
68235c4bbdfSmrg
68305b261ecSmrg    old_width = root->pixWidth;
68405b261ecSmrg    old_height = root->pixHeight;
68505b261ecSmrg
68605b261ecSmrg    root->pixWidth = PanoramiXPixWidth;
68705b261ecSmrg    root->pixHeight = PanoramiXPixHeight;
68805b261ecSmrg    width_mult = (1.0 * root->pixWidth) / old_width;
68905b261ecSmrg    height_mult = (1.0 * root->pixHeight) / old_height;
69005b261ecSmrg    root->mmWidth *= width_mult;
69105b261ecSmrg    root->mmHeight *= height_mult;
69205b261ecSmrg
69335c4bbdfSmrg    while (ConnectionCallbackList) {
69435c4bbdfSmrg        void *tmp;
69505b261ecSmrg
69635c4bbdfSmrg        tmp = (void *) ConnectionCallbackList;
69735c4bbdfSmrg        (*ConnectionCallbackList->func) ();
69835c4bbdfSmrg        ConnectionCallbackList = ConnectionCallbackList->next;
69935c4bbdfSmrg        free(tmp);
70005b261ecSmrg    }
70105b261ecSmrg
70205b261ecSmrg    return TRUE;
70305b261ecSmrg}
70405b261ecSmrg
7054642e01fSmrg/*
7064642e01fSmrg * This isn't just memcmp(), bitsPerRGBValue is skipped.  markv made that
7074642e01fSmrg * change way back before xf86 4.0, but the comment for _why_ is a bit
7084642e01fSmrg * opaque, so I'm not going to question it for now.
7094642e01fSmrg *
7104642e01fSmrg * This is probably better done as a screen hook so DBE/EVI/GLX can add
7114642e01fSmrg * their own tests, and adding privates to VisualRec so they don't have to
7124642e01fSmrg * do their own back-mapping.
7134642e01fSmrg */
7144642e01fSmrgstatic Bool
7154642e01fSmrgVisualsEqual(VisualPtr a, ScreenPtr pScreenB, VisualPtr b)
71605b261ecSmrg{
7174642e01fSmrg    return ((a->class == b->class) &&
71835c4bbdfSmrg            (a->ColormapEntries == b->ColormapEntries) &&
71935c4bbdfSmrg            (a->nplanes == b->nplanes) &&
72035c4bbdfSmrg            (a->redMask == b->redMask) &&
72135c4bbdfSmrg            (a->greenMask == b->greenMask) &&
72235c4bbdfSmrg            (a->blueMask == b->blueMask) &&
72335c4bbdfSmrg            (a->offsetRed == b->offsetRed) &&
72435c4bbdfSmrg            (a->offsetGreen == b->offsetGreen) &&
72535c4bbdfSmrg            (a->offsetBlue == b->offsetBlue));
7264642e01fSmrg}
72705b261ecSmrg
7284642e01fSmrgstatic void
7294642e01fSmrgPanoramiXMaybeAddDepth(DepthPtr pDepth)
7304642e01fSmrg{
7314642e01fSmrg    ScreenPtr pScreen;
7324642e01fSmrg    int j, k;
7334642e01fSmrg    Bool found = FALSE;
7344642e01fSmrg
73535c4bbdfSmrg    FOR_NSCREENS_FORWARD_SKIP(j) {
73635c4bbdfSmrg        pScreen = screenInfo.screens[j];
73735c4bbdfSmrg        for (k = 0; k < pScreen->numDepths; k++) {
73835c4bbdfSmrg            if (pScreen->allowedDepths[k].depth == pDepth->depth) {
73935c4bbdfSmrg                found = TRUE;
74035c4bbdfSmrg                break;
74135c4bbdfSmrg            }
74235c4bbdfSmrg        }
7434642e01fSmrg    }
74405b261ecSmrg
7454642e01fSmrg    if (!found)
74635c4bbdfSmrg        return;
74705b261ecSmrg
7484642e01fSmrg    j = PanoramiXNumDepths;
7494642e01fSmrg    PanoramiXNumDepths++;
75035c4bbdfSmrg    PanoramiXDepths = reallocarray(PanoramiXDepths,
75135c4bbdfSmrg                                   PanoramiXNumDepths, sizeof(DepthRec));
7524642e01fSmrg    PanoramiXDepths[j].depth = pDepth->depth;
7534642e01fSmrg    PanoramiXDepths[j].numVids = 0;
7547e31ba66Smrg    PanoramiXDepths[j].vids = NULL;
7554642e01fSmrg}
7564642e01fSmrg
7574642e01fSmrgstatic void
7584642e01fSmrgPanoramiXMaybeAddVisual(VisualPtr pVisual)
7594642e01fSmrg{
7604642e01fSmrg    ScreenPtr pScreen;
7614642e01fSmrg    int j, k;
7624642e01fSmrg    Bool found = FALSE;
76305b261ecSmrg
76435c4bbdfSmrg    FOR_NSCREENS_FORWARD_SKIP(j) {
76535c4bbdfSmrg        pScreen = screenInfo.screens[j];
76635c4bbdfSmrg        found = FALSE;
76705b261ecSmrg
76835c4bbdfSmrg        for (k = 0; k < pScreen->numVisuals; k++) {
76935c4bbdfSmrg            VisualPtr candidate = &pScreen->visuals[k];
77005b261ecSmrg
77135c4bbdfSmrg            if ((*XineramaVisualsEqualPtr) (pVisual, pScreen, candidate)
77205b261ecSmrg#ifdef GLXPROXY
77335c4bbdfSmrg                && glxMatchVisual(screenInfo.screens[0], pVisual, pScreen)
77405b261ecSmrg#endif
77535c4bbdfSmrg                ) {
77635c4bbdfSmrg                found = TRUE;
77735c4bbdfSmrg                break;
77835c4bbdfSmrg            }
77935c4bbdfSmrg        }
78035c4bbdfSmrg
78135c4bbdfSmrg        if (!found)
78235c4bbdfSmrg            return;
7834642e01fSmrg    }
7844642e01fSmrg
7854642e01fSmrg    /* found a matching visual on all screens, add it to the subset list */
7864642e01fSmrg    j = PanoramiXNumVisuals;
7874642e01fSmrg    PanoramiXNumVisuals++;
78835c4bbdfSmrg    PanoramiXVisuals = reallocarray(PanoramiXVisuals,
78935c4bbdfSmrg                                    PanoramiXNumVisuals, sizeof(VisualRec));
7904642e01fSmrg
7914642e01fSmrg    memcpy(&PanoramiXVisuals[j], pVisual, sizeof(VisualRec));
7924642e01fSmrg
7934642e01fSmrg    for (k = 0; k < PanoramiXNumDepths; k++) {
79435c4bbdfSmrg        if (PanoramiXDepths[k].depth == pVisual->nplanes) {
7957e31ba66Smrg            PanoramiXDepths[k].vids = reallocarray(PanoramiXDepths[k].vids,
7967e31ba66Smrg                                                   PanoramiXDepths[k].numVids + 1,
7977e31ba66Smrg                                                   sizeof(VisualID));
79835c4bbdfSmrg            PanoramiXDepths[k].vids[PanoramiXDepths[k].numVids] = pVisual->vid;
79935c4bbdfSmrg            PanoramiXDepths[k].numVids++;
80035c4bbdfSmrg            break;
80135c4bbdfSmrg        }
80235c4bbdfSmrg    }
8034642e01fSmrg}
8044642e01fSmrg
8054642e01fSmrgextern void
8064642e01fSmrgPanoramiXConsolidate(void)
8074642e01fSmrg{
80835c4bbdfSmrg    int i;
8094642e01fSmrg    PanoramiXRes *root, *defmap, *saver;
81035c4bbdfSmrg    ScreenPtr pScreen = screenInfo.screens[0];
81135c4bbdfSmrg    DepthPtr pDepth = pScreen->allowedDepths;
81235c4bbdfSmrg    VisualPtr pVisual = pScreen->visuals;
8134642e01fSmrg
8144642e01fSmrg    PanoramiXNumDepths = 0;
8154642e01fSmrg    PanoramiXNumVisuals = 0;
81605b261ecSmrg
8174642e01fSmrg    for (i = 0; i < pScreen->numDepths; i++)
81835c4bbdfSmrg        PanoramiXMaybeAddDepth(pDepth++);
81905b261ecSmrg
8204642e01fSmrg    for (i = 0; i < pScreen->numVisuals; i++)
82135c4bbdfSmrg        PanoramiXMaybeAddVisual(pVisual++);
8224642e01fSmrg
8236747b715Smrg    root = malloc(sizeof(PanoramiXRes));
82405b261ecSmrg    root->type = XRT_WINDOW;
8256747b715Smrg    defmap = malloc(sizeof(PanoramiXRes));
82605b261ecSmrg    defmap->type = XRT_COLORMAP;
8276747b715Smrg    saver = malloc(sizeof(PanoramiXRes));
82805b261ecSmrg    saver->type = XRT_WINDOW;
82905b261ecSmrg
83035c4bbdfSmrg    FOR_NSCREENS(i) {
83135c4bbdfSmrg        ScreenPtr scr = screenInfo.screens[i];
83235c4bbdfSmrg
83335c4bbdfSmrg        root->info[i].id = scr->root->drawable.id;
83435c4bbdfSmrg        root->u.win.class = InputOutput;
83505b261ecSmrg        root->u.win.root = TRUE;
83635c4bbdfSmrg        saver->info[i].id = scr->screensaver.wid;
83705b261ecSmrg        saver->u.win.class = InputOutput;
83805b261ecSmrg        saver->u.win.root = TRUE;
83935c4bbdfSmrg        defmap->info[i].id = scr->defColormap;
84005b261ecSmrg    }
84105b261ecSmrg
84205b261ecSmrg    AddResource(root->info[0].id, XRT_WINDOW, root);
84305b261ecSmrg    AddResource(saver->info[0].id, XRT_WINDOW, saver);
84405b261ecSmrg    AddResource(defmap->info[0].id, XRT_COLORMAP, defmap);
84505b261ecSmrg}
84605b261ecSmrg
8476747b715SmrgVisualID
8484642e01fSmrgPanoramiXTranslateVisualID(int screen, VisualID orig)
8494642e01fSmrg{
8504642e01fSmrg    ScreenPtr pOtherScreen = screenInfo.screens[screen];
8514642e01fSmrg    VisualPtr pVisual = NULL;
8524642e01fSmrg    int i;
8534642e01fSmrg
8544642e01fSmrg    for (i = 0; i < PanoramiXNumVisuals; i++) {
85535c4bbdfSmrg        if (orig == PanoramiXVisuals[i].vid) {
85635c4bbdfSmrg            pVisual = &PanoramiXVisuals[i];
85735c4bbdfSmrg            break;
85835c4bbdfSmrg        }
8594642e01fSmrg    }
8604642e01fSmrg
8614642e01fSmrg    if (!pVisual)
86235c4bbdfSmrg        return 0;
8634642e01fSmrg
8644642e01fSmrg    /* if screen is 0, orig is already the correct visual ID */
8654642e01fSmrg    if (screen == 0)
86635c4bbdfSmrg        return orig;
8674642e01fSmrg
8684642e01fSmrg    /* found the original, now translate it relative to the backend screen */
8694642e01fSmrg    for (i = 0; i < pOtherScreen->numVisuals; i++) {
87035c4bbdfSmrg        VisualPtr pOtherVisual = &pOtherScreen->visuals[i];
8714642e01fSmrg
87235c4bbdfSmrg        if ((*XineramaVisualsEqualPtr) (pVisual, pOtherScreen, pOtherVisual))
87335c4bbdfSmrg            return pOtherVisual->vid;
8744642e01fSmrg    }
8754642e01fSmrg
8764642e01fSmrg    return 0;
8774642e01fSmrg}
8784642e01fSmrg
87905b261ecSmrg/*
88005b261ecSmrg *	PanoramiXResetProc()
88105b261ecSmrg *		Exit, deallocating as needed.
88205b261ecSmrg */
88305b261ecSmrg
88435c4bbdfSmrgstatic void
88535c4bbdfSmrgPanoramiXResetProc(ExtensionEntry * extEntry)
88605b261ecSmrg{
88735c4bbdfSmrg    int i;
88805b261ecSmrg
88935c4bbdfSmrg    PanoramiXRenderReset();
89035c4bbdfSmrg    PanoramiXFixesReset();
89135c4bbdfSmrg    PanoramiXDamageReset();
89235c4bbdfSmrg#ifdef COMPOSITE
89335c4bbdfSmrg    PanoramiXCompositeReset ();
8949ace9065Smrg#endif
89505b261ecSmrg    screenInfo.numScreens = PanoramiXNumScreens;
89635c4bbdfSmrg    for (i = 256; i--;)
89735c4bbdfSmrg        ProcVector[i] = SavedProcVector[i];
89805b261ecSmrg}
89905b261ecSmrg
90005b261ecSmrgint
90135c4bbdfSmrgProcPanoramiXQueryVersion(ClientPtr client)
90205b261ecSmrg{
90305b261ecSmrg    /* REQUEST(xPanoramiXQueryVersionReq); */
90435c4bbdfSmrg    xPanoramiXQueryVersionReply rep = {
90535c4bbdfSmrg        .type = X_Reply,
90635c4bbdfSmrg        .sequenceNumber = client->sequence,
90735c4bbdfSmrg        .length = 0,
90835c4bbdfSmrg        .majorVersion = SERVER_PANORAMIX_MAJOR_VERSION,
90935c4bbdfSmrg        .minorVersion = SERVER_PANORAMIX_MINOR_VERSION
91035c4bbdfSmrg    };
91135c4bbdfSmrg
91235c4bbdfSmrg    REQUEST_SIZE_MATCH(xPanoramiXQueryVersionReq);
91335c4bbdfSmrg    if (client->swapped) {
91435c4bbdfSmrg        swaps(&rep.sequenceNumber);
91535c4bbdfSmrg        swapl(&rep.length);
91635c4bbdfSmrg        swaps(&rep.majorVersion);
91735c4bbdfSmrg        swaps(&rep.minorVersion);
91805b261ecSmrg    }
91935c4bbdfSmrg    WriteToClient(client, sizeof(xPanoramiXQueryVersionReply), &rep);
9206747b715Smrg    return Success;
92105b261ecSmrg}
92205b261ecSmrg
92305b261ecSmrgint
92405b261ecSmrgProcPanoramiXGetState(ClientPtr client)
92505b261ecSmrg{
92635c4bbdfSmrg    REQUEST(xPanoramiXGetStateReq);
92735c4bbdfSmrg    WindowPtr pWin;
92835c4bbdfSmrg    xPanoramiXGetStateReply rep;
92935c4bbdfSmrg    int rc;
93035c4bbdfSmrg
93135c4bbdfSmrg    REQUEST_SIZE_MATCH(xPanoramiXGetStateReq);
93235c4bbdfSmrg    rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
93335c4bbdfSmrg    if (rc != Success)
93435c4bbdfSmrg        return rc;
93535c4bbdfSmrg
93635c4bbdfSmrg    rep = (xPanoramiXGetStateReply) {
93735c4bbdfSmrg        .type = X_Reply,
93835c4bbdfSmrg        .state = !noPanoramiXExtension,
93935c4bbdfSmrg        .sequenceNumber = client->sequence,
94035c4bbdfSmrg        .length = 0,
94135c4bbdfSmrg        .window = stuff->window
94235c4bbdfSmrg    };
94335c4bbdfSmrg    if (client->swapped) {
94435c4bbdfSmrg        swaps(&rep.sequenceNumber);
94535c4bbdfSmrg        swapl(&rep.length);
94635c4bbdfSmrg        swapl(&rep.window);
94735c4bbdfSmrg    }
94835c4bbdfSmrg    WriteToClient(client, sizeof(xPanoramiXGetStateReply), &rep);
94935c4bbdfSmrg    return Success;
95005b261ecSmrg
95105b261ecSmrg}
95205b261ecSmrg
95335c4bbdfSmrgint
95405b261ecSmrgProcPanoramiXGetScreenCount(ClientPtr client)
95505b261ecSmrg{
95635c4bbdfSmrg    REQUEST(xPanoramiXGetScreenCountReq);
95735c4bbdfSmrg    WindowPtr pWin;
95835c4bbdfSmrg    xPanoramiXGetScreenCountReply rep;
95935c4bbdfSmrg    int rc;
96035c4bbdfSmrg
96135c4bbdfSmrg    REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq);
96235c4bbdfSmrg    rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
96335c4bbdfSmrg    if (rc != Success)
96435c4bbdfSmrg        return rc;
96535c4bbdfSmrg
96635c4bbdfSmrg    rep = (xPanoramiXGetScreenCountReply) {
96735c4bbdfSmrg        .type = X_Reply,
96835c4bbdfSmrg        .ScreenCount = PanoramiXNumScreens,
96935c4bbdfSmrg        .sequenceNumber = client->sequence,
97035c4bbdfSmrg        .length = 0,
97135c4bbdfSmrg        .window = stuff->window
97235c4bbdfSmrg    };
97335c4bbdfSmrg    if (client->swapped) {
97435c4bbdfSmrg        swaps(&rep.sequenceNumber);
97535c4bbdfSmrg        swapl(&rep.length);
97635c4bbdfSmrg        swapl(&rep.window);
97735c4bbdfSmrg    }
97835c4bbdfSmrg    WriteToClient(client, sizeof(xPanoramiXGetScreenCountReply), &rep);
97935c4bbdfSmrg    return Success;
98005b261ecSmrg}
98105b261ecSmrg
98235c4bbdfSmrgint
98305b261ecSmrgProcPanoramiXGetScreenSize(ClientPtr client)
98405b261ecSmrg{
98535c4bbdfSmrg    REQUEST(xPanoramiXGetScreenSizeReq);
98635c4bbdfSmrg    WindowPtr pWin;
98735c4bbdfSmrg    xPanoramiXGetScreenSizeReply rep;
98835c4bbdfSmrg    int rc;
98935c4bbdfSmrg
9906e78d31fSmrg    REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq);
9916e78d31fSmrg
99235c4bbdfSmrg    if (stuff->screen >= PanoramiXNumScreens)
99335c4bbdfSmrg        return BadMatch;
99435c4bbdfSmrg
99535c4bbdfSmrg    rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
99635c4bbdfSmrg    if (rc != Success)
99735c4bbdfSmrg        return rc;
99835c4bbdfSmrg
99935c4bbdfSmrg    rep = (xPanoramiXGetScreenSizeReply) {
100035c4bbdfSmrg        .type = X_Reply,
100135c4bbdfSmrg        .sequenceNumber = client->sequence,
100235c4bbdfSmrg        .length = 0,
100335c4bbdfSmrg    /* screen dimensions */
100435c4bbdfSmrg        .width = screenInfo.screens[stuff->screen]->width,
100535c4bbdfSmrg        .height = screenInfo.screens[stuff->screen]->height,
100635c4bbdfSmrg        .window = stuff->window,
100735c4bbdfSmrg        .screen = stuff->screen
100835c4bbdfSmrg    };
100935c4bbdfSmrg    if (client->swapped) {
101035c4bbdfSmrg        swaps(&rep.sequenceNumber);
101135c4bbdfSmrg        swapl(&rep.length);
101235c4bbdfSmrg        swapl(&rep.width);
101335c4bbdfSmrg        swapl(&rep.height);
101435c4bbdfSmrg        swapl(&rep.window);
101535c4bbdfSmrg        swapl(&rep.screen);
101635c4bbdfSmrg    }
101735c4bbdfSmrg    WriteToClient(client, sizeof(xPanoramiXGetScreenSizeReply), &rep);
101835c4bbdfSmrg    return Success;
101905b261ecSmrg}
102005b261ecSmrg
102105b261ecSmrgint
102205b261ecSmrgProcXineramaIsActive(ClientPtr client)
102305b261ecSmrg{
102405b261ecSmrg    /* REQUEST(xXineramaIsActiveReq); */
102535c4bbdfSmrg    xXineramaIsActiveReply rep;
102605b261ecSmrg
102705b261ecSmrg    REQUEST_SIZE_MATCH(xXineramaIsActiveReq);
102805b261ecSmrg
102935c4bbdfSmrg    rep = (xXineramaIsActiveReply) {
103035c4bbdfSmrg        .type = X_Reply,
103135c4bbdfSmrg        .sequenceNumber = client->sequence,
103235c4bbdfSmrg        .length = 0,
103305b261ecSmrg#if 1
103435c4bbdfSmrg        /* The following hack fools clients into thinking that Xinerama
103535c4bbdfSmrg         * is disabled even though it is not. */
103635c4bbdfSmrg        .state = !noPanoramiXExtension && !PanoramiXExtensionDisabledHack
103705b261ecSmrg#else
103835c4bbdfSmrg        .state = !noPanoramiXExtension;
103905b261ecSmrg#endif
104035c4bbdfSmrg    };
104105b261ecSmrg    if (client->swapped) {
104235c4bbdfSmrg        swaps(&rep.sequenceNumber);
104335c4bbdfSmrg        swapl(&rep.length);
104435c4bbdfSmrg        swapl(&rep.state);
104535c4bbdfSmrg    }
104635c4bbdfSmrg    WriteToClient(client, sizeof(xXineramaIsActiveReply), &rep);
10476747b715Smrg    return Success;
104805b261ecSmrg}
104905b261ecSmrg
105005b261ecSmrgint
105105b261ecSmrgProcXineramaQueryScreens(ClientPtr client)
105205b261ecSmrg{
105305b261ecSmrg    /* REQUEST(xXineramaQueryScreensReq); */
105435c4bbdfSmrg    CARD32 number = (noPanoramiXExtension) ? 0 : PanoramiXNumScreens;
105535c4bbdfSmrg    xXineramaQueryScreensReply rep = {
105635c4bbdfSmrg        .type = X_Reply,
105735c4bbdfSmrg        .sequenceNumber = client->sequence,
105835c4bbdfSmrg        .length = bytes_to_int32(number * sz_XineramaScreenInfo),
105935c4bbdfSmrg        .number = number
106035c4bbdfSmrg    };
106105b261ecSmrg
106205b261ecSmrg    REQUEST_SIZE_MATCH(xXineramaQueryScreensReq);
106305b261ecSmrg
106405b261ecSmrg    if (client->swapped) {
106535c4bbdfSmrg        swaps(&rep.sequenceNumber);
106635c4bbdfSmrg        swapl(&rep.length);
106735c4bbdfSmrg        swapl(&rep.number);
106835c4bbdfSmrg    }
106935c4bbdfSmrg    WriteToClient(client, sizeof(xXineramaQueryScreensReply), &rep);
107035c4bbdfSmrg
107135c4bbdfSmrg    if (!noPanoramiXExtension) {
107235c4bbdfSmrg        xXineramaScreenInfo scratch;
107335c4bbdfSmrg        int i;
107435c4bbdfSmrg
107535c4bbdfSmrg        FOR_NSCREENS(i) {
107635c4bbdfSmrg            scratch.x_org = screenInfo.screens[i]->x;
107735c4bbdfSmrg            scratch.y_org = screenInfo.screens[i]->y;
107835c4bbdfSmrg            scratch.width = screenInfo.screens[i]->width;
107935c4bbdfSmrg            scratch.height = screenInfo.screens[i]->height;
108035c4bbdfSmrg
108135c4bbdfSmrg            if (client->swapped) {
108235c4bbdfSmrg                swaps(&scratch.x_org);
108335c4bbdfSmrg                swaps(&scratch.y_org);
108435c4bbdfSmrg                swaps(&scratch.width);
108535c4bbdfSmrg                swaps(&scratch.height);
108635c4bbdfSmrg            }
108735c4bbdfSmrg            WriteToClient(client, sz_XineramaScreenInfo, &scratch);
108835c4bbdfSmrg        }
108905b261ecSmrg    }
109005b261ecSmrg
10916747b715Smrg    return Success;
109205b261ecSmrg}
109305b261ecSmrg
109405b261ecSmrgstatic int
109535c4bbdfSmrgProcPanoramiXDispatch(ClientPtr client)
109635c4bbdfSmrg{
109735c4bbdfSmrg    REQUEST(xReq);
109835c4bbdfSmrg    switch (stuff->data) {
109935c4bbdfSmrg    case X_PanoramiXQueryVersion:
110035c4bbdfSmrg        return ProcPanoramiXQueryVersion(client);
110135c4bbdfSmrg    case X_PanoramiXGetState:
110235c4bbdfSmrg        return ProcPanoramiXGetState(client);
110335c4bbdfSmrg    case X_PanoramiXGetScreenCount:
110435c4bbdfSmrg        return ProcPanoramiXGetScreenCount(client);
110535c4bbdfSmrg    case X_PanoramiXGetScreenSize:
110635c4bbdfSmrg        return ProcPanoramiXGetScreenSize(client);
110735c4bbdfSmrg    case X_XineramaIsActive:
110835c4bbdfSmrg        return ProcXineramaIsActive(client);
110935c4bbdfSmrg    case X_XineramaQueryScreens:
111035c4bbdfSmrg        return ProcXineramaQueryScreens(client);
111105b261ecSmrg    }
111205b261ecSmrg    return BadRequest;
111305b261ecSmrg}
111405b261ecSmrg
111505b261ecSmrg#if X_BYTE_ORDER == X_LITTLE_ENDIAN
111605b261ecSmrg#define SHIFT_L(v,s) (v) << (s)
111705b261ecSmrg#define SHIFT_R(v,s) (v) >> (s)
111805b261ecSmrg#else
111905b261ecSmrg#define SHIFT_L(v,s) (v) >> (s)
112005b261ecSmrg#define SHIFT_R(v,s) (v) << (s)
112105b261ecSmrg#endif
112205b261ecSmrg
112305b261ecSmrgstatic void
112405b261ecSmrgCopyBits(char *dst, int shiftL, char *src, int bytes)
112505b261ecSmrg{
112635c4bbdfSmrg    /* Just get it to work.  Worry about speed later */
112705b261ecSmrg    int shiftR = 8 - shiftL;
112805b261ecSmrg
112935c4bbdfSmrg    while (bytes--) {
113035c4bbdfSmrg        *dst |= SHIFT_L(*src, shiftL);
113135c4bbdfSmrg        *(dst + 1) |= SHIFT_R(*src, shiftR);
113235c4bbdfSmrg        dst++;
113335c4bbdfSmrg        src++;
113435c4bbdfSmrg    }
113505b261ecSmrg}
113605b261ecSmrg
113705b261ecSmrg/* Caution.  This doesn't support 2 and 4 bpp formats.  We expect
113805b261ecSmrg   1 bpp and planar data to be already cleared when presented
113905b261ecSmrg   to this function */
114005b261ecSmrg
114105b261ecSmrgvoid
114235c4bbdfSmrgXineramaGetImageData(DrawablePtr *pDrawables,
114335c4bbdfSmrg                     int left,
114435c4bbdfSmrg                     int top,
114535c4bbdfSmrg                     int width,
114635c4bbdfSmrg                     int height,
114735c4bbdfSmrg                     unsigned int format,
114835c4bbdfSmrg                     unsigned long planemask,
114935c4bbdfSmrg                     char *data, int pitch, Bool isRoot)
115035c4bbdfSmrg{
11516747b715Smrg    RegionRec SrcRegion, ScreenRegion, GrabRegion;
115205b261ecSmrg    BoxRec SrcBox, *pbox;
115305b261ecSmrg    int x, y, w, h, i, j, nbox, size, sizeNeeded, ScratchPitch, inOut, depth;
115405b261ecSmrg    DrawablePtr pDraw = pDrawables[0];
115505b261ecSmrg    char *ScratchMem = NULL;
115605b261ecSmrg
115705b261ecSmrg    size = 0;
115805b261ecSmrg
115905b261ecSmrg    /* find box in logical screen space */
116005b261ecSmrg    SrcBox.x1 = left;
116105b261ecSmrg    SrcBox.y1 = top;
116235c4bbdfSmrg    if (!isRoot) {
116335c4bbdfSmrg        SrcBox.x1 += pDraw->x + screenInfo.screens[0]->x;
116435c4bbdfSmrg        SrcBox.y1 += pDraw->y + screenInfo.screens[0]->y;
116505b261ecSmrg    }
116605b261ecSmrg    SrcBox.x2 = SrcBox.x1 + width;
116705b261ecSmrg    SrcBox.y2 = SrcBox.y1 + height;
116835c4bbdfSmrg
11696747b715Smrg    RegionInit(&SrcRegion, &SrcBox, 1);
11706747b715Smrg    RegionNull(&GrabRegion);
117105b261ecSmrg
117205b261ecSmrg    depth = (format == XYPixmap) ? 1 : pDraw->depth;
117305b261ecSmrg
117435c4bbdfSmrg    FOR_NSCREENS(i) {
117535c4bbdfSmrg        BoxRec TheBox;
117635c4bbdfSmrg        ScreenPtr pScreen;
117735c4bbdfSmrg
117835c4bbdfSmrg        pDraw = pDrawables[i];
117935c4bbdfSmrg        pScreen = pDraw->pScreen;
118035c4bbdfSmrg
118135c4bbdfSmrg        TheBox.x1 = pScreen->x;
118235c4bbdfSmrg        TheBox.x2 = TheBox.x1 + pScreen->width;
118335c4bbdfSmrg        TheBox.y1 = pScreen->y;
118435c4bbdfSmrg        TheBox.y2 = TheBox.y1 + pScreen->height;
118535c4bbdfSmrg
118635c4bbdfSmrg        RegionInit(&ScreenRegion, &TheBox, 1);
118735c4bbdfSmrg        inOut = RegionContainsRect(&ScreenRegion, &SrcBox);
118835c4bbdfSmrg        if (inOut == rgnPART)
118935c4bbdfSmrg            RegionIntersect(&GrabRegion, &SrcRegion, &ScreenRegion);
119035c4bbdfSmrg        RegionUninit(&ScreenRegion);
119135c4bbdfSmrg
119235c4bbdfSmrg        if (inOut == rgnIN) {
119335c4bbdfSmrg            (*pScreen->GetImage) (pDraw,
119435c4bbdfSmrg                                  SrcBox.x1 - pDraw->x -
119535c4bbdfSmrg                                  screenInfo.screens[i]->x,
119635c4bbdfSmrg                                  SrcBox.y1 - pDraw->y -
119735c4bbdfSmrg                                  screenInfo.screens[i]->y, width, height,
119835c4bbdfSmrg                                  format, planemask, data);
119935c4bbdfSmrg            break;
120035c4bbdfSmrg        }
120135c4bbdfSmrg        else if (inOut == rgnOUT)
120235c4bbdfSmrg            continue;
120335c4bbdfSmrg
120435c4bbdfSmrg        nbox = RegionNumRects(&GrabRegion);
120535c4bbdfSmrg
120635c4bbdfSmrg        if (nbox) {
120735c4bbdfSmrg            pbox = RegionRects(&GrabRegion);
120835c4bbdfSmrg
120935c4bbdfSmrg            while (nbox--) {
121035c4bbdfSmrg                w = pbox->x2 - pbox->x1;
121135c4bbdfSmrg                h = pbox->y2 - pbox->y1;
121235c4bbdfSmrg                ScratchPitch = PixmapBytePad(w, depth);
121335c4bbdfSmrg                sizeNeeded = ScratchPitch * h;
121435c4bbdfSmrg
121535c4bbdfSmrg                if (sizeNeeded > size) {
121635c4bbdfSmrg                    char *tmpdata = ScratchMem;
121735c4bbdfSmrg
121835c4bbdfSmrg                    ScratchMem = realloc(ScratchMem, sizeNeeded);
121935c4bbdfSmrg                    if (ScratchMem)
122035c4bbdfSmrg                        size = sizeNeeded;
122135c4bbdfSmrg                    else {
122235c4bbdfSmrg                        ScratchMem = tmpdata;
122335c4bbdfSmrg                        break;
122435c4bbdfSmrg                    }
122535c4bbdfSmrg                }
122635c4bbdfSmrg
122735c4bbdfSmrg                x = pbox->x1 - pDraw->x - screenInfo.screens[i]->x;
122835c4bbdfSmrg                y = pbox->y1 - pDraw->y - screenInfo.screens[i]->y;
122935c4bbdfSmrg
123035c4bbdfSmrg                (*pScreen->GetImage) (pDraw, x, y, w, h,
123135c4bbdfSmrg                                      format, planemask, ScratchMem);
123235c4bbdfSmrg
123335c4bbdfSmrg                /* copy the memory over */
123435c4bbdfSmrg
123535c4bbdfSmrg                if (depth == 1) {
123635c4bbdfSmrg                    int k, shift, leftover, index, index2;
123735c4bbdfSmrg
123835c4bbdfSmrg                    x = pbox->x1 - SrcBox.x1;
123935c4bbdfSmrg                    y = pbox->y1 - SrcBox.y1;
124035c4bbdfSmrg                    shift = x & 7;
124135c4bbdfSmrg                    x >>= 3;
124235c4bbdfSmrg                    leftover = w & 7;
124335c4bbdfSmrg                    w >>= 3;
124435c4bbdfSmrg
124535c4bbdfSmrg                    /* clean up the edge */
124635c4bbdfSmrg                    if (leftover) {
124735c4bbdfSmrg                        int mask = (1 << leftover) - 1;
124835c4bbdfSmrg
124935c4bbdfSmrg                        for (j = h, k = w; j--; k += ScratchPitch)
125035c4bbdfSmrg                            ScratchMem[k] &= mask;
125135c4bbdfSmrg                    }
125235c4bbdfSmrg
125335c4bbdfSmrg                    for (j = 0, index = (pitch * y) + x, index2 = 0; j < h;
125435c4bbdfSmrg                         j++, index += pitch, index2 += ScratchPitch) {
125535c4bbdfSmrg                        if (w) {
125635c4bbdfSmrg                            if (!shift)
125735c4bbdfSmrg                                memcpy(data + index, ScratchMem + index2, w);
125835c4bbdfSmrg                            else
125935c4bbdfSmrg                                CopyBits(data + index, shift,
126035c4bbdfSmrg                                         ScratchMem + index2, w);
126135c4bbdfSmrg                        }
126235c4bbdfSmrg
126335c4bbdfSmrg                        if (leftover) {
126435c4bbdfSmrg                            data[index + w] |=
126535c4bbdfSmrg                                SHIFT_L(ScratchMem[index2 + w], shift);
126635c4bbdfSmrg                            if ((shift + leftover) > 8)
126735c4bbdfSmrg                                data[index + w + 1] |=
126835c4bbdfSmrg                                    SHIFT_R(ScratchMem[index2 + w],
126935c4bbdfSmrg                                            (8 - shift));
127035c4bbdfSmrg                        }
127135c4bbdfSmrg                    }
127235c4bbdfSmrg                }
127335c4bbdfSmrg                else {
127435c4bbdfSmrg                    j = BitsPerPixel(depth) >> 3;
127535c4bbdfSmrg                    x = (pbox->x1 - SrcBox.x1) * j;
127635c4bbdfSmrg                    y = pbox->y1 - SrcBox.y1;
127735c4bbdfSmrg                    w *= j;
127835c4bbdfSmrg
127935c4bbdfSmrg                    for (j = 0; j < h; j++) {
128035c4bbdfSmrg                        memcpy(data + (pitch * (y + j)) + x,
128135c4bbdfSmrg                               ScratchMem + (ScratchPitch * j), w);
128235c4bbdfSmrg                    }
128335c4bbdfSmrg                }
128435c4bbdfSmrg                pbox++;
128535c4bbdfSmrg            }
128635c4bbdfSmrg
128735c4bbdfSmrg            RegionSubtract(&SrcRegion, &SrcRegion, &GrabRegion);
128835c4bbdfSmrg            if (!RegionNotEmpty(&SrcRegion))
128935c4bbdfSmrg                break;
129035c4bbdfSmrg        }
129135c4bbdfSmrg
129205b261ecSmrg    }
129305b261ecSmrg
12946747b715Smrg    free(ScratchMem);
129505b261ecSmrg
12966747b715Smrg    RegionUninit(&SrcRegion);
12976747b715Smrg    RegionUninit(&GrabRegion);
129805b261ecSmrg}
1299