Backed out 6 changesets (bug 1754336, bug 1754131, bug 1754809, bug 1749380, bug 1754350, bug 1754160) as requested by gwatson CLOSED TREE

Backed out changeset 6ad4a655b768 (bug 1754809)
Backed out changeset c60f4861cfa5 (bug 1754350)
Backed out changeset e3acddf74704 (bug 1754336)
Backed out changeset 49db3f1cc79a (bug 1754160)
Backed out changeset 346a4ffcb536 (bug 1754131)
Backed out changeset b7f88e5c537b (bug 1749380)
This commit is contained in:
Cristian Tuns 2022-02-14 23:25:33 -05:00
parent a7a6e060cf
commit 10c82ef861
55 changed files with 1500 additions and 1068 deletions

View File

@ -20,7 +20,7 @@ fails-if(useDrawSnapshot) == 1501195.html 1501195-ref.html
== 1519754.html 1519754-ref.html
skip-if(!asyncPan) == 1524261.html 1524261-ref.html
fuzzy-if(!useDrawSnapshot,14-14,44-95) == 1524353.html 1524353-ref.html
== 1523776.html 1523776-ref.html
fuzzy-if(!useDrawSnapshot,2-7,17500-36908) == 1523776.html 1523776-ref.html
== bug1523410-translate-scale-snap.html bug1523410-translate-scale-snap-ref.html
== 1523080.html 1523080-ref.html
== 1616444-same-color-different-paths.html 1616444-same-color-different-paths-ref.html

View File

