| author | Glenn Watson <gw@intuitionlibrary.com> |
| Mon, 02 Mar 2020 10:07:23 +0000 | |
| changeset 516370 | 38b7f4761f5041a0e3b2326c2be37f98da509e21 |
| parent 516369 | 02c2d6aeb09a5f4a4677e3c7d839db86c79964a1 |
| child 516371 | 097aecdda3d06ebdf7b41e5d27f42f73a4e8f816 |
| push id | 37173 |
| push user | btara@mozilla.com |
| push date | Mon, 02 Mar 2020 21:27:32 +0000 |
| treeherder | mozilla-central@c32706293416 [default view] [failures only] |
| perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
| reviewers | nical |
| bugs | 1579235 |
| milestone | 75.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
|
| gfx/wr/webrender/src/composite.rs | file | annotate | diff | comparison | revisions | |
| gfx/wr/webrender/src/picture.rs | file | annotate | diff | comparison | revisions |
--- 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, };