tor-browser

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

commit c00ab92de8d3865179fbf95d8ac06deeb7f22038
parent a5133cb167280d25f9a5c0e4efad8bbc9347af50
Author: Nicolas Silva <nical@fastmail.com>
Date:   Mon, 15 Dec 2025 10:53:22 +0000

Bug 1998913 - Part 12 - Move composite mode gpu block logic into picture_composite_mode.rs. r=gfx-reviewers,jnicol

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

Diffstat:
Mgfx/wr/webrender/src/picture.rs | 106++++++++-----------------------------------------------------------------------
Mgfx/wr/webrender/src/picture_composite_mode.rs | 102++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
Mgfx/wr/webrender/src/prepare.rs | 44+++++++++++++++++++++-----------------------
3 files changed, 130 insertions(+), 122 deletions(-)

diff --git a/gfx/wr/webrender/src/picture.rs b/gfx/wr/webrender/src/picture.rs @@ -94,7 +94,7 @@ //! blend the overlay tile (this is not always optimal right now, but will be //! improved as a follow up). -use api::{PremultipliedColorF, RasterSpace}; +use api::RasterSpace; use api::{DebugFlags, ColorF, PrimitiveFlags, SnapshotInfo}; use api::units::*; use crate::command_buffer::PrimitiveCommand; @@ -109,8 +109,6 @@ use euclid::{vec3, Scale, Vector2D, Box2D}; use crate::internal_types::{FastHashMap, PlaneSplitter, Filter}; use crate::internal_types::{PlaneSplitterIndex, PlaneSplitAnchor, TextureSource}; use crate::frame_builder::{FrameBuildingContext, FrameBuildingState, PictureState, PictureContext}; -use crate::gpu_types::{BrushSegmentGpuData, ImageBrushPrimitiveData}; -use crate::svg_filter::FilterGraphOp; use plane_split::{Clipper, Polygon}; use crate::prim_store::{PictureIndex, PrimitiveInstance, PrimitiveInstanceKind}; use crate::prim_store::PrimitiveScratchBuffer; @@ -1376,108 +1374,24 @@ impl PicturePrimitive { } } - pub fn prepare_for_render( + pub fn write_gpu_blocks( &mut self, frame_state: &mut FrameBuildingState, data_stores: &mut DataStores, - ) -> bool { + ) { let raster_config = match self.raster_config { Some(ref mut raster_config) => raster_config, None => { - return true + return; } }; - // TODO(gw): Almost all of the Picture types below use extra_gpu_data - // to store the same type of data. The exception is the filter - // with a ColorMatrix, which stores the color matrix here. It's - // probably worth tidying this code up to be a bit more consistent. - // Perhaps store the color matrix after the common data, even though - // it's not used by that shader. - - match raster_config.composite_mode { - PictureCompositeMode::TileCache { .. } => {} - PictureCompositeMode::Filter(Filter::Blur { .. }) => {} - PictureCompositeMode::Filter(Filter::DropShadows(ref shadows)) => { - self.extra_gpu_data.resize(shadows.len(), GpuBufferAddress::INVALID); - for (shadow, extra_handle) in shadows.iter().zip(self.extra_gpu_data.iter_mut()) { - let mut writer = frame_state.frame_gpu_data.f32.write_blocks(5); - let surface = &frame_state.surfaces[raster_config.surface_index.0]; - let prim_rect = surface.clipped_local_rect.cast_unit(); - - // Basic brush primitive header is (see end of prepare_prim_for_render_inner in prim_store.rs) - // [brush specific data] - // [segment_rect, segment data] - let (blur_inflation_x, blur_inflation_y) = surface.clamp_blur_radius( - shadow.blur_radius, - shadow.blur_radius, - ); - - let shadow_rect = prim_rect.inflate( - blur_inflation_x * BLUR_SAMPLE_SCALE, - blur_inflation_y * BLUR_SAMPLE_SCALE, - ).translate(shadow.offset); - - // ImageBrush colors - writer.push(&ImageBrushPrimitiveData { - color: shadow.color.premultiplied(), - background_color: PremultipliedColorF::WHITE, - stretch_size: shadow_rect.size(), - }); - - writer.push(&BrushSegmentGpuData { - local_rect: shadow_rect, - extra_data: [0.0; 4], - }); - - *extra_handle = writer.finish(); - } - } - PictureCompositeMode::Filter(ref filter) => { - match *filter { - Filter::ColorMatrix(ref m) => { - if self.extra_gpu_data.is_empty() { - self.extra_gpu_data.push(GpuBufferAddress::INVALID); - } - let mut writer = frame_state.frame_gpu_data.f32.write_blocks(5); - for i in 0..5 { - writer.push_one([m[i*4], m[i*4+1], m[i*4+2], m[i*4+3]]); - } - self.extra_gpu_data[0] = writer.finish(); - } - Filter::Flood(ref color) => { - if self.extra_gpu_data.is_empty() { - self.extra_gpu_data.push(GpuBufferAddress::INVALID); - } - let mut writer = frame_state.frame_gpu_data.f32.write_blocks(1); - writer.push_one(color.to_array()); - self.extra_gpu_data[0] = writer.finish(); - } - _ => {} - } - } - PictureCompositeMode::ComponentTransferFilter(handle) => { - let filter_data = &mut data_stores.filter_data[handle]; - filter_data.write_gpu_blocks(&mut frame_state.frame_gpu_data.f32); - } - PictureCompositeMode::MixBlend(..) | - PictureCompositeMode::Blit(_) | - PictureCompositeMode::IntermediateSurface => {} - PictureCompositeMode::SVGFEGraph(ref filters) => { - // Update interned filter data - for (_node, op) in filters { - match op { - FilterGraphOp::SVGFEComponentTransferInterned { handle, creates_pixels: _ } => { - let filter_data = &mut data_stores.filter_data[*handle]; - filter_data.write_gpu_blocks(&mut frame_state.frame_gpu_data.f32); - } - _ => {} - } - } - } - } - - true + raster_config.composite_mode.write_gpu_blocks( + &frame_state.surfaces[raster_config.surface_index.0], + &mut frame_state.frame_gpu_data, + data_stores, + &mut self.extra_gpu_data + ); } #[cold] diff --git a/gfx/wr/webrender/src/picture_composite_mode.rs b/gfx/wr/webrender/src/picture_composite_mode.rs @@ -2,20 +2,20 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -use api::{ColorF, ColorU, SnapshotInfo, PropertyBinding, PropertyBindingId}; +use api::{ColorF, ColorU, PremultipliedColorF, PropertyBinding, PropertyBindingId, SnapshotInfo}; use api::units::*; use crate::prim_store::image::AdjustedImageSource; use crate::{render_task_graph::RenderTaskGraphBuilder, renderer::GpuBufferBuilderF}; use crate::box_shadow::BLUR_SAMPLE_SCALE; use crate::frame_builder::{FrameBuildingContext, FrameBuildingState}; -use crate::gpu_types::{BlurEdgeMode, UvRectKind}; +use crate::gpu_types::{BlurEdgeMode, BrushSegmentGpuData, ImageBrushPrimitiveData, UvRectKind}; use crate::intern::ItemUid; use crate::render_backend::DataStores; use crate::render_task_graph::RenderTaskId; use crate::render_target::RenderTargetKind; use crate::render_task::{BlurTask, RenderTask, BlurTaskCache}; use crate::render_task::RenderTaskKind; -use crate::renderer::{BlendMode, GpuBufferAddress}; +use crate::renderer::{BlendMode, GpuBufferAddress, GpuBufferBuilder}; use crate::space::SpaceMapper; use crate::spatial_tree::SpatialTree; use crate::surface::{SurfaceDescriptor, SurfaceInfo, calculate_screen_uv}; @@ -167,6 +167,102 @@ impl PictureCompositeMode { } } + pub fn write_gpu_blocks( + &self, + surface: &SurfaceInfo, + gpu_buffers: &mut GpuBufferBuilder, + data_stores: &mut DataStores, + extra_gpu_data: &mut SmallVec<[GpuBufferAddress; 1]>, + ) { + // TODO(gw): Almost all of the composite modes below use extra_gpu_data + // to store the same type of data. The exception is the filter + // with a ColorMatrix, which stores the color matrix here. It's + // probably worth tidying this code up to be a bit more consistent. + // Perhaps store the color matrix after the common data, even though + // it's not used by that shader. + + match *self { + PictureCompositeMode::TileCache { .. } => {} + PictureCompositeMode::Filter(Filter::Blur { .. }) => {} + PictureCompositeMode::Filter(Filter::DropShadows(ref shadows)) => { + extra_gpu_data.resize(shadows.len(), GpuBufferAddress::INVALID); + for (shadow, extra_handle) in shadows.iter().zip(extra_gpu_data.iter_mut()) { + let mut writer = gpu_buffers.f32.write_blocks(5); + let prim_rect = surface.clipped_local_rect.cast_unit(); + + // Basic brush primitive header is (see end of prepare_prim_for_render_inner in prim_store.rs) + // [brush specific data] + // [segment_rect, segment data] + let (blur_inflation_x, blur_inflation_y) = surface.clamp_blur_radius( + shadow.blur_radius, + shadow.blur_radius, + ); + + let shadow_rect = prim_rect.inflate( + blur_inflation_x * BLUR_SAMPLE_SCALE, + blur_inflation_y * BLUR_SAMPLE_SCALE, + ).translate(shadow.offset); + + // ImageBrush colors + writer.push(&ImageBrushPrimitiveData { + color: shadow.color.premultiplied(), + background_color: PremultipliedColorF::WHITE, + stretch_size: shadow_rect.size(), + }); + + writer.push(&BrushSegmentGpuData { + local_rect: shadow_rect, + extra_data: [0.0; 4], + }); + + *extra_handle = writer.finish(); + } + } + PictureCompositeMode::Filter(ref filter) => { + match *filter { + Filter::ColorMatrix(ref m) => { + if extra_gpu_data.is_empty() { + extra_gpu_data.push(GpuBufferAddress::INVALID); + } + let mut writer = gpu_buffers.f32.write_blocks(5); + for i in 0..5 { + writer.push_one([m[i*4], m[i*4+1], m[i*4+2], m[i*4+3]]); + } + extra_gpu_data[0] = writer.finish(); + } + Filter::Flood(ref color) => { + if extra_gpu_data.is_empty() { + extra_gpu_data.push(GpuBufferAddress::INVALID); + } + let mut writer = gpu_buffers.f32.write_blocks(1); + writer.push_one(color.to_array()); + extra_gpu_data[0] = writer.finish(); + } + _ => {} + } + } + PictureCompositeMode::ComponentTransferFilter(handle) => { + let filter_data = &mut data_stores.filter_data[handle]; + filter_data.write_gpu_blocks(&mut gpu_buffers.f32); + } + PictureCompositeMode::MixBlend(..) | + PictureCompositeMode::Blit(_) | + PictureCompositeMode::IntermediateSurface => {} + PictureCompositeMode::SVGFEGraph(ref filters) => { + // Update interned filter data + for (_node, op) in filters { + match op { + FilterGraphOp::SVGFEComponentTransferInterned { handle, creates_pixels: _ } => { + let filter_data = &mut data_stores.filter_data[*handle]; + filter_data.write_gpu_blocks(&mut gpu_buffers.f32); + } + _ => {} + } + } + } + } + } + /// Returns a static str describing the type of PictureCompositeMode (and /// filter type if applicable) pub fn kind(&self) -> &'static str { diff --git a/gfx/wr/webrender/src/prepare.rs b/gfx/wr/webrender/src/prepare.rs @@ -1157,31 +1157,29 @@ fn prepare_interned_prim_for_render( } } - if pic.prepare_for_render( + pic.write_gpu_blocks( frame_state, data_stores, - ) { - if let Picture3DContext::In { root_data: None, plane_splitter_index, .. } = pic.context_3d { - let dirty_rect = frame_state.current_dirty_region().combined; - let visibility_node = frame_state.current_dirty_region().visibility_spatial_node; - let splitter = &mut frame_state.plane_splitters[plane_splitter_index.0]; - let surface_index = pic.raster_config.as_ref().unwrap().surface_index; - let surface = &frame_state.surfaces[surface_index.0]; - let local_prim_rect = surface.clipped_local_rect.cast_unit(); - - PicturePrimitive::add_split_plane( - splitter, - frame_context.spatial_tree, - prim_spatial_node_index, - visibility_node, - local_prim_rect, - &prim_instance.vis.clip_chain.local_clip_rect, - dirty_rect, - plane_split_anchor, - ); - } - } else { - prim_instance.clear_visibility(); + ); + + if let Picture3DContext::In { root_data: None, plane_splitter_index, .. } = pic.context_3d { + let dirty_rect = frame_state.current_dirty_region().combined; + let visibility_node = frame_state.current_dirty_region().visibility_spatial_node; + let splitter = &mut frame_state.plane_splitters[plane_splitter_index.0]; + let surface_index = pic.raster_config.as_ref().unwrap().surface_index; + let surface = &frame_state.surfaces[surface_index.0]; + let local_prim_rect = surface.clipped_local_rect.cast_unit(); + + PicturePrimitive::add_split_plane( + splitter, + frame_context.spatial_tree, + prim_spatial_node_index, + visibility_node, + local_prim_rect, + &prim_instance.vis.clip_chain.local_clip_rect, + dirty_rect, + plane_split_anchor, + ); } } PrimitiveInstanceKind::BackdropCapture { .. } => {