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 <leo.liu@amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/26174>
This commit is contained in:
David Rosca
2023-11-13 12:00:24 +01:00
committed by Marge Bot
parent 35b0ccd855
commit eafeff6302
4 changed files with 29 additions and 11 deletions

View File

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

View File

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

View File

@@ -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;

View File

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