#include "SkData.h"
#include "SkDeferredCanvas.h"
#include "SkDevice.h"
+#include "SkDrawFilter.h"
#include "SkGPipe.h"
#include "SkGraphics.h"
#include "SkImageDecoder.h"
const GMRegistry* fReg;
};
-static SkString make_name(const char shortName[], const char configName[]) {
- SkString name(shortName);
- name.appendf("_%s", configName);
- return name;
-}
-
-static SkString make_filename(const char path[],
- const char pathSuffix[],
- const SkString& name,
- const char suffix[]) {
- SkString filename(path);
- if (filename.endsWith(PATH_SEPARATOR)) {
- filename.remove(filename.size() - 1, 1);
- }
- filename.append(pathSuffix);
- filename.append(PATH_SEPARATOR);
- filename.appendf("%s.%s", name.c_str(), suffix);
- return filename;
-}
-
-/* since PNG insists on unpremultiplying our alpha, we take no precision chances
- and force all pixels to be 100% opaque, otherwise on compare we may not get
- a perfect match.
- */
-static void force_all_opaque(const SkBitmap& bitmap) {
- SkAutoLockPixels lock(bitmap);
- for (int y = 0; y < bitmap.height(); y++) {
- for (int x = 0; x < bitmap.width(); x++) {
- *bitmap.getAddr32(x, y) |= (SK_A32_MASK << SK_A32_SHIFT);
- }
- }
-}
-
-static bool write_bitmap(const SkString& path, const SkBitmap& bitmap) {
- SkBitmap copy;
- bitmap.copyTo(©, SkBitmap::kARGB_8888_Config);
- force_all_opaque(copy);
- return SkImageEncoder::EncodeFile(path.c_str(), copy,
- SkImageEncoder::kPNG_Type, 100);
-}
-
-static inline SkPMColor compute_diff_pmcolor(SkPMColor c0, SkPMColor c1) {
- int dr = SkGetPackedR32(c0) - SkGetPackedR32(c1);
- int dg = SkGetPackedG32(c0) - SkGetPackedG32(c1);
- int db = SkGetPackedB32(c0) - SkGetPackedB32(c1);
- return SkPackARGB32(0xFF, SkAbs32(dr), SkAbs32(dg), SkAbs32(db));
-}
-
-static void compute_diff(const SkBitmap& target, const SkBitmap& base,
- SkBitmap* diff) {
- SkAutoLockPixels alp(*diff);
-
- const int w = target.width();
- const int h = target.height();
- for (int y = 0; y < h; y++) {
- for (int x = 0; x < w; x++) {
- SkPMColor c0 = *base.getAddr32(x, y);
- SkPMColor c1 = *target.getAddr32(x, y);
- SkPMColor d = 0;
- if (c0 != c1) {
- d = compute_diff_pmcolor(c0, c1);
- }
- *diff->getAddr32(x, y) = d;
- }
- }
-}
-
-// Compares "target" and "base" bitmaps, returning the result (ERROR_NONE
-// if the two bitmaps are identical).
-//
-// If a "diff" bitmap is passed in, pixel diffs (if any) will be written
-// into it.
-//
-// The "name" and "renderModeDescriptor" arguments are only used in the debug
-// output.
-static ErrorBitfield compare(const SkBitmap& target, const SkBitmap& base,
- const SkString& name,
- const char* renderModeDescriptor,
- SkBitmap* diff) {
- SkBitmap copy;
- const SkBitmap* bm = ⌖
- if (target.config() != SkBitmap::kARGB_8888_Config) {
- target.copyTo(©, SkBitmap::kARGB_8888_Config);
- bm = ©
- }
- SkBitmap baseCopy;
- const SkBitmap* bp = &base;
- if (base.config() != SkBitmap::kARGB_8888_Config) {
- base.copyTo(&baseCopy, SkBitmap::kARGB_8888_Config);
- bp = &baseCopy;
- }
-
- force_all_opaque(*bm);
- force_all_opaque(*bp);
-
- const int w = bm->width();
- const int h = bm->height();
- if (w != bp->width() || h != bp->height()) {
- SkDebugf(
-"---- %s dimensions mismatch for %s base [%d %d] current [%d %d]\n",
- renderModeDescriptor, name.c_str(),
- bp->width(), bp->height(), w, h);
- return ERROR_DIMENSION_MISMATCH;
- }
-
- SkAutoLockPixels bmLock(*bm);
- SkAutoLockPixels baseLock(*bp);
-
- for (int y = 0; y < h; y++) {
- for (int x = 0; x < w; x++) {
- SkPMColor c0 = *bp->getAddr32(x, y);
- SkPMColor c1 = *bm->getAddr32(x, y);
- if (c0 != c1) {
- SkDebugf(
-"----- %s pixel mismatch for %s at [%d %d] base 0x%08X current 0x%08X\n",
- renderModeDescriptor, name.c_str(), x, y, c0, c1);
-
- if (diff) {
- diff->setConfig(SkBitmap::kARGB_8888_Config, w, h);
- diff->allocPixels();
- compute_diff(*bm, *bp, diff);
- }
- return ERROR_PIXEL_MISMATCH;
- }
- }
- }
-
- // they're equal
- return ERROR_NONE;
-}
-
-static bool write_document(const SkString& path,
- const SkDynamicMemoryWStream& document) {
- SkFILEWStream stream(path.c_str());
- SkAutoDataUnref data(document.copyToData());
- return stream.writeData(data.get());
-}
-
enum Backend {
kRaster_Backend,
kGPU_Backend,
const char* fName;
};
-/// Returns true if processing should continue, false to skip the
-/// remainder of this config for this GM.
-//@todo thudson 22 April 2011 - could refactor this to take in
-// a factory to generate the context, always call readPixels()
-// (logically a noop for rasters, if wasted time), and thus collapse the
-// GPU special case and also let this be used for SkPicture testing.
-static void setup_bitmap(const ConfigData& gRec, SkISize& size,
- SkBitmap* bitmap) {
- bitmap->setConfig(gRec.fConfig, size.width(), size.height());
- bitmap->allocPixels();
- bitmap->eraseColor(0);
-}
-
-#include "SkDrawFilter.h"
class BWTextDrawFilter : public SkDrawFilter {
public:
virtual void filter(SkPaint*, Type) SK_OVERRIDE;
}
}
-static void installFilter(SkCanvas* canvas) {
- if (gForceBWtext) {
- canvas->setDrawFilter(new BWTextDrawFilter)->unref();
+struct PipeFlagComboData {
+ const char* name;
+ uint32_t flags;
+};
+
+static PipeFlagComboData gPipeWritingFlagCombos[] = {
+ { "", 0 },
+ { " cross-process", SkGPipeWriter::kCrossProcess_Flag },
+ { " cross-process, shared address", SkGPipeWriter::kCrossProcess_Flag
+ | SkGPipeWriter::kSharedAddressSpace_Flag }
+};
+
+
+class GMMain {
+public:
+ static SkString make_name(const char shortName[], const char configName[]) {
+ SkString name(shortName);
+ name.appendf("_%s", configName);
+ return name;
}
-}
-static void invokeGM(GM* gm, SkCanvas* canvas, bool isPDF = false) {
- SkAutoCanvasRestore acr(canvas, true);
+ static SkString make_filename(const char path[],
+ const char pathSuffix[],
+ const SkString& name,
+ const char suffix[]) {
+ SkString filename(path);
+ if (filename.endsWith(PATH_SEPARATOR)) {
+ filename.remove(filename.size() - 1, 1);
+ }
+ filename.append(pathSuffix);
+ filename.append(PATH_SEPARATOR);
+ filename.appendf("%s.%s", name.c_str(), suffix);
+ return filename;
+ }
- if (!isPDF) {
- canvas->concat(gm->getInitialTransform());
+ /* since PNG insists on unpremultiplying our alpha, we take no
+ precision chances and force all pixels to be 100% opaque,
+ otherwise on compare we may not get a perfect match.
+ */
+ static void force_all_opaque(const SkBitmap& bitmap) {
+ SkAutoLockPixels lock(bitmap);
+ for (int y = 0; y < bitmap.height(); y++) {
+ for (int x = 0; x < bitmap.width(); x++) {
+ *bitmap.getAddr32(x, y) |= (SK_A32_MASK << SK_A32_SHIFT);
+ }
+ }
}
- installFilter(canvas);
- gm->draw(canvas);
- canvas->setDrawFilter(NULL);
-}
-static ErrorBitfield generate_image(GM* gm, const ConfigData& gRec,
- GrContext* context,
- GrRenderTarget* rt,
- SkBitmap* bitmap,
- bool deferred) {
- SkISize size (gm->getISize());
- setup_bitmap(gRec, size, bitmap);
+ static bool write_bitmap(const SkString& path, const SkBitmap& bitmap) {
+ SkBitmap copy;
+ bitmap.copyTo(©, SkBitmap::kARGB_8888_Config);
+ force_all_opaque(copy);
+ return SkImageEncoder::EncodeFile(path.c_str(), copy,
+ SkImageEncoder::kPNG_Type, 100);
+ }
- SkAutoTUnref<SkCanvas> canvas;
+ static inline SkPMColor compute_diff_pmcolor(SkPMColor c0, SkPMColor c1) {
+ int dr = SkGetPackedR32(c0) - SkGetPackedR32(c1);
+ int dg = SkGetPackedG32(c0) - SkGetPackedG32(c1);
+ int db = SkGetPackedB32(c0) - SkGetPackedB32(c1);
+ return SkPackARGB32(0xFF, SkAbs32(dr), SkAbs32(dg), SkAbs32(db));
+ }
- if (gRec.fBackend == kRaster_Backend) {
- SkAutoTUnref<SkDevice> device(new SkDevice(*bitmap));
- if (deferred) {
- canvas.reset(new SkDeferredCanvas(device));
- } else {
- canvas.reset(new SkCanvas(device));
+ static void compute_diff(const SkBitmap& target, const SkBitmap& base,
+ SkBitmap* diff) {
+ SkAutoLockPixels alp(*diff);
+
+ const int w = target.width();
+ const int h = target.height();
+ for (int y = 0; y < h; y++) {
+ for (int x = 0; x < w; x++) {
+ SkPMColor c0 = *base.getAddr32(x, y);
+ SkPMColor c1 = *target.getAddr32(x, y);
+ SkPMColor d = 0;
+ if (c0 != c1) {
+ d = compute_diff_pmcolor(c0, c1);
+ }
+ *diff->getAddr32(x, y) = d;
+ }
}
- invokeGM(gm, canvas);
- canvas->flush();
}
-#if SK_SUPPORT_GPU
- else { // GPU
- if (NULL == context) {
- return ERROR_NO_GPU_CONTEXT;
+
+ // Compares "target" and "base" bitmaps, returning the result
+ // (ERROR_NONE if the two bitmaps are identical).
+ //
+ // If a "diff" bitmap is passed in, pixel diffs (if any) will be written
+ // into it.
+ //
+ // The "name" and "renderModeDescriptor" arguments are only used
+ // in the debug output.
+ static ErrorBitfield compare(const SkBitmap& target, const SkBitmap& base,
+ const SkString& name,
+ const char* renderModeDescriptor,
+ SkBitmap* diff) {
+ SkBitmap copy;
+ const SkBitmap* bm = ⌖
+ if (target.config() != SkBitmap::kARGB_8888_Config) {
+ target.copyTo(©, SkBitmap::kARGB_8888_Config);
+ bm = ©
}
- SkAutoTUnref<SkDevice> device(new SkGpuDevice(context, rt));
- if (deferred) {
- canvas.reset(new SkDeferredCanvas(device));
- } else {
- canvas.reset(new SkCanvas(device));
+ SkBitmap baseCopy;
+ const SkBitmap* bp = &base;
+ if (base.config() != SkBitmap::kARGB_8888_Config) {
+ base.copyTo(&baseCopy, SkBitmap::kARGB_8888_Config);
+ bp = &baseCopy;
+ }
+
+ force_all_opaque(*bm);
+ force_all_opaque(*bp);
+
+ const int w = bm->width();
+ const int h = bm->height();
+ if (w != bp->width() || h != bp->height()) {
+ SkDebugf(
+ "---- %s dimensions mismatch for %s base [%d %d] current [%d %d]\n",
+ renderModeDescriptor, name.c_str(),
+ bp->width(), bp->height(), w, h);
+ return ERROR_DIMENSION_MISMATCH;
}
- invokeGM(gm, canvas);
- // the device is as large as the current rendertarget, so we explicitly
- // only readback the amount we expect (in size)
- // overwrite our previous allocation
- bitmap->setConfig(SkBitmap::kARGB_8888_Config, size.fWidth,
- size.fHeight);
- canvas->readPixels(bitmap, 0, 0);
+
+ SkAutoLockPixels bmLock(*bm);
+ SkAutoLockPixels baseLock(*bp);
+
+ for (int y = 0; y < h; y++) {
+ for (int x = 0; x < w; x++) {
+ SkPMColor c0 = *bp->getAddr32(x, y);
+ SkPMColor c1 = *bm->getAddr32(x, y);
+ if (c0 != c1) {
+ SkDebugf(
+ "----- %s pixel mismatch for %s at [%d %d] base 0x%08X current 0x%08X\n",
+ renderModeDescriptor, name.c_str(), x, y, c0, c1);
+
+ if (diff) {
+ diff->setConfig(SkBitmap::kARGB_8888_Config, w, h);
+ diff->allocPixels();
+ compute_diff(*bm, *bp, diff);
+ }
+ return ERROR_PIXEL_MISMATCH;
+ }
+ }
+ }
+
+ // they're equal
+ return ERROR_NONE;
}
-#endif
- return ERROR_NONE;
-}
-static void generate_image_from_picture(GM* gm, const ConfigData& gRec,
- SkPicture* pict, SkBitmap* bitmap) {
- SkISize size = gm->getISize();
- setup_bitmap(gRec, size, bitmap);
- SkCanvas canvas(*bitmap);
- installFilter(&canvas);
- canvas.drawPicture(*pict);
-}
+ static bool write_document(const SkString& path,
+ const SkDynamicMemoryWStream& document) {
+ SkFILEWStream stream(path.c_str());
+ SkAutoDataUnref data(document.copyToData());
+ return stream.writeData(data.get());
+ }
-static void generate_pdf(GM* gm, SkDynamicMemoryWStream& pdf) {
-#ifdef SK_SUPPORT_PDF
- SkMatrix initialTransform = gm->getInitialTransform();
- SkISize pageSize = gm->getISize();
- SkPDFDevice* dev = NULL;
- if (initialTransform.isIdentity()) {
- dev = new SkPDFDevice(pageSize, pageSize, initialTransform);
- } else {
- SkRect content = SkRect::MakeWH(SkIntToScalar(pageSize.width()),
- SkIntToScalar(pageSize.height()));
- initialTransform.mapRect(&content);
- content.intersect(0, 0, SkIntToScalar(pageSize.width()),
- SkIntToScalar(pageSize.height()));
- SkISize contentSize =
- SkISize::Make(SkScalarRoundToInt(content.width()),
- SkScalarRoundToInt(content.height()));
- dev = new SkPDFDevice(pageSize, contentSize, initialTransform);
+ /// Returns true if processing should continue, false to skip the
+ /// remainder of this config for this GM.
+ //@todo thudson 22 April 2011 - could refactor this to take in
+ // a factory to generate the context, always call readPixels()
+ // (logically a noop for rasters, if wasted time), and thus collapse the
+ // GPU special case and also let this be used for SkPicture testing.
+ static void setup_bitmap(const ConfigData& gRec, SkISize& size,
+ SkBitmap* bitmap) {
+ bitmap->setConfig(gRec.fConfig, size.width(), size.height());
+ bitmap->allocPixels();
+ bitmap->eraseColor(0);
}
- SkAutoUnref aur(dev);
- SkCanvas c(dev);
- invokeGM(gm, &c, true);
+ static void installFilter(SkCanvas* canvas) {
+ if (gForceBWtext) {
+ canvas->setDrawFilter(new BWTextDrawFilter)->unref();
+ }
+ }
- SkPDFDocument doc;
- doc.appendPage(dev);
- doc.emitPDF(&pdf);
-#endif
-}
+ static void invokeGM(GM* gm, SkCanvas* canvas, bool isPDF = false) {
+ SkAutoCanvasRestore acr(canvas, true);
-static void generate_xps(GM* gm, SkDynamicMemoryWStream& xps) {
-#ifdef SK_SUPPORT_XPS
- SkISize size = gm->getISize();
-
- SkSize trimSize = SkSize::Make(SkIntToScalar(size.width()),
- SkIntToScalar(size.height()));
- static const SkScalar inchesPerMeter = SkScalarDiv(10000, 254);
- static const SkScalar upm = 72 * inchesPerMeter;
- SkVector unitsPerMeter = SkPoint::Make(upm, upm);
- static const SkScalar ppm = 200 * inchesPerMeter;
- SkVector pixelsPerMeter = SkPoint::Make(ppm, ppm);
-
- SkXPSDevice* dev = new SkXPSDevice();
- SkAutoUnref aur(dev);
-
- SkCanvas c(dev);
- dev->beginPortfolio(&xps);
- dev->beginSheet(unitsPerMeter, pixelsPerMeter, trimSize);
- invokeGM(gm, &c);
- dev->endSheet();
- dev->endPortfolio();
+ if (!isPDF) {
+ canvas->concat(gm->getInitialTransform());
+ }
+ installFilter(canvas);
+ gm->draw(canvas);
+ canvas->setDrawFilter(NULL);
+ }
-#endif
-}
+ static ErrorBitfield generate_image(GM* gm, const ConfigData& gRec,
+ GrContext* context,
+ GrRenderTarget* rt,
+ SkBitmap* bitmap,
+ bool deferred) {
+ SkISize size (gm->getISize());
+ setup_bitmap(gRec, size, bitmap);
+
+ SkAutoTUnref<SkCanvas> canvas;
-static ErrorBitfield write_reference_image(const ConfigData& gRec,
- const char writePath [],
- const char renderModeDescriptor [],
- const SkString& name,
- SkBitmap& bitmap,
- SkDynamicMemoryWStream* document) {
- SkString path;
- bool success = false;
- if (gRec.fBackend == kRaster_Backend ||
- gRec.fBackend == kGPU_Backend ||
- (gRec.fBackend == kPDF_Backend && CAN_IMAGE_PDF)) {
-
- path = make_filename(writePath, renderModeDescriptor, name, "png");
- success = write_bitmap(path, bitmap);
+ if (gRec.fBackend == kRaster_Backend) {
+ SkAutoTUnref<SkDevice> device(new SkDevice(*bitmap));
+ if (deferred) {
+ canvas.reset(new SkDeferredCanvas(device));
+ } else {
+ canvas.reset(new SkCanvas(device));
+ }
+ invokeGM(gm, canvas);
+ canvas->flush();
+ }
+#if SK_SUPPORT_GPU
+ else { // GPU
+ if (NULL == context) {
+ return ERROR_NO_GPU_CONTEXT;
+ }
+ SkAutoTUnref<SkDevice> device(new SkGpuDevice(context, rt));
+ if (deferred) {
+ canvas.reset(new SkDeferredCanvas(device));
+ } else {
+ canvas.reset(new SkCanvas(device));
+ }
+ invokeGM(gm, canvas);
+ // the device is as large as the current rendertarget, so
+ // we explicitly only readback the amount we expect (in
+ // size) overwrite our previous allocation
+ bitmap->setConfig(SkBitmap::kARGB_8888_Config, size.fWidth,
+ size.fHeight);
+ canvas->readPixels(bitmap, 0, 0);
+ }
+#endif
+ return ERROR_NONE;
}
- if (kPDF_Backend == gRec.fBackend) {
- path = make_filename(writePath, renderModeDescriptor, name, "pdf");
- success = write_document(path, *document);
+
+ static void generate_image_from_picture(GM* gm, const ConfigData& gRec,
+ SkPicture* pict, SkBitmap* bitmap) {
+ SkISize size = gm->getISize();
+ setup_bitmap(gRec, size, bitmap);
+ SkCanvas canvas(*bitmap);
+ installFilter(&canvas);
+ canvas.drawPicture(*pict);
}
- if (kXPS_Backend == gRec.fBackend) {
- path = make_filename(writePath, renderModeDescriptor, name, "xps");
- success = write_document(path, *document);
+
+ static void generate_pdf(GM* gm, SkDynamicMemoryWStream& pdf) {
+#ifdef SK_SUPPORT_PDF
+ SkMatrix initialTransform = gm->getInitialTransform();
+ SkISize pageSize = gm->getISize();
+ SkPDFDevice* dev = NULL;
+ if (initialTransform.isIdentity()) {
+ dev = new SkPDFDevice(pageSize, pageSize, initialTransform);
+ } else {
+ SkRect content = SkRect::MakeWH(SkIntToScalar(pageSize.width()),
+ SkIntToScalar(pageSize.height()));
+ initialTransform.mapRect(&content);
+ content.intersect(0, 0, SkIntToScalar(pageSize.width()),
+ SkIntToScalar(pageSize.height()));
+ SkISize contentSize =
+ SkISize::Make(SkScalarRoundToInt(content.width()),
+ SkScalarRoundToInt(content.height()));
+ dev = new SkPDFDevice(pageSize, contentSize, initialTransform);
+ }
+ SkAutoUnref aur(dev);
+
+ SkCanvas c(dev);
+ invokeGM(gm, &c, true);
+
+ SkPDFDocument doc;
+ doc.appendPage(dev);
+ doc.emitPDF(&pdf);
+#endif
}
- if (success) {
- return ERROR_NONE;
- } else {
- fprintf(stderr, "FAILED to write %s\n", path.c_str());
- return ERROR_WRITING_REFERENCE_IMAGE;
+
+ static void generate_xps(GM* gm, SkDynamicMemoryWStream& xps) {
+#ifdef SK_SUPPORT_XPS
+ SkISize size = gm->getISize();
+
+ SkSize trimSize = SkSize::Make(SkIntToScalar(size.width()),
+ SkIntToScalar(size.height()));
+ static const SkScalar inchesPerMeter = SkScalarDiv(10000, 254);
+ static const SkScalar upm = 72 * inchesPerMeter;
+ SkVector unitsPerMeter = SkPoint::Make(upm, upm);
+ static const SkScalar ppm = 200 * inchesPerMeter;
+ SkVector pixelsPerMeter = SkPoint::Make(ppm, ppm);
+
+ SkXPSDevice* dev = new SkXPSDevice();
+ SkAutoUnref aur(dev);
+
+ SkCanvas c(dev);
+ dev->beginPortfolio(&xps);
+ dev->beginSheet(unitsPerMeter, pixelsPerMeter, trimSize);
+ invokeGM(gm, &c);
+ dev->endSheet();
+ dev->endPortfolio();
+
+#endif
}
-}
-// Compares bitmap "bitmap" to "referenceBitmap"; if they are
-// different, writes out "bitmap" (in PNG format) within the diffPath subdir.
-//
-// Returns the ErrorBitfield from compare(), describing any differences
-// between "bitmap" and "referenceBitmap" (or ERROR_NONE if there are none).
-static ErrorBitfield compare_to_reference_image_in_memory(const SkString& name,
- SkBitmap &bitmap,
- const SkBitmap& referenceBitmap,
- const char diffPath [],
- const char renderModeDescriptor []) {
- ErrorBitfield errors;
- SkBitmap diffBitmap;
- errors = compare(bitmap, referenceBitmap, name, renderModeDescriptor,
- diffPath ? &diffBitmap : NULL);
- if ((ERROR_NONE != errors) && diffPath) {
- // write out the generated image
- SkString genName = make_filename(diffPath, "", name, "png");
- if (!write_bitmap(genName, bitmap)) {
- errors |= ERROR_WRITING_REFERENCE_IMAGE;
+ static ErrorBitfield write_reference_image(
+ const ConfigData& gRec, const char writePath [],
+ const char renderModeDescriptor [], const SkString& name,
+ SkBitmap& bitmap, SkDynamicMemoryWStream* document) {
+ SkString path;
+ bool success = false;
+ if (gRec.fBackend == kRaster_Backend ||
+ gRec.fBackend == kGPU_Backend ||
+ (gRec.fBackend == kPDF_Backend && CAN_IMAGE_PDF)) {
+
+ path = make_filename(writePath, renderModeDescriptor, name, "png");
+ success = write_bitmap(path, bitmap);
+ }
+ if (kPDF_Backend == gRec.fBackend) {
+ path = make_filename(writePath, renderModeDescriptor, name, "pdf");
+ success = write_document(path, *document);
+ }
+ if (kXPS_Backend == gRec.fBackend) {
+ path = make_filename(writePath, renderModeDescriptor, name, "xps");
+ success = write_document(path, *document);
+ }
+ if (success) {
+ return ERROR_NONE;
+ } else {
+ fprintf(stderr, "FAILED to write %s\n", path.c_str());
+ return ERROR_WRITING_REFERENCE_IMAGE;
}
}
- return errors;
-}
-// Compares bitmap "bitmap" to a reference bitmap read from disk; if they are
-// different, writes out "bitmap" (in PNG format) within the diffPath subdir.
-//
-// Returns a description of the difference between "bitmap" and the reference
-// bitmap, or ERROR_READING_REFERENCE_IMAGE if unable to read the reference
-// bitmap from disk.
-static ErrorBitfield compare_to_reference_image_on_disk(const char readPath [],
- const SkString& name,
- SkBitmap &bitmap,
- const char diffPath [],
- const char renderModeDescriptor []) {
- SkString path = make_filename(readPath, "", name, "png");
- SkBitmap referenceBitmap;
- if (SkImageDecoder::DecodeFile(path.c_str(), &referenceBitmap,
- SkBitmap::kARGB_8888_Config,
- SkImageDecoder::kDecodePixels_Mode, NULL)) {
- return compare_to_reference_image_in_memory(name, bitmap,
- referenceBitmap, diffPath,
- renderModeDescriptor);
- } else {
- if (gNotifyMissingReadReference) {
- fprintf(stderr, "FAILED to read %s\n", path.c_str());
+ // Compares bitmap "bitmap" to "referenceBitmap"; if they are
+ // different, writes out "bitmap" (in PNG format) within the
+ // diffPath subdir.
+ //
+ // Returns the ErrorBitfield from compare(), describing any differences
+ // between "bitmap" and "referenceBitmap" (or ERROR_NONE if there are none).
+ static ErrorBitfield compare_to_reference_image_in_memory(
+ const SkString& name, SkBitmap &bitmap, const SkBitmap& referenceBitmap,
+ const char diffPath [], const char renderModeDescriptor []) {
+ ErrorBitfield errors;
+ SkBitmap diffBitmap;
+ errors = compare(bitmap, referenceBitmap, name, renderModeDescriptor,
+ diffPath ? &diffBitmap : NULL);
+ if ((ERROR_NONE != errors) && diffPath) {
+ // write out the generated image
+ SkString genName = make_filename(diffPath, "", name, "png");
+ if (!write_bitmap(genName, bitmap)) {
+ errors |= ERROR_WRITING_REFERENCE_IMAGE;
+ }
}
- return ERROR_READING_REFERENCE_IMAGE;
+ return errors;
}
-}
-// NOTE: As far as I can tell, this function is NEVER called with a
-// non-blank renderModeDescriptor, EXCEPT with readPath and writePath are
-// both NULL (and thus no images are read from or written to disk).
-// So I don't trust that the renderModeDescriptor is being used for
-// anything other than debug output these days.
-static ErrorBitfield handle_test_results(GM* gm,
- const ConfigData& gRec,
- const char writePath [],
- const char readPath [],
- const char diffPath [],
- const char renderModeDescriptor [],
- SkBitmap& bitmap,
- SkDynamicMemoryWStream* pdf,
- const SkBitmap* referenceBitmap) {
- SkString name = make_name(gm->shortName(), gRec.fName);
- ErrorBitfield retval = ERROR_NONE;
-
- if (readPath && (gRec.fFlags & kRead_ConfigFlag)) {
- retval |= compare_to_reference_image_on_disk(readPath, name, bitmap,
- diffPath, renderModeDescriptor);
- }
- if (writePath && (gRec.fFlags & kWrite_ConfigFlag)) {
- retval |= write_reference_image(gRec, writePath, renderModeDescriptor,
- name, bitmap, pdf);
+ // Compares bitmap "bitmap" to a reference bitmap read from disk;
+ // if they are different, writes out "bitmap" (in PNG format)
+ // within the diffPath subdir.
+ //
+ // Returns a description of the difference between "bitmap" and
+ // the reference bitmap, or ERROR_READING_REFERENCE_IMAGE if
+ // unable to read the reference bitmap from disk.
+ static ErrorBitfield compare_to_reference_image_on_disk(
+ const char readPath [], const SkString& name, SkBitmap &bitmap,
+ const char diffPath [], const char renderModeDescriptor []) {
+ SkString path = make_filename(readPath, "", name, "png");
+ SkBitmap referenceBitmap;
+ if (SkImageDecoder::DecodeFile(path.c_str(), &referenceBitmap,
+ SkBitmap::kARGB_8888_Config,
+ SkImageDecoder::kDecodePixels_Mode,
+ NULL)) {
+ return compare_to_reference_image_in_memory(name, bitmap,
+ referenceBitmap,
+ diffPath,
+ renderModeDescriptor);
+ } else {
+ if (gNotifyMissingReadReference) {
+ fprintf(stderr, "FAILED to read %s\n", path.c_str());
+ }
+ return ERROR_READING_REFERENCE_IMAGE;
+ }
}
- if (referenceBitmap) {
- retval |= compare_to_reference_image_in_memory(name, bitmap,
- *referenceBitmap, diffPath,
- renderModeDescriptor);
+
+ // NOTE: As far as I can tell, this function is NEVER called with a
+ // non-blank renderModeDescriptor, EXCEPT when readPath and writePath are
+ // both NULL (and thus no images are read from or written to disk).
+ // So I don't trust that the renderModeDescriptor is being used for
+ // anything other than debug output these days.
+ static ErrorBitfield handle_test_results(GM* gm,
+ const ConfigData& gRec,
+ const char writePath [],
+ const char readPath [],
+ const char diffPath [],
+ const char renderModeDescriptor [],
+ SkBitmap& bitmap,
+ SkDynamicMemoryWStream* pdf,
+ const SkBitmap* referenceBitmap) {
+ SkString name = make_name(gm->shortName(), gRec.fName);
+ ErrorBitfield retval = ERROR_NONE;
+
+ if (readPath && (gRec.fFlags & kRead_ConfigFlag)) {
+ retval |= compare_to_reference_image_on_disk(readPath, name, bitmap,
+ diffPath,
+ renderModeDescriptor);
+ }
+ if (writePath && (gRec.fFlags & kWrite_ConfigFlag)) {
+ retval |= write_reference_image(gRec, writePath,
+ renderModeDescriptor,
+ name, bitmap, pdf);
+ }
+ if (referenceBitmap) {
+ retval |= compare_to_reference_image_in_memory(
+ name, bitmap, *referenceBitmap, diffPath, renderModeDescriptor);
+ }
+ return retval;
}
- return retval;
-}
-static SkPicture* generate_new_picture(GM* gm) {
- // Pictures are refcounted so must be on heap
- SkPicture* pict = new SkPicture;
- SkISize size = gm->getISize();
- SkCanvas* cv = pict->beginRecording(size.width(), size.height());
- invokeGM(gm, cv);
- pict->endRecording();
+ static SkPicture* generate_new_picture(GM* gm) {
+ // Pictures are refcounted so must be on heap
+ SkPicture* pict = new SkPicture;
+ SkISize size = gm->getISize();
+ SkCanvas* cv = pict->beginRecording(size.width(), size.height());
+ invokeGM(gm, cv);
+ pict->endRecording();
- return pict;
-}
+ return pict;
+ }
-static SkPicture* stream_to_new_picture(const SkPicture& src) {
-
- // To do in-memory commiunications with a stream, we need to:
- // * create a dynamic memory stream
- // * copy it into a buffer
- // * create a read stream from it
- // ?!?!
-
- SkDynamicMemoryWStream storage;
- src.serialize(&storage);
-
- int streamSize = storage.getOffset();
- SkAutoMalloc dstStorage(streamSize);
- void* dst = dstStorage.get();
- //char* dst = new char [streamSize];
- //@todo thudson 22 April 2011 when can we safely delete [] dst?
- storage.copyTo(dst);
- SkMemoryStream pictReadback(dst, streamSize);
- SkPicture* retval = new SkPicture (&pictReadback);
- return retval;
-}
+ static SkPicture* stream_to_new_picture(const SkPicture& src) {
+
+ // To do in-memory commiunications with a stream, we need to:
+ // * create a dynamic memory stream
+ // * copy it into a buffer
+ // * create a read stream from it
+ // ?!?!
+
+ SkDynamicMemoryWStream storage;
+ src.serialize(&storage);
+
+ int streamSize = storage.getOffset();
+ SkAutoMalloc dstStorage(streamSize);
+ void* dst = dstStorage.get();
+ //char* dst = new char [streamSize];
+ //@todo thudson 22 April 2011 when can we safely delete [] dst?
+ storage.copyTo(dst);
+ SkMemoryStream pictReadback(dst, streamSize);
+ SkPicture* retval = new SkPicture (&pictReadback);
+ return retval;
+ }
-// Test: draw into a bitmap or pdf.
-// Depending on flags, possibly compare to an expected image
-// and possibly output a diff image if it fails to match.
-static ErrorBitfield test_drawing(GM* gm,
- const ConfigData& gRec,
- const char writePath [],
- const char readPath [],
- const char diffPath [],
- GrContext* context,
- GrRenderTarget* rt,
- SkBitmap* bitmap) {
- SkDynamicMemoryWStream document;
-
- if (gRec.fBackend == kRaster_Backend ||
- gRec.fBackend == kGPU_Backend) {
- // Early exit if we can't generate the image.
- ErrorBitfield errors = generate_image(gm, gRec, context, rt, bitmap,
- false);
- if (ERROR_NONE != errors) {
- return errors;
- }
- } else if (gRec.fBackend == kPDF_Backend) {
- generate_pdf(gm, document);
+ // Test: draw into a bitmap or pdf.
+ // Depending on flags, possibly compare to an expected image
+ // and possibly output a diff image if it fails to match.
+ static ErrorBitfield test_drawing(GM* gm,
+ const ConfigData& gRec,
+ const char writePath [],
+ const char readPath [],
+ const char diffPath [],
+ GrContext* context,
+ GrRenderTarget* rt,
+ SkBitmap* bitmap) {
+ SkDynamicMemoryWStream document;
+
+ if (gRec.fBackend == kRaster_Backend ||
+ gRec.fBackend == kGPU_Backend) {
+ // Early exit if we can't generate the image.
+ ErrorBitfield errors = generate_image(gm, gRec, context, rt, bitmap,
+ false);
+ if (ERROR_NONE != errors) {
+ return errors;
+ }
+ } else if (gRec.fBackend == kPDF_Backend) {
+ generate_pdf(gm, document);
#if CAN_IMAGE_PDF
- SkAutoDataUnref data(document.copyToData());
- SkMemoryStream stream(data->data(), data->size());
- SkPDFDocumentToBitmap(&stream, bitmap);
+ SkAutoDataUnref data(document.copyToData());
+ SkMemoryStream stream(data->data(), data->size());
+ SkPDFDocumentToBitmap(&stream, bitmap);
#endif
- } else if (gRec.fBackend == kXPS_Backend) {
- generate_xps(gm, document);
+ } else if (gRec.fBackend == kXPS_Backend) {
+ generate_xps(gm, document);
+ }
+ return handle_test_results(gm, gRec, writePath, readPath, diffPath,
+ "", *bitmap, &document, NULL);
}
- return handle_test_results(gm, gRec, writePath, readPath, diffPath,
- "", *bitmap, &document, NULL);
-}
-static ErrorBitfield test_deferred_drawing(GM* gm,
- const ConfigData& gRec,
- const SkBitmap& referenceBitmap,
- const char diffPath [],
- GrContext* context,
- GrRenderTarget* rt) {
- SkDynamicMemoryWStream document;
-
- if (gRec.fBackend == kRaster_Backend ||
- gRec.fBackend == kGPU_Backend) {
- SkBitmap bitmap;
- // Early exit if we can't generate the image, but this is
- // expected in some cases, so don't report a test failure.
- if (!generate_image(gm, gRec, context, rt, &bitmap, true)) {
- return ERROR_NONE;
+ static ErrorBitfield test_deferred_drawing(GM* gm,
+ const ConfigData& gRec,
+ const SkBitmap& referenceBitmap,
+ const char diffPath [],
+ GrContext* context,
+ GrRenderTarget* rt) {
+ SkDynamicMemoryWStream document;
+
+ if (gRec.fBackend == kRaster_Backend ||
+ gRec.fBackend == kGPU_Backend) {
+ SkBitmap bitmap;
+ // Early exit if we can't generate the image, but this is
+ // expected in some cases, so don't report a test failure.
+ if (!generate_image(gm, gRec, context, rt, &bitmap, true)) {
+ return ERROR_NONE;
+ }
+ return handle_test_results(gm, gRec, NULL, NULL, diffPath,
+ "-deferred", bitmap, NULL,
+ &referenceBitmap);
}
- return handle_test_results(gm, gRec, NULL, NULL, diffPath,
- "-deferred", bitmap, NULL, &referenceBitmap);
+ return ERROR_NONE;
}
- return ERROR_NONE;
-}
-struct PipeFlagComboData {
- const char* name;
- uint32_t flags;
-};
-
-static PipeFlagComboData gPipeWritingFlagCombos[] = {
- { "", 0 },
- { " cross-process", SkGPipeWriter::kCrossProcess_Flag },
- { " cross-process, shared address", SkGPipeWriter::kCrossProcess_Flag
- | SkGPipeWriter::kSharedAddressSpace_Flag }
-};
-
-static ErrorBitfield test_pipe_playback(GM* gm,
- const ConfigData& gRec,
- const SkBitmap& referenceBitmap,
- const char readPath [],
- const char diffPath []) {
- ErrorBitfield errors = ERROR_NONE;
- for (size_t i = 0; i < SK_ARRAY_COUNT(gPipeWritingFlagCombos); ++i) {
- SkBitmap bitmap;
- SkISize size = gm->getISize();
- setup_bitmap(gRec, size, &bitmap);
- SkCanvas canvas(bitmap);
- PipeController pipeController(&canvas);
- SkGPipeWriter writer;
- SkCanvas* pipeCanvas = writer.startRecording(
- &pipeController, gPipeWritingFlagCombos[i].flags);
- invokeGM(gm, pipeCanvas);
- writer.endRecording();
- SkString string("-pipe");
- string.append(gPipeWritingFlagCombos[i].name);
- errors |= handle_test_results(gm, gRec, NULL, NULL, diffPath,
- string.c_str(), bitmap, NULL,
- &referenceBitmap);
- if (errors != ERROR_NONE) {
- break;
+ static ErrorBitfield test_pipe_playback(GM* gm,
+ const ConfigData& gRec,
+ const SkBitmap& referenceBitmap,
+ const char readPath [],
+ const char diffPath []) {
+ ErrorBitfield errors = ERROR_NONE;
+ for (size_t i = 0; i < SK_ARRAY_COUNT(gPipeWritingFlagCombos); ++i) {
+ SkBitmap bitmap;
+ SkISize size = gm->getISize();
+ setup_bitmap(gRec, size, &bitmap);
+ SkCanvas canvas(bitmap);
+ PipeController pipeController(&canvas);
+ SkGPipeWriter writer;
+ SkCanvas* pipeCanvas = writer.startRecording(
+ &pipeController, gPipeWritingFlagCombos[i].flags);
+ invokeGM(gm, pipeCanvas);
+ writer.endRecording();
+ SkString string("-pipe");
+ string.append(gPipeWritingFlagCombos[i].name);
+ errors |= handle_test_results(gm, gRec, NULL, NULL, diffPath,
+ string.c_str(), bitmap, NULL,
+ &referenceBitmap);
+ if (errors != ERROR_NONE) {
+ break;
+ }
}
+ return errors;
}
- return errors;
-}
-static ErrorBitfield test_tiled_pipe_playback(GM* gm,
- const ConfigData& gRec,
- const SkBitmap& referenceBitmap,
- const char readPath [],
- const char diffPath []) {
- ErrorBitfield errors = ERROR_NONE;
- for (size_t i = 0; i < SK_ARRAY_COUNT(gPipeWritingFlagCombos); ++i) {
- SkBitmap bitmap;
- SkISize size = gm->getISize();
- setup_bitmap(gRec, size, &bitmap);
- SkCanvas canvas(bitmap);
- TiledPipeController pipeController(bitmap);
- SkGPipeWriter writer;
- SkCanvas* pipeCanvas = writer.startRecording(
- &pipeController, gPipeWritingFlagCombos[i].flags);
- invokeGM(gm, pipeCanvas);
- writer.endRecording();
- SkString string("-tiled pipe");
- string.append(gPipeWritingFlagCombos[i].name);
- errors |= handle_test_results(gm, gRec, NULL, NULL, diffPath,
- string.c_str(), bitmap, NULL,
- &referenceBitmap);
- if (errors != ERROR_NONE) {
- break;
+ static ErrorBitfield test_tiled_pipe_playback(
+ GM* gm, const ConfigData& gRec, const SkBitmap& referenceBitmap,
+ const char readPath [], const char diffPath []) {
+ ErrorBitfield errors = ERROR_NONE;
+ for (size_t i = 0; i < SK_ARRAY_COUNT(gPipeWritingFlagCombos); ++i) {
+ SkBitmap bitmap;
+ SkISize size = gm->getISize();
+ setup_bitmap(gRec, size, &bitmap);
+ SkCanvas canvas(bitmap);
+ TiledPipeController pipeController(bitmap);
+ SkGPipeWriter writer;
+ SkCanvas* pipeCanvas = writer.startRecording(
+ &pipeController, gPipeWritingFlagCombos[i].flags);
+ invokeGM(gm, pipeCanvas);
+ writer.endRecording();
+ SkString string("-tiled pipe");
+ string.append(gPipeWritingFlagCombos[i].name);
+ errors |= handle_test_results(gm, gRec, NULL, NULL, diffPath,
+ string.c_str(), bitmap, NULL,
+ &referenceBitmap);
+ if (errors != ERROR_NONE) {
+ break;
+ }
}
+ return errors;
}
- return errors;
-}
+}; // end of GMMain class definition
#if SK_SUPPORT_GPU
static const GLContextType kDontCare_GLContextType = GrContextFactory::kNative_GLContextType;
gSkSuppressFontCachePurgeSpew = true;
setSystemPreferences();
+ GMMain gmmain;
const char* writePath = NULL; // if non-null, where we write the originals
const char* writePicturePath = NULL; // if non-null, where we write serialized pictures
} else if (strcmp(*argv, "--enable-missing-warning") == 0) {
gNotifyMissingReadReference = true;
} else if (strcmp(*argv, "--serialize") == 0) {
- // Leaving in this option so that a user need not modify their command line arguments
- // to still run.
+ // Leaving in this option so that a user need not modify
+ // their command line arguments to still run.
doSerialize = true;
} else if (strcmp(*argv, "--noserialize") == 0) {
doSerialize = false;
// Skip any tests that we don't even need to try.
if ((kPDF_Backend == config.fBackend) &&
(!doPDF || (gmFlags & GM::kSkipPDF_Flag)))
- {
- continue;
- }
+ {
+ continue;
+ }
if ((gmFlags & GM::kSkip565_Flag) &&
(kRaster_Backend == config.fBackend) &&
(SkBitmap::kRGB_565_Config == config.fConfig)) {
SkBitmap comparisonBitmap;
if (ERROR_NONE == renderErrors) {
- renderErrors |= test_drawing(gm, config,
- writePath, readPath, diffPath,
- GetGr(), renderTarget, &comparisonBitmap);
+ renderErrors |= gmmain.test_drawing(gm, config, writePath,
+ readPath, diffPath, GetGr(),
+ renderTarget,
+ &comparisonBitmap);
}
if (doDeferred && !renderErrors &&
(kGPU_Backend == config.fBackend ||
kRaster_Backend == config.fBackend)) {
- renderErrors |= test_deferred_drawing(gm, config, comparisonBitmap,
- diffPath, GetGr(), renderTarget);
+ renderErrors |= gmmain.test_deferred_drawing(gm, config,
+ comparisonBitmap,
+ diffPath, GetGr(),
+ renderTarget);
}
testErrors |= renderErrors;
if (is_recordable_failure(renderErrors)) {
- failedTests.push_back(make_name(shortName, config.fName));
+ failedTests.push_back(gmmain.make_name(shortName,
+ config.fName));
}
}
SkBitmap comparisonBitmap;
const ConfigData compareConfig =
{ SkBitmap::kARGB_8888_Config, kRaster_Backend, kDontCare_GLContextType, 0, kRW_ConfigFlag, "comparison" };
- testErrors |= generate_image(gm, compareConfig, NULL, NULL, &comparisonBitmap, false);
+ testErrors |= gmmain.generate_image(gm, compareConfig, NULL, NULL, &comparisonBitmap, false);
// run the picture centric GM steps
if (!(gmFlags & GM::kSkipPicture_Flag)) {
ErrorBitfield pictErrors = ERROR_NONE;
//SkAutoTUnref<SkPicture> pict(generate_new_picture(gm));
- SkPicture* pict = generate_new_picture(gm);
+ SkPicture* pict = gmmain.generate_new_picture(gm);
SkAutoUnref aur(pict);
if ((ERROR_NONE == testErrors) && doReplay) {
SkBitmap bitmap;
- generate_image_from_picture(gm, compareConfig, pict, &bitmap);
- pictErrors |= handle_test_results(gm, compareConfig, NULL, NULL, diffPath,
- "-replay", bitmap, NULL, &comparisonBitmap);
+ gmmain.generate_image_from_picture(gm, compareConfig, pict,
+ &bitmap);
+ pictErrors |= gmmain.handle_test_results(gm, compareConfig,
+ NULL, NULL, diffPath,
+ "-replay", bitmap,
+ NULL,
+ &comparisonBitmap);
if (is_recordable_failure(pictErrors)) {
- failedTests.push_back(make_name(shortName, "pict-replay"));
+ failedTests.push_back(gmmain.make_name(shortName,
+ "pict-replay"));
}
}
- if ((ERROR_NONE == testErrors) && (ERROR_NONE == pictErrors) && doSerialize) {
- SkPicture* repict = stream_to_new_picture(*pict);
+ if ((ERROR_NONE == testErrors) &&
+ (ERROR_NONE == pictErrors) &&
+ doSerialize) {
+ SkPicture* repict = gmmain.stream_to_new_picture(*pict);
SkAutoUnref aurr(repict);
SkBitmap bitmap;
- generate_image_from_picture(gm, compareConfig, repict, &bitmap);
- pictErrors |= handle_test_results(gm, compareConfig, NULL, NULL, diffPath,
- "-serialize", bitmap, NULL, &comparisonBitmap);
+ gmmain.generate_image_from_picture(gm, compareConfig, repict,
+ &bitmap);
+ pictErrors |= gmmain.handle_test_results(gm, compareConfig,
+ NULL, NULL, diffPath,
+ "-serialize", bitmap,
+ NULL,
+ &comparisonBitmap);
if (is_recordable_failure(pictErrors)) {
- failedTests.push_back(make_name(shortName, "pict-serialize"));
+ failedTests.push_back(gmmain.make_name(shortName,
+ "pict-serialize"));
}
}
if (writePicturePath) {
const char* pictureSuffix = "skp";
- SkString path = make_filename(writePicturePath, "",
- SkString(gm->shortName()), pictureSuffix);
+ SkString path = gmmain.make_filename(writePicturePath, "",
+ SkString(gm->shortName()),
+ pictureSuffix);
SkFILEWStream stream(path.c_str());
pict->serialize(&stream);
}
ErrorBitfield pipeErrors = ERROR_NONE;
if ((ERROR_NONE == testErrors) && doPipe) {
- pipeErrors |= test_pipe_playback(gm, compareConfig,
- comparisonBitmap,
- readPath, diffPath);
+ pipeErrors |= gmmain.test_pipe_playback(gm, compareConfig,
+ comparisonBitmap,
+ readPath, diffPath);
if (is_recordable_failure(pipeErrors)) {
- failedTests.push_back(make_name(shortName, "pipe"));
+ failedTests.push_back(gmmain.make_name(shortName, "pipe"));
}
}
if ((ERROR_NONE == testErrors) &&
(ERROR_NONE == pipeErrors) &&
doTiledPipe && !(gmFlags & GM::kSkipTiled_Flag)) {
- pipeErrors |= test_tiled_pipe_playback(gm, compareConfig,
- comparisonBitmap,
- readPath, diffPath);
+ pipeErrors |= gmmain.test_tiled_pipe_playback(gm, compareConfig,
+ comparisonBitmap,
+ readPath,
+ diffPath);
if (is_recordable_failure(pipeErrors)) {
- failedTests.push_back(make_name(shortName, "pipe-tiled"));
+ failedTests.push_back(gmmain.make_name(shortName,
+ "pipe-tiled"));
}
}