Bug 1583460 - Refactor picture caching setup to simplify creating multiple slices. r=nical

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

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Glenn Watson 2019-09-24 20:09:19 +00:00
Родитель 5a2c81ed47
Коммит b0ffdb3a87
2 изменённых файлов: 98 добавлений и 137 удалений

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

@ -2244,6 +2244,10 @@ bitflags! {
const IS_VISIBLE = 4;
/// Is a backdrop-filter cluster that requires special handling during post_update.
const IS_BACKDROP_FILTER = 8;
/// Force creation of a picture caching slice before this cluster.
const CREATE_PICTURE_CACHE_PRE = 16;
/// Force creation of a picture caching slice after this cluster.
const CREATE_PICTURE_CACHE_POST = 32;
}
}
@ -2299,7 +2303,6 @@ impl PrimitiveCluster {
&mut self,
prim_instance: PrimitiveInstance,
prim_size: LayoutSize,
insert_position: PrimitiveListPosition,
) {
let prim_rect = LayoutRect::new(
prim_instance.prim_origin,
@ -2310,15 +2313,7 @@ impl PrimitiveCluster {
.unwrap_or_else(LayoutRect::zero);
self.bounding_rect = self.bounding_rect.union(&culling_rect);
match insert_position {
PrimitiveListPosition::Begin => {
self.prim_instances.insert(0, prim_instance);
}
PrimitiveListPosition::End => {
self.prim_instances.push(prim_instance);
}
}
self.prim_instances.push(prim_instance);
}
}
@ -2373,24 +2368,17 @@ impl PrimitiveList {
// Insert the primitive into the first or last cluster as required
match insert_position {
PrimitiveListPosition::Begin => {
if let Some(cluster) = self.clusters.first_mut() {
if cluster.is_compatible(spatial_node_index, flags) {
cluster.push(prim_instance, prim_size, insert_position);
return;
}
}
let mut cluster = PrimitiveCluster::new(
spatial_node_index,
flags,
);
cluster.push(prim_instance, prim_size, insert_position);
cluster.push(prim_instance, prim_size);
self.clusters.insert(0, cluster);
}
PrimitiveListPosition::End => {
if let Some(cluster) = self.clusters.last_mut() {
if cluster.is_compatible(spatial_node_index, flags) {
cluster.push(prim_instance, prim_size, insert_position);
cluster.push(prim_instance, prim_size);
return;
}
}
@ -2399,7 +2387,7 @@ impl PrimitiveList {
spatial_node_index,
flags,
);
cluster.push(prim_instance, prim_size, insert_position);
cluster.push(prim_instance, prim_size);
self.clusters.push(cluster);
}
}

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

@ -683,72 +683,15 @@ impl<'a> SceneBuilder<'a> {
}
}
let prim_list = remaining_prims;
// Now, create a picture with tile caching enabled that will hold all
// of the primitives selected as belonging to the main scroll root.
let pic_key = PictureKey::new(
PrimitiveFlags::IS_BACKFACE_VISIBLE,
LayoutSize::zero(),
Picture {
composite_mode_key: PictureCompositeKey::Identity,
},
);
let pic_data_handle = self.interners
.picture
.intern(&pic_key, || {
PrimitiveSceneData {
prim_size: LayoutSize::zero(),
flags: PrimitiveFlags::IS_BACKFACE_VISIBLE,
}
}
);
// Build a clip-chain for the tile cache, that contains any of the shared clips
// we will apply when drawing the tiles. In all cases provided by Gecko, these
// are rectangle clips with a scale/offset transform only, and get handled as
// a simple local clip rect in the vertex shader. However, this should in theory
// also work with any complex clips, such as rounded rects and image masks, by
// producing a clip mask that is applied to the picture cache tiles.
let mut parent_clip_chain_id = ClipChainId::NONE;
for clip_handle in &shared_clips {
parent_clip_chain_id = self.clip_store.add_clip_chain_node(
*clip_handle,
parent_clip_chain_id,
);
}
let tile_cache = Box::new(TileCacheInstance::new(
let instance = create_tile_cache(
0,
main_scroll_root,
remaining_prims,
self.config.background_color,
shared_clips,
parent_clip_chain_id,
));
let pic_index = self.prim_store.pictures.alloc().init(PicturePrimitive::new_image(
Some(PictureCompositeMode::TileCache { }),
Picture3DContext::Out,
None,
true,
PrimitiveFlags::IS_BACKFACE_VISIBLE,
RasterSpace::Screen,
prim_list,
main_scroll_root,
Some(tile_cache),
PictureOptions::default(),
));
let instance = PrimitiveInstance::new(
LayoutPoint::zero(),
LayoutRect::max_rect(),
PrimitiveInstanceKind::Picture {
data_handle: pic_data_handle,
pic_index: PictureIndex(pic_index),
segment_instance_index: SegmentInstanceIndex::INVALID,
},
parent_clip_chain_id,
&mut self.interners,
&mut self.prim_store,
&mut self.clip_store,
);
// This contains the tile caching picture, with preceding and
@ -2013,71 +1956,22 @@ impl<'a> SceneBuilder<'a> {
!self.found_explicit_tile_cache &&
self.config.enable_picture_caching {
let scroll_root = ROOT_SPATIAL_NODE_INDEX;
// Now, create a picture with tile caching enabled that will hold all
// of the primitives selected as belonging to the main scroll root.
let pic_key = PictureKey::new(
PrimitiveFlags::IS_BACKFACE_VISIBLE,
LayoutSize::zero(),
Picture {
composite_mode_key: PictureCompositeKey::Identity,
},
);
let pic_data_handle = self.interners
.picture
.intern(&pic_key, || {
PrimitiveSceneData {
prim_size: LayoutSize::zero(),
flags: PrimitiveFlags::IS_BACKFACE_VISIBLE,
}
}
);
// TODO(gw): For now, we don't bother trying to share any clips if we create an
// implicit picture cache. This cache always caches with a fixed position
// root scroll node, so it won't save any invalidations. It might save
// some per-item clipping work though. We should handle this by unifying
// the implicit cache creation code here to work as part of the normal
// setup_picture_caching method.
let tile_cache = TileCacheInstance::new(
let instance = create_tile_cache(
0,
ROOT_SPATIAL_NODE_INDEX,
stacking_context.prim_list,
self.config.background_color,
Vec::new(),
ClipChainId::NONE,
);
let pic_index = self.prim_store.pictures.alloc().init(PicturePrimitive::new_image(
Some(PictureCompositeMode::TileCache {}),
Picture3DContext::Out,
None,
true,
PrimitiveFlags::IS_BACKFACE_VISIBLE,
RasterSpace::Screen,
stacking_context.prim_list,
scroll_root,
Some(Box::new(tile_cache)),
PictureOptions::default(),
));
let instance = PrimitiveInstance::new(
LayoutPoint::zero(),
LayoutRect::max_rect(),
PrimitiveInstanceKind::Picture {
data_handle: pic_data_handle,
pic_index: PictureIndex(pic_index),
segment_instance_index: SegmentInstanceIndex::INVALID,
},
ClipChainId::NONE,
&mut self.interners,
&mut self.prim_store,
&mut self.clip_store,
);
let mut prim_list = PrimitiveList::empty();
prim_list.add_prim(
instance,
LayoutSize::zero(),
scroll_root,
ROOT_SPATIAL_NODE_INDEX,
PrimitiveFlags::IS_BACKFACE_VISIBLE,
);
stacking_context.prim_list = prim_list;
@ -3941,3 +3835,82 @@ fn process_repeat_size(
},
)
}
/// Given a PrimitiveList and scroll root, construct a tile cache primitive instance
/// that wraps the primitive list.
fn create_tile_cache(
slice: usize,
scroll_root: SpatialNodeIndex,
prim_list: PrimitiveList,
background_color: Option<ColorF>,
shared_clips: Vec<ClipDataHandle>,
interners: &mut Interners,
prim_store: &mut PrimitiveStore,
clip_store: &mut ClipStore,
) -> PrimitiveInstance {
// Now, create a picture with tile caching enabled that will hold all
// of the primitives selected as belonging to the main scroll root.
let pic_key = PictureKey::new(
PrimitiveFlags::IS_BACKFACE_VISIBLE,
LayoutSize::zero(),
Picture {
composite_mode_key: PictureCompositeKey::Identity,
},
);
let pic_data_handle = interners
.picture
.intern(&pic_key, || {
PrimitiveSceneData {
prim_size: LayoutSize::zero(),
flags: PrimitiveFlags::IS_BACKFACE_VISIBLE,
}
}
);
// Build a clip-chain for the tile cache, that contains any of the shared clips
// we will apply when drawing the tiles. In all cases provided by Gecko, these
// are rectangle clips with a scale/offset transform only, and get handled as
// a simple local clip rect in the vertex shader. However, this should in theory
// also work with any complex clips, such as rounded rects and image masks, by
// producing a clip mask that is applied to the picture cache tiles.
let mut parent_clip_chain_id = ClipChainId::NONE;
for clip_handle in &shared_clips {
parent_clip_chain_id = clip_store.add_clip_chain_node(
*clip_handle,
parent_clip_chain_id,
);
}
let tile_cache = Box::new(TileCacheInstance::new(
slice,
scroll_root,
background_color,
shared_clips,
parent_clip_chain_id,
));
let pic_index = prim_store.pictures.alloc().init(PicturePrimitive::new_image(
Some(PictureCompositeMode::TileCache { }),
Picture3DContext::Out,
None,
true,
PrimitiveFlags::IS_BACKFACE_VISIBLE,
RasterSpace::Screen,
prim_list,
scroll_root,
Some(tile_cache),
PictureOptions::default(),
));
PrimitiveInstance::new(
LayoutPoint::zero(),
LayoutRect::max_rect(),
PrimitiveInstanceKind::Picture {
data_handle: pic_data_handle,
pic_index: PictureIndex(pic_index),
segment_instance_index: SegmentInstanceIndex::INVALID,
},
parent_clip_chain_id,
)
}