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)
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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.
|
||||
|
@ -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),
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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)),
|
||||
|
@ -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),
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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(),
|
||||
))
|
||||
);
|
||||
|
||||
|
@ -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(
|
||||
|
@ -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)
|
||||
|
@ -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 {
|
||||
|
@ -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)
|
||||
})
|
||||
}
|
||||
|
@ -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
|
@ -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
|
@ -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]
|
@ -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]
|
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 18 KiB |
@ -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
|
||||
|
@ -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
|
||||
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.0 KiB |
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 3.3 KiB |
Before Width: | Height: | Size: 54 KiB After Width: | Height: | Size: 53 KiB |
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 3.0 KiB |
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 32 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 77 KiB After Width: | Height: | Size: 77 KiB |
Before Width: | Height: | Size: 116 KiB After Width: | Height: | Size: 107 KiB |
@ -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
|
||||
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
@ -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
|
||||
|
@ -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
|
@ -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
|
||||
|
Before Width: | Height: | Size: 61 KiB After Width: | Height: | Size: 61 KiB |
@ -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
|
||||
|
Before Width: | Height: | Size: 93 KiB After Width: | Height: | Size: 93 KiB |
@ -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 ]
|
||||
|
Before Width: | Height: | Size: 225 KiB After Width: | Height: | Size: 226 KiB |
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -1,3 +0,0 @@
|
||||
[mix-blend-mode-both-parent-and-blended-with-3D-transform.html]
|
||||
fuzzy:
|
||||
maxDifference=94-95;totalPixels=340-460
|
@ -1,3 +0,0 @@
|
||||
[mix-blend-mode-parent-with-3D-transform.html]
|
||||
fuzzy:
|
||||
maxDifference=60-61;totalPixels=140-140
|
@ -0,0 +1,3 @@
|
||||
[mix-blend-mode-rotated-clip.html]
|
||||
expected:
|
||||
FAIL
|
@ -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
|
||||
|