diff options
Diffstat (limited to 'xorg-server/Xext/panoramiX.c')
-rw-r--r-- | xorg-server/Xext/panoramiX.c | 2598 |
1 files changed, 1299 insertions, 1299 deletions
diff --git a/xorg-server/Xext/panoramiX.c b/xorg-server/Xext/panoramiX.c index 00afe94f1..27e54e2e4 100644 --- a/xorg-server/Xext/panoramiX.c +++ b/xorg-server/Xext/panoramiX.c @@ -1,1299 +1,1299 @@ -/***************************************************************** -Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts. -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software. - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING, -BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY, -WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR -IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -Except as contained in this notice, the name of Digital Equipment Corporation -shall not be used in advertising or otherwise to promote the sale, use or other -dealings in this Software without prior written authorization from Digital -Equipment Corporation. -******************************************************************/ - -#ifdef HAVE_DIX_CONFIG_H -#include <dix-config.h> -#endif - -#ifdef HAVE_DMX_CONFIG_H -#include <dmx-config.h> -#endif - -#include <stdio.h> -#include <X11/X.h> -#include <X11/Xproto.h> -#include <X11/Xarch.h> -#include "misc.h" -#include "cursor.h" -#include "cursorstr.h" -#include "extnsionst.h" -#include "dixstruct.h" -#include "gc.h" -#include "gcstruct.h" -#include "scrnintstr.h" -#include "window.h" -#include "windowstr.h" -#include "pixmapstr.h" -#include "panoramiX.h" -#include <X11/extensions/panoramiXproto.h> -#include "panoramiXsrv.h" -#include "globals.h" -#include "servermd.h" -#include "resource.h" -#include "picturestr.h" -#ifdef XFIXES -#include "xfixesint.h" -#endif -#ifdef COMPOSITE -#include "compint.h" -#endif -#include "modinit.h" -#include "protocol-versions.h" - -#ifdef GLXPROXY -extern VisualPtr glxMatchVisual(ScreenPtr pScreen, - VisualPtr pVisual, - ScreenPtr pMatchScreen); -#endif - -/* - * PanoramiX data declarations - */ - -int PanoramiXPixWidth = 0; -int PanoramiXPixHeight = 0; -int PanoramiXNumScreens = 0; - -static RegionRec PanoramiXScreenRegion = {{0, 0, 0, 0}, NULL}; - -static int PanoramiXNumDepths; -static DepthPtr PanoramiXDepths; -static int PanoramiXNumVisuals; -static VisualPtr PanoramiXVisuals; - -RESTYPE XRC_DRAWABLE; -RESTYPE XRT_WINDOW; -RESTYPE XRT_PIXMAP; -RESTYPE XRT_GC; -RESTYPE XRT_COLORMAP; - -static Bool VisualsEqual(VisualPtr, ScreenPtr, VisualPtr); -XineramaVisualsEqualProcPtr XineramaVisualsEqualPtr = &VisualsEqual; - -/* - * Function prototypes - */ - -static int panoramiXGeneration; -static int ProcPanoramiXDispatch(ClientPtr client); - -static void PanoramiXResetProc(ExtensionEntry*); - -/* - * External references for functions and data variables - */ - -#include "panoramiXh.h" - -int (* SavedProcVector[256]) (ClientPtr client) = { NULL, }; - -static DevPrivateKeyRec PanoramiXGCKeyRec; -#define PanoramiXGCKey (&PanoramiXGCKeyRec) -static DevPrivateKeyRec PanoramiXScreenKeyRec; -#define PanoramiXScreenKey (&PanoramiXScreenKeyRec) - -typedef struct { - DDXPointRec clipOrg; - DDXPointRec patOrg; - GCFuncs *wrapFuncs; -} PanoramiXGCRec, *PanoramiXGCPtr; - -typedef struct { - CreateGCProcPtr CreateGC; - CloseScreenProcPtr CloseScreen; -} PanoramiXScreenRec, *PanoramiXScreenPtr; - -static void XineramaValidateGC(GCPtr, unsigned long, DrawablePtr); -static void XineramaChangeGC(GCPtr, unsigned long); -static void XineramaCopyGC(GCPtr, unsigned long, GCPtr); -static void XineramaDestroyGC(GCPtr); -static void XineramaChangeClip(GCPtr, int, pointer, int); -static void XineramaDestroyClip(GCPtr); -static void XineramaCopyClip(GCPtr, GCPtr); - -static GCFuncs XineramaGCFuncs = { - XineramaValidateGC, XineramaChangeGC, XineramaCopyGC, XineramaDestroyGC, - XineramaChangeClip, XineramaDestroyClip, XineramaCopyClip -}; - -#define Xinerama_GC_FUNC_PROLOGUE(pGC)\ - PanoramiXGCPtr pGCPriv = (PanoramiXGCPtr) \ - dixLookupPrivate(&(pGC)->devPrivates, PanoramiXGCKey); \ - (pGC)->funcs = pGCPriv->wrapFuncs; - -#define Xinerama_GC_FUNC_EPILOGUE(pGC)\ - pGCPriv->wrapFuncs = (pGC)->funcs;\ - (pGC)->funcs = &XineramaGCFuncs; - - -static Bool -XineramaCloseScreen (int i, ScreenPtr pScreen) -{ - PanoramiXScreenPtr pScreenPriv = (PanoramiXScreenPtr) - dixLookupPrivate(&pScreen->devPrivates, PanoramiXScreenKey); - - pScreen->CloseScreen = pScreenPriv->CloseScreen; - pScreen->CreateGC = pScreenPriv->CreateGC; - - if (pScreen->myNum == 0) - RegionUninit(&PanoramiXScreenRegion); - - free((pointer) pScreenPriv); - - return (*pScreen->CloseScreen) (i, pScreen); -} - -static Bool -XineramaCreateGC(GCPtr pGC) -{ - ScreenPtr pScreen = pGC->pScreen; - PanoramiXScreenPtr pScreenPriv = (PanoramiXScreenPtr) - dixLookupPrivate(&pScreen->devPrivates, PanoramiXScreenKey); - Bool ret; - - pScreen->CreateGC = pScreenPriv->CreateGC; - if((ret = (*pScreen->CreateGC)(pGC))) { - PanoramiXGCPtr pGCPriv = (PanoramiXGCPtr) - dixLookupPrivate(&pGC->devPrivates, PanoramiXGCKey); - - pGCPriv->wrapFuncs = pGC->funcs; - pGC->funcs = &XineramaGCFuncs; - - pGCPriv->clipOrg.x = pGC->clipOrg.x; - pGCPriv->clipOrg.y = pGC->clipOrg.y; - pGCPriv->patOrg.x = pGC->patOrg.x; - pGCPriv->patOrg.y = pGC->patOrg.y; - } - pScreen->CreateGC = XineramaCreateGC; - - return ret; -} - -static void -XineramaValidateGC( - GCPtr pGC, - unsigned long changes, - DrawablePtr pDraw -){ - Xinerama_GC_FUNC_PROLOGUE (pGC); - - if((pDraw->type == DRAWABLE_WINDOW) && !(((WindowPtr)pDraw)->parent)) { - /* the root window */ - int x_off = pGC->pScreen->x; - int y_off = pGC->pScreen->y; - int new_val; - - new_val = pGCPriv->clipOrg.x - x_off; - if(pGC->clipOrg.x != new_val) { - pGC->clipOrg.x = new_val; - changes |= GCClipXOrigin; - } - new_val = pGCPriv->clipOrg.y - y_off; - if(pGC->clipOrg.y != new_val) { - pGC->clipOrg.y = new_val; - changes |= GCClipYOrigin; - } - new_val = pGCPriv->patOrg.x - x_off; - if(pGC->patOrg.x != new_val) { - pGC->patOrg.x = new_val; - changes |= GCTileStipXOrigin; - } - new_val = pGCPriv->patOrg.y - y_off; - if(pGC->patOrg.y != new_val) { - pGC->patOrg.y = new_val; - changes |= GCTileStipYOrigin; - } - } else { - if(pGC->clipOrg.x != pGCPriv->clipOrg.x) { - pGC->clipOrg.x = pGCPriv->clipOrg.x; - changes |= GCClipXOrigin; - } - if(pGC->clipOrg.y != pGCPriv->clipOrg.y) { - pGC->clipOrg.y = pGCPriv->clipOrg.y; - changes |= GCClipYOrigin; - } - if(pGC->patOrg.x != pGCPriv->patOrg.x) { - pGC->patOrg.x = pGCPriv->patOrg.x; - changes |= GCTileStipXOrigin; - } - if(pGC->patOrg.y != pGCPriv->patOrg.y) { - pGC->patOrg.y = pGCPriv->patOrg.y; - changes |= GCTileStipYOrigin; - } - } - - (*pGC->funcs->ValidateGC)(pGC, changes, pDraw); - Xinerama_GC_FUNC_EPILOGUE (pGC); -} - -static void -XineramaDestroyGC(GCPtr pGC) -{ - Xinerama_GC_FUNC_PROLOGUE (pGC); - (*pGC->funcs->DestroyGC)(pGC); - Xinerama_GC_FUNC_EPILOGUE (pGC); -} - -static void -XineramaChangeGC ( - GCPtr pGC, - unsigned long mask -){ - Xinerama_GC_FUNC_PROLOGUE (pGC); - - if(mask & GCTileStipXOrigin) - pGCPriv->patOrg.x = pGC->patOrg.x; - if(mask & GCTileStipYOrigin) - pGCPriv->patOrg.y = pGC->patOrg.y; - if(mask & GCClipXOrigin) - pGCPriv->clipOrg.x = pGC->clipOrg.x; - if(mask & GCClipYOrigin) - pGCPriv->clipOrg.y = pGC->clipOrg.y; - - (*pGC->funcs->ChangeGC) (pGC, mask); - Xinerama_GC_FUNC_EPILOGUE (pGC); -} - -static void -XineramaCopyGC ( - GCPtr pGCSrc, - unsigned long mask, - GCPtr pGCDst -){ - PanoramiXGCPtr pSrcPriv = (PanoramiXGCPtr) - dixLookupPrivate(&pGCSrc->devPrivates, PanoramiXGCKey); - Xinerama_GC_FUNC_PROLOGUE (pGCDst); - - if(mask & GCTileStipXOrigin) - pGCPriv->patOrg.x = pSrcPriv->patOrg.x; - if(mask & GCTileStipYOrigin) - pGCPriv->patOrg.y = pSrcPriv->patOrg.y; - if(mask & GCClipXOrigin) - pGCPriv->clipOrg.x = pSrcPriv->clipOrg.x; - if(mask & GCClipYOrigin) - pGCPriv->clipOrg.y = pSrcPriv->clipOrg.y; - - (*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst); - Xinerama_GC_FUNC_EPILOGUE (pGCDst); -} - -static void -XineramaChangeClip ( - GCPtr pGC, - int type, - pointer pvalue, - int nrects -){ - Xinerama_GC_FUNC_PROLOGUE (pGC); - (*pGC->funcs->ChangeClip) (pGC, type, pvalue, nrects); - Xinerama_GC_FUNC_EPILOGUE (pGC); -} - -static void -XineramaCopyClip(GCPtr pgcDst, GCPtr pgcSrc) -{ - Xinerama_GC_FUNC_PROLOGUE (pgcDst); - (* pgcDst->funcs->CopyClip)(pgcDst, pgcSrc); - Xinerama_GC_FUNC_EPILOGUE (pgcDst); -} - -static void -XineramaDestroyClip(GCPtr pGC) -{ - Xinerama_GC_FUNC_PROLOGUE (pGC); - (* pGC->funcs->DestroyClip)(pGC); - Xinerama_GC_FUNC_EPILOGUE (pGC); -} - -int -XineramaDeleteResource(pointer data, XID id) -{ - free(data); - return 1; -} - -typedef struct { - int screen; - int id; -} PanoramiXSearchData; - -static Bool -XineramaFindIDByScrnum(pointer resource, XID id, pointer privdata) -{ - PanoramiXRes *res = (PanoramiXRes*)resource; - PanoramiXSearchData *data = (PanoramiXSearchData*)privdata; - - return res->info[data->screen].id == data->id; -} - -PanoramiXRes * -PanoramiXFindIDByScrnum(RESTYPE type, XID id, int screen) -{ - PanoramiXSearchData data; - pointer val; - - if(!screen) { - dixLookupResourceByType(&val, id, type, serverClient, DixReadAccess); - return val; - } - - data.screen = screen; - data.id = id; - - return LookupClientResourceComplex(clients[CLIENT_ID(id)], type, - XineramaFindIDByScrnum, &data); -} - -typedef struct _connect_callback_list { - void (*func)(void); - struct _connect_callback_list *next; -} XineramaConnectionCallbackList; - -static XineramaConnectionCallbackList *ConnectionCallbackList = NULL; - -Bool -XineramaRegisterConnectionBlockCallback(void (*func)(void)) -{ - XineramaConnectionCallbackList *newlist; - - if(!(newlist = malloc(sizeof(XineramaConnectionCallbackList)))) - return FALSE; - - newlist->next = ConnectionCallbackList; - newlist->func = func; - ConnectionCallbackList = newlist; - - return TRUE; -} - -static void XineramaInitData(ScreenPtr pScreen) -{ - int i, w, h; - - RegionNull(&PanoramiXScreenRegion); - FOR_NSCREENS(i) { - BoxRec TheBox; - RegionRec ScreenRegion; - - pScreen = screenInfo.screens[i]; - - TheBox.x1 = pScreen->x; - TheBox.x2 = TheBox.x1 + pScreen->width; - TheBox.y1 = pScreen->y; - TheBox.y2 = TheBox.y1 + pScreen->height; - - RegionInit(&ScreenRegion, &TheBox, 1); - RegionUnion(&PanoramiXScreenRegion, &PanoramiXScreenRegion, - &ScreenRegion); - RegionUninit(&ScreenRegion); - } - - PanoramiXPixWidth = screenInfo.screens[0]->x + screenInfo.screens[0]->width; - PanoramiXPixHeight = screenInfo.screens[0]->y + screenInfo.screens[0]->height; - - FOR_NSCREENS_FORWARD_SKIP(i) { - pScreen = screenInfo.screens[i]; - w = pScreen->x + pScreen->width; - h = pScreen->y + pScreen->height; - - if (PanoramiXPixWidth < w) - PanoramiXPixWidth = w; - if (PanoramiXPixHeight < h) - PanoramiXPixHeight = h; - } -} - -void XineramaReinitData(ScreenPtr pScreen) -{ - RegionUninit(&PanoramiXScreenRegion); - XineramaInitData(pScreen); -} - -/* - * PanoramiXExtensionInit(): - * Called from InitExtensions in main(). - * Register PanoramiXeen Extension - * Initialize global variables. - */ - -void PanoramiXExtensionInit(int argc, char *argv[]) -{ - int i; - Bool success = FALSE; - ExtensionEntry *extEntry; - ScreenPtr pScreen = screenInfo.screens[0]; - PanoramiXScreenPtr pScreenPriv; - - if (noPanoramiXExtension) - return; - - if (!dixRegisterPrivateKey(&PanoramiXScreenKeyRec, PRIVATE_SCREEN, 0)) { - noPanoramiXExtension = TRUE; - return; - } - - if (!dixRegisterPrivateKey(&PanoramiXGCKeyRec, PRIVATE_GC, sizeof(PanoramiXGCRec))) { - noPanoramiXExtension = TRUE; - return; - } - - PanoramiXNumScreens = screenInfo.numScreens; - if (PanoramiXNumScreens == 1) { /* Only 1 screen */ - noPanoramiXExtension = TRUE; - return; - } - - while (panoramiXGeneration != serverGeneration) { - extEntry = AddExtension(PANORAMIX_PROTOCOL_NAME, 0,0, - ProcPanoramiXDispatch, - SProcPanoramiXDispatch, PanoramiXResetProc, - StandardMinorOpcode); - if (!extEntry) - break; - - /* - * First make sure all the basic allocations succeed. If not, - * run in non-PanoramiXeen mode. - */ - - FOR_NSCREENS(i) { - pScreen = screenInfo.screens[i]; - pScreenPriv = malloc(sizeof(PanoramiXScreenRec)); - dixSetPrivate(&pScreen->devPrivates, PanoramiXScreenKey, - pScreenPriv); - if(!pScreenPriv) { - noPanoramiXExtension = TRUE; - return; - } - - pScreenPriv->CreateGC = pScreen->CreateGC; - pScreenPriv->CloseScreen = pScreen->CloseScreen; - - pScreen->CreateGC = XineramaCreateGC; - pScreen->CloseScreen = XineramaCloseScreen; - } - - XRC_DRAWABLE = CreateNewResourceClass(); - XRT_WINDOW = CreateNewResourceType(XineramaDeleteResource, - "XineramaWindow"); - if (XRT_WINDOW) - XRT_WINDOW |= XRC_DRAWABLE; - XRT_PIXMAP = CreateNewResourceType(XineramaDeleteResource, - "XineramaPixmap"); - if (XRT_PIXMAP) - XRT_PIXMAP |= XRC_DRAWABLE; - XRT_GC = CreateNewResourceType(XineramaDeleteResource, - "XineramaGC"); - XRT_COLORMAP = CreateNewResourceType(XineramaDeleteResource, - "XineramaColormap"); - - if (XRT_WINDOW && XRT_PIXMAP && XRT_GC && XRT_COLORMAP) { - panoramiXGeneration = serverGeneration; - success = TRUE; - } - SetResourceTypeErrorValue(XRT_WINDOW, BadWindow); - SetResourceTypeErrorValue(XRT_PIXMAP, BadPixmap); - SetResourceTypeErrorValue(XRT_GC, BadGC); - SetResourceTypeErrorValue(XRT_COLORMAP, BadColor); - } - - if (!success) { - noPanoramiXExtension = TRUE; - ErrorF(PANORAMIX_PROTOCOL_NAME " extension failed to initialize\n"); - return; - } - - XineramaInitData(pScreen); - - /* - * Put our processes into the ProcVector - */ - - for (i = 256; i--; ) - SavedProcVector[i] = ProcVector[i]; - - ProcVector[X_CreateWindow] = PanoramiXCreateWindow; - ProcVector[X_ChangeWindowAttributes] = PanoramiXChangeWindowAttributes; - ProcVector[X_DestroyWindow] = PanoramiXDestroyWindow; - ProcVector[X_DestroySubwindows] = PanoramiXDestroySubwindows; - ProcVector[X_ChangeSaveSet] = PanoramiXChangeSaveSet; - ProcVector[X_ReparentWindow] = PanoramiXReparentWindow; - ProcVector[X_MapWindow] = PanoramiXMapWindow; - ProcVector[X_MapSubwindows] = PanoramiXMapSubwindows; - ProcVector[X_UnmapWindow] = PanoramiXUnmapWindow; - ProcVector[X_UnmapSubwindows] = PanoramiXUnmapSubwindows; - ProcVector[X_ConfigureWindow] = PanoramiXConfigureWindow; - ProcVector[X_CirculateWindow] = PanoramiXCirculateWindow; - ProcVector[X_GetGeometry] = PanoramiXGetGeometry; - ProcVector[X_TranslateCoords] = PanoramiXTranslateCoords; - ProcVector[X_CreatePixmap] = PanoramiXCreatePixmap; - ProcVector[X_FreePixmap] = PanoramiXFreePixmap; - ProcVector[X_CreateGC] = PanoramiXCreateGC; - ProcVector[X_ChangeGC] = PanoramiXChangeGC; - ProcVector[X_CopyGC] = PanoramiXCopyGC; - ProcVector[X_SetDashes] = PanoramiXSetDashes; - ProcVector[X_SetClipRectangles] = PanoramiXSetClipRectangles; - ProcVector[X_FreeGC] = PanoramiXFreeGC; - ProcVector[X_ClearArea] = PanoramiXClearToBackground; - ProcVector[X_CopyArea] = PanoramiXCopyArea; - ProcVector[X_CopyPlane] = PanoramiXCopyPlane; - ProcVector[X_PolyPoint] = PanoramiXPolyPoint; - ProcVector[X_PolyLine] = PanoramiXPolyLine; - ProcVector[X_PolySegment] = PanoramiXPolySegment; - ProcVector[X_PolyRectangle] = PanoramiXPolyRectangle; - ProcVector[X_PolyArc] = PanoramiXPolyArc; - ProcVector[X_FillPoly] = PanoramiXFillPoly; - ProcVector[X_PolyFillRectangle] = PanoramiXPolyFillRectangle; - ProcVector[X_PolyFillArc] = PanoramiXPolyFillArc; - ProcVector[X_PutImage] = PanoramiXPutImage; - ProcVector[X_GetImage] = PanoramiXGetImage; - ProcVector[X_PolyText8] = PanoramiXPolyText8; - ProcVector[X_PolyText16] = PanoramiXPolyText16; - ProcVector[X_ImageText8] = PanoramiXImageText8; - ProcVector[X_ImageText16] = PanoramiXImageText16; - ProcVector[X_CreateColormap] = PanoramiXCreateColormap; - ProcVector[X_FreeColormap] = PanoramiXFreeColormap; - ProcVector[X_CopyColormapAndFree] = PanoramiXCopyColormapAndFree; - ProcVector[X_InstallColormap] = PanoramiXInstallColormap; - ProcVector[X_UninstallColormap] = PanoramiXUninstallColormap; - ProcVector[X_AllocColor] = PanoramiXAllocColor; - ProcVector[X_AllocNamedColor] = PanoramiXAllocNamedColor; - ProcVector[X_AllocColorCells] = PanoramiXAllocColorCells; - ProcVector[X_AllocColorPlanes] = PanoramiXAllocColorPlanes; - ProcVector[X_FreeColors] = PanoramiXFreeColors; - ProcVector[X_StoreColors] = PanoramiXStoreColors; - ProcVector[X_StoreNamedColor] = PanoramiXStoreNamedColor; - - PanoramiXRenderInit (); -#ifdef XFIXES - PanoramiXFixesInit (); -#endif -#ifdef COMPOSITE - PanoramiXCompositeInit (); -#endif - -} - -extern Bool CreateConnectionBlock(void); - -Bool PanoramiXCreateConnectionBlock(void) -{ - int i, j, length; - Bool disableBackingStore = FALSE; - int old_width, old_height; - float width_mult, height_mult; - xWindowRoot *root; - xVisualType *visual; - xDepth *depth; - VisualPtr pVisual; - ScreenPtr pScreen; - - /* - * Do normal CreateConnectionBlock but faking it for only one screen - */ - - if(!PanoramiXNumDepths) { - ErrorF("Xinerama error: No common visuals\n"); - return FALSE; - } - - for(i = 1; i < screenInfo.numScreens; i++) { - pScreen = screenInfo.screens[i]; - if(pScreen->rootDepth != screenInfo.screens[0]->rootDepth) { - ErrorF("Xinerama error: Root window depths differ\n"); - return FALSE; - } - if(pScreen->backingStoreSupport != screenInfo.screens[0]->backingStoreSupport) - disableBackingStore = TRUE; - } - - if (disableBackingStore) { - for (i = 0; i < screenInfo.numScreens; i++) { - pScreen = screenInfo.screens[i]; - pScreen->backingStoreSupport = NotUseful; - } - } - - i = screenInfo.numScreens; - screenInfo.numScreens = 1; - if (!CreateConnectionBlock()) { - screenInfo.numScreens = i; - return FALSE; - } - - screenInfo.numScreens = i; - - root = (xWindowRoot *) (ConnectionInfo + connBlockScreenStart); - length = connBlockScreenStart + sizeof(xWindowRoot); - - /* overwrite the connection block */ - root->nDepths = PanoramiXNumDepths; - - for (i = 0; i < PanoramiXNumDepths; i++) { - depth = (xDepth *) (ConnectionInfo + length); - depth->depth = PanoramiXDepths[i].depth; - depth->nVisuals = PanoramiXDepths[i].numVids; - length += sizeof(xDepth); - visual = (xVisualType *)(ConnectionInfo + length); - - for (j = 0; j < depth->nVisuals; j++, visual++) { - visual->visualID = PanoramiXDepths[i].vids[j]; - - for (pVisual = PanoramiXVisuals; - pVisual->vid != visual->visualID; - pVisual++) - ; - - visual->class = pVisual->class; - visual->bitsPerRGB = pVisual->bitsPerRGBValue; - visual->colormapEntries = pVisual->ColormapEntries; - visual->redMask = pVisual->redMask; - visual->greenMask = pVisual->greenMask; - visual->blueMask = pVisual->blueMask; - } - - length += (depth->nVisuals * sizeof(xVisualType)); - } - - connSetupPrefix.length = bytes_to_int32(length); - - for (i = 0; i < PanoramiXNumDepths; i++) - free(PanoramiXDepths[i].vids); - free(PanoramiXDepths); - PanoramiXDepths = NULL; - - /* - * OK, change some dimensions so it looks as if it were one big screen - */ - - old_width = root->pixWidth; - old_height = root->pixHeight; - - root->pixWidth = PanoramiXPixWidth; - root->pixHeight = PanoramiXPixHeight; - width_mult = (1.0 * root->pixWidth) / old_width; - height_mult = (1.0 * root->pixHeight) / old_height; - root->mmWidth *= width_mult; - root->mmHeight *= height_mult; - - while(ConnectionCallbackList) { - pointer tmp; - - tmp = (pointer)ConnectionCallbackList; - (*ConnectionCallbackList->func)(); - ConnectionCallbackList = ConnectionCallbackList->next; - free(tmp); - } - - return TRUE; -} - -/* - * This isn't just memcmp(), bitsPerRGBValue is skipped. markv made that - * change way back before xf86 4.0, but the comment for _why_ is a bit - * opaque, so I'm not going to question it for now. - * - * This is probably better done as a screen hook so DBE/EVI/GLX can add - * their own tests, and adding privates to VisualRec so they don't have to - * do their own back-mapping. - */ -static Bool -VisualsEqual(VisualPtr a, ScreenPtr pScreenB, VisualPtr b) -{ - return ((a->class == b->class) && - (a->ColormapEntries == b->ColormapEntries) && - (a->nplanes == b->nplanes) && - (a->redMask == b->redMask) && - (a->greenMask == b->greenMask) && - (a->blueMask == b->blueMask) && - (a->offsetRed == b->offsetRed) && - (a->offsetGreen == b->offsetGreen) && - (a->offsetBlue == b->offsetBlue)); -} - -static void -PanoramiXMaybeAddDepth(DepthPtr pDepth) -{ - ScreenPtr pScreen; - int j, k; - Bool found = FALSE; - - FOR_NSCREENS_FORWARD_SKIP(j) { - pScreen = screenInfo.screens[j]; - for (k = 0; k < pScreen->numDepths; k++) { - if (pScreen->allowedDepths[k].depth == pDepth->depth) { - found = TRUE; - break; - } - } - } - - if (!found) - return; - - j = PanoramiXNumDepths; - PanoramiXNumDepths++; - PanoramiXDepths = realloc(PanoramiXDepths, - PanoramiXNumDepths * sizeof(DepthRec)); - PanoramiXDepths[j].depth = pDepth->depth; - PanoramiXDepths[j].numVids = 0; - /* XXX suboptimal, should grow these dynamically */ - if(pDepth->numVids) - PanoramiXDepths[j].vids = malloc(sizeof(VisualID) * pDepth->numVids); - else - PanoramiXDepths[j].vids = NULL; -} - -static void -PanoramiXMaybeAddVisual(VisualPtr pVisual) -{ - ScreenPtr pScreen; - int j, k; - Bool found = FALSE; - - FOR_NSCREENS_FORWARD_SKIP(j) { - pScreen = screenInfo.screens[j]; - found = FALSE; - - for (k = 0; k < pScreen->numVisuals; k++) { - VisualPtr candidate = &pScreen->visuals[k]; - - if ((*XineramaVisualsEqualPtr)(pVisual, pScreen, candidate) -#ifdef GLXPROXY - && glxMatchVisual(screenInfo.screens[0], pVisual, pScreen) -#endif - ) { - found = TRUE; - break; - } - } - - if (!found) - return; - } - - /* found a matching visual on all screens, add it to the subset list */ - j = PanoramiXNumVisuals; - PanoramiXNumVisuals++; - PanoramiXVisuals = realloc(PanoramiXVisuals, - PanoramiXNumVisuals * sizeof(VisualRec)); - - memcpy(&PanoramiXVisuals[j], pVisual, sizeof(VisualRec)); - - for (k = 0; k < PanoramiXNumDepths; k++) { - if (PanoramiXDepths[k].depth == pVisual->nplanes) { - PanoramiXDepths[k].vids[PanoramiXDepths[k].numVids] = pVisual->vid; - PanoramiXDepths[k].numVids++; - break; - } - } -} - -extern void -PanoramiXConsolidate(void) -{ - int i; - PanoramiXRes *root, *defmap, *saver; - ScreenPtr pScreen = screenInfo.screens[0]; - DepthPtr pDepth = pScreen->allowedDepths; - VisualPtr pVisual = pScreen->visuals; - - PanoramiXNumDepths = 0; - PanoramiXNumVisuals = 0; - - for (i = 0; i < pScreen->numDepths; i++) - PanoramiXMaybeAddDepth(pDepth++); - - for (i = 0; i < pScreen->numVisuals; i++) - PanoramiXMaybeAddVisual(pVisual++); - - root = malloc(sizeof(PanoramiXRes)); - root->type = XRT_WINDOW; - defmap = malloc(sizeof(PanoramiXRes)); - defmap->type = XRT_COLORMAP; - saver = malloc(sizeof(PanoramiXRes)); - saver->type = XRT_WINDOW; - - FOR_NSCREENS(i) { - ScreenPtr pScreen = screenInfo.screens[i]; - root->info[i].id = pScreen->root->drawable.id; - root->u.win.class = InputOutput; - root->u.win.root = TRUE; - saver->info[i].id = pScreen->screensaver.wid; - saver->u.win.class = InputOutput; - saver->u.win.root = TRUE; - defmap->info[i].id = pScreen->defColormap; - } - - AddResource(root->info[0].id, XRT_WINDOW, root); - AddResource(saver->info[0].id, XRT_WINDOW, saver); - AddResource(defmap->info[0].id, XRT_COLORMAP, defmap); -} - -VisualID -PanoramiXTranslateVisualID(int screen, VisualID orig) -{ - ScreenPtr pOtherScreen = screenInfo.screens[screen]; - VisualPtr pVisual = NULL; - int i; - - for (i = 0; i < PanoramiXNumVisuals; i++) { - if (orig == PanoramiXVisuals[i].vid) { - pVisual = &PanoramiXVisuals[i]; - break; - } - } - - if (!pVisual) - return 0; - - /* if screen is 0, orig is already the correct visual ID */ - if (screen == 0) - return orig; - - /* found the original, now translate it relative to the backend screen */ - for (i = 0; i < pOtherScreen->numVisuals; i++) { - VisualPtr pOtherVisual = &pOtherScreen->visuals[i]; - - if ((*XineramaVisualsEqualPtr)(pVisual, pOtherScreen, pOtherVisual)) - return pOtherVisual->vid; - } - - return 0; -} - - -/* - * PanoramiXResetProc() - * Exit, deallocating as needed. - */ - -static void PanoramiXResetProc(ExtensionEntry* extEntry) -{ - int i; - - PanoramiXRenderReset (); -#ifdef XFIXES - PanoramiXFixesReset (); -#endif - screenInfo.numScreens = PanoramiXNumScreens; - for (i = 256; i--; ) - ProcVector[i] = SavedProcVector[i]; -} - - -int -ProcPanoramiXQueryVersion (ClientPtr client) -{ - /* REQUEST(xPanoramiXQueryVersionReq); */ - xPanoramiXQueryVersionReply rep; - register int n; - - REQUEST_SIZE_MATCH (xPanoramiXQueryVersionReq); - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - rep.majorVersion = SERVER_PANORAMIX_MAJOR_VERSION; - rep.minorVersion = SERVER_PANORAMIX_MINOR_VERSION; - if (client->swapped) { - swaps(&rep.sequenceNumber, n); - swapl(&rep.length, n); - swaps(&rep.majorVersion, n); - swaps(&rep.minorVersion, n); - } - WriteToClient(client, sizeof (xPanoramiXQueryVersionReply), (char *)&rep); - return Success; -} - -int -ProcPanoramiXGetState(ClientPtr client) -{ - REQUEST(xPanoramiXGetStateReq); - WindowPtr pWin; - xPanoramiXGetStateReply rep; - int n, rc; - - REQUEST_SIZE_MATCH(xPanoramiXGetStateReq); - rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); - if (rc != Success) - return rc; - - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - rep.state = !noPanoramiXExtension; - rep.window = stuff->window; - if (client->swapped) { - swaps (&rep.sequenceNumber, n); - swapl (&rep.length, n); - swapl (&rep.window, n); - } - WriteToClient (client, sizeof (xPanoramiXGetStateReply), (char *) &rep); - return Success; - -} - -int -ProcPanoramiXGetScreenCount(ClientPtr client) -{ - REQUEST(xPanoramiXGetScreenCountReq); - WindowPtr pWin; - xPanoramiXGetScreenCountReply rep; - int n, rc; - - REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq); - rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); - if (rc != Success) - return rc; - - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - rep.ScreenCount = PanoramiXNumScreens; - rep.window = stuff->window; - if (client->swapped) { - swaps (&rep.sequenceNumber, n); - swapl (&rep.length, n); - swapl (&rep.window, n); - } - WriteToClient (client, sizeof (xPanoramiXGetScreenCountReply), (char *) &rep); - return Success; -} - -int -ProcPanoramiXGetScreenSize(ClientPtr client) -{ - REQUEST(xPanoramiXGetScreenSizeReq); - WindowPtr pWin; - xPanoramiXGetScreenSizeReply rep; - int n, rc; - - if (stuff->screen >= PanoramiXNumScreens) - return BadMatch; - - REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq); - rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); - if (rc != Success) - return rc; - - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - /* screen dimensions */ - rep.width = screenInfo.screens[stuff->screen]->width; - rep.height = screenInfo.screens[stuff->screen]->height; - rep.window = stuff->window; - rep.screen = stuff->screen; - if (client->swapped) { - swaps (&rep.sequenceNumber, n); - swapl (&rep.length, n); - swapl (&rep.width, n); - swapl (&rep.height, n); - swapl (&rep.window, n); - swapl (&rep.screen, n); - } - WriteToClient (client, sizeof (xPanoramiXGetScreenSizeReply), (char *) &rep); - return Success; -} - - -int -ProcXineramaIsActive(ClientPtr client) -{ - /* REQUEST(xXineramaIsActiveReq); */ - xXineramaIsActiveReply rep; - - REQUEST_SIZE_MATCH(xXineramaIsActiveReq); - - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; -#if 1 - { - /* The following hack fools clients into thinking that Xinerama - * is disabled even though it is not. */ - rep.state = !noPanoramiXExtension && !PanoramiXExtensionDisabledHack; - } -#else - rep.state = !noPanoramiXExtension; -#endif - if (client->swapped) { - int n; - swaps (&rep.sequenceNumber, n); - swapl (&rep.length, n); - swapl (&rep.state, n); - } - WriteToClient (client, sizeof (xXineramaIsActiveReply), (char *) &rep); - return Success; -} - - -int -ProcXineramaQueryScreens(ClientPtr client) -{ - /* REQUEST(xXineramaQueryScreensReq); */ - xXineramaQueryScreensReply rep; - - REQUEST_SIZE_MATCH(xXineramaQueryScreensReq); - - rep.type = X_Reply; - rep.sequenceNumber = client->sequence; - rep.number = (noPanoramiXExtension) ? 0 : PanoramiXNumScreens; - rep.length = bytes_to_int32(rep.number * sz_XineramaScreenInfo); - if (client->swapped) { - int n; - swaps (&rep.sequenceNumber, n); - swapl (&rep.length, n); - swapl (&rep.number, n); - } - WriteToClient (client, sizeof (xXineramaQueryScreensReply), (char *) &rep); - - if(!noPanoramiXExtension) { - xXineramaScreenInfo scratch; - int i; - - FOR_NSCREENS(i) { - scratch.x_org = screenInfo.screens[i]->x; - scratch.y_org = screenInfo.screens[i]->y; - scratch.width = screenInfo.screens[i]->width; - scratch.height = screenInfo.screens[i]->height; - - if(client->swapped) { - int n; - swaps (&scratch.x_org, n); - swaps (&scratch.y_org, n); - swaps (&scratch.width, n); - swaps (&scratch.height, n); - } - WriteToClient (client, sz_XineramaScreenInfo, (char *) &scratch); - } - } - - return Success; -} - - -static int -ProcPanoramiXDispatch (ClientPtr client) -{ REQUEST(xReq); - switch (stuff->data) - { - case X_PanoramiXQueryVersion: - return ProcPanoramiXQueryVersion(client); - case X_PanoramiXGetState: - return ProcPanoramiXGetState(client); - case X_PanoramiXGetScreenCount: - return ProcPanoramiXGetScreenCount(client); - case X_PanoramiXGetScreenSize: - return ProcPanoramiXGetScreenSize(client); - case X_XineramaIsActive: - return ProcXineramaIsActive(client); - case X_XineramaQueryScreens: - return ProcXineramaQueryScreens(client); - } - return BadRequest; -} - - -#if X_BYTE_ORDER == X_LITTLE_ENDIAN -#define SHIFT_L(v,s) (v) << (s) -#define SHIFT_R(v,s) (v) >> (s) -#else -#define SHIFT_L(v,s) (v) >> (s) -#define SHIFT_R(v,s) (v) << (s) -#endif - -static void -CopyBits(char *dst, int shiftL, char *src, int bytes) -{ - /* Just get it to work. Worry about speed later */ - int shiftR = 8 - shiftL; - - while(bytes--) { - *dst |= SHIFT_L(*src, shiftL); - *(dst + 1) |= SHIFT_R(*src, shiftR); - dst++; src++; - } -} - - -/* Caution. This doesn't support 2 and 4 bpp formats. We expect - 1 bpp and planar data to be already cleared when presented - to this function */ - -void -XineramaGetImageData( - DrawablePtr *pDrawables, - int left, - int top, - int width, - int height, - unsigned int format, - unsigned long planemask, - char *data, - int pitch, - Bool isRoot -){ - RegionRec SrcRegion, ScreenRegion, GrabRegion; - BoxRec SrcBox, *pbox; - int x, y, w, h, i, j, nbox, size, sizeNeeded, ScratchPitch, inOut, depth; - DrawablePtr pDraw = pDrawables[0]; - char *ScratchMem = NULL; - - size = 0; - - /* find box in logical screen space */ - SrcBox.x1 = left; - SrcBox.y1 = top; - if(!isRoot) { - SrcBox.x1 += pDraw->x + screenInfo.screens[0]->x; - SrcBox.y1 += pDraw->y + screenInfo.screens[0]->y; - } - SrcBox.x2 = SrcBox.x1 + width; - SrcBox.y2 = SrcBox.y1 + height; - - RegionInit(&SrcRegion, &SrcBox, 1); - RegionNull(&GrabRegion); - - depth = (format == XYPixmap) ? 1 : pDraw->depth; - - FOR_NSCREENS(i) { - BoxRec TheBox; - ScreenPtr pScreen; - pDraw = pDrawables[i]; - pScreen = pDraw->pScreen; - - TheBox.x1 = pScreen->x; - TheBox.x2 = TheBox.x1 + pScreen->width; - TheBox.y1 = pScreen->y; - TheBox.y2 = TheBox.y1 + pScreen->height; - - RegionInit(&ScreenRegion, &TheBox, 1); - inOut = RegionContainsRect(&ScreenRegion, &SrcBox); - if(inOut == rgnPART) - RegionIntersect(&GrabRegion, &SrcRegion, &ScreenRegion); - RegionUninit(&ScreenRegion); - - if(inOut == rgnIN) { - (*pScreen->GetImage)(pDraw, - SrcBox.x1 - pDraw->x - screenInfo.screens[i]->x, - SrcBox.y1 - pDraw->y - screenInfo.screens[i]->y, - width, height, format, planemask, data); - break; - } else if (inOut == rgnOUT) - continue; - - nbox = RegionNumRects(&GrabRegion); - - if(nbox) { - pbox = RegionRects(&GrabRegion); - - while(nbox--) { - w = pbox->x2 - pbox->x1; - h = pbox->y2 - pbox->y1; - ScratchPitch = PixmapBytePad(w, depth); - sizeNeeded = ScratchPitch * h; - - if(sizeNeeded > size) { - char *tmpdata = ScratchMem; - ScratchMem = realloc(ScratchMem, sizeNeeded); - if(ScratchMem) - size = sizeNeeded; - else { - ScratchMem = tmpdata; - break; - } - } - - x = pbox->x1 - pDraw->x - screenInfo.screens[i]->x; - y = pbox->y1 - pDraw->y - screenInfo.screens[i]->y; - - (*pScreen->GetImage)(pDraw, x, y, w, h, - format, planemask, ScratchMem); - - /* copy the memory over */ - - if(depth == 1) { - int k, shift, leftover, index, index2; - - x = pbox->x1 - SrcBox.x1; - y = pbox->y1 - SrcBox.y1; - shift = x & 7; - x >>= 3; - leftover = w & 7; - w >>= 3; - - /* clean up the edge */ - if(leftover) { - int mask = (1 << leftover) - 1; - for(j = h, k = w; j--; k += ScratchPitch) - ScratchMem[k] &= mask; - } - - for(j = 0, index = (pitch * y) + x, index2 = 0; j < h; - j++, index += pitch, index2 += ScratchPitch) - { - if(w) { - if(!shift) - memcpy(data + index, ScratchMem + index2, w); - else - CopyBits(data + index, shift, - ScratchMem + index2, w); - } - - if(leftover) { - data[index + w] |= - SHIFT_L(ScratchMem[index2 + w], shift); - if((shift + leftover) > 8) - data[index + w + 1] |= - SHIFT_R(ScratchMem[index2 + w],(8 - shift)); - } - } - } else { - j = BitsPerPixel(depth) >> 3; - x = (pbox->x1 - SrcBox.x1) * j; - y = pbox->y1 - SrcBox.y1; - w *= j; - - for(j = 0; j < h; j++) { - memcpy(data + (pitch * (y + j)) + x, - ScratchMem + (ScratchPitch * j), w); - } - } - pbox++; - } - - RegionSubtract(&SrcRegion, &SrcRegion, &GrabRegion); - if(!RegionNotEmpty(&SrcRegion)) - break; - } - - } - - free(ScratchMem); - - RegionUninit(&SrcRegion); - RegionUninit(&GrabRegion); -} +/*****************************************************************
+Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts.
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING,
+BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of Digital Equipment Corporation
+shall not be used in advertising or otherwise to promote the sale, use or other
+dealings in this Software without prior written authorization from Digital
+Equipment Corporation.
+******************************************************************/
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#ifdef HAVE_DMX_CONFIG_H
+#include <dmx-config.h>
+#endif
+
+#include <stdio.h>
+#include <X11/X.h>
+#include <X11/Xproto.h>
+#include <X11/Xarch.h>
+#include "misc.h"
+#include "cursor.h"
+#include "cursorstr.h"
+#include "extnsionst.h"
+#include "dixstruct.h"
+#include "gc.h"
+#include "gcstruct.h"
+#include "scrnintstr.h"
+#include "window.h"
+#include "windowstr.h"
+#include "pixmapstr.h"
+#include "panoramiX.h"
+#include <X11/extensions/panoramiXproto.h>
+#include "panoramiXsrv.h"
+#include "globals.h"
+#include "servermd.h"
+#include "resource.h"
+#include "picturestr.h"
+#ifdef XFIXES
+#include "xfixesint.h"
+#endif
+#ifdef COMPOSITE
+#include "compint.h"
+#endif
+#include "modinit.h"
+#include "protocol-versions.h"
+
+#ifdef GLXPROXY
+extern VisualPtr glxMatchVisual(ScreenPtr pScreen,
+ VisualPtr pVisual,
+ ScreenPtr pMatchScreen);
+#endif
+
+/*
+ * PanoramiX data declarations
+ */
+
+int PanoramiXPixWidth = 0;
+int PanoramiXPixHeight = 0;
+int PanoramiXNumScreens = 0;
+
+static RegionRec PanoramiXScreenRegion = {{0, 0, 0, 0}, NULL};
+
+static int PanoramiXNumDepths;
+static DepthPtr PanoramiXDepths;
+static int PanoramiXNumVisuals;
+static VisualPtr PanoramiXVisuals;
+
+RESTYPE XRC_DRAWABLE;
+RESTYPE XRT_WINDOW;
+RESTYPE XRT_PIXMAP;
+RESTYPE XRT_GC;
+RESTYPE XRT_COLORMAP;
+
+static Bool VisualsEqual(VisualPtr, ScreenPtr, VisualPtr);
+XineramaVisualsEqualProcPtr XineramaVisualsEqualPtr = &VisualsEqual;
+
+/*
+ * Function prototypes
+ */
+
+static int panoramiXGeneration;
+static int ProcPanoramiXDispatch(ClientPtr client);
+
+static void PanoramiXResetProc(ExtensionEntry*);
+
+/*
+ * External references for functions and data variables
+ */
+
+#include "panoramiXh.h"
+
+int (* SavedProcVector[256]) (ClientPtr client) = { NULL, };
+
+static DevPrivateKeyRec PanoramiXGCKeyRec;
+#define PanoramiXGCKey (&PanoramiXGCKeyRec)
+static DevPrivateKeyRec PanoramiXScreenKeyRec;
+#define PanoramiXScreenKey (&PanoramiXScreenKeyRec)
+
+typedef struct {
+ DDXPointRec clipOrg;
+ DDXPointRec patOrg;
+ GCFuncs *wrapFuncs;
+} PanoramiXGCRec, *PanoramiXGCPtr;
+
+typedef struct {
+ CreateGCProcPtr CreateGC;
+ CloseScreenProcPtr CloseScreen;
+} PanoramiXScreenRec, *PanoramiXScreenPtr;
+
+static void XineramaValidateGC(GCPtr, unsigned long, DrawablePtr);
+static void XineramaChangeGC(GCPtr, unsigned long);
+static void XineramaCopyGC(GCPtr, unsigned long, GCPtr);
+static void XineramaDestroyGC(GCPtr);
+static void XineramaChangeClip(GCPtr, int, pointer, int);
+static void XineramaDestroyClip(GCPtr);
+static void XineramaCopyClip(GCPtr, GCPtr);
+
+static GCFuncs XineramaGCFuncs = {
+ XineramaValidateGC, XineramaChangeGC, XineramaCopyGC, XineramaDestroyGC,
+ XineramaChangeClip, XineramaDestroyClip, XineramaCopyClip
+};
+
+#define Xinerama_GC_FUNC_PROLOGUE(pGC)\
+ PanoramiXGCPtr pGCPriv = (PanoramiXGCPtr) \
+ dixLookupPrivate(&(pGC)->devPrivates, PanoramiXGCKey); \
+ (pGC)->funcs = pGCPriv->wrapFuncs;
+
+#define Xinerama_GC_FUNC_EPILOGUE(pGC)\
+ pGCPriv->wrapFuncs = (pGC)->funcs;\
+ (pGC)->funcs = &XineramaGCFuncs;
+
+
+static Bool
+XineramaCloseScreen (int i, ScreenPtr pScreen)
+{
+ PanoramiXScreenPtr pScreenPriv = (PanoramiXScreenPtr)
+ dixLookupPrivate(&pScreen->devPrivates, PanoramiXScreenKey);
+
+ pScreen->CloseScreen = pScreenPriv->CloseScreen;
+ pScreen->CreateGC = pScreenPriv->CreateGC;
+
+ if (pScreen->myNum == 0)
+ RegionUninit(&PanoramiXScreenRegion);
+
+ free((pointer) pScreenPriv);
+
+ return (*pScreen->CloseScreen) (i, pScreen);
+}
+
+static Bool
+XineramaCreateGC(GCPtr pGC)
+{
+ ScreenPtr pScreen = pGC->pScreen;
+ PanoramiXScreenPtr pScreenPriv = (PanoramiXScreenPtr)
+ dixLookupPrivate(&pScreen->devPrivates, PanoramiXScreenKey);
+ Bool ret;
+
+ pScreen->CreateGC = pScreenPriv->CreateGC;
+ if((ret = (*pScreen->CreateGC)(pGC))) {
+ PanoramiXGCPtr pGCPriv = (PanoramiXGCPtr)
+ dixLookupPrivate(&pGC->devPrivates, PanoramiXGCKey);
+
+ pGCPriv->wrapFuncs = pGC->funcs;
+ pGC->funcs = &XineramaGCFuncs;
+
+ pGCPriv->clipOrg.x = pGC->clipOrg.x;
+ pGCPriv->clipOrg.y = pGC->clipOrg.y;
+ pGCPriv->patOrg.x = pGC->patOrg.x;
+ pGCPriv->patOrg.y = pGC->patOrg.y;
+ }
+ pScreen->CreateGC = XineramaCreateGC;
+
+ return ret;
+}
+
+static void
+XineramaValidateGC(
+ GCPtr pGC,
+ unsigned long changes,
+ DrawablePtr pDraw
+){
+ Xinerama_GC_FUNC_PROLOGUE (pGC);
+
+ if((pDraw->type == DRAWABLE_WINDOW) && !(((WindowPtr)pDraw)->parent)) {
+ /* the root window */
+ int x_off = pGC->pScreen->x;
+ int y_off = pGC->pScreen->y;
+ int new_val;
+
+ new_val = pGCPriv->clipOrg.x - x_off;
+ if(pGC->clipOrg.x != new_val) {
+ pGC->clipOrg.x = new_val;
+ changes |= GCClipXOrigin;
+ }
+ new_val = pGCPriv->clipOrg.y - y_off;
+ if(pGC->clipOrg.y != new_val) {
+ pGC->clipOrg.y = new_val;
+ changes |= GCClipYOrigin;
+ }
+ new_val = pGCPriv->patOrg.x - x_off;
+ if(pGC->patOrg.x != new_val) {
+ pGC->patOrg.x = new_val;
+ changes |= GCTileStipXOrigin;
+ }
+ new_val = pGCPriv->patOrg.y - y_off;
+ if(pGC->patOrg.y != new_val) {
+ pGC->patOrg.y = new_val;
+ changes |= GCTileStipYOrigin;
+ }
+ } else {
+ if(pGC->clipOrg.x != pGCPriv->clipOrg.x) {
+ pGC->clipOrg.x = pGCPriv->clipOrg.x;
+ changes |= GCClipXOrigin;
+ }
+ if(pGC->clipOrg.y != pGCPriv->clipOrg.y) {
+ pGC->clipOrg.y = pGCPriv->clipOrg.y;
+ changes |= GCClipYOrigin;
+ }
+ if(pGC->patOrg.x != pGCPriv->patOrg.x) {
+ pGC->patOrg.x = pGCPriv->patOrg.x;
+ changes |= GCTileStipXOrigin;
+ }
+ if(pGC->patOrg.y != pGCPriv->patOrg.y) {
+ pGC->patOrg.y = pGCPriv->patOrg.y;
+ changes |= GCTileStipYOrigin;
+ }
+ }
+
+ (*pGC->funcs->ValidateGC)(pGC, changes, pDraw);
+ Xinerama_GC_FUNC_EPILOGUE (pGC);
+}
+
+static void
+XineramaDestroyGC(GCPtr pGC)
+{
+ Xinerama_GC_FUNC_PROLOGUE (pGC);
+ (*pGC->funcs->DestroyGC)(pGC);
+ Xinerama_GC_FUNC_EPILOGUE (pGC);
+}
+
+static void
+XineramaChangeGC (
+ GCPtr pGC,
+ unsigned long mask
+){
+ Xinerama_GC_FUNC_PROLOGUE (pGC);
+
+ if(mask & GCTileStipXOrigin)
+ pGCPriv->patOrg.x = pGC->patOrg.x;
+ if(mask & GCTileStipYOrigin)
+ pGCPriv->patOrg.y = pGC->patOrg.y;
+ if(mask & GCClipXOrigin)
+ pGCPriv->clipOrg.x = pGC->clipOrg.x;
+ if(mask & GCClipYOrigin)
+ pGCPriv->clipOrg.y = pGC->clipOrg.y;
+
+ (*pGC->funcs->ChangeGC) (pGC, mask);
+ Xinerama_GC_FUNC_EPILOGUE (pGC);
+}
+
+static void
+XineramaCopyGC (
+ GCPtr pGCSrc,
+ unsigned long mask,
+ GCPtr pGCDst
+){
+ PanoramiXGCPtr pSrcPriv = (PanoramiXGCPtr)
+ dixLookupPrivate(&pGCSrc->devPrivates, PanoramiXGCKey);
+ Xinerama_GC_FUNC_PROLOGUE (pGCDst);
+
+ if(mask & GCTileStipXOrigin)
+ pGCPriv->patOrg.x = pSrcPriv->patOrg.x;
+ if(mask & GCTileStipYOrigin)
+ pGCPriv->patOrg.y = pSrcPriv->patOrg.y;
+ if(mask & GCClipXOrigin)
+ pGCPriv->clipOrg.x = pSrcPriv->clipOrg.x;
+ if(mask & GCClipYOrigin)
+ pGCPriv->clipOrg.y = pSrcPriv->clipOrg.y;
+
+ (*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst);
+ Xinerama_GC_FUNC_EPILOGUE (pGCDst);
+}
+
+static void
+XineramaChangeClip (
+ GCPtr pGC,
+ int type,
+ pointer pvalue,
+ int nrects
+){
+ Xinerama_GC_FUNC_PROLOGUE (pGC);
+ (*pGC->funcs->ChangeClip) (pGC, type, pvalue, nrects);
+ Xinerama_GC_FUNC_EPILOGUE (pGC);
+}
+
+static void
+XineramaCopyClip(GCPtr pgcDst, GCPtr pgcSrc)
+{
+ Xinerama_GC_FUNC_PROLOGUE (pgcDst);
+ (* pgcDst->funcs->CopyClip)(pgcDst, pgcSrc);
+ Xinerama_GC_FUNC_EPILOGUE (pgcDst);
+}
+
+static void
+XineramaDestroyClip(GCPtr pGC)
+{
+ Xinerama_GC_FUNC_PROLOGUE (pGC);
+ (* pGC->funcs->DestroyClip)(pGC);
+ Xinerama_GC_FUNC_EPILOGUE (pGC);
+}
+
+int
+XineramaDeleteResource(pointer data, XID id)
+{
+ free(data);
+ return 1;
+}
+
+typedef struct {
+ int screen;
+ int id;
+} PanoramiXSearchData;
+
+static Bool
+XineramaFindIDByScrnum(pointer resource, XID id, pointer privdata)
+{
+ PanoramiXRes *res = (PanoramiXRes*)resource;
+ PanoramiXSearchData *data = (PanoramiXSearchData*)privdata;
+
+ return res->info[data->screen].id == data->id;
+}
+
+PanoramiXRes *
+PanoramiXFindIDByScrnum(RESTYPE type, XID id, int screen)
+{
+ PanoramiXSearchData data;
+ pointer val;
+
+ if(!screen) {
+ dixLookupResourceByType(&val, id, type, serverClient, DixReadAccess);
+ return val;
+ }
+
+ data.screen = screen;
+ data.id = id;
+
+ return LookupClientResourceComplex(clients[CLIENT_ID(id)], type,
+ XineramaFindIDByScrnum, &data);
+}
+
+typedef struct _connect_callback_list {
+ void (*func)(void);
+ struct _connect_callback_list *next;
+} XineramaConnectionCallbackList;
+
+static XineramaConnectionCallbackList *ConnectionCallbackList = NULL;
+
+Bool
+XineramaRegisterConnectionBlockCallback(void (*func)(void))
+{
+ XineramaConnectionCallbackList *newlist;
+
+ if(!(newlist = malloc(sizeof(XineramaConnectionCallbackList))))
+ return FALSE;
+
+ newlist->next = ConnectionCallbackList;
+ newlist->func = func;
+ ConnectionCallbackList = newlist;
+
+ return TRUE;
+}
+
+static void XineramaInitData(ScreenPtr pScreen)
+{
+ int i, w, h;
+
+ RegionNull(&PanoramiXScreenRegion);
+ FOR_NSCREENS(i) {
+ BoxRec TheBox;
+ RegionRec ScreenRegion;
+
+ pScreen = screenInfo.screens[i];
+
+ TheBox.x1 = pScreen->x;
+ TheBox.x2 = TheBox.x1 + pScreen->width;
+ TheBox.y1 = pScreen->y;
+ TheBox.y2 = TheBox.y1 + pScreen->height;
+
+ RegionInit(&ScreenRegion, &TheBox, 1);
+ RegionUnion(&PanoramiXScreenRegion, &PanoramiXScreenRegion,
+ &ScreenRegion);
+ RegionUninit(&ScreenRegion);
+ }
+
+ PanoramiXPixWidth = screenInfo.screens[0]->x + screenInfo.screens[0]->width;
+ PanoramiXPixHeight = screenInfo.screens[0]->y + screenInfo.screens[0]->height;
+
+ FOR_NSCREENS_FORWARD_SKIP(i) {
+ pScreen = screenInfo.screens[i];
+ w = pScreen->x + pScreen->width;
+ h = pScreen->y + pScreen->height;
+
+ if (PanoramiXPixWidth < w)
+ PanoramiXPixWidth = w;
+ if (PanoramiXPixHeight < h)
+ PanoramiXPixHeight = h;
+ }
+}
+
+void XineramaReinitData(ScreenPtr pScreen)
+{
+ RegionUninit(&PanoramiXScreenRegion);
+ XineramaInitData(pScreen);
+}
+
+/*
+ * PanoramiXExtensionInit():
+ * Called from InitExtensions in main().
+ * Register PanoramiXeen Extension
+ * Initialize global variables.
+ */
+
+void PanoramiXExtensionInit(int argc, char *argv[])
+{
+ int i;
+ Bool success = FALSE;
+ ExtensionEntry *extEntry;
+ ScreenPtr pScreen = screenInfo.screens[0];
+ PanoramiXScreenPtr pScreenPriv;
+
+ if (noPanoramiXExtension)
+ return;
+
+ if (!dixRegisterPrivateKey(&PanoramiXScreenKeyRec, PRIVATE_SCREEN, 0)) {
+ noPanoramiXExtension = TRUE;
+ return;
+ }
+
+ if (!dixRegisterPrivateKey(&PanoramiXGCKeyRec, PRIVATE_GC, sizeof(PanoramiXGCRec))) {
+ noPanoramiXExtension = TRUE;
+ return;
+ }
+
+ PanoramiXNumScreens = screenInfo.numScreens;
+ if (PanoramiXNumScreens == 1) { /* Only 1 screen */
+ noPanoramiXExtension = TRUE;
+ return;
+ }
+
+ while (panoramiXGeneration != serverGeneration) {
+ extEntry = AddExtension(PANORAMIX_PROTOCOL_NAME, 0,0,
+ ProcPanoramiXDispatch,
+ SProcPanoramiXDispatch, PanoramiXResetProc,
+ StandardMinorOpcode);
+ if (!extEntry)
+ break;
+
+ /*
+ * First make sure all the basic allocations succeed. If not,
+ * run in non-PanoramiXeen mode.
+ */
+
+ FOR_NSCREENS(i) {
+ pScreen = screenInfo.screens[i];
+ pScreenPriv = malloc(sizeof(PanoramiXScreenRec));
+ dixSetPrivate(&pScreen->devPrivates, PanoramiXScreenKey,
+ pScreenPriv);
+ if(!pScreenPriv) {
+ noPanoramiXExtension = TRUE;
+ return;
+ }
+
+ pScreenPriv->CreateGC = pScreen->CreateGC;
+ pScreenPriv->CloseScreen = pScreen->CloseScreen;
+
+ pScreen->CreateGC = XineramaCreateGC;
+ pScreen->CloseScreen = XineramaCloseScreen;
+ }
+
+ XRC_DRAWABLE = CreateNewResourceClass();
+ XRT_WINDOW = CreateNewResourceType(XineramaDeleteResource,
+ "XineramaWindow");
+ if (XRT_WINDOW)
+ XRT_WINDOW |= XRC_DRAWABLE;
+ XRT_PIXMAP = CreateNewResourceType(XineramaDeleteResource,
+ "XineramaPixmap");
+ if (XRT_PIXMAP)
+ XRT_PIXMAP |= XRC_DRAWABLE;
+ XRT_GC = CreateNewResourceType(XineramaDeleteResource,
+ "XineramaGC");
+ XRT_COLORMAP = CreateNewResourceType(XineramaDeleteResource,
+ "XineramaColormap");
+
+ if (XRT_WINDOW && XRT_PIXMAP && XRT_GC && XRT_COLORMAP) {
+ panoramiXGeneration = serverGeneration;
+ success = TRUE;
+ }
+ SetResourceTypeErrorValue(XRT_WINDOW, BadWindow);
+ SetResourceTypeErrorValue(XRT_PIXMAP, BadPixmap);
+ SetResourceTypeErrorValue(XRT_GC, BadGC);
+ SetResourceTypeErrorValue(XRT_COLORMAP, BadColor);
+ }
+
+ if (!success) {
+ noPanoramiXExtension = TRUE;
+ ErrorF(PANORAMIX_PROTOCOL_NAME " extension failed to initialize\n");
+ return;
+ }
+
+ XineramaInitData(pScreen);
+
+ /*
+ * Put our processes into the ProcVector
+ */
+
+ for (i = 256; i--; )
+ SavedProcVector[i] = ProcVector[i];
+
+ ProcVector[X_CreateWindow] = PanoramiXCreateWindow;
+ ProcVector[X_ChangeWindowAttributes] = PanoramiXChangeWindowAttributes;
+ ProcVector[X_DestroyWindow] = PanoramiXDestroyWindow;
+ ProcVector[X_DestroySubwindows] = PanoramiXDestroySubwindows;
+ ProcVector[X_ChangeSaveSet] = PanoramiXChangeSaveSet;
+ ProcVector[X_ReparentWindow] = PanoramiXReparentWindow;
+ ProcVector[X_MapWindow] = PanoramiXMapWindow;
+ ProcVector[X_MapSubwindows] = PanoramiXMapSubwindows;
+ ProcVector[X_UnmapWindow] = PanoramiXUnmapWindow;
+ ProcVector[X_UnmapSubwindows] = PanoramiXUnmapSubwindows;
+ ProcVector[X_ConfigureWindow] = PanoramiXConfigureWindow;
+ ProcVector[X_CirculateWindow] = PanoramiXCirculateWindow;
+ ProcVector[X_GetGeometry] = PanoramiXGetGeometry;
+ ProcVector[X_TranslateCoords] = PanoramiXTranslateCoords;
+ ProcVector[X_CreatePixmap] = PanoramiXCreatePixmap;
+ ProcVector[X_FreePixmap] = PanoramiXFreePixmap;
+ ProcVector[X_CreateGC] = PanoramiXCreateGC;
+ ProcVector[X_ChangeGC] = PanoramiXChangeGC;
+ ProcVector[X_CopyGC] = PanoramiXCopyGC;
+ ProcVector[X_SetDashes] = PanoramiXSetDashes;
+ ProcVector[X_SetClipRectangles] = PanoramiXSetClipRectangles;
+ ProcVector[X_FreeGC] = PanoramiXFreeGC;
+ ProcVector[X_ClearArea] = PanoramiXClearToBackground;
+ ProcVector[X_CopyArea] = PanoramiXCopyArea;
+ ProcVector[X_CopyPlane] = PanoramiXCopyPlane;
+ ProcVector[X_PolyPoint] = PanoramiXPolyPoint;
+ ProcVector[X_PolyLine] = PanoramiXPolyLine;
+ ProcVector[X_PolySegment] = PanoramiXPolySegment;
+ ProcVector[X_PolyRectangle] = PanoramiXPolyRectangle;
+ ProcVector[X_PolyArc] = PanoramiXPolyArc;
+ ProcVector[X_FillPoly] = PanoramiXFillPoly;
+ ProcVector[X_PolyFillRectangle] = PanoramiXPolyFillRectangle;
+ ProcVector[X_PolyFillArc] = PanoramiXPolyFillArc;
+ ProcVector[X_PutImage] = PanoramiXPutImage;
+ ProcVector[X_GetImage] = PanoramiXGetImage;
+ ProcVector[X_PolyText8] = PanoramiXPolyText8;
+ ProcVector[X_PolyText16] = PanoramiXPolyText16;
+ ProcVector[X_ImageText8] = PanoramiXImageText8;
+ ProcVector[X_ImageText16] = PanoramiXImageText16;
+ ProcVector[X_CreateColormap] = PanoramiXCreateColormap;
+ ProcVector[X_FreeColormap] = PanoramiXFreeColormap;
+ ProcVector[X_CopyColormapAndFree] = PanoramiXCopyColormapAndFree;
+ ProcVector[X_InstallColormap] = PanoramiXInstallColormap;
+ ProcVector[X_UninstallColormap] = PanoramiXUninstallColormap;
+ ProcVector[X_AllocColor] = PanoramiXAllocColor;
+ ProcVector[X_AllocNamedColor] = PanoramiXAllocNamedColor;
+ ProcVector[X_AllocColorCells] = PanoramiXAllocColorCells;
+ ProcVector[X_AllocColorPlanes] = PanoramiXAllocColorPlanes;
+ ProcVector[X_FreeColors] = PanoramiXFreeColors;
+ ProcVector[X_StoreColors] = PanoramiXStoreColors;
+ ProcVector[X_StoreNamedColor] = PanoramiXStoreNamedColor;
+
+ PanoramiXRenderInit ();
+#ifdef XFIXES
+ PanoramiXFixesInit ();
+#endif
+#ifdef COMPOSITE
+ PanoramiXCompositeInit ();
+#endif
+
+}
+
+extern Bool CreateConnectionBlock(void);
+
+Bool PanoramiXCreateConnectionBlock(void)
+{
+ int i, j, length;
+ Bool disableBackingStore = FALSE;
+ int old_width, old_height;
+ float width_mult, height_mult;
+ xWindowRoot *root;
+ xVisualType *visual;
+ xDepth *depth;
+ VisualPtr pVisual;
+ ScreenPtr pScreen;
+
+ /*
+ * Do normal CreateConnectionBlock but faking it for only one screen
+ */
+
+ if(!PanoramiXNumDepths) {
+ ErrorF("Xinerama error: No common visuals\n");
+ return FALSE;
+ }
+
+ for(i = 1; i < screenInfo.numScreens; i++) {
+ pScreen = screenInfo.screens[i];
+ if(pScreen->rootDepth != screenInfo.screens[0]->rootDepth) {
+ ErrorF("Xinerama error: Root window depths differ\n");
+ return FALSE;
+ }
+ if(pScreen->backingStoreSupport != screenInfo.screens[0]->backingStoreSupport)
+ disableBackingStore = TRUE;
+ }
+
+ if (disableBackingStore) {
+ for (i = 0; i < screenInfo.numScreens; i++) {
+ pScreen = screenInfo.screens[i];
+ pScreen->backingStoreSupport = NotUseful;
+ }
+ }
+
+ i = screenInfo.numScreens;
+ screenInfo.numScreens = 1;
+ if (!CreateConnectionBlock()) {
+ screenInfo.numScreens = i;
+ return FALSE;
+ }
+
+ screenInfo.numScreens = i;
+
+ root = (xWindowRoot *) (ConnectionInfo + connBlockScreenStart);
+ length = connBlockScreenStart + sizeof(xWindowRoot);
+
+ /* overwrite the connection block */
+ root->nDepths = PanoramiXNumDepths;
+
+ for (i = 0; i < PanoramiXNumDepths; i++) {
+ depth = (xDepth *) (ConnectionInfo + length);
+ depth->depth = PanoramiXDepths[i].depth;
+ depth->nVisuals = PanoramiXDepths[i].numVids;
+ length += sizeof(xDepth);
+ visual = (xVisualType *)(ConnectionInfo + length);
+
+ for (j = 0; j < depth->nVisuals; j++, visual++) {
+ visual->visualID = PanoramiXDepths[i].vids[j];
+
+ for (pVisual = PanoramiXVisuals;
+ pVisual->vid != visual->visualID;
+ pVisual++)
+ ;
+
+ visual->class = pVisual->class;
+ visual->bitsPerRGB = pVisual->bitsPerRGBValue;
+ visual->colormapEntries = pVisual->ColormapEntries;
+ visual->redMask = pVisual->redMask;
+ visual->greenMask = pVisual->greenMask;
+ visual->blueMask = pVisual->blueMask;
+ }
+
+ length += (depth->nVisuals * sizeof(xVisualType));
+ }
+
+ connSetupPrefix.length = bytes_to_int32(length);
+
+ for (i = 0; i < PanoramiXNumDepths; i++)
+ free(PanoramiXDepths[i].vids);
+ free(PanoramiXDepths);
+ PanoramiXDepths = NULL;
+
+ /*
+ * OK, change some dimensions so it looks as if it were one big screen
+ */
+
+ old_width = root->pixWidth;
+ old_height = root->pixHeight;
+
+ root->pixWidth = PanoramiXPixWidth;
+ root->pixHeight = PanoramiXPixHeight;
+ width_mult = (1.0 * root->pixWidth) / old_width;
+ height_mult = (1.0 * root->pixHeight) / old_height;
+ root->mmWidth *= width_mult;
+ root->mmHeight *= height_mult;
+
+ while(ConnectionCallbackList) {
+ pointer tmp;
+
+ tmp = (pointer)ConnectionCallbackList;
+ (*ConnectionCallbackList->func)();
+ ConnectionCallbackList = ConnectionCallbackList->next;
+ free(tmp);
+ }
+
+ return TRUE;
+}
+
+/*
+ * This isn't just memcmp(), bitsPerRGBValue is skipped. markv made that
+ * change way back before xf86 4.0, but the comment for _why_ is a bit
+ * opaque, so I'm not going to question it for now.
+ *
+ * This is probably better done as a screen hook so DBE/EVI/GLX can add
+ * their own tests, and adding privates to VisualRec so they don't have to
+ * do their own back-mapping.
+ */
+static Bool
+VisualsEqual(VisualPtr a, ScreenPtr pScreenB, VisualPtr b)
+{
+ return ((a->class == b->class) &&
+ (a->ColormapEntries == b->ColormapEntries) &&
+ (a->nplanes == b->nplanes) &&
+ (a->redMask == b->redMask) &&
+ (a->greenMask == b->greenMask) &&
+ (a->blueMask == b->blueMask) &&
+ (a->offsetRed == b->offsetRed) &&
+ (a->offsetGreen == b->offsetGreen) &&
+ (a->offsetBlue == b->offsetBlue));
+}
+
+static void
+PanoramiXMaybeAddDepth(DepthPtr pDepth)
+{
+ ScreenPtr pScreen;
+ int j, k;
+ Bool found = FALSE;
+
+ FOR_NSCREENS_FORWARD_SKIP(j) {
+ pScreen = screenInfo.screens[j];
+ for (k = 0; k < pScreen->numDepths; k++) {
+ if (pScreen->allowedDepths[k].depth == pDepth->depth) {
+ found = TRUE;
+ break;
+ }
+ }
+ }
+
+ if (!found)
+ return;
+
+ j = PanoramiXNumDepths;
+ PanoramiXNumDepths++;
+ PanoramiXDepths = realloc(PanoramiXDepths,
+ PanoramiXNumDepths * sizeof(DepthRec));
+ PanoramiXDepths[j].depth = pDepth->depth;
+ PanoramiXDepths[j].numVids = 0;
+ /* XXX suboptimal, should grow these dynamically */
+ if(pDepth->numVids)
+ PanoramiXDepths[j].vids = malloc(sizeof(VisualID) * pDepth->numVids);
+ else
+ PanoramiXDepths[j].vids = NULL;
+}
+
+static void
+PanoramiXMaybeAddVisual(VisualPtr pVisual)
+{
+ ScreenPtr pScreen;
+ int j, k;
+ Bool found = FALSE;
+
+ FOR_NSCREENS_FORWARD_SKIP(j) {
+ pScreen = screenInfo.screens[j];
+ found = FALSE;
+
+ for (k = 0; k < pScreen->numVisuals; k++) {
+ VisualPtr candidate = &pScreen->visuals[k];
+
+ if ((*XineramaVisualsEqualPtr)(pVisual, pScreen, candidate)
+#ifdef GLXPROXY
+ && glxMatchVisual(screenInfo.screens[0], pVisual, pScreen)
+#endif
+ ) {
+ found = TRUE;
+ break;
+ }
+ }
+
+ if (!found)
+ return;
+ }
+
+ /* found a matching visual on all screens, add it to the subset list */
+ j = PanoramiXNumVisuals;
+ PanoramiXNumVisuals++;
+ PanoramiXVisuals = realloc(PanoramiXVisuals,
+ PanoramiXNumVisuals * sizeof(VisualRec));
+
+ memcpy(&PanoramiXVisuals[j], pVisual, sizeof(VisualRec));
+
+ for (k = 0; k < PanoramiXNumDepths; k++) {
+ if (PanoramiXDepths[k].depth == pVisual->nplanes) {
+ PanoramiXDepths[k].vids[PanoramiXDepths[k].numVids] = pVisual->vid;
+ PanoramiXDepths[k].numVids++;
+ break;
+ }
+ }
+}
+
+extern void
+PanoramiXConsolidate(void)
+{
+ int i;
+ PanoramiXRes *root, *defmap, *saver;
+ ScreenPtr pScreen = screenInfo.screens[0];
+ DepthPtr pDepth = pScreen->allowedDepths;
+ VisualPtr pVisual = pScreen->visuals;
+
+ PanoramiXNumDepths = 0;
+ PanoramiXNumVisuals = 0;
+
+ for (i = 0; i < pScreen->numDepths; i++)
+ PanoramiXMaybeAddDepth(pDepth++);
+
+ for (i = 0; i < pScreen->numVisuals; i++)
+ PanoramiXMaybeAddVisual(pVisual++);
+
+ root = malloc(sizeof(PanoramiXRes));
+ root->type = XRT_WINDOW;
+ defmap = malloc(sizeof(PanoramiXRes));
+ defmap->type = XRT_COLORMAP;
+ saver = malloc(sizeof(PanoramiXRes));
+ saver->type = XRT_WINDOW;
+
+ FOR_NSCREENS(i) {
+ ScreenPtr pScreen = screenInfo.screens[i];
+ root->info[i].id = pScreen->root->drawable.id;
+ root->u.win.class = InputOutput;
+ root->u.win.root = TRUE;
+ saver->info[i].id = pScreen->screensaver.wid;
+ saver->u.win.class = InputOutput;
+ saver->u.win.root = TRUE;
+ defmap->info[i].id = pScreen->defColormap;
+ }
+
+ AddResource(root->info[0].id, XRT_WINDOW, root);
+ AddResource(saver->info[0].id, XRT_WINDOW, saver);
+ AddResource(defmap->info[0].id, XRT_COLORMAP, defmap);
+}
+
+VisualID
+PanoramiXTranslateVisualID(int screen, VisualID orig)
+{
+ ScreenPtr pOtherScreen = screenInfo.screens[screen];
+ VisualPtr pVisual = NULL;
+ int i;
+
+ for (i = 0; i < PanoramiXNumVisuals; i++) {
+ if (orig == PanoramiXVisuals[i].vid) {
+ pVisual = &PanoramiXVisuals[i];
+ break;
+ }
+ }
+
+ if (!pVisual)
+ return 0;
+
+ /* if screen is 0, orig is already the correct visual ID */
+ if (screen == 0)
+ return orig;
+
+ /* found the original, now translate it relative to the backend screen */
+ for (i = 0; i < pOtherScreen->numVisuals; i++) {
+ VisualPtr pOtherVisual = &pOtherScreen->visuals[i];
+
+ if ((*XineramaVisualsEqualPtr)(pVisual, pOtherScreen, pOtherVisual))
+ return pOtherVisual->vid;
+ }
+
+ return 0;
+}
+
+
+/*
+ * PanoramiXResetProc()
+ * Exit, deallocating as needed.
+ */
+
+static void PanoramiXResetProc(ExtensionEntry* extEntry)
+{
+ int i;
+
+ PanoramiXRenderReset ();
+#ifdef XFIXES
+ PanoramiXFixesReset ();
+#endif
+ screenInfo.numScreens = PanoramiXNumScreens;
+ for (i = 256; i--; )
+ ProcVector[i] = SavedProcVector[i];
+}
+
+
+int
+ProcPanoramiXQueryVersion (ClientPtr client)
+{
+ /* REQUEST(xPanoramiXQueryVersionReq); */
+ xPanoramiXQueryVersionReply rep;
+ register int n;
+
+ REQUEST_SIZE_MATCH (xPanoramiXQueryVersionReq);
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+ rep.majorVersion = SERVER_PANORAMIX_MAJOR_VERSION;
+ rep.minorVersion = SERVER_PANORAMIX_MINOR_VERSION;
+ if (client->swapped) {
+ swaps(&rep.sequenceNumber, n);
+ swapl(&rep.length, n);
+ swaps(&rep.majorVersion, n);
+ swaps(&rep.minorVersion, n);
+ }
+ WriteToClient(client, sizeof (xPanoramiXQueryVersionReply), (char *)&rep);
+ return Success;
+}
+
+int
+ProcPanoramiXGetState(ClientPtr client)
+{
+ REQUEST(xPanoramiXGetStateReq);
+ WindowPtr pWin;
+ xPanoramiXGetStateReply rep;
+ int n, rc;
+
+ REQUEST_SIZE_MATCH(xPanoramiXGetStateReq);
+ rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
+ if (rc != Success)
+ return rc;
+
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+ rep.state = !noPanoramiXExtension;
+ rep.window = stuff->window;
+ if (client->swapped) {
+ swaps (&rep.sequenceNumber, n);
+ swapl (&rep.length, n);
+ swapl (&rep.window, n);
+ }
+ WriteToClient (client, sizeof (xPanoramiXGetStateReply), (char *) &rep);
+ return Success;
+
+}
+
+int
+ProcPanoramiXGetScreenCount(ClientPtr client)
+{
+ REQUEST(xPanoramiXGetScreenCountReq);
+ WindowPtr pWin;
+ xPanoramiXGetScreenCountReply rep;
+ int n, rc;
+
+ REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq);
+ rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
+ if (rc != Success)
+ return rc;
+
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+ rep.ScreenCount = PanoramiXNumScreens;
+ rep.window = stuff->window;
+ if (client->swapped) {
+ swaps (&rep.sequenceNumber, n);
+ swapl (&rep.length, n);
+ swapl (&rep.window, n);
+ }
+ WriteToClient (client, sizeof (xPanoramiXGetScreenCountReply), (char *) &rep);
+ return Success;
+}
+
+int
+ProcPanoramiXGetScreenSize(ClientPtr client)
+{
+ REQUEST(xPanoramiXGetScreenSizeReq);
+ WindowPtr pWin;
+ xPanoramiXGetScreenSizeReply rep;
+ int n, rc;
+
+ if (stuff->screen >= PanoramiXNumScreens)
+ return BadMatch;
+
+ REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq);
+ rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
+ if (rc != Success)
+ return rc;
+
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+ /* screen dimensions */
+ rep.width = screenInfo.screens[stuff->screen]->width;
+ rep.height = screenInfo.screens[stuff->screen]->height;
+ rep.window = stuff->window;
+ rep.screen = stuff->screen;
+ if (client->swapped) {
+ swaps (&rep.sequenceNumber, n);
+ swapl (&rep.length, n);
+ swapl (&rep.width, n);
+ swapl (&rep.height, n);
+ swapl (&rep.window, n);
+ swapl (&rep.screen, n);
+ }
+ WriteToClient (client, sizeof (xPanoramiXGetScreenSizeReply), (char *) &rep);
+ return Success;
+}
+
+
+int
+ProcXineramaIsActive(ClientPtr client)
+{
+ /* REQUEST(xXineramaIsActiveReq); */
+ xXineramaIsActiveReply rep;
+
+ REQUEST_SIZE_MATCH(xXineramaIsActiveReq);
+
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+#if 1
+ {
+ /* The following hack fools clients into thinking that Xinerama
+ * is disabled even though it is not. */
+ rep.state = !noPanoramiXExtension && !PanoramiXExtensionDisabledHack;
+ }
+#else
+ rep.state = !noPanoramiXExtension;
+#endif
+ if (client->swapped) {
+ int n;
+ swaps (&rep.sequenceNumber, n);
+ swapl (&rep.length, n);
+ swapl (&rep.state, n);
+ }
+ WriteToClient (client, sizeof (xXineramaIsActiveReply), (char *) &rep);
+ return Success;
+}
+
+
+int
+ProcXineramaQueryScreens(ClientPtr client)
+{
+ /* REQUEST(xXineramaQueryScreensReq); */
+ xXineramaQueryScreensReply rep;
+
+ REQUEST_SIZE_MATCH(xXineramaQueryScreensReq);
+
+ rep.type = X_Reply;
+ rep.sequenceNumber = client->sequence;
+ rep.number = (noPanoramiXExtension) ? 0 : PanoramiXNumScreens;
+ rep.length = bytes_to_int32(rep.number * sz_XineramaScreenInfo);
+ if (client->swapped) {
+ int n;
+ swaps (&rep.sequenceNumber, n);
+ swapl (&rep.length, n);
+ swapl (&rep.number, n);
+ }
+ WriteToClient (client, sizeof (xXineramaQueryScreensReply), (char *) &rep);
+
+ if(!noPanoramiXExtension) {
+ xXineramaScreenInfo scratch;
+ int i;
+
+ FOR_NSCREENS(i) {
+ scratch.x_org = screenInfo.screens[i]->x;
+ scratch.y_org = screenInfo.screens[i]->y;
+ scratch.width = screenInfo.screens[i]->width;
+ scratch.height = screenInfo.screens[i]->height;
+
+ if(client->swapped) {
+ int n;
+ swaps (&scratch.x_org, n);
+ swaps (&scratch.y_org, n);
+ swaps (&scratch.width, n);
+ swaps (&scratch.height, n);
+ }
+ WriteToClient (client, sz_XineramaScreenInfo, (char *) &scratch);
+ }
+ }
+
+ return Success;
+}
+
+
+static int
+ProcPanoramiXDispatch (ClientPtr client)
+{ REQUEST(xReq);
+ switch (stuff->data)
+ {
+ case X_PanoramiXQueryVersion:
+ return ProcPanoramiXQueryVersion(client);
+ case X_PanoramiXGetState:
+ return ProcPanoramiXGetState(client);
+ case X_PanoramiXGetScreenCount:
+ return ProcPanoramiXGetScreenCount(client);
+ case X_PanoramiXGetScreenSize:
+ return ProcPanoramiXGetScreenSize(client);
+ case X_XineramaIsActive:
+ return ProcXineramaIsActive(client);
+ case X_XineramaQueryScreens:
+ return ProcXineramaQueryScreens(client);
+ }
+ return BadRequest;
+}
+
+
+#if X_BYTE_ORDER == X_LITTLE_ENDIAN
+#define SHIFT_L(v,s) (v) << (s)
+#define SHIFT_R(v,s) (v) >> (s)
+#else
+#define SHIFT_L(v,s) (v) >> (s)
+#define SHIFT_R(v,s) (v) << (s)
+#endif
+
+static void
+CopyBits(char *dst, int shiftL, char *src, int bytes)
+{
+ /* Just get it to work. Worry about speed later */
+ int shiftR = 8 - shiftL;
+
+ while(bytes--) {
+ *dst |= SHIFT_L(*src, shiftL);
+ *(dst + 1) |= SHIFT_R(*src, shiftR);
+ dst++; src++;
+ }
+}
+
+
+/* Caution. This doesn't support 2 and 4 bpp formats. We expect
+ 1 bpp and planar data to be already cleared when presented
+ to this function */
+
+void
+XineramaGetImageData(
+ DrawablePtr *pDrawables,
+ int left,
+ int top,
+ int width,
+ int height,
+ unsigned int format,
+ unsigned long planemask,
+ char *data,
+ int pitch,
+ Bool isRoot
+){
+ RegionRec SrcRegion, ScreenRegion, GrabRegion;
+ BoxRec SrcBox, *pbox;
+ int x, y, w, h, i, j, nbox, size, sizeNeeded, ScratchPitch, inOut, depth;
+ DrawablePtr pDraw = pDrawables[0];
+ char *ScratchMem = NULL;
+
+ size = 0;
+
+ /* find box in logical screen space */
+ SrcBox.x1 = left;
+ SrcBox.y1 = top;
+ if(!isRoot) {
+ SrcBox.x1 += pDraw->x + screenInfo.screens[0]->x;
+ SrcBox.y1 += pDraw->y + screenInfo.screens[0]->y;
+ }
+ SrcBox.x2 = SrcBox.x1 + width;
+ SrcBox.y2 = SrcBox.y1 + height;
+
+ RegionInit(&SrcRegion, &SrcBox, 1);
+ RegionNull(&GrabRegion);
+
+ depth = (format == XYPixmap) ? 1 : pDraw->depth;
+
+ FOR_NSCREENS(i) {
+ BoxRec TheBox;
+ ScreenPtr pScreen;
+ pDraw = pDrawables[i];
+ pScreen = pDraw->pScreen;
+
+ TheBox.x1 = pScreen->x;
+ TheBox.x2 = TheBox.x1 + pScreen->width;
+ TheBox.y1 = pScreen->y;
+ TheBox.y2 = TheBox.y1 + pScreen->height;
+
+ RegionInit(&ScreenRegion, &TheBox, 1);
+ inOut = RegionContainsRect(&ScreenRegion, &SrcBox);
+ if(inOut == rgnPART)
+ RegionIntersect(&GrabRegion, &SrcRegion, &ScreenRegion);
+ RegionUninit(&ScreenRegion);
+
+ if(inOut == rgnIN) {
+ (*pScreen->GetImage)(pDraw,
+ SrcBox.x1 - pDraw->x - screenInfo.screens[i]->x,
+ SrcBox.y1 - pDraw->y - screenInfo.screens[i]->y,
+ width, height, format, planemask, data);
+ break;
+ } else if (inOut == rgnOUT)
+ continue;
+
+ nbox = RegionNumRects(&GrabRegion);
+
+ if(nbox) {
+ pbox = RegionRects(&GrabRegion);
+
+ while(nbox--) {
+ w = pbox->x2 - pbox->x1;
+ h = pbox->y2 - pbox->y1;
+ ScratchPitch = PixmapBytePad(w, depth);
+ sizeNeeded = ScratchPitch * h;
+
+ if(sizeNeeded > size) {
+ char *tmpdata = ScratchMem;
+ ScratchMem = realloc(ScratchMem, sizeNeeded);
+ if(ScratchMem)
+ size = sizeNeeded;
+ else {
+ ScratchMem = tmpdata;
+ break;
+ }
+ }
+
+ x = pbox->x1 - pDraw->x - screenInfo.screens[i]->x;
+ y = pbox->y1 - pDraw->y - screenInfo.screens[i]->y;
+
+ (*pScreen->GetImage)(pDraw, x, y, w, h,
+ format, planemask, ScratchMem);
+
+ /* copy the memory over */
+
+ if(depth == 1) {
+ int k, shift, leftover, index, index2;
+
+ x = pbox->x1 - SrcBox.x1;
+ y = pbox->y1 - SrcBox.y1;
+ shift = x & 7;
+ x >>= 3;
+ leftover = w & 7;
+ w >>= 3;
+
+ /* clean up the edge */
+ if(leftover) {
+ int mask = (1 << leftover) - 1;
+ for(j = h, k = w; j--; k += ScratchPitch)
+ ScratchMem[k] &= mask;
+ }
+
+ for(j = 0, index = (pitch * y) + x, index2 = 0; j < h;
+ j++, index += pitch, index2 += ScratchPitch)
+ {
+ if(w) {
+ if(!shift)
+ memcpy(data + index, ScratchMem + index2, w);
+ else
+ CopyBits(data + index, shift,
+ ScratchMem + index2, w);
+ }
+
+ if(leftover) {
+ data[index + w] |=
+ SHIFT_L(ScratchMem[index2 + w], shift);
+ if((shift + leftover) > 8)
+ data[index + w + 1] |=
+ SHIFT_R(ScratchMem[index2 + w],(8 - shift));
+ }
+ }
+ } else {
+ j = BitsPerPixel(depth) >> 3;
+ x = (pbox->x1 - SrcBox.x1) * j;
+ y = pbox->y1 - SrcBox.y1;
+ w *= j;
+
+ for(j = 0; j < h; j++) {
+ memcpy(data + (pitch * (y + j)) + x,
+ ScratchMem + (ScratchPitch * j), w);
+ }
+ }
+ pbox++;
+ }
+
+ RegionSubtract(&SrcRegion, &SrcRegion, &GrabRegion);
+ if(!RegionNotEmpty(&SrcRegion))
+ break;
+ }
+
+ }
+
+ free(ScratchMem);
+
+ RegionUninit(&SrcRegion);
+ RegionUninit(&GrabRegion);
+}
|