diff --git a/packages/graphics/Mesa/package.mk b/packages/graphics/Mesa/package.mk index f772b85b03..c6b025f5c2 100644 --- a/packages/graphics/Mesa/package.mk +++ b/packages/graphics/Mesa/package.mk @@ -19,7 +19,7 @@ ################################################################################ PKG_NAME="Mesa" -PKG_VERSION="c325aa5" +PKG_VERSION="5442c0e" PKG_REV="1" PKG_ARCH="any" PKG_LICENSE="OSS" @@ -85,6 +85,7 @@ PKG_CONFIGURE_OPTS_TARGET="CC_FOR_BUILD=$HOST_CC \ --disable-gles2 \ --disable-openvg \ --enable-dri \ + --disable-dri3 \ --enable-glx \ --disable-osmesa \ --disable-egl \ diff --git a/packages/graphics/Mesa/patches/Mesa-001-implement-NV_vdpau_interop-v5.patch b/packages/graphics/Mesa/patches/Mesa-001-implement-NV_vdpau_interop-v5.patch deleted file mode 100644 index 67c81964bc..0000000000 --- a/packages/graphics/Mesa/patches/Mesa-001-implement-NV_vdpau_interop-v5.patch +++ /dev/null @@ -1,1026 +0,0 @@ -From b6f37beabda60079cf623d71914b3adb5af27ab3 Mon Sep 17 00:00:00 2001 -From: Christian König -Date: Wed, 15 May 2013 13:10:11 +0000 -Subject: implement NV_vdpau_interop v5 - -v2: Actually implement interop between the gallium - state tracker and the VDPAU backend. - -v3: Make it also available in non legacy contexts, - fix video buffer sharing. - -v4: deny interop if we don't have the same screen object - -v5: rebased on upstream changes - -Signed-off-by: Christian König ---- -diff --git a/src/gallium/include/state_tracker/vdpau_interop.h b/src/gallium/include/state_tracker/vdpau_interop.h -new file mode 100644 -index 0000000..3ca7c9d ---- a/dev/null -+++ b/src/gallium/include/state_tracker/vdpau_interop.h -@@ -0,0 +1,49 @@ -+/************************************************************************** -+ * -+ * Copyright 2013 Advanced Micro Devices, Inc. -+ * 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 THE COPYRIGHT HOLDER(S) OR AUTHOR(S) 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. -+ * -+ **************************************************************************/ -+ -+/* -+ * Authors: -+ * Christian König -+ * -+ */ -+ -+#ifndef _VDPAU_INTEROP_H_ -+#define _VDPAU_INTEROP_H_ -+ -+/* driver specific functions for NV_vdpau_interop */ -+ -+#define VDP_FUNC_ID_BASE_DRIVER 0x2000 -+#define VDP_FUNC_ID_VIDEO_SURFACE_GALLIUM (VDP_FUNC_ID_BASE_DRIVER + 0) -+#define VDP_FUNC_ID_OUTPUT_SURFACE_GALLIUM (VDP_FUNC_ID_BASE_DRIVER + 1) -+ -+struct pipe_resource; -+struct pipe_video_buffer; -+ -+typedef struct pipe_video_buffer *VdpVideoSurfaceGallium(uint32_t surface); -+typedef struct pipe_resource *VdpOutputSurfaceGallium(uint32_t surface); -+ -+#endif /* _VDPAU_INTEROP_H_ */ -diff --git a/src/gallium/state_trackers/vdpau/ftab.c b/src/gallium/state_trackers/vdpau/ftab.c -index 81d16ec..2c84554 100644 ---- a/src/gallium/state_trackers/vdpau/ftab.c -+++ b/src/gallium/state_trackers/vdpau/ftab.c -@@ -26,6 +26,9 @@ - **************************************************************************/ - - #include -+ -+#include "util/u_memory.h" -+ - #include "vdpau_private.h" - - static void* ftab[67] = -@@ -104,19 +107,31 @@ static void* ftab_winsys[1] = - &vlVdpPresentationQueueTargetCreateX11 /* VDP_FUNC_ID_PRESENTATION_QUEUE_TARGET_CREATE_X11 */ - }; - -+static void* ftab_driver[2] = -+{ -+ &vlVdpVideoSurfaceGallium, /* VDP_FUNC_ID_SURFACE_GALLIUM */ -+ &vlVdpOutputSurfaceGallium /* VDP_FUNC_ID_OUTPUT_SURFACE_GALLIUM */ -+}; -+ - boolean vlGetFuncFTAB(VdpFuncId function_id, void **func) - { - assert(func); -+ *func = NULL; -+ - if (function_id < VDP_FUNC_ID_BASE_WINSYS) { -- if (function_id > 66) -- return FALSE; -- *func = ftab[function_id]; -- } -- else { -+ if (function_id < Elements(ftab)) -+ *func = ftab[function_id]; -+ -+ } else if (function_id < VDP_FUNC_ID_BASE_DRIVER) { - function_id -= VDP_FUNC_ID_BASE_WINSYS; -- if (function_id > 0) -- return FALSE; -- *func = ftab_winsys[function_id]; -+ if (function_id < Elements(ftab_winsys)) -+ *func = ftab_winsys[function_id]; -+ -+ } else { -+ function_id -= VDP_FUNC_ID_BASE_DRIVER; -+ if (function_id < Elements(ftab_driver)) -+ *func = ftab_driver[function_id]; - } -+ - return *func != NULL; - } -diff --git a/src/gallium/state_trackers/vdpau/output.c b/src/gallium/state_trackers/vdpau/output.c -index cf77b53..def01c8 100644 ---- a/src/gallium/state_trackers/vdpau/output.c -+++ b/src/gallium/state_trackers/vdpau/output.c -@@ -725,3 +725,14 @@ vlVdpOutputSurfaceRenderBitmapSurface(VdpOutputSurface destination_surface, - - return VDP_STATUS_OK; - } -+ -+struct pipe_resource *vlVdpOutputSurfaceGallium(VdpOutputSurface surface) -+{ -+ vlVdpOutputSurface *vlsurface; -+ -+ vlsurface = vlGetDataHTAB(surface); -+ if (!vlsurface || !vlsurface->surface) -+ return NULL; -+ -+ return vlsurface->surface->texture; -+} -diff --git a/src/gallium/state_trackers/vdpau/surface.c b/src/gallium/state_trackers/vdpau/surface.c -index e371bca..a5682e3 100644 ---- a/src/gallium/state_trackers/vdpau/surface.c -+++ b/src/gallium/state_trackers/vdpau/surface.c -@@ -360,3 +360,24 @@ vlVdpVideoSurfaceClear(vlVdpSurface *vlsurf) - } - pipe->flush(pipe, NULL, 0); - } -+ -+/** -+ * Interop to mesa state tracker -+ */ -+struct pipe_video_buffer *vlVdpVideoSurfaceGallium(VdpVideoSurface surface) -+{ -+ vlVdpSurface *p_surf = vlGetDataHTAB(surface); -+ if (!p_surf) -+ return NULL; -+ -+ pipe_mutex_lock(p_surf->device->mutex); -+ if (p_surf->video_buffer == NULL) { -+ struct pipe_context *pipe = p_surf->device->context; -+ -+ /* try to create a video buffer if we don't already have one */ -+ p_surf->video_buffer = pipe->create_video_buffer(pipe, &p_surf->templat); -+ } -+ pipe_mutex_unlock(p_surf->device->mutex); -+ -+ return p_surf->video_buffer; -+} -diff --git a/src/gallium/state_trackers/vdpau/vdpau_private.h b/src/gallium/state_trackers/vdpau/vdpau_private.h -index bb91de1..60196ac 100644 ---- a/src/gallium/state_trackers/vdpau/vdpau_private.h -+++ b/src/gallium/state_trackers/vdpau/vdpau_private.h -@@ -36,6 +36,8 @@ - #include "pipe/p_compiler.h" - #include "pipe/p_video_codec.h" - -+#include "state_tracker/vdpau_interop.h" -+ - #include "util/u_debug.h" - #include "util/u_rect.h" - #include "os/os_thread.h" -@@ -498,6 +500,10 @@ VdpVideoMixerGetAttributeValues vlVdpVideoMixerGetAttributeValues; - VdpVideoMixerDestroy vlVdpVideoMixerDestroy; - VdpGenerateCSCMatrix vlVdpGenerateCSCMatrix; - -+/* interop to mesa state tracker */ -+VdpVideoSurfaceGallium vlVdpVideoSurfaceGallium; -+VdpOutputSurfaceGallium vlVdpOutputSurfaceGallium; -+ - #define VDPAU_OUT 0 - #define VDPAU_ERR 1 - #define VDPAU_WARN 2 -diff --git a/src/mapi/glapi/gen/Makefile.am b/src/mapi/glapi/gen/Makefile.am -index 6bb2f1e..d363885a 100644 ---- a/src/mapi/glapi/gen/Makefile.am -+++ b/src/mapi/glapi/gen/Makefile.am -@@ -133,6 +133,7 @@ API_XML = \ - NV_conditional_render.xml \ - NV_primitive_restart.xml \ - NV_texture_barrier.xml \ -+ NV_vdpau_interop.xml \ - OES_EGL_image.xml \ - GL3x.xml - -diff --git a/src/mapi/glapi/gen/NV_vdpau_interop.xml b/src/mapi/glapi/gen/NV_vdpau_interop.xml -new file mode 100644 -index 0000000..cf5f0ed ---- a/dev/null -+++ b/src/mapi/glapi/gen/NV_vdpau_interop.xml -@@ -0,0 +1,69 @@ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -+ -diff --git a/src/mapi/glapi/gen/gl_API.xml b/src/mapi/glapi/gen/gl_API.xml -index 48fce36..93ae72b 100644 ---- a/src/mapi/glapi/gen/gl_API.xml -+++ b/src/mapi/glapi/gen/gl_API.xml -@@ -13150,4 +13150,6 @@ - - - -+ -+ - -diff --git a/src/mapi/glapi/gen/gl_genexec.py b/src/mapi/glapi/gen/gl_genexec.py -index a074c23..3ce190f 100644 ---- a/src/mapi/glapi/gen/gl_genexec.py -+++ b/src/mapi/glapi/gen/gl_genexec.py -@@ -111,6 +111,7 @@ header = """/** - #include "main/syncobj.h" - #include "main/formatquery.h" - #include "main/dispatch.h" -+#include "main/vdpau.h" - #include "vbo/vbo.h" - - -diff --git a/src/mesa/Makefile.sources b/src/mesa/Makefile.sources -index ff242b4..a84f8a7 100644 ---- a/src/mesa/Makefile.sources -+++ b/src/mesa/Makefile.sources -@@ -108,6 +108,7 @@ MAIN_FILES = \ - $(SRCDIR)main/uniforms.c \ - $(SRCDIR)main/uniform_query.cpp \ - $(SRCDIR)main/varray.c \ -+ $(SRCDIR)main/vdpau.c \ - $(SRCDIR)main/version.c \ - $(SRCDIR)main/viewport.c \ - $(SRCDIR)main/vtxfmt.c \ -@@ -248,7 +249,8 @@ STATETRACKER_FILES = \ - $(SRCDIR)state_tracker/st_manager.c \ - $(SRCDIR)state_tracker/st_mesa_to_tgsi.c \ - $(SRCDIR)state_tracker/st_program.c \ -- $(SRCDIR)state_tracker/st_texture.c -+ $(SRCDIR)state_tracker/st_texture.c \ -+ $(SRCDIR)state_tracker/st_vdpau.c - - PROGRAM_FILES = \ - $(SRCDIR)program/arbprogparse.c \ -diff --git a/src/mesa/main/dd.h b/src/mesa/main/dd.h -index 0806e41..04eac88 100644 ---- a/src/mesa/main/dd.h -+++ b/src/mesa/main/dd.h -@@ -867,6 +867,20 @@ struct dd_function_table { - struct gl_framebuffer *fb, - GLuint index, - GLfloat *outValue); -+ -+ /** -+ * \name NV_vdpau_interop interface -+ */ -+ void (*VDPAUMapSurface)(struct gl_context *ctx, GLenum target, -+ GLenum access, GLboolean output, -+ struct gl_texture_object *texObj, -+ struct gl_texture_image *texImage, -+ const GLvoid *vdpSurface, GLuint index); -+ void (*VDPAUUnmapSurface)(struct gl_context *ctx, GLenum target, -+ GLenum access, GLboolean output, -+ struct gl_texture_object *texObj, -+ struct gl_texture_image *texImage, -+ const GLvoid *vdpSurface, GLuint index); - }; - - -diff --git a/src/mesa/main/extensions.c b/src/mesa/main/extensions.c -index 2507fdf..92039e9 100644 ---- a/src/mesa/main/extensions.c -+++ b/src/mesa/main/extensions.c -@@ -334,6 +334,7 @@ static const struct extension extension_table[] = { - { "GL_NV_texture_barrier", o(NV_texture_barrier), GL, 2009 }, - { "GL_NV_texture_env_combine4", o(NV_texture_env_combine4), GLL, 1999 }, - { "GL_NV_texture_rectangle", o(NV_texture_rectangle), GLL, 2000 }, -+ { "GL_NV_vdpau_interop", o(NV_vdpau_interop), GL, 2010 }, - { "GL_S3_s3tc", o(ANGLE_texture_compression_dxt), GL, 1999 }, - { "GL_SGIS_generate_mipmap", o(dummy_true), GLL, 1997 }, - { "GL_SGIS_texture_border_clamp", o(ARB_texture_border_clamp), GLL, 1997 }, -diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h -index 15893ec..16f8317 100644 ---- a/src/mesa/main/mtypes.h -+++ b/src/mesa/main/mtypes.h -@@ -3291,6 +3291,7 @@ struct gl_extensions - GLboolean NV_texture_barrier; - GLboolean NV_texture_env_combine4; - GLboolean NV_texture_rectangle; -+ GLboolean NV_vdpau_interop; - GLboolean TDFX_texture_compression_FXT1; - GLboolean OES_EGL_image; - GLboolean OES_draw_texture; -@@ -3821,6 +3822,14 @@ struct gl_context - struct st_context *st; - void *aelt_context; - /*@}*/ -+ -+ /** -+ * \name NV_vdpau_interop -+ */ -+ /*@{*/ -+ const void *vdpDevice; -+ const void *vdpGetProcAddress; -+ /*@}*/ - }; - - -diff --git a/src/mesa/main/vdpau.c b/src/mesa/main/vdpau.c -new file mode 100644 -index 0000000..68f087b ---- a/dev/null -+++ b/src/mesa/main/vdpau.c -@@ -0,0 +1,279 @@ -+/************************************************************************** -+ * -+ * Copyright 2013 Advanced Micro Devices, Inc. -+ * 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 THE COPYRIGHT HOLDER(S) OR AUTHOR(S) 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. -+ * -+ **************************************************************************/ -+ -+/* -+ * Authors: -+ * Christian König -+ * -+ */ -+ -+#include -+#include "context.h" -+#include "glformats.h" -+#include "texobj.h" -+#include "teximage.h" -+#include "vdpau.h" -+ -+#define MAX_TEXTURES 4 -+ -+struct vdp_surface -+{ -+ GLenum target; -+ struct gl_texture_object *textures[MAX_TEXTURES]; -+ GLenum access; -+ GLboolean output; -+ const GLvoid *vdpSurface; -+}; -+ -+void GLAPIENTRY -+_mesa_VDPAUInitNV(const GLvoid *vdpDevice, const GLvoid *getProcAddress) -+{ -+ GET_CURRENT_CONTEXT(ctx); -+ -+ if (!vdpDevice) { -+ _mesa_error(ctx, GL_INVALID_VALUE, "vdpDevice"); -+ return; -+ } -+ -+ if (!getProcAddress) { -+ _mesa_error(ctx, GL_INVALID_VALUE, "getProcAddress"); -+ return; -+ } -+ -+ if (ctx->vdpDevice || ctx->vdpGetProcAddress) { -+ _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUInitNV"); -+ return; -+ } -+ -+ ctx->vdpDevice = vdpDevice; -+ ctx->vdpGetProcAddress = getProcAddress; -+} -+ -+void GLAPIENTRY -+_mesa_VDPAUFiniNV() -+{ -+ GET_CURRENT_CONTEXT(ctx); -+ -+ if (!ctx->vdpDevice || !ctx->vdpGetProcAddress) { -+ _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUFiniNV"); -+ return; -+ } -+ -+ /* TODO: unregister all surfaces */ -+ -+ ctx->vdpDevice = 0; -+ ctx->vdpGetProcAddress = 0; -+} -+ -+static GLintptr -+register_surface(struct gl_context *ctx, GLboolean isOutput, -+ const GLvoid *vdpSurface, GLenum target, -+ GLsizei numTextureNames, const GLuint *textureNames) -+{ -+ struct vdp_surface *surf; -+ int i; -+ -+ if (!ctx->vdpDevice || !ctx->vdpGetProcAddress) { -+ _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAURegisterSurfaceNV"); -+ return (GLintptr)NULL; -+ } -+ -+ if (target != GL_TEXTURE_2D && target != GL_TEXTURE_RECTANGLE) { -+ _mesa_error(ctx, GL_INVALID_ENUM, "VDPAURegisterSurfaceNV"); -+ return (GLintptr)NULL; -+ } -+ -+ surf = MALLOC_STRUCT( vdp_surface ); -+ surf->vdpSurface = vdpSurface; -+ surf->target = target; -+ surf->access = GL_READ_WRITE; -+ surf->output = isOutput; -+ for (i = 0; i < numTextureNames; ++i) { -+ struct gl_texture_object *tex; -+ tex = _mesa_lookup_texture(ctx, textureNames[i]); -+ -+ if (tex->Target == 0) -+ tex->Target = target; -+ else if (tex->Target != target) { -+ _mesa_error(ctx, GL_INVALID_OPERATION, -+ "VDPAURegisterSurfaceNV(target mismatch)"); -+ return (GLintptr)NULL; -+ } -+ -+ surf->textures[i] = tex; -+ } -+ -+ return (GLintptr)surf; -+} -+ -+GLintptr GLAPIENTRY -+_mesa_VDPAURegisterVideoSurfaceNV(const GLvoid *vdpSurface, GLenum target, -+ GLsizei numTextureNames, -+ const GLuint *textureNames) -+{ -+ GET_CURRENT_CONTEXT(ctx); -+ -+ if (numTextureNames != 4) { -+ _mesa_error(ctx, GL_INVALID_VALUE, "VDPAURegisterVideoSurfaceNV"); -+ return (GLintptr)NULL; -+ } -+ -+ return register_surface(ctx, false, vdpSurface, target, -+ numTextureNames, textureNames); -+} -+ -+GLintptr GLAPIENTRY -+_mesa_VDPAURegisterOutputSurfaceNV(const GLvoid *vdpSurface, GLenum target, -+ GLsizei numTextureNames, -+ const GLuint *textureNames) -+{ -+ GET_CURRENT_CONTEXT(ctx); -+ -+ if (numTextureNames != 1) { -+ _mesa_error(ctx, GL_INVALID_VALUE, "VDPAURegisterVideoSurfaceNV"); -+ return (GLintptr)NULL; -+ } -+ -+ return register_surface(ctx, true, vdpSurface, target, -+ numTextureNames, textureNames); -+} -+ -+void GLAPIENTRY -+_mesa_VDPAUIsSurfaceNV(GLintptr surface) -+{ -+ GET_CURRENT_CONTEXT(ctx); -+ -+ if (!ctx->vdpDevice || !ctx->vdpGetProcAddress) { -+ _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUIsSurfaceNV"); -+ return; -+ } -+} -+ -+void GLAPIENTRY -+_mesa_VDPAUUnregisterSurfaceNV(GLintptr surface) -+{ -+ FREE((struct vdp_surface *)surface); -+} -+ -+void GLAPIENTRY -+_mesa_VDPAUGetSurfaceivNV(GLintptr surface, GLenum pname, GLsizei bufSize, -+ GLsizei *length, GLint *values) -+{ -+ GET_CURRENT_CONTEXT(ctx); -+ -+ if (!ctx->vdpDevice || !ctx->vdpGetProcAddress) { -+ _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUGetSurfaceivNV"); -+ return; -+ } -+} -+ -+void GLAPIENTRY -+_mesa_VDPAUSurfaceAccessNV(GLintptr surface, GLenum access) -+{ -+ struct vdp_surface *surf = (struct vdp_surface *)surface; -+ GET_CURRENT_CONTEXT(ctx); -+ -+ if (!ctx->vdpDevice || !ctx->vdpGetProcAddress) { -+ _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUSurfaceAccessNV"); -+ return; -+ } -+ -+ surf->access = access; -+} -+ -+void GLAPIENTRY -+_mesa_VDPAUMapSurfacesNV(GLsizei numSurfaces, const GLintptr *surfaces) -+{ -+ GET_CURRENT_CONTEXT(ctx); -+ int i, j; -+ -+ if (!ctx->vdpDevice || !ctx->vdpGetProcAddress) { -+ _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUUnmapSurfacesNV"); -+ return; -+ } -+ -+ for (i = 0; i < numSurfaces; ++i) { -+ struct vdp_surface *surf = (struct vdp_surface *)surfaces[i]; -+ unsigned numTextureNames = surf->output ? 1 : 4; -+ -+ for (j = 0; j < numTextureNames; ++j) { -+ struct gl_texture_object *tex = surf->textures[j]; -+ struct gl_texture_image *image; -+ -+ _mesa_lock_texture(ctx, tex); -+ image = _mesa_get_tex_image(ctx, tex, surf->target, 0); -+ if (!image) { -+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "VDPAUMapSurfacesNV"); -+ _mesa_unlock_texture(ctx, tex); -+ return; -+ } -+ -+ ctx->Driver.FreeTextureImageBuffer(ctx, image); -+ -+ ctx->Driver.VDPAUMapSurface(ctx, surf->target, surf->access, -+ surf->output, tex, image, -+ surf->vdpSurface, j); -+ -+ _mesa_unlock_texture(ctx, tex); -+ } -+ } -+} -+ -+void GLAPIENTRY -+_mesa_VDPAUUnmapSurfacesNV(GLsizei numSurfaces, const GLintptr *surfaces) -+{ -+ GET_CURRENT_CONTEXT(ctx); -+ int i, j; -+ -+ if (!ctx->vdpDevice || !ctx->vdpGetProcAddress) { -+ _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUUnmapSurfacesNV"); -+ return; -+ } -+ -+ for (i = 0; i < numSurfaces; ++i) { -+ struct vdp_surface *surf = (struct vdp_surface *)surfaces[i]; -+ unsigned numTextureNames = surf->output ? 1 : 4; -+ -+ for (j = 0; j < numTextureNames; ++j) { -+ struct gl_texture_object *tex = surf->textures[j]; -+ struct gl_texture_image *image; -+ -+ _mesa_lock_texture(ctx, tex); -+ -+ image = _mesa_select_tex_image(ctx, tex, surf->target, 0); -+ -+ ctx->Driver.VDPAUUnmapSurface(ctx, surf->target, surf->access, -+ surf->output, tex, image, -+ surf->vdpSurface, j); -+ -+ if (image) -+ ctx->Driver.FreeTextureImageBuffer(ctx, image); -+ -+ _mesa_unlock_texture(ctx, tex); -+ } -+ } -+} -diff --git a/src/mesa/main/vdpau.h b/src/mesa/main/vdpau.h -new file mode 100644 -index 0000000..f32d6da ---- a/dev/null -+++ b/src/mesa/main/vdpau.h -@@ -0,0 +1,72 @@ -+/************************************************************************** -+ * -+ * Copyright 2013 Advanced Micro Devices, Inc. -+ * 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 THE COPYRIGHT HOLDER(S) OR AUTHOR(S) 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. -+ * -+ **************************************************************************/ -+ -+/* -+ * Authors: -+ * Christian König -+ * -+ */ -+ -+#ifndef VDPAU_H -+#define VDPAU_H -+ -+extern void GLAPIENTRY -+_mesa_VDPAUInitNV(const GLvoid *vdpDevice, const GLvoid *getProcAddress); -+ -+extern void GLAPIENTRY -+_mesa_VDPAUFiniNV(void); -+ -+extern GLintptr GLAPIENTRY -+_mesa_VDPAURegisterVideoSurfaceNV(const GLvoid *vdpSurface, GLenum target, -+ GLsizei numTextureNames, -+ const GLuint *textureNames); -+ -+extern GLintptr GLAPIENTRY -+_mesa_VDPAURegisterOutputSurfaceNV(const GLvoid *vdpSurface, GLenum target, -+ GLsizei numTextureNames, -+ const GLuint *textureNames); -+ -+extern void GLAPIENTRY -+_mesa_VDPAUIsSurfaceNV(GLintptr surface); -+ -+extern void GLAPIENTRY -+_mesa_VDPAUUnregisterSurfaceNV(GLintptr surface); -+ -+extern void GLAPIENTRY -+_mesa_VDPAUGetSurfaceivNV(GLintptr surface, GLenum pname, GLsizei bufSize, -+ GLsizei *length, GLint *values); -+ -+extern void GLAPIENTRY -+_mesa_VDPAUSurfaceAccessNV(GLintptr surface, GLenum access); -+ -+extern void GLAPIENTRY -+_mesa_VDPAUMapSurfacesNV(GLsizei numSurfaces, const GLintptr *surfaces); -+ -+extern void GLAPIENTRY -+_mesa_VDPAUUnmapSurfacesNV(GLsizei numSurfaces, const GLintptr *surfaces); -+ -+#endif /* VDPAU_H */ -diff --git a/src/mesa/state_tracker/st_context.c b/src/mesa/state_tracker/st_context.c -index 80393cf..1194437 100644 ---- a/src/mesa/state_tracker/st_context.c -+++ b/src/mesa/state_tracker/st_context.c -@@ -65,6 +65,7 @@ - #include "st_extensions.h" - #include "st_gen_mipmap.h" - #include "st_program.h" -+#include "st_vdpau.h" - #include "pipe/p_context.h" - #include "util/u_inlines.h" - #include "util/u_upload_mgr.h" -@@ -356,5 +357,7 @@ void st_init_driver_functions(struct dd_function_table *functions) - st_init_xformfb_functions(functions); - st_init_syncobj_functions(functions); - -+ st_init_vdpau_functions(functions); -+ - functions->UpdateState = st_invalidate_state; - } -diff --git a/src/mesa/state_tracker/st_extensions.c b/src/mesa/state_tracker/st_extensions.c -index 97dd732..2898a8d 100644 ---- a/src/mesa/state_tracker/st_extensions.c -+++ b/src/mesa/state_tracker/st_extensions.c -@@ -564,6 +564,7 @@ void st_init_extensions(struct st_context *st) - ctx->Extensions.NV_fog_distance = GL_TRUE; - ctx->Extensions.NV_texture_env_combine4 = GL_TRUE; - ctx->Extensions.NV_texture_rectangle = GL_TRUE; -+ ctx->Extensions.NV_vdpau_interop = GL_TRUE; - - ctx->Extensions.OES_EGL_image = GL_TRUE; - ctx->Extensions.OES_EGL_image_external = GL_TRUE; -diff --git a/src/mesa/state_tracker/st_vdpau.c b/src/mesa/state_tracker/st_vdpau.c -new file mode 100644 -index 0000000..9b165ee ---- a/dev/null -+++ b/src/mesa/state_tracker/st_vdpau.c -@@ -0,0 +1,181 @@ -+/************************************************************************** -+ * -+ * Copyright 2013 Advanced Micro Devices, Inc. -+ * 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 THE COPYRIGHT HOLDER(S) OR AUTHOR(S) 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. -+ * -+ **************************************************************************/ -+ -+/* -+ * Authors: -+ * Christian König -+ * -+ */ -+ -+#include "main/texobj.h" -+#include "main/teximage.h" -+#include "main/errors.h" -+#include "program/prog_instruction.h" -+ -+#include "pipe/p_state.h" -+#include "pipe/p_video_codec.h" -+ -+#include "state_tracker/vdpau_interop.h" -+ -+#include "util/u_inlines.h" -+ -+#include "st_vdpau.h" -+#include "st_context.h" -+#include "st_texture.h" -+#include "st_format.h" -+ -+static void -+st_vdpau_map_surface(struct gl_context *ctx, GLenum target, GLenum access, -+ GLboolean output, struct gl_texture_object *texObj, -+ struct gl_texture_image *texImage, -+ const GLvoid *vdpSurface, GLuint index) -+{ -+ int (*getProcAddr)(uint32_t device, uint32_t id, void **ptr); -+ uint32_t device = (uintptr_t)ctx->vdpDevice; -+ -+ struct st_context *st = st_context(ctx); -+ struct st_texture_object *stObj = st_texture_object(texObj); -+ struct st_texture_image *stImage = st_texture_image(texImage); -+ -+ struct pipe_resource *res; -+ struct pipe_sampler_view *sv, templ; -+ gl_format texFormat; -+ -+ getProcAddr = ctx->vdpGetProcAddress; -+ if (output) { -+ VdpOutputSurfaceGallium *f; -+ -+ if (getProcAddr(device, VDP_FUNC_ID_OUTPUT_SURFACE_GALLIUM, (void**)&f)) { -+ _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUMapSurfacesNV"); -+ return; -+ } -+ -+ res = f((uintptr_t)vdpSurface); -+ -+ if (!res) { -+ _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUMapSurfacesNV"); -+ return; -+ } -+ -+ } else { -+ VdpVideoSurfaceGallium *f; -+ -+ struct pipe_video_buffer *buffer; -+ struct pipe_sampler_view **samplers; -+ -+ if (getProcAddr(device, VDP_FUNC_ID_VIDEO_SURFACE_GALLIUM, (void**)&f)) { -+ _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUMapSurfacesNV"); -+ return; -+ } -+ -+ buffer = f((uintptr_t)vdpSurface); -+ if (!buffer) { -+ _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUMapSurfacesNV"); -+ return; -+ } -+ -+ samplers = buffer->get_sampler_view_planes(buffer); -+ if (!samplers) { -+ _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUMapSurfacesNV"); -+ return; -+ } -+ -+ sv = samplers[index >> 1]; -+ if (!sv) { -+ _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUMapSurfacesNV"); -+ return; -+ } -+ -+ res = sv->texture; -+ } -+ -+ if (!res) { -+ _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUMapSurfacesNV"); -+ return; -+ } -+ -+ /* do we have different screen objects ? */ -+ if (res->screen != st->pipe->screen) { -+ _mesa_error(ctx, GL_INVALID_OPERATION, "VDPAUMapSurfacesNV"); -+ return; -+ } -+ -+ /* switch to surface based */ -+ if (!stObj->surface_based) { -+ _mesa_clear_texture_object(ctx, texObj); -+ stObj->surface_based = GL_TRUE; -+ } -+ -+ texFormat = st_pipe_format_to_mesa_format(res->format); -+ -+ _mesa_init_teximage_fields(ctx, texImage, -+ res->width0, res->height0, 1, 0, GL_RGBA, -+ texFormat); -+ -+ pipe_resource_reference(&stObj->pt, res); -+ pipe_sampler_view_reference(&stObj->sampler_view, NULL); -+ pipe_resource_reference(&stImage->pt, res); -+ -+ u_sampler_view_default_template(&templ, res, res->format); -+ templ.u.tex.first_layer = index & 1; -+ templ.u.tex.last_layer = index & 1; -+ templ.swizzle_r = GET_SWZ(stObj->base._Swizzle, 0); -+ templ.swizzle_g = GET_SWZ(stObj->base._Swizzle, 1); -+ templ.swizzle_b = GET_SWZ(stObj->base._Swizzle, 2); -+ templ.swizzle_a = GET_SWZ(stObj->base._Swizzle, 3); -+ stObj->sampler_view = st->pipe->create_sampler_view(st->pipe, res, &templ); -+ -+ stObj->width0 = res->width0; -+ stObj->height0 = res->height0; -+ stObj->depth0 = 1; -+ stObj->surface_format = res->format; -+ -+ _mesa_dirty_texobj(ctx, texObj); -+} -+ -+static void -+st_vdpau_unmap_surface(struct gl_context *ctx, GLenum target, GLenum access, -+ GLboolean output, struct gl_texture_object *texObj, -+ struct gl_texture_image *texImage, -+ const GLvoid *vdpSurface, GLuint index) -+{ -+ struct st_texture_object *stObj = st_texture_object(texObj); -+ struct st_texture_image *stImage = st_texture_image(texImage); -+ -+ pipe_resource_reference(&stObj->pt, NULL); -+ pipe_sampler_view_reference(&stObj->sampler_view, NULL); -+ pipe_resource_reference(&stImage->pt, NULL); -+ -+ _mesa_dirty_texobj(ctx, texObj); -+} -+ -+void -+st_init_vdpau_functions(struct dd_function_table *functions) -+{ -+ functions->VDPAUMapSurface = st_vdpau_map_surface; -+ functions->VDPAUUnmapSurface = st_vdpau_unmap_surface; -+} -diff --git a/src/mesa/state_tracker/st_vdpau.h b/src/mesa/state_tracker/st_vdpau.h -new file mode 100644 -index 0000000..59c7443 ---- a/dev/null -+++ b/src/mesa/state_tracker/st_vdpau.h -@@ -0,0 +1,42 @@ -+/************************************************************************** -+ * -+ * Copyright 2013 Advanced Micro Devices, Inc. -+ * 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 THE COPYRIGHT HOLDER(S) OR AUTHOR(S) 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. -+ * -+ **************************************************************************/ -+ -+/* -+ * Authors: -+ * Christian König -+ * -+ */ -+ -+#ifndef ST_VDPAU_H -+#define ST_VDPAU_H -+ -+struct dd_function_table; -+ -+extern void -+st_init_vdpau_functions(struct dd_function_table *functions); -+ -+#endif /* ST_VDPAU_H */ --- -cgit v0.9.0.2-2-gbebe diff --git a/packages/graphics/Mesa/patches/Mesa-002-make-radeon_drm_winsys_create-public.patch b/packages/graphics/Mesa/patches/Mesa-002-make-radeon_drm_winsys_create-public.patch deleted file mode 100644 index b9bd469a6a..0000000000 --- a/packages/graphics/Mesa/patches/Mesa-002-make-radeon_drm_winsys_create-public.patch +++ /dev/null @@ -1,24 +0,0 @@ -From 3dfe8b13fe2efdf5b284c69c89eb4d436c27bd4a Mon Sep 17 00:00:00 2001 -From: Christian König -Date: Fri, 11 Oct 2013 09:07:44 +0000 -Subject: winsys/radeon: make radeon_drm_winsys_create public - -Otherwise OpenGL/VDPAU interop won't work as expected. - -Signed-off-by: Christian König ---- -diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_winsys.c b/src/gallium/winsys/radeon/drm/radeon_drm_winsys.c -index 4f43093..2200e09 100644 ---- a/src/gallium/winsys/radeon/drm/radeon_drm_winsys.c -+++ b/src/gallium/winsys/radeon/drm/radeon_drm_winsys.c -@@ -599,7 +599,7 @@ next: - DEBUG_GET_ONCE_BOOL_OPTION(thread, "RADEON_THREAD", TRUE) - static PIPE_THREAD_ROUTINE(radeon_drm_cs_emit_ioctl, param); - --struct radeon_winsys *radeon_drm_winsys_create(int fd) -+PUBLIC struct radeon_winsys *radeon_drm_winsys_create(int fd) - { - struct radeon_drm_winsys *ws; - --- -cgit v0.9.0.2-2-gbebe diff --git a/packages/graphics/Mesa/patches/Mesa-motion_adaptive_deinterlacer-v8.patch b/packages/graphics/Mesa/patches/Mesa-motion_adaptive_deinterlacer-v8.patch new file mode 100644 index 0000000000..195b089b75 --- /dev/null +++ b/packages/graphics/Mesa/patches/Mesa-motion_adaptive_deinterlacer-v8.patch @@ -0,0 +1,828 @@ +From 08155442aba570a9d2d351795c86fdea466d806d Mon Sep 17 00:00:00 2001 +From: Grigori Goronzy +Date: Sat, 2 Nov 2013 21:54:01 +0100 +Subject: [PATCH] WIP: st/vl, st/vdpau: motion adaptive deinterlacer + +v2: make it actually work +v3: fix motion detection, simplify +v4: use correct (field) semantics for past/future, + use 4-frame motion detection +v5: cleanup, move dest surface handling into filter +v6: implement skip_chroma +v7: tweak motion detection, further cleanup +v8: fix tgsi code, unbreaks with llvm +--- + src/gallium/auxiliary/Makefile.sources | 3 +- + src/gallium/auxiliary/vl/vl_deint_filter.c | 494 +++++++++++++++++++++++ + src/gallium/auxiliary/vl/vl_deint_filter.h | 78 ++++ + src/gallium/state_trackers/vdpau/mixer.c | 69 +++- + src/gallium/state_trackers/vdpau/query.c | 1 + + src/gallium/state_trackers/vdpau/vdpau_private.h | 7 + + 6 files changed, 647 insertions(+), 5 deletions(-) + create mode 100644 src/gallium/auxiliary/vl/vl_deint_filter.c + create mode 100644 src/gallium/auxiliary/vl/vl_deint_filter.h + +diff --git a/src/gallium/auxiliary/Makefile.sources b/src/gallium/auxiliary/Makefile.sources +index c89cbdd..19004e0 100644 +--- a/src/gallium/auxiliary/Makefile.sources ++++ b/src/gallium/auxiliary/Makefile.sources +@@ -155,7 +155,8 @@ C_SOURCES := \ + vl/vl_idct.c \ + vl/vl_mc.c \ + vl/vl_vertex_buffers.c \ +- vl/vl_video_buffer.c ++ vl/vl_video_buffer.c \ ++ vl/vl_deint_filter.c + + GENERATED_SOURCES := \ + indices/u_indices_gen.c \ +diff --git a/src/gallium/auxiliary/vl/vl_deint_filter.c b/src/gallium/auxiliary/vl/vl_deint_filter.c +new file mode 100644 +index 0000000..3b3cc6d +--- /dev/null ++++ b/src/gallium/auxiliary/vl/vl_deint_filter.c +@@ -0,0 +1,494 @@ ++/************************************************************************** ++ * ++ * Copyright 2013 Grigori Goronzy . ++ * 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. ++ * ++ **************************************************************************/ ++ ++/* ++ * References: ++ * ++ * Lin, S. F., Chang, Y. L., & Chen, L. G. (2003). ++ * Motion adaptive interpolation with horizontal motion detection for deinterlacing. ++ * Consumer Electronics, IEEE Transactions on, 49(4), 1256-1265. ++ * ++ * Pei-Yin, C. H. E. N., & Yao-Hsien, L. A. I. (2007). ++ * A low-complexity interpolation method for deinterlacing. ++ * IEICE transactions on information and systems, 90(2), 606-608. ++ * ++ */ ++ ++#include ++ ++#include "pipe/p_context.h" ++ ++#include "tgsi/tgsi_ureg.h" ++ ++#include "util/u_draw.h" ++#include "util/u_memory.h" ++#include "util/u_math.h" ++ ++#include "vl_types.h" ++#include "vl_video_buffer.h" ++#include "vl_vertex_buffers.h" ++#include "vl_deint_filter.h" ++ ++enum VS_OUTPUT ++{ ++ VS_O_VPOS = 0, ++ VS_O_VTEX = 0 ++}; ++ ++static void * ++create_vert_shader(struct vl_deint_filter *filter) ++{ ++ struct ureg_program *shader; ++ struct ureg_src i_vpos; ++ struct ureg_dst o_vpos, o_vtex; ++ ++ shader = ureg_create(TGSI_PROCESSOR_VERTEX); ++ if (!shader) ++ return NULL; ++ ++ i_vpos = ureg_DECL_vs_input(shader, 0); ++ o_vpos = ureg_DECL_output(shader, TGSI_SEMANTIC_POSITION, VS_O_VPOS); ++ o_vtex = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_VTEX); ++ ++ ureg_MOV(shader, o_vpos, i_vpos); ++ ureg_MOV(shader, o_vtex, i_vpos); ++ ++ ureg_END(shader); ++ ++ return ureg_create_shader_and_destroy(shader, filter->pipe); ++} ++ ++static void * ++create_copy_frag_shader(struct vl_deint_filter *filter, unsigned field) ++{ ++ struct ureg_program *shader; ++ struct ureg_src i_vtex; ++ struct ureg_src sampler; ++ struct ureg_dst o_fragment; ++ struct ureg_dst t_tex; ++ ++ shader = ureg_create(TGSI_PROCESSOR_FRAGMENT); ++ if (!shader) { ++ return NULL; ++ } ++ t_tex = ureg_DECL_temporary(shader); ++ ++ i_vtex = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_VTEX, TGSI_INTERPOLATE_LINEAR); ++ sampler = ureg_DECL_sampler(shader, 2); ++ o_fragment = ureg_DECL_output(shader, TGSI_SEMANTIC_COLOR, 0); ++ ++ ureg_MOV(shader, t_tex, i_vtex); ++ if (field) { ++ ureg_MOV(shader, ureg_writemask(t_tex, TGSI_WRITEMASK_ZW), ++ ureg_imm4f(shader, 0, 0, 1.0f, 0)); ++ } else { ++ ureg_MOV(shader, ureg_writemask(t_tex, TGSI_WRITEMASK_ZW), ++ ureg_imm1f(shader, 0)); ++ } ++ ++ ureg_TEX(shader, o_fragment, TGSI_TEXTURE_2D_ARRAY, ureg_src(t_tex), sampler); ++ ++ ureg_release_temporary(shader, t_tex); ++ ureg_END(shader); ++ ++ return ureg_create_shader_and_destroy(shader, filter->pipe); ++} ++ ++static void * ++create_deint_frag_shader(struct vl_deint_filter *filter, unsigned field, ++ struct vertex2f *sizes, bool spatial_filter) ++{ ++ struct ureg_program *shader; ++ struct ureg_src i_vtex; ++ struct ureg_src sampler_cur; ++ struct ureg_src sampler_prevprev; ++ struct ureg_src sampler_prev; ++ struct ureg_src sampler_next; ++ struct ureg_dst o_fragment; ++ struct ureg_dst t_tex; ++ struct ureg_dst t_comp_top, t_comp_bot; ++ struct ureg_dst t_diff; ++ struct ureg_dst t_a, t_b; ++ struct ureg_dst t_weave, t_linear; ++ ++ shader = ureg_create(TGSI_PROCESSOR_FRAGMENT); ++ if (!shader) { ++ return NULL; ++ } ++ ++ t_tex = ureg_DECL_temporary(shader); ++ t_comp_top = ureg_DECL_temporary(shader); ++ t_comp_bot = ureg_DECL_temporary(shader); ++ t_diff = ureg_DECL_temporary(shader); ++ t_a = ureg_DECL_temporary(shader); ++ t_b = ureg_DECL_temporary(shader); ++ t_weave = ureg_DECL_temporary(shader); ++ t_linear = ureg_DECL_temporary(shader); ++ ++ i_vtex = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_VTEX, TGSI_INTERPOLATE_LINEAR); ++ sampler_prevprev = ureg_DECL_sampler(shader, 0); ++ sampler_prev = ureg_DECL_sampler(shader, 1); ++ sampler_cur = ureg_DECL_sampler(shader, 2); ++ sampler_next = ureg_DECL_sampler(shader, 3); ++ o_fragment = ureg_DECL_output(shader, TGSI_SEMANTIC_COLOR, 0); ++ ++ // we don't care about ZW interpolation (allows better optimization) ++ ureg_MOV(shader, t_tex, i_vtex); ++ ureg_MOV(shader, ureg_writemask(t_tex, TGSI_WRITEMASK_ZW), ++ ureg_imm1f(shader, 0)); ++ ++ // sample between texels for cheap lowpass ++ ureg_ADD(shader, t_comp_top, ureg_src(t_tex), ++ ureg_imm4f(shader, sizes->x * 0.5f, sizes->y * -0.5f, 0, 0)); ++ ureg_ADD(shader, t_comp_bot, ureg_src(t_tex), ++ ureg_imm4f(shader, sizes->x * -0.5f, sizes->y * 0.5f, 1.0f, 0)); ++ ++ if (field == 0) { ++ /* interpolating top field -> current field is a bottom field */ ++ // cur vs prev2 ++ ureg_TEX(shader, t_a, TGSI_TEXTURE_2D_ARRAY, ureg_src(t_comp_bot), sampler_cur); ++ ureg_TEX(shader, t_b, TGSI_TEXTURE_2D_ARRAY, ureg_src(t_comp_bot), sampler_prevprev); ++ ureg_SUB(shader, ureg_writemask(t_diff, TGSI_WRITEMASK_X), ureg_src(t_a), ureg_src(t_b)); ++ // prev vs next ++ ureg_TEX(shader, t_a, TGSI_TEXTURE_2D_ARRAY, ureg_src(t_comp_top), sampler_prev); ++ ureg_TEX(shader, t_b, TGSI_TEXTURE_2D_ARRAY, ureg_src(t_comp_top), sampler_next); ++ ureg_SUB(shader, ureg_writemask(t_diff, TGSI_WRITEMASK_Y), ureg_src(t_a), ureg_src(t_b)); ++ } else { ++ /* interpolating bottom field -> current field is a top field */ ++ // cur vs prev2 ++ ureg_TEX(shader, t_a, TGSI_TEXTURE_2D_ARRAY, ureg_src(t_comp_top), sampler_cur); ++ ureg_TEX(shader, t_b, TGSI_TEXTURE_2D_ARRAY, ureg_src(t_comp_top), sampler_prevprev); ++ ureg_SUB(shader, ureg_writemask(t_diff, TGSI_WRITEMASK_X), ureg_src(t_a), ureg_src(t_b)); ++ // prev vs next ++ ureg_TEX(shader, t_a, TGSI_TEXTURE_2D_ARRAY, ureg_src(t_comp_bot), sampler_prev); ++ ureg_TEX(shader, t_b, TGSI_TEXTURE_2D_ARRAY, ureg_src(t_comp_bot), sampler_next); ++ ureg_SUB(shader, ureg_writemask(t_diff, TGSI_WRITEMASK_Y), ureg_src(t_a), ureg_src(t_b)); ++ } ++ ++ // absolute maximum of differences ++ ureg_MAX(shader, ureg_writemask(t_diff, TGSI_WRITEMASK_X), ureg_abs(ureg_src(t_diff)), ++ ureg_scalar(ureg_abs(ureg_src(t_diff)), TGSI_SWIZZLE_Y)); ++ ++ if (field == 0) { ++ /* weave with prev top field */ ++ ureg_TEX(shader, t_weave, TGSI_TEXTURE_2D_ARRAY, ureg_src(t_tex), sampler_prev); ++ /* get linear interpolation from current bottom field */ ++ ureg_ADD(shader, t_comp_top, ureg_src(t_tex), ureg_imm4f(shader, 0, sizes->y * -1.0f, 1.0f, 0)); ++ ureg_TEX(shader, t_linear, TGSI_TEXTURE_2D_ARRAY, ureg_src(t_comp_top), sampler_cur); ++ } else { ++ /* weave with prev bottom field */ ++ ureg_ADD(shader, t_comp_bot, ureg_src(t_tex), ureg_imm4f(shader, 0, 0, 1.0f, 0)); ++ ureg_TEX(shader, t_weave, TGSI_TEXTURE_2D_ARRAY, ureg_src(t_comp_bot), sampler_prev); ++ /* get linear interpolation from current top field */ ++ ureg_ADD(shader, t_comp_bot, ureg_src(t_tex), ureg_imm4f(shader, 0, sizes->y * 1.0f, 0, 0)); ++ ureg_TEX(shader, t_linear, TGSI_TEXTURE_2D_ARRAY, ureg_src(t_comp_bot), sampler_cur); ++ } ++ ++ // mix between weave and linear ++ // fully weave if diff < 6 (0.02353), fully interpolate if diff > 14 (0.05490) ++ ureg_ADD(shader, ureg_writemask(t_diff, TGSI_WRITEMASK_X), ureg_src(t_diff), ++ ureg_imm4f(shader, -0.02353f, 0, 0, 0)); ++ ureg_MUL(shader, ureg_saturate(ureg_writemask(t_diff, TGSI_WRITEMASK_X)), ++ ureg_src(t_diff), ureg_imm4f(shader, 31.8750f, 0, 0, 0)); ++ ureg_LRP(shader, ureg_writemask(o_fragment, TGSI_WRITEMASK_X), ureg_src(t_diff), ++ ureg_src(t_linear), ureg_src(t_weave)); ++ ++ ureg_release_temporary(shader, t_tex); ++ ureg_release_temporary(shader, t_comp_top); ++ ureg_release_temporary(shader, t_comp_bot); ++ ureg_release_temporary(shader, t_diff); ++ ureg_release_temporary(shader, t_a); ++ ureg_release_temporary(shader, t_b); ++ ureg_release_temporary(shader, t_weave); ++ ureg_release_temporary(shader, t_linear); ++ ureg_END(shader); ++ ++ return ureg_create_shader_and_destroy(shader, filter->pipe); ++} ++ ++bool ++vl_deint_filter_init(struct vl_deint_filter *filter, struct pipe_context *pipe, ++ unsigned video_width, unsigned video_height, ++ bool skip_chroma, bool spatial_filter) ++{ ++ struct pipe_rasterizer_state rs_state; ++ struct pipe_blend_state blend; ++ struct pipe_sampler_state sampler; ++ struct pipe_vertex_element ve; ++ struct vertex2f sizes; ++ struct pipe_video_buffer templ; ++ ++ assert(filter && pipe); ++ assert(video_width && video_height); ++ ++ memset(filter, 0, sizeof(*filter)); ++ filter->pipe = pipe; ++ filter->skip_chroma = skip_chroma; ++ filter->video_width = video_width; ++ filter->video_height = video_height; ++ ++ /* TODO: handle other than 4:2:0 subsampling */ ++ memset(&templ, 0, sizeof(templ)); ++ templ.buffer_format = PIPE_FORMAT_YV12; ++ templ.chroma_format = PIPE_VIDEO_CHROMA_FORMAT_420; ++ templ.width = video_width; ++ templ.height = video_height; ++ templ.interlaced = true; ++ filter->video_buffer = vl_video_buffer_create(pipe, &templ); ++ if (!filter->video_buffer) ++ goto error_video_buffer; ++ ++ memset(&rs_state, 0, sizeof(rs_state)); ++ rs_state.half_pixel_center = true; ++ rs_state.bottom_edge_rule = true; ++ rs_state.depth_clip = 1; ++ filter->rs_state = pipe->create_rasterizer_state(pipe, &rs_state); ++ if (!filter->rs_state) ++ goto error_rs_state; ++ ++ memset(&blend, 0, sizeof blend); ++ blend.rt[0].colormask = PIPE_MASK_RGBA; ++ filter->blend = pipe->create_blend_state(pipe, &blend); ++ if (!filter->blend) ++ goto error_blend; ++ ++ memset(&sampler, 0, sizeof(sampler)); ++ sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE; ++ sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE; ++ sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE; ++ sampler.min_img_filter = PIPE_TEX_FILTER_LINEAR; ++ sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE; ++ sampler.mag_img_filter = PIPE_TEX_FILTER_LINEAR; ++ sampler.normalized_coords = 1; ++ filter->sampler[0] = pipe->create_sampler_state(pipe, &sampler); ++ filter->sampler[1] = filter->sampler[2] = filter->sampler[3] = filter->sampler[0]; ++ if (!filter->sampler[0]) ++ goto error_sampler; ++ ++ filter->quad = vl_vb_upload_quads(pipe); ++ if(!filter->quad.buffer) ++ goto error_quad; ++ ++ memset(&ve, 0, sizeof(ve)); ++ ve.src_offset = 0; ++ ve.instance_divisor = 0; ++ ve.vertex_buffer_index = 0; ++ ve.src_format = PIPE_FORMAT_R32G32_FLOAT; ++ filter->ves = pipe->create_vertex_elements_state(pipe, 1, &ve); ++ if (!filter->ves) ++ goto error_ves; ++ ++ sizes.x = 1.0f / video_width; ++ sizes.y = 1.0f / video_height; ++ ++ filter->vs = create_vert_shader(filter); ++ if (!filter->vs) ++ goto error_vs; ++ ++ filter->fs_copy_top = create_copy_frag_shader(filter, 0); ++ if (!filter->fs_copy_top) ++ goto error_fs_copy_top; ++ ++ filter->fs_copy_bottom = create_copy_frag_shader(filter, 1); ++ if (!filter->fs_copy_bottom) ++ goto error_fs_copy_bottom; ++ ++ filter->fs_deint_top = create_deint_frag_shader(filter, 0, &sizes, spatial_filter); ++ if (!filter->fs_deint_top) ++ goto error_fs_deint_top; ++ ++ filter->fs_deint_bottom = create_deint_frag_shader(filter, 1, &sizes, spatial_filter); ++ if (!filter->fs_deint_bottom) ++ goto error_fs_deint_bottom; ++ ++ return true; ++ ++error_fs_deint_bottom: ++ pipe->delete_fs_state(pipe, filter->fs_deint_top); ++ ++error_fs_deint_top: ++ pipe->delete_fs_state(pipe, filter->fs_copy_bottom); ++ ++error_fs_copy_bottom: ++ pipe->delete_fs_state(pipe, filter->fs_copy_top); ++ ++error_fs_copy_top: ++ pipe->delete_vs_state(pipe, filter->vs); ++ ++error_vs: ++ pipe->delete_vertex_elements_state(pipe, filter->ves); ++ ++error_ves: ++ pipe_resource_reference(&filter->quad.buffer, NULL); ++ ++error_quad: ++ pipe->delete_sampler_state(pipe, filter->sampler); ++ ++error_sampler: ++ pipe->delete_blend_state(pipe, filter->blend); ++ ++error_blend: ++ pipe->delete_rasterizer_state(pipe, filter->rs_state); ++ ++error_rs_state: ++ filter->video_buffer->destroy(filter->video_buffer); ++ ++error_video_buffer: ++ return false; ++} ++ ++void ++vl_deint_filter_cleanup(struct vl_deint_filter *filter) ++{ ++ assert(filter); ++ ++ filter->pipe->delete_sampler_state(filter->pipe, filter->sampler[0]); ++ filter->pipe->delete_blend_state(filter->pipe, filter->blend); ++ filter->pipe->delete_rasterizer_state(filter->pipe, filter->rs_state); ++ filter->pipe->delete_vertex_elements_state(filter->pipe, filter->ves); ++ pipe_resource_reference(&filter->quad.buffer, NULL); ++ ++ filter->pipe->delete_vs_state(filter->pipe, filter->vs); ++ filter->pipe->delete_fs_state(filter->pipe, filter->fs_copy_top); ++ filter->pipe->delete_fs_state(filter->pipe, filter->fs_copy_bottom); ++ filter->pipe->delete_fs_state(filter->pipe, filter->fs_deint_top); ++ filter->pipe->delete_fs_state(filter->pipe, filter->fs_deint_bottom); ++ ++ filter->video_buffer->destroy(filter->video_buffer); ++} ++ ++bool ++vl_deint_filter_check_buffers(struct vl_deint_filter *filter, ++ struct pipe_video_buffer *prevprev, ++ struct pipe_video_buffer *prev, ++ struct pipe_video_buffer *cur, ++ struct pipe_video_buffer *next) ++{ ++ int i; ++ struct pipe_video_buffer *bufs[] = { prevprev, prev, cur, next }; ++ ++ for (i = 0; i < 4; i++) { ++ if (bufs[i]->chroma_format != PIPE_VIDEO_CHROMA_FORMAT_420) ++ return false; ++ if (bufs[i]->width < filter->video_width || ++ bufs[i]->height < filter->video_height) ++ return false; ++ if (!bufs[i]->interlaced) ++ return false; ++ } ++ ++ return true; ++} ++ ++void ++vl_deint_filter_render(struct vl_deint_filter *filter, ++ struct pipe_video_buffer *prevprev, ++ struct pipe_video_buffer *prev, ++ struct pipe_video_buffer *cur, ++ struct pipe_video_buffer *next, ++ unsigned field) ++{ ++ struct pipe_viewport_state viewport; ++ struct pipe_framebuffer_state fb_state; ++ struct pipe_sampler_view **cur_sv; ++ struct pipe_sampler_view **prevprev_sv; ++ struct pipe_sampler_view **prev_sv; ++ struct pipe_sampler_view **next_sv; ++ struct pipe_sampler_view *sampler_views[4]; ++ struct pipe_surface **dst_surfaces; ++ int j; ++ ++ assert(filter && prevprev && prev && cur && next && field <= 1); ++ ++ /* set up destination and source */ ++ dst_surfaces = filter->video_buffer->get_surfaces(filter->video_buffer); ++ cur_sv = cur->get_sampler_view_components(cur); ++ prevprev_sv = prevprev->get_sampler_view_components(prevprev); ++ prev_sv = prev->get_sampler_view_components(prev); ++ next_sv = next->get_sampler_view_components(next); ++ ++ /* set up pipe state */ ++ filter->pipe->bind_rasterizer_state(filter->pipe, filter->rs_state); ++ filter->pipe->bind_blend_state(filter->pipe, filter->blend); ++ filter->pipe->set_vertex_buffers(filter->pipe, 0, 1, &filter->quad); ++ filter->pipe->bind_vertex_elements_state(filter->pipe, filter->ves); ++ filter->pipe->bind_vs_state(filter->pipe, filter->vs); ++ filter->pipe->bind_sampler_states(filter->pipe, PIPE_SHADER_FRAGMENT, ++ 0, 4, filter->sampler); ++ ++ /* prepare viewport */ ++ memset(&viewport, 0, sizeof(viewport)); ++ viewport.scale[2] = 1; ++ viewport.scale[3] = 1; ++ ++ /* prepare framebuffer */ ++ memset(&fb_state, 0, sizeof(fb_state)); ++ fb_state.nr_cbufs = 1; ++ ++ /* process each plane separately */ ++ for (j = 0; j < 3; j++) { ++ /* select correct YV12 surfaces */ ++ int k = j == 1 ? 2 : ++ j == 2 ? 1 : 0; ++ struct pipe_surface *blit_surf = dst_surfaces[2 * k + field]; ++ struct pipe_surface *dst_surf = dst_surfaces[2 * k + 1 - field]; ++ ++ /* update render target state */ ++ viewport.scale[0] = blit_surf->texture->width0; ++ viewport.scale[1] = blit_surf->texture->height0; ++ fb_state.width = blit_surf->texture->width0; ++ fb_state.height = blit_surf->texture->height0; ++ ++ /* update sampler view sources */ ++ sampler_views[0] = prevprev_sv[j]; ++ sampler_views[1] = prev_sv[j]; ++ sampler_views[2] = cur_sv[j]; ++ sampler_views[3] = next_sv[j]; ++ filter->pipe->set_sampler_views(filter->pipe, PIPE_SHADER_FRAGMENT, 0, 4, sampler_views); ++ ++ /* blit current field */ ++ fb_state.cbufs[0] = blit_surf; ++ filter->pipe->bind_fs_state(filter->pipe, field ? filter->fs_copy_bottom : filter->fs_copy_top); ++ filter->pipe->set_framebuffer_state(filter->pipe, &fb_state); ++ filter->pipe->set_viewport_states(filter->pipe, 0, 1, &viewport); ++ util_draw_arrays(filter->pipe, PIPE_PRIM_QUADS, 0, 4); ++ ++ fb_state.cbufs[0] = dst_surf; ++ if (j > 0 && filter->skip_chroma) { ++ /* blit other field */ ++ filter->pipe->set_framebuffer_state(filter->pipe, &fb_state); ++ util_draw_arrays(filter->pipe, PIPE_PRIM_QUADS, 0, 4); ++ } else { ++ /* interpolate other field */ ++ filter->pipe->bind_fs_state(filter->pipe, field ? filter->fs_deint_top : filter->fs_deint_bottom); ++ filter->pipe->set_framebuffer_state(filter->pipe, &fb_state); ++ util_draw_arrays(filter->pipe, PIPE_PRIM_QUADS, 0, 4); ++ } ++ ++ } ++} ++ +diff --git a/src/gallium/auxiliary/vl/vl_deint_filter.h b/src/gallium/auxiliary/vl/vl_deint_filter.h +new file mode 100644 +index 0000000..5a21402 +--- /dev/null ++++ b/src/gallium/auxiliary/vl/vl_deint_filter.h +@@ -0,0 +1,78 @@ ++/************************************************************************** ++ * ++ * Copyright 2013 Grigori Goronzy ++ * 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. ++ * ++ **************************************************************************/ ++ ++/* motion adaptive deinterlacer implementation */ ++ ++#ifndef vl_deint_filter_h ++#define vl_deint_filter_h ++ ++#include "pipe/p_state.h" ++ ++struct vl_deint_filter ++{ ++ struct pipe_context *pipe; ++ struct pipe_vertex_buffer quad; ++ ++ void *rs_state; ++ void *blend; ++ void *sampler[4]; ++ void *ves; ++ void *vs; ++ void *fs_copy_top, *fs_copy_bottom; ++ void *fs_deint_top, *fs_deint_bottom; ++ ++ unsigned video_width, video_height; ++ bool skip_chroma; ++ ++ struct pipe_video_buffer *video_buffer; ++}; ++ ++bool ++vl_deint_filter_init(struct vl_deint_filter *filter, struct pipe_context *pipe, ++ unsigned video_width, unsigned video_height, ++ bool skip_chroma, bool spatial_filter); ++ ++void ++vl_deint_filter_cleanup(struct vl_deint_filter *filter); ++ ++bool ++vl_deint_filter_check_buffers(struct vl_deint_filter *filter, ++ struct pipe_video_buffer *prevprev, ++ struct pipe_video_buffer *prev, ++ struct pipe_video_buffer *cur, ++ struct pipe_video_buffer *next); ++ ++void ++vl_deint_filter_render(struct vl_deint_filter *filter, ++ struct pipe_video_buffer *prevprev, ++ struct pipe_video_buffer *prev, ++ struct pipe_video_buffer *cur, ++ struct pipe_video_buffer *next, ++ unsigned field); ++ ++#endif /* vl_deint_filter_h */ ++ +diff --git a/src/gallium/state_trackers/vdpau/mixer.c b/src/gallium/state_trackers/vdpau/mixer.c +index f9b413e..74351c6 100644 +--- a/src/gallium/state_trackers/vdpau/mixer.c ++++ b/src/gallium/state_trackers/vdpau/mixer.c +@@ -80,7 +80,6 @@ + for (i = 0; i < feature_count; ++i) { + switch (features[i]) { + /* they are valid, but we doesn't support them */ +- case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL: + case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL: + case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1: + case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L2: +@@ -95,6 +94,10 @@ + case VDP_VIDEO_MIXER_FEATURE_LUMA_KEY: + break; + ++ case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL: ++ vmixer->deint.supported = true; ++ break; ++ + case VDP_VIDEO_MIXER_FEATURE_SHARPNESS: + vmixer->sharpness.supported = true; + break; +@@ -181,6 +184,11 @@ + + vl_compositor_cleanup_state(&vmixer->cstate); + ++ if (vmixer->deint.filter) { ++ vl_deint_filter_cleanup(vmixer->deint.filter); ++ FREE(vmixer->deint.filter); ++ } ++ + if (vmixer->noise_reduction.filter) { + vl_median_filter_cleanup(vmixer->noise_reduction.filter); + FREE(vmixer->noise_reduction.filter); +@@ -219,6 +227,7 @@ VdpStatus vlVdpVideoMixerRender(VdpVideoMixer mixer, + enum vl_compositor_deinterlace deinterlace; + struct u_rect rect, clip, *prect; + unsigned i, layer = 0; ++ struct pipe_video_buffer *video_buffer; + + vlVdpVideoMixer *vmixer; + vlVdpSurface *surf; +@@ -233,6 +242,7 @@ VdpStatus vlVdpVideoMixerRender(VdpVideoMixer mixer, + compositor = &vmixer->device->compositor; + + surf = vlGetDataHTAB(video_surface_current); ++ video_buffer = surf->video_buffer; + if (!surf) + return VDP_STATUS_INVALID_HANDLE; + +@@ -283,6 +293,24 @@ VdpStatus vlVdpVideoMixerRender(VdpVideoMixer mixer, + pipe_mutex_unlock(vmixer->device->mutex); + return VDP_STATUS_INVALID_VIDEO_MIXER_PICTURE_STRUCTURE; + }; ++ ++ if (deinterlace != VL_COMPOSITOR_WEAVE && vmixer->deint.enabled && ++ video_surface_past_count > 1 && video_surface_future_count > 0) { ++ vlVdpSurface *prevprev = vlGetDataHTAB(video_surface_past[1]); ++ vlVdpSurface *prev = vlGetDataHTAB(video_surface_past[0]); ++ vlVdpSurface *next = vlGetDataHTAB(video_surface_future[0]); ++ if (prevprev && prev && next && ++ vl_deint_filter_check_buffers(vmixer->deint.filter, ++ prevprev->video_buffer, prev->video_buffer, surf->video_buffer, next->video_buffer)) { ++ vl_deint_filter_render(vmixer->deint.filter, prevprev->video_buffer, ++ prev->video_buffer, surf->video_buffer, ++ next->video_buffer, ++ deinterlace == VL_COMPOSITOR_BOB_BOTTOM); ++ deinterlace = VL_COMPOSITOR_WEAVE; ++ video_buffer = vmixer->deint.filter->video_buffer; ++ } ++ } ++ + prect = RectToPipe(video_source_rect, &rect); + if (!prect) { + rect.x0 = 0; +@@ -291,7 +319,7 @@ VdpStatus vlVdpVideoMixerRender(VdpVideoMixer mixer, + rect.y1 = surf->templat.height; + prect = ▭ + } +- vl_compositor_set_buffer_layer(&vmixer->cstate, compositor, layer, surf->video_buffer, prect, NULL, deinterlace); ++ vl_compositor_set_buffer_layer(&vmixer->cstate, compositor, layer, video_buffer, prect, NULL, deinterlace); + vl_compositor_set_layer_dst_area(&vmixer->cstate, layer++, RectToPipe(destination_video_rect, &rect)); + + for (i = 0; i < layer_count; ++i) { +@@ -332,6 +360,31 @@ VdpStatus vlVdpVideoMixerRender(VdpVideoMixer mixer, + return VDP_STATUS_OK; + } + ++static void ++vlVdpVideoMixerUpdateDeinterlaceFilter(vlVdpVideoMixer *vmixer) ++{ ++ struct pipe_context *pipe = vmixer->device->context; ++ assert(vmixer); ++ ++ /* remove existing filter */ ++ if (vmixer->deint.filter) { ++ vl_deint_filter_cleanup(vmixer->deint.filter); ++ FREE(vmixer->deint.filter); ++ vmixer->deint.filter = NULL; ++ } ++ ++ /* create a new filter if requested */ ++ if (vmixer->deint.enabled && vmixer->chroma_format == PIPE_VIDEO_CHROMA_FORMAT_420) { ++ vmixer->deint.filter = MALLOC(sizeof(struct vl_deint_filter)); ++ vmixer->deint.enabled = vl_deint_filter_init(vmixer->deint.filter, pipe, ++ vmixer->video_width, vmixer->video_height, ++ vmixer->skip_chroma_deint, vmixer->deint.spatial); ++ if (!vmixer->deint.enabled) { ++ FREE(vmixer->deint.filter); ++ } ++ } ++} ++ + /** + * Update the noise reduction setting + */ +@@ -424,7 +477,6 @@ VdpStatus vlVdpVideoMixerRender(VdpVideoMixer mixer, + for (i = 0; i < feature_count; ++i) { + switch (features[i]) { + /* they are valid, but we doesn't support them */ +- case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL: + case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL: + case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1: + case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L2: +@@ -440,6 +492,10 @@ VdpStatus vlVdpVideoMixerRender(VdpVideoMixer mixer, + feature_supports[i] = false; + break; + ++ case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL: ++ feature_supports[i] = vmixer->deint.supported; ++ break; ++ + case VDP_VIDEO_MIXER_FEATURE_SHARPNESS: + feature_supports[i] = vmixer->sharpness.supported; + break; +@@ -479,7 +535,6 @@ VdpStatus vlVdpVideoMixerRender(VdpVideoMixer mixer, + for (i = 0; i < feature_count; ++i) { + switch (features[i]) { + /* they are valid, but we doesn't support them */ +- case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL: + case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL: + case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1: + case VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L2: +@@ -494,6 +549,11 @@ VdpStatus vlVdpVideoMixerRender(VdpVideoMixer mixer, + case VDP_VIDEO_MIXER_FEATURE_LUMA_KEY: + break; + ++ case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL: ++ vmixer->deint.enabled = feature_enables[i]; ++ vlVdpVideoMixerUpdateDeinterlaceFilter(vmixer); ++ break; ++ + case VDP_VIDEO_MIXER_FEATURE_SHARPNESS: + vmixer->sharpness.enabled = feature_enables[i]; + vlVdpVideoMixerUpdateSharpnessFilter(vmixer); +@@ -648,6 +708,7 @@ VdpStatus vlVdpVideoMixerRender(VdpVideoMixer mixer, + if (*(uint8_t*)attribute_values[i] > 1) + return VDP_STATUS_INVALID_VALUE; + vmixer->skip_chroma_deint = *(uint8_t*)attribute_values[i]; ++ vlVdpVideoMixerUpdateDeinterlaceFilter(vmixer); + break; + default: + pipe_mutex_unlock(vmixer->device->mutex); +diff --git a/src/gallium/state_trackers/vdpau/query.c b/src/gallium/state_trackers/vdpau/query.c +index 1d35252..aba65ee 100644 +--- a/src/gallium/state_trackers/vdpau/query.c ++++ b/src/gallium/state_trackers/vdpau/query.c +@@ -469,6 +469,7 @@ + switch (feature) { + case VDP_VIDEO_MIXER_FEATURE_SHARPNESS: + case VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION: ++ case VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL: + *is_supported = VDP_TRUE; + break; + default: +diff --git a/src/gallium/state_trackers/vdpau/vdpau_private.h b/src/gallium/state_trackers/vdpau/vdpau_private.h +index 60196ac..0811df6 100644 +--- a/src/gallium/state_trackers/vdpau/vdpau_private.h ++++ b/src/gallium/state_trackers/vdpau/vdpau_private.h +@@ -42,8 +42,10 @@ + #include "util/u_rect.h" + #include "os/os_thread.h" + ++#include "vl/vl_video_buffer.h" + #include "vl/vl_compositor.h" + #include "vl/vl_csc.h" ++#include "vl/vl_deint_filter.h" + #include "vl/vl_matrix_filter.h" + #include "vl/vl_median_filter.h" + #include "vl/vl_winsys.h" +@@ -351,6 +353,11 @@ + struct vl_compositor_state cstate; + + struct { ++ bool supported, enabled, spatial; ++ struct vl_deint_filter *filter; ++ } deint; ++ ++ struct { + bool supported, enabled; + unsigned level; + struct vl_median_filter *filter; +-- +1.8.4 +