Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit f4fa7db

Browse files
flarharryterkelsen
authored andcommitted
Add option to save Impeller failure images in rendertests (#47142)
The rendering tests currently always save the impeller failure images into a temporary directory in /tmp which is out of the way and might accumulate over time. The images are now only saved when `--save-impeller-failures` is specified on the command line and they are now saved into a local sub-directory with multiple runs saving into new sub-directories to keep the failure images from getting confused with each other over time. The new image directories are named `./impeller_failure_images/NNNN/*.png`
1 parent 1e9a3a1 commit f4fa7db

File tree

1 file changed

+114
-39
lines changed

1 file changed

+114
-39
lines changed

display_list/testing/dl_rendering_unittests.cc

Lines changed: 114 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "flutter/display_list/skia/dl_sk_dispatcher.h"
1414
#include "flutter/display_list/testing/dl_test_surface_provider.h"
1515
#include "flutter/display_list/utils/dl_comparable.h"
16+
#include "flutter/fml/file.h"
1617
#include "flutter/fml/math.h"
1718
#include "flutter/testing/display_list_testing.h"
1819
#include "flutter/testing/testing.h"
@@ -1102,8 +1103,10 @@ class TestParameters {
11021103

11031104
class CanvasCompareTester {
11041105
public:
1105-
static std::vector<BackendType> kTestBackends;
1106-
static std::string kTempDirectory;
1106+
static std::vector<BackendType> TestBackends;
1107+
static std::string ImpellerFailureImageDirectory;
1108+
static bool SaveImpellerFailureImages;
1109+
static std::vector<std::string> ImpellerFailureImages;
11071110

11081111
static std::unique_ptr<DlSurfaceProvider> GetProvider(BackendType type) {
11091112
auto provider = DlSurfaceProvider::Create(type);
@@ -1122,15 +1125,15 @@ class CanvasCompareTester {
11221125
if (!provider) {
11231126
return false;
11241127
}
1125-
CanvasCompareTester::kTestBackends.push_back(type);
1128+
CanvasCompareTester::TestBackends.push_back(type);
11261129
return true;
11271130
}
11281131

11291132
static BoundsTolerance DefaultTolerance;
11301133

11311134
static void RenderAll(const TestParameters& params,
11321135
const BoundsTolerance& tolerance = DefaultTolerance) {
1133-
for (auto& back_end : kTestBackends) {
1136+
for (auto& back_end : TestBackends) {
11341137
auto provider = GetProvider(back_end);
11351138
RenderEnvironment env = RenderEnvironment::MakeN32(provider.get());
11361139
env.init_ref(kEmptySkSetup, params.sk_renderer(), //
@@ -1142,8 +1145,8 @@ class CanvasCompareTester {
11421145
"Impeller reference")) {
11431146
std::string test_name =
11441147
::testing::UnitTest::GetInstance()->current_test_info()->name();
1145-
impeller_result->write(
1146-
to_png_filename(test_name + " (Impeller reference)"));
1148+
save_to_png(impeller_result, test_name + " (Impeller reference)",
1149+
"base rendering was blank or out of bounds");
11471150
}
11481151
} else {
11491152
static OncePerBackendWarning warnings("No Impeller output tests");
@@ -2264,16 +2267,75 @@ class CanvasCompareTester {
22642267
.with_diff_clip());
22652268
}
22662269

2267-
static std::string to_png_filename(const std::string& desc) {
2268-
if (kTempDirectory.length() == 0) {
2269-
kTempDirectory = fml::CreateTemporaryDirectory();
2270+
enum class DirectoryStatus {
2271+
kExisted,
2272+
kCreated,
2273+
kFailed,
2274+
};
2275+
2276+
static DirectoryStatus CheckDir(const std::string& dir) {
2277+
auto ret =
2278+
fml::OpenDirectory(dir.c_str(), false, fml::FilePermission::kRead);
2279+
if (ret.is_valid()) {
2280+
return DirectoryStatus::kExisted;
2281+
}
2282+
ret =
2283+
fml::OpenDirectory(dir.c_str(), true, fml::FilePermission::kReadWrite);
2284+
if (ret.is_valid()) {
2285+
return DirectoryStatus::kCreated;
22702286
}
2287+
FML_LOG(ERROR) << "Could not create directory (" << dir
2288+
<< ") for impeller failure images"
2289+
<< ", ret = " << ret.get() << ", errno = " << errno;
2290+
return DirectoryStatus::kFailed;
2291+
}
22712292

2272-
std::string ret = kTempDirectory + "/";
2273-
for (const char& ch : desc) {
2274-
ret += (ch == ':' || ch == ' ') ? '_' : ch;
2293+
static void SetupImpellerFailureImageDirectory() {
2294+
std::string base_dir = "./impeller_failure_images";
2295+
if (CheckDir(base_dir) == DirectoryStatus::kFailed) {
2296+
return;
2297+
}
2298+
for (int i = 0; i < 10000; i++) {
2299+
std::string sub_dir = std::to_string(i);
2300+
while (sub_dir.length() < 4) {
2301+
sub_dir = "0" + sub_dir;
2302+
}
2303+
std::string try_dir = base_dir + "/" + sub_dir;
2304+
switch (CheckDir(try_dir)) {
2305+
case DirectoryStatus::kExisted:
2306+
break;
2307+
case DirectoryStatus::kCreated:
2308+
ImpellerFailureImageDirectory = try_dir;
2309+
return;
2310+
case DirectoryStatus::kFailed:
2311+
return;
2312+
}
22752313
}
2276-
return ret + ".png";
2314+
FML_LOG(ERROR) << "Too many output directories for Impeller failure images";
2315+
}
2316+
2317+
static void save_to_png(const RenderResult* result,
2318+
const std::string& op_desc,
2319+
const std::string& reason) {
2320+
if (!SaveImpellerFailureImages) {
2321+
return;
2322+
}
2323+
if (ImpellerFailureImageDirectory.length() == 0) {
2324+
SetupImpellerFailureImageDirectory();
2325+
if (ImpellerFailureImageDirectory.length() == 0) {
2326+
SaveImpellerFailureImages = false;
2327+
return;
2328+
}
2329+
}
2330+
2331+
std::string filename = ImpellerFailureImageDirectory + "/";
2332+
for (const char& ch : op_desc) {
2333+
filename += (ch == ':' || ch == ' ') ? '_' : ch;
2334+
}
2335+
filename = filename + ".png";
2336+
result->write(filename);
2337+
ImpellerFailureImages.push_back(filename);
2338+
FML_LOG(ERROR) << reason << ": " << filename;
22772339
}
22782340

22792341
static void RenderWith(const TestParameters& testP,
@@ -2352,23 +2414,17 @@ class CanvasCompareTester {
23522414
env.ref_impeller_result(), imp_result.get(), false,
23532415
imp_info + " (attribute should affect rendering)");
23542416
}
2355-
if (!success) {
2417+
if (SaveImpellerFailureImages && !success) {
23562418
FML_LOG(ERROR) << "Impeller issue encountered for: "
23572419
<< *imp_job.MakeDisplayList(base_info);
2358-
std::string filename = to_png_filename(info + " (Impeller Output)");
2359-
imp_result->write(filename);
2360-
FML_LOG(ERROR) << "output saved in: " << filename;
2361-
std::string src_filename = to_png_filename(info + " (Impeller Input)");
2362-
env.ref_impeller_result()->write(src_filename);
2363-
FML_LOG(ERROR) << "compare to reference without attributes: "
2364-
<< src_filename;
2365-
std::string sk_filename = to_png_filename(info + " (Skia Output)");
2366-
sk_result->write(sk_filename);
2367-
FML_LOG(ERROR) << "and to Skia reference with attributes: "
2368-
<< sk_filename;
2369-
std::string sk_src_filename = to_png_filename(info + " (Skia Input)");
2370-
env.ref_sk_result()->write(sk_src_filename);
2371-
FML_LOG(ERROR) << "operating on Skia source image: " << sk_src_filename;
2420+
save_to_png(imp_result.get(), info + " (Impeller Result)",
2421+
"output saved in");
2422+
save_to_png(env.ref_impeller_result(), info + " (Impeller Reference)",
2423+
"compare to reference without attributes");
2424+
save_to_png(sk_result.get(), info + " (Skia Result)",
2425+
"and to Skia reference with attributes");
2426+
save_to_png(env.ref_sk_result(), info + " (Skia Reference)",
2427+
"and to Skia reference without attributes");
23722428
}
23732429
}
23742430

@@ -2755,8 +2811,10 @@ class CanvasCompareTester {
27552811
}
27562812
};
27572813

2758-
std::vector<BackendType> CanvasCompareTester::kTestBackends;
2759-
std::string CanvasCompareTester::kTempDirectory = "";
2814+
std::vector<BackendType> CanvasCompareTester::TestBackends;
2815+
std::string CanvasCompareTester::ImpellerFailureImageDirectory = "";
2816+
bool CanvasCompareTester::SaveImpellerFailureImages = false;
2817+
std::vector<std::string> CanvasCompareTester::ImpellerFailureImages;
27602818

27612819
BoundsTolerance CanvasCompareTester::DefaultTolerance =
27622820
BoundsTolerance().addAbsolutePadding(1, 1);
@@ -2790,6 +2848,10 @@ class DisplayListRenderingTestBase : public BaseT,
27902848
for (auto p_arg = std::next(args.begin()); p_arg != args.end(); p_arg++) {
27912849
std::string arg = *p_arg;
27922850
bool enable = true;
2851+
if (arg == "--save-impeller-failures") {
2852+
CanvasCompareTester::SaveImpellerFailureImages = true;
2853+
continue;
2854+
}
27932855
if (StartsWith(arg, "--no")) {
27942856
enable = false;
27952857
arg = "-" + arg.substr(4);
@@ -2812,12 +2874,25 @@ class DisplayListRenderingTestBase : public BaseT,
28122874
CanvasCompareTester::AddProvider(BackendType::kMetalBackend);
28132875
}
28142876
std::string providers = "";
2815-
for (auto& back_end : CanvasCompareTester::kTestBackends) {
2877+
for (auto& back_end : CanvasCompareTester::TestBackends) {
28162878
providers += " " + DlSurfaceProvider::BackendName(back_end);
28172879
}
28182880
FML_LOG(INFO) << "Running tests on [" << providers << " ]";
28192881
}
28202882

2883+
static void TearDownTestSuite() {
2884+
if (CanvasCompareTester::ImpellerFailureImages.size() > 0) {
2885+
FML_LOG(INFO);
2886+
FML_LOG(INFO) << CanvasCompareTester::ImpellerFailureImages.size()
2887+
<< " images saved in "
2888+
<< CanvasCompareTester::ImpellerFailureImageDirectory;
2889+
for (auto filename : CanvasCompareTester::ImpellerFailureImages) {
2890+
FML_LOG(INFO) << " " << filename;
2891+
}
2892+
FML_LOG(INFO);
2893+
}
2894+
}
2895+
28212896
private:
28222897
FML_DISALLOW_COPY_AND_ASSIGN(DisplayListRenderingTestBase);
28232898
};
@@ -3811,7 +3886,7 @@ TEST_F(DisplayListRendering, SaveLayerClippedContentStillFilters) {
38113886
CaseParameters case_params("Filtered SaveLayer with clipped content");
38123887
BoundsTolerance tolerance = BoundsTolerance().addAbsolutePadding(6.0f, 6.0f);
38133888

3814-
for (auto& back_end : CanvasCompareTester::kTestBackends) {
3889+
for (auto& back_end : CanvasCompareTester::TestBackends) {
38153890
auto provider = CanvasCompareTester::GetProvider(back_end);
38163891
RenderEnvironment env = RenderEnvironment::MakeN32(provider.get());
38173892
env.init_ref(kEmptySkSetup, test_params.sk_renderer(), //
@@ -3926,7 +4001,7 @@ TEST_F(DisplayListRendering, SaveLayerConsolidation) {
39264001
bool same, bool rev_same,
39274002
const std::string& desc1,
39284003
const std::string& desc2) {
3929-
for (auto& back_end : CanvasCompareTester::kTestBackends) {
4004+
for (auto& back_end : CanvasCompareTester::TestBackends) {
39304005
auto provider = CanvasCompareTester::GetProvider(back_end);
39314006
auto env = std::make_unique<RenderEnvironment>(
39324007
provider.get(), PixelFormat::kN32PremulPixelFormat);
@@ -4039,7 +4114,7 @@ TEST_F(DisplayListRendering, MatrixColorFilterModifyTransparencyCheck) {
40394114
builder2.Restore();
40404115
auto display_list2 = builder2.Build();
40414116

4042-
for (auto& back_end : CanvasCompareTester::kTestBackends) {
4117+
for (auto& back_end : CanvasCompareTester::TestBackends) {
40434118
auto provider = CanvasCompareTester::GetProvider(back_end);
40444119
auto env = std::make_unique<RenderEnvironment>(
40454120
provider.get(), PixelFormat::kN32PremulPixelFormat);
@@ -4110,7 +4185,7 @@ TEST_F(DisplayListRendering, MatrixColorFilterOpacityCommuteCheck) {
41104185
builder2.Restore();
41114186
auto display_list2 = builder2.Build();
41124187

4113-
for (auto& back_end : CanvasCompareTester::kTestBackends) {
4188+
for (auto& back_end : CanvasCompareTester::TestBackends) {
41144189
auto provider = CanvasCompareTester::GetProvider(back_end);
41154190
auto env = std::make_unique<RenderEnvironment>(
41164191
provider.get(), PixelFormat::kN32PremulPixelFormat);
@@ -4215,7 +4290,7 @@ TEST_F(DisplayListRendering, BlendColorFilterModifyTransparencyCheck) {
42154290
builder2.Restore();
42164291
auto display_list2 = builder2.Build();
42174292

4218-
for (auto& back_end : CanvasCompareTester::kTestBackends) {
4293+
for (auto& back_end : CanvasCompareTester::TestBackends) {
42194294
auto provider = CanvasCompareTester::GetProvider(back_end);
42204295
auto env = std::make_unique<RenderEnvironment>(
42214296
provider.get(), PixelFormat::kN32PremulPixelFormat);
@@ -4279,7 +4354,7 @@ TEST_F(DisplayListRendering, BlendColorFilterOpacityCommuteCheck) {
42794354
builder2.Restore();
42804355
auto display_list2 = builder2.Build();
42814356

4282-
for (auto& back_end : CanvasCompareTester::kTestBackends) {
4357+
for (auto& back_end : CanvasCompareTester::TestBackends) {
42834358
auto provider = CanvasCompareTester::GetProvider(back_end);
42844359
auto env = std::make_unique<RenderEnvironment>(
42854360
provider.get(), PixelFormat::kN32PremulPixelFormat);
@@ -4538,7 +4613,7 @@ class DisplayListNopTest : public DisplayListRendering {
45384613
SkPaint sk_paint;
45394614
sk_paint.setBlendMode(sk_mode);
45404615
sk_paint.setColor(ToSk(color));
4541-
for (auto& back_end : CanvasCompareTester::kTestBackends) {
4616+
for (auto& back_end : CanvasCompareTester::TestBackends) {
45424617
auto provider = CanvasCompareTester::GetProvider(back_end);
45434618
auto result_surface = provider->MakeOffscreenSurface(
45444619
test_image->width(), test_image->height(),
@@ -4601,7 +4676,7 @@ class DisplayListNopTest : public DisplayListRendering {
46014676
sk_paint.setColor(ToSk(color));
46024677
sk_paint.setColorFilter(ToSk(color_filter));
46034678
sk_paint.setImageFilter(ToSk(image_filter));
4604-
for (auto& back_end : CanvasCompareTester::kTestBackends) {
4679+
for (auto& back_end : CanvasCompareTester::TestBackends) {
46054680
auto provider = CanvasCompareTester::GetProvider(back_end);
46064681
auto result_surface = provider->MakeOffscreenSurface(
46074682
w, h, DlSurfaceProvider::kN32PremulPixelFormat);

0 commit comments

Comments
 (0)