📄 intel_xvmc.c
字号:
/* * Copyright © 2007 Intel Corporation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * * Authors: * Zhenyu Wang <zhenyu.z.wang@intel.com> * */#include "intel_xvmc.h"/* global */struct _intel_xvmc_driver *xvmc_driver = NULL;/* Lookup tables to speed common calculations for coded_block_pattern *//* each block is ((8*8) * sizeof(short)) */unsigned int mb_bytes_420[] = { 0, /* 0 */ 128, /* 1 */ 128, /* 10 */ 256, /* 11 */ 128, /* 100 */ 256, /* 101 */ 256, /* 110 */ 384, /* 111 */ 128, /* 1000 */ 256, /* 1001 */ 256, /* 1010 */ 384, /* 1011 */ 256, /* 1100 */ 384, /* 1101 */ 384, /* 1110 */ 512, /* 1111 */ 128, /* 10000 */ 256, /* 10001 */ 256, /* 10010 */ 384, /* 10011 */ 256, /* 10100 */ 384, /* 10101 */ 384, /* 10110 */ 512, /* 10111 */ 256, /* 11000 */ 384, /* 11001 */ 384, /* 11010 */ 512, /* 11011 */ 384, /* 11100 */ 512, /* 11101 */ 512, /* 11110 */ 640, /* 11111 */ 128, /* 100000 */ 256, /* 100001 */ 256, /* 100010 */ 384, /* 100011 */ 256, /* 100100 */ 384, /* 100101 */ 384, /* 100110 */ 512, /* 100111 */ 256, /* 101000 */ 384, /* 101001 */ 384, /* 101010 */ 512, /* 101011 */ 384, /* 101100 */ 512, /* 101101 */ 512, /* 101110 */ 640, /* 101111 */ 256, /* 110000 */ 384, /* 110001 */ 384, /* 110010 */ 512, /* 110011 */ 384, /* 110100 */ 512, /* 110101 */ 512, /* 110110 */ 640, /* 110111 */ 384, /* 111000 */ 512, /* 111001 */ 512, /* 111010 */ 640, /* 111011 */ 512, /* 111100 */ 640, /* 111101 */ 640, /* 111110 */ 768 /* 111111 */};int DEBUG;static int error_base;static int event_base;static void intel_xvmc_debug_init(void){ if (getenv("INTEL_XVMC_DEBUG")) DEBUG = 1;}/* locking */static void intel_xvmc_try_heavy_lock(drm_context_t ctx){ drmGetLock(xvmc_driver->fd, ctx, 0);}void LOCK_HARDWARE(drm_context_t ctx){ char __ret = 0; PPTHREAD_MUTEX_LOCK(); assert(!xvmc_driver->locked); DRM_CAS(xvmc_driver->driHwLock, ctx, (DRM_LOCK_HELD | ctx), __ret); if (__ret) intel_xvmc_try_heavy_lock(ctx); xvmc_driver->locked = 1;}void UNLOCK_HARDWARE(drm_context_t ctx){ xvmc_driver->locked = 0; DRM_UNLOCK(xvmc_driver->fd, xvmc_driver->driHwLock, ctx); PPTHREAD_MUTEX_UNLOCK();}static intel_xvmc_context_ptr intel_xvmc_new_context(Display *dpy){ intel_xvmc_context_ptr ret; ret = (intel_xvmc_context_ptr)calloc(1, sizeof(intel_xvmc_context_t)); if (!ret) return NULL; if (!xvmc_driver->ctx_list) ret->next = NULL; else ret->next = xvmc_driver->ctx_list; xvmc_driver->ctx_list = ret; xvmc_driver->num_ctx++; return ret;}static void intel_xvmc_free_context(XID id){ intel_xvmc_context_ptr p = xvmc_driver->ctx_list; intel_xvmc_context_ptr pre = p; while(p) { if (p->context && p->context->context_id == id) { if (p == xvmc_driver->ctx_list) xvmc_driver->ctx_list = p->next; else pre->next = p->next; break; } pre = p; p = p->next; } if (p) { free(p); xvmc_driver->num_ctx--; }}intel_xvmc_context_ptr intel_xvmc_find_context(XID id){ intel_xvmc_context_ptr p = xvmc_driver->ctx_list; while(p) { 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.* Arguments:* display - Connection to the X server.* port - XvPortID to use as avertised by the X connection.* surface_type_id - Unique identifier for the Surface type.* width - Width of the surfaces.* height - Height of the surfaces.* flags - one or more of the following* XVMC_DIRECT - A direct rendered context is requested.** Notes: surface_type_id and width/height parameters must match those* returned by XvMCListSurfaceTypes.* Returns: Status*/Status XvMCCreateContext(Display *display, XvPortID port, int surface_type_id, int width, int height, int flags, XvMCContext *context){ Status ret; drm_sarea_t *pSAREA; char *curBusID; CARD32 *priv_data = NULL; struct _intel_xvmc_common *comm; drm_magic_t magic; int major, minor; int priv_count; int isCapable; int screen = DefaultScreen(display); intel_xvmc_context_ptr intel_ctx; int fd; /* Verify Obvious things first */ if (!display || !context) return BadValue; if (!(flags & XVMC_DIRECT)) { XVMC_ERR("Indirect Rendering not supported! Using Direct."); return BadValue; } intel_xvmc_debug_init(); /* Open DRI Device */ if((fd = drmOpen("i915", NULL)) < 0) { XVMC_ERR("DRM Device could not be opened."); return BadValue; } /* Width, Height, and flags are checked against surface_type_id and port for validity inside the X server, no need to check here. */ context->surface_type_id = surface_type_id; context->width = (unsigned short)((width + 15) & ~15); context->height = (unsigned short)((height + 15) & ~15); context->flags = flags; context->port = port; if (!XvMCQueryExtension(display, &event_base, &error_base)) { XVMC_ERR("XvMCExtension is not available!"); return BadValue; } ret = XvMCQueryVersion(display, &major, &minor); if (ret) { XVMC_ERR("XvMCQueryVersion Failed, unable to determine protocol version."); return ret; } /* XXX: major and minor could be checked in future for XvMC * protocol capability (i.e H.264/AVC decode available) */ /* Pass control to the X server to create a drm_context_t for us and validate the with/height and flags. */ if ((ret = _xvmc_create_context(display, context, &priv_count, &priv_data))) { XVMC_ERR("Unable to create XvMC Context."); return ret; } XVMC_DBG("new context %d created\n", (int)context->context_id); comm = (struct _intel_xvmc_common *)priv_data; if (xvmc_driver == NULL || xvmc_driver->type != comm->type) { switch (comm->type) { case XVMC_I915_MPEG2_MC: xvmc_driver = &i915_xvmc_mc_driver; break; case XVMC_I965_MPEG2_MC: case XVMC_I945_MPEG2_VLD: case XVMC_I965_MPEG2_VLD: default: XVMC_ERR("unimplemented xvmc type %d", comm->type); XFree(priv_data); priv_data = NULL; return BadValue; } } if (xvmc_driver == NULL || xvmc_driver->type != comm->type) { XVMC_ERR("fail to load xvmc driver for type %d\n", comm->type); return BadValue; } xvmc_driver->fd = fd; XVMC_INFO("decoder type is %s", intel_xvmc_decoder_string(comm->type)); xvmc_driver->sarea_size = comm->sarea_size; xvmc_driver->batchbuffer.handle = comm->batchbuffer.handle; xvmc_driver->batchbuffer.offset = comm->batchbuffer.offset; xvmc_driver->batchbuffer.size = comm->batchbuffer.size; /* assign local ctx info */ intel_ctx = intel_xvmc_new_context(display); if (!intel_ctx) { 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!"); 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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -