summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCooper Yuan <cooperyuan@gmail.com>2009-05-31 13:14:25 +0800
committerCooper Yuan <cooperyuan@gmail.com>2009-05-31 13:14:25 +0800
commit49a9c8e285c9307660c12abdb0710846bec67760 (patch)
tree02e5a8420d5b23d035479012983052b02f8f264b
parent9cd6384cbbe0ad3fbee0eae9a63d3bb7252650bd (diff)
xvmc: finish XvMCCreateContext and XvMCDestroyContext interface
-rw-r--r--src/xvmc/radeon_xvmc.c241
-rw-r--r--src/xvmc/radeon_xvmc.h17
2 files changed, 249 insertions, 9 deletions
diff --git a/src/xvmc/radeon_xvmc.c b/src/xvmc/radeon_xvmc.c
index 1fadbef..1874133 100644
--- a/src/xvmc/radeon_xvmc.c
+++ b/src/xvmc/radeon_xvmc.c
@@ -28,6 +28,118 @@
struct radeon_xvmc_driver *xvmc_driver_ptr = NULL;
+static radeon_xvmc_context_ptr radeon_xvmc_new_context(Display *dpy)
+{
+ radeon_xvmc_context_ptr ret;
+
+ ret = (radeon_xvmc_context_ptr)calloc(1, sizeof(radeon_xvmc_context_t));
+ if (!ret)
+ return NULL;
+
+ ret->next = xvmc_driver_ptr->ctx_list;
+ xvmc_driver_ptr->ctx_list = ret;
+ xvmc_driver_ptr->num_ctx++;
+
+ return ret;
+
+}
+
+static void radeon_xvmc_free_context(XID id)
+{
+ radeon_xvmc_context_ptr p = xvmc_driver_ptr->ctx_list;
+ radeon_xvmc_context_ptr pre = p;
+
+ while(p)
+ {
+ if (p->context && p->context->context_id == id)
+ {
+ if (p == xvmc_driver_ptr->ctx_list)
+ xvmc_driver_ptr->ctx_list = p->next;
+ else
+ pre->next = p->next;
+ break;
+ }
+ pre = p;
+ p = p->next;
+ }
+
+ if (p)
+ {
+ free(p);
+ xvmc_driver_ptr->num_ctx--;
+ }
+}
+
+radeon_xvmc_context_ptr radeon_xvmc_find_context(XID id)
+{
+ radeon_xvmc_context_ptr p = xvmc_driver_ptr->ctx_list;
+
+ while(p)
+ {
+ if (p->context && p->context->context_id == id)
+ return p;
+ p = p->next;
+ }
+ return NULL;
+}
+
+static radeon_xvmc_surface_ptr radeon_xvmc_new_surface(Display *dpy)
+{
+ radeon_xvmc_surface_ptr ret;
+
+ ret = (radeon_xvmc_surface_ptr)calloc(1, sizeof(radeon_xvmc_surface_t));
+ if (!ret)
+ return NULL;
+
+ ret->next = xvmc_driver_ptr->surf_list;
+ xvmc_driver_ptr->surf_list = ret;
+ xvmc_driver_ptr->num_surf++;
+
+ ret->image = NULL;
+ ret->gc_init = FALSE;
+
+ return ret;
+}
+
+static void radeon_xvmc_free_surface(XID id)
+{
+ radeon_xvmc_surface_ptr p = xvmc_driver_ptr->surf_list;
+ radeon_xvmc_surface_ptr pre = p;
+
+ while(p)
+ {
+ if (p->surface && p->surface->surface_id == id)
+ {
+ if (p == xvmc_driver_ptr->surf_list)
+ xvmc_driver_ptr->surf_list = p->next;
+ else
+ pre->next = p->next;
+ break;
+ }
+ pre = p;
+ p = p->next;
+ }
+
+ if (p)
+ {
+ free(p);
+ xvmc_driver_ptr->num_surf--;
+ }
+}
+
+radeon_xvmc_surface_ptr radeon_xvmc_find_surface(XID id)
+{
+ radeon_xvmc_surface_ptr p = xvmc_driver_ptr->surf_list;
+
+ while(p)
+ {
+ if (p->surface && p->surface->surface_id == id)
+ return p;
+ p = p->next;
+ }
+ return NULL;
+}
+
/*
* Function: XvMCCreateContext
* Description: Create a XvMC context for the given surface parameters.
@@ -59,7 +171,7 @@ _X_EXPORT Status XvMCCreateContext(Display *display, XvPortID port,
int isCapable;
int event_base, error_base;
int screen = DefaultScreen(display);
- radeon_xvmc_context_ptr intel_ctx;
+ radeon_xvmc_context_ptr radeon_ctx;
int fd;
/* Verify Obvious things first */
@@ -68,7 +180,7 @@ _X_EXPORT Status XvMCCreateContext(Display *display, XvPortID port,
if (!(flags & XVMC_DIRECT))
{
- ErrorF("Radeon: Indirect Rendering not supported! Using Direct.");
+ ErrorF("[XvMC]: Radeon: Indirect Rendering not supported! Using Direct.");
return BadValue;
}
@@ -80,14 +192,14 @@ _X_EXPORT Status XvMCCreateContext(Display *display, XvPortID port,
if (!XvMCQueryExtension(display, &event_base, &error_base))
{
- ErrorF("Radeon: XvMCExtension is not available!");
+ ErrorF("[XvMC]: Radeon: XvMCExtension is not available!");
return BadValue;
}
ret = XvMCQueryVersion(display, &major, &minor);
if (ret)
{
- ErrorF("Radeon: XvMCQueryVersion Failed, unable to determine protocol version.");
+ ErrorF("[XvMC]: Radeon: XvMCQueryVersion Failed, unable to determine protocol version.");
return ret;
}
@@ -97,7 +209,7 @@ _X_EXPORT Status XvMCCreateContext(Display *display, XvPortID port,
*/
if ((ret = _xvmc_create_context(display, context, &priv_count, &priv_data)))
{
- ErrorF("Radeon: Unable to create XvMC Context.");
+ ErrorF("[XvMC]: Radeon: Unable to create XvMC Context.");
return ret;
}
@@ -111,7 +223,7 @@ _X_EXPORT Status XvMCCreateContext(Display *display, XvPortID port,
xvmc_driver_ptr = &r500_xvmc_driver;
break;
default:
- ErrorF("Radeon: unimplemented xvmc type %d", comm->type);
+ ErrorF("[XvMC]: Radeon: unimplemented xvmc type %d", comm->type);
XFree(priv_data);
priv_data = NULL;
return BadValue;
@@ -120,7 +232,7 @@ _X_EXPORT Status XvMCCreateContext(Display *display, XvPortID port,
if (xvmc_driver_ptr == NULL || xvmc_driver_ptr->type != comm->type)
{
- ErrorF("Radeon: fail to load xvmc driver for type %d\n", comm->type);
+ ErrorF("[XvMC]: Radeon: fail to load xvmc driver for type %d\n", comm->type);
return BadValue;
}
@@ -129,6 +241,84 @@ _X_EXPORT Status XvMCCreateContext(Display *display, XvPortID port,
xvmc_driver_ptr->batchbuffer.offset = comm->batchbuffer.offset;
xvmc_driver_ptr->batchbuffer.size = comm->batchbuffer.size;
+ /* assign local ctx info */
+ radeon_ctx = radeon_xvmc_new_context(display);
+ if (!radeon_ctx)
+ {
+ ErrorF("[XvMC]: Radeon XvMC context create failed\n");
+ return BadAlloc;
+ }
+ radeon_ctx->context = context;
+
+ ret = uniDRIQueryDirectRenderingCapable(display, screen, &isCapable);
+ if (!ret || !isCapable)
+ {
+ ErrorF("[XvMC]: Direct Rendering is not available on this system!");
+ XFree(priv_data);
+ return BadValue;
+ }
+
+ if (!uniDRIOpenConnection(display, screen, &xvmc_driver_ptr->hsarea, &curBusID))
+ {
+ ErrorF("[XvMC]: Could not open DRI connection to X server!");
+ XFree(priv_data);
+ return BadValue;
+ }
+
+ /* Open DRI Device */
+ if((fd = drmOpen("radeon", curBusID)) < 0)
+ {
+ ErrorF("[XvMC]: DRM Device could not be opened.");
+ XFree(priv_data);
+ XFree(curBusID);
+ return BadValue;
+ }
+
+ xvmc_driver_ptr->fd = fd;
+
+ strncpy(xvmc_driver_ptr->busID, curBusID, 20);
+ xvmc_driver_ptr->busID[20] = '\0';
+ XFree(curBusID);
+
+ /* Get magic number */
+ drmGetMagic(xvmc_driver_ptr->fd, &magic);
+
+ if (!uniDRIAuthConnection(display, screen, magic))
+ {
+ ErrorF("[XvMC]: X server did not allow DRI. Check permissions.");
+ xvmc_driver_ptr = NULL;
+ XFree(priv_data);
+ return BadAlloc;
+ }
+
+ /*
+ * Map DRI Sarea. we always want it right?
+ */
+ if (drmMap(xvmc_driver_ptr->fd, xvmc_driver_ptr->hsarea,
+ xvmc_driver_ptr->sarea_size, &xvmc_driver_ptr->sarea_address) < 0)
+ {
+ XVMC_ERR("[XvMC]: Unable to map DRI SAREA.\n");
+ xvmc_driver_ptr = NULL;
+ XFree(priv_data);
+ return BadAlloc;
+ }
+ pSAREA = (drm_sarea_t *)xvmc_driver_ptr->sarea_address;
+ xvmc_driver_ptr->driHwLock = (drmLock *)&pSAREA->lock;
+ pthread_mutex_init(&xvmc_driver_ptr->ctxmutex, NULL);
+
+ /* context_id is alloc in _xvmc_create_context */
+ if (!uniDRICreateContext(display, screen, DefaultVisual(display, screen),
+ context->context_id,
+ &radeon_ctx->hw_context))
+ {
+ XVMC_ERR("[XvMC]: Could not create DRI context for xvmc ctx %d.",
+ (int)context->context_id);
+ XFree(priv_data);
+ context->privData = NULL;
+ drmUnmap(xvmc_driver_ptr->sarea_address, xvmc_driver_ptr->sarea_size);
+ return BadAlloc;
+ }
+
/*
* call driver hook.
* driver hook should free priv_data after return if success.
@@ -136,7 +326,7 @@ _X_EXPORT Status XvMCCreateContext(Display *display, XvPortID port,
ret = (xvmc_driver_ptr->create_context)(display, context, priv_count, priv_data);
if (ret)
{
- ErrorF("driver create context failed\n");
+ ErrorF("[XvMC]: driver create context failed\n");
XFree(priv_data);
drmUnmap(xvmc_driver_ptr->sarea_address, xvmc_driver_ptr->sarea_size);
return ret;
@@ -156,6 +346,41 @@ _X_EXPORT Status XvMCCreateContext(Display *display, XvPortID port,
*/
_X_EXPORT Status XvMCDestroyContext(Display *display, XvMCContext *context)
{
+ Status ret;
+ int screen;
+
+ if (!display || !context)
+ return XvMCBadContext;
+ screen = DefaultScreen(display);
+ ret = (xvmc_driver_ptr->destroy_context)(display, context);
+ if (ret)
+ {
+ ErrorF("[XvMC]: destroy context fail\n");
+ return ret;
+ }
+
+ uniDRIDestroyContext(display, screen, context->context_id);
+ radeon_xvmc_free_context(context->context_id);
+
+ ret = _xvmc_destroy_context(display, context);
+ if (ret != Success)
+ {
+ ErrorF("[XvMC]: _xvmc_destroy_context fail\n");
+ return ret;
+ }
+
+ if (xvmc_driver_ptr->num_ctx == 0)
+ {
+ uniDRICloseConnection(display, screen);
+ pthread_mutex_destroy(&xvmc_driver_ptr->ctxmutex);
+
+ drmUnmap(xvmc_driver_ptr->sarea_address, xvmc_driver_ptr->sarea_size);
+
+ if (xvmc_driver_ptr->fd >= 0)
+ drmClose(xvmc_driver_ptr->fd);
+ xvmc_driver_ptr->fd = -1;
+ }
+ return Success;
}
/*
diff --git a/src/xvmc/radeon_xvmc.h b/src/xvmc/radeon_xvmc.h
index be98ac2..0cfacf2 100644
--- a/src/xvmc/radeon_xvmc.h
+++ b/src/xvmc/radeon_xvmc.h
@@ -56,9 +56,19 @@ typedef struct radeon_xvmc_context
{
XvMCContext *context;
drm_context_t hw_context; /* context id to kernel drm */
- struct _radeon_xvmc_context *next;
+ struct radeon_xvmc_context *next;
} radeon_xvmc_context_t, *radeon_xvmc_context_ptr;
+typedef struct radeon_xvmc_surface
+{
+ XvMCSurface *surface;
+ XvImage *image;
+ GC gc;
+ Bool gc_init;
+ Drawable last_draw;
+ struct radeon_xvmc_surface *next;
+} radeon_xvmc_surface_t, *radeon_xvmc_surface_ptr;
+
typedef struct radeon_xvmc_drm_map
{
drm_handle_t handle;
@@ -107,7 +117,9 @@ typedef struct radeon_xvmc_driver
drmLock *driHwLock;
int num_ctx;
+ radeon_xvmc_context_ptr ctx_list;
int num_surf;
+ radeon_xvmc_surface_ptr surf_list;
void *private;
@@ -147,4 +159,7 @@ typedef struct radeon_xvmc_driver
extern struct radeon_xvmc_driver *xvmc_driver_ptr;
extern struct radeon_xvmc_driver r500_xvmc_driver;
+extern radeon_xvmc_context_ptr radeon_xvmc_find_context(XID id);
+extern radeon_xvmc_surface_ptr radeon_xvmc_find_surface(XID id);
+
#endif \ No newline at end of file