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++) { |