Module: Mesa
Branch: main
Commit: eafeff6302f4eabed52d90aadd730c4492699ece
URL:    
http://cgit.freedesktop.org/mesa/mesa/commit/?id=eafeff6302f4eabed52d90aadd730c4492699ece

Author: David Rosca <[email protected]>
Date:   Mon Nov 13 12:00:24 2023 +0100

gallium/auxiliary/vl: Support interleaved input in deinterlace filter

This adds support for deinterlacing interleaved surfaces (both fields
interleaved together instead of as separate layers).

Reviewed-by: Leo Liu <[email protected]>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/26174>

---

 src/gallium/auxiliary/vl/vl_deint_filter.c | 30 +++++++++++++++++++++++-------
 src/gallium/auxiliary/vl/vl_deint_filter.h |  3 ++-
 src/gallium/frontends/va/postproc.c        |  5 +++--
 src/gallium/frontends/vdpau/mixer.c        |  2 +-
 4 files changed, 29 insertions(+), 11 deletions(-)

diff --git a/src/gallium/auxiliary/vl/vl_deint_filter.c 
b/src/gallium/auxiliary/vl/vl_deint_filter.c
index 2161141a618..9197c6ee924 100644
--- a/src/gallium/auxiliary/vl/vl_deint_filter.c
+++ b/src/gallium/auxiliary/vl/vl_deint_filter.c
@@ -84,7 +84,8 @@ create_vert_shader(struct vl_deint_filter *filter)
 }
 
 static void *
