1470 lines
		
	
	
		
			45 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			1470 lines
		
	
	
		
			45 KiB
		
	
	
	
		
			C
		
	
	
	
| /******************************************************************************
 | ||
|  *
 | ||
|  * 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 */
 | ||
| 
 | ||
| #ifdef HAVE_DIX_CONFIG_H
 | ||
| #include <dix-config.h>
 | ||
| #endif
 | ||
| 
 | ||
| #include <string.h>
 | ||
| #include <stdint.h>
 | ||
| #include <X11/X.h>
 | ||
| #include <X11/Xproto.h>
 | ||
| #include "scrnintstr.h"
 | ||
| #include "extnsionst.h"
 | ||
| #include "extinit.h"
 | ||
| #include "gcstruct.h"
 | ||
| #include "dixstruct.h"
 | ||
| #define NEED_DBE_PROTOCOL
 | ||
| #include "dbestruct.h"
 | ||
| #include "midbe.h"
 | ||
| #include "xace.h"
 | ||
| 
 | ||
| /* GLOBALS */
 | ||
| 
 | ||
| /* These are globals for use by DDX */
 | ||
| DevPrivateKeyRec dbeScreenPrivKeyRec;
 | ||
| DevPrivateKeyRec dbeWindowPrivKeyRec;
 | ||
| 
 | ||
| /* These are globals for use by DDX */
 | ||
| RESTYPE dbeDrawableResType;
 | ||
| RESTYPE dbeWindowPrivResType;
 | ||
| 
 | ||
| /* Used to generate DBE's BadBuffer error. */
 | ||
| static int dbeErrorBase;
 | ||
| 
 | ||
| /******************************************************************************
 | ||
|  *
 | ||
|  * 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->WinPrivDelete = 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 = {
 | ||
|         .type = X_Reply,
 | ||
|         .sequenceNumber = client->sequence,
 | ||
|         .length = 0,
 | ||
|         .majorVersion = DBE_MAJOR_VERSION,
 | ||
|         .minorVersion = DBE_MINOR_VERSION
 | ||
|     };
 | ||
| 
 | ||
|     REQUEST_SIZE_MATCH(xDbeGetVersionReq);
 | ||
| 
 | ||
|     if (client->swapped) {
 | ||
|         swaps(&rep.sequenceNumber);
 | ||
|     }
 | ||
| 
 | ||
|     WriteToClient(client, sizeof(xDbeGetVersionReply), &rep);
 | ||
| 
 | ||
|     return Success;
 | ||
| 
 | ||
| }                               /* 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. */
 | ||
