tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit f058a705aed4e359d6136c6fd6b07e8f565238ac
parent 3f08434492003e9e056d21407693653a0025dc9c
Author: Sotaro Ikeda <sotaro.ikeda.g@gmail.com>
Date:   Mon, 15 Dec 2025 07:36:53 +0000

Bug 2005103 - Use overlay with video rendering with rounded rects if possible r=gfx-reviewers,gw

Power usage of overlay could be more efficient than underlay.

Differential Revision: https://phabricator.services.mozilla.com/D275922

Diffstat:
Mgfx/wr/webrender/src/composite.rs | 10+++++++++-
Mgfx/wr/webrender/src/tile_cache/mod.rs | 112+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
Mlayout/reftests/border-radius/reftest.list | 2+-
3 files changed, 120 insertions(+), 4 deletions(-)

diff --git a/gfx/wr/webrender/src/composite.rs b/gfx/wr/webrender/src/composite.rs @@ -214,6 +214,7 @@ pub struct ExternalSurfaceDescriptor { pub local_clip_rect: PictureRect, pub clip_rect: DeviceRect, pub transform_index: CompositorTransformIndex, + pub compositor_clip_index: Option<CompositorClipIndex>, pub image_rendering: ImageRendering, pub z_id: ZBufferId, pub dependency: ExternalSurfaceDependency, @@ -1106,6 +1107,13 @@ impl CompositeState { // For each compositor surface that was promoted, build the // information required for the compositor to draw it for compositor_surface in &sub_slice.compositor_surfaces { + let compositor_clip_index = if compositor_surface.descriptor.compositor_clip_index.is_some() { + assert!(tile_cache.compositor_clip.is_none()); + compositor_surface.descriptor.compositor_clip_index + } else { + tile_cache.compositor_clip + }; + self.push_compositor_surface( &compositor_surface.descriptor, compositor_surface.is_opaque, @@ -1113,7 +1121,7 @@ impl CompositeState { resource_cache, gpu_buffer, deferred_resolves, - tile_cache.compositor_clip, + compositor_clip_index, ); } } diff --git a/gfx/wr/webrender/src/tile_cache/mod.rs b/gfx/wr/webrender/src/tile_cache/mod.rs @@ -1842,6 +1842,9 @@ impl TileCacheInstance { surface_kind: CompositorSurfaceKind, pic_coverage_rect: PictureRect, frame_context: &FrameVisibilityContext, + data_stores: &DataStores, + clip_store: &ClipStore, + composite_state: &CompositeState, force: bool, ) -> Result<CompositorSurfaceKind, SurfacePromotionFailure> { use SurfacePromotionFailure::*; @@ -1859,7 +1862,33 @@ impl TileCacheInstance { // If a complex clip is being applied to this primitive, it can't be // promoted directly to a compositor surface. if prim_clip_chain.needs_mask { - return Err(OverlayNeedsMask); + let mut is_supported_rounded_rect = false; + if let CompositorKind::Layer { .. } = composite_state.compositor_kind { + if prim_clip_chain.clips_range.count == 1 && self.compositor_clip.is_none() { + let clip_instance = clip_store.get_instance_from_range(&prim_clip_chain.clips_range, 0); + let clip_node = &data_stores.clip[clip_instance.handle]; + + if let ClipItemKind::RoundedRectangle { ref radius, mode: ClipMode::Clip, rect, .. } = clip_node.item.kind { + let max_corner_width = radius.top_left.width + .max(radius.bottom_left.width) + .max(radius.top_right.width) + .max(radius.bottom_right.width); + let max_corner_height = radius.top_left.height + .max(radius.bottom_left.height) + .max(radius.top_right.height) + .max(radius.bottom_right.height); + + if max_corner_width <= 0.5 * rect.size().width && + max_corner_height <= 0.5 * rect.size().height { + is_supported_rounded_rect = true; + } + } + } + } + + if !is_supported_rounded_rect { + return Err(OverlayNeedsMask); + } } } CompositorSurfaceKind::Underlay => { @@ -1943,9 +1972,12 @@ impl TileCacheInstance { prim_info: &mut PrimitiveDependencyInfo, flags: PrimitiveFlags, local_prim_rect: LayoutRect, + prim_clip_chain: &ClipChainInstance, prim_spatial_node_index: SpatialNodeIndex, pic_coverage_rect: PictureRect, frame_context: &FrameVisibilityContext, + data_stores: &DataStores, + clip_store: &ClipStore, image_dependencies: &[ImageDependency;3], api_keys: &[ImageKey; 3], resource_cache: &mut ResourceCache, @@ -1975,9 +2007,12 @@ impl TileCacheInstance { prim_info, flags, local_prim_rect, + prim_clip_chain, prim_spatial_node_index, pic_coverage_rect, frame_context, + data_stores, + clip_store, ExternalSurfaceDependency::Yuv { image_dependencies: *image_dependencies, color_space, @@ -1999,9 +2034,12 @@ impl TileCacheInstance { prim_info: &mut PrimitiveDependencyInfo, flags: PrimitiveFlags, local_prim_rect: LayoutRect, + prim_clip_chain: &ClipChainInstance, prim_spatial_node_index: SpatialNodeIndex, pic_coverage_rect: PictureRect, frame_context: &FrameVisibilityContext, + data_stores: &DataStores, + clip_store: &ClipStore, image_dependency: ImageDependency, api_key: ImageKey, resource_cache: &mut ResourceCache, @@ -2033,9 +2071,12 @@ impl TileCacheInstance { prim_info, flags, local_prim_rect, + prim_clip_chain, prim_spatial_node_index, pic_coverage_rect, frame_context, + data_stores, + clip_store, ExternalSurfaceDependency::Rgb { image_dependency, }, @@ -2056,9 +2097,12 @@ impl TileCacheInstance { prim_info: &mut PrimitiveDependencyInfo, flags: PrimitiveFlags, local_prim_rect: LayoutRect, + prim_clip_chain: &ClipChainInstance, prim_spatial_node_index: SpatialNodeIndex, pic_coverage_rect: PictureRect, frame_context: &FrameVisibilityContext, + data_stores: &DataStores, + clip_store: &ClipStore, dependency: ExternalSurfaceDependency, api_keys: &[ImageKey; 3], resource_cache: &mut ResourceCache, @@ -2157,6 +2201,57 @@ impl TileCacheInstance { let clip_rect = (world_clip_rect * frame_context.global_device_pixel_scale).round(); + + let mut compositor_clip_index = None; + + if surface_kind == CompositorSurfaceKind::Overlay && + prim_clip_chain.needs_mask { + assert!(prim_clip_chain.clips_range.count == 1); + assert!(self.compositor_clip.is_none()); + + let clip_instance = clip_store.get_instance_from_range(&prim_clip_chain.clips_range, 0); + let clip_node = &data_stores.clip[clip_instance.handle]; + if let ClipItemKind::RoundedRectangle { radius, mode: ClipMode::Clip, rect, .. } = clip_node.item.kind { + // Map the clip in to device space. We know from the shared + // clip creation logic it's in root coord system, so only a + // 2d axis-aligned transform can apply. For example, in the + // case of a pinch-zoom effect. + let map = ClipSpaceConversion::new( + frame_context.root_spatial_node_index, + clip_node.item.spatial_node_index, + frame_context.root_spatial_node_index, + frame_context.spatial_tree, + ); + + let (rect, radius) = match map { + ClipSpaceConversion::Local => { + (rect.cast_unit(), radius) + } + ClipSpaceConversion::ScaleOffset(scale_offset) => { + ( + scale_offset.map_rect(&rect), + BorderRadius { + top_left: scale_offset.map_size(&radius.top_left), + top_right: scale_offset.map_size(&radius.top_right), + bottom_left: scale_offset.map_size(&radius.bottom_left), + bottom_right: scale_offset.map_size(&radius.bottom_right), + }, + ) + } + ClipSpaceConversion::Transform(..) => { + unreachable!(); + } + }; + + compositor_clip_index = Some(composite_state.register_clip( + rect, + radius, + )); + } else { + unreachable!(); + } + } + if surface_size.width >= MAX_COMPOSITOR_SURFACES_SIZE || surface_size.height >= MAX_COMPOSITOR_SURFACES_SIZE { return Err(SizeTooLarge); @@ -2265,6 +2360,7 @@ impl TileCacheInstance { image_rendering, clip_rect, transform_index: compositor_transform_index, + compositor_clip_index: compositor_clip_index, z_id: ZBufferId::invalid(), native_surface_id, update_params, @@ -2593,6 +2689,9 @@ impl TileCacheInstance { CompositorSurfaceKind::Overlay, pic_coverage_rect, frame_context, + data_stores, + clip_store, + composite_state, false); } @@ -2608,9 +2707,12 @@ impl TileCacheInstance { &mut prim_info, image_key.common.flags, local_prim_rect, + prim_clip_chain, prim_spatial_node_index, pic_coverage_rect, frame_context, + data_stores, + clip_store, ImageDependency { key: image_data.key, generation: resource_cache.get_image_generation(image_data.key), @@ -2682,6 +2784,9 @@ impl TileCacheInstance { kind, pic_coverage_rect, frame_context, + data_stores, + clip_store, + composite_state, force); if promotion_result.is_ok() { break; @@ -2724,9 +2829,12 @@ impl TileCacheInstance { &mut prim_info, prim_data.common.flags, local_prim_rect, + prim_clip_chain, prim_spatial_node_index, pic_coverage_rect, frame_context, + data_stores, + clip_store, &image_dependencies, &prim_data.kind.yuv_key, resource_cache, @@ -3352,7 +3460,7 @@ impl SubSlice { } } -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Debug)] enum SurfacePromotionFailure { ImageWaitingOnYuvImage, NotPremultipliedAlpha, diff --git a/layout/reftests/border-radius/reftest.list b/layout/reftests/border-radius/reftest.list @@ -50,7 +50,7 @@ skip-if(Android&&emulator) == clipping-5-canvas.html clipping-5-refc.html fuzzy-if(winWidget,0-1,0-5) == clipping-5-image.html clipping-5-refi.html fuzzy(0-1,0-77) == clipping-5-overflow-hidden.html clipping-5-ref.html fuzzy(0-1,0-97) == clipping-5-refi.html clipping-5-ref.html -skip-if(Android&&emulator) fuzzy(0-1,0-77) fuzzy-if(useDrawSnapshot,1-1,97-97) == clipping-5-refc.html clipping-5-ref.html # bug 732535 +skip-if(Android&&emulator) fuzzy(0-1,0-77) fuzzy-if(useDrawSnapshot,1-1,97-97) fuzzy-if(winWidget,0-255,0-113) == clipping-5-refc.html clipping-5-ref.html # bug 732535 fuzzy(0-21,0-76) fuzzy-if(winWidget,0-144,0-335) == clipping-6.html clipping-6-ref.html # PaintedLayer and MaskLayer with transforms that aren't identical fuzzy(0-28,0-97) == clipping-7.html clipping-7-ref.html # ColorLayer and MaskLayer with transforms that aren't identical. Reference image rendered without using layers (which causes fuzzy failures). == clipping-and-zindex-1.html clipping-and-zindex-1-ref.html