Bug 1571974: Make prim_store::get_line_decoration_sizes return an oriented LayoutSize. r=kvark
☠☠ backed out by 801277ae423f ☠ ☠
authorJim Blandy <jimb@mozilla.com>
Mon, 03 Feb 2020 09:31:22 +0000
changeset 512396 3549dd471446c291864822736f4587c81741cd56
parent 512395 9f8766e42efea809351839114d64085d7518adf9
child 512397 dfb21632ea198c1acdc6a34ee08113d516f666d5
push id37087
push usernbeleuzu@mozilla.com
push dateTue, 04 Feb 2020 04:04:16 +0000
treeherdermozilla-central@c32017c40f19 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskvark
bugs1571974
milestone74.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1571974: Make prim_store::get_line_decoration_sizes return an oriented LayoutSize. r=kvark Without this change, get_line_decoration_sizes returns an (inline_size, block_size) pair, where inline_size is parallel to the line being decorated, and block_size perpendicular. However, these values are generally used as the dimensions of an axis-aligned bounding box for the line, not as specific parameters to the rendering process, so it makes sense to arrange them into a LayoutSize value in this function, since it is already taking the orientation into account anyway. The caller, SceneBuilder::add_line, then doesn't need to swap the components, and the adjustment of the clipping rectangle to avoid partial dots looks a bit more natural: widths with widths, heights with heights. Differential Revision: https://phabricator.services.mozilla.com/D60925
gfx/wr/webrender/src/prim_store/mod.rs
gfx/wr/webrender/src/scene_building.rs
--- a/gfx/wr/webrender/src/prim_store/mod.rs
+++ b/gfx/wr/webrender/src/prim_store/mod.rs
@@ -4124,59 +4124,82 @@ pub fn get_raster_rects(
     // Ensure that we won't try to allocate a zero-sized clip render task.
     if clipped.is_empty() {
         return None;
     }
 
     Some((clipped.to_i32(), unclipped))
 }
 
