Bug 1585898 - Fix broken tab bar with picture caching on mac. r=mstange

Promote clear primitives to be picture cache slices that can
be drawn during the composite step. Without this, the clear
primitive is not correct since it only operates on the slice
it is assigned to, not the entire background before it.

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

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Glenn Watson 2019-10-04 01:20:49 +00:00
parent eec7bc66fd
commit d170ede903
5 changed files with 94 additions and 29 deletions

View File

@ -1204,32 +1204,42 @@ impl BatchBuilder {
let tile = &tile_cache.tiles[key];
let device_rect = (tile.world_rect * ctx.global_device_pixel_scale).round();
let surface = tile.surface.as_ref().expect("no tile surface set!");
let (surface, is_opaque) = match surface {
match surface {
TileSurface::Color { color } => {
(CompositeTileSurface::Color { color: *color }, true)
composite_config.opaque_tiles.push(CompositeTile {
surface: CompositeTileSurface::Color { color: *color },
rect: device_rect,
clip_rect: device_clip_rect,
z_id,
});
}
TileSurface::Clear => {
composite_config.clear_tiles.push(CompositeTile {
surface: CompositeTileSurface::Clear,
rect: device_rect,
clip_rect: device_clip_rect,
z_id,
});
}
TileSurface::Texture { handle, .. } => {
let cache_item = ctx.resource_cache.texture_cache.get(handle);
(
CompositeTileSurface::Texture {
let composite_tile = CompositeTile {
surface: CompositeTileSurface::Texture {
texture_id: cache_item.texture_id,
texture_layer: cache_item.texture_layer,
},
tile.is_opaque || tile_cache.is_opaque(),
)
rect: device_rect,
clip_rect: device_clip_rect,
z_id,
};
if tile.is_opaque || tile_cache.is_opaque() {
composite_config.opaque_tiles.push(composite_tile);
} else {
composite_config.alpha_tiles.push(composite_tile);
}
}
};
let composite_tile = CompositeTile {
surface,
rect: device_rect,
clip_rect: device_clip_rect,
z_id,
};
if is_opaque {
composite_config.opaque_tiles.push(composite_tile);
} else {
composite_config.alpha_tiles.push(composite_tile);
}
}
}

View File

@ -23,6 +23,7 @@ pub enum CompositeTileSurface {
Color {
color: ColorF,
},
Clear,
}
/// Describes the geometry and surface of a tile to be composited
@ -41,6 +42,7 @@ pub struct CompositeTile {
pub struct CompositeConfig {
pub opaque_tiles: Vec<CompositeTile>,
pub alpha_tiles: Vec<CompositeTile>,
pub clear_tiles: Vec<CompositeTile>,
pub z_generator: ZBufferIdGenerator,
}
@ -49,6 +51,7 @@ impl CompositeConfig {
CompositeConfig {
opaque_tiles: Vec::new(),
alpha_tiles: Vec::new(),
clear_tiles: Vec::new(),
z_generator: ZBufferIdGenerator::new(0),
}
}

View File

@ -379,6 +379,7 @@ pub enum TileSurface {
Color {
color: ColorF,
},
Clear,
}
impl TileSurface {
@ -386,6 +387,7 @@ impl TileSurface {
match *self {
TileSurface::Color { .. } => "Color",
TileSurface::Texture { .. } => "Texture",
TileSurface::Clear => "Clear",
}
}
}
@ -655,15 +657,22 @@ impl Tile {
// See if this tile is a simple color, in which case we can just draw
// it as a rect, and avoid allocating a texture surface and drawing it.
let is_solid_color = self.current_descriptor.prims.len() == 1 && self.is_opaque;
let is_simple_prim = self.current_descriptor.prims.len() == 1 && self.is_opaque;
// Set up the backing surface for this tile.
let mut surface = if is_solid_color {
let mut surface = if is_simple_prim {
// If we determine the tile can be represented by a color, set the
// surface unconditionally (this will drop any previously used
// texture cache backing surface).
TileSurface::Color {
color: ctx.backdrop.color,
match ctx.backdrop.kind {
BackdropKind::Color { color } => {
TileSurface::Color {
color,
}
}
BackdropKind::Clear => {
TileSurface::Clear
}
}
} else {
// If this tile will be backed by a surface, we want to retain
@ -674,7 +683,7 @@ impl Tile {
Some(old_surface @ TileSurface::Texture { .. }) => {
old_surface
}
Some(TileSurface::Color { .. }) | None => {
Some(TileSurface::Color { .. }) | Some(TileSurface::Clear) | None => {
TileSurface::Texture {
handle: TextureCacheHandle::invalid(),
visibility_mask: PrimitiveVisibilityMask::empty(),
@ -1067,6 +1076,14 @@ impl ::std::fmt::Debug for RecordedDirtyRegion {
}
}
#[derive(Debug, Copy, Clone)]
enum BackdropKind {
Color {
color: ColorF,
},
Clear,
}
/// Stores information about the calculated opaque backdrop of this slice.
#[derive(Debug, Copy, Clone)]
struct BackdropInfo {
@ -1074,15 +1091,17 @@ struct BackdropInfo {
/// to determine where subpixel AA can be used, and where alpha blending
/// can be disabled.
rect: PictureRect,
/// Color of the backdrop.
color: ColorF,
/// Kind of the backdrop
kind: BackdropKind,
}
impl BackdropInfo {
fn empty() -> Self {
BackdropInfo {
rect: PictureRect::zero(),
color: ColorF::BLACK,
kind: BackdropKind::Color {
color: ColorF::BLACK,
},
}
}
}
@ -1619,7 +1638,9 @@ impl TileCacheInstance {
if clip_chain.pic_clip_rect.contains_rect(&self.backdrop.rect) {
self.backdrop = BackdropInfo {
rect: clip_chain.pic_clip_rect,
color,
kind: BackdropKind::Color {
color,
},
};
}
}
@ -1685,8 +1706,15 @@ impl TileCacheInstance {
}
}
}
PrimitiveInstanceKind::Clear { .. } => {
if let Some(ref clip_chain) = prim_clip_chain {
self.backdrop = BackdropInfo {
rect: clip_chain.pic_clip_rect,
kind: BackdropKind::Clear,
};
}
}
PrimitiveInstanceKind::LineDecoration { .. } |
PrimitiveInstanceKind::Clear { .. } |
PrimitiveInstanceKind::NormalBorder { .. } |
PrimitiveInstanceKind::LinearGradient { .. } |
PrimitiveInstanceKind::RadialGradient { .. } |
@ -2287,6 +2315,8 @@ bitflags! {
const CREATE_PICTURE_CACHE_POST = 32;
/// If set, this cluster represents a scroll bar container.
const SCROLLBAR_CONTAINER = 64;
/// If set, this cluster contains clear rectangle primitives.
const IS_CLEAR_PRIMITIVE = 128;
}
}
@ -2400,6 +2430,9 @@ impl PrimitiveList {
PrimitiveInstanceKind::Backdrop { .. } => {
flags.insert(ClusterFlags::IS_BACKDROP_FILTER);
}
PrimitiveInstanceKind::Clear { .. } => {
flags.insert(ClusterFlags::IS_CLEAR_PRIMITIVE);
}
_ => {}
}

View File

@ -3849,6 +3849,9 @@ impl Renderer {
CompositeTileSurface::Color { color } => {
(TextureSource::Dummy, 0.0, color)
}
CompositeTileSurface::Clear => {
(TextureSource::Dummy, 0.0, ColorF::BLACK)
}
CompositeTileSurface::Texture { texture_id, texture_layer } => {
(texture_id, texture_layer as f32, ColorF::WHITE)
}
@ -3925,6 +3928,18 @@ impl Renderer {
self.gpu_profile.finish_sampler(opaque_sampler);
}
if !composite_config.clear_tiles.is_empty() {
let transparent_sampler = self.gpu_profile.start_sampler(GPU_SAMPLER_TAG_TRANSPARENT);
self.device.disable_depth_write();
self.set_blend(true, FramebufferKind::Main);
self.device.set_blend_mode_premultiplied_dest_out();
self.draw_tile_list(
composite_config.clear_tiles.iter(),
stats,
);
self.gpu_profile.finish_sampler(transparent_sampler);
}
// Draw alpha tiles
if !composite_config.alpha_tiles.is_empty() {
let transparent_sampler = self.gpu_profile.start_sampler(GPU_SAMPLER_TAG_TRANSPARENT);

View File

@ -511,7 +511,9 @@ impl<'a> SceneBuilder<'a> {
// Walk the supplied top level of clusters, slicing into slices as appropriate
for cluster in main_prim_list.clusters.drain(..) {
// Check if this cluster requires a new slice
create_slice |= cluster.flags.contains(ClusterFlags::CREATE_PICTURE_CACHE_PRE);
create_slice |= cluster.flags.intersects(
ClusterFlags::CREATE_PICTURE_CACHE_PRE | ClusterFlags::IS_CLEAR_PRIMITIVE
);
if create_slice {
// When creating a slice, close off any open clip chains on prev slice.
@ -608,7 +610,9 @@ impl<'a> SceneBuilder<'a> {
}
// If this cluster creates a slice after, then note that for next cluster
create_slice |= cluster.flags.contains(ClusterFlags::CREATE_PICTURE_CACHE_POST);
create_slice |= cluster.flags.intersects(
ClusterFlags::CREATE_PICTURE_CACHE_POST | ClusterFlags::IS_CLEAR_PRIMITIVE
);
// Finally, add this cluster to the current slice
slices.last_mut().unwrap().prim_list.add_cluster(cluster);