add support to run dl_canvas_unittests on GPU surfaces (off by default) (#38993)
* add support to run dl_canvas_unittests on GPU surfaces (off by default)
* empty commit to trigger build
* conditionally include platform-specific surface provider headers
* ignore DL test files during license checks
* typo
* add dependencies to rendertests to hopefully build on Windows
* remove benchmarking deps from dl_rendertests
* more changes to get Windows rendertests to link
* add --enable-gl synonym and prevent non-SW surface provider dest on Windows
* fix gn formatting
* review feedback
diff --git a/ci/licenses_golden/excluded_files b/ci/licenses_golden/excluded_files
index d800da4..7d6275a 100644
--- a/ci/licenses_golden/excluded_files
+++ b/ci/licenses_golden/excluded_files
@@ -43,6 +43,7 @@
../../../flutter/display_list/display_list_unittests.cc
../../../flutter/display_list/display_list_utils_unittests.cc
../../../flutter/display_list/display_list_vertices_unittests.cc
+../../../flutter/display_list/testing
../../../flutter/docs
../../../flutter/examples
../../../flutter/flow/README.md
diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter
index 605e0b8..d2468df 100644
--- a/ci/licenses_golden/licenses_flutter
+++ b/ci/licenses_golden/licenses_flutter
@@ -822,16 +822,8 @@
ORIGIN: ../../../flutter/display_list/display_list.cc + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/display_list/display_list.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/display_list/display_list_attributes.h + ../../../flutter/LICENSE
-ORIGIN: ../../../flutter/display_list/display_list_attributes_testing.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/display_list/display_list_benchmarks.cc + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/display_list/display_list_benchmarks.h + ../../../flutter/LICENSE
-ORIGIN: ../../../flutter/display_list/display_list_benchmarks_canvas_provider.h + ../../../flutter/LICENSE
-ORIGIN: ../../../flutter/display_list/display_list_benchmarks_gl.cc + ../../../flutter/LICENSE
-ORIGIN: ../../../flutter/display_list/display_list_benchmarks_gl.h + ../../../flutter/LICENSE
-ORIGIN: ../../../flutter/display_list/display_list_benchmarks_metal.cc + ../../../flutter/LICENSE
-ORIGIN: ../../../flutter/display_list/display_list_benchmarks_metal.h + ../../../flutter/LICENSE
-ORIGIN: ../../../flutter/display_list/display_list_benchmarks_software.cc + ../../../flutter/LICENSE
-ORIGIN: ../../../flutter/display_list/display_list_benchmarks_software.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/display_list/display_list_blend_mode.cc + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/display_list/display_list_blend_mode.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/display_list/display_list_builder.cc + ../../../flutter/LICENSE
@@ -881,8 +873,6 @@
ORIGIN: ../../../flutter/display_list/display_list_runtime_effect.cc + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/display_list/display_list_runtime_effect.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/display_list/display_list_sampling_options.h + ../../../flutter/LICENSE
-ORIGIN: ../../../flutter/display_list/display_list_test_utils.cc + ../../../flutter/LICENSE
-ORIGIN: ../../../flutter/display_list/display_list_test_utils.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/display_list/display_list_tile_mode.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/display_list/display_list_utils.cc + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/display_list/display_list_utils.h + ../../../flutter/LICENSE
@@ -3309,16 +3299,8 @@
FILE: ../../../flutter/display_list/display_list.cc
FILE: ../../../flutter/display_list/display_list.h
FILE: ../../../flutter/display_list/display_list_attributes.h
-FILE: ../../../flutter/display_list/display_list_attributes_testing.h
FILE: ../../../flutter/display_list/display_list_benchmarks.cc
FILE: ../../../flutter/display_list/display_list_benchmarks.h
-FILE: ../../../flutter/display_list/display_list_benchmarks_canvas_provider.h
-FILE: ../../../flutter/display_list/display_list_benchmarks_gl.cc
-FILE: ../../../flutter/display_list/display_list_benchmarks_gl.h
-FILE: ../../../flutter/display_list/display_list_benchmarks_metal.cc
-FILE: ../../../flutter/display_list/display_list_benchmarks_metal.h
-FILE: ../../../flutter/display_list/display_list_benchmarks_software.cc
-FILE: ../../../flutter/display_list/display_list_benchmarks_software.h
FILE: ../../../flutter/display_list/display_list_blend_mode.cc
FILE: ../../../flutter/display_list/display_list_blend_mode.h
FILE: ../../../flutter/display_list/display_list_builder.cc
@@ -3368,8 +3350,6 @@
FILE: ../../../flutter/display_list/display_list_runtime_effect.cc
FILE: ../../../flutter/display_list/display_list_runtime_effect.h
FILE: ../../../flutter/display_list/display_list_sampling_options.h
-FILE: ../../../flutter/display_list/display_list_test_utils.cc
-FILE: ../../../flutter/display_list/display_list_test_utils.h
FILE: ../../../flutter/display_list/display_list_tile_mode.h
FILE: ../../../flutter/display_list/display_list_utils.cc
FILE: ../../../flutter/display_list/display_list_utils.h
diff --git a/display_list/BUILD.gn b/display_list/BUILD.gn
index 32756ec..160647a 100644
--- a/display_list/BUILD.gn
+++ b/display_list/BUILD.gn
@@ -86,23 +86,6 @@
fixtures = []
}
- source_set("display_list_testing") {
- testonly = true
-
- sources = [
- "display_list_attributes_testing.h",
- "display_list_test_utils.cc",
- "display_list_test_utils.h",
- ]
-
- deps = [
- "//flutter/testing:testing_lib",
- "//third_party/skia",
- ]
-
- public_deps = [ ":display_list" ]
- }
-
executable("display_list_unittests") {
testonly = true
@@ -126,7 +109,7 @@
deps = [
":display_list",
":display_list_fixtures",
- ":display_list_testing",
+ "//flutter/display_list/testing:display_list_testing",
"//flutter/testing",
]
@@ -153,7 +136,8 @@
deps = [
":display_list",
":display_list_fixtures",
- ":display_list_testing",
+ "//flutter/display_list/testing:display_list_surface_provider",
+ "//flutter/display_list/testing:display_list_testing",
"//flutter/testing",
]
@@ -180,8 +164,8 @@
deps = [
":display_list",
":display_list_fixtures",
- ":display_list_testing",
"//flutter/benchmarking",
+ "//flutter/display_list/testing:display_list_testing",
"//flutter/testing:testing_lib",
]
}
@@ -204,64 +188,13 @@
":display_list_benchmarks_fixtures",
"//flutter/benchmarking",
"//flutter/common/graphics",
+ "//flutter/display_list/testing:display_list_surface_provider",
"//flutter/fml",
"//flutter/testing:skia",
"//flutter/testing:testing_lib",
"//third_party/dart/runtime:libdart_jit", # for tracing
"//third_party/skia",
]
-
- defines = []
-
- if (is_android) {
- libs = [
- "android",
- "EGL",
- "GLESv2",
- ]
- }
-
- # We only do software benchmarks on non-mobile platforms
- if (!is_android && !is_ios) {
- sources += [
- "display_list_benchmarks_software.cc",
- "display_list_benchmarks_software.h",
- ]
- defines += [ "ENABLE_SOFTWARE_BENCHMARKS" ]
- }
-
- # iOS and Fuchsia don't support OpenGL
- _enable_gl_benchmarks = !is_fuchsia && !is_ios
-
- # TODO (https://github.com/flutter/flutter/issues/107357):
- # impeller_enable_vulkan currently requires skia to not use VMA, which inturn
- # causes linkage problems with swiftshader.
- if (impeller_enable_vulkan) {
- _enable_gl_benchmarks = false
- }
-
- if (_enable_gl_benchmarks) {
- defines += [ "ENABLE_OPENGL_BENCHMARKS" ]
- sources += [
- "display_list_benchmarks_gl.cc",
- "display_list_benchmarks_gl.h",
- ]
- deps += [ "//flutter/testing:opengl" ]
- }
-
- if (is_mac || is_ios) {
- defines += [ "ENABLE_METAL_BENCHMARKS" ]
- sources += [
- "display_list_benchmarks_metal.cc",
- "display_list_benchmarks_metal.h",
- ]
- deps += [ "//flutter/testing:metal" ]
- }
-
- # Don't snapshot test results on mobile platforms
- if (is_android || is_ios) {
- defines += [ "BENCHMARKS_NO_SNAPSHOT" ]
- }
}
executable("display_list_benchmarks") {
diff --git a/display_list/display_list_benchmarks.cc b/display_list/display_list_benchmarks.cc
index 03dd0a4..0ade02a 100644
--- a/display_list/display_list_benchmarks.cc
+++ b/display_list/display_list_benchmarks.cc
@@ -13,27 +13,6 @@
namespace flutter {
namespace testing {
-std::unique_ptr<CanvasProvider> CreateCanvasProvider(BackendType backend_type) {
- switch (backend_type) {
-#ifdef ENABLE_SOFTWARE_BENCHMARKS
- case kSoftware_Backend:
- return std::make_unique<SoftwareCanvasProvider>();
-#endif
-#ifdef ENABLE_OPENGL_BENCHMARKS
- case kOpenGL_Backend:
- return std::make_unique<OpenGLCanvasProvider>();
-#endif
-#ifdef ENABLE_METAL_BENCHMARKS
- case kMetal_Backend:
- return std::make_unique<MetalCanvasProvider>();
-#endif
- default:
- return nullptr;
- }
-
- return nullptr;
-}
-
SkPaint GetPaintForRun(unsigned attributes) {
SkPaint paint;
@@ -95,7 +74,7 @@
void BM_DrawLine(benchmark::State& state,
BackendType backend_type,
unsigned attributes) {
- auto canvas_provider = CreateCanvasProvider(backend_type);
+ auto surface_provider = DlSurfaceProvider::Create(backend_type);
DisplayListBuilder builder;
builder.setAttributesFromPaint(GetPaintForRun(attributes),
DisplayListOpFlags::kDrawLineFlags);
@@ -103,8 +82,9 @@
size_t length = state.range(0);
- canvas_provider->InitializeSurface(length, length);
- auto canvas = canvas_provider->GetSurface()->getCanvas();
+ surface_provider->InitializeSurface(length, length);
+ auto surface = surface_provider->GetPrimarySurface()->sk_surface();
+ auto canvas = surface->getCanvas();
state.counters["DrawCallCount"] = kLinesToDraw;
for (size_t i = 0; i < kLinesToDraw; i++) {
@@ -117,12 +97,12 @@
// We only want to time the actual rasterization.
for ([[maybe_unused]] auto _ : state) {
display_list->RenderTo(canvas);
- canvas_provider->GetSurface()->flushAndSubmit(true);
+ surface->flushAndSubmit(true);
}
- auto filename = canvas_provider->BackendName() + "-DrawLine-" +
+ auto filename = surface_provider->backend_name() + "-DrawLine-" +
std::to_string(state.range(0)) + ".png";
- canvas_provider->Snapshot(filename);
+ surface_provider->Snapshot(filename);
}
// Draws a series of square rects of the requested width across
@@ -132,7 +112,7 @@
void BM_DrawRect(benchmark::State& state,
BackendType backend_type,
unsigned attributes) {
- auto canvas_provider = CreateCanvasProvider(backend_type);
+ auto surface_provider = DlSurfaceProvider::Create(backend_type);
DisplayListBuilder builder;
builder.setAttributesFromPaint(GetPaintForRun(attributes),
DisplayListOpFlags::kDrawRectFlags);
@@ -140,8 +120,9 @@
size_t length = state.range(0);
size_t canvas_size = length * 2;
- canvas_provider->InitializeSurface(canvas_size, canvas_size);
- auto canvas = canvas_provider->GetSurface()->getCanvas();
+ surface_provider->InitializeSurface(canvas_size, canvas_size);
+ auto surface = surface_provider->GetPrimarySurface()->sk_surface();
+ auto canvas = surface->getCanvas();
// As rects have SkScalar dimensions, we want to ensure that we also
// draw rects with non-integer position and size
@@ -165,12 +146,12 @@
// We only want to time the actual rasterization.
for ([[maybe_unused]] auto _ : state) {
display_list->RenderTo(canvas);
- canvas_provider->GetSurface()->flushAndSubmit(true);
+ surface->flushAndSubmit(true);
}
- auto filename = canvas_provider->BackendName() + "-DrawRect-" +
+ auto filename = surface_provider->backend_name() + "-DrawRect-" +
std::to_string(state.range(0)) + ".png";
- canvas_provider->Snapshot(filename);
+ surface_provider->Snapshot(filename);
}
// Draws a series of ovals of the requested height with aspect ratio 3:2 across
@@ -180,7 +161,7 @@
void BM_DrawOval(benchmark::State& state,
BackendType backend_type,
unsigned attributes) {
- auto canvas_provider = CreateCanvasProvider(backend_type);
+ auto surface_provider = DlSurfaceProvider::Create(backend_type);
DisplayListBuilder builder;
builder.setAttributesFromPaint(GetPaintForRun(attributes),
DisplayListOpFlags::kDrawOvalFlags);
@@ -188,8 +169,9 @@
size_t length = state.range(0);
size_t canvas_size = length * 2;
- canvas_provider->InitializeSurface(canvas_size, canvas_size);
- auto canvas = canvas_provider->GetSurface()->getCanvas();
+ surface_provider->InitializeSurface(canvas_size, canvas_size);
+ auto surface = surface_provider->GetPrimarySurface()->sk_surface();
+ auto canvas = surface->getCanvas();
SkRect rect = SkRect::MakeXYWH(0, 0, length * 1.5f, length);
const SkScalar offset = 0.5f;
@@ -210,12 +192,12 @@
// We only want to time the actual rasterization.
for ([[maybe_unused]] auto _ : state) {
display_list->RenderTo(canvas);
- canvas_provider->GetSurface()->flushAndSubmit(true);
+ surface->flushAndSubmit(true);
}
- auto filename = canvas_provider->BackendName() + "-DrawOval-" +
+ auto filename = surface_provider->backend_name() + "-DrawOval-" +
std::to_string(state.range(0)) + ".png";
- canvas_provider->Snapshot(filename);
+ surface_provider->Snapshot(filename);
}
// Draws a series of circles of the requested radius across
@@ -225,7 +207,7 @@
void BM_DrawCircle(benchmark::State& state,
BackendType backend_type,
unsigned attributes) {
- auto canvas_provider = CreateCanvasProvider(backend_type);
+ auto surface_provider = DlSurfaceProvider::Create(backend_type);
DisplayListBuilder builder;
builder.setAttributesFromPaint(GetPaintForRun(attributes),
DisplayListOpFlags::kDrawCircleFlags);
@@ -233,8 +215,9 @@
size_t length = state.range(0);
size_t canvas_size = length * 2;
- canvas_provider->InitializeSurface(canvas_size, canvas_size);
- auto canvas = canvas_provider->GetSurface()->getCanvas();
+ surface_provider->InitializeSurface(canvas_size, canvas_size);
+ auto surface = surface_provider->GetPrimarySurface()->sk_surface();
+ auto canvas = surface->getCanvas();
SkScalar radius = length / 2.0f;
const SkScalar offset = 0.5f;
@@ -257,12 +240,12 @@
// We only want to time the actual rasterization.
for ([[maybe_unused]] auto _ : state) {
display_list->RenderTo(canvas);
- canvas_provider->GetSurface()->flushAndSubmit(true);
+ surface->flushAndSubmit(true);
}
- auto filename = canvas_provider->BackendName() + "-DrawCircle-" +
+ auto filename = surface_provider->backend_name() + "-DrawCircle-" +
std::to_string(state.range(0)) + ".png";
- canvas_provider->Snapshot(filename);
+ surface_provider->Snapshot(filename);
}
// Draws a series of rounded rects of the requested width across
@@ -273,7 +256,7 @@
BackendType backend_type,
unsigned attributes,
SkRRect::Type type) {
- auto canvas_provider = CreateCanvasProvider(backend_type);
+ auto surface_provider = DlSurfaceProvider::Create(backend_type);
DisplayListBuilder builder;
builder.setAttributesFromPaint(GetPaintForRun(attributes),
DisplayListOpFlags::kDrawRRectFlags);
@@ -281,8 +264,9 @@
size_t length = state.range(0);
size_t canvas_size = length * 2;
- canvas_provider->InitializeSurface(canvas_size, canvas_size);
- auto canvas = canvas_provider->GetSurface()->getCanvas();
+ surface_provider->InitializeSurface(canvas_size, canvas_size);
+ auto surface = surface_provider->GetPrimarySurface()->sk_surface();
+ auto canvas = surface->getCanvas();
SkVector radii[4] = {};
switch (type) {
@@ -334,12 +318,12 @@
// We only want to time the actual rasterization.
for ([[maybe_unused]] auto _ : state) {
display_list->RenderTo(canvas);
- canvas_provider->GetSurface()->flushAndSubmit(true);
+ surface->flushAndSubmit(true);
}
- auto filename = canvas_provider->BackendName() + "-DrawRRect-" +
+ auto filename = surface_provider->backend_name() + "-DrawRRect-" +
std::to_string(state.range(0)) + ".png";
- canvas_provider->Snapshot(filename);
+ surface_provider->Snapshot(filename);
}
// Draws a series of "DR" rects of the requested width across
@@ -353,7 +337,7 @@
BackendType backend_type,
unsigned attributes,
SkRRect::Type type) {
- auto canvas_provider = CreateCanvasProvider(backend_type);
+ auto surface_provider = DlSurfaceProvider::Create(backend_type);
DisplayListBuilder builder;
builder.setAttributesFromPaint(GetPaintForRun(attributes),
DisplayListOpFlags::kDrawDRRectFlags);
@@ -361,8 +345,9 @@
size_t length = state.range(0);
size_t canvas_size = length * 2;
- canvas_provider->InitializeSurface(canvas_size, canvas_size);
- auto canvas = canvas_provider->GetSurface()->getCanvas();
+ surface_provider->InitializeSurface(canvas_size, canvas_size);
+ auto surface = surface_provider->GetPrimarySurface()->sk_surface();
+ auto canvas = surface->getCanvas();
SkVector radii[4] = {};
switch (type) {
@@ -415,18 +400,18 @@
// We only want to time the actual rasterization.
for ([[maybe_unused]] auto _ : state) {
display_list->RenderTo(canvas);
- canvas_provider->GetSurface()->flushAndSubmit(true);
+ surface->flushAndSubmit(true);
}
- auto filename = canvas_provider->BackendName() + "-DrawDRRect-" +
+ auto filename = surface_provider->backend_name() + "-DrawDRRect-" +
std::to_string(state.range(0)) + ".png";
- canvas_provider->Snapshot(filename);
+ surface_provider->Snapshot(filename);
}
void BM_DrawArc(benchmark::State& state,
BackendType backend_type,
unsigned attributes) {
- auto canvas_provider = CreateCanvasProvider(backend_type);
+ auto surface_provider = DlSurfaceProvider::Create(backend_type);
DisplayListBuilder builder;
builder.setAttributesFromPaint(GetPaintForRun(attributes),
DisplayListOpFlags::kDrawArcNoCenterFlags);
@@ -435,8 +420,9 @@
size_t length = state.range(0);
size_t canvas_size = length * 2;
- canvas_provider->InitializeSurface(canvas_size, canvas_size);
- auto canvas = canvas_provider->GetSurface()->getCanvas();
+ surface_provider->InitializeSurface(canvas_size, canvas_size);
+ auto surface = surface_provider->GetPrimarySurface()->sk_surface();
+ auto canvas = surface->getCanvas();
SkScalar starting_angle = 0.0f;
SkScalar offset = 0.5f;
@@ -467,12 +453,12 @@
// We only want to time the actual rasterization.
for ([[maybe_unused]] auto _ : state) {
display_list->RenderTo(canvas);
- canvas_provider->GetSurface()->flushAndSubmit(true);
+ surface->flushAndSubmit(true);
}
- auto filename = canvas_provider->BackendName() + "-DrawArc-" +
+ auto filename = surface_provider->backend_name() + "-DrawArc-" +
std::to_string(state.range(0)) + ".png";
- canvas_provider->Snapshot(filename);
+ surface_provider->Snapshot(filename);
}
// Returns a list of SkPoints that represent `n` points equally spaced out
@@ -641,15 +627,16 @@
BackendType backend_type,
unsigned attributes,
SkPath::Verb type) {
- auto canvas_provider = CreateCanvasProvider(backend_type);
+ auto surface_provider = DlSurfaceProvider::Create(backend_type);
DisplayListBuilder builder;
builder.setAttributesFromPaint(GetPaintForRun(attributes),
DisplayListOpFlags::kDrawPathFlags);
AnnotateAttributes(attributes, state, DisplayListOpFlags::kDrawPathFlags);
size_t length = kFixedCanvasSize;
- canvas_provider->InitializeSurface(length, length);
- auto canvas = canvas_provider->GetSurface()->getCanvas();
+ surface_provider->InitializeSurface(length, length);
+ auto surface = surface_provider->GetPrimarySurface()->sk_surface();
+ auto canvas = surface->getCanvas();
SkPath path;
@@ -669,12 +656,12 @@
// We only want to time the actual rasterization.
for ([[maybe_unused]] auto _ : state) {
display_list->RenderTo(canvas);
- canvas_provider->GetSurface()->flushAndSubmit(true);
+ surface->flushAndSubmit(true);
}
- auto filename = canvas_provider->BackendName() + "-DrawPath-" + label + "-" +
- std::to_string(state.range(0)) + ".png";
- canvas_provider->Snapshot(filename);
+ auto filename = surface_provider->backend_name() + "-DrawPath-" + label +
+ "-" + std::to_string(state.range(0)) + ".png";
+ surface_provider->Snapshot(filename);
}
// Returns a set of vertices that describe a circle that has a
@@ -778,15 +765,16 @@
BackendType backend_type,
unsigned attributes,
DlVertexMode mode) {
- auto canvas_provider = CreateCanvasProvider(backend_type);
+ auto surface_provider = DlSurfaceProvider::Create(backend_type);
DisplayListBuilder builder;
builder.setAttributesFromPaint(GetPaintForRun(attributes),
DisplayListOpFlags::kDrawVerticesFlags);
AnnotateAttributes(attributes, state, DisplayListOpFlags::kDrawVerticesFlags);
size_t length = kFixedCanvasSize;
- canvas_provider->InitializeSurface(length, length);
- auto canvas = canvas_provider->GetSurface()->getCanvas();
+ surface_provider->InitializeSurface(length, length);
+ auto surface = surface_provider->GetPrimarySurface()->sk_surface();
+ auto canvas = surface->getCanvas();
SkPoint center = SkPoint::Make(length / 2.0f, length / 2.0f);
@@ -814,13 +802,13 @@
// We only want to time the actual rasterization.
for ([[maybe_unused]] auto _ : state) {
display_list->RenderTo(canvas);
- canvas_provider->GetSurface()->flushAndSubmit(true);
+ surface->flushAndSubmit(true);
}
- auto filename = canvas_provider->BackendName() + "-DrawVertices-" +
+ auto filename = surface_provider->backend_name() + "-DrawVertices-" +
std::to_string(disc_count) + "-" + VertexModeToString(mode) +
".png";
- canvas_provider->Snapshot(filename);
+ surface_provider->Snapshot(filename);
}
// Generate `count` test points.
@@ -873,7 +861,7 @@
BackendType backend_type,
unsigned attributes,
SkCanvas::PointMode mode) {
- auto canvas_provider = CreateCanvasProvider(backend_type);
+ auto surface_provider = DlSurfaceProvider::Create(backend_type);
DisplayListBuilder builder;
SkPaint paint;
switch (mode) {
@@ -901,8 +889,9 @@
}
size_t length = kFixedCanvasSize;
- canvas_provider->InitializeSurface(length, length);
- auto canvas = canvas_provider->GetSurface()->getCanvas();
+ surface_provider->InitializeSurface(length, length);
+ auto surface = surface_provider->GetPrimarySurface()->sk_surface();
+ auto canvas = surface->getCanvas();
size_t point_count = state.range(0);
state.SetComplexityN(point_count);
@@ -917,13 +906,13 @@
for ([[maybe_unused]] auto _ : state) {
display_list->RenderTo(canvas);
- canvas_provider->GetSurface()->flushAndSubmit(true);
+ surface->flushAndSubmit(true);
}
- auto filename = canvas_provider->BackendName() + "-DrawPoints-" +
+ auto filename = surface_provider->backend_name() + "-DrawPoints-" +
PointModeToString(mode) + "-" + std::to_string(point_count) +
".png";
- canvas_provider->Snapshot(filename);
+ surface_provider->Snapshot(filename);
}
sk_sp<SkImage> ImageFromBitmapWithNewID(const SkBitmap& bitmap) {
@@ -942,7 +931,7 @@
unsigned attributes,
DlImageSampling options,
bool upload_bitmap) {
- auto canvas_provider = CreateCanvasProvider(backend_type);
+ auto surface_provider = DlSurfaceProvider::Create(backend_type);
DisplayListBuilder builder;
builder.setAttributesFromPaint(GetPaintForRun(attributes),
DisplayListOpFlags::kDrawImageWithPaintFlags);
@@ -951,10 +940,12 @@
size_t bitmap_size = state.range(0);
size_t canvas_size = 2 * bitmap_size;
- canvas_provider->InitializeSurface(canvas_size, canvas_size);
- auto canvas = canvas_provider->GetSurface()->getCanvas();
+ surface_provider->InitializeSurface(canvas_size, canvas_size);
+ auto surface = surface_provider->GetPrimarySurface()->sk_surface();
+ auto canvas = surface->getCanvas();
sk_sp<SkImage> image;
+ std::shared_ptr<DlSurfaceInstance> offscreen_instance;
sk_sp<SkSurface> offscreen;
SkBitmap bitmap;
@@ -965,7 +956,9 @@
bitmap.allocPixels(info, 0);
bitmap.eraseColor(SK_ColorBLUE);
} else {
- offscreen = canvas_provider->MakeOffscreenSurface(bitmap_size, bitmap_size);
+ offscreen_instance =
+ surface_provider->MakeOffscreenSurface(bitmap_size, bitmap_size);
+ offscreen = offscreen_instance->sk_surface();
offscreen->getCanvas()->clear(SK_ColorRED);
}
@@ -991,13 +984,13 @@
for ([[maybe_unused]] auto _ : state) {
display_list->RenderTo(canvas);
- canvas_provider->GetSurface()->flushAndSubmit(true);
+ surface->flushAndSubmit(true);
}
- auto filename = canvas_provider->BackendName() + "-DrawImage-" +
+ auto filename = surface_provider->backend_name() + "-DrawImage-" +
(upload_bitmap ? "Upload-" : "Texture-") +
std::to_string(bitmap_size) + ".png";
- canvas_provider->Snapshot(filename);
+ surface_provider->Snapshot(filename);
}
std::string ConstraintToString(SkCanvas::SrcRectConstraint constraint) {
@@ -1021,7 +1014,7 @@
DlImageSampling options,
SkCanvas::SrcRectConstraint constraint,
bool upload_bitmap) {
- auto canvas_provider = CreateCanvasProvider(backend_type);
+ auto surface_provider = DlSurfaceProvider::Create(backend_type);
DisplayListBuilder builder;
builder.setAttributesFromPaint(
GetPaintForRun(attributes),
@@ -1031,10 +1024,12 @@
size_t bitmap_size = state.range(0);
size_t canvas_size = 2 * bitmap_size;
- canvas_provider->InitializeSurface(canvas_size, canvas_size);
- auto canvas = canvas_provider->GetSurface()->getCanvas();
+ surface_provider->InitializeSurface(canvas_size, canvas_size);
+ auto surface = surface_provider->GetPrimarySurface()->sk_surface();
+ auto canvas = surface->getCanvas();
sk_sp<SkImage> image;
+ std::shared_ptr<DlSurfaceInstance> offscreen_instance;
sk_sp<SkSurface> offscreen;
SkBitmap bitmap;
@@ -1045,7 +1040,9 @@
bitmap.allocPixels(info, 0);
bitmap.eraseColor(SK_ColorBLUE);
} else {
- offscreen = canvas_provider->MakeOffscreenSurface(bitmap_size, bitmap_size);
+ offscreen_instance =
+ surface_provider->MakeOffscreenSurface(bitmap_size, bitmap_size);
+ offscreen = offscreen_instance->sk_surface();
offscreen->getCanvas()->clear(SK_ColorRED);
}
@@ -1074,14 +1071,14 @@
for ([[maybe_unused]] auto _ : state) {
display_list->RenderTo(canvas);
- canvas_provider->GetSurface()->flushAndSubmit(true);
+ surface->flushAndSubmit(true);
}
- auto filename = canvas_provider->BackendName() + "-DrawImageRect-" +
+ auto filename = surface_provider->backend_name() + "-DrawImageRect-" +
(upload_bitmap ? "Upload-" : "Texture-") +
ConstraintToString(constraint) + "-" +
std::to_string(bitmap_size) + ".png";
- canvas_provider->Snapshot(filename);
+ surface_provider->Snapshot(filename);
}
std::string FilterModeToString(const DlFilterMode mode) {
@@ -1105,7 +1102,7 @@
unsigned attributes,
const DlFilterMode filter,
bool upload_bitmap) {
- auto canvas_provider = CreateCanvasProvider(backend_type);
+ auto surface_provider = DlSurfaceProvider::Create(backend_type);
DisplayListBuilder builder;
builder.setAttributesFromPaint(
GetPaintForRun(attributes),
@@ -1115,13 +1112,15 @@
size_t bitmap_size = state.range(0);
size_t canvas_size = 2 * bitmap_size;
- canvas_provider->InitializeSurface(canvas_size, canvas_size);
- auto canvas = canvas_provider->GetSurface()->getCanvas();
+ surface_provider->InitializeSurface(canvas_size, canvas_size);
+ auto surface = surface_provider->GetPrimarySurface()->sk_surface();
+ auto canvas = surface->getCanvas();
SkIRect center = SkIRect::MakeXYWH(bitmap_size / 4, bitmap_size / 4,
bitmap_size / 2, bitmap_size / 2);
sk_sp<SkImage> image;
+ std::shared_ptr<DlSurfaceInstance> offscreen_instance;
sk_sp<SkSurface> offscreen;
SkBitmap bitmap;
@@ -1132,7 +1131,9 @@
bitmap.allocPixels(info, 0);
bitmap.eraseColor(SK_ColorBLUE);
} else {
- offscreen = canvas_provider->MakeOffscreenSurface(bitmap_size, bitmap_size);
+ offscreen_instance =
+ surface_provider->MakeOffscreenSurface(bitmap_size, bitmap_size);
+ offscreen = offscreen_instance->sk_surface();
offscreen->getCanvas()->clear(SK_ColorRED);
}
@@ -1158,14 +1159,14 @@
for ([[maybe_unused]] auto _ : state) {
display_list->RenderTo(canvas);
- canvas_provider->GetSurface()->flushAndSubmit(true);
+ surface->flushAndSubmit(true);
}
- auto filename = canvas_provider->BackendName() + "-DrawImageNine-" +
+ auto filename = surface_provider->backend_name() + "-DrawImageNine-" +
(upload_bitmap ? "Upload-" : "Texture-") +
FilterModeToString(filter) + "-" +
std::to_string(bitmap_size) + ".png";
- canvas_provider->Snapshot(filename);
+ surface_provider->Snapshot(filename);
}
// Draws a series of glyph runs with 32 glyphs in each run. The number of runs
@@ -1178,7 +1179,7 @@
void BM_DrawTextBlob(benchmark::State& state,
BackendType backend_type,
unsigned attributes) {
- auto canvas_provider = CreateCanvasProvider(backend_type);
+ auto surface_provider = DlSurfaceProvider::Create(backend_type);
DisplayListBuilder builder;
builder.setAttributesFromPaint(GetPaintForRun(attributes),
DisplayListOpFlags::kDrawTextBlobFlags);
@@ -1186,8 +1187,9 @@
size_t draw_calls = state.range(0);
size_t canvas_size = kFixedCanvasSize;
- canvas_provider->InitializeSurface(canvas_size, canvas_size);
- auto canvas = canvas_provider->GetSurface()->getCanvas();
+ surface_provider->InitializeSurface(canvas_size, canvas_size);
+ auto surface = surface_provider->GetPrimarySurface()->sk_surface();
+ auto canvas = surface->getCanvas();
state.counters["DrawCallCount_Varies"] = draw_calls;
state.counters["GlyphCount"] = draw_calls;
@@ -1203,12 +1205,12 @@
for ([[maybe_unused]] auto _ : state) {
display_list->RenderTo(canvas);
- canvas_provider->GetSurface()->flushAndSubmit(true);
+ surface->flushAndSubmit(true);
}
- auto filename = canvas_provider->BackendName() + "-DrawTextBlob-" +
+ auto filename = surface_provider->backend_name() + "-DrawTextBlob-" +
std::to_string(draw_calls) + ".png";
- canvas_provider->Snapshot(filename);
+ surface_provider->Snapshot(filename);
}
// Draw the shadow for a 10-sided regular polygon where the polygon's
@@ -1224,15 +1226,16 @@
unsigned attributes,
bool transparent_occluder,
SkPath::Verb type) {
- auto canvas_provider = CreateCanvasProvider(backend_type);
+ auto surface_provider = DlSurfaceProvider::Create(backend_type);
DisplayListBuilder builder;
builder.setAttributesFromPaint(GetPaintForRun(attributes),
DisplayListOpFlags::kDrawShadowFlags);
AnnotateAttributes(attributes, state, DisplayListOpFlags::kDrawShadowFlags);
size_t length = kFixedCanvasSize;
- canvas_provider->InitializeSurface(length, length);
- auto canvas = canvas_provider->GetSurface()->getCanvas();
+ surface_provider->InitializeSurface(length, length);
+ auto surface = surface_provider->GetPrimarySurface()->sk_surface();
+ auto canvas = surface->getCanvas();
SkPath path;
@@ -1267,14 +1270,14 @@
// We only want to time the actual rasterization.
for ([[maybe_unused]] auto _ : state) {
display_list->RenderTo(canvas);
- canvas_provider->GetSurface()->flushAndSubmit(true);
+ surface->flushAndSubmit(true);
}
- auto filename = canvas_provider->BackendName() + "-DrawShadow-" +
+ auto filename = surface_provider->backend_name() + "-DrawShadow-" +
VerbToString(type) + "-" +
(transparent_occluder ? "Transparent-" : "Opaque-") +
std::to_string(elevation) + "-" + ".png";
- canvas_provider->Snapshot(filename);
+ surface_provider->Snapshot(filename);
}
// Calls saveLayer N times from the root canvas layer, and optionally calls
@@ -1287,15 +1290,16 @@
BackendType backend_type,
unsigned attributes,
size_t save_depth) {
- auto canvas_provider = CreateCanvasProvider(backend_type);
+ auto surface_provider = DlSurfaceProvider::Create(backend_type);
DisplayListBuilder builder;
builder.setAttributesFromPaint(GetPaintForRun(attributes),
DisplayListOpFlags::kSaveLayerFlags);
AnnotateAttributes(attributes, state, DisplayListOpFlags::kSaveLayerFlags);
size_t length = kFixedCanvasSize;
- canvas_provider->InitializeSurface(length, length);
- auto canvas = canvas_provider->GetSurface()->getCanvas();
+ surface_provider->InitializeSurface(length, length);
+ auto surface = surface_provider->GetPrimarySurface()->sk_surface();
+ auto canvas = surface->getCanvas();
size_t save_layer_calls = state.range(0);
@@ -1320,14 +1324,26 @@
// We only want to time the actual rasterization.
for ([[maybe_unused]] auto _ : state) {
display_list->RenderTo(canvas);
- canvas_provider->GetSurface()->flushAndSubmit(true);
+ surface->flushAndSubmit(true);
}
- auto filename = canvas_provider->BackendName() + "-SaveLayer-" +
+ auto filename = surface_provider->backend_name() + "-SaveLayer-" +
std::to_string(save_depth) + "-" +
std::to_string(save_layer_calls) + ".png";
- canvas_provider->Snapshot(filename);
+ surface_provider->Snapshot(filename);
}
+#ifdef ENABLE_SOFTWARE_BENCHMARKS
+RUN_DISPLAYLIST_BENCHMARKS(Software)
+#endif
+
+#ifdef ENABLE_OPENGL_BENCHMARKS
+RUN_DISPLAYLIST_BENCHMARKS(OpenGL)
+#endif
+
+#ifdef ENABLE_METAL_BENCHMARKS
+RUN_DISPLAYLIST_BENCHMARKS(Metal)
+#endif
+
} // namespace testing
} // namespace flutter
diff --git a/display_list/display_list_benchmarks.h b/display_list/display_list_benchmarks.h
index 38c27ed..ad64fdc 100644
--- a/display_list/display_list_benchmarks.h
+++ b/display_list/display_list_benchmarks.h
@@ -5,9 +5,9 @@
#ifndef FLUTTER_FLOW_DISPLAY_LIST_BENCHMARKS_H_
#define FLUTTER_FLOW_DISPLAY_LIST_BENCHMARKS_H_
-#include "flutter/display_list/display_list_benchmarks_canvas_provider.h"
#include "flutter/display_list/display_list_sampling_options.h"
#include "flutter/display_list/display_list_vertices.h"
+#include "flutter/display_list/testing/dl_test_surface_provider.h"
#include "third_party/benchmark/include/benchmark/benchmark.h"
#include "third_party/skia/include/core/SkCanvas.h"
@@ -16,21 +16,9 @@
#include "third_party/skia/include/core/SkSurface.h"
#include "third_party/skia/include/core/SkVertices.h"
-#ifdef ENABLE_SOFTWARE_BENCHMARKS
-#include "flutter/display_list/display_list_benchmarks_software.h"
-#endif
-#ifdef ENABLE_OPENGL_BENCHMARKS
-#include "flutter/display_list/display_list_benchmarks_gl.h"
-#endif
-#ifdef ENABLE_METAL_BENCHMARKS
-#include "flutter/display_list/display_list_benchmarks_metal.h"
-#endif
-
namespace flutter {
namespace testing {
-typedef enum { kSoftware_Backend, kOpenGL_Backend, kMetal_Backend } BackendType;
-
enum BenchmarkAttributes {
kEmpty_Flag = 0,
kStrokedStyle_Flag = 1 << 0,
@@ -39,9 +27,10 @@
kAntiAliasing_Flag = 1 << 3
};
-std::unique_ptr<CanvasProvider> CreateCanvasProvider(BackendType backend_type);
SkPaint GetPaintForRun(unsigned attributes);
+using BackendType = DlSurfaceProvider::BackendType;
+
// Benchmarks
void BM_DrawLine(benchmark::State& state,
diff --git a/display_list/display_list_benchmarks_canvas_provider.h b/display_list/display_list_benchmarks_canvas_provider.h
deleted file mode 100644
index 3b12ef7..0000000
--- a/display_list/display_list_benchmarks_canvas_provider.h
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright 2013 The Flutter Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef FLUTTER_FLOW_DISPLAY_LIST_BENCHMARKS_CANVAS_PROVIDER_H_
-#define FLUTTER_FLOW_DISPLAY_LIST_BENCHMARKS_CANVAS_PROVIDER_H_
-
-#include "flutter/fml/mapping.h"
-#include "flutter/testing/testing.h"
-
-#include "third_party/skia/include/core/SkData.h"
-#include "third_party/skia/include/core/SkSurface.h"
-
-namespace flutter {
-namespace testing {
-
-class CanvasProvider {
- public:
- virtual ~CanvasProvider() = default;
- virtual const std::string BackendName() = 0;
- virtual void InitializeSurface(const size_t width, const size_t height) = 0;
- virtual sk_sp<SkSurface> GetSurface() = 0;
- virtual sk_sp<SkSurface> MakeOffscreenSurface(const size_t width,
- const size_t height) = 0;
-
- virtual bool Snapshot(std::string filename) {
-#ifdef BENCHMARKS_NO_SNAPSHOT
- return false;
-#else
- auto image = GetSurface()->makeImageSnapshot();
- if (!image) {
- return false;
- }
- auto raster = image->makeRasterImage();
- if (!raster) {
- return false;
- }
- auto data = raster->encodeToData();
- if (!data) {
- return false;
- }
- fml::NonOwnedMapping mapping(static_cast<const uint8_t*>(data->data()),
- data->size());
- return WriteAtomically(OpenFixturesDirectory(), filename.c_str(), mapping);
-#endif
- }
-};
-
-} // namespace testing
-} // namespace flutter
-
-#endif // FLUTTER_FLOW_DISPLAY_LIST_BENCHMARKS_CANVAS_PROVIDER_H_
diff --git a/display_list/display_list_benchmarks_gl.cc b/display_list/display_list_benchmarks_gl.cc
deleted file mode 100644
index fcf5f96..0000000
--- a/display_list/display_list_benchmarks_gl.cc
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright 2013 The Flutter Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "flutter/display_list/display_list_benchmarks_gl.h"
-#include "flutter/display_list/display_list_benchmarks.h"
-
-#include "third_party/skia/include/core/SkCanvas.h"
-#include "third_party/skia/include/core/SkSurface.h"
-
-namespace flutter {
-namespace testing {
-
-void OpenGLCanvasProvider::InitializeSurface(const size_t width,
- const size_t height) {
- surface_size_ = SkISize::Make(width, height);
-
- gl_surface_ = std::make_unique<TestGLSurface>(surface_size_);
- gl_surface_->MakeCurrent();
-
- const auto image_info = SkImageInfo::MakeN32Premul(surface_size_);
- surface_ = SkSurface::MakeRenderTarget(
- gl_surface_->GetGrContext().get(), skgpu::Budgeted::kNo, image_info, 1,
- kTopLeft_GrSurfaceOrigin, nullptr, false);
- surface_->getCanvas()->clear(SK_ColorTRANSPARENT);
-}
-
-sk_sp<SkSurface> OpenGLCanvasProvider::GetSurface() {
- if (!gl_surface_->MakeCurrent()) {
- return nullptr;
- }
- return surface_;
-}
-
-sk_sp<SkSurface> OpenGLCanvasProvider::MakeOffscreenSurface(
- const size_t width,
- const size_t height) {
- surface_size_ = SkISize::Make(width, height);
- const auto image_info = SkImageInfo::MakeN32Premul(surface_size_);
-
- auto offscreen_surface = SkSurface::MakeRenderTarget(
- gl_surface_->GetGrContext().get(), skgpu::Budgeted::kNo, image_info, 1,
- kTopLeft_GrSurfaceOrigin, nullptr, false);
-
- offscreen_surface->getCanvas()->clear(SK_ColorTRANSPARENT);
- return offscreen_surface;
-}
-
-RUN_DISPLAYLIST_BENCHMARKS(OpenGL)
-
-} // namespace testing
-} // namespace flutter
diff --git a/display_list/display_list_benchmarks_gl.h b/display_list/display_list_benchmarks_gl.h
deleted file mode 100644
index e00eaeb..0000000
--- a/display_list/display_list_benchmarks_gl.h
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright 2013 The Flutter Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef FLUTTER_FLOW_DISPLAY_LIST_BENCHMARKS_GL_H_
-#define FLUTTER_FLOW_DISPLAY_LIST_BENCHMARKS_GL_H_
-
-#include "flutter/display_list/display_list_benchmarks_canvas_provider.h"
-
-#include "flutter/testing/test_gl_surface.h"
-
-#include "third_party/skia/include/core/SkSurface.h"
-
-namespace flutter {
-namespace testing {
-
-class OpenGLCanvasProvider : public CanvasProvider {
- public:
- virtual ~OpenGLCanvasProvider() = default;
- void InitializeSurface(const size_t width, const size_t height) override;
- sk_sp<SkSurface> GetSurface() override;
- sk_sp<SkSurface> MakeOffscreenSurface(const size_t width,
- const size_t height) override;
- const std::string BackendName() override { return "OpenGL"; }
-
- private:
- SkISize surface_size_;
- sk_sp<SkSurface> surface_;
- std::unique_ptr<TestGLSurface> gl_surface_;
-};
-
-} // namespace testing
-} // namespace flutter
-
-#endif // FLUTTER_FLOW_DISPLAY_LIST_BENCHMARKS_GL_H_
diff --git a/display_list/display_list_benchmarks_metal.cc b/display_list/display_list_benchmarks_metal.cc
deleted file mode 100644
index 2437663..0000000
--- a/display_list/display_list_benchmarks_metal.cc
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright 2013 The Flutter Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "flutter/display_list/display_list_benchmarks_metal.h"
-#include "flutter/display_list/display_list_benchmarks.h"
-
-#include "third_party/skia/include/core/SkCanvas.h"
-#include "third_party/skia/include/core/SkSurface.h"
-
-namespace flutter {
-namespace testing {
-
-void MetalCanvasProvider::InitializeSurface(const size_t width,
- const size_t height) {
- metal_context_ = std::make_unique<TestMetalContext>();
- metal_surface_ =
- TestMetalSurface::Create(*metal_context_, SkISize::Make(width, height));
- metal_surface_->GetSurface()->getCanvas()->clear(SK_ColorTRANSPARENT);
-}
-
-sk_sp<SkSurface> MetalCanvasProvider::GetSurface() {
- if (!metal_surface_) {
- return nullptr;
- }
- return metal_surface_->GetSurface();
-}
-
-sk_sp<SkSurface> MetalCanvasProvider::MakeOffscreenSurface(
- const size_t width,
- const size_t height) {
- metal_offscreen_surface_ =
- TestMetalSurface::Create(*metal_context_, SkISize::Make(width, height));
- return metal_offscreen_surface_->GetSurface();
-}
-
-RUN_DISPLAYLIST_BENCHMARKS(Metal)
-
-} // namespace testing
-} // namespace flutter
diff --git a/display_list/display_list_benchmarks_metal.h b/display_list/display_list_benchmarks_metal.h
deleted file mode 100644
index bb8f635..0000000
--- a/display_list/display_list_benchmarks_metal.h
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright 2013 The Flutter Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef FLUTTER_FLOW_DISPLAY_LIST_BENCHMARKS_METAL_H_
-#define FLUTTER_FLOW_DISPLAY_LIST_BENCHMARKS_METAL_H_
-
-#include "flutter/display_list/display_list_benchmarks_canvas_provider.h"
-#include "flutter/testing/test_metal_surface.h"
-
-#include "third_party/skia/include/core/SkSurface.h"
-
-namespace flutter {
-namespace testing {
-
-class MetalCanvasProvider : public CanvasProvider {
- public:
- virtual ~MetalCanvasProvider() = default;
-
- void InitializeSurface(const size_t width, const size_t height) override;
- sk_sp<SkSurface> GetSurface() override;
- sk_sp<SkSurface> MakeOffscreenSurface(const size_t width,
- const size_t height) override;
- const std::string BackendName() override { return "Metal"; }
-
- private:
- std::unique_ptr<TestMetalContext> metal_context_;
- std::unique_ptr<TestMetalSurface> metal_surface_;
- std::unique_ptr<TestMetalSurface> metal_offscreen_surface_;
-};
-
-} // namespace testing
-} // namespace flutter
-
-#endif // FLUTTER_FLOW_DISPLAY_LIST_BENCHMARKS_METAL_H_
diff --git a/display_list/display_list_benchmarks_software.cc b/display_list/display_list_benchmarks_software.cc
deleted file mode 100644
index 7e2e7f4..0000000
--- a/display_list/display_list_benchmarks_software.cc
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright 2013 The Flutter Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "flutter/display_list/display_list_benchmarks_software.h"
-#include "flutter/display_list/display_list_benchmarks.h"
-
-#include "third_party/skia/include/core/SkSurface.h"
-
-namespace flutter {
-namespace testing {
-
-void SoftwareCanvasProvider::InitializeSurface(const size_t width,
- const size_t height) {
- surface_ = SkSurface::MakeRasterN32Premul(width, height);
- surface_->getCanvas()->clear(SK_ColorTRANSPARENT);
-}
-
-sk_sp<SkSurface> SoftwareCanvasProvider::MakeOffscreenSurface(
- const size_t width,
- const size_t height) {
- auto surface = SkSurface::MakeRasterN32Premul(width, height);
- surface->getCanvas()->clear(SK_ColorTRANSPARENT);
- return surface;
-}
-
-RUN_DISPLAYLIST_BENCHMARKS(Software)
-
-} // namespace testing
-} // namespace flutter
diff --git a/display_list/display_list_benchmarks_software.h b/display_list/display_list_benchmarks_software.h
deleted file mode 100644
index 6451c0c..0000000
--- a/display_list/display_list_benchmarks_software.h
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2013 The Flutter Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef FLUTTER_FLOW_DISPLAY_LIST_BENCHMARKS_SOFTWARE_H_
-#define FLUTTER_FLOW_DISPLAY_LIST_BENCHMARKS_SOFTWARE_H_
-
-#include "flutter/display_list/display_list_benchmarks_canvas_provider.h"
-
-#include "third_party/skia/include/core/SkSurface.h"
-
-namespace flutter {
-namespace testing {
-
-class SoftwareCanvasProvider : public CanvasProvider {
- public:
- virtual ~SoftwareCanvasProvider() = default;
- void InitializeSurface(const size_t width, const size_t height) override;
- sk_sp<SkSurface> GetSurface() override { return surface_; }
- sk_sp<SkSurface> MakeOffscreenSurface(const size_t width,
- const size_t height) override;
- const std::string BackendName() override { return "Software"; }
-
- private:
- sk_sp<SkSurface> surface_;
-};
-
-} // namespace testing
-} // namespace flutter
-
-#endif // FLUTTER_FLOW_DISPLAY_LIST_BENCHMARKS_SOFTWARE_H_
diff --git a/display_list/display_list_builder_benchmarks.cc b/display_list/display_list_builder_benchmarks.cc
index 5727057..5228c4b 100644
--- a/display_list/display_list_builder_benchmarks.cc
+++ b/display_list/display_list_builder_benchmarks.cc
@@ -3,7 +3,7 @@
// found in the LICENSE file.
#include "flutter/benchmarking/benchmarking.h"
-#include "flutter/display_list/display_list_test_utils.h"
+#include "flutter/display_list/testing/dl_test_snippets.h"
namespace flutter {
namespace {
diff --git a/display_list/display_list_canvas_unittests.cc b/display_list/display_list_canvas_unittests.cc
index aebb618..29401b9 100644
--- a/display_list/display_list_canvas_unittests.cc
+++ b/display_list/display_list_canvas_unittests.cc
@@ -10,6 +10,7 @@
#include "flutter/display_list/display_list_comparable.h"
#include "flutter/display_list/display_list_flags.h"
#include "flutter/display_list/display_list_sampling_options.h"
+#include "flutter/display_list/testing/dl_test_surface_provider.h"
#include "flutter/fml/math.h"
#include "flutter/testing/testing.h"
#include "third_party/skia/include/core/SkPictureRecorder.h"
@@ -176,6 +177,13 @@
return copy;
}
+ BoundsTolerance addPostClipPadding(SkScalar absolute_pad_x,
+ SkScalar absolute_pad_y) const {
+ BoundsTolerance copy = BoundsTolerance(*this);
+ copy.clip_pad_.offset(absolute_pad_x, absolute_pad_y);
+ return copy;
+ }
+
BoundsTolerance addDiscreteOffset(SkScalar discrete_offset) const {
BoundsTolerance copy = BoundsTolerance(*this);
copy.discrete_offset_ += discrete_offset;
@@ -206,6 +214,7 @@
if (!allowed.intersect(clip_)) {
allowed.setEmpty();
}
+ allowed.outset(clip_pad_.fX, clip_pad_.fY);
SkIRect rounded = allowed.roundOut();
int pad_left = std::max(0, pix_bounds.fLeft - rounded.fLeft);
int pad_top = std::max(0, pix_bounds.fTop - rounded.fTop);
@@ -215,7 +224,7 @@
int allowed_pad_y = std::max(pad_top, pad_bottom);
if (worst_bounds_pad_x > allowed_pad_x ||
worst_bounds_pad_y > allowed_pad_y) {
- FML_LOG(ERROR) << "allowed pad: " //
+ FML_LOG(ERROR) << "acceptable bounds padding: " //
<< allowed_pad_x << ", " << allowed_pad_y;
}
return (worst_bounds_pad_x > allowed_pad_x ||
@@ -229,6 +238,7 @@
SkPoint scale_ = {1, 1};
SkPoint absolute_pad_ = {0, 0};
SkRect clip_ = {-1E9, -1E9, 1E9, 1E9};
+ SkPoint clip_pad_ = {0, 0};
SkScalar discrete_offset_ = 0;
};
@@ -236,99 +246,268 @@
typedef const std::function<void(SkCanvas*, SkPaint&)> CvSetup;
typedef const std::function<void(SkCanvas*, const SkPaint&)> CvRenderer;
typedef const std::function<void(DisplayListBuilder&)> DlRenderer;
-static void EmptyCvRenderer(SkCanvas*, const SkPaint&) {}
-static void EmptyDlRenderer(DisplayListBuilder&) {}
+static const CvSetup kEmptyCvSetup = [](SkCanvas*, SkPaint&) {};
+static const CvRenderer kEmptyCvRenderer = [](SkCanvas*, const SkPaint&) {};
+static const DlRenderer kEmptyDlRenderer = [](DisplayListBuilder&) {};
-class RenderSurface {
+using PixelFormat = DlSurfaceProvider::PixelFormat;
+using BackendType = DlSurfaceProvider::BackendType;
+
+class RenderResult {
public:
- explicit RenderSurface(sk_sp<SkSurface> surface)
- : surface_(std::move(surface)) {
- EXPECT_EQ(canvas()->save(), 1);
+ RenderResult(const sk_sp<SkSurface>& surface,
+ const SkMatrix& matrix,
+ const SkIRect& clip_bounds)
+ : matrix_(matrix), clip_bounds_(clip_bounds) {
+ SkImageInfo info = surface->imageInfo();
+ info = SkImageInfo::MakeN32Premul(info.dimensions());
+ addr_ = malloc(info.computeMinByteSize() * info.height());
+ pixmap_.reset(info, addr_, info.minRowBytes());
+ EXPECT_TRUE(surface->readPixels(pixmap_, 0, 0));
}
- ~RenderSurface() { sk_free(addr_); }
+ ~RenderResult() { free(addr_); }
- SkCanvas* canvas() { return surface_->getCanvas(); }
+ int width() const { return pixmap_.width(); }
+ int height() const { return pixmap_.height(); }
+ const SkMatrix& matrix() const { return matrix_; }
+ const SkIRect& clip_bounds() const { return clip_bounds_; }
+ const uint32_t* addr32(int x, int y) const { return pixmap_.addr32(x, y); }
- const SkPixmap* pixmap() {
- if (!pixmap_.addr()) {
- canvas()->restoreToCount(1);
- SkImageInfo info = surface_->imageInfo();
- if (info.colorType() != kN32_SkColorType ||
- !surface_->peekPixels(&pixmap_)) {
- info = SkImageInfo::MakeN32Premul(info.dimensions());
- addr_ = malloc(info.computeMinByteSize() * info.height());
- pixmap_.reset(info, addr_, info.minRowBytes());
- EXPECT_TRUE(surface_->readPixels(pixmap_, 0, 0));
- }
+ private:
+ SkPixmap pixmap_;
+ void* addr_ = nullptr;
+ SkMatrix matrix_;
+ SkIRect clip_bounds_;
+};
+
+struct RenderJobInfo {
+ int width = kTestWidth;
+ int height = kTestHeight;
+ DlColor bg = DlColor::kTransparent();
+ SkScalar scale = SK_Scalar1;
+ SkScalar opacity = SK_Scalar1;
+};
+
+struct JobRenderer {
+ virtual void Render(SkCanvas* canvas,
+ const RenderJobInfo& info,
+ SkMatrix* setup_matrix = nullptr,
+ SkIRect* setup_clip_bounds = nullptr) = 0;
+};
+
+struct CvJobRenderer : public JobRenderer {
+ explicit CvJobRenderer(CvSetup& cv_setup = kEmptyCvSetup,
+ CvRenderer& cv_render = kEmptyCvRenderer,
+ CvRenderer& cv_restore = kEmptyCvRenderer)
+ : cv_setup_(cv_setup), cv_render_(cv_render), cv_restore_(cv_restore) {}
+
+ void Render(SkCanvas* canvas,
+ const RenderJobInfo& info,
+ SkMatrix* setup_matrix = nullptr,
+ SkIRect* setup_clip_bounds = nullptr) override {
+ FML_DCHECK(info.opacity == SK_Scalar1);
+ SkPaint paint;
+ cv_setup_(canvas, paint);
+ setup_paint_ = paint;
+ paint_is_setup_ = true;
+ if (setup_matrix) {
+ *setup_matrix = canvas->getTotalMatrix();
}
- return &pixmap_;
+ if (setup_clip_bounds) {
+ *setup_clip_bounds = canvas->getDeviceClipBounds();
+ }
+ cv_render_(canvas, paint);
+ cv_restore_(canvas, paint);
+ }
+
+ sk_sp<SkPicture> MakePicture() {
+ SkPictureRecorder recorder;
+ SkRTreeFactory rtree_factory;
+ SkCanvas* cv = recorder.beginRecording(kTestBounds, &rtree_factory);
+ Render(cv, {}, nullptr, nullptr);
+ return recorder.finishRecordingAsPicture();
+ }
+
+ SkPaint& setup_paint() {
+ FML_CHECK(paint_is_setup_);
+ return setup_paint_;
}
private:
- sk_sp<SkSurface> surface_;
- SkPixmap pixmap_;
- void* addr_ = nullptr;
+ CvSetup cv_setup_;
+ CvRenderer cv_render_;
+ CvRenderer cv_restore_;
+ bool paint_is_setup_ = false;
+ SkPaint setup_paint_;
+};
+
+struct CvPictureRenderJob : public JobRenderer {
+ explicit CvPictureRenderJob(sk_sp<SkPicture> picture)
+ : picture_(std::move(picture)) {}
+
+ void Render(SkCanvas* canvas,
+ const RenderJobInfo& info,
+ SkMatrix* setup_matrix = nullptr,
+ SkIRect* setup_clip_bounds = nullptr) {
+ FML_DCHECK(info.opacity == SK_Scalar1);
+ picture_->playback(canvas);
+ }
+
+ private:
+ sk_sp<SkPicture> picture_;
+};
+
+struct DlRenderJob : public JobRenderer {
+ explicit DlRenderJob(DlRenderer& dl_setup = kEmptyDlRenderer,
+ DlRenderer& dl_render = kEmptyDlRenderer,
+ DlRenderer& dl_restore = kEmptyDlRenderer)
+ : dl_setup_(dl_setup),
+ dl_render_(dl_render),
+ dl_restore_(dl_restore),
+ is_built_(false) {}
+
+ explicit DlRenderJob(sk_sp<DisplayList> display_list)
+ : dl_setup_(kEmptyDlRenderer),
+ dl_render_(kEmptyDlRenderer),
+ dl_restore_(kEmptyDlRenderer),
+ is_built_(true),
+ display_list_(std::move(display_list)) {}
+
+ void Render(SkCanvas* canvas,
+ const RenderJobInfo& info,
+ SkMatrix* setup_matrix = nullptr,
+ SkIRect* setup_clip_bounds = nullptr) {
+ get_display_list(info, setup_matrix, setup_clip_bounds)
+ ->RenderTo(canvas, info.opacity);
+ }
+
+ sk_sp<DisplayList> display_list() {
+ FML_CHECK(is_built_);
+ return display_list_;
+ }
+
+ private:
+ sk_sp<DisplayList> get_display_list(const RenderJobInfo& info,
+ SkMatrix* setup_matrix,
+ SkIRect* setup_clip_bounds) {
+ if (!display_list_) {
+ DisplayListBuilder builder(SkRect::MakeWH(info.width, info.height));
+ dl_setup_(builder);
+ if (setup_matrix) {
+ *setup_matrix = builder.getTransform();
+ }
+ if (setup_clip_bounds) {
+ *setup_clip_bounds = builder.getDestinationClipBounds().roundOut();
+ }
+ dl_render_(builder);
+ dl_restore_(builder);
+ display_list_ = builder.Build();
+ is_built_ = true;
+ }
+ return display_list_;
+ }
+
+ const DlRenderer dl_setup_;
+ const DlRenderer dl_render_;
+ const DlRenderer dl_restore_;
+ bool is_built_;
+ sk_sp<DisplayList> display_list_;
};
class RenderEnvironment {
public:
- static RenderEnvironment Make565() {
- return RenderEnvironment(
- SkImageInfo::Make({1, 1}, kRGB_565_SkColorType, kOpaque_SkAlphaType));
+ RenderEnvironment(const DlSurfaceProvider* provider, PixelFormat format)
+ : provider_(provider), format_(format) {
+ if (provider->supports(format)) {
+ surface_1x_ =
+ provider->MakeOffscreenSurface(kTestWidth, kTestHeight, format);
+ surface_2x_ = provider->MakeOffscreenSurface(kTestWidth * 2,
+ kTestHeight * 2, format);
+ }
}
- static RenderEnvironment MakeN32() {
- return RenderEnvironment(SkImageInfo::MakeN32Premul(1, 1));
+ static RenderEnvironment Make565(const DlSurfaceProvider* provider) {
+ return RenderEnvironment(provider, PixelFormat::k565_PixelFormat);
}
- std::unique_ptr<RenderSurface> MakeSurface(
- const DlColor bg = DlColor::kTransparent(),
- int width = kTestWidth,
- int height = kTestHeight) const {
- sk_sp<SkSurface> surface =
- SkSurface::MakeRaster(info_.makeWH(width, height));
- surface->getCanvas()->clear(bg);
- return std::make_unique<RenderSurface>(surface);
+ static RenderEnvironment MakeN32(const DlSurfaceProvider* provider) {
+ return RenderEnvironment(provider, PixelFormat::kN32Premul_PixelFormat);
}
void init_ref(CvRenderer& cv_renderer, DlColor bg = DlColor::kTransparent()) {
- init_ref([=](SkCanvas*, SkPaint&) {}, cv_renderer,
- [=](DisplayListBuilder&) {}, bg);
+ init_ref(kEmptyCvSetup, cv_renderer, kEmptyDlRenderer, bg);
}
void init_ref(CvSetup& cv_setup,
CvRenderer& cv_renderer,
DlRenderer& dl_setup,
DlColor bg = DlColor::kTransparent()) {
- ref_canvas()->clear(bg);
+ CvJobRenderer job(cv_setup, cv_renderer);
+ RenderJobInfo info = {
+ .bg = bg,
+ };
+ ref_result_ = getResult(info, job);
dl_setup(ref_attr_);
- SkPaint paint;
- cv_setup(ref_canvas(), paint);
- ref_matrix_ = ref_canvas()->getTotalMatrix();
- ref_clip_ = ref_canvas()->getDeviceClipBounds();
- cv_renderer(ref_canvas(), paint);
- ref_pixmap_ = ref_surface_->pixmap();
}
- const SkImageInfo& info() const { return info_; }
- SkCanvas* ref_canvas() { return ref_surface_->canvas(); }
+ std::unique_ptr<RenderResult> getResult(const RenderJobInfo& info,
+ JobRenderer& renderer) const {
+ auto surface = getSurface(info.width, info.height);
+ FML_DCHECK(surface != nullptr);
+ auto canvas = surface->getCanvas();
+ canvas->clear(info.bg);
+
+ int restore_count = canvas->save();
+ canvas->scale(info.scale, info.scale);
+ SkMatrix setup_matrix;
+ SkIRect setup_clip_bounds;
+ renderer.Render(canvas, info, &setup_matrix, &setup_clip_bounds);
+ canvas->restoreToCount(restore_count);
+
+ canvas->flush();
+ surface->flushAndSubmit(true);
+ return std::make_unique<RenderResult>(surface, setup_matrix,
+ setup_clip_bounds);
+ }
+
+ std::unique_ptr<RenderResult> getResult(sk_sp<DisplayList> dl) const {
+ DlRenderJob job(std::move(dl));
+ RenderJobInfo info = {};
+ return getResult(info, job);
+ }
+
+ const DlSurfaceProvider* provider() const { return provider_; }
+ bool valid() const { return provider_->supports(format_); }
+ const std::string backend_name() const { return provider_->backend_name(); }
+
+ PixelFormat format() const { return format_; }
const DisplayListBuilder& ref_attr() const { return ref_attr_; }
- const SkMatrix& ref_matrix() const { return ref_matrix_; }
- const SkIRect& ref_clip_bounds() const { return ref_clip_; }
- const SkPixmap* ref_pixmap() const { return ref_pixmap_; }
+ const RenderResult* ref_result() const { return ref_result_.get(); }
private:
- explicit RenderEnvironment(const SkImageInfo& info) : info_(info) {
- ref_surface_ = MakeSurface();
+ sk_sp<SkSurface> getSurface(int width, int height) const {
+ FML_DCHECK(valid());
+ FML_DCHECK(surface_1x_ != nullptr);
+ FML_DCHECK(surface_2x_ != nullptr);
+ if (width == kTestWidth && height == kTestHeight) {
+ return surface_1x_->sk_surface();
+ }
+ if (width == kTestWidth * 2 && height == kTestHeight * 2) {
+ return surface_2x_->sk_surface();
+ }
+ FML_LOG(ERROR) << "Test surface size (" << width << " x " << height
+ << ") not supported.";
+ FML_DCHECK(false);
+ return nullptr;
}
- const SkImageInfo info_;
+ const DlSurfaceProvider* provider_;
+ const PixelFormat format_;
+ std::shared_ptr<DlSurfaceInstance> surface_1x_;
+ std::shared_ptr<DlSurfaceInstance> surface_2x_;
DisplayListBuilder ref_attr_;
- SkMatrix ref_matrix_;
- SkIRect ref_clip_;
- std::unique_ptr<RenderSurface> ref_surface_;
- const SkPixmap* ref_pixmap_ = nullptr;
+ std::unique_ptr<RenderResult> ref_result_;
};
class TestParameters {
@@ -349,10 +528,11 @@
if (has_mutating_save_layer) {
return false;
}
- if (env.ref_clip_bounds() != device_clip || has_diff_clip) {
+ const RenderResult* ref_result = env.ref_result();
+ if (ref_result->clip_bounds() != device_clip || has_diff_clip) {
return false;
}
- if (env.ref_matrix() != matrix && !flags_.is_flood()) {
+ if (ref_result->matrix() != matrix && !flags_.is_flood()) {
return false;
}
if (flags_.ignores_paint()) {
@@ -545,6 +725,7 @@
bool is_draw_display_list() const { return is_draw_display_list_; }
bool is_draw_line() const { return is_draw_line_; }
bool is_draw_arc_center() const { return is_draw_arc_center_; }
+ bool is_draw_path() const { return is_draw_path_; }
bool is_horizontal_line() const { return is_horizontal_line_; }
bool is_vertical_line() const { return is_vertical_line_; }
bool ignores_dashes() const { return ignores_dashes_; }
@@ -569,6 +750,10 @@
is_draw_arc_center_ = true;
return *this;
}
+ TestParameters& set_draw_path() {
+ is_draw_path_ = true;
+ return *this;
+ }
TestParameters& set_ignores_dashes() {
ignores_dashes_ = true;
return *this;
@@ -592,6 +777,7 @@
bool is_draw_display_list_ = false;
bool is_draw_line_ = false;
bool is_draw_arc_center_ = false;
+ bool is_draw_path_ = false;
bool ignores_dashes_ = false;
bool is_horizontal_line_ = false;
bool is_vertical_line_ = false;
@@ -600,14 +786,14 @@
class CaseParameters {
public:
explicit CaseParameters(std::string info)
- : CaseParameters(std::move(info), EmptyCvRenderer, EmptyDlRenderer) {}
+ : CaseParameters(std::move(info), kEmptyCvRenderer, kEmptyDlRenderer) {}
CaseParameters(std::string info, CvSetup& cv_setup, DlRenderer& dl_setup)
: CaseParameters(std::move(info),
cv_setup,
dl_setup,
- EmptyCvRenderer,
- EmptyDlRenderer,
+ kEmptyCvRenderer,
+ kEmptyDlRenderer,
SK_ColorTRANSPARENT,
false,
false,
@@ -694,18 +880,22 @@
class CanvasCompareTester {
public:
+ static std::vector<std::unique_ptr<DlSurfaceProvider>> kTestProviders;
+
static BoundsTolerance DefaultTolerance;
static void RenderAll(const TestParameters& params,
const BoundsTolerance& tolerance = DefaultTolerance) {
- RenderEnvironment env = RenderEnvironment::MakeN32();
- env.init_ref(params.cv_renderer());
- RenderWithTransforms(params, env, tolerance);
- RenderWithClips(params, env, tolerance);
- RenderWithSaveRestore(params, env, tolerance);
- // Only test attributes if the canvas version uses the paint object
- if (params.uses_paint()) {
- RenderWithAttributes(params, env, tolerance);
+ for (auto& provider : kTestProviders) {
+ RenderEnvironment env = RenderEnvironment::MakeN32(provider.get());
+ env.init_ref(params.cv_renderer());
+ RenderWithTransforms(params, env, tolerance);
+ RenderWithClips(params, env, tolerance);
+ RenderWithSaveRestore(params, env, tolerance);
+ // Only test attributes if the canvas version uses the paint object
+ if (params.uses_paint()) {
+ RenderWithAttributes(params, env, tolerance);
+ }
}
}
@@ -827,7 +1017,8 @@
// so we set an alpha value which works for all primitives except for
// drawColor which can override the alpha with its color, but it now uses
// a non-opaque color to avoid that problem.
- RenderEnvironment backdrop_env = RenderEnvironment::MakeN32();
+ RenderEnvironment backdrop_env =
+ RenderEnvironment::MakeN32(env.provider());
CvSetup cv_backdrop_setup = [=](SkCanvas* cv, SkPaint& p) {
SkPaint setup_p;
setup_p.setShader(kTestImageColorSource.skia_object());
@@ -991,7 +1182,7 @@
// CPU renderer with default line width of 0 does not show antialiasing
// for stroked primitives, so we make a new reference with a non-trivial
// stroke width to demonstrate the differences
- RenderEnvironment aa_env = RenderEnvironment::MakeN32();
+ RenderEnvironment aa_env = RenderEnvironment::MakeN32(env.provider());
// Tweak the bounds tolerance for the displacement of 1/10 of a pixel
const BoundsTolerance aa_tolerance = tolerance.addBoundsPadding(1, 1);
CvSetup cv_aa_setup = [=](SkCanvas* cv, SkPaint& p) {
@@ -1033,44 +1224,54 @@
// surface, so we use a shader instead of a color. Also, thin stroked
// primitives (mainly drawLine and drawPoints) do not show much
// dithering so we use a non-trivial stroke width as well.
- RenderEnvironment dither_env = RenderEnvironment::Make565();
- DlColor dither_bg = DlColor::kBlack();
- CvSetup cv_dither_setup = [=](SkCanvas*, SkPaint& p) {
- p.setShader(kTestImageColorSource.skia_object());
- p.setAlpha(0xf0);
- p.setStrokeWidth(5.0);
- };
- DlRenderer dl_dither_setup = [=](DisplayListBuilder& b) {
- b.setColorSource(&kTestImageColorSource);
- b.setColor(DlColor(0xf0000000));
- b.setStrokeWidth(5.0);
- };
- dither_env.init_ref(cv_dither_setup, testP.cv_renderer(), //
- dl_dither_setup, dither_bg);
- RenderWith(testP, dither_env, tolerance,
- CaseParameters(
- "Dither == True",
- [=](SkCanvas* cv, SkPaint& p) {
- cv_dither_setup(cv, p);
- p.setDither(true);
- },
- [=](DisplayListBuilder& b) {
- dl_dither_setup(b);
- b.setDither(true);
- })
- .with_bg(dither_bg));
- RenderWith(testP, dither_env, tolerance,
- CaseParameters(
- "Dither = False",
- [=](SkCanvas* cv, SkPaint& p) {
- cv_dither_setup(cv, p);
- p.setDither(false);
- },
- [=](DisplayListBuilder& b) {
- dl_dither_setup(b);
- b.setDither(false);
- })
- .with_bg(dither_bg));
+ RenderEnvironment dither_env = RenderEnvironment::Make565(env.provider());
+ if (!dither_env.valid()) {
+ // Currently only happens on Metal backend
+ static std::set<std::string> warnings_sent;
+ std::string name = dither_env.backend_name();
+ if (warnings_sent.find(name) == warnings_sent.end()) {
+ warnings_sent.insert(name);
+ FML_LOG(INFO) << "Skipping Dithering tests on " << name;
+ }
+ } else {
+ DlColor dither_bg = DlColor::kBlack();
+ CvSetup cv_dither_setup = [=](SkCanvas*, SkPaint& p) {
+ p.setShader(kTestImageColorSource.skia_object());
+ p.setAlpha(0xf0);
+ p.setStrokeWidth(5.0);
+ };
+ DlRenderer dl_dither_setup = [=](DisplayListBuilder& b) {
+ b.setColorSource(&kTestImageColorSource);
+ b.setColor(DlColor(0xf0000000));
+ b.setStrokeWidth(5.0);
+ };
+ dither_env.init_ref(cv_dither_setup, testP.cv_renderer(), //
+ dl_dither_setup, dither_bg);
+ RenderWith(testP, dither_env, tolerance,
+ CaseParameters(
+ "Dither == True",
+ [=](SkCanvas* cv, SkPaint& p) {
+ cv_dither_setup(cv, p);
+ p.setDither(true);
+ },
+ [=](DisplayListBuilder& b) {
+ dl_dither_setup(b);
+ b.setDither(true);
+ })
+ .with_bg(dither_bg));
+ RenderWith(testP, dither_env, tolerance,
+ CaseParameters(
+ "Dither = False",
+ [=](SkCanvas* cv, SkPaint& p) {
+ cv_dither_setup(cv, p);
+ p.setDither(false);
+ },
+ [=](DisplayListBuilder& b) {
+ dl_dither_setup(b);
+ b.setDither(false);
+ })
+ .with_bg(dither_bg));
+ }
}
RenderWith(testP, env, tolerance,
@@ -1143,7 +1344,7 @@
// Being able to see a blur requires some non-default attributes,
// like a non-trivial stroke width and a shader rather than a color
// (for drawPaint) so we create a new environment for these tests.
- RenderEnvironment blur_env = RenderEnvironment::MakeN32();
+ RenderEnvironment blur_env = RenderEnvironment::MakeN32(env.provider());
CvSetup cv_blur_setup = [=](SkCanvas*, SkPaint& p) {
p.setShader(kTestImageColorSource.skia_object());
p.setStrokeWidth(5.0);
@@ -1188,7 +1389,7 @@
// Being able to see a dilate requires some non-default attributes,
// like a non-trivial stroke width and a shader rather than a color
// (for drawPaint) so we create a new environment for these tests.
- RenderEnvironment dilate_env = RenderEnvironment::MakeN32();
+ RenderEnvironment dilate_env = RenderEnvironment::MakeN32(env.provider());
CvSetup cv_dilate_setup = [=](SkCanvas*, SkPaint& p) {
p.setShader(kTestImageColorSource.skia_object());
p.setStrokeWidth(5.0);
@@ -1217,7 +1418,7 @@
// Being able to see an erode requires some non-default attributes,
// like a non-trivial stroke width and a shader rather than a color
// (for drawPaint) so we create a new environment for these tests.
- RenderEnvironment erode_env = RenderEnvironment::MakeN32();
+ RenderEnvironment erode_env = RenderEnvironment::MakeN32(env.provider());
CvSetup cv_erode_setup = [=](SkCanvas*, SkPaint& p) {
p.setShader(kTestImageColorSource.skia_object());
p.setStrokeWidth(6.0);
@@ -1420,13 +1621,28 @@
[=](DisplayListBuilder& b) { //
b.setStyle(DlDrawStyle::kFill);
}));
+ // Skia on HW produces a strong miter consistent with width=1.0
+ // for any width less than a pixel, but the bounds computations of
+ // both DL and SkPicture do not account for this. We will get
+ // OOB pixel errors for the highly mitered drawPath geometry if
+ // we don't set stroke width to 1.0 for that test on HW.
+ // See https://bugs.chromium.org/p/skia/issues/detail?id=14046
+ bool no_hairlines =
+ testP.is_draw_path() &&
+ env.provider()->backend_type() != BackendType::kSoftware_Backend;
RenderWith(testP, env, tolerance,
CaseParameters(
"Stroke + defaults",
[=](SkCanvas*, SkPaint& p) { //
+ if (no_hairlines) {
+ p.setStrokeWidth(1.0);
+ }
p.setStyle(SkPaint::kStroke_Style);
},
[=](DisplayListBuilder& b) { //
+ if (no_hairlines) {
+ b.setStrokeWidth(1.0);
+ }
b.setStyle(DlDrawStyle::kStroke);
}));
@@ -1442,7 +1658,8 @@
b.setStrokeWidth(10.0);
}));
- RenderEnvironment stroke_base_env = RenderEnvironment::MakeN32();
+ RenderEnvironment stroke_base_env =
+ RenderEnvironment::MakeN32(env.provider());
CvSetup cv_stroke_setup = [=](SkCanvas*, SkPaint& p) {
p.setStyle(SkPaint::kStroke_Style);
p.setStrokeWidth(5.0);
@@ -1685,11 +1902,20 @@
static void RenderWithClips(const TestParameters& testP,
const RenderEnvironment& env,
const BoundsTolerance& diff_tolerance) {
- SkRect r_clip = kRenderBounds.makeInset(15.5, 15.5);
+ // We used to use an inset of 15.5 pixels here, but since Skia's rounding
+ // behavior at the center of pixels does not match between HW and SW, we
+ // ended up with some clips including different pixels between the two
+ // destinations and this interacted poorly with the carefully chosen
+ // geometry in some of the tests which was designed to have just the
+ // right features fully filling the clips based on the SW rounding. By
+ // moving to a 15.4 inset, the edge of the clip is never on the "rounding
+ // edge" of a pixel.
+ SkRect r_clip = kRenderBounds.makeInset(15.4, 15.4);
BoundsTolerance intersect_tolerance = diff_tolerance.clip(r_clip);
+ intersect_tolerance = intersect_tolerance.addPostClipPadding(1, 1);
RenderWith(testP, env, intersect_tolerance,
CaseParameters(
- "Hard ClipRect inset by 15.5",
+ "Hard ClipRect inset by 15.4",
[=](SkCanvas* c, SkPaint&) {
c->clipRect(r_clip, SkClipOp::kIntersect, false);
},
@@ -1698,7 +1924,7 @@
}));
RenderWith(testP, env, intersect_tolerance,
CaseParameters(
- "AntiAlias ClipRect inset by 15.5",
+ "AntiAlias ClipRect inset by 15.4",
[=](SkCanvas* c, SkPaint&) {
c->clipRect(r_clip, SkClipOp::kIntersect, true);
},
@@ -1707,7 +1933,7 @@
}));
RenderWith(testP, env, diff_tolerance,
CaseParameters(
- "Hard ClipRect Diff, inset by 15.5",
+ "Hard ClipRect Diff, inset by 15.4",
[=](SkCanvas* c, SkPaint&) {
c->clipRect(r_clip, SkClipOp::kDifference, false);
},
@@ -1715,10 +1941,15 @@
b.clipRect(r_clip, SkClipOp::kDifference, false);
})
.with_diff_clip());
- SkRRect rr_clip = SkRRect::MakeRectXY(r_clip, 1.8, 2.7);
+ // This test RR clip used to use very small radii, but due to
+ // optimizations in the HW rrect rasterization, this caused small
+ // bulges in the corners of the RRect which were interpreted as
+ // "clip overruns" by the clip OOB pixel testing code. Using less
+ // abusively small radii fixes the problem.
+ SkRRect rr_clip = SkRRect::MakeRectXY(r_clip, 9, 9);
RenderWith(testP, env, intersect_tolerance,
CaseParameters(
- "Hard ClipRRect inset by 15.5",
+ "Hard ClipRRect with radius of 15.4",
[=](SkCanvas* c, SkPaint&) {
c->clipRRect(rr_clip, SkClipOp::kIntersect, false);
},
@@ -1727,7 +1958,7 @@
}));
RenderWith(testP, env, intersect_tolerance,
CaseParameters(
- "AntiAlias ClipRRect inset by 15.5",
+ "AntiAlias ClipRRect with radius of 15.4",
[=](SkCanvas* c, SkPaint&) {
c->clipRRect(rr_clip, SkClipOp::kIntersect, true);
},
@@ -1736,7 +1967,7 @@
}));
RenderWith(testP, env, diff_tolerance,
CaseParameters(
- "Hard ClipRRect Diff, inset by 15.5",
+ "Hard ClipRRect Diff, with radius of 15.4",
[=](SkCanvas* c, SkPaint&) {
c->clipRRect(rr_clip, SkClipOp::kDifference, false);
},
@@ -1750,7 +1981,7 @@
path_clip.addCircle(kRenderCenterX, kRenderCenterY, 1.0);
RenderWith(testP, env, intersect_tolerance,
CaseParameters(
- "Hard ClipPath inset by 15.5",
+ "Hard ClipPath inset by 15.4",
[=](SkCanvas* c, SkPaint&) {
c->clipPath(path_clip, SkClipOp::kIntersect, false);
},
@@ -1759,7 +1990,7 @@
}));
RenderWith(testP, env, intersect_tolerance,
CaseParameters(
- "AntiAlias ClipPath inset by 15.5",
+ "AntiAlias ClipPath inset by 15.4",
[=](SkCanvas* c, SkPaint&) {
c->clipPath(path_clip, SkClipOp::kIntersect, true);
},
@@ -1768,7 +1999,7 @@
}));
RenderWith(testP, env, diff_tolerance,
CaseParameters(
- "Hard ClipPath Diff, inset by 15.5",
+ "Hard ClipPath Diff, inset by 15.4",
[=](SkCanvas* c, SkPaint&) {
c->clipPath(path_clip, SkClipOp::kDifference, false);
},
@@ -1791,47 +2022,49 @@
const RenderEnvironment& env,
const BoundsTolerance& tolerance_in,
const CaseParameters& caseP) {
- // sk_surface is a direct rendering via SkCanvas to SkSurface
- // DisplayList mechanisms are not involved in this operation
- const std::string info = caseP.info();
+ const std::string info = env.backend_name() + ": " + caseP.info();
const DlColor bg = caseP.bg();
- std::unique_ptr<RenderSurface> sk_surface = env.MakeSurface(bg);
- SkCanvas* sk_canvas = sk_surface->canvas();
- SkPaint sk_paint;
- caseP.cv_setup()(sk_canvas, sk_paint);
- SkMatrix sk_matrix = sk_canvas->getTotalMatrix();
- SkIRect sk_clip = sk_canvas->getDeviceClipBounds();
+
+ // sk_result is a direct rendering via SkCanvas to SkSurface
+ // DisplayList mechanisms are not involved in this operation
+ // SkPaint sk_paint;
+ CvJobRenderer sk_job(caseP.cv_setup(), //
+ testP.cv_renderer(), //
+ caseP.cv_restore());
+ RenderJobInfo base_info = {
+ .bg = caseP.bg(),
+ };
+ auto sk_result = env.getResult(base_info, sk_job);
const BoundsTolerance tolerance =
- testP.adjust(tolerance_in, sk_paint, sk_canvas->getTotalMatrix());
- testP.render_to(sk_canvas, sk_paint);
- caseP.cv_restore()(sk_canvas, sk_paint);
- const sk_sp<SkPicture> sk_picture = getSkPicture(testP, caseP);
+ testP.adjust(tolerance_in, sk_job.setup_paint(), sk_result->matrix());
+ const sk_sp<SkPicture> sk_picture = sk_job.MakePicture();
SkRect sk_bounds = sk_picture->cullRect();
- const SkPixmap* sk_pixels = sk_surface->pixmap();
- ASSERT_EQ(sk_pixels->width(), kTestWidth) << info;
- ASSERT_EQ(sk_pixels->height(), kTestHeight) << info;
- ASSERT_EQ(sk_pixels->info().bytesPerPixel(), 4) << info;
- checkPixels(sk_pixels, sk_bounds, info + " (Skia reference)", bg);
+ ASSERT_EQ(sk_result->width(), kTestWidth) << info;
+ ASSERT_EQ(sk_result->height(), kTestHeight) << info;
+ checkPixels(sk_result.get(), sk_bounds, info + " (Skia reference)", bg);
DisplayListBuilder dl_attr;
caseP.dl_setup()(dl_attr);
- if (testP.should_match(env, dl_attr, sk_matrix, sk_clip,
- caseP.has_diff_clip(),
+ if (testP.should_match(env, dl_attr, sk_result->matrix(),
+ sk_result->clip_bounds(), caseP.has_diff_clip(),
caseP.has_mutating_save_layer())) {
- quickCompareToReference(env.ref_pixmap(), sk_pixels, true,
+ quickCompareToReference(env.ref_result(), sk_result.get(), true,
info + " (attribute has no effect)");
} else {
- quickCompareToReference(env.ref_pixmap(), sk_pixels, false,
+ quickCompareToReference(env.ref_result(), sk_result.get(), false,
info + " (attribute affects rendering)");
}
+ sk_sp<DisplayList> display_list;
{
// This sequence plays the provided equivalently constructed
// DisplayList onto the SkCanvas of the surface
// DisplayList => direct rendering
- DisplayListBuilder builder(kTestBounds);
- caseP.render_to(builder, testP);
- sk_sp<DisplayList> display_list = builder.Build();
+ DlRenderJob dl_job(caseP.dl_setup(), //
+ testP.dl_renderer(), //
+ caseP.dl_restore());
+ auto dl_result = env.getResult(base_info, dl_job);
+ display_list = dl_job.display_list();
SkRect dl_bounds = display_list->bounds();
if (!sk_bounds.roundOut().contains(dl_bounds)) {
FML_LOG(ERROR) << "For " << info;
@@ -1866,15 +2099,13 @@
<< info;
}
- std::unique_ptr<RenderSurface> dl_surface = env.MakeSurface(bg);
- display_list->RenderTo(dl_surface->canvas());
- compareToReference(dl_surface->pixmap(), sk_pixels,
+ compareToReference(dl_result.get(), sk_result.get(),
info + " (DisplayList built directly -> surface)",
&dl_bounds, &tolerance, bg,
caseP.fuzzy_compare_components());
if (display_list->can_apply_group_opacity()) {
- checkGroupOpacity(env, display_list, dl_surface->pixmap(),
+ checkGroupOpacity(env, display_list, dl_result.get(),
info + " with Group Opacity", bg);
}
}
@@ -1885,11 +2116,11 @@
// This sequence renders SkCanvas calls to a DisplayList and then
// plays them back on SkCanvas to SkSurface
// SkCanvas calls => DisplayList => rendering
- std::unique_ptr<RenderSurface> cv_dl_surface = env.MakeSurface(bg);
DisplayListCanvasRecorder dl_recorder(kTestBounds);
- caseP.render_to(&dl_recorder, testP);
- dl_recorder.builder()->Build()->RenderTo(cv_dl_surface->canvas());
- compareToReference(cv_dl_surface->pixmap(), sk_pixels,
+ sk_job.Render(&dl_recorder, base_info);
+ DlRenderJob cv_dl_job(dl_recorder.Build());
+ auto cv_dl_result = env.getResult(base_info, cv_dl_job);
+ compareToReference(cv_dl_result.get(), sk_result.get(),
info + " (Skia calls -> DisplayList -> surface)",
nullptr, nullptr, bg,
caseP.fuzzy_compare_components());
@@ -1905,31 +2136,20 @@
const int test_height_2 = kTestHeight * 2;
const SkScalar test_scale = 2.0;
- SkPictureRecorder sk_x2_recorder;
- SkCanvas* ref_canvas = sk_x2_recorder.beginRecording(kTestBounds);
- SkPaint ref_paint;
- caseP.render_to(ref_canvas, testP);
- sk_sp<SkPicture> ref_x2_picture =
- sk_x2_recorder.finishRecordingAsPicture();
- std::unique_ptr<RenderSurface> ref_x2_surface =
- env.MakeSurface(bg, test_width_2, test_height_2);
- SkCanvas* ref_x2_canvas = ref_x2_surface->canvas();
- ref_x2_canvas->scale(test_scale, test_scale);
- ref_x2_picture->playback(ref_x2_canvas);
- const SkPixmap* ref_x2_pixels = ref_x2_surface->pixmap();
- ASSERT_EQ(ref_x2_pixels->width(), test_width_2) << info;
- ASSERT_EQ(ref_x2_pixels->height(), test_height_2) << info;
- ASSERT_EQ(ref_x2_pixels->info().bytesPerPixel(), 4) << info;
+ CvPictureRenderJob sk_job_x2(sk_picture);
+ RenderJobInfo info_2x = {
+ .width = test_width_2,
+ .height = test_height_2,
+ .bg = bg,
+ .scale = test_scale,
+ };
+ auto ref_x2_result = env.getResult(info_2x, sk_job_x2);
+ ASSERT_EQ(ref_x2_result->width(), test_width_2) << info;
+ ASSERT_EQ(ref_x2_result->height(), test_height_2) << info;
- DisplayListBuilder builder_x2(kTestBounds);
- caseP.render_to(builder_x2, testP);
- sk_sp<DisplayList> display_list_x2 = builder_x2.Build();
- std::unique_ptr<RenderSurface> test_x2_surface =
- env.MakeSurface(bg, test_width_2, test_height_2);
- SkCanvas* test_x2_canvas = test_x2_surface->canvas();
- test_x2_canvas->scale(test_scale, test_scale);
- display_list_x2->RenderTo(test_x2_canvas);
- compareToReference(test_x2_surface->pixmap(), ref_x2_pixels,
+ DlRenderJob dl_job_x2(display_list);
+ auto test_x2_result = env.getResult(info_2x, dl_job_x2);
+ compareToReference(test_x2_result.get(), ref_x2_result.get(),
info + " (Both rendered scaled 2x)", nullptr, nullptr,
bg, caseP.fuzzy_compare_components(), //
test_width_2, test_height_2, false);
@@ -1947,28 +2167,40 @@
return true;
}
+ static int groupOpacityFudgeFactor(const RenderEnvironment& env) {
+ if (env.format() == PixelFormat::k565_PixelFormat) {
+ return 9;
+ }
+ if (env.provider()->backend_type() == BackendType::kOpenGL_Backend) {
+ // OpenGL gets a little fuzzy at times. Still, "within 5" (aka +/-4)
+ // for byte samples is not bad, though the other backends give +/-1
+ return 5;
+ }
+ return 2;
+ }
static void checkGroupOpacity(const RenderEnvironment& env,
const sk_sp<DisplayList>& display_list,
- const SkPixmap* ref_pixmap,
+ const RenderResult* ref_result,
const std::string& info,
DlColor bg) {
SkScalar opacity = 128.0 / 255.0;
- std::unique_ptr<RenderSurface> group_opacity_surface = env.MakeSurface(bg);
- SkCanvas* group_opacity_canvas = group_opacity_surface->canvas();
- display_list->RenderTo(group_opacity_canvas, opacity);
- const SkPixmap* group_opacity_pixmap = group_opacity_surface->pixmap();
+ DlRenderJob opacity_job(display_list);
+ RenderJobInfo opacity_info = {
+ .bg = bg,
+ .opacity = opacity,
+ };
+ auto group_opacity_result = env.getResult(opacity_info, opacity_job);
- ASSERT_EQ(group_opacity_pixmap->width(), kTestWidth) << info;
- ASSERT_EQ(group_opacity_pixmap->height(), kTestHeight) << info;
- ASSERT_EQ(group_opacity_pixmap->info().bytesPerPixel(), 4) << info;
+ ASSERT_EQ(group_opacity_result->width(), kTestWidth) << info;
+ ASSERT_EQ(group_opacity_result->height(), kTestHeight) << info;
- ASSERT_EQ(ref_pixmap->width(), kTestWidth) << info;
- ASSERT_EQ(ref_pixmap->height(), kTestHeight) << info;
- ASSERT_EQ(ref_pixmap->info().bytesPerPixel(), 4) << info;
+ ASSERT_EQ(ref_result->width(), kTestWidth) << info;
+ ASSERT_EQ(ref_result->height(), kTestHeight) << info;
int pixels_touched = 0;
int pixels_different = 0;
+ int max_diff = 0;
// We need to allow some slight differences per component due to the
// fact that rearranging discrete calculations can compound round off
// errors. Off-by-2 is enough for 8 bit components, but for the 565
@@ -1977,10 +2209,10 @@
// max step of 8 converting 5 bits to 8 bits, but it is really
// converting 31 steps to 255 steps with an average step size of
// 8.23 - 24 of the steps are by 8, but 7 of them are by 9.)
- int fudge = env.info().bytesPerPixel() < 4 ? 9 : 2;
+ int fudge = groupOpacityFudgeFactor(env);
for (int y = 0; y < kTestHeight; y++) {
- const uint32_t* ref_row = ref_pixmap->addr32(0, y);
- const uint32_t* test_row = group_opacity_pixmap->addr32(0, y);
+ const uint32_t* ref_row = ref_result->addr32(0, y);
+ const uint32_t* test_row = group_opacity_result->addr32(0, y);
for (int x = 0; x < kTestWidth; x++) {
uint32_t ref_pixel = ref_row[x];
uint32_t test_pixel = test_row[x];
@@ -1992,6 +2224,10 @@
SkScalar faded_comp = bg_comp + (ref_comp - bg_comp) * opacity;
int test_comp = (test_pixel >> i) & 0xff;
if (std::abs(faded_comp - test_comp) > fudge) {
+ int diff = std::abs(faded_comp - test_comp);
+ if (max_diff < diff) {
+ max_diff = diff;
+ }
pixels_different++;
break;
}
@@ -2000,10 +2236,13 @@
}
}
ASSERT_GT(pixels_touched, 20) << info;
+ if (pixels_different > 1) {
+ FML_LOG(ERROR) << "max diff == " << max_diff << " for " << info;
+ }
ASSERT_LE(pixels_different, 1) << info;
}
- static void checkPixels(const SkPixmap* ref_pixels,
+ static void checkPixels(const RenderResult* ref_result,
const SkRect ref_bounds,
const std::string& info,
const DlColor bg) {
@@ -2012,7 +2251,7 @@
int pixels_oob = 0;
SkIRect i_bounds = ref_bounds.roundOut();
for (int y = 0; y < kTestHeight; y++) {
- const uint32_t* ref_row = ref_pixels->addr32(0, y);
+ const uint32_t* ref_row = ref_result->addr32(0, y);
for (int x = 0; x < kTestWidth; x++) {
if (ref_row[x] != untouched) {
pixels_touched++;
@@ -2026,19 +2265,19 @@
ASSERT_GT(pixels_touched, 0) << info;
}
- static void quickCompareToReference(const SkPixmap* ref_pixels,
- const SkPixmap* test_pixels,
+ static void quickCompareToReference(const RenderResult* ref_result,
+ const RenderResult* test_result,
bool should_match,
const std::string& info) {
- ASSERT_EQ(test_pixels->width(), ref_pixels->width()) << info;
- ASSERT_EQ(test_pixels->height(), ref_pixels->height()) << info;
- ASSERT_EQ(test_pixels->info().bytesPerPixel(), 4) << info;
- ASSERT_EQ(ref_pixels->info().bytesPerPixel(), 4) << info;
+ int w = test_result->width();
+ int h = test_result->height();
+ ASSERT_EQ(w, ref_result->width()) << info;
+ ASSERT_EQ(h, ref_result->height()) << info;
int pixels_different = 0;
- for (int y = 0; y < test_pixels->height(); y++) {
- const uint32_t* ref_row = ref_pixels->addr32(0, y);
- const uint32_t* test_row = test_pixels->addr32(0, y);
- for (int x = 0; x < test_pixels->width(); x++) {
+ for (int y = 0; y < h; y++) {
+ const uint32_t* ref_row = ref_result->addr32(0, y);
+ const uint32_t* test_row = test_result->addr32(0, y);
+ for (int x = 0; x < w; x++) {
if (ref_row[x] != test_row[x]) {
if (should_match) {
FML_LOG(ERROR) << std::hex << ref_row[x] << " != " << test_row[x];
@@ -2054,8 +2293,8 @@
}
}
- static void compareToReference(const SkPixmap* test_pixels,
- const SkPixmap* ref_pixels,
+ static void compareToReference(const RenderResult* test_result,
+ const RenderResult* ref_result,
const std::string& info,
SkRect* bounds,
const BoundsTolerance* tolerance,
@@ -2065,10 +2304,8 @@
int height = kTestHeight,
bool printMismatches = false) {
uint32_t untouched = bg.premultipliedArgb();
- ASSERT_EQ(test_pixels->width(), width) << info;
- ASSERT_EQ(test_pixels->height(), height) << info;
- ASSERT_EQ(test_pixels->info().bytesPerPixel(), 4) << info;
- ASSERT_EQ(ref_pixels->info().bytesPerPixel(), 4) << info;
+ ASSERT_EQ(test_result->width(), width) << info;
+ ASSERT_EQ(test_result->height(), height) << info;
SkIRect i_bounds =
bounds ? bounds->roundOut() : SkIRect::MakeWH(width, height);
@@ -2079,8 +2316,8 @@
int max_x = 0;
int max_y = 0;
for (int y = 0; y < height; y++) {
- const uint32_t* ref_row = ref_pixels->addr32(0, y);
- const uint32_t* test_row = test_pixels->addr32(0, y);
+ const uint32_t* ref_row = ref_result->addr32(0, y);
+ const uint32_t* test_row = test_result->addr32(0, y);
for (int x = 0; x < width; x++) {
if (bounds && test_row[x] != untouched) {
if (min_x > x) {
@@ -2146,7 +2383,7 @@
int worst_pad_x = std::max(pad_left, pad_right);
int worst_pad_y = std::max(pad_top, pad_bottom);
if (tolerance->overflows(pix_bounds, worst_pad_x, worst_pad_y)) {
- FML_LOG(ERROR) << "Overflow for " << info;
+ FML_LOG(ERROR) << "Computed bounds for " << info;
FML_LOG(ERROR) << "pix bounds[" //
<< pixLeft << ", " << pixTop << " => " //
<< pixRight << ", " << pixBottom //
@@ -2156,14 +2393,15 @@
<< " => " //
<< bounds.fRight << ", " << bounds.fBottom //
<< "]";
- FML_LOG(ERROR) << "Bounds overflowed by up to " //
+ FML_LOG(ERROR) << "Bounds overly conservative by up to " //
<< worst_pad_x << ", " << worst_pad_y //
<< " (" << (worst_pad_x * 100.0 / pix_width) //
<< "%, " << (worst_pad_y * 100.0 / pix_height) << "%)";
int pix_area = pix_size.area();
int dl_area = bounds.width() * bounds.height();
FML_LOG(ERROR) << "Total overflow area: " << (dl_area - pix_area) //
- << " (+" << (dl_area * 100.0 / pix_area - 100.0) << "%)";
+ << " (+" << (dl_area * 100.0 / pix_area - 100.0) //
+ << "% larger)";
FML_LOG(ERROR);
}
}
@@ -2201,6 +2439,9 @@
}
};
+std::vector<std::unique_ptr<DlSurfaceProvider>>
+ CanvasCompareTester::kTestProviders;
+
BoundsTolerance CanvasCompareTester::DefaultTolerance =
BoundsTolerance().addAbsolutePadding(1, 1);
@@ -2219,6 +2460,73 @@
public:
DisplayListCanvasTestBase() = default;
+ static bool StartsWith(std::string str, std::string prefix) {
+ if (prefix.length() > str.length()) {
+ return false;
+ }
+ for (size_t i = 0; i < prefix.length(); i++) {
+ if (str[i] != prefix[i]) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ static void AddProvider(BackendType type, const std::string& name) {
+ auto provider = DlSurfaceProvider::Create(type);
+ if (provider == nullptr) {
+ FML_LOG(ERROR) << "provider " << name << " not supported (ignoring)";
+ return;
+ }
+ provider->InitializeSurface(kTestWidth, kTestHeight,
+ PixelFormat::kN32Premul_PixelFormat);
+ CanvasCompareTester::kTestProviders.push_back(std::move(provider));
+ }
+
+ static void SetUpTestSuite() {
+ bool do_software = true;
+ bool do_opengl = false;
+ bool do_metal = false;
+ std::vector<std::string> args = ::testing::internal::GetArgvs();
+ for (auto p_arg = std::next(args.begin()); p_arg != args.end(); p_arg++) {
+ std::string arg = *p_arg;
+ bool enable = true;
+ if (StartsWith(arg, "--no")) {
+ enable = false;
+ arg = "-" + arg.substr(4);
+ }
+ if (arg == "--enable-software") {
+ do_software = enable;
+ } else if (arg == "--enable-opengl" || arg == "--enable-gl") {
+ do_opengl = enable;
+ } else if (arg == "--enable-metal") {
+ do_metal = enable;
+ }
+ }
+ if (do_software) {
+ AddProvider(BackendType::kSoftware_Backend, "Software");
+ }
+ if (do_opengl) {
+ AddProvider(BackendType::kOpenGL_Backend, "OpenGL");
+ }
+ if (do_metal) {
+ AddProvider(BackendType::kMetal_Backend, "Metal");
+ }
+ std::string providers = "";
+ auto begin = CanvasCompareTester::kTestProviders.cbegin();
+ auto end = CanvasCompareTester::kTestProviders.cend();
+ while (begin != end) {
+ providers += " " + (*begin++)->backend_name();
+ }
+ FML_LOG(INFO) << "Running tests on [" << providers << " ]";
+ }
+
+ static void TearDownTestSuite() {
+ // Deleting these provider objects allows Metal to clean up its
+ // resources before the exit handler reports them as leaks.
+ CanvasCompareTester::kTestProviders.clear();
+ }
+
private:
FML_DISALLOW_COPY_AND_ASSIGN(DisplayListCanvasTestBase);
};
@@ -2236,7 +2544,28 @@
kDrawPaintFlags));
}
-TEST_F(DisplayListCanvas, DrawColor) {
+TEST_F(DisplayListCanvas, DrawOpaqueColor) {
+ // We use a non-opaque color to avoid obliterating any backdrop filter output
+ CanvasCompareTester::RenderAll( //
+ TestParameters(
+ [=](SkCanvas* canvas, const SkPaint& paint) {
+ // DrawColor is not tested against attributes because it is supposed
+ // to ignore them. So, if the paint has an alpha, it is because we
+ // are doing a saveLayer+backdrop test and we need to not flood over
+ // the backdrop output with a solid color. So, we perform an alpha
+ // drawColor for that case only.
+ SkColor color = SkColorSetA(0xFFFF00FF, paint.getAlpha());
+ canvas->drawColor(color);
+ },
+ [=](DisplayListBuilder& builder) {
+ DlColor color = 0xFFFF00FF;
+ color = color.withAlpha(builder.getColor().getAlpha());
+ builder.drawColor(color, DlBlendMode::kSrcOver);
+ },
+ kDrawColorFlags));
+}
+
+TEST_F(DisplayListCanvas, DrawAlphaColor) {
// We use a non-opaque color to avoid obliterating any backdrop filter output
CanvasCompareTester::RenderAll( //
TestParameters(
@@ -2254,6 +2583,12 @@
SkPoint p2 = SkPoint::Make(kRenderRight, kRenderBottom);
SkPoint p3 = SkPoint::Make(kRenderLeft, kRenderBottom);
SkPoint p4 = SkPoint::Make(kRenderRight, kRenderTop);
+ // Adding some edge center to edge center diagonals to better fill
+ // out the RRect Clip so bounds checking sees less empty bounds space.
+ SkPoint p5 = SkPoint::Make(kRenderCenterX, kRenderTop);
+ SkPoint p6 = SkPoint::Make(kRenderRight, kRenderCenterY);
+ SkPoint p7 = SkPoint::Make(kRenderLeft, kRenderCenterY);
+ SkPoint p8 = SkPoint::Make(kRenderCenterX, kRenderBottom);
CanvasCompareTester::RenderAll( //
TestParameters(
@@ -2265,10 +2600,14 @@
p.setStyle(SkPaint::kStroke_Style);
canvas->drawLine(p1, p2, p);
canvas->drawLine(p3, p4, p);
+ canvas->drawLine(p5, p6, p);
+ canvas->drawLine(p7, p8, p);
},
[=](DisplayListBuilder& builder) { //
builder.drawLine(p1, p2);
builder.drawLine(p3, p4);
+ builder.drawLine(p5, p6);
+ builder.drawLine(p7, p8);
},
kDrawLineFlags)
.set_draw_line());
@@ -2419,7 +2758,8 @@
[=](DisplayListBuilder& builder) { //
builder.drawPath(path);
},
- kDrawPathFlags));
+ kDrawPathFlags)
+ .set_draw_path());
}
TEST_F(DisplayListCanvas, DrawArc) {
@@ -2558,13 +2898,16 @@
TEST_F(DisplayListCanvas, DrawPointsAsPolygon) {
const SkPoint points1[] = {
- // RenderBounds box with a diagonal
+ // RenderBounds box with a diamond
SkPoint::Make(kRenderLeft, kRenderTop),
SkPoint::Make(kRenderRight, kRenderTop),
SkPoint::Make(kRenderRight, kRenderBottom),
SkPoint::Make(kRenderLeft, kRenderBottom),
SkPoint::Make(kRenderLeft, kRenderTop),
- SkPoint::Make(kRenderRight, kRenderBottom),
+ SkPoint::Make(kRenderCenterX, kRenderTop),
+ SkPoint::Make(kRenderRight, kRenderCenterY),
+ SkPoint::Make(kRenderCenterX, kRenderBottom),
+ SkPoint::Make(kRenderLeft, kRenderCenterY),
};
const int count1 = sizeof(points1) / sizeof(points1[0]);
@@ -3042,7 +3385,8 @@
sk_sp<SkPicture> makeTestPicture() {
SkPictureRecorder recorder;
- SkCanvas* cv = recorder.beginRecording(kRenderBounds);
+ SkRTreeFactory rtree_factory;
+ SkCanvas* cv = recorder.beginRecording(kRenderBounds, &rtree_factory);
SkPaint p;
p.setStyle(SkPaint::kFill_Style);
p.setColor(SK_ColorRED);
@@ -3281,7 +3625,12 @@
std::make_shared<DlMatrixImageFilter>(contract_matrix,
DlImageSampling::kLinear),
};
- RenderEnvironment env = RenderEnvironment::MakeN32();
+ std::vector<std::unique_ptr<RenderEnvironment>> environments;
+ for (auto& provider : CanvasCompareTester::kTestProviders) {
+ auto env = std::make_unique<RenderEnvironment>(
+ provider.get(), PixelFormat::kN32Premul_PixelFormat);
+ environments.push_back(std::move(env));
+ }
auto render_content = [](DisplayListBuilder& builder) {
builder.drawRect(
@@ -3298,50 +3647,57 @@
DlPaint().setColor(DlColor::kRed().modulateOpacity(0.5f)));
};
- // clang-format off
- auto test_attributes = [&env, render_content]
- (DlPaint& paint1, DlPaint& paint2, const DlPaint& paint_both,
- bool same, bool rev_same, const std::string& desc1,
- const std::string& desc2) {
- // clang-format on
- DisplayListBuilder nested_builder;
- nested_builder.saveLayer(&kTestBounds, &paint1);
- nested_builder.saveLayer(&kTestBounds, &paint2);
- render_content(nested_builder);
- auto nested_surface = env.MakeSurface();
- nested_builder.Build()->RenderTo(nested_surface->canvas());
+ auto test_attributes_env =
+ [render_content](DlPaint& paint1, DlPaint& paint2,
+ const DlPaint& paint_both, bool same, bool rev_same,
+ const std::string& desc1, const std::string& desc2,
+ const RenderEnvironment* env) {
+ DisplayListBuilder nested_builder;
+ nested_builder.saveLayer(&kTestBounds, &paint1);
+ nested_builder.saveLayer(&kTestBounds, &paint2);
+ render_content(nested_builder);
+ auto nested_results = env->getResult(nested_builder.Build());
- DisplayListBuilder reverse_builder;
- reverse_builder.saveLayer(&kTestBounds, &paint2);
- reverse_builder.saveLayer(&kTestBounds, &paint1);
- render_content(reverse_builder);
- auto reverse_surface = env.MakeSurface();
- reverse_builder.Build()->RenderTo(reverse_surface->canvas());
+ DisplayListBuilder reverse_builder;
+ reverse_builder.saveLayer(&kTestBounds, &paint2);
+ reverse_builder.saveLayer(&kTestBounds, &paint1);
+ render_content(reverse_builder);
+ auto reverse_results = env->getResult(reverse_builder.Build());
- DisplayListBuilder combined_builder;
- combined_builder.saveLayer(&kTestBounds, &paint_both);
- render_content(combined_builder);
- auto combined_surface = env.MakeSurface();
- combined_builder.Build()->RenderTo(combined_surface->canvas());
+ DisplayListBuilder combined_builder;
+ combined_builder.saveLayer(&kTestBounds, &paint_both);
+ render_content(combined_builder);
+ auto combined_results = env->getResult(combined_builder.Build());
- // Set this boolean to true to test if combinations that are marked
- // as incompatible actually are compatible despite our predictions.
- // Some of the combinations that we treat as incompatible actually
- // are compatible with swapping the order of the operations, but
- // it would take a bit of new infrastructure to really identify
- // those combinations. The only hard constraint to test here is
- // when we claim that they are compatible and they aren't.
- const bool always = false;
+ // Set this boolean to true to test if combinations that are marked
+ // as incompatible actually are compatible despite our predictions.
+ // Some of the combinations that we treat as incompatible actually
+ // are compatible with swapping the order of the operations, but
+ // it would take a bit of new infrastructure to really identify
+ // those combinations. The only hard constraint to test here is
+ // when we claim that they are compatible and they aren't.
+ const bool always = false;
- if (always || same) {
- CanvasCompareTester::quickCompareToReference(
- nested_surface->pixmap(), combined_surface->pixmap(), same,
- "nested " + desc1 + " then " + desc2);
- }
- if (always || rev_same) {
- CanvasCompareTester::quickCompareToReference(
- reverse_surface->pixmap(), combined_surface->pixmap(), rev_same,
- "nested " + desc2 + " then " + desc1);
+ if (always || same) {
+ CanvasCompareTester::quickCompareToReference(
+ nested_results.get(), combined_results.get(), same,
+ "nested " + desc1 + " then " + desc2);
+ }
+ if (always || rev_same) {
+ CanvasCompareTester::quickCompareToReference(
+ reverse_results.get(), combined_results.get(), rev_same,
+ "nested " + desc2 + " then " + desc1);
+ }
+ };
+
+ auto test_attributes = [test_attributes_env, &environments](
+ DlPaint& paint1, DlPaint& paint2,
+ const DlPaint& paint_both, bool same,
+ bool rev_same, const std::string& desc1,
+ const std::string& desc2) {
+ for (auto& env : environments) {
+ test_attributes_env(paint1, paint2, paint_both, //
+ same, rev_same, desc1, desc2, env.get());
}
};
diff --git a/display_list/display_list_color_filter_unittests.cc b/display_list/display_list_color_filter_unittests.cc
index 3642ec8..6884c60 100644
--- a/display_list/display_list_color_filter_unittests.cc
+++ b/display_list/display_list_color_filter_unittests.cc
@@ -2,9 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "flutter/display_list/display_list_attributes_testing.h"
#include "flutter/display_list/display_list_builder.h"
#include "flutter/display_list/display_list_color_filter.h"
+#include "flutter/display_list/testing/dl_test_equality.h"
#include "flutter/display_list/types.h"
namespace flutter {
diff --git a/display_list/display_list_color_source_unittests.cc b/display_list/display_list_color_source_unittests.cc
index 5c9a62a..8968ff5 100644
--- a/display_list/display_list_color_source_unittests.cc
+++ b/display_list/display_list_color_source_unittests.cc
@@ -5,12 +5,12 @@
#include <memory>
#include <vector>
-#include "flutter/display_list/display_list_attributes_testing.h"
#include "flutter/display_list/display_list_builder.h"
#include "flutter/display_list/display_list_color_source.h"
#include "flutter/display_list/display_list_image.h"
#include "flutter/display_list/display_list_runtime_effect.h"
#include "flutter/display_list/display_list_sampling_options.h"
+#include "flutter/display_list/testing/dl_test_equality.h"
#include "flutter/display_list/types.h"
#include "third_party/skia/include/core/SkString.h"
#include "third_party/skia/include/core/SkSurface.h"
diff --git a/display_list/display_list_color_unittests.cc b/display_list/display_list_color_unittests.cc
index f150605..0d44688 100644
--- a/display_list/display_list_color_unittests.cc
+++ b/display_list/display_list_color_unittests.cc
@@ -2,9 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "flutter/display_list/display_list_attributes_testing.h"
#include "flutter/display_list/display_list_builder.h"
#include "flutter/display_list/display_list_color_source.h"
+#include "flutter/display_list/testing/dl_test_equality.h"
#include "flutter/display_list/types.h"
#include "third_party/skia/include/core/SkSurface.h"
diff --git a/display_list/display_list_complexity_unittests.cc b/display_list/display_list_complexity_unittests.cc
index d2dfbcd..403ca30 100644
--- a/display_list/display_list_complexity_unittests.cc
+++ b/display_list/display_list_complexity_unittests.cc
@@ -8,7 +8,7 @@
#include "flutter/display_list/display_list_complexity_gl.h"
#include "flutter/display_list/display_list_complexity_metal.h"
#include "flutter/display_list/display_list_sampling_options.h"
-#include "flutter/display_list/display_list_test_utils.h"
+#include "flutter/display_list/testing/dl_test_snippets.h"
#include "flutter/testing/testing.h"
#include "third_party/skia/include/core/SkColor.h"
diff --git a/display_list/display_list_image_filter_unittests.cc b/display_list/display_list_image_filter_unittests.cc
index 95807c0..6170ab2 100644
--- a/display_list/display_list_image_filter_unittests.cc
+++ b/display_list/display_list_image_filter_unittests.cc
@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "flutter/display_list/display_list_attributes_testing.h"
#include "flutter/display_list/display_list_blend_mode.h"
#include "flutter/display_list/display_list_builder.h"
#include "flutter/display_list/display_list_color.h"
@@ -11,6 +10,7 @@
#include "flutter/display_list/display_list_image_filter.h"
#include "flutter/display_list/display_list_sampling_options.h"
#include "flutter/display_list/display_list_tile_mode.h"
+#include "flutter/display_list/testing/dl_test_equality.h"
#include "flutter/display_list/types.h"
#include "gtest/gtest.h"
diff --git a/display_list/display_list_mask_filter_unittests.cc b/display_list/display_list_mask_filter_unittests.cc
index 5a46856..a508dd2 100644
--- a/display_list/display_list_mask_filter_unittests.cc
+++ b/display_list/display_list_mask_filter_unittests.cc
@@ -2,10 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "flutter/display_list/display_list_attributes_testing.h"
#include "flutter/display_list/display_list_builder.h"
#include "flutter/display_list/display_list_comparable.h"
#include "flutter/display_list/display_list_mask_filter.h"
+#include "flutter/display_list/testing/dl_test_equality.h"
#include "flutter/display_list/types.h"
#include "gtest/gtest.h"
diff --git a/display_list/display_list_path_effect_unittests.cc b/display_list/display_list_path_effect_unittests.cc
index 9a89e22..f9bdc0d 100644
--- a/display_list/display_list_path_effect_unittests.cc
+++ b/display_list/display_list_path_effect_unittests.cc
@@ -2,9 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "flutter/display_list/display_list_attributes_testing.h"
#include "flutter/display_list/display_list_builder.h"
#include "flutter/display_list/display_list_comparable.h"
+#include "flutter/display_list/testing/dl_test_equality.h"
#include "flutter/display_list/types.h"
#include "gtest/gtest.h"
#include "include/core/SkPath.h"
diff --git a/display_list/display_list_unittests.cc b/display_list/display_list_unittests.cc
index 91ec814..63e34f2 100644
--- a/display_list/display_list_unittests.cc
+++ b/display_list/display_list_unittests.cc
@@ -14,8 +14,8 @@
#include "flutter/display_list/display_list_canvas_recorder.h"
#include "flutter/display_list/display_list_paint.h"
#include "flutter/display_list/display_list_rtree.h"
-#include "flutter/display_list/display_list_test_utils.h"
#include "flutter/display_list/display_list_utils.h"
+#include "flutter/display_list/testing/dl_test_snippets.h"
#include "flutter/fml/logging.h"
#include "flutter/fml/math.h"
#include "flutter/testing/display_list_testing.h"
diff --git a/display_list/display_list_vertices_unittests.cc b/display_list/display_list_vertices_unittests.cc
index 04d9549..0323b62 100644
--- a/display_list/display_list_vertices_unittests.cc
+++ b/display_list/display_list_vertices_unittests.cc
@@ -2,10 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "flutter/display_list/display_list_attributes_testing.h"
#include "flutter/display_list/display_list_builder.h"
#include "flutter/display_list/display_list_comparable.h"
#include "flutter/display_list/display_list_vertices.h"
+#include "flutter/display_list/testing/dl_test_equality.h"
#include "flutter/display_list/types.h"
#include "gtest/gtest.h"
diff --git a/display_list/testing/BUILD.gn b/display_list/testing/BUILD.gn
new file mode 100644
index 0000000..fabb290
--- /dev/null
+++ b/display_list/testing/BUILD.gn
@@ -0,0 +1,104 @@
+# Copyright 2013 The Flutter Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+# We only do software benchmarks on non-mobile platforms
+
+import("//flutter/impeller/tools/impeller.gni")
+
+source_set("display_list_testing") {
+ testonly = true
+
+ sources = [
+ "dl_test_equality.h",
+ "dl_test_snippets.cc",
+ "dl_test_snippets.h",
+ ]
+
+ deps = [
+ "//flutter/testing:testing_lib",
+ "//third_party/skia",
+ ]
+
+ public_deps = [ "//flutter/display_list:display_list" ]
+}
+
+surface_provider_include_software = !is_android && !is_ios
+
+# iOS and Fuchsia and Windows don't support OpenGL
+# Note: Windows would need some work to support OpenGL
+# But, since benchmarks do not run on Windows and rendertests only
+# runs on SW by default, this restriction currently only limits the
+# ability to manually cross-check OpenGL on Windows for rendertests
+surface_provider_include_gl = !is_fuchsia && !is_ios && !is_win
+
+# TODO (https://github.com/flutter/flutter/issues/107357):
+# impeller_enable_vulkan currently requires skia to not use VMA, which in turn
+# causes linkage problems with swiftshader.
+if (impeller_enable_vulkan) {
+ surface_provider_include_gl = false
+}
+
+surface_provider_include_metal = is_mac || is_ios
+
+config("surface_provider_config") {
+ defines = []
+
+ if (surface_provider_include_software) {
+ defines += [ "ENABLE_SOFTWARE_BENCHMARKS" ]
+ }
+ if (surface_provider_include_gl) {
+ defines += [ "ENABLE_OPENGL_BENCHMARKS" ]
+ }
+ if (surface_provider_include_metal) {
+ defines += [ "ENABLE_METAL_BENCHMARKS" ]
+ }
+
+ # Don't snapshot test results on mobile platforms
+ if (is_android || is_ios) {
+ defines += [ "BENCHMARKS_NO_SNAPSHOT" ]
+ }
+}
+
+source_set("display_list_surface_provider") {
+ testonly = true
+
+ sources = [ "dl_test_surface_provider.cc" ]
+
+ deps = [
+ "//flutter/common/graphics",
+ "//flutter/testing:testing_lib",
+ ]
+
+ public_configs = [ ":surface_provider_config" ]
+
+ if (is_android) {
+ libs = [
+ "android",
+ "EGL",
+ "GLESv2",
+ ]
+ }
+
+ if (surface_provider_include_software) {
+ sources += [
+ "dl_test_surface_software.cc",
+ "dl_test_surface_software.h",
+ ]
+ }
+
+ if (surface_provider_include_gl) {
+ sources += [
+ "dl_test_surface_gl.cc",
+ "dl_test_surface_gl.h",
+ ]
+ deps += [ "//flutter/testing:opengl" ]
+ }
+
+ if (surface_provider_include_metal) {
+ sources += [
+ "dl_test_surface_metal.cc",
+ "dl_test_surface_metal.h",
+ ]
+ deps += [ "//flutter/testing:metal" ]
+ }
+}
diff --git a/display_list/display_list_attributes_testing.h b/display_list/testing/dl_test_equality.h
similarity index 85%
rename from display_list/display_list_attributes_testing.h
rename to display_list/testing/dl_test_equality.h
index 37ef015..8e511e5 100644
--- a/display_list/display_list_attributes_testing.h
+++ b/display_list/testing/dl_test_equality.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef FLUTTER_DISPLAY_LIST_DISPLAY_LIST_ATTRIBUTES_TESTING_H_
-#define FLUTTER_DISPLAY_LIST_DISPLAY_LIST_ATTRIBUTES_TESTING_H_
+#ifndef FLUTTER_DISPLAY_LIST_TESTING_DL_TEST_EQUALITY_H_
+#define FLUTTER_DISPLAY_LIST_TESTING_DL_TEST_EQUALITY_H_
#include "flutter/display_list/display_list_attributes.h"
#include "flutter/display_list/display_list_comparable.h"
@@ -39,4 +39,4 @@
} // namespace testing
} // namespace flutter
-#endif // FLUTTER_DISPLAY_LIST_DISPLAY_LIST_ATTRIBUTES_TESTING_H_
+#endif // FLUTTER_DISPLAY_LIST_TESTING_DL_TEST_EQUALITY_H_
diff --git a/display_list/display_list_test_utils.cc b/display_list/testing/dl_test_snippets.cc
similarity index 99%
rename from display_list/display_list_test_utils.cc
rename to display_list/testing/dl_test_snippets.cc
index 9d8ee65..1ba810f 100644
--- a/display_list/display_list_test_utils.cc
+++ b/display_list/testing/dl_test_snippets.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "flutter/display_list/display_list_test_utils.h"
+#include "flutter/display_list/testing/dl_test_snippets.h"
#include "flutter/display_list/display_list_builder.h"
namespace flutter {
diff --git a/display_list/display_list_test_utils.h b/display_list/testing/dl_test_snippets.h
similarity index 97%
rename from display_list/display_list_test_utils.h
rename to display_list/testing/dl_test_snippets.h
index 711b718..07396f5 100644
--- a/display_list/display_list_test_utils.h
+++ b/display_list/testing/dl_test_snippets.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef FLUTTER_FLOW_DISPLAY_LIST_COMPLEXITY_UNITTESTS_H_
-#define FLUTTER_FLOW_DISPLAY_LIST_COMPLEXITY_UNITTESTS_H_
+#ifndef FLUTTER_DISPLAY_LIST_TESTING_DL_TEST_SNIPPETS_H_
+#define FLUTTER_DISPLAY_LIST_TESTING_DL_TEST_SNIPPETS_H_
#include "flutter/display_list/display_list.h"
#include "flutter/display_list/display_list_builder.h"
@@ -333,4 +333,4 @@
} // namespace testing
} // namespace flutter
-#endif // FLUTTER_FLOW_DISPLAY_LIST_COMPLEXITY_UNITTESTS_H_
+#endif // FLUTTER_DISPLAY_LIST_TESTING_DL_TEST_SNIPPETS_H_
diff --git a/display_list/testing/dl_test_surface_gl.cc b/display_list/testing/dl_test_surface_gl.cc
new file mode 100644
index 0000000..ce9d627
--- /dev/null
+++ b/display_list/testing/dl_test_surface_gl.cc
@@ -0,0 +1,47 @@
+// Copyright 2013 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "flutter/display_list/testing/dl_test_surface_gl.h"
+
+#include "third_party/skia/include/core/SkCanvas.h"
+#include "third_party/skia/include/core/SkSurface.h"
+
+namespace flutter {
+namespace testing {
+
+using PixelFormat = DlSurfaceProvider::PixelFormat;
+
+bool DlOpenGLSurfaceProvider::InitializeSurface(size_t width,
+ size_t height,
+ PixelFormat format) {
+ gl_surface_ = std::make_unique<TestGLSurface>(SkISize::Make(width, height));
+ gl_surface_->MakeCurrent();
+
+ primary_ = MakeOffscreenSurface(width, height, format);
+ return true;
+}
+
+std::shared_ptr<DlSurfaceInstance> DlOpenGLSurfaceProvider::GetPrimarySurface()
+ const {
+ if (!gl_surface_->MakeCurrent()) {
+ return nullptr;
+ }
+ return primary_;
+}
+
+std::shared_ptr<DlSurfaceInstance>
+DlOpenGLSurfaceProvider::MakeOffscreenSurface(size_t width,
+ size_t height,
+ PixelFormat format) const {
+ auto offscreen_surface = SkSurface::MakeRenderTarget(
+ (GrRecordingContext*)gl_surface_->GetGrContext().get(),
+ skgpu::Budgeted::kNo, MakeInfo(format, width, height), 1,
+ kTopLeft_GrSurfaceOrigin, nullptr, false);
+
+ offscreen_surface->getCanvas()->clear(SK_ColorTRANSPARENT);
+ return std::make_shared<DlSurfaceInstanceBase>(offscreen_surface);
+}
+
+} // namespace testing
+} // namespace flutter
diff --git a/display_list/testing/dl_test_surface_gl.h b/display_list/testing/dl_test_surface_gl.h
new file mode 100644
index 0000000..882e0fd
--- /dev/null
+++ b/display_list/testing/dl_test_surface_gl.h
@@ -0,0 +1,42 @@
+// Copyright 2013 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef FLUTTER_DISPLAY_LIST_TESTING_DL_TEST_SURFACE_GL_H_
+#define FLUTTER_DISPLAY_LIST_TESTING_DL_TEST_SURFACE_GL_H_
+
+#include "flutter/display_list/testing/dl_test_surface_provider.h"
+
+#include "flutter/testing/test_gl_surface.h"
+
+namespace flutter {
+namespace testing {
+
+class DlOpenGLSurfaceProvider : public DlSurfaceProvider {
+ public:
+ DlOpenGLSurfaceProvider() : DlSurfaceProvider() {}
+ virtual ~DlOpenGLSurfaceProvider() = default;
+
+ bool InitializeSurface(size_t width,
+ size_t height,
+ PixelFormat format) override;
+ std::shared_ptr<DlSurfaceInstance> GetPrimarySurface() const override;
+ std::shared_ptr<DlSurfaceInstance> MakeOffscreenSurface(
+ size_t width,
+ size_t height,
+ PixelFormat format) const override;
+ const std::string backend_name() const override { return "OpenGL"; }
+ BackendType backend_type() const override { return kOpenGL_Backend; }
+ bool supports(PixelFormat format) const override {
+ return format == kN32Premul_PixelFormat;
+ }
+
+ private:
+ std::shared_ptr<DlSurfaceInstance> primary_;
+ std::unique_ptr<TestGLSurface> gl_surface_;
+};
+
+} // namespace testing
+} // namespace flutter
+
+#endif // FLUTTER_DISPLAY_LIST_TESTING_DL_TEST_SURFACE_GL_H_
diff --git a/display_list/testing/dl_test_surface_metal.cc b/display_list/testing/dl_test_surface_metal.cc
new file mode 100644
index 0000000..7c3617e
--- /dev/null
+++ b/display_list/testing/dl_test_surface_metal.cc
@@ -0,0 +1,58 @@
+// Copyright 2013 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "flutter/display_list/testing/dl_test_surface_metal.h"
+
+#include "third_party/skia/include/core/SkCanvas.h"
+#include "third_party/skia/include/core/SkSurface.h"
+
+namespace flutter {
+namespace testing {
+
+class DlMetalSurfaceInstance : public DlSurfaceInstance {
+ public:
+ explicit DlMetalSurfaceInstance(
+ std::unique_ptr<TestMetalSurface> metal_surface)
+ : metal_surface_(std::move(metal_surface)) {}
+ ~DlMetalSurfaceInstance() = default;
+
+ sk_sp<SkSurface> sk_surface() const override {
+ return metal_surface_->GetSurface();
+ }
+
+ private:
+ std::unique_ptr<TestMetalSurface> metal_surface_;
+};
+
+bool DlMetalSurfaceProvider::InitializeSurface(size_t width,
+ size_t height,
+ PixelFormat format) {
+ if (format != kN32Premul_PixelFormat) {
+ return false;
+ }
+ metal_context_ = std::make_unique<TestMetalContext>();
+ metal_surface_ = MakeOffscreenSurface(width, height, format);
+ return true;
+}
+
+std::shared_ptr<DlSurfaceInstance> DlMetalSurfaceProvider::GetPrimarySurface()
+ const {
+ if (!metal_surface_) {
+ return nullptr;
+ }
+ return metal_surface_;
+}
+
+std::shared_ptr<DlSurfaceInstance> DlMetalSurfaceProvider::MakeOffscreenSurface(
+ size_t width,
+ size_t height,
+ PixelFormat format) const {
+ auto surface =
+ TestMetalSurface::Create(*metal_context_, SkISize::Make(width, height));
+ surface->GetSurface()->getCanvas()->clear(SK_ColorTRANSPARENT);
+ return std::make_shared<DlMetalSurfaceInstance>(std::move(surface));
+}
+
+} // namespace testing
+} // namespace flutter
diff --git a/display_list/testing/dl_test_surface_metal.h b/display_list/testing/dl_test_surface_metal.h
new file mode 100644
index 0000000..c660c6d
--- /dev/null
+++ b/display_list/testing/dl_test_surface_metal.h
@@ -0,0 +1,42 @@
+// Copyright 2013 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef FLUTTER_DISPLAY_LIST_TESTING_DL_TEST_SURFACE_METAL_H_
+#define FLUTTER_DISPLAY_LIST_TESTING_DL_TEST_SURFACE_METAL_H_
+
+#include "flutter/display_list/testing/dl_test_surface_provider.h"
+
+#include "flutter/testing/test_metal_surface.h"
+
+namespace flutter {
+namespace testing {
+
+class DlMetalSurfaceProvider : public DlSurfaceProvider {
+ public:
+ explicit DlMetalSurfaceProvider() : DlSurfaceProvider() {}
+ virtual ~DlMetalSurfaceProvider() = default;
+
+ bool InitializeSurface(size_t width,
+ size_t height,
+ PixelFormat format) override;
+ std::shared_ptr<DlSurfaceInstance> GetPrimarySurface() const override;
+ std::shared_ptr<DlSurfaceInstance> MakeOffscreenSurface(
+ size_t width,
+ size_t height,
+ PixelFormat format) const override;
+ const std::string backend_name() const override { return "Metal"; }
+ BackendType backend_type() const override { return kMetal_Backend; }
+ bool supports(PixelFormat format) const override {
+ return format == kN32Premul_PixelFormat;
+ }
+
+ private:
+ std::unique_ptr<TestMetalContext> metal_context_;
+ std::shared_ptr<DlSurfaceInstance> metal_surface_;
+};
+
+} // namespace testing
+} // namespace flutter
+
+#endif // FLUTTER_DISPLAY_LIST_TESTING_DL_TEST_SURFACE_METAL_H_
diff --git a/display_list/testing/dl_test_surface_provider.cc b/display_list/testing/dl_test_surface_provider.cc
new file mode 100644
index 0000000..99ac2f7
--- /dev/null
+++ b/display_list/testing/dl_test_surface_provider.cc
@@ -0,0 +1,69 @@
+// Copyright 2013 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "flutter/display_list/testing/dl_test_surface_provider.h"
+
+#include "third_party/skia/include/core/SkCanvas.h"
+#include "third_party/skia/include/core/SkData.h"
+#include "third_party/skia/include/core/SkSurface.h"
+
+#ifdef ENABLE_SOFTWARE_BENCHMARKS
+#include "flutter/display_list/testing/dl_test_surface_software.h"
+#endif
+#ifdef ENABLE_OPENGL_BENCHMARKS
+#include "flutter/display_list/testing/dl_test_surface_gl.h"
+#endif
+#ifdef ENABLE_METAL_BENCHMARKS
+#include "flutter/display_list/testing/dl_test_surface_metal.h"
+#endif
+
+namespace flutter {
+namespace testing {
+
+std::unique_ptr<DlSurfaceProvider> DlSurfaceProvider::Create(
+ BackendType backend_type) {
+ switch (backend_type) {
+#ifdef ENABLE_SOFTWARE_BENCHMARKS
+ case kSoftware_Backend:
+ return std::make_unique<DlSoftwareSurfaceProvider>();
+#endif
+#ifdef ENABLE_OPENGL_BENCHMARKS
+ case kOpenGL_Backend:
+ return std::make_unique<DlOpenGLSurfaceProvider>();
+#endif
+#ifdef ENABLE_METAL_BENCHMARKS
+ case kMetal_Backend:
+ return std::make_unique<DlMetalSurfaceProvider>();
+#endif
+ default:
+ return nullptr;
+ }
+
+ return nullptr;
+}
+
+bool DlSurfaceProvider::Snapshot(std::string& filename) const {
+#ifdef BENCHMARKS_NO_SNAPSHOT
+ return false;
+#else
+ auto image = GetPrimarySurface()->sk_surface()->makeImageSnapshot();
+ if (!image) {
+ return false;
+ }
+ auto raster = image->makeRasterImage();
+ if (!raster) {
+ return false;
+ }
+ auto data = raster->encodeToData();
+ if (!data) {
+ return false;
+ }
+ fml::NonOwnedMapping mapping(static_cast<const uint8_t*>(data->data()),
+ data->size());
+ return WriteAtomically(OpenFixturesDirectory(), filename.c_str(), mapping);
+#endif
+}
+
+} // namespace testing
+} // namespace flutter
diff --git a/display_list/testing/dl_test_surface_provider.h b/display_list/testing/dl_test_surface_provider.h
new file mode 100644
index 0000000..d3944ab
--- /dev/null
+++ b/display_list/testing/dl_test_surface_provider.h
@@ -0,0 +1,82 @@
+// Copyright 2013 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef FLUTTER_DISPLAY_LIST_TESTING_DL_TEST_SURFACE_PROVIDER_H_
+#define FLUTTER_DISPLAY_LIST_TESTING_DL_TEST_SURFACE_PROVIDER_H_
+
+#include "flutter/fml/mapping.h"
+#include "flutter/testing/testing.h"
+
+#include "third_party/skia/include/core/SkSurface.h"
+
+namespace flutter {
+namespace testing {
+
+class DlSurfaceInstance {
+ public:
+ virtual ~DlSurfaceInstance() = default;
+
+ virtual sk_sp<SkSurface> sk_surface() const = 0;
+
+ int width() const { return sk_surface()->width(); }
+ int height() const { return sk_surface()->height(); }
+};
+
+class DlSurfaceInstanceBase : public DlSurfaceInstance {
+ public:
+ DlSurfaceInstanceBase(sk_sp<SkSurface> surface) : surface_(surface) {}
+ ~DlSurfaceInstanceBase() = default;
+
+ sk_sp<SkSurface> sk_surface() const override { return surface_; }
+
+ private:
+ sk_sp<SkSurface> surface_;
+};
+
+class DlSurfaceProvider {
+ public:
+ typedef enum { kN32Premul_PixelFormat, k565_PixelFormat } PixelFormat;
+ typedef enum {
+ kSoftware_Backend,
+ kOpenGL_Backend,
+ kMetal_Backend
+ } BackendType;
+
+ static SkImageInfo MakeInfo(PixelFormat format, int w, int h) {
+ switch (format) {
+ case kN32Premul_PixelFormat:
+ return SkImageInfo::MakeN32Premul(w, h);
+ case k565_PixelFormat:
+ return SkImageInfo::Make(SkISize::Make(w, h), kRGB_565_SkColorType,
+ kOpaque_SkAlphaType);
+ }
+ FML_DCHECK(false);
+ }
+
+ static std::unique_ptr<DlSurfaceProvider> Create(BackendType backend_type);
+
+ virtual ~DlSurfaceProvider() = default;
+ virtual const std::string backend_name() const = 0;
+ virtual BackendType backend_type() const = 0;
+ virtual bool supports(PixelFormat format) const = 0;
+ virtual bool InitializeSurface(
+ size_t width,
+ size_t height,
+ PixelFormat format = kN32Premul_PixelFormat) = 0;
+ virtual std::shared_ptr<DlSurfaceInstance> GetPrimarySurface() const = 0;
+ virtual std::shared_ptr<DlSurfaceInstance> MakeOffscreenSurface(
+ size_t width,
+ size_t height,
+ PixelFormat format = kN32Premul_PixelFormat) const = 0;
+
+ virtual bool Snapshot(std::string& filename) const;
+
+ protected:
+ DlSurfaceProvider() = default;
+};
+
+} // namespace testing
+} // namespace flutter
+
+#endif // FLUTTER_DISPLAY_LIST_TESTING_DL_TEST_SURFACE_PROVIDER_H_
diff --git a/display_list/testing/dl_test_surface_software.cc b/display_list/testing/dl_test_surface_software.cc
new file mode 100644
index 0000000..8a887a6
--- /dev/null
+++ b/display_list/testing/dl_test_surface_software.cc
@@ -0,0 +1,32 @@
+// Copyright 2013 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "flutter/display_list/testing/dl_test_surface_software.h"
+
+#include "third_party/skia/include/core/SkCanvas.h"
+#include "third_party/skia/include/core/SkSurface.h"
+
+namespace flutter {
+namespace testing {
+
+using PixelFormat = DlSurfaceProvider::PixelFormat;
+
+bool DlSoftwareSurfaceProvider::InitializeSurface(size_t width,
+ size_t height,
+ PixelFormat format) {
+ primary_ = MakeOffscreenSurface(width, height, format);
+ return primary_ != nullptr;
+}
+
+std::shared_ptr<DlSurfaceInstance>
+DlSoftwareSurfaceProvider::MakeOffscreenSurface(size_t width,
+ size_t height,
+ PixelFormat format) const {
+ auto surface = SkSurface::MakeRaster(MakeInfo(format, width, height));
+ surface->getCanvas()->clear(SK_ColorTRANSPARENT);
+ return std::make_shared<DlSurfaceInstanceBase>(surface);
+}
+
+} // namespace testing
+} // namespace flutter
diff --git a/display_list/testing/dl_test_surface_software.h b/display_list/testing/dl_test_surface_software.h
new file mode 100644
index 0000000..5fbbe19
--- /dev/null
+++ b/display_list/testing/dl_test_surface_software.h
@@ -0,0 +1,39 @@
+// Copyright 2013 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef FLUTTER_DISPLAY_LIST_TESTING_DL_TEST_SURFACE_SOFTWARE_H_
+#define FLUTTER_DISPLAY_LIST_TESTING_DL_TEST_SURFACE_SOFTWARE_H_
+
+#include "flutter/display_list/testing/dl_test_surface_provider.h"
+
+namespace flutter {
+namespace testing {
+
+class DlSoftwareSurfaceProvider : public DlSurfaceProvider {
+ public:
+ DlSoftwareSurfaceProvider() = default;
+ virtual ~DlSoftwareSurfaceProvider() = default;
+
+ bool InitializeSurface(size_t width,
+ size_t height,
+ PixelFormat format) override;
+ std::shared_ptr<DlSurfaceInstance> GetPrimarySurface() const override {
+ return primary_;
+ }
+ std::shared_ptr<DlSurfaceInstance> MakeOffscreenSurface(
+ size_t width,
+ size_t height,
+ PixelFormat format) const override;
+ const std::string backend_name() const override { return "Software"; }
+ BackendType backend_type() const override { return kSoftware_Backend; }
+ bool supports(PixelFormat format) const override { return true; }
+
+ private:
+ std::shared_ptr<DlSurfaceInstance> primary_;
+};
+
+} // namespace testing
+} // namespace flutter
+
+#endif // FLUTTER_DISPLAY_LIST_TESTING_DL_TEST_SURFACE_SOFTWARE_H_
diff --git a/flow/BUILD.gn b/flow/BUILD.gn
index 09ed594..c3261cb 100644
--- a/flow/BUILD.gn
+++ b/flow/BUILD.gn
@@ -183,7 +183,7 @@
":flow_fixtures",
":flow_testing",
"//flutter/common/graphics",
- "//flutter/display_list:display_list_testing",
+ "//flutter/display_list/testing:display_list_testing",
"//flutter/fml",
"//flutter/testing:skia",
"//flutter/testing:testing_lib",
diff --git a/flow/raster_cache_unittests.cc b/flow/raster_cache_unittests.cc
index 90d31ef..d3bb3cb 100644
--- a/flow/raster_cache_unittests.cc
+++ b/flow/raster_cache_unittests.cc
@@ -4,7 +4,7 @@
#include "flutter/display_list/display_list.h"
#include "flutter/display_list/display_list_builder.h"
-#include "flutter/display_list/display_list_test_utils.h"
+#include "flutter/display_list/testing/dl_test_snippets.h"
#include "flutter/flow/layers/container_layer.h"
#include "flutter/flow/layers/display_list_layer.h"
#include "flutter/flow/layers/image_filter_layer.h"