diff options
Diffstat (limited to 'Xext/panoramiX.c')
-rw-r--r-- | Xext/panoramiX.c | 1301 |
1 files changed, 893 insertions, 408 deletions
diff --git a/Xext/panoramiX.c b/Xext/panoramiX.c index 2d3eb7c42..fb0b9c541 100644 --- a/Xext/panoramiX.c +++ b/Xext/panoramiX.c @@ -23,11 +23,13 @@ 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. ******************************************************************/ +/* $XFree86: xc/programs/Xserver/Xext/panoramiX.c,v 3.32 2002/08/01 00:30:34 mvojkovi Exp $ */ #define NEED_REPLIES #include <stdio.h> #include "X.h" #include "Xproto.h" +#include "Xarch.h" #include "misc.h" #include "cursor.h" #include "cursorstr.h" @@ -39,32 +41,44 @@ Equipment Corporation. #include "window.h" #include "windowstr.h" #include "pixmapstr.h" -#if 0 -#include <sys/workstation.h> -#include <X11/Xserver/ws.h> -#endif #include "panoramiX.h" #include "panoramiXproto.h" +#include "panoramiXsrv.h" +#include "globals.h" +#include "servermd.h" +#include "resource.h" +#ifdef RENDER +#include "picturestr.h" +#endif + static unsigned char PanoramiXReqCode = 0; /* * PanoramiX data declarations */ -int PanoramiXPixWidth; -int PanoramiXPixHeight; -int PanoramiXNumScreens; +int PanoramiXPixWidth = 0; +int PanoramiXPixHeight = 0; +int PanoramiXNumScreens = 0; + +PanoramiXData *panoramiXdataPtr = NULL; -PanoramiXData *panoramiXdataPtr; -PanoramiXWindow *PanoramiXWinRoot; -PanoramiXGC *PanoramiXGCRoot; -PanoramiXCmap *PanoramiXCmapRoot; -PanoramiXPmap *PanoramiXPmapRoot; -PanoramiXEdge panoramiXEdgePtr[MAXSCREENS]; -RegionRec PanoramiXScreenRegion[MAXSCREENS]; -PanoramiXCDT PanoramiXColorDepthTable[MAXSCREENS]; -PanoramiXDepth PanoramiXLargestScreenDepth; +RegionRec PanoramiXScreenRegion; + +int PanoramiXNumDepths; +DepthPtr PanoramiXDepths; +int PanoramiXNumVisuals; +VisualPtr PanoramiXVisuals; +/* We support at most 256 visuals */ +XID *PanoramiXVisualTable = NULL; + +unsigned long XRC_DRAWABLE; +unsigned long XRT_WINDOW; +unsigned long XRT_PIXMAP; +unsigned long XRT_GC; +unsigned long XRT_COLORMAP; + int (* SavedProcVector[256]) (); ScreenInfo *GlobalScrInfo; @@ -75,7 +89,6 @@ static int ProcPanoramiXDispatch(); * Function prototypes */ -static void locate_neighbors(int); static void PanoramiXResetProc(ExtensionEntry*); /* @@ -83,16 +96,9 @@ static void PanoramiXResetProc(ExtensionEntry*); */ extern int SProcPanoramiXDispatch(); -extern Bool noPanoramiXExtension; -extern Bool PanoramiXVisibilityNotifySent; -extern WindowPtr *WindowTable; -#if 0 -extern ScreenArgsRec screenArgs[MAXSCREENS]; -#endif -extern int defaultBackingStore; extern char *ConnectionInfo; extern int connBlockScreenStart; -extern int (* ProcVector[256]) (); +extern xConnSetupPrefix connSetupPrefix; /* * Server dispatcher function replacements @@ -104,11 +110,10 @@ int PanoramiXChangeSaveSet(), PanoramiXReparentWindow(); int PanoramiXMapWindow(), PanoramiXMapSubwindows(); int PanoramiXUnmapWindow(), PanoramiXUnmapSubwindows(); int PanoramiXConfigureWindow(), PanoramiXCirculateWindow(); -int PanoramiXGetGeometry(), PanoramiXChangeProperty(); -int PanoramiXDeleteProperty(), PanoramiXSendEvent(); +int PanoramiXGetGeometry(), PanoramiXTranslateCoords(); int PanoramiXCreatePixmap(), PanoramiXFreePixmap(); int PanoramiXCreateGC(), PanoramiXChangeGC(); -int PanoramiXCopyGC(); +int PanoramiXCopyGC(), PanoramiXCopyColormapAndFree(); int PanoramiXSetDashes(), PanoramiXSetClipRectangles(); int PanoramiXFreeGC(), PanoramiXClearToBackground(); int PanoramiXCopyArea(), PanoramiXCopyPlane(); @@ -122,8 +127,326 @@ int PanoramiXImageText8(), PanoramiXImageText16(); int PanoramiXCreateColormap(), PanoramiXFreeColormap(); int PanoramiXInstallColormap(), PanoramiXUninstallColormap(); int PanoramiXAllocColor(), PanoramiXAllocNamedColor(); -int PanoramiXAllocColorCells(); +int PanoramiXAllocColorCells(), PanoramiXStoreNamedColor(); int PanoramiXFreeColors(), PanoramiXStoreColors(); +int PanoramiXAllocColorPlanes(); + +static int PanoramiXGCIndex = -1; +static int PanoramiXScreenIndex = -1; + +typedef struct { + DDXPointRec clipOrg; + DDXPointRec patOrg; + GCFuncs *wrapFuncs; +} PanoramiXGCRec, *PanoramiXGCPtr; + +typedef struct { + CreateGCProcPtr CreateGC; + CloseScreenProcPtr CloseScreen; +} PanoramiXScreenRec, *PanoramiXScreenPtr; + +RegionRec XineramaScreenRegions[MAXSCREENS]; + +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); + +GCFuncs XineramaGCFuncs = { + XineramaValidateGC, XineramaChangeGC, XineramaCopyGC, XineramaDestroyGC, + XineramaChangeClip, XineramaDestroyClip, XineramaCopyClip +}; + +#define Xinerama_GC_FUNC_PROLOGUE(pGC)\ + PanoramiXGCPtr pGCPriv = \ + (PanoramiXGCPtr) (pGC)->devPrivates[PanoramiXGCIndex].ptr;\ + (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) pScreen->devPrivates[PanoramiXScreenIndex].ptr; + + pScreen->CloseScreen = pScreenPriv->CloseScreen; + pScreen->CreateGC = pScreenPriv->CreateGC; + + REGION_UNINIT(pScreen, &XineramaScreenRegions[pScreen->myNum]); + if (pScreen->myNum == 0) + REGION_UNINIT(pScreen, &PanoramiXScreenRegion); + + xfree ((pointer) pScreenPriv); + + return (*pScreen->CloseScreen) (i, pScreen); +} + +Bool +XineramaCreateGC(GCPtr pGC) +{ + ScreenPtr pScreen = pGC->pScreen; + PanoramiXScreenPtr pScreenPriv = + (PanoramiXScreenPtr) pScreen->devPrivates[PanoramiXScreenIndex].ptr; + Bool ret; + + pScreen->CreateGC = pScreenPriv->CreateGC; + if((ret = (*pScreen->CreateGC)(pGC))) { + PanoramiXGCPtr pGCPriv = + (PanoramiXGCPtr) pGC->devPrivates[PanoramiXGCIndex].ptr; + + 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 = panoramiXdataPtr[pGC->pScreen->myNum].x; + int y_off = panoramiXdataPtr[pGC->pScreen->myNum].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) pGCSrc->devPrivates[PanoramiXGCIndex].ptr; + 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) +{ + xfree(data); + return 1; +} + + +static Bool +XineramaFindIDOnAnyScreen(pointer resource, XID id, pointer privdata) +{ + PanoramiXRes *res = (PanoramiXRes*)resource; + int j; + + FOR_NSCREENS(j) + if(res->info[j].id == *((XID*)privdata)) return TRUE; + + return FALSE; +} + +PanoramiXRes * +PanoramiXFindIDOnAnyScreen(RESTYPE type, XID id) +{ + return LookupClientResourceComplex(clients[CLIENT_ID(id)], type, + XineramaFindIDOnAnyScreen, &id); +} + +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; + + if(!screen) + return LookupIDByType(id, type); + + data.screen = screen; + data.id = id; + + return LookupClientResourceComplex(clients[CLIENT_ID(id)], type, + XineramaFindIDByScrnum, &data); +} + +WindowPtr +PanoramiXChangeWindow(int ScrnNum, WindowPtr pWin) +{ + int num = pWin->drawable.pScreen->myNum; + + if(num != ScrnNum) { + PanoramiXRes *win; + + win = PanoramiXFindIDByScrnum(XRT_WINDOW, pWin->drawable.id, num); + + if (win) + pWin = (WindowPtr) LookupIDByType(win->info[ScrnNum].id, RT_WINDOW); + } + + return pWin; +} + +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 = xalloc(sizeof(XineramaConnectionCallbackList)))) + return FALSE; + + newlist->next = ConnectionCallbackList; + newlist->func = func; + ConnectionCallbackList = newlist; + + return TRUE; +} /* * PanoramiXExtensionInit(): @@ -134,14 +457,16 @@ int PanoramiXFreeColors(), PanoramiXStoreColors(); void PanoramiXExtensionInit(int argc, char *argv[]) { - int i, j, PhyScrNum, ArgScrNum; - Bool success = FALSE; - ExtensionEntry *extEntry, *AddExtension(); - PanoramiXData *panoramiXtempPtr; - ScreenPtr pScreen; + int i; + Bool success = FALSE; + ExtensionEntry *extEntry; + ScreenPtr pScreen; + PanoramiXScreenPtr pScreenPriv; + int w, h; - if (!noPanoramiXExtension) - { + if (noPanoramiXExtension) + return; + GlobalScrInfo = &screenInfo; /* For debug visibility */ PanoramiXNumScreens = screenInfo.numScreens; if (PanoramiXNumScreens == 1) { /* Only 1 screen */ @@ -165,13 +490,43 @@ void PanoramiXExtensionInit(int argc, char *argv[]) * run in non-PanoramiXeen mode. */ - panoramiXdataPtr = (PanoramiXData *) Xcalloc(PanoramiXNumScreens * sizeof(PanoramiXData)); - PanoramiXWinRoot = (PanoramiXWindow *) Xcalloc(sizeof(PanoramiXWindow)); - PanoramiXGCRoot = (PanoramiXGC *) Xcalloc(sizeof(PanoramiXGC)); - PanoramiXCmapRoot = (PanoramiXCmap *) Xcalloc(sizeof(PanoramiXCmap)); - PanoramiXPmapRoot = (PanoramiXPmap *) Xcalloc(sizeof(PanoramiXPmap)); - BREAK_IF(!(panoramiXdataPtr && PanoramiXWinRoot && PanoramiXGCRoot && - PanoramiXCmapRoot && PanoramiXPmapRoot)); + panoramiXdataPtr = (PanoramiXData *) + xcalloc(PanoramiXNumScreens, sizeof(PanoramiXData)); + + BREAK_IF(!panoramiXdataPtr); + BREAK_IF((PanoramiXGCIndex = AllocateGCPrivateIndex()) < 0); + BREAK_IF((PanoramiXScreenIndex = AllocateScreenPrivateIndex()) < 0); + + for (i = 0; i < PanoramiXNumScreens; i++) { + pScreen = screenInfo.screens[i]; + if(!AllocateGCPrivate(pScreen, PanoramiXGCIndex, + sizeof(PanoramiXGCRec))) { + noPanoramiXExtension = TRUE; + return; + } + + pScreenPriv = xalloc(sizeof(PanoramiXScreenRec)); + pScreen->devPrivates[PanoramiXScreenIndex].ptr = + (pointer)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) | + XRC_DRAWABLE; + XRT_PIXMAP = CreateNewResourceType(XineramaDeleteResource) | + XRC_DRAWABLE; + XRT_GC = CreateNewResourceType(XineramaDeleteResource); + XRT_COLORMAP = CreateNewResourceType(XineramaDeleteResource); panoramiXGeneration = serverGeneration; success = TRUE; @@ -182,117 +537,40 @@ void PanoramiXExtensionInit(int argc, char *argv[]) ErrorF("%s Extension failed to initialize\n", PANORAMIX_PROTOCOL_NAME); return; } - - /* Set up a default configuration base on horizontal ordering */ - for (i = PanoramiXNumScreens -1; i >= 0 ; i--) { - panoramiXdataPtr[i].above = panoramiXdataPtr[i].below = -1; - panoramiXdataPtr[i].left = panoramiXdataPtr[i].right = -1; - panoramiXEdgePtr[i].no_edges = TRUE; - } - for (i = PanoramiXNumScreens - 1; i >= 0; i--) { - panoramiXdataPtr[i].left = i - 1; - panoramiXdataPtr[i].right = i + 1; - } - panoramiXdataPtr[PanoramiXNumScreens - 1].right = -1; + - /* - * Position the screens relative to each other based on - * command line options. - */ + REGION_INIT(pScreen, &PanoramiXScreenRegion, NullBox, 1); + for (i = 0; i < PanoramiXNumScreens; i++) { + BoxRec TheBox; -#if 0 - for (PhyScrNum = PanoramiXNumScreens - 1; PhyScrNum >= 0; PhyScrNum--) { - if (wsRemapPhysToLogScreens) - i = wsPhysToLogScreens[PhyScrNum]; - else - i = PhyScrNum; - if (i < 0) - continue; - panoramiXdataPtr[i].width = (screenInfo.screens[i])->width; - panoramiXdataPtr[i].height = (screenInfo.screens[i])->height; - if (screenArgs[i].flags & ARG_EDGE_L) { - ArgScrNum = screenArgs[PhyScrNum].edge_left; - if (ArgScrNum < 0) - j = -1; - else { - if (wsRemapPhysToLogScreens) - j = wsPhysToLogScreens[ArgScrNum]; - else - j = ArgScrNum; - } - panoramiXdataPtr[i].left = j; - panoramiXEdgePtr[i].no_edges = FALSE; - if ( j >= 0) - panoramiXdataPtr[j].right = i; - else { - if ( i >= 1 ) - panoramiXdataPtr[i - 1].right = -1; - } - } - if (screenArgs[i].flags & ARG_EDGE_R) { - ArgScrNum = screenArgs[PhyScrNum].edge_right; - if (ArgScrNum < 0) - j = -1; - else { - if (wsRemapPhysToLogScreens) - j = wsPhysToLogScreens[ArgScrNum]; - else - j = ArgScrNum; - } - panoramiXdataPtr[i].right = j; - panoramiXEdgePtr[i].no_edges = FALSE; - if ( j >= 0) - panoramiXdataPtr[j].left = i; - } - if (screenArgs[i].flags & ARG_EDGE_T) { - ArgScrNum = screenArgs[PhyScrNum].edge_top; - if (ArgScrNum < 0) - j = -1; - else { - if (wsRemapPhysToLogScreens) - j = wsPhysToLogScreens[ArgScrNum]; - else - j = ArgScrNum; - } - panoramiXdataPtr[i].above = j; - panoramiXEdgePtr[i].no_edges = FALSE; - if ( j >= 0) - panoramiXdataPtr[j].below = i; - } - if (screenArgs[i].flags & ARG_EDGE_B) { - ArgScrNum = screenArgs[PhyScrNum].edge_bottom; - if (ArgScrNum < 0) - j = -1; - else { - if (wsRemapPhysToLogScreens) - j = wsPhysToLogScreens[ArgScrNum]; - else - j = ArgScrNum; - } - panoramiXdataPtr[i].below = j; - panoramiXEdgePtr[i].no_edges = FALSE; - if ( j >= 0) - panoramiXdataPtr[j].above = i; - } - } -#else - for (PhyScrNum = PanoramiXNumScreens - 1; PhyScrNum >= 0; PhyScrNum--) { - i = PhyScrNum; - if (i < 0) - continue; + panoramiXdataPtr[i].x = dixScreenOrigins[i].x; + panoramiXdataPtr[i].y = dixScreenOrigins[i].y; panoramiXdataPtr[i].width = (screenInfo.screens[i])->width; panoramiXdataPtr[i].height = (screenInfo.screens[i])->height; + + TheBox.x1 = panoramiXdataPtr[i].x; + TheBox.x2 = TheBox.x1 + panoramiXdataPtr[i].width; + TheBox.y1 = panoramiXdataPtr[i].y; + TheBox.y2 = TheBox.y1 + panoramiXdataPtr[i].height; + + REGION_INIT(pScreen, &XineramaScreenRegions[i], &TheBox, 1); + REGION_UNION(pScreen, &PanoramiXScreenRegion, &PanoramiXScreenRegion, + &XineramaScreenRegions[i]); } -#endif - /* - * Find the upper-left screen and then locate all the others - */ - panoramiXtempPtr = panoramiXdataPtr; - for (i = PanoramiXNumScreens; i; i--, panoramiXtempPtr++) - if (panoramiXtempPtr->above == -1 && panoramiXtempPtr->left == -1) - break; - locate_neighbors(PanoramiXNumScreens - i); + + PanoramiXPixWidth = panoramiXdataPtr[0].x + panoramiXdataPtr[0].width; + PanoramiXPixHeight = panoramiXdataPtr[0].y + panoramiXdataPtr[0].height; + + for (i = 1; i < PanoramiXNumScreens; i++) { + w = panoramiXdataPtr[i].x + panoramiXdataPtr[i].width; + h = panoramiXdataPtr[i].y + panoramiXdataPtr[i].height; + + if(PanoramiXPixWidth < w) + PanoramiXPixWidth = w; + if(PanoramiXPixHeight < h) + PanoramiXPixHeight = h; + } /* * Put our processes into the ProcVector @@ -314,9 +592,7 @@ void PanoramiXExtensionInit(int argc, char *argv[]) ProcVector[X_ConfigureWindow] = PanoramiXConfigureWindow; ProcVector[X_CirculateWindow] = PanoramiXCirculateWindow; ProcVector[X_GetGeometry] = PanoramiXGetGeometry; - ProcVector[X_ChangeProperty] = PanoramiXChangeProperty; - ProcVector[X_DeleteProperty] = PanoramiXDeleteProperty; - ProcVector[X_SendEvent] = PanoramiXSendEvent; + ProcVector[X_TranslateCoords] = PanoramiXTranslateCoords; ProcVector[X_CreatePixmap] = PanoramiXCreatePixmap; ProcVector[X_FreePixmap] = PanoramiXFreePixmap; ProcVector[X_CreateGC] = PanoramiXCreateGC; @@ -344,252 +620,262 @@ void PanoramiXExtensionInit(int argc, char *argv[]) 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_StoreColors] = PanoramiXStoreColors; + ProcVector[X_StoreNamedColor] = PanoramiXStoreNamedColor; - } - else - return; +#ifdef RENDER + PanoramiXRenderInit (); +#endif } -extern + +extern Bool CreateConnectionBlock(void); + Bool PanoramiXCreateConnectionBlock(void) { - int i; + int i, j, length; + Bool disableBackingStore = FALSE; + Bool disableSaveUnders = FALSE; int old_width, old_height; - int width_mult, height_mult; + float width_mult, height_mult; xWindowRoot *root; xConnSetup *setup; + xVisualType *visual; + xDepth *depth; + VisualPtr pVisual; + ScreenPtr pScreen; /* * Do normal CreateConnectionBlock but faking it for only one screen */ + if(!PanoramiXNumDepths) { + ErrorF("PanoramiX error: Incompatible screens. 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("PanoramiX error: Incompatible screens. Root window depths differ\n"); + return FALSE; + } + if(pScreen->backingStoreSupport != screenInfo.screens[0]->backingStoreSupport) + disableBackingStore = TRUE; + if(pScreen->saveUnderSupport != screenInfo.screens[0]->saveUnderSupport) + disableSaveUnders = TRUE; + } + + if(disableBackingStore || disableSaveUnders) { + for(i = 0; i < screenInfo.numScreens; i++) { + pScreen = screenInfo.screens[i]; + if(disableBackingStore) + pScreen->backingStoreSupport = NotUseful; + if(disableSaveUnders) + pScreen->saveUnderSupport = NotUseful; + } + } + + i = screenInfo.numScreens; + screenInfo.numScreens = 1; if (!CreateConnectionBlock()) { + screenInfo.numScreens = i; return FALSE; } + screenInfo.numScreens = i; + + setup = (xConnSetup *) ConnectionInfo; + 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 = length >> 2; + + xfree(PanoramiXVisuals); + for (i = 0; i < PanoramiXNumDepths; i++) + xfree(PanoramiXDepths[i].vids); + xfree(PanoramiXDepths); + /* * OK, change some dimensions so it looks as if it were one big screen */ - - setup = (xConnSetup *) ConnectionInfo; - setup->numRoots = 1; - root = (xWindowRoot *) (ConnectionInfo + connBlockScreenStart); old_width = root->pixWidth; old_height = root->pixHeight; - for (i = PanoramiXNumScreens - 1; i >= 0; i--) { - if (panoramiXdataPtr[i].right == -1 ) - root->pixWidth = panoramiXdataPtr[i].x + panoramiXdataPtr[i].width; - if (panoramiXdataPtr[i].below == -1) - root->pixHeight = panoramiXdataPtr[i].y + panoramiXdataPtr[i].height; - } - PanoramiXPixWidth = root->pixWidth; - PanoramiXPixHeight = root->pixHeight; - width_mult = root->pixWidth / old_width; - height_mult = root->pixHeight / old_height; + + 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; - return TRUE; -} -extern -Bool PanoramiXCreateScreenRegion(pWin) -WindowPtr pWin; -{ - ScreenPtr pScreen; - BoxRec box; - int i; - Bool ret; - - pScreen = pWin->drawable.pScreen; - for (i = 0; i < PanoramiXNumScreens; i++) { - box.x1 = 0 - panoramiXdataPtr[i].x; - box.x2 = box.x1 + PanoramiXPixWidth; - box.y1 = 0 - panoramiXdataPtr[i].y; - box.y2 = box.y1 + PanoramiXPixHeight; - REGION_INIT(pScreen, &PanoramiXScreenRegion[i], &box, 1); - ret = REGION_NOTEMPTY(pScreen, &PanoramiXScreenRegion[i]); - if (!ret) - return ret; - } - return ret; -} + while(ConnectionCallbackList) { + pointer tmp; -extern -void PanoramiXDestroyScreenRegion(pWin) -WindowPtr pWin; -{ - ScreenPtr pScreen; - int i; - Bool ret; + tmp = (pointer)ConnectionCallbackList; + (*ConnectionCallbackList->func)(); + ConnectionCallbackList = ConnectionCallbackList->next; + xfree(tmp); + } - pScreen = pWin->drawable.pScreen; - for (i = 0; i < PanoramiXNumScreens; i++) - REGION_DESTROY(pScreen, &PanoramiXScreenRegion[i]); + return TRUE; } -/* - * Assign the Root window and colormap ID's in the PanoramiXScreen Root - * linked lists. Note: WindowTable gets setup in dix_main by - * InitRootWindow, and GlobalScrInfo is screenInfo which gets setup - * by InitOutput. - */ extern void PanoramiXConsolidate(void) { - int i,j,k,v,d,n, thisMaxDepth; - int depthIndex; - DepthPtr pDepth, pLargeDepth; - VisualPtr pVisual; - VisualID it; - register WindowPtr pWin, pLargeWin; - Bool SameDepth; - - PanoramiXLargestScreenDepth.numDepths = (screenInfo.screens[PanoramiXNumScreens -1])->numDepths; - PanoramiXLargestScreenDepth.screenNum = PanoramiXNumScreens - 1; - SameDepth = TRUE; - for (i = 0; i < 2; i++) - { - for (j =0; j < 6; j++) - { - PanoramiXColorDepthTable[i].panoramiXScreenMap[j].numDepths=0; - for (n = 0; n < 6; n++) - { - PanoramiXColorDepthTable[i].panoramiXScreenMap[j].listDepths[n]=0; + int i, j, k; + VisualPtr pVisual, pVisual2; + ScreenPtr pScreen, pScreen2; + PanoramiXRes *root, *defmap; + + if(!PanoramiXVisualTable) + PanoramiXVisualTable = xcalloc(256 * MAXSCREENS, sizeof(XID)); + + pScreen = screenInfo.screens[0]; + pVisual = pScreen->visuals; + + PanoramiXNumDepths = 0; + PanoramiXDepths = xcalloc(pScreen->numDepths,sizeof(DepthRec)); + PanoramiXNumVisuals = 0; + PanoramiXVisuals = xcalloc(pScreen->numVisuals,sizeof(VisualRec)); + + for (i = 0; i < pScreen->numVisuals; i++, pVisual++) { + PanoramiXVisualTable[pVisual->vid * MAXSCREENS] = pVisual->vid; + + /* check if the visual exists on all screens */ + for (j = 1; j < PanoramiXNumScreens; j++) { + pScreen2 = screenInfo.screens[j]; + pVisual2 = pScreen2->visuals; + + for (k = 0; k < pScreen2->numVisuals; k++, pVisual2++) { + if ((pVisual->class == pVisual2->class) && + (pVisual->ColormapEntries == pVisual2->ColormapEntries) && + (pVisual->nplanes == pVisual2->nplanes) && + (pVisual->redMask == pVisual2->redMask) && + (pVisual->greenMask == pVisual2->greenMask) && + (pVisual->blueMask == pVisual2->blueMask) && + (pVisual->offsetRed == pVisual2->offsetRed) && + (pVisual->offsetGreen == pVisual2->offsetGreen) && + (pVisual->offsetBlue == pVisual2->offsetBlue)) + { + Bool AlreadyUsed = FALSE; +#if 0 +/* Open GL should do this reduction, not us */ + for (l = 0; l < 256; l++) { + if (pVisual2->vid == + PanoramiXVisualTable[(l * MAXSCREENS) + j]) + { + AlreadyUsed = TRUE; + break; + } + } +#endif + if (!AlreadyUsed) { + PanoramiXVisualTable[(pVisual->vid * MAXSCREENS) + j] = + pVisual2->vid; + break; + } + } + } } - for (k = 0; k < 33; k++) - { - PanoramiXColorDepthTable[i].panoramiXScreenMap[j].vmap[k].numVids=0; - for (v = 0; v < 10; v++) - { - PanoramiXColorDepthTable[i].panoramiXScreenMap[j].vmap[k].vid[v]=0; + + /* if it doesn't exist on all screens we can't use it */ + for (j = 0; j < PanoramiXNumScreens; j++) { + if (!PanoramiXVisualTable[(pVisual->vid * MAXSCREENS) + j]) { + PanoramiXVisualTable[pVisual->vid * MAXSCREENS] = 0; + break; } } - } - } - for (i = PanoramiXNumScreens - 1; i >= 0; i--) - { - PanoramiXWinRoot->info[i].id = WindowTable[i]->drawable.id; - PanoramiXCmapRoot->info[i].id = (screenInfo.screens[i])->defColormap; - - /* Create a Color-Depth-Table, this will help us deal - with mixing graphics boards and visuals, of course - given that the boards support multi-screen to begin - with. Fill the panoramiXCDT table by screen, then - visual type and allowable depths. - */ - pWin = WindowTable[i]; - if ( (screenInfo.screens[i])->numDepths > - PanoramiXLargestScreenDepth.numDepths ) - { - PanoramiXLargestScreenDepth.numDepths = (screenInfo.screens[i])->numDepths; - PanoramiXLargestScreenDepth.screenNum = i; - SameDepth = FALSE; - } - for (v = 0, pVisual = pWin->drawable.pScreen->visuals; - v < pWin->drawable.pScreen->numVisuals; v++, pVisual++) - { - PanoramiXColorDepthTable[i].panoramiXScreenMap[pVisual->class].numDepths = (screenInfo.screens[i])->numDepths; - for ( j = 0; j < (screenInfo.screens[i])->numDepths; j++) - { - pDepth = (DepthPtr) &pWin->drawable.pScreen->allowedDepths[j]; - PanoramiXColorDepthTable[i].panoramiXScreenMap[pVisual->class].listDepths[j] = pDepth->depth; - for (d = 0; d < pDepth->numVids; d++) - { - if (pVisual->vid == pDepth->vids[d]) - { - PanoramiXColorDepthTable[i]. - panoramiXScreenMap[pVisual->class].vmap[pDepth->depth]. - vid[ - PanoramiXColorDepthTable[i]. - panoramiXScreenMap[pVisual->class]. - vmap[pDepth->depth].numVids++ - ] - = pDepth->vids[d]; - } - } - } - } - PanoramiXColorDepthTable[i].numVisuals = 6; - } /* for each screen */ - /* Fill in ColorDepthTable for mixed visuals with varying depth. - Can't do that until we figure out how to handle mixed visuals - and varying card visual/depth initialization. If we can decide - how to map the relationship, then we can use this table to - shove the information into and use for cross-referencing when - necessary. - - In the meantime, check to see if the screens are the same, - if they don't then disable panoramiX, print out a message, - don't support this mode. - */ -} -/* Since locate_neighbors is recursive, a quick simple example - is in order.This mostly so you can see what the initial values are. - - Given 3 screens: - upperleft screen[0] - panoramiXdataPtr[0].x = 0 - panoramiXdataPtr[0].y = 0 - panoramiXdataPtr[0].width = 640 - panoramiXdataPtr[0].height = 480 - panoramiXdataPtr[0].below = -1 - panoramiXdataPtr[0].right = 1 - panoramiXdataPtr[0].above = -1 - panoramiXdataPtr[0].left = -1 - middle screen[1] - panoramiXdataPtr[1].x = 0 - panoramiXdataPtr[1].y = 0 - panoramiXdataPtr[1].width = 640 - panoramiXdataPtr[1].height = 480 - panoramiXdataPtr[1].below = -1 - panoramiXdataPtr[1].right = 2 - panoramiXdataPtr[1].above = -1 - panoramiXdataPtr[1].left = 0 - last right screen[2] - panoramiXdataPtr[2].x = 0 - panoramiXdataPtr[2].y = 0 - panoramiXdataPtr[2].width = 640 - panoramiXdataPtr[2].height = 480 - panoramiXdataPtr[2].below = -1 - panoramiXdataPtr[2].right = -1 - panoramiXdataPtr[2].above = -1 - panoramiXdataPtr[2].left = 1 - - Calling locate_neighbors(0) results in: - panoramiXdataPtr[0].x = 0 - panoramiXdataPtr[0].y = 0 - panoramiXdataPtr[1].x = 640 - panoramiXdataPtr[1].y = 0 - panoramiXdataPtr[2].x = 1280 - panoramiXdataPtr[2].y = 0 -*/ - -static void locate_neighbors(int i) -{ - int j; - - j = panoramiXdataPtr[i].right; - if ((j != -1) && !panoramiXdataPtr[j].x && !panoramiXdataPtr[j].y) { - panoramiXdataPtr[j].x = panoramiXdataPtr[i].x + panoramiXdataPtr[i].width; - panoramiXdataPtr[j].y = panoramiXdataPtr[i].y; - locate_neighbors(j); - } - j = panoramiXdataPtr[i].below; - if ((j != -1) && !panoramiXdataPtr[j].x && !panoramiXdataPtr[j].y) { - panoramiXdataPtr[j].y = panoramiXdataPtr[i].y + panoramiXdataPtr[i].height; - panoramiXdataPtr[j].x = panoramiXdataPtr[i].x; - locate_neighbors(j); + /* if it does, make sure it's in the list of supported depths and visuals */ + if(PanoramiXVisualTable[pVisual->vid * MAXSCREENS]) { + Bool GotIt = FALSE; + + PanoramiXVisuals[PanoramiXNumVisuals].vid = pVisual->vid; + PanoramiXVisuals[PanoramiXNumVisuals].class = pVisual->class; + PanoramiXVisuals[PanoramiXNumVisuals].bitsPerRGBValue = pVisual->bitsPerRGBValue; + PanoramiXVisuals[PanoramiXNumVisuals].ColormapEntries = pVisual->ColormapEntries; + PanoramiXVisuals[PanoramiXNumVisuals].nplanes = pVisual->nplanes; + PanoramiXVisuals[PanoramiXNumVisuals].redMask = pVisual->redMask; + PanoramiXVisuals[PanoramiXNumVisuals].greenMask = pVisual->greenMask; + PanoramiXVisuals[PanoramiXNumVisuals].blueMask = pVisual->blueMask; + PanoramiXVisuals[PanoramiXNumVisuals].offsetRed = pVisual->offsetRed; + PanoramiXVisuals[PanoramiXNumVisuals].offsetGreen = pVisual->offsetGreen; + PanoramiXVisuals[PanoramiXNumVisuals].offsetBlue = pVisual->offsetBlue; + PanoramiXNumVisuals++; + + for (j = 0; j < PanoramiXNumDepths; j++) { + if (PanoramiXDepths[j].depth == pVisual->nplanes) { + PanoramiXDepths[j].vids[PanoramiXDepths[j].numVids] = pVisual->vid; + PanoramiXDepths[j].numVids++; + GotIt = TRUE; + break; + } + } + + if (!GotIt) { + PanoramiXDepths[PanoramiXNumDepths].depth = pVisual->nplanes; + PanoramiXDepths[PanoramiXNumDepths].numVids = 1; + PanoramiXDepths[PanoramiXNumDepths].vids = xalloc(sizeof(VisualID) * 256); + PanoramiXDepths[PanoramiXNumDepths].vids[0] = pVisual->vid; + PanoramiXNumDepths++; + } + } + } + + + root = (PanoramiXRes *) xalloc(sizeof(PanoramiXRes)); + root->type = XRT_WINDOW; + defmap = (PanoramiXRes *) xalloc(sizeof(PanoramiXRes)); + defmap->type = XRT_COLORMAP; + + for (i = 0; i < PanoramiXNumScreens; i++) { + root->info[i].id = WindowTable[i]->drawable.id; + root->u.win.class = InputOutput; + defmap->info[i].id = (screenInfo.screens[i])->defColormap; } -} + AddResource(root->info[0].id, XRT_WINDOW, root); + AddResource(defmap->info[0].id, XRT_COLORMAP, defmap); +} /* @@ -597,46 +883,25 @@ static void locate_neighbors(int i) * Exit, deallocating as needed. */ -static void PanoramiXResetProc(extEntry) - ExtensionEntry* extEntry; +static void PanoramiXResetProc(ExtensionEntry* extEntry) { int i; - PanoramiXList *pPanoramiXList; - PanoramiXList *tempList; - for (pPanoramiXList = PanoramiXPmapRoot; pPanoramiXList; pPanoramiXList = tempList){ - tempList = pPanoramiXList->next; - Xfree(pPanoramiXList); - } - for (pPanoramiXList = PanoramiXCmapRoot; pPanoramiXList; pPanoramiXList = tempList){ - tempList = pPanoramiXList->next; - Xfree(pPanoramiXList); - } - for (pPanoramiXList = PanoramiXGCRoot; pPanoramiXList; pPanoramiXList = tempList) { - tempList = pPanoramiXList->next; - Xfree(pPanoramiXList); - } - for (pPanoramiXList = PanoramiXWinRoot; pPanoramiXList; pPanoramiXList = tempList) { - tempList = pPanoramiXList->next; - Xfree(pPanoramiXList); - } +#ifdef RENDER + PanoramiXRenderReset (); +#endif screenInfo.numScreens = PanoramiXNumScreens; for (i = 256; i--; ) ProcVector[i] = SavedProcVector[i]; - Xfree(panoramiXdataPtr); - + + Xfree(panoramiXdataPtr); } int -#if NeedFunctionPrototypes ProcPanoramiXQueryVersion (ClientPtr client) -#else -ProcPanoramiXQueryVersion (client) - register ClientPtr client; -#endif { - REQUEST(xPanoramiXQueryVersionReq); + /* REQUEST(xPanoramiXQueryVersionReq); */ xPanoramiXQueryVersionReply rep; register int n; @@ -649,18 +914,15 @@ ProcPanoramiXQueryVersion (client) 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 (client->noClientException); } int -#if NeedFunctionPrototypes ProcPanoramiXGetState(ClientPtr client) -#else -ProcPanoramiXGetState(client) - register ClientPtr client; -#endif { REQUEST(xPanoramiXGetStateReq); WindowPtr pWin; @@ -686,12 +948,7 @@ ProcPanoramiXGetState(client) } int -#if NeedFunctionPrototypes ProcPanoramiXGetScreenCount(ClientPtr client) -#else -ProcPanoramiXGetScreenCount(client) - register ClientPtr client; -#endif { REQUEST(xPanoramiXGetScreenCountReq); WindowPtr pWin; @@ -716,12 +973,7 @@ ProcPanoramiXGetScreenCount(client) } int -#if NeedFunctionPrototypes ProcPanoramiXGetScreenSize(ClientPtr client) -#else -ProcPanoramiXGetScreenSize(client) - register ClientPtr client; -#endif { REQUEST(xPanoramiXGetScreenSizeReq); WindowPtr pWin; @@ -741,29 +993,84 @@ ProcPanoramiXGetScreenSize(client) if (client->swapped) { swaps (&rep.sequenceNumber, n); swapl (&rep.length, n); - swaps (rep.width, n); - swaps (rep.height, n); + swaps (&rep.width, n); + swaps (&rep.height, n); } WriteToClient (client, sizeof (xPanoramiXGetScreenSizeReply), (char *) &rep); return client->noClientException; } -void PrintList(PanoramiXList *head) +int +ProcXineramaIsActive(ClientPtr client) +{ + /* REQUEST(xXineramaIsActiveReq); */ + xXineramaIsActiveReply rep; + + REQUEST_SIZE_MATCH(xXineramaIsActiveReq); + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.state = !noPanoramiXExtension; + if (client->swapped) { + register int n; + swaps (&rep.sequenceNumber, n); + swapl (&rep.length, n); + swapl (&rep.state, n); + } + WriteToClient (client, sizeof (xXineramaIsActiveReply), (char *) &rep); + return client->noClientException; +} + + +int +ProcXineramaQueryScreens(ClientPtr client) { - int i = 0; + /* REQUEST(xXineramaQueryScreensReq); */ + xXineramaQueryScreensReply rep; + + REQUEST_SIZE_MATCH(xXineramaQueryScreensReq); + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.number = (noPanoramiXExtension) ? 0 : PanoramiXNumScreens; + rep.length = rep.number * sz_XineramaScreenInfo >> 2; + if (client->swapped) { + register int n; + swaps (&rep.sequenceNumber, n); + swapl (&rep.length, n); + swapl (&rep.number, n); + } + WriteToClient (client, sizeof (xXineramaQueryScreensReply), (char *) &rep); - for (; head; i++, head = head->next) - fprintf(stderr, "%2d next = 0x%010lx, id[0] = 0x%08x, id[1] = 0x%08x\n", - i, head->next, head->info[0].id, head->info[1].id); + if(!noPanoramiXExtension) { + xXineramaScreenInfo scratch; + int i; + + for(i = 0; i < PanoramiXNumScreens; i++) { + scratch.x_org = panoramiXdataPtr[i].x; + scratch.y_org = panoramiXdataPtr[i].y; + scratch.width = panoramiXdataPtr[i].width; + scratch.height = panoramiXdataPtr[i].height; + + if(client->swapped) { + register 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 client->noClientException; } + + static int -#if NeedFunctionPrototypes ProcPanoramiXDispatch (ClientPtr client) -#else -ProcPanoramiXDispatch (client) - ClientPtr client; -#endif { REQUEST(xReq); switch (stuff->data) { @@ -775,6 +1082,184 @@ ProcPanoramiXDispatch (client) 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, 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 + panoramiXdataPtr[0].x; + SrcBox.y1 += pDraw->y + panoramiXdataPtr[0].y; + } + SrcBox.x2 = SrcBox.x1 + width; + SrcBox.y2 = SrcBox.y1 + height; + + REGION_INIT(pScreen, &SrcRegion, &SrcBox, 1); + REGION_INIT(pScreen, &GrabRegion, NullBox, 1); + + depth = (format == XYPixmap) ? 1 : pDraw->depth; + + for(i = 0; i < PanoramiXNumScreens; i++) { + pDraw = pDrawables[i]; + + inOut = RECT_IN_REGION(pScreen,&XineramaScreenRegions[i],&SrcBox); + + if(inOut == rgnIN) { + (*pDraw->pScreen->GetImage)(pDraw, + SrcBox.x1 - pDraw->x - panoramiXdataPtr[i].x, + SrcBox.y1 - pDraw->y - panoramiXdataPtr[i].y, + width, height, format, planemask, data); + break; + } else if (inOut == rgnOUT) + continue; + + REGION_INTERSECT(pScreen, &GrabRegion, &SrcRegion, + &XineramaScreenRegions[i]); + + nbox = REGION_NUM_RECTS(&GrabRegion); + + if(nbox) { + pbox = REGION_RECTS(&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 = xrealloc(ScratchMem, sizeNeeded); + if(ScratchMem) + size = sizeNeeded; + else { + ScratchMem = tmpdata; + break; + } + } + + x = pbox->x1 - pDraw->x - panoramiXdataPtr[i].x; + y = pbox->y1 - pDraw->y - panoramiXdataPtr[i].y; + + (*pDraw->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++; + } + + REGION_SUBTRACT(pScreen, &SrcRegion, &SrcRegion, &GrabRegion); + if(!REGION_NOTEMPTY(pScreen, &SrcRegion)) + break; + } + + } + + if(ScratchMem) + xfree(ScratchMem); + + REGION_UNINIT(pScreen, &SrcRegion); + REGION_UNINIT(pScreen, &GrabRegion); +} |