Chromium Code Reviews| 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 |