Backed out changeset c2c9dbf826fe (bug 1581757) by dev's request

This commit is contained in:
Dorel Luca 2019-09-26 12:37:59 +03:00
parent 8d8222b8a9
commit f1e99da78f
3 changed files with 301 additions and 294 deletions

View File

@ -2266,8 +2266,6 @@ pub struct PrimitiveCluster {
pub prim_instances: Vec<PrimitiveInstance>,
/// Various flags / state for this cluster.
pub flags: ClusterFlags,
/// An optional scroll root to use if this cluster establishes a picture cache slice.
pub cache_scroll_root: Option<SpatialNodeIndex>,
}
/// Where to insert a prim instance in a primitive list.
@ -2288,7 +2286,6 @@ impl PrimitiveCluster {
spatial_node_index,
flags,
prim_instances: Vec::new(),
cache_scroll_root: None,
}
}
@ -2435,15 +2432,23 @@ impl PrimitiveList {
self.clusters.is_empty()
}
/// Add an existing cluster to this prim list
pub fn add_cluster(&mut self, cluster: PrimitiveCluster) {
self.clusters.push(cluster);
}
/// Merge another primitive list into this one
pub fn extend(&mut self, prim_list: PrimitiveList) {
self.clusters.extend(prim_list.clusters);
}
/// Return the number of clusters in this prim list
pub fn len(&self) -> usize {
self.clusters.len()
}
/// Split this primitive list at the given cluster index
pub fn split_off(&mut self, index: usize) -> PrimitiveList {
let clusters = self.clusters.split_off(index);
PrimitiveList {
clusters
}
}
}
/// Defines configuration options for a given picture primitive.

View File

