g3dvl: Implement XvMC using pipe_video_context.

This commit is contained in:
Younes Manton 2009-09-27 20:18:02 -04:00
parent f547472bfa
commit e44c85637a
16 changed files with 1163 additions and 738 deletions

View File

@ -0,0 +1,11 @@
TOP = ../../../..
include $(TOP)/configs/current
SUBDIRS = $(GALLIUM_WINSYS_DIRS)
default install clean:
@for dir in $(SUBDIRS) ; do \
if [ -d $$dir ] ; then \
(cd $$dir && $(MAKE) $@) || exit 1; \
fi \
done

View File

@ -2,13 +2,22 @@
#define vl_winsys_h
#include <X11/Xlib.h>
#include <pipe/p_defines.h>
#include <pipe/p_format.h>
struct pipe_context;
struct pipe_screen;
struct pipe_video_context;
struct pipe_context* create_pipe_context(Display *display, int screen);
int destroy_pipe_context(struct pipe_context *pipe);
int bind_pipe_drawable(struct pipe_context *pipe, Drawable drawable);
int unbind_pipe_drawable(struct pipe_context *pipe);
struct pipe_screen*
vl_screen_create(Display *display, int screen);
struct pipe_video_context*
vl_video_create(struct pipe_screen *screen,
enum pipe_video_profile profile,
enum pipe_video_chroma_format chroma_format,
unsigned width, unsigned height);
Drawable
vl_video_bind_drawable(struct pipe_video_context *vpipe, Drawable drawable);
#endif

View File

@ -0,0 +1,74 @@
# This makefile produces a "stand-alone" libXvMCg3dvl.so which is
# based on Xlib (no DRI HW acceleration)
TOP = ../../../../..
include $(TOP)/configs/current
XVMC_MAJOR = 1
XVMC_MINOR = 0
XVMC_LIB = XvMCg3dvl
XVMC_LIB_NAME = lib$(XVMC_LIB).so
XVMC_LIB_DEPS = $(EXTRA_LIB_PATH) -lXvMC -lXv -lX11 -lm
INCLUDES = -I$(TOP)/src/gallium/include \
-I$(TOP)/src/gallium/auxiliary \
-I$(TOP)/src/gallium/drivers \
-I$(TOP)/src/gallium/winsys/g3dvl
DEFINES += -DGALLIUM_SOFTPIPE \
-DGALLIUM_TRACE
SOURCES = xsp_winsys.c
# XXX: Hack, if we include libXvMCapi.a in LIBS none of the symbols are
# pulled in by the linker because xsp_winsys.c doesn't refer to them
OBJECTS = $(SOURCES:.c=.o) $(TOP)/src/xvmc/*.o
LIBS = $(TOP)/src/gallium/drivers/softpipe/libsoftpipe.a \
$(TOP)/src/gallium/auxiliary/vl/libvl.a \
$(TOP)/src/gallium/auxiliary/tgsi/libtgsi.a \
$(TOP)/src/gallium/auxiliary/draw/libdraw.a \
$(TOP)/src/gallium/auxiliary/translate/libtranslate.a \
$(TOP)/src/gallium/auxiliary/cso_cache/libcso_cache.a \
$(TOP)/src/gallium/auxiliary/rtasm/librtasm.a \
$(TOP)/src/gallium/auxiliary/util/libutil.a
.c.o:
$(CC) -c $(INCLUDES) $(DEFINES) $(CFLAGS) $< -o $@
.S.o:
$(CC) -c $(INCLUDES) $(DEFINES) $(CFLAGS) $< -o $@
.PHONY: default $(TOP)/$(LIB_DIR)/gallium clean
default: depend $(TOP)/$(LIB_DIR)/gallium $(TOP)/$(LIB_DIR)/gallium/$(XVMC_LIB_NAME)
$(TOP)/$(LIB_DIR)/gallium:
@mkdir -p $(TOP)/$(LIB_DIR)/gallium
# Make the libXvMCg3dvl.so library
$(TOP)/$(LIB_DIR)/gallium/$(XVMC_LIB_NAME): $(OBJECTS) $(LIBS) Makefile
$(MKLIB) -o $(XVMC_LIB) -linker '$(CC)' -ldflags '$(LDFLAGS)' \
-major $(XVMC_MAJOR) -minor $(XVMC_MINOR) $(MKLIB_OPTIONS) \
-install $(TOP)/$(LIB_DIR)/gallium -id $(INSTALL_LIB_DIR)/lib$(XVMC_LIB).1.dylib \
$(XVMC_LIB_DEPS) $(OBJECTS) $(LIBS)
depend: $(SOURCES) Makefile
$(RM) depend
touch depend
$(MKDEP) $(MKDEP_OPTIONS) $(DEFINES) $(INCLUDES) $(SOURCES)
#install: default
# $(INSTALL) -d $(INSTALL_DIR)/include/GL
# $(INSTALL) -d $(INSTALL_DIR)/$(LIB_DIR)
# $(INSTALL) -m 644 $(TOP)/include/GL/*.h $(INSTALL_DIR)/include/GL
# @if [ -e $(TOP)/$(LIB_DIR)/$(GL_LIB_NAME) ]; then \
# $(INSTALL) $(TOP)/$(LIB_DIR)/libGL* $(INSTALL_DIR)/$(LIB_DIR); \
# fi
clean: Makefile
$(RM) $(TOP)/$(LIB_DIR)/gallium/$(XVMC_LIB_NAME)
$(RM) *.o *~
$(RM) depend depend.bak
-include depend

View File

@ -0,0 +1,307 @@
#include <vl_winsys.h>
#include <X11/Xutil.h>
#include <pipe/internal/p_winsys_screen.h>
#include <pipe/p_state.h>
#include <pipe/p_inlines.h>
#include <util/u_memory.h>
#include <util/u_math.h>
#include <softpipe/sp_winsys.h>
#include <softpipe/sp_video_context.h>
#include <softpipe/sp_texture.h>
/* pipe_winsys implementation */
struct xsp_pipe_winsys
{
struct pipe_winsys base;
Display *display;
int screen;
XImage *fbimage;
};
struct xsp_context
{
Drawable drawable;
void (*pipe_destroy)(struct pipe_video_context *vpipe);
};
struct xsp_buffer
{
struct pipe_buffer base;
boolean is_user_buffer;
void *data;
void *mapped_data;
};
static struct pipe_buffer* xsp_buffer_create(struct pipe_winsys *pws, unsigned alignment, unsigned usage, unsigned size)
{
struct xsp_buffer *buffer;
assert(pws);
buffer = calloc(1, sizeof(struct xsp_buffer));
pipe_reference_init(&buffer->base.reference, 1);
buffer->base.alignment = alignment;
buffer->base.usage = usage;
buffer->base.size = size;
buffer->data = align_malloc(size, alignment);
return (struct pipe_buffer*)buffer;
}
static struct pipe_buffer* xsp_user_buffer_create(struct pipe_winsys *pws, void *data, unsigned size)
{
struct xsp_buffer *buffer;
assert(pws);
buffer = calloc(1, sizeof(struct xsp_buffer));
pipe_reference_init(&buffer->base.reference, 1);
buffer->base.size = size;
buffer->is_user_buffer = TRUE;
buffer->data = data;
return (struct pipe_buffer*)buffer;
}
static void* xsp_buffer_map(struct pipe_winsys *pws, struct pipe_buffer *buffer, unsigned flags)
{
struct xsp_buffer *xsp_buf = (struct xsp_buffer*)buffer;
assert(pws);
assert(buffer);
xsp_buf->mapped_data = xsp_buf->data;
return xsp_buf->mapped_data;
}
static void xsp_buffer_unmap(struct pipe_winsys *pws, struct pipe_buffer *buffer)
{
struct xsp_buffer *xsp_buf = (struct xsp_buffer*)buffer;
assert(pws);
assert(buffer);
xsp_buf->mapped_data = NULL;
}
static void xsp_buffer_destroy(struct pipe_buffer *buffer)
{
struct xsp_buffer *xsp_buf = (struct xsp_buffer*)buffer;
assert(buffer);
if (!xsp_buf->is_user_buffer)
align_free(xsp_buf->data);
free(xsp_buf);
}
static struct pipe_buffer* xsp_surface_buffer_create
(
struct pipe_winsys *pws,
unsigned width,
unsigned height,
enum pipe_format format,
unsigned usage,
unsigned tex_usage,
unsigned *stride
)
{
const unsigned int ALIGNMENT = 1;
struct pipe_format_block block;
unsigned nblocksx, nblocksy;
pf_get_block(format, &block);
nblocksx = pf_get_nblocksx(&block, width);
nblocksy = pf_get_nblocksy(&block, height);
*stride = align(nblocksx * block.size, ALIGNMENT);
return pws->buffer_create(pws, ALIGNMENT,
usage,
*stride * nblocksy);
}
static void xsp_fence_reference(struct pipe_winsys *pws, struct pipe_fence_handle **ptr, struct pipe_fence_handle *fence)
{
assert(pws);
assert(ptr);
assert(fence);
}
static int xsp_fence_signalled(struct pipe_winsys *pws, struct pipe_fence_handle *fence, unsigned flag)
{
assert(pws);
assert(fence);
return 0;
}
static int xsp_fence_finish(struct pipe_winsys *pws, struct pipe_fence_handle *fence, unsigned flag)
{
assert(pws);
assert(fence);
return 0;
}
static void xsp_flush_frontbuffer(struct pipe_winsys *pws, struct pipe_surface *surface, void *context_private)
{
struct xsp_pipe_winsys *xsp_winsys;
struct xsp_context *xsp_context;
assert(pws);
assert(surface);
assert(context_private);
xsp_winsys = (struct xsp_pipe_winsys*)pws;
xsp_context = (struct xsp_context*)context_private;
xsp_winsys->fbimage->width = surface->width;
xsp_winsys->fbimage->height = surface->height;
xsp_winsys->fbimage->bytes_per_line = surface->width * (xsp_winsys->fbimage->bits_per_pixel >> 3);
xsp_winsys->fbimage->data = (char*)((struct xsp_buffer *)softpipe_texture(surface->texture)->buffer)->data + surface->offset;
XPutImage
(
xsp_winsys->display, xsp_context->drawable,
XDefaultGC(xsp_winsys->display, xsp_winsys->screen),
xsp_winsys->fbimage, 0, 0, 0, 0,
surface->width, surface->height
);
XFlush(xsp_winsys->display);
}
static const char* xsp_get_name(struct pipe_winsys *pws)
{
assert(pws);
return "X11 SoftPipe";
}
static void xsp_destroy(struct pipe_winsys *pws)
{
struct xsp_pipe_winsys *xsp_winsys = (struct xsp_pipe_winsys*)pws;
assert(pws);
/* XDestroyImage() wants to free the data as well */
xsp_winsys->fbimage->data = NULL;
XDestroyImage(xsp_winsys->fbimage);
FREE(xsp_winsys);
}
/* Called through pipe_video_context::destroy() */
static void xsp_pipe_destroy(struct pipe_video_context *vpipe)
{
struct xsp_context *xsp_context;
assert(vpipe);
xsp_context = vpipe->priv;
/* Call the original destroy */
xsp_context->pipe_destroy(vpipe);
FREE(xsp_context);
}
/* Show starts here */
Drawable
vl_video_bind_drawable(struct pipe_video_context *vpipe, Drawable drawable)
{
struct xsp_context *xsp_context;
Drawable old_drawable;
assert(vpipe);
xsp_context = vpipe->priv;
old_drawable = xsp_context->drawable;
xsp_context->drawable = drawable;
return old_drawable;
}
struct pipe_screen*
vl_screen_create(Display *display, int screen)
{
struct xsp_pipe_winsys *xsp_winsys;
assert(display);
xsp_winsys = CALLOC_STRUCT(xsp_pipe_winsys);
if (!xsp_winsys)
return NULL;
xsp_winsys->base.buffer_create = xsp_buffer_create;
xsp_winsys->base.user_buffer_create = xsp_user_buffer_create;
xsp_winsys->base.buffer_map = xsp_buffer_map;
xsp_winsys->base.buffer_unmap = xsp_buffer_unmap;
xsp_winsys->base.buffer_destroy = xsp_buffer_destroy;
xsp_winsys->base.surface_buffer_create = xsp_surface_buffer_create;
xsp_winsys->base.fence_reference = xsp_fence_reference;
xsp_winsys->base.fence_signalled = xsp_fence_signalled;
xsp_winsys->base.fence_finish = xsp_fence_finish;
xsp_winsys->base.flush_frontbuffer = xsp_flush_frontbuffer;
xsp_winsys->base.get_name = xsp_get_name;
xsp_winsys->base.destroy = xsp_destroy;
xsp_winsys->display = display;
xsp_winsys->screen = screen;
xsp_winsys->fbimage = XCreateImage
(
display,
XDefaultVisual(display, screen),
XDefaultDepth(display, screen),
ZPixmap,
0,
NULL,
0, /* Don't know the width and height until flush_frontbuffer */
0,
32,
0
);
if (!xsp_winsys->fbimage)
{
FREE(xsp_winsys);
return NULL;
}
XInitImage(xsp_winsys->fbimage);
return softpipe_create_screen(&xsp_winsys->base);
}
struct pipe_video_context*
vl_video_create(struct pipe_screen *screen,
enum pipe_video_profile profile,
enum pipe_video_chroma_format chroma_format,
unsigned width, unsigned height)
{
struct pipe_video_context *vpipe;
struct xsp_context *xsp_context;
assert(screen);
assert(width && height);
vpipe = sp_video_create(screen, profile, chroma_format, width, height);
if (!vpipe)
return NULL;
xsp_context = CALLOC_STRUCT(xsp_context);
if (!xsp_context)
{
vpipe->destroy(vpipe);
return NULL;
}
/* Override this so we can free our xsp_context when the pipe is freed */
xsp_context->pipe_destroy = vpipe->destroy;
vpipe->destroy = xsp_pipe_destroy;
vpipe->priv = xsp_context;
return vpipe;
}

