diff --git a/webrender/src/clip_scroll_tree.rs b/webrender/src/clip_scroll_tree.rs index 23bd924c7d..e52c3013a4 100644 --- a/webrender/src/clip_scroll_tree.rs +++ b/webrender/src/clip_scroll_tree.rs @@ -26,6 +26,10 @@ pub type ScrollStates = FastHashMap; pub struct CoordinateSystemId(pub u32); impl CoordinateSystemId { + pub fn root() -> CoordinateSystemId { + CoordinateSystemId(0) + } + pub fn next(&self) -> CoordinateSystemId { let CoordinateSystemId(id) = *self; CoordinateSystemId(id + 1) diff --git a/webrender/src/prim_store.rs b/webrender/src/prim_store.rs index eae36a93c1..0be4a00f30 100644 --- a/webrender/src/prim_store.rs +++ b/webrender/src/prim_store.rs @@ -9,7 +9,7 @@ use api::{ClipMode, LayerSize, LayerVector2D, LayerToWorldTransform, LineOrienta use api::{ClipAndScrollInfo, EdgeAaSegmentMask, PremultipliedColorF, TileOffset}; use api::{ClipId, LayerTransform, PipelineId, YuvColorSpace, YuvFormat}; use border::BorderCornerInstance; -use clip_scroll_tree::ClipScrollTree; +use clip_scroll_tree::{CoordinateSystemId, ClipScrollTree}; use clip::{ClipSourcesHandle, ClipStore}; use frame_builder::PrimitiveContext; use glyph_rasterizer::{FontInstance, FontTransform}; @@ -1322,6 +1322,14 @@ impl PrimitiveStore { .collect(); if clips.is_empty() { + // If this item is in the root coordinate system, then + // we know that the local_clip_rect in the clip node + // will take care of applying this clip, so no need + // for a mask. + if prim_coordinate_system_id == CoordinateSystemId::root() { + return true; + } + // If we have filtered all clips and the screen rect isn't any smaller, we can just // skip masking entirely. if combined_outer_rect == prim_screen_rect { @@ -1375,7 +1383,7 @@ impl PrimitiveStore { // Reset the visibility of this primitive. // Do some basic checks first, that can early out // without even knowing the local rect. - let (cpu_prim_index, dependencies, cull_children) = { + let (cpu_prim_index, dependencies, cull_children, may_need_clip_mask) = { let metadata = &mut self.cpu_metadata[prim_index.0]; metadata.screen_rect = None; @@ -1385,7 +1393,7 @@ impl PrimitiveStore { return None; } - let (dependencies, cull_children) = match metadata.prim_kind { + let (dependencies, cull_children, may_need_clip_mask) = match metadata.prim_kind { PrimitiveKind::Picture => { let pic = &mut self.cpu_pictures[metadata.cpu_prim_index.0]; @@ -1393,18 +1401,24 @@ impl PrimitiveStore { return None; } - let rfid = match pic.kind { - PictureKind::Image { reference_frame_id, .. } => Some(reference_frame_id), - _ => None, + let (rfid, may_need_clip_mask) = match pic.kind { + PictureKind::Image { reference_frame_id, .. } => { + (Some(reference_frame_id), false) + } + _ => { + (None, true) + } }; - (Some((pic.pipeline_id, mem::replace(&mut pic.runs, Vec::new()), rfid)), pic.cull_children) + (Some((pic.pipeline_id, mem::replace(&mut pic.runs, Vec::new()), rfid)), + pic.cull_children, + may_need_clip_mask) } _ => { - (None, true) + (None, true, true) } }; - (metadata.cpu_prim_index, dependencies, cull_children) + (metadata.cpu_prim_index, dependencies, cull_children, may_need_clip_mask) }; // If we have dependencies, we need to prepare them first, in order @@ -1476,7 +1490,7 @@ impl PrimitiveStore { (local_rect, xf_rect.bounding_rect) }; - if !self.update_clip_task( + if perform_culling && may_need_clip_mask && !self.update_clip_task( prim_index, prim_context, &unclipped_device_rect, @@ -1486,7 +1500,7 @@ impl PrimitiveStore { render_tasks, clip_store, parent_tasks, - ) && perform_culling { + ) { return None; } diff --git a/wrench/reftests/performance/no-clip-mask.png b/wrench/reftests/performance/no-clip-mask.png new file mode 100644 index 0000000000..9d06d15144 Binary files /dev/null and b/wrench/reftests/performance/no-clip-mask.png differ diff --git a/wrench/reftests/performance/no-clip-mask.yaml b/wrench/reftests/performance/no-clip-mask.yaml new file mode 100644 index 0000000000..ecc2f2c1bf --- /dev/null +++ b/wrench/reftests/performance/no-clip-mask.yaml @@ -0,0 +1,23 @@ +# In this case, there is no incompatible transform. +# Therefore, the clip condition should be handled +# by the vertex shader via the local_clip_rect, and +# there should be no clip mask generated. +--- +root: + items: + - + type: "stacking-context" + items: + - + bounds: [0, 111, 1887, 1365] + "clip-rect": [0, 111, 1887, 1365] + type: iframe + id: [1, 2] +pipelines: + - + id: [1, 2] + items: + - + bounds: [1875, -1, 12, 999] + "clip-rect": [1875, -1, 12, 999] + image: checkerboard(4, 8, 8) diff --git a/wrench/reftests/performance/reftest.list b/wrench/reftests/performance/reftest.list new file mode 100644 index 0000000000..50bbbb25dc --- /dev/null +++ b/wrench/reftests/performance/reftest.list @@ -0,0 +1 @@ +== color_targets(1) alpha_targets(0) no-clip-mask.yaml no-clip-mask.png diff --git a/wrench/reftests/reftest.list b/wrench/reftests/reftest.list index c573c70887..9db9842235 100644 --- a/wrench/reftests/reftest.list +++ b/wrench/reftests/reftest.list @@ -8,6 +8,7 @@ include filters/reftest.list include gradient/reftest.list include image/reftest.list include mask/reftest.list +include performance/reftest.list include scrolling/reftest.list include snap/reftest.list include split/reftest.list