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