1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5#ifdef WR_FEATURE_TEXTURE_EXTERNAL
6// Please check https://www.khronos.org/registry/OpenGL/extensions/OES/OES_EGL_image_external_essl3.txt
7// for this extension.
8#extension GL_OES_EGL_image_external_essl3 : require
9#endif
10
11#ifdef WR_FEATURE_TEXTURE_EXTERNAL_ESSL1
12// Some GLES 3 devices do not support GL_OES_EGL_image_external_essl3, so we
13// must use GL_OES_EGL_image_external instead and make the shader ESSL1
14// compatible.
15#extension GL_OES_EGL_image_external : require
16#endif
17
18#ifdef WR_FEATURE_ADVANCED_BLEND
19#extension GL_KHR_blend_equation_advanced : require
20#endif
21
22#ifdef WR_FEATURE_DUAL_SOURCE_BLENDING
23#ifdef GL_ES
24#extension GL_EXT_blend_func_extended : require
25#else
26#extension GL_ARB_explicit_attrib_location : require
27#endif
28#endif
29
30#include base
31
32#if defined(WR_FEATURE_TEXTURE_EXTERNAL_ESSL1)
33#define TEX_SAMPLE(sampler, tex_coord) texture2D(sampler, tex_coord.xy)
34#else
35#define TEX_SAMPLE(sampler, tex_coord) texture(sampler, tex_coord.xy)
36#endif
37
38#if defined(WR_FEATURE_TEXTURE_EXTERNAL) && defined(PLATFORM_ANDROID)
39// On some Mali GPUs we have encountered crashes in glDrawElements when using
40// textureSize(samplerExternalOES) in a vertex shader without potentially
41// sampling from the texture. This tricks the driver in to thinking the texture
42// may be sampled from, avoiding the crash. See bug 1692848.
43uniform bool u_mali_workaround_dummy;
44#define TEX_SIZE(sampler) (u_mali_workaround_dummy ? ivec2(texture(sampler, vec2(0.0, 0.0)).rr) : textureSize(sampler, 0))
45#else
46#define TEX_SIZE(sampler) textureSize(sampler, 0)
47#endif
48
49//======================================================================================
50// Vertex shader attributes and uniforms
51//======================================================================================
52#ifdef WR_VERTEX_SHADER
53    // A generic uniform that shaders can optionally use to configure
54    // an operation mode for this batch.
55    uniform int uMode;
56
57    // Uniform inputs
58    uniform mat4 uTransform;       // Orthographic projection
59
60    // Attribute inputs
61    attribute vec2 aPosition;
62
63    // get_fetch_uv is a macro to work around a macOS Intel driver parsing bug.
64    // TODO: convert back to a function once the driver issues are resolved, if ever.
65    // https://github.com/servo/webrender/pull/623
66    // https://github.com/servo/servo/issues/13953
67    // Do the division with unsigned ints because that's more efficient with D3D
68    #define get_fetch_uv(i, vpi)  ivec2(int(vpi * (uint(i) % (WR_MAX_VERTEX_TEXTURE_WIDTH/vpi))), int(uint(i) / (WR_MAX_VERTEX_TEXTURE_WIDTH/vpi)))
69#endif
70
71//======================================================================================
72// Fragment shader attributes and uniforms
73//======================================================================================
74#ifdef WR_FRAGMENT_SHADER
75    // Uniform inputs
76
77    // Fragment shader outputs
78    #ifdef WR_FEATURE_ADVANCED_BLEND
79        layout(blend_support_all_equations) out;
80    #endif
81
82    #if __VERSION__ == 100
83        #define oFragColor gl_FragColor
84    #elif defined(WR_FEATURE_DUAL_SOURCE_BLENDING)
85        layout(location = 0, index = 0) out vec4 oFragColor;
86        layout(location = 0, index = 1) out vec4 oFragBlend;
87    #else
88        out vec4 oFragColor;
89    #endif
90
91    // Write an output color in normal shaders.
92    void write_output(vec4 color) {
93        oFragColor = color;
94    }
95
96    #define EPSILON                     0.0001
97
98    // "Show Overdraw" color. Premultiplied.
99    #define WR_DEBUG_OVERDRAW_COLOR     vec4(0.110, 0.077, 0.027, 0.125)
100
101    float distance_to_line(vec2 p0, vec2 perp_dir, vec2 p) {
102        vec2 dir_to_p0 = p0 - p;
103        return dot(normalize(perp_dir), dir_to_p0);
104    }
105
106// fwidth is not defined in ESSL 1, but that's okay because we don't need
107// it for any ESSL 1 shader variants.
108#if __VERSION__ != 100
109    /// Find the appropriate half range to apply the AA approximation over.
110    /// This range represents a coefficient to go from one CSS pixel to half a device pixel.
111    float compute_aa_range(vec2 position) {
112        // The constant factor is chosen to compensate for the fact that length(fw) is equal
113        // to sqrt(2) times the device pixel ratio in the typical case.
114        //
115        // This coefficient is chosen to ensure that any sample 0.5 pixels or more inside of
116        // the shape has no anti-aliasing applied to it (since pixels are sampled at their center,
117        // such a pixel (axis aligned) is fully inside the border). We need this so that antialiased
118        // curves properly connect with non-antialiased vertical or horizontal lines, among other things.
119        //
120        // Lines over a half-pixel away from the pixel center *can* intersect with the pixel square;
121        // indeed, unless they are horizontal or vertical, they are guaranteed to. However, choosing
122        // a nonzero area for such pixels causes noticeable artifacts at the junction between an anti-
123        // aliased corner and a straight edge.
124        //
125        // We may want to adjust this constant in specific scenarios (for example keep the principled
126        // value for straight edges where we want pixel-perfect equivalence with non antialiased lines
127        // when axis aligned, while selecting a larger and smoother aa range on curves).
128        //
129        // As a further optimization, we compute the reciprocal of this range, such that we
130        // can then use the cheaper inversesqrt() instead of length(). This also elides a
131        // division that would otherwise be necessary inside distance_aa.
132        #ifdef SWGL
133            // SWGL uses an approximation for fwidth() such that it returns equal x and y.
134            // Thus, sqrt(2)/length(w) = sqrt(2)/sqrt(x*x + x*x) = recip(x).
135            return recip(fwidth(position).x);
136        #else
137            // sqrt(2)/length(w) = inversesqrt(0.5 * dot(w, w))
138            vec2 w = fwidth(position);
139            return inversesqrt(0.5 * dot(w, w));
140        #endif
141    }
142#endif
143
144    /// Return the blending coefficient for distance antialiasing.
145    ///
146    /// 0.0 means inside the shape, 1.0 means outside.
147    ///
148    /// This makes the simplifying assumption that the area of a 1x1 pixel square
149    /// under a line is reasonably similar to just the signed Euclidian distance
150    /// from the center of the square to that line. This diverges slightly from
151    /// better approximations of the exact area, but the difference between the
152    /// methods is not perceptibly noticeable, while this approximation is much
153    /// faster to compute.
154    ///
155    /// See the comments in `compute_aa_range()` for more information on the
156    /// cutoff values of -0.5 and 0.5.
157    float distance_aa(float aa_range, float signed_distance) {
158        float dist = signed_distance * aa_range;
159        return clamp(0.5 - dist, 0.0, 1.0);
160    }
161
162    /// Component-wise selection.
163    ///
164    /// The idea of using this is to ensure both potential branches are executed before
165    /// selecting the result, to avoid observable timing differences based on the condition.
166    ///
167    /// Example usage: color = if_then_else(LessThanEqual(color, vec3(0.5)), vec3(0.0), vec3(1.0));
168    ///
169    /// The above example sets each component to 0.0 or 1.0 independently depending on whether
170    /// their values are below or above 0.5.
171    ///
172    /// This is written as a macro in order to work with vectors of any dimension.
173    ///
174    /// Note: Some older android devices don't support mix with bvec. If we ever run into them
175    /// the only option we have is to polyfill it with a branch per component.
176    #define if_then_else(cond, then_branch, else_branch) mix(else_branch, then_branch, cond)
177#endif
178
179//======================================================================================
180// Shared shader uniforms
181//======================================================================================
182#ifdef WR_FEATURE_TEXTURE_2D
183uniform sampler2D sColor0;
184uniform sampler2D sColor1;
185uniform sampler2D sColor2;
186#elif defined WR_FEATURE_TEXTURE_RECT
187uniform sampler2DRect sColor0;
188uniform sampler2DRect sColor1;
189uniform sampler2DRect sColor2;
190#elif defined(WR_FEATURE_TEXTURE_EXTERNAL) || defined(WR_FEATURE_TEXTURE_EXTERNAL_ESSL1)
191uniform samplerExternalOES sColor0;
192uniform samplerExternalOES sColor1;
193uniform samplerExternalOES sColor2;
194#endif
195
196#ifdef WR_FEATURE_DITHERING
197uniform sampler2D sDither;
198#endif
199
200//======================================================================================
201// Interpolator definitions
202//======================================================================================
203
204//======================================================================================
205// VS only types and UBOs
206//======================================================================================
207
208//======================================================================================
209// VS only functions
210//======================================================================================
211