-/// Get the inline (horizontal) and block (vertical) sizes
-/// for a given line decoration.
-pub fn get_line_decoration_sizes(
+/// Choose the decoration mask tile size for a given line.
+///
+/// Given a line with overall size `rect_size` and the given `orientation`,
+/// return the dimensions of a single mask tile for the decoration pattern
+/// described by `style` and `wavy_line_thickness`.
+///
+/// If `style` is `Solid`, no mask tile is necessary; return `None`. The other
+/// styles each have their own characteristic periods of repetition, so for each
+/// one, this function returns a `LayoutSize` with the right aspect ratio and
+/// whose specific size is convenient for the `cs_line_decoration.glsl` fragment
+/// shader to work with. The shader uses a local coordinate space in which the
+/// tile fills a rectangle with one corner at the origin, and with the size this
+/// function returns.
+///
+/// The returned size is not necessarily in pixels; device scaling and other
+/// concerns can still affect the actual task size.
+///
+/// Regardless of whether `orientation` is `Vertical` or `Horizontal`, the
+/// `width` and `height` of the returned size are always horizontal and
+/// vertical, respectively.
+pub fn get_line_decoration_size(
     rect_size: &LayoutSize,
     orientation: LineOrientation,
     style: LineStyle,
     wavy_line_thickness: f32,
-) -> Option<(f32, f32)> {
+) -> Option<LayoutSize> {
     let h = match orientation {
         LineOrientation::Horizontal => rect_size.height,
         LineOrientation::Vertical => rect_size.width,
     };
 
     // TODO(gw): The formulae below are based on the existing gecko and line
     //           shader code. They give reasonable results for most inputs,
     //           but could definitely do with a detailed pass to get better
     //           quality on a wider range of inputs!
     //           See nsCSSRendering::PaintDecorationLine in Gecko.
 
-    match style {
+    let (parallel, perpendicular) = match style {
         LineStyle::Solid => {
-            None
+            return None;
         }
         LineStyle::Dashed => {
             let dash_length = (3.0 * h).min(64.0).max(1.0);
 
-            Some((2.0 * dash_length, 4.0))
+            (2.0 * dash_length, 4.0)
         }
         LineStyle::Dotted => {
             let diameter = h.min(64.0).max(1.0);
             let period = 2.0 * diameter;
 
-            Some((period, diameter))
+            (period, diameter)
         }
         LineStyle::Wavy => {
             let line_thickness = wavy_line_thickness.max(1.0);
             let slope_length = h - line_thickness;
             let flat_length = ((line_thickness - 1.0) * 2.0).max(1.0);
             let approx_period = 2.0 * (slope_length + flat_length);
 
-            Some((approx_period, h))
+            (approx_period, h)
         }
-    }
+    };
+
+    Some(match orientation {
+        LineOrientation::Horizontal => LayoutSize::new(parallel, perpendicular),
+        LineOrientation::Vertical => LayoutSize::new(perpendicular, parallel),
+    })
 }
 
 fn update_opacity_binding(
     opacity_bindings: &mut OpacityBindingStorage,
     opacity_binding_index: OpacityBindingIndex,
     scene_properties: &SceneProperties,
 ) -> f32 {
     if opacity_binding_index == OpacityBindingIndex::INVALID {
--- a/gfx/wr/webrender/src/scene_building.rs
+++ b/gfx/wr/webrender/src/scene_building.rs
@@ -22,17 +22,17 @@ use crate::image::simplify_repeated_prim
 use crate::intern::Interner;
 use crate::internal_types::{FastHashMap, FastHashSet, LayoutPrimitiveInfo, Filter};
 use crate::picture::{Picture3DContext, PictureCompositeMode, PicturePrimitive, PictureOptions};
 use crate::picture::{BlitReason, OrderedPictureChild, PrimitiveList, TileCacheInstance, ClusterFlags};
 use crate::prim_store::{PrimitiveInstance, PrimitiveSceneData};
 use crate::prim_store::{PrimitiveInstanceKind, NinePatchDescriptor, PrimitiveStore};
 use crate::prim_store::{ScrollNodeAndClipChain, PictureIndex};
 use crate::prim_store::{InternablePrimitive, SegmentInstanceIndex};
-use crate::prim_store::{register_prim_chase_id, get_line_decoration_sizes};
+use crate::prim_store::{register_prim_chase_id, get_line_decoration_size};
 use crate::prim_store::{SpaceSnapper};
 use crate::prim_store::backdrop::Backdrop;
 use crate::prim_store::borders::{ImageBorder, NormalBorderPrim};
 use crate::prim_store::gradient::{GradientStopKey, LinearGradient, RadialGradient, RadialGradientParams};
 use crate::prim_store::image::{Image, YuvImage};
 use crate::prim_store::line_dec::{LineDecoration, LineDecorationCacheKey};
 use crate::prim_store::picture::{Picture, PictureCompositeKey, PictureKey};
 use crate::prim_store::text_run::TextRun;
@@ -2744,43 +2744,38 @@ impl<'a> SceneBuilder<'a> {
         color: ColorF,
         style: LineStyle,
     ) {
         // For line decorations, we can construct the render task cache key
         // here during scene building, since it doesn't depend on device
         // pixel ratio or transform.
         let mut info = info.clone();
 
-        let size = get_line_decoration_sizes(
+        let size = get_line_decoration_size(
             &info.rect.size,
             orientation,
             style,
             wavy_line_thickness,
         );
 
-        let cache_key = size.map(|(inline_size, block_size)| {
-            let size = match orientation {
-                LineOrientation::Horizontal => LayoutSize::new(inline_size, block_size),
-                LineOrientation::Vertical => LayoutSize::new(block_size, inline_size),
-            };
-
+        let cache_key = size.map(|size| {
             // If dotted, adjust the clip rect to ensure we don't draw a final
             // partial dot.
             if style == LineStyle::Dotted {
                 let clip_size = match orientation {
                     LineOrientation::Horizontal => {
                         LayoutSize::new(
-                            inline_size * (info.rect.size.width / inline_size).floor(),
+                            size.width * (info.rect.size.width / size.width).floor(),
                             info.rect.size.height,
                         )
                     }
                     LineOrientation::Vertical => {
                         LayoutSize::new(
                             info.rect.size.width,
-                            inline_size * (info.rect.size.height / inline_size).floor(),
+                            size.height * (info.rect.size.height / size.height).floor(),
                         )
                     }
                 };
                 let clip_rect = LayoutRect::new(
                     info.rect.origin,
                     clip_size,
                 );
                 info.clip_rect = clip_rect