View File

@ -1,73 +1,45 @@
TARGET = libXvMCg3dvl.so
SONAME = libXvMCg3dvl.so.1
GALLIUMDIR = ../gallium
TOP = ../..
include $(TOP)/configs/current
OBJECTS = block.o surface.o context.o subpicture.o attributes.o
#DEFINES += -DDEFAULT_DRIVER_DIR=\"$(DRI_DRIVER_SEARCH_DIR)\"
ifeq (${DRIVER}, softpipe)
OBJECTS += ${GALLIUMDIR}/winsys/g3dvl/xsp_winsys.o
endif
SOURCES = block.c \
surface.c \
context.c \
subpicture.c \
attributes.c
CFLAGS += -g -fPIC -Wall -Werror=implicit-function-declaration \
-I${GALLIUMDIR}/state_trackers/g3dvl \
-I${GALLIUMDIR}/winsys/g3dvl \
-I${GALLIUMDIR}/include \
-I${GALLIUMDIR}/auxiliary \
-I${GALLIUMDIR}/drivers
OBJECTS = $(SOURCES:.c=.o)
ifeq (${DRIVER}, softpipe)
LDFLAGS += -L${GALLIUMDIR}/state_trackers/g3dvl \
-L${GALLIUMDIR}/drivers/softpipe \
-L${GALLIUMDIR}/auxiliary/tgsi \
-L${GALLIUMDIR}/auxiliary/draw \
-L${GALLIUMDIR}/auxiliary/translate \
-L${GALLIUMDIR}/auxiliary/cso_cache \
-L${GALLIUMDIR}/auxiliary/util \
-L${GALLIUMDIR}/auxiliary/rtasm
else
LDFLAGS += -L${GALLIUMDIR}/state_trackers/g3dvl \
-L${GALLIUMDIR}/winsys/g3dvl/nouveau \
-L${GALLIUMDIR}/auxiliary/util
endif
INCLUDES = -I$(TOP)/src/gallium/include \
-I$(TOP)/src/gallium/auxiliary \
-I$(TOP)/src/gallium/winsys/g3dvl
ifeq (${DRIVER}, softpipe)
LIBS += -lg3dvl -lsoftpipe -ldraw -ltgsi -ltranslate -lrtasm -lcso_cache -lutil -lm
else
LIBS += -lg3dvl -lnouveau_dri -lutil
endif
##### RULES #####
#############################################
.c.o:
$(CC) -c $(INCLUDES) $(DEFINES) $(CFLAGS) $< -o $@
ifeq (${DRIVER}, softpipe)
.PHONY = all clean g3dvl
else
.PHONY = all clean g3dvl nouveau_winsys
endif
.S.o:
$(CC) -c $(INCLUDES) $(DEFINES) $(CFLAGS) $< -o $@
all: ${TARGET}
##### TARGETS #####
ifeq (${DRIVER}, softpipe)
${TARGET}: ${OBJECTS} g3dvl
$(CC) ${LDFLAGS} -shared -Wl,-soname,${SONAME} -o $@ ${OBJECTS} ${LIBS}
.PHONY: default clean
g3dvl:
cd ${GALLIUMDIR}/state_trackers/g3dvl; ${MAKE}
default: depend libXvMCapi.a
clean:
cd ${GALLIUMDIR}/state_trackers/g3dvl; ${MAKE} clean
rm -rf ${OBJECTS} ${TARGET}
else
${TARGET}: ${OBJECTS} g3dvl nouveau_winsys
$(CC) ${LDFLAGS} -shared -Wl,-soname,${SONAME} -o $@ ${OBJECTS} ${LIBS}
libXvMCapi.a: $(OBJECTS) Makefile
$(MKLIB) -o XvMCapi $(MKLIB_OPTIONS) -static $(OBJECTS)
g3dvl:
cd ${GALLIUMDIR}/state_trackers/g3dvl; ${MAKE}
depend: $(SOURCES) Makefile
$(RM) depend
touch depend
$(MKDEP) $(MKDEP_OPTIONS) $(DEFINES) $(INCLUDES) $(SOURCES)
nouveau_winsys:
cd ${GALLIUMDIR}/winsys/g3dvl/nouveau; ${MAKE}
clean: Makefile
$(RM) libXvMCapi.a
$(RM) *.o *~
$(RM) depend depend.bak
clean:
cd ${GALLIUMDIR}/state_trackers/g3dvl; ${MAKE} clean
cd ${GALLIUMDIR}/winsys/g3dvl/nouveau; ${MAKE} clean
rm -rf ${OBJECTS} ${TARGET}
endif
-include depend

