mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-20 16:55:40 +00:00
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:
parent
eec7bc66fd
commit
d170ede903
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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),
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user