dbe.c revision 6e78d31f
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 */
56DevPrivateKeyRec dbeScreenPrivKeyRec;
57DevPrivateKeyRec dbeWindowPrivKeyRec;
58
59/* These are globals for use by DDX */
60RESTYPE dbeDrawableResType;
61RESTYPE dbeWindowPrivResType;
62
63/* Used to generate DBE's BadBuffer error. */
64static 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
77static void
78DbeStubScreen(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
115static int
116ProcDbeGetVersion(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
162static int
163ProcDbeAllocateBackBufferName(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
374static int
375ProcDbeDeallocateBackBufferName(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
443static int
444ProcDbeSwapBuffers(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
562static int
563ProcDbeGetVisualInfo(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
720static int
721ProcDbeGetBackBufferAttributes(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
765static int
766ProcDbeDispatch(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
817static int
818SProcDbeGetVersion(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
850static int
851SProcDbeAllocateBackBufferName(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
883static int
884SProcDbeDeallocateBackBufferName(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
918static int
919SProcDbeSwapBuffers(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
966static int
967SProcDbeGetVisualInfo(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
997static int
998SProcDbeGetBackBufferAttributes(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
1021static int
1022SProcDbeDispatch(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
1072static Bool
1073DbeSetupBackgroundPainter(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 deleteion 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 *****************************************************************************/
1135static int
1136DbeDrawableDelete(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 *****************************************************************************/
1153static int
1154DbeWindowPrivDelete(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         * assignement 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 *****************************************************************************/
1250static void
1251DbeResetProc(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
1282static Bool
1283DbeDestroyWindow(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
1360void
1361DbeExtensionInit(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() */
1473