21
src/xvmc/SConscript Normal file
View File

@ -0,0 +1,21 @@
Import('*')
if env['platform'] not in ['linux']:
Return()
env = env.Clone()
env.AppendUnique(CPPPATH = [
'#/src/gallium/winsys/g3dvl',
])
XvMCapi = env.StaticLibrary(
target = 'XvMCapi',
source = [
'block.c',
'surface.c',
'context.c',
'subpicture.c',
'attributes.c',
],
)

View File

@ -1,20 +1,19 @@
#include <assert.h>
#include <X11/Xlib.h>
#include <X11/extensions/Xvlib.h>
#include <X11/extensions/XvMC.h>
#include <X11/extensions/XvMClib.h>
XvAttribute* XvMCQueryAttributes(Display *display, XvMCContext *context, int *number)
XvAttribute* XvMCQueryAttributes(Display *dpy, XvMCContext *context, int *number)
{
return NULL;
return NULL;
}
Status XvMCSetAttribute(Display *display, XvMCContext *context, Atom attribute, int value)
Status XvMCSetAttribute(Display *dpy, XvMCContext *context, Atom attribute, int value)
{
return BadImplementation;
return BadImplementation;
}
Status XvMCGetAttribute(Display *display, XvMCContext *context, Atom attribute, int *value)
Status XvMCGetAttribute(Display *dpy, XvMCContext *context, Atom attribute, int *value)
{
return BadImplementation;
return BadImplementation;
}

View File

@ -1,79 +1,61 @@
#include <assert.h>
#include <X11/Xlib.h>
#include <X11/extensions/XvMC.h>
#include <X11/extensions/XvMClib.h>
#include <util/u_memory.h>
#include <vl_display.h>
#include <vl_screen.h>
#include <vl_context.h>
#include "xvmc_private.h"
#define BLOCK_SIZE (64 * 2)
Status XvMCCreateBlocks(Display *display, XvMCContext *context, unsigned int num_blocks, XvMCBlockArray *blocks)
Status XvMCCreateBlocks(Display *dpy, XvMCContext *context, unsigned int num_blocks, XvMCBlockArray *blocks)
{
struct vlContext *vl_ctx;
assert(dpy);
assert(display);
if (!context)
return XvMCBadContext;
if (num_blocks == 0)
return BadValue;
if (!context)
return XvMCBadContext;
if (num_blocks == 0)
return BadValue;
assert(blocks);
assert(blocks);
blocks->context_id = context->context_id;
blocks->num_blocks = num_blocks;
blocks->blocks = MALLOC(BLOCK_SIZE_BYTES * num_blocks);
blocks->privData = NULL;
vl_ctx = context->privData;
assert(display == vlGetNativeDisplay(vlGetDisplay(vlContextGetScreen(vl_ctx))));
blocks->context_id = context->context_id;
blocks->num_blocks = num_blocks;
blocks->blocks = MALLOC(BLOCK_SIZE * num_blocks);
/* Since we don't have a VL type for blocks, set privData to the display so we can catch mismatches */
blocks->privData = display;
return Success;
return Success;
}
Status XvMCDestroyBlocks(Display *display, XvMCBlockArray *blocks)
Status XvMCDestroyBlocks(Display *dpy, XvMCBlockArray *blocks)
{
assert(display);
assert(blocks);
assert(display == blocks->privData);
FREE(blocks->blocks);
assert(dpy);
assert(blocks);
FREE(blocks->blocks);
return Success;
return Success;
}
Status XvMCCreateMacroBlocks(Display *display, XvMCContext *context, unsigned int num_blocks, XvMCMacroBlockArray *blocks)
Status XvMCCreateMacroBlocks(Display *dpy, XvMCContext *context, unsigned int num_blocks, XvMCMacroBlockArray *blocks)
{
struct vlContext *vl_ctx;
assert(dpy);
assert(display);
if (!context)
return XvMCBadContext;
if (num_blocks == 0)
return BadValue;
if (!context)
return XvMCBadContext;
if (num_blocks == 0)
return BadValue;
assert(blocks);
assert(blocks);
blocks->context_id = context->context_id;
blocks->num_blocks = num_blocks;
blocks->macro_blocks = MALLOC(sizeof(XvMCMacroBlock) * num_blocks);
blocks->privData = NULL;
vl_ctx = context->privData;
assert(display == vlGetNativeDisplay(vlGetDisplay(vlContextGetScreen(vl_ctx))));
blocks->context_id = context->context_id;
blocks->num_blocks = num_blocks;
blocks->macro_blocks = MALLOC(sizeof(XvMCMacroBlock) * num_blocks);
/* Since we don't have a VL type for blocks, set privData to the display so we can catch mismatches */
blocks->privData = display;
return Success;
return Success;
}
Status XvMCDestroyMacroBlocks(Display *display, XvMCMacroBlockArray *blocks)
Status XvMCDestroyMacroBlocks(Display *dpy, XvMCMacroBlockArray *blocks)
{
assert(display);
assert(blocks);
assert(display == blocks->privData);
FREE(blocks->macro_blocks);
assert(dpy);
assert(blocks);
FREE(blocks->macro_blocks);
return Success;
return Success;
}

View File

