summaryrefslogtreecommitdiffstats
path: root/gfx/wr/webrender/res/yuv.glsl
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
commit2aa4a82499d4becd2284cdb482213d541b8804dd (patch)
treeb80bf8bf13c3766139fbacc530efd0dd9d54394c /gfx/wr/webrender/res/yuv.glsl
parentInitial commit. (diff)
downloadfirefox-2aa4a82499d4becd2284cdb482213d541b8804dd.tar.xz
firefox-2aa4a82499d4becd2284cdb482213d541b8804dd.zip
Adding upstream version 86.0.1.upstream/86.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'gfx/wr/webrender/res/yuv.glsl')
-rw-r--r--gfx/wr/webrender/res/yuv.glsl176
1 files changed, 176 insertions, 0 deletions
diff --git a/gfx/wr/webrender/res/yuv.glsl b/gfx/wr/webrender/res/yuv.glsl
new file mode 100644
index 0000000000..bfcf656b16
--- /dev/null
+++ b/gfx/wr/webrender/res/yuv.glsl
@@ -0,0 +1,176 @@
+/* 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
+
+#ifdef WR_FEATURE_TEXTURE_RECT
+ #define TEX_SIZE(sampler) vec2(1.0)
+#else
+ #define TEX_SIZE(sampler) vec2(textureSize(sampler, 0).xy)
+#endif
+
+#define YUV_COLOR_SPACE_REC601 0
+#define YUV_COLOR_SPACE_REC709 1
+#define YUV_COLOR_SPACE_REC2020 2
+#define YUV_COLOR_SPACE_IDENTITY 3
+
+// 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
+);
+
+// The matrix is stored in column-major.
+// Identity is stored as GBR
+const mat3 IdentityColorMatrix = mat3(
+ 0.0 , 1.0, 0.0,
+ 0.0 , 0.0, 1.0,
+ 1.0 , 0.0, 0.0
+);
+
+mat3 get_yuv_color_matrix(int color_space) {
+ if (color_space == YUV_COLOR_SPACE_REC601) {
+ return YuvColorMatrixRec601;
+ } else if (color_space == YUV_COLOR_SPACE_REC709) {
+ return YuvColorMatrixRec709;
+ } else if (color_space == YUV_COLOR_SPACE_IDENTITY) {
+ return IdentityColorMatrix;
+ } else {
+ return YuvColorMatrixRec2020;
+ }
+}
+
+vec3 get_yuv_offset_vector(int color_space) {
+ // Float conversion to work around a macOS Intel shader compiler bug
+ if (float(color_space) == float(YUV_COLOR_SPACE_IDENTITY)) {
+ return vec3(0.0, 0.0, 0.0);
+ } else {
+ return vec3(0.06275, 0.50196, 0.50196);
+ }
+}
+
+void write_uv_rect(
+ vec2 uv0,
+ vec2 uv1,
+ vec2 f,
+ vec2 texture_size,
+ out vec2 uv,
+ out vec4 uv_bounds
+) {
+ uv = mix(uv0, uv1, f);
+
+ uv_bounds = vec4(uv0 + vec2(0.5), uv1 - vec2(0.5));
+
+ #ifndef WR_FEATURE_TEXTURE_RECT
+ uv /= texture_size;
+ uv_bounds /= texture_size.xyxy;
+ #endif
+}
+#endif
+
+#ifdef WR_FRAGMENT_SHADER
+
+vec4 sample_yuv(
+ int format,
+ mat3 yuv_color_matrix,
+ vec3 yuv_offset_vector,
+ float coefficient,
+ vec3 yuv_layers,
+ vec2 in_uv_y,
+ vec2 in_uv_u,
+ vec2 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, uv_bounds_y.xy, uv_bounds_y.zw);
+ vec2 uv_u = clamp(in_uv_u, uv_bounds_u.xy, uv_bounds_u.zw);
+ vec2 uv_v = clamp(in_uv_v, uv_bounds_v.xy, uv_bounds_v.zw);
+ yuv_value.x = TEX_SAMPLE(sColor0, vec3(uv_y, yuv_layers.x)).r;
+ yuv_value.y = TEX_SAMPLE(sColor1, vec3(uv_u, yuv_layers.y)).r;
+ yuv_value.z = TEX_SAMPLE(sColor2, vec3(uv_v, yuv_layers.z)).r;
+ }
+ break;
+
+ case YUV_FORMAT_NV12:
+ {
+ vec2 uv_y = clamp(in_uv_y, uv_bounds_y.xy, uv_bounds_y.zw);
+ vec2 uv_uv = clamp(in_uv_u, uv_bounds_u.xy, uv_bounds_u.zw);
+ yuv_value.x = TEX_SAMPLE(sColor0, vec3(uv_y, yuv_layers.x)).r;
+ yuv_value.yz = TEX_SAMPLE(sColor1, vec3(uv_uv, yuv_layers.y)).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, uv_bounds_y.xy, uv_bounds_y.zw);
+ yuv_value = TEX_SAMPLE(sColor0, vec3(uv_y, yuv_layers.x)).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 - yuv_offset_vector);
+ vec4 color = vec4(rgb, 1.0);
+
+ return color;
+}
+#endif