/****************************************************************************** * * Copyright (c) 1994, 1995 Hewlett-Packard Company * * 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, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * 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 HEWLETT-PACKARD COMPANY BE LIABLE FOR ANY CLAIM, * 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 the Hewlett-Packard * Company shall not be used in advertising or otherwise to promote the * sale, use or other dealings in this Software without prior written * authorization from the Hewlett-Packard Company. * * DIX DBE code * *****************************************************************************/ /* INCLUDES */ #define NEED_EVENTS #ifdef HAVE_DIX_CONFIG_H #include #endif #include #if HAVE_STDINT_H #include #elif !defined(UINT32_MAX) #define UINT32_MAX 0xffffffffU #endif #include #include #include "scrnintstr.h" #include "extnsionst.h" #include "gcstruct.h" #include "dixstruct.h" #define NEED_DBE_PROTOCOL #include "dbestruct.h" #include "midbe.h" /* GLOBALS */ /* Per-screen initialization functions [init'ed by DbeRegisterFunction()] */ static Bool (* DbeInitFunct[MAXSCREENS])(); /* pScreen, pDbeScreenPriv */ /* These are static globals copied to DBE's screen private for use by DDX */ static int dbeScreenPrivIndex; static int dbeWindowPrivIndex; /* These are static globals copied to DBE's screen private for use by DDX */ static RESTYPE dbeDrawableResType; static RESTYPE dbeWindowPrivResType; /* This global is used by DbeAllocWinPrivPrivIndex() */ static int winPrivPrivCount = 0; /* Used to generate DBE's BadBuffer error. */ static int dbeErrorBase; /* Used by DbeRegisterFunction() to initialize the initialization function * table only once per server lifetime. */ static Bool firstRegistrationPass = TRUE; /****************************************************************************** * * DBE DIX Procedure: DbeRegisterFunction * * Description: * * This function registers the DBE init function for the specified screen. * *****************************************************************************/ void DbeRegisterFunction(ScreenPtr pScreen, Bool (*funct) (/* ??? */)) { int i; /* Initialize the initialization function table if it has not been * initialized already. */ if (firstRegistrationPass) { for (i = 0; i < MAXSCREENS; i++) { DbeInitFunct[i] = NULL; } firstRegistrationPass = FALSE; } DbeInitFunct[pScreen->myNum] = funct; } /* DbeRegisterFunction() */ /****************************************************************************** * * DBE DIX Procedure: DbeAllocWinPriv * * Description: * * This function was cloned from AllocateWindow() in window.c. * This function allocates a window priv structure to be associated * with a double-buffered window. * *****************************************************************************/ static DbeWindowPrivPtr DbeAllocWinPriv(ScreenPtr pScreen) { DbeWindowPrivPtr pDbeWindowPriv; DbeScreenPrivPtr pDbeScreenPriv; register char *ptr; register DevUnion *ppriv; register unsigned int *sizes; register unsigned int size; register int i; pDbeScreenPriv = DBE_SCREEN_PRIV(pScreen); pDbeWindowPriv = (DbeWindowPrivPtr)xalloc(pDbeScreenPriv->totalWinPrivSize); if (pDbeWindowPriv) { ppriv = (DevUnion *)(pDbeWindowPriv + 1); pDbeWindowPriv->devPrivates = ppriv; sizes = pDbeScreenPriv->winPrivPrivSizes; ptr = (char *)(ppriv + pDbeScreenPriv->winPrivPrivLen); for (i = pDbeScreenPriv->winPrivPrivLen; --i >= 0; ppriv++, sizes++) { if ((size = *sizes)) { ppriv->ptr = (pointer)ptr; ptr += size; } else ppriv->ptr = (pointer)NULL; } } return(pDbeWindowPriv); } /* DbeAllocWinPriv() */ /****************************************************************************** * * DBE DIX Procedure: DbeFallbackAllocWinPriv * * Description: * * This is a fallback function for AllocWinPriv(). * *****************************************************************************/ #if 0 /* NOT USED */ static DbeWindowPrivPtr DbeFallbackAllocWinPriv(pScreen) ScreenPtr pScreen; { return (NULL); } /* DbeFallbackAllocWinPriv() */ #endif /****************************************************************************** * * DBE DIX Procedure: DbeAllocWinPrivPrivIndex * * Description: * * This function was cloned from AllocateWindowPrivateIndex() in window.c. * This function allocates a new window priv priv index by simply returning * an incremented private counter. * *****************************************************************************/ static int DbeAllocWinPrivPrivIndex(void) { return winPrivPrivCount++; } /* DbeAllocWinPrivPrivIndex() */ /****************************************************************************** * * DBE DIX Procedure: DbeAllocWinPrivPriv * * Description: * * This function was cloned from AllocateWindowPrivate() in privates.c. * This function allocates a private structure to be hung off * a window private. * *****************************************************************************/ static Bool DbeAllocWinPrivPriv(register ScreenPtr pScreen, int index, unsigned int amount) { DbeScreenPrivPtr pDbeScreenPriv; unsigned int oldamount; pDbeScreenPriv = DBE_SCREEN_PRIV(pScreen); if (index >= pDbeScreenPriv->winPrivPrivLen) { unsigned *nsizes; nsizes = (unsigned *)xrealloc(pDbeScreenPriv->winPrivPrivSizes, (index + 1) * sizeof(unsigned)); if (!nsizes) { return(FALSE); } while (pDbeScreenPriv->winPrivPrivLen <= index) { nsizes[pDbeScreenPriv->winPrivPrivLen++] = 0; pDbeScreenPriv->totalWinPrivSize += sizeof(DevUnion); } pDbeScreenPriv->winPrivPrivSizes = nsizes; } oldamount = pDbeScreenPriv->winPrivPrivSizes[index]; if (amount > oldamount) { pDbeScreenPriv->winPrivPrivSizes[index] = amount; pDbeScreenPriv->totalWinPrivSize += (amount - oldamount); } return(TRUE); } /* DbeAllocWinPrivPriv() */ /****************************************************************************** * * DBE DIX Procedure: DbeStubScreen * * Description: * * This is function stubs the function pointers in the given DBE screen * private and increments the number of stubbed screens. * *****************************************************************************/ static void DbeStubScreen(DbeScreenPrivPtr pDbeScreenPriv, int *nStubbedScreens) { /* Stub DIX. */ pDbeScreenPriv->SetupBackgroundPainter = NULL; pDbeScreenPriv->AllocWinPriv = NULL; pDbeScreenPriv->AllocWinPrivPrivIndex = NULL; pDbeScreenPriv->AllocWinPrivPriv = NULL; /* Do not unwrap PositionWindow nor DestroyWindow. If the DDX * initialization function failed, we assume that it did not wrap * PositionWindow. Also, DestroyWindow is only wrapped if the DDX * initialization function succeeded. */ /* Stub DDX. */ pDbeScreenPriv->GetVisualInfo = NULL; pDbeScreenPriv->AllocBackBufferName = NULL; pDbeScreenPriv->SwapBuffers = NULL; pDbeScreenPriv->BeginIdiom = NULL; pDbeScreenPriv->EndIdiom = NULL; pDbeScreenPriv->WinPrivDelete = NULL; pDbeScreenPriv->ResetProc = NULL; (*nStubbedScreens)++; } /* DbeStubScreen() */ /****************************************************************************** * * DBE DIX Procedure: ProcDbeGetVersion * * Description: * * This function is for processing a DbeGetVersion request. * This request returns the major and minor version numbers of this * extension. * * Return Values: * * Success * *****************************************************************************/ static int ProcDbeGetVersion(ClientPtr client) { /* REQUEST(xDbeGetVersionReq); */ xDbeGetVersionReply rep; register int n; REQUEST_SIZE_MATCH(xDbeGetVersionReq); rep.type = X_Reply; rep.length = 0; rep.sequenceNumber = client->sequence; rep.majorVersion = DBE_MAJOR_VERSION; rep.minorVersion = DBE_MINOR_VERSION; if (client->swapped) { swaps(&rep.sequenceNumber, n); } WriteToClient(client, sizeof(xDbeGetVersionReply), (char *)&rep); return(client->noClientException); } /* ProcDbeGetVersion() */ /****************************************************************************** * * DBE DIX Procedure: ProcDbeAllocateBackBufferName * * Description: * * This function is for processing a DbeAllocateBackBufferName request. * This request allocates a drawable ID used to refer to the back buffer * of a window. * * Return Values: * * BadAlloc - server can not allocate resources * BadIDChoice - id is out of range for client; id is already in use * BadMatch - window is not an InputOutput window; * visual of window is not on list returned by * DBEGetVisualInfo; * BadValue - invalid swap action is specified * BadWindow - window is not a valid window * Success * *****************************************************************************/ static int ProcDbeAllocateBackBufferName(ClientPtr client) { REQUEST(xDbeAllocateBackBufferNameReq); WindowPtr pWin; DbeScreenPrivPtr pDbeScreenPriv; DbeWindowPrivPtr pDbeWindowPriv; XdbeScreenVisualInfo scrVisInfo; register int i; Bool visualMatched = FALSE; xDbeSwapAction swapAction; VisualID visual; int status; int add_index; REQUEST_SIZE_MATCH(xDbeAllocateBackBufferNameReq); /* The window must be valid. */ status = dixLookupWindow(&pWin, stuff->window, client, DixWriteAccess); if (status != Success) return status; /* The window must be InputOutput. */ if (pWin->drawable.class != InputOutput) { return(BadMatch); } /* The swap action must be valid. */ swapAction = stuff->swapAction; /* use local var for performance. */ if ((swapAction != XdbeUndefined ) && (swapAction != XdbeBackground) && (swapAction != XdbeUntouched ) && (swapAction != XdbeCopied )) { return(BadValue); } /* The id must be in range and not already in use. */ LEGAL_NEW_RESOURCE(stuff->buffer, client); /* The visual of the window must be in the list returned by * GetVisualInfo. */ pDbeScreenPriv = DBE_SCREEN_PRIV_FROM_WINDOW(pWin); if (!pDbeScreenPriv->GetVisualInfo) return(BadMatch); /* screen doesn't support double buffering */ if (!(*pDbeScreenPriv->GetVisualInfo)(pWin->drawable.pScreen, &scrVisInfo)) { /* GetVisualInfo() failed to allocate visual info data. */ return(BadAlloc); } /* See if the window's visual is on the list. */ visual = wVisual(pWin); for (i = 0; (i < scrVisInfo.count) && !visualMatched; i++) { if (scrVisInfo.visinfo[i].visual == visual) { visualMatched = TRUE; } } /* Free what was allocated by the GetVisualInfo() call above. */ xfree(scrVisInfo.visinfo); if (!visualMatched) { return(BadMatch); } if ((pDbeWindowPriv = DBE_WINDOW_PRIV(pWin)) == NULL) { /* There is no buffer associated with the window. * Allocate a window priv. */ if (!(pDbeWindowPriv = (*pDbeScreenPriv->AllocWinPriv)(pWin->drawable.pScreen))) { return(BadAlloc); } /* Fill out window priv information. */ pDbeWindowPriv->pWindow = pWin; pDbeWindowPriv->width = pWin->drawable.width; pDbeWindowPriv->height = pWin->drawable.height; pDbeWindowPriv->x = pWin->drawable.x; pDbeWindowPriv->y = pWin->drawable.y; pDbeWindowPriv->nBufferIDs = 0; /* Set the buffer ID array pointer to the initial (static) array). */ pDbeWindowPriv->IDs = pDbeWindowPriv->initIDs; /* Initialize the buffer ID list. */ pDbeWindowPriv->maxAvailableIDs = DBE_INIT_MAX_IDS; add_index = 0; for (i = 1; i < DBE_INIT_MAX_IDS; i++) { pDbeWindowPriv->IDs[i] = DBE_FREE_ID_ELEMENT; } /* Actually connect the window priv to the window. */ pWin->devPrivates[dbeWindowPrivIndex].ptr = (pointer)pDbeWindowPriv; } /* if -- There is no buffer associated with the window. */ else { /* A buffer is already associated with the window. * Add the new buffer ID to the array, reallocating the array memory * if necessary. */ /* Determine if there is a free element in the ID array. */ for (i = 0; i < pDbeWindowPriv->maxAvailableIDs; i++) { if (pDbeWindowPriv->IDs[i] == DBE_FREE_ID_ELEMENT) { /* There is still room in the ID array. */ break; } } if (i == pDbeWindowPriv->maxAvailableIDs) { /* No more room in the ID array -- reallocate another array. */ XID *pIDs; /* Setup an array pointer for the realloc operation below. */ if (pDbeWindowPriv->maxAvailableIDs == DBE_INIT_MAX_IDS) { /* We will malloc a new array. */ pIDs = NULL; } else { /* We will realloc a new array. */ pIDs = pDbeWindowPriv->IDs; } /* malloc/realloc a new array and initialize all elements to 0. */ pDbeWindowPriv->IDs = (XID *)xrealloc(pIDs, (pDbeWindowPriv->maxAvailableIDs+DBE_INCR_MAX_IDS)*sizeof(XID)); if (!pDbeWindowPriv->IDs) { return(BadAlloc); } memset(&pDbeWindowPriv->IDs[pDbeWindowPriv->nBufferIDs], 0, (pDbeWindowPriv->maxAvailableIDs + DBE_INCR_MAX_IDS - pDbeWindowPriv->nBufferIDs) * sizeof(XID)); if (pDbeWindowPriv->maxAvailableIDs == DBE_INIT_MAX_IDS) { /* We just went from using the initial (static) array to a * newly allocated array. Copy the IDs from the initial array * to the new array. */ memcpy(pDbeWindowPriv->IDs, pDbeWindowPriv->initIDs, DBE_INIT_MAX_IDS * sizeof(XID)); } pDbeWindowPriv->maxAvailableIDs += DBE_INCR_MAX_IDS; } add_index = i; } /* else -- A buffer is already associated with the window. */ /* Call the DDX routine to allocate the back buffer. */ status = (*pDbeScreenPriv->AllocBackBufferName)(pWin, stuff->buffer, stuff->swapAction); if (status == Success) { pDbeWindowPriv->IDs[add_index] = stuff->buffer; if (!AddResource(stuff->buffer, dbeWindowPrivResType, (pointer)pDbeWindowPriv)) { pDbeWindowPriv->IDs[add_index] = DBE_FREE_ID_ELEMENT; if (pDbeWindowPriv->nBufferIDs == 0) { status = BadAlloc; goto out_free; } } } else { /* The DDX buffer allocation routine failed for the first buffer of * this window. */ if (pDbeWindowPriv->nBufferIDs == 0) { goto out_free; } } /* Increment the number of buffers (XIDs) associated with this window. */ pDbeWindowPriv->nBufferIDs++; /* Set swap action on all calls. */ pDbeWindowPriv->swapAction = stuff->swapAction; return(status); out_free: pWin->devPrivates[dbeWindowPrivIndex].ptr = NULL; xfree(pDbeWindowPriv); return(status); } /* ProcDbeAllocateBackBufferName() */ /****************************************************************************** * * DBE DIX Procedure: ProcDbeDeallocateBackBufferName * * Description: * * This function is for processing a DbeDeallocateBackBufferName request. * This request frees a drawable ID that was obtained by a * DbeAllocateBackBufferName request. * * Return Values: * * BadBuffer - buffer to deallocate is not associated with a window * Success * *****************************************************************************/ static int ProcDbeDeallocateBackBufferName(ClientPtr client) { REQUEST(xDbeDeallocateBackBufferNameReq); DbeWindowPrivPtr pDbeWindowPriv; int i; REQUEST_SIZE_MATCH(xDbeDeallocateBackBufferNameReq); /* Buffer name must be valid */ if (!(pDbeWindowPriv = (DbeWindowPrivPtr)SecurityLookupIDByType(client, stuff->buffer, dbeWindowPrivResType, DixDestroyAccess)) || !(SecurityLookupIDByType(client, stuff->buffer, dbeDrawableResType, DixDestroyAccess))) { client->errorValue = stuff->buffer; return(dbeErrorBase + DbeBadBuffer); } /* Make sure that the id is valid for the window. * This is paranoid code since we already looked up the ID by type * above. */ for (i = 0; i < pDbeWindowPriv->nBufferIDs; i++) { /* Loop through the ID list to find the ID. */ if (pDbeWindowPriv->IDs[i] == stuff->buffer) { break; } } if (i == pDbeWindowPriv->nBufferIDs) { /* We did not find the ID in the ID list. */ client->errorValue = stuff->buffer; return(dbeErrorBase + DbeBadBuffer); } FreeResource(stuff->buffer, RT_NONE); return(Success); } /* ProcDbeDeallocateBackBufferName() */ /****************************************************************************** * * DBE DIX Procedure: ProcDbeSwapBuffers * * Description: * * This function is for processing a DbeSwapBuffers request. * This request swaps the buffers for all windows listed, applying the * appropriate swap action for each window. * * Return Values: * * BadAlloc - local allocation failed; this return value is not defined * by the protocol * BadMatch - a window in request is not double-buffered; a window in * request is listed more than once * BadValue - invalid swap action is specified; no swap action is * specified * BadWindow - a window in request is not valid * Success * *****************************************************************************/ static int ProcDbeSwapBuffers(ClientPtr client) { REQUEST(xDbeSwapBuffersReq); WindowPtr pWin; DbeScreenPrivPtr pDbeScreenPriv; DbeSwapInfoPtr swapInfo; xDbeSwapInfo *dbeSwapInfo; int error; register int i, j; int nStuff; REQUEST_AT_LEAST_SIZE(xDbeSwapBuffersReq); nStuff = stuff->n; /* use local variable for performance. */ if (nStuff == 0) { return(Success); } if (nStuff > UINT32_MAX / sizeof(DbeSwapInfoRec)) return BadAlloc; /* Get to the swap info appended to the end of the request. */ dbeSwapInfo = (xDbeSwapInfo *)&stuff[1]; /* Allocate array to record swap information. */ swapInfo = (DbeSwapInfoPtr)Xalloc(nStuff * sizeof(DbeSwapInfoRec)); if (swapInfo == NULL) { return(BadAlloc); } for (i = 0; i < nStuff; i++) { /* Check all windows to swap. */ /* Each window must be a valid window - BadWindow. */ error = dixLookupWindow(&pWin, dbeSwapInfo[i].window, client, DixWriteAccess); if (error != Success) { Xfree(swapInfo); return error; } /* Each window must be double-buffered - BadMatch. */ if (DBE_WINDOW_PRIV(pWin) == NULL) { Xfree(swapInfo); return(BadMatch); } /* Each window must only be specified once - BadMatch. */ for (j = i + 1; j < nStuff; j++) { if (dbeSwapInfo[i].window == dbeSwapInfo[j].window) { Xfree(swapInfo); return(BadMatch); } } /* Each swap action must be valid - BadValue. */ if ((dbeSwapInfo[i].swapAction != XdbeUndefined ) && (dbeSwapInfo[i].swapAction != XdbeBackground) && (dbeSwapInfo[i].swapAction != XdbeUntouched ) && (dbeSwapInfo[i].swapAction != XdbeCopied )) { Xfree(swapInfo); return(BadValue); } /* Everything checks out OK. Fill in the swap info array. */ swapInfo[i].pWindow = pWin; swapInfo[i].swapAction = dbeSwapInfo[i].swapAction; } /* for (i = 0; i < nStuff; i++) */ /* Call the DDX routine to perform the swap(s). The DDX routine should * scan the swap list (swap info), swap any buffers that it knows how to * handle, delete them from the list, and update nStuff to indicate how * many windows it did not handle. * * This scheme allows a range of sophistication in the DDX SwapBuffers() * implementation. Naive implementations could just swap the first buffer * in the list, move the last buffer to the front, decrement nStuff, and * return. The next level of sophistication could be to scan the whole * list for windows on the same screen. Up another level, the DDX routine * could deal with cross-screen synchronization. */ while (nStuff > 0) { pDbeScreenPriv = DBE_SCREEN_PRIV_FROM_WINDOW(swapInfo[0].pWindow); error = (*pDbeScreenPriv->SwapBuffers)(client, &nStuff, swapInfo); if (error != Success) { Xfree(swapInfo); return(error); } } Xfree(swapInfo); return(Success); } /* ProcDbeSwapBuffers() */ /****************************************************************************** * * DBE DIX Procedure: ProcDbeBeginIdiom * * Description: * * This function is for processing a DbeBeginIdiom request. * This request informs the server that a complex swap will immediately * follow this request. * * Return Values: * * Success * *****************************************************************************/ static int ProcDbeBeginIdiom(ClientPtr client) { /* REQUEST(xDbeBeginIdiomReq); */ DbeScreenPrivPtr pDbeScreenPriv; register int i; REQUEST_SIZE_MATCH(xDbeBeginIdiomReq); for (i = 0; i < screenInfo.numScreens; i++) { pDbeScreenPriv = DBE_SCREEN_PRIV(screenInfo.screens[i]); /* Call the DDX begin idiom procedure if there is one. */ if (pDbeScreenPriv->BeginIdiom) { (*pDbeScreenPriv->BeginIdiom)(client); } } return(Success); } /* ProcDbeBeginIdiom() */ /****************************************************************************** * * DBE DIX Procedure: ProcDbeGetVisualInfo * * Description: * * This function is for processing a ProcDbeGetVisualInfo request. * This request returns information about which visuals support * double buffering. * * Return Values: * * BadDrawable - value in screen specifiers is not a valid drawable * Success * *****************************************************************************/ static int ProcDbeGetVisualInfo(ClientPtr client) { REQUEST(xDbeGetVisualInfoReq); DbeScreenPrivPtr pDbeScreenPriv; xDbeGetVisualInfoReply rep; Drawable *drawables; DrawablePtr *pDrawables = NULL; register int i, j, n, rc; register int count; /* number of visual infos in reply */ register int length; /* length of reply */ ScreenPtr pScreen; XdbeScreenVisualInfo *pScrVisInfo; REQUEST_AT_LEAST_SIZE(xDbeGetVisualInfoReq); if (stuff->n > UINT32_MAX / sizeof(DrawablePtr)) return BadAlloc; /* Make sure any specified drawables are valid. */ if (stuff->n != 0) { if (!(pDrawables = (DrawablePtr *)Xalloc(stuff->n * sizeof(DrawablePtr)))) { return(BadAlloc); } drawables = (Drawable *)&stuff[1]; for (i = 0; i < stuff->n; i++) { rc = dixLookupDrawable(pDrawables+i, drawables[i], client, 0, DixReadAccess); if (rc != Success) { Xfree(pDrawables); return rc; } } } count = (stuff->n == 0) ? screenInfo.numScreens : stuff->n; if (!(pScrVisInfo = (XdbeScreenVisualInfo *)xalloc(count * sizeof(XdbeScreenVisualInfo)))) { if (pDrawables) { Xfree(pDrawables); } return(BadAlloc); } length = 0; for (i = 0; i < count; i++) { pScreen = (stuff->n == 0) ? screenInfo.screens[i] : pDrawables[i]->pScreen; pDbeScreenPriv = DBE_SCREEN_PRIV(pScreen); if (!(*pDbeScreenPriv->GetVisualInfo)(pScreen, &pScrVisInfo[i])) { /* We failed to alloc pScrVisInfo[i].visinfo. */ /* Free visinfos that we allocated for previous screen infos.*/ for (j = 0; j < i; j++) { xfree(pScrVisInfo[j].visinfo); } /* Free pDrawables if we needed to allocate it above. */ if (pDrawables) { Xfree(pDrawables); } return(BadAlloc); } /* Account for n, number of xDbeVisInfo items in list. */ length += sizeof(CARD32); /* Account for n xDbeVisInfo items */ length += pScrVisInfo[i].count * sizeof(xDbeVisInfo); } rep.type = X_Reply; rep.sequenceNumber = client->sequence; rep.length = length >> 2; rep.m = count; if (client->swapped) { swaps(&rep.sequenceNumber, n); swapl(&rep.length, n); swapl(&rep.m, n); } /* Send off reply. */ WriteToClient(client, sizeof(xDbeGetVisualInfoReply), (char *)&rep); for (i = 0; i < count; i++) { CARD32 data32; /* For each screen in the reply, send off the visual info */ /* Send off number of visuals. */ data32 = (CARD32)pScrVisInfo[i].count; if (client->swapped) { swapl(&data32, n); } WriteToClient(client, sizeof(CARD32), (char *)&data32); /* Now send off visual info items. */ for (j = 0; j < pScrVisInfo[i].count; j++) { xDbeVisInfo visInfo; /* Copy the data in the client data structure to a protocol * data structure. We will send data to the client from the * protocol data structure. */ visInfo.visualID = (CARD32)pScrVisInfo[i].visinfo[j].visual; visInfo.depth = (CARD8) pScrVisInfo[i].visinfo[j].depth; visInfo.perfLevel = (CARD8) pScrVisInfo[i].visinfo[j].perflevel; if (client->swapped) { swapl(&visInfo.visualID, n); /* We do not need to swap depth and perfLevel since they are * already 1 byte quantities. */ } /* Write visualID(32), depth(8), perfLevel(8), and pad(16). */ WriteToClient(client, 2*sizeof(CARD32), (char *)&visInfo.visualID); } } /* Clean up memory. */ for (i = 0; i < count; i++) { xfree(pScrVisInfo[i].visinfo); } xfree(pScrVisInfo); if (pDrawables) { Xfree(pDrawables); } return(client->noClientException); } /* ProcDbeGetVisualInfo() */ /****************************************************************************** * * DBE DIX Procedure: ProcDbeGetbackBufferAttributes * * Description: * * This function is for processing a ProcDbeGetbackBufferAttributes * request. This request returns information about a back buffer. * * Return Values: * * Success * *****************************************************************************/ static int ProcDbeGetBackBufferAttributes(ClientPtr client) { REQUEST(xDbeGetBackBufferAttributesReq); xDbeGetBackBufferAttributesReply rep; DbeWindowPrivPtr pDbeWindowPriv; int n; REQUEST_SIZE_MATCH(xDbeGetBackBufferAttributesReq); if (!(pDbeWindowPriv = (DbeWindowPrivPtr)SecurityLookupIDByType(client, stuff->buffer, dbeWindowPrivResType, DixReadAccess))) { rep.attributes = None; } else { rep.attributes = pDbeWindowPriv->pWindow->drawable.id; } rep.type = X_Reply; rep.sequenceNumber = client->sequence; rep.length = 0; if (client->swapped) { swaps(&rep.sequenceNumber, n); swapl(&rep.length, n); swapl(&rep.attributes, n); } WriteToClient(client, sizeof(xDbeGetBackBufferAttributesReply), (char *)&rep); return(client->noClientException); } /* ProcDbeGetbackBufferAttributes() */ /****************************************************************************** * * DBE DIX Procedure: ProcDbeDispatch * * Description: * * This function dispatches DBE requests. * *****************************************************************************/ static int ProcDbeDispatch(ClientPtr client) { REQUEST(xReq); switch (stuff->data) { case X_DbeGetVersion: return(ProcDbeGetVersion(client)); case X_DbeAllocateBackBufferName: return(ProcDbeAllocateBackBufferName(client)); case X_DbeDeallocateBackBufferName: return(ProcDbeDeallocateBackBufferName(client)); case X_DbeSwapBuffers: return(ProcDbeSwapBuffers(client)); case X_DbeBeginIdiom: return(ProcDbeBeginIdiom(client)); case X_DbeEndIdiom: return(Success); case X_DbeGetVisualInfo: return(ProcDbeGetVisualInfo(client)); case X_DbeGetBackBufferAttributes: return(ProcDbeGetBackBufferAttributes(client)); default: return(BadRequest); } } /* ProcDbeDispatch() */ /****************************************************************************** * * DBE DIX Procedure: SProcDbeGetVersion * * Description: * * This function is for processing a DbeGetVersion request on a swapped * server. This request returns the major and minor version numbers of * this extension. * * Return Values: * * Success * *****************************************************************************/ static int SProcDbeGetVersion(ClientPtr client) { REQUEST(xDbeGetVersionReq); register int n; swaps(&stuff->length, n); return(ProcDbeGetVersion(client)); } /* SProcDbeGetVersion() */ /****************************************************************************** * * DBE DIX Procedure: SProcDbeAllocateBackBufferName * * Description: * * This function is for processing a DbeAllocateBackBufferName request on * a swapped server. This request allocates a drawable ID used to refer * to the back buffer of a window. * * Return Values: * * BadAlloc - server can not allocate resources * BadIDChoice - id is out of range for client; id is already in use * BadMatch - window is not an InputOutput window; * visual of window is not on list returned by * DBEGetVisualInfo; * BadValue - invalid swap action is specified * BadWindow - window is not a valid window * Success * *****************************************************************************/ static int SProcDbeAllocateBackBufferName(ClientPtr client) { REQUEST(xDbeAllocateBackBufferNameReq); register int n; swaps(&stuff->length, n); REQUEST_SIZE_MATCH(xDbeAllocateBackBufferNameReq); swapl(&stuff->window, n); swapl(&stuff->buffer, n); /* stuff->swapAction is a byte. We do not need to swap this field. */ return(ProcDbeAllocateBackBufferName(client)); } /* SProcDbeAllocateBackBufferName() */ /****************************************************************************** * * DBE DIX Procedure: SProcDbeDeallocateBackBufferName * * Description: * * This function is for processing a DbeDeallocateBackBufferName request * on a swapped server. This request frees a drawable ID that was * obtained by a DbeAllocateBackBufferName request. * * Return Values: * * BadBuffer - buffer to deallocate is not associated with a window * Success * *****************************************************************************/ static int SProcDbeDeallocateBackBufferName(ClientPtr client) { REQUEST (xDbeDeallocateBackBufferNameReq); register int n; swaps(&stuff->length, n); REQUEST_SIZE_MATCH(xDbeDeallocateBackBufferNameReq); swapl(&stuff->buffer, n); return(ProcDbeDeallocateBackBufferName(client)); } /* SProcDbeDeallocateBackBufferName() */ /****************************************************************************** * * DBE DIX Procedure: SProcDbeSwapBuffers * * Description: * * This function is for processing a DbeSwapBuffers request on a swapped * server. This request swaps the buffers for all windows listed, * applying the appropriate swap action for each window. * * Return Values: * * BadMatch - a window in request is not double-buffered; a window in * request is listed more than once; all windows in request do * not have the same root * BadValue - invalid swap action is specified * BadWindow - a window in request is not valid * Success * *****************************************************************************/ static int SProcDbeSwapBuffers(ClientPtr client) { REQUEST(xDbeSwapBuffersReq); register int i, n; xDbeSwapInfo *pSwapInfo; swaps(&stuff->length, n); REQUEST_AT_LEAST_SIZE(xDbeSwapBuffersReq); swapl(&stuff->n, n); if (stuff->n != 0) { pSwapInfo = (xDbeSwapInfo *)stuff+1; /* The swap info following the fix part of this request is a window(32) * followed by a 1 byte swap action and then 3 pad bytes. We only need * to swap the window information. */ for (i = 0; i < stuff->n; i++) { swapl(&pSwapInfo->window, n); } } return(ProcDbeSwapBuffers(client)); } /* SProcDbeSwapBuffers() */ /****************************************************************************** * * DBE DIX Procedure: SProcDbeBeginIdiom * * Description: * * This function is for processing a DbeBeginIdiom request on a swapped * server. This request informs the server that a complex swap will * immediately follow this request. * * Return Values: * * Success * *****************************************************************************/ static int SProcDbeBeginIdiom(ClientPtr client) { REQUEST(xDbeBeginIdiomReq); register int n; swaps(&stuff->length, n); return(ProcDbeBeginIdiom(client)); } /* SProcDbeBeginIdiom() */ /****************************************************************************** * * DBE DIX Procedure: SProcDbeGetVisualInfo * * Description: * * This function is for processing a ProcDbeGetVisualInfo request on a * swapped server. This request returns information about which visuals * support double buffering. * * Return Values: * * BadDrawable - value in screen specifiers is not a valid drawable * Success * *****************************************************************************/ static int SProcDbeGetVisualInfo(ClientPtr client) { REQUEST(xDbeGetVisualInfoReq); register int n; swaps(&stuff->length, n); REQUEST_AT_LEAST_SIZE(xDbeGetVisualInfoReq); swapl(&stuff->n, n); SwapRestL(stuff); return(ProcDbeGetVisualInfo(client)); } /* SProcDbeGetVisualInfo() */ /****************************************************************************** * * DBE DIX Procedure: SProcDbeGetbackBufferAttributes * * Description: * * This function is for processing a ProcDbeGetbackBufferAttributes * request on a swapped server. This request returns information about a * back buffer. * * Return Values: * * Success * *****************************************************************************/ static int SProcDbeGetBackBufferAttributes(ClientPtr client) { REQUEST (xDbeGetBackBufferAttributesReq); register int n; swaps(&stuff->length, n); REQUEST_SIZE_MATCH(xDbeGetBackBufferAttributesReq); swapl(&stuff->buffer, n); return(ProcDbeGetBackBufferAttributes(client)); } /* SProcDbeGetBackBufferAttributes() */ /****************************************************************************** * * DBE DIX Procedure: SProcDbeDispatch * * Description: * * This function dispatches DBE requests on a swapped server. * *****************************************************************************/ static int SProcDbeDispatch(ClientPtr client) { REQUEST(xReq); switch (stuff->data) { case X_DbeGetVersion: return(SProcDbeGetVersion(client)); case X_DbeAllocateBackBufferName: return(SProcDbeAllocateBackBufferName(client)); case X_DbeDeallocateBackBufferName: return(SProcDbeDeallocateBackBufferName(client)); case X_DbeSwapBuffers: return(SProcDbeSwapBuffers(client)); case X_DbeBeginIdiom: return(SProcDbeBeginIdiom(client)); case X_DbeEndIdiom: return(Success); case X_DbeGetVisualInfo: return(SProcDbeGetVisualInfo(client)); case X_DbeGetBackBufferAttributes: return(SProcDbeGetBackBufferAttributes(client)); default: return (BadRequest); } } /* SProcDbeDispatch() */ /****************************************************************************** * * DBE DIX Procedure: DbeSetupBackgroundPainter * * Description: * * This function sets up pGC to clear pixmaps. * * Return Values: * * TRUE - setup was successful * FALSE - the window's background state is NONE * *****************************************************************************/ static Bool DbeSetupBackgroundPainter(WindowPtr pWin, GCPtr pGC) { pointer gcvalues[4]; int ts_x_origin, ts_y_origin; PixUnion background; int backgroundState; Mask gcmask; /* First take care of any ParentRelative stuff by altering the * tile/stipple origin to match the coordinates of the upper-left * corner of the first ancestor without a ParentRelative background. * This coordinate is, of course, negative. */ ts_x_origin = ts_y_origin = 0; while (pWin->backgroundState == ParentRelative) { ts_x_origin -= pWin->origin.x; ts_y_origin -= pWin->origin.y; pWin = pWin->parent; } backgroundState = pWin->backgroundState; background = pWin->background; switch (backgroundState) { case BackgroundPixel: gcvalues[0] = (pointer)background.pixel; gcvalues[1] = (pointer)FillSolid; gcmask = GCForeground|GCFillStyle; break; case BackgroundPixmap: gcvalues[0] = (pointer)FillTiled; gcvalues[1] = (pointer)background.pixmap; gcvalues[2] = (pointer)(long)ts_x_origin; gcvalues[3] = (pointer)(long)ts_y_origin; gcmask = GCFillStyle|GCTile|GCTileStipXOrigin|GCTileStipYOrigin; break; default: /* pWin->backgroundState == None */ return(FALSE); } if (DoChangeGC(pGC, gcmask, (XID *)gcvalues, TRUE) != 0) { return(FALSE); } return(TRUE); } /* DbeSetupBackgroundPainter() */ /****************************************************************************** * * DBE DIX Procedure: DbeDrawableDelete * * Description: * * This is the resource delete function for dbeDrawableResType. * It is registered when the drawable resource type is created in * DbeExtensionInit(). * * To make resource deletion simple, we do not do anything in this function * and leave all resource deleteion to DbeWindowPrivDelete(), which will * eventually be called or already has been called. Deletion functions are * not guaranteed to be called in any particular order. * *****************************************************************************/ static int DbeDrawableDelete(pointer pDrawable, XID id) { return(Success); } /* DbeDrawableDelete() */ /****************************************************************************** * * DBE DIX Procedure: DbeWindowPrivDelete * * Description: * * This is the resource delete function for dbeWindowPrivResType. * It is registered when the drawable resource type is created in * DbeExtensionInit(). * *****************************************************************************/ static int DbeWindowPrivDelete(pointer pDbeWinPriv, XID id) { DbeScreenPrivPtr pDbeScreenPriv; DbeWindowPrivPtr pDbeWindowPriv = (DbeWindowPrivPtr)pDbeWinPriv; int i; /* ************************************************************************** ** Remove the buffer ID from the ID array. ************************************************************************** */ /* Find the ID in the ID array. */ i = 0; while ((i < pDbeWindowPriv->nBufferIDs) && (pDbeWindowPriv->IDs[i] != id)) { i++; } if (i == pDbeWindowPriv->nBufferIDs) { /* We did not find the ID in the array. We should never get here. */ return(BadValue); } /* Remove the ID from the array. */ if (i < (pDbeWindowPriv->nBufferIDs - 1)) { /* Compress the buffer ID array, overwriting the ID in the process. */ memmove(&pDbeWindowPriv->IDs[i], &pDbeWindowPriv->IDs[i+1], (pDbeWindowPriv->nBufferIDs - i - 1) * sizeof(XID)); } else { /* We are removing the last ID in the array, in which case, the * assignement below is all that we need to do. */ } pDbeWindowPriv->IDs[pDbeWindowPriv->nBufferIDs - 1] = DBE_FREE_ID_ELEMENT; pDbeWindowPriv->nBufferIDs--; /* If an extended array was allocated, then check to see if the remaining * buffer IDs will fit in the static array. */ if ((pDbeWindowPriv->maxAvailableIDs > DBE_INIT_MAX_IDS) && (pDbeWindowPriv->nBufferIDs == DBE_INIT_MAX_IDS)) { /* Copy the IDs back into the static array. */ memcpy(pDbeWindowPriv->initIDs, pDbeWindowPriv->IDs, DBE_INIT_MAX_IDS * sizeof(XID)); /* Free the extended array; use the static array. */ xfree(pDbeWindowPriv->IDs); pDbeWindowPriv->IDs = pDbeWindowPriv->initIDs; pDbeWindowPriv->maxAvailableIDs = DBE_INIT_MAX_IDS; } /* ************************************************************************** ** Perform DDX level tasks. ************************************************************************** */ pDbeScreenPriv = DBE_SCREEN_PRIV_FROM_WINDOW_PRIV( (DbeWindowPrivPtr)pDbeWindowPriv); (*pDbeScreenPriv->WinPrivDelete)((DbeWindowPrivPtr)pDbeWindowPriv, id); /* ************************************************************************** ** Perform miscellaneous tasks if this is the last buffer associated ** with the window. ************************************************************************** */ if (pDbeWindowPriv->nBufferIDs == 0) { /* Reset the DBE window priv pointer. */ pDbeWindowPriv->pWindow->devPrivates[dbeWindowPrivIndex].ptr = (pointer)NULL; /* We are done with the window priv. */ xfree(pDbeWindowPriv); } return(Success); } /* DbeWindowPrivDelete() */ /****************************************************************************** * * DBE DIX Procedure: DbeResetProc * * Description: * * This routine is called at the end of every server generation. * It deallocates any memory reserved for the extension and performs any * other tasks related to shutting down the extension. * *****************************************************************************/ static void DbeResetProc(ExtensionEntry *extEntry) { int i; ScreenPtr pScreen; DbeScreenPrivPtr pDbeScreenPriv; if (dbeScreenPrivIndex < 0) { return; } for (i = 0; i < screenInfo.numScreens; i++) { pScreen = screenInfo.screens[i]; pDbeScreenPriv = DBE_SCREEN_PRIV(pScreen); if (pDbeScreenPriv) { /* Unwrap DestroyWindow, which was wrapped in DbeExtensionInit().*/ pScreen->DestroyWindow = pDbeScreenPriv->DestroyWindow; if (pDbeScreenPriv->ResetProc) (*pDbeScreenPriv->ResetProc)(pScreen); if (pDbeScreenPriv->winPrivPrivSizes) { xfree(pDbeScreenPriv->winPrivPrivSizes); } xfree(pDbeScreenPriv); } } /* We want to init the initialization function table after every server * reset in DbeRegisterFunction(). */ firstRegistrationPass = TRUE; } /* DbeResetProc() */ /****************************************************************************** * * DBE DIX Procedure: DbeDestroyWindow * * Description: * * This is the wrapper for pScreen->DestroyWindow. * This function frees buffer resources for a window before it is * destroyed. * *****************************************************************************/ static Bool DbeDestroyWindow(WindowPtr pWin) { DbeScreenPrivPtr pDbeScreenPriv; DbeWindowPrivPtr pDbeWindowPriv; ScreenPtr pScreen; Bool ret; /* ************************************************************************** ** 1. Unwrap the member routine. ************************************************************************** */ pScreen = pWin->drawable.pScreen; pDbeScreenPriv = DBE_SCREEN_PRIV(pScreen); pScreen->DestroyWindow = pDbeScreenPriv->DestroyWindow; /* ************************************************************************** ** 2. Do any work necessary before the member routine is called. ** ** Call the window priv delete function for all buffer IDs associated ** with this window. ************************************************************************** */ if ((pDbeWindowPriv = DBE_WINDOW_PRIV(pWin))) { while (pDbeWindowPriv) { /* *DbeWinPrivDelete() will free the window private and set it to * NULL if there are no more buffer IDs associated with this * window. */ FreeResource(pDbeWindowPriv->IDs[0], RT_NONE); pDbeWindowPriv = DBE_WINDOW_PRIV(pWin); } } /* ************************************************************************** ** 3. Call the member routine, saving its result if necessary. ************************************************************************** */ ret = (*pScreen->DestroyWindow)(pWin); /* ************************************************************************** ** 4. Rewrap the member routine, restoring the wrapper value first in case ** the wrapper (or something that it wrapped) change this value. ************************************************************************** */ pDbeScreenPriv->DestroyWindow = pScreen->DestroyWindow; pScreen->DestroyWindow = DbeDestroyWindow; /* ************************************************************************** ** 5. Do any work necessary after the member routine has been called. ** ** In this case we do not need to do anything. ************************************************************************** */ return(ret); } /* DbeDestroyWindow() */ /****************************************************************************** * * DBE DIX Procedure: DbeExtensionInit * * Description: * * Called from InitExtensions in main() * *****************************************************************************/ void DbeExtensionInit(void) { ExtensionEntry *extEntry; register int i, j; ScreenPtr pScreen = NULL; DbeScreenPrivPtr pDbeScreenPriv; int nStubbedScreens = 0; Bool ddxInitSuccess; #ifdef PANORAMIX if(!noPanoramiXExtension) return; #endif /* Allocate private pointers in windows and screens. */ if ((dbeScreenPrivIndex = AllocateScreenPrivateIndex()) < 0) { return; } if ((dbeWindowPrivIndex = AllocateWindowPrivateIndex()) < 0) { return; } /* Initialize the priv priv counts between server generations. */ winPrivPrivCount = 0; /* Create the resource types. */ dbeDrawableResType = CreateNewResourceType(DbeDrawableDelete) | RC_CACHED | RC_DRAWABLE; dbeWindowPrivResType = CreateNewResourceType(DbeWindowPrivDelete); for (i = 0; i < screenInfo.numScreens; i++) { /* For each screen, set up DBE screen privates and init DIX and DDX * interface. */ pScreen = screenInfo.screens[i]; if (!AllocateWindowPrivate(pScreen, dbeWindowPrivIndex, 0) || !(pDbeScreenPriv = (DbeScreenPrivPtr)Xcalloc(sizeof(DbeScreenPrivRec)))) { /* If we can not alloc a window or screen private, * then free any privates that we already alloc'ed and return */ for (j = 0; j < i; j++) { xfree(screenInfo.screens[j]->devPrivates[dbeScreenPrivIndex].ptr); screenInfo.screens[j]->devPrivates[dbeScreenPrivIndex].ptr = NULL; } return; } pScreen->devPrivates[dbeScreenPrivIndex].ptr = (pointer)pDbeScreenPriv; /* Store the DBE priv priv size info for later use when allocating * priv privs at the driver level. */ pDbeScreenPriv->winPrivPrivLen = 0; pDbeScreenPriv->winPrivPrivSizes = (unsigned *)NULL; pDbeScreenPriv->totalWinPrivSize = sizeof(DbeWindowPrivRec); /* Copy the resource types */ pDbeScreenPriv->dbeDrawableResType = dbeDrawableResType; pDbeScreenPriv->dbeWindowPrivResType = dbeWindowPrivResType; /* Copy the private indices */ pDbeScreenPriv->dbeScreenPrivIndex = dbeScreenPrivIndex; pDbeScreenPriv->dbeWindowPrivIndex = dbeWindowPrivIndex; if(DbeInitFunct[i]) { /* This screen supports DBE. */ /* Setup DIX. */ pDbeScreenPriv->SetupBackgroundPainter = DbeSetupBackgroundPainter; pDbeScreenPriv->AllocWinPriv = DbeAllocWinPriv; pDbeScreenPriv->AllocWinPrivPrivIndex = DbeAllocWinPrivPrivIndex; pDbeScreenPriv->AllocWinPrivPriv = DbeAllocWinPrivPriv; /* Setup DDX. */ ddxInitSuccess = (*DbeInitFunct[i])(pScreen, pDbeScreenPriv); /* DDX DBE initialization may have the side affect of * reallocating pDbeScreenPriv, so we need to update it. */ pDbeScreenPriv = DBE_SCREEN_PRIV(pScreen); if (ddxInitSuccess) { /* Wrap DestroyWindow. The DDX initialization function * already wrapped PositionWindow for us. */ pDbeScreenPriv->DestroyWindow = pScreen->DestroyWindow; pScreen->DestroyWindow = DbeDestroyWindow; } else { /* DDX initialization failed. Stub the screen. */ DbeStubScreen(pDbeScreenPriv, &nStubbedScreens); } } else { /* This screen does not support DBE. */ #ifndef DISABLE_MI_DBE_BY_DEFAULT /* Setup DIX. */ pDbeScreenPriv->SetupBackgroundPainter = DbeSetupBackgroundPainter; pDbeScreenPriv->AllocWinPriv = DbeAllocWinPriv; pDbeScreenPriv->AllocWinPrivPrivIndex = DbeAllocWinPrivPrivIndex; pDbeScreenPriv->AllocWinPrivPriv = DbeAllocWinPrivPriv; /* Setup DDX. */ ddxInitSuccess = miDbeInit(pScreen, pDbeScreenPriv); /* DDX DBE initialization may have the side affect of * reallocating pDbeScreenPriv, so we need to update it. */ pDbeScreenPriv = DBE_SCREEN_PRIV(pScreen); if (ddxInitSuccess) { /* Wrap DestroyWindow. The DDX initialization function * already wrapped PositionWindow for us. */ pDbeScreenPriv->DestroyWindow = pScreen->DestroyWindow; pScreen->DestroyWindow = DbeDestroyWindow; } else { /* DDX initialization failed. Stub the screen. */ DbeStubScreen(pDbeScreenPriv, &nStubbedScreens); } #else DbeStubScreen(pDbeScreenPriv, &nStubbedScreens); #endif } /* else -- this screen does not support DBE. */ } /* for (i = 0; i < screenInfo.numScreens; i++) */ if (nStubbedScreens == screenInfo.numScreens) { /* All screens stubbed. Clean up and return. */ for (i = 0; i < screenInfo.numScreens; i++) { xfree(screenInfo.screens[i]->devPrivates[dbeScreenPrivIndex].ptr); pScreen->devPrivates[dbeScreenPrivIndex].ptr = NULL; } return; } /* Now add the extension. */ extEntry = AddExtension(DBE_PROTOCOL_NAME, DbeNumberEvents, DbeNumberErrors, ProcDbeDispatch, SProcDbeDispatch, DbeResetProc, StandardMinorOpcode); dbeErrorBase = extEntry->errorBase; } /* DbeExtensionInit() */