11cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger/*
21cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Copyright 2011 Google Inc.
31cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger *
41cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * Use of this source code is governed by a BSD-style license that can be
51cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger * found in the LICENSE file.
61cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger */
71cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
8e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed#include "gm.h"
94f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger#include "system_preferences.h"
101cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#include "GrContext.h"
111cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#include "GrRenderTarget.h"
121cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
13e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed#include "SkColorPriv.h"
141cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#include "SkData.h"
154f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger#include "SkDeferredCanvas.h"
161cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#include "SkDevice.h"
171cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#include "SkGpuCanvas.h"
181cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#include "SkGpuDevice.h"
19e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed#include "SkGraphics.h"
20e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed#include "SkImageDecoder.h"
21e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed#include "SkImageEncoder.h"
224f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger#include "gl/SkNativeGLContext.h"
234f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger#include "gl/SkMesaGLContext.h"
2435e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger#include "SkPicture.h"
2540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger#include "SkStream.h"
2640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger#include "SkRefCnt.h"
2740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
281cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic bool gForceBWtext;
291cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
301cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerextern bool gSkSuppressFontCachePurgeSpew;
3140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
3240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger#ifdef SK_SUPPORT_PDF
3335e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    #include "SkPDFDevice.h"
3435e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    #include "SkPDFDocument.h"
3540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger#endif
36e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed
374f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger// Until we resolve http://code.google.com/p/skia/issues/detail?id=455 ,
384f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger// stop writing out XPS-format image baselines in gm.
394f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger#undef SK_SUPPORT_XPS
401cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#ifdef SK_SUPPORT_XPS
411cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    #include "SkXPSDevice.h"
421cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#endif
431cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
441cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#ifdef SK_BUILD_FOR_MAC
451cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    #include "SkCGUtils.h"
461cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    #define CAN_IMAGE_PDF   1
471cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#else
481cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    #define CAN_IMAGE_PDF   0
491cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#endif
501cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
511cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergertypedef int ErrorBitfield;
521cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerconst static ErrorBitfield ERROR_NONE                    = 0x00;
531cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerconst static ErrorBitfield ERROR_NO_GPU_CONTEXT          = 0x01;
541cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerconst static ErrorBitfield ERROR_PIXEL_MISMATCH          = 0x02;
551cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerconst static ErrorBitfield ERROR_DIMENSION_MISMATCH      = 0x04;
561cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerconst static ErrorBitfield ERROR_READING_REFERENCE_IMAGE = 0x08;
571cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerconst static ErrorBitfield ERROR_WRITING_REFERENCE_IMAGE = 0x10;
58e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed
591cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerusing namespace skiagm;
60e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed
61e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reedclass Iter {
62e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reedpublic:
63e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed    Iter() {
641cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        this->reset();
651cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
661cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
671cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    void reset() {
68e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed        fReg = GMRegistry::Head();
69e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed    }
7040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
71e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed    GM* next() {
72e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed        if (fReg) {
73e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed            GMRegistry::Factory fact = fReg->factory();
74e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed            fReg = fReg->next();
75e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed            return fact(0);
76e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed        }
77e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed        return NULL;
78e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed    }
7940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
80e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed    static int Count() {
81e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed        const GMRegistry* reg = GMRegistry::Head();
82e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed        int count = 0;
83e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed        while (reg) {
84e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed            count += 1;
85e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed            reg = reg->next();
86e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed        }
87e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed        return count;
88e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed    }
8940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
90e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reedprivate:
91e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed    const GMRegistry* fReg;
92e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed};
93e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed
94e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reedstatic SkString make_name(const char shortName[], const char configName[]) {
95e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed    SkString name(shortName);
96e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed    name.appendf("_%s", configName);
97e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed    return name;
98e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed}
99e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed
10035e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenbergerstatic SkString make_filename(const char path[],
10135e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger                              const char pathSuffix[],
10235e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger                              const SkString& name,
10335e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger                              const char suffix[]) {
104e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed    SkString filename(path);
10535e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    if (filename.endsWith("/")) {
10635e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        filename.remove(filename.size() - 1, 1);
107e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed    }
10835e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    filename.append(pathSuffix);
10935e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    filename.append("/");
11040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    filename.appendf("%s.%s", name.c_str(), suffix);
111e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed    return filename;
112e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed}
113e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed
114e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed/* since PNG insists on unpremultiplying our alpha, we take no precision chances
115e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed    and force all pixels to be 100% opaque, otherwise on compare we may not get
116e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed    a perfect match.
117e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed */
118e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reedstatic void force_all_opaque(const SkBitmap& bitmap) {
119e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed    SkAutoLockPixels lock(bitmap);
120e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed    for (int y = 0; y < bitmap.height(); y++) {
121e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed        for (int x = 0; x < bitmap.width(); x++) {
122e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed            *bitmap.getAddr32(x, y) |= (SK_A32_MASK << SK_A32_SHIFT);
123e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed        }
124e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed    }
125e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed}
126e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed
127e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reedstatic bool write_bitmap(const SkString& path, const SkBitmap& bitmap) {
128e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed    SkBitmap copy;
129e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed    bitmap.copyTo(&copy, SkBitmap::kARGB_8888_Config);
130e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed    force_all_opaque(copy);
131e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed    return SkImageEncoder::EncodeFile(path.c_str(), copy,
132e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed                                      SkImageEncoder::kPNG_Type, 100);
133e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed}
134e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed
13540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerstatic inline SkPMColor compute_diff_pmcolor(SkPMColor c0, SkPMColor c1) {
13635e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    int dr = SkGetPackedR32(c0) - SkGetPackedR32(c1);
13735e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    int dg = SkGetPackedG32(c0) - SkGetPackedG32(c1);
13835e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    int db = SkGetPackedB32(c0) - SkGetPackedB32(c1);
13935e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    return SkPackARGB32(0xFF, SkAbs32(dr), SkAbs32(dg), SkAbs32(db));
14040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger}
14140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
14240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerstatic void compute_diff(const SkBitmap& target, const SkBitmap& base,
14335e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger                         SkBitmap* diff) {
14435e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    SkAutoLockPixels alp(*diff);
14540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
14640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    const int w = target.width();
14740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    const int h = target.height();
14840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    for (int y = 0; y < h; y++) {
14940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        for (int x = 0; x < w; x++) {
15040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            SkPMColor c0 = *base.getAddr32(x, y);
15140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            SkPMColor c1 = *target.getAddr32(x, y);
15235e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger            SkPMColor d = 0;
15335e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger            if (c0 != c1) {
15435e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger                d = compute_diff_pmcolor(c0, c1);
15535e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger            }
15635e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger            *diff->getAddr32(x, y) = d;
15735e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        }
15835e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    }
15940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger}
16040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
1611cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic ErrorBitfield compare(const SkBitmap& target, const SkBitmap& base,
1621cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                             const SkString& name,
1631cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                             const char* renderModeDescriptor,
1641cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                             SkBitmap* diff) {
165e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed    SkBitmap copy;
166e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed    const SkBitmap* bm = &target;
167e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed    if (target.config() != SkBitmap::kARGB_8888_Config) {
168e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed        target.copyTo(&copy, SkBitmap::kARGB_8888_Config);
169e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed        bm = &copy;
170e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed    }
1711cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkBitmap baseCopy;
1721cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    const SkBitmap* bp = &base;
1731cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (base.config() != SkBitmap::kARGB_8888_Config) {
1741cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        base.copyTo(&baseCopy, SkBitmap::kARGB_8888_Config);
1751cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        bp = &baseCopy;
1761cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
177e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed
178e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed    force_all_opaque(*bm);
1791cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    force_all_opaque(*bp);
180e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed
181e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed    const int w = bm->width();
182e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed    const int h = bm->height();
1831cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (w != bp->width() || h != bp->height()) {
1840199fa7423f89a129da2b22a488f2c18e2e4727fDerek Sollenberger        SkDebugf(
1850199fa7423f89a129da2b22a488f2c18e2e4727fDerek Sollenberger"---- %s dimensions mismatch for %s base [%d %d] current [%d %d]\n",
1860199fa7423f89a129da2b22a488f2c18e2e4727fDerek Sollenberger                 renderModeDescriptor, name.c_str(),
1871cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                 bp->width(), bp->height(), w, h);
1881cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        return ERROR_DIMENSION_MISMATCH;
189e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed    }
190e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed
191e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed    SkAutoLockPixels bmLock(*bm);
1921cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkAutoLockPixels baseLock(*bp);
193e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed
194e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed    for (int y = 0; y < h; y++) {
195e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed        for (int x = 0; x < w; x++) {
1961cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            SkPMColor c0 = *bp->getAddr32(x, y);
197e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed            SkPMColor c1 = *bm->getAddr32(x, y);
198e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed            if (c0 != c1) {
1990199fa7423f89a129da2b22a488f2c18e2e4727fDerek Sollenberger                SkDebugf(
2000199fa7423f89a129da2b22a488f2c18e2e4727fDerek Sollenberger"----- %s pixel mismatch for %s at [%d %d] base 0x%08X current 0x%08X\n",
2010199fa7423f89a129da2b22a488f2c18e2e4727fDerek Sollenberger                         renderModeDescriptor, name.c_str(), x, y, c0, c1);
20235e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
20335e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger                if (diff) {
20435e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger                    diff->setConfig(SkBitmap::kARGB_8888_Config, w, h);
20535e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger                    diff->allocPixels();
2061cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                    compute_diff(*bm, *bp, diff);
20735e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger                }
2081cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                return ERROR_PIXEL_MISMATCH;
209e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed            }
210e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed        }
211e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed    }
21240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
21335e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    // they're equal
2141cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    return ERROR_NONE;
21540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger}
21640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
2171cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic bool write_document(const SkString& path,
2181cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                           const SkDynamicMemoryWStream& document) {
21940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    SkFILEWStream stream(path.c_str());
2201cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkAutoDataUnref data(document.copyToData());
2211cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    return stream.writeData(data.get());
222e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed}
223e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed
22440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenbergerenum Backend {
22540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger  kRaster_Backend,
22640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger  kGPU_Backend,
22740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger  kPDF_Backend,
2281cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger  kXPS_Backend,
22940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger};
23040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
23135e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenbergerstruct ConfigData {
23235e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    SkBitmap::Config    fConfig;
23340528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    Backend             fBackend;
23435e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    const char*         fName;
23535e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger};
23635e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
23735e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger/// Returns true if processing should continue, false to skip the
23835e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger/// remainder of this config for this GM.
23935e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger//@todo thudson 22 April 2011 - could refactor this to take in
24035e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger// a factory to generate the context, always call readPixels()
24135e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger// (logically a noop for rasters, if wasted time), and thus collapse the
24235e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger// GPU special case and also let this be used for SkPicture testing.
24335e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenbergerstatic void setup_bitmap(const ConfigData& gRec, SkISize& size,
24435e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger                         SkBitmap* bitmap) {
24535e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    bitmap->setConfig(gRec.fConfig, size.width(), size.height());
24635e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    bitmap->allocPixels();
24735e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    bitmap->eraseColor(0);
24835e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger}
24935e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
2501cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#include "SkDrawFilter.h"
2511cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerclass BWTextDrawFilter : public SkDrawFilter {
2521cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerpublic:
2531cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    virtual void filter(SkPaint*, Type) SK_OVERRIDE;
2541cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger};
2551cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergervoid BWTextDrawFilter::filter(SkPaint* p, Type t) {
2561cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (kText_Type == t) {
2571cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        p->setAntiAlias(false);
2581cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
2591cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
2601cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
2611cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic void installFilter(SkCanvas* canvas) {
2621cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (gForceBWtext) {
2631cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        canvas->setDrawFilter(new BWTextDrawFilter)->unref();
2641cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
2651cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
2661cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
2671cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic void invokeGM(GM* gm, SkCanvas* canvas) {
2681cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    installFilter(canvas);
2691cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    gm->draw(canvas);
2701cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    canvas->setDrawFilter(NULL);
2711cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
2721cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
2731cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic ErrorBitfield generate_image(GM* gm, const ConfigData& gRec,
2741cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                    GrContext* context,
2751cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                    GrRenderTarget* rt,
2764f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                    SkBitmap* bitmap,
2774f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                    bool deferred) {
27835e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    SkISize size (gm->getISize());
2791cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    setup_bitmap(gRec, size, bitmap);
28035e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
28135e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    if (gRec.fBackend == kRaster_Backend) {
2824f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        SkCanvas* canvas;
2834f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        if (deferred) {
2844f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            canvas = new SkDeferredCanvas;
2854f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            canvas->setDevice(new SkDevice(*bitmap))->unref();
2864f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        } else {
2874f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            canvas = new SkCanvas(*bitmap);
2884f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        }
2894f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        SkAutoUnref canvasUnref(canvas);
2904f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        invokeGM(gm, canvas);
2914f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        canvas->flush();
29235e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    } else {  // GPU
29335e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        if (NULL == context) {
2941cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            return ERROR_NO_GPU_CONTEXT;
29535e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        }
2964f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        SkCanvas* gc;
2974f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        if (deferred) {
2984f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            gc = new SkDeferredCanvas;
2994f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        } else {
3004f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            gc = new SkGpuCanvas(context, rt);
3014f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        }
3024f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        SkAutoUnref gcUnref(gc);
3034f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        gc->setDevice(new SkGpuDevice(context, rt))->unref();
3044f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        invokeGM(gm, gc);
3051cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        // the device is as large as the current rendertarget, so we explicitly
3061cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        // only readback the amount we expect (in size)
3071cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        // overwrite our previous allocation
3081cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        bitmap->setConfig(SkBitmap::kARGB_8888_Config, size.fWidth,
3091cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                                       size.fHeight);
3104f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        gc->readPixels(bitmap, 0, 0);
31135e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    }
3121cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    return ERROR_NONE;
31335e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger}
31435e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
31535e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenbergerstatic void generate_image_from_picture(GM* gm, const ConfigData& gRec,
31635e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger                                        SkPicture* pict, SkBitmap* bitmap) {
31735e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    SkISize size = gm->getISize();
31835e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    setup_bitmap(gRec, size, bitmap);
31935e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    SkCanvas canvas(*bitmap);
3201cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    installFilter(&canvas);
32135e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    canvas.drawPicture(*pict);
32235e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger}
32335e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
32435e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenbergerstatic void generate_pdf(GM* gm, SkDynamicMemoryWStream& pdf) {
32535e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger#ifdef SK_SUPPORT_PDF
32635e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    SkISize size = gm->getISize();
32735e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    SkMatrix identity;
32835e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    identity.reset();
32935e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    SkPDFDevice* dev = new SkPDFDevice(size, size, identity);
33035e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    SkAutoUnref aur(dev);
33135e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
33235e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    SkCanvas c(dev);
3331cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    invokeGM(gm, &c);
33435e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
33535e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    SkPDFDocument doc;
33635e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    doc.appendPage(dev);
33735e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    doc.emitPDF(&pdf);
33835e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger#endif
33935e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger}
34035e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
3411cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic void generate_xps(GM* gm, SkDynamicMemoryWStream& xps) {
3421cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#ifdef SK_SUPPORT_XPS
3431cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkISize size = gm->getISize();
3441cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
3451cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkSize trimSize = SkSize::Make(SkIntToScalar(size.width()),
3461cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                   SkIntToScalar(size.height()));
3471cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    static const SkScalar inchesPerMeter = SkScalarDiv(10000, 254);
3481cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    static const SkScalar upm = 72 * inchesPerMeter;
3491cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkVector unitsPerMeter = SkPoint::Make(upm, upm);
3501cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    static const SkScalar ppm = 200 * inchesPerMeter;
3511cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkVector pixelsPerMeter = SkPoint::Make(ppm, ppm);
3521cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
3531cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkXPSDevice* dev = new SkXPSDevice();
3541cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkAutoUnref aur(dev);
3551cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
3561cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkCanvas c(dev);
3571cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    dev->beginPortfolio(&xps);
3581cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    dev->beginSheet(unitsPerMeter, pixelsPerMeter, trimSize);
3591cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    invokeGM(gm, &c);
3601cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    dev->endSheet();
3611cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    dev->endPortfolio();
3621cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
3631cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#endif
3641cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
3651cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
3661cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic ErrorBitfield write_reference_image(const ConfigData& gRec,
3671cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                           const char writePath [],
3681cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                           const char renderModeDescriptor [],
3691cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                           const SkString& name,
3701cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                           SkBitmap& bitmap,
3711cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                           SkDynamicMemoryWStream* document) {
37235e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    SkString path;
37335e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    bool success = false;
3741cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (gRec.fBackend == kRaster_Backend ||
3751cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        gRec.fBackend == kGPU_Backend ||
3761cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        (gRec.fBackend == kPDF_Backend && CAN_IMAGE_PDF)) {
3771cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
3780199fa7423f89a129da2b22a488f2c18e2e4727fDerek Sollenberger        path = make_filename(writePath, renderModeDescriptor, name, "png");
37935e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        success = write_bitmap(path, bitmap);
3801cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
3811cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (kPDF_Backend == gRec.fBackend) {
3820199fa7423f89a129da2b22a488f2c18e2e4727fDerek Sollenberger        path = make_filename(writePath, renderModeDescriptor, name, "pdf");
3831cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        success = write_document(path, *document);
38435e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    }
3851cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (kXPS_Backend == gRec.fBackend) {
3861cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        path = make_filename(writePath, renderModeDescriptor, name, "xps");
3871cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        success = write_document(path, *document);
3881cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
3891cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (success) {
3901cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        return ERROR_NONE;
3911cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    } else {
39235e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        fprintf(stderr, "FAILED to write %s\n", path.c_str());
3931cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        return ERROR_WRITING_REFERENCE_IMAGE;
39435e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    }
39535e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger}
39635e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
3971cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic ErrorBitfield compare_to_reference_image(const SkString& name,
3981cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                                SkBitmap &bitmap,
3991cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                                const SkBitmap& comparisonBitmap,
4001cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                                const char diffPath [],
4011cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                                const char renderModeDescriptor []) {
4021cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    ErrorBitfield errors;
4031cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkBitmap diffBitmap;
4041cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    errors = compare(bitmap, comparisonBitmap, name, renderModeDescriptor,
4051cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                     diffPath ? &diffBitmap : NULL);
4061cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if ((ERROR_NONE == errors) && diffPath) {
4071cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        SkString diffName = make_filename(diffPath, "", name, ".diff.png");
4081cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        if (!write_bitmap(diffName, diffBitmap)) {
4091cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            errors |= ERROR_WRITING_REFERENCE_IMAGE;
4101cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        }
4111cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
4121cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    return errors;
4131cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
4141cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
4151cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic ErrorBitfield compare_to_reference_image(const char readPath [],
4161cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                                const SkString& name,
4171cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                                SkBitmap &bitmap,
4181cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                                const char diffPath [],
4191cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                                const char renderModeDescriptor []) {
42035e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    SkString path = make_filename(readPath, "", name, "png");
42135e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    SkBitmap orig;
4221cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (SkImageDecoder::DecodeFile(path.c_str(), &orig,
4231cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                   SkBitmap::kARGB_8888_Config,
4241cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                   SkImageDecoder::kDecodePixels_Mode, NULL)) {
4251cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        return compare_to_reference_image(name, bitmap,
4261cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                          orig, diffPath,
4271cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                          renderModeDescriptor);
42835e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    } else {
42935e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        fprintf(stderr, "FAILED to read %s\n", path.c_str());
4301cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        return ERROR_READING_REFERENCE_IMAGE;
43135e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    }
43235e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger}
43335e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
4341cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic ErrorBitfield handle_test_results(GM* gm,
4351cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                         const ConfigData& gRec,
4361cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                         const char writePath [],
4371cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                         const char readPath [],
4381cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                         const char diffPath [],
4391cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                         const char renderModeDescriptor [],
4401cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                         SkBitmap& bitmap,
4411cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                         SkDynamicMemoryWStream* pdf,
4421cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                         const SkBitmap* comparisonBitmap) {
44335e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    SkString name = make_name(gm->shortName(), gRec.fName);
44435e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
44535e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    if (writePath) {
4461cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        return write_reference_image(gRec, writePath, renderModeDescriptor,
4471cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                     name, bitmap, pdf);
4481cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    } else if (readPath && (
4491cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                   gRec.fBackend == kRaster_Backend ||
4501cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                   gRec.fBackend == kGPU_Backend ||
4511cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                   (gRec.fBackend == kPDF_Backend && CAN_IMAGE_PDF))) {
45235e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        return compare_to_reference_image(readPath, name, bitmap,
4530199fa7423f89a129da2b22a488f2c18e2e4727fDerek Sollenberger                                   diffPath, renderModeDescriptor);
4541cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    } else if (comparisonBitmap) {
4551cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        return compare_to_reference_image(name, bitmap,
4561cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                   *comparisonBitmap, diffPath,
4571cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                   renderModeDescriptor);
4581cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    } else {
4591cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        return ERROR_NONE;
46035e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    }
46135e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger}
46235e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
46335e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenbergerstatic SkPicture* generate_new_picture(GM* gm) {
46435e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    // Pictures are refcounted so must be on heap
46535e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    SkPicture* pict = new SkPicture;
46635e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    SkCanvas* cv = pict->beginRecording(1000, 1000);
4671cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    invokeGM(gm, cv);
46835e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    pict->endRecording();
46935e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
47035e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    return pict;
47135e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger}
47235e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
47335e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenbergerstatic SkPicture* stream_to_new_picture(const SkPicture& src) {
47435e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
47535e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    // To do in-memory commiunications with a stream, we need to:
47635e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    // * create a dynamic memory stream
47735e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    // * copy it into a buffer
47835e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    // * create a read stream from it
47935e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    // ?!?!
48035e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
48135e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    SkDynamicMemoryWStream storage;
48235e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    src.serialize(&storage);
48335e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
48435e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    int streamSize = storage.getOffset();
48535e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    SkAutoMalloc dstStorage(streamSize);
48635e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    void* dst = dstStorage.get();
48735e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    //char* dst = new char [streamSize];
48835e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    //@todo thudson 22 April 2011 when can we safely delete [] dst?
48935e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    storage.copyTo(dst);
49035e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    SkMemoryStream pictReadback(dst, streamSize);
49135e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    SkPicture* retval = new SkPicture (&pictReadback);
49235e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    return retval;
49335e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger}
49435e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
49535e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger// Test: draw into a bitmap or pdf.
49635e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger// Depending on flags, possibly compare to an expected image
49735e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger// and possibly output a diff image if it fails to match.
4981cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic ErrorBitfield test_drawing(GM* gm,
4991cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                  const ConfigData& gRec,
5001cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                  const char writePath [],
5011cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                  const char readPath [],
5021cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                  const char diffPath [],
5031cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                  GrContext* context,
5041cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                  GrRenderTarget* rt,
5051cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                  SkBitmap* bitmap) {
5061cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkDynamicMemoryWStream document;
50735e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
50835e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    if (gRec.fBackend == kRaster_Backend ||
5091cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        gRec.fBackend == kGPU_Backend) {
5101cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        // Early exit if we can't generate the image.
5114f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        ErrorBitfield errors = generate_image(gm, gRec, context, rt, bitmap,
5124f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            false);
5131cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        if (ERROR_NONE != errors) {
5141cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            return errors;
51535e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        }
5161cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    } else if (gRec.fBackend == kPDF_Backend) {
5171cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        generate_pdf(gm, document);
5181cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#if CAN_IMAGE_PDF
5191cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        SkAutoDataUnref data(document.copyToData());
5201cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        SkMemoryStream stream(data.data(), data.size());
5211cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        SkPDFDocumentToBitmap(&stream, bitmap);
5221cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#endif
5231cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    } else if (gRec.fBackend == kXPS_Backend) {
5241cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        generate_xps(gm, document);
52535e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    }
52635e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    return handle_test_results(gm, gRec, writePath, readPath, diffPath,
5271cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                               "", *bitmap, &document, NULL);
52835e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger}
52935e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
5304f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenbergerstatic ErrorBitfield test_deferred_drawing(GM* gm,
5314f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                         const ConfigData& gRec,
5324f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                         const SkBitmap& comparisonBitmap,
5334f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                         const char diffPath [],
5344f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                         GrContext* context,
5354f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                         GrRenderTarget* rt) {
5364f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    SkDynamicMemoryWStream document;
5374f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
5384f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    if (gRec.fBackend == kRaster_Backend ||
5394f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        gRec.fBackend == kGPU_Backend) {
5404f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        SkBitmap bitmap;
5414f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        // Early exit if we can't generate the image, but this is
5424f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        // expected in some cases, so don't report a test failure.
5434f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        if (!generate_image(gm, gRec, context, rt, &bitmap, true)) {
5444f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            return ERROR_NONE;
5454f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        }
5464f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        return handle_test_results(gm, gRec, NULL, NULL, diffPath,
5474f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                   "-deferred", bitmap, NULL, &comparisonBitmap);
5484f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    }
5494f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    return ERROR_NONE;
5504f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger}
5514f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
5521cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic ErrorBitfield test_picture_playback(GM* gm,
5531cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                           const ConfigData& gRec,
5541cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                           const SkBitmap& comparisonBitmap,
5551cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                           const char readPath [],
5561cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                           const char diffPath []) {
55735e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    SkPicture* pict = generate_new_picture(gm);
55835e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    SkAutoUnref aur(pict);
55935e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
56035e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    if (kRaster_Backend == gRec.fBackend) {
56135e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        SkBitmap bitmap;
56235e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        generate_image_from_picture(gm, gRec, pict, &bitmap);
5631cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        return handle_test_results(gm, gRec, NULL, NULL, diffPath,
5641cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                            "-replay", bitmap, NULL, &comparisonBitmap);
5651cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    } else {
5661cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        return ERROR_NONE;
56735e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    }
56835e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger}
56935e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
5701cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic ErrorBitfield test_picture_serialization(GM* gm,
5711cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                                const ConfigData& gRec,
5721cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                                const SkBitmap& comparisonBitmap,
5731cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                                const char readPath [],
5741cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                                const char diffPath []) {
57535e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    SkPicture* pict = generate_new_picture(gm);
57635e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    SkAutoUnref aurp(pict);
57735e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    SkPicture* repict = stream_to_new_picture(*pict);
57835e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    SkAutoUnref aurr(repict);
57935e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
58035e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    if (kRaster_Backend == gRec.fBackend) {
58135e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        SkBitmap bitmap;
58235e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        generate_image_from_picture(gm, gRec, repict, &bitmap);
5831cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        return handle_test_results(gm, gRec, NULL, NULL, diffPath,
5841cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                            "-serialize", bitmap, NULL, &comparisonBitmap);
5851cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    } else {
5861cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        return ERROR_NONE;
58735e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    }
58835e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger}
58935e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
59035e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenbergerstatic void usage(const char * argv0) {
5914f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    SkDebugf(
5924f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        "%s [-w writePath] [-r readPath] [-d diffPath] [--noreplay]\n"
5934f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        "    [--serialize] [--forceBWtext] [--nopdf] [--nodeferred]\n"
5944f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        "    [--match substring] [--notexturecache]"
5954f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger#if SK_MESA
5964f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        " [--mesagl]"
5974f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger#endif
5984f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        "\n\n", argv0);
59935e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    SkDebugf("    writePath: directory to write rendered images in.\n");
60035e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    SkDebugf(
60135e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger"    readPath: directory to read reference images from;\n"
60235e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger"        reports if any pixels mismatch between reference and new images\n");
60335e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    SkDebugf("    diffPath: directory to write difference images in.\n");
6044f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    SkDebugf("    --noreplay: do not exercise SkPicture replay.\n");
60535e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    SkDebugf(
60635e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger"    --serialize: exercise SkPicture serialization & deserialization.\n");
6074f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    SkDebugf("    --forceBWtext: disable text anti-aliasing.\n");
6084f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    SkDebugf("    --nopdf: skip the pdf rendering test pass.\n");
6094f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    SkDebugf("    --nodeferred: skip the deferred rendering test pass.\n");
6101cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkDebugf("    --match foo will only run tests that substring match foo.\n");
6111cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#if SK_MESA
6121cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkDebugf("    --mesagl will run using the osmesa sw gl rasterizer.\n");
6131cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#endif
6144f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    SkDebugf("    --notexturecache: disable the gpu texture cache.\n");
61535e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger}
61635e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
61735e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenbergerstatic const ConfigData gRec[] = {
61840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    { SkBitmap::kARGB_8888_Config, kRaster_Backend, "8888" },
61940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    { SkBitmap::kARGB_4444_Config, kRaster_Backend, "4444" },
62040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    { SkBitmap::kRGB_565_Config,   kRaster_Backend, "565" },
6211cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#ifdef SK_SCALAR_IS_FLOAT
62240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    { SkBitmap::kARGB_8888_Config, kGPU_Backend,    "gpu" },
6231cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#endif
62440528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger#ifdef SK_SUPPORT_PDF
62540528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    { SkBitmap::kARGB_8888_Config, kPDF_Backend,    "pdf" },
62640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger#endif
6271cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#ifdef SK_SUPPORT_XPS
6281cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    { SkBitmap::kARGB_8888_Config, kXPS_Backend,    "xps" },
6291cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#endif
630e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed};
631e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed
6321cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic bool skip_name(const SkTDArray<const char*> array, const char name[]) {
6331cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (0 == array.count()) {
6341cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        // no names, so don't skip anything
6351cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        return false;
6361cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
6371cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    for (int i = 0; i < array.count(); ++i) {
6381cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        if (strstr(name, array[i])) {
6391cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            // found the name, so don't skip
6401cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            return false;
6411cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        }
6421cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
6431cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    return true;
6441cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
6451cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
6461cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergernamespace skiagm {
6471cab2921ab279367f8206cdadc9259d12e603548Derek Sollenbergerstatic GrContext* gGrContext;
6481cab2921ab279367f8206cdadc9259d12e603548Derek SollenbergerGrContext* GetGr() {
6491cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    return gGrContext;
6501cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
6511cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger}
6521cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
65335e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenbergerint main(int argc, char * const argv[]) {
654e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed    SkAutoGraphics ag;
6551cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    // we don't need to see this during a run
6561cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    gSkSuppressFontCachePurgeSpew = true;
65740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
6584f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    setSystemPreferences();
6594f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
660e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed    const char* writePath = NULL;   // if non-null, where we write the originals
661e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed    const char* readPath = NULL;    // if non-null, were we read from to compare
66235e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    const char* diffPath = NULL;    // if non-null, where we write our diffs (from compare)
663e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed
6641cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkTDArray<const char*> fMatches;
6654f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
6661cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    bool doPDF = true;
6670b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger    bool doReplay = true;
66835e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    bool doSerialize = false;
6691cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    bool useMesa = false;
6704f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    bool doDeferred = true;
6714f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    bool disableTextureCache = false;
6724f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
67335e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    const char* const commandName = argv[0];
674e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed    char* const* stop = argv + argc;
675e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed    for (++argv; argv < stop; ++argv) {
676e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed        if (strcmp(*argv, "-w") == 0) {
677e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed            argv++;
678e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed            if (argv < stop && **argv) {
679e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed                writePath = *argv;
680e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed            }
681e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed        } else if (strcmp(*argv, "-r") == 0) {
682e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed            argv++;
683e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed            if (argv < stop && **argv) {
684e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed                readPath = *argv;
685e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed            }
68640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        } else if (strcmp(*argv, "-d") == 0) {
68735e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger            argv++;
68840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            if (argv < stop && **argv) {
68940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger                diffPath = *argv;
69040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            }
6911cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        } else if (strcmp(*argv, "--forceBWtext") == 0) {
6921cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            gForceBWtext = true;
6930b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger        } else if (strcmp(*argv, "--noreplay") == 0) {
6940b15698a8c76bb8abc1b555c1d91892669b4118fDerek Sollenberger            doReplay = false;
6951cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        } else if (strcmp(*argv, "--nopdf") == 0) {
6961cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            doPDF = false;
6974f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        } else if (strcmp(*argv, "--nodeferred") == 0) {
6984f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            doDeferred = false;
69935e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        } else if (strcmp(*argv, "--serialize") == 0) {
70035e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger            doSerialize = true;
7011cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        } else if (strcmp(*argv, "--match") == 0) {
7021cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            ++argv;
7031cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            if (argv < stop && **argv) {
7041cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                // just record the ptr, no need for a deep copy
7051cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                *fMatches.append() = *argv;
7061cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            }
7071cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#if SK_MESA
7081cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        } else if (strcmp(*argv, "--mesagl") == 0) {
7091cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            useMesa = true;
7101cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#endif
7114f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        } else if (strcmp(*argv, "--notexturecache") == 0) {
7124f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger          disableTextureCache = true;
71335e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        } else {
71435e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger          usage(commandName);
71535e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger          return -1;
71635e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        }
71735e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    }
71835e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    if (argv != stop) {
71935e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger      usage(commandName);
72035e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger      return -1;
72135e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger    }
72240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
7231cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    int maxW = -1;
7241cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    int maxH = -1;
7251cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    Iter iter;
7261cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GM* gm;
7271cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    while ((gm = iter.next()) != NULL) {
7281cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        SkISize size = gm->getISize();
7291cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        maxW = SkMax32(size.width(), maxW);
7301cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        maxH = SkMax32(size.height(), maxH);
7311cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
73240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    // setup a GL context for drawing offscreen
7331cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    SkAutoTUnref<SkGLContext> glContext;
7341cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#if SK_MESA
7351cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (useMesa) {
7361cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        glContext.reset(new SkMesaGLContext());
7371cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    } else
7381cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger#endif
7391cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    {
7401cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        glContext.reset(new SkNativeGLContext());
741e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed    }
74240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
7431cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    GrPlatformRenderTargetDesc rtDesc;
7441cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    if (glContext.get()->init(maxW, maxH)) {
7451cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        GrPlatform3DContext ctx =
7461cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            reinterpret_cast<GrPlatform3DContext>(glContext.get()->gl());
7471cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        gGrContext = GrContext::Create(kOpenGL_Shaders_GrEngine, ctx);
7481cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        if (NULL != gGrContext) {
7491cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            rtDesc.fConfig = kSkia8888_PM_GrPixelConfig;
7501cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            rtDesc.fStencilBits = 8;
7511cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            rtDesc.fRenderTargetHandle = glContext.get()->getFBOID();
7521cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        }
7531cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    } else {
7541cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        fprintf(stderr, "could not create GL context.\n");
7551cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
75640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
75740528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    if (readPath) {
75840528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        fprintf(stderr, "reading from %s\n", readPath);
75940528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    } else if (writePath) {
76040528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger        fprintf(stderr, "writing to %s\n", writePath);
76140528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger    }
76240528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger
7631cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    // Accumulate success of all tests.
7641cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    int testsRun = 0;
7651cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    int testsPassed = 0;
7661cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    int testsFailed = 0;
7671cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    int testsMissingReferenceImages = 0;
7681cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
7694f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    if (disableTextureCache) {
7704f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger        skiagm::GetGr()->setTextureCacheLimits(0, 0);
7714f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger    }
7724f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
7731cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    iter.reset();
774e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed    while ((gm = iter.next()) != NULL) {
7751cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        const char* shortName = gm->shortName();
7761cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        if (skip_name(fMatches, shortName)) {
7771cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            SkDELETE(gm);
7781cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            continue;
7791cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        }
7801cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
78135e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        SkISize size = gm->getISize();
7821cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        SkDebugf("drawing... %s [%d %d]\n", shortName,
783e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed                 size.width(), size.height());
7841cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        SkBitmap forwardRenderedBitmap;
7851cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
7861cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        // Above we created an fbo for the context at maxW x maxH size.
7871cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        // Here we lie about the size of the rt. We claim it is the size
7881cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        // desired by the test. The reason is that rasterization may change
7891cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        // slightly when the viewport dimensions change. Previously, whenever
7901cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        // a new test was checked in that bumped maxW or maxH several images
7911cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        // would slightly change.
7921cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        rtDesc.fWidth = size.width();
7931cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        rtDesc.fHeight = size.height();
7941cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        SkAutoTUnref<GrRenderTarget> rt;
7951cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        if (gGrContext) {
7961cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            rt.reset(gGrContext->createPlatformRenderTarget(rtDesc));
7971cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        }
798e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed
79935e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger        for (size_t i = 0; i < SK_ARRAY_COUNT(gRec); i++) {
8001cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            // Skip any tests that we don't even need to try.
8011cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            uint32_t gmFlags = gm->getFlags();
8024f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            if ((kPDF_Backend == gRec[i].fBackend) &&
8031cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                (!doPDF || (gmFlags & GM::kSkipPDF_Flag)))
8041cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            {
8051cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                continue;
80640528743dbb9ce7f39f093e0cdc47849ac8887cfDerek Sollenberger            }
80735e2e62b55598210f6999fc2ea26ff8f41446ffeDerek Sollenberger
8081cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            // Now we know that we want to run this test and record its
8091cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            // success or failure.
8101cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            ErrorBitfield testErrors = ERROR_NONE;
8111cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger
8121cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            if ((ERROR_NONE == testErrors) &&
8131cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                (kGPU_Backend == gRec[i].fBackend) &&
8141cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                (NULL == rt.get())) {
8151cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                fprintf(stderr, "Could not create render target for gpu.\n");
8161cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                testErrors |= ERROR_NO_GPU_CONTEXT;
817e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed            }
818e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed
8191cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            if (ERROR_NONE == testErrors) {
8201cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                testErrors |= test_drawing(gm, gRec[i],
8211cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                           writePath, readPath, diffPath,
8221cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                           gGrContext,
8231cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                           rt.get(), &forwardRenderedBitmap);
8241cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            }
825e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed
8264f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            if (doDeferred && !testErrors &&
8274f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                (kGPU_Backend == gRec[i].fBackend ||
8284f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                kRaster_Backend == gRec[i].fBackend)) {
8294f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                testErrors |= test_deferred_drawing(gm, gRec[i],
8304f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                    forwardRenderedBitmap,
8314f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger                                    diffPath, gGrContext, rt.get());
8324f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger            }
8334f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger
8341cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            if ((ERROR_NONE == testErrors) && doReplay &&
8351cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                !(gmFlags & GM::kSkipPicture_Flag)) {
8361cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                testErrors |= test_picture_playback(gm, gRec[i],
8371cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                                    forwardRenderedBitmap,
8381cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                                    readPath, diffPath);
8391cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            }
840e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed
8411cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            if ((ERROR_NONE == testErrors) && doSerialize) {
8421cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                testErrors |= test_picture_serialization(gm, gRec[i],
8431cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                                         forwardRenderedBitmap,
8441cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                                                         readPath, diffPath);
8451cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            }
846e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed
8471cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            // Update overall results.
8481cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            // We only tabulate the particular error types that we currently
8491cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            // care about (e.g., missing reference images). Later on, if we
8501cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            // want to also tabulate pixel mismatches vs dimension mistmatches
8511cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            // (or whatever else), we can do so.
8521cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            testsRun++;
8531cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            if (ERROR_NONE == testErrors) {
8541cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                testsPassed++;
8551cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            } else if (ERROR_READING_REFERENCE_IMAGE & testErrors) {
8561cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                testsMissingReferenceImages++;
8571cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            } else {
8581cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger                testsFailed++;
8591cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger            }
8601cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        }
8611cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger        SkDELETE(gm);
8621cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    }
8631cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    printf("Ran %d tests: %d passed, %d failed, %d missing reference images\n",
8641cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger           testsRun, testsPassed, testsFailed, testsMissingReferenceImages);
8651cab2921ab279367f8206cdadc9259d12e603548Derek Sollenberger    return (0 == testsFailed) ? 0 : -1;
866e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed}
867