clip sources. try: -b do -p linux64 -u all[linux64-qr] -t none
clip sources. try: -b do -p linux64 -u all[linux64-qr] -t none
--- a/gfx/webrender/examples/scrolling.rs
+++ b/gfx/webrender/examples/scrolling.rs
@@ -77,18 +77,31 @@ impl Example for App {
ScrollSensitivity::ScriptAndInputEvents);
builder.push_clip_id(nested_clip_id);
// give it a giant gray background just to distinguish it and to easily
// visually identify the nested scrollbox
builder.push_rect((-1000, -1000).to(5000, 5000), None, ColorF::new(0.5, 0.5, 0.5, 1.0));
// add a teal square to visualize the scrolling/clipping behaviour
- // as you scroll the nested scrollbox with WASD keys
- builder.push_rect((0, 100).to(50, 150), None, ColorF::new(0.0, 1.0, 1.0, 1.0));
+ // as you scroll the nested scrollbox
+ builder.push_rect((0, 200).to(50, 250), None, ColorF::new(0.0, 1.0, 1.0, 1.0));
+
+ // Add a sticky frame. It will "stick" at a margin of 10px from the top, until
+ // the scrollframe scrolls another 60px, at which point it will "unstick". This lines
+ // it up with the above teal square as it scrolls out of the visible area of the
+ // scrollframe
+ let sticky_id = builder.define_sticky_frame(
+ None,
+ (50, 140).to(100, 190),
+ StickyFrameInfo::new(Some(StickySideConstraint{ margin: 10.0, max_offset: 60.0 }),
+ None, None, None));
+ builder.push_clip_id(sticky_id);
+ builder.push_rect((50, 140).to(100, 190), None, ColorF::new(0.5, 0.5, 1.0, 1.0));
+ builder.pop_clip_id(); // sticky_id
// just for good measure add another teal square in the bottom-right
// corner of the nested scrollframe content, which can be scrolled into
// view by the user
builder.push_rect((250, 350).to(300, 400), None, ColorF::new(0.0, 1.0, 1.0, 1.0));
builder.pop_clip_id(); // nested_clip_id
deleted file mode 100644
--- a/gfx/webrender/res/cs_blur.fs.glsl
+++ /dev/null
@@ -1,48 +0,0 @@
-/* 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/. */
-
-// TODO(gw): Write a fast path blur that handles smaller blur radii
-// with a offset / weight uniform table and a constant
-// loop iteration count!
-
-// TODO(gw): Make use of the bilinear sampling trick to reduce
-// the number of texture fetches needed for a gaussian blur.
-
-float gauss(float x, float sigma) {
- return (1.0 / sqrt(6.283185307179586 * sigma * sigma)) * exp(-(x * x) / (2.0 * sigma * sigma));
-}
-
-void main(void) {
- vec4 cache_sample = texture(sCacheRGBA8, vUv);
-
- // TODO(gw): The gauss function gets NaNs when blur radius
- // is zero. In the future, detect this earlier
- // and skip the blur passes completely.
- if (vBlurRadius == 0) {
- oFragColor = cache_sample;
- return;
- }
-
- vec4 color = vec4(cache_sample.rgb, 1.0) * (cache_sample.a * gauss(0.0, vSigma));
-
- for (int i=1 ; i < vBlurRadius ; ++i) {
- vec2 offset = vec2(float(i)) * vOffsetScale;
-
- vec2 st0 = clamp(vUv.xy + offset, vUvRect.xy, vUvRect.zw);
- vec4 color0 = texture(sCacheRGBA8, vec3(st0, vUv.z));
-
- vec2 st1 = clamp(vUv.xy - offset, vUvRect.xy, vUvRect.zw);
- vec4 color1 = texture(sCacheRGBA8, vec3(st1, vUv.z));
-
- // Alpha must be premultiplied in order to properly blur the alpha channel.
- float weight = gauss(float(i), vSigma);
- color += vec4(color0.rgb * color0.a, color0.a) * weight;
- color += vec4(color1.rgb * color1.a, color1.a) * weight;
- }
-
- // Unpremultiply the alpha.
- color.rgb /= color.a;
-
- oFragColor = dither(color);
-}
--- a/gfx/webrender/res/cs_blur.glsl
+++ b/gfx/webrender/res/cs_blur.glsl
@@ -4,8 +4,119 @@
#include shared,prim_shared
varying vec3 vUv;
flat varying vec4 vUvRect;
flat varying vec2 vOffsetScale;
flat varying float vSigma;
flat varying int vBlurRadius;
+
+#ifdef WR_VERTEX_SHADER
+// Applies a separable gaussian blur in one direction, as specified
+// by the dir field in the blur command.
+
+#define DIR_HORIZONTAL 0
+#define DIR_VERTICAL 1
+
+in int aBlurRenderTaskIndex;
+in int aBlurSourceTaskIndex;
+in int aBlurDirection;
+
+struct BlurCommand {
+ int task_id;
+ int src_task_id;
+ int dir;
+};
+
+BlurCommand fetch_blur() {
+ BlurCommand blur;
+
+ blur.task_id = aBlurRenderTaskIndex;
+ blur.src_task_id = aBlurSourceTaskIndex;
+ blur.dir = aBlurDirection;
+
+ return blur;
+}
+
+void main(void) {
+ BlurCommand cmd = fetch_blur();
+ RenderTaskData task = fetch_render_task(cmd.task_id);
+ RenderTaskData src_task = fetch_render_task(cmd.src_task_id);
+
+ vec4 local_rect = task.data0;
+
+ vec2 pos = mix(local_rect.xy,
+ local_rect.xy + local_rect.zw,
+ aPosition.xy);
+
+ vec2 texture_size = vec2(textureSize(sCacheRGBA8, 0).xy);
+ vUv.z = src_task.data1.x;
+ vBlurRadius = int(task.data1.y);
+ vSigma = task.data1.y * 0.5;
+
+ switch (cmd.dir) {
+ case DIR_HORIZONTAL:
+ vOffsetScale = vec2(1.0 / texture_size.x, 0.0);
+ break;
+ case DIR_VERTICAL:
+ vOffsetScale = vec2(0.0, 1.0 / texture_size.y);
+ break;
+ }
+
+ vUvRect = vec4(src_task.data0.xy + vec2(0.5),
+ src_task.data0.xy + src_task.data0.zw - vec2(0.5));
+ vUvRect /= texture_size.xyxy;
+
+ vec2 uv0 = src_task.data0.xy / texture_size;
+ vec2 uv1 = (src_task.data0.xy + src_task.data0.zw) / texture_size;
+ vUv.xy = mix(uv0, uv1, aPosition.xy);
+
+ gl_Position = uTransform * vec4(pos, 0.0, 1.0);
+}
+#endif
+
+#ifdef WR_FRAGMENT_SHADER
+// TODO(gw): Write a fast path blur that handles smaller blur radii
+// with a offset / weight uniform table and a constant
+// loop iteration count!
+
+// TODO(gw): Make use of the bilinear sampling trick to reduce
+// the number of texture fetches needed for a gaussian blur.
+
+float gauss(float x, float sigma) {
+ return (1.0 / sqrt(6.283185307179586 * sigma * sigma)) * exp(-(x * x) / (2.0 * sigma * sigma));
+}
+
+void main(void) {
+ vec4 cache_sample = texture(sCacheRGBA8, vUv);
+
+ // TODO(gw): The gauss function gets NaNs when blur radius
+ // is zero. In the future, detect this earlier
+ // and skip the blur passes completely.
+ if (vBlurRadius == 0) {
+ oFragColor = cache_sample;
+ return;
+ }
+
+ vec4 color = vec4(cache_sample.rgb, 1.0) * (cache_sample.a * gauss(0.0, vSigma));
+
+ for (int i=1 ; i < vBlurRadius ; ++i) {
+ vec2 offset = vec2(float(i)) * vOffsetScale;
+
+ vec2 st0 = clamp(vUv.xy + offset, vUvRect.xy, vUvRect.zw);
+ vec4 color0 = texture(sCacheRGBA8, vec3(st0, vUv.z));
+
+ vec2 st1 = clamp(vUv.xy - offset, vUvRect.xy, vUvRect.zw);
+ vec4 color1 = texture(sCacheRGBA8, vec3(st1, vUv.z));
+
+ // Alpha must be premultiplied in order to properly blur the alpha channel.
+ float weight = gauss(float(i), vSigma);
+ color += vec4(color0.rgb * color0.a, color0.a) * weight;
+ color += vec4(color1.rgb * color1.a, color1.a) * weight;
+ }
+
+ // Unpremultiply the alpha.
+ color.rgb /= color.a;
+
+ oFragColor = dither(color);
+}
+#endif
deleted file mode 100644
--- a/gfx/webrender/res/cs_blur.vs.glsl
+++ /dev/null
@@ -1,65 +0,0 @@
-/* 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/. */
-
-// Applies a separable gaussian blur in one direction, as specified
-// by the dir field in the blur command.
-
-#define DIR_HORIZONTAL 0
-#define DIR_VERTICAL 1
-
-in int aBlurRenderTaskIndex;
-in int aBlurSourceTaskIndex;
-in int aBlurDirection;
-
-struct BlurCommand {
- int task_id;
- int src_task_id;
- int dir;
-};
-
-BlurCommand fetch_blur() {
- BlurCommand blur;
-
- blur.task_id = aBlurRenderTaskIndex;
- blur.src_task_id = aBlurSourceTaskIndex;
- blur.dir = aBlurDirection;
-
- return blur;
-}
-
-void main(void) {
- BlurCommand cmd = fetch_blur();
- RenderTaskData task = fetch_render_task(cmd.task_id);
- RenderTaskData src_task = fetch_render_task(cmd.src_task_id);
-
- vec4 local_rect = task.data0;
-
- vec2 pos = mix(local_rect.xy,
- local_rect.xy + local_rect.zw,
- aPosition.xy);
-
- vec2 texture_size = vec2(textureSize(sCacheRGBA8, 0).xy);
- vUv.z = src_task.data1.x;
- vBlurRadius = int(task.data1.y);
- vSigma = task.data1.y * 0.5;
-
- switch (cmd.dir) {
- case DIR_HORIZONTAL:
- vOffsetScale = vec2(1.0 / texture_size.x, 0.0);
- break;
- case DIR_VERTICAL:
- vOffsetScale = vec2(0.0, 1.0 / texture_size.y);
- break;
- }
-
- vUvRect = vec4(src_task.data0.xy + vec2(0.5),
- src_task.data0.xy + src_task.data0.zw - vec2(0.5));
- vUvRect /= texture_size.xyxy;
-
- vec2 uv0 = src_task.data0.xy / texture_size;
- vec2 uv1 = (src_task.data0.xy + src_task.data0.zw) / texture_size;
- vUv.xy = mix(uv0, uv1, aPosition.xy);
-
- gl_Position = uTransform * vec4(pos, 0.0, 1.0);
-}
deleted file mode 100644
--- a/gfx/webrender/res/ps_angle_gradient.fs.glsl
+++ /dev/null
@@ -1,18 +0,0 @@
-/* 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/. */
-
-void main(void) {
- vec2 pos = mod(vPos, vTileRepeat);
-
- if (pos.x >= vTileSize.x ||
- pos.y >= vTileSize.y) {
- discard;
- }
-
- float offset = dot(pos - vStartPoint, vScaledDir);
-
- oFragColor = sample_gradient(vGradientAddress,
- offset,
- vGradientRepeat);
-}
--- a/gfx/webrender/res/ps_angle_gradient.glsl
+++ b/gfx/webrender/res/ps_angle_gradient.glsl
@@ -9,8 +9,56 @@ flat varying float vGradientRepeat;
flat varying vec2 vScaledDir;
flat varying vec2 vStartPoint;
flat varying vec2 vTileSize;
flat varying vec2 vTileRepeat;
varying vec2 vPos;
+
+#ifdef WR_VERTEX_SHADER
+void main(void) {
+ Primitive prim = load_primitive();
+ Gradient gradient = fetch_gradient(prim.specific_prim_address);
+
+ VertexInfo vi = write_vertex(prim.local_rect,
+ prim.local_clip_rect,
+ prim.z,
+ prim.layer,
+ prim.task,
+ prim.local_rect);
+
+ vPos = vi.local_pos - prim.local_rect.p0;
+
+ vec2 start_point = gradient.start_end_point.xy;
+ vec2 end_point = gradient.start_end_point.zw;
+ vec2 dir = end_point - start_point;
+
+ vStartPoint = start_point;
+ vScaledDir = dir / dot(dir, dir);
+
+ vTileSize = gradient.tile_size_repeat.xy;
+ vTileRepeat = gradient.tile_size_repeat.zw;
+
+ vGradientAddress = prim.specific_prim_address + VECS_PER_GRADIENT;
+
+ // Whether to repeat the gradient instead of clamping.
+ vGradientRepeat = float(int(gradient.extend_mode.x) == EXTEND_MODE_REPEAT);
+}
+#endif
+
+#ifdef WR_FRAGMENT_SHADER
+void main(void) {
+ vec2 pos = mod(vPos, vTileRepeat);
+
+ if (pos.x >= vTileSize.x ||
+ pos.y >= vTileSize.y) {
+ discard;
+ }
+
+ float offset = dot(pos - vStartPoint, vScaledDir);
+
+ oFragColor = sample_gradient(vGradientAddress,
+ offset,
+ vGradientRepeat);
+}
+#endif
deleted file mode 100644
--- a/gfx/webrender/res/ps_angle_gradient.vs.glsl
+++ /dev/null
@@ -1,32 +0,0 @@
-/* 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/. */
-
-void main(void) {
- Primitive prim = load_primitive();
- Gradient gradient = fetch_gradient(prim.specific_prim_address);
-
- VertexInfo vi = write_vertex(prim.local_rect,
- prim.local_clip_rect,
- prim.z,
- prim.layer,
- prim.task,
- prim.local_rect);
-
- vPos = vi.local_pos - prim.local_rect.p0;
-
- vec2 start_point = gradient.start_end_point.xy;
- vec2 end_point = gradient.start_end_point.zw;
- vec2 dir = end_point - start_point;
-
- vStartPoint = start_point;
- vScaledDir = dir / dot(dir, dir);
-
- vTileSize = gradient.tile_size_repeat.xy;
- vTileRepeat = gradient.tile_size_repeat.zw;
-
- vGradientAddress = prim.specific_prim_address + VECS_PER_GRADIENT;
-
- // Whether to repeat the gradient instead of clamping.
- vGradientRepeat = float(int(gradient.extend_mode.x) == EXTEND_MODE_REPEAT);
-}
deleted file mode 100644
--- a/gfx/webrender/res/ps_composite.fs.glsl
+++ /dev/null
@@ -1,247 +0,0 @@
-/* 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/. */
-
-float gauss(float x, float sigma) {
- if (sigma == 0.0)
- return 1.0;
- return (1.0 / sqrt(6.283185307179586 * sigma * sigma)) * exp(-(x * x) / (2.0 * sigma * sigma));
-}
-
-vec3 Multiply(vec3 Cb, vec3 Cs) {
- return Cb * Cs;
-}
-
-vec3 Screen(vec3 Cb, vec3 Cs) {
- return Cb + Cs - (Cb * Cs);
-}
-
-vec3 HardLight(vec3 Cb, vec3 Cs) {
- vec3 m = Multiply(Cb, 2.0 * Cs);
- vec3 s = Screen(Cb, 2.0 * Cs - 1.0);
- vec3 edge = vec3(0.5, 0.5, 0.5);
- return mix(m, s, step(edge, Cs));
-}
-
-// TODO: Worth doing with mix/step? Check GLSL output.
-float ColorDodge(float Cb, float Cs) {
- if (Cb == 0.0)
- return 0.0;
- else if (Cs == 1.0)
- return 1.0;
- else
- return min(1.0, Cb / (1.0 - Cs));
-}
-
-// TODO: Worth doing with mix/step? Check GLSL output.
-float ColorBurn(float Cb, float Cs) {
- if (Cb == 1.0)
- return 1.0;
- else if (Cs == 0.0)
- return 0.0;
- else
- return 1.0 - min(1.0, (1.0 - Cb) / Cs);
-}
-
-float SoftLight(float Cb, float Cs) {
- if (Cs <= 0.5) {
- return Cb - (1.0 - 2.0 * Cs) * Cb * (1.0 - Cb);
- } else {
- float D;
-
- if (Cb <= 0.25)
- D = ((16.0 * Cb - 12.0) * Cb + 4.0) * Cb;
- else
- D = sqrt(Cb);
-
- return Cb + (2.0 * Cs - 1.0) * (D - Cb);
- }
-}
-
-vec3 Difference(vec3 Cb, vec3 Cs) {
- return abs(Cb - Cs);
-}
-
-vec3 Exclusion(vec3 Cb, vec3 Cs) {
- return Cb + Cs - 2.0 * Cb * Cs;
-}
-
-// These functions below are taken from the spec.
-// There's probably a much quicker way to implement
-// them in GLSL...
-float Sat(vec3 c) {
- return max(c.r, max(c.g, c.b)) - min(c.r, min(c.g, c.b));
-}
-
-float Lum(vec3 c) {
- vec3 f = vec3(0.3, 0.59, 0.11);
- return dot(c, f);
-}
-
-vec3 ClipColor(vec3 C) {
- float L = Lum(C);
- float n = min(C.r, min(C.g, C.b));
- float x = max(C.r, max(C.g, C.b));
-
- if (n < 0.0)
- C = L + (((C - L) * L) / (L - n));
-
- if (x > 1.0)
- C = L + (((C - L) * (1.0 - L)) / (x - L));
-
- return C;
-}
-
-vec3 SetLum(vec3 C, float l) {
- float d = l - Lum(C);
- return ClipColor(C + d);
-}
-
-void SetSatInner(inout float Cmin, inout float Cmid, inout float Cmax, float s) {
- if (Cmax > Cmin) {
- Cmid = (((Cmid - Cmin) * s) / (Cmax - Cmin));
- Cmax = s;
- } else {
- Cmid = 0.0;
- Cmax = 0.0;
- }
- Cmin = 0.0;
-}
-
-vec3 SetSat(vec3 C, float s) {
- if (C.r <= C.g) {
- if (C.g <= C.b) {
- SetSatInner(C.r, C.g, C.b, s);
- } else {
- if (C.r <= C.b) {
- SetSatInner(C.r, C.b, C.g, s);
- } else {
- SetSatInner(C.b, C.r, C.g, s);
- }
- }
- } else {
- if (C.r <= C.b) {
- SetSatInner(C.g, C.r, C.b, s);
- } else {
- if (C.g <= C.b) {
- SetSatInner(C.g, C.b, C.r, s);
- } else {
- SetSatInner(C.b, C.g, C.r, s);
- }
- }
- }
- return C;
-}
-
-vec3 Hue(vec3 Cb, vec3 Cs) {
- return SetLum(SetSat(Cs, Sat(Cb)), Lum(Cb));
-}
-
-vec3 Saturation(vec3 Cb, vec3 Cs) {
- return SetLum(SetSat(Cb, Sat(Cs)), Lum(Cb));
-}
-
-vec3 Color(vec3 Cb, vec3 Cs) {
- return SetLum(Cs, Lum(Cb));
-}
-
-vec3 Luminosity(vec3 Cb, vec3 Cs) {
- return SetLum(Cb, Lum(Cs));
-}
-
-const int MixBlendMode_Multiply = 1;
-const int MixBlendMode_Screen = 2;
-const int MixBlendMode_Overlay = 3;
-const int MixBlendMode_Darken = 4;
-const int MixBlendMode_Lighten = 5;
-const int MixBlendMode_ColorDodge = 6;
-const int MixBlendMode_ColorBurn = 7;
-const int MixBlendMode_HardLight = 8;
-const int MixBlendMode_SoftLight = 9;
-const int MixBlendMode_Difference = 10;
-const int MixBlendMode_Exclusion = 11;
-const int MixBlendMode_Hue = 12;
-const int MixBlendMode_Saturation = 13;
-const int MixBlendMode_Color = 14;
-const int MixBlendMode_Luminosity = 15;
-
-void main(void) {
- vec4 Cb = texture(sCacheRGBA8, vUv0);
- vec4 Cs = texture(sCacheRGBA8, vUv1);
-
- // The mix-blend-mode functions assume no premultiplied alpha
- Cb.rgb /= Cb.a;
- Cs.rgb /= Cs.a;
-
- if (Cb.a == 0.0) {
- oFragColor = Cs;
- return;
- }
- if (Cs.a == 0.0) {
- oFragColor = vec4(0.0, 0.0, 0.0, 0.0);
- return;
- }
-
- // Return yellow if none of the branches match (shouldn't happen).
- vec4 result = vec4(1.0, 1.0, 0.0, 1.0);
-
- switch (vOp) {
- case MixBlendMode_Multiply:
- result.rgb = Multiply(Cb.rgb, Cs.rgb);
- break;
- case MixBlendMode_Screen:
- result.rgb = Screen(Cb.rgb, Cs.rgb);
- break;
- case MixBlendMode_Overlay:
- // Overlay is inverse of Hardlight
- result.rgb = HardLight(Cs.rgb, Cb.rgb);
- break;
- case MixBlendMode_Darken:
- result.rgb = min(Cs.rgb, Cb.rgb);
- break;
- case MixBlendMode_Lighten:
- result.rgb = max(Cs.rgb, Cb.rgb);
- break;
- case MixBlendMode_ColorDodge:
- result.r = ColorDodge(Cb.r, Cs.r);
- result.g = ColorDodge(Cb.g, Cs.g);
- result.b = ColorDodge(Cb.b, Cs.b);
- break;
- case MixBlendMode_ColorBurn:
- result.r = ColorBurn(Cb.r, Cs.r);
- result.g = ColorBurn(Cb.g, Cs.g);
- result.b = ColorBurn(Cb.b, Cs.b);
- break;
- case MixBlendMode_HardLight:
- result.rgb = HardLight(Cb.rgb, Cs.rgb);
- break;
- case MixBlendMode_SoftLight:
- result.r = SoftLight(Cb.r, Cs.r);
- result.g = SoftLight(Cb.g, Cs.g);
- result.b = SoftLight(Cb.b, Cs.b);
- break;
- case MixBlendMode_Difference:
- result.rgb = Difference(Cb.rgb, Cs.rgb);
- break;
- case MixBlendMode_Exclusion:
- result.rgb = Exclusion(Cb.rgb, Cs.rgb);
- break;
- case MixBlendMode_Hue:
- result.rgb = Hue(Cb.rgb, Cs.rgb);
- break;
- case MixBlendMode_Saturation:
- result.rgb = Saturation(Cb.rgb, Cs.rgb);
- break;
- case MixBlendMode_Color:
- result.rgb = Color(Cb.rgb, Cs.rgb);
- break;
- case MixBlendMode_Luminosity:
- result.rgb = Luminosity(Cb.rgb, Cs.rgb);
- break;
- }
-
- result.rgb = (1.0 - Cb.a) * Cs.rgb + Cb.a * result.rgb;
- result.a = Cs.a;
-
- oFragColor = result;
-}
--- a/gfx/webrender/res/ps_composite.glsl
+++ b/gfx/webrender/res/ps_composite.glsl
@@ -2,8 +2,285 @@
* 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,prim_shared
varying vec3 vUv0;
varying vec3 vUv1;
flat varying int vOp;
+
+#ifdef WR_VERTEX_SHADER
+void main(void) {
+ CompositeInstance ci = fetch_composite_instance();
+ AlphaBatchTask dest_task = fetch_alpha_batch_task(ci.render_task_index);
+ ReadbackTask backdrop_task = fetch_readback_task(ci.backdrop_task_index);
+ AlphaBatchTask src_task = fetch_alpha_batch_task(ci.src_task_index);
+
+ vec2 dest_origin = dest_task.render_target_origin -
+ dest_task.screen_space_origin +
+ src_task.screen_space_origin;
+
+ vec2 local_pos = mix(dest_origin,
+ dest_origin + src_task.size,
+ aPosition.xy);
+
+ vec2 texture_size = vec2(textureSize(sCacheRGBA8, 0));
+
+ vec2 st0 = backdrop_task.render_target_origin / texture_size;
+ vec2 st1 = (backdrop_task.render_target_origin + backdrop_task.size) / texture_size;
+ vUv0 = vec3(mix(st0, st1, aPosition.xy), backdrop_task.render_target_layer_index);
+
+ st0 = src_task.render_target_origin / texture_size;
+ st1 = (src_task.render_target_origin + src_task.size) / texture_size;
+ vUv1 = vec3(mix(st0, st1, aPosition.xy), src_task.render_target_layer_index);
+
+ vOp = ci.user_data0;
+
+ gl_Position = uTransform * vec4(local_pos, ci.z, 1.0);
+}
+#endif
+
+#ifdef WR_FRAGMENT_SHADER
+float gauss(float x, float sigma) {
+ if (sigma == 0.0)
+ return 1.0;
+ return (1.0 / sqrt(6.283185307179586 * sigma * sigma)) * exp(-(x * x) / (2.0 * sigma * sigma));
+}
+
+vec3 Multiply(vec3 Cb, vec3 Cs) {
+ return Cb * Cs;
+}
+
+vec3 Screen(vec3 Cb, vec3 Cs) {
+ return Cb + Cs - (Cb * Cs);
+}
+
+vec3 HardLight(vec3 Cb, vec3 Cs) {
+ vec3 m = Multiply(Cb, 2.0 * Cs);
+ vec3 s = Screen(Cb, 2.0 * Cs - 1.0);
+ vec3 edge = vec3(0.5, 0.5, 0.5);
+ return mix(m, s, step(edge, Cs));
+}
+
+// TODO: Worth doing with mix/step? Check GLSL output.
+float ColorDodge(float Cb, float Cs) {
+ if (Cb == 0.0)
+ return 0.0;
+ else if (Cs == 1.0)
+ return 1.0;
+ else
+ return min(1.0, Cb / (1.0 - Cs));
+}
+
+// TODO: Worth doing with mix/step? Check GLSL output.
+float ColorBurn(float Cb, float Cs) {
+ if (Cb == 1.0)
+ return 1.0;
+ else if (Cs == 0.0)
+ return 0.0;
+ else
+ return 1.0 - min(1.0, (1.0 - Cb) / Cs);
+}
+
+float SoftLight(float Cb, float Cs) {
+ if (Cs <= 0.5) {
+ return Cb - (1.0 - 2.0 * Cs) * Cb * (1.0 - Cb);
+ } else {
+ float D;
+
+ if (Cb <= 0.25)
+ D = ((16.0 * Cb - 12.0) * Cb + 4.0) * Cb;
+ else
+ D = sqrt(Cb);
+
+ return Cb + (2.0 * Cs - 1.0) * (D - Cb);
+ }
+}
+
+vec3 Difference(vec3 Cb, vec3 Cs) {
+ return abs(Cb - Cs);
+}
+
+vec3 Exclusion(vec3 Cb, vec3 Cs) {
+ return Cb + Cs - 2.0 * Cb * Cs;
+}
+
+// These functions below are taken from the spec.
+// There's probably a much quicker way to implement
+// them in GLSL...
+float Sat(vec3 c) {
+ return max(c.r, max(c.g, c.b)) - min(c.r, min(c.g, c.b));
+}
+
+float Lum(vec3 c) {
+ vec3 f = vec3(0.3, 0.59, 0.11);
+ return dot(c, f);
+}
+
+vec3 ClipColor(vec3 C) {
+ float L = Lum(C);
+ float n = min(C.r, min(C.g, C.b));
+ float x = max(C.r, max(C.g, C.b));
+
+ if (n < 0.0)
+ C = L + (((C - L) * L) / (L - n));
+
+ if (x > 1.0)
+ C = L + (((C - L) * (1.0 - L)) / (x - L));
+
+ return C;
+}
+
+vec3 SetLum(vec3 C, float l) {
+ float d = l - Lum(C);
+ return ClipColor(C + d);
+}
+
+void SetSatInner(inout float Cmin, inout float Cmid, inout float Cmax, float s) {
+ if (Cmax > Cmin) {
+ Cmid = (((Cmid - Cmin) * s) / (Cmax - Cmin));
+ Cmax = s;
+ } else {
+ Cmid = 0.0;
+ Cmax = 0.0;
+ }
+ Cmin = 0.0;
+}
+
+vec3 SetSat(vec3 C, float s) {
+ if (C.r <= C.g) {
+ if (C.g <= C.b) {
+ SetSatInner(C.r, C.g, C.b, s);
+ } else {
+ if (C.r <= C.b) {
+ SetSatInner(C.r, C.b, C.g, s);
+ } else {
+ SetSatInner(C.b, C.r, C.g, s);
+ }
+ }
+ } else {
+ if (C.r <= C.b) {
+ SetSatInner(C.g, C.r, C.b, s);
+ } else {
+ if (C.g <= C.b) {
+ SetSatInner(C.g, C.b, C.r, s);
+ } else {
+ SetSatInner(C.b, C.g, C.r, s);
+ }
+ }
+ }
+ return C;
+}
+
+vec3 Hue(vec3 Cb, vec3 Cs) {
+ return SetLum(SetSat(Cs, Sat(Cb)), Lum(Cb));
+}
+
+vec3 Saturation(vec3 Cb, vec3 Cs) {
+ return SetLum(SetSat(Cb, Sat(Cs)), Lum(Cb));
+}
+
+vec3 Color(vec3 Cb, vec3 Cs) {
+ return SetLum(Cs, Lum(Cb));
+}
+
+vec3 Luminosity(vec3 Cb, vec3 Cs) {
+ return SetLum(Cb, Lum(Cs));
+}
+
+const int MixBlendMode_Multiply = 1;
+const int MixBlendMode_Screen = 2;
+const int MixBlendMode_Overlay = 3;
+const int MixBlendMode_Darken = 4;
+const int MixBlendMode_Lighten = 5;
+const int MixBlendMode_ColorDodge = 6;
+const int MixBlendMode_ColorBurn = 7;
+const int MixBlendMode_HardLight = 8;
+const int MixBlendMode_SoftLight = 9;
+const int MixBlendMode_Difference = 10;
+const int MixBlendMode_Exclusion = 11;
+const int MixBlendMode_Hue = 12;
+const int MixBlendMode_Saturation = 13;
+const int MixBlendMode_Color = 14;
+const int MixBlendMode_Luminosity = 15;
+
+void main(void) {
+ vec4 Cb = texture(sCacheRGBA8, vUv0);
+ vec4 Cs = texture(sCacheRGBA8, vUv1);
+
+ // The mix-blend-mode functions assume no premultiplied alpha
+ Cb.rgb /= Cb.a;
+ Cs.rgb /= Cs.a;
+
+ if (Cb.a == 0.0) {
+ oFragColor = Cs;
+ return;
+ }
+ if (Cs.a == 0.0) {
+ oFragColor = vec4(0.0, 0.0, 0.0, 0.0);
+ return;
+ }
+
+ // Return yellow if none of the branches match (shouldn't happen).
+ vec4 result = vec4(1.0, 1.0, 0.0, 1.0);
+
+ switch (vOp) {
+ case MixBlendMode_Multiply:
+ result.rgb = Multiply(Cb.rgb, Cs.rgb);
+ break;
+ case MixBlendMode_Screen:
+ result.rgb = Screen(Cb.rgb, Cs.rgb);
+ break;
+ case MixBlendMode_Overlay:
+ // Overlay is inverse of Hardlight
+ result.rgb = HardLight(Cs.rgb, Cb.rgb);
+ break;
+ case MixBlendMode_Darken:
+ result.rgb = min(Cs.rgb, Cb.rgb);
+ break;
+ case MixBlendMode_Lighten:
+ result.rgb = max(Cs.rgb, Cb.rgb);
+ break;
+ case MixBlendMode_ColorDodge:
+ result.r = ColorDodge(Cb.r, Cs.r);
+ result.g = ColorDodge(Cb.g, Cs.g);
+ result.b = ColorDodge(Cb.b, Cs.b);
+ break;
+ case MixBlendMode_ColorBurn:
+ result.r = ColorBurn(Cb.r, Cs.r);
+ result.g = ColorBurn(Cb.g, Cs.g);
+ result.b = ColorBurn(Cb.b, Cs.b);
+ break;
+ case MixBlendMode_HardLight:
+ result.rgb = HardLight(Cb.rgb, Cs.rgb);
+ break;
+ case MixBlendMode_SoftLight:
+ result.r = SoftLight(Cb.r, Cs.r);
+ result.g = SoftLight(Cb.g, Cs.g);
+ result.b = SoftLight(Cb.b, Cs.b);
+ break;
+ case MixBlendMode_Difference:
+ result.rgb = Difference(Cb.rgb, Cs.rgb);
+ break;
+ case MixBlendMode_Exclusion:
+ result.rgb = Exclusion(Cb.rgb, Cs.rgb);
+ break;
+ case MixBlendMode_Hue:
+ result.rgb = Hue(Cb.rgb, Cs.rgb);
+ break;
+ case MixBlendMode_Saturation:
+ result.rgb = Saturation(Cb.rgb, Cs.rgb);
+ break;
+ case MixBlendMode_Color:
+ result.rgb = Color(Cb.rgb, Cs.rgb);
+ break;
+ case MixBlendMode_Luminosity:
+ result.rgb = Luminosity(Cb.rgb, Cs.rgb);
+ break;
+ }
+
+ result.rgb = (1.0 - Cb.a) * Cs.rgb + Cb.a * result.rgb;
+ result.a = Cs.a;
+
+ oFragColor = result;
+}
+#endif
deleted file mode 100644
--- a/gfx/webrender/res/ps_composite.vs.glsl
+++ /dev/null
@@ -1,32 +0,0 @@
-/* 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/. */
-
-void main(void) {
- CompositeInstance ci = fetch_composite_instance();
- AlphaBatchTask dest_task = fetch_alpha_batch_task(ci.render_task_index);
- ReadbackTask backdrop_task = fetch_readback_task(ci.backdrop_task_index);
- AlphaBatchTask src_task = fetch_alpha_batch_task(ci.src_task_index);
-
- vec2 dest_origin = dest_task.render_target_origin -
- dest_task.screen_space_origin +
- src_task.screen_space_origin;
-
- vec2 local_pos = mix(dest_origin,
- dest_origin + src_task.size,
- aPosition.xy);
-
- vec2 texture_size = vec2(textureSize(sCacheRGBA8, 0));
-
- vec2 st0 = backdrop_task.render_target_origin / texture_size;
- vec2 st1 = (backdrop_task.render_target_origin + backdrop_task.size) / texture_size;
- vUv0 = vec3(mix(st0, st1, aPosition.xy), backdrop_task.render_target_layer_index);
-
- st0 = src_task.render_target_origin / texture_size;
- st1 = (src_task.render_target_origin + src_task.size) / texture_size;
- vUv1 = vec3(mix(st0, st1, aPosition.xy), src_task.render_target_layer_index);
-
- vOp = ci.user_data0;
-
- gl_Position = uTransform * vec4(local_pos, ci.z, 1.0);
-}
deleted file mode 100644
--- a/gfx/webrender/res/ps_gradient.fs.glsl
+++ /dev/null
@@ -1,16 +0,0 @@
-/* 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/. */
-
-void main(void) {
-#ifdef WR_FEATURE_TRANSFORM
- float alpha = 0.0;
- vec2 local_pos = init_transform_fs(vLocalPos, alpha);
-#else
- float alpha = 1.0;
- vec2 local_pos = vPos;
-#endif
-
- alpha = min(alpha, do_clip());
- oFragColor = dither(vColor * vec4(1.0, 1.0, 1.0, alpha));
-}
--- a/gfx/webrender/res/ps_gradient.glsl
+++ b/gfx/webrender/res/ps_gradient.glsl
@@ -6,8 +6,108 @@
varying vec4 vColor;
#ifdef WR_FEATURE_TRANSFORM
varying vec3 vLocalPos;
#else
varying vec2 vPos;
#endif
+
+#ifdef WR_VERTEX_SHADER
+void main(void) {
+ Primitive prim = load_primitive();
+ Gradient gradient = fetch_gradient(prim.specific_prim_address);
+
+ vec4 abs_start_end_point = gradient.start_end_point + prim.local_rect.p0.xyxy;
+
+ int stop_address = prim.specific_prim_address +
+ VECS_PER_GRADIENT +
+ VECS_PER_GRADIENT_STOP * prim.user_data0;
+
+ GradientStop g0 = fetch_gradient_stop(stop_address);
+ GradientStop g1 = fetch_gradient_stop(stop_address + VECS_PER_GRADIENT_STOP);
+
+ RectWithSize segment_rect;
+ vec2 axis;
+ vec4 adjusted_color_g0 = g0.color;
+ vec4 adjusted_color_g1 = g1.color;
+ if (abs_start_end_point.y == abs_start_end_point.w) {
+ // Calculate the x coord of the gradient stops
+ vec2 g01_x = mix(abs_start_end_point.xx, abs_start_end_point.zz,
+ vec2(g0.offset.x, g1.offset.x));
+
+ // The gradient stops might exceed the geometry rect so clamp them
+ vec2 g01_x_clamped = clamp(g01_x,
+ prim.local_rect.p0.xx,
+ prim.local_rect.p0.xx + prim.local_rect.size.xx);
+
+ // Calculate the segment rect using the clamped coords
+ segment_rect.p0 = vec2(g01_x_clamped.x, prim.local_rect.p0.y);
+ segment_rect.size = vec2(g01_x_clamped.y - g01_x_clamped.x, prim.local_rect.size.y);
+ axis = vec2(1.0, 0.0);
+
+ // Adjust the stop colors by how much they were clamped
+ vec2 adjusted_offset = (g01_x_clamped - g01_x.xx) / (g01_x.y - g01_x.x);
+ adjusted_color_g0 = mix(g0.color, g1.color, adjusted_offset.x);
+ adjusted_color_g1 = mix(g0.color, g1.color, adjusted_offset.y);
+ } else {
+ // Calculate the y coord of the gradient stops
+ vec2 g01_y = mix(abs_start_end_point.yy, abs_start_end_point.ww,
+ vec2(g0.offset.x, g1.offset.x));
+
+ // The gradient stops might exceed the geometry rect so clamp them
+ vec2 g01_y_clamped = clamp(g01_y,
+ prim.local_rect.p0.yy,
+ prim.local_rect.p0.yy + prim.local_rect.size.yy);
+
+ // Calculate the segment rect using the clamped coords
+ segment_rect.p0 = vec2(prim.local_rect.p0.x, g01_y_clamped.x);
+ segment_rect.size = vec2(prim.local_rect.size.x, g01_y_clamped.y - g01_y_clamped.x);
+ axis = vec2(0.0, 1.0);
+
+ // Adjust the stop colors by how much they were clamped
+ vec2 adjusted_offset = (g01_y_clamped - g01_y.xx) / (g01_y.y - g01_y.x);
+ adjusted_color_g0 = mix(g0.color, g1.color, adjusted_offset.x);
+ adjusted_color_g1 = mix(g0.color, g1.color, adjusted_offset.y);
+ }
+
+#ifdef WR_FEATURE_TRANSFORM
+ TransformVertexInfo vi = write_transform_vertex(segment_rect,
+ prim.local_clip_rect,
+ prim.z,
+ prim.layer,
+ prim.task,
+ prim.local_rect);
+ vLocalPos = vi.local_pos;
+ vec2 f = (vi.local_pos.xy - prim.local_rect.p0) / prim.local_rect.size;
+#else
+ VertexInfo vi = write_vertex(segment_rect,
+ prim.local_clip_rect,
+ prim.z,
+ prim.layer,
+ prim.task,
+ prim.local_rect);
+
+ vec2 f = (vi.local_pos - segment_rect.p0) / segment_rect.size;
+ vPos = vi.local_pos;
+#endif
+
+ write_clip(vi.screen_pos, prim.clip_area);
+
+ vColor = mix(adjusted_color_g0, adjusted_color_g1, dot(f, axis));
+}
+#endif
+
+#ifdef WR_FRAGMENT_SHADER
+void main(void) {
+#ifdef WR_FEATURE_TRANSFORM
+ float alpha = 0.0;
+ vec2 local_pos = init_transform_fs(vLocalPos, alpha);
+#else
+ float alpha = 1.0;
+ vec2 local_pos = vPos;
+#endif
+
+ alpha = min(alpha, do_clip());
+ oFragColor = dither(vColor * vec4(1.0, 1.0, 1.0, alpha));
+}
+#endif
deleted file mode 100644
--- a/gfx/webrender/res/ps_gradient.vs.glsl
+++ /dev/null
@@ -1,86 +0,0 @@
-/* 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/. */
-
-void main(void) {
- Primitive prim = load_primitive();
- Gradient gradient = fetch_gradient(prim.specific_prim_address);
-
- vec4 abs_start_end_point = gradient.start_end_point + prim.local_rect.p0.xyxy;
-
- int stop_address = prim.specific_prim_address +
- VECS_PER_GRADIENT +
- VECS_PER_GRADIENT_STOP * prim.user_data0;
-
- GradientStop g0 = fetch_gradient_stop(stop_address);
- GradientStop g1 = fetch_gradient_stop(stop_address + VECS_PER_GRADIENT_STOP);
-
- RectWithSize segment_rect;
- vec2 axis;
- vec4 adjusted_color_g0 = g0.color;
- vec4 adjusted_color_g1 = g1.color;
- if (abs_start_end_point.y == abs_start_end_point.w) {
- // Calculate the x coord of the gradient stops
- vec2 g01_x = mix(abs_start_end_point.xx, abs_start_end_point.zz,
- vec2(g0.offset.x, g1.offset.x));
-
- // The gradient stops might exceed the geometry rect so clamp them
- vec2 g01_x_clamped = clamp(g01_x,
- prim.local_rect.p0.xx,
- prim.local_rect.p0.xx + prim.local_rect.size.xx);
-
- // Calculate the segment rect using the clamped coords
- segment_rect.p0 = vec2(g01_x_clamped.x, prim.local_rect.p0.y);
- segment_rect.size = vec2(g01_x_clamped.y - g01_x_clamped.x, prim.local_rect.size.y);
- axis = vec2(1.0, 0.0);
-
- // Adjust the stop colors by how much they were clamped
- vec2 adjusted_offset = (g01_x_clamped - g01_x.xx) / (g01_x.y - g01_x.x);
- adjusted_color_g0 = mix(g0.color, g1.color, adjusted_offset.x);
- adjusted_color_g1 = mix(g0.color, g1.color, adjusted_offset.y);
- } else {
- // Calculate the y coord of the gradient stops
- vec2 g01_y = mix(abs_start_end_point.yy, abs_start_end_point.ww,
- vec2(g0.offset.x, g1.offset.x));
-
- // The gradient stops might exceed the geometry rect so clamp them
- vec2 g01_y_clamped = clamp(g01_y,
- prim.local_rect.p0.yy,
- prim.local_rect.p0.yy + prim.local_rect.size.yy);
-
- // Calculate the segment rect using the clamped coords
- segment_rect.p0 = vec2(prim.local_rect.p0.x, g01_y_clamped.x);
- segment_rect.size = vec2(prim.local_rect.size.x, g01_y_clamped.y - g01_y_clamped.x);
- axis = vec2(0.0, 1.0);
-
- // Adjust the stop colors by how much they were clamped
- vec2 adjusted_offset = (g01_y_clamped - g01_y.xx) / (g01_y.y - g01_y.x);
- adjusted_color_g0 = mix(g0.color, g1.color, adjusted_offset.x);
- adjusted_color_g1 = mix(g0.color, g1.color, adjusted_offset.y);
- }
-
-#ifdef WR_FEATURE_TRANSFORM
- TransformVertexInfo vi = write_transform_vertex(segment_rect,
- prim.local_clip_rect,
- prim.z,
- prim.layer,
- prim.task,
- prim.local_rect);
- vLocalPos = vi.local_pos;
- vec2 f = (vi.local_pos.xy - prim.local_rect.p0) / prim.local_rect.size;
-#else
- VertexInfo vi = write_vertex(segment_rect,
- prim.local_clip_rect,
- prim.z,
- prim.layer,
- prim.task,
- prim.local_rect);
-
- vec2 f = (vi.local_pos - segment_rect.p0) / segment_rect.size;
- vPos = vi.local_pos;
-#endif
-
- write_clip(vi.screen_pos, prim.clip_area);
-
- vColor = mix(adjusted_color_g0, adjusted_color_g1, dot(f, axis));
-}
deleted file mode 100644
--- a/gfx/webrender/res/ps_line.fs.glsl
+++ /dev/null
@@ -1,122 +0,0 @@
-/* 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/. */
-
-float det(vec2 a, vec2 b) {
- return a.x * b.y - b.x * a.y;
-}
-
-// From: http://research.microsoft.com/en-us/um/people/hoppe/ravg.pdf
-vec2 get_distance_vector(vec2 b0, vec2 b1, vec2 b2) {
- float a = det(b0, b2);
- float b = 2.0 * det(b1, b0);
- float d = 2.0 * det(b2, b1);
-
- float f = b * d - a * a;
- vec2 d21 = b2 - b1;
- vec2 d10 = b1 - b0;
- vec2 d20 = b2 - b0;
-
- vec2 gf = 2.0 * (b *d21 + d * d10 + a * d20);
- gf = vec2(gf.y,-gf.x);
- vec2 pp = -f * gf / dot(gf, gf);
- vec2 d0p = b0 - pp;
- float ap = det(d0p, d20);
- float bp = 2.0 * det(d10, d0p);
-
- float t = clamp((ap + bp) / (2.0 * a + b + d), 0.0, 1.0);
- return mix(mix(b0, b1, t), mix(b1,b2,t), t);
-}
-
-// Approximate distance from point to quadratic bezier.
-float approx_distance(vec2 p, vec2 b0, vec2 b1, vec2 b2) {
- return length(get_distance_vector(b0 - p, b1 - p, b2 - p));
-}
-
-void main(void) {
- float alpha = 1.0;
-
-#ifdef WR_FEATURE_CACHE
- vec2 local_pos = vLocalPos;
-#else
- #ifdef WR_FEATURE_TRANSFORM
- alpha = 0.0;
- vec2 local_pos = init_transform_fs(vLocalPos, alpha);
- #else
- vec2 local_pos = vLocalPos;
- #endif
-
- alpha = min(alpha, do_clip());
-#endif
-
- // Find the appropriate distance to apply the step over.
- vec2 fw = fwidth(local_pos);
- float afwidth = length(fw);
-
- // Select the x/y coord, depending on which axis this edge is.
- vec2 pos = mix(local_pos.xy, local_pos.yx, vAxisSelect);
-
- switch (vStyle) {
- case LINE_STYLE_SOLID: {
- break;
- }
- case LINE_STYLE_DASHED: {
- // Get the main-axis position relative to closest dot or dash.
- float x = mod(pos.x - vLocalOrigin.x, vParams.x);
-
- // Calculate dash alpha (on/off) based on dash length
- alpha = min(alpha, step(x, vParams.y));
- break;
- }
- case LINE_STYLE_DOTTED: {
- // Get the main-axis position relative to closest dot or dash.
- float x = mod(pos.x - vLocalOrigin.x, vParams.x);
-
- // Get the dot alpha
- vec2 dot_relative_pos = vec2(x, pos.y) - vParams.yz;
- float dot_distance = length(dot_relative_pos) - vParams.y;
- alpha = min(alpha, 1.0 - smoothstep(-0.5 * afwidth,
- 0.5 * afwidth,
- dot_distance));
- break;
- }
- case LINE_STYLE_WAVY: {
- vec2 normalized_local_pos = pos - vLocalOrigin.xy;
-
- float y0 = vParams.y;
- float dy = vParams.z;
- float dx = vParams.w;
-
- // Flip the position of the bezier center points each
- // wave period.
- dy *= step(mod(normalized_local_pos.x, 4.0 * dx), 2.0 * dx) * 2.0 - 1.0;
-
- // Convert pos to a local position within one wave period.
- normalized_local_pos.x = dx + mod(normalized_local_pos.x, 2.0 * dx);
-
- // Evaluate SDF to the first bezier.
- vec2 b0_0 = vec2(0.0 * dx, y0);
- vec2 b1_0 = vec2(1.0 * dx, y0 - dy);
- vec2 b2_0 = vec2(2.0 * dx, y0);
- float d1 = approx_distance(normalized_local_pos, b0_0, b1_0, b2_0);
-
- // Evaluate SDF to the second bezier.
- vec2 b0_1 = vec2(2.0 * dx, y0);
- vec2 b1_1 = vec2(3.0 * dx, y0 + dy);
- vec2 b2_1 = vec2(4.0 * dx, y0);
- float d2 = approx_distance(normalized_local_pos, b0_1, b1_1, b2_1);
-
- // SDF union - this is needed to avoid artifacts where the
- // bezier curves join.
- float d = min(d1, d2);
-
- // Apply AA based on the thickness of the wave.
- alpha = 1.0 - smoothstep(vParams.x - 0.5 * afwidth,
- vParams.x + 0.5 * afwidth,
- d);
- break;
- }
- }
-
- oFragColor = vColor * vec4(1.0, 1.0, 1.0, alpha);
-}
--- a/gfx/webrender/res/ps_line.glsl
+++ b/gfx/webrender/res/ps_line.glsl
@@ -10,8 +10,243 @@ flat varying float vAxisSelect;
flat varying vec4 vParams;
flat varying vec2 vLocalOrigin;
#ifdef WR_FEATURE_TRANSFORM
varying vec3 vLocalPos;
#else
varying vec2 vLocalPos;
#endif
+
+#ifdef WR_VERTEX_SHADER
+#define LINE_ORIENTATION_VERTICAL 0
+#define LINE_ORIENTATION_HORIZONTAL 1
+
+void main(void) {
+ Primitive prim = load_primitive();
+ Line line = fetch_line(prim.specific_prim_address);
+
+ vec2 pos, size;
+
+ switch (int(line.orientation)) {
+ case LINE_ORIENTATION_HORIZONTAL:
+ vAxisSelect = 0.0;
+ pos = prim.local_rect.p0;
+ size = prim.local_rect.size;
+ break;
+ case LINE_ORIENTATION_VERTICAL:
+ vAxisSelect = 1.0;
+ pos = prim.local_rect.p0.yx;
+ size = prim.local_rect.size.yx;
+ break;
+ }
+
+ vLocalOrigin = pos;
+ vStyle = int(line.style);
+
+ switch (vStyle) {
+ case LINE_STYLE_SOLID: {
+ break;
+ }
+ case LINE_STYLE_DASHED: {
+ // y = dash on + off length
+ // z = dash length
+ // w = center line of edge cross-axis (for dots only)
+ float desired_dash_length = size.y * 3.0;
+ // Consider half total length since there is an equal on/off for each dash.
+ float dash_count = 1.0 + ceil(size.x / desired_dash_length);
+ float dash_length = size.x / dash_count;
+ vParams = vec4(2.0 * dash_length,
+ dash_length,
+ 0.0,
+ 0.0);
+ break;
+ }
+ case LINE_STYLE_DOTTED: {
+ float diameter = size.y;
+ float radius = 0.5 * diameter;
+ float dot_count = ceil(0.5 * size.x / diameter);
+ float empty_space = size.x - dot_count * diameter;
+ float distance_between_centers = diameter + empty_space / dot_count;
+ float center_line = pos.y + 0.5 * size.y;
+ vParams = vec4(distance_between_centers,
+ radius,
+ center_line,
+ 0.0);
+ break;
+ }
+ case LINE_STYLE_WAVY: {
+ // Choose some arbitrary values to scale thickness,
+ // wave period etc.
+ // TODO(gw): Tune these to get closer to what Gecko uses.
+ float thickness = 0.15 * size.y;
+ vParams = vec4(thickness,
+ size.y * 0.5,
+ size.y * 0.75,
+ size.y * 0.5);
+ break;
+ }
+ }
+
+#ifdef WR_FEATURE_CACHE
+ int text_shadow_address = prim.user_data0;
+ PrimitiveGeometry shadow_geom = fetch_primitive_geometry(text_shadow_address);
+ TextShadow shadow = fetch_text_shadow(text_shadow_address + VECS_PER_PRIM_HEADER);
+
+ vec2 device_origin = prim.task.render_target_origin +
+ uDevicePixelRatio * (prim.local_rect.p0 + shadow.offset - shadow_geom.local_rect.p0);
+ vec2 device_size = uDevicePixelRatio * prim.local_rect.size;
+
+ vec2 device_pos = mix(device_origin,
+ device_origin + device_size,
+ aPosition.xy);
+
+ vColor = shadow.color;
+ vLocalPos = mix(prim.local_rect.p0,
+ prim.local_rect.p0 + prim.local_rect.size,
+ aPosition.xy);
+
+ gl_Position = uTransform * vec4(device_pos, 0.0, 1.0);
+#else
+ vColor = line.color;
+
+ #ifdef WR_FEATURE_TRANSFORM
+ TransformVertexInfo vi = write_transform_vertex(prim.local_rect,
+ prim.local_clip_rect,
+ prim.z,
+ prim.layer,
+ prim.task,
+ prim.local_rect);
+ #else
+ VertexInfo vi = write_vertex(prim.local_rect,
+ prim.local_clip_rect,
+ prim.z,
+ prim.layer,
+ prim.task,
+ prim.local_rect);
+ #endif
+
+ vLocalPos = vi.local_pos;
+ write_clip(vi.screen_pos, prim.clip_area);
+#endif
+}
+#endif
+
+#ifdef WR_FRAGMENT_SHADER
+float det(vec2 a, vec2 b) {
+ return a.x * b.y - b.x * a.y;
+}
+
+// From: http://research.microsoft.com/en-us/um/people/hoppe/ravg.pdf
+vec2 get_distance_vector(vec2 b0, vec2 b1, vec2 b2) {
+ float a = det(b0, b2);
+ float b = 2.0 * det(b1, b0);
+ float d = 2.0 * det(b2, b1);
+
+ float f = b * d - a * a;
+ vec2 d21 = b2 - b1;
+ vec2 d10 = b1 - b0;
+ vec2 d20 = b2 - b0;
+
+ vec2 gf = 2.0 * (b *d21 + d * d10 + a * d20);
+ gf = vec2(gf.y,-gf.x);
+ vec2 pp = -f * gf / dot(gf, gf);
+ vec2 d0p = b0 - pp;
+ float ap = det(d0p, d20);
+ float bp = 2.0 * det(d10, d0p);
+
+ float t = clamp((ap + bp) / (2.0 * a + b + d), 0.0, 1.0);
+ return mix(mix(b0, b1, t), mix(b1,b2,t), t);
+}
+
+// Approximate distance from point to quadratic bezier.
+float approx_distance(vec2 p, vec2 b0, vec2 b1, vec2 b2) {
+ return length(get_distance_vector(b0 - p, b1 - p, b2 - p));
+}
+
+void main(void) {
+ float alpha = 1.0;
+
+#ifdef WR_FEATURE_CACHE
+ vec2 local_pos = vLocalPos;
+#else
+ #ifdef WR_FEATURE_TRANSFORM
+ alpha = 0.0;
+ vec2 local_pos = init_transform_fs(vLocalPos, alpha);
+ #else
+ vec2 local_pos = vLocalPos;
+ #endif
+
+ alpha = min(alpha, do_clip());
+#endif
+
+ // Find the appropriate distance to apply the step over.
+ vec2 fw = fwidth(local_pos);
+ float afwidth = length(fw);
+
+ // Select the x/y coord, depending on which axis this edge is.
+ vec2 pos = mix(local_pos.xy, local_pos.yx, vAxisSelect);
+
+ switch (vStyle) {
+ case LINE_STYLE_SOLID: {
+ break;
+ }
+ case LINE_STYLE_DASHED: {
+ // Get the main-axis position relative to closest dot or dash.
+ float x = mod(pos.x - vLocalOrigin.x, vParams.x);
+
+ // Calculate dash alpha (on/off) based on dash length
+ alpha = min(alpha, step(x, vParams.y));
+ break;
+ }
+ case LINE_STYLE_DOTTED: {
+ // Get the main-axis position relative to closest dot or dash.
+ float x = mod(pos.x - vLocalOrigin.x, vParams.x);
+
+ // Get the dot alpha
+ vec2 dot_relative_pos = vec2(x, pos.y) - vParams.yz;
+ float dot_distance = length(dot_relative_pos) - vParams.y;
+ alpha = min(alpha, 1.0 - smoothstep(-0.5 * afwidth,
+ 0.5 * afwidth,
+ dot_distance));
+ break;
+ }
+ case LINE_STYLE_WAVY: {
+ vec2 normalized_local_pos = pos - vLocalOrigin.xy;
+
+ float y0 = vParams.y;
+ float dy = vParams.z;
+ float dx = vParams.w;
+
+ // Flip the position of the bezier center points each
+ // wave period.
+ dy *= step(mod(normalized_local_pos.x, 4.0 * dx), 2.0 * dx) * 2.0 - 1.0;
+
+ // Convert pos to a local position within one wave period.
+ normalized_local_pos.x = dx + mod(normalized_local_pos.x, 2.0 * dx);
+
+ // Evaluate SDF to the first bezier.
+ vec2 b0_0 = vec2(0.0 * dx, y0);
+ vec2 b1_0 = vec2(1.0 * dx, y0 - dy);
+ vec2 b2_0 = vec2(2.0 * dx, y0);
+ float d1 = approx_distance(normalized_local_pos, b0_0, b1_0, b2_0);
+
+ // Evaluate SDF to the second bezier.
+ vec2 b0_1 = vec2(2.0 * dx, y0);
+ vec2 b1_1 = vec2(3.0 * dx, y0 + dy);
+ vec2 b2_1 = vec2(4.0 * dx, y0);
+ float d2 = approx_distance(normalized_local_pos, b0_1, b1_1, b2_1);
+
+ // SDF union - this is needed to avoid artifacts where the
+ // bezier curves join.
+ float d = min(d1, d2);
+
+ // Apply AA based on the thickness of the wave.
+ alpha = 1.0 - smoothstep(vParams.x - 0.5 * afwidth,
+ vParams.x + 0.5 * afwidth,
+ d);
+ break;
+ }
+ }
+
+ oFragColor = vColor * vec4(1.0, 1.0, 1.0, alpha);
+}
+#endif
deleted file mode 100644
--- a/gfx/webrender/res/ps_line.vs.glsl
+++ /dev/null
@@ -1,115 +0,0 @@
-/* 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/. */
-
-#define LINE_ORIENTATION_VERTICAL 0
-#define LINE_ORIENTATION_HORIZONTAL 1
-
-void main(void) {
- Primitive prim = load_primitive();
- Line line = fetch_line(prim.specific_prim_address);
-
- vec2 pos, size;
-
- switch (int(line.orientation)) {
- case LINE_ORIENTATION_HORIZONTAL:
- vAxisSelect = 0.0;
- pos = prim.local_rect.p0;
- size = prim.local_rect.size;
- break;
- case LINE_ORIENTATION_VERTICAL:
- vAxisSelect = 1.0;
- pos = prim.local_rect.p0.yx;
- size = prim.local_rect.size.yx;
- break;
- }
-
- vLocalOrigin = pos;
- vStyle = int(line.style);
-
- switch (vStyle) {
- case LINE_STYLE_SOLID: {
- break;
- }
- case LINE_STYLE_DASHED: {
- // y = dash on + off length
- // z = dash length
- // w = center line of edge cross-axis (for dots only)
- float desired_dash_length = size.y * 3.0;
- // Consider half total length since there is an equal on/off for each dash.
- float dash_count = 1.0 + ceil(size.x / desired_dash_length);
- float dash_length = size.x / dash_count;
- vParams = vec4(2.0 * dash_length,
- dash_length,
- 0.0,
- 0.0);
- break;
- }
- case LINE_STYLE_DOTTED: {
- float diameter = size.y;
- float radius = 0.5 * diameter;
- float dot_count = ceil(0.5 * size.x / diameter);
- float empty_space = size.x - dot_count * diameter;
- float distance_between_centers = diameter + empty_space / dot_count;
- float center_line = pos.y + 0.5 * size.y;
- vParams = vec4(distance_between_centers,
- radius,
- center_line,
- 0.0);
- break;
- }
- case LINE_STYLE_WAVY: {
- // Choose some arbitrary values to scale thickness,
- // wave period etc.
- // TODO(gw): Tune these to get closer to what Gecko uses.
- float thickness = 0.15 * size.y;
- vParams = vec4(thickness,
- size.y * 0.5,
- size.y * 0.75,
- size.y * 0.5);
- break;
- }
- }
-
-#ifdef WR_FEATURE_CACHE
- int text_shadow_address = prim.user_data0;
- PrimitiveGeometry shadow_geom = fetch_primitive_geometry(text_shadow_address);
- TextShadow shadow = fetch_text_shadow(text_shadow_address + VECS_PER_PRIM_HEADER);
-
- vec2 device_origin = prim.task.render_target_origin +
- uDevicePixelRatio * (prim.local_rect.p0 + shadow.offset - shadow_geom.local_rect.p0);
- vec2 device_size = uDevicePixelRatio * prim.local_rect.size;
-
- vec2 device_pos = mix(device_origin,
- device_origin + device_size,
- aPosition.xy);
-
- vColor = shadow.color;
- vLocalPos = mix(prim.local_rect.p0,
- prim.local_rect.p0 + prim.local_rect.size,
- aPosition.xy);
-
- gl_Position = uTransform * vec4(device_pos, 0.0, 1.0);
-#else
- vColor = line.color;
-
- #ifdef WR_FEATURE_TRANSFORM
- TransformVertexInfo vi = write_transform_vertex(prim.local_rect,
- prim.local_clip_rect,
- prim.z,
- prim.layer,
- prim.task,
- prim.local_rect);
- #else
- VertexInfo vi = write_vertex(prim.local_rect,
- prim.local_clip_rect,
- prim.z,
- prim.layer,
- prim.task,
- prim.local_rect);
- #endif
-
- vLocalPos = vi.local_pos;
- write_clip(vi.screen_pos, prim.clip_area);
-#endif
-}
deleted file mode 100644
--- a/gfx/webrender/res/ps_radial_gradient.fs.glsl
+++ /dev/null
@@ -1,55 +0,0 @@
-/* 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/. */
-
-void main(void) {
- vec2 pos = mod(vPos, vTileRepeat);
-
- if (pos.x >= vTileSize.x ||
- pos.y >= vTileSize.y) {
- discard;
- }
-
- vec2 cd = vEndCenter - vStartCenter;
- vec2 pd = pos - vStartCenter;
- float rd = vEndRadius - vStartRadius;
-
- // Solve for t in length(t * cd - pd) = vStartRadius + t * rd
- // using a quadratic equation in form of At^2 - 2Bt + C = 0
- float A = dot(cd, cd) - rd * rd;
- float B = dot(pd, cd) + vStartRadius * rd;
- float C = dot(pd, pd) - vStartRadius * vStartRadius;
-
- float offset;
- if (A == 0.0) {
- // Since A is 0, just solve for -2Bt + C = 0
- if (B == 0.0) {
- discard;
- }
- float t = 0.5 * C / B;
- if (vStartRadius + rd * t >= 0.0) {
- offset = t;
- } else {
- discard;
- }
- } else {
- float discr = B * B - A * C;
- if (discr < 0.0) {
- discard;
- }
- discr = sqrt(discr);
- float t0 = (B + discr) / A;
- float t1 = (B - discr) / A;
- if (vStartRadius + rd * t0 >= 0.0) {
- offset = t0;
- } else if (vStartRadius + rd * t1 >= 0.0) {
- offset = t1;
- } else {
- discard;
- }
- }
-
- oFragColor = sample_gradient(vGradientAddress,
- offset,
- vGradientRepeat);
-}
--- a/gfx/webrender/res/ps_radial_gradient.glsl
+++ b/gfx/webrender/res/ps_radial_gradient.glsl
@@ -11,8 +11,101 @@ flat varying vec2 vStartCenter;
flat varying vec2 vEndCenter;
flat varying float vStartRadius;
flat varying float vEndRadius;
flat varying vec2 vTileSize;
flat varying vec2 vTileRepeat;
varying vec2 vPos;
+
+#ifdef WR_VERTEX_SHADER
+void main(void) {
+ Primitive prim = load_primitive();
+ RadialGradient gradient = fetch_radial_gradient(prim.specific_prim_address);
+
+ VertexInfo vi = write_vertex(prim.local_rect,
+ prim.local_clip_rect,
+ prim.z,
+ prim.layer,
+ prim.task,
+ prim.local_rect);
+
+ vPos = vi.local_pos - prim.local_rect.p0;
+
+ vStartCenter = gradient.start_end_center.xy;
+ vEndCenter = gradient.start_end_center.zw;
+
+ vStartRadius = gradient.start_end_radius_ratio_xy_extend_mode.x;
+ vEndRadius = gradient.start_end_radius_ratio_xy_extend_mode.y;
+
+ vTileSize = gradient.tile_size_repeat.xy;
+ vTileRepeat = gradient.tile_size_repeat.zw;
+
+ // Transform all coordinates by the y scale so the
+ // fragment shader can work with circles
+ float ratio_xy = gradient.start_end_radius_ratio_xy_extend_mode.z;
+ vPos.y *= ratio_xy;
+ vStartCenter.y *= ratio_xy;
+ vEndCenter.y *= ratio_xy;
+ vTileSize.y *= ratio_xy;
+ vTileRepeat.y *= ratio_xy;
+
+ vGradientAddress = prim.specific_prim_address + VECS_PER_GRADIENT;
+
+ // Whether to repeat the gradient instead of clamping.
+ vGradientRepeat = float(int(gradient.start_end_radius_ratio_xy_extend_mode.w) == EXTEND_MODE_REPEAT);
+}
+#endif
+
+#ifdef WR_FRAGMENT_SHADER
+void main(void) {
+ vec2 pos = mod(vPos, vTileRepeat);
+
+ if (pos.x >= vTileSize.x ||
+ pos.y >= vTileSize.y) {
+ discard;
+ }
+
+ vec2 cd = vEndCenter - vStartCenter;
+ vec2 pd = pos - vStartCenter;
+ float rd = vEndRadius - vStartRadius;
+
+ // Solve for t in length(t * cd - pd) = vStartRadius + t * rd
+ // using a quadratic equation in form of At^2 - 2Bt + C = 0
+ float A = dot(cd, cd) - rd * rd;
+ float B = dot(pd, cd) + vStartRadius * rd;
+ float C = dot(pd, pd) - vStartRadius * vStartRadius;
+
+ float offset;
+ if (A == 0.0) {
+ // Since A is 0, just solve for -2Bt + C = 0
+ if (B == 0.0) {
+ discard;
+ }
+ float t = 0.5 * C / B;
+ if (vStartRadius + rd * t >= 0.0) {
+ offset = t;
+ } else {
+ discard;
+ }
+ } else {
+ float discr = B * B - A * C;
+ if (discr < 0.0) {
+ discard;
+ }
+ discr = sqrt(discr);
+ float t0 = (B + discr) / A;
+ float t1 = (B - discr) / A;
+ if (vStartRadius + rd * t0 >= 0.0) {
+ offset = t0;
+ } else if (vStartRadius + rd * t1 >= 0.0) {
+ offset = t1;
+ } else {
+ discard;
+ }
+ }
+
+ oFragColor = sample_gradient(vGradientAddress,
+ offset,
+ vGradientRepeat);
+}
+#endif
deleted file mode 100644
--- a/gfx/webrender/res/ps_radial_gradient.vs.glsl
+++ /dev/null
@@ -1,40 +0,0 @@
-/* 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/. */
-
-void main(void) {
- Primitive prim = load_primitive();
- RadialGradient gradient = fetch_radial_gradient(prim.specific_prim_address);
-
- VertexInfo vi = write_vertex(prim.local_rect,
- prim.local_clip_rect,
- prim.z,
- prim.layer,
- prim.task,
- prim.local_rect);
-
- vPos = vi.local_pos - prim.local_rect.p0;
-
- vStartCenter = gradient.start_end_center.xy;
- vEndCenter = gradient.start_end_center.zw;
-
- vStartRadius = gradient.start_end_radius_ratio_xy_extend_mode.x;
- vEndRadius = gradient.start_end_radius_ratio_xy_extend_mode.y;
-
- vTileSize = gradient.tile_size_repeat.xy;
- vTileRepeat = gradient.tile_size_repeat.zw;
-
- // Transform all coordinates by the y scale so the
- // fragment shader can work with circles
- float ratio_xy = gradient.start_end_radius_ratio_xy_extend_mode.z;
- vPos.y *= ratio_xy;
- vStartCenter.y *= ratio_xy;
- vEndCenter.y *= ratio_xy;
- vTileSize.y *= ratio_xy;
- vTileRepeat.y *= ratio_xy;
-
- vGradientAddress = prim.specific_prim_address + VECS_PER_GRADIENT;
-
- // Whether to repeat the gradient instead of clamping.
- vGradientRepeat = float(int(gradient.start_end_radius_ratio_xy_extend_mode.w) == EXTEND_MODE_REPEAT);
-}
deleted file mode 100644
--- a/gfx/webrender/res/ps_split_composite.fs.glsl
+++ /dev/null
@@ -1,14 +0,0 @@
-/* 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/. */
-
-void main(void) {
- bvec4 inside = lessThanEqual(vec4(vUvTaskBounds.xy, vUv.xy),
- vec4(vUv.xy, vUvTaskBounds.zw));
- if (all(inside)) {
- vec2 uv = clamp(vUv.xy, vUvSampleBounds.xy, vUvSampleBounds.zw);
- oFragColor = textureLod(sCacheRGBA8, vec3(uv, vUv.z), 0.0);
- } else {
- oFragColor = vec4(0.0);
- }
-}
--- a/gfx/webrender/res/ps_split_composite.glsl
+++ b/gfx/webrender/res/ps_split_composite.glsl
@@ -2,8 +2,68 @@
* 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,prim_shared
varying vec3 vUv;
flat varying vec4 vUvTaskBounds;
flat varying vec4 vUvSampleBounds;
+
+#ifdef WR_VERTEX_SHADER
+struct SplitGeometry {
+ vec3 points[4];
+};
+
+SplitGeometry fetch_split_geometry(int address) {
+ ivec2 uv = get_resource_cache_uv(address);
+
+ vec4 data0 = texelFetchOffset(sResourceCache, uv, 0, ivec2(0, 0));
+ vec4 data1 = texelFetchOffset(sResourceCache, uv, 0, ivec2(1, 0));
+ vec4 data2 = texelFetchOffset(sResourceCache, uv, 0, ivec2(2, 0));
+
+ SplitGeometry geo;
+ geo.points = vec3[4](
+ data0.xyz, vec3(data0.w, data1.xy),
+ vec3(data1.zw, data2.x), data2.yzw
+ );
+ return geo;
+}
+
+vec3 bilerp(vec3 a, vec3 b, vec3 c, vec3 d, float s, float t) {
+ vec3 x = mix(a, b, t);
+ vec3 y = mix(c, d, t);
+ return mix(x, y, s);
+}
+
+void main(void) {
+ CompositeInstance ci = fetch_composite_instance();
+ SplitGeometry geometry = fetch_split_geometry(ci.user_data0);
+ AlphaBatchTask src_task = fetch_alpha_batch_task(ci.src_task_index);
+
+ vec3 world_pos = bilerp(geometry.points[0], geometry.points[1],
+ geometry.points[3], geometry.points[2],
+ aPosition.y, aPosition.x);
+ vec4 final_pos = vec4(world_pos.xy * uDevicePixelRatio, ci.z, 1.0);
+
+ gl_Position = uTransform * final_pos;
+
+ vec2 uv_origin = src_task.render_target_origin;
+ vec2 uv_pos = uv_origin + world_pos.xy - src_task.screen_space_origin;
+ vec2 texture_size = vec2(textureSize(sCacheRGBA8, 0));
+ vUv = vec3(uv_pos / texture_size, src_task.render_target_layer_index);
+ vUvTaskBounds = vec4(uv_origin, uv_origin + src_task.size) / texture_size.xyxy;
+ vUvSampleBounds = vec4(uv_origin + 0.5, uv_origin + src_task.size - 0.5) / texture_size.xyxy;
+}
+#endif
+
+#ifdef WR_FRAGMENT_SHADER
+void main(void) {
+ bvec4 inside = lessThanEqual(vec4(vUvTaskBounds.xy, vUv.xy),
+ vec4(vUv.xy, vUvTaskBounds.zw));
+ if (all(inside)) {
+ vec2 uv = clamp(vUv.xy, vUvSampleBounds.xy, vUvSampleBounds.zw);
+ oFragColor = textureLod(sCacheRGBA8, vec3(uv, vUv.z), 0.0);
+ } else {
+ oFragColor = vec4(0.0);
+ }
+}
+#endif
deleted file mode 100644
--- a/gfx/webrender/res/ps_split_composite.vs.glsl
+++ /dev/null
@@ -1,48 +0,0 @@
-/* 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/. */
-
-struct SplitGeometry {
- vec3 points[4];
-};
-
-SplitGeometry fetch_split_geometry(int address) {
- ivec2 uv = get_resource_cache_uv(address);
-
- vec4 data0 = texelFetchOffset(sResourceCache, uv, 0, ivec2(0, 0));
- vec4 data1 = texelFetchOffset(sResourceCache, uv, 0, ivec2(1, 0));
- vec4 data2 = texelFetchOffset(sResourceCache, uv, 0, ivec2(2, 0));
-
- SplitGeometry geo;
- geo.points = vec3[4](
- data0.xyz, vec3(data0.w, data1.xy),
- vec3(data1.zw, data2.x), data2.yzw
- );
- return geo;
-}
-
-vec3 bilerp(vec3 a, vec3 b, vec3 c, vec3 d, float s, float t) {
- vec3 x = mix(a, b, t);
- vec3 y = mix(c, d, t);
- return mix(x, y, s);
-}
-
-void main(void) {
- CompositeInstance ci = fetch_composite_instance();
- SplitGeometry geometry = fetch_split_geometry(ci.user_data0);
- AlphaBatchTask src_task = fetch_alpha_batch_task(ci.src_task_index);
-
- vec3 world_pos = bilerp(geometry.points[0], geometry.points[1],
- geometry.points[3], geometry.points[2],
- aPosition.y, aPosition.x);
- vec4 final_pos = vec4(world_pos.xy * uDevicePixelRatio, ci.z, 1.0);
-
- gl_Position = uTransform * final_pos;
-
- vec2 uv_origin = src_task.render_target_origin;
- vec2 uv_pos = uv_origin + world_pos.xy - src_task.screen_space_origin;
- vec2 texture_size = vec2(textureSize(sCacheRGBA8, 0));
- vUv = vec3(uv_pos / texture_size, src_task.render_target_layer_index);
- vUvTaskBounds = vec4(uv_origin, uv_origin + src_task.size) / texture_size.xyxy;
- vUvSampleBounds = vec4(uv_origin + 0.5, uv_origin + src_task.size - 0.5) / texture_size.xyxy;
-}
--- a/gfx/webrender/src/border.rs
+++ b/gfx/webrender/src/border.rs
@@ -1,18 +1,18 @@
/* 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/. */
use api::{BorderSide, BorderStyle, BorderWidths, ClipAndScrollInfo, ColorF, LayerPoint, LayerRect};
use api::{LayerSize, LocalClip, NormalBorder};
+use clip::ClipSource;
use ellipse::Ellipse;
use gpu_cache::GpuDataRequest;
use frame_builder::FrameBuilder;
-use mask_cache::ClipSource;
use prim_store::{BorderPrimitiveCpu, PrimitiveContainer};
use tiling::PrimitiveFlags;
use util::{lerp, pack_as_float};
#[repr(u8)]
#[derive(Debug, Copy, Clone, PartialEq)]
pub enum BorderCornerInstance {
Single, // Single instance needed - corner styles are same or similar.
@@ -223,17 +223,17 @@ impl NormalBorderHelpers for NormalBorde
impl FrameBuilder {
fn add_normal_border_primitive(&mut self,
rect: &LayerRect,
border: &NormalBorder,
widths: &BorderWidths,
clip_and_scroll: ClipAndScrollInfo,
local_clip: &LocalClip,
corner_instances: [BorderCornerInstance; 4],
- extra_clips: &[ClipSource]) {
+ clip_sources: Vec<ClipSource>) {
let radius = &border.radius;
let left = &border.left;
let right = &border.right;
let top = &border.top;
let bottom = &border.bottom;
// These colors are used during inset/outset scaling.
let left_color = left.border_color(1.0, 2.0/3.0, 0.3, 0.7);
@@ -269,17 +269,17 @@ impl FrameBuilder {
radius.bottom_left.width,
radius.bottom_left.height ].into(),
],
};
self.add_primitive(clip_and_scroll,
&rect,
local_clip,
- extra_clips,
+ clip_sources,
PrimitiveContainer::Border(prim_cpu));
}
// TODO(gw): This allows us to move border types over to the
// simplified shader model one at a time. Once all borders
// are converted, this can be removed, along with the complex
// border code path.
pub fn add_normal_border(&mut self,
@@ -420,17 +420,17 @@ impl FrameBuilder {
}
self.add_normal_border_primitive(rect,
border,
widths,
clip_and_scroll,
local_clip,
corner_instances,
- &extra_clips);
+ extra_clips);
}
}
}
pub trait BorderSideHelpers {
fn border_color(&self,
scale_factor_0: f32,
scale_factor_1: f32,
new file mode 100644
--- /dev/null
+++ b/gfx/webrender/src/clip.rs
@@ -0,0 +1,158 @@
+/* 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/. */
+
+use api::{BorderRadius, ComplexClipRegion, ImageMask, ImageRendering};
+use api::{LayerPoint, LayerRect, LayerToWorldTransform, LocalClip};
+use border::BorderCornerClipSource;
+use gpu_cache::GpuCache;
+use mask_cache::MaskCacheInfo;
+use resource_cache::ResourceCache;
+use std::ops::Not;
+
+#[derive(Clone, Debug)]
+pub struct ClipRegion {
+ pub origin: LayerPoint,
+ pub main: LayerRect,
+ pub image_mask: Option<ImageMask>,
+ pub complex_clips: Vec<ComplexClipRegion>,
+}
+
+impl ClipRegion {
+ pub fn create_for_clip_node(rect: LayerRect,
+ mut complex_clips: Vec<ComplexClipRegion>,
+ mut image_mask: Option<ImageMask>)
+ -> ClipRegion {
+ // All the coordinates we receive are relative to the stacking context, but we want
+ // to convert them to something relative to the origin of the clip.
+ let negative_origin = -rect.origin.to_vector();
+ if let Some(ref mut image_mask) = image_mask {
+ image_mask.rect = image_mask.rect.translate(&negative_origin);
+ }
+
+ for complex_clip in complex_clips.iter_mut() {
+ complex_clip.rect = complex_clip.rect.translate(&negative_origin);
+ }
+
+ ClipRegion {
+ origin: rect.origin,
+ main: LayerRect::new(LayerPoint::zero(), rect.size),
+ image_mask,
+ complex_clips,
+ }
+ }
+
+ pub fn create_for_clip_node_with_local_clip(local_clip: &LocalClip) -> ClipRegion {
+ let complex_clips = match local_clip {
+ &LocalClip::Rect(_) => Vec::new(),
+ &LocalClip::RoundedRect(_, ref region) => vec![region.clone()],
+ };
+ ClipRegion::create_for_clip_node(*local_clip.clip_rect(), complex_clips, None)
+ }
+}
+
+#[repr(C)]
+#[derive(Copy, Clone, Debug, PartialEq)]
+pub enum ClipMode {
+ Clip, // Pixels inside the region are visible.
+ ClipOut, // Pixels outside the region are visible.
+}
+
+impl Not for ClipMode {
+ type Output = ClipMode;
+
+ fn not(self) -> ClipMode {
+ match self {
+ ClipMode::Clip => ClipMode::ClipOut,
+ ClipMode::ClipOut => ClipMode::Clip
+ }
+ }
+}
+
+#[derive(Debug)]
+pub enum ClipSource {
+ Rectangle(LayerRect),
+ RoundedRectangle(LayerRect, BorderRadius, ClipMode),
+ Image(ImageMask),
+ /// TODO(gw): This currently only handles dashed style
+ /// clips, where the border style is dashed for both
+ /// adjacent border edges. Expand to handle dotted style
+ /// and different styles per edge.
+ BorderCorner(BorderCornerClipSource),
+}
+
+impl From<ClipRegion> for ClipSources {
+ fn from(region: ClipRegion) -> ClipSources {
+ let mut clips = Vec::new();
+
+ if let Some(info) = region.image_mask {
+ clips.push(ClipSource::Image(info));
+ }
+
+ clips.push(ClipSource::Rectangle(region.main));
+
+ for complex in region.complex_clips {
+ clips.push(ClipSource::RoundedRectangle(complex.rect, complex.radii, ClipMode::Clip));
+ }
+
+ ClipSources::new(clips)
+ }
+}
+
+#[derive(Debug)]
+pub struct ClipSources {
+ clips: Vec<ClipSource>,
+ mask_cache_info: MaskCacheInfo,
+}
+
+impl ClipSources {
+ pub fn new(clips: Vec<ClipSource>) -> ClipSources {
+ let mask_cache_info = MaskCacheInfo::new(&clips);
+
+ ClipSources {
+ clips,
+ mask_cache_info,
+ }
+ }
+
+ pub fn clips(&self) -> &[ClipSource] {
+ &self.clips
+ }
+
+ pub fn update(&mut self,
+ layer_transform: &LayerToWorldTransform,
+ gpu_cache: &mut GpuCache,
+ resource_cache: &mut ResourceCache,
+ device_pixel_ratio: f32) {
+ if self.clips.is_empty() {
+ return;
+ }
+
+ self.mask_cache_info
+ .update(&self.clips,
+ layer_transform,
+ gpu_cache,
+ device_pixel_ratio);
+
+ for clip in &self.clips {
+ if let ClipSource::Image(ref mask) = *clip {
+ resource_cache.request_image(mask.image,
+ ImageRendering::Auto,
+ None,
+ gpu_cache);
+ }
+ }
+ }
+
+ pub fn is_masking(&self) -> bool {
+ self.mask_cache_info.is_masking()
+ }
+
+ pub fn clone_mask_cache_info(&self, keep_aligned: bool) -> MaskCacheInfo {
+ if keep_aligned {
+ self.mask_cache_info.clone()
+ } else {
+ self.mask_cache_info.strip_aligned()
+ }
+ }
+}
--- a/gfx/webrender/src/clip_scroll_node.rs
+++ b/gfx/webrender/src/clip_scroll_node.rs
@@ -1,72 +1,61 @@
/* 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/. */
use api::{ClipId, DeviceIntRect, LayerPixel, LayerPoint, LayerRect, LayerSize};
use api::{LayerToScrollTransform, LayerToWorldTransform, LayerVector2D, PipelineId};
use api::{ScrollClamping, ScrollEventPhase, ScrollLocation, ScrollSensitivity, StickyFrameInfo};
use api::WorldPoint;
+use clip::{ClipRegion, ClipSources};
use clip_scroll_tree::TransformUpdateState;
use geometry::ray_intersects_rect;
-use mask_cache::{ClipRegion, ClipSource, MaskCacheInfo};
use spring::{DAMPING, STIFFNESS, Spring};
use tiling::PackedLayerIndex;
use util::{MatrixHelpers, TransformedRectKind};
#[cfg(target_os = "macos")]
const CAN_OVERSCROLL: bool = true;
#[cfg(not(target_os = "macos"))]
const CAN_OVERSCROLL: bool = false;
-#[derive(Clone, Debug)]
+#[derive(Debug)]
pub struct ClipInfo {
- /// The ClipSource for this node, which is used to generate mask_cache_info.
- pub clip_sources: Vec<ClipSource>,
-
- /// The MaskCacheInfo for this node, which is produced by processing the
- /// provided ClipSource.
- pub mask_cache_info: MaskCacheInfo,
+ /// The clips for this node.
+ pub clip_sources: ClipSources,
/// The packed layer index for this node, which is used to render a clip mask
/// for it, if necessary.
pub packed_layer_index: PackedLayerIndex,
/// The final transformed rectangle of this clipping region for this node,
/// which depends on the screen rectangle and the transformation of all of
/// the parents.
pub screen_bounding_rect: Option<(TransformedRectKind, DeviceIntRect)>,
- /// The biggest final transformed rectangle that is completely inside the
- /// clipping region for this node.
- pub screen_inner_rect: DeviceIntRect,
-
/// A rectangle which defines the rough boundaries of this clip in reference
/// frame relative coordinates (with no scroll offsets).
pub clip_rect: LayerRect,
}
impl ClipInfo {
pub fn new(clip_region: ClipRegion, packed_layer_index: PackedLayerIndex) -> ClipInfo {
let clip_rect = LayerRect::new(clip_region.origin, clip_region.main.size);
- let clip_sources = vec![ClipSource::Region(clip_region)];
ClipInfo {
- mask_cache_info: MaskCacheInfo::new(&clip_sources),
- clip_sources,
+ clip_sources: ClipSources::from(clip_region),
packed_layer_index,
screen_bounding_rect: None,
- screen_inner_rect: DeviceIntRect::zero(),
clip_rect: clip_rect,
}
}
}
-#[derive(Clone, Debug)]
+#[derive(Debug)]
pub enum NodeType {
/// A reference frame establishes a new coordinate space in the tree.
ReferenceFrame(ReferenceFrameInfo),
/// Other nodes just do clipping, but no transformation.
Clip(ClipInfo),
/// Transforms it's content, but doesn't clip it. Can also be adjusted
@@ -76,17 +65,17 @@ pub enum NodeType {
/// A special kind of node that adjusts its position based on the position
/// of its parent node and a given set of sticky positioning constraints.
/// Sticky positioned is described in the CSS Positioned Layout Module Level 3 here:
/// https://www.w3.org/TR/css-position-3/#sticky-pos
StickyFrame(StickyFrameInfo),
}
/// Contains information common among all types of ClipScrollTree nodes.
-#[derive(Clone, Debug)]
+#[derive(Debug)]
pub struct ClipScrollNode {
/// Size of the content inside the scroll region (in logical pixels)
pub content_size: LayerSize,
/// Viewing rectangle in the coordinate system of the parent reference frame.
pub local_viewport_rect: LayerRect,
/// Clip rect of this node - typically the same as viewport rect, except
--- a/gfx/webrender/src/clip_scroll_tree.rs
+++ b/gfx/webrender/src/clip_scroll_tree.rs
@@ -372,20 +372,20 @@ impl ClipScrollTree {
fn print_node(&self, id: &ClipId, pt: &mut PrintTree) {
let node = self.nodes.get(id).unwrap();
match node.node_type {
NodeType::Clip(ref info) => {
pt.new_level("Clip".to_owned());
pt.add_item(format!("screen_bounding_rect: {:?}", info.screen_bounding_rect));
- pt.add_item(format!("screen_inner_rect: {:?}", info.screen_inner_rect));
- pt.new_level(format!("Clip Sources [{}]", info.clip_sources.len()));
- for source in &info.clip_sources {
+ let clips = info.clip_sources.clips();
+ pt.new_level(format!("Clip Sources [{}]", clips.len()));
+ for source in clips {
pt.add_item(format!("{:?}", source));
}
pt.end_level();
}
NodeType::ReferenceFrame(ref info) => {
pt.new_level(format!("ReferenceFrame {:?}", info.transform));
}
NodeType::ScrollFrame(scrolling_info) => {
--- a/gfx/webrender/src/frame.rs
+++ b/gfx/webrender/src/frame.rs
@@ -4,22 +4,22 @@
use api::{BuiltDisplayList, BuiltDisplayListIter, ClipAndScrollInfo, ClipId, ColorF};
use api::{ComplexClipRegion, DeviceUintRect, DeviceUintSize, DisplayItemRef, Epoch, FilterOp};
use api::{ImageDisplayItem, ItemRange, LayerPoint, LayerRect, LayerSize, LayerToScrollTransform};
use api::{LayerVector2D, LayoutSize, LayoutTransform, LocalClip, MixBlendMode, PipelineId};
use api::{PropertyBinding, ScrollClamping, ScrollEventPhase, ScrollLayerState, ScrollLocation};
use api::{ScrollPolicy, ScrollSensitivity, SpecificDisplayItem, StackingContext, TileOffset};
use api::{TransformStyle, WorldPoint};
+use clip::ClipRegion;
use clip_scroll_tree::{ClipScrollTree, ScrollStates};
use euclid::rect;
use gpu_cache::GpuCache;
use internal_types::{FastHashMap, RendererFrame};
use frame_builder::{FrameBuilder, FrameBuilderConfig};
-use mask_cache::ClipRegion;
use profiler::{GpuCacheProfileCounters, TextureCacheProfileCounters};
use resource_cache::{ResourceCache, TiledImageMap};
use scene::{Scene, SceneProperties};
use tiling::{CompositeOps, DisplayListMap, PrimitiveFlags};
use util::{ComplexClipRegionHelpers, subtract_rect};
#[derive(Copy, Clone, PartialEq, PartialOrd, Debug, Eq, Ord)]
pub struct FrameId(pub u32);
--- a/gfx/webrender/src/frame_builder.rs
+++ b/gfx/webrender/src/frame_builder.rs
@@ -1,25 +1,25 @@
/* 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/. */
-use api::{BorderDetails, BorderDisplayItem, BoxShadowClipMode, ClipAndScrollInfo, ClipId, ColorF};
+use api::{BorderDetails, BorderDisplayItem, BorderRadius, BoxShadowClipMode, ClipAndScrollInfo, ClipId, ColorF};
use api::{DeviceIntPoint, DeviceIntRect, DeviceIntSize, DeviceUintRect, DeviceUintSize};
use api::{ExtendMode, FontInstance, FontRenderMode};
use api::{GlyphInstance, GlyphOptions, GradientStop};
use api::{ImageKey, ImageRendering, ItemRange, LayerPoint, LayerRect, LayerSize};
use api::{LayerToScrollTransform, LayerVector2D, LayoutVector2D, LineOrientation, LineStyle};
use api::{LocalClip, PipelineId, RepeatMode, ScrollSensitivity, SubpixelDirection, TextShadow};
use api::{TileOffset, TransformStyle, WorldPixel, YuvColorSpace, YuvData};
use app_units::Au;
+use clip::{ClipMode, ClipRegion, ClipSource, ClipSources};
use frame::FrameId;
use gpu_cache::GpuCache;
use internal_types::{FastHashMap, HardwareCompositeOp};
-use mask_cache::{ClipMode, ClipRegion, ClipSource, MaskCacheInfo};
use plane_split::{BspSplitter, Polygon, Splitter};
use prim_store::{GradientPrimitiveCpu, ImagePrimitiveCpu, LinePrimitive, PrimitiveKind};
use prim_store::{PrimitiveContainer, PrimitiveIndex};
use prim_store::{PrimitiveStore, RadialGradientPrimitiveCpu, TextRunMode};
use prim_store::{RectanglePrimitive, TextRunPrimitiveCpu, TextShadowPrimitiveCpu};
use prim_store::{BoxShadowPrimitiveCpu, TexelRect, YuvImagePrimitiveCpu};
use profiler::{FrameProfileCounters, GpuCacheProfileCounters, TextureCacheProfileCounters};
use render_task::{AlphaRenderItem, ClipWorkItem, RenderTask};
@@ -193,35 +193,30 @@ impl FrameBuilder {
/// Create a primitive and add it to the prim store. This method doesn't
/// add the primitive to the draw list, so can be used for creating
/// sub-primitives.
fn create_primitive(&mut self,
clip_and_scroll: ClipAndScrollInfo,
rect: &LayerRect,
local_clip: &LocalClip,
- extra_clips: &[ClipSource],
+ mut clip_sources: Vec<ClipSource>,
container: PrimitiveContainer) -> PrimitiveIndex {
self.create_clip_scroll_group_if_necessary(clip_and_scroll);
- let mut clip_sources = extra_clips.to_vec();
- if let &LocalClip::RoundedRect(_, _) = local_clip {
- clip_sources.push(ClipSource::Region(ClipRegion::create_for_local_clip(local_clip)))
+ if let &LocalClip::RoundedRect(main, region) = local_clip {
+ clip_sources.push(ClipSource::Rectangle(main));
+ clip_sources.push(ClipSource::RoundedRectangle(region.rect, region.radii, ClipMode::Clip));
}
- let clip_info = if !clip_sources.is_empty() {
- Some(MaskCacheInfo::new(&clip_sources))
- } else {
- None
- };
+ let clip_sources = ClipSources::new(clip_sources);
let prim_index = self.prim_store.add_primitive(rect,
&local_clip.clip_rect(),
clip_sources,
- clip_info,
container);
prim_index
}
/// Add an already created primitive to the draw lists.
pub fn add_primitive_to_draw_list(&mut self,
prim_index: PrimitiveIndex,
@@ -242,22 +237,22 @@ impl FrameBuilder {
}
/// Convenience interface that creates a primitive entry and adds it
/// to the draw list.
pub fn add_primitive(&mut self,
clip_and_scroll: ClipAndScrollInfo,
rect: &LayerRect,
local_clip: &LocalClip,
- extra_clips: &[ClipSource],
+ clip_sources: Vec<ClipSource>,
container: PrimitiveContainer) -> PrimitiveIndex {
let prim_index = self.create_primitive(clip_and_scroll,
rect,
local_clip,
- extra_clips,
+ clip_sources,
container);
self.add_primitive_to_draw_list(prim_index, clip_and_scroll);
prim_index
}
pub fn create_clip_scroll_group(&mut self, info: ClipAndScrollInfo) -> ClipScrollGroupIndex {
@@ -445,17 +440,17 @@ impl FrameBuilder {
// Create an empty text-shadow primitive. Insert it into
// the draw lists immediately so that it will be drawn
// before any visual text elements that are added as
// part of this text-shadow context.
let prim_index = self.add_primitive(clip_and_scroll,
&LayerRect::zero(),
local_clip,
- &[],
+ Vec::new(),
PrimitiveContainer::TextShadow(prim));
self.shadow_prim_stack.push(prim_index);
}
pub fn pop_text_shadow(&mut self) {
let prim_index = self.shadow_prim_stack
.pop()
@@ -479,17 +474,17 @@ impl FrameBuilder {
flags: PrimitiveFlags) {
let prim = RectanglePrimitive {
color: *color,
};
let prim_index = self.add_primitive(clip_and_scroll,
rect,
local_clip,
- &[],
+ Vec::new(),
PrimitiveContainer::Rectangle(prim));
match flags {
PrimitiveFlags::None => {}
PrimitiveFlags::Scrollbar(clip_id, border_radius) => {
self.scrollbar_prims.push(ScrollbarPrimitive {
prim_index,
clip_id,
@@ -535,24 +530,24 @@ impl FrameBuilder {
}
}
for shadow in fast_text_shadow_prims {
let mut line = line.clone();
line.color = shadow.color;
self.add_primitive(clip_and_scroll,
&new_rect.translate(&shadow.offset),
local_clip,
- &[],
+ Vec::new(),
PrimitiveContainer::Line(line));
}
let prim_index = self.create_primitive(clip_and_scroll,
&new_rect,
local_clip,
- &[],
+ Vec::new(),
PrimitiveContainer::Line(line));
if color.a > 0.0 {
self.add_primitive_to_draw_list(prim_index, clip_and_scroll);
}
for shadow_prim_index in &self.shadow_prim_stack {
let shadow_metadata = &mut self.prim_store.cpu_metadata[shadow_prim_index.0];
@@ -830,17 +825,17 @@ impl FrameBuilder {
};
let prim = if aligned {
PrimitiveContainer::AlignedGradient(gradient_cpu)
} else {
PrimitiveContainer::AngleGradient(gradient_cpu)
};
- self.add_primitive(clip_and_scroll, &rect, local_clip, &[], prim);
+ self.add_primitive(clip_and_scroll, &rect, local_clip, Vec::new(), prim);
}
pub fn add_radial_gradient(&mut self,
clip_and_scroll: ClipAndScrollInfo,
rect: LayerRect,
local_clip: &LocalClip,
start_center: LayerPoint,
start_radius: f32,
@@ -862,17 +857,17 @@ impl FrameBuilder {
[start_radius, end_radius, ratio_xy, pack_as_float(extend_mode as u32)].into(),
[tile_size.width, tile_size.height, tile_repeat.width, tile_repeat.height].into(),
],
};
self.add_primitive(clip_and_scroll,
&rect,
local_clip,
- &[],
+ Vec::new(),
PrimitiveContainer::RadialGradient(radial_gradient_cpu));
}
pub fn add_text(&mut self,
clip_and_scroll: ClipAndScrollInfo,
run_offset: LayoutVector2D,
rect: LayerRect,
local_clip: &LocalClip,
@@ -974,26 +969,26 @@ impl FrameBuilder {
text_prim.offset += shadow_prim.shadow.offset;
fast_text_shadow_prims.push(text_prim);
}
}
for text_prim in fast_text_shadow_prims {
self.add_primitive(clip_and_scroll,
&rect.translate(&text_prim.offset),
local_clip,
- &[],
+ Vec::new(),
PrimitiveContainer::TextRun(text_prim));
}
// Create (and add to primitive store) the primitive that will be
// used for both the visual element and also the shadow(s).
let prim_index = self.create_primitive(clip_and_scroll,
&rect,
local_clip,
- &[],
+ Vec::new(),
PrimitiveContainer::TextRun(prim));
// Only add a visual element if it can contribute to the scene.
if color.a > 0.0 {
self.add_primitive_to_draw_list(prim_index, clip_and_scroll);
}
// Now add this primitive index to all the currently active text shadow
@@ -1031,27 +1026,28 @@ impl FrameBuilder {
BoxShadowClipMode::Outset |
BoxShadowClipMode::None => (ClipMode::Clip, bs_rect),
BoxShadowClipMode::Inset => (ClipMode::ClipOut, *box_bounds),
};
let box_clip_mode = !bs_clip_mode;
// Clip the inside and then the outside of the box.
- let extra_clips = [ClipSource::Complex(bs_rect, border_radius, bs_clip_mode),
- ClipSource::Complex(*box_bounds, border_radius, box_clip_mode)];
+ let border_radius = BorderRadius::uniform(border_radius);
+ let extra_clips = vec![ClipSource::RoundedRectangle(bs_rect, border_radius, bs_clip_mode),
+ ClipSource::RoundedRectangle(*box_bounds, border_radius, box_clip_mode)];
let prim = RectanglePrimitive {
color: *color,
};
self.add_primitive(clip_and_scroll,
&rect_to_draw,
local_clip,
- &extra_clips,
+ extra_clips,
PrimitiveContainer::Rectangle(prim));
}
pub fn add_box_shadow(&mut self,
clip_and_scroll: ClipAndScrollInfo,
box_bounds: &LayerRect,
local_clip: &LocalClip,
box_offset: &LayerVector2D,
@@ -1192,36 +1188,36 @@ impl FrameBuilder {
// need a clip out of the center box.
let extra_clip_mode = match clip_mode {
BoxShadowClipMode::Outset | BoxShadowClipMode::None => ClipMode::ClipOut,
BoxShadowClipMode::Inset => ClipMode::Clip,
};
let mut extra_clips = Vec::new();
if border_radius >= 0.0 {
- extra_clips.push(ClipSource::Complex(*box_bounds,
- border_radius,
- extra_clip_mode));
+ extra_clips.push(ClipSource::RoundedRectangle(*box_bounds,
+ BorderRadius::uniform(border_radius),
+ extra_clip_mode));
}
let prim_cpu = BoxShadowPrimitiveCpu {
src_rect: *box_bounds,
bs_rect,
color: *color,
blur_radius,
border_radius,
edge_size,
inverted,
rects,
};
self.add_primitive(clip_and_scroll,
&outer_rect,
local_clip,
- extra_clips.as_slice(),
+ extra_clips,
PrimitiveContainer::BoxShadow(prim_cpu));
}
}
}
pub fn add_image(&mut self,
clip_and_scroll: ClipAndScrollInfo,
rect: LayerRect,
@@ -1245,17 +1241,17 @@ impl FrameBuilder {
tile_spacing.height ].into(),
sub_rect_block,
],
};
self.add_primitive(clip_and_scroll,
&rect,
local_clip,
- &[],
+ Vec::new(),
PrimitiveContainer::Image(prim_cpu));
}
pub fn add_yuv_image(&mut self,
clip_and_scroll: ClipAndScrollInfo,
rect: LayerRect,
clip_rect: &LocalClip,
yuv_data: YuvData,
@@ -1276,17 +1272,17 @@ impl FrameBuilder {
color_space,
image_rendering,
gpu_block: [rect.size.width, rect.size.height, 0.0, 0.0].into(),
};
self.add_primitive(clip_and_scroll,
&rect,
clip_rect,
- &[],
+ Vec::new(),
PrimitiveContainer::YuvImage(prim_cpu));
}
/// Compute the contribution (bounding rectangles, and resources) of layers and their
/// primitives in screen space.
fn build_layer_screen_rects_and_cull_layers(&mut self,
screen_rect: &DeviceIntRect,
clip_scroll_tree: &mut ClipScrollTree,
@@ -1762,41 +1758,20 @@ impl<'a> LayerRectCalculationAndCullingP
packed_layer.set_rect(&local_viewport_rect,
self.screen_rect,
self.device_pixel_ratio)
} else {
None
};
- let inner_rect = match node_clip_info.screen_bounding_rect {
- Some((_, rect)) => rect,
- None => DeviceIntRect::zero(),
- };
- node_clip_info.screen_inner_rect = inner_rect;
-
- let bounds = node_clip_info.mask_cache_info.update(&node_clip_info.clip_sources,
- &transform,
- self.gpu_cache,
- self.device_pixel_ratio);
-
- node_clip_info.screen_inner_rect = bounds.inner.as_ref()
- .and_then(|inner| inner.device_rect.intersection(&inner_rect))
- .unwrap_or(DeviceIntRect::zero());
-
- for clip_source in &node_clip_info.clip_sources {
- if let Some(mask) = clip_source.image_mask() {
- // We don't add the image mask for resolution, because
- // layer masks are resolved later.
- self.resource_cache.request_image(mask.image,
- ImageRendering::Auto,
- None,
- self.gpu_cache);
- }
- }
+ node_clip_info.clip_sources.update(&transform,
+ self.gpu_cache,
+ self.resource_cache,
+ self.device_pixel_ratio);
}
}
fn recalculate_clip_scroll_groups(&mut self) {
debug!("recalculate_clip_scroll_groups");
for ref mut group in &mut self.frame_builder.clip_scroll_group_store {
let scroll_node = &self.clip_scroll_tree.nodes[&group.scroll_node_id];
let clip_node = &self.clip_scroll_tree.nodes[&group.clip_node_id];
@@ -1895,34 +1870,30 @@ impl<'a> LayerRectCalculationAndCullingP
current_id = node.parent;
let clip = match node.node_type {
NodeType::ReferenceFrame(ref info) => {
// if the transform is non-aligned, bake the next LCCR into the clip mask
next_node_needs_region_mask |= !info.transform.preserves_2d_axis_alignment();
continue
},
- NodeType::Clip(ref clip) if clip.mask_cache_info.is_masking() => clip,
+ NodeType::Clip(ref clip) if clip.clip_sources.is_masking() => clip,
_ => continue,
};
// apply the screen bounds of the clip node
//Note: these are based on the local combined viewport, so can be tighter
if let Some((_kind, ref screen_rect)) = clip.screen_bounding_rect {
bounding_rect = match bounding_rect.intersection(screen_rect) {
Some(rect) => rect,
None => return None,
}
}
- let clip_info = if next_node_needs_region_mask {
- clip.mask_cache_info.clone()
- } else {
- clip.mask_cache_info.strip_aligned()
- };
+ let clip_info = clip.clip_sources.clone_mask_cache_info(next_node_needs_region_mask);
// apply the outer device bounds of the clip stack
if let Some(ref outer) = clip_info.bounds.outer {
bounding_rect = match bounding_rect.intersection(&outer.device_rect) {
Some(rect) => rect,
None => return None,
}
}
@@ -2001,50 +1972,53 @@ impl<'a> LayerRectCalculationAndCullingP
display_list,
TextRunMode::Normal,
&mut self.render_tasks);
stacking_context.screen_bounds = stacking_context.screen_bounds.union(&prim_screen_rect);
stacking_context.isolated_items_bounds = stacking_context.isolated_items_bounds.union(&prim_local_rect);
// Try to create a mask if we may need to.
- if !self.current_clip_stack.is_empty() || prim_metadata.clip_cache_info.is_some() {
+ let clip_task = if prim_metadata.clips.is_masking() {
+ let info = prim_metadata.clips.clone_mask_cache_info(false);
+
+ // Take into account the actual clip info of the primitive, and
+ // mutate the current bounds accordingly.
+ let mask_rect = match info.bounds.outer {
+ Some(ref outer) => {
+ match prim_screen_rect.intersection(&outer.device_rect) {
+ Some(rect) => rect,
+ None => continue,
+ }
+ }
+ _ => prim_screen_rect,
+ };
+
+ let extra = (packed_layer_index, info);
+
+ RenderTask::new_mask(None,
+ mask_rect,
+ &self.current_clip_stack,
+ Some(extra),
+ prim_screen_rect)
+ } else if !self.current_clip_stack.is_empty() {
// If the primitive doesn't have a specific clip, key the task ID off the
// stacking context. This means that two primitives which are only clipped
// by the stacking context stack can share clip masks during render task
// assignment to targets.
- let (cache_key, mask_rect, extra) = match prim_metadata.clip_cache_info {
- Some(ref info) => {
- // Take into account the actual clip info of the primitive, and
- // mutate the current bounds accordingly.
- let mask_rect = match info.bounds.outer {
- Some(ref outer) => {
- match prim_screen_rect.intersection(&outer.device_rect) {
- Some(rect) => rect,
- None => continue,
- }
- }
- _ => prim_screen_rect,
- };
- (None,
- mask_rect,
- Some((packed_layer_index, info.strip_aligned())))
- }
- None => {
- (Some(clip_and_scroll.clip_node_id()),
- clip_bounds,
- None)
- }
- };
- let clip_task = RenderTask::new_mask(cache_key,
- mask_rect,
- &self.current_clip_stack,
- extra);
- let render_tasks = &mut self.render_tasks;
- prim_metadata.clip_task_id = clip_task.map(|clip_task| {
- render_tasks.add(clip_task)
- });
- }
+ RenderTask::new_mask(Some(clip_and_scroll.clip_node_id()),
+ clip_bounds,
+ &self.current_clip_stack,
+ None,
+ prim_screen_rect)
+ } else {
+ None
+ };
+
+ let render_tasks = &mut self.render_tasks;
+ prim_metadata.clip_task_id = clip_task.map(|clip_task| {
+ render_tasks.add(clip_task)
+ });
self.profile_counters.visible_primitives.inc();
}
}
}
--- a/gfx/webrender/src/lib.rs
+++ b/gfx/webrender/src/lib.rs
@@ -45,16 +45,17 @@ extern crate lazy_static;
#[macro_use]
extern crate log;
#[macro_use]
extern crate bitflags;
#[macro_use]
extern crate thread_profiler;
mod border;
+mod clip;
mod clip_scroll_node;
mod clip_scroll_tree;
mod debug_colors;
mod debug_font_data;
mod debug_render;
#[cfg(feature = "debugger")]
mod debug_server;
mod device;
--- a/gfx/webrender/src/mask_cache.rs
+++ b/gfx/webrender/src/mask_cache.rs
@@ -1,116 +1,22 @@
/* 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/. */
-use api::{BorderRadius, ComplexClipRegion, DeviceIntRect, ImageMask, LayerPoint, LayerRect};
-use api::{LayerSize, LayerToWorldTransform, LocalClip};
+use api::{DeviceIntRect, ImageMask, LayerPoint, LayerRect};
+use api::{LayerSize, LayerToWorldTransform};
use border::BorderCornerClipSource;
+use clip::{ClipMode, ClipSource};
use gpu_cache::{GpuCache, GpuCacheHandle, ToGpuBlocks};
use prim_store::{CLIP_DATA_GPU_BLOCKS, ClipData, ImageMaskData};
-use util::{ComplexClipRegionHelpers, TransformedRect};
-use std::ops::Not;
+use util::{extract_inner_rect_safe, TransformedRect};
const MAX_CLIP: f32 = 1000000.0;
-#[derive(Clone, Debug)]
-pub struct ClipRegion {
- pub origin: LayerPoint,
- pub main: LayerRect,
- pub image_mask: Option<ImageMask>,
- pub complex_clips: Vec<ComplexClipRegion>,
-}
-
-impl ClipRegion {
- pub fn create_for_clip_node(rect: LayerRect,
- mut complex_clips: Vec<ComplexClipRegion>,
- mut image_mask: Option<ImageMask>)
- -> ClipRegion {
- // All the coordinates we receive are relative to the stacking context, but we want
- // to convert them to something relative to the origin of the clip.
- let negative_origin = -rect.origin.to_vector();
- if let Some(ref mut image_mask) = image_mask {
- image_mask.rect = image_mask.rect.translate(&negative_origin);
- }
-
- for complex_clip in complex_clips.iter_mut() {
- complex_clip.rect = complex_clip.rect.translate(&negative_origin);
- }
-
- ClipRegion {
- origin: rect.origin,
- main: LayerRect::new(LayerPoint::zero(), rect.size),
- image_mask,
- complex_clips,
- }
- }
-
- pub fn create_for_clip_node_with_local_clip(local_clip: &LocalClip) -> ClipRegion {
- let complex_clips = match local_clip {
- &LocalClip::Rect(_) => Vec::new(),
- &LocalClip::RoundedRect(_, ref region) => vec![region.clone()],
- };
- ClipRegion::create_for_clip_node(*local_clip.clip_rect(), complex_clips, None)
- }
-
- pub fn create_for_local_clip(local_clip: &LocalClip) -> ClipRegion {
- let complex_clips = match local_clip {
- &LocalClip::Rect(_) => Vec::new(),
- &LocalClip::RoundedRect(_, ref region) => vec![region.clone()],
- };
-
- ClipRegion {
- origin: LayerPoint::zero(),
- main: *local_clip.clip_rect(),
- image_mask: None,
- complex_clips,
- }
- }
-}
-
-#[repr(C)]
-#[derive(Copy, Clone, Debug, PartialEq)]
-pub enum ClipMode {
- Clip, // Pixels inside the region are visible.
- ClipOut, // Pixels outside the region are visible.
-}
-
-impl Not for ClipMode {
- type Output = ClipMode;
-
- fn not(self) -> ClipMode {
- match self {
- ClipMode::Clip => ClipMode::ClipOut,
- ClipMode::ClipOut => ClipMode::Clip
- }
- }
-}
-
-#[derive(Clone, Debug)]
-pub enum ClipSource {
- Complex(LayerRect, f32, ClipMode),
- Region(ClipRegion),
- /// TODO(gw): This currently only handles dashed style
- /// clips, where the border style is dashed for both
- /// adjacent border edges. Expand to handle dotted style
- /// and different styles per edge.
- BorderCorner(BorderCornerClipSource),
-}
-
-impl ClipSource {
- pub fn image_mask(&self) -> Option<ImageMask> {
- match *self {
- ClipSource::Complex(..) |
- ClipSource::BorderCorner(..) => None,
- ClipSource::Region(ref region) => region.image_mask,
- }
- }
-}
-
#[derive(Debug, Copy, Clone)]
pub struct ClipAddressRange {
pub location: GpuCacheHandle,
item_count: usize,
}
impl ClipAddressRange {
fn new(count: usize) -> Self {
@@ -203,27 +109,26 @@ impl MaskCacheInfo {
let mut border_corners = Vec::new();
let mut complex_clip_count = 0;
let mut layer_clip_count = 0;
// Work out how much clip data space we need to allocate
// and if we have an image mask.
for clip in clips {
match *clip {
- ClipSource::Complex(..) => {
+ ClipSource::RoundedRectangle(..) => {
complex_clip_count += 1;
}
- ClipSource::Region(ref region) => {
- if let Some(info) = region.image_mask {
- debug_assert!(image.is_none()); // TODO(gw): Support >1 image mask!
- image = Some((info, GpuCacheHandle::new()));
- }
- complex_clip_count += region.complex_clips.len();
+ ClipSource::Rectangle(..) => {
layer_clip_count += 1;
}
+ ClipSource::Image(image_mask) => {
+ debug_assert!(image.is_none()); // TODO(gw): Support >1 image mask!
+ image = Some((image_mask, GpuCacheHandle::new()));
+ }
ClipSource::BorderCorner(ref source) => {
border_corners.push((source.clone(), GpuCacheHandle::new()));
}
}
}
MaskCacheInfo {
complex_clip_range: ClipAddressRange::new(complex_clip_count),
@@ -238,112 +143,89 @@ impl MaskCacheInfo {
}
pub fn update(&mut self,
sources: &[ClipSource],
transform: &LayerToWorldTransform,
gpu_cache: &mut GpuCache,
device_pixel_ratio: f32)
-> &MaskBounds {
-
// Step[1] - compute the local bounds
//TODO: move to initialization stage?
if self.bounds.inner.is_none() {
let mut local_rect = Some(LayerRect::new(LayerPoint::new(-MAX_CLIP, -MAX_CLIP),
LayerSize::new(2.0 * MAX_CLIP, 2.0 * MAX_CLIP)));
- let mut local_inner: Option<LayerRect> = None;
+ let mut local_inner = local_rect;
let mut has_clip_out = false;
let has_border_clip = !self.border_corners.is_empty();
for source in sources {
match *source {
- ClipSource::Complex(rect, radius, mode) => {
+ ClipSource::Image(ref mask) => {
+ if !mask.repeat {
+ local_rect = local_rect.and_then(|r| r.intersection(&mask.rect));
+ }
+ local_inner = None;
+ }
+ ClipSource::Rectangle(rect) => {
+ local_rect = local_rect.and_then(|r| r.intersection(&rect));
+ local_inner = local_inner.and_then(|r| r.intersection(&rect));
+ }
+ ClipSource::RoundedRectangle(ref rect, ref radius, mode) => {
// Once we encounter a clip-out, we just assume the worst
// case clip mask size, for now.
if mode == ClipMode::ClipOut {
has_clip_out = true;
break;
}
- local_rect = local_rect.and_then(|r| r.intersection(&rect));
- local_inner = ComplexClipRegion::new(rect, BorderRadius::uniform(radius))
- .get_inner_rect_safe();
- }
- ClipSource::Region(ref region) => {
- local_rect = local_rect.and_then(|r| r.intersection(®ion.main));
- local_inner = match region.image_mask {
- Some(ref mask) => {
- if !mask.repeat {
- local_rect = local_rect.and_then(|r| r.intersection(&mask.rect));
- }
- None
- },
- None => local_rect,
- };
+
+ local_rect = local_rect.and_then(|r| r.intersection(rect));
- for clip in ®ion.complex_clips {
- local_rect = local_rect.and_then(|r| r.intersection(&clip.rect));
- local_inner = local_inner.and_then(|r| clip.get_inner_rect_safe()
- .and_then(|ref inner| r.intersection(inner)));
- }
+ let inner_rect = extract_inner_rect_safe(rect, radius);
+ local_inner = local_inner.and_then(|r| inner_rect.and_then(|ref inner| r.intersection(inner)));
}
ClipSource::BorderCorner{..} => {}
}
}
// Work out the type of mask geometry we have, based on the
// list of clip sources above.
self.bounds = if has_clip_out || has_border_clip {
// For clip-out, the mask rect is not known.
MaskBounds {
outer: None,
inner: Some(LayerRect::zero().into()),
}
} else {
- // TODO(gw): local inner is only valid if there's a single clip (for now).
- // This can be improved in the future, with some proper
- // rectangle region handling.
- if sources.len() > 1 {
- local_inner = None;
- }
-
MaskBounds {
outer: Some(local_rect.unwrap_or(LayerRect::zero()).into()),
inner: Some(local_inner.unwrap_or(LayerRect::zero()).into()),
}
};
}
// Step[2] - update GPU cache data
if let Some(block_count) = self.complex_clip_range.get_block_count() {
if let Some(mut request) = gpu_cache.request(&mut self.complex_clip_range.location) {
for source in sources {
- match *source {
- ClipSource::Complex(rect, radius, mode) => {
- let data = ClipData::uniform(rect, radius, mode);
- data.write(&mut request);
- }
- ClipSource::Region(ref region) => {
- for clip in ®ion.complex_clips {
- let data = ClipData::from_clip_region(&clip);
- data.write(&mut request);
- }
- }
- ClipSource::BorderCorner{..} => {}
+ if let ClipSource::RoundedRectangle(ref rect, ref radius, mode) = *source {
+ let data = ClipData::rounded_rect(rect, radius, mode);
+ data.write(&mut request);
}
}
assert_eq!(request.close(), block_count);
}
}
if let Some(block_count) = self.layer_clip_range.get_block_count() {
if let Some(mut request) = gpu_cache.request(&mut self.layer_clip_range.location) {
for source in sources {
- if let ClipSource::Region(ref region) = *source {
- let data = ClipData::uniform(region.main, 0.0, ClipMode::Clip);
+ if let ClipSource::Rectangle(rect) = *source {
+ let data = ClipData::uniform(rect, 0.0, ClipMode::Clip);
data.write(&mut request);
}
}
assert_eq!(request.close(), block_count);
}
}
for &mut (ref mut border_source, ref mut gpu_location) in &mut self.border_corners {
--- a/gfx/webrender/src/prim_store.rs
+++ b/gfx/webrender/src/prim_store.rs
@@ -1,22 +1,22 @@
/* 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/. */
use api::{BuiltDisplayList, ColorF, ComplexClipRegion, DeviceIntRect, DeviceIntSize, DevicePoint};
-use api::{ExtendMode, FontRenderMode, GlyphInstance, GradientStop};
+use api::{BorderRadius, ExtendMode, FontRenderMode, GlyphInstance, GradientStop};
use api::{ImageKey, ImageRendering, ItemRange, LayerPoint, LayerRect, LayerSize, TextShadow};
use api::{GlyphKey, LayerToWorldTransform, TileOffset, YuvColorSpace, YuvFormat};
use api::{device_length, FontInstance, LayerVector2D, LineOrientation, LineStyle};
use app_units::Au;
use border::BorderCornerInstance;
+use clip::{ClipMode, ClipSources};
use euclid::{Size2D};
use gpu_cache::{GpuCacheAddress, GpuBlockData, GpuCache, GpuCacheHandle, GpuDataRequest, ToGpuBlocks};
-use mask_cache::{ClipMode, ClipRegion, ClipSource, MaskCacheInfo};
use renderer::MAX_VERTEX_TEXTURE_WIDTH;
use render_task::{RenderTask, RenderTaskId, RenderTaskTree};
use resource_cache::{ImageProperties, ResourceCache};
use std::{mem, usize};
use util::{pack_as_float, TransformedRect, recycle_vec};
pub const CLIP_DATA_GPU_BLOCKS: usize = 10;
@@ -129,18 +129,17 @@ impl GpuCacheHandle {
address.v as i32 * MAX_VERTEX_TEXTURE_WIDTH as i32 + address.u as i32
}
}
// TODO(gw): Pack the fields here better!
#[derive(Debug)]
pub struct PrimitiveMetadata {
pub opacity: PrimitiveOpacity,
- pub clips: Vec<ClipSource>,
- pub clip_cache_info: Option<MaskCacheInfo>,
+ pub clips: ClipSources,
pub prim_kind: PrimitiveKind,
pub cpu_prim_index: SpecificPrimitiveIndex,
pub gpu_location: GpuCacheHandle,
// An optional render task that is a dependency of
// drawing this primitive. For instance, box shadows
// use this to draw a portion of the box shadow to
// a render target to reduce the number of pixels
// that the box-shadow shader needs to run on. For
@@ -660,57 +659,56 @@ pub struct ClipData {
rect: ClipRect,
top_left: ClipCorner,
top_right: ClipCorner,
bottom_left: ClipCorner,
bottom_right: ClipCorner,
}
impl ClipData {
- pub fn from_clip_region(clip: &ComplexClipRegion) -> ClipData {
+ pub fn rounded_rect(rect: &LayerRect, radii: &BorderRadius, mode: ClipMode) -> ClipData {
ClipData {
rect: ClipRect {
- rect: clip.rect,
- // TODO(gw): Support other clip modes for regions?
- mode: ClipMode::Clip as u32 as f32,
+ rect: *rect,
+ mode: mode as u32 as f32,
},
top_left: ClipCorner {
rect: LayerRect::new(
- LayerPoint::new(clip.rect.origin.x, clip.rect.origin.y),
- LayerSize::new(clip.radii.top_left.width, clip.radii.top_left.height)),
- outer_radius_x: clip.radii.top_left.width,
- outer_radius_y: clip.radii.top_left.height,
+ LayerPoint::new(rect.origin.x, rect.origin.y),
+ LayerSize::new(radii.top_left.width, radii.top_left.height)),
+ outer_radius_x: radii.top_left.width,
+ outer_radius_y: radii.top_left.height,
inner_radius_x: 0.0,
inner_radius_y: 0.0,
},
top_right: ClipCorner {
rect: LayerRect::new(
- LayerPoint::new(clip.rect.origin.x + clip.rect.size.width - clip.radii.top_right.width, clip.rect.origin.y),
- LayerSize::new(clip.radii.top_right.width, clip.radii.top_right.height)),
- outer_radius_x: clip.radii.top_right.width,
- outer_radius_y: clip.radii.top_right.height,
+ LayerPoint::new(rect.origin.x + rect.size.width - radii.top_right.width, rect.origin.y),
+ LayerSize::new(radii.top_right.width, radii.top_right.height)),
+ outer_radius_x: radii.top_right.width,
+ outer_radius_y: radii.top_right.height,
inner_radius_x: 0.0,
inner_radius_y: 0.0,
},
bottom_left: ClipCorner {
rect: LayerRect::new(
- LayerPoint::new(clip.rect.origin.x, clip.rect.origin.y + clip.rect.size.height - clip.radii.bottom_left.height),
- LayerSize::new(clip.radii.bottom_left.width, clip.radii.bottom_left.height)),
- outer_radius_x: clip.radii.bottom_left.width,
- outer_radius_y: clip.radii.bottom_left.height,
+ LayerPoint::new(rect.origin.x, rect.origin.y + rect.size.height - radii.bottom_left.height),
+ LayerSize::new(radii.bottom_left.width, radii.bottom_left.height)),
+ outer_radius_x: radii.bottom_left.width,
+ outer_radius_y: radii.bottom_left.height,
inner_radius_x: 0.0,
inner_radius_y: 0.0,
},
bottom_right: ClipCorner {
rect: LayerRect::new(
- LayerPoint::new(clip.rect.origin.x + clip.rect.size.width - clip.radii.bottom_right.width,
- clip.rect.origin.y + clip.rect.size.height - clip.radii.bottom_right.height),
- LayerSize::new(clip.radii.bottom_right.width, clip.radii.bottom_right.height)),
- outer_radius_x: clip.radii.bottom_right.width,
- outer_radius_y: clip.radii.bottom_right.height,
+ LayerPoint::new(rect.origin.x + rect.size.width - radii.bottom_right.width,
+ rect.origin.y + rect.size.height - radii.bottom_right.height),
+ LayerSize::new(radii.bottom_right.width, radii.bottom_right.height)),
+ outer_radius_x: radii.bottom_right.width,
+ outer_radius_y: radii.bottom_right.height,
inner_radius_x: 0.0,
inner_radius_y: 0.0,
},
}
}
pub fn uniform(rect: LayerRect, radius: f32, mode: ClipMode) -> ClipData {
ClipData {
@@ -814,28 +812,26 @@ impl PrimitiveStore {
cpu_box_shadows: recycle_vec(self.cpu_box_shadows),
cpu_lines: recycle_vec(self.cpu_lines),
}
}
pub fn add_primitive(&mut self,
local_rect: &LayerRect,
local_clip_rect: &LayerRect,
- clips: Vec<ClipSource>,
- clip_info: Option<MaskCacheInfo>,
+ clips: ClipSources,
container: PrimitiveContainer) -> PrimitiveIndex {
let prim_index = self.cpu_metadata.len();
self.cpu_bounding_rects.push(None);
let metadata = match container {
PrimitiveContainer::Rectangle(rect) => {
let metadata = PrimitiveMetadata {
opacity: PrimitiveOpacity::from_alpha(rect.color.a),
clips,
- clip_cache_info: clip_info,
prim_kind: PrimitiveKind::Rectangle,
cpu_prim_index: SpecificPrimitiveIndex(self.cpu_rectangles.len()),
gpu_location: GpuCacheHandle::new(),
render_task_id: None,
clip_task_id: None,
local_rect: *local_rect,
local_clip_rect: *local_clip_rect,
};
@@ -843,119 +839,112 @@ impl PrimitiveStore {
self.cpu_rectangles.push(rect);
metadata
}
PrimitiveContainer::Line(line) => {
let metadata = PrimitiveMetadata {
opacity: PrimitiveOpacity::translucent(),
clips,
- clip_cache_info: clip_info,
prim_kind: PrimitiveKind::Line,
cpu_prim_index: SpecificPrimitiveIndex(self.cpu_lines.len()),
gpu_location: GpuCacheHandle::new(),
render_task_id: None,
clip_task_id: None,
local_rect: *local_rect,
local_clip_rect: *local_clip_rect,
};
self.cpu_lines.push(line);
metadata
}
PrimitiveContainer::TextRun(text_cpu) => {
let metadata = PrimitiveMetadata {
opacity: PrimitiveOpacity::translucent(),
clips,
- clip_cache_info: clip_info,
prim_kind: PrimitiveKind::TextRun,
cpu_prim_index: SpecificPrimitiveIndex(self.cpu_text_runs.len()),
gpu_location: GpuCacheHandle::new(),
render_task_id: None,
clip_task_id: None,
local_rect: *local_rect,
local_clip_rect: *local_clip_rect,
};
self.cpu_text_runs.push(text_cpu);
metadata
}
PrimitiveContainer::TextShadow(text_shadow) => {
let metadata = PrimitiveMetadata {
opacity: PrimitiveOpacity::translucent(),
clips,
- clip_cache_info: clip_info,
prim_kind: PrimitiveKind::TextShadow,
cpu_prim_index: SpecificPrimitiveIndex(self.cpu_text_shadows.len()),
gpu_location: GpuCacheHandle::new(),
render_task_id: None,
clip_task_id: None,
local_rect: *local_rect,
local_clip_rect: *local_clip_rect,
};
self.cpu_text_shadows.push(text_shadow);
metadata
}
PrimitiveContainer::Image(image_cpu) => {
let metadata = PrimitiveMetadata {
opacity: PrimitiveOpacity::translucent(),
clips,
- clip_cache_info: clip_info,
prim_kind: PrimitiveKind::Image,
cpu_prim_index: SpecificPrimitiveIndex(self.cpu_images.len()),
gpu_location: GpuCacheHandle::new(),
render_task_id: None,
clip_task_id: None,
local_rect: *local_rect,
local_clip_rect: *local_clip_rect,
};
self.cpu_images.push(image_cpu);
metadata
}
PrimitiveContainer::YuvImage(image_cpu) => {
let metadata = PrimitiveMetadata {
opacity: PrimitiveOpacity::opaque(),
clips,
- clip_cache_info: clip_info,
prim_kind: PrimitiveKind::YuvImage,
cpu_prim_index: SpecificPrimitiveIndex(self.cpu_yuv_images.len()),
gpu_location: GpuCacheHandle::new(),
render_task_id: None,
clip_task_id: None,
local_rect: *local_rect,
local_clip_rect: *local_clip_rect,
};
self.cpu_yuv_images.push(image_cpu);
metadata
}
PrimitiveContainer::Border(border_cpu) => {
let metadata = PrimitiveMetadata {
opacity: PrimitiveOpacity::translucent(),
clips,
- clip_cache_info: clip_info,
prim_kind: PrimitiveKind::Border,
cpu_prim_index: SpecificPrimitiveIndex(self.cpu_borders.len()),
gpu_location: GpuCacheHandle::new(),
render_task_id: None,
clip_task_id: None,
local_rect: *local_rect,
local_clip_rect: *local_clip_rect,
};
self.cpu_borders.push(border_cpu);
metadata
}
PrimitiveContainer::AlignedGradient(gradient_cpu) => {
let metadata = PrimitiveMetadata {
opacity: PrimitiveOpacity::translucent(),
clips,
- clip_cache_info: clip_info,
prim_kind: PrimitiveKind::AlignedGradient,
cpu_prim_index: SpecificPrimitiveIndex(self.cpu_gradients.len()),
gpu_location: GpuCacheHandle::new(),
render_task_id: None,
clip_task_id: None,
local_rect: *local_rect,
local_clip_rect: *local_clip_rect,
};
@@ -963,17 +952,16 @@ impl PrimitiveStore {
self.cpu_gradients.push(gradient_cpu);
metadata
}
PrimitiveContainer::AngleGradient(gradient_cpu) => {
let metadata = PrimitiveMetadata {
// TODO: calculate if the gradient is actually opaque
opacity: PrimitiveOpacity::translucent(),
clips,
- clip_cache_info: clip_info,
prim_kind: PrimitiveKind::AngleGradient,
cpu_prim_index: SpecificPrimitiveIndex(self.cpu_gradients.len()),
gpu_location: GpuCacheHandle::new(),
render_task_id: None,
clip_task_id: None,
local_rect: *local_rect,
local_clip_rect: *local_clip_rect,
};
@@ -981,34 +969,32 @@ impl PrimitiveStore {
self.cpu_gradients.push(gradient_cpu);
metadata
}
PrimitiveContainer::RadialGradient(radial_gradient_cpu) => {
let metadata = PrimitiveMetadata {
// TODO: calculate if the gradient is actually opaque
opacity: PrimitiveOpacity::translucent(),
clips,
- clip_cache_info: clip_info,
prim_kind: PrimitiveKind::RadialGradient,
cpu_prim_index: SpecificPrimitiveIndex(self.cpu_radial_gradients.len()),
gpu_location: GpuCacheHandle::new(),
render_task_id: None,
clip_task_id: None,
local_rect: *local_rect,
local_clip_rect: *local_clip_rect,
};
self.cpu_radial_gradients.push(radial_gradient_cpu);
metadata
}
PrimitiveContainer::BoxShadow(box_shadow) => {
let metadata = PrimitiveMetadata {
opacity: PrimitiveOpacity::translucent(),
clips,
- clip_cache_info: clip_info,
prim_kind: PrimitiveKind::BoxShadow,
cpu_prim_index: SpecificPrimitiveIndex(self.cpu_box_shadows.len()),
gpu_location: GpuCacheHandle::new(),
render_task_id: None,
clip_task_id: None,
local_rect: *local_rect,
local_clip_rect: *local_clip_rect,
};
@@ -1083,32 +1069,20 @@ impl PrimitiveStore {
device_pixel_ratio,
display_list,
TextRunMode::Shadow,
render_tasks);
}
}
let metadata = &mut self.cpu_metadata[prim_index.0];
-
- if let Some(ref mut clip_info) = metadata.clip_cache_info {
- clip_info.update(&metadata.clips, layer_transform, gpu_cache, device_pixel_ratio);
-
- //TODO-LCCR: we could tighten up the `local_clip_rect` here
- // but that would require invalidating the whole GPU block
-
- for clip in &metadata.clips {
- if let ClipSource::Region(ClipRegion{ image_mask: Some(ref mask), .. }, ..) = *clip {
- resource_cache.request_image(mask.image,
- ImageRendering::Auto,
- None,
- gpu_cache);
- }
- }
- }
+ metadata.clips.update(layer_transform,
+ gpu_cache,
+ resource_cache,
+ device_pixel_ratio);
match metadata.prim_kind {
PrimitiveKind::Rectangle |
PrimitiveKind::Border |
PrimitiveKind::Line => {}
PrimitiveKind::BoxShadow => {
// TODO(gw): Account for zoom factor!
// Here, we calculate the size of the patch required in order
--- a/gfx/webrender/src/render_task.rs
+++ b/gfx/webrender/src/render_task.rs
@@ -239,17 +239,18 @@ impl RenderTask {
location: RenderTaskLocation::Dynamic(None, screen_rect.size),
kind: RenderTaskKind::Readback(screen_rect),
}
}
pub fn new_mask(key: Option<ClipId>,
task_rect: DeviceIntRect,
raw_clips: &[ClipWorkItem],
- extra_clip: Option<ClipWorkItem>)
+ extra_clip: Option<ClipWorkItem>,
+ prim_rect: DeviceIntRect)
-> Option<RenderTask> {
// Filter out all the clip instances that don't contribute to the result
let mut inner_rect = Some(task_rect);
let clips: Vec<_> = raw_clips.iter()
.chain(extra_clip.iter())
.filter(|&&(_, ref clip_info)| {
// If this clip does not contribute to a mask, then ensure
// it gets filtered out here. Otherwise, if a mask is
@@ -278,23 +279,30 @@ impl RenderTask {
}
// TODO(gw): This optimization is very conservative for now.
// For now, only draw optimized geometry if it is
// a single aligned rect mask with rounded corners.
// In the future, we'll expand this to handle the
// more complex types of clip mask geometry.
let mut geometry_kind = MaskGeometryKind::Default;
- if inner_rect.is_some() && clips.len() == 1 {
- let (_, ref info) = clips[0];
- if info.border_corners.is_empty() &&
- info.image.is_none() &&
- info.complex_clip_range.get_count() == 1 &&
- info.layer_clip_range.get_count() == 0 {
- geometry_kind = MaskGeometryKind::CornersOnly;
+ if let Some(inner_rect) = inner_rect {
+ // If the inner rect completely contains the primitive
+ // rect, then this mask can't affect the primitive.
+ if inner_rect.contains_rect(&prim_rect) {
+ return None;
+ }
+ if clips.len() == 1 {
+ let (_, ref info) = clips[0];
+ if info.border_corners.is_empty() &&
+ info.image.is_none() &&
+ info.complex_clip_range.get_count() == 1 &&
+ info.layer_clip_range.get_count() == 0 {
+ geometry_kind = MaskGeometryKind::CornersOnly;
+ }
}
}
Some(RenderTask {
cache_key: key.map(RenderTaskKey::CacheMask),
children: Vec::new(),
location: RenderTaskLocation::Dynamic(None, task_rect.size),
kind: RenderTaskKind::CacheMask(CacheMaskTask {
--- a/gfx/webrender/src/util.rs
+++ b/gfx/webrender/src/util.rs
@@ -262,31 +262,22 @@ impl TransformedRect {
#[inline(always)]
pub fn pack_as_float(value: u32) -> f32 {
value as f32 + 0.5
}
pub trait ComplexClipRegionHelpers {
- /// Return an aligned rectangle that is inside the clip region and doesn't intersect
- /// any of the bounding rectangles of the rounded corners.
- fn get_inner_rect_safe(&self) -> Option<LayoutRect>;
/// Return the approximately largest aligned rectangle that is fully inside
/// the provided clip region.
fn get_inner_rect_full(&self) -> Option<LayoutRect>;
}
impl ComplexClipRegionHelpers for ComplexClipRegion {
- fn get_inner_rect_safe(&self) -> Option<LayoutRect> {
- // value of `k==1.0` is used for extraction of the corner rectangles
- // see `SEGMENT_CORNER_*` in `clip_shared.glsl`
- extract_inner_rect_impl(&self.rect, &self.radii, 1.0)
- }
-
fn get_inner_rect_full(&self) -> Option<LayoutRect> {
// this `k` optimal for a simple case of all border radii being equal
let k = 1.0 - 0.5 * FRAC_1_SQRT_2; // could be nicely approximated to `0.3`
extract_inner_rect_impl(&self.rect, &self.radii, k)
}
}
#[inline]
@@ -305,16 +296,25 @@ fn extract_inner_rect_impl<U>(rect: &Typ
if xl <= xr && yt <= yb {
Some(TypedRect::new(TypedPoint2D::new(rect.origin.x + xl, rect.origin.y + yt),
TypedSize2D::new(xr-xl, yb-yt)))
} else {
None
}
}
+/// Return an aligned rectangle that is inside the clip region and doesn't intersect
+/// any of the bounding rectangles of the rounded corners.
+pub fn extract_inner_rect_safe<U>(rect: &TypedRect<f32, U>,
+ radii: &BorderRadius) -> Option<TypedRect<f32, U>> {
+ // value of `k==1.0` is used for extraction of the corner rectangles
+ // see `SEGMENT_CORNER_*` in `clip_shared.glsl`
+ extract_inner_rect_impl(rect, radii, 1.0)
+}
+
/// Consumes the old vector and returns a new one that may reuse the old vector's allocated
/// memory.
pub fn recycle_vec<T>(mut old_vec: Vec<T>) -> Vec<T> {
if old_vec.capacity() > 2 * old_vec.len() {
// Avoid reusing the buffer if it is a lot larger than it needs to be. This prevents
// a frame with exceptionally large allocations to cause subsequent frames to retain
// more memory than they need.
return Vec::with_capacity(old_vec.len());