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); }