@ -1,210 +1,203 @@
#include <assert.h>
#include <X11/Xlib.h>
#include <X11/extensions/XvMClib.h>
#include <X11/Xlibint.h>
#include <pipe/p_context.h>
#include <vl_display.h>
#include <vl_screen.h>
#include <vl_context.h>
#include <X11/extensions/XvMClib.h>
#include <pipe/p_screen.h>
#include <pipe/p_video_context.h>
#include <pipe/p_video_state.h>
#include <pipe/p_state.h>
#include <vl_winsys.h>
#include <util/u_memory.h>
#include "xvmc_private.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
)
static Status Validate(Display *dpy, XvPortID port, int surface_type_id,
unsigned int width, unsigned int height, int flags,
bool *found_port, int *screen, 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;
bool found_surface = false;
XvAdaptorInfo *adaptor_info;
unsigned int num_adaptors;
int num_types;
unsigned int max_width, max_height;
Status ret;
assert(display && chroma_format);
assert(dpy);
assert(found_port);
assert(screen);
assert(chroma_format);
assert(mc_type);
*found_port = 0;
*found_port = false;
ret = XvQueryAdaptors(display, XDefaultRootWindow(display), &num_adaptors, &adaptor_info);
if (ret != Success)
return ret;
for (unsigned int i = 0; i < XScreenCount(dpy); ++i)
{
ret = XvQueryAdaptors(dpy, XRootWindow(dpy, i), &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;
for (unsigned int j = 0; j < num_adaptors && !*found_port; ++j)
{
for (unsigned int k = 0; k < adaptor_info[j].num_ports && !*found_port; ++k)
{
XvMCSurfaceInfo *surface_info;
*found_port = 1;
surface_info = XvMCListSurfaceTypes(display, adaptor_info[i].base_id, &num_types);
if (adaptor_info[j].base_id + k != port)
continue;
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;
}
}
*found_port = true;
XFree(surface_info);
}
else
{
XvFreeAdaptorInfo(adaptor_info);
return BadAlloc;
}
}
}
}
surface_info = XvMCListSurfaceTypes(dpy, adaptor_info[j].base_id, &num_types);
if (!surface_info)
{
XvFreeAdaptorInfo(adaptor_info);
return BadAlloc;
}
XvFreeAdaptorInfo(adaptor_info);
for (unsigned int l = 0; l < num_types && !found_surface; ++l)
{
if (surface_info[l].surface_type_id != surface_type_id)
continue;
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;
found_surface = true;
max_width = surface_info[l].max_width;
max_height = surface_info[l].max_height;
*chroma_format = surface_info[l].chroma_format;
*mc_type = surface_info[l].mc_type;
*screen = i;
}
return Success;
XFree(surface_info);
}
}
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)
static enum pipe_video_profile ProfileToPipe(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);
if (xvmc_profile & XVMC_MPEG_1)
assert(0);
if (xvmc_profile & XVMC_MPEG_2)
return PIPE_VIDEO_PROFILE_MPEG2_MAIN;
if (xvmc_profile & XVMC_H263)
assert(0);
if (xvmc_profile & XVMC_MPEG_4)
assert(0);
assert(0);
return -1;
return -1;
}
static enum vlEntryPoint EntryToVL(int xvmc_entry)
static enum pipe_video_chroma_format FormatToPipe(int xvmc_format)
{
return xvmc_entry & XVMC_IDCT ? vlEntryPointIDCT : vlEntryPointMC;
switch (xvmc_format)
{
case XVMC_CHROMA_FORMAT_420:
return PIPE_VIDEO_CHROMA_FORMAT_420;
case XVMC_CHROMA_FORMAT_422:
return PIPE_VIDEO_CHROMA_FORMAT_422;
case XVMC_CHROMA_FORMAT_444:
return PIPE_VIDEO_CHROMA_FORMAT_444;
default:
assert(0);
}
return -1;
}
static enum vlFormat FormatToVL(int xvmc_format)
Status XvMCCreateContext(Display *dpy, XvPortID port, int surface_type_id,
int width, int height, int flags, XvMCContext *context)
{
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);
}
bool found_port;
int scrn;
int chroma_format;
int mc_type;
Status ret;
struct pipe_screen *screen;
struct pipe_video_context *vpipe;
XvMCContextPrivate *context_priv;
return -1;
assert(dpy);
if (!context)
return XvMCBadContext;
ret = Validate(dpy, port, surface_type_id, width, height, flags,
&found_port, &scrn, &chroma_format, &mc_type);
/* Success and XvBadPort have the same value */
if (ret != Success || !found_port)
return ret;
context_priv = CALLOC(1, sizeof(XvMCContextPrivate));
if (!context_priv)
return BadAlloc;
/* TODO: Reuse screen if process creates another context */
screen = vl_screen_create(dpy, scrn);
if (!screen)
{
FREE(context_priv);
return BadAlloc;
}
vpipe = vl_video_create(screen, ProfileToPipe(mc_type),
FormatToPipe(chroma_format), width, height);
if (!vpipe)
{
screen->destroy(screen);
FREE(context_priv);
return BadAlloc;
}
context_priv->vpipe = vpipe;
context->context_id = XAllocID(dpy);
context->surface_type_id = surface_type_id;
context->width = width;
context->height = height;
context->flags = flags;
context->port = port;
context->privData = context_priv;
SyncHandle();
return Success;
}
Status XvMCCreateContext(Display *display, XvPortID port, int surface_type_id, int width, int height, int flags, XvMCContext *context)
Status XvMCDestroyContext(Display *dpy, 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;
Display *dpy = display;
struct pipe_screen *screen;
struct pipe_video_context *vpipe;
XvMCContextPrivate *context_priv;
assert(display);
assert(dpy);
if (!context)
return XvMCBadContext;
if (!context || !context->privData)
return XvMCBadContext;
ret = Validate(display, port, surface_type_id, width, height, flags, &found_port, &chroma_format, &mc_type);
context_priv = context->privData;
vpipe = context_priv->vpipe;
pipe_surface_reference(&context_priv->backbuffer, NULL);
screen = vpipe->screen;
vpipe->destroy(vpipe);
screen->destroy(screen);
FREE(context_priv);
context->privData = NULL;
/* 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;
SyncHandle();
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;
return Success;
}

View File

@ -1,218 +1,168 @@
#include <assert.h>
#include <X11/Xlib.h>
#include <X11/extensions/Xvlib.h>
#include <X11/extensions/XvMC.h>
#include <X11/Xlibint.h>
#include <X11/extensions/XvMClib.h>
Status XvMCCreateSubpicture
(
Display *display,
XvMCContext *context,
XvMCSubpicture *subpicture,
unsigned short width,
unsigned short height,
int xvimage_id
)
Status XvMCCreateSubpicture(Display *dpy, XvMCContext *context, XvMCSubpicture *subpicture,
unsigned short width, unsigned short height, int xvimage_id)
{
Display *dpy = display;
assert(display);
if (!context)
return XvMCBadContext;
assert(subpicture);
if (width > 2048 || height > 2048)
return BadValue;
if (xvimage_id != 123)
return BadMatch;
subpicture->subpicture_id = XAllocID(display);
subpicture->context_id = context->context_id;
subpicture->xvimage_id = xvimage_id;
subpicture->width = width;
subpicture->height = height;
subpicture->num_palette_entries = 0;
subpicture->entry_bytes = 0;
subpicture->component_order[0] = 0;
subpicture->component_order[1] = 0;
subpicture->component_order[2] = 0;
subpicture->component_order[3] = 0;
/* TODO: subpicture->privData = ;*/
assert(dpy);
SyncHandle();
return Success;
if (!context)
return XvMCBadContext;
assert(subpicture);
/*if (width > || height > )
return BadValue;*/
/*if (xvimage_id != )
return BadMatch;*/
subpicture->subpicture_id = XAllocID(dpy);
subpicture->context_id = context->context_id;
subpicture->xvimage_id = xvimage_id;
subpicture->width = width;
subpicture->height = height;
subpicture->num_palette_entries = 0;
subpicture->entry_bytes = 0;
subpicture->component_order[0] = 0;
subpicture->component_order[1] = 0;
subpicture->component_order[2] = 0;
subpicture->component_order[3] = 0;
/* TODO: subpicture->privData = ;*/
SyncHandle();
return Success;
}
Status XvMCClearSubpicture
(
Display *display,
XvMCSubpicture *subpicture,
short x,
short y,
unsigned short width,
unsigned short height,
unsigned int color
)
Status XvMCClearSubpicture(Display *dpy, XvMCSubpicture *subpicture, short x, short y,
unsigned short width, unsigned short height, unsigned int color)
{
assert(display);
if (!subpicture)
return XvMCBadSubpicture;
/* TODO: Assert clear rect is within bounds? Or clip? */
return Success;
assert(dpy);
if (!subpicture)
return XvMCBadSubpicture;
/* TODO: Assert clear rect is within bounds? Or clip? */
return Success;
}
Status XvMCCompositeSubpicture
(
Display *display,
XvMCSubpicture *subpicture,
XvImage *image,
short srcx,
short srcy,
unsigned short width,
unsigned short height,
short dstx,
short dsty
)
Status XvMCCompositeSubpicture(Display *dpy, XvMCSubpicture *subpicture, XvImage *image,
short srcx, short srcy, unsigned short width, unsigned short height,
short dstx, short dsty)
{
assert(display);
if (!subpicture)
return XvMCBadSubpicture;
assert(image);
if (subpicture->xvimage_id != image->id)
return BadMatch;
/* TODO: Assert rects are within bounds? Or clip? */
return Success;
assert(dpy);
if (!subpicture)
return XvMCBadSubpicture;
assert(image);
if (subpicture->xvimage_id != image->id)
return BadMatch;
/* TODO: Assert rects are within bounds? Or clip? */
return Success;
}
Status XvMCDestroySubpicture(Display *display, XvMCSubpicture *subpicture)
Status XvMCDestroySubpicture(Display *dpy, XvMCSubpicture *subpicture)
{
assert(display);
if (!subpicture)
return XvMCBadSubpicture;
return BadImplementation;
assert(dpy);
if (!subpicture)
return XvMCBadSubpicture;
return BadImplementation;
}
Status XvMCSetSubpicturePalette(Display *display, XvMCSubpicture *subpicture, unsigned char *palette)
Status XvMCSetSubpicturePalette(Display *dpy, XvMCSubpicture *subpicture, unsigned char *palette)
{
assert(display);
if (!subpicture)
return XvMCBadSubpicture;
assert(palette);
/* We don't support paletted subpictures */
return BadMatch;
assert(dpy);
if (!subpicture)
return XvMCBadSubpicture;
assert(palette);
/* We don't support paletted subpictures */
return BadMatch;
}
Status XvMCBlendSubpicture
(
Display *display,
XvMCSurface *target_surface,
XvMCSubpicture *subpicture,
short subx,
short suby,
unsigned short subw,
unsigned short subh,
short surfx,
short surfy,
unsigned short surfw,
unsigned short surfh
)
Status XvMCBlendSubpicture(Display *dpy, XvMCSurface *target_surface, XvMCSubpicture *subpicture,
short subx, short suby, unsigned short subw, unsigned short subh,
short surfx, short surfy, unsigned short surfw, unsigned short surfh)
{
assert(display);
if (!target_surface)
return XvMCBadSurface;
if (!subpicture)
return XvMCBadSubpicture;
if (target_surface->context_id != subpicture->context_id)
return BadMatch;
/* TODO: Assert rects are within bounds? Or clip? */
return Success;
assert(dpy);
if (!target_surface)
return XvMCBadSurface;
if (!subpicture)
return XvMCBadSubpicture;
if (target_surface->context_id != subpicture->context_id)
return BadMatch;
/* TODO: Assert rects are within bounds? Or clip? */
return Success;
}
Status XvMCBlendSubpicture2
(
Display *display,
XvMCSurface *source_surface,
XvMCSurface *target_surface,
XvMCSubpicture *subpicture,
short subx,
short suby,
unsigned short subw,
unsigned short subh,
short surfx,
short surfy,
unsigned short surfw,
unsigned short surfh
)
Status XvMCBlendSubpicture2(Display *dpy, XvMCSurface *source_surface, XvMCSurface *target_surface,
XvMCSubpicture *subpicture, short subx, short suby, unsigned short subw, unsigned short subh,
short surfx, short surfy, unsigned short surfw, unsigned short surfh)
{
assert(display);
if (!source_surface || !target_surface)
return XvMCBadSurface;
if (!subpicture)
return XvMCBadSubpicture;
if (source_surface->context_id != subpicture->context_id)
return BadMatch;
if (source_surface->context_id != subpicture->context_id)
return BadMatch;
/* TODO: Assert rects are within bounds? Or clip? */
return Success;
assert(dpy);
if (!source_surface || !target_surface)
return XvMCBadSurface;
if (!subpicture)
return XvMCBadSubpicture;
if (source_surface->context_id != subpicture->context_id)
return BadMatch;
if (source_surface->context_id != subpicture->context_id)
return BadMatch;
/* TODO: Assert rects are within bounds? Or clip? */
return Success;
}
Status XvMCSyncSubpicture(Display *display, XvMCSubpicture *subpicture)
Status XvMCSyncSubpicture(Display *dpy, XvMCSubpicture *subpicture)
{
assert(display);
if (!subpicture)
return XvMCBadSubpicture;
return Success;
assert(dpy);
if (!subpicture)
return XvMCBadSubpicture;
return Success;
}
Status XvMCFlushSubpicture(Display *display, XvMCSubpicture *subpicture)
Status XvMCFlushSubpicture(Display *dpy, XvMCSubpicture *subpicture)
{
assert(display);
if (!subpicture)
return XvMCBadSubpicture;
return Success;
assert(dpy);
if (!subpicture)
return XvMCBadSubpicture;
return Success;
}
Status XvMCGetSubpictureStatus(Display *display, XvMCSubpicture *subpicture, int *status)
Status XvMCGetSubpictureStatus(Display *dpy, XvMCSubpicture *subpicture, int *status)
{
assert(display);
if (!subpicture)
return XvMCBadSubpicture;
assert(status);
/* TODO */
*status = 0;
return Success;
}
assert(dpy);
if (!subpicture)
return XvMCBadSubpicture;
assert(status);
/* TODO */
*status = 0;
return Success;
}

