Bug 1734346 - Support backdrops with simple rounded-rect clip cases. r=gfx-reviewers,nical

This allows picture slice backdrops to be supported when they contain
rounded-rect clip(s) that are in the same coordinate system as the
primitive. This is the common case, and allows subpixel AA to be
used in bookmark menu and other popups that are part of the current
Gecko UI.

Differential Revision: https://phabricator.services.mozilla.com/D128156
This commit is contained in:
Glenn Watson 2021-10-12 23:38:23 +00:00
parent 2570aaff04
commit 601f48038d
5 changed files with 110 additions and 3 deletions

View File

@ -1228,6 +1228,66 @@ impl ClipStore {
}
}
/// Given a clip-chain instance, return a safe rect within the visible region
/// that can be assumed to be unaffected by clip radii. Returns None if it
/// encounters any complex cases, just handling rounded rects in the same
/// coordinate system as the clip-chain for now.
pub fn get_inner_rect_for_clip_chain(
&self,
clip_chain: &ClipChainInstance,
clip_data_store: &ClipDataStore,
spatial_tree: &SpatialTree,
) -> Option<PictureRect> {
let mut inner_rect = clip_chain.pic_clip_rect;
let clip_instances = &self
.clip_node_instances[clip_chain.clips_range.to_range()];
for clip_instance in clip_instances {
// Don't handle mapping between coord systems for now
if !clip_instance.flags.contains(ClipNodeFlags::SAME_COORD_SYSTEM) {
return None;
}
let clip_node = &clip_data_store[clip_instance.handle];
match clip_node.item.kind {
// Ignore any clips which are complex or impossible to calculate
// inner rects for now
ClipItemKind::Rectangle { mode: ClipMode::ClipOut, .. } |
ClipItemKind::Image { .. } |
ClipItemKind::BoxShadow { .. } |
ClipItemKind::RoundedRectangle { mode: ClipMode::ClipOut, .. } => {
return None;
}
// Normal Clip rects are already handled by the clip-chain pic_clip_rect,
// no need to do anything here
ClipItemKind::Rectangle { mode: ClipMode::Clip, .. } => {}
ClipItemKind::RoundedRectangle { mode: ClipMode::Clip, rect, radius } => {
// Get an inner rect for the rounded-rect clip
let local_inner_rect = match extract_inner_rect_safe(&rect, &radius) {
Some(rect) => rect,
None => return None,
};
// Map it from local -> picture space
let mapper = SpaceMapper::new_with_target(
clip_chain.pic_spatial_node_index,
clip_instance.spatial_node_index,
PictureRect::max_rect(),
spatial_tree,
);
// Accumulate in to the inner_rect, in case there are multiple rounded-rect clips
if let Some(pic_inner_rect) = mapper.map(&local_inner_rect) {
inner_rect = inner_rect.intersection(&pic_inner_rect).unwrap_or(PictureRect::zero());
}
}
}
}
Some(inner_rect)
}
/// The main interface external code uses. Given a local primitive, positioning
/// information, and a clip chain id, build an optimized clip chain instance.
pub fn build_clip_chain_instance(

View File

@ -3706,7 +3706,7 @@ impl TileCacheInstance {
let sub_slice = &mut self.sub_slices[sub_slice_index];
if let Some(backdrop_candidate) = backdrop_candidate {
if let Some(mut backdrop_candidate) = backdrop_candidate {
let is_suitable_backdrop = match backdrop_candidate.kind {
Some(BackdropKind::Clear) => {
// Clear prims are special - they always end up in their own slice,
@ -3739,8 +3739,19 @@ impl TileCacheInstance {
if sub_slice_index == 0 &&
is_suitable_backdrop &&
sub_slice.compositor_surfaces.is_empty() &&
!prim_clip_chain.needs_mask {
sub_slice.compositor_surfaces.is_empty() {
// If the backdrop candidate has a clip-mask, try to extract an opaque inner
// rect that is safe to use for subpixel rendering
if prim_clip_chain.needs_mask {
backdrop_candidate.opaque_rect = clip_store
.get_inner_rect_for_clip_chain(
prim_clip_chain,
&data_stores.clip,
frame_context.spatial_tree,
)
.unwrap_or(PictureRect::zero());
}
if backdrop_candidate.opaque_rect.contains_box(&self.backdrop.opaque_rect) {
self.backdrop.opaque_rect = backdrop_candidate.opaque_rect;

View File

@ -82,3 +82,4 @@ fuzzy(1,15) platform(linux) force_subpixel_aa_where_possible(false) == text-fixe
# the main goal of the test is that everything is in the same place, at the same scale, clipped the same way,
# despite 4x on-the-fly scale change.
skip_on(android) fuzzy-range(<=3,*21700,<=20,*3500,<=119,*590) fuzzy-if(platform(swgl),108,24907) == raster_root_C_8192.yaml raster_root_C_ref.yaml
== subpx-bg-mask.yaml subpx-bg-mask-ref.yaml

View File

@ -0,0 +1,8 @@
---
root:
items:
- text: "A"
origin: 20 190
size: 180
color: black
font: "FreeSans.ttf"

View File

@ -0,0 +1,27 @@
# Verify that text on a picture cache slice where the background
# has a rounded-rect clip correct enables subpixel AA
---
root:
items:
- type: rect
bounds: [0, 0, 100, 100]
color: white
- type: scroll-frame
bounds: [0, 0, 200, 200]
content-size: [200, 200]
scroll-offset: [0, 0]
items:
- type: clip
bounds: [0, 0, 200, 200]
complex:
- rect: [0, 0, 200, 200]
radius: 4
items:
- type: rect
bounds: [0, 0, 200, 200]
color: white
- text: "A"
origin: 20 190
size: 180
color: black
font: "FreeSans.ttf"