summaryrefslogtreecommitdiff
path: root/hw/xfree86/dri
diff options
context:
space:
mode:
authorIan Romanick <idr@us.ibm.com>2007-06-18 16:51:13 -0700
committerIan Romanick <idr@us.ibm.com>2007-06-18 16:51:13 -0700
commitab7a6d860d4a275a810a64b1ba7b13726ed10575 (patch)
tree1198628dab08c3989dff073b4bbe6920a1feca59 /hw/xfree86/dri
parente9130b8bac73a0843d5ff6b2216eccfb3e094a48 (diff)
parent2e7fef7d0837939e822c40b6ac77e7f0e66d57bd (diff)
Merge branch 'master' of git+ssh://git.freedesktop.org/git/xorg/xserver into pci-rework
Conflicts: hw/xfree86/os-support/bus/Pci.c hw/xfree86/os-support/bus/linuxPci.c
Diffstat (limited to 'hw/xfree86/dri')
-rw-r--r--hw/xfree86/dri/dri.c554
-rw-r--r--hw/xfree86/dri/dri.h27
-rw-r--r--hw/xfree86/dri/drimodule.c2
-rw-r--r--hw/xfree86/dri/dristruct.h24
-rw-r--r--hw/xfree86/dri/sarea.h5
-rw-r--r--hw/xfree86/dri/xf86dri.c34
6 files changed, 459 insertions, 187 deletions
diff --git a/hw/xfree86/dri/dri.c b/hw/xfree86/dri/dri.c
index a9ca4cc80..12504d0d0 100644
--- a/hw/xfree86/dri/dri.c
+++ b/hw/xfree86/dri/dri.c
@@ -43,6 +43,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include <string.h>
#include <stdio.h>
#include <sys/ioctl.h>
+#include <errno.h>
#define NEED_REPLIES
#define NEED_EVENTS
@@ -77,6 +78,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
extern Bool noPanoramiXExtension;
#endif
+static int DRIEntPrivIndex = -1;
static int DRIScreenPrivIndex = -1;
static int DRIWindowPrivIndex = -1;
static unsigned long DRIGeneration = 0;
@@ -112,18 +114,203 @@ DRIDrvMsg(int scrnIndex, MessageType type, const char *format, ...)
}
+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;
+}
+
+void *
+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 && pDRIEntPriv->drmFD != -1)
+ 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;
+
+ if (!pDRIEntPriv)
+ 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 +340,12 @@ DRIScreenInit(ScreenPtr pScreen, DRIInfoPtr pDRIInfo, int *pDRMFD)
}
}
- 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;
-
- /* 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 (!DRIOpenDRMMaster(pScrn, pDRIInfo->SAREASize,
+ pDRIInfo->busIdString,
+ pDRIInfo->drmDriverName))
+ 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 +354,7 @@ DRIScreenInit(ScreenPtr pScreen, DRIInfoPtr pDRIInfo, int *pDRMFD)
}
pScreen->devPrivates[DRIScreenPrivIndex].ptr = (pointer) pDRIPriv;
- pDRIPriv->drmFD = fd;
+ pDRIPriv->drmFD = pDRIEntPriv->drmFD;
pDRIPriv->directRenderingSupport = TRUE;
pDRIPriv->pDriverInfo = pDRIInfo;
pDRIPriv->nrWindows = 0;
@@ -214,89 +366,54 @@ DRIScreenInit(ScreenPtr pScreen, DRIInfoPtr pDRIInfo, int *pDRMFD)
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 +433,26 @@ DRIScreenInit(ScreenPtr pScreen, DRIInfoPtr pDRIInfo, int *pDRMFD)
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 +470,14 @@ DRIScreenInit(ScreenPtr pScreen, DRIInfoPtr pDRIInfo, int *pDRMFD)
pDRIPriv->pSAREA->drawableTable[i].flags = 0;
}
+ pDRIPriv->pLockRefCount = &pDRIEntPriv->lockRefCount;
+ pDRIPriv->pLockingContext = &pDRIEntPriv->lockingContext;
+
+ if (!pDRIEntPriv->keepFDOpen)
+ pDRIEntPriv->keepFDOpen = pDRIInfo->keepFDOpen;
+
+ pDRIEntPriv->refCount++;
+
return TRUE;
}
@@ -490,6 +619,9 @@ DRICloseScreen(ScreenPtr pScreen)
DRIInfoPtr pDRIInfo;
drm_context_t * reserved;
int reserved_count;
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ DRIEntPrivPtr pDRIEntPriv = DRI_ENT_PRIV(pScrn);
+ Bool closeMaster;
if (pDRIPriv && pDRIPriv->directRenderingSupport) {
@@ -542,38 +674,55 @@ 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;
+ closeMaster = (--pDRIEntPriv->refCount == 0) &&
+ !pDRIEntPriv->keepFDOpen;
+ if (closeMaster || 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 (closeMaster || (pDRIEntPriv->drmFD != pDRIPriv->drmFD)) {
+ drmClose(pDRIPriv->drmFD);
+ if (pDRIEntPriv->drmFD == pDRIPriv->drmFD) {
+ DRIDrvMsg(pScreen->myNum, X_INFO,
+ "[drm] Closed DRM master.\n");
+ pDRIEntPriv->drmFD = -1;
+ }
+ }
xfree(pDRIPriv);
pScreen->devPrivates[DRIScreenPrivIndex].ptr = NULL;
@@ -1369,13 +1518,18 @@ DRIGetDrawableInfo(ScreenPtr pScreen,
if (x1 > pScreen->width) x1 = pScreen->width;
if (y1 > pScreen->height) y1 = pScreen->height;
- pDRIPriv->private_buffer_rect.x1 = x0;
- pDRIPriv->private_buffer_rect.y1 = y0;
- pDRIPriv->private_buffer_rect.x2 = x1;
- pDRIPriv->private_buffer_rect.y2 = y1;
-
- *numBackClipRects = 1;
- *pBackClipRects = &(pDRIPriv->private_buffer_rect);
+ if (y0 >= y1 || x0 >= x1) {
+ *numBackClipRects = 0;
+ *pBackClipRects = NULL;
+ } else {
+ pDRIPriv->private_buffer_rect.x1 = x0;
+ pDRIPriv->private_buffer_rect.y1 = y0;
+ pDRIPriv->private_buffer_rect.x2 = x1;
+ pDRIPriv->private_buffer_rect.y2 = y1;
+
+ *numBackClipRects = 1;
+ *pBackClipRects = &(pDRIPriv->private_buffer_rect);
+ }
} else {
/* Use the frontbuffer cliprects for back buffers. */
*numBackClipRects = 0;
@@ -1714,11 +1868,15 @@ DRITreeTraversal(WindowPtr pWin, pointer data)
if(pDRIDrawablePriv) {
ScreenPtr pScreen = pWin->drawable.pScreen;
DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
- RegionPtr reg = (RegionPtr)data;
- REGION_UNION(pScreen, reg, reg, &(pWin->clipList));
+ if(REGION_NUM_RECTS(&(pWin->clipList)) > 0) {
+ RegionPtr reg = (RegionPtr)data;
- if(pDRIPriv->nrWindows == 1)
+ REGION_UNION(pScreen, reg, reg, &(pWin->clipList));
+ pDRIPriv->nrWalked++;
+ }
+
+ if(pDRIPriv->nrWindows == pDRIPriv->nrWalked)
return WT_STOPWALKING;
}
return WT_WALKCHILDREN;
@@ -1736,6 +1894,7 @@ DRICopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
RegionRec reg;
REGION_NULL(pScreen, &reg);
+ pDRIPriv->nrWalked = 0;
TraverseTree(pWin, DRITreeTraversal, (pointer)(&reg));
if(REGION_NOTEMPTY(pScreen, &reg)) {
@@ -2001,28 +2160,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 *
@@ -2043,6 +2220,19 @@ DRIGetContext(ScreenPtr pScreen)
return pDRIPriv->myContext;
}
+void
+DRIGetTexOffsetFuncs(ScreenPtr pScreen,
+ DRITexOffsetStartProcPtr *texOffsetStartFunc,
+ DRITexOffsetFinishProcPtr *texOffsetFinishFunc)
+{
+ DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
+
+ if (!pDRIPriv) return;
+
+ *texOffsetStartFunc = pDRIPriv->pDriverInfo->texOffsetStart;
+ *texOffsetFinishFunc = pDRIPriv->pDriverInfo->texOffsetFinish;
+}
+
/* This lets get at the unwrapped functions so that they can correctly
* call the lowerlevel functions, and choose whether they will be
* called at every level of recursion (eg in validatetree).
diff --git a/hw/xfree86/dri/dri.h b/hw/xfree86/dri/dri.h
index 395b4f1b3..c81500dc4 100644
--- a/hw/xfree86/dri/dri.h
+++ b/hw/xfree86/dri/dri.h
@@ -109,9 +109,12 @@ typedef struct {
*/
#define DRIINFO_MAJOR_VERSION 5
-#define DRIINFO_MINOR_VERSION 1
+#define DRIINFO_MINOR_VERSION 3
#define DRIINFO_PATCH_VERSION 0
+typedef unsigned long long (*DRITexOffsetStartProcPtr)(PixmapPtr pPix);
+typedef void (*DRITexOffsetFinishProcPtr)(PixmapPtr pPix);
+
typedef struct {
/* driver call back functions
*
@@ -178,9 +181,21 @@ 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;
+ Bool keepFDOpen;
+
+ /* New with DRI version 5.3.0 */
+ DRITexOffsetStartProcPtr texOffsetStart;
+ DRITexOffsetFinishProcPtr texOffsetFinish;
} 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);
@@ -346,6 +361,16 @@ extern char *DRICreatePCIBusID(const struct pci_device *PciInfo);
extern int drmInstallSIGIOHandler(int fd, void (*f)(int, void *, void *));
extern int drmRemoveSIGIOHandler(int fd);
+extern int DRIMasterFD(ScrnInfoPtr pScrn);
+
+extern void *DRIMasterSareaPointer(ScrnInfoPtr pScrn);
+
+extern drm_handle_t DRIMasterSareaHandle(ScrnInfoPtr pScrn);
+
+extern void DRIGetTexOffsetFuncs(ScreenPtr pScreen,
+ DRITexOffsetStartProcPtr *texOffsetStartFunc,
+ DRITexOffsetFinishProcPtr *texOffsetFinishFunc);
+
#define _DRI_H_
#endif
diff --git a/hw/xfree86/dri/drimodule.c b/hw/xfree86/dri/drimodule.c
index 0e3d84eb8..3aa9245b9 100644
--- a/hw/xfree86/dri/drimodule.c
+++ b/hw/xfree86/dri/drimodule.c
@@ -88,6 +88,6 @@ driSetup(pointer module, pointer opts, int *errmaj, int *errmin)
drmSetServerInfo(&DRIDRMServerInfo);
/* Need a non-NULL return value to indicate success */
- return 1;
+ return (pointer)1;
}
diff --git a/hw/xfree86/dri/dristruct.h b/hw/xfree86/dri/dristruct.h
index 9c42ff9cc..a3bac8556 100644
--- a/hw/xfree86/dri/dristruct.h
+++ b/hw/xfree86/dri/dristruct.h
@@ -73,6 +73,11 @@ struct _DRIContextPrivRec
#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,25 @@ 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;
+ Bool keepFDOpen;
+ int refCount;
+} DRIEntPrivRec, *DRIEntPrivPtr;
+
#endif /* DRI_STRUCT_H */
diff --git a/hw/xfree86/dri/sarea.h b/hw/xfree86/dri/sarea.h
index a0d6084f3..1528cc191 100644
--- a/hw/xfree86/dri/sarea.h
+++ b/hw/xfree86/dri/sarea.h
@@ -89,4 +89,9 @@ typedef struct _XF86DRISAREA {
drm_context_t dummy_context;
} XF86DRISAREARec, *XF86DRISAREAPtr;
+typedef struct _XF86DRILSAREA {
+ drmLock lock;
+ drmLock otherLocks[31];
+} XF86DRILSAREARec, *XF86DRILSAREAPtr;
+
#endif
diff --git a/hw/xfree86/dri/xf86dri.c b/hw/xfree86/dri/xf86dri.c
index 933cd3e18..9690e8895 100644
--- a/hw/xfree86/dri/xf86dri.c
+++ b/hw/xfree86/dri/xf86dri.c
@@ -452,7 +452,7 @@ ProcXF86DRIGetDrawableInfo(
xXF86DRIGetDrawableInfoReply rep;
DrawablePtr pDrawable;
int X, Y, W, H;
- drm_clip_rect_t * pClipRects;
+ drm_clip_rect_t * pClipRects, *pClippedRects;
drm_clip_rect_t * pBackClipRects;
int backX, backY, rc;
@@ -502,8 +502,35 @@ ProcXF86DRIGetDrawableInfo(
if (rep.numBackClipRects)
rep.length += sizeof(drm_clip_rect_t) * rep.numBackClipRects;
- if (rep.numClipRects)
+ pClippedRects = pClipRects;
+
+ if (rep.numClipRects) {
+ /* Clip cliprects to screen dimensions (redirected windows) */
+ pClippedRects = xalloc(rep.numClipRects * sizeof(drm_clip_rect_t));
+
+ if (pClippedRects) {
+ ScreenPtr pScreen = screenInfo.screens[stuff->screen];
+ int i, j;
+
+ for (i = 0, j = 0; i < rep.numClipRects; i++) {
+ pClippedRects[j].x1 = max(pClipRects[i].x1, 0);
+ pClippedRects[j].y1 = max(pClipRects[i].y1, 0);
+ pClippedRects[j].x2 = min(pClipRects[i].x2, pScreen->width);
+ pClippedRects[j].y2 = min(pClipRects[i].y2, pScreen->height);
+
+ if (pClippedRects[j].x1 < pClippedRects[j].x2 &&
+ pClippedRects[j].y1 < pClippedRects[j].y2) {
+ j++;
+ }
+ }
+
+ rep.numClipRects = j;
+ } else {
+ rep.numClipRects = 0;
+ }
+
rep.length += sizeof(drm_clip_rect_t) * rep.numClipRects;
+ }
rep.length = ((rep.length + 3) & ~3) >> 2;
@@ -512,7 +539,8 @@ ProcXF86DRIGetDrawableInfo(
if (rep.numClipRects) {
WriteToClient(client,
sizeof(drm_clip_rect_t) * rep.numClipRects,
- (char *)pClipRects);
+ (char *)pClippedRects);
+ xfree(pClippedRects);
}
if (rep.numBackClipRects) {