View File

@ -1,290 +1,369 @@
#include <assert.h>
#include <X11/Xlib.h>
#include <X11/extensions/XvMC.h>
#include <X11/Xlibint.h>
#include <vl_display.h>
#include <vl_screen.h>
#include <vl_context.h>
#include <vl_surface.h>
#include <vl_types.h>
#include <pipe/p_video_context.h>
#include <pipe/p_video_state.h>
#include <pipe/p_state.h>
#include <util/u_memory.h>
#include "xvmc_private.h"
static enum vlMacroBlockType TypeToVL(int xvmc_mb_type)
static enum pipe_mpeg12_macroblock_type TypeToPipe(int xvmc_mb_type)
{
if (xvmc_mb_type & XVMC_MB_TYPE_INTRA)
return vlMacroBlockTypeIntra;
if ((xvmc_mb_type & (XVMC_MB_TYPE_MOTION_FORWARD | XVMC_MB_TYPE_MOTION_BACKWARD)) == XVMC_MB_TYPE_MOTION_FORWARD)
return vlMacroBlockTypeFwdPredicted;
if ((xvmc_mb_type & (XVMC_MB_TYPE_MOTION_FORWARD | XVMC_MB_TYPE_MOTION_BACKWARD)) == XVMC_MB_TYPE_MOTION_BACKWARD)
return vlMacroBlockTypeBkwdPredicted;
if ((xvmc_mb_type & (XVMC_MB_TYPE_MOTION_FORWARD | XVMC_MB_TYPE_MOTION_BACKWARD)) == (XVMC_MB_TYPE_MOTION_FORWARD | XVMC_MB_TYPE_MOTION_BACKWARD))
return vlMacroBlockTypeBiPredicted;
if (xvmc_mb_type & XVMC_MB_TYPE_INTRA)
return PIPE_MPEG12_MACROBLOCK_TYPE_INTRA;
if ((xvmc_mb_type & (XVMC_MB_TYPE_MOTION_FORWARD | XVMC_MB_TYPE_MOTION_BACKWARD)) == XVMC_MB_TYPE_MOTION_FORWARD)
return PIPE_MPEG12_MACROBLOCK_TYPE_FWD;
if ((xvmc_mb_type & (XVMC_MB_TYPE_MOTION_FORWARD | XVMC_MB_TYPE_MOTION_BACKWARD)) == XVMC_MB_TYPE_MOTION_BACKWARD)
return PIPE_MPEG12_MACROBLOCK_TYPE_BKWD;
if ((xvmc_mb_type & (XVMC_MB_TYPE_MOTION_FORWARD | XVMC_MB_TYPE_MOTION_BACKWARD)) == (XVMC_MB_TYPE_MOTION_FORWARD | XVMC_MB_TYPE_MOTION_BACKWARD))
return PIPE_MPEG12_MACROBLOCK_TYPE_BI;
assert(0);
assert(0);
return -1;
return -1;
}
static enum vlPictureType PictureToVL(int xvmc_pic)
static enum pipe_mpeg12_picture_type PictureToPipe(int xvmc_pic)
{
switch (xvmc_pic)
{
case XVMC_TOP_FIELD:
return vlPictureTypeTopField;
case XVMC_BOTTOM_FIELD:
return vlPictureTypeBottomField;
case XVMC_FRAME_PICTURE:
return vlPictureTypeFrame;
default:
assert(0);
}
switch (xvmc_pic)
{
case XVMC_TOP_FIELD:
return PIPE_MPEG12_PICTURE_TYPE_FIELD_TOP;
case XVMC_BOTTOM_FIELD:
return PIPE_MPEG12_PICTURE_TYPE_FIELD_BOTTOM;
case XVMC_FRAME_PICTURE:
return PIPE_MPEG12_PICTURE_TYPE_FRAME;
default:
assert(0);
}
return -1;
return -1;
}
static enum vlMotionType MotionToVL(int xvmc_motion_type, int xvmc_dct_type)
static enum pipe_mpeg12_motion_type MotionToPipe(int xvmc_motion_type, int xvmc_dct_type)
{
switch (xvmc_motion_type)
{
case XVMC_PREDICTION_FRAME:
return xvmc_dct_type == XVMC_DCT_TYPE_FIELD ? vlMotionType16x8 : vlMotionTypeFrame;
case XVMC_PREDICTION_FIELD:
return vlMotionTypeField;
case XVMC_PREDICTION_DUAL_PRIME:
return vlMotionTypeDualPrime;
default:
assert(0);
}
switch (xvmc_motion_type)
{
case XVMC_PREDICTION_FRAME:
return xvmc_dct_type == XVMC_DCT_TYPE_FIELD ?
PIPE_MPEG12_MOTION_TYPE_16x8 : PIPE_MPEG12_MOTION_TYPE_FRAME;
case XVMC_PREDICTION_FIELD:
return PIPE_MPEG12_MOTION_TYPE_FIELD;
case XVMC_PREDICTION_DUAL_PRIME:
return PIPE_MPEG12_MOTION_TYPE_DUALPRIME;
default:
assert(0);
}
return -1;
return -1;
}
Status XvMCCreateSurface(Display *display, XvMCContext *context, XvMCSurface *surface)
static bool
CreateOrResizeBackBuffer(struct pipe_video_context *vpipe, unsigned int width, unsigned int height,
struct pipe_surface **backbuffer)
{
struct vlContext *vl_ctx;
struct vlSurface *vl_sfc;
Display *dpy = display;
struct pipe_texture template;
struct pipe_texture *tex;
assert(display);
assert(vpipe);
if (!context)
return XvMCBadContext;
if (!surface)
return XvMCBadSurface;
if (*backbuffer)
{
if ((*backbuffer)->width != width || (*backbuffer)->height != height)
pipe_surface_reference(backbuffer, NULL);
else
return true;
}
vl_ctx = context->privData;
memset(&template, 0, sizeof(struct pipe_texture));
template.target = PIPE_TEXTURE_2D;
/* XXX: Needs to match the drawable's format? */
template.format = PIPE_FORMAT_X8R8G8B8_UNORM;
template.last_level = 0;
template.width[0] = width;
template.height[0] = height;
template.depth[0] = 1;
pf_get_block(template.format, &template.block);
template.tex_usage = PIPE_TEXTURE_USAGE_DISPLAY_TARGET;
assert(display == vlGetNativeDisplay(vlGetDisplay(vlContextGetScreen(vl_ctx))));
tex = vpipe->screen->texture_create(vpipe->screen, &template);
if (!tex)
return false;
if (vlCreateSurface(vlContextGetScreen(vl_ctx),
context->width, context->height,
vlGetPictureFormat(vl_ctx),
&vl_sfc))
{
return BadAlloc;
}
*backbuffer = vpipe->screen->get_tex_surface(vpipe->screen, tex, 0, 0, 0,
PIPE_BUFFER_USAGE_GPU_READ |
PIPE_BUFFER_USAGE_GPU_WRITE);
pipe_texture_reference(&tex, NULL);
vlBindToContext(vl_sfc, vl_ctx);
if (!*backbuffer)
return false;
surface->surface_id = XAllocID(display);
surface->context_id = context->context_id;
surface->surface_type_id = context->surface_type_id;
surface->width = context->width;
surface->height = context->height;
surface->privData = vl_sfc;
/* Clear the backbuffer in case the video doesn't cover the whole window */
/* FIXME: Need to clear every time a frame moves and leaves dirty rects */
vpipe->clear_surface(vpipe, 0, 0, width, height, 0, *backbuffer);
SyncHandle();
return Success;
return true;
}
Status XvMCRenderSurface
(
Display *display,
XvMCContext *context,
unsigned int picture_structure,
XvMCSurface *target_surface,
XvMCSurface *past_surface,
XvMCSurface *future_surface,
unsigned int flags,
unsigned int num_macroblocks,
unsigned int first_macroblock,
XvMCMacroBlockArray *macroblocks,
XvMCBlockArray *blocks
static void
MacroBlocksToPipe(const XvMCMacroBlockArray *xvmc_macroblocks,
const XvMCBlockArray *xvmc_blocks,
unsigned int first_macroblock,
unsigned int num_macroblocks,
struct pipe_mpeg12_macroblock *pipe_macroblocks)
{
unsigned int i, j, k, l;
XvMCMacroBlock *xvmc_mb;
assert(xvmc_macroblocks);
assert(xvmc_blocks);
assert(pipe_macroblocks);
assert(num_macroblocks);
xvmc_mb = xvmc_macroblocks->macro_blocks + first_macroblock;
for (i = 0; i < num_macroblocks; ++i)
{
pipe_macroblocks->base.codec = PIPE_VIDEO_CODEC_MPEG12;
pipe_macroblocks->mbx = xvmc_mb->x;
pipe_macroblocks->mby = xvmc_mb->y;
pipe_macroblocks->mb_type = TypeToPipe(xvmc_mb->macroblock_type);
if (pipe_macroblocks->mb_type != PIPE_MPEG12_MACROBLOCK_TYPE_INTRA)
pipe_macroblocks->mo_type = MotionToPipe(xvmc_mb->motion_type, xvmc_mb->dct_type);
/* Get rid of Valgrind 'undefined' warnings */
else
pipe_macroblocks->mo_type = -1;
pipe_macroblocks->dct_type = xvmc_mb->dct_type == XVMC_DCT_TYPE_FIELD ?
PIPE_MPEG12_DCT_TYPE_FIELD : PIPE_MPEG12_DCT_TYPE_FRAME;
for (j = 0; j < 2; ++j)
for (k = 0; k < 2; ++k)
for (l = 0; l < 2; ++l)
pipe_macroblocks->pmv[j][k][l] = xvmc_mb->PMV[j][k][l];
pipe_macroblocks->cbp = xvmc_mb->coded_block_pattern;
pipe_macroblocks->blocks = xvmc_blocks->blocks + xvmc_mb->index * BLOCK_SIZE_SAMPLES;
++pipe_macroblocks;
++xvmc_mb;
}
}
Status XvMCCreateSurface(Display *dpy, XvMCContext *context, XvMCSurface *surface)
{
XvMCContextPrivate *context_priv;
struct pipe_video_context *vpipe;
XvMCSurfacePrivate *surface_priv;
struct pipe_video_surface *vsfc;
assert(dpy);
if (!context)
return XvMCBadContext;
if (!surface)
return XvMCBadSurface;
context_priv = context->privData;
vpipe = context_priv->vpipe;
surface_priv = CALLOC(1, sizeof(XvMCSurfacePrivate));
if (!surface_priv)
return BadAlloc;
vsfc = vpipe->screen->video_surface_create(vpipe->screen, vpipe->chroma_format,
vpipe->width, vpipe->height);
if (!vsfc)
{
FREE(surface_priv);
return BadAlloc;
}
surface_priv->pipe_vsfc = vsfc;
surface_priv->context = context;
surface->surface_id = XAllocID(dpy);
surface->context_id = context->context_id;
surface->surface_type_id = context->surface_type_id;
surface->width = context->width;
surface->height = context->height;
surface->privData = surface_priv;
SyncHandle();
return Success;
}
Status XvMCRenderSurface(Display *dpy, XvMCContext *context, unsigned int picture_structure,
XvMCSurface *target_surface, XvMCSurface *past_surface, XvMCSurface *future_surface,
unsigned int flags, unsigned int num_macroblocks, unsigned int first_macroblock,
XvMCMacroBlockArray *macroblocks, XvMCBlockArray *blocks
)
{
struct vlContext *vl_ctx;
struct vlSurface *target_vl_surface;
struct vlSurface *past_vl_surface;
struct vlSurface *future_vl_surface;
struct vlMpeg2MacroBlockBatch batch;
struct vlMpeg2MacroBlock vl_macroblocks[num_macroblocks];
unsigned int i;
struct pipe_video_context *vpipe;
struct pipe_surface *t_vsfc;
struct pipe_surface *p_vsfc;
struct pipe_surface *f_vsfc;
XvMCContextPrivate *context_priv;
XvMCSurfacePrivate *target_surface_priv;
XvMCSurfacePrivate *past_surface_priv;
XvMCSurfacePrivate *future_surface_priv;
struct pipe_mpeg12_macroblock pipe_macroblocks[num_macroblocks];
assert(display);
assert(dpy);
if (!context)
return XvMCBadContext;
if (!target_surface)
return XvMCBadSurface;
if (!context || !context->privData)
return XvMCBadContext;
if (!target_surface || !target_surface->privData)
return XvMCBadSurface;
if
(
picture_structure != XVMC_TOP_FIELD &&
picture_structure != XVMC_BOTTOM_FIELD &&
picture_structure != XVMC_FRAME_PICTURE
)
return BadValue;
if (future_surface && !past_surface)
return BadMatch;
if (picture_structure != XVMC_TOP_FIELD &&
picture_structure != XVMC_BOTTOM_FIELD &&
picture_structure != XVMC_FRAME_PICTURE)
return BadValue;
/* Bkwd pred equivalent to fwd (past && !future) */
if (future_surface && !past_surface)
return BadMatch;
vl_ctx = context->privData;
assert(context->context_id == target_surface->context_id);
assert(!past_surface || context->context_id == past_surface->context_id);
assert(!future_surface || context->context_id == future_surface->context_id);
assert(display == vlGetNativeDisplay(vlGetDisplay(vlContextGetScreen(vl_ctx))));
assert(macroblocks);
assert(blocks);
target_vl_surface = target_surface->privData;
past_vl_surface = past_surface ? past_surface->privData : NULL;
future_vl_surface = future_surface ? future_surface->privData : NULL;
assert(macroblocks->context_id == context->context_id);
assert(blocks->context_id == context->context_id);
assert(context->context_id == target_surface->context_id);
assert(!past_surface || context->context_id == past_surface->context_id);
assert(!future_surface || context->context_id == future_surface->context_id);
assert(flags == 0 || flags == XVMC_SECOND_FIELD);
assert(macroblocks);
assert(blocks);
target_surface_priv = target_surface->privData;
past_surface_priv = past_surface ? past_surface->privData : NULL;
future_surface_priv = future_surface ? future_surface->privData : NULL;
assert(macroblocks->context_id == context->context_id);
assert(blocks->context_id == context->context_id);
assert(target_surface_priv->context == context);
assert(!past_surface || past_surface_priv->context == context);
assert(!future_surface || future_surface_priv->context == context);
assert(flags == 0 || flags == XVMC_SECOND_FIELD);
context_priv = context->privData;
vpipe = context_priv->vpipe;
batch.past_surface = past_vl_surface;
batch.future_surface = future_vl_surface;
batch.picture_type = PictureToVL(picture_structure);
batch.field_order = flags & XVMC_SECOND_FIELD ? vlFieldOrderSecond : vlFieldOrderFirst;
batch.num_macroblocks = num_macroblocks;
batch.macroblocks = vl_macroblocks;
t_vsfc = target_surface_priv->pipe_vsfc;
p_vsfc = past_surface ? past_surface_priv->pipe_vsfc : NULL;
f_vsfc = future_surface ? future_surface_priv->pipe_vsfc : NULL;
for (i = 0; i < num_macroblocks; ++i)
{
unsigned int j = first_macroblock + i;
MacroBlocksToPipe(macroblocks, blocks, first_macroblock,
num_macroblocks, pipe_macroblocks);
unsigned int k, l, m;
vpipe->set_decode_target(vpipe, t_vsfc);
vpipe->decode_macroblocks(vpipe, p_vsfc, f_vsfc, num_macroblocks,
&pipe_macroblocks->base, target_surface_priv->render_fence);
batch.macroblocks[i].mbx = macroblocks->macro_blocks[j].x;
batch.macroblocks[i].mby = macroblocks->macro_blocks[j].y;
batch.macroblocks[i].mb_type = TypeToVL(macroblocks->macro_blocks[j].macroblock_type);
if (batch.macroblocks[i].mb_type != vlMacroBlockTypeIntra)
batch.macroblocks[i].mo_type = MotionToVL(macroblocks->macro_blocks[j].motion_type, macroblocks->macro_blocks[j].dct_type);
batch.macroblocks[i].dct_type = macroblocks->macro_blocks[j].dct_type == XVMC_DCT_TYPE_FIELD ? vlDCTTypeFieldCoded : vlDCTTypeFrameCoded;
for (k = 0; k < 2; ++k)
for (l = 0; l < 2; ++l)
for (m = 0; m < 2; ++m)
batch.macroblocks[i].PMV[k][l][m] = macroblocks->macro_blocks[j].PMV[k][l][m];
batch.macroblocks[i].cbp = macroblocks->macro_blocks[j].coded_block_pattern;
batch.macroblocks[i].blocks = blocks->blocks + (macroblocks->macro_blocks[j].index * 64);
}
vlRenderMacroBlocksMpeg2(&batch, target_vl_surface);
return Success;
return Success;
}
Status XvMCFlushSurface(Display *display, XvMCSurface *surface)
Status XvMCFlushSurface(Display *dpy, XvMCSurface *surface)
{
#if 0
struct vlSurface *vl_sfc;
assert(display);
assert(dpy);
if (!surface)
return XvMCBadSurface;
vl_sfc = surface->privData;
assert(display == vlGetNativeDisplay(vlGetDisplay(vlSurfaceGetScreen(vl_sfc))));
vlSurfaceFlush(vl_sfc);
return Success;
#endif
return Success;
}
Status XvMCSyncSurface(Display *display, XvMCSurface *surface)
Status XvMCSyncSurface(Display *dpy, XvMCSurface *surface)
{
#if 0
struct vlSurface *vl_sfc;
assert(display);
assert(dpy);
if (!surface)
return XvMCBadSurface;
vl_sfc = surface->privData;
assert(display == vlGetNativeDisplay(vlGetDisplay(vlSurfaceGetScreen(vl_sfc))));
vlSurfaceSync(vl_sfc);
return Success;
#endif
return Success;
}
Status XvMCPutSurface
(
Display *display,
XvMCSurface *surface,
Drawable drawable,
short srcx,
short srcy,
unsigned short srcw,
unsigned short srch,
short destx,
short desty,
unsigned short destw,
unsigned short desth,
int flags
)
Status XvMCPutSurface(Display *dpy, XvMCSurface *surface, Drawable drawable,
short srcx, short srcy, unsigned short srcw, unsigned short srch,
short destx, short desty, unsigned short destw, unsigned short desth,
int flags)
{
Window root;
int x, y;
unsigned int width, height;
unsigned int border_width;
unsigned int depth;
struct vlSurface *vl_sfc;
Window root;
int x, y;
unsigned int width, height;
unsigned int border_width;
unsigned int depth;
struct pipe_video_context *vpipe;
XvMCSurfacePrivate *surface_priv;
XvMCContextPrivate *context_priv;
XvMCContext *context;
struct pipe_video_rect src_rect = {srcx, srcy, srcw, srch};
struct pipe_video_rect dst_rect = {destx, desty, destw, desth};
assert(display);
assert(dpy);
if (!surface)
return XvMCBadSurface;
if (!surface || !surface->privData)
return XvMCBadSurface;
if (XGetGeometry(display, drawable, &root, &x, &y, &width, &height, &border_width, &depth) == BadDrawable)
return BadDrawable;
if (XGetGeometry(dpy, drawable, &root, &x, &y, &width, &height, &border_width, &depth) == BadDrawable)
return BadDrawable;
assert(flags == XVMC_TOP_FIELD || flags == XVMC_BOTTOM_FIELD || flags == XVMC_FRAME_PICTURE);
assert(flags == XVMC_TOP_FIELD || flags == XVMC_BOTTOM_FIELD || flags == XVMC_FRAME_PICTURE);
assert(srcx + srcw - 1 < surface->width);
assert(srcy + srch - 1 < surface->height);
/*
* Some apps (mplayer) hit these asserts because they call
* this function after the window has been resized by the WM
* but before they've handled the corresponding XEvent and
* know about the new dimensions. The output should be clipped
* until the app updates destw and desth.
*/
/*
assert(destx + destw - 1 < width);
assert(desty + desth - 1 < height);
*/
/* TODO: Correct for negative srcx,srcy & destx,desty by clipping */
surface_priv = surface->privData;
context = surface_priv->context;
context_priv = context->privData;
vpipe = context_priv->vpipe;
assert(srcx + srcw - 1 < surface->width);
assert(srcy + srch - 1 < surface->height);
/* XXX: Some apps (mplayer) hit these asserts because they call
* this function after the window has been resized by the WM
* but before they've handled the corresponding XEvent and
* know about the new dimensions. The output will be clipped
* for a few frames until the app updates destw and desth.
*/
/*assert(destx + destw - 1 < width);
assert(desty + desth - 1 < height);*/
if (!CreateOrResizeBackBuffer(vpipe, width, height, &context_priv->backbuffer))
return BadAlloc;
vl_sfc = surface->privData;
vpipe->render_picture(vpipe, surface_priv->pipe_vsfc, PictureToPipe(flags), &src_rect,
context_priv->backbuffer, &dst_rect, surface_priv->disp_fence);
vlPutPicture(vl_sfc, drawable, srcx, srcy, srcw, srch, destx, desty, destw, desth, width, height, PictureToVL(flags));
vl_video_bind_drawable(vpipe, drawable);
vpipe->screen->flush_frontbuffer
(
vpipe->screen,
context_priv->backbuffer,
vpipe->priv
);
return Success;
return Success;
}
Status XvMCGetSurfaceStatus(Display *display, XvMCSurface *surface, int *status)
Status XvMCGetSurfaceStatus(Display *dpy, XvMCSurface *surface, int *status)
{
#if 0
struct vlSurface *vl_sfc;
enum vlResourceStatus res_status;
assert(display);
assert(dpy);
if (!surface)
return XvMCBadSurface;
@ -293,8 +372,6 @@ Status XvMCGetSurfaceStatus(Display *display, XvMCSurface *surface, int *status)
vl_sfc = surface->privData;
assert(display == vlGetNativeDisplay(vlGetDisplay(vlSurfaceGetScreen(vl_sfc))));
vlSurfaceGetStatus(vl_sfc, &res_status);
switch (res_status)
@ -317,42 +394,36 @@ Status XvMCGetSurfaceStatus(Display *display, XvMCSurface *surface, int *status)
default:
assert(0);
}
return Success;
#endif
*status = 0;
return Success;
}
Status XvMCDestroySurface(Display *display, XvMCSurface *surface)
Status XvMCDestroySurface(Display *dpy, XvMCSurface *surface)
{
struct vlSurface *vl_sfc;
XvMCSurfacePrivate *surface_priv;
assert(display);
assert(dpy);
if (!surface)
return XvMCBadSurface;
if (!surface || !surface->privData)
return XvMCBadSurface;
vl_sfc = surface->privData;
surface_priv = surface->privData;
pipe_video_surface_reference(&surface_priv->pipe_vsfc, NULL);
FREE(surface_priv);
surface->privData = NULL;
assert(display == vlGetNativeDisplay(vlGetDisplay(vlSurfaceGetScreen(vl_sfc))));
vlDestroySurface(vl_sfc);
return Success;
return Success;
}
Status XvMCHideSurface(Display *display, XvMCSurface *surface)
Status XvMCHideSurface(Display *dpy, XvMCSurface *surface)
{
struct vlSurface *vl_sfc;
assert(dpy);
assert(display);
if (!surface || !surface->privData)
return XvMCBadSurface;
if (!surface)
return XvMCBadSurface;
/* No op, only for overlaid rendering */
vl_sfc = surface->privData;
assert(display == vlGetNativeDisplay(vlGetDisplay(vlSurfaceGetScreen(vl_sfc))));
/* No op, only for overlaid rendering */
return Success;
return Success;
}

