diff --git a/Cargo.lock b/Cargo.lock index 540af7029e3..400d9618696 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2817,6 +2817,7 @@ name = "fonts_traits" version = "0.0.1" dependencies = [ "atomic_refcell", + "base", "dwrote", "ipc-channel", "log", diff --git a/components/compositing/compositor.rs b/components/compositing/compositor.rs index 352f5a9ae2c..13ea3a32428 100644 --- a/components/compositing/compositor.rs +++ b/components/compositing/compositor.rs @@ -14,7 +14,7 @@ use std::time::{SystemTime, UNIX_EPOCH}; use base::Epoch; use base::cross_process_instant::CrossProcessInstant; use base::generic_channel::{GenericSender, RoutedReceiver}; -use base::id::{PipelineId, WebViewId}; +use base::id::{PipelineId, RenderingGroupId, WebViewId}; use bitflags::bitflags; use compositing_traits::display_list::{CompositorDisplayListInfo, ScrollTree, ScrollType}; use compositing_traits::rendering_context::RenderingContext; @@ -792,11 +792,13 @@ impl IOCompositor { number_of_font_keys, number_of_font_instance_keys, result_sender, + rendering_group_id, ) => { self.handle_generate_font_keys( number_of_font_keys, number_of_font_instance_keys, result_sender, + rendering_group_id, ); }, CompositorMsg::Viewport(webview_id, viewport_description) => { @@ -834,11 +836,13 @@ impl IOCompositor { number_of_font_keys, number_of_font_instance_keys, result_sender, + rendering_group_id, ) => { self.handle_generate_font_keys( number_of_font_keys, number_of_font_instance_keys, result_sender, + rendering_group_id, ); }, CompositorMsg::NewWebRenderFrameReady(..) => { @@ -852,11 +856,13 @@ impl IOCompositor { } /// Generate the font keys and send them to the `result_sender`. + /// Currently `RenderingGroupId` is not used. fn handle_generate_font_keys( &self, number_of_font_keys: usize, number_of_font_instance_keys: usize, result_sender: GenericSender<(Vec, Vec)>, + _rendering_group_id: RenderingGroupId, ) { let font_keys = (0..number_of_font_keys) .map(|_| self.global.borrow().webrender_api.generate_font_key()) diff --git a/components/fonts/font.rs b/components/fonts/font.rs index 5a787fd6ea4..543936db63b 100644 --- a/components/fonts/font.rs +++ b/components/fonts/font.rs @@ -12,6 +12,7 @@ use std::time::Instant; use std::{iter, str}; use app_units::Au; +use base::id::RenderingGroupId; use bitflags::bitflags; use euclid::default::{Point2D, Rect}; use euclid::num::Zero; @@ -21,6 +22,7 @@ use malloc_size_of_derive::MallocSizeOf; use parking_lot::RwLock; use read_fonts::tables::os2::{Os2, SelectionFlags}; use read_fonts::types::Tag; +use rustc_hash::FxHashMap; use serde::{Deserialize, Serialize}; use smallvec::SmallVec; use style::computed_values::font_variant_caps; @@ -223,7 +225,7 @@ pub struct Font { shaper: OnceLock, cached_shape_data: RwLock, - pub(crate) font_instance_key: OnceLock, + font_instance_key: RwLock>, /// If this is a synthesized small caps font, then this font reference is for /// the version of the font used to replace lowercase ASCII letters. It's up @@ -248,12 +250,15 @@ impl malloc_size_of::MallocSizeOf for Font { fn size_of(&self, ops: &mut malloc_size_of::MallocSizeOfOps) -> usize { // TODO: Collect memory usage for platform fonts and for shapers. // This skips the template, because they are already stored in the template cache. + self.metrics.size_of(ops) + self.descriptor.size_of(ops) + self.cached_shape_data.read().size_of(ops) + self.font_instance_key - .get() - .map_or(0, |key| key.size_of(ops)) + .read() + .values() + .map(|key| key.size_of(ops)) + .sum::() } } @@ -306,10 +311,16 @@ impl Font { }) } - pub fn key(&self, font_context: &FontContext) -> FontInstanceKey { + pub fn key( + &self, + rendering_group_id: RenderingGroupId, + font_context: &FontContext, + ) -> FontInstanceKey { *self .font_instance_key - .get_or_init(|| font_context.create_font_instance_key(self)) + .write() + .entry(rendering_group_id) + .or_insert_with(|| font_context.create_font_instance_key(self, rendering_group_id)) } /// Return the data for this `Font`. Note that this is currently highly inefficient for system diff --git a/components/fonts/font_context.rs b/components/fonts/font_context.rs index 38f189ab136..345d045b61e 100644 --- a/components/fonts/font_context.rs +++ b/components/fonts/font_context.rs @@ -10,7 +10,7 @@ use std::sync::Arc; use std::sync::atomic::{AtomicBool, Ordering}; use app_units::Au; -use base::id::WebViewId; +use base::id::{RenderingGroupId, WebViewId}; use compositing_traits::CrossProcessCompositorApi; use fonts_traits::{ CSSFontFaceDescriptors, FontDescriptor, FontIdentifier, FontTemplate, FontTemplateRef, @@ -277,19 +277,25 @@ impl FontContext { )?))) } - pub(crate) fn create_font_instance_key(&self, font: &Font) -> FontInstanceKey { + pub(crate) fn create_font_instance_key( + &self, + font: &Font, + rendering_group_id: RenderingGroupId, + ) -> FontInstanceKey { match font.template.identifier() { FontIdentifier::Local(_) => self.system_font_service_proxy.get_system_font_instance( font.template.identifier(), font.descriptor.pt_size, font.webrender_font_instance_flags(), font.variations().to_owned(), + rendering_group_id, ), FontIdentifier::Web(_) => self.create_web_font_instance( font.template.clone(), font.descriptor.pt_size, font.webrender_font_instance_flags(), font.variations().to_owned(), + rendering_group_id, ), } } @@ -300,6 +306,7 @@ impl FontContext { pt_size: Au, flags: FontInstanceFlags, variations: Vec, + rendering_group_id: RenderingGroupId, ) -> FontInstanceKey { let identifier = font_template.identifier().clone(); let font_data = self @@ -310,7 +317,9 @@ impl FontContext { .write() .entry(identifier.clone()) .or_insert_with(|| { - let font_key = self.system_font_service_proxy.generate_font_key(); + let font_key = self + .system_font_service_proxy + .generate_font_key(rendering_group_id); self.compositor_api.lock().add_font( font_key, font_data.as_ipc_shared_memory(), @@ -324,7 +333,9 @@ impl FontContext { .write() .entry((font_key, pt_size, variations.clone())) .or_insert_with(|| { - let font_instance_key = self.system_font_service_proxy.generate_font_instance_key(); + let font_instance_key = self + .system_font_service_proxy + .generate_font_instance_key(rendering_group_id); self.compositor_api.lock().add_font_instance( font_instance_key, font_key, diff --git a/components/fonts/system_font_service.rs b/components/fonts/system_font_service.rs index eaaa0bb52db..4d9100316f9 100644 --- a/components/fonts/system_font_service.rs +++ b/components/fonts/system_font_service.rs @@ -8,6 +8,7 @@ use std::collections::HashMap; use std::thread; use app_units::Au; +use base::id::RenderingGroupId; use compositing_traits::CrossProcessCompositorApi; use fonts_traits::{ FontDescriptor, FontIdentifier, FontTemplate, FontTemplateRef, LowercaseFontFamilyName, @@ -20,6 +21,7 @@ use profile_traits::mem::{ ProcessReports, ProfilerChan, Report, ReportKind, ReportsChan, perform_memory_report, }; use profile_traits::path; +use rustc_hash::FxHashMap; use servo_config::pref; use style::values::computed::font::{GenericFontFamily, SingleFontFamily}; use webrender_api::{FontInstanceFlags, FontInstanceKey, FontKey, FontVariation}; @@ -48,21 +50,23 @@ pub struct SystemFontService { port: IpcReceiver, local_families: FontStore, compositor_api: CrossProcessCompositorApi, - webrender_fonts: HashMap, - font_instances: HashMap<(FontKey, Au, Vec), FontInstanceKey>, + // keys already have the IdNamespace for webrender + webrender_fonts: HashMap<(FontIdentifier, RenderingGroupId), FontKey>, + font_instances: HashMap<(FontKey, Au, Vec, RenderingGroupId), FontInstanceKey>, generic_fonts: ResolvedGenericFontFamilies, /// This is an optimization that allows the [`SystemFontService`] to send font data to /// the compositor asynchronously for creating WebRender fonts, while immediately /// returning a font key for that data. Once the free keys are exhausted, the /// [`SystemFontService`] will fetch a new batch. - free_font_keys: Vec, + /// TODO: We currently do not delete the free keys if a `WebView` is removed. + free_font_keys: FxHashMap>, /// This is an optimization that allows the [`SystemFontService`] to create WebRender font /// instances in the compositor asynchronously, while immediately returning a font /// instance key for the instance. Once the free keys are exhausted, the /// [`SystemFontService`] will fetch a new batch. - free_font_instance_keys: Vec, + free_font_instance_keys: FxHashMap>, } impl SystemFontService { @@ -88,7 +92,7 @@ impl SystemFontService { free_font_instance_keys: Default::default(), }; - cache.fetch_new_keys(); + cache.fetch_new_keys(RenderingGroupId::default()); cache.refresh_local_families(); memory_profiler_sender.run_with_memory_reporting( @@ -120,22 +124,41 @@ impl SystemFontService { result_sender.send(self.get_font_templates(font_descriptor, font_family)); }, SystemFontServiceMessage::GetFontInstance( + rendering_group_id, identifier, pt_size, flags, variations, result, ) => { - let _ = - result.send(self.get_font_instance(identifier, pt_size, flags, variations)); + let _ = result.send(self.get_font_instance( + rendering_group_id, + identifier, + pt_size, + flags, + variations, + )); }, - SystemFontServiceMessage::GetFontKey(result_sender) => { - self.fetch_new_keys(); - let _ = result_sender.send(self.free_font_keys.pop().unwrap()); + SystemFontServiceMessage::GetFontKey(rendering_group_id, result_sender) => { + self.fetch_new_keys(rendering_group_id); + + let _ = result_sender.send( + self.free_font_keys + .get_mut(&rendering_group_id) + .expect("We just filled the keys") + .pop() + .unwrap(), + ); }, - SystemFontServiceMessage::GetFontInstanceKey(result_sender) => { - self.fetch_new_keys(); - let _ = result_sender.send(self.free_font_instance_keys.pop().unwrap()); + SystemFontServiceMessage::GetFontInstanceKey(rendering_group_id, result_sender) => { + self.fetch_new_keys(rendering_group_id); + let _ = result_sender.send( + self.free_font_instance_keys + .get_mut(&rendering_group_id) + .expect("We just filled the keys") + .pop() + .unwrap(), + ); }, SystemFontServiceMessage::CollectMemoryReport(report_sender) => { self.collect_memory_report(report_sender); @@ -161,8 +184,16 @@ impl SystemFontService { } #[servo_tracing::instrument(skip_all)] - fn fetch_new_keys(&mut self) { - if !self.free_font_keys.is_empty() && !self.free_font_instance_keys.is_empty() { + fn fetch_new_keys(&mut self, rendering_group_id: RenderingGroupId) { + if !self + .free_font_keys + .get(&rendering_group_id) + .is_none_or(|v| v.is_empty()) && + !self + .free_font_instance_keys + .get(&rendering_group_id) + .is_none_or(|v| v.is_empty()) + { return; } @@ -171,9 +202,15 @@ impl SystemFontService { let (mut new_font_keys, mut new_font_instance_keys) = self.compositor_api.fetch_font_keys( FREE_FONT_KEYS_BATCH_SIZE - self.free_font_keys.len(), FREE_FONT_INSTANCE_KEYS_BATCH_SIZE - self.free_font_instance_keys.len(), + rendering_group_id, ); - self.free_font_keys.append(&mut new_font_keys); + self.free_font_keys + .entry(rendering_group_id) + .or_default() + .append(&mut new_font_keys); self.free_font_instance_keys + .entry(rendering_group_id) + .or_default() .append(&mut new_font_instance_keys); } @@ -228,20 +265,26 @@ impl SystemFontService { #[servo_tracing::instrument(skip_all)] fn get_font_instance( &mut self, + rendering_group_id: RenderingGroupId, identifier: FontIdentifier, pt_size: Au, flags: FontInstanceFlags, variations: Vec, ) -> FontInstanceKey { - self.fetch_new_keys(); + self.fetch_new_keys(rendering_group_id); let compositor_api = &self.compositor_api; let webrender_fonts = &mut self.webrender_fonts; let font_key = *webrender_fonts - .entry(identifier.clone()) + .entry((identifier.clone(), rendering_group_id)) .or_insert_with(|| { - let font_key = self.free_font_keys.pop().unwrap(); + let font_key = self + .free_font_keys + .get_mut(&rendering_group_id) + .expect("We just filled the keys") + .pop() + .unwrap(); let FontIdentifier::Local(local_font_identifier) = identifier else { unreachable!("Should never have a web font in the system font service"); }; @@ -252,9 +295,14 @@ impl SystemFontService { *self .font_instances - .entry((font_key, pt_size, variations.clone())) + .entry((font_key, pt_size, variations.clone(), rendering_group_id)) .or_insert_with(|| { - let font_instance_key = self.free_font_instance_keys.pop().unwrap(); + let font_instance_key = self + .free_font_instance_keys + .get_mut(&rendering_group_id) + .expect("We just filled the keys") + .pop() + .unwrap(); compositor_api.add_font_instance( font_instance_key, font_key, diff --git a/components/fonts/tests/font_context.rs b/components/fonts/tests/font_context.rs index b25f59bf86e..d91f09d83c3 100644 --- a/components/fonts/tests/font_context.rs +++ b/components/fonts/tests/font_context.rs @@ -130,11 +130,11 @@ mod font_context { .collect(), ); }, - SystemFontServiceMessage::GetFontInstanceKey(result_sender) | - SystemFontServiceMessage::GetFontInstance(_, _, _, _, result_sender) => { + SystemFontServiceMessage::GetFontInstanceKey(_, result_sender) | + SystemFontServiceMessage::GetFontInstance(_, _, _, _, _, result_sender) => { let _ = result_sender.send(FontInstanceKey(IdNamespace(0), 0)); }, - SystemFontServiceMessage::GetFontKey(result_sender) => { + SystemFontServiceMessage::GetFontKey(_, result_sender) => { let _ = result_sender.send(FontKey(IdNamespace(0), 0)); }, SystemFontServiceMessage::Exit(result_sender) => { diff --git a/components/layout/construct_modern.rs b/components/layout/construct_modern.rs index 5ccaf88e20d..7725e94ba8d 100644 --- a/components/layout/construct_modern.rs +++ b/components/layout/construct_modern.rs @@ -63,6 +63,7 @@ impl<'dom> ModernContainerJob<'dom> { true, /* has_first_formatted_line */ false, /* is_single_line_text_box */ builder.info.style.to_bidi_level(), + builder.context.rendering_group_id, )?; let block_formatting_context = BlockFormattingContext::from_block_container( diff --git a/components/layout/context.rs b/components/layout/context.rs index 2267597c487..1436056ce7e 100644 --- a/components/layout/context.rs +++ b/components/layout/context.rs @@ -5,6 +5,7 @@ use std::collections::HashMap; use std::sync::Arc; +use base::id::RenderingGroupId; use embedder_traits::UntrustedNodeAddress; use euclid::Size2D; use fonts::FontContext; @@ -44,6 +45,8 @@ pub(crate) struct LayoutContext<'a> { /// An [`ImageResolver`] used for resolving images during box and fragment /// tree construction. Later passed to display list construction. pub image_resolver: Arc, + + pub rendering_group_id: RenderingGroupId, } pub enum ResolvedImage<'a> { diff --git a/components/layout/flow/construct.rs b/components/layout/flow/construct.rs index 35feab41cde..aa5feefb103 100644 --- a/components/layout/flow/construct.rs +++ b/components/layout/flow/construct.rs @@ -230,6 +230,7 @@ impl<'dom, 'style> BlockContainerBuilder<'dom, 'style> { !self.have_already_seen_first_line_for_text_indent, self.info.node.is_single_line_text_input(), self.info.style.to_bidi_level(), + self.context.rendering_group_id, ) } diff --git a/components/layout/flow/inline/construct.rs b/components/layout/flow/inline/construct.rs index 120a6a5b8b3..779a095fa08 100644 --- a/components/layout/flow/inline/construct.rs +++ b/components/layout/flow/inline/construct.rs @@ -5,6 +5,7 @@ use std::borrow::Cow; use std::char::{ToLowercase, ToUppercase}; +use base::id::RenderingGroupId; use icu_segmenter::WordSegmenter; use itertools::izip; use style::computed_values::white_space_collapse::T as WhiteSpaceCollapse; @@ -475,6 +476,7 @@ impl InlineFormattingContextBuilder { has_first_formatted_line, /* is_single_line_text_input = */ false, default_bidi_level, + layout_context.rendering_group_id, ) } @@ -485,6 +487,7 @@ impl InlineFormattingContextBuilder { has_first_formatted_line: bool, is_single_line_text_input: bool, default_bidi_level: Level, + rendering_group_id: RenderingGroupId, ) -> Option { if self.is_empty { return None; @@ -498,6 +501,7 @@ impl InlineFormattingContextBuilder { has_first_formatted_line, is_single_line_text_input, default_bidi_level, + rendering_group_id, )) } } diff --git a/components/layout/flow/inline/mod.rs b/components/layout/flow/inline/mod.rs index 7034144a79d..3bf9f05782d 100644 --- a/components/layout/flow/inline/mod.rs +++ b/components/layout/flow/inline/mod.rs @@ -79,6 +79,7 @@ use std::mem; use std::rc::Rc; use app_units::{Au, MAX_AU}; +use base::id::RenderingGroupId; use bitflags::bitflags; use construct::InlineFormattingContextBuilder; use fonts::{ByteIndex, FontMetrics, GlyphStore}; @@ -1681,6 +1682,7 @@ impl InlineFormattingContext { has_first_formatted_line: bool, is_single_line_text_input: bool, starting_bidi_level: Level, + rendering_group_id: RenderingGroupId, ) -> Self { // This is to prevent a double borrow. let text_content: String = builder.text_segments.into_iter().collect(); @@ -1699,6 +1701,7 @@ impl InlineFormattingContext { &mut new_linebreaker, &mut font_metrics, &bidi_info, + rendering_group_id, ); }, InlineItem::StartInlineBox(inline_box) => { @@ -1711,6 +1714,7 @@ impl InlineFormattingContext { &font, &mut font_metrics, &layout_context.font_context, + rendering_group_id, )); } }, diff --git a/components/layout/flow/inline/text_run.rs b/components/layout/flow/inline/text_run.rs index e37be9a5687..6e73659198a 100644 --- a/components/layout/flow/inline/text_run.rs +++ b/components/layout/flow/inline/text_run.rs @@ -6,6 +6,7 @@ use std::mem; use std::ops::Range; use app_units::Au; +use base::id::RenderingGroupId; use base::text::is_bidi_control; use fonts::{ FontContext, FontRef, GlyphRun, LAST_RESORT_GLYPH_ADVANCE, ShapingFlags, ShapingOptions, @@ -96,6 +97,7 @@ impl TextRunSegment { bidi_level: Level, fonts: &[FontKeyAndMetrics], font_context: &FontContext, + rendering_group_id: RenderingGroupId, ) -> bool { fn is_specific(script: Script) -> bool { script != Script::Common && script != Script::Inherited @@ -106,7 +108,7 @@ impl TextRunSegment { } let current_font_key_and_metrics = &fonts[self.font_index]; - if new_font.key(font_context) != current_font_key_and_metrics.key || + if new_font.key(rendering_group_id, font_context) != current_font_key_and_metrics.key || new_font.descriptor.pt_size != current_font_key_and_metrics.pt_size { return false; @@ -371,6 +373,7 @@ impl TextRun { linebreaker: &mut LineBreaker, font_cache: &mut Vec, bidi_info: &BidiInfo, + rendering_group_id: RenderingGroupId, ) { let parent_style = self.inline_styles.style.borrow().clone(); let inherited_text_style = parent_style.get_inherited_text().clone(); @@ -403,6 +406,7 @@ impl TextRun { font_cache, bidi_info, &parent_style, + rendering_group_id, ) .into_iter() .map(|(mut segment, font)| { @@ -451,6 +455,7 @@ impl TextRun { font_cache: &mut Vec, bidi_info: &BidiInfo, parent_style: &Arc, + rendering_group_id: RenderingGroupId, ) -> Vec<(TextRunSegment, FontRef)> { let font_group = font_context.font_group(parent_style.clone_font()); let mut current: Option<(TextRunSegment, FontRef)> = None; @@ -497,12 +502,13 @@ impl TextRun { bidi_level, font_cache, font_context, + rendering_group_id, ) { continue; } } - let font_index = add_or_get_font(&font, font_cache, font_context); + let font_index = add_or_get_font(&font, font_cache, font_context, rendering_group_id); // Add the new segment and finish the existing one, if we had one. If the first // characters in the run were control characters we may be creating the first @@ -527,7 +533,8 @@ impl TextRun { // of those cases, just use the first font. if current.is_none() { current = font_group.write().first(font_context).map(|font| { - let font_index = add_or_get_font(&font, font_cache, font_context); + let font_index = + add_or_get_font(&font, font_cache, font_context, rendering_group_id); ( TextRunSegment::new( font_index, @@ -597,8 +604,9 @@ pub(super) fn add_or_get_font( font: &FontRef, ifc_fonts: &mut Vec, font_context: &FontContext, + rendering_group_id: RenderingGroupId, ) -> usize { - let font_instance_key = font.key(font_context); + let font_instance_key = font.key(rendering_group_id, font_context); for (index, ifc_font_info) in ifc_fonts.iter().enumerate() { if ifc_font_info.key == font_instance_key && ifc_font_info.pt_size == font.descriptor.pt_size diff --git a/components/layout/layout_impl.rs b/components/layout/layout_impl.rs index 671e12e5022..77c174b4188 100644 --- a/components/layout/layout_impl.rs +++ b/components/layout/layout_impl.rs @@ -997,6 +997,7 @@ impl LayoutThread { iframe_sizes: Mutex::default(), use_rayon: rayon_pool.is_some(), image_resolver: image_resolver.clone(), + rendering_group_id: self.webview_id.into(), }; let restyle = reflow_request diff --git a/components/servo/webview.rs b/components/servo/webview.rs index c423279d4f4..5ac0f6e91ec 100644 --- a/components/servo/webview.rs +++ b/components/servo/webview.rs @@ -7,7 +7,7 @@ use std::hash::Hash; use std::rc::{Rc, Weak}; use std::time::Duration; -use base::id::WebViewId; +use base::id::{RenderingGroupId, WebViewId}; use compositing::IOCompositor; use compositing_traits::WebViewTrait; use constellation_traits::{EmbedderToConstellationMessage, TraversalDirection}; @@ -90,6 +90,8 @@ pub(crate) struct WebViewInner { focused: bool, animating: bool, cursor: Cursor, + + rendering_group_id: RenderingGroupId, } impl Drop for WebViewInner { @@ -132,16 +134,18 @@ impl WebView { focused: false, animating: false, cursor: Cursor::Pointer, + rendering_group_id: builder.group_id.unwrap_or_default(), }))); let viewport_details = webview.viewport_details(); - servo.compositor.borrow_mut().add_webview( - Box::new(ServoRendererWebView { - weak_handle: webview.weak_handle(), - id, - }), - viewport_details, - ); + let wv = Box::new(ServoRendererWebView { + weak_handle: webview.weak_handle(), + id, + }); + servo + .compositor + .borrow_mut() + .add_webview(wv, viewport_details); servo .webviews @@ -213,6 +217,10 @@ impl WebView { self.inner().id } + pub fn rendering_group_id(&self) -> RenderingGroupId { + self.inner().rendering_group_id + } + pub fn load_status(&self) -> LoadStatus { self.inner().load_status } @@ -604,6 +612,10 @@ impl WebViewTrait for ServoRendererWebView { webview.set_animating(new_value); } } + + fn rendering_group_id(&self) -> Option { + WebView::from_weak_handle(&self.weak_handle).map(|webview| webview.rendering_group_id()) + } } pub struct WebViewBuilder<'servo> { @@ -613,6 +625,7 @@ pub struct WebViewBuilder<'servo> { url: Option, size: Option>, hidpi_scale_factor: Scale, + group_id: Option, } impl<'servo> WebViewBuilder<'servo> { @@ -624,6 +637,7 @@ impl<'servo> WebViewBuilder<'servo> { size: None, hidpi_scale_factor: Scale::new(1.0), delegate: Rc::new(DefaultWebViewDelegate), + group_id: None, } } diff --git a/components/shared/base/id.rs b/components/shared/base/id.rs index c0c9f203201..e8df1c25d13 100644 --- a/components/shared/base/id.rs +++ b/components/shared/base/id.rs @@ -10,7 +10,7 @@ use std::cell::Cell; use std::fmt; use std::marker::PhantomData; use std::num::NonZeroU32; -use std::sync::{Arc, LazyLock}; +use std::sync::{Arc, LazyLock, RwLock}; use malloc_size_of::MallocSizeOfOps; use malloc_size_of_derive::MallocSizeOf; @@ -302,10 +302,10 @@ thread_local!(pub static WEBVIEW_ID: Cell> = #[derive( Clone, Copy, Deserialize, Eq, Hash, MallocSizeOf, Ord, PartialEq, PartialOrd, Serialize, )] -pub struct WebViewId(BrowsingContextId); +pub struct WebViewId(RenderingGroupId, BrowsingContextId); -size_of_test!(WebViewId, 8); -size_of_test!(Option, 8); +size_of_test!(WebViewId, 12); +size_of_test!(Option, 12); impl fmt::Debug for WebViewId { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { @@ -315,13 +315,17 @@ impl fmt::Debug for WebViewId { impl fmt::Display for WebViewId { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "TopLevel{}", self.0) + write!(f, "RenderingGroup {}, TopLevel{}", self.0, self.1) } } impl WebViewId { pub fn new() -> WebViewId { - WebViewId(BrowsingContextId::new()) + WebViewId(RenderingGroupId::default(), BrowsingContextId::new()) + } + + pub fn new_with_rendering_group(rendering_group_id: RenderingGroupId) -> WebViewId { + WebViewId(rendering_group_id, BrowsingContextId::new()) } /// Each script and layout thread should have the top-level browsing context id installed, @@ -335,25 +339,31 @@ impl WebViewId { } pub fn mock_for_testing(browsing_context_id: BrowsingContextId) -> WebViewId { - WebViewId(browsing_context_id) + WebViewId(RenderingGroupId::default(), browsing_context_id) } } impl From for BrowsingContextId { fn from(id: WebViewId) -> BrowsingContextId { + id.1 + } +} + +impl From for RenderingGroupId { + fn from(id: WebViewId) -> RenderingGroupId { id.0 } } impl PartialEq for BrowsingContextId { fn eq(&self, rhs: &WebViewId) -> bool { - self.eq(&rhs.0) + self.eq(&rhs.1) } } impl PartialEq for WebViewId { fn eq(&self, rhs: &BrowsingContextId) -> bool { - self.0.eq(rhs) + self.1.eq(rhs) } } @@ -404,7 +414,10 @@ pub const TEST_BROWSING_CONTEXT_ID: BrowsingContextId = BrowsingContextId { index: TEST_BROWSING_CONTEXT_INDEX, }; -pub const TEST_WEBVIEW_ID: WebViewId = WebViewId(TEST_BROWSING_CONTEXT_ID); +pub const TEST_WEBVIEW_ID: WebViewId = WebViewId( + RenderingGroupId::mock_rendering_id(), + TEST_BROWSING_CONTEXT_ID, +); /// An id for a ScrollTreeNode in the ScrollTree. This contains both the index /// to the node in the tree's array of nodes as well as the corresponding SpatialId @@ -414,3 +427,36 @@ pub struct ScrollTreeNodeId { /// The index of this scroll tree node in the tree's array of nodes. pub index: usize, } + +#[derive( + Clone, Copy, Debug, PartialEq, PartialOrd, Ord, Hash, Eq, Serialize, Deserialize, MallocSizeOf, +)] +pub struct RenderingGroupId(u32); + +impl fmt::Display for RenderingGroupId { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "RenderingGroup: {}", self.0) + } +} + +static RENDER_GROUP_COUNTER: RwLock = RwLock::new(RenderingGroupId(1)); + +impl Default for RenderingGroupId { + fn default() -> Self { + Self(RENDER_GROUP_COUNTER.read().unwrap().0) + } +} + +impl RenderingGroupId { + const fn mock_rendering_id() -> RenderingGroupId { + RenderingGroupId(0) + } + + /// the new rendering group id. The first returned id will be 1. + pub fn new() -> RenderingGroupId { + let mut cur = RENDER_GROUP_COUNTER.write().unwrap(); + let n = RenderingGroupId(cur.0 + 1); + *cur = n; + n + } +} diff --git a/components/shared/compositing/lib.rs b/components/shared/compositing/lib.rs index ebde61789fd..148328d949b 100644 --- a/components/shared/compositing/lib.rs +++ b/components/shared/compositing/lib.rs @@ -7,7 +7,7 @@ use std::fmt::{Debug, Error, Formatter}; use base::Epoch; -use base::id::{PipelineId, WebViewId}; +use base::id::{PipelineId, RenderingGroupId, WebViewId}; use crossbeam_channel::Sender; use embedder_traits::{AnimationState, EventLoopWaker, TouchEventResult}; use log::warn; @@ -143,6 +143,7 @@ pub enum CompositorMsg { usize, usize, GenericSender<(Vec, Vec)>, + RenderingGroupId, ), /// Add a font with the given data and font key. AddFont(FontKey, Arc, u32), @@ -372,12 +373,14 @@ impl CrossProcessCompositorApi { &self, number_of_font_keys: usize, number_of_font_instance_keys: usize, + rendering_group_id: RenderingGroupId, ) -> (Vec, Vec) { let (sender, receiver) = generic_channel::channel().expect("Could not create IPC channel"); let _ = self.0.send(CompositorMsg::GenerateFontKeys( number_of_font_keys, number_of_font_instance_keys, sender, + rendering_group_id, )); receiver.recv().unwrap() } @@ -608,6 +611,7 @@ impl From for ImageData { /// layer. pub trait WebViewTrait { fn id(&self) -> WebViewId; + fn rendering_group_id(&self) -> Option; fn screen_geometry(&self) -> Option; fn set_animating(&self, new_value: bool); } diff --git a/components/shared/fonts/Cargo.toml b/components/shared/fonts/Cargo.toml index be02bf7b7e9..e80e58958cc 100644 --- a/components/shared/fonts/Cargo.toml +++ b/components/shared/fonts/Cargo.toml @@ -13,6 +13,7 @@ path = "lib.rs" [dependencies] atomic_refcell = { workspace = true } +base = { workspace = true } ipc-channel = { workspace = true } log = { workspace = true } malloc_size_of = { workspace = true } diff --git a/components/shared/fonts/system_font_service_proxy.rs b/components/shared/fonts/system_font_service_proxy.rs index 8b32fcedde5..d2a4b2289d2 100644 --- a/components/shared/fonts/system_font_service_proxy.rs +++ b/components/shared/fonts/system_font_service_proxy.rs @@ -4,6 +4,7 @@ use std::collections::HashMap; +use base::id::RenderingGroupId; use ipc_channel::ipc::{self, IpcSender}; use log::debug; use malloc_size_of_derive::MallocSizeOf; @@ -25,14 +26,15 @@ pub enum SystemFontServiceMessage { IpcSender>, ), GetFontInstance( + RenderingGroupId, FontIdentifier, Au, FontInstanceFlags, Vec, IpcSender, ), - GetFontKey(IpcSender), - GetFontInstanceKey(IpcSender), + GetFontKey(RenderingGroupId, IpcSender), + GetFontInstanceKey(RenderingGroupId, IpcSender), CollectMemoryReport(ReportsChan), Exit(IpcSender<()>), Ping, @@ -85,10 +87,12 @@ impl SystemFontServiceProxy { size: Au, flags: FontInstanceFlags, variations: Vec, + rendering_group_id: RenderingGroupId, ) -> FontInstanceKey { let (response_chan, response_port) = ipc::channel().expect("failed to create IPC channel"); self.sender .send(SystemFontServiceMessage::GetFontInstance( + rendering_group_id, identifier, size, flags, @@ -151,22 +155,31 @@ impl SystemFontServiceProxy { templates } - pub fn generate_font_key(&self) -> FontKey { + pub fn generate_font_key(&self, rendering_group_id: RenderingGroupId) -> FontKey { let (result_sender, result_receiver) = ipc::channel().expect("failed to create IPC channel"); self.sender - .send(SystemFontServiceMessage::GetFontKey(result_sender)) + .send(SystemFontServiceMessage::GetFontKey( + rendering_group_id, + result_sender, + )) .expect("failed to send message to system font service"); result_receiver .recv() .expect("Failed to communicate with system font service.") } - pub fn generate_font_instance_key(&self) -> FontInstanceKey { + pub fn generate_font_instance_key( + &self, + rendering_group_id: RenderingGroupId, + ) -> FontInstanceKey { let (result_sender, result_receiver) = ipc::channel().expect("failed to create IPC channel"); self.sender - .send(SystemFontServiceMessage::GetFontInstanceKey(result_sender)) + .send(SystemFontServiceMessage::GetFontInstanceKey( + rendering_group_id, + result_sender, + )) .expect("failed to send message to system font service"); result_receiver .recv()