Bug 1617524 - Fix crash in get_relative_transform edge case. r=jnicol
authorGlenn Watson <git@intuitionlibrary.com>
Thu, 21 May 2020 07:42:32 +0000
changeset 531501 b04340bad99d70638efda2e7d528e89df77e47c4
parent 531500 fdfb16cb82a6fd84f0ebc11e1545c429a7852989
child 531502 a2078244558da928f2df9943595ab8ad03485c29
push id37440
push userabutkovits@mozilla.com
push dateFri, 22 May 2020 09:43:16 +0000
treeherdermozilla-central@fbf71e4d2e21 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjnicol
bugs1617524
milestone78.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 1617524 - Fix crash in get_relative_transform edge case. r=jnicol Previously, WR would attempt to detect at the start of frame building if the spatial node of any picture cache contained a non-axis-aligned transform, and disable picture caching in that edge case. However, picture caching can't (currently) be disabled when the native compositor is active. In this mode, picture caching was force enabled, causing an assertion failure due to unexpected coordinate systems when updating pictures. This patch changes the way the detection of scroll root logic works such that we don't consider any scroll frame inside a reference frame to be a valid scroll root for picture caching purposes. Thus it's not possible to create a picture cache where the reference spatial node has a non-axis-aligned transform. Differential Revision: https://phabricator.services.mozilla.com/D75890
gfx/webrender_bindings/src/bindings.rs
gfx/wr/webrender/src/clip.rs
gfx/wr/webrender/src/frame_builder.rs
gfx/wr/webrender/src/prim_store/mod.rs
gfx/wr/webrender/src/spatial_node.rs
gfx/wr/webrender/src/spatial_tree.rs
gfx/wr/webrender_api/src/display_item.rs
gfx/wr/wrench/reftests/filters/reftest.list
gfx/wr/wrench/reftests/transforms/coord-system.png
gfx/wr/wrench/reftests/transforms/local-clip.png
gfx/wr/wrench/reftests/transforms/rotated-clip-large.png
layout/painting/nsDisplayList.cpp
--- a/gfx/webrender_bindings/src/bindings.rs
+++ b/gfx/webrender_bindings/src/bindings.rs
@@ -2235,16 +2235,17 @@ pub extern "C" fn wr_dp_clear_save(state
     state.frame_builder.dl_builder.clear_save();
 }
 
 #[repr(u8)]
 #[derive(PartialEq, Eq, Debug)]
 pub enum WrReferenceFrameKind {
     Transform,
     Perspective,
+    Zoom,
 }
 
 /// IMPORTANT: If you add fields to this struct, you need to also add initializers
 /// for those fields in WebRenderAPI.h.
 #[repr(C)]
 pub struct WrStackingContextParams {
     pub clip: WrStackingContextClip,
     pub animation: *const WrAnimationProperty,
@@ -2348,16 +2349,17 @@ pub extern "C" fn wr_dp_push_stacking_co
                 Some(ExternalScrollId(*scroll_id, state.pipeline_id))
             }
             None => None,
         };
 
         let reference_frame_kind = match params.reference_frame_kind {
             WrReferenceFrameKind::Transform => ReferenceFrameKind::Transform,
             WrReferenceFrameKind::Perspective => ReferenceFrameKind::Perspective { scrolling_relative_to },
+            WrReferenceFrameKind::Zoom => ReferenceFrameKind::Zoom,
         };
         wr_spatial_id = state.frame_builder.dl_builder.push_reference_frame(
             bounds.origin,
             wr_spatial_id,
             params.transform_style,
             transform_binding,
             reference_frame_kind,
         );
--- a/gfx/wr/webrender/src/clip.rs
+++ b/gfx/wr/webrender/src/clip.rs
@@ -93,17 +93,17 @@
 //!
 
 use api::{BorderRadius, ClipIntern, ClipMode, ComplexClipRegion, ImageMask};
 use api::{BoxShadowClipMode, ClipId, ImageKey, ImageRendering, PipelineId};
 use api::units::*;
 use api::image_tiling::{self, Repetition};
 use crate::border::{ensure_no_corner_overlap, BorderRadiusAu};
 use crate::box_shadow::{BLUR_SAMPLE_SCALE, BoxShadowClipSource, BoxShadowCacheKey};
