diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 14:29:10 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 14:29:10 +0000 |
commit | 2aa4a82499d4becd2284cdb482213d541b8804dd (patch) | |
tree | b80bf8bf13c3766139fbacc530efd0dd9d54394c /gfx/wr/webrender/res/yuv.glsl | |
parent | Initial commit. (diff) | |
download | firefox-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.glsl | 176 |
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 |