From 60ebef430a5a40398f2b227b6374bc26bd10c042 Mon Sep 17 00:00:00 2001 From: Italo Nicola Date: Fri, 21 Jul 2023 00:27:48 +0000 Subject: [PATCH] gallium/st: add non-CSC lowering of I420 as PIPE_FORMAT_R8_G8_B8_420 This new format is similar to PIPE_FORMAT_G8_B8_R8_420, but with R as Y, G as U and B as V. The need for two diferent formats here is because gallium maps the YUV channels differently from vulkan. Some hardware, e.g. Mali GPUs, can sample from I420 but need CSC in shader, this patch implements that. Signed-off-by: Italo Nicola Reviewed-by: Daniel Stone Part-of: --- src/gallium/frontends/dri/dri2.c | 20 +++++++++++++++++ src/mesa/state_tracker/st_atom_sampler.c | 4 ++++ src/mesa/state_tracker/st_atom_texture.c | 4 ++++ src/mesa/state_tracker/st_cb_eglimage.c | 28 ++++++++++++++++++++++-- src/mesa/state_tracker/st_program.h | 4 ++++ src/mesa/state_tracker/st_sampler_view.c | 4 ++++ src/util/format/u_format.csv | 1 + src/util/format/u_format_table.py | 1 + src/util/format/u_formats.h | 1 + 9 files changed, 65 insertions(+), 2 deletions(-) diff --git a/src/gallium/frontends/dri/dri2.c b/src/gallium/frontends/dri/dri2.c index 242f9577cf7..2d7f3b3916f 100644 --- a/src/gallium/frontends/dri/dri2.c +++ b/src/gallium/frontends/dri/dri2.c @@ -858,6 +858,17 @@ dri2_update_tex_buffer(struct dri_drawable *drawable, /* no-op */ } +static const struct dri2_format_mapping r8_g8_b8_mapping = { + DRM_FORMAT_YUV420, + __DRI_IMAGE_FORMAT_NONE, + __DRI_IMAGE_COMPONENTS_Y_U_V, + PIPE_FORMAT_R8_G8_B8_420_UNORM, + 3, + { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8 }, + { 1, 1, 1, __DRI_IMAGE_FORMAT_R8 }, + { 2, 1, 1, __DRI_IMAGE_FORMAT_R8 } } +}; + static const struct dri2_format_mapping r8_g8b8_mapping = { DRM_FORMAT_NV12, __DRI_IMAGE_FORMAT_NONE, @@ -953,6 +964,15 @@ dri2_create_image_from_winsys(__DRIscreen *_screen, tex_usage |= PIPE_BIND_SAMPLER_VIEW; } + /* For I420, see if we have support for sampling r8_g8_b8 */ + if (!tex_usage && map->pipe_format == PIPE_FORMAT_IYUV && + map->dri_fourcc == DRM_FORMAT_YUV420 && + pscreen->is_format_supported(pscreen, PIPE_FORMAT_R8_G8_B8_420_UNORM, + screen->target, 0, 0, PIPE_BIND_SAMPLER_VIEW)) { + map = &r8_g8_b8_mapping; + tex_usage |= PIPE_BIND_SAMPLER_VIEW; + } + /* If the hardware supports R8G8_R8B8 style subsampled RGB formats, these * can be used for YUYV and UYVY formats. */ diff --git a/src/mesa/state_tracker/st_atom_sampler.c b/src/mesa/state_tracker/st_atom_sampler.c index 9f04aac98ee..4157a105c0d 100644 --- a/src/mesa/state_tracker/st_atom_sampler.c +++ b/src/mesa/state_tracker/st_atom_sampler.c @@ -298,6 +298,10 @@ update_shader_samplers(struct st_context *st, states[extra] = sampler; break; case PIPE_FORMAT_IYUV: + if (stObj->pt->format == PIPE_FORMAT_R8_G8_B8_420_UNORM) { + /* no additional views needed */ + break; + } /* we need two additional samplers: */ extra = u_bit_scan(&free_slots); states[extra] = sampler; diff --git a/src/mesa/state_tracker/st_atom_texture.c b/src/mesa/state_tracker/st_atom_texture.c index f816dbdaa40..ed3e0d8bc0e 100644 --- a/src/mesa/state_tracker/st_atom_texture.c +++ b/src/mesa/state_tracker/st_atom_texture.c @@ -210,6 +210,10 @@ st_get_sampler_views(struct st_context *st, pipe->create_sampler_view(pipe, stObj->pt->next, &tmpl); break; case PIPE_FORMAT_IYUV: + if (stObj->pt->format == PIPE_FORMAT_R8_G8_B8_420_UNORM) + /* no additional views needed */ + break; + /* we need two additional R8 views: */ tmpl.format = PIPE_FORMAT_R8_UNORM; extra = u_bit_scan(&free_slots); diff --git a/src/mesa/state_tracker/st_cb_eglimage.c b/src/mesa/state_tracker/st_cb_eglimage.c index 4b0a639c48a..6156d00f76e 100644 --- a/src/mesa/state_tracker/st_cb_eglimage.c +++ b/src/mesa/state_tracker/st_cb_eglimage.c @@ -194,6 +194,24 @@ is_nv12_as_r8_g8b8_supported(struct pipe_screen *screen, struct st_egl_image *ou return false; } +static bool +is_i420_as_r8_g8_b8_420_supported(struct pipe_screen *screen, + struct st_egl_image *out, + unsigned usage, bool *native_supported) +{ + if (out->format == PIPE_FORMAT_IYUV && + out->texture->format == PIPE_FORMAT_R8_G8_B8_420_UNORM && + screen->is_format_supported(screen, PIPE_FORMAT_R8_G8_B8_420_UNORM, + PIPE_TEXTURE_2D, + out->texture->nr_samples, + out->texture->nr_storage_samples, + usage)) { + *native_supported = false; + return true; + } + + return false; +} /** * Return the gallium texture of an EGLImage. @@ -218,6 +236,7 @@ st_get_egl_image(struct gl_context *ctx, GLeglImageOES image_handle, } if (!is_nv12_as_r8_g8b8_supported(screen, out, usage, native_supported) && + !is_i420_as_r8_g8_b8_420_supported(screen, out, usage, native_supported) && !is_format_supported(screen, out->format, out->texture->nr_samples, out->texture->nr_storage_samples, usage, native_supported)) { @@ -372,8 +391,13 @@ st_bind_egl_image(struct gl_context *ctx, texObj->RequiredTextureImageUnits = 1; break; case PIPE_FORMAT_IYUV: - texFormat = MESA_FORMAT_R_UNORM8; - texObj->RequiredTextureImageUnits = 3; + if (stimg->texture->format == PIPE_FORMAT_R8_G8_B8_420_UNORM) { + texFormat = MESA_FORMAT_R8G8B8X8_UNORM; + texObj->RequiredTextureImageUnits = 1; + } else { + texFormat = MESA_FORMAT_R_UNORM8; + texObj->RequiredTextureImageUnits = 3; + } break; case PIPE_FORMAT_YUYV: case PIPE_FORMAT_YVYU: diff --git a/src/mesa/state_tracker/st_program.h b/src/mesa/state_tracker/st_program.h index ea35fe5c87a..7a826f832fd 100644 --- a/src/mesa/state_tracker/st_program.h +++ b/src/mesa/state_tracker/st_program.h @@ -104,6 +104,10 @@ st_get_external_sampler_key(struct st_context *st, struct gl_program *prog) key.lower_nv21 |= (1 << unit); break; case PIPE_FORMAT_IYUV: + if (stObj->pt->format == PIPE_FORMAT_R8_G8_B8_420_UNORM) { + key.lower_yuv |= (1 << unit); + break; + } key.lower_iyuv |= (1 << unit); break; case PIPE_FORMAT_YUYV: diff --git a/src/mesa/state_tracker/st_sampler_view.c b/src/mesa/state_tracker/st_sampler_view.c index 59df3922c78..753b67733f2 100644 --- a/src/mesa/state_tracker/st_sampler_view.c +++ b/src/mesa/state_tracker/st_sampler_view.c @@ -393,6 +393,10 @@ st_get_sampler_view_format(const struct st_context *st, } FALLTHROUGH; case PIPE_FORMAT_IYUV: + if (texObj->pt->format == PIPE_FORMAT_R8_G8_B8_420_UNORM) { + format = PIPE_FORMAT_R8_G8_B8_420_UNORM; + break; + } format = PIPE_FORMAT_R8_UNORM; break; case PIPE_FORMAT_P010: diff --git a/src/util/format/u_format.csv b/src/util/format/u_format.csv index cbb39ba16a2..93517cec310 100644 --- a/src/util/format/u_format.csv +++ b/src/util/format/u_format.csv @@ -407,6 +407,7 @@ PIPE_FORMAT_Y8_400_UNORM , other , 1, 1, 1, un8, , , , x0 # multiplane textures but needs color-space conversion in the shader. PIPE_FORMAT_R8_G8B8_420_UNORM , planar2, 1, 1, 1, un8, , , , xyzw, rgb PIPE_FORMAT_G8_B8R8_420_UNORM , planar2, 1, 1, 1, un8, , , , xyzw, rgb +PIPE_FORMAT_R8_G8_B8_420_UNORM , planar3, 1, 1, 1, un8, , , , xyzw, rgb PIPE_FORMAT_G8_B8_R8_420_UNORM , planar3, 1, 1, 1, un8, , , , xyzw, rgb PIPE_FORMAT_R8_G8_B8_UNORM , planar3, 1, 1, 1, un8, , , , xyzw, rgb diff --git a/src/util/format/u_format_table.py b/src/util/format/u_format_table.py index 84d0e21ee95..8427760a2a4 100644 --- a/src/util/format/u_format_table.py +++ b/src/util/format/u_format_table.py @@ -114,6 +114,7 @@ def has_access(format): 'y16_u16_v16_444_unorm', 'r8_g8b8_420_unorm', 'g8_b8r8_420_unorm', + 'r8_g8_b8_420_unorm', 'g8_b8_r8_420_unorm', 'r8_g8_b8_unorm', 'y8_unorm', diff --git a/src/util/format/u_formats.h b/src/util/format/u_formats.h index 935e8bc2bbc..45af123b9ef 100644 --- a/src/util/format/u_formats.h +++ b/src/util/format/u_formats.h @@ -512,6 +512,7 @@ enum pipe_format { PIPE_FORMAT_R8_G8B8_420_UNORM, PIPE_FORMAT_G8_B8R8_420_UNORM, + PIPE_FORMAT_R8_G8_B8_420_UNORM, PIPE_FORMAT_G8_B8_R8_420_UNORM, PIPE_FORMAT_R8_G8_B8_UNORM, PIPE_FORMAT_Y8_UNORM,