diff options
Diffstat (limited to 'src/libXvMC/context.c')
-rw-r--r-- | src/libXvMC/context.c | 218 |
1 files changed, 218 insertions, 0 deletions
diff --git a/src/libXvMC/context.c b/src/libXvMC/context.c new file mode 100644 index 0000000000..9cf654d6bb --- /dev/null +++ b/src/libXvMC/context.c @@ -0,0 +1,218 @@ +#include <assert.h> +#include <X11/Xlib.h> +#include <X11/extensions/XvMClib.h> +#include <vl_context.h> +#include <vl_winsys.h> + +static Status Validate(Display *display, XvPortID port, int surface_type_id, unsigned int width, unsigned int height, int flags, int *chroma_format) +{ + unsigned int found_port = 0; + unsigned int found_surface = 0; + XvAdaptorInfo *adaptor_info; + unsigned int num_adaptors; + int num_types; + unsigned int max_width, max_height; + Status ret; + unsigned int i, j, k; + + assert(display && chroma_format); + + ret = XvQueryAdaptors(display, XDefaultRootWindow(display), &num_adaptors, &adaptor_info); + if (ret != Success) + return ret; + + /* Scan through all adaptors looking for this port and surface */ + for (i = 0; i < num_adaptors && !found_port; ++i) + { + /* Scan through all ports of this adaptor looking for our port */ + for (j = 0; j < adaptor_info[i].num_ports && !found_port; ++j) + { + /* If this is our port, scan through all its surfaces looking for our surface */ + if (adaptor_info[i].base_id + j == port) + { + XvMCSurfaceInfo *surface_info; + + found_port = 1; + surface_info = XvMCListSurfaceTypes(display, adaptor_info[i].base_id, &num_types); + + if (surface_info) + { + for (k = 0; k < num_types && !found_surface; ++k) + { + if (surface_info[k].surface_type_id == surface_type_id) + { + found_surface = 1; + max_width = surface_info[k].max_width; + max_height = surface_info[k].max_height; + *chroma_format = surface_info[k].chroma_format; + } + } + + XFree(surface_info); + } + else + { + XvFreeAdaptorInfo(adaptor_info); + return BadAlloc; + } + } + } + } + + XvFreeAdaptorInfo(adaptor_info); + + if (!found_port) + return XvBadPort; + if (!found_surface) + return BadMatch; + if (width > max_width || height > max_height) + return BadValue; + if (flags != XVMC_DIRECT && flags != 0) + return BadValue; + + return Success; +} + +static enum VL_FORMAT FormatToVL(int xvmc_format) +{ + enum VL_FORMAT vl_format; + + switch (xvmc_format) + { + case XVMC_CHROMA_FORMAT_420: + { + vl_format = VL_FORMAT_YCBCR_420; + break; + } + case XVMC_CHROMA_FORMAT_422: + { + vl_format = VL_FORMAT_YCBCR_422; + break; + } + case XVMC_CHROMA_FORMAT_444: + { + vl_format = VL_FORMAT_YCBCR_444; + break; + } + default: + assert(0); + } + + return vl_format; +} + +Status XvMCCreateContext(Display *display, XvPortID port, int surface_type_id, int width, int height, int flags, XvMCContext *context) +{ + int chroma_format; + Status ret; + struct VL_CONTEXT *vl_ctx; + struct pipe_context *pipe; + + assert(display); + + if (!context) + return XvMCBadContext; + + ret = Validate(display, port, surface_type_id, width, height, flags, &chroma_format); + if (ret != Success) + return ret; + + pipe = create_pipe_context(display, XDefaultScreen(display)); + + assert(pipe); + + vlCreateContext(display, pipe, width, height, FormatToVL(chroma_format), &vl_ctx); + + context->context_id = XAllocID(display); + context->surface_type_id = surface_type_id; + context->width = width; + context->height = height; + context->flags = flags; + context->port = port; + context->privData = vl_ctx; + + return Success; +} + +Status XvMCDestroyContext(Display *display, XvMCContext *context) +{ + struct VL_CONTEXT *vl_ctx; + struct pipe_context *pipe; + + assert(display); + + if (!context) + return XvMCBadContext; + + vl_ctx = context->privData; + + assert(display == vl_ctx->display); + + pipe = vl_ctx->pipe; + vlDestroyContext(vl_ctx); + destroy_pipe_context(pipe); + + return Success; +} + +/* XXX: The following are here temporarily, need to be implemented in the DDX driver */ +/* TODO: Figure out which of these need to be in DDX, which are better off in DDX, which can stay */ + +Bool XvMCQueryExtension(Display *display, int *event_base, int *err_base) +{ + *event_base = 0; + *err_base = 0; + + return True; +} + +Status XvMCQueryVersion(Display *display, int *major, int *minor) +{ + *major = 1; + *minor = 0; + + return Success; +} + +XvMCSurfaceInfo* XvMCListSurfaceTypes(Display *display, XvPortID port, int *num) +{ + XvMCSurfaceInfo *surface_info = calloc(1, sizeof(XvMCSurfaceInfo)); + + *num = 1; + + surface_info->chroma_format = XVMC_CHROMA_FORMAT_420; + surface_info->max_width = 2048; + surface_info->max_height = 2048; + surface_info->subpicture_max_width = 2048; + surface_info->subpicture_max_height = 2048; + surface_info->mc_type = XVMC_IDCT | XVMC_MPEG_2; + surface_info->surface_type_id = 123; /* FIXME: XAllocID(display)*/; + surface_info->flags = XVMC_INTRA_UNSIGNED | XVMC_SUBPICTURE_INDEPENDENT_SCALING | XVMC_BACKEND_SUBPICTURE; + + return surface_info; +} + +XvImageFormatValues* XvMCListSubpictureTypes(Display* display, XvPortID port, int surface_type_id, int *count_return) +{ + XvImageFormatValues *image_formats = calloc(1, sizeof(XvImageFormatValues)); + + *count_return = 1; + + image_formats[0].id = 123; + image_formats[0].type = XvRGB; + image_formats[0].byte_order = LSBFirst; + image_formats[0].bits_per_pixel = 8; + image_formats[0].format = XvPacked; + image_formats[0].num_planes = 1; + image_formats[0].depth = 8; + image_formats[0].red_mask = 0x0000FF; + image_formats[0].green_mask = 0x00FF00; + image_formats[0].blue_mask = 0xFF0000; + image_formats[0].component_order[0] = 'R'; + image_formats[0].component_order[0] = 'G'; + image_formats[0].component_order[0] = 'B'; + image_formats[0].scanline_order = XvTopToBottom; + + return image_formats; +} + |