Bug 1917493 - Enable quad box shadows on a subset of outset box-shadows r=gfx-reviewers,nical

We'll incrementally enable it on a wider range of content once we
resolve the unrelated pre-existing timing-related intermittent failures
that are tickled by these changes.

Differential Revision: https://phabricator.services.mozilla.com/D221413
This commit is contained in:
Glenn Watson 2024-09-22 20:03:09 +00:00
parent 5f63b3b97d
commit 0a430dcd09
12 changed files with 299 additions and 25 deletions

View File

@ -405,8 +405,7 @@ impl<'a> SceneBuilder<'a> {
// box-shadow support will be added to this path as a follow up.
if is_root_coord_system &&
clip_mode == BoxShadowClipMode::Outset &&
blur_radius < 32.0 &&
false {
blur_radius < 32.0 {
// Make sure corners don't overlap.
ensure_no_corner_overlap(&mut shadow_radius, shadow_rect.size());
@ -446,7 +445,7 @@ impl<'a> SceneBuilder<'a> {
let inner_shadow_rect = shadow_rect.inflate(-sig3, -sig3);
let outer_shadow_rect = shadow_rect.inflate( sig3, sig3);
let inner_shadow_rect = extract_inner_rect_k(&inner_shadow_rect, &shadow_radius, 0.5).unwrap_or(LayoutRect::zero());
let inner_shadow_rect = extract_inner_rect_k(&inner_shadow_rect, &shadow_radius, 1.0).unwrap_or(LayoutRect::zero());
let prim = BoxShadow {
color: color.into(),
@ -581,3 +580,104 @@ fn adjust_radius_for_box_shadow(border_radius: f32, spread_amount: f32) -> f32 {
0.0
}
}
pub struct BoxShadowSegment {
pub color: ColorF,
pub blur_radius: f32,
pub clip: ClipDataHandle,
pub pattern_rect: LayoutRect,
}
impl PatternBuilder for BoxShadowSegment {
fn build(
&self,
_sub_rect: Option<DeviceRect>,
ctx: &crate::pattern::PatternBuilderContext,
state: &mut crate::pattern::PatternBuilderState,
) -> Pattern {
let raster_spatial_node_index = ctx.spatial_tree.root_reference_frame_index();
let task_size = self.pattern_rect.size().cast_unit().to_i32();
let content_origin = self.pattern_rect.min.cast_unit();
let scale_factor = DevicePixelScale::new(1.0);
let uv_rect_kind = UvRectKind::Rect;
let blur_radius = self.blur_radius * scale_factor.0;
let clips_range = state.clip_store.push_clip_instance(self.clip);
let color_pattern = Pattern::color(self.color);
let pattern_prim_address_f = quad::write_prim_blocks(
&mut state.frame_gpu_data.f32,
self.pattern_rect,
self.pattern_rect,
color_pattern.base_color,
color_pattern.texture_input.task_id,
&[],
ScaleOffset::identity(),
);
let pattern_task_id = state.rg_builder.add().init(RenderTask::new_dynamic(
task_size,
RenderTaskKind::Prim(PrimTask {
pattern: color_pattern.kind,
pattern_input: color_pattern.shader_input,
raster_spatial_node_index,
device_pixel_scale: DevicePixelScale::new(1.0),
content_origin,
prim_address_f: pattern_prim_address_f,
transform_id: TransformPaletteId::IDENTITY,
edge_flags: EdgeAaSegmentMask::empty(),
quad_flags: QuadFlags::APPLY_RENDER_TASK_CLIP | QuadFlags::IGNORE_DEVICE_PIXEL_SCALE,
prim_needs_scissor_rect: false,
texture_input: color_pattern.texture_input.task_id,
}),
));
let masks = MaskSubPass {
clip_node_range: clips_range,
prim_spatial_node_index: raster_spatial_node_index,
prim_address_f: pattern_prim_address_f,
};
let task = state.rg_builder.get_task_mut(pattern_task_id);
task.add_sub_pass(SubPass::Masks { masks });
let blur_task_v = state.rg_builder.add().init(RenderTask::new_dynamic(
task_size,
RenderTaskKind::VerticalBlur(BlurTask {
blur_std_deviation: blur_radius,
target_kind: RenderTargetKind::Color,
blur_region: task_size,
}),
));
state.rg_builder.add_dependency(blur_task_v, pattern_task_id);
let blur_task_h = state.rg_builder.add().init(RenderTask::new_dynamic(
task_size,
RenderTaskKind::HorizontalBlur(BlurTask {
blur_std_deviation: blur_radius,
target_kind: RenderTargetKind::Color,
blur_region: task_size,
}),
).with_uv_rect_kind(uv_rect_kind));
state.rg_builder.add_dependency(blur_task_h, blur_task_v);
Pattern::texture(
blur_task_h,
self.color,
)
}
fn get_base_color(
&self,
_ctx: &crate::pattern::PatternBuilderContext,
) -> ColorF {
self.color
}
fn use_shared_pattern(
&self,
) -> bool {
false
}
}

View File

@ -142,3 +142,33 @@ impl Pattern {
}
}
}
// A reusable pattern builder for a segment of a larger primitive that can be
// drawn as a solid color
pub struct SolidColorSegment {
pub color: ColorF,
}
impl PatternBuilder for SolidColorSegment {
fn build(
&self,
_sub_rect: Option<DeviceRect>,
_ctx: &crate::pattern::PatternBuilderContext,
_state: &mut crate::pattern::PatternBuilderState,
) -> Pattern {
Pattern::color(self.color)
}
fn get_base_color(
&self,
_ctx: &crate::pattern::PatternBuilderContext,
) -> ColorF {
self.color
}
fn use_shared_pattern(
&self,
) -> bool {
true
}
}

View File

@ -11,12 +11,13 @@ use api::{BoxShadowClipMode, BorderStyle, ClipMode};
use api::units::*;
use euclid::Scale;
use smallvec::SmallVec;
use crate::box_shadow::BoxShadowSegment;
use crate::composite::CompositorSurfaceKind;
use crate::command_buffer::{CommandBufferIndex, PrimitiveCommand};
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::clip::{ClipNodeRange, ClipStore};
use crate::pattern::{Pattern, SolidColorSegment};
use crate::spatial_tree::{SpatialNodeIndex, SpatialTree};
use crate::clip::{ClipDataStore, ClipNodeFlags, ClipChainInstance, ClipItemKind};
use crate::frame_builder::{FrameBuildingContext, FrameBuildingState, PictureContext, PictureState};
@ -324,21 +325,164 @@ fn prepare_interned_prim_for_render(
PrimitiveInstanceKind::BoxShadow { data_handle } => {
let prim_data = &mut data_stores.box_shadow[*data_handle];
quad::prepare_quad(
prim_data,
&prim_data.kind.outer_shadow_rect,
prim_instance_index,
prim_spatial_node_index,
&prim_instance.vis.clip_chain,
device_pixel_scale,
frame_context,
pic_context,
targets,
&data_stores.clip,
frame_state,
pic_state,
scratch,
);
// If there isn't an inner shadow rect, draw as a single primitive
if prim_data.kind.inner_shadow_rect.is_empty() {
quad::prepare_quad(
prim_data,
&prim_data.kind.outer_shadow_rect,
prim_instance_index,
prim_spatial_node_index,
&prim_instance.vis.clip_chain,
device_pixel_scale,
frame_context,
pic_context,
targets,
&data_stores.clip,
frame_state,
pic_state,
scratch,
);
} else {
// If we have an inner shadow rect, draw that as a solid color
// segment, and box-shadow segments for the outer segments
let dirty_world_rect = frame_state.current_dirty_region().combined;
let inner_segment = SolidColorSegment {
color: prim_data.kind.color,
};
quad::prepare_quad(
&inner_segment,
&prim_data.kind.inner_shadow_rect,
prim_instance_index,
prim_spatial_node_index,
&prim_instance.vis.clip_chain,
device_pixel_scale,
frame_context,
pic_context,
targets,
&data_stores.clip,
frame_state,
pic_state,
scratch,
);
let p0 = prim_data.kind.outer_shadow_rect.min;
let p1 = prim_data.kind.inner_shadow_rect.min;
let p3 = prim_data.kind.outer_shadow_rect.max;
let p2 = prim_data.kind.inner_shadow_rect.max;
let outer_rects = [
// Corners
LayoutRect::new(
LayoutPoint::new(p0.x, p0.y),
LayoutPoint::new(p1.x, p1.y),
),
LayoutRect::new(
LayoutPoint::new(p2.x, p0.y),
LayoutPoint::new(p3.x, p1.y),
),
LayoutRect::new(
LayoutPoint::new(p2.x, p2.y),
LayoutPoint::new(p3.x, p3.y),
),
LayoutRect::new(
LayoutPoint::new(p0.x, p2.y),
LayoutPoint::new(p1.x, p3.y),
),
// Top + Bottom
LayoutRect::new(
LayoutPoint::new(p1.x, p0.y),
LayoutPoint::new(p2.x, p1.y),
),
LayoutRect::new(
LayoutPoint::new(p1.x, p2.y),
LayoutPoint::new(p2.x, p3.y),
),
// Left + Right
LayoutRect::new(
LayoutPoint::new(p0.x, p1.y),
LayoutPoint::new(p1.x, p2.y),
),
LayoutRect::new(
LayoutPoint::new(p2.x, p1.y),
LayoutPoint::new(p3.x, p2.y),
),
];
for (i, rect) in outer_rects.iter().enumerate() {
// Edge (non-corner) segments are the same across the
// entire axis, so we can draw a small portion of them
// and stretch when drawing the segment, to reduce
// number of blurred pixels, which is important for swgl.
let fixed_size = 4.0;
let pattern_rect = match i {
0 ..= 3 => *rect,
4 ..= 5 => {
LayoutRect::new(
rect.min,
LayoutPoint::new(rect.min.x + fixed_size, rect.max.y),
)
},
6 ..= 7 => {
LayoutRect::new(
rect.min,
LayoutPoint::new(rect.max.x, rect.min.y + fixed_size),
)
}
_ => unreachable!(),
};
let shadow_segment = BoxShadowSegment {
color: prim_data.kind.color,
blur_radius: prim_data.kind.blur_radius,
clip: prim_data.kind.clip,
pattern_rect,
};
frame_state.clip_store.set_active_clips_from_clip_chain(
&prim_instance.vis.clip_chain,
prim_spatial_node_index,
&frame_context.spatial_tree,
&data_stores.clip,
);
if let Some(segment_clip_chain) = frame_state
.clip_store
.build_clip_chain_instance(
*rect,
&pic_state.map_local_to_pic,
&pic_state.map_pic_to_world,
&frame_context.spatial_tree,
frame_state.gpu_cache,
frame_state.resource_cache,
device_pixel_scale,
&dirty_world_rect,
&mut data_stores.clip,
frame_state.rg_builder,
false,
) {
quad::prepare_quad(
&shadow_segment,
rect,
prim_instance_index,
prim_spatial_node_index,
&segment_clip_chain,
device_pixel_scale,
frame_context,
pic_context,
targets,
&data_stores.clip,
frame_state,
pic_state,
scratch,
);
}
}
}
return;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 85 KiB

After

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

View File

@ -11,7 +11,7 @@ random != boxshadow-blur-2.html boxshadow-blur-2-notref.html # fixedpoint divisi
== boxshadow-rounding.html boxshadow-rounding-ref.html
# One uses old path, one uses WR box shadow.
== boxshadow-button.html boxshadow-button-ref.html
fuzzy(0-14,0-179) fuzzy-if(swgl&&!Android,0-1,0-952) fuzzy-if(useDrawSnapshot&&swgl,14-14,54-54) == boxshadow-large-border-radius.html boxshadow-large-border-radius-ref.html # Bug 1209649
fuzzy(0-14,0-179) fuzzy-if(swgl&&!Android,0-1,0-2400) fuzzy-if(useDrawSnapshot&&swgl,14-14,54-54) == boxshadow-large-border-radius.html boxshadow-large-border-radius-ref.html # Bug 1209649
== boxshadow-fileupload.html boxshadow-fileupload-ref.html
fuzzy(13-19,28-51) == boxshadow-inner-basic.html boxshadow-inner-basic-ref.svg
@ -29,7 +29,7 @@ fuzzy-if(useDrawSnapshot,1-1,1197-2400) == boxshadow-opacity.html boxshadow-opac
fuzzy(0-3,0-500) fuzzy-if(winWidget,0-2,0-1080) == boxshadow-border-radius-int.html boxshadow-border-radius-int-ref.html
== boxshadow-inset-neg-spread.html about:blank
== boxshadow-inset-neg-spread2.html boxshadow-inset-neg-spread2-ref.html
fuzzy(0-26,0-3610) fuzzy-if(winWidget,0-26,0-5910) fuzzy-if(!(swgl&&Android),0-6,378-4500) == boxshadow-rotated.html boxshadow-rotated-ref.html # Bug 1211264
fuzzy(0-7,0-3150) == boxshadow-rotated.html boxshadow-rotated-ref.html # Bug 1211264
== boxshadow-inset-large-border-radius.html boxshadow-inset-large-border-radius-ref.html
# fuzzy due to blur going inside, but as long as it's essentially black instead of a light gray its ok.
@ -40,7 +40,7 @@ fuzzy(12-15,9400-13267) == boxshadow-inset-large-offset.html boxshadow-inset-lar
== overflow-not-scrollable-2.html overflow-not-scrollable-2-ref.html
fuzzy(0-1,0-655) == 611574-1.html 611574-1-ref.html
fuzzy(0-4,0-144) fuzzy-if(winWidget,0-1,0-36) == 611574-2.html 611574-2-ref.html
fuzzy(0-16,0-10) == fieldset.html fieldset-ref.html # minor anti-aliasing problem on Windows
fuzzy(0-2,0-220) == fieldset.html fieldset-ref.html # minor anti-aliasing problem on Windows
fuzzy(0-16,0-10) == fieldset-inset.html fieldset-inset-ref.html # minor anti-aliasing problem on Windows
== 1178575.html 1178575-ref.html
== 1178575-2.html 1178575-2-ref.html

View File

@ -2087,7 +2087,7 @@ fuzzy(0-2,0-21184) == 1626259-2.html 1626259-2-ref.html
!= 1642583-1.html 1642583-1-ref.html
== 1642603-1.html 1642603-1-ref.html
== 1645549-2.html 1645549-2-ref.html
== 1641769-1.html 1641769-1-ref.html
fuzzy(0-3,0-6200) == 1641769-1.html 1641769-1-ref.html
fuzzy(0-2,0-96600) == 1648282-1a.html 1648282-1-ref.html
fuzzy(0-2,0-96600) == 1648282-1b.html 1648282-1-ref.html
!= 1672137-1.html 1672137-1-notref.html

View File

@ -1,4 +1,4 @@
[range-tick-marks-02.html]
bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1803108
fuzzy:
if (os == "mac") and not nightly_build: maxDifference=0-4;totalPixels=0-35
maxDifference=0-4;totalPixels=0-300