midbe.c revision 6747b715
105b261ecSmrg/******************************************************************************
205b261ecSmrg *
305b261ecSmrg * Copyright (c) 1994, 1995  Hewlett-Packard Company
405b261ecSmrg *
505b261ecSmrg * Permission is hereby granted, free of charge, to any person obtaining
605b261ecSmrg * a copy of this software and associated documentation files (the
705b261ecSmrg * "Software"), to deal in the Software without restriction, including
805b261ecSmrg * without limitation the rights to use, copy, modify, merge, publish,
905b261ecSmrg * distribute, sublicense, and/or sell copies of the Software, and to
1005b261ecSmrg * permit persons to whom the Software is furnished to do so, subject to
1105b261ecSmrg * the following conditions:
1205b261ecSmrg *
1305b261ecSmrg * The above copyright notice and this permission notice shall be included
1405b261ecSmrg * in all copies or substantial portions of the Software.
1505b261ecSmrg *
1605b261ecSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
1705b261ecSmrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
1805b261ecSmrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
1905b261ecSmrg * IN NO EVENT SHALL HEWLETT-PACKARD COMPANY BE LIABLE FOR ANY CLAIM,
2005b261ecSmrg * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
2105b261ecSmrg * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
2205b261ecSmrg * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2305b261ecSmrg *
2405b261ecSmrg * Except as contained in this notice, the name of the Hewlett-Packard
2505b261ecSmrg * Company shall not be used in advertising or otherwise to promote the
2605b261ecSmrg * sale, use or other dealings in this Software without prior written
2705b261ecSmrg * authorization from the Hewlett-Packard Company.
2805b261ecSmrg *
2905b261ecSmrg *     Machine-independent DBE code
3005b261ecSmrg *
3105b261ecSmrg *****************************************************************************/
3205b261ecSmrg
3305b261ecSmrg
3405b261ecSmrg/* INCLUDES */
3505b261ecSmrg
3605b261ecSmrg#ifdef HAVE_DIX_CONFIG_H
3705b261ecSmrg#include <dix-config.h>
3805b261ecSmrg#endif
3905b261ecSmrg
4005b261ecSmrg#include <X11/X.h>
4105b261ecSmrg#include <X11/Xproto.h>
4205b261ecSmrg#include "misc.h"
4305b261ecSmrg#include "os.h"
4405b261ecSmrg#include "windowstr.h"
4505b261ecSmrg#include "scrnintstr.h"
4605b261ecSmrg#include "pixmapstr.h"
4705b261ecSmrg#include "extnsionst.h"
4805b261ecSmrg#include "dixstruct.h"
4905b261ecSmrg#include "resource.h"
5005b261ecSmrg#include "opaque.h"
5105b261ecSmrg#include "dbestruct.h"
5205b261ecSmrg#include "midbestr.h"
5305b261ecSmrg#include "regionstr.h"
5405b261ecSmrg#include "gcstruct.h"
5505b261ecSmrg#include "inputstr.h"
5605b261ecSmrg#include "midbe.h"
574642e01fSmrg#include "xace.h"
5805b261ecSmrg
5905b261ecSmrg#include <stdio.h>
6005b261ecSmrg
616747b715Smrgstatic DevPrivateKeyRec miDbeWindowPrivPrivKeyRec;
626747b715Smrg#define miDbeWindowPrivPrivKey (&miDbeWindowPrivPrivKeyRec)
6305b261ecSmrg
6405b261ecSmrg
6505b261ecSmrg/******************************************************************************
6605b261ecSmrg *
6705b261ecSmrg * DBE MI Procedure: miDbeGetVisualInfo
6805b261ecSmrg *
6905b261ecSmrg * Description:
7005b261ecSmrg *
7105b261ecSmrg *     This is the MI function for the DbeGetVisualInfo request.  This function
7205b261ecSmrg *     is called through pDbeScreenPriv->GetVisualInfo.  This function is also
7305b261ecSmrg *     called for the DbeAllocateBackBufferName request at the extension level;
7405b261ecSmrg *     it is called by ProcDbeAllocateBackBufferName() in dbe.c.
7505b261ecSmrg *
7605b261ecSmrg *     If memory allocation fails or we can not get the visual info, this
7705b261ecSmrg *     function returns FALSE.  Otherwise, it returns TRUE for success.
7805b261ecSmrg *
7905b261ecSmrg *****************************************************************************/
8005b261ecSmrg
8105b261ecSmrgstatic Bool
8205b261ecSmrgmiDbeGetVisualInfo(ScreenPtr pScreen, XdbeScreenVisualInfo *pScrVisInfo)
8305b261ecSmrg{
8405b261ecSmrg    register int	i, j, k;
8505b261ecSmrg    register int	count;
8605b261ecSmrg    DepthPtr		pDepth;
8705b261ecSmrg    XdbeVisualInfo	*visInfo;
8805b261ecSmrg
8905b261ecSmrg
9005b261ecSmrg    /* Determine number of visuals for this screen. */
9105b261ecSmrg    for (i = 0, count = 0; i < pScreen->numDepths; i++)
9205b261ecSmrg    {
9305b261ecSmrg        count += pScreen->allowedDepths[i].numVids;
9405b261ecSmrg    }
9505b261ecSmrg
9605b261ecSmrg    /* Allocate an array of XdbeVisualInfo items. */
976747b715Smrg    if (!(visInfo = (XdbeVisualInfo *)malloc(count * sizeof(XdbeVisualInfo))))
9805b261ecSmrg    {
996747b715Smrg        return FALSE; /* memory alloc failure */
10005b261ecSmrg    }
10105b261ecSmrg
10205b261ecSmrg    for (i = 0, k = 0; i < pScreen->numDepths; i++)
10305b261ecSmrg    {
10405b261ecSmrg        /* For each depth of this screen, get visual information. */
10505b261ecSmrg
10605b261ecSmrg        pDepth = &pScreen->allowedDepths[i];
10705b261ecSmrg
10805b261ecSmrg        for (j = 0; j < pDepth->numVids; j++)
10905b261ecSmrg        {
11005b261ecSmrg            /* For each visual for this depth of this screen, get visual ID
11105b261ecSmrg             * and visual depth.  Since this is MI code, we will always return
11205b261ecSmrg             * the same performance level for all visuals (0).  A higher
11305b261ecSmrg             * performance level value indicates higher performance.
11405b261ecSmrg             */
11505b261ecSmrg            visInfo[k].visual    = pDepth->vids[j];
11605b261ecSmrg            visInfo[k].depth     = pDepth->depth;
11705b261ecSmrg            visInfo[k].perflevel = 0;
11805b261ecSmrg            k++;
11905b261ecSmrg        }
12005b261ecSmrg    }
12105b261ecSmrg
12205b261ecSmrg    /* Record the number of visuals and point visual_depth to
12305b261ecSmrg     * the array of visual info.
12405b261ecSmrg     */
12505b261ecSmrg    pScrVisInfo->count   = count;
12605b261ecSmrg    pScrVisInfo->visinfo = visInfo;
12705b261ecSmrg
1286747b715Smrg    return TRUE; /* success */
12905b261ecSmrg
13005b261ecSmrg} /* miDbeGetVisualInfo() */
13105b261ecSmrg
13205b261ecSmrg
13305b261ecSmrg/******************************************************************************
13405b261ecSmrg *
13505b261ecSmrg * DBE MI Procedure: miAllocBackBufferName
13605b261ecSmrg *
13705b261ecSmrg * Description:
13805b261ecSmrg *
13905b261ecSmrg *     This is the MI function for the DbeAllocateBackBufferName request.
14005b261ecSmrg *
14105b261ecSmrg *****************************************************************************/
14205b261ecSmrg
14305b261ecSmrgstatic int
14405b261ecSmrgmiDbeAllocBackBufferName(WindowPtr pWin, XID bufId, int swapAction)
14505b261ecSmrg{
14605b261ecSmrg    ScreenPtr			pScreen;
14705b261ecSmrg    DbeWindowPrivPtr		pDbeWindowPriv;
14805b261ecSmrg    MiDbeWindowPrivPrivPtr	pDbeWindowPrivPriv;
14905b261ecSmrg    DbeScreenPrivPtr		pDbeScreenPriv;
15005b261ecSmrg    GCPtr			pGC;
15105b261ecSmrg    xRectangle			clearRect;
1524642e01fSmrg    int				rc;
15305b261ecSmrg
15405b261ecSmrg
15505b261ecSmrg    pScreen = pWin->drawable.pScreen;
15605b261ecSmrg    pDbeWindowPriv = DBE_WINDOW_PRIV(pWin);
15705b261ecSmrg
15805b261ecSmrg    if (pDbeWindowPriv->nBufferIDs == 0)
15905b261ecSmrg    {
16005b261ecSmrg        /* There is no buffer associated with the window.
16105b261ecSmrg         * We have to create the window priv priv.  Remember, the window
16205b261ecSmrg         * priv was created at the DIX level, so all we need to do is
16305b261ecSmrg         * create the priv priv and attach it to the priv.
16405b261ecSmrg         */
16505b261ecSmrg
16605b261ecSmrg        pDbeScreenPriv = DBE_SCREEN_PRIV(pScreen);
16705b261ecSmrg
16805b261ecSmrg        /* Setup the window priv priv. */
16905b261ecSmrg        pDbeWindowPrivPriv = MI_DBE_WINDOW_PRIV_PRIV(pDbeWindowPriv);
17005b261ecSmrg        pDbeWindowPrivPriv->pDbeWindowPriv = pDbeWindowPriv;
17105b261ecSmrg
17205b261ecSmrg        /* Get a front pixmap. */
17305b261ecSmrg        if (!(pDbeWindowPrivPriv->pFrontBuffer =
17405b261ecSmrg            (*pScreen->CreatePixmap)(pScreen, pDbeWindowPriv->width,
17505b261ecSmrg                                     pDbeWindowPriv->height,
1764642e01fSmrg                                     pWin->drawable.depth, 0)))
17705b261ecSmrg        {
1786747b715Smrg            return BadAlloc;
17905b261ecSmrg        }
18005b261ecSmrg
18105b261ecSmrg        /* Get a back pixmap. */
18205b261ecSmrg        if (!(pDbeWindowPrivPriv->pBackBuffer =
18305b261ecSmrg            (*pScreen->CreatePixmap)(pScreen, pDbeWindowPriv->width,
18405b261ecSmrg                                     pDbeWindowPriv->height,
1854642e01fSmrg                                     pWin->drawable.depth, 0)))
18605b261ecSmrg        {
18705b261ecSmrg            (*pScreen->DestroyPixmap)(pDbeWindowPrivPriv->pFrontBuffer);
1886747b715Smrg            return BadAlloc;
18905b261ecSmrg        }
19005b261ecSmrg
1914642e01fSmrg	/* Security creation/labeling check. */
1924642e01fSmrg	rc = XaceHook(XACE_RESOURCE_ACCESS, serverClient, bufId,
1934642e01fSmrg		      dbeDrawableResType, pDbeWindowPrivPriv->pBackBuffer,
1944642e01fSmrg		      RT_WINDOW, pWin, DixCreateAccess);
19505b261ecSmrg
19605b261ecSmrg        /* Make the back pixmap a DBE drawable resource. */
1974642e01fSmrg        if (rc != Success || !AddResource(bufId, dbeDrawableResType,
1984642e01fSmrg					  pDbeWindowPrivPriv->pBackBuffer))
19905b261ecSmrg        {
20005b261ecSmrg            /* free the buffer and the drawable resource */
20105b261ecSmrg            FreeResource(bufId, RT_NONE);
2024642e01fSmrg            return (rc == Success) ? BadAlloc : rc;
20305b261ecSmrg        }
20405b261ecSmrg
20505b261ecSmrg        /* Clear the back buffer. */
20605b261ecSmrg        pGC = GetScratchGC(pWin->drawable.depth, pWin->drawable.pScreen);
20705b261ecSmrg        if ((*pDbeScreenPriv->SetupBackgroundPainter)(pWin, pGC))
20805b261ecSmrg        {
20905b261ecSmrg            ValidateGC((DrawablePtr)pDbeWindowPrivPriv->pBackBuffer, pGC);
21005b261ecSmrg            clearRect.x = clearRect.y = 0;
21105b261ecSmrg            clearRect.width  = pDbeWindowPrivPriv->pBackBuffer->drawable.width;
21205b261ecSmrg            clearRect.height = pDbeWindowPrivPriv->pBackBuffer->drawable.height;
21305b261ecSmrg            (*pGC->ops->PolyFillRect)(
21405b261ecSmrg                (DrawablePtr)pDbeWindowPrivPriv->pBackBuffer, pGC, 1,
21505b261ecSmrg                &clearRect);
21605b261ecSmrg        }
21705b261ecSmrg        FreeScratchGC(pGC);
21805b261ecSmrg
21905b261ecSmrg    } /* if no buffer associated with the window */
22005b261ecSmrg
22105b261ecSmrg    else
22205b261ecSmrg    {
22305b261ecSmrg        /* A buffer is already associated with the window.
22405b261ecSmrg         * Place the new buffer ID information at the head of the ID list.
22505b261ecSmrg         */
22605b261ecSmrg
22705b261ecSmrg        /* Associate the new ID with an existing pixmap. */
22805b261ecSmrg        pDbeWindowPrivPriv = MI_DBE_WINDOW_PRIV_PRIV(pDbeWindowPriv);
22905b261ecSmrg        if (!AddResource(bufId, dbeDrawableResType,
23005b261ecSmrg                         (pointer)pDbeWindowPrivPriv->pBackBuffer))
23105b261ecSmrg        {
2326747b715Smrg            return BadAlloc;
23305b261ecSmrg        }
23405b261ecSmrg
23505b261ecSmrg    }
23605b261ecSmrg
2376747b715Smrg    return Success;
23805b261ecSmrg
23905b261ecSmrg} /* miDbeAllocBackBufferName() */
24005b261ecSmrg
24105b261ecSmrg
24205b261ecSmrg/******************************************************************************
24305b261ecSmrg *
24405b261ecSmrg * DBE MI Procedure: miDbeAliasBuffers
24505b261ecSmrg *
24605b261ecSmrg * Description:
24705b261ecSmrg *
24805b261ecSmrg *     This function associates all XIDs of a buffer with the back pixmap
24905b261ecSmrg *     stored in the window priv.
25005b261ecSmrg *
25105b261ecSmrg *****************************************************************************/
25205b261ecSmrg
25305b261ecSmrgstatic void
25405b261ecSmrgmiDbeAliasBuffers(DbeWindowPrivPtr pDbeWindowPriv)
25505b261ecSmrg{
25605b261ecSmrg    int				i;
25705b261ecSmrg    MiDbeWindowPrivPrivPtr	pDbeWindowPrivPriv =
25805b261ecSmrg                                    MI_DBE_WINDOW_PRIV_PRIV(pDbeWindowPriv);
25905b261ecSmrg
26005b261ecSmrg    for (i = 0; i < pDbeWindowPriv->nBufferIDs; i++)
26105b261ecSmrg    {
26205b261ecSmrg        ChangeResourceValue(pDbeWindowPriv->IDs[i], dbeDrawableResType,
26305b261ecSmrg                            (pointer)pDbeWindowPrivPriv->pBackBuffer);
26405b261ecSmrg    }
26505b261ecSmrg
26605b261ecSmrg} /* miDbeAliasBuffers() */
26705b261ecSmrg
26805b261ecSmrg
26905b261ecSmrg/******************************************************************************
27005b261ecSmrg *
27105b261ecSmrg * DBE MI Procedure: miDbeSwapBuffers
27205b261ecSmrg *
27305b261ecSmrg * Description:
27405b261ecSmrg *
27505b261ecSmrg *     This is the MI function for the DbeSwapBuffers request.
27605b261ecSmrg *
27705b261ecSmrg *****************************************************************************/
27805b261ecSmrg
27905b261ecSmrgstatic int
28005b261ecSmrgmiDbeSwapBuffers(ClientPtr client, int *pNumWindows, DbeSwapInfoPtr swapInfo)
28105b261ecSmrg{
28205b261ecSmrg    DbeScreenPrivPtr		pDbeScreenPriv;
28305b261ecSmrg    GCPtr		    	pGC;
28405b261ecSmrg    WindowPtr		    	pWin;
28505b261ecSmrg    MiDbeWindowPrivPrivPtr	pDbeWindowPrivPriv;
28605b261ecSmrg    PixmapPtr			pTmpBuffer;
28705b261ecSmrg    xRectangle			clearRect;
28805b261ecSmrg
28905b261ecSmrg
29005b261ecSmrg    pWin               = swapInfo[0].pWindow;
29105b261ecSmrg    pDbeScreenPriv     = DBE_SCREEN_PRIV_FROM_WINDOW(pWin);
29205b261ecSmrg    pDbeWindowPrivPriv = MI_DBE_WINDOW_PRIV_PRIV_FROM_WINDOW(pWin);
29305b261ecSmrg    pGC = GetScratchGC(pWin->drawable.depth, pWin->drawable.pScreen);
29405b261ecSmrg
29505b261ecSmrg    /*
29605b261ecSmrg     **********************************************************************
29705b261ecSmrg     ** Setup before swap.
29805b261ecSmrg     **********************************************************************
29905b261ecSmrg     */
30005b261ecSmrg
30105b261ecSmrg    switch(swapInfo[0].swapAction)
30205b261ecSmrg    {
30305b261ecSmrg        case XdbeUndefined:
30405b261ecSmrg            break;
30505b261ecSmrg
30605b261ecSmrg        case XdbeBackground:
30705b261ecSmrg            break;
30805b261ecSmrg
30905b261ecSmrg        case XdbeUntouched:
31005b261ecSmrg            ValidateGC((DrawablePtr)pDbeWindowPrivPriv->pFrontBuffer, pGC);
31105b261ecSmrg            (*pGC->ops->CopyArea)((DrawablePtr)pWin,
31205b261ecSmrg                                  (DrawablePtr)pDbeWindowPrivPriv->pFrontBuffer,
31305b261ecSmrg                                  pGC, 0, 0, pWin->drawable.width,
31405b261ecSmrg                                  pWin->drawable.height, 0, 0);
31505b261ecSmrg            break;
31605b261ecSmrg
31705b261ecSmrg        case XdbeCopied:
31805b261ecSmrg            break;
31905b261ecSmrg
32005b261ecSmrg    }
32105b261ecSmrg
32205b261ecSmrg    /*
32305b261ecSmrg     **********************************************************************
32405b261ecSmrg     ** Swap.
32505b261ecSmrg     **********************************************************************
32605b261ecSmrg     */
32705b261ecSmrg
32805b261ecSmrg    ValidateGC((DrawablePtr)pWin, pGC);
32905b261ecSmrg    (*pGC->ops->CopyArea)((DrawablePtr)pDbeWindowPrivPriv->pBackBuffer,
33005b261ecSmrg                          (DrawablePtr)pWin, pGC, 0, 0,
33105b261ecSmrg                          pWin->drawable.width, pWin->drawable.height,
33205b261ecSmrg                          0, 0);
33305b261ecSmrg
33405b261ecSmrg    /*
33505b261ecSmrg     **********************************************************************
33605b261ecSmrg     ** Tasks after swap.
33705b261ecSmrg     **********************************************************************
33805b261ecSmrg     */
33905b261ecSmrg
34005b261ecSmrg    switch(swapInfo[0].swapAction)
34105b261ecSmrg    {
34205b261ecSmrg        case XdbeUndefined:
34305b261ecSmrg            break;
34405b261ecSmrg
34505b261ecSmrg        case XdbeBackground:
34605b261ecSmrg            if ((*pDbeScreenPriv->SetupBackgroundPainter)(pWin, pGC))
34705b261ecSmrg            {
34805b261ecSmrg                ValidateGC((DrawablePtr)pDbeWindowPrivPriv->pBackBuffer, pGC);
34905b261ecSmrg                clearRect.x = 0;
35005b261ecSmrg                clearRect.y = 0;
35105b261ecSmrg                clearRect.width =
35205b261ecSmrg                    pDbeWindowPrivPriv->pBackBuffer->drawable.width;
35305b261ecSmrg                clearRect.height =
35405b261ecSmrg                    pDbeWindowPrivPriv->pBackBuffer->drawable.height;
35505b261ecSmrg                (*pGC->ops->PolyFillRect)(
35605b261ecSmrg				(DrawablePtr)pDbeWindowPrivPriv->pBackBuffer,
35705b261ecSmrg				pGC, 1, &clearRect);
35805b261ecSmrg	    }
35905b261ecSmrg            break;
36005b261ecSmrg
36105b261ecSmrg        case XdbeUntouched:
36205b261ecSmrg            /* Swap pixmap pointers. */
36305b261ecSmrg            pTmpBuffer = pDbeWindowPrivPriv->pBackBuffer;
36405b261ecSmrg            pDbeWindowPrivPriv->pBackBuffer =
36505b261ecSmrg                pDbeWindowPrivPriv->pFrontBuffer;
36605b261ecSmrg            pDbeWindowPrivPriv->pFrontBuffer = pTmpBuffer;
36705b261ecSmrg
36805b261ecSmrg            miDbeAliasBuffers(pDbeWindowPrivPriv->pDbeWindowPriv);
36905b261ecSmrg
37005b261ecSmrg            break;
37105b261ecSmrg
37205b261ecSmrg        case XdbeCopied:
37305b261ecSmrg            break;
37405b261ecSmrg
37505b261ecSmrg    }
37605b261ecSmrg
37705b261ecSmrg    /* Remove the swapped window from the swap information array and decrement
37805b261ecSmrg     * pNumWindows to indicate to the DIX level how many windows were actually
37905b261ecSmrg     * swapped.
38005b261ecSmrg     */
38105b261ecSmrg
38205b261ecSmrg    if (*pNumWindows > 1)
38305b261ecSmrg    {
38405b261ecSmrg        /* We were told to swap more than one window, but we only swapped the
38505b261ecSmrg         * first one.  Remove the first window in the list by moving the last
38605b261ecSmrg         * window to the beginning.
38705b261ecSmrg         */
38805b261ecSmrg        swapInfo[0].pWindow    = swapInfo[*pNumWindows - 1].pWindow;
38905b261ecSmrg        swapInfo[0].swapAction = swapInfo[*pNumWindows - 1].swapAction;
39005b261ecSmrg
39105b261ecSmrg        /* Clear the last window information just to be safe. */
39205b261ecSmrg        swapInfo[*pNumWindows - 1].pWindow    = (WindowPtr)NULL;
39305b261ecSmrg        swapInfo[*pNumWindows - 1].swapAction = 0;
39405b261ecSmrg    }
39505b261ecSmrg    else
39605b261ecSmrg    {
39705b261ecSmrg        /* Clear the window information just to be safe. */
39805b261ecSmrg        swapInfo[0].pWindow    = (WindowPtr)NULL;
39905b261ecSmrg        swapInfo[0].swapAction = 0;
40005b261ecSmrg    }
40105b261ecSmrg
40205b261ecSmrg    (*pNumWindows)--;
40305b261ecSmrg
40405b261ecSmrg    FreeScratchGC(pGC);
40505b261ecSmrg
4066747b715Smrg    return Success;
40705b261ecSmrg
40805b261ecSmrg} /* miSwapBuffers() */
40905b261ecSmrg
41005b261ecSmrg
41105b261ecSmrg/******************************************************************************
41205b261ecSmrg *
41305b261ecSmrg * DBE MI Procedure: miDbeWinPrivDelete
41405b261ecSmrg *
41505b261ecSmrg * Description:
41605b261ecSmrg *
41705b261ecSmrg *     This is the MI function for deleting the dbeWindowPrivResType resource.
41805b261ecSmrg *     This function is invoked indirectly by calling FreeResource() to free
41905b261ecSmrg *     the resources associated with a DBE buffer ID.  There are 5 ways that
42005b261ecSmrg *     miDbeWinPrivDelete() can be called by FreeResource().  They are:
42105b261ecSmrg *
42205b261ecSmrg *     - A DBE window is destroyed, in which case the DbeDestroyWindow()
42305b261ecSmrg *       wrapper is invoked.  The wrapper calls FreeResource() for all DBE
42405b261ecSmrg *       buffer IDs.
42505b261ecSmrg *
42605b261ecSmrg *     - miDbeAllocBackBufferName() calls FreeResource() to clean up resources
42705b261ecSmrg *       after a buffer allocation failure.
42805b261ecSmrg *
42905b261ecSmrg *     - The PositionWindow wrapper, miDbePositionWindow(), calls
43005b261ecSmrg *       FreeResource() when it fails to create buffers of the new size.
43105b261ecSmrg *       FreeResource() is called for all DBE buffer IDs.
43205b261ecSmrg *
43305b261ecSmrg *     - FreeClientResources() calls FreeResource() when a client dies or the
43405b261ecSmrg *       the server resets.
43505b261ecSmrg *
43605b261ecSmrg *     When FreeResource() is called for a DBE buffer ID, the delete function
43705b261ecSmrg *     for the only other type of DBE resource, dbeDrawableResType, is also
43805b261ecSmrg *     invoked.  This delete function (DbeDrawableDelete) is a NOOP to make
43905b261ecSmrg *     resource deletion easier.  It is not guaranteed which delete function is
44005b261ecSmrg *     called first.  Hence, we will let miDbeWinPrivDelete() free all DBE
44105b261ecSmrg *     resources.
44205b261ecSmrg *
44305b261ecSmrg *     This function deletes/frees the following stuff associated with
44405b261ecSmrg *     the window private:
44505b261ecSmrg *
44605b261ecSmrg *     - the ID node in the ID list representing the passed in ID.
44705b261ecSmrg *
44805b261ecSmrg *     In addition, pDbeWindowPriv->nBufferIDs is decremented.
44905b261ecSmrg *
45005b261ecSmrg *     If this function is called for the last/only buffer ID for a window,
45105b261ecSmrg *     these are additionally deleted/freed:
45205b261ecSmrg *
45305b261ecSmrg *     - the front and back pixmaps
45405b261ecSmrg *     - the window priv itself
45505b261ecSmrg *
45605b261ecSmrg *****************************************************************************/
45705b261ecSmrg
45805b261ecSmrgstatic void
45905b261ecSmrgmiDbeWinPrivDelete(DbeWindowPrivPtr pDbeWindowPriv, XID bufId)
46005b261ecSmrg{
46105b261ecSmrg    MiDbeWindowPrivPrivPtr	pDbeWindowPrivPriv;
46205b261ecSmrg
46305b261ecSmrg
46405b261ecSmrg    if (pDbeWindowPriv->nBufferIDs != 0)
46505b261ecSmrg    {
46605b261ecSmrg        /* We still have at least one more buffer ID associated with this
46705b261ecSmrg         * window.
46805b261ecSmrg         */
46905b261ecSmrg        return;
47005b261ecSmrg    }
47105b261ecSmrg
47205b261ecSmrg
47305b261ecSmrg    /* We have no more buffer IDs associated with this window.  We need to
47405b261ecSmrg     * free some stuff.
47505b261ecSmrg     */
47605b261ecSmrg
47705b261ecSmrg    pDbeWindowPrivPriv = MI_DBE_WINDOW_PRIV_PRIV(pDbeWindowPriv);
47805b261ecSmrg
47905b261ecSmrg    /* Destroy the front and back pixmaps. */
48005b261ecSmrg    if (pDbeWindowPrivPriv->pFrontBuffer)
48105b261ecSmrg    {
48205b261ecSmrg        (*pDbeWindowPriv->pWindow->drawable.pScreen->DestroyPixmap)(
48305b261ecSmrg            pDbeWindowPrivPriv->pFrontBuffer);
48405b261ecSmrg    }
48505b261ecSmrg    if (pDbeWindowPrivPriv->pBackBuffer)
48605b261ecSmrg    {
48705b261ecSmrg        (*pDbeWindowPriv->pWindow->drawable.pScreen->DestroyPixmap)(
48805b261ecSmrg            pDbeWindowPrivPriv->pBackBuffer);
48905b261ecSmrg    }
49005b261ecSmrg
49105b261ecSmrg} /* miDbeWinPrivDelete() */
49205b261ecSmrg
49305b261ecSmrg
49405b261ecSmrg/******************************************************************************
49505b261ecSmrg *
49605b261ecSmrg * DBE MI Procedure: miDbePositionWindow
49705b261ecSmrg *
49805b261ecSmrg * Description:
49905b261ecSmrg *
50005b261ecSmrg *     This function was cloned from miMbxPositionWindow() in mimultibuf.c.
50105b261ecSmrg *     This function resizes the buffer when the window is resized.
50205b261ecSmrg *
50305b261ecSmrg *****************************************************************************/
50405b261ecSmrg
50505b261ecSmrgstatic Bool
50605b261ecSmrgmiDbePositionWindow(WindowPtr pWin, int x, int y)
50705b261ecSmrg{
50805b261ecSmrg    ScreenPtr			pScreen;
50905b261ecSmrg    DbeScreenPrivPtr		pDbeScreenPriv;
51005b261ecSmrg    DbeWindowPrivPtr		pDbeWindowPriv;
51105b261ecSmrg    int				width, height;
51205b261ecSmrg    int				dx, dy, dw, dh;
51305b261ecSmrg    int				sourcex, sourcey;
51405b261ecSmrg    int				destx, desty;
51505b261ecSmrg    int				savewidth, saveheight;
51605b261ecSmrg    PixmapPtr			pFrontBuffer;
51705b261ecSmrg    PixmapPtr			pBackBuffer;
51805b261ecSmrg    Bool			clear;
51905b261ecSmrg    GCPtr			pGC;
52005b261ecSmrg    xRectangle			clearRect;
52105b261ecSmrg    Bool			ret;
52205b261ecSmrg
52305b261ecSmrg
52405b261ecSmrg    /*
52505b261ecSmrg     **************************************************************************
52605b261ecSmrg     ** 1. Unwrap the member routine.
52705b261ecSmrg     **************************************************************************
52805b261ecSmrg     */
52905b261ecSmrg
53005b261ecSmrg    pScreen                 = pWin->drawable.pScreen;
53105b261ecSmrg    pDbeScreenPriv          = DBE_SCREEN_PRIV(pScreen);
53205b261ecSmrg    pScreen->PositionWindow = pDbeScreenPriv->PositionWindow;
53305b261ecSmrg
53405b261ecSmrg    /*
53505b261ecSmrg     **************************************************************************
53605b261ecSmrg     ** 2. Do any work necessary before the member routine is called.
53705b261ecSmrg     **
53805b261ecSmrg     **    In this case we do not need to do anything.
53905b261ecSmrg     **************************************************************************
54005b261ecSmrg     */
54105b261ecSmrg
54205b261ecSmrg    /*
54305b261ecSmrg     **************************************************************************
54405b261ecSmrg     ** 3. Call the member routine, saving its result if necessary.
54505b261ecSmrg     **************************************************************************
54605b261ecSmrg     */
54705b261ecSmrg
54805b261ecSmrg    ret = (*pScreen->PositionWindow)(pWin, x, y);
54905b261ecSmrg
55005b261ecSmrg    /*
55105b261ecSmrg     **************************************************************************
55205b261ecSmrg     ** 4. Rewrap the member routine, restoring the wrapper value first in case
55305b261ecSmrg     **    the wrapper (or something that it wrapped) change this value.
55405b261ecSmrg     **************************************************************************
55505b261ecSmrg     */
55605b261ecSmrg
55705b261ecSmrg    pDbeScreenPriv->PositionWindow = pScreen->PositionWindow;
55805b261ecSmrg    pScreen->PositionWindow = miDbePositionWindow;
55905b261ecSmrg
56005b261ecSmrg    /*
56105b261ecSmrg     **************************************************************************
56205b261ecSmrg     ** 5. Do any work necessary after the member routine has been called.
56305b261ecSmrg     **************************************************************************
56405b261ecSmrg     */
56505b261ecSmrg
56605b261ecSmrg    if (!(pDbeWindowPriv = DBE_WINDOW_PRIV(pWin)))
56705b261ecSmrg    {
5686747b715Smrg	return ret;
56905b261ecSmrg    }
57005b261ecSmrg
57105b261ecSmrg    if (pDbeWindowPriv->width  == pWin->drawable.width &&
57205b261ecSmrg        pDbeWindowPriv->height == pWin->drawable.height)
57305b261ecSmrg    {
5746747b715Smrg	return ret;
57505b261ecSmrg    }
57605b261ecSmrg
57705b261ecSmrg    width  = pWin->drawable.width;
57805b261ecSmrg    height = pWin->drawable.height;
57905b261ecSmrg
58005b261ecSmrg    dx = pWin->drawable.x - pDbeWindowPriv->x;
58105b261ecSmrg    dy = pWin->drawable.y - pDbeWindowPriv->y;
58205b261ecSmrg    dw = width  - pDbeWindowPriv->width;
58305b261ecSmrg    dh = height - pDbeWindowPriv->height;
58405b261ecSmrg
58505b261ecSmrg    GravityTranslate (0, 0, -dx, -dy, dw, dh, pWin->bitGravity, &destx, &desty);
58605b261ecSmrg
58705b261ecSmrg    clear = ((pDbeWindowPriv->width  < (unsigned short)width ) ||
58805b261ecSmrg             (pDbeWindowPriv->height < (unsigned short)height) ||
58905b261ecSmrg             (pWin->bitGravity == ForgetGravity));
59005b261ecSmrg
59105b261ecSmrg    sourcex = 0;
59205b261ecSmrg    sourcey = 0;
59305b261ecSmrg    savewidth  = pDbeWindowPriv->width;
59405b261ecSmrg    saveheight = pDbeWindowPriv->height;
59505b261ecSmrg
59605b261ecSmrg    /* Clip rectangle to source and destination. */
59705b261ecSmrg    if (destx < 0)
59805b261ecSmrg    {
59905b261ecSmrg	savewidth += destx;
60005b261ecSmrg	sourcex   -= destx;
60105b261ecSmrg	destx      = 0;
60205b261ecSmrg    }
60305b261ecSmrg
60405b261ecSmrg    if (destx + savewidth > width)
60505b261ecSmrg    {
60605b261ecSmrg	savewidth = width - destx;
60705b261ecSmrg    }
60805b261ecSmrg
60905b261ecSmrg    if (desty < 0)
61005b261ecSmrg    {
61105b261ecSmrg	saveheight += desty;
61205b261ecSmrg	sourcey    -= desty;
61305b261ecSmrg	desty       = 0;
61405b261ecSmrg    }
61505b261ecSmrg
61605b261ecSmrg    if (desty + saveheight > height)
61705b261ecSmrg    {
61805b261ecSmrg	saveheight = height - desty;
61905b261ecSmrg    }
62005b261ecSmrg
62105b261ecSmrg    pDbeWindowPriv->width  = width;
62205b261ecSmrg    pDbeWindowPriv->height = height;
62305b261ecSmrg    pDbeWindowPriv->x = pWin->drawable.x;
62405b261ecSmrg    pDbeWindowPriv->y = pWin->drawable.y;
62505b261ecSmrg
62605b261ecSmrg    pGC = GetScratchGC (pWin->drawable.depth, pScreen);
62705b261ecSmrg
62805b261ecSmrg    if (clear)
62905b261ecSmrg    {
63005b261ecSmrg	if ((*pDbeScreenPriv->SetupBackgroundPainter)(pWin, pGC))
63105b261ecSmrg	{
63205b261ecSmrg	    clearRect.x = 0;
63305b261ecSmrg	    clearRect.y = 0;
63405b261ecSmrg	    clearRect.width  = width;
63505b261ecSmrg	    clearRect.height = height;
63605b261ecSmrg	}
63705b261ecSmrg	else
63805b261ecSmrg	{
63905b261ecSmrg	    clear = FALSE;
64005b261ecSmrg	}
64105b261ecSmrg    }
64205b261ecSmrg
64305b261ecSmrg    /* Create DBE buffer pixmaps equal to size of resized window. */
64405b261ecSmrg    pFrontBuffer = (*pScreen->CreatePixmap)(pScreen, width, height,
6454642e01fSmrg					    pWin->drawable.depth, 0);
64605b261ecSmrg
64705b261ecSmrg    pBackBuffer = (*pScreen->CreatePixmap)(pScreen, width, height,
6484642e01fSmrg					   pWin->drawable.depth, 0);
64905b261ecSmrg
65005b261ecSmrg    if (!pFrontBuffer || !pBackBuffer)
65105b261ecSmrg    {
65205b261ecSmrg        /* We failed at creating 1 or 2 of the pixmaps. */
65305b261ecSmrg
65405b261ecSmrg        if (pFrontBuffer)
65505b261ecSmrg        {
65605b261ecSmrg	    (*pScreen->DestroyPixmap)(pFrontBuffer);
65705b261ecSmrg        }
65805b261ecSmrg
65905b261ecSmrg        if (pBackBuffer)
66005b261ecSmrg        {
66105b261ecSmrg	    (*pScreen->DestroyPixmap)(pBackBuffer);
66205b261ecSmrg        }
66305b261ecSmrg
66405b261ecSmrg        /* Destroy all buffers for this window. */
66505b261ecSmrg        while (pDbeWindowPriv)
66605b261ecSmrg        {
66705b261ecSmrg            /* DbeWindowPrivDelete() will free the window private if there no
66805b261ecSmrg             * more buffer IDs associated with this window.
66905b261ecSmrg             */
67005b261ecSmrg            FreeResource(pDbeWindowPriv->IDs[0], RT_NONE);
67105b261ecSmrg            pDbeWindowPriv = DBE_WINDOW_PRIV(pWin);
67205b261ecSmrg        }
67305b261ecSmrg
67405b261ecSmrg        FreeScratchGC(pGC);
6756747b715Smrg        return FALSE;
67605b261ecSmrg    }
67705b261ecSmrg
67805b261ecSmrg    else
67905b261ecSmrg    {
68005b261ecSmrg        /* Clear out the new DBE buffer pixmaps. */
68105b261ecSmrg
68205b261ecSmrg        MiDbeWindowPrivPrivPtr	pDbeWindowPrivPriv;
68305b261ecSmrg
68405b261ecSmrg
68505b261ecSmrg        pDbeWindowPrivPriv = MI_DBE_WINDOW_PRIV_PRIV(pDbeWindowPriv);
68605b261ecSmrg
68705b261ecSmrg	/* I suppose this could avoid quite a bit of work if
68805b261ecSmrg	 * it computed the minimal area required.
68905b261ecSmrg	 */
6906747b715Smrg	ValidateGC(&pFrontBuffer->drawable, pGC);
69105b261ecSmrg	if (clear)
69205b261ecSmrg        {
69305b261ecSmrg	    (*pGC->ops->PolyFillRect)((DrawablePtr)pFrontBuffer, pGC, 1,
69405b261ecSmrg				      &clearRect);
6956747b715Smrg	}
6966747b715Smrg	/* Copy the contents of the old front pixmap to the new one. */
69705b261ecSmrg	if (pWin->bitGravity != ForgetGravity)
69805b261ecSmrg	{
69905b261ecSmrg	    (*pGC->ops->CopyArea)((DrawablePtr)pDbeWindowPrivPriv->pFrontBuffer,
70005b261ecSmrg                                  (DrawablePtr)pFrontBuffer, pGC, sourcex,
70105b261ecSmrg                                  sourcey, savewidth, saveheight, destx, desty);
7026747b715Smrg        }
7036747b715Smrg
7046747b715Smrg	ValidateGC(&pBackBuffer->drawable, pGC);
7056747b715Smrg	if (clear)
7066747b715Smrg	{
7076747b715Smrg	    (*pGC->ops->PolyFillRect)((DrawablePtr)pBackBuffer , pGC, 1,
7086747b715Smrg				      &clearRect);
7096747b715Smrg	}
7106747b715Smrg	/* Copy the contents of the old back pixmap to the new one. */
7116747b715Smrg	if (pWin->bitGravity != ForgetGravity)
7126747b715Smrg	{
71305b261ecSmrg	    (*pGC->ops->CopyArea)((DrawablePtr)pDbeWindowPrivPriv->pBackBuffer,
71405b261ecSmrg                                  (DrawablePtr)pBackBuffer, pGC, sourcex,
71505b261ecSmrg                                  sourcey, savewidth, saveheight, destx, desty);
71605b261ecSmrg	}
71705b261ecSmrg
71805b261ecSmrg        /* Destroy the old pixmaps, and point the DBE window priv to the new
71905b261ecSmrg         * pixmaps.
72005b261ecSmrg         */
72105b261ecSmrg
72205b261ecSmrg	(*pScreen->DestroyPixmap)(pDbeWindowPrivPriv->pFrontBuffer);
72305b261ecSmrg	(*pScreen->DestroyPixmap)(pDbeWindowPrivPriv->pBackBuffer);
72405b261ecSmrg
72505b261ecSmrg        pDbeWindowPrivPriv->pFrontBuffer = pFrontBuffer;
72605b261ecSmrg        pDbeWindowPrivPriv->pBackBuffer  = pBackBuffer;
72705b261ecSmrg
72805b261ecSmrg	/* Make sure all XID are associated with the new back pixmap. */
72905b261ecSmrg        miDbeAliasBuffers(pDbeWindowPriv);
73005b261ecSmrg
73105b261ecSmrg        FreeScratchGC(pGC);
73205b261ecSmrg    }
73305b261ecSmrg
7346747b715Smrg    return ret;
73505b261ecSmrg
73605b261ecSmrg} /* miDbePositionWindow() */
73705b261ecSmrg
73805b261ecSmrg
73905b261ecSmrg/******************************************************************************
74005b261ecSmrg *
74105b261ecSmrg * DBE MI Procedure: miDbeResetProc
74205b261ecSmrg *
74305b261ecSmrg * Description:
74405b261ecSmrg *
74505b261ecSmrg *     This function is called from DbeResetProc(), which is called at the end
74605b261ecSmrg *     of every server generation.  This function peforms any MI-specific
74705b261ecSmrg *     shutdown tasks.
74805b261ecSmrg *
74905b261ecSmrg *****************************************************************************/
75005b261ecSmrg
75105b261ecSmrgstatic void
75205b261ecSmrgmiDbeResetProc(ScreenPtr pScreen)
75305b261ecSmrg{
75405b261ecSmrg    DbeScreenPrivPtr    pDbeScreenPriv;
75505b261ecSmrg
75605b261ecSmrg
75705b261ecSmrg    pDbeScreenPriv = DBE_SCREEN_PRIV(pScreen);
75805b261ecSmrg
75905b261ecSmrg    /* Unwrap wrappers */
76005b261ecSmrg    pScreen->PositionWindow = pDbeScreenPriv->PositionWindow;
76105b261ecSmrg
76205b261ecSmrg} /* miDbeResetProc() */
76305b261ecSmrg
76405b261ecSmrg
76505b261ecSmrg/******************************************************************************
76605b261ecSmrg *
76705b261ecSmrg * DBE MI Procedure: miDbeInit
76805b261ecSmrg *
76905b261ecSmrg * Description:
77005b261ecSmrg *
77105b261ecSmrg *     This is the MI initialization function called by DbeExtensionInit().
77205b261ecSmrg *
77305b261ecSmrg *****************************************************************************/
77405b261ecSmrg
77505b261ecSmrgBool
77605b261ecSmrgmiDbeInit(ScreenPtr pScreen, DbeScreenPrivPtr pDbeScreenPriv)
77705b261ecSmrg{
7786747b715Smrg    if (!dixRegisterPrivateKey(&miDbeWindowPrivPrivKeyRec, PRIVATE_DBE_WINDOW,
7796747b715Smrg			       sizeof(MiDbeWindowPrivPrivRec)))
7806747b715Smrg        return FALSE;
78105b261ecSmrg
78205b261ecSmrg    /* Wrap functions. */
78305b261ecSmrg    pDbeScreenPriv->PositionWindow = pScreen->PositionWindow;
78405b261ecSmrg    pScreen->PositionWindow        = miDbePositionWindow;
78505b261ecSmrg
78605b261ecSmrg    /* Initialize the per-screen DBE function pointers. */
78705b261ecSmrg    pDbeScreenPriv->GetVisualInfo         = miDbeGetVisualInfo;
78805b261ecSmrg    pDbeScreenPriv->AllocBackBufferName   = miDbeAllocBackBufferName;
78905b261ecSmrg    pDbeScreenPriv->SwapBuffers           = miDbeSwapBuffers;
79005b261ecSmrg    pDbeScreenPriv->BeginIdiom            = 0;
79105b261ecSmrg    pDbeScreenPriv->EndIdiom              = 0;
79205b261ecSmrg    pDbeScreenPriv->ResetProc             = miDbeResetProc;
79305b261ecSmrg    pDbeScreenPriv->WinPrivDelete         = miDbeWinPrivDelete;
79405b261ecSmrg
7956747b715Smrg    return TRUE;
79605b261ecSmrg
79705b261ecSmrg} /* miDbeInit() */
798