diff options
author | Christian König <[email protected]> | 2011-07-13 22:56:06 +0200 |
---|---|---|
committer | Christian König <[email protected]> | 2011-07-13 22:56:06 +0200 |
commit | ed24e19070b7dff12670151b2d184f31c845ccae (patch) | |
tree | 98b47585f9223ee95cbbf541e6434598d9439491 /src/gallium/state_trackers | |
parent | 85e1fa55066783d2748993810708dee6db7a4993 (diff) | |
parent | a2a6799fbefc6900f2371efab778c5bc2bf5a6e9 (diff) |
Merge branch 'pipe-video'
Diffstat (limited to 'src/gallium/state_trackers')
42 files changed, 7029 insertions, 0 deletions
diff --git a/src/gallium/state_trackers/va/Makefile b/src/gallium/state_trackers/va/Makefile new file mode 100644 index 00000000000..d5b3ec3caf2 --- /dev/null +++ b/src/gallium/state_trackers/va/Makefile @@ -0,0 +1,28 @@ +TOP = ../../../.. +include $(TOP)/configs/current + +LIBNAME = vatracker + +VA_MAJOR = 0 +VA_MINOR = 3 +LIBRARY_DEFINES = -DVER_MAJOR=$(VA_MAJOR) -DVER_MINOR=$(VA_MINOR) $(STATE_TRACKER_DEFINES) + +LIBRARY_INCLUDES = \ + $(shell pkg-config --cflags-only-I libva) \ + -I$(TOP)/src/gallium/winsys/g3dvl + +C_SOURCES = htab.c \ + ftab.c \ + va_context.c \ + va_image.c \ + va_subpicture.c \ + va_buffer.c \ + va_config.c \ + va_picture.c \ + va_surface.c \ + va_display.c + + + +include ../../Makefile.template + diff --git a/src/gallium/state_trackers/va/ftab.c b/src/gallium/state_trackers/va/ftab.c new file mode 100644 index 00000000000..dc9513e2d7c --- /dev/null +++ b/src/gallium/state_trackers/va/ftab.c @@ -0,0 +1,136 @@ +/************************************************************************** + * + * Copyright 2010 Thomas Balling Sørensen & Orasanu Lucian. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include <assert.h> + +#include <va/va.h> +#include <va/va_backend.h> + +#include "va_private.h" + +static struct VADriverVTable vtable = +{ + &vlVaTerminate, /* VAStatus (*vaTerminate) ( VADriverContextP ctx ); */ + &vlVaQueryConfigProfiles, /* VAStatus (*vaQueryConfigProfiles) ( VADriverContextP ctx, VAProfile *profile_list,int *num_profiles); */ + &vlVaQueryConfigEntrypoints, /* VAStatus (*vaQueryConfigEntrypoints) ( VADriverContextP ctx, VAProfile profile, VAEntrypoint *entrypoint_list, int *num_entrypoints ); */ + &vlVaGetConfigAttributes, /* VAStatus (*vaGetConfigAttributes) ( VADriverContextP ctx, VAProfile profile, VAEntrypoint entrypoint, VAConfigAttrib *attrib_list, int num_attribs ); */ + &vlVaCreateConfig, /* VAStatus (*vaCreateConfig) ( VADriverContextP ctx, VAProfile profile, VAEntrypoint entrypoint, VAConfigAttrib *attrib_list, int num_attribs, VAConfigID *config_id); */ + &vlVaDestroyConfig, /* VAStatus (*vaDestroyConfig) ( VADriverContextP ctx, VAConfigID config_id); */ + &vlVaQueryConfigAttributes, /* VAStatus (*vaQueryConfigAttributes) ( VADriverContextP ctx, VAConfigID config_id, VAProfile *profile, VAEntrypoint *entrypoint, VAConfigAttrib *attrib_list, int *num_attribs); */ + &vlVaCreateSurfaces, /* VAStatus (*vaCreateSurfaces) ( VADriverContextP ctx,int width,int height,int format,int num_surfaces,VASurfaceID *surfaces); */ + &vlVaDestroySurfaces, /* VAStatus (*vaDestroySurfaces) ( VADriverContextP ctx, VASurfaceID *surface_list, int num_surfaces ); */ + &vlVaCreateContext, /* VAStatus (*vaCreateContext) (VADriverContextP ctx,VAConfigID config_id,int picture_width,int picture_height,int flag,VASurfaceID *render_targets,int num_render_targets,VAContextID *context); */ + &vlVaDestroyContext, /* VAStatus (*vaDestroyContext) (VADriverContextP ctx,VAContextID context); */ + &vlVaCreateBuffer, /* VAStatus (*vaCreateBuffer) (VADriverContextP ctx,VAContextID context,VABufferType type,unsigned int size,unsigned int num_elements,void *data,VABufferID *buf_id); */ + &vlVaBufferSetNumElements, /* VAStatus (*vaBufferSetNumElements) (VADriverContextP ctx,VABufferID buf_id,unsigned int num_elements); */ + &vlVaMapBuffer, /* VAStatus (*vaMapBuffer) (VADriverContextP ctx,VABufferID buf_id,void **pbuf); */ + &vlVaUnmapBuffer, /* VAStatus (*vaUnmapBuffer) (VADriverContextP ctx,VABufferID buf_id); */ + &vlVaDestroyBuffer, /* VAStatus (*vaDestroyBuffer) (VADriverContextP ctx,VABufferID buffer_id); */ + &vlVaBeginPicture, /* VAStatus (*vaBeginPicture) (VADriverContextP ctx,VAContextID context,VASurfaceID render_target); */ + &vlVaRenderPicture, /* VAStatus (*vaRenderPicture) (VADriverContextP ctx,VAContextID context,VABufferID *buffers,int num_buffers); */ + &vlVaEndPicture, /* VAStatus (*vaEndPicture) (VADriverContextP ctx,VAContextID context); */ + &vlVaSyncSurface, /* VAStatus (*vaSyncSurface) (VADriverContextP ctx,VASurfaceID render_target); */ + &vlVaQuerySurfaceStatus, /* VAStatus (*vaQuerySurfaceStatus) (VADriverContextP ctx,VASurfaceID render_target,VASurfaceStatus *status); */ + &vlVaPutSurface, /* VAStatus (*vaPutSurface) ( + VADriverContextP ctx, + VASurfaceID surface, + void* draw, + short srcx, + short srcy, + unsigned short srcw, + unsigned short srch, + short destx, + short desty, + unsigned short destw, + unsigned short desth, + VARectangle *cliprects, + unsigned int number_cliprects, + unsigned int flags); */ + &vlVaQueryImageFormats, /* VAStatus (*vaQueryImageFormats) ( VADriverContextP ctx, VAImageFormat *format_list,int *num_formats); */ + &vlVaCreateImage, /* VAStatus (*vaCreateImage) (VADriverContextP ctx,VAImageFormat *format,int width,int height,VAImage *image); */ + &vlVaDeriveImage, /* VAStatus (*vaDeriveImage) (VADriverContextP ctx,VASurfaceID surface,VAImage *image); */ + &vlVaDestroyImage, /* VAStatus (*vaDestroyImage) (VADriverContextP ctx,VAImageID image); */ + &vlVaSetImagePalette, /* VAStatus (*vaSetImagePalette) (VADriverContextP ctx,VAImageID image, unsigned char *palette); */ + &vlVaGetImage, /* VAStatus (*vaGetImage) (VADriverContextP ctx,VASurfaceID surface,int x,int y,unsigned int width,unsigned int height,VAImageID image); */ + &vlVaPutImage, /* VAStatus (*vaPutImage) ( + VADriverContextP ctx, + VASurfaceID surface, + VAImageID image, + int src_x, + int src_y, + unsigned int src_width, + unsigned int src_height, + int dest_x, + int dest_y, + unsigned int dest_width, + unsigned int dest_height + ); */ + &vlVaQuerySubpictureFormats, /* VAStatus (*vaQuerySubpictureFormats) (VADriverContextP ctx,VAImageFormat *format_list,unsigned int *flags,unsigned int *num_formats); */ + &vlVaCreateSubpicture, /* VAStatus (*vaCreateSubpicture) (VADriverContextP ctx,VAImageID image,VASubpictureID *subpicture); */ + &vlVaDestroySubpicture, /* VAStatus (*vaDestroySubpicture) (VADriverContextP ctx,VASubpictureID subpicture); */ + &vlVaSubpictureImage, /* VAStatus (*vaSetSubpictureImage) (VADriverContextP ctx,VASubpictureID subpicture,VAImageID image); */ + &vlVaSetSubpictureChromakey, /* VAStatus (*vaSetSubpictureChromakey) (VADriverContextP ctx,VASubpictureID subpicture,unsigned int chromakey_min,unsigned int chromakey_max,unsigned int chromakey_mask); */ + &vlVaSetSubpictureGlobalAlpha, /* VAStatus (*vaSetSubpictureGlobalAlpha) (VADriverContextP ctx,VASubpictureID subpicture,float global_alpha); */ + &vlVaAssociateSubpicture, /* VAStatus (*vaAssociateSubpicture) ( + VADriverContextP ctx, + VASubpictureID subpicture, + VASurfaceID *target_surfaces, + int num_surfaces, + short src_x, + short src_y, + unsigned short src_width, + unsigned short src_height, + short dest_x, + short dest_y, + unsigned short dest_width, + unsigned short dest_height, + unsigned int flags); */ + &vlVaDeassociateSubpicture, /* VAStatus (*vaDeassociateSubpicture) (VADriverContextP ctx,VASubpictureID subpicture,VASurfaceID *target_surfaces,int num_surfaces); */ + &vlVaQueryDisplayAttributes, /* VAStatus (*vaQueryDisplayAttributes) (VADriverContextP ctx,VADisplayAttribute *attr_list,int *num_attributes); */ + &vlVaGetDisplayAttributes, /* VAStatus (*vaGetDisplayAttributes) (VADriverContextP ctx,VADisplayAttribute *attr_list,int num_attributes); */ + &vlVaSetDisplayAttributes, /* VAStatus (*vaSetDisplayAttributes) (VADriverContextP ctx,VADisplayAttribute *attr_list,int num_attributes); */ + &vlVaBufferInfo, /* VAStatus (*vaBufferInfo) (VADriverContextP ctx,VAContextID context,VABufferID buf_id,VABufferType *type,unsigned int *size,unsigned int *num_elements); */ + &vlVaLockSurface, /* VAStatus (*vaLockSurface) ( + VADriverContextP ctx, + VASurfaceID surface, + unsigned int *fourcc, + unsigned int *luma_stride, + unsigned int *chroma_u_stride, + unsigned int *chroma_v_stride, + unsigned int *luma_offset, + unsigned int *chroma_u_offset, + unsigned int *chroma_v_offset, + unsigned int *buffer_name, + void **buffer); */ + &vlVaUnlockSurface, /* VAStatus (*vaUnlockSurface) (VADriverContextP ctx,VASurfaceID surface); */ + NULL /* struct VADriverVTableGLX *glx; "Optional" */ +}; + +struct VADriverVTable vlVaGetVtable() +{ + return vtable; +} diff --git a/src/gallium/state_trackers/va/htab.c b/src/gallium/state_trackers/va/htab.c new file mode 100644 index 00000000000..40b9edac819 --- /dev/null +++ b/src/gallium/state_trackers/va/htab.c @@ -0,0 +1,95 @@ +/************************************************************************** + * + * Copyright 2010 Younes Manton. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include <util/u_handle_table.h> +#include <os/os_thread.h> + +#include "va_private.h" + +#ifdef VL_HANDLES +static struct handle_table *htab = NULL; +pipe_static_mutex(htab_lock); +#endif + +bool vlCreateHTAB(void) +{ +#ifdef VL_HANDLES + bool ret; + /* Make sure handle table handles match VAAPI handles. */ + assert(sizeof(unsigned) <= sizeof(VAGenericID)); + pipe_mutex_lock(htab_lock); + if (!htab) + htab = handle_table_create(); + ret = htab != NULL; + pipe_mutex_unlock(htab_lock); + return ret; +#else + return TRUE; +#endif +} + +void vlDestroyHTAB(void) +{ +#ifdef VL_HANDLES + pipe_mutex_lock(htab_lock); + if (htab) { + handle_table_destroy(htab); + htab = NULL; + } + pipe_mutex_unlock(htab_lock); +#endif +} + +VAGenericID vlAddDataHTAB(void *data) +{ + assert(data); +#ifdef VL_HANDLES + VAGenericID handle = 0; + pipe_mutex_lock(htab_lock); + if (htab) + handle = handle_table_add(htab, data); + pipe_mutex_unlock(htab_lock); + return handle; +#else + return (VAGenericID)data; +#endif +} + +void* vlGetDataHTAB(VAGenericID handle) +{ + assert(handle); +#ifdef VL_HANDLES + void *data = NULL; + pipe_mutex_lock(htab_lock); + if (htab) + data = handle_table_get(htab, handle); + pipe_mutex_unlock(htab_lock); + return data; +#else + return (void*)handle; +#endif +} diff --git a/src/gallium/state_trackers/va/va_buffer.c b/src/gallium/state_trackers/va/va_buffer.c new file mode 100644 index 00000000000..d14e06d69e4 --- /dev/null +++ b/src/gallium/state_trackers/va/va_buffer.c @@ -0,0 +1,88 @@ +/************************************************************************** + * + * Copyright 2010 Thomas Balling Sørensen & Orasanu Lucian. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include <va/va.h> +#include <va/va_backend.h> + +#include "va_private.h" + +VAStatus +vlVaCreateBuffer(VADriverContextP ctx, VAContextID context, VABufferType type, + unsigned int size, unsigned int num_elements, void *data, + VABufferID *buf_id) +{ + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + return VA_STATUS_ERROR_UNIMPLEMENTED; +} + +VAStatus +vlVaBufferSetNumElements(VADriverContextP ctx, VABufferID buf_id, unsigned int num_elements) +{ + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + return VA_STATUS_ERROR_UNIMPLEMENTED; +} + +VAStatus +vlVaMapBuffer(VADriverContextP ctx, VABufferID buf_id, void **pbuff) +{ + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + return VA_STATUS_ERROR_UNIMPLEMENTED; +} + +VAStatus +vlVaUnmapBuffer(VADriverContextP ctx, VABufferID buf_id) +{ + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + return VA_STATUS_ERROR_UNIMPLEMENTED; +} + +VAStatus +vlVaDestroyBuffer(VADriverContextP ctx, VABufferID buffer_id) +{ + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + return VA_STATUS_ERROR_UNIMPLEMENTED; +} + +VAStatus +vlVaBufferInfo(VADriverContextP ctx, VAContextID context, VABufferID buf_id, + VABufferType *type, unsigned int *size, unsigned int *num_elements) +{ + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + return VA_STATUS_ERROR_UNIMPLEMENTED; +} diff --git a/src/gallium/state_trackers/va/va_config.c b/src/gallium/state_trackers/va/va_config.c new file mode 100644 index 00000000000..6f1cb78bb53 --- /dev/null +++ b/src/gallium/state_trackers/va/va_config.c @@ -0,0 +1,121 @@ +/************************************************************************** + * + * Copyright 2010 Thomas Balling Sørensen & Orasanu Lucian. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include <va/va.h> +#include <va/va_backend.h> + +#include <util/u_debug.h> + +#include "va_private.h" + +VAStatus +vlVaQueryConfigProfiles(VADriverContextP ctx, VAProfile *profile_list, int *num_profiles) +{ + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + int i = 0; + + profile_list[i++] = VAProfileMPEG2Simple; + *num_profiles = i; + + return VA_STATUS_SUCCESS; +} + + +VAStatus +vlVaQueryConfigEntrypoints(VADriverContextP ctx, VAProfile profile, + VAEntrypoint *entrypoint_list, int *num_entrypoints) +{ + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + VAStatus vaStatus = VA_STATUS_SUCCESS; + + switch (profile) { + case VAProfileMPEG2Simple: + case VAProfileMPEG2Main: + VA_INFO("Using profile %08x\n",profile); + entrypoint_list[0] = VAEntrypointMoComp; + *num_entrypoints = 1; + break; + + case VAProfileH264Baseline: + case VAProfileH264Main: + case VAProfileH264High: + vaStatus = VA_STATUS_ERROR_UNSUPPORTED_PROFILE; + *num_entrypoints = 0; + break; + + default: + VA_ERROR("Unsupported profile %08x\n",profile); + vaStatus = VA_STATUS_ERROR_UNSUPPORTED_PROFILE; + *num_entrypoints = 0; + break; + } + + return vaStatus; +} + +VAStatus +vlVaGetConfigAttributes(VADriverContextP ctx, VAProfile profile, VAEntrypoint entrypoint, + VAConfigAttrib *attrib_list, int num_attribs) +{ + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + return VA_STATUS_ERROR_UNIMPLEMENTED; +} + +VAStatus +vlVaCreateConfig(VADriverContextP ctx, VAProfile profile, VAEntrypoint entrypoint, + VAConfigAttrib *attrib_list, int num_attribs, VAConfigID *config_id) +{ + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + return VA_STATUS_ERROR_UNIMPLEMENTED; +} + +VAStatus +vlVaDestroyConfig(VADriverContextP ctx, VAConfigID config_id) +{ + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + return VA_STATUS_ERROR_UNIMPLEMENTED; +} + +VAStatus +vlVaQueryConfigAttributes(VADriverContextP ctx, VAConfigID config_id, VAProfile *profile, + VAEntrypoint *entrypoint, VAConfigAttrib *attrib_list, int *num_attribs) +{ + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + return VA_STATUS_ERROR_UNIMPLEMENTED; +} diff --git a/src/gallium/state_trackers/va/va_context.c b/src/gallium/state_trackers/va/va_context.c new file mode 100644 index 00000000000..62ba3d24ae3 --- /dev/null +++ b/src/gallium/state_trackers/va/va_context.c @@ -0,0 +1,106 @@ +/************************************************************************** + * + * Copyright 2010 Thomas Balling Sørensen & Orasanu Lucian. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include <va/va.h> +#include <va/va_backend.h> + +#include <pipe/p_screen.h> +#include <pipe/p_screen.h> +#include <pipe/p_video_decoder.h> + +#include <util/u_debug.h> +#include <util/u_memory.h> + +#include <vl_winsys.h> + +#include "va_private.h" + +PUBLIC VAStatus +__vaDriverInit_0_31(VADriverContextP ctx) +{ + vlVaDriverContextPriv *driver_context = NULL; + + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + + /* Create private driver context */ + driver_context = CALLOC(1,sizeof(vlVaDriverContextPriv)); + if (!driver_context) + return VA_STATUS_ERROR_ALLOCATION_FAILED; + + driver_context->vscreen = vl_screen_create(ctx->native_dpy, ctx->x11_screen); + if (!driver_context->vscreen) { + FREE(driver_context); + return VA_STATUS_ERROR_ALLOCATION_FAILED; + } + + ctx->str_vendor = "mesa gallium vaapi"; + ctx->vtable = vlVaGetVtable(); + ctx->max_attributes = 1; + ctx->max_display_attributes = 1; + ctx->max_entrypoints = VA_MAX_ENTRYPOINTS; + ctx->max_image_formats = VA_MAX_IMAGE_FORMATS_SUPPORTED; + ctx->max_profiles = 1; + ctx->max_subpic_formats = VA_MAX_SUBPIC_FORMATS_SUPPORTED; + ctx->version_major = 3; + ctx->version_minor = 1; + ctx->pDriverData = (void *)driver_context; + + VA_INFO("vl_screen_pointer %p\n",ctx->native_dpy); + + return VA_STATUS_SUCCESS; +} + +VAStatus +vlVaCreateContext(VADriverContextP ctx, VAConfigID config_id, int picture_width, + int picture_height, int flag, VASurfaceID *render_targets, + int num_render_targets, VAContextID *conext) +{ + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + return VA_STATUS_ERROR_UNIMPLEMENTED; +} + +VAStatus +vlVaDestroyContext(VADriverContextP ctx, VAContextID context) +{ + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + return VA_STATUS_ERROR_UNIMPLEMENTED; +} + +VAStatus +vlVaTerminate(VADriverContextP ctx) +{ + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + return VA_STATUS_ERROR_UNIMPLEMENTED; +} diff --git a/src/gallium/state_trackers/va/va_display.c b/src/gallium/state_trackers/va/va_display.c new file mode 100644 index 00000000000..11116d0c00a --- /dev/null +++ b/src/gallium/state_trackers/va/va_display.c @@ -0,0 +1,63 @@ +/************************************************************************** + * + * Copyright 2010 Thomas Balling Sørensen. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + + #include <va/va.h> + #include <va/va_backend.h> + + #include "va_private.h" + +VAStatus +vlVaQueryDisplayAttributes(VADriverContextP ctx, VADisplayAttribute *attr_list, int *num_attributes) +{ + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + if (!(attr_list && num_attributes)) + return VA_STATUS_ERROR_UNKNOWN; + + *num_attributes = 0; + + return VA_STATUS_SUCCESS; +} + +VAStatus +vlVaGetDisplayAttributes(VADriverContextP ctx, VADisplayAttribute *attr_list, int num_attributes) +{ + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + return VA_STATUS_ERROR_UNIMPLEMENTED; +} + +VAStatus +vlVaSetDisplayAttributes(VADriverContextP ctx, VADisplayAttribute *attr_list, int num_attributes) +{ + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + return VA_STATUS_ERROR_UNIMPLEMENTED; +} diff --git a/src/gallium/state_trackers/va/va_image.c b/src/gallium/state_trackers/va/va_image.c new file mode 100644 index 00000000000..43c3a946737 --- /dev/null +++ b/src/gallium/state_trackers/va/va_image.c @@ -0,0 +1,151 @@ +/************************************************************************** + * + * Copyright 2010 Thomas Balling Sørensen & Orasanu Lucian. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include <va/va.h> +#include <va/va_backend.h> + +#include <pipe/p_format.h> + +#include <util/u_memory.h> +#include <util/u_format.h> +#include <util/u_debug.h> + +#include "va_private.h" + +typedef struct { + enum pipe_format pipe_format; + VAImageFormat va_format; +} va_image_formats_supported_t; + +static const va_image_formats_supported_t va_image_formats_supported[VA_MAX_IMAGE_FORMATS_SUPPORTED] = +{ + { PIPE_FORMAT_B8G8R8A8_UNORM, + { VA_FOURCC('B','G','R','A'), VA_LSB_FIRST, 32, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 }}, + { PIPE_FORMAT_R8G8B8A8_UNORM, + { VA_FOURCC_RGBA, VA_LSB_FIRST, 32, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 }} +}; + +VAStatus +vlVaQueryImageFormats(VADriverContextP ctx, VAImageFormat *format_list, int *num_formats) +{ + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + if (!(format_list && num_formats)) + return VA_STATUS_ERROR_UNKNOWN; + + int n = 0; + + num_formats[0] = VA_MAX_IMAGE_FORMATS_SUPPORTED; + + /* Query supported formats */ + for (n = 0; n < VA_MAX_IMAGE_FORMATS_SUPPORTED; n++) { + format_list[n] = va_image_formats_supported[n].va_format; + } + + return VA_STATUS_SUCCESS; +} + +VAStatus +vlVaCreateImage(VADriverContextP ctx, VAImageFormat *format, int width, int height, VAImage *image) +{ + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + if(!format) + return VA_STATUS_ERROR_UNKNOWN; + + if (!(width && height)) + return VA_STATUS_ERROR_INVALID_IMAGE_FORMAT; + + if (!vlCreateHTAB()) + return VA_STATUS_ERROR_UNKNOWN; + + switch (format->fourcc) { + case VA_FOURCC('B','G','R','A'): + VA_INFO("Creating BGRA image of size %dx%d\n",width,height); + break; + case VA_FOURCC_RGBA: + VA_INFO("Creating RGBA image of size %dx%d\n",width,height); + break; + default: + VA_ERROR("Couldn't create image of type %0x08\n",format->fourcc); + return VA_STATUS_ERROR_UNSUPPORTED_RT_FORMAT; + } + + VA_INFO("Image %p created successfully\n",format); + + return VA_STATUS_SUCCESS; +} + +VAStatus +vlVaDeriveImage(VADriverContextP ctx, VASurfaceID surface, VAImage *image) +{ + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + return VA_STATUS_ERROR_UNIMPLEMENTED; +} + +VAStatus +vlVaDestroyImage(VADriverContextP ctx, VAImageID image) +{ + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + return VA_STATUS_ERROR_UNIMPLEMENTED; +} + +VAStatus +vlVaSetImagePalette(VADriverContextP ctx, VAImageID image, unsigned char *palette) +{ + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + return VA_STATUS_ERROR_UNIMPLEMENTED; +} + +VAStatus +vlVaGetImage(VADriverContextP ctx, VASurfaceID surface, int x, int y, + unsigned int width, unsigned int height, VAImageID image) +{ + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + return VA_STATUS_ERROR_UNIMPLEMENTED; +} + +VAStatus +vlVaPutImage(VADriverContextP ctx, VASurfaceID surface, VAImageID image, + int src_x, int src_y, unsigned int src_width, unsigned int src_height, + int dest_x, int dest_y, unsigned int dest_width, unsigned int dest_height) +{ + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + return VA_STATUS_ERROR_UNIMPLEMENTED; +} diff --git a/src/gallium/state_trackers/va/va_picture.c b/src/gallium/state_trackers/va/va_picture.c new file mode 100644 index 00000000000..3b52a6a7e10 --- /dev/null +++ b/src/gallium/state_trackers/va/va_picture.c @@ -0,0 +1,60 @@ +/************************************************************************** + * + * Copyright 2010 Thomas Balling Sørensen & Orasanu Lucian. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include <va/va.h> +#include <va/va_backend.h> + +#include <util/u_debug.h> + +#include "va_private.h" + +VAStatus +vlVaBeginPicture(VADriverContextP ctx, VAContextID context, VASurfaceID render_target) +{ + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + return VA_STATUS_ERROR_UNIMPLEMENTED; +} + +VAStatus +vlVaRenderPicture(VADriverContextP ctx, VAContextID context, VABufferID *buffers, int num_buffers) +{ + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + return VA_STATUS_ERROR_UNIMPLEMENTED; +} + +VAStatus +vlVaEndPicture(VADriverContextP ctx, VAContextID context) +{ + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + return VA_STATUS_ERROR_UNIMPLEMENTED; +} diff --git a/src/gallium/state_trackers/va/va_private.h b/src/gallium/state_trackers/va/va_private.h new file mode 100644 index 00000000000..f1023dbf87b --- /dev/null +++ b/src/gallium/state_trackers/va/va_private.h @@ -0,0 +1,162 @@ +/************************************************************************** + * + * Copyright 2010 Thomas Balling Sørensen & Orasanu Lucian. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef VA_PRIVATE_H +#define VA_PRIVATE_H + +#include <va/va.h> +#include <va/va_backend.h> + +#include <pipe/p_format.h> +#include <pipe/p_state.h> + +#define VA_DEBUG(_str,...) debug_printf("[Gallium VA backend]: " _str,__VA_ARGS__) +#define VA_INFO(_str,...) VA_DEBUG("INFO: " _str,__VA_ARGS__) +#define VA_WARNING(_str,...) VA_DEBUG("WARNING: " _str,__VA_ARGS__) +#define VA_ERROR(_str,...) VA_DEBUG("ERROR: " _str,__VA_ARGS__) + +#define VA_MAX_IMAGE_FORMATS_SUPPORTED 2 +#define VA_MAX_SUBPIC_FORMATS_SUPPORTED 2 +#define VA_MAX_ENTRYPOINTS 1 + +#define VL_HANDLES + +typedef struct { + struct vl_screen *vscreen; + struct pipe_surface *backbuffer; +} vlVaDriverContextPriv; + +typedef struct { + unsigned int width; + unsigned int height; + enum pipe_video_chroma_format format; + VADriverContextP ctx; +} vlVaSurfacePriv; + +// Public functions: +VAStatus __vaDriverInit_0_31 (VADriverContextP ctx); + +// Private functions: +struct VADriverVTable vlVaGetVtable(); + +bool vlCreateHTAB(void); +void vlDestroyHTAB(void); +VAGenericID vlAddDataHTAB(void *data); +void* vlGetDataHTAB(VAGenericID handle); + +// Vtable functions: +VAStatus vlVaTerminate (VADriverContextP ctx); +VAStatus vlVaQueryConfigProfiles (VADriverContextP ctx, VAProfile *profile_list,int *num_profiles); +VAStatus vlVaQueryConfigEntrypoints (VADriverContextP ctx, VAProfile profile, VAEntrypoint *entrypoint_list, int *num_entrypoints); +VAStatus vlVaGetConfigAttributes (VADriverContextP ctx, VAProfile profile, VAEntrypoint entrypoint, VAConfigAttrib *attrib_list, int num_attribs); +VAStatus vlVaCreateConfig (VADriverContextP ctx, VAProfile profile, VAEntrypoint entrypoint, VAConfigAttrib *attrib_list, int num_attribs, VAConfigID *config_id); +VAStatus vlVaDestroyConfig (VADriverContextP ctx, VAConfigID config_id); +VAStatus vlVaQueryConfigAttributes (VADriverContextP ctx, VAConfigID config_id, VAProfile *profile, VAEntrypoint *entrypoint, VAConfigAttrib *attrib_list, int *num_attribs); +VAStatus vlVaCreateSurfaces (VADriverContextP ctx,int width,int height,int format,int num_surfaces,VASurfaceID *surfaces); +VAStatus vlVaDestroySurfaces (VADriverContextP ctx, VASurfaceID *surface_list, int num_surfaces); +VAStatus vlVaCreateContext (VADriverContextP ctx,VAConfigID config_id,int picture_width,int picture_height,int flag,VASurfaceID *render_targets,int num_render_targets,VAContextID *context); +VAStatus vlVaDestroyContext (VADriverContextP ctx,VAContextID context); +VAStatus vlVaCreateBuffer (VADriverContextP ctx,VAContextID context,VABufferType type,unsigned int size,unsigned int num_elements,void *data,VABufferID *buf_id); +VAStatus vlVaBufferSetNumElements (VADriverContextP ctx,VABufferID buf_id,unsigned int num_elements); +VAStatus vlVaMapBuffer (VADriverContextP ctx,VABufferID buf_id,void **pbuf); +VAStatus vlVaUnmapBuffer (VADriverContextP ctx,VABufferID buf_id); +VAStatus vlVaDestroyBuffer (VADriverContextP ctx,VABufferID buffer_id); +VAStatus vlVaBeginPicture (VADriverContextP ctx,VAContextID context,VASurfaceID render_target); +VAStatus vlVaRenderPicture (VADriverContextP ctx,VAContextID context,VABufferID *buffers,int num_buffers); +VAStatus vlVaEndPicture (VADriverContextP ctx,VAContextID context); +VAStatus vlVaSyncSurface (VADriverContextP ctx,VASurfaceID render_target); +VAStatus vlVaQuerySurfaceStatus (VADriverContextP ctx,VASurfaceID render_target,VASurfaceStatus *status); +VAStatus vlVaPutSurface (VADriverContextP ctx, + VASurfaceID surface, + void* draw, + short srcx, + short srcy, + unsigned short srcw, + unsigned short srch, + short destx, + short desty, + unsigned short destw, + unsigned short desth, + VARectangle *cliprects, + unsigned int number_cliprects, + unsigned int flags); +VAStatus vlVaQueryImageFormats (VADriverContextP ctx,VAImageFormat *format_list,int *num_formats); +VAStatus vlVaQuerySubpictureFormats(VADriverContextP ctx,VAImageFormat *format_list,unsigned int *flags,unsigned int *num_formats); +VAStatus vlVaCreateImage(VADriverContextP ctx,VAImageFormat *format,int width,int height,VAImage *image); +VAStatus vlVaDeriveImage(VADriverContextP ctx,VASurfaceID surface,VAImage *image); +VAStatus vlVaDestroyImage(VADriverContextP ctx,VAImageID image); +VAStatus vlVaSetImagePalette(VADriverContextP ctx,VAImageID image, unsigned char *palette); +VAStatus vlVaGetImage(VADriverContextP ctx,VASurfaceID surface,int x,int y,unsigned int width,unsigned int height,VAImageID image); +VAStatus vlVaPutImage(VADriverContextP ctx, + VASurfaceID surface, + VAImageID image, + int src_x, + int src_y, + unsigned int src_width, + unsigned int src_height, + int dest_x, + int dest_y, + unsigned int dest_width, + unsigned int dest_height); +VAStatus vlVaQuerySubpictureFormats(VADriverContextP ctx,VAImageFormat *format_list,unsigned int *flags,unsigned int *num_formats); +VAStatus vlVaCreateSubpicture(VADriverContextP ctx,VAImageID image,VASubpictureID *subpicture); +VAStatus vlVaDestroySubpicture(VADriverContextP ctx,VASubpictureID subpicture); +VAStatus vlVaSubpictureImage(VADriverContextP ctx,VASubpictureID subpicture,VAImageID image); +VAStatus vlVaSetSubpictureChromakey(VADriverContextP ctx,VASubpictureID subpicture,unsigned int chromakey_min,unsigned int chromakey_max,unsigned int chromakey_mask); +VAStatus vlVaSetSubpictureGlobalAlpha(VADriverContextP ctx,VASubpictureID subpicture,float global_alpha); +VAStatus vlVaAssociateSubpicture(VADriverContextP ctx, + VASubpictureID subpicture, + VASurfaceID *target_surfaces, + int num_surfaces, + short src_x, + short src_y, + unsigned short src_width, + unsigned short src_height, + short dest_x, + short dest_y, + unsigned short dest_width, + unsigned short dest_height, + unsigned int flags); +VAStatus vlVaDeassociateSubpicture(VADriverContextP ctx,VASubpictureID subpicture,VASurfaceID *target_surfaces,int num_surfaces); +VAStatus vlVaQueryDisplayAttributes(VADriverContextP ctx,VADisplayAttribute *attr_list,int *num_attributes); +VAStatus vlVaGetDisplayAttributes(VADriverContextP ctx,VADisplayAttribute *attr_list,int num_attributes); +VAStatus vlVaSetDisplayAttributes(VADriverContextP ctx,VADisplayAttribute *attr_list,int num_attributes); +VAStatus vlVaBufferInfo(VADriverContextP ctx,VAContextID context,VABufferID buf_id,VABufferType *type,unsigned int *size,unsigned int *num_elements); +VAStatus vlVaLockSurface(VADriverContextP ctx, + VASurfaceID surface, + unsigned int *fourcc, + unsigned int *luma_stride, + unsigned int *chroma_u_stride, + unsigned int *chroma_v_stride, + unsigned int *luma_offset, + unsigned int *chroma_u_offset, + unsigned int *chroma_v_offset, + unsigned int *buffer_name, + void **buffer); +VAStatus vlVaUnlockSurface(VADriverContextP ctx,VASurfaceID surface); + +#endif //VA_PRIVATE_H diff --git a/src/gallium/state_trackers/va/va_subpicture.c b/src/gallium/state_trackers/va/va_subpicture.c new file mode 100644 index 00000000000..3f370e5889f --- /dev/null +++ b/src/gallium/state_trackers/va/va_subpicture.c @@ -0,0 +1,143 @@ +/************************************************************************** + * + * Copyright 2010 Thomas Balling Sørensen & Orasanu Lucian. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include <va/va.h> +#include <va/va_backend.h> + +#include <pipe/p_format.h> + +#include "va_private.h" + +typedef struct { + enum pipe_format pipe_format; + VAImageFormat va_format; + unsigned int va_flags; +} va_subpicture_formats_supported_t; + +static const va_subpicture_formats_supported_t va_subpicture_formats_supported[VA_MAX_SUBPIC_FORMATS_SUPPORTED + 1] = +{ + { PIPE_FORMAT_B8G8R8A8_UNORM, + { VA_FOURCC('B','G','R','A'), VA_LSB_FIRST, 32, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000 }, + 0 }, + { PIPE_FORMAT_R8G8B8A8_UNORM, + { VA_FOURCC_RGBA, VA_LSB_FIRST, 32, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000 }, + 0 } +}; + +VAStatus +vlVaQuerySubpictureFormats(VADriverContextP ctx, VAImageFormat *format_list, + unsigned int *flags, unsigned int *num_formats) +{ + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + if (!(format_list && flags && num_formats)) + return VA_STATUS_ERROR_UNKNOWN; + + num_formats[0] = VA_MAX_SUBPIC_FORMATS_SUPPORTED; + + int n = 0; + /* Query supported formats */ + for (n = 0; n < VA_MAX_SUBPIC_FORMATS_SUPPORTED ; n++) { + const va_subpicture_formats_supported_t * const format_map = &va_subpicture_formats_supported[n]; + flags[n] = format_map->va_flags; + format_list[n] = format_map->va_format; + } + + return VA_STATUS_SUCCESS; +} + +VAStatus +vlVaCreateSubpicture(VADriverContextP ctx, VAImageID image, VASubpictureID *subpicture) +{ + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + return VA_STATUS_ERROR_UNIMPLEMENTED; +} + +VAStatus +vlVaDestroySubpicture(VADriverContextP ctx, VASubpictureID subpicture) +{ + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + return VA_STATUS_ERROR_UNIMPLEMENTED; +} + +VAStatus +vlVaSubpictureImage(VADriverContextP ctx, VASubpictureID subpicture, VAImageID image) +{ + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + return VA_STATUS_ERROR_UNIMPLEMENTED; +} + +VAStatus +vlVaSetSubpictureChromakey(VADriverContextP ctx, VASubpictureID subpicture, + unsigned int chromakey_min, unsigned int chromakey_max, unsigned int chromakey_mask) +{ + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + return VA_STATUS_ERROR_UNIMPLEMENTED; +} + +VAStatus +vlVaSetSubpictureGlobalAlpha(VADriverContextP ctx, VASubpictureID subpicture, float global_alpha) +{ + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + return VA_STATUS_ERROR_UNIMPLEMENTED; +} + +VAStatus +vlVaAssociateSubpicture(VADriverContextP ctx, VASubpictureID subpicture, VASurfaceID *target_surfaces, + int num_surfaces, short src_x, short src_y, + unsigned short src_width, unsigned short src_height, + short dest_x, short dest_y, + unsigned short dest_width, + unsigned short dest_height, + unsigned int flags) +{ + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + return VA_STATUS_ERROR_UNIMPLEMENTED; +} + +VAStatus +vlVaDeassociateSubpicture(VADriverContextP ctx, VASubpictureID subpicture, + VASurfaceID *target_surfaces, int num_surfaces) +{ + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + return VA_STATUS_ERROR_UNIMPLEMENTED; +} diff --git a/src/gallium/state_trackers/va/va_surface.c b/src/gallium/state_trackers/va/va_surface.c new file mode 100644 index 00000000000..b7f9732d248 --- /dev/null +++ b/src/gallium/state_trackers/va/va_surface.c @@ -0,0 +1,142 @@ +/************************************************************************** + * + * Copyright 2010 Thomas Balling Sørensen & Orasanu Lucian. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include <va/va.h> +#include <va/va_backend.h> +#include <util/u_debug.h> +#include <util/u_memory.h> +#include "va_private.h" + +static enum pipe_video_chroma_format +VaRTFormatToPipe(unsigned int va_type) +{ + switch (va_type) { + case VA_RT_FORMAT_YUV420: + return PIPE_VIDEO_CHROMA_FORMAT_420; + case VA_RT_FORMAT_YUV422: + return PIPE_VIDEO_CHROMA_FORMAT_422; + case VA_RT_FORMAT_YUV444: + return PIPE_VIDEO_CHROMA_FORMAT_444; + default: + assert(0); + } + + return -1; +} + +VAStatus +vlVaCreateSurfaces(VADriverContextP ctx, int width, int height, int format, + int num_surfaces, VASurfaceID *surfaces) +{ + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + /* We only support one format */ + if (VA_RT_FORMAT_YUV420 != format) + return VA_STATUS_ERROR_UNSUPPORTED_RT_FORMAT; + + if (!(width && height)) + return VA_STATUS_ERROR_INVALID_IMAGE_FORMAT; + + if (!vlCreateHTAB()) + return VA_STATUS_ERROR_UNKNOWN; + + vlVaSurfacePriv *va_surface = (vlVaSurfacePriv *)CALLOC(num_surfaces,sizeof(vlVaSurfacePriv)); + if (!va_surface) + return VA_STATUS_ERROR_ALLOCATION_FAILED; + + int n = 0; + for (n = 0; n < num_surfaces; n++) { + va_surface[n].width = width; + va_surface[n].height = height; + va_surface[n].format = VaRTFormatToPipe(format); + va_surface[n].ctx = ctx; + surfaces[n] = vlAddDataHTAB((void *)(va_surface + n)); + } + + return VA_STATUS_SUCCESS; +} + +VAStatus +vlVaDestroySurfaces(VADriverContextP ctx, VASurfaceID *surface_list, int num_surfaces) +{ + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + return VA_STATUS_ERROR_UNIMPLEMENTED; +} + +VAStatus +vlVaSyncSurface(VADriverContextP ctx, VASurfaceID render_target) +{ + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + return VA_STATUS_ERROR_UNIMPLEMENTED; +} + +VAStatus +vlVaQuerySurfaceStatus(VADriverContextP ctx, VASurfaceID render_target, VASurfaceStatus *status) +{ + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + return VA_STATUS_ERROR_UNIMPLEMENTED; +} + +VAStatus +vlVaPutSurface(VADriverContextP ctx, VASurfaceID surface, void* draw, short srcx, short srcy, + unsigned short srcw, unsigned short srch, short destx, short desty, + unsigned short destw, unsigned short desth, VARectangle *cliprects, + unsigned int number_cliprects, unsigned int flags) +{ + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + return VA_STATUS_ERROR_UNIMPLEMENTED; +} + +VAStatus +vlVaLockSurface(VADriverContextP ctx, VASurfaceID surface, unsigned int *fourcc, + unsigned int *luma_stride, unsigned int *chroma_u_stride, unsigned int *chroma_v_stride, + unsigned int *luma_offset, unsigned int *chroma_u_offset, unsigned int *chroma_v_offset, + unsigned int *buffer_name, void **buffer) +{ + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + return VA_STATUS_ERROR_UNIMPLEMENTED; +} + +VAStatus +vlVaUnlockSurface(VADriverContextP ctx, VASurfaceID surface) +{ + if (!ctx) + return VA_STATUS_ERROR_INVALID_CONTEXT; + + return VA_STATUS_ERROR_UNIMPLEMENTED; +} diff --git a/src/gallium/state_trackers/vdpau/Makefile b/src/gallium/state_trackers/vdpau/Makefile new file mode 100644 index 00000000000..c1fd0eb7d0e --- /dev/null +++ b/src/gallium/state_trackers/vdpau/Makefile @@ -0,0 +1,28 @@ +TOP = ../../../.. +include $(TOP)/configs/current + +LIBNAME = vdpautracker + +VDPAU_MAJOR = 1 +VDPAU_MINOR = 0 +LIBRARY_DEFINES = -DVER_MAJOR=$(VDPAU_MAJOR) -DVER_MINOR=$(VDPAU_MINOR) $(STATE_TRACKER_DEFINES) + +LIBRARY_INCLUDES = \ + $(shell pkg-config --cflags-only-I vdpau) \ + -I$(TOP)/src/gallium/winsys/g3dvl + +C_SOURCES = htab.c \ + ftab.c \ + device.c \ + query.c \ + surface.c \ + decode.c \ + presentation.c \ + bitmap.c \ + output.c \ + preemption.c \ + mixer.c + + +include ../../Makefile.template + diff --git a/src/gallium/state_trackers/vdpau/bitmap.c b/src/gallium/state_trackers/vdpau/bitmap.c new file mode 100644 index 00000000000..e336568df47 --- /dev/null +++ b/src/gallium/state_trackers/vdpau/bitmap.c @@ -0,0 +1,74 @@ +/************************************************************************** + * + * Copyright 2010 Thomas Balling Sørensen. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include <vdpau/vdpau.h> + +#include "vdpau_private.h" + +VdpStatus +vlVdpBitmapSurfaceCreate(VdpDevice device, + VdpRGBAFormat rgba_format, + uint32_t width, uint32_t height, + VdpBool frequently_accessed, + VdpBitmapSurface *surface) +{ + VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Creating a bitmap surface\n"); + if (!surface) + return VDP_STATUS_INVALID_POINTER; + + return VDP_STATUS_NO_IMPLEMENTATION; +} + +VdpStatus +vlVdpBitmapSurfaceDestroy(VdpBitmapSurface surface) +{ + return VDP_STATUS_NO_IMPLEMENTATION; +} + +VdpStatus +vlVdpBitmapSurfaceGetParameters(VdpBitmapSurface surface, + VdpRGBAFormat *rgba_format, + uint32_t *width, uint32_t *height, + VdpBool *frequently_accessed) +{ + if (!(rgba_format && width && height && frequently_accessed)) + return VDP_STATUS_INVALID_POINTER; + + return VDP_STATUS_NO_IMPLEMENTATION; +} + +VdpStatus +vlVdpBitmapSurfacePutBitsNative(VdpBitmapSurface surface, + void const *const *source_data, + uint32_t const *source_pitches, + VdpRect const *destination_rect ) +{ + if (!(source_data && source_pitches && destination_rect)) + return VDP_STATUS_INVALID_POINTER; + + return VDP_STATUS_NO_IMPLEMENTATION; +} diff --git a/src/gallium/state_trackers/vdpau/decode.c b/src/gallium/state_trackers/vdpau/decode.c new file mode 100644 index 00000000000..0696278ac3e --- /dev/null +++ b/src/gallium/state_trackers/vdpau/decode.c @@ -0,0 +1,273 @@ +/************************************************************************** + * + * Copyright 2010 Thomas Balling Sørensen. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include <util/u_memory.h> +#include <util/u_math.h> +#include <util/u_debug.h> + +#include "vdpau_private.h" + +VdpStatus +vlVdpDecoderCreate(VdpDevice device, + VdpDecoderProfile profile, + uint32_t width, uint32_t height, + uint32_t max_references, + VdpDecoder *decoder) +{ + enum pipe_video_profile p_profile; + struct pipe_context *pipe; + vlVdpDevice *dev; + vlVdpDecoder *vldecoder; + VdpStatus ret; + unsigned i; + + VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Creating decoder\n"); + + if (!decoder) + return VDP_STATUS_INVALID_POINTER; + + if (!(width && height)) + return VDP_STATUS_INVALID_VALUE; + + p_profile = ProfileToPipe(profile); + if (p_profile == PIPE_VIDEO_PROFILE_UNKNOWN) + return VDP_STATUS_INVALID_DECODER_PROFILE; + + dev = vlGetDataHTAB(device); + if (!dev) + return VDP_STATUS_INVALID_HANDLE; + + pipe = dev->context->pipe; + + vldecoder = CALLOC(1,sizeof(vlVdpDecoder)); + if (!vldecoder) + return VDP_STATUS_RESOURCES; + + vldecoder->device = dev; + + // TODO: Define max_references. Used mainly for H264 + vldecoder->decoder = pipe->create_video_decoder + ( + pipe, p_profile, + PIPE_VIDEO_ENTRYPOINT_BITSTREAM, + PIPE_VIDEO_CHROMA_FORMAT_420, + width, height + ); + if (!vldecoder->decoder) { + ret = VDP_STATUS_ERROR; + goto error_decoder; + } + + vldecoder->cur_buffer = 0; + + for (i = 0; i < VL_NUM_DECODE_BUFFERS; ++i) { + vldecoder->buffer[i] = vldecoder->decoder->create_buffer(vldecoder->decoder); + if (!vldecoder->buffer[i]) { + ret = VDP_STATUS_ERROR; + goto error_buffer; + } + } + + *decoder = vlAddDataHTAB(vldecoder); + if (*decoder == 0) { + ret = VDP_STATUS_ERROR; + goto error_handle; + } + + VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Decoder created succesfully\n"); + + return VDP_STATUS_OK; + +error_handle: +error_buffer: + + for (i = 0; i < VL_NUM_DECODE_BUFFERS; ++i) + if (vldecoder->buffer[i]) + vldecoder->buffer[i]->destroy(vldecoder->buffer[i]); + + vldecoder->decoder->destroy(vldecoder->decoder); + +error_decoder: + FREE(vldecoder); + return ret; +} + +VdpStatus +vlVdpDecoderDestroy(VdpDecoder decoder) +{ + vlVdpDecoder *vldecoder; + unsigned i; + + VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Destroying decoder\n"); + + vldecoder = (vlVdpDecoder *)vlGetDataHTAB(decoder); + if (!vldecoder) + return VDP_STATUS_INVALID_HANDLE; + + for (i = 0; i < VL_NUM_DECODE_BUFFERS; ++i) + if (vldecoder->buffer[i]) + vldecoder->buffer[i]->destroy(vldecoder->buffer[i]); + + vldecoder->decoder->destroy(vldecoder->decoder); + + FREE(vldecoder); + + return VDP_STATUS_OK; +} + +VdpStatus +vlVdpDecoderGetParameters(VdpDecoder decoder, + VdpDecoderProfile *profile, + uint32_t *width, + uint32_t *height) +{ + vlVdpDecoder *vldecoder; + + VDPAU_MSG(VDPAU_TRACE, "[VDPAU] decoder get parameters called\n"); + + vldecoder = (vlVdpDecoder *)vlGetDataHTAB(decoder); + if (!vldecoder) + return VDP_STATUS_INVALID_HANDLE; + + *profile = PipeToProfile(vldecoder->decoder->profile); + *width = vldecoder->decoder->width; + *height = vldecoder->decoder->height; + + return VDP_STATUS_OK; +} + +static VdpStatus +vlVdpDecoderRenderMpeg2(struct pipe_video_decoder *decoder, + struct pipe_video_decode_buffer *buffer, + struct pipe_video_buffer *target, + VdpPictureInfoMPEG1Or2 *picture_info, + uint32_t bitstream_buffer_count, + VdpBitstreamBuffer const *bitstream_buffers) +{ + struct pipe_mpeg12_picture_desc picture; + struct pipe_video_buffer *ref_frames[2]; + uint8_t intra_quantizer_matrix[64]; + unsigned num_ycbcr_blocks[3] = { 0, 0, 0 }; + unsigned i; + + VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Decoding MPEG2\n"); + + /* if surfaces equals VDP_STATUS_INVALID_HANDLE, they are not used */ + if (picture_info->forward_reference == VDP_INVALID_HANDLE) + ref_frames[0] = NULL; + else { + ref_frames[0] = ((vlVdpSurface *)vlGetDataHTAB(picture_info->forward_reference))->video_buffer; + if (!ref_frames[0]) + return VDP_STATUS_INVALID_HANDLE; + } + + if (picture_info->backward_reference == VDP_INVALID_HANDLE) + ref_frames[1] = NULL; + else { + ref_frames[1] = ((vlVdpSurface *)vlGetDataHTAB(picture_info->backward_reference))->video_buffer; + if (!ref_frames[1]) + return VDP_STATUS_INVALID_HANDLE; + } + + memset(&picture, 0, sizeof(picture)); + picture.base.profile = decoder->profile; + picture.picture_coding_type = picture_info->picture_coding_type; + picture.picture_structure = picture_info->picture_structure; + picture.frame_pred_frame_dct = picture_info->frame_pred_frame_dct; + picture.q_scale_type = picture_info->q_scale_type; + picture.alternate_scan = picture_info->alternate_scan; + picture.intra_vlc_format = picture_info->intra_vlc_format; + picture.concealment_motion_vectors = picture_info->concealment_motion_vectors; + picture.f_code[0][0] = picture_info->f_code[0][0] - 1; + picture.f_code[0][1] = picture_info->f_code[0][1] - 1; + picture.f_code[1][0] = picture_info->f_code[1][0] - 1; + picture.f_code[1][1] = picture_info->f_code[1][1] - 1; + + buffer->begin_frame(buffer); + + memcpy(intra_quantizer_matrix, picture_info->intra_quantizer_matrix, sizeof(intra_quantizer_matrix)); + intra_quantizer_matrix[0] = 1 << (7 - picture_info->intra_dc_precision); + buffer->set_quant_matrix(buffer, intra_quantizer_matrix, picture_info->non_intra_quantizer_matrix); + + for (i = 0; i < bitstream_buffer_count; ++i) + buffer->decode_bitstream(buffer, bitstream_buffers[i].bitstream_bytes, + bitstream_buffers[i].bitstream, &picture, num_ycbcr_blocks); + + buffer->end_frame(buffer); + + decoder->flush_buffer(buffer, num_ycbcr_blocks, ref_frames, target); + + return VDP_STATUS_OK; +} + +VdpStatus +vlVdpDecoderRender(VdpDecoder decoder, + VdpVideoSurface target, + VdpPictureInfo const *picture_info, + uint32_t bitstream_buffer_count, + VdpBitstreamBuffer const *bitstream_buffers) +{ + vlVdpDecoder *vldecoder; + vlVdpSurface *vlsurf; + + VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Decoding\n"); + + if (!(picture_info && bitstream_buffers)) + return VDP_STATUS_INVALID_POINTER; + + vldecoder = (vlVdpDecoder *)vlGetDataHTAB(decoder); + if (!vldecoder) + return VDP_STATUS_INVALID_HANDLE; + + vlsurf = (vlVdpSurface *)vlGetDataHTAB(target); + if (!vlsurf) + return VDP_STATUS_INVALID_HANDLE; + + if (vlsurf->device != vldecoder->device) + return VDP_STATUS_HANDLE_DEVICE_MISMATCH; + + if (vlsurf->video_buffer->chroma_format != vldecoder->decoder->chroma_format) + // TODO: Recreate decoder with correct chroma + return VDP_STATUS_INVALID_CHROMA_TYPE; + + // TODO: Right now only mpeg2 is supported. + switch (vldecoder->decoder->profile) { + case PIPE_VIDEO_PROFILE_MPEG2_SIMPLE: + case PIPE_VIDEO_PROFILE_MPEG2_MAIN: + ++vldecoder->cur_buffer; + vldecoder->cur_buffer %= VL_NUM_DECODE_BUFFERS; + return vlVdpDecoderRenderMpeg2(vldecoder->decoder, + vldecoder->buffer[vldecoder->cur_buffer], + vlsurf->video_buffer, + (VdpPictureInfoMPEG1Or2 *)picture_info, + bitstream_buffer_count,bitstream_buffers); + break; + + default: + return VDP_STATUS_INVALID_DECODER_PROFILE; + } +} diff --git a/src/gallium/state_trackers/vdpau/device.c b/src/gallium/state_trackers/vdpau/device.c new file mode 100644 index 00000000000..200d5f62f63 --- /dev/null +++ b/src/gallium/state_trackers/vdpau/device.c @@ -0,0 +1,225 @@ +/************************************************************************** + * + * Copyright 2010 Younes Manton og Thomas Balling Sørensen. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include <pipe/p_compiler.h> + +#include <util/u_memory.h> +#include <util/u_debug.h> + +#include <vl_winsys.h> + +#include "vdpau_private.h" + +PUBLIC VdpStatus +vdp_imp_device_create_x11(Display *display, int screen, VdpDevice *device, + VdpGetProcAddress **get_proc_address) +{ + VdpStatus ret; + vlVdpDevice *dev = NULL; + + if (!(display && device && get_proc_address)) + return VDP_STATUS_INVALID_POINTER; + + if (!vlCreateHTAB()) { + ret = VDP_STATUS_RESOURCES; + goto no_htab; + } + + dev = CALLOC(1, sizeof(vlVdpDevice)); + if (!dev) { + ret = VDP_STATUS_RESOURCES; + goto no_dev; + } + + dev->vscreen = vl_screen_create(display, screen); + if (!dev->vscreen) { + ret = VDP_STATUS_RESOURCES; + goto no_vscreen; + } + + dev->context = vl_video_create(dev->vscreen); + if (!dev->context) { + ret = VDP_STATUS_RESOURCES; + goto no_context; + } + + *device = vlAddDataHTAB(dev); + if (*device == 0) { + ret = VDP_STATUS_ERROR; + goto no_handle; + } + + *get_proc_address = &vlVdpGetProcAddress; + VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Device created succesfully\n"); + + return VDP_STATUS_OK; + +no_handle: + /* Destroy vscreen */ +no_context: + vl_screen_destroy(dev->vscreen); +no_vscreen: + FREE(dev); +no_dev: + vlDestroyHTAB(); +no_htab: + return ret; +} + +PUBLIC VdpStatus +vlVdpPresentationQueueTargetCreateX11(VdpDevice device, Drawable drawable, + VdpPresentationQueueTarget *target) +{ + vlVdpPresentationQueueTarget *pqt; + VdpStatus ret; + + VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Creating PresentationQueueTarget\n"); + + if (!drawable) + return VDP_STATUS_INVALID_HANDLE; + + vlVdpDevice *dev = vlGetDataHTAB(device); + if (!dev) + return VDP_STATUS_INVALID_HANDLE; + + pqt = CALLOC(1, sizeof(vlVdpPresentationQueue)); + if (!pqt) + return VDP_STATUS_RESOURCES; + + pqt->device = dev; + pqt->drawable = drawable; + + *target = vlAddDataHTAB(pqt); + if (*target == 0) { + ret = VDP_STATUS_ERROR; + goto no_handle; + } + + return VDP_STATUS_OK; + +no_handle: + FREE(pqt); + return ret; +} + +VdpStatus +vlVdpPresentationQueueTargetDestroy(VdpPresentationQueueTarget presentation_queue_target) +{ + vlVdpPresentationQueueTarget *pqt; + + VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Destroying PresentationQueueTarget\n"); + + pqt = vlGetDataHTAB(presentation_queue_target); + if (!pqt) + return VDP_STATUS_INVALID_HANDLE; + + vlRemoveDataHTAB(presentation_queue_target); + FREE(pqt); + + return VDP_STATUS_OK; +} + +VdpStatus +vlVdpDeviceDestroy(VdpDevice device) +{ + VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Destroying destroy\n"); + + vlVdpDevice *dev = vlGetDataHTAB(device); + if (!dev) + return VDP_STATUS_INVALID_HANDLE; + + vl_video_destroy(dev->context); + vl_screen_destroy(dev->vscreen); + + FREE(dev); + vlDestroyHTAB(); + + VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Device destroyed succesfully\n"); + + return VDP_STATUS_OK; +} + +VdpStatus +vlVdpGetProcAddress(VdpDevice device, VdpFuncId function_id, void **function_pointer) +{ + vlVdpDevice *dev = vlGetDataHTAB(device); + if (!dev) + return VDP_STATUS_INVALID_HANDLE; + + if (!function_pointer) + return VDP_STATUS_INVALID_POINTER; + + if (!vlGetFuncFTAB(function_id, function_pointer)) + return VDP_STATUS_INVALID_FUNC_ID; + + VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Got proc adress %p for id %d\n", *function_pointer, function_id); + + return VDP_STATUS_OK; +} + +#define _ERROR_TYPE(TYPE,STRING) case TYPE: return STRING; + +char const * +vlVdpGetErrorString (VdpStatus status) +{ + switch (status) { + _ERROR_TYPE(VDP_STATUS_OK,"The operation completed successfully; no error."); + _ERROR_TYPE(VDP_STATUS_NO_IMPLEMENTATION,"No backend implementation could be loaded."); + _ERROR_TYPE(VDP_STATUS_DISPLAY_PREEMPTED,"The display was preempted, or a fatal error occurred. The application must re-initialize VDPAU."); + _ERROR_TYPE(VDP_STATUS_INVALID_HANDLE,"An invalid handle value was provided. Either the handle does not exist at all, or refers to an object of an incorrect type."); + _ERROR_TYPE(VDP_STATUS_INVALID_POINTER ,"An invalid pointer was provided. Typically, this means that a NULL pointer was provided for an 'output' parameter."); + _ERROR_TYPE(VDP_STATUS_INVALID_CHROMA_TYPE ,"An invalid/unsupported VdpChromaType value was supplied."); + _ERROR_TYPE(VDP_STATUS_INVALID_Y_CB_CR_FORMAT,"An invalid/unsupported VdpYCbCrFormat value was supplied."); + _ERROR_TYPE(VDP_STATUS_INVALID_RGBA_FORMAT,"An invalid/unsupported VdpRGBAFormat value was supplied."); + _ERROR_TYPE(VDP_STATUS_INVALID_INDEXED_FORMAT,"An invalid/unsupported VdpIndexedFormat value was supplied."); + _ERROR_TYPE(VDP_STATUS_INVALID_COLOR_STANDARD,"An invalid/unsupported VdpColorStandard value was supplied."); + _ERROR_TYPE(VDP_STATUS_INVALID_COLOR_TABLE_FORMAT,"An invalid/unsupported VdpColorTableFormat value was supplied."); + _ERROR_TYPE(VDP_STATUS_INVALID_BLEND_FACTOR,"An invalid/unsupported VdpOutputSurfaceRenderBlendFactor value was supplied."); + _ERROR_TYPE(VDP_STATUS_INVALID_BLEND_EQUATION,"An invalid/unsupported VdpOutputSurfaceRenderBlendEquation value was supplied."); + _ERROR_TYPE(VDP_STATUS_INVALID_FLAG,"An invalid/unsupported flag value/combination was supplied."); + _ERROR_TYPE(VDP_STATUS_INVALID_DECODER_PROFILE,"An invalid/unsupported VdpDecoderProfile value was supplied."); + _ERROR_TYPE(VDP_STATUS_INVALID_VIDEO_MIXER_FEATURE,"An invalid/unsupported VdpVideoMixerFeature value was supplied."); + _ERROR_TYPE(VDP_STATUS_INVALID_VIDEO_MIXER_PARAMETER ,"An invalid/unsupported VdpVideoMixerParameter value was supplied."); + _ERROR_TYPE(VDP_STATUS_INVALID_VIDEO_MIXER_ATTRIBUTE,"An invalid/unsupported VdpVideoMixerAttribute value was supplied."); + _ERROR_TYPE(VDP_STATUS_INVALID_VIDEO_MIXER_PICTURE_STRUCTURE,"An invalid/unsupported VdpVideoMixerPictureStructure value was supplied."); + _ERROR_TYPE(VDP_STATUS_INVALID_FUNC_ID,"An invalid/unsupported VdpFuncId value was supplied."); + _ERROR_TYPE(VDP_STATUS_INVALID_SIZE,"The size of a supplied object does not match the object it is being used with.\ + For example, a VdpVideoMixer is configured to process VdpVideoSurface objects of a specific size.\ + If presented with a VdpVideoSurface of a different size, this error will be raised."); + _ERROR_TYPE(VDP_STATUS_INVALID_VALUE,"An invalid/unsupported value was supplied.\ + This is a catch-all error code for values of type other than those with a specific error code."); + _ERROR_TYPE(VDP_STATUS_INVALID_STRUCT_VERSION,"An invalid/unsupported structure version was specified in a versioned structure. \ + This implies that the implementation is older than the header file the application was built against."); + _ERROR_TYPE(VDP_STATUS_RESOURCES,"The system does not have enough resources to complete the requested operation at this time."); + _ERROR_TYPE(VDP_STATUS_HANDLE_DEVICE_MISMATCH,"The set of handles supplied are not all related to the same VdpDevice.When performing operations \ + that operate on multiple surfaces, such as VdpOutputSurfaceRenderOutputSurface or VdpVideoMixerRender, \ + all supplied surfaces must have been created within the context of the same VdpDevice object. \ + This error is raised if they were not."); + _ERROR_TYPE(VDP_STATUS_ERROR,"A catch-all error, used when no other error code applies."); + default: return "Unknown Error"; + } +} diff --git a/src/gallium/state_trackers/vdpau/ftab.c b/src/gallium/state_trackers/vdpau/ftab.c new file mode 100644 index 00000000000..66ed50c3299 --- /dev/null +++ b/src/gallium/state_trackers/vdpau/ftab.c @@ -0,0 +1,122 @@ +/************************************************************************** + * + * Copyright 2010 Younes Manton & Thomas Balling Sørensen. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include <assert.h> +#include "vdpau_private.h" + +static void* ftab[67] = +{ + &vlVdpGetErrorString, /* VDP_FUNC_ID_GET_ERROR_STRING */ + &vlVdpGetProcAddress, /* VDP_FUNC_ID_GET_PROC_ADDRESS */ + &vlVdpGetApiVersion, /* VDP_FUNC_ID_GET_API_VERSION */ + NULL, /* DUMMY */ + &vlVdpGetInformationString, /* VDP_FUNC_ID_GET_INFORMATION_STRING */ + &vlVdpDeviceDestroy, /* VDP_FUNC_ID_DEVICE_DESTROY */ + &vlVdpGenerateCSCMatrix, /* VDP_FUNC_ID_GENERATE_CSC_MATRIX */ + &vlVdpVideoSurfaceQueryCapabilities, /* VDP_FUNC_ID_VIDEO_SURFACE_QUERY_CAPABILITIES */ + &vlVdpVideoSurfaceQueryGetPutBitsYCbCrCapabilities, /* VDP_FUNC_ID_VIDEO_SURFACE_QUERY_GET_PUT_BITS_Y_CB_CR_CAPABILITIES */ + &vlVdpVideoSurfaceCreate, /* VDP_FUNC_ID_VIDEO_SURFACE_CREATE */ + &vlVdpVideoSurfaceDestroy, /* VDP_FUNC_ID_VIDEO_SURFACE_DESTROY */ + &vlVdpVideoSurfaceGetParameters, /* VDP_FUNC_ID_VIDEO_SURFACE_GET_PARAMETERS */ + &vlVdpVideoSurfaceGetBitsYCbCr, /* VDP_FUNC_ID_VIDEO_SURFACE_GET_BITS_Y_CB_CR */ + &vlVdpVideoSurfacePutBitsYCbCr, /* VDP_FUNC_ID_VIDEO_SURFACE_PUT_BITS_Y_CB_CR */ + &vlVdpOutputSurfaceQueryCapabilities, /* VDP_FUNC_ID_OUTPUT_SURFACE_QUERY_CAPABILITIES */ + &vlVdpOutputSurfaceQueryGetPutBitsNativeCapabilities, /* VDP_FUNC_ID_OUTPUT_SURFACE_QUERY_GET_PUT_BITS_NATIVE_CAPABILITIES */ + &vlVdpOutputSurfaceQueryPutBitsIndexedCapabilities, /* VDP_FUNC_ID_OUTPUT_SURFACE_QUERY_PUT_BITS_INDEXED_CAPABILITIES */ + &vlVdpOutputSurfaceQueryPutBitsYCbCrCapabilities, /* VDP_FUNC_ID_OUTPUT_SURFACE_QUERY_PUT_BITS_Y_CB_CR_CAPABILITIES */ + &vlVdpOutputSurfaceCreate, /* VDP_FUNC_ID_OUTPUT_SURFACE_CREATE */ + &vlVdpOutputSurfaceDestroy, /* VDP_FUNC_ID_OUTPUT_SURFACE_DESTROY */ + &vlVdpOutputSurfaceGetParameters, /* VDP_FUNC_ID_OUTPUT_SURFACE_GET_PARAMETERS */ + &vlVdpOutputSurfaceGetBitsNative, /* VDP_FUNC_ID_OUTPUT_SURFACE_GET_BITS_NATIVE */ + &vlVdpOutputSurfacePutBitsNative, /* VDP_FUNC_ID_OUTPUT_SURFACE_PUT_BITS_NATIVE */ + &vlVdpOutputSurfacePutBitsIndexed, /* VDP_FUNC_ID_OUTPUT_SURFACE_PUT_BITS_INDEXED */ + &vlVdpOutputSurfacePutBitsYCbCr, /* VDP_FUNC_ID_OUTPUT_SURFACE_PUT_BITS_Y_CB_CR */ + &vlVdpBitmapSurfaceQueryCapabilities, /* VDP_FUNC_ID_BITMAP_SURFACE_QUERY_CAPABILITIES */ + &vlVdpBitmapSurfaceCreate, /* VDP_FUNC_ID_BITMAP_SURFACE_CREATE */ + &vlVdpBitmapSurfaceDestroy, /* VDP_FUNC_ID_BITMAP_SURFACE_DESTROY */ + &vlVdpBitmapSurfaceGetParameters, /* VDP_FUNC_ID_BITMAP_SURFACE_GET_PARAMETERS */ + &vlVdpBitmapSurfacePutBitsNative, /* VDP_FUNC_ID_BITMAP_SURFACE_PUT_BITS_NATIVE */ + NULL, /* DUMMY */ + NULL, /* DUMMY */ + NULL, /* DUMMY */ + &vlVdpOutputSurfaceRenderOutputSurface, /* VDP_FUNC_ID_OUTPUT_SURFACE_RENDER_OUTPUT_SURFACE */ + &vlVdpOutputSurfaceRenderBitmapSurface, /* VDP_FUNC_ID_OUTPUT_SURFACE_RENDER_BITMAP_SURFACE */ + NULL, /* VDP_FUNC_ID_OUTPUT_SURFACE_RENDER_VIDEO_SURFACE_LUMA */ + &vlVdpDecoderQueryCapabilities, /* VDP_FUNC_ID_DECODER_QUERY_CAPABILITIES */ + &vlVdpDecoderCreate, /* VDP_FUNC_ID_DECODER_CREATE */ + &vlVdpDecoderDestroy, /* VDP_FUNC_ID_DECODER_DESTROY */ + &vlVdpDecoderGetParameters, /* VDP_FUNC_ID_DECODER_GET_PARAMETERS */ + &vlVdpDecoderRender, /* VDP_FUNC_ID_DECODER_RENDER */ + &vlVdpVideoMixerQueryFeatureSupport, /* VDP_FUNC_ID_VIDEO_MIXER_QUERY_FEATURE_SUPPORT */ + &vlVdpVideoMixerQueryParameterSupport, /* VDP_FUNC_ID_VIDEO_MIXER_QUERY_PARAMETER_SUPPORT */ + &vlVdpVideoMixerQueryAttributeSupport, /* VDP_FUNC_ID_VIDEO_MIXER_QUERY_ATTRIBUTE_SUPPORT */ + &vlVdpVideoMixerQueryParameterValueRange, /* VDP_FUNC_ID_VIDEO_MIXER_QUERY_PARAMETER_VALUE_RANGE */ + &vlVdpVideoMixerQueryAttributeValueRange, /* VDP_FUNC_ID_VIDEO_MIXER_QUERY_ATTRIBUTE_VALUE_RANGE */ + &vlVdpVideoMixerCreate, /* VDP_FUNC_ID_VIDEO_MIXER_CREATE */ + &vlVdpVideoMixerSetFeatureEnables, /* VDP_FUNC_ID_VIDEO_MIXER_SET_FEATURE_ENABLES */ + &vlVdpVideoMixerSetAttributeValues, /* VDP_FUNC_ID_VIDEO_MIXER_SET_ATTRIBUTE_VALUES */ + &vlVdpVideoMixerGetFeatureSupport, /* VDP_FUNC_ID_VIDEO_MIXER_GET_FEATURE_SUPPORT */ + &vlVdpVideoMixerGetFeatureEnables, /* VDP_FUNC_ID_VIDEO_MIXER_GET_FEATURE_ENABLES */ + &vlVdpVideoMixerGetParameterValues, /* VDP_FUNC_ID_VIDEO_MIXER_GET_PARAMETER_VALUES */ + &vlVdpVideoMixerGetAttributeValues, /* VDP_FUNC_ID_VIDEO_MIXER_GET_ATTRIBUTE_VALUES */ + &vlVdpVideoMixerDestroy, /* VDP_FUNC_ID_VIDEO_MIXER_DESTROY */ + &vlVdpVideoMixerRender, /* VDP_FUNC_ID_VIDEO_MIXER_RENDER */ + &vlVdpPresentationQueueTargetDestroy, /* VDP_FUNC_ID_PRESENTATION_QUEUE_TARGET_DESTROY */ + &vlVdpPresentationQueueCreate, /* VDP_FUNC_ID_PRESENTATION_QUEUE_CREATE */ + &vlVdpPresentationQueueDestroy, /* VDP_FUNC_ID_PRESENTATION_QUEUE_DESTROY */ + &vlVdpPresentationQueueSetBackgroundColor, /* VDP_FUNC_ID_PRESENTATION_QUEUE_SET_BACKGROUND_COLOR */ + &vlVdpPresentationQueueGetBackgroundColor, /* VDP_FUNC_ID_PRESENTATION_QUEUE_GET_BACKGROUND_COLOR */ + NULL, /* DUMMY */ + NULL, /* DUMMY */ + &vlVdpPresentationQueueGetTime, /* VDP_FUNC_ID_PRESENTATION_QUEUE_GET_TIME */ + &vlVdpPresentationQueueDisplay, /* VDP_FUNC_ID_PRESENTATION_QUEUE_DISPLAY */ + &vlVdpPresentationQueueBlockUntilSurfaceIdle, /* VDP_FUNC_ID_PRESENTATION_QUEUE_BLOCK_UNTIL_SURFACE_IDLE */ + &vlVdpPresentationQueueQuerySurfaceStatus, /* VDP_FUNC_ID_PRESENTATION_QUEUE_QUERY_SURFACE_STATUS */ + &vlVdpPreemptionCallbackRegister /* VDP_FUNC_ID_PREEMPTION_CALLBACK_REGISTER */ +}; + +static void* ftab_winsys[1] = +{ + &vlVdpPresentationQueueTargetCreateX11 /* VDP_FUNC_ID_PRESENTATION_QUEUE_TARGET_CREATE_X11 */ +}; + +boolean vlGetFuncFTAB(VdpFuncId function_id, void **func) +{ + assert(func); + if (function_id < VDP_FUNC_ID_BASE_WINSYS) { + if (function_id > 66) + return FALSE; + *func = ftab[function_id]; + } + else { + function_id -= VDP_FUNC_ID_BASE_WINSYS; + if (function_id > 0) + return FALSE; + *func = ftab_winsys[function_id]; + } + return *func != NULL; +} diff --git a/src/gallium/state_trackers/vdpau/htab.c b/src/gallium/state_trackers/vdpau/htab.c new file mode 100644 index 00000000000..20f5a171f19 --- /dev/null +++ b/src/gallium/state_trackers/vdpau/htab.c @@ -0,0 +1,104 @@ +/************************************************************************** + * + * Copyright 2010 Younes Manton. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include <util/u_handle_table.h> +#include <os/os_thread.h> +#include "vdpau_private.h" + +#ifdef VL_HANDLES +static struct handle_table *htab = NULL; +pipe_static_mutex(htab_lock); +#endif + +boolean vlCreateHTAB(void) +{ +#ifdef VL_HANDLES + boolean ret; + /* Make sure handle table handles match VDPAU handles. */ + assert(sizeof(unsigned) <= sizeof(vlHandle)); + pipe_mutex_lock(htab_lock); + if (!htab) + htab = handle_table_create(); + ret = htab != NULL; + pipe_mutex_unlock(htab_lock); + return ret; +#else + return TRUE; +#endif +} + +void vlDestroyHTAB(void) +{ +#ifdef VL_HANDLES + pipe_mutex_lock(htab_lock); + if (htab) { + handle_table_destroy(htab); + htab = NULL; + } + pipe_mutex_unlock(htab_lock); +#endif +} + +vlHandle vlAddDataHTAB(void *data) +{ + assert(data); +#ifdef VL_HANDLES + vlHandle handle = 0; + pipe_mutex_lock(htab_lock); + if (htab) + handle = handle_table_add(htab, data); + pipe_mutex_unlock(htab_lock); + return handle; +#else + return (vlHandle)data; +#endif +} + +void* vlGetDataHTAB(vlHandle handle) +{ + assert(handle); +#ifdef VL_HANDLES + void *data = NULL; + pipe_mutex_lock(htab_lock); + if (htab) + data = handle_table_get(htab, handle); + pipe_mutex_unlock(htab_lock); + return data; +#else + return (void*)handle; +#endif +} + +void vlRemoveDataHTAB(vlHandle handle) +{ +#ifdef VL_HANDLES + pipe_mutex_lock(htab_lock); + if (htab) + handle_table_remove(htab, handle); + pipe_mutex_unlock(htab_lock); +#endif +} diff --git a/src/gallium/state_trackers/vdpau/mixer.c b/src/gallium/state_trackers/vdpau/mixer.c new file mode 100644 index 00000000000..d5187006bfc --- /dev/null +++ b/src/gallium/state_trackers/vdpau/mixer.c @@ -0,0 +1,233 @@ +/************************************************************************** + * + * Copyright 2010 Thomas Balling Sørensen. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include <vdpau/vdpau.h> + +#include <util/u_memory.h> +#include <util/u_debug.h> + +#include <vl/vl_csc.h> + +#include "vdpau_private.h" + +VdpStatus +vlVdpVideoMixerCreate(VdpDevice device, + uint32_t feature_count, + VdpVideoMixerFeature const *features, + uint32_t parameter_count, + VdpVideoMixerParameter const *parameters, + void const *const *parameter_values, + VdpVideoMixer *mixer) +{ + vlVdpVideoMixer *vmixer = NULL; + VdpStatus ret; + float csc[16]; + + VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Creating VideoMixer\n"); + + vlVdpDevice *dev = vlGetDataHTAB(device); + if (!dev) + return VDP_STATUS_INVALID_HANDLE; + + vmixer = CALLOC(1, sizeof(vlVdpVideoMixer)); + if (!vmixer) + return VDP_STATUS_RESOURCES; + + vmixer->device = dev; + vl_compositor_init(&vmixer->compositor, dev->context->pipe); + + vl_csc_get_matrix + ( + debug_get_bool_option("G3DVL_NO_CSC", FALSE) ? + VL_CSC_COLOR_STANDARD_IDENTITY : VL_CSC_COLOR_STANDARD_BT_601, + NULL, true, csc + ); + vl_compositor_set_csc_matrix(&vmixer->compositor, csc); + + /* + * TODO: Handle features and parameters + * */ + + *mixer = vlAddDataHTAB(vmixer); + if (*mixer == 0) { + ret = VDP_STATUS_ERROR; + goto no_handle; + } + + return VDP_STATUS_OK; +no_handle: + return ret; +} + +VdpStatus +vlVdpVideoMixerDestroy(VdpVideoMixer mixer) +{ + vlVdpVideoMixer *vmixer; + + VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Destroying VideoMixer\n"); + + vmixer = vlGetDataHTAB(mixer); + if (!vmixer) + return VDP_STATUS_INVALID_HANDLE; + + vl_compositor_cleanup(&vmixer->compositor); + + FREE(vmixer); + + return VDP_STATUS_OK; +} + +VdpStatus +vlVdpVideoMixerSetFeatureEnables(VdpVideoMixer mixer, + uint32_t feature_count, + VdpVideoMixerFeature const *features, + VdpBool const *feature_enables) +{ + VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Setting VideoMixer features\n"); + + if (!(features && feature_enables)) + return VDP_STATUS_INVALID_POINTER; + + vlVdpVideoMixer *vmixer = vlGetDataHTAB(mixer); + if (!vmixer) + return VDP_STATUS_INVALID_HANDLE; + + /* + * TODO: Set features + * */ + + return VDP_STATUS_OK; +} + +VdpStatus vlVdpVideoMixerRender(VdpVideoMixer mixer, + VdpOutputSurface background_surface, + VdpRect const *background_source_rect, + VdpVideoMixerPictureStructure current_picture_structure, + uint32_t video_surface_past_count, + VdpVideoSurface const *video_surface_past, + VdpVideoSurface video_surface_current, + uint32_t video_surface_future_count, + VdpVideoSurface const *video_surface_future, + VdpRect const *video_source_rect, + VdpOutputSurface destination_surface, + VdpRect const *destination_rect, + VdpRect const *destination_video_rect, + uint32_t layer_count, + VdpLayer const *layers) +{ + vlVdpVideoMixer *vmixer; + vlVdpSurface *surf; + vlVdpOutputSurface *dst; + + vmixer = vlGetDataHTAB(mixer); + if (!vmixer) + return VDP_STATUS_INVALID_HANDLE; + + surf = vlGetDataHTAB(video_surface_current); + if (!surf) + return VDP_STATUS_INVALID_HANDLE; + + dst = vlGetDataHTAB(destination_surface); + if (!dst) + return VDP_STATUS_INVALID_HANDLE; + + vl_compositor_clear_layers(&vmixer->compositor); + vl_compositor_set_buffer_layer(&vmixer->compositor, 0, surf->video_buffer, NULL, NULL); + vl_compositor_render(&vmixer->compositor, PIPE_MPEG12_PICTURE_TYPE_FRAME, + dst->surface, NULL, NULL); + + return VDP_STATUS_OK; +} + +VdpStatus +vlVdpVideoMixerSetAttributeValues(VdpVideoMixer mixer, + uint32_t attribute_count, + VdpVideoMixerAttribute const *attributes, + void const *const *attribute_values) +{ + if (!(attributes && attribute_values)) + return VDP_STATUS_INVALID_POINTER; + + vlVdpVideoMixer *vmixer = vlGetDataHTAB(mixer); + if (!vmixer) + return VDP_STATUS_INVALID_HANDLE; + + /* + * TODO: Implement the function + * + * */ + + return VDP_STATUS_OK; +} + +VdpStatus +vlVdpVideoMixerGetFeatureSupport(VdpVideoMixer mixer, + uint32_t feature_count, + VdpVideoMixerFeature const *features, + VdpBool *feature_supports) +{ + return VDP_STATUS_NO_IMPLEMENTATION; +} + +VdpStatus +vlVdpVideoMixerGetFeatureEnables(VdpVideoMixer mixer, + uint32_t feature_count, + VdpVideoMixerFeature const *features, + VdpBool *feature_enables) +{ + return VDP_STATUS_NO_IMPLEMENTATION; +} + +VdpStatus +vlVdpVideoMixerGetParameterValues(VdpVideoMixer mixer, + uint32_t parameter_count, + VdpVideoMixerParameter const *parameters, + void *const *parameter_values) +{ + return VDP_STATUS_NO_IMPLEMENTATION; +} + +VdpStatus +vlVdpVideoMixerGetAttributeValues(VdpVideoMixer mixer, + uint32_t attribute_count, + VdpVideoMixerAttribute const *attributes, + void *const *attribute_values) +{ + return VDP_STATUS_NO_IMPLEMENTATION; +} + +VdpStatus +vlVdpGenerateCSCMatrix(VdpProcamp *procamp, + VdpColorStandard standard, + VdpCSCMatrix *csc_matrix) +{ + VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Generating CSCMatrix\n"); + if (!(csc_matrix && procamp)) + return VDP_STATUS_INVALID_POINTER; + + return VDP_STATUS_OK; +} diff --git a/src/gallium/state_trackers/vdpau/output.c b/src/gallium/state_trackers/vdpau/output.c new file mode 100644 index 00000000000..bc4b39ae75c --- /dev/null +++ b/src/gallium/state_trackers/vdpau/output.c @@ -0,0 +1,221 @@ +/************************************************************************** + * + * Copyright 2010 Thomas Balling Sørensen. + * Copyright 2011 Christian König. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include <vdpau/vdpau.h> + +#include <util/u_debug.h> +#include <util/u_memory.h> +#include <util/u_sampler.h> + +#include "vdpau_private.h" + +VdpStatus +vlVdpOutputSurfaceCreate(VdpDevice device, + VdpRGBAFormat rgba_format, + uint32_t width, uint32_t height, + VdpOutputSurface *surface) +{ + struct pipe_context *pipe; + struct pipe_resource res_tmpl, *res; + struct pipe_sampler_view sv_templ; + struct pipe_surface surf_templ; + + vlVdpOutputSurface *vlsurface = NULL; + + VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Creating output surface\n"); + if (!(width && height)) + return VDP_STATUS_INVALID_SIZE; + + vlVdpDevice *dev = vlGetDataHTAB(device); + if (!dev) + return VDP_STATUS_INVALID_HANDLE; + + pipe = dev->context->pipe; + if (!pipe) + return VDP_STATUS_INVALID_HANDLE; + + vlsurface = CALLOC(1, sizeof(vlVdpOutputSurface)); + if (!vlsurface) + return VDP_STATUS_RESOURCES; + + memset(&res_tmpl, 0, sizeof(res_tmpl)); + + res_tmpl.target = PIPE_TEXTURE_2D; + res_tmpl.format = FormatRGBAToPipe(rgba_format); + res_tmpl.width0 = width; + res_tmpl.height0 = height; + res_tmpl.depth0 = 1; + res_tmpl.array_size = 1; + res_tmpl.bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET; + res_tmpl.usage = PIPE_USAGE_STATIC; + + res = pipe->screen->resource_create(pipe->screen, &res_tmpl); + if (!res) { + FREE(dev); + return VDP_STATUS_ERROR; + } + + memset(&sv_templ, 0, sizeof(sv_templ)); + u_sampler_view_default_template(&sv_templ, res, res->format); + + // as long as we don't have a background picture we don't want an alpha channel + sv_templ.swizzle_a = PIPE_SWIZZLE_ONE; + + vlsurface->sampler_view = pipe->create_sampler_view(pipe, res, &sv_templ); + if (!vlsurface->sampler_view) { + pipe_resource_reference(&res, NULL); + FREE(dev); + return VDP_STATUS_ERROR; + } + + memset(&surf_templ, 0, sizeof(surf_templ)); + surf_templ.format = res->format; + surf_templ.usage = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET; + vlsurface->surface = pipe->create_surface(pipe, res, &surf_templ); + if (!vlsurface->surface) { + pipe_resource_reference(&res, NULL); + FREE(dev); + return VDP_STATUS_ERROR; + } + + *surface = vlAddDataHTAB(vlsurface); + if (*surface == 0) { + pipe_resource_reference(&res, NULL); + FREE(dev); + return VDP_STATUS_ERROR; + } + + pipe_resource_reference(&res, NULL); + + return VDP_STATUS_OK; +} + +VdpStatus +vlVdpOutputSurfaceDestroy(VdpOutputSurface surface) +{ + vlVdpOutputSurface *vlsurface; + + VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Destroying output surface\n"); + + vlsurface = vlGetDataHTAB(surface); + if (!vlsurface) + return VDP_STATUS_INVALID_HANDLE; + + pipe_surface_reference(&vlsurface->surface, NULL); + pipe_sampler_view_reference(&vlsurface->sampler_view, NULL); + + vlRemoveDataHTAB(surface); + FREE(vlsurface); + + return VDP_STATUS_OK; +} + +VdpStatus +vlVdpOutputSurfaceGetParameters(VdpOutputSurface surface, + VdpRGBAFormat *rgba_format, + uint32_t *width, uint32_t *height) +{ + vlVdpOutputSurface *vlsurface; + + VDPAU_MSG(VDPAU_TRACE, "[VDPAU] getting surface parameters\n"); + + vlsurface = vlGetDataHTAB(surface); + if (!vlsurface) + return VDP_STATUS_INVALID_HANDLE; + + *rgba_format = PipeToFormatRGBA(vlsurface->sampler_view->texture->format); + *width = vlsurface->sampler_view->texture->width0; + *height = vlsurface->sampler_view->texture->height0; + + return VDP_STATUS_OK; +} + +VdpStatus +vlVdpOutputSurfaceGetBitsNative(VdpOutputSurface surface, + VdpRect const *source_rect, + void *const *destination_data, + uint32_t const *destination_pitches) +{ + return VDP_STATUS_NO_IMPLEMENTATION; +} + +VdpStatus +vlVdpOutputSurfacePutBitsNative(VdpOutputSurface surface, + void const *const *source_data, + uint32_t const *source_pitches, + VdpRect const *destination_rect) +{ + return VDP_STATUS_NO_IMPLEMENTATION; +} + +VdpStatus +vlVdpOutputSurfacePutBitsIndexed(VdpOutputSurface surface, + VdpIndexedFormat source_indexed_format, + void const *const *source_data, + uint32_t const *source_pitch, + VdpRect const *destination_rect, + VdpColorTableFormat color_table_format, + void const *color_table) +{ + return VDP_STATUS_NO_IMPLEMENTATION; +} + +VdpStatus +vlVdpOutputSurfacePutBitsYCbCr(VdpOutputSurface surface, + VdpYCbCrFormat source_ycbcr_format, + void const *const *source_data, + uint32_t const *source_pitches, + VdpRect const *destination_rect, + VdpCSCMatrix const *csc_matrix) +{ + return VDP_STATUS_NO_IMPLEMENTATION; +} + +VdpStatus +vlVdpOutputSurfaceRenderOutputSurface(VdpOutputSurface destination_surface, + VdpRect const *destination_rect, + VdpOutputSurface source_surface, + VdpRect const *source_rect, + VdpColor const *colors, + VdpOutputSurfaceRenderBlendState const *blend_state, + uint32_t flags) +{ + return VDP_STATUS_NO_IMPLEMENTATION; +} + +VdpStatus +vlVdpOutputSurfaceRenderBitmapSurface(VdpOutputSurface destination_surface, + VdpRect const *destination_rect, + VdpBitmapSurface source_surface, + VdpRect const *source_rect, + VdpColor const *colors, + VdpOutputSurfaceRenderBlendState const *blend_state, + uint32_t flags) +{ + return VDP_STATUS_NO_IMPLEMENTATION; +} diff --git a/src/gallium/state_trackers/vdpau/preemption.c b/src/gallium/state_trackers/vdpau/preemption.c new file mode 100644 index 00000000000..fa70bb09cbc --- /dev/null +++ b/src/gallium/state_trackers/vdpau/preemption.c @@ -0,0 +1,39 @@ +/************************************************************************** + * + * Copyright 2010 Thomas Balling Sørensen. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + + #include <vdpau/vdpau.h> + + void vlVdpPreemptionCallback(VdpDevice device, void *context) + { + /* TODO: Implement preemption */ + } + + VdpStatus vlVdpPreemptionCallbackRegister(VdpDevice device, VdpPreemptionCallback callback, + void *context) + { + return VDP_STATUS_OK; + } diff --git a/src/gallium/state_trackers/vdpau/presentation.c b/src/gallium/state_trackers/vdpau/presentation.c new file mode 100644 index 00000000000..1176c7a30b7 --- /dev/null +++ b/src/gallium/state_trackers/vdpau/presentation.c @@ -0,0 +1,223 @@ +/************************************************************************** + * + * Copyright 2010 Thomas Balling Sørensen. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include <stdio.h> + +#include <vdpau/vdpau.h> + +#include <util/u_debug.h> +#include <util/u_memory.h> + +#include "vdpau_private.h" + +VdpStatus +vlVdpPresentationQueueCreate(VdpDevice device, + VdpPresentationQueueTarget presentation_queue_target, + VdpPresentationQueue *presentation_queue) +{ + vlVdpPresentationQueue *pq = NULL; + VdpStatus ret; + + VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Creating PresentationQueue\n"); + + if (!presentation_queue) + return VDP_STATUS_INVALID_POINTER; + + vlVdpDevice *dev = vlGetDataHTAB(device); + if (!dev) + return VDP_STATUS_INVALID_HANDLE; + + vlVdpPresentationQueueTarget *pqt = vlGetDataHTAB(presentation_queue_target); + if (!pqt) + return VDP_STATUS_INVALID_HANDLE; + + if (dev != pqt->device) + return VDP_STATUS_HANDLE_DEVICE_MISMATCH; + + pq = CALLOC(1, sizeof(vlVdpPresentationQueue)); + if (!pq) + return VDP_STATUS_RESOURCES; + + pq->device = dev; + pq->drawable = pqt->drawable; + + if (!vl_compositor_init(&pq->compositor, dev->context->pipe)) { + ret = VDP_STATUS_ERROR; + goto no_compositor; + } + + *presentation_queue = vlAddDataHTAB(pq); + if (*presentation_queue == 0) { + ret = VDP_STATUS_ERROR; + goto no_handle; + } + + return VDP_STATUS_OK; +no_handle: +no_compositor: + FREE(pq); + return ret; +} + +VdpStatus +vlVdpPresentationQueueDestroy(VdpPresentationQueue presentation_queue) +{ + vlVdpPresentationQueue *pq; + + VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Destroying PresentationQueue\n"); + + pq = vlGetDataHTAB(presentation_queue); + if (!pq) + return VDP_STATUS_INVALID_HANDLE; + + vl_compositor_cleanup(&pq->compositor); + + vlRemoveDataHTAB(presentation_queue); + FREE(pq); + + return VDP_STATUS_OK; +} + +VdpStatus +vlVdpPresentationQueueSetBackgroundColor(VdpPresentationQueue presentation_queue, + VdpColor *const background_color) +{ + vlVdpPresentationQueue *pq; + + VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Setting Background Color\n"); + + if (!background_color) + return VDP_STATUS_INVALID_POINTER; + + pq = vlGetDataHTAB(presentation_queue); + if (!pq) + return VDP_STATUS_INVALID_HANDLE; + + vl_compositor_set_clear_color(&pq->compositor, (float*)background_color); + + return VDP_STATUS_OK; +} + +VdpStatus +vlVdpPresentationQueueGetBackgroundColor(VdpPresentationQueue presentation_queue, + VdpColor *const background_color) +{ + if (!background_color) + return VDP_STATUS_INVALID_POINTER; + + return VDP_STATUS_NO_IMPLEMENTATION; +} + +VdpStatus +vlVdpPresentationQueueGetTime(VdpPresentationQueue presentation_queue, + VdpTime *current_time) +{ + if (!current_time) + return VDP_STATUS_INVALID_POINTER; + + return VDP_STATUS_NO_IMPLEMENTATION; +} + +VdpStatus +vlVdpPresentationQueueDisplay(VdpPresentationQueue presentation_queue, + VdpOutputSurface surface, + uint32_t clip_width, + uint32_t clip_height, + VdpTime earliest_presentation_time) +{ + static int dump_window = -1; + + vlVdpPresentationQueue *pq; + vlVdpOutputSurface *surf; + struct pipe_surface *drawable_surface; + + pq = vlGetDataHTAB(presentation_queue); + if (!pq) + return VDP_STATUS_INVALID_HANDLE; + + drawable_surface = vl_drawable_surface_get(pq->device->context, pq->drawable); + if (!drawable_surface) + return VDP_STATUS_INVALID_HANDLE; + + surf = vlGetDataHTAB(surface); + if (!surf) + return VDP_STATUS_INVALID_HANDLE; + + vl_compositor_clear_layers(&pq->compositor); + vl_compositor_set_rgba_layer(&pq->compositor, 0, surf->sampler_view, NULL, NULL); + vl_compositor_render(&pq->compositor, PIPE_MPEG12_PICTURE_TYPE_FRAME, + drawable_surface, NULL, NULL); + + pq->device->context->pipe->screen->flush_frontbuffer + ( + pq->device->context->pipe->screen, + drawable_surface->texture, + 0, 0, + vl_contextprivate_get(pq->device->context, drawable_surface) + ); + + if(dump_window == -1) { + dump_window = debug_get_num_option("VDPAU_DUMP", 0); + } + + if(dump_window) { + static unsigned int framenum = 0; + char cmd[256]; + + sprintf(cmd, "xwd -id %d -out vdpau_frame_%08d.xwd", (int)pq->drawable, ++framenum); + if (system(cmd) != 0) + VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Dumping surface %d failed.\n", surface); + } + + pipe_surface_reference(&drawable_surface, NULL); + + return VDP_STATUS_OK; +} + +VdpStatus +vlVdpPresentationQueueBlockUntilSurfaceIdle(VdpPresentationQueue presentation_queue, + VdpOutputSurface surface, + VdpTime *first_presentation_time) +{ + if (!first_presentation_time) + return VDP_STATUS_INVALID_POINTER; + + //return VDP_STATUS_NO_IMPLEMENTATION; + return VDP_STATUS_OK; +} + +VdpStatus +vlVdpPresentationQueueQuerySurfaceStatus(VdpPresentationQueue presentation_queue, + VdpOutputSurface surface, + VdpPresentationQueueStatus *status, + VdpTime *first_presentation_time) +{ + if (!(status && first_presentation_time)) + return VDP_STATUS_INVALID_POINTER; + + return VDP_STATUS_NO_IMPLEMENTATION; +} diff --git a/src/gallium/state_trackers/vdpau/query.c b/src/gallium/state_trackers/vdpau/query.c new file mode 100644 index 00000000000..ec17e59118f --- /dev/null +++ b/src/gallium/state_trackers/vdpau/query.c @@ -0,0 +1,279 @@ +/************************************************************************** + * + * Copyright 2010 Younes Manton. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include "vdpau_private.h" +#include <vl_winsys.h> +#include <assert.h> +#include <pipe/p_screen.h> +#include <pipe/p_defines.h> +#include <math.h> +#include <util/u_debug.h> + + +VdpStatus +vlVdpGetApiVersion(uint32_t *api_version) +{ + if (!api_version) + return VDP_STATUS_INVALID_POINTER; + + *api_version = 1; + return VDP_STATUS_OK; +} + +VdpStatus +vlVdpGetInformationString(char const **information_string) +{ + if (!information_string) + return VDP_STATUS_INVALID_POINTER; + + *information_string = INFORMATION_STRING; + return VDP_STATUS_OK; +} + +VdpStatus +vlVdpVideoSurfaceQueryCapabilities(VdpDevice device, VdpChromaType surface_chroma_type, + VdpBool *is_supported, uint32_t *max_width, uint32_t *max_height) +{ + vlVdpDevice *dev; + struct pipe_screen *pscreen; + uint32_t max_2d_texture_level; + + VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Querying video surfaces\n"); + + if (!(is_supported && max_width && max_height)) + return VDP_STATUS_INVALID_POINTER; + + dev = vlGetDataHTAB(device); + if (!dev) + return VDP_STATUS_INVALID_HANDLE; + + pscreen = dev->vscreen->pscreen; + if (!pscreen) + return VDP_STATUS_RESOURCES; + + /* XXX: Current limits */ + *is_supported = true; + if (surface_chroma_type != VDP_CHROMA_TYPE_420) + *is_supported = false; + + max_2d_texture_level = pscreen->get_param(pscreen, PIPE_CAP_MAX_TEXTURE_2D_LEVELS); + if (!max_2d_texture_level) + return VDP_STATUS_RESOURCES; + + /* I am not quite sure if it is max_2d_texture_level-1 or just max_2d_texture_level */ + *max_width = *max_height = pow(2,max_2d_texture_level-1); + + return VDP_STATUS_OK; +} + +VdpStatus +vlVdpVideoSurfaceQueryGetPutBitsYCbCrCapabilities(VdpDevice device, VdpChromaType surface_chroma_type, + VdpYCbCrFormat bits_ycbcr_format, + VdpBool *is_supported) +{ + vlVdpDevice *dev; + struct pipe_screen *pscreen; + + VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Querying get put video surfaces\n"); + + if (!is_supported) + return VDP_STATUS_INVALID_POINTER; + + dev = vlGetDataHTAB(device); + if (!dev) + return VDP_STATUS_INVALID_HANDLE; + + pscreen = dev->vscreen->pscreen; + if (!pscreen) + return VDP_STATUS_RESOURCES; + + *is_supported = pscreen->is_video_format_supported + ( + pscreen, + FormatYCBCRToPipe(bits_ycbcr_format), + PIPE_VIDEO_PROFILE_UNKNOWN + ); + + return VDP_STATUS_OK; +} + +VdpStatus +vlVdpDecoderQueryCapabilities(VdpDevice device, VdpDecoderProfile profile, + VdpBool *is_supported, uint32_t *max_level, uint32_t *max_macroblocks, + uint32_t *max_width, uint32_t *max_height) +{ + vlVdpDevice *dev; + struct pipe_screen *pscreen; + enum pipe_video_profile p_profile; + + VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Querying decoder\n"); + + if (!(is_supported && max_level && max_macroblocks && max_width && max_height)) + return VDP_STATUS_INVALID_POINTER; + + dev = vlGetDataHTAB(device); + if (!dev) + return VDP_STATUS_INVALID_HANDLE; + + pscreen = dev->vscreen->pscreen; + if (!pscreen) + return VDP_STATUS_RESOURCES; + + p_profile = ProfileToPipe(profile); + if (p_profile == PIPE_VIDEO_PROFILE_UNKNOWN) { + *is_supported = false; + return VDP_STATUS_OK; + } + + *is_supported = pscreen->get_video_param(pscreen, p_profile, PIPE_VIDEO_CAP_SUPPORTED); + if (*is_supported) { + *max_width = pscreen->get_video_param(pscreen, p_profile, PIPE_VIDEO_CAP_MAX_WIDTH); + *max_height = pscreen->get_video_param(pscreen, p_profile, PIPE_VIDEO_CAP_MAX_HEIGHT); + *max_level = 16; + *max_macroblocks = (*max_width/16)*(*max_height/16); + } else { + *max_width = 0; + *max_height = 0; + *max_level = 0; + *max_macroblocks = 0; + } + + return VDP_STATUS_OK; +} + +VdpStatus +vlVdpOutputSurfaceQueryCapabilities(VdpDevice device, VdpRGBAFormat surface_rgba_format, + VdpBool *is_supported, uint32_t *max_width, uint32_t *max_height) +{ + if (!(is_supported && max_width && max_height)) + return VDP_STATUS_INVALID_POINTER; + + VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Querying ouput surfaces\n"); + + return VDP_STATUS_NO_IMPLEMENTATION; +} + +VdpStatus +vlVdpOutputSurfaceQueryGetPutBitsNativeCapabilities(VdpDevice device, VdpRGBAFormat surface_rgba_format, + VdpBool *is_supported) +{ + VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Querying output surfaces get put native cap\n"); + + if (!is_supported) + return VDP_STATUS_INVALID_POINTER; + + return VDP_STATUS_NO_IMPLEMENTATION; +} + +VdpStatus +vlVdpOutputSurfaceQueryPutBitsIndexedCapabilities(VdpDevice device, + VdpRGBAFormat surface_rgba_format, + VdpIndexedFormat bits_indexed_format, + VdpColorTableFormat color_table_format, + VdpBool *is_supported) +{ + VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Querying output surfaces get put indexed cap\n"); + + if (!is_supported) + return VDP_STATUS_INVALID_POINTER; + + return VDP_STATUS_NO_IMPLEMENTATION; +} + +VdpStatus +vlVdpOutputSurfaceQueryPutBitsYCbCrCapabilities(VdpDevice device, VdpRGBAFormat surface_rgba_format, + VdpYCbCrFormat bits_ycbcr_format, + VdpBool *is_supported) +{ + VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Querying output surfaces put ycrcb cap\n"); + if (!is_supported) + return VDP_STATUS_INVALID_POINTER; + + return VDP_STATUS_NO_IMPLEMENTATION; +} + +VdpStatus +vlVdpBitmapSurfaceQueryCapabilities(VdpDevice device, VdpRGBAFormat surface_rgba_format, + VdpBool *is_supported, uint32_t *max_width, uint32_t *max_height) +{ + VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Querying bitmap surfaces\n"); + if (!(is_supported && max_width && max_height)) + return VDP_STATUS_INVALID_POINTER; + + return VDP_STATUS_NO_IMPLEMENTATION; +} + +VdpStatus +vlVdpVideoMixerQueryFeatureSupport(VdpDevice device, VdpVideoMixerFeature feature, + VdpBool *is_supported) +{ + VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Querying mixer feature support\n"); + if (!is_supported) + return VDP_STATUS_INVALID_POINTER; + + return VDP_STATUS_NO_IMPLEMENTATION; +} + +VdpStatus +vlVdpVideoMixerQueryParameterSupport(VdpDevice device, VdpVideoMixerParameter parameter, + VdpBool *is_supported) +{ + if (!is_supported) + return VDP_STATUS_INVALID_POINTER; + + return VDP_STATUS_NO_IMPLEMENTATION; +} + +VdpStatus +vlVdpVideoMixerQueryParameterValueRange(VdpDevice device, VdpVideoMixerParameter parameter, + void *min_value, void *max_value) +{ + if (!(min_value && max_value)) + return VDP_STATUS_INVALID_POINTER; + + return VDP_STATUS_NO_IMPLEMENTATION; +} + +VdpStatus +vlVdpVideoMixerQueryAttributeSupport(VdpDevice device, VdpVideoMixerAttribute attribute, + VdpBool *is_supported) +{ + if (!is_supported) + return VDP_STATUS_INVALID_POINTER; + + return VDP_STATUS_NO_IMPLEMENTATION; +} + +VdpStatus +vlVdpVideoMixerQueryAttributeValueRange(VdpDevice device, VdpVideoMixerAttribute attribute, + void *min_value, void *max_value) +{ + if (!(min_value && max_value)) + return VDP_STATUS_INVALID_POINTER; + + return VDP_STATUS_NO_IMPLEMENTATION; +} diff --git a/src/gallium/state_trackers/vdpau/surface.c b/src/gallium/state_trackers/vdpau/surface.c new file mode 100644 index 00000000000..d3f6b5d8bc5 --- /dev/null +++ b/src/gallium/state_trackers/vdpau/surface.c @@ -0,0 +1,210 @@ +/************************************************************************** + * + * Copyright 2010 Thomas Balling Sørensen. + * Copyright 2011 Christian König. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include <assert.h> + +#include <pipe/p_state.h> + +#include <util/u_memory.h> +#include <util/u_debug.h> +#include <util/u_rect.h> + +#include "vdpau_private.h" + +VdpStatus +vlVdpVideoSurfaceCreate(VdpDevice device, VdpChromaType chroma_type, + uint32_t width, uint32_t height, + VdpVideoSurface *surface) +{ + vlVdpSurface *p_surf; + VdpStatus ret; + + VDPAU_MSG(VDPAU_TRACE, "[VDPAU] Creating a surface\n"); + + if (!(width && height)) { + ret = VDP_STATUS_INVALID_SIZE; + goto inv_size; + } + + if (!vlCreateHTAB()) { + ret = VDP_STATUS_RESOURCES; + goto no_htab; + } + + p_surf = CALLOC(1, sizeof(vlVdpSurface)); + if (!p_surf) { + ret = VDP_STATUS_RESOURCES; + goto no_res; + } + + vlVdpDevice *dev = vlGetDataHTAB(device); + if (!dev) { + ret = VDP_STATUS_INVALID_HANDLE; + goto inv_device; + } + + p_surf->device = dev; + p_surf->video_buffer = dev->context->pipe->create_video_buffer + ( + dev->context->pipe, + PIPE_FORMAT_YV12, // most common used + ChromaToPipe(chroma_type), + width, height + ); + + *surface = vlAddDataHTAB(p_surf); + if (*surface == 0) { + ret = VDP_STATUS_ERROR; + goto no_handle; + } + + return VDP_STATUS_OK; + +no_handle: + p_surf->video_buffer->destroy(p_surf->video_buffer); + +inv_device: + FREE(p_surf); + +no_res: +no_htab: +inv_size: + return ret; +} + +VdpStatus +vlVdpVideoSurfaceDestroy(VdpVideoSurface surface) +{ + vlVdpSurface *p_surf; + + p_surf = (vlVdpSurface *)vlGetDataHTAB((vlHandle)surface); + if (!p_surf) + return VDP_STATUS_INVALID_HANDLE; + + if (p_surf->video_buffer) + p_surf->video_buffer->destroy(p_surf->video_buffer); + + FREE(p_surf); + return VDP_STATUS_OK; +} + +VdpStatus +vlVdpVideoSurfaceGetParameters(VdpVideoSurface surface, + VdpChromaType *chroma_type, + uint32_t *width, uint32_t *height) +{ + if (!(width && height && chroma_type)) + return VDP_STATUS_INVALID_POINTER; + + vlVdpSurface *p_surf = vlGetDataHTAB(surface); + if (!p_surf) + return VDP_STATUS_INVALID_HANDLE; + + *width = p_surf->video_buffer->width; + *height = p_surf->video_buffer->height; + *chroma_type = PipeToChroma(p_surf->video_buffer->chroma_format); + + return VDP_STATUS_OK; +} + +VdpStatus +vlVdpVideoSurfaceGetBitsYCbCr(VdpVideoSurface surface, + VdpYCbCrFormat destination_ycbcr_format, + void *const *destination_data, + uint32_t const *destination_pitches) +{ + if (!vlCreateHTAB()) + return VDP_STATUS_RESOURCES; + + vlVdpSurface *p_surf = vlGetDataHTAB(surface); + if (!p_surf) + return VDP_STATUS_INVALID_HANDLE; + + //if (!p_surf->psurface) + // return VDP_STATUS_RESOURCES; + + //return VDP_STATUS_OK; + return VDP_STATUS_NO_IMPLEMENTATION; +} + +VdpStatus +vlVdpVideoSurfacePutBitsYCbCr(VdpVideoSurface surface, + VdpYCbCrFormat source_ycbcr_format, + void const *const *source_data, + uint32_t const *source_pitches) +{ + enum pipe_format pformat = FormatYCBCRToPipe(source_ycbcr_format); + struct pipe_context *pipe; + struct pipe_sampler_view **sampler_views; + unsigned i; + + if (!vlCreateHTAB()) + return VDP_STATUS_RESOURCES; + + vlVdpSurface *p_surf = vlGetDataHTAB(surface); + if (!p_surf) + return VDP_STATUS_INVALID_HANDLE; + + pipe = p_surf->device->context->pipe; + if (!pipe) + return VDP_STATUS_INVALID_HANDLE; + + if (p_surf->video_buffer == NULL || pformat != p_surf->video_buffer->buffer_format) { + assert(0); // TODO Recreate resource + return VDP_STATUS_NO_IMPLEMENTATION; + } + + sampler_views = p_surf->video_buffer->get_sampler_view_planes(p_surf->video_buffer); + if (!sampler_views) + return VDP_STATUS_RESOURCES; + + for (i = 0; i < 3; ++i) { //TODO put nr of planes into util format + struct pipe_sampler_view *sv = sampler_views[i ? i ^ 3 : 0]; + struct pipe_box dst_box = { 0, 0, 0, sv->texture->width0, sv->texture->height0, 1 }; + + struct pipe_transfer *transfer; + void *map; + + transfer = pipe->get_transfer(pipe, sv->texture, 0, PIPE_TRANSFER_WRITE, &dst_box); + if (!transfer) + return VDP_STATUS_RESOURCES; + + map = pipe->transfer_map(pipe, transfer); + if (map) { + util_copy_rect(map, sv->texture->format, transfer->stride, 0, 0, + dst_box.width, dst_box.height, + source_data[i], source_pitches[i], 0, 0); + + pipe->transfer_unmap(pipe, transfer); + } + + pipe->transfer_destroy(pipe, transfer); + } + + return VDP_STATUS_OK; +} diff --git a/src/gallium/state_trackers/vdpau/vdpau_private.h b/src/gallium/state_trackers/vdpau/vdpau_private.h new file mode 100644 index 00000000000..e5d945629fb --- /dev/null +++ b/src/gallium/state_trackers/vdpau/vdpau_private.h @@ -0,0 +1,361 @@ +/************************************************************************** + * + * Copyright 2010 Younes Manton & Thomas Balling Sørensen. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef VDPAU_PRIVATE_H +#define VDPAU_PRIVATE_H + +#include <assert.h> + +#include <vdpau/vdpau.h> +#include <vdpau/vdpau_x11.h> + +#include <pipe/p_compiler.h> +#include <pipe/p_video_decoder.h> + +#include <util/u_debug.h> +#include <vl/vl_compositor.h> + +#include <vl_winsys.h> + +#define INFORMATION G3DVL VDPAU Driver Shared Library version VER_MAJOR.VER_MINOR +#define QUOTEME(x) #x +#define TOSTRING(x) QUOTEME(x) +#define INFORMATION_STRING TOSTRING(INFORMATION) +#define VL_HANDLES +#define VL_NUM_DECODE_BUFFERS 4 + +static inline enum pipe_video_chroma_format +ChromaToPipe(VdpChromaType vdpau_type) +{ + switch (vdpau_type) { + case VDP_CHROMA_TYPE_420: + return PIPE_VIDEO_CHROMA_FORMAT_420; + case VDP_CHROMA_TYPE_422: + return PIPE_VIDEO_CHROMA_FORMAT_422; + case VDP_CHROMA_TYPE_444: + return PIPE_VIDEO_CHROMA_FORMAT_444; + default: + assert(0); + } + + return -1; +} + +static inline VdpChromaType +PipeToChroma(enum pipe_video_chroma_format pipe_type) +{ + switch (pipe_type) { + case PIPE_VIDEO_CHROMA_FORMAT_420: + return VDP_CHROMA_TYPE_420; + case PIPE_VIDEO_CHROMA_FORMAT_422: + return VDP_CHROMA_TYPE_422; + case PIPE_VIDEO_CHROMA_FORMAT_444: + return VDP_CHROMA_TYPE_444; + default: + assert(0); + } + + return -1; +} + + +static inline enum pipe_format +FormatYCBCRToPipe(VdpYCbCrFormat vdpau_format) +{ + switch (vdpau_format) { + case VDP_YCBCR_FORMAT_NV12: + return PIPE_FORMAT_NV12; + case VDP_YCBCR_FORMAT_YV12: + return PIPE_FORMAT_YV12; + case VDP_YCBCR_FORMAT_UYVY: + return PIPE_FORMAT_UYVY; + case VDP_YCBCR_FORMAT_YUYV: + return PIPE_FORMAT_YUYV; + case VDP_YCBCR_FORMAT_Y8U8V8A8: /* Not defined in p_format.h */ + return 0; + case VDP_YCBCR_FORMAT_V8U8Y8A8: + return PIPE_FORMAT_VUYA; + default: + assert(0); + } + + return -1; +} + +static inline VdpYCbCrFormat +PipeToFormatYCBCR(enum pipe_format p_format) +{ + switch (p_format) { + case PIPE_FORMAT_NV12: + return VDP_YCBCR_FORMAT_NV12; + case PIPE_FORMAT_YV12: + return VDP_YCBCR_FORMAT_YV12; + case PIPE_FORMAT_UYVY: + return VDP_YCBCR_FORMAT_UYVY; + case PIPE_FORMAT_YUYV: + return VDP_YCBCR_FORMAT_YUYV; + //case PIPE_FORMAT_YUVA: + // return VDP_YCBCR_FORMAT_Y8U8V8A8; + case PIPE_FORMAT_VUYA: + return VDP_YCBCR_FORMAT_V8U8Y8A8; + default: + assert(0); + } + + return -1; +} + +static inline enum pipe_format +FormatRGBAToPipe(VdpRGBAFormat vdpau_format) +{ + switch (vdpau_format) { + case VDP_RGBA_FORMAT_A8: + return PIPE_FORMAT_A8_UNORM; + case VDP_RGBA_FORMAT_B10G10R10A2: + return PIPE_FORMAT_B10G10R10A2_UNORM; + case VDP_RGBA_FORMAT_B8G8R8A8: + return PIPE_FORMAT_B8G8R8A8_UNORM; + case VDP_RGBA_FORMAT_R10G10B10A2: + return PIPE_FORMAT_R10G10B10A2_UNORM; + case VDP_RGBA_FORMAT_R8G8B8A8: + return PIPE_FORMAT_R8G8B8A8_UNORM; + default: + assert(0); + } + + return -1; +} + +static inline VdpRGBAFormat +PipeToFormatRGBA(enum pipe_format p_format) +{ + switch (p_format) { + case PIPE_FORMAT_A8_UNORM: + return VDP_RGBA_FORMAT_A8; + case PIPE_FORMAT_B10G10R10A2_UNORM: + return VDP_RGBA_FORMAT_B10G10R10A2; + case PIPE_FORMAT_B8G8R8A8_UNORM: + return VDP_RGBA_FORMAT_B8G8R8A8; + case PIPE_FORMAT_R10G10B10A2_UNORM: + return VDP_RGBA_FORMAT_R10G10B10A2; + case PIPE_FORMAT_R8G8B8A8_UNORM: + return VDP_RGBA_FORMAT_R8G8B8A8; + default: + assert(0); + } + + return -1; +} + +static inline enum pipe_video_profile +ProfileToPipe(VdpDecoderProfile vdpau_profile) +{ + switch (vdpau_profile) { + case VDP_DECODER_PROFILE_MPEG1: + return PIPE_VIDEO_PROFILE_MPEG1; + case VDP_DECODER_PROFILE_MPEG2_SIMPLE: + return PIPE_VIDEO_PROFILE_MPEG2_SIMPLE; + case VDP_DECODER_PROFILE_MPEG2_MAIN: + return PIPE_VIDEO_PROFILE_MPEG2_MAIN; + case VDP_DECODER_PROFILE_H264_BASELINE: + return PIPE_VIDEO_PROFILE_MPEG4_AVC_BASELINE; + case VDP_DECODER_PROFILE_H264_MAIN: /* Not defined in p_format.h */ + return PIPE_VIDEO_PROFILE_MPEG4_AVC_MAIN; + case VDP_DECODER_PROFILE_H264_HIGH: + return PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH; + default: + return PIPE_VIDEO_PROFILE_UNKNOWN; + } +} + +static inline VdpDecoderProfile +PipeToProfile(enum pipe_video_profile p_profile) +{ + switch (p_profile) { + case PIPE_VIDEO_PROFILE_MPEG1: + return VDP_DECODER_PROFILE_MPEG1; + case PIPE_VIDEO_PROFILE_MPEG2_SIMPLE: + return VDP_DECODER_PROFILE_MPEG2_SIMPLE; + case PIPE_VIDEO_PROFILE_MPEG2_MAIN: + return VDP_DECODER_PROFILE_MPEG2_MAIN; + case PIPE_VIDEO_PROFILE_MPEG4_AVC_BASELINE: + return VDP_DECODER_PROFILE_H264_BASELINE; + case PIPE_VIDEO_PROFILE_MPEG4_AVC_MAIN: /* Not defined in p_format.h */ + return VDP_DECODER_PROFILE_H264_MAIN; + case PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH: + return VDP_DECODER_PROFILE_H264_HIGH; + default: + assert(0); + return -1; + } +} + +typedef struct +{ + struct vl_screen *vscreen; + struct vl_context *context; +} vlVdpDevice; + +typedef struct +{ + vlVdpDevice *device; + Drawable drawable; +} vlVdpPresentationQueueTarget; + +typedef struct +{ + vlVdpDevice *device; + Drawable drawable; + struct vl_compositor compositor; +} vlVdpPresentationQueue; + +typedef struct +{ + vlVdpDevice *device; + struct vl_compositor compositor; +} vlVdpVideoMixer; + +typedef struct +{ + vlVdpDevice *device; + struct pipe_video_buffer *video_buffer; +} vlVdpSurface; + +typedef struct +{ + vlVdpDevice *device; + struct pipe_surface *surface; + struct pipe_sampler_view *sampler_view; +} vlVdpOutputSurface; + +typedef struct +{ + vlVdpDevice *device; + struct pipe_video_decoder *decoder; + struct pipe_video_decode_buffer *buffer[VL_NUM_DECODE_BUFFERS]; + unsigned cur_buffer; +} vlVdpDecoder; + +typedef uint32_t vlHandle; + +boolean vlCreateHTAB(void); +void vlDestroyHTAB(void); +vlHandle vlAddDataHTAB(void *data); +void* vlGetDataHTAB(vlHandle handle); +void vlRemoveDataHTAB(vlHandle handle); + +boolean vlGetFuncFTAB(VdpFuncId function_id, void **func); + +/* Public functions */ +VdpDeviceCreateX11 vdp_imp_device_create_x11; +VdpPresentationQueueTargetCreateX11 vlVdpPresentationQueueTargetCreateX11; + +/* Internal function pointers */ +VdpGetErrorString vlVdpGetErrorString; +VdpDeviceDestroy vlVdpDeviceDestroy; +VdpGetProcAddress vlVdpGetProcAddress; +VdpGetApiVersion vlVdpGetApiVersion; +VdpGetInformationString vlVdpGetInformationString; +VdpVideoSurfaceQueryCapabilities vlVdpVideoSurfaceQueryCapabilities; +VdpVideoSurfaceQueryGetPutBitsYCbCrCapabilities vlVdpVideoSurfaceQueryGetPutBitsYCbCrCapabilities; +VdpDecoderQueryCapabilities vlVdpDecoderQueryCapabilities; +VdpOutputSurfaceQueryCapabilities vlVdpOutputSurfaceQueryCapabilities; +VdpOutputSurfaceQueryGetPutBitsNativeCapabilities vlVdpOutputSurfaceQueryGetPutBitsNativeCapabilities; +VdpOutputSurfaceQueryPutBitsIndexedCapabilities vlVdpOutputSurfaceQueryPutBitsIndexedCapabilities; +VdpOutputSurfaceQueryPutBitsYCbCrCapabilities vlVdpOutputSurfaceQueryPutBitsYCbCrCapabilities; +VdpBitmapSurfaceQueryCapabilities vlVdpBitmapSurfaceQueryCapabilities; +VdpVideoMixerQueryFeatureSupport vlVdpVideoMixerQueryFeatureSupport; +VdpVideoMixerQueryParameterSupport vlVdpVideoMixerQueryParameterSupport; +VdpVideoMixerQueryParameterValueRange vlVdpVideoMixerQueryParameterValueRange; +VdpVideoMixerQueryAttributeSupport vlVdpVideoMixerQueryAttributeSupport; +VdpVideoMixerQueryAttributeValueRange vlVdpVideoMixerQueryAttributeValueRange; +VdpVideoSurfaceCreate vlVdpVideoSurfaceCreate; +VdpVideoSurfaceDestroy vlVdpVideoSurfaceDestroy; +VdpVideoSurfaceGetParameters vlVdpVideoSurfaceGetParameters; +VdpVideoSurfaceGetBitsYCbCr vlVdpVideoSurfaceGetBitsYCbCr; +VdpVideoSurfacePutBitsYCbCr vlVdpVideoSurfacePutBitsYCbCr; +VdpDecoderCreate vlVdpDecoderCreate; +VdpDecoderDestroy vlVdpDecoderDestroy; +VdpDecoderGetParameters vlVdpDecoderGetParameters; +VdpDecoderRender vlVdpDecoderRender; +VdpOutputSurfaceCreate vlVdpOutputSurfaceCreate; +VdpOutputSurfaceDestroy vlVdpOutputSurfaceDestroy; +VdpOutputSurfaceGetParameters vlVdpOutputSurfaceGetParameters; +VdpOutputSurfaceGetBitsNative vlVdpOutputSurfaceGetBitsNative; +VdpOutputSurfacePutBitsNative vlVdpOutputSurfacePutBitsNative; +VdpOutputSurfacePutBitsIndexed vlVdpOutputSurfacePutBitsIndexed; +VdpOutputSurfacePutBitsYCbCr vlVdpOutputSurfacePutBitsYCbCr; +VdpOutputSurfaceRenderOutputSurface vlVdpOutputSurfaceRenderOutputSurface; +VdpOutputSurfaceRenderBitmapSurface vlVdpOutputSurfaceRenderBitmapSurface; +VdpBitmapSurfaceCreate vlVdpBitmapSurfaceCreate; +VdpBitmapSurfaceDestroy vlVdpBitmapSurfaceDestroy; +VdpBitmapSurfaceGetParameters vlVdpBitmapSurfaceGetParameters; +VdpBitmapSurfacePutBitsNative vlVdpBitmapSurfacePutBitsNative; +VdpPresentationQueueTargetDestroy vlVdpPresentationQueueTargetDestroy; +VdpPresentationQueueCreate vlVdpPresentationQueueCreate; +VdpPresentationQueueDestroy vlVdpPresentationQueueDestroy; +VdpPresentationQueueSetBackgroundColor vlVdpPresentationQueueSetBackgroundColor; +VdpPresentationQueueGetBackgroundColor vlVdpPresentationQueueGetBackgroundColor; +VdpPresentationQueueGetTime vlVdpPresentationQueueGetTime; +VdpPresentationQueueDisplay vlVdpPresentationQueueDisplay; +VdpPresentationQueueBlockUntilSurfaceIdle vlVdpPresentationQueueBlockUntilSurfaceIdle; +VdpPresentationQueueQuerySurfaceStatus vlVdpPresentationQueueQuerySurfaceStatus; +VdpPreemptionCallback vlVdpPreemptionCallback; +VdpPreemptionCallbackRegister vlVdpPreemptionCallbackRegister; +VdpVideoMixerSetFeatureEnables vlVdpVideoMixerSetFeatureEnables; +VdpVideoMixerCreate vlVdpVideoMixerCreate; +VdpVideoMixerRender vlVdpVideoMixerRender; +VdpVideoMixerSetAttributeValues vlVdpVideoMixerSetAttributeValues; +VdpVideoMixerGetFeatureSupport vlVdpVideoMixerGetFeatureSupport; +VdpVideoMixerGetFeatureEnables vlVdpVideoMixerGetFeatureEnables; +VdpVideoMixerGetParameterValues vlVdpVideoMixerGetParameterValues; +VdpVideoMixerGetAttributeValues vlVdpVideoMixerGetAttributeValues; +VdpVideoMixerDestroy vlVdpVideoMixerDestroy; +VdpGenerateCSCMatrix vlVdpGenerateCSCMatrix; + +#define VDPAU_OUT 0 +#define VDPAU_ERR 1 +#define VDPAU_WARN 2 +#define VDPAU_TRACE 3 + +static inline void VDPAU_MSG(unsigned int level, const char *fmt, ...) +{ + static int debug_level = -1; + + if (debug_level == -1) { + debug_level = MAX2(debug_get_num_option("VDPAU_DEBUG", 0), 0); + } + + if (level <= debug_level) { + va_list ap; + va_start(ap, fmt); + _debug_vprintf(fmt, ap); + va_end(ap); + } +} + +#endif // VDPAU_PRIVATE_H diff --git a/src/gallium/state_trackers/xorg/xvmc/Makefile b/src/gallium/state_trackers/xorg/xvmc/Makefile new file mode 100644 index 00000000000..126dc6d58f1 --- /dev/null +++ b/src/gallium/state_trackers/xorg/xvmc/Makefile @@ -0,0 +1,16 @@ +TOP = ../../../../.. +include $(TOP)/configs/current + +LIBNAME = xvmctracker + +LIBRARY_INCLUDES = \ + $(shell pkg-config --cflags-only-I xvmc) \ + -I$(TOP)/src/gallium/winsys/g3dvl + +C_SOURCES = block.c \ + surface.c \ + context.c \ + subpicture.c \ + attributes.c + +include ../../../Makefile.template diff --git a/src/gallium/state_trackers/xorg/xvmc/attributes.c b/src/gallium/state_trackers/xorg/xvmc/attributes.c new file mode 100644 index 00000000000..817af531a32 --- /dev/null +++ b/src/gallium/state_trackers/xorg/xvmc/attributes.c @@ -0,0 +1,156 @@ +/************************************************************************** + * + * Copyright 2009 Younes Manton. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include <assert.h> +#include <stdlib.h> + +#include <X11/Xlib.h> +#include <X11/extensions/Xvlib.h> +#include <X11/extensions/XvMClib.h> + +#include <vl/vl_compositor.h> + +#include "xvmc_private.h" + +#define XV_BRIGHTNESS "XV_BRIGHTNESS" +#define XV_CONTRAST "XV_CONTRAST" +#define XV_SATURATION "XV_SATURATION" +#define XV_HUE "XV_HUE" +#define XV_COLORSPACE "XV_COLORSPACE" + +static const XvAttribute attributes[] = { + { XvGettable | XvSettable, -1000, 1000, XV_BRIGHTNESS }, + { XvGettable | XvSettable, -1000, 1000, XV_CONTRAST }, + { XvGettable | XvSettable, -1000, 1000, XV_SATURATION }, + { XvGettable | XvSettable, -1000, 1000, XV_HUE }, + { XvGettable | XvSettable, 0, 1, XV_COLORSPACE } +}; + +PUBLIC +XvAttribute* XvMCQueryAttributes(Display *dpy, XvMCContext *context, int *number) +{ + XvMCContextPrivate *context_priv; + XvAttribute *result; + + assert(dpy && number); + + if (!context || !context->privData) + return NULL; + + context_priv = context->privData; + + result = malloc(sizeof(attributes)); + if (!result) + return NULL; + + memcpy(result, attributes, sizeof(attributes)); + *number = sizeof(attributes) / sizeof(XvAttribute); + + XVMC_MSG(XVMC_TRACE, "[XvMC] Returning %d attributes for context %p.\n", *number, context); + + return result; +} + +PUBLIC +Status XvMCSetAttribute(Display *dpy, XvMCContext *context, Atom attribute, int value) +{ + XvMCContextPrivate *context_priv; + const char *attr; + float csc[16]; + + assert(dpy); + + if (!context || !context->privData) + return XvMCBadContext; + + context_priv = context->privData; + + attr = XGetAtomName(dpy, attribute); + if (!attr) + return XvMCBadContext; + + if (strcmp(attr, XV_BRIGHTNESS)) + context_priv->procamp.brightness = value / 1000.0f; + else if (strcmp(attr, XV_CONTRAST)) + context_priv->procamp.contrast = value / 1000.0f + 1.0f; + else if (strcmp(attr, XV_SATURATION)) + context_priv->procamp.saturation = value / 1000.0f + 1.0f; + else if (strcmp(attr, XV_HUE)) + context_priv->procamp.hue = value / 1000.0f; + else if (strcmp(attr, XV_COLORSPACE)) + context_priv->color_standard = value ? + VL_CSC_COLOR_STANDARD_BT_601 : + VL_CSC_COLOR_STANDARD_BT_709; + else + return BadName; + + vl_csc_get_matrix + ( + context_priv->color_standard, + &context_priv->procamp, true, csc + ); + vl_compositor_set_csc_matrix(&context_priv->compositor, csc); + + XVMC_MSG(XVMC_TRACE, "[XvMC] Set attribute %s to value %d.\n", attr, value); + + return Success; +} + +PUBLIC +Status XvMCGetAttribute(Display *dpy, XvMCContext *context, Atom attribute, int *value) +{ + XvMCContextPrivate *context_priv; + const char *attr; + + assert(dpy); + + if (!context || !context->privData) + return XvMCBadContext; + + context_priv = context->privData; + + attr = XGetAtomName(dpy, attribute); + if (!attr) + return XvMCBadContext; + + if (strcmp(attr, XV_BRIGHTNESS)) + *value = context_priv->procamp.brightness * 1000; + else if (strcmp(attr, XV_CONTRAST)) + *value = context_priv->procamp.contrast * 1000 - 1000; + else if (strcmp(attr, XV_SATURATION)) + *value = context_priv->procamp.saturation * 1000 + 1000; + else if (strcmp(attr, XV_HUE)) + *value = context_priv->procamp.hue * 1000; + else if (strcmp(attr, XV_COLORSPACE)) + *value = context_priv->color_standard == VL_CSC_COLOR_STANDARD_BT_709; + else + return BadName; + + XVMC_MSG(XVMC_TRACE, "[XvMC] Got value %d for attribute %s.\n", *value, attr); + + return Success; +} diff --git a/src/gallium/state_trackers/xorg/xvmc/block.c b/src/gallium/state_trackers/xorg/xvmc/block.c new file mode 100644 index 00000000000..6b0b21273f5 --- /dev/null +++ b/src/gallium/state_trackers/xorg/xvmc/block.c @@ -0,0 +1,95 @@ +/************************************************************************** + * + * Copyright 2009 Younes Manton. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include <assert.h> + +#include <X11/Xlib.h> +#include <X11/extensions/XvMClib.h> + +#include <util/u_memory.h> + +#include "xvmc_private.h" + +PUBLIC +Status XvMCCreateBlocks(Display *dpy, XvMCContext *context, unsigned int num_blocks, XvMCBlockArray *blocks) +{ + assert(dpy); + + if (!context) + return XvMCBadContext; + if (num_blocks == 0) + return BadValue; + + assert(blocks); + + blocks->context_id = context->context_id; + blocks->num_blocks = num_blocks; + blocks->blocks = MALLOC(BLOCK_SIZE_BYTES * num_blocks); + blocks->privData = NULL; + + return Success; +} + +PUBLIC +Status XvMCDestroyBlocks(Display *dpy, XvMCBlockArray *blocks) +{ + assert(dpy); + assert(blocks); + FREE(blocks->blocks); + + return Success; +} + +PUBLIC +Status XvMCCreateMacroBlocks(Display *dpy, XvMCContext *context, unsigned int num_blocks, XvMCMacroBlockArray *blocks) +{ + assert(dpy); + + if (!context) + return XvMCBadContext; + if (num_blocks == 0) + return BadValue; + + assert(blocks); + + blocks->context_id = context->context_id; + blocks->num_blocks = num_blocks; + blocks->macro_blocks = MALLOC(sizeof(XvMCMacroBlock) * num_blocks); + blocks->privData = NULL; + + return Success; +} + +PUBLIC +Status XvMCDestroyMacroBlocks(Display *dpy, XvMCMacroBlockArray *blocks) +{ + assert(dpy); + assert(blocks); + FREE(blocks->macro_blocks); + + return Success; +} diff --git a/src/gallium/state_trackers/xorg/xvmc/context.c b/src/gallium/state_trackers/xorg/xvmc/context.c new file mode 100644 index 00000000000..f21ebda76d3 --- /dev/null +++ b/src/gallium/state_trackers/xorg/xvmc/context.c @@ -0,0 +1,332 @@ +/************************************************************************** + * + * Copyright 2009 Younes Manton. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include <assert.h> + +#include <X11/Xlibint.h> +#include <X11/extensions/XvMClib.h> + +#include <pipe/p_screen.h> +#include <pipe/p_video_decoder.h> +#include <pipe/p_video_state.h> +#include <pipe/p_state.h> + +#include <util/u_memory.h> + +#include <vl/vl_csc.h> +#include <vl_winsys.h> + +#include "xvmc_private.h" + +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, int *surface_flags, + unsigned short *subpic_max_w, + unsigned short *subpic_max_h) +{ + bool found_surface = false; + XvAdaptorInfo *adaptor_info; + unsigned int num_adaptors; + int num_types; + unsigned int max_width = 0, max_height = 0; + Status ret; + + assert(dpy); + assert(found_port); + assert(screen); + assert(chroma_format); + assert(mc_type); + assert(surface_flags); + assert(subpic_max_w); + assert(subpic_max_h); + + *found_port = false; + + for (unsigned int i = 0; i < XScreenCount(dpy); ++i) { + ret = XvQueryAdaptors(dpy, XRootWindow(dpy, i), &num_adaptors, &adaptor_info); + if (ret != Success) + return ret; + + 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; + + if (adaptor_info[j].base_id + k != port) + continue; + + *found_port = true; + + surface_info = XvMCListSurfaceTypes(dpy, adaptor_info[j].base_id, &num_types); + if (!surface_info) { + XvFreeAdaptorInfo(adaptor_info); + return BadAlloc; + } + + for (unsigned int l = 0; l < num_types && !found_surface; ++l) { + if (surface_info[l].surface_type_id != surface_type_id) + continue; + + 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; + *surface_flags = surface_info[l].flags; + *subpic_max_w = surface_info[l].subpicture_max_width; + *subpic_max_h = surface_info[l].subpicture_max_height; + *screen = i; + + XVMC_MSG(XVMC_TRACE, "[XvMC] Found requested context surface format.\n" \ + "[XvMC] screen=%u, port=%u\n" \ + "[XvMC] id=0x%08X\n" \ + "[XvMC] max width=%u, max height=%u\n" \ + "[XvMC] chroma format=0x%08X\n" \ + "[XvMC] acceleration level=0x%08X\n" \ + "[XvMC] flags=0x%08X\n" \ + "[XvMC] subpicture max width=%u, max height=%u\n", + i, port, surface_type_id, max_width, max_height, *chroma_format, + *mc_type, *surface_flags, *subpic_max_w, *subpic_max_h); + } + + XFree(surface_info); + } + } + + XvFreeAdaptorInfo(adaptor_info); + } + + if (!*found_port) { + XVMC_MSG(XVMC_ERR, "[XvMC] Could not find a suitable port.\n"); + return XvBadPort; + } + if (!found_surface) { + XVMC_MSG(XVMC_ERR, "[XvMC] Could not find a suitable surface.\n"); + return BadMatch; + } + if (width > max_width || height > max_height) { + XVMC_MSG(XVMC_ERR, "[XvMC] Requested context dimensions (w=%u,h=%u) too large (max w=%u,h=%u).\n", + width, height, max_width, max_height); + return BadValue; + } + if (flags != XVMC_DIRECT && flags != 0) { + XVMC_MSG(XVMC_ERR, "[XvMC] Invalid context flags 0x%08X.\n", flags); + return BadValue; + } + + return Success; +} + +static enum pipe_video_profile ProfileToPipe(int xvmc_profile) +{ + 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); + + XVMC_MSG(XVMC_ERR, "[XvMC] Unrecognized profile 0x%08X.\n", xvmc_profile); + + return -1; +} + +static enum pipe_video_chroma_format FormatToPipe(int xvmc_format) +{ + 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); + } + + XVMC_MSG(XVMC_ERR, "[XvMC] Unrecognized format 0x%08X.\n", xvmc_format); + + return -1; +} + +PUBLIC +Status XvMCCreateContext(Display *dpy, XvPortID port, int surface_type_id, + int width, int height, int flags, XvMCContext *context) +{ + bool found_port; + int scrn = 0; + int chroma_format = 0; + int mc_type = 0; + int surface_flags = 0; + unsigned short subpic_max_w = 0; + unsigned short subpic_max_h = 0; + Status ret; + struct vl_screen *vscreen; + struct vl_context *vctx; + XvMCContextPrivate *context_priv; + float csc[16]; + + XVMC_MSG(XVMC_TRACE, "[XvMC] Creating context %p.\n", context); + + assert(dpy); + + if (!context) + return XvMCBadContext; + + ret = Validate(dpy, port, surface_type_id, width, height, flags, + &found_port, &scrn, &chroma_format, &mc_type, &surface_flags, + &subpic_max_w, &subpic_max_h); + + /* Success and XvBadPort have the same value */ + if (ret != Success || !found_port) + return ret; + + /* XXX: Current limits */ + if (chroma_format != XVMC_CHROMA_FORMAT_420) { + XVMC_MSG(XVMC_ERR, "[XvMC] Cannot decode requested surface type. Unsupported chroma format.\n"); + return BadImplementation; + } + if ((mc_type & ~XVMC_IDCT) != (XVMC_MOCOMP | XVMC_MPEG_2)) { + XVMC_MSG(XVMC_ERR, "[XvMC] Cannot decode requested surface type. Non-MPEG2/Mocomp/iDCT acceleration unsupported.\n"); + return BadImplementation; + } + if (surface_flags & XVMC_INTRA_UNSIGNED) { + XVMC_MSG(XVMC_ERR, "[XvMC] Cannot decode requested surface type. Unsigned intra unsupported.\n"); + return BadImplementation; + } + + context_priv = CALLOC(1, sizeof(XvMCContextPrivate)); + if (!context_priv) + return BadAlloc; + + /* TODO: Reuse screen if process creates another context */ + vscreen = vl_screen_create(dpy, scrn); + + if (!vscreen) { + XVMC_MSG(XVMC_ERR, "[XvMC] Could not create VL screen.\n"); + FREE(context_priv); + return BadAlloc; + } + + vctx = vl_video_create(vscreen); + if (!vctx) { + XVMC_MSG(XVMC_ERR, "[XvMC] Could not create VL context.\n"); + vl_screen_destroy(vscreen); + FREE(context_priv); + return BadAlloc; + } + + context_priv->decoder = vctx->pipe->create_video_decoder + ( + vctx->pipe, + ProfileToPipe(mc_type), + (mc_type & XVMC_IDCT) ? PIPE_VIDEO_ENTRYPOINT_IDCT : PIPE_VIDEO_ENTRYPOINT_MC, + FormatToPipe(chroma_format), + width, height + ); + + if (!context_priv->decoder) { + XVMC_MSG(XVMC_ERR, "[XvMC] Could not create VL decoder.\n"); + vl_video_destroy(vctx); + vl_screen_destroy(vscreen); + FREE(context_priv); + return BadAlloc; + } + + if (!vl_compositor_init(&context_priv->compositor, vctx->pipe)) { + XVMC_MSG(XVMC_ERR, "[XvMC] Could not create VL compositor.\n"); + context_priv->decoder->destroy(context_priv->decoder); + vl_video_destroy(vctx); + vl_screen_destroy(vscreen); + FREE(context_priv); + return BadAlloc; + } + + context_priv->color_standard = + debug_get_bool_option("G3DVL_NO_CSC", FALSE) ? + VL_CSC_COLOR_STANDARD_IDENTITY : VL_CSC_COLOR_STANDARD_BT_601; + context_priv->procamp = vl_default_procamp; + + vl_csc_get_matrix + ( + context_priv->color_standard, + &context_priv->procamp, true, csc + ); + vl_compositor_set_csc_matrix(&context_priv->compositor, csc); + + context_priv->vctx = vctx; + context_priv->subpicture_max_width = subpic_max_w; + context_priv->subpicture_max_height = subpic_max_h; + + 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(); + + XVMC_MSG(XVMC_TRACE, "[XvMC] Context %p created.\n", context); + + return Success; +} + +PUBLIC +Status XvMCDestroyContext(Display *dpy, XvMCContext *context) +{ + struct vl_screen *vscreen; + struct vl_context *vctx; + XvMCContextPrivate *context_priv; + + XVMC_MSG(XVMC_TRACE, "[XvMC] Destroying context %p.\n", context); + + assert(dpy); + + if (!context || !context->privData) + return XvMCBadContext; + + context_priv = context->privData; + vctx = context_priv->vctx; + vscreen = vctx->vscreen; + pipe_surface_reference(&context_priv->drawable_surface, NULL); + context_priv->decoder->destroy(context_priv->decoder); + vl_compositor_cleanup(&context_priv->compositor); + vl_video_destroy(vctx); + vl_screen_destroy(vscreen); + FREE(context_priv); + context->privData = NULL; + + XVMC_MSG(XVMC_TRACE, "[XvMC] Context %p destroyed.\n", context); + + return Success; +} diff --git a/src/gallium/state_trackers/xorg/xvmc/subpicture.c b/src/gallium/state_trackers/xorg/xvmc/subpicture.c new file mode 100644 index 00000000000..7d6ff061eb7 --- /dev/null +++ b/src/gallium/state_trackers/xorg/xvmc/subpicture.c @@ -0,0 +1,561 @@ +/************************************************************************** + * + * Copyright 2009 Younes Manton. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include <assert.h> + +#include <X11/Xlibint.h> +#include <X11/extensions/XvMClib.h> +#include <xorg/fourcc.h> + +#include <pipe/p_screen.h> +#include <pipe/p_video_decoder.h> +#include <pipe/p_state.h> + +#include <util/u_memory.h> +#include <util/u_math.h> +#include <util/u_format.h> +#include <util/u_sampler.h> +#include <util/u_rect.h> + +#include <vl_winsys.h> + +#include "xvmc_private.h" + +#define FOURCC_RGB 0x0000003 + +static enum pipe_format XvIDToPipe(int xvimage_id) +{ + switch (xvimage_id) { + case FOURCC_RGB: + return PIPE_FORMAT_B8G8R8X8_UNORM; + + case FOURCC_AI44: + case FOURCC_IA44: + return PIPE_FORMAT_L4A4_UNORM; + + default: + XVMC_MSG(XVMC_ERR, "[XvMC] Unrecognized Xv image ID 0x%08X.\n", xvimage_id); + return PIPE_FORMAT_NONE; + } +} + +static unsigned NumPaletteEntries4XvID(int xvimage_id) +{ + switch (xvimage_id) { + case FOURCC_RGB: + return 0; + + case FOURCC_AI44: + case FOURCC_IA44: + return 16; + + default: + XVMC_MSG(XVMC_ERR, "[XvMC] Unrecognized Xv image ID 0x%08X.\n", xvimage_id); + return 0; + } +} + +static void XvIDToSwizzle(int xvimage_id, struct pipe_sampler_view *tmpl) +{ + switch (xvimage_id) { + default: + XVMC_MSG(XVMC_ERR, "[XvMC] Unrecognized Xv image ID 0x%08X.\n", xvimage_id); + + /* fall through */ + case FOURCC_RGB: + tmpl->swizzle_r = PIPE_SWIZZLE_BLUE; + tmpl->swizzle_g = PIPE_SWIZZLE_GREEN; + tmpl->swizzle_b = PIPE_SWIZZLE_RED; + tmpl->swizzle_a = PIPE_SWIZZLE_ONE; + break; + + case FOURCC_IA44: + tmpl->swizzle_r = PIPE_SWIZZLE_ALPHA; + tmpl->swizzle_g = PIPE_SWIZZLE_ZERO; + tmpl->swizzle_b = PIPE_SWIZZLE_ZERO; + tmpl->swizzle_a = PIPE_SWIZZLE_RED; + break; + + case FOURCC_AI44: + tmpl->swizzle_r = PIPE_SWIZZLE_RED; + tmpl->swizzle_g = PIPE_SWIZZLE_ZERO; + tmpl->swizzle_b = PIPE_SWIZZLE_ZERO; + tmpl->swizzle_a = PIPE_SWIZZLE_ALPHA; + break; + } +} + +static int PipeToComponentOrder(enum pipe_format format, char *component_order) +{ + assert(component_order); + + switch (format) { + case PIPE_FORMAT_B8G8R8X8_UNORM: + return 0; + + case PIPE_FORMAT_L4A4_UNORM: + component_order[0] = 'Y'; + component_order[1] = 'U'; + component_order[2] = 'V'; + component_order[3] = 'A'; + return 4; + + default: + XVMC_MSG(XVMC_ERR, "[XvMC] Unrecognized PIPE_FORMAT 0x%08X.\n", format); + component_order[0] = 0; + component_order[1] = 0; + component_order[2] = 0; + component_order[3] = 0; + return 0; + } +} + +static Status Validate(Display *dpy, XvPortID port, int surface_type_id, int xvimage_id) +{ + XvImageFormatValues *subpictures; + int num_subpics; + unsigned int i; + + subpictures = XvMCListSubpictureTypes(dpy, port, surface_type_id, &num_subpics); + if (num_subpics < 1) { + if (subpictures) + XFree(subpictures); + return BadMatch; + } + if (!subpictures) + return BadAlloc; + + for (i = 0; i < num_subpics; ++i) { + if (subpictures[i].id == xvimage_id) { + XVMC_MSG(XVMC_TRACE, "[XvMC] Found requested subpicture format.\n" \ + "[XvMC] port=%u\n" \ + "[XvMC] surface id=0x%08X\n" \ + "[XvMC] image id=0x%08X\n" \ + "[XvMC] type=%08X\n" \ + "[XvMC] byte order=%08X\n" \ + "[XvMC] bits per pixel=%u\n" \ + "[XvMC] format=%08X\n" \ + "[XvMC] num planes=%d\n", + port, surface_type_id, xvimage_id, subpictures[i].type, subpictures[i].byte_order, + subpictures[i].bits_per_pixel, subpictures[i].format, subpictures[i].num_planes); + if (subpictures[i].type == XvRGB) { + XVMC_MSG(XVMC_TRACE, "[XvMC] depth=%d\n" \ + "[XvMC] red mask=0x%08X\n" \ + "[XvMC] green mask=0x%08X\n" \ + "[XvMC] blue mask=0x%08X\n", + subpictures[i].depth, subpictures[i].red_mask, + subpictures[i].green_mask, subpictures[i].blue_mask); + } + else if (subpictures[i].type == XvYUV) { + XVMC_MSG(XVMC_TRACE, "[XvMC] y sample bits=0x%08X\n" \ + "[XvMC] u sample bits=0x%08X\n" \ + "[XvMC] v sample bits=0x%08X\n" \ + "[XvMC] horz y period=%u\n" \ + "[XvMC] horz u period=%u\n" \ + "[XvMC] horz v period=%u\n" \ + "[XvMC] vert y period=%u\n" \ + "[XvMC] vert u period=%u\n" \ + "[XvMC] vert v period=%u\n", + subpictures[i].y_sample_bits, subpictures[i].u_sample_bits, subpictures[i].v_sample_bits, + subpictures[i].horz_y_period, subpictures[i].horz_u_period, subpictures[i].horz_v_period, + subpictures[i].vert_y_period, subpictures[i].vert_u_period, subpictures[i].vert_v_period); + } + break; + } + } + + XFree(subpictures); + + return i < num_subpics ? Success : BadMatch; +} + +static void +upload_sampler(struct pipe_context *pipe, struct pipe_sampler_view *dst, + const struct pipe_box *dst_box, const void *src, unsigned src_stride, + unsigned src_x, unsigned src_y) +{ + struct pipe_transfer *transfer; + void *map; + + transfer = pipe->get_transfer(pipe, dst->texture, 0, PIPE_TRANSFER_WRITE, dst_box); + if (!transfer) + return; + + map = pipe->transfer_map(pipe, transfer); + if (map) { + util_copy_rect(map, dst->texture->format, transfer->stride, 0, 0, + dst_box->width, dst_box->height, + src, src_stride, src_x, src_y); + + pipe->transfer_unmap(pipe, transfer); + } + + pipe->transfer_destroy(pipe, transfer); +} + +PUBLIC +Status XvMCCreateSubpicture(Display *dpy, XvMCContext *context, XvMCSubpicture *subpicture, + unsigned short width, unsigned short height, int xvimage_id) +{ + XvMCContextPrivate *context_priv; + XvMCSubpicturePrivate *subpicture_priv; + struct pipe_context *pipe; + struct pipe_resource tex_templ, *tex; + struct pipe_sampler_view sampler_templ; + Status ret; + + XVMC_MSG(XVMC_TRACE, "[XvMC] Creating subpicture %p.\n", subpicture); + + assert(dpy); + + if (!context) + return XvMCBadContext; + + context_priv = context->privData; + pipe = context_priv->vctx->pipe; + + if (!subpicture) + return XvMCBadSubpicture; + + if (width > context_priv->subpicture_max_width || + height > context_priv->subpicture_max_height) + return BadValue; + + ret = Validate(dpy, context->port, context->surface_type_id, xvimage_id); + if (ret != Success) + return ret; + + subpicture_priv = CALLOC(1, sizeof(XvMCSubpicturePrivate)); + if (!subpicture_priv) + return BadAlloc; + + memset(&tex_templ, 0, sizeof(tex_templ)); + tex_templ.target = PIPE_TEXTURE_2D; + tex_templ.format = XvIDToPipe(xvimage_id); + tex_templ.last_level = 0; + if (pipe->screen->get_video_param(pipe->screen, + PIPE_VIDEO_PROFILE_UNKNOWN, + PIPE_VIDEO_CAP_NPOT_TEXTURES)) { + tex_templ.width0 = width; + tex_templ.height0 = height; + } + else { + tex_templ.width0 = util_next_power_of_two(width); + tex_templ.height0 = util_next_power_of_two(height); + } + tex_templ.depth0 = 1; + tex_templ.array_size = 1; + tex_templ.usage = PIPE_USAGE_DYNAMIC; + tex_templ.bind = PIPE_BIND_SAMPLER_VIEW; + tex_templ.flags = 0; + + tex = pipe->screen->resource_create(pipe->screen, &tex_templ); + + memset(&sampler_templ, 0, sizeof(sampler_templ)); + u_sampler_view_default_template(&sampler_templ, tex, tex->format); + XvIDToSwizzle(xvimage_id, &sampler_templ); + + subpicture_priv->sampler = pipe->create_sampler_view(pipe, tex, &sampler_templ); + pipe_resource_reference(&tex, NULL); + if (!subpicture_priv->sampler) { + FREE(subpicture_priv); + return BadAlloc; + } + + subpicture_priv->context = context; + 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 = NumPaletteEntries4XvID(xvimage_id); + subpicture->entry_bytes = PipeToComponentOrder(tex_templ.format, subpicture->component_order); + subpicture->privData = subpicture_priv; + + if (subpicture->num_palette_entries > 0) { + tex_templ.target = PIPE_TEXTURE_1D; + tex_templ.format = PIPE_FORMAT_R8G8B8A8_UNORM; + tex_templ.width0 = subpicture->num_palette_entries; + tex_templ.height0 = 1; + tex_templ.usage = PIPE_USAGE_STATIC; + + tex = pipe->screen->resource_create(pipe->screen, &tex_templ); + + memset(&sampler_templ, 0, sizeof(sampler_templ)); + u_sampler_view_default_template(&sampler_templ, tex, tex->format); + sampler_templ.swizzle_a = PIPE_SWIZZLE_ONE; + subpicture_priv->palette = pipe->create_sampler_view(pipe, tex, &sampler_templ); + pipe_resource_reference(&tex, NULL); + if (!subpicture_priv->sampler) { + FREE(subpicture_priv); + return BadAlloc; + } + } + + SyncHandle(); + + XVMC_MSG(XVMC_TRACE, "[XvMC] Subpicture %p created.\n", subpicture); + + return Success; +} + +PUBLIC +Status XvMCClearSubpicture(Display *dpy, XvMCSubpicture *subpicture, short x, short y, + unsigned short width, unsigned short height, unsigned int color) +{ + XvMCSubpicturePrivate *subpicture_priv; + XvMCContextPrivate *context_priv; + struct pipe_context *pipe; + struct pipe_sampler_view *dst; + struct pipe_box dst_box = {x, y, 0, width, height, 1}; + struct pipe_transfer *transfer; + union util_color uc; + void *map; + + assert(dpy); + + if (!subpicture) + return XvMCBadSubpicture; + + /* Convert color to float */ + util_format_read_4f(PIPE_FORMAT_B8G8R8A8_UNORM, + uc.f, 1, &color, 4, + 0, 0, 1, 1); + + subpicture_priv = subpicture->privData; + context_priv = subpicture_priv->context->privData; + pipe = context_priv->vctx->pipe; + dst = subpicture_priv->sampler; + + /* TODO: Assert clear rect is within bounds? Or clip? */ + transfer = pipe->get_transfer(pipe, dst->texture, 0, PIPE_TRANSFER_WRITE, &dst_box); + if (!transfer) + return XvMCBadSubpicture; + + map = pipe->transfer_map(pipe, transfer); + if (map) { + util_fill_rect(map, dst->texture->format, transfer->stride, 0, 0, + dst_box.width, dst_box.height, &uc); + + pipe->transfer_unmap(pipe, transfer); + } + + pipe->transfer_destroy(pipe, transfer); + + return Success; +} + +PUBLIC +Status XvMCCompositeSubpicture(Display *dpy, XvMCSubpicture *subpicture, XvImage *image, + short srcx, short srcy, unsigned short width, unsigned short height, + short dstx, short dsty) +{ + XvMCSubpicturePrivate *subpicture_priv; + XvMCContextPrivate *context_priv; + struct pipe_context *pipe; + struct pipe_box dst_box = {dstx, dsty, 0, width, height, 1}; + unsigned src_stride; + + XVMC_MSG(XVMC_TRACE, "[XvMC] Compositing subpicture %p.\n", subpicture); + + assert(dpy); + + if (!subpicture) + return XvMCBadSubpicture; + + assert(image); + + if (subpicture->xvimage_id != image->id) + return BadMatch; + + /* No planar support for now */ + if (image->num_planes != 1) + return BadMatch; + + subpicture_priv = subpicture->privData; + context_priv = subpicture_priv->context->privData; + pipe = context_priv->vctx->pipe; + + /* clipping should be done by upload_sampler and regardles what the documentation + says image->pitches[0] doesn't seems to be in bytes, so don't use it */ + src_stride = image->width * util_format_get_blocksize(subpicture_priv->sampler->texture->format); + upload_sampler(pipe, subpicture_priv->sampler, &dst_box, image->data, src_stride, srcx, srcy); + + XVMC_MSG(XVMC_TRACE, "[XvMC] Subpicture %p composited.\n", subpicture); + + return Success; +} + +PUBLIC +Status XvMCDestroySubpicture(Display *dpy, XvMCSubpicture *subpicture) +{ + XvMCSubpicturePrivate *subpicture_priv; + + XVMC_MSG(XVMC_TRACE, "[XvMC] Destroying subpicture %p.\n", subpicture); + + assert(dpy); + + if (!subpicture) + return XvMCBadSubpicture; + + subpicture_priv = subpicture->privData; + pipe_sampler_view_reference(&subpicture_priv->sampler, NULL); + pipe_sampler_view_reference(&subpicture_priv->palette, NULL); + FREE(subpicture_priv); + + XVMC_MSG(XVMC_TRACE, "[XvMC] Subpicture %p destroyed.\n", subpicture); + + return Success; +} + +PUBLIC +Status XvMCSetSubpicturePalette(Display *dpy, XvMCSubpicture *subpicture, unsigned char *palette) +{ + XvMCSubpicturePrivate *subpicture_priv; + XvMCContextPrivate *context_priv; + struct pipe_context *pipe; + struct pipe_box dst_box = {0, 0, 0, 0, 1, 1}; + + assert(dpy); + assert(palette); + + if (!subpicture) + return XvMCBadSubpicture; + + subpicture_priv = subpicture->privData; + context_priv = subpicture_priv->context->privData; + pipe = context_priv->vctx->pipe; + + dst_box.width = subpicture->num_palette_entries; + + upload_sampler(pipe, subpicture_priv->palette, &dst_box, palette, 0, 0, 0); + + XVMC_MSG(XVMC_TRACE, "[XvMC] Palette of Subpicture %p set.\n", subpicture); + + return Success; +} + +PUBLIC +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) +{ + struct pipe_video_rect src_rect = {subx, suby, subw, subh}; + struct pipe_video_rect dst_rect = {surfx, surfy, surfw, surfh}; + + XvMCSurfacePrivate *surface_priv; + XvMCSubpicturePrivate *subpicture_priv; + + XVMC_MSG(XVMC_TRACE, "[XvMC] Associating subpicture %p with surface %p.\n", subpicture, target_surface); + + assert(dpy); + + if (!target_surface) + return XvMCBadSurface; + + if (!subpicture) + return XvMCBadSubpicture; + + if (target_surface->context_id != subpicture->context_id) + return BadMatch; + + /* TODO: Verify against subpicture independent scaling */ + + surface_priv = target_surface->privData; + subpicture_priv = subpicture->privData; + + /* TODO: Assert rects are within bounds? Or clip? */ + subpicture_priv->src_rect = src_rect; + subpicture_priv->dst_rect = dst_rect; + + surface_priv->subpicture = subpicture; + subpicture_priv->surface = target_surface; + + return Success; +} + +PUBLIC +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(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; +} + +PUBLIC +Status XvMCSyncSubpicture(Display *dpy, XvMCSubpicture *subpicture) +{ + assert(dpy); + + if (!subpicture) + return XvMCBadSubpicture; + + return Success; +} + +PUBLIC +Status XvMCFlushSubpicture(Display *dpy, XvMCSubpicture *subpicture) +{ + assert(dpy); + + if (!subpicture) + return XvMCBadSubpicture; + + return Success; +} + +PUBLIC +Status XvMCGetSubpictureStatus(Display *dpy, XvMCSubpicture *subpicture, int *status) +{ + assert(dpy); + + if (!subpicture) + return XvMCBadSubpicture; + + assert(status); + + /* TODO */ + *status = 0; + + return Success; +} diff --git a/src/gallium/state_trackers/xorg/xvmc/surface.c b/src/gallium/state_trackers/xorg/xvmc/surface.c new file mode 100644 index 00000000000..aef1eff2bb3 --- /dev/null +++ b/src/gallium/state_trackers/xorg/xvmc/surface.c @@ -0,0 +1,664 @@ +/************************************************************************** + * + * Copyright 2009 Younes Manton. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include <assert.h> +#include <stdio.h> + +#include <X11/Xlibint.h> + +#include <pipe/p_video_decoder.h> +#include <pipe/p_video_state.h> +#include <pipe/p_state.h> + +#include <util/u_inlines.h> +#include <util/u_memory.h> +#include <util/u_math.h> + +#include <vl_winsys.h> + +#include "xvmc_private.h" + +static const unsigned const_empty_block_mask_420[3][2][2] = { + { { 0x20, 0x10 }, { 0x08, 0x04 } }, + { { 0x02, 0x02 }, { 0x02, 0x02 } }, + { { 0x01, 0x01 }, { 0x01, 0x01 } } +}; + +static enum pipe_mpeg12_picture_type PictureToPipe(int xvmc_pic) +{ + 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); + } + + XVMC_MSG(XVMC_ERR, "[XvMC] Unrecognized picture type 0x%08X.\n", xvmc_pic); + + return -1; +} + +static inline void +MacroBlockTypeToPipeWeights(const XvMCMacroBlock *xvmc_mb, unsigned weights[2]) +{ + assert(xvmc_mb); + + switch (xvmc_mb->macroblock_type & (XVMC_MB_TYPE_MOTION_FORWARD | XVMC_MB_TYPE_MOTION_BACKWARD)) { + case XVMC_MB_TYPE_MOTION_FORWARD: + weights[0] = PIPE_VIDEO_MV_WEIGHT_MAX; + weights[1] = PIPE_VIDEO_MV_WEIGHT_MIN; + break; + + case (XVMC_MB_TYPE_MOTION_FORWARD | XVMC_MB_TYPE_MOTION_BACKWARD): + weights[0] = PIPE_VIDEO_MV_WEIGHT_HALF; + weights[1] = PIPE_VIDEO_MV_WEIGHT_HALF; + break; + + case XVMC_MB_TYPE_MOTION_BACKWARD: + weights[0] = PIPE_VIDEO_MV_WEIGHT_MIN; + weights[1] = PIPE_VIDEO_MV_WEIGHT_MAX; + break; + + default: + /* workaround for xines xxmc video out plugin */ + if (!(xvmc_mb->macroblock_type & ~XVMC_MB_TYPE_PATTERN)) { + weights[0] = PIPE_VIDEO_MV_WEIGHT_MAX; + weights[1] = PIPE_VIDEO_MV_WEIGHT_MIN; + } else { + weights[0] = PIPE_VIDEO_MV_WEIGHT_MIN; + weights[1] = PIPE_VIDEO_MV_WEIGHT_MIN; + } + break; + } +} + +static inline struct pipe_motionvector +MotionVectorToPipe(const XvMCMacroBlock *xvmc_mb, unsigned vector, + unsigned field_select_mask, unsigned weight) +{ + struct pipe_motionvector mv; + + assert(xvmc_mb); + + switch (xvmc_mb->motion_type) { + case XVMC_PREDICTION_FRAME: + mv.top.x = xvmc_mb->PMV[0][vector][0]; + mv.top.y = xvmc_mb->PMV[0][vector][1]; + mv.top.field_select = PIPE_VIDEO_FRAME; + mv.top.weight = weight; + + mv.bottom.x = xvmc_mb->PMV[0][vector][0]; + mv.bottom.y = xvmc_mb->PMV[0][vector][1]; + mv.bottom.weight = weight; + mv.bottom.field_select = PIPE_VIDEO_FRAME; + break; + + case XVMC_PREDICTION_FIELD: + mv.top.x = xvmc_mb->PMV[0][vector][0]; + mv.top.y = xvmc_mb->PMV[0][vector][1]; + mv.top.field_select = (xvmc_mb->motion_vertical_field_select & field_select_mask) ? + PIPE_VIDEO_BOTTOM_FIELD : PIPE_VIDEO_TOP_FIELD; + mv.top.weight = weight; + + mv.bottom.x = xvmc_mb->PMV[1][vector][0]; + mv.bottom.y = xvmc_mb->PMV[1][vector][1]; + mv.bottom.field_select = (xvmc_mb->motion_vertical_field_select & (field_select_mask << 2)) ? + PIPE_VIDEO_BOTTOM_FIELD : PIPE_VIDEO_TOP_FIELD; + mv.bottom.weight = weight; + break; + + default: // TODO: Support DUALPRIME and 16x8 + break; + } + + return mv; +} + +static inline void +UploadYcbcrBlocks(XvMCSurfacePrivate *surface, + const XvMCMacroBlock *xvmc_mb, + const XvMCBlockArray *xvmc_blocks) +{ + enum pipe_mpeg12_dct_intra intra; + enum pipe_mpeg12_dct_type coding; + + unsigned tb, x, y, luma_blocks; + short *blocks; + + assert(surface); + assert(xvmc_mb); + + if (!xvmc_mb->coded_block_pattern) + return; + + intra = xvmc_mb->macroblock_type & XVMC_MB_TYPE_INTRA ? + PIPE_MPEG12_DCT_INTRA : PIPE_MPEG12_DCT_DELTA; + + coding = xvmc_mb->dct_type == XVMC_DCT_TYPE_FIELD ? + PIPE_MPEG12_DCT_TYPE_FIELD : PIPE_MPEG12_DCT_TYPE_FRAME; + + blocks = xvmc_blocks->blocks + xvmc_mb->index * BLOCK_SIZE_SAMPLES; + + for (y = 0, luma_blocks = 0; y < 2; ++y) { + for (x = 0; x < 2; ++x, ++tb) { + if (xvmc_mb->coded_block_pattern & const_empty_block_mask_420[0][y][x]) { + + struct pipe_ycbcr_block *stream = surface->ycbcr[0].stream; + stream->x = xvmc_mb->x * 2 + x; + stream->y = xvmc_mb->y * 2 + y; + stream->intra = intra; + stream->coding = coding; + + surface->ycbcr[0].num_blocks_added++; + surface->ycbcr[0].stream++; + + luma_blocks++; + } + } + } + + if (luma_blocks > 0) { + memcpy(surface->ycbcr[0].buffer, blocks, BLOCK_SIZE_BYTES * luma_blocks); + surface->ycbcr[0].buffer += BLOCK_SIZE_SAMPLES * luma_blocks; + blocks += BLOCK_SIZE_SAMPLES * luma_blocks; + } + + /* TODO: Implement 422, 444 */ + //assert(ctx->base.chroma_format == PIPE_VIDEO_CHROMA_FORMAT_420); + + for (tb = 1; tb < 3; ++tb) { + if (xvmc_mb->coded_block_pattern & const_empty_block_mask_420[tb][0][0]) { + + struct pipe_ycbcr_block *stream = surface->ycbcr[tb].stream; + stream->x = xvmc_mb->x; + stream->y = xvmc_mb->y; + stream->intra = intra; + stream->coding = PIPE_MPEG12_DCT_TYPE_FRAME; + + memcpy(surface->ycbcr[tb].buffer, blocks, BLOCK_SIZE_BYTES); + + surface->ycbcr[tb].num_blocks_added++; + surface->ycbcr[tb].stream++; + surface->ycbcr[tb].buffer += BLOCK_SIZE_SAMPLES; + blocks += BLOCK_SIZE_SAMPLES; + } + } + +} + +static void +MacroBlocksToPipe(XvMCSurfacePrivate *surface, + unsigned int xvmc_picture_structure, + const XvMCMacroBlock *xvmc_mb, + const XvMCBlockArray *xvmc_blocks, + unsigned int num_macroblocks) +{ + unsigned int i, j; + + assert(xvmc_mb); + assert(xvmc_blocks); + assert(num_macroblocks); + + for (i = 0; i < num_macroblocks; ++i) { + unsigned mv_pos = xvmc_mb->x + surface->mv_stride * xvmc_mb->y; + unsigned mv_weights[2]; + + if (xvmc_mb->macroblock_type & (XVMC_MB_TYPE_PATTERN | XVMC_MB_TYPE_INTRA)) + UploadYcbcrBlocks(surface, xvmc_mb, xvmc_blocks); + + MacroBlockTypeToPipeWeights(xvmc_mb, mv_weights); + + for (j = 0; j < 2; ++j) { + if (!surface->ref[j].mv) continue; + + surface->ref[j].mv[mv_pos] = MotionVectorToPipe + ( + xvmc_mb, j, + j ? XVMC_SELECT_FIRST_BACKWARD : XVMC_SELECT_FIRST_FORWARD, + mv_weights[j] + ); + } + + ++xvmc_mb; + } +} + +static void +unmap_and_flush_surface(XvMCSurfacePrivate *surface) +{ + struct pipe_video_buffer *ref_frames[2]; + XvMCContextPrivate *context_priv; + unsigned i, num_ycbcr_blocks[3]; + + assert(surface); + + context_priv = surface->context->privData; + + for ( i = 0; i < 2; ++i ) { + if (surface->ref[i].surface) { + XvMCSurfacePrivate *ref = surface->ref[i].surface->privData; + + assert(ref); + + unmap_and_flush_surface(ref); + surface->ref[i].surface = NULL; + ref_frames[i] = ref->video_buffer; + } else { + ref_frames[i] = NULL; + } + } + + if (surface->mapped) { + surface->decode_buffer->end_frame(surface->decode_buffer); + for (i = 0; i < 3; ++i) + num_ycbcr_blocks[i] = surface->ycbcr[i].num_blocks_added; + context_priv->decoder->flush_buffer(surface->decode_buffer, + num_ycbcr_blocks, + ref_frames, + surface->video_buffer); + surface->mapped = 0; + } +} + +PUBLIC +Status XvMCCreateSurface(Display *dpy, XvMCContext *context, XvMCSurface *surface) +{ + static const uint8_t dummy_quant[64] = { + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10 + }; + + XvMCContextPrivate *context_priv; + struct pipe_context *pipe; + XvMCSurfacePrivate *surface_priv; + + XVMC_MSG(XVMC_TRACE, "[XvMC] Creating surface %p.\n", surface); + + assert(dpy); + + if (!context) + return XvMCBadContext; + if (!surface) + return XvMCBadSurface; + + context_priv = context->privData; + pipe = context_priv->vctx->pipe; + + surface_priv = CALLOC(1, sizeof(XvMCSurfacePrivate)); + if (!surface_priv) + return BadAlloc; + + surface_priv->decode_buffer = context_priv->decoder->create_buffer(context_priv->decoder); + surface_priv->decode_buffer->set_quant_matrix(surface_priv->decode_buffer, dummy_quant, dummy_quant); + + surface_priv->mv_stride = surface_priv->decode_buffer->get_mv_stream_stride(surface_priv->decode_buffer); + surface_priv->video_buffer = pipe->create_video_buffer + ( + pipe, PIPE_FORMAT_NV12, context_priv->decoder->chroma_format, + context_priv->decoder->width, context_priv->decoder->height + ); + + 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(); + + XVMC_MSG(XVMC_TRACE, "[XvMC] Surface %p created.\n", surface); + + return Success; +} + +PUBLIC +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 pipe_video_decode_buffer *t_buffer; + + XvMCSurfacePrivate *target_surface_priv; + XvMCSurfacePrivate *past_surface_priv; + XvMCSurfacePrivate *future_surface_priv; + XvMCMacroBlock *xvmc_mb; + + unsigned i; + + XVMC_MSG(XVMC_TRACE, "[XvMC] Rendering to surface %p, with past %p and future %p\n", + target_surface, past_surface, future_surface); + + assert(dpy); + + 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; + /* Bkwd pred equivalent to fwd (past && !future) */ + if (future_surface && !past_surface) + return BadMatch; + + 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(macroblocks); + assert(blocks); + + assert(macroblocks->context_id == context->context_id); + assert(blocks->context_id == context->context_id); + + assert(flags == 0 || flags == XVMC_SECOND_FIELD); + + 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(target_surface_priv->context == context); + assert(!past_surface || past_surface_priv->context == context); + assert(!future_surface || future_surface_priv->context == context); + + t_buffer = target_surface_priv->decode_buffer; + + // enshure that all reference frames are flushed + // not really nessasary, but speeds ups rendering + if (past_surface) + unmap_and_flush_surface(past_surface->privData); + + if (future_surface) + unmap_and_flush_surface(future_surface->privData); + + xvmc_mb = macroblocks->macro_blocks + first_macroblock; + + /* If the surface we're rendering hasn't changed the ref frames shouldn't change. */ + if (target_surface_priv->mapped && ( + target_surface_priv->ref[0].surface != past_surface || + target_surface_priv->ref[1].surface != future_surface || + (xvmc_mb->x == 0 && xvmc_mb->y == 0))) { + + // If they change anyway we need to clear our surface + unmap_and_flush_surface(target_surface_priv); + } + + if (!target_surface_priv->mapped) { + t_buffer->begin_frame(t_buffer); + + for (i = 0; i < 3; ++i) { + target_surface_priv->ycbcr[i].num_blocks_added = 0; + target_surface_priv->ycbcr[i].stream = t_buffer->get_ycbcr_stream(t_buffer, i); + target_surface_priv->ycbcr[i].buffer = t_buffer->get_ycbcr_buffer(t_buffer, i); + } + + for (i = 0; i < 2; ++i) { + target_surface_priv->ref[i].surface = i == 0 ? past_surface : future_surface; + + if (target_surface_priv->ref[i].surface) + target_surface_priv->ref[i].mv = t_buffer->get_mv_stream(t_buffer, i); + else + target_surface_priv->ref[i].mv = NULL; + } + + target_surface_priv->mapped = 1; + } + + MacroBlocksToPipe(target_surface_priv, picture_structure, xvmc_mb, blocks, num_macroblocks); + + XVMC_MSG(XVMC_TRACE, "[XvMC] Submitted surface %p for rendering.\n", target_surface); + + return Success; +} + +PUBLIC +Status XvMCFlushSurface(Display *dpy, XvMCSurface *surface) +{ + assert(dpy); + + if (!surface) + return XvMCBadSurface; + + // don't call flush here, because this is usually + // called once for every slice instead of every frame + + XVMC_MSG(XVMC_TRACE, "[XvMC] Flushing surface %p\n", surface); + + return Success; +} + +PUBLIC +Status XvMCSyncSurface(Display *dpy, XvMCSurface *surface) +{ + assert(dpy); + + if (!surface) + return XvMCBadSurface; + + XVMC_MSG(XVMC_TRACE, "[XvMC] Syncing surface %p\n", surface); + + return Success; +} + +PUBLIC +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) +{ + static int dump_window = -1; + + struct pipe_context *pipe; + struct vl_compositor *compositor; + + XvMCSurfacePrivate *surface_priv; + XvMCContextPrivate *context_priv; + XvMCSubpicturePrivate *subpicture_priv; + XvMCContext *context; + struct pipe_video_rect src_rect = {srcx, srcy, srcw, srch}; + struct pipe_video_rect dst_rect = {destx, desty, destw, desth}; + + XVMC_MSG(XVMC_TRACE, "[XvMC] Displaying surface %p.\n", surface); + + assert(dpy); + + if (!surface || !surface->privData) + return XvMCBadSurface; + + surface_priv = surface->privData; + context = surface_priv->context; + context_priv = context->privData; + + 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); + + subpicture_priv = surface_priv->subpicture ? surface_priv->subpicture->privData : NULL; + pipe = context_priv->vctx->pipe; + compositor = &context_priv->compositor; + + if (!context_priv->drawable_surface || + context_priv->dst_rect.x != dst_rect.x || context_priv->dst_rect.y != dst_rect.y || + context_priv->dst_rect.w != dst_rect.w || context_priv->dst_rect.h != dst_rect.h) { + + pipe_surface_reference(&context_priv->drawable_surface, NULL); + context_priv->drawable_surface = vl_drawable_surface_get(context_priv->vctx, drawable); + context_priv->dst_rect = dst_rect; + vl_compositor_reset_dirty_area(compositor); + } + + if (!context_priv->drawable_surface) + return BadDrawable; + + /* + * 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 < drawable_surface->width); + assert(desty + desth - 1 < drawable_surface->height); + */ + + unmap_and_flush_surface(surface_priv); + + vl_compositor_clear_layers(compositor); + vl_compositor_set_buffer_layer(compositor, 0, surface_priv->video_buffer, &src_rect, NULL); + + if (subpicture_priv) { + XVMC_MSG(XVMC_TRACE, "[XvMC] Surface %p has subpicture %p.\n", surface, surface_priv->subpicture); + + assert(subpicture_priv->surface == surface); + + if (subpicture_priv->palette) + vl_compositor_set_palette_layer(compositor, 1, subpicture_priv->sampler, subpicture_priv->palette, + &subpicture_priv->src_rect, &subpicture_priv->dst_rect); + else + vl_compositor_set_rgba_layer(compositor, 1, subpicture_priv->sampler, + &subpicture_priv->src_rect, &subpicture_priv->dst_rect); + + surface_priv->subpicture = NULL; + subpicture_priv->surface = NULL; + } + + // Workaround for r600g, there seems to be a bug in the fence refcounting code + pipe->screen->fence_reference(pipe->screen, &surface_priv->fence, NULL); + + vl_compositor_render(compositor, PictureToPipe(flags), context_priv->drawable_surface, &dst_rect, &surface_priv->fence); + + XVMC_MSG(XVMC_TRACE, "[XvMC] Submitted surface %p for display. Pushing to front buffer.\n", surface); + + pipe->screen->flush_frontbuffer + ( + pipe->screen, + context_priv->drawable_surface->texture, + 0, 0, + vl_contextprivate_get(context_priv->vctx, context_priv->drawable_surface) + ); + + if(dump_window == -1) { + dump_window = debug_get_num_option("XVMC_DUMP", 0); + } + + if(dump_window) { + static unsigned int framenum = 0; + char cmd[256]; + + sprintf(cmd, "xwd -id %d -out xvmc_frame_%08d.xwd", (int)drawable, ++framenum); + if (system(cmd) != 0) + XVMC_MSG(XVMC_ERR, "[XvMC] Dumping surface %p failed.\n", surface); + } + + XVMC_MSG(XVMC_TRACE, "[XvMC] Pushed surface %p to front buffer.\n", surface); + + return Success; +} + +PUBLIC +Status XvMCGetSurfaceStatus(Display *dpy, XvMCSurface *surface, int *status) +{ + struct pipe_context *pipe; + XvMCSurfacePrivate *surface_priv; + XvMCContextPrivate *context_priv; + + assert(dpy); + + if (!surface) + return XvMCBadSurface; + + assert(status); + + surface_priv = surface->privData; + context_priv = surface_priv->context->privData; + pipe = context_priv->vctx->pipe; + + *status = 0; + + if (surface_priv->fence) + if (!pipe->screen->fence_signalled(pipe->screen, surface_priv->fence)) + *status |= XVMC_RENDERING; + + return Success; +} + +PUBLIC +Status XvMCDestroySurface(Display *dpy, XvMCSurface *surface) +{ + XvMCSurfacePrivate *surface_priv; + + XVMC_MSG(XVMC_TRACE, "[XvMC] Destroying surface %p.\n", surface); + + assert(dpy); + + if (!surface || !surface->privData) + return XvMCBadSurface; + + surface_priv = surface->privData; + + if (surface_priv->mapped) + surface_priv->decode_buffer->end_frame(surface_priv->decode_buffer); + surface_priv->decode_buffer->destroy(surface_priv->decode_buffer); + surface_priv->video_buffer->destroy(surface_priv->video_buffer); + FREE(surface_priv); + surface->privData = NULL; + + XVMC_MSG(XVMC_TRACE, "[XvMC] Surface %p destroyed.\n", surface); + + return Success; +} + +PUBLIC +Status XvMCHideSurface(Display *dpy, XvMCSurface *surface) +{ + assert(dpy); + + if (!surface || !surface->privData) + return XvMCBadSurface; + + /* No op, only for overlaid rendering */ + + return Success; +} diff --git a/src/gallium/state_trackers/xorg/xvmc/tests/.gitignore b/src/gallium/state_trackers/xorg/xvmc/tests/.gitignore new file mode 100644 index 00000000000..9a8e05d9472 --- /dev/null +++ b/src/gallium/state_trackers/xorg/xvmc/tests/.gitignore @@ -0,0 +1,6 @@ +test_context +test_surface +test_subpicture +test_blocks +test_rendering +xvmc_bench diff --git a/src/gallium/state_trackers/xorg/xvmc/tests/Makefile b/src/gallium/state_trackers/xorg/xvmc/tests/Makefile new file mode 100644 index 00000000000..88b03763563 --- /dev/null +++ b/src/gallium/state_trackers/xorg/xvmc/tests/Makefile @@ -0,0 +1,31 @@ +TOP = ../../../../../.. +include $(TOP)/configs/current + +LIBS = -lXvMCW -lXvMC -lXv -lX11 + +############################################# + +.PHONY: default clean + +default: test_context test_surface test_subpicture test_blocks test_rendering xvmc_bench + +test_context: test_context.o testlib.o + $(CC) $(LDFLAGS) -o $@ $^ $(LIBS) + +test_surface: test_surface.o testlib.o + $(CC) $(LDFLAGS) -o $@ $^ $(LIBS) + +test_subpicture: test_subpicture.o testlib.o + $(CC) $(LDFLAGS) -o $@ $^ $(LIBS) + +test_blocks: test_blocks.o testlib.o + $(CC) $(LDFLAGS) -o $@ $^ $(LIBS) + +test_rendering: test_rendering.o testlib.o + $(CC) $(LDFLAGS) -o $@ $^ $(LIBS) + +xvmc_bench: xvmc_bench.o testlib.o + $(CC) $(LDFLAGS) -o $@ $^ $(LIBS) + +clean: + $(RM) -rf *.o test_context test_surface test_subpicture test_blocks test_rendering xvmc_bench diff --git a/src/gallium/state_trackers/xorg/xvmc/tests/test_blocks.c b/src/gallium/state_trackers/xorg/xvmc/tests/test_blocks.c new file mode 100644 index 00000000000..994e3ca4d14 --- /dev/null +++ b/src/gallium/state_trackers/xorg/xvmc/tests/test_blocks.c @@ -0,0 +1,111 @@ +/************************************************************************** + * + * Copyright 2009 Younes Manton. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include <assert.h> +#include <error.h> +#include "testlib.h" + +int main(int argc, char **argv) +{ + const unsigned int width = 16, height = 16; + const unsigned int min_required_blocks = 1, min_required_macroblocks = 1; + 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; + unsigned int is_overlay, intra_unsigned; + int colorkey; + XvMCContext context; + XvMCSurface surface; + XvMCBlockArray blocks = {0}; + XvMCMacroBlockArray macroblocks = {0}; + + display = XOpenDisplay(NULL); + + if (!GetPort + ( + display, + width, + height, + XVMC_CHROMA_FORMAT_420, + mc_types, + 2, + &port_num, + &surface_type_id, + &is_overlay, + &intra_unsigned + )) + { + 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); + assert(XvMCCreateSurface(display, &context, &surface) == Success); + + /* Test NULL context */ + assert(XvMCCreateBlocks(display, NULL, 1, &blocks) == XvMCBadContext); + /* Test 0 blocks */ + assert(XvMCCreateBlocks(display, &context, 0, &blocks) == BadValue); + /* Test valid params */ + assert(XvMCCreateBlocks(display, &context, min_required_blocks, &blocks) == Success); + /* Test context id assigned and correct */ + assert(blocks.context_id == context.context_id); + /* Test number of blocks assigned and correct */ + assert(blocks.num_blocks == min_required_blocks); + /* Test block pointer valid */ + assert(blocks.blocks != NULL); + /* Test NULL context */ + assert(XvMCCreateMacroBlocks(display, NULL, 1, ¯oblocks) == XvMCBadContext); + /* Test 0 macroblocks */ + assert(XvMCCreateMacroBlocks(display, &context, 0, ¯oblocks) == BadValue); + /* Test valid params */ + assert(XvMCCreateMacroBlocks(display, &context, min_required_macroblocks, ¯oblocks) == Success); + /* Test context id assigned and correct */ + assert(macroblocks.context_id == context.context_id); + /* Test macroblock pointer valid */ + assert(macroblocks.macro_blocks != NULL); + /* Test valid params */ + assert(XvMCDestroyMacroBlocks(display, ¯oblocks) == Success); + /* Test valid params */ + assert(XvMCDestroyBlocks(display, &blocks) == Success); + + assert(XvMCDestroySurface(display, &surface) == Success); + assert(XvMCDestroyContext(display, &context) == Success); + + XvUngrabPort(display, port_num, CurrentTime); + XCloseDisplay(display); + + return 0; +} diff --git a/src/gallium/state_trackers/xorg/xvmc/tests/test_context.c b/src/gallium/state_trackers/xorg/xvmc/tests/test_context.c new file mode 100644 index 00000000000..3da957c9330 --- /dev/null +++ b/src/gallium/state_trackers/xorg/xvmc/tests/test_context.c @@ -0,0 +1,119 @@ +/************************************************************************** + * + * Copyright 2009 Younes Manton. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include <assert.h> +#include <error.h> +#include "testlib.h" + +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; + unsigned int is_overlay, intra_unsigned; + int colorkey; + XvMCContext context = {0}; + + display = XOpenDisplay(NULL); + + if (!GetPort + ( + display, + width, + height, + XVMC_CHROMA_FORMAT_420, + mc_types, + 2, + &port_num, + &surface_type_id, + &is_overlay, + &intra_unsigned + )) + { + 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); + } + + /* Test NULL context */ + /* XXX: XvMCBadContext not a valid return for XvMCCreateContext in the XvMC API, but openChrome driver returns it */ + assert(XvMCCreateContext(display, port_num, surface_type_id, width, height, XVMC_DIRECT, NULL) == XvMCBadContext); + /* Test invalid port */ + /* XXX: Success and XvBadPort have the same value, if this call actually gets passed the validation step as of now we'll crash later */ + assert(XvMCCreateContext(display, -1, surface_type_id, width, height, XVMC_DIRECT, &context) == XvBadPort); + /* Test invalid surface */ + assert(XvMCCreateContext(display, port_num, -1, width, height, XVMC_DIRECT, &context) == BadMatch); + /* Test invalid flags */ + assert(XvMCCreateContext(display, port_num, surface_type_id, width, height, -1, &context) == BadValue); + /* Test huge width */ + assert(XvMCCreateContext(display, port_num, surface_type_id, 16384, height, XVMC_DIRECT, &context) == BadValue); + /* Test huge height */ + assert(XvMCCreateContext(display, port_num, surface_type_id, width, 16384, XVMC_DIRECT, &context) == BadValue); + /* Test huge width & height */ + assert(XvMCCreateContext(display, port_num, surface_type_id, 16384, 16384, XVMC_DIRECT, &context) == BadValue); + /* Test valid params */ + assert(XvMCCreateContext(display, port_num, surface_type_id, width, height, XVMC_DIRECT, &context) == Success); + /* Test context id assigned */ + assert(context.context_id != 0); + /* Test surface type id assigned and correct */ + assert(context.surface_type_id == surface_type_id); + /* Test width & height assigned and correct */ + assert(context.width == width && context.height == height); + /* Test port assigned and correct */ + assert(context.port == port_num); + /* Test flags assigned and correct */ + assert(context.flags == XVMC_DIRECT); + /* Test NULL context */ + assert(XvMCDestroyContext(display, NULL) == XvMCBadContext); + /* Test valid params */ + assert(XvMCDestroyContext(display, &context) == Success); + /* Test awkward but valid width */ + assert(XvMCCreateContext(display, port_num, surface_type_id, width + 1, height, XVMC_DIRECT, &context) == Success); + assert(context.width >= width + 1); + assert(XvMCDestroyContext(display, &context) == Success); + /* Test awkward but valid height */ + assert(XvMCCreateContext(display, port_num, surface_type_id, width, height + 1, XVMC_DIRECT, &context) == Success); + assert(context.height >= height + 1); + assert(XvMCDestroyContext(display, &context) == Success); + /* Test awkward but valid width & height */ + assert(XvMCCreateContext(display, port_num, surface_type_id, width + 1, height + 1, XVMC_DIRECT, &context) == Success); + assert(context.width >= width + 1 && context.height >= height + 1); + assert(XvMCDestroyContext(display, &context) == Success); + + XvUngrabPort(display, port_num, CurrentTime); + XCloseDisplay(display); + + return 0; +} diff --git a/src/gallium/state_trackers/xorg/xvmc/tests/test_rendering.c b/src/gallium/state_trackers/xorg/xvmc/tests/test_rendering.c new file mode 100644 index 00000000000..6058783a798 --- /dev/null +++ b/src/gallium/state_trackers/xorg/xvmc/tests/test_rendering.c @@ -0,0 +1,317 @@ +/************************************************************************** + * + * Copyright 2009 Younes Manton. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include <assert.h> +#include <stdio.h> +#include <string.h> +#include <error.h> +#include "testlib.h" + +#define BLOCK_WIDTH 8 +#define BLOCK_HEIGHT 8 +#define BLOCK_SIZE (BLOCK_WIDTH * BLOCK_HEIGHT) +#define MACROBLOCK_WIDTH 16 +#define MACROBLOCK_HEIGHT 16 +#define MACROBLOCK_WIDTH_IN_BLOCKS (MACROBLOCK_WIDTH / BLOCK_WIDTH) +#define MACROBLOCK_HEIGHT_IN_BLOCKS (MACROBLOCK_HEIGHT / BLOCK_HEIGHT) +#define BLOCKS_PER_MACROBLOCK 6 + +#define INPUT_WIDTH 16 +#define INPUT_HEIGHT 16 +#define INPUT_WIDTH_IN_MACROBLOCKS (INPUT_WIDTH / MACROBLOCK_WIDTH) +#define INPUT_HEIGHT_IN_MACROBLOCKS (INPUT_HEIGHT / MACROBLOCK_HEIGHT) +#define NUM_MACROBLOCKS (INPUT_WIDTH_IN_MACROBLOCKS * INPUT_HEIGHT_IN_MACROBLOCKS) + +#define DEFAULT_OUTPUT_WIDTH INPUT_WIDTH +#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; + int i; + + *output_width = DEFAULT_OUTPUT_WIDTH; + *output_height = DEFAULT_OUTPUT_WIDTH; + *acceptable_error = DEFAULT_ACCEPTABLE_ERR; + *prompt = 1; + + for (i = 1; i < argc && !fail; ++i) + { + if (!strcmp(argv[i], "-w")) + { + if (sscanf(argv[++i], "%u", output_width) != 1) + fail = 1; + } + else if (!strcmp(argv[i], "-h")) + { + if (sscanf(argv[++i], "%u", output_height) != 1) + fail = 1; + } + else if (!strcmp(argv[i], "-e")) + { + if (sscanf(argv[++i], "%lf", acceptable_error) != 1) + fail = 1; + } + else if (strcmp(argv[i], "-n")) + *prompt = 0; + else + fail = 1; + } + + if (fail) + error + ( + 1, 0, + "Bad argument.\n" + "\n" + "Usage: %s [options]\n" + "\t-w <width>\tOutput width\n" + "\t-h <height>\tOutput height\n" + "\t-e <error>\tAcceptable margin of error per pixel, from 0 to 1\n" + "\t-n\tDon't prompt for quit\n", + argv[0] + ); +} + +void Gradient(short *block, unsigned int start, unsigned int stop, int horizontal) +{ + unsigned int x, y; + unsigned int range = stop - start; + + if (horizontal) + { + for (y = 0; y < BLOCK_HEIGHT; ++y) + for (x = 0; x < BLOCK_WIDTH; ++x) + block[y * BLOCK_WIDTH + x] = (short)(start + range * (x / (float)(BLOCK_WIDTH - 1))); + } + else + { + for (y = 0; y < BLOCK_HEIGHT; ++y) + for (x = 0; x < BLOCK_WIDTH; ++x) + block[y * BLOCK_WIDTH + x] = (short)(start + range * (y / (float)(BLOCK_HEIGHT - 1))); + } +} + +int main(int argc, char **argv) +{ + unsigned int output_width; + unsigned int output_height; + double acceptable_error; + int prompt; + Display *display; + Window root, window; + const unsigned int mc_types[2] = {XVMC_MOCOMP | XVMC_MPEG_2, XVMC_IDCT | XVMC_MPEG_2}; + XvPortID port_num; + int surface_type_id; + unsigned int is_overlay, intra_unsigned; + int colorkey; + XvMCContext context; + XvMCSurface surface; + XvMCBlockArray block_array; + XvMCMacroBlockArray mb_array; + int mbx, mby, bx, by; + XvMCMacroBlock *mb; + short *blocks; + int quit = 0; + + ParseArgs(argc, argv, &output_width, &output_height, &acceptable_error, &prompt); + + display = XOpenDisplay(NULL); + + if (!GetPort + ( + display, + INPUT_WIDTH, + INPUT_HEIGHT, + XVMC_CHROMA_FORMAT_420, + mc_types, + 2, + &port_num, + &surface_type_id, + &is_overlay, + &intra_unsigned + )) + { + 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); + } + + root = XDefaultRootWindow(display); + window = XCreateSimpleWindow(display, root, 0, 0, output_width, output_height, 0, 0, colorkey); + + assert(XvMCCreateContext(display, port_num, surface_type_id, INPUT_WIDTH, INPUT_HEIGHT, XVMC_DIRECT, &context) == Success); + assert(XvMCCreateSurface(display, &context, &surface) == Success); + assert(XvMCCreateBlocks(display, &context, NUM_MACROBLOCKS * BLOCKS_PER_MACROBLOCK, &block_array) == Success); + assert(XvMCCreateMacroBlocks(display, &context, NUM_MACROBLOCKS, &mb_array) == Success); + + mb = mb_array.macro_blocks; + blocks = block_array.blocks; + + for (mby = 0; mby < INPUT_HEIGHT_IN_MACROBLOCKS; ++mby) + for (mbx = 0; mbx < INPUT_WIDTH_IN_MACROBLOCKS; ++mbx) + { + mb->x = mbx; + mb->y = mby; + mb->macroblock_type = XVMC_MB_TYPE_INTRA; + /*mb->motion_type = ;*/ + /*mb->motion_vertical_field_select = ;*/ + mb->dct_type = XVMC_DCT_TYPE_FRAME; + /*mb->PMV[0][0][0] = ; + mb->PMV[0][0][1] = ; + mb->PMV[0][1][0] = ; + mb->PMV[0][1][1] = ; + mb->PMV[1][0][0] = ; + mb->PMV[1][0][1] = ; + mb->PMV[1][1][0] = ; + mb->PMV[1][1][1] = ;*/ + mb->index = (mby * INPUT_WIDTH_IN_MACROBLOCKS + mbx) * BLOCKS_PER_MACROBLOCK; + mb->coded_block_pattern = 0x3F; + + mb++; + + for (by = 0; by < MACROBLOCK_HEIGHT_IN_BLOCKS; ++by) + for (bx = 0; bx < MACROBLOCK_WIDTH_IN_BLOCKS; ++bx) + { + const int start = 16, stop = 235, range = stop - start; + + Gradient + ( + blocks, + (short)(start + range * ((mbx * MACROBLOCK_WIDTH + bx * BLOCK_WIDTH) / (float)(INPUT_WIDTH - 1))), + (short)(start + range * ((mbx * MACROBLOCK_WIDTH + bx * BLOCK_WIDTH + BLOCK_WIDTH - 1) / (float)(INPUT_WIDTH - 1))), + 1 + ); + + blocks += BLOCK_SIZE; + } + + for (by = 0; by < MACROBLOCK_HEIGHT_IN_BLOCKS / 2; ++by) + for (bx = 0; bx < MACROBLOCK_WIDTH_IN_BLOCKS / 2; ++bx) + { + const int start = 16, stop = 240, range = stop - start; + + Gradient + ( + blocks, + (short)(start + range * ((mbx * MACROBLOCK_WIDTH + bx * BLOCK_WIDTH) / (float)(INPUT_WIDTH - 1))), + (short)(start + range * ((mbx * MACROBLOCK_WIDTH + bx * BLOCK_WIDTH + BLOCK_WIDTH - 1) / (float)(INPUT_WIDTH - 1))), + 1 + ); + + blocks += BLOCK_SIZE; + + Gradient + ( + blocks, + (short)(start + range * ((mbx * MACROBLOCK_WIDTH + bx * BLOCK_WIDTH) / (float)(INPUT_WIDTH - 1))), + (short)(start + range * ((mbx * MACROBLOCK_WIDTH + bx * BLOCK_WIDTH + BLOCK_WIDTH - 1) / (float)(INPUT_WIDTH - 1))), + 1 + ); + + blocks += BLOCK_SIZE; + } + } + + XSelectInput(display, window, ExposureMask | KeyPressMask); + XMapWindow(display, window); + XSync(display, 0); + + /* Test NULL context */ + assert(XvMCRenderSurface(display, NULL, XVMC_FRAME_PICTURE, &surface, NULL, NULL, 0, NUM_MACROBLOCKS, 0, &mb_array, &block_array) == XvMCBadContext); + /* Test NULL surface */ + assert(XvMCRenderSurface(display, &context, XVMC_FRAME_PICTURE, NULL, NULL, NULL, 0, NUM_MACROBLOCKS, 0, &mb_array, &block_array) == XvMCBadSurface); + /* Test bad picture structure */ + assert(XvMCRenderSurface(display, &context, 0, &surface, NULL, NULL, 0, NUM_MACROBLOCKS, 0, &mb_array, &block_array) == BadValue); + /* Test valid params */ + assert(XvMCRenderSurface(display, &context, XVMC_FRAME_PICTURE, &surface, NULL, NULL, 0, NUM_MACROBLOCKS, 0, &mb_array, &block_array) == Success); + + /* Test NULL surface */ + assert(XvMCPutSurface(display, NULL, window, 0, 0, INPUT_WIDTH, INPUT_HEIGHT, 0, 0, output_width, output_height, XVMC_FRAME_PICTURE) == XvMCBadSurface); + /* Test bad window */ + /* XXX: X halts with a bad drawable for some reason, doesn't return BadDrawable as expected */ + /*assert(XvMCPutSurface(display, &surface, 0, 0, 0, width, height, 0, 0, width, height, XVMC_FRAME_PICTURE) == BadDrawable);*/ + + if (prompt) + { + puts("Press any button to quit..."); + + while (!quit) + { + if (XPending(display) > 0) + { + XEvent event; + + XNextEvent(display, &event); + + switch (event.type) + { + case Expose: + { + /* Test valid params */ + assert + ( + XvMCPutSurface + ( + display, &surface, window, + 0, 0, INPUT_WIDTH, INPUT_HEIGHT, + 0, 0, output_width, output_height, + XVMC_FRAME_PICTURE + ) == Success + ); + break; + } + case KeyPress: + { + quit = 1; + break; + } + } + } + } + } + + assert(XvMCDestroyBlocks(display, &block_array) == Success); + assert(XvMCDestroyMacroBlocks(display, &mb_array) == Success); + assert(XvMCDestroySurface(display, &surface) == Success); + assert(XvMCDestroyContext(display, &context) == Success); + + XvUngrabPort(display, port_num, CurrentTime); + XDestroyWindow(display, window); + XCloseDisplay(display); + + return 0; +} diff --git a/src/gallium/state_trackers/xorg/xvmc/tests/test_subpicture.c b/src/gallium/state_trackers/xorg/xvmc/tests/test_subpicture.c new file mode 100644 index 00000000000..20d0907a07f --- /dev/null +++ b/src/gallium/state_trackers/xorg/xvmc/tests/test_subpicture.c @@ -0,0 +1,182 @@ +/************************************************************************** + * + * Copyright 2009 Younes Manton. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include <assert.h> +#include <error.h> +#include <stdio.h> +#include "testlib.h" + +static void PrintGUID(const char *guid) +{ + int i; + printf("\tguid: "); + for (i = 0; i < 4; ++i) + printf("%C,", guid[i] == 0 ? '0' : guid[i]); + for (; i < 15; ++i) + printf("%x,", (unsigned char)guid[i]); + printf("%x\n", (unsigned int)guid[15]); +} + +static void PrintComponentOrder(const char *co) +{ + int i; + printf("\tcomponent_order:\n\t "); + for (i = 0; i < 4; ++i) + printf("%C,", co[i] == 0 ? '0' : co[i]); + for (; i < 31; ++i) + printf("%x,", (unsigned int)co[i]); + printf("%x\n", (unsigned int)co[31]); +} + +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}; + const unsigned int subpic_width = 16, subpic_height = 16; + + Display *display; + XvPortID port_num; + int surface_type_id; + unsigned int is_overlay, intra_unsigned; + int colorkey; + XvMCContext context; + XvImageFormatValues *subpics; + int num_subpics; + XvMCSubpicture subpicture = {0}; + int i; + + display = XOpenDisplay(NULL); + + if (!GetPort + ( + display, + width, + height, + XVMC_CHROMA_FORMAT_420, + mc_types, + 2, + &port_num, + &surface_type_id, + &is_overlay, + &intra_unsigned + )) + { + 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); + + subpics = XvMCListSubpictureTypes(display, port_num, surface_type_id, &num_subpics); + assert((subpics && num_subpics) > 0 || (!subpics && num_subpics == 0)); + + for (i = 0; i < num_subpics; ++i) + { + printf("Subpicture %d:\n", i); + printf("\tid: 0x%08x\n", subpics[i].id); + printf("\ttype: %s\n", subpics[i].type == XvRGB ? "XvRGB" : (subpics[i].type == XvYUV ? "XvYUV" : "Unknown")); + printf("\tbyte_order: %s\n", subpics[i].byte_order == LSBFirst ? "LSB First" : (subpics[i].byte_order == MSBFirst ? "MSB First" : "Unknown")); + PrintGUID(subpics[i].guid); + printf("\tbpp: %u\n", subpics[i].bits_per_pixel); + printf("\tformat: %s\n", subpics[i].format == XvPacked ? "XvPacked" : (subpics[i].format == XvPlanar ? "XvPlanar" : "Unknown")); + printf("\tnum_planes: %u\n", subpics[i].num_planes); + + if (subpics[i].type == XvRGB) + { + printf("\tdepth: %u\n", subpics[i].depth); + printf("\tred_mask: 0x%08x\n", subpics[i].red_mask); + printf("\tgreen_mask: 0x%08x\n", subpics[i].green_mask); + printf("\tblue_mask: 0x%08x\n", subpics[i].blue_mask); + } + else if (subpics[i].type == XvYUV) + { + printf("\ty_sample_bits: %u\n", subpics[i].y_sample_bits); + printf("\tu_sample_bits: %u\n", subpics[i].u_sample_bits); + printf("\tv_sample_bits: %u\n", subpics[i].v_sample_bits); + printf("\thorz_y_period: %u\n", subpics[i].horz_y_period); + printf("\thorz_u_period: %u\n", subpics[i].horz_u_period); + printf("\thorz_v_period: %u\n", subpics[i].horz_v_period); + printf("\tvert_y_period: %u\n", subpics[i].vert_y_period); + printf("\tvert_u_period: %u\n", subpics[i].vert_u_period); + printf("\tvert_v_period: %u\n", subpics[i].vert_v_period); + } + PrintComponentOrder(subpics[i].component_order); + printf("\tscanline_order: %s\n", subpics[i].scanline_order == XvTopToBottom ? "XvTopToBottom" : (subpics[i].scanline_order == XvBottomToTop ? "XvBottomToTop" : "Unknown")); + } + + if (num_subpics == 0) + { + printf("Subpictures not supported, nothing to test.\n"); + return 0; + } + + /* Test NULL context */ + assert(XvMCCreateSubpicture(display, NULL, &subpicture, subpic_width, subpic_height, subpics[0].id) == XvMCBadContext); + /* Test NULL subpicture */ + assert(XvMCCreateSubpicture(display, &context, NULL, subpic_width, subpic_height, subpics[0].id) == XvMCBadSubpicture); + /* Test invalid subpicture */ + assert(XvMCCreateSubpicture(display, &context, &subpicture, subpic_width, subpic_height, -1) == BadMatch); + /* Test huge width */ + assert(XvMCCreateSubpicture(display, &context, &subpicture, 16384, subpic_height, subpics[0].id) == BadValue); + /* Test huge height */ + assert(XvMCCreateSubpicture(display, &context, &subpicture, subpic_width, 16384, subpics[0].id) == BadValue); + /* Test huge width & height */ + assert(XvMCCreateSubpicture(display, &context, &subpicture, 16384, 16384, subpics[0].id) == BadValue); + for (i = 0; i < num_subpics; ++i) + { + /* Test valid params */ + assert(XvMCCreateSubpicture(display, &context, &subpicture, subpic_width, subpic_height, subpics[i].id) == Success); + /* Test subpicture id assigned */ + assert(subpicture.subpicture_id != 0); + /* Test context id assigned and correct */ + assert(subpicture.context_id == context.context_id); + /* Test subpicture type id assigned and correct */ + assert(subpicture.xvimage_id == subpics[i].id); + /* Test width & height assigned and correct */ + assert(subpicture.width == width && subpicture.height == height); + /* Test no palette support */ + assert(subpicture.num_palette_entries == 0 && subpicture.entry_bytes == 0); + /* Test valid params */ + assert(XvMCDestroySubpicture(display, &subpicture) == Success); + } + /* Test NULL surface */ + assert(XvMCDestroySubpicture(display, NULL) == XvMCBadSubpicture); + + assert(XvMCDestroyContext(display, &context) == Success); + + XFree(subpics); + XvUngrabPort(display, port_num, CurrentTime); + XCloseDisplay(display); + + return 0; +} diff --git a/src/gallium/state_trackers/xorg/xvmc/tests/test_surface.c b/src/gallium/state_trackers/xorg/xvmc/tests/test_surface.c new file mode 100644 index 00000000000..b65eb265c0a --- /dev/null +++ b/src/gallium/state_trackers/xorg/xvmc/tests/test_surface.c @@ -0,0 +1,98 @@ +/************************************************************************** + * + * Copyright 2009 Younes Manton. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include <assert.h> +#include <error.h> +#include "testlib.h" + +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; + unsigned int is_overlay, intra_unsigned; + int colorkey; + XvMCContext context; + XvMCSurface surface = {0}; + + display = XOpenDisplay(NULL); + + if (!GetPort + ( + display, + width, + height, + XVMC_CHROMA_FORMAT_420, + mc_types, + 2, + &port_num, + &surface_type_id, + &is_overlay, + &intra_unsigned + )) + { + 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 */ + assert(XvMCCreateSurface(display, &context, NULL) == XvMCBadSurface); + /* Test valid params */ + assert(XvMCCreateSurface(display, &context, &surface) == Success); + /* Test surface id assigned */ + assert(surface.surface_id != 0); + /* Test context id assigned and correct */ + assert(surface.context_id == context.context_id); + /* Test surface type id assigned and correct */ + assert(surface.surface_type_id == surface_type_id); + /* Test width & height assigned and correct */ + assert(surface.width == width && surface.height == height); + /* Test valid params */ + 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/gallium/state_trackers/xorg/xvmc/tests/testlib.c b/src/gallium/state_trackers/xorg/xvmc/tests/testlib.c new file mode 100644 index 00000000000..142c09bb590 --- /dev/null +++ b/src/gallium/state_trackers/xorg/xvmc/tests/testlib.c @@ -0,0 +1,146 @@ +/************************************************************************** + * + * Copyright 2009 Younes Manton. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include "testlib.h" +#include <stdio.h> + +/* +void test(int pred, const char *pred_string, const char *doc_string, const char *file, unsigned int line) +{ + fputs(doc_string, stderr); + if (!pred) + fprintf(stderr, " FAIL!\n\t\"%s\" at %s:%u\n", pred_string, file, line); + else + fputs(" PASS!\n", stderr); +} +*/ + +int GetPort +( + Display *display, + unsigned int width, + unsigned int height, + unsigned int chroma_format, + const unsigned int *mc_types, + unsigned int num_mc_types, + XvPortID *port_id, + int *surface_type_id, + unsigned int *is_overlay, + unsigned int *intra_unsigned +) +{ + unsigned int found_port = 0; + XvAdaptorInfo *adaptor_info; + unsigned int num_adaptors; + int num_types; + int ev_base, err_base; + unsigned int i, j, k, l; + + if (!XvMCQueryExtension(display, &ev_base, &err_base)) + return 0; + if (XvQueryAdaptors(display, XDefaultRootWindow(display), &num_adaptors, &adaptor_info) != Success) + return 0; + + for (i = 0; i < num_adaptors && !found_port; ++i) + { + if (adaptor_info[i].type & XvImageMask) + { + XvMCSurfaceInfo *surface_info = XvMCListSurfaceTypes(display, adaptor_info[i].base_id, &num_types); + + if (surface_info) + { + for (j = 0; j < num_types && !found_port; ++j) + { + if + ( + surface_info[j].chroma_format == chroma_format && + surface_info[j].max_width >= width && + surface_info[j].max_height >= height + ) + { + for (k = 0; k < num_mc_types && !found_port; ++k) + { + if (surface_info[j].mc_type == mc_types[k]) + { + for (l = 0; l < adaptor_info[i].num_ports && !found_port; ++l) + { + if (XvGrabPort(display, adaptor_info[i].base_id + l, CurrentTime) == Success) + { + *port_id = adaptor_info[i].base_id + l; + *surface_type_id = surface_info[j].surface_type_id; + *is_overlay = surface_info[j].flags & XVMC_OVERLAID_SURFACE; + *intra_unsigned = surface_info[j].flags & XVMC_INTRA_UNSIGNED; + found_port = 1; + } + } + } + } + } + } + + XFree(surface_info); + } + } + } + + XvFreeAdaptorInfo(adaptor_info); + + return found_port; +} + +unsigned int align(unsigned int value, unsigned int alignment) +{ + return (value + alignment - 1) & ~(alignment - 1); +} + +/* From the glibc manual */ +int timeval_subtract(struct timeval *result, struct timeval *x, struct timeval *y) +{ + /* Perform the carry for the later subtraction by updating y. */ + if (x->tv_usec < y->tv_usec) + { + int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1; + y->tv_usec -= 1000000 * nsec; + y->tv_sec += nsec; + } + if (x->tv_usec - y->tv_usec > 1000000) + { + int nsec = (x->tv_usec - y->tv_usec) / 1000000; + y->tv_usec += 1000000 * nsec; + y->tv_sec -= nsec; + } + + /* + * Compute the time remaining to wait. + * tv_usec is certainly positive. + */ + result->tv_sec = x->tv_sec - y->tv_sec; + result->tv_usec = x->tv_usec - y->tv_usec; + + /* Return 1 if result is negative. */ + return x->tv_sec < y->tv_sec; +} diff --git a/src/gallium/state_trackers/xorg/xvmc/tests/testlib.h b/src/gallium/state_trackers/xorg/xvmc/tests/testlib.h new file mode 100644 index 00000000000..0438e52928b --- /dev/null +++ b/src/gallium/state_trackers/xorg/xvmc/tests/testlib.h @@ -0,0 +1,69 @@ +/************************************************************************** + * + * Copyright 2009 Younes Manton. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef testlib_h +#define testlib_h + +/* +#define TEST(pred, doc) test(pred, #pred, doc, __FILE__, __LINE__) + +void test(int pred, const char *pred_string, const char *doc_string, const char *file, unsigned int line); +*/ + +#include <sys/time.h> +#include <X11/Xlib.h> +#include <X11/extensions/XvMClib.h> + +/* + * display: IN A valid X display + * width, height: IN Surface size that the port must display + * chroma_format: IN Chroma format that the port must display + * mc_types, num_mc_types: IN List of MC types that the port must support, first port that matches the first mc_type will be returned + * port_id: OUT Your port's ID + * surface_type_id: OUT Your port's surface ID + * is_overlay: OUT If 1, port uses overlay surfaces, you need to set a colorkey + * intra_unsigned: OUT If 1, port uses unsigned values for intra-coded blocks + */ +int GetPort +( + Display *display, + unsigned int width, + unsigned int height, + unsigned int chroma_format, + const unsigned int *mc_types, + unsigned int num_mc_types, + XvPortID *port_id, + int *surface_type_id, + unsigned int *is_overlay, + unsigned int *intra_unsigned +); + +unsigned int align(unsigned int value, unsigned int alignment); + +int timeval_subtract(struct timeval *result, struct timeval *x, struct timeval *y); + +#endif diff --git a/src/gallium/state_trackers/xorg/xvmc/tests/xvmc_bench.c b/src/gallium/state_trackers/xorg/xvmc/tests/xvmc_bench.c new file mode 100644 index 00000000000..bf94d856234 --- /dev/null +++ b/src/gallium/state_trackers/xorg/xvmc/tests/xvmc_bench.c @@ -0,0 +1,300 @@ +/************************************************************************** + * + * Copyright 2009 Younes Manton. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include <assert.h> +#include <stdio.h> +#include <string.h> +#include <error.h> +#include <sys/time.h> +#include "testlib.h" + +#define MACROBLOCK_WIDTH 16 +#define MACROBLOCK_HEIGHT 16 +#define BLOCKS_PER_MACROBLOCK 6 + +#define DEFAULT_INPUT_WIDTH 720 +#define DEFAULT_INPUT_HEIGHT 480 +#define DEFAULT_REPS 100 + +#define PIPELINE_STEP_MC 1 +#define PIPELINE_STEP_CSC 2 +#define PIPELINE_STEP_SWAP 4 + +#define MB_TYPE_I 1 +#define MB_TYPE_P 2 +#define MB_TYPE_B 4 + +struct Config +{ + unsigned int input_width; + unsigned int input_height; + unsigned int output_width; + unsigned int output_height; + unsigned int pipeline; + unsigned int mb_types; + unsigned int reps; +}; + +void ParseArgs(int argc, char **argv, struct Config *config); + +void ParseArgs(int argc, char **argv, struct Config *config) +{ + int fail = 0; + int i; + + config->input_width = DEFAULT_INPUT_WIDTH; + config->input_height = DEFAULT_INPUT_HEIGHT; + config->output_width = 0; + config->output_height = 0; + config->pipeline = 0; + config->mb_types = 0; + config->reps = DEFAULT_REPS; + + for (i = 1; i < argc && !fail; ++i) + { + if (!strcmp(argv[i], "-iw")) + { + if (sscanf(argv[++i], "%u", &config->input_width) != 1) + fail = 1; + } + else if (!strcmp(argv[i], "-ih")) + { + if (sscanf(argv[++i], "%u", &config->input_height) != 1) + fail = 1; + } + else if (!strcmp(argv[i], "-ow")) + { + if (sscanf(argv[++i], "%u", &config->output_width) != 1) + fail = 1; + } + else if (!strcmp(argv[i], "-oh")) + { + if (sscanf(argv[++i], "%u", &config->output_height) != 1) + fail = 1; + } + else if (!strcmp(argv[i], "-p")) + { + char *token = strtok(argv[++i], ","); + + while (token && !fail) + { + if (!strcmp(token, "mc")) + config->pipeline |= PIPELINE_STEP_MC; + else if (!strcmp(token, "csc")) + config->pipeline |= PIPELINE_STEP_CSC; + else if (!strcmp(token, "swp")) + config->pipeline |= PIPELINE_STEP_SWAP; + else + fail = 1; + + if (!fail) + token = strtok(NULL, ","); + } + } + else if (!strcmp(argv[i], "-mb")) + { + char *token = strtok(argv[++i], ","); + + while (token && !fail) + { + if (strcmp(token, "i")) + config->mb_types |= MB_TYPE_I; + else if (strcmp(token, "p")) + config->mb_types |= MB_TYPE_P; + else if (strcmp(token, "b")) + config->mb_types |= MB_TYPE_B; + else + fail = 1; + + if (!fail) + token = strtok(NULL, ","); + } + } + else if (!strcmp(argv[i], "-r")) + { + if (sscanf(argv[++i], "%u", &config->reps) != 1) + fail = 1; + } + else + fail = 1; + } + + if (fail) + error + ( + 1, 0, + "Bad argument.\n" + "\n" + "Usage: %s [options]\n" + "\t-iw <width>\tInput width\n" + "\t-ih <height>\tInput height\n" + "\t-ow <width>\tOutput width\n" + "\t-oh <height>\tOutput height\n" + "\t-p <pipeline>\tPipeline to test\n" + "\t-mb <mb type>\tMacroBlock types to use\n" + "\t-r <reps>\tRepetitions\n\n" + "\tPipeline steps: mc,csc,swap\n" + "\tMB types: i,p,b\n", + argv[0] + ); + + if (config->output_width == 0) + config->output_width = config->input_width; + if (config->output_height == 0) + config->output_height = config->input_height; + if (!config->pipeline) + config->pipeline = PIPELINE_STEP_MC | PIPELINE_STEP_CSC | PIPELINE_STEP_SWAP; + if (!config->mb_types) + config->mb_types = MB_TYPE_I | MB_TYPE_P | MB_TYPE_B; +} + +int main(int argc, char **argv) +{ + struct Config config; + Display *display; + Window root, window; + const unsigned int mc_types[2] = {XVMC_MOCOMP | XVMC_MPEG_2, XVMC_IDCT | XVMC_MPEG_2}; + XvPortID port_num; + int surface_type_id; + unsigned int is_overlay, intra_unsigned; + int colorkey; + XvMCContext context; + XvMCSurface surface; + XvMCBlockArray block_array; + XvMCMacroBlockArray mb_array; + unsigned int mbw, mbh; + unsigned int mbx, mby; + unsigned int reps; + struct timeval start, stop, diff; + double diff_secs; + + ParseArgs(argc, argv, &config); + + mbw = align(config.input_width, MACROBLOCK_WIDTH) / MACROBLOCK_WIDTH; + mbh = align(config.input_height, MACROBLOCK_HEIGHT) / MACROBLOCK_HEIGHT; + + display = XOpenDisplay(NULL); + + if (!GetPort + ( + display, + config.input_width, + config.input_height, + XVMC_CHROMA_FORMAT_420, + mc_types, + 2, + &port_num, + &surface_type_id, + &is_overlay, + &intra_unsigned + )) + { + 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); + } + + root = XDefaultRootWindow(display); + window = XCreateSimpleWindow(display, root, 0, 0, config.output_width, config.output_height, 0, 0, colorkey); + + assert(XvMCCreateContext(display, port_num, surface_type_id, config.input_width, config.input_height, XVMC_DIRECT, &context) == Success); + assert(XvMCCreateSurface(display, &context, &surface) == Success); + assert(XvMCCreateBlocks(display, &context, mbw * mbh * BLOCKS_PER_MACROBLOCK, &block_array) == Success); + assert(XvMCCreateMacroBlocks(display, &context, mbw * mbh, &mb_array) == Success); + + for (mby = 0; mby < mbh; ++mby) + for (mbx = 0; mbx < mbw; ++mbx) + { + mb_array.macro_blocks[mby * mbw + mbx].x = mbx; + mb_array.macro_blocks[mby * mbw + mbx].y = mby; + mb_array.macro_blocks[mby * mbw + mbx].macroblock_type = XVMC_MB_TYPE_INTRA; + /*mb->motion_type = ;*/ + /*mb->motion_vertical_field_select = ;*/ + mb_array.macro_blocks[mby * mbw + mbx].dct_type = XVMC_DCT_TYPE_FRAME; + /*mb->PMV[0][0][0] = ; + mb->PMV[0][0][1] = ; + mb->PMV[0][1][0] = ; + mb->PMV[0][1][1] = ; + mb->PMV[1][0][0] = ; + mb->PMV[1][0][1] = ; + mb->PMV[1][1][0] = ; + mb->PMV[1][1][1] = ;*/ + mb_array.macro_blocks[mby * mbw + mbx].index = (mby * mbw + mbx) * BLOCKS_PER_MACROBLOCK; + mb_array.macro_blocks[mby * mbw + mbx].coded_block_pattern = 0x3F; + } + + XSelectInput(display, window, ExposureMask | KeyPressMask); + XMapWindow(display, window); + XSync(display, 0); + + gettimeofday(&start, NULL); + + for (reps = 0; reps < config.reps; ++reps) + { + if (config.pipeline & PIPELINE_STEP_MC) + { + assert(XvMCRenderSurface(display, &context, XVMC_FRAME_PICTURE, &surface, NULL, NULL, 0, mbw * mbh, 0, &mb_array, &block_array) == Success); + assert(XvMCFlushSurface(display, &surface) == Success); + } + if (config.pipeline & PIPELINE_STEP_CSC) + assert(XvMCPutSurface(display, &surface, window, 0, 0, config.input_width, config.input_height, 0, 0, config.output_width, config.output_height, XVMC_FRAME_PICTURE) == Success); + } + + gettimeofday(&stop, NULL); + + timeval_subtract(&diff, &stop, &start); + diff_secs = (double)diff.tv_sec + (double)diff.tv_usec / 1000000.0; + + printf("XvMC Benchmark\n"); + printf("Input: %u,%u\nOutput: %u,%u\n", config.input_width, config.input_height, config.output_width, config.output_height); + printf("Pipeline: "); + if (config.pipeline & PIPELINE_STEP_MC) + printf("|mc|"); + if (config.pipeline & PIPELINE_STEP_CSC) + printf("|csc|"); + if (config.pipeline & PIPELINE_STEP_SWAP) + printf("|swap|"); + printf("\n"); + printf("Reps: %u\n", config.reps); + printf("Total time: %.2lf (%.2lf reps / sec)\n", diff_secs, config.reps / diff_secs); + + assert(XvMCDestroyBlocks(display, &block_array) == Success); + assert(XvMCDestroyMacroBlocks(display, &mb_array) == Success); + assert(XvMCDestroySurface(display, &surface) == Success); + assert(XvMCDestroyContext(display, &context) == Success); + + XvUngrabPort(display, port_num, CurrentTime); + XDestroyWindow(display, window); + XCloseDisplay(display); + + return 0; +} diff --git a/src/gallium/state_trackers/xorg/xvmc/xvmc_private.h b/src/gallium/state_trackers/xorg/xvmc/xvmc_private.h new file mode 100644 index 00000000000..5f8d9d13cb3 --- /dev/null +++ b/src/gallium/state_trackers/xorg/xvmc/xvmc_private.h @@ -0,0 +1,139 @@ +/************************************************************************** + * + * Copyright 2009 Younes Manton. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef xvmc_private_h +#define xvmc_private_h + +#include <X11/Xlib.h> +#include <X11/extensions/XvMClib.h> + +#include <pipe/p_video_state.h> + +#include <util/u_debug.h> +#include <util/u_math.h> + +#include <vl/vl_csc.h> +#include <vl/vl_compositor.h> + +#define BLOCK_SIZE_SAMPLES 64 +#define BLOCK_SIZE_BYTES (BLOCK_SIZE_SAMPLES * 2) + +struct vl_context; + +struct pipe_video_decoder; +struct pipe_video_decode_buffer; +struct pipe_video_buffer; + +struct pipe_sampler_view; +struct pipe_fence_handle; + +typedef struct +{ + struct vl_context *vctx; + struct pipe_video_decoder *decoder; + + enum VL_CSC_COLOR_STANDARD color_standard; + struct vl_procamp procamp; + struct vl_compositor compositor; + + unsigned short subpicture_max_width; + unsigned short subpicture_max_height; + + struct pipe_video_rect dst_rect; + struct pipe_surface *drawable_surface; + +} XvMCContextPrivate; + +typedef struct +{ + struct pipe_video_decode_buffer *decode_buffer; + struct pipe_video_buffer *video_buffer; + + bool mapped; // are we still mapped to memory? + + struct { + unsigned num_blocks_added; + struct pipe_ycbcr_block *stream; + short *buffer; + } ycbcr[3]; + + unsigned mv_stride; + struct { + XvMCSurface *surface; + struct pipe_motionvector *mv; + } ref[2]; + + struct pipe_fence_handle *fence; + + /* The subpicture associated with this surface, if any. */ + XvMCSubpicture *subpicture; + + /* Some XvMC functions take a surface but not a context, + so we keep track of which context each surface belongs to. */ + XvMCContext *context; +} XvMCSurfacePrivate; + +typedef struct +{ + struct pipe_sampler_view *sampler; + + /* optional palette for this subpicture */ + struct pipe_sampler_view *palette; + + struct pipe_video_rect src_rect; + struct pipe_video_rect dst_rect; + + /* The surface this subpicture is currently associated with, if any. */ + XvMCSurface *surface; + + /* Some XvMC functions take a subpicture but not a context, + so we keep track of which context each subpicture belongs to. */ + XvMCContext *context; +} XvMCSubpicturePrivate; + +#define XVMC_OUT 0 +#define XVMC_ERR 1 +#define XVMC_WARN 2 +#define XVMC_TRACE 3 + +static INLINE void XVMC_MSG(unsigned int level, const char *fmt, ...) +{ + static int debug_level = -1; + + if (debug_level == -1) { + debug_level = MAX2(debug_get_num_option("XVMC_DEBUG", 0), 0); + } + + if (level <= debug_level) { + va_list ap; + va_start(ap, fmt); + _debug_vprintf(fmt, ap); + va_end(ap); + } +} + +#endif /* xvmc_private_h */ |