@ -953,14 +953,8 @@ impl BatchBuilder {
render_tasks,
).unwrap();
let prim_rect = ctx.data_stores.get_local_prim_rect(
child_prim_instance,
&ctx.prim_store.pictures,
ctx.surfaces,
);
let prim_header = PrimitiveHeader {
local_rect: prim_rect,
local_rect: pic.precise_local_rect,
local_clip_rect: child_prim_info.combined_local_clip_rect,
specific_prim_address: GpuCacheAddress::INVALID,
transform_id: transforms
@ -971,6 +965,11 @@ impl BatchBuilder {
),
};
let raster_config = pic
.raster_config
.as_ref()
.expect("BUG: 3d primitive was not assigned a surface");
let child_pic_task_id = pic
.primary_render_task_id
.unwrap();
@ -990,7 +989,7 @@ impl BatchBuilder {
let prim_header_index = prim_headers.push(&prim_header, z_id, [
uv_rect_address.as_int(),
BrushFlags::PERSPECTIVE_INTERPOLATION.bits() as i32,
if raster_config.establishes_raster_root { 1 } else { 0 },
0,
child_clip_task_address.0 as i32,
]);
@ -1073,8 +1072,7 @@ impl BatchBuilder {
let prim_rect = ctx.data_stores.get_local_prim_rect(
prim_instance,
&ctx.prim_store.pictures,
ctx.surfaces,
ctx.prim_store,
);
let mut batch_features = BatchFeatures::empty();
@ -1542,7 +1540,7 @@ impl BatchBuilder {
let prim_cache_address = gpu_cache.get_address(&ctx.globals.default_image_handle);
let prim_header = PrimitiveHeader {
local_rect: prim_rect,
local_rect: picture.precise_local_rect,
local_clip_rect: prim_info.combined_local_clip_rect,
specific_prim_address: prim_cache_address,
transform_id,
@ -1564,12 +1562,16 @@ impl BatchBuilder {
Some(ref raster_config) => {
// If the child picture was rendered in local space, we can safely
// interpolate the UV coordinates with perspective correction.
let brush_flags = BrushFlags::PERSPECTIVE_INTERPOLATION;
let brush_flags = if raster_config.establishes_raster_root {
BrushFlags::PERSPECTIVE_INTERPOLATION
} else {
BrushFlags::empty()
};
let surface = &ctx.surfaces[raster_config.surface_index.0];
let mut is_opaque = prim_info.clip_task_index == ClipTaskIndex::INVALID
&& surface.is_opaque
&& surface.opaque_rect.contains_box(&surface.rect)
&& transform_kind == TransformedRectKind::AxisAligned;
let pic_task_id = picture.primary_render_task_id.unwrap();
@ -1584,7 +1586,7 @@ impl BatchBuilder {
PictureCompositeMode::Filter(ref filter) => {
assert!(filter.is_visible());
match filter {
Filter::Blur { .. } => {
Filter::Blur(..) => {
let (clip_task_address, clip_mask_texture_id) = ctx.get_prim_clip_task_and_texture(
prim_info.clip_task_index,
render_tasks,
@ -1823,7 +1825,7 @@ impl BatchBuilder {
// These filters are handled via different paths.
Filter::ComponentTransfer |
Filter::Blur { .. } |
Filter::Blur(..) |
Filter::DropShadows(..) |
Filter::Opacity(..) => unreachable!(),
};
@ -2110,7 +2112,7 @@ impl BatchBuilder {
};
let prim_header = PrimitiveHeader {
local_rect: prim_rect,
local_rect: picture.precise_local_rect,
local_clip_rect: prim_info.combined_local_clip_rect,
specific_prim_address: prim_cache_address,
transform_id,
@ -3041,8 +3043,9 @@ impl BatchBuilder {
);
let prim_cache_address = gpu_cache.get_address(&ctx.globals.default_image_handle);
let backdrop_picture = &ctx.prim_store.pictures[backdrop_pic_index.0];
let prim_header = PrimitiveHeader {
local_rect: prim_rect,
local_rect: backdrop_picture.precise_local_rect,
local_clip_rect: prim_info.combined_local_clip_rect,
transform_id,
specific_prim_address: prim_cache_address,

View File

@ -32,7 +32,7 @@ use crate::space::SpaceMapper;
use crate::segment::SegmentBuilder;
use std::{f32, mem};
use crate::util::{VecHelper, Preallocator};
use crate::visibility::{update_prim_visibility, FrameVisibilityState, FrameVisibilityContext};
use crate::visibility::{update_primitive_visibility, FrameVisibilityState, FrameVisibilityContext};
use plane_split::Splitter;
@ -125,7 +125,7 @@ impl FrameGlobalResources {
pub struct FrameScratchBuffer {
dirty_region_stack: Vec<DirtyRegion>,
surface_stack: Vec<(PictureIndex, SurfaceIndex)>,
surface_stack: Vec<SurfaceIndex>,
clip_chain_stack: ClipChainStack,
}
@ -204,13 +204,12 @@ impl<'a> FrameBuildingState<'a> {
&mut self,
surface_index: SurfaceIndex,
tasks: Vec<RenderTaskId>,
clipping_rect: PictureRect,
raster_rect: DeviceRect,
) {
let surface = &mut self.surfaces[surface_index.0];
assert!(surface.render_tasks.is_none());
surface.render_tasks = Some(SurfaceRenderTasks::Tiled(tasks));
// TODO(gw): Include the dirty rect here, to reduce child surface sizes
surface.clipping_rect = clipping_rect;
surface.raster_rect = Some(raster_rect);
}
/// Initialize render tasks for a simple surface, that contains only a
@ -220,12 +219,12 @@ impl<'a> FrameBuildingState<'a> {
surface_index: SurfaceIndex,
task_id: RenderTaskId,
parent_surface_index: SurfaceIndex,
clipping_rect: PictureRect,
raster_rect: DeviceRect,
) {
let surface = &mut self.surfaces[surface_index.0];
assert!(surface.render_tasks.is_none());
surface.render_tasks = Some(SurfaceRenderTasks::Simple(task_id));
surface.clipping_rect = clipping_rect;
surface.raster_rect = Some(raster_rect);
self.add_child_render_task(
parent_surface_index,
@ -242,12 +241,12 @@ impl<'a> FrameBuildingState<'a> {
root_task_id: RenderTaskId,
port_task_id: RenderTaskId,
parent_surface_index: SurfaceIndex,
clipping_rect: PictureRect,
raster_rect: DeviceRect,
) {
let surface = &mut self.surfaces[surface_index.0];
assert!(surface.render_tasks.is_none());
surface.render_tasks = Some(SurfaceRenderTasks::Chained { root_task_id, port_task_id });
surface.clipping_rect = clipping_rect;
surface.raster_rect = Some(raster_rect);
self.add_child_render_task(
parent_surface_index,
@ -376,6 +375,7 @@ impl FrameBuilder {
global_device_pixel_scale,
spatial_tree,
global_screen_world_rect,
surfaces: &mut scene.surfaces,
debug_flags,
scene_properties,
config: scene.config,
@ -405,9 +405,8 @@ impl FrameBuilder {
// If we have a tile cache for this picture, see if any of the
// relative transforms have changed, which means we need to
// re-map the dependencies of any child primitives.
let surface = &scene.surfaces[surface_index.0];
let world_culling_rect = tile_cache.pre_update(
surface.local_rect,
layout_rect_as_picture_rect(&pic.estimated_local_rect),
surface_index,
&visibility_context,
&mut visibility_state,
@ -416,23 +415,21 @@ impl FrameBuilder {
// Push a new surface, supplying the list of clips that should be
// ignored, since they are handled by clipping when drawing this surface.
visibility_state.push_surface(
*pic_index,
surface_index,
&tile_cache.shared_clips,
frame_context.spatial_tree,
);
update_prim_visibility(
update_primitive_visibility(
&mut scene.prim_store,
*pic_index,
None,
&world_culling_rect,
&mut scene.prim_store,
&mut scene.prim_instances,
&mut scene.surfaces,
true,
&visibility_context,
&mut visibility_state,
tile_cache,
true,
&mut scene.prim_instances,
);
// Build the dirty region(s) for this tile cache.

View File

@ -208,11 +208,7 @@ const OPACITY_EPSILON: f32 = 0.001;
#[cfg_attr(feature = "replay", derive(Deserialize))]
pub enum Filter {
Identity,
Blur {
width: f32,
height: f32,
should_inflate: bool,
},
Blur(f32, f32),
Brightness(f32),
Contrast(f32),
Grayscale(f32),
@ -233,7 +229,7 @@ impl Filter {
pub fn is_visible(&self) -> bool {
match *self {
Filter::Identity |
Filter::Blur { .. } |
Filter::Blur(..) |
Filter::Brightness(..) |
Filter::Contrast(..) |
Filter::Grayscale(..) |
@ -258,7 +254,7 @@ impl Filter {
pub fn is_noop(&self) -> bool {
match *self {
Filter::Identity => false, // this is intentional
Filter::Blur { width, height, .. } => width == 0.0 && height == 0.0,
Filter::Blur(width, height) => width == 0.0 && height == 0.0,
Filter::Brightness(amount) => amount == 1.0,
Filter::Contrast(amount) => amount == 1.0,
Filter::Grayscale(amount) => amount == 0.0,
@ -310,7 +306,7 @@ impl Filter {
Filter::LinearToSrgb => 9,
Filter::Flood(..) => 10,
Filter::ComponentTransfer => 11,
Filter::Blur { .. } => 12,
Filter::Blur(..) => 12,
Filter::DropShadows(..) => 13,
Filter::Opacity(..) => 14,
}
@ -321,7 +317,7 @@ impl From<FilterOp> for Filter {
fn from(op: FilterOp) -> Self {
match op {
FilterOp::Identity => Filter::Identity,
FilterOp::Blur(width, height) => Filter::Blur { width, height, should_inflate: true },
FilterOp::Blur(w, h) => Filter::Blur(w, h),
FilterOp::Brightness(b) => Filter::Brightness(b),
FilterOp::Contrast(c) => Filter::Contrast(c),
FilterOp::Grayscale(g) => Filter::Grayscale(g),

File diff suppressed because it is too large Load Diff

View File

@ -106,18 +106,12 @@ impl PictureGraph {
let info = &mut self.pic_info[pic_index.0];
match pictures[pic_index.0].assign_surface(
info.surface_index = Some(pictures[pic_index.0].assign_surface(
frame_context,
tile_caches,
parent_surface_index,
surfaces,
) {
Some(surface_index) => {
info.surface_index = Some(surface_index);
}
None => {
info.surface_index = Some(parent_surface_index.unwrap());
}
}
));
}
}
}

View File

@ -64,6 +64,8 @@ pub fn prepare_primitives(
frame_context.spatial_tree,
);
frame_state.surfaces[pic_context.surface_index.0].opaque_rect = PictureRect::zero();
for prim_instance_index in cluster.prim_range() {
// First check for coarse visibility (if this primitive was completely off-screen)
let prim_instance = &mut prim_instances[prim_instance_index];
@ -125,6 +127,14 @@ pub fn prepare_primitives(
prim_instances[prim_instance_index].clear_visibility();
}
}
if !cluster.opaque_rect.is_empty() {
let surface = &mut frame_state.surfaces[pic_context.surface_index.0];
if let Some(cluster_opaque_rect) = surface.map_local_to_surface.map_inner_bounds(&cluster.opaque_rect) {
surface.opaque_rect = crate::util::conservative_union_rect(&surface.opaque_rect, &cluster_opaque_rect);
}
}
}
}
@ -149,14 +159,9 @@ fn prepare_prim_for_render(
// For example, scrolling may affect the location of an item in
// local space, which may force us to render this item on a larger
// picture target, if being composited.
let mut is_passthrough = false;
if let PrimitiveInstanceKind::Picture { pic_index, .. } = prim_instances[prim_instance_index].kind {
let pic = &mut store.pictures[pic_index.0];
// TODO(gw): Plan to remove pictures with no composite mode, so that we don't need
// to special case for pass through pictures.
is_passthrough = pic.composite_mode.is_none();
match pic.take_context(
pic_index,
pic_context.surface_spatial_node_index,
@ -198,35 +203,32 @@ fn prepare_prim_for_render(
let prim_instance = &mut prim_instances[prim_instance_index];
if !is_passthrough {
let prim_rect = data_stores.get_local_prim_rect(
prim_instance,
&store.pictures,
frame_state.surfaces,
);
if !update_clip_task(
prim_instance,
&prim_rect.min,
cluster.spatial_node_index,
pic_context.raster_spatial_node_index,
pic_context,
pic_state,
frame_context,
frame_state,
store,
data_stores,
scratch,
) {
if prim_instance.is_chased() {
info!("\tconsidered invisible");
}
return false;
}
let prim_rect = data_stores.get_local_prim_rect(
prim_instance,
store,
);
if !update_clip_task(
prim_instance,
&prim_rect.min,
cluster.spatial_node_index,
pic_context.raster_spatial_node_index,
pic_context,
pic_state,
frame_context,
frame_state,
store,
data_stores,
scratch,
) {
if prim_instance.is_chased() {
info!("\tconsidered visible and ready with local pos {:?}", prim_rect.min);
info!("\tconsidered invisible");
}
return false;
}
if prim_instance.is_chased() {
info!("\tconsidered visible and ready with local pos {:?}", prim_rect.min);
}
#[cfg(debug_assertions)]
@ -266,6 +268,7 @@ fn prepare_interned_prim_for_render(
let prim_spatial_node_index = cluster.spatial_node_index;
let is_chased = prim_instance.is_chased();
let device_pixel_scale = frame_state.surfaces[pic_context.surface_index.0].device_pixel_scale;
let mut is_opaque = false;
match &mut prim_instance.kind {
PrimitiveInstanceKind::LineDecoration { data_handle, ref mut render_task, .. } => {
@ -286,27 +289,9 @@ fn prepare_interned_prim_for_render(
// If we have a cache key, it's a wavy / dashed / dotted line. Otherwise, it's
// a simple solid line.
if let Some(cache_key) = line_dec_data.cache_key.as_ref() {
// TODO(gw): These scale factors don't do a great job if the world transform
// contains perspective
let scale = frame_context
.spatial_tree
.get_world_transform(prim_spatial_node_index)
.scale_factors();
// Scale factors are normalized to a power of 2 to reduce the number of
// resolution changes.
// For frames with a changing scale transform round scale factors up to
// nearest power-of-2 boundary so that we don't keep having to redraw
// the content as it scales up and down. Rounding up to nearest
// power-of-2 boundary ensures we never scale up, only down --- avoiding
// jaggies. It also ensures we never scale down by more than a factor of
// 2, avoiding bad downscaling quality.
let scale_width = clamp_to_scale_factor(scale.0, false);
let scale_height = clamp_to_scale_factor(scale.1, false);
// Pick the maximum dimension as scale
let world_scale = LayoutToWorldScale::new(scale_width.max(scale_height));
let scale_factor = world_scale * device_pixel_scale;
// TODO(gw): Do we ever need / want to support scales for text decorations
// based on the current transform?
let scale_factor = Scale::new(1.0) * device_pixel_scale;
let mut task_size = (LayoutSize::from_au(cache_key.size) * scale_factor).ceil().to_i32();
if task_size.width > MAX_LINE_DECORATION_RESOLUTION as i32 ||
task_size.height > MAX_LINE_DECORATION_RESOLUTION as i32 {
@ -363,7 +348,12 @@ fn prepare_interned_prim_for_render(
.into_fast_transform();
let prim_offset = prim_data.common.prim_rect.min.to_vector() - run.reference_frame_relative_offset;
let pic = &store.pictures[pic_context.pic_index.0];
let surface = &frame_state.surfaces[pic_context.surface_index.0];
let root_scaling_factor = match pic.raster_config {
Some(ref raster_config) => raster_config.root_scaling_factor,
None => 1.0
};
// If subpixel AA is disabled due to the backing surface the glyphs
// are being drawn onto, disable it (unless we are using the
@ -401,6 +391,7 @@ fn prepare_interned_prim_for_render(
&transform.to_transform().with_destination::<_>(),
surface,
prim_spatial_node_index,
root_scaling_factor,
allow_subpixel,
frame_context.fb_config.low_quality_pinch_zoom,
frame_state.resource_cache,
@ -553,6 +544,8 @@ fn prepare_interned_prim_for_render(
frame_context.scene_properties,
);
is_opaque = prim_data.common.opacity.is_opaque;
write_segment(
*segment_instance_index,
frame_state,
@ -571,6 +564,7 @@ fn prepare_interned_prim_for_render(
let prim_data = &mut data_stores.yuv_image[*data_handle];
let common_data = &mut prim_data.common;
let yuv_image_data = &mut prim_data.kind;
is_opaque = true;
common_data.may_need_repetition = false;
@ -608,6 +602,9 @@ fn prepare_interned_prim_for_render(
&mut prim_instance.vis,
);
// common_data.opacity.is_opaque is computed in the above update call.
is_opaque = common_data.opacity.is_opaque;
write_segment(
image_instance.segment_instance_index,
frame_state,
@ -780,15 +777,12 @@ fn prepare_interned_prim_for_render(
if let Picture3DContext::In { root_data: None, plane_splitter_index, .. } = pic.context_3d {
let dirty_rect = frame_state.current_dirty_region().combined;
let splitter = &mut frame_state.plane_splitters[plane_splitter_index.0];
let surface_index = pic.raster_config.as_ref().unwrap().surface_index;
let surface = &frame_state.surfaces[surface_index.0];
let local_prim_rect = surface.local_rect.cast_unit();
PicturePrimitive::add_split_plane(
splitter,
frame_context.spatial_tree,
prim_spatial_node_index,
local_prim_rect,
pic.precise_local_rect,
&prim_instance.vis.combined_local_clip_rect,
dirty_rect,
plane_split_anchor,
@ -848,6 +842,26 @@ fn prepare_interned_prim_for_render(
}
}
};
// If the primitive is opaque, see if it can contribut to it's picture surface's opaque rect.
is_opaque = is_opaque && {
let clip = prim_instance.vis.clip_task_index;
clip == ClipTaskIndex::INVALID
};
is_opaque = is_opaque && !frame_context.spatial_tree.is_relative_transform_complex(
prim_spatial_node_index,
pic_context.raster_spatial_node_index,
);
if is_opaque {
let prim_local_rect = data_stores.get_local_prim_rect(
prim_instance,
store,
);
cluster.opaque_rect = crate::util::conservative_union_rect(&cluster.opaque_rect, &prim_local_rect);
}
}
@ -1410,8 +1424,7 @@ fn build_segments_if_needed(
// in the instance and primitive template.
let prim_local_rect = data_stores.get_local_prim_rect(
instance,
&prim_store.pictures,
frame_state.surfaces,
prim_store,
);
let segment_instance_index = match instance.kind {

View File

@ -79,7 +79,7 @@ pub enum PictureCompositeKey {
Identity,
// FilterOp
Blur(Au, Au, bool),
Blur(Au, Au),
Brightness(Au),
Contrast(Au),
Grayscale(Au),
@ -142,8 +142,8 @@ impl From<Option<PictureCompositeMode>> for PictureCompositeKey {
}
Some(PictureCompositeMode::Filter(op)) => {
match op {
Filter::Blur { width, height, should_inflate } =>
PictureCompositeKey::Blur(Au::from_f32_px(width), Au::from_f32_px(height), should_inflate),
Filter::Blur(width, height) =>
PictureCompositeKey::Blur(Au::from_f32_px(width), Au::from_f32_px(height)),
Filter::Brightness(value) => PictureCompositeKey::Brightness(Au::from_f32_px(value)),
Filter::Contrast(value) => PictureCompositeKey::Contrast(Au::from_f32_px(value)),
Filter::Grayscale(value) => PictureCompositeKey::Grayscale(Au::from_f32_px(value)),

View File

@ -246,6 +246,7 @@ impl TextRunPrimitive {
transform: &LayoutToWorldTransform,
mut allow_subpixel: bool,
raster_space: RasterSpace,
root_scaling_factor: f32,
spatial_tree: &SpatialTree,
) -> bool {
// If local raster space is specified, include that in the scale
@ -256,7 +257,10 @@ impl TextRunPrimitive {
// will no longer be required.
let raster_scale = raster_space.local_scale().unwrap_or(1.0).max(0.001);
let dps = surface.device_pixel_scale.0;
// root_scaling_factor is used to scale very large pictures that establish
// a raster root back to something sane, thus scale the device size accordingly.
// to the shader it looks like a change in DPI which it already supports.
let dps = surface.device_pixel_scale.0 * root_scaling_factor;
let font_size = specified_font.size.to_f32_px();
// Small floating point error can accumulate in the raster * device_pixel scale.
@ -438,6 +442,7 @@ impl TextRunPrimitive {
transform: &LayoutToWorldTransform,
surface: &SurfaceInfo,
spatial_node_index: SpatialNodeIndex,
root_scaling_factor: f32,
allow_subpixel: bool,
low_quality_pinch_zoom: bool,
resource_cache: &mut ResourceCache,
@ -459,13 +464,14 @@ impl TextRunPrimitive {
transform,
allow_subpixel,
raster_space,
root_scaling_factor,
spatial_tree,
);
if self.glyph_keys_range.is_empty() || cache_dirty {
let subpx_dir = self.used_font.get_subpx_dir();
let dps = surface.device_pixel_scale.0;
let dps = surface.device_pixel_scale.0 * root_scaling_factor;
let transform = match raster_space {
RasterSpace::Local(scale) => FontTransform::new(scale * dps, 0.0, 0.0, scale * dps),
RasterSpace::Screen => self.used_font.transform.scale(dps),

View File

@ -31,13 +31,12 @@ use crate::gpu_cache::GpuCache;
use crate::hit_test::{HitTest, HitTester, SharedHitTester};
use crate::intern::DataStore;
#[cfg(any(feature = "capture", feature = "replay"))]
use crate::internal_types::{DebugOutput};
use crate::internal_types::DebugOutput;
use crate::internal_types::{FastHashMap, RenderedDocument, ResultMsg, FrameId, FrameStamp};
use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
use crate::picture::{PictureScratchBuffer, SliceId, TileCacheInstance, TileCacheParams, SurfaceInfo, RasterConfig};
use crate::picture::{PicturePrimitive};
use crate::picture::{PictureScratchBuffer, SliceId, TileCacheInstance, TileCacheParams};
use crate::prim_store::{PrimitiveScratchBuffer, PrimitiveInstance};
use crate::prim_store::{PrimitiveInstanceKind, PrimTemplateCommonData};
use crate::prim_store::{PrimitiveInstanceKind, PrimTemplateCommonData, PrimitiveStore};
use crate::prim_store::interned::*;
use crate::profiler::{self, TransactionProfile};
use crate::render_task_graph::RenderTaskGraphBuilder;
@ -136,53 +135,12 @@ impl DataStores {
pub fn get_local_prim_rect(
&self,
prim_instance: &PrimitiveInstance,
pictures: &[PicturePrimitive],
surfaces: &[SurfaceInfo],
prim_store: &PrimitiveStore,
) -> LayoutRect {
match prim_instance.kind {
PrimitiveInstanceKind::Picture { pic_index, .. } => {
let pic = &pictures[pic_index.0];
match pic.raster_config {
Some(RasterConfig { surface_index, ref composite_mode, .. }) => {
let surface = &surfaces[surface_index.0];
composite_mode.get_rect(surface, None)
}
None => {
panic!("bug: get_local_prim_rect should not be called for pass-through pictures");
}
}
}
_ => {
self.as_common_data(prim_instance).prim_rect
}
}
}
/// Returns the local coverage (space occupied) for a primitive. For most primitives,
/// this is stored in the template. For pictures, this is stored inside the picture
/// primitive instance itself, since this is determined during frame building.
pub fn get_local_prim_coverage_rect(
&self,
prim_instance: &PrimitiveInstance,
pictures: &[PicturePrimitive],
surfaces: &[SurfaceInfo],
) -> LayoutRect {
match prim_instance.kind {
PrimitiveInstanceKind::Picture { pic_index, .. } => {
let pic = &pictures[pic_index.0];
match pic.raster_config {
Some(RasterConfig { surface_index, ref composite_mode, .. }) => {
let surface = &surfaces[surface_index.0];
composite_mode.get_coverage(surface, None)
}
None => {
panic!("bug: get_local_prim_coverage_rect should not be called for pass-through pictures");
}
}
let pic = &prim_store.pictures[pic_index.0];
pic.precise_local_rect
}
_ => {
self.as_common_data(prim_instance).prim_rect

View File

@ -272,13 +272,16 @@ impl RenderTarget for ColorRenderTarget {
RenderTaskKind::Picture(ref pic_task) => {
let pic = &ctx.prim_store.pictures[pic_task.pic_index.0];
let raster_spatial_node_index = pic.raster_config
.as_ref()
.map(|raster_config| {
let raster_spatial_node_index = match pic.raster_config {
Some(ref raster_config) => {
let surface = &ctx.surfaces[raster_config.surface_index.0];
surface.raster_spatial_node_index
})
.expect("bug: pass-through pic found on render task");
}
None => {
// This must be the main framebuffer
ctx.root_spatial_node_index
}
};
let target_rect = task.get_target_rect();

View File

@ -56,7 +56,7 @@ use crate::glyph_rasterizer::FontInstance;
use crate::hit_test::HitTestingScene;
use crate::intern::Interner;
use crate::internal_types::{FastHashMap, LayoutPrimitiveInfo, Filter, PlaneSplitter, PlaneSplitterIndex, PipelineInstanceId};
use crate::picture::{Picture3DContext, PictureCompositeMode, PicturePrimitive};
use crate::picture::{Picture3DContext, PictureCompositeMode, PicturePrimitive, PictureOptions};
use crate::picture::{BlitReason, OrderedPictureChild, PrimitiveList, SurfaceInfo};
use crate::picture_graph::PictureGraph;
use crate::prim_store::{PrimitiveInstance, register_prim_chase_id};
@ -268,6 +268,7 @@ impl PictureChainBuilder {
self,
composite_mode: PictureCompositeMode,
context_3d: Picture3DContext<OrderedPictureChild>,
options: PictureOptions,
interners: &mut Interners,
prim_store: &mut PrimitiveStore,
prim_instances: &mut Vec<PrimitiveInstance>,
@ -300,6 +301,7 @@ impl PictureChainBuilder {
self.flags,
prim_list,
self.spatial_node_index,
options,
))
);
@ -344,6 +346,7 @@ impl PictureChainBuilder {
self.flags,
prim_list,
self.spatial_node_index,
PictureOptions::default(),
))
);
@ -2159,6 +2162,7 @@ impl<'a> SceneBuilder<'a> {
stacking_context.prim_flags,
stacking_context.prim_list,
stacking_context.spatial_node_index,
PictureOptions::default(),
))
);
@ -2197,6 +2201,7 @@ impl<'a> SceneBuilder<'a> {
stacking_context.prim_flags,
stacking_context.prim_list,
stacking_context.spatial_node_index,
PictureOptions::default(),
))
);
@ -2295,6 +2300,7 @@ impl<'a> SceneBuilder<'a> {
stacking_context.prim_flags,
prim_list,
stacking_context.spatial_node_index,
PictureOptions::default(),
))
);
@ -2319,6 +2325,7 @@ impl<'a> SceneBuilder<'a> {
stacking_context.composite_ops.filters,
stacking_context.composite_ops.filter_primitives,
stacking_context.composite_ops.filter_datas,
true,
);
// Same for mix-blend-mode, except we can skip if this primitive is the first in the parent
@ -2344,6 +2351,7 @@ impl<'a> SceneBuilder<'a> {
source = source.add_picture(
composite_mode,
Picture3DContext::Out,
PictureOptions::default(),
&mut self.interners,
&mut self.prim_store,
&mut self.prim_instances,
@ -2700,11 +2708,7 @@ impl<'a> SceneBuilder<'a> {
// Add any primitives that come after this shadow in the item
// list to this shadow.
let mut prim_list = PrimitiveList::empty();
let blur_filter = Filter::Blur {
width: std_deviation,
height: std_deviation,
should_inflate: pending_shadow.should_inflate,
};
let blur_filter = Filter::Blur(std_deviation, std_deviation);
let blur_is_noop = blur_filter.is_noop();
for item in &items {
@ -2774,10 +2778,17 @@ impl<'a> SceneBuilder<'a> {
// blur radius is 0, the code in Picture::prepare_for_render will
// detect this and mark the picture to be drawn directly into the
// parent picture, which avoids an intermediate surface and blur.
let blur_filter = Filter::Blur(std_deviation, std_deviation);
assert!(!blur_filter.is_noop());
let composite_mode = Some(PictureCompositeMode::Filter(blur_filter));
let composite_mode_key = composite_mode.clone().into();
// Pass through configuration information about whether WR should
// do the bounding rect inflation for text shadows.
let options = PictureOptions {
inflate_if_required: pending_shadow.should_inflate,
};
// Create the primitive to draw the shadow picture into the scene.
let shadow_pic_index = PictureIndex(self.prim_store.pictures
.alloc()
@ -2788,6 +2799,7 @@ impl<'a> SceneBuilder<'a> {
PrimitiveFlags::IS_BACKFACE_VISIBLE,
prim_list,
pending_shadow.spatial_node_index,
options,
))
);
@ -3483,6 +3495,9 @@ impl<'a> SceneBuilder<'a> {
prim_flags,
prim_list,
backdrop_spatial_node_index,
PictureOptions {
inflate_if_required: false,
},
))
);
@ -3505,6 +3520,7 @@ impl<'a> SceneBuilder<'a> {
filters,
filter_primitives,
filter_datas,
false,
);
// Apply filters from all stacking contexts up to, but not including the backdrop root.
@ -3523,6 +3539,7 @@ impl<'a> SceneBuilder<'a> {
filters,
filter_primitives,
filter_datas,
false,
);
}
@ -3603,6 +3620,7 @@ impl<'a> SceneBuilder<'a> {
mut filter_ops: Vec<Filter>,
mut filter_primitives: Vec<FilterPrimitive>,
filter_datas: Vec<FilterData>,
inflate_if_required: bool,
) -> PictureChainBuilder {
// TODO(cbrewster): Currently CSS and SVG filters live side by side in WebRender, but unexpected results will
// happen if they are used simulataneously. Gecko only provides either filter ops or filter primitives.
@ -3654,6 +3672,7 @@ impl<'a> SceneBuilder<'a> {
source = source.add_picture(
composite_mode,
Picture3DContext::Out,
PictureOptions { inflate_if_required },
&mut self.interners,
&mut self.prim_store,
&mut self.prim_instances,
@ -3690,6 +3709,7 @@ impl<'a> SceneBuilder<'a> {
source = source.add_picture(
composite_mode,
Picture3DContext::Out,
PictureOptions { inflate_if_required },
&mut self.interners,
&mut self.prim_store,
&mut self.prim_instances,
@ -3852,6 +3872,7 @@ impl FlattenedStackingContext {
self.prim_flags,
mem::replace(&mut self.prim_list, PrimitiveList::empty()),
self.spatial_node_index,
PictureOptions::default(),
))
);

View File

@ -1012,17 +1012,19 @@ impl SpatialTree {
CoordinateSpaceMapping::Transform(transform)
}
/// Returns true if both supplied spatial nodes are in the same coordinate system
/// (implies the relative transform produce axis-aligned rects).
pub fn is_matching_coord_system(
pub fn is_relative_transform_complex(
&self,
index0: SpatialNodeIndex,
index1: SpatialNodeIndex,
child_index: SpatialNodeIndex,
parent_index: SpatialNodeIndex,
) -> bool {
let node0 = self.get_spatial_node(index0);
let node1 = self.get_spatial_node(index1);
if child_index == parent_index {
return false;
}
node0.coordinate_system_id == node1.coordinate_system_id
let child = self.get_spatial_node(child_index);
let parent = self.get_spatial_node(parent_index);
child.coordinate_system_id != parent.coordinate_system_id
}
fn get_world_transform_impl(

View File

@ -7,7 +7,7 @@ use api::units::*;
use crate::clip::{ClipChainId, ClipNodeKind, ClipStore, ClipInstance};
use crate::frame_builder::FrameBuilderConfig;
use crate::internal_types::{FastHashMap, FastHashSet};
use crate::picture::{PrimitiveList, PictureCompositeMode, PicturePrimitive, SliceId};
use crate::picture::{PrimitiveList, PictureCompositeMode, PictureOptions, PicturePrimitive, SliceId};
use crate::picture::{Picture3DContext, TileCacheParams, TileOffset};
use crate::prim_store::{PrimitiveInstance, PrimitiveStore, PictureIndex};
use crate::scene_building::SliceFlags;
@ -629,6 +629,7 @@ fn create_tile_cache(
PrimitiveFlags::IS_BACKFACE_VISIBLE,
prim_list,
scroll_root,
PictureOptions::default(),
));
PictureIndex(pic_index)

View File

@ -4,7 +4,7 @@
use api::BorderRadius;
use api::units::*;
use euclid::{Point2D, Rect, Box2D, Size2D, Vector2D};
use euclid::{Point2D, Rect, Box2D, Size2D, Vector2D, point2};
use euclid::{default, Transform2D, Transform3D, Scale};
use malloc_size_of::{MallocShallowSizeOf, MallocSizeOf, MallocSizeOfOps};
use plane_split::{Clipper, Polygon};
@ -1551,6 +1551,142 @@ macro_rules! c_str {
}
}
// Find a rectangle that is contained by the sum of r1 and r2.
pub fn conservative_union_rect<U>(r1: &Box2D<f32, U>, r2: &Box2D<f32, U>) -> Box2D<f32, U> {
// +---+---+ +--+-+--+
// | | | | | | |
// | | | | | | |
// +---+---+ +--+-+--+
if r1.min.y == r2.min.y && r1.max.y == r2.max.y {
if r2.min.x <= r1.max.x && r2.max.x >= r1.min.x {
let min_x = f32::min(r1.min.x, r2.min.x);
let max_x = f32::max(r1.max.x, r2.max.x);
return Box2D {
min: point2(min_x, r1.min.y),
max: point2(max_x, r1.max.y),
}
}
}
// +----+ +----+
// | | | |
// | | +----+
// +----+ | |
// | | +----+
// | | | |
// +----+ +----+
if r1.min.x == r2.min.x && r1.max.x == r2.max.x {
if r2.min.y <= r1.max.y && r2.max.y >= r1.min.y {
let min_y = f32::min(r1.min.y, r2.min.y);
let max_y = f32::max(r1.max.y, r2.max.y);
return Box2D {
min: point2(r1.min.x, min_y),
max: point2(r1.max.x, max_y),
}
}
}
if r1.area() >= r2.area() { *r1 } else {*r2 }
}
#[test]
fn test_conservative_union_rect() {
// Adjacent, x axis
let r = conservative_union_rect(
&LayoutRect { min: point2(1.0, 2.0), max: point2(4.0, 6.0) },
&LayoutRect { min: point2(4.0, 2.0), max: point2(9.0, 6.0) },
);
assert_eq!(r, LayoutRect { min: point2(1.0, 2.0), max: point2(9.0, 6.0) });
let r = conservative_union_rect(
&LayoutRect { min: point2(4.0, 2.0), max: point2(9.0, 6.0) },
&LayoutRect { min: point2(1.0, 2.0), max: point2(4.0, 6.0) },
);
assert_eq!(r, LayoutRect { min: point2(1.0, 2.0), max: point2(9.0, 6.0) });
// Averlapping adjacent, x axis
let r = conservative_union_rect(
&LayoutRect { min: point2(1.0, 2.0), max: point2(4.0, 6.0) },
&LayoutRect { min: point2(3.0, 2.0), max: point2(8.0, 6.0) },
);
assert_eq!(r, LayoutRect { min: point2(1.0, 2.0), max: point2(8.0, 6.0) });
let r = conservative_union_rect(
&LayoutRect { min: point2(5.0, 2.0), max: point2(8.0, 6.0) },
&LayoutRect { min: point2(1.0, 2.0), max: point2(6.0, 6.0) },
);
assert_eq!(r, LayoutRect { min: point2(1.0, 2.0), max: point2(8.0, 6.0) });
// Adjacent but not touching, x axis
let r = conservative_union_rect(
&LayoutRect { min: point2(1.0, 2.0), max: point2(4.0, 6.0) },
&LayoutRect { min: point2(6.0, 2.0), max: point2(11.0, 6.0) },
);
assert_eq!(r, LayoutRect { min: point2(6.0, 2.0), max: point2(11.0, 6.0) });
let r = conservative_union_rect(
&LayoutRect { min: point2(1.0, 2.0), max: point2(4.0, 6.0) },
&LayoutRect { min: point2(-6.0, 2.0), max: point2(-5.0, 6.0) },
);
assert_eq!(r, LayoutRect { min: point2(1.0, 2.0), max: point2(4.0, 6.0) });
// Adjacent, y axis
let r = conservative_union_rect(
&LayoutRect { min: point2(1.0, 2.0), max: point2(4.0, 6.0) },
&LayoutRect { min: point2(1.0, 6.0), max: point2(4.0, 10.0) },
);
assert_eq!(r, LayoutRect { min: point2(1.0, 2.0), max: point2(4.0, 10.0) });
let r = conservative_union_rect(
&LayoutRect { min: point2(1.0, 5.0), max: point2(4.0, 9.0) },
&LayoutRect { min: point2(1.0, 1.0), max: point2(4.0, 5.0) },
);
assert_eq!(r, LayoutRect { min: point2(1.0, 1.0), max: point2(4.0, 9.0) });
// Averlapping adjacent, y axis
let r = conservative_union_rect(
&LayoutRect { min: point2(1.0, 2.0), max: point2(4.0, 6.0) },
&LayoutRect { min: point2(1.0, 3.0), max: point2(4.0, 7.0) },
);
assert_eq!(r, LayoutRect { min: point2(1.0, 2.0), max: point2(4.0, 7.0) });
let r = conservative_union_rect(
&LayoutRect { min: point2(1.0, 4.0), max: point2(4.0, 8.0) },
&LayoutRect { min: point2(1.0, 2.0), max: point2(4.0, 6.0) },
);
assert_eq!(r, LayoutRect { min: point2(1.0, 2.0), max: point2(4.0, 8.0) });
// Adjacent but not touching, y axis
let r = conservative_union_rect(
&LayoutRect { min: point2(1.0, 2.0), max: point2(4.0, 6.0) },
&LayoutRect { min: point2(1.0, 10.0), max: point2(4.0, 15.0) },
);
assert_eq!(r, LayoutRect { min: point2(1.0, 10.0), max: point2(4.0, 15.0) });
let r = conservative_union_rect(
&LayoutRect { min: point2(1.0, 5.0), max: point2(4.0, 9.0) },
&LayoutRect { min: point2(1.0, 0.0), max: point2(4.0, 3.0) },
);
assert_eq!(r, LayoutRect { min: point2(1.0, 5.0), max: point2(4.0, 9.0) });
// Contained
let r = conservative_union_rect(
&LayoutRect { min: point2(1.0, 2.0), max: point2(4.0, 6.0) },
&LayoutRect { min: point2(0.0, 1.0), max: point2(10.0, 12.0) },
);
assert_eq!(r, LayoutRect { min: point2(0.0, 1.0), max: point2(10.0, 12.0) });
let r = conservative_union_rect(
&LayoutRect { min: point2(0.0, 1.0), max: point2(10.0, 12.0) },
&LayoutRect { min: point2(1.0, 2.0), max: point2(4.0, 6.0) },
);
assert_eq!(r, LayoutRect { min: point2(0.0, 1.0), max: point2(10.0, 12.0) });
}
/// This is inspired by the `weak-table` crate.
/// It holds a Vec of weak pointers that are garbage collected as the Vec
pub struct WeakTable {

View File

@ -7,30 +7,34 @@
//! TODO: document what this pass does!
//!
use api::{DebugFlags};
use api::{ColorF, DebugFlags};
use api::units::*;
use std::{usize};
use euclid::Scale;
use std::{usize, mem};
use crate::batch::BatchFilter;
use crate::clip::{ClipStore, ClipChainStack};
use crate::composite::CompositeState;
use crate::spatial_tree::{SpatialTree, SpatialNodeIndex};
use crate::clip::{ClipInstance, ClipChainInstance};
use crate::debug_colors;
use crate::frame_builder::FrameBuilderConfig;
use crate::gpu_cache::GpuCache;
use crate::picture::{PictureCompositeMode, ClusterFlags, SurfaceInfo, TileCacheInstance};
use crate::picture::{SurfaceIndex, RasterConfig};
use crate::picture::{PrimitiveList, SurfaceIndex, RasterConfig};
use crate::prim_store::{ClipTaskIndex, PictureIndex, PrimitiveInstanceKind};
use crate::prim_store::{PrimitiveStore, PrimitiveInstance};
use crate::render_backend::{DataStores, ScratchBuffer};
use crate::resource_cache::ResourceCache;
use crate::scene::SceneProperties;
use crate::space::SpaceMapper;
use crate::internal_types::Filter;
use crate::util::{MaxRect};
pub struct FrameVisibilityContext<'a> {
pub spatial_tree: &'a SpatialTree,
pub global_screen_world_rect: WorldRect,
pub global_device_pixel_scale: DevicePixelScale,
pub surfaces: &'a [SurfaceInfo],
pub debug_flags: DebugFlags,
pub scene_properties: &'a SceneProperties,
pub config: FrameBuilderConfig,
@ -47,18 +51,17 @@ pub struct FrameVisibilityState<'a> {
pub composite_state: &'a mut CompositeState,
/// A stack of currently active off-screen surfaces during the
/// visibility frame traversal.
pub surface_stack: Vec<(PictureIndex, SurfaceIndex)>,
pub surface_stack: Vec<SurfaceIndex>,
}
impl<'a> FrameVisibilityState<'a> {
pub fn push_surface(
&mut self,
pic_index: PictureIndex,
surface_index: SurfaceIndex,
shared_clips: &[ClipInstance],
spatial_tree: &SpatialTree,
) {
self.surface_stack.push((pic_index, surface_index));
self.surface_stack.push(surface_index);
self.clip_chain_stack.push_surface(
shared_clips,
spatial_tree,
@ -161,52 +164,59 @@ impl PrimitiveVisibility {
}
}
pub fn update_prim_visibility(
/// Update visibility pass - update each primitive visibility struct, and
/// build the clip chain instance if appropriate.
pub fn update_primitive_visibility(
store: &mut PrimitiveStore,
pic_index: PictureIndex,
parent_surface_index: Option<SurfaceIndex>,
world_culling_rect: &WorldRect,
store: &PrimitiveStore,
prim_instances: &mut [PrimitiveInstance],
surfaces: &mut [SurfaceInfo],
is_root_tile_cache: bool,
frame_context: &FrameVisibilityContext,
frame_state: &mut FrameVisibilityState,
tile_cache: &mut TileCacheInstance,
) {
let pic = &store.pictures[pic_index.0];
is_root_tile_cache: bool,
prim_instances: &mut Vec<PrimitiveInstance>,
) -> Option<PictureRect> {
profile_scope!("update_visibility");
let (mut prim_list, surface_index, apply_local_clip_rect, world_culling_rect, pop_surface) = {
let pic = &mut store.pictures[pic_index.0];
let (surface_index, pop_surface) = match pic.raster_config {
Some(RasterConfig { surface_index, composite_mode: PictureCompositeMode::TileCache { .. }, .. }) => {
(surface_index, false)
}
Some(ref raster_config) => {
frame_state.push_surface(
pic_index,
raster_config.surface_index,
&[],
frame_context.spatial_tree,
);
let prim_list = mem::replace(&mut pic.prim_list, PrimitiveList::empty());
let (surface_index, pop_surface) = match pic.raster_config {
Some(RasterConfig { surface_index, composite_mode: PictureCompositeMode::TileCache { .. }, .. }) => {
(surface_index, false)
}
Some(ref raster_config) => {
frame_state.push_surface(
raster_config.surface_index,
&[],
frame_context.spatial_tree,
);
let surface_local_rect = surfaces[raster_config.surface_index.0].local_rect.cast_unit();
// Let the picture cache know that we are pushing an off-screen
// surface, so it can treat dependencies of surface atomically.
tile_cache.push_surface(
pic.estimated_local_rect,
pic.spatial_node_index,
frame_context.spatial_tree,
);
// Let the picture cache know that we are pushing an off-screen
// surface, so it can treat dependencies of surface atomically.
tile_cache.push_surface(
surface_local_rect,
pic.spatial_node_index,
frame_context.spatial_tree,
);
(raster_config.surface_index, true)
}
None => {
(parent_surface_index.expect("bug: pass-through with no parent"), false)
}
};
(raster_config.surface_index, true)
}
None => {
(parent_surface_index.expect("bug: pass-through with no parent"), false)
}
(prim_list, surface_index, pic.apply_local_clip_rect, world_culling_rect, pop_surface)
};
let surface = &surfaces[surface_index.0 as usize];
let device_pixel_scale = surface.device_pixel_scale;
let mut map_local_to_surface = surface.map_local_to_surface.clone();
let surface = &frame_context.surfaces[surface_index.0 as usize];
let mut map_local_to_surface = surface
.map_local_to_surface
.clone();
let map_surface_to_world = SpaceMapper::new_with_target(
frame_context.root_spatial_node_index,
surface.surface_spatial_node_index,
@ -214,7 +224,9 @@ pub fn update_prim_visibility(
frame_context.spatial_tree,
);
for cluster in &pic.prim_list.clusters {
let mut surface_rect = PictureRect::zero();
for cluster in &mut prim_list.clusters {
profile_scope!("cluster");
// Each prim instance must have reset called each frame, to clear
@ -244,141 +256,325 @@ pub fn update_prim_visibility(
);
for prim_instance_index in cluster.prim_range() {
if let PrimitiveInstanceKind::Picture { pic_index, .. } = prim_instances[prim_instance_index].kind {
if !store.pictures[pic_index.0].is_visible(frame_context.spatial_tree) {
continue;
}
let (is_passthrough, prim_local_rect, prim_shadowed_rect) = match prim_instances[prim_instance_index].kind {
PrimitiveInstanceKind::Picture { pic_index, .. } => {
let (is_visible, is_passthrough) = {
let pic = &store.pictures[pic_index.0];
(pic.is_visible(frame_context.spatial_tree), pic.raster_config.is_none())
};
let is_passthrough = match store.pictures[pic_index.0].raster_config {
Some(..) => false,
None => true,
};
if !is_visible {
continue;
}
if is_passthrough {
frame_state.clip_chain_stack.push_clip(
prim_instances[prim_instance_index].clip_set.clip_chain_id,
frame_state.clip_store,
if is_passthrough {
frame_state.clip_chain_stack.push_clip(
prim_instances[prim_instance_index].clip_set.clip_chain_id,
frame_state.clip_store,
);
}
let pic_surface_rect = update_primitive_visibility(
store,
pic_index,
Some(surface_index),
world_culling_rect,
frame_context,
frame_state,
tile_cache,
false,
prim_instances,
);
if is_passthrough {
frame_state.clip_chain_stack.pop_clip();
}
let pic = &store.pictures[pic_index.0];
let mut shadow_rect = pic.precise_local_rect;
match pic.raster_config {
Some(ref rc) => match rc.composite_mode {
// If we have a drop shadow filter, we also need to include the shadow in
// our shadowed local rect for the purpose of calculating the size of the
// picture.
PictureCompositeMode::Filter(Filter::DropShadows(ref shadows)) => {
for shadow in shadows {
shadow_rect = shadow_rect.union(&pic.precise_local_rect.translate(shadow.offset));
}
}
_ => {}
}
None => {
// If the primitive does not have its own raster config, we need to
// propogate the surface rect calculation to the parent.
if let Some(ref rect) = pic_surface_rect {
surface_rect = surface_rect.union(rect);
}
}
}
(is_passthrough, pic.precise_local_rect, shadow_rect)
}
_ => {
let prim_instance = &prim_instances[prim_instance_index];
let prim_data = &frame_state.data_stores.as_common_data(&prim_instance);
update_prim_visibility(
pic_index,
Some(surface_index),
world_culling_rect,
store,
prim_instances,
surfaces,
false,
frame_context,
frame_state,
tile_cache,
);
if is_passthrough {
frame_state.clip_chain_stack.pop_clip();
// Pass through pictures are always considered visible in all dirty tiles.
prim_instances[prim_instance_index].vis.state = VisibilityState::PassThrough;
continue;
(false, prim_data.prim_rect, prim_data.prim_rect)
}
}
};
let prim_instance = &mut prim_instances[prim_instance_index];
let local_coverage_rect = frame_state.data_stores.get_local_prim_coverage_rect(
prim_instance,
&store.pictures,
surfaces,
);
// Include the clip chain for this primitive in the current stack.
frame_state.clip_chain_stack.push_clip(
prim_instance.clip_set.clip_chain_id,
frame_state.clip_store,
);
frame_state.clip_store.set_active_clips(
prim_instance.clip_set.local_clip_rect,
cluster.spatial_node_index,
map_local_to_surface.ref_spatial_node_index,
frame_state.clip_chain_stack.current_clips_array(),
&frame_context.spatial_tree,
&frame_state.data_stores.clip,
);
let clip_chain = frame_state
.clip_store
.build_clip_chain_instance(
local_coverage_rect,
&map_local_to_surface,
&map_surface_to_world,
&frame_context.spatial_tree,
frame_state.gpu_cache,
frame_state.resource_cache,
device_pixel_scale,
&world_culling_rect,
&mut frame_state.data_stores.clip,
true,
prim_instance.is_chased(),
);
// Ensure the primitive clip is popped
frame_state.clip_chain_stack.pop_clip();
prim_instance.vis.clip_chain = match clip_chain {
Some(clip_chain) => clip_chain,
None => {
if is_passthrough {
// Pass through pictures are always considered visible in all dirty tiles.
prim_instance.vis.state = VisibilityState::PassThrough;
} else {
if prim_local_rect.width() <= 0.0 || prim_local_rect.height() <= 0.0 {
if prim_instance.is_chased() {
info!("\tunable to build the clip chain, skipping");
info!("\tculled for zero local rectangle");
}
continue;
}
};
if prim_instance.is_chased() {
info!("\teffective clip chain from {:?} {}",
prim_instance.vis.clip_chain.clips_range,
if pic.apply_local_clip_rect { "(applied)" } else { "" },
// Inflate the local rect for this primitive by the inflation factor of
// the picture context and include the shadow offset. This ensures that
// even if the primitive itstore is not visible, any effects from the
// blur radius or shadow will be correctly taken into account.
let inflation_factor = surface.inflation_factor;
let local_rect = prim_shadowed_rect
.inflate(inflation_factor, inflation_factor)
.intersection(&prim_instance.clip_set.local_clip_rect);
let local_rect = match local_rect {
Some(local_rect) => local_rect,
None => {
if prim_instance.is_chased() {
info!("\tculled for being out of the local clip rectangle: {:?}",
prim_instance.clip_set.local_clip_rect);
}
continue;
}
};
// Include the clip chain for this primitive in the current stack.
frame_state.clip_chain_stack.push_clip(
prim_instance.clip_set.clip_chain_id,
frame_state.clip_store,
);
info!("\tpicture rect {:?} @{:?}",
prim_instance.vis.clip_chain.pic_coverage_rect,
prim_instance.vis.clip_chain.pic_spatial_node_index,
frame_state.clip_store.set_active_clips(
prim_instance.clip_set.local_clip_rect,
cluster.spatial_node_index,
map_local_to_surface.ref_spatial_node_index,
frame_state.clip_chain_stack.current_clips_array(),
&frame_context.spatial_tree,
&frame_state.data_stores.clip,
);
let clip_chain = frame_state
.clip_store
.build_clip_chain_instance(
local_rect,
&map_local_to_surface,
&map_surface_to_world,
&frame_context.spatial_tree,
frame_state.gpu_cache,
frame_state.resource_cache,
surface.device_pixel_scale,
&world_culling_rect,
&mut frame_state.data_stores.clip,
true,
prim_instance.is_chased(),
);
// Ensure the primitive clip is popped
frame_state.clip_chain_stack.pop_clip();
prim_instance.vis.clip_chain = match clip_chain {
Some(clip_chain) => clip_chain,
None => {
if prim_instance.is_chased() {
info!("\tunable to build the clip chain, skipping");
}
continue;
}
};
if prim_instance.is_chased() {
info!("\teffective clip chain from {:?} {}",
prim_instance.vis.clip_chain.clips_range,
if apply_local_clip_rect { "(applied)" } else { "" },
);
info!("\tpicture rect {:?} @{:?}",
prim_instance.vis.clip_chain.pic_coverage_rect,
prim_instance.vis.clip_chain.pic_spatial_node_index,
);
}
prim_instance.vis.combined_local_clip_rect = if apply_local_clip_rect {
prim_instance.vis.clip_chain.local_clip_rect
} else {
prim_instance.clip_set.local_clip_rect
};
if prim_instance.vis.combined_local_clip_rect.is_empty() {
if prim_instance.is_chased() {
info!("\tculled for zero local clip rectangle");
}
continue;
}
// Include the visible area for primitive, including any shadows, in
// the area affected by the surface.
match prim_instance.vis.combined_local_clip_rect.intersection(&local_rect) {
Some(visible_rect) => {
if let Some(rect) = map_local_to_surface.map(&visible_rect) {
surface_rect = surface_rect.union(&rect);
}
}
None => {
if prim_instance.is_chased() {
info!("\tculled for zero visible rectangle");
}
continue;
}
}
tile_cache.update_prim_dependencies(
prim_instance,
cluster.spatial_node_index,
prim_local_rect,
frame_context,
frame_state.data_stores,
frame_state.clip_store,
&store.pictures,
frame_state.resource_cache,
&store.color_bindings,
&frame_state.surface_stack,
&mut frame_state.composite_state,
&mut frame_state.gpu_cache,
is_root_tile_cache,
);
// Skip post visibility prim update if this primitive was culled above.
match prim_instance.vis.state {
VisibilityState::Unset => panic!("bug: invalid state"),
VisibilityState::Culled => continue,
VisibilityState::Coarse { .. } | VisibilityState::Detailed { .. } | VisibilityState::PassThrough => {}
}
// When the debug display is enabled, paint a colored rectangle around each
// primitive.
if frame_context.debug_flags.contains(::api::DebugFlags::PRIMITIVE_DBG) {
let debug_color = match prim_instance.kind {
PrimitiveInstanceKind::Picture { .. } => ColorF::TRANSPARENT,
PrimitiveInstanceKind::TextRun { .. } => debug_colors::RED,
PrimitiveInstanceKind::LineDecoration { .. } => debug_colors::PURPLE,
PrimitiveInstanceKind::NormalBorder { .. } |
PrimitiveInstanceKind::ImageBorder { .. } => debug_colors::ORANGE,
PrimitiveInstanceKind::Rectangle { .. } => ColorF { r: 0.8, g: 0.8, b: 0.8, a: 0.5 },
PrimitiveInstanceKind::YuvImage { .. } => debug_colors::BLUE,
PrimitiveInstanceKind::Image { .. } => debug_colors::BLUE,
PrimitiveInstanceKind::LinearGradient { .. } => debug_colors::PINK,
PrimitiveInstanceKind::CachedLinearGradient { .. } => debug_colors::PINK,
PrimitiveInstanceKind::RadialGradient { .. } => debug_colors::PINK,
PrimitiveInstanceKind::ConicGradient { .. } => debug_colors::PINK,
PrimitiveInstanceKind::Clear { .. } => debug_colors::CYAN,
PrimitiveInstanceKind::Backdrop { .. } => debug_colors::MEDIUMAQUAMARINE,
};
if debug_color.a != 0.0 {
if let Some(rect) = calculate_prim_clipped_world_rect(
&prim_instance.vis.clip_chain.pic_coverage_rect,
&world_culling_rect,
&map_surface_to_world,
) {
let debug_rect = rect * frame_context.global_device_pixel_scale;
frame_state.scratch.primitive.push_debug_rect(debug_rect, debug_color, debug_color.scale_alpha(0.5));
}
}
} else if frame_context.debug_flags.contains(::api::DebugFlags::OBSCURE_IMAGES) {
let is_image = matches!(
prim_instance.kind,
PrimitiveInstanceKind::Image { .. } | PrimitiveInstanceKind::YuvImage { .. }
);
if is_image {
// We allow "small" images, since they're generally UI elements.
if let Some(rect) = calculate_prim_clipped_world_rect(
&prim_instance.vis.clip_chain.pic_coverage_rect,
&world_culling_rect,
&map_surface_to_world,
) {
let rect = rect * frame_context.global_device_pixel_scale;
if rect.width() > 70.0 && rect.height() > 70.0 {
frame_state.scratch.primitive.push_debug_rect(rect, debug_colors::PURPLE, debug_colors::PURPLE);
}
}
}
}
if prim_instance.is_chased() {
info!("\tvisible with {:?}", prim_instance.vis.combined_local_clip_rect);
}
// TODO(gw): This should probably be an instance method on PrimitiveInstance?
update_prim_post_visibility(
store,
prim_instance,
world_culling_rect,
&map_surface_to_world,
);
}
prim_instance.vis.combined_local_clip_rect = if pic.apply_local_clip_rect {
prim_instance.vis.clip_chain.local_clip_rect
} else {
prim_instance.clip_set.local_clip_rect
};
tile_cache.update_prim_dependencies(
prim_instance,
cluster.spatial_node_index,
// It's OK to pass the local_coverage_rect here as it's only used by primitives
// (for compositor surfaces) that don't have inflation anyway.
local_coverage_rect,
frame_context,
frame_state.data_stores,
frame_state.clip_store,
&store.pictures,
frame_state.resource_cache,
&store.color_bindings,
&frame_state.surface_stack,
&mut frame_state.composite_state,
&mut frame_state.gpu_cache,
is_root_tile_cache,
surfaces,
);
}
}
// Similar to above, pop either the clip chain or root entry off the current clip stack.
if pop_surface {
frame_state.pop_surface();
}
let pic = &mut store.pictures[pic_index.0];
pic.prim_list = prim_list;
// If the local rect changed (due to transforms in child primitives) then
// invalidate the GPU cache location to re-upload the new local rect
// and stretch size. Drop shadow filters also depend on the local rect
// size for the extra GPU cache data handle.
// TODO(gw): In future, if we support specifying a flag which gets the
// stretch size from the segment rect in the shaders, we can
// remove this invalidation here completely.
if let Some(ref rc) = pic.raster_config {
// Inflate the local bounding rect if required by the filter effect.
if pic.options.inflate_if_required {
surface_rect = rc.composite_mode.inflate_picture_rect(surface_rect, surface.scale_factors);
}
// Layout space for the picture is picture space from the
// perspective of its child primitives.
pic.precise_local_rect = surface_rect * Scale::new(1.0);
// If the precise rect changed since last frame, we need to invalidate
// any segments and gpu cache handles for drop-shadows.
// TODO(gw): Requiring storage of the `prev_precise_local_rect` here
// is a total hack. It's required because `prev_precise_local_rect`
// gets written to twice (during initial vis pass and also during
// prepare pass). The proper longer term fix for this is to make
// use of the conservative picture rect for segmenting (which should
// be done during scene building).
if pic.precise_local_rect != pic.prev_precise_local_rect {
match rc.composite_mode {
PictureCompositeMode::Filter(Filter::DropShadows(..)) => {
for handle in &pic.extra_gpu_data_handles {
frame_state.gpu_cache.invalidate(handle);
}
}
_ => {}
}
// Invalidate any segments built for this picture, since the local
// rect has changed.
pic.segments_are_valid = false;
pic.prev_precise_local_rect = pic.precise_local_rect;
}
match rc.composite_mode {
PictureCompositeMode::TileCache { .. } => {}
_ => {
@ -386,6 +582,50 @@ pub fn update_prim_visibility(
tile_cache.pop_surface();
}
}
None
} else {
let parent_surface = &frame_context.surfaces[parent_surface_index.expect("bug: no parent").0 as usize];
let map_surface_to_parent_surface = SpaceMapper::new_with_target(
parent_surface.surface_spatial_node_index,
surface.surface_spatial_node_index,
PictureRect::max_rect(),
frame_context.spatial_tree,
);
map_surface_to_parent_surface.map(&surface_rect)
}
}
fn update_prim_post_visibility(
store: &mut PrimitiveStore,
prim_instance: &mut PrimitiveInstance,
world_culling_rect: &WorldRect,
map_surface_to_world: &SpaceMapper<PicturePixel, WorldPixel>,
) {
profile_scope!("update_prim_post_visibility");
match prim_instance.kind {
PrimitiveInstanceKind::Picture { pic_index, .. } => {
let pic = &mut store.pictures[pic_index.0];
// If this picture has a surface, determine the clipped bounding rect for it to
// minimize the size of the render target that is required.
if let Some(ref mut raster_config) = pic.raster_config {
raster_config.clipped_bounding_rect = map_surface_to_world
.map(&prim_instance.vis.clip_chain.pic_coverage_rect)
.and_then(|rect| {
rect.intersection(world_culling_rect)
})
.unwrap_or(WorldRect::zero());
}
}
PrimitiveInstanceKind::TextRun { .. } => {
// Text runs can't request resources early here, as we don't
// know until TileCache::post_update() whether we are drawing
// on an opaque surface.
// TODO(gw): We might be able to detect simple cases of this earlier,
// during the picture traversal. But it's probably not worth it?
}
_ => {}
}
}
@ -436,3 +676,15 @@ pub fn compute_conservative_visible_rect(
None => clip_chain.local_clip_rect,
}
}
fn calculate_prim_clipped_world_rect(
pic_clip_rect: &PictureRect,
world_culling_rect: &WorldRect,
map_surface_to_world: &SpaceMapper<PicturePixel, WorldPixel>,
) -> Option<WorldRect> {
map_surface_to_world
.map(&pic_clip_rect)
.and_then(|world_rect| {
world_rect.intersection(world_culling_rect)
})
}

View File

@ -1,14 +0,0 @@
# Ensure that we correctly calculate the UV sampling rect for the backdrop
# Similar to the mix-blend-mode-overflowing-child.html test in Gecko
---
root:
items:
- type: rect
bounds: [0, 0, 100, 100]
color: green
- type: rect
bounds: [50, 50, 100, 100]
color: green
- type: rect
bounds: [50, 50, 50, 50]
color: black

View File

@ -1,18 +0,0 @@
# Ensure that we correctly calculate the UV sampling rect for the backdrop
# Similar to the mix-blend-mode-overflowing-child.html test in Gecko
---
root:
items:
- type: stacking-context
blend-container: true
items:
- type: rect
bounds: [0, 0, 100, 100]
color: green
- type: stacking-context
bounds: [50, 50, 100, 100]
mix-blend-mode: difference
items:
- type: rect
bounds: [0, 0, 100, 100]
color: green

View File

@ -1,17 +0,0 @@
---
root:
items:
- type: stacking-context
blend-container: true
bounds: [0, 0, 100, 100]
items:
- type: rect
bounds: [0, 0, 100, 100]
color: [255, 0, 0]
- type: stacking-context
bounds: [0, 0, 100, 100]
mix-blend-mode: hue
items:
- type: rect
bounds: [0, 0, 100, 100]
color: [255, 255, 0]

View File

@ -1,22 +0,0 @@
# verify that the clipping_rect of a child surface (caused by the identity filter)
# is corrected used to select the backdrop for a mix-blend child surface
---
root:
items:
- type: stacking-context
filters: [identity]
items:
- type: stacking-context
blend-container: true
bounds: [0, 0, 100, 100]
items:
- type: rect
bounds: [0, 0, 100, 100]
color: [255, 0, 0]
- type: stacking-context
bounds: [0, 0, 100, 100]
mix-blend-mode: hue
items:
- type: rect
bounds: [0, 0, 100, 100]
color: [255, 255, 0]

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 18 KiB

View File

@ -25,5 +25,3 @@ fuzzy(2,420) == multi-mix-blend-mode.yaml multi-mix-blend-mode-ref.yaml
== mix-blend-invalid-backdrop.yaml mix-blend-invalid-backdrop-ref.yaml
platform(linux) == mix-blend-complex-transform.yaml mix-blend-complex-transform.png
== raster-roots-1.yaml raster-roots-1-ref.yaml
== child-surface.yaml child-surface-ref.yaml
== blend-overflow.yaml blend-overflow-ref.yaml

View File

@ -10,7 +10,7 @@ platform(linux,mac) == segmentation-with-other-coordinate-system-clip.yaml segme
== 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
== snapping.yaml snapping-ref.yaml
fuzzy(160,1055) == clip-and-filter-with-rotation.yaml clip-and-filter-with-rotation-ref.yaml
fuzzy(70,2400) == clip-and-filter-with-rotation.yaml clip-and-filter-with-rotation-ref.yaml
== clipped-occlusion.yaml clipped-occlusion-ref.yaml
== clip-empty-inner-rect.yaml clip-empty-inner-rect-ref.yaml
== iframe-nested-in-stacking-context.yaml iframe-nested-in-stacking-context-ref.yaml

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 77 KiB

After

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 116 KiB

After

Width:  |  Height:  |  Size: 107 KiB

View File

@ -36,7 +36,7 @@ platform(linux,mac) == filter-drop-shadow-on-viewport-edge.yaml filter-drop-shad
platform(linux,mac) == blend-clipped.yaml blend-clipped.png
platform(linux,mac) == filter-drop-shadow-clip.yaml filter-drop-shadow-clip.png
fuzzy(2,10) platform(linux,mac) == filter-drop-shadow-clip-2.yaml filter-drop-shadow-clip-2.png
fuzzy(1,58) platform(linux) == filter-drop-shadow-clip-3.yaml filter-drop-shadow-clip-3.png
fuzzy(1,26) platform(linux) == filter-drop-shadow-clip-3.yaml filter-drop-shadow-clip-3.png
fuzzy(5,100000) == filter-drop-shadow-scaled.yaml filter-drop-shadow-scaled-ref.yaml
== filter-segments.yaml filter-segments-ref.yaml
== iframe-dropshadow.yaml iframe-dropshadow-ref.yaml
@ -46,10 +46,10 @@ skip_on(android,device) == filter-mix-blend-mode.yaml filter-mix-blend-mode-ref.
!= filter-blur-huge.yaml blank.yaml
!= filter-drop-shadow-huge.yaml blank.yaml
!= filter-drop-shadow-transform-huge.yaml blank.yaml
fuzzy(4,62000) == filter-drop-shadow-blur-clamping.yaml filter-drop-shadow-blur-clamping-ref.yaml
fuzzy(3,79400) == filter-drop-shadow-blur-clamping.yaml filter-drop-shadow-blur-clamping-ref.yaml
== filter-blur-scaled.yaml filter-blur-scaled-ref.yaml
fuzzy(5,72000) == filter-blur-clamping.yaml filter-blur-clamping-ref.yaml
skip_on(android,device) skip_on(win) fuzzy(1,104) fuzzy-if(platform(swgl),4,18484) == filter-blur-scaled-xonly.yaml filter-blur-scaled-xonly.png # fails on Pixel2
== filter-blur-clamping.yaml filter-blur-clamping-ref.yaml
skip_on(android,device) fuzzy(1,104) fuzzy-if(platform(swgl),4,18484) == filter-blur-scaled-xonly.yaml filter-blur-scaled-xonly.png # fails on Pixel2
== svg-filter-component-transfer.yaml filter-component-transfer-ref.yaml
== svg-filter-flood.yaml svg-filter-flood-ref.yaml
skip_on(android,device) == svg-filter-blend.yaml svg-filter-blend-ref.yaml
@ -57,7 +57,7 @@ skip_on(android,device) == svg-filter-color-matrix.yaml filter-color-matrix-ref.
platform(linux,mac) == draw_calls(8) color_targets(8) alpha_targets(0) svg-filter-blur.yaml filter-blur.png # Extra draw call is due to render task graph workaround
platform(linux,mac) == svg-filter-drop-shadow.yaml svg-filter-drop-shadow.png
== fuzzy(1,10000) svg-srgb-to-linear.yaml srgb-to-linear-ref.yaml
platform(linux,mac) == fuzzy(6,36790) svg-filter-drop-shadow-rotate.yaml svg-filter-drop-shadow-rotate-ref.yaml
platform(linux,mac) == fuzzy(5,35250) svg-filter-drop-shadow-rotate.yaml svg-filter-drop-shadow-rotate-ref.yaml
platform(linux,mac) fuzzy(3,3550) == svg-filter-blur-transforms.yaml svg-filter-blur-transforms.png
platform(linux,mac) == svg-filter-drop-shadow-on-viewport-edge.yaml svg-filter-drop-shadow-on-viewport-edge.png
fuzzy(1,1) platform(linux,mac) == svg-filter-drop-shadow-perspective.yaml svg-filter-drop-shadow-perspective.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

View File

@ -1,13 +0,0 @@
root:
items:
- type: stacking-context
bounds: [0, 0, 1920, 1200]
transform: translate(-45, 7)
items:
- type: stacking-context
filters: [opacity(0.9)]
items:
- text: "This should be pixel aligned!"
origin: 416.543499 160.008325
size: 16

View File

@ -1,14 +0,0 @@
# Verify that a fractional transform that is attached to an off-screen
# surface is able to snap correctly
root:
items:
- type: stacking-context
bounds: [0, 0, 1920, 1200]
transform: translate(-45, 7.491675)
items:
- type: stacking-context
filters: [opacity(0.9)]
items:
- text: "This should be pixel aligned!"
origin: 416.543499 160.008325
size: 16

View File

@ -2,4 +2,3 @@ platform(linux,mac) == snap.yaml snap.png
== transform.yaml transform.png
platform(linux,mac) == preserve-3d.yaml preserve-3d.png
fuzzy(128,200) == subpixel-raster-root.yaml subpixel-raster-root-ref.yaml
platform(linux,mac) == fractional-filter.yaml fractional-filter-ref.yaml

Binary file not shown.

Before

Width:  |  Height:  |  Size: 61 KiB

After

Width:  |  Height:  |  Size: 61 KiB

View File

@ -81,5 +81,5 @@ fuzzy(1,15) platform(linux) force_subpixel_aa_where_possible(false) == text-fixe
# most pixels are off by a small amount, but a few pixels on the edge vary by a lot, pushing up the fuzzy max-diff;
# the main goal of the test is that everything is in the same place, at the same scale, clipped the same way,
# despite 4x on-the-fly scale change.
skip_on(android) fuzzy(200,29500) == raster_root_C_8192.yaml raster_root_C_ref.yaml
skip_on(android) fuzzy-range(<=3,*21700,<=20,*3500,<=119,*590) fuzzy-if(platform(swgl),108,24907) == raster_root_C_8192.yaml raster_root_C_ref.yaml
== subpx-bg-mask.yaml subpx-bg-mask-ref.yaml

Binary file not shown.

Before

Width:  |  Height:  |  Size: 93 KiB

After

Width:  |  Height:  |  Size: 93 KiB

View File

@ -3,7 +3,7 @@ root:
items:
- type: stacking-context
transform-style: preserve-3d
transform: scale(-2, 44, 1)
transform: scale(-2, 44, 44727)
items:
- type: rect
bounds: [ -100, -100, 200, 101 ]

Binary file not shown.

Before

Width:  |  Height:  |  Size: 225 KiB

After

Width:  |  Height:  |  Size: 226 KiB

View File

@ -1822,7 +1822,7 @@ pref(layout.css.caption-side-non-standard.enabled,true) == 1062963-floatmanager-
== 1069716-1.html 1069716-1-ref.html
== 1078262-1.html about:blank # bug 1656792
test-pref(layout.testing.overlay-scrollbars.always-visible,false) == 1081072-1.html 1081072-1-ref.html
fuzzy(15-40,142-845) fuzzy-if(useDrawSnapshot,33-33,218-218) == 1081185-1.html 1081185-1-ref.html
fuzzy(63-64,142-845) fuzzy-if(useDrawSnapshot,33-33,218-218) == 1081185-1.html 1081185-1-ref.html
== 1097437-1.html 1097437-1-ref.html
== 1103258-1.html 1103258-1-ref.html # assertion crash test with layers culling test
== 1105137-1.html 1105137-1-ref.html
@ -2058,7 +2058,7 @@ pref(layout.css.supports-selector.enabled,false) != 1499386.html 1499386-ref.htm
== 1513423-2.html 1513423-2-ref.html
== 1513423-3.html 1513423-3-ref.html
pref(layout.accessiblecaret.enabled,true) == 1517385.html 1517385-ref.html
fuzzy(0-5,0-2300) == 1529992-1.html 1529992-1-ref.html
fuzzy-if(winWidget&&swgl,1-1,12-16) fuzzy-if(cocoaWidget&&swgl,1-1,32-32) fuzzy-if(useDrawSnapshot,2-2,209-209) == 1529992-1.html 1529992-1-ref.html
fuzzy-if(Android,9-14,44-60) fails-if(!useDrawSnapshot) == 1529992-2.html 1529992-2-ref.html
== 1535040-1.html 1535040-1-ref.html
== 1545360-1.xhtml 1545360-1-ref.xhtml

View File

@ -16,7 +16,7 @@ random-if(d2d) fuzzy-if(!useDrawSnapshot,255-255,39-42) == element-paint-transfo
fuzzy-if(d2d&&/^Windows\x20NT\x206\.1/.test(http.oscpu),0-16,0-90) == element-paint-background-size-01.html element-paint-background-size-01-ref.html
== element-paint-background-size-02.html element-paint-background-size-02-ref.html
fuzzy(0-255,0-4) random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) == element-paint-transform-repeated.html element-paint-transform-repeated-ref.html # Bug 1475907
fuzzy-if(d2d,0-255,0-24) fuzzy-if(!useDrawSnapshot,255-255,56-115) == element-paint-transform-03.html element-paint-transform-03-ref.html
fuzzy-if(d2d,0-255,0-24) fuzzy-if(!useDrawSnapshot,255-255,56-72) == element-paint-transform-03.html element-paint-transform-03-ref.html
# For !nativeThemePref: element() uses fallback / skia in WebRender, which antialiases differently from WR.
# For !nativeThemePref+Windows+WebRender: bug 1496542, the scrollframe snaps differently.

View File

@ -2,6 +2,6 @@
# e.g. filter: blur(3px) grayscale(0.5) invert(0.2);
# Some platforms render this complex filter chain a little differently, and that's ok.
fuzzy(4-6,12000-19950) fuzzy-if(swgl,5-10,13600-20260) == long-chain.html long-chain-ref.html # Win10: Bug 1258241
fuzzy(4-6,12000-19484) fuzzy-if(swgl,5-10,13600-20088) == long-chain.html long-chain-ref.html # Win10: Bug 1258241
== moz-element.html moz-element-ref.html
fuzzy-if(!useDrawSnapshot,13-15,7670-7982) fuzzy-if(!useDrawSnapshot&&swgl,11-12,14052-14056) == same-filter.html same-filter-ref.html

View File

@ -107,7 +107,7 @@ fuzzy(0-1,0-400) == feDisplacementMap-alpha-01.svg pass.svg
fuzzy(0-2,0-500) == feDisplacementMap-colour-01.svg feDisplacementMap-colour-01-ref.svg
== feDisplacementMap-scale-01.svg pass.svg
fuzzy-if(/^Windows\x20NT\x2010\.0/.test(http.oscpu),0-2,0-25) fuzzy-if(!useDrawSnapshot,55-98,14033-16360) == feDropShadow-01.svg feDropShadow-01-ref.svg
fuzzy-if(/^Windows\x20NT\x2010\.0/.test(http.oscpu),0-2,0-25) fuzzy-if(!useDrawSnapshot,55-98,14033-16345) == feDropShadow-01.svg feDropShadow-01-ref.svg
== feFlood-color-01.svg pass.svg

View File

@ -4,13 +4,13 @@
== clip-input.svg clip-input-ref.svg
== clip-original-SourceGraphic.svg clip-original-SourceGraphic-ref.svg
== clip-output.svg clip-output-ref.svg
fuzzy(0-5,0-20300) == default-subregion.svg default-subregion-ref.svg
fuzzy(0-5,0-20155) == default-subregion.svg default-subregion-ref.svg
== different-FillPaint-filter-regions.svg different-FillPaint-filter-regions-ref.svg
== different-StrokePaint-filter-regions.svg different-StrokePaint-filter-regions-ref.svg
== dont-clip-previous-primitives.svg dont-clip-previous-primitives-ref.svg
== intersecting-filter-regions.svg intersecting-filter-regions-ref.svg
fuzzy-if(!useDrawSnapshot,9-9,5168-5536) fuzzy-if(!useDrawSnapshot&&swgl,7-7,13170-13184) == long-chain.svg simple-chain-ref.svg
fuzzy-if(!useDrawSnapshot,9-9,5168-5536) fuzzy-if(!useDrawSnapshot&&swgl,7-7,13170-13184) == multiple-primitives-per-filter.svg simple-chain-ref.svg
fuzzy-if(/^Windows\x20NT\x2010\.0/.test(http.oscpu),0-1,0-173) fuzzy-if(!useDrawSnapshot||(winWidget&&isCoverageBuild),9-9,5128-5496) fuzzy-if(!useDrawSnapshot&&swgl,7-7,12820-12830) == second-filter-uses-SourceAlpha.svg second-filter-uses-SourceAlpha-ref.svg
fuzzy-if(!useDrawSnapshot,9-9,5168-5536) fuzzy-if(!useDrawSnapshot&&swgl,7-7,13170-13180) == second-filter-uses-SourceGraphic.svg simple-chain-ref.svg
fuzzy-if(!useDrawSnapshot,9-9,5168-5536) fuzzy-if(!useDrawSnapshot&&swgl,7-7,13184-13184) == long-chain.svg simple-chain-ref.svg
fuzzy-if(!useDrawSnapshot,9-9,5168-5536) fuzzy-if(!useDrawSnapshot&&swgl,7-7,13184-13184) == multiple-primitives-per-filter.svg simple-chain-ref.svg
fuzzy-if(/^Windows\x20NT\x2010\.0/.test(http.oscpu),0-1,0-173) fuzzy-if(!useDrawSnapshot||(winWidget&&isCoverageBuild),9-9,5128-5496) fuzzy-if(!useDrawSnapshot&&swgl,7-7,12836-12836) == second-filter-uses-SourceAlpha.svg second-filter-uses-SourceAlpha-ref.svg
fuzzy-if(!useDrawSnapshot,9-9,5168-5536) fuzzy-if(!useDrawSnapshot&&swgl,7-7,13184-13184) == second-filter-uses-SourceGraphic.svg simple-chain-ref.svg
== simple-chain.svg simple-chain-ref.svg

View File

@ -3,7 +3,7 @@ random-if(Android) == chrome://reftest/content/text-shadow/basic-negcoord.xhtml
!= chrome://reftest/content/text-shadow/blur.xhtml chrome://reftest/content/text-shadow/blur-notref.xhtml
== chrome://reftest/content/text-shadow/color-inherit.xhtml chrome://reftest/content/text-shadow/color-inherit-ref.xhtml
== chrome://reftest/content/text-shadow/multiple-noblur.xhtml chrome://reftest/content/text-shadow/multiple-noblur-ref.xhtml
fuzzy(0-2,0-6400) random-if(useDrawSnapshot) == blur-opacity.html blur-opacity-ref.html
fuzzy-if(swgl&&!Android,2-2,6320-6320) random-if(useDrawSnapshot) == blur-opacity.html blur-opacity-ref.html
fuzzy-if(cocoaWidget,0-27,0-2) fuzzy-if(winWidget,0-47,0-2) == overflow-clip.html overflow-clip-ref.html

View File

@ -82,9 +82,9 @@ fuzzy(0-1,0-10000) == opacity-preserve3d-3.html opacity-preserve3d-3-ref.html
fuzzy(0-1,0-10000) == opacity-preserve3d-4.html opacity-preserve3d-4-ref.html
== opacity-preserve3d-5.html opacity-preserve3d-5-ref.html
== snap-perspective-1.html snap-perspective-1-ref.html
fuzzy(0-120,0-590) == mask-layer-1.html mask-layer-ref.html
fuzzy(0-120,0-590) == mask-layer-2.html mask-layer-ref.html
fuzzy(0-120,0-590) == mask-layer-3.html mask-layer-ref.html
fuzzy-if(Android,0-8,0-1) == mask-layer-1.html mask-layer-ref.html
fuzzy-if(Android,0-8,0-1) == mask-layer-2.html mask-layer-ref.html
fuzzy(0-16,0-132) == mask-layer-3.html mask-layer-ref.html
== split-intersect1.html split-intersect1-ref.html
fuzzy(0-255,0-150) fails-if(useDrawSnapshot) == split-intersect2.html split-intersect2-ref.html
fuzzy(0-255,0-100) fails-if(useDrawSnapshot) == split-non-ortho1.html split-non-ortho1-ref.html
@ -94,7 +94,7 @@ fuzzy-if(winWidget&&!nativeThemePref,0-4,0-51) == transform-geometry-1.html tran
== intermediate-1.html intermediate-1-ref.html
== preserves3d-nested-filter-1.html preserves3d-nested-filter-1-ref.html
!= preserve3d-scale.html about:blank
fuzzy(0-50,0-1460) == preserve3d-scale.html preserve3d-scale-ref.html
fuzzy(0-51,0-1154) == preserve3d-scale.html preserve3d-scale-ref.html
fuzzy(0-1,0-5) == perspective-overflow-1.html perspective-overflow-1-ref.html
== perspective-overflow-2.html perspective-overflow-2-ref.html
== 1544995-1.html 1544995-1-ref.html

View File

@ -159,13 +159,13 @@ test-pref(layout.css.zoom-transform-hack.enabled,true) == zoom-hack-2.html zoom-
== transform-anon-block-1.html transform-anon-block-1-ref.html
test-pref(layout.animation.prerender.partial.jank,true) test-pref(layout.animation.prerender.partial,true) == partial-prerender-expansion-translate.html partial-prerender-expansion-ref.html
test-pref(layout.animation.prerender.partial,true) == partial-prerender-translate-1.html about:blank
test-pref(layout.animation.prerender.partial.jank,true) test-pref(layout.animation.prerender.partial,true) test-pref(layout.animation.prerender.viewport-ratio-limit,"1.125") fuzzy-if(Android,0-255,0-7000) == partial-prerender-translate-2.html partial-prerender-translate-2-ref.html
test-pref(layout.animation.prerender.partial.jank,true) test-pref(layout.animation.prerender.partial,true) test-pref(layout.animation.prerender.viewport-ratio-limit,"1.125") == partial-prerender-translate-2.html partial-prerender-translate-2-ref.html
fails-if(!useDrawSnapshot) test-pref(layout.animation.prerender.partial.jank,true) test-pref(layout.animation.prerender.partial,true) test-pref(layout.animation.prerender.viewport-ratio-limit,"1.125") == partial-prerender-translate-3.html partial-prerender-translate-3-ref.html # bug 1642575
# This reftest doesn't fail on WebRender, this reftest fails only if there is a jank mechanism and the mechanism doesn't properly handle ancestor's transform values
test-pref(layout.animation.prerender.partial.jank,true) test-pref(layout.animation.prerender.partial,true) test-pref(layout.animation.prerender.viewport-ratio-limit,"1.125") == partial-prerender-translate-4.html partial-prerender-expansion-ref.html
# This reftest doesn't fail on WebRender, this reftest fails only if there is a jank mechanism and the mechanism does inproperly handle position:fixed scroll target
test-pref(layout.animation.prerender.partial.jank,true) test-pref(layout.animation.prerender.partial,true) test-pref(layout.animation.prerender.viewport-ratio-limit,"1.125") == partial-prerender-translate-5.html partial-prerender-translate-5-ref.html
random-if(useDrawSnapshot) test-pref(layout.animation.prerender.partial.jank,true) test-pref(layout.animation.prerender.partial,true) test-pref(layout.animation.prerender.viewport-ratio-limit,"1.125") fuzzy-if(Android,0-255,0-9900) == partial-prerender-translate-6.html partial-prerender-translate-6-ref.html
random-if(useDrawSnapshot) test-pref(layout.animation.prerender.partial.jank,true) test-pref(layout.animation.prerender.partial,true) test-pref(layout.animation.prerender.viewport-ratio-limit,"1.125") == partial-prerender-translate-6.html partial-prerender-translate-6-ref.html
test-pref(layout.animation.prerender.partial.jank,true) test-pref(layout.animation.prerender.partial,true) test-pref(layout.animation.prerender.viewport-ratio-limit,"1.125") == partial-prerender-translate-7.html partial-prerender-translate-2-ref.html
# This reftest doesn't fail on WebRender, this reftest fails only if there is a jank mechanism and the mechanism doesn't properly clip transform in iframes.
test-pref(layout.animation.prerender.partial.jank,true) test-pref(layout.animation.prerender.partial,true) test-pref(layout.animation.prerender.viewport-ratio-limit,"1.125") == partial-prerender-translate-8.html partial-prerender-translate-8-ref.html
@ -179,6 +179,6 @@ skip test-pref(layout.animation.prerender.partial.jank,true) test-pref(layout.an
skip-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)||Android) test-pref(layout.animation.prerender.partial,true) test-pref(layout.animation.prerender.viewport-ratio-limit,"1.125") fuzzy-if(!layersGPUAccelerated,0-75,0-2683) == partial-prerender-expansion-rotate.html partial-prerender-expansion-ref.html
skip-if(useDrawSnapshot) test-pref(layout.animation.prerender.partial,true) test-pref(layout.animation.prerender.viewport-ratio-limit,"1.125") pref(dom.meta-viewport.enabled,true) pref(apz.allow_zooming,true) == partial-prerender-expansion-with-resolution-1.html partial-prerender-expansion-with-resolution-ref.html
skip test-pref(layout.animation.prerender.partial,true) test-pref(layout.animation.prerender.viewport-ratio-limit,"1.125") pref(dom.meta-viewport.enabled,true) pref(apz.allow_zooming,true) == partial-prerender-expansion-with-resolution-2.html partial-prerender-expansion-with-resolution-ref.html # bug 1650039 for WebRender
test-pref(layout.animation.prerender.partial.jank,true) test-pref(layout.animation.prerender.partial,true) test-pref(layout.animation.prerender.viewport-ratio-limit,"1.125") fuzzy-if(Android,0-255,0-400) == partial-prerender-in-svg-1.html partial-prerender-in-svg-1-ref.html
test-pref(layout.animation.prerender.partial.jank,true) test-pref(layout.animation.prerender.partial,true) test-pref(layout.animation.prerender.viewport-ratio-limit,"1.125") == partial-prerender-in-svg-1.html partial-prerender-in-svg-1-ref.html
test-pref(layout.animation.prerender.partial.jank,true) test-pref(layout.animation.prerender.partial,true) test-pref(layout.animation.prerender.viewport-ratio-limit,"1.125") == partial-prerender-in-svg-2.html partial-prerender-in-svg-1-ref.html # Reuse partial-prerender-in-svg-1-ref.html since the result should look same as partial-prerender-in-svg-1.html
test-pref(layout.animation.prerender.partial.jank,true) test-pref(layout.animation.prerender.partial,true) test-pref(layout.animation.prerender.viewport-ratio-limit,"1.125") fuzzy-if(Android,0-255,0-2000) == partial-prerender-in-svg-3.html partial-prerender-in-svg-3-ref.html
test-pref(layout.animation.prerender.partial.jank,true) test-pref(layout.animation.prerender.partial,true) test-pref(layout.animation.prerender.viewport-ratio-limit,"1.125") == partial-prerender-in-svg-3.html partial-prerender-in-svg-3-ref.html

View File

@ -1,3 +0,0 @@
[mix-blend-mode-both-parent-and-blended-with-3D-transform.html]
fuzzy:
maxDifference=94-95;totalPixels=340-460

View File

@ -1,3 +0,0 @@
[mix-blend-mode-parent-with-3D-transform.html]
fuzzy:
maxDifference=60-61;totalPixels=140-140

View File

@ -0,0 +1,3 @@
[mix-blend-mode-rotated-clip.html]
expected:
FAIL

View File

@ -1,5 +1,3 @@
[transform3d-preserve3d-001.html]
fuzzy:
if os == "android": maxDifference=4;totalPixels=185
if os == "mac": maxDifference=198;totalPixels=308
if os == "win": maxDifference=174;totalPixels=240
expected:
if os == "win": FAIL