aboutsummaryrefslogtreecommitdiffhomepage
path: root/dm/DM.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'dm/DM.cpp')
-rw-r--r--dm/DM.cpp580
1 files changed, 225 insertions, 355 deletions
diff --git a/dm/DM.cpp b/dm/DM.cpp
index d8efc58448..7113ad839a 100644
--- a/dm/DM.cpp
+++ b/dm/DM.cpp
@@ -1,423 +1,293 @@
+// Main binary for DM.
+// For a high-level overview, please see dm/README.
+
#include "CrashHandler.h"
-#include "DMJsonWriter.h"
-#include "DMSrcSink.h"
-#include "OverwriteLine.h"
-#include "ProcStats.h"
-#include "SkBBHFactory.h"
+#include "LazyDecodeBitmap.h"
#include "SkCommonFlags.h"
#include "SkForceLinking.h"
#include "SkGraphics.h"
-#include "SkMD5.h"
#include "SkOSFile.h"
+#include "SkPicture.h"
+#include "SkString.h"
#include "SkTaskGroup.h"
#include "Test.h"
-#include "Timer.h"
+#include "gm.h"
+#include "sk_tool_utils.h"
+#include "sk_tool_utils_flags.h"
+
+#include "DMCpuGMTask.h"
+#include "DMGpuGMTask.h"
+#include "DMGpuSupport.h"
+#include "DMImageTask.h"
+#include "DMJsonWriter.h"
+#include "DMPDFTask.h"
+#include "DMPDFRasterizeTask.h"
+#include "DMReporter.h"
+#include "DMSKPTask.h"
+#include "DMTask.h"
+#include "DMTaskRunner.h"
+#include "DMTestTask.h"
+
+#ifdef SK_BUILD_POPPLER
+# include "SkPDFRasterizer.h"
+# define RASTERIZE_PDF_PROC SkPopplerRasterizePDF
+#elif defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS)
+# include "SkCGUtils.h"
+# define RASTERIZE_PDF_PROC SkPDFDocumentToBitmap
+#else
+# define RASTERIZE_PDF_PROC NULL
+#endif
-DEFINE_bool(tests, true, "Run tests?");
-DEFINE_string(images, "resources", "Images to decode.");
-DEFINE_string(src, "gm skp image subset", "Source types to test.");
-DEFINE_bool(nameByHash, false,
- "If true, write to FLAGS_writePath[0]/<hash>.png instead of "
- "to FLAGS_writePath[0]/<config>/<sourceType>/<name>.png");
-DEFINE_bool2(pathOpsExtended, x, false, "Run extended pathOps tests.");
-DEFINE_string(matrix, "1 0 0 0 1 0 0 0 1",
- "Matrix to apply when using 'matrix' in config.");
+#include <ctype.h>
-__SK_FORCE_IMAGE_DECODER_LINKING;
-using namespace DM;
+using skiagm::GM;
+using skiagm::GMRegistry;
+using skiatest::Test;
+using skiatest::TestRegistry;
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+static const char kGpuAPINameGL[] = "gl";
+static const char kGpuAPINameGLES[] = "gles";
-static int gPending = 0, gFailures = 0;
+DEFINE_bool(gms, true, "Run GMs?");
+DEFINE_bool(tests, true, "Run tests?");
+DEFINE_bool(reportUsedChars, false, "Output test font construction data to be pasted into"
+ " create_test_font.cpp.");
+DEFINE_string(images, "resources", "Path to directory containing images to decode.");
+DEFINE_bool(rasterPDF, true, "Rasterize PDFs?");
-static void fail(ImplicitString err) {
- SkDebugf("\n\nERROR: %s\n\n", err.c_str());
- sk_atomic_inc(&gFailures);
-}
+__SK_FORCE_IMAGE_DECODER_LINKING;
-static void done(double ms, ImplicitString config, ImplicitString src, ImplicitString name) {
- SkDebugf("%s(%4dMB %5d) %s\t%s %s %s ", FLAGS_verbose ? "\n" : kSkOverwriteLine
- , sk_tools::getMaxResidentSetSizeMB()
- , sk_atomic_dec(&gPending)-1
- , HumanizeMs(ms).c_str()
- , config.c_str()
- , src.c_str()
- , name.c_str());
+static DM::RasterizePdfProc get_pdf_rasterizer_proc() {
+ return reinterpret_cast<DM::RasterizePdfProc>(
+ FLAGS_rasterPDF ? RASTERIZE_PDF_PROC : NULL);
}
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-template <typename T>
-struct Tagged : public SkAutoTDelete<T> { const char* tag; };
-
-static const bool kMemcpyOK = true;
-
-static SkTArray<Tagged<Src>, kMemcpyOK> gSrcs;
-static SkTArray<Tagged<Sink>, kMemcpyOK> gSinks;
-
-static void push_src(const char* tag, Src* s) {
- SkAutoTDelete<Src> src(s);
- if (FLAGS_src.contains(tag) &&
- !SkCommandLineFlags::ShouldSkip(FLAGS_match, src->name().c_str())) {
- Tagged<Src>& s = gSrcs.push_back();
- s.reset(src.detach());
- s.tag = tag;
+// "FooBar" -> "foobar". Obviously, ASCII only.
+static SkString lowercase(SkString s) {
+ for (size_t i = 0; i < s.size(); i++) {
+ s[i] = tolower(s[i]);
}
+ return s;
}
-static void gather_srcs() {
- for (const skiagm::GMRegistry* r = skiagm::GMRegistry::Head(); r; r = r->next()) {
- push_src("gm", new GMSrc(r->factory()));
- }
- if (!FLAGS_skps.isEmpty()) {
- SkOSFile::Iter it(FLAGS_skps[0], "skp");
- for (SkString file; it.next(&file); ) {
- push_src("skp", new SKPSrc(SkOSPath::Join(FLAGS_skps[0], file.c_str())));
- }
+static const GrContextFactory::GLContextType native = GrContextFactory::kNative_GLContextType;
+static const GrContextFactory::GLContextType nvpr = GrContextFactory::kNVPR_GLContextType;
+static const GrContextFactory::GLContextType null = GrContextFactory::kNull_GLContextType;
+static const GrContextFactory::GLContextType debug = GrContextFactory::kDebug_GLContextType;
+#if SK_ANGLE
+static const GrContextFactory::GLContextType angle = GrContextFactory::kANGLE_GLContextType;
+#endif
+#if SK_MESA
+static const GrContextFactory::GLContextType mesa = GrContextFactory::kMESA_GLContextType;
+#endif
+
+static void kick_off_gms(const SkTDArray<GMRegistry::Factory>& gms,
+ const SkTArray<SkString>& configs,
+ GrGLStandard gpuAPI,
+ DM::Reporter* reporter,
+ DM::TaskRunner* tasks) {
+#define START(name, type, ...) \
+ if (lowercase(configs[j]).equals(name)) { \
+ tasks->add(SkNEW_ARGS(DM::type, (name, reporter, tasks, gms[i], ## __VA_ARGS__))); \
}
- if (!FLAGS_images.isEmpty()) {
- const char* exts[] = {
- "bmp", "gif", "jpg", "jpeg", "png", "webp", "ktx", "astc", "wbmp", "ico",
- "BMP", "GIF", "JPG", "JPEG", "PNG", "WEBP", "KTX", "ASTC", "WBMP", "ICO",
- };
- for (size_t i = 0; i < SK_ARRAY_COUNT(exts); i++) {
- SkOSFile::Iter it(FLAGS_images[0], exts[i]);
- for (SkString file; it.next(&file); ) {
- SkString path = SkOSPath::Join(FLAGS_images[0], file.c_str());
- push_src("image", new ImageSrc(path)); // Decode entire image.
- push_src("subset", new ImageSrc(path, 5)); // Decode 5 random subsets.
- }
+ for (int i = 0; i < gms.count(); i++) {
+ for (int j = 0; j < configs.count(); j++) {
+
+ START("565", CpuGMTask, kRGB_565_SkColorType);
+ START("8888", CpuGMTask, kN32_SkColorType);
+ START("gpu", GpuGMTask, native, gpuAPI, 0, false);
+ START("msaa4", GpuGMTask, native, gpuAPI, 4, false);
+ START("msaa16", GpuGMTask, native, gpuAPI, 16, false);
+ START("nvprmsaa4", GpuGMTask, nvpr, gpuAPI, 4, false);
+ START("nvprmsaa16", GpuGMTask, nvpr, gpuAPI, 16, false);
+ START("gpudft", GpuGMTask, native, gpuAPI, 0, true);
+ START("gpunull", GpuGMTask, null, gpuAPI, 0, false);
+ START("gpudebug", GpuGMTask, debug, gpuAPI, 0, false);
+#if SK_ANGLE
+ START("angle", GpuGMTask, angle, gpuAPI, 0, false);
+#endif
+#if SK_MESA
+ START("mesa", GpuGMTask, mesa, gpuAPI, 0, false);
+#endif
+ START("pdf", PDFTask, get_pdf_rasterizer_proc());
}
}
+#undef START
}
-static GrGLStandard get_gpu_api() {
- if (FLAGS_gpuAPI.contains("gl")) { return kGL_GrGLStandard; }
- if (FLAGS_gpuAPI.contains("gles")) { return kGLES_GrGLStandard; }
- return kNone_GrGLStandard;
+static void kick_off_tests(const SkTDArray<TestRegistry::Factory>& tests,
+ DM::Reporter* reporter,
+ DM::TaskRunner* tasks) {
+ for (int i = 0; i < tests.count(); i++) {
+ SkAutoTDelete<Test> test(tests[i](NULL));
+ if (test->isGPUTest()) {
+ tasks->add(SkNEW_ARGS(DM::GpuTestTask, (reporter, tasks, tests[i])));
+ } else {
+ tasks->add(SkNEW_ARGS(DM::CpuTestTask, (reporter, tasks, tests[i])));
+ }
+ }
}
-static void push_sink(const char* tag, Sink* s) {
- SkAutoTDelete<Sink> sink(s);
- if (!FLAGS_config.contains(tag)) {
- return;
- }
- // Try a noop Src as a canary. If it fails, skip this sink.
- struct : public Src {
- Error draw(SkCanvas*) const SK_OVERRIDE { return ""; }
- SkISize size() const SK_OVERRIDE { return SkISize::Make(16, 16); }
- Name name() const SK_OVERRIDE { return "noop"; }
- } noop;
-
- SkBitmap bitmap;
- SkDynamicMemoryWStream stream;
- Error err = sink->draw(noop, &bitmap, &stream);
- if (!err.isEmpty()) {
- SkDebugf("Skipping %s: %s\n", tag, err.c_str());
+static void find_files(const char* dir,
+ const char* suffixes[],
+ size_t num_suffixes,
+ SkTArray<SkString>* files) {
+ if (0 == strcmp(dir, "")) {
return;
}
- Tagged<Sink>& ts = gSinks.push_back();
- ts.reset(sink.detach());
- ts.tag = tag;
+ SkString filename;
+ for (size_t i = 0; i < num_suffixes; i++) {
+ SkOSFile::Iter it(dir, suffixes[i]);
+ while (it.next(&filename)) {
+ if (!SkCommandLineFlags::ShouldSkip(FLAGS_match, filename.c_str())) {
+ files->push_back(SkOSPath::Join(dir, filename.c_str()));
+ }
+ }
+ }
}
-static bool gpu_supported() {
-#if SK_SUPPORT_GPU
- return FLAGS_gpu;
-#else
- return false;
-#endif
-}
+static void kick_off_skps(const SkTArray<SkString>& skps,
+ DM::Reporter* reporter,
+ DM::TaskRunner* tasks) {
+ for (int i = 0; i < skps.count(); ++i) {
+ SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(skps[i].c_str()));
+ if (stream.get() == NULL) {
+ SkDebugf("Could not read %s.\n", skps[i].c_str());
+ exit(1);
+ }
+ SkAutoTUnref<SkPicture> pic(
+ SkPicture::CreateFromStream(stream.get(), &sk_tools::LazyDecodeBitmap));
+ if (pic.get() == NULL) {
+ SkDebugf("Could not read %s as an SkPicture.\n", skps[i].c_str());
+ exit(1);
+ }
-static Sink* create_sink(const char* tag) {
-#define SINK(t, sink, ...) if (0 == strcmp(t, tag)) { return new sink(__VA_ARGS__); }
- if (gpu_supported()) {
- const GrGLStandard api = get_gpu_api();
- SINK("gpunull", GPUSink, GrContextFactory::kNull_GLContextType, api, 0, false);
- SINK("gpudebug", GPUSink, GrContextFactory::kDebug_GLContextType, api, 0, false);
- SINK("gpu", GPUSink, GrContextFactory::kNative_GLContextType, api, 0, false);
- SINK("gpudft", GPUSink, GrContextFactory::kNative_GLContextType, api, 0, true);
- SINK("msaa4", GPUSink, GrContextFactory::kNative_GLContextType, api, 4, false);
- SINK("msaa16", GPUSink, GrContextFactory::kNative_GLContextType, api, 16, false);
- SINK("nvprmsaa4", GPUSink, GrContextFactory::kNVPR_GLContextType, api, 4, false);
- SINK("nvprmsaa16", GPUSink, GrContextFactory::kNVPR_GLContextType, api, 16, false);
- #if SK_ANGLE
- SINK("angle", GPUSink, GrContextFactory::kANGLE_GLContextType, api, 0, false);
- #endif
- #if SK_MESA
- SINK("mesa", GPUSink, GrContextFactory::kMESA_GLContextType, api, 0, false);
- #endif
+ SkString filename = SkOSPath::Basename(skps[i].c_str());
+ tasks->add(SkNEW_ARGS(DM::SKPTask, (reporter, tasks, pic, filename)));
+ tasks->add(SkNEW_ARGS(DM::PDFTask, (reporter, tasks, pic, filename,
+ get_pdf_rasterizer_proc())));
}
+}
- if (FLAGS_cpu) {
- SINK("565", RasterSink, kRGB_565_SkColorType);
- SINK("8888", RasterSink, kN32_SkColorType);
- // TODO(mtklein): reenable once skiagold can handle .pdf uploads.
- //SINK("pdf", PDFSink);
+static void kick_off_images(const SkTArray<SkString>& images,
+ DM::Reporter* reporter,
+ DM::TaskRunner* tasks) {
+ for (int i = 0; i < images.count(); i++) {
+ SkAutoTUnref<SkData> image(SkData::NewFromFileName(images[i].c_str()));
+ if (!image) {
+ SkDebugf("Could not read %s.\n", images[i].c_str());
+ exit(1);
+ }
+ SkString filename = SkOSPath::Basename(images[i].c_str());
+ tasks->add(SkNEW_ARGS(DM::ImageTask, (reporter, tasks, image, filename)));
+ tasks->add(SkNEW_ARGS(DM::ImageTask, (reporter, tasks, image, filename, 5/*subsets*/)));
}
-#undef SINK
- return NULL;
}
-static Sink* create_via(const char* tag, Sink* wrapped) {
-#define VIA(t, via, ...) if (0 == strcmp(t, tag)) { return new via(__VA_ARGS__); }
- VIA("serialize", ViaSerialization, wrapped);
-
- VIA("tiles", ViaTiles, 256, 256, NULL, wrapped);
- VIA("tiles_rt", ViaTiles, 256, 256, new SkRTreeFactory, wrapped);
- const int xp = SkGPipeWriter::kCrossProcess_Flag,
- sa = xp | SkGPipeWriter::kSharedAddressSpace_Flag;
- VIA("pipe", ViaPipe, 0, wrapped);
- VIA("pipe_xp", ViaPipe, xp, wrapped);
- VIA("pipe_sa", ViaPipe, sa, wrapped);
+static void report_failures(const SkTArray<SkString>& failures) {
+ if (failures.count() == 0) {
+ return;
+ }
- if (FLAGS_matrix.count() == 9) {
- SkMatrix m;
- for (int i = 0; i < 9; i++) {
- m[i] = (SkScalar)atof(FLAGS_matrix[i]);
- }
- VIA("matrix", ViaMatrix, m, wrapped);
+ SkDebugf("Failures:\n");
+ for (int i = 0; i < failures.count(); i++) {
+ SkDebugf(" %s\n", failures[i].c_str());
}
-#undef VIA
- return NULL;
+ SkDebugf("%d failures.\n", failures.count());
}
-static void gather_sinks() {
- for (int i = 0; i < FLAGS_config.count(); i++) {
- const char* config = FLAGS_config[i];
- SkTArray<SkString> parts;
- SkStrSplit(config, "-", &parts);
-
- Sink* sink = NULL;
- for (int i = parts.count(); i-- > 0;) {
- const char* part = parts[i].c_str();
- Sink* next = (sink == NULL) ? create_sink(part) : create_via(part, sink);
- if (next == NULL) {
- SkDebugf("Skipping %s: Don't understand '%s'.\n", config, part);
- delete sink;
- sink = NULL;
- break;
- }
- sink = next;
- }
- if (sink) {
- push_sink(config, sink);
- }
- }
+static GrGLStandard get_gl_standard() {
+ if (FLAGS_gpuAPI.contains(kGpuAPINameGL)) {
+ return kGL_GrGLStandard;
+ }
+ if (FLAGS_gpuAPI.contains(kGpuAPINameGLES)) {
+ return kGLES_GrGLStandard;
+ }
+ return kNone_GrGLStandard;
}
-// The finest-grained unit of work we can run: draw a single Src into a single Sink,
-// report any errors, and perhaps write out the output: a .png of the bitmap, or a raw stream.
-struct Task {
- Task(const Tagged<Src>& src, const Tagged<Sink>& sink) : src(src), sink(sink) {}
- const Tagged<Src>& src;
- const Tagged<Sink>& sink;
-
- static void Run(Task* task) {
- WallTimer timer;
- timer.start();
- if (!FLAGS_dryRun) {
- SkBitmap bitmap;
- SkDynamicMemoryWStream stream;
- Error err = task->sink->draw(*task->src, &bitmap, &stream);
- if (!err.isEmpty()) {
- fail(SkStringPrintf("%s %s %s: %s",
- task->sink.tag,
- task->src.tag,
- task->src->name().c_str(),
- err.c_str()));
- }
- if (!FLAGS_writePath.isEmpty()) {
- const char* ext = task->sink->fileExtension();
- if (stream.bytesWritten() == 0) {
- SkMemoryStream pixels(bitmap.getPixels(), bitmap.getSize());
- WriteToDisk(*task, &pixels, bitmap.getSize(), &bitmap, ext);
- } else {
- SkAutoTDelete<SkStreamAsset> data(stream.detachAsStream());
- WriteToDisk(*task, data, data->getLength(), NULL, ext);
- }
- }
+template <typename T, typename Registry>
+static void append_matching_factories(Registry* head, SkTDArray<typename Registry::Factory>* out) {
+ for (const Registry* reg = head; reg != NULL; reg = reg->next()) {
+ SkAutoTDelete<T> forName(reg->factory()(NULL));
+ if (!SkCommandLineFlags::ShouldSkip(FLAGS_match, forName->getName())) {
+ *out->append() = reg->factory();
}
- timer.end();
- done(timer.fWall, task->sink.tag, task->src.tag, task->src->name());
}
+}
- static void WriteToDisk(const Task& task,
- SkStream* data, size_t len,
- const SkBitmap* bitmap,
- const char* ext) {
- SkMD5 hash;
- hash.writeStream(data, len);
- SkMD5::Digest digest;
- hash.finish(digest);
-
- JsonWriter::BitmapResult result;
- result.name = task.src->name();
- result.config = task.sink.tag;
- result.sourceType = task.src.tag;
- result.ext = ext;
- for (int i = 0; i < 16; i++) {
- result.md5.appendf("%02x", digest.data[i]);
- }
- JsonWriter::AddBitmapResult(result);
-
- const char* dir = FLAGS_writePath[0];
- if (0 == strcmp(dir, "@")) { // Needed for iOS.
- dir = FLAGS_resourcePath[0];
- }
- sk_mkdir(dir);
-
- SkString path;
- if (FLAGS_nameByHash) {
- path = SkOSPath::Join(dir, result.md5.c_str());
- path.append(".");
- path.append(ext);
- if (sk_exists(path.c_str())) {
- return; // Content-addressed. If it exists already, we're done.
- }
- } else {
- path = SkOSPath::Join(dir, task.sink.tag);
- sk_mkdir(path.c_str());
- path = SkOSPath::Join(path.c_str(), task.src.tag);
- sk_mkdir(path.c_str());
- path = SkOSPath::Join(path.c_str(), task.src->name().c_str());
- path.append(".");
- path.append(ext);
- }
-
- SkFILEWStream file(path.c_str());
- if (!file.isValid()) {
- fail(SkStringPrintf("Can't open %s for writing.\n", path.c_str()));
- return;
- }
+int dm_main();
+int dm_main() {
+ SetupCrashHandler();
+ SkAutoGraphics ag;
+ SkTaskGroup::Enabler enabled(FLAGS_threads);
- data->rewind();
- if (bitmap) {
- // We can't encode A8 bitmaps as PNGs. Convert them to 8888 first.
- SkBitmap converted;
- if (bitmap->info().colorType() == kAlpha_8_SkColorType) {
- if (!bitmap->copyTo(&converted, kN32_SkColorType)) {
- fail("Can't convert A8 to 8888.\n");
- return;
- }
- bitmap = &converted;
- }
- if (!SkImageEncoder::EncodeStream(&file, *bitmap, SkImageEncoder::kPNG_Type, 100)) {
- fail(SkStringPrintf("Can't encode PNG to %s.\n", path.c_str()));
- return;
- }
- } else {
- if (!file.writeStream(data, len)) {
- fail(SkStringPrintf("Can't write to %s.\n", path.c_str()));
- return;
- }
- }
+ if (FLAGS_dryRun || FLAGS_veryVerbose) {
+ FLAGS_verbose = true;
}
-};
+#if SK_ENABLE_INST_COUNT
+ gPrintInstCount = FLAGS_leaks;
+#endif
-// Run all tasks in the same enclave serially on the same thread.
-// They can't possibly run concurrently with each other.
-static void run_enclave(SkTArray<Task>* tasks) {
- for (int i = 0; i < tasks->count(); i++) {
- Task::Run(tasks->begin() + i);
+ SkTArray<SkString> configs;
+ for (int i = 0; i < FLAGS_config.count(); i++) {
+ SkStrSplit(FLAGS_config[i], ", ", &configs);
}
-}
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+ GrGLStandard gpuAPI = get_gl_standard();
-// Unit tests don't fit so well into the Src/Sink model, so we give them special treatment.
+ SkTDArray<GMRegistry::Factory> gms;
+ if (FLAGS_gms) {
+ append_matching_factories<GM>(GMRegistry::Head(), &gms);
+ }
-static struct : public skiatest::Reporter {
- void onReportFailed(const skiatest::Failure& failure) SK_OVERRIDE {
- SkString s;
- failure.getFailureString(&s);
- fail(s);
- JsonWriter::AddTestFailure(failure);
+ SkTDArray<TestRegistry::Factory> tests;
+ if (FLAGS_tests) {
+ append_matching_factories<Test>(TestRegistry::Head(), &tests);
}
- bool allowExtendedTest() const SK_OVERRIDE { return FLAGS_pathOpsExtended; }
- bool verbose() const SK_OVERRIDE { return FLAGS_veryVerbose; }
-} gTestReporter;
-static SkTArray<SkAutoTDelete<skiatest::Test>, kMemcpyOK> gTests;
-static void gather_tests() {
- if (!FLAGS_tests) {
- return;
- }
- for (const skiatest::TestRegistry* r = skiatest::TestRegistry::Head(); r; r = r->next()) {
- SkAutoTDelete<skiatest::Test> test(r->factory()(NULL));
- if (SkCommandLineFlags::ShouldSkip(FLAGS_match, test->getName())) {
- continue;
- }
- if (test->isGPUTest() && !gpu_supported()) {
- continue;
- }
- if (!test->isGPUTest() && !FLAGS_cpu) {
- continue;
- }
- test->setReporter(&gTestReporter);
- gTests.push_back().reset(test.detach());
+ SkTArray<SkString> skps;
+ if (!FLAGS_skps.isEmpty()) {
+ const char* suffixes[] = { "skp" };
+ find_files(FLAGS_skps[0], suffixes, SK_ARRAY_COUNT(suffixes), &skps);
}
-}
-static void run_test(SkAutoTDelete<skiatest::Test>* t) {
- WallTimer timer;
- timer.start();
- skiatest::Test* test = t->get();
- if (!FLAGS_dryRun) {
- GrContextFactory grFactory;
- test->setGrContextFactory(&grFactory);
- test->run();
- if (!test->passed()) {
- fail(SkStringPrintf("test %s failed", test->getName()));
- }
+ SkTArray<SkString> images;
+ if (!FLAGS_images.isEmpty()) {
+ const char* suffixes[] = {
+ "bmp", "gif", "jpg", "jpeg", "png", "webp", "ktx", "astc", "wbmp", "ico",
+ "BMP", "GIF", "JPG", "JPEG", "PNG", "WEBP", "KTX", "ASTC", "WBMP", "ICO",
+ };
+ find_files(FLAGS_images[0], suffixes, SK_ARRAY_COUNT(suffixes), &images);
}
- timer.end();
- done(timer.fWall, "test", "", test->getName());
-}
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-int dm_main();
-int dm_main() {
- SetupCrashHandler();
- SkAutoGraphics ag;
- SkTaskGroup::Enabler enabled(FLAGS_threads);
+ SkDebugf("%d GMs x %d configs, %d tests, %d pictures, %d images\n",
+ gms.count(), configs.count(), tests.count(), skps.count(), images.count());
+ DM::Reporter reporter;
- gather_srcs();
- gather_sinks();
- gather_tests();
-
- gPending = gSrcs.count() * gSinks.count() + gTests.count();
- SkDebugf("%d srcs * %d sinks + %d tests == %d tasks\n",
- gSrcs.count(), gSinks.count(), gTests.count(), gPending);
-
- // We try to exploit as much parallelism as is safe. Most Src/Sink pairs run on any thread,
- // but Sinks that identify as part of a particular enclave run serially on a single thread.
- // Tests run on any thread, with a separate GrContextFactory for each GPU test.
- SkTArray<Task> enclaves[kNumEnclaves];
- for (int j = 0; j < gSinks.count(); j++) {
- SkTArray<Task>& tasks = enclaves[gSinks[j]->enclave()];
- for (int i = 0; i < gSrcs.count(); i++) {
- tasks.push_back(Task(gSrcs[i], gSinks[j]));
- }
- }
+ DM::TaskRunner tasks;
+ kick_off_tests(tests, &reporter, &tasks);
+ kick_off_gms(gms, configs, gpuAPI, &reporter, &tasks);
+ kick_off_skps(skps, &reporter, &tasks);
+ kick_off_images(images, &reporter, &tasks);
+ tasks.wait();
- SK_COMPILE_ASSERT(kAnyThread_Enclave == 0, AnyThreadZero);
- SkTaskGroup tg;
- tg.batch( Task::Run, enclaves[0].begin(), enclaves[0].count());
- tg.batch(run_enclave, enclaves+1, kNumEnclaves-1);
- tg.batch( run_test, gTests.begin(), gTests.count());
- tg.wait();
+ DM::JsonWriter::DumpJson();
- if (!FLAGS_verbose) {
- SkDebugf("\n");
+ SkDebugf("\n");
+#ifdef SK_DEBUG
+ if (FLAGS_portableFonts && FLAGS_reportUsedChars) {
+ sk_tool_utils::report_used_chars();
}
+#endif
- JsonWriter::DumpJson();
- return gPending == 0 && gFailures == 0 ? 0 : 1;
+ SkTArray<SkString> failures;
+ reporter.getFailures(&failures);
+ report_failures(failures);
+ return failures.count() > 0;
}
#if !defined(SK_BUILD_FOR_IOS) && !defined(SK_BUILD_FOR_NACL)