From b11f543c4e424be9c0adfecd4a8d6b0cc631150e Mon Sep 17 00:00:00 2001 From: "Eric R. Smith" Date: Sat, 14 Jun 2025 21:54:17 +0000 Subject: [PATCH] mesa: Add R16G16_R16B16_UNORM and related formats Including the 10 bit variant X6R10X6G10_X6R10X6B10_UNORM. Only the RG_RB variants seem to have fourccs, so those are the only ones being added for now, although they would, obviously, be easy to add). These are used for Y210, Y212, and Y216 fourccs. In particular Y210 is interesting for panfrost, as it is the fourcc used to indicate a 10 bit single plane 4:2:2 encoded as AFBC (similar to how YUYV is the canonical AFBC for 10 bit 4:2:0). Reviewed-by: Boris Brezillon Part-of: --- src/gallium/frontends/dri/dri2.c | 27 ++++++++++++++++ src/mesa/main/formats.csv | 3 ++ src/mesa/main/formats.h | 2 ++ src/mesa/state_tracker/st_atom_sampler.c | 4 ++- src/mesa/state_tracker/st_atom_texture.c | 5 +++ src/mesa/state_tracker/st_cb_eglimage.c | 41 ++++++++++++++++++++---- src/mesa/state_tracker/st_program.h | 18 ++++++++--- src/mesa/state_tracker/st_sampler_view.c | 10 +++++- src/util/format/u_format.yaml | 13 ++++++++ src/util/format/u_format_table.py | 2 ++ 10 files changed, 112 insertions(+), 13 deletions(-) diff --git a/src/gallium/frontends/dri/dri2.c b/src/gallium/frontends/dri/dri2.c index e4304bd72af..ff1658af41e 100644 --- a/src/gallium/frontends/dri/dri2.c +++ b/src/gallium/frontends/dri/dri2.c @@ -562,6 +562,21 @@ static const struct dri2_format_mapping g8r8_b8r8_mapping = { { 0, 1, 0, __DRI_IMAGE_FORMAT_ABGR8888 } } }; +static const struct dri2_format_mapping r16g16_r16b16_mapping = { + DRM_FORMAT_Y216, + __DRI_IMAGE_FORMAT_NONE, + PIPE_FORMAT_R16G16_R16B16_422_UNORM, 2, + { { 0, 0, 0, __DRI_IMAGE_FORMAT_GR1616 }, + { 0, 1, 0, __DRI_IMAGE_FORMAT_ABGR16161616 } } +}; +static const struct dri2_format_mapping r10g10_r10b10_mapping = { + DRM_FORMAT_Y210, + __DRI_IMAGE_FORMAT_NONE, + PIPE_FORMAT_X6R10X6G10_X6R10X6B10_422_UNORM, 2, + { { 0, 0, 0, __DRI_IMAGE_FORMAT_GR1616 }, + { 0, 1, 0, __DRI_IMAGE_FORMAT_ABGR16161616 } } +}; + static const struct dri2_format_mapping r10_g10b10_mapping = { DRM_FORMAT_NV15, __DRI_IMAGE_FORMAT_NONE, @@ -768,6 +783,18 @@ dri_create_image_from_winsys(struct dri_screen *screen, map = &b8r8_g8r8_mapping; tex_usage |= PIPE_BIND_SAMPLER_VIEW; } + if (!tex_usage && map->pipe_format == PIPE_FORMAT_Y210 && + pscreen->is_format_supported(pscreen, PIPE_FORMAT_X6R10X6G10_X6R10X6B10_422_UNORM, + screen->target, 0, 0, PIPE_BIND_SAMPLER_VIEW)) { + map = &r10g10_r10b10_mapping; + tex_usage |= PIPE_BIND_SAMPLER_VIEW; + } + if (!tex_usage && map->pipe_format == PIPE_FORMAT_Y216 && + pscreen->is_format_supported(pscreen, PIPE_FORMAT_R16G16_R16B16_422_UNORM, + screen->target, 0, 0, PIPE_BIND_SAMPLER_VIEW)) { + map = &r16g16_r16b16_mapping; + tex_usage |= PIPE_BIND_SAMPLER_VIEW; + } if (!tex_usage && util_format_is_yuv(map->pipe_format)) { /* YUV format sampling can be emulated by the GL gallium frontend by diff --git a/src/mesa/main/formats.csv b/src/mesa/main/formats.csv index f046d3859f6..d78a08508d8 100644 --- a/src/mesa/main/formats.csv +++ b/src/mesa/main/formats.csv @@ -99,6 +99,9 @@ MESA_FORMAT_RB_RG_UNORM8 , other , 2, 1, 1, x16 , , , MESA_FORMAT_GR_BR_UNORM8 , other , 2, 1, 1, x16 , , , , xyz1, rgb MESA_FORMAT_BR_GR_UNORM8 , other , 2, 1, 1, x16 , , , , xyz1, rgb +MESA_FORMAT_RG_RB_UNORM10 , other , 2, 1, 1, x32 , , , , xyz1, rgb +MESA_FORMAT_RG_RB_UNORM16 , other , 2, 1, 1, x32 , , , , xyz1, rgb + # Array normalized formats MESA_FORMAT_A_UNORM8 , array , 1, 1, 1, un8 , , , , 000x, rgb MESA_FORMAT_A_UNORM16 , array , 1, 1, 1, un16, , , , 000x, rgb diff --git a/src/mesa/main/formats.h b/src/mesa/main/formats.h index 67a0d67e029..a295c584412 100644 --- a/src/mesa/main/formats.h +++ b/src/mesa/main/formats.h @@ -391,6 +391,8 @@ typedef enum pipe_format mesa_format; #define MESA_FORMAT_RB_RG_UNORM8 PIPE_FORMAT_R8B8_R8G8_UNORM #define MESA_FORMAT_GR_BR_UNORM8 PIPE_FORMAT_G8R8_B8R8_UNORM #define MESA_FORMAT_BR_GR_UNORM8 PIPE_FORMAT_B8R8_G8R8_UNORM +#define MESA_FORMAT_RG_RB_UNORM10 PIPE_FORMAT_X6R10X6G10_X6R10X6B10_422_UNORM +#define MESA_FORMAT_RG_RB_UNORM16 PIPE_FORMAT_R16G16_R16B16_422_UNORM #define MESA_FORMAT_A_UNORM8 PIPE_FORMAT_A8_UNORM #define MESA_FORMAT_A_UNORM16 PIPE_FORMAT_A16_UNORM #define MESA_FORMAT_L_UNORM8 PIPE_FORMAT_L8_UNORM diff --git a/src/mesa/state_tracker/st_atom_sampler.c b/src/mesa/state_tracker/st_atom_sampler.c index 8b30c72aa83..a123be3703f 100644 --- a/src/mesa/state_tracker/st_atom_sampler.c +++ b/src/mesa/state_tracker/st_atom_sampler.c @@ -305,7 +305,9 @@ update_shader_samplers(struct st_context *st, if (stObj->pt->format == PIPE_FORMAT_R8G8_R8B8_UNORM || stObj->pt->format == PIPE_FORMAT_R8B8_R8G8_UNORM || stObj->pt->format == PIPE_FORMAT_B8R8_G8R8_UNORM || - stObj->pt->format == PIPE_FORMAT_G8R8_B8R8_UNORM) { + stObj->pt->format == PIPE_FORMAT_G8R8_B8R8_UNORM || + stObj->pt->format == PIPE_FORMAT_R16G16_R16B16_422_UNORM || + stObj->pt->format == PIPE_FORMAT_X6R10X6G10_X6R10X6B10_422_UNORM) { /* no additional views needed */ break; } diff --git a/src/mesa/state_tracker/st_atom_texture.c b/src/mesa/state_tracker/st_atom_texture.c index 60b347ead39..d721603d84d 100644 --- a/src/mesa/state_tracker/st_atom_texture.c +++ b/src/mesa/state_tracker/st_atom_texture.c @@ -310,6 +310,11 @@ st_get_sampler_views(struct st_context *st, case PIPE_FORMAT_Y210: case PIPE_FORMAT_Y212: case PIPE_FORMAT_Y216: + if (stObj->pt->format == PIPE_FORMAT_R16G16_R16B16_422_UNORM || + stObj->pt->format == PIPE_FORMAT_X6R10X6G10_X6R10X6B10_422_UNORM) + /* no additional views needed */ + break; + /* we need one additional R16G16B16A16 view: */ tmpl.format = PIPE_FORMAT_R16G16B16A16_UNORM; tmpl.swizzle_b = PIPE_SWIZZLE_Z; diff --git a/src/mesa/state_tracker/st_cb_eglimage.c b/src/mesa/state_tracker/st_cb_eglimage.c index 9feae1f3609..183ce65502b 100644 --- a/src/mesa/state_tracker/st_cb_eglimage.c +++ b/src/mesa/state_tracker/st_cb_eglimage.c @@ -107,14 +107,30 @@ is_format_supported(struct pipe_screen *screen, enum pipe_format format, nr_storage_samples, usage); break; case PIPE_FORMAT_Y210: - case PIPE_FORMAT_Y212: - case PIPE_FORMAT_Y216: - supported = screen->is_format_supported(screen, PIPE_FORMAT_R16G16_UNORM, + /* in principle this could be emulated by R16G16_R16B16_UNORM, but in + * practice we won't pick that format for Y210, only the 10 bit variant + */ + supported = screen->is_format_supported(screen, PIPE_FORMAT_X6R10X6G10_X6R10X6B10_422_UNORM, + PIPE_TEXTURE_2D, nr_samples, + nr_storage_samples, usage) || + (screen->is_format_supported(screen, PIPE_FORMAT_R16G16_UNORM, PIPE_TEXTURE_2D, nr_samples, nr_storage_samples, usage) && screen->is_format_supported(screen, PIPE_FORMAT_R16G16B16A16_UNORM, PIPE_TEXTURE_2D, nr_samples, - nr_storage_samples, usage); + nr_storage_samples, usage)); + break; + case PIPE_FORMAT_Y212: + case PIPE_FORMAT_Y216: + supported = screen->is_format_supported(screen, PIPE_FORMAT_R16G16_R16B16_422_UNORM, + PIPE_TEXTURE_2D, nr_samples, + nr_storage_samples, usage) || + (screen->is_format_supported(screen, PIPE_FORMAT_R16G16_UNORM, + PIPE_TEXTURE_2D, nr_samples, + nr_storage_samples, usage) && + screen->is_format_supported(screen, PIPE_FORMAT_R16G16B16A16_UNORM, + PIPE_TEXTURE_2D, nr_samples, + nr_storage_samples, usage)); break; case PIPE_FORMAT_Y410: supported = screen->is_format_supported(screen, PIPE_FORMAT_R10G10B10A2_UNORM, @@ -526,10 +542,23 @@ st_bind_egl_image(struct gl_context *ctx, texObj->RequiredTextureImageUnits = 2; break; case PIPE_FORMAT_Y210: + if (stimg->texture->format == PIPE_FORMAT_X6R10X6G10_X6R10X6B10_422_UNORM) { + texFormat = MESA_FORMAT_RG_RB_UNORM10; + texObj->RequiredTextureImageUnits = 1; + } else { + texFormat = MESA_FORMAT_RG_UNORM16; + texObj->RequiredTextureImageUnits = 2; + } + break; case PIPE_FORMAT_Y212: case PIPE_FORMAT_Y216: - texFormat = MESA_FORMAT_RG_UNORM16; - texObj->RequiredTextureImageUnits = 2; + if (stimg->texture->format == PIPE_FORMAT_R16G16_R16B16_422_UNORM) { + texFormat = MESA_FORMAT_RG_RB_UNORM16; + texObj->RequiredTextureImageUnits = 1; + } else { + texFormat = MESA_FORMAT_RG_UNORM16; + texObj->RequiredTextureImageUnits = 2; + } break; case PIPE_FORMAT_Y410: texFormat = MESA_FORMAT_B10G10R10A2_UNORM; diff --git a/src/mesa/state_tracker/st_program.h b/src/mesa/state_tracker/st_program.h index 6aba1d742b7..18c64bbf59e 100644 --- a/src/mesa/state_tracker/st_program.h +++ b/src/mesa/state_tracker/st_program.h @@ -166,15 +166,23 @@ st_get_external_sampler_key(struct st_context *st, struct gl_program *prog) key.lower_iyuv |= (1 << unit); break; case PIPE_FORMAT_YUYV: - if (stObj->pt->format == PIPE_FORMAT_R8G8_R8B8_UNORM) { + if (stObj->pt->format == PIPE_FORMAT_R8G8_R8B8_UNORM) key.lower_yu_yv |= (1 << unit); - break; - } - FALLTHROUGH; + else + key.lower_yx_xuxv |= (1 << unit); + break; case PIPE_FORMAT_Y210: + if (stObj->pt->format == PIPE_FORMAT_X6R10X6G10_X6R10X6B10_422_UNORM) + key.lower_yu_yv |= (1 << unit); + else + key.lower_yx_xuxv |= (1 << unit); + break; case PIPE_FORMAT_Y212: case PIPE_FORMAT_Y216: - key.lower_yx_xuxv |= (1 << unit); + if (stObj->pt->format == PIPE_FORMAT_R16G16_R16B16_422_UNORM) + key.lower_yu_yv |= (1 << unit); + else + key.lower_yx_xuxv |= (1 << unit); break; case PIPE_FORMAT_UYVY: if (stObj->pt->format == PIPE_FORMAT_G8R8_B8R8_UNORM) { diff --git a/src/mesa/state_tracker/st_sampler_view.c b/src/mesa/state_tracker/st_sampler_view.c index 8b7ac8352bc..3ff380d7a77 100644 --- a/src/mesa/state_tracker/st_sampler_view.c +++ b/src/mesa/state_tracker/st_sampler_view.c @@ -423,9 +423,17 @@ st_get_sampler_view_format(const struct st_context *st, format = PIPE_FORMAT_R16_UNORM; break; case PIPE_FORMAT_Y210: + if (texObj->pt->format == PIPE_FORMAT_X6R10X6G10_X6R10X6B10_422_UNORM) + format = texObj->pt->format; + else + format = PIPE_FORMAT_R16G16_UNORM; + break; case PIPE_FORMAT_Y212: case PIPE_FORMAT_Y216: - format = PIPE_FORMAT_R16G16_UNORM; + if (texObj->pt->format == PIPE_FORMAT_R16G16_R16B16_422_UNORM) + format = texObj->pt->format; + else + format = PIPE_FORMAT_R16G16_UNORM; break; case PIPE_FORMAT_Y410: format = PIPE_FORMAT_R10G10B10A2_UNORM; diff --git a/src/util/format/u_format.yaml b/src/util/format/u_format.yaml index b1012095f00..de6bcd6aed0 100644 --- a/src/util/format/u_format.yaml +++ b/src/util/format/u_format.yaml @@ -794,6 +794,19 @@ channels: [UN8, UN8, UN8, UN8] swizzles: [X, Y, Z, 1] +# 16 bit versions +- name: R16G16_R16B16_422_UNORM + layout: subsampled + colorspace: RGB + block: {width: 2, height: 1, depth: 1} + channels: [UN16, UN16, UN16, UN16] + swizzles: [X, Y, Z, 1] +- name: X6R10X6G10_X6R10X6B10_422_UNORM + layout: subsampled + colorspace: RGB + block: {width: 2, height: 1, depth: 1} + channels: [UN16, UN16, UN16, UN16] + swizzles: [X, Y, Z, 1] # some special formats not fitting anywhere else - name: R11G11B10_FLOAT diff --git a/src/util/format/u_format_table.py b/src/util/format/u_format_table.py index 9c864185f9d..db363e8a707 100644 --- a/src/util/format/u_format_table.py +++ b/src/util/format/u_format_table.py @@ -110,6 +110,8 @@ def has_access(format): 'g8r8_g8b8_422_unorm', 'g8b8_g8r8_422_unorm', 'b8g8_r8g8_422_unorm', + 'r16g16_r16b16_422_unorm', + 'x6r10x6g10_x6r10x6b10_422_unorm', 'x6g10_x6b10x6r10_420_unorm', 'x4g12_x4b12x4r12_420_unorm', 'y8_400_unorm',