[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