Bug 1579235 - Part 3 - Abstract some parts of yuv shader logic. r=nical
authorGlenn Watson <gw@intuitionlibrary.com>
Tue, 18 Feb 2020 08:21:16 +0000
changeset 514368 bde7c898937d877132b5d2aaeae022227c9da7af
parent 514367 2b174daed07cadbcdf81bb4e128aad8ac77085ca
child 514369 813b494a8388485c900045d829c603d45acdd106
push id37134
push userncsoregi@mozilla.com
push dateTue, 18 Feb 2020 16:57:22 +0000
treeherdermozilla-central@a5e2eb343af7 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnical
bugs1579235
milestone75.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1579235 - Part 3 - Abstract some parts of yuv shader logic. r=nical Factor some parts of the YUV brush shader out into a shared yuv.glsl shader include. In future, this shader code will also be referenced by the composite.glsl shader when using the simple (Draw) compositing mode, to composite video surfaces directly into the framebuffer where possible. Differential Revision: https://phabricator.services.mozilla.com/D63123
gfx/wr/webrender/res/brush_yuv_image.glsl
gfx/wr/webrender/res/yuv.glsl
--- a/gfx/wr/webrender/res/brush_yuv_image.glsl
+++ b/gfx/wr/webrender/res/brush_yuv_image.glsl
@@ -3,98 +3,42 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #define VECS_PER_YUV_BRUSH 1
 #define VECS_PER_SPECIFIC_BRUSH VECS_PER_YUV_BRUSH
 
 #define WR_BRUSH_VS_FUNCTION yuv_brush_vs
 #define WR_BRUSH_FS_FUNCTION yuv_brush_fs
 
-#include shared,prim_shared,brush
-
-// TODO(gw): Consider whether we should even have separate shader compilations
-//           for the various YUV modes. To save on the number of shaders we
-//           need to compile, it might be worth just doing this as an
-//           uber-shader instead.
-
-#define YUV_COLOR_SPACE_REC601 0
-#define YUV_COLOR_SPACE_REC709 1
-#define YUV_COLOR_SPACE_REC2020 2
-
-#define YUV_FORMAT_NV12 0
-#define YUV_FORMAT_PLANAR 1
-#define YUV_FORMAT_INTERLEAVED 2
+#include shared,prim_shared,brush,yuv
 
 #ifdef WR_FEATURE_ALPHA_PASS
 varying vec2 vLocalPos;
 #endif
 
 varying vec3 vUv_Y;
 flat varying vec4 vUvBounds_Y;
 
 varying vec3 vUv_U;
 flat varying vec4 vUvBounds_U;
 
 varying vec3 vUv_V;
 flat varying vec4 vUvBounds_V;
 
-#ifdef WR_FEATURE_TEXTURE_RECT
-    #define TEX_SIZE(sampler) vec2(1.0)
-#else
-    #define TEX_SIZE(sampler) vec2(textureSize(sampler, 0).xy)
-#endif
-
 flat varying float vCoefficient;
 flat varying mat3 vYuvColorMatrix;
 flat varying int vFormat;
 
 #ifdef WR_VERTEX_SHADER
-// The constants added to the Y, U and V components are applied in the fragment shader.
 
