From a2221721d7002fac3b3a9dd844228d404ab677f9 Mon Sep 17 00:00:00 2001 From: Xiang, Haihao Date: Thu, 9 Apr 2009 10:20:11 +0800 Subject: [PATCH] XvMC: enable XvMC on DRI2 --- src/i830_driver.c | 3 +- src/i830_hwmc.c | 32 ++++-- src/i915_hwmc.c | 10 +- src/i965_hwmc.c | 7 +- src/xvmc/Makefile.am | 4 +- src/xvmc/dri2.c | 301 +++++++++++++++++++++++++++++++++++++++++++++++++ src/xvmc/dri2.h | 70 ++++++++++++ src/xvmc/i915_xvmc.c | 25 +++-- src/xvmc/intel_xvmc.c | 243 +++++++++++++++++++++++++++------------- src/xvmc/intel_xvmc.h | 4 + 10 files changed, 598 insertions(+), 101 deletions(-) create mode 100644 src/xvmc/dri2.c create mode 100644 src/xvmc/dri2.h diff --git a/src/i830_driver.c b/src/i830_driver.c index 32ca6c9..5be7655 100644 --- a/src/i830_driver.c +++ b/src/i830_driver.c @@ -3282,7 +3282,8 @@ I830ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) #ifdef I830_XV #ifdef INTEL_XVMC pI830->XvMCEnabled = FALSE; - from = (pI830->directRenderingType == DRI_XF86DRI && + from = ((pI830->directRenderingType == DRI_XF86DRI || + pI830->directRenderingType == DRI_DRI2) && xf86GetOptValBool(pI830->Options, OPTION_XVMC, &pI830->XvMCEnabled)) ? X_CONFIG : X_DEFAULT; xf86DrvMsg(pScrn->scrnIndex, from, "Intel XvMC decoder %sabled\n", diff --git a/src/i830_hwmc.c b/src/i830_hwmc.c index e33a15d..fef2695 100644 --- a/src/i830_hwmc.c +++ b/src/i830_hwmc.c @@ -52,12 +52,6 @@ Bool intel_xvmc_probe(ScrnInfoPtr pScrn) I830Ptr pI830 = I830PTR(pScrn); Bool ret = FALSE; - /* Disable XvMC on DRI2 for now */ - if (pI830->directRenderingType == DRI_DRI2) { - pI830->XvMCEnabled = FALSE; - return FALSE; - } - if (!pI830->XvMCEnabled) return FALSE; @@ -83,6 +77,9 @@ void intel_xvmc_finish(ScrnInfoPtr pScrn) Bool intel_xvmc_driver_init(ScreenPtr pScreen, XF86VideoAdaptorPtr xv_adaptor) { ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + I830Ptr pI830 = I830PTR(pScrn); + struct drm_i915_setparam sp; + int ret; if (!xvmc_driver) { ErrorF("Failed to probe XvMC driver.\n"); @@ -93,14 +90,23 @@ Bool intel_xvmc_driver_init(ScreenPtr pScreen, XF86VideoAdaptorPtr xv_adaptor) ErrorF("XvMC driver initialize failed.\n"); return FALSE; } - return TRUE; + + /* Currently XvMC uses batchbuffer */ + sp.param = I915_SETPARAM_ALLOW_BATCHBUFFER; + sp.value = 1; + ret = drmCommandWrite(pI830->drmSubFD, DRM_I915_SETPARAM, + &sp, sizeof(sp)); + if (ret == 0) + return TRUE; + + return FALSE; } Bool intel_xvmc_screen_init(ScreenPtr pScreen) { ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; I830Ptr pI830 = I830PTR(pScrn); - DRIInfoPtr pDRIInfo = pI830->pDRIInfo; + char buf[64]; if (!xvmc_driver) return FALSE; @@ -117,9 +123,15 @@ Bool intel_xvmc_screen_init(ScreenPtr pScreen) return FALSE; } + sprintf(buf, "pci:%04x:%02x:%02x.%d", + pI830->PciInfo->domain, + pI830->PciInfo->bus, + pI830->PciInfo->dev, + pI830->PciInfo->func); + xf86XvMCRegisterDRInfo(pScreen, INTEL_XVMC_LIBNAME, - pDRIInfo->busIdString, - INTEL_XVMC_MAJOR, INTEL_XVMC_MINOR, INTEL_XVMC_PATCHLEVEL); + buf, + INTEL_XVMC_MAJOR, INTEL_XVMC_MINOR, INTEL_XVMC_PATCHLEVEL); return TRUE; } diff --git a/src/i915_hwmc.c b/src/i915_hwmc.c index 659638e..b0bfdb7 100644 --- a/src/i915_hwmc.c +++ b/src/i915_hwmc.c @@ -417,7 +417,6 @@ static int i915_xvmc_create_context (ScrnInfoPtr pScrn, XvMCContextPtr pContext, { I830Ptr pI830 = I830PTR(pScrn); DRIInfoPtr pDRIInfo = pI830->pDRIInfo; - I830DRIPtr pI830DRI = pDRIInfo->devPrivate; I915XvMCCreateContextRec *contextRec = NULL; I915XvMCPtr pXvMC = (I915XvMCPtr)xvmc_driver->devPrivate; I915XvMCContextPriv *ctxpriv = NULL; @@ -490,7 +489,12 @@ static int i915_xvmc_create_context (ScrnInfoPtr pScrn, XvMCContextPtr pContext, /* common context items */ contextRec->comm.type = xvmc_driver->flag; - contextRec->comm.sarea_size = pDRIInfo->SAREASize; + + if (pDRIInfo != NULL) + contextRec->comm.sarea_size = pDRIInfo->SAREASize; + else + contextRec->comm.sarea_size = 0; + contextRec->comm.batchbuffer.offset = xvmc_driver->batch->offset; contextRec->comm.batchbuffer.size = xvmc_driver->batch->size; contextRec->comm.batchbuffer.handle = xvmc_driver->batch_handle; @@ -516,7 +520,7 @@ static int i915_xvmc_create_context (ScrnInfoPtr pScrn, XvMCContextPtr pContext, contextRec->corrdata.offset = ctxpriv->mcCorrdata->offset; contextRec->corrdata.size = ctxpriv->mcCorrdata->size; contextRec->sarea_priv_offset = sizeof(XF86DRISAREARec); - contextRec->deviceID = pI830DRI->deviceID; + contextRec->deviceID = DEVICE_ID(pI830->PciInfo); if (IS_I915G(pI830) || IS_I915GM(pI830)) { contextRec->sis.bus_addr = ctxpriv->mcStaticIndirectState->bus_addr; diff --git a/src/i965_hwmc.c b/src/i965_hwmc.c index d9b4f0d..6e4d80d 100644 --- a/src/i965_hwmc.c +++ b/src/i965_hwmc.c @@ -130,7 +130,12 @@ static int create_context(ScrnInfoPtr pScrn, private_context->is_g4x = IS_G4X(I830); private_context->is_965_q = IS_965_Q(I830); private_context->comm.type = xvmc_driver->flag; - private_context->comm.sarea_size = driinfo->SAREASize; + + if (driinfo != NULL) + private_context->comm.sarea_size = driinfo->SAREASize; + else + private_context->comm.sarea_size = 0; + private_context->comm.batchbuffer.offset = xvmc_driver->batch->offset; private_context->comm.batchbuffer.size = xvmc_driver->batch->size; private_context->comm.batchbuffer.handle = xvmc_driver->batch_handle; diff --git a/src/xvmc/Makefile.am b/src/xvmc/Makefile.am index a376eb7..574ce9d 100644 --- a/src/xvmc/Makefile.am +++ b/src/xvmc/Makefile.am @@ -23,7 +23,9 @@ libIntelXvMC_la_SOURCES = intel_xvmc.c \ intel_batchbuffer.h \ xf86dri.c \ xf86dri.h \ - xf86dristr.h + xf86dristr.h \ + dri2.c \ + dri2.h libIntelXvMC_la_CFLAGS = @XORG_CFLAGS@ @DRM_CFLAGS@ @DRI_CFLAGS@ \ @XVMCLIB_CFLAGS@ -I$(top_srcdir)/src -DTRUE=1 -DFALSE=0 diff --git a/src/xvmc/dri2.c b/src/xvmc/dri2.c new file mode 100644 index 0000000..f967432 --- /dev/null +++ b/src/xvmc/dri2.c @@ -0,0 +1,301 @@ +/* + * Copyright © 2008 Red Hat, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Soft- + * ware"), to deal in the Software without restriction, including without + * limitation the rights to use, copy, modify, merge, publish, distribute, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, provided that the above copyright + * notice(s) and this permission notice appear in all copies of the Soft- + * ware and that both the above copyright notice(s) and this permission + * notice appear in supporting documentation. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- + * ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY + * RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN + * THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE- + * QUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFOR- + * MANCE OF THIS SOFTWARE. + * + * Except as contained in this notice, the name of a copyright holder shall + * not be used in advertising or otherwise to promote the sale, use or + * other dealings in this Software without prior written authorization of + * the copyright holder. + * + * Authors: + * Kristian Høgsberg (krh@redhat.com) + */ + + +#define NEED_REPLIES +#include +#include +#include +#include +#include "xf86drm.h" +#include "dri2.h" + +static char dri2ExtensionName[] = DRI2_NAME; +static XExtensionInfo *dri2Info; +static XEXT_GENERATE_CLOSE_DISPLAY (DRI2CloseDisplay, dri2Info) +static /* const */ XExtensionHooks dri2ExtensionHooks = { + NULL, /* create_gc */ + NULL, /* copy_gc */ + NULL, /* flush_gc */ + NULL, /* free_gc */ + NULL, /* create_font */ + NULL, /* free_font */ + DRI2CloseDisplay, /* close_display */ + NULL, /* wire_to_event */ + NULL, /* event_to_wire */ + NULL, /* error */ + NULL, /* error_string */ +}; + +static XEXT_GENERATE_FIND_DISPLAY (DRI2FindDisplay, dri2Info, + dri2ExtensionName, + &dri2ExtensionHooks, + 0, NULL) + +Bool DRI2QueryExtension(Display *dpy, int *eventBase, int *errorBase) +{ + XExtDisplayInfo *info = DRI2FindDisplay(dpy); + + if (XextHasExtension(info)) { + *eventBase = info->codes->first_event; + *errorBase = info->codes->first_error; + return True; + } + + return False; +} + +Bool DRI2QueryVersion(Display *dpy, int *major, int *minor) +{ + XExtDisplayInfo *info = DRI2FindDisplay (dpy); + xDRI2QueryVersionReply rep; + xDRI2QueryVersionReq *req; + + XextCheckExtension (dpy, info, dri2ExtensionName, False); + + LockDisplay(dpy); + GetReq(DRI2QueryVersion, req); + req->reqType = info->codes->major_opcode; + req->dri2ReqType = X_DRI2QueryVersion; + req->majorVersion = DRI2_MAJOR; + req->minorVersion = DRI2_MINOR; + if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + *major = rep.majorVersion; + *minor = rep.minorVersion; + UnlockDisplay(dpy); + SyncHandle(); + + return True; +} + +Bool DRI2Connect(Display *dpy, XID window, + char **driverName, char **deviceName) +{ + XExtDisplayInfo *info = DRI2FindDisplay(dpy); + xDRI2ConnectReply rep; + xDRI2ConnectReq *req; + + XextCheckExtension (dpy, info, dri2ExtensionName, False); + + LockDisplay(dpy); + GetReq(DRI2Connect, req); + req->reqType = info->codes->major_opcode; + req->dri2ReqType = X_DRI2Connect; + req->window = window; + req->driverType = DRI2DriverDRI; + if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + + if (rep.driverNameLength == 0 && rep.deviceNameLength == 0) { + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + + *driverName = Xmalloc(rep.driverNameLength + 1); + if (*driverName == NULL) { + _XEatData(dpy, + ((rep.driverNameLength + 3) & ~3) + + ((rep.deviceNameLength + 3) & ~3)); + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + _XReadPad(dpy, *driverName, rep.driverNameLength); + (*driverName)[rep.driverNameLength] = '\0'; + + *deviceName = Xmalloc(rep.deviceNameLength + 1); + if (*deviceName == NULL) { + Xfree(*driverName); + _XEatData(dpy, ((rep.deviceNameLength + 3) & ~3)); + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + _XReadPad(dpy, *deviceName, rep.deviceNameLength); + (*deviceName)[rep.deviceNameLength] = '\0'; + + UnlockDisplay(dpy); + SyncHandle(); + + return True; +} + +Bool DRI2Authenticate(Display *dpy, XID window, drm_magic_t magic) +{ + XExtDisplayInfo *info = DRI2FindDisplay(dpy); + xDRI2AuthenticateReq *req; + xDRI2AuthenticateReply rep; + + XextCheckExtension (dpy, info, dri2ExtensionName, False); + + LockDisplay(dpy); + GetReq(DRI2Authenticate, req); + req->reqType = info->codes->major_opcode; + req->dri2ReqType = X_DRI2Authenticate; + req->window = window; + req->magic = magic; + + if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + + UnlockDisplay(dpy); + SyncHandle(); + + return rep.authenticated; +} + +void DRI2CreateDrawable(Display *dpy, XID drawable) +{ + XExtDisplayInfo *info = DRI2FindDisplay(dpy); + xDRI2CreateDrawableReq *req; + + XextSimpleCheckExtension (dpy, info, dri2ExtensionName); + + LockDisplay(dpy); + GetReq(DRI2CreateDrawable, req); + req->reqType = info->codes->major_opcode; + req->dri2ReqType = X_DRI2CreateDrawable; + req->drawable = drawable; + UnlockDisplay(dpy); + SyncHandle(); +} + +void DRI2DestroyDrawable(Display *dpy, XID drawable) +{ + XExtDisplayInfo *info = DRI2FindDisplay(dpy); + xDRI2DestroyDrawableReq *req; + + XextSimpleCheckExtension (dpy, info, dri2ExtensionName); + + XSync(dpy, False); + + LockDisplay(dpy); + GetReq(DRI2DestroyDrawable, req); + req->reqType = info->codes->major_opcode; + req->dri2ReqType = X_DRI2DestroyDrawable; + req->drawable = drawable; + UnlockDisplay(dpy); + SyncHandle(); +} + +DRI2Buffer *DRI2GetBuffers(Display *dpy, XID drawable, + int *width, int *height, + unsigned int *attachments, int count, + int *outCount) +{ + XExtDisplayInfo *info = DRI2FindDisplay(dpy); + xDRI2GetBuffersReply rep; + xDRI2GetBuffersReq *req; + DRI2Buffer *buffers; + xDRI2Buffer repBuffer; + CARD32 *p; + int i; + + XextCheckExtension (dpy, info, dri2ExtensionName, False); + + LockDisplay(dpy); + GetReqExtra(DRI2GetBuffers, count * 4, req); + req->reqType = info->codes->major_opcode; + req->dri2ReqType = X_DRI2GetBuffers; + req->drawable = drawable; + req->count = count; + p = (CARD32 *) &req[1]; + for (i = 0; i < count; i++) + p[i] = attachments[i]; + + if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + return NULL; + } + + *width = rep.width; + *height = rep.height; + *outCount = rep.count; + + buffers = Xmalloc(rep.count * sizeof buffers[0]); + if (buffers == NULL) { + _XEatData(dpy, rep.count * sizeof repBuffer); + UnlockDisplay(dpy); + SyncHandle(); + return NULL; + } + + for (i = 0; i < rep.count; i++) { + _XReadPad(dpy, (char *) &repBuffer, sizeof repBuffer); + buffers[i].attachment = repBuffer.attachment; + buffers[i].name = repBuffer.name; + buffers[i].pitch = repBuffer.pitch; + buffers[i].cpp = repBuffer.cpp; + buffers[i].flags = repBuffer.flags; + } + + UnlockDisplay(dpy); + SyncHandle(); + + return buffers; +} + +void DRI2CopyRegion(Display *dpy, XID drawable, XserverRegion region, + CARD32 dest, CARD32 src) +{ + XExtDisplayInfo *info = DRI2FindDisplay(dpy); + xDRI2CopyRegionReq *req; + xDRI2CopyRegionReply rep; + + XextSimpleCheckExtension (dpy, info, dri2ExtensionName); + + LockDisplay(dpy); + GetReq(DRI2CopyRegion, req); + req->reqType = info->codes->major_opcode; + req->dri2ReqType = X_DRI2CopyRegion; + req->drawable = drawable; + req->region = region; + req->dest = dest; + req->src = src; + + _XReply(dpy, (xReply *)&rep, 0, xFalse); + + UnlockDisplay(dpy); + SyncHandle(); +} diff --git a/src/xvmc/dri2.h b/src/xvmc/dri2.h new file mode 100644 index 0000000..356c6bc --- /dev/null +++ b/src/xvmc/dri2.h @@ -0,0 +1,70 @@ +/* + * Copyright © 2007,2008 Red Hat, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Soft- + * ware"), to deal in the Software without restriction, including without + * limitation the rights to use, copy, modify, merge, publish, distribute, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, provided that the above copyright + * notice(s) and this permission notice appear in all copies of the Soft- + * ware and that both the above copyright notice(s) and this permission + * notice appear in supporting documentation. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- + * ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY + * RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN + * THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE- + * QUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFOR- + * MANCE OF THIS SOFTWARE. + * + * Except as contained in this notice, the name of a copyright holder shall + * not be used in advertising or otherwise to promote the sale, use or + * other dealings in this Software without prior written authorization of + * the copyright holder. + * + * Authors: + * Kristian Høgsberg (krh@redhat.com) + */ + +#ifndef _DRI2_H_ +#define _DRI2_H_ + +#include +#include + +typedef struct { + unsigned int attachment; + unsigned int name; + unsigned int pitch; + unsigned int cpp; + unsigned int flags; +} DRI2Buffer; + +extern Bool +DRI2QueryExtension(Display *display, int *eventBase, int *errorBase); +extern Bool +DRI2QueryVersion(Display *display, int *major, int *minor); +extern Bool +DRI2Connect(Display *display, XID window, + char **driverName, char **deviceName); +extern Bool +DRI2Authenticate(Display *display, XID window, drm_magic_t magic); +extern void +DRI2CreateDrawable(Display *display, XID drawable); +extern void +DRI2DestroyDrawable(Display *display, XID handle); +extern DRI2Buffer * +DRI2GetBuffers(Display *dpy, XID drawable, + int *width, int *height, + unsigned int *attachments, int count, + int *outCount); + +extern void +DRI2CopyRegion(Display *dpy, XID drawable, XserverRegion region, + CARD32 dest, CARD32 src); + +#endif diff --git a/src/xvmc/i915_xvmc.c b/src/xvmc/i915_xvmc.c index c32073a..192be08 100644 --- a/src/xvmc/i915_xvmc.c +++ b/src/xvmc/i915_xvmc.c @@ -1618,8 +1618,12 @@ static Status i915_xvmc_mc_create_context(Display *display, XvMCContext *context XFree(priv_data); priv_data = NULL; - pSAREA = (drm_sarea_t *)xvmc_driver->sarea_address; - pI915XvMC->sarea = (drmI830Sarea*)((char*)pSAREA + pI915XvMC->sarea_priv_offset); + if (xvmc_driver->sarea_address) { + pSAREA = (drm_sarea_t *)xvmc_driver->sarea_address; + pI915XvMC->sarea = (drmI830Sarea*)((char*)pSAREA + pI915XvMC->sarea_priv_offset); + } else { + pI915XvMC->sarea = NULL; + } if (i915_xvmc_map_buffers(pI915XvMC)) { i915_xvmc_unmap_buffers(pI915XvMC); @@ -2042,9 +2046,11 @@ static int i915_xvmc_mc_get_surface_status(Display *display, } } - if (pI915Surface->last_render && - (pI915Surface->last_render > pI915XvMC->sarea->last_dispatch)) { - *stat |= XVMC_RENDERING; + if (pI915XvMC->sarea) { + if (pI915Surface->last_render && + (pI915Surface->last_render > pI915XvMC->sarea->last_dispatch)) { + *stat |= XVMC_RENDERING; + } } PPTHREAD_MUTEX_UNLOCK(); @@ -2457,10 +2463,13 @@ Status i915_xvmc_get_subpict_status(Display *display, XvMCSubpicture *subpicture return XvMCBadSubpicture; PPTHREAD_MUTEX_LOCK(); + /* FIXME: */ - if (pI915Subpicture->last_render && - (pI915Subpicture->last_render > pI915XvMC->sarea->last_dispatch)) { - *stat |= XVMC_RENDERING; + if (pI915XvMC->sarea) { + if (pI915Subpicture->last_render && + (pI915Subpicture->last_render > pI915XvMC->sarea->last_dispatch)) { + *stat |= XVMC_RENDERING; + } } PPTHREAD_MUTEX_UNLOCK(); diff --git a/src/xvmc/intel_xvmc.c b/src/xvmc/intel_xvmc.c index 4b73caa..d5175a7 100644 --- a/src/xvmc/intel_xvmc.c +++ b/src/xvmc/intel_xvmc.c @@ -100,9 +100,6 @@ unsigned int mb_bytes_420[] = { int DEBUG; -static int error_base; -static int event_base; - static void intel_xvmc_debug_init(void) { if (getenv("INTEL_XVMC_DEBUG")) @@ -122,11 +119,13 @@ void LOCK_HARDWARE(drm_context_t ctx) PPTHREAD_MUTEX_LOCK(); assert(!xvmc_driver->locked); - DRM_CAS(xvmc_driver->driHwLock, ctx, - (DRM_LOCK_HELD | ctx), __ret); + if (!xvmc_driver->dri2.enabled) { + DRM_CAS(xvmc_driver->driHwLock, ctx, + (DRM_LOCK_HELD | ctx), __ret); - if (__ret) - intel_xvmc_try_heavy_lock(ctx); + if (__ret) + intel_xvmc_try_heavy_lock(ctx); + } xvmc_driver->locked = 1; } @@ -134,7 +133,10 @@ void LOCK_HARDWARE(drm_context_t ctx) void UNLOCK_HARDWARE(drm_context_t ctx) { xvmc_driver->locked = 0; - DRM_UNLOCK(xvmc_driver->fd, xvmc_driver->driHwLock, ctx); + + if (!xvmc_driver->dri2.enabled) + DRM_UNLOCK(xvmc_driver->fd, xvmc_driver->driHwLock, ctx); + PPTHREAD_MUTEX_UNLOCK(); } @@ -270,16 +272,19 @@ _X_EXPORT Status XvMCCreateContext(Display *display, XvPortID port, { Status ret; drm_sarea_t *pSAREA; - char *curBusID; + char *curBusID = NULL; CARD32 *priv_data = NULL; struct _intel_xvmc_common *comm; drm_magic_t magic; int major, minor; + int error_base; + int event_base; int priv_count; int isCapable; int screen = DefaultScreen(display); intel_xvmc_context_ptr intel_ctx; int fd; + char *driverName = NULL, *deviceName = NULL; /* Verify Obvious things first */ if (!display || !context) @@ -367,84 +372,165 @@ _X_EXPORT Status XvMCCreateContext(Display *display, XvPortID port, } intel_ctx->context = context; - ret = uniDRIQueryDirectRenderingCapable(display, screen, - &isCapable); - if (!ret || !isCapable) { - XVMC_ERR("Direct Rendering is not available on this system!"); - XFree(priv_data); - return BadValue; - } - - if (!uniDRIOpenConnection(display, screen, - &xvmc_driver->hsarea, &curBusID)) { - XVMC_ERR("Could not open DRI connection to X server!"); - XFree(priv_data); - return BadValue; - } + { + ret = Success; + xvmc_driver->dri2.enabled = FALSE; + xvmc_driver->fd = -1; + xvmc_driver->sarea_address = NULL; + + /* check DRI2 */ + do { + if (!DRI2QueryExtension(display, &event_base, &error_base)) { + ret = BadValue; + break; + } + + if (!DRI2QueryVersion(display, &major, &minor)) { + ret = BadValue; + break; + } + + if (!DRI2Connect(display, RootWindow(display, screen), + &driverName, &deviceName)) { + ret = BadValue; + break; + } + + xvmc_driver->fd = open(deviceName, O_RDWR); + + if (xvmc_driver->fd < 0) { + XVMC_ERR("Failed to open drm device: %s\n", strerror(errno)); + ret = BadValue; + break; + } + + if (drmGetMagic(xvmc_driver->fd, &magic)) { + XVMC_ERR("Failed to get magic\n"); + ret = BadValue; + break; + } + + if (!DRI2Authenticate(display, RootWindow(display, screen), magic)) { + XVMC_ERR("Failed to authenticate magic %d\n", magic); + ret = BadValue; + break; + } + + xvmc_driver->dri2.enabled = TRUE; + } while (0); + + XFree(driverName); + XFree(deviceName); + + if (!xvmc_driver->dri2.enabled && (xvmc_driver->fd >= 0)) { + close(xvmc_driver->fd); + xvmc_driver->fd = -1; + } + + /* check legacy direct rendering */ + if (!xvmc_driver->dri2.enabled) { + ret = Success; + + do { + ret = uniDRIQueryDirectRenderingCapable(display, screen, + &isCapable); + if (!ret || !isCapable) { + XVMC_ERR("Direct Rendering is not available on this system!"); + ret = BadValue; + break; + } + + ret = Success; + + if (!uniDRIOpenConnection(display, screen, + &xvmc_driver->hsarea, &curBusID)) { + XVMC_ERR("Could not open DRI connection to X server!"); + ret = BadValue; + break; + } + + /* Open DRI Device */ + xvmc_driver->fd = drmOpen("i915", curBusID); + if (xvmc_driver->fd < 0) { + XVMC_ERR("DRM Device could not be opened."); + ret = BadValue; + break; + } + + strncpy(xvmc_driver->busID, curBusID, 20); + xvmc_driver->busID[20] = '\0'; + + /* Get magic number */ + if (drmGetMagic(xvmc_driver->fd, &magic)) { + XVMC_ERR("Failed to get magic\n"); + ret = BadValue; + break; + } + + if (!uniDRIAuthConnection(display, screen, magic)) { + XVMC_ERR("[XvMC]: X server did not allow DRI. Check permissions."); + ret = BadAlloc; + break; + } + + /* + * Map DRI Sarea. we always want it right? + */ + if (drmMap(xvmc_driver->fd, xvmc_driver->hsarea, + xvmc_driver->sarea_size, &xvmc_driver->sarea_address) < 0) { + XVMC_ERR("Unable to map DRI SAREA.\n"); + ret = BadAlloc; + break; + } + + pSAREA = (drm_sarea_t *)xvmc_driver->sarea_address; + xvmc_driver->driHwLock = (drmLock *)&pSAREA->lock; + + /* context_id is alloc in _xvmc_create_context */ + if (!uniDRICreateContext(display, screen, DefaultVisual(display, screen), + context->context_id, + &intel_ctx->hw_context)) { + XVMC_ERR("Could not create DRI context for xvmc ctx %d.", + (int)context->context_id); + ret = BadAlloc; + break; + } + } while (0); + } - /* Open DRI Device */ - if((fd = drmOpen("i915", curBusID)) < 0) { - XVMC_ERR("DRM Device could not be opened."); - XFree(priv_data); XFree(curBusID); - return BadValue; - } - xvmc_driver->fd = fd; + if (ret != Success) { + XFree(priv_data); + context->privData = NULL; - strncpy(xvmc_driver->busID, curBusID, 20); - xvmc_driver->busID[20] = '\0'; - XFree(curBusID); + if (xvmc_driver->sarea_address) + drmUnmap(xvmc_driver->sarea_address, xvmc_driver->sarea_size); + + if (xvmc_driver->fd >= 0) + drmClose(xvmc_driver->fd); - /* Get magic number */ - drmGetMagic(xvmc_driver->fd, &magic); - // context->flags = (unsigned long)magic; - - if (!uniDRIAuthConnection(display, screen, magic)) { - XVMC_ERR("[XvMC]: X server did not allow DRI. Check permissions."); - xvmc_driver = NULL; - XFree(priv_data); - return BadAlloc; + xvmc_driver = NULL; + return ret; + } } - - /* - * Map DRI Sarea. we always want it right? - */ - if (drmMap(xvmc_driver->fd, xvmc_driver->hsarea, - xvmc_driver->sarea_size, &xvmc_driver->sarea_address) < 0) { - XVMC_ERR("Unable to map DRI SAREA.\n"); - xvmc_driver = NULL; - XFree(priv_data); - return BadAlloc; - } - pSAREA = (drm_sarea_t *)xvmc_driver->sarea_address; - xvmc_driver->driHwLock = (drmLock *)&pSAREA->lock; - pthread_mutex_init(&xvmc_driver->ctxmutex, NULL); - - /* context_id is alloc in _xvmc_create_context */ - if (!uniDRICreateContext(display, screen, DefaultVisual(display, screen), - context->context_id, - &intel_ctx->hw_context)) { - XVMC_ERR("Could not create DRI context for xvmc ctx %d.", - (int)context->context_id); - XFree(priv_data); - context->privData = NULL; - drmUnmap(xvmc_driver->sarea_address, xvmc_driver->sarea_size); - return BadAlloc; - } - /* call driver hook. * driver hook should free priv_data after return if success.*/ ret = (xvmc_driver->create_context)(display, context, priv_count, priv_data); if (ret) { XVMC_ERR("driver create context failed\n"); XFree(priv_data); - drmUnmap(xvmc_driver->sarea_address, xvmc_driver->sarea_size); + context->privData = NULL; + + if (xvmc_driver->sarea_address) + drmUnmap(xvmc_driver->sarea_address, xvmc_driver->sarea_size); + + xvmc_driver = NULL; return ret; } + pthread_mutex_init(&xvmc_driver->ctxmutex, NULL); intelInitBatchBuffer(); - intel_xvmc_dump_open(); return Success; @@ -484,17 +570,20 @@ _X_EXPORT Status XvMCDestroyContext(Display *display, XvMCContext *context) if (xvmc_driver->num_ctx == 0) { uniDRICloseConnection(display, screen); - pthread_mutex_destroy(&xvmc_driver->ctxmutex); - drmUnmap(xvmc_driver->sarea_address, xvmc_driver->sarea_size); + if (xvmc_driver->sarea_address) + drmUnmap(xvmc_driver->sarea_address, xvmc_driver->sarea_size); - if (xvmc_driver->fd >= 0) - drmClose(xvmc_driver->fd); + if (xvmc_driver->fd >= 0) { + if (xvmc_driver->dri2.enabled) + close(xvmc_driver->fd); + else + drmClose(xvmc_driver->fd); + } + xvmc_driver->fd = -1; - intelFiniBatchBuffer(); - intel_xvmc_dump_close(); } return Success; diff --git a/src/xvmc/intel_xvmc.h b/src/xvmc/intel_xvmc.h index 9ef2121..5b1296d 100644 --- a/src/xvmc/intel_xvmc.h +++ b/src/xvmc/intel_xvmc.h @@ -166,6 +166,10 @@ typedef struct _intel_xvmc_driver { void *private; + struct { + int enabled; + } dri2; + /* driver specific xvmc callbacks */ Status (*create_context)(Display* display, XvMCContext *context, int priv_count, CARD32 *priv_data); -- 1.5.6.3