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_DUAL_SOURCE_BLENDING
12#extension GL_ARB_explicit_attrib_location : require
13#endif
14
15#include base
16
17#if defined(WR_FEATURE_TEXTURE_EXTERNAL) || defined(WR_FEATURE_TEXTURE_RECT) || defined(WR_FEATURE_TEXTURE_2D)
18#define TEX_SAMPLE(sampler, tex_coord) texture(sampler, tex_coord.xy)
19#else
20#define TEX_SAMPLE(sampler, tex_coord) texture(sampler, tex_coord)
21#endif
22
23//======================================================================================
24// Vertex shader attributes and uniforms
25//======================================================================================
26#ifdef WR_VERTEX_SHADER
27    // A generic uniform that shaders can optionally use to configure
28    // an operation mode for this batch.
29    uniform int uMode;
30
31    // Uniform inputs
32    uniform mat4 uTransform;       // Orthographic projection
33
34    // Attribute inputs
35    in vec3 aPosition;
36
37    // get_fetch_uv is a macro to work around a macOS Intel driver parsing bug.
38    // TODO: convert back to a function once the driver issues are resolved, if ever.
39    // https://github.com/servo/webrender/pull/623
40    // https://github.com/servo/servo/issues/13953
41    // Do the division with unsigned ints because that's more efficient with D3D
42    #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)))
43#endif
44
45//======================================================================================
46// Fragment shader attributes and uniforms
47//======================================================================================
48#ifdef WR_FRAGMENT_SHADER
49    // Uniform inputs
50
51    // Fragment shader outputs
52    #ifdef WR_FEATURE_DUAL_SOURCE_BLENDING
53        layout(location = 0, index = 0) out vec4 oFragColor;
54        layout(location = 0, index = 1) out vec4 oFragBlend;
55    #else
56        out vec4 oFragColor;
57    #endif
58
59    #define EPSILON                     0.0001
60
61    // "Show Overdraw" color. Premultiplied.
62    #define WR_DEBUG_OVERDRAW_COLOR     vec4(0.110, 0.077, 0.027, 0.125)
63
64    float distance_to_line(vec2 p0, vec2 perp_dir, vec2 p) {
65        vec2 dir_to_p0 = p0 - p;
66        return dot(normalize(perp_dir), dir_to_p0);
67    }
68
69    /// Find the appropriate half range to apply the AA approximation over.
70    /// This range represents a coefficient to go from one CSS pixel to half a device pixel.
71    float compute_aa_range(vec2 position) {
72        // The constant factor is chosen to compensate for the fact that length(fw) is equal
73        // to sqrt(2) times the device pixel ratio in the typical case. 0.5/sqrt(2) = 0.35355.
74        //
75        // This coefficient is chosen to ensure that any sample 0.5 pixels or more inside of
76        // the shape has no anti-aliasing applied to it (since pixels are sampled at their center,
77        // such a pixel (axis aligned) is fully inside the border). We need this so that antialiased
78        // curves properly connect with non-antialiased vertical or horizontal lines, among other things.
79        //
80        // Lines over a half-pixel away from the pixel center *can* intersect with the pixel square;
81        // indeed, unless they are horizontal or vertical, they are guaranteed to. However, choosing
82        // a nonzero area for such pixels causes noticeable artifacts at the junction between an anti-
83        // aliased corner and a straight edge.
84        //
85        // We may want to adjust this constant in specific scenarios (for example keep the principled
86        // value for straight edges where we want pixel-perfect equivalence with non antialiased lines
87        // when axis aligned, while selecting a larger and smoother aa range on curves).
88        return 0.35355 * length(fwidth(position));
89    }
90
91    /// Return the blending coefficient for distance antialiasing.
92    ///
93    /// 0.0 means inside the shape, 1.0 means outside.
94    ///
95    /// This cubic polynomial approximates the area of a 1x1 pixel square under a
96    /// line, given the signed Euclidean distance from the center of the square to
97    /// that line. Calculating the *exact* area would require taking into account
98    /// not only this distance but also the angle of the line. However, in
99    /// practice, this complexity is not required, as the area is roughly the same
100    /// regardless of the angle.
101    ///
102    /// The coefficients of this polynomial were determined through least-squares
103    /// regression and are accurate to within 2.16% of the total area of the pixel
104    /// square 95% of the time, with a maximum error of 3.53%.
105    ///
106    /// See the comments in `compute_aa_range()` for more information on the
107    /// cutoff values of -0.5 and 0.5.
108    float distance_aa(float aa_range, float signed_distance) {
109        float dist = 0.5 * signed_distance / aa_range;
110        if (dist <= -0.5 + EPSILON)
111            return 1.0;
112        if (dist >= 0.5 - EPSILON)
113            return 0.0;
114        return 0.5 + dist * (0.8431027 * dist * dist - 1.14453603);
115    }
116
117    /// Component-wise selection.
118    ///
119    /// The idea of using this is to ensure both potential branches are executed before
120    /// selecting the result, to avoid observable timing differences based on the condition.
121    ///
122    /// Example usage: color = if_then_else(LessThanEqual(color, vec3(0.5)), vec3(0.0), vec3(1.0));
123    ///
124    /// The above example sets each component to 0.0 or 1.0 independently depending on whether
125    /// their values are below or above 0.5.
126    ///
127    /// This is written as a macro in order to work with vectors of any dimension.
128    ///
129    /// Note: Some older android devices don't support mix with bvec. If we ever run into them
130    /// the only option we have is to polyfill it with a branch per component.
131    #define if_then_else(cond, then_branch, else_branch) mix(else_branch, then_branch, cond)
132#endif
133
134//======================================================================================
135// Shared shader uniforms
136//======================================================================================
137#ifdef WR_FEATURE_TEXTURE_2D
138uniform sampler2D sColor0;
139uniform sampler2D sColor1;
140uniform sampler2D sColor2;
141#elif defined WR_FEATURE_TEXTURE_RECT
142uniform sampler2DRect sColor0;
143uniform sampler2DRect sColor1;
144uniform sampler2DRect sColor2;
145#elif defined WR_FEATURE_TEXTURE_EXTERNAL
146uniform samplerExternalOES sColor0;
147uniform samplerExternalOES sColor1;
148uniform samplerExternalOES sColor2;
149#else
150uniform sampler2DArray sColor0;
151uniform sampler2DArray sColor1;
152uniform sampler2DArray sColor2;
153#endif
154
155#ifdef WR_FEATURE_DITHERING
156uniform sampler2D sDither;
157#endif
158
159//======================================================================================
160// Interpolator definitions
161//======================================================================================
162
163//======================================================================================
164// VS only types and UBOs
165//======================================================================================
166
167//======================================================================================
168// VS only functions
169//======================================================================================
170