1292 lines
		
	
	
		
			38 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			1292 lines
		
	
	
		
			38 KiB
		
	
	
	
		
			C
		
	
	
	
| /*****************************************************************
 | |
| 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(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) (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(void)
 | |
| {
 | |
|     int i, w, h;
 | |
| 
 | |
|     RegionNull(&PanoramiXScreenRegion);
 | |
|     FOR_NSCREENS(i) {
 | |
|         BoxRec TheBox;
 | |
|         RegionRec ScreenRegion;
 | |
| 
 | |
|         ScreenPtr 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) {
 | |
|         ScreenPtr 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(void)
 | |
| {
 | |
|     RegionUninit(&PanoramiXScreenRegion);
 | |
|     XineramaInitData();
 | |
| }
 | |
| 
 | |
| /*
 | |
|  *	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();
 | |
| 
 | |
|     /*
 | |
|      *  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;
 | |
| 
 | |
|     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);
 | |
|         swapl(&rep.length);
 | |
|         swaps(&rep.majorVersion);
 | |
|         swaps(&rep.minorVersion);
 | |
|     }
 | |
|     WriteToClient(client, sizeof(xPanoramiXQueryVersionReply), (char *) &rep);
 | |
|     return Success;
 | |
| }
 | |
| 
 | |
| int
 | |
| ProcPanoramiXGetState(ClientPtr client)
 | |
| {
 | |
|     REQUEST(xPanoramiXGetStateReq);
 | |
|     WindowPtr pWin;
 | |
|     xPanoramiXGetStateReply rep;
 | |
|     int 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);
 | |
|         swapl(&rep.length);
 | |
|         swapl(&rep.window);
 | |
|     }
 | |
|     WriteToClient(client, sizeof(xPanoramiXGetStateReply), (char *) &rep);
 | |
|     return Success;
 | |
| 
 | |
| }
 | |
| 
 | |
| int
 | |
| ProcPanoramiXGetScreenCount(ClientPtr client)
 | |
| {
 | |
|     REQUEST(xPanoramiXGetScreenCountReq);
 | |
|     WindowPtr pWin;
 | |
|     xPanoramiXGetScreenCountReply rep;
 | |
|     int 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);
 | |
|         swapl(&rep.length);
 | |
|         swapl(&rep.window);
 | |
|     }
 | |
|     WriteToClient(client, sizeof(xPanoramiXGetScreenCountReply), (char *) &rep);
 | |
|     return Success;
 | |
| }
 | |
| 
 | |
| int
 | |
| ProcPanoramiXGetScreenSize(ClientPtr client)
 | |
| {
 | |
|     REQUEST(xPanoramiXGetScreenSizeReq);
 | |
|     WindowPtr pWin;
 | |
|     xPanoramiXGetScreenSizeReply rep;
 | |
|     int 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);
 | |
|         swapl(&rep.length);
 | |
|         swapl(&rep.width);
 | |
|         swapl(&rep.height);
 | |
|         swapl(&rep.window);
 | |
|         swapl(&rep.screen);
 | |
|     }
 | |
|     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) {
 | |
|         swaps(&rep.sequenceNumber);
 | |
|         swapl(&rep.length);
 | |
|         swapl(&rep.state);
 | |
|     }
 | |
|     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) {
 | |
|         swaps(&rep.sequenceNumber);
 | |
|         swapl(&rep.length);
 | |
|         swapl(&rep.number);
 | |
|     }
 | |
|     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) {
 | |
|                 swaps(&scratch.x_org);
 | |
|                 swaps(&scratch.y_org);
 | |
|                 swaps(&scratch.width);
 | |
|                 swaps(&scratch.height);
 | |
|             }
 | |
|             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);
 | |
| }
 |