-// From Rec601:
-// [R]   [1.1643835616438356,  0.0,                 1.5960267857142858   ]   [Y -  16]
-// [G] = [1.1643835616438358, -0.3917622900949137, -0.8129676472377708   ] x [U - 128]
-// [B]   [1.1643835616438356,  2.017232142857143,   8.862867620416422e-17]   [V - 128]
-//
-// For the range [0,1] instead of [0,255].
-//
-// The matrix is stored in column-major.
-const mat3 YuvColorMatrixRec601 = mat3(
-    1.16438,  1.16438, 1.16438,
-    0.0,     -0.39176, 2.01723,
-    1.59603, -0.81297, 0.0
-);
-
-// From Rec709:
-// [R]   [1.1643835616438356,  0.0,                    1.7927410714285714]   [Y -  16]
-// [G] = [1.1643835616438358, -0.21324861427372963,   -0.532909328559444 ] x [U - 128]
-// [B]   [1.1643835616438356,  2.1124017857142854,     0.0               ]   [V - 128]
-//
-// For the range [0,1] instead of [0,255]:
-//
-// The matrix is stored in column-major.
-const mat3 YuvColorMatrixRec709 = mat3(
-    1.16438,  1.16438,  1.16438,
-    0.0    , -0.21325,  2.11240,
-    1.79274, -0.53291,  0.0
-);
-
-// From Re2020:
-// [R]   [1.16438356164384,  0.0,                    1.678674107142860 ]   [Y -  16]
-// [G] = [1.16438356164384, -0.187326104219343,     -0.650424318505057 ] x [U - 128]
-// [B]   [1.16438356164384,  2.14177232142857,       0.0               ]   [V - 128]
-//
-// For the range [0,1] instead of [0,255]:
-//
-// The matrix is stored in column-major.
-const mat3 YuvColorMatrixRec2020 = mat3(
-    1.16438356164384 ,  1.164383561643840,  1.16438356164384,
-    0.0              , -0.187326104219343,  2.14177232142857,
-    1.67867410714286 , -0.650424318505057,  0.0
-);
+#ifdef WR_FEATURE_TEXTURE_RECT
+    #define TEX_SIZE(sampler) vec2(1.0)
+#else
+    #define TEX_SIZE(sampler) vec2(textureSize(sampler, 0).xy)
+#endif
 
 void write_uv_rect(
     int resource_id,
     vec2 f,
     vec2 texture_size,
     out vec3 uv,
     out vec4 uv_bounds
 ) {
@@ -136,23 +80,17 @@ void yuv_brush_vs(
     int brush_flags,
     vec4 unused
 ) {
     vec2 f = (vi.local_pos - local_rect.p0) / local_rect.size;
 
     YuvPrimitive prim = fetch_yuv_primitive(prim_address);
     vCoefficient = prim.coefficient;
 
-    if (prim.color_space == YUV_COLOR_SPACE_REC601) {
-      vYuvColorMatrix = YuvColorMatrixRec601;
-    } else if (prim.color_space == YUV_COLOR_SPACE_REC709) {
-      vYuvColorMatrix = YuvColorMatrixRec709;
-    } else {
-      vYuvColorMatrix = YuvColorMatrixRec2020;
-    }
+    vYuvColorMatrix = get_yuv_color_matrix(prim.color_space);
     vFormat = prim.yuv_format;
 
 #ifdef WR_FEATURE_ALPHA_PASS
     vLocalPos = vi.local_pos;
 #endif
 
     if (vFormat == YUV_FORMAT_PLANAR) {
         write_uv_rect(prim_user_data.x, f, TEX_SIZE(sColor0), vUv_Y, vUvBounds_Y);
@@ -165,44 +103,27 @@ void yuv_brush_vs(
         write_uv_rect(prim_user_data.x, f, TEX_SIZE(sColor0), vUv_Y, vUvBounds_Y);
     }
 }
 #endif
 
 #ifdef WR_FRAGMENT_SHADER
 
 Fragment yuv_brush_fs() {
-    vec3 yuv_value;
-
-    if (vFormat == YUV_FORMAT_PLANAR) {
-        // The yuv_planar format should have this third texture coordinate.
-        vec2 uv_y = clamp(vUv_Y.xy, vUvBounds_Y.xy, vUvBounds_Y.zw);
-        vec2 uv_u = clamp(vUv_U.xy, vUvBounds_U.xy, vUvBounds_U.zw);
-        vec2 uv_v = clamp(vUv_V.xy, vUvBounds_V.xy, vUvBounds_V.zw);
-        yuv_value.x = TEX_SAMPLE(sColor0, vec3(uv_y, vUv_Y.z)).r;
-        yuv_value.y = TEX_SAMPLE(sColor1, vec3(uv_u, vUv_U.z)).r;
-        yuv_value.z = TEX_SAMPLE(sColor2, vec3(uv_v, vUv_V.z)).r;
-    } else if (vFormat == YUV_FORMAT_NV12) {
-        vec2 uv_y = clamp(vUv_Y.xy, vUvBounds_Y.xy, vUvBounds_Y.zw);
-        vec2 uv_uv = clamp(vUv_U.xy, vUvBounds_U.xy, vUvBounds_U.zw);
-        yuv_value.x = TEX_SAMPLE(sColor0, vec3(uv_y, vUv_Y.z)).r;
-        yuv_value.yz = TEX_SAMPLE(sColor1, vec3(uv_uv, vUv_U.z)).rg;
-    } else if (vFormat == YUV_FORMAT_INTERLEAVED) {
-        // "The Y, Cb and Cr color channels within the 422 data are mapped into
-        // the existing green, blue and red color channels."
-        // https://www.khronos.org/registry/OpenGL/extensions/APPLE/APPLE_rgb_422.txt
-        vec2 uv_y = clamp(vUv_Y.xy, vUvBounds_Y.xy, vUvBounds_Y.zw);
-        yuv_value = TEX_SAMPLE(sColor0, vec3(uv_y, vUv_Y.z)).gbr;
-    } else {
-        yuv_value = vec3(0.0);
-    }
-
-    // See the YuvColorMatrix definition for an explanation of where the constants come from.
-    vec3 rgb = vYuvColorMatrix * (yuv_value * vCoefficient - vec3(0.06275, 0.50196, 0.50196));
-    vec4 color = vec4(rgb, 1.0);
+    vec4 color = sample_yuv(
+        vFormat,
+        vYuvColorMatrix,
+        vCoefficient,
+        vUv_Y,
+        vUv_U,
+        vUv_V,
+        vUvBounds_Y,
+        vUvBounds_U,
+        vUvBounds_V
+    );
 
 #ifdef WR_FEATURE_ALPHA_PASS
     color *= init_transform_fs(vLocalPos);
 #endif
 
     return Fragment(color);
 }
 #endif
new file mode 100644
--- /dev/null
+++ b/gfx/wr/webrender/res/yuv.glsl
@@ -0,0 +1,131 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include shared
+
+#define YUV_FORMAT_NV12             0
+#define YUV_FORMAT_PLANAR           1
+#define YUV_FORMAT_INTERLEAVED      2
+
+#ifdef WR_VERTEX_SHADER
+
+#define YUV_COLOR_SPACE_REC601      0
+#define YUV_COLOR_SPACE_REC709      1
+#define YUV_COLOR_SPACE_REC2020     2
+
+// The constants added to the Y, U and V components are applied in the fragment shader.
+
+// From Rec601:
+// [R]   [1.1643835616438356,  0.0,                 1.5960267857142858   ]   [Y -  16]
+// [G] = [1.1643835616438358, -0.3917622900949137, -0.8129676472377708   ] x [U - 128]
+// [B]   [1.1643835616438356,  2.017232142857143,   8.862867620416422e-17]   [V - 128]
+//
+// For the range [0,1] instead of [0,255].
+//
+// The matrix is stored in column-major.
+const mat3 YuvColorMatrixRec601 = mat3(
+    1.16438,  1.16438, 1.16438,
+    0.0,     -0.39176, 2.01723,
+    1.59603, -0.81297, 0.0
+);
+
+// From Rec709:
+// [R]   [1.1643835616438356,  0.0,                    1.7927410714285714]   [Y -  16]
+// [G] = [1.1643835616438358, -0.21324861427372963,   -0.532909328559444 ] x [U - 128]
+// [B]   [1.1643835616438356,  2.1124017857142854,     0.0               ]   [V - 128]
+//
+// For the range [0,1] instead of [0,255]:
+//
+// The matrix is stored in column-major.
+const mat3 YuvColorMatrixRec709 = mat3(
+    1.16438,  1.16438,  1.16438,
+    0.0    , -0.21325,  2.11240,
+    1.79274, -0.53291,  0.0
+);
+
+// From Re2020:
+// [R]   [1.16438356164384,  0.0,                    1.678674107142860 ]   [Y -  16]
+// [G] = [1.16438356164384, -0.187326104219343,     -0.650424318505057 ] x [U - 128]
+// [B]   [1.16438356164384,  2.14177232142857,       0.0               ]   [V - 128]
+//
+// For the range [0,1] instead of [0,255]:
+//
+// The matrix is stored in column-major.
+const mat3 YuvColorMatrixRec2020 = mat3(
+    1.16438356164384 ,  1.164383561643840,  1.16438356164384,
+    0.0              , -0.187326104219343,  2.14177232142857,
+    1.67867410714286 , -0.650424318505057,  0.0
+);
+
+mat3 get_yuv_color_matrix(int color_space) {
+    switch (color_space) {
+        case YUV_COLOR_SPACE_REC601:
+            return YuvColorMatrixRec601;
+        case YUV_COLOR_SPACE_REC709:
+            return YuvColorMatrixRec709;
+        default:
+            return YuvColorMatrixRec2020;
+    }
+}
+#endif
+
+#ifdef WR_FRAGMENT_SHADER
+
+vec4 sample_yuv(
+    int format,
+    mat3 yuv_color_matrix,
+    float coefficient,
+    vec3 in_uv_y,
+    vec3 in_uv_u,
+    vec3 in_uv_v,
+    vec4 uv_bounds_y,
+    vec4 uv_bounds_u,
+    vec4 uv_bounds_v
+) {
+    vec3 yuv_value;
+
+    switch (format) {
+        case YUV_FORMAT_PLANAR:
+            {
+                // The yuv_planar format should have this third texture coordinate.
+                vec2 uv_y = clamp(in_uv_y.xy, uv_bounds_y.xy, uv_bounds_y.zw);
+                vec2 uv_u = clamp(in_uv_u.xy, uv_bounds_u.xy, uv_bounds_u.zw);
+                vec2 uv_v = clamp(in_uv_v.xy, uv_bounds_v.xy, uv_bounds_v.zw);
+                yuv_value.x = TEX_SAMPLE(sColor0, vec3(uv_y, in_uv_y.z)).r;
+                yuv_value.y = TEX_SAMPLE(sColor1, vec3(uv_u, in_uv_u.z)).r;
+                yuv_value.z = TEX_SAMPLE(sColor2, vec3(uv_v, in_uv_v.z)).r;
+            }
+            break;
+
+        case YUV_FORMAT_NV12:
+            {
+                vec2 uv_y = clamp(in_uv_y.xy, uv_bounds_y.xy, uv_bounds_y.zw);
+                vec2 uv_uv = clamp(in_uv_u.xy, uv_bounds_u.xy, uv_bounds_u.zw);
+                yuv_value.x = TEX_SAMPLE(sColor0, vec3(uv_y, in_uv_y.z)).r;
+                yuv_value.yz = TEX_SAMPLE(sColor1, vec3(uv_uv, in_uv_u.z)).rg;
+            }
+            break;
+
+        case YUV_FORMAT_INTERLEAVED:
+            {
+                // "The Y, Cb and Cr color channels within the 422 data are mapped into
+                // the existing green, blue and red color channels."
+                // https://www.khronos.org/registry/OpenGL/extensions/APPLE/APPLE_rgb_422.txt
+                vec2 uv_y = clamp(in_uv_y.xy, uv_bounds_y.xy, uv_bounds_y.zw);
+                yuv_value = TEX_SAMPLE(sColor0, vec3(uv_y, in_uv_y.z)).gbr;
+            }
+            break;
+
+        default:
+            yuv_value = vec3(0.0);
+            break;
+    }
+
+    // See the YuvColorMatrix definition for an explanation of where the constants come from.
+    vec3 rgb = yuv_color_matrix * (yuv_value * coefficient - vec3(0.06275, 0.50196, 0.50196));
+    vec4 color = vec4(rgb, 1.0);
+
+    return color;
+}
+#endif