View File

@ -1,27 +1,28 @@
CFLAGS += -g -Wall
LDFLAGS +=
LIBS += -lXvMCW -lXvMC -lXv
TOP = ../../..
include $(TOP)/configs/current
LIBS = -lXvMCW -lXvMC -lXv -lX11
#############################################
.PHONY = all clean
.PHONY: default clean
all: test_context test_surface test_blocks test_rendering xvmc_bench
default: test_context test_surface test_blocks test_rendering xvmc_bench
test_context: test_context.o testlib.o
$(CC) ${LDFLAGS} -o $@ $^ ${LIBS}
$(CC) $(LDFLAGS) -o $@ $^ $(LIBS)
test_surface: test_surface.o testlib.o
$(CC) ${LDFLAGS} -o $@ $^ ${LIBS}
$(CC) $(LDFLAGS) -o $@ $^ $(LIBS)
test_blocks: test_blocks.o testlib.o
$(CC) ${LDFLAGS} -o $@ $^ ${LIBS}
$(CC) $(LDFLAGS) -o $@ $^ $(LIBS)
test_rendering: test_rendering.o testlib.o
$(CC) ${LDFLAGS} -o $@ $^ ${LIBS}
$(CC) $(LDFLAGS) -o $@ $^ $(LIBS)
xvmc_bench: xvmc_bench.o testlib.o
$(CC) ${LDFLAGS} -o $@ $^ ${LIBS}
$(CC) $(LDFLAGS) -o $@ $^ $(LIBS)
clean:
rm -rf *.o test_context test_surface test_blocks test_rendering xvmc_bench
$(RM) -rf *.o test_context test_surface test_blocks test_rendering xvmc_bench

