That's most likely an issue with st/vdpau. I implemented a small hack to clear the black bars of a surface only once. No idea how exactly it happens, but Grigoris patch seems to somehow break the logic there.

Anyway we need to rework this part when getting DRI3 anyway (much more efficiently and cleanly), so I'm not sure if we should bother fixing it.

Christian.

Am 15.02.2014 07:17, schrieb Ilia Mirkin:
Grigori,

I just tried this out on a few interlaced videos I have, and it works
really quite well! One thing I did notice is that when playing back
content with mplayer (and -vo vdpau:deint=3) in full screen mode, the
black bars are now stale/uninitialized textures. This does not happen
if I don't use deint=3. Is it something that we're doing wrong in
nouveau, or is it an issue in st/vdpau? If it's likely an issue in
nouveau, any hints on what it might be?

   -ilia

On Fri, Feb 14, 2014 at 3:18 AM, Christian König
<deathsim...@vodafone.de> wrote:
A really nice piece of work, thx allot.

Both patches reviewed and pushed upstream.

Cheers,
Christian.

Am 13.02.2014 21:32, schrieb Grigori Goronzy:

---
   src/gallium/auxiliary/Makefile.sources     |   3 +-
   src/gallium/auxiliary/vl/vl_deint_filter.c | 491
+++++++++++++++++++++++++++++
   src/gallium/auxiliary/vl/vl_deint_filter.h |  78 +++++
   3 files changed, 571 insertions(+), 1 deletion(-)
   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..9b05154
--- /dev/null
+++ b/src/gallium/auxiliary/vl/vl_deint_filter.c
@@ -0,0 +1,491 @@

+/**************************************************************************
+ *
+ * Copyright 2013 Grigori Goronzy <g...@chown.ath.cx>.
+ * 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 <stdio.h>
+
+#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);
+
+      /* blit or interpolate other field */
+      fb_state.cbufs[0] = dst_surf;
+      filter->pipe->set_framebuffer_state(filter->pipe, &fb_state);
+      if (j > 0 && filter->skip_chroma) {
+         util_draw_arrays(filter->pipe, PIPE_PRIM_QUADS, 0, 4);
+      } else {
+         filter->pipe->bind_fs_state(filter->pipe, field ?
filter->fs_deint_top : filter->fs_deint_bottom);
+         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 <g...@chown.ath.cx>
+ * 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 */
+

_______________________________________________
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/mesa-dev

_______________________________________________
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/mesa-dev

Reply via email to