diff --git a/src/external-patches/firefox/corner_shape_support/D296935.patch b/src/external-patches/firefox/corner_shape_support/D296935.patch index a177a80f3..df1f71702 100644 --- a/src/external-patches/firefox/corner_shape_support/D296935.patch +++ b/src/external-patches/firefox/corner_shape_support/D296935.patch @@ -1528,7 +1528,7 @@ diff --git a/servo/components/style/values/specified/mod.rs b/servo/components/s --- a/servo/components/style/values/specified/mod.rs +++ b/servo/components/style/values/specified/mod.rs @@ -50,10 +50,11 @@ - }; + pub use self::calc::{CalcLengthPercentage, CalcNumeric}; pub use self::color::{ Color, ColorOrAuto, ColorPropertyValue, ColorScheme, ForcedColorAdjust, PrintColorAdjust, }; @@ -1551,6 +1551,21 @@ diff --git a/servo/components/style/values/specified/mod.rs b/servo/components/s pub mod effects; pub mod flex; pub mod font; +diff --git a/servo/components/style/values/specified/position.rs b/servo/components/style/values/specified/position.rs +--- a/servo/components/style/values/specified/position.rs ++++ b/servo/components/style/values/specified/position.rs +@@ -747,11 +747,10 @@ + #[css(iterable, if_empty = "none")] + #[ignore_malloc_size_of = "Arc"] + pub crate::ArcSlice, + ); + +- + impl IsTreeScoped for PositionTryFallbacksList { + fn is_tree_scoped(&self) -> bool { + !self.is_none() + } + } diff --git a/servo/ports/geckolib/cbindgen.toml b/servo/ports/geckolib/cbindgen.toml --- a/servo/ports/geckolib/cbindgen.toml +++ b/servo/ports/geckolib/cbindgen.toml diff --git a/src/external-patches/firefox/corner_shape_support/D297660.patch b/src/external-patches/firefox/corner_shape_support/D297660.patch index 9d999e266..589cf6ffa 100644 --- a/src/external-patches/firefox/corner_shape_support/D297660.patch +++ b/src/external-patches/firefox/corner_shape_support/D297660.patch @@ -609,7 +609,7 @@ diff --git a/gfx/wr/webrender/src/border.rs b/gfx/wr/webrender/src/border.rs diff --git a/gfx/wr/webrender/src/clip.rs b/gfx/wr/webrender/src/clip.rs --- a/gfx/wr/webrender/src/clip.rs +++ b/gfx/wr/webrender/src/clip.rs -@@ -2334,10 +2334,14 @@ +@@ -2344,10 +2344,14 @@ BorderRadius { top_left: LayoutSize::new(tl, tl), top_right: LayoutSize::new(tr, tr), @@ -624,7 +624,7 @@ diff --git a/gfx/wr/webrender/src/clip.rs b/gfx/wr/webrender/src/clip.rs #[test] fn test_intersect_identical() { -@@ -2446,10 +2450,14 @@ +@@ -2456,10 +2460,14 @@ let result_rect = rect_a.intersection(&rect_b)?; if result_rect.is_empty() { return None; @@ -639,7 +639,7 @@ diff --git a/gfx/wr/webrender/src/clip.rs b/gfx/wr/webrender/src/clip.rs result_rect.min.x, result_rect.min.y, rect_a.min.x, rect_a.min.y, radius_a.top_left, rect_b.min.x, rect_b.min.y, radius_b.top_left, -@@ -2471,10 +2479,14 @@ +@@ -2481,10 +2489,14 @@ result_rect.max.x, result_rect.max.y, rect_a.max.x, rect_a.max.y, radius_a.bottom_right, rect_b.max.x, rect_b.max.y, radius_b.bottom_right, @@ -654,6 +654,25 @@ diff --git a/gfx/wr/webrender/src/clip.rs b/gfx/wr/webrender/src/clip.rs if !result_radius.can_use_fast_path_in(&result_rect) { return None; } +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 +@@ -549,12 +549,12 @@ + // talos stress tests. If you get a failure here on CI, there's two possibilities: + // (a) You made a structure smaller than it currently is. Great work! Update the + // test expectations and move on. + // (b) You made a structure larger. This is not necessarily a problem, but should only + // be done with care, and after checking if talos performance regresses badly. +- assert_eq!(mem::size_of::(), 84, "NormalBorderPrim size changed"); +- assert_eq!(mem::size_of::(), 140, "NormalBorderTemplate size changed"); +- assert_eq!(mem::size_of::(), 88, "NormalBorderKey size changed"); ++ assert_eq!(mem::size_of::(), 100, "NormalBorderPrim size changed"); ++ assert_eq!(mem::size_of::(), 156, "NormalBorderTemplate size changed"); ++ assert_eq!(mem::size_of::(), 104, "NormalBorderKey size changed"); + assert_eq!(mem::size_of::(), 68, "ImageBorder size changed"); + assert_eq!(mem::size_of::(), 104, "ImageBorderTemplate size changed"); + assert_eq!(mem::size_of::(), 72, "ImageBorderKey size changed"); + } diff --git a/gfx/wr/webrender/src/quad.rs b/gfx/wr/webrender/src/quad.rs --- a/gfx/wr/webrender/src/quad.rs +++ b/gfx/wr/webrender/src/quad.rs @@ -665,7 +684,7 @@ diff --git a/gfx/wr/webrender/src/quad.rs b/gfx/wr/webrender/src/quad.rs } else { - let mut writer = gpu_buffer.write_blocks(4); + let mut writer = gpu_buffer.write_blocks(5); - writer.push_one(rect); + writer.push_one(clip_instance.clip_rect); writer.push_one([ radius.top_left.width, radius.top_left.height, @@ -723,7 +742,7 @@ diff --git a/gfx/wr/webrender/src/tile_cache/mod.rs b/gfx/wr/webrender/src/tile_ diff --git a/gfx/wr/webrender_api/src/display_item.rs b/gfx/wr/webrender_api/src/display_item.rs --- a/gfx/wr/webrender_api/src/display_item.rs +++ b/gfx/wr/webrender_api/src/display_item.rs -@@ -530,23 +530,41 @@ +@@ -523,23 +523,41 @@ pub struct BorderRadius { pub top_left: LayoutSize, pub top_right: LayoutSize, @@ -765,7 +784,7 @@ diff --git a/gfx/wr/webrender_api/src/display_item.rs b/gfx/wr/webrender_api/src pub struct BorderSide { pub color: ColorF, pub style: BorderStyle, -@@ -2009,28 +2027,40 @@ +@@ -2069,28 +2087,40 @@ BorderRadius { top_left: LayoutSize::new(0.0, 0.0), top_right: LayoutSize::new(0.0, 0.0), @@ -806,7 +825,7 @@ diff --git a/gfx/wr/webrender_api/src/display_item.rs b/gfx/wr/webrender_api/src pub fn all_sides_uniform(&self) -> bool { let corner_is_uniform = |corner: &LayoutSize| corner.width == corner.height; -@@ -2039,10 +2069,13 @@ +@@ -2099,10 +2129,13 @@ corner_is_uniform(&self.bottom_right) && corner_is_uniform(&self.bottom_left) } @@ -889,6 +908,25 @@ diff --git a/gfx/wr/wrench/src/yaml_helper.rs b/gfx/wr/wrench/src/yaml_helper.rs _ => { panic!("Invalid border radius specified: {:?}", self); } +diff --git a/layout/base/ShapeUtils.cpp b/layout/base/ShapeUtils.cpp +--- a/layout/base/ShapeUtils.cpp ++++ b/layout/base/ShapeUtils.cpp +@@ -145,12 +145,13 @@ + + /* static */ + bool ShapeUtils::ComputeRectRadii(const StyleBorderRadius& aBorderRadius, + const nsRect& aRefBox, const nsRect& aRect, + nsRectCornerRadii& aRadii) { +- return nsIFrame::ComputeBorderRadii(aBorderRadius, aRefBox.Size(), +- aRect.Size(), Sides(), aRadii); ++ return nsIFrame::ComputeBorderRadii( ++ aBorderRadius, {{1.0f}, {1.0f}, {1.0f}, {1.0f}}, aRefBox.Size(), ++ aRect.Size(), Sides(), aRadii); + } + + /* static */ + nsTArray ShapeUtils::ComputePolygonVertices( + const StyleBasicShape& aBasicShape, const nsRect& aRefBox) { diff --git a/layout/generic/TextDrawTarget.h b/layout/generic/TextDrawTarget.h --- a/layout/generic/TextDrawTarget.h +++ b/layout/generic/TextDrawTarget.h @@ -906,46 +944,132 @@ diff --git a/layout/generic/TextDrawTarget.h b/layout/generic/TextDrawTarget.h if (!rect.Intersects(GeckoClipRect())) { return; } +diff --git a/layout/generic/nsIFrame.h b/layout/generic/nsIFrame.h +--- a/layout/generic/nsIFrame.h ++++ b/layout/generic/nsIFrame.h +@@ -1670,10 +1670,11 @@ + * large. + * + * Return whether any radii are nonzero. + */ + static bool ComputeBorderRadii(const mozilla::BorderRadius&, ++ const mozilla::CornerShapeRect&, + const nsSize& aFrameSize, + const nsSize& aBorderArea, Sides aSkipSides, + nsRectCornerRadii&); + + /** diff --git a/layout/generic/nsIFrame.cpp b/layout/generic/nsIFrame.cpp --- a/layout/generic/nsIFrame.cpp +++ b/layout/generic/nsIFrame.cpp -@@ -1885,10 +1885,15 @@ +@@ -1808,30 +1808,49 @@ + nsRect nsIFrame::GetContentRect() const { + return GetContentRectRelativeToSelf() + GetPosition(); + } + + bool nsIFrame::ComputeBorderRadii(const BorderRadius& aBorderRadius, ++ const CornerShapeRect& aCornerShape, + const nsSize& aFrameSize, + const nsSize& aBorderArea, Sides aSkipSides, + nsRectCornerRadii& aRadii) { + // Percentages are relative to whichever side they're on. + for (const auto i : mozilla::AllPhysicalHalfCorners()) { + const LengthPercentage& c = aBorderRadius.Get(i); + nscoord axis = HalfCornerIsX(i) ? aFrameSize.width : aFrameSize.height; + aRadii[i] = std::max(0, c.Resolve(axis)); + } + +- if (aSkipSides.Intersects(SideBits::eTop | SideBits::eLeft)) { ++ aRadii.mShapeK[mozilla::eCornerTopLeft] = aCornerShape.top_left.k; ++ aRadii.mShapeK[mozilla::eCornerTopRight] = aCornerShape.top_right.k; ++ aRadii.mShapeK[mozilla::eCornerBottomLeft] = aCornerShape.bottom_left.k; ++ aRadii.mShapeK[mozilla::eCornerBottomRight] = aCornerShape.bottom_right.k; ++ ++ bool isTopLeftSquare = ++ isinf(aCornerShape.top_left.k) && (aCornerShape.top_left.k > 0.0f); ++ bool isTopRightSquare = ++ isinf(aCornerShape.top_right.k) && (aCornerShape.top_right.k > 0.0f); ++ bool isBottomLeftSquare = ++ isinf(aCornerShape.bottom_left.k) && (aCornerShape.bottom_left.k > 0.0f); ++ bool isBottomRightSquare = isinf(aCornerShape.bottom_right.k) && ++ (aCornerShape.bottom_right.k > 0.0f); ++ ++ if (aSkipSides.Intersects(SideBits::eTop | SideBits::eLeft) || ++ isTopLeftSquare) { + aRadii.TopLeft() = {}; + } +- if (aSkipSides.Intersects(SideBits::eTop | SideBits::eRight)) { ++ if (aSkipSides.Intersects(SideBits::eTop | SideBits::eRight) || ++ isTopRightSquare) { + aRadii.TopRight() = {}; + } +- if (aSkipSides.Intersects(SideBits::eBottom | SideBits::eLeft)) { ++ if (aSkipSides.Intersects(SideBits::eBottom | SideBits::eLeft) || ++ isBottomLeftSquare) { + aRadii.BottomLeft() = {}; + } +- if (aSkipSides.Intersects(SideBits::eBottom | SideBits::eRight)) { ++ if (aSkipSides.Intersects(SideBits::eBottom | SideBits::eRight) || ++ isBottomRightSquare) { + aRadii.BottomRight() = {}; + } + + // css3-background specifies this algorithm for reducing + // corner radii when they are too big. +@@ -1887,12 +1906,13 @@ + // zero. + return false; } const auto& radii = StyleBorder()->mBorderRadius; - const bool hasRadii = - ComputeBorderRadii(radii, aFrameSize, aBorderArea, aSkipSides, aRadii); -+ const auto& shape = StyleBorder()->mCornerShape; -+ aRadii.mShapeK[mozilla::eCornerTopLeft] = shape.top_left.k; -+ aRadii.mShapeK[mozilla::eCornerTopRight] = shape.top_right.k; -+ aRadii.mShapeK[mozilla::eCornerBottomRight] = shape.bottom_right.k; -+ aRadii.mShapeK[mozilla::eCornerBottomLeft] = shape.bottom_left.k; +- const bool hasRadii = +- ComputeBorderRadii(radii, aFrameSize, aBorderArea, aSkipSides, aRadii); ++ const auto& cornerShape = StyleBorder()->mCornerShape; ++ const bool hasRadii = ComputeBorderRadii(radii, cornerShape, aFrameSize, ++ aBorderArea, aSkipSides, aRadii); if (!hasRadii) { // TODO(emilio): Maybe we can just remove this bit and do the // IsDefinitelyZero check unconditionally. That should still avoid most of // the work, though maybe not the cache miss of going through the style and // the border struct. +diff --git a/layout/generic/nsTextFrame.cpp b/layout/generic/nsTextFrame.cpp +--- a/layout/generic/nsTextFrame.cpp ++++ b/layout/generic/nsTextFrame.cpp +@@ -7156,12 +7156,15 @@ + if (auto* style = + aParams.textPaintStyle->GetSelectionPseudoStyle()) { + nsSize size = LayoutDeviceRect::ToAppUnits(selectionRect, + appUnitsPerDevPixel) + .Size(); ++ ++ const auto& borderRadius = style->StyleBorder()->mBorderRadius; ++ const auto& cornerShape = style->StyleBorder()->mCornerShape; + hasRadii = nsIFrame::ComputeBorderRadii( +- style->StyleBorder()->mBorderRadius, size, size, {}, radii); ++ borderRadius, cornerShape, size, size, {}, radii); + } + } + + if (hasRadii) { + textDrawer->AppendSelectionRoundRect( diff --git a/layout/painting/nsCSSRendering.cpp b/layout/painting/nsCSSRendering.cpp --- a/layout/painting/nsCSSRendering.cpp +++ b/layout/painting/nsCSSRendering.cpp -@@ -485,10 +485,16 @@ +@@ -484,11 +484,12 @@ + if (&aBorder == aForFrame->StyleBorder() && frameSize == aOrigBorderArea.Size()) { haveRoundedCorners = aForFrame->GetBorderRadii(sz, sz, Sides(), aRadii); } else { haveRoundedCorners = nsIFrame::ComputeBorderRadii( - aBorder.mBorderRadius, frameSize, sz, Sides(), aRadii); -+ aRadii.mShapeK[mozilla::eCornerTopLeft] = aBorder.mCornerShape.top_left.k; -+ aRadii.mShapeK[mozilla::eCornerTopRight] = aBorder.mCornerShape.top_right.k; -+ aRadii.mShapeK[mozilla::eCornerBottomRight] = -+ aBorder.mCornerShape.bottom_right.k; -+ aRadii.mShapeK[mozilla::eCornerBottomLeft] = -+ aBorder.mCornerShape.bottom_left.k; +- aBorder.mBorderRadius, frameSize, sz, Sides(), aRadii); ++ aBorder.mBorderRadius, aBorder.mCornerShape, frameSize, sz, Sides(), ++ aRadii); } return haveRoundedCorners; } -@@ -593,10 +599,11 @@ +@@ -593,10 +594,11 @@ RectCornerRadii* oBorderRadii) { for (const auto corner : mozilla::AllPhysicalCorners()) { (*oBorderRadii)[corner] = @@ -957,14 +1081,29 @@ diff --git a/layout/painting/nsCSSRendering.cpp b/layout/painting/nsCSSRendering static Maybe GetBorderIfVisited(const ComputedStyle& aStyle) { Maybe result; +diff --git a/layout/style/ServoStyleConstsInlines.h b/layout/style/ServoStyleConstsInlines.h +--- a/layout/style/ServoStyleConstsInlines.h ++++ b/layout/style/ServoStyleConstsInlines.h +@@ -570,10 +570,11 @@ + using Length = StyleLength; + using LengthOrAuto = StyleLengthOrAuto; + using NonNegativeLength = StyleNonNegativeLength; + using NonNegativeLengthOrAuto = StyleNonNegativeLengthOrAuto; + using BorderRadius = StyleBorderRadius; ++using CornerShapeRect = StyleCornerShapeRect; + + bool StyleCSSPixelLength::IsZero() const { return _0 == 0.0f; } + + void StyleCSSPixelLength::ScaleBy(float aScale) { _0 *= aScale; } + diff --git a/testing/web-platform/meta/css/css-borders/corner-shape/corner-shape-backdrop-filter-overflow.html.ini b/testing/web-platform/meta/css/css-borders/corner-shape/corner-shape-backdrop-filter-overflow.html.ini --- a/testing/web-platform/meta/css/css-borders/corner-shape/corner-shape-backdrop-filter-overflow.html.ini +++ b/testing/web-platform/meta/css/css-borders/corner-shape/corner-shape-backdrop-filter-overflow.html.ini -@@ -1,4 +1,5 @@ +@@ -1,4 +1,4 @@ [corner-shape-backdrop-filter-overflow.html] expected: if not useDrawSnapshot and asan and not fission and not swgl: TIMEOUT - if useDrawSnapshot: FAIL +- if useDrawSnapshot: FAIL + FAIL diff --git a/testing/web-platform/meta/css/css-borders/corner-shape/corner-shape-bevel-overflow-composite.html.ini b/testing/web-platform/meta/css/css-borders/corner-shape/corner-shape-bevel-overflow-composite.html.ini --- a/testing/web-platform/meta/css/css-borders/corner-shape/corner-shape-bevel-overflow-composite.html.ini @@ -987,8 +1126,8 @@ new file mode 100644 --- /dev/null +++ b/testing/web-platform/meta/css/css-borders/corner-shape/corner-shape-noop-keyframe.html.ini @@ -0,0 +1,2 @@ -+[corner-shape-noop-keyframe.html] -+ fuzzy: maxDifference=0-13;totalPixels=0-350 ++[corner-shape-noop-keyframe.html] ++ fuzzy: maxDifference=0-13;totalPixels=0-350 diff --git a/testing/web-platform/meta/css/css-borders/corner-shape/corner-shape-notch.html.ini b/testing/web-platform/meta/css/css-borders/corner-shape/corner-shape-notch.html.ini --- a/testing/web-platform/meta/css/css-borders/corner-shape/corner-shape-notch.html.ini +++ b/testing/web-platform/meta/css/css-borders/corner-shape/corner-shape-notch.html.ini @@ -1000,7 +1139,7 @@ diff --git a/testing/web-platform/meta/css/css-borders/corner-shape/corner-shape diff --git a/testing/web-platform/meta/css/css-borders/corner-shape/render-corner-shape.html.ini b/testing/web-platform/meta/css/css-borders/corner-shape/render-corner-shape.html.ini --- a/testing/web-platform/meta/css/css-borders/corner-shape/render-corner-shape.html.ini +++ b/testing/web-platform/meta/css/css-borders/corner-shape/render-corner-shape.html.ini -@@ -1,125 +1,160 @@ +@@ -1,125 +1,156 @@ [render-corner-shape.html?border-radius=50&corner-shape=0&shadow-spread=10] expected: FAIL @@ -1119,10 +1258,8 @@ diff --git a/testing/web-platform/meta/css/css-borders/corner-shape/render-corne [render-corner-shape.html?corner-shape=3&border-top-right-radius=33] - expected: FAIL -+ expected: -+ if useDrawSnapshot: FAIL - - [render-corner-shape.html?corner-shape=square&border-bottom-left-radius=5] +- +-[render-corner-shape.html?corner-shape=square&border-bottom-left-radius=5] - expected: FAIL + expected: + if useDrawSnapshot: FAIL diff --git a/src/external-patches/firefox/corner_shape_support/D306773.patch b/src/external-patches/firefox/corner_shape_support/D306773.patch new file mode 100644 index 000000000..c069216a7 --- /dev/null +++ b/src/external-patches/firefox/corner_shape_support/D306773.patch @@ -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) { + diff --git a/src/external-patches/firefox/corner_shape_support/D306774.patch b/src/external-patches/firefox/corner_shape_support/D306774.patch new file mode 100644 index 000000000..fb9509b33 --- /dev/null +++ b/src/external-patches/firefox/corner_shape_support/D306774.patch @@ -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)}; + } + diff --git a/src/external-patches/firefox/corner_shape_support/D306775.patch b/src/external-patches/firefox/corner_shape_support/D306775.patch new file mode 100644 index 000000000..2093edeb4 --- /dev/null +++ b/src/external-patches/firefox/corner_shape_support/D306775.patch @@ -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; + } + diff --git a/src/external-patches/firefox/corner_shape_support/D306776.patch b/src/external-patches/firefox/corner_shape_support/D306776.patch new file mode 100644 index 000000000..33ee6f2d8 --- /dev/null +++ b/src/external-patches/firefox/corner_shape_support/D306776.patch @@ -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; + diff --git a/src/external-patches/firefox/corner_shape_support/D306777.patch b/src/external-patches/firefox/corner_shape_support/D306777.patch new file mode 100644 index 000000000..6326a9efd --- /dev/null +++ b/src/external-patches/firefox/corner_shape_support/D306777.patch @@ -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); ++} + diff --git a/src/external-patches/firefox/corner_shape_support/D306778.patch b/src/external-patches/firefox/corner_shape_support/D306778.patch new file mode 100644 index 000000000..6fcc32e3a --- /dev/null +++ b/src/external-patches/firefox/corner_shape_support/D306778.patch @@ -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 +zc%1E7dpy(q+pko@P*RT39g>JG<;-rBRz#@W-Oki1IYx78me`i;cIad|q?J+$b*~&^ +z<}j3om6#-t=W@AbK^&-;>g#Pxu@ +zth(%q6)WTqqV{=!-@+9uR(@W$7W_r(iHupXLaX=SKKr9_`QQ3wZulO%+45t{8h3Xe +z*>`Bv`t|Gk)ShiwvF77G_uB_nZphMWb2+o`cH@W3O6y76h16K>j`2z|2sE2k9Jp2eM_9OUQD9X+Vb`Hl$H77&Oh;(PSw-djs53?zp`~CtIbUaSJhp!XX8ZyA`u3Met+#@d*b`fXLUKDIFW{$j#fK84W1(3) +zpHFS?u&unHmouqX#?}$sgj)wyw0=KiEV@s37<;)S=xR5vQ&nW_A4*7+DPT`W1XM6k +zxUZS41?zc68oIKdAU(7*iq@anF;G3vxTvHfD&?{|EnE3NhubG#K~Y&9FVg?oWTqa)+S=PlthZ(d(T2Ej!&_QfAUarL{vb-1xYyH&H%QM<7CL +zKt&Vk&J#J&m+S2cHmp$bMVqWP-LlwctofFu71Y&E)5nr{nYL)NaG#0J#s>*$6W?GW +z8d*kFe4^@0`6pI+Rb%L~sQsa9v(#hYf;2&ViYY@rhEQ^hrxapxIZ2DR+w+Lh9(jz} +z3daHY=xykOB!;^yuQ)%bqSFp7xA}AO2jCt|4Jyv$ng4NIH~Gds6g3-wKj +zU9)NQB=c|8v{t0xuz8qh#Z>{3G3(m+UHXXb_GQ+A7k2FHc7wHkZ>~FJcEr=J>EpEu +zW)k$=WNod+W)Iy_PKfE4xM^b`;N`Oo<2`uqEX%#7i&*!g{mQ=_q#PLgx8T2q;F6=; +zY?~q4gdRHg-WfeJmPh+}k2BMm*IsaLj%kW^LxOy{#UZJoGi`$A>ZMAlMQWxkp`WUH +z%4M7aJZd*kRYwn#_23Z=wenQuQD1U4`4r+lq9mZF{=3oHvKE(mmzKCECW3GqaTVt! +zJJ&b<0Y@+Ah4|EO%U1$b*46IXD+qsjiL;)%0WAkx2GmDeEN~Cl@H^A8*t?d|%nT%# +z-y8hnckyP7N^<2*HR12h!3y=7so6M%+QXFCSHlX_0?h83nb@9QTx$+O_SEn?`C*AvYg4D +zKD37B<>20ozzN}P4iK!qnXtL!CDKK$0_aTe8JNhAq_s-(vl|VMIxqy<{$gKZz +zB`|R*xZU*E-@DvmcjcleLbDo&X!7SZ(V^&a7XL+vDbQvvv_fDaH)2G +zzEyY8zO;$M@*w`l+5h1*s0JBzQjQu&(b8qH +ziA+n?H~xDmIN8F1evF2KM>S*Cc&ES{QOH1v+Z3_WC#fbES4u;D#M)6iePORt&<>=a +zv?4_GwEBZi6s>^bpE}r?>kJzqbWC0Ljz6VYWR^CuMb(NfH|Y+#N;vO;)>+KYK?_uv +z65ARsXo4RI(9JmS=#RZXHSmng`Uv`308cUScoRx<1fL|DMQem!N`czXHx|3qhnW3G +zn;f>B#@z18unz&AV0g$Dewu_TI77W{8kO~@URmW9A&j|$#PD$CnfITp;3il=UFt21 +z-TdiFc3hi`D9e$VVYycNG59iS!gu5pgp!*jWun!6@c6YaT$i!MW1x+hrXWHA1 +zYhV&t8jPw2(L^cQdltJ2BeUwVs<_BN@g~WE8L{N{g7g#to-y0eY=qAyFF9%>RxSUA +zZTkOE(f`i`L1aMfQ2dOX>-K8jYy{6U?+oqGq_%3A)=U^vOUicF3@co}_Lo|)S^RE= +zCT}H29e6~&QN|#ya?dD@oEcnq<%FEh$SZZzwZq^G9aZr=V-}vz8O|I|zHvF*bZ#}w +zrn!eKL*4}U$aqeEqv|$`ckL?93wx2x5zP-LR|S2B*}8}DUThmZ1gif~Iz7)+02;|x +z`GPpSe`1&>W0THle%jSk*V@K`j1B&z{O7H51$B$Q)Zol!dmnft!SDBXtno#13VbLf +z*)-;=nic)X{GE9+ZCX|f)v0P3Y;re`wSa$B43A)-rog(GOzAS~dr|khJ}vMwjCMEN +zp;!*Sw5mWrNH!HzR8a~q+~Tn5;qP^vI(p^4nh6Tv%lK?A{Co>{vw4gd(f7#R0>xIf +zaGY|eq|9V;&_P9suzZT5vU$v(QTwTCrjc1?5Hmj9v3Q*PPIX)X*e}(rAd>SxgMD@= +z3RX*;_cfs`t2ZegH^@jf`HEGs7TC_g7suVAvKoPXQyyS<^-LH^x%IVLVsS4;J2szV +zFO23iLQ3sTC^+e8Bd4ptcC334QJn7o`E8Z;;8r}OG{w(hS$))qq}=pcZSfvMp#a(4 +zGKI~F0S3-L%3&>dhAnYp54P5;2?Ky=&A@H!^mPl=Zs2L+2WQ?gp;}&N9GIZ(!e?p6 +z)$^sa>+P?B5KrFCVX^B!WoGYzJk`VSOi$pHK(gd +zt0_sH=4B+vU}c#8h~0bEcCb7lPcrLzgDhTW0rO&ktxNHO9Iy#=LYsn^caFiIVf`me +zDA(tu(U6(N(@D6Uf=?hSlP;7Tpl|LdcghWaXCpYz`7Y~iQ@vWkhF=tLh=c;d{fi<8 +z@!Vs*Z2&y(zbFt7L;*a%C{hql5le)KByi=Y=8GLVSAq|%=fM+0-;glB=t-HkhIk&b +zun^BKh-WGmJ-cQ?)&sl_2Dzec_y@zW?{J;!8qC!O|}IuvyEl}s`9tE=rwQOva!WN~g7pgoH}4s46aWz5bw@<=%*Q-UPsS8_MJBuKSd0HDQG +zT_68WB6G5)e0GkAB-@sH$uHC}W{+#o%^e@fF9EVCvJ!0(7R2WEUyPpkcFUWIZg0dH;C0K`rh>hQ +z38VbZfLqNdn$R#N$qw6pp|oo&X?Nq3 +zn&if2I|W7^SSb&)Lr +zy10>4JMi3VR>|`{e{iB?#G{ZgyIbH+-i7cE_}P6vtqCbeHx8j8V#aVUVt$K~_71LS +zgvU6UJpW0oo9($;Tc|rZxQ(Gy!R +zVT2Cc;3G~O7uKn4l9Fjt(;b(5)sk)`6(+Rt +z-{`laJND$+^@o1kLw)Sou9fhbpQiuad`*`^V*dqi`gGJv(#vp|$d)_;zYjMII^Ov7 +z>WM8>o9(%nUh}}8hT2`{RNWAc+6u$;A5PSB<$LpNs%K47KfzC~?LXC9ApA`*2p7-7 +zHG*1#e*S~3hSA6S5#)^Fc^2>Zqj^8>x|LqeQhVXqTX23It;>vTiM4pq*4G0t!DwNcqj4_CfY-2BXL<{i6F9E6-J$dSQIAxC&?bDp!5C{i +zk6ak|q$Nu&raUm#gLkYKV2=xRF0kA7Y-LRGC&%I$L~Tb-+Ha<3rk+_F2zKTtz2bz| +z41T`yn<>vurp7asMNhVr9|jD(zndnDSS9u4uW@r!3&ACbK^|gQ*tD?REVvBTPb3`Q +zTamd~o}-0wJ+luiOBZ{SqVMeg;yHc{K;F17@67#}u!l&=pNLnJN>Q +zcNcf@U1e#qnRdd?!D&Q_f)cb_P8x^hWU9r`i69PM$&^gBE?Fz!@x9cfy#)KQ%^;5d +zEUg0n}hDfF4_KJYQ1W +za!*!_KeRxd0+{D0FE7Bj6;<~{9?SN +zQ(;ci$9#EgpRNSiQ;&}iB}mJOW>oF)e?ypVetAw8jtYEoYbL}mZc#BY#} +z$~vS6wGQq2T5X;9lI;Sb*6u{Q-5((!w)^pQR-^W$FXg!`H_K*z-vH2;1ChnMm~Mz` +z^bm)EkdmIx0_Rx(bRMxx8o!Tq=;69k>zKRI(W9TY-UPt)ofVLR}^frW+hG8c7v1 +zHlhum0vABnhGFBG!>Vb;`7GRw2DKBX^$$Es4=!s!*?>MCb&unh2!i13W8yflaVD6= +z@O0&Y$C|SU0<&tC!8riS`j+FkNN7DP9E-ZSQP^gfcQ}vmOM%Fpc}Oyq&GFmq9VDY! +zWCBu6hIx_1_@e#F?Nsc+<$2&L;dUdhv-Io^E<&4hje{fn`NduonP{l!Qn#|A+&WEKBU +z{E?g}33$#yqz6K@KK7iK|K7z3|MolaEun2UdO9EZN3IlKK1wKbvR#4$T)4(DqP|vb +z#+VtRDkcfdR3CTfkmu}be-iC(c)IQF!^VPpYCRQ-X;HI)WgHm!u-I-XqSp+zEKZItvOq=|+SKY2Gv3OWUfnri{~WKD_n8(8~h${OTsW +zt9f8g1FD)!j8`3ge22AAEv)Dp+WH_6f|G}MOFp8Dq#MM-!e3xgrr?%87c{o0ERXMP +z9VLnPZm`B>nCDduq>;$6Zd+Gg4gd0Tc?ZM(5cI&m_W>Mte_rM4mkS^R=!73f{dr?| +z&Q&xiSfC8z!p3GHz}gqw(SWj)tXw5{Nb9eZDu6*~mp-r#1fl~N+5p8U>&Fb0RDVC_ +z%TOuj*S=E8Qn&ii?ep`A@ld)K#;@PtI8P(|kxGz}6o3wElx2KP7=I`Lqygwl#+FHy +z`9CGzuDY7qF?DS?_HCMpUtc`7_>W(ZP&hNPv1On`K2yGwl_9 +z3er(chSueiYc|PXy_xZ|5 +z$jzwr=Cu_wLTGd0@52|J)PFRcvo46B`g!&Z+#?|b`%77$&Ps|2ww`UFXk0Wewe5WY_MwX`_* +z8u!P?jtR-;dV9fN>M6JDvNA?H`gV!!@y}9S&GGY!$ze?Ip +zi8h6G7B4)74@n5C+Kv39n{~e@!1!fWgVqxuWkxNEl?SM0n*W +z68?S*lu+6(wXB8wsEd;p1{ukwF~FO#=$0SV!$lS#%0yt+6t83sfMuF4jBLB~v~RO`zEkXr>T{?vI|)EP_L-VnHzO!-)Y! +z781pWYFUcbFzvkup!r24VY29qWD<`;KrZWpgS9g4981AWOSg`}fS(I}Q|Q!}BeZC`t}Aj8FzgLuYI;5KK$bQWnpJW+>L4yb)+# +zb<-ij%8wI&A@(8bZ8MbPkChX;5dUe?AWIvE;@p4R!9=C}TWwvj2k$VHM>5I@@z9lZ +zpqQ&c!OOXOhDW++<3y0$l>H1j-+hOQ|J(o4{hu+2wQs)L6(GKt=(Ym<9Nh1^ugoFf +G@_zvPNe@N< + +literal 0 +Hc$@%O$L{C7@8`as-|zXoyRP?icvui_ +zCSj(Di3u)v4SNGvU&9|_0nk3G`Gkqd^jpDf)~3|L51LRk^jBiTaC2(*yRyZ3apZG1 +zb8+IQVYlO?jEao?yVx92`Kt3c`^RCCTW7m=kk}g~>IHF2veQPsJB*I4m~!l0nKC%3 +z85}DdyRLfO?0vC}I+&EAdRFBbGuO0HhzYV0%SQCymS;7UcZ=unq?McLJSK7qn?_cq +zB3?8}RtClqXuC;@b0noLB4?v2Um?X#GI|E%pxOx+#W@%H6-537RXGVMK9bQ4%tN4^ +zASpy7x)UPzL*-u)c^oQ#fXIcYJPnacP`M8xe~fzh3a`^7O<5R|Z-*yVJ1ZH8<#%Ug +zJ()IfQcK9fhGt3j5rwtM_#Hc~h*PMx|135X!H$SA&y2-H%uv^5@r*X=>}1Nr#%E +z0d$}lvBa_X4}*AnY$e~UYl@1{f!*err^ret#4^%KLlXKgXXn#7Rq3H;Yh7q+|28R^ +zwkx7Xi&%!PZ-cn84&vrYh!HY?UYlI$!r$ySqd6GH=>T@c#$G6&Uk2oD@!3F*>W~0A +z;u?^h^MKpmHXgXGI3Iz~#m)hb8`R)2HUOBdqV7U9K$L@p&s-03d4VT^AnRTQa=KJt +z4(CLJDtY1tDEE3oISsmJL<9GxQ<*?M-})Zni)Rqkf}pmhPh6x_}% +zuv83kwizuj=YGZwNPCyG0;zO8emnkhhL0kFFz#^tt-sSlCo?l&$4tk`$qg}Y&o;by +zQzI=28Xt)t(hi7MrxO@TW${@j+1Q{=6{gdy)IGmg^H&?COuBPu-=kmZnlA;Q7{kNm +z*s$M`&ujN4=U-;zI<7kB$RO2w+}^_G;f98a_}}iSU%F`&OKshrK99oJ#Pi1F{2md1 +zxErH7KW%`@;SUA;kz)SWgX8A1*a{RYc&BpEHR2yrX6*|wZ{L;g6@2uw_Rl(-C-GpD +z=$^!S|H}E2@0Hc8H7`YoDtGdm%s;c0NrU8qG)Pu;^aax$66edh?pvUZu*A+MgZ$jB +z6c<{FXx5?-F?v0p1zCe=n}z-IV$-p5YkXnK-|ZS#e!{QT+R)gdUFW +zWra5;(vxq8b?Pz$>3y}7J2qe>{hPTOrIAdfb9Jo-axJy}vK_TmKmoJxA|>Iz?1Z<7 +zy2(5;?u}E#>PaO>nMO4b5BY}q5tOb>nBCJfU-!Pl8#|>Z?OwVs!v>*kkP&p(-m;I%;qa0qrEe7z>8D}qO0?Ip9PyG=?R@) +z+;QiHz#iWFYWodYcNcE8+Rm)ABhz9;DRC?wOaEcerviA@Fm)AC +z*}xO$)qITu)r2mz7&x17^S&(Di3mFeC(6PX{s_Bt7mn8bkHXAA^Xa?(Yxy`w)7_^S +TV>Bg#Z@5WtKp0!@_p|UHon4m# + +literal 0 +Hc$@ Option { + 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 { +@@ -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); + } + diff --git a/src/external-patches/firefox/corner_shape_support/D306779.patch b/src/external-patches/firefox/corner_shape_support/D306779.patch new file mode 100644 index 000000000..ce05cadd3 --- /dev/null +++ b/src/external-patches/firefox/corner_shape_support/D306779.patch @@ -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, + 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 { + 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"), + ], + }; + + diff --git a/src/external-patches/manifest.json b/src/external-patches/manifest.json index 489aabb0c..e75d33907 100644 --- a/src/external-patches/manifest.json +++ b/src/external-patches/manifest.json @@ -8,7 +8,15 @@ "D296935", "D303334", "D297660", - "D304517" + "D304517", + + "D306773", + "D306774", + "D306775", + "D306776", + "D306777", + "D306778", + "D306779" ], "name": "Corner shape support" }, diff --git a/src/zen/common/styles/zen-theme.css b/src/zen/common/styles/zen-theme.css index 9208710de..e358c4abd 100644 --- a/src/zen/common/styles/zen-theme.css +++ b/src/zen/common/styles/zen-theme.css @@ -213,7 +213,7 @@ --toolbarbutton-border-radius: 6px; --urlbar-margin-inline: 1px !important; - --zen-squircle-value: 1.3; + --zen-squircle-value: 1.4; --tab-icon-overlay-stroke: light-dark(white, black) !important; --tab-close-button-padding: 4px !important; @@ -346,6 +346,8 @@ %include zen-buttons.css -*:not(.no-squircles) { - corner-shape: superellipse(var(--zen-squircle-value)); +@media (-moz-pref('layout.css.corner-shape.enabled')) { + *:not(.no-squircles) { + corner-shape: superellipse(var(--zen-squircle-value)); + } }