commit dad13aef3397c48e5db96173af761f8e6022baf2
parent b598f6fc9a6ce7ec3696f7e3b235da380824f3af
Author: Nicolas Silva <nical@fastmail.com>
Date: Tue, 9 Dec 2025 08:19:05 +0000
Bug 2000393 - Add QuadPrimitive and QuadSegment. r=gw
Differential Revision: https://phabricator.services.mozilla.com/D272810
Diffstat:
6 files changed, 93 insertions(+), 38 deletions(-)
diff --git a/gfx/wr/webrender/src/box_shadow.rs b/gfx/wr/webrender/src/box_shadow.rs
@@ -101,8 +101,8 @@ impl PatternBuilder for BoxShadowTemplate {
let pattern_prim_address_f = quad::write_prim_blocks(
&mut state.frame_gpu_data.f32,
- pattern_rect,
- pattern_rect,
+ pattern_rect.to_untyped(),
+ pattern_rect.to_untyped(),
color_pattern.base_color,
color_pattern.texture_input.task_id,
&[],
diff --git a/gfx/wr/webrender/src/gpu_types.rs b/gfx/wr/webrender/src/gpu_types.rs
@@ -6,6 +6,7 @@ use api::{AlphaType, PremultipliedColorF, YuvFormat, YuvRangedColorSpace};
use api::units::*;
use euclid::HomogeneousVector;
use crate::composite::{CompositeFeatures, CompositorClip};
+use crate::quad::LayoutOrDeviceRect;
use crate::segment::EdgeAaSegmentMask;
use crate::spatial_tree::{SpatialTree, SpatialNodeIndex};
use crate::internal_types::{FastHashMap, FrameVec, FrameMemory};
@@ -14,7 +15,7 @@ use crate::render_task::RenderTaskAddress;
use crate::render_task_graph::RenderTaskId;
use crate::renderer::{GpuBufferAddress, GpuBufferBuilderF, GpuBufferHandle, GpuBufferWriterF, GpuBufferDataF, ShaderColorMode};
use std::i32;
-use crate::util::{MatrixHelpers, TransformedRectKind};
+use crate::util::{MatrixHelpers, ScaleOffset, TransformedRectKind};
use glyph_rasterizer::SubpixelDirection;
use crate::util::pack_as_float;
@@ -646,13 +647,49 @@ impl From<QuadInstance> for PrimitiveInstanceData {
}
}
+/// Matches QuadPrimitive in ps_quad.glsl
+pub struct QuadPrimitive {
+ pub bounds: LayoutOrDeviceRect,
+ pub clip: LayoutOrDeviceRect,
+ // TODO: This gets translated into a Rect just before upload.
+ // It would be better to send the gpu buffer address to the shader.
+ pub input_task: RenderTaskId,
+ pub pattern_scale_offset: ScaleOffset,
+ /// Base color of the pattern.
+ pub color: PremultipliedColorF,
+}
+
+impl GpuBufferDataF for QuadPrimitive {
+ const NUM_BLOCKS: usize = 5;
+ fn write(&self, writer: &mut GpuBufferWriterF) {
+ writer.push_one(self.bounds);
+ writer.push_one(self.clip);
+ writer.push_render_task(self.input_task);
+ writer.push_one(self.pattern_scale_offset);
+ writer.push_one(self.color);
+ }
+}
+
+pub const VECS_PER_QUAD_SEGMENT: usize = 2;
+
+/// Matches QuadSegment in ps_quad.glsl
#[derive(Debug)]
#[cfg_attr(feature = "capture", derive(Serialize))]
pub struct QuadSegment {
- pub rect: LayoutRect,
+ pub rect: LayoutOrDeviceRect,
+ // TODO: This gets translated into a Rect just before upload.
+ // It would be better to send the gpu buffer address to the shader.
pub task_id: RenderTaskId,
}
+impl GpuBufferDataF for QuadSegment {
+ const NUM_BLOCKS: usize = VECS_PER_QUAD_SEGMENT;
+ fn write(&self, writer: &mut GpuBufferWriterF) {
+ writer.push_one(self.rect);
+ writer.push_render_task(self.task_id)
+ }
+}
+
#[derive(Copy, Debug, Clone, PartialEq)]
#[cfg_attr(feature = "capture", derive(Serialize))]
#[cfg_attr(feature = "replay", derive(Deserialize))]
diff --git a/gfx/wr/webrender/src/prepare.rs b/gfx/wr/webrender/src/prepare.rs
@@ -1006,7 +1006,7 @@ fn prepare_interned_prim_for_render(
}
let pic_surface_index = pic.raster_config.as_ref().unwrap().surface_index;
- let prim_local_rect = frame_state
+ let prim_local_rect: LayoutRect = frame_state
.surfaces[pic_surface_index.0]
.clipped_local_rect
.cast_unit();
@@ -1015,8 +1015,8 @@ fn prepare_interned_prim_for_render(
let prim_address_f = quad::write_prim_blocks(
&mut frame_state.frame_gpu_data.f32,
- prim_local_rect,
- prim_instance.vis.clip_chain.local_clip_rect,
+ prim_local_rect.to_untyped(),
+ prim_instance.vis.clip_chain.local_clip_rect.to_untyped(),
pattern.base_color,
pattern.texture_input.task_id,
&[],
diff --git a/gfx/wr/webrender/src/quad.rs b/gfx/wr/webrender/src/quad.rs
@@ -9,7 +9,7 @@ use crate::batch::{BatchKey, BatchKind, BatchTextures};
use crate::clip::{ClipChainInstance, ClipIntern, ClipItemKind, ClipNodeRange, ClipSpaceConversion, ClipStore};
use crate::command_buffer::{CommandBufferIndex, PrimitiveCommand, QuadFlags};
use crate::frame_builder::{FrameBuildingContext, FrameBuildingState, PictureContext, PictureState};
-use crate::gpu_types::{PrimitiveInstanceData, QuadInstance, QuadSegment, TransformPaletteId, ZBufferId};
+use crate::gpu_types::{PrimitiveInstanceData, QuadInstance, QuadPrimitive, QuadSegment, TransformPaletteId, ZBufferId};
use crate::intern::DataStore;
use crate::internal_types::TextureSource;
use crate::pattern::{Pattern, PatternBuilder, PatternBuilderContext, PatternBuilderState, PatternKind, PatternShaderInput};
@@ -24,6 +24,10 @@ use crate::surface::SurfaceBuilder;
use crate::util::{extract_inner_rect_k, MaxRect, ScaleOffset};
use crate::visibility::compute_conservative_visible_rect;
+/// This type reflects the unfortunate situation with quad coordinates where we
+/// sometimes use layout and sometimes device coordinates.
+pub type LayoutOrDeviceRect = api::euclid::default::Box2D<f32>;
+
const MIN_AA_SEGMENTS_SIZE: f32 = 4.0;
const MIN_QUAD_SPLIT_SIZE: f32 = 256.0;
const MAX_TILES_PER_QUAD: usize = 4;
@@ -335,8 +339,8 @@ fn prepare_quad_impl(
let main_prim_address = write_prim_blocks(
&mut frame_state.frame_gpu_data.f32,
- *local_rect,
- clip_chain.local_clip_rect,
+ local_rect.to_untyped(),
+ clip_chain.local_clip_rect.to_untyped(),
pattern.base_color,
pattern.texture_input.task_id,
&[],
@@ -395,8 +399,8 @@ fn prepare_quad_impl(
let main_prim_address = write_prim_blocks(
&mut frame_state.frame_gpu_data.f32,
- *local_rect,
- clip_chain.local_clip_rect,
+ local_rect.to_untyped(),
+ clip_chain.local_clip_rect.to_untyped(),
pattern.base_color,
pattern.texture_input.task_id,
&[],
@@ -425,7 +429,7 @@ fn prepare_quad_impl(
&mut frame_state.surface_builder,
);
- let rect = clipped_surface_rect.to_f32().cast_unit();
+ let rect = clipped_surface_rect.to_f32().to_untyped();
add_composite_prim(
pattern_builder.get_base_color(&ctx),
prim_instance_index,
@@ -652,8 +656,8 @@ fn prepare_quad_impl(
let main_prim_address = write_prim_blocks(
&mut state.frame_gpu_data.f32,
- *local_rect,
- clip_chain.local_clip_rect,
+ local_rect.to_untyped(),
+ clip_chain.local_clip_rect.to_untyped(),
pattern.base_color,
pattern.texture_input.task_id,
&[],
@@ -704,8 +708,8 @@ fn prepare_quad_impl(
&pattern,
local_to_device.inverse(),
prim_instance_index,
- device_prim_rect.cast_unit(),
- clip_coverage_rect.cast_unit(),
+ device_prim_rect.to_untyped(),
+ clip_coverage_rect.to_untyped(),
pattern.is_opaque,
frame_state,
targets,
@@ -717,7 +721,7 @@ fn prepare_quad_impl(
add_composite_prim(
pattern_builder.get_base_color(&ctx),
prim_instance_index,
- clip_coverage_rect.cast_unit(),
+ clip_coverage_rect.to_untyped(),
frame_state,
targets,
&scratch.quad_indirect_segments,
@@ -829,8 +833,8 @@ fn prepare_quad_impl(
let main_prim_address = write_prim_blocks(
&mut state.frame_gpu_data.f32,
- *local_rect,
- clip_chain.local_clip_rect,
+ local_rect.to_untyped(),
+ clip_chain.local_clip_rect.to_untyped(),
pattern.base_color,
pattern.texture_input.task_id,
&[],
@@ -1031,8 +1035,8 @@ fn add_pattern_prim(
pattern: &Pattern,
pattern_transform: ScaleOffset,
prim_instance_index: PrimitiveInstanceIndex,
- rect: LayoutRect,
- clip_rect: LayoutRect,
+ rect: LayoutOrDeviceRect,
+ clip_rect: LayoutOrDeviceRect,
is_opaque: bool,
frame_state: &mut FrameBuildingState,
targets: &[CommandBufferIndex],
@@ -1076,7 +1080,7 @@ fn add_pattern_prim(
fn add_composite_prim(
base_color: ColorF,
prim_instance_index: PrimitiveInstanceIndex,
- rect: LayoutRect,
+ rect: LayoutOrDeviceRect,
frame_state: &mut FrameBuildingState,
targets: &[CommandBufferIndex],
segments: &[QuadSegment],
@@ -1121,24 +1125,25 @@ fn add_composite_prim(
pub fn write_prim_blocks(
builder: &mut GpuBufferBuilderF,
- prim_rect: LayoutRect,
- clip_rect: LayoutRect,
+ prim_rect: LayoutOrDeviceRect,
+ clip_rect: LayoutOrDeviceRect,
pattern_base_color: ColorF,
pattern_texture_input: RenderTaskId,
segments: &[QuadSegment],
- scale_offset: ScaleOffset,
+ pattern_scale_offset: ScaleOffset,
) -> GpuBufferAddress {
let mut writer = builder.write_blocks(5 + segments.len() * 2);
- writer.push_one(prim_rect);
- writer.push_one(clip_rect);
- writer.push_render_task(pattern_texture_input);
- writer.push_one(scale_offset);
- writer.push_one(pattern_base_color.premultiplied());
+ writer.push(&QuadPrimitive {
+ bounds: prim_rect,
+ clip: clip_rect,
+ input_task: pattern_texture_input,
+ pattern_scale_offset,
+ color: pattern_base_color.premultiplied(),
+ });
for segment in segments {
- writer.push_one(segment.rect);
- writer.push_render_task(segment.task_id)
+ writer.push(segment);
}
writer.finish()
diff --git a/gfx/wr/webrender/src/render_target.rs b/gfx/wr/webrender/src/render_target.rs
@@ -1053,12 +1053,12 @@ fn build_mask_tasks(
for tile in clip_store.visible_mask_tiles(&clip_instance) {
let clip_prim_address = quad::write_prim_blocks(
&mut gpu_buffer_builder.f32,
- rect,
- rect,
+ rect.to_untyped(),
+ rect.to_untyped(),
pattern.base_color,
pattern.texture_input.task_id,
&[QuadSegment {
- rect: tile.tile_rect,
+ rect: tile.tile_rect.to_untyped(),
task_id: tile.task_id,
}],
ScaleOffset::identity(),
@@ -1123,8 +1123,8 @@ fn build_mask_tasks(
let main_prim_address = quad::write_prim_blocks(
&mut gpu_buffer_builder.f32,
- task_world_rect.cast_unit(),
- task_world_rect.cast_unit(),
+ task_world_rect.to_untyped(),
+ task_world_rect.to_untyped(),
pattern.base_color,
pattern.texture_input.task_id,
&[],
diff --git a/gfx/wr/webrender/src/renderer/gpu_buffer.rs b/gfx/wr/webrender/src/renderer/gpu_buffer.rs
@@ -172,6 +172,19 @@ impl Into<GpuBufferBlockF> for LayoutRect {
}
}
+impl Into<GpuBufferBlockF> for crate::quad::LayoutOrDeviceRect {
+ fn into(self) -> GpuBufferBlockF {
+ GpuBufferBlockF {
+ data: [
+ self.min.x,
+ self.min.y,
+ self.max.x,
+ self.max.y,
+ ],
+ }
+ }
+}
+
impl Into<GpuBufferBlockF> for ScaleOffset {
fn into(self) -> GpuBufferBlockF {
GpuBufferBlockF {