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

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