1478652e918d73a4c0330e27e03eaa9564138c0f7scroggo/*
2478652e918d73a4c0330e27e03eaa9564138c0f7scroggo * Copyright 2013 Google Inc.
3478652e918d73a4c0330e27e03eaa9564138c0f7scroggo *
4478652e918d73a4c0330e27e03eaa9564138c0f7scroggo * Use of this source code is governed by a BSD-style license that can be
5478652e918d73a4c0330e27e03eaa9564138c0f7scroggo * found in the LICENSE file.
6478652e918d73a4c0330e27e03eaa9564138c0f7scroggo */
7478652e918d73a4c0330e27e03eaa9564138c0f7scroggo
83b27adef0a52f6d321fdee7412ef69e7a7284bccjcgregorio#include "CrashHandler.h"
9748ca3bf2d170708f263693e8579e6722389d0efmtklein#include "DMJsonWriter.h"
10748ca3bf2d170708f263693e8579e6722389d0efmtklein#include "DMSrcSink.h"
11eebc39ad5a1dcbde1b10a9b2ab54679549522b52tomhudson#include "DMSrcSinkAndroid.h"
12748ca3bf2d170708f263693e8579e6722389d0efmtklein#include "OverwriteLine.h"
13748ca3bf2d170708f263693e8579e6722389d0efmtklein#include "ProcStats.h"
14748ca3bf2d170708f263693e8579e6722389d0efmtklein#include "SkBBHFactory.h"
1562bd1a69ea49318aa5022151262c842887e0ecf4mtklein#include "SkChecksum.h"
1617f0b6df7248b9bbdaddacc3a6c9c6efe4ae278ecaryclark#include "SkCommonFlags.h"
17d36522d12d3e71958e50683a7eef43dc2a47d96dmtklein@google.com#include "SkForceLinking.h"
18d36522d12d3e71958e50683a7eef43dc2a47d96dmtklein@google.com#include "SkGraphics.h"
19e67164d9b3a0fcc5f7d2a4149041284f7cde31b9mtklein#include "SkInstCnt.h"
20748ca3bf2d170708f263693e8579e6722389d0efmtklein#include "SkMD5.h"
211d0f1642e8bc0fda200972926e2eaa99744e4d93mtklein#include "SkOSFile.h"
22a82f562725cc7309fa158f04d4faa9859be318f5mtklein#include "SkTHash.h"
23406654be7a930b484159f5bca107d3b11d8a9edemtklein#include "SkTaskGroup.h"
24de6fc2bf464b734f35449c40421064b33cd9e2b4mtklein#include "SkThreadUtils.h"
250dc5bd149a8b69e8dc6d3b4713b827659c9b0a6bcommit-bot@chromium.org#include "Test.h"
26748ca3bf2d170708f263693e8579e6722389d0efmtklein#include "Timer.h"
2730bf3e2ffcb78fc76e5a62b2ca67638e0411cba9mtklein
2854416de52381ac11dd755100a8025debf595873adjsollenDEFINE_string(src, "tests gm skp image", "Source types to test.");
29748ca3bf2d170708f263693e8579e6722389d0efmtkleinDEFINE_bool(nameByHash, false,
30748ca3bf2d170708f263693e8579e6722389d0efmtklein            "If true, write to FLAGS_writePath[0]/<hash>.png instead of "
3154416de52381ac11dd755100a8025debf595873adjsollen            "to FLAGS_writePath[0]/<config>/<sourceType>/<sourceOptions>/<name>.png");
32748ca3bf2d170708f263693e8579e6722389d0efmtkleinDEFINE_bool2(pathOpsExtended, x, false, "Run extended pathOps tests.");
33d603b22903bf7c023226bf52bd7c1f49a9bee1bfmtkleinDEFINE_string(matrix, "1 0 0 1",
34d603b22903bf7c023226bf52bd7c1f49a9bee1bfmtklein              "2x2 scale+skew matrix to apply or upright when using "
35d603b22903bf7c023226bf52bd7c1f49a9bee1bfmtklein              "'matrix' or 'upright' in config.");
3682d2843cc59dc048b7d8d1d928dab743d8e85a3bmtkleinDEFINE_bool(gpu_threading, false, "Allow GPU work to run on multiple threads?");
37d36522d12d3e71958e50683a7eef43dc2a47d96dmtklein@google.com
38a2ef642b00fdd58512b0889d12796d963a27f739mtkleinDEFINE_string(blacklist, "",
3954416de52381ac11dd755100a8025debf595873adjsollen        "Space-separated config/src/srcOptions/name quadruples to blacklist.  '_' matches anything.  E.g. \n"
4054416de52381ac11dd755100a8025debf595873adjsollen        "'--blacklist gpu skp _ _' will blacklist all SKPs drawn into the gpu config.\n"
4154416de52381ac11dd755100a8025debf595873adjsollen        "'--blacklist gpu skp _ _ 8888 gm _ aarects' will also blacklist the aarects GM on 8888.");
42a2ef642b00fdd58512b0889d12796d963a27f739mtklein
4362bd1a69ea49318aa5022151262c842887e0ecf4mtkleinDEFINE_string2(readPath, r, "", "If set check for equality with golden results in this directory.");
4462bd1a69ea49318aa5022151262c842887e0ecf4mtklein
4509ed480906881b6f84bb28c772786928ba3a59d6borenetDEFINE_string(uninterestingHashesFile, "",
4609ed480906881b6f84bb28c772786928ba3a59d6borenet        "File containing a list of uninteresting hashes. If a result hashes to something in "
4709ed480906881b6f84bb28c772786928ba3a59d6borenet        "this list, no image is written for that result.");
4809ed480906881b6f84bb28c772786928ba3a59d6borenet
496393c0653e5338a093c3908a410bdfd2ea1bdcabmtkleinDEFINE_int32(shards, 1, "We're splitting source data into this many shards.");
506393c0653e5338a093c3908a410bdfd2ea1bdcabmtkleinDEFINE_int32(shard,  0, "Which shard do I run?");
516393c0653e5338a093c3908a410bdfd2ea1bdcabmtklein
52748ca3bf2d170708f263693e8579e6722389d0efmtklein__SK_FORCE_IMAGE_DECODER_LINKING;
53748ca3bf2d170708f263693e8579e6722389d0efmtkleinusing namespace DM;
54d36522d12d3e71958e50683a7eef43dc2a47d96dmtklein@google.com
55748ca3bf2d170708f263693e8579e6722389d0efmtklein/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
5680549fcdd50269d7e069d6db02b395fca128056ckkinnunen
57748ca3bf2d170708f263693e8579e6722389d0efmtkleinSK_DECLARE_STATIC_MUTEX(gFailuresMutex);
58748ca3bf2d170708f263693e8579e6722389d0efmtkleinstatic SkTArray<SkString> gFailures;
59d36522d12d3e71958e50683a7eef43dc2a47d96dmtklein@google.com
60748ca3bf2d170708f263693e8579e6722389d0efmtkleinstatic void fail(ImplicitString err) {
61748ca3bf2d170708f263693e8579e6722389d0efmtklein    SkAutoMutexAcquire lock(gFailuresMutex);
62748ca3bf2d170708f263693e8579e6722389d0efmtklein    SkDebugf("\n\nFAILURE: %s\n\n", err.c_str());
63748ca3bf2d170708f263693e8579e6722389d0efmtklein    gFailures.push_back(err);
64748ca3bf2d170708f263693e8579e6722389d0efmtklein}
65d36522d12d3e71958e50683a7eef43dc2a47d96dmtklein@google.com
66b37cb41a8bfc1bdf65fb8387c24d45da7cf8b7damtkleinstatic int32_t gPending = 0;  // Atomic.  Total number of running and queued tasks.
67b37cb41a8bfc1bdf65fb8387c24d45da7cf8b7damtklein
68b37cb41a8bfc1bdf65fb8387c24d45da7cf8b7damtkleinSK_DECLARE_STATIC_MUTEX(gRunningMutex);
69b37cb41a8bfc1bdf65fb8387c24d45da7cf8b7damtkleinstatic SkTArray<SkString> gRunning;
70748ca3bf2d170708f263693e8579e6722389d0efmtklein
71b9eb4ac0f1c29d6fe10ad7ff81ed8326ac1ea043mtkleinstatic void done(double ms,
7254416de52381ac11dd755100a8025debf595873adjsollen                 ImplicitString config, ImplicitString src, ImplicitString srcOptions,
7354416de52381ac11dd755100a8025debf595873adjsollen                 ImplicitString name, ImplicitString note, ImplicitString log) {
7454416de52381ac11dd755100a8025debf595873adjsollen    SkString id = SkStringPrintf("%s %s %s %s", config.c_str(), src.c_str(),
7554416de52381ac11dd755100a8025debf595873adjsollen                                                srcOptions.c_str(), name.c_str());
76b37cb41a8bfc1bdf65fb8387c24d45da7cf8b7damtklein    {
77b37cb41a8bfc1bdf65fb8387c24d45da7cf8b7damtklein        SkAutoMutexAcquire lock(gRunningMutex);
78b37cb41a8bfc1bdf65fb8387c24d45da7cf8b7damtklein        for (int i = 0; i < gRunning.count(); i++) {
79b37cb41a8bfc1bdf65fb8387c24d45da7cf8b7damtklein            if (gRunning[i] == id) {
80b37cb41a8bfc1bdf65fb8387c24d45da7cf8b7damtklein                gRunning.removeShuffle(i);
81b37cb41a8bfc1bdf65fb8387c24d45da7cf8b7damtklein                break;
82b37cb41a8bfc1bdf65fb8387c24d45da7cf8b7damtklein            }
83b37cb41a8bfc1bdf65fb8387c24d45da7cf8b7damtklein        }
84b37cb41a8bfc1bdf65fb8387c24d45da7cf8b7damtklein    }
85b37cb41a8bfc1bdf65fb8387c24d45da7cf8b7damtklein    if (!FLAGS_verbose) {
86b37cb41a8bfc1bdf65fb8387c24d45da7cf8b7damtklein        note = "";
87b37cb41a8bfc1bdf65fb8387c24d45da7cf8b7damtklein    }
88b9eb4ac0f1c29d6fe10ad7ff81ed8326ac1ea043mtklein    if (!log.isEmpty()) {
89b9eb4ac0f1c29d6fe10ad7ff81ed8326ac1ea043mtklein        log.prepend("\n");
90b9eb4ac0f1c29d6fe10ad7ff81ed8326ac1ea043mtklein    }
916dee2ad388152cd960253021009f109d45db1fe4mtklein    auto pending = sk_atomic_dec(&gPending)-1;
92d75c466ef57ef4dbdf96390b2c01121e4de36f23mtklein    SkDebugf("%s(%4d/%-4dMB %5d) %s\t%s%s%s", FLAGS_verbose ? "\n" : kSkOverwriteLine
93d75c466ef57ef4dbdf96390b2c01121e4de36f23mtklein                                       , sk_tools::getCurrResidentSetSizeMB()
94d75c466ef57ef4dbdf96390b2c01121e4de36f23mtklein                                       , sk_tools::getMaxResidentSetSizeMB()
95b37cb41a8bfc1bdf65fb8387c24d45da7cf8b7damtklein                                       , pending
96b37cb41a8bfc1bdf65fb8387c24d45da7cf8b7damtklein                                       , HumanizeMs(ms).c_str()
97b37cb41a8bfc1bdf65fb8387c24d45da7cf8b7damtklein                                       , id.c_str()
98b37cb41a8bfc1bdf65fb8387c24d45da7cf8b7damtklein                                       , note.c_str()
99b37cb41a8bfc1bdf65fb8387c24d45da7cf8b7damtklein                                       , log.c_str());
100a17241bd0a59efd6c30a007db8f10274b8f80f26mtklein    // We write our dm.json file every once in a while in case we crash.
101a17241bd0a59efd6c30a007db8f10274b8f80f26mtklein    // Notice this also handles the final dm.json when pending == 0.
102a17241bd0a59efd6c30a007db8f10274b8f80f26mtklein    if (pending % 500 == 0) {
103a17241bd0a59efd6c30a007db8f10274b8f80f26mtklein        JsonWriter::DumpJson();
104a17241bd0a59efd6c30a007db8f10274b8f80f26mtklein    }
1059e398f79c95640359847a153f53f30a2823be40chalcanary}
1069e398f79c95640359847a153f53f30a2823be40chalcanary
10754416de52381ac11dd755100a8025debf595873adjsollenstatic void start(ImplicitString config, ImplicitString src,
10854416de52381ac11dd755100a8025debf595873adjsollen                  ImplicitString srcOptions, ImplicitString name) {
10954416de52381ac11dd755100a8025debf595873adjsollen    SkString id = SkStringPrintf("%s %s %s %s", config.c_str(), src.c_str(),
11054416de52381ac11dd755100a8025debf595873adjsollen                                                srcOptions.c_str(), name.c_str());
111b37cb41a8bfc1bdf65fb8387c24d45da7cf8b7damtklein    SkAutoMutexAcquire lock(gRunningMutex);
112b37cb41a8bfc1bdf65fb8387c24d45da7cf8b7damtklein    gRunning.push_back(id);
113b37cb41a8bfc1bdf65fb8387c24d45da7cf8b7damtklein}
114b37cb41a8bfc1bdf65fb8387c24d45da7cf8b7damtklein
115748ca3bf2d170708f263693e8579e6722389d0efmtklein/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
116748ca3bf2d170708f263693e8579e6722389d0efmtklein
11762bd1a69ea49318aa5022151262c842887e0ecf4mtkleinstruct Gold : public SkString {
118a82f562725cc7309fa158f04d4faa9859be318f5mtklein    Gold() : SkString("") {}
11954416de52381ac11dd755100a8025debf595873adjsollen    Gold(ImplicitString sink, ImplicitString src, ImplicitString srcOptions,
12054416de52381ac11dd755100a8025debf595873adjsollen         ImplicitString name, ImplicitString md5)
12162bd1a69ea49318aa5022151262c842887e0ecf4mtklein        : SkString("") {
12262bd1a69ea49318aa5022151262c842887e0ecf4mtklein        this->append(sink);
12362bd1a69ea49318aa5022151262c842887e0ecf4mtklein        this->append(src);
12454416de52381ac11dd755100a8025debf595873adjsollen        this->append(srcOptions);
12562bd1a69ea49318aa5022151262c842887e0ecf4mtklein        this->append(name);
12662bd1a69ea49318aa5022151262c842887e0ecf4mtklein        this->append(md5);
12762bd1a69ea49318aa5022151262c842887e0ecf4mtklein    }
12802f46cf878535fb79317d15ebed66dfa3f2cd772mtklein    static uint32_t Hash(const Gold& g) { return SkGoodHash((const SkString&)g); }
12962bd1a69ea49318aa5022151262c842887e0ecf4mtklein};
130a82f562725cc7309fa158f04d4faa9859be318f5mtkleinstatic SkTHashSet<Gold, Gold::Hash> gGold;
13162bd1a69ea49318aa5022151262c842887e0ecf4mtklein
13262bd1a69ea49318aa5022151262c842887e0ecf4mtkleinstatic void add_gold(JsonWriter::BitmapResult r) {
13354416de52381ac11dd755100a8025debf595873adjsollen    gGold.add(Gold(r.config, r.sourceType, r.sourceOptions, r.name, r.md5));
13462bd1a69ea49318aa5022151262c842887e0ecf4mtklein}
13562bd1a69ea49318aa5022151262c842887e0ecf4mtklein
13662bd1a69ea49318aa5022151262c842887e0ecf4mtkleinstatic void gather_gold() {
13762bd1a69ea49318aa5022151262c842887e0ecf4mtklein    if (!FLAGS_readPath.isEmpty()) {
13862bd1a69ea49318aa5022151262c842887e0ecf4mtklein        SkString path(FLAGS_readPath[0]);
13962bd1a69ea49318aa5022151262c842887e0ecf4mtklein        path.append("/dm.json");
14062bd1a69ea49318aa5022151262c842887e0ecf4mtklein        if (!JsonWriter::ReadJson(path.c_str(), add_gold)) {
14162bd1a69ea49318aa5022151262c842887e0ecf4mtklein            fail(SkStringPrintf("Couldn't read %s for golden results.", path.c_str()));
14262bd1a69ea49318aa5022151262c842887e0ecf4mtklein        }
14362bd1a69ea49318aa5022151262c842887e0ecf4mtklein    }
14462bd1a69ea49318aa5022151262c842887e0ecf4mtklein}
14562bd1a69ea49318aa5022151262c842887e0ecf4mtklein
14662bd1a69ea49318aa5022151262c842887e0ecf4mtklein/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
14762bd1a69ea49318aa5022151262c842887e0ecf4mtklein
14809ed480906881b6f84bb28c772786928ba3a59d6borenetstatic SkTHashSet<SkString> gUninterestingHashes;
14909ed480906881b6f84bb28c772786928ba3a59d6borenet
15009ed480906881b6f84bb28c772786928ba3a59d6borenetstatic void gather_uninteresting_hashes() {
15109ed480906881b6f84bb28c772786928ba3a59d6borenet    if (!FLAGS_uninterestingHashesFile.isEmpty()) {
15209ed480906881b6f84bb28c772786928ba3a59d6borenet        SkAutoTUnref<SkData> data(SkData::NewFromFileName(FLAGS_uninterestingHashesFile[0]));
15309ed480906881b6f84bb28c772786928ba3a59d6borenet        SkTArray<SkString> hashes;
15409ed480906881b6f84bb28c772786928ba3a59d6borenet        SkStrSplit((const char*)data->data(), "\n", &hashes);
15509ed480906881b6f84bb28c772786928ba3a59d6borenet        for (const SkString& hash : hashes) {
15609ed480906881b6f84bb28c772786928ba3a59d6borenet            gUninterestingHashes.add(hash);
15709ed480906881b6f84bb28c772786928ba3a59d6borenet        }
15809ed480906881b6f84bb28c772786928ba3a59d6borenet    }
15909ed480906881b6f84bb28c772786928ba3a59d6borenet}
16009ed480906881b6f84bb28c772786928ba3a59d6borenet
16109ed480906881b6f84bb28c772786928ba3a59d6borenet/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
16209ed480906881b6f84bb28c772786928ba3a59d6borenet
163748ca3bf2d170708f263693e8579e6722389d0efmtkleintemplate <typename T>
16454416de52381ac11dd755100a8025debf595873adjsollenstruct Tagged : public SkAutoTDelete<T> {
16554416de52381ac11dd755100a8025debf595873adjsollen  const char* tag;
16654416de52381ac11dd755100a8025debf595873adjsollen  const char* options;
16754416de52381ac11dd755100a8025debf595873adjsollen};
168748ca3bf2d170708f263693e8579e6722389d0efmtklein
169748ca3bf2d170708f263693e8579e6722389d0efmtkleinstatic const bool kMemcpyOK = true;
170748ca3bf2d170708f263693e8579e6722389d0efmtklein
171748ca3bf2d170708f263693e8579e6722389d0efmtkleinstatic SkTArray<Tagged<Src>,  kMemcpyOK>  gSrcs;
172748ca3bf2d170708f263693e8579e6722389d0efmtkleinstatic SkTArray<Tagged<Sink>, kMemcpyOK> gSinks;
173748ca3bf2d170708f263693e8579e6722389d0efmtklein
1746393c0653e5338a093c3908a410bdfd2ea1bdcabmtkleinstatic bool in_shard() {
1756393c0653e5338a093c3908a410bdfd2ea1bdcabmtklein    static int N = 0;
1766393c0653e5338a093c3908a410bdfd2ea1bdcabmtklein    return N++ % FLAGS_shards == FLAGS_shard;
1776393c0653e5338a093c3908a410bdfd2ea1bdcabmtklein}
1786393c0653e5338a093c3908a410bdfd2ea1bdcabmtklein
17954416de52381ac11dd755100a8025debf595873adjsollenstatic void push_src(const char* tag, const char* options, Src* s) {
180748ca3bf2d170708f263693e8579e6722389d0efmtklein    SkAutoTDelete<Src> src(s);
1816393c0653e5338a093c3908a410bdfd2ea1bdcabmtklein    if (in_shard() &&
1826393c0653e5338a093c3908a410bdfd2ea1bdcabmtklein        FLAGS_src.contains(tag) &&
183748ca3bf2d170708f263693e8579e6722389d0efmtklein        !SkCommandLineFlags::ShouldSkip(FLAGS_match, src->name().c_str())) {
184748ca3bf2d170708f263693e8579e6722389d0efmtklein        Tagged<Src>& s = gSrcs.push_back();
185748ca3bf2d170708f263693e8579e6722389d0efmtklein        s.reset(src.detach());
186748ca3bf2d170708f263693e8579e6722389d0efmtklein        s.tag = tag;
18754416de52381ac11dd755100a8025debf595873adjsollen        s.options = options;
188d36522d12d3e71958e50683a7eef43dc2a47d96dmtklein@google.com    }
189d36522d12d3e71958e50683a7eef43dc2a47d96dmtklein@google.com}
190d36522d12d3e71958e50683a7eef43dc2a47d96dmtklein@google.com
191438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarettstatic void push_codec_srcs(Path path) {
192438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett    SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(path.c_str()));
193438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett    if (!encoded) {
194438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett        SkDebugf("Couldn't read %s.", path.c_str());
195438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett        return;
196438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett    }
197438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett    SkAutoTDelete<SkCodec> codec(SkCodec::NewFromData(encoded));
198438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett    if (NULL == codec.get()) {
199438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett        SkDebugf("Couldn't create codec for %s.", path.c_str());
200438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett        return;
201438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett    }
202438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett
203438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett    // Build additional test cases for images that decode natively to non-canvas types
204438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett    switch(codec->getInfo().colorType()) {
205438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett        case kGray_8_SkColorType:
206a669bc37c613a18a07a879eb791253e5246f455adjsollen            push_src("image", "codec_kGray8", new CodecSrc(path, CodecSrc::kNormal_Mode,
207438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett                    CodecSrc::kGrayscale_Always_DstColorType));
208a669bc37c613a18a07a879eb791253e5246f455adjsollen            push_src("image", "scanline_kGray8", new CodecSrc(path, CodecSrc::kScanline_Mode,
209438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett                    CodecSrc::kGrayscale_Always_DstColorType));
210438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett            // Intentional fall through
211438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett            // FIXME: Is this a long term solution for testing wbmps decodes to kIndex8?
212438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett            // Further discussion on this topic is at skbug.com/3683
213438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett      case kIndex_8_SkColorType:
214a669bc37c613a18a07a879eb791253e5246f455adjsollen          push_src("image", "codec_kIndex8", new CodecSrc(path, CodecSrc::kNormal_Mode,
215438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett                  CodecSrc::kIndex8_Always_DstColorType));
2169e43cabaa1ff26167e990f0bcb9a5c20d662d52cmsarett          push_src("image", "scanline_kIndex8", new CodecSrc(path, CodecSrc::kScanline_Mode,
2179e43cabaa1ff26167e990f0bcb9a5c20d662d52cmsarett                  CodecSrc::kIndex8_Always_DstColorType));
218438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett        break;
219438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett      default:
220438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett        // Do nothing
221438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett        break;
222438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett    }
223438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett
224438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett    // Decode all images to the canvas color type
225438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett    push_src("image", "codec", new CodecSrc(path, CodecSrc::kNormal_Mode,
226438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett            CodecSrc::kGetFromCanvas_DstColorType));
227438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett    push_src("image", "scanline", new CodecSrc(path, CodecSrc::kScanline_Mode,
228438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett            CodecSrc::kGetFromCanvas_DstColorType));
229438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett}
230438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett
2319b77ddde08efe702256355a333cf31ade8f15bb0scroggostatic bool codec_supported(const char* ext) {
2329b77ddde08efe702256355a333cf31ade8f15bb0scroggo    // FIXME: Once other versions of SkCodec are available, we can add them to this
2339b77ddde08efe702256355a333cf31ade8f15bb0scroggo    // list (and eventually we can remove this check once they are all supported).
2348c8f22a3bba18edaad41d6ac8451a77aa093a958msarett    static const char* const exts[] = {
235e16b04aa6041efb6507546547737e9603fa1606emsarett        "bmp", "gif", "jpg", "jpeg", "png", "ico", "wbmp",
236e16b04aa6041efb6507546547737e9603fa1606emsarett        "BMP", "GIF", "JPG", "JPEG", "PNG", "ICO", "WBMP"
2378c8f22a3bba18edaad41d6ac8451a77aa093a958msarett    };
2388c8f22a3bba18edaad41d6ac8451a77aa093a958msarett
2398c8f22a3bba18edaad41d6ac8451a77aa093a958msarett    for (uint32_t i = 0; i < SK_ARRAY_COUNT(exts); i++) {
2408c8f22a3bba18edaad41d6ac8451a77aa093a958msarett        if (0 == strcmp(exts[i], ext)) {
2418c8f22a3bba18edaad41d6ac8451a77aa093a958msarett            return true;
2428c8f22a3bba18edaad41d6ac8451a77aa093a958msarett        }
2438c8f22a3bba18edaad41d6ac8451a77aa093a958msarett    }
2448c8f22a3bba18edaad41d6ac8451a77aa093a958msarett    return false;
2459b77ddde08efe702256355a333cf31ade8f15bb0scroggo}
2469b77ddde08efe702256355a333cf31ade8f15bb0scroggo
247748ca3bf2d170708f263693e8579e6722389d0efmtkleinstatic void gather_srcs() {
248748ca3bf2d170708f263693e8579e6722389d0efmtklein    for (const skiagm::GMRegistry* r = skiagm::GMRegistry::Head(); r; r = r->next()) {
24954416de52381ac11dd755100a8025debf595873adjsollen        push_src("gm", "", new GMSrc(r->factory()));
250d36522d12d3e71958e50683a7eef43dc2a47d96dmtklein@google.com    }
251fc37ad168090637973bf21452aa2685cfcbb273chalcanary    for (int i = 0; i < FLAGS_skps.count(); i++) {
252fc37ad168090637973bf21452aa2685cfcbb273chalcanary        const char* path = FLAGS_skps[i];
253fc37ad168090637973bf21452aa2685cfcbb273chalcanary        if (sk_isdir(path)) {
254fc37ad168090637973bf21452aa2685cfcbb273chalcanary            SkOSFile::Iter it(path, "skp");
255fc37ad168090637973bf21452aa2685cfcbb273chalcanary            for (SkString file; it.next(&file); ) {
25654416de52381ac11dd755100a8025debf595873adjsollen                push_src("skp", "", new SKPSrc(SkOSPath::Join(path, file.c_str())));
257fc37ad168090637973bf21452aa2685cfcbb273chalcanary            }
258fc37ad168090637973bf21452aa2685cfcbb273chalcanary        } else {
25954416de52381ac11dd755100a8025debf595873adjsollen            push_src("skp", "", new SKPSrc(path));
260ef57b7e65330d5f794a513630517907500f1c1d0commit-bot@chromium.org        }
2610dc5bd149a8b69e8dc6d3b4713b827659c9b0a6bcommit-bot@chromium.org    }
26223b03c3c5a79d624c12bd1af5d11ba87967c53e2halcanary    static const char* const exts[] = {
26323b03c3c5a79d624c12bd1af5d11ba87967c53e2halcanary        "bmp", "gif", "jpg", "jpeg", "png", "webp", "ktx", "astc", "wbmp", "ico",
26423b03c3c5a79d624c12bd1af5d11ba87967c53e2halcanary        "BMP", "GIF", "JPG", "JPEG", "PNG", "WEBP", "KTX", "ASTC", "WBMP", "ICO",
26523b03c3c5a79d624c12bd1af5d11ba87967c53e2halcanary    };
26623b03c3c5a79d624c12bd1af5d11ba87967c53e2halcanary    for (int i = 0; i < FLAGS_images.count(); i++) {
26723b03c3c5a79d624c12bd1af5d11ba87967c53e2halcanary        const char* flag = FLAGS_images[i];
26823b03c3c5a79d624c12bd1af5d11ba87967c53e2halcanary        if (sk_isdir(flag)) {
26923b03c3c5a79d624c12bd1af5d11ba87967c53e2halcanary            for (size_t j = 0; j < SK_ARRAY_COUNT(exts); j++) {
27023b03c3c5a79d624c12bd1af5d11ba87967c53e2halcanary                SkOSFile::Iter it(flag, exts[j]);
27123b03c3c5a79d624c12bd1af5d11ba87967c53e2halcanary                for (SkString file; it.next(&file); ) {
27223b03c3c5a79d624c12bd1af5d11ba87967c53e2halcanary                    SkString path = SkOSPath::Join(flag, file.c_str());
27354416de52381ac11dd755100a8025debf595873adjsollen                    push_src("image", "decode", new ImageSrc(path)); // Decode entire image
27454416de52381ac11dd755100a8025debf595873adjsollen                    push_src("image", "subset", new ImageSrc(path, 2)); // Decode into 2x2 subsets
2759b77ddde08efe702256355a333cf31ade8f15bb0scroggo                    if (codec_supported(exts[j])) {
276438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett                        push_codec_srcs(path);
2779b77ddde08efe702256355a333cf31ade8f15bb0scroggo                    }
27823b03c3c5a79d624c12bd1af5d11ba87967c53e2halcanary                }
279748ca3bf2d170708f263693e8579e6722389d0efmtklein            }
28023b03c3c5a79d624c12bd1af5d11ba87967c53e2halcanary        } else if (sk_exists(flag)) {
28123b03c3c5a79d624c12bd1af5d11ba87967c53e2halcanary            // assume that FLAGS_images[i] is a valid image if it is a file.
28254416de52381ac11dd755100a8025debf595873adjsollen            push_src("image", "decode", new ImageSrc(flag)); // Decode entire image.
28354416de52381ac11dd755100a8025debf595873adjsollen            push_src("image", "subset", new ImageSrc(flag, 2)); // Decode into 2 x 2 subsets
284438b2adefb9e9213e0ddaf0609405d3087a1cf0amsarett            push_codec_srcs(flag);
285114c3cd0543d77aa0ac08d8af436ac7f9d32714dmtklein        }
286114c3cd0543d77aa0ac08d8af436ac7f9d32714dmtklein    }
287709d2c3e5062c5b57f91273bfc11a751f5b2bb88mtklein}
288709d2c3e5062c5b57f91273bfc11a751f5b2bb88mtklein
289748ca3bf2d170708f263693e8579e6722389d0efmtkleinstatic GrGLStandard get_gpu_api() {
290748ca3bf2d170708f263693e8579e6722389d0efmtklein    if (FLAGS_gpuAPI.contains("gl"))   { return kGL_GrGLStandard; }
291748ca3bf2d170708f263693e8579e6722389d0efmtklein    if (FLAGS_gpuAPI.contains("gles")) { return kGLES_GrGLStandard; }
292748ca3bf2d170708f263693e8579e6722389d0efmtklein    return kNone_GrGLStandard;
293748ca3bf2d170708f263693e8579e6722389d0efmtklein}
294748ca3bf2d170708f263693e8579e6722389d0efmtklein
295748ca3bf2d170708f263693e8579e6722389d0efmtkleinstatic void push_sink(const char* tag, Sink* s) {
296748ca3bf2d170708f263693e8579e6722389d0efmtklein    SkAutoTDelete<Sink> sink(s);
297748ca3bf2d170708f263693e8579e6722389d0efmtklein    if (!FLAGS_config.contains(tag)) {
298748ca3bf2d170708f263693e8579e6722389d0efmtklein        return;
299748ca3bf2d170708f263693e8579e6722389d0efmtklein    }
300748ca3bf2d170708f263693e8579e6722389d0efmtklein    // Try a noop Src as a canary.  If it fails, skip this sink.
301748ca3bf2d170708f263693e8579e6722389d0efmtklein    struct : public Src {
30236352bf5e38f45a70ee4f4fc132a38048d38206dmtklein        Error draw(SkCanvas*) const override { return ""; }
30336352bf5e38f45a70ee4f4fc132a38048d38206dmtklein        SkISize size() const override { return SkISize::Make(16, 16); }
30436352bf5e38f45a70ee4f4fc132a38048d38206dmtklein        Name name() const override { return "noop"; }
305748ca3bf2d170708f263693e8579e6722389d0efmtklein    } noop;
306748ca3bf2d170708f263693e8579e6722389d0efmtklein
307748ca3bf2d170708f263693e8579e6722389d0efmtklein    SkBitmap bitmap;
308748ca3bf2d170708f263693e8579e6722389d0efmtklein    SkDynamicMemoryWStream stream;
309b9eb4ac0f1c29d6fe10ad7ff81ed8326ac1ea043mtklein    SkString log;
310b9eb4ac0f1c29d6fe10ad7ff81ed8326ac1ea043mtklein    Error err = sink->draw(noop, &bitmap, &stream, &log);
3114089ef7c982592fadeec441438c551ffb4c746bemtklein    if (err.isFatal()) {
31205641a5582bbb3ee40dc2c9ba21d837df9340583mtklein        SkDebugf("Could not run %s: %s\n", tag, err.c_str());
31305641a5582bbb3ee40dc2c9ba21d837df9340583mtklein        exit(1);
314a98683bc50a3fe1241396f0ae20e35c7b1133fa9halcanary    }
315709d2c3e5062c5b57f91273bfc11a751f5b2bb88mtklein
316748ca3bf2d170708f263693e8579e6722389d0efmtklein    Tagged<Sink>& ts = gSinks.push_back();
317748ca3bf2d170708f263693e8579e6722389d0efmtklein    ts.reset(sink.detach());
318748ca3bf2d170708f263693e8579e6722389d0efmtklein    ts.tag = tag;
319748ca3bf2d170708f263693e8579e6722389d0efmtklein}
320748ca3bf2d170708f263693e8579e6722389d0efmtklein
321748ca3bf2d170708f263693e8579e6722389d0efmtkleinstatic bool gpu_supported() {
322748ca3bf2d170708f263693e8579e6722389d0efmtklein#if SK_SUPPORT_GPU
323748ca3bf2d170708f263693e8579e6722389d0efmtklein    return FLAGS_gpu;
324748ca3bf2d170708f263693e8579e6722389d0efmtklein#else
325748ca3bf2d170708f263693e8579e6722389d0efmtklein    return false;
326748ca3bf2d170708f263693e8579e6722389d0efmtklein#endif
327748ca3bf2d170708f263693e8579e6722389d0efmtklein}
328748ca3bf2d170708f263693e8579e6722389d0efmtklein
329748ca3bf2d170708f263693e8579e6722389d0efmtkleinstatic Sink* create_sink(const char* tag) {
330748ca3bf2d170708f263693e8579e6722389d0efmtklein#define SINK(t, sink, ...) if (0 == strcmp(t, tag)) { return new sink(__VA_ARGS__); }
331748ca3bf2d170708f263693e8579e6722389d0efmtklein    if (gpu_supported()) {
33282d2843cc59dc048b7d8d1d928dab743d8e85a3bmtklein        typedef GrContextFactory Gr;
333748ca3bf2d170708f263693e8579e6722389d0efmtklein        const GrGLStandard api = get_gpu_api();
33482d2843cc59dc048b7d8d1d928dab743d8e85a3bmtklein        SINK("gpunull",    GPUSink, Gr::kNull_GLContextType,   api,  0, false, FLAGS_gpu_threading);
33582d2843cc59dc048b7d8d1d928dab743d8e85a3bmtklein        SINK("gpudebug",   GPUSink, Gr::kDebug_GLContextType,  api,  0, false, FLAGS_gpu_threading);
33682d2843cc59dc048b7d8d1d928dab743d8e85a3bmtklein        SINK("gpu",        GPUSink, Gr::kNative_GLContextType, api,  0, false, FLAGS_gpu_threading);
33782d2843cc59dc048b7d8d1d928dab743d8e85a3bmtklein        SINK("gpudft",     GPUSink, Gr::kNative_GLContextType, api,  0,  true, FLAGS_gpu_threading);
33882d2843cc59dc048b7d8d1d928dab743d8e85a3bmtklein        SINK("msaa4",      GPUSink, Gr::kNative_GLContextType, api,  4, false, FLAGS_gpu_threading);
33982d2843cc59dc048b7d8d1d928dab743d8e85a3bmtklein        SINK("msaa16",     GPUSink, Gr::kNative_GLContextType, api, 16, false, FLAGS_gpu_threading);
34082d2843cc59dc048b7d8d1d928dab743d8e85a3bmtklein        SINK("nvprmsaa4",  GPUSink, Gr::kNVPR_GLContextType,   api,  4, false, FLAGS_gpu_threading);
34182d2843cc59dc048b7d8d1d928dab743d8e85a3bmtklein        SINK("nvprmsaa16", GPUSink, Gr::kNVPR_GLContextType,   api, 16, false, FLAGS_gpu_threading);
342748ca3bf2d170708f263693e8579e6722389d0efmtklein    #if SK_ANGLE
34382d2843cc59dc048b7d8d1d928dab743d8e85a3bmtklein        SINK("angle",      GPUSink, Gr::kANGLE_GLContextType,  api,  0, false, FLAGS_gpu_threading);
344748ca3bf2d170708f263693e8579e6722389d0efmtklein    #endif
345748ca3bf2d170708f263693e8579e6722389d0efmtklein    #if SK_MESA
34682d2843cc59dc048b7d8d1d928dab743d8e85a3bmtklein        SINK("mesa",       GPUSink, Gr::kMESA_GLContextType,   api,  0, false, FLAGS_gpu_threading);
347748ca3bf2d170708f263693e8579e6722389d0efmtklein    #endif
348748ca3bf2d170708f263693e8579e6722389d0efmtklein    }
349748ca3bf2d170708f263693e8579e6722389d0efmtklein
350eebc39ad5a1dcbde1b10a9b2ab54679549522b52tomhudson#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
351eebc39ad5a1dcbde1b10a9b2ab54679549522b52tomhudson    SINK("hwui",           HWUISink);
352eebc39ad5a1dcbde1b10a9b2ab54679549522b52tomhudson#endif
353eebc39ad5a1dcbde1b10a9b2ab54679549522b52tomhudson
354748ca3bf2d170708f263693e8579e6722389d0efmtklein    if (FLAGS_cpu) {
355748ca3bf2d170708f263693e8579e6722389d0efmtklein        SINK("565",  RasterSink, kRGB_565_SkColorType);
356748ca3bf2d170708f263693e8579e6722389d0efmtklein        SINK("8888", RasterSink, kN32_SkColorType);
35719f306013e2a88acb7f5c7322c6f751c8a74f6e4mtklein        SINK("pdf",  PDFSink);
3589c3f17d6e859a11535f40497cb9f6e777d15f62emtklein        SINK("skp",  SKPSink);
3598a4527e98a57b1d2dd248a635f0c4fa227be2089mtklein        SINK("svg",  SVGSink);
3608a4527e98a57b1d2dd248a635f0c4fa227be2089mtklein        SINK("null", NullSink);
36147ef4d5d934bba86848aa238efab21f54a160c1ahalcanary        SINK("xps",  XPSSink);
362748ca3bf2d170708f263693e8579e6722389d0efmtklein    }
363748ca3bf2d170708f263693e8579e6722389d0efmtklein#undef SINK
364748ca3bf2d170708f263693e8579e6722389d0efmtklein    return NULL;
365748ca3bf2d170708f263693e8579e6722389d0efmtklein}
366748ca3bf2d170708f263693e8579e6722389d0efmtklein
367748ca3bf2d170708f263693e8579e6722389d0efmtkleinstatic Sink* create_via(const char* tag, Sink* wrapped) {
368748ca3bf2d170708f263693e8579e6722389d0efmtklein#define VIA(t, via, ...) if (0 == strcmp(t, tag)) { return new via(__VA_ARGS__); }
3696fbf4b3a7f0a3304649c482ab0a911dc147a6825mtklein    VIA("twice",     ViaTwice,         wrapped);
3707edca21226017e6b87a0c95fa571d34c36ceca04mtklein    VIA("pipe",      ViaPipe,          wrapped);
371748ca3bf2d170708f263693e8579e6722389d0efmtklein    VIA("serialize", ViaSerialization, wrapped);
37206a22f618cd2adbbd33634a701b5cf8353886d63reed    VIA("deferred",  ViaDeferred,      wrapped);
373b7e8d69fc21a3043348fd9b76876471e0a6ae7femtklein    VIA("2ndpic",    ViaSecondPicture, wrapped);
374d31c13d0441aecc8b2a4fa4f45fd5e59584cb3eamtklein    VIA("sp",        ViaSingletonPictures, wrapped);
3757edca21226017e6b87a0c95fa571d34c36ceca04mtklein    VIA("tiles",     ViaTiles, 256, 256,               NULL, wrapped);
3767edca21226017e6b87a0c95fa571d34c36ceca04mtklein    VIA("tiles_rt",  ViaTiles, 256, 256, new SkRTreeFactory, wrapped);
377748ca3bf2d170708f263693e8579e6722389d0efmtklein
378d603b22903bf7c023226bf52bd7c1f49a9bee1bfmtklein    if (FLAGS_matrix.count() == 4) {
379748ca3bf2d170708f263693e8579e6722389d0efmtklein        SkMatrix m;
380d603b22903bf7c023226bf52bd7c1f49a9bee1bfmtklein        m.reset();
381d603b22903bf7c023226bf52bd7c1f49a9bee1bfmtklein        m.setScaleX((SkScalar)atof(FLAGS_matrix[0]));
382d603b22903bf7c023226bf52bd7c1f49a9bee1bfmtklein        m.setSkewX ((SkScalar)atof(FLAGS_matrix[1]));
383d603b22903bf7c023226bf52bd7c1f49a9bee1bfmtklein        m.setSkewY ((SkScalar)atof(FLAGS_matrix[2]));
384d603b22903bf7c023226bf52bd7c1f49a9bee1bfmtklein        m.setScaleY((SkScalar)atof(FLAGS_matrix[3]));
385d603b22903bf7c023226bf52bd7c1f49a9bee1bfmtklein        VIA("matrix",  ViaMatrix,  m, wrapped);
386d603b22903bf7c023226bf52bd7c1f49a9bee1bfmtklein        VIA("upright", ViaUpright, m, wrapped);
387114c3cd0543d77aa0ac08d8af436ac7f9d32714dmtklein    }
38864de1e179012302d5f3b805d0736a583ad91c6a2tomhudson
38964de1e179012302d5f3b805d0736a583ad91c6a2tomhudson#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
39064de1e179012302d5f3b805d0736a583ad91c6a2tomhudson    VIA("androidsdk", ViaAndroidSDK, wrapped);
39164de1e179012302d5f3b805d0736a583ad91c6a2tomhudson#endif
39264de1e179012302d5f3b805d0736a583ad91c6a2tomhudson
393748ca3bf2d170708f263693e8579e6722389d0efmtklein#undef VIA
394748ca3bf2d170708f263693e8579e6722389d0efmtklein    return NULL;
395a98683bc50a3fe1241396f0ae20e35c7b1133fa9halcanary}
39690b5a2a653b312ff9bcd7102412da2dbeb52368ccommit-bot@chromium.org
397748ca3bf2d170708f263693e8579e6722389d0efmtkleinstatic void gather_sinks() {
398748ca3bf2d170708f263693e8579e6722389d0efmtklein    for (int i = 0; i < FLAGS_config.count(); i++) {
399748ca3bf2d170708f263693e8579e6722389d0efmtklein        const char* config = FLAGS_config[i];
400748ca3bf2d170708f263693e8579e6722389d0efmtklein        SkTArray<SkString> parts;
401748ca3bf2d170708f263693e8579e6722389d0efmtklein        SkStrSplit(config, "-", &parts);
402748ca3bf2d170708f263693e8579e6722389d0efmtklein
403748ca3bf2d170708f263693e8579e6722389d0efmtklein        Sink* sink = NULL;
404748ca3bf2d170708f263693e8579e6722389d0efmtklein        for (int i = parts.count(); i-- > 0;) {
405748ca3bf2d170708f263693e8579e6722389d0efmtklein            const char* part = parts[i].c_str();
406748ca3bf2d170708f263693e8579e6722389d0efmtklein            Sink* next = (sink == NULL) ? create_sink(part) : create_via(part, sink);
407748ca3bf2d170708f263693e8579e6722389d0efmtklein            if (next == NULL) {
408748ca3bf2d170708f263693e8579e6722389d0efmtklein                SkDebugf("Skipping %s: Don't understand '%s'.\n", config, part);
409748ca3bf2d170708f263693e8579e6722389d0efmtklein                delete sink;
410748ca3bf2d170708f263693e8579e6722389d0efmtklein                sink = NULL;
411748ca3bf2d170708f263693e8579e6722389d0efmtklein                break;
412748ca3bf2d170708f263693e8579e6722389d0efmtklein            }
413748ca3bf2d170708f263693e8579e6722389d0efmtklein            sink = next;
414114c3cd0543d77aa0ac08d8af436ac7f9d32714dmtklein        }
415748ca3bf2d170708f263693e8579e6722389d0efmtklein        if (sink) {
416748ca3bf2d170708f263693e8579e6722389d0efmtklein            push_sink(config, sink);
417114c3cd0543d77aa0ac08d8af436ac7f9d32714dmtklein        }
41890b5a2a653b312ff9bcd7102412da2dbeb52368ccommit-bot@chromium.org    }
419114c3cd0543d77aa0ac08d8af436ac7f9d32714dmtklein}
42090b5a2a653b312ff9bcd7102412da2dbeb52368ccommit-bot@chromium.org
421a2ef642b00fdd58512b0889d12796d963a27f739mtkleinstatic bool match(const char* needle, const char* haystack) {
422a2ef642b00fdd58512b0889d12796d963a27f739mtklein    return 0 == strcmp("_", needle) || NULL != strstr(haystack, needle);
423a2ef642b00fdd58512b0889d12796d963a27f739mtklein}
424a2ef642b00fdd58512b0889d12796d963a27f739mtklein
42554416de52381ac11dd755100a8025debf595873adjsollenstatic ImplicitString is_blacklisted(const char* sink, const char* src,
42654416de52381ac11dd755100a8025debf595873adjsollen                                     const char* srcOptions, const char* name) {
4270d243ffe352f6b0063286334c79f1ea84b3b48famtklein    for (int i = 0; i < FLAGS_blacklist.count() - 3; i += 4) {
428a2ef642b00fdd58512b0889d12796d963a27f739mtklein        if (match(FLAGS_blacklist[i+0], sink) &&
42954416de52381ac11dd755100a8025debf595873adjsollen            match(FLAGS_blacklist[i+1], src) &&
43054416de52381ac11dd755100a8025debf595873adjsollen            match(FLAGS_blacklist[i+2], srcOptions) &&
43154416de52381ac11dd755100a8025debf595873adjsollen            match(FLAGS_blacklist[i+3], name)) {
43254416de52381ac11dd755100a8025debf595873adjsollen            return SkStringPrintf("%s %s %s %s",
43354416de52381ac11dd755100a8025debf595873adjsollen                                  FLAGS_blacklist[i+0], FLAGS_blacklist[i+1],
43454416de52381ac11dd755100a8025debf595873adjsollen                                  FLAGS_blacklist[i+2], FLAGS_blacklist[i+3]);
435a2ef642b00fdd58512b0889d12796d963a27f739mtklein        }
436a2ef642b00fdd58512b0889d12796d963a27f739mtklein    }
437a2ef642b00fdd58512b0889d12796d963a27f739mtklein    return "";
438a2ef642b00fdd58512b0889d12796d963a27f739mtklein}
439a2ef642b00fdd58512b0889d12796d963a27f739mtklein
440748ca3bf2d170708f263693e8579e6722389d0efmtklein// The finest-grained unit of work we can run: draw a single Src into a single Sink,
441748ca3bf2d170708f263693e8579e6722389d0efmtklein// report any errors, and perhaps write out the output: a .png of the bitmap, or a raw stream.
442748ca3bf2d170708f263693e8579e6722389d0efmtkleinstruct Task {
443748ca3bf2d170708f263693e8579e6722389d0efmtklein    Task(const Tagged<Src>& src, const Tagged<Sink>& sink) : src(src), sink(sink) {}
444748ca3bf2d170708f263693e8579e6722389d0efmtklein    const Tagged<Src>&  src;
445748ca3bf2d170708f263693e8579e6722389d0efmtklein    const Tagged<Sink>& sink;
446748ca3bf2d170708f263693e8579e6722389d0efmtklein
447748ca3bf2d170708f263693e8579e6722389d0efmtklein    static void Run(Task* task) {
448a2ef642b00fdd58512b0889d12796d963a27f739mtklein        SkString name = task->src->name();
449b37cb41a8bfc1bdf65fb8387c24d45da7cf8b7damtklein        SkString note;
45054416de52381ac11dd755100a8025debf595873adjsollen        SkString whyBlacklisted = is_blacklisted(task->sink.tag, task->src.tag,
45154416de52381ac11dd755100a8025debf595873adjsollen                                                 task->src.options, name.c_str());
452b37cb41a8bfc1bdf65fb8387c24d45da7cf8b7damtklein        if (!whyBlacklisted.isEmpty()) {
453b37cb41a8bfc1bdf65fb8387c24d45da7cf8b7damtklein            note.appendf(" (--blacklist %s)", whyBlacklisted.c_str());
454b37cb41a8bfc1bdf65fb8387c24d45da7cf8b7damtklein        }
455b9eb4ac0f1c29d6fe10ad7ff81ed8326ac1ea043mtklein        SkString log;
456748ca3bf2d170708f263693e8579e6722389d0efmtklein        WallTimer timer;
457748ca3bf2d170708f263693e8579e6722389d0efmtklein        timer.start();
458a2ef642b00fdd58512b0889d12796d963a27f739mtklein        if (!FLAGS_dryRun && whyBlacklisted.isEmpty()) {
459748ca3bf2d170708f263693e8579e6722389d0efmtklein            SkBitmap bitmap;
460748ca3bf2d170708f263693e8579e6722389d0efmtklein            SkDynamicMemoryWStream stream;
46154416de52381ac11dd755100a8025debf595873adjsollen            start(task->sink.tag, task->src.tag, task->src.options, name.c_str());
462b9eb4ac0f1c29d6fe10ad7ff81ed8326ac1ea043mtklein            Error err = task->sink->draw(*task->src, &bitmap, &stream, &log);
463748ca3bf2d170708f263693e8579e6722389d0efmtklein            if (!err.isEmpty()) {
4644089ef7c982592fadeec441438c551ffb4c746bemtklein                timer.end();
4654089ef7c982592fadeec441438c551ffb4c746bemtklein                if (err.isFatal()) {
46654416de52381ac11dd755100a8025debf595873adjsollen                    fail(SkStringPrintf("%s %s %s %s: %s",
4674089ef7c982592fadeec441438c551ffb4c746bemtklein                                        task->sink.tag,
4684089ef7c982592fadeec441438c551ffb4c746bemtklein                                        task->src.tag,
46954416de52381ac11dd755100a8025debf595873adjsollen                                        task->src.options,
4704089ef7c982592fadeec441438c551ffb4c746bemtklein                                        name.c_str(),
4714089ef7c982592fadeec441438c551ffb4c746bemtklein                                        err.c_str()));
472b37cb41a8bfc1bdf65fb8387c24d45da7cf8b7damtklein                } else {
473b37cb41a8bfc1bdf65fb8387c24d45da7cf8b7damtklein                    note.appendf(" (skipped: %s)", err.c_str());
4744089ef7c982592fadeec441438c551ffb4c746bemtklein                }
47554416de52381ac11dd755100a8025debf595873adjsollen                done(timer.fWall, task->sink.tag, task->src.tag, task->src.options,
47654416de52381ac11dd755100a8025debf595873adjsollen                     name, note, log);
4774089ef7c982592fadeec441438c551ffb4c746bemtklein                return;
478748ca3bf2d170708f263693e8579e6722389d0efmtklein            }
47962bd1a69ea49318aa5022151262c842887e0ecf4mtklein            SkAutoTDelete<SkStreamAsset> data(stream.detachAsStream());
48062bd1a69ea49318aa5022151262c842887e0ecf4mtklein
48162bd1a69ea49318aa5022151262c842887e0ecf4mtklein            SkString md5;
48262bd1a69ea49318aa5022151262c842887e0ecf4mtklein            if (!FLAGS_writePath.isEmpty() || !FLAGS_readPath.isEmpty()) {
48362bd1a69ea49318aa5022151262c842887e0ecf4mtklein                SkMD5 hash;
48462bd1a69ea49318aa5022151262c842887e0ecf4mtklein                if (data->getLength()) {
48562bd1a69ea49318aa5022151262c842887e0ecf4mtklein                    hash.writeStream(data, data->getLength());
48662bd1a69ea49318aa5022151262c842887e0ecf4mtklein                    data->rewind();
48762bd1a69ea49318aa5022151262c842887e0ecf4mtklein                } else {
48862bd1a69ea49318aa5022151262c842887e0ecf4mtklein                    hash.write(bitmap.getPixels(), bitmap.getSize());
48962bd1a69ea49318aa5022151262c842887e0ecf4mtklein                }
49062bd1a69ea49318aa5022151262c842887e0ecf4mtklein                SkMD5::Digest digest;
49162bd1a69ea49318aa5022151262c842887e0ecf4mtklein                hash.finish(digest);
49262bd1a69ea49318aa5022151262c842887e0ecf4mtklein                for (int i = 0; i < 16; i++) {
49362bd1a69ea49318aa5022151262c842887e0ecf4mtklein                    md5.appendf("%02x", digest.data[i]);
49462bd1a69ea49318aa5022151262c842887e0ecf4mtklein                }
49562bd1a69ea49318aa5022151262c842887e0ecf4mtklein            }
49662bd1a69ea49318aa5022151262c842887e0ecf4mtklein
49762bd1a69ea49318aa5022151262c842887e0ecf4mtklein            if (!FLAGS_readPath.isEmpty() &&
49854416de52381ac11dd755100a8025debf595873adjsollen                !gGold.contains(Gold(task->sink.tag, task->src.tag,
49954416de52381ac11dd755100a8025debf595873adjsollen                                     task->src.options, name, md5))) {
50054416de52381ac11dd755100a8025debf595873adjsollen                fail(SkStringPrintf("%s not found for %s %s %s %s in %s",
50162bd1a69ea49318aa5022151262c842887e0ecf4mtklein                                    md5.c_str(),
50262bd1a69ea49318aa5022151262c842887e0ecf4mtklein                                    task->sink.tag,
50362bd1a69ea49318aa5022151262c842887e0ecf4mtklein                                    task->src.tag,
50454416de52381ac11dd755100a8025debf595873adjsollen                                    task->src.options,
50562bd1a69ea49318aa5022151262c842887e0ecf4mtklein                                    name.c_str(),
50662bd1a69ea49318aa5022151262c842887e0ecf4mtklein                                    FLAGS_readPath[0]));
50762bd1a69ea49318aa5022151262c842887e0ecf4mtklein            }
50862bd1a69ea49318aa5022151262c842887e0ecf4mtklein
509b0531a790cc4ec2f903c79206c0c1053108664f5mtklein            if (!FLAGS_writePath.isEmpty()) {
510748ca3bf2d170708f263693e8579e6722389d0efmtklein                const char* ext = task->sink->fileExtension();
51162bd1a69ea49318aa5022151262c842887e0ecf4mtklein                if (data->getLength()) {
51262bd1a69ea49318aa5022151262c842887e0ecf4mtklein                    WriteToDisk(*task, md5, ext, data, data->getLength(), NULL);
513022afb8384019b448c7c1c62a9ff63fa9e477737halcanary                    SkASSERT(bitmap.drawsNothing());
514022afb8384019b448c7c1c62a9ff63fa9e477737halcanary                } else if (!bitmap.drawsNothing()) {
51562bd1a69ea49318aa5022151262c842887e0ecf4mtklein                    WriteToDisk(*task, md5, ext, NULL, 0, &bitmap);
516748ca3bf2d170708f263693e8579e6722389d0efmtklein                }
517748ca3bf2d170708f263693e8579e6722389d0efmtklein            }
518114c3cd0543d77aa0ac08d8af436ac7f9d32714dmtklein        }
519748ca3bf2d170708f263693e8579e6722389d0efmtklein        timer.end();
52054416de52381ac11dd755100a8025debf595873adjsollen        done(timer.fWall, task->sink.tag, task->src.tag, task->src.options, name, note, log);
521f6139f7c3867a70a750620cd34ce10338a54086emtklein    }
522f6139f7c3867a70a750620cd34ce10338a54086emtklein
523748ca3bf2d170708f263693e8579e6722389d0efmtklein    static void WriteToDisk(const Task& task,
52462bd1a69ea49318aa5022151262c842887e0ecf4mtklein                            SkString md5,
52562bd1a69ea49318aa5022151262c842887e0ecf4mtklein                            const char* ext,
526748ca3bf2d170708f263693e8579e6722389d0efmtklein                            SkStream* data, size_t len,
52762bd1a69ea49318aa5022151262c842887e0ecf4mtklein                            const SkBitmap* bitmap) {
528748ca3bf2d170708f263693e8579e6722389d0efmtklein        JsonWriter::BitmapResult result;
52954416de52381ac11dd755100a8025debf595873adjsollen        result.name          = task.src->name();
53054416de52381ac11dd755100a8025debf595873adjsollen        result.config        = task.sink.tag;
53154416de52381ac11dd755100a8025debf595873adjsollen        result.sourceType    = task.src.tag;
53254416de52381ac11dd755100a8025debf595873adjsollen        result.sourceOptions = task.src.options;
53354416de52381ac11dd755100a8025debf595873adjsollen        result.ext           = ext;
53454416de52381ac11dd755100a8025debf595873adjsollen        result.md5           = md5;
535748ca3bf2d170708f263693e8579e6722389d0efmtklein        JsonWriter::AddBitmapResult(result);
536709d2c3e5062c5b57f91273bfc11a751f5b2bb88mtklein
537b0531a790cc4ec2f903c79206c0c1053108664f5mtklein        // If an MD5 is uninteresting, we want it noted in the JSON file,
538b0531a790cc4ec2f903c79206c0c1053108664f5mtklein        // but don't want to dump it out as a .png (or whatever ext is).
539b0531a790cc4ec2f903c79206c0c1053108664f5mtklein        if (gUninterestingHashes.contains(md5)) {
540b0531a790cc4ec2f903c79206c0c1053108664f5mtklein            return;
541b0531a790cc4ec2f903c79206c0c1053108664f5mtklein        }
542b0531a790cc4ec2f903c79206c0c1053108664f5mtklein
543748ca3bf2d170708f263693e8579e6722389d0efmtklein        const char* dir = FLAGS_writePath[0];
544748ca3bf2d170708f263693e8579e6722389d0efmtklein        if (0 == strcmp(dir, "@")) {  // Needed for iOS.
545748ca3bf2d170708f263693e8579e6722389d0efmtklein            dir = FLAGS_resourcePath[0];
546748ca3bf2d170708f263693e8579e6722389d0efmtklein        }
547748ca3bf2d170708f263693e8579e6722389d0efmtklein        sk_mkdir(dir);
548748ca3bf2d170708f263693e8579e6722389d0efmtklein
549748ca3bf2d170708f263693e8579e6722389d0efmtklein        SkString path;
550748ca3bf2d170708f263693e8579e6722389d0efmtklein        if (FLAGS_nameByHash) {
551748ca3bf2d170708f263693e8579e6722389d0efmtklein            path = SkOSPath::Join(dir, result.md5.c_str());
552748ca3bf2d170708f263693e8579e6722389d0efmtklein            path.append(".");
553748ca3bf2d170708f263693e8579e6722389d0efmtklein            path.append(ext);
554748ca3bf2d170708f263693e8579e6722389d0efmtklein            if (sk_exists(path.c_str())) {
555748ca3bf2d170708f263693e8579e6722389d0efmtklein                return;  // Content-addressed.  If it exists already, we're done.
556748ca3bf2d170708f263693e8579e6722389d0efmtklein            }
557748ca3bf2d170708f263693e8579e6722389d0efmtklein        } else {
558748ca3bf2d170708f263693e8579e6722389d0efmtklein            path = SkOSPath::Join(dir, task.sink.tag);
559748ca3bf2d170708f263693e8579e6722389d0efmtklein            sk_mkdir(path.c_str());
560748ca3bf2d170708f263693e8579e6722389d0efmtklein            path = SkOSPath::Join(path.c_str(), task.src.tag);
561748ca3bf2d170708f263693e8579e6722389d0efmtklein            sk_mkdir(path.c_str());
56254416de52381ac11dd755100a8025debf595873adjsollen            if (strcmp(task.src.options, "") != 0) {
56354416de52381ac11dd755100a8025debf595873adjsollen              path = SkOSPath::Join(path.c_str(), task.src.options);
56454416de52381ac11dd755100a8025debf595873adjsollen              sk_mkdir(path.c_str());
56554416de52381ac11dd755100a8025debf595873adjsollen            }
566748ca3bf2d170708f263693e8579e6722389d0efmtklein            path = SkOSPath::Join(path.c_str(), task.src->name().c_str());
567748ca3bf2d170708f263693e8579e6722389d0efmtklein            path.append(".");
568748ca3bf2d170708f263693e8579e6722389d0efmtklein            path.append(ext);
569748ca3bf2d170708f263693e8579e6722389d0efmtklein        }
570748ca3bf2d170708f263693e8579e6722389d0efmtklein
571748ca3bf2d170708f263693e8579e6722389d0efmtklein        SkFILEWStream file(path.c_str());
572748ca3bf2d170708f263693e8579e6722389d0efmtklein        if (!file.isValid()) {
573748ca3bf2d170708f263693e8579e6722389d0efmtklein            fail(SkStringPrintf("Can't open %s for writing.\n", path.c_str()));
574748ca3bf2d170708f263693e8579e6722389d0efmtklein            return;
575748ca3bf2d170708f263693e8579e6722389d0efmtklein        }
576748ca3bf2d170708f263693e8579e6722389d0efmtklein
577748ca3bf2d170708f263693e8579e6722389d0efmtklein        if (bitmap) {
578748ca3bf2d170708f263693e8579e6722389d0efmtklein            // We can't encode A8 bitmaps as PNGs.  Convert them to 8888 first.
579748ca3bf2d170708f263693e8579e6722389d0efmtklein            SkBitmap converted;
580748ca3bf2d170708f263693e8579e6722389d0efmtklein            if (bitmap->info().colorType() == kAlpha_8_SkColorType) {
581748ca3bf2d170708f263693e8579e6722389d0efmtklein                if (!bitmap->copyTo(&converted, kN32_SkColorType)) {
582748ca3bf2d170708f263693e8579e6722389d0efmtklein                    fail("Can't convert A8 to 8888.\n");
583748ca3bf2d170708f263693e8579e6722389d0efmtklein                    return;
584748ca3bf2d170708f263693e8579e6722389d0efmtklein                }
585748ca3bf2d170708f263693e8579e6722389d0efmtklein                bitmap = &converted;
586748ca3bf2d170708f263693e8579e6722389d0efmtklein            }
587748ca3bf2d170708f263693e8579e6722389d0efmtklein            if (!SkImageEncoder::EncodeStream(&file, *bitmap, SkImageEncoder::kPNG_Type, 100)) {
588748ca3bf2d170708f263693e8579e6722389d0efmtklein                fail(SkStringPrintf("Can't encode PNG to %s.\n", path.c_str()));
589748ca3bf2d170708f263693e8579e6722389d0efmtklein                return;
590748ca3bf2d170708f263693e8579e6722389d0efmtklein            }
591748ca3bf2d170708f263693e8579e6722389d0efmtklein        } else {
592748ca3bf2d170708f263693e8579e6722389d0efmtklein            if (!file.writeStream(data, len)) {
593748ca3bf2d170708f263693e8579e6722389d0efmtklein                fail(SkStringPrintf("Can't write to %s.\n", path.c_str()));
594748ca3bf2d170708f263693e8579e6722389d0efmtklein                return;
595748ca3bf2d170708f263693e8579e6722389d0efmtklein            }
596748ca3bf2d170708f263693e8579e6722389d0efmtklein        }
597114c3cd0543d77aa0ac08d8af436ac7f9d32714dmtklein    }
598748ca3bf2d170708f263693e8579e6722389d0efmtklein};
599d36522d12d3e71958e50683a7eef43dc2a47d96dmtklein@google.com
600748ca3bf2d170708f263693e8579e6722389d0efmtklein// Run all tasks in the same enclave serially on the same thread.
601748ca3bf2d170708f263693e8579e6722389d0efmtklein// They can't possibly run concurrently with each other.
602748ca3bf2d170708f263693e8579e6722389d0efmtkleinstatic void run_enclave(SkTArray<Task>* tasks) {
603748ca3bf2d170708f263693e8579e6722389d0efmtklein    for (int i = 0; i < tasks->count(); i++) {
604748ca3bf2d170708f263693e8579e6722389d0efmtklein        Task::Run(tasks->begin() + i);
605d36522d12d3e71958e50683a7eef43dc2a47d96dmtklein@google.com    }
606d36522d12d3e71958e50683a7eef43dc2a47d96dmtklein@google.com}
607d36522d12d3e71958e50683a7eef43dc2a47d96dmtklein@google.com
608748ca3bf2d170708f263693e8579e6722389d0efmtklein/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
609748ca3bf2d170708f263693e8579e6722389d0efmtklein
610748ca3bf2d170708f263693e8579e6722389d0efmtklein// Unit tests don't fit so well into the Src/Sink model, so we give them special treatment.
611748ca3bf2d170708f263693e8579e6722389d0efmtklein
61255e88b226ccb85d2c712a9e3e9e1f5bdcaac05acmtkleinstatic SkTDArray<skiatest::Test> gThreadedTests, gGPUTests;
613748ca3bf2d170708f263693e8579e6722389d0efmtklein
614748ca3bf2d170708f263693e8579e6722389d0efmtkleinstatic void gather_tests() {
6156c5fed2d5c18129a2ae6ef461d75e388f1b0bacdmtklein    if (!FLAGS_src.contains("tests")) {
616748ca3bf2d170708f263693e8579e6722389d0efmtklein        return;
617748ca3bf2d170708f263693e8579e6722389d0efmtklein    }
6186393c0653e5338a093c3908a410bdfd2ea1bdcabmtklein    for (const skiatest::TestRegistry* r = skiatest::TestRegistry::Head(); r; r = r->next()) {
6196393c0653e5338a093c3908a410bdfd2ea1bdcabmtklein        if (!in_shard()) {
6206393c0653e5338a093c3908a410bdfd2ea1bdcabmtklein            continue;
6216393c0653e5338a093c3908a410bdfd2ea1bdcabmtklein        }
62287f3ba4847aa575016eb3a21e944197d757df8c0halcanary        // Despite its name, factory() is returning a reference to
62387f3ba4847aa575016eb3a21e944197d757df8c0halcanary        // link-time static const POD data.
62487f3ba4847aa575016eb3a21e944197d757df8c0halcanary        const skiatest::Test& test = r->factory();
62587f3ba4847aa575016eb3a21e944197d757df8c0halcanary        if (SkCommandLineFlags::ShouldSkip(FLAGS_match, test.name)) {
626748ca3bf2d170708f263693e8579e6722389d0efmtklein            continue;
627748ca3bf2d170708f263693e8579e6722389d0efmtklein        }
62887f3ba4847aa575016eb3a21e944197d757df8c0halcanary        if (test.needsGpu && gpu_supported()) {
62955e88b226ccb85d2c712a9e3e9e1f5bdcaac05acmtklein            (FLAGS_gpu_threading ? gThreadedTests : gGPUTests).push(test);
63087f3ba4847aa575016eb3a21e944197d757df8c0halcanary        } else if (!test.needsGpu && FLAGS_cpu) {
63155e88b226ccb85d2c712a9e3e9e1f5bdcaac05acmtklein            gThreadedTests.push(test);
63282d2843cc59dc048b7d8d1d928dab743d8e85a3bmtklein        }
633748ca3bf2d170708f263693e8579e6722389d0efmtklein    }
63480549fcdd50269d7e069d6db02b395fca128056ckkinnunen}
63580549fcdd50269d7e069d6db02b395fca128056ckkinnunen
63687f3ba4847aa575016eb3a21e944197d757df8c0halcanarystatic void run_test(skiatest::Test* test) {
63787f3ba4847aa575016eb3a21e944197d757df8c0halcanary    struct : public skiatest::Reporter {
63836352bf5e38f45a70ee4f4fc132a38048d38206dmtklein        void reportFailed(const skiatest::Failure& failure) override {
63987f3ba4847aa575016eb3a21e944197d757df8c0halcanary            fail(failure.toString());
64087f3ba4847aa575016eb3a21e944197d757df8c0halcanary            JsonWriter::AddTestFailure(failure);
64187f3ba4847aa575016eb3a21e944197d757df8c0halcanary        }
64236352bf5e38f45a70ee4f4fc132a38048d38206dmtklein        bool allowExtendedTest() const override {
64387f3ba4847aa575016eb3a21e944197d757df8c0halcanary            return FLAGS_pathOpsExtended;
64487f3ba4847aa575016eb3a21e944197d757df8c0halcanary        }
64536352bf5e38f45a70ee4f4fc132a38048d38206dmtklein        bool verbose() const override { return FLAGS_veryVerbose; }
64687f3ba4847aa575016eb3a21e944197d757df8c0halcanary    } reporter;
647748ca3bf2d170708f263693e8579e6722389d0efmtklein    WallTimer timer;
648748ca3bf2d170708f263693e8579e6722389d0efmtklein    timer.start();
649748ca3bf2d170708f263693e8579e6722389d0efmtklein    if (!FLAGS_dryRun) {
65054416de52381ac11dd755100a8025debf595873adjsollen        start("unit", "test", "", test->name);
65155e88b226ccb85d2c712a9e3e9e1f5bdcaac05acmtklein        GrContextFactory factory;
65255e88b226ccb85d2c712a9e3e9e1f5bdcaac05acmtklein        test->proc(&reporter, &factory);
65338aeb0fd7a2bdab5e44531d96045dffe25c8e2b0commit-bot@chromium.org    }
654748ca3bf2d170708f263693e8579e6722389d0efmtklein    timer.end();
65554416de52381ac11dd755100a8025debf595873adjsollen    done(timer.fWall, "unit", "test", "", test->name, "", "");
656114c3cd0543d77aa0ac08d8af436ac7f9d32714dmtklein}
65738aeb0fd7a2bdab5e44531d96045dffe25c8e2b0commit-bot@chromium.org
658748ca3bf2d170708f263693e8579e6722389d0efmtklein/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
659748ca3bf2d170708f263693e8579e6722389d0efmtklein
66055e88b226ccb85d2c712a9e3e9e1f5bdcaac05acmtklein// If we're isolating all GPU-bound work to one thread (the default), this function runs all that.
66155e88b226ccb85d2c712a9e3e9e1f5bdcaac05acmtkleinstatic void run_enclave_and_gpu_tests(SkTArray<Task>* tasks) {
66255e88b226ccb85d2c712a9e3e9e1f5bdcaac05acmtklein    run_enclave(tasks);
66355e88b226ccb85d2c712a9e3e9e1f5bdcaac05acmtklein    for (int i = 0; i < gGPUTests.count(); i++) {
66455e88b226ccb85d2c712a9e3e9e1f5bdcaac05acmtklein        run_test(&gGPUTests[i]);
66555e88b226ccb85d2c712a9e3e9e1f5bdcaac05acmtklein    }
66655e88b226ccb85d2c712a9e3e9e1f5bdcaac05acmtklein}
66755e88b226ccb85d2c712a9e3e9e1f5bdcaac05acmtklein
668de6fc2bf464b734f35449c40421064b33cd9e2b4mtklein// Some runs (mostly, Valgrind) are so slow that the bot framework thinks we've hung.
669de6fc2bf464b734f35449c40421064b33cd9e2b4mtklein// This prints something every once in a while so that it knows we're still working.
6702e1c47e13551dfc592bd3d92074f3f4b69c4b6a9mtkleinstatic void start_keepalive() {
6712e1c47e13551dfc592bd3d92074f3f4b69c4b6a9mtklein    struct Loop {
6722e1c47e13551dfc592bd3d92074f3f4b69c4b6a9mtklein        static void forever(void*) {
6732e1c47e13551dfc592bd3d92074f3f4b69c4b6a9mtklein            for (;;) {
6742e1c47e13551dfc592bd3d92074f3f4b69c4b6a9mtklein                static const int kSec = 300;
6752e1c47e13551dfc592bd3d92074f3f4b69c4b6a9mtklein            #if defined(SK_BUILD_FOR_WIN)
6762e1c47e13551dfc592bd3d92074f3f4b69c4b6a9mtklein                Sleep(kSec * 1000);
6772e1c47e13551dfc592bd3d92074f3f4b69c4b6a9mtklein            #else
6782e1c47e13551dfc592bd3d92074f3f4b69c4b6a9mtklein                sleep(kSec);
6792e1c47e13551dfc592bd3d92074f3f4b69c4b6a9mtklein            #endif
680b37cb41a8bfc1bdf65fb8387c24d45da7cf8b7damtklein                SkString running;
681b37cb41a8bfc1bdf65fb8387c24d45da7cf8b7damtklein                {
682b37cb41a8bfc1bdf65fb8387c24d45da7cf8b7damtklein                    SkAutoMutexAcquire lock(gRunningMutex);
683b37cb41a8bfc1bdf65fb8387c24d45da7cf8b7damtklein                    for (int i = 0; i < gRunning.count(); i++) {
684b37cb41a8bfc1bdf65fb8387c24d45da7cf8b7damtklein                        running.appendf("\n\t%s", gRunning[i].c_str());
685b37cb41a8bfc1bdf65fb8387c24d45da7cf8b7damtklein                    }
686b37cb41a8bfc1bdf65fb8387c24d45da7cf8b7damtklein                }
687b37cb41a8bfc1bdf65fb8387c24d45da7cf8b7damtklein                SkDebugf("\nCurrently running:%s\n", running.c_str());
6882e1c47e13551dfc592bd3d92074f3f4b69c4b6a9mtklein            }
6892e1c47e13551dfc592bd3d92074f3f4b69c4b6a9mtklein        }
6902e1c47e13551dfc592bd3d92074f3f4b69c4b6a9mtklein    };
6912e1c47e13551dfc592bd3d92074f3f4b69c4b6a9mtklein    static SkThread* intentionallyLeaked = new SkThread(Loop::forever);
6922e1c47e13551dfc592bd3d92074f3f4b69c4b6a9mtklein    intentionallyLeaked->start();
693de6fc2bf464b734f35449c40421064b33cd9e2b4mtklein}
694de6fc2bf464b734f35449c40421064b33cd9e2b4mtklein
695114c3cd0543d77aa0ac08d8af436ac7f9d32714dmtkleinint dm_main();
696114c3cd0543d77aa0ac08d8af436ac7f9d32714dmtkleinint dm_main() {
697114c3cd0543d77aa0ac08d8af436ac7f9d32714dmtklein    SetupCrashHandler();
698114c3cd0543d77aa0ac08d8af436ac7f9d32714dmtklein    SkAutoGraphics ag;
699114c3cd0543d77aa0ac08d8af436ac7f9d32714dmtklein    SkTaskGroup::Enabler enabled(FLAGS_threads);
700e67164d9b3a0fcc5f7d2a4149041284f7cde31b9mtklein    if (FLAGS_leaks) {
701e67164d9b3a0fcc5f7d2a4149041284f7cde31b9mtklein        SkInstCountPrintLeaksOnExit();
702e67164d9b3a0fcc5f7d2a4149041284f7cde31b9mtklein    }
703709d2c3e5062c5b57f91273bfc11a751f5b2bb88mtklein
7042e1c47e13551dfc592bd3d92074f3f4b69c4b6a9mtklein    start_keepalive();
705de6fc2bf464b734f35449c40421064b33cd9e2b4mtklein
70662bd1a69ea49318aa5022151262c842887e0ecf4mtklein    gather_gold();
70709ed480906881b6f84bb28c772786928ba3a59d6borenet    gather_uninteresting_hashes();
70862bd1a69ea49318aa5022151262c842887e0ecf4mtklein
709748ca3bf2d170708f263693e8579e6722389d0efmtklein    gather_srcs();
710748ca3bf2d170708f263693e8579e6722389d0efmtklein    gather_sinks();
711748ca3bf2d170708f263693e8579e6722389d0efmtklein    gather_tests();
712748ca3bf2d170708f263693e8579e6722389d0efmtklein
71355e88b226ccb85d2c712a9e3e9e1f5bdcaac05acmtklein    gPending = gSrcs.count() * gSinks.count() + gThreadedTests.count() + gGPUTests.count();
714748ca3bf2d170708f263693e8579e6722389d0efmtklein    SkDebugf("%d srcs * %d sinks + %d tests == %d tasks\n",
71555e88b226ccb85d2c712a9e3e9e1f5bdcaac05acmtklein             gSrcs.count(), gSinks.count(), gThreadedTests.count() + gGPUTests.count(), gPending);
716748ca3bf2d170708f263693e8579e6722389d0efmtklein
717748ca3bf2d170708f263693e8579e6722389d0efmtklein    // We try to exploit as much parallelism as is safe.  Most Src/Sink pairs run on any thread,
718748ca3bf2d170708f263693e8579e6722389d0efmtklein    // but Sinks that identify as part of a particular enclave run serially on a single thread.
71982d2843cc59dc048b7d8d1d928dab743d8e85a3bmtklein    // CPU tests run on any thread.  GPU tests depend on --gpu_threading.
720748ca3bf2d170708f263693e8579e6722389d0efmtklein    SkTArray<Task> enclaves[kNumEnclaves];
721748ca3bf2d170708f263693e8579e6722389d0efmtklein    for (int j = 0; j < gSinks.count(); j++) {
722748ca3bf2d170708f263693e8579e6722389d0efmtklein        SkTArray<Task>& tasks = enclaves[gSinks[j]->enclave()];
723748ca3bf2d170708f263693e8579e6722389d0efmtklein        for (int i = 0; i < gSrcs.count(); i++) {
724748ca3bf2d170708f263693e8579e6722389d0efmtklein            tasks.push_back(Task(gSrcs[i], gSinks[j]));
725748ca3bf2d170708f263693e8579e6722389d0efmtklein        }
72638aeb0fd7a2bdab5e44531d96045dffe25c8e2b0commit-bot@chromium.org    }
72738aeb0fd7a2bdab5e44531d96045dffe25c8e2b0commit-bot@chromium.org
728748ca3bf2d170708f263693e8579e6722389d0efmtklein    SkTaskGroup tg;
72955e88b226ccb85d2c712a9e3e9e1f5bdcaac05acmtklein    tg.batch(run_test, gThreadedTests.begin(), gThreadedTests.count());
73055e88b226ccb85d2c712a9e3e9e1f5bdcaac05acmtklein    for (int i = 0; i < kNumEnclaves; i++) {
73155e88b226ccb85d2c712a9e3e9e1f5bdcaac05acmtklein        switch(i) {
73255e88b226ccb85d2c712a9e3e9e1f5bdcaac05acmtklein            case kAnyThread_Enclave:
73355e88b226ccb85d2c712a9e3e9e1f5bdcaac05acmtklein                tg.batch(Task::Run, enclaves[i].begin(), enclaves[i].count());
73455e88b226ccb85d2c712a9e3e9e1f5bdcaac05acmtklein                break;
73555e88b226ccb85d2c712a9e3e9e1f5bdcaac05acmtklein            case kGPU_Enclave:
73655e88b226ccb85d2c712a9e3e9e1f5bdcaac05acmtklein                tg.add(run_enclave_and_gpu_tests, &enclaves[i]);
73755e88b226ccb85d2c712a9e3e9e1f5bdcaac05acmtklein                break;
73855e88b226ccb85d2c712a9e3e9e1f5bdcaac05acmtklein            default:
73955e88b226ccb85d2c712a9e3e9e1f5bdcaac05acmtklein                tg.add(run_enclave, &enclaves[i]);
74055e88b226ccb85d2c712a9e3e9e1f5bdcaac05acmtklein                break;
74182d2843cc59dc048b7d8d1d928dab743d8e85a3bmtklein        }
74255e88b226ccb85d2c712a9e3e9e1f5bdcaac05acmtklein    }
743748ca3bf2d170708f263693e8579e6722389d0efmtklein    tg.wait();
744748ca3bf2d170708f263693e8579e6722389d0efmtklein    // At this point we're back in single-threaded land.
745d36522d12d3e71958e50683a7eef43dc2a47d96dmtklein@google.com
7462f64eec5df75d96178c667ebba0be965eae16440mtklein    SkDebugf("\n");
747748ca3bf2d170708f263693e8579e6722389d0efmtklein    if (gFailures.count() > 0) {
748748ca3bf2d170708f263693e8579e6722389d0efmtklein        SkDebugf("Failures:\n");
749748ca3bf2d170708f263693e8579e6722389d0efmtklein        for (int i = 0; i < gFailures.count(); i++) {
7509dc0910c2cf4cc41a9a7eaa6bcee914844155205mtklein            SkDebugf("\t%s\n", gFailures[i].c_str());
751748ca3bf2d170708f263693e8579e6722389d0efmtklein        }
752748ca3bf2d170708f263693e8579e6722389d0efmtklein        SkDebugf("%d failures\n", gFailures.count());
753748ca3bf2d170708f263693e8579e6722389d0efmtklein        return 1;
754f6139f7c3867a70a750620cd34ce10338a54086emtklein    }
755748ca3bf2d170708f263693e8579e6722389d0efmtklein    if (gPending > 0) {
756748ca3bf2d170708f263693e8579e6722389d0efmtklein        SkDebugf("Hrm, we didn't seem to run everything we intended to!  Please file a bug.\n");
757748ca3bf2d170708f263693e8579e6722389d0efmtklein        return 1;
758992c7b03ef7914a18bfd78e965b0b4c99a5f5672Cary Clark    }
759748ca3bf2d170708f263693e8579e6722389d0efmtklein    return 0;
760d36522d12d3e71958e50683a7eef43dc2a47d96dmtklein@google.com}
7613b27adef0a52f6d321fdee7412ef69e7a7284bccjcgregorio
7624808757d7a8bbe8c773a312a894738e9ff701b5fborenet#if !defined(SK_BUILD_FOR_IOS)
7633b27adef0a52f6d321fdee7412ef69e7a7284bccjcgregorioint main(int argc, char** argv) {
7643b27adef0a52f6d321fdee7412ef69e7a7284bccjcgregorio    SkCommandLineFlags::Parse(argc, argv);
7653b27adef0a52f6d321fdee7412ef69e7a7284bccjcgregorio    return dm_main();
7663b27adef0a52f6d321fdee7412ef69e7a7284bccjcgregorio}
7673b27adef0a52f6d321fdee7412ef69e7a7284bccjcgregorio#endif
768