Bug 1579235 - Part 8 - Remove overlay tiles, they can be alpha tiles instead. r=nical
authorGlenn Watson <gw@intuitionlibrary.com>
Mon, 02 Mar 2020 10:07:23 +0000
changeset 516370 38b7f4761f5041a0e3b2326c2be37f98da509e21
parent 516369 02c2d6aeb09a5f4a4677e3c7d839db86c79964a1
child 516371 097aecdda3d06ebdf7b41e5d27f42f73a4e8f816
push id37173
push userbtara@mozilla.com
push dateMon, 02 Mar 2020 21:27:32 +0000
treeherdermozilla-central@c32706293416 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnical
bugs1579235
milestone75.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 1579235 - Part 8 - Remove overlay tiles, they can be alpha tiles instead. r=nical A previous patch in this series introduced overlay tiles. However, now that native surfaces exist for for the opaque and alpha tiles within a slice, we can remove the overlay tiles array and add these special tiles to the alpha surface. Differential Revision: https://phabricator.services.mozilla.com/D64899
gfx/wr/webrender/src/composite.rs
gfx/wr/webrender/src/picture.rs
--- a/gfx/wr/webrender/src/composite.rs
+++ b/gfx/wr/webrender/src/composite.rs
@@ -66,39 +66,27 @@ pub enum CompositeTileSurface {
 
 /// The surface format for a tile being composited.
 #[derive(Debug, Copy, Clone)]
 pub enum CompositeSurfaceFormat {
     Rgba,
     Yuv,
 }
 
-/// The ordering that this tile should be composited with.
-#[cfg_attr(feature = "capture", derive(Serialize))]
-#[cfg_attr(feature = "replay", derive(Deserialize))]
-#[derive(Debug, Copy, Clone)]
-pub enum TileCompositeMode {
-    /// Normal z-ordering for this tile
-    Default,
-    /// This tile overlaps a compositor surface - draw it after them
-    Over,
-}
-
 /// Describes the geometry and surface of a tile to be composited
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
 pub struct CompositeTile {
     pub surface: CompositeTileSurface,
     pub rect: DeviceRect,
     pub clip_rect: DeviceRect,
     pub dirty_rect: DeviceRect,
     pub valid_rect: DeviceRect,
     pub z_id: ZBufferId,
     pub tile_id: Option<NativeTileId>,
-    pub mode: TileCompositeMode,
 }
 
 /// Describes information about drawing a primitive as a compositor surface.
 /// For now, we support only YUV images as compositor surfaces, but in future
 /// this will also support RGBA images.
 pub struct ExternalSurfaceDescriptor {
     pub local_rect: PictureRect,
     pub device_rect: DeviceRect,
@@ -418,43 +406,24 @@ impl CompositeState {
             };
 
             if is_opaque {
                 visible_opaque_tile_count += 1;
             } else {
                 visible_alpha_tile_count += 1;
             }
 
-            // Determine ordering of this tile, based on presence of compositor
-            // surfaces that intersect the tile.
-            let mut mode = TileCompositeMode::Default;
-
-            if tile.has_compositor_surface {
-                // TODO(gw): This will almost always select over blend, due to the
-                //           background rectangle. In future, we can optimize this
-                //           case to only check items that come _after_ the compositor
-                //           surface z_id? A better option might be to tweak the z_id
-                //           values so that the alpha pixels get z-rejected?
-                for surface in &tile_cache.external_surfaces {
-                    if surface.device_rect.intersects(&tile.device_valid_rect) {
-                        mode = TileCompositeMode::Over;
-                        break;
-                    }
-                }
-            }
-
             let tile = CompositeTile {
                 surface,
                 rect: device_rect,
                 valid_rect: tile.device_valid_rect.translate(-device_rect.origin.to_vector()),
                 dirty_rect: tile.device_dirty_rect.translate(-device_rect.origin.to_vector()),
                 clip_rect: device_clip_rect,
                 z_id,
                 tile_id,
-                mode,
             };
 
             self.push_tile(tile, is_opaque);
         }
 
         // For each compositor surface that was promoted, build the
         // information required for the compositor to draw it
         for external_surface in &tile_cache.external_surfaces {
@@ -559,29 +528,22 @@ impl CompositeState {
                 // tiles if we ever find pages that have a lot of these.
                 self.opaque_tiles.push(tile);
             }
             CompositeTileSurface::Clear => {
                 // Clear tiles have a special bucket
                 self.clear_tiles.push(tile);
             }
             CompositeTileSurface::Texture { .. } => {
-                match tile.mode {
-                    TileCompositeMode::Default => {
-                        // Texture surfaces get bucketed by opaque/alpha, for z-rejection
-                        // on the Draw compositor mode.
-                        if is_opaque {
-                            self.opaque_tiles.push(tile);
-                        } else {
-                            self.alpha_tiles.push(tile);
-                        }
-                    }
-                    TileCompositeMode::Over => {
-                        self.alpha_tiles.push(tile);
-                    }
+                // Texture surfaces get bucketed by opaque/alpha, for z-rejection
+                // on the Draw compositor mode.
+                if is_opaque {
+                    self.opaque_tiles.push(tile);
+                } else {
+                    self.alpha_tiles.push(tile);
                 }
             }
         }
     }
 }
 
 /// An arbitrary identifier for a native (OS compositor) surface
 #[repr(C)]
