From e44c85637a3298918e292e9ddba812856cf92924 Mon Sep 17 00:00:00 2001 From: Younes Manton Date: Sun, 27 Sep 2009 20:18:02 -0400 Subject: [PATCH] g3dvl: Implement XvMC using pipe_video_context. --- src/gallium/winsys/g3dvl/Makefile | 11 + src/gallium/winsys/g3dvl/vl_winsys.h | 21 +- src/gallium/winsys/g3dvl/xlib/Makefile | 74 +++ src/gallium/winsys/g3dvl/xlib/xsp_winsys.c | 307 ++++++++++++ src/xvmc/Makefile | 90 ++-- src/xvmc/SConscript | 21 + src/xvmc/attributes.c | 15 +- src/xvmc/block.c | 90 ++-- src/xvmc/context.c | 345 +++++++------- src/xvmc/subpicture.c | 320 ++++++------- src/xvmc/surface.c | 529 ++++++++++++--------- src/xvmc/tests/Makefile | 23 +- src/xvmc/tests/test_rendering.c | 3 + src/xvmc/tests/test_surface.c | 19 +- src/xvmc/tests/xvmc_bench.c | 2 + src/xvmc/xvmc_private.h | 31 ++ 16 files changed, 1163 insertions(+), 738 deletions(-) create mode 100644 src/gallium/winsys/g3dvl/Makefile create mode 100644 src/gallium/winsys/g3dvl/xlib/Makefile create mode 100644 src/gallium/winsys/g3dvl/xlib/xsp_winsys.c create mode 100644 src/xvmc/SConscript create mode 100644 src/xvmc/xvmc_private.h diff --git a/src/gallium/winsys/g3dvl/Makefile b/src/gallium/winsys/g3dvl/Makefile new file mode 100644 index 00000000000..424ddea87ad --- /dev/null +++ b/src/gallium/winsys/g3dvl/Makefile @@ -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 diff --git a/src/gallium/winsys/g3dvl/vl_winsys.h b/src/gallium/winsys/g3dvl/vl_winsys.h index c83db28dd98..4f7a2433612 100644 --- a/src/gallium/winsys/g3dvl/vl_winsys.h +++ b/src/gallium/winsys/g3dvl/vl_winsys.h @@ -2,13 +2,22 @@ #define vl_winsys_h #include +#include +#include -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 - diff --git a/src/gallium/winsys/g3dvl/xlib/Makefile b/src/gallium/winsys/g3dvl/xlib/Makefile new file mode 100644 index 00000000000..d4cbf0e2bba --- /dev/null +++ b/src/gallium/winsys/g3dvl/xlib/Makefile @@ -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 diff --git a/src/gallium/winsys/g3dvl/xlib/xsp_winsys.c b/src/gallium/winsys/g3dvl/xlib/xsp_winsys.c new file mode 100644 index 00000000000..37eee79c5d3 --- /dev/null +++ b/src/gallium/winsys/g3dvl/xlib/xsp_winsys.c @@ -0,0 +1,307 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* 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; +} diff --git a/src/xvmc/Makefile b/src/xvmc/Makefile index 7badcfd2645..e7636e65c60 100644 --- a/src/xvmc/Makefile +++ b/src/xvmc/Makefile @@ -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 diff --git a/src/xvmc/SConscript b/src/xvmc/SConscript new file mode 100644 index 00000000000..53e04183e40 --- /dev/null +++ b/src/xvmc/SConscript @@ -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', + ], +) diff --git a/src/xvmc/attributes.c b/src/xvmc/attributes.c index 674524b8b82..638da0b5775 100644 --- a/src/xvmc/attributes.c +++ b/src/xvmc/attributes.c @@ -1,20 +1,19 @@ #include #include #include -#include +#include -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; } - diff --git a/src/xvmc/block.c b/src/xvmc/block.c index b38a89be092..78fddfb79e0 100644 --- a/src/xvmc/block.c +++ b/src/xvmc/block.c @@ -1,79 +1,61 @@ #include #include -#include +#include #include -#include -#include -#include +#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; } diff --git a/src/xvmc/context.c b/src/xvmc/context.c index 9c2b6648bb5..33f47838f51 100644 --- a/src/xvmc/context.c +++ b/src/xvmc/context.c @@ -1,210 +1,203 @@ #include -#include -#include #include -#include -#include -#include -#include +#include +#include +#include +#include +#include #include +#include +#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; } diff --git a/src/xvmc/subpicture.c b/src/xvmc/subpicture.c index 09e9c98e6af..78ba618f5ab 100644 --- a/src/xvmc/subpicture.c +++ b/src/xvmc/subpicture.c @@ -1,218 +1,168 @@ #include -#include -#include -#include #include +#include -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; +} diff --git a/src/xvmc/surface.c b/src/xvmc/surface.c index fea351b84f0..0467c4d07d9 100644 --- a/src/xvmc/surface.c +++ b/src/xvmc/surface.c @@ -1,290 +1,369 @@ #include -#include -#include #include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#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; } diff --git a/src/xvmc/tests/Makefile b/src/xvmc/tests/Makefile index de095161d29..11b2e1a812b 100644 --- a/src/xvmc/tests/Makefile +++ b/src/xvmc/tests/Makefile @@ -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 diff --git a/src/xvmc/tests/test_rendering.c b/src/xvmc/tests/test_rendering.c index 1e7467a3aa6..6d720dfcdca 100644 --- a/src/xvmc/tests/test_rendering.c +++ b/src/xvmc/tests/test_rendering.c @@ -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; diff --git a/src/xvmc/tests/test_surface.c b/src/xvmc/tests/test_surface.c index 25ebdcc4fcf..06948201ac9 100644 --- a/src/xvmc/tests/test_surface.c +++ b/src/xvmc/tests/test_surface.c @@ -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; } - diff --git a/src/xvmc/tests/xvmc_bench.c b/src/xvmc/tests/xvmc_bench.c index d5a39ecf17d..97adcfc58a8 100644 --- a/src/xvmc/tests/xvmc_bench.c +++ b/src/xvmc/tests/xvmc_bench.c @@ -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; diff --git a/src/xvmc/xvmc_private.h b/src/xvmc/xvmc_private.h new file mode 100644 index 00000000000..1e3dd561c66 --- /dev/null +++ b/src/xvmc/xvmc_private.h @@ -0,0 +1,31 @@ +#ifndef xvmc_private_h +#define xvmc_private_h + +#include +#include + +#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 */