@ -21,7 +21,7 @@ use crate::image::simplify_repeated_primitive;
use crate::intern::Interner;
use crate::internal_types::{FastHashMap, FastHashSet, LayoutPrimitiveInfo, Filter};
use crate::picture::{Picture3DContext, PictureCompositeMode, PicturePrimitive, PictureOptions};
use crate::picture::{BlitReason, OrderedPictureChild, PrimitiveList, TileCacheInstance, ClusterFlags};
use crate::picture::{BlitReason, OrderedPictureChild, PrimitiveList, TileCacheInstance};
use crate::prim_store::{PrimitiveInstance, PrimitiveSceneData};
use crate::prim_store::{PrimitiveInstanceKind, NinePatchDescriptor, PrimitiveStore};
use crate::prim_store::{ScrollNodeAndClipChain, PictureIndex};
@ -238,63 +238,6 @@ impl CompositeOps {
}
}
/// Information about unpaired Push/Pop clip chain instances that need to be fixed up.
struct ClipChainPairInfo {
spatial_node_index: SpatialNodeIndex,
clip_chain_id: ClipChainId,
}
/// Information about a set of primitive clusters that will form a picture cache slice.
struct Slice {
/// The spatial node root of the picture cache. If this is None, the slice
/// will not be cached and instead drawn directly to the parent surface. This
/// is a temporary measure until we enable caching all slices.
cache_scroll_root: Option<SpatialNodeIndex>,
/// List of primitive clusters that make up this slice
prim_list: PrimitiveList,
/// A list of clips that are shared by all primitives in the slice. These can be
/// filtered out and applied when the tile cache is composited rather than per-item.
shared_clips: Option<Vec<ClipDataHandle>>,
}
impl Slice {
// Open clip chain instances at the start of a slice
fn push_clip_instances(
&mut self,
stack: &[ClipChainPairInfo],
) {
for clip_chain_instance in stack.iter().rev() {
self.prim_list.add_prim_to_start(
create_clip_prim_instance(
clip_chain_instance.clip_chain_id,
PrimitiveInstanceKind::PushClipChain,
),
LayoutSize::zero(),
clip_chain_instance.spatial_node_index,
PrimitiveFlags::IS_BACKFACE_VISIBLE,
);
}
}
// Close clip chain instances at the end of a slice
fn pop_clip_instances(
&mut self,
stack: &[ClipChainPairInfo],
) {
for clip_chain_instance in stack {
self.prim_list.add_prim(
create_clip_prim_instance(
clip_chain_instance.clip_chain_id,
PrimitiveInstanceKind::PopClipChain,
),
LayoutSize::zero(),
clip_chain_instance.spatial_node_index,
PrimitiveFlags::IS_BACKFACE_VISIBLE,
);
}
}
}
/// A structure that converts a serialized display list into a form that WebRender
/// can use to later build a frame. This structure produces a BuiltScene. Public
/// members are typically those that are destructured into the BuiltScene.
@ -472,8 +415,6 @@ impl<'a> SceneBuilder<'a> {
rf_offset + scroll_offset
}
/// Figure out the shape of the display list, and wrap various primitive clusters
/// into tile cache primitive instances.
fn setup_picture_caching(
&mut self,
main_prim_list: &mut PrimitiveList,
@ -482,21 +423,71 @@ impl<'a> SceneBuilder<'a> {
return;
}
// If no explicit tile cache was enabled, insert a marker that will result in the
// entire display list being cached.
if !self.found_explicit_tile_cache {
if let Some(cluster) = main_prim_list.clusters.first_mut() {
cluster.flags.insert(ClusterFlags::CREATE_PICTURE_CACHE_PRE);
cluster.cache_scroll_root = Some(ROOT_SPATIAL_NODE_INDEX);
}
}
// This method is basically a hack to set up picture caching in a minimal
// way without having to check the public API (yet). The intent is to
// work out a good API for this and switch to using it. In the mean
// time, this allows basic picture caching to be enabled and used for
// ironing out remaining bugs, fixing performance issues and profiling.
// List of slices that have been found
let mut slices: Vec<Slice> = Vec::new();
// Current stack of open clip chain instances that need to be fixed up
//
// We know that the display list will contain something like the following:
// [Some number of primitives attached to root scroll now]
// [IFrame for the content]
// [A scroll root for the content (what we're interested in)]
// [Primitives attached to the scroll root, possibly with sub-scroll roots]
// [Some number of trailing primitives attached to root scroll frame]
//
// So we want to slice that stacking context up into:
// [root primitives]
// [tile cache picture]
// [primitives attached to cached scroll root]
// [trailing root primitives]
//
// This step is typically very quick, because there are only
// a small number of items in the root stacking context, since
// most of the content is embedded in its own picture.
//
// Find the first primitive which has the desired scroll root.
let mut first_index = None;
let mut main_scroll_root = None;
// If the main primitive list that we split for picture caching has
// clip chain instances at the top level, it's possible that we will
// create a split resulting in one list having unmatched PushClipChain
// or PopClipChain instances. This causes panics in pop_surface(),
// which asserts that the clip chain instances are matched.
// The code below is a (very inelegant) solution to that. It records
// clip chain instances found during the initial scan for scroll roots.
// Later, it uses this information to fix up unopened or unclosed clip
// instances on the split primitive lists.
// This is far from ideal - but it fixes the crash for now. In future
// we will be simplifying and/or removing how clip chain instances
// and picture cache splitting works, so we can tidy this up as
// part of those future changes.
let mut clip_chain_instances = Vec::new();
let mut clip_chain_instance_stack = Vec::new();
// Tracker for whether a new slice should be created
let mut create_slice = true;
// Maintain a list of clip node handles that are shared by every primitive
// in this list. These are often root / fixed position clips. We collect these
// and handle them when compositing the picture cache tiles. This saves per-item
// clip work, but more importantly, it avoids lots of invalidations due to
// content being clipped by fixed iframe/scrollframe rects.
// TODO(gw): The logic to build the shared clips list is quite complicated, because:
// (a) We want to cache result and not do a heap of extra work per primitive,
// since stress tests like dl_mutate have 50000+ primitives. Since each
// primitive often shares the same clip chain as the previous primitive,
// caching the last set of prim clips is generally sufficient.
// (b) The general logic to set up picture caching is still complicated due to
// not caching multiple slices (e.g. scroll bars). Once we enable
// multiple picture cache slices, this logic becomes much simpler.
// The clips we have found that exist on every primitive we are going to cache.
let mut shared_clips = Vec::new();
// The clips found the last time we traversed a set of clip chains. Stored and cleared
// here to avoid constant allocations.
let mut prim_clips = Vec::new();
@ -505,44 +496,58 @@ impl<'a> SceneBuilder<'a> {
// The last prim clip chain we build prim_clips for.
let mut last_prim_clip_chain_id = ClipChainId::NONE;
// 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);
/// Records the indices in the list of a push/pop clip chain instance pair.
#[derive(Debug)]
struct ClipChainPairInfo {
push_index: usize,
pop_index: usize,
spatial_node_index: SpatialNodeIndex,
clip_chain_id: ClipChainId,
}
if create_slice {
// When creating a slice, close off any open clip chains on prev slice.
if let Some(prev_slice) = slices.last_mut() {
prev_slice.pop_clip_instances(&clip_chain_instance_stack);
}
// Helper fn to collect clip handles from a given clip chain.
fn add_clips(
clip_chain_id: ClipChainId,
prim_clips: &mut Vec<ClipDataHandle>,
clip_store: &ClipStore,
) {
let mut current_clip_chain_id = clip_chain_id;
let mut slice = Slice {
cache_scroll_root: cluster.cache_scroll_root,
prim_list: PrimitiveList::empty(),
shared_clips: None,
};
while current_clip_chain_id != ClipChainId::NONE {
let clip_chain_node = &clip_store
.clip_chain_nodes[current_clip_chain_id.0 as usize];
// Open up clip chains on the stack on the new slice
slice.push_clip_instances(&clip_chain_instance_stack);
slices.push(slice);
create_slice = false;
prim_clips.push(clip_chain_node.handle);
current_clip_chain_id = clip_chain_node.parent_clip_chain_id;
}
}
for (cluster_index, cluster) in main_prim_list.clusters.iter().enumerate() {
let scroll_root = self.clip_scroll_tree.find_scroll_root(
cluster.spatial_node_index,
);
// Step through each prim instance, in order to collect shared clips for the slice.
for instance in &cluster.prim_instances {
// If a Push/Pop clip chain, record that in the clip stack stack.
// If we encounter a push/pop clip, record where they occurred in the
// primitive list for later processing.
match instance.kind {
PrimitiveInstanceKind::PushClipChain => {
clip_chain_instance_stack.push(ClipChainPairInfo {
clip_chain_instance_stack.push(clip_chain_instances.len());
clip_chain_instances.push(ClipChainPairInfo {
push_index: cluster_index,
pop_index: usize::MAX,
spatial_node_index: cluster.spatial_node_index,
clip_chain_id: instance.clip_chain_id,
});
// Invalidate the prim_clips cache - a clip chain was removed.
// Invalidate the prim_clips cache - there is a new clip chain.
update_shared_clips = true;
continue;
}
PrimitiveInstanceKind::PopClipChain => {
let clip_chain_instance = clip_chain_instance_stack.pop().unwrap();
let index = clip_chain_instance_stack.pop().unwrap();
let clip_chain_instance = &mut clip_chain_instances[index];
debug_assert_eq!(clip_chain_instance.pop_index, usize::MAX);
debug_assert_eq!(
clip_chain_instance.clip_chain_id,
instance.clip_chain_id,
@ -551,6 +556,7 @@ impl<'a> SceneBuilder<'a> {
clip_chain_instance.spatial_node_index,
cluster.spatial_node_index,
);
clip_chain_instance.pop_index = cluster_index;
// Invalidate the prim_clips cache - a clip chain was removed.
update_shared_clips = true;
continue;
@ -562,93 +568,141 @@ impl<'a> SceneBuilder<'a> {
update_shared_clips |= last_prim_clip_chain_id != instance.clip_chain_id;
last_prim_clip_chain_id = instance.clip_chain_id;
// TODO(gw): This is a hack for wrench, to not share clips for implicit
// picture caches. It's needed until we properly exclude
// shared clips that are not simple.
if update_shared_clips && self.found_explicit_tile_cache {
if update_shared_clips {
prim_clips.clear();
// Update the list of clips that apply to this primitive instance
for clip_instance in &clip_chain_instance_stack {
// Collect any clips from the clip chain stack that will affect this prim.
for clip_instance_index in &clip_chain_instance_stack {
let clip_instance = &clip_chain_instances[*clip_instance_index];
add_clips(
clip_instance.clip_chain_id,
&mut prim_clips,
&self.clip_store,
);
}
// Collect any clips from the primitive's specific clip chain.
add_clips(
instance.clip_chain_id,
&mut prim_clips,
&self.clip_store,
);
// We want to only retain clips that are shared across all primitives.
// TODO(gw): We could consider using a HashSet here, but:
// (a) The sizes of these arrays are typically very small (<< 10).
// (b) We would have to impl Ord/Eq on interner handles, which we
// otherwise don't need / want.
shared_clips.retain(|h1: &ClipDataHandle| {
let uid = h1.uid();
prim_clips.iter().any(|h2| {
uid == h2.uid()
})
});
update_shared_clips = false;
}
// If there are no shared clips set for this slice, the shared clips are just
// the current clips set. Otherwise, the shared clips are those that are
// in both the current shared list and the clips list for this primitive.
match slices.last_mut().unwrap().shared_clips {
Some(ref mut shared_clips) => {
if update_shared_clips {
shared_clips.retain(|h1: &ClipDataHandle| {
let uid = h1.uid();
prim_clips.iter().any(|h2| {
uid == h2.uid()
})
});
if scroll_root != ROOT_SPATIAL_NODE_INDEX {
// If we find multiple scroll roots in this page, then skip
// picture caching for now. In future, we can handle picture
// caching on these sites by creating a tile cache per
// scroll root, or (more likely) selecting the common parent
// scroll root between the detected scroll roots.
match main_scroll_root {
Some(main_scroll_root) => {
if main_scroll_root != scroll_root {
return;
}
}
None => {
main_scroll_root = Some(scroll_root);
}
}
ref mut shared_clips @ None => {
*shared_clips = Some(prim_clips.clone());
if first_index.is_none() {
// The first time we identify a prim that will be cached, set the prim_clips
// array to this, such that the retain() logic above works.
shared_clips = prim_clips.clone();
first_index = Some(cluster_index);
}
}
update_shared_clips = false;
}
// If this cluster creates a slice after, then note that for next cluster
create_slice |= cluster.flags.contains(ClusterFlags::CREATE_PICTURE_CACHE_POST);
// Finally, add this cluster to the current slice
slices.last_mut().unwrap().prim_list.add_cluster(cluster);
}
// Close off any open clip chains on prev slice.
if let Some(prev_slice) = slices.last_mut() {
prev_slice.pop_clip_instances(&clip_chain_instance_stack);
}
// Step through the slices, creating picture cache wrapper instances.
for (slice_index, slice) in slices.drain(..).enumerate() {
match slice.cache_scroll_root {
Some(scroll_root) => {
let background_color = if slice_index == 0 {
self.config.background_color
} else {
None
};
let instance = create_tile_cache(
slice_index,
scroll_root,
slice.prim_list,
background_color,
slice.shared_clips.unwrap_or(Vec::new()),
&mut self.interners,
&mut self.prim_store,
&mut self.clip_store,
);
main_prim_list.add_prim(
instance,
LayoutSize::zero(),
scroll_root,
PrimitiveFlags::IS_BACKFACE_VISIBLE,
);
}
None => {
main_prim_list.extend(slice.prim_list);
}
}
}
let main_scroll_root = match main_scroll_root {
Some(main_scroll_root) => main_scroll_root,
None => ROOT_SPATIAL_NODE_INDEX,
};
// Get the list of existing primitives in the main stacking context.
let mut old_prim_list = mem::replace(main_prim_list, PrimitiveList::empty());
// In the simple case, there are no preceding or trailing primitives,
// because everything is anchored to the root scroll node. Handle
// this case specially to avoid underflow error in the Some(..)
// path below.
let mut preceding_prims;
let mut remaining_prims;
match first_index {
Some(first_index) => {
// Split off the preceding primtives.
remaining_prims = old_prim_list.split_off(first_index);
preceding_prims = old_prim_list;
}
None => {
preceding_prims = PrimitiveList::empty();
remaining_prims = old_prim_list;
}
}
let mid_index = preceding_prims.len();
// Step through each clip chain pair, and see if it crosses a slice boundary.
for clip_chain_instance in clip_chain_instances {
if clip_chain_instance.push_index < mid_index && clip_chain_instance.pop_index >= mid_index {
preceding_prims.add_prim(
create_clip_prim_instance(
clip_chain_instance.clip_chain_id,
PrimitiveInstanceKind::PopClipChain,
),
LayoutSize::zero(),
clip_chain_instance.spatial_node_index,
PrimitiveFlags::IS_BACKFACE_VISIBLE,
);
remaining_prims.add_prim_to_start(
create_clip_prim_instance(
clip_chain_instance.clip_chain_id,
PrimitiveInstanceKind::PushClipChain,
),
LayoutSize::zero(),
clip_chain_instance.spatial_node_index,
PrimitiveFlags::IS_BACKFACE_VISIBLE,
);
}
}
let instance = create_tile_cache(
0,
main_scroll_root,
remaining_prims,
self.config.background_color,
shared_clips,
&mut self.interners,
&mut self.prim_store,
&mut self.clip_store,
);
// This contains the tile caching picture, with preceding and
// trailing primitives outside the main scroll root.
main_prim_list.extend(preceding_prims);
main_prim_list.add_prim(
instance,
LayoutSize::zero(),
main_scroll_root,
PrimitiveFlags::IS_BACKFACE_VISIBLE,
);
}
fn build_items(
@ -1678,6 +1732,9 @@ impl<'a> SceneBuilder<'a> {
None
};
// Mark if a user supplied tile cache was specified.
self.found_explicit_tile_cache |= create_tile_cache;
if is_pipeline_root && create_tile_cache && self.config.enable_picture_caching {
// we don't expect any nested tile-cache-enabled stacking contexts
debug_assert!(!self.sc_stack.iter().any(|sc| sc.create_tile_cache));
@ -1816,55 +1873,39 @@ impl<'a> SceneBuilder<'a> {
let parent_is_empty = match self.sc_stack.last_mut() {
Some(parent_sc) => {
if stacking_context.is_redundant(parent_sc) {
if !stacking_context.prim_list.is_empty() {
if stacking_context.clip_chain_id != ClipChainId::NONE {
let prim = create_clip_prim_instance(
stacking_context.clip_chain_id,
PrimitiveInstanceKind::PushClipChain,
);
stacking_context.prim_list.add_prim_to_start(
prim,
LayoutSize::zero(),
stacking_context.spatial_node_index,
PrimitiveFlags::IS_BACKFACE_VISIBLE,
);
if stacking_context.clip_chain_id != ClipChainId::NONE {
let prim = create_clip_prim_instance(
stacking_context.clip_chain_id,
PrimitiveInstanceKind::PushClipChain,
);
parent_sc.prim_list.add_prim(
prim,
LayoutSize::zero(),
stacking_context.spatial_node_index,
PrimitiveFlags::IS_BACKFACE_VISIBLE,
);
}
let prim = create_clip_prim_instance(
stacking_context.clip_chain_id,
PrimitiveInstanceKind::PopClipChain,
);
stacking_context.prim_list.add_prim(
prim,
LayoutSize::zero(),
stacking_context.spatial_node_index,
PrimitiveFlags::IS_BACKFACE_VISIBLE,
);
}
// If the parent context primitives list is empty, it's faster
// to assign the storage of the popped context instead of paying
// the copying cost for extend.
if parent_sc.prim_list.is_empty() {
parent_sc.prim_list = stacking_context.prim_list;
} else {
parent_sc.prim_list.extend(stacking_context.prim_list);
}
// If popping a redundant stacking context that is from a different pipeline,
// we want to insert flags where the picture cache slices should be created
// for this iframe. For now, we want to match existing behavior, that is:
// - Only cache content that is within the main scroll root, and:
// - Skip caching fixed position content before / after the scroll root.
// This means that we don't add scrollbars, which cause lots of extra
// invalidations. There is ongoing work to add tags to primitives that
// are scrollbars. Once this lands, we can simplify this logic considerably
// (and add a separate picture cache slice / OS layer for scroll bars).
if parent_sc.pipeline_id != stacking_context.pipeline_id {
stacking_context.init_picture_caching(&self.clip_scroll_tree);
// Mark that a user supplied tile cache was specified.
self.found_explicit_tile_cache = true;
}
// If the parent context primitives list is empty, it's faster
// to assign the storage of the popped context instead of paying
// the copying cost for extend.
if parent_sc.prim_list.is_empty() {
parent_sc.prim_list = stacking_context.prim_list;
} else {
parent_sc.prim_list.extend(stacking_context.prim_list);
}
if stacking_context.clip_chain_id != ClipChainId::NONE {
let prim = create_clip_prim_instance(
stacking_context.clip_chain_id,
PrimitiveInstanceKind::PopClipChain,
);
parent_sc.prim_list.add_prim(
prim,
LayoutSize::zero(),
stacking_context.spatial_node_index,
PrimitiveFlags::IS_BACKFACE_VISIBLE,
);
}
return;
@ -1874,7 +1915,7 @@ impl<'a> SceneBuilder<'a> {
None => true,
};
if self.sc_stack.is_empty() {
if stacking_context.create_tile_cache {
self.setup_picture_caching(
&mut stacking_context.prim_list,
);
@ -1907,6 +1948,35 @@ impl<'a> SceneBuilder<'a> {
),
};
// If no user supplied tile cache was specified, and picture caching is enabled,
// create an implicit tile cache for the whole frame builder.
// TODO(gw): This is only needed temporarily - once we support multiple slices
// correctly, this will be handled by setup_picture_caching.
if self.sc_stack.is_empty() &&
!self.found_explicit_tile_cache &&
self.config.enable_picture_caching {
let instance = create_tile_cache(
0,
ROOT_SPATIAL_NODE_INDEX,
stacking_context.prim_list,
self.config.background_color,
Vec::new(),
&mut self.interners,
&mut self.prim_store,
&mut self.clip_store,
);
let mut prim_list = PrimitiveList::empty();
prim_list.add_prim(
instance,
LayoutSize::zero(),
ROOT_SPATIAL_NODE_INDEX,
PrimitiveFlags::IS_BACKFACE_VISIBLE,
);
stacking_context.prim_list = prim_list;
}
// Add picture for this actual stacking context contents to render into.
let leaf_pic_index = PictureIndex(self.prim_store.pictures
.alloc()
@ -3509,61 +3579,6 @@ impl FlattenedStackingContext {
self.transform_style == TransformStyle::Preserve3D && self.composite_ops.is_empty()
}
/// Set up appropriate cluster flags for picture caching on this stacking context.
fn init_picture_caching(
&mut self,
clip_scroll_tree: &ClipScrollTree,
) {
let mut selected_cluster_and_scroll_root = None;
// There's probably a tidier way to express the logic below, but we will be
// removing this shortly anyway, as we create slices for more than just the
// main scroll root.
for (cluster_index, cluster) in self.prim_list.clusters.iter().enumerate() {
let scroll_root = clip_scroll_tree.find_scroll_root(
cluster.spatial_node_index,
);
if scroll_root != ROOT_SPATIAL_NODE_INDEX {
match selected_cluster_and_scroll_root {
Some((_, selected_scroll_root)) => {
if selected_scroll_root != scroll_root {
// Found multiple scroll roots - bail out and just cache fixed position
selected_cluster_and_scroll_root = None;
break;
}
}
None => {
selected_cluster_and_scroll_root = Some((cluster_index, scroll_root));
}
}
}
}
// Either set up a fixed root cache, or a scrolling one if there was only
// a single scroll root found (the common case).
match selected_cluster_and_scroll_root {
Some((cluster_index, scroll_root)) => {
let cluster = &mut self.prim_list.clusters[cluster_index];
cluster.flags.insert(ClusterFlags::CREATE_PICTURE_CACHE_PRE);
cluster.cache_scroll_root = Some(scroll_root);
}
None => {
if let Some(cluster) = self.prim_list.clusters.first_mut() {
cluster.flags.insert(ClusterFlags::CREATE_PICTURE_CACHE_PRE);
cluster.cache_scroll_root = Some(ROOT_SPATIAL_NODE_INDEX);
}
}
}
// For now, always end the cache slice at the end of the stacking context.
// This preserves existing behavior, but breaks in some cases on platforms
// that use overlay scroll bars. We can fix this as a follow up once this
// patch lands.
if let Some(cluster) = self.prim_list.clusters.last_mut() {
cluster.flags.insert(ClusterFlags::CREATE_PICTURE_CACHE_POST);
}
}
/// Return true if the stacking context isn't needed.
pub fn is_redundant(
&self,
@ -3606,6 +3621,11 @@ impl FlattenedStackingContext {
return false;
}
// If this stacking context gets picture caching, we need it.
if self.create_tile_cache {
return false;
}
// It is redundant!
true
}
@ -3894,21 +3914,3 @@ fn create_tile_cache(
parent_clip_chain_id,
)
}
// Helper fn to collect clip handles from a given clip chain.
fn add_clips(
clip_chain_id: ClipChainId,
prim_clips: &mut Vec<ClipDataHandle>,
clip_store: &ClipStore,
) {
let mut current_clip_chain_id = clip_chain_id;
while current_clip_chain_id != ClipChainId::NONE {
let clip_chain_node = &clip_store
.clip_chain_nodes[current_clip_chain_id.0 as usize];
prim_clips.push(clip_chain_node.handle);
current_clip_chain_id = clip_chain_node.parent_clip_chain_id;
}
}

View File

@ -83,8 +83,8 @@ fuzzy-if(Android&&!webrender,3-3,4-4) fuzzy-if(Android&&webrender,13-13,4-4) fuz
# checkerboarding to occur
default-preferences pref(layers.low-precision-buffer,false)
skip-if(!asyncPan) == checkerboard-1.html checkerboard-1-ref.html
skip-if(!asyncPan) == checkerboard-2.html checkerboard-2-ref.html
skip-if(!asyncPan) == checkerboard-3.html checkerboard-3-ref.html
skip-if(!asyncPan) fails-if(geckoview&&webrender) == checkerboard-2.html checkerboard-2-ref.html
skip-if(!asyncPan) fails-if(geckoview&&webrender) == checkerboard-3.html checkerboard-3-ref.html
default-preferences
skip-if(!Android) pref(apz.allow_zooming,true) fails-if(geckoview&&webrender) == position-fixed-async-zoom-1.html position-fixed-async-zoom-1-ref.html