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