Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / third_party / skia / gm / gmmain.cpp
1 /*
2  * Copyright 2011 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7
8 /*
9  * Code for the "gm" (Golden Master) rendering comparison tool.
10  *
11  * If you make changes to this, re-run the self-tests at gm/tests/run.sh
12  * to make sure they still pass... you may need to change the expected
13  * results of the self-test.
14  */
15
16 #include "gm.h"
17 #include "gm_error.h"
18 #include "gm_expectations.h"
19 #include "system_preferences.h"
20 #include "CrashHandler.h"
21 #include "ProcStats.h"
22 #include "Resources.h"
23 #include "SamplePipeControllers.h"
24 #include "SkBitmap.h"
25 #include "SkColorPriv.h"
26 #include "SkCommandLineFlags.h"
27 #include "SkData.h"
28 #include "SkDeferredCanvas.h"
29 #include "SkDevice.h"
30 #include "SkDocument.h"
31 #include "SkDrawFilter.h"
32 #include "SkForceLinking.h"
33 #include "SkGPipe.h"
34 #include "SkGraphics.h"
35 #include "SkImageDecoder.h"
36 #include "SkImageEncoder.h"
37 #include "SkJSONCPP.h"
38 #include "SkOSFile.h"
39 #include "SkPDFRasterizer.h"
40 #include "SkPicture.h"
41 #include "SkPictureRecorder.h"
42 #include "SkRefCnt.h"
43 #include "SkScalar.h"
44 #include "SkStream.h"
45 #include "SkString.h"
46 #include "SkSurface.h"
47 #include "SkTArray.h"
48 #include "SkTDict.h"
49
50 #ifdef SK_DEBUG
51 static const bool kDebugOnly = true;
52 #define GR_DUMP_FONT_CACHE 0
53 #else
54 static const bool kDebugOnly = false;
55 #endif
56
57 __SK_FORCE_IMAGE_DECODER_LINKING;
58
59 #if SK_SUPPORT_GPU
60 #include "GrContextFactory.h"
61 #include "SkGpuDevice.h"
62 typedef GrContextFactory::GLContextType GLContextType;
63 #define DEFAULT_CACHE_VALUE -1
64 static int gGpuCacheSizeBytes;
65 static int gGpuCacheSizeCount;
66 #else
67 class GrContextFactory;
68 class GrContext;
69 class GrSurface;
70 typedef int GLContextType;
71 typedef int GrGLStandard;
72 #endif
73
74 #define DEBUGFAIL_SEE_STDERR SkDEBUGFAIL("see stderr for message")
75
76 DECLARE_bool(useDocumentInsteadOfDevice);
77
78 #ifdef SK_SUPPORT_PDF
79     #include "SkPDFDevice.h"
80     #include "SkPDFDocument.h"
81 #endif
82
83 // Until we resolve http://code.google.com/p/skia/issues/detail?id=455 ,
84 // stop writing out XPS-format image baselines in gm.
85 #undef SK_SUPPORT_XPS
86 #ifdef SK_SUPPORT_XPS
87     #include "SkXPSDevice.h"
88 #endif
89
90 #ifdef SK_BUILD_FOR_MAC
91     #include "SkCGUtils.h"
92 #endif
93
94 using namespace skiagm;
95
96 class Iter {
97 public:
98     Iter() {
99         this->reset();
100     }
101
102     void reset() {
103         fReg = GMRegistry::Head();
104     }
105
106     GM* next() {
107         if (fReg) {
108             GMRegistry::Factory fact = fReg->factory();
109             fReg = fReg->next();
110             return fact(0);
111         }
112         return NULL;
113     }
114
115     static int Count() {
116         const GMRegistry* reg = GMRegistry::Head();
117         int count = 0;
118         while (reg) {
119             count += 1;
120             reg = reg->next();
121         }
122         return count;
123     }
124
125 private:
126     const GMRegistry* fReg;
127 };
128
129 // TODO(epoger): Right now, various places in this code assume that all the
130 // image files read/written by GM use this file extension.
131 // Search for references to this constant to find these assumptions.
132 const static char kPNG_FileExtension[] = "png";
133
134 enum Backend {
135     kRaster_Backend,
136     kGPU_Backend,
137     kPDF_Backend,
138     kXPS_Backend,
139 };
140
141 enum BbhType {
142     kNone_BbhType,
143     kRTree_BbhType,
144     kTileGrid_BbhType,
145 };
146
147 enum ConfigFlags {
148     kNone_ConfigFlag  = 0x0,
149     /* Write GM images if a write path is provided. */
150     kWrite_ConfigFlag = 0x1,
151     /* Read reference GM images if a read path is provided. */
152     kRead_ConfigFlag  = 0x2,
153     kRW_ConfigFlag    = (kWrite_ConfigFlag | kRead_ConfigFlag),
154 };
155
156 struct ConfigData {
157     SkColorType                     fColorType;
158     Backend                         fBackend;
159     GLContextType                   fGLContextType; // GPU backend only
160     int                             fSampleCnt;     // GPU backend only
161     ConfigFlags                     fFlags;
162     const char*                     fName;
163     bool                            fRunByDefault;
164 };
165
166 struct PDFRasterizerData {
167     bool        (*fRasterizerFunction)(SkStream*, SkBitmap*);
168     const char* fName;
169     bool        fRunByDefault;
170 };
171
172 class BWTextDrawFilter : public SkDrawFilter {
173 public:
174     virtual bool filter(SkPaint*, Type) SK_OVERRIDE;
175 };
176 bool BWTextDrawFilter::filter(SkPaint* p, Type t) {
177     if (kText_Type == t) {
178         p->setAntiAlias(false);
179     }
180     return true;
181 }
182
183 struct PipeFlagComboData {
184     const char* name;
185     uint32_t flags;
186 };
187
188 static PipeFlagComboData gPipeWritingFlagCombos[] = {
189     { "", 0 },
190     { " cross-process", SkGPipeWriter::kCrossProcess_Flag },
191     { " cross-process, shared address", SkGPipeWriter::kCrossProcess_Flag
192         | SkGPipeWriter::kSharedAddressSpace_Flag }
193 };
194
195 static SkData* encode_to_dct_data(size_t* pixelRefOffset, const SkBitmap& bitmap);
196 DECLARE_int32(pdfRasterDpi);
197
198 const static ErrorCombination kDefaultIgnorableErrorTypes = ErrorCombination()
199     .plus(kMissingExpectations_ErrorType)
200     .plus(kIntentionallySkipped_ErrorType);
201
202 class GMMain {
203 public:
204     GMMain() : fUseFileHierarchy(false), fWriteChecksumBasedFilenames(false),
205                fIgnorableErrorTypes(kDefaultIgnorableErrorTypes),
206                fMismatchPath(NULL), fMissingExpectationsPath(NULL), fTestsRun(0),
207                fRenderModesEncountered(1) {}
208
209     /**
210      * Assemble shortNamePlusConfig from (surprise!) shortName and configName.
211      *
212      * The method for doing so depends on whether we are using hierarchical naming.
213      * For example, shortName "selftest1" and configName "8888" could be assembled into
214      * either "selftest1_8888" or "8888/selftest1".
215      */
216     SkString make_shortname_plus_config(const char *shortName, const char *configName) {
217         SkString name;
218         if (0 == strlen(configName)) {
219             name.append(shortName);
220         } else if (fUseFileHierarchy) {
221             name.appendf("%s%c%s", configName, SkPATH_SEPARATOR, shortName);
222         } else {
223             name.appendf("%s_%s", shortName, configName);
224         }
225         return name;
226     }
227
228     /**
229      * Assemble filename, suitable for writing out the results of a particular test.
230      */
231     SkString make_filename(const char *path,
232                            const char *shortName,
233                            const char *configName,
234                            const char *renderModeDescriptor,
235                            const char *suffix) {
236         SkString filename = make_shortname_plus_config(shortName, configName);
237         filename.append(renderModeDescriptor);
238         filename.appendUnichar('.');
239         filename.append(suffix);
240         return SkOSPath::Join(path, filename.c_str());
241     }
242
243     /**
244      * Assemble filename suitable for writing out an SkBitmap.
245      */
246     SkString make_bitmap_filename(const char *path,
247                                   const char *shortName,
248                                   const char *configName,
249                                   const char *renderModeDescriptor,
250                                   const GmResultDigest &bitmapDigest) {
251         if (fWriteChecksumBasedFilenames) {
252             SkString filename;
253             filename.append(bitmapDigest.getHashType());
254             filename.appendUnichar('_');
255             filename.append(shortName);
256             filename.appendUnichar('_');
257             filename.append(bitmapDigest.getDigestValue());
258             filename.appendUnichar('.');
259             filename.append(kPNG_FileExtension);
260             return SkOSPath::Join(path, filename.c_str());
261         } else {
262             return make_filename(path, shortName, configName, renderModeDescriptor,
263                                  kPNG_FileExtension);
264         }
265     }
266
267     /* since PNG insists on unpremultiplying our alpha, we take no
268        precision chances and force all pixels to be 100% opaque,
269        otherwise on compare we may not get a perfect match.
270     */
271     static void force_all_opaque(const SkBitmap& bitmap) {
272         SkColorType colorType = bitmap.colorType();
273         switch (colorType) {
274         case kN32_SkColorType:
275             force_all_opaque_8888(bitmap);
276             break;
277         case kRGB_565_SkColorType:
278             // nothing to do here; 565 bitmaps are inherently opaque
279             break;
280         default:
281             SkDebugf("unsupported bitmap colorType %d\n", colorType);
282             DEBUGFAIL_SEE_STDERR;
283         }
284     }
285
286     static void force_all_opaque_8888(const SkBitmap& bitmap) {
287         SkAutoLockPixels lock(bitmap);
288         for (int y = 0; y < bitmap.height(); y++) {
289             for (int x = 0; x < bitmap.width(); x++) {
290                 *bitmap.getAddr32(x, y) |= (SK_A32_MASK << SK_A32_SHIFT);
291             }
292         }
293     }
294
295     static ErrorCombination write_bitmap(const SkString& path, const SkBitmap& bitmap) {
296         // TODO(epoger): Now that we have removed force_all_opaque()
297         // from this method, we should be able to get rid of the
298         // transformation to 8888 format also.
299         SkBitmap copy;
300         bitmap.copyTo(&copy, kN32_SkColorType);
301         if (!SkImageEncoder::EncodeFile(path.c_str(), copy,
302                                         SkImageEncoder::kPNG_Type,
303                                         100)) {
304             SkDebugf("FAILED to write bitmap: %s\n", path.c_str());
305             return ErrorCombination(kWritingReferenceImage_ErrorType);
306         }
307         return kEmpty_ErrorCombination;
308     }
309
310     /**
311      * Add all render modes encountered thus far to the "modes" array.
312      */
313     void GetRenderModesEncountered(SkTArray<SkString> &modes) {
314         SkTDict<int>::Iter iter(this->fRenderModesEncountered);
315         const char* mode;
316         while ((mode = iter.next(NULL)) != NULL) {
317             SkString modeAsString = SkString(mode);
318             // TODO(epoger): It seems a bit silly that all of these modes were
319             // recorded with a leading "-" which we have to remove here
320             // (except for mode "", which means plain old original mode).
321             // But that's how renderModeDescriptor has been passed into
322             // compare_test_results_to_reference_bitmap() historically,
323             // and changing that now may affect other parts of our code.
324             if (modeAsString.startsWith("-")) {
325                 modeAsString.remove(0, 1);
326             }
327             modes.push_back(modeAsString);
328         }
329     }
330
331     /**
332      * Returns true if failures on this test should be ignored.
333      */
334     bool ShouldIgnoreTest(const char *name) const {
335         for (int i = 0; i < fIgnorableTestNames.count(); i++) {
336             if (fIgnorableTestNames[i].equals(name)) {
337                 return true;
338             }
339         }
340         return false;
341     }
342
343     /**
344      * Calls RecordTestResults to record that we skipped a test.
345      *
346      * Depending on the backend, this may mean that we skipped a single rendermode, or all
347      * rendermodes; see http://skbug.com/1994 and https://codereview.chromium.org/129203002/
348      */
349     void RecordSkippedTest(const SkString& shortNamePlusConfig,
350                            const char renderModeDescriptor [], Backend backend) {
351         if (kRaster_Backend == backend) {
352             // Skipping a test on kRaster_Backend means that we will skip ALL renderModes
353             // (as opposed to other backends, on which we only run the default renderMode).
354             //
355             // We cannot call RecordTestResults yet, because we won't know the full set of
356             // renderModes until we have run all tests.
357             fTestsSkippedOnAllRenderModes.push_back(shortNamePlusConfig);
358         } else {
359             this->RecordTestResults(kIntentionallySkipped_ErrorType, shortNamePlusConfig,
360                                     renderModeDescriptor);
361         }
362     }
363
364     /**
365      * Records the results of this test in fTestsRun and fFailedTests.
366      *
367      * We even record successes, and errors that we regard as
368      * "ignorable"; we can filter them out later.
369      */
370     void RecordTestResults(const ErrorCombination& errorCombination,
371                            const SkString& shortNamePlusConfig,
372                            const char renderModeDescriptor []) {
373         // Things to do regardless of errorCombination.
374         fTestsRun++;
375         int renderModeCount = 0;
376         this->fRenderModesEncountered.find(renderModeDescriptor, &renderModeCount);
377         renderModeCount++;
378         this->fRenderModesEncountered.set(renderModeDescriptor, renderModeCount);
379
380         if (errorCombination.isEmpty()) {
381             return;
382         }
383
384         // Things to do only if there is some error condition.
385         SkString fullName = shortNamePlusConfig;
386         fullName.append(renderModeDescriptor);
387         for (int typeInt = 0; typeInt <= kLast_ErrorType; typeInt++) {
388             ErrorType type = static_cast<ErrorType>(typeInt);
389             if (errorCombination.includes(type)) {
390                 fFailedTests[type].push_back(fullName);
391             }
392         }
393     }
394
395     /**
396      * Return the number of significant (non-ignorable) errors we have
397      * encountered so far.
398      */
399     int NumSignificantErrors() {
400         int significantErrors = 0;
401         for (int typeInt = 0; typeInt <= kLast_ErrorType; typeInt++) {
402             ErrorType type = static_cast<ErrorType>(typeInt);
403             if (!fIgnorableErrorTypes.includes(type)) {
404                 significantErrors += fFailedTests[type].count();
405             }
406         }
407         return significantErrors;
408     }
409
410     /**
411      * Display the summary of results with this ErrorType.
412      *
413      * @param type which ErrorType
414      * @param verbose whether to be all verbose about it
415      */
416     void DisplayResultTypeSummary(ErrorType type, bool verbose) {
417         bool isIgnorableType = fIgnorableErrorTypes.includes(type);
418
419         SkString line;
420         if (isIgnorableType) {
421             line.append("[ ] ");
422         } else {
423             line.append("[*] ");
424         }
425
426         SkTArray<SkString> *failedTestsOfThisType = &fFailedTests[type];
427         int count = failedTestsOfThisType->count();
428         line.appendf("%d %s", count, getErrorTypeName(type));
429         if (!isIgnorableType || verbose) {
430             line.append(":");
431             for (int i = 0; i < count; ++i) {
432                 line.append(" ");
433                 line.append((*failedTestsOfThisType)[i]);
434             }
435         }
436         SkDebugf("%s\n", line.c_str());
437     }
438
439     /**
440      * List contents of fFailedTests to stdout.
441      *
442      * @param verbose whether to be all verbose about it
443      */
444     void ListErrors(bool verbose) {
445         // First, print a single summary line.
446         SkString summary;
447         summary.appendf("Ran %d tests:", fTestsRun);
448         for (int typeInt = 0; typeInt <= kLast_ErrorType; typeInt++) {
449             ErrorType type = static_cast<ErrorType>(typeInt);
450             summary.appendf(" %s=%d", getErrorTypeName(type), fFailedTests[type].count());
451         }
452         SkDebugf("%s\n", summary.c_str());
453
454         // Now, for each failure type, list the tests that failed that way.
455         for (int typeInt = 0; typeInt <= kLast_ErrorType; typeInt++) {
456             this->DisplayResultTypeSummary(static_cast<ErrorType>(typeInt), verbose);
457         }
458         SkDebugf("(results marked with [*] will cause nonzero return value)\n");
459     }
460
461     static ErrorCombination write_document(const SkString& path, SkStreamAsset* asset) {
462         SkFILEWStream stream(path.c_str());
463         if (!stream.writeStream(asset, asset->getLength())) {
464             SkDebugf("FAILED to write document: %s\n", path.c_str());
465             return ErrorCombination(kWritingReferenceImage_ErrorType);
466         }
467         return kEmpty_ErrorCombination;
468     }
469
470     /**
471      * Prepare an SkBitmap to render a GM into.
472      *
473      * After you've rendered the GM into the SkBitmap, you must call
474      * complete_bitmap()!
475      *
476      * @todo thudson 22 April 2011 - could refactor this to take in
477      * a factory to generate the context, always call readPixels()
478      * (logically a noop for rasters, if wasted time), and thus collapse the
479      * GPU special case and also let this be used for SkPicture testing.
480      */
481     static void setup_bitmap(const ConfigData& gRec, SkISize& size,
482                              SkBitmap* bitmap) {
483         bitmap->allocPixels(SkImageInfo::Make(size.width(), size.height(),
484                                               gRec.fColorType, kPremul_SkAlphaType));
485         bitmap->eraseColor(SK_ColorTRANSPARENT);
486     }
487
488     /**
489      * Any finalization steps we need to perform on the SkBitmap after
490      * we have rendered the GM into it.
491      *
492      * It's too bad that we are throwing away alpha channel data
493      * we could otherwise be examining, but this had always been happening
494      * before... it was buried within the compare() method at
495      * https://code.google.com/p/skia/source/browse/trunk/gm/gmmain.cpp?r=7289#305 .
496      *
497      * Apparently we need this, at least for bitmaps that are either:
498      * (a) destined to be written out as PNG files, or
499      * (b) compared against bitmaps read in from PNG files
500      * for the reasons described just above the force_all_opaque() method.
501      *
502      * Neglecting to do this led to the difficult-to-diagnose
503      * http://code.google.com/p/skia/issues/detail?id=1079 ('gm generating
504      * spurious pixel_error messages as of r7258')
505      *
506      * TODO(epoger): Come up with a better solution that allows us to
507      * compare full pixel data, including alpha channel, while still being
508      * robust in the face of transformations to/from PNG files.
509      * Options include:
510      *
511      * 1. Continue to call force_all_opaque(), but ONLY for bitmaps that
512      *    will be written to, or compared against, PNG files.
513      *    PRO: Preserve/compare alpha channel info for the non-PNG cases
514      *         (comparing different renderModes in-memory)
515      *    CON: The bitmaps (and hash digests) for these non-PNG cases would be
516      *         different than those for the PNG-compared cases, and in the
517      *         case of a failed renderMode comparison, how would we write the
518      *         image to disk for examination?
519      *
520      * 2. Always compute image hash digests from PNG format (either
521      *    directly from the the bytes of a PNG file, or capturing the
522      *    bytes we would have written to disk if we were writing the
523      *    bitmap out as a PNG).
524      *    PRO: I think this would allow us to never force opaque, and to
525      *         the extent that alpha channel data can be preserved in a PNG
526      *         file, we could observe it.
527      *    CON: If we read a bitmap from disk, we need to take its hash digest
528      *         from the source PNG (we can't compute it from the bitmap we
529      *         read out of the PNG, because we will have already premultiplied
530      *         the alpha).
531      *    CON: Seems wasteful to convert a bitmap to PNG format just to take
532      *         its hash digest. (Although we're wasting lots of effort already
533      *         calling force_all_opaque().)
534      *
535      * 3. Make the alpha premultiply/unpremultiply routines 100% consistent,
536      *    so we can transform images back and forth without fear of off-by-one
537      *    errors.
538      *    CON: Math is hard.
539      *
540      * 4. Perform a "close enough" comparison of bitmaps (+/- 1 bit in each
541      *    channel), rather than demanding absolute equality.
542      *    CON: Can't do this with hash digests.
543      */
544     static void complete_bitmap(SkBitmap* bitmap) {
545         force_all_opaque(*bitmap);
546     }
547
548     static void installFilter(SkCanvas* canvas);
549
550     static void invokeGM(GM* gm, SkCanvas* canvas, bool isPDF, bool isDeferred) {
551         SkAutoCanvasRestore acr(canvas, true);
552
553         if (!isPDF) {
554             canvas->concat(gm->getInitialTransform());
555         }
556         installFilter(canvas);
557         gm->setCanvasIsDeferred(isDeferred);
558         gm->draw(canvas);
559         canvas->setDrawFilter(NULL);
560     }
561
562     static ErrorCombination generate_image(GM* gm, const ConfigData& gRec,
563                                            GrSurface* gpuTarget,
564                                            SkBitmap* bitmap,
565                                            bool deferred) {
566         SkISize size (gm->getISize());
567         setup_bitmap(gRec, size, bitmap);
568         const SkImageInfo info = bitmap->info();
569
570         SkAutoTUnref<SkSurface> surface;
571         SkAutoTUnref<SkCanvas> canvas;
572
573         if (gRec.fBackend == kRaster_Backend) {
574             surface.reset(SkSurface::NewRasterDirect(info,
575                                                      bitmap->getPixels(),
576                                                      bitmap->rowBytes()));
577             if (deferred) {
578                 canvas.reset(SkDeferredCanvas::Create(surface));
579             } else {
580                 canvas.reset(SkRef(surface->getCanvas()));
581             }
582             invokeGM(gm, canvas, false, deferred);
583             canvas->flush();
584         }
585 #if SK_SUPPORT_GPU
586         else {  // GPU
587             surface.reset(SkSurface::NewRenderTargetDirect(gpuTarget->asRenderTarget()));
588             if (deferred) {
589                 canvas.reset(SkDeferredCanvas::Create(surface));
590             } else {
591                 canvas.reset(SkRef(surface->getCanvas()));
592             }
593             invokeGM(gm, canvas, false, deferred);
594             // the device is as large as the current rendertarget, so
595             // we explicitly only readback the amount we expect (in
596             // size) overwrite our previous allocation
597             bitmap->setInfo(SkImageInfo::MakeN32Premul(size.fWidth, size.fHeight));
598             canvas->readPixels(bitmap, 0, 0);
599         }
600 #endif
601         complete_bitmap(bitmap);
602         return kEmpty_ErrorCombination;
603     }
604
605     static void generate_image_from_picture(GM* gm, const ConfigData& gRec,
606                                             SkPicture* pict, SkBitmap* bitmap,
607                                             SkScalar scale = SK_Scalar1,
608                                             bool tile = false) {
609         SkISize size = gm->getISize();
610         setup_bitmap(gRec, size, bitmap);
611
612         if (tile) {
613             // Generate the result image by rendering to tiles and accumulating
614             // the results in 'bitmap'
615
616             // This 16x16 tiling matches the settings applied to 'pict' in
617             // 'generate_new_picture'
618             SkISize tileSize = SkISize::Make(16, 16);
619
620             SkBitmap tileBM;
621             setup_bitmap(gRec, tileSize, &tileBM);
622             SkCanvas tileCanvas(tileBM);
623             installFilter(&tileCanvas);
624
625             SkCanvas bmpCanvas(*bitmap);
626             SkPaint bmpPaint;
627             bmpPaint.setXfermodeMode(SkXfermode::kSrc_Mode);
628
629             for (int yTile = 0; yTile < (size.height()+15)/16; ++yTile) {
630                 for (int xTile = 0; xTile < (size.width()+15)/16; ++xTile) {
631                     int saveCount = tileCanvas.save();
632                     SkMatrix mat(tileCanvas.getTotalMatrix());
633                     mat.postTranslate(SkIntToScalar(-xTile*tileSize.width()),
634                                       SkIntToScalar(-yTile*tileSize.height()));
635                     tileCanvas.setMatrix(mat);
636                     pict->playback(&tileCanvas);
637                     tileCanvas.flush();
638                     tileCanvas.restoreToCount(saveCount);
639                     bmpCanvas.drawBitmap(tileBM,
640                                          SkIntToScalar(xTile * tileSize.width()),
641                                          SkIntToScalar(yTile * tileSize.height()),
642                                          &bmpPaint);
643                 }
644             }
645         } else {
646             SkCanvas canvas(*bitmap);
647             installFilter(&canvas);
648             canvas.scale(scale, scale);
649             canvas.drawPicture(pict);
650             complete_bitmap(bitmap);
651         }
652     }
653
654     static bool generate_pdf(GM* gm, SkDynamicMemoryWStream& pdf) {
655 #ifdef SK_SUPPORT_PDF
656         SkMatrix initialTransform = gm->getInitialTransform();
657         if (FLAGS_useDocumentInsteadOfDevice) {
658             SkISize pageISize = gm->getISize();
659             SkAutoTUnref<SkDocument> pdfDoc(
660                     SkDocument::CreatePDF(&pdf, NULL,
661                                           encode_to_dct_data,
662                                           SkIntToScalar(FLAGS_pdfRasterDpi)));
663
664             if (!pdfDoc.get()) {
665                 return false;
666             }
667
668             SkCanvas* canvas = NULL;
669             canvas = pdfDoc->beginPage(SkIntToScalar(pageISize.width()),
670                                        SkIntToScalar(pageISize.height()));
671             canvas->concat(initialTransform);
672
673             invokeGM(gm, canvas, true, false);
674
675             return pdfDoc->close();
676         } else {
677             SkISize pageSize = gm->getISize();
678             SkPDFDevice* dev = NULL;
679             if (initialTransform.isIdentity()) {
680                 dev = new SkPDFDevice(pageSize, pageSize, initialTransform);
681             } else {
682                 SkRect content = SkRect::MakeWH(SkIntToScalar(pageSize.width()),
683                                                 SkIntToScalar(pageSize.height()));
684                 initialTransform.mapRect(&content);
685                 content.intersect(0, 0, SkIntToScalar(pageSize.width()),
686                                   SkIntToScalar(pageSize.height()));
687                 SkISize contentSize =
688                     SkISize::Make(SkScalarRoundToInt(content.width()),
689                                   SkScalarRoundToInt(content.height()));
690                 dev = new SkPDFDevice(pageSize, contentSize, initialTransform);
691             }
692             dev->setDCTEncoder(encode_to_dct_data);
693             dev->setRasterDpi(SkIntToScalar(FLAGS_pdfRasterDpi));
694             SkAutoUnref aur(dev);
695             SkCanvas c(dev);
696             invokeGM(gm, &c, true, false);
697             SkPDFDocument doc;
698             doc.appendPage(dev);
699             doc.emitPDF(&pdf);
700         }
701 #endif  // SK_SUPPORT_PDF
702         return true; // Do not report failure if pdf is not supported.
703     }
704
705     static void generate_xps(GM* gm, SkDynamicMemoryWStream& xps) {
706 #ifdef SK_SUPPORT_XPS
707         SkISize size = gm->getISize();
708
709         SkSize trimSize = SkSize::Make(SkIntToScalar(size.width()),
710                                        SkIntToScalar(size.height()));
711         static const SkScalar inchesPerMeter = SkScalarDiv(10000, 254);
712         static const SkScalar upm = 72 * inchesPerMeter;
713         SkVector unitsPerMeter = SkPoint::Make(upm, upm);
714         static const SkScalar ppm = 200 * inchesPerMeter;
715         SkVector pixelsPerMeter = SkPoint::Make(ppm, ppm);
716
717         SkXPSDevice* dev = new SkXPSDevice();
718         SkAutoUnref aur(dev);
719
720         SkCanvas c(dev);
721         dev->beginPortfolio(&xps);
722         dev->beginSheet(unitsPerMeter, pixelsPerMeter, trimSize);
723         invokeGM(gm, &c, false, false);
724         dev->endSheet();
725         dev->endPortfolio();
726
727 #endif
728     }
729
730     /**
731      * Log more detail about the mistmatch between expectedBitmap and
732      * actualBitmap.
733      */
734     void report_bitmap_diffs(const SkBitmap& expectedBitmap, const SkBitmap& actualBitmap,
735                              const char *testName) {
736         const int expectedWidth = expectedBitmap.width();
737         const int expectedHeight = expectedBitmap.height();
738         const int width = actualBitmap.width();
739         const int height = actualBitmap.height();
740         if ((expectedWidth != width) || (expectedHeight != height)) {
741             SkDebugf("---- %s: dimension mismatch -- expected [%d %d], actual [%d %d]\n",
742                      testName, expectedWidth, expectedHeight, width, height);
743             return;
744         }
745
746         if ((kN32_SkColorType != expectedBitmap.colorType()) ||
747             (kN32_SkColorType != actualBitmap.colorType())) {
748             SkDebugf("---- %s: not computing max per-channel pixel mismatch because non-8888\n",
749                      testName);
750             return;
751         }
752
753         SkAutoLockPixels alp0(expectedBitmap);
754         SkAutoLockPixels alp1(actualBitmap);
755         int errR = 0;
756         int errG = 0;
757         int errB = 0;
758         int errA = 0;
759         int differingPixels = 0;
760
761         for (int y = 0; y < height; ++y) {
762             const SkPMColor* expectedPixelPtr = expectedBitmap.getAddr32(0, y);
763             const SkPMColor* actualPixelPtr = actualBitmap.getAddr32(0, y);
764             for (int x = 0; x < width; ++x) {
765                 SkPMColor expectedPixel = *expectedPixelPtr++;
766                 SkPMColor actualPixel = *actualPixelPtr++;
767                 if (expectedPixel != actualPixel) {
768                     differingPixels++;
769                     errR = SkMax32(errR, SkAbs32((int)SkGetPackedR32(expectedPixel) -
770                                                  (int)SkGetPackedR32(actualPixel)));
771                     errG = SkMax32(errG, SkAbs32((int)SkGetPackedG32(expectedPixel) -
772                                                  (int)SkGetPackedG32(actualPixel)));
773                     errB = SkMax32(errB, SkAbs32((int)SkGetPackedB32(expectedPixel) -
774                                                  (int)SkGetPackedB32(actualPixel)));
775                     errA = SkMax32(errA, SkAbs32((int)SkGetPackedA32(expectedPixel) -
776                                                  (int)SkGetPackedA32(actualPixel)));
777                 }
778             }
779         }
780         SkDebugf("---- %s: %d (of %d) differing pixels, "
781                  "max per-channel mismatch R=%d G=%d B=%d A=%d\n",
782                  testName, differingPixels, width*height, errR, errG, errB, errA);
783     }
784
785     /**
786      * Compares actual hash digest to expectations, returning the set of errors
787      * (if any) that we saw along the way.
788      *
789      * If fMismatchPath has been set, and there are pixel diffs, then the
790      * actual bitmap will be written out to a file within fMismatchPath.
791      * And similarly for fMissingExpectationsPath...
792      *
793      * @param expectations what expectations to compare actualBitmap against
794      * @param actualBitmapAndDigest the SkBitmap we actually generated, and its GmResultDigest
795      * @param shortName name of test, e.g. "selftest1"
796      * @param configName name of config, e.g. "8888"
797      * @param renderModeDescriptor e.g., "-rtree", "-deferred"
798      * @param addToJsonSummary whether to add these results (both actual and
799      *        expected) to the JSON summary. Regardless of this setting, if
800      *        we find an image mismatch in this test, we will write these
801      *        results to the JSON summary.  (This is so that we will always
802      *        report errors across rendering modes, such as pipe vs tiled.
803      *        See https://codereview.chromium.org/13650002/ )
804      */
805     ErrorCombination compare_to_expectations(Expectations expectations,
806                                              const BitmapAndDigest& actualBitmapAndDigest,
807                                              const char *shortName, const char *configName,
808                                              const char *renderModeDescriptor,
809                                              bool addToJsonSummary) {
810         ErrorCombination errors;
811         SkString shortNamePlusConfig = make_shortname_plus_config(shortName, configName);
812         SkString completeNameString(shortNamePlusConfig);
813         completeNameString.append(renderModeDescriptor);
814         completeNameString.append(".");
815         completeNameString.append(kPNG_FileExtension);
816         const char* completeName = completeNameString.c_str();
817
818         if (expectations.empty()) {
819             errors.add(kMissingExpectations_ErrorType);
820
821             // Write out the "actuals" for any tests without expectations, if we have
822             // been directed to do so.
823             if (fMissingExpectationsPath) {
824                 SkString path = make_bitmap_filename(fMissingExpectationsPath, shortName,
825                                                      configName, renderModeDescriptor,
826                                                      actualBitmapAndDigest.fDigest);
827                 write_bitmap(path, actualBitmapAndDigest.fBitmap);
828             }
829
830         } else if (!expectations.match(actualBitmapAndDigest.fDigest)) {
831             addToJsonSummary = true;
832             // The error mode we record depends on whether this was running
833             // in a non-standard renderMode.
834             if ('\0' == *renderModeDescriptor) {
835                 errors.add(kExpectationsMismatch_ErrorType);
836             } else {
837                 errors.add(kRenderModeMismatch_ErrorType);
838             }
839
840             // Write out the "actuals" for any mismatches, if we have
841             // been directed to do so.
842             if (fMismatchPath) {
843                 SkString path = make_bitmap_filename(fMismatchPath, shortName, configName,
844                                                      renderModeDescriptor,
845                                                      actualBitmapAndDigest.fDigest);
846                 write_bitmap(path, actualBitmapAndDigest.fBitmap);
847             }
848
849             // If we have access to a single expected bitmap, log more
850             // detail about the mismatch.
851             const SkBitmap *expectedBitmapPtr = expectations.asBitmap();
852             if (expectedBitmapPtr) {
853                 report_bitmap_diffs(*expectedBitmapPtr, actualBitmapAndDigest.fBitmap,
854                                     completeName);
855             }
856         }
857
858         if (addToJsonSummary) {
859             add_actual_results_to_json_summary(completeName, actualBitmapAndDigest.fDigest, errors,
860                                                expectations.ignoreFailure());
861             add_expected_results_to_json_summary(completeName, expectations);
862         }
863
864         return errors;
865     }
866
867     /**
868      * Add this result to the appropriate JSON collection of actual results (but just ONE),
869      * depending on errors encountered.
870      */
871     void add_actual_results_to_json_summary(const char testName[],
872                                             const GmResultDigest &actualResultDigest,
873                                             ErrorCombination errors,
874                                             bool ignoreFailure) {
875         Json::Value jsonActualResults = actualResultDigest.asJsonTypeValuePair();
876         Json::Value *resultCollection = NULL;
877
878         if (errors.isEmpty()) {
879             resultCollection = &this->fJsonActualResults_Succeeded;
880         } else if (errors.includes(kRenderModeMismatch_ErrorType)) {
881             resultCollection = &this->fJsonActualResults_Failed;
882         } else if (errors.includes(kExpectationsMismatch_ErrorType)) {
883             if (ignoreFailure) {
884                 resultCollection = &this->fJsonActualResults_FailureIgnored;
885             } else {
886                 resultCollection = &this->fJsonActualResults_Failed;
887             }
888         } else if (errors.includes(kMissingExpectations_ErrorType)) {
889             // TODO: What about the case where there IS an expected
890             // image hash digest, but that gm test doesn't actually
891             // run?  For now, those cases will always be ignored,
892             // because gm only looks at expectations that correspond
893             // to gm tests that were actually run.
894             //
895             // Once we have the ability to express expectations as a
896             // JSON file, we should fix this (and add a test case for
897             // which an expectation is given but the test is never
898             // run).
899             resultCollection = &this->fJsonActualResults_NoComparison;
900         }
901
902         // If none of the above cases match, we don't add it to ANY tally of actual results.
903         if (resultCollection) {
904             (*resultCollection)[testName] = jsonActualResults;
905         }
906     }
907
908     /**
909      * Add this test to the JSON collection of expected results.
910      */
911     void add_expected_results_to_json_summary(const char testName[],
912                                               Expectations expectations) {
913         this->fJsonExpectedResults[testName] = expectations.asJsonValue();
914     }
915
916     /**
917      * Compare actualBitmap to expectations stored in this->fExpectationsSource.
918      *
919      * @param gm which test generated the actualBitmap
920      * @param gRec
921      * @param configName The config name to look for in the expectation file.
922      * @param actualBitmapAndDigest ptr to bitmap generated by this run, or NULL
923      *        if we don't have a usable bitmap representation
924      */
925     ErrorCombination compare_test_results_to_stored_expectations(
926         GM* gm, const ConfigData& gRec, const char* configName,
927         const BitmapAndDigest* actualBitmapAndDigest) {
928         ErrorCombination errors;
929
930         if (NULL == actualBitmapAndDigest) {
931             // Note that we intentionally skipped validating the results for
932             // this test, because we don't know how to generate an SkBitmap
933             // version of the output.
934             errors.add(ErrorCombination(kIntentionallySkipped_ErrorType));
935         } else if (!(gRec.fFlags & kWrite_ConfigFlag)) {
936             // We don't record the results for this test or compare them
937             // against any expectations, because the output image isn't
938             // meaningful.
939             // See https://code.google.com/p/skia/issues/detail?id=1410 ('some
940             // GM result images not available for download from Google Storage')
941             errors.add(ErrorCombination(kIntentionallySkipped_ErrorType));
942         } else {
943             ExpectationsSource *expectationsSource = this->fExpectationsSource.get();
944             SkString nameWithExtension = make_shortname_plus_config(gm->getName(), configName);
945             nameWithExtension.append(".");
946             nameWithExtension.append(kPNG_FileExtension);
947
948             if (expectationsSource && (gRec.fFlags & kRead_ConfigFlag)) {
949                 /*
950                  * Get the expected results for this test, as one or more allowed
951                  * hash digests. The current implementation of expectationsSource
952                  * get this by computing the hash digest of a single PNG file on disk.
953                  *
954                  * TODO(epoger): This relies on the fact that
955                  * force_all_opaque() was called on the bitmap before it
956                  * was written to disk as a PNG in the first place. If
957                  * not, the hash digest returned here may not match the
958                  * hash digest of actualBitmap, which *has* been run through
959                  * force_all_opaque().
960                  * See comments above complete_bitmap() for more detail.
961                  */
962                 Expectations expectations = expectationsSource->get(nameWithExtension.c_str());
963                 if (this->ShouldIgnoreTest(gm->getName())) {
964                     expectations.setIgnoreFailure(true);
965                 }
966                 errors.add(compare_to_expectations(expectations, *actualBitmapAndDigest,
967                                                    gm->getName(), configName, "", true));
968             } else {
969                 // If we are running without expectations, we still want to
970                 // record the actual results.
971                 add_actual_results_to_json_summary(nameWithExtension.c_str(),
972                                                    actualBitmapAndDigest->fDigest,
973                                                    ErrorCombination(kMissingExpectations_ErrorType),
974                                                    false);
975                 errors.add(ErrorCombination(kMissingExpectations_ErrorType));
976             }
977         }
978         return errors;
979     }
980
981     /**
982      * Compare actualBitmap to referenceBitmap.
983      *
984      * @param shortName test name, e.g. "selftest1"
985      * @param configName configuration name, e.g. "8888"
986      * @param renderModeDescriptor
987      * @param actualBitmap actual bitmap generated by this run
988      * @param referenceBitmap bitmap we expected to be generated
989      */
990     ErrorCombination compare_test_results_to_reference_bitmap(
991         const char *shortName, const char *configName, const char *renderModeDescriptor,
992         SkBitmap& actualBitmap, const SkBitmap* referenceBitmap) {
993
994         SkASSERT(referenceBitmap);
995         Expectations expectations(*referenceBitmap);
996         BitmapAndDigest actualBitmapAndDigest(actualBitmap);
997
998         // TODO: Eliminate RecordTestResults from here.
999         // Results recording code for the test_drawing path has been refactored so that
1000         // RecordTestResults is only called once, at the topmost level. However, the
1001         // other paths have not yet been refactored, and RecordTestResults has been added
1002         // here to maintain proper behavior for calls not coming from the test_drawing path.
1003         ErrorCombination errors;
1004         errors.add(compare_to_expectations(expectations, actualBitmapAndDigest, shortName,
1005                                            configName, renderModeDescriptor, false));
1006         SkString shortNamePlusConfig = make_shortname_plus_config(shortName, configName);
1007         RecordTestResults(errors, shortNamePlusConfig, renderModeDescriptor);
1008
1009         return errors;
1010     }
1011
1012     static SkPicture* generate_new_picture(GM* gm, BbhType bbhType, uint32_t recordFlags,
1013                                            SkScalar scale = SK_Scalar1) {
1014         SkScalar width = SkScalarMul(SkIntToScalar(gm->getISize().width()), scale);
1015         SkScalar height = SkScalarMul(SkIntToScalar(gm->getISize().height()), scale);
1016
1017         SkAutoTDelete<SkBBHFactory> factory;
1018         if (kTileGrid_BbhType == bbhType) {
1019             SkTileGridFactory::TileGridInfo info;
1020             info.fMargin.setEmpty();
1021             info.fOffset.setZero();
1022             info.fTileInterval.set(16, 16);
1023             factory.reset(SkNEW_ARGS(SkTileGridFactory, (info)));
1024         } else if (kRTree_BbhType == bbhType) {
1025             factory.reset(SkNEW(SkRTreeFactory));
1026         }
1027         SkPictureRecorder recorder;
1028         SkCanvas* cv = recorder.beginRecording(width, height, factory.get(), recordFlags);
1029         cv->scale(scale, scale);
1030         invokeGM(gm, cv, false, false);
1031         return recorder.endRecording();
1032     }
1033
1034     static SkPicture* stream_to_new_picture(const SkPicture& src) {
1035         SkDynamicMemoryWStream storage;
1036         src.serialize(&storage, NULL);
1037         SkAutoTUnref<SkStreamAsset> pictReadback(storage.detachAsStream());
1038         SkPicture* retval = SkPicture::CreateFromStream(pictReadback,
1039                                                         &SkImageDecoder::DecodeMemory);
1040         return retval;
1041     }
1042
1043     // Test: draw into a bitmap or pdf.
1044     // Depending on flags, possibly compare to an expected image.
1045     // If writePath is not NULL, also write images (or documents) to the specified path.
1046     ErrorCombination test_drawing(GM* gm, const ConfigData& gRec,
1047                                   const SkTDArray<const PDFRasterizerData*> &pdfRasterizers,
1048                                   const char writePath [],
1049                                   GrSurface* gpuTarget,
1050                                   SkBitmap* bitmap) {
1051         ErrorCombination errors;
1052         SkDynamicMemoryWStream document;
1053         SkString path;
1054
1055         if (gRec.fBackend == kRaster_Backend ||
1056             gRec.fBackend == kGPU_Backend) {
1057             // Early exit if we can't generate the image.
1058             errors.add(generate_image(gm, gRec, gpuTarget, bitmap, false));
1059             if (!errors.isEmpty()) {
1060                 // TODO: Add a test to exercise what the stdout and
1061                 // JSON look like if we get an "early error" while
1062                 // trying to generate the image.
1063                 return errors;
1064             }
1065             BitmapAndDigest bitmapAndDigest(*bitmap);
1066             errors.add(compare_test_results_to_stored_expectations(
1067                            gm, gRec, gRec.fName, &bitmapAndDigest));
1068
1069             if (writePath && (gRec.fFlags & kWrite_ConfigFlag)) {
1070                 path = make_bitmap_filename(writePath, gm->getName(), gRec.fName,
1071                                             "", bitmapAndDigest.fDigest);
1072                 errors.add(write_bitmap(path, bitmapAndDigest.fBitmap));
1073             }
1074         } else if (gRec.fBackend == kPDF_Backend) {
1075             if (!generate_pdf(gm, document)) {
1076                 errors.add(kGeneratePdfFailed_ErrorType);
1077             } else {
1078                 SkAutoTUnref<SkStreamAsset> documentStream(document.detachAsStream());
1079                 if (writePath && (gRec.fFlags & kWrite_ConfigFlag)) {
1080                     path = make_filename(writePath, gm->getName(), gRec.fName, "", "pdf");
1081                     errors.add(write_document(path, documentStream));
1082                 }
1083
1084                 if (!(gm->getFlags() & GM::kSkipPDFRasterization_Flag)) {
1085                     for (int i = 0; i < pdfRasterizers.count(); i++) {
1086                         SkBitmap pdfBitmap;
1087                         documentStream->rewind();
1088                         bool success = (*pdfRasterizers[i]->fRasterizerFunction)(
1089                                 documentStream.get(), &pdfBitmap);
1090                         if (!success) {
1091                             SkDebugf("FAILED to render PDF for %s using renderer %s\n",
1092                                      gm->getName(),
1093                                      pdfRasterizers[i]->fName);
1094                             continue;
1095                         }
1096
1097                         SkString configName(gRec.fName);
1098                         configName.append("-");
1099                         configName.append(pdfRasterizers[i]->fName);
1100
1101                         BitmapAndDigest bitmapAndDigest(pdfBitmap);
1102                         errors.add(compare_test_results_to_stored_expectations(
1103                                    gm, gRec, configName.c_str(), &bitmapAndDigest));
1104
1105                         if (writePath && (gRec.fFlags & kWrite_ConfigFlag)) {
1106                             path = make_bitmap_filename(writePath, gm->getName(),
1107                                                         configName.c_str(),
1108                                                         "", bitmapAndDigest.fDigest);
1109                             errors.add(write_bitmap(path, bitmapAndDigest.fBitmap));
1110                         }
1111                     }
1112                 } else {
1113                     errors.add(kIntentionallySkipped_ErrorType);
1114                 }
1115             }
1116         } else if (gRec.fBackend == kXPS_Backend) {
1117             generate_xps(gm, document);
1118             SkAutoTUnref<SkStreamAsset> documentStream(document.detachAsStream());
1119
1120             errors.add(compare_test_results_to_stored_expectations(
1121                            gm, gRec, gRec.fName, NULL));
1122
1123             if (writePath && (gRec.fFlags & kWrite_ConfigFlag)) {
1124                 path = make_filename(writePath, gm->getName(), gRec.fName, "", "xps");
1125                 errors.add(write_document(path, documentStream));
1126             }
1127         } else {
1128             SkASSERT(false);
1129         }
1130         return errors;
1131     }
1132
1133     ErrorCombination test_deferred_drawing(GM* gm,
1134                                            const ConfigData& gRec,
1135                                            const SkBitmap& referenceBitmap,
1136                                            GrSurface* gpuTarget) {
1137         if (gRec.fBackend == kRaster_Backend ||
1138             gRec.fBackend == kGPU_Backend) {
1139             const char renderModeDescriptor[] = "-deferred";
1140             SkBitmap bitmap;
1141             // Early exit if we can't generate the image, but this is
1142             // expected in some cases, so don't report a test failure.
1143             ErrorCombination errors = generate_image(gm, gRec, gpuTarget, &bitmap, true);
1144             // TODO(epoger): This logic is the opposite of what is
1145             // described above... if we succeeded in generating the
1146             // -deferred image, we exit early!  We should fix this
1147             // ASAP, because it is hiding -deferred errors... but for
1148             // now, I'm leaving the logic as it is so that the
1149             // refactoring change
1150             // https://codereview.chromium.org/12992003/ is unblocked.
1151             //
1152             // Filed as https://code.google.com/p/skia/issues/detail?id=1180
1153             // ('image-surface gm test is failing in "deferred" mode,
1154             // and gm is not reporting the failure')
1155             if (errors.isEmpty()) {
1156                 // TODO(epoger): Report this as a new ErrorType,
1157                 // something like kImageGeneration_ErrorType?
1158                 return kEmpty_ErrorCombination;
1159             }
1160             return compare_test_results_to_reference_bitmap(
1161                 gm->getName(), gRec.fName, renderModeDescriptor, bitmap, &referenceBitmap);
1162         }
1163         return kEmpty_ErrorCombination;
1164     }
1165
1166     ErrorCombination test_pipe_playback(GM* gm, const ConfigData& gRec,
1167                                         const SkBitmap& referenceBitmap, bool simulateFailure) {
1168         const SkString shortNamePlusConfig = make_shortname_plus_config(gm->getName(),
1169                                                                         gRec.fName);
1170         ErrorCombination errors;
1171         for (size_t i = 0; i < SK_ARRAY_COUNT(gPipeWritingFlagCombos); ++i) {
1172             SkString renderModeDescriptor("-pipe");
1173             renderModeDescriptor.append(gPipeWritingFlagCombos[i].name);
1174
1175             if (gm->getFlags() & GM::kSkipPipe_Flag
1176                 || (gPipeWritingFlagCombos[i].flags == SkGPipeWriter::kCrossProcess_Flag
1177                     && gm->getFlags() & GM::kSkipPipeCrossProcess_Flag)) {
1178                 RecordTestResults(kIntentionallySkipped_ErrorType, shortNamePlusConfig,
1179                                   renderModeDescriptor.c_str());
1180                 errors.add(kIntentionallySkipped_ErrorType);
1181             } else {
1182                 SkBitmap bitmap;
1183                 SkISize size = gm->getISize();
1184                 setup_bitmap(gRec, size, &bitmap);
1185                 SkCanvas canvas(bitmap);
1186                 installFilter(&canvas);
1187                 // Pass a decoding function so the factory GM (which has an SkBitmap
1188                 // with encoded data) will not fail playback.
1189                 PipeController pipeController(&canvas, &SkImageDecoder::DecodeMemory);
1190                 SkGPipeWriter writer;
1191                 SkCanvas* pipeCanvas = writer.startRecording(&pipeController,
1192                                                              gPipeWritingFlagCombos[i].flags,
1193                                                              size.width(), size.height());
1194                 if (!simulateFailure) {
1195                     invokeGM(gm, pipeCanvas, false, false);
1196                 }
1197                 complete_bitmap(&bitmap);
1198                 writer.endRecording();
1199                 errors.add(compare_test_results_to_reference_bitmap(
1200                     gm->getName(), gRec.fName, renderModeDescriptor.c_str(), bitmap,
1201                     &referenceBitmap));
1202                 if (!errors.isEmpty()) {
1203                     break;
1204                 }
1205             }
1206         }
1207         return errors;
1208     }
1209
1210     ErrorCombination test_tiled_pipe_playback(GM* gm, const ConfigData& gRec,
1211                                               const SkBitmap& referenceBitmap) {
1212         const SkString shortNamePlusConfig = make_shortname_plus_config(gm->getName(),
1213                                                                         gRec.fName);
1214         ErrorCombination errors;
1215         for (size_t i = 0; i < SK_ARRAY_COUNT(gPipeWritingFlagCombos); ++i) {
1216             SkString renderModeDescriptor("-tiled pipe");
1217             renderModeDescriptor.append(gPipeWritingFlagCombos[i].name);
1218
1219             if ((gm->getFlags() & GM::kSkipPipe_Flag) ||
1220                 (gm->getFlags() & GM::kSkipTiled_Flag)) {
1221                 RecordTestResults(kIntentionallySkipped_ErrorType, shortNamePlusConfig,
1222                                   renderModeDescriptor.c_str());
1223                 errors.add(kIntentionallySkipped_ErrorType);
1224             } else {
1225                 SkBitmap bitmap;
1226                 SkISize size = gm->getISize();
1227                 setup_bitmap(gRec, size, &bitmap);
1228                 SkCanvas canvas(bitmap);
1229                 installFilter(&canvas);
1230                 TiledPipeController pipeController(bitmap, &SkImageDecoder::DecodeMemory);
1231                 SkGPipeWriter writer;
1232                 SkCanvas* pipeCanvas = writer.startRecording(&pipeController,
1233                                                              gPipeWritingFlagCombos[i].flags,
1234                                                              size.width(), size.height());
1235                 invokeGM(gm, pipeCanvas, false, false);
1236                 complete_bitmap(&bitmap);
1237                 writer.endRecording();
1238                 errors.add(compare_test_results_to_reference_bitmap(gm->getName(), gRec.fName,
1239                                                                     renderModeDescriptor.c_str(),
1240                                                                     bitmap, &referenceBitmap));
1241                 if (!errors.isEmpty()) {
1242                     break;
1243                 }
1244             }
1245         }
1246         return errors;
1247     }
1248
1249     //
1250     // member variables.
1251     // They are public for now, to allow easier setting by tool_main().
1252     //
1253
1254     bool fUseFileHierarchy, fWriteChecksumBasedFilenames;
1255     ErrorCombination fIgnorableErrorTypes;
1256     SkTArray<SkString> fIgnorableTestNames;
1257
1258     const char* fMismatchPath;
1259     const char* fMissingExpectationsPath;
1260
1261     // collection of tests that have failed with each ErrorType
1262     SkTArray<SkString> fFailedTests[kLast_ErrorType+1];
1263     SkTArray<SkString> fTestsSkippedOnAllRenderModes;
1264     int fTestsRun;
1265     SkTDict<int> fRenderModesEncountered;
1266
1267     // Where to read expectations (expected image hash digests, etc.) from.
1268     // If unset, we don't do comparisons.
1269     SkAutoTUnref<ExpectationsSource> fExpectationsSource;
1270
1271     // JSON summaries that we generate as we go (just for output).
1272     Json::Value fJsonExpectedResults;
1273     Json::Value fJsonActualResults_Failed;
1274     Json::Value fJsonActualResults_FailureIgnored;
1275     Json::Value fJsonActualResults_NoComparison;
1276     Json::Value fJsonActualResults_Succeeded;
1277 }; // end of GMMain class definition
1278
1279 #if SK_SUPPORT_GPU
1280 static const GLContextType kDontCare_GLContextType = GrContextFactory::kNative_GLContextType;
1281 #else
1282 static const GLContextType kDontCare_GLContextType = 0;
1283 #endif
1284
1285 static const ConfigData gRec[] = {
1286     { kN32_SkColorType,     kRaster_Backend, kDontCare_GLContextType,                  0, kRW_ConfigFlag,    "8888",         true },
1287     { kRGB_565_SkColorType, kRaster_Backend, kDontCare_GLContextType,                  0, kRW_ConfigFlag,    "565",          true },
1288 #if SK_SUPPORT_GPU
1289     { kN32_SkColorType, kGPU_Backend,    GrContextFactory::kNative_GLContextType,  0, kRW_ConfigFlag,    "gpu",          true },
1290     { kN32_SkColorType, kGPU_Backend,    GrContextFactory::kNative_GLContextType, 16, kRW_ConfigFlag,    "msaa16",       false},
1291     { kN32_SkColorType, kGPU_Backend,    GrContextFactory::kNative_GLContextType,  4, kRW_ConfigFlag,    "msaa4",        false},
1292     { kN32_SkColorType, kGPU_Backend,    GrContextFactory::kNVPR_GLContextType,    4, kRW_ConfigFlag,    "nvprmsaa4",   true },
1293     { kN32_SkColorType, kGPU_Backend,    GrContextFactory::kNVPR_GLContextType,   16, kRW_ConfigFlag,    "nvprmsaa16",  false},
1294     /* The gpudebug context does not generate meaningful images, so don't record
1295      * the images it generates!  We only run it to look for asserts. */
1296     { kN32_SkColorType, kGPU_Backend,    GrContextFactory::kDebug_GLContextType,   0, kNone_ConfigFlag,  "gpudebug",     kDebugOnly},
1297     /* The gpunull context does the least amount of work possible and doesn't
1298        generate meaninful images, so don't record them!. It can be run to
1299        isolate the CPU-side processing expense from the GPU-side.
1300       */
1301     { kN32_SkColorType, kGPU_Backend,    GrContextFactory::kNull_GLContextType,    0, kNone_ConfigFlag,  "gpunull",      kDebugOnly},
1302 #if SK_ANGLE
1303     { kN32_SkColorType, kGPU_Backend,    GrContextFactory::kANGLE_GLContextType,   0, kRW_ConfigFlag,    "angle",        true },
1304     { kN32_SkColorType, kGPU_Backend,    GrContextFactory::kANGLE_GLContextType,  16, kRW_ConfigFlag,    "anglemsaa16",  true },
1305 #endif // SK_ANGLE
1306 #ifdef SK_MESA
1307     { kN32_SkColorType, kGPU_Backend,    GrContextFactory::kMESA_GLContextType,    0, kRW_ConfigFlag,    "mesa",         true },
1308 #endif // SK_MESA
1309 #endif // SK_SUPPORT_GPU
1310 #ifdef SK_SUPPORT_XPS
1311     /* At present we have no way of comparing XPS files (either natively or by converting to PNG). */
1312     { kN32_SkColorType, kXPS_Backend,    kDontCare_GLContextType,                  0, kWrite_ConfigFlag, "xps",          true },
1313 #endif // SK_SUPPORT_XPS
1314 #ifdef SK_SUPPORT_PDF
1315     { kN32_SkColorType, kPDF_Backend,    kDontCare_GLContextType,                  0, kRW_ConfigFlag,    "pdf",          true },
1316 #endif // SK_SUPPORT_PDF
1317 };
1318
1319 static bool SkNoRasterizePDF(SkStream*, SkBitmap*) { return false; }
1320
1321 static const PDFRasterizerData kPDFRasterizers[] = {
1322 #ifdef SK_BUILD_FOR_MAC
1323     { &SkPDFDocumentToBitmap, "mac",     true },
1324 #endif
1325 #ifdef SK_BUILD_POPPLER
1326     { &SkPopplerRasterizePDF, "poppler", true },
1327 #endif
1328 #ifdef SK_BUILD_NATIVE_PDF_RENDERER
1329     { &SkNativeRasterizePDF,  "native",  true },
1330 #endif  // SK_BUILD_NATIVE_PDF_RENDERER
1331     // The following exists so that this array is never zero length.
1332     { &SkNoRasterizePDF,      "none",    false},
1333 };
1334
1335 static const char kDefaultsConfigStr[] = "defaults";
1336 static const char kExcludeConfigChar = '~';
1337 #if SK_SUPPORT_GPU
1338 static const char kGpuAPINameGL[] = "gl";
1339 static const char kGpuAPINameGLES[] = "gles";
1340 #endif
1341
1342 static SkString configUsage() {
1343     SkString result;
1344     result.appendf("Space delimited list of which configs to run. Possible options: [");
1345     for (size_t i = 0; i < SK_ARRAY_COUNT(gRec); ++i) {
1346         SkASSERT(gRec[i].fName != kDefaultsConfigStr);
1347         if (i > 0) {
1348             result.append("|");
1349         }
1350         result.appendf("%s", gRec[i].fName);
1351     }
1352     result.append("]\n");
1353     result.appendf("The default value is: \"");
1354     SkString firstDefault;
1355     SkString allButFirstDefaults;
1356     SkString nonDefault;
1357     for (size_t i = 0; i < SK_ARRAY_COUNT(gRec); ++i) {
1358         if (gRec[i].fRunByDefault) {
1359             if (i > 0) {
1360                 result.append(" ");
1361             }
1362             result.append(gRec[i].fName);
1363             if (firstDefault.isEmpty()) {
1364                 firstDefault = gRec[i].fName;
1365             } else {
1366                 if (!allButFirstDefaults.isEmpty()) {
1367                     allButFirstDefaults.append(" ");
1368                 }
1369                 allButFirstDefaults.append(gRec[i].fName);
1370             }
1371         } else {
1372             nonDefault = gRec[i].fName;
1373         }
1374     }
1375     result.append("\"\n");
1376     result.appendf("\"%s\" evaluates to the default set of configs.\n", kDefaultsConfigStr);
1377     result.appendf("Prepending \"%c\" on a config name excludes it from the set of configs to run.\n"
1378                    "Exclusions always override inclusions regardless of order.\n",
1379                    kExcludeConfigChar);
1380     result.appendf("E.g. \"--config %s %c%s %s\" will run these configs:\n\t%s %s",
1381                    kDefaultsConfigStr,
1382                    kExcludeConfigChar,
1383                    firstDefault.c_str(),
1384                    nonDefault.c_str(),
1385                    allButFirstDefaults.c_str(),
1386                    nonDefault.c_str());
1387     return result;
1388 }
1389
1390 static SkString pdfRasterizerUsage() {
1391     SkString result;
1392     result.appendf("Space delimited list of which PDF rasterizers to run. Possible options: [");
1393     // For this (and further) loops through kPDFRasterizers, there is a typecast to int to avoid
1394     // the compiler giving an "comparison of unsigned expression < 0 is always false" warning
1395     // and turning it into a build-breaking error.
1396     for (int i = 0; i < (int)SK_ARRAY_COUNT(kPDFRasterizers); ++i) {
1397         if (i > 0) {
1398             result.append(" ");
1399         }
1400         result.append(kPDFRasterizers[i].fName);
1401     }
1402     result.append("]\n");
1403     result.append("The default value is: \"");
1404     for (int i = 0; i < (int)SK_ARRAY_COUNT(kPDFRasterizers); ++i) {
1405         if (kPDFRasterizers[i].fRunByDefault) {
1406             if (i > 0) {
1407                 result.append(" ");
1408             }
1409             result.append(kPDFRasterizers[i].fName);
1410         }
1411     }
1412     result.append("\"");
1413     return result;
1414 }
1415
1416 // Macro magic to convert a numeric preprocessor token into a string.
1417 // Adapted from http://stackoverflow.com/questions/240353/convert-a-preprocessor-token-to-a-string
1418 // This should probably be moved into one of our common headers...
1419 #define TOSTRING_INTERNAL(x) #x
1420 #define TOSTRING(x) TOSTRING_INTERNAL(x)
1421
1422 // Alphabetized ignoring "no" prefix ("readPath", "noreplay", "resourcePath").
1423 DEFINE_string(config, "", configUsage().c_str());
1424 DEFINE_bool(cpu, true, "Allows non-GPU configs to be run. Applied after --config.");
1425 DEFINE_string(pdfRasterizers, "default", pdfRasterizerUsage().c_str());
1426 DEFINE_bool(deferred, false, "Exercise the deferred rendering test pass.");
1427 DEFINE_bool(dryRun, false, "Don't actually run the tests, just print what would have been done.");
1428 DEFINE_string(excludeConfig, "", "Space delimited list of configs to skip.");
1429 DEFINE_bool(forceBWtext, false, "Disable text anti-aliasing.");
1430 #if SK_SUPPORT_GPU
1431 DEFINE_string(gpuAPI, "", "Force use of specific gpu API.  Using \"gl\" "
1432               "forces OpenGL API. Using \"gles\" forces OpenGL ES API. "
1433               "Defaults to empty string, which selects the API native to the "
1434               "system.");
1435 DEFINE_string(gpuCacheSize, "", "<bytes> <count>: Limit the gpu cache to byte size or "
1436               "object count. " TOSTRING(DEFAULT_CACHE_VALUE) " for either value means "
1437               "use the default. 0 for either disables the cache.");
1438 DEFINE_bool(gpu, true, "Allows GPU configs to be run. Applied after --config.");
1439 DEFINE_bool(gpuCompressAlphaMasks, false, "Compress masks generated from falling back to "
1440                                           "software path rendering.");
1441 #endif
1442 DEFINE_bool(hierarchy, false, "Whether to use multilevel directory structure "
1443             "when reading/writing files.");
1444 DEFINE_string(ignoreErrorTypes, kDefaultIgnorableErrorTypes.asString(" ").c_str(),
1445               "Space-separated list of ErrorTypes that should be ignored. If any *other* error "
1446               "types are encountered, the tool will exit with a nonzero return value.");
1447 DEFINE_string(ignoreFailuresFile, "", "Path to file containing a list of tests for which we "
1448               "should ignore failures.\n"
1449               "The file should list one test per line, except for comment lines starting with #");
1450 DEFINE_bool2(leaks, l, false, "show leaked ref cnt'd objects.");
1451 DEFINE_string(match, "", "[~][^]substring[$] [...] of test name to run.\n"
1452               "Multiple matches may be separated by spaces.\n"
1453               "~ causes a matching test to always be skipped\n"
1454               "^ requires the start of the test to match\n"
1455               "$ requires the end of the test to match\n"
1456               "^ and $ requires an exact match\n"
1457               "If a test does not match any list entry,\n"
1458               "it is skipped unless some list entry starts with ~");
1459 DEFINE_string(missingExpectationsPath, "", "Write images for tests without expectations "
1460               "into this directory.");
1461 DEFINE_string(mismatchPath, "", "Write images for tests that failed due to "
1462               "pixel mismatches into this directory.");
1463 DEFINE_string(modulo, "", "[--modulo <remainder> <divisor>]: only run tests for which "
1464               "testIndex %% divisor == remainder.");
1465 DEFINE_bool(pipe, false, "Exercise the SkGPipe replay test pass.");
1466 DEFINE_string2(readPath, r, "", "Read reference images from this dir, and report "
1467                "any differences between those and the newly generated ones.");
1468 DEFINE_bool(replay, false, "Exercise the SkPicture replay test pass.");
1469
1470 #ifdef SK_BUILD_FOR_ANDROID
1471 DEFINE_bool(resetGpuContext, true, "Reset the GrContext prior to running each GM.");
1472 #else
1473 DEFINE_bool(resetGpuContext, false, "Reset the GrContext prior to running each GM.");
1474 #endif
1475
1476 DEFINE_bool(rtree, false, "Exercise the R-Tree variant of SkPicture test pass.");
1477 DEFINE_bool(serialize, false, "Exercise the SkPicture serialization & deserialization test pass.");
1478 DEFINE_bool(simulatePipePlaybackFailure, false, "Simulate a rendering failure in pipe mode only.");
1479 DEFINE_bool(tiledPipe, false, "Exercise tiled SkGPipe replay.");
1480 DEFINE_bool(tileGrid, false, "Exercise the tile grid variant of SkPicture.");
1481 DEFINE_string(tileGridReplayScales, "", "Space separated list of floating-point scale "
1482               "factors to be used for tileGrid playback testing. Default value: 1.0");
1483 DEFINE_bool2(verbose, v, false, "Give more detail (e.g. list all GMs run, more info about "
1484              "each test).");
1485 DEFINE_bool(writeChecksumBasedFilenames, false, "When writing out actual images, use checksum-"
1486             "based filenames, as rebaseline.py will use when downloading them from Google Storage");
1487 DEFINE_string(writeJsonSummaryPath, "", "Write a JSON-formatted result summary to this file.");
1488 DEFINE_string2(writePath, w, "",  "Write rendered images into this directory.");
1489 DEFINE_string2(writePicturePath, p, "", "Write .skp files into this directory.");
1490 DEFINE_int32(pdfJpegQuality, -1, "Encodes images in JPEG at quality level N, "
1491              "which can be in range 0-100). N = -1 will disable JPEG compression. "
1492              "Default is N = 100, maximum quality.");
1493 // TODO(edisonn): pass a matrix instead of forcePerspectiveMatrix
1494 // Either the 9 numbers defining the matrix
1495 // or probably more readable would be to replace it with a set of a few predicates
1496 // Like --prerotate 100 200 10 --posttranslate 10, 10
1497 // Probably define spacial names like centerx, centery, top, bottom, left, right
1498 // then we can write something reabable like --rotate centerx centery 90
1499 DEFINE_bool(forcePerspectiveMatrix, false, "Force a perspective matrix.");
1500 DEFINE_bool(useDocumentInsteadOfDevice, false, "Use SkDocument::CreateFoo instead of SkFooDevice.");
1501 DEFINE_int32(pdfRasterDpi, 72, "Scale at which at which the non suported "
1502              "features in PDF are rasterized. Must be be in range 0-10000. "
1503              "Default is 72. N = 0 will disable rasterizing features like "
1504              "text shadows or perspective bitmaps.");
1505 static SkData* encode_to_dct_data(size_t*, const SkBitmap& bitmap) {
1506     // Filter output of warnings that JPEG is not available for the image.
1507     if (bitmap.width() >= 65500 || bitmap.height() >= 65500) return NULL;
1508     if (FLAGS_pdfJpegQuality == -1) return NULL;
1509
1510     SkBitmap bm = bitmap;
1511 #if defined(SK_BUILD_FOR_MAC)
1512     // Workaround bug #1043 where bitmaps with referenced pixels cause
1513     // CGImageDestinationFinalize to crash
1514     SkBitmap copy;
1515     bitmap.deepCopyTo(&copy);
1516     bm = copy;
1517 #endif
1518
1519     SkPixelRef* pr = bm.pixelRef();
1520     if (pr != NULL) {
1521         SkData* data = pr->refEncodedData();
1522         if (data != NULL) {
1523             return data;
1524         }
1525     }
1526
1527     return SkImageEncoder::EncodeData(bm,
1528                                       SkImageEncoder::kJPEG_Type,
1529                                       FLAGS_pdfJpegQuality);
1530 }
1531
1532 static int findConfig(const char config[]) {
1533     for (size_t i = 0; i < SK_ARRAY_COUNT(gRec); i++) {
1534         if (!strcmp(config, gRec[i].fName)) {
1535             return (int) i;
1536         }
1537     }
1538     return -1;
1539 }
1540
1541 static const PDFRasterizerData* findPDFRasterizer(const char rasterizer[]) {
1542     for (int i = 0; i < (int)SK_ARRAY_COUNT(kPDFRasterizers); i++) {
1543         if (!strcmp(rasterizer, kPDFRasterizers[i].fName)) {
1544             return &kPDFRasterizers[i];
1545         }
1546     }
1547     return NULL;
1548 }
1549
1550 template <typename T> void appendUnique(SkTDArray<T>* array, const T& value) {
1551     int index = array->find(value);
1552     if (index < 0) {
1553         *array->append() = value;
1554     }
1555 }
1556
1557 /**
1558  * Run this test in a number of different drawing modes (pipe,
1559  * deferred, tiled, etc.), confirming that the resulting bitmaps all
1560  * *exactly* match comparisonBitmap.
1561  *
1562  * Returns all errors encountered while doing so.
1563  */
1564 ErrorCombination run_multiple_modes(GMMain &gmmain, GM *gm, const ConfigData &compareConfig,
1565                                     const SkBitmap &comparisonBitmap,
1566                                     const SkTDArray<SkScalar> &tileGridReplayScales);
1567 ErrorCombination run_multiple_modes(GMMain &gmmain, GM *gm, const ConfigData &compareConfig,
1568                                     const SkBitmap &comparisonBitmap,
1569                                     const SkTDArray<SkScalar> &tileGridReplayScales) {
1570     ErrorCombination errorsForAllModes;
1571     uint32_t gmFlags = gm->getFlags();
1572     const SkString shortNamePlusConfig = gmmain.make_shortname_plus_config(gm->getName(),
1573                                                                            compareConfig.fName);
1574
1575     SkPicture* pict = gmmain.generate_new_picture(gm, kNone_BbhType, 0);
1576     SkAutoUnref aur(pict);
1577     if (FLAGS_replay) {
1578         const char renderModeDescriptor[] = "-replay";
1579         if (gmFlags & GM::kSkipPicture_Flag) {
1580             gmmain.RecordTestResults(kIntentionallySkipped_ErrorType, shortNamePlusConfig,
1581                                      renderModeDescriptor);
1582             errorsForAllModes.add(kIntentionallySkipped_ErrorType);
1583         } else {
1584             SkBitmap bitmap;
1585             gmmain.generate_image_from_picture(gm, compareConfig, pict, &bitmap);
1586             errorsForAllModes.add(gmmain.compare_test_results_to_reference_bitmap(
1587                 gm->getName(), compareConfig.fName, renderModeDescriptor, bitmap,
1588                 &comparisonBitmap));
1589         }
1590     }
1591
1592     if (FLAGS_serialize) {
1593         const char renderModeDescriptor[] = "-serialize";
1594         if (gmFlags & GM::kSkipPicture_Flag) {
1595             gmmain.RecordTestResults(kIntentionallySkipped_ErrorType, shortNamePlusConfig,
1596                                      renderModeDescriptor);
1597             errorsForAllModes.add(kIntentionallySkipped_ErrorType);
1598         } else {
1599             SkPicture* repict = gmmain.stream_to_new_picture(*pict);
1600             SkAutoUnref aurr(repict);
1601             SkBitmap bitmap;
1602             gmmain.generate_image_from_picture(gm, compareConfig, repict, &bitmap);
1603             errorsForAllModes.add(gmmain.compare_test_results_to_reference_bitmap(
1604                 gm->getName(), compareConfig.fName, renderModeDescriptor, bitmap,
1605                 &comparisonBitmap));
1606         }
1607     }
1608
1609     if ((1 == FLAGS_writePicturePath.count()) &&
1610         !(gmFlags & GM::kSkipPicture_Flag)) {
1611         const char* pictureSuffix = "skp";
1612         // TODO(epoger): Make sure this still works even though the
1613         // filename now contains the config name (it used to contain
1614         // just the shortName).  I think this is actually an
1615         // *improvement*, because now runs with different configs will
1616         // write out their SkPictures to separate files rather than
1617         // overwriting each other.  But we should make sure it doesn't
1618         // break anybody.
1619         SkString path = gmmain.make_filename(FLAGS_writePicturePath[0], gm->getName(),
1620                                              compareConfig.fName, "", pictureSuffix);
1621         SkFILEWStream stream(path.c_str());
1622         pict->serialize(&stream);
1623     }
1624
1625     if (FLAGS_rtree) {
1626         const char renderModeDescriptor[] = "-rtree";
1627         if ((gmFlags & GM::kSkipPicture_Flag) || (gmFlags & GM::kSkipTiled_Flag)) {
1628             gmmain.RecordTestResults(kIntentionallySkipped_ErrorType, shortNamePlusConfig,
1629                                      renderModeDescriptor);
1630             errorsForAllModes.add(kIntentionallySkipped_ErrorType);
1631         } else {
1632             SkPicture* pict = gmmain.generate_new_picture(gm, kRTree_BbhType, 0);
1633             SkAutoUnref aur(pict);
1634             SkBitmap bitmap;
1635             gmmain.generate_image_from_picture(gm, compareConfig, pict, &bitmap);
1636             errorsForAllModes.add(gmmain.compare_test_results_to_reference_bitmap(
1637                 gm->getName(), compareConfig.fName, renderModeDescriptor, bitmap,
1638                 &comparisonBitmap));
1639         }
1640     }
1641
1642     if (FLAGS_tileGrid) {
1643         for(int scaleIndex = 0; scaleIndex < tileGridReplayScales.count(); ++scaleIndex) {
1644             SkScalar replayScale = tileGridReplayScales[scaleIndex];
1645             SkString renderModeDescriptor("-tilegrid");
1646             if (SK_Scalar1 != replayScale) {
1647                 renderModeDescriptor += "-scale-";
1648                 renderModeDescriptor.appendScalar(replayScale);
1649             }
1650
1651             if ((gmFlags & GM::kSkipPicture_Flag) ||
1652                 (gmFlags & GM::kSkipTiled_Flag) ||
1653                 ((gmFlags & GM::kSkipScaledReplay_Flag) && replayScale != 1)) {
1654                 gmmain.RecordTestResults(kIntentionallySkipped_ErrorType, shortNamePlusConfig,
1655                                          renderModeDescriptor.c_str());
1656                 errorsForAllModes.add(kIntentionallySkipped_ErrorType);
1657             } else {
1658                 // We record with the reciprocal scale to obtain a replay
1659                 // result that can be validated against comparisonBitmap.
1660                 SkScalar recordScale = SkScalarInvert(replayScale);
1661                 SkPicture* pict = gmmain.generate_new_picture(
1662                     gm, kTileGrid_BbhType, 0, recordScale);
1663                 SkAutoUnref aur(pict);
1664                 SkBitmap bitmap;
1665                 // We cannot yet pass 'true' to generate_image_from_picture to
1666                 // perform actual tiled rendering (see Issue 1198 -
1667                 // https://code.google.com/p/skia/issues/detail?id=1198)
1668                 gmmain.generate_image_from_picture(gm, compareConfig, pict, &bitmap,
1669                                                    replayScale /*, true */);
1670                 errorsForAllModes.add(gmmain.compare_test_results_to_reference_bitmap(
1671                     gm->getName(), compareConfig.fName, renderModeDescriptor.c_str(), bitmap,
1672                     &comparisonBitmap));
1673             }
1674         }
1675     }
1676
1677     // run the pipe centric GM steps
1678     if (FLAGS_pipe) {
1679         errorsForAllModes.add(gmmain.test_pipe_playback(gm, compareConfig, comparisonBitmap,
1680                                                         FLAGS_simulatePipePlaybackFailure));
1681         if (FLAGS_tiledPipe) {
1682             errorsForAllModes.add(gmmain.test_tiled_pipe_playback(gm, compareConfig,
1683                                                                   comparisonBitmap));
1684         }
1685     }
1686     return errorsForAllModes;
1687 }
1688
1689
1690 /**
1691  * Run this test in a number of different configs (8888, 565, PDF,
1692  * etc.), confirming that the resulting bitmaps match expectations
1693  * (which may be different for each config).
1694  *
1695  * Returns all errors encountered while doing so.
1696  */
1697 ErrorCombination run_multiple_configs(GMMain &gmmain, GM *gm,
1698                                       const SkTDArray<size_t> &configs,
1699                                       const SkTDArray<const PDFRasterizerData*> &pdfRasterizers,
1700                                       const SkTDArray<SkScalar> &tileGridReplayScales,
1701                                       GrContextFactory *grFactory,
1702                                       GrGLStandard gpuAPI);
1703 ErrorCombination run_multiple_configs(GMMain &gmmain, GM *gm,
1704                                       const SkTDArray<size_t> &configs,
1705                                       const SkTDArray<const PDFRasterizerData*> &pdfRasterizers,
1706                                       const SkTDArray<SkScalar> &tileGridReplayScales,
1707                                       GrContextFactory *grFactory,
1708                                       GrGLStandard gpuAPI) {
1709     const char renderModeDescriptor[] = "";
1710     ErrorCombination errorsForAllConfigs;
1711     uint32_t gmFlags = gm->getFlags();
1712
1713     for (int i = 0; i < configs.count(); i++) {
1714         ConfigData config = gRec[configs[i]];
1715         const SkString shortNamePlusConfig = gmmain.make_shortname_plus_config(gm->getName(),
1716                                                                                config.fName);
1717
1718         // Skip any tests that we don't even need to try.
1719         // If any of these were skipped on a per-GM basis, record them as
1720         // kIntentionallySkipped.
1721         if (kPDF_Backend == config.fBackend) {
1722             if (gmFlags & GM::kSkipPDF_Flag) {
1723                 gmmain.RecordSkippedTest(shortNamePlusConfig,
1724                                          renderModeDescriptor,
1725                                          config.fBackend);
1726                 errorsForAllConfigs.add(kIntentionallySkipped_ErrorType);
1727                 continue;
1728             }
1729         }
1730         if ((gmFlags & GM::kSkip565_Flag) &&
1731             (kRaster_Backend == config.fBackend) &&
1732             (kRGB_565_SkColorType == config.fColorType)) {
1733             gmmain.RecordSkippedTest(shortNamePlusConfig,
1734                                      renderModeDescriptor,
1735                                      config.fBackend);
1736             errorsForAllConfigs.add(kIntentionallySkipped_ErrorType);
1737             continue;
1738         }
1739         if (((gmFlags & GM::kSkipGPU_Flag) && kGPU_Backend == config.fBackend) ||
1740             ((gmFlags & GM::kGPUOnly_Flag) && kGPU_Backend != config.fBackend)) {
1741             gmmain.RecordSkippedTest(shortNamePlusConfig,
1742                                      renderModeDescriptor,
1743                                      config.fBackend);
1744             errorsForAllConfigs.add(kIntentionallySkipped_ErrorType);
1745             continue;
1746         }
1747
1748         // Now we know that we want to run this test and record its
1749         // success or failure.
1750         ErrorCombination errorsForThisConfig;
1751         GrSurface* gpuTarget = NULL;
1752 #if SK_SUPPORT_GPU
1753         SkAutoTUnref<GrSurface> auGpuTarget;
1754         if ((errorsForThisConfig.isEmpty()) && (kGPU_Backend == config.fBackend)) {
1755             if (FLAGS_resetGpuContext) {
1756                 grFactory->destroyContexts();
1757             }
1758             GrContext* gr = grFactory->get(config.fGLContextType, gpuAPI);
1759             bool grSuccess = false;
1760             if (gr) {
1761                 // create a render target to back the device
1762                 GrSurfaceDesc desc;
1763                 desc.fConfig = kSkia8888_GrPixelConfig;
1764                 desc.fFlags = kRenderTarget_GrSurfaceFlag;
1765                 desc.fWidth = gm->getISize().width();
1766                 desc.fHeight = gm->getISize().height();
1767                 desc.fSampleCnt = config.fSampleCnt;
1768                 auGpuTarget.reset(gr->createUncachedTexture(desc, NULL, 0));
1769                 if (auGpuTarget) {
1770                     gpuTarget = auGpuTarget;
1771                     grSuccess = true;
1772                     // Set the user specified cache limits if non-default.
1773                     size_t bytes;
1774                     int count;
1775                     gr->getResourceCacheLimits(&count, &bytes);
1776                     if (DEFAULT_CACHE_VALUE != gGpuCacheSizeBytes) {
1777                         bytes = static_cast<size_t>(gGpuCacheSizeBytes);
1778                     }
1779                     if (DEFAULT_CACHE_VALUE != gGpuCacheSizeCount) {
1780                         count = gGpuCacheSizeCount;
1781                     }
1782                     gr->setResourceCacheLimits(count, bytes);
1783                 }
1784             }
1785             if (!grSuccess) {
1786                 errorsForThisConfig.add(kNoGpuContext_ErrorType);
1787             }
1788         }
1789 #endif
1790
1791         SkBitmap comparisonBitmap;
1792
1793         const char* writePath;
1794         if (FLAGS_writePath.count() == 1) {
1795             writePath = FLAGS_writePath[0];
1796         } else {
1797             writePath = NULL;
1798         }
1799
1800         if (errorsForThisConfig.isEmpty()) {
1801             errorsForThisConfig.add(gmmain.test_drawing(gm, config, pdfRasterizers,
1802                                                         writePath, gpuTarget,
1803                                                         &comparisonBitmap));
1804             gmmain.RecordTestResults(errorsForThisConfig, shortNamePlusConfig, "");
1805         }
1806
1807         // TODO: run only if gmmain.test_drawing succeeded.
1808         if (kRaster_Backend == config.fBackend) {
1809             run_multiple_modes(gmmain, gm, config, comparisonBitmap, tileGridReplayScales);
1810         }
1811
1812         if (FLAGS_deferred && errorsForThisConfig.isEmpty() &&
1813             (kGPU_Backend == config.fBackend || kRaster_Backend == config.fBackend)) {
1814             errorsForThisConfig.add(gmmain.test_deferred_drawing(gm, config, comparisonBitmap,
1815                                                                  gpuTarget));
1816         }
1817
1818         errorsForAllConfigs.add(errorsForThisConfig);
1819     }
1820     return errorsForAllConfigs;
1821 }
1822
1823
1824 /**
1825  * Read individual lines from a file, pushing them into the given array.
1826  *
1827  * @param filename path to the file to read
1828  * @param lines array of strings to add the lines to
1829  * @returns true if able to read lines from the file
1830  */
1831 static bool read_lines_from_file(const char* filename, SkTArray<SkString> &lines) {
1832     SkAutoTUnref<SkStream> streamWrapper(SkStream::NewFromFile(filename));
1833     SkStream *stream = streamWrapper.get();
1834     if (!stream) {
1835         SkDebugf("unable to read file '%s'\n", filename);
1836         return false;
1837     }
1838
1839     char c;
1840     SkString line;
1841     while (1 == stream->read(&c, 1)) {
1842         // If we hit either CR or LF, we've completed a line.
1843         //
1844         // TODO: If the file uses both CR and LF, this will return an extra blank
1845         // line for each line of the file.  Which is OK for current purposes...
1846         //
1847         // TODO: Does this properly handle unicode?  It doesn't matter for
1848         // current purposes...
1849         if ((c == 0x0d) || (c == 0x0a)) {
1850             lines.push_back(line);
1851             line.reset();
1852         } else {
1853             line.append(&c, 1);
1854         }
1855     }
1856     lines.push_back(line);
1857     return true;
1858 }
1859
1860 /**
1861  * Return a list of all entries in an array of strings as a single string
1862  * of this form:
1863  * "item1", "item2", "item3"
1864  */
1865 SkString list_all(const SkTArray<SkString> &stringArray);
1866 SkString list_all(const SkTArray<SkString> &stringArray) {
1867     SkString total;
1868     for (int i = 0; i < stringArray.count(); i++) {
1869         if (i > 0) {
1870             total.append(", ");
1871         }
1872         total.append("\"");
1873         total.append(stringArray[i]);
1874         total.append("\"");
1875     }
1876     return total;
1877 }
1878
1879 /**
1880  * Return a list of configuration names, as a single string of this form:
1881  * "item1", "item2", "item3"
1882  *
1883  * @param configs configurations, as a list of indices into gRec
1884  */
1885 SkString list_all_config_names(const SkTDArray<size_t> &configs);
1886 SkString list_all_config_names(const SkTDArray<size_t> &configs) {
1887     SkString total;
1888     for (int i = 0; i < configs.count(); i++) {
1889         if (i > 0) {
1890             total.append(", ");
1891         }
1892         total.append("\"");
1893         total.append(gRec[configs[i]].fName);
1894         total.append("\"");
1895     }
1896     return total;
1897 }
1898
1899 static bool prepare_subdirectories(const char *root, bool useFileHierarchy,
1900                                    const SkTDArray<size_t> &configs,
1901                                    const SkTDArray<const PDFRasterizerData*>& pdfRasterizers) {
1902     if (!sk_mkdir(root)) {
1903         return false;
1904     }
1905     if (useFileHierarchy) {
1906         for (int i = 0; i < configs.count(); i++) {
1907             ConfigData config = gRec[configs[i]];
1908             SkString subdir;
1909             subdir.appendf("%s%c%s", root, SkPATH_SEPARATOR, config.fName);
1910             if (!sk_mkdir(subdir.c_str())) {
1911                 return false;
1912             }
1913
1914             if (config.fBackend == kPDF_Backend) {
1915                 for (int j = 0; j < pdfRasterizers.count(); j++) {
1916                     SkString pdfSubdir = subdir;
1917                     pdfSubdir.appendf("-%s", pdfRasterizers[j]->fName);
1918                     if (!sk_mkdir(pdfSubdir.c_str())) {
1919                         return false;
1920                     }
1921                 }
1922             }
1923         }
1924     }
1925     return true;
1926 }
1927
1928 static bool parse_flags_configs(SkTDArray<size_t>* outConfigs,
1929                          GrContextFactory* grFactory, GrGLStandard gpuAPI) {
1930     SkTDArray<size_t> excludeConfigs;
1931
1932     for (int i = 0; i < FLAGS_config.count(); i++) {
1933         const char* config = FLAGS_config[i];
1934         bool exclude = false;
1935         if (*config == kExcludeConfigChar) {
1936             exclude = true;
1937             config += 1;
1938         }
1939         int index = findConfig(config);
1940         if (index >= 0) {
1941             if (exclude) {
1942                 *excludeConfigs.append() = index;
1943             } else {
1944                 appendUnique<size_t>(outConfigs, index);
1945             }
1946         } else if (0 == strcmp(kDefaultsConfigStr, config)) {
1947             if (exclude) {
1948                 SkDebugf("%c%s is not allowed.\n",
1949                          kExcludeConfigChar, kDefaultsConfigStr);
1950                 return false;
1951             }
1952             for (size_t c = 0; c < SK_ARRAY_COUNT(gRec); ++c) {
1953                 if (gRec[c].fRunByDefault) {
1954                     appendUnique<size_t>(outConfigs, c);
1955                 }
1956             }
1957         } else {
1958             SkDebugf("unrecognized config %s\n", config);
1959             return false;
1960         }
1961     }
1962
1963     for (int i = 0; i < FLAGS_excludeConfig.count(); i++) {
1964         int index = findConfig(FLAGS_excludeConfig[i]);
1965         if (index >= 0) {
1966             *excludeConfigs.append() = index;
1967         } else {
1968             SkDebugf("unrecognized excludeConfig %s\n", FLAGS_excludeConfig[i]);
1969             return false;
1970         }
1971     }
1972
1973     if (outConfigs->count() == 0) {
1974         // if no config is specified by user, add the defaults
1975         for (size_t i = 0; i < SK_ARRAY_COUNT(gRec); ++i) {
1976             if (gRec[i].fRunByDefault) {
1977                 *outConfigs->append() = i;
1978             }
1979         }
1980     }
1981     // now remove any explicitly excluded configs
1982     for (int i = 0; i < excludeConfigs.count(); ++i) {
1983         int index = outConfigs->find(excludeConfigs[i]);
1984         if (index >= 0) {
1985             outConfigs->remove(index);
1986             // now assert that there was only one copy in configs[]
1987             SkASSERT(outConfigs->find(excludeConfigs[i]) < 0);
1988         }
1989     }
1990
1991     for (int i = 0; i < outConfigs->count(); ++i) {
1992         size_t index = (*outConfigs)[i];
1993         if (kGPU_Backend == gRec[index].fBackend) {
1994 #if SK_SUPPORT_GPU
1995             if (!FLAGS_gpu) {
1996                 outConfigs->remove(i);
1997                 --i;
1998                 continue;
1999             }
2000 #endif
2001         } else if (!FLAGS_cpu) {
2002             outConfigs->remove(i);
2003             --i;
2004             continue;
2005         }
2006 #if SK_SUPPORT_GPU
2007         SkASSERT(grFactory != NULL);
2008         if (kGPU_Backend == gRec[index].fBackend) {
2009             GrContext* ctx = grFactory->get(gRec[index].fGLContextType, gpuAPI);
2010             if (NULL == ctx) {
2011                 SkDebugf("GrContext could not be created for config %s. Config will be skipped.\n",
2012                          gRec[index].fName);
2013                 outConfigs->remove(i);
2014                 --i;
2015                 continue;
2016             }
2017             if (gRec[index].fSampleCnt > ctx->getMaxSampleCount()) {
2018                 SkDebugf("Sample count (%d) of config %s is not supported."
2019                          " Config will be skipped.\n",
2020                          gRec[index].fSampleCnt, gRec[index].fName);
2021                 outConfigs->remove(i);
2022                 --i;
2023             }
2024         }
2025 #endif
2026     }
2027
2028     if (outConfigs->isEmpty()) {
2029         SkDebugf("No configs to run.");
2030         return false;
2031     }
2032
2033     // now show the user the set of configs that will be run.
2034     SkString configStr("These configs will be run:");
2035     // show the user the config that will run.
2036     for (int i = 0; i < outConfigs->count(); ++i) {
2037         configStr.appendf(" %s", gRec[(*outConfigs)[i]].fName);
2038     }
2039     SkDebugf("%s\n", configStr.c_str());
2040
2041     return true;
2042 }
2043
2044 static bool parse_flags_pdf_rasterizers(const SkTDArray<size_t>& configs,
2045                                         SkTDArray<const PDFRasterizerData*>* outRasterizers) {
2046     // No need to run this check (and display the PDF rasterizers message)
2047     // if no PDF backends are in the configs.
2048     bool configHasPDF = false;
2049     for (int i = 0; i < configs.count(); i++) {
2050         if (gRec[configs[i]].fBackend == kPDF_Backend) {
2051             configHasPDF = true;
2052             break;
2053         }
2054     }
2055     if (!configHasPDF) {
2056         return true;
2057     }
2058
2059     if (FLAGS_pdfRasterizers.count() == 1 &&
2060             !strcmp(FLAGS_pdfRasterizers[0], "default")) {
2061         for (int i = 0; i < (int)SK_ARRAY_COUNT(kPDFRasterizers); ++i) {
2062             if (kPDFRasterizers[i].fRunByDefault) {
2063                 *outRasterizers->append() = &kPDFRasterizers[i];
2064             }
2065         }
2066     } else {
2067         for (int i = 0; i < FLAGS_pdfRasterizers.count(); i++) {
2068             const char* rasterizer = FLAGS_pdfRasterizers[i];
2069             const PDFRasterizerData* rasterizerPtr =
2070                     findPDFRasterizer(rasterizer);
2071             if (rasterizerPtr == NULL) {
2072                 SkDebugf("unrecognized rasterizer %s\n", rasterizer);
2073                 return false;
2074             }
2075             appendUnique<const PDFRasterizerData*>(outRasterizers,
2076                                                    rasterizerPtr);
2077         }
2078     }
2079
2080     // now show the user the set of configs that will be run.
2081     SkString configStr("These PDF rasterizers will be run:");
2082     // show the user the config that will run.
2083     for (int i = 0; i < outRasterizers->count(); ++i) {
2084         configStr.appendf(" %s", (*outRasterizers)[i]->fName);
2085     }
2086     SkDebugf("%s\n", configStr.c_str());
2087
2088     return true;
2089 }
2090
2091 static bool parse_flags_ignore_error_types(ErrorCombination* outErrorTypes) {
2092     if (FLAGS_ignoreErrorTypes.count() > 0) {
2093         *outErrorTypes = ErrorCombination();
2094         for (int i = 0; i < FLAGS_ignoreErrorTypes.count(); i++) {
2095             ErrorType type;
2096             const char *name = FLAGS_ignoreErrorTypes[i];
2097             if (!getErrorTypeByName(name, &type)) {
2098                 SkDebugf("cannot find ErrorType with name '%s'\n", name);
2099                 return false;
2100             } else {
2101                 outErrorTypes->add(type);
2102             }
2103         }
2104     }
2105     return true;
2106 }
2107
2108 /**
2109  * Replace contents of ignoreTestNames with a list of test names, indicating
2110  * which tests' failures should be ignored.
2111  */
2112 static bool parse_flags_ignore_tests(SkTArray<SkString> &ignoreTestNames) {
2113     ignoreTestNames.reset();
2114
2115     // Parse --ignoreFailuresFile
2116     for (int i = 0; i < FLAGS_ignoreFailuresFile.count(); i++) {
2117         SkTArray<SkString> linesFromFile;
2118         if (!read_lines_from_file(FLAGS_ignoreFailuresFile[i], linesFromFile)) {
2119             return false;
2120         } else {
2121             for (int j = 0; j < linesFromFile.count(); j++) {
2122                 SkString thisLine = linesFromFile[j];
2123                 if (thisLine.isEmpty() || thisLine.startsWith('#')) {
2124                     // skip this line
2125                 } else {
2126                     ignoreTestNames.push_back(thisLine);
2127                 }
2128             }
2129         }
2130     }
2131
2132     return true;
2133 }
2134
2135 static bool parse_flags_modulo(int* moduloRemainder, int* moduloDivisor) {
2136     if (FLAGS_modulo.count() == 2) {
2137         *moduloRemainder = atoi(FLAGS_modulo[0]);
2138         *moduloDivisor = atoi(FLAGS_modulo[1]);
2139         if (*moduloRemainder < 0 || *moduloDivisor <= 0 ||
2140                 *moduloRemainder >= *moduloDivisor) {
2141             SkDebugf("invalid modulo values.");
2142             return false;
2143         }
2144     }
2145     return true;
2146 }
2147
2148 #if SK_SUPPORT_GPU
2149 static bool parse_flags_gpu_cache(int* sizeBytes, int* sizeCount) {
2150     if (FLAGS_gpuCacheSize.count() > 0) {
2151         if (FLAGS_gpuCacheSize.count() != 2) {
2152             SkDebugf("--gpuCacheSize requires two arguments\n");
2153             return false;
2154         }
2155         *sizeBytes = atoi(FLAGS_gpuCacheSize[0]);
2156         *sizeCount = atoi(FLAGS_gpuCacheSize[1]);
2157     } else {
2158         *sizeBytes = DEFAULT_CACHE_VALUE;
2159         *sizeCount = DEFAULT_CACHE_VALUE;
2160     }
2161     return true;
2162 }
2163
2164 static bool parse_flags_gl_standard(GrGLStandard* gpuAPI) {
2165     if (0 == FLAGS_gpuAPI.count()) {
2166         *gpuAPI = kNone_GrGLStandard;
2167         return true;
2168     }
2169     if (1 == FLAGS_gpuAPI.count()) {
2170         if (FLAGS_gpuAPI.contains(kGpuAPINameGL)) {
2171             *gpuAPI = kGL_GrGLStandard;
2172             return true;
2173         }
2174         if (FLAGS_gpuAPI.contains(kGpuAPINameGLES)) {
2175             *gpuAPI = kGLES_GrGLStandard;
2176             return true;
2177         }
2178     }
2179     SkDebugf("--gpuAPI invalid api value");
2180     return false;
2181 }
2182 #endif
2183
2184 static bool parse_flags_tile_grid_replay_scales(SkTDArray<SkScalar>* outScales) {
2185     *outScales->append() = SK_Scalar1; // By default only test at scale 1.0
2186     if (FLAGS_tileGridReplayScales.count() > 0) {
2187         outScales->reset();
2188         for (int i = 0; i < FLAGS_tileGridReplayScales.count(); i++) {
2189             double val = atof(FLAGS_tileGridReplayScales[i]);
2190             if (0 < val) {
2191                 *outScales->append() = SkDoubleToScalar(val);
2192             }
2193         }
2194         if (0 == outScales->count()) {
2195             // Should have at least one scale
2196             SkDebugf("--tileGridReplayScales requires at least one scale.\n");
2197             return false;
2198         }
2199     }
2200     return true;
2201 }
2202
2203 static bool parse_flags_gmmain_paths(GMMain* gmmain) {
2204     gmmain->fUseFileHierarchy = FLAGS_hierarchy;
2205     gmmain->fWriteChecksumBasedFilenames = FLAGS_writeChecksumBasedFilenames;
2206
2207     if (FLAGS_mismatchPath.count() == 1) {
2208         gmmain->fMismatchPath = FLAGS_mismatchPath[0];
2209     }
2210
2211     if (FLAGS_missingExpectationsPath.count() == 1) {
2212         gmmain->fMissingExpectationsPath = FLAGS_missingExpectationsPath[0];
2213     }
2214
2215     if (FLAGS_readPath.count() == 1) {
2216         const char* readPath = FLAGS_readPath[0];
2217         if (!sk_exists(readPath)) {
2218             SkDebugf("readPath %s does not exist!\n", readPath);
2219             return false;
2220         }
2221         if (sk_isdir(readPath)) {
2222             if (FLAGS_verbose) {
2223                 SkDebugf("reading from %s\n", readPath);
2224             }
2225             gmmain->fExpectationsSource.reset(SkNEW_ARGS(
2226                 IndividualImageExpectationsSource, (readPath)));
2227         } else {
2228             if (FLAGS_verbose) {
2229                 SkDebugf("reading expectations from JSON summary file %s\n", readPath);
2230             }
2231             gmmain->fExpectationsSource.reset(SkNEW_ARGS(JsonExpectationsSource, (readPath)));
2232         }
2233     }
2234     return true;
2235 }
2236
2237 static bool parse_flags_jpeg_quality() {
2238     if (FLAGS_pdfJpegQuality < -1 || FLAGS_pdfJpegQuality > 100) {
2239         SkDebugf("%s\n", "pdfJpegQuality must be in [-1 .. 100] range.");
2240         return false;
2241     }
2242     return true;
2243 }
2244
2245 int tool_main(int argc, char** argv);
2246 int tool_main(int argc, char** argv) {
2247     SetupCrashHandler();
2248
2249     SkString usage;
2250     usage.printf("Run the golden master tests.\n");
2251     SkCommandLineFlags::SetUsage(usage.c_str());
2252     SkCommandLineFlags::Parse(argc, argv);
2253
2254 #if SK_ENABLE_INST_COUNT
2255     if (FLAGS_leaks) {
2256         gPrintInstCount = true;
2257     }
2258 #endif
2259
2260     SkGraphics::Init();
2261
2262     setSystemPreferences();
2263     GMMain gmmain;
2264
2265     SkTDArray<size_t> configs;
2266
2267     int moduloRemainder = -1;
2268     int moduloDivisor = -1;
2269     SkTDArray<const PDFRasterizerData*> pdfRasterizers;
2270     SkTDArray<SkScalar> tileGridReplayScales;
2271 #if SK_SUPPORT_GPU
2272     GrGLStandard gpuAPI = kNone_GrGLStandard;
2273     GrContext::Options grContextOpts;
2274     grContextOpts.fDrawPathToCompressedTexture = FLAGS_gpuCompressAlphaMasks;
2275     GrContextFactory* grFactory = new GrContextFactory(grContextOpts);
2276 #else
2277     GrGLStandard gpuAPI = 0;
2278     GrContextFactory* grFactory = NULL;
2279 #endif
2280
2281     if (FLAGS_dryRun) {
2282         SkDebugf( "Doing a dry run; no tests will actually be executed.\n");
2283     }
2284
2285     if (!parse_flags_modulo(&moduloRemainder, &moduloDivisor) ||
2286         !parse_flags_ignore_error_types(&gmmain.fIgnorableErrorTypes) ||
2287         !parse_flags_ignore_tests(gmmain.fIgnorableTestNames) ||
2288 #if SK_SUPPORT_GPU
2289         !parse_flags_gpu_cache(&gGpuCacheSizeBytes, &gGpuCacheSizeCount) ||
2290         !parse_flags_gl_standard(&gpuAPI) ||
2291 #endif
2292         !parse_flags_tile_grid_replay_scales(&tileGridReplayScales) ||
2293         !parse_flags_jpeg_quality() ||
2294         !parse_flags_configs(&configs, grFactory, gpuAPI) ||
2295         !parse_flags_pdf_rasterizers(configs, &pdfRasterizers) ||
2296         !parse_flags_gmmain_paths(&gmmain)) {
2297         return -1;
2298     }
2299
2300     if (FLAGS_verbose) {
2301         if (FLAGS_writePath.count() == 1) {
2302             SkDebugf("writing to %s\n", FLAGS_writePath[0]);
2303         }
2304         if (gmmain.fMismatchPath) {
2305             SkDebugf("writing mismatches to %s\n", gmmain.fMismatchPath);
2306         }
2307         if (gmmain.fMissingExpectationsPath) {
2308             SkDebugf("writing images without expectations to %s\n",
2309                      gmmain.fMissingExpectationsPath);
2310         }
2311         if (FLAGS_writePicturePath.count() == 1) {
2312             SkDebugf("writing pictures to %s\n", FLAGS_writePicturePath[0]);
2313         }
2314         if (!GetResourcePath().isEmpty()) {
2315             SkDebugf("reading resources from %s\n", GetResourcePath().c_str());
2316         }
2317     }
2318
2319     int gmsRun = 0;
2320     int gmIndex = -1;
2321     SkString moduloStr;
2322
2323     if (!FLAGS_dryRun) {
2324         // If we will be writing out files, prepare subdirectories.
2325         if (FLAGS_writePath.count() == 1) {
2326             if (!prepare_subdirectories(FLAGS_writePath[0], gmmain.fUseFileHierarchy,
2327                                         configs, pdfRasterizers)) {
2328                 return -1;
2329             }
2330         }
2331         if (gmmain.fMismatchPath) {
2332             if (!prepare_subdirectories(gmmain.fMismatchPath, gmmain.fUseFileHierarchy,
2333                                         configs, pdfRasterizers)) {
2334                 return -1;
2335             }
2336         }
2337         if (gmmain.fMissingExpectationsPath) {
2338             if (!prepare_subdirectories(gmmain.fMissingExpectationsPath, gmmain.fUseFileHierarchy,
2339                                         configs, pdfRasterizers)) {
2340                 return -1;
2341             }
2342         }
2343     }
2344     Iter iter;
2345     GM* gm;
2346     while ((gm = iter.next()) != NULL) {
2347         if (FLAGS_forcePerspectiveMatrix) {
2348             SkMatrix perspective;
2349             perspective.setIdentity();
2350             perspective.setPerspY(SkScalarDiv(SK_Scalar1, SkIntToScalar(1000)));
2351             perspective.setSkewX(SkScalarDiv(SkIntToScalar(8),
2352                                  SkIntToScalar(25)));
2353
2354             gm->setStarterMatrix(perspective);
2355         }
2356         SkAutoTDelete<GM> adgm(gm);
2357         ++gmIndex;
2358         if (moduloRemainder >= 0) {
2359             if ((gmIndex % moduloDivisor) != moduloRemainder) {
2360                 continue;
2361             }
2362             moduloStr.printf("[%d.%d] ", gmIndex, moduloDivisor);
2363         }
2364
2365         const char* shortName = gm->getName();
2366
2367         if (SkCommandLineFlags::ShouldSkip(FLAGS_match, shortName)) {
2368             continue;
2369         }
2370
2371         gmsRun++;
2372         SkISize size = gm->getISize();
2373         SkDebugf("%4dM %sdrawing... %s [%d %d]\n",
2374                  sk_tools::getMaxResidentSetSizeMB(), moduloStr.c_str(), shortName,
2375                  size.width(), size.height());
2376         if (!FLAGS_dryRun)
2377             run_multiple_configs(gmmain, gm, configs, pdfRasterizers, tileGridReplayScales,
2378                                  grFactory, gpuAPI);
2379     }
2380
2381     if (FLAGS_dryRun)
2382         return 0;
2383
2384     SkTArray<SkString> modes;
2385     gmmain.GetRenderModesEncountered(modes);
2386     int modeCount = modes.count();
2387
2388     // Now that we have run all the tests and thus know the full set of renderModes that we
2389     // tried to run, we can call RecordTestResults() to record the cases in which we skipped
2390     // ALL renderModes.
2391     // See http://skbug.com/1994 and https://codereview.chromium.org/129203002/
2392     int testCount = gmmain.fTestsSkippedOnAllRenderModes.count();
2393     for (int testNum = 0; testNum < testCount; ++testNum) {
2394         const SkString &shortNamePlusConfig = gmmain.fTestsSkippedOnAllRenderModes[testNum];
2395         for (int modeNum = 0; modeNum < modeCount; ++modeNum) {
2396             gmmain.RecordTestResults(kIntentionallySkipped_ErrorType, shortNamePlusConfig,
2397                                      modes[modeNum].c_str());
2398         }
2399     }
2400
2401     bool reportError = false;
2402     if (gmmain.NumSignificantErrors() > 0) {
2403         reportError = true;
2404     }
2405
2406     // We test every GM against every config, and for every raster config also test every mode.
2407     int rasterConfigs = 0;
2408     for (int i = 0; i < configs.count(); i++) {
2409         if (gRec[configs[i]].fBackend == kRaster_Backend) {
2410             rasterConfigs++;
2411         }
2412     }
2413     // For raster configs, we run all renderModes; for non-raster configs, just default renderMode
2414     const int expectedNumberOfTests = rasterConfigs * gmsRun * modeCount
2415                                     + (configs.count() - rasterConfigs) * gmsRun;
2416
2417     // Output summary to stdout.
2418     if (FLAGS_verbose) {
2419         SkDebugf("Ran %d GMs\n", gmsRun);
2420         SkDebugf("... over %2d configs [%s]\n", configs.count(),
2421                  list_all_config_names(configs).c_str());
2422         SkDebugf("...  and %2d modes   [%s]\n", modeCount, list_all(modes).c_str());
2423         SkDebugf("... so there should be a total of %d tests.\n", expectedNumberOfTests);
2424     }
2425     gmmain.ListErrors(FLAGS_verbose);
2426
2427     // TODO(epoger): Enable this check for Android, too, once we resolve
2428     // https://code.google.com/p/skia/issues/detail?id=1222
2429     // ('GM is unexpectedly skipping tests on Android')
2430 #ifndef SK_BUILD_FOR_ANDROID
2431     if (expectedNumberOfTests != gmmain.fTestsRun) {
2432         SkDebugf("expected %d tests, but ran or skipped %d tests\n",
2433                  expectedNumberOfTests, gmmain.fTestsRun);
2434         reportError = true;
2435     }
2436 #endif
2437
2438     if (FLAGS_writeJsonSummaryPath.count() == 1) {
2439         Json::Value root = CreateJsonTree(
2440             gmmain.fJsonExpectedResults,
2441             gmmain.fJsonActualResults_Failed, gmmain.fJsonActualResults_FailureIgnored,
2442             gmmain.fJsonActualResults_NoComparison, gmmain.fJsonActualResults_Succeeded);
2443         std::string jsonStdString = root.toStyledString();
2444         SkFILEWStream stream(FLAGS_writeJsonSummaryPath[0]);
2445         stream.write(jsonStdString.c_str(), jsonStdString.length());
2446     }
2447
2448 #if SK_SUPPORT_GPU
2449
2450 #if GR_CACHE_STATS
2451     for (int i = 0; i < configs.count(); i++) {
2452         ConfigData config = gRec[configs[i]];
2453
2454         if (FLAGS_verbose && (kGPU_Backend == config.fBackend)) {
2455             GrContext* gr = grFactory->get(config.fGLContextType, gpuAPI);
2456
2457             SkDebugf("config: %s %x\n", config.fName, gr);
2458             gr->printCacheStats();
2459         }
2460     }
2461 #endif
2462
2463 #if GR_DUMP_FONT_CACHE
2464     for (int i = 0; i < configs.count(); i++) {
2465         ConfigData config = gRec[configs[i]];
2466
2467         if (kGPU_Backend == config.fBackend) {
2468             GrContext* gr = grFactory->get(config.fGLContextType, gpuAPI);
2469
2470            gr->dumpFontCache();
2471         }
2472     }
2473 #endif
2474
2475     delete grFactory;
2476 #endif
2477     SkGraphics::Term();
2478
2479     return (reportError) ? -1 : 0;
2480 }
2481
2482 void GMMain::installFilter(SkCanvas* canvas) {
2483     if (FLAGS_forceBWtext) {
2484         canvas->setDrawFilter(SkNEW(BWTextDrawFilter))->unref();
2485     }
2486 }
2487
2488 #if !defined(SK_BUILD_FOR_IOS) && !defined(SK_BUILD_FOR_NACL)
2489 int main(int argc, char * const argv[]) {
2490     return tool_main(argc, (char**) argv);
2491 }
2492 #endif