From a166d7609fb8448e8b5ece8f6fc0e9c437b2a398 Mon Sep 17 00:00:00 2001 From: Robert Mader Date: Wed, 12 Mar 2025 18:16:56 +0100 Subject: [PATCH] gles: Add support for 10/12/16 bit SW decoder YCbCr formats Signed-off-by: Robert Mader Co-Authored-by: Daniel Stone Reviewed-by: Eric R. Smith Reviewed-by: Boris Brezillon Part-of: --- src/compiler/nir/nir.h | 2 ++ src/compiler/nir/nir_lower_tex.c | 10 ++++++ src/egl/drivers/dri2/egl_dri2.c | 9 +++++ src/gallium/frontends/dri/dri_helpers.c | 46 ++++++++++++++++++++++++ src/mesa/state_tracker/st_atom_sampler.c | 15 ++++++++ src/mesa/state_tracker/st_atom_texture.c | 18 ++++++++++ src/mesa/state_tracker/st_cb_eglimage.c | 25 +++++++++++++ src/mesa/state_tracker/st_program.c | 2 ++ src/mesa/state_tracker/st_program.h | 19 ++++++++++ src/mesa/state_tracker/st_sampler_view.c | 9 +++++ 10 files changed, 155 insertions(+) diff --git a/src/compiler/nir/nir.h b/src/compiler/nir/nir.h index 6870a2822e7..9abd387c05a 100644 --- a/src/compiler/nir/nir.h +++ b/src/compiler/nir/nir.h @@ -5492,6 +5492,8 @@ typedef struct nir_lower_tex_options { unsigned lower_yu_yv_external; unsigned lower_yv_yu_external; unsigned lower_y41x_external; + unsigned lower_sx10_external; + unsigned lower_sx12_external; unsigned bt709_external; unsigned bt2020_external; unsigned yuv_full_range_external; diff --git a/src/compiler/nir/nir_lower_tex.c b/src/compiler/nir/nir_lower_tex.c index 40136e406d4..cce82c3b754 100644 --- a/src/compiler/nir/nir_lower_tex.c +++ b/src/compiler/nir/nir_lower_tex.c @@ -441,6 +441,16 @@ convert_yuv_to_rgb(nir_builder *b, nir_tex_instr *tex, nir_def *m1 = nir_f2fN(b, nir_build_imm(b, 4, 32, m->v[1]), bit_size); nir_def *m2 = nir_f2fN(b, nir_build_imm(b, 4, 32, m->v[2]), bit_size); + if (options->lower_sx10_external & (1u << texture_index)) { + m0 = nir_fmul_imm(b, m0, 64.0f); + m1 = nir_fmul_imm(b, m1, 64.0f); + m2 = nir_fmul_imm(b, m2, 64.0f); + } else if (options->lower_sx12_external & (1u << texture_index)) { + m0 = nir_fmul_imm(b, m0, 16.0f); + m1 = nir_fmul_imm(b, m1, 16.0f); + m2 = nir_fmul_imm(b, m2, 16.0f); + } + nir_def *result = nir_ffma(b, y, m0, nir_ffma(b, u, m1, nir_ffma(b, v, m2, offset))); diff --git a/src/egl/drivers/dri2/egl_dri2.c b/src/egl/drivers/dri2/egl_dri2.c index ccb5dc51f44..73d468b58b0 100644 --- a/src/egl/drivers/dri2/egl_dri2.c +++ b/src/egl/drivers/dri2/egl_dri2.c @@ -2315,6 +2315,15 @@ dri2_num_fourcc_format_planes(EGLint format) case DRM_FORMAT_YVU422: case DRM_FORMAT_YUV444: case DRM_FORMAT_YVU444: + case DRM_FORMAT_S010: + case DRM_FORMAT_S210: + case DRM_FORMAT_S410: + case DRM_FORMAT_S012: + case DRM_FORMAT_S212: + case DRM_FORMAT_S412: + case DRM_FORMAT_S016: + case DRM_FORMAT_S216: + case DRM_FORMAT_S416: return 3; default: diff --git a/src/gallium/frontends/dri/dri_helpers.c b/src/gallium/frontends/dri/dri_helpers.c index 7d477a0c5d4..0ff15c43628 100644 --- a/src/gallium/frontends/dri/dri_helpers.c +++ b/src/gallium/frontends/dri/dri_helpers.c @@ -547,6 +547,52 @@ static const struct dri2_format_mapping dri2_format_table[] = { { 2, 0, 0, __DRI_IMAGE_FORMAT_R8 }, { 1, 0, 0, __DRI_IMAGE_FORMAT_R8 } } }, + { DRM_FORMAT_S010, __DRI_IMAGE_FORMAT_NONE, + __DRI_IMAGE_COMPONENTS_Y_U_V, PIPE_FORMAT_Y10X6_U10X6_V10X6_420_UNORM, 3, + { { 0, 0, 0, __DRI_IMAGE_FORMAT_R16 }, + { 1, 1, 1, __DRI_IMAGE_FORMAT_R16 }, + { 2, 1, 1, __DRI_IMAGE_FORMAT_R16 } } }, + { DRM_FORMAT_S210, __DRI_IMAGE_FORMAT_NONE, + __DRI_IMAGE_COMPONENTS_Y_U_V, PIPE_FORMAT_Y10X6_U10X6_V10X6_422_UNORM, 3, + { { 0, 0, 0, __DRI_IMAGE_FORMAT_R16 }, + { 1, 1, 0, __DRI_IMAGE_FORMAT_R16 }, + { 2, 1, 0, __DRI_IMAGE_FORMAT_R16 } } }, + { DRM_FORMAT_S410, __DRI_IMAGE_FORMAT_NONE, + __DRI_IMAGE_COMPONENTS_Y_U_V, PIPE_FORMAT_Y10X6_U10X6_V10X6_444_UNORM, 3, + { { 0, 0, 0, __DRI_IMAGE_FORMAT_R16 }, + { 1, 0, 0, __DRI_IMAGE_FORMAT_R16 }, + { 2, 0, 0, __DRI_IMAGE_FORMAT_R16 } } }, + { DRM_FORMAT_S012, __DRI_IMAGE_FORMAT_NONE, + __DRI_IMAGE_COMPONENTS_Y_U_V, PIPE_FORMAT_Y12X4_U12X4_V12X4_420_UNORM, 3, + { { 0, 0, 0, __DRI_IMAGE_FORMAT_R16 }, + { 1, 1, 1, __DRI_IMAGE_FORMAT_R16 }, + { 2, 1, 1, __DRI_IMAGE_FORMAT_R16 } } }, + { DRM_FORMAT_S212, __DRI_IMAGE_FORMAT_NONE, + __DRI_IMAGE_COMPONENTS_Y_U_V, PIPE_FORMAT_Y12X4_U12X4_V12X4_422_UNORM, 3, + { { 0, 0, 0, __DRI_IMAGE_FORMAT_R16 }, + { 1, 1, 0, __DRI_IMAGE_FORMAT_R16 }, + { 2, 1, 0, __DRI_IMAGE_FORMAT_R16 } } }, + { DRM_FORMAT_S412, __DRI_IMAGE_FORMAT_NONE, + __DRI_IMAGE_COMPONENTS_Y_U_V, PIPE_FORMAT_Y12X4_U12X4_V12X4_444_UNORM, 3, + { { 0, 0, 0, __DRI_IMAGE_FORMAT_R16 }, + { 1, 0, 0, __DRI_IMAGE_FORMAT_R16 }, + { 2, 0, 0, __DRI_IMAGE_FORMAT_R16 } } }, + { DRM_FORMAT_S016, __DRI_IMAGE_FORMAT_NONE, + __DRI_IMAGE_COMPONENTS_Y_U_V, PIPE_FORMAT_Y16_U16_V16_420_UNORM, 3, + { { 0, 0, 0, __DRI_IMAGE_FORMAT_R16 }, + { 1, 1, 1, __DRI_IMAGE_FORMAT_R16 }, + { 2, 1, 1, __DRI_IMAGE_FORMAT_R16 } } }, + { DRM_FORMAT_S216, __DRI_IMAGE_FORMAT_NONE, + __DRI_IMAGE_COMPONENTS_Y_U_V, PIPE_FORMAT_Y16_U16_V16_422_UNORM, 3, + { { 0, 0, 0, __DRI_IMAGE_FORMAT_R16 }, + { 1, 1, 0, __DRI_IMAGE_FORMAT_R16 }, + { 2, 1, 0, __DRI_IMAGE_FORMAT_R16 } } }, + { DRM_FORMAT_S416, __DRI_IMAGE_FORMAT_NONE, + __DRI_IMAGE_COMPONENTS_Y_U_V, PIPE_FORMAT_Y16_U16_V16_444_UNORM, 3, + { { 0, 0, 0, __DRI_IMAGE_FORMAT_R16 }, + { 1, 0, 0, __DRI_IMAGE_FORMAT_R16 }, + { 2, 0, 0, __DRI_IMAGE_FORMAT_R16 } } }, + { DRM_FORMAT_NV12, __DRI_IMAGE_FORMAT_NONE, __DRI_IMAGE_COMPONENTS_Y_UV, PIPE_FORMAT_NV12, 2, { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8 }, diff --git a/src/mesa/state_tracker/st_atom_sampler.c b/src/mesa/state_tracker/st_atom_sampler.c index 67bdba5dc2e..5ac9962a5d0 100644 --- a/src/mesa/state_tracker/st_atom_sampler.c +++ b/src/mesa/state_tracker/st_atom_sampler.c @@ -323,6 +323,21 @@ update_shader_samplers(struct st_context *st, extra = u_bit_scan(&free_slots); states[extra] = sampler; break; + case PIPE_FORMAT_Y10X6_U10X6_V10X6_420_UNORM: + case PIPE_FORMAT_Y10X6_U10X6_V10X6_422_UNORM: + case PIPE_FORMAT_Y10X6_U10X6_V10X6_444_UNORM: + case PIPE_FORMAT_Y12X4_U12X4_V12X4_420_UNORM: + case PIPE_FORMAT_Y12X4_U12X4_V12X4_422_UNORM: + case PIPE_FORMAT_Y12X4_U12X4_V12X4_444_UNORM: + case PIPE_FORMAT_Y16_U16_V16_420_UNORM: + case PIPE_FORMAT_Y16_U16_V16_422_UNORM: + case PIPE_FORMAT_Y16_U16_V16_444_UNORM: + /* we need two additional samplers: */ + extra = u_bit_scan(&free_slots); + states[extra] = sampler; + extra = u_bit_scan(&free_slots); + states[extra] = sampler; + break; default: break; } diff --git a/src/mesa/state_tracker/st_atom_texture.c b/src/mesa/state_tracker/st_atom_texture.c index 93af78d5b41..1ca8b28687c 100644 --- a/src/mesa/state_tracker/st_atom_texture.c +++ b/src/mesa/state_tracker/st_atom_texture.c @@ -238,6 +238,24 @@ st_get_sampler_views(struct st_context *st, sampler_views[extra] = pipe->create_sampler_view(pipe, stObj->pt->next->next, &tmpl); break; + case PIPE_FORMAT_Y10X6_U10X6_V10X6_420_UNORM: + case PIPE_FORMAT_Y10X6_U10X6_V10X6_422_UNORM: + case PIPE_FORMAT_Y10X6_U10X6_V10X6_444_UNORM: + case PIPE_FORMAT_Y12X4_U12X4_V12X4_420_UNORM: + case PIPE_FORMAT_Y12X4_U12X4_V12X4_422_UNORM: + case PIPE_FORMAT_Y12X4_U12X4_V12X4_444_UNORM: + case PIPE_FORMAT_Y16_U16_V16_420_UNORM: + case PIPE_FORMAT_Y16_U16_V16_422_UNORM: + case PIPE_FORMAT_Y16_U16_V16_444_UNORM: + /* we need two additional R16 views: */ + tmpl.format = PIPE_FORMAT_R16_UNORM; + extra = u_bit_scan(&free_slots); + sampler_views[extra] = + pipe->create_sampler_view(pipe, stObj->pt->next, &tmpl); + extra = u_bit_scan(&free_slots); + sampler_views[extra] = + pipe->create_sampler_view(pipe, stObj->pt->next->next, &tmpl); + break; case PIPE_FORMAT_YUYV: case PIPE_FORMAT_YVYU: if (stObj->pt->format == PIPE_FORMAT_R8G8_R8B8_UNORM || diff --git a/src/mesa/state_tracker/st_cb_eglimage.c b/src/mesa/state_tracker/st_cb_eglimage.c index 15489c74f12..c2f10f5b4b0 100644 --- a/src/mesa/state_tracker/st_cb_eglimage.c +++ b/src/mesa/state_tracker/st_cb_eglimage.c @@ -83,6 +83,19 @@ is_format_supported(struct pipe_screen *screen, enum pipe_format format, PIPE_TEXTURE_2D, nr_samples, nr_storage_samples, usage); break; + case PIPE_FORMAT_Y10X6_U10X6_V10X6_420_UNORM: + case PIPE_FORMAT_Y10X6_U10X6_V10X6_422_UNORM: + case PIPE_FORMAT_Y10X6_U10X6_V10X6_444_UNORM: + case PIPE_FORMAT_Y12X4_U12X4_V12X4_420_UNORM: + case PIPE_FORMAT_Y12X4_U12X4_V12X4_422_UNORM: + case PIPE_FORMAT_Y12X4_U12X4_V12X4_444_UNORM: + case PIPE_FORMAT_Y16_U16_V16_420_UNORM: + case PIPE_FORMAT_Y16_U16_V16_422_UNORM: + case PIPE_FORMAT_Y16_U16_V16_444_UNORM: + supported = screen->is_format_supported(screen, PIPE_FORMAT_R16_UNORM, + PIPE_TEXTURE_2D, nr_samples, + nr_storage_samples, usage); + break; case PIPE_FORMAT_Y210: case PIPE_FORMAT_Y212: case PIPE_FORMAT_Y216: @@ -523,6 +536,18 @@ st_bind_egl_image(struct gl_context *ctx, texObj->RequiredTextureImageUnits = 3; } break; + case PIPE_FORMAT_Y10X6_U10X6_V10X6_420_UNORM: + case PIPE_FORMAT_Y10X6_U10X6_V10X6_422_UNORM: + case PIPE_FORMAT_Y10X6_U10X6_V10X6_444_UNORM: + case PIPE_FORMAT_Y12X4_U12X4_V12X4_420_UNORM: + case PIPE_FORMAT_Y12X4_U12X4_V12X4_422_UNORM: + case PIPE_FORMAT_Y12X4_U12X4_V12X4_444_UNORM: + case PIPE_FORMAT_Y16_U16_V16_420_UNORM: + case PIPE_FORMAT_Y16_U16_V16_422_UNORM: + case PIPE_FORMAT_Y16_U16_V16_444_UNORM: + texFormat = MESA_FORMAT_R_UNORM16; + texObj->RequiredTextureImageUnits = 3; + break; case PIPE_FORMAT_YUYV: case PIPE_FORMAT_YVYU: case PIPE_FORMAT_UYVY: diff --git a/src/mesa/state_tracker/st_program.c b/src/mesa/state_tracker/st_program.c index ab97902f489..e41511782d8 100644 --- a/src/mesa/state_tracker/st_program.c +++ b/src/mesa/state_tracker/st_program.c @@ -1180,6 +1180,8 @@ st_create_fp_variant(struct st_context *st, options.lower_yu_yv_external = key->external.lower_yu_yv; options.lower_yv_yu_external = key->external.lower_yv_yu; options.lower_y41x_external = key->external.lower_y41x; + options.lower_sx10_external = key->external.lower_sx10; + options.lower_sx12_external = key->external.lower_sx12; options.bt709_external = key->external.bt709; options.bt2020_external = key->external.bt2020; options.yuv_full_range_external = key->external.yuv_full_range; diff --git a/src/mesa/state_tracker/st_program.h b/src/mesa/state_tracker/st_program.h index 08e3b4b2177..ecf8f7c90a4 100644 --- a/src/mesa/state_tracker/st_program.h +++ b/src/mesa/state_tracker/st_program.h @@ -60,6 +60,8 @@ struct st_external_sampler_key GLuint lower_yu_yv; GLuint lower_yv_yu; GLuint lower_y41x; + GLuint lower_sx10; + GLuint lower_sx12; GLuint bt709; GLuint bt2020; GLuint yuv_full_range; @@ -142,6 +144,23 @@ st_get_external_sampler_key(struct st_context *st, struct gl_program *prog) } key.lower_iyuv |= (1 << unit); break; + case PIPE_FORMAT_Y10X6_U10X6_V10X6_420_UNORM: + case PIPE_FORMAT_Y10X6_U10X6_V10X6_422_UNORM: + case PIPE_FORMAT_Y10X6_U10X6_V10X6_444_UNORM: + key.lower_iyuv |= (1 << unit); + key.lower_sx10 |= (1 << unit); + break; + case PIPE_FORMAT_Y12X4_U12X4_V12X4_420_UNORM: + case PIPE_FORMAT_Y12X4_U12X4_V12X4_422_UNORM: + case PIPE_FORMAT_Y12X4_U12X4_V12X4_444_UNORM: + key.lower_iyuv |= (1 << unit); + key.lower_sx12 |= (1 << unit); + break; + case PIPE_FORMAT_Y16_U16_V16_420_UNORM: + case PIPE_FORMAT_Y16_U16_V16_422_UNORM: + case PIPE_FORMAT_Y16_U16_V16_444_UNORM: + key.lower_iyuv |= (1 << unit); + break; case PIPE_FORMAT_YUYV: if (stObj->pt->format == PIPE_FORMAT_R8G8_R8B8_UNORM) { key.lower_yu_yv |= (1 << unit); diff --git a/src/mesa/state_tracker/st_sampler_view.c b/src/mesa/state_tracker/st_sampler_view.c index 3765e530cf9..7dfd429cb29 100644 --- a/src/mesa/state_tracker/st_sampler_view.c +++ b/src/mesa/state_tracker/st_sampler_view.c @@ -407,6 +407,15 @@ st_get_sampler_view_format(const struct st_context *st, case PIPE_FORMAT_P012: case PIPE_FORMAT_P016: case PIPE_FORMAT_P030: + case PIPE_FORMAT_Y10X6_U10X6_V10X6_420_UNORM: + case PIPE_FORMAT_Y10X6_U10X6_V10X6_422_UNORM: + case PIPE_FORMAT_Y10X6_U10X6_V10X6_444_UNORM: + case PIPE_FORMAT_Y12X4_U12X4_V12X4_420_UNORM: + case PIPE_FORMAT_Y12X4_U12X4_V12X4_422_UNORM: + case PIPE_FORMAT_Y12X4_U12X4_V12X4_444_UNORM: + case PIPE_FORMAT_Y16_U16_V16_420_UNORM: + case PIPE_FORMAT_Y16_U16_V16_422_UNORM: + case PIPE_FORMAT_Y16_U16_V16_444_UNORM: format = PIPE_FORMAT_R16_UNORM; break; case PIPE_FORMAT_Y210: