dbe.c revision 706f2543
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
670    if (stuff->n > UINT32_MAX / sizeof(DrawablePtr))
671	    return BadAlloc;
672    /* Make sure any specified drawables are valid. */
673    if (stuff->n != 0)
674    {
675        if (!(pDrawables = (DrawablePtr *)malloc(stuff->n *
676                                                 sizeof(DrawablePtr))))
677        {
678            return BadAlloc;
679        }
680
681        drawables = (Drawable *)&stuff[1];
682
683        for (i = 0; i < stuff->n; i++)
684        {
685	    rc = dixLookupDrawable(pDrawables+i, drawables[i], client, 0,
686				   DixGetAttrAccess);
687	    if (rc != Success) {
688                free(pDrawables);
689                return rc;
690            }
691        }
692    }
693
694    count = (stuff->n == 0) ? screenInfo.numScreens : stuff->n;
695    if (!(pScrVisInfo = calloc(count, sizeof(XdbeScreenVisualInfo))))
696    {
697        free(pDrawables);
698
699        return BadAlloc;
700    }
701
702    length = 0;
703
704    for (i = 0; i < count; i++)
705    {
706        pScreen = (stuff->n == 0) ? screenInfo.screens[i] :
707                                    pDrawables[i]->pScreen;
708        pDbeScreenPriv = DBE_SCREEN_PRIV(pScreen);
709
710	rc = XaceHook(XACE_SCREEN_ACCESS, client, pScreen, DixGetAttrAccess);
711        if (rc != Success)
712            goto freeScrVisInfo;
713
714        if (!(*pDbeScreenPriv->GetVisualInfo)(pScreen, &pScrVisInfo[i]))
715        {
716            /* We failed to alloc pScrVisInfo[i].visinfo. */
717            rc = BadAlloc;
718
719            /* Free visinfos that we allocated for previous screen infos.*/
720            goto freeScrVisInfo;
721        }
722
723        /* Account for n, number of xDbeVisInfo items in list. */
724        length += sizeof(CARD32);
725
726        /* Account for n xDbeVisInfo items */
727        length += pScrVisInfo[i].count * sizeof(xDbeVisInfo);
728    }
729
730    rep.type           = X_Reply;
731    rep.sequenceNumber = client->sequence;
732    rep.length         = bytes_to_int32(length);
733    rep.m              = count;
734
735    if (client->swapped)
736    {
737        swaps(&rep.sequenceNumber, n);
738        swapl(&rep.length, n);
739        swapl(&rep.m, n);
740    }
741
742    /* Send off reply. */
743    WriteToClient(client, sizeof(xDbeGetVisualInfoReply), (char *)&rep);
744
745    for (i = 0; i < count; i++)
746    {
747        CARD32	data32;
748
749        /* For each screen in the reply, send off the visual info */
750
751        /* Send off number of visuals. */
752        data32 = (CARD32)pScrVisInfo[i].count;
753
754        if (client->swapped)
755        {
756            swapl(&data32, n);
757        }
758
759        WriteToClient(client, sizeof(CARD32), (char *)&data32);
760
761        /* Now send off visual info items. */
762        for (j = 0; j < pScrVisInfo[i].count; j++)
763        {
764            xDbeVisInfo		visInfo;
765
766            /* Copy the data in the client data structure to a protocol
767             * data structure.  We will send data to the client from the
768             * protocol data structure.
769             */
770
771            visInfo.visualID  = (CARD32)pScrVisInfo[i].visinfo[j].visual;
772            visInfo.depth     = (CARD8) pScrVisInfo[i].visinfo[j].depth;
773            visInfo.perfLevel = (CARD8) pScrVisInfo[i].visinfo[j].perflevel;
774
775            if (client->swapped)
776            {
777                swapl(&visInfo.visualID, n);
778
779                /* We do not need to swap depth and perfLevel since they are
780                 * already 1 byte quantities.
781                 */
782            }
783
784            /* Write visualID(32), depth(8), perfLevel(8), and pad(16). */
785            WriteToClient(client, 2*sizeof(CARD32), (char *)&visInfo.visualID);
786        }
787    }
788
789    rc = Success;
790
791  freeScrVisInfo:
792    /* Clean up memory. */
793    for (i = 0; i < count; i++)
794    {
795        free(pScrVisInfo[i].visinfo);
796    }
797    free(pScrVisInfo);
798
799    free(pDrawables);
800
801    return rc;
802
803} /* ProcDbeGetVisualInfo() */
804
805
806/******************************************************************************
807 *
808 * DBE DIX Procedure: ProcDbeGetbackBufferAttributes
809 *
810 * Description:
811 *
812 *     This function is for processing a ProcDbeGetbackBufferAttributes
813 *     request.  This request returns information about a back buffer.
814 *
815 * Return Values:
816 *
817 *     Success
818 *
819 *****************************************************************************/
820
821static int
822ProcDbeGetBackBufferAttributes(ClientPtr client)
823{
824    REQUEST(xDbeGetBackBufferAttributesReq);
825    xDbeGetBackBufferAttributesReply	rep;
826    DbeWindowPrivPtr			pDbeWindowPriv;
827    int					rc, n;
828
829
830    REQUEST_SIZE_MATCH(xDbeGetBackBufferAttributesReq);
831
832    rc = dixLookupResourceByType((pointer *)&pDbeWindowPriv, stuff->buffer,
833				 dbeWindowPrivResType, client,
834				 DixGetAttrAccess);
835    if (rc == Success)
836    {
837        rep.attributes = pDbeWindowPriv->pWindow->drawable.id;
838    }
839    else
840    {
841        rep.attributes = None;
842    }
843
844    rep.type           = X_Reply;
845    rep.sequenceNumber = client->sequence;
846    rep.length         = 0;
847
848    if (client->swapped)
849    {
850        swaps(&rep.sequenceNumber, n);
851        swapl(&rep.length, n);
852        swapl(&rep.attributes, n);
853    }
854
855    WriteToClient(client, sizeof(xDbeGetBackBufferAttributesReply),
856                  (char *)&rep);
857    return Success;
858
859} /* ProcDbeGetbackBufferAttributes() */
860
861
862/******************************************************************************
863 *
864 * DBE DIX Procedure: ProcDbeDispatch
865 *
866 * Description:
867 *
868 *     This function dispatches DBE requests.
869 *
870 *****************************************************************************/
871
872static int
873ProcDbeDispatch(ClientPtr client)
874{
875    REQUEST(xReq);
876
877
878    switch (stuff->data)
879    {
880        case X_DbeGetVersion:
881            return(ProcDbeGetVersion(client));
882
883        case X_DbeAllocateBackBufferName:
884            return(ProcDbeAllocateBackBufferName(client));
885
886        case X_DbeDeallocateBackBufferName:
887            return(ProcDbeDeallocateBackBufferName(client));
888
889        case X_DbeSwapBuffers:
890            return(ProcDbeSwapBuffers(client));
891
892        case X_DbeBeginIdiom:
893            return(ProcDbeBeginIdiom(client));
894
895        case X_DbeEndIdiom:
896            return Success;
897
898        case X_DbeGetVisualInfo:
899            return(ProcDbeGetVisualInfo(client));
900
901        case X_DbeGetBackBufferAttributes:
902            return(ProcDbeGetBackBufferAttributes(client));
903
904        default:
905            return BadRequest;
906    }
907
908} /* ProcDbeDispatch() */
909
910
911/******************************************************************************
912 *
913 * DBE DIX Procedure: SProcDbeGetVersion
914 *
915 * Description:
916 *
917 *     This function is for processing a DbeGetVersion request on a swapped
918 *     server.  This request returns the major and minor version numbers of
919 *     this extension.
920 *
921 * Return Values:
922 *
923 *     Success
924 *
925 *****************************************************************************/
926
927static int
928SProcDbeGetVersion(ClientPtr client)
929{
930    REQUEST(xDbeGetVersionReq);
931    register int	n;
932
933
934    swaps(&stuff->length, n);
935    return(ProcDbeGetVersion(client));
936
937} /* SProcDbeGetVersion() */
938
939
940/******************************************************************************
941 *
942 * DBE DIX Procedure: SProcDbeAllocateBackBufferName
943 *
944 * Description:
945 *
946 *     This function is for processing a DbeAllocateBackBufferName request on
947 *     a swapped server.  This request allocates a drawable ID used to refer
948 *     to the back buffer of a window.
949 *
950 * Return Values:
951 *
952 *     BadAlloc    - server can not allocate resources
953 *     BadIDChoice - id is out of range for client; id is already in use
954 *     BadMatch    - window is not an InputOutput window;
955 *                   visual of window is not on list returned by
956 *                   DBEGetVisualInfo;
957 *     BadValue    - invalid swap action is specified
958 *     BadWindow   - window is not a valid window
959 *     Success
960 *
961 *****************************************************************************/
962
963static int
964SProcDbeAllocateBackBufferName(ClientPtr client)
965{
966    REQUEST(xDbeAllocateBackBufferNameReq);
967    register int	n;
968
969    swaps(&stuff->length, n);
970    REQUEST_SIZE_MATCH(xDbeAllocateBackBufferNameReq);
971
972    swapl(&stuff->window, n);
973    swapl(&stuff->buffer, n);
974    /* stuff->swapAction is a byte.  We do not need to swap this field. */
975
976    return(ProcDbeAllocateBackBufferName(client));
977
978} /* SProcDbeAllocateBackBufferName() */
979
980
981/******************************************************************************
982 *
983 * DBE DIX Procedure: SProcDbeDeallocateBackBufferName
984 *
985 * Description:
986 *
987 *     This function is for processing a DbeDeallocateBackBufferName request
988 *     on a swapped server.  This request frees a drawable ID that was
989 *     obtained by a DbeAllocateBackBufferName request.
990 *
991 * Return Values:
992 *
993 *     BadBuffer - buffer to deallocate is not associated with a window
994 *     Success
995 *
996 *****************************************************************************/
997
998static int
999SProcDbeDeallocateBackBufferName(ClientPtr client)
1000{
1001    REQUEST (xDbeDeallocateBackBufferNameReq);
1002    register int	n;
1003
1004
1005    swaps(&stuff->length, n);
1006    REQUEST_SIZE_MATCH(xDbeDeallocateBackBufferNameReq);
1007
1008    swapl(&stuff->buffer, n);
1009
1010    return(ProcDbeDeallocateBackBufferName(client));
1011
1012} /* SProcDbeDeallocateBackBufferName() */
1013
1014
1015/******************************************************************************
1016 *
1017 * DBE DIX Procedure: SProcDbeSwapBuffers
1018 *
1019 * Description:
1020 *
1021 *     This function is for processing a DbeSwapBuffers request on a swapped
1022 *     server.  This request swaps the buffers for all windows listed,
1023 *     applying the appropriate swap action for each window.
1024 *
1025 * Return Values:
1026 *
1027 *     BadMatch  - a window in request is not double-buffered; a window in
1028 *                 request is listed more than once; all windows in request do
1029 *                 not have the same root
1030 *     BadValue  - invalid swap action is specified
1031 *     BadWindow - a window in request is not valid
1032 *     Success
1033 *
1034 *****************************************************************************/
1035
1036static int
1037SProcDbeSwapBuffers(ClientPtr client)
1038{
1039    REQUEST(xDbeSwapBuffersReq);
1040    unsigned int	i, n;
1041    xDbeSwapInfo	*pSwapInfo;
1042
1043
1044    swaps(&stuff->length, n);
1045    REQUEST_AT_LEAST_SIZE(xDbeSwapBuffersReq);
1046
1047    swapl(&stuff->n, n);
1048    if (stuff->n > UINT32_MAX / sizeof(DbeSwapInfoRec))
1049        return BadAlloc;
1050    REQUEST_FIXED_SIZE(xDbeSwapBuffersReq, stuff->n * sizeof(xDbeSwapInfo));
1051
1052    if (stuff->n != 0)
1053    {
1054        pSwapInfo = (xDbeSwapInfo *)stuff+1;
1055
1056        /* The swap info following the fix part of this request is a window(32)
1057         * followed by a 1 byte swap action and then 3 pad bytes.  We only need
1058         * to swap the window information.
1059         */
1060        for (i = 0; i < stuff->n; i++)
1061        {
1062            swapl(&pSwapInfo->window, n);
1063        }
1064    }
1065
1066    return(ProcDbeSwapBuffers(client));
1067
1068} /* SProcDbeSwapBuffers() */
1069
1070
1071/******************************************************************************
1072 *
1073 * DBE DIX Procedure: SProcDbeBeginIdiom
1074 *
1075 * Description:
1076 *
1077 *     This function is for processing a DbeBeginIdiom request on a swapped
1078 *     server.  This request informs the server that a complex swap will
1079 *     immediately follow this request.
1080 *
1081 * Return Values:
1082 *
1083 *     Success
1084 *
1085 *****************************************************************************/
1086
1087static int
1088SProcDbeBeginIdiom(ClientPtr client)
1089{
1090    REQUEST(xDbeBeginIdiomReq);
1091    register int	n;
1092
1093    swaps(&stuff->length, n);
1094    return(ProcDbeBeginIdiom(client));
1095
1096} /* SProcDbeBeginIdiom() */
1097
1098
1099/******************************************************************************
1100 *
1101 * DBE DIX Procedure: SProcDbeGetVisualInfo
1102 *
1103 * Description:
1104 *
1105 *     This function is for processing a ProcDbeGetVisualInfo request on a
1106 *     swapped server.  This request returns information about which visuals
1107 *     support double buffering.
1108 *
1109 * Return Values:
1110 *
1111 *     BadDrawable - value in screen specifiers is not a valid drawable
1112 *     Success
1113 *
1114 *****************************************************************************/
1115
1116static int
1117SProcDbeGetVisualInfo(ClientPtr client)
1118{
1119    REQUEST(xDbeGetVisualInfoReq);
1120    register int	n;
1121
1122
1123    swaps(&stuff->length, n);
1124    REQUEST_AT_LEAST_SIZE(xDbeGetVisualInfoReq);
1125
1126    swapl(&stuff->n, n);
1127    SwapRestL(stuff);
1128
1129    return(ProcDbeGetVisualInfo(client));
1130
1131} /* SProcDbeGetVisualInfo() */
1132
1133
1134/******************************************************************************
1135 *
1136 * DBE DIX Procedure: SProcDbeGetbackBufferAttributes
1137 *
1138 * Description:
1139 *
1140 *     This function is for processing a ProcDbeGetbackBufferAttributes
1141 *     request on a swapped server.  This request returns information about a
1142 *     back buffer.
1143 *
1144 * Return Values:
1145 *
1146 *     Success
1147 *
1148 *****************************************************************************/
1149
1150static int
1151SProcDbeGetBackBufferAttributes(ClientPtr client)
1152{
1153    REQUEST (xDbeGetBackBufferAttributesReq);
1154    register int	n;
1155
1156    swaps(&stuff->length, n);
1157    REQUEST_SIZE_MATCH(xDbeGetBackBufferAttributesReq);
1158
1159    swapl(&stuff->buffer, n);
1160
1161    return(ProcDbeGetBackBufferAttributes(client));
1162
1163} /* SProcDbeGetBackBufferAttributes() */
1164
1165
1166/******************************************************************************
1167 *
1168 * DBE DIX Procedure: SProcDbeDispatch
1169 *
1170 * Description:
1171 *
1172 *     This function dispatches DBE requests on a swapped server.
1173 *
1174 *****************************************************************************/
1175
1176static int
1177SProcDbeDispatch(ClientPtr client)
1178{
1179    REQUEST(xReq);
1180
1181
1182    switch (stuff->data)
1183    {
1184        case X_DbeGetVersion:
1185            return(SProcDbeGetVersion(client));
1186
1187        case X_DbeAllocateBackBufferName:
1188            return(SProcDbeAllocateBackBufferName(client));
1189
1190        case X_DbeDeallocateBackBufferName:
1191            return(SProcDbeDeallocateBackBufferName(client));
1192
1193        case X_DbeSwapBuffers:
1194            return(SProcDbeSwapBuffers(client));
1195
1196        case X_DbeBeginIdiom:
1197            return(SProcDbeBeginIdiom(client));
1198
1199        case X_DbeEndIdiom:
1200            return Success;
1201
1202        case X_DbeGetVisualInfo:
1203            return(SProcDbeGetVisualInfo(client));
1204
1205        case X_DbeGetBackBufferAttributes:
1206            return(SProcDbeGetBackBufferAttributes(client));
1207
1208        default:
1209            return BadRequest;
1210    }
1211
1212} /* SProcDbeDispatch() */
1213
1214
1215/******************************************************************************
1216 *
1217 * DBE DIX Procedure: DbeSetupBackgroundPainter
1218 *
1219 * Description:
1220 *
1221 *     This function sets up pGC to clear pixmaps.
1222 *
1223 * Return Values:
1224 *
1225 *     TRUE  - setup was successful
1226 *     FALSE - the window's background state is NONE
1227 *
1228 *****************************************************************************/
1229
1230static Bool
1231DbeSetupBackgroundPainter(WindowPtr pWin, GCPtr pGC)
1232{
1233    ChangeGCVal	gcvalues[4];
1234    int		ts_x_origin, ts_y_origin;
1235    PixUnion	background;
1236    int		backgroundState;
1237    Mask	gcmask;
1238
1239
1240    /* First take care of any ParentRelative stuff by altering the
1241     * tile/stipple origin to match the coordinates of the upper-left
1242     * corner of the first ancestor without a ParentRelative background.
1243     * This coordinate is, of course, negative.
1244     */
1245    ts_x_origin = ts_y_origin = 0;
1246    while (pWin->backgroundState == ParentRelative)
1247    {
1248        ts_x_origin -= pWin->origin.x;
1249        ts_y_origin -= pWin->origin.y;
1250
1251        pWin = pWin->parent;
1252    }
1253    backgroundState = pWin->backgroundState;
1254    background      = pWin->background;
1255
1256    switch (backgroundState)
1257    {
1258        case BackgroundPixel:
1259            gcvalues[0].val = background.pixel;
1260            gcvalues[1].val = FillSolid;
1261            gcmask = GCForeground|GCFillStyle;
1262            break;
1263
1264        case BackgroundPixmap:
1265            gcvalues[0].val = FillTiled;
1266            gcvalues[1].ptr = background.pixmap;
1267            gcvalues[2].val = ts_x_origin;
1268            gcvalues[3].val = ts_y_origin;
1269            gcmask = GCFillStyle|GCTile|GCTileStipXOrigin|GCTileStipYOrigin;
1270            break;
1271
1272        default:
1273            /* pWin->backgroundState == None */
1274            return FALSE;
1275    }
1276
1277    return ChangeGC(NullClient, pGC, gcmask, gcvalues) == 0;
1278} /* DbeSetupBackgroundPainter() */
1279
1280
1281/******************************************************************************
1282 *
1283 * DBE DIX Procedure: DbeDrawableDelete
1284 *
1285 * Description:
1286 *
1287 *     This is the resource delete function for dbeDrawableResType.
1288 *     It is registered when the drawable resource type is created in
1289 *     DbeExtensionInit().
1290 *
1291 *     To make resource deletion simple, we do not do anything in this function
1292 *     and leave all resource deleteion to DbeWindowPrivDelete(), which will
1293 *     eventually be called or already has been called.  Deletion functions are
1294 *     not guaranteed to be called in any particular order.
1295 *
1296 *****************************************************************************/
1297static int
1298DbeDrawableDelete(pointer pDrawable, XID id)
1299{
1300    return Success;
1301
1302} /* DbeDrawableDelete() */
1303
1304
1305/******************************************************************************
1306 *
1307 * DBE DIX Procedure: DbeWindowPrivDelete
1308 *
1309 * Description:
1310 *
1311 *     This is the resource delete function for dbeWindowPrivResType.
1312 *     It is registered when the drawable resource type is created in
1313 *     DbeExtensionInit().
1314 *
1315 *****************************************************************************/
1316static int
1317DbeWindowPrivDelete(pointer pDbeWinPriv, XID id)
1318{
1319    DbeScreenPrivPtr	pDbeScreenPriv;
1320    DbeWindowPrivPtr	pDbeWindowPriv = (DbeWindowPrivPtr)pDbeWinPriv;
1321    int			i;
1322
1323
1324    /*
1325     **************************************************************************
1326     ** Remove the buffer ID from the ID array.
1327     **************************************************************************
1328     */
1329
1330    /* Find the ID in the ID array. */
1331    i = 0;
1332    while ((i < pDbeWindowPriv->nBufferIDs) && (pDbeWindowPriv->IDs[i] != id))
1333    {
1334        i++;
1335    }
1336
1337    if (i == pDbeWindowPriv->nBufferIDs)
1338    {
1339        /* We did not find the ID in the array.  We should never get here. */
1340        return BadValue;
1341    }
1342
1343    /* Remove the ID from the array. */
1344
1345    if (i < (pDbeWindowPriv->nBufferIDs - 1))
1346    {
1347        /* Compress the buffer ID array, overwriting the ID in the process. */
1348        memmove(&pDbeWindowPriv->IDs[i], &pDbeWindowPriv->IDs[i+1],
1349            (pDbeWindowPriv->nBufferIDs - i - 1) * sizeof(XID));
1350    }
1351    else
1352    {
1353        /* We are removing the last ID in the array, in which case, the
1354         * assignement below is all that we need to do.
1355         */
1356    }
1357    pDbeWindowPriv->IDs[pDbeWindowPriv->nBufferIDs - 1] = DBE_FREE_ID_ELEMENT;
1358
1359    pDbeWindowPriv->nBufferIDs--;
1360
1361    /* If an extended array was allocated, then check to see if the remaining
1362     * buffer IDs will fit in the static array.
1363     */
1364
1365    if ((pDbeWindowPriv->maxAvailableIDs >  DBE_INIT_MAX_IDS) &&
1366        (pDbeWindowPriv->nBufferIDs      == DBE_INIT_MAX_IDS))
1367    {
1368        /* Copy the IDs back into the static array. */
1369        memcpy(pDbeWindowPriv->initIDs, pDbeWindowPriv->IDs,
1370               DBE_INIT_MAX_IDS * sizeof(XID));
1371
1372        /* Free the extended array; use the static array. */
1373        free(pDbeWindowPriv->IDs);
1374        pDbeWindowPriv->IDs = pDbeWindowPriv->initIDs;
1375        pDbeWindowPriv->maxAvailableIDs = DBE_INIT_MAX_IDS;
1376    }
1377
1378
1379    /*
1380     **************************************************************************
1381     ** Perform DDX level tasks.
1382     **************************************************************************
1383     */
1384
1385    pDbeScreenPriv = DBE_SCREEN_PRIV_FROM_WINDOW_PRIV(
1386                         (DbeWindowPrivPtr)pDbeWindowPriv);
1387    (*pDbeScreenPriv->WinPrivDelete)((DbeWindowPrivPtr)pDbeWindowPriv, id);
1388
1389
1390    /*
1391     **************************************************************************
1392     ** Perform miscellaneous tasks if this is the last buffer associated
1393     ** with the window.
1394     **************************************************************************
1395     */
1396
1397    if (pDbeWindowPriv->nBufferIDs == 0)
1398    {
1399        /* Reset the DBE window priv pointer. */
1400	dixSetPrivate(&pDbeWindowPriv->pWindow->devPrivates, dbeWindowPrivKey,
1401		      NULL);
1402
1403        /* We are done with the window priv. */
1404	dixFreeObjectWithPrivates(pDbeWindowPriv, PRIVATE_DBE_WINDOW);
1405    }
1406
1407    return Success;
1408
1409} /* DbeWindowPrivDelete() */
1410
1411
1412/******************************************************************************
1413 *
1414 * DBE DIX Procedure: DbeResetProc
1415 *
1416 * Description:
1417 *
1418 *     This routine is called at the end of every server generation.
1419 *     It deallocates any memory reserved for the extension and performs any
1420 *     other tasks related to shutting down the extension.
1421 *
1422 *****************************************************************************/
1423static void
1424DbeResetProc(ExtensionEntry *extEntry)
1425{
1426    int			i;
1427    ScreenPtr		pScreen;
1428    DbeScreenPrivPtr	pDbeScreenPriv;
1429
1430    for (i = 0; i < screenInfo.numScreens; i++)
1431    {
1432	pScreen = screenInfo.screens[i];
1433	pDbeScreenPriv = DBE_SCREEN_PRIV(pScreen);
1434
1435	if (pDbeScreenPriv)
1436	{
1437            /* Unwrap DestroyWindow, which was wrapped in DbeExtensionInit().*/
1438            pScreen->DestroyWindow = pDbeScreenPriv->DestroyWindow;
1439
1440	    if (pDbeScreenPriv->ResetProc)
1441		(*pDbeScreenPriv->ResetProc)(pScreen);
1442
1443	    free(pDbeScreenPriv);
1444	}
1445    }
1446} /* DbeResetProc() */
1447
1448
1449/******************************************************************************
1450 *
1451 * DBE DIX Procedure: DbeDestroyWindow
1452 *
1453 * Description:
1454 *
1455 *     This is the wrapper for pScreen->DestroyWindow.
1456 *     This function frees buffer resources for a window before it is
1457 *     destroyed.
1458 *
1459 *****************************************************************************/
1460
1461static Bool
1462DbeDestroyWindow(WindowPtr pWin)
1463{
1464    DbeScreenPrivPtr	pDbeScreenPriv;
1465    DbeWindowPrivPtr	pDbeWindowPriv;
1466    ScreenPtr		pScreen;
1467    Bool		ret;
1468
1469
1470    /*
1471     **************************************************************************
1472     ** 1. Unwrap the member routine.
1473     **************************************************************************
1474     */
1475
1476    pScreen                = pWin->drawable.pScreen;
1477    pDbeScreenPriv         = DBE_SCREEN_PRIV(pScreen);
1478    pScreen->DestroyWindow = pDbeScreenPriv->DestroyWindow;
1479
1480    /*
1481     **************************************************************************
1482     ** 2. Do any work necessary before the member routine is called.
1483     **
1484     **    Call the window priv delete function for all buffer IDs associated
1485     **    with this window.
1486     **************************************************************************
1487     */
1488
1489    if ((pDbeWindowPriv = DBE_WINDOW_PRIV(pWin)))
1490    {
1491        while (pDbeWindowPriv)
1492        {
1493            /* *DbeWinPrivDelete() will free the window private and set it to
1494             * NULL if there are no more buffer IDs associated with this
1495             * window.
1496             */
1497            FreeResource(pDbeWindowPriv->IDs[0], RT_NONE);
1498            pDbeWindowPriv = DBE_WINDOW_PRIV(pWin);
1499        }
1500    }
1501
1502    /*
1503     **************************************************************************
1504     ** 3. Call the member routine, saving its result if necessary.
1505     **************************************************************************
1506     */
1507
1508    ret = (*pScreen->DestroyWindow)(pWin);
1509
1510    /*
1511     **************************************************************************
1512     ** 4. Rewrap the member routine, restoring the wrapper value first in case
1513     **    the wrapper (or something that it wrapped) change this value.
1514     **************************************************************************
1515     */
1516
1517    pDbeScreenPriv->DestroyWindow = pScreen->DestroyWindow;
1518    pScreen->DestroyWindow = DbeDestroyWindow;
1519
1520    /*
1521     **************************************************************************
1522     ** 5. Do any work necessary after the member routine has been called.
1523     **
1524     **    In this case we do not need to do anything.
1525     **************************************************************************
1526     */
1527
1528    return ret;
1529
1530} /* DbeDestroyWindow() */
1531
1532
1533/******************************************************************************
1534 *
1535 * DBE DIX Procedure: DbeExtensionInit
1536 *
1537 * Description:
1538 *
1539 *     Called from InitExtensions in main()
1540 *
1541 *****************************************************************************/
1542
1543void
1544DbeExtensionInit(void)
1545{
1546    ExtensionEntry	*extEntry;
1547    register int	i, j;
1548    ScreenPtr		pScreen = NULL;
1549    DbeScreenPrivPtr	pDbeScreenPriv;
1550    int			nStubbedScreens = 0;
1551    Bool		ddxInitSuccess;
1552
1553#ifdef PANORAMIX
1554    if(!noPanoramiXExtension) return;
1555#endif
1556
1557    /* Create the resource types. */
1558    dbeDrawableResType =
1559        CreateNewResourceType(DbeDrawableDelete, "dbeDrawable");
1560    if (!dbeDrawableResType)
1561	return;
1562    dbeDrawableResType |= RC_DRAWABLE;
1563
1564    dbeWindowPrivResType =
1565        CreateNewResourceType(DbeWindowPrivDelete, "dbeWindow");
1566    if (!dbeWindowPrivResType)
1567	return;
1568
1569    if (!dixRegisterPrivateKey(&dbeScreenPrivKeyRec, PRIVATE_SCREEN, 0))
1570	return;
1571
1572    if (!dixRegisterPrivateKey(&dbeWindowPrivKeyRec, PRIVATE_WINDOW, 0))
1573	return;
1574
1575    for (i = 0; i < screenInfo.numScreens; i++)
1576    {
1577        /* For each screen, set up DBE screen privates and init DIX and DDX
1578         * interface.
1579         */
1580
1581	pScreen = screenInfo.screens[i];
1582
1583	if (!(pDbeScreenPriv = malloc (sizeof (DbeScreenPrivRec))))
1584	{
1585            /* If we can not alloc a window or screen private,
1586             * then free any privates that we already alloc'ed and return
1587             */
1588
1589	    for (j = 0; j < i; j++)
1590	    {
1591		free(dixLookupPrivate(&screenInfo.screens[j]->devPrivates,
1592				       dbeScreenPrivKey));
1593		dixSetPrivate(&screenInfo.screens[j]->devPrivates,
1594			      dbeScreenPrivKey, NULL);
1595	    }
1596	    return;
1597	}
1598
1599	dixSetPrivate(&pScreen->devPrivates, dbeScreenPrivKey, pDbeScreenPriv);
1600
1601        {
1602            /* We don't have DDX support for DBE anymore */
1603
1604#ifndef DISABLE_MI_DBE_BY_DEFAULT
1605            /* Setup DIX. */
1606            pDbeScreenPriv->SetupBackgroundPainter = DbeSetupBackgroundPainter;
1607
1608            /* Setup DDX. */
1609            ddxInitSuccess = miDbeInit(pScreen, pDbeScreenPriv);
1610
1611            /* DDX DBE initialization may have the side affect of
1612             * reallocating pDbeScreenPriv, so we need to update it.
1613             */
1614            pDbeScreenPriv = DBE_SCREEN_PRIV(pScreen);
1615
1616            if (ddxInitSuccess)
1617            {
1618                /* Wrap DestroyWindow.  The DDX initialization function
1619                 * already wrapped PositionWindow for us.
1620                 */
1621
1622                pDbeScreenPriv->DestroyWindow = pScreen->DestroyWindow;
1623                pScreen->DestroyWindow        = DbeDestroyWindow;
1624            }
1625            else
1626            {
1627                /* DDX initialization failed.  Stub the screen. */
1628                DbeStubScreen(pDbeScreenPriv, &nStubbedScreens);
1629            }
1630#else
1631            DbeStubScreen(pDbeScreenPriv, &nStubbedScreens);
1632#endif
1633
1634        }
1635
1636    } /* for (i = 0; i < screenInfo.numScreens; i++) */
1637
1638
1639    if (nStubbedScreens == screenInfo.numScreens)
1640    {
1641	/* All screens stubbed.  Clean up and return. */
1642
1643        for (i = 0; i < screenInfo.numScreens; i++)
1644        {
1645		free(dixLookupPrivate(&screenInfo.screens[i]->devPrivates,
1646				       dbeScreenPrivKey));
1647		dixSetPrivate(&pScreen->devPrivates, dbeScreenPrivKey, NULL);
1648        }
1649        return;
1650    }
1651
1652
1653    /* Now add the extension. */
1654    extEntry = AddExtension(DBE_PROTOCOL_NAME, DbeNumberEvents,
1655                            DbeNumberErrors, ProcDbeDispatch, SProcDbeDispatch,
1656                            DbeResetProc, StandardMinorOpcode);
1657
1658    dbeErrorBase = extEntry->errorBase;
1659    SetResourceTypeErrorValue(dbeWindowPrivResType, dbeErrorBase + DbeBadBuffer);
1660    SetResourceTypeErrorValue(dbeDrawableResType, dbeErrorBase + DbeBadBuffer);
1661
1662} /* DbeExtensionInit() */
1663
1664