-use crate::spatial_tree::{ROOT_SPATIAL_NODE_INDEX, SpatialTree, SpatialNodeIndex};
+use crate::spatial_tree::{ROOT_SPATIAL_NODE_INDEX, SpatialTree, SpatialNodeIndex, CoordinateSystemId};
 use crate::ellipse::Ellipse;
 use crate::gpu_cache::{GpuCache, GpuCacheHandle, ToGpuBlocks};
 use crate::gpu_types::{BoxShadowStretchMode};
 use crate::intern::{self, ItemUid};
 use crate::internal_types::{FastHashMap, FastHashSet};
 use crate::prim_store::{ClipData, ImageMaskData, SpaceMapper, VisibleMaskImageTile};
 use crate::prim_store::{PointKey, SizeKey, RectangleKey};
 use crate::render_task_cache::to_cache_size;
@@ -879,18 +879,37 @@ impl ClipChainStack {
             self.clips.pop().unwrap();
         }
     }
 
     /// When a surface is created, it takes all clips and establishes a new
     /// stack of clips to be propagated.
     pub fn push_surface(
         &mut self,
-        shared_clips: &[ClipInstance],
+        maybe_shared_clips: &[ClipInstance],
+        spatial_tree: &SpatialTree,
     ) {
+        let mut shared_clips = Vec::new();
+
+        // If there are clips in the shared list for a picture cache, only include
+        // them if they are simple, axis-aligned clips (i.e. in the root coordinate
+        // system). This is necessary since when compositing picture cache tiles
+        // into the parent, we don't support applying a clip mask. This only ever
+        // occurs in wrench tests, not in display lists supplied by Gecko.
+        // TODO(gw): We can remove this when we update the WR API to have better
+        //           knowledge of what coordinate system a clip must be in (by
+        //           knowing if a reference frame exists in the chain between the
+        //           clip's spatial node and the picture cache reference spatial node).
+        for clip in maybe_shared_clips {
+            let spatial_node = &spatial_tree.spatial_nodes[clip.spatial_node_index.0 as usize];
+            if spatial_node.coordinate_system_id == CoordinateSystemId::root() {
+                shared_clips.push(*clip);
+            }
+        }
+
         let level = ClipChainLevel {
             shared_clips: shared_clips.to_vec(),
             first_clip_index: self.clips.len(),
             initial_clip_counts_len: self.clip_counts.len(),
         };
 
         self.levels.push(level);
     }
--- a/gfx/wr/webrender/src/frame_builder.rs
+++ b/gfx/wr/webrender/src/frame_builder.rs
@@ -1,17 +1,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 use api::{ColorF, DebugFlags, DocumentLayer, FontRenderMode, PremultipliedColorF};
 use api::units::*;
 use crate::batch::{BatchBuilder, AlphaBatchBuilder, AlphaBatchContainer};
 use crate::clip::{ClipStore, ClipChainStack, ClipInstance};
-use crate::spatial_tree::{SpatialTree, ROOT_SPATIAL_NODE_INDEX, SpatialNodeIndex, CoordinateSystemId};
+use crate::spatial_tree::{SpatialTree, ROOT_SPATIAL_NODE_INDEX, SpatialNodeIndex};
 use crate::composite::{CompositorKind, CompositeState};
 use crate::debug_render::DebugItem;
 use crate::gpu_cache::{GpuCache, GpuCacheHandle};
 use crate::gpu_types::{PrimitiveHeaders, TransformPalette, UvRectKind, ZBufferIdGenerator};
 use crate::gpu_types::TransformData;
 use crate::internal_types::{FastHashMap, PlaneSplitter, SavedTargetIndex};
 use crate::picture::{PictureUpdateState, SurfaceInfo, ROOT_SURFACE_INDEX, SurfaceIndex, RecordedDirtyRegion};
 use crate::picture::{RetainedTiles, TileCacheInstance, DirtyRegion, SurfaceRenderTasks, SubpixelMode};
@@ -148,20 +148,21 @@ pub struct FrameVisibilityState<'a> {
     /// visibility frame traversal.
     pub surface_stack: Vec<SurfaceIndex>,
 }
 
 impl<'a> FrameVisibilityState<'a> {
     pub fn push_surface(
         &mut self,
         surface_index: SurfaceIndex,
-        shared_clips: &[ClipInstance]
+        shared_clips: &[ClipInstance],
+        spatial_tree: &SpatialTree,
     ) {
         self.surface_stack.push(surface_index);
-        self.clip_chain_stack.push_surface(shared_clips);
+        self.clip_chain_stack.push_surface(shared_clips, spatial_tree);
     }
 
     pub fn pop_surface(&mut self) {
         self.surface_stack.pop().unwrap();
         self.clip_chain_stack.pop_surface();
     }
 }
 
