Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(4)

Side by Side Diff: dm/DM.cpp

Issue 853883004: Revert of Sketch DM refactor. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « bench/nanobench.cpp ('k') | dm/DMCpuGMTask.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Main binary for DM.
2 // For a high-level overview, please see dm/README.
3
1 #include "CrashHandler.h" 4 #include "CrashHandler.h"
2 #include "DMJsonWriter.h" 5 #include "LazyDecodeBitmap.h"
3 #include "DMSrcSink.h"
4 #include "OverwriteLine.h"
5 #include "ProcStats.h"
6 #include "SkBBHFactory.h"
7 #include "SkCommonFlags.h" 6 #include "SkCommonFlags.h"
8 #include "SkForceLinking.h" 7 #include "SkForceLinking.h"
9 #include "SkGraphics.h" 8 #include "SkGraphics.h"
10 #include "SkMD5.h"
11 #include "SkOSFile.h" 9 #include "SkOSFile.h"
10 #include "SkPicture.h"
11 #include "SkString.h"
12 #include "SkTaskGroup.h" 12 #include "SkTaskGroup.h"
13 #include "Test.h" 13 #include "Test.h"
14 #include "Timer.h" 14 #include "gm.h"
15 15 #include "sk_tool_utils.h"
16 #include "sk_tool_utils_flags.h"
17
18 #include "DMCpuGMTask.h"
19 #include "DMGpuGMTask.h"
20 #include "DMGpuSupport.h"
21 #include "DMImageTask.h"
22 #include "DMJsonWriter.h"
23 #include "DMPDFTask.h"
24 #include "DMPDFRasterizeTask.h"
25 #include "DMReporter.h"
26 #include "DMSKPTask.h"
27 #include "DMTask.h"
28 #include "DMTaskRunner.h"
29 #include "DMTestTask.h"
30
31 #ifdef SK_BUILD_POPPLER
32 # include "SkPDFRasterizer.h"
33 # define RASTERIZE_PDF_PROC SkPopplerRasterizePDF
34 #elif defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS)
35 # include "SkCGUtils.h"
36 # define RASTERIZE_PDF_PROC SkPDFDocumentToBitmap
37 #else
38 # define RASTERIZE_PDF_PROC NULL
39 #endif
40
41 #include <ctype.h>
42
43 using skiagm::GM;
44 using skiagm::GMRegistry;
45 using skiatest::Test;
46 using skiatest::TestRegistry;
47
48 static const char kGpuAPINameGL[] = "gl";
49 static const char kGpuAPINameGLES[] = "gles";
50
51 DEFINE_bool(gms, true, "Run GMs?");
16 DEFINE_bool(tests, true, "Run tests?"); 52 DEFINE_bool(tests, true, "Run tests?");
17 DEFINE_string(images, "resources", "Images to decode."); 53 DEFINE_bool(reportUsedChars, false, "Output test font construction data to be pa sted into"
18 DEFINE_string(src, "gm skp image subset", "Source types to test."); 54 " create_test_font.cpp.");
19 DEFINE_bool(nameByHash, false, 55 DEFINE_string(images, "resources", "Path to directory containing images to decod e.");
20 "If true, write to FLAGS_writePath[0]/<hash>.png instead of " 56 DEFINE_bool(rasterPDF, true, "Rasterize PDFs?");
21 "to FLAGS_writePath[0]/<config>/<sourceType>/<name>.png");
22 DEFINE_bool2(pathOpsExtended, x, false, "Run extended pathOps tests.");
23 DEFINE_string(matrix, "1 0 0 0 1 0 0 0 1",
24 "Matrix to apply when using 'matrix' in config.");
25 57
26 __SK_FORCE_IMAGE_DECODER_LINKING; 58 __SK_FORCE_IMAGE_DECODER_LINKING;
27 using namespace DM; 59
28 60 static DM::RasterizePdfProc get_pdf_rasterizer_proc() {
29 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~*/ 61 return reinterpret_cast<DM::RasterizePdfProc>(
30 62 FLAGS_rasterPDF ? RASTERIZE_PDF_PROC : NULL);
31 static int gPending = 0, gFailures = 0; 63 }
32 64
33 static void fail(ImplicitString err) { 65 // "FooBar" -> "foobar". Obviously, ASCII only.
34 SkDebugf("\n\nERROR: %s\n\n", err.c_str()); 66 static SkString lowercase(SkString s) {
35 sk_atomic_inc(&gFailures); 67 for (size_t i = 0; i < s.size(); i++) {
36 } 68 s[i] = tolower(s[i]);
37 69 }
38 static void done(double ms, ImplicitString config, ImplicitString src, ImplicitS tring name) { 70 return s;
39 SkDebugf("%s(%4dMB %5d) %s\t%s %s %s ", FLAGS_verbose ? "\n" : kSkOverwrite Line 71 }
40 , sk_tools::getMaxResidentSetSizeMB() 72
41 , sk_atomic_dec(&gPending)-1 73 static const GrContextFactory::GLContextType native = GrContextFactory::kNative_ GLContextType;
42 , HumanizeMs(ms).c_str() 74 static const GrContextFactory::GLContextType nvpr = GrContextFactory::kNVPR_GL ContextType;
43 , config.c_str() 75 static const GrContextFactory::GLContextType null = GrContextFactory::kNull_GL ContextType;
44 , src.c_str() 76 static const GrContextFactory::GLContextType debug = GrContextFactory::kDebug_G LContextType;
45 , name.c_str()); 77 #if SK_ANGLE
46 } 78 static const GrContextFactory::GLContextType angle = GrContextFactory::kANGLE_G LContextType;
47 79 #endif
48 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~*/ 80 #if SK_MESA
49 81 static const GrContextFactory::GLContextType mesa = GrContextFactory::kMESA_GL ContextType;
50 template <typename T> 82 #endif
51 struct Tagged : public SkAutoTDelete<T> { const char* tag; }; 83
52 84 static void kick_off_gms(const SkTDArray<GMRegistry::Factory>& gms,
53 static const bool kMemcpyOK = true; 85 const SkTArray<SkString>& configs,
54 86 GrGLStandard gpuAPI,
55 static SkTArray<Tagged<Src>, kMemcpyOK> gSrcs; 87 DM::Reporter* reporter,
56 static SkTArray<Tagged<Sink>, kMemcpyOK> gSinks; 88 DM::TaskRunner* tasks) {
57 89 #define START(name, type, ...) \
58 static void push_src(const char* tag, Src* s) { 90 if (lowercase(configs[j]).equals(name)) { \
59 SkAutoTDelete<Src> src(s); 91 tasks->add(SkNEW_ARGS(DM::type, (name, reporter, tasks, gms[i], ## __VA_ ARGS__))); \
60 if (FLAGS_src.contains(tag) && 92 }
61 !SkCommandLineFlags::ShouldSkip(FLAGS_match, src->name().c_str())) { 93 for (int i = 0; i < gms.count(); i++) {
62 Tagged<Src>& s = gSrcs.push_back(); 94 for (int j = 0; j < configs.count(); j++) {
63 s.reset(src.detach()); 95
64 s.tag = tag; 96 START("565", CpuGMTask, kRGB_565_SkColorType);
65 } 97 START("8888", CpuGMTask, kN32_SkColorType);
66 } 98 START("gpu", GpuGMTask, native, gpuAPI, 0, false);
67 99 START("msaa4", GpuGMTask, native, gpuAPI, 4, false);
68 static void gather_srcs() { 100 START("msaa16", GpuGMTask, native, gpuAPI, 16, false);
69 for (const skiagm::GMRegistry* r = skiagm::GMRegistry::Head(); r; r = r->nex t()) { 101 START("nvprmsaa4", GpuGMTask, nvpr, gpuAPI, 4, false);
70 push_src("gm", new GMSrc(r->factory())); 102 START("nvprmsaa16", GpuGMTask, nvpr, gpuAPI, 16, false);
71 } 103 START("gpudft", GpuGMTask, native, gpuAPI, 0, true);
72 if (!FLAGS_skps.isEmpty()) { 104 START("gpunull", GpuGMTask, null, gpuAPI, 0, false);
73 SkOSFile::Iter it(FLAGS_skps[0], "skp"); 105 START("gpudebug", GpuGMTask, debug, gpuAPI, 0, false);
74 for (SkString file; it.next(&file); ) { 106 #if SK_ANGLE
75 push_src("skp", new SKPSrc(SkOSPath::Join(FLAGS_skps[0], file.c_str( )))); 107 START("angle", GpuGMTask, angle, gpuAPI, 0, false);
76 } 108 #endif
77 } 109 #if SK_MESA
78 if (!FLAGS_images.isEmpty()) { 110 START("mesa", GpuGMTask, mesa, gpuAPI, 0, false);
79 const char* exts[] = { 111 #endif
80 "bmp", "gif", "jpg", "jpeg", "png", "webp", "ktx", "astc", "wbmp", " ico", 112 START("pdf", PDFTask, get_pdf_rasterizer_proc());
81 "BMP", "GIF", "JPG", "JPEG", "PNG", "WEBP", "KTX", "ASTC", "WBMP", " ICO", 113 }
82 }; 114 }
83 for (size_t i = 0; i < SK_ARRAY_COUNT(exts); i++) { 115 #undef START
84 SkOSFile::Iter it(FLAGS_images[0], exts[i]); 116 }
85 for (SkString file; it.next(&file); ) { 117
86 SkString path = SkOSPath::Join(FLAGS_images[0], file.c_str()); 118 static void kick_off_tests(const SkTDArray<TestRegistry::Factory>& tests,
87 push_src("image", new ImageSrc(path)); // Decode entire ima ge. 119 DM::Reporter* reporter,
88 push_src("subset", new ImageSrc(path, 5)); // Decode 5 random s ubsets. 120 DM::TaskRunner* tasks) {
121 for (int i = 0; i < tests.count(); i++) {
122 SkAutoTDelete<Test> test(tests[i](NULL));
123 if (test->isGPUTest()) {
124 tasks->add(SkNEW_ARGS(DM::GpuTestTask, (reporter, tasks, tests[i]))) ;
125 } else {
126 tasks->add(SkNEW_ARGS(DM::CpuTestTask, (reporter, tasks, tests[i]))) ;
127 }
128 }
129 }
130
131 static void find_files(const char* dir,
132 const char* suffixes[],
133 size_t num_suffixes,
134 SkTArray<SkString>* files) {
135 if (0 == strcmp(dir, "")) {
136 return;
137 }
138
139 SkString filename;
140 for (size_t i = 0; i < num_suffixes; i++) {
141 SkOSFile::Iter it(dir, suffixes[i]);
142 while (it.next(&filename)) {
143 if (!SkCommandLineFlags::ShouldSkip(FLAGS_match, filename.c_str())) {
144 files->push_back(SkOSPath::Join(dir, filename.c_str()));
89 } 145 }
90 } 146 }
91 } 147 }
92 } 148 }
93 149
94 static GrGLStandard get_gpu_api() { 150 static void kick_off_skps(const SkTArray<SkString>& skps,
95 if (FLAGS_gpuAPI.contains("gl")) { return kGL_GrGLStandard; } 151 DM::Reporter* reporter,
96 if (FLAGS_gpuAPI.contains("gles")) { return kGLES_GrGLStandard; } 152 DM::TaskRunner* tasks) {
97 return kNone_GrGLStandard; 153 for (int i = 0; i < skps.count(); ++i) {
98 } 154 SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(skps[i].c_str()));
99 155 if (stream.get() == NULL) {
100 static void push_sink(const char* tag, Sink* s) { 156 SkDebugf("Could not read %s.\n", skps[i].c_str());
101 SkAutoTDelete<Sink> sink(s); 157 exit(1);
102 if (!FLAGS_config.contains(tag)) { 158 }
159 SkAutoTUnref<SkPicture> pic(
160 SkPicture::CreateFromStream(stream.get(), &sk_tools::LazyDecodeB itmap));
161 if (pic.get() == NULL) {
162 SkDebugf("Could not read %s as an SkPicture.\n", skps[i].c_str());
163 exit(1);
164 }
165
166 SkString filename = SkOSPath::Basename(skps[i].c_str());
167 tasks->add(SkNEW_ARGS(DM::SKPTask, (reporter, tasks, pic, filename)));
168 tasks->add(SkNEW_ARGS(DM::PDFTask, (reporter, tasks, pic, filename,
169 get_pdf_rasterizer_proc())));
170 }
171 }
172
173 static void kick_off_images(const SkTArray<SkString>& images,
174 DM::Reporter* reporter,
175 DM::TaskRunner* tasks) {
176 for (int i = 0; i < images.count(); i++) {
177 SkAutoTUnref<SkData> image(SkData::NewFromFileName(images[i].c_str()));
178 if (!image) {
179 SkDebugf("Could not read %s.\n", images[i].c_str());
180 exit(1);
181 }
182 SkString filename = SkOSPath::Basename(images[i].c_str());
183 tasks->add(SkNEW_ARGS(DM::ImageTask, (reporter, tasks, image, filename)) );
184 tasks->add(SkNEW_ARGS(DM::ImageTask, (reporter, tasks, image, filename, 5/*subsets*/)));
185 }
186 }
187
188
189 static void report_failures(const SkTArray<SkString>& failures) {
190 if (failures.count() == 0) {
103 return; 191 return;
104 } 192 }
105 // Try a noop Src as a canary. If it fails, skip this sink. 193
106 struct : public Src { 194 SkDebugf("Failures:\n");
107 Error draw(SkCanvas*) const SK_OVERRIDE { return ""; } 195 for (int i = 0; i < failures.count(); i++) {
108 SkISize size() const SK_OVERRIDE { return SkISize::Make(16, 16); } 196 SkDebugf(" %s\n", failures[i].c_str());
109 Name name() const SK_OVERRIDE { return "noop"; } 197 }
110 } noop; 198 SkDebugf("%d failures.\n", failures.count());
111 199 }
112 SkBitmap bitmap; 200
113 SkDynamicMemoryWStream stream; 201 static GrGLStandard get_gl_standard() {
114 Error err = sink->draw(noop, &bitmap, &stream); 202 if (FLAGS_gpuAPI.contains(kGpuAPINameGL)) {
115 if (!err.isEmpty()) { 203 return kGL_GrGLStandard;
116 SkDebugf("Skipping %s: %s\n", tag, err.c_str()); 204 }
117 return; 205 if (FLAGS_gpuAPI.contains(kGpuAPINameGLES)) {
118 } 206 return kGLES_GrGLStandard;
119 207 }
120 Tagged<Sink>& ts = gSinks.push_back(); 208 return kNone_GrGLStandard;
121 ts.reset(sink.detach()); 209 }
122 ts.tag = tag; 210
123 } 211 template <typename T, typename Registry>
124 212 static void append_matching_factories(Registry* head, SkTDArray<typename Registr y::Factory>* out) {
125 static bool gpu_supported() { 213 for (const Registry* reg = head; reg != NULL; reg = reg->next()) {
126 #if SK_SUPPORT_GPU 214 SkAutoTDelete<T> forName(reg->factory()(NULL));
127 return FLAGS_gpu; 215 if (!SkCommandLineFlags::ShouldSkip(FLAGS_match, forName->getName())) {
128 #else 216 *out->append() = reg->factory();
129 return false; 217 }
130 #endif 218 }
131 } 219 }
132
133 static Sink* create_sink(const char* tag) {
134 #define SINK(t, sink, ...) if (0 == strcmp(t, tag)) { return new sink(__VA_ARGS_ _); }
135 if (gpu_supported()) {
136 const GrGLStandard api = get_gpu_api();
137 SINK("gpunull", GPUSink, GrContextFactory::kNull_GLContextType, api , 0, false);
138 SINK("gpudebug", GPUSink, GrContextFactory::kDebug_GLContextType, api , 0, false);
139 SINK("gpu", GPUSink, GrContextFactory::kNative_GLContextType, api , 0, false);
140 SINK("gpudft", GPUSink, GrContextFactory::kNative_GLContextType, api , 0, true);
141 SINK("msaa4", GPUSink, GrContextFactory::kNative_GLContextType, api , 4, false);
142 SINK("msaa16", GPUSink, GrContextFactory::kNative_GLContextType, api , 16, false);
143 SINK("nvprmsaa4", GPUSink, GrContextFactory::kNVPR_GLContextType, api , 4, false);
144 SINK("nvprmsaa16", GPUSink, GrContextFactory::kNVPR_GLContextType, api , 16, false);
145 #if SK_ANGLE
146 SINK("angle", GPUSink, GrContextFactory::kANGLE_GLContextType, api , 0, false);
147 #endif
148 #if SK_MESA
149 SINK("mesa", GPUSink, GrContextFactory::kMESA_GLContextType, api , 0, false);
150 #endif
151 }
152
153 if (FLAGS_cpu) {
154 SINK("565", RasterSink, kRGB_565_SkColorType);
155 SINK("8888", RasterSink, kN32_SkColorType);
156 // TODO(mtklein): reenable once skiagold can handle .pdf uploads.
157 //SINK("pdf", PDFSink);
158 }
159 #undef SINK
160 return NULL;
161 }
162
163 static Sink* create_via(const char* tag, Sink* wrapped) {
164 #define VIA(t, via, ...) if (0 == strcmp(t, tag)) { return new via(__VA_ARGS__); }
165 VIA("serialize", ViaSerialization, wrapped);
166
167 VIA("tiles", ViaTiles, 256, 256, NULL, wrapped);
168 VIA("tiles_rt", ViaTiles, 256, 256, new SkRTreeFactory, wrapped);
169
170 const int xp = SkGPipeWriter::kCrossProcess_Flag,
171 sa = xp | SkGPipeWriter::kSharedAddressSpace_Flag;
172 VIA("pipe", ViaPipe, 0, wrapped);
173 VIA("pipe_xp", ViaPipe, xp, wrapped);
174 VIA("pipe_sa", ViaPipe, sa, wrapped);
175
176 if (FLAGS_matrix.count() == 9) {
177 SkMatrix m;
178 for (int i = 0; i < 9; i++) {
179 m[i] = (SkScalar)atof(FLAGS_matrix[i]);
180 }
181 VIA("matrix", ViaMatrix, m, wrapped);
182 }
183 #undef VIA
184 return NULL;
185 }
186
187 static void gather_sinks() {
188 for (int i = 0; i < FLAGS_config.count(); i++) {
189 const char* config = FLAGS_config[i];
190 SkTArray<SkString> parts;
191 SkStrSplit(config, "-", &parts);
192
193 Sink* sink = NULL;
194 for (int i = parts.count(); i-- > 0;) {
195 const char* part = parts[i].c_str();
196 Sink* next = (sink == NULL) ? create_sink(part) : create_via(part, s ink);
197 if (next == NULL) {
198 SkDebugf("Skipping %s: Don't understand '%s'.\n", config, part);
199 delete sink;
200 sink = NULL;
201 break;
202 }
203 sink = next;
204 }
205 if (sink) {
206 push_sink(config, sink);
207 }
208 }
209 }
210
211 // The finest-grained unit of work we can run: draw a single Src into a single S ink,
212 // report any errors, and perhaps write out the output: a .png of the bitmap, or a raw stream.
213 struct Task {
214 Task(const Tagged<Src>& src, const Tagged<Sink>& sink) : src(src), sink(sink ) {}
215 const Tagged<Src>& src;
216 const Tagged<Sink>& sink;
217
218 static void Run(Task* task) {
219 WallTimer timer;
220 timer.start();
221 if (!FLAGS_dryRun) {
222 SkBitmap bitmap;
223 SkDynamicMemoryWStream stream;
224 Error err = task->sink->draw(*task->src, &bitmap, &stream);
225 if (!err.isEmpty()) {
226 fail(SkStringPrintf("%s %s %s: %s",
227 task->sink.tag,
228 task->src.tag,
229 task->src->name().c_str(),
230 err.c_str()));
231 }
232 if (!FLAGS_writePath.isEmpty()) {
233 const char* ext = task->sink->fileExtension();
234 if (stream.bytesWritten() == 0) {
235 SkMemoryStream pixels(bitmap.getPixels(), bitmap.getSize());
236 WriteToDisk(*task, &pixels, bitmap.getSize(), &bitmap, ext);
237 } else {
238 SkAutoTDelete<SkStreamAsset> data(stream.detachAsStream());
239 WriteToDisk(*task, data, data->getLength(), NULL, ext);
240 }
241 }
242 }
243 timer.end();
244 done(timer.fWall, task->sink.tag, task->src.tag, task->src->name());
245 }
246
247 static void WriteToDisk(const Task& task,
248 SkStream* data, size_t len,
249 const SkBitmap* bitmap,
250 const char* ext) {
251 SkMD5 hash;
252 hash.writeStream(data, len);
253 SkMD5::Digest digest;
254 hash.finish(digest);
255
256 JsonWriter::BitmapResult result;
257 result.name = task.src->name();
258 result.config = task.sink.tag;
259 result.sourceType = task.src.tag;
260 result.ext = ext;
261 for (int i = 0; i < 16; i++) {
262 result.md5.appendf("%02x", digest.data[i]);
263 }
264 JsonWriter::AddBitmapResult(result);
265
266 const char* dir = FLAGS_writePath[0];
267 if (0 == strcmp(dir, "@")) { // Needed for iOS.
268 dir = FLAGS_resourcePath[0];
269 }
270 sk_mkdir(dir);
271
272 SkString path;
273 if (FLAGS_nameByHash) {
274 path = SkOSPath::Join(dir, result.md5.c_str());
275 path.append(".");
276 path.append(ext);
277 if (sk_exists(path.c_str())) {
278 return; // Content-addressed. If it exists already, we're done .
279 }
280 } else {
281 path = SkOSPath::Join(dir, task.sink.tag);
282 sk_mkdir(path.c_str());
283 path = SkOSPath::Join(path.c_str(), task.src.tag);
284 sk_mkdir(path.c_str());
285 path = SkOSPath::Join(path.c_str(), task.src->name().c_str());
286 path.append(".");
287 path.append(ext);
288 }
289
290 SkFILEWStream file(path.c_str());
291 if (!file.isValid()) {
292 fail(SkStringPrintf("Can't open %s for writing.\n", path.c_str()));
293 return;
294 }
295
296 data->rewind();
297 if (bitmap) {
298 // We can't encode A8 bitmaps as PNGs. Convert them to 8888 first.
299 SkBitmap converted;
300 if (bitmap->info().colorType() == kAlpha_8_SkColorType) {
301 if (!bitmap->copyTo(&converted, kN32_SkColorType)) {
302 fail("Can't convert A8 to 8888.\n");
303 return;
304 }
305 bitmap = &converted;
306 }
307 if (!SkImageEncoder::EncodeStream(&file, *bitmap, SkImageEncoder::kP NG_Type, 100)) {
308 fail(SkStringPrintf("Can't encode PNG to %s.\n", path.c_str()));
309 return;
310 }
311 } else {
312 if (!file.writeStream(data, len)) {
313 fail(SkStringPrintf("Can't write to %s.\n", path.c_str()));
314 return;
315 }
316 }
317 }
318 };
319
320 // Run all tasks in the same enclave serially on the same thread.
321 // They can't possibly run concurrently with each other.
322 static void run_enclave(SkTArray<Task>* tasks) {
323 for (int i = 0; i < tasks->count(); i++) {
324 Task::Run(tasks->begin() + i);
325 }
326 }
327
328 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~*/
329
330 // Unit tests don't fit so well into the Src/Sink model, so we give them special treatment.
331
332 static struct : public skiatest::Reporter {
333 void onReportFailed(const skiatest::Failure& failure) SK_OVERRIDE {
334 SkString s;
335 failure.getFailureString(&s);
336 fail(s);
337 JsonWriter::AddTestFailure(failure);
338 }
339 bool allowExtendedTest() const SK_OVERRIDE { return FLAGS_pathOpsExtended; }
340 bool verbose() const SK_OVERRIDE { return FLAGS_veryVerbose; }
341 } gTestReporter;
342
343 static SkTArray<SkAutoTDelete<skiatest::Test>, kMemcpyOK> gTests;
344
345 static void gather_tests() {
346 if (!FLAGS_tests) {
347 return;
348 }
349 for (const skiatest::TestRegistry* r = skiatest::TestRegistry::Head(); r; r = r->next()) {
350 SkAutoTDelete<skiatest::Test> test(r->factory()(NULL));
351 if (SkCommandLineFlags::ShouldSkip(FLAGS_match, test->getName())) {
352 continue;
353 }
354 if (test->isGPUTest() && !gpu_supported()) {
355 continue;
356 }
357 if (!test->isGPUTest() && !FLAGS_cpu) {
358 continue;
359 }
360 test->setReporter(&gTestReporter);
361 gTests.push_back().reset(test.detach());
362 }
363 }
364
365 static void run_test(SkAutoTDelete<skiatest::Test>* t) {
366 WallTimer timer;
367 timer.start();
368 skiatest::Test* test = t->get();
369 if (!FLAGS_dryRun) {
370 GrContextFactory grFactory;
371 test->setGrContextFactory(&grFactory);
372 test->run();
373 if (!test->passed()) {
374 fail(SkStringPrintf("test %s failed", test->getName()));
375 }
376 }
377 timer.end();
378 done(timer.fWall, "test", "", test->getName());
379 }
380
381 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~*/
382 220
383 int dm_main(); 221 int dm_main();
384 int dm_main() { 222 int dm_main() {
385 SetupCrashHandler(); 223 SetupCrashHandler();
386 SkAutoGraphics ag; 224 SkAutoGraphics ag;
387 SkTaskGroup::Enabler enabled(FLAGS_threads); 225 SkTaskGroup::Enabler enabled(FLAGS_threads);
388 226
389 gather_srcs(); 227 if (FLAGS_dryRun || FLAGS_veryVerbose) {
390 gather_sinks(); 228 FLAGS_verbose = true;
391 gather_tests(); 229 }
230 #if SK_ENABLE_INST_COUNT
231 gPrintInstCount = FLAGS_leaks;
232 #endif
392 233
393 gPending = gSrcs.count() * gSinks.count() + gTests.count(); 234 SkTArray<SkString> configs;
394 SkDebugf("%d srcs * %d sinks + %d tests == %d tasks\n", 235 for (int i = 0; i < FLAGS_config.count(); i++) {
395 gSrcs.count(), gSinks.count(), gTests.count(), gPending); 236 SkStrSplit(FLAGS_config[i], ", ", &configs);
396
397 // We try to exploit as much parallelism as is safe. Most Src/Sink pairs ru n on any thread,
398 // but Sinks that identify as part of a particular enclave run serially on a single thread.
399 // Tests run on any thread, with a separate GrContextFactory for each GPU te st.
400 SkTArray<Task> enclaves[kNumEnclaves];
401 for (int j = 0; j < gSinks.count(); j++) {
402 SkTArray<Task>& tasks = enclaves[gSinks[j]->enclave()];
403 for (int i = 0; i < gSrcs.count(); i++) {
404 tasks.push_back(Task(gSrcs[i], gSinks[j]));
405 }
406 } 237 }
407 238
408 SK_COMPILE_ASSERT(kAnyThread_Enclave == 0, AnyThreadZero); 239 GrGLStandard gpuAPI = get_gl_standard();
409 SkTaskGroup tg;
410 tg.batch( Task::Run, enclaves[0].begin(), enclaves[0].count());
411 tg.batch(run_enclave, enclaves+1, kNumEnclaves-1);
412 tg.batch( run_test, gTests.begin(), gTests.count());
413 tg.wait();
414 240
415 if (!FLAGS_verbose) { 241 SkTDArray<GMRegistry::Factory> gms;
416 SkDebugf("\n"); 242 if (FLAGS_gms) {
243 append_matching_factories<GM>(GMRegistry::Head(), &gms);
417 } 244 }
418 245
419 JsonWriter::DumpJson(); 246 SkTDArray<TestRegistry::Factory> tests;
420 return gPending == 0 && gFailures == 0 ? 0 : 1; 247 if (FLAGS_tests) {
248 append_matching_factories<Test>(TestRegistry::Head(), &tests);
249 }
250
251
252 SkTArray<SkString> skps;
253 if (!FLAGS_skps.isEmpty()) {
254 const char* suffixes[] = { "skp" };
255 find_files(FLAGS_skps[0], suffixes, SK_ARRAY_COUNT(suffixes), &skps);
256 }
257
258 SkTArray<SkString> images;
259 if (!FLAGS_images.isEmpty()) {
260 const char* suffixes[] = {
261 "bmp", "gif", "jpg", "jpeg", "png", "webp", "ktx", "astc", "wbmp", " ico",
262 "BMP", "GIF", "JPG", "JPEG", "PNG", "WEBP", "KTX", "ASTC", "WBMP", " ICO",
263 };
264 find_files(FLAGS_images[0], suffixes, SK_ARRAY_COUNT(suffixes), &images) ;
265 }
266
267 SkDebugf("%d GMs x %d configs, %d tests, %d pictures, %d images\n",
268 gms.count(), configs.count(), tests.count(), skps.count(), images.c ount());
269 DM::Reporter reporter;
270
271 DM::TaskRunner tasks;
272 kick_off_tests(tests, &reporter, &tasks);
273 kick_off_gms(gms, configs, gpuAPI, &reporter, &tasks);
274 kick_off_skps(skps, &reporter, &tasks);
275 kick_off_images(images, &reporter, &tasks);
276 tasks.wait();
277
278 DM::JsonWriter::DumpJson();
279
280 SkDebugf("\n");
281 #ifdef SK_DEBUG
282 if (FLAGS_portableFonts && FLAGS_reportUsedChars) {
283 sk_tool_utils::report_used_chars();
284 }
285 #endif
286
287 SkTArray<SkString> failures;
288 reporter.getFailures(&failures);
289 report_failures(failures);
290 return failures.count() > 0;
421 } 291 }
422 292
423 #if !defined(SK_BUILD_FOR_IOS) && !defined(SK_BUILD_FOR_NACL) 293 #if !defined(SK_BUILD_FOR_IOS) && !defined(SK_BUILD_FOR_NACL)
424 int main(int argc, char** argv) { 294 int main(int argc, char** argv) {
425 SkCommandLineFlags::Parse(argc, argv); 295 SkCommandLineFlags::Parse(argc, argv);
426 return dm_main(); 296 return dm_main();
427 } 297 }
428 #endif 298 #endif
OLDNEW
« no previous file with comments | « bench/nanobench.cpp ('k') | dm/DMCpuGMTask.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698