зеркало из https://github.com/mozilla/gecko-dev.git
Backed out changeset e24b51679d83 (bug 1741781) on devs request. a=backout
This commit is contained in:
Родитель
3ef6a5c028
Коммит
96d7010bce
|
@ -110,7 +110,8 @@ use crate::render_task_cache::to_cache_size;
|
|||
use crate::resource_cache::{ImageRequest, ResourceCache};
|
||||
use crate::space::SpaceMapper;
|
||||
use crate::util::{clamp_to_scale_factor, MaxRect, extract_inner_rect_safe, project_rect, ScaleOffset, VecHelper};
|
||||
use std::{ops, u32, mem};
|
||||
use euclid::approxeq::ApproxEq;
|
||||
use std::{iter, ops, u32, mem};
|
||||
|
||||
// Type definitions for interning clip nodes.
|
||||
|
||||
|
@ -539,7 +540,7 @@ impl ClipNodeRange {
|
|||
enum ClipSpaceConversion {
|
||||
Local,
|
||||
ScaleOffset(ScaleOffset),
|
||||
Transform(LayoutTransform),
|
||||
Transform(LayoutToWorldTransform),
|
||||
}
|
||||
|
||||
impl ClipSpaceConversion {
|
||||
|
@ -563,11 +564,9 @@ impl ClipSpaceConversion {
|
|||
.accumulate(&clip_spatial_node.content_transform);
|
||||
ClipSpaceConversion::ScaleOffset(scale_offset)
|
||||
} else {
|
||||
assert!(spatial_tree.is_ancestor(clip_spatial_node_index, prim_spatial_node_index));
|
||||
|
||||
ClipSpaceConversion::Transform(
|
||||
spatial_tree
|
||||
.get_relative_transform(prim_spatial_node_index, clip_spatial_node_index)
|
||||
.get_world_transform(clip_spatial_node_index)
|
||||
.into_transform()
|
||||
)
|
||||
}
|
||||
|
@ -1295,10 +1294,12 @@ impl ClipStore {
|
|||
&mut self,
|
||||
local_prim_rect: LayoutRect,
|
||||
prim_to_pic_mapper: &SpaceMapper<LayoutPixel, PicturePixel>,
|
||||
pic_to_world_mapper: &SpaceMapper<PicturePixel, WorldPixel>,
|
||||
spatial_tree: &SpatialTree,
|
||||
gpu_cache: &mut GpuCache,
|
||||
resource_cache: &mut ResourceCache,
|
||||
device_pixel_scale: DevicePixelScale,
|
||||
world_rect: &WorldRect,
|
||||
clip_data_store: &mut ClipDataStore,
|
||||
request_resources: bool,
|
||||
is_chased: bool,
|
||||
|
@ -1314,6 +1315,7 @@ impl ClipStore {
|
|||
|
||||
let local_bounding_rect = local_prim_rect.intersection(&local_clip_rect)?;
|
||||
let mut pic_clip_rect = prim_to_pic_mapper.map(&local_bounding_rect)?;
|
||||
let world_clip_rect = pic_to_world_mapper.map(&pic_clip_rect)?;
|
||||
|
||||
// Now, we've collected all the clip nodes that *potentially* affect this
|
||||
// primitive region, and reduced the size of the prim region as much as possible.
|
||||
|
@ -1340,8 +1342,9 @@ impl ClipStore {
|
|||
ClipSpaceConversion::Transform(ref transform) => {
|
||||
has_non_local_clips = true;
|
||||
node.item.kind.get_clip_result_complex(
|
||||
&local_bounding_rect,
|
||||
transform,
|
||||
&world_clip_rect,
|
||||
world_rect,
|
||||
)
|
||||
}
|
||||
};
|
||||
|
@ -1800,9 +1803,15 @@ impl ClipItemKind {
|
|||
|
||||
fn get_clip_result_complex(
|
||||
&self,
|
||||
local_prim_rect: &LayoutRect,
|
||||
prim_to_clip_transform: &LayoutTransform,
|
||||
transform: &LayoutToWorldTransform,
|
||||
prim_world_rect: &WorldRect,
|
||||
world_rect: &WorldRect,
|
||||
) -> ClipResult {
|
||||
let visible_rect = match prim_world_rect.intersection(world_rect) {
|
||||
Some(rect) => rect,
|
||||
None => return ClipResult::Reject,
|
||||
};
|
||||
|
||||
let (clip_rect, inner_rect, mode) = match *self {
|
||||
ClipItemKind::Rectangle { rect, mode } => {
|
||||
(rect, Some(rect), mode)
|
||||
|
@ -1820,15 +1829,8 @@ impl ClipItemKind {
|
|||
}
|
||||
};
|
||||
|
||||
let prim_rect = match project_rect(prim_to_clip_transform, local_prim_rect, &clip_rect) {
|
||||
Some(rect) => rect,
|
||||
None => {
|
||||
return ClipResult::Reject;
|
||||
}
|
||||
};
|
||||
|
||||
if let Some(ref inner_clip_rect) = inner_rect {
|
||||
if inner_clip_rect.contains_box(&prim_rect) {
|
||||
if let Some(()) = projected_rect_contains(inner_clip_rect, transform, &visible_rect) {
|
||||
return match mode {
|
||||
ClipMode::Clip => ClipResult::Accept,
|
||||
ClipMode::ClipOut => ClipResult::Reject,
|
||||
|
@ -1836,7 +1838,28 @@ impl ClipItemKind {
|
|||
}
|
||||
}
|
||||
|
||||
return ClipResult::Partial;
|
||||
match mode {
|
||||
ClipMode::Clip => {
|
||||
let outer_clip_rect = match project_rect(
|
||||
transform,
|
||||
&clip_rect,
|
||||
&world_rect,
|
||||
) {
|
||||
Some(outer_clip_rect) => outer_clip_rect,
|
||||
None => return ClipResult::Partial,
|
||||
};
|
||||
|
||||
match outer_clip_rect.intersection(prim_world_rect) {
|
||||
Some(..) => {
|
||||
ClipResult::Partial
|
||||
}
|
||||
None => {
|
||||
ClipResult::Reject
|
||||
}
|
||||
}
|
||||
}
|
||||
ClipMode::ClipOut => ClipResult::Partial,
|
||||
}
|
||||
}
|
||||
|
||||
// Check how a given clip source affects a local primitive region.
|
||||
|
@ -2078,6 +2101,42 @@ pub fn polygon_contains_point(
|
|||
}
|
||||
}
|
||||
|
||||
pub fn projected_rect_contains(
|
||||
source_rect: &LayoutRect,
|
||||
transform: &LayoutToWorldTransform,
|
||||
target_rect: &WorldRect,
|
||||
) -> Option<()> {
|
||||
let points = [
|
||||
transform.transform_point2d(source_rect.top_left())?,
|
||||
transform.transform_point2d(source_rect.top_right())?,
|
||||
transform.transform_point2d(source_rect.bottom_right())?,
|
||||
transform.transform_point2d(source_rect.bottom_left())?,
|
||||
];
|
||||
let target_points = [
|
||||
target_rect.top_left(),
|
||||
target_rect.top_right(),
|
||||
target_rect.bottom_right(),
|
||||
target_rect.bottom_left(),
|
||||
];
|
||||
// iterate the edges of the transformed polygon
|
||||
for (a, b) in points
|
||||
.iter()
|
||||
.cloned()
|
||||
.zip(points[1..].iter().cloned().chain(iter::once(points[0])))
|
||||
{
|
||||
// If this edge is redundant, it's a weird, case, and we shouldn't go
|
||||
// length in trying to take the fast path (e.g. when the whole rectangle is a point).
|
||||
// If any of edges of the target rectangle crosses the edge, it's not completely
|
||||
// inside our transformed polygon either.
|
||||
if a.approx_eq(&b) || target_points.iter().any(|&c| (b - a).cross(c - a) < 0.0) {
|
||||
return None
|
||||
}
|
||||
}
|
||||
|
||||
Some(())
|
||||
}
|
||||
|
||||
|
||||
// Add a clip node into the list of clips to be processed
|
||||
// for the current clip chain. Returns false if the clip
|
||||
// results in the entire primitive being culled out.
|
||||
|
@ -2119,6 +2178,8 @@ fn add_clip_node_to_current_chain(
|
|||
};
|
||||
}
|
||||
ClipSpaceConversion::Transform(..) => {
|
||||
assert!(spatial_tree.is_ancestor(node.spatial_node_index, prim_spatial_node_index));
|
||||
|
||||
// Map the local clip rect directly into the same space as the picture
|
||||
// surface. This will often be the same space as the clip itself, which
|
||||
// results in a reduction in allocated clip mask size.
|
||||
|
@ -2163,6 +2224,25 @@ fn add_clip_node_to_current_chain(
|
|||
true
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::projected_rect_contains;
|
||||
use euclid::{Transform3D, rect};
|
||||
|
||||
#[test]
|
||||
fn test_empty_projected_rect() {
|
||||
assert_eq!(
|
||||
None,
|
||||
projected_rect_contains(
|
||||
&rect(10.0, 10.0, 0.0, 0.0).to_box2d(),
|
||||
&Transform3D::identity(),
|
||||
&rect(20.0, 20.0, 10.0, 10.0).to_box2d(),
|
||||
),
|
||||
"Empty rectangle is considered to include a non-empty!"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// PolygonKeys get interned, because it's a convenient way to move the data
|
||||
/// for the polygons out of the ClipItemKind and ClipItemKeyKind enums. The
|
||||
/// polygon data is both interned and retrieved by the scene builder, and not
|
||||
|
|
|
@ -2164,10 +2164,12 @@ impl TileCacheInstance {
|
|||
let clip_chain_instance = frame_state.clip_store.build_clip_chain_instance(
|
||||
pic_rect.cast_unit(),
|
||||
&map_local_to_surface,
|
||||
&pic_to_world_mapper,
|
||||
frame_context.spatial_tree,
|
||||
frame_state.gpu_cache,
|
||||
frame_state.resource_cache,
|
||||
frame_context.global_device_pixel_scale,
|
||||
&frame_context.global_screen_world_rect,
|
||||
&mut frame_state.data_stores.clip,
|
||||
true,
|
||||
false,
|
||||
|
|
|
@ -1095,6 +1095,8 @@ fn update_clip_task_for_brush(
|
|||
);
|
||||
clip_mask_instances.push(clip_mask_kind);
|
||||
} else {
|
||||
let dirty_world_rect = frame_state.current_dirty_region().combined;
|
||||
|
||||
for segment in segments {
|
||||
// Build a clip chain for the smaller segment rect. This will
|
||||
// often manage to eliminate most/all clips, and sometimes
|
||||
|
@ -1110,10 +1112,12 @@ fn update_clip_task_for_brush(
|
|||
.build_clip_chain_instance(
|
||||
segment.local_rect.translate(prim_origin.to_vector()),
|
||||
&pic_state.map_local_to_pic,
|
||||
&pic_state.map_pic_to_world,
|
||||
&frame_context.spatial_tree,
|
||||
frame_state.gpu_cache,
|
||||
frame_state.resource_cache,
|
||||
device_pixel_scale,
|
||||
&dirty_world_rect,
|
||||
&mut data_stores.clip,
|
||||
false,
|
||||
instance.is_chased(),
|
||||
|
|
|
@ -398,10 +398,12 @@ pub fn update_primitive_visibility(
|
|||
.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(),
|
||||
|
|
Загрузка…
Ссылка в новой задаче