nir: Add colorspace support to YUV lowering pass
authorDavid Stevens <stevensd@chromium.org>
Wed, 8 Jul 2020 04:23:22 +0000 (13:23 +0900)
committerMarge Bot <eric+marge@anholt.net>
Fri, 31 Jul 2020 07:27:03 +0000 (07:27 +0000)
This change adds support for BT709 and BT2020 colorspace to the YUV
lowering pass. The default remains BT601.

This change also fixes minor imprecision in the last digits of the BT601
offsets due to computation from rounded values when the math was
simplified.

Reviewed-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
Reviewed-by: Rob Clark <robdclark@chromium.org>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6122>

src/compiler/nir/nir.h
src/compiler/nir/nir_lower_tex.c

index 433dec5b7f83bf48aac70e1f6cfc937c6edfda7b..7533cfe4ddabca78091d3fef3e1d171c8c0e43a3 100644 (file)
@@ -4249,6 +4249,8 @@ typedef struct nir_lower_tex_options {
    unsigned lower_xy_uxvx_external;
    unsigned lower_ayuv_external;
    unsigned lower_xyuv_external;
    unsigned lower_xy_uxvx_external;
    unsigned lower_ayuv_external;
    unsigned lower_xyuv_external;
+   unsigned bt709_external;
+   unsigned bt2020_external;
 
    /**
     * To emulate certain texture wrap modes, this can be used
 
    /**
     * To emulate certain texture wrap modes, this can be used
index 46bcc8b6d1fa83718b2b49865e5d604ef6dce978..2e68f2b164eb6de20806a55fe25d73e287943f9e 100644 (file)
 #include "nir_builtin_builder.h"
 #include "nir_format_convert.h"
 
 #include "nir_builtin_builder.h"
 #include "nir_format_convert.h"
 
+static float bt601_csc_coeffs[9] = {
+   1.16438356f,  1.16438356f, 1.16438356f,
+   0.0f,        -0.39176229f, 2.01723214f,
+   1.59602678f, -0.81296764f, 0.0f,
+};
+static float bt709_csc_coeffs[9] = {
+   1.16438356f,  1.16438356f, 1.16438356f,
+   0.0f       , -0.21324861f, 2.11240179f,
+   1.79274107f, -0.53290933f, 0.0f,
+};
+static float bt2020_csc_coeffs[9] = {
+   1.16438356f,  1.16438356f, 1.16438356f,
+   0.0f       , -0.18732610f, 2.14177232f,
+   1.67867411f, -0.65042432f, 0.0f,
+};
+
+static float bt601_csc_offsets[3] = {
+   -0.874202218f, 0.531667823f, -1.085630789f
+};
+static float bt709_csc_offsets[3] = {
+   -0.972945075f, 0.301482665f, -1.133402218f
+};
+static float bt2020_csc_offsets[3] = {
+   -0.915687932f, 0.347458499f, -1.148145075f
+};
+
 static bool
 project_src(nir_builder *b, nir_tex_instr *tex)
 {
 static bool
 project_src(nir_builder *b, nir_tex_instr *tex)
 {
@@ -256,20 +282,36 @@ sample_plane(nir_builder *b, nir_tex_instr *tex, int plane,
 static void
 convert_yuv_to_rgb(nir_builder *b, nir_tex_instr *tex,
                    nir_ssa_def *y, nir_ssa_def *u, nir_ssa_def *v,
 static void
 convert_yuv_to_rgb(nir_builder *b, nir_tex_instr *tex,
                    nir_ssa_def *y, nir_ssa_def *u, nir_ssa_def *v,
-                   nir_ssa_def *a)
+                   nir_ssa_def *a,
+                   const nir_lower_tex_options *options)
 {
 {
+
+   float *offset_vals;
+   float *m_vals;
+   assert((options->bt709_external & options->bt2020_external) == 0);
+   if (options->bt709_external & (1 << tex->texture_index)) {
+      m_vals = bt709_csc_coeffs;
+      offset_vals = bt709_csc_offsets;
+   } else if (options->bt2020_external & (1 << tex->texture_index)) {
+      m_vals = bt2020_csc_coeffs;
+      offset_vals = bt2020_csc_offsets;
+   } else {
+      m_vals = bt601_csc_coeffs;
+      offset_vals = bt601_csc_offsets;
+   }
+
    nir_const_value m[3][4] = {
    nir_const_value m[3][4] = {
-      { { .f32 = 1.16438356f }, { .f32 =  1.16438356f }, { .f32 = 1.16438356f }, { .f32 = 0.0f } },
-      { { .f32 = 0.0f        }, { .f32 = -0.39176229f }, { .f32 = 2.01723214f }, { .f32 = 0.0f } },
-      { { .f32 = 1.59602678f }, { .f32 = -0.81296764f }, { .f32 = 0.0f        }, { .f32 = 0.0f } },
+      { { .f32 = m_vals[0] }, { .f32 =  m_vals[1] }, { .f32 = m_vals[2] }, { .f32 = 0.0f } },
+      { { .f32 = m_vals[3] }, { .f32 =  m_vals[4] }, { .f32 = m_vals[5] }, { .f32 = 0.0f } },
+      { { .f32 = m_vals[6] }, { .f32 =  m_vals[7] }, { .f32 = m_vals[8] }, { .f32 = 0.0f } },
    };
    unsigned bit_size = nir_dest_bit_size(tex->dest);
 
    nir_ssa_def *offset =
       nir_vec4(b,
    };
    unsigned bit_size = nir_dest_bit_size(tex->dest);
 
    nir_ssa_def *offset =
       nir_vec4(b,
-               nir_imm_float(b, -0.874202214f),
-               nir_imm_float(b,  0.531667820f),
-               nir_imm_float(b, -1.085630787f),
+               nir_imm_float(b, offset_vals[0]),
+               nir_imm_float(b, offset_vals[1]),
+               nir_imm_float(b, offset_vals[2]),
                a);
 
    offset = nir_f2fN(b, offset, bit_size);
                a);
 
    offset = nir_f2fN(b, offset, bit_size);
@@ -297,7 +339,8 @@ lower_y_uv_external(nir_builder *b, nir_tex_instr *tex,
                       nir_channel(b, y, 0),
                       nir_channel(b, uv, 0),
                       nir_channel(b, uv, 1),
                       nir_channel(b, y, 0),
                       nir_channel(b, uv, 0),
                       nir_channel(b, uv, 1),
-                      nir_imm_float(b, 1.0f));
+                      nir_imm_float(b, 1.0f),
+                      options);
 }
 
 static void
 }
 
 static void
@@ -314,7 +357,8 @@ lower_y_u_v_external(nir_builder *b, nir_tex_instr *tex,
                       nir_channel(b, y, 0),
                       nir_channel(b, u, 0),
                       nir_channel(b, v, 0),
                       nir_channel(b, y, 0),
                       nir_channel(b, u, 0),
                       nir_channel(b, v, 0),
-                      nir_imm_float(b, 1.0f));
+                      nir_imm_float(b, 1.0f),
+                      options);
 }
 
 static void
 }
 
 static void
@@ -330,7 +374,8 @@ lower_yx_xuxv_external(nir_builder *b, nir_tex_instr *tex,
                       nir_channel(b, y, 0),
                       nir_channel(b, xuxv, 1),
                       nir_channel(b, xuxv, 3),
                       nir_channel(b, y, 0),
                       nir_channel(b, xuxv, 1),
                       nir_channel(b, xuxv, 3),
-                      nir_imm_float(b, 1.0f));
+                      nir_imm_float(b, 1.0f),
+                      options);
 }
 
 static void
 }
 
 static void
@@ -346,7 +391,8 @@ lower_xy_uxvx_external(nir_builder *b, nir_tex_instr *tex,
                      nir_channel(b, y, 1),
                      nir_channel(b, uxvx, 0),
                      nir_channel(b, uxvx, 2),
                      nir_channel(b, y, 1),
                      nir_channel(b, uxvx, 0),
                      nir_channel(b, uxvx, 2),
-                     nir_imm_float(b, 1.0f));
+                     nir_imm_float(b, 1.0f),
+                     options);
 }
 
 static void
 }
 
 static void
@@ -361,7 +407,8 @@ lower_ayuv_external(nir_builder *b, nir_tex_instr *tex,
                      nir_channel(b, ayuv, 2),
                      nir_channel(b, ayuv, 1),
                      nir_channel(b, ayuv, 0),
                      nir_channel(b, ayuv, 2),
                      nir_channel(b, ayuv, 1),
                      nir_channel(b, ayuv, 0),
-                     nir_channel(b, ayuv, 3));
+                     nir_channel(b, ayuv, 3),
+                     options);
 }
 
 static void
 }
 
 static void
@@ -376,7 +423,8 @@ lower_xyuv_external(nir_builder *b, nir_tex_instr *tex,
                      nir_channel(b, xyuv, 2),
                      nir_channel(b, xyuv, 1),
                      nir_channel(b, xyuv, 0),
                      nir_channel(b, xyuv, 2),
                      nir_channel(b, xyuv, 1),
                      nir_channel(b, xyuv, 0),
-                     nir_imm_float(b, 1.0f));
+                     nir_imm_float(b, 1.0f),
+                     options);
 }
 
 /*
 }
 
 /*