gm: change ErrorBitfield to ErrorType/ErrorCombination
This will enable future GM changes to report errors more completely/consistently, like skdiff. Review URL: https://codereview.chromium.org/12992003 git-svn-id: http://skia.googlecode.com/svn/trunk@8344 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
parent
292b1d4903
commit
6f6568b27e
89
gm/gm_error.h
Normal file
89
gm/gm_error.h
Normal file
@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright 2013 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Error codes used by gmmain.cpp.
|
||||
*/
|
||||
|
||||
namespace skiagm {
|
||||
|
||||
/**
|
||||
* The complete list of error types we might encounter in GM.
|
||||
*/
|
||||
enum ErrorType {
|
||||
#if SK_SUPPORT_GPU
|
||||
kNoGpuContext_ErrorType,
|
||||
#endif
|
||||
kImageMismatch_ErrorType,
|
||||
kMissingExpectations_ErrorType,
|
||||
kWritingReferenceImage_ErrorType,
|
||||
kLast_ErrorType = kWritingReferenceImage_ErrorType
|
||||
};
|
||||
|
||||
/**
|
||||
* A combination of 0 or more ErrorTypes.
|
||||
*/
|
||||
class ErrorCombination {
|
||||
public:
|
||||
ErrorCombination() : fBitfield(0) {}
|
||||
ErrorCombination(const ErrorType type) : fBitfield(1 << type) {}
|
||||
|
||||
/**
|
||||
* Returns true iff there are NO errors.
|
||||
*/
|
||||
bool isEmpty() const {
|
||||
return (0 == this->fBitfield);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds this ErrorType to this ErrorCombination.
|
||||
*/
|
||||
void add(const ErrorType type) {
|
||||
this->fBitfield |= (1 << type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds all ErrorTypes in "other" to this ErrorCombination.
|
||||
*/
|
||||
void add(const ErrorCombination other) {
|
||||
this->fBitfield |= other.fBitfield;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true iff this ErrorCombination includes this ErrorType.
|
||||
*/
|
||||
bool includes(const ErrorType type) const {
|
||||
return !(0 == (this->fBitfield & (1 << type)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new ErrorCombination, which includes the union of all
|
||||
* ErrorTypes in two ErrorCombination objects (this and other).
|
||||
*/
|
||||
ErrorCombination plus(const ErrorCombination& other) const {
|
||||
ErrorCombination retval;
|
||||
retval.fBitfield = this->fBitfield | other.fBitfield;
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new ErrorCombination, which is a copy of "this"
|
||||
* but with all ErrorTypes in "other" removed.
|
||||
*/
|
||||
ErrorCombination minus(const ErrorCombination& other) const {
|
||||
ErrorCombination retval;
|
||||
retval.fBitfield = this->fBitfield & ~(other.fBitfield);
|
||||
return retval;
|
||||
}
|
||||
|
||||
private:
|
||||
int fBitfield;
|
||||
};
|
||||
|
||||
// No errors at all.
|
||||
const static ErrorCombination kEmpty_ErrorCombination;
|
||||
}
|
373
gm/gmmain.cpp
373
gm/gmmain.cpp
@ -14,6 +14,7 @@
|
||||
*/
|
||||
|
||||
#include "gm.h"
|
||||
#include "gm_error.h"
|
||||
#include "gm_expectations.h"
|
||||
#include "system_preferences.h"
|
||||
#include "SkBitmap.h"
|
||||
@ -52,6 +53,9 @@
|
||||
#include "GrRenderTarget.h"
|
||||
#include "SkGpuDevice.h"
|
||||
typedef GrContextFactory::GLContextType GLContextType;
|
||||
#define DEFAULT_CACHE_VALUE -1
|
||||
static int gGpuCacheSizeBytes;
|
||||
static int gGpuCacheSizeCount;
|
||||
#else
|
||||
class GrContextFactory;
|
||||
class GrContext;
|
||||
@ -80,17 +84,6 @@ extern bool gSkSuppressFontCachePurgeSpew;
|
||||
#define CAN_IMAGE_PDF 0
|
||||
#endif
|
||||
|
||||
typedef int ErrorBitfield;
|
||||
// an empty bitfield means no errors:
|
||||
const static ErrorBitfield kEmptyErrorBitfield = 0x00;
|
||||
// individual error types:
|
||||
const static ErrorBitfield kNoGpuContext_ErrorBitmask = 0x01;
|
||||
const static ErrorBitfield kImageMismatch_ErrorBitmask = 0x02;
|
||||
const static ErrorBitfield kMissingExpectations_ErrorBitmask = 0x04;
|
||||
const static ErrorBitfield kWritingReferenceImage_ErrorBitmask = 0x08;
|
||||
// we typically ignore any errors matching this bitmask:
|
||||
const static ErrorBitfield kIgnorable_ErrorBitmask = kMissingExpectations_ErrorBitmask;
|
||||
|
||||
using namespace skiagm;
|
||||
|
||||
struct FailRec {
|
||||
@ -195,6 +188,7 @@ public:
|
||||
// Set default values of member variables, which tool_main()
|
||||
// may override.
|
||||
fUseFileHierarchy = false;
|
||||
fIgnorableErrorCombination.add(kMissingExpectations_ErrorType);
|
||||
fMismatchPath = NULL;
|
||||
}
|
||||
|
||||
@ -248,24 +242,24 @@ public:
|
||||
SkImageEncoder::kPNG_Type, 100);
|
||||
}
|
||||
|
||||
// Records an error in fFailedTests, if we want to record errors
|
||||
// of this type.
|
||||
void RecordError(ErrorBitfield errorType, const SkString& name,
|
||||
/**
|
||||
* Records the errors encountered in fFailedTests, except for any error
|
||||
* types we want to ignore.
|
||||
*/
|
||||
void RecordError(const ErrorCombination& errorCombination, const SkString& name,
|
||||
const char renderModeDescriptor []) {
|
||||
// The common case: no error means nothing to record.
|
||||
if (kEmptyErrorBitfield == errorType) {
|
||||
if (errorCombination.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If only certain error type(s) were reported, we know we can ignore them.
|
||||
if (errorType == (errorType & kIgnorable_ErrorBitmask)) {
|
||||
if (errorCombination.minus(fIgnorableErrorCombination).isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
FailRec& rec = fFailedTests.push_back(make_name(
|
||||
name.c_str(), renderModeDescriptor));
|
||||
rec.fIsPixelError =
|
||||
(kEmptyErrorBitfield != (errorType & kImageMismatch_ErrorBitmask));
|
||||
FailRec& rec = fFailedTests.push_back(make_name(name.c_str(), renderModeDescriptor));
|
||||
rec.fIsPixelError = errorCombination.includes(kImageMismatch_ErrorType);
|
||||
}
|
||||
|
||||
// List contents of fFailedTests via SkDebug.
|
||||
@ -378,11 +372,11 @@ public:
|
||||
canvas->setDrawFilter(NULL);
|
||||
}
|
||||
|
||||
static ErrorBitfield generate_image(GM* gm, const ConfigData& gRec,
|
||||
GrContext* context,
|
||||
GrRenderTarget* rt,
|
||||
SkBitmap* bitmap,
|
||||
bool deferred) {
|
||||
static ErrorCombination generate_image(GM* gm, const ConfigData& gRec,
|
||||
GrContext* context,
|
||||
GrRenderTarget* rt,
|
||||
SkBitmap* bitmap,
|
||||
bool deferred) {
|
||||
SkISize size (gm->getISize());
|
||||
setup_bitmap(gRec, size, bitmap);
|
||||
|
||||
@ -401,7 +395,7 @@ public:
|
||||
#if SK_SUPPORT_GPU
|
||||
else { // GPU
|
||||
if (NULL == context) {
|
||||
return kNoGpuContext_ErrorBitmask;
|
||||
return ErrorCombination(kNoGpuContext_ErrorType);
|
||||
}
|
||||
SkAutoTUnref<SkDevice> device(new SkGpuDevice(context, rt));
|
||||
if (deferred) {
|
||||
@ -419,7 +413,7 @@ public:
|
||||
}
|
||||
#endif
|
||||
complete_bitmap(bitmap);
|
||||
return kEmptyErrorBitfield;
|
||||
return kEmpty_ErrorCombination;
|
||||
}
|
||||
|
||||
static void generate_image_from_picture(GM* gm, const ConfigData& gRec,
|
||||
@ -488,10 +482,9 @@ public:
|
||||
#endif
|
||||
}
|
||||
|
||||
ErrorBitfield write_reference_image(
|
||||
const ConfigData& gRec, const char writePath [],
|
||||
const char renderModeDescriptor [], const SkString& name,
|
||||
SkBitmap& bitmap, SkDynamicMemoryWStream* document) {
|
||||
ErrorCombination 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 ||
|
||||
@ -513,12 +506,12 @@ public:
|
||||
success = write_document(path, *document);
|
||||
}
|
||||
if (success) {
|
||||
return kEmptyErrorBitfield;
|
||||
return kEmpty_ErrorCombination;
|
||||
} else {
|
||||
gm_fprintf(stderr, "FAILED to write %s\n", path.c_str());
|
||||
RecordError(kWritingReferenceImage_ErrorBitmask, name,
|
||||
renderModeDescriptor);
|
||||
return kWritingReferenceImage_ErrorBitmask;
|
||||
ErrorCombination errors(kWritingReferenceImage_ErrorType);
|
||||
RecordError(errors, name, renderModeDescriptor);
|
||||
return errors;
|
||||
}
|
||||
}
|
||||
|
||||
@ -579,9 +572,8 @@ public:
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares actual checksum to expectations. Returns
|
||||
* kEmptyErrorBitfield if they match, or some combination of
|
||||
* _ErrorBitmask values otherwise.
|
||||
* Compares actual checksum to expectations, returning the set of errors
|
||||
* (if any) that we saw along the way.
|
||||
*
|
||||
* If fMismatchPath has been set, and there are pixel diffs, then the
|
||||
* actual bitmap will be written out to a file within fMismatchPath.
|
||||
@ -598,23 +590,21 @@ public:
|
||||
* in-memory comparisons (Rtree vs regular, etc.) are not written to the
|
||||
* JSON summary. We may wish to change that.
|
||||
*/
|
||||
ErrorBitfield compare_to_expectations(Expectations expectations,
|
||||
const SkBitmap& actualBitmap,
|
||||
const SkString& baseNameString,
|
||||
const char renderModeDescriptor[],
|
||||
bool addToJsonSummary=false) {
|
||||
ErrorBitfield retval;
|
||||
ErrorCombination compare_to_expectations(Expectations expectations,
|
||||
const SkBitmap& actualBitmap,
|
||||
const SkString& baseNameString,
|
||||
const char renderModeDescriptor[],
|
||||
bool addToJsonSummary=false) {
|
||||
ErrorCombination errors;
|
||||
Checksum actualChecksum = SkBitmapChecksummer::Compute64(actualBitmap);
|
||||
SkString completeNameString = baseNameString;
|
||||
completeNameString.append(renderModeDescriptor);
|
||||
const char* completeName = completeNameString.c_str();
|
||||
|
||||
if (expectations.empty()) {
|
||||
retval = kMissingExpectations_ErrorBitmask;
|
||||
} else if (expectations.match(actualChecksum)) {
|
||||
retval = kEmptyErrorBitfield;
|
||||
} else {
|
||||
retval = kImageMismatch_ErrorBitmask;
|
||||
errors.add(kMissingExpectations_ErrorType);
|
||||
} else if (!expectations.match(actualChecksum)) {
|
||||
errors.add(kImageMismatch_ErrorType);
|
||||
|
||||
// Write out the "actuals" for any mismatches, if we have
|
||||
// been directed to do so.
|
||||
@ -632,16 +622,15 @@ public:
|
||||
report_bitmap_diffs(*expectedBitmapPtr, actualBitmap, completeName);
|
||||
}
|
||||
}
|
||||
RecordError(retval, baseNameString, renderModeDescriptor);
|
||||
RecordError(errors, baseNameString, renderModeDescriptor);
|
||||
|
||||
if (addToJsonSummary) {
|
||||
add_actual_results_to_json_summary(completeName, actualChecksum,
|
||||
retval,
|
||||
add_actual_results_to_json_summary(completeName, actualChecksum, errors,
|
||||
expectations.ignoreFailure());
|
||||
add_expected_results_to_json_summary(completeName, expectations);
|
||||
}
|
||||
|
||||
return retval;
|
||||
return errors;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -650,12 +639,12 @@ public:
|
||||
*/
|
||||
void add_actual_results_to_json_summary(const char testName[],
|
||||
Checksum actualChecksum,
|
||||
ErrorBitfield result,
|
||||
ErrorCombination result,
|
||||
bool ignoreFailure) {
|
||||
Json::Value actualResults;
|
||||
actualResults[kJsonKey_ActualResults_AnyStatus_Checksum] =
|
||||
asJsonValue(actualChecksum);
|
||||
if (kEmptyErrorBitfield == result) {
|
||||
if (result.isEmpty()) {
|
||||
this->fJsonActualResults_Succeeded[testName] = actualResults;
|
||||
} else {
|
||||
if (ignoreFailure) {
|
||||
@ -663,12 +652,12 @@ public:
|
||||
// actual results against expectations in a JSON file
|
||||
// (where we can set ignore-failure to either true or
|
||||
// false), add test cases that exercise ignored
|
||||
// failures (both for kMissingExpectations_ErrorBitmask
|
||||
// and kImageMismatch_ErrorBitmask).
|
||||
// failures (both for kMissingExpectations_ErrorType
|
||||
// and kImageMismatch_ErrorType).
|
||||
this->fJsonActualResults_FailureIgnored[testName] =
|
||||
actualResults;
|
||||
} else {
|
||||
if (kEmptyErrorBitfield != (result & kMissingExpectations_ErrorBitmask)) {
|
||||
if (result.includes(kMissingExpectations_ErrorType)) {
|
||||
// TODO: What about the case where there IS an
|
||||
// expected image checksum, but that gm test
|
||||
// doesn't actually run? For now, those cases
|
||||
@ -683,7 +672,7 @@ public:
|
||||
this->fJsonActualResults_NoComparison[testName] =
|
||||
actualResults;
|
||||
}
|
||||
if (kEmptyErrorBitfield != (result & kImageMismatch_ErrorBitmask)) {
|
||||
if (result.includes(kImageMismatch_ErrorType)) {
|
||||
this->fJsonActualResults_Failed[testName] = actualResults;
|
||||
}
|
||||
}
|
||||
@ -716,15 +705,14 @@ public:
|
||||
* @param actualBitmap bitmap generated by this run
|
||||
* @param pdf
|
||||
*/
|
||||
ErrorBitfield compare_test_results_to_stored_expectations(
|
||||
ErrorCombination compare_test_results_to_stored_expectations(
|
||||
GM* gm, const ConfigData& gRec, const char writePath[],
|
||||
SkBitmap& actualBitmap, SkDynamicMemoryWStream* pdf) {
|
||||
|
||||
SkString name = make_name(gm->shortName(), gRec.fName);
|
||||
ErrorBitfield retval = kEmptyErrorBitfield;
|
||||
ErrorCombination errors;
|
||||
|
||||
ExpectationsSource *expectationsSource =
|
||||
this->fExpectationsSource.get();
|
||||
ExpectationsSource *expectationsSource = this->fExpectationsSource.get();
|
||||
if (expectationsSource && (gRec.fFlags & kRead_ConfigFlag)) {
|
||||
/*
|
||||
* Get the expected results for this test, as one or more allowed
|
||||
@ -740,15 +728,15 @@ public:
|
||||
* See comments above complete_bitmap() for more detail.
|
||||
*/
|
||||
Expectations expectations = expectationsSource->get(name.c_str());
|
||||
retval |= compare_to_expectations(expectations, actualBitmap,
|
||||
name, "", true);
|
||||
errors.add(compare_to_expectations(expectations, actualBitmap,
|
||||
name, "", true));
|
||||
} else {
|
||||
// If we are running without expectations, we still want to
|
||||
// record the actual results.
|
||||
Checksum actualChecksum =
|
||||
SkBitmapChecksummer::Compute64(actualBitmap);
|
||||
add_actual_results_to_json_summary(name.c_str(), actualChecksum,
|
||||
kMissingExpectations_ErrorBitmask,
|
||||
ErrorCombination(kMissingExpectations_ErrorType),
|
||||
false);
|
||||
}
|
||||
|
||||
@ -757,11 +745,11 @@ public:
|
||||
// we don't want to write out the actual bitmaps for all
|
||||
// renderModes of all tests! That would be a lot of files.
|
||||
if (writePath && (gRec.fFlags & kWrite_ConfigFlag)) {
|
||||
retval |= write_reference_image(gRec, writePath, "",
|
||||
name, actualBitmap, pdf);
|
||||
errors.add(write_reference_image(gRec, writePath, "",
|
||||
name, actualBitmap, pdf));
|
||||
}
|
||||
|
||||
return retval;
|
||||
return errors;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -773,7 +761,7 @@ public:
|
||||
* @param actualBitmap actual bitmap generated by this run
|
||||
* @param referenceBitmap bitmap we expected to be generated
|
||||
*/
|
||||
ErrorBitfield compare_test_results_to_reference_bitmap(
|
||||
ErrorCombination compare_test_results_to_reference_bitmap(
|
||||
GM* gm, const ConfigData& gRec, const char renderModeDescriptor [],
|
||||
SkBitmap& actualBitmap, const SkBitmap* referenceBitmap) {
|
||||
|
||||
@ -835,20 +823,19 @@ public:
|
||||
|
||||
// Test: draw into a bitmap or pdf.
|
||||
// Depending on flags, possibly compare to an expected image.
|
||||
ErrorBitfield test_drawing(GM* gm,
|
||||
const ConfigData& gRec,
|
||||
const char writePath [],
|
||||
GrContext* context,
|
||||
GrRenderTarget* rt,
|
||||
SkBitmap* bitmap) {
|
||||
ErrorCombination test_drawing(GM* gm,
|
||||
const ConfigData& gRec,
|
||||
const char writePath [],
|
||||
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 (kEmptyErrorBitfield != errors) {
|
||||
ErrorCombination errors = generate_image(gm, gRec, context, rt, bitmap, false);
|
||||
if (!errors.isEmpty()) {
|
||||
// TODO: Add a test to exercise what the stdout and
|
||||
// JSON look like if we get an "early error" while
|
||||
// trying to generate the image.
|
||||
@ -868,11 +855,11 @@ public:
|
||||
gm, gRec, writePath, *bitmap, &document);
|
||||
}
|
||||
|
||||
ErrorBitfield test_deferred_drawing(GM* gm,
|
||||
const ConfigData& gRec,
|
||||
const SkBitmap& referenceBitmap,
|
||||
GrContext* context,
|
||||
GrRenderTarget* rt) {
|
||||
ErrorCombination test_deferred_drawing(GM* gm,
|
||||
const ConfigData& gRec,
|
||||
const SkBitmap& referenceBitmap,
|
||||
GrContext* context,
|
||||
GrRenderTarget* rt) {
|
||||
SkDynamicMemoryWStream document;
|
||||
|
||||
if (gRec.fBackend == kRaster_Backend ||
|
||||
@ -880,19 +867,31 @@ public:
|
||||
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 kEmptyErrorBitfield;
|
||||
ErrorCombination errors = generate_image(gm, gRec, context, rt, &bitmap, true);
|
||||
// TODO(epoger): This logic is the opposite of what is
|
||||
// described above... if we succeeded in generating the
|
||||
// -deferred image, we exit early! We should fix this
|
||||
// ASAP, because it is hiding -deferred errors... but for
|
||||
// now, I'm leaving the logic as it is so that the
|
||||
// refactoring change
|
||||
// https://codereview.chromium.org/12992003/ is unblocked.
|
||||
//
|
||||
// Filed as https://code.google.com/p/skia/issues/detail?id=1180
|
||||
// ('image-surface gm test is failing in "deferred" mode,
|
||||
// and gm is not reporting the failure')
|
||||
if (errors.isEmpty()) {
|
||||
return kEmpty_ErrorCombination;
|
||||
}
|
||||
return compare_test_results_to_reference_bitmap(
|
||||
gm, gRec, "-deferred", bitmap, &referenceBitmap);
|
||||
}
|
||||
return kEmptyErrorBitfield;
|
||||
return kEmpty_ErrorCombination;
|
||||
}
|
||||
|
||||
ErrorBitfield test_pipe_playback(GM* gm,
|
||||
const ConfigData& gRec,
|
||||
const SkBitmap& referenceBitmap) {
|
||||
ErrorBitfield errors = kEmptyErrorBitfield;
|
||||
ErrorCombination test_pipe_playback(GM* gm,
|
||||
const ConfigData& gRec,
|
||||
const SkBitmap& referenceBitmap) {
|
||||
ErrorCombination errors;
|
||||
for (size_t i = 0; i < SK_ARRAY_COUNT(gPipeWritingFlagCombos); ++i) {
|
||||
SkBitmap bitmap;
|
||||
SkISize size = gm->getISize();
|
||||
@ -908,18 +907,18 @@ public:
|
||||
writer.endRecording();
|
||||
SkString string("-pipe");
|
||||
string.append(gPipeWritingFlagCombos[i].name);
|
||||
errors |= compare_test_results_to_reference_bitmap(
|
||||
gm, gRec, string.c_str(), bitmap, &referenceBitmap);
|
||||
if (errors != kEmptyErrorBitfield) {
|
||||
errors.add(compare_test_results_to_reference_bitmap(
|
||||
gm, gRec, string.c_str(), bitmap, &referenceBitmap));
|
||||
if (!errors.isEmpty()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return errors;
|
||||
}
|
||||
|
||||
ErrorBitfield test_tiled_pipe_playback(
|
||||
GM* gm, const ConfigData& gRec, const SkBitmap& referenceBitmap) {
|
||||
ErrorBitfield errors = kEmptyErrorBitfield;
|
||||
ErrorCombination test_tiled_pipe_playback(GM* gm, const ConfigData& gRec,
|
||||
const SkBitmap& referenceBitmap) {
|
||||
ErrorCombination errors;
|
||||
for (size_t i = 0; i < SK_ARRAY_COUNT(gPipeWritingFlagCombos); ++i) {
|
||||
SkBitmap bitmap;
|
||||
SkISize size = gm->getISize();
|
||||
@ -935,9 +934,9 @@ public:
|
||||
writer.endRecording();
|
||||
SkString string("-tiled pipe");
|
||||
string.append(gPipeWritingFlagCombos[i].name);
|
||||
errors |= compare_test_results_to_reference_bitmap(
|
||||
gm, gRec, string.c_str(), bitmap, &referenceBitmap);
|
||||
if (errors != kEmptyErrorBitfield) {
|
||||
errors.add(compare_test_results_to_reference_bitmap(
|
||||
gm, gRec, string.c_str(), bitmap, &referenceBitmap));
|
||||
if (!errors.isEmpty()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -950,6 +949,7 @@ public:
|
||||
//
|
||||
|
||||
bool fUseFileHierarchy;
|
||||
ErrorCombination fIgnorableErrorCombination;
|
||||
|
||||
const char* fMismatchPath;
|
||||
|
||||
@ -1033,6 +1033,12 @@ static SkString configUsage() {
|
||||
return result;
|
||||
}
|
||||
|
||||
// Macro magic to convert a numeric preprocessor token into a string.
|
||||
// Adapted from http://stackoverflow.com/questions/240353/convert-a-preprocessor-token-to-a-string
|
||||
// This should probably be moved into one of our common headers...
|
||||
#define TOSTRING_INTERNAL(x) #x
|
||||
#define TOSTRING(x) TOSTRING_INTERNAL(x)
|
||||
|
||||
// Alphabetized ignoring "no" prefix ("readPath", "noreplay", "resourcePath").
|
||||
DEFINE_string(config, "", configUsage().c_str());
|
||||
DEFINE_bool(deferred, true, "Exercise the deferred rendering test pass.");
|
||||
@ -1042,8 +1048,8 @@ DEFINE_string(excludeConfig, "", "Space delimited list of configs to skip.");
|
||||
DEFINE_bool(forceBWtext, false, "Disable text anti-aliasing.");
|
||||
#if SK_SUPPORT_GPU
|
||||
DEFINE_string(gpuCacheSize, "", "<bytes> <count>: Limit the gpu cache to byte size or "
|
||||
"object count. -1 for either value means use the default. 0 for either "
|
||||
"disables the cache.");
|
||||
"object count. " TOSTRING(DEFAULT_CACHE_VALUE) " for either value means "
|
||||
"use the default. 0 for either disables the cache.");
|
||||
#endif
|
||||
DEFINE_bool(hierarchy, false, "Whether to use multilevel directory structure "
|
||||
"when reading/writing files.");
|
||||
@ -1149,29 +1155,13 @@ template <typename T> void appendUnique(SkTDArray<T>* array, const T& value) {
|
||||
*
|
||||
* Returns all errors encountered while doing so.
|
||||
*/
|
||||
ErrorBitfield run_multiple_configs(GMMain &gmmain, GM *gm, const SkTDArray<size_t> &configs,
|
||||
GrContextFactory *grFactory);
|
||||
ErrorBitfield run_multiple_configs(GMMain &gmmain, GM *gm, const SkTDArray<size_t> &configs,
|
||||
GrContextFactory *grFactory) {
|
||||
ErrorBitfield errorsForAllConfigs = kEmptyErrorBitfield;
|
||||
ErrorCombination run_multiple_configs(GMMain &gmmain, GM *gm, const SkTDArray<size_t> &configs,
|
||||
GrContextFactory *grFactory);
|
||||
ErrorCombination run_multiple_configs(GMMain &gmmain, GM *gm, const SkTDArray<size_t> &configs,
|
||||
GrContextFactory *grFactory) {
|
||||
ErrorCombination errorsForAllConfigs;
|
||||
uint32_t gmFlags = gm->getFlags();
|
||||
|
||||
#if SK_SUPPORT_GPU
|
||||
struct {
|
||||
int fBytes;
|
||||
int fCount;
|
||||
} gpuCacheSize = { -1, -1 }; // -1s mean use the default
|
||||
|
||||
if (FLAGS_gpuCacheSize.count() > 0) {
|
||||
if (FLAGS_gpuCacheSize.count() != 2) {
|
||||
gm_fprintf(stderr, "--gpuCacheSize requires two arguments\n");
|
||||
return -1;
|
||||
}
|
||||
gpuCacheSize.fBytes = atoi(FLAGS_gpuCacheSize[0]);
|
||||
gpuCacheSize.fCount = atoi(FLAGS_gpuCacheSize[1]);
|
||||
}
|
||||
#endif
|
||||
|
||||
for (int i = 0; i < configs.count(); i++) {
|
||||
ConfigData config = gRec[configs[i]];
|
||||
|
||||
@ -1192,12 +1182,12 @@ ErrorBitfield run_multiple_configs(GMMain &gmmain, GM *gm, const SkTDArray<size_
|
||||
|
||||
// Now we know that we want to run this test and record its
|
||||
// success or failure.
|
||||
ErrorBitfield errorsForThisConfig = kEmptyErrorBitfield;
|
||||
ErrorCombination errorsForThisConfig;
|
||||
GrRenderTarget* renderTarget = NULL;
|
||||
#if SK_SUPPORT_GPU
|
||||
SkAutoTUnref<GrRenderTarget> rt;
|
||||
AutoResetGr autogr;
|
||||
if ((kEmptyErrorBitfield == errorsForThisConfig) && (kGPU_Backend == config.fBackend)) {
|
||||
if ((errorsForThisConfig.isEmpty()) && (kGPU_Backend == config.fBackend)) {
|
||||
GrContext* gr = grFactory->get(config.fGLContextType);
|
||||
bool grSuccess = false;
|
||||
if (gr) {
|
||||
@ -1221,16 +1211,16 @@ ErrorBitfield run_multiple_configs(GMMain &gmmain, GM *gm, const SkTDArray<size_
|
||||
size_t bytes;
|
||||
int count;
|
||||
gr->getTextureCacheLimits(&count, &bytes);
|
||||
if (-1 != gpuCacheSize.fBytes) {
|
||||
bytes = static_cast<size_t>(gpuCacheSize.fBytes);
|
||||
if (DEFAULT_CACHE_VALUE != gGpuCacheSizeBytes) {
|
||||
bytes = static_cast<size_t>(gGpuCacheSizeBytes);
|
||||
}
|
||||
if (-1 != gpuCacheSize.fCount) {
|
||||
count = gpuCacheSize.fCount;
|
||||
if (DEFAULT_CACHE_VALUE != gGpuCacheSizeCount) {
|
||||
count = gGpuCacheSizeCount;
|
||||
}
|
||||
gr->setTextureCacheLimits(count, bytes);
|
||||
}
|
||||
if (!grSuccess) {
|
||||
errorsForThisConfig |= kNoGpuContext_ErrorBitmask;
|
||||
errorsForThisConfig.add(kNoGpuContext_ErrorType);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@ -1243,19 +1233,18 @@ ErrorBitfield run_multiple_configs(GMMain &gmmain, GM *gm, const SkTDArray<size_
|
||||
} else {
|
||||
writePath = NULL;
|
||||
}
|
||||
if (kEmptyErrorBitfield == errorsForThisConfig) {
|
||||
errorsForThisConfig |= gmmain.test_drawing(gm, config, writePath, GetGr(),
|
||||
renderTarget, &comparisonBitmap);
|
||||
if (errorsForThisConfig.isEmpty()) {
|
||||
errorsForThisConfig.add(gmmain.test_drawing(gm, config, writePath, GetGr(),
|
||||
renderTarget, &comparisonBitmap));
|
||||
}
|
||||
|
||||
if (FLAGS_deferred && !errorsForThisConfig &&
|
||||
(kGPU_Backend == config.fBackend ||
|
||||
kRaster_Backend == config.fBackend)) {
|
||||
errorsForThisConfig |= gmmain.test_deferred_drawing(gm, config, comparisonBitmap,
|
||||
GetGr(), renderTarget);
|
||||
if (FLAGS_deferred && errorsForThisConfig.isEmpty() &&
|
||||
(kGPU_Backend == config.fBackend || kRaster_Backend == config.fBackend)) {
|
||||
errorsForThisConfig.add(gmmain.test_deferred_drawing(gm, config, comparisonBitmap,
|
||||
GetGr(), renderTarget));
|
||||
}
|
||||
|
||||
errorsForAllConfigs |= errorsForThisConfig;
|
||||
errorsForAllConfigs.add(errorsForThisConfig);
|
||||
}
|
||||
return errorsForAllConfigs;
|
||||
}
|
||||
@ -1267,34 +1256,19 @@ ErrorBitfield run_multiple_configs(GMMain &gmmain, GM *gm, const SkTDArray<size_
|
||||
*
|
||||
* Returns all errors encountered while doing so.
|
||||
*/
|
||||
ErrorBitfield run_multiple_modes(GMMain &gmmain, GM *gm, const ConfigData &compareConfig,
|
||||
const SkBitmap &comparisonBitmap);
|
||||
ErrorBitfield run_multiple_modes(GMMain &gmmain, GM *gm, const ConfigData &compareConfig,
|
||||
const SkBitmap &comparisonBitmap) {
|
||||
SkTDArray<SkScalar> tileGridReplayScales;
|
||||
*tileGridReplayScales.append() = SK_Scalar1; // By default only test at scale 1.0
|
||||
if (FLAGS_tileGridReplayScales.count() > 0) {
|
||||
tileGridReplayScales.reset();
|
||||
for (int i = 0; i < FLAGS_tileGridReplayScales.count(); i++) {
|
||||
double val = atof(FLAGS_tileGridReplayScales[i]);
|
||||
if (0 < val) {
|
||||
*tileGridReplayScales.append() = SkDoubleToScalar(val);
|
||||
}
|
||||
}
|
||||
if (0 == tileGridReplayScales.count()) {
|
||||
// Should have at least one scale
|
||||
gm_fprintf(stderr, "--tileGridReplayScales requires at least one scale.\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
ErrorBitfield errorsForAllModes = kEmptyErrorBitfield;
|
||||
ErrorCombination run_multiple_modes(GMMain &gmmain, GM *gm, const ConfigData &compareConfig,
|
||||
const SkBitmap &comparisonBitmap,
|
||||
const SkTDArray<SkScalar> &tileGridReplayScales);
|
||||
ErrorCombination run_multiple_modes(GMMain &gmmain, GM *gm, const ConfigData &compareConfig,
|
||||
const SkBitmap &comparisonBitmap,
|
||||
const SkTDArray<SkScalar> &tileGridReplayScales) {
|
||||
ErrorCombination errorsForAllModes;
|
||||
uint32_t gmFlags = gm->getFlags();
|
||||
|
||||
// run the picture centric GM steps
|
||||
if (!(gmFlags & GM::kSkipPicture_Flag)) {
|
||||
|
||||
ErrorBitfield pictErrors = kEmptyErrorBitfield;
|
||||
ErrorCombination pictErrors;
|
||||
|
||||
//SkAutoTUnref<SkPicture> pict(generate_new_picture(gm));
|
||||
SkPicture* pict = gmmain.generate_new_picture(gm, kNone_BbhType, 0);
|
||||
@ -1303,18 +1277,18 @@ ErrorBitfield run_multiple_modes(GMMain &gmmain, GM *gm, const ConfigData &compa
|
||||
if (FLAGS_replay) {
|
||||
SkBitmap bitmap;
|
||||
gmmain.generate_image_from_picture(gm, compareConfig, pict, &bitmap);
|
||||
pictErrors |= gmmain.compare_test_results_to_reference_bitmap(
|
||||
gm, compareConfig, "-replay", bitmap, &comparisonBitmap);
|
||||
pictErrors.add(gmmain.compare_test_results_to_reference_bitmap(
|
||||
gm, compareConfig, "-replay", bitmap, &comparisonBitmap));
|
||||
}
|
||||
|
||||
if ((kEmptyErrorBitfield == pictErrors) && FLAGS_serialize) {
|
||||
if ((pictErrors.isEmpty()) && FLAGS_serialize) {
|
||||
SkPicture* repict = gmmain.stream_to_new_picture(*pict);
|
||||
SkAutoUnref aurr(repict);
|
||||
|
||||
SkBitmap bitmap;
|
||||
gmmain.generate_image_from_picture(gm, compareConfig, repict, &bitmap);
|
||||
pictErrors |= gmmain.compare_test_results_to_reference_bitmap(
|
||||
gm, compareConfig, "-serialize", bitmap, &comparisonBitmap);
|
||||
pictErrors.add(gmmain.compare_test_results_to_reference_bitmap(
|
||||
gm, compareConfig, "-serialize", bitmap, &comparisonBitmap));
|
||||
}
|
||||
|
||||
if (FLAGS_writePicturePath.count() == 1) {
|
||||
@ -1325,7 +1299,7 @@ ErrorBitfield run_multiple_modes(GMMain &gmmain, GM *gm, const ConfigData &compa
|
||||
pict->serialize(&stream);
|
||||
}
|
||||
|
||||
errorsForAllModes |= pictErrors;
|
||||
errorsForAllModes.add(pictErrors);
|
||||
}
|
||||
|
||||
// TODO: add a test in which the RTree rendering results in a
|
||||
@ -1338,8 +1312,8 @@ ErrorBitfield run_multiple_modes(GMMain &gmmain, GM *gm, const ConfigData &compa
|
||||
SkAutoUnref aur(pict);
|
||||
SkBitmap bitmap;
|
||||
gmmain.generate_image_from_picture(gm, compareConfig, pict, &bitmap);
|
||||
errorsForAllModes |= gmmain.compare_test_results_to_reference_bitmap(
|
||||
gm, compareConfig, "-rtree", bitmap, &comparisonBitmap);
|
||||
errorsForAllModes.add(gmmain.compare_test_results_to_reference_bitmap(
|
||||
gm, compareConfig, "-rtree", bitmap, &comparisonBitmap));
|
||||
}
|
||||
|
||||
if (!(gmFlags & GM::kSkipPicture_Flag) && FLAGS_tileGrid) {
|
||||
@ -1361,26 +1335,26 @@ ErrorBitfield run_multiple_modes(GMMain &gmmain, GM *gm, const ConfigData &compa
|
||||
suffix += "-scale-";
|
||||
suffix.appendScalar(replayScale);
|
||||
}
|
||||
errorsForAllModes |= gmmain.compare_test_results_to_reference_bitmap(
|
||||
gm, compareConfig, suffix.c_str(), bitmap, &comparisonBitmap);
|
||||
errorsForAllModes.add(gmmain.compare_test_results_to_reference_bitmap(
|
||||
gm, compareConfig, suffix.c_str(), bitmap, &comparisonBitmap));
|
||||
}
|
||||
}
|
||||
|
||||
// run the pipe centric GM steps
|
||||
if (!(gmFlags & GM::kSkipPipe_Flag)) {
|
||||
|
||||
ErrorBitfield pipeErrors = kEmptyErrorBitfield;
|
||||
ErrorCombination pipeErrors;
|
||||
|
||||
if (FLAGS_pipe) {
|
||||
pipeErrors |= gmmain.test_pipe_playback(gm, compareConfig, comparisonBitmap);
|
||||
pipeErrors.add(gmmain.test_pipe_playback(gm, compareConfig, comparisonBitmap));
|
||||
}
|
||||
|
||||
if ((kEmptyErrorBitfield == pipeErrors) &&
|
||||
if ((pipeErrors.isEmpty()) &&
|
||||
FLAGS_tiledPipe && !(gmFlags & GM::kSkipTiled_Flag)) {
|
||||
pipeErrors |= gmmain.test_tiled_pipe_playback(gm, compareConfig, comparisonBitmap);
|
||||
pipeErrors.add(gmmain.test_tiled_pipe_playback(gm, compareConfig, comparisonBitmap));
|
||||
}
|
||||
|
||||
errorsForAllModes |= pipeErrors;
|
||||
errorsForAllModes.add(pipeErrors);
|
||||
}
|
||||
return errorsForAllModes;
|
||||
}
|
||||
@ -1446,6 +1420,37 @@ int tool_main(int argc, char** argv) {
|
||||
}
|
||||
}
|
||||
|
||||
#if SK_SUPPORT_GPU
|
||||
if (FLAGS_gpuCacheSize.count() > 0) {
|
||||
if (FLAGS_gpuCacheSize.count() != 2) {
|
||||
gm_fprintf(stderr, "--gpuCacheSize requires two arguments\n");
|
||||
return -1;
|
||||
}
|
||||
gGpuCacheSizeBytes = atoi(FLAGS_gpuCacheSize[0]);
|
||||
gGpuCacheSizeCount = atoi(FLAGS_gpuCacheSize[1]);
|
||||
} else {
|
||||
gGpuCacheSizeBytes = DEFAULT_CACHE_VALUE;
|
||||
gGpuCacheSizeCount = DEFAULT_CACHE_VALUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
SkTDArray<SkScalar> tileGridReplayScales;
|
||||
*tileGridReplayScales.append() = SK_Scalar1; // By default only test at scale 1.0
|
||||
if (FLAGS_tileGridReplayScales.count() > 0) {
|
||||
tileGridReplayScales.reset();
|
||||
for (int i = 0; i < FLAGS_tileGridReplayScales.count(); i++) {
|
||||
double val = atof(FLAGS_tileGridReplayScales[i]);
|
||||
if (0 < val) {
|
||||
*tileGridReplayScales.append() = SkDoubleToScalar(val);
|
||||
}
|
||||
}
|
||||
if (0 == tileGridReplayScales.count()) {
|
||||
// Should have at least one scale
|
||||
gm_fprintf(stderr, "--tileGridReplayScales requires at least one scale.\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!userConfig) {
|
||||
// if no config is specified by user, add the defaults
|
||||
for (size_t i = 0; i < SK_ARRAY_COUNT(gRec); ++i) {
|
||||
@ -1584,17 +1589,19 @@ int tool_main(int argc, char** argv) {
|
||||
gm_fprintf(stdout, "%sdrawing... %s [%d %d]\n", moduloStr.c_str(), shortName,
|
||||
size.width(), size.height());
|
||||
|
||||
ErrorBitfield testErrors = kEmptyErrorBitfield;
|
||||
testErrors |= run_multiple_configs(gmmain, gm, configs, grFactory);
|
||||
ErrorCombination testErrors;
|
||||
testErrors.add(run_multiple_configs(gmmain, gm, configs, grFactory));
|
||||
|
||||
SkBitmap comparisonBitmap;
|
||||
const ConfigData compareConfig =
|
||||
{ SkBitmap::kARGB_8888_Config, kRaster_Backend, kDontCare_GLContextType, 0, kRW_ConfigFlag, "comparison", false };
|
||||
testErrors |= gmmain.generate_image(gm, compareConfig, NULL, NULL, &comparisonBitmap, false);
|
||||
testErrors.add(gmmain.generate_image(
|
||||
gm, compareConfig, NULL, NULL, &comparisonBitmap, false));
|
||||
|
||||
// TODO(epoger): only run this if gmmain.generate_image() succeeded?
|
||||
// Otherwise, what are we comparing against?
|
||||
testErrors |= run_multiple_modes(gmmain, gm, compareConfig, comparisonBitmap);
|
||||
testErrors.add(run_multiple_modes(gmmain, gm, compareConfig, comparisonBitmap,
|
||||
tileGridReplayScales));
|
||||
|
||||
// Update overall results.
|
||||
// We only tabulate the particular error types that we currently
|
||||
@ -1602,10 +1609,10 @@ int tool_main(int argc, char** argv) {
|
||||
// want to also tabulate other error types, we can do so.
|
||||
testsRun++;
|
||||
if (!gmmain.fExpectationsSource.get() ||
|
||||
(kEmptyErrorBitfield != (kMissingExpectations_ErrorBitmask & testErrors))) {
|
||||
(testErrors.includes(kMissingExpectations_ErrorType))) {
|
||||
testsMissingReferenceImages++;
|
||||
}
|
||||
if (testErrors == (testErrors & kIgnorable_ErrorBitmask)) {
|
||||
if (testErrors.minus(gmmain.fIgnorableErrorCombination).isEmpty()) {
|
||||
testsPassed++;
|
||||
} else {
|
||||
testsFailed++;
|
||||
|
Loading…
Reference in New Issue
Block a user