summaryrefslogtreecommitdiffstats
path: root/gfx/wr/webrender/res/cs_border_solid.glsl
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/wr/webrender/res/cs_border_solid.glsl')
-rw-r--r--gfx/wr/webrender/res/cs_border_solid.glsl178
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