From 36d22d82aa202bb199967e9512281e9a53db42c9 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 21:33:14 +0200 Subject: Adding upstream version 115.7.0esr. Signed-off-by: Daniel Baumann --- gfx/wr/webrender/res/brush_mix_blend.glsl | 332 ++++++++++++++++++++++++++++++ 1 file changed, 332 insertions(+) create mode 100644 gfx/wr/webrender/res/brush_mix_blend.glsl (limited to 'gfx/wr/webrender/res/brush_mix_blend.glsl') diff --git a/gfx/wr/webrender/res/brush_mix_blend.glsl b/gfx/wr/webrender/res/brush_mix_blend.glsl new file mode 100644 index 0000000000..c18b95161b --- /dev/null +++ b/gfx/wr/webrender/res/brush_mix_blend.glsl @@ -0,0 +1,332 @@ +/* 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/. */ + +#define VECS_PER_SPECIFIC_BRUSH 3 +#define WR_FEATURE_TEXTURE_2D + +#include shared,prim_shared,brush + +// UV and bounds for the source image +varying highp vec2 v_src_uv; +flat varying highp vec4 v_src_uv_sample_bounds; + +// UV and bounds for the backdrop image +varying highp vec2 v_backdrop_uv; +flat varying highp vec4 v_backdrop_uv_sample_bounds; + +// Flag to allow perspective interpolation of UV. +// Packed in to vector to work around bug 1630356. +flat varying mediump vec2 v_perspective; +// mix-blend op. Packed in to vector to work around bug 1630356. +flat varying mediump ivec2 v_op; + +#ifdef WR_VERTEX_SHADER + +void get_uv( + int res_address, + vec2 f, + ivec2 texture_size, + float perspective_f, + out vec2 out_uv, + out vec4 out_uv_sample_bounds +) { + ImageSource res = fetch_image_source(res_address); + vec2 uv0 = res.uv_rect.p0; + vec2 uv1 = res.uv_rect.p1; + + vec2 inv_texture_size = vec2(1.0) / vec2(texture_size); + f = get_image_quad_uv(res_address, f); + vec2 uv = mix(uv0, uv1, f); + + out_uv = uv * inv_texture_size * perspective_f; + out_uv_sample_bounds = vec4(uv0 + vec2(0.5), uv1 - vec2(0.5)) * inv_texture_size.xyxy; +} + +void brush_vs( + VertexInfo vi, + int prim_address, + RectWithEndpoint local_rect, + RectWithEndpoint segment_rect, + ivec4 prim_user_data, + int specific_resource_address, + mat4 transform, + PictureTask pic_task, + int brush_flags, + vec4 unused +) { + vec2 f = (vi.local_pos - local_rect.p0) / rect_size(local_rect); + float perspective_interpolate = (brush_flags & BRUSH_FLAG_PERSPECTIVE_INTERPOLATION) != 0 ? 1.0 : 0.0; + float perspective_f = mix(vi.world_pos.w, 1.0, perspective_interpolate); + v_perspective.x = perspective_interpolate; + v_op.x = prim_user_data.x; + + get_uv( + prim_user_data.y, + f, + TEX_SIZE(sColor0).xy, + 1.0, + v_backdrop_uv, + v_backdrop_uv_sample_bounds + ); + + get_uv( + prim_user_data.z, + f, + TEX_SIZE(sColor1).xy, + perspective_f, + v_src_uv, + v_src_uv_sample_bounds + ); +} +#endif + +#ifdef WR_FRAGMENT_SHADER +vec3 Multiply(vec3 Cb, vec3 Cs) { + return Cb * Cs; +} + +vec3 Screen(vec3 Cb, vec3 Cs) { + return Cb + Cs - (Cb * Cs); +} + +vec3 HardLight(vec3 Cb, vec3 Cs) { + vec3 m = Multiply(Cb, 2.0 * Cs); + vec3 s = Screen(Cb, 2.0 * Cs - 1.0); + vec3 edge = vec3(0.5, 0.5, 0.5); + return mix(m, s, step(edge, Cs)); +} + +// TODO: Worth doing with mix/step? Check GLSL output. +float ColorDodge(float Cb, float Cs) { + if (Cb == 0.0) + return 0.0; + else if (Cs == 1.0) + return 1.0; + else + return min(1.0, Cb / (1.0 - Cs)); +} + +// TODO: Worth doing with mix/step? Check GLSL output. +float ColorBurn(float Cb, float Cs) { + if (Cb == 1.0) + return 1.0; + else if (Cs == 0.0) + return 0.0; + else + return 1.0 - min(1.0, (1.0 - Cb) / Cs); +} + +float SoftLight(float Cb, float Cs) { + if (Cs <= 0.5) { + return Cb - (1.0 - 2.0 * Cs) * Cb * (1.0 - Cb); + } else { + float D; + + if (Cb <= 0.25) + D = ((16.0 * Cb - 12.0) * Cb + 4.0) * Cb; + else + D = sqrt(Cb); + + return Cb + (2.0 * Cs - 1.0) * (D - Cb); + } +} + +vec3 Difference(vec3 Cb, vec3 Cs) { + return abs(Cb - Cs); +} + +// These functions below are taken from the spec. +// There's probably a much quicker way to implement +// them in GLSL... +float Sat(vec3 c) { + return max(c.r, max(c.g, c.b)) - min(c.r, min(c.g, c.b)); +} + +float Lum(vec3 c) { + vec3 f = vec3(0.3, 0.59, 0.11); + return dot(c, f); +} + +vec3 ClipColor(vec3 C) { + float L = Lum(C); + float n = min(C.r, min(C.g, C.b)); + float x = max(C.r, max(C.g, C.b)); + + if (n < 0.0) + C = L + (((C - L) * L) / (L - n)); + + if (x > 1.0) + C = L + (((C - L) * (1.0 - L)) / (x - L)); + + return C; +} + +vec3 SetLum(vec3 C, float l) { + float d = l - Lum(C); + return ClipColor(C + d); +} + +void SetSatInner(inout float Cmin, inout float Cmid, inout float Cmax, float s) { + if (Cmax > Cmin) { + Cmid = (((Cmid - Cmin) * s) / (Cmax - Cmin)); + Cmax = s; + } else { + Cmid = 0.0; + Cmax = 0.0; + } + Cmin = 0.0; +} + +vec3 SetSat(vec3 C, float s) { + if (C.r <= C.g) { + if (C.g <= C.b) { + SetSatInner(C.r, C.g, C.b, s); + } else { + if (C.r <= C.b) { + SetSatInner(C.r, C.b, C.g, s); + } else { + SetSatInner(C.b, C.r, C.g, s); + } + } + } else { + if (C.r <= C.b) { + SetSatInner(C.g, C.r, C.b, s); + } else { + if (C.g <= C.b) { + SetSatInner(C.g, C.b, C.r, s); + } else { + SetSatInner(C.b, C.g, C.r, s); + } + } + } + return C; +} + +vec3 Hue(vec3 Cb, vec3 Cs) { + return SetLum(SetSat(Cs, Sat(Cb)), Lum(Cb)); +} + +vec3 Saturation(vec3 Cb, vec3 Cs) { + return SetLum(SetSat(Cb, Sat(Cs)), Lum(Cb)); +} + +vec3 Color(vec3 Cb, vec3 Cs) { + return SetLum(Cs, Lum(Cb)); +} + +vec3 Luminosity(vec3 Cb, vec3 Cs) { + return SetLum(Cb, Lum(Cs)); +} + +const int MixBlendMode_Multiply = 1; +const int MixBlendMode_Screen = 2; +const int MixBlendMode_Overlay = 3; +const int MixBlendMode_Darken = 4; +const int MixBlendMode_Lighten = 5; +const int MixBlendMode_ColorDodge = 6; +const int MixBlendMode_ColorBurn = 7; +const int MixBlendMode_HardLight = 8; +const int MixBlendMode_SoftLight = 9; +const int MixBlendMode_Difference = 10; +const int MixBlendMode_Exclusion = 11; +const int MixBlendMode_Hue = 12; +const int MixBlendMode_Saturation = 13; +const int MixBlendMode_Color = 14; +const int MixBlendMode_Luminosity = 15; +const int MixBlendMode_PlusLighter = 16; + +Fragment brush_fs() { + float perspective_divisor = mix(gl_FragCoord.w, 1.0, v_perspective.x); + + vec2 src_uv = v_src_uv * perspective_divisor; + src_uv = clamp(src_uv, v_src_uv_sample_bounds.xy, v_src_uv_sample_bounds.zw); + + vec2 backdrop_uv = clamp(v_backdrop_uv, v_backdrop_uv_sample_bounds.xy, v_backdrop_uv_sample_bounds.zw); + + vec4 Cb = texture(sColor0, backdrop_uv); + vec4 Cs = texture(sColor1, src_uv); + + // The mix-blend-mode functions assume no premultiplied alpha + if (Cb.a != 0.0) { + Cb.rgb /= Cb.a; + } + + if (Cs.a != 0.0) { + Cs.rgb /= Cs.a; + } + + // Return yellow if none of the branches match (shouldn't happen). + vec4 result = vec4(1.0, 1.0, 0.0, 1.0); + + // On Android v_op has been packed in to a vector to avoid a driver bug + // on Adreno 3xx. However, this runs in to another Adreno 3xx driver bug + // where the switch doesn't match any cases. Unpacking the value from the + // vec in to a local variable prior to the switch works around this, but + // gets optimized away by glslopt. Adding a bitwise AND prevents that. + // See bug 1726755. + // default: default: to appease angle_shader_validation + switch (v_op.x & 0xFF) { + case MixBlendMode_Multiply: + result.rgb = Multiply(Cb.rgb, Cs.rgb); + break; + case MixBlendMode_Overlay: + // Overlay is inverse of Hardlight + result.rgb = HardLight(Cs.rgb, Cb.rgb); + break; + case MixBlendMode_Darken: + result.rgb = min(Cs.rgb, Cb.rgb); + break; + case MixBlendMode_Lighten: + result.rgb = max(Cs.rgb, Cb.rgb); + break; + case MixBlendMode_ColorDodge: + result.r = ColorDodge(Cb.r, Cs.r); + result.g = ColorDodge(Cb.g, Cs.g); + result.b = ColorDodge(Cb.b, Cs.b); + break; + case MixBlendMode_ColorBurn: + result.r = ColorBurn(Cb.r, Cs.r); + result.g = ColorBurn(Cb.g, Cs.g); + result.b = ColorBurn(Cb.b, Cs.b); + break; + case MixBlendMode_HardLight: + result.rgb = HardLight(Cb.rgb, Cs.rgb); + break; + case MixBlendMode_SoftLight: + result.r = SoftLight(Cb.r, Cs.r); + result.g = SoftLight(Cb.g, Cs.g); + result.b = SoftLight(Cb.b, Cs.b); + break; + case MixBlendMode_Difference: + result.rgb = Difference(Cb.rgb, Cs.rgb); + break; + case MixBlendMode_Hue: + result.rgb = Hue(Cb.rgb, Cs.rgb); + break; + case MixBlendMode_Saturation: + result.rgb = Saturation(Cb.rgb, Cs.rgb); + break; + case MixBlendMode_Color: + result.rgb = Color(Cb.rgb, Cs.rgb); + break; + case MixBlendMode_Luminosity: + result.rgb = Luminosity(Cb.rgb, Cs.rgb); + break; + case MixBlendMode_Screen: + case MixBlendMode_Exclusion: + case MixBlendMode_PlusLighter: + // This should be unreachable, since we implement + // MixBlendMode::Screen, MixBlendMode::Exclusion and + // MixBlendMode::PlusLighter using glBlendFuncSeparate. + break; + default: break; + } + + result.rgb = (1.0 - Cb.a) * Cs.rgb + Cb.a * result.rgb; + result.a = Cs.a; + result.rgb *= result.a; + + return Fragment(result); +} +#endif -- cgit v1.2.3