1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2013 Google Inc.
3*c8dee2aaSAndroid Build Coastguard Worker *
4*c8dee2aaSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker */
7*c8dee2aaSAndroid Build Coastguard Worker
8*c8dee2aaSAndroid Build Coastguard Worker #include "dm/DMJsonWriter.h"
9*c8dee2aaSAndroid Build Coastguard Worker #include "dm/DMSrcSink.h"
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/codec/SkCodec.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/codec/SkEncodedImageFormat.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkBBHFactory.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkColorPriv.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkColorSpace.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkData.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkDocument.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkGraphics.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "src/base/SkHalf.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "src/base/SkLeanWindows.h"
20*c8dee2aaSAndroid Build Coastguard Worker #include "src/base/SkNoDestructor.h"
21*c8dee2aaSAndroid Build Coastguard Worker #include "src/base/SkSpinlock.h"
22*c8dee2aaSAndroid Build Coastguard Worker #include "src/base/SkTime.h"
23*c8dee2aaSAndroid Build Coastguard Worker #include "src/base/SkVx.h"
24*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkChecksum.h"
25*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkColorSpacePriv.h"
26*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkMD5.h"
27*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkOSFile.h"
28*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkStringUtils.h"
29*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkTHash.h"
30*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkTaskGroup.h"
31*c8dee2aaSAndroid Build Coastguard Worker #include "src/utils/SkOSPath.h"
32*c8dee2aaSAndroid Build Coastguard Worker #include "tools/AutoreleasePool.h"
33*c8dee2aaSAndroid Build Coastguard Worker #include "tools/CodecUtils.h"
34*c8dee2aaSAndroid Build Coastguard Worker #include "tools/HashAndEncode.h"
35*c8dee2aaSAndroid Build Coastguard Worker #include "tools/ProcStats.h"
36*c8dee2aaSAndroid Build Coastguard Worker #include "tools/Resources.h"
37*c8dee2aaSAndroid Build Coastguard Worker #include "tools/TestFontDataProvider.h"
38*c8dee2aaSAndroid Build Coastguard Worker #include "tools/ToolUtils.h"
39*c8dee2aaSAndroid Build Coastguard Worker #include "tools/flags/CommonFlags.h"
40*c8dee2aaSAndroid Build Coastguard Worker #include "tools/flags/CommonFlagsConfig.h"
41*c8dee2aaSAndroid Build Coastguard Worker #include "tools/flags/CommonFlagsGanesh.h"
42*c8dee2aaSAndroid Build Coastguard Worker #include "tools/fonts/FontToolUtils.h"
43*c8dee2aaSAndroid Build Coastguard Worker #include "tools/trace/ChromeTracingTracer.h"
44*c8dee2aaSAndroid Build Coastguard Worker #include "tools/trace/EventTracingPriv.h"
45*c8dee2aaSAndroid Build Coastguard Worker #include "tools/trace/SkDebugfTracer.h"
46*c8dee2aaSAndroid Build Coastguard Worker
47*c8dee2aaSAndroid Build Coastguard Worker #include <memory>
48*c8dee2aaSAndroid Build Coastguard Worker #include <vector>
49*c8dee2aaSAndroid Build Coastguard Worker
50*c8dee2aaSAndroid Build Coastguard Worker #include <stdlib.h>
51*c8dee2aaSAndroid Build Coastguard Worker
52*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_GRAPHITE)
53*c8dee2aaSAndroid Build Coastguard Worker #include "tools/flags/CommonFlagsGraphite.h"
54*c8dee2aaSAndroid Build Coastguard Worker #endif
55*c8dee2aaSAndroid Build Coastguard Worker
56*c8dee2aaSAndroid Build Coastguard Worker #if !defined(SK_DISABLE_LEGACY_TESTS)
57*c8dee2aaSAndroid Build Coastguard Worker #include "tests/Test.h"
58*c8dee2aaSAndroid Build Coastguard Worker #include "tests/TestHarness.h"
59*c8dee2aaSAndroid Build Coastguard Worker #endif
60*c8dee2aaSAndroid Build Coastguard Worker
61*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_BUILD_FOR_IOS)
62*c8dee2aaSAndroid Build Coastguard Worker #include "tools/ios_utils.h"
63*c8dee2aaSAndroid Build Coastguard Worker #endif
64*c8dee2aaSAndroid Build Coastguard Worker
65*c8dee2aaSAndroid Build Coastguard Worker #ifndef SK_BUILD_FOR_WIN
66*c8dee2aaSAndroid Build Coastguard Worker #include <unistd.h>
67*c8dee2aaSAndroid Build Coastguard Worker #endif
68*c8dee2aaSAndroid Build Coastguard Worker
69*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_BUILD_FOR_ANDROID_FRAMEWORK) && defined(SK_HAS_HEIF_LIBRARY)
70*c8dee2aaSAndroid Build Coastguard Worker #include <binder/IPCThreadState.h>
71*c8dee2aaSAndroid Build Coastguard Worker #endif
72*c8dee2aaSAndroid Build Coastguard Worker
73*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_BUILD_FOR_MAC)
74*c8dee2aaSAndroid Build Coastguard Worker #include "include/utils/mac/SkCGUtils.h"
75*c8dee2aaSAndroid Build Coastguard Worker #include "src/utils/mac/SkUniqueCFRef.h"
76*c8dee2aaSAndroid Build Coastguard Worker #endif
77*c8dee2aaSAndroid Build Coastguard Worker
78*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_ENABLE_SVG)
79*c8dee2aaSAndroid Build Coastguard Worker #include "modules/svg/include/SkSVGOpenTypeSVGDecoder.h"
80*c8dee2aaSAndroid Build Coastguard Worker #endif
81*c8dee2aaSAndroid Build Coastguard Worker
82*c8dee2aaSAndroid Build Coastguard Worker using namespace skia_private;
83*c8dee2aaSAndroid Build Coastguard Worker
84*c8dee2aaSAndroid Build Coastguard Worker extern bool gSkForceRasterPipelineBlitter;
85*c8dee2aaSAndroid Build Coastguard Worker extern bool gForceHighPrecisionRasterPipeline;
86*c8dee2aaSAndroid Build Coastguard Worker extern bool gCreateProtectedContext;
87*c8dee2aaSAndroid Build Coastguard Worker
88*c8dee2aaSAndroid Build Coastguard Worker static DEFINE_string(src, "tests gm skp mskp lottie rive svg image colorImage",
89*c8dee2aaSAndroid Build Coastguard Worker "Source types to test.");
90*c8dee2aaSAndroid Build Coastguard Worker static DEFINE_bool(nameByHash, false,
91*c8dee2aaSAndroid Build Coastguard Worker "If true, write to FLAGS_writePath[0]/<hash>.png instead of "
92*c8dee2aaSAndroid Build Coastguard Worker "to FLAGS_writePath[0]/<config>/<sourceType>/<sourceOptions>/<name>.png");
93*c8dee2aaSAndroid Build Coastguard Worker static DEFINE_bool2(pathOpsExtended, x, false, "Run extended pathOps tests.");
94*c8dee2aaSAndroid Build Coastguard Worker static DEFINE_string(matrix, "1 0 0 1",
95*c8dee2aaSAndroid Build Coastguard Worker "2x2 scale+skew matrix to apply or upright when using "
96*c8dee2aaSAndroid Build Coastguard Worker "'matrix' or 'upright' in config.");
97*c8dee2aaSAndroid Build Coastguard Worker
98*c8dee2aaSAndroid Build Coastguard Worker static DEFINE_string(skip, "",
99*c8dee2aaSAndroid Build Coastguard Worker "Space-separated config/src/srcOptions/name quadruples to skip. "
100*c8dee2aaSAndroid Build Coastguard Worker "'_' matches anything. '~' negates the match. E.g. \n"
101*c8dee2aaSAndroid Build Coastguard Worker "'--skip gpu skp _ _' will skip all SKPs drawn into the gpu config.\n"
102*c8dee2aaSAndroid Build Coastguard Worker "'--skip gpu skp _ _ 8888 gm _ aarects' will also skip the aarects GM on 8888.\n"
103*c8dee2aaSAndroid Build Coastguard Worker "'--skip ~8888 svg _ svgparse_' blocks non-8888 SVGs that contain \"svgparse_\" in "
104*c8dee2aaSAndroid Build Coastguard Worker "the name.");
105*c8dee2aaSAndroid Build Coastguard Worker
106*c8dee2aaSAndroid Build Coastguard Worker static DEFINE_string2(readPath, r, "",
107*c8dee2aaSAndroid Build Coastguard Worker "If set check for equality with golden results in this directory.");
108*c8dee2aaSAndroid Build Coastguard Worker DEFINE_string2(writePath, w, "", "If set, write bitmaps here as .pngs.");
109*c8dee2aaSAndroid Build Coastguard Worker
110*c8dee2aaSAndroid Build Coastguard Worker
111*c8dee2aaSAndroid Build Coastguard Worker static DEFINE_string(uninterestingHashesFile, "",
112*c8dee2aaSAndroid Build Coastguard Worker "File containing a list of uninteresting hashes. If a result hashes to something in "
113*c8dee2aaSAndroid Build Coastguard Worker "this list, no image is written for that result.");
114*c8dee2aaSAndroid Build Coastguard Worker
115*c8dee2aaSAndroid Build Coastguard Worker static DEFINE_int(shards, 1, "We're splitting source data into this many shards.");
116*c8dee2aaSAndroid Build Coastguard Worker static DEFINE_int(shard, 0, "Which shard do I run?");
117*c8dee2aaSAndroid Build Coastguard Worker
118*c8dee2aaSAndroid Build Coastguard Worker static DEFINE_string(mskps, "", "Directory to read mskps from, or a single mskp file.");
119*c8dee2aaSAndroid Build Coastguard Worker static DEFINE_bool(forceRasterPipeline, false, "sets gSkForceRasterPipelineBlitter");
120*c8dee2aaSAndroid Build Coastguard Worker static DEFINE_bool(forceRasterPipelineHP, false, "sets gSkForceRasterPipelineBlitter and gForceHighPrecisionRasterPipeline");
121*c8dee2aaSAndroid Build Coastguard Worker static DEFINE_bool(createProtected, false, "attempts to create a protected backend context");
122*c8dee2aaSAndroid Build Coastguard Worker
123*c8dee2aaSAndroid Build Coastguard Worker static DEFINE_string(bisect, "",
124*c8dee2aaSAndroid Build Coastguard Worker "Pair of: SKP file to bisect, followed by an l/r bisect trail string (e.g., 'lrll'). The "
125*c8dee2aaSAndroid Build Coastguard Worker "l/r trail specifies which half to keep at each step of a binary search through the SKP's "
126*c8dee2aaSAndroid Build Coastguard Worker "paths. An empty string performs no bisect. Only the SkPaths are bisected; all other draws "
127*c8dee2aaSAndroid Build Coastguard Worker "are thrown out. This is useful for finding a reduced repo case for path drawing bugs.");
128*c8dee2aaSAndroid Build Coastguard Worker
129*c8dee2aaSAndroid Build Coastguard Worker static DEFINE_bool(ignoreSigInt, false, "ignore SIGINT signals during test execution");
130*c8dee2aaSAndroid Build Coastguard Worker
131*c8dee2aaSAndroid Build Coastguard Worker static DEFINE_bool(checkF16, false, "Ensure that F16Norm pixels are clamped.");
132*c8dee2aaSAndroid Build Coastguard Worker
133*c8dee2aaSAndroid Build Coastguard Worker static DEFINE_string(colorImages, "",
134*c8dee2aaSAndroid Build Coastguard Worker "List of images and/or directories to decode with color correction. "
135*c8dee2aaSAndroid Build Coastguard Worker "A directory with no images is treated as a fatal error.");
136*c8dee2aaSAndroid Build Coastguard Worker
137*c8dee2aaSAndroid Build Coastguard Worker static DEFINE_bool2(veryVerbose, V, false, "tell individual tests to be verbose.");
138*c8dee2aaSAndroid Build Coastguard Worker
139*c8dee2aaSAndroid Build Coastguard Worker static DEFINE_bool(cpu, true, "Run CPU-bound work?");
140*c8dee2aaSAndroid Build Coastguard Worker static DEFINE_bool(gpu, true, "Run GPU-bound work?");
141*c8dee2aaSAndroid Build Coastguard Worker static DEFINE_bool(graphite, true, "Run Graphite work?");
142*c8dee2aaSAndroid Build Coastguard Worker
143*c8dee2aaSAndroid Build Coastguard Worker static DEFINE_bool(dryRun, false,
144*c8dee2aaSAndroid Build Coastguard Worker "just print the tests that would be run, without actually running them.");
145*c8dee2aaSAndroid Build Coastguard Worker
146*c8dee2aaSAndroid Build Coastguard Worker static DEFINE_string(images, "",
147*c8dee2aaSAndroid Build Coastguard Worker "List of images and/or directories to decode. A directory with no images"
148*c8dee2aaSAndroid Build Coastguard Worker " is treated as a fatal error.");
149*c8dee2aaSAndroid Build Coastguard Worker
150*c8dee2aaSAndroid Build Coastguard Worker static DEFINE_bool(simpleCodec, false,
151*c8dee2aaSAndroid Build Coastguard Worker "Runs of a subset of the codec tests, "
152*c8dee2aaSAndroid Build Coastguard Worker "with no scaling or subsetting, always using the canvas color type.");
153*c8dee2aaSAndroid Build Coastguard Worker
154*c8dee2aaSAndroid Build Coastguard Worker static DEFINE_string2(match, m, nullptr,
155*c8dee2aaSAndroid Build Coastguard Worker "[~][^]substring[$] [...] of name to run.\n"
156*c8dee2aaSAndroid Build Coastguard Worker "Multiple matches may be separated by spaces.\n"
157*c8dee2aaSAndroid Build Coastguard Worker "~ causes a matching name to always be skipped\n"
158*c8dee2aaSAndroid Build Coastguard Worker "^ requires the start of the name to match\n"
159*c8dee2aaSAndroid Build Coastguard Worker "$ requires the end of the name to match\n"
160*c8dee2aaSAndroid Build Coastguard Worker "^ and $ requires an exact match\n"
161*c8dee2aaSAndroid Build Coastguard Worker "If a name does not match any list entry,\n"
162*c8dee2aaSAndroid Build Coastguard Worker "it is skipped unless some list entry starts with ~");
163*c8dee2aaSAndroid Build Coastguard Worker
164*c8dee2aaSAndroid Build Coastguard Worker static DEFINE_bool2(quiet, q, false, "if true, don't print status updates.");
165*c8dee2aaSAndroid Build Coastguard Worker static DEFINE_bool2(verbose, v, false, "enable verbose output from the test driver.");
166*c8dee2aaSAndroid Build Coastguard Worker
167*c8dee2aaSAndroid Build Coastguard Worker static DEFINE_string(skps, "skps", "Directory to read skps from.");
168*c8dee2aaSAndroid Build Coastguard Worker static DEFINE_string(lotties, "lotties", "Directory to read (Bodymovin) jsons from.");
169*c8dee2aaSAndroid Build Coastguard Worker static DEFINE_string(svgs, "", "Directory to read SVGs from, or a single SVG file.");
170*c8dee2aaSAndroid Build Coastguard Worker
171*c8dee2aaSAndroid Build Coastguard Worker static DEFINE_int_2(threads, j, -1,
172*c8dee2aaSAndroid Build Coastguard Worker "Run threadsafe tests on a threadpool with this many extra threads, "
173*c8dee2aaSAndroid Build Coastguard Worker "defaulting to one extra thread per core.");
174*c8dee2aaSAndroid Build Coastguard Worker
175*c8dee2aaSAndroid Build Coastguard Worker static DEFINE_string(key, "",
176*c8dee2aaSAndroid Build Coastguard Worker "Space-separated key/value pairs to add to JSON identifying this builder.");
177*c8dee2aaSAndroid Build Coastguard Worker static DEFINE_string(properties, "",
178*c8dee2aaSAndroid Build Coastguard Worker "Space-separated key/value pairs to add to JSON identifying this run.");
179*c8dee2aaSAndroid Build Coastguard Worker
180*c8dee2aaSAndroid Build Coastguard Worker static DEFINE_bool(rasterize_pdf, false, "Rasterize PDFs when possible.");
181*c8dee2aaSAndroid Build Coastguard Worker
182*c8dee2aaSAndroid Build Coastguard Worker using namespace DM;
183*c8dee2aaSAndroid Build Coastguard Worker
184*c8dee2aaSAndroid Build Coastguard Worker #if !defined(SK_DISABLE_LEGACY_TESTS)
185*c8dee2aaSAndroid Build Coastguard Worker using skiatest::TestType;
186*c8dee2aaSAndroid Build Coastguard Worker #endif
187*c8dee2aaSAndroid Build Coastguard Worker using sk_gpu_test::GrContextFactory;
188*c8dee2aaSAndroid Build Coastguard Worker using sk_gpu_test::ContextInfo;
189*c8dee2aaSAndroid Build Coastguard Worker #ifdef SK_GL
190*c8dee2aaSAndroid Build Coastguard Worker using sk_gpu_test::GLTestContext;
191*c8dee2aaSAndroid Build Coastguard Worker #endif
192*c8dee2aaSAndroid Build Coastguard Worker
193*c8dee2aaSAndroid Build Coastguard Worker /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
194*c8dee2aaSAndroid Build Coastguard Worker
195*c8dee2aaSAndroid Build Coastguard Worker static FILE* gVLog;
196*c8dee2aaSAndroid Build Coastguard Worker
197*c8dee2aaSAndroid Build Coastguard Worker static void vlog(const char* fmt, ...) SK_PRINTF_LIKE(1, 2);
198*c8dee2aaSAndroid Build Coastguard Worker
vlog(const char * fmt,...)199*c8dee2aaSAndroid Build Coastguard Worker static void vlog(const char* fmt, ...) {
200*c8dee2aaSAndroid Build Coastguard Worker if (gVLog) {
201*c8dee2aaSAndroid Build Coastguard Worker va_list args;
202*c8dee2aaSAndroid Build Coastguard Worker va_start(args, fmt);
203*c8dee2aaSAndroid Build Coastguard Worker vfprintf(gVLog, fmt, args);
204*c8dee2aaSAndroid Build Coastguard Worker fflush(gVLog);
205*c8dee2aaSAndroid Build Coastguard Worker va_end(args);
206*c8dee2aaSAndroid Build Coastguard Worker }
207*c8dee2aaSAndroid Build Coastguard Worker }
208*c8dee2aaSAndroid Build Coastguard Worker
209*c8dee2aaSAndroid Build Coastguard Worker static void info(const char* fmt, ...) SK_PRINTF_LIKE(1, 2);
210*c8dee2aaSAndroid Build Coastguard Worker
info(const char * fmt,...)211*c8dee2aaSAndroid Build Coastguard Worker static void info(const char* fmt, ...) {
212*c8dee2aaSAndroid Build Coastguard Worker va_list args;
213*c8dee2aaSAndroid Build Coastguard Worker va_start(args, fmt);
214*c8dee2aaSAndroid Build Coastguard Worker
215*c8dee2aaSAndroid Build Coastguard Worker if (gVLog) {
216*c8dee2aaSAndroid Build Coastguard Worker va_list vlogArgs;
217*c8dee2aaSAndroid Build Coastguard Worker va_copy(vlogArgs, args);
218*c8dee2aaSAndroid Build Coastguard Worker vfprintf(gVLog, fmt, vlogArgs);
219*c8dee2aaSAndroid Build Coastguard Worker fflush(gVLog);
220*c8dee2aaSAndroid Build Coastguard Worker va_end(vlogArgs);
221*c8dee2aaSAndroid Build Coastguard Worker }
222*c8dee2aaSAndroid Build Coastguard Worker
223*c8dee2aaSAndroid Build Coastguard Worker if (!FLAGS_quiet) {
224*c8dee2aaSAndroid Build Coastguard Worker vprintf(fmt, args);
225*c8dee2aaSAndroid Build Coastguard Worker }
226*c8dee2aaSAndroid Build Coastguard Worker
227*c8dee2aaSAndroid Build Coastguard Worker va_end(args);
228*c8dee2aaSAndroid Build Coastguard Worker }
229*c8dee2aaSAndroid Build Coastguard Worker
230*c8dee2aaSAndroid Build Coastguard Worker static TArray<SkString>* gFailures = new TArray<SkString>;
231*c8dee2aaSAndroid Build Coastguard Worker
fail(const SkString & err)232*c8dee2aaSAndroid Build Coastguard Worker static void fail(const SkString& err) {
233*c8dee2aaSAndroid Build Coastguard Worker static SkSpinlock mutex;
234*c8dee2aaSAndroid Build Coastguard Worker SkAutoSpinlock lock(mutex);
235*c8dee2aaSAndroid Build Coastguard Worker SkDebugf("\n\nFAILURE: %s\n\n", err.c_str());
236*c8dee2aaSAndroid Build Coastguard Worker gFailures->push_back(err);
237*c8dee2aaSAndroid Build Coastguard Worker }
238*c8dee2aaSAndroid Build Coastguard Worker
239*c8dee2aaSAndroid Build Coastguard Worker struct Running {
240*c8dee2aaSAndroid Build Coastguard Worker SkString id;
241*c8dee2aaSAndroid Build Coastguard Worker SkThreadID thread;
242*c8dee2aaSAndroid Build Coastguard Worker
dumpRunning243*c8dee2aaSAndroid Build Coastguard Worker void dump() const {
244*c8dee2aaSAndroid Build Coastguard Worker info("\t%s\n", id.c_str());
245*c8dee2aaSAndroid Build Coastguard Worker }
246*c8dee2aaSAndroid Build Coastguard Worker };
247*c8dee2aaSAndroid Build Coastguard Worker
dump_json()248*c8dee2aaSAndroid Build Coastguard Worker static void dump_json() {
249*c8dee2aaSAndroid Build Coastguard Worker if (!FLAGS_writePath.isEmpty()) {
250*c8dee2aaSAndroid Build Coastguard Worker JsonWriter::DumpJson(FLAGS_writePath[0], FLAGS_key, FLAGS_properties);
251*c8dee2aaSAndroid Build Coastguard Worker }
252*c8dee2aaSAndroid Build Coastguard Worker }
253*c8dee2aaSAndroid Build Coastguard Worker
254*c8dee2aaSAndroid Build Coastguard Worker // We use a spinlock to make locking this in a signal handler _somewhat_ safe.
255*c8dee2aaSAndroid Build Coastguard Worker static SkSpinlock gMutex;
256*c8dee2aaSAndroid Build Coastguard Worker static int gPending;
257*c8dee2aaSAndroid Build Coastguard Worker static int gTotalCounts;
258*c8dee2aaSAndroid Build Coastguard Worker static double gLastUpdate;
259*c8dee2aaSAndroid Build Coastguard Worker static SkNoDestructor<TArray<Running>> gRunning;
260*c8dee2aaSAndroid Build Coastguard Worker
done(const char * config,const char * src,const char * srcOptions,const char * name)261*c8dee2aaSAndroid Build Coastguard Worker static void done(const char* config, const char* src, const char* srcOptions, const char* name) {
262*c8dee2aaSAndroid Build Coastguard Worker SkString id = SkStringPrintf("%s %s %s %s", config, src, srcOptions, name);
263*c8dee2aaSAndroid Build Coastguard Worker bool updateDueToProgress;
264*c8dee2aaSAndroid Build Coastguard Worker double lastUpdate;
265*c8dee2aaSAndroid Build Coastguard Worker int totalCounts;
266*c8dee2aaSAndroid Build Coastguard Worker int pending;
267*c8dee2aaSAndroid Build Coastguard Worker {
268*c8dee2aaSAndroid Build Coastguard Worker SkAutoSpinlock lock(gMutex);
269*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < gRunning->size(); i++) {
270*c8dee2aaSAndroid Build Coastguard Worker if (gRunning->at(i).id == id) {
271*c8dee2aaSAndroid Build Coastguard Worker gRunning->removeShuffle(i);
272*c8dee2aaSAndroid Build Coastguard Worker break;
273*c8dee2aaSAndroid Build Coastguard Worker }
274*c8dee2aaSAndroid Build Coastguard Worker }
275*c8dee2aaSAndroid Build Coastguard Worker --gPending;
276*c8dee2aaSAndroid Build Coastguard Worker updateDueToProgress = gPending % 500 == 0;
277*c8dee2aaSAndroid Build Coastguard Worker lastUpdate = gLastUpdate;
278*c8dee2aaSAndroid Build Coastguard Worker totalCounts = gTotalCounts;
279*c8dee2aaSAndroid Build Coastguard Worker pending = gPending;
280*c8dee2aaSAndroid Build Coastguard Worker }
281*c8dee2aaSAndroid Build Coastguard Worker vlog("[%d/%d] %s done\n", totalCounts - pending, totalCounts, id.c_str());
282*c8dee2aaSAndroid Build Coastguard Worker
283*c8dee2aaSAndroid Build Coastguard Worker // We write out dm.json file and print out a progress update every once in a while.
284*c8dee2aaSAndroid Build Coastguard Worker // Notice this also handles the final dm.json and progress update when pending == 0.
285*c8dee2aaSAndroid Build Coastguard Worker double now = SkTime::GetNSecs();
286*c8dee2aaSAndroid Build Coastguard Worker bool updateDueToTime = now - lastUpdate > 4e9;
287*c8dee2aaSAndroid Build Coastguard Worker if (updateDueToProgress || updateDueToTime) {
288*c8dee2aaSAndroid Build Coastguard Worker dump_json();
289*c8dee2aaSAndroid Build Coastguard Worker
290*c8dee2aaSAndroid Build Coastguard Worker int curr = sk_tools::getCurrResidentSetSizeMB(),
291*c8dee2aaSAndroid Build Coastguard Worker peak = sk_tools::getMaxResidentSetSizeMB();
292*c8dee2aaSAndroid Build Coastguard Worker
293*c8dee2aaSAndroid Build Coastguard Worker SkAutoSpinlock lock(gMutex);
294*c8dee2aaSAndroid Build Coastguard Worker
295*c8dee2aaSAndroid Build Coastguard Worker // Since multiple threads can call `done`, it's possible that another thread has raced with
296*c8dee2aaSAndroid Build Coastguard Worker // this one and printed an update since we did our progress check above. We detect this case
297*c8dee2aaSAndroid Build Coastguard Worker // by checking to see if `gLastUpdate` has changed; if so, we don't need to print anything.
298*c8dee2aaSAndroid Build Coastguard Worker if (lastUpdate == gLastUpdate) {
299*c8dee2aaSAndroid Build Coastguard Worker info("\n[%d/%d] %dMB RAM, %dMB peak, %d queued, %d threads:\n\t%s done\n",
300*c8dee2aaSAndroid Build Coastguard Worker gTotalCounts - gPending, gTotalCounts,
301*c8dee2aaSAndroid Build Coastguard Worker curr, peak, gPending - gRunning->size(), gRunning->size() + 1, id.c_str());
302*c8dee2aaSAndroid Build Coastguard Worker for (auto& task : *gRunning) {
303*c8dee2aaSAndroid Build Coastguard Worker task.dump();
304*c8dee2aaSAndroid Build Coastguard Worker }
305*c8dee2aaSAndroid Build Coastguard Worker gLastUpdate = now;
306*c8dee2aaSAndroid Build Coastguard Worker }
307*c8dee2aaSAndroid Build Coastguard Worker }
308*c8dee2aaSAndroid Build Coastguard Worker }
309*c8dee2aaSAndroid Build Coastguard Worker
start(const char * config,const char * src,const char * srcOptions,const char * name)310*c8dee2aaSAndroid Build Coastguard Worker static void start(const char* config, const char* src, const char* srcOptions, const char* name) {
311*c8dee2aaSAndroid Build Coastguard Worker SkString id = SkStringPrintf("%s %s %s %s", config, src, srcOptions, name);
312*c8dee2aaSAndroid Build Coastguard Worker vlog("\tstart %s\n", id.c_str());
313*c8dee2aaSAndroid Build Coastguard Worker SkAutoSpinlock lock(gMutex);
314*c8dee2aaSAndroid Build Coastguard Worker gRunning->push_back({id,SkGetThreadID()});
315*c8dee2aaSAndroid Build Coastguard Worker }
316*c8dee2aaSAndroid Build Coastguard Worker
find_culprit()317*c8dee2aaSAndroid Build Coastguard Worker static void find_culprit() {
318*c8dee2aaSAndroid Build Coastguard Worker // Assumes gMutex is locked.
319*c8dee2aaSAndroid Build Coastguard Worker SkThreadID thisThread = SkGetThreadID();
320*c8dee2aaSAndroid Build Coastguard Worker for (auto& task : *gRunning) {
321*c8dee2aaSAndroid Build Coastguard Worker if (task.thread == thisThread) {
322*c8dee2aaSAndroid Build Coastguard Worker info("Likely culprit:\n");
323*c8dee2aaSAndroid Build Coastguard Worker task.dump();
324*c8dee2aaSAndroid Build Coastguard Worker }
325*c8dee2aaSAndroid Build Coastguard Worker }
326*c8dee2aaSAndroid Build Coastguard Worker }
327*c8dee2aaSAndroid Build Coastguard Worker
328*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_BUILD_FOR_WIN)
crash_handler(EXCEPTION_POINTERS * e)329*c8dee2aaSAndroid Build Coastguard Worker static LONG WINAPI crash_handler(EXCEPTION_POINTERS* e) {
330*c8dee2aaSAndroid Build Coastguard Worker static const struct {
331*c8dee2aaSAndroid Build Coastguard Worker const char* name;
332*c8dee2aaSAndroid Build Coastguard Worker DWORD code;
333*c8dee2aaSAndroid Build Coastguard Worker } kExceptions[] = {
334*c8dee2aaSAndroid Build Coastguard Worker #define _(E) {#E, E}
335*c8dee2aaSAndroid Build Coastguard Worker _(EXCEPTION_ACCESS_VIOLATION),
336*c8dee2aaSAndroid Build Coastguard Worker _(EXCEPTION_BREAKPOINT),
337*c8dee2aaSAndroid Build Coastguard Worker _(EXCEPTION_INT_DIVIDE_BY_ZERO),
338*c8dee2aaSAndroid Build Coastguard Worker _(EXCEPTION_STACK_OVERFLOW),
339*c8dee2aaSAndroid Build Coastguard Worker // TODO: more?
340*c8dee2aaSAndroid Build Coastguard Worker #undef _
341*c8dee2aaSAndroid Build Coastguard Worker };
342*c8dee2aaSAndroid Build Coastguard Worker
343*c8dee2aaSAndroid Build Coastguard Worker SkAutoSpinlock lock(gMutex);
344*c8dee2aaSAndroid Build Coastguard Worker
345*c8dee2aaSAndroid Build Coastguard Worker const DWORD code = e->ExceptionRecord->ExceptionCode;
346*c8dee2aaSAndroid Build Coastguard Worker info("\nCaught exception %lu", code);
347*c8dee2aaSAndroid Build Coastguard Worker for (const auto& exception : kExceptions) {
348*c8dee2aaSAndroid Build Coastguard Worker if (exception.code == code) {
349*c8dee2aaSAndroid Build Coastguard Worker info(" %s", exception.name);
350*c8dee2aaSAndroid Build Coastguard Worker }
351*c8dee2aaSAndroid Build Coastguard Worker }
352*c8dee2aaSAndroid Build Coastguard Worker info(", was running:\n");
353*c8dee2aaSAndroid Build Coastguard Worker for (auto& task : *gRunning) {
354*c8dee2aaSAndroid Build Coastguard Worker task.dump();
355*c8dee2aaSAndroid Build Coastguard Worker }
356*c8dee2aaSAndroid Build Coastguard Worker find_culprit();
357*c8dee2aaSAndroid Build Coastguard Worker fflush(stdout);
358*c8dee2aaSAndroid Build Coastguard Worker
359*c8dee2aaSAndroid Build Coastguard Worker // Execute default exception handler... hopefully, exit.
360*c8dee2aaSAndroid Build Coastguard Worker return EXCEPTION_EXECUTE_HANDLER;
361*c8dee2aaSAndroid Build Coastguard Worker }
362*c8dee2aaSAndroid Build Coastguard Worker
setup_crash_handler()363*c8dee2aaSAndroid Build Coastguard Worker static void setup_crash_handler() {
364*c8dee2aaSAndroid Build Coastguard Worker SetUnhandledExceptionFilter(crash_handler);
365*c8dee2aaSAndroid Build Coastguard Worker }
366*c8dee2aaSAndroid Build Coastguard Worker #else
367*c8dee2aaSAndroid Build Coastguard Worker #include <signal.h>
368*c8dee2aaSAndroid Build Coastguard Worker #if !defined(SK_BUILD_FOR_ANDROID)
369*c8dee2aaSAndroid Build Coastguard Worker #include <execinfo.h>
370*c8dee2aaSAndroid Build Coastguard Worker #endif
371*c8dee2aaSAndroid Build Coastguard Worker
max_of()372*c8dee2aaSAndroid Build Coastguard Worker static constexpr int max_of() { return 0; }
373*c8dee2aaSAndroid Build Coastguard Worker template <typename... Rest>
max_of(int x,Rest...rest)374*c8dee2aaSAndroid Build Coastguard Worker static constexpr int max_of(int x, Rest... rest) {
375*c8dee2aaSAndroid Build Coastguard Worker return x > max_of(rest...) ? x : max_of(rest...);
376*c8dee2aaSAndroid Build Coastguard Worker }
377*c8dee2aaSAndroid Build Coastguard Worker
378*c8dee2aaSAndroid Build Coastguard Worker static void (*previous_handler[max_of(SIGABRT,SIGBUS,SIGFPE,SIGILL,SIGSEGV,SIGTERM)+1])(int);
379*c8dee2aaSAndroid Build Coastguard Worker
crash_handler(int sig)380*c8dee2aaSAndroid Build Coastguard Worker static void crash_handler(int sig) {
381*c8dee2aaSAndroid Build Coastguard Worker SkAutoSpinlock lock(gMutex);
382*c8dee2aaSAndroid Build Coastguard Worker
383*c8dee2aaSAndroid Build Coastguard Worker info("\nCaught signal %d [%s] (%dMB RAM, peak %dMB), was running:\n",
384*c8dee2aaSAndroid Build Coastguard Worker sig, strsignal(sig),
385*c8dee2aaSAndroid Build Coastguard Worker sk_tools::getCurrResidentSetSizeMB(), sk_tools::getMaxResidentSetSizeMB());
386*c8dee2aaSAndroid Build Coastguard Worker
387*c8dee2aaSAndroid Build Coastguard Worker for (auto& task : *gRunning) {
388*c8dee2aaSAndroid Build Coastguard Worker task.dump();
389*c8dee2aaSAndroid Build Coastguard Worker }
390*c8dee2aaSAndroid Build Coastguard Worker find_culprit();
391*c8dee2aaSAndroid Build Coastguard Worker
392*c8dee2aaSAndroid Build Coastguard Worker #if !defined(SK_BUILD_FOR_ANDROID)
393*c8dee2aaSAndroid Build Coastguard Worker void* stack[128];
394*c8dee2aaSAndroid Build Coastguard Worker int count = backtrace(stack, std::size(stack));
395*c8dee2aaSAndroid Build Coastguard Worker char** symbols = backtrace_symbols(stack, count);
396*c8dee2aaSAndroid Build Coastguard Worker info("\nStack trace:\n");
397*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < count; i++) {
398*c8dee2aaSAndroid Build Coastguard Worker info(" %s\n", symbols[i]);
399*c8dee2aaSAndroid Build Coastguard Worker }
400*c8dee2aaSAndroid Build Coastguard Worker #endif
401*c8dee2aaSAndroid Build Coastguard Worker fflush(stdout);
402*c8dee2aaSAndroid Build Coastguard Worker
403*c8dee2aaSAndroid Build Coastguard Worker if (sig == SIGINT && FLAGS_ignoreSigInt) {
404*c8dee2aaSAndroid Build Coastguard Worker info("Ignoring signal %d because of --ignoreSigInt.\n"
405*c8dee2aaSAndroid Build Coastguard Worker "This is probably a sign the bot is overloaded with work.\n", sig);
406*c8dee2aaSAndroid Build Coastguard Worker } else {
407*c8dee2aaSAndroid Build Coastguard Worker signal(sig, previous_handler[sig]);
408*c8dee2aaSAndroid Build Coastguard Worker raise(sig);
409*c8dee2aaSAndroid Build Coastguard Worker }
410*c8dee2aaSAndroid Build Coastguard Worker }
411*c8dee2aaSAndroid Build Coastguard Worker
setup_crash_handler()412*c8dee2aaSAndroid Build Coastguard Worker static void setup_crash_handler() {
413*c8dee2aaSAndroid Build Coastguard Worker const int kSignals[] = { SIGABRT, SIGBUS, SIGFPE, SIGILL, SIGINT, SIGSEGV, SIGTERM };
414*c8dee2aaSAndroid Build Coastguard Worker for (int sig : kSignals) {
415*c8dee2aaSAndroid Build Coastguard Worker previous_handler[sig] = signal(sig, crash_handler);
416*c8dee2aaSAndroid Build Coastguard Worker }
417*c8dee2aaSAndroid Build Coastguard Worker }
418*c8dee2aaSAndroid Build Coastguard Worker #endif
419*c8dee2aaSAndroid Build Coastguard Worker
420*c8dee2aaSAndroid Build Coastguard Worker /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
421*c8dee2aaSAndroid Build Coastguard Worker
422*c8dee2aaSAndroid Build Coastguard Worker struct Gold : public SkString {
GoldGold423*c8dee2aaSAndroid Build Coastguard Worker Gold() : SkString("") {}
GoldGold424*c8dee2aaSAndroid Build Coastguard Worker Gold(const SkString& sink, const SkString& src,
425*c8dee2aaSAndroid Build Coastguard Worker const SkString& srcOptions, const SkString& name,
426*c8dee2aaSAndroid Build Coastguard Worker const SkString& md5)
427*c8dee2aaSAndroid Build Coastguard Worker : SkString("") {
428*c8dee2aaSAndroid Build Coastguard Worker this->append(sink);
429*c8dee2aaSAndroid Build Coastguard Worker this->append(src);
430*c8dee2aaSAndroid Build Coastguard Worker this->append(srcOptions);
431*c8dee2aaSAndroid Build Coastguard Worker this->append(name);
432*c8dee2aaSAndroid Build Coastguard Worker this->append(md5);
433*c8dee2aaSAndroid Build Coastguard Worker }
434*c8dee2aaSAndroid Build Coastguard Worker struct Hash {
operator ()Gold::Hash435*c8dee2aaSAndroid Build Coastguard Worker uint32_t operator()(const Gold& g) const {
436*c8dee2aaSAndroid Build Coastguard Worker return SkGoodHash()((const SkString&)g);
437*c8dee2aaSAndroid Build Coastguard Worker }
438*c8dee2aaSAndroid Build Coastguard Worker };
439*c8dee2aaSAndroid Build Coastguard Worker };
440*c8dee2aaSAndroid Build Coastguard Worker static THashSet<Gold, Gold::Hash>* gGold = new THashSet<Gold, Gold::Hash>;
441*c8dee2aaSAndroid Build Coastguard Worker
add_gold(JsonWriter::BitmapResult r)442*c8dee2aaSAndroid Build Coastguard Worker static void add_gold(JsonWriter::BitmapResult r) {
443*c8dee2aaSAndroid Build Coastguard Worker gGold->add(Gold(r.config, r.sourceType, r.sourceOptions, r.name, r.md5));
444*c8dee2aaSAndroid Build Coastguard Worker }
445*c8dee2aaSAndroid Build Coastguard Worker
gather_gold()446*c8dee2aaSAndroid Build Coastguard Worker static void gather_gold() {
447*c8dee2aaSAndroid Build Coastguard Worker if (!FLAGS_readPath.isEmpty()) {
448*c8dee2aaSAndroid Build Coastguard Worker SkString path(FLAGS_readPath[0]);
449*c8dee2aaSAndroid Build Coastguard Worker path.append("/dm.json");
450*c8dee2aaSAndroid Build Coastguard Worker if (!JsonWriter::ReadJson(path.c_str(), add_gold)) {
451*c8dee2aaSAndroid Build Coastguard Worker fail(SkStringPrintf("Couldn't read %s for golden results.", path.c_str()));
452*c8dee2aaSAndroid Build Coastguard Worker }
453*c8dee2aaSAndroid Build Coastguard Worker }
454*c8dee2aaSAndroid Build Coastguard Worker }
455*c8dee2aaSAndroid Build Coastguard Worker
456*c8dee2aaSAndroid Build Coastguard Worker /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
457*c8dee2aaSAndroid Build Coastguard Worker
458*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_BUILD_FOR_WIN)
459*c8dee2aaSAndroid Build Coastguard Worker static constexpr char kNewline[] = "\r\n";
460*c8dee2aaSAndroid Build Coastguard Worker #else
461*c8dee2aaSAndroid Build Coastguard Worker static constexpr char kNewline[] = "\n";
462*c8dee2aaSAndroid Build Coastguard Worker #endif
463*c8dee2aaSAndroid Build Coastguard Worker
464*c8dee2aaSAndroid Build Coastguard Worker static THashSet<SkString>* gUninterestingHashes = new THashSet<SkString>;
465*c8dee2aaSAndroid Build Coastguard Worker
gather_uninteresting_hashes()466*c8dee2aaSAndroid Build Coastguard Worker static void gather_uninteresting_hashes() {
467*c8dee2aaSAndroid Build Coastguard Worker if (!FLAGS_uninterestingHashesFile.isEmpty()) {
468*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkData> data(SkData::MakeFromFileName(FLAGS_uninterestingHashesFile[0]));
469*c8dee2aaSAndroid Build Coastguard Worker if (!data) {
470*c8dee2aaSAndroid Build Coastguard Worker info("WARNING: unable to read uninteresting hashes from %s\n",
471*c8dee2aaSAndroid Build Coastguard Worker FLAGS_uninterestingHashesFile[0]);
472*c8dee2aaSAndroid Build Coastguard Worker return;
473*c8dee2aaSAndroid Build Coastguard Worker }
474*c8dee2aaSAndroid Build Coastguard Worker
475*c8dee2aaSAndroid Build Coastguard Worker // Copy to a string to make sure SkStrSplit has a terminating \0 to find.
476*c8dee2aaSAndroid Build Coastguard Worker SkString contents((const char*)data->data(), data->size());
477*c8dee2aaSAndroid Build Coastguard Worker
478*c8dee2aaSAndroid Build Coastguard Worker TArray<SkString> hashes;
479*c8dee2aaSAndroid Build Coastguard Worker SkStrSplit(contents.c_str(), kNewline, &hashes);
480*c8dee2aaSAndroid Build Coastguard Worker for (const SkString& hash : hashes) {
481*c8dee2aaSAndroid Build Coastguard Worker gUninterestingHashes->add(hash);
482*c8dee2aaSAndroid Build Coastguard Worker }
483*c8dee2aaSAndroid Build Coastguard Worker info("FYI: loaded %d distinct uninteresting hashes from %d lines\n",
484*c8dee2aaSAndroid Build Coastguard Worker gUninterestingHashes->count(), hashes.size());
485*c8dee2aaSAndroid Build Coastguard Worker }
486*c8dee2aaSAndroid Build Coastguard Worker }
487*c8dee2aaSAndroid Build Coastguard Worker
488*c8dee2aaSAndroid Build Coastguard Worker /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
489*c8dee2aaSAndroid Build Coastguard Worker
490*c8dee2aaSAndroid Build Coastguard Worker struct TaggedSrc : public std::unique_ptr<Src> {
491*c8dee2aaSAndroid Build Coastguard Worker SkString tag;
492*c8dee2aaSAndroid Build Coastguard Worker SkString options;
493*c8dee2aaSAndroid Build Coastguard Worker };
494*c8dee2aaSAndroid Build Coastguard Worker
495*c8dee2aaSAndroid Build Coastguard Worker struct TaggedSink : public std::unique_ptr<Sink> {
496*c8dee2aaSAndroid Build Coastguard Worker SkString tag;
497*c8dee2aaSAndroid Build Coastguard Worker };
498*c8dee2aaSAndroid Build Coastguard Worker
499*c8dee2aaSAndroid Build Coastguard Worker static constexpr bool kMemcpyOK = true;
500*c8dee2aaSAndroid Build Coastguard Worker
501*c8dee2aaSAndroid Build Coastguard Worker static TArray<TaggedSrc, kMemcpyOK>* gSrcs = new TArray<TaggedSrc, kMemcpyOK>;
502*c8dee2aaSAndroid Build Coastguard Worker static TArray<TaggedSink, kMemcpyOK>* gSinks = new TArray<TaggedSink, kMemcpyOK>;
503*c8dee2aaSAndroid Build Coastguard Worker
in_shard()504*c8dee2aaSAndroid Build Coastguard Worker static bool in_shard() {
505*c8dee2aaSAndroid Build Coastguard Worker static int N = 0;
506*c8dee2aaSAndroid Build Coastguard Worker return N++ % FLAGS_shards == FLAGS_shard;
507*c8dee2aaSAndroid Build Coastguard Worker }
508*c8dee2aaSAndroid Build Coastguard Worker
push_src(const char * tag,ImplicitString options,Src * inSrc)509*c8dee2aaSAndroid Build Coastguard Worker static void push_src(const char* tag, ImplicitString options, Src* inSrc) {
510*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<Src> src(inSrc);
511*c8dee2aaSAndroid Build Coastguard Worker if (in_shard() && FLAGS_src.contains(tag) &&
512*c8dee2aaSAndroid Build Coastguard Worker !CommandLineFlags::ShouldSkip(FLAGS_match, src->name().c_str())) {
513*c8dee2aaSAndroid Build Coastguard Worker TaggedSrc& s = gSrcs->push_back();
514*c8dee2aaSAndroid Build Coastguard Worker s.reset(src.release()); // NOLINT(misc-uniqueptr-reset-release)
515*c8dee2aaSAndroid Build Coastguard Worker s.tag = tag;
516*c8dee2aaSAndroid Build Coastguard Worker s.options = options;
517*c8dee2aaSAndroid Build Coastguard Worker }
518*c8dee2aaSAndroid Build Coastguard Worker }
519*c8dee2aaSAndroid Build Coastguard Worker
push_codec_src(Path path,CodecSrc::Mode mode,CodecSrc::DstColorType dstColorType,SkAlphaType dstAlphaType,float scale)520*c8dee2aaSAndroid Build Coastguard Worker static void push_codec_src(Path path, CodecSrc::Mode mode, CodecSrc::DstColorType dstColorType,
521*c8dee2aaSAndroid Build Coastguard Worker SkAlphaType dstAlphaType, float scale) {
522*c8dee2aaSAndroid Build Coastguard Worker if (FLAGS_simpleCodec) {
523*c8dee2aaSAndroid Build Coastguard Worker const bool simple = CodecSrc::kCodec_Mode == mode || CodecSrc::kAnimated_Mode == mode;
524*c8dee2aaSAndroid Build Coastguard Worker if (!simple || dstColorType != CodecSrc::kGetFromCanvas_DstColorType || scale != 1.0f) {
525*c8dee2aaSAndroid Build Coastguard Worker // Only decode in the simple case.
526*c8dee2aaSAndroid Build Coastguard Worker return;
527*c8dee2aaSAndroid Build Coastguard Worker }
528*c8dee2aaSAndroid Build Coastguard Worker }
529*c8dee2aaSAndroid Build Coastguard Worker SkString folder;
530*c8dee2aaSAndroid Build Coastguard Worker switch (mode) {
531*c8dee2aaSAndroid Build Coastguard Worker case CodecSrc::kCodec_Mode:
532*c8dee2aaSAndroid Build Coastguard Worker folder.append("codec");
533*c8dee2aaSAndroid Build Coastguard Worker break;
534*c8dee2aaSAndroid Build Coastguard Worker case CodecSrc::kCodecZeroInit_Mode:
535*c8dee2aaSAndroid Build Coastguard Worker folder.append("codec_zero_init");
536*c8dee2aaSAndroid Build Coastguard Worker break;
537*c8dee2aaSAndroid Build Coastguard Worker case CodecSrc::kScanline_Mode:
538*c8dee2aaSAndroid Build Coastguard Worker folder.append("scanline");
539*c8dee2aaSAndroid Build Coastguard Worker break;
540*c8dee2aaSAndroid Build Coastguard Worker case CodecSrc::kStripe_Mode:
541*c8dee2aaSAndroid Build Coastguard Worker folder.append("stripe");
542*c8dee2aaSAndroid Build Coastguard Worker break;
543*c8dee2aaSAndroid Build Coastguard Worker case CodecSrc::kCroppedScanline_Mode:
544*c8dee2aaSAndroid Build Coastguard Worker folder.append("crop");
545*c8dee2aaSAndroid Build Coastguard Worker break;
546*c8dee2aaSAndroid Build Coastguard Worker case CodecSrc::kSubset_Mode:
547*c8dee2aaSAndroid Build Coastguard Worker folder.append("codec_subset");
548*c8dee2aaSAndroid Build Coastguard Worker break;
549*c8dee2aaSAndroid Build Coastguard Worker case CodecSrc::kAnimated_Mode:
550*c8dee2aaSAndroid Build Coastguard Worker folder.append("codec_animated");
551*c8dee2aaSAndroid Build Coastguard Worker break;
552*c8dee2aaSAndroid Build Coastguard Worker }
553*c8dee2aaSAndroid Build Coastguard Worker
554*c8dee2aaSAndroid Build Coastguard Worker switch (dstColorType) {
555*c8dee2aaSAndroid Build Coastguard Worker case CodecSrc::kGrayscale_Always_DstColorType:
556*c8dee2aaSAndroid Build Coastguard Worker folder.append("_kGray8");
557*c8dee2aaSAndroid Build Coastguard Worker break;
558*c8dee2aaSAndroid Build Coastguard Worker case CodecSrc::kNonNative8888_Always_DstColorType:
559*c8dee2aaSAndroid Build Coastguard Worker folder.append("_kNonNative");
560*c8dee2aaSAndroid Build Coastguard Worker break;
561*c8dee2aaSAndroid Build Coastguard Worker default:
562*c8dee2aaSAndroid Build Coastguard Worker break;
563*c8dee2aaSAndroid Build Coastguard Worker }
564*c8dee2aaSAndroid Build Coastguard Worker
565*c8dee2aaSAndroid Build Coastguard Worker switch (dstAlphaType) {
566*c8dee2aaSAndroid Build Coastguard Worker case kPremul_SkAlphaType:
567*c8dee2aaSAndroid Build Coastguard Worker folder.append("_premul");
568*c8dee2aaSAndroid Build Coastguard Worker break;
569*c8dee2aaSAndroid Build Coastguard Worker case kUnpremul_SkAlphaType:
570*c8dee2aaSAndroid Build Coastguard Worker folder.append("_unpremul");
571*c8dee2aaSAndroid Build Coastguard Worker break;
572*c8dee2aaSAndroid Build Coastguard Worker default:
573*c8dee2aaSAndroid Build Coastguard Worker break;
574*c8dee2aaSAndroid Build Coastguard Worker }
575*c8dee2aaSAndroid Build Coastguard Worker
576*c8dee2aaSAndroid Build Coastguard Worker if (1.0f != scale) {
577*c8dee2aaSAndroid Build Coastguard Worker folder.appendf("_%.3f", scale);
578*c8dee2aaSAndroid Build Coastguard Worker }
579*c8dee2aaSAndroid Build Coastguard Worker
580*c8dee2aaSAndroid Build Coastguard Worker CodecSrc* src = new CodecSrc(path, mode, dstColorType, dstAlphaType, scale);
581*c8dee2aaSAndroid Build Coastguard Worker push_src("image", folder, src);
582*c8dee2aaSAndroid Build Coastguard Worker }
583*c8dee2aaSAndroid Build Coastguard Worker
push_android_codec_src(Path path,CodecSrc::DstColorType dstColorType,SkAlphaType dstAlphaType,int sampleSize)584*c8dee2aaSAndroid Build Coastguard Worker static void push_android_codec_src(Path path, CodecSrc::DstColorType dstColorType,
585*c8dee2aaSAndroid Build Coastguard Worker SkAlphaType dstAlphaType, int sampleSize) {
586*c8dee2aaSAndroid Build Coastguard Worker SkString folder;
587*c8dee2aaSAndroid Build Coastguard Worker folder.append("scaled_codec");
588*c8dee2aaSAndroid Build Coastguard Worker
589*c8dee2aaSAndroid Build Coastguard Worker switch (dstColorType) {
590*c8dee2aaSAndroid Build Coastguard Worker case CodecSrc::kGrayscale_Always_DstColorType:
591*c8dee2aaSAndroid Build Coastguard Worker folder.append("_kGray8");
592*c8dee2aaSAndroid Build Coastguard Worker break;
593*c8dee2aaSAndroid Build Coastguard Worker case CodecSrc::kNonNative8888_Always_DstColorType:
594*c8dee2aaSAndroid Build Coastguard Worker folder.append("_kNonNative");
595*c8dee2aaSAndroid Build Coastguard Worker break;
596*c8dee2aaSAndroid Build Coastguard Worker default:
597*c8dee2aaSAndroid Build Coastguard Worker break;
598*c8dee2aaSAndroid Build Coastguard Worker }
599*c8dee2aaSAndroid Build Coastguard Worker
600*c8dee2aaSAndroid Build Coastguard Worker switch (dstAlphaType) {
601*c8dee2aaSAndroid Build Coastguard Worker case kPremul_SkAlphaType:
602*c8dee2aaSAndroid Build Coastguard Worker folder.append("_premul");
603*c8dee2aaSAndroid Build Coastguard Worker break;
604*c8dee2aaSAndroid Build Coastguard Worker case kUnpremul_SkAlphaType:
605*c8dee2aaSAndroid Build Coastguard Worker folder.append("_unpremul");
606*c8dee2aaSAndroid Build Coastguard Worker break;
607*c8dee2aaSAndroid Build Coastguard Worker default:
608*c8dee2aaSAndroid Build Coastguard Worker break;
609*c8dee2aaSAndroid Build Coastguard Worker }
610*c8dee2aaSAndroid Build Coastguard Worker
611*c8dee2aaSAndroid Build Coastguard Worker if (1 != sampleSize) {
612*c8dee2aaSAndroid Build Coastguard Worker folder.appendf("_%.3f", 1.0f / (float) sampleSize);
613*c8dee2aaSAndroid Build Coastguard Worker }
614*c8dee2aaSAndroid Build Coastguard Worker
615*c8dee2aaSAndroid Build Coastguard Worker AndroidCodecSrc* src = new AndroidCodecSrc(path, dstColorType, dstAlphaType, sampleSize);
616*c8dee2aaSAndroid Build Coastguard Worker push_src("image", folder, src);
617*c8dee2aaSAndroid Build Coastguard Worker }
618*c8dee2aaSAndroid Build Coastguard Worker
push_image_gen_src(Path path,ImageGenSrc::Mode mode,SkAlphaType alphaType,bool isGpu)619*c8dee2aaSAndroid Build Coastguard Worker static void push_image_gen_src(Path path, ImageGenSrc::Mode mode, SkAlphaType alphaType, bool isGpu)
620*c8dee2aaSAndroid Build Coastguard Worker {
621*c8dee2aaSAndroid Build Coastguard Worker SkString folder;
622*c8dee2aaSAndroid Build Coastguard Worker switch (mode) {
623*c8dee2aaSAndroid Build Coastguard Worker case ImageGenSrc::kCodec_Mode:
624*c8dee2aaSAndroid Build Coastguard Worker folder.append("gen_codec");
625*c8dee2aaSAndroid Build Coastguard Worker break;
626*c8dee2aaSAndroid Build Coastguard Worker case ImageGenSrc::kPlatform_Mode:
627*c8dee2aaSAndroid Build Coastguard Worker folder.append("gen_platform");
628*c8dee2aaSAndroid Build Coastguard Worker break;
629*c8dee2aaSAndroid Build Coastguard Worker }
630*c8dee2aaSAndroid Build Coastguard Worker
631*c8dee2aaSAndroid Build Coastguard Worker if (isGpu) {
632*c8dee2aaSAndroid Build Coastguard Worker folder.append("_gpu");
633*c8dee2aaSAndroid Build Coastguard Worker } else {
634*c8dee2aaSAndroid Build Coastguard Worker switch (alphaType) {
635*c8dee2aaSAndroid Build Coastguard Worker case kOpaque_SkAlphaType:
636*c8dee2aaSAndroid Build Coastguard Worker folder.append("_opaque");
637*c8dee2aaSAndroid Build Coastguard Worker break;
638*c8dee2aaSAndroid Build Coastguard Worker case kPremul_SkAlphaType:
639*c8dee2aaSAndroid Build Coastguard Worker folder.append("_premul");
640*c8dee2aaSAndroid Build Coastguard Worker break;
641*c8dee2aaSAndroid Build Coastguard Worker case kUnpremul_SkAlphaType:
642*c8dee2aaSAndroid Build Coastguard Worker folder.append("_unpremul");
643*c8dee2aaSAndroid Build Coastguard Worker break;
644*c8dee2aaSAndroid Build Coastguard Worker default:
645*c8dee2aaSAndroid Build Coastguard Worker break;
646*c8dee2aaSAndroid Build Coastguard Worker }
647*c8dee2aaSAndroid Build Coastguard Worker }
648*c8dee2aaSAndroid Build Coastguard Worker
649*c8dee2aaSAndroid Build Coastguard Worker ImageGenSrc* src = new ImageGenSrc(path, mode, alphaType, isGpu);
650*c8dee2aaSAndroid Build Coastguard Worker push_src("image", folder, src);
651*c8dee2aaSAndroid Build Coastguard Worker }
652*c8dee2aaSAndroid Build Coastguard Worker
653*c8dee2aaSAndroid Build Coastguard Worker #ifdef SK_ENABLE_ANDROID_UTILS
push_brd_src(Path path,CodecSrc::DstColorType dstColorType,BRDSrc::Mode mode,uint32_t sampleSize)654*c8dee2aaSAndroid Build Coastguard Worker static void push_brd_src(Path path, CodecSrc::DstColorType dstColorType, BRDSrc::Mode mode,
655*c8dee2aaSAndroid Build Coastguard Worker uint32_t sampleSize) {
656*c8dee2aaSAndroid Build Coastguard Worker SkString folder("brd_android_codec");
657*c8dee2aaSAndroid Build Coastguard Worker switch (mode) {
658*c8dee2aaSAndroid Build Coastguard Worker case BRDSrc::kFullImage_Mode:
659*c8dee2aaSAndroid Build Coastguard Worker break;
660*c8dee2aaSAndroid Build Coastguard Worker case BRDSrc::kDivisor_Mode:
661*c8dee2aaSAndroid Build Coastguard Worker folder.append("_divisor");
662*c8dee2aaSAndroid Build Coastguard Worker break;
663*c8dee2aaSAndroid Build Coastguard Worker default:
664*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(false);
665*c8dee2aaSAndroid Build Coastguard Worker return;
666*c8dee2aaSAndroid Build Coastguard Worker }
667*c8dee2aaSAndroid Build Coastguard Worker
668*c8dee2aaSAndroid Build Coastguard Worker switch (dstColorType) {
669*c8dee2aaSAndroid Build Coastguard Worker case CodecSrc::kGetFromCanvas_DstColorType:
670*c8dee2aaSAndroid Build Coastguard Worker break;
671*c8dee2aaSAndroid Build Coastguard Worker case CodecSrc::kGrayscale_Always_DstColorType:
672*c8dee2aaSAndroid Build Coastguard Worker folder.append("_kGray");
673*c8dee2aaSAndroid Build Coastguard Worker break;
674*c8dee2aaSAndroid Build Coastguard Worker default:
675*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(false);
676*c8dee2aaSAndroid Build Coastguard Worker return;
677*c8dee2aaSAndroid Build Coastguard Worker }
678*c8dee2aaSAndroid Build Coastguard Worker
679*c8dee2aaSAndroid Build Coastguard Worker if (1 != sampleSize) {
680*c8dee2aaSAndroid Build Coastguard Worker folder.appendf("_%.3f", 1.0f / (float) sampleSize);
681*c8dee2aaSAndroid Build Coastguard Worker }
682*c8dee2aaSAndroid Build Coastguard Worker
683*c8dee2aaSAndroid Build Coastguard Worker BRDSrc* src = new BRDSrc(path, mode, dstColorType, sampleSize);
684*c8dee2aaSAndroid Build Coastguard Worker push_src("image", folder, src);
685*c8dee2aaSAndroid Build Coastguard Worker }
686*c8dee2aaSAndroid Build Coastguard Worker
push_brd_srcs(Path path,bool gray)687*c8dee2aaSAndroid Build Coastguard Worker static void push_brd_srcs(Path path, bool gray) {
688*c8dee2aaSAndroid Build Coastguard Worker if (gray) {
689*c8dee2aaSAndroid Build Coastguard Worker // Only run grayscale to one sampleSize and Mode. Though interesting
690*c8dee2aaSAndroid Build Coastguard Worker // to test grayscale, it should not reveal anything across various
691*c8dee2aaSAndroid Build Coastguard Worker // sampleSizes and Modes
692*c8dee2aaSAndroid Build Coastguard Worker // Arbitrarily choose Mode and sampleSize.
693*c8dee2aaSAndroid Build Coastguard Worker push_brd_src(path, CodecSrc::kGrayscale_Always_DstColorType,
694*c8dee2aaSAndroid Build Coastguard Worker BRDSrc::kFullImage_Mode, 2);
695*c8dee2aaSAndroid Build Coastguard Worker }
696*c8dee2aaSAndroid Build Coastguard Worker
697*c8dee2aaSAndroid Build Coastguard Worker // Test on a variety of sampleSizes, making sure to include:
698*c8dee2aaSAndroid Build Coastguard Worker // - 2, 4, and 8, which are natively supported by jpeg
699*c8dee2aaSAndroid Build Coastguard Worker // - multiples of 2 which are not divisible by 4 (analogous for 4)
700*c8dee2aaSAndroid Build Coastguard Worker // - larger powers of two, since BRD clients generally use powers of 2
701*c8dee2aaSAndroid Build Coastguard Worker // We will only produce output for the larger sizes on large images.
702*c8dee2aaSAndroid Build Coastguard Worker const uint32_t sampleSizes[] = { 1, 2, 3, 4, 5, 6, 7, 8, 12, 16, 24, 32, 64 };
703*c8dee2aaSAndroid Build Coastguard Worker
704*c8dee2aaSAndroid Build Coastguard Worker const BRDSrc::Mode modes[] = { BRDSrc::kFullImage_Mode, BRDSrc::kDivisor_Mode, };
705*c8dee2aaSAndroid Build Coastguard Worker
706*c8dee2aaSAndroid Build Coastguard Worker for (uint32_t sampleSize : sampleSizes) {
707*c8dee2aaSAndroid Build Coastguard Worker for (BRDSrc::Mode mode : modes) {
708*c8dee2aaSAndroid Build Coastguard Worker push_brd_src(path, CodecSrc::kGetFromCanvas_DstColorType, mode, sampleSize);
709*c8dee2aaSAndroid Build Coastguard Worker }
710*c8dee2aaSAndroid Build Coastguard Worker }
711*c8dee2aaSAndroid Build Coastguard Worker }
712*c8dee2aaSAndroid Build Coastguard Worker #endif // SK_ENABLE_ANDROID_UTILS
713*c8dee2aaSAndroid Build Coastguard Worker
push_codec_srcs(Path path)714*c8dee2aaSAndroid Build Coastguard Worker static void push_codec_srcs(Path path) {
715*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkData> encoded(SkData::MakeFromFileName(path.c_str()));
716*c8dee2aaSAndroid Build Coastguard Worker if (!encoded) {
717*c8dee2aaSAndroid Build Coastguard Worker info("Couldn't read %s.", path.c_str());
718*c8dee2aaSAndroid Build Coastguard Worker return;
719*c8dee2aaSAndroid Build Coastguard Worker }
720*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<SkCodec> codec = SkCodec::MakeFromData(encoded);
721*c8dee2aaSAndroid Build Coastguard Worker if (nullptr == codec) {
722*c8dee2aaSAndroid Build Coastguard Worker info("Couldn't create codec for %s.", path.c_str());
723*c8dee2aaSAndroid Build Coastguard Worker return;
724*c8dee2aaSAndroid Build Coastguard Worker }
725*c8dee2aaSAndroid Build Coastguard Worker
726*c8dee2aaSAndroid Build Coastguard Worker // native scaling is only supported by WEBP and JPEG
727*c8dee2aaSAndroid Build Coastguard Worker bool supportsNativeScaling = false;
728*c8dee2aaSAndroid Build Coastguard Worker
729*c8dee2aaSAndroid Build Coastguard Worker TArray<CodecSrc::Mode> nativeModes;
730*c8dee2aaSAndroid Build Coastguard Worker nativeModes.push_back(CodecSrc::kCodec_Mode);
731*c8dee2aaSAndroid Build Coastguard Worker nativeModes.push_back(CodecSrc::kCodecZeroInit_Mode);
732*c8dee2aaSAndroid Build Coastguard Worker switch (codec->getEncodedFormat()) {
733*c8dee2aaSAndroid Build Coastguard Worker case SkEncodedImageFormat::kJPEG:
734*c8dee2aaSAndroid Build Coastguard Worker nativeModes.push_back(CodecSrc::kScanline_Mode);
735*c8dee2aaSAndroid Build Coastguard Worker nativeModes.push_back(CodecSrc::kStripe_Mode);
736*c8dee2aaSAndroid Build Coastguard Worker nativeModes.push_back(CodecSrc::kCroppedScanline_Mode);
737*c8dee2aaSAndroid Build Coastguard Worker supportsNativeScaling = true;
738*c8dee2aaSAndroid Build Coastguard Worker break;
739*c8dee2aaSAndroid Build Coastguard Worker case SkEncodedImageFormat::kWEBP:
740*c8dee2aaSAndroid Build Coastguard Worker nativeModes.push_back(CodecSrc::kSubset_Mode);
741*c8dee2aaSAndroid Build Coastguard Worker supportsNativeScaling = true;
742*c8dee2aaSAndroid Build Coastguard Worker break;
743*c8dee2aaSAndroid Build Coastguard Worker case SkEncodedImageFormat::kDNG:
744*c8dee2aaSAndroid Build Coastguard Worker break;
745*c8dee2aaSAndroid Build Coastguard Worker default:
746*c8dee2aaSAndroid Build Coastguard Worker nativeModes.push_back(CodecSrc::kScanline_Mode);
747*c8dee2aaSAndroid Build Coastguard Worker break;
748*c8dee2aaSAndroid Build Coastguard Worker }
749*c8dee2aaSAndroid Build Coastguard Worker
750*c8dee2aaSAndroid Build Coastguard Worker TArray<CodecSrc::DstColorType> colorTypes;
751*c8dee2aaSAndroid Build Coastguard Worker colorTypes.push_back(CodecSrc::kGetFromCanvas_DstColorType);
752*c8dee2aaSAndroid Build Coastguard Worker colorTypes.push_back(CodecSrc::kNonNative8888_Always_DstColorType);
753*c8dee2aaSAndroid Build Coastguard Worker switch (codec->getInfo().colorType()) {
754*c8dee2aaSAndroid Build Coastguard Worker case kGray_8_SkColorType:
755*c8dee2aaSAndroid Build Coastguard Worker colorTypes.push_back(CodecSrc::kGrayscale_Always_DstColorType);
756*c8dee2aaSAndroid Build Coastguard Worker break;
757*c8dee2aaSAndroid Build Coastguard Worker default:
758*c8dee2aaSAndroid Build Coastguard Worker break;
759*c8dee2aaSAndroid Build Coastguard Worker }
760*c8dee2aaSAndroid Build Coastguard Worker
761*c8dee2aaSAndroid Build Coastguard Worker TArray<SkAlphaType> alphaModes;
762*c8dee2aaSAndroid Build Coastguard Worker alphaModes.push_back(kPremul_SkAlphaType);
763*c8dee2aaSAndroid Build Coastguard Worker if (codec->getInfo().alphaType() != kOpaque_SkAlphaType) {
764*c8dee2aaSAndroid Build Coastguard Worker alphaModes.push_back(kUnpremul_SkAlphaType);
765*c8dee2aaSAndroid Build Coastguard Worker }
766*c8dee2aaSAndroid Build Coastguard Worker
767*c8dee2aaSAndroid Build Coastguard Worker for (CodecSrc::Mode mode : nativeModes) {
768*c8dee2aaSAndroid Build Coastguard Worker for (CodecSrc::DstColorType colorType : colorTypes) {
769*c8dee2aaSAndroid Build Coastguard Worker for (SkAlphaType alphaType : alphaModes) {
770*c8dee2aaSAndroid Build Coastguard Worker // Only test kCroppedScanline_Mode when the alpha type is premul. The test is
771*c8dee2aaSAndroid Build Coastguard Worker // slow and won't be interestingly different with different alpha types.
772*c8dee2aaSAndroid Build Coastguard Worker if (CodecSrc::kCroppedScanline_Mode == mode &&
773*c8dee2aaSAndroid Build Coastguard Worker kPremul_SkAlphaType != alphaType) {
774*c8dee2aaSAndroid Build Coastguard Worker continue;
775*c8dee2aaSAndroid Build Coastguard Worker }
776*c8dee2aaSAndroid Build Coastguard Worker
777*c8dee2aaSAndroid Build Coastguard Worker push_codec_src(path, mode, colorType, alphaType, 1.0f);
778*c8dee2aaSAndroid Build Coastguard Worker
779*c8dee2aaSAndroid Build Coastguard Worker // Skip kNonNative on different native scales. It won't be interestingly
780*c8dee2aaSAndroid Build Coastguard Worker // different.
781*c8dee2aaSAndroid Build Coastguard Worker if (supportsNativeScaling &&
782*c8dee2aaSAndroid Build Coastguard Worker CodecSrc::kNonNative8888_Always_DstColorType == colorType) {
783*c8dee2aaSAndroid Build Coastguard Worker // Native Scales
784*c8dee2aaSAndroid Build Coastguard Worker // SkJpegCodec natively supports scaling to the following:
785*c8dee2aaSAndroid Build Coastguard Worker for (auto scale : { 0.125f, 0.25f, 0.375f, 0.5f, 0.625f, 0.750f, 0.875f }) {
786*c8dee2aaSAndroid Build Coastguard Worker push_codec_src(path, mode, colorType, alphaType, scale);
787*c8dee2aaSAndroid Build Coastguard Worker }
788*c8dee2aaSAndroid Build Coastguard Worker }
789*c8dee2aaSAndroid Build Coastguard Worker }
790*c8dee2aaSAndroid Build Coastguard Worker }
791*c8dee2aaSAndroid Build Coastguard Worker }
792*c8dee2aaSAndroid Build Coastguard Worker
793*c8dee2aaSAndroid Build Coastguard Worker {
794*c8dee2aaSAndroid Build Coastguard Worker std::vector<SkCodec::FrameInfo> frameInfos = codec->getFrameInfo();
795*c8dee2aaSAndroid Build Coastguard Worker if (frameInfos.size() > 1) {
796*c8dee2aaSAndroid Build Coastguard Worker for (auto dstCT : { CodecSrc::kNonNative8888_Always_DstColorType,
797*c8dee2aaSAndroid Build Coastguard Worker CodecSrc::kGetFromCanvas_DstColorType }) {
798*c8dee2aaSAndroid Build Coastguard Worker for (auto at : { kUnpremul_SkAlphaType, kPremul_SkAlphaType }) {
799*c8dee2aaSAndroid Build Coastguard Worker push_codec_src(path, CodecSrc::kAnimated_Mode, dstCT, at, 1.0f);
800*c8dee2aaSAndroid Build Coastguard Worker }
801*c8dee2aaSAndroid Build Coastguard Worker }
802*c8dee2aaSAndroid Build Coastguard Worker for (float scale : { .5f, .33f }) {
803*c8dee2aaSAndroid Build Coastguard Worker push_codec_src(path, CodecSrc::kAnimated_Mode, CodecSrc::kGetFromCanvas_DstColorType,
804*c8dee2aaSAndroid Build Coastguard Worker kPremul_SkAlphaType, scale);
805*c8dee2aaSAndroid Build Coastguard Worker }
806*c8dee2aaSAndroid Build Coastguard Worker }
807*c8dee2aaSAndroid Build Coastguard Worker
808*c8dee2aaSAndroid Build Coastguard Worker }
809*c8dee2aaSAndroid Build Coastguard Worker
810*c8dee2aaSAndroid Build Coastguard Worker if (FLAGS_simpleCodec) {
811*c8dee2aaSAndroid Build Coastguard Worker return;
812*c8dee2aaSAndroid Build Coastguard Worker }
813*c8dee2aaSAndroid Build Coastguard Worker
814*c8dee2aaSAndroid Build Coastguard Worker const int sampleSizes[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
815*c8dee2aaSAndroid Build Coastguard Worker
816*c8dee2aaSAndroid Build Coastguard Worker for (int sampleSize : sampleSizes) {
817*c8dee2aaSAndroid Build Coastguard Worker for (CodecSrc::DstColorType colorType : colorTypes) {
818*c8dee2aaSAndroid Build Coastguard Worker for (SkAlphaType alphaType : alphaModes) {
819*c8dee2aaSAndroid Build Coastguard Worker // We can exercise all of the kNonNative support code in the swizzler with just a
820*c8dee2aaSAndroid Build Coastguard Worker // few sample sizes. Skip the rest.
821*c8dee2aaSAndroid Build Coastguard Worker if (CodecSrc::kNonNative8888_Always_DstColorType == colorType && sampleSize > 3) {
822*c8dee2aaSAndroid Build Coastguard Worker continue;
823*c8dee2aaSAndroid Build Coastguard Worker }
824*c8dee2aaSAndroid Build Coastguard Worker
825*c8dee2aaSAndroid Build Coastguard Worker push_android_codec_src(path, colorType, alphaType, sampleSize);
826*c8dee2aaSAndroid Build Coastguard Worker }
827*c8dee2aaSAndroid Build Coastguard Worker }
828*c8dee2aaSAndroid Build Coastguard Worker }
829*c8dee2aaSAndroid Build Coastguard Worker
830*c8dee2aaSAndroid Build Coastguard Worker const char* ext = strrchr(path.c_str(), '.');
831*c8dee2aaSAndroid Build Coastguard Worker if (ext) {
832*c8dee2aaSAndroid Build Coastguard Worker ext++;
833*c8dee2aaSAndroid Build Coastguard Worker
834*c8dee2aaSAndroid Build Coastguard Worker static const char* const rawExts[] = {
835*c8dee2aaSAndroid Build Coastguard Worker "arw", "cr2", "dng", "nef", "nrw", "orf", "raf", "rw2", "pef", "srw",
836*c8dee2aaSAndroid Build Coastguard Worker "ARW", "CR2", "DNG", "NEF", "NRW", "ORF", "RAF", "RW2", "PEF", "SRW",
837*c8dee2aaSAndroid Build Coastguard Worker };
838*c8dee2aaSAndroid Build Coastguard Worker for (const char* rawExt : rawExts) {
839*c8dee2aaSAndroid Build Coastguard Worker if (0 == strcmp(rawExt, ext)) {
840*c8dee2aaSAndroid Build Coastguard Worker // RAW is not supported by image generator (skbug.com/5079) or BRD.
841*c8dee2aaSAndroid Build Coastguard Worker return;
842*c8dee2aaSAndroid Build Coastguard Worker }
843*c8dee2aaSAndroid Build Coastguard Worker }
844*c8dee2aaSAndroid Build Coastguard Worker
845*c8dee2aaSAndroid Build Coastguard Worker #ifdef SK_ENABLE_ANDROID_UTILS
846*c8dee2aaSAndroid Build Coastguard Worker static const char* const brdExts[] = {
847*c8dee2aaSAndroid Build Coastguard Worker "jpg", "jpeg", "png", "webp",
848*c8dee2aaSAndroid Build Coastguard Worker "JPG", "JPEG", "PNG", "WEBP",
849*c8dee2aaSAndroid Build Coastguard Worker };
850*c8dee2aaSAndroid Build Coastguard Worker for (const char* brdExt : brdExts) {
851*c8dee2aaSAndroid Build Coastguard Worker if (0 == strcmp(brdExt, ext)) {
852*c8dee2aaSAndroid Build Coastguard Worker bool gray = codec->getInfo().colorType() == kGray_8_SkColorType;
853*c8dee2aaSAndroid Build Coastguard Worker push_brd_srcs(path, gray);
854*c8dee2aaSAndroid Build Coastguard Worker break;
855*c8dee2aaSAndroid Build Coastguard Worker }
856*c8dee2aaSAndroid Build Coastguard Worker }
857*c8dee2aaSAndroid Build Coastguard Worker #endif
858*c8dee2aaSAndroid Build Coastguard Worker }
859*c8dee2aaSAndroid Build Coastguard Worker
860*c8dee2aaSAndroid Build Coastguard Worker // Push image generator GPU test.
861*c8dee2aaSAndroid Build Coastguard Worker push_image_gen_src(path, ImageGenSrc::kCodec_Mode, codec->getInfo().alphaType(), true);
862*c8dee2aaSAndroid Build Coastguard Worker
863*c8dee2aaSAndroid Build Coastguard Worker // Push image generator CPU tests.
864*c8dee2aaSAndroid Build Coastguard Worker for (SkAlphaType alphaType : alphaModes) {
865*c8dee2aaSAndroid Build Coastguard Worker push_image_gen_src(path, ImageGenSrc::kCodec_Mode, alphaType, false);
866*c8dee2aaSAndroid Build Coastguard Worker
867*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS)
868*c8dee2aaSAndroid Build Coastguard Worker if (SkEncodedImageFormat::kWEBP != codec->getEncodedFormat() &&
869*c8dee2aaSAndroid Build Coastguard Worker SkEncodedImageFormat::kWBMP != codec->getEncodedFormat() &&
870*c8dee2aaSAndroid Build Coastguard Worker kUnpremul_SkAlphaType != alphaType)
871*c8dee2aaSAndroid Build Coastguard Worker {
872*c8dee2aaSAndroid Build Coastguard Worker push_image_gen_src(path, ImageGenSrc::kPlatform_Mode, alphaType, false);
873*c8dee2aaSAndroid Build Coastguard Worker }
874*c8dee2aaSAndroid Build Coastguard Worker #elif defined(SK_BUILD_FOR_WIN)
875*c8dee2aaSAndroid Build Coastguard Worker if (SkEncodedImageFormat::kWEBP != codec->getEncodedFormat() &&
876*c8dee2aaSAndroid Build Coastguard Worker SkEncodedImageFormat::kWBMP != codec->getEncodedFormat())
877*c8dee2aaSAndroid Build Coastguard Worker {
878*c8dee2aaSAndroid Build Coastguard Worker push_image_gen_src(path, ImageGenSrc::kPlatform_Mode, alphaType, false);
879*c8dee2aaSAndroid Build Coastguard Worker }
880*c8dee2aaSAndroid Build Coastguard Worker #elif defined(SK_ENABLE_NDK_IMAGES)
881*c8dee2aaSAndroid Build Coastguard Worker push_image_gen_src(path, ImageGenSrc::kPlatform_Mode, alphaType, false);
882*c8dee2aaSAndroid Build Coastguard Worker #endif
883*c8dee2aaSAndroid Build Coastguard Worker }
884*c8dee2aaSAndroid Build Coastguard Worker }
885*c8dee2aaSAndroid Build Coastguard Worker
886*c8dee2aaSAndroid Build Coastguard Worker template <typename T>
gather_file_srcs(const CommandLineFlags::StringArray & flags,const char * ext,const char * src_name=nullptr)887*c8dee2aaSAndroid Build Coastguard Worker void gather_file_srcs(const CommandLineFlags::StringArray& flags,
888*c8dee2aaSAndroid Build Coastguard Worker const char* ext,
889*c8dee2aaSAndroid Build Coastguard Worker const char* src_name = nullptr) {
890*c8dee2aaSAndroid Build Coastguard Worker if (!src_name) {
891*c8dee2aaSAndroid Build Coastguard Worker // With the exception of Lottie files, the source name is the extension.
892*c8dee2aaSAndroid Build Coastguard Worker src_name = ext;
893*c8dee2aaSAndroid Build Coastguard Worker }
894*c8dee2aaSAndroid Build Coastguard Worker
895*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < flags.size(); i++) {
896*c8dee2aaSAndroid Build Coastguard Worker const char* path = flags[i];
897*c8dee2aaSAndroid Build Coastguard Worker if (sk_isdir(path)) {
898*c8dee2aaSAndroid Build Coastguard Worker SkOSFile::Iter it(path, ext);
899*c8dee2aaSAndroid Build Coastguard Worker for (SkString file; it.next(&file); ) {
900*c8dee2aaSAndroid Build Coastguard Worker push_src(src_name, "", new T(SkOSPath::Join(path, file.c_str())));
901*c8dee2aaSAndroid Build Coastguard Worker }
902*c8dee2aaSAndroid Build Coastguard Worker } else {
903*c8dee2aaSAndroid Build Coastguard Worker push_src(src_name, "", new T(path));
904*c8dee2aaSAndroid Build Coastguard Worker }
905*c8dee2aaSAndroid Build Coastguard Worker }
906*c8dee2aaSAndroid Build Coastguard Worker }
907*c8dee2aaSAndroid Build Coastguard Worker
gather_srcs()908*c8dee2aaSAndroid Build Coastguard Worker static bool gather_srcs() {
909*c8dee2aaSAndroid Build Coastguard Worker for (const skiagm::GMFactory& f : skiagm::GMRegistry::Range()) {
910*c8dee2aaSAndroid Build Coastguard Worker push_src("gm", "", new GMSrc(f));
911*c8dee2aaSAndroid Build Coastguard Worker }
912*c8dee2aaSAndroid Build Coastguard Worker
913*c8dee2aaSAndroid Build Coastguard Worker gather_file_srcs<SKPSrc>(FLAGS_skps, "skp");
914*c8dee2aaSAndroid Build Coastguard Worker gather_file_srcs<MSKPSrc>(FLAGS_mskps, "mskp");
915*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_ENABLE_SKOTTIE)
916*c8dee2aaSAndroid Build Coastguard Worker gather_file_srcs<SkottieSrc>(FLAGS_lotties, "json", "lottie");
917*c8dee2aaSAndroid Build Coastguard Worker #endif
918*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_ENABLE_SVG)
919*c8dee2aaSAndroid Build Coastguard Worker gather_file_srcs<SVGSrc>(FLAGS_svgs, "svg");
920*c8dee2aaSAndroid Build Coastguard Worker #endif
921*c8dee2aaSAndroid Build Coastguard Worker if (!FLAGS_bisect.isEmpty()) {
922*c8dee2aaSAndroid Build Coastguard Worker // An empty l/r trail string will draw all the paths.
923*c8dee2aaSAndroid Build Coastguard Worker push_src("bisect", "",
924*c8dee2aaSAndroid Build Coastguard Worker new BisectSrc(FLAGS_bisect[0], FLAGS_bisect.size() > 1 ? FLAGS_bisect[1] : ""));
925*c8dee2aaSAndroid Build Coastguard Worker }
926*c8dee2aaSAndroid Build Coastguard Worker
927*c8dee2aaSAndroid Build Coastguard Worker TArray<SkString> images;
928*c8dee2aaSAndroid Build Coastguard Worker if (!CommonFlags::CollectImages(FLAGS_images, &images)) {
929*c8dee2aaSAndroid Build Coastguard Worker return false;
930*c8dee2aaSAndroid Build Coastguard Worker }
931*c8dee2aaSAndroid Build Coastguard Worker
932*c8dee2aaSAndroid Build Coastguard Worker for (const SkString& image : images) {
933*c8dee2aaSAndroid Build Coastguard Worker push_codec_srcs(image);
934*c8dee2aaSAndroid Build Coastguard Worker }
935*c8dee2aaSAndroid Build Coastguard Worker
936*c8dee2aaSAndroid Build Coastguard Worker TArray<SkString> colorImages;
937*c8dee2aaSAndroid Build Coastguard Worker if (!CommonFlags::CollectImages(FLAGS_colorImages, &colorImages)) {
938*c8dee2aaSAndroid Build Coastguard Worker return false;
939*c8dee2aaSAndroid Build Coastguard Worker }
940*c8dee2aaSAndroid Build Coastguard Worker
941*c8dee2aaSAndroid Build Coastguard Worker for (const SkString& colorImage : colorImages) {
942*c8dee2aaSAndroid Build Coastguard Worker push_src("colorImage", "decode_native", new ColorCodecSrc(colorImage, false));
943*c8dee2aaSAndroid Build Coastguard Worker push_src("colorImage", "decode_to_dst", new ColorCodecSrc(colorImage, true));
944*c8dee2aaSAndroid Build Coastguard Worker }
945*c8dee2aaSAndroid Build Coastguard Worker
946*c8dee2aaSAndroid Build Coastguard Worker return true;
947*c8dee2aaSAndroid Build Coastguard Worker }
948*c8dee2aaSAndroid Build Coastguard Worker
push_sink(const SkCommandLineConfig & config,Sink * s)949*c8dee2aaSAndroid Build Coastguard Worker static void push_sink(const SkCommandLineConfig& config, Sink* s) {
950*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<Sink> sink(s);
951*c8dee2aaSAndroid Build Coastguard Worker
952*c8dee2aaSAndroid Build Coastguard Worker // Try a simple Src as a canary. If it fails, skip this sink.
953*c8dee2aaSAndroid Build Coastguard Worker struct : public Src {
954*c8dee2aaSAndroid Build Coastguard Worker Result draw(SkCanvas* c, skiatest::graphite::GraphiteTestContext*) const override {
955*c8dee2aaSAndroid Build Coastguard Worker c->drawRect(SkRect::MakeWH(1,1), SkPaint());
956*c8dee2aaSAndroid Build Coastguard Worker return Result::Ok();
957*c8dee2aaSAndroid Build Coastguard Worker }
958*c8dee2aaSAndroid Build Coastguard Worker SkISize size() const override { return SkISize::Make(16, 16); }
959*c8dee2aaSAndroid Build Coastguard Worker Name name() const override { return "justOneRect"; }
960*c8dee2aaSAndroid Build Coastguard Worker } justOneRect;
961*c8dee2aaSAndroid Build Coastguard Worker
962*c8dee2aaSAndroid Build Coastguard Worker SkBitmap bitmap;
963*c8dee2aaSAndroid Build Coastguard Worker SkDynamicMemoryWStream stream;
964*c8dee2aaSAndroid Build Coastguard Worker SkString log;
965*c8dee2aaSAndroid Build Coastguard Worker Result result = sink->draw(justOneRect, &bitmap, &stream, &log);
966*c8dee2aaSAndroid Build Coastguard Worker if (result.isFatal()) {
967*c8dee2aaSAndroid Build Coastguard Worker info("Could not run %s: %s\n", config.getTag().c_str(), result.c_str());
968*c8dee2aaSAndroid Build Coastguard Worker exit(1);
969*c8dee2aaSAndroid Build Coastguard Worker }
970*c8dee2aaSAndroid Build Coastguard Worker
971*c8dee2aaSAndroid Build Coastguard Worker TaggedSink& ts = gSinks->push_back();
972*c8dee2aaSAndroid Build Coastguard Worker ts.reset(sink.release()); // NOLINT(misc-uniqueptr-reset-release)
973*c8dee2aaSAndroid Build Coastguard Worker ts.tag = config.getTag();
974*c8dee2aaSAndroid Build Coastguard Worker }
975*c8dee2aaSAndroid Build Coastguard Worker
create_sink(const GrContextOptions & grCtxOptions,const skiatest::graphite::TestOptions & graphiteOptions,const SkCommandLineConfig * config)976*c8dee2aaSAndroid Build Coastguard Worker static Sink* create_sink(const GrContextOptions& grCtxOptions,
977*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_GRAPHITE)
978*c8dee2aaSAndroid Build Coastguard Worker const skiatest::graphite::TestOptions& graphiteOptions,
979*c8dee2aaSAndroid Build Coastguard Worker #endif
980*c8dee2aaSAndroid Build Coastguard Worker const SkCommandLineConfig* config) {
981*c8dee2aaSAndroid Build Coastguard Worker if (FLAGS_gpu) {
982*c8dee2aaSAndroid Build Coastguard Worker if (const SkCommandLineConfigGpu* gpuConfig = config->asConfigGpu()) {
983*c8dee2aaSAndroid Build Coastguard Worker GrContextFactory testFactory(grCtxOptions);
984*c8dee2aaSAndroid Build Coastguard Worker if (!testFactory.get(gpuConfig->getContextType(), gpuConfig->getContextOverrides())) {
985*c8dee2aaSAndroid Build Coastguard Worker info("WARNING: can not create GPU context for config '%s'. "
986*c8dee2aaSAndroid Build Coastguard Worker "GM tests will be skipped.\n", gpuConfig->getTag().c_str());
987*c8dee2aaSAndroid Build Coastguard Worker return nullptr;
988*c8dee2aaSAndroid Build Coastguard Worker }
989*c8dee2aaSAndroid Build Coastguard Worker if (gpuConfig->getTestPersistentCache()) {
990*c8dee2aaSAndroid Build Coastguard Worker return new GPUPersistentCacheTestingSink(gpuConfig, grCtxOptions);
991*c8dee2aaSAndroid Build Coastguard Worker } else if (gpuConfig->getTestPrecompile()) {
992*c8dee2aaSAndroid Build Coastguard Worker return new GPUPrecompileTestingSink(gpuConfig, grCtxOptions);
993*c8dee2aaSAndroid Build Coastguard Worker } else if (gpuConfig->getUseDDLSink()) {
994*c8dee2aaSAndroid Build Coastguard Worker return new GPUDDLSink(gpuConfig, grCtxOptions);
995*c8dee2aaSAndroid Build Coastguard Worker } else if (gpuConfig->getSlug()) {
996*c8dee2aaSAndroid Build Coastguard Worker return new GPUSlugSink(gpuConfig, grCtxOptions);
997*c8dee2aaSAndroid Build Coastguard Worker } else if (gpuConfig->getSerializedSlug()) {
998*c8dee2aaSAndroid Build Coastguard Worker return new GPUSerializeSlugSink(gpuConfig, grCtxOptions);
999*c8dee2aaSAndroid Build Coastguard Worker } else if (gpuConfig->getRemoteSlug()) {
1000*c8dee2aaSAndroid Build Coastguard Worker return new GPURemoteSlugSink(gpuConfig, grCtxOptions);
1001*c8dee2aaSAndroid Build Coastguard Worker } else {
1002*c8dee2aaSAndroid Build Coastguard Worker return new GPUSink(gpuConfig, grCtxOptions);
1003*c8dee2aaSAndroid Build Coastguard Worker }
1004*c8dee2aaSAndroid Build Coastguard Worker }
1005*c8dee2aaSAndroid Build Coastguard Worker }
1006*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_GRAPHITE)
1007*c8dee2aaSAndroid Build Coastguard Worker if (FLAGS_graphite) {
1008*c8dee2aaSAndroid Build Coastguard Worker if (const SkCommandLineConfigGraphite *graphiteConfig = config->asConfigGraphite()) {
1009*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_ENABLE_PRECOMPILE)
1010*c8dee2aaSAndroid Build Coastguard Worker if (graphiteConfig->getTestPrecompile()) {
1011*c8dee2aaSAndroid Build Coastguard Worker return new GraphitePrecompileTestingSink(graphiteConfig, graphiteOptions);
1012*c8dee2aaSAndroid Build Coastguard Worker } else
1013*c8dee2aaSAndroid Build Coastguard Worker #endif // SK_ENABLE_PRECOMPILE
1014*c8dee2aaSAndroid Build Coastguard Worker {
1015*c8dee2aaSAndroid Build Coastguard Worker return new GraphiteSink(graphiteConfig, graphiteOptions);
1016*c8dee2aaSAndroid Build Coastguard Worker }
1017*c8dee2aaSAndroid Build Coastguard Worker }
1018*c8dee2aaSAndroid Build Coastguard Worker }
1019*c8dee2aaSAndroid Build Coastguard Worker #endif // SK_GRAPHITE
1020*c8dee2aaSAndroid Build Coastguard Worker if (const SkCommandLineConfigSvg* svgConfig = config->asConfigSvg()) {
1021*c8dee2aaSAndroid Build Coastguard Worker int pageIndex = svgConfig->getPageIndex();
1022*c8dee2aaSAndroid Build Coastguard Worker return new SVGSink(pageIndex);
1023*c8dee2aaSAndroid Build Coastguard Worker }
1024*c8dee2aaSAndroid Build Coastguard Worker
1025*c8dee2aaSAndroid Build Coastguard Worker #define SINK(t, sink, ...) if (config->getBackend().equals(t)) return new sink(__VA_ARGS__)
1026*c8dee2aaSAndroid Build Coastguard Worker
1027*c8dee2aaSAndroid Build Coastguard Worker if (FLAGS_cpu) {
1028*c8dee2aaSAndroid Build Coastguard Worker SINK("r8", RasterSink, kR8_unorm_SkColorType);
1029*c8dee2aaSAndroid Build Coastguard Worker SINK("565", RasterSink, kRGB_565_SkColorType);
1030*c8dee2aaSAndroid Build Coastguard Worker SINK("4444", RasterSink, kARGB_4444_SkColorType);
1031*c8dee2aaSAndroid Build Coastguard Worker SINK("8888", RasterSink, kN32_SkColorType);
1032*c8dee2aaSAndroid Build Coastguard Worker SINK("rgba", RasterSink, kRGBA_8888_SkColorType);
1033*c8dee2aaSAndroid Build Coastguard Worker SINK("bgra", RasterSink, kBGRA_8888_SkColorType);
1034*c8dee2aaSAndroid Build Coastguard Worker SINK("rgbx", RasterSink, kRGB_888x_SkColorType);
1035*c8dee2aaSAndroid Build Coastguard Worker SINK("1010102", RasterSink, kRGBA_1010102_SkColorType);
1036*c8dee2aaSAndroid Build Coastguard Worker SINK("101010x", RasterSink, kRGB_101010x_SkColorType);
1037*c8dee2aaSAndroid Build Coastguard Worker SINK("bgra1010102", RasterSink, kBGRA_1010102_SkColorType);
1038*c8dee2aaSAndroid Build Coastguard Worker SINK("bgr101010x", RasterSink, kBGR_101010x_SkColorType);
1039*c8dee2aaSAndroid Build Coastguard Worker SINK("f16", RasterSink, kRGBA_F16_SkColorType);
1040*c8dee2aaSAndroid Build Coastguard Worker SINK("f16norm", RasterSink, kRGBA_F16Norm_SkColorType);
1041*c8dee2aaSAndroid Build Coastguard Worker SINK("f16f16f16x", RasterSink, kRGB_F16F16F16x_SkColorType);
1042*c8dee2aaSAndroid Build Coastguard Worker SINK("f32", RasterSink, kRGBA_F32_SkColorType);
1043*c8dee2aaSAndroid Build Coastguard Worker SINK("srgba", RasterSink, kSRGBA_8888_SkColorType);
1044*c8dee2aaSAndroid Build Coastguard Worker
1045*c8dee2aaSAndroid Build Coastguard Worker SINK("pdf", PDFSink, false, SK_ScalarDefaultRasterDPI);
1046*c8dee2aaSAndroid Build Coastguard Worker SINK("skp", SKPSink);
1047*c8dee2aaSAndroid Build Coastguard Worker SINK("svg", SVGSink);
1048*c8dee2aaSAndroid Build Coastguard Worker SINK("null", NullSink);
1049*c8dee2aaSAndroid Build Coastguard Worker SINK("xps", XPSSink);
1050*c8dee2aaSAndroid Build Coastguard Worker SINK("pdfa", PDFSink, true, SK_ScalarDefaultRasterDPI);
1051*c8dee2aaSAndroid Build Coastguard Worker SINK("pdf300", PDFSink, false, 300);
1052*c8dee2aaSAndroid Build Coastguard Worker SINK("jsdebug", DebugSink);
1053*c8dee2aaSAndroid Build Coastguard Worker }
1054*c8dee2aaSAndroid Build Coastguard Worker #undef SINK
1055*c8dee2aaSAndroid Build Coastguard Worker return nullptr;
1056*c8dee2aaSAndroid Build Coastguard Worker }
1057*c8dee2aaSAndroid Build Coastguard Worker
create_via(const SkString & tag,Sink * wrapped)1058*c8dee2aaSAndroid Build Coastguard Worker static Sink* create_via(const SkString& tag, Sink* wrapped) {
1059*c8dee2aaSAndroid Build Coastguard Worker #define VIA(t, via, ...) if (tag.equals(t)) return new via(__VA_ARGS__)
1060*c8dee2aaSAndroid Build Coastguard Worker #ifdef TEST_VIA_SVG
1061*c8dee2aaSAndroid Build Coastguard Worker VIA("svg", ViaSVG, wrapped);
1062*c8dee2aaSAndroid Build Coastguard Worker #endif
1063*c8dee2aaSAndroid Build Coastguard Worker VIA("serialize", ViaSerialization, wrapped);
1064*c8dee2aaSAndroid Build Coastguard Worker VIA("pic", ViaPicture, wrapped);
1065*c8dee2aaSAndroid Build Coastguard Worker VIA("rtblend", ViaRuntimeBlend, wrapped);
1066*c8dee2aaSAndroid Build Coastguard Worker
1067*c8dee2aaSAndroid Build Coastguard Worker if (FLAGS_matrix.size() == 4) {
1068*c8dee2aaSAndroid Build Coastguard Worker SkMatrix m;
1069*c8dee2aaSAndroid Build Coastguard Worker m.reset();
1070*c8dee2aaSAndroid Build Coastguard Worker m.setScaleX((SkScalar)atof(FLAGS_matrix[0]));
1071*c8dee2aaSAndroid Build Coastguard Worker m.setSkewX ((SkScalar)atof(FLAGS_matrix[1]));
1072*c8dee2aaSAndroid Build Coastguard Worker m.setSkewY ((SkScalar)atof(FLAGS_matrix[2]));
1073*c8dee2aaSAndroid Build Coastguard Worker m.setScaleY((SkScalar)atof(FLAGS_matrix[3]));
1074*c8dee2aaSAndroid Build Coastguard Worker VIA("matrix", ViaMatrix, m, wrapped);
1075*c8dee2aaSAndroid Build Coastguard Worker VIA("upright", ViaUpright, m, wrapped);
1076*c8dee2aaSAndroid Build Coastguard Worker }
1077*c8dee2aaSAndroid Build Coastguard Worker
1078*c8dee2aaSAndroid Build Coastguard Worker #undef VIA
1079*c8dee2aaSAndroid Build Coastguard Worker
1080*c8dee2aaSAndroid Build Coastguard Worker return nullptr;
1081*c8dee2aaSAndroid Build Coastguard Worker }
1082*c8dee2aaSAndroid Build Coastguard Worker
gather_sinks(const GrContextOptions & grCtxOptions,const skiatest::graphite::TestOptions & graphiteOptions,bool defaultConfigs)1083*c8dee2aaSAndroid Build Coastguard Worker static bool gather_sinks(const GrContextOptions& grCtxOptions,
1084*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_GRAPHITE)
1085*c8dee2aaSAndroid Build Coastguard Worker const skiatest::graphite::TestOptions& graphiteOptions,
1086*c8dee2aaSAndroid Build Coastguard Worker #endif
1087*c8dee2aaSAndroid Build Coastguard Worker bool defaultConfigs) {
1088*c8dee2aaSAndroid Build Coastguard Worker if (FLAGS_src.size() == 1 && FLAGS_src.contains("tests")) {
1089*c8dee2aaSAndroid Build Coastguard Worker // If we're just running tests skip trying to accumulate sinks. The 'justOneRect' test
1090*c8dee2aaSAndroid Build Coastguard Worker // can fail for protected contexts.
1091*c8dee2aaSAndroid Build Coastguard Worker return true;
1092*c8dee2aaSAndroid Build Coastguard Worker }
1093*c8dee2aaSAndroid Build Coastguard Worker
1094*c8dee2aaSAndroid Build Coastguard Worker SkCommandLineConfigArray configs;
1095*c8dee2aaSAndroid Build Coastguard Worker ParseConfigs(FLAGS_config, &configs);
1096*c8dee2aaSAndroid Build Coastguard Worker AutoreleasePool pool;
1097*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < configs.size(); i++) {
1098*c8dee2aaSAndroid Build Coastguard Worker const SkCommandLineConfig& config = *configs[i];
1099*c8dee2aaSAndroid Build Coastguard Worker Sink* sink = create_sink(grCtxOptions,
1100*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_GRAPHITE)
1101*c8dee2aaSAndroid Build Coastguard Worker graphiteOptions,
1102*c8dee2aaSAndroid Build Coastguard Worker #endif
1103*c8dee2aaSAndroid Build Coastguard Worker &config);
1104*c8dee2aaSAndroid Build Coastguard Worker if (sink == nullptr) {
1105*c8dee2aaSAndroid Build Coastguard Worker info("Skipping config %s: Don't understand '%s'.\n", config.getTag().c_str(),
1106*c8dee2aaSAndroid Build Coastguard Worker config.getTag().c_str());
1107*c8dee2aaSAndroid Build Coastguard Worker continue;
1108*c8dee2aaSAndroid Build Coastguard Worker }
1109*c8dee2aaSAndroid Build Coastguard Worker
1110*c8dee2aaSAndroid Build Coastguard Worker // The command line config already parsed out the via-style color space. Apply it here.
1111*c8dee2aaSAndroid Build Coastguard Worker sink->setColorSpace(config.refColorSpace());
1112*c8dee2aaSAndroid Build Coastguard Worker
1113*c8dee2aaSAndroid Build Coastguard Worker const TArray<SkString>& parts = config.getViaParts();
1114*c8dee2aaSAndroid Build Coastguard Worker for (int j = parts.size(); j-- > 0;) {
1115*c8dee2aaSAndroid Build Coastguard Worker const SkString& part = parts[j];
1116*c8dee2aaSAndroid Build Coastguard Worker Sink* next = create_via(part, sink);
1117*c8dee2aaSAndroid Build Coastguard Worker if (next == nullptr) {
1118*c8dee2aaSAndroid Build Coastguard Worker info("Skipping config %s: Don't understand '%s'.\n", config.getTag().c_str(),
1119*c8dee2aaSAndroid Build Coastguard Worker part.c_str());
1120*c8dee2aaSAndroid Build Coastguard Worker delete sink;
1121*c8dee2aaSAndroid Build Coastguard Worker sink = nullptr;
1122*c8dee2aaSAndroid Build Coastguard Worker break;
1123*c8dee2aaSAndroid Build Coastguard Worker }
1124*c8dee2aaSAndroid Build Coastguard Worker sink = next;
1125*c8dee2aaSAndroid Build Coastguard Worker }
1126*c8dee2aaSAndroid Build Coastguard Worker if (sink) {
1127*c8dee2aaSAndroid Build Coastguard Worker push_sink(config, sink);
1128*c8dee2aaSAndroid Build Coastguard Worker }
1129*c8dee2aaSAndroid Build Coastguard Worker }
1130*c8dee2aaSAndroid Build Coastguard Worker
1131*c8dee2aaSAndroid Build Coastguard Worker // If no configs were requested (just running tests, perhaps?), then we're okay.
1132*c8dee2aaSAndroid Build Coastguard Worker if (configs.size() == 0 ||
1133*c8dee2aaSAndroid Build Coastguard Worker // If we're using the default configs, we're okay.
1134*c8dee2aaSAndroid Build Coastguard Worker defaultConfigs ||
1135*c8dee2aaSAndroid Build Coastguard Worker // Otherwise, make sure that all specified configs have become sinks.
1136*c8dee2aaSAndroid Build Coastguard Worker configs.size() == gSinks->size()) {
1137*c8dee2aaSAndroid Build Coastguard Worker return true;
1138*c8dee2aaSAndroid Build Coastguard Worker }
1139*c8dee2aaSAndroid Build Coastguard Worker return false;
1140*c8dee2aaSAndroid Build Coastguard Worker }
1141*c8dee2aaSAndroid Build Coastguard Worker
match(const char * needle,const char * haystack)1142*c8dee2aaSAndroid Build Coastguard Worker static bool match(const char* needle, const char* haystack) {
1143*c8dee2aaSAndroid Build Coastguard Worker if ('~' == needle[0]) {
1144*c8dee2aaSAndroid Build Coastguard Worker return !match(needle + 1, haystack);
1145*c8dee2aaSAndroid Build Coastguard Worker }
1146*c8dee2aaSAndroid Build Coastguard Worker if (0 == strcmp("_", needle)) {
1147*c8dee2aaSAndroid Build Coastguard Worker return true;
1148*c8dee2aaSAndroid Build Coastguard Worker }
1149*c8dee2aaSAndroid Build Coastguard Worker return nullptr != strstr(haystack, needle);
1150*c8dee2aaSAndroid Build Coastguard Worker }
1151*c8dee2aaSAndroid Build Coastguard Worker
should_skip(const char * sink,const char * src,const char * srcOptions,const char * name)1152*c8dee2aaSAndroid Build Coastguard Worker static bool should_skip(const char* sink, const char* src,
1153*c8dee2aaSAndroid Build Coastguard Worker const char* srcOptions, const char* name) {
1154*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < FLAGS_skip.size() - 3; i += 4) {
1155*c8dee2aaSAndroid Build Coastguard Worker if (match(FLAGS_skip[i+0], sink) &&
1156*c8dee2aaSAndroid Build Coastguard Worker match(FLAGS_skip[i+1], src) &&
1157*c8dee2aaSAndroid Build Coastguard Worker match(FLAGS_skip[i+2], srcOptions) &&
1158*c8dee2aaSAndroid Build Coastguard Worker match(FLAGS_skip[i+3], name)) {
1159*c8dee2aaSAndroid Build Coastguard Worker return true;
1160*c8dee2aaSAndroid Build Coastguard Worker }
1161*c8dee2aaSAndroid Build Coastguard Worker }
1162*c8dee2aaSAndroid Build Coastguard Worker return false;
1163*c8dee2aaSAndroid Build Coastguard Worker }
1164*c8dee2aaSAndroid Build Coastguard Worker
1165*c8dee2aaSAndroid Build Coastguard Worker // Even when a Task Sink reports to be non-threadsafe (e.g. GPU), we know things like
1166*c8dee2aaSAndroid Build Coastguard Worker // .png encoding are definitely thread safe. This lets us offload that work to CPU threads.
1167*c8dee2aaSAndroid Build Coastguard Worker static SkTaskGroup* gDefinitelyThreadSafeWork = new SkTaskGroup;
1168*c8dee2aaSAndroid Build Coastguard Worker
1169*c8dee2aaSAndroid Build Coastguard Worker // The finest-grained unit of work we can run: draw a single Src into a single Sink,
1170*c8dee2aaSAndroid Build Coastguard Worker // report any errors, and perhaps write out the output: a .png of the bitmap, or a raw stream.
1171*c8dee2aaSAndroid Build Coastguard Worker struct Task {
TaskTask1172*c8dee2aaSAndroid Build Coastguard Worker Task(const TaggedSrc& src, const TaggedSink& sink) : src(src), sink(sink) {}
1173*c8dee2aaSAndroid Build Coastguard Worker const TaggedSrc& src;
1174*c8dee2aaSAndroid Build Coastguard Worker const TaggedSink& sink;
1175*c8dee2aaSAndroid Build Coastguard Worker
RunTask1176*c8dee2aaSAndroid Build Coastguard Worker static void Run(const Task& task) {
1177*c8dee2aaSAndroid Build Coastguard Worker AutoreleasePool pool;
1178*c8dee2aaSAndroid Build Coastguard Worker SkString name = task.src->name();
1179*c8dee2aaSAndroid Build Coastguard Worker
1180*c8dee2aaSAndroid Build Coastguard Worker SkString log;
1181*c8dee2aaSAndroid Build Coastguard Worker if (!FLAGS_dryRun) {
1182*c8dee2aaSAndroid Build Coastguard Worker SkBitmap bitmap;
1183*c8dee2aaSAndroid Build Coastguard Worker SkDynamicMemoryWStream stream;
1184*c8dee2aaSAndroid Build Coastguard Worker start(task.sink.tag.c_str(), task.src.tag.c_str(),
1185*c8dee2aaSAndroid Build Coastguard Worker task.src.options.c_str(), name.c_str());
1186*c8dee2aaSAndroid Build Coastguard Worker Result result = task.sink->draw(*task.src, &bitmap, &stream, &log);
1187*c8dee2aaSAndroid Build Coastguard Worker if (!log.isEmpty()) {
1188*c8dee2aaSAndroid Build Coastguard Worker info("%s %s %s %s:\n%s\n", task.sink.tag.c_str()
1189*c8dee2aaSAndroid Build Coastguard Worker , task.src.tag.c_str()
1190*c8dee2aaSAndroid Build Coastguard Worker , task.src.options.c_str()
1191*c8dee2aaSAndroid Build Coastguard Worker , name.c_str()
1192*c8dee2aaSAndroid Build Coastguard Worker , log.c_str());
1193*c8dee2aaSAndroid Build Coastguard Worker }
1194*c8dee2aaSAndroid Build Coastguard Worker if (result.isSkip()) {
1195*c8dee2aaSAndroid Build Coastguard Worker done(task.sink.tag.c_str(), task.src.tag.c_str(),
1196*c8dee2aaSAndroid Build Coastguard Worker task.src.options.c_str(), name.c_str());
1197*c8dee2aaSAndroid Build Coastguard Worker return;
1198*c8dee2aaSAndroid Build Coastguard Worker }
1199*c8dee2aaSAndroid Build Coastguard Worker if (result.isFatal()) {
1200*c8dee2aaSAndroid Build Coastguard Worker fail(SkStringPrintf("%s %s %s %s: %s",
1201*c8dee2aaSAndroid Build Coastguard Worker task.sink.tag.c_str(),
1202*c8dee2aaSAndroid Build Coastguard Worker task.src.tag.c_str(),
1203*c8dee2aaSAndroid Build Coastguard Worker task.src.options.c_str(),
1204*c8dee2aaSAndroid Build Coastguard Worker name.c_str(),
1205*c8dee2aaSAndroid Build Coastguard Worker result.c_str()));
1206*c8dee2aaSAndroid Build Coastguard Worker }
1207*c8dee2aaSAndroid Build Coastguard Worker
1208*c8dee2aaSAndroid Build Coastguard Worker // We're likely switching threads here, so we must capture by value, [=] or [foo,bar].
1209*c8dee2aaSAndroid Build Coastguard Worker SkStreamAsset* data = stream.detachAsStream().release();
1210*c8dee2aaSAndroid Build Coastguard Worker gDefinitelyThreadSafeWork->add([task,name,bitmap,data]{
1211*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<SkStreamAsset> ownedData(data);
1212*c8dee2aaSAndroid Build Coastguard Worker
1213*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<HashAndEncode> hashAndEncode;
1214*c8dee2aaSAndroid Build Coastguard Worker
1215*c8dee2aaSAndroid Build Coastguard Worker SkString md5;
1216*c8dee2aaSAndroid Build Coastguard Worker if (!FLAGS_writePath.isEmpty() || !FLAGS_readPath.isEmpty()) {
1217*c8dee2aaSAndroid Build Coastguard Worker SkMD5 hash;
1218*c8dee2aaSAndroid Build Coastguard Worker if (data->getLength()) {
1219*c8dee2aaSAndroid Build Coastguard Worker hash.writeStream(data, data->getLength());
1220*c8dee2aaSAndroid Build Coastguard Worker data->rewind();
1221*c8dee2aaSAndroid Build Coastguard Worker } else {
1222*c8dee2aaSAndroid Build Coastguard Worker hashAndEncode = std::make_unique<HashAndEncode>(bitmap);
1223*c8dee2aaSAndroid Build Coastguard Worker hashAndEncode->feedHash(&hash);
1224*c8dee2aaSAndroid Build Coastguard Worker }
1225*c8dee2aaSAndroid Build Coastguard Worker md5 = hash.finish().toLowercaseHexString();
1226*c8dee2aaSAndroid Build Coastguard Worker }
1227*c8dee2aaSAndroid Build Coastguard Worker
1228*c8dee2aaSAndroid Build Coastguard Worker if (!FLAGS_readPath.isEmpty() &&
1229*c8dee2aaSAndroid Build Coastguard Worker !gGold->contains(Gold(task.sink.tag, task.src.tag,
1230*c8dee2aaSAndroid Build Coastguard Worker task.src.options, name, md5))) {
1231*c8dee2aaSAndroid Build Coastguard Worker fail(SkStringPrintf("%s not found for %s %s %s %s in %s",
1232*c8dee2aaSAndroid Build Coastguard Worker md5.c_str(),
1233*c8dee2aaSAndroid Build Coastguard Worker task.sink.tag.c_str(),
1234*c8dee2aaSAndroid Build Coastguard Worker task.src.tag.c_str(),
1235*c8dee2aaSAndroid Build Coastguard Worker task.src.options.c_str(),
1236*c8dee2aaSAndroid Build Coastguard Worker name.c_str(),
1237*c8dee2aaSAndroid Build Coastguard Worker FLAGS_readPath[0]));
1238*c8dee2aaSAndroid Build Coastguard Worker }
1239*c8dee2aaSAndroid Build Coastguard Worker
1240*c8dee2aaSAndroid Build Coastguard Worker // Tests sometimes use a nullptr ext to indicate no image should be uploaded.
1241*c8dee2aaSAndroid Build Coastguard Worker const char* ext = task.sink->fileExtension();
1242*c8dee2aaSAndroid Build Coastguard Worker if (ext && !FLAGS_writePath.isEmpty()) {
1243*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_BUILD_FOR_MAC)
1244*c8dee2aaSAndroid Build Coastguard Worker if (FLAGS_rasterize_pdf && SkString("pdf").equals(ext)) {
1245*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(data->getLength() > 0);
1246*c8dee2aaSAndroid Build Coastguard Worker
1247*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkData> blob = SkData::MakeFromStream(data, data->getLength());
1248*c8dee2aaSAndroid Build Coastguard Worker
1249*c8dee2aaSAndroid Build Coastguard Worker SkUniqueCFRef<CGDataProviderRef> provider{
1250*c8dee2aaSAndroid Build Coastguard Worker CGDataProviderCreateWithData(nullptr,
1251*c8dee2aaSAndroid Build Coastguard Worker blob->data(),
1252*c8dee2aaSAndroid Build Coastguard Worker blob->size(),
1253*c8dee2aaSAndroid Build Coastguard Worker nullptr)};
1254*c8dee2aaSAndroid Build Coastguard Worker
1255*c8dee2aaSAndroid Build Coastguard Worker SkUniqueCFRef<CGPDFDocumentRef> pdf{
1256*c8dee2aaSAndroid Build Coastguard Worker CGPDFDocumentCreateWithProvider(provider.get())};
1257*c8dee2aaSAndroid Build Coastguard Worker
1258*c8dee2aaSAndroid Build Coastguard Worker CGPDFPageRef page = CGPDFDocumentGetPage(pdf.get(), 1);
1259*c8dee2aaSAndroid Build Coastguard Worker
1260*c8dee2aaSAndroid Build Coastguard Worker CGRect bounds = CGPDFPageGetBoxRect(page, kCGPDFMediaBox);
1261*c8dee2aaSAndroid Build Coastguard Worker const int w = (int)CGRectGetWidth (bounds),
1262*c8dee2aaSAndroid Build Coastguard Worker h = (int)CGRectGetHeight(bounds);
1263*c8dee2aaSAndroid Build Coastguard Worker
1264*c8dee2aaSAndroid Build Coastguard Worker SkBitmap rasterized;
1265*c8dee2aaSAndroid Build Coastguard Worker rasterized.allocPixels(SkImageInfo::Make(
1266*c8dee2aaSAndroid Build Coastguard Worker w, h, kRGBA_8888_SkColorType, kPremul_SkAlphaType));
1267*c8dee2aaSAndroid Build Coastguard Worker rasterized.eraseColor(SK_ColorWHITE);
1268*c8dee2aaSAndroid Build Coastguard Worker
1269*c8dee2aaSAndroid Build Coastguard Worker SkUniqueCFRef<CGColorSpaceRef> cs{CGColorSpaceCreateDeviceRGB()};
1270*c8dee2aaSAndroid Build Coastguard Worker CGBitmapInfo info = kCGBitmapByteOrder32Big |
1271*c8dee2aaSAndroid Build Coastguard Worker (CGBitmapInfo)kCGImageAlphaPremultipliedLast;
1272*c8dee2aaSAndroid Build Coastguard Worker
1273*c8dee2aaSAndroid Build Coastguard Worker SkUniqueCFRef<CGContextRef> ctx{CGBitmapContextCreate(
1274*c8dee2aaSAndroid Build Coastguard Worker rasterized.getPixels(), w,h,8, rasterized.rowBytes(), cs.get(), info)};
1275*c8dee2aaSAndroid Build Coastguard Worker CGContextDrawPDFPage(ctx.get(), page);
1276*c8dee2aaSAndroid Build Coastguard Worker
1277*c8dee2aaSAndroid Build Coastguard Worker // Skip calling hashAndEncode->feedHash(SkMD5*)... we want the .pdf's hash.
1278*c8dee2aaSAndroid Build Coastguard Worker hashAndEncode = std::make_unique<HashAndEncode>(rasterized);
1279*c8dee2aaSAndroid Build Coastguard Worker WriteToDisk(task, md5, "png", nullptr,0, &rasterized, hashAndEncode.get());
1280*c8dee2aaSAndroid Build Coastguard Worker } else
1281*c8dee2aaSAndroid Build Coastguard Worker #endif
1282*c8dee2aaSAndroid Build Coastguard Worker if (data->getLength()) {
1283*c8dee2aaSAndroid Build Coastguard Worker WriteToDisk(task, md5, ext, data, data->getLength(), nullptr, nullptr);
1284*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(bitmap.drawsNothing());
1285*c8dee2aaSAndroid Build Coastguard Worker } else if (!bitmap.drawsNothing()) {
1286*c8dee2aaSAndroid Build Coastguard Worker WriteToDisk(task, md5, ext, nullptr, 0, &bitmap, hashAndEncode.get());
1287*c8dee2aaSAndroid Build Coastguard Worker }
1288*c8dee2aaSAndroid Build Coastguard Worker }
1289*c8dee2aaSAndroid Build Coastguard Worker
1290*c8dee2aaSAndroid Build Coastguard Worker SkPixmap pm;
1291*c8dee2aaSAndroid Build Coastguard Worker if (FLAGS_checkF16 && bitmap.colorType() == kRGBA_F16Norm_SkColorType &&
1292*c8dee2aaSAndroid Build Coastguard Worker bitmap.peekPixels(&pm)) {
1293*c8dee2aaSAndroid Build Coastguard Worker bool unclamped = false;
1294*c8dee2aaSAndroid Build Coastguard Worker for (int y = 0; y < pm.height() && !unclamped; ++y)
1295*c8dee2aaSAndroid Build Coastguard Worker for (int x = 0; x < pm.width() && !unclamped; ++x) {
1296*c8dee2aaSAndroid Build Coastguard Worker skvx::float4 rgba = from_half(skvx::half4::Load(pm.addr64(x, y)));
1297*c8dee2aaSAndroid Build Coastguard Worker float a = rgba[3];
1298*c8dee2aaSAndroid Build Coastguard Worker if (a > 1.0f || any(rgba < 0.0f) || any(rgba > a)) {
1299*c8dee2aaSAndroid Build Coastguard Worker SkDebugf("[%s] F16Norm pixel [%d, %d] unclamped: (%g, %g, %g, %g)\n",
1300*c8dee2aaSAndroid Build Coastguard Worker name.c_str(), x, y, rgba[0], rgba[1], rgba[2], rgba[3]);
1301*c8dee2aaSAndroid Build Coastguard Worker unclamped = true;
1302*c8dee2aaSAndroid Build Coastguard Worker }
1303*c8dee2aaSAndroid Build Coastguard Worker }
1304*c8dee2aaSAndroid Build Coastguard Worker }
1305*c8dee2aaSAndroid Build Coastguard Worker });
1306*c8dee2aaSAndroid Build Coastguard Worker }
1307*c8dee2aaSAndroid Build Coastguard Worker done(task.sink.tag.c_str(), task.src.tag.c_str(), task.src.options.c_str(), name.c_str());
1308*c8dee2aaSAndroid Build Coastguard Worker }
1309*c8dee2aaSAndroid Build Coastguard Worker
identify_gamutTask1310*c8dee2aaSAndroid Build Coastguard Worker static SkString identify_gamut(SkColorSpace* cs) {
1311*c8dee2aaSAndroid Build Coastguard Worker if (!cs) {
1312*c8dee2aaSAndroid Build Coastguard Worker return SkString("untagged");
1313*c8dee2aaSAndroid Build Coastguard Worker }
1314*c8dee2aaSAndroid Build Coastguard Worker
1315*c8dee2aaSAndroid Build Coastguard Worker skcms_Matrix3x3 gamut;
1316*c8dee2aaSAndroid Build Coastguard Worker if (cs->toXYZD50(&gamut)) {
1317*c8dee2aaSAndroid Build Coastguard Worker auto eq = [](skcms_Matrix3x3 x, skcms_Matrix3x3 y) {
1318*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < 3; i++)
1319*c8dee2aaSAndroid Build Coastguard Worker for (int j = 0; j < 3; j++) {
1320*c8dee2aaSAndroid Build Coastguard Worker if (x.vals[i][j] != y.vals[i][j]) { return false; }
1321*c8dee2aaSAndroid Build Coastguard Worker }
1322*c8dee2aaSAndroid Build Coastguard Worker return true;
1323*c8dee2aaSAndroid Build Coastguard Worker };
1324*c8dee2aaSAndroid Build Coastguard Worker
1325*c8dee2aaSAndroid Build Coastguard Worker if (eq(gamut, SkNamedGamut::kSRGB )) { return SkString("sRGB"); }
1326*c8dee2aaSAndroid Build Coastguard Worker if (eq(gamut, SkNamedGamut::kAdobeRGB )) { return SkString("Adobe"); }
1327*c8dee2aaSAndroid Build Coastguard Worker if (eq(gamut, SkNamedGamut::kDisplayP3)) { return SkString("P3"); }
1328*c8dee2aaSAndroid Build Coastguard Worker if (eq(gamut, SkNamedGamut::kRec2020 )) { return SkString("2020"); }
1329*c8dee2aaSAndroid Build Coastguard Worker if (eq(gamut, SkNamedGamut::kXYZ )) { return SkString("XYZ"); }
1330*c8dee2aaSAndroid Build Coastguard Worker if (eq(gamut, gNarrow_toXYZD50 )) { return SkString("narrow"); }
1331*c8dee2aaSAndroid Build Coastguard Worker return SkString("other");
1332*c8dee2aaSAndroid Build Coastguard Worker }
1333*c8dee2aaSAndroid Build Coastguard Worker return SkString("non-XYZ");
1334*c8dee2aaSAndroid Build Coastguard Worker }
1335*c8dee2aaSAndroid Build Coastguard Worker
identify_transfer_fnTask1336*c8dee2aaSAndroid Build Coastguard Worker static SkString identify_transfer_fn(SkColorSpace* cs) {
1337*c8dee2aaSAndroid Build Coastguard Worker if (!cs) {
1338*c8dee2aaSAndroid Build Coastguard Worker return SkString("untagged");
1339*c8dee2aaSAndroid Build Coastguard Worker }
1340*c8dee2aaSAndroid Build Coastguard Worker
1341*c8dee2aaSAndroid Build Coastguard Worker auto eq = [](skcms_TransferFunction x, skcms_TransferFunction y) {
1342*c8dee2aaSAndroid Build Coastguard Worker return x.g == y.g
1343*c8dee2aaSAndroid Build Coastguard Worker && x.a == y.a
1344*c8dee2aaSAndroid Build Coastguard Worker && x.b == y.b
1345*c8dee2aaSAndroid Build Coastguard Worker && x.c == y.c
1346*c8dee2aaSAndroid Build Coastguard Worker && x.d == y.d
1347*c8dee2aaSAndroid Build Coastguard Worker && x.e == y.e
1348*c8dee2aaSAndroid Build Coastguard Worker && x.f == y.f;
1349*c8dee2aaSAndroid Build Coastguard Worker };
1350*c8dee2aaSAndroid Build Coastguard Worker
1351*c8dee2aaSAndroid Build Coastguard Worker skcms_TransferFunction tf;
1352*c8dee2aaSAndroid Build Coastguard Worker cs->transferFn(&tf);
1353*c8dee2aaSAndroid Build Coastguard Worker switch (skcms_TransferFunction_getType(&tf)) {
1354*c8dee2aaSAndroid Build Coastguard Worker case skcms_TFType_sRGBish:
1355*c8dee2aaSAndroid Build Coastguard Worker if (tf.a == 1 && tf.b == 0 && tf.c == 0 && tf.d == 0 && tf.e == 0 && tf.f == 0) {
1356*c8dee2aaSAndroid Build Coastguard Worker return SkStringPrintf("gamma %.3g", tf.g);
1357*c8dee2aaSAndroid Build Coastguard Worker }
1358*c8dee2aaSAndroid Build Coastguard Worker if (eq(tf, SkNamedTransferFn::kSRGB)) { return SkString("sRGB"); }
1359*c8dee2aaSAndroid Build Coastguard Worker if (eq(tf, SkNamedTransferFn::kRec2020)) { return SkString("2020"); }
1360*c8dee2aaSAndroid Build Coastguard Worker return SkStringPrintf("%.3g %.3g %.3g %.3g %.3g %.3g %.3g",
1361*c8dee2aaSAndroid Build Coastguard Worker tf.g, tf.a, tf.b, tf.c, tf.d, tf.e, tf.f);
1362*c8dee2aaSAndroid Build Coastguard Worker
1363*c8dee2aaSAndroid Build Coastguard Worker case skcms_TFType_PQish:
1364*c8dee2aaSAndroid Build Coastguard Worker if (eq(tf, SkNamedTransferFn::kPQ)) { return SkString("PQ"); }
1365*c8dee2aaSAndroid Build Coastguard Worker return SkStringPrintf("PQish %.3g %.3g %.3g %.3g %.3g %.3g",
1366*c8dee2aaSAndroid Build Coastguard Worker tf.a, tf.b, tf.c, tf.d, tf.e, tf.f);
1367*c8dee2aaSAndroid Build Coastguard Worker
1368*c8dee2aaSAndroid Build Coastguard Worker case skcms_TFType_HLGish:
1369*c8dee2aaSAndroid Build Coastguard Worker if (eq(tf, SkNamedTransferFn::kHLG)) { return SkString("HLG"); }
1370*c8dee2aaSAndroid Build Coastguard Worker return SkStringPrintf("HLGish %.3g %.3g %.3g %.3g %.3g (%.3g)",
1371*c8dee2aaSAndroid Build Coastguard Worker tf.a, tf.b, tf.c, tf.d, tf.e, tf.f+1);
1372*c8dee2aaSAndroid Build Coastguard Worker
1373*c8dee2aaSAndroid Build Coastguard Worker case skcms_TFType_HLGinvish: break;
1374*c8dee2aaSAndroid Build Coastguard Worker case skcms_TFType_Invalid: break;
1375*c8dee2aaSAndroid Build Coastguard Worker }
1376*c8dee2aaSAndroid Build Coastguard Worker return SkString("non-numeric");
1377*c8dee2aaSAndroid Build Coastguard Worker }
1378*c8dee2aaSAndroid Build Coastguard Worker
WriteToDiskTask1379*c8dee2aaSAndroid Build Coastguard Worker static void WriteToDisk(const Task& task,
1380*c8dee2aaSAndroid Build Coastguard Worker SkString md5,
1381*c8dee2aaSAndroid Build Coastguard Worker const char* ext,
1382*c8dee2aaSAndroid Build Coastguard Worker SkStream* data, size_t len,
1383*c8dee2aaSAndroid Build Coastguard Worker const SkBitmap* bitmap,
1384*c8dee2aaSAndroid Build Coastguard Worker const HashAndEncode* hashAndEncode) {
1385*c8dee2aaSAndroid Build Coastguard Worker
1386*c8dee2aaSAndroid Build Coastguard Worker // Determine whether or not the OldestSupportedSkpVersion extra_config is provided.
1387*c8dee2aaSAndroid Build Coastguard Worker bool isOldestSupportedSkp = false;
1388*c8dee2aaSAndroid Build Coastguard Worker for (int i = 1; i < FLAGS_key.size(); i += 2) {
1389*c8dee2aaSAndroid Build Coastguard Worker if (0 == strcmp(FLAGS_key[i-1], "extra_config") &&
1390*c8dee2aaSAndroid Build Coastguard Worker 0 == strcmp(FLAGS_key[i], "OldestSupportedSkpVersion")) {
1391*c8dee2aaSAndroid Build Coastguard Worker isOldestSupportedSkp = true;
1392*c8dee2aaSAndroid Build Coastguard Worker break;
1393*c8dee2aaSAndroid Build Coastguard Worker }
1394*c8dee2aaSAndroid Build Coastguard Worker }
1395*c8dee2aaSAndroid Build Coastguard Worker
1396*c8dee2aaSAndroid Build Coastguard Worker JsonWriter::BitmapResult result;
1397*c8dee2aaSAndroid Build Coastguard Worker result.name = task.src->name();
1398*c8dee2aaSAndroid Build Coastguard Worker result.config = task.sink.tag;
1399*c8dee2aaSAndroid Build Coastguard Worker result.sourceType = task.src.tag;
1400*c8dee2aaSAndroid Build Coastguard Worker // If the OldestSupportedSkpVersion extra_config is provided, override the "skp"
1401*c8dee2aaSAndroid Build Coastguard Worker // source_type with "old-skp". This has the effect of grouping the oldest supported SKPs in
1402*c8dee2aaSAndroid Build Coastguard Worker // a separate Gold corpus for easier triaging.
1403*c8dee2aaSAndroid Build Coastguard Worker if (isOldestSupportedSkp && 0 == strcmp(result.sourceType.c_str(), "skp")) {
1404*c8dee2aaSAndroid Build Coastguard Worker result.sourceType = "old-skp";
1405*c8dee2aaSAndroid Build Coastguard Worker }
1406*c8dee2aaSAndroid Build Coastguard Worker result.sourceOptions = task.src.options;
1407*c8dee2aaSAndroid Build Coastguard Worker result.ext = ext;
1408*c8dee2aaSAndroid Build Coastguard Worker result.md5 = md5;
1409*c8dee2aaSAndroid Build Coastguard Worker if (bitmap) {
1410*c8dee2aaSAndroid Build Coastguard Worker result.gamut = identify_gamut (bitmap->colorSpace());
1411*c8dee2aaSAndroid Build Coastguard Worker result.transferFn = identify_transfer_fn (bitmap->colorSpace());
1412*c8dee2aaSAndroid Build Coastguard Worker result.colorType = ToolUtils::colortype_name (bitmap->colorType());
1413*c8dee2aaSAndroid Build Coastguard Worker result.alphaType = ToolUtils::alphatype_name (bitmap->alphaType());
1414*c8dee2aaSAndroid Build Coastguard Worker result.colorDepth = ToolUtils::colortype_depth(bitmap->colorType());
1415*c8dee2aaSAndroid Build Coastguard Worker }
1416*c8dee2aaSAndroid Build Coastguard Worker JsonWriter::AddBitmapResult(result);
1417*c8dee2aaSAndroid Build Coastguard Worker
1418*c8dee2aaSAndroid Build Coastguard Worker // If an MD5 is uninteresting, we want it noted in the JSON file,
1419*c8dee2aaSAndroid Build Coastguard Worker // but don't want to dump it out as a .png (or whatever ext is).
1420*c8dee2aaSAndroid Build Coastguard Worker if (gUninterestingHashes->contains(md5)) {
1421*c8dee2aaSAndroid Build Coastguard Worker return;
1422*c8dee2aaSAndroid Build Coastguard Worker }
1423*c8dee2aaSAndroid Build Coastguard Worker
1424*c8dee2aaSAndroid Build Coastguard Worker const char* dir = FLAGS_writePath[0];
1425*c8dee2aaSAndroid Build Coastguard Worker SkString resources = GetResourcePath();
1426*c8dee2aaSAndroid Build Coastguard Worker if (0 == strcmp(dir, "@")) { // Needed for iOS.
1427*c8dee2aaSAndroid Build Coastguard Worker dir = resources.c_str();
1428*c8dee2aaSAndroid Build Coastguard Worker }
1429*c8dee2aaSAndroid Build Coastguard Worker sk_mkdir(dir);
1430*c8dee2aaSAndroid Build Coastguard Worker
1431*c8dee2aaSAndroid Build Coastguard Worker SkString path;
1432*c8dee2aaSAndroid Build Coastguard Worker if (FLAGS_nameByHash) {
1433*c8dee2aaSAndroid Build Coastguard Worker path = SkOSPath::Join(dir, result.md5.c_str());
1434*c8dee2aaSAndroid Build Coastguard Worker path.append(".");
1435*c8dee2aaSAndroid Build Coastguard Worker path.append(ext);
1436*c8dee2aaSAndroid Build Coastguard Worker if (sk_exists(path.c_str())) {
1437*c8dee2aaSAndroid Build Coastguard Worker return; // Content-addressed. If it exists already, we're done.
1438*c8dee2aaSAndroid Build Coastguard Worker }
1439*c8dee2aaSAndroid Build Coastguard Worker } else {
1440*c8dee2aaSAndroid Build Coastguard Worker path = SkOSPath::Join(dir, task.sink.tag.c_str());
1441*c8dee2aaSAndroid Build Coastguard Worker sk_mkdir(path.c_str());
1442*c8dee2aaSAndroid Build Coastguard Worker path = SkOSPath::Join(path.c_str(), task.src.tag.c_str());
1443*c8dee2aaSAndroid Build Coastguard Worker sk_mkdir(path.c_str());
1444*c8dee2aaSAndroid Build Coastguard Worker if (0 != strcmp(task.src.options.c_str(), "")) {
1445*c8dee2aaSAndroid Build Coastguard Worker path = SkOSPath::Join(path.c_str(), task.src.options.c_str());
1446*c8dee2aaSAndroid Build Coastguard Worker sk_mkdir(path.c_str());
1447*c8dee2aaSAndroid Build Coastguard Worker }
1448*c8dee2aaSAndroid Build Coastguard Worker path = SkOSPath::Join(path.c_str(), task.src->name().c_str());
1449*c8dee2aaSAndroid Build Coastguard Worker path.append(".");
1450*c8dee2aaSAndroid Build Coastguard Worker path.append(ext);
1451*c8dee2aaSAndroid Build Coastguard Worker }
1452*c8dee2aaSAndroid Build Coastguard Worker
1453*c8dee2aaSAndroid Build Coastguard Worker SkFILEWStream file(path.c_str());
1454*c8dee2aaSAndroid Build Coastguard Worker if (!file.isValid()) {
1455*c8dee2aaSAndroid Build Coastguard Worker fail(SkStringPrintf("Can't open %s for writing.\n", path.c_str()));
1456*c8dee2aaSAndroid Build Coastguard Worker return;
1457*c8dee2aaSAndroid Build Coastguard Worker }
1458*c8dee2aaSAndroid Build Coastguard Worker if (bitmap) {
1459*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(hashAndEncode);
1460*c8dee2aaSAndroid Build Coastguard Worker if (!hashAndEncode->encodePNG(&file,
1461*c8dee2aaSAndroid Build Coastguard Worker result.md5.c_str(),
1462*c8dee2aaSAndroid Build Coastguard Worker FLAGS_key,
1463*c8dee2aaSAndroid Build Coastguard Worker FLAGS_properties)) {
1464*c8dee2aaSAndroid Build Coastguard Worker fail(SkStringPrintf("Can't encode PNG to %s.\n", path.c_str()));
1465*c8dee2aaSAndroid Build Coastguard Worker return;
1466*c8dee2aaSAndroid Build Coastguard Worker }
1467*c8dee2aaSAndroid Build Coastguard Worker } else {
1468*c8dee2aaSAndroid Build Coastguard Worker if (!file.writeStream(data, len)) {
1469*c8dee2aaSAndroid Build Coastguard Worker fail(SkStringPrintf("Can't write to %s.\n", path.c_str()));
1470*c8dee2aaSAndroid Build Coastguard Worker return;
1471*c8dee2aaSAndroid Build Coastguard Worker }
1472*c8dee2aaSAndroid Build Coastguard Worker }
1473*c8dee2aaSAndroid Build Coastguard Worker }
1474*c8dee2aaSAndroid Build Coastguard Worker };
1475*c8dee2aaSAndroid Build Coastguard Worker
1476*c8dee2aaSAndroid Build Coastguard Worker /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
1477*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_DISABLE_LEGACY_TESTS)
gather_tests()1478*c8dee2aaSAndroid Build Coastguard Worker static int gather_tests() { return 0; }
1479*c8dee2aaSAndroid Build Coastguard Worker #else
1480*c8dee2aaSAndroid Build Coastguard Worker // Unit tests don't fit so well into the Src/Sink model, so we give them special treatment.
1481*c8dee2aaSAndroid Build Coastguard Worker
1482*c8dee2aaSAndroid Build Coastguard Worker static SkTDArray<skiatest::Test>* gCPUTests = new SkTDArray<skiatest::Test>;
1483*c8dee2aaSAndroid Build Coastguard Worker static SkTDArray<skiatest::Test>* gCPUSerialTests = new SkTDArray<skiatest::Test>;
1484*c8dee2aaSAndroid Build Coastguard Worker static SkTDArray<skiatest::Test>* gGaneshTests = new SkTDArray<skiatest::Test>;
1485*c8dee2aaSAndroid Build Coastguard Worker static SkTDArray<skiatest::Test>* gGraphiteTests = new SkTDArray<skiatest::Test>;
1486*c8dee2aaSAndroid Build Coastguard Worker
gather_tests()1487*c8dee2aaSAndroid Build Coastguard Worker static int gather_tests() {
1488*c8dee2aaSAndroid Build Coastguard Worker if (!FLAGS_src.contains("tests")) {
1489*c8dee2aaSAndroid Build Coastguard Worker return 0;
1490*c8dee2aaSAndroid Build Coastguard Worker }
1491*c8dee2aaSAndroid Build Coastguard Worker for (const skiatest::Test& test : skiatest::TestRegistry::Range()) {
1492*c8dee2aaSAndroid Build Coastguard Worker if (!in_shard()) {
1493*c8dee2aaSAndroid Build Coastguard Worker continue;
1494*c8dee2aaSAndroid Build Coastguard Worker }
1495*c8dee2aaSAndroid Build Coastguard Worker if (CommandLineFlags::ShouldSkip(FLAGS_match, test.fName)) {
1496*c8dee2aaSAndroid Build Coastguard Worker continue;
1497*c8dee2aaSAndroid Build Coastguard Worker }
1498*c8dee2aaSAndroid Build Coastguard Worker if (test.fTestType == TestType::kGanesh && FLAGS_gpu) {
1499*c8dee2aaSAndroid Build Coastguard Worker gGaneshTests->push_back(test);
1500*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_GRAPHITE)
1501*c8dee2aaSAndroid Build Coastguard Worker } else if (test.fTestType == TestType::kGraphite && FLAGS_graphite) {
1502*c8dee2aaSAndroid Build Coastguard Worker gGraphiteTests->push_back(test);
1503*c8dee2aaSAndroid Build Coastguard Worker #endif
1504*c8dee2aaSAndroid Build Coastguard Worker } else if (test.fTestType == TestType::kCPU && FLAGS_cpu) {
1505*c8dee2aaSAndroid Build Coastguard Worker gCPUTests->push_back(test);
1506*c8dee2aaSAndroid Build Coastguard Worker } else if (test.fTestType == TestType::kCPUSerial && FLAGS_cpu) {
1507*c8dee2aaSAndroid Build Coastguard Worker gCPUSerialTests->push_back(test);
1508*c8dee2aaSAndroid Build Coastguard Worker }
1509*c8dee2aaSAndroid Build Coastguard Worker }
1510*c8dee2aaSAndroid Build Coastguard Worker return gCPUTests->size() + gCPUSerialTests->size() +
1511*c8dee2aaSAndroid Build Coastguard Worker gGaneshTests->size() + gGraphiteTests->size();
1512*c8dee2aaSAndroid Build Coastguard Worker }
1513*c8dee2aaSAndroid Build Coastguard Worker
1514*c8dee2aaSAndroid Build Coastguard Worker struct DMReporter : public skiatest::Reporter {
reportFailedDMReporter1515*c8dee2aaSAndroid Build Coastguard Worker void reportFailed(const skiatest::Failure& failure) override {
1516*c8dee2aaSAndroid Build Coastguard Worker fail(failure.toString());
1517*c8dee2aaSAndroid Build Coastguard Worker }
allowExtendedTestDMReporter1518*c8dee2aaSAndroid Build Coastguard Worker bool allowExtendedTest() const override {
1519*c8dee2aaSAndroid Build Coastguard Worker return FLAGS_pathOpsExtended;
1520*c8dee2aaSAndroid Build Coastguard Worker }
verboseDMReporter1521*c8dee2aaSAndroid Build Coastguard Worker bool verbose() const override { return FLAGS_veryVerbose; }
1522*c8dee2aaSAndroid Build Coastguard Worker };
1523*c8dee2aaSAndroid Build Coastguard Worker
run_cpu_test(skiatest::Test test)1524*c8dee2aaSAndroid Build Coastguard Worker static void run_cpu_test(skiatest::Test test) {
1525*c8dee2aaSAndroid Build Coastguard Worker DMReporter reporter;
1526*c8dee2aaSAndroid Build Coastguard Worker if (!FLAGS_dryRun && !should_skip("_", "tests", "_", test.fName)) {
1527*c8dee2aaSAndroid Build Coastguard Worker skiatest::ReporterContext ctx(&reporter, SkString(test.fName));
1528*c8dee2aaSAndroid Build Coastguard Worker start("unit", "test", "", test.fName);
1529*c8dee2aaSAndroid Build Coastguard Worker test.cpu(&reporter);
1530*c8dee2aaSAndroid Build Coastguard Worker }
1531*c8dee2aaSAndroid Build Coastguard Worker done("unit", "test", "", test.fName);
1532*c8dee2aaSAndroid Build Coastguard Worker }
1533*c8dee2aaSAndroid Build Coastguard Worker
run_ganesh_test(skiatest::Test test,const GrContextOptions & grCtxOptions)1534*c8dee2aaSAndroid Build Coastguard Worker static void run_ganesh_test(skiatest::Test test, const GrContextOptions& grCtxOptions) {
1535*c8dee2aaSAndroid Build Coastguard Worker DMReporter reporter;
1536*c8dee2aaSAndroid Build Coastguard Worker if (!FLAGS_dryRun && !should_skip("_", "tests", "_", test.fName)) {
1537*c8dee2aaSAndroid Build Coastguard Worker AutoreleasePool pool;
1538*c8dee2aaSAndroid Build Coastguard Worker GrContextOptions options = grCtxOptions;
1539*c8dee2aaSAndroid Build Coastguard Worker test.modifyGrContextOptions(&options);
1540*c8dee2aaSAndroid Build Coastguard Worker
1541*c8dee2aaSAndroid Build Coastguard Worker skiatest::ReporterContext ctx(&reporter, SkString(test.fName));
1542*c8dee2aaSAndroid Build Coastguard Worker start("unit", "test", "", test.fName);
1543*c8dee2aaSAndroid Build Coastguard Worker test.ganesh(&reporter, options);
1544*c8dee2aaSAndroid Build Coastguard Worker }
1545*c8dee2aaSAndroid Build Coastguard Worker done("unit", "test", "", test.fName);
1546*c8dee2aaSAndroid Build Coastguard Worker }
1547*c8dee2aaSAndroid Build Coastguard Worker
1548*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_GRAPHITE)
run_graphite_test(skiatest::Test test,const skiatest::graphite::TestOptions & optionsIn)1549*c8dee2aaSAndroid Build Coastguard Worker static void run_graphite_test(skiatest::Test test,
1550*c8dee2aaSAndroid Build Coastguard Worker const skiatest::graphite::TestOptions& optionsIn) {
1551*c8dee2aaSAndroid Build Coastguard Worker DMReporter reporter;
1552*c8dee2aaSAndroid Build Coastguard Worker if (!FLAGS_dryRun && !should_skip("_", "tests", "_", test.fName)) {
1553*c8dee2aaSAndroid Build Coastguard Worker AutoreleasePool pool;
1554*c8dee2aaSAndroid Build Coastguard Worker skiatest::graphite::TestOptions options = optionsIn;
1555*c8dee2aaSAndroid Build Coastguard Worker test.modifyGraphiteContextOptions(&options.fContextOptions);
1556*c8dee2aaSAndroid Build Coastguard Worker
1557*c8dee2aaSAndroid Build Coastguard Worker skiatest::ReporterContext ctx(&reporter, SkString(test.fName));
1558*c8dee2aaSAndroid Build Coastguard Worker start("unit", "test", "", test.fName);
1559*c8dee2aaSAndroid Build Coastguard Worker test.graphite(&reporter, options);
1560*c8dee2aaSAndroid Build Coastguard Worker }
1561*c8dee2aaSAndroid Build Coastguard Worker done("unit", "test", "", test.fName);
1562*c8dee2aaSAndroid Build Coastguard Worker }
1563*c8dee2aaSAndroid Build Coastguard Worker #endif
1564*c8dee2aaSAndroid Build Coastguard Worker
1565*c8dee2aaSAndroid Build Coastguard Worker /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
1566*c8dee2aaSAndroid Build Coastguard Worker
CurrentTestHarness()1567*c8dee2aaSAndroid Build Coastguard Worker TestHarness CurrentTestHarness() {
1568*c8dee2aaSAndroid Build Coastguard Worker return TestHarness::kDM;
1569*c8dee2aaSAndroid Build Coastguard Worker }
1570*c8dee2aaSAndroid Build Coastguard Worker
1571*c8dee2aaSAndroid Build Coastguard Worker /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
1572*c8dee2aaSAndroid Build Coastguard Worker
1573*c8dee2aaSAndroid Build Coastguard Worker #endif // !SK_DISABLE_LEGACY_TESTS
1574*c8dee2aaSAndroid Build Coastguard Worker
main(int argc,char ** argv)1575*c8dee2aaSAndroid Build Coastguard Worker int main(int argc, char** argv) {
1576*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_BUILD_FOR_ANDROID_FRAMEWORK) && defined(SK_HAS_HEIF_LIBRARY)
1577*c8dee2aaSAndroid Build Coastguard Worker android::ProcessState::self()->startThreadPool();
1578*c8dee2aaSAndroid Build Coastguard Worker #endif
1579*c8dee2aaSAndroid Build Coastguard Worker CommandLineFlags::Parse(argc, argv);
1580*c8dee2aaSAndroid Build Coastguard Worker
1581*c8dee2aaSAndroid Build Coastguard Worker initializeEventTracingForTools();
1582*c8dee2aaSAndroid Build Coastguard Worker
1583*c8dee2aaSAndroid Build Coastguard Worker #if !defined(SK_BUILD_FOR_GOOGLE3) && defined(SK_BUILD_FOR_IOS)
1584*c8dee2aaSAndroid Build Coastguard Worker cd_Documents();
1585*c8dee2aaSAndroid Build Coastguard Worker #endif
1586*c8dee2aaSAndroid Build Coastguard Worker setbuf(stdout, nullptr);
1587*c8dee2aaSAndroid Build Coastguard Worker setup_crash_handler();
1588*c8dee2aaSAndroid Build Coastguard Worker
1589*c8dee2aaSAndroid Build Coastguard Worker skiatest::SetFontTestDataDirectory();
1590*c8dee2aaSAndroid Build Coastguard Worker
1591*c8dee2aaSAndroid Build Coastguard Worker gSkForceRasterPipelineBlitter = FLAGS_forceRasterPipelineHP || FLAGS_forceRasterPipeline;
1592*c8dee2aaSAndroid Build Coastguard Worker gForceHighPrecisionRasterPipeline = FLAGS_forceRasterPipelineHP;
1593*c8dee2aaSAndroid Build Coastguard Worker gCreateProtectedContext = FLAGS_createProtected;
1594*c8dee2aaSAndroid Build Coastguard Worker
1595*c8dee2aaSAndroid Build Coastguard Worker // The bots like having a verbose.log to upload, so always touch the file even if --verbose.
1596*c8dee2aaSAndroid Build Coastguard Worker if (!FLAGS_writePath.isEmpty()) {
1597*c8dee2aaSAndroid Build Coastguard Worker sk_mkdir(FLAGS_writePath[0]);
1598*c8dee2aaSAndroid Build Coastguard Worker gVLog = fopen(SkOSPath::Join(FLAGS_writePath[0], "verbose.log").c_str(), "w");
1599*c8dee2aaSAndroid Build Coastguard Worker }
1600*c8dee2aaSAndroid Build Coastguard Worker if (FLAGS_verbose) {
1601*c8dee2aaSAndroid Build Coastguard Worker gVLog = stderr;
1602*c8dee2aaSAndroid Build Coastguard Worker }
1603*c8dee2aaSAndroid Build Coastguard Worker
1604*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_GRAPHITE)
1605*c8dee2aaSAndroid Build Coastguard Worker skiatest::graphite::TestOptions graphiteOptions;
1606*c8dee2aaSAndroid Build Coastguard Worker CommonFlags::SetTestOptions(&graphiteOptions);
1607*c8dee2aaSAndroid Build Coastguard Worker #endif
1608*c8dee2aaSAndroid Build Coastguard Worker
1609*c8dee2aaSAndroid Build Coastguard Worker GrContextOptions grCtxOptions;
1610*c8dee2aaSAndroid Build Coastguard Worker CommonFlags::SetCtxOptions(&grCtxOptions);
1611*c8dee2aaSAndroid Build Coastguard Worker
1612*c8dee2aaSAndroid Build Coastguard Worker dump_json(); // It's handy for the bots to assume this is ~never missing.
1613*c8dee2aaSAndroid Build Coastguard Worker
1614*c8dee2aaSAndroid Build Coastguard Worker SkGraphics::Init();
1615*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_ENABLE_SVG)
1616*c8dee2aaSAndroid Build Coastguard Worker SkGraphics::SetOpenTypeSVGDecoderFactory(SkSVGOpenTypeSVGDecoder::Make);
1617*c8dee2aaSAndroid Build Coastguard Worker #endif
1618*c8dee2aaSAndroid Build Coastguard Worker SkTaskGroup::Enabler enabled(FLAGS_threads);
1619*c8dee2aaSAndroid Build Coastguard Worker CodecUtils::RegisterAllAvailable();
1620*c8dee2aaSAndroid Build Coastguard Worker
1621*c8dee2aaSAndroid Build Coastguard Worker if (nullptr == GetResourceAsData("images/color_wheel.png")) {
1622*c8dee2aaSAndroid Build Coastguard Worker info("Some resources are missing. Do you need to set --resourcePath?\n");
1623*c8dee2aaSAndroid Build Coastguard Worker }
1624*c8dee2aaSAndroid Build Coastguard Worker gather_gold();
1625*c8dee2aaSAndroid Build Coastguard Worker gather_uninteresting_hashes();
1626*c8dee2aaSAndroid Build Coastguard Worker
1627*c8dee2aaSAndroid Build Coastguard Worker if (!gather_srcs()) {
1628*c8dee2aaSAndroid Build Coastguard Worker return 1;
1629*c8dee2aaSAndroid Build Coastguard Worker }
1630*c8dee2aaSAndroid Build Coastguard Worker bool defaultConfigs = true;
1631*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < argc; i++) {
1632*c8dee2aaSAndroid Build Coastguard Worker if (strcmp(argv[i], "--config") == 0) {
1633*c8dee2aaSAndroid Build Coastguard Worker defaultConfigs = false;
1634*c8dee2aaSAndroid Build Coastguard Worker break;
1635*c8dee2aaSAndroid Build Coastguard Worker }
1636*c8dee2aaSAndroid Build Coastguard Worker }
1637*c8dee2aaSAndroid Build Coastguard Worker if (!gather_sinks(grCtxOptions,
1638*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_GRAPHITE)
1639*c8dee2aaSAndroid Build Coastguard Worker graphiteOptions,
1640*c8dee2aaSAndroid Build Coastguard Worker #endif
1641*c8dee2aaSAndroid Build Coastguard Worker defaultConfigs)) {
1642*c8dee2aaSAndroid Build Coastguard Worker return 1;
1643*c8dee2aaSAndroid Build Coastguard Worker }
1644*c8dee2aaSAndroid Build Coastguard Worker
1645*c8dee2aaSAndroid Build Coastguard Worker const int testCount = gather_tests();
1646*c8dee2aaSAndroid Build Coastguard Worker gPending = gSrcs->size() * gSinks->size() + testCount;
1647*c8dee2aaSAndroid Build Coastguard Worker gTotalCounts = gPending;
1648*c8dee2aaSAndroid Build Coastguard Worker gLastUpdate = SkTime::GetNSecs();
1649*c8dee2aaSAndroid Build Coastguard Worker info("%d srcs * %d sinks + %d tests == %d tasks\n",
1650*c8dee2aaSAndroid Build Coastguard Worker gSrcs->size(), gSinks->size(), testCount,
1651*c8dee2aaSAndroid Build Coastguard Worker gPending);
1652*c8dee2aaSAndroid Build Coastguard Worker
1653*c8dee2aaSAndroid Build Coastguard Worker #if !defined(SK_DISABLE_LEGACY_TESTS)
1654*c8dee2aaSAndroid Build Coastguard Worker // Kick off as much parallel work as we can, making note of any serial work we'll need to do.
1655*c8dee2aaSAndroid Build Coastguard Worker // However, execute all CPU-serial tests first so that they don't have races with parallel tests
1656*c8dee2aaSAndroid Build Coastguard Worker for (skiatest::Test& test : *gCPUSerialTests) { run_cpu_test(test); }
1657*c8dee2aaSAndroid Build Coastguard Worker #endif
1658*c8dee2aaSAndroid Build Coastguard Worker
1659*c8dee2aaSAndroid Build Coastguard Worker SkTaskGroup parallel;
1660*c8dee2aaSAndroid Build Coastguard Worker TArray<Task> serial;
1661*c8dee2aaSAndroid Build Coastguard Worker
1662*c8dee2aaSAndroid Build Coastguard Worker for (TaggedSink& sink : *gSinks) {
1663*c8dee2aaSAndroid Build Coastguard Worker for (TaggedSrc& src : *gSrcs) {
1664*c8dee2aaSAndroid Build Coastguard Worker if (src->veto(sink->flags()) ||
1665*c8dee2aaSAndroid Build Coastguard Worker should_skip(sink.tag.c_str(), src.tag.c_str(),
1666*c8dee2aaSAndroid Build Coastguard Worker src.options.c_str(), src->name().c_str())) {
1667*c8dee2aaSAndroid Build Coastguard Worker SkAutoSpinlock lock(gMutex);
1668*c8dee2aaSAndroid Build Coastguard Worker gPending--;
1669*c8dee2aaSAndroid Build Coastguard Worker continue;
1670*c8dee2aaSAndroid Build Coastguard Worker }
1671*c8dee2aaSAndroid Build Coastguard Worker
1672*c8dee2aaSAndroid Build Coastguard Worker Task task(src, sink);
1673*c8dee2aaSAndroid Build Coastguard Worker if (src->serial() || sink->serial()) {
1674*c8dee2aaSAndroid Build Coastguard Worker serial.push_back(task);
1675*c8dee2aaSAndroid Build Coastguard Worker } else {
1676*c8dee2aaSAndroid Build Coastguard Worker parallel.add([task] { Task::Run(task); });
1677*c8dee2aaSAndroid Build Coastguard Worker }
1678*c8dee2aaSAndroid Build Coastguard Worker }
1679*c8dee2aaSAndroid Build Coastguard Worker }
1680*c8dee2aaSAndroid Build Coastguard Worker
1681*c8dee2aaSAndroid Build Coastguard Worker #if !defined(SK_DISABLE_LEGACY_TESTS)
1682*c8dee2aaSAndroid Build Coastguard Worker for (skiatest::Test& test : *gCPUTests) {
1683*c8dee2aaSAndroid Build Coastguard Worker parallel.add([test] { run_cpu_test(test); });
1684*c8dee2aaSAndroid Build Coastguard Worker }
1685*c8dee2aaSAndroid Build Coastguard Worker #endif // !SK_DISABLE_LEGACY_TESTS
1686*c8dee2aaSAndroid Build Coastguard Worker
1687*c8dee2aaSAndroid Build Coastguard Worker // With the parallel work running, run serial tasks and tests here on main thread.
1688*c8dee2aaSAndroid Build Coastguard Worker for (Task& task : serial) { Task::Run(task); }
1689*c8dee2aaSAndroid Build Coastguard Worker
1690*c8dee2aaSAndroid Build Coastguard Worker #if !defined(SK_DISABLE_LEGACY_TESTS)
1691*c8dee2aaSAndroid Build Coastguard Worker for (skiatest::Test& test : *gGaneshTests) { run_ganesh_test(test, grCtxOptions); }
1692*c8dee2aaSAndroid Build Coastguard Worker
1693*c8dee2aaSAndroid Build Coastguard Worker #if defined(SK_GRAPHITE)
1694*c8dee2aaSAndroid Build Coastguard Worker for (skiatest::Test& test : *gGraphiteTests) { run_graphite_test(test, graphiteOptions); }
1695*c8dee2aaSAndroid Build Coastguard Worker #endif
1696*c8dee2aaSAndroid Build Coastguard Worker #endif // !SK_DISABLE_LEGACY_TESTS
1697*c8dee2aaSAndroid Build Coastguard Worker
1698*c8dee2aaSAndroid Build Coastguard Worker // Wait for any remaining parallel work to complete (including any spun off of serial tasks).
1699*c8dee2aaSAndroid Build Coastguard Worker parallel.wait();
1700*c8dee2aaSAndroid Build Coastguard Worker gDefinitelyThreadSafeWork->wait();
1701*c8dee2aaSAndroid Build Coastguard Worker
1702*c8dee2aaSAndroid Build Coastguard Worker // At this point we're back in single-threaded land.
1703*c8dee2aaSAndroid Build Coastguard Worker
1704*c8dee2aaSAndroid Build Coastguard Worker // We'd better have run everything.
1705*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(gPending == 0);
1706*c8dee2aaSAndroid Build Coastguard Worker // Make sure we've flushed all our results to disk.
1707*c8dee2aaSAndroid Build Coastguard Worker dump_json();
1708*c8dee2aaSAndroid Build Coastguard Worker
1709*c8dee2aaSAndroid Build Coastguard Worker if (!gFailures->empty()) {
1710*c8dee2aaSAndroid Build Coastguard Worker info("Failures:\n");
1711*c8dee2aaSAndroid Build Coastguard Worker for (const SkString& fail : *gFailures) {
1712*c8dee2aaSAndroid Build Coastguard Worker info("\t%s\n", fail.c_str());
1713*c8dee2aaSAndroid Build Coastguard Worker }
1714*c8dee2aaSAndroid Build Coastguard Worker info("%d failures\n", gFailures->size());
1715*c8dee2aaSAndroid Build Coastguard Worker return 1;
1716*c8dee2aaSAndroid Build Coastguard Worker }
1717*c8dee2aaSAndroid Build Coastguard Worker
1718*c8dee2aaSAndroid Build Coastguard Worker SkGraphics::PurgeAllCaches();
1719*c8dee2aaSAndroid Build Coastguard Worker info("Finished!\n");
1720*c8dee2aaSAndroid Build Coastguard Worker
1721*c8dee2aaSAndroid Build Coastguard Worker return 0;
1722*c8dee2aaSAndroid Build Coastguard Worker }
1723