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:
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 { .. } => {