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 |