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 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
73 #include "SkXPSDevice.h" | 73 #include "SkXPSDevice.h" |
74 #endif | 74 #endif |
75 | 75 |
76 #ifdef SK_BUILD_FOR_MAC | 76 #ifdef SK_BUILD_FOR_MAC |
77 #include "SkCGUtils.h" | 77 #include "SkCGUtils.h" |
78 #define CAN_IMAGE_PDF 1 | 78 #define CAN_IMAGE_PDF 1 |
79 #else | 79 #else |
80 #define CAN_IMAGE_PDF 0 | 80 #define CAN_IMAGE_PDF 0 |
81 #endif | 81 #endif |
82 | 82 |
83 // TODO(epoger): We created this ErrorBitfield so that we could record | |
84 // multiple error types for the same comparison. But in practice, we | |
85 // process its final value in switch() statements, which inherently | |
86 // assume that only one error type will be set. | |
87 // I think we should probably change this to be an enum, and thus | |
88 // constrain ourselves to a single error type per comparison. | |
89 typedef int ErrorBitfield; | 83 typedef int ErrorBitfield; |
90 const static ErrorBitfield ERROR_NONE = 0x00; | 84 // an empty bitfield means no errors: |
91 const static ErrorBitfield ERROR_NO_GPU_CONTEXT = 0x01; | 85 const static ErrorBitfield kEmptyErrorBitfield = 0x00; |
92 const static ErrorBitfield ERROR_IMAGE_MISMATCH = 0x02; | 86 // individual error types: |
93 // const static ErrorBitfield ERROR_DIMENSION_MISMATCH = 0x04; DEPRECATED i
n https://codereview.appspot.com/7064047 | 87 const static ErrorBitfield kNoGpuContext_ErrorBitmask = 0x01; |
94 const static ErrorBitfield ERROR_READING_REFERENCE_IMAGE = 0x08; | 88 const static ErrorBitfield kImageMismatch_ErrorBitmask = 0x02; |
95 const static ErrorBitfield ERROR_WRITING_REFERENCE_IMAGE = 0x10; | 89 const static ErrorBitfield kMissingExpectations_ErrorBitmask = 0x04; |
| 90 const static ErrorBitfield kWritingReferenceImage_ErrorBitmask = 0x08; |
| 91 // we typically ignore any errors matching this bitmask: |
| 92 const static ErrorBitfield kIgnorable_ErrorBitmask = kMissingExpectations_ErrorB
itmask; |
96 | 93 |
97 using namespace skiagm; | 94 using namespace skiagm; |
98 | 95 |
99 struct FailRec { | 96 struct FailRec { |
100 SkString fName; | 97 SkString fName; |
101 bool fIsPixelError; | 98 bool fIsPixelError; |
102 | 99 |
103 FailRec() : fIsPixelError(false) {} | 100 FailRec() : fIsPixelError(false) {} |
104 FailRec(const SkString& name) : fName(name), fIsPixelError(false) {} | 101 FailRec(const SkString& name) : fName(name), fIsPixelError(false) {} |
105 }; | 102 }; |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
247 SkBitmap copy; | 244 SkBitmap copy; |
248 bitmap.copyTo(©, SkBitmap::kARGB_8888_Config); | 245 bitmap.copyTo(©, SkBitmap::kARGB_8888_Config); |
249 return SkImageEncoder::EncodeFile(path.c_str(), copy, | 246 return SkImageEncoder::EncodeFile(path.c_str(), copy, |
250 SkImageEncoder::kPNG_Type, 100); | 247 SkImageEncoder::kPNG_Type, 100); |
251 } | 248 } |
252 | 249 |
253 // Records an error in fFailedTests, if we want to record errors | 250 // Records an error in fFailedTests, if we want to record errors |
254 // of this type. | 251 // of this type. |
255 void RecordError(ErrorBitfield errorType, const SkString& name, | 252 void RecordError(ErrorBitfield errorType, const SkString& name, |
256 const char renderModeDescriptor []) { | 253 const char renderModeDescriptor []) { |
257 bool isPixelError; | 254 // The common case: no error means nothing to record. |
258 switch (errorType) { | 255 if (kEmptyErrorBitfield == errorType) { |
259 case ERROR_NONE: | |
260 return; | 256 return; |
261 case ERROR_READING_REFERENCE_IMAGE: | 257 } |
| 258 |
| 259 // If only certain error type(s) were reported, we know we can ignore th
em. |
| 260 if (errorType == (errorType & kIgnorable_ErrorBitmask)) { |
262 return; | 261 return; |
263 case ERROR_IMAGE_MISMATCH: | |
264 isPixelError = true; | |
265 break; | |
266 default: | |
267 isPixelError = false; | |
268 break; | |
269 } | 262 } |
270 | 263 |
271 FailRec& rec = fFailedTests.push_back(make_name( | 264 FailRec& rec = fFailedTests.push_back(make_name( |
272 name.c_str(), renderModeDescriptor)); | 265 name.c_str(), renderModeDescriptor)); |
273 rec.fIsPixelError = isPixelError; | 266 rec.fIsPixelError = (errorType & kImageMismatch_ErrorBitmask); |
274 } | 267 } |
275 | 268 |
276 // List contents of fFailedTests via SkDebug. | 269 // List contents of fFailedTests via SkDebug. |
277 void ListErrors() { | 270 void ListErrors() { |
278 for (int i = 0; i < fFailedTests.count(); ++i) { | 271 for (int i = 0; i < fFailedTests.count(); ++i) { |
279 if (fFailedTests[i].fIsPixelError) { | 272 if (fFailedTests[i].fIsPixelError) { |
280 SkDebugf("\t\t%s pixel_error\n", fFailedTests[i].fName.c_str()); | 273 SkDebugf("\t\t%s pixel_error\n", fFailedTests[i].fName.c_str()); |
281 } else { | 274 } else { |
282 SkDebugf("\t\t%s\n", fFailedTests[i].fName.c_str()); | 275 SkDebugf("\t\t%s\n", fFailedTests[i].fName.c_str()); |
283 } | 276 } |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
403 canvas.reset(new SkDeferredCanvas(device)); | 396 canvas.reset(new SkDeferredCanvas(device)); |
404 } else { | 397 } else { |
405 canvas.reset(new SkCanvas(device)); | 398 canvas.reset(new SkCanvas(device)); |
406 } | 399 } |
407 invokeGM(gm, canvas, false, deferred); | 400 invokeGM(gm, canvas, false, deferred); |
408 canvas->flush(); | 401 canvas->flush(); |
409 } | 402 } |
410 #if SK_SUPPORT_GPU | 403 #if SK_SUPPORT_GPU |
411 else { // GPU | 404 else { // GPU |
412 if (NULL == context) { | 405 if (NULL == context) { |
413 return ERROR_NO_GPU_CONTEXT; | 406 return kNoGpuContext_ErrorBitmask; |
414 } | 407 } |
415 SkAutoTUnref<SkDevice> device(new SkGpuDevice(context, rt)); | 408 SkAutoTUnref<SkDevice> device(new SkGpuDevice(context, rt)); |
416 if (deferred) { | 409 if (deferred) { |
417 canvas.reset(new SkDeferredCanvas(device)); | 410 canvas.reset(new SkDeferredCanvas(device)); |
418 } else { | 411 } else { |
419 canvas.reset(new SkCanvas(device)); | 412 canvas.reset(new SkCanvas(device)); |
420 } | 413 } |
421 invokeGM(gm, canvas, false, deferred); | 414 invokeGM(gm, canvas, false, deferred); |
422 // the device is as large as the current rendertarget, so | 415 // the device is as large as the current rendertarget, so |
423 // we explicitly only readback the amount we expect (in | 416 // we explicitly only readback the amount we expect (in |
424 // size) overwrite our previous allocation | 417 // size) overwrite our previous allocation |
425 bitmap->setConfig(SkBitmap::kARGB_8888_Config, size.fWidth, | 418 bitmap->setConfig(SkBitmap::kARGB_8888_Config, size.fWidth, |
426 size.fHeight); | 419 size.fHeight); |
427 canvas->readPixels(bitmap, 0, 0); | 420 canvas->readPixels(bitmap, 0, 0); |
428 } | 421 } |
429 #endif | 422 #endif |
430 complete_bitmap(bitmap); | 423 complete_bitmap(bitmap); |
431 return ERROR_NONE; | 424 return kEmptyErrorBitfield; |
432 } | 425 } |
433 | 426 |
434 static void generate_image_from_picture(GM* gm, const ConfigData& gRec, | 427 static void generate_image_from_picture(GM* gm, const ConfigData& gRec, |
435 SkPicture* pict, SkBitmap* bitmap, | 428 SkPicture* pict, SkBitmap* bitmap, |
436 SkScalar scale = SK_Scalar1) { | 429 SkScalar scale = SK_Scalar1) { |
437 SkISize size = gm->getISize(); | 430 SkISize size = gm->getISize(); |
438 setup_bitmap(gRec, size, bitmap); | 431 setup_bitmap(gRec, size, bitmap); |
439 SkCanvas canvas(*bitmap); | 432 SkCanvas canvas(*bitmap); |
440 installFilter(&canvas); | 433 installFilter(&canvas); |
441 canvas.scale(scale, scale); | 434 canvas.scale(scale, scale); |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
515 path = make_filename(writePath, renderModeDescriptor, name.c_str(), | 508 path = make_filename(writePath, renderModeDescriptor, name.c_str(), |
516 "pdf"); | 509 "pdf"); |
517 success = write_document(path, *document); | 510 success = write_document(path, *document); |
518 } | 511 } |
519 if (kXPS_Backend == gRec.fBackend) { | 512 if (kXPS_Backend == gRec.fBackend) { |
520 path = make_filename(writePath, renderModeDescriptor, name.c_str(), | 513 path = make_filename(writePath, renderModeDescriptor, name.c_str(), |
521 "xps"); | 514 "xps"); |
522 success = write_document(path, *document); | 515 success = write_document(path, *document); |
523 } | 516 } |
524 if (success) { | 517 if (success) { |
525 return ERROR_NONE; | 518 return kEmptyErrorBitfield; |
526 } else { | 519 } else { |
527 fprintf(stderr, "FAILED to write %s\n", path.c_str()); | 520 fprintf(stderr, "FAILED to write %s\n", path.c_str()); |
528 RecordError(ERROR_WRITING_REFERENCE_IMAGE, name, | 521 RecordError(kWritingReferenceImage_ErrorBitmask, name, |
529 renderModeDescriptor); | 522 renderModeDescriptor); |
530 return ERROR_WRITING_REFERENCE_IMAGE; | 523 return kWritingReferenceImage_ErrorBitmask; |
531 } | 524 } |
532 } | 525 } |
533 | 526 |
534 /** | 527 /** |
535 * Log more detail about the mistmatch between expectedBitmap and | 528 * Log more detail about the mistmatch between expectedBitmap and |
536 * actualBitmap. | 529 * actualBitmap. |
537 */ | 530 */ |
538 void report_bitmap_diffs(const SkBitmap& expectedBitmap, const SkBitmap& act
ualBitmap, | 531 void report_bitmap_diffs(const SkBitmap& expectedBitmap, const SkBitmap& act
ualBitmap, |
539 const char *testName) { | 532 const char *testName) { |
540 const int expectedWidth = expectedBitmap.width(); | 533 const int expectedWidth = expectedBitmap.width(); |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
580 (int)SkGetPackedA32(actualPixel
))); | 573 (int)SkGetPackedA32(actualPixel
))); |
581 } | 574 } |
582 } | 575 } |
583 } | 576 } |
584 SkDebugf("---- %s: %d (of %d) differing pixels, max per-channel mismatch
" | 577 SkDebugf("---- %s: %d (of %d) differing pixels, max per-channel mismatch
" |
585 " R=%d G=%d B=%d A=%d\n", | 578 " R=%d G=%d B=%d A=%d\n", |
586 testName, differingPixels, width*height, errR, errG, errB, errA
); | 579 testName, differingPixels, width*height, errR, errG, errB, errA
); |
587 } | 580 } |
588 | 581 |
589 /** | 582 /** |
590 * Compares actual checksum to expectations. | 583 * Compares actual checksum to expectations. Returns |
591 * Returns ERROR_NONE if they match, or some particular error code otherwise | 584 * kEmptyErrorBitfield if they match, or some combination of |
| 585 * _ErrorBitmask values otherwise. |
592 * | 586 * |
593 * If fMismatchPath has been set, and there are pixel diffs, then the | 587 * If fMismatchPath has been set, and there are pixel diffs, then the |
594 * actual bitmap will be written out to a file within fMismatchPath. | 588 * actual bitmap will be written out to a file within fMismatchPath. |
595 * | 589 * |
596 * @param expectations what expectations to compare actualBitmap against | 590 * @param expectations what expectations to compare actualBitmap against |
597 * @param actualBitmap the image we actually generated | 591 * @param actualBitmap the image we actually generated |
598 * @param baseNameString name of test without renderModeDescriptor added | 592 * @param baseNameString name of test without renderModeDescriptor added |
599 * @param renderModeDescriptor e.g., "-rtree", "-deferred" | 593 * @param renderModeDescriptor e.g., "-rtree", "-deferred" |
600 * @param addToJsonSummary whether to add these results (both actual and | 594 * @param addToJsonSummary whether to add these results (both actual and |
601 * expected) to the JSON summary | 595 * expected) to the JSON summary |
602 * | 596 * |
603 * TODO: For now, addToJsonSummary is only set to true within | 597 * TODO: For now, addToJsonSummary is only set to true within |
604 * compare_test_results_to_stored_expectations(), so results of our | 598 * compare_test_results_to_stored_expectations(), so results of our |
605 * in-memory comparisons (Rtree vs regular, etc.) are not written to the | 599 * in-memory comparisons (Rtree vs regular, etc.) are not written to the |
606 * JSON summary. We may wish to change that. | 600 * JSON summary. We may wish to change that. |
607 */ | 601 */ |
608 ErrorBitfield compare_to_expectations(Expectations expectations, | 602 ErrorBitfield compare_to_expectations(Expectations expectations, |
609 const SkBitmap& actualBitmap, | 603 const SkBitmap& actualBitmap, |
610 const SkString& baseNameString, | 604 const SkString& baseNameString, |
611 const char renderModeDescriptor[], | 605 const char renderModeDescriptor[], |
612 bool addToJsonSummary=false) { | 606 bool addToJsonSummary=false) { |
613 ErrorBitfield retval; | 607 ErrorBitfield retval; |
614 Checksum actualChecksum = SkBitmapChecksummer::Compute64(actualBitmap); | 608 Checksum actualChecksum = SkBitmapChecksummer::Compute64(actualBitmap); |
615 SkString completeNameString = baseNameString; | 609 SkString completeNameString = baseNameString; |
616 completeNameString.append(renderModeDescriptor); | 610 completeNameString.append(renderModeDescriptor); |
617 const char* completeName = completeNameString.c_str(); | 611 const char* completeName = completeNameString.c_str(); |
618 | 612 |
619 if (expectations.empty()) { | 613 if (expectations.empty()) { |
620 retval = ERROR_READING_REFERENCE_IMAGE; | 614 retval = kMissingExpectations_ErrorBitmask; |
621 } else if (expectations.match(actualChecksum)) { | 615 } else if (expectations.match(actualChecksum)) { |
622 retval = ERROR_NONE; | 616 retval = kEmptyErrorBitfield; |
623 } else { | 617 } else { |
624 retval = ERROR_IMAGE_MISMATCH; | 618 retval = kImageMismatch_ErrorBitmask; |
625 | 619 |
626 // Write out the "actuals" for any mismatches, if we have | 620 // Write out the "actuals" for any mismatches, if we have |
627 // been directed to do so. | 621 // been directed to do so. |
628 if (fMismatchPath) { | 622 if (fMismatchPath) { |
629 SkString path = | 623 SkString path = |
630 make_filename(fMismatchPath, renderModeDescriptor, | 624 make_filename(fMismatchPath, renderModeDescriptor, |
631 baseNameString.c_str(), "png"); | 625 baseNameString.c_str(), "png"); |
632 write_bitmap(path, actualBitmap); | 626 write_bitmap(path, actualBitmap); |
633 } | 627 } |
634 | 628 |
(...skipping 20 matching lines...) Expand all Loading... |
655 * Add this result to the appropriate JSON collection of actual results, | 649 * Add this result to the appropriate JSON collection of actual results, |
656 * depending on status. | 650 * depending on status. |
657 */ | 651 */ |
658 void add_actual_results_to_json_summary(const char testName[], | 652 void add_actual_results_to_json_summary(const char testName[], |
659 Checksum actualChecksum, | 653 Checksum actualChecksum, |
660 ErrorBitfield result, | 654 ErrorBitfield result, |
661 bool ignoreFailure) { | 655 bool ignoreFailure) { |
662 Json::Value actualResults; | 656 Json::Value actualResults; |
663 actualResults[kJsonKey_ActualResults_AnyStatus_Checksum] = | 657 actualResults[kJsonKey_ActualResults_AnyStatus_Checksum] = |
664 asJsonValue(actualChecksum); | 658 asJsonValue(actualChecksum); |
665 if (ERROR_NONE == result) { | 659 if (kEmptyErrorBitfield == result) { |
666 this->fJsonActualResults_Succeeded[testName] = actualResults; | 660 this->fJsonActualResults_Succeeded[testName] = actualResults; |
667 } else { | 661 } else { |
668 if (ignoreFailure) { | 662 if (ignoreFailure) { |
669 // TODO: Once we have added the ability to compare | 663 // TODO: Once we have added the ability to compare |
670 // actual results against expectations in a JSON file | 664 // actual results against expectations in a JSON file |
671 // (where we can set ignore-failure to either true or | 665 // (where we can set ignore-failure to either true or |
672 // false), add test cases that exercise ignored | 666 // false), add test cases that exercise ignored |
673 // failures (both for ERROR_READING_REFERENCE_IMAGE | 667 // failures (both for kMissingExpectations_ErrorBitmask |
674 // and ERROR_IMAGE_MISMATCH). | 668 // and kImageMismatch_ErrorBitmask). |
675 this->fJsonActualResults_FailureIgnored[testName] = | 669 this->fJsonActualResults_FailureIgnored[testName] = |
676 actualResults; | 670 actualResults; |
677 } else { | 671 } else { |
678 switch(result) { | 672 if (result & kMissingExpectations_ErrorBitmask) { |
679 case ERROR_READING_REFERENCE_IMAGE: | |
680 // TODO: What about the case where there IS an | 673 // TODO: What about the case where there IS an |
681 // expected image checksum, but that gm test | 674 // expected image checksum, but that gm test |
682 // doesn't actually run? For now, those cases | 675 // doesn't actually run? For now, those cases |
683 // will always be ignored, because gm only looks | 676 // will always be ignored, because gm only looks |
684 // at expectations that correspond to gm tests | 677 // at expectations that correspond to gm tests |
685 // that were actually run. | 678 // that were actually run. |
686 // | 679 // |
687 // Once we have the ability to express | 680 // Once we have the ability to express |
688 // expectations as a JSON file, we should fix this | 681 // expectations as a JSON file, we should fix this |
689 // (and add a test case for which an expectation | 682 // (and add a test case for which an expectation |
690 // is given but the test is never run). | 683 // is given but the test is never run). |
691 this->fJsonActualResults_NoComparison[testName] = | 684 this->fJsonActualResults_NoComparison[testName] = |
692 actualResults; | 685 actualResults; |
693 break; | 686 } |
694 case ERROR_IMAGE_MISMATCH: | 687 if (result & kImageMismatch_ErrorBitmask) { |
695 this->fJsonActualResults_Failed[testName] = actualResults; | 688 this->fJsonActualResults_Failed[testName] = actualResults; |
696 break; | |
697 default: | |
698 fprintf(stderr, "encountered unexpected result %d\n", | |
699 result); | |
700 SkDEBUGFAIL("encountered unexpected result"); | |
701 break; | |
702 } | 689 } |
703 } | 690 } |
704 } | 691 } |
705 } | 692 } |
706 | 693 |
707 /** | 694 /** |
708 * Add this test to the JSON collection of expected results. | 695 * Add this test to the JSON collection of expected results. |
709 */ | 696 */ |
710 void add_expected_results_to_json_summary(const char testName[], | 697 void add_expected_results_to_json_summary(const char testName[], |
711 Expectations expectations) { | 698 Expectations expectations) { |
(...skipping 16 matching lines...) Expand all Loading... |
728 * @param writePath unless this is NULL, write out actual images into this | 715 * @param writePath unless this is NULL, write out actual images into this |
729 * directory | 716 * directory |
730 * @param actualBitmap bitmap generated by this run | 717 * @param actualBitmap bitmap generated by this run |
731 * @param pdf | 718 * @param pdf |
732 */ | 719 */ |
733 ErrorBitfield compare_test_results_to_stored_expectations( | 720 ErrorBitfield compare_test_results_to_stored_expectations( |
734 GM* gm, const ConfigData& gRec, const char writePath[], | 721 GM* gm, const ConfigData& gRec, const char writePath[], |
735 SkBitmap& actualBitmap, SkDynamicMemoryWStream* pdf) { | 722 SkBitmap& actualBitmap, SkDynamicMemoryWStream* pdf) { |
736 | 723 |
737 SkString name = make_name(gm->shortName(), gRec.fName); | 724 SkString name = make_name(gm->shortName(), gRec.fName); |
738 ErrorBitfield retval = ERROR_NONE; | 725 ErrorBitfield retval = kEmptyErrorBitfield; |
739 | 726 |
740 ExpectationsSource *expectationsSource = | 727 ExpectationsSource *expectationsSource = |
741 this->fExpectationsSource.get(); | 728 this->fExpectationsSource.get(); |
742 if (expectationsSource && (gRec.fFlags & kRead_ConfigFlag)) { | 729 if (expectationsSource && (gRec.fFlags & kRead_ConfigFlag)) { |
743 /* | 730 /* |
744 * Get the expected results for this test, as one or more allowed | 731 * Get the expected results for this test, as one or more allowed |
745 * checksums. The current implementation of expectationsSource | 732 * checksums. The current implementation of expectationsSource |
746 * get this by computing the checksum of a single PNG file on disk. | 733 * get this by computing the checksum of a single PNG file on disk. |
747 * | 734 * |
748 * TODO(epoger): This relies on the fact that | 735 * TODO(epoger): This relies on the fact that |
749 * force_all_opaque() was called on the bitmap before it | 736 * force_all_opaque() was called on the bitmap before it |
750 * was written to disk as a PNG in the first place. If | 737 * was written to disk as a PNG in the first place. If |
751 * not, the checksum returned here may not match the | 738 * not, the checksum returned here may not match the |
752 * checksum of actualBitmap, which *has* been run through | 739 * checksum of actualBitmap, which *has* been run through |
753 * force_all_opaque(). | 740 * force_all_opaque(). |
754 * See comments above complete_bitmap() for more detail. | 741 * See comments above complete_bitmap() for more detail. |
755 */ | 742 */ |
756 Expectations expectations = expectationsSource->get(name.c_str()); | 743 Expectations expectations = expectationsSource->get(name.c_str()); |
757 retval |= compare_to_expectations(expectations, actualBitmap, | 744 retval |= compare_to_expectations(expectations, actualBitmap, |
758 name, "", true); | 745 name, "", true); |
759 } else { | 746 } else { |
760 // If we are running without expectations, we still want to | 747 // If we are running without expectations, we still want to |
761 // record the actual results. | 748 // record the actual results. |
762 Checksum actualChecksum = | 749 Checksum actualChecksum = |
763 SkBitmapChecksummer::Compute64(actualBitmap); | 750 SkBitmapChecksummer::Compute64(actualBitmap); |
764 add_actual_results_to_json_summary(name.c_str(), actualChecksum, | 751 add_actual_results_to_json_summary(name.c_str(), actualChecksum, |
765 ERROR_READING_REFERENCE_IMAGE, | 752 kMissingExpectations_ErrorBitmask
, |
766 false); | 753 false); |
767 } | 754 } |
768 | 755 |
769 // TODO: Consider moving this into compare_to_expectations(), | 756 // TODO: Consider moving this into compare_to_expectations(), |
770 // similar to fMismatchPath... for now, we don't do that, because | 757 // similar to fMismatchPath... for now, we don't do that, because |
771 // we don't want to write out the actual bitmaps for all | 758 // we don't want to write out the actual bitmaps for all |
772 // renderModes of all tests! That would be a lot of files. | 759 // renderModes of all tests! That would be a lot of files. |
773 if (writePath && (gRec.fFlags & kWrite_ConfigFlag)) { | 760 if (writePath && (gRec.fFlags & kWrite_ConfigFlag)) { |
774 retval |= write_reference_image(gRec, writePath, "", | 761 retval |= write_reference_image(gRec, writePath, "", |
775 name, actualBitmap, pdf); | 762 name, actualBitmap, pdf); |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
855 GrContext* context, | 842 GrContext* context, |
856 GrRenderTarget* rt, | 843 GrRenderTarget* rt, |
857 SkBitmap* bitmap) { | 844 SkBitmap* bitmap) { |
858 SkDynamicMemoryWStream document; | 845 SkDynamicMemoryWStream document; |
859 | 846 |
860 if (gRec.fBackend == kRaster_Backend || | 847 if (gRec.fBackend == kRaster_Backend || |
861 gRec.fBackend == kGPU_Backend) { | 848 gRec.fBackend == kGPU_Backend) { |
862 // Early exit if we can't generate the image. | 849 // Early exit if we can't generate the image. |
863 ErrorBitfield errors = generate_image(gm, gRec, context, rt, bitmap, | 850 ErrorBitfield errors = generate_image(gm, gRec, context, rt, bitmap, |
864 false); | 851 false); |
865 if (ERROR_NONE != errors) { | 852 if (kEmptyErrorBitfield != errors) { |
866 // TODO: Add a test to exercise what the stdout and | 853 // TODO: Add a test to exercise what the stdout and |
867 // JSON look like if we get an "early error" while | 854 // JSON look like if we get an "early error" while |
868 // trying to generate the image. | 855 // trying to generate the image. |
869 return errors; | 856 return errors; |
870 } | 857 } |
871 } else if (gRec.fBackend == kPDF_Backend) { | 858 } else if (gRec.fBackend == kPDF_Backend) { |
872 generate_pdf(gm, document); | 859 generate_pdf(gm, document); |
873 #if CAN_IMAGE_PDF | 860 #if CAN_IMAGE_PDF |
874 SkAutoDataUnref data(document.copyToData()); | 861 SkAutoDataUnref data(document.copyToData()); |
875 SkMemoryStream stream(data->data(), data->size()); | 862 SkMemoryStream stream(data->data(), data->size()); |
(...skipping 12 matching lines...) Expand all Loading... |
888 GrContext* context, | 875 GrContext* context, |
889 GrRenderTarget* rt) { | 876 GrRenderTarget* rt) { |
890 SkDynamicMemoryWStream document; | 877 SkDynamicMemoryWStream document; |
891 | 878 |
892 if (gRec.fBackend == kRaster_Backend || | 879 if (gRec.fBackend == kRaster_Backend || |
893 gRec.fBackend == kGPU_Backend) { | 880 gRec.fBackend == kGPU_Backend) { |
894 SkBitmap bitmap; | 881 SkBitmap bitmap; |
895 // Early exit if we can't generate the image, but this is | 882 // Early exit if we can't generate the image, but this is |
896 // expected in some cases, so don't report a test failure. | 883 // expected in some cases, so don't report a test failure. |
897 if (!generate_image(gm, gRec, context, rt, &bitmap, true)) { | 884 if (!generate_image(gm, gRec, context, rt, &bitmap, true)) { |
898 return ERROR_NONE; | 885 return kEmptyErrorBitfield; |
899 } | 886 } |
900 return compare_test_results_to_reference_bitmap( | 887 return compare_test_results_to_reference_bitmap( |
901 gm, gRec, "-deferred", bitmap, &referenceBitmap); | 888 gm, gRec, "-deferred", bitmap, &referenceBitmap); |
902 } | 889 } |
903 return ERROR_NONE; | 890 return kEmptyErrorBitfield; |
904 } | 891 } |
905 | 892 |
906 ErrorBitfield test_pipe_playback(GM* gm, | 893 ErrorBitfield test_pipe_playback(GM* gm, |
907 const ConfigData& gRec, | 894 const ConfigData& gRec, |
908 const SkBitmap& referenceBitmap) { | 895 const SkBitmap& referenceBitmap) { |
909 ErrorBitfield errors = ERROR_NONE; | 896 ErrorBitfield errors = kEmptyErrorBitfield; |
910 for (size_t i = 0; i < SK_ARRAY_COUNT(gPipeWritingFlagCombos); ++i) { | 897 for (size_t i = 0; i < SK_ARRAY_COUNT(gPipeWritingFlagCombos); ++i) { |
911 SkBitmap bitmap; | 898 SkBitmap bitmap; |
912 SkISize size = gm->getISize(); | 899 SkISize size = gm->getISize(); |
913 setup_bitmap(gRec, size, &bitmap); | 900 setup_bitmap(gRec, size, &bitmap); |
914 SkCanvas canvas(bitmap); | 901 SkCanvas canvas(bitmap); |
915 PipeController pipeController(&canvas); | 902 PipeController pipeController(&canvas); |
916 SkGPipeWriter writer; | 903 SkGPipeWriter writer; |
917 SkCanvas* pipeCanvas = writer.startRecording( | 904 SkCanvas* pipeCanvas = writer.startRecording( |
918 &pipeController, gPipeWritingFlagCombos[i].flags); | 905 &pipeController, gPipeWritingFlagCombos[i].flags); |
919 invokeGM(gm, pipeCanvas, false, false); | 906 invokeGM(gm, pipeCanvas, false, false); |
920 complete_bitmap(&bitmap); | 907 complete_bitmap(&bitmap); |
921 writer.endRecording(); | 908 writer.endRecording(); |
922 SkString string("-pipe"); | 909 SkString string("-pipe"); |
923 string.append(gPipeWritingFlagCombos[i].name); | 910 string.append(gPipeWritingFlagCombos[i].name); |
924 errors |= compare_test_results_to_reference_bitmap( | 911 errors |= compare_test_results_to_reference_bitmap( |
925 gm, gRec, string.c_str(), bitmap, &referenceBitmap); | 912 gm, gRec, string.c_str(), bitmap, &referenceBitmap); |
926 if (errors != ERROR_NONE) { | 913 if (errors != kEmptyErrorBitfield) { |
927 break; | 914 break; |
928 } | 915 } |
929 } | 916 } |
930 return errors; | 917 return errors; |
931 } | 918 } |
932 | 919 |
933 ErrorBitfield test_tiled_pipe_playback( | 920 ErrorBitfield test_tiled_pipe_playback( |
934 GM* gm, const ConfigData& gRec, const SkBitmap& referenceBitmap) { | 921 GM* gm, const ConfigData& gRec, const SkBitmap& referenceBitmap) { |
935 ErrorBitfield errors = ERROR_NONE; | 922 ErrorBitfield errors = kEmptyErrorBitfield; |
936 for (size_t i = 0; i < SK_ARRAY_COUNT(gPipeWritingFlagCombos); ++i) { | 923 for (size_t i = 0; i < SK_ARRAY_COUNT(gPipeWritingFlagCombos); ++i) { |
937 SkBitmap bitmap; | 924 SkBitmap bitmap; |
938 SkISize size = gm->getISize(); | 925 SkISize size = gm->getISize(); |
939 setup_bitmap(gRec, size, &bitmap); | 926 setup_bitmap(gRec, size, &bitmap); |
940 SkCanvas canvas(bitmap); | 927 SkCanvas canvas(bitmap); |
941 TiledPipeController pipeController(bitmap); | 928 TiledPipeController pipeController(bitmap); |
942 SkGPipeWriter writer; | 929 SkGPipeWriter writer; |
943 SkCanvas* pipeCanvas = writer.startRecording( | 930 SkCanvas* pipeCanvas = writer.startRecording( |
944 &pipeController, gPipeWritingFlagCombos[i].flags); | 931 &pipeController, gPipeWritingFlagCombos[i].flags); |
945 invokeGM(gm, pipeCanvas, false, false); | 932 invokeGM(gm, pipeCanvas, false, false); |
946 complete_bitmap(&bitmap); | 933 complete_bitmap(&bitmap); |
947 writer.endRecording(); | 934 writer.endRecording(); |
948 SkString string("-tiled pipe"); | 935 SkString string("-tiled pipe"); |
949 string.append(gPipeWritingFlagCombos[i].name); | 936 string.append(gPipeWritingFlagCombos[i].name); |
950 errors |= compare_test_results_to_reference_bitmap( | 937 errors |= compare_test_results_to_reference_bitmap( |
951 gm, gRec, string.c_str(), bitmap, &referenceBitmap); | 938 gm, gRec, string.c_str(), bitmap, &referenceBitmap); |
952 if (errors != ERROR_NONE) { | 939 if (errors != kEmptyErrorBitfield) { |
953 break; | 940 break; |
954 } | 941 } |
955 } | 942 } |
956 return errors; | 943 return errors; |
957 } | 944 } |
958 | 945 |
959 // | 946 // |
960 // member variables. | 947 // member variables. |
961 // They are public for now, to allow easier setting by tool_main(). | 948 // They are public for now, to allow easier setting by tool_main(). |
962 // | 949 // |
(...skipping 494 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1457 const char* shortName = gm->shortName(); | 1444 const char* shortName = gm->shortName(); |
1458 if (skip_name(fMatches, shortName)) { | 1445 if (skip_name(fMatches, shortName)) { |
1459 SkDELETE(gm); | 1446 SkDELETE(gm); |
1460 continue; | 1447 continue; |
1461 } | 1448 } |
1462 | 1449 |
1463 SkISize size = gm->getISize(); | 1450 SkISize size = gm->getISize(); |
1464 SkDebugf("%sdrawing... %s [%d %d]\n", moduloStr.c_str(), shortName, | 1451 SkDebugf("%sdrawing... %s [%d %d]\n", moduloStr.c_str(), shortName, |
1465 size.width(), size.height()); | 1452 size.width(), size.height()); |
1466 | 1453 |
1467 ErrorBitfield testErrors = ERROR_NONE; | 1454 ErrorBitfield testErrors = kEmptyErrorBitfield; |
1468 uint32_t gmFlags = gm->getFlags(); | 1455 uint32_t gmFlags = gm->getFlags(); |
1469 | 1456 |
1470 for (int i = 0; i < configs.count(); i++) { | 1457 for (int i = 0; i < configs.count(); i++) { |
1471 ConfigData config = gRec[configs[i]]; | 1458 ConfigData config = gRec[configs[i]]; |
1472 | 1459 |
1473 // Skip any tests that we don't even need to try. | 1460 // Skip any tests that we don't even need to try. |
1474 if ((kPDF_Backend == config.fBackend) && | 1461 if ((kPDF_Backend == config.fBackend) && |
1475 (!doPDF || (gmFlags & GM::kSkipPDF_Flag))) | 1462 (!doPDF || (gmFlags & GM::kSkipPDF_Flag))) |
1476 { | 1463 { |
1477 continue; | 1464 continue; |
1478 } | 1465 } |
1479 if ((gmFlags & GM::kSkip565_Flag) && | 1466 if ((gmFlags & GM::kSkip565_Flag) && |
1480 (kRaster_Backend == config.fBackend) && | 1467 (kRaster_Backend == config.fBackend) && |
1481 (SkBitmap::kRGB_565_Config == config.fConfig)) { | 1468 (SkBitmap::kRGB_565_Config == config.fConfig)) { |
1482 continue; | 1469 continue; |
1483 } | 1470 } |
1484 | 1471 |
1485 // Now we know that we want to run this test and record its | 1472 // Now we know that we want to run this test and record its |
1486 // success or failure. | 1473 // success or failure. |
1487 ErrorBitfield renderErrors = ERROR_NONE; | 1474 ErrorBitfield renderErrors = kEmptyErrorBitfield; |
1488 GrRenderTarget* renderTarget = NULL; | 1475 GrRenderTarget* renderTarget = NULL; |
1489 #if SK_SUPPORT_GPU | 1476 #if SK_SUPPORT_GPU |
1490 SkAutoTUnref<GrRenderTarget> rt; | 1477 SkAutoTUnref<GrRenderTarget> rt; |
1491 AutoResetGr autogr; | 1478 AutoResetGr autogr; |
1492 if ((ERROR_NONE == renderErrors) && | 1479 if ((kEmptyErrorBitfield == renderErrors) && |
1493 kGPU_Backend == config.fBackend) { | 1480 kGPU_Backend == config.fBackend) { |
1494 GrContext* gr = grFactory->get(config.fGLContextType); | 1481 GrContext* gr = grFactory->get(config.fGLContextType); |
1495 bool grSuccess = false; | 1482 bool grSuccess = false; |
1496 if (gr) { | 1483 if (gr) { |
1497 // create a render target to back the device | 1484 // create a render target to back the device |
1498 GrTextureDesc desc; | 1485 GrTextureDesc desc; |
1499 desc.fConfig = kSkia8888_GrPixelConfig; | 1486 desc.fConfig = kSkia8888_GrPixelConfig; |
1500 desc.fFlags = kRenderTarget_GrTextureFlagBit; | 1487 desc.fFlags = kRenderTarget_GrTextureFlagBit; |
1501 desc.fWidth = gm->getISize().width(); | 1488 desc.fWidth = gm->getISize().width(); |
1502 desc.fHeight = gm->getISize().height(); | 1489 desc.fHeight = gm->getISize().height(); |
1503 desc.fSampleCnt = config.fSampleCnt; | 1490 desc.fSampleCnt = config.fSampleCnt; |
1504 GrTexture* tex = gr->createUncachedTexture(desc, NULL, 0); | 1491 GrTexture* tex = gr->createUncachedTexture(desc, NULL, 0); |
1505 if (tex) { | 1492 if (tex) { |
1506 rt.reset(tex->asRenderTarget()); | 1493 rt.reset(tex->asRenderTarget()); |
1507 rt.get()->ref(); | 1494 rt.get()->ref(); |
1508 tex->unref(); | 1495 tex->unref(); |
1509 autogr.set(gr); | 1496 autogr.set(gr); |
1510 renderTarget = rt.get(); | 1497 renderTarget = rt.get(); |
1511 grSuccess = NULL != renderTarget; | 1498 grSuccess = NULL != renderTarget; |
1512 } | 1499 } |
1513 } | 1500 } |
1514 if (!grSuccess) { | 1501 if (!grSuccess) { |
1515 renderErrors |= ERROR_NO_GPU_CONTEXT; | 1502 renderErrors |= kNoGpuContext_ErrorBitmask; |
1516 } | 1503 } |
1517 } | 1504 } |
1518 #endif | 1505 #endif |
1519 | 1506 |
1520 SkBitmap comparisonBitmap; | 1507 SkBitmap comparisonBitmap; |
1521 | 1508 |
1522 if (ERROR_NONE == renderErrors) { | 1509 if (kEmptyErrorBitfield == renderErrors) { |
1523 renderErrors |= gmmain.test_drawing(gm, config, writePath, | 1510 renderErrors |= gmmain.test_drawing(gm, config, writePath, |
1524 GetGr(), | 1511 GetGr(), |
1525 renderTarget, | 1512 renderTarget, |
1526 &comparisonBitmap); | 1513 &comparisonBitmap); |
1527 } | 1514 } |
1528 | 1515 |
1529 if (doDeferred && !renderErrors && | 1516 if (doDeferred && !renderErrors && |
1530 (kGPU_Backend == config.fBackend || | 1517 (kGPU_Backend == config.fBackend || |
1531 kRaster_Backend == config.fBackend)) { | 1518 kRaster_Backend == config.fBackend)) { |
1532 renderErrors |= gmmain.test_deferred_drawing(gm, config, | 1519 renderErrors |= gmmain.test_deferred_drawing(gm, config, |
1533 comparisonBitmap, | 1520 comparisonBitmap, |
1534 GetGr(), | 1521 GetGr(), |
1535 renderTarget); | 1522 renderTarget); |
1536 } | 1523 } |
1537 | 1524 |
1538 testErrors |= renderErrors; | 1525 testErrors |= renderErrors; |
1539 } | 1526 } |
1540 | 1527 |
1541 SkBitmap comparisonBitmap; | 1528 SkBitmap comparisonBitmap; |
1542 const ConfigData compareConfig = | 1529 const ConfigData compareConfig = |
1543 { SkBitmap::kARGB_8888_Config, kRaster_Backend, kDontCare_GLContextT
ype, 0, kRW_ConfigFlag, "comparison" }; | 1530 { SkBitmap::kARGB_8888_Config, kRaster_Backend, kDontCare_GLContextT
ype, 0, kRW_ConfigFlag, "comparison" }; |
1544 testErrors |= gmmain.generate_image(gm, compareConfig, NULL, NULL, &comp
arisonBitmap, false); | 1531 testErrors |= gmmain.generate_image(gm, compareConfig, NULL, NULL, &comp
arisonBitmap, false); |
1545 | 1532 |
1546 // run the picture centric GM steps | 1533 // run the picture centric GM steps |
1547 if (!(gmFlags & GM::kSkipPicture_Flag)) { | 1534 if (!(gmFlags & GM::kSkipPicture_Flag)) { |
1548 | 1535 |
1549 ErrorBitfield pictErrors = ERROR_NONE; | 1536 ErrorBitfield pictErrors = kEmptyErrorBitfield; |
1550 | 1537 |
1551 //SkAutoTUnref<SkPicture> pict(generate_new_picture(gm)); | 1538 //SkAutoTUnref<SkPicture> pict(generate_new_picture(gm)); |
1552 SkPicture* pict = gmmain.generate_new_picture(gm, kNone_BbhType, 0); | 1539 SkPicture* pict = gmmain.generate_new_picture(gm, kNone_BbhType, 0); |
1553 SkAutoUnref aur(pict); | 1540 SkAutoUnref aur(pict); |
1554 | 1541 |
1555 if ((ERROR_NONE == testErrors) && doReplay) { | 1542 if ((kEmptyErrorBitfield == testErrors) && doReplay) { |
1556 SkBitmap bitmap; | 1543 SkBitmap bitmap; |
1557 gmmain.generate_image_from_picture(gm, compareConfig, pict, | 1544 gmmain.generate_image_from_picture(gm, compareConfig, pict, |
1558 &bitmap); | 1545 &bitmap); |
1559 pictErrors |= gmmain.compare_test_results_to_reference_bitmap( | 1546 pictErrors |= gmmain.compare_test_results_to_reference_bitmap( |
1560 gm, compareConfig, "-replay", bitmap, &comparisonBitmap); | 1547 gm, compareConfig, "-replay", bitmap, &comparisonBitmap); |
1561 } | 1548 } |
1562 | 1549 |
1563 if ((ERROR_NONE == testErrors) && | 1550 if ((kEmptyErrorBitfield == testErrors) && |
1564 (ERROR_NONE == pictErrors) && | 1551 (kEmptyErrorBitfield == pictErrors) && |
1565 doSerialize) { | 1552 doSerialize) { |
1566 SkPicture* repict = gmmain.stream_to_new_picture(*pict); | 1553 SkPicture* repict = gmmain.stream_to_new_picture(*pict); |
1567 SkAutoUnref aurr(repict); | 1554 SkAutoUnref aurr(repict); |
1568 | 1555 |
1569 SkBitmap bitmap; | 1556 SkBitmap bitmap; |
1570 gmmain.generate_image_from_picture(gm, compareConfig, repict, | 1557 gmmain.generate_image_from_picture(gm, compareConfig, repict, |
1571 &bitmap); | 1558 &bitmap); |
1572 pictErrors |= gmmain.compare_test_results_to_reference_bitmap( | 1559 pictErrors |= gmmain.compare_test_results_to_reference_bitmap( |
1573 gm, compareConfig, "-serialize", bitmap, &comparisonBitmap); | 1560 gm, compareConfig, "-serialize", bitmap, &comparisonBitmap); |
1574 } | 1561 } |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1622 } | 1609 } |
1623 testErrors |= gmmain.compare_test_results_to_reference_bitmap( | 1610 testErrors |= gmmain.compare_test_results_to_reference_bitmap( |
1624 gm, compareConfig, suffix.c_str(), bitmap, | 1611 gm, compareConfig, suffix.c_str(), bitmap, |
1625 &comparisonBitmap); | 1612 &comparisonBitmap); |
1626 } | 1613 } |
1627 } | 1614 } |
1628 | 1615 |
1629 // run the pipe centric GM steps | 1616 // run the pipe centric GM steps |
1630 if (!(gmFlags & GM::kSkipPipe_Flag)) { | 1617 if (!(gmFlags & GM::kSkipPipe_Flag)) { |
1631 | 1618 |
1632 ErrorBitfield pipeErrors = ERROR_NONE; | 1619 ErrorBitfield pipeErrors = kEmptyErrorBitfield; |
1633 | 1620 |
1634 if ((ERROR_NONE == testErrors) && doPipe) { | 1621 if ((kEmptyErrorBitfield == testErrors) && doPipe) { |
1635 pipeErrors |= gmmain.test_pipe_playback(gm, compareConfig, | 1622 pipeErrors |= gmmain.test_pipe_playback(gm, compareConfig, |
1636 comparisonBitmap); | 1623 comparisonBitmap); |
1637 } | 1624 } |
1638 | 1625 |
1639 if ((ERROR_NONE == testErrors) && | 1626 if ((kEmptyErrorBitfield == testErrors) && |
1640 (ERROR_NONE == pipeErrors) && | 1627 (kEmptyErrorBitfield == pipeErrors) && |
1641 doTiledPipe && !(gmFlags & GM::kSkipTiled_Flag)) { | 1628 doTiledPipe && !(gmFlags & GM::kSkipTiled_Flag)) { |
1642 pipeErrors |= gmmain.test_tiled_pipe_playback(gm, compareConfig, | 1629 pipeErrors |= gmmain.test_tiled_pipe_playback(gm, compareConfig, |
1643 comparisonBitmap); | 1630 comparisonBitmap); |
1644 } | 1631 } |
1645 | 1632 |
1646 testErrors |= pipeErrors; | 1633 testErrors |= pipeErrors; |
1647 } | 1634 } |
1648 | 1635 |
1649 // Update overall results. | 1636 // Update overall results. |
1650 // We only tabulate the particular error types that we currently | 1637 // We only tabulate the particular error types that we currently |
1651 // care about (e.g., missing reference images). Later on, if we | 1638 // care about (e.g., missing reference images). Later on, if we |
1652 // want to also tabulate other error types, we can do so. | 1639 // want to also tabulate other error types, we can do so. |
1653 testsRun++; | 1640 testsRun++; |
1654 if (!gmmain.fExpectationsSource.get() || | 1641 if (!gmmain.fExpectationsSource.get() || |
1655 (ERROR_READING_REFERENCE_IMAGE & testErrors)) { | 1642 (kMissingExpectations_ErrorBitmask & testErrors)) { |
1656 testsMissingReferenceImages++; | 1643 testsMissingReferenceImages++; |
1657 } | 1644 } |
1658 if (ERROR_NONE == testErrors || ERROR_READING_REFERENCE_IMAGE == testErr
ors) { | 1645 if (testErrors == (testErrors & kIgnorable_ErrorBitmask)) { |
1659 testsPassed++; | 1646 testsPassed++; |
1660 } else { | 1647 } else { |
1661 testsFailed++; | 1648 testsFailed++; |
1662 } | 1649 } |
1663 | 1650 |
1664 SkDELETE(gm); | 1651 SkDELETE(gm); |
1665 } | 1652 } |
1666 SkDebugf("Ran %d tests: %d passed, %d failed, %d missing reference images\n"
, | 1653 SkDebugf("Ran %d tests: %d passed, %d failed, %d missing reference images\n"
, |
1667 testsRun, testsPassed, testsFailed, testsMissingReferenceImages); | 1654 testsRun, testsPassed, testsFailed, testsMissingReferenceImages); |
1668 gmmain.ListErrors(); | 1655 gmmain.ListErrors(); |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1705 SkGraphics::Term(); | 1692 SkGraphics::Term(); |
1706 | 1693 |
1707 return (0 == testsFailed) ? 0 : -1; | 1694 return (0 == testsFailed) ? 0 : -1; |
1708 } | 1695 } |
1709 | 1696 |
1710 #if !defined(SK_BUILD_FOR_IOS) && !defined(SK_BUILD_FOR_NACL) | 1697 #if !defined(SK_BUILD_FOR_IOS) && !defined(SK_BUILD_FOR_NACL) |
1711 int main(int argc, char * const argv[]) { | 1698 int main(int argc, char * const argv[]) { |
1712 return tool_main(argc, (char**) argv); | 1699 return tool_main(argc, (char**) argv); |
1713 } | 1700 } |
1714 #endif | 1701 #endif |
OLD | NEW |