@@ -561,18 +562,17 @@ impl FrameBuilder {
         // (4) If any picture cache spatial nodes are not in the root coordinate system
         let picture_caching_is_enabled =
             scene.config.global_enable_picture_caching &&
             !debug_flags.contains(DebugFlags::DISABLE_PICTURE_CACHING) &&
             !scene.picture_cache_spatial_nodes.iter().any(|spatial_node_index| {
                 let spatial_node = &scene
                     .spatial_tree
                     .spatial_nodes[spatial_node_index.0 as usize];
-                spatial_node.coordinate_system_id != CoordinateSystemId::root() ||
-                    spatial_node.is_ancestor_or_self_zooming
+                spatial_node.is_ancestor_or_self_zooming
             });
 
         let mut composite_state = CompositeState::new(
             scene.config.compositor_kind,
             picture_caching_is_enabled,
             global_device_pixel_scale,
             scene.config.max_depth_ids,
         );
--- a/gfx/wr/webrender/src/prim_store/mod.rs
+++ b/gfx/wr/webrender/src/prim_store/mod.rs
@@ -1901,22 +1901,30 @@ impl PrimitiveStore {
                         layout_rect_as_picture_rect(&pic.estimated_local_rect),
                         surface_index,
                         frame_context,
                         frame_state,
                     );
 
                     // Push a new surface, supplying the list of clips that should be
                     // ignored, since they are handled by clipping when drawing this surface.
-                    frame_state.push_surface(surface_index, &tile_cache.shared_clips);
+                    frame_state.push_surface(
+                        surface_index,
+                        &tile_cache.shared_clips,
+                        frame_context.spatial_tree,
+                    );
                     frame_state.tile_cache = Some(tile_cache);
                 }
                 _ => {
                     if is_composite {
-                        frame_state.push_surface(surface_index, &[]);
+                        frame_state.push_surface(
+                            surface_index,
+                            &[],
+                            frame_context.spatial_tree,
+                        );
                     }
                 }
             }
 
             (prim_list, surface_index, pic.apply_local_clip_rect, world_culling_rect, is_composite)
         };
 
         let surface = &frame_context.surfaces[surface_index.0 as usize];
--- a/gfx/wr/webrender/src/spatial_node.rs
+++ b/gfx/wr/webrender/src/spatial_node.rs
@@ -335,17 +335,17 @@ impl SpatialNode {
 
                             // Do a change-basis operation on the
                             // perspective matrix using the scroll offset.
                             source_transform
                                 .pre_translate(scroll_offset)
                                 .post_translate(-scroll_offset)
                         }
                         ReferenceFrameKind::Perspective { scrolling_relative_to: None } |
-                        ReferenceFrameKind::Transform => source_transform,
+                        ReferenceFrameKind::Transform | ReferenceFrameKind::Zoom => source_transform,
                     };
 
                     let resolved_transform =
                         LayoutFastTransform::with_vector(info.origin_in_parent_reference_frame)
                             .pre_transform(&source_transform);
 
                     // The transformation for this viewport in world coordinates is the transformation for
                     // our parent reference frame, plus any accumulated scrolling offsets from nodes
