1706f2543Smrg/******************************************************************************
2706f2543Smrg *
3706f2543Smrg * Copyright (c) 1994, 1995  Hewlett-Packard Company
4706f2543Smrg *
5706f2543Smrg * Permission is hereby granted, free of charge, to any person obtaining
6706f2543Smrg * a copy of this software and associated documentation files (the
7706f2543Smrg * "Software"), to deal in the Software without restriction, including
8706f2543Smrg * without limitation the rights to use, copy, modify, merge, publish,
9706f2543Smrg * distribute, sublicense, and/or sell copies of the Software, and to
10706f2543Smrg * permit persons to whom the Software is furnished to do so, subject to
11706f2543Smrg * the following conditions:
12706f2543Smrg *
13706f2543Smrg * The above copyright notice and this permission notice shall be included
14706f2543Smrg * in all copies or substantial portions of the Software.
15706f2543Smrg *
16706f2543Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17706f2543Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18706f2543Smrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19706f2543Smrg * IN NO EVENT SHALL HEWLETT-PACKARD COMPANY BE LIABLE FOR ANY CLAIM,
20706f2543Smrg * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
21706f2543Smrg * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
22706f2543Smrg * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23706f2543Smrg *
24706f2543Smrg * Except as contained in this notice, the name of the Hewlett-Packard
25706f2543Smrg * Company shall not be used in advertising or otherwise to promote the
26706f2543Smrg * sale, use or other dealings in this Software without prior written
27706f2543Smrg * authorization from the Hewlett-Packard Company.
28706f2543Smrg *
29706f2543Smrg *     Machine-independent DBE code
30706f2543Smrg *
31706f2543Smrg *****************************************************************************/
32706f2543Smrg
33706f2543Smrg
34706f2543Smrg/* INCLUDES */
35706f2543Smrg
36706f2543Smrg#ifdef HAVE_DIX_CONFIG_H
37706f2543Smrg#include <dix-config.h>
38706f2543Smrg#endif
39706f2543Smrg
40706f2543Smrg#include <X11/X.h>
41706f2543Smrg#include <X11/Xproto.h>
42706f2543Smrg#include "misc.h"
43706f2543Smrg#include "os.h"
44706f2543Smrg#include "windowstr.h"
45706f2543Smrg#include "scrnintstr.h"
46706f2543Smrg#include "pixmapstr.h"
47706f2543Smrg#include "extnsionst.h"
48706f2543Smrg#include "dixstruct.h"
49706f2543Smrg#include "resource.h"
50706f2543Smrg#include "opaque.h"
51706f2543Smrg#include "dbestruct.h"
52706f2543Smrg#include "midbestr.h"
53706f2543Smrg#include "regionstr.h"
54706f2543Smrg#include "gcstruct.h"
55706f2543Smrg#include "inputstr.h"
56706f2543Smrg#include "midbe.h"
57706f2543Smrg#include "xace.h"
58706f2543Smrg
59706f2543Smrg#include <stdio.h>
60706f2543Smrg
61706f2543Smrgstatic DevPrivateKeyRec miDbeWindowPrivPrivKeyRec;
62706f2543Smrg#define miDbeWindowPrivPrivKey (&miDbeWindowPrivPrivKeyRec)
63706f2543Smrg
64706f2543Smrg
65706f2543Smrg/******************************************************************************
66706f2543Smrg *
67706f2543Smrg * DBE MI Procedure: miDbeGetVisualInfo
68706f2543Smrg *
69706f2543Smrg * Description:
70706f2543Smrg *
71706f2543Smrg *     This is the MI function for the DbeGetVisualInfo request.  This function
72706f2543Smrg *     is called through pDbeScreenPriv->GetVisualInfo.  This function is also
73706f2543Smrg *     called for the DbeAllocateBackBufferName request at the extension level;
74706f2543Smrg *     it is called by ProcDbeAllocateBackBufferName() in dbe.c.
75706f2543Smrg *
76706f2543Smrg *     If memory allocation fails or we can not get the visual info, this
77706f2543Smrg *     function returns FALSE.  Otherwise, it returns TRUE for success.
78706f2543Smrg *
79706f2543Smrg *****************************************************************************/
80706f2543Smrg
81706f2543Smrgstatic Bool
82706f2543SmrgmiDbeGetVisualInfo(ScreenPtr pScreen, XdbeScreenVisualInfo *pScrVisInfo)
83706f2543Smrg{
84706f2543Smrg    register int	i, j, k;
85706f2543Smrg    register int	count;
86706f2543Smrg    DepthPtr		pDepth;
87706f2543Smrg    XdbeVisualInfo	*visInfo;
88706f2543Smrg
89706f2543Smrg
90706f2543Smrg    /* Determine number of visuals for this screen. */
91706f2543Smrg    for (i = 0, count = 0; i < pScreen->numDepths; i++)
92706f2543Smrg    {
93706f2543Smrg        count += pScreen->allowedDepths[i].numVids;
94706f2543Smrg    }
95706f2543Smrg
96706f2543Smrg    /* Allocate an array of XdbeVisualInfo items. */
97706f2543Smrg    if (!(visInfo = (XdbeVisualInfo *)malloc(count * sizeof(XdbeVisualInfo))))
98706f2543Smrg    {
99706f2543Smrg        return FALSE; /* memory alloc failure */
100706f2543Smrg    }
101706f2543Smrg
102706f2543Smrg    for (i = 0, k = 0; i < pScreen->numDepths; i++)
103706f2543Smrg    {
104706f2543Smrg        /* For each depth of this screen, get visual information. */
105706f2543Smrg
106706f2543Smrg        pDepth = &pScreen->allowedDepths[i];
107706f2543Smrg
108706f2543Smrg        for (j = 0; j < pDepth->numVids; j++)
109706f2543Smrg        {
110706f2543Smrg            /* For each visual for this depth of this screen, get visual ID
111706f2543Smrg             * and visual depth.  Since this is MI code, we will always return
112706f2543Smrg             * the same performance level for all visuals (0).  A higher
113706f2543Smrg             * performance level value indicates higher performance.
114706f2543Smrg             */
115706f2543Smrg            visInfo[k].visual    = pDepth->vids[j];
116706f2543Smrg            visInfo[k].depth     = pDepth->depth;
117706f2543Smrg            visInfo[k].perflevel = 0;
118706f2543Smrg            k++;
119706f2543Smrg        }
120706f2543Smrg    }
121706f2543Smrg
122706f2543Smrg    /* Record the number of visuals and point visual_depth to
123706f2543Smrg     * the array of visual info.
124706f2543Smrg     */
125706f2543Smrg    pScrVisInfo->count   = count;
126706f2543Smrg    pScrVisInfo->visinfo = visInfo;
127706f2543Smrg
128706f2543Smrg    return TRUE; /* success */
129706f2543Smrg
130706f2543Smrg} /* miDbeGetVisualInfo() */
131706f2543Smrg
132706f2543Smrg
133706f2543Smrg/******************************************************************************
134706f2543Smrg *
135706f2543Smrg * DBE MI Procedure: miAllocBackBufferName
136706f2543Smrg *
137706f2543Smrg * Description:
138706f2543Smrg *
139706f2543Smrg *     This is the MI function for the DbeAllocateBackBufferName request.
140706f2543Smrg *
141706f2543Smrg *****************************************************************************/
142706f2543Smrg
143706f2543Smrgstatic int
144706f2543SmrgmiDbeAllocBackBufferName(WindowPtr pWin, XID bufId, int swapAction)
145706f2543Smrg{
146706f2543Smrg    ScreenPtr			pScreen;
147706f2543Smrg    DbeWindowPrivPtr		pDbeWindowPriv;
148706f2543Smrg    MiDbeWindowPrivPrivPtr	pDbeWindowPrivPriv;
149706f2543Smrg    DbeScreenPrivPtr		pDbeScreenPriv;
150706f2543Smrg    GCPtr			pGC;
151706f2543Smrg    xRectangle			clearRect;
152706f2543Smrg    int				rc;
153706f2543Smrg
154706f2543Smrg
155706f2543Smrg    pScreen = pWin->drawable.pScreen;
156706f2543Smrg    pDbeWindowPriv = DBE_WINDOW_PRIV(pWin);
157706f2543Smrg
158706f2543Smrg    if (pDbeWindowPriv->nBufferIDs == 0)
159706f2543Smrg    {
160706f2543Smrg        /* There is no buffer associated with the window.
161706f2543Smrg         * We have to create the window priv priv.  Remember, the window
162706f2543Smrg         * priv was created at the DIX level, so all we need to do is
163706f2543Smrg         * create the priv priv and attach it to the priv.
164706f2543Smrg         */
165706f2543Smrg
166706f2543Smrg        pDbeScreenPriv = DBE_SCREEN_PRIV(pScreen);
167706f2543Smrg
168706f2543Smrg        /* Setup the window priv priv. */
169706f2543Smrg        pDbeWindowPrivPriv = MI_DBE_WINDOW_PRIV_PRIV(pDbeWindowPriv);
170706f2543Smrg        pDbeWindowPrivPriv->pDbeWindowPriv = pDbeWindowPriv;
171706f2543Smrg
172706f2543Smrg        /* Get a front pixmap. */
173706f2543Smrg        if (!(pDbeWindowPrivPriv->pFrontBuffer =
174706f2543Smrg            (*pScreen->CreatePixmap)(pScreen, pDbeWindowPriv->width,
175706f2543Smrg                                     pDbeWindowPriv->height,
176706f2543Smrg                                     pWin->drawable.depth, 0)))
177706f2543Smrg        {
178706f2543Smrg            return BadAlloc;
179706f2543Smrg        }
180706f2543Smrg
181706f2543Smrg        /* Get a back pixmap. */
182706f2543Smrg        if (!(pDbeWindowPrivPriv->pBackBuffer =
183706f2543Smrg            (*pScreen->CreatePixmap)(pScreen, pDbeWindowPriv->width,
184706f2543Smrg                                     pDbeWindowPriv->height,
185706f2543Smrg                                     pWin->drawable.depth, 0)))
186706f2543Smrg        {
187706f2543Smrg            (*pScreen->DestroyPixmap)(pDbeWindowPrivPriv->pFrontBuffer);
188706f2543Smrg            return BadAlloc;
189706f2543Smrg        }
190706f2543Smrg
191706f2543Smrg	/* Security creation/labeling check. */
192706f2543Smrg	rc = XaceHook(XACE_RESOURCE_ACCESS, serverClient, bufId,
193706f2543Smrg		      dbeDrawableResType, pDbeWindowPrivPriv->pBackBuffer,
194706f2543Smrg		      RT_WINDOW, pWin, DixCreateAccess);
195706f2543Smrg
196706f2543Smrg        /* Make the back pixmap a DBE drawable resource. */
197706f2543Smrg        if (rc != Success || !AddResource(bufId, dbeDrawableResType,
198706f2543Smrg					  pDbeWindowPrivPriv->pBackBuffer))
199706f2543Smrg        {
200706f2543Smrg            /* free the buffer and the drawable resource */
201706f2543Smrg            FreeResource(bufId, RT_NONE);
202706f2543Smrg            return (rc == Success) ? BadAlloc : rc;
203706f2543Smrg        }
204706f2543Smrg
205706f2543Smrg        /* Clear the back buffer. */
206706f2543Smrg        pGC = GetScratchGC(pWin->drawable.depth, pWin->drawable.pScreen);
207706f2543Smrg        if ((*pDbeScreenPriv->SetupBackgroundPainter)(pWin, pGC))
208706f2543Smrg        {
209706f2543Smrg            ValidateGC((DrawablePtr)pDbeWindowPrivPriv->pBackBuffer, pGC);
210706f2543Smrg            clearRect.x = clearRect.y = 0;
211706f2543Smrg            clearRect.width  = pDbeWindowPrivPriv->pBackBuffer->drawable.width;
212706f2543Smrg            clearRect.height = pDbeWindowPrivPriv->pBackBuffer->drawable.height;
213706f2543Smrg            (*pGC->ops->PolyFillRect)(
214706f2543Smrg                (DrawablePtr)pDbeWindowPrivPriv->pBackBuffer, pGC, 1,
215706f2543Smrg                &clearRect);
216706f2543Smrg        }
217706f2543Smrg        FreeScratchGC(pGC);
218706f2543Smrg
219706f2543Smrg    } /* if no buffer associated with the window */
220706f2543Smrg
221706f2543Smrg    else
222706f2543Smrg    {
223706f2543Smrg        /* A buffer is already associated with the window.
224706f2543Smrg         * Place the new buffer ID information at the head of the ID list.
225706f2543Smrg         */
226706f2543Smrg
227706f2543Smrg        /* Associate the new ID with an existing pixmap. */
228706f2543Smrg        pDbeWindowPrivPriv = MI_DBE_WINDOW_PRIV_PRIV(pDbeWindowPriv);
229706f2543Smrg        if (!AddResource(bufId, dbeDrawableResType,
230706f2543Smrg                         (pointer)pDbeWindowPrivPriv->pBackBuffer))
231706f2543Smrg        {
232706f2543Smrg            return BadAlloc;
233706f2543Smrg        }
234706f2543Smrg
235706f2543Smrg    }
236706f2543Smrg
237706f2543Smrg    return Success;
238706f2543Smrg
239706f2543Smrg} /* miDbeAllocBackBufferName() */
240706f2543Smrg
241706f2543Smrg
242706f2543Smrg/******************************************************************************
243706f2543Smrg *
244706f2543Smrg * DBE MI Procedure: miDbeAliasBuffers
245706f2543Smrg *
246706f2543Smrg * Description:
247706f2543Smrg *
248706f2543Smrg *     This function associates all XIDs of a buffer with the back pixmap
249706f2543Smrg *     stored in the window priv.
250706f2543Smrg *
251706f2543Smrg *****************************************************************************/
252706f2543Smrg
253706f2543Smrgstatic void
254706f2543SmrgmiDbeAliasBuffers(DbeWindowPrivPtr pDbeWindowPriv)
255706f2543Smrg{
256706f2543Smrg    int				i;
257706f2543Smrg    MiDbeWindowPrivPrivPtr	pDbeWindowPrivPriv =
258706f2543Smrg                                    MI_DBE_WINDOW_PRIV_PRIV(pDbeWindowPriv);
259706f2543Smrg
260706f2543Smrg    for (i = 0; i < pDbeWindowPriv->nBufferIDs; i++)
261706f2543Smrg    {
262706f2543Smrg        ChangeResourceValue(pDbeWindowPriv->IDs[i], dbeDrawableResType,
263706f2543Smrg                            (pointer)pDbeWindowPrivPriv->pBackBuffer);
264706f2543Smrg    }
265706f2543Smrg
266706f2543Smrg} /* miDbeAliasBuffers() */
267706f2543Smrg
268706f2543Smrg
269706f2543Smrg/******************************************************************************
270706f2543Smrg *
271706f2543Smrg * DBE MI Procedure: miDbeSwapBuffers
272706f2543Smrg *
273706f2543Smrg * Description:
274706f2543Smrg *
275706f2543Smrg *     This is the MI function for the DbeSwapBuffers request.
276706f2543Smrg *
277706f2543Smrg *****************************************************************************/
278706f2543Smrg
279706f2543Smrgstatic int
280706f2543SmrgmiDbeSwapBuffers(ClientPtr client, int *pNumWindows, DbeSwapInfoPtr swapInfo)
281706f2543Smrg{
282706f2543Smrg    DbeScreenPrivPtr		pDbeScreenPriv;
283706f2543Smrg    GCPtr		    	pGC;
284706f2543Smrg    WindowPtr		    	pWin;
285706f2543Smrg    MiDbeWindowPrivPrivPtr	pDbeWindowPrivPriv;
286706f2543Smrg    PixmapPtr			pTmpBuffer;
287706f2543Smrg    xRectangle			clearRect;
288706f2543Smrg
289706f2543Smrg
290706f2543Smrg    pWin               = swapInfo[0].pWindow;
291706f2543Smrg    pDbeScreenPriv     = DBE_SCREEN_PRIV_FROM_WINDOW(pWin);
292706f2543Smrg    pDbeWindowPrivPriv = MI_DBE_WINDOW_PRIV_PRIV_FROM_WINDOW(pWin);
293706f2543Smrg    pGC = GetScratchGC(pWin->drawable.depth, pWin->drawable.pScreen);
294706f2543Smrg
295706f2543Smrg    /*
296706f2543Smrg     **********************************************************************
297706f2543Smrg     ** Setup before swap.
298706f2543Smrg     **********************************************************************
299706f2543Smrg     */
300706f2543Smrg
301706f2543Smrg    switch(swapInfo[0].swapAction)
302706f2543Smrg    {
303706f2543Smrg        case XdbeUndefined:
304706f2543Smrg            break;
305706f2543Smrg
306706f2543Smrg        case XdbeBackground:
307706f2543Smrg            break;
308706f2543Smrg
309706f2543Smrg        case XdbeUntouched:
310706f2543Smrg            ValidateGC((DrawablePtr)pDbeWindowPrivPriv->pFrontBuffer, pGC);
311706f2543Smrg            (*pGC->ops->CopyArea)((DrawablePtr)pWin,
312706f2543Smrg                                  (DrawablePtr)pDbeWindowPrivPriv->pFrontBuffer,
313706f2543Smrg                                  pGC, 0, 0, pWin->drawable.width,
314706f2543Smrg                                  pWin->drawable.height, 0, 0);
315706f2543Smrg            break;
316706f2543Smrg
317706f2543Smrg        case XdbeCopied:
318706f2543Smrg            break;
319706f2543Smrg
320706f2543Smrg    }
321706f2543Smrg
322706f2543Smrg    /*
323706f2543Smrg     **********************************************************************
324706f2543Smrg     ** Swap.
325706f2543Smrg     **********************************************************************
326706f2543Smrg     */
327706f2543Smrg
328706f2543Smrg    ValidateGC((DrawablePtr)pWin, pGC);
329706f2543Smrg    (*pGC->ops->CopyArea)((DrawablePtr)pDbeWindowPrivPriv->pBackBuffer,
330706f2543Smrg                          (DrawablePtr)pWin, pGC, 0, 0,
331706f2543Smrg                          pWin->drawable.width, pWin->drawable.height,
332706f2543Smrg                          0, 0);
333706f2543Smrg
334706f2543Smrg    /*
335706f2543Smrg     **********************************************************************
336706f2543Smrg     ** Tasks after swap.
337706f2543Smrg     **********************************************************************
338706f2543Smrg     */
339706f2543Smrg
340706f2543Smrg    switch(swapInfo[0].swapAction)
341706f2543Smrg    {
342706f2543Smrg        case XdbeUndefined:
343706f2543Smrg            break;
344706f2543Smrg
345706f2543Smrg        case XdbeBackground:
346706f2543Smrg            if ((*pDbeScreenPriv->SetupBackgroundPainter)(pWin, pGC))
347706f2543Smrg            {
348706f2543Smrg                ValidateGC((DrawablePtr)pDbeWindowPrivPriv->pBackBuffer, pGC);
349706f2543Smrg                clearRect.x = 0;
350706f2543Smrg                clearRect.y = 0;
351706f2543Smrg                clearRect.width =
352706f2543Smrg                    pDbeWindowPrivPriv->pBackBuffer->drawable.width;
353706f2543Smrg                clearRect.height =
354706f2543Smrg                    pDbeWindowPrivPriv->pBackBuffer->drawable.height;
355706f2543Smrg                (*pGC->ops->PolyFillRect)(
356706f2543Smrg				(DrawablePtr)pDbeWindowPrivPriv->pBackBuffer,
357706f2543Smrg				pGC, 1, &clearRect);
358706f2543Smrg	    }
359706f2543Smrg            break;
360706f2543Smrg
361706f2543Smrg        case XdbeUntouched:
362706f2543Smrg            /* Swap pixmap pointers. */
363706f2543Smrg            pTmpBuffer = pDbeWindowPrivPriv->pBackBuffer;
364706f2543Smrg            pDbeWindowPrivPriv->pBackBuffer =
365706f2543Smrg                pDbeWindowPrivPriv->pFrontBuffer;
366706f2543Smrg            pDbeWindowPrivPriv->pFrontBuffer = pTmpBuffer;
367706f2543Smrg
368706f2543Smrg            miDbeAliasBuffers(pDbeWindowPrivPriv->pDbeWindowPriv);
369706f2543Smrg
370706f2543Smrg            break;
371706f2543Smrg
372706f2543Smrg        case XdbeCopied:
373706f2543Smrg            break;
374706f2543Smrg
375706f2543Smrg    }
376706f2543Smrg
377706f2543Smrg    /* Remove the swapped window from the swap information array and decrement
378706f2543Smrg     * pNumWindows to indicate to the DIX level how many windows were actually
379706f2543Smrg     * swapped.
380706f2543Smrg     */
381706f2543Smrg
382706f2543Smrg    if (*pNumWindows > 1)
383706f2543Smrg    {
384706f2543Smrg        /* We were told to swap more than one window, but we only swapped the
385706f2543Smrg         * first one.  Remove the first window in the list by moving the last
386706f2543Smrg         * window to the beginning.
387706f2543Smrg         */
388706f2543Smrg        swapInfo[0].pWindow    = swapInfo[*pNumWindows - 1].pWindow;
389706f2543Smrg        swapInfo[0].swapAction = swapInfo[*pNumWindows - 1].swapAction;
390706f2543Smrg
391706f2543Smrg        /* Clear the last window information just to be safe. */
392706f2543Smrg        swapInfo[*pNumWindows - 1].pWindow    = (WindowPtr)NULL;
393706f2543Smrg        swapInfo[*pNumWindows - 1].swapAction = 0;
394706f2543Smrg    }
395706f2543Smrg    else
396706f2543Smrg    {
397706f2543Smrg        /* Clear the window information just to be safe. */
398706f2543Smrg        swapInfo[0].pWindow    = (WindowPtr)NULL;
399706f2543Smrg        swapInfo[0].swapAction = 0;
400706f2543Smrg    }
401706f2543Smrg
402706f2543Smrg    (*pNumWindows)--;
403706f2543Smrg
404706f2543Smrg    FreeScratchGC(pGC);
405706f2543Smrg
406706f2543Smrg    return Success;
407706f2543Smrg
408706f2543Smrg} /* miSwapBuffers() */
409706f2543Smrg
410706f2543Smrg
411706f2543Smrg/******************************************************************************
412706f2543Smrg *
413706f2543Smrg * DBE MI Procedure: miDbeWinPrivDelete
414706f2543Smrg *
415706f2543Smrg * Description:
416706f2543Smrg *
417706f2543Smrg *     This is the MI function for deleting the dbeWindowPrivResType resource.
418706f2543Smrg *     This function is invoked indirectly by calling FreeResource() to free
419706f2543Smrg *     the resources associated with a DBE buffer ID.  There are 5 ways that
420706f2543Smrg *     miDbeWinPrivDelete() can be called by FreeResource().  They are:
421706f2543Smrg *
422706f2543Smrg *     - A DBE window is destroyed, in which case the DbeDestroyWindow()
423706f2543Smrg *       wrapper is invoked.  The wrapper calls FreeResource() for all DBE
424706f2543Smrg *       buffer IDs.
425706f2543Smrg *
426706f2543Smrg *     - miDbeAllocBackBufferName() calls FreeResource() to clean up resources
427706f2543Smrg *       after a buffer allocation failure.
428706f2543Smrg *
429706f2543Smrg *     - The PositionWindow wrapper, miDbePositionWindow(), calls
430706f2543Smrg *       FreeResource() when it fails to create buffers of the new size.
431706f2543Smrg *       FreeResource() is called for all DBE buffer IDs.
432706f2543Smrg *
433706f2543Smrg *     - FreeClientResources() calls FreeResource() when a client dies or the
434706f2543Smrg *       the server resets.
435706f2543Smrg *
436706f2543Smrg *     When FreeResource() is called for a DBE buffer ID, the delete function
437706f2543Smrg *     for the only other type of DBE resource, dbeDrawableResType, is also
438706f2543Smrg *     invoked.  This delete function (DbeDrawableDelete) is a NOOP to make
439706f2543Smrg *     resource deletion easier.  It is not guaranteed which delete function is
440706f2543Smrg *     called first.  Hence, we will let miDbeWinPrivDelete() free all DBE
441706f2543Smrg *     resources.
442706f2543Smrg *
443706f2543Smrg *     This function deletes/frees the following stuff associated with
444706f2543Smrg *     the window private:
445706f2543Smrg *
446706f2543Smrg *     - the ID node in the ID list representing the passed in ID.
447706f2543Smrg *
448706f2543Smrg *     In addition, pDbeWindowPriv->nBufferIDs is decremented.
449706f2543Smrg *
450706f2543Smrg *     If this function is called for the last/only buffer ID for a window,
451706f2543Smrg *     these are additionally deleted/freed:
452706f2543Smrg *
453706f2543Smrg *     - the front and back pixmaps
454706f2543Smrg *     - the window priv itself
455706f2543Smrg *
456706f2543Smrg *****************************************************************************/
457706f2543Smrg
458706f2543Smrgstatic void
459706f2543SmrgmiDbeWinPrivDelete(DbeWindowPrivPtr pDbeWindowPriv, XID bufId)
460706f2543Smrg{
461706f2543Smrg    MiDbeWindowPrivPrivPtr	pDbeWindowPrivPriv;
462706f2543Smrg
463706f2543Smrg
464706f2543Smrg    if (pDbeWindowPriv->nBufferIDs != 0)
465706f2543Smrg    {
466706f2543Smrg        /* We still have at least one more buffer ID associated with this
467706f2543Smrg         * window.
468706f2543Smrg         */
469706f2543Smrg        return;
470706f2543Smrg    }
471706f2543Smrg
472706f2543Smrg
473706f2543Smrg    /* We have no more buffer IDs associated with this window.  We need to
474706f2543Smrg     * free some stuff.
475706f2543Smrg     */
476706f2543Smrg
477706f2543Smrg    pDbeWindowPrivPriv = MI_DBE_WINDOW_PRIV_PRIV(pDbeWindowPriv);
478706f2543Smrg
479706f2543Smrg    /* Destroy the front and back pixmaps. */
480706f2543Smrg    if (pDbeWindowPrivPriv->pFrontBuffer)
481706f2543Smrg    {
482706f2543Smrg        (*pDbeWindowPriv->pWindow->drawable.pScreen->DestroyPixmap)(
483706f2543Smrg            pDbeWindowPrivPriv->pFrontBuffer);
484706f2543Smrg    }
485706f2543Smrg    if (pDbeWindowPrivPriv->pBackBuffer)
486706f2543Smrg    {
487706f2543Smrg        (*pDbeWindowPriv->pWindow->drawable.pScreen->DestroyPixmap)(
488706f2543Smrg            pDbeWindowPrivPriv->pBackBuffer);
489706f2543Smrg    }
490706f2543Smrg
491706f2543Smrg} /* miDbeWinPrivDelete() */
492706f2543Smrg
493706f2543Smrg
494706f2543Smrg/******************************************************************************
495706f2543Smrg *
496706f2543Smrg * DBE MI Procedure: miDbePositionWindow
497706f2543Smrg *
498706f2543Smrg * Description:
499706f2543Smrg *
500706f2543Smrg *     This function was cloned from miMbxPositionWindow() in mimultibuf.c.
501706f2543Smrg *     This function resizes the buffer when the window is resized.
502706f2543Smrg *
503706f2543Smrg *****************************************************************************/
504706f2543Smrg
505706f2543Smrgstatic Bool
506706f2543SmrgmiDbePositionWindow(WindowPtr pWin, int x, int y)
507706f2543Smrg{
508706f2543Smrg    ScreenPtr			pScreen;
509706f2543Smrg    DbeScreenPrivPtr		pDbeScreenPriv;
510706f2543Smrg    DbeWindowPrivPtr		pDbeWindowPriv;
511706f2543Smrg    int				width, height;
512706f2543Smrg    int				dx, dy, dw, dh;
513706f2543Smrg    int				sourcex, sourcey;
514706f2543Smrg    int				destx, desty;
515706f2543Smrg    int				savewidth, saveheight;
516706f2543Smrg    PixmapPtr			pFrontBuffer;
517706f2543Smrg    PixmapPtr			pBackBuffer;
518706f2543Smrg    Bool			clear;
519706f2543Smrg    GCPtr			pGC;
520706f2543Smrg    xRectangle			clearRect;
521706f2543Smrg    Bool			ret;
522706f2543Smrg
523706f2543Smrg
524706f2543Smrg    /*
525706f2543Smrg     **************************************************************************
526706f2543Smrg     ** 1. Unwrap the member routine.
527706f2543Smrg     **************************************************************************
528706f2543Smrg     */
529706f2543Smrg
530706f2543Smrg    pScreen                 = pWin->drawable.pScreen;
531706f2543Smrg    pDbeScreenPriv          = DBE_SCREEN_PRIV(pScreen);
532706f2543Smrg    pScreen->PositionWindow = pDbeScreenPriv->PositionWindow;
533706f2543Smrg
534706f2543Smrg    /*
535706f2543Smrg     **************************************************************************
536706f2543Smrg     ** 2. Do any work necessary before the member routine is called.
537706f2543Smrg     **
538706f2543Smrg     **    In this case we do not need to do anything.
539706f2543Smrg     **************************************************************************
540706f2543Smrg     */
541706f2543Smrg
542706f2543Smrg    /*
543706f2543Smrg     **************************************************************************
544706f2543Smrg     ** 3. Call the member routine, saving its result if necessary.
545706f2543Smrg     **************************************************************************
546706f2543Smrg     */
547706f2543Smrg
548706f2543Smrg    ret = (*pScreen->PositionWindow)(pWin, x, y);
549706f2543Smrg
550706f2543Smrg    /*
551706f2543Smrg     **************************************************************************
552706f2543Smrg     ** 4. Rewrap the member routine, restoring the wrapper value first in case
553706f2543Smrg     **    the wrapper (or something that it wrapped) change this value.
554706f2543Smrg     **************************************************************************
555706f2543Smrg     */
556706f2543Smrg
557706f2543Smrg    pDbeScreenPriv->PositionWindow = pScreen->PositionWindow;
558706f2543Smrg    pScreen->PositionWindow = miDbePositionWindow;
559706f2543Smrg
560706f2543Smrg    /*
561706f2543Smrg     **************************************************************************
562706f2543Smrg     ** 5. Do any work necessary after the member routine has been called.
563706f2543Smrg     **************************************************************************
564706f2543Smrg     */
565706f2543Smrg
566706f2543Smrg    if (!(pDbeWindowPriv = DBE_WINDOW_PRIV(pWin)))
567706f2543Smrg    {
568706f2543Smrg	return ret;
569706f2543Smrg    }
570706f2543Smrg
571706f2543Smrg    if (pDbeWindowPriv->width  == pWin->drawable.width &&
572706f2543Smrg        pDbeWindowPriv->height == pWin->drawable.height)
573706f2543Smrg    {
574706f2543Smrg	return ret;
575706f2543Smrg    }
576706f2543Smrg
577706f2543Smrg    width  = pWin->drawable.width;
578706f2543Smrg    height = pWin->drawable.height;
579706f2543Smrg
580706f2543Smrg    dx = pWin->drawable.x - pDbeWindowPriv->x;
581706f2543Smrg    dy = pWin->drawable.y - pDbeWindowPriv->y;
582706f2543Smrg    dw = width  - pDbeWindowPriv->width;
583706f2543Smrg    dh = height - pDbeWindowPriv->height;
584706f2543Smrg
585706f2543Smrg    GravityTranslate (0, 0, -dx, -dy, dw, dh, pWin->bitGravity, &destx, &desty);
586706f2543Smrg
587706f2543Smrg    clear = ((pDbeWindowPriv->width  < (unsigned short)width ) ||
588706f2543Smrg             (pDbeWindowPriv->height < (unsigned short)height) ||
589706f2543Smrg             (pWin->bitGravity == ForgetGravity));
590706f2543Smrg
591706f2543Smrg    sourcex = 0;
592706f2543Smrg    sourcey = 0;
593706f2543Smrg    savewidth  = pDbeWindowPriv->width;
594706f2543Smrg    saveheight = pDbeWindowPriv->height;
595706f2543Smrg
596706f2543Smrg    /* Clip rectangle to source and destination. */
597706f2543Smrg    if (destx < 0)
598706f2543Smrg    {
599706f2543Smrg	savewidth += destx;
600706f2543Smrg	sourcex   -= destx;
601706f2543Smrg	destx      = 0;
602706f2543Smrg    }
603706f2543Smrg
604706f2543Smrg    if (destx + savewidth > width)
605706f2543Smrg    {
606706f2543Smrg	savewidth = width - destx;
607706f2543Smrg    }
608706f2543Smrg
609706f2543Smrg    if (desty < 0)
610706f2543Smrg    {
611706f2543Smrg	saveheight += desty;
612706f2543Smrg	sourcey    -= desty;
613706f2543Smrg	desty       = 0;
614706f2543Smrg    }
615706f2543Smrg
616706f2543Smrg    if (desty + saveheight > height)
617706f2543Smrg    {
618706f2543Smrg	saveheight = height - desty;
619706f2543Smrg    }
620706f2543Smrg
621706f2543Smrg    pDbeWindowPriv->width  = width;
622706f2543Smrg    pDbeWindowPriv->height = height;
623706f2543Smrg    pDbeWindowPriv->x = pWin->drawable.x;
624706f2543Smrg    pDbeWindowPriv->y = pWin->drawable.y;
625706f2543Smrg
626706f2543Smrg    pGC = GetScratchGC (pWin->drawable.depth, pScreen);
627706f2543Smrg
628706f2543Smrg    if (clear)
629706f2543Smrg    {
630706f2543Smrg	if ((*pDbeScreenPriv->SetupBackgroundPainter)(pWin, pGC))
631706f2543Smrg	{
632706f2543Smrg	    clearRect.x = 0;
633706f2543Smrg	    clearRect.y = 0;
634706f2543Smrg	    clearRect.width  = width;
635706f2543Smrg	    clearRect.height = height;
636706f2543Smrg	}
637706f2543Smrg	else
638706f2543Smrg	{
639706f2543Smrg	    clear = FALSE;
640706f2543Smrg	}
641706f2543Smrg    }
642706f2543Smrg
643706f2543Smrg    /* Create DBE buffer pixmaps equal to size of resized window. */
644706f2543Smrg    pFrontBuffer = (*pScreen->CreatePixmap)(pScreen, width, height,
645706f2543Smrg					    pWin->drawable.depth, 0);
646706f2543Smrg
647706f2543Smrg    pBackBuffer = (*pScreen->CreatePixmap)(pScreen, width, height,
648706f2543Smrg					   pWin->drawable.depth, 0);
649706f2543Smrg
650706f2543Smrg    if (!pFrontBuffer || !pBackBuffer)
651706f2543Smrg    {
652706f2543Smrg        /* We failed at creating 1 or 2 of the pixmaps. */
653706f2543Smrg
654706f2543Smrg        if (pFrontBuffer)
655706f2543Smrg        {
656706f2543Smrg	    (*pScreen->DestroyPixmap)(pFrontBuffer);
657706f2543Smrg        }
658706f2543Smrg
659706f2543Smrg        if (pBackBuffer)
660706f2543Smrg        {
661706f2543Smrg	    (*pScreen->DestroyPixmap)(pBackBuffer);
662706f2543Smrg        }
663706f2543Smrg
664706f2543Smrg        /* Destroy all buffers for this window. */
665706f2543Smrg        while (pDbeWindowPriv)
666706f2543Smrg        {
667706f2543Smrg            /* DbeWindowPrivDelete() will free the window private if there no
668706f2543Smrg             * more buffer IDs associated with this window.
669706f2543Smrg             */
670706f2543Smrg            FreeResource(pDbeWindowPriv->IDs[0], RT_NONE);
671706f2543Smrg            pDbeWindowPriv = DBE_WINDOW_PRIV(pWin);
672706f2543Smrg        }
673706f2543Smrg
674706f2543Smrg        FreeScratchGC(pGC);
675706f2543Smrg        return FALSE;
676706f2543Smrg    }
677706f2543Smrg
678706f2543Smrg    else
679706f2543Smrg    {
680706f2543Smrg        /* Clear out the new DBE buffer pixmaps. */
681706f2543Smrg
682706f2543Smrg        MiDbeWindowPrivPrivPtr	pDbeWindowPrivPriv;
683706f2543Smrg
684706f2543Smrg
685706f2543Smrg        pDbeWindowPrivPriv = MI_DBE_WINDOW_PRIV_PRIV(pDbeWindowPriv);
686706f2543Smrg
687706f2543Smrg	/* I suppose this could avoid quite a bit of work if
688706f2543Smrg	 * it computed the minimal area required.
689706f2543Smrg	 */
690706f2543Smrg	ValidateGC(&pFrontBuffer->drawable, pGC);
691706f2543Smrg	if (clear)
692706f2543Smrg        {
693706f2543Smrg	    (*pGC->ops->PolyFillRect)((DrawablePtr)pFrontBuffer, pGC, 1,
694706f2543Smrg				      &clearRect);
695706f2543Smrg	}
696706f2543Smrg	/* Copy the contents of the old front pixmap to the new one. */
697706f2543Smrg	if (pWin->bitGravity != ForgetGravity)
698706f2543Smrg	{
699706f2543Smrg	    (*pGC->ops->CopyArea)((DrawablePtr)pDbeWindowPrivPriv->pFrontBuffer,
700706f2543Smrg                                  (DrawablePtr)pFrontBuffer, pGC, sourcex,
701706f2543Smrg                                  sourcey, savewidth, saveheight, destx, desty);
702706f2543Smrg        }
703706f2543Smrg
704706f2543Smrg	ValidateGC(&pBackBuffer->drawable, pGC);
705706f2543Smrg	if (clear)
706706f2543Smrg	{
707706f2543Smrg	    (*pGC->ops->PolyFillRect)((DrawablePtr)pBackBuffer , pGC, 1,
708706f2543Smrg				      &clearRect);
709706f2543Smrg	}
710706f2543Smrg	/* Copy the contents of the old back pixmap to the new one. */
711706f2543Smrg	if (pWin->bitGravity != ForgetGravity)
712706f2543Smrg	{
713706f2543Smrg	    (*pGC->ops->CopyArea)((DrawablePtr)pDbeWindowPrivPriv->pBackBuffer,
714706f2543Smrg                                  (DrawablePtr)pBackBuffer, pGC, sourcex,
715706f2543Smrg                                  sourcey, savewidth, saveheight, destx, desty);
716706f2543Smrg	}
717706f2543Smrg
718706f2543Smrg        /* Destroy the old pixmaps, and point the DBE window priv to the new
719706f2543Smrg         * pixmaps.
720706f2543Smrg         */
721706f2543Smrg
722706f2543Smrg	(*pScreen->DestroyPixmap)(pDbeWindowPrivPriv->pFrontBuffer);
723706f2543Smrg	(*pScreen->DestroyPixmap)(pDbeWindowPrivPriv->pBackBuffer);
724706f2543Smrg
725706f2543Smrg        pDbeWindowPrivPriv->pFrontBuffer = pFrontBuffer;
726706f2543Smrg        pDbeWindowPrivPriv->pBackBuffer  = pBackBuffer;
727706f2543Smrg
728706f2543Smrg	/* Make sure all XID are associated with the new back pixmap. */
729706f2543Smrg        miDbeAliasBuffers(pDbeWindowPriv);
730706f2543Smrg
731706f2543Smrg        FreeScratchGC(pGC);
732706f2543Smrg    }
733706f2543Smrg
734706f2543Smrg    return ret;
735706f2543Smrg
736706f2543Smrg} /* miDbePositionWindow() */
737706f2543Smrg
738706f2543Smrg
739706f2543Smrg/******************************************************************************
740706f2543Smrg *
741706f2543Smrg * DBE MI Procedure: miDbeResetProc
742706f2543Smrg *
743706f2543Smrg * Description:
744706f2543Smrg *
745706f2543Smrg *     This function is called from DbeResetProc(), which is called at the end
746706f2543Smrg *     of every server generation.  This function peforms any MI-specific
747706f2543Smrg *     shutdown tasks.
748706f2543Smrg *
749706f2543Smrg *****************************************************************************/
750706f2543Smrg
751706f2543Smrgstatic void
752706f2543SmrgmiDbeResetProc(ScreenPtr pScreen)
753706f2543Smrg{
754706f2543Smrg    DbeScreenPrivPtr    pDbeScreenPriv;
755706f2543Smrg
756706f2543Smrg
757706f2543Smrg    pDbeScreenPriv = DBE_SCREEN_PRIV(pScreen);
758706f2543Smrg
759706f2543Smrg    /* Unwrap wrappers */
760706f2543Smrg    pScreen->PositionWindow = pDbeScreenPriv->PositionWindow;
761706f2543Smrg
762706f2543Smrg} /* miDbeResetProc() */
763706f2543Smrg
764706f2543Smrg
765706f2543Smrg/******************************************************************************
766706f2543Smrg *
767706f2543Smrg * DBE MI Procedure: miDbeInit
768706f2543Smrg *
769706f2543Smrg * Description:
770706f2543Smrg *
771706f2543Smrg *     This is the MI initialization function called by DbeExtensionInit().
772706f2543Smrg *
773706f2543Smrg *****************************************************************************/
774706f2543Smrg
775706f2543SmrgBool
776706f2543SmrgmiDbeInit(ScreenPtr pScreen, DbeScreenPrivPtr pDbeScreenPriv)
777706f2543Smrg{
778706f2543Smrg    if (!dixRegisterPrivateKey(&miDbeWindowPrivPrivKeyRec, PRIVATE_DBE_WINDOW,
779706f2543Smrg			       sizeof(MiDbeWindowPrivPrivRec)))
780706f2543Smrg        return FALSE;
781706f2543Smrg
782706f2543Smrg    /* Wrap functions. */
783706f2543Smrg    pDbeScreenPriv->PositionWindow = pScreen->PositionWindow;
784706f2543Smrg    pScreen->PositionWindow        = miDbePositionWindow;
785706f2543Smrg
786706f2543Smrg    /* Initialize the per-screen DBE function pointers. */
787706f2543Smrg    pDbeScreenPriv->GetVisualInfo         = miDbeGetVisualInfo;
788706f2543Smrg    pDbeScreenPriv->AllocBackBufferName   = miDbeAllocBackBufferName;
789706f2543Smrg    pDbeScreenPriv->SwapBuffers           = miDbeSwapBuffers;
790706f2543Smrg    pDbeScreenPriv->BeginIdiom            = 0;
791706f2543Smrg    pDbeScreenPriv->EndIdiom              = 0;
792706f2543Smrg    pDbeScreenPriv->ResetProc             = miDbeResetProc;
793706f2543Smrg    pDbeScreenPriv->WinPrivDelete         = miDbeWinPrivDelete;
794706f2543Smrg
795706f2543Smrg    return TRUE;
796706f2543Smrg
797706f2543Smrg} /* miDbeInit() */
798