blob: 7113ad839a02e4e61cc028adf608c389e389edea [file] [log] [blame]
mtklein114c3cd2015-01-15 10:15:02 -08001// Main binary for DM.
2// For a high-level overview, please see dm/README.
3
jcgregorio3b27ade2014-11-13 08:06:40 -08004#include "CrashHandler.h"
mtklein114c3cd2015-01-15 10:15:02 -08005#include "LazyDecodeBitmap.h"
caryclark17f0b6d2014-07-22 10:15:34 -07006#include "SkCommonFlags.h"
mtklein@google.comd36522d2013-10-16 13:02:15 +00007#include "SkForceLinking.h"
8#include "SkGraphics.h"
mtklein1d0f1642014-09-08 08:05:18 -07009#include "SkOSFile.h"
mtklein114c3cd2015-01-15 10:15:02 -080010#include "SkPicture.h"
11#include "SkString.h"
mtklein406654b2014-09-03 15:34:37 -070012#include "SkTaskGroup.h"
commit-bot@chromium.org0dc5bd12014-02-26 16:31:22 +000013#include "Test.h"
mtklein114c3cd2015-01-15 10:15:02 -080014#include "gm.h"
15#include "sk_tool_utils.h"
16#include "sk_tool_utils_flags.h"
mtklein@google.comd36522d2013-10-16 13:02:15 +000017
mtklein114c3cd2015-01-15 10:15:02 -080018#include "DMCpuGMTask.h"
19#include "DMGpuGMTask.h"
20#include "DMGpuSupport.h"
21#include "DMImageTask.h"
22#include "DMJsonWriter.h"
23#include "DMPDFTask.h"
24#include "DMPDFRasterizeTask.h"
25#include "DMReporter.h"
26#include "DMSKPTask.h"
27#include "DMTask.h"
28#include "DMTaskRunner.h"
29#include "DMTestTask.h"
30
31#ifdef SK_BUILD_POPPLER
32# include "SkPDFRasterizer.h"
33# define RASTERIZE_PDF_PROC SkPopplerRasterizePDF
34#elif defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS)
35# include "SkCGUtils.h"
36# define RASTERIZE_PDF_PROC SkPDFDocumentToBitmap
37#else
38# define RASTERIZE_PDF_PROC NULL
39#endif
40
41#include <ctype.h>
42
43using skiagm::GM;
44using skiagm::GMRegistry;
45using skiatest::Test;
46using skiatest::TestRegistry;
47
48static const char kGpuAPINameGL[] = "gl";
49static const char kGpuAPINameGLES[] = "gles";
50
51DEFINE_bool(gms, true, "Run GMs?");
commit-bot@chromium.org0dc5bd12014-02-26 16:31:22 +000052DEFINE_bool(tests, true, "Run tests?");
mtklein114c3cd2015-01-15 10:15:02 -080053DEFINE_bool(reportUsedChars, false, "Output test font construction data to be pasted into"
54 " create_test_font.cpp.");
55DEFINE_string(images, "resources", "Path to directory containing images to decode.");
56DEFINE_bool(rasterPDF, true, "Rasterize PDFs?");
mtklein@google.comd36522d2013-10-16 13:02:15 +000057
58__SK_FORCE_IMAGE_DECODER_LINKING;
59
mtklein114c3cd2015-01-15 10:15:02 -080060static DM::RasterizePdfProc get_pdf_rasterizer_proc() {
61 return reinterpret_cast<DM::RasterizePdfProc>(
62 FLAGS_rasterPDF ? RASTERIZE_PDF_PROC : NULL);
halcanary9e398f72015-01-10 11:18:04 -080063}
64
mtklein114c3cd2015-01-15 10:15:02 -080065// "FooBar" -> "foobar". Obviously, ASCII only.
66static SkString lowercase(SkString s) {
67 for (size_t i = 0; i < s.size(); i++) {
68 s[i] = tolower(s[i]);
69 }
70 return s;
mtklein@google.comd36522d2013-10-16 13:02:15 +000071}
72
mtklein114c3cd2015-01-15 10:15:02 -080073static const GrContextFactory::GLContextType native = GrContextFactory::kNative_GLContextType;
74static const GrContextFactory::GLContextType nvpr = GrContextFactory::kNVPR_GLContextType;
75static const GrContextFactory::GLContextType null = GrContextFactory::kNull_GLContextType;
76static const GrContextFactory::GLContextType debug = GrContextFactory::kDebug_GLContextType;
77#if SK_ANGLE
78static const GrContextFactory::GLContextType angle = GrContextFactory::kANGLE_GLContextType;
mtklein709d2c32015-01-15 08:30:25 -080079#endif
mtklein114c3cd2015-01-15 10:15:02 -080080#if SK_MESA
81static const GrContextFactory::GLContextType mesa = GrContextFactory::kMESA_GLContextType;
82#endif
83
84static void kick_off_gms(const SkTDArray<GMRegistry::Factory>& gms,
85 const SkTArray<SkString>& configs,
86 GrGLStandard gpuAPI,
87 DM::Reporter* reporter,
88 DM::TaskRunner* tasks) {
89#define START(name, type, ...) \
90 if (lowercase(configs[j]).equals(name)) { \
91 tasks->add(SkNEW_ARGS(DM::type, (name, reporter, tasks, gms[i], ## __VA_ARGS__))); \
92 }
93 for (int i = 0; i < gms.count(); i++) {
94 for (int j = 0; j < configs.count(); j++) {
95
96 START("565", CpuGMTask, kRGB_565_SkColorType);
97 START("8888", CpuGMTask, kN32_SkColorType);
98 START("gpu", GpuGMTask, native, gpuAPI, 0, false);
99 START("msaa4", GpuGMTask, native, gpuAPI, 4, false);
100 START("msaa16", GpuGMTask, native, gpuAPI, 16, false);
101 START("nvprmsaa4", GpuGMTask, nvpr, gpuAPI, 4, false);
102 START("nvprmsaa16", GpuGMTask, nvpr, gpuAPI, 16, false);
103 START("gpudft", GpuGMTask, native, gpuAPI, 0, true);
104 START("gpunull", GpuGMTask, null, gpuAPI, 0, false);
105 START("gpudebug", GpuGMTask, debug, gpuAPI, 0, false);
106#if SK_ANGLE
107 START("angle", GpuGMTask, angle, gpuAPI, 0, false);
108#endif
109#if SK_MESA
110 START("mesa", GpuGMTask, mesa, gpuAPI, 0, false);
111#endif
112 START("pdf", PDFTask, get_pdf_rasterizer_proc());
113 }
114 }
115#undef START
mtklein709d2c32015-01-15 08:30:25 -0800116}
117
mtklein114c3cd2015-01-15 10:15:02 -0800118static void kick_off_tests(const SkTDArray<TestRegistry::Factory>& tests,
119 DM::Reporter* reporter,
120 DM::TaskRunner* tasks) {
121 for (int i = 0; i < tests.count(); i++) {
122 SkAutoTDelete<Test> test(tests[i](NULL));
123 if (test->isGPUTest()) {
124 tasks->add(SkNEW_ARGS(DM::GpuTestTask, (reporter, tasks, tests[i])));
mtklein709d2c32015-01-15 08:30:25 -0800125 } else {
mtklein114c3cd2015-01-15 10:15:02 -0800126 tasks->add(SkNEW_ARGS(DM::CpuTestTask, (reporter, tasks, tests[i])));
mtklein709d2c32015-01-15 08:30:25 -0800127 }
mtklein709d2c32015-01-15 08:30:25 -0800128 }
129}
130
mtklein114c3cd2015-01-15 10:15:02 -0800131static void find_files(const char* dir,
132 const char* suffixes[],
133 size_t num_suffixes,
134 SkTArray<SkString>* files) {
135 if (0 == strcmp(dir, "")) {
mtklein709d2c32015-01-15 08:30:25 -0800136 return;
137 }
mtklein114c3cd2015-01-15 10:15:02 -0800138
139 SkString filename;
140 for (size_t i = 0; i < num_suffixes; i++) {
141 SkOSFile::Iter it(dir, suffixes[i]);
142 while (it.next(&filename)) {
143 if (!SkCommandLineFlags::ShouldSkip(FLAGS_match, filename.c_str())) {
144 files->push_back(SkOSPath::Join(dir, filename.c_str()));
145 }
mtklein709d2c32015-01-15 08:30:25 -0800146 }
mtklein709d2c32015-01-15 08:30:25 -0800147 }
148}
149
mtklein114c3cd2015-01-15 10:15:02 -0800150static void kick_off_skps(const SkTArray<SkString>& skps,
151 DM::Reporter* reporter,
152 DM::TaskRunner* tasks) {
153 for (int i = 0; i < skps.count(); ++i) {
154 SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(skps[i].c_str()));
155 if (stream.get() == NULL) {
156 SkDebugf("Could not read %s.\n", skps[i].c_str());
157 exit(1);
mtklein709d2c32015-01-15 08:30:25 -0800158 }
mtklein114c3cd2015-01-15 10:15:02 -0800159 SkAutoTUnref<SkPicture> pic(
160 SkPicture::CreateFromStream(stream.get(), &sk_tools::LazyDecodeBitmap));
161 if (pic.get() == NULL) {
162 SkDebugf("Could not read %s as an SkPicture.\n", skps[i].c_str());
163 exit(1);
164 }
165
166 SkString filename = SkOSPath::Basename(skps[i].c_str());
167 tasks->add(SkNEW_ARGS(DM::SKPTask, (reporter, tasks, pic, filename)));
168 tasks->add(SkNEW_ARGS(DM::PDFTask, (reporter, tasks, pic, filename,
169 get_pdf_rasterizer_proc())));
mtklein709d2c32015-01-15 08:30:25 -0800170 }
mtklein709d2c32015-01-15 08:30:25 -0800171}
172
mtklein114c3cd2015-01-15 10:15:02 -0800173static void kick_off_images(const SkTArray<SkString>& images,
174 DM::Reporter* reporter,
175 DM::TaskRunner* tasks) {
176 for (int i = 0; i < images.count(); i++) {
177 SkAutoTUnref<SkData> image(SkData::NewFromFileName(images[i].c_str()));
178 if (!image) {
179 SkDebugf("Could not read %s.\n", images[i].c_str());
180 exit(1);
181 }
182 SkString filename = SkOSPath::Basename(images[i].c_str());
183 tasks->add(SkNEW_ARGS(DM::ImageTask, (reporter, tasks, image, filename)));
184 tasks->add(SkNEW_ARGS(DM::ImageTask, (reporter, tasks, image, filename, 5/*subsets*/)));
185 }
186}
187
188
189static void report_failures(const SkTArray<SkString>& failures) {
190 if (failures.count() == 0) {
191 return;
192 }
193
194 SkDebugf("Failures:\n");
195 for (int i = 0; i < failures.count(); i++) {
196 SkDebugf(" %s\n", failures[i].c_str());
197 }
198 SkDebugf("%d failures.\n", failures.count());
199}
200
201static GrGLStandard get_gl_standard() {
202 if (FLAGS_gpuAPI.contains(kGpuAPINameGL)) {
203 return kGL_GrGLStandard;
204 }
205 if (FLAGS_gpuAPI.contains(kGpuAPINameGLES)) {
206 return kGLES_GrGLStandard;
207 }
208 return kNone_GrGLStandard;
209}
210
211template <typename T, typename Registry>
212static void append_matching_factories(Registry* head, SkTDArray<typename Registry::Factory>* out) {
213 for (const Registry* reg = head; reg != NULL; reg = reg->next()) {
214 SkAutoTDelete<T> forName(reg->factory()(NULL));
215 if (!SkCommandLineFlags::ShouldSkip(FLAGS_match, forName->getName())) {
216 *out->append() = reg->factory();
217 }
218 }
219}
mtklein709d2c32015-01-15 08:30:25 -0800220
jcgregorio3b27ade2014-11-13 08:06:40 -0800221int dm_main();
caryclark17f0b6d2014-07-22 10:15:34 -0700222int dm_main() {
jcgregorio3b27ade2014-11-13 08:06:40 -0800223 SetupCrashHandler();
commit-bot@chromium.org39e8d932014-05-29 20:14:48 +0000224 SkAutoGraphics ag;
mtklein406654b2014-09-03 15:34:37 -0700225 SkTaskGroup::Enabler enabled(FLAGS_threads);
commit-bot@chromium.orga65e2fd2014-05-30 17:23:31 +0000226
mtklein114c3cd2015-01-15 10:15:02 -0800227 if (FLAGS_dryRun || FLAGS_veryVerbose) {
228 FLAGS_verbose = true;
229 }
230#if SK_ENABLE_INST_COUNT
231 gPrintInstCount = FLAGS_leaks;
232#endif
commit-bot@chromium.org0dc5bd12014-02-26 16:31:22 +0000233
mtklein114c3cd2015-01-15 10:15:02 -0800234 SkTArray<SkString> configs;
235 for (int i = 0; i < FLAGS_config.count(); i++) {
236 SkStrSplit(FLAGS_config[i], ", ", &configs);
commit-bot@chromium.org38aeb0f2014-02-26 23:01:57 +0000237 }
238
mtklein114c3cd2015-01-15 10:15:02 -0800239 GrGLStandard gpuAPI = get_gl_standard();
kkinnunen80549fc2014-06-30 06:36:31 -0700240
mtklein114c3cd2015-01-15 10:15:02 -0800241 SkTDArray<GMRegistry::Factory> gms;
242 if (FLAGS_gms) {
243 append_matching_factories<GM>(GMRegistry::Head(), &gms);
mtklein@google.comd36522d2013-10-16 13:02:15 +0000244 }
245
mtklein114c3cd2015-01-15 10:15:02 -0800246 SkTDArray<TestRegistry::Factory> tests;
247 if (FLAGS_tests) {
248 append_matching_factories<Test>(TestRegistry::Head(), &tests);
249 }
250
251
252 SkTArray<SkString> skps;
253 if (!FLAGS_skps.isEmpty()) {
254 const char* suffixes[] = { "skp" };
255 find_files(FLAGS_skps[0], suffixes, SK_ARRAY_COUNT(suffixes), &skps);
256 }
257
258 SkTArray<SkString> images;
259 if (!FLAGS_images.isEmpty()) {
260 const char* suffixes[] = {
261 "bmp", "gif", "jpg", "jpeg", "png", "webp", "ktx", "astc", "wbmp", "ico",
262 "BMP", "GIF", "JPG", "JPEG", "PNG", "WEBP", "KTX", "ASTC", "WBMP", "ICO",
263 };
264 find_files(FLAGS_images[0], suffixes, SK_ARRAY_COUNT(suffixes), &images);
265 }
266
267 SkDebugf("%d GMs x %d configs, %d tests, %d pictures, %d images\n",
268 gms.count(), configs.count(), tests.count(), skps.count(), images.count());
269 DM::Reporter reporter;
270
271 DM::TaskRunner tasks;
272 kick_off_tests(tests, &reporter, &tasks);
273 kick_off_gms(gms, configs, gpuAPI, &reporter, &tasks);
274 kick_off_skps(skps, &reporter, &tasks);
275 kick_off_images(images, &reporter, &tasks);
276 tasks.wait();
277
278 DM::JsonWriter::DumpJson();
279
280 SkDebugf("\n");
281#ifdef SK_DEBUG
282 if (FLAGS_portableFonts && FLAGS_reportUsedChars) {
283 sk_tool_utils::report_used_chars();
284 }
285#endif
286
287 SkTArray<SkString> failures;
288 reporter.getFailures(&failures);
289 report_failures(failures);
290 return failures.count() > 0;
mtklein@google.comd36522d2013-10-16 13:02:15 +0000291}
jcgregorio3b27ade2014-11-13 08:06:40 -0800292
293#if !defined(SK_BUILD_FOR_IOS) && !defined(SK_BUILD_FOR_NACL)
294int main(int argc, char** argv) {
295 SkCommandLineFlags::Parse(argc, argv);
296 return dm_main();
297}
298#endif