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