Bug 1584439 - Enable picture caching for scroll bars and UI content. r=nical

Once this patch lands, all content drawn by WebRender is drawn into
a picture cache surface.

This will incur some extra GPU memory overhead since there are extra
GPU texture buffers. Much of this can be reduced by adding a couple
of simple optimizations in future to detect tiles that are solid
colors only.

With this change, we'll now be able to provide exact dirty rects for
the entire screen without any hacks, and start the work to draw into
OS compositor surfaces directly.

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

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Glenn Watson 2019-10-01 04:51:56 +00:00
parent 896ee6e424
commit cc9a8ee004
28 changed files with 207 additions and 114 deletions

View File

@ -1463,6 +1463,12 @@ impl Device {
self.max_texture_size = self.max_texture_size.min(size);
}
/// Returns the device string of the renderer. Useful to enable code paths to
/// work around bugs on various renderers.
pub fn renderer_name(&self) -> &str {
&self.renderer_name
}
/// Returns the limit on texture dimensions (width or height).
pub fn max_texture_size(&self) -> i32 {
self.max_texture_size

View File

@ -34,7 +34,7 @@ use crate::render_task::{RenderTask, RenderTaskLocation, BlurTaskCache, ClearMod
use crate::resource_cache::ResourceCache;
use crate::scene::SceneProperties;
use smallvec::SmallVec;
use std::{mem, u8};
use std::{mem, u8, marker};
use std::sync::atomic::{AtomicUsize, Ordering};
use crate::texture_cache::TextureCacheHandle;
use crate::util::{TransformedRectKind, MatrixHelpers, MaxRect, scale_factors, VecHelper, subtract_rect};
@ -141,6 +141,8 @@ pub struct PictureCacheState {
opacity_bindings: FastHashMap<PropertyBindingId, OpacityBindingInfo>,
/// The current transform of the picture cache root spatial node
root_transform: TransformKey,
/// The current tile size in device pixels
current_tile_size: DeviceIntSize,
}
/// Stores a list of cached picture tiles that are retained
@ -177,15 +179,19 @@ pub type TileOffset = Point2D<i32, TileCoordinate>;
pub type TileSize = Size2D<i32, TileCoordinate>;
pub type TileRect = Rect<i32, TileCoordinate>;
/// The size in device pixels of a cached tile. The currently chosen
/// size is arbitrary. We should do some profiling to find the best
/// size for real world pages.
///
/// Note that we use a separate, smaller size during wrench testing, so that
/// we get tighter dirty rects and can do more meaningful invalidation
/// tests.
pub const TILE_SIZE_WIDTH: i32 = 2048;
pub const TILE_SIZE_HEIGHT: i32 = 512;
/// The size in device pixels of a normal cached tile.
pub const TILE_SIZE_LARGE: DeviceIntSize = DeviceIntSize {
width: 2048,
height: 512,
_unit: marker::PhantomData,
};
/// The size in device pixels of a tile for small picture caches.
pub const TILE_SIZE_SMALL: DeviceIntSize = DeviceIntSize {
width: 128,
height: 128,
_unit: marker::PhantomData,
};
/// The maximum size per axis of a surface,
/// in WorldPixel coordinates.
@ -286,6 +292,9 @@ struct TilePostUpdateContext<'a> {
/// Helper to map picture coordinates to world space
pic_to_world_mapper: SpaceMapper<PicturePixel, WorldPixel>,
/// Current size in device pixels of tiles for this cache
current_tile_size: DeviceIntSize,
}
// Mutable state passed to picture cache tiles during post_update
@ -628,10 +637,20 @@ impl Tile {
return false;
}
// For small tiles, only allow splitting once, since otherwise we
// end up splitting into tiny dirty rects that aren't saving much
// in the way of pixel work.
let max_split_level = if ctx.current_tile_size == TILE_SIZE_LARGE {
3
} else {
1
};
// Consider splitting / merging dirty regions
self.root.maybe_merge_or_split(
0,
&self.current_descriptor.prims,
max_split_level,
);
// See if this tile is a simple color, in which case we can just draw
@ -715,12 +734,8 @@ impl Tile {
// Ensure that this texture is allocated.
if let TileSurface::Texture { ref mut handle, ref mut visibility_mask } = surface {
if !state.resource_cache.texture_cache.is_allocated(handle) {
let tile_size = DeviceIntSize::new(
TILE_SIZE_WIDTH,
TILE_SIZE_HEIGHT,
);
state.resource_cache.texture_cache.update_picture_cache(
tile_size,
ctx.current_tile_size,
handle,
state.gpu_cache,
);
@ -1081,6 +1096,8 @@ pub struct TileCacheInstance {
/// between display lists - this seems very unlikely to occur on most pages, but
/// can be revisited if we ever notice that.
pub slice: usize,
/// The currently selected tile size to use for this cache
pub current_tile_size: DeviceIntSize,
/// The positioning node for this tile cache.
pub spatial_node_index: SpatialNodeIndex,
/// Hash of tiles present in this picture.
@ -1175,6 +1192,7 @@ impl TileCacheInstance {
root_transform: TransformKey::Local,
shared_clips,
shared_clip_chain,
current_tile_size: DeviceIntSize::zero(),
}
}
@ -1221,8 +1239,6 @@ impl TileCacheInstance {
frame_context: &FrameVisibilityContext,
frame_state: &mut FrameVisibilityState,
) -> WorldRect {
let tile_width = TILE_SIZE_WIDTH;
let tile_height = TILE_SIZE_HEIGHT;
self.surface_index = surface_index;
self.local_rect = pic_rect;
self.local_clip_rect = PictureRect::max_rect();
@ -1292,6 +1308,26 @@ impl TileCacheInstance {
self.root_transform = prev_state.root_transform;
self.spatial_nodes = prev_state.spatial_nodes;
self.opacity_bindings = prev_state.opacity_bindings;
self.current_tile_size = prev_state.current_tile_size;
}
// Work out what size tile is appropriate for this picture cache.
let desired_tile_size = if pic_rect.size.width < 2.0 * TILE_SIZE_SMALL.width as f32 ||
pic_rect.size.height < 2.0 * TILE_SIZE_SMALL.height as f32 {
TILE_SIZE_SMALL
} else {
TILE_SIZE_LARGE
};
// If the desired tile size has changed, then invalidate and drop any
// existing tiles.
// TODO(gw): This could in theory result in invalidating every frame if the
// size of a picture is dynamically changing, just around the
// threshold above. If we ever see this happening we can improve
// the theshold logic above.
if desired_tile_size != self.current_tile_size {
self.tiles.clear();
self.current_tile_size = desired_tile_size;
}
// Map an arbitrary point in picture space to world space, to work out
@ -1352,8 +1388,8 @@ impl TileCacheInstance {
}
let world_tile_size = WorldSize::new(
tile_width as f32 / frame_context.global_device_pixel_scale.0,
tile_height as f32 / frame_context.global_device_pixel_scale.0,
self.current_tile_size.width as f32 / frame_context.global_device_pixel_scale.0,
self.current_tile_size.height as f32 / frame_context.global_device_pixel_scale.0,
);
// We know that this is an exact rectangle, since we (for now) only support tile
@ -1760,6 +1796,7 @@ impl TileCacheInstance {
spatial_nodes: &self.spatial_nodes,
opacity_bindings: &self.opacity_bindings,
pic_to_world_mapper,
current_tile_size: self.current_tile_size,
};
let mut state = TilePostUpdateState {
@ -2248,6 +2285,8 @@ bitflags! {
const CREATE_PICTURE_CACHE_PRE = 16;
/// Force creation of a picture caching slice after this cluster.
const CREATE_PICTURE_CACHE_POST = 32;
/// If set, this cluster represents a scroll bar container.
const SCROLLBAR_CONTAINER = 64;
}
}
@ -2368,6 +2407,10 @@ impl PrimitiveList {
flags.insert(ClusterFlags::IS_BACKFACE_VISIBLE);
}
if prim_flags.contains(PrimitiveFlags::IS_SCROLLBAR_CONTAINER) {
flags.insert(ClusterFlags::SCROLLBAR_CONTAINER);
}
// Insert the primitive into the first or last cluster as required
match insert_position {
PrimitiveListPosition::Begin => {
@ -2628,6 +2671,7 @@ impl PicturePrimitive {
opacity_bindings: tile_cache.opacity_bindings,
fract_offset: tile_cache.fract_offset,
root_transform: tile_cache.root_transform,
current_tile_size: tile_cache.current_tile_size,
},
);
}
@ -3034,11 +3078,6 @@ impl PicturePrimitive {
let tile_cache = self.tile_cache.as_mut().unwrap();
let mut first = true;
let tile_size = DeviceSize::new(
TILE_SIZE_WIDTH as f32,
TILE_SIZE_HEIGHT as f32,
);
for key in &tile_cache.tiles_to_draw {
let tile = tile_cache.tiles.get_mut(key).expect("bug: no tile found!");
@ -3080,9 +3119,9 @@ impl PicturePrimitive {
RenderTaskLocation::PictureCache {
texture: cache_item.texture_id,
layer: cache_item.texture_layer,
size: tile_size.to_i32(),
size: tile_cache.current_tile_size,
},
tile_size,
tile_cache.current_tile_size.to_f32(),
pic_index,
content_origin.to_i32(),
UvRectKind::Rect,
@ -4168,7 +4207,7 @@ impl TileNode {
let world_rect = pic_to_world_mapper.map(&self.rect).unwrap();
let device_rect = world_rect * global_device_pixel_scale;
let outer_color = color.scale_alpha(0.6);
let outer_color = color.scale_alpha(0.3);
let inner_color = outer_color.scale_alpha(0.5);
scratch.push_debug_rect(
device_rect.inflate(-3.0, -3.0),
@ -4268,6 +4307,7 @@ impl TileNode {
&self,
level: i32,
can_merge: bool,
max_split_levels: i32,
) -> Option<TileModification> {
match self.kind {
TileNodeKind::Leaf { dirty_tracker, frames_since_modified, .. } => {
@ -4275,7 +4315,7 @@ impl TileNode {
if frames_since_modified > 64 {
let dirty_frames = dirty_tracker.count_ones();
// If the tree isn't too deep, and has been regularly invalidating, split
if level < 3 && dirty_frames > 32 {
if level < max_split_levels && dirty_frames > 32 {
Some(TileModification::Split)
} else if can_merge && (dirty_tracker == 0 || dirty_frames == 64) && level > 0 {
// If allowed to merge, and nothing has changed for 64 frames, merge
@ -4298,15 +4338,16 @@ impl TileNode {
&mut self,
level: i32,
curr_prims: &[PrimitiveDescriptor],
max_split_levels: i32,
) {
// Determine if this tile wants to split or merge
let tile_mod = match self.kind {
TileNodeKind::Leaf { .. } => {
self.get_preference(level, false)
self.get_preference(level, false, max_split_levels)
}
TileNodeKind::Node { ref children, .. } => {
// Only merge if all children want to merge
if children.iter().all(|c| c.get_preference(level+1, true) == Some(TileModification::Merge)) {
if children.iter().all(|c| c.get_preference(level+1, true, max_split_levels) == Some(TileModification::Merge)) {
Some(TileModification::Merge)
} else {
None
@ -4396,6 +4437,7 @@ impl TileNode {
child.maybe_merge_or_split(
level+1,
curr_prims,
max_split_levels,
);
}
}

View File

@ -68,7 +68,7 @@ use crate::internal_types::{CacheTextureId, DebugOutput, FastHashMap, FastHashSe
use crate::internal_types::{TextureCacheAllocationKind, TextureCacheUpdate, TextureUpdateList, TextureUpdateSource};
use crate::internal_types::{RenderTargetInfo, SavedTargetIndex, Swizzle};
use malloc_size_of::MallocSizeOfOps;
use crate::picture::{RecordedDirtyRegion, TILE_SIZE_WIDTH, TILE_SIZE_HEIGHT};
use crate::picture::{RecordedDirtyRegion, TILE_SIZE_LARGE, TILE_SIZE_SMALL};
use crate::prim_store::DeferredResolve;
use crate::profiler::{BackendProfileCounters, FrameProfileCounters, TimeProfileCounter,
GpuProfileTag, RendererProfileCounters, RendererProfileTimers};
@ -1890,6 +1890,7 @@ impl Renderer {
}
let max_texture_size = device.max_texture_size();
let max_texture_layers = device.max_texture_layers();
let is_android_emulator = device.renderer_name().contains("Android Emulator");
register_thread_with_profiler("Compositor".to_owned());
@ -2150,9 +2151,18 @@ impl Renderer {
}
let picture_tile_sizes = &[
DeviceIntSize::new(TILE_SIZE_WIDTH, TILE_SIZE_HEIGHT),
TILE_SIZE_LARGE,
TILE_SIZE_SMALL,
];
// The android emulator has a bug where invalid errors are generated
// when doing a blit while resizing picture cache texture arrays. As
// a temporary workaround for this, allocate enough initial slices when
// running on the emulator so that we don't end up resizing during a
// wrench test run. We should remove this once the upstream bug is
// fixed. See https://bugzilla.mozilla.org/show_bug.cgi?id=1555002.
let min_picture_cache_slices = if is_android_emulator { 16 } else { 1 };
let texture_cache = TextureCache::new(
max_texture_size,
max_texture_layers,
@ -2164,6 +2174,7 @@ impl Renderer {
start_size,
color_cache_formats,
swizzle_settings,
min_picture_cache_slices,
);
let glyph_cache = GlyphCache::new(max_glyph_cache_size);

View File

@ -2279,6 +2279,7 @@ impl ResourceCache {
DeviceIntSize::zero(),
self.texture_cache.color_formats(),
self.texture_cache.swizzle_settings(),
self.texture_cache.min_picture_cache_slices(),
);
}
}

View File

@ -487,13 +487,11 @@ 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);
}
// Unconditionally insert a marker to create a picture cache slice on the
// first cluster. This handles implicit picture caches, and also the common
// case, by allowing the root / background primitives to be cached in a slice.
if let Some(cluster) = main_prim_list.clusters.first_mut() {
cluster.flags.insert(ClusterFlags::CREATE_PICTURE_CACHE_PRE);
}
// List of slices that have been found
@ -623,36 +621,35 @@ impl<'a> SceneBuilder<'a> {
// 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 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,
);
// If the cluster specifies a scroll root, use it. Otherwise,
// just cache assuming no scrolling takes place. Even if that's
// not true, we still get caching benefits for any changes that
// occur while not scrolling (such as animation, video etc);
let scroll_root = slice.cache_scroll_root.unwrap_or(ROOT_SPATIAL_NODE_INDEX);
main_prim_list.add_prim(
instance,
LayoutSize::zero(),
scroll_root,
PrimitiveFlags::IS_BACKFACE_VISIBLE,
);
}
None => {
main_prim_list.extend(slice.prim_list);
}
}
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,
);
}
}
@ -3521,51 +3518,71 @@ impl FlattenedStackingContext {
&mut self,
clip_scroll_tree: &ClipScrollTree,
) {
let mut selected_cluster_and_scroll_root = None;
struct SliceInfo {
cluster_index: usize,
scroll_roots: Vec<SpatialNodeIndex>,
}
// 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.
let mut slices: Vec<SliceInfo> = Vec::new();
// Step through each cluster, and work out where the slice boundaries should be.
for (cluster_index, cluster) in self.prim_list.clusters.iter().enumerate() {
let scroll_root = clip_scroll_tree.find_scroll_root(
cluster.spatial_node_index,
);
// We want to create a slice in the following conditions:
// (1) This cluster is a scrollbar
// (2) This cluster begins a 'real' scroll root, where we don't currently have a real scroll root
// (3) No slice exists yet
let create_new_slice =
cluster.flags.contains(ClusterFlags::SCROLLBAR_CONTAINER) ||
slices.last().map(|slice| {
scroll_root != ROOT_SPATIAL_NODE_INDEX &&
slice.scroll_roots.is_empty()
}).unwrap_or(true);
// Create a new slice if required
if create_new_slice {
slices.push(SliceInfo {
cluster_index,
scroll_roots: Vec::new(),
});
}
// If this is a 'real' scroll root, include that in the list of scroll roots
// that have been found for this slice.
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));
}
let slice = slices.last_mut().unwrap();
if !slice.scroll_roots.contains(&scroll_root) {
slice.scroll_roots.push(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);
}
// Walk the list of slices, setting appropriate flags on the clusters which are
// later used during setup_picture_caching.
for slice in slices.drain(..) {
let cluster = &mut self.prim_list.clusters[slice.cluster_index];
// Mark that this cluster creates a picture cache slice
cluster.flags.insert(ClusterFlags::CREATE_PICTURE_CACHE_PRE);
assert!(!slice.scroll_roots.contains(&ROOT_SPATIAL_NODE_INDEX));
// Only select a scroll root for this slice if there's a single 'real' scroll
// root. If there are no scroll roots (doesn't scroll) or there are multiple
// scroll roots, then cache as a fixed slice. In the case of multiple scroll
// roots, this means we'll do some extra rasterization work (but only in dirty
// regions) as parts of the slice scroll. However, it does mean that we
// reduce number of tiles / GPU memory, and keep subpixel AA. In future, we
// might decide to create extra slices in some cases where there are multiple
// scroll roots (specifically, non-overlapping sibling scroll roots might be
// useful to support).
if slice.scroll_roots.len() == 1 {
cluster.cache_scroll_root = Some(slice.scroll_roots.first().cloned().unwrap());
}
}
// 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.
// Always end the cache at the end of the stacking context, so that we don't
// cache anything from primitives outside this pipeline in the same slice.
if let Some(cluster) = self.prim_list.clusters.last_mut() {
cluster.flags.insert(ClusterFlags::CREATE_PICTURE_CACHE_POST);
}
@ -3613,6 +3630,11 @@ impl FlattenedStackingContext {
return false;
}
// If this stacking context is a scrollbar, retain it so it can form a picture cache slice
if self.prim_flags.contains(PrimitiveFlags::IS_SCROLLBAR_CONTAINER) {
return false;
}
// It is redundant!
true
}

View File

@ -517,6 +517,9 @@ pub struct TextureCache {
/// Maximum number of texture layers supported by hardware.
max_texture_layers: usize,
/// The minimum number of picture cache slices to allocate.
min_picture_cache_slices: usize,
/// Settings on using texture unit swizzling.
swizzle: Option<SwizzleSettings>,
@ -565,6 +568,7 @@ impl TextureCache {
initial_size: DeviceIntSize,
color_formats: TextureFormatPair<ImageFormat>,
swizzle: Option<SwizzleSettings>,
min_picture_cache_slices: usize,
) -> Self {
if cfg!(target_os = "macos") {
// On MBP integrated Intel GPUs, texture arrays appear to be
@ -608,7 +612,7 @@ impl TextureCache {
slices: {
let num_x = (initial_size.width + tile_size.width - 1) / tile_size.width;
let num_y = (initial_size.height + tile_size.height - 1) / tile_size.height;
let count = (num_x * num_y).max(1).min(16) as usize;
let count = (num_x * num_y).max(min_picture_cache_slices as i32).min(16) as usize;
info!("Initializing picture texture with {}x{} slices", num_x, num_y);
vec![WholeTextureSlice { uv_rect_handle: None }; count]
},
@ -641,6 +645,7 @@ impl TextureCache {
per_doc_data: FastHashMap::default(),
doc_data: PerDocumentData::new(),
require_frame_build: false,
min_picture_cache_slices,
}
}
@ -660,6 +665,7 @@ impl TextureCache {
DeviceIntSize::zero(),
TextureFormatPair::from(image_format),
None,
1,
);
let mut now = FrameStamp::first(DocumentId::new(IdNamespace(1), 1));
now.advance();
@ -700,7 +706,7 @@ impl TextureCache {
fn clear_picture(&mut self) {
self.clear_kind(EntryKind::Picture);
for picture_texture in &mut self.picture_textures {
if let Some(texture_id) = picture_texture.reset(PICTURE_TEXTURE_ADD_SLICES) {
if let Some(texture_id) = picture_texture.reset(PICTURE_TEXTURE_ADD_SLICES.max(self.min_picture_cache_slices)) {
self.pending_updates.push_reset(texture_id, picture_texture.to_info());
}
}
@ -893,6 +899,11 @@ impl TextureCache {
self.swizzle
}
#[cfg(feature = "replay")]
pub fn min_picture_cache_slices(&self) -> usize {
self.min_picture_cache_slices
}
pub fn pending_updates(&mut self) -> TextureUpdateList {
mem::replace(&mut self.pending_updates, TextureUpdateList::new())
}

View File

@ -9,7 +9,7 @@ fuzzy(1,30000) == difference-transparent.yaml difference-transparent-ref.yaml
fuzzy(1,32) == repeated-difference.yaml repeated-difference-ref.yaml
== isolated.yaml isolated-ref.yaml
fuzzy(3,393) == isolated-2.yaml isolated-2-ref.yaml
fuzzy(3,397) == isolated-2.yaml isolated-2-ref.yaml
== isolated-with-filter.yaml isolated-ref.yaml
== isolated-premultiplied.yaml blank.yaml
== isolated-premultiplied-2.yaml isolated-premultiplied-2-ref.yaml

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@ -5,7 +5,7 @@ platform(linux,mac) == border-gradient-nine-patch.yaml border-gradient-nine-patc
platform(linux,mac) == border-radial-gradient-nine-patch.yaml border-radial-gradient-nine-patch.png
== border-radii.yaml border-radii.png
== border-none.yaml border-none-ref.yaml
fuzzy(1,68) == border-overlapping-corner.yaml border-overlapping-corner-ref.yaml
fuzzy(128,69) == border-overlapping-corner.yaml border-overlapping-corner-ref.yaml
== border-overlapping-edge.yaml border-overlapping-edge-ref.yaml
== border-invisible.yaml border-invisible-ref.yaml
platform(linux,mac) == border-suite.yaml border-suite.png

View File

@ -9,7 +9,7 @@ fuzzy(8,60) == custom-clip-chains.yaml custom-clip-chains-ref.yaml
== fixed-position-clipping.yaml fixed-position-clipping-ref.yaml
platform(linux,mac) == segmentation-with-other-coordinate-system-clip.yaml segmentation-with-other-coordinate-system-clip.png
== segmentation-across-rotation.yaml segmentation-across-rotation-ref.yaml
skip_on(android,device) == color_targets(3) alpha_targets(1) stacking-context-clip.yaml stacking-context-clip-ref.yaml
skip_on(android,device) == color_targets(4) alpha_targets(1) stacking-context-clip.yaml stacking-context-clip-ref.yaml
== snapping.yaml snapping-ref.yaml
fuzzy(70,2400) == clip-and-filter-with-rotation.yaml clip-and-filter-with-rotation-ref.yaml
color_targets(1) alpha_targets(0) == clip-out-rotation.yaml blank.yaml # Unexpected color targets, see bug 1580795

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

After

Width:  |  Height:  |  Size: 4.9 KiB

View File

@ -28,7 +28,7 @@ skip_on(android,device) fuzzy(1,12) == draw_calls(6) color_targets(6) alpha_targ
== filter-saturate-red-alpha-1.yaml filter-saturate-red-alpha-1-ref.yaml
== filter-saturate-green-alpha-1.yaml filter-saturate-green-alpha-1-ref.yaml
== filter-saturate-blue-alpha-1.yaml filter-saturate-blue-alpha-1-ref.yaml
fuzzy(1,1) == filter-hue-rotate-1.yaml filter-hue-rotate-1-ref.yaml
fuzzy(1,14) == filter-hue-rotate-1.yaml filter-hue-rotate-1-ref.yaml
skip_on(android,device) == filter-hue-rotate-alpha-1.yaml filter-hue-rotate-alpha-1-ref.yaml # Fails on Pixel2
skip_on(android,device) fuzzy(2,9072) == filter-long-chain.yaml filter-long-chain.png # fails on Pixel2
platform(linux,mac) == filter-drop-shadow.yaml filter-drop-shadow.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.1 KiB

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

View File

@ -7,7 +7,7 @@ skip_on(android,emulator) == nested-mask-tiling.yaml nested-mask-ref.yaml # And
== mask-transformed-to-empty-rect.yaml mask-transformed-to-empty-rect-ref.yaml
platform(linux,mac) == rounded-corners.yaml rounded-corners.png
!= mask.yaml out-of-bounds.yaml
platform(linux,mac) fuzzy(1,17500) color_targets(3) alpha_targets(1) == mask-atomicity.yaml mask-atomicity-ref.yaml
platform(linux,mac) fuzzy(1,17500) color_targets(6) alpha_targets(1) == mask-atomicity.yaml mask-atomicity-ref.yaml
platform(linux,mac) fuzzy(1,17500) == mask-atomicity-tiling.yaml mask-atomicity-ref.yaml
platform(linux,mac) == mask-perspective.yaml mask-perspective.png
skip_on(android,emulator) == fuzzy(1,7) mask-perspective-tiling.yaml mask-perspective.yaml # Android emulator: GL error 502 at tex_sub_image_3d_pbo, fails on opt

View File

@ -1 +1 @@
skip_on(android) == color_targets(2) alpha_targets(0) no-clip-mask.yaml no-clip-mask.png # Too wide for Android
skip_on(android) == color_targets(4) alpha_targets(0) no-clip-mask.yaml no-clip-mask.png # Too wide for Android

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.6 KiB

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 19 KiB

View File

@ -22,8 +22,8 @@ skip_on(android) == shadow-red.yaml shadow-red-ref.yaml
skip_on(android) fuzzy(1,735) == shadow-grey.yaml shadow-grey-ref.yaml
skip_on(android) fuzzy(1,663) == shadow-grey-transparent.yaml shadow-grey-ref.yaml
== subtle-shadow.yaml subtle-shadow-ref.yaml
== shadow-atomic.yaml shadow-atomic-ref.yaml
== shadow-clip-rect.yaml shadow-atomic-ref.yaml
fuzzy(1,64) == shadow-atomic.yaml shadow-atomic-ref.yaml
fuzzy(1,64) == shadow-clip-rect.yaml shadow-atomic-ref.yaml
fuzzy(1,1) platform(linux) == shadow-ordering.yaml shadow-ordering-ref.yaml
# Next 6 tests affected by bug 1548099 on Android
skip_on(android) != synthetic-bold.yaml synthetic-bold-not-ref.yaml
@ -70,5 +70,5 @@ fuzzy(5,4369) == shadow-border.yaml shadow-solid-ref.yaml
fuzzy(5,4369) == shadow-image.yaml shadow-solid-ref.yaml
options(disable-aa) == snap-clip.yaml snap-clip-ref.yaml
platform(linux) == perspective-clip.yaml perspective-clip.png
fuzzy(1,6) options(disable-subpixel) == raster-space-snap.yaml raster-space-snap-ref.yaml
fuzzy(1,39) options(disable-subpixel) == raster-space-snap.yaml raster-space-snap-ref.yaml
# == intermediate-transform.yaml intermediate-transform-ref.yaml # fails because of AA inavailable with an intermediate surface

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

View File

@ -50,9 +50,9 @@ fuzzy(0-1,0-60000) skip-if(!asyncPan) == group-opacity-surface-size-1.html group
fuzzy-if(Android,0-1,0-197) fuzzy-if(webrender,0-1,0-1) skip-if(!asyncPan) == position-sticky-transformed.html position-sticky-transformed-ref.html
skip-if(!asyncPan) == offscreen-prerendered-active-opacity.html offscreen-prerendered-active-opacity-ref.html
fuzzy-if(Android,0-6,0-4) fuzzy-if(skiaContent&&!Android,0-1,0-34) fuzzy-if(webrender&&gtkWidget,64-64,24-24) fuzzy-if(webrender&&cocoaWidget,7-7,37-37) skip-if(!asyncPan) == offscreen-clipped-blendmode-1.html offscreen-clipped-blendmode-ref.html
fuzzy-if(Android,0-6,0-4) fuzzy-if(webrender&&gtkWidget,64-64,14-14) fuzzy-if(webrender&&cocoaWidget,7-7,37-37) skip-if(!asyncPan) == offscreen-clipped-blendmode-2.html offscreen-clipped-blendmode-ref.html
fuzzy-if(Android,0-6,0-4) fuzzy-if(webrender&&gtkWidget,64-64,24-24) fuzzy-if(webrender&&cocoaWidget,7-7,37-37) skip-if(!asyncPan) == offscreen-clipped-blendmode-2.html offscreen-clipped-blendmode-ref.html
fuzzy-if(Android,0-6,0-4) skip == offscreen-clipped-blendmode-3.html offscreen-clipped-blendmode-ref.html # bug 1251588 - wrong AGR on mix-blend-mode item
fuzzy-if(Android,0-6,0-4) fuzzy-if(webrender&&gtkWidget,64-64,14-14) fuzzy-if(webrender&&cocoaWidget,7-7,37-37) skip-if(!asyncPan) == offscreen-clipped-blendmode-4.html offscreen-clipped-blendmode-ref.html
fuzzy-if(Android,0-6,0-4) fuzzy-if(webrender&&gtkWidget,64-64,24-24) fuzzy-if(webrender&&cocoaWidget,7-7,37-37) skip-if(!asyncPan) == offscreen-clipped-blendmode-4.html offscreen-clipped-blendmode-ref.html
fuzzy-if(Android,0-7,0-1406) fuzzy-if(webrender&&gtkWidget,1-1,20-20) fuzzy-if(webrender&&cocoaWidget,1-1,19-19) skip-if(!asyncPan) == perspective-scrolling-1.html perspective-scrolling-1-ref.html
fuzzy-if(Android,0-7,0-4) skip-if(!asyncPan) == perspective-scrolling-2.html perspective-scrolling-2-ref.html
fuzzy-if(Android,0-19,0-4) fuzzy-if(webrender&&gtkWidget,24-24,14-14) fuzzy-if(webrender&&cocoaWidget,13-13,39-39) skip-if(!asyncPan) == perspective-scrolling-3.html perspective-scrolling-3-ref.html

View File

@ -51,5 +51,5 @@ fuzzy-if(Android,0-8,0-630) fuzzy-if(OSX,0-1,0-11) fuzzy-if(skiaContent,0-1,0-22
== iframe-1.html iframe-1-ref.html
== transformed-1.html transformed-1-ref.html
fuzzy-if(Android,0-4,0-4) fuzzy-if(webrender&&gtkWidget,31-31,24-24) fuzzy-if(webrender&&cocoaWidget,8-8,37-37) skip-if(!asyncPan) == transformed-2.html transformed-2-ref.html
skip-if(!asyncPan) fuzzy-if(Android,0-10,0-4) fuzzy-if(webrender&&gtkWidget,57-57,24-24) fuzzy-if(webrender&&cocoaWidget,16-16,40-40) == nested-sticky-1.html nested-sticky-1-ref.html
skip-if(!asyncPan) fuzzy-if(Android,0-10,0-4) fuzzy-if(/^Windows\x20NT\x206\.1/.test(http.oscpu),0-4,0-104) fuzzy-if(webrender&&gtkWidget,57-57,24-24) fuzzy-if(webrender&&cocoaWidget,16-16,40-40) == nested-sticky-2.html nested-sticky-2-ref.html
skip-if(!asyncPan) fuzzy-if(Android,0-10,0-4) fuzzy-if(webrender&&gtkWidget,56-56,24-24) fuzzy-if(webrender&&cocoaWidget,16-16,40-40) == nested-sticky-1.html nested-sticky-1-ref.html
skip-if(!asyncPan) fuzzy-if(Android,0-10,0-4) fuzzy-if(/^Windows\x20NT\x206\.1/.test(http.oscpu),0-4,0-104) fuzzy-if(webrender&&gtkWidget,56-56,24-24) fuzzy-if(webrender&&cocoaWidget,16-16,40-40) == nested-sticky-2.html nested-sticky-2-ref.html