зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1696905
- Store composite tiles in a single array. r=gfx-reviewers,bradwerth
It used to be more convenient to store them in separate arrays but with the new occlusion culling code we don't benefit from it and have to undo it to traverse tiles from front to back. This is a cleanup patch that should not change the behavior of the code. Differential Revision: https://phabricator.services.mozilla.com/D113989
This commit is contained in:
Родитель
67286e28c2
Коммит
1f87bb2116
|
@ -97,6 +97,14 @@ bitflags! {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||
#[cfg_attr(feature = "capture", derive(Serialize))]
|
||||
#[cfg_attr(feature = "replay", derive(Deserialize))]
|
||||
pub enum TileKind {
|
||||
Opaque,
|
||||
Alpha,
|
||||
Clear,
|
||||
}
|
||||
|
||||
/// Describes the geometry and surface of a tile to be composited
|
||||
#[cfg_attr(feature = "capture", derive(Serialize))]
|
||||
|
@ -109,6 +117,27 @@ pub struct CompositeTile {
|
|||
pub valid_rect: DeviceRect,
|
||||
pub transform: Option<CompositorSurfaceTransform>,
|
||||
pub z_id: ZBufferId,
|
||||
pub kind: TileKind,
|
||||
}
|
||||
|
||||
fn tile_kind(surface: &CompositeTileSurface, is_opaque: bool) -> TileKind {
|
||||
match surface {
|
||||
// Color tiles are, by definition, opaque. We might support non-opaque color
|
||||
// tiles if we ever find pages that have a lot of these.
|
||||
CompositeTileSurface::Color { .. } => TileKind::Opaque,
|
||||
// Clear tiles have a special bucket
|
||||
CompositeTileSurface::Clear => TileKind::Clear,
|
||||
CompositeTileSurface::Texture { .. }
|
||||
| CompositeTileSurface::ExternalSurface { .. } => {
|
||||
// Texture surfaces get bucketed by opaque/alpha, for z-rejection
|
||||
// on the Draw compositor mode.
|
||||
if is_opaque {
|
||||
TileKind::Opaque
|
||||
} else {
|
||||
TileKind::Alpha
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub enum ExternalSurfaceDependency {
|
||||
|
@ -405,9 +434,7 @@ impl CompositeDescriptor {
|
|||
}
|
||||
|
||||
pub struct CompositeStatePreallocator {
|
||||
opaque_tiles: Preallocator,
|
||||
alpha_tiles: Preallocator,
|
||||
clear_tiles: Preallocator,
|
||||
tiles: Preallocator,
|
||||
external_surfaces: Preallocator,
|
||||
occluders: Preallocator,
|
||||
occluders_events: Preallocator,
|
||||
|
@ -417,9 +444,7 @@ pub struct CompositeStatePreallocator {
|
|||
|
||||
impl CompositeStatePreallocator {
|
||||
pub fn record(&mut self, state: &CompositeState) {
|
||||
self.opaque_tiles.record_vec(&state.opaque_tiles);
|
||||
self.alpha_tiles.record_vec(&state.alpha_tiles);
|
||||
self.clear_tiles.record_vec(&state.clear_tiles);
|
||||
self.tiles.record_vec(&state.tiles);
|
||||
self.external_surfaces.record_vec(&state.external_surfaces);
|
||||
self.occluders.record_vec(&state.occluders.occluders);
|
||||
self.occluders_events.record_vec(&state.occluders.events);
|
||||
|
@ -428,9 +453,7 @@ impl CompositeStatePreallocator {
|
|||
}
|
||||
|
||||
pub fn preallocate(&self, state: &mut CompositeState) {
|
||||
self.opaque_tiles.preallocate_vec(&mut state.opaque_tiles);
|
||||
self.alpha_tiles.preallocate_vec(&mut state.alpha_tiles);
|
||||
self.clear_tiles.preallocate_vec(&mut state.clear_tiles);
|
||||
self.tiles.preallocate_vec(&mut state.tiles);
|
||||
self.external_surfaces.preallocate_vec(&mut state.external_surfaces);
|
||||
self.occluders.preallocate_vec(&mut state.occluders.occluders);
|
||||
self.occluders_events.preallocate_vec(&mut state.occluders.events);
|
||||
|
@ -442,9 +465,7 @@ impl CompositeStatePreallocator {
|
|||
impl Default for CompositeStatePreallocator {
|
||||
fn default() -> Self {
|
||||
CompositeStatePreallocator {
|
||||
opaque_tiles: Preallocator::new(40),
|
||||
alpha_tiles: Preallocator::new(16),
|
||||
clear_tiles: Preallocator::new(0),
|
||||
tiles: Preallocator::new(56),
|
||||
external_surfaces: Preallocator::new(0),
|
||||
occluders: Preallocator::new(16),
|
||||
occluders_events: Preallocator::new(32),
|
||||
|
@ -461,12 +482,10 @@ pub struct CompositeState {
|
|||
// TODO(gw): Consider splitting up CompositeState into separate struct types depending
|
||||
// on the selected compositing mode. Many of the fields in this state struct
|
||||
// are only applicable to either Native or Draw compositing mode.
|
||||
/// List of opaque tiles to be drawn by the Draw compositor.
|
||||
pub opaque_tiles: Vec<CompositeTile>,
|
||||
/// List of alpha tiles to be drawn by the Draw compositor.
|
||||
pub alpha_tiles: Vec<CompositeTile>,
|
||||
/// List of clear tiles to be drawn by the Draw compositor.
|
||||
pub clear_tiles: Vec<CompositeTile>,
|
||||
/// List of tiles to be drawn by the Draw compositor.
|
||||
/// Tiles are accumulated in this vector and sorted from front to back at the end of the
|
||||
/// frame.
|
||||
pub tiles: Vec<CompositeTile>,
|
||||
/// List of primitives that were promoted to be compositor surfaces.
|
||||
pub external_surfaces: Vec<ResolvedExternalSurface>,
|
||||
/// Used to generate z-id values for tiles in the Draw compositor mode.
|
||||
|
@ -500,9 +519,7 @@ impl CompositeState {
|
|||
dirty_rects_are_valid: bool,
|
||||
) -> Self {
|
||||
CompositeState {
|
||||
opaque_tiles: Vec::new(),
|
||||
alpha_tiles: Vec::new(),
|
||||
clear_tiles: Vec::new(),
|
||||
tiles: Vec::new(),
|
||||
z_generator: ZBufferIdGenerator::new(max_depth_ids),
|
||||
dirty_rects_are_valid,
|
||||
compositor_kind,
|
||||
|
@ -573,13 +590,13 @@ impl CompositeState {
|
|||
(CompositeTileSurface::Color { color: *color }, true)
|
||||
}
|
||||
TileSurface::Clear => {
|
||||
(CompositeTileSurface::Clear, false)
|
||||
(CompositeTileSurface::Clear, true)
|
||||
}
|
||||
TileSurface::Texture { descriptor, .. } => {
|
||||
let surface = descriptor.resolve(resource_cache, tile_cache.current_tile_size);
|
||||
(
|
||||
CompositeTileSurface::Texture { surface },
|
||||
tile.is_opaque
|
||||
tile.is_opaque
|
||||
)
|
||||
}
|
||||
};
|
||||
|
@ -593,6 +610,7 @@ impl CompositeState {
|
|||
}
|
||||
|
||||
let tile = CompositeTile {
|
||||
kind: tile_kind(&surface, is_opaque),
|
||||
surface,
|
||||
rect: device_rect,
|
||||
valid_rect: tile.device_valid_rect.translate(-device_rect.origin.to_vector()),
|
||||
|
@ -602,7 +620,7 @@ impl CompositeState {
|
|||
z_id: tile.z_id,
|
||||
};
|
||||
|
||||
self.push_tile(tile, is_opaque);
|
||||
self.tiles.push(tile);
|
||||
}
|
||||
|
||||
// Sort the tile descriptor lists, since iterating values in the tile_cache.tiles
|
||||
|
@ -714,8 +732,10 @@ impl CompositeState {
|
|||
ResolvedExternalSurfaceIndex::INVALID
|
||||
};
|
||||
|
||||
let surface = CompositeTileSurface::ExternalSurface { external_surface_index };
|
||||
let tile = CompositeTile {
|
||||
surface: CompositeTileSurface::ExternalSurface { external_surface_index },
|
||||
kind: tile_kind(&surface, compositor_surface.is_opaque),
|
||||
surface,
|
||||
rect: external_surface.surface_rect,
|
||||
valid_rect: external_surface.surface_rect.translate(-external_surface.surface_rect.origin.to_vector()),
|
||||
dirty_rect: external_surface.surface_rect.translate(-external_surface.surface_rect.origin.to_vector()),
|
||||
|
@ -738,7 +758,7 @@ impl CompositeState {
|
|||
}
|
||||
);
|
||||
|
||||
self.push_tile(tile, compositor_surface.is_opaque);
|
||||
self.tiles.push(tile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -841,39 +861,9 @@ impl CompositeState {
|
|||
external_surface_index
|
||||
}
|
||||
|
||||
/// Add a tile to the appropriate array, depending on tile properties and compositor mode.
|
||||
fn push_tile(
|
||||
&mut self,
|
||||
tile: CompositeTile,
|
||||
is_opaque: bool,
|
||||
) {
|
||||
match tile.surface {
|
||||
CompositeTileSurface::Color { .. } => {
|
||||
// Color tiles are, by definition, opaque. We might support non-opaque color
|
||||
// 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 { .. } => {
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
CompositeTileSurface::ExternalSurface { .. } => {
|
||||
if is_opaque {
|
||||
self.opaque_tiles.push(tile);
|
||||
} else {
|
||||
self.alpha_tiles.push(tile);
|
||||
}
|
||||
}
|
||||
}
|
||||
pub fn end_frame(&mut self) {
|
||||
// Sort tiles from front to back.
|
||||
self.tiles.sort_by_key(|tile| -tile.z_id.0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -689,6 +689,8 @@ impl FrameBuilder {
|
|||
self.prim_headers_prealloc.record_vec(&mut prim_headers.headers_int);
|
||||
self.composite_state_prealloc.record(&composite_state);
|
||||
|
||||
composite_state.end_frame();
|
||||
|
||||
Frame {
|
||||
device_rect: DeviceIntRect::new(
|
||||
device_origin,
|
||||
|
|
|
@ -62,18 +62,11 @@ use euclid::point2;
|
|||
use smallvec::SmallVec;
|
||||
use api::units::*;
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||
pub enum ItemSource {
|
||||
Opaque(usize),
|
||||
Alpha(usize),
|
||||
Clear(usize),
|
||||
}
|
||||
|
||||
/// A visible part of a rectangle after occlusion culling.
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct Item {
|
||||
pub rectangle: DeviceBox2D,
|
||||
pub src: ItemSource,
|
||||
pub key: usize,
|
||||
}
|
||||
|
||||
/// A builder that applies occlusion culling with rectangles provided in front-to-back order.
|
||||
|
@ -95,7 +88,7 @@ impl FrontToBackBuilder {
|
|||
/// Add a rectangle, potentially splitting it and discarding the occluded parts if any.
|
||||
///
|
||||
/// Returns true the rectangle is at least partially visible.
|
||||
pub fn add(&mut self, rect: &DeviceBox2D, is_opaque: bool, src: ItemSource) -> bool {
|
||||
pub fn add(&mut self, rect: &DeviceBox2D, is_opaque: bool, key: usize) -> bool {
|
||||
let mut fragments: SmallVec<[DeviceBox2D; 16]> = SmallVec::new();
|
||||
fragments.push(*rect);
|
||||
|
||||
|
@ -117,7 +110,7 @@ impl FrontToBackBuilder {
|
|||
for rect in &fragments {
|
||||
list.push(Item {
|
||||
rectangle: *rect,
|
||||
src,
|
||||
key,
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -57,6 +57,7 @@ use crate::capture::{CaptureConfig, ExternalCaptureImage, PlainExternalImage};
|
|||
use crate::composite::{CompositeState, CompositeTileSurface, ResolvedExternalSurface, CompositorSurfaceTransform};
|
||||
use crate::composite::{CompositorKind, Compositor, NativeTileId, CompositeFeatures, CompositeSurfaceFormat, ResolvedExternalSurfaceColorData};
|
||||
use crate::composite::{CompositorConfig, NativeSurfaceOperationDetails, NativeSurfaceId, NativeSurfaceOperation};
|
||||
use crate::composite::TileKind;
|
||||
use crate::c_str;
|
||||
use crate::debug_colors;
|
||||
use crate::device::{DepthFunction, Device, DrawTarget, ExternalTexture, GpuFrameId};
|
||||
|
@ -3287,13 +3288,7 @@ impl Renderer {
|
|||
);
|
||||
|
||||
for item in tiles_iter {
|
||||
let tile = match item.src {
|
||||
occ::ItemSource::Opaque(idx) => &composite_state.opaque_tiles[idx],
|
||||
occ::ItemSource::Alpha(idx) => &composite_state.alpha_tiles[idx],
|
||||
occ::ItemSource::Clear(..) => {
|
||||
continue;
|
||||
}
|
||||
};
|
||||
let tile = &composite_state.tiles[item.key];
|
||||
|
||||
let clip_rect = item.rectangle.to_rect();
|
||||
|
||||
|
@ -3502,35 +3497,13 @@ impl Renderer {
|
|||
}
|
||||
}
|
||||
|
||||
let cap = composite_state.opaque_tiles.len() +
|
||||
composite_state.alpha_tiles.len() +
|
||||
composite_state.clear_tiles.len();
|
||||
let cap = composite_state.tiles.len();
|
||||
|
||||
let mut occlusion = occlusion::FrontToBackBuilder::with_capacity(cap, cap);
|
||||
|
||||
let mut items = Vec::with_capacity(cap);
|
||||
|
||||
// TODO: This will get simpler if we stop storing tiles in separate arrays.
|
||||
|
||||
for (idx, tile) in composite_state.opaque_tiles.iter().enumerate() {
|
||||
items.push((tile.z_id.0, occ::ItemSource::Opaque(idx)));
|
||||
}
|
||||
for (idx, tile) in composite_state.alpha_tiles.iter().enumerate() {
|
||||
items.push((tile.z_id.0, occ::ItemSource::Alpha(idx)));
|
||||
}
|
||||
for (idx, tile) in composite_state.clear_tiles.iter().enumerate() {
|
||||
items.push((tile.z_id.0, occ::ItemSource::Clear(idx)));
|
||||
}
|
||||
|
||||
items.sort_by_key(|item| -item.0);
|
||||
for &(_, src) in &items {
|
||||
let tile = match src {
|
||||
occ::ItemSource::Opaque(idx) => &composite_state.opaque_tiles[idx],
|
||||
occ::ItemSource::Alpha(idx) => &composite_state.alpha_tiles[idx],
|
||||
occ::ItemSource::Clear(idx) => &composite_state.clear_tiles[idx],
|
||||
};
|
||||
|
||||
let is_opaque = !matches!(src, occ::ItemSource::Alpha(..));
|
||||
for (idx, tile) in composite_state.tiles.iter().enumerate() {
|
||||
// Clear tiles overwrite whatever is under them, so they are treated as opaque.
|
||||
let is_opaque = tile.kind != TileKind::Alpha;
|
||||
|
||||
// Determine a clip rect to apply to this tile, depending on what
|
||||
// the partial present mode is.
|
||||
|
@ -3553,7 +3526,7 @@ impl Renderer {
|
|||
continue;
|
||||
}
|
||||
|
||||
occlusion.add(&rect, is_opaque, src);
|
||||
occlusion.add(&rect, is_opaque, idx);
|
||||
}
|
||||
|
||||
// Clear the framebuffer
|
||||
|
@ -3578,8 +3551,9 @@ impl Renderer {
|
|||
|
||||
// We are only interested in tiles backed with actual cached pixels so we don't
|
||||
// count clear tiles here.
|
||||
let num_tiles = composite_state.opaque_tiles.len()
|
||||
+ composite_state.alpha_tiles.len();
|
||||
let num_tiles = composite_state.tiles
|
||||
.iter()
|
||||
.filter(|tile| tile.kind != TileKind::Clear).count();
|
||||
self.profile.set(profiler::PICTURE_TILES, num_tiles);
|
||||
|
||||
if !occlusion.opaque_items().is_empty() {
|
||||
|
@ -4442,7 +4416,10 @@ impl Renderer {
|
|||
|
||||
// Work out how many dirty rects WR produced, and if that's more than
|
||||
// what the device supports.
|
||||
for tile in composite_state.opaque_tiles.iter().chain(composite_state.alpha_tiles.iter()) {
|
||||
for tile in &composite_state.tiles {
|
||||
if tile.kind == TileKind::Clear {
|
||||
continue;
|
||||
}
|
||||
let tile_dirty_rect = tile.dirty_rect.translate(tile.rect.origin.to_vector());
|
||||
let transformed_dirty_rect = if let Some(transform) = tile.transform {
|
||||
transform.outer_transformed_rect(&tile_dirty_rect)
|
||||
|
@ -4616,7 +4593,10 @@ impl Renderer {
|
|||
let compositor = self.compositor_config.compositor().unwrap();
|
||||
// Invalidate any native surface tiles that might be updated by passes.
|
||||
if !frame.has_been_rendered {
|
||||
for tile in frame.composite_state.opaque_tiles.iter().chain(frame.composite_state.alpha_tiles.iter()) {
|
||||
for tile in &frame.composite_state.tiles {
|
||||
if tile.kind == TileKind::Clear {
|
||||
continue;
|
||||
}
|
||||
if !tile.dirty_rect.is_empty() {
|
||||
if let CompositeTileSurface::Texture { surface: ResolvedSurfaceTexture::Native { id, .. } } =
|
||||
tile.surface {
|
||||
|
|
Загрузка…
Ссылка в новой задаче