|     free(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 = calloc(1, sizeof(DbeWindowPrivRec));
 | ||
|         if (!pDbeWindowPriv)
 | ||
|             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;
 | ||
|         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 =
 | ||
|                 reallocarray(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,
 | ||
|                          (void *) 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);
 | ||
|     free(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 rc, i;
 | ||
|     void *val;
 | ||
| 
 | ||
|     REQUEST_SIZE_MATCH(xDbeDeallocateBackBufferNameReq);
 | ||
| 
 | ||
|     /* Buffer name must be valid */
 | ||
|     rc = dixLookupResourceByType((void **) &pDbeWindowPriv, stuff->buffer,
 | ||
|                                  dbeWindowPrivResType, client,
 | ||
|                                  DixDestroyAccess);
 | ||
|     if (rc != Success)
 | ||
|         return rc;
 | ||
| 
 | ||
|     rc = dixLookupResourceByType(&val, stuff->buffer, dbeDrawableResType,
 | ||
|                                  client, DixDestroyAccess);
 | ||
|     if (rc != Success)
 | ||
|         return rc;
 | ||
| 
 | ||
|     /* 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;
 | ||
|     unsigned int i, j;
 | ||
|     unsigned int nStuff;
 | ||
|     int nStuff_i;       /* DDX API requires int for nStuff */
 | ||
| 
 | ||
|     REQUEST_AT_LEAST_SIZE(xDbeSwapBuffersReq);
 | ||
|     nStuff = stuff->n;          /* use local variable for performance. */
 | ||
| 
 | ||
|     if (nStuff == 0) {
 | ||
|         REQUEST_SIZE_MATCH(xDbeSwapBuffersReq);
 | ||
|         return Success;
 | ||
|     }
 | ||
| 
 | ||
|     if (nStuff > UINT32_MAX / sizeof(DbeSwapInfoRec))
 | ||
|         return BadAlloc;
 | ||
|     REQUEST_FIXED_SIZE(xDbeSwapBuffersReq, nStuff * sizeof(xDbeSwapInfo));
 | ||
| 
 | ||
|     /* Get to the swap info appended to the end of the request. */
 | ||
|     dbeSwapInfo = (xDbeSwapInfo *) &stuff[1];
 | ||
| 
 | ||
|     /* Allocate array to record swap information. */
 | ||
|     swapInfo = xallocarray(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) {
 | ||
|             free(swapInfo);
 | ||
|             return error;
 | ||
|         }
 | ||
| 
 | ||
|         /* Each window must be double-buffered - BadMatch. */
 | ||
|         if (DBE_WINDOW_PRIV(pWin) == NULL) {
 | ||
|             free(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) {
 | ||
|                 free(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)) {
 | ||
|             free(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.
 | ||
|      */
 | ||
| 
 | ||
|     nStuff_i = nStuff;
 | ||
|     while (nStuff_i > 0) {
 | ||
|         pDbeScreenPriv = DBE_SCREEN_PRIV_FROM_WINDOW(swapInfo[0].pWindow);
 | ||
|         error = (*pDbeScreenPriv->SwapBuffers) (client, &nStuff_i, swapInfo);
 | ||
|         if (error != Success) {
 | ||
|             free(swapInfo);
 | ||
|             return error;
 | ||
|         }
 | ||
|     }
 | ||
| 
 | ||
|     free(swapInfo);
 | ||
|     return Success;
 | ||
| 
 | ||
| }                               /* ProcDbeSwapBuffers() */
 | ||
| 
 | ||
| /******************************************************************************
 | ||
|  *
 | ||
|  * 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, 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 = xallocarray(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) {
 | ||
|                 free(pDrawables);
 | ||
|                 return rc;
 | ||
|             }
 | ||
|         }
 | ||
|     }
 | ||
| 
 | ||
|     count = (stuff->n == 0) ? screenInfo.numScreens : stuff->n;
 | ||
|     if (!(pScrVisInfo = calloc(count, sizeof(XdbeScreenVisualInfo)))) {
 | ||
|         free(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)
 | ||
|             goto freeScrVisInfo;
 | ||
| 
 | ||
|         if (!(*pDbeScreenPriv->GetVisualInfo) (pScreen, &pScrVisInfo[i])) {
 | ||
|             /* We failed to alloc pScrVisInfo[i].visinfo. */
 | ||
|             rc = BadAlloc;
 | ||
| 
 | ||
|             /* Free visinfos that we allocated for previous screen infos. */
 | ||
|             goto freeScrVisInfo;
 | ||
|         }
 | ||
| 
 | ||
|         /* Account for n, number of xDbeVisInfo items in list. */
 | ||
|         length += sizeof(CARD32);
 | ||
| 
 | ||
|         /* Account for n xDbeVisInfo items */
 | ||
|         length += pScrVisInfo[i].count * sizeof(xDbeVisInfo);
 | ||
|     }
 | ||
| 
 | ||
|     rep = (xDbeGetVisualInfoReply) {
 | ||
|         .type = X_Reply,
 | ||
|         .sequenceNumber = client->sequence,
 | ||
|         .length = bytes_to_int32(length),
 | ||
|         .m = count
 | ||
|     };
 | ||
| 
 | ||
|     if (client->swapped) {
 | ||
|         swaps(&rep.sequenceNumber);
 | ||
|         swapl(&rep.length);
 | ||
|         swapl(&rep.m);
 | ||
|     }
 | ||
| 
 | ||
|     /* Send off reply. */
 | ||
|     WriteToClient(client, sizeof(xDbeGetVisualInfoReply), &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);
 | ||
|         }
 | ||
| 
 | ||
|         WriteToClient(client, sizeof(CARD32), &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);
 | ||
| 
 | ||
|                 /* 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), &visInfo.visualID);
 | ||
|         }
 | ||
|     }
 | ||
| 
 | ||
|     rc = Success;
 | ||
| 
 | ||
|  freeScrVisInfo:
 | ||
|     /* Clean up memory. */
 | ||
|     for (i = 0; i < count; i++) {
 | ||
|         free(pScrVisInfo[i].visinfo);
 | ||
|     }
 | ||
|     free(pScrVisInfo);
 | ||
| 
 | ||
|     free(pDrawables);
 | ||
| 
 | ||
|     return rc;
 | ||
| 
 | ||
| }                               /* 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 = {
 | ||
|         .type = X_Reply,
 | ||
|         .sequenceNumber = client->sequence,
 | ||
|         .length = 0
 | ||
|     };
 | ||
|     DbeWindowPrivPtr pDbeWindowPriv;
 | ||
|     int rc;
 | ||
| 
 | ||
|     REQUEST_SIZE_MATCH(xDbeGetBackBufferAttributesReq);
 | ||
| 
 | ||
|     rc = dixLookupResourceByType((void **) &pDbeWindowPriv, stuff->buffer,
 | ||
|                                  dbeWindowPrivResType, client,
 | ||
|                                  DixGetAttrAccess);
 | ||
|     if (rc == Success) {
 | ||
|         rep.attributes = pDbeWindowPriv->pWindow->drawable.id;
 | ||
|     }
 | ||
|     else {
 | ||
|         rep.attributes = None;
 | ||
|     }
 | ||
| 
 | ||
|     if (client->swapped) {
 | ||
|         swaps(&rep.sequenceNumber);
 | ||
|         swapl(&rep.length);
 | ||
|         swapl(&rep.attributes);
 | ||
|     }
 | ||
| 
 | ||
|     WriteToClient(client, sizeof(xDbeGetBackBufferAttributesReply), &rep);
 | ||
|     return Success;
 | ||
| 
 | ||
| }                               /* 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 Success;
 | ||
| 
 | ||
|     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 _X_COLD
 | ||
| SProcDbeGetVersion(ClientPtr client)
 | ||
| {
 | ||
|     REQUEST(xDbeGetVersionReq);
 | ||
| 
 | ||
|     swaps(&stuff->length);
 | ||
|     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 _X_COLD
 | ||
| SProcDbeAllocateBackBufferName(ClientPtr client)
 | ||
| {
 | ||
|     REQUEST(xDbeAllocateBackBufferNameReq);
 | ||
| 
 | ||
|     swaps(&stuff->length);
 | ||
|     REQUEST_SIZE_MATCH(xDbeAllocateBackBufferNameReq);
 | ||
| 
 | ||
|     swapl(&stuff->window);
 | ||
|     swapl(&stuff->buffer);
 | ||
|     /* 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 _X_COLD
 | ||
| SProcDbeDeallocateBackBufferName(ClientPtr client)
 | ||
| {
 | ||
|     REQUEST(xDbeDeallocateBackBufferNameReq);
 | ||
| 
 | ||
|     swaps(&stuff->length);
 | ||
|     REQUEST_SIZE_MATCH(xDbeDeallocateBackBufferNameReq);
 | ||
| 
 | ||
|     swapl(&stuff->buffer);
 | ||
| 
 | ||
|     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 _X_COLD
 | ||
| SProcDbeSwapBuffers(ClientPtr client)
 | ||
| {
 | ||
|     REQUEST(xDbeSwapBuffersReq);
 | ||
|     unsigned int i;
 | ||
|     xDbeSwapInfo *pSwapInfo;
 | ||
| 
 | ||
|     swaps(&stuff->length);
 | ||
|     REQUEST_AT_LEAST_SIZE(xDbeSwapBuffersReq);
 | ||
| 
 | ||
|     swapl(&stuff->n);
 | ||
|     if (stuff->n > UINT32_MAX / sizeof(DbeSwapInfoRec))
 | ||
|         return BadAlloc;
 | ||
|     REQUEST_FIXED_SIZE(xDbeSwapBuffersReq, stuff->n * sizeof(xDbeSwapInfo));
 | ||
| 
 | ||
|     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);
 | ||
|         }
 | ||
|     }
 | ||
| 
 | ||
|     return (ProcDbeSwapBuffers(client));
 | ||
| 
 | ||
| }                               /* SProcDbeSwapBuffers() */
 | ||
