BACKPORT: UPSTREAM: mesa/st: Account for YUV color space and range.

- Upstream patch description:

This patch plumbs the YUV color space and range provided through
EGL_EXT_image_dma_buf_import all the way to nir_lower_tex().

NIR already accounts for the YUV color space courtesy of commit
d8fdb8da. However, the color space was wired only for i965/i915 (see
6c11a799) and not for Gallium.

Tested-by: Andres Calderon Jaramillo <andrescj@chromium.org>
Reviewed-by: Rob Clark <robdclark@chromium.org>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/16651>
(cherry picked from commit cd04679a08c7c276a7cadad5ddb5ced540d95300)

- Upstream MR:

https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/16651

- Upstream commit:

https://gitlab.freedesktop.org/mesa/mesa/-/commit/cd04679a08c7c276a7cadad5ddb5ced540d95300

- Conflicts:

In st_program.c: it looks like st_create_fp_variant() has changed quite
a bit upstream. I went ahead and added the new options.bt709_external,
options.bt2020_external, and options.yuv_full_range_external right above
the NIR_PASS_V(state.ir.nir, nir_lower_tex, &options) call in the
ChromeOS version of st_create_fp_variant().

BUG=b:220336463
TEST=Play full-range video on drallion with the mesa-iris driver

Cq-Depend: chromium:3718548
Change-Id: I85d483eb06bfba03ff7c03afb8a7f7ba28a49e74
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/mesa/+/3718549
Tested-by: Andres Calderon Jaramillo <andrescj@chromium.org>
Commit-Queue: Andres Calderon Jaramillo <andrescj@chromium.org>
Reviewed-by: Stéphane Marchesin <marcheu@chromium.org>
Reviewed-by: Chad Versace <chadversary@chromium.org>
diff --git a/src/gallium/frontends/dri/dri_screen.c b/src/gallium/frontends/dri/dri_screen.c
index e68a8c1..a57d8dd 100644
--- a/src/gallium/frontends/dri/dri_screen.c
+++ b/src/gallium/frontends/dri/dri_screen.c
@@ -458,6 +458,9 @@
       stimg->internalformat = driGLFormatToSizedInternalGLFormat(mesa_format);
    }
 
+   stimg->yuv_color_space = img->yuv_color_space;
+   stimg->yuv_range = img->sample_range;
+
    return TRUE;
 }
 
diff --git a/src/gallium/include/frontend/api.h b/src/gallium/include/frontend/api.h
index c7aab40..57a6a45 100644
--- a/src/gallium/include/frontend/api.h
+++ b/src/gallium/include/frontend/api.h
@@ -187,6 +187,12 @@
    unsigned layer;
    /* GL internal format. */
    unsigned internalformat;
+
+   /* one of __DRI_YUV_COLOR_SPACE_* */
+   unsigned yuv_color_space;
+
+   /* one of __DRI_YUV_RANGE_* */
+   unsigned yuv_range;
 };
 
 /**
diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h
index cd2af9f..fec26d2 100644
--- a/src/mesa/main/mtypes.h
+++ b/src/mesa/main/mtypes.h
@@ -893,6 +893,16 @@
    struct util_dynarray Handles;
 };
 
+/**
+ * YUV color space that should be used to sample textures backed by YUV
+ * images.
+ */
+enum gl_texture_yuv_color_space
+{
+   GL_TEXTURE_YUV_COLOR_SPACE_REC601,
+   GL_TEXTURE_YUV_COLOR_SPACE_REC709,
+   GL_TEXTURE_YUV_COLOR_SPACE_REC2020,
+};
 
 /**
  * Texture object state.  Contains the array of mipmap images, border color,
@@ -1009,6 +1019,12 @@
     */
    enum pipe_format surface_format;
 
+   /* If surface_based is true and surface_format is a YUV format, these
+    * settings should be used to convert from YUV to RGB.
+    */
+   enum gl_texture_yuv_color_space yuv_color_space;
+   bool yuv_full_range;
+
    /* When non-negative, samplers should use this level instead of the level
     * range specified by the GL state.
     *
diff --git a/src/mesa/state_tracker/st_cb_eglimage.c b/src/mesa/state_tracker/st_cb_eglimage.c
index 0768db8..0912c35 100644
--- a/src/mesa/state_tracker/st_cb_eglimage.c
+++ b/src/mesa/state_tracker/st_cb_eglimage.c
@@ -25,6 +25,7 @@
  *    Chia-I Wu <olv@lunarg.com>
  */
 
+#include <GL/internal/dri_interface.h>
 #include "main/errors.h"
 #include "main/texobj.h"
 #include "main/teximage.h"
@@ -382,6 +383,22 @@
       st->screen->resource_changed(st->screen, texImage->pt);
 
    texObj->surface_format = stimg->format;
+
+   switch (stimg->yuv_color_space) {
+   case __DRI_YUV_COLOR_SPACE_ITU_REC709:
+      texObj->yuv_color_space = GL_TEXTURE_YUV_COLOR_SPACE_REC709;
+      break;
+   case __DRI_YUV_COLOR_SPACE_ITU_REC2020:
+      texObj->yuv_color_space = GL_TEXTURE_YUV_COLOR_SPACE_REC2020;
+      break;
+   default:
+      texObj->yuv_color_space = GL_TEXTURE_YUV_COLOR_SPACE_REC601;
+      break;
+   }
+
+   if (stimg->yuv_range == __DRI_YUV_FULL_RANGE)
+      texObj->yuv_full_range = true;
+
    texObj->level_override = stimg->level;
    texObj->layer_override = stimg->layer;
 
diff --git a/src/mesa/state_tracker/st_program.c b/src/mesa/state_tracker/st_program.c
index 46b4455..18ad5cf 100644
--- a/src/mesa/state_tracker/st_program.c
+++ b/src/mesa/state_tracker/st_program.c
@@ -1465,6 +1465,9 @@
          options.lower_yuv_external = key->external.lower_yuv;
          options.lower_yu_yv_external = key->external.lower_yu_yv;
          options.lower_y41x_external = key->external.lower_y41x;
+         options.bt709_external = key->external.bt709;
+         options.bt2020_external = key->external.bt2020;
+         options.yuv_full_range_external = key->external.yuv_full_range;
          NIR_PASS_V(state.ir.nir, nir_lower_tex, &options);
          finalize = true;
          need_lower_tex_src_plane = true;
diff --git a/src/mesa/state_tracker/st_program.h b/src/mesa/state_tracker/st_program.h
index 3570d3d..5dd63c2 100644
--- a/src/mesa/state_tracker/st_program.h
+++ b/src/mesa/state_tracker/st_program.h
@@ -57,6 +57,9 @@
    GLuint lower_yuv;
    GLuint lower_yu_yv;
    GLuint lower_y41x;
+   GLuint bt709;
+   GLuint bt2020;
+   GLuint yuv_full_range;
 };
 
 static inline struct st_external_sampler_key
@@ -126,6 +129,20 @@
                 format);
          break;
       }
+
+      switch (stObj->yuv_color_space) {
+      case GL_TEXTURE_YUV_COLOR_SPACE_REC601:
+         break;
+      case GL_TEXTURE_YUV_COLOR_SPACE_REC709:
+         key.bt709 |= (1 << unit);
+         break;
+      case GL_TEXTURE_YUV_COLOR_SPACE_REC2020:
+         key.bt2020 |= (1 << unit);
+         break;
+      }
+
+      if (stObj->yuv_full_range)
+         key.yuv_full_range |= (1 << unit);
    }
 
    return key;