Bug 1550725 - Cull primitives with an empty clip. r=kvark
authorAndrew Osmond <aosmond@mozilla.com>
Fri, 10 May 2019 11:17:10 -0400
changeset 532325 0849b28c8e3db984273f97a8d6ea4f7284802f49
parent 532324 13e26dbd7cc7799690ea1cc4e4e1c35fb3de927b
child 532326 2c874d7d890cd9a96aeef5de5acf4c24c4e78bd8
push id11265
push userffxbld-merge
push dateMon, 13 May 2019 10:53:39 +0000
treeherdermozilla-beta@77e0fe8dbdd3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskvark
bugs1550725
milestone68.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 1550725 - Cull primitives with an empty clip. r=kvark When the clip chain generates the local clip rect for a primitive, it can be empty. This violated the assumption that the visible rect will never be empty, and so when we snap, it produces NaNs, which in turn, violates other assumptions when converting between spaces, and hence the crash. Now we cull the primitive from the visible list if the local clip rect is empty, or if the visible rect is empty. Differential Revision: https://phabricator.services.mozilla.com/D30659
gfx/wr/webrender/src/prim_store/mod.rs
--- a/gfx/wr/webrender/src/prim_store/mod.rs
+++ b/gfx/wr/webrender/src/prim_store/mod.rs
@@ -2023,27 +2023,44 @@ impl PrimitiveStore {
                 };
 
                 let combined_local_clip_rect = if apply_local_clip_rect {
                     clip_chain.local_clip_rect
                 } else {
                     prim_instance.local_clip_rect
                 };
 
+                if combined_local_clip_rect.size.is_empty_or_negative() {
+                    debug_assert!(combined_local_clip_rect.size.width >= 0.0 &&
+                                  combined_local_clip_rect.size.height >= 0.0);
+                    if prim_instance.is_chased() {
+                        println!("\tculled for zero local clip rectangle");
+                    }
+                    prim_instance.visibility_info = PrimitiveVisibilityIndex::INVALID;
+                    continue;
+                }
+
                 // All pictures must snap to their primitive rect instead of the
                 // visible rect like most primitives. This is because the picture's
                 // visible rect includes the effect of the picture's clip rect,
                 // which was not considered by the picture's children. The primitive
                 // rect however is simply the union of the visible rect of the
                 // children, which they snapped to, which is precisely what we also
                 // need to snap to in order to be consistent.
                 let visible_rect = if snap_to_visible {
-                    combined_local_clip_rect
-                        .intersection(&prim_local_rect)
-                        .unwrap_or(LayoutRect::zero())
+                    match combined_local_clip_rect.intersection(&prim_local_rect) {
+                        Some(r) => r,
+                        None => {
+                            if prim_instance.is_chased() {
+                                println!("\tculled for zero visible rectangle");
+                            }
+                            prim_instance.visibility_info = PrimitiveVisibilityIndex::INVALID;
+                            continue;
+                        }
+                    }
                 } else {
                     prim_local_rect
                 };
 
                 // This is how primitives get snapped. In general, snapping a picture's
                 // visible rect here will have no effect, but if it is rasterized in its
                 // own space, or it has a blur or drop shadow effect applied, it may
                 // provide a snapping offset.