OLD | NEW |
---|---|
1 #include "CrashHandler.h" | 1 #include "CrashHandler.h" |
2 #include "DMJsonWriter.h" | 2 #include "DMJsonWriter.h" |
3 #include "DMSrcSink.h" | 3 #include "DMSrcSink.h" |
4 #include "OverwriteLine.h" | 4 #include "OverwriteLine.h" |
5 #include "ProcStats.h" | 5 #include "ProcStats.h" |
6 #include "SkBBHFactory.h" | 6 #include "SkBBHFactory.h" |
7 #include "SkChecksum.h" | |
7 #include "SkCommonFlags.h" | 8 #include "SkCommonFlags.h" |
8 #include "SkForceLinking.h" | 9 #include "SkForceLinking.h" |
9 #include "SkGraphics.h" | 10 #include "SkGraphics.h" |
10 #include "SkMD5.h" | 11 #include "SkMD5.h" |
11 #include "SkOSFile.h" | 12 #include "SkOSFile.h" |
13 #include "SkTDynamicHash.h" | |
12 #include "SkTaskGroup.h" | 14 #include "SkTaskGroup.h" |
13 #include "Test.h" | 15 #include "Test.h" |
14 #include "Timer.h" | 16 #include "Timer.h" |
15 | 17 |
16 DEFINE_string(images, "resources", "Images to decode."); | 18 DEFINE_string(images, "resources", "Images to decode."); |
17 DEFINE_string(src, "tests gm skp image", "Source types to test."); | 19 DEFINE_string(src, "tests gm skp image", "Source types to test."); |
18 DEFINE_bool(nameByHash, false, | 20 DEFINE_bool(nameByHash, false, |
19 "If true, write to FLAGS_writePath[0]/<hash>.png instead of " | 21 "If true, write to FLAGS_writePath[0]/<hash>.png instead of " |
20 "to FLAGS_writePath[0]/<config>/<sourceType>/<name>.png"); | 22 "to FLAGS_writePath[0]/<config>/<sourceType>/<name>.png"); |
21 DEFINE_bool2(pathOpsExtended, x, false, "Run extended pathOps tests."); | 23 DEFINE_bool2(pathOpsExtended, x, false, "Run extended pathOps tests."); |
22 DEFINE_string(matrix, "1 0 0 0 1 0 0 0 1", | 24 DEFINE_string(matrix, "1 0 0 0 1 0 0 0 1", |
23 "Matrix to apply when using 'matrix' in config."); | 25 "Matrix to apply when using 'matrix' in config."); |
24 DEFINE_bool(gpu_threading, false, "Allow GPU work to run on multiple threads?"); | 26 DEFINE_bool(gpu_threading, false, "Allow GPU work to run on multiple threads?"); |
25 | 27 |
26 DEFINE_string(blacklist, "", | 28 DEFINE_string(blacklist, "", |
27 "Space-separated config/src/name triples to blacklist. '_' matches anyt hing. E.g. \n" | 29 "Space-separated config/src/name triples to blacklist. '_' matches anyt hing. E.g. \n" |
28 "'--blacklist gpu skp _' will blacklist all SKPs drawn into the gpu conf ig.\n" | 30 "'--blacklist gpu skp _' will blacklist all SKPs drawn into the gpu conf ig.\n" |
29 "'--blacklist gpu skp _ 8888 gm aarects' will also blacklist the aarects GM on 8888."); | 31 "'--blacklist gpu skp _ 8888 gm aarects' will also blacklist the aarects GM on 8888."); |
30 | 32 |
33 DEFINE_string2(readPath, r, "", "If set check for equality with golden results i n this directory."); | |
34 | |
31 __SK_FORCE_IMAGE_DECODER_LINKING; | 35 __SK_FORCE_IMAGE_DECODER_LINKING; |
32 using namespace DM; | 36 using namespace DM; |
33 | 37 |
34 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~*/ | 38 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~*/ |
35 | 39 |
36 SK_DECLARE_STATIC_MUTEX(gFailuresMutex); | 40 SK_DECLARE_STATIC_MUTEX(gFailuresMutex); |
37 static SkTArray<SkString> gFailures; | 41 static SkTArray<SkString> gFailures; |
38 | 42 |
39 static void fail(ImplicitString err) { | 43 static void fail(ImplicitString err) { |
40 SkAutoMutexAcquire lock(gFailuresMutex); | 44 SkAutoMutexAcquire lock(gFailuresMutex); |
(...skipping 14 matching lines...) Expand all Loading... | |
55 , name.c_str()); | 59 , name.c_str()); |
56 // We write our dm.json file every once in a while in case we crash. | 60 // We write our dm.json file every once in a while in case we crash. |
57 // Notice this also handles the final dm.json when pending == 0. | 61 // Notice this also handles the final dm.json when pending == 0. |
58 if (pending % 500 == 0) { | 62 if (pending % 500 == 0) { |
59 JsonWriter::DumpJson(); | 63 JsonWriter::DumpJson(); |
60 } | 64 } |
61 } | 65 } |
62 | 66 |
63 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~*/ | 67 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~*/ |
64 | 68 |
69 struct Gold : public SkString { | |
70 Gold(ImplicitString sink, ImplicitString src, ImplicitString name, ImplicitS tring md5) | |
71 : SkString("") { | |
72 this->append(sink); | |
73 this->append(src); | |
74 this->append(name); | |
75 this->append(md5); | |
76 while (this->size() % 4) { | |
77 this->append("!"); // Pad out if needed so we can pass this to Murm ur3. | |
78 } | |
79 } | |
80 static const Gold& GetKey(const Gold& g) { return g; } | |
81 static uint32_t Hash(const Gold& g) { | |
82 return SkChecksum::Murmur3((const uint32_t*)g.c_str(), g.size()); | |
83 } | |
84 }; | |
85 static SkTDynamicHash<Gold, Gold> gGold; | |
86 | |
87 static void add_gold(JsonWriter::BitmapResult r) { | |
88 gGold.add(new Gold(r.config, r.sourceType, r.name, r.md5)); // We'll let th ese leak. Lazybones. | |
89 } | |
90 | |
91 static void gather_gold() { | |
92 if (!FLAGS_readPath.isEmpty()) { | |
93 SkString path(FLAGS_readPath[0]); | |
94 path.append("/dm.json"); | |
95 if (!JsonWriter::ReadJson(path.c_str(), add_gold)) { | |
96 fail(SkStringPrintf("Couldn't read %s for golden results.", path.c_s tr())); | |
97 } | |
98 } | |
99 } | |
100 | |
101 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~*/ | |
102 | |
65 template <typename T> | 103 template <typename T> |
66 struct Tagged : public SkAutoTDelete<T> { const char* tag; }; | 104 struct Tagged : public SkAutoTDelete<T> { const char* tag; }; |
67 | 105 |
68 static const bool kMemcpyOK = true; | 106 static const bool kMemcpyOK = true; |
69 | 107 |
70 static SkTArray<Tagged<Src>, kMemcpyOK> gSrcs; | 108 static SkTArray<Tagged<Src>, kMemcpyOK> gSrcs; |
71 static SkTArray<Tagged<Sink>, kMemcpyOK> gSinks; | 109 static SkTArray<Tagged<Sink>, kMemcpyOK> gSinks; |
72 | 110 |
73 static void push_src(const char* tag, Src* s) { | 111 static void push_src(const char* tag, Src* s) { |
74 SkAutoTDelete<Src> src(s); | 112 SkAutoTDelete<Src> src(s); |
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
249 SkBitmap bitmap; | 287 SkBitmap bitmap; |
250 SkDynamicMemoryWStream stream; | 288 SkDynamicMemoryWStream stream; |
251 Error err = task->sink->draw(*task->src, &bitmap, &stream); | 289 Error err = task->sink->draw(*task->src, &bitmap, &stream); |
252 if (!err.isEmpty()) { | 290 if (!err.isEmpty()) { |
253 fail(SkStringPrintf("%s %s %s: %s", | 291 fail(SkStringPrintf("%s %s %s: %s", |
254 task->sink.tag, | 292 task->sink.tag, |
255 task->src.tag, | 293 task->src.tag, |
256 name.c_str(), | 294 name.c_str(), |
257 err.c_str())); | 295 err.c_str())); |
258 } | 296 } |
297 SkAutoTDelete<SkStreamAsset> data(stream.detachAsStream()); | |
298 | |
299 SkString md5; | |
300 if (!FLAGS_writePath.isEmpty() || !FLAGS_readPath.isEmpty()) { | |
301 SkMD5 hash; | |
302 if (data->getLength()) { | |
303 hash.writeStream(data, data->getLength()); | |
304 data->rewind(); | |
305 } else { | |
306 hash.write(bitmap.getPixels(), bitmap.getSize()); | |
307 } | |
308 SkMD5::Digest digest; | |
309 hash.finish(digest); | |
310 for (int i = 0; i < 16; i++) { | |
hal.canary
2015/01/27 22:44:55
I want SkString SkMD5::toString();
| |
311 md5.appendf("%02x", digest.data[i]); | |
312 } | |
313 } | |
314 | |
315 if (!FLAGS_readPath.isEmpty() && | |
316 !gGold.find(Gold(task->sink.tag, task->src.tag, name, md5))) { | |
317 fail(SkStringPrintf("%s not found for %s %s %s in %s", | |
318 md5.c_str(), | |
319 task->sink.tag, | |
320 task->src.tag, | |
321 name.c_str(), | |
322 FLAGS_readPath[0])); | |
323 } | |
324 | |
259 if (!FLAGS_writePath.isEmpty()) { | 325 if (!FLAGS_writePath.isEmpty()) { |
260 const char* ext = task->sink->fileExtension(); | 326 const char* ext = task->sink->fileExtension(); |
261 if (stream.bytesWritten() == 0) { | 327 if (data->getLength()) { |
262 SkMemoryStream pixels(bitmap.getPixels(), bitmap.getSize()); | 328 WriteToDisk(*task, md5, ext, data, data->getLength(), NULL); |
263 WriteToDisk(*task, &pixels, bitmap.getSize(), &bitmap, ext); | |
264 } else { | 329 } else { |
265 SkAutoTDelete<SkStreamAsset> data(stream.detachAsStream()); | 330 WriteToDisk(*task, md5, ext, NULL, 0, &bitmap); |
266 WriteToDisk(*task, data, data->getLength(), NULL, ext); | |
267 } | 331 } |
268 } | 332 } |
269 } | 333 } |
270 timer.end(); | 334 timer.end(); |
271 if (!whyBlacklisted.isEmpty()) { | 335 if (!whyBlacklisted.isEmpty()) { |
272 name.appendf(" (--blacklist, %s)", whyBlacklisted.c_str()); | 336 name.appendf(" (--blacklist, %s)", whyBlacklisted.c_str()); |
273 } | 337 } |
274 done(timer.fWall, task->sink.tag, task->src.tag, name); | 338 done(timer.fWall, task->sink.tag, task->src.tag, name); |
275 } | 339 } |
276 | 340 |
277 static void WriteToDisk(const Task& task, | 341 static void WriteToDisk(const Task& task, |
342 SkString md5, | |
343 const char* ext, | |
278 SkStream* data, size_t len, | 344 SkStream* data, size_t len, |
279 const SkBitmap* bitmap, | 345 const SkBitmap* bitmap) { |
280 const char* ext) { | |
281 SkMD5 hash; | |
282 hash.writeStream(data, len); | |
283 SkMD5::Digest digest; | |
284 hash.finish(digest); | |
285 | |
286 JsonWriter::BitmapResult result; | 346 JsonWriter::BitmapResult result; |
287 result.name = task.src->name(); | 347 result.name = task.src->name(); |
288 result.config = task.sink.tag; | 348 result.config = task.sink.tag; |
289 result.sourceType = task.src.tag; | 349 result.sourceType = task.src.tag; |
290 result.ext = ext; | 350 result.ext = ext; |
291 for (int i = 0; i < 16; i++) { | 351 result.md5 = md5; |
292 result.md5.appendf("%02x", digest.data[i]); | |
293 } | |
294 JsonWriter::AddBitmapResult(result); | 352 JsonWriter::AddBitmapResult(result); |
295 | 353 |
296 const char* dir = FLAGS_writePath[0]; | 354 const char* dir = FLAGS_writePath[0]; |
297 if (0 == strcmp(dir, "@")) { // Needed for iOS. | 355 if (0 == strcmp(dir, "@")) { // Needed for iOS. |
298 dir = FLAGS_resourcePath[0]; | 356 dir = FLAGS_resourcePath[0]; |
299 } | 357 } |
300 sk_mkdir(dir); | 358 sk_mkdir(dir); |
301 | 359 |
302 SkString path; | 360 SkString path; |
303 if (FLAGS_nameByHash) { | 361 if (FLAGS_nameByHash) { |
(...skipping 12 matching lines...) Expand all Loading... | |
316 path.append("."); | 374 path.append("."); |
317 path.append(ext); | 375 path.append(ext); |
318 } | 376 } |
319 | 377 |
320 SkFILEWStream file(path.c_str()); | 378 SkFILEWStream file(path.c_str()); |
321 if (!file.isValid()) { | 379 if (!file.isValid()) { |
322 fail(SkStringPrintf("Can't open %s for writing.\n", path.c_str())); | 380 fail(SkStringPrintf("Can't open %s for writing.\n", path.c_str())); |
323 return; | 381 return; |
324 } | 382 } |
325 | 383 |
326 data->rewind(); | |
327 if (bitmap) { | 384 if (bitmap) { |
328 // We can't encode A8 bitmaps as PNGs. Convert them to 8888 first. | 385 // We can't encode A8 bitmaps as PNGs. Convert them to 8888 first. |
329 SkBitmap converted; | 386 SkBitmap converted; |
330 if (bitmap->info().colorType() == kAlpha_8_SkColorType) { | 387 if (bitmap->info().colorType() == kAlpha_8_SkColorType) { |
331 if (!bitmap->copyTo(&converted, kN32_SkColorType)) { | 388 if (!bitmap->copyTo(&converted, kN32_SkColorType)) { |
332 fail("Can't convert A8 to 8888.\n"); | 389 fail("Can't convert A8 to 8888.\n"); |
333 return; | 390 return; |
334 } | 391 } |
335 bitmap = &converted; | 392 bitmap = &converted; |
336 } | 393 } |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
411 run_test(&gGPUTests[i]); | 468 run_test(&gGPUTests[i]); |
412 } | 469 } |
413 } | 470 } |
414 | 471 |
415 int dm_main(); | 472 int dm_main(); |
416 int dm_main() { | 473 int dm_main() { |
417 SetupCrashHandler(); | 474 SetupCrashHandler(); |
418 SkAutoGraphics ag; | 475 SkAutoGraphics ag; |
419 SkTaskGroup::Enabler enabled(FLAGS_threads); | 476 SkTaskGroup::Enabler enabled(FLAGS_threads); |
420 | 477 |
478 gather_gold(); | |
479 | |
421 gather_srcs(); | 480 gather_srcs(); |
422 gather_sinks(); | 481 gather_sinks(); |
423 gather_tests(); | 482 gather_tests(); |
424 | 483 |
425 gPending = gSrcs.count() * gSinks.count() + gThreadedTests.count() + gGPUTes ts.count(); | 484 gPending = gSrcs.count() * gSinks.count() + gThreadedTests.count() + gGPUTes ts.count(); |
426 SkDebugf("%d srcs * %d sinks + %d tests == %d tasks\n", | 485 SkDebugf("%d srcs * %d sinks + %d tests == %d tasks\n", |
427 gSrcs.count(), gSinks.count(), gThreadedTests.count() + gGPUTests.c ount(), gPending); | 486 gSrcs.count(), gSinks.count(), gThreadedTests.count() + gGPUTests.c ount(), gPending); |
428 | 487 |
429 // We try to exploit as much parallelism as is safe. Most Src/Sink pairs ru n on any thread, | 488 // We try to exploit as much parallelism as is safe. Most Src/Sink pairs ru n on any thread, |
430 // but Sinks that identify as part of a particular enclave run serially on a single thread. | 489 // but Sinks that identify as part of a particular enclave run serially on a single thread. |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
470 } | 529 } |
471 return 0; | 530 return 0; |
472 } | 531 } |
473 | 532 |
474 #if !defined(SK_BUILD_FOR_IOS) && !defined(SK_BUILD_FOR_NACL) | 533 #if !defined(SK_BUILD_FOR_IOS) && !defined(SK_BUILD_FOR_NACL) |
475 int main(int argc, char** argv) { | 534 int main(int argc, char** argv) { |
476 SkCommandLineFlags::Parse(argc, argv); | 535 SkCommandLineFlags::Parse(argc, argv); |
477 return dm_main(); | 536 return dm_main(); |
478 } | 537 } |
479 #endif | 538 #endif |
OLD | NEW |