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
DbeStubScreen(DbeScreenPrivPtr pDbeScreenPriv,int * nStubbedScreens)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
ProcDbeGetVersion(ClientPtr client)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
ProcDbeAllocateBackBufferName(ClientPtr client)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
ProcDbeDeallocateBackBufferName(ClientPtr client)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
ProcDbeSwapBuffers(ClientPtr client)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
ProcDbeGetVisualInfo(ClientPtr client)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
ProcDbeGetBackBufferAttributes(ClientPtr client)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
ProcDbeDispatch(ClientPtr client)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
SProcDbeGetVersion(ClientPtr client)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
SProcDbeAllocateBackBufferName(ClientPtr client)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
SProcDbeDeallocateBackBufferName(ClientPtr client)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
SProcDbeSwapBuffers(ClientPtr client)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
SProcDbeGetVisualInfo(ClientPtr client)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
SProcDbeGetBackBufferAttributes(ClientPtr client)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
SProcDbeDispatch(ClientPtr client)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
DbeSetupBackgroundPainter(WindowPtr pWin,GCPtr pGC)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
DbeDrawableDelete(void * pDrawable,XID id)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
DbeWindowPrivDelete(void * pDbeWinPriv,XID id)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
DbeResetProc(ExtensionEntry * extEntry)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
DbeDestroyWindow(WindowPtr pWin)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
DbeExtensionInit(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() */
1473