gallium/st: add non-CSC lowering of I420 as PIPE_FORMAT_R8_G8_B8_420
authorItalo Nicola <italonicola@collabora.com>
Fri, 21 Jul 2023 00:27:48 +0000 (00:27 +0000)
committerMarge Bot <emma+marge@anholt.net>
Fri, 11 Aug 2023 18:43:38 +0000 (18:43 +0000)
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 <italonicola@collabora.com>
Reviewed-by: Daniel Stone <daniels@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/24266>

src/gallium/frontends/dri/dri2.c
src/mesa/state_tracker/st_atom_sampler.c
src/mesa/state_tracker/st_atom_texture.c
src/mesa/state_tracker/st_cb_eglimage.c
src/mesa/state_tracker/st_program.h
src/mesa/state_tracker/st_sampler_view.c
src/util/format/u_format.csv
src/util/format/u_format_table.py
src/util/format/u_formats.h

index 242f957..2d7f3b3 100644 (file)
@@ -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.
     */
index 9f04aac..4157a10 100644 (file)
@@ -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;
index f816dbd..ed3e0d8 100644 (file)
@@ -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);
index 4b0a639..6156d00 100644 (file)
@@ -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:
index ea35fe5..7a826f8 100644 (file)
@@ -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:
index 59df392..753b677 100644 (file)
@@ -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:
index cbb39ba..93517ce 100644 (file)
@@ -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
 
index 84d0e21..8427760 100644 (file)
@@ -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',
index 935e8bc..45af123 100644 (file)
@@ -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,