Chromium Code Reviews| Index: dm/DM.cpp |
| diff --git a/dm/DM.cpp b/dm/DM.cpp |
| index 4ab5da975ee7785b2085957ab72e114cc4eac7e5..0b47e0a367a961145e5d5518ddeb5194cdb747ba 100644 |
| --- a/dm/DM.cpp |
| +++ b/dm/DM.cpp |
| @@ -9,6 +9,7 @@ |
| #include "SkCommonFlags.h" |
| #include "SkForceLinking.h" |
| #include "SkGraphics.h" |
| +#include "SkImageInfo.h" |
| #include "SkInstCnt.h" |
| #include "SkMD5.h" |
| #include "SkOSFile.h" |
| @@ -114,18 +115,80 @@ struct Tagged : public SkAutoTDelete<T> { const char* tag; }; |
| static const bool kMemcpyOK = true; |
| static SkTArray<Tagged<Src>, kMemcpyOK> gSrcs; |
| -static SkTArray<Tagged<Sink>, kMemcpyOK> gSinks; |
| +static SkTArray<Tagged<Sink>, kMemcpyOK> gSinks; |
| -static void push_src(const char* tag, Src* s) { |
| +// SkCodec uses a separate set of srcs and sinks, since we are testing decoding, rather than |
| +// drawing. For the same reason, we only want to draw to one particular sink (in particular, |
| +// kN32 for typical decodes - it is important that it accept alpha so images with alpha draw |
| +// reasonably; a GPU sink for GPU based decodes (e.g. YUV, not yet tested)). |
| +static SkTArray<Tagged<Src>, kMemcpyOK> gCodecSrcs; |
| +static SkTArray<Tagged<Sink>, kMemcpyOK> gCodecSinks; |
| + |
| +static void push_src(const char* tag, Src* s, SkTArray<Tagged<Src>, kMemcpyOK>* srcList = &gSrcs) { |
| SkAutoTDelete<Src> src(s); |
| if (FLAGS_src.contains(tag) && |
| !SkCommandLineFlags::ShouldSkip(FLAGS_match, src->name().c_str())) { |
| - Tagged<Src>& s = gSrcs.push_back(); |
| + Tagged<Src>& s = srcList->push_back(); |
| s.reset(src.detach()); |
| s.tag = tag; |
| } |
| } |
| +static void gather_codec_srcs(Path path) { |
| + if (!FLAGS_src.contains("codec")) { |
| + // push_src would skip adding theses sources anyway, but early exit so |
| + // we don't bother checking all combinations. |
| + return; |
| + } |
| + static const SkColorType gDstCTs[] = { |
| + kN32_SkColorType, |
| + kRGB_565_SkColorType, |
| + kAlpha_8_SkColorType |
| + }; |
| + static const SkAlphaType gDstATs[] = { |
| + kOpaque_SkAlphaType, |
| + kPremul_SkAlphaType |
| + // FIXME: Support kUnpremul once that is supported as a source. |
| + //kUnpremul_SkAlphaType |
| + }; |
| + 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
|
| + // TODO: Once https://codereview.chromium.org/980903002/ lands, use |
| + // its enum and run while skipping zeroes. |
| + //CodecSrc::kSkipZeroes, |
| + CodecSrc::kNo_SkipZeroes |
| + }; |
| + static const CodecSrc::Scanlines gScanlines[] = { |
| + CodecSrc::kNormal_Scanlines |
| + // TODO: Support other modes |
| + }; |
| + |
| + // Possible alternate approach? |
| + // For an 8888 decode, we attempt all the alpha types, but in reality, two |
| + // is the max for a given image. If we created an SkCodec first, we would |
| + // know whether the image was opaque. If so, we would only need a task to |
| + // decode to kOpaque. Otherwise, we need two tasks: one for kPremul and one |
| + // for kUnpremul. This would mean creating the SkCodec on the main thread, |
| + // but maybe that's a fair tradeoff for spawning less tasks. |
| + for (size_t dstCTs = 0; dstCTs < SK_ARRAY_COUNT(gDstCTs); dstCTs++) { |
| + const SkColorType ct = gDstCTs[dstCTs]; |
| + for (size_t dstATs = 0; dstATs < SK_ARRAY_COUNT(gDstATs); dstATs++) { |
| + const SkAlphaType at = gDstATs[dstATs]; |
| + SkAlphaType canonical; |
| + 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
|
| + // This alpha type does not match the color type. Skip it. |
| + continue; |
| + } |
| + for (size_t scanlines = 0; scanlines < SK_ARRAY_COUNT(gScanlines); scanlines++) { |
| + for (size_t skips = 0; skips < SK_ARRAY_COUNT(gSkips); skips++) { |
| + push_src("codec", new CodecSrc(path, ct, at, gSkips[skips], |
| + gScanlines[scanlines]), |
| + &gCodecSrcs); |
| + } |
| + } |
| + } |
| + } |
| +} |
| + |
| static void gather_srcs() { |
| for (const skiagm::GMRegistry* r = skiagm::GMRegistry::Head(); r; r = r->next()) { |
| push_src("gm", new GMSrc(r->factory())); |
| @@ -154,12 +217,14 @@ static void gather_srcs() { |
| SkString path = SkOSPath::Join(flag, file.c_str()); |
| push_src("image", new ImageSrc(path)); // Decode entire image. |
| push_src("subset", new ImageSrc(path, 2)); // Decode into 2 x 2 subsets |
| + gather_codec_srcs(path); |
| } |
| } |
| } else if (sk_exists(flag)) { |
| // assume that FLAGS_images[i] is a valid image if it is a file. |
| push_src("image", new ImageSrc(flag)); // Decode entire image. |
| push_src("subset", new ImageSrc(flag, 2)); // Decode into 2 x 2 subsets |
| + gather_codec_srcs(flag); |
| } |
| } |
| } |
| @@ -170,9 +235,13 @@ static GrGLStandard get_gpu_api() { |
| return kNone_GrGLStandard; |
| } |
| -static void push_sink(const char* tag, Sink* s) { |
| +static void push_sink(const char* tag, Sink* s, SkTArray<Tagged<Sink>, |
| + kMemcpyOK>* sinksArray = &gSinks) { |
| SkAutoTDelete<Sink> sink(s); |
| - if (!FLAGS_config.contains(tag)) { |
| + if (!FLAGS_config.contains(tag) |
| + // If we're running codec sources, and we're attempting to push one |
| + // of its sinks, do it whether or not the configs include this sink. |
| + && !(&gCodecSinks == sinksArray && FLAGS_src.contains("codec"))) { |
| return; |
| } |
| // Try a noop Src as a canary. If it fails, skip this sink. |
| @@ -191,7 +260,7 @@ static void push_sink(const char* tag, Sink* s) { |
| return; |
| } |
| - Tagged<Sink>& ts = gSinks.push_back(); |
| + Tagged<Sink>& ts = sinksArray->push_back(); |
| ts.reset(sink.detach()); |
| ts.tag = tag; |
| } |
| @@ -530,9 +599,11 @@ int dm_main() { |
| gather_sinks(); |
| gather_tests(); |
| - gPending = gSrcs.count() * gSinks.count() + gThreadedTests.count() + gGPUTests.count(); |
| - SkDebugf("%d srcs * %d sinks + %d tests == %d tasks\n", |
| - gSrcs.count(), gSinks.count(), gThreadedTests.count() + gGPUTests.count(), gPending); |
| + gPending = gSrcs.count() * gSinks.count() + gThreadedTests.count() + gGPUTests.count() |
| + + gCodecSrcs.count(); |
| + SkDebugf("%d srcs * %d sinks + %d tests + %d codecs == %d tasks\n", |
| + gSrcs.count(), gSinks.count(), gThreadedTests.count() + gGPUTests.count(), |
| + gCodecSrcs.count(), gPending); |
| // We try to exploit as much parallelism as is safe. Most Src/Sink pairs run on any thread, |
| // but Sinks that identify as part of a particular enclave run serially on a single thread. |
| @@ -545,6 +616,18 @@ int dm_main() { |
| } |
| } |
| + // All CodecSrcs should run on 8888. |
| + if (gCodecSrcs.count() > 0) { |
| + push_sink("8888", new RasterSink(kN32_SkColorType), &gCodecSinks); |
| + // TODO: Once we start testing GPU decodes, draw to GPU sinks |
| + if (gCodecSinks.count() > 0) { |
| + for (int i = 0; i < gCodecSrcs.count(); i++) { |
| + SkTArray<Task>& tasks = enclaves[gCodecSinks[0]->enclave()]; |
| + tasks.push_back(Task(gCodecSrcs[i], gCodecSinks[0])); |
| + } |
| + } |
| + } |
| + |
| SkTaskGroup tg; |
| tg.batch(run_test, gThreadedTests.begin(), gThreadedTests.count()); |
| for (int i = 0; i < kNumEnclaves; i++) { |