summaryrefslogtreecommitdiff
path: root/src/xvmc/intel_xvmc.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/xvmc/intel_xvmc.c')
-rw-r--r--src/xvmc/intel_xvmc.c141
1 files changed, 125 insertions, 16 deletions
diff --git a/src/xvmc/intel_xvmc.c b/src/xvmc/intel_xvmc.c
index fead3a4d..0ce3cc2d 100644
--- a/src/xvmc/intel_xvmc.c
+++ b/src/xvmc/intel_xvmc.c
@@ -84,7 +84,7 @@ static void intel_xvmc_free_context(XID id)
intel_xvmc_context_ptr pre = p;
while(p) {
- if (p->context->context_id == id) {
+ if (p->context && p->context->context_id == id) {
if (p == xvmc_driver->ctx_list)
xvmc_driver->ctx_list = p->next;
else
@@ -95,9 +95,10 @@ static void intel_xvmc_free_context(XID id)
p = p->next;
}
- if (p)
+ if (p) {
free(p);
- xvmc_driver->num_ctx--;
+ xvmc_driver->num_ctx--;
+ }
}
intel_xvmc_context_ptr intel_xvmc_find_context(XID id)
@@ -105,13 +106,69 @@ intel_xvmc_context_ptr intel_xvmc_find_context(XID id)
intel_xvmc_context_ptr p = xvmc_driver->ctx_list;
while(p) {
- if (p->context->context_id == id)
+ if (p->context && p->context->context_id == id)
return p;
p = p->next;
}
return NULL;
}
+static intel_xvmc_surface_ptr intel_xvmc_new_surface(Display *dpy)
+{
+ intel_xvmc_surface_ptr ret;
+
+ ret = (intel_xvmc_surface_ptr)calloc(1, sizeof(intel_xvmc_surface_t));
+ if (!ret)
+ return NULL;
+
+ if (!xvmc_driver->surf_list)
+ ret->next = NULL;
+ else
+ ret->next = xvmc_driver->surf_list;
+ xvmc_driver->surf_list = ret;
+ xvmc_driver->num_surf++;
+
+ ret->image = NULL;
+ ret->gc_init = FALSE;
+
+ return ret;
+
+}
+
+static void intel_xvmc_free_surface(XID id)
+{
+ intel_xvmc_surface_ptr p = xvmc_driver->surf_list;
+ intel_xvmc_surface_ptr pre = p;
+
+ while(p) {
+ if (p->surface && p->surface->surface_id == id) {
+ if (p == xvmc_driver->surf_list)
+ xvmc_driver->surf_list = p->next;
+ else
+ pre->next = p->next;
+ break;
+ }
+ pre = p;
+ p = p->next;
+ }
+
+ if (p) {
+ free(p);
+ xvmc_driver->num_surf--;
+ }
+}
+
+intel_xvmc_surface_ptr intel_xvmc_find_surface(XID id)
+{
+ intel_xvmc_surface_ptr p = xvmc_driver->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.
@@ -207,7 +264,7 @@ Status XvMCCreateContext(Display *display, XvPortID port,
case XVMC_I965_MPEG2_VLD:
default:
XVMC_ERR("unimplemented xvmc type %d", comm->type);
- free(priv_data);
+ XFree(priv_data);
priv_data = NULL;
return BadValue;
}
@@ -231,32 +288,33 @@ Status XvMCCreateContext(Display *display, XvPortID port,
XVMC_ERR("Intel XvMC context create fail\n");
return BadAlloc;
}
+ intel_ctx->context = context;
ret = uniDRIQueryDirectRenderingCapable(display, screen,
&isCapable);
if (!ret || !isCapable) {
XVMC_ERR("Direct Rendering is not available on this system!");
- free(priv_data);
+ XFree(priv_data);
return BadValue;
}
if (!uniDRIOpenConnection(display, screen,
&xvmc_driver->hsarea, &curBusID)) {
XVMC_ERR("Could not open DRI connection to X server!");
- free(priv_data);
+ XFree(priv_data);
return BadValue;
}
strncpy(xvmc_driver->busID, curBusID, 20);
xvmc_driver->busID[20] = '\0';
- free(curBusID);
+ XFree(curBusID);
/* Open DRI Device */
if((xvmc_driver->fd = drmOpen("i915", NULL)) < 0) {
XVMC_ERR("DRM Device could not be opened.");
//(xvmc_driver->fini)();
xvmc_driver = NULL;
- free(priv_data);
+ XFree(priv_data);
return BadValue;
}
@@ -267,7 +325,7 @@ Status XvMCCreateContext(Display *display, XvPortID port,
if (!uniDRIAuthConnection(display, screen, magic)) {
XVMC_ERR("[XvMC]: X server did not allow DRI. Check permissions.");
xvmc_driver = NULL;
- free(priv_data);
+ XFree(priv_data);
return BadAlloc;
}
@@ -278,7 +336,7 @@ Status XvMCCreateContext(Display *display, XvPortID port,
xvmc_driver->sarea_size, &xvmc_driver->sarea_address) < 0) {
XVMC_ERR("Unable to map DRI SAREA.\n");
xvmc_driver = NULL;
- free(priv_data);
+ XFree(priv_data);
return BadAlloc;
}
pSAREA = (drm_sarea_t *)xvmc_driver->sarea_address;
@@ -290,7 +348,7 @@ Status XvMCCreateContext(Display *display, XvPortID port,
context->context_id,
&intel_ctx->hw_context)) {
XVMC_ERR("Could not create DRI context.");
- free(priv_data);
+ XFree(priv_data);
context->privData = NULL;
drmUnmap(xvmc_driver->sarea_address, xvmc_driver->sarea_size);
return BadAlloc;
@@ -301,7 +359,7 @@ Status XvMCCreateContext(Display *display, XvPortID port,
ret = (xvmc_driver->create_context)(display, context, priv_count, priv_data);
if (ret) {
XVMC_ERR("driver create context failed\n");
- free(priv_data);
+ XFree(priv_data);
drmUnmap(xvmc_driver->sarea_address, xvmc_driver->sarea_size);
return ret;
}
@@ -367,6 +425,7 @@ Status XvMCCreateSurface(Display *display, XvMCContext *context, XvMCSurface *su
Status ret;
int priv_count;
CARD32 *priv_data;
+ intel_xvmc_surface_ptr intel_surf = NULL;
if (!display || !context)
return XvMCBadContext;
@@ -374,12 +433,28 @@ Status XvMCCreateSurface(Display *display, XvMCContext *context, XvMCSurface *su
if (!surface)
return XvMCBadSurface;
+ intel_surf = intel_xvmc_new_surface(display);
+ if (!intel_surf)
+ return BadAlloc;
+ intel_surf->surface = surface;
+
if ((ret = _xvmc_create_surface(display, context, surface,
&priv_count, &priv_data))) {
XVMC_ERR("Unable to create XvMCSurface.");
return ret;
}
+ intel_surf->image = XvCreateImage(display, context->port,
+ FOURCC_XVMC, (char *)&intel_surf->data, surface->width,
+ surface->height);
+ if (!intel_surf->image) {
+ XVMC_ERR("Can't create XvImage for surface\n");
+ _xvmc_destroy_surface(display, surface);
+ intel_xvmc_free_surface(surface->surface_id);
+ return BadAlloc;
+ }
+ intel_surf->image->data = (char *)&intel_surf->data;
+
ret = (xvmc_driver->create_surface)(display, context, surface, priv_count,
priv_data);
if (ret) {
@@ -396,9 +471,20 @@ Status XvMCCreateSurface(Display *display, XvMCContext *context, XvMCSurface *su
*/
Status XvMCDestroySurface(Display *display, XvMCSurface *surface)
{
+ intel_xvmc_surface_ptr intel_surf;
+
if (!display || !surface)
return XvMCBadSurface;
+ intel_surf = intel_xvmc_find_surface(surface->surface_id);
+ if (!intel_surf)
+ return XvMCBadSurface;
+
+ XFree(intel_surf->image);
+ if (intel_surf->gc_init)
+ XFreeGC(display, intel_surf->gc);
+ intel_xvmc_free_surface(surface->surface_id);
+
(xvmc_driver->destroy_surface)(display, surface);
_xvmc_destroy_surface(display, surface);
@@ -559,19 +645,42 @@ Status XvMCPutSurface(Display *display,XvMCSurface *surface,
unsigned short destw, unsigned short desth,
int flags)
{
- Status ret;
+ Status ret = Success;
+ XvMCContext *context;
+ intel_xvmc_context_ptr intel_ctx;
+ intel_xvmc_surface_ptr intel_surf;
if (!display || !surface)
return XvMCBadSurface;
+ intel_ctx = intel_xvmc_find_context(surface->context_id);
+ intel_surf = intel_xvmc_find_surface(surface->surface_id);
+ if (!intel_ctx || !intel_surf)
+ return XvMCBadSurface;
+ context = intel_ctx->context;
+
+ if (intel_surf->gc_init == FALSE) {
+ intel_surf->gc = XCreateGC(display, draw, 0, NULL);
+ intel_surf->gc_init = TRUE;
+ } else if (draw != intel_surf->last_draw) {
+ XFreeGC(display, intel_surf->gc);
+ intel_surf->gc = XCreateGC(display, draw, 0, NULL);
+ }
+ intel_surf->last_draw = draw;
+
+ /* fill intel_surf->data */
ret = (xvmc_driver->put_surface)(display, surface, draw, srcx, srcy,
- srcw, srch, destx, desty, destw, desth, flags);
+ srcw, srch, destx, desty, destw, desth, flags, &intel_surf->data);
if (ret) {
XVMC_ERR("put surface fail\n");
return ret;
}
- return Success;
+ ret = XvPutImage(display, context->port, draw, intel_surf->gc,
+ intel_surf->image, srcx, srcy, srcw, srch, destx, desty,
+ destw, desth);
+
+ return ret;
}
/*