Compare commits

...

4 Commits

Author SHA1 Message Date
mr. m
94b2a4b67e no-bug: Add border render support 2026-06-20 16:03:48 +02:00
mr. m
cf98127a5e Merge branch 'dev' into feat/9324
Signed-off-by: mr. m <91018726+mr-cheffy@users.noreply.github.com>
2026-06-19 08:29:45 +02:00
mr. m
b7a8e79299 no-bug: Apply squircles to elements 2026-06-06 14:08:36 +02:00
mr. m
0048f21a52 no-bug: Squircles support 2026-06-04 01:37:46 +02:00
20 changed files with 6769 additions and 9 deletions

View File

@@ -95,6 +95,9 @@
- name: browser.search.widget.new
value: true
- name: layout.css.corner-shape.enabled
value: true
# Disabled from https://searchfox.org/firefox-main/rev/d6bfff43852356ca98af848b4705d37f8d41856f/modules/libpref/init/StaticPrefList.yaml#2008
# Only enabled for windows, doesn't really fit inside Zen.
- name: browser.startup.preXulSkeletonUI

View File

@@ -131,10 +131,10 @@
</box>
<html:input type="range" value="0.4" step="0.001" id="PanelUI-zen-gradient-generator-opacity"
#ifdef XP_MACOSX
max="0.9"
max="0.8"
min="0.30"
#else
max="0.9"
max="0.8"
min="0.25"
#endif
/>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,15 @@
diff --git a/servo/components/style/values/generics/border.rs b/servo/components/style/values/generics/border.rs
--- a/servo/components/style/values/generics/border.rs
+++ b/servo/components/style/values/generics/border.rs
@@ -296,9 +296,9 @@
pub fn all(s: S) -> Self {
Self {
top_left: s.clone(),
top_right: s.clone(),
bottom_right: s.clone(),
- bottom_left: s.clone(),
+ bottom_left: s,
}
}
}

View File

@@ -0,0 +1,38 @@
diff --git a/gfx/wr/glsl-to-cxx/src/hir.rs b/gfx/wr/glsl-to-cxx/src/hir.rs
--- a/gfx/wr/glsl-to-cxx/src/hir.rs
+++ b/gfx/wr/glsl-to-cxx/src/hir.rs
@@ -3531,10 +3531,11 @@
None,
Type::new(Float),
vec![Type::new(Vec2)],
);
declare_function(state, "pow", None, Type::new(Vec3), vec![Type::new(Vec3)]);
+ declare_function(state, "pow", None, Type::new(Vec2), vec![Type::new(Vec2)]);
declare_function(state, "pow", None, Type::new(Float), vec![Type::new(Float)]);
declare_function(state, "exp", None, Type::new(Float), vec![Type::new(Float)]);
declare_function(state, "exp2", None, Type::new(Float), vec![Type::new(Float)]);
declare_function(state, "log", None, Type::new(Float), vec![Type::new(Float)]);
declare_function(state, "log2", None, Type::new(Float), vec![Type::new(Float)]);
diff --git a/gfx/wr/swgl/src/glsl.h b/gfx/wr/swgl/src/glsl.h
--- a/gfx/wr/swgl/src/glsl.h
+++ b/gfx/wr/swgl/src/glsl.h
@@ -800,10 +800,18 @@
Float pow(Float x, Float y) {
return if_then_else((x == 0) | (x == 1), x, approx_pow2(approx_log2(x) * y));
}
+vec2 pow(vec2 a, vec2 b) {
+ return vec2(pow(a.x, b.x), pow(a.y, b.y));
+}
+
+vec2_scalar pow(vec2_scalar a, vec2_scalar b) {
+ return vec2_scalar(pow(a.x, b.x), pow(a.y, b.y));
+}
+
#define exp __glsl_exp
SI float exp(float x) { return expf(x); }
Float exp(Float y) {

View File

@@ -0,0 +1,19 @@
diff --git a/gfx/wr/swgl/src/glsl.h b/gfx/wr/swgl/src/glsl.h
--- a/gfx/wr/swgl/src/glsl.h
+++ b/gfx/wr/swgl/src/glsl.h
@@ -1611,10 +1611,14 @@
vec3_scalar make_vec3(const vec2_scalar& v, float z) {
return vec3_scalar{v.x, v.y, z};
}
+vec3_scalar make_vec3(float x, const vec2_scalar& v) {
+ return vec3_scalar{x, v.x, v.y};
+}
+
vec3_scalar make_vec3(float x, float y, float z) {
return vec3_scalar{x, y, z};
}
vec3_scalar make_vec3(int32_t x, int32_t y, float z) {

View File

@@ -0,0 +1,22 @@
diff --git a/gfx/wr/swgl/src/glsl.h b/gfx/wr/swgl/src/glsl.h
--- a/gfx/wr/swgl/src/glsl.h
+++ b/gfx/wr/swgl/src/glsl.h
@@ -1599,10 +1599,17 @@
x += a.x;
y += a.y;
z += a.z;
return *this;
}
+
+ vec3& operator*=(Float a) {
+ x *= a;
+ y *= a;
+ z *= a;
+ return *this;
+ }
};
vec3_scalar force_scalar(const vec3& v) {
return vec3_scalar{force_scalar(v.x), force_scalar(v.y), force_scalar(v.z)};
}

View File

@@ -0,0 +1,20 @@
diff --git a/gfx/wr/swgl/src/glsl.h b/gfx/wr/swgl/src/glsl.h
--- a/gfx/wr/swgl/src/glsl.h
+++ b/gfx/wr/swgl/src/glsl.h
@@ -469,10 +469,15 @@
vec2_scalar_ref& operator=(const vec2_scalar& a) {
x = a.x;
y = a.y;
return *this;
}
+ vec2_scalar_ref& operator+=(vec2_scalar a) {
+ x += a.x;
+ y += a.y;
+ return *this;
+ }
vec2_scalar_ref& operator*=(vec2_scalar a) {
x *= a.x;
y *= a.y;
return *this;
}

View File

