[RFC] libdri changes for single-entity multi-screen DRI.

Alex Deucher alexdeucher at gmail.com
Wed Apr 4 07:16:06 PDT 2007


On 4/4/07, Thomas Hellström <thomas at tungstengraphics.com> wrote:
> Hi!
>
> I'd like to commit the attached patch before the xserver-1.3 release.
> It may break DRI drivers that depend on DRM lastclose to do their
> cleanup, so it would be good to have some feedback
> on this.
>

Add your patch or commit to the 1.3 page so it can be considered for inclusion.
http://wiki.x.org/wiki/Server13Branch

Alex

> /Thomas
>
>
> >From 6c5b2664c9f26833d4d5543ff59dfe1c697b2d64 Mon Sep 17 00:00:00 2001
> From: Thomas Hellstrom <thomas-at-tungstengraphics-dot-com>
> Date: Wed, 4 Apr 2007 13:52:18 +0200
> Subject: [PATCH] Changes for single-entity-multi-screen DRI.
> The entity has a screen-common SAREA that contains the hardware lock.
> In addition, each screen creates a new sarea, but screen 0 has the
> option to reuse the entity sarea. This is the default and should make the
> change backwards compatible.
>
> The master DRI file descriptor will be common for all screens and will not
> be closed between server generations.
>
> DRI drivers that depend on DRM to do cleanup in "lastclose" between
> server generations will not work as intended.
>
> The DRI fd will only be closed when the X server exits.
> Signed-off-by: Thomas Hellstrom <thomas-at-tungstengraphics-dot-com>
> ---
>  hw/xfree86/dri/dri.c       |  494 +++++++++++++++++++++++++++++---------------
>  hw/xfree86/dri/dri.h       |    9 +
>  hw/xfree86/dri/dristruct.h |   28 ++
>  hw/xfree86/dri/sarea.h     |   12 +
>  4 files changed, 370 insertions(+), 173 deletions(-)
>
> diff --git a/hw/xfree86/dri/dri.c b/hw/xfree86/dri/dri.c
> index 7bd07c0..25a9492 100644
> --- a/hw/xfree86/dri/dri.c
> +++ b/hw/xfree86/dri/dri.c
> @@ -43,6 +43,7 @@ #include <unistd.h>
>  #include <string.h>
>  #include <stdio.h>
>  #include <sys/ioctl.h>
> +#include <errno.h>
>
>  #define NEED_REPLIES
>  #define NEED_EVENTS
> @@ -77,6 +78,7 @@ #if !defined(PANORAMIX)
>  extern Bool noPanoramiXExtension;
>  #endif
>
> +static int DRIEntPrivIndex = -1;
>  static int DRIScreenPrivIndex = -1;
>  static int DRIWindowPrivIndex = -1;
>  static unsigned long DRIGeneration = 0;
> @@ -112,18 +114,200 @@ DRIDrvMsg(int scrnIndex, MessageType typ
>  }
>
>
> +static void
> +DRIOpenDRMCleanup(DRIEntPrivPtr pDRIEntPriv)
> +{
> +    if (pDRIEntPriv->pLSAREA != NULL) {
> +       drmUnmap(pDRIEntPriv->pLSAREA, pDRIEntPriv->sAreaSize);
> +       pDRIEntPriv->pLSAREA = NULL;
> +    }
> +    if (pDRIEntPriv->hLSAREA != 0) {
> +       drmRmMap(pDRIEntPriv->drmFD, pDRIEntPriv->hLSAREA);
> +    }
> +    if (pDRIEntPriv->drmFD >= 0) {
> +       drmClose(pDRIEntPriv->drmFD);
> +       pDRIEntPriv->drmFD = 0;
> +    }
> +}
> +
> +int
> +DRIMasterFD(ScrnInfoPtr pScrn)
> +{
> +    return DRI_ENT_PRIV(pScrn)->drmFD;
> +}
> +
> +XF86DRILSAREAPtr
> +DRIMasterSareaPointer(ScrnInfoPtr pScrn)
> +{
> +    return DRI_ENT_PRIV(pScrn)->pLSAREA;
> +}
> +
> +drm_handle_t
> +DRIMasterSareaHandle(ScrnInfoPtr pScrn)
> +{
> +    return DRI_ENT_PRIV(pScrn)->hLSAREA;
> +}
> +
> +
> +Bool
> +DRIOpenDRMMaster(ScrnInfoPtr pScrn,
> +                unsigned long sAreaSize,
> +                const char *busID,
> +                const char *drmDriverName)
> +{
> +    drmSetVersion saveSv, sv;
> +    Bool drmWasAvailable;
> +    DRIEntPrivPtr pDRIEntPriv;
> +    DRIEntPrivRec tmp;
> +    drmVersionPtr drmlibv;
> +    int drmlibmajor, drmlibminor;
> +    const char *openBusID;
> +    int count;
> +    int err;
> +
> +    if (DRIEntPrivIndex == -1)
> +       DRIEntPrivIndex = xf86AllocateEntityPrivateIndex();
> +
> +    pDRIEntPriv = DRI_ENT_PRIV(pScrn);
> +    if (pDRIEntPriv)
> +       return TRUE;
> +
> +    drmWasAvailable = drmAvailable();
> +
> +    memset(&tmp, 0, sizeof(tmp));
> +
> +    /* Check the DRM lib version.
> +     * drmGetLibVersion was not supported in version 1.0, so check for
> +     * symbol first to avoid possible crash or hang.
> +     */
> +
> +    drmlibmajor = 1;
> +    drmlibminor = 0;
> +    if (xf86LoaderCheckSymbol("drmGetLibVersion")) {
> +       drmlibv = drmGetLibVersion(-1);
> +       if (drmlibv != NULL) {
> +           drmlibmajor = drmlibv->version_major;
> +           drmlibminor = drmlibv->version_minor;
> +           drmFreeVersion(drmlibv);
> +       }
> +    }
> +
> +    /* Check if the libdrm can handle falling back to loading based on name
> +     * if a busid string is passed.
> +     */
> +    openBusID = (drmlibmajor == 1 && drmlibminor >= 2) ? busID : NULL;
> +
> +    tmp.drmFD = -1;
> +    sv.drm_di_major = 1;
> +    sv.drm_di_minor = 1;
> +    sv.drm_dd_major = -1;
> +
> +    saveSv = sv;
> +    count = 10;
> +    while (count--) {
> +       tmp.drmFD = drmOpen(drmDriverName, openBusID);
> +
> +       if (tmp.drmFD < 0) {
> +           DRIDrvMsg(-1, X_ERROR, "[drm] drmOpen failed.\n");
> +           goto out_err;
> +       }
> +
> +       err = drmSetInterfaceVersion(tmp.drmFD, &sv);
> +
> +       if (err != -EPERM)
> +           break;
> +
> +       sv = saveSv;
> +       drmClose(tmp.drmFD);
> +       tmp.drmFD = -1;
> +       usleep(100000);
> +    }
> +
> +    if (tmp.drmFD <= 0) {
> +       DRIDrvMsg(-1, X_ERROR, "[drm] DRM was busy with another master.\n");
> +       goto out_err;
> +    }
> +
> +    if (!drmWasAvailable) {
> +       DRIDrvMsg(-1, X_INFO,
> +                 "[drm] loaded kernel module for \"%s\" driver.\n",
> +                 drmDriverName);
> +    }
> +
> +    if (err != 0) {
> +       sv.drm_di_major = 1;
> +       sv.drm_di_minor = 0;
> +    }
> +
> +    DRIDrvMsg(-1, X_INFO, "[drm] DRM interface version %d.%d\n",
> +             sv.drm_di_major, sv.drm_di_minor);
> +
> +    if (sv.drm_di_major == 1 && sv.drm_di_minor >= 1)
> +       err = 0;
> +    else
> +       err = drmSetBusid(tmp.drmFD, busID);
> +
> +    if (err) {
> +       DRIDrvMsg(-1, X_ERROR, "[drm] Could not set DRM device bus ID.\n");
> +       goto out_err;
> +    }
> +
> +    /*
> +     * Create a lock-containing sarea.
> +     */
> +
> +    if (drmAddMap( tmp.drmFD, 0, sAreaSize, DRM_SHM,
> +                  DRM_CONTAINS_LOCK, &tmp.hLSAREA) < 0) {
> +        DRIDrvMsg(-1, X_INFO, "[drm] Could not create SAREA for DRM lock.\n");
> +       tmp.hLSAREA = 0;
> +       goto out_err;
> +    }
> +
> +    if (drmMap( tmp.drmFD, tmp.hLSAREA, sAreaSize,
> +               (drmAddressPtr)(&tmp.pLSAREA)) < 0) {
> +        DRIDrvMsg(-1, X_INFO, "[drm] Mapping SAREA for DRM lock failed.\n");
> +       tmp.pLSAREA = NULL;
> +       goto out_err;
> +    }
> +
> +    memset(tmp.pLSAREA, 0, sAreaSize);
> +
> +    /*
> +     * Reserved contexts are handled by the first opened screen.
> +     */
> +
> +    tmp.resOwner = NULL;
> +
> +    pDRIEntPriv = xnfcalloc(sizeof(*pDRIEntPriv), 1);
> +    if (!pDRIEntPriv) {
> +        DRIDrvMsg(-1, X_INFO, "[drm] Failed to allocate memory for "
> +                 "DRM device.\n");
> +       goto out_err;
> +    }
> +    *pDRIEntPriv = tmp;
> +    xf86GetEntityPrivate((pScrn)->entityList[0],DRIEntPrivIndex)->ptr =
> +       pDRIEntPriv;
> +
> +    DRIDrvMsg(-1, X_INFO, "[drm] DRM open master succeeded.\n");
> +    return TRUE;
> +
> +  out_err:
> +
> +    DRIOpenDRMCleanup(&tmp);
> +    return FALSE;
> +}
> +
> +
>  Bool
>  DRIScreenInit(ScreenPtr pScreen, DRIInfoPtr pDRIInfo, int *pDRMFD)
>  {
>      DRIScreenPrivPtr    pDRIPriv;
>      drm_context_t *       reserved;
>      int                 reserved_count;
> -    int                 i, fd, drmWasAvailable;
> +    int                 i;
>      Bool                xineramaInCore = FALSE;
> -    int                 err = 0;
> -    char                *openbusid;
> -    drmVersionPtr       drmlibv;
> -    int                 drmlibmajor, drmlibminor, drmdimajor, drmdiminor;
> +    DRIEntPrivPtr       pDRIEntPriv;
> +    ScrnInfoPtr         pScrn = xf86Screens[pScreen->myNum];
>
>      if (DRIGeneration != serverGeneration) {
>         if ((DRIScreenPrivIndex = AllocateScreenPrivateIndex()) < 0)
> @@ -153,47 +337,12 @@ DRIScreenInit(ScreenPtr pScreen, DRIInfo
>         }
>      }
>
> -    drmWasAvailable = drmAvailable();
> -
> -    /* Check the DRM lib version.
> -     * drmGetLibVersion was not supported in version 1.0, so check for
> -     * symbol first to avoid possible crash or hang.
> -     */
> -    drmlibmajor = 1;
> -    drmlibminor = 0;
> -    if (xf86LoaderCheckSymbol("drmGetLibVersion")) {
> -       drmlibv = drmGetLibVersion(-1);
> -       if (drmlibv != NULL) {
> -           drmlibmajor = drmlibv->version_major;
> -           drmlibminor = drmlibv->version_minor;
> -           drmFreeVersion(drmlibv);
> -       }
> -    }
> -
> -    /* Check if the libdrm can handle falling back to loading based on name
> -     * if a busid string is passed.
> -     */
> -    if (drmlibmajor == 1 && drmlibminor >= 2)
> -       openbusid = pDRIInfo->busIdString;
> -    else
> -       openbusid = NULL;
> +    if (!DRIOpenDRMMaster(pScrn, pDRIInfo->SAREASize,
> +                         pDRIInfo->busIdString,
> +                         pDRIInfo->drmDriverName))
> +       return FALSE;
>
> -    /* Note that drmOpen will try to load the kernel module, if needed. */
> -    fd = drmOpen(pDRIInfo->drmDriverName, openbusid);
> -    if (fd < 0) {
> -        /* failed to open DRM */
> -        pScreen->devPrivates[DRIScreenPrivIndex].ptr = NULL;
> -        DRIDrvMsg(pScreen->myNum, X_INFO,
> -                  "[drm] drmOpen failed\n");
> -        return FALSE;
> -    }
> -
> -    if (!drmWasAvailable) {
> -       /* drmOpen loaded the kernel module, print a message to say so */
> -       DRIDrvMsg(pScreen->myNum, X_INFO,
> -                 "[drm] loaded kernel module for \"%s\" driver\n",
> -                 pDRIInfo->drmDriverName);
> -    }
> +    pDRIEntPriv = DRI_ENT_PRIV(pScrn);
>
>      pDRIPriv = (DRIScreenPrivPtr) xcalloc(1, sizeof(DRIScreenPrivRec));
>      if (!pDRIPriv) {
> @@ -202,7 +351,7 @@ DRIScreenInit(ScreenPtr pScreen, DRIInfo
>      }
>
>      pScreen->devPrivates[DRIScreenPrivIndex].ptr = (pointer) pDRIPriv;
> -    pDRIPriv->drmFD = fd;
> +    pDRIPriv->drmFD = pDRIEntPriv->drmFD;
>      pDRIPriv->directRenderingSupport = TRUE;
>      pDRIPriv->pDriverInfo = pDRIInfo;
>      pDRIPriv->nrWindows = 0;
> @@ -214,89 +363,54 @@ DRIScreenInit(ScreenPtr pScreen, DRIInfo
>
>      pDRIPriv->grabbedDRILock = FALSE;
>      pDRIPriv->drmSIGIOHandlerInstalled = FALSE;
> -
> -    if (drmlibmajor == 1 && drmlibminor >= 2) {
> -       drmSetVersion sv;
> -
> -       /* Get the interface version, asking for 1.1. */
> -       sv.drm_di_major = 1;
> -       sv.drm_di_minor = 1;
> -       sv.drm_dd_major = -1;
> -       err = drmSetInterfaceVersion(pDRIPriv->drmFD, &sv);
> -       if (err == 0) {
> -           drmdimajor = sv.drm_di_major;
> -           drmdiminor = sv.drm_di_minor;
> -       } else {
> -           /* failure, so set it to 1.0.0. */
> -           drmdimajor = 1;
> -           drmdiminor = 0;
> -       }
> -    }
> -    else {
> -       /* We can't check the DI DRM interface version, so set it to 1.0.0. */
> -       drmdimajor = 1;
> -       drmdiminor = 0;
> -    }
> -    DRIDrvMsg(pScreen->myNum, X_INFO,
> -              "[drm] DRM interface version %d.%d\n", drmdimajor, drmdiminor);
> -
> -    /* If the interface minor number is 1.1, then we've opened a DRM device
> -     * that already had the busid set through drmOpen.
> -     */
> -    if (drmdimajor == 1 && drmdiminor >= 1)
> -       err = 0;
> -    else
> -       err = drmSetBusid(pDRIPriv->drmFD, pDRIPriv->pDriverInfo->busIdString);
> -
> -    if (err < 0) {
> -       pDRIPriv->directRenderingSupport = FALSE;
> -       pScreen->devPrivates[DRIScreenPrivIndex].ptr = NULL;
> -       drmClose(pDRIPriv->drmFD);
> -        DRIDrvMsg(pScreen->myNum, X_INFO,
> -                  "[drm] drmSetBusid failed (%d, %s), %s\n",
> -                  pDRIPriv->drmFD, pDRIPriv->pDriverInfo->busIdString, strerror(-err));
> -       return FALSE;
> -    }
> -
>      *pDRMFD = pDRIPriv->drmFD;
> -    DRIDrvMsg(pScreen->myNum, X_INFO,
> -             "[drm] created \"%s\" driver at busid \"%s\"\n",
> -             pDRIPriv->pDriverInfo->drmDriverName,
> -             pDRIPriv->pDriverInfo->busIdString);
>
> -    if (drmAddMap( pDRIPriv->drmFD,
> -                  0,
> -                  pDRIPriv->pDriverInfo->SAREASize,
> -                  DRM_SHM,
> -                  DRM_CONTAINS_LOCK,
> -                  &pDRIPriv->hSAREA) < 0)
> -    {
> -       pDRIPriv->directRenderingSupport = FALSE;
> -       pScreen->devPrivates[DRIScreenPrivIndex].ptr = NULL;
> -       drmClose(pDRIPriv->drmFD);
> -        DRIDrvMsg(pScreen->myNum, X_INFO,
> -                  "[drm] drmAddMap failed\n");
> -       return FALSE;
> +    if (pDRIEntPriv->sAreaGrabbed || pDRIInfo->allocSarea) {
> +
> +       if (drmAddMap( pDRIPriv->drmFD,
> +                      0,
> +                      pDRIPriv->pDriverInfo->SAREASize,
> +                      DRM_SHM,
> +                      0,
> +                      &pDRIPriv->hSAREA) < 0)
> +       {
> +           pDRIPriv->directRenderingSupport = FALSE;
> +           pScreen->devPrivates[DRIScreenPrivIndex].ptr = NULL;
> +           drmClose(pDRIPriv->drmFD);
> +           DRIDrvMsg(pScreen->myNum, X_INFO,
> +                     "[drm] drmAddMap failed\n");
> +           return FALSE;
> +       }
> +       DRIDrvMsg(pScreen->myNum, X_INFO,
> +                 "[drm] added %d byte SAREA at %p\n",
> +                 pDRIPriv->pDriverInfo->SAREASize, pDRIPriv->hSAREA);
> +
> +       /* Backwards compat. */
> +       if (drmMap( pDRIPriv->drmFD,
> +                   pDRIPriv->hSAREA,
> +                   pDRIPriv->pDriverInfo->SAREASize,
> +                   (drmAddressPtr)(&pDRIPriv->pSAREA)) < 0)
> +       {
> +           pDRIPriv->directRenderingSupport = FALSE;
> +           pScreen->devPrivates[DRIScreenPrivIndex].ptr = NULL;
> +           drmClose(pDRIPriv->drmFD);
> +           DRIDrvMsg(pScreen->myNum, X_INFO,
> +                     "[drm] drmMap failed\n");
> +           return FALSE;
> +       }
> +       DRIDrvMsg(pScreen->myNum, X_INFO, "[drm] mapped SAREA %p to %p\n",
> +                 pDRIPriv->hSAREA, pDRIPriv->pSAREA);
> +       memset(pDRIPriv->pSAREA, 0, pDRIPriv->pDriverInfo->SAREASize);
> +    } else {
> +       DRIDrvMsg(pScreen->myNum, X_INFO, "[drm] Using the DRM lock "
> +                 "SAREA also for drawables.\n");
> +       pDRIPriv->hSAREA = pDRIEntPriv->hLSAREA;
> +       pDRIPriv->pSAREA = (XF86DRISAREAPtr) pDRIEntPriv->pLSAREA;
> +       pDRIEntPriv->sAreaGrabbed = TRUE;
>      }
> -    DRIDrvMsg(pScreen->myNum, X_INFO,
> -             "[drm] added %d byte SAREA at %p\n",
> -             pDRIPriv->pDriverInfo->SAREASize, pDRIPriv->hSAREA);
>
> -    if (drmMap( pDRIPriv->drmFD,
> -               pDRIPriv->hSAREA,
> -               pDRIPriv->pDriverInfo->SAREASize,
> -               (drmAddressPtr)(&pDRIPriv->pSAREA)) < 0)
> -    {
> -       pDRIPriv->directRenderingSupport = FALSE;
> -       pScreen->devPrivates[DRIScreenPrivIndex].ptr = NULL;
> -       drmClose(pDRIPriv->drmFD);
> -        DRIDrvMsg(pScreen->myNum, X_INFO,
> -                  "[drm] drmMap failed\n");
> -       return FALSE;
> -    }
> -    memset(pDRIPriv->pSAREA, 0, pDRIPriv->pDriverInfo->SAREASize);
> -    DRIDrvMsg(pScreen->myNum, X_INFO, "[drm] mapped SAREA %p to %p\n",
> -             pDRIPriv->hSAREA, pDRIPriv->pSAREA);
> +    pDRIPriv->hLSAREA = pDRIEntPriv->hLSAREA;
> +    pDRIPriv->pLSAREA = pDRIEntPriv->pLSAREA;
>
>      if (drmAddMap( pDRIPriv->drmFD,
>                    (drm_handle_t)pDRIPriv->pDriverInfo->frameBufferPhysicalAddress,
> @@ -316,22 +430,26 @@ DRIScreenInit(ScreenPtr pScreen, DRIInfo
>      DRIDrvMsg(pScreen->myNum, X_INFO, "[drm] framebuffer handle = %p\n",
>               pDRIPriv->hFrameBuffer);
>
> -                               /* Add tags for reserved contexts */
> -    if ((reserved = drmGetReservedContextList(pDRIPriv->drmFD,
> -                                             &reserved_count))) {
> -       int  i;
> -       void *tag;
> -
> -       for (i = 0; i < reserved_count; i++) {
> -           tag = DRICreateContextPrivFromHandle(pScreen,
> -                                                reserved[i],
> -                                                DRI_CONTEXT_RESERVED);
> -           drmAddContextTag(pDRIPriv->drmFD, reserved[i], tag);
> +    if (pDRIEntPriv->resOwner == NULL) {
> +       pDRIEntPriv->resOwner = pScreen;
> +
> +       /* Add tags for reserved contexts */
> +       if ((reserved = drmGetReservedContextList(pDRIPriv->drmFD,
> +                                                 &reserved_count))) {
> +           int  i;
> +           void *tag;
> +
> +           for (i = 0; i < reserved_count; i++) {
> +               tag = DRICreateContextPrivFromHandle(pScreen,
> +                                                    reserved[i],
> +                                                    DRI_CONTEXT_RESERVED);
> +               drmAddContextTag(pDRIPriv->drmFD, reserved[i], tag);
> +           }
> +           drmFreeReservedContextList(reserved);
> +           DRIDrvMsg(pScreen->myNum, X_INFO,
> +                     "[drm] added %d reserved context%s for kernel\n",
> +                     reserved_count, reserved_count > 1 ? "s" : "");
>         }
> -       drmFreeReservedContextList(reserved);
> -       DRIDrvMsg(pScreen->myNum, X_INFO,
> -                 "[drm] added %d reserved context%s for kernel\n",
> -                 reserved_count, reserved_count > 1 ? "s" : "");
>      }
>
>      /* validate max drawable table entry set by driver */
> @@ -349,6 +467,9 @@ DRIScreenInit(ScreenPtr pScreen, DRIInfo
>         pDRIPriv->pSAREA->drawableTable[i].flags = 0;
>      }
>
> +    pDRIPriv->pLockRefCount = &pDRIEntPriv->lockRefCount;
> +    pDRIPriv->pLockingContext = &pDRIEntPriv->lockingContext;
> +
>      return TRUE;
>  }
>
> @@ -490,6 +611,8 @@ DRICloseScreen(ScreenPtr pScreen)
>      DRIInfoPtr       pDRIInfo;
>      drm_context_t *    reserved;
>      int              reserved_count;
> +    ScrnInfoPtr      pScrn = xf86Screens[pScreen->myNum];
> +    DRIEntPrivPtr    pDRIEntPriv = DRI_ENT_PRIV(pScrn);
>
>      if (pDRIPriv && pDRIPriv->directRenderingSupport) {
>
> @@ -542,38 +665,47 @@ DRICloseScreen(ScreenPtr pScreen)
>         }
>
>                                 /* Remove tags for reserved contexts */
> -       if ((reserved = drmGetReservedContextList(pDRIPriv->drmFD,
> +       if (pDRIEntPriv->resOwner == pScreen) {
> +           pDRIEntPriv->resOwner = NULL;
> +
> +           if ((reserved = drmGetReservedContextList(pDRIPriv->drmFD,
>                                                   &reserved_count))) {
> -           int  i;
> +               int  i;
>
> -           for (i = 0; i < reserved_count; i++) {
> -               DRIDestroyContextPriv(drmGetContextTag(pDRIPriv->drmFD,
> -                                                      reserved[i]));
> +               for (i = 0; i < reserved_count; i++) {
> +                   DRIDestroyContextPriv(drmGetContextTag(pDRIPriv->drmFD,
> +                                                          reserved[i]));
> +               }
> +               drmFreeReservedContextList(reserved);
> +               DRIDrvMsg(pScreen->myNum, X_INFO,
> +                         "[drm] removed %d reserved context%s for kernel\n",
> +                         reserved_count, reserved_count > 1 ? "s" : "");
>             }
> -           drmFreeReservedContextList(reserved);
> -           DRIDrvMsg(pScreen->myNum, X_INFO,
> -                     "[drm] removed %d reserved context%s for kernel\n",
> -                     reserved_count, reserved_count > 1 ? "s" : "");
>         }
>
>         /* Make sure signals get unblocked etc. */
>         drmUnlock(pDRIPriv->drmFD, pDRIPriv->myContext);
> -       pDRIPriv->lockRefCount = 0;
> -       DRIDrvMsg(pScreen->myNum, X_INFO,
> -                 "[drm] unmapping %d bytes of SAREA %p at %p\n",
> -                 pDRIInfo->SAREASize,
> -                 pDRIPriv->hSAREA,
> -                 pDRIPriv->pSAREA);
> -       if (drmUnmap(pDRIPriv->pSAREA, pDRIInfo->SAREASize)) {
> -           DRIDrvMsg(pScreen->myNum, X_ERROR,
> -                     "[drm] unable to unmap %d bytes"
> -                     " of SAREA %p at %p\n",
> +       pDRIPriv->pLockRefCount = NULL;
> +       if (pDRIPriv->hSAREA != pDRIEntPriv->hLSAREA) {
> +           DRIDrvMsg(pScreen->myNum, X_INFO,
> +                     "[drm] unmapping %d bytes of SAREA %p at %p\n",
>                       pDRIInfo->SAREASize,
>                       pDRIPriv->hSAREA,
>                       pDRIPriv->pSAREA);
> +           if (drmUnmap(pDRIPriv->pSAREA, pDRIInfo->SAREASize)) {
> +               DRIDrvMsg(pScreen->myNum, X_ERROR,
> +                         "[drm] unable to unmap %d bytes"
> +                         " of SAREA %p at %p\n",
> +                         pDRIInfo->SAREASize,
> +                         pDRIPriv->hSAREA,
> +                         pDRIPriv->pSAREA);
> +           }
> +       } else {
> +           pDRIEntPriv->sAreaGrabbed = FALSE;
>         }
>
> -       drmClose(pDRIPriv->drmFD);
> +       if (pDRIEntPriv->drmFD != pDRIPriv->drmFD)
> +           drmClose(pDRIPriv->drmFD);
>
>         xfree(pDRIPriv);
>         pScreen->devPrivates[DRIScreenPrivIndex].ptr = NULL;
> @@ -2001,28 +2133,46 @@ void
>  DRILock(ScreenPtr pScreen, int flags)
>  {
>      DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
> -    if(!pDRIPriv) return;
>
> -    if (!pDRIPriv->lockRefCount)
> -        DRM_LOCK(pDRIPriv->drmFD, pDRIPriv->pSAREA, pDRIPriv->myContext, flags);
> -    pDRIPriv->lockRefCount++;
> +    if(!pDRIPriv || !pDRIPriv->pLockRefCount) return;
> +
> +    if (!*pDRIPriv->pLockRefCount) {
> +        DRM_LOCK(pDRIPriv->drmFD, pDRIPriv->pLSAREA, pDRIPriv->myContext, flags);
> +       *pDRIPriv->pLockingContext = pDRIPriv->myContext;
> +    } else if (*pDRIPriv->pLockingContext != pDRIPriv->myContext) {
> +       DRIDrvMsg(pScreen->myNum, X_ERROR,
> +                 "[DRI] Locking deadlock.\n"
> +                 "\tAlready locked with context %d,\n"
> +                 "\ttrying to lock with context %d.\n",
> +                 pDRIPriv->pLockingContext,
> +                 pDRIPriv->myContext);
> +    }
> +    (*pDRIPriv->pLockRefCount)++;
>  }
>
>  void
>  DRIUnlock(ScreenPtr pScreen)
>  {
>      DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
> -    if(!pDRIPriv) return;
>
> -    if (pDRIPriv->lockRefCount > 0) {
> -        pDRIPriv->lockRefCount--;
> -    }
> -    else {
> -        ErrorF("DRIUnlock called when not locked\n");
> +    if(!pDRIPriv || !pDRIPriv->pLockRefCount) return;
> +
> +    if (*pDRIPriv->pLockRefCount > 0) {
> +       if (pDRIPriv->myContext != *pDRIPriv->pLockingContext) {
> +           DRIDrvMsg(pScreen->myNum, X_ERROR,
> +                     "[DRI] Unlocking inconsistency:\n"
> +                     "\tContext %d trying to unlock lock held by context %d\n",
> +                     pDRIPriv->pLockingContext,
> +                     pDRIPriv->myContext);
> +       }
> +       (*pDRIPriv->pLockRefCount)--;
> +    } else {
> +        DRIDrvMsg(pScreen->myNum, X_ERROR,
> +                 "DRIUnlock called when not locked.\n");
>          return;
>      }
> -    if (!pDRIPriv->lockRefCount)
> -        DRM_UNLOCK(pDRIPriv->drmFD, pDRIPriv->pSAREA, pDRIPriv->myContext);
> +    if (! *pDRIPriv->pLockRefCount)
> +        DRM_UNLOCK(pDRIPriv->drmFD, pDRIPriv->pLSAREA, pDRIPriv->myContext);
>  }
>
>  void *
> diff --git a/hw/xfree86/dri/dri.h b/hw/xfree86/dri/dri.h
> index f65c571..38a1b62 100644
> --- a/hw/xfree86/dri/dri.h
> +++ b/hw/xfree86/dri/dri.h
> @@ -107,7 +107,7 @@ typedef struct {
>   */
>
>  #define DRIINFO_MAJOR_VERSION   5
> -#define DRIINFO_MINOR_VERSION   1
> +#define DRIINFO_MINOR_VERSION   2
>  #define DRIINFO_PATCH_VERSION   0
>
>  typedef struct {
> @@ -176,9 +176,16 @@ typedef struct {
>
>      /* New with DRI version 5.1.0 */
>      void        (*ClipNotify)(ScreenPtr pScreen, WindowPtr *ppWin, int num);
> +
> +    /* New with DRI version 5.2.0 */
> +    Bool                allocSarea;
>  } DRIInfoRec, *DRIInfoPtr;
>
>
> +extern Bool DRIOpenDRMMaster(ScrnInfoPtr pScrn, unsigned long sAreaSize,
> +                            const char *busID,
> +                            const char *drmDriverName);
> +
>  extern Bool DRIScreenInit(ScreenPtr pScreen,
>                            DRIInfoPtr pDRIInfo,
>                            int *pDRMFD);
> diff --git a/hw/xfree86/dri/dristruct.h b/hw/xfree86/dri/dristruct.h
> index 9c42ff9..29fe9f0 100644
> --- a/hw/xfree86/dri/dristruct.h
> +++ b/hw/xfree86/dri/dristruct.h
> @@ -73,6 +73,11 @@ #define DRI_SCREEN_PRIV(pScreen) \
>  #define DRI_SCREEN_PRIV_FROM_INDEX(screenIndex) ((DRIScreenPrivPtr) \
>      (screenInfo.screens[screenIndex]->devPrivates[DRIScreenPrivIndex].ptr))
>
> +#define DRI_ENT_PRIV(pScrn)  \
> +    ((DRIEntPrivIndex < 0) ? \
> +     NULL:                  \
> +     ((DRIEntPrivPtr)(xf86GetEntityPrivate((pScrn)->entityList[0], \
> +                                          DRIEntPrivIndex)->ptr)))
>
>  typedef struct _DRIScreenPrivRec
>  {
> @@ -103,6 +108,29 @@ typedef struct _DRIScreenPrivRec
>      Bool               wrapped;
>      Bool               windowsTouched;
>      int                        lockRefCount;
> +    drm_handle_t        hLSAREA;      /* Handle to SAREA containing lock, for mapping */
> +    XF86DRILSAREAPtr    pLSAREA;      /* Mapped pointer to SAREA containing lock */
> +    int*                pLockRefCount;
> +    int*                pLockingContext;
>  } DRIScreenPrivRec, *DRIScreenPrivPtr;
>
> +
> +typedef struct _DRIEntPrivRec {
> +    int drmFD;
> +    Bool drmOpened;
> +    Bool sAreaGrabbed;
> +    drm_handle_t hLSAREA;
> +    XF86DRILSAREAPtr pLSAREA;
> +    unsigned long sAreaSize;
> +    int lockRefCount;
> +    int lockingContext;
> +    ScreenPtr resOwner;
> +} DRIEntPrivRec, *DRIEntPrivPtr;
> +
> +extern int DRIMasterFD(ScrnInfoPtr pScrn);
> +
> +extern XF86DRILSAREAPtr DRIMasterSareaPointer(ScrnInfoPtr pScrn);
> +
> +extern drm_handle_t DRIMasterSareaHandle(ScrnInfoPtr pScrn);
> +
>  #endif /* DRI_STRUCT_H */
> diff --git a/hw/xfree86/dri/sarea.h b/hw/xfree86/dri/sarea.h
> index a0d6084..996631c 100644
> --- a/hw/xfree86/dri/sarea.h
> +++ b/hw/xfree86/dri/sarea.h
> @@ -89,4 +89,16 @@ typedef struct _XF86DRISAREA {
>      drm_context_t                      dummy_context;
>  } XF86DRISAREARec, *XF86DRISAREAPtr;
>
> +typedef struct _XF86DRILSAREA  {
> +    drmLock                     lock;
> +    drmLock                     otherLocks[4096 / sizeof(drmLock) - 1];
> +} XF86DRILSAREARec, *XF86DRILSAREAPtr;
> +
> +
> +
> +
> +
> +
> +
> +
>  #endif
> --
> 1.4.1
>
>
> _______________________________________________
> xorg mailing list
> xorg at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/xorg
>



More information about the xorg mailing list