Skip to content

Commit 466f011

Browse files
author
Glenn Watson
committed
Bug 1917985 - Apply scroll snapping without external offsets during scene building r=gfx-reviewers,botond,lsalzman
Apply the external scroll offset normalization prior to snapping during scene building. This makes snapping be unaffected by the external scroll offset, which may now be fractional. Note that although this makes several tests pass, I had to add fails-if() on draw snapshot mode for a couple of the tests. I believe this is because that drawing path doesn't correctly handle the `layout.scroll.disable-pixel-alignment` option. Differential Revision: https://phabricator.services.mozilla.com/D235720
1 parent 95d341f commit 466f011

File tree

1 file changed

+43
-41
lines changed

1 file changed

+43
-41
lines changed

webrender/src/scene_building.rs

Lines changed: 43 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1243,8 +1243,6 @@ impl<'a> SceneBuilder<'a> {
12431243

12441244
self.clip_tree_builder.push_clip_chain(Some(info.space_and_clip.clip_chain_id), false);
12451245

1246-
let external_scroll_offset = self.current_external_scroll_offset(spatial_node_index);
1247-
12481246
// TODO(gw): This is the only remaining call site that relies on ClipId parenting, remove me!
12491247
self.add_rect_clip_node(
12501248
ClipId::root(iframe_pipeline_id),
@@ -1258,13 +1256,11 @@ impl<'a> SceneBuilder<'a> {
12581256

12591257
self.id_to_index_mapper_stack.push(NodeIdToIndexMapper::default());
12601258

1261-
let mut bounds = self.snap_rect(
1259+
let bounds = self.normalize_scroll_offset_and_snap_rect(
12621260
&info.bounds,
12631261
spatial_node_index,
12641262
);
12651263

1266-
bounds = bounds.translate(external_scroll_offset);
1267-
12681264
let spatial_node_index = self.push_reference_frame(
12691265
SpatialId::root_reference_frame(iframe_pipeline_id),
12701266
spatial_node_index,
@@ -1341,36 +1337,35 @@ impl<'a> SceneBuilder<'a> {
13411337
let spatial_node_index = self.get_space(common.spatial_id);
13421338

13431339
// If no bounds rect is given, default to clip rect.
1344-
let (rect, clip_rect) = if common.flags.contains(PrimitiveFlags::ANTIALISED) {
1345-
(bounds.unwrap_or(common.clip_rect), common.clip_rect)
1340+
let mut clip_rect = common.clip_rect;
1341+
let mut prim_rect = bounds.unwrap_or(clip_rect);
1342+
let unsnapped_rect = self.normalize_rect_scroll_offset(&prim_rect, spatial_node_index);
1343+
1344+
// If antialiased, no need to snap but we still need to remove the
1345+
// external scroll offset (it's applied later during frame building,
1346+
// so that we don't intern to a different hash and invalidate content
1347+
// in picture caches unnecessarily).
1348+
if common.flags.contains(PrimitiveFlags::ANTIALISED) {
1349+
prim_rect = self.normalize_rect_scroll_offset(&prim_rect, spatial_node_index);
1350+
clip_rect = self.normalize_rect_scroll_offset(&clip_rect, spatial_node_index);
13461351
} else {
1347-
let clip_rect = self.snap_rect(
1348-
&common.clip_rect,
1352+
clip_rect = self.normalize_scroll_offset_and_snap_rect(
1353+
&clip_rect,
13491354
spatial_node_index,
13501355
);
13511356

1352-
let rect = bounds.map_or(clip_rect, |bounds| {
1353-
self.snap_rect(
1354-
&bounds,
1355-
spatial_node_index,
1356-
)
1357-
});
1358-
1359-
(rect, clip_rect)
1360-
};
1361-
1362-
let current_offset = self.current_external_scroll_offset(spatial_node_index);
1363-
1364-
let rect = rect.translate(current_offset);
1365-
let clip_rect = clip_rect.translate(current_offset);
1366-
let unsnapped_rect = bounds.unwrap_or(common.clip_rect).translate(current_offset);
1357+
prim_rect = self.normalize_scroll_offset_and_snap_rect(
1358+
&prim_rect,
1359+
spatial_node_index,
1360+
);
1361+
}
13671362

13681363
let clip_node_id = self.get_clip_node(
13691364
common.clip_chain_id,
13701365
);
13711366

13721367
let layout = LayoutPrimitiveInfo {
1373-
rect,
1368+
rect: prim_rect,
13741369
clip_rect,
13751370
flags: common.flags,
13761371
};
@@ -1389,11 +1384,29 @@ impl<'a> SceneBuilder<'a> {
13891384
)
13901385
}
13911386

1392-
pub fn snap_rect(
1387+
// Remove the effect of the external scroll offset embedded in the display list
1388+
// coordinates by Gecko. This ensures that we don't necessarily invalidate picture
1389+
// cache tiles due to the embedded scroll offsets.
1390+
fn normalize_rect_scroll_offset(
1391+
&mut self,
1392+
rect: &LayoutRect,
1393+
spatial_node_index: SpatialNodeIndex,
1394+
) -> LayoutRect {
1395+
let current_offset = self.current_external_scroll_offset(spatial_node_index);
1396+
1397+
rect.translate(current_offset)
1398+
}
1399+
1400+
// Remove external scroll offset and snap a rect. The external scroll offset must
1401+
// be removed first, as it may be fractional (which we don't want to affect the
1402+
// snapping behavior during scene building).
1403+
fn normalize_scroll_offset_and_snap_rect(
13931404
&mut self,
13941405
rect: &LayoutRect,
13951406
target_spatial_node: SpatialNodeIndex,
13961407
) -> LayoutRect {
1408+
let rect = self.normalize_rect_scroll_offset(rect, target_spatial_node);
1409+
13971410
self.snap_to_device.set_target_spatial_node(
13981411
target_spatial_node,
13991412
self.spatial_tree,
@@ -1522,15 +1535,12 @@ impl<'a> SceneBuilder<'a> {
15221535
profile_scope!("hit_test");
15231536

15241537
let spatial_node_index = self.get_space(info.spatial_id);
1525-
let current_offset = self.current_external_scroll_offset(spatial_node_index);
15261538

1527-
let mut rect = self.snap_rect(
1539+
let rect = self.normalize_scroll_offset_and_snap_rect(
15281540
&info.rect,
15291541
spatial_node_index,
15301542
);
15311543

1532-
rect = rect.translate(current_offset);
1533-
15341544
let layout = LayoutPrimitiveInfo {
15351545
rect,
15361546
clip_rect: rect,
@@ -2820,13 +2830,11 @@ impl<'a> SceneBuilder<'a> {
28202830
points_range: ItemRange<LayoutPoint>,
28212831
) {
28222832
let spatial_node_index = self.get_space(spatial_id);
2823-
let external_scroll_offset = self.current_external_scroll_offset(spatial_node_index);
28242833

2825-
let mut snapped_mask_rect = self.snap_rect(
2834+
let snapped_mask_rect = self.normalize_scroll_offset_and_snap_rect(
28262835
&image_mask.rect,
28272836
spatial_node_index,
28282837
);
2829-
snapped_mask_rect = snapped_mask_rect.translate(external_scroll_offset);
28302838

28312839
let points: Vec<LayoutPoint> = points_range.iter().collect();
28322840

@@ -2870,15 +2878,12 @@ impl<'a> SceneBuilder<'a> {
28702878
clip_rect: &LayoutRect,
28712879
) {
28722880
let spatial_node_index = self.get_space(spatial_id);
2873-
let external_scroll_offset = self.current_external_scroll_offset(spatial_node_index);
28742881

2875-
let mut snapped_clip_rect = self.snap_rect(
2882+
let snapped_clip_rect = self.normalize_scroll_offset_and_snap_rect(
28762883
clip_rect,
28772884
spatial_node_index,
28782885
);
28792886

2880-
snapped_clip_rect = snapped_clip_rect.translate(external_scroll_offset);
2881-
28822887
let item = ClipItemKey {
28832888
kind: ClipItemKeyKind::rectangle(snapped_clip_rect, ClipMode::Clip),
28842889
spatial_node_index,
@@ -2905,15 +2910,12 @@ impl<'a> SceneBuilder<'a> {
29052910
clip: &ComplexClipRegion,
29062911
) {
29072912
let spatial_node_index = self.get_space(spatial_id);
2908-
let external_scroll_offset = self.current_external_scroll_offset(spatial_node_index);
29092913

2910-
let mut snapped_region_rect = self.snap_rect(
2914+
let snapped_region_rect = self.normalize_scroll_offset_and_snap_rect(
29112915
&clip.rect,
29122916
spatial_node_index,
29132917
);
29142918

2915-
snapped_region_rect = snapped_region_rect.translate(external_scroll_offset);
2916-
29172919
let item = ClipItemKey {
29182920
kind: ClipItemKeyKind::rounded_rect(
29192921
snapped_region_rect,

0 commit comments

Comments
 (0)