@@ -0,0 +1,67 @@
diff --git a/gfx/wr/glsl-to-cxx/src/hir.rs b/gfx/wr/glsl-to-cxx/src/hir.rs
--- a/gfx/wr/glsl-to-cxx/src/hir.rs
+++ b/gfx/wr/glsl-to-cxx/src/hir.rs
@@ -3537,10 +3537,12 @@
declare_function(state, "pow", None, Type::new(Float), vec![Type::new(Float)]);
declare_function(state, "exp", None, Type::new(Float), vec![Type::new(Float)]);
declare_function(state, "exp2", None, Type::new(Float), vec![Type::new(Float)]);
declare_function(state, "log", None, Type::new(Float), vec![Type::new(Float)]);
declare_function(state, "log2", None, Type::new(Float), vec![Type::new(Float)]);
+ declare_function(state, "isnan", None, Type::new(Bool), vec![Type::new(Float)]);
+ declare_function(state, "isinf", None, Type::new(Bool), vec![Type::new(Float)]);
for t in &[Float, Vec2] {
// recip is non-standard
declare_function(
state,
"recip",
diff --git a/gfx/wr/swgl/src/glsl.h b/gfx/wr/swgl/src/glsl.h
--- a/gfx/wr/swgl/src/glsl.h
+++ b/gfx/wr/swgl/src/glsl.h
@@ -205,10 +205,46 @@
#else
return (Float){sqrtf(v.x), sqrtf(v.y), sqrtf(v.z), sqrtf(v.w)};
#endif
}
+// NOTE: the Bool type is actually int under the hood,
+// and is used for bitwise return value masking in the
+// generated code ("ret_mask" variable).
+//
+// The ret_mask is initialized to -1 (0xffffffff), and
+// is then subsequently masked with condition results.
+//
+// If we use the boolean result directly here (0 or 1),
+// the bitwise AND ends up removing just one bit from
+// the mask, and it doesn't work.
+//
+// Taking the negative transforms 1 (single bit) into -1
+// (all bits 1), and correctly broadcasts the boolean
+// result into all bits of the ret_mask.
+//
+// If the condition is false, 0 becomes -0 which is the
+// same bit pattern for integers (all bits 0).
+
+SI Bool isnan(Float v) {
+ return (Bool){
+ -(fpclassify(v.x) == FP_NAN),
+ -(fpclassify(v.y) == FP_NAN),
+ -(fpclassify(v.z) == FP_NAN),
+ -(fpclassify(v.w) == FP_NAN)
+ };
+}
+
+SI Bool isinf(Float v) {
+ return (Bool){
+ -(fpclassify(v.x) == FP_INFINITE),
+ -(fpclassify(v.y) == FP_INFINITE),
+ -(fpclassify(v.z) == FP_INFINITE),
+ -(fpclassify(v.w) == FP_INFINITE)
+ };
+}
+
SI float recip(float x) {
#if USE_SSE2
return _mm_cvtss_f32(_mm_rcp_ss(_mm_set_ss(x)));
#else
return 1.0f / x;

View File

@@ -0,0 +1,49 @@
diff --git a/gfx/wr/webrender/res/debug.glsl b/gfx/wr/webrender/res/debug.glsl
new file mode 100644
--- /dev/null
+++ b/gfx/wr/webrender/res/debug.glsl
@@ -0,0 +1,43 @@
+/* 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/. */
+
+// Display a signed distance field as color
+//
+// It will be orange outside the shape (positive distance), and blue
+// inside (negative distance).
+//
+// Color will cycle every 10px.
+//
+// The shape outline (distance = 0) is drawn as a thin white outline.
+//
+// NaNs and infinite values will be drawn as red and yellow respectively.
+//
+// Example usage:
+//
+// #include debug
+//
+// void main(void) {
+// float d = compute_some_distance_in_pixels(...);
+// oFragColor = debug_sdf(d);
+// }
+//
+vec4 debug_sdf(float d) {
+ if (isnan(d)) {
+ return vec4(1.0, 0.0, 0.0, 1.0);
+ }
+ if (isinf(d)) {
+ return vec4(1.0, 1.0, 0.0, 1.0);
+ }
+
+ vec3 color = (d > 0.0) ? vec3(0.9, 0.6, 0.3) : vec3(0.6, 0.8, 1.0);
+ color *= 1.0 - exp(-0.32 * abs(d));
+ color *= fract(d / 10.0) * 0.4 + 0.6;
+#ifdef SWGL
+ // SWGL doesn't support smoothstep() for now
+ color = mix(color, vec3(1.0), step(abs(d), 2.0));
+#else
+ color = mix(color, vec3(1.0), smoothstep(2.0, 0.0, abs(d)));
+#endif
+ return vec4(color, 1.0);
+}

View File

@@ -0,0 +1,456 @@
diff --git a/gfx/wr/wrench/reftests/clip/clip-superellipse.png b/gfx/wr/wrench/reftests/clip/clip-superellipse.png
new file mode 100644
index 0000000000000000000000000000000000000000..4470f8b707c255bc3e4eb026368945267ee895e6
GIT binary patch
literal 7953
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
G@_zvPNe@N<
literal 0
Hc$@<O00001
diff --git a/gfx/wr/wrench/reftests/clip/clip-superellipse.yaml b/gfx/wr/wrench/reftests/clip/clip-superellipse.yaml
new file mode 100644
--- /dev/null
+++ b/gfx/wr/wrench/reftests/clip/clip-superellipse.yaml
@@ -0,0 +1,174 @@
+---
+root:
+ items:
+ - type: clip
+ id: 100
+ complex:
+ - rect: [20, 20, 100, 100]
+ radius:
+ top-left: [32, 16]
+ top-right: [32, 16]
+ bottom-right: [32, 16]
+ bottom-left: [32, 16]
+ shape-top-left: 0.5
+ shape-top-right: +Inf
+ shape-bottom-left: -2.1
+ shape-bottom-right: 0
+ - type: clip-chain
+ id: 200
+ clips: [100]
+ - type: rect
+ bounds: [20, 20, 100, 100]
+ color: red
+ clip-chain: 200
+
+ - type: clip
+ id: 101
+ complex:
+ - rect: [130, 20, 100, 100]
+ radius:
+ top-left: [32, 16]
+ top-right: [32, 16]
+ bottom-right: [32, 16]
+ bottom-left: [32, 16]
+ shape-top-left: 0.5
+ shape-top-right: +Inf
+ shape-bottom-left: -2.1
+ shape-bottom-right: 0
+ clip-mode: clip-out
+ - type: clip-chain
+ id: 201
+ clips: [101]
+ - type: rect
+ bounds: [130, 20, 100, 100]
+ color: green
+ clip-chain: 201
+
+ - type: clip
+ id: 102
+ complex:
+ - rect: [20, 130, 100, 100]
+ radius:
+ top-left: [16, 32]
+ top-right: [16, 32]
+ bottom-right: [16, 32]
+ bottom-left: [16, 32]
+ shape-top-left: 0.5
+ shape-top-right: +Inf
+ shape-bottom-left: -2.1
+ shape-bottom-right: 0
+ - type: clip-chain
+ id: 202
+ clips: [102]
+ - type: rect
+ bounds: [20, 130, 100, 100]
+ color: red
+ clip-chain: 202
+
+ - type: clip
+ id: 103
+ complex:
+ - rect: [130, 130, 100, 100]
+ radius:
+ top-left: [16, 32]
+ top-right: [16, 32]
+ bottom-right: [16, 32]
+ bottom-left: [16, 32]
+ shape-top-left: 0.5
+ shape-top-right: +Inf
+ shape-bottom-left: -2.1
+ shape-bottom-right: 0
+ clip-mode: clip-out
+ - type: clip-chain
+ id: 203
+ clips: [103]
+ - type: rect
+ bounds: [130, 130, 100, 100]
+ color: green
+ clip-chain: 203
+
+ - type: clip
+ id: 104
+ complex:
+ - rect: [20, 240, 100, 100]
+ radius:
+ top-left: [128, 32]
+ top-right: [128, 32]
+ bottom-right: [128, 32]
+ bottom-left: [128, 32]
+ shape-top-left: 0.5
+ shape-top-right: +Inf
+ shape-bottom-left: -2.1
+ shape-bottom-right: 0
+ - type: clip-chain
+ id: 204
+ clips: [104]
+ - type: rect
+ bounds: [20, 240, 100, 100]
+ color: red
+ clip-chain: 204
+
+ - type: clip
+ id: 105
+ complex:
+ - rect: [130, 240, 100, 100]
+ radius:
+ top-left: [128, 32]
+ top-right: [128, 32]
+ bottom-right: [128, 32]
+ bottom-left: [128, 32]
+ shape-top-left: 0.5
+ shape-top-right: +Inf
+ shape-bottom-left: -2.1
+ shape-bottom-right: 0
+ clip-mode: clip-out
+ - type: clip-chain
+ id: 205
+ clips: [105]
+ - type: rect
+ bounds: [130, 240, 100, 100]
+ color: green
+ clip-chain: 205
+
+ - type: clip
+ id: 106
+ complex:
+ - rect: [20, 350, 100, 100]
+ radius:
+ top-left: [32, 128]
+ top-right: [32, 128]
+ bottom-right: [32, 128]
+ bottom-left: [32, 128]
+ shape-top-left: 0.5
+ shape-top-right: +Inf
+ shape-bottom-left: -2.1
+ shape-bottom-right: 0
+ - type: clip-chain
+ id: 206
+ clips: [106]
+ - type: rect
+ bounds: [20, 350, 100, 100]
+ color: red
+ clip-chain: 206
+
+ - type: clip
+ id: 107
+ complex:
+ - rect: [130, 350, 100, 100]
+ radius:
+ top-left: [32, 128]
+ top-right: [32, 128]
+ bottom-right: [32, 128]
+ bottom-left: [32, 128]
+ shape-top-left: 0.5
+ shape-top-right: +Inf
+ shape-bottom-left: -2.1
+ shape-bottom-right: 0
+ clip-mode: clip-out
+ - type: clip-chain
+ id: 207
+ clips: [107]
+ - type: rect
+ bounds: [130, 350, 100, 100]
+ color: green
+ clip-chain: 207
diff --git a/gfx/wr/wrench/reftests/clip/reftest.list b/gfx/wr/wrench/reftests/clip/reftest.list
--- a/gfx/wr/wrench/reftests/clip/reftest.list
+++ b/gfx/wr/wrench/reftests/clip/reftest.list
@@ -1,8 +1,9 @@
platform(linux,mac) == border-with-rounded-clip.yaml border-with-rounded-clip.png
fuzzy-if(platform(swgl),1,4) == clip-mode.yaml clip-mode.png
fuzzy-if(platform(swgl),1,80) == clip-ellipse.yaml clip-ellipse.png
+fuzzy-if(platform(android),128,200) fuzzy-if(platform(swgl),1,350) == clip-superellipse.yaml clip-superellipse.png
fuzzy(1,1000) platform(linux,mac) == clip-45-degree-rotation.yaml clip-45-degree-rotation-ref.png
== clip-3d-transform.yaml clip-3d-transform-ref.yaml
fuzzy(1,4) == clip-corner-overlap.yaml clip-corner-overlap-ref.yaml
== custom-clip-chain-node-ancestors.yaml custom-clip-chain-node-ancestors-ref.yaml
== fixed-position-clipping.yaml fixed-position-clipping-ref.yaml
diff --git a/gfx/wr/wrench/reftests/mask/reftest.list b/gfx/wr/wrench/reftests/mask/reftest.list
--- a/gfx/wr/wrench/reftests/mask/reftest.list
+++ b/gfx/wr/wrench/reftests/mask/reftest.list
@@ -14,5 +14,6 @@
platform(linux,mac) == checkerboard.yaml checkerboard.png
skip_on(android,device) fuzzy(2,1900) == checkerboard.yaml checkerboard-tiling.yaml # Fails on a Pixel2
== missing-mask.yaml missing-mask-ref.yaml
platform(linux) == scaled-filter-raster-root.yaml scaled-filter-raster-root.png
platform(linux,mac) == mask-multiple-coord-systems.yaml mask-multiple-coord-systems.png
+fuzzy(1,10) fuzzy-if(platform(swgl),5,100) == shaped-corners.yaml shaped-corners.png
diff --git a/gfx/wr/wrench/reftests/mask/shaped-corners.png b/gfx/wr/wrench/reftests/mask/shaped-corners.png
new file mode 100644
index 0000000000000000000000000000000000000000..0599a1f93a7d3564c6da950908fe495c98216f7c
GIT binary patch
literal 2026
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
TV>Bg#Z@5WtKp0!@_p|UHon4m#
literal 0
Hc$@<O00001
diff --git a/gfx/wr/wrench/reftests/mask/shaped-corners.yaml b/gfx/wr/wrench/reftests/mask/shaped-corners.yaml
new file mode 100644
--- /dev/null
+++ b/gfx/wr/wrench/reftests/mask/shaped-corners.yaml
@@ -0,0 +1,12 @@
+---
+root:
+ items:
+ - type: clip
+ id: 2
+ complex:
+ - rect: [10, 10, 200, 200]
+ radius: [200, 200, 200, 200, 8.2, 0, -2.8, +Inf]
+ - type: rect
+ clip-chain: [2]
+ bounds: [10, 10, 200, 200]
+ color: blue
diff --git a/gfx/wr/wrench/src/yaml_helper.rs b/gfx/wr/wrench/src/yaml_helper.rs
--- a/gfx/wr/wrench/src/yaml_helper.rs
+++ b/gfx/wr/wrench/src/yaml_helper.rs
@@ -206,10 +206,12 @@
impl YamlHelper for Yaml {
fn as_f32(&self) -> Option<f32> {
match *self {
Yaml::Integer(iv) => Some(iv as f32),
Yaml::Real(ref sv) => f32::from_str(sv.as_str()).ok(),
+ Yaml::String(ref sv) if sv == "+Inf" => Some(f32::INFINITY),
+ Yaml::String(ref sv) if sv == "-Inf" => Some(f32::NEG_INFINITY),
_ => None,
}
}
fn as_force_f32(&self) -> Option<f32> {
@@ -483,24 +485,48 @@
shape_top_right: 1.0,
shape_bottom_left: 1.0,
shape_bottom_right: 1.0,
})
}
+ Yaml::Array(ref array) if array.len() == 8 => {
+ let top_left = array[0].as_border_radius_component();
+ let top_right = array[1].as_border_radius_component();
+ let bottom_left = array[2].as_border_radius_component();
+ let bottom_right = array[3].as_border_radius_component();
+ let shape_top_left = array[4].as_f32().unwrap();
+ let shape_top_right = array[5].as_f32().unwrap();
+ let shape_bottom_left = array[6].as_f32().unwrap();
+ let shape_bottom_right = array[7].as_f32().unwrap();
+ Some(BorderRadius {
+ top_left,
+ top_right,
+ bottom_left,
+ bottom_right,
+ shape_top_left,
+ shape_top_right,
+ shape_bottom_left,
+ shape_bottom_right,
+ })
+ }
Yaml::Hash(_) => {
let top_left = self["top-left"].as_border_radius_component();
let top_right = self["top-right"].as_border_radius_component();
let bottom_left = self["bottom-left"].as_border_radius_component();
let bottom_right = self["bottom-right"].as_border_radius_component();
+ let shape_top_left = self["shape-top-left"].as_f32().unwrap_or(1.0);
+ let shape_top_right = self["shape-top-right"].as_f32().unwrap_or(1.0);
+ let shape_bottom_left = self["shape-bottom-left"].as_f32().unwrap_or(1.0);
+ let shape_bottom_right = self["shape-bottom-right"].as_f32().unwrap_or(1.0);
Some(BorderRadius {
top_left,
top_right,
bottom_left,
bottom_right,
- shape_top_left: 1.0,
- shape_top_right: 1.0,
- shape_bottom_left: 1.0,
- shape_bottom_right: 1.0,
+ shape_top_left,
+ shape_top_right,
+ shape_bottom_left,
+ shape_bottom_right,
})
}
_ => {
panic!("Invalid border radius specified: {:?}", self);
}

View File

@@ -0,0 +1,592 @@
diff --git a/gfx/wr/webrender/res/border_shared.glsl b/gfx/wr/webrender/res/border_shared.glsl
new file mode 100644
--- /dev/null
+++ b/gfx/wr/webrender/res/border_shared.glsl
@@ -0,0 +1,47 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include gpu_buffer
+
+#define SEGMENT_TOP_LEFT 0
+#define SEGMENT_TOP_RIGHT 1
+#define SEGMENT_BOTTOM_RIGHT 2
+#define SEGMENT_BOTTOM_LEFT 3
+#define SEGMENT_LEFT 4
+#define SEGMENT_TOP 5
+#define SEGMENT_RIGHT 6
+#define SEGMENT_BOTTOM 7
+
+#ifdef WR_VERTEX_SHADER
+
+PER_INSTANCE in vec2 aTaskOrigin;
+PER_INSTANCE in int aFlags;
+PER_INSTANCE in int aGpuDataAddress;
+PER_INSTANCE in vec4 aClipParams1;
+PER_INSTANCE in vec4 aClipParams2;
+
+struct BorderInstanceGpuData {
+ vec4 rect;
+ vec4 color0;
+ vec4 color1;
+ vec2 widths;
+ vec2 radii;
+ float shape;
+};
+
+BorderInstanceGpuData fetch_gpu_data(int index) {
+ BorderInstanceGpuData data;
+
+ vec4 texels[5] = fetch_from_gpu_buffer_5f(index);
+ data.rect = texels[0];
+ data.color0 = texels[1];
+ data.color1 = texels[2];
+ data.widths = texels[3].xy;
+ data.radii = texels[3].zw;
+ data.shape = texels[4].x;
+
+ return data;
+}
+
+#endif
diff --git a/gfx/wr/webrender/res/cs_border_segment.glsl b/gfx/wr/webrender/res/cs_border_segment.glsl
--- a/gfx/wr/webrender/res/cs_border_segment.glsl
+++ b/gfx/wr/webrender/res/cs_border_segment.glsl
@@ -1,10 +1,10 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-#include shared,rect,ellipse
+#include shared,rect,border_shared,ellipse
// For edges, the colors are the same. For corners, these
// are the colors of each edge making up the corner.
flat varying mediump vec4 vColor00;
flat varying mediump vec4 vColor01;
@@ -44,19 +44,10 @@
flat varying mediump vec4 vClipParams2;
// Local space position
varying highp vec2 vPos;
-#define SEGMENT_TOP_LEFT 0
-#define SEGMENT_TOP_RIGHT 1
-#define SEGMENT_BOTTOM_RIGHT 2
-#define SEGMENT_BOTTOM_LEFT 3
-#define SEGMENT_LEFT 4
-#define SEGMENT_TOP 5
-#define SEGMENT_RIGHT 6
-#define SEGMENT_BOTTOM 7
-
// Border styles as defined in webrender_api/types.rs
#define BORDER_STYLE_NONE 0
#define BORDER_STYLE_SOLID 1
#define BORDER_STYLE_DOUBLE 2
#define BORDER_STYLE_DOTTED 3
@@ -72,20 +63,10 @@
#define CLIP_DASH_EDGE 2
#define CLIP_DOT 3
#ifdef WR_VERTEX_SHADER
-PER_INSTANCE in vec2 aTaskOrigin;
-PER_INSTANCE in vec4 aRect;
-PER_INSTANCE in vec4 aColor0;
-PER_INSTANCE in vec4 aColor1;
-PER_INSTANCE in int aFlags;
-PER_INSTANCE in vec2 aWidths;
-PER_INSTANCE in vec2 aRadii;
-PER_INSTANCE in vec4 aClipParams1;
-PER_INSTANCE in vec4 aClipParams2;
-
vec2 get_outer_corner_scale(int segment) {
vec2 p;
switch (segment) {
case SEGMENT_TOP_LEFT:
@@ -153,16 +134,18 @@
return result;
}
void main(void) {
+ BorderInstanceGpuData data = fetch_gpu_data(aGpuDataAddress);
+
int segment = aFlags & 0xff;
int style0 = (aFlags >> 8) & 0xff;
int style1 = (aFlags >> 16) & 0xff;
int clip_mode = (aFlags >> 24) & 0x0f;
- vec2 size = aRect.zw - aRect.xy;
+ vec2 size = data.rect.zw - data.rect.xy;
vec2 outer_scale = get_outer_corner_scale(segment);
vec2 outer = outer_scale * size;
vec2 clip_sign = 1.0 - 2.0 * outer_scale;
// Set some flags used by the FS to determine the
@@ -176,19 +159,19 @@
edge_axis = ivec2(0, 1);
edge_reference = outer;
break;
case SEGMENT_TOP_RIGHT:
edge_axis = ivec2(1, 0);
- edge_reference = vec2(outer.x - aWidths.x, outer.y);
+ edge_reference = vec2(outer.x - data.widths.x, outer.y);
break;
case SEGMENT_BOTTOM_RIGHT:
edge_axis = ivec2(0, 1);
- edge_reference = outer - aWidths;
+ edge_reference = outer - data.widths;
break;
case SEGMENT_BOTTOM_LEFT:
edge_axis = ivec2(1, 0);
- edge_reference = vec2(outer.x, outer.y - aWidths.y);
+ edge_reference = vec2(outer.x, outer.y - data.widths.y);
break;
case SEGMENT_TOP:
case SEGMENT_BOTTOM:
edge_axis = ivec2(1, 1);
break;
@@ -199,23 +182,23 @@
}
vSegmentClipMode = vec2(float(segment), float(clip_mode));
vStyleEdgeAxis = vec4(float(style0), float(style1), float(edge_axis.x), float(edge_axis.y));
- vPartialWidths = vec4(aWidths / 3.0, aWidths / 2.0);
+ vPartialWidths = vec4(data.widths / 3.0, data.widths / 2.0);
vPos = size * aPosition.xy;
- vec4[2] color0 = get_colors_for_side(aColor0, style0);
+ vec4[2] color0 = get_colors_for_side(data.color0, style0);
vColor00 = color0[0];
vColor01 = color0[1];
- vec4[2] color1 = get_colors_for_side(aColor1, style1);
+ vec4[2] color1 = get_colors_for_side(data.color1, style1);
vColor10 = color1[0];
vColor11 = color1[1];
- vClipCenter_Sign = vec4(outer + clip_sign * aRadii, clip_sign);
- vClipRadii = vec4(aRadii, max(aRadii - aWidths, 0.0));
- vColorLine = vec4(outer, aWidths.y * -clip_sign.y, aWidths.x * clip_sign.x);
- vEdgeReference = vec4(edge_reference, edge_reference + aWidths);
+ vClipCenter_Sign = vec4(outer + clip_sign * data.radii, clip_sign);
+ vClipRadii = vec4(data.radii, max(data.radii - data.widths, 0.0));
+ vColorLine = vec4(outer, data.widths.y * -clip_sign.y, data.widths.x * clip_sign.x);
+ vEdgeReference = vec4(edge_reference, edge_reference + data.widths);
vClipParams1 = aClipParams1;
vClipParams2 = aClipParams2;
// For the case of dot and dash clips, optimize the number of pixels that
// are hit to just include the dot itself.
@@ -234,17 +217,17 @@
// This is a gross approximation which works out because dashes don't have
// a strong curvature and we will overshoot by inflating the geometry by
// this amount on each side (sqrt(2) * length(dash) would be enough and we
// compute 2 * approx_length(dash)).
float dash_length = length(aClipParams1.xy - aClipParams2.xy);
- float width = max(aWidths.x, aWidths.y);
+ float width = max(data.widths.x, data.widths.y);
// expand by a small amout for AA just like we do for dots.
vec2 r = vec2(max(dash_length, width)) + 2.0;
vPos = clamp(vPos, center - r, center + r);
}
- gl_Position = uTransform * vec4(aTaskOrigin + aRect.xy + vPos, 0.0, 1.0);
+ gl_Position = uTransform * vec4(aTaskOrigin + data.rect.xy + vPos, 0.0, 1.0);
}
#endif
#ifdef WR_FRAGMENT_SHADER
vec4 evaluate_color_for_style_in_corner(
diff --git a/gfx/wr/webrender/res/cs_border_solid.glsl b/gfx/wr/webrender/res/cs_border_solid.glsl
--- a/gfx/wr/webrender/res/cs_border_solid.glsl
+++ b/gfx/wr/webrender/res/cs_border_solid.glsl
@@ -1,10 +1,10 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-#include shared,rect,ellipse
+#include shared,rect,border_shared,ellipse
#define DONT_MIX 0
#define MIX_AA 1
#define MIX_NO_AA 2
@@ -37,27 +37,12 @@
flat varying highp vec2 vVerticalClipRadii;
// Local space position
varying highp vec2 vPos;
-#define SEGMENT_TOP_LEFT 0
-#define SEGMENT_TOP_RIGHT 1
-#define SEGMENT_BOTTOM_RIGHT 2
-#define SEGMENT_BOTTOM_LEFT 3
-
#ifdef WR_VERTEX_SHADER
-PER_INSTANCE in vec2 aTaskOrigin;
-PER_INSTANCE in vec4 aRect;
-PER_INSTANCE in vec4 aColor0;
-PER_INSTANCE in vec4 aColor1;
-PER_INSTANCE in int aFlags;
-PER_INSTANCE in vec2 aWidths;
-PER_INSTANCE in vec2 aRadii;
-PER_INSTANCE in vec4 aClipParams1;
-PER_INSTANCE in vec4 aClipParams2;
-
vec2 get_outer_corner_scale(int segment) {
vec2 p;
switch (segment) {
case SEGMENT_TOP_LEFT:
@@ -80,15 +65,17 @@
return p;
}
void main(void) {
+ BorderInstanceGpuData data = fetch_gpu_data(aGpuDataAddress);
+
int segment = aFlags & 0xff;
bool do_aa = ((aFlags >> 24) & 0xf0) != 0;
vec2 outer_scale = get_outer_corner_scale(segment);
- vec2 size = aRect.zw - aRect.xy;
+ vec2 size = data.rect.zw - data.rect.xy;
vec2 outer = outer_scale * size;
vec2 clip_sign = 1.0 - 2.0 * outer_scale;
int mix_colors;
switch (segment) {
@@ -105,15 +92,15 @@
}
vMixColors.x = mix_colors;
vPos = size * aPosition.xy;
- vColor0 = aColor0;
- vColor1 = aColor1;
- vClipCenter_Sign = vec4(outer + clip_sign * aRadii, clip_sign);
- vClipRadii = vec4(aRadii, max(aRadii - aWidths, 0.0));
- vColorLine = vec4(outer, aWidths.y * -clip_sign.y, aWidths.x * clip_sign.x);
+ vColor0 = data.color0;
+ vColor1 = data.color1;
+ vClipCenter_Sign = vec4(outer + clip_sign * data.radii, clip_sign);
+ vClipRadii = vec4(data.radii, max(data.radii - data.widths, 0.0));
+ vColorLine = vec4(outer, data.widths.y * -clip_sign.y, data.widths.x * clip_sign.x);
vec2 horizontal_clip_sign = vec2(-clip_sign.x, clip_sign.y);
vHorizontalClipCenter_Sign = vec4(aClipParams1.xy +
horizontal_clip_sign * aClipParams1.zw,
horizontal_clip_sign);
@@ -123,11 +110,11 @@
vVerticalClipCenter_Sign = vec4(aClipParams2.xy +
vertical_clip_sign * aClipParams2.zw,
vertical_clip_sign);
vVerticalClipRadii = aClipParams2.zw;
- gl_Position = uTransform * vec4(aTaskOrigin + aRect.xy + vPos, 0.0, 1.0);
+ gl_Position = uTransform * vec4(aTaskOrigin + data.rect.xy + vPos, 0.0, 1.0);
}
#endif
#ifdef WR_FRAGMENT_SHADER
void main(void) {
diff --git a/gfx/wr/webrender/src/border.rs b/gfx/wr/webrender/src/border.rs
--- a/gfx/wr/webrender/src/border.rs
+++ b/gfx/wr/webrender/src/border.rs
@@ -6,13 +6,14 @@
use api::{NormalBorder as ApiNormalBorder, RepeatMode};
use api::units::*;
use crate::clip::ClipNodeId;
use crate::ellipse::Ellipse;
use euclid::vec2;
+use crate::renderer::GpuBufferBuilderF;
use crate::scene_building::SceneBuilder;
use crate::spatial_tree::SpatialNodeIndex;
-use crate::gpu_types::{BorderInstance, BorderSegment, BrushFlags};
+use crate::gpu_types::{BorderInstance, BorderInstanceGpuData, BorderSegment, BrushFlags};
use crate::prim_store::{BorderSegmentInfo, BrushSegment, NinePatchDescriptor};
use crate::prim_store::borders::NormalBorderPrim;
use crate::util::{lerp, RectHelpers};
use crate::internal_types::LayoutPrimitiveInfo;
use crate::segment::EdgeMask;
@@ -125,10 +126,11 @@
#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
pub struct BorderSegmentCacheKey {
pub size: LayoutSizeAu,
pub radius: LayoutSizeAu,
+ pub shape: u32,
pub side0: BorderSideAu,
pub side1: BorderSideAu,
pub segment: BorderSegment,
pub do_aa: bool,
pub h_adjacent_corner_outer: LayoutPointAu,
@@ -762,10 +764,11 @@
),
border.left,
border.top,
LayoutSize::new(widths.left, widths.top),
border.radius.top_left,
+ border.radius.shape_top_left,
BorderSegment::TopLeft,
EdgeMask::TOP | EdgeMask::LEFT,
rect.top_right(),
border.radius.top_right,
rect.bottom_left(),
@@ -789,10 +792,11 @@
),
border.top,
border.right,
LayoutSize::new(widths.right, widths.top),
border.radius.top_right,
+ border.radius.shape_top_right,
BorderSegment::TopRight,
EdgeMask::TOP | EdgeMask::RIGHT,
rect.min,
border.radius.top_left,
rect.max,
@@ -816,10 +820,11 @@
),
border.right,
border.bottom,
LayoutSize::new(widths.right, widths.bottom),
border.radius.bottom_right,
+ border.radius.shape_bottom_right,
BorderSegment::BottomRight,
EdgeMask::BOTTOM | EdgeMask::RIGHT,
rect.bottom_left(),
border.radius.bottom_left,
rect.top_right(),
@@ -843,10 +848,11 @@
),
border.bottom,
border.left,
LayoutSize::new(widths.left, widths.bottom),
border.radius.bottom_left,
+ border.radius.shape_bottom_left,
BorderSegment::BottomLeft,
EdgeMask::BOTTOM | EdgeMask::LEFT,
rect.max,
border.radius.bottom_right,
rect.min,
@@ -881,30 +887,37 @@
color1: ColorF,
segment: BorderSegment,
instances: &mut Vec<BorderInstance>,
widths: DeviceSize,
radius: DeviceSize,
+ shape: f32,
do_aa: bool,
h_adjacent_corner_outer: DevicePoint,
h_adjacent_corner_radius: DeviceSize,
v_adjacent_corner_outer: DevicePoint,
v_adjacent_corner_radius: DeviceSize,
+ gpu_buffer_builder: &mut GpuBufferBuilderF,
) {
let base_flags = (segment as i32) |
((style0 as i32) << 8) |
((style1 as i32) << 16) |
((do_aa as i32) << 28);
- let base_instance = BorderInstance {
- task_origin: DevicePoint::zero(),
+ let instance_gpu_data = BorderInstanceGpuData {
local_rect: task_rect,
- flags: base_flags,
color0: color0.premultiplied(),
color1: color1.premultiplied(),
widths,
radius,
+ shape
+ };
+
+ let base_instance = BorderInstance {
+ task_origin: DevicePoint::zero(),
+ flags: base_flags,
clip_params: [0.0; 8],
+ gpu_data_address: instance_gpu_data.write(gpu_buffer_builder)
};
match segment {
BorderSegment::TopLeft |
BorderSegment::TopRight |
@@ -1018,10 +1031,11 @@
non_overlapping_rect: LayoutRect,
side0: BorderSide,
side1: BorderSide,
widths: LayoutSize,
radius: LayoutSize,
+ shape: f32,
segment: BorderSegment,
edge_flags: EdgeMask,
h_adjacent_corner_outer: LayoutPoint,
h_adjacent_corner_radius: LayoutSize,
v_adjacent_corner_outer: LayoutPoint,
@@ -1137,10 +1151,11 @@
do_aa,
side0: side0.into(),
side1: side1.into(),
segment,
radius: radius.to_au(),
+ shape: shape.to_bits(),
size: widths.to_au(),
h_adjacent_corner_outer: (h_corner_outer - image_rect.min).to_point().to_au(),
h_adjacent_corner_radius: h_corner_radius.to_au(),
v_adjacent_corner_outer: (v_corner_outer - image_rect.min).to_point().to_au(),
v_adjacent_corner_radius: v_corner_radius.to_au(),
@@ -1200,10 +1215,11 @@
cache_key: BorderSegmentCacheKey {
do_aa,
side0: side.into(),
side1: side.into(),
radius: LayoutSizeAu::zero(),
+ shape: 0,
size: size.to_au(),
segment,
h_adjacent_corner_outer: LayoutPointAu::zero(),
h_adjacent_corner_radius: LayoutSizeAu::zero(),
v_adjacent_corner_outer: LayoutPointAu::zero(),
@@ -1217,10 +1233,11 @@
pub fn build_border_instances(
cache_key: &BorderSegmentCacheKey,
cache_size: DeviceIntSize,
border: &ApiNormalBorder,
scale: LayoutToDeviceScale,
+ gpu_buffer_builder: &mut GpuBufferBuilderF,
) -> Vec<BorderInstance> {
let mut instances = Vec::new();
let (side0, side1, flip0, flip1) = match cache_key.segment {
BorderSegment::Left => (&border.left, &border.left, false, false),
@@ -1247,10 +1264,11 @@
let color0 = side0.border_color(flip0);
let color1 = side1.border_color(flip1);
let widths = (LayoutSize::from_au(cache_key.size) * scale).ceil();
let radius = (LayoutSize::from_au(cache_key.radius) * scale).ceil();
+ let shape = f32::from_bits(cache_key.shape);
let h_corner_outer = (LayoutPoint::from_au(cache_key.h_adjacent_corner_outer) * scale).round();
let h_corner_radius = (LayoutSize::from_au(cache_key.h_adjacent_corner_radius) * scale).ceil();
let v_corner_outer = (LayoutPoint::from_au(cache_key.v_adjacent_corner_outer) * scale).round();
let v_corner_radius = (LayoutSize::from_au(cache_key.v_adjacent_corner_radius) * scale).ceil();
@@ -1263,15 +1281,17 @@
color1,
cache_key.segment,
&mut instances,
widths,
radius,
+ shape,
border.do_aa,
h_corner_outer,
h_corner_radius,
v_corner_outer,
v_corner_radius,
+ gpu_buffer_builder,
);
instances
}
diff --git a/gfx/wr/webrender/src/gpu_types.rs b/gfx/wr/webrender/src/gpu_types.rs
--- a/gfx/wr/webrender/src/gpu_types.rs
+++ b/gfx/wr/webrender/src/gpu_types.rs
@@ -192,22 +192,40 @@
Top,
Right,
Bottom,
}
+pub struct BorderInstanceGpuData {
+ pub local_rect: DeviceRect,
+ pub color0: PremultipliedColorF,
+ pub color1: PremultipliedColorF,
+ pub widths: DeviceSize,
+ pub radius: DeviceSize,
+ pub shape: f32,
+}
+
+impl BorderInstanceGpuData {
+ pub fn write(&self, gpu_buffer_builder: &mut GpuBufferBuilderF) -> GpuBufferAddress {
+ let mut writer = gpu_buffer_builder.write_blocks(5);
+ writer.push_one(self.local_rect);
+ writer.push_one(self.color0);
+ writer.push_one(self.color1);
+ writer.push_one([self.widths.width, self.widths.height, self.radius.width, self.radius.height]);
+ writer.push_one([self.shape, 0.0, 0.0, 0.0]);
+
+ writer.finish()
+ }
+}
+
#[derive(Debug, Clone)]
#[repr(C)]
#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
pub struct BorderInstance {
pub task_origin: DevicePoint,
- pub local_rect: DeviceRect,
- pub color0: PremultipliedColorF,
- pub color1: PremultipliedColorF,
pub flags: i32,
- pub widths: DeviceSize,
- pub radius: DeviceSize,
+ pub gpu_data_address: GpuBufferAddress,
pub clip_params: [f32; 8],
}
#[derive(Copy, Clone, Debug)]
#[cfg_attr(feature = "capture", derive(Serialize))]
diff --git a/gfx/wr/webrender/src/prim_store/borders.rs b/gfx/wr/webrender/src/prim_store/borders.rs
--- a/gfx/wr/webrender/src/prim_store/borders.rs
+++ b/gfx/wr/webrender/src/prim_store/borders.rs
@@ -230,19 +230,20 @@
false, // TODO(gw): We don't calculate opacity for borders yet!
RenderTaskParent::Surface,
&mut frame_state.frame_gpu_data.f32,
frame_state.rg_builder,
&mut frame_state.surface_builder,
- &mut |rg_builder, _| {
+ &mut |rg_builder, gpu_buffer_builder| {
rg_builder.add().init(RenderTask::new_dynamic(
cache_size,
RenderTaskKind::new_border_segment(
build_border_instances(
&segment.cache_key,
cache_size,
&self.border,
scale,
+ gpu_buffer_builder,
)
),
))
}
);
diff --git a/gfx/wr/webrender/src/renderer/vertex.rs b/gfx/wr/webrender/src/renderer/vertex.rs
--- a/gfx/wr/webrender/src/renderer/vertex.rs
+++ b/gfx/wr/webrender/src/renderer/vertex.rs
@@ -63,16 +63,12 @@
pub const BORDER: VertexDescriptor = VertexDescriptor {
vertex_attributes: &[VertexAttribute::quad_instance_vertex()],
instance_attributes: &[
VertexAttribute::f32x2("aTaskOrigin"),
- VertexAttribute::f32x4("aRect"),
- VertexAttribute::f32x4("aColor0"),
- VertexAttribute::f32x4("aColor1"),
VertexAttribute::i32("aFlags"),
- VertexAttribute::f32x2("aWidths"),
- VertexAttribute::f32x2("aRadii"),
+ VertexAttribute::gpu_buffer_address("aGpuDataAddress"),
VertexAttribute::f32x4("aClipParams1"),
VertexAttribute::f32x4("aClipParams2"),
],
};

View File

@@ -2,6 +2,24 @@
// 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/.
[
{
"type": "phabricator",
"ids": [
"D296935",
"D303334",
"D297660",
"D304517",
"D306773",
"D306774",
"D306775",
"D306776",
"D306777",
"D306778",
"D306779"
],
"name": "Corner shape support"
},
{
"type": "phabricator",
"id": "D299584",

View File

@@ -185,7 +185,7 @@
.toolbarbutton-1:not(#tabs-newtab-button),
.urlbar-page-action,
.identity-box-button {
--tab-border-radius: 6px;
--tab-border-radius: 8px;
--toolbarbutton-border-radius: var(--tab-border-radius);
--toolbarbutton-padding-inner: 6px;
--toolbarbutton-padding-outer: 1px;

View File

@@ -213,6 +213,8 @@
--toolbarbutton-border-radius: 6px;
--urlbar-margin-inline: 1px !important;
--zen-squircle-value: 1.4;
--tab-icon-overlay-stroke: light-dark(white, black) !important;
--tab-close-button-padding: 4px !important;
@@ -343,3 +345,9 @@
}
%include zen-buttons.css
@media (-moz-pref('layout.css.corner-shape.enabled')) {
*:not(.no-squircles) {
corner-shape: superellipse(var(--zen-squircle-value));
}
}

View File

@@ -41,11 +41,11 @@
&:hover {
background: light-dark(rgb(41, 41, 41), rgb(204, 204, 204));
scale: 1.05;
scale: 1.02;
}
&:hover:active {
scale: 0.95;
scale: 0.98;
}
& label {

View File

@@ -4,8 +4,8 @@
<html:template id="zen-glance-sidebar-template">
<vbox class="zen-glance-sidebar-container">
<toolbarbutton class="zen-glance-sidebar-close toolbarbutton-1" command="cmd_zenGlanceClose" data-l10n-id="zen-general-confirm" />
<toolbarbutton class="zen-glance-sidebar-open toolbarbutton-1" command="cmd_zenGlanceExpand" />
<toolbarbutton class="zen-glance-sidebar-split toolbarbutton-1" command="cmd_zenGlanceSplit" />
<toolbarbutton class="no-squircles zen-glance-sidebar-close toolbarbutton-1" command="cmd_zenGlanceClose" data-l10n-id="zen-general-confirm" />
<toolbarbutton class="no-squircles zen-glance-sidebar-open toolbarbutton-1" command="cmd_zenGlanceExpand" />
<toolbarbutton class="no-squircles zen-glance-sidebar-split toolbarbutton-1" command="cmd_zenGlanceSplit" />
</vbox>
</html:template>

View File

@@ -31,6 +31,7 @@
& toolbarbutton {
margin: 0;
max-width: 28px;
border-radius: var(--toolbarbutton-border-radius);
height: 28px;
display: flex;
justify-content: center;

View File

@@ -235,7 +235,7 @@
}
@media (-moz-platform: macos) {
--border-radius-medium: 12px;
--border-radius-medium: 14px;
--tab-border-radius: 8px;
}
@@ -1232,6 +1232,8 @@
background: var(--zen-essential-tab-selected-bg);
margin: var(--zen-essential-bg-margin);
border-radius: calc(var(--border-radius-medium) - var(--zen-essential-bg-margin));
/* stylelint-disable-next-line property-no-unknown */
corner-shape: var(--zen-squircle-value);
position: absolute;
inset: 0;
z-index: 0;