зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1609805 - Support a new reftest kind, for verifying rasterizer accuracy. r=nical,Bert
This patch introduces a new reftest (syntax ** or !* in reftest files). This type of test renders a single input file multiple times, at a range of different picture cache tile sizes. It then verifies that each of the images matches (or doesn't). This can be used to verify rasterizer accuracy when drawing primitives with different tile sizes and/or dirty rect update strategies. One of the included tests in this patch fails the accuracy test - the intent is to fix this inaccuracy in a follow up patch and then be able to mark it pixel exact. Differential Revision: https://phabricator.services.mozilla.com/D60185 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
6802b12993
Коммит
3bf8ad7884
|
@ -65,6 +65,7 @@ pub struct FrameBuilderConfig {
|
|||
pub batch_lookback_count: usize,
|
||||
pub background_color: Option<ColorF>,
|
||||
pub compositor_kind: CompositorKind,
|
||||
pub tile_size_override: Option<DeviceIntSize>,
|
||||
}
|
||||
|
||||
/// A set of common / global resources that are retained between
|
||||
|
@ -117,7 +118,7 @@ pub struct FrameVisibilityContext<'a> {
|
|||
pub surfaces: &'a [SurfaceInfo],
|
||||
pub debug_flags: DebugFlags,
|
||||
pub scene_properties: &'a SceneProperties,
|
||||
pub config: &'a FrameBuilderConfig,
|
||||
pub config: FrameBuilderConfig,
|
||||
}
|
||||
|
||||
pub struct FrameVisibilityState<'a> {
|
||||
|
@ -242,6 +243,7 @@ impl FrameBuilder {
|
|||
texture_cache_profile: &mut TextureCacheProfileCounters,
|
||||
composite_state: &mut CompositeState,
|
||||
tile_cache_logger: &mut TileCacheLogger,
|
||||
config: FrameBuilderConfig,
|
||||
) -> Option<RenderTaskId> {
|
||||
profile_scope!("cull");
|
||||
|
||||
|
@ -327,7 +329,7 @@ impl FrameBuilder {
|
|||
surfaces,
|
||||
debug_flags,
|
||||
scene_properties,
|
||||
config: &scene.config,
|
||||
config,
|
||||
};
|
||||
|
||||
let mut visibility_state = FrameVisibilityState {
|
||||
|
@ -472,6 +474,7 @@ impl FrameBuilder {
|
|||
render_task_counters: &mut RenderTaskGraphCounters,
|
||||
debug_flags: DebugFlags,
|
||||
tile_cache_logger: &mut TileCacheLogger,
|
||||
config: FrameBuilderConfig,
|
||||
) -> Frame {
|
||||
profile_scope!("build");
|
||||
profile_marker!("BuildFrame");
|
||||
|
@ -542,6 +545,7 @@ impl FrameBuilder {
|
|||
&mut resource_profile.texture_cache,
|
||||
&mut composite_state,
|
||||
tile_cache_logger,
|
||||
config,
|
||||
);
|
||||
|
||||
let mut passes;
|
||||
|
|
|
@ -278,13 +278,38 @@ pub const TILE_SIZE_SCROLLBAR_VERTICAL: DeviceIntSize = DeviceIntSize {
|
|||
_unit: marker::PhantomData,
|
||||
};
|
||||
|
||||
const TILE_SIZE_FOR_TESTS: [DeviceIntSize; 6] = [
|
||||
DeviceIntSize {
|
||||
width: 128,
|
||||
height: 128,
|
||||
_unit: marker::PhantomData,
|
||||
},
|
||||
DeviceIntSize {
|
||||
width: 256,
|
||||
height: 256,
|
||||
_unit: marker::PhantomData,
|
||||
},
|
||||
DeviceIntSize {
|
||||
width: 512,
|
||||
height: 512,
|
||||
_unit: marker::PhantomData,
|
||||
},
|
||||
TILE_SIZE_DEFAULT,
|
||||
TILE_SIZE_SCROLLBAR_VERTICAL,
|
||||
TILE_SIZE_SCROLLBAR_HORIZONTAL,
|
||||
];
|
||||
|
||||
// Return the list of tile sizes for the renderer to allocate texture arrays for.
|
||||
pub fn tile_cache_sizes() -> &'static [DeviceIntSize] {
|
||||
&[
|
||||
TILE_SIZE_DEFAULT,
|
||||
TILE_SIZE_SCROLLBAR_HORIZONTAL,
|
||||
TILE_SIZE_SCROLLBAR_VERTICAL,
|
||||
]
|
||||
pub fn tile_cache_sizes(testing: bool) -> &'static [DeviceIntSize] {
|
||||
if testing {
|
||||
&TILE_SIZE_FOR_TESTS
|
||||
} else {
|
||||
&[
|
||||
TILE_SIZE_DEFAULT,
|
||||
TILE_SIZE_SCROLLBAR_HORIZONTAL,
|
||||
TILE_SIZE_SCROLLBAR_VERTICAL,
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
/// The maximum size per axis of a surface,
|
||||
|
@ -1654,6 +1679,9 @@ pub struct TileCacheInstance {
|
|||
pub device_position: DevicePoint,
|
||||
/// True if the entire picture cache surface is opaque.
|
||||
is_opaque: bool,
|
||||
/// The currently considered tile size override. Used to check if we should
|
||||
/// re-evaluate tile size, even if the frame timer hasn't expired.
|
||||
tile_size_override: Option<DeviceIntSize>,
|
||||
}
|
||||
|
||||
impl TileCacheInstance {
|
||||
|
@ -1704,6 +1732,7 @@ impl TileCacheInstance {
|
|||
native_surface_id: None,
|
||||
device_position: DevicePoint::zero(),
|
||||
is_opaque: true,
|
||||
tile_size_override: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1861,22 +1890,28 @@ impl TileCacheInstance {
|
|||
// Only evaluate what tile size to use fairly infrequently, so that we don't end
|
||||
// up constantly invalidating and reallocating tiles if the picture rect size is
|
||||
// changing near a threshold value.
|
||||
if self.frames_until_size_eval == 0 {
|
||||
if self.frames_until_size_eval == 0 ||
|
||||
self.tile_size_override != frame_context.config.tile_size_override {
|
||||
const TILE_SIZE_TINY: f32 = 32.0;
|
||||
|
||||
// Work out what size tile is appropriate for this picture cache.
|
||||
let desired_tile_size;
|
||||
|
||||
// There's no need to check the other dimension. If we encounter a picture
|
||||
// that is small on one dimension, it's a reasonable choice to use a scrollbar
|
||||
// sized tile configuration regardless of the other dimension.
|
||||
if pic_rect.size.width <= TILE_SIZE_TINY {
|
||||
desired_tile_size = TILE_SIZE_SCROLLBAR_VERTICAL;
|
||||
} else if pic_rect.size.height <= TILE_SIZE_TINY {
|
||||
desired_tile_size = TILE_SIZE_SCROLLBAR_HORIZONTAL;
|
||||
} else {
|
||||
desired_tile_size = TILE_SIZE_DEFAULT;
|
||||
}
|
||||
let desired_tile_size = match frame_context.config.tile_size_override {
|
||||
Some(tile_size_override) => {
|
||||
tile_size_override
|
||||
}
|
||||
None => {
|
||||
// There's no need to check the other dimension. If we encounter a picture
|
||||
// that is small on one dimension, it's a reasonable choice to use a scrollbar
|
||||
// sized tile configuration regardless of the other dimension.
|
||||
if pic_rect.size.width <= TILE_SIZE_TINY {
|
||||
TILE_SIZE_SCROLLBAR_VERTICAL
|
||||
} else if pic_rect.size.height <= TILE_SIZE_TINY {
|
||||
TILE_SIZE_SCROLLBAR_HORIZONTAL
|
||||
} else {
|
||||
TILE_SIZE_DEFAULT
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// If the desired tile size has changed, then invalidate and drop any
|
||||
// existing tiles.
|
||||
|
@ -1893,6 +1928,7 @@ impl TileCacheInstance {
|
|||
// Reset counter until next evaluating the desired tile size. This is an
|
||||
// arbitrary value.
|
||||
self.frames_until_size_eval = 120;
|
||||
self.tile_size_override = frame_context.config.tile_size_override;
|
||||
}
|
||||
|
||||
// Map an arbitrary point in picture space to world space, to work out
|
||||
|
|
|
@ -541,6 +541,7 @@ impl Document {
|
|||
resource_profile: &mut ResourceProfileCounters,
|
||||
debug_flags: DebugFlags,
|
||||
tile_cache_logger: &mut TileCacheLogger,
|
||||
config: FrameBuilderConfig,
|
||||
) -> RenderedDocument {
|
||||
let accumulated_scale_factor = self.view.accumulated_scale_factor();
|
||||
let pan = self.view.pan.to_f32() / accumulated_scale_factor;
|
||||
|
@ -568,6 +569,7 @@ impl Document {
|
|||
&mut self.render_task_counters,
|
||||
debug_flags,
|
||||
tile_cache_logger,
|
||||
config,
|
||||
);
|
||||
self.hit_tester = Some(self.scene.create_hit_tester(&self.data_stores.clip));
|
||||
frame
|
||||
|
@ -1142,6 +1144,11 @@ impl RenderBackend {
|
|||
// We don't want to forward this message to the renderer.
|
||||
return RenderBackendStatus::Continue;
|
||||
}
|
||||
DebugCommand::SetPictureTileSize(tile_size) => {
|
||||
self.frame_config.tile_size_override = tile_size;
|
||||
|
||||
return RenderBackendStatus::Continue;
|
||||
}
|
||||
DebugCommand::FetchDocuments => {
|
||||
// Ask SceneBuilderThread to send JSON presentation of the documents,
|
||||
// that will be forwarded to Renderer.
|
||||
|
@ -1534,6 +1541,7 @@ impl RenderBackend {
|
|||
&mut profile_counters.resources,
|
||||
self.debug_flags,
|
||||
&mut self.tile_cache_logger,
|
||||
self.frame_config,
|
||||
);
|
||||
|
||||
debug!("generated frame for document {:?} with {} passes",
|
||||
|
@ -1712,6 +1720,7 @@ impl RenderBackend {
|
|||
&mut profile_counters.resources,
|
||||
self.debug_flags,
|
||||
&mut self.tile_cache_logger,
|
||||
self.frame_config,
|
||||
);
|
||||
// After we rendered the frames, there are pending updates to both
|
||||
// GPU cache and resources. Instead of serializing them, we are going to make sure
|
||||
|
|
|
@ -2185,6 +2185,7 @@ impl Renderer {
|
|||
batch_lookback_count: options.batch_lookback_count,
|
||||
background_color: options.clear_color,
|
||||
compositor_kind,
|
||||
tile_size_override: None,
|
||||
};
|
||||
info!("WR {:?}", config);
|
||||
|
||||
|
@ -2292,7 +2293,7 @@ impl Renderer {
|
|||
max_texture_size,
|
||||
max_texture_layers,
|
||||
if config.global_enable_picture_caching {
|
||||
tile_cache_sizes()
|
||||
tile_cache_sizes(config.testing)
|
||||
} else {
|
||||
&[]
|
||||
},
|
||||
|
@ -2845,7 +2846,8 @@ impl Renderer {
|
|||
fn handle_debug_command(&mut self, command: DebugCommand) {
|
||||
match command {
|
||||
DebugCommand::EnableDualSourceBlending(_) |
|
||||
DebugCommand::SetTransactionLogging(_) => {
|
||||
DebugCommand::SetTransactionLogging(_) |
|
||||
DebugCommand::SetPictureTileSize(_) => {
|
||||
panic!("Should be handled by render backend");
|
||||
}
|
||||
DebugCommand::FetchDocuments |
|
||||
|
|
|
@ -258,6 +258,7 @@ impl BuiltScene {
|
|||
batch_lookback_count: 0,
|
||||
background_color: None,
|
||||
compositor_kind: CompositorKind::default(),
|
||||
tile_size_override: None,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
@ -977,6 +977,8 @@ pub enum DebugCommand {
|
|||
SimulateLongLowPrioritySceneBuild(u32),
|
||||
/// Logs transactions to a file for debugging purposes
|
||||
SetTransactionLogging(bool),
|
||||
/// Set an override tile size to use for picture caches
|
||||
SetPictureTileSize(Option<DeviceIntSize>),
|
||||
}
|
||||
|
||||
/// Message sent by the `RenderApi` to the render backend thread.
|
||||
|
|
|
@ -28,5 +28,5 @@ platform(linux,mac) == small-dotted-border.yaml small-dotted-border.png
|
|||
platform(linux,mac) == border-dashed-dotted-caching.yaml border-dashed-dotted-caching.png
|
||||
!= small-inset-outset.yaml small-inset-outset-notref.yaml
|
||||
fuzzy(1,16) == no-aa.yaml green-square.yaml
|
||||
skip_on(android,device) border-double-1px.yaml border-double-1px-ref.yaml # Fails on Pixel2
|
||||
skip_on(android,device) == border-double-1px.yaml border-double-1px-ref.yaml # Fails on Pixel2
|
||||
== max-scale.yaml max-scale-ref.yaml
|
||||
|
|
|
@ -15,3 +15,4 @@ include snap/reftest.list
|
|||
include split/reftest.list
|
||||
include text/reftest.list
|
||||
include transforms/reftest.list
|
||||
include tiles/reftest.list
|
||||
|
|
|
@ -73,5 +73,5 @@ options(disable-aa) == snap-clip.yaml snap-clip-ref.yaml
|
|||
platform(linux) == perspective-clip.yaml perspective-clip.png
|
||||
fuzzy(1,39) options(disable-subpixel) == raster-space-snap.yaml raster-space-snap-ref.yaml
|
||||
# == intermediate-transform.yaml intermediate-transform-ref.yaml # fails because of AA inavailable with an intermediate surface
|
||||
platform(linux) allow_sacrificing_subpixel_aa(false) text-fixed-slice.yaml text-fixed-slice-slow.png
|
||||
platform(linux) allow_sacrificing_subpixel_aa(true) text-fixed-slice.yaml text-fixed-slice-fast.png
|
||||
platform(linux) allow_sacrificing_subpixel_aa(false) == text-fixed-slice.yaml text-fixed-slice-slow.png
|
||||
platform(linux) allow_sacrificing_subpixel_aa(true) == text-fixed-slice.yaml text-fixed-slice-fast.png
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
---
|
||||
root:
|
||||
items:
|
||||
- type: stacking-context
|
||||
bounds: [50, 50, 100, 100]
|
||||
transform: rotate(30)
|
||||
items:
|
||||
- type: rect
|
||||
bounds: [ 10, 10, 80, 80 ]
|
||||
color: [0, 255, 0]
|
||||
- type: box-shadow
|
||||
bounds: [ 10, 10, 80, 80 ]
|
||||
blur-radius: 25
|
||||
clip-mode: inset
|
||||
|
||||
- type: rect
|
||||
bounds: [ 140, 10, 80, 80 ]
|
||||
color: [0, 255, 0]
|
||||
- type: box-shadow
|
||||
bounds: [ 140, 10, 80, 80 ]
|
||||
blur-radius: 25
|
||||
clip-mode: outset
|
||||
|
||||
- type: border
|
||||
bounds: [ 250, 10, 100, 100 ]
|
||||
width: [ 10, 10, 10, 10 ]
|
||||
border-type: normal
|
||||
style: solid
|
||||
color: [ red, green, blue, black ]
|
||||
radius: {
|
||||
top-left: [20, 20],
|
||||
top-right: [10, 10],
|
||||
bottom-left: [25, 25],
|
||||
bottom-right: [0, 0],
|
||||
}
|
||||
|
||||
- bounds: [150, 150, 128, 128]
|
||||
image: checkerboard(4, 15, 8)
|
||||
stretch-size: 128 128
|
||||
|
||||
- type: radial-gradient
|
||||
bounds: 300 150 100 100
|
||||
center: 50 50
|
||||
radius: 50 50
|
||||
stops: [0, red, 1, blue]
|
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
root:
|
||||
items:
|
||||
- type: rect
|
||||
bounds: 50 50 200 200
|
||||
color: red
|
|
@ -0,0 +1,4 @@
|
|||
** rect.yaml
|
||||
** simple-gradient.yaml
|
||||
# TODO: Fix rasterizer inaccuracies so this is the same regardless of tile size!
|
||||
!* prim-suite.yaml
|
|
@ -0,0 +1,9 @@
|
|||
---
|
||||
root:
|
||||
items:
|
||||
- type: gradient
|
||||
bounds: [ 0, 0, 1980, 1080]
|
||||
start: [ 0, -2000 ]
|
||||
end: [ 0, 4000 ]
|
||||
stops: [ 0.0, red, 1.0, green ]
|
||||
repeat: false
|
|
@ -44,9 +44,16 @@ impl ReftestOptions {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub enum ReftestOp {
|
||||
/// Expect that the images match the reference
|
||||
Equal,
|
||||
/// Expect that the images *don't* match the reference
|
||||
NotEqual,
|
||||
/// Expect that drawing the reference at different tiles sizes gives the same pixel exact result.
|
||||
Accurate,
|
||||
/// Expect that drawing the reference at different tiles sizes gives a *different* pixel exact result.
|
||||
Inaccurate,
|
||||
}
|
||||
|
||||
impl Display for ReftestOp {
|
||||
|
@ -57,6 +64,8 @@ impl Display for ReftestOp {
|
|||
match *self {
|
||||
ReftestOp::Equal => "==".to_owned(),
|
||||
ReftestOp::NotEqual => "!=".to_owned(),
|
||||
ReftestOp::Accurate => "**".to_owned(),
|
||||
ReftestOp::Inaccurate => "!*".to_owned(),
|
||||
}
|
||||
)
|
||||
}
|
||||
|
@ -102,6 +111,62 @@ pub struct Reftest {
|
|||
allow_sacrificing_subpixel_aa: Option<bool>,
|
||||
}
|
||||
|
||||
impl Reftest {
|
||||
/// Check the positive case (expecting equality) and report details if different
|
||||
fn check_and_report_equality_failure(
|
||||
&self,
|
||||
comparison: ReftestImageComparison,
|
||||
test: &ReftestImage,
|
||||
reference: &ReftestImage,
|
||||
) -> bool {
|
||||
match comparison {
|
||||
ReftestImageComparison::Equal => {
|
||||
true
|
||||
}
|
||||
ReftestImageComparison::NotEqual { max_difference, count_different } => {
|
||||
if max_difference > self.max_difference || count_different > self.num_differences {
|
||||
println!(
|
||||
"{} | {} | {}: {}, {}: {}",
|
||||
"REFTEST TEST-UNEXPECTED-FAIL",
|
||||
self,
|
||||
"image comparison, max difference",
|
||||
max_difference,
|
||||
"number of differing pixels",
|
||||
count_different
|
||||
);
|
||||
println!("REFTEST IMAGE 1 (TEST): {}", test.clone().create_data_uri());
|
||||
println!(
|
||||
"REFTEST IMAGE 2 (REFERENCE): {}",
|
||||
reference.clone().create_data_uri()
|
||||
);
|
||||
println!("REFTEST TEST-END | {}", self);
|
||||
|
||||
false
|
||||
} else {
|
||||
true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Check the negative case (expecting inequality) and report details if same
|
||||
fn check_and_report_inequality_failure(
|
||||
&self,
|
||||
comparison: ReftestImageComparison,
|
||||
) -> bool {
|
||||
match comparison {
|
||||
ReftestImageComparison::Equal => {
|
||||
println!("REFTEST TEST-UNEXPECTED-FAIL | {} | image comparison", self);
|
||||
println!("REFTEST TEST-END | {}", self);
|
||||
false
|
||||
}
|
||||
ReftestImageComparison::NotEqual { .. } => {
|
||||
true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Reftest {
|
||||
fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
|
||||
let paths: Vec<String> = self.test.iter().map(|t| t.display().to_string()).collect();
|
||||
|
@ -115,10 +180,13 @@ impl Display for Reftest {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ReftestImage {
|
||||
pub data: Vec<u8>,
|
||||
pub size: DeviceIntSize,
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub enum ReftestImageComparison {
|
||||
Equal,
|
||||
NotEqual {
|
||||
|
@ -212,7 +280,7 @@ impl ReftestManifest {
|
|||
|
||||
let mut max_difference = 0;
|
||||
let mut max_count = 0;
|
||||
let mut op = ReftestOp::Equal;
|
||||
let mut op = None;
|
||||
let mut font_render_mode = None;
|
||||
let mut extra_checks = vec![];
|
||||
let mut disable_dual_source_blending = false;
|
||||
|
@ -299,10 +367,16 @@ impl ReftestManifest {
|
|||
}
|
||||
}
|
||||
"==" => {
|
||||
op = ReftestOp::Equal;
|
||||
op = Some(ReftestOp::Equal);
|
||||
}
|
||||
"!=" => {
|
||||
op = ReftestOp::NotEqual;
|
||||
op = Some(ReftestOp::NotEqual);
|
||||
}
|
||||
"**" => {
|
||||
op = Some(ReftestOp::Accurate);
|
||||
}
|
||||
"!*" => {
|
||||
op = Some(ReftestOp::Inaccurate);
|
||||
}
|
||||
_ => {
|
||||
paths.push(dir.join(*token));
|
||||
|
@ -311,10 +385,13 @@ impl ReftestManifest {
|
|||
}
|
||||
|
||||
// Don't try to add tests for include lines.
|
||||
if paths.len() < 2 {
|
||||
assert_eq!(paths.len(), 0, "Only one path provided: {:?}", paths[0]);
|
||||
continue;
|
||||
}
|
||||
let op = match op {
|
||||
Some(op) => op,
|
||||
None => {
|
||||
assert!(paths.is_empty(), format!("paths = {:?}", paths));
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
// The reference is the last path provided. If multiple paths are
|
||||
// passed for the test, they render sequentially before being
|
||||
|
@ -530,15 +607,52 @@ impl<'a> ReftestHarness<'a> {
|
|||
let mut images = vec![];
|
||||
let mut results = vec![];
|
||||
|
||||
for filename in t.test.iter() {
|
||||
let output = self.render_yaml(
|
||||
&filename,
|
||||
test_size,
|
||||
t.font_render_mode,
|
||||
t.allow_mipmaps,
|
||||
);
|
||||
images.push(output.image);
|
||||
results.push(output.results);
|
||||
match t.op {
|
||||
ReftestOp::Equal | ReftestOp::NotEqual => {
|
||||
// For equality tests, render each test image and store result
|
||||
for filename in t.test.iter() {
|
||||
let output = self.render_yaml(
|
||||
&filename,
|
||||
test_size,
|
||||
t.font_render_mode,
|
||||
t.allow_mipmaps,
|
||||
);
|
||||
images.push(output.image);
|
||||
results.push(output.results);
|
||||
}
|
||||
}
|
||||
ReftestOp::Accurate | ReftestOp::Inaccurate => {
|
||||
// For accuracy tests, render the reference yaml at an arbitrary series
|
||||
// of tile sizes, and compare to the reference drawn at normal tile size.
|
||||
let tile_sizes = [
|
||||
DeviceIntSize::new(128, 128),
|
||||
DeviceIntSize::new(256, 256),
|
||||
DeviceIntSize::new(512, 512),
|
||||
];
|
||||
|
||||
for tile_size in &tile_sizes {
|
||||
self.wrench
|
||||
.api
|
||||
.send_debug_cmd(
|
||||
DebugCommand::SetPictureTileSize(Some(*tile_size))
|
||||
);
|
||||
|
||||
let output = self.render_yaml(
|
||||
&t.reference,
|
||||
test_size,
|
||||
t.font_render_mode,
|
||||
t.allow_mipmaps,
|
||||
);
|
||||
images.push(output.image);
|
||||
results.push(output.results);
|
||||
}
|
||||
|
||||
self.wrench
|
||||
.api
|
||||
.send_debug_cmd(
|
||||
DebugCommand::SetPictureTileSize(None)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
let reference = match reference_image {
|
||||
|
@ -575,44 +689,50 @@ impl<'a> ReftestHarness<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
let test = images.pop().unwrap();
|
||||
let comparison = test.compare(&reference);
|
||||
match (&t.op, comparison) {
|
||||
(&ReftestOp::Equal, ReftestImageComparison::Equal) => true,
|
||||
(
|
||||
&ReftestOp::Equal,
|
||||
ReftestImageComparison::NotEqual {
|
||||
max_difference,
|
||||
count_different,
|
||||
},
|
||||
) => if max_difference > t.max_difference || count_different > t.num_differences {
|
||||
println!(
|
||||
"{} | {} | {}: {}, {}: {}",
|
||||
"REFTEST TEST-UNEXPECTED-FAIL",
|
||||
t,
|
||||
"image comparison, max difference",
|
||||
max_difference,
|
||||
"number of differing pixels",
|
||||
count_different
|
||||
);
|
||||
println!("REFTEST IMAGE 1 (TEST): {}", test.create_data_uri());
|
||||
println!(
|
||||
"REFTEST IMAGE 2 (REFERENCE): {}",
|
||||
reference.create_data_uri()
|
||||
);
|
||||
println!("REFTEST TEST-END | {}", t);
|
||||
|
||||
false
|
||||
} else {
|
||||
true
|
||||
},
|
||||
(&ReftestOp::NotEqual, ReftestImageComparison::Equal) => {
|
||||
println!("REFTEST TEST-UNEXPECTED-FAIL | {} | image comparison", t);
|
||||
println!("REFTEST TEST-END | {}", t);
|
||||
|
||||
false
|
||||
match t.op {
|
||||
ReftestOp::Equal => {
|
||||
// Ensure that the final image matches the reference
|
||||
let test = images.pop().unwrap();
|
||||
let comparison = test.compare(&reference);
|
||||
t.check_and_report_equality_failure(
|
||||
comparison,
|
||||
&test,
|
||||
&reference,
|
||||
)
|
||||
}
|
||||
ReftestOp::NotEqual => {
|
||||
// Ensure that the final image *doesn't* match the reference
|
||||
let test = images.pop().unwrap();
|
||||
let comparison = test.compare(&reference);
|
||||
t.check_and_report_inequality_failure(comparison)
|
||||
}
|
||||
ReftestOp::Accurate => {
|
||||
// Ensure that *all* images match the reference
|
||||
for test in images.drain(..) {
|
||||
let comparison = test.compare(&reference);
|
||||
|
||||
if !t.check_and_report_equality_failure(
|
||||
comparison,
|
||||
&test,
|
||||
&reference,
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
ReftestOp::Inaccurate => {
|
||||
// Ensure that at least one of the images doesn't match the reference
|
||||
let mut found_mismatch = false;
|
||||
|
||||
for test in images.drain(..) {
|
||||
let comparison = test.compare(&reference);
|
||||
found_mismatch |= t.check_and_report_inequality_failure(comparison);
|
||||
}
|
||||
|
||||
found_mismatch
|
||||
}
|
||||
(&ReftestOp::NotEqual, ReftestImageComparison::NotEqual { .. }) => true,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче