Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(32)

Side by Side Diff: dm/DM.cpp

Issue 788243008: Sketch DM refactor. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: better failure messages, disable a few things temporarily to try to go green Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « bench/nanobench.cpp ('k') | dm/DMCpuGMTask.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Main binary for DM.
2 // For a high-level overview, please see dm/README.
3
4 #include "CrashHandler.h" 1 #include "CrashHandler.h"
5 #include "LazyDecodeBitmap.h" 2 #include "DMJsonWriter.h"
3 #include "DMSrcSink.h"
4 #include "OverwriteLine.h"
5 #include "ProcStats.h"
6 #include "SkBBHFactory.h"
6 #include "SkCommonFlags.h" 7 #include "SkCommonFlags.h"
7 #include "SkForceLinking.h" 8 #include "SkForceLinking.h"
8 #include "SkGraphics.h" 9 #include "SkGraphics.h"
10 #include "SkMD5.h"
9 #include "SkOSFile.h" 11 #include "SkOSFile.h"
10 #include "SkPicture.h"
11 #include "SkString.h"
12 #include "SkTaskGroup.h" 12 #include "SkTaskGroup.h"
13 #include "Test.h" 13 #include "Test.h"
14 #include "gm.h" 14 #include "Timer.h"
15 #include "sk_tool_utils.h" 15
16 #include "sk_tool_utils_flags.h" 16 DEFINE_bool(tests, true, "Run tests?");
17 17 DEFINE_string(images, "resources", "Images to decode.");
18 #include "DMCpuGMTask.h" 18 //DEFINE_string(src, "gm skp image subset", "Source types to test.");
19 #include "DMGpuGMTask.h" 19 DEFINE_string(src, "gm skp", "Source types to test. TEMPORARILY DISABLED");
20 #include "DMGpuSupport.h" 20 DEFINE_bool(nameByHash, false,
21 #include "DMImageTask.h" 21 "If true, write to FLAGS_writePath[0]/<hash>.png instead of "
22 #include "DMJsonWriter.h" 22 "to FLAGS_writePath[0]/<config>/<sourceType>/<name>.png");
23 #include "DMPDFTask.h" 23 DEFINE_bool2(pathOpsExtended, x, false, "Run extended pathOps tests.");
24 #include "DMPDFRasterizeTask.h" 24 DEFINE_string(matrix, "1 0 0 0 1 0 0 0 1",
25 #include "DMReporter.h" 25 "Matrix to apply when using 'matrix' in config.");
26 #include "DMSKPTask.h" 26
27 #include "DMTask.h" 27 __SK_FORCE_IMAGE_DECODER_LINKING;
28 #include "DMTaskRunner.h" 28 using namespace DM;
29 #include "DMTestTask.h" 29
30 30 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~*/
31 #ifdef SK_BUILD_POPPLER 31
32 # include "SkPDFRasterizer.h" 32 SK_DECLARE_STATIC_MUTEX(gFailuresMutex);
33 # define RASTERIZE_PDF_PROC SkPopplerRasterizePDF 33 static SkTArray<SkString> gFailures;
34 #elif defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS) 34
35 # include "SkCGUtils.h" 35 static void fail(ImplicitString err) {
36 # define RASTERIZE_PDF_PROC SkPDFDocumentToBitmap 36 SkAutoMutexAcquire lock(gFailuresMutex);
37 SkDebugf("\n\nFAILURE: %s\n\n", err.c_str());
38 gFailures.push_back(err);
39 }
40
41 static int32_t gPending = 0; // Atomic.
42
43 static void done(double ms, ImplicitString config, ImplicitString src, ImplicitS tring name) {
44 SkDebugf("%s(%4dMB %5d) %s\t%s %s %s ", FLAGS_verbose ? "\n" : kSkOverwrite Line
45 , sk_tools::getMaxResidentSetSizeMB()
46 , sk_atomic_dec(&gPending)-1
47 , HumanizeMs(ms).c_str()
48 , config.c_str()
49 , src.c_str()
50 , name.c_str());
51 }
52
53 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~*/
54
55 template <typename T>
56 struct Tagged : public SkAutoTDelete<T> { const char* tag; };
57
58 static const bool kMemcpyOK = true;
59
60 static SkTArray<Tagged<Src>, kMemcpyOK> gSrcs;
61 static SkTArray<Tagged<Sink>, kMemcpyOK> gSinks;
62
63 static void push_src(const char* tag, Src* s) {
64 SkAutoTDelete<Src> src(s);
65 if (FLAGS_src.contains(tag) &&
66 !SkCommandLineFlags::ShouldSkip(FLAGS_match, src->name().c_str())) {
67 Tagged<Src>& s = gSrcs.push_back();
68 s.reset(src.detach());
69 s.tag = tag;
70 }
71 }
72
73 static void gather_srcs() {
74 for (const skiagm::GMRegistry* r = skiagm::GMRegistry::Head(); r; r = r->nex t()) {
75 push_src("gm", new GMSrc(r->factory()));
76 }
77 if (!FLAGS_skps.isEmpty()) {
78 SkOSFile::Iter it(FLAGS_skps[0], "skp");
79 for (SkString file; it.next(&file); ) {
80 push_src("skp", new SKPSrc(SkOSPath::Join(FLAGS_skps[0], file.c_str( ))));
81 }
82 }
83 if (!FLAGS_images.isEmpty()) {
84 const char* exts[] = {
85 "bmp", "gif", "jpg", "jpeg", "png", "webp", "ktx", "astc", "wbmp", " ico",
86 "BMP", "GIF", "JPG", "JPEG", "PNG", "WEBP", "KTX", "ASTC", "WBMP", " ICO",
87 };
88 for (size_t i = 0; i < SK_ARRAY_COUNT(exts); i++) {
89 SkOSFile::Iter it(FLAGS_images[0], exts[i]);
90 for (SkString file; it.next(&file); ) {
91 SkString path = SkOSPath::Join(FLAGS_images[0], file.c_str());
92 push_src("image", new ImageSrc(path)); // Decode entire ima ge.
93 push_src("subset", new ImageSrc(path, 5)); // Decode 5 random s ubsets.
94 }
95 }
96 }
97 }
98
99 static GrGLStandard get_gpu_api() {
100 if (FLAGS_gpuAPI.contains("gl")) { return kGL_GrGLStandard; }
101 if (FLAGS_gpuAPI.contains("gles")) { return kGLES_GrGLStandard; }
102 return kNone_GrGLStandard;
103 }
104
105 static void push_sink(const char* tag, Sink* s) {
106 SkAutoTDelete<Sink> sink(s);
107 if (!FLAGS_config.contains(tag)) {
108 return;
109 }
110 // Try a noop Src as a canary. If it fails, skip this sink.
111 struct : public Src {
112 Error draw(SkCanvas*) const SK_OVERRIDE { return ""; }
113 SkISize size() const SK_OVERRIDE { return SkISize::Make(16, 16); }
114 Name name() const SK_OVERRIDE { return "noop"; }
115 } noop;
116
117 SkBitmap bitmap;
118 SkDynamicMemoryWStream stream;
119 Error err = sink->draw(noop, &bitmap, &stream);
120 if (!err.isEmpty()) {
121 SkDebugf("Skipping %s: %s\n", tag, err.c_str());
122 return;
123 }
124
125 Tagged<Sink>& ts = gSinks.push_back();
126 ts.reset(sink.detach());
127 ts.tag = tag;
128 }
129
130 static bool gpu_supported() {
131 #if SK_SUPPORT_GPU
132 return FLAGS_gpu;
37 #else 133 #else
38 # define RASTERIZE_PDF_PROC NULL 134 return false;
39 #endif 135 #endif
40 136 }
41 #include <ctype.h> 137
42 138 static Sink* create_sink(const char* tag) {
43 using skiagm::GM; 139 #define SINK(t, sink, ...) if (0 == strcmp(t, tag)) { return new sink(__VA_ARGS_ _); }
44 using skiagm::GMRegistry; 140 if (gpu_supported()) {
45 using skiatest::Test; 141 const GrGLStandard api = get_gpu_api();
46 using skiatest::TestRegistry; 142 SINK("gpunull", GPUSink, GrContextFactory::kNull_GLContextType, api , 0, false);
47 143 SINK("gpudebug", GPUSink, GrContextFactory::kDebug_GLContextType, api , 0, false);
48 static const char kGpuAPINameGL[] = "gl"; 144 SINK("gpu", GPUSink, GrContextFactory::kNative_GLContextType, api , 0, false);
49 static const char kGpuAPINameGLES[] = "gles"; 145 SINK("gpudft", GPUSink, GrContextFactory::kNative_GLContextType, api , 0, true);
50 146 SINK("msaa4", GPUSink, GrContextFactory::kNative_GLContextType, api , 4, false);
51 DEFINE_bool(gms, true, "Run GMs?"); 147 SINK("msaa16", GPUSink, GrContextFactory::kNative_GLContextType, api , 16, false);
52 DEFINE_bool(tests, true, "Run tests?"); 148 SINK("nvprmsaa4", GPUSink, GrContextFactory::kNVPR_GLContextType, api , 4, false);
53 DEFINE_bool(reportUsedChars, false, "Output test font construction data to be pa sted into" 149 SINK("nvprmsaa16", GPUSink, GrContextFactory::kNVPR_GLContextType, api , 16, false);
54 " create_test_font.cpp."); 150 #if SK_ANGLE
55 DEFINE_string(images, "resources", "Path to directory containing images to decod e."); 151 SINK("angle", GPUSink, GrContextFactory::kANGLE_GLContextType, api , 0, false);
56 DEFINE_bool(rasterPDF, true, "Rasterize PDFs?"); 152 #endif
57 153 #if SK_MESA
58 __SK_FORCE_IMAGE_DECODER_LINKING; 154 SINK("mesa", GPUSink, GrContextFactory::kMESA_GLContextType, api , 0, false);
59 155 #endif
60 static DM::RasterizePdfProc get_pdf_rasterizer_proc() { 156 }
61 return reinterpret_cast<DM::RasterizePdfProc>( 157
62 FLAGS_rasterPDF ? RASTERIZE_PDF_PROC : NULL); 158 if (FLAGS_cpu) {
63 } 159 SINK("565", RasterSink, kRGB_565_SkColorType);
64 160 SINK("8888", RasterSink, kN32_SkColorType);
65 // "FooBar" -> "foobar". Obviously, ASCII only. 161 // TODO(mtklein): reenable once skiagold can handle .pdf uploads.
66 static SkString lowercase(SkString s) { 162 //SINK("pdf", PDFSink);
67 for (size_t i = 0; i < s.size(); i++) { 163 }
68 s[i] = tolower(s[i]); 164 #undef SINK
69 } 165 return NULL;
70 return s; 166 }
71 } 167
72 168 static Sink* create_via(const char* tag, Sink* wrapped) {
73 static const GrContextFactory::GLContextType native = GrContextFactory::kNative_ GLContextType; 169 #define VIA(t, via, ...) if (0 == strcmp(t, tag)) { return new via(__VA_ARGS__); }
74 static const GrContextFactory::GLContextType nvpr = GrContextFactory::kNVPR_GL ContextType; 170 VIA("serialize", ViaSerialization, wrapped);
75 static const GrContextFactory::GLContextType null = GrContextFactory::kNull_GL ContextType; 171
76 static const GrContextFactory::GLContextType debug = GrContextFactory::kDebug_G LContextType; 172 VIA("tiles", ViaTiles, 256, 256, NULL, wrapped);
77 #if SK_ANGLE 173 VIA("tiles_rt", ViaTiles, 256, 256, new SkRTreeFactory, wrapped);
78 static const GrContextFactory::GLContextType angle = GrContextFactory::kANGLE_G LContextType; 174
79 #endif 175 const int xp = SkGPipeWriter::kCrossProcess_Flag,
80 #if SK_MESA 176 sa = xp | SkGPipeWriter::kSharedAddressSpace_Flag;
81 static const GrContextFactory::GLContextType mesa = GrContextFactory::kMESA_GL ContextType; 177 VIA("pipe", ViaPipe, 0, wrapped);
82 #endif 178 VIA("pipe_xp", ViaPipe, xp, wrapped);
83 179 VIA("pipe_sa", ViaPipe, sa, wrapped);
84 static void kick_off_gms(const SkTDArray<GMRegistry::Factory>& gms, 180
85 const SkTArray<SkString>& configs, 181 if (FLAGS_matrix.count() == 9) {
86 GrGLStandard gpuAPI, 182 SkMatrix m;
87 DM::Reporter* reporter, 183 for (int i = 0; i < 9; i++) {
88 DM::TaskRunner* tasks) { 184 m[i] = (SkScalar)atof(FLAGS_matrix[i]);
89 #define START(name, type, ...) \ 185 }
90 if (lowercase(configs[j]).equals(name)) { \ 186 VIA("matrix", ViaMatrix, m, wrapped);
91 tasks->add(SkNEW_ARGS(DM::type, (name, reporter, tasks, gms[i], ## __VA_ ARGS__))); \ 187 }
92 } 188 #undef VIA
93 for (int i = 0; i < gms.count(); i++) { 189 return NULL;
94 for (int j = 0; j < configs.count(); j++) { 190 }
95 191
96 START("565", CpuGMTask, kRGB_565_SkColorType); 192 static void gather_sinks() {
97 START("8888", CpuGMTask, kN32_SkColorType); 193 for (int i = 0; i < FLAGS_config.count(); i++) {
98 START("gpu", GpuGMTask, native, gpuAPI, 0, false); 194 const char* config = FLAGS_config[i];
99 START("msaa4", GpuGMTask, native, gpuAPI, 4, false); 195 SkTArray<SkString> parts;
100 START("msaa16", GpuGMTask, native, gpuAPI, 16, false); 196 SkStrSplit(config, "-", &parts);
101 START("nvprmsaa4", GpuGMTask, nvpr, gpuAPI, 4, false); 197
102 START("nvprmsaa16", GpuGMTask, nvpr, gpuAPI, 16, false); 198 Sink* sink = NULL;
103 START("gpudft", GpuGMTask, native, gpuAPI, 0, true); 199 for (int i = parts.count(); i-- > 0;) {
104 START("gpunull", GpuGMTask, null, gpuAPI, 0, false); 200 const char* part = parts[i].c_str();
105 START("gpudebug", GpuGMTask, debug, gpuAPI, 0, false); 201 Sink* next = (sink == NULL) ? create_sink(part) : create_via(part, s ink);
106 #if SK_ANGLE 202 if (next == NULL) {
107 START("angle", GpuGMTask, angle, gpuAPI, 0, false); 203 SkDebugf("Skipping %s: Don't understand '%s'.\n", config, part);
108 #endif 204 delete sink;
109 #if SK_MESA 205 sink = NULL;
110 START("mesa", GpuGMTask, mesa, gpuAPI, 0, false); 206 break;
111 #endif 207 }
112 START("pdf", PDFTask, get_pdf_rasterizer_proc()); 208 sink = next;
113 } 209 }
114 } 210 if (sink) {
115 #undef START 211 push_sink(config, sink);
116 } 212 }
117 213 }
118 static void kick_off_tests(const SkTDArray<TestRegistry::Factory>& tests, 214 }
119 DM::Reporter* reporter, 215
120 DM::TaskRunner* tasks) { 216 // The finest-grained unit of work we can run: draw a single Src into a single S ink,
121 for (int i = 0; i < tests.count(); i++) { 217 // report any errors, and perhaps write out the output: a .png of the bitmap, or a raw stream.
122 SkAutoTDelete<Test> test(tests[i](NULL)); 218 struct Task {
123 if (test->isGPUTest()) { 219 Task(const Tagged<Src>& src, const Tagged<Sink>& sink) : src(src), sink(sink ) {}
124 tasks->add(SkNEW_ARGS(DM::GpuTestTask, (reporter, tasks, tests[i]))) ; 220 const Tagged<Src>& src;
221 const Tagged<Sink>& sink;
222
223 static void Run(Task* task) {
224 WallTimer timer;
225 timer.start();
226 if (!FLAGS_dryRun) {
227 SkBitmap bitmap;
228 SkDynamicMemoryWStream stream;
229 Error err = task->sink->draw(*task->src, &bitmap, &stream);
230 if (!err.isEmpty()) {
231 fail(SkStringPrintf("%s %s %s: %s",
232 task->sink.tag,
233 task->src.tag,
234 task->src->name().c_str(),
235 err.c_str()));
236 }
237 if (!FLAGS_writePath.isEmpty()) {
238 const char* ext = task->sink->fileExtension();
239 if (stream.bytesWritten() == 0) {
240 SkMemoryStream pixels(bitmap.getPixels(), bitmap.getSize());
241 WriteToDisk(*task, &pixels, bitmap.getSize(), &bitmap, ext);
242 } else {
243 SkAutoTDelete<SkStreamAsset> data(stream.detachAsStream());
244 WriteToDisk(*task, data, data->getLength(), NULL, ext);
245 }
246 }
247 }
248 timer.end();
249 done(timer.fWall, task->sink.tag, task->src.tag, task->src->name());
250 }
251
252 static void WriteToDisk(const Task& task,
253 SkStream* data, size_t len,
254 const SkBitmap* bitmap,
255 const char* ext) {
256 SkMD5 hash;
257 hash.writeStream(data, len);
258 SkMD5::Digest digest;
259 hash.finish(digest);
260
261 JsonWriter::BitmapResult result;
262 result.name = task.src->name();
263 result.config = task.sink.tag;
264 result.sourceType = task.src.tag;
265 result.ext = ext;
266 for (int i = 0; i < 16; i++) {
267 result.md5.appendf("%02x", digest.data[i]);
268 }
269 JsonWriter::AddBitmapResult(result);
270
271 const char* dir = FLAGS_writePath[0];
272 if (0 == strcmp(dir, "@")) { // Needed for iOS.
273 dir = FLAGS_resourcePath[0];
274 }
275 sk_mkdir(dir);
276
277 SkString path;
278 if (FLAGS_nameByHash) {
279 path = SkOSPath::Join(dir, result.md5.c_str());
280 path.append(".");
281 path.append(ext);
282 if (sk_exists(path.c_str())) {
283 return; // Content-addressed. If it exists already, we're done .
284 }
125 } else { 285 } else {
126 tasks->add(SkNEW_ARGS(DM::CpuTestTask, (reporter, tasks, tests[i]))) ; 286 path = SkOSPath::Join(dir, task.sink.tag);
127 } 287 sk_mkdir(path.c_str());
128 } 288 path = SkOSPath::Join(path.c_str(), task.src.tag);
129 } 289 sk_mkdir(path.c_str());
130 290 path = SkOSPath::Join(path.c_str(), task.src->name().c_str());
131 static void find_files(const char* dir, 291 path.append(".");
132 const char* suffixes[], 292 path.append(ext);
133 size_t num_suffixes, 293 }
134 SkTArray<SkString>* files) { 294
135 if (0 == strcmp(dir, "")) { 295 SkFILEWStream file(path.c_str());
296 if (!file.isValid()) {
297 fail(SkStringPrintf("Can't open %s for writing.\n", path.c_str()));
298 return;
299 }
300
301 data->rewind();
302 if (bitmap) {
303 // We can't encode A8 bitmaps as PNGs. Convert them to 8888 first.
304 SkBitmap converted;
305 if (bitmap->info().colorType() == kAlpha_8_SkColorType) {
306 if (!bitmap->copyTo(&converted, kN32_SkColorType)) {
307 fail("Can't convert A8 to 8888.\n");
308 return;
309 }
310 bitmap = &converted;
311 }
312 if (!SkImageEncoder::EncodeStream(&file, *bitmap, SkImageEncoder::kP NG_Type, 100)) {
313 fail(SkStringPrintf("Can't encode PNG to %s.\n", path.c_str()));
314 return;
315 }
316 } else {
317 if (!file.writeStream(data, len)) {
318 fail(SkStringPrintf("Can't write to %s.\n", path.c_str()));
319 return;
320 }
321 }
322 }
323 };
324
325 // Run all tasks in the same enclave serially on the same thread.
326 // They can't possibly run concurrently with each other.
327 static void run_enclave(SkTArray<Task>* tasks) {
328 for (int i = 0; i < tasks->count(); i++) {
329 Task::Run(tasks->begin() + i);
330 }
331 }
332
333 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~*/
334
335 // Unit tests don't fit so well into the Src/Sink model, so we give them special treatment.
336
337 static struct : public skiatest::Reporter {
338 void onReportFailed(const skiatest::Failure& failure) SK_OVERRIDE {
339 SkString s;
340 failure.getFailureString(&s);
341 fail(s);
342 JsonWriter::AddTestFailure(failure);
343 }
344 bool allowExtendedTest() const SK_OVERRIDE { return FLAGS_pathOpsExtended; }
345 bool verbose() const SK_OVERRIDE { return FLAGS_veryVerbose; }
346 } gTestReporter;
347
348 static SkTArray<SkAutoTDelete<skiatest::Test>, kMemcpyOK> gTests;
349
350 static void gather_tests() {
351 if (!FLAGS_tests) {
136 return; 352 return;
137 } 353 }
138 354 for (const skiatest::TestRegistry* r = skiatest::TestRegistry::Head(); r; r = r->next()) {
139 SkString filename; 355 SkAutoTDelete<skiatest::Test> test(r->factory()(NULL));
140 for (size_t i = 0; i < num_suffixes; i++) { 356 if (SkCommandLineFlags::ShouldSkip(FLAGS_match, test->getName())) {
141 SkOSFile::Iter it(dir, suffixes[i]); 357 continue;
142 while (it.next(&filename)) { 358 }
143 if (!SkCommandLineFlags::ShouldSkip(FLAGS_match, filename.c_str())) { 359 if (test->isGPUTest() /*&& !gpu_supported()*/) { // TEMPORARILY DISABLE D
144 files->push_back(SkOSPath::Join(dir, filename.c_str())); 360 continue;
145 } 361 }
146 } 362 if (!test->isGPUTest() && !FLAGS_cpu) {
147 } 363 continue;
148 } 364 }
149 365 test->setReporter(&gTestReporter);
150 static void kick_off_skps(const SkTArray<SkString>& skps, 366 gTests.push_back().reset(test.detach());
151 DM::Reporter* reporter, 367 }
152 DM::TaskRunner* tasks) { 368 }
153 for (int i = 0; i < skps.count(); ++i) { 369
154 SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(skps[i].c_str())); 370 static void run_test(SkAutoTDelete<skiatest::Test>* t) {
155 if (stream.get() == NULL) { 371 WallTimer timer;
156 SkDebugf("Could not read %s.\n", skps[i].c_str()); 372 timer.start();
157 exit(1); 373 skiatest::Test* test = t->get();
158 } 374 if (!FLAGS_dryRun) {
159 SkAutoTUnref<SkPicture> pic( 375 GrContextFactory grFactory;
160 SkPicture::CreateFromStream(stream.get(), &sk_tools::LazyDecodeB itmap)); 376 test->setGrContextFactory(&grFactory);
161 if (pic.get() == NULL) { 377 test->run();
162 SkDebugf("Could not read %s as an SkPicture.\n", skps[i].c_str()); 378 if (!test->passed()) {
163 exit(1); 379 fail(SkStringPrintf("test %s failed", test->getName()));
164 } 380 }
165 381 }
166 SkString filename = SkOSPath::Basename(skps[i].c_str()); 382 timer.end();
167 tasks->add(SkNEW_ARGS(DM::SKPTask, (reporter, tasks, pic, filename))); 383 done(timer.fWall, "unit", "test", test->getName());
168 tasks->add(SkNEW_ARGS(DM::PDFTask, (reporter, tasks, pic, filename, 384 }
169 get_pdf_rasterizer_proc()))); 385
170 } 386 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~*/
171 }
172
173 static 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
189 static 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
201 static 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
211 template <typename T, typename Registry>
212 static void append_matching_factories(Registry* head, SkTDArray<typename Registr y::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 }
220 387
221 int dm_main(); 388 int dm_main();
222 int dm_main() { 389 int dm_main() {
223 SetupCrashHandler(); 390 SetupCrashHandler();
224 SkAutoGraphics ag; 391 SkAutoGraphics ag;
225 SkTaskGroup::Enabler enabled(FLAGS_threads); 392 SkTaskGroup::Enabler enabled(FLAGS_threads);
226 393
227 if (FLAGS_dryRun || FLAGS_veryVerbose) { 394 gather_srcs();
228 FLAGS_verbose = true; 395 gather_sinks();
229 } 396 gather_tests();
230 #if SK_ENABLE_INST_COUNT 397
231 gPrintInstCount = FLAGS_leaks; 398 gPending = gSrcs.count() * gSinks.count() + gTests.count();
232 #endif 399 SkDebugf("%d srcs * %d sinks + %d tests == %d tasks\n",
233 400 gSrcs.count(), gSinks.count(), gTests.count(), gPending);
234 SkTArray<SkString> configs; 401
235 for (int i = 0; i < FLAGS_config.count(); i++) { 402 // We try to exploit as much parallelism as is safe. Most Src/Sink pairs ru n on any thread,
236 SkStrSplit(FLAGS_config[i], ", ", &configs); 403 // but Sinks that identify as part of a particular enclave run serially on a single thread.
237 } 404 // Tests run on any thread, with a separate GrContextFactory for each GPU te st.
238 405 SkTArray<Task> enclaves[kNumEnclaves];
239 GrGLStandard gpuAPI = get_gl_standard(); 406 for (int j = 0; j < gSinks.count(); j++) {
240 407 SkTArray<Task>& tasks = enclaves[gSinks[j]->enclave()];
241 SkTDArray<GMRegistry::Factory> gms; 408 for (int i = 0; i < gSrcs.count(); i++) {
242 if (FLAGS_gms) { 409 tasks.push_back(Task(gSrcs[i], gSinks[j]));
243 append_matching_factories<GM>(GMRegistry::Head(), &gms); 410 }
244 } 411 }
245 412
246 SkTDArray<TestRegistry::Factory> tests; 413 SK_COMPILE_ASSERT(kAnyThread_Enclave == 0, AnyThreadZero);
247 if (FLAGS_tests) { 414 SkTaskGroup tg;
248 append_matching_factories<Test>(TestRegistry::Head(), &tests); 415 tg.batch( Task::Run, enclaves[0].begin(), enclaves[0].count());
249 } 416 tg.batch(run_enclave, enclaves+1, kNumEnclaves-1);
250 417 tg.batch( run_test, gTests.begin(), gTests.count());
251 418 tg.wait();
252 SkTArray<SkString> skps; 419
253 if (!FLAGS_skps.isEmpty()) { 420 // At this point we're back in single-threaded land.
254 const char* suffixes[] = { "skp" }; 421
255 find_files(FLAGS_skps[0], suffixes, SK_ARRAY_COUNT(suffixes), &skps); 422 if (!FLAGS_verbose) {
256 } 423 SkDebugf("\n");
257 424 }
258 SkTArray<SkString> images; 425
259 if (!FLAGS_images.isEmpty()) { 426 JsonWriter::DumpJson();
260 const char* suffixes[] = { 427
261 "bmp", "gif", "jpg", "jpeg", "png", "webp", "ktx", "astc", "wbmp", " ico", 428 if (gFailures.count() > 0) {
262 "BMP", "GIF", "JPG", "JPEG", "PNG", "WEBP", "KTX", "ASTC", "WBMP", " ICO", 429 SkDebugf("Failures:\n");
263 }; 430 for (int i = 0; i < gFailures.count(); i++) {
264 find_files(FLAGS_images[0], suffixes, SK_ARRAY_COUNT(suffixes), &images) ; 431 SkDebugf("\t%s", gFailures[i].c_str());
265 } 432 }
266 433 SkDebugf("%d failures\n", gFailures.count());
267 SkDebugf("%d GMs x %d configs, %d tests, %d pictures, %d images\n", 434 return 1;
268 gms.count(), configs.count(), tests.count(), skps.count(), images.c ount()); 435 }
269 DM::Reporter reporter; 436 if (gPending > 0) {
270 437 SkDebugf("Hrm, we didn't seem to run everything we intended to! Please file a bug.\n");
271 DM::TaskRunner tasks; 438 return 1;
272 kick_off_tests(tests, &reporter, &tasks); 439 }
273 kick_off_gms(gms, configs, gpuAPI, &reporter, &tasks); 440 return 0;
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;
291 } 441 }
292 442
293 #if !defined(SK_BUILD_FOR_IOS) && !defined(SK_BUILD_FOR_NACL) 443 #if !defined(SK_BUILD_FOR_IOS) && !defined(SK_BUILD_FOR_NACL)
294 int main(int argc, char** argv) { 444 int main(int argc, char** argv) {
295 SkCommandLineFlags::Parse(argc, argv); 445 SkCommandLineFlags::Parse(argc, argv);
296 return dm_main(); 446 return dm_main();
297 } 447 }
298 #endif 448 #endif
OLDNEW
« no previous file with comments | « bench/nanobench.cpp ('k') | dm/DMCpuGMTask.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698