mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-01-29 09:30:20 +01:00
207 lines
4.5 KiB
C
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;
|
|
}
|