--- a/gfx/wr/webrender/src/picture.rs
+++ b/gfx/wr/webrender/src/picture.rs
@@ -64,32 +64,32 @@
 //! picture caching to. If that's not found, it will apply to the entire root
 //! stacking context of the display list. Apart from that, the format of the
 //! display list is not important to picture caching. Each time a new scroll root
 //! is encountered, a new picture cache slice will be created. If the display
 //! list contains more than some arbitrary number of slices (currently 8), the
 //! content will all be squashed into a single slice, in order to save GPU memory
 //! and compositing performance.
 //!
-//! ## Overlay Tiles
+//! ## Compositor Surfaces
 //!
 //! Sometimes, a primitive would prefer to exist as a native compositor surface.
 //! This allows a large and/or regularly changing primitive (such as a video, or
 //! webgl canvas) to be updated each frame without invalidating the content of
 //! tiles, and can provide a significant performance win and battery saving.
 //!
 //! Since drawing a primitive as a compositor surface alters the ordering of
 //! primitives in a tile, we use 'overlay tiles' to ensure correctness. If a
 //! tile has a compositor surface, _and_ that tile has primitives that overlap
-//! the compositor surface rect, the tile switches to be drawn in overlay mode.
+//! the compositor surface rect, the tile switches to be drawn in alpha mode.
 //!
 //! We rely on only promoting compositor surfaces that are opaque primitives.
 //! With this assumption, the tile(s) that intersect the compositor surface get
 //! a 'cutout' in the rectangle where the compositor surface exists (not the
-//! entire tile), allowing that tile to be drawn as an overlay after the
+//! entire tile), allowing that tile to be drawn as an alpha tile after the
 //! compositor surface.
 //!
 //! Tiles are only drawn in overlay mode if there is content that exists on top
 //! of the compositor surface. Otherwise, we can draw the tiles in the normal fast
 //! path before the compositor surface is drawn. Use of the per-tile valid and
 //! dirty rects ensure that we do a minimal amount of per-pixel work here to
 //! blend the overlay tile (this is not always optimal right now, but will be
 //! improved as a follow up).
@@ -487,16 +487,19 @@ struct TilePostUpdateContext<'a> {
     /// Information about color bindings from the picture cache.
     color_bindings: &'a FastHashMap<PropertyBindingId, ColorBindingInfo>,
 
     /// Current size in device pixels of tiles for this cache
     current_tile_size: DeviceIntSize,
 
     /// The local rect of the overall picture cache
     local_rect: PictureRect,
+
+    /// A list of the external surfaces that are present on this slice
+    external_surfaces: &'a [ExternalSurfaceDescriptor],
 }
 
 // Mutable state passed to picture cache tiles during post_update
 struct TilePostUpdateState<'a> {
     /// Allow access to the texture cache for requesting tiles
     resource_cache: &'a mut ResourceCache,
 
     /// Current configuration and setup for compositing all the picture cache tiles in renderer.
@@ -1205,17 +1208,31 @@ impl Tile {
             .unwrap_or_else(DeviceRect::zero);
 
         // 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 clipped_rect = self.current_descriptor.local_valid_rect
             .intersection(&ctx.local_clip_rect)
             .unwrap_or_else(PictureRect::zero);
-        let is_opaque = ctx.backdrop.rect.contains_rect(&clipped_rect);
+        let mut is_opaque = ctx.backdrop.rect.contains_rect(&clipped_rect);
+
+        if self.has_compositor_surface {
+            // TODO(gw): This will almost always select over blend, due to the
+            //           background rectangle. In future, we can optimize this
+            //           case to only check items that come _after_ the compositor
+            //           surface z_id? A better option might be to tweak the z_id
+            //           values so that the alpha pixels get z-rejected?
+            for surface in ctx.external_surfaces {
+                if surface.device_rect.intersects(&self.device_valid_rect) {
+                    is_opaque = false;
+                    break;
+                }
+            }
+        }
 
         if is_opaque != self.is_opaque {
             // If opacity changed, the native compositor surface and all tiles get invalidated.
             // (this does nothing if not using native compositor mode).
             // TODO(gw): This property probably changes very rarely, so it is OK to invalidate
             //           everything in this case. If it turns out that this isn't true, we could
             //           consider other options, such as per-tile opacity (natively supported
             //           on CoreAnimation, and supported if backed by non-virtual surfaces in
@@ -3212,16 +3229,17 @@ impl TileCacheInstance {
             global_device_pixel_scale: frame_context.global_device_pixel_scale,
             local_clip_rect: self.local_clip_rect,
             backdrop: self.backdrop,
             spatial_nodes: &self.spatial_nodes,
             opacity_bindings: &self.opacity_bindings,
             color_bindings: &self.color_bindings,
             current_tile_size: self.current_tile_size,
             local_rect: self.local_rect,
+            external_surfaces: &self.external_surfaces,
         };
 
         let mut state = TilePostUpdateState {
             resource_cache: frame_state.resource_cache,
             composite_state: frame_state.composite_state,
             compare_cache: &mut self.compare_cache,
         };