| 
 | ||
| /******************************************************************************
 | ||
|  *
 | ||
|  * 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 _X_COLD
 | ||
| SProcDbeGetVisualInfo(ClientPtr client)
 | ||
| {
 | ||
|     REQUEST(xDbeGetVisualInfoReq);
 | ||
| 
 | ||
|     swaps(&stuff->length);
 | ||
|     REQUEST_AT_LEAST_SIZE(xDbeGetVisualInfoReq);
 | ||
| 
 | ||
|     swapl(&stuff->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 _X_COLD
 | ||
| SProcDbeGetBackBufferAttributes(ClientPtr client)
 | ||
| {
 | ||
|     REQUEST(xDbeGetBackBufferAttributesReq);
 | ||
| 
 | ||
|     swaps(&stuff->length);
 | ||
|     REQUEST_SIZE_MATCH(xDbeGetBackBufferAttributesReq);
 | ||
| 
 | ||
|     swapl(&stuff->buffer);
 | ||
| 
 | ||
|     return (ProcDbeGetBackBufferAttributes(client));
 | ||
| 
 | ||
| }                               /* SProcDbeGetBackBufferAttributes() */
 | ||
| 
 | ||
| /******************************************************************************
 | ||
|  *
 | ||
|  * DBE DIX Procedure: SProcDbeDispatch
 | ||
|  *
 | ||
|  * Description:
 | ||
|  *
 | ||
|  *     This function dispatches DBE requests on a swapped server.
 | ||
|  *
 | ||
|  *****************************************************************************/
 | ||
