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(©, 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 = ⌖ 167e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed if (target.config() != SkBitmap::kARGB_8888_Config) { 168e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed target.copyTo(©, SkBitmap::kARGB_8888_Config); 169e32706edd70b0f847fe4d124a195cd2927dc8021Mike Reed bm = © 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