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