xserver

xserver with xephyr scale patch
git clone https://git.neptards.moe/u3shit/xserver.git
Log | Files | Refs | README | LICENSE

dbe.c (46628B)


      1 /******************************************************************************
      2  *
      3  * Copyright (c) 1994, 1995  Hewlett-Packard Company
      4  *
      5  * Permission is hereby granted, free of charge, to any person obtaining
      6  * a copy of this software and associated documentation files (the
      7  * "Software"), to deal in the Software without restriction, including
      8  * without limitation the rights to use, copy, modify, merge, publish,
      9  * distribute, sublicense, and/or sell copies of the Software, and to
     10  * permit persons to whom the Software is furnished to do so, subject to
     11  * the following conditions:
     12  *
     13  * The above copyright notice and this permission notice shall be included
     14  * in all copies or substantial portions of the Software.
     15  *
     16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     17  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
     19  * IN NO EVENT SHALL HEWLETT-PACKARD COMPANY BE LIABLE FOR ANY CLAIM,
     20  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
     21  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
     22  * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     23  *
     24  * Except as contained in this notice, the name of the Hewlett-Packard
     25  * Company shall not be used in advertising or otherwise to promote the
     26  * sale, use or other dealings in this Software without prior written
     27  * authorization from the Hewlett-Packard Company.
     28  *
     29  *     DIX DBE code
     30  *
     31  *****************************************************************************/
     32 
     33 /* INCLUDES */
     34 
     35 #ifdef HAVE_DIX_CONFIG_H
     36 #include <dix-config.h>
     37 #endif
     38 
     39 #include <string.h>
     40 #include <stdint.h>
     41 #include <X11/X.h>
     42 #include <X11/Xproto.h>
     43 #include "scrnintstr.h"
     44 #include "extnsionst.h"
     45 #include "extinit.h"
     46 #include "gcstruct.h"
     47 #include "dixstruct.h"
     48 #define NEED_DBE_PROTOCOL
     49 #include "dbestruct.h"
     50 #include "midbe.h"
     51 #include "xace.h"
     52 
     53 /* GLOBALS */
     54 
     55 /* These are globals for use by DDX */
     56 DevPrivateKeyRec dbeScreenPrivKeyRec;
     57 DevPrivateKeyRec dbeWindowPrivKeyRec;
     58 
     59 /* These are globals for use by DDX */
     60 RESTYPE dbeDrawableResType;
     61 RESTYPE dbeWindowPrivResType;
     62 
     63 /* Used to generate DBE's BadBuffer error. */
     64 static int dbeErrorBase;
     65 
     66 /******************************************************************************
     67  *
     68  * DBE DIX Procedure: DbeStubScreen
     69  *
     70  * Description:
     71  *
     72  *     This is function stubs the function pointers in the given DBE screen
     73  *     private and increments the number of stubbed screens.
     74  *
     75  *****************************************************************************/
     76 
     77 static void
     78 DbeStubScreen(DbeScreenPrivPtr pDbeScreenPriv, int *nStubbedScreens)
     79 {
     80     /* Stub DIX. */
     81     pDbeScreenPriv->SetupBackgroundPainter = NULL;
     82 
     83     /* Do not unwrap PositionWindow nor DestroyWindow.  If the DDX
     84      * initialization function failed, we assume that it did not wrap
     85      * PositionWindow.  Also, DestroyWindow is only wrapped if the DDX
     86      * initialization function succeeded.
     87      */
     88 
     89     /* Stub DDX. */
     90     pDbeScreenPriv->GetVisualInfo = NULL;
     91     pDbeScreenPriv->AllocBackBufferName = NULL;
     92     pDbeScreenPriv->SwapBuffers = NULL;
     93     pDbeScreenPriv->WinPrivDelete = NULL;
     94 
     95     (*nStubbedScreens)++;
     96 
     97 }                               /* DbeStubScreen() */
     98 
     99 /******************************************************************************
    100  *
    101  * DBE DIX Procedure: ProcDbeGetVersion
    102  *
    103  * Description:
    104  *
    105  *     This function is for processing a DbeGetVersion request.
    106  *     This request returns the major and minor version numbers of this
    107  *     extension.
    108  *
    109  * Return Values:
    110  *
    111  *     Success
    112  *
    113  *****************************************************************************/
    114 
    115 static int
    116 ProcDbeGetVersion(ClientPtr client)
    117 {
    118     /* REQUEST(xDbeGetVersionReq); */
    119     xDbeGetVersionReply rep = {
    120         .type = X_Reply,
    121         .sequenceNumber = client->sequence,
    122         .length = 0,
    123         .majorVersion = DBE_MAJOR_VERSION,
    124         .minorVersion = DBE_MINOR_VERSION
    125     };
    126 
    127     REQUEST_SIZE_MATCH(xDbeGetVersionReq);
    128 
    129     if (client->swapped) {
    130         swaps(&rep.sequenceNumber);
    131     }
    132 
    133     WriteToClient(client, sizeof(xDbeGetVersionReply), &rep);
    134 
    135     return Success;
    136 
    137 }                               /* ProcDbeGetVersion() */
    138 
    139 /******************************************************************************
    140  *
    141  * DBE DIX Procedure: ProcDbeAllocateBackBufferName
    142  *
    143  * Description:
    144  *
    145  *     This function is for processing a DbeAllocateBackBufferName request.
    146  *     This request allocates a drawable ID used to refer to the back buffer
    147  *     of a window.
    148  *
    149  * Return Values:
    150  *
    151  *     BadAlloc    - server can not allocate resources
    152  *     BadIDChoice - id is out of range for client; id is already in use
    153  *     BadMatch    - window is not an InputOutput window;
    154  *                   visual of window is not on list returned by
    155  *                   DBEGetVisualInfo;
    156  *     BadValue    - invalid swap action is specified
    157  *     BadWindow   - window is not a valid window
    158  *     Success
    159  *
    160  *****************************************************************************/
    161 
    162 static int
    163 ProcDbeAllocateBackBufferName(ClientPtr client)
    164 {
    165     REQUEST(xDbeAllocateBackBufferNameReq);
    166     WindowPtr pWin;
    167     DbeScreenPrivPtr pDbeScreenPriv;
    168     DbeWindowPrivPtr pDbeWindowPriv;
    169     XdbeScreenVisualInfo scrVisInfo;
    170     register int i;
    171     Bool visualMatched = FALSE;
    172     xDbeSwapAction swapAction;
    173     VisualID visual;
    174     int status;
    175     int add_index;
    176 
    177     REQUEST_SIZE_MATCH(xDbeAllocateBackBufferNameReq);
    178 
    179     /* The window must be valid. */
    180     status = dixLookupWindow(&pWin, stuff->window, client, DixManageAccess);
    181     if (status != Success)
    182         return status;
    183 
    184     /* The window must be InputOutput. */
    185     if (pWin->drawable.class != InputOutput) {
    186         return BadMatch;
    187     }
    188 
    189     /* The swap action must be valid. */
    190     swapAction = stuff->swapAction;     /* use local var for performance. */
    191     if ((swapAction != XdbeUndefined) &&
    192         (swapAction != XdbeBackground) &&
    193         (swapAction != XdbeUntouched) && (swapAction != XdbeCopied)) {
    194         return BadValue;
    195     }
    196 
    197     /* The id must be in range and not already in use. */
    198     LEGAL_NEW_RESOURCE(stuff->buffer, client);
    199 
    200     /* The visual of the window must be in the list returned by
    201      * GetVisualInfo.
    202      */
    203     pDbeScreenPriv = DBE_SCREEN_PRIV_FROM_WINDOW(pWin);
    204     if (!pDbeScreenPriv->GetVisualInfo)
    205         return BadMatch;        /* screen doesn't support double buffering */
    206 
    207     if (!(*pDbeScreenPriv->GetVisualInfo) (pWin->drawable.pScreen, &scrVisInfo)) {
    208         /* GetVisualInfo() failed to allocate visual info data. */
    209         return BadAlloc;
    210     }
    211 
    212     /* See if the window's visual is on the list. */
    213     visual = wVisual(pWin);
    214     for (i = 0; (i < scrVisInfo.count) && !visualMatched; i++) {
    215         if (scrVisInfo.visinfo[i].visual == visual) {
    216             visualMatched = TRUE;
    217         }
    218     }
    219 
    220     /* Free what was allocated by the GetVisualInfo() call above. */
    221     free(scrVisInfo.visinfo);
    222 
    223     if (!visualMatched) {
    224         return BadMatch;
    225     }
    226 
    227     if ((pDbeWindowPriv = DBE_WINDOW_PRIV(pWin)) == NULL) {
    228         /* There is no buffer associated with the window.
    229          * Allocate a window priv.
    230          */
    231 
    232         pDbeWindowPriv = calloc(1, sizeof(DbeWindowPrivRec));
    233         if (!pDbeWindowPriv)
    234             return BadAlloc;
    235 
    236         /* Fill out window priv information. */
    237         pDbeWindowPriv->pWindow = pWin;
    238         pDbeWindowPriv->width = pWin->drawable.width;
    239         pDbeWindowPriv->height = pWin->drawable.height;
    240         pDbeWindowPriv->x = pWin->drawable.x;
    241         pDbeWindowPriv->y = pWin->drawable.y;
    242         pDbeWindowPriv->nBufferIDs = 0;
    243 
    244         /* Set the buffer ID array pointer to the initial (static) array). */
    245         pDbeWindowPriv->IDs = pDbeWindowPriv->initIDs;
    246 
    247         /* Initialize the buffer ID list. */
    248         pDbeWindowPriv->maxAvailableIDs = DBE_INIT_MAX_IDS;
    249         pDbeWindowPriv->IDs[0] = stuff->buffer;
    250 
    251         add_index = 0;
    252         for (i = 0; i < DBE_INIT_MAX_IDS; i++) {
    253             pDbeWindowPriv->IDs[i] = DBE_FREE_ID_ELEMENT;
    254         }
    255 
    256         /* Actually connect the window priv to the window. */
    257         dixSetPrivate(&pWin->devPrivates, dbeWindowPrivKey, pDbeWindowPriv);
    258 
    259     }                           /* if -- There is no buffer associated with the window. */
    260 
    261     else {
    262         /* A buffer is already associated with the window.
    263          * Add the new buffer ID to the array, reallocating the array memory
    264          * if necessary.
    265          */
    266 
    267         /* Determine if there is a free element in the ID array. */
    268         for (i = 0; i < pDbeWindowPriv->maxAvailableIDs; i++) {
    269             if (pDbeWindowPriv->IDs[i] == DBE_FREE_ID_ELEMENT) {
    270                 /* There is still room in the ID array. */
    271                 break;
    272             }
    273         }
    274 
    275         if (i == pDbeWindowPriv->maxAvailableIDs) {
    276             /* No more room in the ID array -- reallocate another array. */
    277             XID *pIDs;
    278 
    279             /* Setup an array pointer for the realloc operation below. */
    280             if (pDbeWindowPriv->maxAvailableIDs == DBE_INIT_MAX_IDS) {
    281                 /* We will malloc a new array. */
    282                 pIDs = NULL;
    283             }
    284             else {
    285                 /* We will realloc a new array. */
    286                 pIDs = pDbeWindowPriv->IDs;
    287             }
    288 
    289             /* malloc/realloc a new array and initialize all elements to 0. */
    290             pDbeWindowPriv->IDs =
    291                 reallocarray(pIDs,
    292                              pDbeWindowPriv->maxAvailableIDs + DBE_INCR_MAX_IDS,
    293                              sizeof(XID));
    294             if (!pDbeWindowPriv->IDs) {
    295                 return BadAlloc;
    296             }
    297             memset(&pDbeWindowPriv->IDs[pDbeWindowPriv->nBufferIDs], 0,
    298                    (pDbeWindowPriv->maxAvailableIDs + DBE_INCR_MAX_IDS -
    299                     pDbeWindowPriv->nBufferIDs) * sizeof(XID));
    300 
    301             if (pDbeWindowPriv->maxAvailableIDs == DBE_INIT_MAX_IDS) {
    302                 /* We just went from using the initial (static) array to a
    303                  * newly allocated array.  Copy the IDs from the initial array
    304                  * to the new array.
    305                  */
    306                 memcpy(pDbeWindowPriv->IDs, pDbeWindowPriv->initIDs,
    307                        DBE_INIT_MAX_IDS * sizeof(XID));
    308             }
    309 
    310             pDbeWindowPriv->maxAvailableIDs += DBE_INCR_MAX_IDS;
    311         }
    312 
    313         add_index = i;
    314 
    315     }                           /* else -- A buffer is already associated with the window. */
    316 
    317     /* Call the DDX routine to allocate the back buffer. */
    318     status = (*pDbeScreenPriv->AllocBackBufferName) (pWin, stuff->buffer,
    319                                                      stuff->swapAction);
    320 
    321     if (status == Success) {
    322         pDbeWindowPriv->IDs[add_index] = stuff->buffer;
    323         if (!AddResource(stuff->buffer, dbeWindowPrivResType,
    324                          (void *) pDbeWindowPriv)) {
    325             pDbeWindowPriv->IDs[add_index] = DBE_FREE_ID_ELEMENT;
    326 
    327             if (pDbeWindowPriv->nBufferIDs == 0) {
    328                 status = BadAlloc;
    329                 goto out_free;
    330             }
    331         }
    332     }
    333     else {
    334         /* The DDX buffer allocation routine failed for the first buffer of
    335          * this window.
    336          */
    337         if (pDbeWindowPriv->nBufferIDs == 0) {
    338             goto out_free;
    339         }
    340     }
    341 
    342     /* Increment the number of buffers (XIDs) associated with this window. */
    343     pDbeWindowPriv->nBufferIDs++;
    344 
    345     /* Set swap action on all calls. */
    346     pDbeWindowPriv->swapAction = stuff->swapAction;
    347 
    348     return status;
    349 
    350  out_free:
    351     dixSetPrivate(&pWin->devPrivates, dbeWindowPrivKey, NULL);
    352     free(pDbeWindowPriv);
    353     return status;
    354 
    355 }                               /* ProcDbeAllocateBackBufferName() */
    356 
    357 /******************************************************************************
    358  *
    359  * DBE DIX Procedure: ProcDbeDeallocateBackBufferName
    360  *
    361  * Description:
    362  *
    363  *     This function is for processing a DbeDeallocateBackBufferName request.
    364  *     This request frees a drawable ID that was obtained by a
    365  *     DbeAllocateBackBufferName request.
    366  *
    367  * Return Values:
    368  *
    369  *     BadBuffer - buffer to deallocate is not associated with a window
    370  *     Success
    371  *
    372  *****************************************************************************/
    373 
    374 static int
    375 ProcDbeDeallocateBackBufferName(ClientPtr client)
    376 {
    377     REQUEST(xDbeDeallocateBackBufferNameReq);
    378     DbeWindowPrivPtr pDbeWindowPriv;
    379     int rc, i;
    380     void *val;
    381 
    382     REQUEST_SIZE_MATCH(xDbeDeallocateBackBufferNameReq);
    383 
    384     /* Buffer name must be valid */
    385     rc = dixLookupResourceByType((void **) &pDbeWindowPriv, stuff->buffer,
    386                                  dbeWindowPrivResType, client,
    387                                  DixDestroyAccess);
    388     if (rc != Success)
    389         return rc;
    390 
    391     rc = dixLookupResourceByType(&val, stuff->buffer, dbeDrawableResType,
    392                                  client, DixDestroyAccess);
    393     if (rc != Success)
    394         return rc;
    395 
    396     /* Make sure that the id is valid for the window.
    397      * This is paranoid code since we already looked up the ID by type
    398      * above.
    399      */
    400 
    401     for (i = 0; i < pDbeWindowPriv->nBufferIDs; i++) {
    402         /* Loop through the ID list to find the ID. */
    403         if (pDbeWindowPriv->IDs[i] == stuff->buffer) {
    404             break;
    405         }
    406     }
    407 
    408     if (i == pDbeWindowPriv->nBufferIDs) {
    409         /* We did not find the ID in the ID list. */
    410         client->errorValue = stuff->buffer;
    411         return dbeErrorBase + DbeBadBuffer;
    412     }
    413 
    414     FreeResource(stuff->buffer, RT_NONE);
    415 
    416     return Success;
    417 
    418 }                               /* ProcDbeDeallocateBackBufferName() */
    419 
    420 /******************************************************************************
    421  *
    422  * DBE DIX Procedure: ProcDbeSwapBuffers
    423  *
    424  * Description:
    425  *
    426  *     This function is for processing a DbeSwapBuffers request.
    427  *     This request swaps the buffers for all windows listed, applying the
    428  *     appropriate swap action for each window.
    429  *
    430  * Return Values:
    431  *
    432  *     BadAlloc  - local allocation failed; this return value is not defined
    433  *                 by the protocol
    434  *     BadMatch  - a window in request is not double-buffered; a window in
    435  *                 request is listed more than once
    436  *     BadValue  - invalid swap action is specified; no swap action is
    437  *                 specified
    438  *     BadWindow - a window in request is not valid
    439  *     Success
    440  *
    441  *****************************************************************************/
    442 
    443 static int
    444 ProcDbeSwapBuffers(ClientPtr client)
    445 {
    446     REQUEST(xDbeSwapBuffersReq);
    447     WindowPtr pWin;
    448     DbeScreenPrivPtr pDbeScreenPriv;
    449     DbeSwapInfoPtr swapInfo;
    450     xDbeSwapInfo *dbeSwapInfo;
    451     int error;
    452     unsigned int i, j;
    453     unsigned int nStuff;
    454     int nStuff_i;       /* DDX API requires int for nStuff */
    455 
    456     REQUEST_AT_LEAST_SIZE(xDbeSwapBuffersReq);
    457     nStuff = stuff->n;          /* use local variable for performance. */
    458 
    459     if (nStuff == 0) {
    460         REQUEST_SIZE_MATCH(xDbeSwapBuffersReq);
    461         return Success;
    462     }
    463 
    464     if (nStuff > UINT32_MAX / sizeof(DbeSwapInfoRec))
    465         return BadAlloc;
    466     REQUEST_FIXED_SIZE(xDbeSwapBuffersReq, nStuff * sizeof(xDbeSwapInfo));
    467 
    468     /* Get to the swap info appended to the end of the request. */
    469     dbeSwapInfo = (xDbeSwapInfo *) &stuff[1];
    470 
    471     /* Allocate array to record swap information. */
    472     swapInfo = xallocarray(nStuff, sizeof(DbeSwapInfoRec));
    473     if (swapInfo == NULL) {
    474         return BadAlloc;
    475     }
    476 
    477     for (i = 0; i < nStuff; i++) {
    478         /* Check all windows to swap. */
    479 
    480         /* Each window must be a valid window - BadWindow. */
    481         error = dixLookupWindow(&pWin, dbeSwapInfo[i].window, client,
    482                                 DixWriteAccess);
    483         if (error != Success) {
    484             free(swapInfo);
    485             return error;
    486         }
    487 
    488         /* Each window must be double-buffered - BadMatch. */
    489         if (DBE_WINDOW_PRIV(pWin) == NULL) {
    490             free(swapInfo);
    491             return BadMatch;
    492         }
    493 
    494         /* Each window must only be specified once - BadMatch. */
    495         for (j = i + 1; j < nStuff; j++) {
    496             if (dbeSwapInfo[i].window == dbeSwapInfo[j].window) {
    497                 free(swapInfo);
    498                 return BadMatch;
    499             }
    500         }
    501 
    502         /* Each swap action must be valid - BadValue. */
    503         if ((dbeSwapInfo[i].swapAction != XdbeUndefined) &&
    504             (dbeSwapInfo[i].swapAction != XdbeBackground) &&
    505             (dbeSwapInfo[i].swapAction != XdbeUntouched) &&
    506             (dbeSwapInfo[i].swapAction != XdbeCopied)) {
    507             free(swapInfo);
    508             return BadValue;
    509         }
    510 
    511         /* Everything checks out OK.  Fill in the swap info array. */
    512         swapInfo[i].pWindow = pWin;
    513         swapInfo[i].swapAction = dbeSwapInfo[i].swapAction;
    514 
    515     }                           /* for (i = 0; i < nStuff; i++) */
    516 
    517     /* Call the DDX routine to perform the swap(s).  The DDX routine should
    518      * scan the swap list (swap info), swap any buffers that it knows how to
    519      * handle, delete them from the list, and update nStuff to indicate how
    520      * many windows it did not handle.
    521      *
    522      * This scheme allows a range of sophistication in the DDX SwapBuffers()
    523      * implementation.  Naive implementations could just swap the first buffer
    524      * in the list, move the last buffer to the front, decrement nStuff, and
    525      * return.  The next level of sophistication could be to scan the whole
    526      * list for windows on the same screen.  Up another level, the DDX routine
    527      * could deal with cross-screen synchronization.
    528      */
    529 
    530     nStuff_i = nStuff;
    531     while (nStuff_i > 0) {
    532         pDbeScreenPriv = DBE_SCREEN_PRIV_FROM_WINDOW(swapInfo[0].pWindow);
    533         error = (*pDbeScreenPriv->SwapBuffers) (client, &nStuff_i, swapInfo);
    534         if (error != Success) {
    535             free(swapInfo);
    536             return error;
    537         }
    538     }
    539 
    540     free(swapInfo);
    541     return Success;
    542 
    543 }                               /* ProcDbeSwapBuffers() */
    544 
    545 /******************************************************************************
    546  *
    547  * DBE DIX Procedure: ProcDbeGetVisualInfo
    548  *
    549  * Description:
    550  *
    551  *     This function is for processing a ProcDbeGetVisualInfo request.
    552  *     This request returns information about which visuals support
    553  *     double buffering.
    554  *
    555  * Return Values:
    556  *
    557  *     BadDrawable - value in screen specifiers is not a valid drawable
    558  *     Success
    559  *
    560  *****************************************************************************/
    561 
    562 static int
    563 ProcDbeGetVisualInfo(ClientPtr client)
    564 {
    565     REQUEST(xDbeGetVisualInfoReq);
    566     DbeScreenPrivPtr pDbeScreenPriv;
    567     xDbeGetVisualInfoReply rep;
    568     Drawable *drawables;
    569     DrawablePtr *pDrawables = NULL;
    570     register int i, j, rc;
    571     register int count;         /* number of visual infos in reply */
    572     register int length;        /* length of reply */
    573     ScreenPtr pScreen;
    574     XdbeScreenVisualInfo *pScrVisInfo;
    575 
    576     REQUEST_AT_LEAST_SIZE(xDbeGetVisualInfoReq);
    577     if (stuff->n > UINT32_MAX / sizeof(CARD32))
    578         return BadLength;
    579     REQUEST_FIXED_SIZE(xDbeGetVisualInfoReq, stuff->n * sizeof(CARD32));
    580 
    581     if (stuff->n > UINT32_MAX / sizeof(DrawablePtr))
    582         return BadAlloc;
    583     /* Make sure any specified drawables are valid. */
    584     if (stuff->n != 0) {
    585         if (!(pDrawables = xallocarray(stuff->n, sizeof(DrawablePtr)))) {
    586             return BadAlloc;
    587         }
    588 
    589         drawables = (Drawable *) &stuff[1];
    590 
    591         for (i = 0; i < stuff->n; i++) {
    592             rc = dixLookupDrawable(pDrawables + i, drawables[i], client, 0,
    593                                    DixGetAttrAccess);
    594             if (rc != Success) {
    595                 free(pDrawables);
    596                 return rc;
    597             }
    598         }
    599     }
    600 
    601     count = (stuff->n == 0) ? screenInfo.numScreens : stuff->n;
    602     if (!(pScrVisInfo = calloc(count, sizeof(XdbeScreenVisualInfo)))) {
    603         free(pDrawables);
    604 
    605         return BadAlloc;
    606     }
    607 
    608     length = 0;
    609 
    610     for (i = 0; i < count; i++) {
    611         pScreen = (stuff->n == 0) ? screenInfo.screens[i] :
    612             pDrawables[i]->pScreen;
    613         pDbeScreenPriv = DBE_SCREEN_PRIV(pScreen);
    614 
    615         rc = XaceHook(XACE_SCREEN_ACCESS, client, pScreen, DixGetAttrAccess);
    616         if (rc != Success)
    617             goto freeScrVisInfo;
    618 
    619         if (!(*pDbeScreenPriv->GetVisualInfo) (pScreen, &pScrVisInfo[i])) {
    620             /* We failed to alloc pScrVisInfo[i].visinfo. */
    621             rc = BadAlloc;
    622 
    623             /* Free visinfos that we allocated for previous screen infos. */
    624             goto freeScrVisInfo;
    625         }
    626 
    627         /* Account for n, number of xDbeVisInfo items in list. */
    628         length += sizeof(CARD32);
    629 
    630         /* Account for n xDbeVisInfo items */
    631         length += pScrVisInfo[i].count * sizeof(xDbeVisInfo);
    632     }
    633 
    634     rep = (xDbeGetVisualInfoReply) {
    635         .type = X_Reply,
    636         .sequenceNumber = client->sequence,
    637         .length = bytes_to_int32(length),
    638         .m = count
    639     };
    640 
    641     if (client->swapped) {
    642         swaps(&rep.sequenceNumber);
    643         swapl(&rep.length);
    644         swapl(&rep.m);
    645     }
    646 
    647     /* Send off reply. */
    648     WriteToClient(client, sizeof(xDbeGetVisualInfoReply), &rep);
    649 
    650     for (i = 0; i < count; i++) {
    651         CARD32 data32;
    652 
    653         /* For each screen in the reply, send off the visual info */
    654 
    655         /* Send off number of visuals. */
    656         data32 = (CARD32) pScrVisInfo[i].count;
    657 
    658         if (client->swapped) {
    659             swapl(&data32);
    660         }
    661 
    662         WriteToClient(client, sizeof(CARD32), &data32);
    663 
    664         /* Now send off visual info items. */
    665         for (j = 0; j < pScrVisInfo[i].count; j++) {
    666             xDbeVisInfo visInfo;
    667 
    668             /* Copy the data in the client data structure to a protocol
    669              * data structure.  We will send data to the client from the
    670              * protocol data structure.
    671              */
    672 
    673             visInfo.visualID = (CARD32) pScrVisInfo[i].visinfo[j].visual;
    674             visInfo.depth = (CARD8) pScrVisInfo[i].visinfo[j].depth;
    675             visInfo.perfLevel = (CARD8) pScrVisInfo[i].visinfo[j].perflevel;
    676 
    677             if (client->swapped) {
    678                 swapl(&visInfo.visualID);
    679 
    680                 /* We do not need to swap depth and perfLevel since they are
    681                  * already 1 byte quantities.
    682                  */
    683             }
    684 
    685             /* Write visualID(32), depth(8), perfLevel(8), and pad(16). */
    686             WriteToClient(client, 2 * sizeof(CARD32), &visInfo.visualID);
    687         }
    688     }
    689 
    690     rc = Success;
    691 
    692  freeScrVisInfo:
    693     /* Clean up memory. */
    694     for (i = 0; i < count; i++) {
    695         free(pScrVisInfo[i].visinfo);
    696     }
    697     free(pScrVisInfo);
    698 
    699     free(pDrawables);
    700 
    701     return rc;
    702 
    703 }                               /* ProcDbeGetVisualInfo() */
    704 
    705 /******************************************************************************
    706  *
    707  * DBE DIX Procedure: ProcDbeGetbackBufferAttributes
    708  *
    709  * Description:
    710  *
    711  *     This function is for processing a ProcDbeGetbackBufferAttributes
    712  *     request.  This request returns information about a back buffer.
    713  *
    714  * Return Values:
    715  *
    716  *     Success
    717  *
    718  *****************************************************************************/
    719 
    720 static int
    721 ProcDbeGetBackBufferAttributes(ClientPtr client)
    722 {
    723     REQUEST(xDbeGetBackBufferAttributesReq);
    724     xDbeGetBackBufferAttributesReply rep = {
    725         .type = X_Reply,
    726         .sequenceNumber = client->sequence,
    727         .length = 0
    728     };
    729     DbeWindowPrivPtr pDbeWindowPriv;
    730     int rc;
    731 
    732     REQUEST_SIZE_MATCH(xDbeGetBackBufferAttributesReq);
    733 
    734     rc = dixLookupResourceByType((void **) &pDbeWindowPriv, stuff->buffer,
    735                                  dbeWindowPrivResType, client,
    736                                  DixGetAttrAccess);
    737     if (rc == Success) {
    738         rep.attributes = pDbeWindowPriv->pWindow->drawable.id;
    739     }
    740     else {
    741         rep.attributes = None;
    742     }
    743 
    744     if (client->swapped) {
    745         swaps(&rep.sequenceNumber);
    746         swapl(&rep.length);
    747         swapl(&rep.attributes);
    748     }
    749 
    750     WriteToClient(client, sizeof(xDbeGetBackBufferAttributesReply), &rep);
    751     return Success;
    752 
    753 }                               /* ProcDbeGetbackBufferAttributes() */
    754 
    755 /******************************************************************************
    756  *
    757  * DBE DIX Procedure: ProcDbeDispatch
    758  *
    759  * Description:
    760  *
    761  *     This function dispatches DBE requests.
    762  *
    763  *****************************************************************************/
    764 
    765 static int
    766 ProcDbeDispatch(ClientPtr client)
    767 {
    768     REQUEST(xReq);
    769 
    770     switch (stuff->data) {
    771     case X_DbeGetVersion:
    772         return (ProcDbeGetVersion(client));
    773 
    774     case X_DbeAllocateBackBufferName:
    775         return (ProcDbeAllocateBackBufferName(client));
    776 
    777     case X_DbeDeallocateBackBufferName:
    778         return (ProcDbeDeallocateBackBufferName(client));
    779 
    780     case X_DbeSwapBuffers:
    781         return (ProcDbeSwapBuffers(client));
    782 
    783     case X_DbeBeginIdiom:
    784         return Success;
    785 
    786     case X_DbeEndIdiom:
    787         return Success;
    788 
    789     case X_DbeGetVisualInfo:
    790         return (ProcDbeGetVisualInfo(client));
    791 
    792     case X_DbeGetBackBufferAttributes:
    793         return (ProcDbeGetBackBufferAttributes(client));
    794 
    795     default:
    796         return BadRequest;
    797     }
    798 
    799 }                               /* ProcDbeDispatch() */
    800 
    801 /******************************************************************************
    802  *
    803  * DBE DIX Procedure: SProcDbeGetVersion
    804  *
    805  * Description:
    806  *
    807  *     This function is for processing a DbeGetVersion request on a swapped
    808  *     server.  This request returns the major and minor version numbers of
    809  *     this extension.
    810  *
    811  * Return Values:
    812  *
    813  *     Success
    814  *
    815  *****************************************************************************/
    816 
    817 static int _X_COLD
    818 SProcDbeGetVersion(ClientPtr client)
    819 {
    820     REQUEST(xDbeGetVersionReq);
    821 
    822     swaps(&stuff->length);
    823     return (ProcDbeGetVersion(client));
    824 
    825 }                               /* SProcDbeGetVersion() */
    826 
    827 /******************************************************************************
    828  *
    829  * DBE DIX Procedure: SProcDbeAllocateBackBufferName
    830  *
    831  * Description:
    832  *
    833  *     This function is for processing a DbeAllocateBackBufferName request on
    834  *     a swapped server.  This request allocates a drawable ID used to refer
    835  *     to the back buffer of a window.
    836  *
    837  * Return Values:
    838  *
    839  *     BadAlloc    - server can not allocate resources
    840  *     BadIDChoice - id is out of range for client; id is already in use
    841  *     BadMatch    - window is not an InputOutput window;
    842  *                   visual of window is not on list returned by
    843  *                   DBEGetVisualInfo;
    844  *     BadValue    - invalid swap action is specified
    845  *     BadWindow   - window is not a valid window
    846  *     Success
    847  *
    848  *****************************************************************************/
    849 
    850 static int _X_COLD
    851 SProcDbeAllocateBackBufferName(ClientPtr client)
    852 {
    853     REQUEST(xDbeAllocateBackBufferNameReq);
    854 
    855     swaps(&stuff->length);
    856     REQUEST_SIZE_MATCH(xDbeAllocateBackBufferNameReq);
    857 
    858     swapl(&stuff->window);
    859     swapl(&stuff->buffer);
    860     /* stuff->swapAction is a byte.  We do not need to swap this field. */
    861 
    862     return (ProcDbeAllocateBackBufferName(client));
    863 
    864 }                               /* SProcDbeAllocateBackBufferName() */
    865 
    866 /******************************************************************************
    867  *
    868  * DBE DIX Procedure: SProcDbeDeallocateBackBufferName
    869  *
    870  * Description:
    871  *
    872  *     This function is for processing a DbeDeallocateBackBufferName request
    873  *     on a swapped server.  This request frees a drawable ID that was
    874  *     obtained by a DbeAllocateBackBufferName request.
    875  *
    876  * Return Values:
    877  *
    878  *     BadBuffer - buffer to deallocate is not associated with a window
    879  *     Success
    880  *
    881  *****************************************************************************/
    882 
    883 static int _X_COLD
    884 SProcDbeDeallocateBackBufferName(ClientPtr client)
    885 {
    886     REQUEST(xDbeDeallocateBackBufferNameReq);
    887 
    888     swaps(&stuff->length);
    889     REQUEST_SIZE_MATCH(xDbeDeallocateBackBufferNameReq);
    890 
    891     swapl(&stuff->buffer);
    892 
    893     return (ProcDbeDeallocateBackBufferName(client));
    894 
    895 }                               /* SProcDbeDeallocateBackBufferName() */
    896 
    897 /******************************************************************************
    898  *
    899  * DBE DIX Procedure: SProcDbeSwapBuffers
    900  *
    901  * Description:
    902  *
    903  *     This function is for processing a DbeSwapBuffers request on a swapped
    904  *     server.  This request swaps the buffers for all windows listed,
    905  *     applying the appropriate swap action for each window.
    906  *
    907  * Return Values:
    908  *
    909  *     BadMatch  - a window in request is not double-buffered; a window in
    910  *                 request is listed more than once; all windows in request do
    911  *                 not have the same root
    912  *     BadValue  - invalid swap action is specified
    913  *     BadWindow - a window in request is not valid
    914  *     Success
    915  *
    916  *****************************************************************************/
    917 
    918 static int _X_COLD
    919 SProcDbeSwapBuffers(ClientPtr client)
    920 {
    921     REQUEST(xDbeSwapBuffersReq);
    922     unsigned int i;
    923     xDbeSwapInfo *pSwapInfo;
    924 
    925     swaps(&stuff->length);
    926     REQUEST_AT_LEAST_SIZE(xDbeSwapBuffersReq);
    927 
    928     swapl(&stuff->n);
    929     if (stuff->n > UINT32_MAX / sizeof(DbeSwapInfoRec))
    930         return BadLength;
    931     REQUEST_FIXED_SIZE(xDbeSwapBuffersReq, stuff->n * sizeof(xDbeSwapInfo));
    932 
    933     if (stuff->n != 0) {
    934         pSwapInfo = (xDbeSwapInfo *) stuff + 1;
    935 
    936         /* The swap info following the fix part of this request is a window(32)
    937          * followed by a 1 byte swap action and then 3 pad bytes.  We only need
    938          * to swap the window information.
    939          */
    940         for (i = 0; i < stuff->n; i++) {
    941             swapl(&pSwapInfo->window);
    942         }
    943     }
    944 
    945     return (ProcDbeSwapBuffers(client));
    946 
    947 }                               /* SProcDbeSwapBuffers() */
    948 
    949 /******************************************************************************
    950  *
    951  * DBE DIX Procedure: SProcDbeGetVisualInfo
    952  *
    953  * Description:
    954  *
    955  *     This function is for processing a ProcDbeGetVisualInfo request on a
    956  *     swapped server.  This request returns information about which visuals
    957  *     support double buffering.
    958  *
    959  * Return Values:
    960  *
    961  *     BadDrawable - value in screen specifiers is not a valid drawable
    962  *     Success
    963  *
    964  *****************************************************************************/
    965 
    966 static int _X_COLD
    967 SProcDbeGetVisualInfo(ClientPtr client)
    968 {
    969     REQUEST(xDbeGetVisualInfoReq);
    970 
    971     swaps(&stuff->length);
    972     REQUEST_AT_LEAST_SIZE(xDbeGetVisualInfoReq);
    973 
    974     swapl(&stuff->n);
    975     SwapRestL(stuff);
    976 
    977     return (ProcDbeGetVisualInfo(client));
    978 
    979 }                               /* SProcDbeGetVisualInfo() */
    980 
    981 /******************************************************************************
    982  *
    983  * DBE DIX Procedure: SProcDbeGetbackBufferAttributes
    984  *
    985  * Description:
    986  *
    987  *     This function is for processing a ProcDbeGetbackBufferAttributes
    988  *     request on a swapped server.  This request returns information about a
    989  *     back buffer.
    990  *
    991  * Return Values:
    992  *
    993  *     Success
    994  *
    995  *****************************************************************************/
    996 
    997 static int _X_COLD
    998 SProcDbeGetBackBufferAttributes(ClientPtr client)
    999 {
   1000     REQUEST(xDbeGetBackBufferAttributesReq);
   1001 
   1002     swaps(&stuff->length);
   1003     REQUEST_SIZE_MATCH(xDbeGetBackBufferAttributesReq);
   1004 
   1005     swapl(&stuff->buffer);
   1006 
   1007     return (ProcDbeGetBackBufferAttributes(client));
   1008 
   1009 }                               /* SProcDbeGetBackBufferAttributes() */
   1010 
   1011 /******************************************************************************
   1012  *
   1013  * DBE DIX Procedure: SProcDbeDispatch
   1014  *
   1015  * Description:
   1016  *
   1017  *     This function dispatches DBE requests on a swapped server.
   1018  *
   1019  *****************************************************************************/
   1020 
   1021 static int _X_COLD
   1022 SProcDbeDispatch(ClientPtr client)
   1023 {
   1024     REQUEST(xReq);
   1025 
   1026     switch (stuff->data) {
   1027     case X_DbeGetVersion:
   1028         return (SProcDbeGetVersion(client));
   1029 
   1030     case X_DbeAllocateBackBufferName:
   1031         return (SProcDbeAllocateBackBufferName(client));
   1032 
   1033     case X_DbeDeallocateBackBufferName:
   1034         return (SProcDbeDeallocateBackBufferName(client));
   1035 
   1036     case X_DbeSwapBuffers:
   1037         return (SProcDbeSwapBuffers(client));
   1038 
   1039     case X_DbeBeginIdiom:
   1040         return Success;
   1041 
   1042     case X_DbeEndIdiom:
   1043         return Success;
   1044 
   1045     case X_DbeGetVisualInfo:
   1046         return (SProcDbeGetVisualInfo(client));
   1047 
   1048     case X_DbeGetBackBufferAttributes:
   1049         return (SProcDbeGetBackBufferAttributes(client));
   1050 
   1051     default:
   1052         return BadRequest;
   1053     }
   1054 
   1055 }                               /* SProcDbeDispatch() */
   1056 
   1057 /******************************************************************************
   1058  *
   1059  * DBE DIX Procedure: DbeSetupBackgroundPainter
   1060  *
   1061  * Description:
   1062  *
   1063  *     This function sets up pGC to clear pixmaps.
   1064  *
   1065  * Return Values:
   1066  *
   1067  *     TRUE  - setup was successful
   1068  *     FALSE - the window's background state is NONE
   1069  *
   1070  *****************************************************************************/
   1071 
   1072 static Bool
   1073 DbeSetupBackgroundPainter(WindowPtr pWin, GCPtr pGC)
   1074 {
   1075     ChangeGCVal gcvalues[4];
   1076     int ts_x_origin, ts_y_origin;
   1077     PixUnion background;
   1078     int backgroundState;
   1079     Mask gcmask;
   1080 
   1081     /* First take care of any ParentRelative stuff by altering the
   1082      * tile/stipple origin to match the coordinates of the upper-left
   1083      * corner of the first ancestor without a ParentRelative background.
   1084      * This coordinate is, of course, negative.
   1085      */
   1086     ts_x_origin = ts_y_origin = 0;
   1087     while (pWin->backgroundState == ParentRelative) {
   1088         ts_x_origin -= pWin->origin.x;
   1089         ts_y_origin -= pWin->origin.y;
   1090 
   1091         pWin = pWin->parent;
   1092     }
   1093     backgroundState = pWin->backgroundState;
   1094     background = pWin->background;
   1095 
   1096     switch (backgroundState) {
   1097     case BackgroundPixel:
   1098         gcvalues[0].val = background.pixel;
   1099         gcvalues[1].val = FillSolid;
   1100         gcmask = GCForeground | GCFillStyle;
   1101         break;
   1102 
   1103     case BackgroundPixmap:
   1104         gcvalues[0].val = FillTiled;
   1105         gcvalues[1].ptr = background.pixmap;
   1106         gcvalues[2].val = ts_x_origin;
   1107         gcvalues[3].val = ts_y_origin;
   1108         gcmask = GCFillStyle | GCTile | GCTileStipXOrigin | GCTileStipYOrigin;
   1109         break;
   1110 
   1111     default:
   1112         /* pWin->backgroundState == None */
   1113         return FALSE;
   1114     }
   1115 
   1116     return ChangeGC(NullClient, pGC, gcmask, gcvalues) == 0;
   1117 }                               /* DbeSetupBackgroundPainter() */
   1118 
   1119 /******************************************************************************
   1120  *
   1121  * DBE DIX Procedure: DbeDrawableDelete
   1122  *
   1123  * Description:
   1124  *
   1125  *     This is the resource delete function for dbeDrawableResType.
   1126  *     It is registered when the drawable resource type is created in
   1127  *     DbeExtensionInit().
   1128  *
   1129  *     To make resource deletion simple, we do not do anything in this function
   1130  *     and leave all resource deletion to DbeWindowPrivDelete(), which will
   1131  *     eventually be called or already has been called.  Deletion functions are
   1132  *     not guaranteed to be called in any particular order.
   1133  *
   1134  *****************************************************************************/
   1135 static int
   1136 DbeDrawableDelete(void *pDrawable, XID id)
   1137 {
   1138     return Success;
   1139 
   1140 }                               /* DbeDrawableDelete() */
   1141 
   1142 /******************************************************************************
   1143  *
   1144  * DBE DIX Procedure: DbeWindowPrivDelete
   1145  *
   1146  * Description:
   1147  *
   1148  *     This is the resource delete function for dbeWindowPrivResType.
   1149  *     It is registered when the drawable resource type is created in
   1150  *     DbeExtensionInit().
   1151  *
   1152  *****************************************************************************/
   1153 static int
   1154 DbeWindowPrivDelete(void *pDbeWinPriv, XID id)
   1155 {
   1156     DbeScreenPrivPtr pDbeScreenPriv;
   1157     DbeWindowPrivPtr pDbeWindowPriv = (DbeWindowPrivPtr) pDbeWinPriv;
   1158     int i;
   1159 
   1160     /*
   1161      **************************************************************************
   1162      ** Remove the buffer ID from the ID array.
   1163      **************************************************************************
   1164      */
   1165 
   1166     /* Find the ID in the ID array. */
   1167     i = 0;
   1168     while ((i < pDbeWindowPriv->nBufferIDs) && (pDbeWindowPriv->IDs[i] != id)) {
   1169         i++;
   1170     }
   1171 
   1172     if (i == pDbeWindowPriv->nBufferIDs) {
   1173         /* We did not find the ID in the array.  We should never get here. */
   1174         return BadValue;
   1175     }
   1176 
   1177     /* Remove the ID from the array. */
   1178 
   1179     if (i < (pDbeWindowPriv->nBufferIDs - 1)) {
   1180         /* Compress the buffer ID array, overwriting the ID in the process. */
   1181         memmove(&pDbeWindowPriv->IDs[i], &pDbeWindowPriv->IDs[i + 1],
   1182                 (pDbeWindowPriv->nBufferIDs - i - 1) * sizeof(XID));
   1183     }
   1184     else {
   1185         /* We are removing the last ID in the array, in which case, the
   1186          * assignment below is all that we need to do.
   1187          */
   1188     }
   1189     pDbeWindowPriv->IDs[pDbeWindowPriv->nBufferIDs - 1] = DBE_FREE_ID_ELEMENT;
   1190 
   1191     pDbeWindowPriv->nBufferIDs--;
   1192 
   1193     /* If an extended array was allocated, then check to see if the remaining
   1194      * buffer IDs will fit in the static array.
   1195      */
   1196 
   1197     if ((pDbeWindowPriv->maxAvailableIDs > DBE_INIT_MAX_IDS) &&
   1198         (pDbeWindowPriv->nBufferIDs == DBE_INIT_MAX_IDS)) {
   1199         /* Copy the IDs back into the static array. */
   1200         memcpy(pDbeWindowPriv->initIDs, pDbeWindowPriv->IDs,
   1201                DBE_INIT_MAX_IDS * sizeof(XID));
   1202 
   1203         /* Free the extended array; use the static array. */
   1204         free(pDbeWindowPriv->IDs);
   1205         pDbeWindowPriv->IDs = pDbeWindowPriv->initIDs;
   1206         pDbeWindowPriv->maxAvailableIDs = DBE_INIT_MAX_IDS;
   1207     }
   1208 
   1209     /*
   1210      **************************************************************************
   1211      ** Perform DDX level tasks.
   1212      **************************************************************************
   1213      */
   1214 
   1215     pDbeScreenPriv = DBE_SCREEN_PRIV_FROM_WINDOW_PRIV((DbeWindowPrivPtr)
   1216                                                       pDbeWindowPriv);
   1217     (*pDbeScreenPriv->WinPrivDelete) ((DbeWindowPrivPtr) pDbeWindowPriv, id);
   1218 
   1219     /*
   1220      **************************************************************************
   1221      ** Perform miscellaneous tasks if this is the last buffer associated
   1222      ** with the window.
   1223      **************************************************************************
   1224      */
   1225 
   1226     if (pDbeWindowPriv->nBufferIDs == 0) {
   1227         /* Reset the DBE window priv pointer. */
   1228         dixSetPrivate(&pDbeWindowPriv->pWindow->devPrivates, dbeWindowPrivKey,
   1229                       NULL);
   1230 
   1231         /* We are done with the window priv. */
   1232         free(pDbeWindowPriv);
   1233     }
   1234 
   1235     return Success;
   1236 
   1237 }                               /* DbeWindowPrivDelete() */
   1238 
   1239 /******************************************************************************
   1240  *
   1241  * DBE DIX Procedure: DbeResetProc
   1242  *
   1243  * Description:
   1244  *
   1245  *     This routine is called at the end of every server generation.
   1246  *     It deallocates any memory reserved for the extension and performs any
   1247  *     other tasks related to shutting down the extension.
   1248  *
   1249  *****************************************************************************/
   1250 static void
   1251 DbeResetProc(ExtensionEntry * extEntry)
   1252 {
   1253     int i;
   1254     ScreenPtr pScreen;
   1255     DbeScreenPrivPtr pDbeScreenPriv;
   1256 
   1257     for (i = 0; i < screenInfo.numScreens; i++) {
   1258         pScreen = screenInfo.screens[i];
   1259         pDbeScreenPriv = DBE_SCREEN_PRIV(pScreen);
   1260 
   1261         if (pDbeScreenPriv) {
   1262             /* Unwrap DestroyWindow, which was wrapped in DbeExtensionInit(). */
   1263             pScreen->DestroyWindow = pDbeScreenPriv->DestroyWindow;
   1264             pScreen->PositionWindow = pDbeScreenPriv->PositionWindow;
   1265             free(pDbeScreenPriv);
   1266         }
   1267     }
   1268 }                               /* DbeResetProc() */
   1269 
   1270 /******************************************************************************
   1271  *
   1272  * DBE DIX Procedure: DbeDestroyWindow
   1273  *
   1274  * Description:
   1275  *
   1276  *     This is the wrapper for pScreen->DestroyWindow.
   1277  *     This function frees buffer resources for a window before it is
   1278  *     destroyed.
   1279  *
   1280  *****************************************************************************/
   1281 
   1282 static Bool
   1283 DbeDestroyWindow(WindowPtr pWin)
   1284 {
   1285     DbeScreenPrivPtr pDbeScreenPriv;
   1286     DbeWindowPrivPtr pDbeWindowPriv;
   1287     ScreenPtr pScreen;
   1288     Bool ret;
   1289 
   1290     /*
   1291      **************************************************************************
   1292      ** 1. Unwrap the member routine.
   1293      **************************************************************************
   1294      */
   1295 
   1296     pScreen = pWin->drawable.pScreen;
   1297     pDbeScreenPriv = DBE_SCREEN_PRIV(pScreen);
   1298     pScreen->DestroyWindow = pDbeScreenPriv->DestroyWindow;
   1299 
   1300     /*
   1301      **************************************************************************
   1302      ** 2. Do any work necessary before the member routine is called.
   1303      **
   1304      **    Call the window priv delete function for all buffer IDs associated
   1305      **    with this window.
   1306      **************************************************************************
   1307      */
   1308 
   1309     if ((pDbeWindowPriv = DBE_WINDOW_PRIV(pWin))) {
   1310         while (pDbeWindowPriv) {
   1311             /* *DbeWinPrivDelete() will free the window private and set it to
   1312              * NULL if there are no more buffer IDs associated with this
   1313              * window.
   1314              */
   1315             FreeResource(pDbeWindowPriv->IDs[0], RT_NONE);
   1316             pDbeWindowPriv = DBE_WINDOW_PRIV(pWin);
   1317         }
   1318     }
   1319 
   1320     /*
   1321      **************************************************************************
   1322      ** 3. Call the member routine, saving its result if necessary.
   1323      **************************************************************************
   1324      */
   1325 
   1326     ret = (*pScreen->DestroyWindow) (pWin);
   1327 
   1328     /*
   1329      **************************************************************************
   1330      ** 4. Rewrap the member routine, restoring the wrapper value first in case
   1331      **    the wrapper (or something that it wrapped) change this value.
   1332      **************************************************************************
   1333      */
   1334 
   1335     pDbeScreenPriv->DestroyWindow = pScreen->DestroyWindow;
   1336     pScreen->DestroyWindow = DbeDestroyWindow;
   1337 
   1338     /*
   1339      **************************************************************************
   1340      ** 5. Do any work necessary after the member routine has been called.
   1341      **
   1342      **    In this case we do not need to do anything.
   1343      **************************************************************************
   1344      */
   1345 
   1346     return ret;
   1347 
   1348 }                               /* DbeDestroyWindow() */
   1349 
   1350 /******************************************************************************
   1351  *
   1352  * DBE DIX Procedure: DbeExtensionInit
   1353  *
   1354  * Description:
   1355  *
   1356  *     Called from InitExtensions in main()
   1357  *
   1358  *****************************************************************************/
   1359 
   1360 void
   1361 DbeExtensionInit(void)
   1362 {
   1363     ExtensionEntry *extEntry;
   1364     register int i, j;
   1365     ScreenPtr pScreen = NULL;
   1366     DbeScreenPrivPtr pDbeScreenPriv;
   1367     int nStubbedScreens = 0;
   1368     Bool ddxInitSuccess;
   1369 
   1370 #ifdef PANORAMIX
   1371     if (!noPanoramiXExtension)
   1372         return;
   1373 #endif
   1374 
   1375     /* Create the resource types. */
   1376     dbeDrawableResType =
   1377         CreateNewResourceType(DbeDrawableDelete, "dbeDrawable");
   1378     if (!dbeDrawableResType)
   1379         return;
   1380     dbeDrawableResType |= RC_DRAWABLE;
   1381 
   1382     dbeWindowPrivResType =
   1383         CreateNewResourceType(DbeWindowPrivDelete, "dbeWindow");
   1384     if (!dbeWindowPrivResType)
   1385         return;
   1386 
   1387     if (!dixRegisterPrivateKey(&dbeScreenPrivKeyRec, PRIVATE_SCREEN, 0))
   1388         return;
   1389 
   1390     if (!dixRegisterPrivateKey(&dbeWindowPrivKeyRec, PRIVATE_WINDOW, 0))
   1391         return;
   1392 
   1393     for (i = 0; i < screenInfo.numScreens; i++) {
   1394         /* For each screen, set up DBE screen privates and init DIX and DDX
   1395          * interface.
   1396          */
   1397 
   1398         pScreen = screenInfo.screens[i];
   1399 
   1400         if (!(pDbeScreenPriv = malloc(sizeof(DbeScreenPrivRec)))) {
   1401             /* If we can not alloc a window or screen private,
   1402              * then free any privates that we already alloc'ed and return
   1403              */
   1404 
   1405             for (j = 0; j < i; j++) {
   1406                 free(dixLookupPrivate(&screenInfo.screens[j]->devPrivates,
   1407                                       dbeScreenPrivKey));
   1408                 dixSetPrivate(&screenInfo.screens[j]->devPrivates,
   1409                               dbeScreenPrivKey, NULL);
   1410             }
   1411             return;
   1412         }
   1413 
   1414         dixSetPrivate(&pScreen->devPrivates, dbeScreenPrivKey, pDbeScreenPriv);
   1415 
   1416         {
   1417             /* We don't have DDX support for DBE anymore */
   1418 
   1419 #ifndef DISABLE_MI_DBE_BY_DEFAULT
   1420             /* Setup DIX. */
   1421             pDbeScreenPriv->SetupBackgroundPainter = DbeSetupBackgroundPainter;
   1422 
   1423             /* Setup DDX. */
   1424             ddxInitSuccess = miDbeInit(pScreen, pDbeScreenPriv);
   1425 
   1426             /* DDX DBE initialization may have the side affect of
   1427              * reallocating pDbeScreenPriv, so we need to update it.
   1428              */
   1429             pDbeScreenPriv = DBE_SCREEN_PRIV(pScreen);
   1430 
   1431             if (ddxInitSuccess) {
   1432                 /* Wrap DestroyWindow.  The DDX initialization function
   1433                  * already wrapped PositionWindow for us.
   1434                  */
   1435 
   1436                 pDbeScreenPriv->DestroyWindow = pScreen->DestroyWindow;
   1437                 pScreen->DestroyWindow = DbeDestroyWindow;
   1438             }
   1439             else {
   1440                 /* DDX initialization failed.  Stub the screen. */
   1441                 DbeStubScreen(pDbeScreenPriv, &nStubbedScreens);
   1442             }
   1443 #else
   1444             DbeStubScreen(pDbeScreenPriv, &nStubbedScreens);
   1445 #endif
   1446 
   1447         }
   1448 
   1449     }                           /* for (i = 0; i < screenInfo.numScreens; i++) */
   1450 
   1451     if (nStubbedScreens == screenInfo.numScreens) {
   1452         /* All screens stubbed.  Clean up and return. */
   1453 
   1454         for (i = 0; i < screenInfo.numScreens; i++) {
   1455             free(dixLookupPrivate(&screenInfo.screens[i]->devPrivates,
   1456                                   dbeScreenPrivKey));
   1457             dixSetPrivate(&pScreen->devPrivates, dbeScreenPrivKey, NULL);
   1458         }
   1459         return;
   1460     }
   1461 
   1462     /* Now add the extension. */
   1463     extEntry = AddExtension(DBE_PROTOCOL_NAME, DbeNumberEvents,
   1464                             DbeNumberErrors, ProcDbeDispatch, SProcDbeDispatch,
   1465                             DbeResetProc, StandardMinorOpcode);
   1466 
   1467     dbeErrorBase = extEntry->errorBase;
   1468     SetResourceTypeErrorValue(dbeWindowPrivResType,
   1469                               dbeErrorBase + DbeBadBuffer);
   1470     SetResourceTypeErrorValue(dbeDrawableResType, dbeErrorBase + DbeBadBuffer);
   1471 
   1472 }                               /* DbeExtensionInit() */