--- a/gfx/wr/webrender/src/spatial_tree.rs
+++ b/gfx/wr/webrender/src/spatial_tree.rs
@@ -626,25 +626,40 @@ impl SpatialTree {
         spatial_node_index: SpatialNodeIndex,
     ) -> SpatialNodeIndex {
         let mut scroll_root = ROOT_SPATIAL_NODE_INDEX;
         let mut node_index = spatial_node_index;
 
         while node_index != ROOT_SPATIAL_NODE_INDEX {
             let node = &self.spatial_nodes[node_index.0 as usize];
             match node.node_type {
-                SpatialNodeType::ReferenceFrame(..) |
-                SpatialNodeType::StickyFrame(..) => {
-                    // TODO(gw): In future, we may need to consider sticky frames.
+                SpatialNodeType::ReferenceFrame(ref info) => {
+                    match info.kind {
+                        ReferenceFrameKind::Zoom => {
+                            // We can handle scroll nodes that pass through a zoom node
+                        }
+                        ReferenceFrameKind::Transform |
+                        ReferenceFrameKind::Perspective { .. } => {
+                            // When a reference frame is encountered, forget any scroll roots
+                            // we have encountered, as they may end up with a non-axis-aligned transform.
+                            scroll_root = ROOT_SPATIAL_NODE_INDEX;
+                        }
+                    }
                 }
+                SpatialNodeType::StickyFrame(..) => {}
                 SpatialNodeType::ScrollFrame(ref info) => {
-                    // If we found an explicit scroll root, store that
-                    // and keep looking up the tree.
-                    if let ScrollFrameKind::Explicit = info.frame_kind {
-                        scroll_root = node_index;
+                    match info.frame_kind {
+                        ScrollFrameKind::PipelineRoot => {
+                            // Once we encounter a pipeline root, there is no need to look further
+                            break;
+                        }
+                        ScrollFrameKind::Explicit => {
+                            // Store the explicit scroll root, keep looking up the tree
+                            scroll_root = node_index;
+                        }
                     }
                 }
             }
             node_index = node.parent.expect("unable to find parent node");
         }
 
         scroll_root
     }
--- a/gfx/wr/webrender_api/src/display_item.rs
+++ b/gfx/wr/webrender_api/src/display_item.rs
@@ -706,17 +706,21 @@ pub struct BackdropFilterDisplayItem {
 pub struct ReferenceFrameDisplayListItem {
     pub origin: LayoutPoint,
     pub parent_spatial_id: SpatialId,
     pub reference_frame: ReferenceFrame,
 }
 
 #[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize, PeekPoke)]
 pub enum ReferenceFrameKind {
+    /// Zoom reference frames must be a scale + translation only
+    Zoom,
+    /// A normal transform matrix, may contain perspective (the CSS transform property)
     Transform,
+    /// A perspective transform, that optionally scrolls relative to a specific scroll node
     Perspective {
         scrolling_relative_to: Option<ExternalScrollId>,
     }
 }
 
 #[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
 pub struct ReferenceFrame {
     pub kind: ReferenceFrameKind,
--- a/gfx/wr/wrench/reftests/filters/reftest.list
+++ b/gfx/wr/wrench/reftests/filters/reftest.list
@@ -53,15 +53,15 @@ skip_on(android,device) fuzzy(1,104) == 
 == svg-filter-component-transfer.yaml filter-component-transfer-ref.yaml
 == svg-filter-flood.yaml svg-filter-flood-ref.yaml
 skip_on(android,device) == svg-filter-blend.yaml svg-filter-blend-ref.yaml
 skip_on(android,device) == svg-filter-color-matrix.yaml filter-color-matrix-ref.yaml  # fails on Pixel2
 platform(linux,mac) == draw_calls(8) color_targets(8) alpha_targets(0) svg-filter-blur.yaml filter-blur.png # Extra draw call is due to render task graph workaround
 platform(linux,mac) == svg-filter-drop-shadow.yaml svg-filter-drop-shadow.png
 == fuzzy(1,10000) svg-srgb-to-linear.yaml srgb-to-linear-ref.yaml
 platform(linux,mac) == fuzzy(4,28250) svg-filter-drop-shadow-rotate.yaml svg-filter-drop-shadow-rotate-ref.yaml
-platform(linux,mac) == svg-filter-blur-transforms.yaml svg-filter-blur-transforms.png
+platform(linux,mac) fuzzy(3,3184) == svg-filter-blur-transforms.yaml svg-filter-blur-transforms.png
 platform(linux,mac) == svg-filter-drop-shadow-on-viewport-edge.yaml svg-filter-drop-shadow-on-viewport-edge.png
 platform(linux,mac) == svg-filter-drop-shadow-perspective.yaml svg-filter-drop-shadow-perspective.png
 == backdrop-filter-basic.yaml backdrop-filter-basic-ref.yaml
 platform(linux,mac) == backdrop-filter-perspective.yaml backdrop-filter-perspective.png
 platform(linux,max) == svg-filter-offset.yaml svg-filter-offset-ref.yaml
 skip_on(android,device) == fuzzy(1,100) svg-filter-composite.yaml svg-filter-composite-ref.yaml
index e18a5b8746fb397d9bbba9e31b72fac00d276b3d..d28a562186a3e4252397655131c6173d7ce7eea1
GIT binary patch
literal 4234
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
UBenf`w*lxo>gb9sJ8~}JUpPsFr~m)}
index 88fcc870f996e059c019f7e9017afb3e9e11aab4..21fcf7de8fd7c64d050469eccd0fdc1f3159d237
GIT binary patch
literal 2187
zc%1E)|4$ob9LKNovOPyOb5HBERDS5)wOt5ow5yO3zhIv|J-)2#2y+-Ix>~ZybO9R7
zGNTLRc82RX*rwZPCIROZ;tzC1maGZlym(;}Ty$|{Xr?q6Gu_JUFfvS-_%QHKFwuk`
z?uYxl-p}XrJn#2C$weyzr5my=SrkQWC@;fR6lM5;JPELtRBms4d6A+(RXO%Pcc^=2
zVmz|(dCGV7p!l%l1V>zz{@l?=a<|$H!Rxzcj8<l3=cU8LQ#I$B`N@|1zlRL13TrrS
z<f$q|KU<+tWelWpxiwZhraqKG>&aEP3jdc-+x}V0p3~>|bp8BATiZhiyh^HAK)+2D
zj9+XVpS^p|tcfz{nf0JNm$U=Gg<Btk0Ug8xN@}o+zhL1k-ZgQgg#I`K21G?X-rCN<
z_5HZM5IrH$wOC1YuhfSacyH#Ne_jB*ciRGMI@k`YVUvl!^KGH9+$+H28@-!X8o#td
zNfrdf<z}BAWg{gG@azP*3XGXjq#sW1m8%6TlzrYVD?jC}tm(1ioM85f%EnD6_bK1J
zD%aD@d<PrxyM4>e7O>*!$rdgcg{5-7yR_aeW=!0)XO2C4%B(HQO5NlxxjIZQLVm9C
z7_5mx0M}*i{P4+Jf6h7&R;bBlr2ln)elWlHnJ7%3WFzat^e`FSX4bYa@G>tZo<#ax
z1*XZa{RDA1r;8u}FFQo%)7<pD4*DGU#yXd@pBS@E4ONf>K_S-3Mp_6WE^H!**tA^@
zWf5c&zGR>RNn~qXlFDios+Gf;m|45Rz=aAm)ki|&#U?kRzlK7R;iN7F9v~s@)IpIQ
zXDng*J;)#0{2;?_q^54kAYd1pb|d;GD<mzP)EtGiZ?l?R2U{GtDc2>n16X^+tbHeg
zxKB;xBl@~cY}(36ubBi-l+_;90f{G+7pBkiIAM25B}RVoj9F`!L4#LKy@2S8yhs9&
zf)6~_2BMId{(j=7dE||u{N9p+@u`-QoMboa-FwVs<ch4g^7~yXRyqK@HpdDuybaOr
zSh2|KqcYg%sw3!emXD43iMRnPp(3|lCMP*g%09JJ@hhQfAJMe3+E)$P0_1t@91ao*
zU|?E1O(bDNzd5)hVE{~z71r61pM1BCaY$zIguPx)*cf3G#YF9};lwNbWPOa>kRL}J
zWFNW=I#VB+qwKpT-gC4+Y(r@>?Zi`^C%~Wy(WOJ9zsv+-__6=yHD87Q7QA-J+4t-I
TD=)?k<R^nF_XThqg`~d$U59TC
index a9c0efbe00324f94a47c77e0869ac7748e476174..88d2eda08523205e54163e5b89ea5e3f941c3b4d
GIT binary patch
literal 7421
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
NM*64q3Qjm*{SQAMz{dap
--- a/layout/painting/nsDisplayList.cpp
+++ b/layout/painting/nsDisplayList.cpp
@@ -6343,16 +6343,19 @@ bool nsDisplayOwnLayer::CreateWebRenderC
   params.clip =
       wr::WrStackingContextClip::ClipChain(aBuilder.CurrentClipChainId());
   if (IsScrollbarContainer()) {
     params.prim_flags |= wr::PrimitiveFlags::IS_SCROLLBAR_CONTAINER;
   }
   if (IsScrollThumbLayer()) {
     params.prim_flags |= wr::PrimitiveFlags::IS_SCROLLBAR_THUMB;
   }
+  if (IsZoomingLayer()) {
+    params.reference_frame_kind = wr::WrReferenceFrameKind::Zoom;
+  }
   StackingContextHelper sc(aSc, GetActiveScrolledRoot(), mFrame, this, aBuilder,
                            params);
 
   nsDisplayWrapList::CreateWebRenderCommands(aBuilder, aResources, sc, aManager,
                                              aDisplayListBuilder);
   return true;
 }