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