diff options
Diffstat (limited to 'xorg-server/dbe/dbe.c')
-rw-r--r-- | xorg-server/dbe/dbe.c | 1752 |
1 files changed, 1752 insertions, 0 deletions
diff --git a/xorg-server/dbe/dbe.c b/xorg-server/dbe/dbe.c new file mode 100644 index 000000000..d34708d38 --- /dev/null +++ b/xorg-server/dbe/dbe.c @@ -0,0 +1,1752 @@ +/****************************************************************************** + * + * 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 <dix-config.h> +#endif + +#include <string.h> +#if HAVE_STDINT_H +#include <stdint.h> +#elif !defined(UINT32_MAX) +#define UINT32_MAX 0xffffffffU +#endif + +#include <X11/X.h> +#include <X11/Xproto.h> +#include "scrnintstr.h" +#include "extnsionst.h" +#include "gcstruct.h" +#include "dixstruct.h" +#define NEED_DBE_PROTOCOL +#include "dbestruct.h" +#include "midbe.h" +#include "xace.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 DevPrivateKey dbeScreenPrivKey = &dbeScreenPrivKey; +static DevPrivateKey dbeWindowPrivKey = &dbeWindowPrivKey; + +/* These are static globals copied to DBE's screen private for use by DDX */ +static RESTYPE dbeDrawableResType; +static RESTYPE dbeWindowPrivResType; + +/* 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: 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; + + /* 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, DixManageAccess); + 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. + */ + + pDbeWindowPriv = (DbeWindowPrivPtr)xalloc(sizeof(DbeWindowPrivRec)); + if (!pDbeWindowPriv) + return(BadAlloc); + bzero(pDbeWindowPriv, sizeof(DbeWindowPrivRec)); + + /* 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; + pDbeWindowPriv->IDs[0] = stuff->buffer; + + add_index = 0; + for (i = 0; i < DBE_INIT_MAX_IDS; i++) + { + pDbeWindowPriv->IDs[i] = DBE_FREE_ID_ELEMENT; + } + + /* Actually connect the window priv to the window. */ + dixSetPrivate(&pWin->devPrivates, dbeWindowPrivKey, 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: + dixSetPrivate(&pWin->devPrivates, dbeWindowPrivKey, 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, + DixGetAttrAccess); + 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); + + rc = XaceHook(XACE_SCREEN_ACCESS, client, pScreen, DixGetAttrAccess); + if ((rc != Success) || + !(*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 (rc == Success) ? BadAlloc : rc; + } + + /* 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, DixGetAttrAccess))) + { + 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. */ + dixSetPrivate(&pDbeWindowPriv->pWindow->devPrivates, dbeWindowPrivKey, + NULL); + + /* We are done with the window priv. */ + dixFreePrivates(pDbeWindowPriv->devPrivates); + 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; + + 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); + + dixFreePrivates(pDbeScreenPriv->devPrivates); + 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 + + /* Create the resource types. */ + dbeDrawableResType = + CreateNewResourceType(DbeDrawableDelete) | RC_DRAWABLE; + dbeWindowPrivResType = + CreateNewResourceType(DbeWindowPrivDelete); + if (!dixRegisterPrivateOffset(dbeDrawableResType, + offsetof(PixmapRec, devPrivates))) + return; + + 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 (!(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(dixLookupPrivate(&screenInfo.screens[j]->devPrivates, + dbeScreenPrivKey)); + dixSetPrivate(&screenInfo.screens[j]->devPrivates, + dbeScreenPrivKey, NULL); + } + return; + } + + dixSetPrivate(&pScreen->devPrivates, dbeScreenPrivKey, pDbeScreenPriv); + + /* Copy the resource types */ + pDbeScreenPriv->dbeDrawableResType = dbeDrawableResType; + pDbeScreenPriv->dbeWindowPrivResType = dbeWindowPrivResType; + + /* Copy the private indices */ + pDbeScreenPriv->dbeScreenPrivKey = dbeScreenPrivKey; + pDbeScreenPriv->dbeWindowPrivKey = dbeWindowPrivKey; + + if(DbeInitFunct[i]) + { + /* This screen supports DBE. */ + + /* Setup DIX. */ + pDbeScreenPriv->SetupBackgroundPainter = DbeSetupBackgroundPainter; + + /* 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; + + /* 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(dixLookupPrivate(&screenInfo.screens[i]->devPrivates, + dbeScreenPrivKey)); + dixSetPrivate(&pScreen->devPrivates, dbeScreenPrivKey, NULL); + } + return; + } + + + /* Now add the extension. */ + extEntry = AddExtension(DBE_PROTOCOL_NAME, DbeNumberEvents, + DbeNumberErrors, ProcDbeDispatch, SProcDbeDispatch, + DbeResetProc, StandardMinorOpcode); + + dbeErrorBase = extEntry->errorBase; + +} /* DbeExtensionInit() */ + |