panoramiX.c revision 6747b715
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"
5605b261ecSmrg#include "modinit.h"
576747b715Smrg#include "protocol-versions.h"
5805b261ecSmrg
5905b261ecSmrg#ifdef GLXPROXY
6005b261ecSmrgextern VisualPtr glxMatchVisual(ScreenPtr pScreen,
6105b261ecSmrg				VisualPtr pVisual,
6205b261ecSmrg				ScreenPtr pMatchScreen);
6305b261ecSmrg#endif
6405b261ecSmrg
6505b261ecSmrg/*
6605b261ecSmrg *	PanoramiX data declarations
6705b261ecSmrg */
6805b261ecSmrg
6905b261ecSmrgint 		PanoramiXPixWidth = 0;
7005b261ecSmrgint 		PanoramiXPixHeight = 0;
716747b715Smrgint 		PanoramiXNumScreens = 0;
7205b261ecSmrg
7305b261ecSmrgstatic RegionRec   	PanoramiXScreenRegion = {{0, 0, 0, 0}, NULL};
7405b261ecSmrg
7505b261ecSmrgstatic int		PanoramiXNumDepths;
7605b261ecSmrgstatic DepthPtr		PanoramiXDepths;
7705b261ecSmrgstatic int		PanoramiXNumVisuals;
7805b261ecSmrgstatic VisualPtr	PanoramiXVisuals;
7905b261ecSmrg
806747b715Smrgunsigned long XRC_DRAWABLE;
816747b715Smrgunsigned long XRT_WINDOW;
826747b715Smrgunsigned long XRT_PIXMAP;
836747b715Smrgunsigned long XRT_GC;
846747b715Smrgunsigned long XRT_COLORMAP;
8505b261ecSmrg
864642e01fSmrgstatic Bool VisualsEqual(VisualPtr, ScreenPtr, VisualPtr);
876747b715SmrgXineramaVisualsEqualProcPtr XineramaVisualsEqualPtr = &VisualsEqual;
884642e01fSmrg
8905b261ecSmrg/*
9005b261ecSmrg *	Function prototypes
9105b261ecSmrg */
9205b261ecSmrg
9305b261ecSmrgstatic int panoramiXGeneration;
9405b261ecSmrgstatic int ProcPanoramiXDispatch(ClientPtr client);
9505b261ecSmrg
9605b261ecSmrgstatic void PanoramiXResetProc(ExtensionEntry*);
9705b261ecSmrg
9805b261ecSmrg/*
9905b261ecSmrg *	External references for functions and data variables
10005b261ecSmrg */
10105b261ecSmrg
10205b261ecSmrg#include "panoramiXh.h"
10305b261ecSmrg
10405b261ecSmrgint (* SavedProcVector[256]) (ClientPtr client) = { NULL, };
10505b261ecSmrg
1066747b715Smrgstatic DevPrivateKeyRec PanoramiXGCKeyRec;
1076747b715Smrg#define PanoramiXGCKey (&PanoramiXGCKeyRec)
1086747b715Smrgstatic DevPrivateKeyRec PanoramiXScreenKeyRec;
1096747b715Smrg#define PanoramiXScreenKey (&PanoramiXScreenKeyRec)
11005b261ecSmrg
11105b261ecSmrgtypedef struct {
11205b261ecSmrg  DDXPointRec clipOrg;
11305b261ecSmrg  DDXPointRec patOrg;
11405b261ecSmrg  GCFuncs *wrapFuncs;
11505b261ecSmrg} PanoramiXGCRec, *PanoramiXGCPtr;
11605b261ecSmrg
11705b261ecSmrgtypedef struct {
11805b261ecSmrg  CreateGCProcPtr	CreateGC;
11905b261ecSmrg  CloseScreenProcPtr	CloseScreen;
12005b261ecSmrg} PanoramiXScreenRec, *PanoramiXScreenPtr;
12105b261ecSmrg
12205b261ecSmrgstatic void XineramaValidateGC(GCPtr, unsigned long, DrawablePtr);
12305b261ecSmrgstatic void XineramaChangeGC(GCPtr, unsigned long);
12405b261ecSmrgstatic void XineramaCopyGC(GCPtr, unsigned long, GCPtr);
12505b261ecSmrgstatic void XineramaDestroyGC(GCPtr);
12605b261ecSmrgstatic void XineramaChangeClip(GCPtr, int, pointer, int);
12705b261ecSmrgstatic void XineramaDestroyClip(GCPtr);
12805b261ecSmrgstatic void XineramaCopyClip(GCPtr, GCPtr);
12905b261ecSmrg
13005b261ecSmrgstatic GCFuncs XineramaGCFuncs = {
13105b261ecSmrg    XineramaValidateGC, XineramaChangeGC, XineramaCopyGC, XineramaDestroyGC,
13205b261ecSmrg    XineramaChangeClip, XineramaDestroyClip, XineramaCopyClip
13305b261ecSmrg};
13405b261ecSmrg
13505b261ecSmrg#define Xinerama_GC_FUNC_PROLOGUE(pGC)\
1364642e01fSmrg    PanoramiXGCPtr  pGCPriv = (PanoramiXGCPtr) \
1374642e01fSmrg	dixLookupPrivate(&(pGC)->devPrivates, PanoramiXGCKey); \
13805b261ecSmrg    (pGC)->funcs = pGCPriv->wrapFuncs;
13905b261ecSmrg
14005b261ecSmrg#define Xinerama_GC_FUNC_EPILOGUE(pGC)\
14105b261ecSmrg    pGCPriv->wrapFuncs = (pGC)->funcs;\
14205b261ecSmrg    (pGC)->funcs = &XineramaGCFuncs;
14305b261ecSmrg
14405b261ecSmrg
14505b261ecSmrgstatic Bool
14605b261ecSmrgXineramaCloseScreen (int i, ScreenPtr pScreen)
14705b261ecSmrg{
1484642e01fSmrg    PanoramiXScreenPtr pScreenPriv = (PanoramiXScreenPtr)
1494642e01fSmrg	dixLookupPrivate(&pScreen->devPrivates, PanoramiXScreenKey);
15005b261ecSmrg
15105b261ecSmrg    pScreen->CloseScreen = pScreenPriv->CloseScreen;
15205b261ecSmrg    pScreen->CreateGC = pScreenPriv->CreateGC;
15305b261ecSmrg
15405b261ecSmrg    if (pScreen->myNum == 0)
1556747b715Smrg	RegionUninit(&PanoramiXScreenRegion);
15605b261ecSmrg
1576747b715Smrg    free((pointer) pScreenPriv);
15805b261ecSmrg
15905b261ecSmrg    return (*pScreen->CloseScreen) (i, pScreen);
16005b261ecSmrg}
16105b261ecSmrg
16205b261ecSmrgstatic Bool
16305b261ecSmrgXineramaCreateGC(GCPtr pGC)
16405b261ecSmrg{
16505b261ecSmrg    ScreenPtr pScreen = pGC->pScreen;
1664642e01fSmrg    PanoramiXScreenPtr pScreenPriv = (PanoramiXScreenPtr)
1674642e01fSmrg	dixLookupPrivate(&pScreen->devPrivates, PanoramiXScreenKey);
16805b261ecSmrg    Bool ret;
16905b261ecSmrg
17005b261ecSmrg    pScreen->CreateGC = pScreenPriv->CreateGC;
17105b261ecSmrg    if((ret = (*pScreen->CreateGC)(pGC))) {
1724642e01fSmrg	PanoramiXGCPtr pGCPriv = (PanoramiXGCPtr)
1734642e01fSmrg	    dixLookupPrivate(&pGC->devPrivates, PanoramiXGCKey);
17405b261ecSmrg
17505b261ecSmrg	pGCPriv->wrapFuncs = pGC->funcs;
17605b261ecSmrg        pGC->funcs = &XineramaGCFuncs;
17705b261ecSmrg
17805b261ecSmrg	pGCPriv->clipOrg.x = pGC->clipOrg.x;
17905b261ecSmrg	pGCPriv->clipOrg.y = pGC->clipOrg.y;
18005b261ecSmrg	pGCPriv->patOrg.x = pGC->patOrg.x;
18105b261ecSmrg	pGCPriv->patOrg.y = pGC->patOrg.y;
18205b261ecSmrg    }
18305b261ecSmrg    pScreen->CreateGC = XineramaCreateGC;
18405b261ecSmrg
18505b261ecSmrg    return ret;
18605b261ecSmrg}
18705b261ecSmrg
18805b261ecSmrgstatic void
18905b261ecSmrgXineramaValidateGC(
19005b261ecSmrg   GCPtr         pGC,
19105b261ecSmrg   unsigned long changes,
19205b261ecSmrg   DrawablePtr   pDraw
19305b261ecSmrg){
19405b261ecSmrg    Xinerama_GC_FUNC_PROLOGUE (pGC);
19505b261ecSmrg
19605b261ecSmrg    if((pDraw->type == DRAWABLE_WINDOW) && !(((WindowPtr)pDraw)->parent)) {
19705b261ecSmrg	/* the root window */
1986747b715Smrg	int x_off = pGC->pScreen->x;
1996747b715Smrg	int y_off = pGC->pScreen->y;
20005b261ecSmrg	int new_val;
20105b261ecSmrg
20205b261ecSmrg	new_val = pGCPriv->clipOrg.x - x_off;
20305b261ecSmrg	if(pGC->clipOrg.x != new_val) {
20405b261ecSmrg	    pGC->clipOrg.x = new_val;
20505b261ecSmrg	    changes |= GCClipXOrigin;
20605b261ecSmrg	}
20705b261ecSmrg	new_val = pGCPriv->clipOrg.y - y_off;
20805b261ecSmrg	if(pGC->clipOrg.y != new_val) {
20905b261ecSmrg	    pGC->clipOrg.y = new_val;
21005b261ecSmrg	    changes |= GCClipYOrigin;
21105b261ecSmrg	}
21205b261ecSmrg	new_val = pGCPriv->patOrg.x - x_off;
21305b261ecSmrg	if(pGC->patOrg.x != new_val) {
21405b261ecSmrg	    pGC->patOrg.x = new_val;
21505b261ecSmrg	    changes |= GCTileStipXOrigin;
21605b261ecSmrg	}
21705b261ecSmrg	new_val = pGCPriv->patOrg.y - y_off;
21805b261ecSmrg	if(pGC->patOrg.y != new_val) {
21905b261ecSmrg	    pGC->patOrg.y = new_val;
22005b261ecSmrg	    changes |= GCTileStipYOrigin;
22105b261ecSmrg	}
22205b261ecSmrg    } else {
22305b261ecSmrg	if(pGC->clipOrg.x != pGCPriv->clipOrg.x) {
22405b261ecSmrg	    pGC->clipOrg.x = pGCPriv->clipOrg.x;
22505b261ecSmrg	    changes |= GCClipXOrigin;
22605b261ecSmrg	}
22705b261ecSmrg	if(pGC->clipOrg.y != pGCPriv->clipOrg.y) {
22805b261ecSmrg	    pGC->clipOrg.y = pGCPriv->clipOrg.y;
22905b261ecSmrg	    changes |= GCClipYOrigin;
23005b261ecSmrg	}
23105b261ecSmrg	if(pGC->patOrg.x != pGCPriv->patOrg.x) {
23205b261ecSmrg	    pGC->patOrg.x = pGCPriv->patOrg.x;
23305b261ecSmrg	    changes |= GCTileStipXOrigin;
23405b261ecSmrg	}
23505b261ecSmrg	if(pGC->patOrg.y != pGCPriv->patOrg.y) {
23605b261ecSmrg	    pGC->patOrg.y = pGCPriv->patOrg.y;
23705b261ecSmrg	    changes |= GCTileStipYOrigin;
23805b261ecSmrg	}
23905b261ecSmrg    }
24005b261ecSmrg
24105b261ecSmrg    (*pGC->funcs->ValidateGC)(pGC, changes, pDraw);
24205b261ecSmrg    Xinerama_GC_FUNC_EPILOGUE (pGC);
24305b261ecSmrg}
24405b261ecSmrg
24505b261ecSmrgstatic void
24605b261ecSmrgXineramaDestroyGC(GCPtr pGC)
24705b261ecSmrg{
24805b261ecSmrg    Xinerama_GC_FUNC_PROLOGUE (pGC);
24905b261ecSmrg    (*pGC->funcs->DestroyGC)(pGC);
25005b261ecSmrg    Xinerama_GC_FUNC_EPILOGUE (pGC);
25105b261ecSmrg}
25205b261ecSmrg
25305b261ecSmrgstatic void
25405b261ecSmrgXineramaChangeGC (
25505b261ecSmrg    GCPtr	    pGC,
25605b261ecSmrg    unsigned long   mask
25705b261ecSmrg){
25805b261ecSmrg    Xinerama_GC_FUNC_PROLOGUE (pGC);
25905b261ecSmrg
26005b261ecSmrg    if(mask & GCTileStipXOrigin)
26105b261ecSmrg	pGCPriv->patOrg.x = pGC->patOrg.x;
26205b261ecSmrg    if(mask & GCTileStipYOrigin)
26305b261ecSmrg	pGCPriv->patOrg.y = pGC->patOrg.y;
26405b261ecSmrg    if(mask & GCClipXOrigin)
26505b261ecSmrg	pGCPriv->clipOrg.x = pGC->clipOrg.x;
26605b261ecSmrg    if(mask & GCClipYOrigin)
26705b261ecSmrg	pGCPriv->clipOrg.y = pGC->clipOrg.y;
26805b261ecSmrg
26905b261ecSmrg    (*pGC->funcs->ChangeGC) (pGC, mask);
27005b261ecSmrg    Xinerama_GC_FUNC_EPILOGUE (pGC);
27105b261ecSmrg}
27205b261ecSmrg
27305b261ecSmrgstatic void
27405b261ecSmrgXineramaCopyGC (
27505b261ecSmrg    GCPtr	    pGCSrc,
27605b261ecSmrg    unsigned long   mask,
27705b261ecSmrg    GCPtr	    pGCDst
27805b261ecSmrg){
2794642e01fSmrg    PanoramiXGCPtr pSrcPriv = (PanoramiXGCPtr)
2804642e01fSmrg	dixLookupPrivate(&pGCSrc->devPrivates, PanoramiXGCKey);
28105b261ecSmrg    Xinerama_GC_FUNC_PROLOGUE (pGCDst);
28205b261ecSmrg
28305b261ecSmrg    if(mask & GCTileStipXOrigin)
28405b261ecSmrg        pGCPriv->patOrg.x = pSrcPriv->patOrg.x;
28505b261ecSmrg    if(mask & GCTileStipYOrigin)
28605b261ecSmrg        pGCPriv->patOrg.y = pSrcPriv->patOrg.y;
28705b261ecSmrg    if(mask & GCClipXOrigin)
28805b261ecSmrg        pGCPriv->clipOrg.x = pSrcPriv->clipOrg.x;
28905b261ecSmrg    if(mask & GCClipYOrigin)
29005b261ecSmrg        pGCPriv->clipOrg.y = pSrcPriv->clipOrg.y;
29105b261ecSmrg
29205b261ecSmrg    (*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst);
29305b261ecSmrg    Xinerama_GC_FUNC_EPILOGUE (pGCDst);
29405b261ecSmrg}
29505b261ecSmrg
29605b261ecSmrgstatic void
29705b261ecSmrgXineramaChangeClip (
29805b261ecSmrg    GCPtr   pGC,
29905b261ecSmrg    int		type,
30005b261ecSmrg    pointer	pvalue,
30105b261ecSmrg    int		nrects
30205b261ecSmrg){
30305b261ecSmrg    Xinerama_GC_FUNC_PROLOGUE (pGC);
30405b261ecSmrg    (*pGC->funcs->ChangeClip) (pGC, type, pvalue, nrects);
30505b261ecSmrg    Xinerama_GC_FUNC_EPILOGUE (pGC);
30605b261ecSmrg}
30705b261ecSmrg
30805b261ecSmrgstatic void
30905b261ecSmrgXineramaCopyClip(GCPtr pgcDst, GCPtr pgcSrc)
31005b261ecSmrg{
31105b261ecSmrg    Xinerama_GC_FUNC_PROLOGUE (pgcDst);
31205b261ecSmrg    (* pgcDst->funcs->CopyClip)(pgcDst, pgcSrc);
31305b261ecSmrg    Xinerama_GC_FUNC_EPILOGUE (pgcDst);
31405b261ecSmrg}
31505b261ecSmrg
31605b261ecSmrgstatic void
31705b261ecSmrgXineramaDestroyClip(GCPtr pGC)
31805b261ecSmrg{
31905b261ecSmrg    Xinerama_GC_FUNC_PROLOGUE (pGC);
32005b261ecSmrg    (* pGC->funcs->DestroyClip)(pGC);
32105b261ecSmrg    Xinerama_GC_FUNC_EPILOGUE (pGC);
32205b261ecSmrg}
32305b261ecSmrg
3246747b715Smrgint
32505b261ecSmrgXineramaDeleteResource(pointer data, XID id)
32605b261ecSmrg{
3276747b715Smrg    free(data);
32805b261ecSmrg    return 1;
32905b261ecSmrg}
33005b261ecSmrg
33105b261ecSmrgtypedef struct {
33205b261ecSmrg   int screen;
33305b261ecSmrg   int id;
33405b261ecSmrg} PanoramiXSearchData;
33505b261ecSmrg
33605b261ecSmrgstatic Bool
33705b261ecSmrgXineramaFindIDByScrnum(pointer resource, XID id, pointer privdata)
33805b261ecSmrg{
33905b261ecSmrg    PanoramiXRes *res = (PanoramiXRes*)resource;
34005b261ecSmrg    PanoramiXSearchData *data = (PanoramiXSearchData*)privdata;
34105b261ecSmrg
3426747b715Smrg    return res->info[data->screen].id == data->id;
34305b261ecSmrg}
34405b261ecSmrg
34505b261ecSmrgPanoramiXRes *
34605b261ecSmrgPanoramiXFindIDByScrnum(RESTYPE type, XID id, int screen)
34705b261ecSmrg{
34805b261ecSmrg    PanoramiXSearchData data;
3496747b715Smrg    pointer val;
35005b261ecSmrg
3516747b715Smrg    if(!screen) {
3526747b715Smrg	dixLookupResourceByType(&val, id, type, serverClient, DixReadAccess);
3536747b715Smrg	return val;
3546747b715Smrg    }
35505b261ecSmrg
35605b261ecSmrg    data.screen = screen;
35705b261ecSmrg    data.id = id;
35805b261ecSmrg
35905b261ecSmrg    return LookupClientResourceComplex(clients[CLIENT_ID(id)], type,
36005b261ecSmrg		XineramaFindIDByScrnum, &data);
36105b261ecSmrg}
36205b261ecSmrg
36305b261ecSmrgtypedef struct _connect_callback_list {
36405b261ecSmrg    void (*func)(void);
36505b261ecSmrg    struct _connect_callback_list *next;
36605b261ecSmrg} XineramaConnectionCallbackList;
36705b261ecSmrg
36805b261ecSmrgstatic XineramaConnectionCallbackList *ConnectionCallbackList = NULL;
36905b261ecSmrg
3706747b715SmrgBool
37105b261ecSmrgXineramaRegisterConnectionBlockCallback(void (*func)(void))
37205b261ecSmrg{
37305b261ecSmrg    XineramaConnectionCallbackList *newlist;
37405b261ecSmrg
3756747b715Smrg    if(!(newlist = malloc(sizeof(XineramaConnectionCallbackList))))
37605b261ecSmrg	return FALSE;
37705b261ecSmrg
37805b261ecSmrg    newlist->next = ConnectionCallbackList;
37905b261ecSmrg    newlist->func = func;
38005b261ecSmrg    ConnectionCallbackList = newlist;
38105b261ecSmrg
38205b261ecSmrg    return TRUE;
38305b261ecSmrg}
38405b261ecSmrg
38505b261ecSmrgstatic void XineramaInitData(ScreenPtr pScreen)
38605b261ecSmrg{
38705b261ecSmrg    int i, w, h;
38805b261ecSmrg
3896747b715Smrg    RegionNull(&PanoramiXScreenRegion);
39005b261ecSmrg    for (i = 0; i < PanoramiXNumScreens; i++) {
39105b261ecSmrg	BoxRec TheBox;
3926747b715Smrg	RegionRec ScreenRegion;
39305b261ecSmrg
39405b261ecSmrg        pScreen = screenInfo.screens[i];
39505b261ecSmrg
3966747b715Smrg	TheBox.x1 = pScreen->x;
3976747b715Smrg	TheBox.x2 = TheBox.x1 + pScreen->width;
3986747b715Smrg	TheBox.y1 = pScreen->y;
3996747b715Smrg	TheBox.y2 = TheBox.y1 + pScreen->height;
40005b261ecSmrg
4016747b715Smrg	RegionInit(&ScreenRegion, &TheBox, 1);
4026747b715Smrg	RegionUnion(&PanoramiXScreenRegion, &PanoramiXScreenRegion,
4036747b715Smrg		     &ScreenRegion);
4046747b715Smrg	RegionUninit(&ScreenRegion);
40505b261ecSmrg    }
40605b261ecSmrg
4076747b715Smrg    PanoramiXPixWidth = screenInfo.screens[0]->x + screenInfo.screens[0]->width;
4086747b715Smrg    PanoramiXPixHeight = screenInfo.screens[0]->y + screenInfo.screens[0]->height;
40905b261ecSmrg
41005b261ecSmrg    for (i = 1; i < PanoramiXNumScreens; i++) {
4116747b715Smrg	pScreen = screenInfo.screens[i];
4126747b715Smrg	w = pScreen->x + pScreen->width;
4136747b715Smrg	h = pScreen->y + pScreen->height;
41405b261ecSmrg
41505b261ecSmrg	if (PanoramiXPixWidth < w)
41605b261ecSmrg	    PanoramiXPixWidth = w;
41705b261ecSmrg	if (PanoramiXPixHeight < h)
41805b261ecSmrg	    PanoramiXPixHeight = h;
41905b261ecSmrg    }
42005b261ecSmrg}
42105b261ecSmrg
42205b261ecSmrgvoid XineramaReinitData(ScreenPtr pScreen)
42305b261ecSmrg{
4246747b715Smrg    RegionUninit(&PanoramiXScreenRegion);
42505b261ecSmrg    XineramaInitData(pScreen);
42605b261ecSmrg}
42705b261ecSmrg
42805b261ecSmrg/*
42905b261ecSmrg *	PanoramiXExtensionInit():
43005b261ecSmrg *		Called from InitExtensions in main().
43105b261ecSmrg *		Register PanoramiXeen Extension
43205b261ecSmrg *		Initialize global variables.
43305b261ecSmrg */
43405b261ecSmrg
43505b261ecSmrgvoid PanoramiXExtensionInit(int argc, char *argv[])
43605b261ecSmrg{
43705b261ecSmrg    int 	     	i;
43805b261ecSmrg    Bool	     	success = FALSE;
43905b261ecSmrg    ExtensionEntry 	*extEntry;
44005b261ecSmrg    ScreenPtr		pScreen = screenInfo.screens[0];
44105b261ecSmrg    PanoramiXScreenPtr	pScreenPriv;
44205b261ecSmrg
44305b261ecSmrg    if (noPanoramiXExtension)
44405b261ecSmrg	return;
44505b261ecSmrg
4466747b715Smrg    if (!dixRegisterPrivateKey(&PanoramiXScreenKeyRec, PRIVATE_SCREEN, 0)) {
4476747b715Smrg	noPanoramiXExtension = TRUE;
4486747b715Smrg	return;
4496747b715Smrg    }
4506747b715Smrg
4516747b715Smrg    if (!dixRegisterPrivateKey(&PanoramiXGCKeyRec, PRIVATE_GC, sizeof(PanoramiXGCRec))) {
4526747b715Smrg	noPanoramiXExtension = TRUE;
4536747b715Smrg	return;
4546747b715Smrg    }
4556747b715Smrg
45605b261ecSmrg    PanoramiXNumScreens = screenInfo.numScreens;
45705b261ecSmrg    if (PanoramiXNumScreens == 1) {		/* Only 1 screen 	*/
45805b261ecSmrg	noPanoramiXExtension = TRUE;
45905b261ecSmrg	return;
46005b261ecSmrg    }
46105b261ecSmrg
46205b261ecSmrg    while (panoramiXGeneration != serverGeneration) {
46305b261ecSmrg	extEntry = AddExtension(PANORAMIX_PROTOCOL_NAME, 0,0,
46405b261ecSmrg				ProcPanoramiXDispatch,
46505b261ecSmrg				SProcPanoramiXDispatch, PanoramiXResetProc,
46605b261ecSmrg				StandardMinorOpcode);
4674642e01fSmrg	if (!extEntry)
46805b261ecSmrg	    break;
46905b261ecSmrg
47005b261ecSmrg	/*
47105b261ecSmrg	 *	First make sure all the basic allocations succeed.  If not,
47205b261ecSmrg	 *	run in non-PanoramiXeen mode.
47305b261ecSmrg	 */
47405b261ecSmrg
47505b261ecSmrg	for (i = 0; i < PanoramiXNumScreens; i++) {
47605b261ecSmrg	   pScreen = screenInfo.screens[i];
4776747b715Smrg	   pScreenPriv = malloc(sizeof(PanoramiXScreenRec));
4784642e01fSmrg	   dixSetPrivate(&pScreen->devPrivates, PanoramiXScreenKey,
4794642e01fSmrg			 pScreenPriv);
48005b261ecSmrg	   if(!pScreenPriv) {
48105b261ecSmrg		noPanoramiXExtension = TRUE;
48205b261ecSmrg		return;
48305b261ecSmrg	   }
48405b261ecSmrg
48505b261ecSmrg	   pScreenPriv->CreateGC = pScreen->CreateGC;
48605b261ecSmrg	   pScreenPriv->CloseScreen = pScreen->CloseScreen;
48705b261ecSmrg
48805b261ecSmrg	   pScreen->CreateGC = XineramaCreateGC;
48905b261ecSmrg	   pScreen->CloseScreen = XineramaCloseScreen;
49005b261ecSmrg	}
49105b261ecSmrg
49205b261ecSmrg	XRC_DRAWABLE = CreateNewResourceClass();
4936747b715Smrg	XRT_WINDOW = CreateNewResourceType(XineramaDeleteResource,
4946747b715Smrg					   "XineramaWindow");
4956747b715Smrg	if (XRT_WINDOW)
4966747b715Smrg	    XRT_WINDOW |= XRC_DRAWABLE;
4976747b715Smrg	XRT_PIXMAP = CreateNewResourceType(XineramaDeleteResource,
4986747b715Smrg					   "XineramaPixmap");
4996747b715Smrg	if (XRT_PIXMAP)
5006747b715Smrg	    XRT_PIXMAP |= XRC_DRAWABLE;
5016747b715Smrg	XRT_GC = CreateNewResourceType(XineramaDeleteResource,
5026747b715Smrg				       "XineramaGC");
5036747b715Smrg	XRT_COLORMAP = CreateNewResourceType(XineramaDeleteResource,
5046747b715Smrg					     "XineramaColormap");
5056747b715Smrg
5066747b715Smrg	if (XRT_WINDOW && XRT_PIXMAP && XRT_GC && XRT_COLORMAP) {
5076747b715Smrg	    panoramiXGeneration = serverGeneration;
5086747b715Smrg	    success = TRUE;
5096747b715Smrg	}
5106747b715Smrg	SetResourceTypeErrorValue(XRT_WINDOW, BadWindow);
5116747b715Smrg	SetResourceTypeErrorValue(XRT_PIXMAP, BadPixmap);
5126747b715Smrg	SetResourceTypeErrorValue(XRT_GC, BadGC);
5136747b715Smrg	SetResourceTypeErrorValue(XRT_COLORMAP, BadColor);
51405b261ecSmrg    }
51505b261ecSmrg
51605b261ecSmrg    if (!success) {
51705b261ecSmrg	noPanoramiXExtension = TRUE;
5184642e01fSmrg	ErrorF(PANORAMIX_PROTOCOL_NAME " extension failed to initialize\n");
51905b261ecSmrg	return;
52005b261ecSmrg    }
52105b261ecSmrg
52205b261ecSmrg    XineramaInitData(pScreen);
52305b261ecSmrg
52405b261ecSmrg    /*
52505b261ecSmrg     *	Put our processes into the ProcVector
52605b261ecSmrg     */
52705b261ecSmrg
52805b261ecSmrg    for (i = 256; i--; )
52905b261ecSmrg	SavedProcVector[i] = ProcVector[i];
53005b261ecSmrg
53105b261ecSmrg    ProcVector[X_CreateWindow] = PanoramiXCreateWindow;
53205b261ecSmrg    ProcVector[X_ChangeWindowAttributes] = PanoramiXChangeWindowAttributes;
53305b261ecSmrg    ProcVector[X_DestroyWindow] = PanoramiXDestroyWindow;
53405b261ecSmrg    ProcVector[X_DestroySubwindows] = PanoramiXDestroySubwindows;
53505b261ecSmrg    ProcVector[X_ChangeSaveSet] = PanoramiXChangeSaveSet;
53605b261ecSmrg    ProcVector[X_ReparentWindow] = PanoramiXReparentWindow;
53705b261ecSmrg    ProcVector[X_MapWindow] = PanoramiXMapWindow;
53805b261ecSmrg    ProcVector[X_MapSubwindows] = PanoramiXMapSubwindows;
53905b261ecSmrg    ProcVector[X_UnmapWindow] = PanoramiXUnmapWindow;
54005b261ecSmrg    ProcVector[X_UnmapSubwindows] = PanoramiXUnmapSubwindows;
54105b261ecSmrg    ProcVector[X_ConfigureWindow] = PanoramiXConfigureWindow;
54205b261ecSmrg    ProcVector[X_CirculateWindow] = PanoramiXCirculateWindow;
54305b261ecSmrg    ProcVector[X_GetGeometry] = PanoramiXGetGeometry;
54405b261ecSmrg    ProcVector[X_TranslateCoords] = PanoramiXTranslateCoords;
54505b261ecSmrg    ProcVector[X_CreatePixmap] = PanoramiXCreatePixmap;
54605b261ecSmrg    ProcVector[X_FreePixmap] = PanoramiXFreePixmap;
54705b261ecSmrg    ProcVector[X_CreateGC] = PanoramiXCreateGC;
54805b261ecSmrg    ProcVector[X_ChangeGC] = PanoramiXChangeGC;
54905b261ecSmrg    ProcVector[X_CopyGC] = PanoramiXCopyGC;
55005b261ecSmrg    ProcVector[X_SetDashes] = PanoramiXSetDashes;
55105b261ecSmrg    ProcVector[X_SetClipRectangles] = PanoramiXSetClipRectangles;
55205b261ecSmrg    ProcVector[X_FreeGC] = PanoramiXFreeGC;
55305b261ecSmrg    ProcVector[X_ClearArea] = PanoramiXClearToBackground;
5544642e01fSmrg    ProcVector[X_CopyArea] = PanoramiXCopyArea;
5554642e01fSmrg    ProcVector[X_CopyPlane] = PanoramiXCopyPlane;
55605b261ecSmrg    ProcVector[X_PolyPoint] = PanoramiXPolyPoint;
55705b261ecSmrg    ProcVector[X_PolyLine] = PanoramiXPolyLine;
55805b261ecSmrg    ProcVector[X_PolySegment] = PanoramiXPolySegment;
55905b261ecSmrg    ProcVector[X_PolyRectangle] = PanoramiXPolyRectangle;
56005b261ecSmrg    ProcVector[X_PolyArc] = PanoramiXPolyArc;
56105b261ecSmrg    ProcVector[X_FillPoly] = PanoramiXFillPoly;
56205b261ecSmrg    ProcVector[X_PolyFillRectangle] = PanoramiXPolyFillRectangle;
56305b261ecSmrg    ProcVector[X_PolyFillArc] = PanoramiXPolyFillArc;
56405b261ecSmrg    ProcVector[X_PutImage] = PanoramiXPutImage;
56505b261ecSmrg    ProcVector[X_GetImage] = PanoramiXGetImage;
56605b261ecSmrg    ProcVector[X_PolyText8] = PanoramiXPolyText8;
56705b261ecSmrg    ProcVector[X_PolyText16] = PanoramiXPolyText16;
56805b261ecSmrg    ProcVector[X_ImageText8] = PanoramiXImageText8;
56905b261ecSmrg    ProcVector[X_ImageText16] = PanoramiXImageText16;
57005b261ecSmrg    ProcVector[X_CreateColormap] = PanoramiXCreateColormap;
57105b261ecSmrg    ProcVector[X_FreeColormap] = PanoramiXFreeColormap;
57205b261ecSmrg    ProcVector[X_CopyColormapAndFree] = PanoramiXCopyColormapAndFree;
57305b261ecSmrg    ProcVector[X_InstallColormap] = PanoramiXInstallColormap;
57405b261ecSmrg    ProcVector[X_UninstallColormap] = PanoramiXUninstallColormap;
57505b261ecSmrg    ProcVector[X_AllocColor] = PanoramiXAllocColor;
57605b261ecSmrg    ProcVector[X_AllocNamedColor] = PanoramiXAllocNamedColor;
57705b261ecSmrg    ProcVector[X_AllocColorCells] = PanoramiXAllocColorCells;
5784642e01fSmrg    ProcVector[X_AllocColorPlanes] = PanoramiXAllocColorPlanes;
57905b261ecSmrg    ProcVector[X_FreeColors] = PanoramiXFreeColors;
5804642e01fSmrg    ProcVector[X_StoreColors] = PanoramiXStoreColors;
5814642e01fSmrg    ProcVector[X_StoreNamedColor] = PanoramiXStoreNamedColor;
58205b261ecSmrg
58305b261ecSmrg    PanoramiXRenderInit ();
58405b261ecSmrg}
58505b261ecSmrg
58605b261ecSmrgextern Bool CreateConnectionBlock(void);
58705b261ecSmrg
58805b261ecSmrgBool PanoramiXCreateConnectionBlock(void)
58905b261ecSmrg{
59005b261ecSmrg    int i, j, length;
59105b261ecSmrg    Bool disableBackingStore = FALSE;
59205b261ecSmrg    int old_width, old_height;
59305b261ecSmrg    float width_mult, height_mult;
59405b261ecSmrg    xWindowRoot *root;
59505b261ecSmrg    xVisualType *visual;
59605b261ecSmrg    xDepth *depth;
59705b261ecSmrg    VisualPtr pVisual;
59805b261ecSmrg    ScreenPtr pScreen;
59905b261ecSmrg
60005b261ecSmrg    /*
60105b261ecSmrg     *	Do normal CreateConnectionBlock but faking it for only one screen
60205b261ecSmrg     */
60305b261ecSmrg
60405b261ecSmrg    if(!PanoramiXNumDepths) {
6054642e01fSmrg	ErrorF("Xinerama error: No common visuals\n");
60605b261ecSmrg	return FALSE;
60705b261ecSmrg    }
60805b261ecSmrg
60905b261ecSmrg    for(i = 1; i < screenInfo.numScreens; i++) {
61005b261ecSmrg	pScreen = screenInfo.screens[i];
61105b261ecSmrg	if(pScreen->rootDepth != screenInfo.screens[0]->rootDepth) {
6124642e01fSmrg	    ErrorF("Xinerama error: Root window depths differ\n");
61305b261ecSmrg	    return FALSE;
61405b261ecSmrg	}
61505b261ecSmrg	if(pScreen->backingStoreSupport != screenInfo.screens[0]->backingStoreSupport)
61605b261ecSmrg	     disableBackingStore = TRUE;
61705b261ecSmrg    }
61805b261ecSmrg
6194642e01fSmrg    if (disableBackingStore) {
6204642e01fSmrg    	for (i = 0; i < screenInfo.numScreens; i++) {
62105b261ecSmrg	    pScreen = screenInfo.screens[i];
6224642e01fSmrg	    pScreen->backingStoreSupport = NotUseful;
62305b261ecSmrg	}
62405b261ecSmrg    }
62505b261ecSmrg
62605b261ecSmrg    i = screenInfo.numScreens;
62705b261ecSmrg    screenInfo.numScreens = 1;
62805b261ecSmrg    if (!CreateConnectionBlock()) {
62905b261ecSmrg	screenInfo.numScreens = i;
63005b261ecSmrg	return FALSE;
63105b261ecSmrg    }
63205b261ecSmrg
63305b261ecSmrg    screenInfo.numScreens = i;
63405b261ecSmrg
63505b261ecSmrg    root = (xWindowRoot *) (ConnectionInfo + connBlockScreenStart);
63605b261ecSmrg    length = connBlockScreenStart + sizeof(xWindowRoot);
63705b261ecSmrg
63805b261ecSmrg    /* overwrite the connection block */
63905b261ecSmrg    root->nDepths = PanoramiXNumDepths;
64005b261ecSmrg
64105b261ecSmrg    for (i = 0; i < PanoramiXNumDepths; i++) {
64205b261ecSmrg	depth = (xDepth *) (ConnectionInfo + length);
64305b261ecSmrg	depth->depth = PanoramiXDepths[i].depth;
64405b261ecSmrg	depth->nVisuals = PanoramiXDepths[i].numVids;
64505b261ecSmrg	length += sizeof(xDepth);
64605b261ecSmrg	visual = (xVisualType *)(ConnectionInfo + length);
64705b261ecSmrg
64805b261ecSmrg	for (j = 0; j < depth->nVisuals; j++, visual++) {
64905b261ecSmrg	    visual->visualID = PanoramiXDepths[i].vids[j];
65005b261ecSmrg
65105b261ecSmrg	    for (pVisual = PanoramiXVisuals;
65205b261ecSmrg		 pVisual->vid != visual->visualID;
65305b261ecSmrg		 pVisual++)
65405b261ecSmrg	         ;
65505b261ecSmrg
65605b261ecSmrg	    visual->class = pVisual->class;
65705b261ecSmrg	    visual->bitsPerRGB = pVisual->bitsPerRGBValue;
65805b261ecSmrg	    visual->colormapEntries = pVisual->ColormapEntries;
65905b261ecSmrg	    visual->redMask = pVisual->redMask;
66005b261ecSmrg	    visual->greenMask = pVisual->greenMask;
66105b261ecSmrg	    visual->blueMask = pVisual->blueMask;
66205b261ecSmrg	}
66305b261ecSmrg
66405b261ecSmrg	length += (depth->nVisuals * sizeof(xVisualType));
66505b261ecSmrg    }
66605b261ecSmrg
6676747b715Smrg    connSetupPrefix.length = bytes_to_int32(length);
66805b261ecSmrg
66905b261ecSmrg    for (i = 0; i < PanoramiXNumDepths; i++)
6706747b715Smrg	free(PanoramiXDepths[i].vids);
6716747b715Smrg    free(PanoramiXDepths);
6724642e01fSmrg    PanoramiXDepths = NULL;
67305b261ecSmrg
67405b261ecSmrg    /*
67505b261ecSmrg     *  OK, change some dimensions so it looks as if it were one big screen
67605b261ecSmrg     */
67705b261ecSmrg
67805b261ecSmrg    old_width = root->pixWidth;
67905b261ecSmrg    old_height = root->pixHeight;
68005b261ecSmrg
68105b261ecSmrg    root->pixWidth = PanoramiXPixWidth;
68205b261ecSmrg    root->pixHeight = PanoramiXPixHeight;
68305b261ecSmrg    width_mult = (1.0 * root->pixWidth) / old_width;
68405b261ecSmrg    height_mult = (1.0 * root->pixHeight) / old_height;
68505b261ecSmrg    root->mmWidth *= width_mult;
68605b261ecSmrg    root->mmHeight *= height_mult;
68705b261ecSmrg
68805b261ecSmrg    while(ConnectionCallbackList) {
68905b261ecSmrg	pointer tmp;
69005b261ecSmrg
69105b261ecSmrg	tmp = (pointer)ConnectionCallbackList;
69205b261ecSmrg	(*ConnectionCallbackList->func)();
69305b261ecSmrg	ConnectionCallbackList = ConnectionCallbackList->next;
6946747b715Smrg	free(tmp);
69505b261ecSmrg    }
69605b261ecSmrg
69705b261ecSmrg    return TRUE;
69805b261ecSmrg}
69905b261ecSmrg
7004642e01fSmrg/*
7014642e01fSmrg * This isn't just memcmp(), bitsPerRGBValue is skipped.  markv made that
7024642e01fSmrg * change way back before xf86 4.0, but the comment for _why_ is a bit
7034642e01fSmrg * opaque, so I'm not going to question it for now.
7044642e01fSmrg *
7054642e01fSmrg * This is probably better done as a screen hook so DBE/EVI/GLX can add
7064642e01fSmrg * their own tests, and adding privates to VisualRec so they don't have to
7074642e01fSmrg * do their own back-mapping.
7084642e01fSmrg */
7094642e01fSmrgstatic Bool
7104642e01fSmrgVisualsEqual(VisualPtr a, ScreenPtr pScreenB, VisualPtr b)
71105b261ecSmrg{
7124642e01fSmrg    return ((a->class == b->class) &&
7134642e01fSmrg	(a->ColormapEntries == b->ColormapEntries) &&
7144642e01fSmrg	(a->nplanes == b->nplanes) &&
7154642e01fSmrg	(a->redMask == b->redMask) &&
7164642e01fSmrg	(a->greenMask == b->greenMask) &&
7174642e01fSmrg	(a->blueMask == b->blueMask) &&
7184642e01fSmrg	(a->offsetRed == b->offsetRed) &&
7194642e01fSmrg	(a->offsetGreen == b->offsetGreen) &&
7204642e01fSmrg	(a->offsetBlue == b->offsetBlue));
7214642e01fSmrg}
72205b261ecSmrg
7234642e01fSmrgstatic void
7244642e01fSmrgPanoramiXMaybeAddDepth(DepthPtr pDepth)
7254642e01fSmrg{
7264642e01fSmrg    ScreenPtr pScreen;
7274642e01fSmrg    int j, k;
7284642e01fSmrg    Bool found = FALSE;
7294642e01fSmrg
7304642e01fSmrg    for (j = 1; j < PanoramiXNumScreens; j++) {
7314642e01fSmrg	pScreen = screenInfo.screens[j];
7324642e01fSmrg	for (k = 0; k < pScreen->numDepths; k++) {
7334642e01fSmrg	    if (pScreen->allowedDepths[k].depth == pDepth->depth) {
7344642e01fSmrg		found = TRUE;
7354642e01fSmrg		break;
7364642e01fSmrg	    }
7374642e01fSmrg	}
7384642e01fSmrg    }
73905b261ecSmrg
7404642e01fSmrg    if (!found)
7414642e01fSmrg	return;
74205b261ecSmrg
7434642e01fSmrg    j = PanoramiXNumDepths;
7444642e01fSmrg    PanoramiXNumDepths++;
7456747b715Smrg    PanoramiXDepths = realloc(PanoramiXDepths,
7464642e01fSmrg	    PanoramiXNumDepths * sizeof(DepthRec));
7474642e01fSmrg    PanoramiXDepths[j].depth = pDepth->depth;
7484642e01fSmrg    PanoramiXDepths[j].numVids = 0;
7494642e01fSmrg    /* XXX suboptimal, should grow these dynamically */
7504642e01fSmrg    if(pDepth->numVids)
7516747b715Smrg	PanoramiXDepths[j].vids = malloc(sizeof(VisualID) * pDepth->numVids);
7524642e01fSmrg    else
7534642e01fSmrg	PanoramiXDepths[j].vids = NULL;
7544642e01fSmrg}
7554642e01fSmrg
7564642e01fSmrgstatic void
7574642e01fSmrgPanoramiXMaybeAddVisual(VisualPtr pVisual)
7584642e01fSmrg{
7594642e01fSmrg    ScreenPtr pScreen;
7604642e01fSmrg    int j, k;
7614642e01fSmrg    Bool found = FALSE;
76205b261ecSmrg
7634642e01fSmrg    for (j = 1; j < PanoramiXNumScreens; j++) {
7644642e01fSmrg	pScreen = screenInfo.screens[j];
7654642e01fSmrg	found = FALSE;
76605b261ecSmrg
7674642e01fSmrg	for (k = 0; k < pScreen->numVisuals; k++) {
7684642e01fSmrg	    VisualPtr candidate = &pScreen->visuals[k];
76905b261ecSmrg
7704642e01fSmrg	    if ((*XineramaVisualsEqualPtr)(pVisual, pScreen, candidate)
77105b261ecSmrg#ifdef GLXPROXY
7724642e01fSmrg		&& glxMatchVisual(screenInfo.screens[0], pVisual, pScreen)
77305b261ecSmrg#endif
7744642e01fSmrg		    ) {
7754642e01fSmrg		found = TRUE;
77605b261ecSmrg		break;
77705b261ecSmrg	    }
77805b261ecSmrg	}
77905b261ecSmrg
7804642e01fSmrg	if (!found)
7814642e01fSmrg	    return;
7824642e01fSmrg    }
7834642e01fSmrg
7844642e01fSmrg    /* found a matching visual on all screens, add it to the subset list */
7854642e01fSmrg    j = PanoramiXNumVisuals;
7864642e01fSmrg    PanoramiXNumVisuals++;
7876747b715Smrg    PanoramiXVisuals = realloc(PanoramiXVisuals,
7884642e01fSmrg	    PanoramiXNumVisuals * sizeof(VisualRec));
7894642e01fSmrg
7904642e01fSmrg    memcpy(&PanoramiXVisuals[j], pVisual, sizeof(VisualRec));
7914642e01fSmrg
7924642e01fSmrg    for (k = 0; k < PanoramiXNumDepths; k++) {
7934642e01fSmrg	if (PanoramiXDepths[k].depth == pVisual->nplanes) {
7944642e01fSmrg	    PanoramiXDepths[k].vids[PanoramiXDepths[k].numVids] = pVisual->vid;
7954642e01fSmrg	    PanoramiXDepths[k].numVids++;
7964642e01fSmrg	    break;
7974642e01fSmrg	}
7984642e01fSmrg    }
7994642e01fSmrg}
8004642e01fSmrg
8014642e01fSmrgextern void
8024642e01fSmrgPanoramiXConsolidate(void)
8034642e01fSmrg{
8044642e01fSmrg    int 	i;
8054642e01fSmrg    PanoramiXRes *root, *defmap, *saver;
8064642e01fSmrg    ScreenPtr   pScreen = screenInfo.screens[0];
8074642e01fSmrg    DepthPtr    pDepth = pScreen->allowedDepths;
8084642e01fSmrg    VisualPtr   pVisual = pScreen->visuals;
8094642e01fSmrg
8104642e01fSmrg    PanoramiXNumDepths = 0;
8114642e01fSmrg    PanoramiXNumVisuals = 0;
81205b261ecSmrg
8134642e01fSmrg    for (i = 0; i < pScreen->numDepths; i++)
8144642e01fSmrg	PanoramiXMaybeAddDepth(pDepth++);
81505b261ecSmrg
8164642e01fSmrg    for (i = 0; i < pScreen->numVisuals; i++)
8174642e01fSmrg	PanoramiXMaybeAddVisual(pVisual++);
8184642e01fSmrg
8196747b715Smrg    root = malloc(sizeof(PanoramiXRes));
82005b261ecSmrg    root->type = XRT_WINDOW;
8216747b715Smrg    defmap = malloc(sizeof(PanoramiXRes));
82205b261ecSmrg    defmap->type = XRT_COLORMAP;
8236747b715Smrg    saver = malloc(sizeof(PanoramiXRes));
82405b261ecSmrg    saver->type = XRT_WINDOW;
82505b261ecSmrg
82605b261ecSmrg    for (i =  0; i < PanoramiXNumScreens; i++) {
8276747b715Smrg	ScreenPtr pScreen = screenInfo.screens[i];
8286747b715Smrg	root->info[i].id = pScreen->root->drawable.id;
82905b261ecSmrg	root->u.win.class = InputOutput;
83005b261ecSmrg        root->u.win.root = TRUE;
8316747b715Smrg        saver->info[i].id = pScreen->screensaver.wid;
83205b261ecSmrg        saver->u.win.class = InputOutput;
83305b261ecSmrg        saver->u.win.root = TRUE;
8346747b715Smrg	defmap->info[i].id = pScreen->defColormap;
83505b261ecSmrg    }
83605b261ecSmrg
83705b261ecSmrg    AddResource(root->info[0].id, XRT_WINDOW, root);
83805b261ecSmrg    AddResource(saver->info[0].id, XRT_WINDOW, saver);
83905b261ecSmrg    AddResource(defmap->info[0].id, XRT_COLORMAP, defmap);
84005b261ecSmrg}
84105b261ecSmrg
8426747b715SmrgVisualID
8434642e01fSmrgPanoramiXTranslateVisualID(int screen, VisualID orig)
8444642e01fSmrg{
8454642e01fSmrg    ScreenPtr pOtherScreen = screenInfo.screens[screen];
8464642e01fSmrg    VisualPtr pVisual = NULL;
8474642e01fSmrg    int i;
8484642e01fSmrg
8494642e01fSmrg    for (i = 0; i < PanoramiXNumVisuals; i++) {
8504642e01fSmrg	if (orig == PanoramiXVisuals[i].vid) {
8514642e01fSmrg	    pVisual = &PanoramiXVisuals[i];
8524642e01fSmrg	    break;
8534642e01fSmrg	}
8544642e01fSmrg    }
8554642e01fSmrg
8564642e01fSmrg    if (!pVisual)
8574642e01fSmrg	return 0;
8584642e01fSmrg
8594642e01fSmrg    /* if screen is 0, orig is already the correct visual ID */
8604642e01fSmrg    if (screen == 0)
8614642e01fSmrg	return orig;
8624642e01fSmrg
8634642e01fSmrg    /* found the original, now translate it relative to the backend screen */
8644642e01fSmrg    for (i = 0; i < pOtherScreen->numVisuals; i++) {
8654642e01fSmrg	VisualPtr pOtherVisual = &pOtherScreen->visuals[i];
8664642e01fSmrg
8674642e01fSmrg	if ((*XineramaVisualsEqualPtr)(pVisual, pOtherScreen, pOtherVisual))
8684642e01fSmrg	    return pOtherVisual->vid;
8694642e01fSmrg    }
8704642e01fSmrg
8714642e01fSmrg    return 0;
8724642e01fSmrg}
8734642e01fSmrg
87405b261ecSmrg
87505b261ecSmrg/*
87605b261ecSmrg *	PanoramiXResetProc()
87705b261ecSmrg *		Exit, deallocating as needed.
87805b261ecSmrg */
87905b261ecSmrg
88005b261ecSmrgstatic void PanoramiXResetProc(ExtensionEntry* extEntry)
88105b261ecSmrg{
88205b261ecSmrg    int		i;
88305b261ecSmrg
88405b261ecSmrg    PanoramiXRenderReset ();
88505b261ecSmrg    screenInfo.numScreens = PanoramiXNumScreens;
88605b261ecSmrg    for (i = 256; i--; )
88705b261ecSmrg	ProcVector[i] = SavedProcVector[i];
88805b261ecSmrg}
88905b261ecSmrg
89005b261ecSmrg
89105b261ecSmrgint
89205b261ecSmrgProcPanoramiXQueryVersion (ClientPtr client)
89305b261ecSmrg{
89405b261ecSmrg    /* REQUEST(xPanoramiXQueryVersionReq); */
89505b261ecSmrg    xPanoramiXQueryVersionReply		rep;
89605b261ecSmrg    register 	int			n;
89705b261ecSmrg
89805b261ecSmrg    REQUEST_SIZE_MATCH (xPanoramiXQueryVersionReq);
89905b261ecSmrg    rep.type = X_Reply;
90005b261ecSmrg    rep.length = 0;
90105b261ecSmrg    rep.sequenceNumber = client->sequence;
90252397711Smrg    rep.majorVersion = SERVER_PANORAMIX_MAJOR_VERSION;
90352397711Smrg    rep.minorVersion = SERVER_PANORAMIX_MINOR_VERSION;
90405b261ecSmrg    if (client->swapped) {
90505b261ecSmrg        swaps(&rep.sequenceNumber, n);
90605b261ecSmrg        swapl(&rep.length, n);
90705b261ecSmrg        swaps(&rep.majorVersion, n);
90805b261ecSmrg        swaps(&rep.minorVersion, n);
90905b261ecSmrg    }
91005b261ecSmrg    WriteToClient(client, sizeof (xPanoramiXQueryVersionReply), (char *)&rep);
9116747b715Smrg    return Success;
91205b261ecSmrg}
91305b261ecSmrg
91405b261ecSmrgint
91505b261ecSmrgProcPanoramiXGetState(ClientPtr client)
91605b261ecSmrg{
91705b261ecSmrg	REQUEST(xPanoramiXGetStateReq);
91805b261ecSmrg    	WindowPtr			pWin;
91905b261ecSmrg	xPanoramiXGetStateReply		rep;
9204642e01fSmrg	int			n, rc;
92105b261ecSmrg
92205b261ecSmrg	REQUEST_SIZE_MATCH(xPanoramiXGetStateReq);
9234642e01fSmrg	rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
92405b261ecSmrg	if (rc != Success)
92505b261ecSmrg	    return rc;
92605b261ecSmrg
92705b261ecSmrg	rep.type = X_Reply;
92805b261ecSmrg	rep.length = 0;
92905b261ecSmrg	rep.sequenceNumber = client->sequence;
93005b261ecSmrg	rep.state = !noPanoramiXExtension;
9314642e01fSmrg	rep.window = stuff->window;
93205b261ecSmrg    	if (client->swapped) {
93305b261ecSmrg	    swaps (&rep.sequenceNumber, n);
93405b261ecSmrg	    swapl (&rep.length, n);
9354642e01fSmrg	    swapl (&rep.window, n);
93605b261ecSmrg	}
93705b261ecSmrg	WriteToClient (client, sizeof (xPanoramiXGetStateReply), (char *) &rep);
9386747b715Smrg	return Success;
93905b261ecSmrg
94005b261ecSmrg}
94105b261ecSmrg
94205b261ecSmrgint
94305b261ecSmrgProcPanoramiXGetScreenCount(ClientPtr client)
94405b261ecSmrg{
94505b261ecSmrg	REQUEST(xPanoramiXGetScreenCountReq);
94605b261ecSmrg    	WindowPtr			pWin;
94705b261ecSmrg	xPanoramiXGetScreenCountReply	rep;
9484642e01fSmrg	int			n, rc;
94905b261ecSmrg
95005b261ecSmrg	REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq);
9514642e01fSmrg	rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
95205b261ecSmrg	if (rc != Success)
95305b261ecSmrg	    return rc;
95405b261ecSmrg
95505b261ecSmrg	rep.type = X_Reply;
95605b261ecSmrg	rep.length = 0;
95705b261ecSmrg	rep.sequenceNumber = client->sequence;
95805b261ecSmrg	rep.ScreenCount = PanoramiXNumScreens;
9594642e01fSmrg	rep.window = stuff->window;
96005b261ecSmrg    	if (client->swapped) {
96105b261ecSmrg	    swaps (&rep.sequenceNumber, n);
96205b261ecSmrg	    swapl (&rep.length, n);
9634642e01fSmrg	    swapl (&rep.window, n);
96405b261ecSmrg	}
96505b261ecSmrg	WriteToClient (client, sizeof (xPanoramiXGetScreenCountReply), (char *) &rep);
9666747b715Smrg	return Success;
96705b261ecSmrg}
96805b261ecSmrg
96905b261ecSmrgint
97005b261ecSmrgProcPanoramiXGetScreenSize(ClientPtr client)
97105b261ecSmrg{
97205b261ecSmrg	REQUEST(xPanoramiXGetScreenSizeReq);
97305b261ecSmrg    	WindowPtr			pWin;
97405b261ecSmrg	xPanoramiXGetScreenSizeReply	rep;
9754642e01fSmrg	int			n, rc;
97605b261ecSmrg
9774642e01fSmrg	if (stuff->screen >= PanoramiXNumScreens)
9784642e01fSmrg	    return BadMatch;
9794642e01fSmrg
98005b261ecSmrg	REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq);
9814642e01fSmrg	rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
98205b261ecSmrg	if (rc != Success)
98305b261ecSmrg	    return rc;
98405b261ecSmrg
98505b261ecSmrg	rep.type = X_Reply;
98605b261ecSmrg	rep.length = 0;
98705b261ecSmrg	rep.sequenceNumber = client->sequence;
98805b261ecSmrg		/* screen dimensions */
9896747b715Smrg	rep.width  = screenInfo.screens[stuff->screen]->width;
9906747b715Smrg	rep.height = screenInfo.screens[stuff->screen]->height;
9914642e01fSmrg	rep.window = stuff->window;
9924642e01fSmrg	rep.screen = stuff->screen;
99305b261ecSmrg    	if (client->swapped) {
99405b261ecSmrg	    swaps (&rep.sequenceNumber, n);
99505b261ecSmrg	    swapl (&rep.length, n);
9964642e01fSmrg	    swapl (&rep.width, n);
9974642e01fSmrg	    swapl (&rep.height, n);
9984642e01fSmrg	    swapl (&rep.window, n);
9994642e01fSmrg	    swapl (&rep.screen, n);
100005b261ecSmrg	}
100105b261ecSmrg	WriteToClient (client, sizeof (xPanoramiXGetScreenSizeReply), (char *) &rep);
10026747b715Smrg	return Success;
100305b261ecSmrg}
100405b261ecSmrg
100505b261ecSmrg
100605b261ecSmrgint
100705b261ecSmrgProcXineramaIsActive(ClientPtr client)
100805b261ecSmrg{
100905b261ecSmrg    /* REQUEST(xXineramaIsActiveReq); */
101005b261ecSmrg    xXineramaIsActiveReply	rep;
101105b261ecSmrg
101205b261ecSmrg    REQUEST_SIZE_MATCH(xXineramaIsActiveReq);
101305b261ecSmrg
101405b261ecSmrg    rep.type = X_Reply;
101505b261ecSmrg    rep.length = 0;
101605b261ecSmrg    rep.sequenceNumber = client->sequence;
101705b261ecSmrg#if 1
101805b261ecSmrg    {
101905b261ecSmrg	/* The following hack fools clients into thinking that Xinerama
102005b261ecSmrg	 * is disabled even though it is not. */
102105b261ecSmrg	rep.state = !noPanoramiXExtension && !PanoramiXExtensionDisabledHack;
102205b261ecSmrg    }
102305b261ecSmrg#else
102405b261ecSmrg    rep.state = !noPanoramiXExtension;
102505b261ecSmrg#endif
102605b261ecSmrg    if (client->swapped) {
10274642e01fSmrg	int n;
102805b261ecSmrg	swaps (&rep.sequenceNumber, n);
102905b261ecSmrg	swapl (&rep.length, n);
103005b261ecSmrg	swapl (&rep.state, n);
103105b261ecSmrg    }
103205b261ecSmrg    WriteToClient (client, sizeof (xXineramaIsActiveReply), (char *) &rep);
10336747b715Smrg    return Success;
103405b261ecSmrg}
103505b261ecSmrg
103605b261ecSmrg
103705b261ecSmrgint
103805b261ecSmrgProcXineramaQueryScreens(ClientPtr client)
103905b261ecSmrg{
104005b261ecSmrg    /* REQUEST(xXineramaQueryScreensReq); */
104105b261ecSmrg    xXineramaQueryScreensReply	rep;
104205b261ecSmrg
104305b261ecSmrg    REQUEST_SIZE_MATCH(xXineramaQueryScreensReq);
104405b261ecSmrg
104505b261ecSmrg    rep.type = X_Reply;
104605b261ecSmrg    rep.sequenceNumber = client->sequence;
104705b261ecSmrg    rep.number = (noPanoramiXExtension) ? 0 : PanoramiXNumScreens;
10486747b715Smrg    rep.length = bytes_to_int32(rep.number * sz_XineramaScreenInfo);
104905b261ecSmrg    if (client->swapped) {
10504642e01fSmrg	int n;
105105b261ecSmrg	swaps (&rep.sequenceNumber, n);
105205b261ecSmrg	swapl (&rep.length, n);
105305b261ecSmrg	swapl (&rep.number, n);
105405b261ecSmrg    }
105505b261ecSmrg    WriteToClient (client, sizeof (xXineramaQueryScreensReply), (char *) &rep);
105605b261ecSmrg
105705b261ecSmrg    if(!noPanoramiXExtension) {
105805b261ecSmrg	xXineramaScreenInfo scratch;
105905b261ecSmrg	int i;
106005b261ecSmrg
106105b261ecSmrg	for(i = 0; i < PanoramiXNumScreens; i++) {
10626747b715Smrg	    scratch.x_org  = screenInfo.screens[i]->x;
10636747b715Smrg	    scratch.y_org  = screenInfo.screens[i]->y;
10646747b715Smrg	    scratch.width  = screenInfo.screens[i]->width;
10656747b715Smrg	    scratch.height = screenInfo.screens[i]->height;
106605b261ecSmrg
106705b261ecSmrg	    if(client->swapped) {
10684642e01fSmrg		int n;
106905b261ecSmrg		swaps (&scratch.x_org, n);
107005b261ecSmrg		swaps (&scratch.y_org, n);
107105b261ecSmrg		swaps (&scratch.width, n);
107205b261ecSmrg		swaps (&scratch.height, n);
107305b261ecSmrg	    }
107405b261ecSmrg	    WriteToClient (client, sz_XineramaScreenInfo, (char *) &scratch);
107505b261ecSmrg	}
107605b261ecSmrg    }
107705b261ecSmrg
10786747b715Smrg    return Success;
107905b261ecSmrg}
108005b261ecSmrg
108105b261ecSmrg
108205b261ecSmrgstatic int
108305b261ecSmrgProcPanoramiXDispatch (ClientPtr client)
108405b261ecSmrg{   REQUEST(xReq);
108505b261ecSmrg    switch (stuff->data)
108605b261ecSmrg    {
108705b261ecSmrg	case X_PanoramiXQueryVersion:
108805b261ecSmrg	     return ProcPanoramiXQueryVersion(client);
108905b261ecSmrg	case X_PanoramiXGetState:
109005b261ecSmrg	     return ProcPanoramiXGetState(client);
109105b261ecSmrg	case X_PanoramiXGetScreenCount:
109205b261ecSmrg	     return ProcPanoramiXGetScreenCount(client);
109305b261ecSmrg	case X_PanoramiXGetScreenSize:
109405b261ecSmrg	     return ProcPanoramiXGetScreenSize(client);
109505b261ecSmrg	case X_XineramaIsActive:
109605b261ecSmrg	     return ProcXineramaIsActive(client);
109705b261ecSmrg	case X_XineramaQueryScreens:
109805b261ecSmrg	     return ProcXineramaQueryScreens(client);
109905b261ecSmrg    }
110005b261ecSmrg    return BadRequest;
110105b261ecSmrg}
110205b261ecSmrg
110305b261ecSmrg
110405b261ecSmrg#if X_BYTE_ORDER == X_LITTLE_ENDIAN
110505b261ecSmrg#define SHIFT_L(v,s) (v) << (s)
110605b261ecSmrg#define SHIFT_R(v,s) (v) >> (s)
110705b261ecSmrg#else
110805b261ecSmrg#define SHIFT_L(v,s) (v) >> (s)
110905b261ecSmrg#define SHIFT_R(v,s) (v) << (s)
111005b261ecSmrg#endif
111105b261ecSmrg
111205b261ecSmrgstatic void
111305b261ecSmrgCopyBits(char *dst, int shiftL, char *src, int bytes)
111405b261ecSmrg{
111505b261ecSmrg   /* Just get it to work.  Worry about speed later */
111605b261ecSmrg    int shiftR = 8 - shiftL;
111705b261ecSmrg
111805b261ecSmrg    while(bytes--) {
111905b261ecSmrg	*dst |= SHIFT_L(*src, shiftL);
112005b261ecSmrg	*(dst + 1) |= SHIFT_R(*src, shiftR);
112105b261ecSmrg	dst++; src++;
112205b261ecSmrg    }
112305b261ecSmrg}
112405b261ecSmrg
112505b261ecSmrg
112605b261ecSmrg/* Caution.  This doesn't support 2 and 4 bpp formats.  We expect
112705b261ecSmrg   1 bpp and planar data to be already cleared when presented
112805b261ecSmrg   to this function */
112905b261ecSmrg
113005b261ecSmrgvoid
113105b261ecSmrgXineramaGetImageData(
113205b261ecSmrg    DrawablePtr *pDrawables,
113305b261ecSmrg    int left,
113405b261ecSmrg    int top,
113505b261ecSmrg    int width,
113605b261ecSmrg    int height,
113705b261ecSmrg    unsigned int format,
113805b261ecSmrg    unsigned long planemask,
113905b261ecSmrg    char *data,
114005b261ecSmrg    int pitch,
114105b261ecSmrg    Bool isRoot
114205b261ecSmrg){
11436747b715Smrg    RegionRec SrcRegion, ScreenRegion, GrabRegion;
114405b261ecSmrg    BoxRec SrcBox, *pbox;
114505b261ecSmrg    int x, y, w, h, i, j, nbox, size, sizeNeeded, ScratchPitch, inOut, depth;
114605b261ecSmrg    DrawablePtr pDraw = pDrawables[0];
114705b261ecSmrg    char *ScratchMem = NULL;
114805b261ecSmrg
114905b261ecSmrg    size = 0;
115005b261ecSmrg
115105b261ecSmrg    /* find box in logical screen space */
115205b261ecSmrg    SrcBox.x1 = left;
115305b261ecSmrg    SrcBox.y1 = top;
115405b261ecSmrg    if(!isRoot) {
11556747b715Smrg	SrcBox.x1 += pDraw->x + screenInfo.screens[0]->x;
11566747b715Smrg	SrcBox.y1 += pDraw->y + screenInfo.screens[0]->y;
115705b261ecSmrg    }
115805b261ecSmrg    SrcBox.x2 = SrcBox.x1 + width;
115905b261ecSmrg    SrcBox.y2 = SrcBox.y1 + height;
116005b261ecSmrg
11616747b715Smrg    RegionInit(&SrcRegion, &SrcBox, 1);
11626747b715Smrg    RegionNull(&GrabRegion);
116305b261ecSmrg
116405b261ecSmrg    depth = (format == XYPixmap) ? 1 : pDraw->depth;
116505b261ecSmrg
116605b261ecSmrg    for(i = 0; i < PanoramiXNumScreens; i++) {
11676747b715Smrg	BoxRec TheBox;
11686747b715Smrg	ScreenPtr pScreen;
116905b261ecSmrg	pDraw = pDrawables[i];
11706747b715Smrg	pScreen = pDraw->pScreen;
11716747b715Smrg
11726747b715Smrg	TheBox.x1 = pScreen->x;
11736747b715Smrg	TheBox.x2 = TheBox.x1 + pScreen->width;
11746747b715Smrg	TheBox.y1 = pScreen->y;
11756747b715Smrg	TheBox.y2 = TheBox.y1 + pScreen->height;
117605b261ecSmrg
11776747b715Smrg	RegionInit(&ScreenRegion, &TheBox, 1);
11786747b715Smrg	inOut = RegionContainsRect(&ScreenRegion, &SrcBox);
11796747b715Smrg	if(inOut == rgnPART)
11806747b715Smrg	    RegionIntersect(&GrabRegion, &SrcRegion, &ScreenRegion);
11816747b715Smrg	RegionUninit(&ScreenRegion);
118205b261ecSmrg
118305b261ecSmrg	if(inOut == rgnIN) {
11846747b715Smrg	    (*pScreen->GetImage)(pDraw,
11856747b715Smrg			SrcBox.x1 - pDraw->x - screenInfo.screens[i]->x,
11866747b715Smrg			SrcBox.y1 - pDraw->y - screenInfo.screens[i]->y,
118705b261ecSmrg			width, height, format, planemask, data);
118805b261ecSmrg	    break;
118905b261ecSmrg	} else if (inOut == rgnOUT)
119005b261ecSmrg	    continue;
119105b261ecSmrg
11926747b715Smrg	nbox = RegionNumRects(&GrabRegion);
119305b261ecSmrg
119405b261ecSmrg	if(nbox) {
11956747b715Smrg	    pbox = RegionRects(&GrabRegion);
119605b261ecSmrg
119705b261ecSmrg	    while(nbox--) {
119805b261ecSmrg		w = pbox->x2 - pbox->x1;
119905b261ecSmrg		h = pbox->y2 - pbox->y1;
120005b261ecSmrg		ScratchPitch = PixmapBytePad(w, depth);
120105b261ecSmrg		sizeNeeded = ScratchPitch * h;
120205b261ecSmrg
120305b261ecSmrg		if(sizeNeeded > size) {
120405b261ecSmrg		    char *tmpdata = ScratchMem;
12056747b715Smrg		    ScratchMem = realloc(ScratchMem, sizeNeeded);
120605b261ecSmrg		    if(ScratchMem)
120705b261ecSmrg			size = sizeNeeded;
120805b261ecSmrg		    else {
120905b261ecSmrg			ScratchMem = tmpdata;
121005b261ecSmrg			break;
121105b261ecSmrg		    }
121205b261ecSmrg		}
121305b261ecSmrg
12146747b715Smrg		x = pbox->x1 - pDraw->x - screenInfo.screens[i]->x;
12156747b715Smrg		y = pbox->y1 - pDraw->y - screenInfo.screens[i]->y;
121605b261ecSmrg
12176747b715Smrg		(*pScreen->GetImage)(pDraw, x, y, w, h,
121805b261ecSmrg					format, planemask, ScratchMem);
121905b261ecSmrg
122005b261ecSmrg		/* copy the memory over */
122105b261ecSmrg
122205b261ecSmrg		if(depth == 1) {
122305b261ecSmrg		   int k, shift, leftover, index, index2;
122405b261ecSmrg
122505b261ecSmrg		   x = pbox->x1 - SrcBox.x1;
122605b261ecSmrg		   y = pbox->y1 - SrcBox.y1;
122705b261ecSmrg		   shift = x & 7;
122805b261ecSmrg		   x >>= 3;
122905b261ecSmrg		   leftover = w & 7;
123005b261ecSmrg		   w >>= 3;
123105b261ecSmrg
123205b261ecSmrg		   /* clean up the edge */
123305b261ecSmrg		   if(leftover) {
123405b261ecSmrg			int mask = (1 << leftover) - 1;
123505b261ecSmrg			for(j = h, k = w; j--; k += ScratchPitch)
123605b261ecSmrg			    ScratchMem[k] &= mask;
123705b261ecSmrg		   }
123805b261ecSmrg
123905b261ecSmrg		   for(j = 0, index = (pitch * y) + x, index2 = 0; j < h;
124005b261ecSmrg		       j++, index += pitch, index2 += ScratchPitch)
124105b261ecSmrg		   {
124205b261ecSmrg			if(w) {
124305b261ecSmrg			    if(!shift)
124405b261ecSmrg				memcpy(data + index, ScratchMem + index2, w);
124505b261ecSmrg			    else
124605b261ecSmrg				CopyBits(data + index, shift,
124705b261ecSmrg						ScratchMem + index2, w);
124805b261ecSmrg			}
124905b261ecSmrg
125005b261ecSmrg			if(leftover) {
125105b261ecSmrg			    data[index + w] |=
125205b261ecSmrg				SHIFT_L(ScratchMem[index2 + w], shift);
125305b261ecSmrg			    if((shift + leftover) > 8)
125405b261ecSmrg				data[index + w + 1] |=
125505b261ecSmrg				  SHIFT_R(ScratchMem[index2 + w],(8 - shift));
125605b261ecSmrg			}
125705b261ecSmrg		    }
125805b261ecSmrg		} else {
125905b261ecSmrg		    j = BitsPerPixel(depth) >> 3;
126005b261ecSmrg		    x = (pbox->x1 - SrcBox.x1) * j;
126105b261ecSmrg		    y = pbox->y1 - SrcBox.y1;
126205b261ecSmrg		    w *= j;
126305b261ecSmrg
126405b261ecSmrg		    for(j = 0; j < h; j++) {
126505b261ecSmrg			memcpy(data + (pitch * (y + j)) + x,
126605b261ecSmrg				ScratchMem + (ScratchPitch * j), w);
126705b261ecSmrg		    }
126805b261ecSmrg		}
126905b261ecSmrg		pbox++;
127005b261ecSmrg	    }
127105b261ecSmrg
12726747b715Smrg	    RegionSubtract(&SrcRegion, &SrcRegion, &GrabRegion);
12736747b715Smrg	    if(!RegionNotEmpty(&SrcRegion))
127405b261ecSmrg		break;
127505b261ecSmrg	}
127605b261ecSmrg
127705b261ecSmrg    }
127805b261ecSmrg
12796747b715Smrg    free(ScratchMem);
128005b261ecSmrg
12816747b715Smrg    RegionUninit(&SrcRegion);
12826747b715Smrg    RegionUninit(&GrabRegion);
128305b261ecSmrg}
1284