105b261ecSmrg/**************************************************************************
205b261ecSmrg
305b261ecSmrgCopyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
405b261ecSmrgCopyright 2000 VA Linux Systems, Inc.
505b261ecSmrgAll Rights Reserved.
605b261ecSmrg
705b261ecSmrgPermission is hereby granted, free of charge, to any person obtaining a
805b261ecSmrgcopy of this software and associated documentation files (the
905b261ecSmrg"Software"), to deal in the Software without restriction, including
1005b261ecSmrgwithout limitation the rights to use, copy, modify, merge, publish,
1105b261ecSmrgdistribute, sub license, and/or sell copies of the Software, and to
1205b261ecSmrgpermit persons to whom the Software is furnished to do so, subject to
1305b261ecSmrgthe following conditions:
1405b261ecSmrg
1505b261ecSmrgThe above copyright notice and this permission notice (including the
1605b261ecSmrgnext paragraph) shall be included in all copies or substantial portions
1705b261ecSmrgof the Software.
1805b261ecSmrg
1905b261ecSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
2005b261ecSmrgOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
2105b261ecSmrgMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
2205b261ecSmrgIN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
2305b261ecSmrgANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
2405b261ecSmrgTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
2505b261ecSmrgSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2605b261ecSmrg
2705b261ecSmrg**************************************************************************/
2805b261ecSmrg
2905b261ecSmrg/*
3005b261ecSmrg * Authors:
3105b261ecSmrg *   Jens Owen <jens@tungstengraphics.com>
3205b261ecSmrg *   Rickard E. (Rik) Faith <faith@valinux.com>
3305b261ecSmrg *
3405b261ecSmrg */
3505b261ecSmrg
3605b261ecSmrg#ifdef HAVE_XORG_CONFIG_H
3705b261ecSmrg#include <xorg-config.h>
3805b261ecSmrg#endif
3905b261ecSmrg
4005b261ecSmrg#include "xf86.h"
4105b261ecSmrg#include <sys/time.h>
4205b261ecSmrg#include <unistd.h>
4305b261ecSmrg#include <string.h>
4405b261ecSmrg#include <stdio.h>
4505b261ecSmrg#include <sys/ioctl.h>
4605b261ecSmrg#include <errno.h>
4705b261ecSmrg
4805b261ecSmrg#include <X11/X.h>
4905b261ecSmrg#include <X11/Xproto.h>
5005b261ecSmrg#include "xf86drm.h"
5105b261ecSmrg#include "misc.h"
5205b261ecSmrg#include "dixstruct.h"
5305b261ecSmrg#include "extnsionst.h"
5435c4bbdfSmrg#include "extinit.h"
5505b261ecSmrg#include "colormapst.h"
5605b261ecSmrg#include "cursorstr.h"
5705b261ecSmrg#include "scrnintstr.h"
5805b261ecSmrg#include "windowstr.h"
5905b261ecSmrg#include "servermd.h"
6005b261ecSmrg#define _XF86DRI_SERVER_
616747b715Smrg#include <X11/dri/xf86driproto.h>
6205b261ecSmrg#include "swaprep.h"
6305b261ecSmrg#include "xf86str.h"
6405b261ecSmrg#include "dri.h"
6505b261ecSmrg#include "sarea.h"
6605b261ecSmrg#include "dristruct.h"
6705b261ecSmrg#include "mi.h"
6805b261ecSmrg#include "mipointer.h"
6905b261ecSmrg#include "xf86_OSproc.h"
704642e01fSmrg#include "inputstr.h"
716747b715Smrg#include "xf86VGAarbiter.h"
7235c4bbdfSmrg#include "xf86Extensions.h"
7305b261ecSmrg
7405b261ecSmrgstatic int DRIEntPrivIndex = -1;
756747b715Smrgstatic DevPrivateKeyRec DRIScreenPrivKeyRec;
7635c4bbdfSmrg
776747b715Smrg#define DRIScreenPrivKey (&DRIScreenPrivKeyRec)
786747b715Smrgstatic DevPrivateKeyRec DRIWindowPrivKeyRec;
7935c4bbdfSmrg
806747b715Smrg#define DRIWindowPrivKey (&DRIWindowPrivKeyRec)
8105b261ecSmrgstatic unsigned long DRIGeneration = 0;
8205b261ecSmrgstatic unsigned int DRIDrawableValidationStamp = 0;
8305b261ecSmrg
8405b261ecSmrgstatic RESTYPE DRIDrawablePrivResType;
8505b261ecSmrgstatic RESTYPE DRIContextPrivResType;
8635c4bbdfSmrgstatic void DRIDestroyDummyContext(ScreenPtr pScreen, Bool hasCtxPriv);
8705b261ecSmrg
8805b261ecSmrgdrmServerInfo DRIDRMServerInfo;
8905b261ecSmrg
9035c4bbdfSmrg                                /* Wrapper just like xf86DrvMsg, but
9135c4bbdfSmrg                                   without the verbosity level checking.
9235c4bbdfSmrg                                   This will make it easy to turn off some
9335c4bbdfSmrg                                   messages later, based on verbosity
9435c4bbdfSmrg                                   level. */
9505b261ecSmrg
9605b261ecSmrg/*
9705b261ecSmrg * Since we're already referencing things from the XFree86 common layer in
9805b261ecSmrg * this file, we'd might as well just call xf86VDrvMsgVerb, and have
9905b261ecSmrg * consistent message formatting.  The verbosity of these messages can be
10005b261ecSmrg * easily changed here.
10105b261ecSmrg */
10205b261ecSmrg#define DRI_MSG_VERBOSITY 1
10335c4bbdfSmrg
10435c4bbdfSmrgstatic void
10535c4bbdfSmrgDRIDrvMsg(int scrnIndex, MessageType type, const char *format, ...)
10635c4bbdfSmrg    _X_ATTRIBUTE_PRINTF(3,4);
10735c4bbdfSmrg
10805b261ecSmrgstatic void
10905b261ecSmrgDRIDrvMsg(int scrnIndex, MessageType type, const char *format, ...)
11005b261ecSmrg{
11135c4bbdfSmrg    va_list ap;
11205b261ecSmrg
11305b261ecSmrg    va_start(ap, format);
11405b261ecSmrg    xf86VDrvMsgVerb(scrnIndex, type, DRI_MSG_VERBOSITY, format, ap);
11505b261ecSmrg    va_end(ap);
11605b261ecSmrg}
11705b261ecSmrg
11805b261ecSmrgstatic void
11905b261ecSmrgDRIOpenDRMCleanup(DRIEntPrivPtr pDRIEntPriv)
12005b261ecSmrg{
12105b261ecSmrg    if (pDRIEntPriv->pLSAREA != NULL) {
12235c4bbdfSmrg        drmUnmap(pDRIEntPriv->pLSAREA, pDRIEntPriv->sAreaSize);
12335c4bbdfSmrg        pDRIEntPriv->pLSAREA = NULL;
12405b261ecSmrg    }
12505b261ecSmrg    if (pDRIEntPriv->hLSAREA != 0) {
12635c4bbdfSmrg        drmRmMap(pDRIEntPriv->drmFD, pDRIEntPriv->hLSAREA);
12705b261ecSmrg    }
12805b261ecSmrg    if (pDRIEntPriv->drmFD >= 0) {
12935c4bbdfSmrg        drmClose(pDRIEntPriv->drmFD);
13035c4bbdfSmrg        pDRIEntPriv->drmFD = 0;
13105b261ecSmrg    }
13205b261ecSmrg}
13305b261ecSmrg
13405b261ecSmrgint
13505b261ecSmrgDRIMasterFD(ScrnInfoPtr pScrn)
13605b261ecSmrg{
13705b261ecSmrg    return DRI_ENT_PRIV(pScrn)->drmFD;
13805b261ecSmrg}
13905b261ecSmrg
14005b261ecSmrgvoid *
14105b261ecSmrgDRIMasterSareaPointer(ScrnInfoPtr pScrn)
14205b261ecSmrg{
14305b261ecSmrg    return DRI_ENT_PRIV(pScrn)->pLSAREA;
14405b261ecSmrg}
14505b261ecSmrg
14605b261ecSmrgdrm_handle_t
14705b261ecSmrgDRIMasterSareaHandle(ScrnInfoPtr pScrn)
14805b261ecSmrg{
14905b261ecSmrg    return DRI_ENT_PRIV(pScrn)->hLSAREA;
15005b261ecSmrg}
15105b261ecSmrg
15205b261ecSmrgBool
15305b261ecSmrgDRIOpenDRMMaster(ScrnInfoPtr pScrn,
15435c4bbdfSmrg                 unsigned long sAreaSize,
15535c4bbdfSmrg                 const char *busID, const char *drmDriverName)
15605b261ecSmrg{
15705b261ecSmrg    drmSetVersion saveSv, sv;
15805b261ecSmrg    Bool drmWasAvailable;
15905b261ecSmrg    DRIEntPrivPtr pDRIEntPriv;
16005b261ecSmrg    DRIEntPrivRec tmp;
16105b261ecSmrg    int count;
16205b261ecSmrg    int err;
16305b261ecSmrg
16405b261ecSmrg    if (DRIEntPrivIndex == -1)
16535c4bbdfSmrg        DRIEntPrivIndex = xf86AllocateEntityPrivateIndex();
16605b261ecSmrg
16705b261ecSmrg    pDRIEntPriv = DRI_ENT_PRIV(pScrn);
16805b261ecSmrg
16905b261ecSmrg    if (pDRIEntPriv && pDRIEntPriv->drmFD != -1)
17035c4bbdfSmrg        return TRUE;
17105b261ecSmrg
17205b261ecSmrg    drmWasAvailable = drmAvailable();
17305b261ecSmrg
17405b261ecSmrg    memset(&tmp, 0, sizeof(tmp));
17505b261ecSmrg
17605b261ecSmrg    tmp.drmFD = -1;
17705b261ecSmrg    sv.drm_di_major = 1;
17805b261ecSmrg    sv.drm_di_minor = 1;
17905b261ecSmrg    sv.drm_dd_major = -1;
18005b261ecSmrg
18105b261ecSmrg    saveSv = sv;
18205b261ecSmrg    count = 10;
18305b261ecSmrg    while (count--) {
1841b5d61b8Smrg        tmp.drmFD = drmOpen(drmDriverName, busID);
18505b261ecSmrg
18635c4bbdfSmrg        if (tmp.drmFD < 0) {
18735c4bbdfSmrg            DRIDrvMsg(-1, X_ERROR, "[drm] drmOpen failed.\n");
18835c4bbdfSmrg            goto out_err;
18935c4bbdfSmrg        }
19005b261ecSmrg
19135c4bbdfSmrg        err = drmSetInterfaceVersion(tmp.drmFD, &sv);
19205b261ecSmrg
19335c4bbdfSmrg        if (err != -EPERM)
19435c4bbdfSmrg            break;
19505b261ecSmrg
19635c4bbdfSmrg        sv = saveSv;
19735c4bbdfSmrg        drmClose(tmp.drmFD);
19835c4bbdfSmrg        tmp.drmFD = -1;
19935c4bbdfSmrg        usleep(100000);
20005b261ecSmrg    }
20105b261ecSmrg
20205b261ecSmrg    if (tmp.drmFD <= 0) {
20335c4bbdfSmrg        DRIDrvMsg(-1, X_ERROR, "[drm] DRM was busy with another master.\n");
20435c4bbdfSmrg        goto out_err;
20505b261ecSmrg    }
20605b261ecSmrg
20705b261ecSmrg    if (!drmWasAvailable) {
20835c4bbdfSmrg        DRIDrvMsg(-1, X_INFO,
20935c4bbdfSmrg                  "[drm] loaded kernel module for \"%s\" driver.\n",
21035c4bbdfSmrg                  drmDriverName);
21105b261ecSmrg    }
21205b261ecSmrg
21305b261ecSmrg    if (err != 0) {
21435c4bbdfSmrg        sv.drm_di_major = 1;
21535c4bbdfSmrg        sv.drm_di_minor = 0;
21605b261ecSmrg    }
21705b261ecSmrg
21805b261ecSmrg    DRIDrvMsg(-1, X_INFO, "[drm] DRM interface version %d.%d\n",
21935c4bbdfSmrg              sv.drm_di_major, sv.drm_di_minor);
22005b261ecSmrg
22105b261ecSmrg    if (sv.drm_di_major == 1 && sv.drm_di_minor >= 1)
22235c4bbdfSmrg        err = 0;
22305b261ecSmrg    else
22435c4bbdfSmrg        err = drmSetBusid(tmp.drmFD, busID);
22505b261ecSmrg
22605b261ecSmrg    if (err) {
22735c4bbdfSmrg        DRIDrvMsg(-1, X_ERROR, "[drm] Could not set DRM device bus ID.\n");
22835c4bbdfSmrg        goto out_err;
22905b261ecSmrg    }
23005b261ecSmrg
23105b261ecSmrg    /*
23205b261ecSmrg     * Create a lock-containing sarea.
23305b261ecSmrg     */
23405b261ecSmrg
23535c4bbdfSmrg    if (drmAddMap(tmp.drmFD, 0, sAreaSize, DRM_SHM,
23635c4bbdfSmrg                  DRM_CONTAINS_LOCK, &tmp.hLSAREA) < 0) {
23705b261ecSmrg        DRIDrvMsg(-1, X_INFO, "[drm] Could not create SAREA for DRM lock.\n");
23835c4bbdfSmrg        tmp.hLSAREA = 0;
23935c4bbdfSmrg        goto out_err;
24005b261ecSmrg    }
24105b261ecSmrg
24235c4bbdfSmrg    if (drmMap(tmp.drmFD, tmp.hLSAREA, sAreaSize,
24335c4bbdfSmrg               (drmAddressPtr) (&tmp.pLSAREA)) < 0) {
24405b261ecSmrg        DRIDrvMsg(-1, X_INFO, "[drm] Mapping SAREA for DRM lock failed.\n");
24535c4bbdfSmrg        tmp.pLSAREA = NULL;
24635c4bbdfSmrg        goto out_err;
24705b261ecSmrg    }
24805b261ecSmrg
24905b261ecSmrg    memset(tmp.pLSAREA, 0, sAreaSize);
25005b261ecSmrg
25105b261ecSmrg    /*
25205b261ecSmrg     * Reserved contexts are handled by the first opened screen.
25305b261ecSmrg     */
25405b261ecSmrg
25505b261ecSmrg    tmp.resOwner = NULL;
25605b261ecSmrg
25705b261ecSmrg    if (!pDRIEntPriv)
25835c4bbdfSmrg        pDRIEntPriv = xnfcalloc(sizeof(*pDRIEntPriv), 1);
25905b261ecSmrg
26005b261ecSmrg    if (!pDRIEntPriv) {
26105b261ecSmrg        DRIDrvMsg(-1, X_INFO, "[drm] Failed to allocate memory for "
26235c4bbdfSmrg                  "DRM device.\n");
26335c4bbdfSmrg        goto out_err;
26405b261ecSmrg    }
26505b261ecSmrg    *pDRIEntPriv = tmp;
26635c4bbdfSmrg    xf86GetEntityPrivate((pScrn)->entityList[0], DRIEntPrivIndex)->ptr =
26735c4bbdfSmrg        pDRIEntPriv;
26805b261ecSmrg
26905b261ecSmrg    DRIDrvMsg(-1, X_INFO, "[drm] DRM open master succeeded.\n");
27005b261ecSmrg    return TRUE;
27105b261ecSmrg
27235c4bbdfSmrg out_err:
27305b261ecSmrg
27405b261ecSmrg    DRIOpenDRMCleanup(&tmp);
27505b261ecSmrg    return FALSE;
27605b261ecSmrg}
27705b261ecSmrg
2784642e01fSmrgstatic void
27935c4bbdfSmrg DRIClipNotifyAllDrawables(ScreenPtr pScreen);
2804642e01fSmrg
2814642e01fSmrgstatic void
2824642e01fSmrgdri_crtc_notify(ScreenPtr pScreen)
2834642e01fSmrg{
28435c4bbdfSmrg    DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
28535c4bbdfSmrg
2864642e01fSmrg    DRIClipNotifyAllDrawables(pScreen);
2874642e01fSmrg    xf86_unwrap_crtc_notify(pScreen, pDRIPriv->xf86_crtc_notify);
2884642e01fSmrg    xf86_crtc_notify(pScreen);
28935c4bbdfSmrg    pDRIPriv->xf86_crtc_notify =
29035c4bbdfSmrg        xf86_wrap_crtc_notify(pScreen, dri_crtc_notify);
2914642e01fSmrg}
29205b261ecSmrg
2931b5d61b8Smrgstatic void
2941b5d61b8SmrgdrmSIGIOHandler(int interrupt, void *closure)
2951b5d61b8Smrg{
2961b5d61b8Smrg    unsigned long key;
2971b5d61b8Smrg    void *value;
2981b5d61b8Smrg    ssize_t count;
2991b5d61b8Smrg    drm_ctx_t ctx;
3001b5d61b8Smrg    typedef void (*_drmCallback) (int, void *, void *);
3011b5d61b8Smrg    char buf[256];
3021b5d61b8Smrg    drm_context_t old;
3031b5d61b8Smrg    drm_context_t new;
3041b5d61b8Smrg    void *oldctx;
3051b5d61b8Smrg    void *newctx;
3061b5d61b8Smrg    char *pt;
3071b5d61b8Smrg    drmHashEntry *entry;
3081b5d61b8Smrg    void *hash_table;
3091b5d61b8Smrg
3101b5d61b8Smrg    hash_table = drmGetHashTable();
3111b5d61b8Smrg
3121b5d61b8Smrg    if (!hash_table)
3131b5d61b8Smrg        return;
3141b5d61b8Smrg    if (drmHashFirst(hash_table, &key, &value)) {
3151b5d61b8Smrg        entry = value;
3161b5d61b8Smrg        do {
3171b5d61b8Smrg            if ((count = read(entry->fd, buf, sizeof(buf) - 1)) > 0) {
3181b5d61b8Smrg                buf[count] = '\0';
3191b5d61b8Smrg
3201b5d61b8Smrg                for (pt = buf; *pt != ' '; ++pt);       /* Find first space */
3211b5d61b8Smrg                ++pt;
3221b5d61b8Smrg                old = strtol(pt, &pt, 0);
3231b5d61b8Smrg                new = strtol(pt, NULL, 0);
3241b5d61b8Smrg                oldctx = drmGetContextTag(entry->fd, old);
3251b5d61b8Smrg                newctx = drmGetContextTag(entry->fd, new);
3261b5d61b8Smrg                ((_drmCallback) entry->f) (entry->fd, oldctx, newctx);
3271b5d61b8Smrg                ctx.handle = new;
3281b5d61b8Smrg                ioctl(entry->fd, DRM_IOCTL_NEW_CTX, &ctx);
3291b5d61b8Smrg            }
3301b5d61b8Smrg        } while (drmHashNext(hash_table, &key, &value));
3311b5d61b8Smrg    }
3321b5d61b8Smrg}
3331b5d61b8Smrg
3341b5d61b8Smrgstatic int
3351b5d61b8SmrgdrmInstallSIGIOHandler(int fd, void (*f) (int, void *, void *))
3361b5d61b8Smrg{
3371b5d61b8Smrg    drmHashEntry *entry;
3381b5d61b8Smrg
3391b5d61b8Smrg    entry = drmGetEntry(fd);
3401b5d61b8Smrg    entry->f = f;
3411b5d61b8Smrg
3421b5d61b8Smrg    return xf86InstallSIGIOHandler(fd, drmSIGIOHandler, 0);
3431b5d61b8Smrg}
3441b5d61b8Smrg
3451b5d61b8Smrgstatic int
3461b5d61b8SmrgdrmRemoveSIGIOHandler(int fd)
3471b5d61b8Smrg{
3481b5d61b8Smrg    drmHashEntry *entry = drmGetEntry(fd);
3491b5d61b8Smrg
3501b5d61b8Smrg    entry->f = NULL;
3511b5d61b8Smrg
3521b5d61b8Smrg    return xf86RemoveSIGIOHandler(fd);
3531b5d61b8Smrg}
3541b5d61b8Smrg
35505b261ecSmrgBool
35605b261ecSmrgDRIScreenInit(ScreenPtr pScreen, DRIInfoPtr pDRIInfo, int *pDRMFD)
35705b261ecSmrg{
35835c4bbdfSmrg    DRIScreenPrivPtr pDRIPriv;
35935c4bbdfSmrg    drm_context_t *reserved;
36035c4bbdfSmrg    int reserved_count;
36135c4bbdfSmrg    int i;
36235c4bbdfSmrg    DRIEntPrivPtr pDRIEntPriv;
36335c4bbdfSmrg    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
36435c4bbdfSmrg    DRIContextFlags flags = 0;
36535c4bbdfSmrg    DRIContextPrivPtr pDRIContextPriv;
36635c4bbdfSmrg    static Bool drm_server_inited;
36705b261ecSmrg
36805b261ecSmrg    /* If the DRI extension is disabled, do not initialize the DRI */
36905b261ecSmrg    if (noXFree86DRIExtension) {
37035c4bbdfSmrg        DRIDrvMsg(pScreen->myNum, X_WARNING,
37135c4bbdfSmrg                  "Direct rendering has been disabled.\n");
37235c4bbdfSmrg        return FALSE;
37305b261ecSmrg    }
37405b261ecSmrg
3756747b715Smrg    if (!xf86VGAarbiterAllowDRI(pScreen)) {
3766747b715Smrg        DRIDrvMsg(pScreen->myNum, X_WARNING,
3776747b715Smrg                  "Direct rendering is not supported when VGA arb is necessary for the device\n");
37835c4bbdfSmrg        return FALSE;
3796747b715Smrg    }
3806747b715Smrg
3816747b715Smrg#ifdef PANORAMIX
38205b261ecSmrg    /*
38305b261ecSmrg     * If Xinerama is on, don't allow DRI to initialise.  It won't be usable
38405b261ecSmrg     * anyway.
38505b261ecSmrg     */
38635c4bbdfSmrg    if (!noPanoramiXExtension) {
38735c4bbdfSmrg        DRIDrvMsg(pScreen->myNum, X_WARNING,
38835c4bbdfSmrg                  "Direct rendering is not supported when Xinerama is enabled\n");
38935c4bbdfSmrg        return FALSE;
39035c4bbdfSmrg    }
3916747b715Smrg#endif
39235c4bbdfSmrg    if (drm_server_inited == FALSE) {
39335c4bbdfSmrg        drmSetServerInfo(&DRIDRMServerInfo);
39435c4bbdfSmrg        drm_server_inited = TRUE;
39535c4bbdfSmrg    }
39605b261ecSmrg
39705b261ecSmrg    if (!DRIOpenDRMMaster(pScrn, pDRIInfo->SAREASize,
39835c4bbdfSmrg                          pDRIInfo->busIdString, pDRIInfo->drmDriverName))
39935c4bbdfSmrg        return FALSE;
40005b261ecSmrg
40105b261ecSmrg    pDRIEntPriv = DRI_ENT_PRIV(pScrn);
40205b261ecSmrg
4034642e01fSmrg    if (DRIGeneration != serverGeneration)
40435c4bbdfSmrg        DRIGeneration = serverGeneration;
40505b261ecSmrg
4066747b715Smrg    if (!dixRegisterPrivateKey(&DRIScreenPrivKeyRec, PRIVATE_SCREEN, 0))
40735c4bbdfSmrg        return FALSE;
4086747b715Smrg    if (!dixRegisterPrivateKey(&DRIWindowPrivKeyRec, PRIVATE_WINDOW, 0))
40935c4bbdfSmrg        return FALSE;
4106747b715Smrg
4116747b715Smrg    pDRIPriv = (DRIScreenPrivPtr) calloc(1, sizeof(DRIScreenPrivRec));
41205b261ecSmrg    if (!pDRIPriv) {
41335c4bbdfSmrg        dixSetPrivate(&pScreen->devPrivates, DRIScreenPrivKey, NULL);
41405b261ecSmrg        return FALSE;
41505b261ecSmrg    }
41605b261ecSmrg
4174642e01fSmrg    dixSetPrivate(&pScreen->devPrivates, DRIScreenPrivKey, pDRIPriv);
41805b261ecSmrg    pDRIPriv->drmFD = pDRIEntPriv->drmFD;
41905b261ecSmrg    pDRIPriv->directRenderingSupport = TRUE;
42005b261ecSmrg    pDRIPriv->pDriverInfo = pDRIInfo;
42105b261ecSmrg    pDRIPriv->nrWindows = 0;
42205b261ecSmrg    pDRIPriv->nrWindowsVisible = 0;
42305b261ecSmrg    pDRIPriv->fullscreen = NULL;
42405b261ecSmrg
42535c4bbdfSmrg    pDRIPriv->createDummyCtx = pDRIInfo->createDummyCtx;
42605b261ecSmrg    pDRIPriv->createDummyCtxPriv = pDRIInfo->createDummyCtxPriv;
42705b261ecSmrg
42805b261ecSmrg    pDRIPriv->grabbedDRILock = FALSE;
42905b261ecSmrg    pDRIPriv->drmSIGIOHandlerInstalled = FALSE;
43005b261ecSmrg    *pDRMFD = pDRIPriv->drmFD;
43105b261ecSmrg
43205b261ecSmrg    if (pDRIEntPriv->sAreaGrabbed || pDRIInfo->allocSarea) {
43305b261ecSmrg
43435c4bbdfSmrg        if (drmAddMap(pDRIPriv->drmFD,
43535c4bbdfSmrg                      0,
43635c4bbdfSmrg                      pDRIPriv->pDriverInfo->SAREASize,
43735c4bbdfSmrg                      DRM_SHM, 0, &pDRIPriv->hSAREA) < 0) {
43835c4bbdfSmrg            pDRIPriv->directRenderingSupport = FALSE;
43935c4bbdfSmrg            dixSetPrivate(&pScreen->devPrivates, DRIScreenPrivKey, NULL);
44035c4bbdfSmrg            drmClose(pDRIPriv->drmFD);
44135c4bbdfSmrg            DRIDrvMsg(pScreen->myNum, X_INFO, "[drm] drmAddMap failed\n");
44235c4bbdfSmrg            return FALSE;
44335c4bbdfSmrg        }
44435c4bbdfSmrg        DRIDrvMsg(pScreen->myNum, X_INFO,
44535c4bbdfSmrg                  "[drm] added %d byte SAREA at %p\n",
44635c4bbdfSmrg                  (int) pDRIPriv->pDriverInfo->SAREASize, (void *) (uintptr_t) pDRIPriv->hSAREA);
44735c4bbdfSmrg
44835c4bbdfSmrg        /* Backwards compat. */
44935c4bbdfSmrg        if (drmMap(pDRIPriv->drmFD,
45035c4bbdfSmrg                   pDRIPriv->hSAREA,
45135c4bbdfSmrg                   pDRIPriv->pDriverInfo->SAREASize,
45235c4bbdfSmrg                   (drmAddressPtr) (&pDRIPriv->pSAREA)) < 0) {
45335c4bbdfSmrg            pDRIPriv->directRenderingSupport = FALSE;
45435c4bbdfSmrg            dixSetPrivate(&pScreen->devPrivates, DRIScreenPrivKey, NULL);
45535c4bbdfSmrg            drmClose(pDRIPriv->drmFD);
45635c4bbdfSmrg            DRIDrvMsg(pScreen->myNum, X_INFO, "[drm] drmMap failed\n");
45735c4bbdfSmrg            return FALSE;
45835c4bbdfSmrg        }
45935c4bbdfSmrg        DRIDrvMsg(pScreen->myNum, X_INFO, "[drm] mapped SAREA %p to %p\n",
46035c4bbdfSmrg                  (void *) (uintptr_t) pDRIPriv->hSAREA, pDRIPriv->pSAREA);
46135c4bbdfSmrg        memset(pDRIPriv->pSAREA, 0, pDRIPriv->pDriverInfo->SAREASize);
46235c4bbdfSmrg    }
46335c4bbdfSmrg    else {
46435c4bbdfSmrg        DRIDrvMsg(pScreen->myNum, X_INFO, "[drm] Using the DRM lock "
46535c4bbdfSmrg                  "SAREA also for drawables.\n");
46635c4bbdfSmrg        pDRIPriv->hSAREA = pDRIEntPriv->hLSAREA;
46735c4bbdfSmrg        pDRIPriv->pSAREA = (XF86DRISAREAPtr) pDRIEntPriv->pLSAREA;
46835c4bbdfSmrg        pDRIEntPriv->sAreaGrabbed = TRUE;
46905b261ecSmrg    }
47005b261ecSmrg
47105b261ecSmrg    pDRIPriv->hLSAREA = pDRIEntPriv->hLSAREA;
47205b261ecSmrg    pDRIPriv->pLSAREA = pDRIEntPriv->pLSAREA;
47305b261ecSmrg
47435c4bbdfSmrg    if (!pDRIPriv->pDriverInfo->dontMapFrameBuffer) {
47535c4bbdfSmrg        if (drmAddMap(pDRIPriv->drmFD,
47635c4bbdfSmrg                      (uintptr_t) pDRIPriv->pDriverInfo->
47735c4bbdfSmrg                      frameBufferPhysicalAddress,
47835c4bbdfSmrg                      pDRIPriv->pDriverInfo->frameBufferSize, DRM_FRAME_BUFFER,
47935c4bbdfSmrg                      0, &pDRIPriv->pDriverInfo->hFrameBuffer) < 0) {
48035c4bbdfSmrg            pDRIPriv->directRenderingSupport = FALSE;
48135c4bbdfSmrg            dixSetPrivate(&pScreen->devPrivates, DRIScreenPrivKey, NULL);
48235c4bbdfSmrg            drmUnmap(pDRIPriv->pSAREA, pDRIPriv->pDriverInfo->SAREASize);
48335c4bbdfSmrg            drmClose(pDRIPriv->drmFD);
48435c4bbdfSmrg            DRIDrvMsg(pScreen->myNum, X_INFO, "[drm] drmAddMap failed\n");
48535c4bbdfSmrg            return FALSE;
48635c4bbdfSmrg        }
48735c4bbdfSmrg        DRIDrvMsg(pScreen->myNum, X_INFO, "[drm] framebuffer handle = %p\n",
48835c4bbdfSmrg                  (void *) (uintptr_t) pDRIPriv->pDriverInfo->hFrameBuffer);
48935c4bbdfSmrg    }
49035c4bbdfSmrg    else {
49135c4bbdfSmrg        DRIDrvMsg(pScreen->myNum, X_INFO,
49235c4bbdfSmrg                  "[drm] framebuffer mapped by ddx driver\n");
49305b261ecSmrg    }
49405b261ecSmrg
49505b261ecSmrg    if (pDRIEntPriv->resOwner == NULL) {
49635c4bbdfSmrg        pDRIEntPriv->resOwner = pScreen;
49735c4bbdfSmrg
49835c4bbdfSmrg        /* Add tags for reserved contexts */
49935c4bbdfSmrg        if ((reserved = drmGetReservedContextList(pDRIPriv->drmFD,
50035c4bbdfSmrg                                                  &reserved_count))) {
50135c4bbdfSmrg            int r;
50235c4bbdfSmrg            void *tag;
50335c4bbdfSmrg
50435c4bbdfSmrg            for (r = 0; r < reserved_count; r++) {
50535c4bbdfSmrg                tag = DRICreateContextPrivFromHandle(pScreen,
50635c4bbdfSmrg                                                     reserved[r],
50735c4bbdfSmrg                                                     DRI_CONTEXT_RESERVED);
50835c4bbdfSmrg                drmAddContextTag(pDRIPriv->drmFD, reserved[r], tag);
50935c4bbdfSmrg            }
51035c4bbdfSmrg            drmFreeReservedContextList(reserved);
51135c4bbdfSmrg            DRIDrvMsg(pScreen->myNum, X_INFO,
51235c4bbdfSmrg                      "[drm] added %d reserved context%s for kernel\n",
51335c4bbdfSmrg                      reserved_count, reserved_count > 1 ? "s" : "");
51435c4bbdfSmrg        }
51505b261ecSmrg    }
51605b261ecSmrg
51705b261ecSmrg    /* validate max drawable table entry set by driver */
51805b261ecSmrg    if ((pDRIPriv->pDriverInfo->maxDrawableTableEntry <= 0) ||
51905b261ecSmrg        (pDRIPriv->pDriverInfo->maxDrawableTableEntry > SAREA_MAX_DRAWABLES)) {
52035c4bbdfSmrg        DRIDrvMsg(pScreen->myNum, X_ERROR,
52135c4bbdfSmrg                  "Invalid max drawable table size set by driver: %d\n",
52235c4bbdfSmrg                  pDRIPriv->pDriverInfo->maxDrawableTableEntry);
52305b261ecSmrg    }
52405b261ecSmrg
52505b261ecSmrg    /* Initialize drawable tables (screen private and SAREA) */
52635c4bbdfSmrg    for (i = 0; i < pDRIPriv->pDriverInfo->maxDrawableTableEntry; i++) {
52735c4bbdfSmrg        pDRIPriv->DRIDrawables[i] = NULL;
52835c4bbdfSmrg        pDRIPriv->pSAREA->drawableTable[i].stamp = 0;
52935c4bbdfSmrg        pDRIPriv->pSAREA->drawableTable[i].flags = 0;
53005b261ecSmrg    }
53105b261ecSmrg
53205b261ecSmrg    pDRIPriv->pLockRefCount = &pDRIEntPriv->lockRefCount;
53305b261ecSmrg    pDRIPriv->pLockingContext = &pDRIEntPriv->lockingContext;
53405b261ecSmrg
53505b261ecSmrg    if (!pDRIEntPriv->keepFDOpen)
53635c4bbdfSmrg        pDRIEntPriv->keepFDOpen = pDRIInfo->keepFDOpen;
53705b261ecSmrg
53805b261ecSmrg    pDRIEntPriv->refCount++;
53905b261ecSmrg
54005b261ecSmrg    /* Set up flags for DRICreateContextPriv */
54105b261ecSmrg    switch (pDRIInfo->driverSwapMethod) {
54205b261ecSmrg    case DRI_KERNEL_SWAP:
54335c4bbdfSmrg        flags = DRI_CONTEXT_2DONLY;
54435c4bbdfSmrg        break;
54505b261ecSmrg    case DRI_HIDE_X_CONTEXT:
54635c4bbdfSmrg        flags = DRI_CONTEXT_PRESERVED;
54735c4bbdfSmrg        break;
54805b261ecSmrg    }
54905b261ecSmrg
55005b261ecSmrg    if (!(pDRIContextPriv = DRICreateContextPriv(pScreen,
55135c4bbdfSmrg                                                 &pDRIPriv->myContext,
55235c4bbdfSmrg                                                 flags))) {
55335c4bbdfSmrg        DRIDrvMsg(pScreen->myNum, X_ERROR, "failed to create server context\n");
55435c4bbdfSmrg        return FALSE;
55505b261ecSmrg    }
55605b261ecSmrg    pDRIPriv->myContextPriv = pDRIContextPriv;
55705b261ecSmrg
55805b261ecSmrg    DRIDrvMsg(pScreen->myNum, X_INFO,
55935c4bbdfSmrg              "X context handle = %p\n", (void *) (uintptr_t) pDRIPriv->myContext);
56005b261ecSmrg
56105b261ecSmrg    /* Now that we have created the X server's context, we can grab the
56205b261ecSmrg     * hardware lock for the X server.
56305b261ecSmrg     */
56405b261ecSmrg    DRILock(pScreen, 0);
56505b261ecSmrg    pDRIPriv->grabbedDRILock = TRUE;
56605b261ecSmrg
56705b261ecSmrg    /* pointers so that we can prevent memory leaks later */
56835c4bbdfSmrg    pDRIPriv->hiddenContextStore = NULL;
56905b261ecSmrg    pDRIPriv->partial3DContextStore = NULL;
57005b261ecSmrg
57135c4bbdfSmrg    switch (pDRIInfo->driverSwapMethod) {
57205b261ecSmrg    case DRI_HIDE_X_CONTEXT:
57335c4bbdfSmrg        /* Server will handle 3D swaps, and hide 2D swaps from kernel.
57435c4bbdfSmrg         * Register server context as a preserved context.
57535c4bbdfSmrg         */
57635c4bbdfSmrg
57735c4bbdfSmrg        /* allocate memory for hidden context store */
57835c4bbdfSmrg        pDRIPriv->hiddenContextStore
57935c4bbdfSmrg            = (void *) calloc(1, pDRIInfo->contextSize);
58035c4bbdfSmrg        if (!pDRIPriv->hiddenContextStore) {
58135c4bbdfSmrg            DRIDrvMsg(pScreen->myNum, X_ERROR,
58235c4bbdfSmrg                      "failed to allocate hidden context\n");
58335c4bbdfSmrg            DRIDestroyContextPriv(pDRIContextPriv);
58435c4bbdfSmrg            return FALSE;
58535c4bbdfSmrg        }
58635c4bbdfSmrg
58735c4bbdfSmrg        /* allocate memory for partial 3D context store */
58835c4bbdfSmrg        pDRIPriv->partial3DContextStore
58935c4bbdfSmrg            = (void *) calloc(1, pDRIInfo->contextSize);
59035c4bbdfSmrg        if (!pDRIPriv->partial3DContextStore) {
59135c4bbdfSmrg            DRIDrvMsg(pScreen->myNum, X_ERROR,
59235c4bbdfSmrg                      "[DRI] failed to allocate partial 3D context\n");
59335c4bbdfSmrg            free(pDRIPriv->hiddenContextStore);
59435c4bbdfSmrg            DRIDestroyContextPriv(pDRIContextPriv);
59535c4bbdfSmrg            return FALSE;
59635c4bbdfSmrg        }
59735c4bbdfSmrg
59835c4bbdfSmrg        /* save initial context store */
59935c4bbdfSmrg        if (pDRIInfo->SwapContext) {
60035c4bbdfSmrg            (*pDRIInfo->SwapContext) (pScreen,
60135c4bbdfSmrg                                      DRI_NO_SYNC,
60235c4bbdfSmrg                                      DRI_2D_CONTEXT,
60335c4bbdfSmrg                                      pDRIPriv->hiddenContextStore,
60435c4bbdfSmrg                                      DRI_NO_CONTEXT, NULL);
60535c4bbdfSmrg        }
60635c4bbdfSmrg        /* fall through */
60705b261ecSmrg
60805b261ecSmrg    case DRI_SERVER_SWAP:
60905b261ecSmrg        /* For swap methods of DRI_SERVER_SWAP and DRI_HIDE_X_CONTEXT
61005b261ecSmrg         * setup signal handler for receiving swap requests from kernel
61135c4bbdfSmrg         */
61235c4bbdfSmrg        if (!(pDRIPriv->drmSIGIOHandlerInstalled =
61335c4bbdfSmrg              drmInstallSIGIOHandler(pDRIPriv->drmFD, DRISwapContext))) {
61435c4bbdfSmrg            DRIDrvMsg(pScreen->myNum, X_ERROR,
61535c4bbdfSmrg                      "[drm] failed to setup DRM signal handler\n");
61635c4bbdfSmrg            free(pDRIPriv->hiddenContextStore);
61735c4bbdfSmrg            free(pDRIPriv->partial3DContextStore);
61835c4bbdfSmrg            DRIDestroyContextPriv(pDRIContextPriv);
61935c4bbdfSmrg            return FALSE;
62035c4bbdfSmrg        }
62135c4bbdfSmrg        else {
62235c4bbdfSmrg            DRIDrvMsg(pScreen->myNum, X_INFO,
62335c4bbdfSmrg                      "[drm] installed DRM signal handler\n");
62435c4bbdfSmrg        }
62505b261ecSmrg
62605b261ecSmrg    default:
62735c4bbdfSmrg        break;
62805b261ecSmrg    }
62905b261ecSmrg
63005b261ecSmrg    return TRUE;
63105b261ecSmrg}
63205b261ecSmrg
63305b261ecSmrgBool
63405b261ecSmrgDRIFinishScreenInit(ScreenPtr pScreen)
63505b261ecSmrg{
63635c4bbdfSmrg    DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
63735c4bbdfSmrg    DRIInfoPtr pDRIInfo = pDRIPriv->pDriverInfo;
63805b261ecSmrg
63905b261ecSmrg    /* Wrap DRI support */
64005b261ecSmrg    if (pDRIInfo->wrap.WindowExposures) {
64135c4bbdfSmrg        pDRIPriv->wrap.WindowExposures = pScreen->WindowExposures;
64235c4bbdfSmrg        pScreen->WindowExposures = pDRIInfo->wrap.WindowExposures;
64305b261ecSmrg    }
64405b261ecSmrg
64535c4bbdfSmrg    pDRIPriv->DestroyWindow = pScreen->DestroyWindow;
64635c4bbdfSmrg    pScreen->DestroyWindow = DRIDestroyWindow;
64705b261ecSmrg
6484642e01fSmrg    pDRIPriv->xf86_crtc_notify = xf86_wrap_crtc_notify(pScreen,
64935c4bbdfSmrg                                                       dri_crtc_notify);
65035c4bbdfSmrg
65105b261ecSmrg    if (pDRIInfo->wrap.CopyWindow) {
65235c4bbdfSmrg        pDRIPriv->wrap.CopyWindow = pScreen->CopyWindow;
65335c4bbdfSmrg        pScreen->CopyWindow = pDRIInfo->wrap.CopyWindow;
65405b261ecSmrg    }
65505b261ecSmrg    if (pDRIInfo->wrap.ClipNotify) {
65635c4bbdfSmrg        pDRIPriv->wrap.ClipNotify = pScreen->ClipNotify;
65735c4bbdfSmrg        pScreen->ClipNotify = pDRIInfo->wrap.ClipNotify;
65805b261ecSmrg    }
65905b261ecSmrg    if (pDRIInfo->wrap.AdjustFrame) {
66035c4bbdfSmrg        ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
66135c4bbdfSmrg
66235c4bbdfSmrg        pDRIPriv->wrap.AdjustFrame = pScrn->AdjustFrame;
66335c4bbdfSmrg        pScrn->AdjustFrame = pDRIInfo->wrap.AdjustFrame;
66405b261ecSmrg    }
66505b261ecSmrg    pDRIPriv->wrapped = TRUE;
66605b261ecSmrg
66705b261ecSmrg    DRIDrvMsg(pScreen->myNum, X_INFO, "[DRI] installation complete\n");
66805b261ecSmrg
66905b261ecSmrg    return TRUE;
67005b261ecSmrg}
67105b261ecSmrg
67205b261ecSmrgvoid
67305b261ecSmrgDRICloseScreen(ScreenPtr pScreen)
67405b261ecSmrg{
67505b261ecSmrg    DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
67635c4bbdfSmrg    DRIInfoPtr pDRIInfo;
67735c4bbdfSmrg    drm_context_t *reserved;
67835c4bbdfSmrg    int reserved_count;
67935c4bbdfSmrg    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
68035c4bbdfSmrg    DRIEntPrivPtr pDRIEntPriv = DRI_ENT_PRIV(pScrn);
68105b261ecSmrg    Bool closeMaster;
68205b261ecSmrg
68305b261ecSmrg    if (pDRIPriv) {
68405b261ecSmrg
68505b261ecSmrg        pDRIInfo = pDRIPriv->pDriverInfo;
68605b261ecSmrg
68735c4bbdfSmrg        if (pDRIPriv->wrapped) {
68835c4bbdfSmrg            /* Unwrap DRI Functions */
68935c4bbdfSmrg            if (pDRIInfo->wrap.WindowExposures) {
69035c4bbdfSmrg                pScreen->WindowExposures = pDRIPriv->wrap.WindowExposures;
69135c4bbdfSmrg                pDRIPriv->wrap.WindowExposures = NULL;
69235c4bbdfSmrg            }
69335c4bbdfSmrg            if (pDRIPriv->DestroyWindow) {
69435c4bbdfSmrg                pScreen->DestroyWindow = pDRIPriv->DestroyWindow;
69535c4bbdfSmrg                pDRIPriv->DestroyWindow = NULL;
69635c4bbdfSmrg            }
69735c4bbdfSmrg
69835c4bbdfSmrg            xf86_unwrap_crtc_notify(pScreen, pDRIPriv->xf86_crtc_notify);
69935c4bbdfSmrg
70035c4bbdfSmrg            if (pDRIInfo->wrap.CopyWindow) {
70135c4bbdfSmrg                pScreen->CopyWindow = pDRIPriv->wrap.CopyWindow;
70235c4bbdfSmrg                pDRIPriv->wrap.CopyWindow = NULL;
70335c4bbdfSmrg            }
70435c4bbdfSmrg            if (pDRIInfo->wrap.ClipNotify) {
70535c4bbdfSmrg                pScreen->ClipNotify = pDRIPriv->wrap.ClipNotify;
70635c4bbdfSmrg                pDRIPriv->wrap.ClipNotify = NULL;
70735c4bbdfSmrg            }
70835c4bbdfSmrg            if (pDRIInfo->wrap.AdjustFrame) {
70935c4bbdfSmrg                ScrnInfoPtr scrn = xf86ScreenToScrn(pScreen);
71035c4bbdfSmrg
71135c4bbdfSmrg                scrn->AdjustFrame = pDRIPriv->wrap.AdjustFrame;
71235c4bbdfSmrg                pDRIPriv->wrap.AdjustFrame = NULL;
71335c4bbdfSmrg            }
71435c4bbdfSmrg
71535c4bbdfSmrg            pDRIPriv->wrapped = FALSE;
71635c4bbdfSmrg        }
71735c4bbdfSmrg
71835c4bbdfSmrg        if (pDRIPriv->drmSIGIOHandlerInstalled) {
71935c4bbdfSmrg            if (!drmRemoveSIGIOHandler(pDRIPriv->drmFD)) {
72035c4bbdfSmrg                DRIDrvMsg(pScreen->myNum, X_ERROR,
72135c4bbdfSmrg                          "[drm] failed to remove DRM signal handler\n");
72235c4bbdfSmrg            }
72335c4bbdfSmrg        }
72405b261ecSmrg
72505b261ecSmrg        if (pDRIPriv->dummyCtxPriv && pDRIPriv->createDummyCtx) {
72635c4bbdfSmrg            DRIDestroyDummyContext(pScreen, pDRIPriv->createDummyCtxPriv);
72735c4bbdfSmrg        }
72835c4bbdfSmrg
72935c4bbdfSmrg        if (!DRIDestroyContextPriv(pDRIPriv->myContextPriv)) {
73035c4bbdfSmrg            DRIDrvMsg(pScreen->myNum, X_ERROR,
73135c4bbdfSmrg                      "failed to destroy server context\n");
73235c4bbdfSmrg        }
73335c4bbdfSmrg
73435c4bbdfSmrg        /* Remove tags for reserved contexts */
73535c4bbdfSmrg        if (pDRIEntPriv->resOwner == pScreen) {
73635c4bbdfSmrg            pDRIEntPriv->resOwner = NULL;
73735c4bbdfSmrg
73835c4bbdfSmrg            if ((reserved = drmGetReservedContextList(pDRIPriv->drmFD,
73935c4bbdfSmrg                                                      &reserved_count))) {
74035c4bbdfSmrg                int i;
74135c4bbdfSmrg
74235c4bbdfSmrg                for (i = 0; i < reserved_count; i++) {
74335c4bbdfSmrg                    DRIDestroyContextPriv(drmGetContextTag(pDRIPriv->drmFD,
74435c4bbdfSmrg                                                           reserved[i]));
74535c4bbdfSmrg                }
74635c4bbdfSmrg                drmFreeReservedContextList(reserved);
74735c4bbdfSmrg                DRIDrvMsg(pScreen->myNum, X_INFO,
74835c4bbdfSmrg                          "[drm] removed %d reserved context%s for kernel\n",
74935c4bbdfSmrg                          reserved_count, reserved_count > 1 ? "s" : "");
75035c4bbdfSmrg            }
75135c4bbdfSmrg        }
75235c4bbdfSmrg
75335c4bbdfSmrg        /* Make sure signals get unblocked etc. */
75435c4bbdfSmrg        drmUnlock(pDRIPriv->drmFD, pDRIPriv->myContext);
75535c4bbdfSmrg        pDRIPriv->pLockRefCount = NULL;
75635c4bbdfSmrg        closeMaster = (--pDRIEntPriv->refCount == 0) &&
75735c4bbdfSmrg            !pDRIEntPriv->keepFDOpen;
75835c4bbdfSmrg        if (closeMaster || pDRIPriv->hSAREA != pDRIEntPriv->hLSAREA) {
75935c4bbdfSmrg            DRIDrvMsg(pScreen->myNum, X_INFO,
76035c4bbdfSmrg                      "[drm] unmapping %d bytes of SAREA %p at %p\n",
76135c4bbdfSmrg                      (int) pDRIInfo->SAREASize, (void *) (uintptr_t) pDRIPriv->hSAREA, pDRIPriv->pSAREA);
76235c4bbdfSmrg            if (drmUnmap(pDRIPriv->pSAREA, pDRIInfo->SAREASize)) {
76335c4bbdfSmrg                DRIDrvMsg(pScreen->myNum, X_ERROR,
76435c4bbdfSmrg                          "[drm] unable to unmap %d bytes"
76535c4bbdfSmrg                          " of SAREA %p at %p\n",
76635c4bbdfSmrg                          (int) pDRIInfo->SAREASize,
76735c4bbdfSmrg                          (void *) (uintptr_t) pDRIPriv->hSAREA, pDRIPriv->pSAREA);
76835c4bbdfSmrg            }
76935c4bbdfSmrg        }
77035c4bbdfSmrg        else {
77135c4bbdfSmrg            pDRIEntPriv->sAreaGrabbed = FALSE;
77235c4bbdfSmrg        }
77335c4bbdfSmrg
77435c4bbdfSmrg        if (closeMaster || (pDRIEntPriv->drmFD != pDRIPriv->drmFD)) {
77535c4bbdfSmrg            drmClose(pDRIPriv->drmFD);
77635c4bbdfSmrg            if (pDRIEntPriv->drmFD == pDRIPriv->drmFD) {
77735c4bbdfSmrg                DRIDrvMsg(pScreen->myNum, X_INFO, "[drm] Closed DRM master.\n");
77835c4bbdfSmrg                pDRIEntPriv->drmFD = -1;
77935c4bbdfSmrg            }
78035c4bbdfSmrg        }
78135c4bbdfSmrg
78235c4bbdfSmrg        free(pDRIPriv);
78335c4bbdfSmrg        dixSetPrivate(&pScreen->devPrivates, DRIScreenPrivKey, NULL);
78405b261ecSmrg    }
78505b261ecSmrg}
78605b261ecSmrg
78705b261ecSmrg#define DRM_MSG_VERBOSITY 3
78805b261ecSmrg
78935c4bbdfSmrgstatic int
79035c4bbdfSmrgdri_drm_debug_print(const char *format, va_list ap)
79135c4bbdfSmrg    _X_ATTRIBUTE_PRINTF(1,0);
79235c4bbdfSmrg
79335c4bbdfSmrgstatic int
79435c4bbdfSmrgdri_drm_debug_print(const char *format, va_list ap)
79505b261ecSmrg{
79635c4bbdfSmrg    xf86VDrvMsgVerb(-1, X_NONE, DRM_MSG_VERBOSITY, format, ap);
79735c4bbdfSmrg    return 0;
79805b261ecSmrg}
79905b261ecSmrg
80035c4bbdfSmrgstatic void
80135c4bbdfSmrgdri_drm_get_perms(gid_t * group, mode_t * mode)
80205b261ecSmrg{
80335c4bbdfSmrg    *group = xf86ConfigDRI.group;
80435c4bbdfSmrg    *mode = xf86ConfigDRI.mode;
80505b261ecSmrg}
80605b261ecSmrg
80735c4bbdfSmrgdrmServerInfo DRIDRMServerInfo = {
80835c4bbdfSmrg    dri_drm_debug_print,
80935c4bbdfSmrg    xf86LoadKernelModule,
81035c4bbdfSmrg    dri_drm_get_perms,
81105b261ecSmrg};
81205b261ecSmrg
81305b261ecSmrgBool
81405b261ecSmrgDRIExtensionInit(void)
81505b261ecSmrg{
8166747b715Smrg    if (DRIGeneration != serverGeneration) {
81735c4bbdfSmrg        return FALSE;
81805b261ecSmrg    }
81905b261ecSmrg
8206747b715Smrg    DRIDrawablePrivResType = CreateNewResourceType(DRIDrawablePrivDelete,
82135c4bbdfSmrg                                                   "DRIDrawable");
8226747b715Smrg    DRIContextPrivResType = CreateNewResourceType(DRIContextPrivDelete,
82335c4bbdfSmrg                                                  "DRIContext");
8246747b715Smrg
8256747b715Smrg    if (!DRIDrawablePrivResType || !DRIContextPrivResType)
82635c4bbdfSmrg        return FALSE;
82705b261ecSmrg
82805b261ecSmrg    RegisterBlockAndWakeupHandlers(DRIBlockHandler, DRIWakeupHandler, NULL);
82905b261ecSmrg
83005b261ecSmrg    return TRUE;
83105b261ecSmrg}
83205b261ecSmrg
83305b261ecSmrgvoid
83405b261ecSmrgDRIReset(void)
83505b261ecSmrg{
83605b261ecSmrg    /*
83705b261ecSmrg     * This stub routine is called when the X Server recycles, resources
83805b261ecSmrg     * allocated by DRIExtensionInit need to be managed here.
83905b261ecSmrg     *
84005b261ecSmrg     * Currently this routine is a stub because all the interesting resources
84105b261ecSmrg     * are managed via the screen init process.
84205b261ecSmrg     */
84305b261ecSmrg}
84405b261ecSmrg
84505b261ecSmrgBool
84635c4bbdfSmrgDRIQueryDirectRenderingCapable(ScreenPtr pScreen, Bool *isCapable)
84705b261ecSmrg{
84805b261ecSmrg    DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
84905b261ecSmrg
85005b261ecSmrg    if (pDRIPriv)
85135c4bbdfSmrg        *isCapable = pDRIPriv->directRenderingSupport;
85205b261ecSmrg    else
85335c4bbdfSmrg        *isCapable = FALSE;
85405b261ecSmrg
85505b261ecSmrg    return TRUE;
85605b261ecSmrg}
85705b261ecSmrg
85805b261ecSmrgBool
85905b261ecSmrgDRIOpenConnection(ScreenPtr pScreen, drm_handle_t * hSAREA, char **busIdString)
86005b261ecSmrg{
86105b261ecSmrg    DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
86205b261ecSmrg
86335c4bbdfSmrg    *hSAREA = pDRIPriv->hSAREA;
86435c4bbdfSmrg    *busIdString = pDRIPriv->pDriverInfo->busIdString;
86505b261ecSmrg
86605b261ecSmrg    return TRUE;
86705b261ecSmrg}
86805b261ecSmrg
86905b261ecSmrgBool
87005b261ecSmrgDRIAuthConnection(ScreenPtr pScreen, drm_magic_t magic)
87105b261ecSmrg{
87205b261ecSmrg    DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
87305b261ecSmrg
87435c4bbdfSmrg    if (drmAuthMagic(pDRIPriv->drmFD, magic))
87535c4bbdfSmrg        return FALSE;
87605b261ecSmrg    return TRUE;
87705b261ecSmrg}
87805b261ecSmrg
87905b261ecSmrgBool
88005b261ecSmrgDRICloseConnection(ScreenPtr pScreen)
88105b261ecSmrg{
88205b261ecSmrg    return TRUE;
88305b261ecSmrg}
88405b261ecSmrg
88505b261ecSmrgBool
88605b261ecSmrgDRIGetClientDriverName(ScreenPtr pScreen,
88705b261ecSmrg                       int *ddxDriverMajorVersion,
88805b261ecSmrg                       int *ddxDriverMinorVersion,
88935c4bbdfSmrg                       int *ddxDriverPatchVersion, char **clientDriverName)
89005b261ecSmrg{
89105b261ecSmrg    DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
89205b261ecSmrg
89305b261ecSmrg    *ddxDriverMajorVersion = pDRIPriv->pDriverInfo->ddxDriverMajorVersion;
89405b261ecSmrg    *ddxDriverMinorVersion = pDRIPriv->pDriverInfo->ddxDriverMinorVersion;
89505b261ecSmrg    *ddxDriverPatchVersion = pDRIPriv->pDriverInfo->ddxDriverPatchVersion;
89635c4bbdfSmrg    *clientDriverName = pDRIPriv->pDriverInfo->clientDriverName;
89705b261ecSmrg
89805b261ecSmrg    return TRUE;
89905b261ecSmrg}
90005b261ecSmrg
90105b261ecSmrg/* DRICreateContextPriv and DRICreateContextPrivFromHandle are helper
90205b261ecSmrg   functions that layer on drmCreateContext and drmAddContextTag.
90305b261ecSmrg
90405b261ecSmrg   DRICreateContextPriv always creates a kernel drm_context_t and then calls
90505b261ecSmrg   DRICreateContextPrivFromHandle to create a DRIContextPriv structure for
90605b261ecSmrg   DRI tracking.  For the SIGIO handler, the drm_context_t is associated with
90705b261ecSmrg   DRIContextPrivPtr.  Any special flags are stored in the DRIContextPriv
90805b261ecSmrg   area and are passed to the kernel (if necessary).
90905b261ecSmrg
91005b261ecSmrg   DRICreateContextPriv returns a pointer to newly allocated
91105b261ecSmrg   DRIContextPriv, and returns the kernel drm_context_t in pHWContext. */
91205b261ecSmrg
91305b261ecSmrgDRIContextPrivPtr
91405b261ecSmrgDRICreateContextPriv(ScreenPtr pScreen,
91535c4bbdfSmrg                     drm_context_t * pHWContext, DRIContextFlags flags)
91605b261ecSmrg{
91735c4bbdfSmrg    DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
91805b261ecSmrg
91905b261ecSmrg    if (drmCreateContext(pDRIPriv->drmFD, pHWContext)) {
92035c4bbdfSmrg        return NULL;
92105b261ecSmrg    }
92205b261ecSmrg
92305b261ecSmrg    return DRICreateContextPrivFromHandle(pScreen, *pHWContext, flags);
92405b261ecSmrg}
92505b261ecSmrg
92605b261ecSmrgDRIContextPrivPtr
92705b261ecSmrgDRICreateContextPrivFromHandle(ScreenPtr pScreen,
92835c4bbdfSmrg                               drm_context_t hHWContext, DRIContextFlags flags)
92905b261ecSmrg{
93035c4bbdfSmrg    DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
93105b261ecSmrg    DRIContextPrivPtr pDRIContextPriv;
93235c4bbdfSmrg    int contextPrivSize;
93305b261ecSmrg
93405b261ecSmrg    contextPrivSize = sizeof(DRIContextPrivRec) +
93535c4bbdfSmrg        pDRIPriv->pDriverInfo->contextSize;
9366747b715Smrg    if (!(pDRIContextPriv = calloc(1, contextPrivSize))) {
93735c4bbdfSmrg        return NULL;
93805b261ecSmrg    }
93935c4bbdfSmrg    pDRIContextPriv->pContextStore = (void *) (pDRIContextPriv + 1);
94005b261ecSmrg
94105b261ecSmrg    drmAddContextTag(pDRIPriv->drmFD, hHWContext, pDRIContextPriv);
94205b261ecSmrg
94305b261ecSmrg    pDRIContextPriv->hwContext = hHWContext;
94435c4bbdfSmrg    pDRIContextPriv->pScreen = pScreen;
94535c4bbdfSmrg    pDRIContextPriv->flags = flags;
94635c4bbdfSmrg    pDRIContextPriv->valid3D = FALSE;
94705b261ecSmrg
94805b261ecSmrg    if (flags & DRI_CONTEXT_2DONLY) {
94935c4bbdfSmrg        if (drmSetContextFlags(pDRIPriv->drmFD, hHWContext, DRM_CONTEXT_2DONLY)) {
95035c4bbdfSmrg            DRIDrvMsg(pScreen->myNum, X_ERROR,
95135c4bbdfSmrg                      "[drm] failed to set 2D context flag\n");
95235c4bbdfSmrg            DRIDestroyContextPriv(pDRIContextPriv);
95335c4bbdfSmrg            return NULL;
95435c4bbdfSmrg        }
95505b261ecSmrg    }
95605b261ecSmrg    if (flags & DRI_CONTEXT_PRESERVED) {
95735c4bbdfSmrg        if (drmSetContextFlags(pDRIPriv->drmFD,
95835c4bbdfSmrg                               hHWContext, DRM_CONTEXT_PRESERVED)) {
95935c4bbdfSmrg            DRIDrvMsg(pScreen->myNum, X_ERROR,
96035c4bbdfSmrg                      "[drm] failed to set preserved flag\n");
96135c4bbdfSmrg            DRIDestroyContextPriv(pDRIContextPriv);
96235c4bbdfSmrg            return NULL;
96335c4bbdfSmrg        }
96405b261ecSmrg    }
96505b261ecSmrg    return pDRIContextPriv;
96605b261ecSmrg}
96705b261ecSmrg
96805b261ecSmrgBool
96905b261ecSmrgDRIDestroyContextPriv(DRIContextPrivPtr pDRIContextPriv)
97005b261ecSmrg{
97105b261ecSmrg    DRIScreenPrivPtr pDRIPriv;
97205b261ecSmrg
97335c4bbdfSmrg    if (!pDRIContextPriv)
97435c4bbdfSmrg        return TRUE;
97505b261ecSmrg
97605b261ecSmrg    pDRIPriv = DRI_SCREEN_PRIV(pDRIContextPriv->pScreen);
97705b261ecSmrg
97805b261ecSmrg    if (!(pDRIContextPriv->flags & DRI_CONTEXT_RESERVED)) {
97935c4bbdfSmrg        /* Don't delete reserved contexts from
98035c4bbdfSmrg           kernel area -- the kernel manages its
98135c4bbdfSmrg           reserved contexts itself. */
98235c4bbdfSmrg        if (drmDestroyContext(pDRIPriv->drmFD, pDRIContextPriv->hwContext))
98335c4bbdfSmrg            return FALSE;
98435c4bbdfSmrg    }
98535c4bbdfSmrg
98635c4bbdfSmrg    /* Remove the tag last to prevent a race
98735c4bbdfSmrg       condition where the context has pending
98835c4bbdfSmrg       buffers.  The context can't be re-used
98935c4bbdfSmrg       while in this thread, but buffers can be
99035c4bbdfSmrg       dispatched asynchronously. */
99105b261ecSmrg    drmDelContextTag(pDRIPriv->drmFD, pDRIContextPriv->hwContext);
9926747b715Smrg    free(pDRIContextPriv);
99305b261ecSmrg    return TRUE;
99405b261ecSmrg}
99505b261ecSmrg
99605b261ecSmrgstatic Bool
99705b261ecSmrgDRICreateDummyContext(ScreenPtr pScreen, Bool needCtxPriv)
99805b261ecSmrg{
99905b261ecSmrg    DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
100005b261ecSmrg    DRIContextPrivPtr pDRIContextPriv;
100105b261ecSmrg    void *contextStore;
100205b261ecSmrg
100305b261ecSmrg    if (!(pDRIContextPriv =
100435c4bbdfSmrg          DRICreateContextPriv(pScreen, &pDRIPriv->pSAREA->dummy_context, 0))) {
100535c4bbdfSmrg        return FALSE;
100605b261ecSmrg    }
100705b261ecSmrg
100805b261ecSmrg    contextStore = DRIGetContextStore(pDRIContextPriv);
100905b261ecSmrg    if (pDRIPriv->pDriverInfo->CreateContext && needCtxPriv) {
101035c4bbdfSmrg        if (!pDRIPriv->pDriverInfo->CreateContext(pScreen, NULL,
101135c4bbdfSmrg                                                  pDRIPriv->pSAREA->
101235c4bbdfSmrg                                                  dummy_context, NULL,
101335c4bbdfSmrg                                                  (DRIContextType) (long)
101435c4bbdfSmrg                                                  contextStore)) {
101535c4bbdfSmrg            DRIDestroyContextPriv(pDRIContextPriv);
101635c4bbdfSmrg            return FALSE;
101735c4bbdfSmrg        }
101805b261ecSmrg    }
101905b261ecSmrg
102005b261ecSmrg    pDRIPriv->dummyCtxPriv = pDRIContextPriv;
102105b261ecSmrg    return TRUE;
102205b261ecSmrg}
102305b261ecSmrg
102405b261ecSmrgstatic void
102505b261ecSmrgDRIDestroyDummyContext(ScreenPtr pScreen, Bool hasCtxPriv)
102605b261ecSmrg{
102705b261ecSmrg    DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
102805b261ecSmrg    DRIContextPrivPtr pDRIContextPriv = pDRIPriv->dummyCtxPriv;
102905b261ecSmrg    void *contextStore;
103005b261ecSmrg
103135c4bbdfSmrg    if (!pDRIContextPriv)
103235c4bbdfSmrg        return;
103305b261ecSmrg    if (pDRIPriv->pDriverInfo->DestroyContext && hasCtxPriv) {
103435c4bbdfSmrg        contextStore = DRIGetContextStore(pDRIContextPriv);
103535c4bbdfSmrg        pDRIPriv->pDriverInfo->DestroyContext(pDRIContextPriv->pScreen,
103635c4bbdfSmrg                                              pDRIContextPriv->hwContext,
103735c4bbdfSmrg                                              (DRIContextType) (long)
103835c4bbdfSmrg                                              contextStore);
103905b261ecSmrg    }
104005b261ecSmrg
104105b261ecSmrg    DRIDestroyContextPriv(pDRIPriv->dummyCtxPriv);
104205b261ecSmrg    pDRIPriv->dummyCtxPriv = NULL;
104305b261ecSmrg}
104405b261ecSmrg
104505b261ecSmrgBool
104605b261ecSmrgDRICreateContext(ScreenPtr pScreen, VisualPtr visual,
104705b261ecSmrg                 XID context, drm_context_t * pHWContext)
104805b261ecSmrg{
104905b261ecSmrg    DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
105005b261ecSmrg    DRIContextPrivPtr pDRIContextPriv;
105105b261ecSmrg    void *contextStore;
105205b261ecSmrg
105305b261ecSmrg    if (pDRIPriv->createDummyCtx && !pDRIPriv->dummyCtxPriv) {
105405b261ecSmrg        if (!DRICreateDummyContext(pScreen, pDRIPriv->createDummyCtxPriv)) {
105535c4bbdfSmrg            DRIDrvMsg(pScreen->myNum, X_INFO,
105635c4bbdfSmrg                      "[drm] Could not create dummy context\n");
105735c4bbdfSmrg            return FALSE;
105835c4bbdfSmrg        }
105905b261ecSmrg    }
106005b261ecSmrg
106105b261ecSmrg    if (!(pDRIContextPriv = DRICreateContextPriv(pScreen, pHWContext, 0))) {
106235c4bbdfSmrg        return FALSE;
106305b261ecSmrg    }
106405b261ecSmrg
106505b261ecSmrg    contextStore = DRIGetContextStore(pDRIContextPriv);
106605b261ecSmrg    if (pDRIPriv->pDriverInfo->CreateContext) {
106735c4bbdfSmrg        if (!((*pDRIPriv->pDriverInfo->CreateContext) (pScreen, NULL,
106835c4bbdfSmrg                                                       *pHWContext, NULL,
106935c4bbdfSmrg                                                       (DRIContextType) (long)
107035c4bbdfSmrg                                                       contextStore))) {
107135c4bbdfSmrg            DRIDestroyContextPriv(pDRIContextPriv);
107235c4bbdfSmrg            return FALSE;
107335c4bbdfSmrg        }
107405b261ecSmrg    }
107505b261ecSmrg
107605b261ecSmrg    /* track this in case the client dies before cleanup */
107735c4bbdfSmrg    if (!AddResource(context, DRIContextPrivResType, (void *) pDRIContextPriv))
107835c4bbdfSmrg        return FALSE;
107905b261ecSmrg
108005b261ecSmrg    return TRUE;
108105b261ecSmrg}
108205b261ecSmrg
108305b261ecSmrgBool
108405b261ecSmrgDRIDestroyContext(ScreenPtr pScreen, XID context)
108505b261ecSmrg{
108605b261ecSmrg    FreeResourceByType(context, DRIContextPrivResType, FALSE);
108705b261ecSmrg
108805b261ecSmrg    return TRUE;
108905b261ecSmrg}
109005b261ecSmrg
109105b261ecSmrg/* DRIContextPrivDelete is called by the resource manager. */
109205b261ecSmrgBool
109335c4bbdfSmrgDRIContextPrivDelete(void *pResource, XID id)
109405b261ecSmrg{
109535c4bbdfSmrg    DRIContextPrivPtr pDRIContextPriv = (DRIContextPrivPtr) pResource;
109605b261ecSmrg    DRIScreenPrivPtr pDRIPriv;
109705b261ecSmrg    void *contextStore;
109805b261ecSmrg
109905b261ecSmrg    pDRIPriv = DRI_SCREEN_PRIV(pDRIContextPriv->pScreen);
110005b261ecSmrg    if (pDRIPriv->pDriverInfo->DestroyContext) {
110135c4bbdfSmrg        contextStore = DRIGetContextStore(pDRIContextPriv);
110235c4bbdfSmrg        pDRIPriv->pDriverInfo->DestroyContext(pDRIContextPriv->pScreen,
110335c4bbdfSmrg                                              pDRIContextPriv->hwContext,
110435c4bbdfSmrg                                              (DRIContextType) (long)
110535c4bbdfSmrg                                              contextStore);
110605b261ecSmrg    }
110705b261ecSmrg    return DRIDestroyContextPriv(pDRIContextPriv);
110805b261ecSmrg}
110905b261ecSmrg
111005b261ecSmrg/* This walks the drawable timestamp array and invalidates all of them
111105b261ecSmrg * in the case of transition from private to shared backbuffers.  It's
111205b261ecSmrg * not necessary for correctness, because DRIClipNotify gets called in
111305b261ecSmrg * time to prevent any conflict, but the transition from
111405b261ecSmrg * shared->private is sometimes missed if we don't do this.
111505b261ecSmrg */
111605b261ecSmrgstatic void
111705b261ecSmrgDRIClipNotifyAllDrawables(ScreenPtr pScreen)
111805b261ecSmrg{
111935c4bbdfSmrg    int i;
112035c4bbdfSmrg    DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
112105b261ecSmrg
112235c4bbdfSmrg    for (i = 0; i < pDRIPriv->pDriverInfo->maxDrawableTableEntry; i++) {
112335c4bbdfSmrg        pDRIPriv->pSAREA->drawableTable[i].stamp = DRIDrawableValidationStamp++;
112435c4bbdfSmrg    }
112505b261ecSmrg}
112605b261ecSmrg
112705b261ecSmrgstatic void
112805b261ecSmrgDRITransitionToSharedBuffers(ScreenPtr pScreen)
112905b261ecSmrg{
113005b261ecSmrg    DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
113105b261ecSmrg    DRIInfoPtr pDRIInfo = pDRIPriv->pDriverInfo;
113205b261ecSmrg
113335c4bbdfSmrg    DRIClipNotifyAllDrawables(pScreen);
113405b261ecSmrg
113505b261ecSmrg    if (pDRIInfo->TransitionSingleToMulti3D)
113635c4bbdfSmrg        pDRIInfo->TransitionSingleToMulti3D(pScreen);
113705b261ecSmrg}
113805b261ecSmrg
113905b261ecSmrgstatic void
114005b261ecSmrgDRITransitionToPrivateBuffers(ScreenPtr pScreen)
114105b261ecSmrg{
114205b261ecSmrg    DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
114305b261ecSmrg    DRIInfoPtr pDRIInfo = pDRIPriv->pDriverInfo;
114405b261ecSmrg
114535c4bbdfSmrg    DRIClipNotifyAllDrawables(pScreen);
114605b261ecSmrg
114705b261ecSmrg    if (pDRIInfo->TransitionMultiToSingle3D)
114835c4bbdfSmrg        pDRIInfo->TransitionMultiToSingle3D(pScreen);
114905b261ecSmrg}
115005b261ecSmrg
115105b261ecSmrgstatic void
115205b261ecSmrgDRITransitionTo3d(ScreenPtr pScreen)
115305b261ecSmrg{
115405b261ecSmrg    DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
115505b261ecSmrg    DRIInfoPtr pDRIInfo = pDRIPriv->pDriverInfo;
115605b261ecSmrg
115735c4bbdfSmrg    DRIClipNotifyAllDrawables(pScreen);
115805b261ecSmrg
115905b261ecSmrg    if (pDRIInfo->TransitionTo3d)
116035c4bbdfSmrg        pDRIInfo->TransitionTo3d(pScreen);
116105b261ecSmrg}
116205b261ecSmrg
116305b261ecSmrgstatic void
116405b261ecSmrgDRITransitionTo2d(ScreenPtr pScreen)
116505b261ecSmrg{
116605b261ecSmrg    DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
116705b261ecSmrg    DRIInfoPtr pDRIInfo = pDRIPriv->pDriverInfo;
116805b261ecSmrg
116935c4bbdfSmrg    DRIClipNotifyAllDrawables(pScreen);
117005b261ecSmrg
117105b261ecSmrg    if (pDRIInfo->TransitionTo2d)
117235c4bbdfSmrg        pDRIInfo->TransitionTo2d(pScreen);
117305b261ecSmrg}
117405b261ecSmrg
117505b261ecSmrgstatic int
117635c4bbdfSmrgDRIDCNTreeTraversal(WindowPtr pWin, void *data)
117705b261ecSmrg{
117805b261ecSmrg    DRIDrawablePrivPtr pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin);
117905b261ecSmrg
118005b261ecSmrg    if (pDRIDrawablePriv) {
118135c4bbdfSmrg        ScreenPtr pScreen = pWin->drawable.pScreen;
118235c4bbdfSmrg        DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
118305b261ecSmrg
118435c4bbdfSmrg        if (RegionNumRects(&pWin->clipList) > 0) {
118535c4bbdfSmrg            WindowPtr *pDRIWindows = (WindowPtr *) data;
118635c4bbdfSmrg            int i = 0;
118705b261ecSmrg
118835c4bbdfSmrg            while (pDRIWindows[i])
118935c4bbdfSmrg                i++;
119005b261ecSmrg
119135c4bbdfSmrg            pDRIWindows[i] = pWin;
119205b261ecSmrg
119335c4bbdfSmrg            pDRIPriv->nrWalked++;
119435c4bbdfSmrg        }
119505b261ecSmrg
119635c4bbdfSmrg        if (pDRIPriv->nrWindows == pDRIPriv->nrWalked)
119735c4bbdfSmrg            return WT_STOPWALKING;
119805b261ecSmrg    }
119905b261ecSmrg
120005b261ecSmrg    return WT_WALKCHILDREN;
120105b261ecSmrg}
120205b261ecSmrg
120305b261ecSmrgstatic void
120405b261ecSmrgDRIDriverClipNotify(ScreenPtr pScreen)
120505b261ecSmrg{
120605b261ecSmrg    DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
120705b261ecSmrg
120805b261ecSmrg    if (pDRIPriv->pDriverInfo->ClipNotify) {
120935c4bbdfSmrg        WindowPtr *pDRIWindows = calloc(sizeof(WindowPtr), pDRIPriv->nrWindows);
121035c4bbdfSmrg        DRIInfoPtr pDRIInfo = pDRIPriv->pDriverInfo;
121105b261ecSmrg
121235c4bbdfSmrg        if (pDRIPriv->nrWindows > 0) {
121335c4bbdfSmrg            pDRIPriv->nrWalked = 0;
121435c4bbdfSmrg            TraverseTree(pScreen->root, DRIDCNTreeTraversal,
121535c4bbdfSmrg                         (void *) pDRIWindows);
121635c4bbdfSmrg        }
121705b261ecSmrg
121835c4bbdfSmrg        pDRIInfo->ClipNotify(pScreen, pDRIWindows, pDRIPriv->nrWindows);
121905b261ecSmrg
122035c4bbdfSmrg        free(pDRIWindows);
122105b261ecSmrg    }
122205b261ecSmrg}
122305b261ecSmrg
122405b261ecSmrgstatic void
122505b261ecSmrgDRIIncreaseNumberVisible(ScreenPtr pScreen)
122605b261ecSmrg{
122705b261ecSmrg    DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
122805b261ecSmrg
122905b261ecSmrg    switch (++pDRIPriv->nrWindowsVisible) {
123005b261ecSmrg    case 1:
123135c4bbdfSmrg        DRITransitionTo3d(pScreen);
123235c4bbdfSmrg        break;
123305b261ecSmrg    case 2:
123435c4bbdfSmrg        DRITransitionToSharedBuffers(pScreen);
123535c4bbdfSmrg        break;
123605b261ecSmrg    default:
123735c4bbdfSmrg        break;
123805b261ecSmrg    }
123905b261ecSmrg
124005b261ecSmrg    DRIDriverClipNotify(pScreen);
124105b261ecSmrg}
124205b261ecSmrg
124305b261ecSmrgstatic void
124405b261ecSmrgDRIDecreaseNumberVisible(ScreenPtr pScreen)
124505b261ecSmrg{
124605b261ecSmrg    DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
124705b261ecSmrg
124805b261ecSmrg    switch (--pDRIPriv->nrWindowsVisible) {
124905b261ecSmrg    case 0:
125035c4bbdfSmrg        DRITransitionTo2d(pScreen);
125135c4bbdfSmrg        break;
125205b261ecSmrg    case 1:
125335c4bbdfSmrg        DRITransitionToPrivateBuffers(pScreen);
125435c4bbdfSmrg        break;
125505b261ecSmrg    default:
125635c4bbdfSmrg        break;
125705b261ecSmrg    }
125805b261ecSmrg
125905b261ecSmrg    DRIDriverClipNotify(pScreen);
126005b261ecSmrg}
126105b261ecSmrg
126205b261ecSmrgBool
126305b261ecSmrgDRICreateDrawable(ScreenPtr pScreen, ClientPtr client, DrawablePtr pDrawable,
126435c4bbdfSmrg                  drm_drawable_t * hHWDrawable)
126505b261ecSmrg{
126635c4bbdfSmrg    DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
126735c4bbdfSmrg    DRIDrawablePrivPtr pDRIDrawablePriv;
126835c4bbdfSmrg    WindowPtr pWin;
126905b261ecSmrg
127005b261ecSmrg    if (pDrawable->type == DRAWABLE_WINDOW) {
127135c4bbdfSmrg        pWin = (WindowPtr) pDrawable;
127235c4bbdfSmrg        if ((pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin))) {
127335c4bbdfSmrg            pDRIDrawablePriv->refCount++;
127435c4bbdfSmrg
127535c4bbdfSmrg            if (!pDRIDrawablePriv->hwDrawable) {
127635c4bbdfSmrg                drmCreateDrawable(pDRIPriv->drmFD,
127735c4bbdfSmrg                                  &pDRIDrawablePriv->hwDrawable);
127835c4bbdfSmrg            }
127935c4bbdfSmrg        }
128035c4bbdfSmrg        else {
128135c4bbdfSmrg            /* allocate a DRI Window Private record */
128235c4bbdfSmrg            if (!(pDRIDrawablePriv = malloc(sizeof(DRIDrawablePrivRec)))) {
128335c4bbdfSmrg                return FALSE;
128435c4bbdfSmrg            }
128535c4bbdfSmrg
128635c4bbdfSmrg            /* Only create a drm_drawable_t once */
128735c4bbdfSmrg            if (drmCreateDrawable(pDRIPriv->drmFD,
128835c4bbdfSmrg                                  &pDRIDrawablePriv->hwDrawable)) {
128935c4bbdfSmrg                free(pDRIDrawablePriv);
129035c4bbdfSmrg                return FALSE;
129135c4bbdfSmrg            }
129235c4bbdfSmrg
129335c4bbdfSmrg            /* add it to the list of DRI drawables for this screen */
129435c4bbdfSmrg            pDRIDrawablePriv->pScreen = pScreen;
129535c4bbdfSmrg            pDRIDrawablePriv->refCount = 1;
129635c4bbdfSmrg            pDRIDrawablePriv->drawableIndex = -1;
129735c4bbdfSmrg            pDRIDrawablePriv->nrects = RegionNumRects(&pWin->clipList);
129835c4bbdfSmrg
129935c4bbdfSmrg            /* save private off of preallocated index */
130035c4bbdfSmrg            dixSetPrivate(&pWin->devPrivates, DRIWindowPrivKey,
130135c4bbdfSmrg                          pDRIDrawablePriv);
130235c4bbdfSmrg            pDRIPriv->nrWindows++;
130335c4bbdfSmrg
130435c4bbdfSmrg            if (pDRIDrawablePriv->nrects)
130535c4bbdfSmrg                DRIIncreaseNumberVisible(pScreen);
130635c4bbdfSmrg        }
130735c4bbdfSmrg
130835c4bbdfSmrg        /* track this in case the client dies */
130935c4bbdfSmrg        if (!AddResource(FakeClientID(client->index), DRIDrawablePrivResType,
131035c4bbdfSmrg                         (void *) (intptr_t) pDrawable->id))
131135c4bbdfSmrg            return FALSE;
131235c4bbdfSmrg
131335c4bbdfSmrg        if (pDRIDrawablePriv->hwDrawable) {
131435c4bbdfSmrg            drmUpdateDrawableInfo(pDRIPriv->drmFD,
131535c4bbdfSmrg                                  pDRIDrawablePriv->hwDrawable,
131635c4bbdfSmrg                                  DRM_DRAWABLE_CLIPRECTS,
131735c4bbdfSmrg                                  RegionNumRects(&pWin->clipList),
131835c4bbdfSmrg                                  RegionRects(&pWin->clipList));
131935c4bbdfSmrg            *hHWDrawable = pDRIDrawablePriv->hwDrawable;
132035c4bbdfSmrg        }
132135c4bbdfSmrg    }
132235c4bbdfSmrg    else if (pDrawable->type != DRAWABLE_PIXMAP) {      /* PBuffer */
132335c4bbdfSmrg        /* NOT_DONE */
132435c4bbdfSmrg        return FALSE;
132505b261ecSmrg    }
132605b261ecSmrg
132705b261ecSmrg    return TRUE;
132805b261ecSmrg}
132905b261ecSmrg
133005b261ecSmrgstatic void
133105b261ecSmrgDRIDrawablePrivDestroy(WindowPtr pWin)
133205b261ecSmrg{
133305b261ecSmrg    DRIDrawablePrivPtr pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin);
133405b261ecSmrg    ScreenPtr pScreen;
133505b261ecSmrg    DRIScreenPrivPtr pDRIPriv;
133605b261ecSmrg
133705b261ecSmrg    if (!pDRIDrawablePriv)
133835c4bbdfSmrg        return;
133905b261ecSmrg
134005b261ecSmrg    pScreen = pWin->drawable.pScreen;
134105b261ecSmrg    pDRIPriv = DRI_SCREEN_PRIV(pScreen);
134205b261ecSmrg
134305b261ecSmrg    if (pDRIDrawablePriv->drawableIndex != -1) {
134435c4bbdfSmrg        /* bump stamp to force outstanding 3D requests to resync */
134535c4bbdfSmrg        pDRIPriv->pSAREA->drawableTable[pDRIDrawablePriv->drawableIndex].stamp
134635c4bbdfSmrg            = DRIDrawableValidationStamp++;
134705b261ecSmrg
134835c4bbdfSmrg        /* release drawable table entry */
134935c4bbdfSmrg        pDRIPriv->DRIDrawables[pDRIDrawablePriv->drawableIndex] = NULL;
135005b261ecSmrg    }
135105b261ecSmrg
135205b261ecSmrg    pDRIPriv->nrWindows--;
135305b261ecSmrg
135405b261ecSmrg    if (pDRIDrawablePriv->nrects)
135535c4bbdfSmrg        DRIDecreaseNumberVisible(pScreen);
135605b261ecSmrg
135705b261ecSmrg    drmDestroyDrawable(pDRIPriv->drmFD, pDRIDrawablePriv->hwDrawable);
135805b261ecSmrg
13596747b715Smrg    free(pDRIDrawablePriv);
13604642e01fSmrg    dixSetPrivate(&pWin->devPrivates, DRIWindowPrivKey, NULL);
136105b261ecSmrg}
136205b261ecSmrg
136305b261ecSmrgstatic Bool
136435c4bbdfSmrgDRIDestroyDrawableCB(void *value, XID id, void *data)
136505b261ecSmrg{
136605b261ecSmrg    if (value == data) {
136735c4bbdfSmrg        /* This calls back DRIDrawablePrivDelete which frees private area */
136835c4bbdfSmrg        FreeResourceByType(id, DRIDrawablePrivResType, FALSE);
136905b261ecSmrg
137035c4bbdfSmrg        return TRUE;
137105b261ecSmrg    }
137205b261ecSmrg
137305b261ecSmrg    return FALSE;
137405b261ecSmrg}
137505b261ecSmrg
137605b261ecSmrgBool
137705b261ecSmrgDRIDestroyDrawable(ScreenPtr pScreen, ClientPtr client, DrawablePtr pDrawable)
137805b261ecSmrg{
137905b261ecSmrg    if (pDrawable->type == DRAWABLE_WINDOW) {
138035c4bbdfSmrg        LookupClientResourceComplex(client, DRIDrawablePrivResType,
138135c4bbdfSmrg                                    DRIDestroyDrawableCB,
138235c4bbdfSmrg                                    (void *) (intptr_t) pDrawable->id);
138305b261ecSmrg    }
138435c4bbdfSmrg    else {                      /* pixmap (or for GLX 1.3, a PBuffer) */
138535c4bbdfSmrg        /* NOT_DONE */
138635c4bbdfSmrg        return FALSE;
138705b261ecSmrg    }
138805b261ecSmrg
138905b261ecSmrg    return TRUE;
139005b261ecSmrg}
139105b261ecSmrg
139205b261ecSmrgBool
139335c4bbdfSmrgDRIDrawablePrivDelete(void *pResource, XID id)
139405b261ecSmrg{
139505b261ecSmrg    WindowPtr pWin;
13966747b715Smrg    int rc;
139705b261ecSmrg
13986747b715Smrg    /* For DRIDrawablePrivResType, the XID is the client's fake ID. The
13996747b715Smrg     * important XID is the value in pResource. */
140035c4bbdfSmrg    id = (XID) (intptr_t) pResource;
14016747b715Smrg    rc = dixLookupWindow(&pWin, id, serverClient, DixGetAttrAccess);
140205b261ecSmrg
14036747b715Smrg    if (rc == Success) {
140435c4bbdfSmrg        DRIDrawablePrivPtr pDRIDrwPriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin);
140505b261ecSmrg
140635c4bbdfSmrg        if (!pDRIDrwPriv)
140735c4bbdfSmrg            return FALSE;
140805b261ecSmrg
140935c4bbdfSmrg        if (--pDRIDrwPriv->refCount == 0)
141035c4bbdfSmrg            DRIDrawablePrivDestroy(pWin);
141105b261ecSmrg
141235c4bbdfSmrg        return TRUE;
141305b261ecSmrg    }
141435c4bbdfSmrg    else {                      /* pixmap (or for GLX 1.3, a PBuffer) */
141535c4bbdfSmrg        /* NOT_DONE */
141635c4bbdfSmrg        return FALSE;
141705b261ecSmrg    }
141805b261ecSmrg}
141905b261ecSmrg
142005b261ecSmrgBool
142105b261ecSmrgDRIGetDrawableInfo(ScreenPtr pScreen,
142205b261ecSmrg                   DrawablePtr pDrawable,
142335c4bbdfSmrg                   unsigned int *index,
142435c4bbdfSmrg                   unsigned int *stamp,
142535c4bbdfSmrg                   int *X,
142635c4bbdfSmrg                   int *Y,
142735c4bbdfSmrg                   int *W,
142835c4bbdfSmrg                   int *H,
142935c4bbdfSmrg                   int *numClipRects,
143005b261ecSmrg                   drm_clip_rect_t ** pClipRects,
143135c4bbdfSmrg                   int *backX,
143235c4bbdfSmrg                   int *backY,
143335c4bbdfSmrg                   int *numBackClipRects, drm_clip_rect_t ** pBackClipRects)
143405b261ecSmrg{
143535c4bbdfSmrg    DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
143635c4bbdfSmrg    DRIDrawablePrivPtr pDRIDrawablePriv, pOldDrawPriv;
143735c4bbdfSmrg    WindowPtr pWin, pOldWin;
143835c4bbdfSmrg    int i;
143905b261ecSmrg
144005b261ecSmrg#if 0
144135c4bbdfSmrg    printf("maxDrawableTableEntry = %d\n",
144235c4bbdfSmrg           pDRIPriv->pDriverInfo->maxDrawableTableEntry);
144305b261ecSmrg#endif
144405b261ecSmrg
144505b261ecSmrg    if (pDrawable->type == DRAWABLE_WINDOW) {
144635c4bbdfSmrg        pWin = (WindowPtr) pDrawable;
144735c4bbdfSmrg        if ((pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin))) {
144835c4bbdfSmrg
144935c4bbdfSmrg            /* Manage drawable table */
145035c4bbdfSmrg            if (pDRIDrawablePriv->drawableIndex == -1) {        /* load SAREA table */
145135c4bbdfSmrg
145235c4bbdfSmrg                /* Search table for empty entry */
145335c4bbdfSmrg                i = 0;
145435c4bbdfSmrg                while (i < pDRIPriv->pDriverInfo->maxDrawableTableEntry) {
145535c4bbdfSmrg                    if (!(pDRIPriv->DRIDrawables[i])) {
145635c4bbdfSmrg                        pDRIPriv->DRIDrawables[i] = pDrawable;
145735c4bbdfSmrg                        pDRIDrawablePriv->drawableIndex = i;
145835c4bbdfSmrg                        pDRIPriv->pSAREA->drawableTable[i].stamp =
145935c4bbdfSmrg                            DRIDrawableValidationStamp++;
146035c4bbdfSmrg                        break;
146135c4bbdfSmrg                    }
146235c4bbdfSmrg                    i++;
146335c4bbdfSmrg                }
146435c4bbdfSmrg
146535c4bbdfSmrg                /* Search table for oldest entry */
146635c4bbdfSmrg                if (i == pDRIPriv->pDriverInfo->maxDrawableTableEntry) {
146705b261ecSmrg                    unsigned int oldestStamp = ~0;
146805b261ecSmrg                    int oldestIndex = 0;
146935c4bbdfSmrg
147035c4bbdfSmrg                    i = pDRIPriv->pDriverInfo->maxDrawableTableEntry;
147135c4bbdfSmrg                    while (i--) {
147235c4bbdfSmrg                        if (pDRIPriv->pSAREA->drawableTable[i].stamp <
147335c4bbdfSmrg                            oldestStamp) {
147435c4bbdfSmrg                            oldestIndex = i;
147535c4bbdfSmrg                            oldestStamp =
147635c4bbdfSmrg                                pDRIPriv->pSAREA->drawableTable[i].stamp;
147735c4bbdfSmrg                        }
147835c4bbdfSmrg                    }
147935c4bbdfSmrg                    pDRIDrawablePriv->drawableIndex = oldestIndex;
148035c4bbdfSmrg
148135c4bbdfSmrg                    /* release oldest drawable table entry */
148235c4bbdfSmrg                    pOldWin = (WindowPtr) pDRIPriv->DRIDrawables[oldestIndex];
148335c4bbdfSmrg                    pOldDrawPriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pOldWin);
148435c4bbdfSmrg                    pOldDrawPriv->drawableIndex = -1;
148535c4bbdfSmrg
148635c4bbdfSmrg                    /* claim drawable table entry */
148735c4bbdfSmrg                    pDRIPriv->DRIDrawables[oldestIndex] = pDrawable;
148835c4bbdfSmrg
148935c4bbdfSmrg                    /* validate SAREA entry */
149035c4bbdfSmrg                    pDRIPriv->pSAREA->drawableTable[oldestIndex].stamp =
149135c4bbdfSmrg                        DRIDrawableValidationStamp++;
149235c4bbdfSmrg
149335c4bbdfSmrg                    /* check for stamp wrap around */
149435c4bbdfSmrg                    if (oldestStamp > DRIDrawableValidationStamp) {
149535c4bbdfSmrg
149635c4bbdfSmrg                        /* walk SAREA table and invalidate all drawables */
149735c4bbdfSmrg                        for (i = 0;
149805b261ecSmrg                             i < pDRIPriv->pDriverInfo->maxDrawableTableEntry;
149905b261ecSmrg                             i++) {
150035c4bbdfSmrg                            pDRIPriv->pSAREA->drawableTable[i].stamp =
150135c4bbdfSmrg                                DRIDrawableValidationStamp++;
150235c4bbdfSmrg                        }
150335c4bbdfSmrg                    }
150435c4bbdfSmrg                }
150535c4bbdfSmrg
150635c4bbdfSmrg                /* If the driver wants to be notified when the index is
150735c4bbdfSmrg                 * set for a drawable, let it know now.
150835c4bbdfSmrg                 */
150935c4bbdfSmrg                if (pDRIPriv->pDriverInfo->SetDrawableIndex)
151035c4bbdfSmrg                    pDRIPriv->pDriverInfo->SetDrawableIndex(pWin,
151135c4bbdfSmrg                                                            pDRIDrawablePriv->
151235c4bbdfSmrg                                                            drawableIndex);
151335c4bbdfSmrg
151435c4bbdfSmrg                /* reinit drawable ID if window is visible */
151535c4bbdfSmrg                if ((pWin->viewable) &&
151635c4bbdfSmrg                    (pDRIPriv->pDriverInfo->bufferRequests != DRI_NO_WINDOWS)) {
151735c4bbdfSmrg                    (*pDRIPriv->pDriverInfo->InitBuffers) (pWin,
151835c4bbdfSmrg                                                           &pWin->clipList,
151935c4bbdfSmrg                                                           pDRIDrawablePriv->
152035c4bbdfSmrg                                                           drawableIndex);
152135c4bbdfSmrg                }
152235c4bbdfSmrg            }
152335c4bbdfSmrg
152435c4bbdfSmrg            *index = pDRIDrawablePriv->drawableIndex;
152535c4bbdfSmrg            *stamp = pDRIPriv->pSAREA->drawableTable[*index].stamp;
152635c4bbdfSmrg            *X = (int) (pWin->drawable.x);
152735c4bbdfSmrg            *Y = (int) (pWin->drawable.y);
152835c4bbdfSmrg            *W = (int) (pWin->drawable.width);
152935c4bbdfSmrg            *H = (int) (pWin->drawable.height);
153035c4bbdfSmrg            *numClipRects = RegionNumRects(&pWin->clipList);
153135c4bbdfSmrg            *pClipRects = (drm_clip_rect_t *) RegionRects(&pWin->clipList);
153235c4bbdfSmrg
153335c4bbdfSmrg            if (!*numClipRects && pDRIPriv->fullscreen) {
153435c4bbdfSmrg                /* use fake full-screen clip rect */
153535c4bbdfSmrg                pDRIPriv->fullscreen_rect.x1 = *X;
153635c4bbdfSmrg                pDRIPriv->fullscreen_rect.y1 = *Y;
153735c4bbdfSmrg                pDRIPriv->fullscreen_rect.x2 = *X + *W;
153835c4bbdfSmrg                pDRIPriv->fullscreen_rect.y2 = *Y + *H;
153935c4bbdfSmrg
154035c4bbdfSmrg                *numClipRects = 1;
154135c4bbdfSmrg                *pClipRects = &pDRIPriv->fullscreen_rect;
154235c4bbdfSmrg            }
154335c4bbdfSmrg
154435c4bbdfSmrg            *backX = *X;
154535c4bbdfSmrg            *backY = *Y;
154635c4bbdfSmrg
154735c4bbdfSmrg            if (pDRIPriv->nrWindowsVisible == 1 && *numClipRects) {
154835c4bbdfSmrg                /* Use a single cliprect. */
154935c4bbdfSmrg
155035c4bbdfSmrg                int x0 = *X;
155135c4bbdfSmrg                int y0 = *Y;
155235c4bbdfSmrg                int x1 = x0 + *W;
155335c4bbdfSmrg                int y1 = y0 + *H;
155435c4bbdfSmrg
155535c4bbdfSmrg                if (x0 < 0)
155635c4bbdfSmrg                    x0 = 0;
155735c4bbdfSmrg                if (y0 < 0)
155835c4bbdfSmrg                    y0 = 0;
155935c4bbdfSmrg                if (x1 > pScreen->width)
156035c4bbdfSmrg                    x1 = pScreen->width;
156135c4bbdfSmrg                if (y1 > pScreen->height)
156235c4bbdfSmrg                    y1 = pScreen->height;
156335c4bbdfSmrg
156435c4bbdfSmrg                if (y0 >= y1 || x0 >= x1) {
156535c4bbdfSmrg                    *numBackClipRects = 0;
156635c4bbdfSmrg                    *pBackClipRects = NULL;
156735c4bbdfSmrg                }
156835c4bbdfSmrg                else {
156935c4bbdfSmrg                    pDRIPriv->private_buffer_rect.x1 = x0;
157035c4bbdfSmrg                    pDRIPriv->private_buffer_rect.y1 = y0;
157135c4bbdfSmrg                    pDRIPriv->private_buffer_rect.x2 = x1;
157235c4bbdfSmrg                    pDRIPriv->private_buffer_rect.y2 = y1;
157335c4bbdfSmrg
157435c4bbdfSmrg                    *numBackClipRects = 1;
157535c4bbdfSmrg                    *pBackClipRects = &(pDRIPriv->private_buffer_rect);
157635c4bbdfSmrg                }
157735c4bbdfSmrg            }
157835c4bbdfSmrg            else {
157935c4bbdfSmrg                /* Use the frontbuffer cliprects for back buffers.  */
158035c4bbdfSmrg                *numBackClipRects = 0;
158135c4bbdfSmrg                *pBackClipRects = 0;
158235c4bbdfSmrg            }
158335c4bbdfSmrg        }
158435c4bbdfSmrg        else {
158535c4bbdfSmrg            /* Not a DRIDrawable */
158635c4bbdfSmrg            return FALSE;
158735c4bbdfSmrg        }
158835c4bbdfSmrg    }
158935c4bbdfSmrg    else {                      /* pixmap (or for GLX 1.3, a PBuffer) */
159035c4bbdfSmrg        /* NOT_DONE */
159135c4bbdfSmrg        return FALSE;
159205b261ecSmrg    }
159305b261ecSmrg
159405b261ecSmrg    return TRUE;
159505b261ecSmrg}
159605b261ecSmrg
159705b261ecSmrgBool
159805b261ecSmrgDRIGetDeviceInfo(ScreenPtr pScreen,
159905b261ecSmrg                 drm_handle_t * hFrameBuffer,
160035c4bbdfSmrg                 int *fbOrigin,
160135c4bbdfSmrg                 int *fbSize,
160235c4bbdfSmrg                 int *fbStride, int *devPrivateSize, void **pDevPrivate)
160305b261ecSmrg{
160405b261ecSmrg    DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
160505b261ecSmrg
160605b261ecSmrg    *hFrameBuffer = pDRIPriv->pDriverInfo->hFrameBuffer;
160705b261ecSmrg    *fbOrigin = 0;
160805b261ecSmrg    *fbSize = pDRIPriv->pDriverInfo->frameBufferSize;
160905b261ecSmrg    *fbStride = pDRIPriv->pDriverInfo->frameBufferStride;
161005b261ecSmrg    *devPrivateSize = pDRIPriv->pDriverInfo->devPrivateSize;
161105b261ecSmrg    *pDevPrivate = pDRIPriv->pDriverInfo->devPrivate;
161205b261ecSmrg
161305b261ecSmrg    return TRUE;
161405b261ecSmrg}
161505b261ecSmrg
161605b261ecSmrgDRIInfoPtr
161705b261ecSmrgDRICreateInfoRec(void)
161805b261ecSmrg{
161935c4bbdfSmrg    DRIInfoPtr inforec = (DRIInfoPtr) calloc(1, sizeof(DRIInfoRec));
162035c4bbdfSmrg
162135c4bbdfSmrg    if (!inforec)
162235c4bbdfSmrg        return NULL;
162305b261ecSmrg
162405b261ecSmrg    /* Initialize defaults */
162505b261ecSmrg    inforec->busIdString = NULL;
162605b261ecSmrg
162705b261ecSmrg    /* Wrapped function defaults */
162835c4bbdfSmrg    inforec->wrap.WakeupHandler = DRIDoWakeupHandler;
162935c4bbdfSmrg    inforec->wrap.BlockHandler = DRIDoBlockHandler;
163035c4bbdfSmrg    inforec->wrap.WindowExposures = DRIWindowExposures;
163135c4bbdfSmrg    inforec->wrap.CopyWindow = DRICopyWindow;
163235c4bbdfSmrg    inforec->wrap.ClipNotify = DRIClipNotify;
163335c4bbdfSmrg    inforec->wrap.AdjustFrame = DRIAdjustFrame;
163405b261ecSmrg
163505b261ecSmrg    inforec->TransitionTo2d = 0;
163605b261ecSmrg    inforec->TransitionTo3d = 0;
163705b261ecSmrg    inforec->SetDrawableIndex = 0;
163805b261ecSmrg
163905b261ecSmrg    return inforec;
164005b261ecSmrg}
164105b261ecSmrg
164205b261ecSmrgvoid
164305b261ecSmrgDRIDestroyInfoRec(DRIInfoPtr DRIInfo)
164405b261ecSmrg{
16456747b715Smrg    free(DRIInfo->busIdString);
164635c4bbdfSmrg    free((char *) DRIInfo);
164705b261ecSmrg}
164805b261ecSmrg
164905b261ecSmrgvoid
16501b5d61b8SmrgDRIWakeupHandler(void *wakeupData, int result)
165105b261ecSmrg{
165205b261ecSmrg    int i;
165305b261ecSmrg
165405b261ecSmrg    for (i = 0; i < screenInfo.numScreens; i++) {
165535c4bbdfSmrg        ScreenPtr pScreen = screenInfo.screens[i];
165635c4bbdfSmrg        DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
165705b261ecSmrg
165835c4bbdfSmrg        if (pDRIPriv && pDRIPriv->pDriverInfo->wrap.WakeupHandler)
16591b5d61b8Smrg            (*pDRIPriv->pDriverInfo->wrap.WakeupHandler) (pScreen, result);
166005b261ecSmrg    }
166105b261ecSmrg}
166205b261ecSmrg
166305b261ecSmrgvoid
16641b5d61b8SmrgDRIBlockHandler(void *blockData, void *pTimeout)
166505b261ecSmrg{
166605b261ecSmrg    int i;
166705b261ecSmrg
166805b261ecSmrg    for (i = 0; i < screenInfo.numScreens; i++) {
166935c4bbdfSmrg        ScreenPtr pScreen = screenInfo.screens[i];
167035c4bbdfSmrg        DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
167105b261ecSmrg
167235c4bbdfSmrg        if (pDRIPriv && pDRIPriv->pDriverInfo->wrap.BlockHandler)
16731b5d61b8Smrg            (*pDRIPriv->pDriverInfo->wrap.BlockHandler) (pScreen, pTimeout);
167405b261ecSmrg    }
167505b261ecSmrg}
167605b261ecSmrg
167705b261ecSmrgvoid
16781b5d61b8SmrgDRIDoWakeupHandler(ScreenPtr pScreen, int result)
167905b261ecSmrg{
168005b261ecSmrg    DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
168105b261ecSmrg
168205b261ecSmrg    DRILock(pScreen, 0);
168305b261ecSmrg    if (pDRIPriv->pDriverInfo->driverSwapMethod == DRI_HIDE_X_CONTEXT) {
168435c4bbdfSmrg        /* hide X context by swapping 2D component here */
168535c4bbdfSmrg        (*pDRIPriv->pDriverInfo->SwapContext) (pScreen,
168635c4bbdfSmrg                                               DRI_3D_SYNC,
168735c4bbdfSmrg                                               DRI_2D_CONTEXT,
168835c4bbdfSmrg                                               pDRIPriv->partial3DContextStore,
168935c4bbdfSmrg                                               DRI_2D_CONTEXT,
169035c4bbdfSmrg                                               pDRIPriv->hiddenContextStore);
169105b261ecSmrg    }
169205b261ecSmrg}
169305b261ecSmrg
169405b261ecSmrgvoid
16951b5d61b8SmrgDRIDoBlockHandler(ScreenPtr pScreen, void *timeout)
169605b261ecSmrg{
169705b261ecSmrg    DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
169805b261ecSmrg
169905b261ecSmrg    if (pDRIPriv->pDriverInfo->driverSwapMethod == DRI_HIDE_X_CONTEXT) {
170035c4bbdfSmrg        /* hide X context by swapping 2D component here */
170135c4bbdfSmrg        (*pDRIPriv->pDriverInfo->SwapContext) (pScreen,
170235c4bbdfSmrg                                               DRI_2D_SYNC,
170335c4bbdfSmrg                                               DRI_NO_CONTEXT,
170435c4bbdfSmrg                                               NULL,
170535c4bbdfSmrg                                               DRI_2D_CONTEXT,
170635c4bbdfSmrg                                               pDRIPriv->partial3DContextStore);
170705b261ecSmrg    }
170805b261ecSmrg
170905b261ecSmrg    if (pDRIPriv->windowsTouched)
171005b261ecSmrg        DRM_SPINUNLOCK(&pDRIPriv->pSAREA->drawable_lock, 1);
171105b261ecSmrg    pDRIPriv->windowsTouched = FALSE;
171205b261ecSmrg
171305b261ecSmrg    DRIUnlock(pScreen);
171405b261ecSmrg}
171505b261ecSmrg
171605b261ecSmrgvoid
171705b261ecSmrgDRISwapContext(int drmFD, void *oldctx, void *newctx)
171805b261ecSmrg{
171935c4bbdfSmrg    DRIContextPrivPtr oldContext = (DRIContextPrivPtr) oldctx;
172035c4bbdfSmrg    DRIContextPrivPtr newContext = (DRIContextPrivPtr) newctx;
172135c4bbdfSmrg    ScreenPtr pScreen = newContext->pScreen;
172235c4bbdfSmrg    DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
172335c4bbdfSmrg    void *oldContextStore = NULL;
172435c4bbdfSmrg    DRIContextType oldContextType;
172535c4bbdfSmrg    void *newContextStore = NULL;
172635c4bbdfSmrg    DRIContextType newContextType;
172735c4bbdfSmrg    DRISyncType syncType;
172835c4bbdfSmrg
172905b261ecSmrg#ifdef DEBUG
173035c4bbdfSmrg    static int count = 0;
173105b261ecSmrg
173205b261ecSmrg    if (!newContext) {
173335c4bbdfSmrg        DRIDrvMsg(pScreen->myNum, X_ERROR,
173435c4bbdfSmrg                  "[DRI] Context Switch Error: oldContext=%p, newContext=%p\n",
173535c4bbdfSmrg                  oldContext, newContext);
173635c4bbdfSmrg        return;
173705b261ecSmrg    }
173805b261ecSmrg
1739ed6184dfSmrg    /* useful for debugging, just print out after n context switches */
174005b261ecSmrg    if (!count || !(count % 1)) {
174135c4bbdfSmrg        DRIDrvMsg(pScreen->myNum, X_INFO,
174235c4bbdfSmrg                  "[DRI] Context switch %5d from %p/0x%08x (%d)\n",
174335c4bbdfSmrg                  count,
174435c4bbdfSmrg                  oldContext,
174535c4bbdfSmrg                  oldContext ? oldContext->flags : 0,
174635c4bbdfSmrg                  oldContext ? oldContext->hwContext : -1);
174735c4bbdfSmrg        DRIDrvMsg(pScreen->myNum, X_INFO,
174835c4bbdfSmrg                  "[DRI] Context switch %5d to   %p/0x%08x (%d)\n",
174935c4bbdfSmrg                  count,
175035c4bbdfSmrg                  newContext,
175135c4bbdfSmrg                  newContext ? newContext->flags : 0,
175235c4bbdfSmrg                  newContext ? newContext->hwContext : -1);
175305b261ecSmrg    }
175405b261ecSmrg    ++count;
175505b261ecSmrg#endif
175605b261ecSmrg
175705b261ecSmrg    if (!pDRIPriv->pDriverInfo->SwapContext) {
175835c4bbdfSmrg        DRIDrvMsg(pScreen->myNum, X_ERROR,
175935c4bbdfSmrg                  "[DRI] DDX driver missing context swap call back\n");
176035c4bbdfSmrg        return;
176105b261ecSmrg    }
176205b261ecSmrg
176305b261ecSmrg    if (pDRIPriv->pDriverInfo->driverSwapMethod == DRI_HIDE_X_CONTEXT) {
176405b261ecSmrg
176505b261ecSmrg        /* only 3D contexts are swapped in this case */
176635c4bbdfSmrg        if (oldContext) {
176735c4bbdfSmrg            oldContextStore = DRIGetContextStore(oldContext);
176835c4bbdfSmrg            oldContext->valid3D = TRUE;
176935c4bbdfSmrg            oldContextType = DRI_3D_CONTEXT;
177035c4bbdfSmrg        }
177135c4bbdfSmrg        else {
177235c4bbdfSmrg            oldContextType = DRI_NO_CONTEXT;
177335c4bbdfSmrg        }
177435c4bbdfSmrg        newContextStore = DRIGetContextStore(newContext);
177535c4bbdfSmrg        if ((newContext->valid3D) &&
177635c4bbdfSmrg            (newContext->hwContext != pDRIPriv->myContext)) {
177735c4bbdfSmrg            newContextType = DRI_3D_CONTEXT;
177835c4bbdfSmrg        }
177935c4bbdfSmrg        else {
178035c4bbdfSmrg            newContextType = DRI_2D_CONTEXT;
178135c4bbdfSmrg        }
178235c4bbdfSmrg        syncType = DRI_3D_SYNC;
178335c4bbdfSmrg    }
178435c4bbdfSmrg    else {                      /* default: driverSwapMethod == DRI_SERVER_SWAP */
178505b261ecSmrg
178605b261ecSmrg        /* optimize 2D context swaps */
178705b261ecSmrg
178835c4bbdfSmrg        if (newContext->flags & DRI_CONTEXT_2DONLY) {
178935c4bbdfSmrg            /* go from 3D context to 2D context and only save 2D
179005b261ecSmrg             * subset of 3D state
179105b261ecSmrg             */
179235c4bbdfSmrg            oldContextStore = DRIGetContextStore(oldContext);
179335c4bbdfSmrg            oldContextType = DRI_2D_CONTEXT;
179435c4bbdfSmrg            newContextStore = DRIGetContextStore(newContext);
179535c4bbdfSmrg            newContextType = DRI_2D_CONTEXT;
179635c4bbdfSmrg            syncType = DRI_3D_SYNC;
179735c4bbdfSmrg            pDRIPriv->lastPartial3DContext = oldContext;
179835c4bbdfSmrg        }
179935c4bbdfSmrg        else if (oldContext->flags & DRI_CONTEXT_2DONLY) {
180035c4bbdfSmrg            if (pDRIPriv->lastPartial3DContext == newContext) {
180135c4bbdfSmrg                /* go from 2D context back to previous 3D context and
180235c4bbdfSmrg                 * only restore 2D subset of previous 3D state
180335c4bbdfSmrg                 */
180435c4bbdfSmrg                oldContextStore = DRIGetContextStore(oldContext);
180535c4bbdfSmrg                oldContextType = DRI_2D_CONTEXT;
180635c4bbdfSmrg                newContextStore = DRIGetContextStore(newContext);
180735c4bbdfSmrg                newContextType = DRI_2D_CONTEXT;
180835c4bbdfSmrg                syncType = DRI_2D_SYNC;
180935c4bbdfSmrg            }
181035c4bbdfSmrg            else {
181135c4bbdfSmrg                /* go from 2D context to a different 3D context */
181235c4bbdfSmrg
181335c4bbdfSmrg                /* call DDX driver to do partial restore */
181435c4bbdfSmrg                oldContextStore = DRIGetContextStore(oldContext);
181535c4bbdfSmrg                newContextStore =
181635c4bbdfSmrg                    DRIGetContextStore(pDRIPriv->lastPartial3DContext);
181735c4bbdfSmrg                (*pDRIPriv->pDriverInfo->SwapContext) (pScreen,
181835c4bbdfSmrg                                                       DRI_2D_SYNC,
181935c4bbdfSmrg                                                       DRI_2D_CONTEXT,
182035c4bbdfSmrg                                                       oldContextStore,
182135c4bbdfSmrg                                                       DRI_2D_CONTEXT,
182235c4bbdfSmrg                                                       newContextStore);
182335c4bbdfSmrg
182435c4bbdfSmrg                /* now setup for a complete 3D swap */
182535c4bbdfSmrg                oldContextStore = newContextStore;
182635c4bbdfSmrg                oldContext->valid3D = TRUE;
182735c4bbdfSmrg                oldContextType = DRI_3D_CONTEXT;
182835c4bbdfSmrg                newContextStore = DRIGetContextStore(newContext);
182935c4bbdfSmrg                if ((newContext->valid3D) &&
183035c4bbdfSmrg                    (newContext->hwContext != pDRIPriv->myContext)) {
183135c4bbdfSmrg                    newContextType = DRI_3D_CONTEXT;
183235c4bbdfSmrg                }
183335c4bbdfSmrg                else {
183435c4bbdfSmrg                    newContextType = DRI_2D_CONTEXT;
183535c4bbdfSmrg                }
183635c4bbdfSmrg                syncType = DRI_NO_SYNC;
183735c4bbdfSmrg            }
183835c4bbdfSmrg        }
183935c4bbdfSmrg        else {
184035c4bbdfSmrg            /* now setup for a complete 3D swap */
184135c4bbdfSmrg            oldContextStore = newContextStore;
184235c4bbdfSmrg            oldContext->valid3D = TRUE;
184335c4bbdfSmrg            oldContextType = DRI_3D_CONTEXT;
184435c4bbdfSmrg            newContextStore = DRIGetContextStore(newContext);
184535c4bbdfSmrg            if ((newContext->valid3D) &&
184635c4bbdfSmrg                (newContext->hwContext != pDRIPriv->myContext)) {
184735c4bbdfSmrg                newContextType = DRI_3D_CONTEXT;
184835c4bbdfSmrg            }
184935c4bbdfSmrg            else {
185035c4bbdfSmrg                newContextType = DRI_2D_CONTEXT;
185135c4bbdfSmrg            }
185235c4bbdfSmrg            syncType = DRI_3D_SYNC;
185335c4bbdfSmrg        }
185405b261ecSmrg    }
185505b261ecSmrg
185605b261ecSmrg    /* call DDX driver to perform the swap */
185735c4bbdfSmrg    (*pDRIPriv->pDriverInfo->SwapContext) (pScreen,
185835c4bbdfSmrg                                           syncType,
185935c4bbdfSmrg                                           oldContextType,
186035c4bbdfSmrg                                           oldContextStore,
186135c4bbdfSmrg                                           newContextType, newContextStore);
186205b261ecSmrg}
186305b261ecSmrg
186435c4bbdfSmrgvoid *
186505b261ecSmrgDRIGetContextStore(DRIContextPrivPtr context)
186605b261ecSmrg{
186735c4bbdfSmrg    return ((void *) context->pContextStore);
186805b261ecSmrg}
186905b261ecSmrg
187005b261ecSmrgvoid
187135c4bbdfSmrgDRIWindowExposures(WindowPtr pWin, RegionPtr prgn)
187205b261ecSmrg{
187305b261ecSmrg    ScreenPtr pScreen = pWin->drawable.pScreen;
187405b261ecSmrg    DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
187505b261ecSmrg    DRIDrawablePrivPtr pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin);
187605b261ecSmrg
187735c4bbdfSmrg    if (pDRIDrawablePriv) {
187835c4bbdfSmrg        (*pDRIPriv->pDriverInfo->InitBuffers) (pWin, prgn,
187905b261ecSmrg                                               pDRIDrawablePriv->drawableIndex);
188005b261ecSmrg    }
188105b261ecSmrg
188205b261ecSmrg    /* call lower wrapped functions */
188305b261ecSmrg    if (pDRIPriv && pDRIPriv->wrap.WindowExposures) {
188405b261ecSmrg
188535c4bbdfSmrg        /* unwrap */
188635c4bbdfSmrg        pScreen->WindowExposures = pDRIPriv->wrap.WindowExposures;
188705b261ecSmrg
188835c4bbdfSmrg        /* call lower layers */
188935c4bbdfSmrg        (*pScreen->WindowExposures) (pWin, prgn);
189005b261ecSmrg
189135c4bbdfSmrg        /* rewrap */
189235c4bbdfSmrg        pDRIPriv->wrap.WindowExposures = pScreen->WindowExposures;
189335c4bbdfSmrg        pScreen->WindowExposures = DRIWindowExposures;
189405b261ecSmrg    }
189505b261ecSmrg}
189605b261ecSmrg
189705b261ecSmrgstatic int
189835c4bbdfSmrgDRITreeTraversal(WindowPtr pWin, void *data)
189905b261ecSmrg{
190005b261ecSmrg    DRIDrawablePrivPtr pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin);
190105b261ecSmrg
190235c4bbdfSmrg    if (pDRIDrawablePriv) {
190305b261ecSmrg        ScreenPtr pScreen = pWin->drawable.pScreen;
190405b261ecSmrg        DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
190505b261ecSmrg
190635c4bbdfSmrg        if (RegionNumRects(&(pWin->clipList)) > 0) {
190735c4bbdfSmrg            RegionPtr reg = (RegionPtr) data;
190805b261ecSmrg
190935c4bbdfSmrg            RegionUnion(reg, reg, &(pWin->clipList));
191035c4bbdfSmrg            pDRIPriv->nrWalked++;
191135c4bbdfSmrg        }
191205b261ecSmrg
191335c4bbdfSmrg        if (pDRIPriv->nrWindows == pDRIPriv->nrWalked)
191435c4bbdfSmrg            return WT_STOPWALKING;
191505b261ecSmrg    }
191605b261ecSmrg    return WT_WALKCHILDREN;
191705b261ecSmrg}
191805b261ecSmrg
191905b261ecSmrgBool
192005b261ecSmrgDRIDestroyWindow(WindowPtr pWin)
192105b261ecSmrg{
192205b261ecSmrg    ScreenPtr pScreen = pWin->drawable.pScreen;
192305b261ecSmrg    DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
192405b261ecSmrg    Bool retval = TRUE;
192505b261ecSmrg
192605b261ecSmrg    DRIDrawablePrivDestroy(pWin);
192705b261ecSmrg
192805b261ecSmrg    /* call lower wrapped functions */
192935c4bbdfSmrg    if (pDRIPriv->DestroyWindow) {
193035c4bbdfSmrg        /* unwrap */
193135c4bbdfSmrg        pScreen->DestroyWindow = pDRIPriv->DestroyWindow;
193205b261ecSmrg
193335c4bbdfSmrg        /* call lower layers */
193435c4bbdfSmrg        retval = (*pScreen->DestroyWindow) (pWin);
193505b261ecSmrg
193635c4bbdfSmrg        /* rewrap */
193735c4bbdfSmrg        pDRIPriv->DestroyWindow = pScreen->DestroyWindow;
193835c4bbdfSmrg        pScreen->DestroyWindow = DRIDestroyWindow;
193905b261ecSmrg    }
194005b261ecSmrg
194105b261ecSmrg    return retval;
194205b261ecSmrg}
194305b261ecSmrg
194405b261ecSmrgvoid
194505b261ecSmrgDRICopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
194605b261ecSmrg{
194705b261ecSmrg    ScreenPtr pScreen = pWin->drawable.pScreen;
194805b261ecSmrg    DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
194905b261ecSmrg
195035c4bbdfSmrg    if (!pDRIPriv)
195135c4bbdfSmrg        return;
195205b261ecSmrg
195335c4bbdfSmrg    if (pDRIPriv->nrWindowsVisible > 0) {
195435c4bbdfSmrg        RegionRec reg;
195505b261ecSmrg
195635c4bbdfSmrg        RegionNull(&reg);
195735c4bbdfSmrg        pDRIPriv->nrWalked = 0;
195835c4bbdfSmrg        TraverseTree(pWin, DRITreeTraversal, (void *) (&reg));
195905b261ecSmrg
196035c4bbdfSmrg        if (RegionNotEmpty(&reg)) {
196135c4bbdfSmrg            RegionTranslate(&reg, ptOldOrg.x - pWin->drawable.x,
196235c4bbdfSmrg                            ptOldOrg.y - pWin->drawable.y);
196335c4bbdfSmrg            RegionIntersect(&reg, &reg, prgnSrc);
196405b261ecSmrg
196535c4bbdfSmrg            /* The MoveBuffers interface is not ideal */
196635c4bbdfSmrg            (*pDRIPriv->pDriverInfo->MoveBuffers) (pWin, ptOldOrg, &reg,
196735c4bbdfSmrg                                                   pDRIPriv->pDriverInfo->
196835c4bbdfSmrg                                                   ddxDrawableTableEntry);
196935c4bbdfSmrg        }
197005b261ecSmrg
197135c4bbdfSmrg        RegionUninit(&reg);
197205b261ecSmrg    }
197305b261ecSmrg
197405b261ecSmrg    /* call lower wrapped functions */
197535c4bbdfSmrg    if (pDRIPriv->wrap.CopyWindow) {
197635c4bbdfSmrg        /* unwrap */
197735c4bbdfSmrg        pScreen->CopyWindow = pDRIPriv->wrap.CopyWindow;
197805b261ecSmrg
197935c4bbdfSmrg        /* call lower layers */
198035c4bbdfSmrg        (*pScreen->CopyWindow) (pWin, ptOldOrg, prgnSrc);
198105b261ecSmrg
198235c4bbdfSmrg        /* rewrap */
198335c4bbdfSmrg        pDRIPriv->wrap.CopyWindow = pScreen->CopyWindow;
198435c4bbdfSmrg        pScreen->CopyWindow = DRICopyWindow;
198505b261ecSmrg    }
198605b261ecSmrg}
198705b261ecSmrg
198805b261ecSmrgstatic void
198905b261ecSmrgDRIGetSecs(long *secs, long *usecs)
199005b261ecSmrg{
199105b261ecSmrg    struct timeval tv;
199205b261ecSmrg
199305b261ecSmrg    gettimeofday(&tv, NULL);
199405b261ecSmrg
199535c4bbdfSmrg    *secs = tv.tv_sec;
199605b261ecSmrg    *usecs = tv.tv_usec;
199705b261ecSmrg}
199805b261ecSmrg
199905b261ecSmrgstatic unsigned long
200005b261ecSmrgDRIComputeMilliSeconds(unsigned long s_secs, unsigned long s_usecs,
200135c4bbdfSmrg                       unsigned long f_secs, unsigned long f_usecs)
200205b261ecSmrg{
200305b261ecSmrg    if (f_usecs < s_usecs) {
200435c4bbdfSmrg        --f_secs;
200535c4bbdfSmrg        f_usecs += 1000000;
200605b261ecSmrg    }
200705b261ecSmrg    return (f_secs - s_secs) * 1000 + (f_usecs - s_usecs) / 1000;
200805b261ecSmrg}
200905b261ecSmrg
201005b261ecSmrgstatic void
201135c4bbdfSmrgDRISpinLockTimeout(drmLock * lock, int val, unsigned long timeout /* in mS */ )
201205b261ecSmrg{
201335c4bbdfSmrg    int count = 10000;
201435c4bbdfSmrg
201505b261ecSmrg#if !defined(__alpha__) && !defined(__powerpc__)
201605b261ecSmrg    char ret;
201705b261ecSmrg#else
201805b261ecSmrg    int ret;
201905b261ecSmrg#endif
202005b261ecSmrg    long s_secs, s_usecs;
202105b261ecSmrg    long f_secs, f_usecs;
202205b261ecSmrg    long msecs;
202335c4bbdfSmrg    long prev = 0;
202405b261ecSmrg
202505b261ecSmrg    DRIGetSecs(&s_secs, &s_usecs);
202605b261ecSmrg
202705b261ecSmrg    do {
202835c4bbdfSmrg        DRM_SPINLOCK_COUNT(lock, val, count, ret);
202935c4bbdfSmrg        if (!ret)
203035c4bbdfSmrg            return;             /* Got lock */
203135c4bbdfSmrg        DRIGetSecs(&f_secs, &f_usecs);
203235c4bbdfSmrg        msecs = DRIComputeMilliSeconds(s_secs, s_usecs, f_secs, f_usecs);
203335c4bbdfSmrg        if (msecs - prev < 250)
203435c4bbdfSmrg            count *= 2;         /* Not more than 0.5S */
203505b261ecSmrg    } while (msecs < timeout);
203605b261ecSmrg
203735c4bbdfSmrg    /* Didn't get lock, so take it.  The worst
203835c4bbdfSmrg       that can happen is that there is some
203935c4bbdfSmrg       garbage written to the wrong part of the
204035c4bbdfSmrg       framebuffer that a refresh will repair.
204135c4bbdfSmrg       That's undesirable, but better than
204235c4bbdfSmrg       locking the server.  This should be a
204335c4bbdfSmrg       very rare event. */
204405b261ecSmrg    DRM_SPINLOCK_TAKE(lock, val);
204505b261ecSmrg}
204605b261ecSmrg
204705b261ecSmrgstatic void
204805b261ecSmrgDRILockTree(ScreenPtr pScreen)
204905b261ecSmrg{
205005b261ecSmrg    DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
205105b261ecSmrg
205235c4bbdfSmrg    if (!pDRIPriv)
205335c4bbdfSmrg        return;
205405b261ecSmrg
205505b261ecSmrg    /* Restore the last known 3D context if the X context is hidden */
205605b261ecSmrg    if (pDRIPriv->pDriverInfo->driverSwapMethod == DRI_HIDE_X_CONTEXT) {
205735c4bbdfSmrg        (*pDRIPriv->pDriverInfo->SwapContext) (pScreen,
205835c4bbdfSmrg                                               DRI_2D_SYNC,
205935c4bbdfSmrg                                               DRI_NO_CONTEXT,
206035c4bbdfSmrg                                               NULL,
206135c4bbdfSmrg                                               DRI_2D_CONTEXT,
206235c4bbdfSmrg                                               pDRIPriv->partial3DContextStore);
206305b261ecSmrg    }
206405b261ecSmrg
206505b261ecSmrg    /* Call kernel to release lock */
206605b261ecSmrg    DRIUnlock(pScreen);
206705b261ecSmrg
206805b261ecSmrg    /* Grab drawable spin lock: a time out between 10 and 30 seconds is
206905b261ecSmrg       appropriate, since this should never time out except in the case of
207005b261ecSmrg       client death while the lock is being held.  The timeout must be
207105b261ecSmrg       greater than any reasonable rendering time. */
207235c4bbdfSmrg    DRISpinLockTimeout(&pDRIPriv->pSAREA->drawable_lock, 1, 10000);     /*10 secs */
207305b261ecSmrg
207405b261ecSmrg    /* Call kernel flush outstanding buffers and relock */
207535c4bbdfSmrg    DRILock(pScreen, DRM_LOCK_QUIESCENT | DRM_LOCK_FLUSH_ALL);
207605b261ecSmrg
207705b261ecSmrg    /* Switch back to our 2D context if the X context is hidden */
207805b261ecSmrg    if (pDRIPriv->pDriverInfo->driverSwapMethod == DRI_HIDE_X_CONTEXT) {
207935c4bbdfSmrg        /* hide X context by swapping 2D component here */
208035c4bbdfSmrg        (*pDRIPriv->pDriverInfo->SwapContext) (pScreen,
208135c4bbdfSmrg                                               DRI_3D_SYNC,
208235c4bbdfSmrg                                               DRI_2D_CONTEXT,
208335c4bbdfSmrg                                               pDRIPriv->partial3DContextStore,
208435c4bbdfSmrg                                               DRI_2D_CONTEXT,
208535c4bbdfSmrg                                               pDRIPriv->hiddenContextStore);
208605b261ecSmrg    }
208705b261ecSmrg}
208805b261ecSmrg
208905b261ecSmrgvoid
209005b261ecSmrgDRIClipNotify(WindowPtr pWin, int dx, int dy)
209105b261ecSmrg{
209205b261ecSmrg    ScreenPtr pScreen = pWin->drawable.pScreen;
209305b261ecSmrg    DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
209435c4bbdfSmrg    DRIDrawablePrivPtr pDRIDrawablePriv;
209505b261ecSmrg
209635c4bbdfSmrg    if (!pDRIPriv)
209735c4bbdfSmrg        return;
209805b261ecSmrg
209905b261ecSmrg    if ((pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin))) {
21006747b715Smrg        int nrects = RegionNumRects(&pWin->clipList);
210105b261ecSmrg
210235c4bbdfSmrg        if (!pDRIPriv->windowsTouched) {
210305b261ecSmrg            DRILockTree(pScreen);
210405b261ecSmrg            pDRIPriv->windowsTouched = TRUE;
210505b261ecSmrg        }
210605b261ecSmrg
210735c4bbdfSmrg        if (nrects && !pDRIDrawablePriv->nrects)
210835c4bbdfSmrg            DRIIncreaseNumberVisible(pScreen);
210935c4bbdfSmrg        else if (!nrects && pDRIDrawablePriv->nrects)
211035c4bbdfSmrg            DRIDecreaseNumberVisible(pScreen);
211135c4bbdfSmrg        else
211235c4bbdfSmrg            DRIDriverClipNotify(pScreen);
211305b261ecSmrg
211435c4bbdfSmrg        pDRIDrawablePriv->nrects = nrects;
211505b261ecSmrg
211635c4bbdfSmrg        pDRIPriv->pSAREA->drawableTable[pDRIDrawablePriv->drawableIndex].stamp
211735c4bbdfSmrg            = DRIDrawableValidationStamp++;
211805b261ecSmrg
211935c4bbdfSmrg        drmUpdateDrawableInfo(pDRIPriv->drmFD, pDRIDrawablePriv->hwDrawable,
212035c4bbdfSmrg                              DRM_DRAWABLE_CLIPRECTS,
212135c4bbdfSmrg                              nrects, RegionRects(&pWin->clipList));
212205b261ecSmrg    }
212305b261ecSmrg
212405b261ecSmrg    /* call lower wrapped functions */
212535c4bbdfSmrg    if (pDRIPriv->wrap.ClipNotify) {
212605b261ecSmrg
212735c4bbdfSmrg        /* unwrap */
212805b261ecSmrg        pScreen->ClipNotify = pDRIPriv->wrap.ClipNotify;
212905b261ecSmrg
213035c4bbdfSmrg        /* call lower layers */
213135c4bbdfSmrg        (*pScreen->ClipNotify) (pWin, dx, dy);
213205b261ecSmrg
213335c4bbdfSmrg        /* rewrap */
213405b261ecSmrg        pDRIPriv->wrap.ClipNotify = pScreen->ClipNotify;
213505b261ecSmrg        pScreen->ClipNotify = DRIClipNotify;
213605b261ecSmrg    }
213705b261ecSmrg}
213805b261ecSmrg
213905b261ecSmrgCARD32
214005b261ecSmrgDRIGetDrawableIndex(WindowPtr pWin)
214105b261ecSmrg{
214205b261ecSmrg    ScreenPtr pScreen = pWin->drawable.pScreen;
214305b261ecSmrg    DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
214405b261ecSmrg    DRIDrawablePrivPtr pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin);
214505b261ecSmrg    CARD32 index;
214605b261ecSmrg
214705b261ecSmrg    if (pDRIDrawablePriv) {
214835c4bbdfSmrg        index = pDRIDrawablePriv->drawableIndex;
214905b261ecSmrg    }
215005b261ecSmrg    else {
215135c4bbdfSmrg        index = pDRIPriv->pDriverInfo->ddxDrawableTableEntry;
215205b261ecSmrg    }
215305b261ecSmrg
215405b261ecSmrg    return index;
215505b261ecSmrg}
215605b261ecSmrg
215705b261ecSmrgunsigned int
215805b261ecSmrgDRIGetDrawableStamp(ScreenPtr pScreen, CARD32 drawable_index)
215905b261ecSmrg{
216005b261ecSmrg    DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
216135c4bbdfSmrg
216205b261ecSmrg    return pDRIPriv->pSAREA->drawableTable[drawable_index].stamp;
216305b261ecSmrg}
216405b261ecSmrg
216505b261ecSmrgvoid
216605b261ecSmrgDRIPrintDrawableLock(ScreenPtr pScreen, char *msg)
216705b261ecSmrg{
216805b261ecSmrg    DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
216905b261ecSmrg
217035c4bbdfSmrg    ErrorF("%s: %d\n", msg, pDRIPriv->pSAREA->drawable_lock.lock);
217105b261ecSmrg}
217205b261ecSmrg
217305b261ecSmrgvoid
217405b261ecSmrgDRILock(ScreenPtr pScreen, int flags)
217505b261ecSmrg{
217605b261ecSmrg    DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
217705b261ecSmrg
217835c4bbdfSmrg    if (!pDRIPriv || !pDRIPriv->pLockRefCount)
217935c4bbdfSmrg        return;
218005b261ecSmrg
218105b261ecSmrg    if (!*pDRIPriv->pLockRefCount) {
218235c4bbdfSmrg        DRM_LOCK(pDRIPriv->drmFD, pDRIPriv->pLSAREA, pDRIPriv->myContext,
218335c4bbdfSmrg                 flags);
218435c4bbdfSmrg        *pDRIPriv->pLockingContext = pDRIPriv->myContext;
218535c4bbdfSmrg    }
218635c4bbdfSmrg    else if (*pDRIPriv->pLockingContext != pDRIPriv->myContext) {
218735c4bbdfSmrg        DRIDrvMsg(pScreen->myNum, X_ERROR,
218835c4bbdfSmrg                  "[DRI] Locking deadlock.\n"
218935c4bbdfSmrg                  "\tAlready locked with context %p,\n"
219035c4bbdfSmrg                  "\ttrying to lock with context %p.\n",
219135c4bbdfSmrg                  pDRIPriv->pLockingContext, (void *) (uintptr_t) pDRIPriv->myContext);
219205b261ecSmrg    }
219305b261ecSmrg    (*pDRIPriv->pLockRefCount)++;
219405b261ecSmrg}
219505b261ecSmrg
219605b261ecSmrgvoid
219705b261ecSmrgDRIUnlock(ScreenPtr pScreen)
219805b261ecSmrg{
219905b261ecSmrg    DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
220005b261ecSmrg
220135c4bbdfSmrg    if (!pDRIPriv || !pDRIPriv->pLockRefCount)
220235c4bbdfSmrg        return;
220305b261ecSmrg
220405b261ecSmrg    if (*pDRIPriv->pLockRefCount > 0) {
220535c4bbdfSmrg        if (pDRIPriv->myContext != *pDRIPriv->pLockingContext) {
220635c4bbdfSmrg            DRIDrvMsg(pScreen->myNum, X_ERROR,
220735c4bbdfSmrg                      "[DRI] Unlocking inconsistency:\n"
220835c4bbdfSmrg                      "\tContext %p trying to unlock lock held by context %p\n",
220935c4bbdfSmrg                      pDRIPriv->pLockingContext, (void *) (uintptr_t) pDRIPriv->myContext);
221035c4bbdfSmrg        }
221135c4bbdfSmrg        (*pDRIPriv->pLockRefCount)--;
221235c4bbdfSmrg    }
221335c4bbdfSmrg    else {
221405b261ecSmrg        DRIDrvMsg(pScreen->myNum, X_ERROR,
221535c4bbdfSmrg                  "DRIUnlock called when not locked.\n");
221605b261ecSmrg        return;
221705b261ecSmrg    }
221835c4bbdfSmrg    if (!*pDRIPriv->pLockRefCount)
221905b261ecSmrg        DRM_UNLOCK(pDRIPriv->drmFD, pDRIPriv->pLSAREA, pDRIPriv->myContext);
222005b261ecSmrg}
222105b261ecSmrg
222205b261ecSmrgvoid *
222305b261ecSmrgDRIGetSAREAPrivate(ScreenPtr pScreen)
222405b261ecSmrg{
222505b261ecSmrg    DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
222605b261ecSmrg
222735c4bbdfSmrg    if (!pDRIPriv)
222835c4bbdfSmrg        return 0;
222935c4bbdfSmrg
223035c4bbdfSmrg    return (void *) (((char *) pDRIPriv->pSAREA) + sizeof(XF86DRISAREARec));
223105b261ecSmrg}
223205b261ecSmrg
223305b261ecSmrgdrm_context_t
223405b261ecSmrgDRIGetContext(ScreenPtr pScreen)
223505b261ecSmrg{
223605b261ecSmrg    DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
223735c4bbdfSmrg
223835c4bbdfSmrg    if (!pDRIPriv)
223935c4bbdfSmrg        return 0;
224005b261ecSmrg
224105b261ecSmrg    return pDRIPriv->myContext;
224205b261ecSmrg}
224305b261ecSmrg
224405b261ecSmrgvoid
224505b261ecSmrgDRIGetTexOffsetFuncs(ScreenPtr pScreen,
224635c4bbdfSmrg                     DRITexOffsetStartProcPtr * texOffsetStartFunc,
224735c4bbdfSmrg                     DRITexOffsetFinishProcPtr * texOffsetFinishFunc)
224805b261ecSmrg{
224905b261ecSmrg    DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
225005b261ecSmrg
225135c4bbdfSmrg    if (!pDRIPriv)
225235c4bbdfSmrg        return;
225305b261ecSmrg
225435c4bbdfSmrg    *texOffsetStartFunc = pDRIPriv->pDriverInfo->texOffsetStart;
225505b261ecSmrg    *texOffsetFinishFunc = pDRIPriv->pDriverInfo->texOffsetFinish;
225605b261ecSmrg}
225705b261ecSmrg
225805b261ecSmrg/* This lets get at the unwrapped functions so that they can correctly
225905b261ecSmrg * call the lowerlevel functions, and choose whether they will be
226005b261ecSmrg * called at every level of recursion (eg in validatetree).
226105b261ecSmrg */
226205b261ecSmrgDRIWrappedFuncsRec *
226305b261ecSmrgDRIGetWrappedFuncs(ScreenPtr pScreen)
226405b261ecSmrg{
226505b261ecSmrg    return &(DRI_SCREEN_PRIV(pScreen)->wrap);
226605b261ecSmrg}
226705b261ecSmrg
226805b261ecSmrg/* note that this returns the library version, not the protocol version */
226905b261ecSmrgvoid
227035c4bbdfSmrgDRIQueryVersion(int *majorVersion, int *minorVersion, int *patchVersion)
227105b261ecSmrg{
227205b261ecSmrg    *majorVersion = DRIINFO_MAJOR_VERSION;
227305b261ecSmrg    *minorVersion = DRIINFO_MINOR_VERSION;
227405b261ecSmrg    *patchVersion = DRIINFO_PATCH_VERSION;
227505b261ecSmrg}
227605b261ecSmrg
227705b261ecSmrgstatic void
227805b261ecSmrg_DRIAdjustFrame(ScrnInfoPtr pScrn, DRIScreenPrivPtr pDRIPriv, int x, int y)
227905b261ecSmrg{
228035c4bbdfSmrg    pDRIPriv->pSAREA->frame.x = x;
228135c4bbdfSmrg    pDRIPriv->pSAREA->frame.y = y;
228235c4bbdfSmrg    pDRIPriv->pSAREA->frame.width = pScrn->frameX1 - x + 1;
228305b261ecSmrg    pDRIPriv->pSAREA->frame.height = pScrn->frameY1 - y + 1;
228405b261ecSmrg}
228505b261ecSmrg
228605b261ecSmrgvoid
228735c4bbdfSmrgDRIAdjustFrame(ScrnInfoPtr pScrn, int x, int y)
228805b261ecSmrg{
228935c4bbdfSmrg    ScreenPtr pScreen = xf86ScrnToScreen(pScrn);
229005b261ecSmrg    DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
229135c4bbdfSmrg    int px, py;
229205b261ecSmrg
229305b261ecSmrg    if (!pDRIPriv || !pDRIPriv->pSAREA) {
229435c4bbdfSmrg        DRIDrvMsg(pScrn->scrnIndex, X_ERROR, "[DRI] No SAREA (%p %p)\n",
229535c4bbdfSmrg                  pDRIPriv, pDRIPriv ? pDRIPriv->pSAREA : NULL);
229635c4bbdfSmrg        return;
229705b261ecSmrg    }
229805b261ecSmrg
229905b261ecSmrg    if (pDRIPriv->fullscreen) {
230035c4bbdfSmrg        /* Fix up frame */
230135c4bbdfSmrg        pScrn->frameX0 = pDRIPriv->pSAREA->frame.x;
230235c4bbdfSmrg        pScrn->frameY0 = pDRIPriv->pSAREA->frame.y;
230335c4bbdfSmrg        pScrn->frameX1 = pScrn->frameX0 + pDRIPriv->pSAREA->frame.width - 1;
230435c4bbdfSmrg        pScrn->frameY1 = pScrn->frameY0 + pDRIPriv->pSAREA->frame.height - 1;
230535c4bbdfSmrg
230635c4bbdfSmrg        /* Fix up cursor */
230735c4bbdfSmrg        miPointerGetPosition(inputInfo.pointer, &px, &py);
230835c4bbdfSmrg
230935c4bbdfSmrg        if (px < pScrn->frameX0)
231035c4bbdfSmrg            px = pScrn->frameX0;
231135c4bbdfSmrg        if (px > pScrn->frameX1)
231235c4bbdfSmrg            px = pScrn->frameX1;
231335c4bbdfSmrg        if (py < pScrn->frameY0)
231435c4bbdfSmrg            py = pScrn->frameY0;
231535c4bbdfSmrg        if (py > pScrn->frameY1)
231635c4bbdfSmrg            py = pScrn->frameY1;
231735c4bbdfSmrg        pScreen->SetCursorPosition(inputInfo.pointer, pScreen, px, py, TRUE);
231835c4bbdfSmrg
231935c4bbdfSmrg        return;
232005b261ecSmrg    }
232105b261ecSmrg
232205b261ecSmrg    if (pDRIPriv->wrap.AdjustFrame) {
232335c4bbdfSmrg        /* unwrap */
232435c4bbdfSmrg        pScrn->AdjustFrame = pDRIPriv->wrap.AdjustFrame;
232535c4bbdfSmrg        /* call lower layers */
232635c4bbdfSmrg        (*pScrn->AdjustFrame) (pScrn, x, y);
232735c4bbdfSmrg        /* rewrap */
232835c4bbdfSmrg        pDRIPriv->wrap.AdjustFrame = pScrn->AdjustFrame;
232935c4bbdfSmrg        pScrn->AdjustFrame = DRIAdjustFrame;
233005b261ecSmrg    }
233105b261ecSmrg
233205b261ecSmrg    _DRIAdjustFrame(pScrn, pDRIPriv, x, y);
233305b261ecSmrg}
233405b261ecSmrg
233535c4bbdfSmrg/*
233605b261ecSmrg * DRIMoveBuffersHelper swaps the regions rects in place leaving you
233705b261ecSmrg * a region with the rects in the order that you need to blit them,
233805b261ecSmrg * but it is possibly (likely) an invalid region afterwards.  If you
233935c4bbdfSmrg * need to use the region again for anything you have to call
234005b261ecSmrg * REGION_VALIDATE on it, or better yet, save a copy first.
234105b261ecSmrg */
234205b261ecSmrg
234305b261ecSmrgvoid
234435c4bbdfSmrgDRIMoveBuffersHelper(ScreenPtr pScreen,
234535c4bbdfSmrg                     int dx, int dy, int *xdir, int *ydir, RegionPtr reg)
234635c4bbdfSmrg{
234735c4bbdfSmrg    BoxPtr extents, pbox, firstBox, lastBox;
234835c4bbdfSmrg    BoxRec tmpBox;
234935c4bbdfSmrg    int y, nbox;
235035c4bbdfSmrg
235135c4bbdfSmrg    extents = RegionExtents(reg);
235235c4bbdfSmrg    nbox = RegionNumRects(reg);
235335c4bbdfSmrg    pbox = RegionRects(reg);
235435c4bbdfSmrg
235535c4bbdfSmrg    if ((dy > 0) && (dy < (extents->y2 - extents->y1))) {
235635c4bbdfSmrg        *ydir = -1;
235735c4bbdfSmrg        if (nbox > 1) {
235835c4bbdfSmrg            firstBox = pbox;
235935c4bbdfSmrg            lastBox = pbox + nbox - 1;
236035c4bbdfSmrg            while ((unsigned long) firstBox < (unsigned long) lastBox) {
236135c4bbdfSmrg                tmpBox = *firstBox;
236235c4bbdfSmrg                *firstBox = *lastBox;
236335c4bbdfSmrg                *lastBox = tmpBox;
236435c4bbdfSmrg                firstBox++;
236535c4bbdfSmrg                lastBox--;
236635c4bbdfSmrg            }
236705b261ecSmrg        }
236835c4bbdfSmrg    }
236935c4bbdfSmrg    else
237035c4bbdfSmrg        *ydir = 1;
237135c4bbdfSmrg
237235c4bbdfSmrg    if ((dx > 0) && (dx < (extents->x2 - extents->x1))) {
237335c4bbdfSmrg        *xdir = -1;
237435c4bbdfSmrg        if (nbox > 1) {
237535c4bbdfSmrg            firstBox = lastBox = pbox;
237635c4bbdfSmrg            y = pbox->y1;
237735c4bbdfSmrg            while (--nbox) {
237835c4bbdfSmrg                pbox++;
237935c4bbdfSmrg                if (pbox->y1 == y)
238035c4bbdfSmrg                    lastBox++;
238135c4bbdfSmrg                else {
238235c4bbdfSmrg                    while ((unsigned long) firstBox < (unsigned long) lastBox) {
238335c4bbdfSmrg                        tmpBox = *firstBox;
238435c4bbdfSmrg                        *firstBox = *lastBox;
238535c4bbdfSmrg                        *lastBox = tmpBox;
238635c4bbdfSmrg                        firstBox++;
238735c4bbdfSmrg                        lastBox--;
238835c4bbdfSmrg                    }
238935c4bbdfSmrg
239035c4bbdfSmrg                    firstBox = lastBox = pbox;
239135c4bbdfSmrg                    y = pbox->y1;
239235c4bbdfSmrg                }
239335c4bbdfSmrg            }
239435c4bbdfSmrg            while ((unsigned long) firstBox < (unsigned long) lastBox) {
239535c4bbdfSmrg                tmpBox = *firstBox;
239635c4bbdfSmrg                *firstBox = *lastBox;
239735c4bbdfSmrg                *lastBox = tmpBox;
239835c4bbdfSmrg                firstBox++;
239935c4bbdfSmrg                lastBox--;
240035c4bbdfSmrg            }
240105b261ecSmrg        }
240235c4bbdfSmrg    }
240335c4bbdfSmrg    else
240435c4bbdfSmrg        *xdir = 1;
240505b261ecSmrg
240605b261ecSmrg}
2407