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 "DMSrcSinkAndroid.h" | 4 #include "DMSrcSinkAndroid.h" |
| 5 #include "OverwriteLine.h" | 5 #include "OverwriteLine.h" |
| 6 #include "ProcStats.h" | 6 #include "ProcStats.h" |
| 7 #include "SkBBHFactory.h" | 7 #include "SkBBHFactory.h" |
| 8 #include "SkChecksum.h" | 8 #include "SkChecksum.h" |
| 9 #include "SkCommonFlags.h" | 9 #include "SkCommonFlags.h" |
| 10 #include "SkForceLinking.h" | 10 #include "SkForceLinking.h" |
| 11 #include "SkGraphics.h" | 11 #include "SkGraphics.h" |
| 12 #include "SkImageInfo.h" | |
| 12 #include "SkInstCnt.h" | 13 #include "SkInstCnt.h" |
| 13 #include "SkMD5.h" | 14 #include "SkMD5.h" |
| 14 #include "SkOSFile.h" | 15 #include "SkOSFile.h" |
| 15 #include "SkTHash.h" | 16 #include "SkTHash.h" |
| 16 #include "SkTaskGroup.h" | 17 #include "SkTaskGroup.h" |
| 17 #include "Test.h" | 18 #include "Test.h" |
| 18 #include "Timer.h" | 19 #include "Timer.h" |
| 19 | 20 |
| 20 DEFINE_string(src, "tests gm skp image subset", "Source types to test."); | 21 DEFINE_string(src, "tests gm skp image subset", "Source types to test."); |
| 21 DEFINE_bool(nameByHash, false, | 22 DEFINE_bool(nameByHash, false, |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 107 } | 108 } |
| 108 | 109 |
| 109 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~*/ | 110 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~*/ |
| 110 | 111 |
| 111 template <typename T> | 112 template <typename T> |
| 112 struct Tagged : public SkAutoTDelete<T> { const char* tag; }; | 113 struct Tagged : public SkAutoTDelete<T> { const char* tag; }; |
| 113 | 114 |
| 114 static const bool kMemcpyOK = true; | 115 static const bool kMemcpyOK = true; |
| 115 | 116 |
| 116 static SkTArray<Tagged<Src>, kMemcpyOK> gSrcs; | 117 static SkTArray<Tagged<Src>, kMemcpyOK> gSrcs; |
| 117 static SkTArray<Tagged<Sink>, kMemcpyOK> gSinks; | 118 static SkTArray<Tagged<Sink>, kMemcpyOK> gSinks; |
| 118 | 119 |
| 119 static void push_src(const char* tag, Src* s) { | 120 // SkCodec uses a separate set of srcs and sinks, since we are testing decoding, rather than |
| 121 // drawing. For the same reason, we only want to draw to one particular sink (in particular, | |
| 122 // kN32 for typical decodes - it is important that it accept alpha so images wit h alpha draw | |
| 123 // reasonably; a GPU sink for GPU based decodes (e.g. YUV, not yet tested)). | |
| 124 static SkTArray<Tagged<Src>, kMemcpyOK> gCodecSrcs; | |
| 125 static SkTArray<Tagged<Sink>, kMemcpyOK> gCodecSinks; | |
| 126 | |
| 127 static void push_src(const char* tag, Src* s, SkTArray<Tagged<Src>, kMemcpyOK>* srcList = &gSrcs) { | |
| 120 SkAutoTDelete<Src> src(s); | 128 SkAutoTDelete<Src> src(s); |
| 121 if (FLAGS_src.contains(tag) && | 129 if (FLAGS_src.contains(tag) && |
| 122 !SkCommandLineFlags::ShouldSkip(FLAGS_match, src->name().c_str())) { | 130 !SkCommandLineFlags::ShouldSkip(FLAGS_match, src->name().c_str())) { |
| 123 Tagged<Src>& s = gSrcs.push_back(); | 131 Tagged<Src>& s = srcList->push_back(); |
| 124 s.reset(src.detach()); | 132 s.reset(src.detach()); |
| 125 s.tag = tag; | 133 s.tag = tag; |
| 126 } | 134 } |
| 127 } | 135 } |
| 128 | 136 |
| 137 static void gather_codec_srcs(Path path) { | |
| 138 if (!FLAGS_src.contains("codec")) { | |
| 139 // push_src would skip adding theses sources anyway, but early exit so | |
| 140 // we don't bother checking all combinations. | |
| 141 return; | |
| 142 } | |
| 143 static const SkColorType gDstCTs[] = { | |
| 144 kN32_SkColorType, | |
| 145 kRGB_565_SkColorType, | |
| 146 kAlpha_8_SkColorType | |
| 147 }; | |
| 148 static const SkAlphaType gDstATs[] = { | |
| 149 kOpaque_SkAlphaType, | |
| 150 kPremul_SkAlphaType | |
| 151 // FIXME: Support kUnpremul once that is supported as a source. | |
| 152 //kUnpremul_SkAlphaType | |
| 153 }; | |
| 154 static const CodecSrc::SkipZeroes gSkips[] = { | |
|
mtklein
2015/03/06 00:25:25
Why don't we wait to land these options until the
scroggo
2015/03/06 20:40:26
Sure! I wasn't ready to land this anyway, I just w
| |
| 155 // TODO: Once https://codereview.chromium.org/980903002/ lands, use | |
| 156 // its enum and run while skipping zeroes. | |
| 157 //CodecSrc::kSkipZeroes, | |
| 158 CodecSrc::kNo_SkipZeroes | |
| 159 }; | |
| 160 static const CodecSrc::Scanlines gScanlines[] = { | |
| 161 CodecSrc::kNormal_Scanlines | |
| 162 // TODO: Support other modes | |
| 163 }; | |
| 164 | |
| 165 // Possible alternate approach? | |
| 166 // For an 8888 decode, we attempt all the alpha types, but in reality, two | |
| 167 // is the max for a given image. If we created an SkCodec first, we would | |
| 168 // know whether the image was opaque. If so, we would only need a task to | |
| 169 // decode to kOpaque. Otherwise, we need two tasks: one for kPremul and one | |
| 170 // for kUnpremul. This would mean creating the SkCodec on the main thread, | |
| 171 // but maybe that's a fair tradeoff for spawning less tasks. | |
| 172 for (size_t dstCTs = 0; dstCTs < SK_ARRAY_COUNT(gDstCTs); dstCTs++) { | |
| 173 const SkColorType ct = gDstCTs[dstCTs]; | |
| 174 for (size_t dstATs = 0; dstATs < SK_ARRAY_COUNT(gDstATs); dstATs++) { | |
| 175 const SkAlphaType at = gDstATs[dstATs]; | |
| 176 SkAlphaType canonical; | |
| 177 if (!SkColorTypeValidateAlphaType(ct, at, &canonical) || canonical ! = at) { | |
|
mtklein
2015/03/06 00:25:25
Don't we know ahead of time which pairs will pass
scroggo
2015/03/06 20:40:26
Yes, that will work.
scroggo
2015/03/13 21:34:33
Leaving out for now, since we're using the config
| |
| 178 // This alpha type does not match the color type. Skip it. | |
| 179 continue; | |
| 180 } | |
| 181 for (size_t scanlines = 0; scanlines < SK_ARRAY_COUNT(gScanlines); s canlines++) { | |
| 182 for (size_t skips = 0; skips < SK_ARRAY_COUNT(gSkips); skips++) { | |
| 183 push_src("codec", new CodecSrc(path, ct, at, gSkips[skips], | |
| 184 gScanlines[scanlines]), | |
| 185 &gCodecSrcs); | |
| 186 } | |
| 187 } | |
| 188 } | |
| 189 } | |
| 190 } | |
| 191 | |
| 129 static void gather_srcs() { | 192 static void gather_srcs() { |
| 130 for (const skiagm::GMRegistry* r = skiagm::GMRegistry::Head(); r; r = r->nex t()) { | 193 for (const skiagm::GMRegistry* r = skiagm::GMRegistry::Head(); r; r = r->nex t()) { |
| 131 push_src("gm", new GMSrc(r->factory())); | 194 push_src("gm", new GMSrc(r->factory())); |
| 132 } | 195 } |
| 133 for (int i = 0; i < FLAGS_skps.count(); i++) { | 196 for (int i = 0; i < FLAGS_skps.count(); i++) { |
| 134 const char* path = FLAGS_skps[i]; | 197 const char* path = FLAGS_skps[i]; |
| 135 if (sk_isdir(path)) { | 198 if (sk_isdir(path)) { |
| 136 SkOSFile::Iter it(path, "skp"); | 199 SkOSFile::Iter it(path, "skp"); |
| 137 for (SkString file; it.next(&file); ) { | 200 for (SkString file; it.next(&file); ) { |
| 138 push_src("skp", new SKPSrc(SkOSPath::Join(path, file.c_str()))); | 201 push_src("skp", new SKPSrc(SkOSPath::Join(path, file.c_str()))); |
| 139 } | 202 } |
| 140 } else { | 203 } else { |
| 141 push_src("skp", new SKPSrc(path)); | 204 push_src("skp", new SKPSrc(path)); |
| 142 } | 205 } |
| 143 } | 206 } |
| 144 static const char* const exts[] = { | 207 static const char* const exts[] = { |
| 145 "bmp", "gif", "jpg", "jpeg", "png", "webp", "ktx", "astc", "wbmp", "ico" , | 208 "bmp", "gif", "jpg", "jpeg", "png", "webp", "ktx", "astc", "wbmp", "ico" , |
| 146 "BMP", "GIF", "JPG", "JPEG", "PNG", "WEBP", "KTX", "ASTC", "WBMP", "ICO" , | 209 "BMP", "GIF", "JPG", "JPEG", "PNG", "WEBP", "KTX", "ASTC", "WBMP", "ICO" , |
| 147 }; | 210 }; |
| 148 for (int i = 0; i < FLAGS_images.count(); i++) { | 211 for (int i = 0; i < FLAGS_images.count(); i++) { |
| 149 const char* flag = FLAGS_images[i]; | 212 const char* flag = FLAGS_images[i]; |
| 150 if (sk_isdir(flag)) { | 213 if (sk_isdir(flag)) { |
| 151 for (size_t j = 0; j < SK_ARRAY_COUNT(exts); j++) { | 214 for (size_t j = 0; j < SK_ARRAY_COUNT(exts); j++) { |
| 152 SkOSFile::Iter it(flag, exts[j]); | 215 SkOSFile::Iter it(flag, exts[j]); |
| 153 for (SkString file; it.next(&file); ) { | 216 for (SkString file; it.next(&file); ) { |
| 154 SkString path = SkOSPath::Join(flag, file.c_str()); | 217 SkString path = SkOSPath::Join(flag, file.c_str()); |
| 155 push_src("image", new ImageSrc(path)); // Decode entire image. | 218 push_src("image", new ImageSrc(path)); // Decode entire image. |
| 156 push_src("subset", new ImageSrc(path, 2)); // Decode into 2 x 2 subsets | 219 push_src("subset", new ImageSrc(path, 2)); // Decode into 2 x 2 subsets |
| 220 gather_codec_srcs(path); | |
| 157 } | 221 } |
| 158 } | 222 } |
| 159 } else if (sk_exists(flag)) { | 223 } else if (sk_exists(flag)) { |
| 160 // assume that FLAGS_images[i] is a valid image if it is a file. | 224 // assume that FLAGS_images[i] is a valid image if it is a file. |
| 161 push_src("image", new ImageSrc(flag)); // Decode entire image. | 225 push_src("image", new ImageSrc(flag)); // Decode entire image. |
| 162 push_src("subset", new ImageSrc(flag, 2)); // Decode into 2 x 2 subs ets | 226 push_src("subset", new ImageSrc(flag, 2)); // Decode into 2 x 2 subs ets |
| 227 gather_codec_srcs(flag); | |
| 163 } | 228 } |
| 164 } | 229 } |
| 165 } | 230 } |
| 166 | 231 |
| 167 static GrGLStandard get_gpu_api() { | 232 static GrGLStandard get_gpu_api() { |
| 168 if (FLAGS_gpuAPI.contains("gl")) { return kGL_GrGLStandard; } | 233 if (FLAGS_gpuAPI.contains("gl")) { return kGL_GrGLStandard; } |
| 169 if (FLAGS_gpuAPI.contains("gles")) { return kGLES_GrGLStandard; } | 234 if (FLAGS_gpuAPI.contains("gles")) { return kGLES_GrGLStandard; } |
| 170 return kNone_GrGLStandard; | 235 return kNone_GrGLStandard; |
| 171 } | 236 } |
| 172 | 237 |
| 173 static void push_sink(const char* tag, Sink* s) { | 238 static void push_sink(const char* tag, Sink* s, SkTArray<Tagged<Sink>, |
| 239 kMemcpyOK>* sinksArray = &gSinks) { | |
| 174 SkAutoTDelete<Sink> sink(s); | 240 SkAutoTDelete<Sink> sink(s); |
| 175 if (!FLAGS_config.contains(tag)) { | 241 if (!FLAGS_config.contains(tag) |
| 242 // If we're running codec sources, and we're attempting to push one | |
| 243 // of its sinks, do it whether or not the configs include this sink. | |
| 244 && !(&gCodecSinks == sinksArray && FLAGS_src.contains("codec"))) { | |
| 176 return; | 245 return; |
| 177 } | 246 } |
| 178 // Try a noop Src as a canary. If it fails, skip this sink. | 247 // Try a noop Src as a canary. If it fails, skip this sink. |
| 179 struct : public Src { | 248 struct : public Src { |
| 180 Error draw(SkCanvas*) const SK_OVERRIDE { return ""; } | 249 Error draw(SkCanvas*) const SK_OVERRIDE { return ""; } |
| 181 SkISize size() const SK_OVERRIDE { return SkISize::Make(16, 16); } | 250 SkISize size() const SK_OVERRIDE { return SkISize::Make(16, 16); } |
| 182 Name name() const SK_OVERRIDE { return "noop"; } | 251 Name name() const SK_OVERRIDE { return "noop"; } |
| 183 } noop; | 252 } noop; |
| 184 | 253 |
| 185 SkBitmap bitmap; | 254 SkBitmap bitmap; |
| 186 SkDynamicMemoryWStream stream; | 255 SkDynamicMemoryWStream stream; |
| 187 SkString log; | 256 SkString log; |
| 188 Error err = sink->draw(noop, &bitmap, &stream, &log); | 257 Error err = sink->draw(noop, &bitmap, &stream, &log); |
| 189 if (err.isFatal()) { | 258 if (err.isFatal()) { |
| 190 SkDebugf("Skipping %s: %s\n", tag, err.c_str()); | 259 SkDebugf("Skipping %s: %s\n", tag, err.c_str()); |
| 191 return; | 260 return; |
| 192 } | 261 } |
| 193 | 262 |
| 194 Tagged<Sink>& ts = gSinks.push_back(); | 263 Tagged<Sink>& ts = sinksArray->push_back(); |
| 195 ts.reset(sink.detach()); | 264 ts.reset(sink.detach()); |
| 196 ts.tag = tag; | 265 ts.tag = tag; |
| 197 } | 266 } |
| 198 | 267 |
| 199 static bool gpu_supported() { | 268 static bool gpu_supported() { |
| 200 #if SK_SUPPORT_GPU | 269 #if SK_SUPPORT_GPU |
| 201 return FLAGS_gpu; | 270 return FLAGS_gpu; |
| 202 #else | 271 #else |
| 203 return false; | 272 return false; |
| 204 #endif | 273 #endif |
| (...skipping 318 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 523 if (FLAGS_leaks) { | 592 if (FLAGS_leaks) { |
| 524 SkInstCountPrintLeaksOnExit(); | 593 SkInstCountPrintLeaksOnExit(); |
| 525 } | 594 } |
| 526 | 595 |
| 527 gather_gold(); | 596 gather_gold(); |
| 528 | 597 |
| 529 gather_srcs(); | 598 gather_srcs(); |
| 530 gather_sinks(); | 599 gather_sinks(); |
| 531 gather_tests(); | 600 gather_tests(); |
| 532 | 601 |
| 533 gPending = gSrcs.count() * gSinks.count() + gThreadedTests.count() + gGPUTes ts.count(); | 602 gPending = gSrcs.count() * gSinks.count() + gThreadedTests.count() + gGPUTes ts.count() |
| 534 SkDebugf("%d srcs * %d sinks + %d tests == %d tasks\n", | 603 + gCodecSrcs.count(); |
| 535 gSrcs.count(), gSinks.count(), gThreadedTests.count() + gGPUTests.c ount(), gPending); | 604 SkDebugf("%d srcs * %d sinks + %d tests + %d codecs == %d tasks\n", |
| 605 gSrcs.count(), gSinks.count(), gThreadedTests.count() + gGPUTests.c ount(), | |
| 606 gCodecSrcs.count(), gPending); | |
| 536 | 607 |
| 537 // We try to exploit as much parallelism as is safe. Most Src/Sink pairs ru n on any thread, | 608 // We try to exploit as much parallelism as is safe. Most Src/Sink pairs ru n on any thread, |
| 538 // but Sinks that identify as part of a particular enclave run serially on a single thread. | 609 // but Sinks that identify as part of a particular enclave run serially on a single thread. |
| 539 // CPU tests run on any thread. GPU tests depend on --gpu_threading. | 610 // CPU tests run on any thread. GPU tests depend on --gpu_threading. |
| 540 SkTArray<Task> enclaves[kNumEnclaves]; | 611 SkTArray<Task> enclaves[kNumEnclaves]; |
| 541 for (int j = 0; j < gSinks.count(); j++) { | 612 for (int j = 0; j < gSinks.count(); j++) { |
| 542 SkTArray<Task>& tasks = enclaves[gSinks[j]->enclave()]; | 613 SkTArray<Task>& tasks = enclaves[gSinks[j]->enclave()]; |
| 543 for (int i = 0; i < gSrcs.count(); i++) { | 614 for (int i = 0; i < gSrcs.count(); i++) { |
| 544 tasks.push_back(Task(gSrcs[i], gSinks[j])); | 615 tasks.push_back(Task(gSrcs[i], gSinks[j])); |
| 545 } | 616 } |
| 546 } | 617 } |
| 547 | 618 |
| 619 // All CodecSrcs should run on 8888. | |
| 620 if (gCodecSrcs.count() > 0) { | |
| 621 push_sink("8888", new RasterSink(kN32_SkColorType), &gCodecSinks); | |
| 622 // TODO: Once we start testing GPU decodes, draw to GPU sinks | |
| 623 if (gCodecSinks.count() > 0) { | |
| 624 for (int i = 0; i < gCodecSrcs.count(); i++) { | |
| 625 SkTArray<Task>& tasks = enclaves[gCodecSinks[0]->enclave()]; | |
| 626 tasks.push_back(Task(gCodecSrcs[i], gCodecSinks[0])); | |
| 627 } | |
| 628 } | |
| 629 } | |
| 630 | |
| 548 SkTaskGroup tg; | 631 SkTaskGroup tg; |
| 549 tg.batch(run_test, gThreadedTests.begin(), gThreadedTests.count()); | 632 tg.batch(run_test, gThreadedTests.begin(), gThreadedTests.count()); |
| 550 for (int i = 0; i < kNumEnclaves; i++) { | 633 for (int i = 0; i < kNumEnclaves; i++) { |
| 551 switch(i) { | 634 switch(i) { |
| 552 case kAnyThread_Enclave: | 635 case kAnyThread_Enclave: |
| 553 tg.batch(Task::Run, enclaves[i].begin(), enclaves[i].count()); | 636 tg.batch(Task::Run, enclaves[i].begin(), enclaves[i].count()); |
| 554 break; | 637 break; |
| 555 case kGPU_Enclave: | 638 case kGPU_Enclave: |
| 556 tg.add(run_enclave_and_gpu_tests, &enclaves[i]); | 639 tg.add(run_enclave_and_gpu_tests, &enclaves[i]); |
| 557 break; | 640 break; |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 578 } | 661 } |
| 579 return 0; | 662 return 0; |
| 580 } | 663 } |
| 581 | 664 |
| 582 #if !defined(SK_BUILD_FOR_IOS) && !defined(SK_BUILD_FOR_NACL) | 665 #if !defined(SK_BUILD_FOR_IOS) && !defined(SK_BUILD_FOR_NACL) |
| 583 int main(int argc, char** argv) { | 666 int main(int argc, char** argv) { |
| 584 SkCommandLineFlags::Parse(argc, argv); | 667 SkCommandLineFlags::Parse(argc, argv); |
| 585 return dm_main(); | 668 return dm_main(); |
| 586 } | 669 } |
| 587 #endif | 670 #endif |
| OLD | NEW |