From 5bc0df5aadae42904379f8bd351dd935c0a3bdce Mon Sep 17 00:00:00 2001 From: David Rosca Date: Fri, 5 Sep 2025 12:16:02 +0200 Subject: [PATCH] vl,frontends/va: Implement YUV->YUV matrix coeff conversion Use separate matrix for YUV->RGB and RGB->YUV conversions. Acked-by: Ruijing Dong Part-of: --- src/gallium/auxiliary/vl/vl_compositor.c | 2 +- src/gallium/auxiliary/vl/vl_compositor.h | 2 + src/gallium/auxiliary/vl/vl_compositor_cs.c | 59 +++++++++++++++------ src/gallium/frontends/va/postproc.c | 38 ++++++++++--- src/gallium/frontends/va/surface.c | 2 +- 5 files changed, 77 insertions(+), 26 deletions(-) diff --git a/src/gallium/auxiliary/vl/vl_compositor.c b/src/gallium/auxiliary/vl/vl_compositor.c index b6ca7fb0343..c501eacfee9 100644 --- a/src/gallium/auxiliary/vl/vl_compositor.c +++ b/src/gallium/auxiliary/vl/vl_compositor.c @@ -888,7 +888,7 @@ vl_compositor_init_state(struct vl_compositor_state *s, struct pipe_context *pip pipe->screen, PIPE_BIND_CONSTANT_BUFFER, PIPE_USAGE_DEFAULT, - sizeof(vl_csc_matrix) + 32 * sizeof(float) + 2 * sizeof(int) + sizeof(vl_csc_matrix) * 2 + 32 * sizeof(float) + 2 * sizeof(int) ); if (!s->shader_params) diff --git a/src/gallium/auxiliary/vl/vl_compositor.h b/src/gallium/auxiliary/vl/vl_compositor.h index 1708d7e0470..c056ad54b82 100644 --- a/src/gallium/auxiliary/vl/vl_compositor.h +++ b/src/gallium/auxiliary/vl/vl_compositor.h @@ -131,6 +131,8 @@ struct vl_compositor_state struct vl_compositor_layer layers[VL_COMPOSITOR_MAX_LAYERS]; bool interlaced; unsigned chroma_location; + vl_csc_matrix yuv2rgb; + vl_csc_matrix rgb2yuv; vl_csc_matrix csc_matrix; float luma_min, luma_max; diff --git a/src/gallium/auxiliary/vl/vl_compositor_cs.c b/src/gallium/auxiliary/vl/vl_compositor_cs.c index 2e822cd93c3..bf961a37e82 100644 --- a/src/gallium/auxiliary/vl/vl_compositor_cs.c +++ b/src/gallium/auxiliary/vl/vl_compositor_cs.c @@ -55,7 +55,7 @@ struct cs_shader { unsigned num_samplers; nir_variable *samplers[3]; nir_variable *image; - nir_def *params[11]; + nir_def *params[14]; nir_def *fone; nir_def *fzero; }; @@ -66,6 +66,11 @@ enum coords_flags { COORDS_CHROMA_OFFSET = 0x2, }; +enum color_conversion { + YUV2RGB, + RGB2YUV, +}; + static nir_def *cs_create_shader(struct vl_compositor *c, struct cs_shader *s) { /* @@ -77,7 +82,7 @@ static nir_def *cs_create_shader(struct vl_compositor *c, struct cs_shader *s) layout (std140, binding = 0) uniform ubo { - vec4 csc_mat[3]; // params[0-2] + vec4 yuv2rgb[3]; // params[0-2] float luma_min; // params[3].x float luma_max; // params[3].y vec2 chroma_offset; // params[3].zw @@ -88,6 +93,7 @@ static nir_def *cs_create_shader(struct vl_compositor *c, struct cs_shader *s) vec2 chroma_clamp; // params[6].zw vec4 proj[3]; // params[7-8] vec4 chroma_proj[3]; // params[9-10] + vec4 rgb2yuv[3]; // params[11-13] }; void main() @@ -246,13 +252,14 @@ static inline nir_def *cs_normalize(struct cs_shader *s, nir_def *src, unsigned return nir_fdiv(b, src, div); } -static inline nir_def *cs_color_space_conversion(struct cs_shader *s, nir_def *src, unsigned comp) +static inline nir_def *cs_color_space_conversion(struct cs_shader *s, nir_def *src, + unsigned comp, enum color_conversion conversion) { /* - return dot(src, params[comp]); + return dot(src, params[(conversion == RGB2YUV ? 11 : 0) + comp]); */ nir_builder *b = &s->b; - return nir_fdot4(b, src, s->params[comp]); + return nir_fdot4(b, src, s->params[(conversion == RGB2YUV ? 11 : 0) + comp]); } static inline nir_def *cs_fetch_texel(struct cs_shader *s, nir_def *coords, unsigned sampler) @@ -335,7 +342,7 @@ static void *create_video_buffer_shader(struct vl_compositor *c) nir_def *color = nir_vec4(b, col[0], col[1], col[2], s.fone); for (unsigned i = 0; i < 3; ++i) - col[i] = cs_color_space_conversion(&s, color, i); + col[i] = cs_color_space_conversion(&s, color, i, YUV2RGB); color = nir_vec4(b, col[0], col[1], col[2], alpha); cs_image_store(&s, cs_translate(&s, ipos), color); @@ -352,19 +359,36 @@ static void *create_yuv_progressive_shader(struct vl_compositor *c, enum vl_comp nir_builder *b = &s.b; nir_def *ipos = cs_create_shader(c, &s); - nir_def *pos = cs_tex_coords(&s, ipos, plane == VL_COMPOSITOR_PLANE_Y ? COORDS_LUMA : COORDS_CHROMA); + nir_def *pos_luma = cs_tex_coords(&s, ipos, COORDS_LUMA); + nir_def *pos_chroma = cs_tex_coords(&s, ipos, COORDS_CHROMA | + (plane == VL_COMPOSITOR_PLANE_Y ? COORDS_CHROMA_OFFSET : 0)); + + nir_def *col[3]; + for (unsigned i = 0; i < 3; i++) + col[i] = cs_fetch_texel(&s, i == 0 ? pos_luma : pos_chroma, i); + + nir_def *color = nir_vec4(b, col[0], col[1], col[2], s.fone); + + for (unsigned i = 0; i < 3; i++) + col[i] = cs_color_space_conversion(&s, color, i, YUV2RGB); + + color = nir_vec4(b, col[0], col[1], col[2], s.fone); + + for (unsigned i = 0; i < 3; i++) + col[i] = cs_color_space_conversion(&s, color, i, RGB2YUV); + + color = nir_vec4(b, col[0], col[1], col[2], s.fone); - nir_def *color; if (plane != VL_COMPOSITOR_PLANE_UV) { unsigned c = 0; if (plane == VL_COMPOSITOR_PLANE_U) c = 1; else if (plane == VL_COMPOSITOR_PLANE_V) c = 2; - color = nir_channel(b, cs_fetch_texel(&s, pos, c), c); + color = nir_channel(b, color, c); } else { - nir_def *col1 = cs_fetch_texel(&s, pos, 1); - nir_def *col2 = cs_fetch_texel(&s, pos, 2); + nir_def *col1 = nir_channel(b, color, 1); + nir_def *col2 = nir_channel(b, color, 2); color = nir_vec2(b, col1, col2); } @@ -439,10 +463,10 @@ static void *create_rgb_yuv_shader(struct vl_compositor *c, enum vl_compositor_p c = 1; else if (plane == VL_COMPOSITOR_PLANE_V) c = 2; - color = cs_color_space_conversion(&s, color, c); + color = cs_color_space_conversion(&s, color, c, RGB2YUV); } else { - nir_def *col1 = cs_color_space_conversion(&s, color, 1); - nir_def *col2 = cs_color_space_conversion(&s, color, 2); + nir_def *col1 = cs_color_space_conversion(&s, color, 1, RGB2YUV); + nir_def *col2 = cs_color_space_conversion(&s, color, 2, RGB2YUV); color = nir_vec2(b, col1, col2); } @@ -560,7 +584,7 @@ static nir_def *create_weave_shader(struct vl_compositor *c, bool rgb, bool y) if (rgb) { nir_def *alpha = cs_luma_key(&s, nir_channel(b, color, 2)); for (unsigned i = 0; i < 3; ++i) - col[i] = cs_color_space_conversion(&s, color, i); + col[i] = cs_color_space_conversion(&s, color, i, YUV2RGB); color = nir_vec4(b, col[0], col[1], col[2], alpha); } else if (y) { color = nir_channel(b, color, 0); @@ -774,7 +798,7 @@ set_viewport(struct vl_compositor_state *s, if (!ptr) return false; - memcpy(ptr, &s->csc_matrix, sizeof(vl_csc_matrix)); + memcpy(ptr, &s->yuv2rgb, sizeof(vl_csc_matrix)); float *ptr_float = (float *)ptr; ptr_float += sizeof(vl_csc_matrix) / sizeof(float); @@ -816,6 +840,9 @@ set_viewport(struct vl_compositor_state *s, memcpy(ptr_float, drawn->proj, sizeof(drawn->proj)); ptr_float += sizeof(drawn->proj) / sizeof(float); memcpy(ptr_float, drawn->chroma_proj, sizeof(drawn->chroma_proj)); + ptr_float += sizeof(drawn->chroma_proj) / sizeof(float); + + memcpy(ptr_float, &s->rgb2yuv, sizeof(vl_csc_matrix)); pipe_buffer_unmap(s->pipe, buf_transfer); diff --git a/src/gallium/frontends/va/postproc.c b/src/gallium/frontends/va/postproc.c index 1f9d572df6d..6f9d96bb2a1 100644 --- a/src/gallium/frontends/va/postproc.c +++ b/src/gallium/frontends/va/postproc.c @@ -58,7 +58,6 @@ vlVaPostProcCompositor(vlVaDriver *drv, struct pipe_vpp_desc *param) { struct pipe_surface *surfaces; - enum pipe_video_vpp_matrix_coefficients coeffs; enum vl_compositor_rotation rotation; enum vl_compositor_mirror mirror; bool src_yuv = util_format_is_yuv(src->buffer_format); @@ -75,14 +74,37 @@ vlVaPostProcCompositor(vlVaDriver *drv, if (!surfaces[0].texture) return VA_STATUS_ERROR_INVALID_SURFACE; - if (src_yuv == dst_yuv || util_format_get_nr_components(src->buffer_format) == 1) - coeffs = PIPE_VIDEO_VPP_MCF_RGB; /* identity */ - else - coeffs = src_yuv ? param->in_matrix_coefficients : param->out_matrix_coefficients; + if (util_format_get_nr_components(src->buffer_format) == 1) { + /* Identity */ + vl_csc_get_rgbyuv_matrix(PIPE_VIDEO_VPP_MCF_RGB, src->buffer_format, dst->buffer_format, + param->in_color_range, param->out_color_range, &drv->cstate.yuv2rgb); + vl_csc_get_rgbyuv_matrix(PIPE_VIDEO_VPP_MCF_RGB, src->buffer_format, dst->buffer_format, + param->in_color_range, param->out_color_range, &drv->cstate.rgb2yuv); + } else if (src_yuv == dst_yuv) { + if (!src_yuv) { + /* RGB to RGB */ + vl_csc_get_rgbyuv_matrix(PIPE_VIDEO_VPP_MCF_RGB, src->buffer_format, dst->buffer_format, + param->in_color_range, param->out_color_range, &drv->cstate.yuv2rgb); + } else { + /* YUV to YUV (convert to RGB for transfer function and primaries) */ + enum pipe_format rgb_format = PIPE_FORMAT_B8G8R8A8_UNORM; + vl_csc_get_rgbyuv_matrix(param->in_matrix_coefficients, src->buffer_format, rgb_format, + param->in_color_range, PIPE_VIDEO_VPP_CHROMA_COLOR_RANGE_FULL, + &drv->cstate.yuv2rgb); + vl_csc_get_rgbyuv_matrix(param->out_matrix_coefficients, rgb_format, dst->buffer_format, + PIPE_VIDEO_VPP_CHROMA_COLOR_RANGE_FULL, param->out_color_range, + &drv->cstate.rgb2yuv); + } + } else if (src_yuv) { + /* YUV to RGB */ + vl_csc_get_rgbyuv_matrix(param->in_matrix_coefficients, src->buffer_format, dst->buffer_format, + param->in_color_range, param->out_color_range, &drv->cstate.yuv2rgb); + } else { + /* RGB to YUV */ + vl_csc_get_rgbyuv_matrix(param->out_matrix_coefficients, src->buffer_format, dst->buffer_format, + param->in_color_range, param->out_color_range, &drv->cstate.rgb2yuv); + } - vl_csc_get_rgbyuv_matrix(coeffs, src->buffer_format, dst->buffer_format, - param->in_color_range, param->out_color_range, &drv->csc); - vl_compositor_set_csc_matrix(&drv->cstate, &drv->csc, 1.0f, 0.0f); if (src_yuv || dst_yuv) { enum pipe_format format = src_yuv ? src->buffer_format : dst->buffer_format; diff --git a/src/gallium/frontends/va/surface.c b/src/gallium/frontends/va/surface.c index 35f80b39141..4952cbc35b8 100644 --- a/src/gallium/frontends/va/surface.c +++ b/src/gallium/frontends/va/surface.c @@ -402,7 +402,7 @@ vlVaPutSurface(VADriverContextP ctx, VASurfaceID surface_id, void* draw, short s vl_csc_get_rgbyuv_matrix(coeffs, format, surf_templ.format, PIPE_VIDEO_VPP_CHROMA_COLOR_RANGE_REDUCED, - PIPE_VIDEO_VPP_CHROMA_COLOR_RANGE_FULL, &drv->cstate.csc_matrix); + PIPE_VIDEO_VPP_CHROMA_COLOR_RANGE_FULL, &drv->cstate.yuv2rgb); vl_compositor_clear_layers(&drv->cstate);