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