/* 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/. */ #ifdef WR_FEATURE_PIXEL_LOCAL_STORAGE // For now, we need both extensions here, in order to initialize // the PLS to the current framebuffer color. In future, we can // possibly remove that requirement, or at least support the // other framebuffer fetch extensions that provide the same // functionality. #extension GL_EXT_shader_pixel_local_storage : require #extension GL_ARM_shader_framebuffer_fetch : require #endif #ifdef WR_FEATURE_TEXTURE_EXTERNAL // Please check https://www.khronos.org/registry/OpenGL/extensions/OES/OES_EGL_image_external_essl3.txt // for this extension. #extension GL_OES_EGL_image_external_essl3 : require #endif #ifdef WR_FEATURE_ADVANCED_BLEND #extension GL_KHR_blend_equation_advanced : require #endif #ifdef WR_FEATURE_DUAL_SOURCE_BLENDING #ifdef GL_ES #extension GL_EXT_blend_func_extended : require #else #extension GL_ARB_explicit_attrib_location : require #endif #endif #include base #if defined(WR_FEATURE_TEXTURE_EXTERNAL) || defined(WR_FEATURE_TEXTURE_RECT) || defined(WR_FEATURE_TEXTURE_2D) #define TEX_SAMPLE(sampler, tex_coord) texture(sampler, tex_coord.xy) #else #define TEX_SAMPLE(sampler, tex_coord) texture(sampler, tex_coord) #endif //====================================================================================== // Vertex shader attributes and uniforms //====================================================================================== #ifdef WR_VERTEX_SHADER // A generic uniform that shaders can optionally use to configure // an operation mode for this batch. uniform int uMode; // Uniform inputs uniform mat4 uTransform; // Orthographic projection // Attribute inputs in vec3 aPosition; // get_fetch_uv is a macro to work around a macOS Intel driver parsing bug. // TODO: convert back to a function once the driver issues are resolved, if ever. // https://github.com/servo/webrender/pull/623 // https://github.com/servo/servo/issues/13953 // Do the division with unsigned ints because that's more efficient with D3D #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))) #endif //====================================================================================== // Fragment shader attributes and uniforms //====================================================================================== #ifdef WR_FRAGMENT_SHADER // Uniform inputs #ifdef WR_FEATURE_PIXEL_LOCAL_STORAGE // Define the storage class of the pixel local storage. // If defined as writable, it's a compile time error to // have a normal fragment output variable declared. #if defined(PLS_READONLY) #define PLS_BLOCK __pixel_local_inEXT #elif defined(PLS_WRITEONLY) #define PLS_BLOCK __pixel_local_outEXT #else #define PLS_BLOCK __pixel_localEXT #endif // The structure of pixel local storage. Right now, it's // just the current framebuffer color. In future, we have // (at least) 12 bytes of space we can store extra info // here (such as clip mask values). PLS_BLOCK FrameBuffer { layout(rgba8) highp vec4 color; } PLS; #ifndef PLS_READONLY // Write the output of a fragment shader to PLS. Applies // premultipled alpha blending by default, since the blender // is disabled when PLS is active. // TODO(gw): Properly support alpha blend mode for webgl / canvas. void write_output(vec4 color) { PLS.color = color + PLS.color * (1.0 - color.a); } // Write a raw value straight to PLS, if the fragment shader has // already applied blending. void write_output_raw(vec4 color) { PLS.color = color; } #endif #ifndef PLS_WRITEONLY // Retrieve the current framebuffer color. Useful in conjunction with // the write_output_raw function. vec4 get_current_framebuffer_color() { return PLS.color; } #endif #else // Fragment shader outputs #ifdef WR_FEATURE_ADVANCED_BLEND layout(blend_support_all_equations) out; #endif #ifdef WR_FEATURE_DUAL_SOURCE_BLENDING layout(location = 0, index = 0) out vec4 oFragColor; layout(location = 0, index = 1) out vec4 oFragBlend; #else out vec4 oFragColor; #endif // Write an output color in normal (non-PLS) shaders. void write_output(vec4 color) { oFragColor = color; } #endif #define EPSILON 0.0001 // "Show Overdraw" color. Premultiplied. #define WR_DEBUG_OVERDRAW_COLOR vec4(0.110, 0.077, 0.027, 0.125) float distance_to_line(vec2 p0, vec2 perp_dir, vec2 p) { vec2 dir_to_p0 = p0 - p; return dot(normalize(perp_dir), dir_to_p0); } /// Find the appropriate half range to apply the AA approximation over. /// This range represents a coefficient to go from one CSS pixel to half a device pixel. float compute_aa_range(vec2 position) { // The constant factor is chosen to compensate for the fact that length(fw) is equal // to sqrt(2) times the device pixel ratio in the typical case. 0.5/sqrt(2) = 0.35355. // // This coefficient is chosen to ensure that any sample 0.5 pixels or more inside of // the shape has no anti-aliasing applied to it (since pixels are sampled at their center, // such a pixel (axis aligned) is fully inside the border). We need this so that antialiased // curves properly connect with non-antialiased vertical or horizontal lines, among other things. // // Lines over a half-pixel away from the pixel center *can* intersect with the pixel square; // indeed, unless they are horizontal or vertical, they are guaranteed to. However, choosing // a nonzero area for such pixels causes noticeable artifacts at the junction between an anti- // aliased corner and a straight edge. // // We may want to adjust this constant in specific scenarios (for example keep the principled // value for straight edges where we want pixel-perfect equivalence with non antialiased lines // when axis aligned, while selecting a larger and smoother aa range on curves). return 0.35355 * length(fwidth(position)); } /// Return the blending coefficient for distance antialiasing. /// /// 0.0 means inside the shape, 1.0 means outside. /// /// This cubic polynomial approximates the area of a 1x1 pixel square under a /// line, given the signed Euclidean distance from the center of the square to /// that line. Calculating the *exact* area would require taking into account /// not only this distance but also the angle of the line. However, in /// practice, this complexity is not required, as the area is roughly the same /// regardless of the angle. /// /// The coefficients of this polynomial were determined through least-squares /// regression and are accurate to within 2.16% of the total area of the pixel /// square 95% of the time, with a maximum error of 3.53%. /// /// See the comments in `compute_aa_range()` for more information on the /// cutoff values of -0.5 and 0.5. float distance_aa(float aa_range, float signed_distance) { float dist = 0.5 * signed_distance / aa_range; if (dist <= -0.5 + EPSILON) return 1.0; if (dist >= 0.5 - EPSILON) return 0.0; return 0.5 + dist * (0.8431027 * dist * dist - 1.14453603); } /// Component-wise selection. /// /// The idea of using this is to ensure both potential branches are executed before /// selecting the result, to avoid observable timing differences based on the condition. /// /// Example usage: color = if_then_else(LessThanEqual(color, vec3(0.5)), vec3(0.0), vec3(1.0)); /// /// The above example sets each component to 0.0 or 1.0 independently depending on whether /// their values are below or above 0.5. /// /// This is written as a macro in order to work with vectors of any dimension. /// /// Note: Some older android devices don't support mix with bvec. If we ever run into them /// the only option we have is to polyfill it with a branch per component. #define if_then_else(cond, then_branch, else_branch) mix(else_branch, then_branch, cond) #endif //====================================================================================== // Shared shader uniforms //====================================================================================== #ifdef WR_FEATURE_TEXTURE_2D uniform sampler2D sColor0; uniform sampler2D sColor1; uniform sampler2D sColor2; #elif defined WR_FEATURE_TEXTURE_RECT uniform sampler2DRect sColor0; uniform sampler2DRect sColor1; uniform sampler2DRect sColor2; #elif defined WR_FEATURE_TEXTURE_EXTERNAL uniform samplerExternalOES sColor0; uniform samplerExternalOES sColor1; uniform samplerExternalOES sColor2; #else uniform sampler2DArray sColor0; uniform sampler2DArray sColor1; uniform sampler2DArray sColor2; #endif #ifdef WR_FEATURE_DITHERING uniform sampler2D sDither; #endif //====================================================================================== // Interpolator definitions //====================================================================================== //====================================================================================== // VS only types and UBOs //====================================================================================== //====================================================================================== // VS only functions //======================================================================================