| 
 | ||
| static int _X_COLD
 | ||
| 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 Success;
 | ||
| 
 | ||
|     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)
 | ||
| {
 | ||
|     ChangeGCVal 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].val = background.pixel;
 | ||
|         gcvalues[1].val = FillSolid;
 | ||
|         gcmask = GCForeground | GCFillStyle;
 | ||
|         break;
 | ||
| 
 | ||
|     case BackgroundPixmap:
 | ||
|         gcvalues[0].val = FillTiled;
 | ||
|         gcvalues[1].ptr = background.pixmap;
 | ||
|         gcvalues[2].val = ts_x_origin;
 | ||
|         gcvalues[3].val = ts_y_origin;
 | ||
|         gcmask = GCFillStyle | GCTile | GCTileStipXOrigin | GCTileStipYOrigin;
 | ||
|         break;
 | ||
| 
 | ||
|     default:
 | ||
|         /* pWin->backgroundState == None */
 | ||
|         return FALSE;
 | ||
|     }
 | ||
| 
 | ||
|     return ChangeGC(NullClient, pGC, gcmask, gcvalues) == 0;
 | ||
| }                               /* 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(void *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(void *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. */
 | ||
|         free(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. */
 | ||
|         free(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;
 | ||
|             pScreen->PositionWindow = pDbeScreenPriv->PositionWindow;
 | ||
|             free(pDbeScreenPriv);
 | ||
|         }
 | ||
|     }
 | ||
| }                               /* 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, "dbeDrawable");
 | ||
|     if (!dbeDrawableResType)
 | ||
|         return;
 | ||
|     dbeDrawableResType |= RC_DRAWABLE;
 | ||
| 
 | ||
|     dbeWindowPrivResType =
 | ||
|         CreateNewResourceType(DbeWindowPrivDelete, "dbeWindow");
 | ||
|     if (!dbeWindowPrivResType)
 | ||
|         return;
 | ||
| 
 | ||
|     if (!dixRegisterPrivateKey(&dbeScreenPrivKeyRec, PRIVATE_SCREEN, 0))
 | ||
|         return;
 | ||
| 
 | ||
|     if (!dixRegisterPrivateKey(&dbeWindowPrivKeyRec, PRIVATE_WINDOW, 0))
 | ||
|         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 = malloc(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++) {
 | ||
|                 free(dixLookupPrivate(&screenInfo.screens[j]->devPrivates,
 | ||
|                                       dbeScreenPrivKey));
 | ||
|                 dixSetPrivate(&screenInfo.screens[j]->devPrivates,
 | ||
|                               dbeScreenPrivKey, NULL);
 | ||
|             }
 | ||
|             return;
 | ||
|         }
 | ||
| 
 | ||
|         dixSetPrivate(&pScreen->devPrivates, dbeScreenPrivKey, pDbeScreenPriv);
 | ||
| 
 | ||
|         {
 | ||
|             /* We don't have DDX support for DBE anymore */
 | ||
| 
 | ||
| #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
 | ||
| 
 | ||
|         }
 | ||
| 
 | ||
|     }                           /* 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++) {
 | ||
|             free(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;
 | ||
|     SetResourceTypeErrorValue(dbeWindowPrivResType,
 | ||
|                               dbeErrorBase + DbeBadBuffer);
 | ||
|     SetResourceTypeErrorValue(dbeDrawableResType, dbeErrorBase + DbeBadBuffer);
 | ||
| 
 | ||
| }                               /* DbeExtensionInit() */
 |