panoramiX.c revision 52397711
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#define NEED_REPLIES
3505b261ecSmrg#include <stdio.h>
3605b261ecSmrg#include <X11/X.h>
3705b261ecSmrg#include <X11/Xproto.h>
3805b261ecSmrg#include <X11/Xarch.h>
3905b261ecSmrg#include "misc.h"
4005b261ecSmrg#include "cursor.h"
4105b261ecSmrg#include "cursorstr.h"
4205b261ecSmrg#include "extnsionst.h"
4305b261ecSmrg#include "dixstruct.h"
4405b261ecSmrg#include "gc.h"
4505b261ecSmrg#include "gcstruct.h"
4605b261ecSmrg#include "scrnintstr.h"
4705b261ecSmrg#include "window.h"
4805b261ecSmrg#include "windowstr.h"
4905b261ecSmrg#include "pixmapstr.h"
5005b261ecSmrg#include "panoramiX.h"
5105b261ecSmrg#include <X11/extensions/panoramiXproto.h>
5205b261ecSmrg#include "panoramiXsrv.h"
5305b261ecSmrg#include "globals.h"
5405b261ecSmrg#include "servermd.h"
5505b261ecSmrg#include "resource.h"
5605b261ecSmrg#ifdef RENDER
5705b261ecSmrg#include "picturestr.h"
5805b261ecSmrg#endif
5905b261ecSmrg#include "modinit.h"
6005b261ecSmrg
6152397711Smrg#define SERVER_PANORAMIX_MAJOR_VERSION	1
6252397711Smrg#define SERVER_PANORAMIX_MINOR_VERSION	1
6305b261ecSmrg
6405b261ecSmrg#ifdef GLXPROXY
6505b261ecSmrgextern VisualPtr glxMatchVisual(ScreenPtr pScreen,
6605b261ecSmrg				VisualPtr pVisual,
6705b261ecSmrg				ScreenPtr pMatchScreen);
6805b261ecSmrg#endif
6905b261ecSmrg
7005b261ecSmrg/*
7105b261ecSmrg *	PanoramiX data declarations
7205b261ecSmrg */
7305b261ecSmrg
7405b261ecSmrgint 		PanoramiXPixWidth = 0;
7505b261ecSmrgint 		PanoramiXPixHeight = 0;
7605b261ecSmrg_X_EXPORT int 	PanoramiXNumScreens = 0;
7705b261ecSmrg
7805b261ecSmrg_X_EXPORT PanoramiXData *panoramiXdataPtr = NULL;
7905b261ecSmrgstatic RegionRec   	PanoramiXScreenRegion = {{0, 0, 0, 0}, NULL};
8005b261ecSmrg
8105b261ecSmrgstatic int		PanoramiXNumDepths;
8205b261ecSmrgstatic DepthPtr		PanoramiXDepths;
8305b261ecSmrgstatic int		PanoramiXNumVisuals;
8405b261ecSmrgstatic VisualPtr	PanoramiXVisuals;
8505b261ecSmrg
8605b261ecSmrg_X_EXPORT unsigned long XRC_DRAWABLE;
8705b261ecSmrg_X_EXPORT unsigned long XRT_WINDOW;
8805b261ecSmrg_X_EXPORT unsigned long XRT_PIXMAP;
8905b261ecSmrg_X_EXPORT unsigned long XRT_GC;
9005b261ecSmrg_X_EXPORT unsigned long XRT_COLORMAP;
9105b261ecSmrg
924642e01fSmrgstatic Bool VisualsEqual(VisualPtr, ScreenPtr, VisualPtr);
934642e01fSmrg_X_EXPORT XineramaVisualsEqualProcPtr XineramaVisualsEqualPtr = &VisualsEqual;
944642e01fSmrg
9505b261ecSmrg/*
9605b261ecSmrg *	Function prototypes
9705b261ecSmrg */
9805b261ecSmrg
9905b261ecSmrgstatic int panoramiXGeneration;
10005b261ecSmrgstatic int ProcPanoramiXDispatch(ClientPtr client);
10105b261ecSmrg
10205b261ecSmrgstatic void PanoramiXResetProc(ExtensionEntry*);
10305b261ecSmrg
10405b261ecSmrg/*
10505b261ecSmrg *	External references for functions and data variables
10605b261ecSmrg */
10705b261ecSmrg
10805b261ecSmrg#include "panoramiXh.h"
10905b261ecSmrg
11005b261ecSmrgint (* SavedProcVector[256]) (ClientPtr client) = { NULL, };
11105b261ecSmrg
1124642e01fSmrgstatic int PanoramiXGCKeyIndex;
1134642e01fSmrgstatic DevPrivateKey PanoramiXGCKey = &PanoramiXGCKeyIndex;
1144642e01fSmrgstatic int PanoramiXScreenKeyIndex;
1154642e01fSmrgstatic DevPrivateKey PanoramiXScreenKey = &PanoramiXScreenKeyIndex;
11605b261ecSmrg
11705b261ecSmrgtypedef struct {
11805b261ecSmrg  DDXPointRec clipOrg;
11905b261ecSmrg  DDXPointRec patOrg;
12005b261ecSmrg  GCFuncs *wrapFuncs;
12105b261ecSmrg} PanoramiXGCRec, *PanoramiXGCPtr;
12205b261ecSmrg
12305b261ecSmrgtypedef struct {
12405b261ecSmrg  CreateGCProcPtr	CreateGC;
12505b261ecSmrg  CloseScreenProcPtr	CloseScreen;
12605b261ecSmrg} PanoramiXScreenRec, *PanoramiXScreenPtr;
12705b261ecSmrg
12805b261ecSmrgRegionRec XineramaScreenRegions[MAXSCREENS];
12905b261ecSmrg
13005b261ecSmrgstatic void XineramaValidateGC(GCPtr, unsigned long, DrawablePtr);
13105b261ecSmrgstatic void XineramaChangeGC(GCPtr, unsigned long);
13205b261ecSmrgstatic void XineramaCopyGC(GCPtr, unsigned long, GCPtr);
13305b261ecSmrgstatic void XineramaDestroyGC(GCPtr);
13405b261ecSmrgstatic void XineramaChangeClip(GCPtr, int, pointer, int);
13505b261ecSmrgstatic void XineramaDestroyClip(GCPtr);
13605b261ecSmrgstatic void XineramaCopyClip(GCPtr, GCPtr);
13705b261ecSmrg
13805b261ecSmrgstatic GCFuncs XineramaGCFuncs = {
13905b261ecSmrg    XineramaValidateGC, XineramaChangeGC, XineramaCopyGC, XineramaDestroyGC,
14005b261ecSmrg    XineramaChangeClip, XineramaDestroyClip, XineramaCopyClip
14105b261ecSmrg};
14205b261ecSmrg
14305b261ecSmrg#define Xinerama_GC_FUNC_PROLOGUE(pGC)\
1444642e01fSmrg    PanoramiXGCPtr  pGCPriv = (PanoramiXGCPtr) \
1454642e01fSmrg	dixLookupPrivate(&(pGC)->devPrivates, PanoramiXGCKey); \
14605b261ecSmrg    (pGC)->funcs = pGCPriv->wrapFuncs;
14705b261ecSmrg
14805b261ecSmrg#define Xinerama_GC_FUNC_EPILOGUE(pGC)\
14905b261ecSmrg    pGCPriv->wrapFuncs = (pGC)->funcs;\
15005b261ecSmrg    (pGC)->funcs = &XineramaGCFuncs;
15105b261ecSmrg
15205b261ecSmrg
15305b261ecSmrgstatic Bool
15405b261ecSmrgXineramaCloseScreen (int i, ScreenPtr pScreen)
15505b261ecSmrg{
1564642e01fSmrg    PanoramiXScreenPtr pScreenPriv = (PanoramiXScreenPtr)
1574642e01fSmrg	dixLookupPrivate(&pScreen->devPrivates, PanoramiXScreenKey);
15805b261ecSmrg
15905b261ecSmrg    pScreen->CloseScreen = pScreenPriv->CloseScreen;
16005b261ecSmrg    pScreen->CreateGC = pScreenPriv->CreateGC;
16105b261ecSmrg
16205b261ecSmrg    REGION_UNINIT(pScreen, &XineramaScreenRegions[pScreen->myNum]);
16305b261ecSmrg    if (pScreen->myNum == 0)
16405b261ecSmrg	REGION_UNINIT(pScreen, &PanoramiXScreenRegion);
16505b261ecSmrg
16605b261ecSmrg    xfree ((pointer) pScreenPriv);
16705b261ecSmrg
16805b261ecSmrg    return (*pScreen->CloseScreen) (i, pScreen);
16905b261ecSmrg}
17005b261ecSmrg
17105b261ecSmrgstatic Bool
17205b261ecSmrgXineramaCreateGC(GCPtr pGC)
17305b261ecSmrg{
17405b261ecSmrg    ScreenPtr pScreen = pGC->pScreen;
1754642e01fSmrg    PanoramiXScreenPtr pScreenPriv = (PanoramiXScreenPtr)
1764642e01fSmrg	dixLookupPrivate(&pScreen->devPrivates, PanoramiXScreenKey);
17705b261ecSmrg    Bool ret;
17805b261ecSmrg
17905b261ecSmrg    pScreen->CreateGC = pScreenPriv->CreateGC;
18005b261ecSmrg    if((ret = (*pScreen->CreateGC)(pGC))) {
1814642e01fSmrg	PanoramiXGCPtr pGCPriv = (PanoramiXGCPtr)
1824642e01fSmrg	    dixLookupPrivate(&pGC->devPrivates, PanoramiXGCKey);
18305b261ecSmrg
18405b261ecSmrg	pGCPriv->wrapFuncs = pGC->funcs;
18505b261ecSmrg        pGC->funcs = &XineramaGCFuncs;
18605b261ecSmrg
18705b261ecSmrg	pGCPriv->clipOrg.x = pGC->clipOrg.x;
18805b261ecSmrg	pGCPriv->clipOrg.y = pGC->clipOrg.y;
18905b261ecSmrg	pGCPriv->patOrg.x = pGC->patOrg.x;
19005b261ecSmrg	pGCPriv->patOrg.y = pGC->patOrg.y;
19105b261ecSmrg    }
19205b261ecSmrg    pScreen->CreateGC = XineramaCreateGC;
19305b261ecSmrg
19405b261ecSmrg    return ret;
19505b261ecSmrg}
19605b261ecSmrg
19705b261ecSmrgstatic void
19805b261ecSmrgXineramaValidateGC(
19905b261ecSmrg   GCPtr         pGC,
20005b261ecSmrg   unsigned long changes,
20105b261ecSmrg   DrawablePtr   pDraw
20205b261ecSmrg){
20305b261ecSmrg    Xinerama_GC_FUNC_PROLOGUE (pGC);
20405b261ecSmrg
20505b261ecSmrg    if((pDraw->type == DRAWABLE_WINDOW) && !(((WindowPtr)pDraw)->parent)) {
20605b261ecSmrg	/* the root window */
20705b261ecSmrg	int x_off = panoramiXdataPtr[pGC->pScreen->myNum].x;
20805b261ecSmrg	int y_off = panoramiXdataPtr[pGC->pScreen->myNum].y;
20905b261ecSmrg	int new_val;
21005b261ecSmrg
21105b261ecSmrg	new_val = pGCPriv->clipOrg.x - x_off;
21205b261ecSmrg	if(pGC->clipOrg.x != new_val) {
21305b261ecSmrg	    pGC->clipOrg.x = new_val;
21405b261ecSmrg	    changes |= GCClipXOrigin;
21505b261ecSmrg	}
21605b261ecSmrg	new_val = pGCPriv->clipOrg.y - y_off;
21705b261ecSmrg	if(pGC->clipOrg.y != new_val) {
21805b261ecSmrg	    pGC->clipOrg.y = new_val;
21905b261ecSmrg	    changes |= GCClipYOrigin;
22005b261ecSmrg	}
22105b261ecSmrg	new_val = pGCPriv->patOrg.x - x_off;
22205b261ecSmrg	if(pGC->patOrg.x != new_val) {
22305b261ecSmrg	    pGC->patOrg.x = new_val;
22405b261ecSmrg	    changes |= GCTileStipXOrigin;
22505b261ecSmrg	}
22605b261ecSmrg	new_val = pGCPriv->patOrg.y - y_off;
22705b261ecSmrg	if(pGC->patOrg.y != new_val) {
22805b261ecSmrg	    pGC->patOrg.y = new_val;
22905b261ecSmrg	    changes |= GCTileStipYOrigin;
23005b261ecSmrg	}
23105b261ecSmrg    } else {
23205b261ecSmrg	if(pGC->clipOrg.x != pGCPriv->clipOrg.x) {
23305b261ecSmrg	    pGC->clipOrg.x = pGCPriv->clipOrg.x;
23405b261ecSmrg	    changes |= GCClipXOrigin;
23505b261ecSmrg	}
23605b261ecSmrg	if(pGC->clipOrg.y != pGCPriv->clipOrg.y) {
23705b261ecSmrg	    pGC->clipOrg.y = pGCPriv->clipOrg.y;
23805b261ecSmrg	    changes |= GCClipYOrigin;
23905b261ecSmrg	}
24005b261ecSmrg	if(pGC->patOrg.x != pGCPriv->patOrg.x) {
24105b261ecSmrg	    pGC->patOrg.x = pGCPriv->patOrg.x;
24205b261ecSmrg	    changes |= GCTileStipXOrigin;
24305b261ecSmrg	}
24405b261ecSmrg	if(pGC->patOrg.y != pGCPriv->patOrg.y) {
24505b261ecSmrg	    pGC->patOrg.y = pGCPriv->patOrg.y;
24605b261ecSmrg	    changes |= GCTileStipYOrigin;
24705b261ecSmrg	}
24805b261ecSmrg    }
24905b261ecSmrg
25005b261ecSmrg    (*pGC->funcs->ValidateGC)(pGC, changes, pDraw);
25105b261ecSmrg    Xinerama_GC_FUNC_EPILOGUE (pGC);
25205b261ecSmrg}
25305b261ecSmrg
25405b261ecSmrgstatic void
25505b261ecSmrgXineramaDestroyGC(GCPtr pGC)
25605b261ecSmrg{
25705b261ecSmrg    Xinerama_GC_FUNC_PROLOGUE (pGC);
25805b261ecSmrg    (*pGC->funcs->DestroyGC)(pGC);
25905b261ecSmrg    Xinerama_GC_FUNC_EPILOGUE (pGC);
26005b261ecSmrg}
26105b261ecSmrg
26205b261ecSmrgstatic void
26305b261ecSmrgXineramaChangeGC (
26405b261ecSmrg    GCPtr	    pGC,
26505b261ecSmrg    unsigned long   mask
26605b261ecSmrg){
26705b261ecSmrg    Xinerama_GC_FUNC_PROLOGUE (pGC);
26805b261ecSmrg
26905b261ecSmrg    if(mask & GCTileStipXOrigin)
27005b261ecSmrg	pGCPriv->patOrg.x = pGC->patOrg.x;
27105b261ecSmrg    if(mask & GCTileStipYOrigin)
27205b261ecSmrg	pGCPriv->patOrg.y = pGC->patOrg.y;
27305b261ecSmrg    if(mask & GCClipXOrigin)
27405b261ecSmrg	pGCPriv->clipOrg.x = pGC->clipOrg.x;
27505b261ecSmrg    if(mask & GCClipYOrigin)
27605b261ecSmrg	pGCPriv->clipOrg.y = pGC->clipOrg.y;
27705b261ecSmrg
27805b261ecSmrg    (*pGC->funcs->ChangeGC) (pGC, mask);
27905b261ecSmrg    Xinerama_GC_FUNC_EPILOGUE (pGC);
28005b261ecSmrg}
28105b261ecSmrg
28205b261ecSmrgstatic void
28305b261ecSmrgXineramaCopyGC (
28405b261ecSmrg    GCPtr	    pGCSrc,
28505b261ecSmrg    unsigned long   mask,
28605b261ecSmrg    GCPtr	    pGCDst
28705b261ecSmrg){
2884642e01fSmrg    PanoramiXGCPtr pSrcPriv = (PanoramiXGCPtr)
2894642e01fSmrg	dixLookupPrivate(&pGCSrc->devPrivates, PanoramiXGCKey);
29005b261ecSmrg    Xinerama_GC_FUNC_PROLOGUE (pGCDst);
29105b261ecSmrg
29205b261ecSmrg    if(mask & GCTileStipXOrigin)
29305b261ecSmrg        pGCPriv->patOrg.x = pSrcPriv->patOrg.x;
29405b261ecSmrg    if(mask & GCTileStipYOrigin)
29505b261ecSmrg        pGCPriv->patOrg.y = pSrcPriv->patOrg.y;
29605b261ecSmrg    if(mask & GCClipXOrigin)
29705b261ecSmrg        pGCPriv->clipOrg.x = pSrcPriv->clipOrg.x;
29805b261ecSmrg    if(mask & GCClipYOrigin)
29905b261ecSmrg        pGCPriv->clipOrg.y = pSrcPriv->clipOrg.y;
30005b261ecSmrg
30105b261ecSmrg    (*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst);
30205b261ecSmrg    Xinerama_GC_FUNC_EPILOGUE (pGCDst);
30305b261ecSmrg}
30405b261ecSmrg
30505b261ecSmrgstatic void
30605b261ecSmrgXineramaChangeClip (
30705b261ecSmrg    GCPtr   pGC,
30805b261ecSmrg    int		type,
30905b261ecSmrg    pointer	pvalue,
31005b261ecSmrg    int		nrects
31105b261ecSmrg){
31205b261ecSmrg    Xinerama_GC_FUNC_PROLOGUE (pGC);
31305b261ecSmrg    (*pGC->funcs->ChangeClip) (pGC, type, pvalue, nrects);
31405b261ecSmrg    Xinerama_GC_FUNC_EPILOGUE (pGC);
31505b261ecSmrg}
31605b261ecSmrg
31705b261ecSmrgstatic void
31805b261ecSmrgXineramaCopyClip(GCPtr pgcDst, GCPtr pgcSrc)
31905b261ecSmrg{
32005b261ecSmrg    Xinerama_GC_FUNC_PROLOGUE (pgcDst);
32105b261ecSmrg    (* pgcDst->funcs->CopyClip)(pgcDst, pgcSrc);
32205b261ecSmrg    Xinerama_GC_FUNC_EPILOGUE (pgcDst);
32305b261ecSmrg}
32405b261ecSmrg
32505b261ecSmrgstatic void
32605b261ecSmrgXineramaDestroyClip(GCPtr pGC)
32705b261ecSmrg{
32805b261ecSmrg    Xinerama_GC_FUNC_PROLOGUE (pGC);
32905b261ecSmrg    (* pGC->funcs->DestroyClip)(pGC);
33005b261ecSmrg    Xinerama_GC_FUNC_EPILOGUE (pGC);
33105b261ecSmrg}
33205b261ecSmrg
33305b261ecSmrg_X_EXPORT int
33405b261ecSmrgXineramaDeleteResource(pointer data, XID id)
33505b261ecSmrg{
33605b261ecSmrg    xfree(data);
33705b261ecSmrg    return 1;
33805b261ecSmrg}
33905b261ecSmrg
34005b261ecSmrgtypedef struct {
34105b261ecSmrg   int screen;
34205b261ecSmrg   int id;
34305b261ecSmrg} PanoramiXSearchData;
34405b261ecSmrg
34505b261ecSmrgstatic Bool
34605b261ecSmrgXineramaFindIDByScrnum(pointer resource, XID id, pointer privdata)
34705b261ecSmrg{
34805b261ecSmrg    PanoramiXRes *res = (PanoramiXRes*)resource;
34905b261ecSmrg    PanoramiXSearchData *data = (PanoramiXSearchData*)privdata;
35005b261ecSmrg
35105b261ecSmrg    return (res->info[data->screen].id == data->id);
35205b261ecSmrg}
35305b261ecSmrg
35405b261ecSmrgPanoramiXRes *
35505b261ecSmrgPanoramiXFindIDByScrnum(RESTYPE type, XID id, int screen)
35605b261ecSmrg{
35705b261ecSmrg    PanoramiXSearchData data;
35805b261ecSmrg
35905b261ecSmrg    if(!screen)
36005b261ecSmrg	return LookupIDByType(id, type);
36105b261ecSmrg
36205b261ecSmrg    data.screen = screen;
36305b261ecSmrg    data.id = id;
36405b261ecSmrg
36505b261ecSmrg    return LookupClientResourceComplex(clients[CLIENT_ID(id)], type,
36605b261ecSmrg		XineramaFindIDByScrnum, &data);
36705b261ecSmrg}
36805b261ecSmrg
36905b261ecSmrgtypedef struct _connect_callback_list {
37005b261ecSmrg    void (*func)(void);
37105b261ecSmrg    struct _connect_callback_list *next;
37205b261ecSmrg} XineramaConnectionCallbackList;
37305b261ecSmrg
37405b261ecSmrgstatic XineramaConnectionCallbackList *ConnectionCallbackList = NULL;
37505b261ecSmrg
37605b261ecSmrg_X_EXPORT Bool
37705b261ecSmrgXineramaRegisterConnectionBlockCallback(void (*func)(void))
37805b261ecSmrg{
37905b261ecSmrg    XineramaConnectionCallbackList *newlist;
38005b261ecSmrg
38105b261ecSmrg    if(!(newlist = xalloc(sizeof(XineramaConnectionCallbackList))))
38205b261ecSmrg	return FALSE;
38305b261ecSmrg
38405b261ecSmrg    newlist->next = ConnectionCallbackList;
38505b261ecSmrg    newlist->func = func;
38605b261ecSmrg    ConnectionCallbackList = newlist;
38705b261ecSmrg
38805b261ecSmrg    return TRUE;
38905b261ecSmrg}
39005b261ecSmrg
39105b261ecSmrgstatic void XineramaInitData(ScreenPtr pScreen)
39205b261ecSmrg{
39305b261ecSmrg    int i, w, h;
39405b261ecSmrg
39505b261ecSmrg    REGION_NULL(pScreen, &PanoramiXScreenRegion)
39605b261ecSmrg    for (i = 0; i < PanoramiXNumScreens; i++) {
39705b261ecSmrg	BoxRec TheBox;
39805b261ecSmrg
39905b261ecSmrg        pScreen = screenInfo.screens[i];
40005b261ecSmrg
40105b261ecSmrg	panoramiXdataPtr[i].x = dixScreenOrigins[i].x;
40205b261ecSmrg	panoramiXdataPtr[i].y = dixScreenOrigins[i].y;
40305b261ecSmrg	panoramiXdataPtr[i].width = pScreen->width;
40405b261ecSmrg	panoramiXdataPtr[i].height = pScreen->height;
40505b261ecSmrg
40605b261ecSmrg	TheBox.x1 = panoramiXdataPtr[i].x;
40705b261ecSmrg	TheBox.x2 = TheBox.x1 + panoramiXdataPtr[i].width;
40805b261ecSmrg	TheBox.y1 = panoramiXdataPtr[i].y;
40905b261ecSmrg	TheBox.y2 = TheBox.y1 + panoramiXdataPtr[i].height;
41005b261ecSmrg
41105b261ecSmrg	REGION_INIT(pScreen, &XineramaScreenRegions[i], &TheBox, 1);
41205b261ecSmrg	REGION_UNION(pScreen, &PanoramiXScreenRegion, &PanoramiXScreenRegion,
41305b261ecSmrg		     &XineramaScreenRegions[i]);
41405b261ecSmrg    }
41505b261ecSmrg
41605b261ecSmrg    PanoramiXPixWidth = panoramiXdataPtr[0].x + panoramiXdataPtr[0].width;
41705b261ecSmrg    PanoramiXPixHeight = panoramiXdataPtr[0].y + panoramiXdataPtr[0].height;
41805b261ecSmrg
41905b261ecSmrg    for (i = 1; i < PanoramiXNumScreens; i++) {
42005b261ecSmrg	w = panoramiXdataPtr[i].x + panoramiXdataPtr[i].width;
42105b261ecSmrg	h = panoramiXdataPtr[i].y + panoramiXdataPtr[i].height;
42205b261ecSmrg
42305b261ecSmrg	if (PanoramiXPixWidth < w)
42405b261ecSmrg	    PanoramiXPixWidth = w;
42505b261ecSmrg	if (PanoramiXPixHeight < h)
42605b261ecSmrg	    PanoramiXPixHeight = h;
42705b261ecSmrg    }
42805b261ecSmrg}
42905b261ecSmrg
43005b261ecSmrgvoid XineramaReinitData(ScreenPtr pScreen)
43105b261ecSmrg{
43205b261ecSmrg    int i;
43305b261ecSmrg
43405b261ecSmrg    REGION_UNINIT(pScreen, &PanoramiXScreenRegion);
43505b261ecSmrg    for (i = 0; i < PanoramiXNumScreens; i++)
43605b261ecSmrg	REGION_UNINIT(pScreen, &XineramaScreenRegions[i]);
43705b261ecSmrg
43805b261ecSmrg    XineramaInitData(pScreen);
43905b261ecSmrg}
44005b261ecSmrg
44105b261ecSmrg/*
44205b261ecSmrg *	PanoramiXExtensionInit():
44305b261ecSmrg *		Called from InitExtensions in main().
44405b261ecSmrg *		Register PanoramiXeen Extension
44505b261ecSmrg *		Initialize global variables.
44605b261ecSmrg */
44705b261ecSmrg
44805b261ecSmrgvoid PanoramiXExtensionInit(int argc, char *argv[])
44905b261ecSmrg{
45005b261ecSmrg    int 	     	i;
45105b261ecSmrg    Bool	     	success = FALSE;
45205b261ecSmrg    ExtensionEntry 	*extEntry;
45305b261ecSmrg    ScreenPtr		pScreen = screenInfo.screens[0];
45405b261ecSmrg    PanoramiXScreenPtr	pScreenPriv;
45505b261ecSmrg
45605b261ecSmrg    if (noPanoramiXExtension)
45705b261ecSmrg	return;
45805b261ecSmrg
45905b261ecSmrg    PanoramiXNumScreens = screenInfo.numScreens;
46005b261ecSmrg    if (PanoramiXNumScreens == 1) {		/* Only 1 screen 	*/
46105b261ecSmrg	noPanoramiXExtension = TRUE;
46205b261ecSmrg	return;
46305b261ecSmrg    }
46405b261ecSmrg
46505b261ecSmrg    while (panoramiXGeneration != serverGeneration) {
46605b261ecSmrg	extEntry = AddExtension(PANORAMIX_PROTOCOL_NAME, 0,0,
46705b261ecSmrg				ProcPanoramiXDispatch,
46805b261ecSmrg				SProcPanoramiXDispatch, PanoramiXResetProc,
46905b261ecSmrg				StandardMinorOpcode);
4704642e01fSmrg	if (!extEntry)
47105b261ecSmrg	    break;
47205b261ecSmrg
47305b261ecSmrg	/*
47405b261ecSmrg	 *	First make sure all the basic allocations succeed.  If not,
47505b261ecSmrg	 *	run in non-PanoramiXeen mode.
47605b261ecSmrg	 */
47705b261ecSmrg
47805b261ecSmrg	panoramiXdataPtr = (PanoramiXData *)
47905b261ecSmrg		xcalloc(PanoramiXNumScreens, sizeof(PanoramiXData));
48005b261ecSmrg
48105b261ecSmrg        BREAK_IF(!panoramiXdataPtr);
4824642e01fSmrg
4834642e01fSmrg	if (!dixRequestPrivate(PanoramiXGCKey, sizeof(PanoramiXGCRec))) {
4844642e01fSmrg		noPanoramiXExtension = TRUE;
4854642e01fSmrg		return;
4864642e01fSmrg	}
48705b261ecSmrg
48805b261ecSmrg	for (i = 0; i < PanoramiXNumScreens; i++) {
48905b261ecSmrg	   pScreen = screenInfo.screens[i];
49005b261ecSmrg	   pScreenPriv = xalloc(sizeof(PanoramiXScreenRec));
4914642e01fSmrg	   dixSetPrivate(&pScreen->devPrivates, PanoramiXScreenKey,
4924642e01fSmrg			 pScreenPriv);
49305b261ecSmrg	   if(!pScreenPriv) {
49405b261ecSmrg		noPanoramiXExtension = TRUE;
49505b261ecSmrg		return;
49605b261ecSmrg	   }
49705b261ecSmrg
49805b261ecSmrg	   pScreenPriv->CreateGC = pScreen->CreateGC;
49905b261ecSmrg	   pScreenPriv->CloseScreen = pScreen->CloseScreen;
50005b261ecSmrg
50105b261ecSmrg	   pScreen->CreateGC = XineramaCreateGC;
50205b261ecSmrg	   pScreen->CloseScreen = XineramaCloseScreen;
50305b261ecSmrg	}
50405b261ecSmrg
50505b261ecSmrg	XRC_DRAWABLE = CreateNewResourceClass();
50605b261ecSmrg	XRT_WINDOW = CreateNewResourceType(XineramaDeleteResource) |
50705b261ecSmrg						XRC_DRAWABLE;
50805b261ecSmrg	XRT_PIXMAP = CreateNewResourceType(XineramaDeleteResource) |
50905b261ecSmrg						XRC_DRAWABLE;
51005b261ecSmrg	XRT_GC = CreateNewResourceType(XineramaDeleteResource);
51105b261ecSmrg	XRT_COLORMAP = CreateNewResourceType(XineramaDeleteResource);
51205b261ecSmrg
51305b261ecSmrg	panoramiXGeneration = serverGeneration;
51405b261ecSmrg	success = TRUE;
51505b261ecSmrg    }
51605b261ecSmrg
51705b261ecSmrg    if (!success) {
51805b261ecSmrg	noPanoramiXExtension = TRUE;
5194642e01fSmrg	ErrorF(PANORAMIX_PROTOCOL_NAME " extension failed to initialize\n");
52005b261ecSmrg	return;
52105b261ecSmrg    }
52205b261ecSmrg
52305b261ecSmrg    XineramaInitData(pScreen);
52405b261ecSmrg
52505b261ecSmrg    /*
52605b261ecSmrg     *	Put our processes into the ProcVector
52705b261ecSmrg     */
52805b261ecSmrg
52905b261ecSmrg    for (i = 256; i--; )
53005b261ecSmrg	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
58405b261ecSmrg#ifdef RENDER
58505b261ecSmrg    PanoramiXRenderInit ();
58605b261ecSmrg#endif
58705b261ecSmrg}
58805b261ecSmrg
58905b261ecSmrgextern Bool CreateConnectionBlock(void);
59005b261ecSmrg
59105b261ecSmrgBool PanoramiXCreateConnectionBlock(void)
59205b261ecSmrg{
59305b261ecSmrg    int i, j, length;
59405b261ecSmrg    Bool disableBackingStore = FALSE;
59505b261ecSmrg    int old_width, old_height;
59605b261ecSmrg    float width_mult, height_mult;
59705b261ecSmrg    xWindowRoot *root;
59805b261ecSmrg    xVisualType *visual;
59905b261ecSmrg    xDepth *depth;
60005b261ecSmrg    VisualPtr pVisual;
60105b261ecSmrg    ScreenPtr pScreen;
60205b261ecSmrg
60305b261ecSmrg    /*
60405b261ecSmrg     *	Do normal CreateConnectionBlock but faking it for only one screen
60505b261ecSmrg     */
60605b261ecSmrg
60705b261ecSmrg    if(!PanoramiXNumDepths) {
6084642e01fSmrg	ErrorF("Xinerama error: No common visuals\n");
60905b261ecSmrg	return FALSE;
61005b261ecSmrg    }
61105b261ecSmrg
61205b261ecSmrg    for(i = 1; i < screenInfo.numScreens; i++) {
61305b261ecSmrg	pScreen = screenInfo.screens[i];
61405b261ecSmrg	if(pScreen->rootDepth != screenInfo.screens[0]->rootDepth) {
6154642e01fSmrg	    ErrorF("Xinerama error: Root window depths differ\n");
61605b261ecSmrg	    return FALSE;
61705b261ecSmrg	}
61805b261ecSmrg	if(pScreen->backingStoreSupport != screenInfo.screens[0]->backingStoreSupport)
61905b261ecSmrg	     disableBackingStore = TRUE;
62005b261ecSmrg    }
62105b261ecSmrg
6224642e01fSmrg    if (disableBackingStore) {
6234642e01fSmrg    	for (i = 0; i < screenInfo.numScreens; i++) {
62405b261ecSmrg	    pScreen = screenInfo.screens[i];
6254642e01fSmrg	    pScreen->backingStoreSupport = NotUseful;
62605b261ecSmrg	}
62705b261ecSmrg    }
62805b261ecSmrg
62905b261ecSmrg    i = screenInfo.numScreens;
63005b261ecSmrg    screenInfo.numScreens = 1;
63105b261ecSmrg    if (!CreateConnectionBlock()) {
63205b261ecSmrg	screenInfo.numScreens = i;
63305b261ecSmrg	return FALSE;
63405b261ecSmrg    }
63505b261ecSmrg
63605b261ecSmrg    screenInfo.numScreens = i;
63705b261ecSmrg
63805b261ecSmrg    root = (xWindowRoot *) (ConnectionInfo + connBlockScreenStart);
63905b261ecSmrg    length = connBlockScreenStart + sizeof(xWindowRoot);
64005b261ecSmrg
64105b261ecSmrg    /* overwrite the connection block */
64205b261ecSmrg    root->nDepths = PanoramiXNumDepths;
64305b261ecSmrg
64405b261ecSmrg    for (i = 0; i < PanoramiXNumDepths; i++) {
64505b261ecSmrg	depth = (xDepth *) (ConnectionInfo + length);
64605b261ecSmrg	depth->depth = PanoramiXDepths[i].depth;
64705b261ecSmrg	depth->nVisuals = PanoramiXDepths[i].numVids;
64805b261ecSmrg	length += sizeof(xDepth);
64905b261ecSmrg	visual = (xVisualType *)(ConnectionInfo + length);
65005b261ecSmrg
65105b261ecSmrg	for (j = 0; j < depth->nVisuals; j++, visual++) {
65205b261ecSmrg	    visual->visualID = PanoramiXDepths[i].vids[j];
65305b261ecSmrg
65405b261ecSmrg	    for (pVisual = PanoramiXVisuals;
65505b261ecSmrg		 pVisual->vid != visual->visualID;
65605b261ecSmrg		 pVisual++)
65705b261ecSmrg	         ;
65805b261ecSmrg
65905b261ecSmrg	    visual->class = pVisual->class;
66005b261ecSmrg	    visual->bitsPerRGB = pVisual->bitsPerRGBValue;
66105b261ecSmrg	    visual->colormapEntries = pVisual->ColormapEntries;
66205b261ecSmrg	    visual->redMask = pVisual->redMask;
66305b261ecSmrg	    visual->greenMask = pVisual->greenMask;
66405b261ecSmrg	    visual->blueMask = pVisual->blueMask;
66505b261ecSmrg	}
66605b261ecSmrg
66705b261ecSmrg	length += (depth->nVisuals * sizeof(xVisualType));
66805b261ecSmrg    }
66905b261ecSmrg
67005b261ecSmrg    connSetupPrefix.length = length >> 2;
67105b261ecSmrg
67205b261ecSmrg    for (i = 0; i < PanoramiXNumDepths; i++)
67305b261ecSmrg	xfree(PanoramiXDepths[i].vids);
67405b261ecSmrg    xfree(PanoramiXDepths);
6754642e01fSmrg    PanoramiXDepths = NULL;
67605b261ecSmrg
67705b261ecSmrg    /*
67805b261ecSmrg     *  OK, change some dimensions so it looks as if it were one big screen
67905b261ecSmrg     */
68005b261ecSmrg
68105b261ecSmrg    old_width = root->pixWidth;
68205b261ecSmrg    old_height = root->pixHeight;
68305b261ecSmrg
68405b261ecSmrg    root->pixWidth = PanoramiXPixWidth;
68505b261ecSmrg    root->pixHeight = PanoramiXPixHeight;
68605b261ecSmrg    width_mult = (1.0 * root->pixWidth) / old_width;
68705b261ecSmrg    height_mult = (1.0 * root->pixHeight) / old_height;
68805b261ecSmrg    root->mmWidth *= width_mult;
68905b261ecSmrg    root->mmHeight *= height_mult;
69005b261ecSmrg
69105b261ecSmrg    while(ConnectionCallbackList) {
69205b261ecSmrg	pointer tmp;
69305b261ecSmrg
69405b261ecSmrg	tmp = (pointer)ConnectionCallbackList;
69505b261ecSmrg	(*ConnectionCallbackList->func)();
69605b261ecSmrg	ConnectionCallbackList = ConnectionCallbackList->next;
69705b261ecSmrg	xfree(tmp);
69805b261ecSmrg    }
69905b261ecSmrg
70005b261ecSmrg    return TRUE;
70105b261ecSmrg}
70205b261ecSmrg
7034642e01fSmrg/*
7044642e01fSmrg * This isn't just memcmp(), bitsPerRGBValue is skipped.  markv made that
7054642e01fSmrg * change way back before xf86 4.0, but the comment for _why_ is a bit
7064642e01fSmrg * opaque, so I'm not going to question it for now.
7074642e01fSmrg *
7084642e01fSmrg * This is probably better done as a screen hook so DBE/EVI/GLX can add
7094642e01fSmrg * their own tests, and adding privates to VisualRec so they don't have to
7104642e01fSmrg * do their own back-mapping.
7114642e01fSmrg */
7124642e01fSmrgstatic Bool
7134642e01fSmrgVisualsEqual(VisualPtr a, ScreenPtr pScreenB, VisualPtr b)
71405b261ecSmrg{
7154642e01fSmrg    return ((a->class == b->class) &&
7164642e01fSmrg	(a->ColormapEntries == b->ColormapEntries) &&
7174642e01fSmrg	(a->nplanes == b->nplanes) &&
7184642e01fSmrg	(a->redMask == b->redMask) &&
7194642e01fSmrg	(a->greenMask == b->greenMask) &&
7204642e01fSmrg	(a->blueMask == b->blueMask) &&
7214642e01fSmrg	(a->offsetRed == b->offsetRed) &&
7224642e01fSmrg	(a->offsetGreen == b->offsetGreen) &&
7234642e01fSmrg	(a->offsetBlue == b->offsetBlue));
7244642e01fSmrg}
72505b261ecSmrg
7264642e01fSmrgstatic void
7274642e01fSmrgPanoramiXMaybeAddDepth(DepthPtr pDepth)
7284642e01fSmrg{
7294642e01fSmrg    ScreenPtr pScreen;
7304642e01fSmrg    int j, k;
7314642e01fSmrg    Bool found = FALSE;
7324642e01fSmrg
7334642e01fSmrg    for (j = 1; j < PanoramiXNumScreens; j++) {
7344642e01fSmrg	pScreen = screenInfo.screens[j];
7354642e01fSmrg	for (k = 0; k < pScreen->numDepths; k++) {
7364642e01fSmrg	    if (pScreen->allowedDepths[k].depth == pDepth->depth) {
7374642e01fSmrg		found = TRUE;
7384642e01fSmrg		break;
7394642e01fSmrg	    }
7404642e01fSmrg	}
7414642e01fSmrg    }
74205b261ecSmrg
7434642e01fSmrg    if (!found)
7444642e01fSmrg	return;
74505b261ecSmrg
7464642e01fSmrg    j = PanoramiXNumDepths;
7474642e01fSmrg    PanoramiXNumDepths++;
7484642e01fSmrg    PanoramiXDepths = xrealloc(PanoramiXDepths,
7494642e01fSmrg	    PanoramiXNumDepths * sizeof(DepthRec));
7504642e01fSmrg    PanoramiXDepths[j].depth = pDepth->depth;
7514642e01fSmrg    PanoramiXDepths[j].numVids = 0;
7524642e01fSmrg    /* XXX suboptimal, should grow these dynamically */
7534642e01fSmrg    if(pDepth->numVids)
7544642e01fSmrg	PanoramiXDepths[j].vids = xalloc(sizeof(VisualID) * pDepth->numVids);
7554642e01fSmrg    else
7564642e01fSmrg	PanoramiXDepths[j].vids = NULL;
7574642e01fSmrg}
7584642e01fSmrg
7594642e01fSmrgstatic void
7604642e01fSmrgPanoramiXMaybeAddVisual(VisualPtr pVisual)
7614642e01fSmrg{
7624642e01fSmrg    ScreenPtr pScreen;
7634642e01fSmrg    int j, k;
7644642e01fSmrg    Bool found = FALSE;
76505b261ecSmrg
7664642e01fSmrg    for (j = 1; j < PanoramiXNumScreens; j++) {
7674642e01fSmrg	pScreen = screenInfo.screens[j];
7684642e01fSmrg	found = FALSE;
76905b261ecSmrg
7704642e01fSmrg	for (k = 0; k < pScreen->numVisuals; k++) {
7714642e01fSmrg	    VisualPtr candidate = &pScreen->visuals[k];
77205b261ecSmrg
7734642e01fSmrg	    if ((*XineramaVisualsEqualPtr)(pVisual, pScreen, candidate)
77405b261ecSmrg#ifdef GLXPROXY
7754642e01fSmrg		&& glxMatchVisual(screenInfo.screens[0], pVisual, pScreen)
77605b261ecSmrg#endif
7774642e01fSmrg		    ) {
7784642e01fSmrg		found = TRUE;
77905b261ecSmrg		break;
78005b261ecSmrg	    }
78105b261ecSmrg	}
78205b261ecSmrg
7834642e01fSmrg	if (!found)
7844642e01fSmrg	    return;
7854642e01fSmrg    }
7864642e01fSmrg
7874642e01fSmrg    /* found a matching visual on all screens, add it to the subset list */
7884642e01fSmrg    j = PanoramiXNumVisuals;
7894642e01fSmrg    PanoramiXNumVisuals++;
7904642e01fSmrg    PanoramiXVisuals = xrealloc(PanoramiXVisuals,
7914642e01fSmrg	    PanoramiXNumVisuals * sizeof(VisualRec));
7924642e01fSmrg
7934642e01fSmrg    memcpy(&PanoramiXVisuals[j], pVisual, sizeof(VisualRec));
7944642e01fSmrg
7954642e01fSmrg    for (k = 0; k < PanoramiXNumDepths; k++) {
7964642e01fSmrg	if (PanoramiXDepths[k].depth == pVisual->nplanes) {
7974642e01fSmrg	    PanoramiXDepths[k].vids[PanoramiXDepths[k].numVids] = pVisual->vid;
7984642e01fSmrg	    PanoramiXDepths[k].numVids++;
7994642e01fSmrg	    break;
8004642e01fSmrg	}
8014642e01fSmrg    }
8024642e01fSmrg}
8034642e01fSmrg
8044642e01fSmrgextern void
8054642e01fSmrgPanoramiXConsolidate(void)
8064642e01fSmrg{
8074642e01fSmrg    int 	i;
8084642e01fSmrg    PanoramiXRes *root, *defmap, *saver;
8094642e01fSmrg    ScreenPtr   pScreen = screenInfo.screens[0];
8104642e01fSmrg    DepthPtr    pDepth = pScreen->allowedDepths;
8114642e01fSmrg    VisualPtr   pVisual = pScreen->visuals;
8124642e01fSmrg
8134642e01fSmrg    PanoramiXNumDepths = 0;
8144642e01fSmrg    PanoramiXNumVisuals = 0;
81505b261ecSmrg
8164642e01fSmrg    for (i = 0; i < pScreen->numDepths; i++)
8174642e01fSmrg	PanoramiXMaybeAddDepth(pDepth++);
81805b261ecSmrg
8194642e01fSmrg    for (i = 0; i < pScreen->numVisuals; i++)
8204642e01fSmrg	PanoramiXMaybeAddVisual(pVisual++);
8214642e01fSmrg
8224642e01fSmrg    root = xalloc(sizeof(PanoramiXRes));
82305b261ecSmrg    root->type = XRT_WINDOW;
8244642e01fSmrg    defmap = xalloc(sizeof(PanoramiXRes));
82505b261ecSmrg    defmap->type = XRT_COLORMAP;
8264642e01fSmrg    saver = xalloc(sizeof(PanoramiXRes));
82705b261ecSmrg    saver->type = XRT_WINDOW;
82805b261ecSmrg
82905b261ecSmrg    for (i =  0; i < PanoramiXNumScreens; i++) {
83005b261ecSmrg	root->info[i].id = WindowTable[i]->drawable.id;
83105b261ecSmrg	root->u.win.class = InputOutput;
83205b261ecSmrg        root->u.win.root = TRUE;
83305b261ecSmrg        saver->info[i].id = savedScreenInfo[i].wid;
83405b261ecSmrg        saver->u.win.class = InputOutput;
83505b261ecSmrg        saver->u.win.root = TRUE;
83605b261ecSmrg	defmap->info[i].id = (screenInfo.screens[i])->defColormap;
83705b261ecSmrg    }
83805b261ecSmrg
83905b261ecSmrg    AddResource(root->info[0].id, XRT_WINDOW, root);
84005b261ecSmrg    AddResource(saver->info[0].id, XRT_WINDOW, saver);
84105b261ecSmrg    AddResource(defmap->info[0].id, XRT_COLORMAP, defmap);
84205b261ecSmrg}
84305b261ecSmrg
8444642e01fSmrg_X_EXPORT VisualID
8454642e01fSmrgPanoramiXTranslateVisualID(int screen, VisualID orig)
8464642e01fSmrg{
8474642e01fSmrg    ScreenPtr pOtherScreen = screenInfo.screens[screen];
8484642e01fSmrg    VisualPtr pVisual = NULL;
8494642e01fSmrg    int i;
8504642e01fSmrg
8514642e01fSmrg    for (i = 0; i < PanoramiXNumVisuals; i++) {
8524642e01fSmrg	if (orig == PanoramiXVisuals[i].vid) {
8534642e01fSmrg	    pVisual = &PanoramiXVisuals[i];
8544642e01fSmrg	    break;
8554642e01fSmrg	}
8564642e01fSmrg    }
8574642e01fSmrg
8584642e01fSmrg    if (!pVisual)
8594642e01fSmrg	return 0;
8604642e01fSmrg
8614642e01fSmrg    /* if screen is 0, orig is already the correct visual ID */
8624642e01fSmrg    if (screen == 0)
8634642e01fSmrg	return orig;
8644642e01fSmrg
8654642e01fSmrg    /* found the original, now translate it relative to the backend screen */
8664642e01fSmrg    for (i = 0; i < pOtherScreen->numVisuals; i++) {
8674642e01fSmrg	VisualPtr pOtherVisual = &pOtherScreen->visuals[i];
8684642e01fSmrg
8694642e01fSmrg	if ((*XineramaVisualsEqualPtr)(pVisual, pOtherScreen, pOtherVisual))
8704642e01fSmrg	    return pOtherVisual->vid;
8714642e01fSmrg    }
8724642e01fSmrg
8734642e01fSmrg    return 0;
8744642e01fSmrg}
8754642e01fSmrg
87605b261ecSmrg
87705b261ecSmrg/*
87805b261ecSmrg *	PanoramiXResetProc()
87905b261ecSmrg *		Exit, deallocating as needed.
88005b261ecSmrg */
88105b261ecSmrg
88205b261ecSmrgstatic void PanoramiXResetProc(ExtensionEntry* extEntry)
88305b261ecSmrg{
88405b261ecSmrg    int		i;
88505b261ecSmrg
88605b261ecSmrg#ifdef RENDER
88705b261ecSmrg    PanoramiXRenderReset ();
88805b261ecSmrg#endif
88905b261ecSmrg    screenInfo.numScreens = PanoramiXNumScreens;
89005b261ecSmrg    for (i = 256; i--; )
89105b261ecSmrg	ProcVector[i] = SavedProcVector[i];
89205b261ecSmrg
89305b261ecSmrg    Xfree(panoramiXdataPtr);
89405b261ecSmrg}
89505b261ecSmrg
89605b261ecSmrg
89705b261ecSmrgint
89805b261ecSmrgProcPanoramiXQueryVersion (ClientPtr client)
89905b261ecSmrg{
90005b261ecSmrg    /* REQUEST(xPanoramiXQueryVersionReq); */
90105b261ecSmrg    xPanoramiXQueryVersionReply		rep;
90205b261ecSmrg    register 	int			n;
90305b261ecSmrg
90405b261ecSmrg    REQUEST_SIZE_MATCH (xPanoramiXQueryVersionReq);
90505b261ecSmrg    rep.type = X_Reply;
90605b261ecSmrg    rep.length = 0;
90705b261ecSmrg    rep.sequenceNumber = client->sequence;
90852397711Smrg    rep.majorVersion = SERVER_PANORAMIX_MAJOR_VERSION;
90952397711Smrg    rep.minorVersion = SERVER_PANORAMIX_MINOR_VERSION;
91005b261ecSmrg    if (client->swapped) {
91105b261ecSmrg        swaps(&rep.sequenceNumber, n);
91205b261ecSmrg        swapl(&rep.length, n);
91305b261ecSmrg        swaps(&rep.majorVersion, n);
91405b261ecSmrg        swaps(&rep.minorVersion, n);
91505b261ecSmrg    }
91605b261ecSmrg    WriteToClient(client, sizeof (xPanoramiXQueryVersionReply), (char *)&rep);
91705b261ecSmrg    return (client->noClientException);
91805b261ecSmrg}
91905b261ecSmrg
92005b261ecSmrgint
92105b261ecSmrgProcPanoramiXGetState(ClientPtr client)
92205b261ecSmrg{
92305b261ecSmrg	REQUEST(xPanoramiXGetStateReq);
92405b261ecSmrg    	WindowPtr			pWin;
92505b261ecSmrg	xPanoramiXGetStateReply		rep;
9264642e01fSmrg	int			n, rc;
92705b261ecSmrg
92805b261ecSmrg	REQUEST_SIZE_MATCH(xPanoramiXGetStateReq);
9294642e01fSmrg	rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
93005b261ecSmrg	if (rc != Success)
93105b261ecSmrg	    return rc;
93205b261ecSmrg
93305b261ecSmrg	rep.type = X_Reply;
93405b261ecSmrg	rep.length = 0;
93505b261ecSmrg	rep.sequenceNumber = client->sequence;
93605b261ecSmrg	rep.state = !noPanoramiXExtension;
9374642e01fSmrg	rep.window = stuff->window;
93805b261ecSmrg    	if (client->swapped) {
93905b261ecSmrg	    swaps (&rep.sequenceNumber, n);
94005b261ecSmrg	    swapl (&rep.length, n);
9414642e01fSmrg	    swapl (&rep.window, n);
94205b261ecSmrg	}
94305b261ecSmrg	WriteToClient (client, sizeof (xPanoramiXGetStateReply), (char *) &rep);
94405b261ecSmrg	return client->noClientException;
94505b261ecSmrg
94605b261ecSmrg}
94705b261ecSmrg
94805b261ecSmrgint
94905b261ecSmrgProcPanoramiXGetScreenCount(ClientPtr client)
95005b261ecSmrg{
95105b261ecSmrg	REQUEST(xPanoramiXGetScreenCountReq);
95205b261ecSmrg    	WindowPtr			pWin;
95305b261ecSmrg	xPanoramiXGetScreenCountReply	rep;
9544642e01fSmrg	int			n, rc;
95505b261ecSmrg
95605b261ecSmrg	REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq);
9574642e01fSmrg	rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
95805b261ecSmrg	if (rc != Success)
95905b261ecSmrg	    return rc;
96005b261ecSmrg
96105b261ecSmrg	rep.type = X_Reply;
96205b261ecSmrg	rep.length = 0;
96305b261ecSmrg	rep.sequenceNumber = client->sequence;
96405b261ecSmrg	rep.ScreenCount = PanoramiXNumScreens;
9654642e01fSmrg	rep.window = stuff->window;
96605b261ecSmrg    	if (client->swapped) {
96705b261ecSmrg	    swaps (&rep.sequenceNumber, n);
96805b261ecSmrg	    swapl (&rep.length, n);
9694642e01fSmrg	    swapl (&rep.window, n);
97005b261ecSmrg	}
97105b261ecSmrg	WriteToClient (client, sizeof (xPanoramiXGetScreenCountReply), (char *) &rep);
97205b261ecSmrg	return client->noClientException;
97305b261ecSmrg}
97405b261ecSmrg
97505b261ecSmrgint
97605b261ecSmrgProcPanoramiXGetScreenSize(ClientPtr client)
97705b261ecSmrg{
97805b261ecSmrg	REQUEST(xPanoramiXGetScreenSizeReq);
97905b261ecSmrg    	WindowPtr			pWin;
98005b261ecSmrg	xPanoramiXGetScreenSizeReply	rep;
9814642e01fSmrg	int			n, rc;
98205b261ecSmrg
9834642e01fSmrg	if (stuff->screen >= PanoramiXNumScreens)
9844642e01fSmrg	    return BadMatch;
9854642e01fSmrg
98605b261ecSmrg	REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq);
9874642e01fSmrg	rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
98805b261ecSmrg	if (rc != Success)
98905b261ecSmrg	    return rc;
99005b261ecSmrg
99105b261ecSmrg	rep.type = X_Reply;
99205b261ecSmrg	rep.length = 0;
99305b261ecSmrg	rep.sequenceNumber = client->sequence;
99405b261ecSmrg		/* screen dimensions */
99505b261ecSmrg	rep.width  = panoramiXdataPtr[stuff->screen].width;
99605b261ecSmrg	rep.height = panoramiXdataPtr[stuff->screen].height;
9974642e01fSmrg	rep.window = stuff->window;
9984642e01fSmrg	rep.screen = stuff->screen;
99905b261ecSmrg    	if (client->swapped) {
100005b261ecSmrg	    swaps (&rep.sequenceNumber, n);
100105b261ecSmrg	    swapl (&rep.length, n);
10024642e01fSmrg	    swapl (&rep.width, n);
10034642e01fSmrg	    swapl (&rep.height, n);
10044642e01fSmrg	    swapl (&rep.window, n);
10054642e01fSmrg	    swapl (&rep.screen, n);
100605b261ecSmrg	}
100705b261ecSmrg	WriteToClient (client, sizeof (xPanoramiXGetScreenSizeReply), (char *) &rep);
100805b261ecSmrg	return client->noClientException;
100905b261ecSmrg}
101005b261ecSmrg
101105b261ecSmrg
101205b261ecSmrgint
101305b261ecSmrgProcXineramaIsActive(ClientPtr client)
101405b261ecSmrg{
101505b261ecSmrg    /* REQUEST(xXineramaIsActiveReq); */
101605b261ecSmrg    xXineramaIsActiveReply	rep;
101705b261ecSmrg
101805b261ecSmrg    REQUEST_SIZE_MATCH(xXineramaIsActiveReq);
101905b261ecSmrg
102005b261ecSmrg    rep.type = X_Reply;
102105b261ecSmrg    rep.length = 0;
102205b261ecSmrg    rep.sequenceNumber = client->sequence;
102305b261ecSmrg#if 1
102405b261ecSmrg    {
102505b261ecSmrg	/* The following hack fools clients into thinking that Xinerama
102605b261ecSmrg	 * is disabled even though it is not. */
102705b261ecSmrg	rep.state = !noPanoramiXExtension && !PanoramiXExtensionDisabledHack;
102805b261ecSmrg    }
102905b261ecSmrg#else
103005b261ecSmrg    rep.state = !noPanoramiXExtension;
103105b261ecSmrg#endif
103205b261ecSmrg    if (client->swapped) {
10334642e01fSmrg	int n;
103405b261ecSmrg	swaps (&rep.sequenceNumber, n);
103505b261ecSmrg	swapl (&rep.length, n);
103605b261ecSmrg	swapl (&rep.state, n);
103705b261ecSmrg    }
103805b261ecSmrg    WriteToClient (client, sizeof (xXineramaIsActiveReply), (char *) &rep);
103905b261ecSmrg    return client->noClientException;
104005b261ecSmrg}
104105b261ecSmrg
104205b261ecSmrg
104305b261ecSmrgint
104405b261ecSmrgProcXineramaQueryScreens(ClientPtr client)
104505b261ecSmrg{
104605b261ecSmrg    /* REQUEST(xXineramaQueryScreensReq); */
104705b261ecSmrg    xXineramaQueryScreensReply	rep;
104805b261ecSmrg
104905b261ecSmrg    REQUEST_SIZE_MATCH(xXineramaQueryScreensReq);
105005b261ecSmrg
105105b261ecSmrg    rep.type = X_Reply;
105205b261ecSmrg    rep.sequenceNumber = client->sequence;
105305b261ecSmrg    rep.number = (noPanoramiXExtension) ? 0 : PanoramiXNumScreens;
105405b261ecSmrg    rep.length = rep.number * sz_XineramaScreenInfo >> 2;
105505b261ecSmrg    if (client->swapped) {
10564642e01fSmrg	int n;
105705b261ecSmrg	swaps (&rep.sequenceNumber, n);
105805b261ecSmrg	swapl (&rep.length, n);
105905b261ecSmrg	swapl (&rep.number, n);
106005b261ecSmrg    }
106105b261ecSmrg    WriteToClient (client, sizeof (xXineramaQueryScreensReply), (char *) &rep);
106205b261ecSmrg
106305b261ecSmrg    if(!noPanoramiXExtension) {
106405b261ecSmrg	xXineramaScreenInfo scratch;
106505b261ecSmrg	int i;
106605b261ecSmrg
106705b261ecSmrg	for(i = 0; i < PanoramiXNumScreens; i++) {
106805b261ecSmrg	    scratch.x_org  = panoramiXdataPtr[i].x;
106905b261ecSmrg	    scratch.y_org  = panoramiXdataPtr[i].y;
107005b261ecSmrg	    scratch.width  = panoramiXdataPtr[i].width;
107105b261ecSmrg	    scratch.height = panoramiXdataPtr[i].height;
107205b261ecSmrg
107305b261ecSmrg	    if(client->swapped) {
10744642e01fSmrg		int n;
107505b261ecSmrg		swaps (&scratch.x_org, n);
107605b261ecSmrg		swaps (&scratch.y_org, n);
107705b261ecSmrg		swaps (&scratch.width, n);
107805b261ecSmrg		swaps (&scratch.height, n);
107905b261ecSmrg	    }
108005b261ecSmrg	    WriteToClient (client, sz_XineramaScreenInfo, (char *) &scratch);
108105b261ecSmrg	}
108205b261ecSmrg    }
108305b261ecSmrg
108405b261ecSmrg    return client->noClientException;
108505b261ecSmrg}
108605b261ecSmrg
108705b261ecSmrg
108805b261ecSmrgstatic int
108905b261ecSmrgProcPanoramiXDispatch (ClientPtr client)
109005b261ecSmrg{   REQUEST(xReq);
109105b261ecSmrg    switch (stuff->data)
109205b261ecSmrg    {
109305b261ecSmrg	case X_PanoramiXQueryVersion:
109405b261ecSmrg	     return ProcPanoramiXQueryVersion(client);
109505b261ecSmrg	case X_PanoramiXGetState:
109605b261ecSmrg	     return ProcPanoramiXGetState(client);
109705b261ecSmrg	case X_PanoramiXGetScreenCount:
109805b261ecSmrg	     return ProcPanoramiXGetScreenCount(client);
109905b261ecSmrg	case X_PanoramiXGetScreenSize:
110005b261ecSmrg	     return ProcPanoramiXGetScreenSize(client);
110105b261ecSmrg	case X_XineramaIsActive:
110205b261ecSmrg	     return ProcXineramaIsActive(client);
110305b261ecSmrg	case X_XineramaQueryScreens:
110405b261ecSmrg	     return ProcXineramaQueryScreens(client);
110505b261ecSmrg    }
110605b261ecSmrg    return BadRequest;
110705b261ecSmrg}
110805b261ecSmrg
110905b261ecSmrg
111005b261ecSmrg#if X_BYTE_ORDER == X_LITTLE_ENDIAN
111105b261ecSmrg#define SHIFT_L(v,s) (v) << (s)
111205b261ecSmrg#define SHIFT_R(v,s) (v) >> (s)
111305b261ecSmrg#else
111405b261ecSmrg#define SHIFT_L(v,s) (v) >> (s)
111505b261ecSmrg#define SHIFT_R(v,s) (v) << (s)
111605b261ecSmrg#endif
111705b261ecSmrg
111805b261ecSmrgstatic void
111905b261ecSmrgCopyBits(char *dst, int shiftL, char *src, int bytes)
112005b261ecSmrg{
112105b261ecSmrg   /* Just get it to work.  Worry about speed later */
112205b261ecSmrg    int shiftR = 8 - shiftL;
112305b261ecSmrg
112405b261ecSmrg    while(bytes--) {
112505b261ecSmrg	*dst |= SHIFT_L(*src, shiftL);
112605b261ecSmrg	*(dst + 1) |= SHIFT_R(*src, shiftR);
112705b261ecSmrg	dst++; src++;
112805b261ecSmrg    }
112905b261ecSmrg}
113005b261ecSmrg
113105b261ecSmrg
113205b261ecSmrg/* Caution.  This doesn't support 2 and 4 bpp formats.  We expect
113305b261ecSmrg   1 bpp and planar data to be already cleared when presented
113405b261ecSmrg   to this function */
113505b261ecSmrg
113605b261ecSmrgvoid
113705b261ecSmrgXineramaGetImageData(
113805b261ecSmrg    DrawablePtr *pDrawables,
113905b261ecSmrg    int left,
114005b261ecSmrg    int top,
114105b261ecSmrg    int width,
114205b261ecSmrg    int height,
114305b261ecSmrg    unsigned int format,
114405b261ecSmrg    unsigned long planemask,
114505b261ecSmrg    char *data,
114605b261ecSmrg    int pitch,
114705b261ecSmrg    Bool isRoot
114805b261ecSmrg){
114905b261ecSmrg    RegionRec SrcRegion, GrabRegion;
115005b261ecSmrg    BoxRec SrcBox, *pbox;
115105b261ecSmrg    int x, y, w, h, i, j, nbox, size, sizeNeeded, ScratchPitch, inOut, depth;
115205b261ecSmrg    DrawablePtr pDraw = pDrawables[0];
115305b261ecSmrg    char *ScratchMem = NULL;
115405b261ecSmrg
115505b261ecSmrg    size = 0;
115605b261ecSmrg
115705b261ecSmrg    /* find box in logical screen space */
115805b261ecSmrg    SrcBox.x1 = left;
115905b261ecSmrg    SrcBox.y1 = top;
116005b261ecSmrg    if(!isRoot) {
116105b261ecSmrg	SrcBox.x1 += pDraw->x + panoramiXdataPtr[0].x;
116205b261ecSmrg	SrcBox.y1 += pDraw->y + panoramiXdataPtr[0].y;
116305b261ecSmrg    }
116405b261ecSmrg    SrcBox.x2 = SrcBox.x1 + width;
116505b261ecSmrg    SrcBox.y2 = SrcBox.y1 + height;
116605b261ecSmrg
116705b261ecSmrg    REGION_INIT(pScreen, &SrcRegion, &SrcBox, 1);
116805b261ecSmrg    REGION_NULL(pScreen, &GrabRegion);
116905b261ecSmrg
117005b261ecSmrg    depth = (format == XYPixmap) ? 1 : pDraw->depth;
117105b261ecSmrg
117205b261ecSmrg    for(i = 0; i < PanoramiXNumScreens; i++) {
117305b261ecSmrg	pDraw = pDrawables[i];
117405b261ecSmrg
117505b261ecSmrg	inOut = RECT_IN_REGION(pScreen,&XineramaScreenRegions[i],&SrcBox);
117605b261ecSmrg
117705b261ecSmrg	if(inOut == rgnIN) {
117805b261ecSmrg	    (*pDraw->pScreen->GetImage)(pDraw,
117905b261ecSmrg			SrcBox.x1 - pDraw->x - panoramiXdataPtr[i].x,
118005b261ecSmrg			SrcBox.y1 - pDraw->y - panoramiXdataPtr[i].y,
118105b261ecSmrg			width, height, format, planemask, data);
118205b261ecSmrg	    break;
118305b261ecSmrg	} else if (inOut == rgnOUT)
118405b261ecSmrg	    continue;
118505b261ecSmrg
118605b261ecSmrg	REGION_INTERSECT(pScreen, &GrabRegion, &SrcRegion,
118705b261ecSmrg					&XineramaScreenRegions[i]);
118805b261ecSmrg
118905b261ecSmrg	nbox = REGION_NUM_RECTS(&GrabRegion);
119005b261ecSmrg
119105b261ecSmrg	if(nbox) {
119205b261ecSmrg	    pbox = REGION_RECTS(&GrabRegion);
119305b261ecSmrg
119405b261ecSmrg	    while(nbox--) {
119505b261ecSmrg		w = pbox->x2 - pbox->x1;
119605b261ecSmrg		h = pbox->y2 - pbox->y1;
119705b261ecSmrg		ScratchPitch = PixmapBytePad(w, depth);
119805b261ecSmrg		sizeNeeded = ScratchPitch * h;
119905b261ecSmrg
120005b261ecSmrg		if(sizeNeeded > size) {
120105b261ecSmrg		    char *tmpdata = ScratchMem;
120205b261ecSmrg		    ScratchMem = xrealloc(ScratchMem, sizeNeeded);
120305b261ecSmrg		    if(ScratchMem)
120405b261ecSmrg			size = sizeNeeded;
120505b261ecSmrg		    else {
120605b261ecSmrg			ScratchMem = tmpdata;
120705b261ecSmrg			break;
120805b261ecSmrg		    }
120905b261ecSmrg		}
121005b261ecSmrg
121105b261ecSmrg		x = pbox->x1 - pDraw->x - panoramiXdataPtr[i].x;
121205b261ecSmrg		y = pbox->y1 - pDraw->y - panoramiXdataPtr[i].y;
121305b261ecSmrg
121405b261ecSmrg		(*pDraw->pScreen->GetImage)(pDraw, x, y, w, h,
121505b261ecSmrg					format, planemask, ScratchMem);
121605b261ecSmrg
121705b261ecSmrg		/* copy the memory over */
121805b261ecSmrg
121905b261ecSmrg		if(depth == 1) {
122005b261ecSmrg		   int k, shift, leftover, index, index2;
122105b261ecSmrg
122205b261ecSmrg		   x = pbox->x1 - SrcBox.x1;
122305b261ecSmrg		   y = pbox->y1 - SrcBox.y1;
122405b261ecSmrg		   shift = x & 7;
122505b261ecSmrg		   x >>= 3;
122605b261ecSmrg		   leftover = w & 7;
122705b261ecSmrg		   w >>= 3;
122805b261ecSmrg
122905b261ecSmrg		   /* clean up the edge */
123005b261ecSmrg		   if(leftover) {
123105b261ecSmrg			int mask = (1 << leftover) - 1;
123205b261ecSmrg			for(j = h, k = w; j--; k += ScratchPitch)
123305b261ecSmrg			    ScratchMem[k] &= mask;
123405b261ecSmrg		   }
123505b261ecSmrg
123605b261ecSmrg		   for(j = 0, index = (pitch * y) + x, index2 = 0; j < h;
123705b261ecSmrg		       j++, index += pitch, index2 += ScratchPitch)
123805b261ecSmrg		   {
123905b261ecSmrg			if(w) {
124005b261ecSmrg			    if(!shift)
124105b261ecSmrg				memcpy(data + index, ScratchMem + index2, w);
124205b261ecSmrg			    else
124305b261ecSmrg				CopyBits(data + index, shift,
124405b261ecSmrg						ScratchMem + index2, w);
124505b261ecSmrg			}
124605b261ecSmrg
124705b261ecSmrg			if(leftover) {
124805b261ecSmrg			    data[index + w] |=
124905b261ecSmrg				SHIFT_L(ScratchMem[index2 + w], shift);
125005b261ecSmrg			    if((shift + leftover) > 8)
125105b261ecSmrg				data[index + w + 1] |=
125205b261ecSmrg				  SHIFT_R(ScratchMem[index2 + w],(8 - shift));
125305b261ecSmrg			}
125405b261ecSmrg		    }
125505b261ecSmrg		} else {
125605b261ecSmrg		    j = BitsPerPixel(depth) >> 3;
125705b261ecSmrg		    x = (pbox->x1 - SrcBox.x1) * j;
125805b261ecSmrg		    y = pbox->y1 - SrcBox.y1;
125905b261ecSmrg		    w *= j;
126005b261ecSmrg
126105b261ecSmrg		    for(j = 0; j < h; j++) {
126205b261ecSmrg			memcpy(data + (pitch * (y + j)) + x,
126305b261ecSmrg				ScratchMem + (ScratchPitch * j), w);
126405b261ecSmrg		    }
126505b261ecSmrg		}
126605b261ecSmrg		pbox++;
126705b261ecSmrg	    }
126805b261ecSmrg
126905b261ecSmrg	    REGION_SUBTRACT(pScreen, &SrcRegion, &SrcRegion, &GrabRegion);
127005b261ecSmrg	    if(!REGION_NOTEMPTY(pScreen, &SrcRegion))
127105b261ecSmrg		break;
127205b261ecSmrg	}
127305b261ecSmrg
127405b261ecSmrg    }
127505b261ecSmrg
127605b261ecSmrg    if(ScratchMem)
127705b261ecSmrg	xfree(ScratchMem);
127805b261ecSmrg
127905b261ecSmrg    REGION_UNINIT(pScreen, &SrcRegion);
128005b261ecSmrg    REGION_UNINIT(pScreen, &GrabRegion);
128105b261ecSmrg}
1282