From ee8a46244a6369b7ace0e4ccbc8b17dee0c40655 Mon Sep 17 00:00:00 2001 From: Brad Werth Date: Thu, 20 May 2021 17:26:23 +0000 Subject: [PATCH] Bug 1706561 Part 5: Intern polygon data for image masks, and retrieve for hit tests. r=gw This moves the polygon data out of the ClipItemKind and ClipItemKeyKind enums, which reduces bloat, which improves access times for scenes with lots of clips -- even if they don't use image mask clips. The SceneBuilder interns polygons when they arrive alongside image mask clips, and the HitTestingScene retrieves them when it's time to build the hit test nodes. Differential Revision: https://phabricator.services.mozilla.com/D114558 --- gfx/webrender_bindings/webrender_ffi.h | 3 ++- gfx/wr/webrender/src/clip.rs | 33 +++++++++++++++++++++++----- gfx/wr/webrender/src/hit_test.rs | 8 ++++--- gfx/wr/webrender/src/intern.rs | 1 + gfx/wr/webrender/src/picture.rs | 2 +- gfx/wr/webrender/src/render_backend.rs | 2 +- gfx/wr/webrender/src/scene_builder_thread.rs | 2 +- gfx/wr/webrender/src/scene_building.rs | 19 ++++++++++++++-- 8 files changed, 55 insertions(+), 15 deletions(-) diff --git a/gfx/webrender_bindings/webrender_ffi.h b/gfx/webrender_bindings/webrender_ffi.h index 882b8436ca00..0653e0115a8b 100644 --- a/gfx/webrender_bindings/webrender_ffi.h +++ b/gfx/webrender_bindings/webrender_ffi.h @@ -55,7 +55,8 @@ bool gecko_profiler_thread_is_being_profiled(); macro(picture); \ macro(text_run); \ macro(filterdata); \ - macro(backdrop); + macro(backdrop); \ + macro(polyon); // Prelude of types necessary before including webrender_ffi_generated.h namespace mozilla { diff --git a/gfx/wr/webrender/src/clip.rs b/gfx/wr/webrender/src/clip.rs index 9b59f5982b96..7a839a68fc93 100644 --- a/gfx/wr/webrender/src/clip.rs +++ b/gfx/wr/webrender/src/clip.rs @@ -409,12 +409,12 @@ impl From for ClipNode { mode, } } - ClipItemKeyKind::ImageMask(rect, image, repeat, polygon) => { + ClipItemKeyKind::ImageMask(rect, image, repeat, polygon_handle) => { ClipItemKind::Image { image, rect: rect.into(), repeat, - polygon, + polygon_handle, } } ClipItemKeyKind::BoxShadow(shadow_rect_fract_offset, shadow_rect_size, shadow_radius, prim_shadow_rect, blur_radius, clip_mode) => { @@ -1449,7 +1449,7 @@ impl ClipRegion> { pub enum ClipItemKeyKind { Rectangle(RectangleKey, ClipMode), RoundedRectangle(RectangleKey, BorderRadiusAu, ClipMode), - ImageMask(RectangleKey, ImageKey, bool, PolygonKey), + ImageMask(RectangleKey, ImageKey, bool, Option), BoxShadow(PointKey, SizeKey, BorderRadiusAu, RectangleKey, Au, BoxShadowClipMode), } @@ -1472,12 +1472,12 @@ impl ClipItemKeyKind { } pub fn image_mask(image_mask: &ImageMask, mask_rect: LayoutRect, - points: Vec, fill_rule: FillRule) -> Self { + polygon_handle: Option) -> Self { ClipItemKeyKind::ImageMask( mask_rect.into(), image_mask.image, image_mask.repeat, - PolygonKey::new(&points, fill_rule) + polygon_handle, ) } @@ -1559,7 +1559,7 @@ pub enum ClipItemKind { image: ImageKey, rect: LayoutRect, repeat: bool, - polygon: PolygonKey, + polygon_handle: Option, }, BoxShadow { source: BoxShadowClipSource, @@ -2207,3 +2207,24 @@ mod tests { ); } } + +/// 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 +/// accessed at all by the frame builder. Another oddity is that the +/// PolygonKey contains the totality of the information about the polygon, so +/// the InternData and StoreData types are both PolygonKey. +#[derive(Copy, Clone, Debug, Hash, MallocSizeOf, PartialEq, Eq)] +#[cfg_attr(any(feature = "serde"), derive(Deserialize, Serialize))] +pub enum PolygonIntern {} + +pub type PolygonDataHandle = intern::Handle; + +impl intern::InternDebug for PolygonKey {} + +impl intern::Internable for PolygonIntern { + type Key = PolygonKey; + type StoreData = PolygonKey; + type InternData = PolygonKey; + const PROFILE_COUNTER: usize = crate::profiler::INTERNED_POLYGONS; +} diff --git a/gfx/wr/webrender/src/hit_test.rs b/gfx/wr/webrender/src/hit_test.rs index f13ec0131bc6..4a73e2158dfa 100644 --- a/gfx/wr/webrender/src/hit_test.rs +++ b/gfx/wr/webrender/src/hit_test.rs @@ -90,9 +90,11 @@ impl HitTestClipNode { ClipItemKind::RoundedRectangle { rect, radius, mode } => { HitTestRegion::RoundedRectangle(rect, radius, mode) } - ClipItemKind::Image { rect, polygon, .. } => { - if polygon.point_count > 0 { - HitTestRegion::Polygon(rect, polygon) + ClipItemKind::Image { rect, polygon_handle, .. } => { + if let Some(handle) = polygon_handle { + // Retrieve the polygon data from the interner. + let polygon = &interners.polygon[handle]; + HitTestRegion::Polygon(rect, *polygon) } else { HitTestRegion::Rectangle(rect, ClipMode::Clip) } diff --git a/gfx/wr/webrender/src/intern.rs b/gfx/wr/webrender/src/intern.rs index 499036cba624..9ba7aa75100e 100644 --- a/gfx/wr/webrender/src/intern.rs +++ b/gfx/wr/webrender/src/intern.rs @@ -395,6 +395,7 @@ macro_rules! enumerate_interners { text_run: TextRun, filter_data: FilterDataIntern, backdrop: Backdrop, + polygon: PolygonIntern, } } } diff --git a/gfx/wr/webrender/src/picture.rs b/gfx/wr/webrender/src/picture.rs index 1b91241245f9..7527101881f3 100644 --- a/gfx/wr/webrender/src/picture.rs +++ b/gfx/wr/webrender/src/picture.rs @@ -147,7 +147,7 @@ use crate::scene_builder_thread::InternerUpdates; #[cfg(any(feature = "capture", feature = "replay"))] use crate::intern::{Internable, UpdateList}; #[cfg(any(feature = "capture", feature = "replay"))] -use crate::clip::ClipIntern; +use crate::clip::{ClipIntern, PolygonIntern}; #[cfg(any(feature = "capture", feature = "replay"))] use crate::filterdata::FilterDataIntern; #[cfg(any(feature = "capture", feature = "replay"))] diff --git a/gfx/wr/webrender/src/render_backend.rs b/gfx/wr/webrender/src/render_backend.rs index bddf5a121f64..96bc6004842b 100644 --- a/gfx/wr/webrender/src/render_backend.rs +++ b/gfx/wr/webrender/src/render_backend.rs @@ -20,7 +20,7 @@ use crate::render_api::CaptureBits; #[cfg(feature = "replay")] use crate::render_api::CapturedDocument; use crate::render_api::{MemoryReport, TransactionMsg, ResourceUpdate, ApiMsg, FrameMsg, ClearCache, DebugCommand}; -use crate::clip::{ClipIntern, ClipStoreScratchBuffer}; +use crate::clip::{ClipIntern, PolygonIntern, ClipStoreScratchBuffer}; use crate::filterdata::FilterDataIntern; #[cfg(any(feature = "capture", feature = "replay"))] use crate::capture::CaptureConfig; diff --git a/gfx/wr/webrender/src/scene_builder_thread.rs b/gfx/wr/webrender/src/scene_builder_thread.rs index 21ca204db455..c10bba793bc3 100644 --- a/gfx/wr/webrender/src/scene_builder_thread.rs +++ b/gfx/wr/webrender/src/scene_builder_thread.rs @@ -14,7 +14,7 @@ use crate::render_api::{ApiMsg, FrameMsg, SceneMsg, ResourceUpdate, TransactionM use crate::capture::CaptureConfig; use crate::frame_builder::FrameBuilderConfig; use crate::scene_building::SceneBuilder; -use crate::clip::ClipIntern; +use crate::clip::{ClipIntern, PolygonIntern}; use crate::filterdata::FilterDataIntern; use crate::intern::{Internable, Interner, UpdateList}; use crate::internal_types::{FastHashMap, FastHashSet}; diff --git a/gfx/wr/webrender/src/scene_building.rs b/gfx/wr/webrender/src/scene_building.rs index 1fd67a9620d2..44b75e6d847d 100644 --- a/gfx/wr/webrender/src/scene_building.rs +++ b/gfx/wr/webrender/src/scene_building.rs @@ -49,6 +49,7 @@ use api::units::*; use crate::image_tiling::simplify_repeated_primitive; use crate::clip::{ClipChainId, ClipRegion, ClipItemKey, ClipStore, ClipItemKeyKind}; use crate::clip::{ClipInternData, ClipNodeKind, ClipInstance, SceneClipInstance}; +use crate::clip::{PolygonDataHandle}; use crate::spatial_tree::{ROOT_SPATIAL_NODE_INDEX, SpatialTree, SpatialNodeIndex, StaticCoordinateSystemId}; use crate::frame_builder::{ChasePrimitive, FrameBuilderConfig}; use crate::glyph_rasterizer::FontInstance; @@ -60,6 +61,7 @@ use crate::picture::{BlitReason, OrderedPictureChild, PrimitiveList}; use crate::prim_store::{PrimitiveInstance, register_prim_chase_id}; use crate::prim_store::{PrimitiveInstanceKind, NinePatchDescriptor, PrimitiveStore}; use crate::prim_store::{InternablePrimitive, SegmentInstanceIndex, PictureIndex}; +use crate::prim_store::PolygonKey; use crate::prim_store::backdrop::Backdrop; use crate::prim_store::borders::{ImageBorder, NormalBorderPrim}; use crate::prim_store::gradient::{ @@ -2427,9 +2429,22 @@ impl<'a> SceneBuilder<'a> { &image_mask.rect, spatial_node_index, ); - let points = points_range.iter().collect(); + let points: Vec = points_range.iter().collect(); + + // If any points are provided, then intern a polygon with the points and fill rule. + let mut polygon_handle: Option = None; + if points.len() > 0 { + let item = PolygonKey::new(&points, fill_rule); + + let handle = self + .interners + .polygon + .intern(&item, || item); + polygon_handle = Some(handle); + } + let item = ClipItemKey { - kind: ClipItemKeyKind::image_mask(image_mask, snapped_mask_rect, points, fill_rule), + kind: ClipItemKeyKind::image_mask(image_mask, snapped_mask_rect, polygon_handle), }; let handle = self -- 2.11.4.GIT