-create_copy_frag_shader(struct vl_deint_filter *filter, unsigned field)
+create_copy_frag_shader(struct vl_deint_filter *filter, unsigned field,
+                        struct vertex2f *sizes)
 {
    struct ureg_program *shader;
    struct ureg_src i_vtex;
@@ -104,9 +105,15 @@ create_copy_frag_shader(struct vl_deint_filter *filter, 
unsigned field)
 
    ureg_MOV(shader, t_tex, i_vtex);
    if (field) {
+      if (filter->interleaved)
+         ureg_ADD(shader, t_tex, ureg_src(t_tex),
+                  ureg_imm4f(shader, 0, sizes->y * 0.5f, 0, 0));
       ureg_MOV(shader, ureg_writemask(t_tex, TGSI_WRITEMASK_ZW),
                ureg_imm4f(shader, 0, 0, 1.0f, 0));
    } else {
+      if (filter->interleaved)
+         ureg_ADD(shader, t_tex, ureg_src(t_tex),
+                  ureg_imm4f(shader, 0, sizes->y * -0.5f, 0, 0));
       ureg_MOV(shader, ureg_writemask(t_tex, TGSI_WRITEMASK_ZW),
                ureg_imm1f(shader, 0));
    }
@@ -196,16 +203,24 @@ create_deint_frag_shader(struct vl_deint_filter *filter, 
unsigned field,
 
    if (field == 0) {
       /* weave with prev top field */
+      if (filter->interleaved)
+         ureg_ADD(shader, t_tex, ureg_src(t_tex),
+                  ureg_imm4f(shader, 0, sizes->y * -0.5f, 0, 0));
       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_ADD(shader, t_comp_top, ureg_src(t_tex),
+               ureg_imm4f(shader, 0, sizes->y * (filter->interleaved ? 1.0f : 
-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 */
+      if (filter->interleaved)
+         ureg_ADD(shader, t_tex, ureg_src(t_tex),
+                  ureg_imm4f(shader, 0, sizes->y * 0.5f, 0, 0));
       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_ADD(shader, t_comp_bot, ureg_src(t_tex),
+               ureg_imm4f(shader, 0, sizes->y * (filter->interleaved ? -1.0f : 
1.0f), 0, 0));
       ureg_TEX(shader, t_linear, TGSI_TEXTURE_2D_ARRAY, ureg_src(t_comp_bot), 
sampler_cur);
    }
 
@@ -235,7 +250,7 @@ create_deint_frag_shader(struct vl_deint_filter *filter, 
unsigned field,
 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)
+                     bool skip_chroma, bool spatial_filter, bool interleaved)
 {
    struct pipe_rasterizer_state rs_state;
    struct pipe_blend_state blend;
@@ -250,6 +265,7 @@ vl_deint_filter_init(struct vl_deint_filter *filter, struct 
pipe_context *pipe,
    memset(filter, 0, sizeof(*filter));
    filter->pipe = pipe;
    filter->skip_chroma = skip_chroma;
+   filter->interleaved = interleaved;
    filter->video_width = video_width;
    filter->video_height = video_height;
 
@@ -328,11 +344,11 @@ vl_deint_filter_init(struct vl_deint_filter *filter, 
struct pipe_context *pipe,
    if (!filter->vs)
       goto error_vs;
 
-   filter->fs_copy_top = create_copy_frag_shader(filter, 0);
+   filter->fs_copy_top = create_copy_frag_shader(filter, 0, &sizes);
    if (!filter->fs_copy_top)
       goto error_fs_copy_top;
 
-   filter->fs_copy_bottom = create_copy_frag_shader(filter, 1);
+   filter->fs_copy_bottom = create_copy_frag_shader(filter, 1, &sizes);
    if (!filter->fs_copy_bottom)
       goto error_fs_copy_bottom;
 
@@ -424,7 +440,7 @@ vl_deint_filter_check_buffers(struct vl_deint_filter 
*filter,
       if (bufs[i]->width < filter->video_width ||
           bufs[i]->height < filter->video_height)
          return false;
-      if (!bufs[i]->interlaced)
+      if (bufs[i]->interlaced != !filter->interleaved)
          return false;
    }
 
diff --git a/src/gallium/auxiliary/vl/vl_deint_filter.h 
b/src/gallium/auxiliary/vl/vl_deint_filter.h
index 49cc96c20b9..ee376bbeb65 100644
--- a/src/gallium/auxiliary/vl/vl_deint_filter.h
+++ b/src/gallium/auxiliary/vl/vl_deint_filter.h
@@ -47,6 +47,7 @@ struct vl_deint_filter
 
    unsigned video_width, video_height;
    bool skip_chroma;
+   bool interleaved;
 
    struct pipe_video_buffer *video_buffer;
 };
@@ -54,7 +55,7 @@ struct vl_deint_filter
 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);
+                     bool skip_chroma, bool spatial_filter, bool interleaved);
 
 void
 vl_deint_filter_cleanup(struct vl_deint_filter *filter);
diff --git a/src/gallium/frontends/va/postproc.c 
b/src/gallium/frontends/va/postproc.c
index 0f74019960d..3fdd2b99e7a 100644
--- a/src/gallium/frontends/va/postproc.c
+++ b/src/gallium/frontends/va/postproc.c
@@ -432,7 +432,8 @@ vlVaApplyDeint(vlVaDriver *drv, vlVaContext *context,
       return current;
 
    if (context->deint && (context->deint->video_width != current->width ||
-       context->deint->video_height != current->height)) {
+       context->deint->video_height != current->height ||
+       context->deint->interleaved != !current->interlaced)) {
       vl_deint_filter_cleanup(context->deint);
       FREE(context->deint);
       context->deint = NULL;
@@ -441,7 +442,7 @@ vlVaApplyDeint(vlVaDriver *drv, vlVaContext *context,
    if (!context->deint) {
       context->deint = MALLOC(sizeof(struct vl_deint_filter));
       if (!vl_deint_filter_init(context->deint, drv->pipe, current->width,
-                                current->height, false, false)) {
+                                current->height, false, false, 
!current->interlaced)) {
          FREE(context->deint);
          context->deint = NULL;
          return current;
diff --git a/src/gallium/frontends/vdpau/mixer.c 
b/src/gallium/frontends/vdpau/mixer.c
index 73680ca0049..40674bd2dfe 100644
--- a/src/gallium/frontends/vdpau/mixer.c
+++ b/src/gallium/frontends/vdpau/mixer.c
@@ -478,7 +478,7 @@ vlVdpVideoMixerUpdateDeinterlaceFilter(vlVdpVideoMixer 
*vmixer)
       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);
+            vmixer->skip_chroma_deint, vmixer->deint.spatial, false);
       if (!vmixer->deint.enabled) {
          FREE(vmixer->deint.filter);
       }

Reply via email to