mesa/src/libXvMC/context.c
2009-01-10 13:52:06 -05:00

207 lines
4.5 KiB
C

#include <assert.h>
#include <X11/Xlib.h>
#include <X11/extensions/XvMClib.h>
#include <pipe/p_context.h>
#include <vl_display.h>
#include <vl_screen.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 *found_port,
int *chroma_format,
int *mc_type
)
{
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);
*found_port = 0;
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;
*mc_type = surface_info[k].mc_type;
}
}
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 vlProfile ProfileToVL(int xvmc_profile)
{
if (xvmc_profile & XVMC_MPEG_1)
assert(0);
else if (xvmc_profile & XVMC_MPEG_2)
return vlProfileMpeg2Main;
else if (xvmc_profile & XVMC_H263)
assert(0);
else if (xvmc_profile & XVMC_MPEG_4)
assert(0);
else
assert(0);
return -1;
}
static enum vlEntryPoint EntryToVL(int xvmc_entry)
{
return xvmc_entry & XVMC_IDCT ? vlEntryPointIDCT : vlEntryPointMC;
}
static enum vlFormat FormatToVL(int xvmc_format)
{
switch (xvmc_format)
{
case XVMC_CHROMA_FORMAT_420:
return vlFormatYCbCr420;
case XVMC_CHROMA_FORMAT_422:
return vlFormatYCbCr422;
case XVMC_CHROMA_FORMAT_444:
return vlFormatYCbCr444;
default:
assert(0);
}
return -1;
}
Status XvMCCreateContext(Display *display, XvPortID port, int surface_type_id, int width, int height, int flags, XvMCContext *context)
{
int found_port;
int chroma_format;
int mc_type;
Status ret;
struct vlDisplay *vl_dpy;
struct vlScreen *vl_scrn;
struct vlContext *vl_ctx;
struct pipe_context *pipe;
assert(display);
if (!context)
return XvMCBadContext;
ret = Validate(display, port, surface_type_id, width, height, flags, &found_port, &chroma_format, &mc_type);
/* XXX: Success and XvBadPort have the same value */
if (ret != Success || !found_port)
return ret;
/* XXX: Assumes default screen, should check which screen port is on */
pipe = create_pipe_context(display, XDefaultScreen(display));
assert(pipe);
vlCreateDisplay(display, &vl_dpy);
vlCreateScreen(vl_dpy, XDefaultScreen(display), pipe->screen, &vl_scrn);
vlCreateContext
(
vl_scrn,
pipe,
width,
height,
FormatToVL(chroma_format),
ProfileToVL(mc_type),
EntryToVL(mc_type),
&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 vlContext *vl_ctx;
struct vlScreen *vl_screen;
struct vlDisplay *vl_dpy;
struct pipe_context *pipe;
assert(display);
if (!context)
return XvMCBadContext;
vl_ctx = context->privData;
assert(display == vlGetNativeDisplay(vlGetDisplay(vlContextGetScreen(vl_ctx))));
pipe = vlGetPipeContext(vl_ctx);
vl_screen = vlContextGetScreen(vl_ctx);
vl_dpy = vlGetDisplay(vl_screen);
vlDestroyContext(vl_ctx);
vlDestroyScreen(vl_screen);
vlDestroyDisplay(vl_dpy);
destroy_pipe_context(pipe);
return Success;
}