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