View File

@ -23,6 +23,9 @@
#define DEFAULT_OUTPUT_HEIGHT INPUT_HEIGHT
#define DEFAULT_ACCEPTABLE_ERR 0.01
void ParseArgs(int argc, char **argv, unsigned int *output_width, unsigned int *output_height, double *acceptable_error, int *prompt);
void Gradient(short *block, unsigned int start, unsigned int stop, int horizontal);
void ParseArgs(int argc, char **argv, unsigned int *output_width, unsigned int *output_height, double *acceptable_error, int *prompt)
{
int fail = 0;

View File

@ -6,7 +6,7 @@ int main(int argc, char **argv)
{
const unsigned int width = 16, height = 16;
const unsigned int mc_types[2] = {XVMC_MOCOMP | XVMC_MPEG_2, XVMC_IDCT | XVMC_MPEG_2};
Display *display;
XvPortID port_num;
int surface_type_id;
@ -14,9 +14,9 @@ int main(int argc, char **argv)
int colorkey;
XvMCContext context;
XvMCSurface surface = {0};
display = XOpenDisplay(NULL);
if (!GetPort
(
display,
@ -34,15 +34,15 @@ int main(int argc, char **argv)
XCloseDisplay(display);
error(1, 0, "Error, unable to find a good port.\n");
}
if (is_overlay)
{
Atom xv_colorkey = XInternAtom(display, "XV_COLORKEY", 0);
XvGetPortAttribute(display, port_num, xv_colorkey, &colorkey);
}
assert(XvMCCreateContext(display, port_num, surface_type_id, width, height, XVMC_DIRECT, &context) == Success);
/* Test NULL context */
assert(XvMCCreateSurface(display, NULL, &surface) == XvMCBadContext);
/* Test NULL surface */
@ -61,12 +61,11 @@ int main(int argc, char **argv)
assert(XvMCDestroySurface(display, &surface) == Success);
/* Test NULL surface */
assert(XvMCDestroySurface(display, NULL) == XvMCBadSurface);
assert(XvMCDestroyContext(display, &context) == Success);
XvUngrabPort(display, port_num, CurrentTime);
XCloseDisplay(display);
return 0;
}

View File

@ -32,6 +32,8 @@ struct Config
unsigned int reps;
};
void ParseArgs(int argc, char **argv, struct Config *config);
void ParseArgs(int argc, char **argv, struct Config *config)
{
int fail = 0;

31
src/xvmc/xvmc_private.h Normal file
View File

@ -0,0 +1,31 @@
#ifndef xvmc_private_h
#define xvmc_private_h
#include <X11/Xlib.h>
#include <X11/extensions/XvMClib.h>
#define BLOCK_SIZE_SAMPLES 64
#define BLOCK_SIZE_BYTES (BLOCK_SIZE_SAMPLES * 2)
struct pipe_video_context;
struct pipe_surface;
struct pipe_fence_handle;
typedef struct
{
struct pipe_video_context *vpipe;
struct pipe_surface *backbuffer;
} XvMCContextPrivate;
typedef struct
{
struct pipe_video_surface *pipe_vsfc;
struct pipe_fence_handle *render_fence;
struct pipe_fence_handle *disp_fence;
/* Some XvMC functions take a surface but not a context,
so we keep track of which context each surface belongs to. */
XvMCContext *context;
} XvMCSurfacePrivate;
#endif /* xvmc_private_h */