using namespace skiagm;
+/*
+ * Return the max of the difference (in absolute value) for any component.
+ * Returns 0 if they are equal.
+ */
+static int compute_PMColor_maxDiff(SkPMColor c0, SkPMColor c1) {
+ int da = SkAbs32(SkGetPackedA32(c0) - SkGetPackedA32(c1));
+ int dr = SkAbs32(SkGetPackedR32(c0) - SkGetPackedR32(c1));
+ int dg = SkAbs32(SkGetPackedG32(c0) - SkGetPackedG32(c1));
+ int db = SkAbs32(SkGetPackedB32(c0) - SkGetPackedB32(c1));
+ return SkMax32(da, SkMax32(dr, SkMax32(dg, db)));
+}
+
class Iter {
public:
Iter() {
static ErrorBitfield compare(const SkBitmap& target, const SkBitmap& base,
const SkString& name,
const char* renderModeDescriptor,
- SkBitmap* diff) {
+ SkBitmap* diff, int* maxPixelError) {
SkBitmap copy;
const SkBitmap* bm = ⌖
if (target.config() != SkBitmap::kARGB_8888_Config) {
SkAutoLockPixels bmLock(*bm);
SkAutoLockPixels baseLock(*bp);
+ int maxErr = 0;
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;
+ maxErr = SkMax32(maxErr, compute_PMColor_maxDiff(c0, c1));
}
}
}
- // they're equal
+ if (maxPixelError) {
+ *maxPixelError = maxErr;
+ }
+ if (maxErr > 0) {
+ SkDebugf(
+ "----- %s max pixel mismatch for %s is %d\n",
+ renderModeDescriptor, name.c_str(), maxErr);
+
+ if (diff) {
+ diff->setConfig(SkBitmap::kARGB_8888_Config, w, h);
+ diff->allocPixels();
+ compute_diff(*bm, *bp, diff);
+ }
+ return ERROR_PIXEL_MISMATCH;
+ }
return ERROR_NONE;
}
// 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 []) {
+ const char diffPath [], const char renderModeDescriptor [],
+ int* maxPixelError) {
ErrorBitfield errors;
SkBitmap diffBitmap;
errors = compare(bitmap, referenceBitmap, name, renderModeDescriptor,
- diffPath ? &diffBitmap : NULL);
+ diffPath ? &diffBitmap : NULL, maxPixelError);
if ((ERROR_NONE != errors) && diffPath) {
// write out the generated image
SkString genName = make_filename(diffPath, "", name, "png");
// unable to read the reference bitmap from disk.
ErrorBitfield compare_to_reference_image_on_disk(
const char readPath [], const SkString& name, SkBitmap &bitmap,
- const char diffPath [], const char renderModeDescriptor []) {
+ const char diffPath [], const char renderModeDescriptor [],
+ int* maxPixelError) {
SkString path = make_filename(readPath, "", name, "png");
SkBitmap referenceBitmap;
if (SkImageDecoder::DecodeFile(path.c_str(), &referenceBitmap,
return compare_to_reference_image_in_memory(name, bitmap,
referenceBitmap,
diffPath,
- renderModeDescriptor);
+ renderModeDescriptor,
+ maxPixelError);
} else {
if (fNotifyMissingReadReference) {
fprintf(stderr, "FAILED to read %s\n", path.c_str());
const char renderModeDescriptor [],
SkBitmap& bitmap,
SkDynamicMemoryWStream* pdf,
- const SkBitmap* referenceBitmap) {
+ const SkBitmap* referenceBitmap,
+ int* maxPixelError) {
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);
+ renderModeDescriptor,
+ maxPixelError);
}
if (writePath && (gRec.fFlags & kWrite_ConfigFlag)) {
retval |= write_reference_image(gRec, writePath,
}
if (referenceBitmap) {
retval |= compare_to_reference_image_in_memory(
- name, bitmap, *referenceBitmap, diffPath, renderModeDescriptor);
+ name, bitmap, *referenceBitmap, diffPath, renderModeDescriptor,
+ maxPixelError);
}
return retval;
}
const char diffPath [],
GrContext* context,
GrRenderTarget* rt,
- SkBitmap* bitmap) {
+ SkBitmap* bitmap,
+ int* maxPixelError) {
SkDynamicMemoryWStream document;
if (gRec.fBackend == kRaster_Backend ||
generate_xps(gm, document);
}
return handle_test_results(gm, gRec, writePath, readPath, diffPath,
- "", *bitmap, &document, NULL);
+ "", *bitmap, &document, NULL, maxPixelError);
}
ErrorBitfield test_deferred_drawing(GM* gm,
}
return handle_test_results(gm, gRec, NULL, NULL, diffPath,
"-deferred", bitmap, NULL,
- &referenceBitmap);
+ &referenceBitmap, NULL);
}
return ERROR_NONE;
}
string.append(gPipeWritingFlagCombos[i].name);
errors |= handle_test_results(gm, gRec, NULL, NULL, diffPath,
string.c_str(), bitmap, NULL,
- &referenceBitmap);
+ &referenceBitmap, NULL);
if (errors != ERROR_NONE) {
break;
}
string.append(gPipeWritingFlagCombos[i].name);
errors |= handle_test_results(gm, gRec, NULL, NULL, diffPath,
string.c_str(), bitmap, NULL,
- &referenceBitmap);
+ &referenceBitmap, NULL);
if (errors != ERROR_NONE) {
break;
}
return ERROR_NONE != errorCode && !(ERROR_READING_REFERENCE_IMAGE & errorCode);
}
+struct FailRec {
+ SkString fName;
+ int fMaxPixelError;
+
+ FailRec() : fMaxPixelError(0) {}
+ FailRec(const SkString& name) : fName(name), fMaxPixelError(0) {}
+};
+
int tool_main(int argc, char** argv);
int tool_main(int argc, char** argv) {
}
#endif
- SkTArray<SkString> failedTests;
+ SkTArray<FailRec> failedTests;
int gmIndex = -1;
SkString moduloStr;
#endif
SkBitmap comparisonBitmap;
+ int maxPixelError = 0;
if (ERROR_NONE == renderErrors) {
renderErrors |= gmmain.test_drawing(gm, config, writePath,
readPath, diffPath, GetGr(),
renderTarget,
- &comparisonBitmap);
+ &comparisonBitmap,
+ &maxPixelError);
}
if (doDeferred && !renderErrors &&
testErrors |= renderErrors;
if (is_recordable_failure(renderErrors)) {
- failedTests.push_back(gmmain.make_name(shortName,
- config.fName));
+ FailRec& rec = failedTests.push_back();
+ rec.fName = gmmain.make_name(shortName, config.fName);
+ rec.fMaxPixelError = maxPixelError;
}
}
NULL, NULL, diffPath,
"-replay", bitmap,
NULL,
- &comparisonBitmap);
+ &comparisonBitmap, NULL);
if (is_recordable_failure(pictErrors)) {
failedTests.push_back(gmmain.make_name(shortName,
"pict-replay"));
NULL, NULL, diffPath,
"-serialize", bitmap,
NULL,
- &comparisonBitmap);
+ &comparisonBitmap, NULL);
if (is_recordable_failure(pictErrors)) {
failedTests.push_back(gmmain.make_name(shortName,
"pict-serialize"));
SkDebugf("Ran %d tests: %d passed, %d failed, %d missing reference images\n",
testsRun, testsPassed, testsFailed, testsMissingReferenceImages);
for (int i = 0; i < failedTests.count(); ++i) {
- SkDebugf("\t\t%s\n", failedTests[i].c_str());
+ int pixErr = failedTests[i].fMaxPixelError;
+ SkString pixStr;
+ if (pixErr > 0) {
+ pixStr.printf(" pixel_error %d", pixErr);
+ }
+ SkDebugf("\t\t%s%s\n", failedTests[i].fName.c_str(), pixStr.c_str());
}
#if SK_SUPPORT_GPU