commit 1acc4435576ca5ed679d6277403da97b7d5bed98
parent 86b60597ed89fdd437f97225d0c7a16216db3c41
Author: Nicolas Silva <nical@fastmail.com>
Date: Wed, 19 Nov 2025 22:17:35 +0000
Bug 2000393 - Add LinearGradientBrushData. r=gw
Also lie a bit less about the coordinate space of the gradient parameters (which are actually layout coordinates despite previously being stored as device coordinates).
Differential Revision: https://phabricator.services.mozilla.com/D272813
Diffstat:
4 files changed, 59 insertions(+), 44 deletions(-)
diff --git a/gfx/wr/webrender/res/brush_linear_gradient.glsl b/gfx/wr/webrender/res/brush_linear_gradient.glsl
@@ -13,15 +13,15 @@ flat varying mediump vec2 v_scale_dir;
#ifdef WR_VERTEX_SHADER
-struct Gradient {
+struct LinearGradientBrushData {
vec4 start_end_point;
int extend_mode;
vec2 stretch_size;
};
-Gradient fetch_gradient(int address) {
+LinearGradientBrushData fetch_gradient(int address) {
vec4 data[2] = fetch_from_gpu_buffer_2f(address);
- return Gradient(
+ return LinearGradientBrushData(
data[0],
int(data[1].x),
data[1].yz
@@ -40,7 +40,7 @@ void brush_vs(
int brush_flags,
vec4 texel_rect
) {
- Gradient gradient = fetch_gradient(prim_address);
+ LinearGradientBrushData gradient = fetch_gradient(prim_address);
write_gradient_vertex(
vi,
diff --git a/gfx/wr/webrender/src/gpu_types.rs b/gfx/wr/webrender/src/gpu_types.rs
@@ -2,7 +2,7 @@
* 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::{AlphaType, PremultipliedColorF, YuvFormat, YuvRangedColorSpace};
+use api::{AlphaType, ExtendMode, PremultipliedColorF, YuvFormat, YuvRangedColorSpace};
use api::units::*;
use euclid::HomogeneousVector;
use crate::composite::{CompositeFeatures, CompositorClip};
@@ -710,6 +710,32 @@ impl GpuBufferDataF for QuadSegment {
}
}
+/// Matches LinearGradientBrushData in brush_linear_gradient.glsl
+pub struct LinearGradientBrushData {
+ pub start: LayoutPoint,
+ pub end: LayoutPoint,
+ pub extend_mode: ExtendMode,
+ pub stretch_size: LayoutSize,
+}
+
+impl GpuBufferDataF for LinearGradientBrushData {
+ const NUM_BLOCKS: usize = 2;
+ fn write(&self, writer: &mut GpuBufferWriterF) {
+ writer.push_one([
+ self.start.x,
+ self.start.y,
+ self.end.x,
+ self.end.y,
+ ]);
+ writer.push_one([
+ pack_as_float(self.extend_mode as u32),
+ self.stretch_size.width,
+ self.stretch_size.height,
+ 0.0,
+ ]);
+ }
+}
+
#[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
@@ -17,11 +17,11 @@ use crate::image_tiling::{self, Repetition};
use crate::border::{get_max_scale_for_border, build_border_instances};
use crate::clip::{ClipStore, ClipNodeRange};
use crate::pattern::Pattern;
-use crate::renderer::{GpuBufferAddress, GpuBufferBuilderF, GpuBufferWriterF};
+use crate::renderer::{GpuBufferAddress, GpuBufferBuilderF, GpuBufferWriterF, GpuBufferDataF};
use crate::spatial_tree::{SpatialNodeIndex, SpatialTree};
use crate::clip::{ClipDataStore, ClipNodeFlags, ClipChainInstance, ClipItemKind};
use crate::frame_builder::{FrameBuildingContext, FrameBuildingState, PictureContext, PictureState};
-use crate::gpu_types::BrushFlags;
+use crate::gpu_types::{BrushFlags, LinearGradientBrushData};
use crate::internal_types::{FastHashMap, PlaneSplitAnchor, Filter};
use crate::picture::{ClusterFlags, PictureCompositeMode, PicturePrimitive, SliceId};
use crate::picture::{PrimitiveList, PrimitiveCluster, SurfaceIndex, TileCacheInstance, SubpixelMode, Picture3DContext};
@@ -35,7 +35,7 @@ use crate::render_task_cache::RenderTaskCacheKeyKind;
use crate::render_task_cache::{RenderTaskCacheKey, to_cache_size, RenderTaskParent};
use crate::render_task::{EmptyTask, MaskSubPass, RenderTask, RenderTaskKind, SubPass};
use crate::segment::SegmentBuilder;
-use crate::util::{clamp_to_scale_factor, pack_as_float, ScaleOffset};
+use crate::util::{clamp_to_scale_factor, ScaleOffset};
use crate::visibility::{compute_conservative_visible_rect, PrimitiveVisibility, VisibilityState};
@@ -786,20 +786,13 @@ fn prepare_interned_prim_for_render(
&mut scratch.gradient_tiles,
&frame_context.spatial_tree,
Some(&mut |_, gpu_buffer| {
- let mut writer = gpu_buffer.write_blocks(2);
- writer.push_one([
- prim_data.start_point.x,
- prim_data.start_point.y,
- prim_data.end_point.x,
- prim_data.end_point.y,
- ]);
- writer.push_one([
- pack_as_float(prim_data.extend_mode as u32),
- prim_data.stretch_size.width,
- prim_data.stretch_size.height,
- 0.0,
- ]);
-
+ let mut writer = gpu_buffer.write_blocks(LinearGradientBrushData::NUM_BLOCKS);
+ writer.push(&LinearGradientBrushData {
+ start: prim_data.start_point,
+ end: prim_data.end_point,
+ extend_mode: prim_data.extend_mode,
+ stretch_size: prim_data.stretch_size,
+ });
writer.finish()
}),
);
diff --git a/gfx/wr/webrender/src/prim_store/gradient/linear.rs b/gfx/wr/webrender/src/prim_store/gradient/linear.rs
@@ -12,7 +12,7 @@ use euclid::approxeq::ApproxEq;
use euclid::{point2, vec2, size2};
use api::{ExtendMode, GradientStop, LineOrientation, PremultipliedColorF, ColorF, ColorU};
use api::units::*;
-use crate::gpu_types::ImageBrushPrimitiveData;
+use crate::gpu_types::{ImageBrushPrimitiveData, LinearGradientBrushData};
use crate::pattern::{Pattern, PatternBuilder, PatternBuilderContext, PatternBuilderState, PatternKind, PatternShaderInput, PatternTextureInput};
use crate::prim_store::gradient::{gpu_gradient_stops_blocks, write_gpu_gradient_stops_tree, write_gpu_gradient_stops_linear, GradientKind};
use crate::scene_building::IsVisible;
@@ -29,7 +29,6 @@ use crate::render_task_graph::RenderTaskId;
use crate::render_task_cache::{RenderTaskCacheKeyKind, RenderTaskCacheKey, RenderTaskParent};
use crate::renderer::{GpuBufferAddress, GpuBufferBuilder};
use crate::segment::EdgeAaSegmentMask;
-use crate::util::pack_as_float;
use super::{stops_and_min_alpha, GradientStopKey, GradientGpuBlockBuilder, apply_gradient_local_clip};
use std::ops::{Deref, DerefMut};
use std::mem::swap;
@@ -85,8 +84,8 @@ impl InternDebug for LinearGradientKey {}
pub struct LinearGradientTemplate {
pub common: PrimTemplateCommonData,
pub extend_mode: ExtendMode,
- pub start_point: DevicePoint,
- pub end_point: DevicePoint,
+ pub start_point: LayoutPoint,
+ pub end_point: LayoutPoint,
pub task_size: DeviceIntSize,
pub scale: DeviceVector2D,
pub stretch_size: LayoutSize,
@@ -398,8 +397,8 @@ impl From<LinearGradientKey> for LinearGradientTemplate {
// should be drawn in.
let stops_opacity = PrimitiveOpacity::from_alpha(min_alpha);
- let start_point = DevicePoint::new(item.start_point.x, item.start_point.y);
- let end_point = DevicePoint::new(item.end_point.x, item.end_point.y);
+ let start_point = LayoutPoint::new(item.start_point.x, item.start_point.y);
+ let end_point = LayoutPoint::new(item.end_point.x, item.end_point.y);
let tile_spacing: LayoutSize = item.tile_spacing.into();
let stretch_size: LayoutSize = item.stretch_size.into();
let mut task_size: DeviceSize = stretch_size.cast_unit();
@@ -506,18 +505,12 @@ impl LinearGradientTemplate {
});
} else {
// We are using the gradient brush.
- writer.push_one([
- self.start_point.x,
- self.start_point.y,
- self.end_point.x,
- self.end_point.y,
- ]);
- writer.push_one([
- pack_as_float(self.extend_mode as u32),
- self.stretch_size.width,
- self.stretch_size.height,
- 0.0,
- ]);
+ writer.push(&LinearGradientBrushData {
+ start: self.start_point,
+ end: self.end_point,
+ extend_mode: self.extend_mode,
+ stretch_size: self.stretch_size,
+ });
}
// write_segment_gpu_blocks
@@ -598,8 +591,11 @@ impl LinearGradientTemplate {
rg_builder.add().init(RenderTask::new_dynamic(
self.task_size,
RenderTaskKind::LinearGradient(LinearGradientTask {
- start: self.start_point,
- end: self.end_point,
+ // Cached brush gradients are rasteried with 1 layout
+ // pixel = 1 device pixel (regardless of potential
+ // scaling factors).
+ start: self.start_point.cast_unit(),
+ end: self.end_point.cast_unit(),
scale: self.scale,
extend_mode: self.extend_mode,
stops: stops.unwrap(),
@@ -781,8 +777,8 @@ pub struct LinearGradientCacheKey {
}
pub fn linear_gradient_pattern(
- start: DevicePoint,
- end: DevicePoint,
+ start: LayoutPoint,
+ end: LayoutPoint,
extend_mode: ExtendMode,
stops: &[GradientStop],
is_software: bool,