| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2011 Google Inc. | 2 * Copyright 2011 Google Inc. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 /* | 8 /* |
| 9 * Code for the "gm" (Golden Master) rendering comparison tool. | 9 * Code for the "gm" (Golden Master) rendering comparison tool. |
| 10 * | 10 * |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 79 | 79 |
| 80 #ifdef SK_BUILD_FOR_MAC | 80 #ifdef SK_BUILD_FOR_MAC |
| 81 #include "SkCGUtils.h" | 81 #include "SkCGUtils.h" |
| 82 #define CAN_IMAGE_PDF 1 | 82 #define CAN_IMAGE_PDF 1 |
| 83 #else | 83 #else |
| 84 #define CAN_IMAGE_PDF 0 | 84 #define CAN_IMAGE_PDF 0 |
| 85 #endif | 85 #endif |
| 86 | 86 |
| 87 using namespace skiagm; | 87 using namespace skiagm; |
| 88 | 88 |
| 89 // EPOGER: we don't need FailRec anymore, just an SkString for each entry? |
| 89 struct FailRec { | 90 struct FailRec { |
| 90 SkString fName; | 91 SkString fName; |
| 91 bool fIsPixelError; | 92 bool fIsPixelError; |
| 92 | 93 |
| 93 FailRec() : fIsPixelError(false) {} | 94 FailRec() : fIsPixelError(false) {} |
| 94 FailRec(const SkString& name) : fName(name), fIsPixelError(false) {} | 95 FailRec(const SkString& name) : fName(name), fIsPixelError(false) {} |
| 95 }; | 96 }; |
| 96 | 97 |
| 97 class Iter { | 98 class Iter { |
| 98 public: | 99 public: |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 183 }; | 184 }; |
| 184 | 185 |
| 185 class GMMain { | 186 class GMMain { |
| 186 public: | 187 public: |
| 187 GMMain() { | 188 GMMain() { |
| 188 // Set default values of member variables, which tool_main() | 189 // Set default values of member variables, which tool_main() |
| 189 // may override. | 190 // may override. |
| 190 fUseFileHierarchy = false; | 191 fUseFileHierarchy = false; |
| 191 fIgnorableErrorCombination.add(kMissingExpectations_ErrorType); | 192 fIgnorableErrorCombination.add(kMissingExpectations_ErrorType); |
| 192 fMismatchPath = NULL; | 193 fMismatchPath = NULL; |
| 194 fTestsRun = 0; |
| 193 } | 195 } |
| 194 | 196 |
| 195 SkString make_name(const char shortName[], const char configName[]) { | 197 SkString make_name(const char shortName[], const char configName[]) { |
| 196 SkString name; | 198 SkString name; |
| 197 if (0 == strlen(configName)) { | 199 if (0 == strlen(configName)) { |
| 198 name.append(shortName); | 200 name.append(shortName); |
| 199 } else if (fUseFileHierarchy) { | 201 } else if (fUseFileHierarchy) { |
| 200 name.appendf("%s%c%s", configName, SkPATH_SEPARATOR, shortName); | 202 name.appendf("%s%c%s", configName, SkPATH_SEPARATOR, shortName); |
| 201 } else { | 203 } else { |
| 202 name.appendf("%s_%s", shortName, configName); | 204 name.appendf("%s_%s", shortName, configName); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 236 // TODO(epoger): Now that we have removed force_all_opaque() | 238 // TODO(epoger): Now that we have removed force_all_opaque() |
| 237 // from this method, we should be able to get rid of the | 239 // from this method, we should be able to get rid of the |
| 238 // transformation to 8888 format also. | 240 // transformation to 8888 format also. |
| 239 SkBitmap copy; | 241 SkBitmap copy; |
| 240 bitmap.copyTo(©, SkBitmap::kARGB_8888_Config); | 242 bitmap.copyTo(©, SkBitmap::kARGB_8888_Config); |
| 241 return SkImageEncoder::EncodeFile(path.c_str(), copy, | 243 return SkImageEncoder::EncodeFile(path.c_str(), copy, |
| 242 SkImageEncoder::kPNG_Type, 100); | 244 SkImageEncoder::kPNG_Type, 100); |
| 243 } | 245 } |
| 244 | 246 |
| 245 /** | 247 /** |
| 246 * Records the errors encountered in fFailedTests, except for any error | 248 * Records the errors encountered in fFailedTests. |
| 247 * types we want to ignore. | 249 * |
| 250 * We even record errors that we regard as "ignorable"; we can filter them |
| 251 * out later. |
| 248 */ | 252 */ |
| 253 // EPOGER: rename as RecordResult(), because it increments fTestsRun?? |
| 249 void RecordError(const ErrorCombination& errorCombination, const SkString& n
ame, | 254 void RecordError(const ErrorCombination& errorCombination, const SkString& n
ame, |
| 250 const char renderModeDescriptor []) { | 255 const char renderModeDescriptor []) { |
| 251 // The common case: no error means nothing to record. | 256 fTestsRun++; |
| 252 if (errorCombination.isEmpty()) { | 257 if (errorCombination.isEmpty()) { |
| 253 return; | 258 return; |
| 254 } | 259 } |
| 255 | 260 SkString fullName = make_name(name.c_str(), renderModeDescriptor); |
| 256 // If only certain error type(s) were reported, we know we can ignore th
em. | 261 for (int typeInt = 0; typeInt <= kLast_ErrorType; typeInt++) { |
| 257 if (errorCombination.minus(fIgnorableErrorCombination).isEmpty()) { | 262 ErrorType type = static_cast<ErrorType>(typeInt); |
| 258 return; | 263 if (errorCombination.includes(type)) { |
| 259 } | 264 fFailedTests[type].push_back(fullName); |
| 260 | |
| 261 FailRec& rec = fFailedTests.push_back(make_name(name.c_str(), renderMode
Descriptor)); | |
| 262 rec.fIsPixelError = errorCombination.includes(kImageMismatch_ErrorType); | |
| 263 } | |
| 264 | |
| 265 // List contents of fFailedTests via SkDebug. | |
| 266 void ListErrors() { | |
| 267 for (int i = 0; i < fFailedTests.count(); ++i) { | |
| 268 if (fFailedTests[i].fIsPixelError) { | |
| 269 gm_fprintf(stderr, "\t\t%s pixel_error\n", fFailedTests[i].fName
.c_str()); | |
| 270 } else { | |
| 271 gm_fprintf(stderr, "\t\t%s\n", fFailedTests[i].fName.c_str()); | |
| 272 } | 265 } |
| 273 } | 266 } |
| 274 } | 267 } |
| 275 | 268 |
| 269 /** |
| 270 * Return the number of significant (non-ignorable) errors we have |
| 271 * encountered so far. |
| 272 */ |
| 273 int NumSignificantErrors() { |
| 274 int significantErrors = 0; |
| 275 for (int typeInt = 0; typeInt <= kLast_ErrorType; typeInt++) { |
| 276 ErrorType type = static_cast<ErrorType>(typeInt); |
| 277 if (!fIgnorableErrorCombination.includes(type)) { |
| 278 significantErrors += fFailedTests[type].count(); |
| 279 } |
| 280 } |
| 281 return significantErrors; |
| 282 } |
| 283 |
| 284 /** |
| 285 * List contents of fFailedTests to stdout. |
| 286 */ |
| 287 void ListErrors() { |
| 288 // First, print a single summary line. |
| 289 SkString summary; |
| 290 summary.appendf("Ran %d tests:", fTestsRun); |
| 291 for (int typeInt = 0; typeInt <= kLast_ErrorType; typeInt++) { |
| 292 ErrorType type = static_cast<ErrorType>(typeInt); |
| 293 summary.appendf(" %s=%d", getErrorTypeName(type), fFailedTests[type]
.count()); |
| 294 } |
| 295 gm_fprintf(stdout, "%s\n", summary.c_str()); |
| 296 |
| 297 // Now, for each failure type, list the tests that failed that way. |
| 298 for (int typeInt = 0; typeInt <= kLast_ErrorType; typeInt++) { |
| 299 SkString line; |
| 300 ErrorType type = static_cast<ErrorType>(typeInt); |
| 301 if (fIgnorableErrorCombination.includes(type)) { |
| 302 line.append("[ ] "); |
| 303 } else { |
| 304 line.append("[*] "); |
| 305 } |
| 306 |
| 307 SkTArray<FailRec> *failedTestsOfThisType = &fFailedTests[type]; |
| 308 int count = failedTestsOfThisType->count(); |
| 309 line.appendf("%d %s:", count, getErrorTypeName(type)); |
| 310 for (int i = 0; i < count; ++i) { |
| 311 line.append(" "); |
| 312 line.append((*failedTestsOfThisType)[i].fName); |
| 313 } |
| 314 gm_fprintf(stdout, "%s\n", line.c_str()); |
| 315 } |
| 316 gm_fprintf(stdout, "(results marked with [*] will cause nonzero return v
alue)\n"); |
| 317 } |
| 318 |
| 276 static bool write_document(const SkString& path, | 319 static bool write_document(const SkString& path, |
| 277 const SkDynamicMemoryWStream& document) { | 320 const SkDynamicMemoryWStream& document) { |
| 278 SkFILEWStream stream(path.c_str()); | 321 SkFILEWStream stream(path.c_str()); |
| 279 SkAutoDataUnref data(document.copyToData()); | 322 SkAutoDataUnref data(document.copyToData()); |
| 280 return stream.writeData(data.get()); | 323 return stream.writeData(data.get()); |
| 281 } | 324 } |
| 282 | 325 |
| 283 /** | 326 /** |
| 284 * Prepare an SkBitmap to render a GM into. | 327 * Prepare an SkBitmap to render a GM into. |
| 285 * | 328 * |
| (...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 503 if (kXPS_Backend == gRec.fBackend) { | 546 if (kXPS_Backend == gRec.fBackend) { |
| 504 path = make_filename(writePath, renderModeDescriptor, name.c_str(), | 547 path = make_filename(writePath, renderModeDescriptor, name.c_str(), |
| 505 "xps"); | 548 "xps"); |
| 506 success = write_document(path, *document); | 549 success = write_document(path, *document); |
| 507 } | 550 } |
| 508 if (success) { | 551 if (success) { |
| 509 return kEmpty_ErrorCombination; | 552 return kEmpty_ErrorCombination; |
| 510 } else { | 553 } else { |
| 511 gm_fprintf(stderr, "FAILED to write %s\n", path.c_str()); | 554 gm_fprintf(stderr, "FAILED to write %s\n", path.c_str()); |
| 512 ErrorCombination errors(kWritingReferenceImage_ErrorType); | 555 ErrorCombination errors(kWritingReferenceImage_ErrorType); |
| 556 // EPOGER: don't call RecordError() here? instead, the caller should
call RecordError (or maybe RecordResults) exactly ONCE to properly record one a
ttempt, one partial failure. |
| 513 RecordError(errors, name, renderModeDescriptor); | 557 RecordError(errors, name, renderModeDescriptor); |
| 514 return errors; | 558 return errors; |
| 515 } | 559 } |
| 516 } | 560 } |
| 517 | 561 |
| 518 /** | 562 /** |
| 519 * Log more detail about the mistmatch between expectedBitmap and | 563 * Log more detail about the mistmatch between expectedBitmap and |
| 520 * actualBitmap. | 564 * actualBitmap. |
| 521 */ | 565 */ |
| 522 void report_bitmap_diffs(const SkBitmap& expectedBitmap, const SkBitmap& act
ualBitmap, | 566 void report_bitmap_diffs(const SkBitmap& expectedBitmap, const SkBitmap& act
ualBitmap, |
| (...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 754 | 798 |
| 755 /** | 799 /** |
| 756 * Compare actualBitmap to referenceBitmap. | 800 * Compare actualBitmap to referenceBitmap. |
| 757 * | 801 * |
| 758 * @param gm which test generated the bitmap | 802 * @param gm which test generated the bitmap |
| 759 * @param gRec | 803 * @param gRec |
| 760 * @param renderModeDescriptor | 804 * @param renderModeDescriptor |
| 761 * @param actualBitmap actual bitmap generated by this run | 805 * @param actualBitmap actual bitmap generated by this run |
| 762 * @param referenceBitmap bitmap we expected to be generated | 806 * @param referenceBitmap bitmap we expected to be generated |
| 763 */ | 807 */ |
| 808 // EPOGER: since this is separate from compare_test_results_to_stored_expect
ations(), that should give me the ability to signal different error types for re
nderModeDiscrepancy! |
| 764 ErrorCombination compare_test_results_to_reference_bitmap( | 809 ErrorCombination compare_test_results_to_reference_bitmap( |
| 765 GM* gm, const ConfigData& gRec, const char renderModeDescriptor [], | 810 GM* gm, const ConfigData& gRec, const char renderModeDescriptor [], |
| 766 SkBitmap& actualBitmap, const SkBitmap* referenceBitmap) { | 811 SkBitmap& actualBitmap, const SkBitmap* referenceBitmap) { |
| 767 | 812 |
| 768 SkASSERT(referenceBitmap); | 813 SkASSERT(referenceBitmap); |
| 769 SkString name = make_name(gm->shortName(), gRec.fName); | 814 SkString name = make_name(gm->shortName(), gRec.fName); |
| 770 Expectations expectations(*referenceBitmap); | 815 Expectations expectations(*referenceBitmap); |
| 771 return compare_to_expectations(expectations, actualBitmap, | 816 return compare_to_expectations(expectations, actualBitmap, |
| 772 name, renderModeDescriptor); | 817 name, renderModeDescriptor); |
| 773 } | 818 } |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 873 // -deferred image, we exit early! We should fix this | 918 // -deferred image, we exit early! We should fix this |
| 874 // ASAP, because it is hiding -deferred errors... but for | 919 // ASAP, because it is hiding -deferred errors... but for |
| 875 // now, I'm leaving the logic as it is so that the | 920 // now, I'm leaving the logic as it is so that the |
| 876 // refactoring change | 921 // refactoring change |
| 877 // https://codereview.chromium.org/12992003/ is unblocked. | 922 // https://codereview.chromium.org/12992003/ is unblocked. |
| 878 // | 923 // |
| 879 // Filed as https://code.google.com/p/skia/issues/detail?id=1180 | 924 // Filed as https://code.google.com/p/skia/issues/detail?id=1180 |
| 880 // ('image-surface gm test is failing in "deferred" mode, | 925 // ('image-surface gm test is failing in "deferred" mode, |
| 881 // and gm is not reporting the failure') | 926 // and gm is not reporting the failure') |
| 882 if (errors.isEmpty()) { | 927 if (errors.isEmpty()) { |
| 928 // EPOGER: for cases like this, return some new ErrorType (TestS
kipped?) so we see that they happened |
| 883 return kEmpty_ErrorCombination; | 929 return kEmpty_ErrorCombination; |
| 884 } | 930 } |
| 885 return compare_test_results_to_reference_bitmap( | 931 return compare_test_results_to_reference_bitmap( |
| 886 gm, gRec, "-deferred", bitmap, &referenceBitmap); | 932 gm, gRec, "-deferred", bitmap, &referenceBitmap); |
| 887 } | 933 } |
| 888 return kEmpty_ErrorCombination; | 934 return kEmpty_ErrorCombination; |
| 889 } | 935 } |
| 890 | 936 |
| 891 ErrorCombination test_pipe_playback(GM* gm, | 937 ErrorCombination test_pipe_playback(GM* gm, |
| 892 const ConfigData& gRec, | 938 const ConfigData& gRec, |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 946 // | 992 // |
| 947 // member variables. | 993 // member variables. |
| 948 // They are public for now, to allow easier setting by tool_main(). | 994 // They are public for now, to allow easier setting by tool_main(). |
| 949 // | 995 // |
| 950 | 996 |
| 951 bool fUseFileHierarchy; | 997 bool fUseFileHierarchy; |
| 952 ErrorCombination fIgnorableErrorCombination; | 998 ErrorCombination fIgnorableErrorCombination; |
| 953 | 999 |
| 954 const char* fMismatchPath; | 1000 const char* fMismatchPath; |
| 955 | 1001 |
| 956 // information about all failed tests we have encountered so far | 1002 // collection of tests that have failed with each ErrorType |
| 957 SkTArray<FailRec> fFailedTests; | 1003 SkTArray<FailRec> fFailedTests[kLast_ErrorType+1]; |
| 1004 int fTestsRun; |
| 958 | 1005 |
| 959 // Where to read expectations (expected image checksums, etc.) from. | 1006 // Where to read expectations (expected image checksums, etc.) from. |
| 960 // If unset, we don't do comparisons. | 1007 // If unset, we don't do comparisons. |
| 961 SkAutoTUnref<ExpectationsSource> fExpectationsSource; | 1008 SkAutoTUnref<ExpectationsSource> fExpectationsSource; |
| 962 | 1009 |
| 963 // JSON summaries that we generate as we go (just for output). | 1010 // JSON summaries that we generate as we go (just for output). |
| 964 Json::Value fJsonExpectedResults; | 1011 Json::Value fJsonExpectedResults; |
| 965 Json::Value fJsonActualResults_Failed; | 1012 Json::Value fJsonActualResults_Failed; |
| 966 Json::Value fJsonActualResults_FailureIgnored; | 1013 Json::Value fJsonActualResults_FailureIgnored; |
| 967 Json::Value fJsonActualResults_NoComparison; | 1014 Json::Value fJsonActualResults_NoComparison; |
| (...skipping 291 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1259 ErrorCombination run_multiple_modes(GMMain &gmmain, GM *gm, const ConfigData &co
mpareConfig, | 1306 ErrorCombination run_multiple_modes(GMMain &gmmain, GM *gm, const ConfigData &co
mpareConfig, |
| 1260 const SkBitmap &comparisonBitmap, | 1307 const SkBitmap &comparisonBitmap, |
| 1261 const SkTDArray<SkScalar> &tileGridReplaySca
les); | 1308 const SkTDArray<SkScalar> &tileGridReplaySca
les); |
| 1262 ErrorCombination run_multiple_modes(GMMain &gmmain, GM *gm, const ConfigData &co
mpareConfig, | 1309 ErrorCombination run_multiple_modes(GMMain &gmmain, GM *gm, const ConfigData &co
mpareConfig, |
| 1263 const SkBitmap &comparisonBitmap, | 1310 const SkBitmap &comparisonBitmap, |
| 1264 const SkTDArray<SkScalar> &tileGridReplaySca
les) { | 1311 const SkTDArray<SkScalar> &tileGridReplaySca
les) { |
| 1265 ErrorCombination errorsForAllModes; | 1312 ErrorCombination errorsForAllModes; |
| 1266 uint32_t gmFlags = gm->getFlags(); | 1313 uint32_t gmFlags = gm->getFlags(); |
| 1267 | 1314 |
| 1268 // run the picture centric GM steps | 1315 // run the picture centric GM steps |
| 1316 // EPOGER: record a different error code if we skipped this mode? |
| 1269 if (!(gmFlags & GM::kSkipPicture_Flag)) { | 1317 if (!(gmFlags & GM::kSkipPicture_Flag)) { |
| 1270 | 1318 |
| 1271 ErrorCombination pictErrors; | 1319 ErrorCombination pictErrors; |
| 1272 | 1320 |
| 1273 //SkAutoTUnref<SkPicture> pict(generate_new_picture(gm)); | 1321 //SkAutoTUnref<SkPicture> pict(generate_new_picture(gm)); |
| 1274 SkPicture* pict = gmmain.generate_new_picture(gm, kNone_BbhType, 0); | 1322 SkPicture* pict = gmmain.generate_new_picture(gm, kNone_BbhType, 0); |
| 1275 SkAutoUnref aur(pict); | 1323 SkAutoUnref aur(pict); |
| 1276 | 1324 |
| 1277 if (FLAGS_replay) { | 1325 if (FLAGS_replay) { |
| 1278 SkBitmap bitmap; | 1326 SkBitmap bitmap; |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1352 if ((pipeErrors.isEmpty()) && | 1400 if ((pipeErrors.isEmpty()) && |
| 1353 FLAGS_tiledPipe && !(gmFlags & GM::kSkipTiled_Flag)) { | 1401 FLAGS_tiledPipe && !(gmFlags & GM::kSkipTiled_Flag)) { |
| 1354 pipeErrors.add(gmmain.test_tiled_pipe_playback(gm, compareConfig, co
mparisonBitmap)); | 1402 pipeErrors.add(gmmain.test_tiled_pipe_playback(gm, compareConfig, co
mparisonBitmap)); |
| 1355 } | 1403 } |
| 1356 | 1404 |
| 1357 errorsForAllModes.add(pipeErrors); | 1405 errorsForAllModes.add(pipeErrors); |
| 1358 } | 1406 } |
| 1359 return errorsForAllModes; | 1407 return errorsForAllModes; |
| 1360 } | 1408 } |
| 1361 | 1409 |
| 1410 /** |
| 1411 * Return a list of all entries in an array of strings as a single string |
| 1412 * of this form: |
| 1413 * "item1", "item2", "item3" |
| 1414 */ |
| 1415 SkString list_all(const SkTArray<SkString> &stringArray); |
| 1416 SkString list_all(const SkTArray<SkString> &stringArray) { |
| 1417 SkString total; |
| 1418 for (int i = 0; i < stringArray.count(); i++) { |
| 1419 if (i > 0) { |
| 1420 total.append(", "); |
| 1421 } |
| 1422 total.append("\""); |
| 1423 total.append(stringArray[i]); |
| 1424 total.append("\""); |
| 1425 } |
| 1426 return total; |
| 1427 } |
| 1428 |
| 1429 /** |
| 1430 * Return a list of configuration names, as a single string of this form: |
| 1431 * "item1", "item2", "item3" |
| 1432 * |
| 1433 * @param configs configurations, as a list of indices into gRec |
| 1434 */ |
| 1435 SkString list_all_config_names(const SkTDArray<size_t> &configs); |
| 1436 SkString list_all_config_names(const SkTDArray<size_t> &configs) { |
| 1437 SkString total; |
| 1438 for (int i = 0; i < configs.count(); i++) { |
| 1439 if (i > 0) { |
| 1440 total.append(", "); |
| 1441 } |
| 1442 total.append("\""); |
| 1443 total.append(gRec[configs[i]].fName); |
| 1444 total.append("\""); |
| 1445 } |
| 1446 return total; |
| 1447 } |
| 1448 |
| 1362 int tool_main(int argc, char** argv); | 1449 int tool_main(int argc, char** argv); |
| 1363 int tool_main(int argc, char** argv) { | 1450 int tool_main(int argc, char** argv) { |
| 1364 | 1451 |
| 1365 #if SK_ENABLE_INST_COUNT | 1452 #if SK_ENABLE_INST_COUNT |
| 1366 gPrintInstCount = true; | 1453 gPrintInstCount = true; |
| 1367 #endif | 1454 #endif |
| 1368 | 1455 |
| 1369 SkGraphics::Init(); | 1456 SkGraphics::Init(); |
| 1370 // we don't need to see this during a run | 1457 // we don't need to see this during a run |
| 1371 gSkSuppressFontCachePurgeSpew = true; | 1458 gSkSuppressFontCachePurgeSpew = true; |
| (...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1533 gm_fprintf(stderr, "reading resources from %s\n", FLAGS_resourcePath[0])
; | 1620 gm_fprintf(stderr, "reading resources from %s\n", FLAGS_resourcePath[0])
; |
| 1534 } | 1621 } |
| 1535 | 1622 |
| 1536 if (moduloDivisor <= 0) { | 1623 if (moduloDivisor <= 0) { |
| 1537 moduloRemainder = -1; | 1624 moduloRemainder = -1; |
| 1538 } | 1625 } |
| 1539 if (moduloRemainder < 0 || moduloRemainder >= moduloDivisor) { | 1626 if (moduloRemainder < 0 || moduloRemainder >= moduloDivisor) { |
| 1540 moduloRemainder = -1; | 1627 moduloRemainder = -1; |
| 1541 } | 1628 } |
| 1542 | 1629 |
| 1543 // Accumulate success of all tests. | 1630 int gmsRun = 0; |
| 1544 int testsRun = 0; | |
| 1545 int testsPassed = 0; | |
| 1546 int testsFailed = 0; | |
| 1547 int testsMissingReferenceImages = 0; | |
| 1548 | |
| 1549 int gmIndex = -1; | 1631 int gmIndex = -1; |
| 1550 SkString moduloStr; | 1632 SkString moduloStr; |
| 1551 | 1633 |
| 1552 // If we will be writing out files, prepare subdirectories. | 1634 // If we will be writing out files, prepare subdirectories. |
| 1553 if (FLAGS_writePath.count() == 1) { | 1635 if (FLAGS_writePath.count() == 1) { |
| 1554 if (!sk_mkdir(FLAGS_writePath[0])) { | 1636 if (!sk_mkdir(FLAGS_writePath[0])) { |
| 1555 return -1; | 1637 return -1; |
| 1556 } | 1638 } |
| 1557 if (gmmain.fUseFileHierarchy) { | 1639 if (gmmain.fUseFileHierarchy) { |
| 1558 for (int i = 0; i < configs.count(); i++) { | 1640 for (int i = 0; i < configs.count(); i++) { |
| (...skipping 19 matching lines...) Expand all Loading... |
| 1578 } | 1660 } |
| 1579 moduloStr.printf("[%d.%d] ", gmIndex, moduloDivisor); | 1661 moduloStr.printf("[%d.%d] ", gmIndex, moduloDivisor); |
| 1580 } | 1662 } |
| 1581 | 1663 |
| 1582 const char* shortName = gm->shortName(); | 1664 const char* shortName = gm->shortName(); |
| 1583 if (skip_name(FLAGS_match, shortName)) { | 1665 if (skip_name(FLAGS_match, shortName)) { |
| 1584 SkDELETE(gm); | 1666 SkDELETE(gm); |
| 1585 continue; | 1667 continue; |
| 1586 } | 1668 } |
| 1587 | 1669 |
| 1670 gmsRun++; |
| 1588 SkISize size = gm->getISize(); | 1671 SkISize size = gm->getISize(); |
| 1589 gm_fprintf(stdout, "%sdrawing... %s [%d %d]\n", moduloStr.c_str(), short
Name, | 1672 gm_fprintf(stdout, "%sdrawing... %s [%d %d]\n", moduloStr.c_str(), short
Name, |
| 1590 size.width(), size.height()); | 1673 size.width(), size.height()); |
| 1591 | 1674 |
| 1592 ErrorCombination testErrors; | 1675 run_multiple_configs(gmmain, gm, configs, grFactory); |
| 1593 testErrors.add(run_multiple_configs(gmmain, gm, configs, grFactory)); | |
| 1594 | 1676 |
| 1595 SkBitmap comparisonBitmap; | 1677 SkBitmap comparisonBitmap; |
| 1596 const ConfigData compareConfig = | 1678 const ConfigData compareConfig = |
| 1597 { SkBitmap::kARGB_8888_Config, kRaster_Backend, kDontCare_GLContextT
ype, 0, kRW_ConfigFlag, "comparison", false }; | 1679 { SkBitmap::kARGB_8888_Config, kRaster_Backend, kDontCare_GLContextT
ype, 0, kRW_ConfigFlag, "comparison", false }; |
| 1598 testErrors.add(gmmain.generate_image( | 1680 gmmain.generate_image(gm, compareConfig, NULL, NULL, &comparisonBitmap,
false); |
| 1599 gm, compareConfig, NULL, NULL, &comparisonBitmap, false)); | |
| 1600 | 1681 |
| 1601 // TODO(epoger): only run this if gmmain.generate_image() succeeded? | 1682 // TODO(epoger): only run this if gmmain.generate_image() succeeded? |
| 1602 // Otherwise, what are we comparing against? | 1683 // Otherwise, what are we comparing against? |
| 1603 testErrors.add(run_multiple_modes(gmmain, gm, compareConfig, comparisonB
itmap, | 1684 run_multiple_modes(gmmain, gm, compareConfig, comparisonBitmap, tileGrid
ReplayScales); |
| 1604 tileGridReplayScales)); | |
| 1605 | |
| 1606 // Update overall results. | |
| 1607 // We only tabulate the particular error types that we currently | |
| 1608 // care about (e.g., missing reference images). Later on, if we | |
| 1609 // want to also tabulate other error types, we can do so. | |
| 1610 testsRun++; | |
| 1611 if (!gmmain.fExpectationsSource.get() || | |
| 1612 (testErrors.includes(kMissingExpectations_ErrorType))) { | |
| 1613 testsMissingReferenceImages++; | |
| 1614 } | |
| 1615 if (testErrors.minus(gmmain.fIgnorableErrorCombination).isEmpty()) { | |
| 1616 testsPassed++; | |
| 1617 } else { | |
| 1618 testsFailed++; | |
| 1619 } | |
| 1620 | 1685 |
| 1621 SkDELETE(gm); | 1686 SkDELETE(gm); |
| 1622 } | 1687 } |
| 1623 gm_fprintf(stdout, "Ran %d tests: %d passed, %d failed, %d missing reference
images\n", | 1688 |
| 1624 testsRun, testsPassed, testsFailed, testsMissingReferenceImages); | 1689 // Assemble the list of modes we ran each test through. |
| 1690 // |
| 1691 // TODO(epoger): Instead of assembling this list of modes here, |
| 1692 // can/should we assemble it as we actually run the tests in |
| 1693 // run_multiple_modes()? |
| 1694 SkTArray<SkString> modes; |
| 1695 if (FLAGS_replay) { |
| 1696 modes.push_back(SkString("replay")); |
| 1697 } |
| 1698 if (FLAGS_serialize) { |
| 1699 modes.push_back(SkString("serialize")); |
| 1700 } |
| 1701 if (FLAGS_rtree) { |
| 1702 modes.push_back(SkString("rtree")); |
| 1703 } |
| 1704 if (FLAGS_tileGrid) { |
| 1705 for (int i = 0; i < tileGridReplayScales.count(); i++) { |
| 1706 SkString modeName("tileGrid"); |
| 1707 modeName.appendf("%f", tileGridReplayScales[i]); |
| 1708 modes.push_back(modeName); |
| 1709 } |
| 1710 } |
| 1711 if (FLAGS_pipe) { |
| 1712 for (size_t i = 0; i < SK_ARRAY_COUNT(gPipeWritingFlagCombos); i++) { |
| 1713 SkString modeName("pipe"); |
| 1714 modeName.append(gPipeWritingFlagCombos[i].name); |
| 1715 modes.push_back(modeName); |
| 1716 } |
| 1717 } |
| 1718 if (FLAGS_tiledPipe) { |
| 1719 for (size_t i = 0; i < SK_ARRAY_COUNT(gPipeWritingFlagCombos); i++) { |
| 1720 SkString modeName("tiledPipe"); |
| 1721 modeName.append(gPipeWritingFlagCombos[i].name); |
| 1722 modes.push_back(modeName); |
| 1723 } |
| 1724 } |
| 1725 |
| 1726 // Output summary to stdout. |
| 1727 gm_fprintf(stdout, "Ran %d GMs, each with %d configs [%s] and %d modes [%s],
so there should be a total of %d tests\n", |
| 1728 gmsRun, configs.count(), list_all_config_names(configs).c_str(),
modes.count(), list_all(modes).c_str(), gmsRun * (configs.count() + modes.count(
))); |
| 1729 // EPOGER: what if the expected total number of tests is wrong? |
| 1625 gmmain.ListErrors(); | 1730 gmmain.ListErrors(); |
| 1626 | 1731 |
| 1627 if (FLAGS_writeJsonSummaryPath.count() == 1) { | 1732 if (FLAGS_writeJsonSummaryPath.count() == 1) { |
| 1628 Json::Value actualResults; | 1733 Json::Value actualResults; |
| 1629 actualResults[kJsonKey_ActualResults_Failed] = | 1734 actualResults[kJsonKey_ActualResults_Failed] = |
| 1630 gmmain.fJsonActualResults_Failed; | 1735 gmmain.fJsonActualResults_Failed; |
| 1631 actualResults[kJsonKey_ActualResults_FailureIgnored] = | 1736 actualResults[kJsonKey_ActualResults_FailureIgnored] = |
| 1632 gmmain.fJsonActualResults_FailureIgnored; | 1737 gmmain.fJsonActualResults_FailureIgnored; |
| 1633 actualResults[kJsonKey_ActualResults_NoComparison] = | 1738 actualResults[kJsonKey_ActualResults_NoComparison] = |
| 1634 gmmain.fJsonActualResults_NoComparison; | 1739 gmmain.fJsonActualResults_NoComparison; |
| (...skipping 19 matching lines...) Expand all Loading... |
| 1654 gm_fprintf(stdout, "config: %s %x\n", config.fName, gr); | 1759 gm_fprintf(stdout, "config: %s %x\n", config.fName, gr); |
| 1655 gr->printCacheStats(); | 1760 gr->printCacheStats(); |
| 1656 } | 1761 } |
| 1657 } | 1762 } |
| 1658 #endif | 1763 #endif |
| 1659 | 1764 |
| 1660 delete grFactory; | 1765 delete grFactory; |
| 1661 #endif | 1766 #endif |
| 1662 SkGraphics::Term(); | 1767 SkGraphics::Term(); |
| 1663 | 1768 |
| 1664 return (0 == testsFailed) ? 0 : -1; | 1769 return (0 == gmmain.NumSignificantErrors()) ? 0 : -1; |
| 1665 } | 1770 } |
| 1666 | 1771 |
| 1667 void GMMain::installFilter(SkCanvas* canvas) { | 1772 void GMMain::installFilter(SkCanvas* canvas) { |
| 1668 if (FLAGS_forceBWtext) { | 1773 if (FLAGS_forceBWtext) { |
| 1669 canvas->setDrawFilter(SkNEW(BWTextDrawFilter))->unref(); | 1774 canvas->setDrawFilter(SkNEW(BWTextDrawFilter))->unref(); |
| 1670 } | 1775 } |
| 1671 } | 1776 } |
| 1672 | 1777 |
| 1673 #if !defined(SK_BUILD_FOR_IOS) && !defined(SK_BUILD_FOR_NACL) | 1778 #if !defined(SK_BUILD_FOR_IOS) && !defined(SK_BUILD_FOR_NACL) |
| 1674 int main(int argc, char * const argv[]) { | 1779 int main(int argc, char * const argv[]) { |
| 1675 return tool_main(argc, (char**) argv); | 1780 return tool_main(argc, (char**) argv); |
| 1676 } | 1781 } |
| 1677 #endif | 1782 #endif |
| OLD | NEW |