diff options
author | Cooper Yuan <cooperyuan@gmail.com> | 2009-05-31 13:14:25 +0800 |
---|---|---|
committer | Cooper Yuan <cooperyuan@gmail.com> | 2009-05-31 13:14:25 +0800 |
commit | 49a9c8e285c9307660c12abdb0710846bec67760 (patch) | |
tree | 02e5a8420d5b23d035479012983052b02f8f264b | |
parent | 9cd6384cbbe0ad3fbee0eae9a63d3bb7252650bd (diff) |
xvmc: finish XvMCCreateContext and XvMCDestroyContext interface
-rw-r--r-- | src/xvmc/radeon_xvmc.c | 241 | ||||
-rw-r--r-- | src/xvmc/radeon_xvmc.h | 17 |
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 |