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
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 35 KiB |
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 85 KiB After Width: | Height: | Size: 85 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|