Bug 1604827 - Workaround for stale tile content in native compositor mode. r=sotaro
authordev <dev@devs-MacBook-Pro.local>
Thu, 19 Dec 2019 01:38:34 +0000
changeset 507684 2dd771769da78bd16ddc7d4928030e5ae8a9ac90
parent 507683 fb2a454b4f66d1fdb7eef474605743a7b9ac658c
child 507685 70c7a9fa71304413d9acaa4eabe0df85d87f7522
push id36931
push useropoprus@mozilla.com
push dateThu, 19 Dec 2019 09:50:06 +0000
treeherdermozilla-central@5e8b48c8cd93 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssotaro
bugs1604827
milestone73.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 1604827 - Workaround for stale tile content in native compositor mode. r=sotaro Differential Revision: https://phabricator.services.mozilla.com/D57711
gfx/wr/webrender/src/picture.rs
--- a/gfx/wr/webrender/src/picture.rs
+++ b/gfx/wr/webrender/src/picture.rs
@@ -873,19 +873,31 @@ impl Tile {
         // (and thus updated / invalidated) until it is on screen again.
         if !self.is_visible {
             return false;
         }
 
         // Invalidate the tile based on the content changing.
         self.update_content_validity(ctx, state);
 
-        // If there are no primitives there is no need to draw or cache it.
-        if self.current_descriptor.prims.is_empty() {
-            return false;
+        // TODO(gw): This is a hack / temporary bug fix. With the recent changes
+        //           to treat native surfaces as an entire surface, we need to
+        //           skip the optimization that drops empty tiles within the
+        //           surface area. This has some unfortunate performance implications
+        //           in some cases, so we'll need a proper fix for this, but this
+        //           should fix correctness for now, at least.
+        match state.composite_state.compositor_kind {
+            CompositorKind::Draw { .. } => {
+                // If there are no primitives there is no need to draw or cache it.
+                if self.current_descriptor.prims.is_empty() {
+                    return false;
+                }
+            }
+            CompositorKind::Native { .. } => {
+            }
         }
 
         // Check if this tile can be considered opaque. Opacity state must be updated only
         // after all early out checks have been performed. Otherwise, we might miss updating
         // the native surface next time this tile becomes visible.
         let tile_is_opaque = ctx.backdrop.rect.contains_rect(&self.clipped_rect);
         let opacity_changed = tile_is_opaque != self.is_opaque;
         self.is_opaque = tile_is_opaque;
@@ -1917,17 +1929,17 @@ impl TileCacheInstance {
             }
         }
 
         // Any old tiles that remain after the loop above are going to be dropped. For
         // simple composite mode, the texture cache handle will expire and be collected
         // by the texture cache. For native compositor mode, we need to explicitly
         // invoke a callback to the client to destroy that surface.
         frame_state.composite_state.destroy_native_tiles(
-            self.old_tiles.values(),
+            self.old_tiles.values_mut(),
             frame_state.resource_cache,
         );
 
         world_culling_rect
     }
 
     /// Update the dependencies for each tile for a given primitive instance.
     pub fn update_prim_dependencies(
@@ -5223,31 +5235,31 @@ impl TileNode {
                 }
             }
         }
     }
 }
 
 impl CompositeState {
     // A helper function to destroy all native surfaces for a given list of tiles
-    pub fn destroy_native_tiles<'a, I: Iterator<Item = &'a Tile>>(
+    pub fn destroy_native_tiles<'a, I: Iterator<Item = &'a mut Tile>>(
         &mut self,
         tiles_iter: I,
         resource_cache: &mut ResourceCache,
     ) {
         // Any old tiles that remain after the loop above are going to be dropped. For
         // simple composite mode, the texture cache handle will expire and be collected
         // by the texture cache. For native compositor mode, we need to explicitly
         // invoke a callback to the client to destroy that surface.
         if let CompositorKind::Native { .. } = self.compositor_kind {
             for tile in tiles_iter {
                 // Only destroy native surfaces that have been allocated. It's
                 // possible for display port tiles to be created that never
                 // come on screen, and thus never get a native surface allocated.
-                if let Some(TileSurface::Texture { descriptor: SurfaceTextureDescriptor::Native { id, .. }, .. }) = tile.surface {
-                    if let Some(id) = id {
+                if let Some(TileSurface::Texture { descriptor: SurfaceTextureDescriptor::Native { ref mut id, .. }, .. }) = tile.surface {
+                    if let Some(id) = id.take() {
                         resource_cache.destroy_compositor_tile(id);
                     }
                 }
             }
         }
     }
 }