diff options
Diffstat (limited to 'gfx/wr/webrender/res/cs_border_solid.glsl')
-rw-r--r-- | gfx/wr/webrender/res/cs_border_solid.glsl | 178 |
1 files changed, 178 insertions, 0 deletions
diff --git a/gfx/wr/webrender/res/cs_border_solid.glsl b/gfx/wr/webrender/res/cs_border_solid.glsl new file mode 100644 index 0000000000..460646e21b --- /dev/null +++ b/gfx/wr/webrender/res/cs_border_solid.glsl @@ -0,0 +1,178 @@ +/* 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,rect,ellipse + +#define DONT_MIX 0 +#define MIX_AA 1 +#define MIX_NO_AA 2 + +// For edges, the colors are the same. For corners, these +// are the colors of each edge making up the corner. +flat varying mediump vec4 vColor0; +flat varying mediump vec4 vColor1; + +// A point + tangent defining the line where the edge +// transition occurs. Used for corners only. +flat varying highp vec4 vColorLine; + +// A boolean indicating that we should be mixing between edge colors. +// Packed in to a vector to work around bug 1630356. +flat varying mediump ivec2 vMixColors; + +// xy = Local space position of the clip center. +// zw = Scale the rect origin by this to get the outer +// corner from the segment rectangle. +flat varying highp vec4 vClipCenter_Sign; + +// An outer and inner elliptical radii for border +// corner clipping. +flat varying highp vec4 vClipRadii; + +// Position, scale, and radii of horizontally and vertically adjacent corner clips. +flat varying highp vec4 vHorizontalClipCenter_Sign; +flat varying highp vec2 vHorizontalClipRadii; +flat varying highp vec4 vVerticalClipCenter_Sign; +flat varying highp vec2 vVerticalClipRadii; + +// Local space position +varying highp vec2 vPos; + +#define SEGMENT_TOP_LEFT 0 +#define SEGMENT_TOP_RIGHT 1 +#define SEGMENT_BOTTOM_RIGHT 2 +#define SEGMENT_BOTTOM_LEFT 3 + +#ifdef WR_VERTEX_SHADER + +PER_INSTANCE in vec2 aTaskOrigin; +PER_INSTANCE in vec4 aRect; +PER_INSTANCE in vec4 aColor0; +PER_INSTANCE in vec4 aColor1; +PER_INSTANCE in int aFlags; +PER_INSTANCE in vec2 aWidths; +PER_INSTANCE in vec2 aRadii; +PER_INSTANCE in vec4 aClipParams1; +PER_INSTANCE in vec4 aClipParams2; + +vec2 get_outer_corner_scale(int segment) { + vec2 p; + + switch (segment) { + case SEGMENT_TOP_LEFT: + p = vec2(0.0, 0.0); + break; + case SEGMENT_TOP_RIGHT: + p = vec2(1.0, 0.0); + break; + case SEGMENT_BOTTOM_RIGHT: + p = vec2(1.0, 1.0); + break; + case SEGMENT_BOTTOM_LEFT: + p = vec2(0.0, 1.0); + break; + default: + // The result is only used for non-default segment cases + p = vec2(0.0); + break; + } + + return p; +} + +void main(void) { + int segment = aFlags & 0xff; + bool do_aa = ((aFlags >> 24) & 0xf0) != 0; + + vec2 outer_scale = get_outer_corner_scale(segment); + vec2 size = aRect.zw - aRect.xy; + vec2 outer = outer_scale * size; + vec2 clip_sign = 1.0 - 2.0 * outer_scale; + + int mix_colors; + switch (segment) { + case SEGMENT_TOP_LEFT: + case SEGMENT_TOP_RIGHT: + case SEGMENT_BOTTOM_RIGHT: + case SEGMENT_BOTTOM_LEFT: { + mix_colors = do_aa ? MIX_AA : MIX_NO_AA; + break; + } + default: + mix_colors = DONT_MIX; + break; + } + + vMixColors.x = mix_colors; + vPos = size * aPosition.xy; + + vColor0 = aColor0; + vColor1 = aColor1; + vClipCenter_Sign = vec4(outer + clip_sign * aRadii, clip_sign); + vClipRadii = vec4(aRadii, max(aRadii - aWidths, 0.0)); + vColorLine = vec4(outer, aWidths.y * -clip_sign.y, aWidths.x * clip_sign.x); + + vec2 horizontal_clip_sign = vec2(-clip_sign.x, clip_sign.y); + vHorizontalClipCenter_Sign = vec4(aClipParams1.xy + + horizontal_clip_sign * aClipParams1.zw, + horizontal_clip_sign); + vHorizontalClipRadii = aClipParams1.zw; + + vec2 vertical_clip_sign = vec2(clip_sign.x, -clip_sign.y); + vVerticalClipCenter_Sign = vec4(aClipParams2.xy + + vertical_clip_sign * aClipParams2.zw, + vertical_clip_sign); + vVerticalClipRadii = aClipParams2.zw; + + gl_Position = uTransform * vec4(aTaskOrigin + aRect.xy + vPos, 0.0, 1.0); +} +#endif + +#ifdef WR_FRAGMENT_SHADER +void main(void) { + float aa_range = compute_aa_range(vPos); + bool do_aa = vMixColors.x != MIX_NO_AA; + + float mix_factor = 0.0; + if (vMixColors.x != DONT_MIX) { + float d_line = distance_to_line(vColorLine.xy, vColorLine.zw, vPos); + if (do_aa) { + mix_factor = distance_aa(aa_range, -d_line); + } else { + mix_factor = d_line + EPSILON >= 0. ? 1.0 : 0.0; + } + } + + // Check if inside main corner clip-region + vec2 clip_relative_pos = vPos - vClipCenter_Sign.xy; + bool in_clip_region = all(lessThan(vClipCenter_Sign.zw * clip_relative_pos, vec2(0.0))); + + float d = -1.0; + if (in_clip_region) { + float d_radii_a = distance_to_ellipse(clip_relative_pos, vClipRadii.xy); + float d_radii_b = distance_to_ellipse(clip_relative_pos, vClipRadii.zw); + d = max(d_radii_a, -d_radii_b); + } + + // And again for horizontally-adjacent corner + clip_relative_pos = vPos - vHorizontalClipCenter_Sign.xy; + in_clip_region = all(lessThan(vHorizontalClipCenter_Sign.zw * clip_relative_pos, vec2(0.0))); + if (in_clip_region) { + float d_radii = distance_to_ellipse(clip_relative_pos, vHorizontalClipRadii.xy); + d = max(d_radii, d); + } + + // And finally for vertically-adjacent corner + clip_relative_pos = vPos - vVerticalClipCenter_Sign.xy; + in_clip_region = all(lessThan(vVerticalClipCenter_Sign.zw * clip_relative_pos, vec2(0.0))); + if (in_clip_region) { + float d_radii = distance_to_ellipse(clip_relative_pos, vVerticalClipRadii.xy); + d = max(d_radii, d); + } + + float alpha = do_aa ? distance_aa(aa_range, d) : 1.0; + vec4 color = mix(vColor0, vColor1, mix_factor); + oFragColor = color * alpha; +} +#endif |