Bug 1627816 - Fix skipping composites when tile surface changes. r=nical

This fixes a case where the backing surface of a picture cache tile
changes, but was still being considered a no-op frame, which skips
the composite as an optimization if nothing has changed.

In this case, the tile surface changes from a rasterized texture
to a solid color that doesn't require a picture cache texture.

The patch ensures that the composite surface descriptors that are
used to detect no-op frame compositions include the backing
surface for each of the tiles that make up this virtual surface.

Differential Revision: https://phabricator.services.mozilla.com/D70138

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Glenn Watson 2020-04-08 09:24:48 +00:00
Родитель cc3fb85223
Коммит 29f4bd98b6
2 изменённых файлов: 57 добавлений и 3 удалений

Просмотреть файл

@ -9,7 +9,7 @@ use crate::batch::{resolve_image, get_buffer_kind};
use crate::gpu_cache::GpuCache;
use crate::gpu_types::{ZBufferId, ZBufferIdGenerator};
use crate::internal_types::TextureSource;
use crate::picture::{ImageDependency, ResolvedSurfaceTexture, TileCacheInstance, TileSurface};
use crate::picture::{ImageDependency, ResolvedSurfaceTexture, TileCacheInstance, TileId, TileSurface};
use crate::prim_store::DeferredResolve;
use crate::renderer::ImageBufferKind;
use crate::resource_cache::{ImageRequest, ResourceCache};
@ -246,7 +246,40 @@ struct Occluder {
device_rect: DeviceIntRect,
}
/// Describes the properties that identify a tile composition uniquely.
/// The backing surface kind for a tile. Same as `TileSurface`, minus
/// the texture cache handles, visibility masks etc.
#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
#[derive(PartialEq, Clone)]
pub enum TileSurfaceKind {
Texture,
Color {
color: ColorF,
},
Clear,
}
impl From<&TileSurface> for TileSurfaceKind {
fn from(surface: &TileSurface) -> Self {
match surface {
TileSurface::Texture { .. } => TileSurfaceKind::Texture,
TileSurface::Color { color } => TileSurfaceKind::Color { color: *color },
TileSurface::Clear => TileSurfaceKind::Clear,
}
}
}
/// Describes properties that identify a tile composition uniquely.
/// The backing surface for this tile.
#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
#[derive(PartialEq, Clone)]
pub struct CompositeTileDescriptor {
pub tile_id: TileId,
pub surface_kind: TileSurfaceKind,
}
/// Describes the properties that identify a surface composition uniquely.
#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
#[derive(PartialEq, Clone)]
@ -259,6 +292,8 @@ pub struct CompositeSurfaceDescriptor {
// thing that has changed is the generation of an compositor surface
// image dependency.
pub image_dependencies: [ImageDependency; 3],
// List of the surface information for each tile added to this virtual surface
pub tile_descriptors: Vec<CompositeTileDescriptor>,
}
/// Describes surface properties used to composite a frame. This
@ -406,6 +441,8 @@ impl CompositeState {
) {
let mut visible_opaque_tile_count = 0;
let mut visible_alpha_tile_count = 0;
let mut opaque_tile_descriptors = Vec::new();
let mut alpha_tile_descriptors = Vec::new();
for tile in tile_cache.tiles.values() {
if !tile.is_visible {
@ -416,6 +453,11 @@ impl CompositeState {
let device_rect = (tile.world_tile_rect * global_device_pixel_scale).round();
let surface = tile.surface.as_ref().expect("no tile surface set!");
let descriptor = CompositeTileDescriptor {
surface_kind: surface.into(),
tile_id: tile.id,
};
let (surface, is_opaque) = match surface {
TileSurface::Color { color } => {
(CompositeTileSurface::Color { color: *color }, true)
@ -433,8 +475,10 @@ impl CompositeState {
};
if is_opaque {
opaque_tile_descriptors.push(descriptor);
visible_opaque_tile_count += 1;
} else {
alpha_tile_descriptors.push(descriptor);
visible_alpha_tile_count += 1;
}
@ -450,6 +494,13 @@ impl CompositeState {
self.push_tile(tile, is_opaque);
}
// Sort the tile descriptor lists, since iterating values in the tile_cache.tiles
// hashmap doesn't provide any ordering guarantees, but we want to detect the
// composite descriptor as equal if the tiles list is the same, regardless of
// ordering.
opaque_tile_descriptors.sort_by_key(|desc| desc.tile_id);
alpha_tile_descriptors.sort_by_key(|desc| desc.tile_id);
// Add opaque surface before any compositor surfaces
if visible_opaque_tile_count > 0 {
self.descriptor.surfaces.push(
@ -458,6 +509,7 @@ impl CompositeState {
offset: tile_cache.device_position,
clip_rect: device_clip_rect,
image_dependencies: [ImageDependency::INVALID; 3],
tile_descriptors: opaque_tile_descriptors,
}
);
}
@ -562,6 +614,7 @@ impl CompositeState {
offset: tile.rect.origin,
clip_rect: tile.clip_rect,
image_dependencies: external_surface.image_dependencies,
tile_descriptors: Vec::new(),
}
);
@ -576,6 +629,7 @@ impl CompositeState {
offset: tile_cache.device_position,
clip_rect: device_clip_rect,
image_dependencies: [ImageDependency::INVALID; 3],
tile_descriptors: alpha_tile_descriptors,
}
);
}

Просмотреть файл

@ -693,7 +693,7 @@ impl PrimitiveDependencyInfo {
/// A stable ID for a given tile, to help debugging. These are also used
/// as unique identifiers for tile surfaces when using a native compositor.
#[derive(Debug, Copy, Clone, PartialEq)]
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Ord, Eq)]
#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
pub struct TileId(pub usize);