tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit 8bceaea4ea5ce031b0932e7665b9c39d728d15ee
parent 62c12522bc6edd6fa334ab7b86017bae57257d25
Author: Glenn Watson <git@chillybin.org>
Date:   Fri, 17 Oct 2025 03:33:24 +0000

Bug 1994872 - Add wrench raw tests support for fractional APZ scrolls r=gfx-reviewers,lsalzman

Differential Revision: https://phabricator.services.mozilla.com/D268963

Diffstat:
Mgfx/wr/wrench/src/rawtest.rs | 1+
Mgfx/wr/wrench/src/rawtests/snapping.rs | 293++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------
2 files changed, 263 insertions(+), 31 deletions(-)

diff --git a/gfx/wr/wrench/src/rawtest.rs b/gfx/wr/wrench/src/rawtest.rs @@ -51,6 +51,7 @@ impl<'a> RawtestHarness<'a> { self.test_clear_cache(); } + #[allow(dead_code)] pub fn render_display_list_and_get_pixels( &mut self, builder: DisplayListBuilder, diff --git a/gfx/wr/wrench/src/rawtests/snapping.rs b/gfx/wr/wrench/src/rawtests/snapping.rs @@ -3,16 +3,17 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use crate::RawtestHarness; +use crate::euclid::point2; use webrender::api::*; use webrender::api::units::*; +use webrender::Transaction; struct SnapTestContext { root_spatial_id: SpatialId, test_size: FramebufferIntSize, font_size: f32, ahem_font_key: FontInstanceKey, - offset: f32, - expected_offset: i32, + variant: usize, } enum SnapTestExpectation { @@ -23,11 +24,22 @@ enum SnapTestExpectation { } } -type SnapTestFunction = fn(&mut DisplayListBuilder, &mut SnapTestContext) -> SnapTestExpectation; +struct ScrollRequest { + external_scroll_id: ExternalScrollId, + amount: f32, +} + +struct SnapTestResult { + scrolls: Vec<ScrollRequest>, + expected: SnapTestExpectation, +} + +type SnapTestFunction = fn(&mut DisplayListBuilder, &mut SnapTestContext) -> SnapTestResult; struct SnapTest { name: &'static str, f: SnapTestFunction, + variations: usize, } struct SnapVariation { @@ -38,25 +50,42 @@ struct SnapVariation { const MAGENTA_RECT: SnapTest = SnapTest { name: "clear", f: dl_clear, + variations: 1, }; // Types of snap tests -const TESTS: &[SnapTest; 2] = &[ +const TESTS: &[SnapTest; 4] = &[ // Rectangle, no transform/scroll SnapTest { name: "rect", f: dl_simple_rect, + variations: SIMPLE_FRACTIONAL_VARIANTS.len(), }, // Glyph, no transform/scroll SnapTest { name: "glyph", f: dl_simple_glyph, + variations: SIMPLE_FRACTIONAL_VARIANTS.len(), }, + + // Rect, APZ + SnapTest { + name: "scroll1", + f: dl_scrolling1, + variations: SCROLL_VARIANTS.len(), + }, + + // Rect, APZ + external scroll offset + SnapTest { + name: "rect-apz-ext-1", + f: dl_scrolling_ext1, + variations: EXTERNAL_SCROLL_VARIANTS.len(), + } ]; // Variants we will run for each snap test with expected float offset and raster difference -const VARIANTS: &[SnapVariation; 13] = &[ +const SIMPLE_FRACTIONAL_VARIANTS: [SnapVariation; 13] = [ SnapVariation { offset: 0.0, expected: 0, @@ -111,6 +140,46 @@ const VARIANTS: &[SnapVariation; 13] = &[ }, ]; +struct ScrollVariation{ + apz_scroll: f32, + prim_offset: f32, + expected: i32, +} + +const SCROLL_VARIANTS: [ScrollVariation; 3] = [ + ScrollVariation { + apz_scroll: 0.0, + prim_offset: 0.0, + expected: 0, + }, + ScrollVariation { + apz_scroll: -1.0, + prim_offset: 0.0, + expected: 1, + }, + ScrollVariation { + apz_scroll: -1.5, + prim_offset: 0.0, + expected: 2, + }, +]; + +struct ExternalScrollVariation{ + external_offset: f32, + apz_scroll: f32, + prim_offset: f32, + expected: i32, +} + +const EXTERNAL_SCROLL_VARIANTS: [ExternalScrollVariation; 1] = [ + ExternalScrollVariation { + external_offset: 100.0, + apz_scroll: -101.0, + prim_offset: -100.0, + expected: 1, + }, +]; + impl<'a> RawtestHarness<'a> { pub fn test_snapping(&mut self) { println!("\tsnapping test..."); @@ -136,14 +205,13 @@ impl<'a> RawtestHarness<'a> { // Run each test for test in TESTS { - for variant in VARIANTS { + for i in 0 .. test.variations { let mut ctx = SnapTestContext { ahem_font_key, font_size, - offset: variant.offset, - expected_offset: variant.expected, root_spatial_id: SpatialId::root_scroll_node(self.wrench.root_pipeline_id), test_size, + variant: i, }; any_fails = !self.run_snap_test(test, &mut ctx); @@ -167,20 +235,42 @@ impl<'a> RawtestHarness<'a> { let mut builder = DisplayListBuilder::new(self.wrench.root_pipeline_id); builder.begin(); - let expected = (test.f)(&mut builder, ctx); + let result = (test.f)(&mut builder, ctx); - let pixels = self.render_display_list_and_get_pixels( - builder, + let window_size = self.window.get_inner_size(); + let window_rect = FramebufferIntRect::from_origin_and_size( + point2(0, window_size.height - ctx.test_size.height), ctx.test_size, ); + + let txn = Transaction::new(); + self.submit_dl(&mut Epoch(0), builder, txn); + + for scroll in result.scrolls { + let mut txn = Transaction::new(); + txn.set_scroll_offsets( + scroll.external_scroll_id, + vec![SampledScrollOffset { + offset: LayoutVector2D::new(0.0, scroll.amount), + generation: APZScrollGeneration::default(), + }], + ); + txn.generate_frame(0, true, false, RenderReasons::TESTING); + self.wrench.api.send_transaction(self.wrench.document_id, txn); + + self.render_and_get_pixels(window_rect); + } + + let pixels = self.render_and_get_pixels(window_rect); + let ok = validate_output( &pixels, - expected, + result.expected, ctx.test_size, ); if !ok { - println!("FAIL {} [{}/{}]", test.name, ctx.offset, ctx.expected_offset); + println!("FAIL {} [{}]", test.name, ctx.variant); // enable to save output as png for debugging // use crate::png; @@ -266,7 +356,7 @@ fn validate_output( fn dl_clear( builder: &mut DisplayListBuilder, ctx: &mut SnapTestContext, -) -> SnapTestExpectation { +) -> SnapTestResult { let color = ColorF::new(1.0, 0.0, 1.0, 1.0); let bounds = ctx.test_size @@ -285,10 +375,13 @@ fn dl_clear( color, ); - SnapTestExpectation::Rect { - expected_color: color.into(), - expected_rect: ctx.test_size.cast_unit().into(), - expected_offset: 0, + SnapTestResult { + scrolls: vec![], + expected: SnapTestExpectation::Rect { + expected_color: color.into(), + expected_rect: ctx.test_size.cast_unit().into(), + expected_offset: 0, + } } } @@ -296,8 +389,9 @@ fn dl_clear( fn dl_simple_rect( builder: &mut DisplayListBuilder, ctx: &mut SnapTestContext -) -> SnapTestExpectation { +) -> SnapTestResult { let color = ColorF::BLACK; + let variant = &SIMPLE_FRACTIONAL_VARIANTS[ctx.variant]; let prim_size = DeviceIntSize::new( ctx.test_size.width / 2, @@ -316,7 +410,7 @@ fn dl_simple_rect( .to_f32() .cast_unit() .translate( - LayoutVector2D::new(0.0, ctx.offset) + LayoutVector2D::new(0.0, variant.offset) ); builder.push_rect( @@ -330,10 +424,13 @@ fn dl_simple_rect( color, ); - SnapTestExpectation::Rect { - expected_color: color.into(), - expected_rect: rect, - expected_offset: ctx.expected_offset, + SnapTestResult { + scrolls: vec![], + expected: SnapTestExpectation::Rect { + expected_color: color.into(), + expected_rect: rect, + expected_offset: variant.expected, + } } } @@ -341,8 +438,9 @@ fn dl_simple_rect( fn dl_simple_glyph( builder: &mut DisplayListBuilder, ctx: &mut SnapTestContext, -) -> SnapTestExpectation { +) -> SnapTestResult { let color = ColorF::BLACK; + let variant = &SIMPLE_FRACTIONAL_VARIANTS[ctx.variant]; let prim_size = DeviceIntSize::new( ctx.test_size.width / 2, @@ -361,8 +459,8 @@ fn dl_simple_glyph( .to_f32() .cast_unit() .translate( - LayoutVector2D::new(0.0, ctx.offset) - ); + LayoutVector2D::new(0.0, variant.offset) + ); builder.push_text( &CommonItemProperties { @@ -387,9 +485,142 @@ fn dl_simple_glyph( None, ); - SnapTestExpectation::Rect { - expected_color: color.into(), - expected_rect: rect, - expected_offset: ctx.expected_offset, + SnapTestResult { + scrolls: vec![], + expected: SnapTestExpectation::Rect { + expected_color: color.into(), + expected_rect: rect, + expected_offset: variant.expected, + } + } +} + +fn dl_scrolling1( + builder: &mut DisplayListBuilder, + ctx: &mut SnapTestContext, +) -> SnapTestResult { + let color = ColorF::BLACK; + let external_scroll_id = ExternalScrollId(1, PipelineId::dummy()); + let variant = &SCROLL_VARIANTS[ctx.variant]; + + let scroll_id = builder.define_scroll_frame( + ctx.root_spatial_id, + external_scroll_id, + LayoutRect::from_size(LayoutSize::new(100.0, 1000.0)), + LayoutRect::from_size(LayoutSize::new(100.0, 100.0)), + LayoutVector2D::zero(), + APZScrollGeneration::default(), + HasScrollLinkedEffect::No, + SpatialTreeItemKey::new(0, 0), + ); + + let prim_size = DeviceIntSize::new( + ctx.test_size.width / 2, + ctx.test_size.height / 2 + ); + + let rect = DeviceIntRect::from_origin_and_size( + DeviceIntPoint::new( + (ctx.test_size.width - prim_size.width) / 2, + (ctx.test_size.height - prim_size.height) / 2, + ), + prim_size, + ); + + let bounds = rect + .to_f32() + .cast_unit() + .translate( + LayoutVector2D::new(0.0, variant.prim_offset) + ); + + builder.push_rect( + &CommonItemProperties { + clip_rect: bounds, + clip_chain_id: ClipChainId::INVALID, + spatial_id: scroll_id, + flags: PrimitiveFlags::default(), + }, + bounds, + color, + ); + + SnapTestResult { + scrolls: vec![ + ScrollRequest { + external_scroll_id, + amount: variant.apz_scroll, + } + ], + expected: SnapTestExpectation::Rect { + expected_color: color.into(), + expected_rect: rect, + expected_offset: variant.expected, + } + } +} + +fn dl_scrolling_ext1( + builder: &mut DisplayListBuilder, + ctx: &mut SnapTestContext, +) -> SnapTestResult { + let color = ColorF::BLACK; + let external_scroll_id = ExternalScrollId(1, PipelineId::dummy()); + let variant = &EXTERNAL_SCROLL_VARIANTS[ctx.variant]; + + let scroll_id = builder.define_scroll_frame( + ctx.root_spatial_id, + external_scroll_id, + LayoutRect::from_size(LayoutSize::new(100.0, 1000.0)), + LayoutRect::from_size(LayoutSize::new(100.0, 100.0)), + LayoutVector2D::new(0.0, variant.external_offset), + APZScrollGeneration::default(), + HasScrollLinkedEffect::No, + SpatialTreeItemKey::new(0, 0), + ); + + let prim_size = DeviceIntSize::new( + ctx.test_size.width / 2, + ctx.test_size.height / 2 + ); + + let rect = DeviceIntRect::from_origin_and_size( + DeviceIntPoint::new( + (ctx.test_size.width - prim_size.width) / 2, + (ctx.test_size.height - prim_size.height) / 2, + ), + prim_size, + ); + + let bounds = rect + .to_f32() + .cast_unit() + .translate( + LayoutVector2D::new(0.0, variant.prim_offset) + ); + + builder.push_rect( + &CommonItemProperties { + clip_rect: bounds, + clip_chain_id: ClipChainId::INVALID, + spatial_id: scroll_id, + flags: PrimitiveFlags::default(), + }, + bounds, + color, + ); + + SnapTestResult { + scrolls: vec![ + ScrollRequest { + external_scroll_id, + amount: variant.apz_scroll, + } + ], + expected: SnapTestExpectation::Rect { + expected_color: color.into(), + expected_rect: rect, + expected_offset: variant.expected, + } } }