Allow WebViews and fonts to have a RenderingGroupId. (#39140)

Motivation: The font cache currently has to store a cache of Keys which
need to be given by the webrender instance.
Having a cache for every WebViewId in the future when we have every
webview have the different webrender::DocumentId might be too wasteful
to store this key cache per DocumentId. This proposes to include in the
WebViewId another id, the RenderingGroupId. This id can be easily
changed
to be equivalent to the DocumentId when we support multiple DocumentIds
for a unique Webrender instance.
Additionally this will keep it easier to integrate the currently out of
tree patches for multiple rendering contexts with different webrenders.


Change:
We introduce the RenderingGroupId in the WebViewId and allow a method to
extract it. The font key cache uses this cache
and forwards it to the Compositor when requesting new changes. The
compositor currently ignores this id.
Additionally, the WebView can return the RenderingGroupId. The WebViewId
also has an appropiate constructor for specifying a RenderingGroupId.
Because there currently will be only one RenderingGroupId the
performance will be minimal.


Signed-off-by: Narfinger <Narfinger@users.noreply.github.com>

Testing: This should be covered by WPT tests and normal browsing
behavior works fine.

---------

Signed-off-by: Narfinger <Narfinger@users.noreply.github.com>
This commit is contained in:
Narfinger 2025-09-29 12:01:56 +02:00 committed by GitHub
parent 32b656adf4
commit e64f021550
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
18 changed files with 240 additions and 63 deletions

1
Cargo.lock generated
View file

@ -2817,6 +2817,7 @@ name = "fonts_traits"
version = "0.0.1"
dependencies = [
"atomic_refcell",
"base",
"dwrote",
"ipc-channel",
"log",

View file

@ -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<FontKey>, Vec<FontInstanceKey>)>,
_rendering_group_id: RenderingGroupId,
) {
let font_keys = (0..number_of_font_keys)
.map(|_| self.global.borrow().webrender_api.generate_font_key())

View file

@ -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<Shaper>,
cached_shape_data: RwLock<CachedShapeData>,
pub(crate) font_instance_key: OnceLock<FontInstanceKey>,
font_instance_key: RwLock<FxHashMap<RenderingGroupId, FontInstanceKey>>,
/// 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::<usize>()
}
}
@ -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

View file

@ -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<FontVariation>,
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,

View file

@ -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<SystemFontServiceMessage>,
local_families: FontStore,
compositor_api: CrossProcessCompositorApi,
webrender_fonts: HashMap<FontIdentifier, FontKey>,
font_instances: HashMap<(FontKey, Au, Vec<FontVariation>), FontInstanceKey>,
// keys already have the IdNamespace for webrender
webrender_fonts: HashMap<(FontIdentifier, RenderingGroupId), FontKey>,
font_instances: HashMap<(FontKey, Au, Vec<FontVariation>, 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<FontKey>,
/// TODO: We currently do not delete the free keys if a `WebView` is removed.
free_font_keys: FxHashMap<RenderingGroupId, Vec<FontKey>>,
/// 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<FontInstanceKey>,
free_font_instance_keys: FxHashMap<RenderingGroupId, Vec<FontInstanceKey>>,
}
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<FontVariation>,
) -> 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,

View file

@ -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) => {

View file

@ -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(

View file

@ -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<ImageResolver>,
pub rendering_group_id: RenderingGroupId,
}
pub enum ResolvedImage<'a> {

View file

@ -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,
)
}

View file

@ -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<InlineFormattingContext> {
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,
))
}
}

View file

@ -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,
));
}
},

View file

@ -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<FontKeyAndMetrics>,
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<FontKeyAndMetrics>,
bidi_info: &BidiInfo,
parent_style: &Arc<ComputedValues>,
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<FontKeyAndMetrics>,
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

View file

@ -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

View file

@ -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<RenderingGroupId> {
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<Url>,
size: Option<PhysicalSize<u32>>,
hidpi_scale_factor: Scale<f32, DeviceIndependentPixel, DevicePixel>,
group_id: Option<RenderingGroupId>,
}
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,
}
}

View file

@ -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<Option<WebViewId>> =
#[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<WebViewId>, 8);
size_of_test!(WebViewId, 12);
size_of_test!(Option<WebViewId>, 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<WebViewId> for BrowsingContextId {
fn from(id: WebViewId) -> BrowsingContextId {
id.1
}
}
impl From<WebViewId> for RenderingGroupId {
fn from(id: WebViewId) -> RenderingGroupId {
id.0
}
}
impl PartialEq<WebViewId> for BrowsingContextId {
fn eq(&self, rhs: &WebViewId) -> bool {
self.eq(&rhs.0)
self.eq(&rhs.1)
}
}
impl PartialEq<BrowsingContextId> 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<RenderingGroupId> = 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
}
}

View file

@ -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<FontKey>, Vec<FontInstanceKey>)>,
RenderingGroupId,
),
/// Add a font with the given data and font key.
AddFont(FontKey, Arc<IpcSharedMemory>, u32),
@ -372,12 +373,14 @@ impl CrossProcessCompositorApi {
&self,
number_of_font_keys: usize,
number_of_font_instance_keys: usize,
rendering_group_id: RenderingGroupId,
) -> (Vec<FontKey>, Vec<FontInstanceKey>) {
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<SerializableImageData> for ImageData {
/// layer.
pub trait WebViewTrait {
fn id(&self) -> WebViewId;
fn rendering_group_id(&self) -> Option<RenderingGroupId>;
fn screen_geometry(&self) -> Option<ScreenGeometry>;
fn set_animating(&self, new_value: bool);
}

View file

@ -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 }

View file

@ -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<Vec<FontTemplate>>,
),
GetFontInstance(
RenderingGroupId,
FontIdentifier,
Au,
FontInstanceFlags,
Vec<FontVariation>,
IpcSender<FontInstanceKey>,
),
GetFontKey(IpcSender<FontKey>),
GetFontInstanceKey(IpcSender<FontInstanceKey>),
GetFontKey(RenderingGroupId, IpcSender<FontKey>),
GetFontInstanceKey(RenderingGroupId, IpcSender<FontInstanceKey>),
CollectMemoryReport(ReportsChan),
Exit(IpcSender<()>),
Ping,
@ -85,10 +87,12 @@ impl SystemFontServiceProxy {
size: Au,
flags: FontInstanceFlags,
variations: Vec<FontVariation>,
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()