| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2014 Google Inc. | 2 * Copyright 2014 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 #include <ctype.h> | 8 #include <ctype.h> |
| 9 | 9 |
| 10 #include "nanobench.h" | 10 #include "nanobench.h" |
| 11 | 11 |
| 12 #include "Benchmark.h" | 12 #include "Benchmark.h" |
| 13 #include "BitmapRegionDecoderBench.h" |
| 13 #include "CodecBench.h" | 14 #include "CodecBench.h" |
| 15 #include "CodecBenchPriv.h" |
| 14 #include "CrashHandler.h" | 16 #include "CrashHandler.h" |
| 15 #include "DecodingBench.h" | 17 #include "DecodingBench.h" |
| 16 #include "GMBench.h" | 18 #include "GMBench.h" |
| 17 #include "ProcStats.h" | 19 #include "ProcStats.h" |
| 18 #include "ResultsWriter.h" | 20 #include "ResultsWriter.h" |
| 19 #include "RecordingBench.h" | 21 #include "RecordingBench.h" |
| 20 #include "SKPAnimationBench.h" | 22 #include "SKPAnimationBench.h" |
| 21 #include "SKPBench.h" | 23 #include "SKPBench.h" |
| 22 #include "SubsetBenchPriv.h" | |
| 23 #include "SubsetSingleBench.h" | 24 #include "SubsetSingleBench.h" |
| 24 #include "SubsetTranslateBench.h" | 25 #include "SubsetTranslateBench.h" |
| 25 #include "SubsetZoomBench.h" | 26 #include "SubsetZoomBench.h" |
| 26 #include "Stats.h" | 27 #include "Stats.h" |
| 27 #include "Timer.h" | 28 #include "Timer.h" |
| 28 | 29 |
| 30 #include "SkBitmapRegionDecoderInterface.h" |
| 29 #include "SkBBoxHierarchy.h" | 31 #include "SkBBoxHierarchy.h" |
| 30 #include "SkCanvas.h" | 32 #include "SkCanvas.h" |
| 31 #include "SkCodec.h" | 33 #include "SkCodec.h" |
| 32 #include "SkCommonFlags.h" | 34 #include "SkCommonFlags.h" |
| 33 #include "SkData.h" | 35 #include "SkData.h" |
| 34 #include "SkForceLinking.h" | 36 #include "SkForceLinking.h" |
| 35 #include "SkGraphics.h" | 37 #include "SkGraphics.h" |
| 36 #include "SkOSFile.h" | 38 #include "SkOSFile.h" |
| 37 #include "SkPictureRecorder.h" | 39 #include "SkPictureRecorder.h" |
| 38 #include "SkPictureUtils.h" | 40 #include "SkPictureUtils.h" |
| (...skipping 479 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 518 // unused otherwise. | 520 // unused otherwise. |
| 519 SkPMColor colors[256]; | 521 SkPMColor colors[256]; |
| 520 int colorCount; | 522 int colorCount; |
| 521 const SkImageInfo info = codec->getInfo().makeColorType(colorType); | 523 const SkImageInfo info = codec->getInfo().makeColorType(colorType); |
| 522 SkAutoTDeleteArray<uint8_t> row(new uint8_t[info.minRowBytes()]); | 524 SkAutoTDeleteArray<uint8_t> row(new uint8_t[info.minRowBytes()]); |
| 523 SkAutoTDelete<SkScanlineDecoder> scanlineDecoder(SkScanlineDecoder::NewF
romData(encoded)); | 525 SkAutoTDelete<SkScanlineDecoder> scanlineDecoder(SkScanlineDecoder::NewF
romData(encoded)); |
| 524 if (nullptr == scanlineDecoder || scanlineDecoder->start(info, nullptr, | 526 if (nullptr == scanlineDecoder || scanlineDecoder->start(info, nullptr, |
| 525 colors, &colorCount) != SkCodec::kSuccess) | 527 colors, &colorCount) != SkCodec::kSuccess) |
| 526 { | 528 { |
| 527 SkDebugf("Could not create scanline decoder for %s with color type %
s. " | 529 SkDebugf("Could not create scanline decoder for %s with color type %
s. " |
| 528 "Skipping bench.\n", path.c_str(), get_color_name(colorType)
); | 530 "Skipping bench.\n", path.c_str(), color_type_to_str(colorTy
pe)); |
| 529 return false; | 531 return false; |
| 530 } | 532 } |
| 531 *width = info.width(); | 533 *width = info.width(); |
| 532 *height = info.height(); | 534 *height = info.height(); |
| 533 } else { | 535 } else { |
| 534 SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factory(stream)); | 536 SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factory(stream)); |
| 535 if (nullptr == decoder) { | 537 if (nullptr == decoder) { |
| 536 SkDebugf("Could not create decoder for %s. Skipping bench.\n", path
.c_str()); | 538 SkDebugf("Could not create decoder for %s. Skipping bench.\n", path
.c_str()); |
| 537 return false; | 539 return false; |
| 538 } | 540 } |
| 539 //FIXME: See skbug.com/3921 | 541 //FIXME: See skbug.com/3921 |
| 540 if (kIndex_8_SkColorType == colorType || kGray_8_SkColorType == colorTyp
e) { | 542 if (kIndex_8_SkColorType == colorType || kGray_8_SkColorType == colorTyp
e) { |
| 541 SkDebugf("Cannot use image subset decoder for %s with color type %s.
" | 543 SkDebugf("Cannot use image subset decoder for %s with color type %s.
" |
| 542 "Skipping bench.\n", path.c_str(), get_color_name(colorType)
); | 544 "Skipping bench.\n", path.c_str(), color_type_to_str(colorTy
pe)); |
| 543 return false; | 545 return false; |
| 544 } | 546 } |
| 545 if (!decoder->buildTileIndex(stream.detach(), width, height)) { | 547 if (!decoder->buildTileIndex(stream.detach(), width, height)) { |
| 546 SkDebugf("Could not build tile index for %s. Skipping bench.\n", pa
th.c_str()); | 548 SkDebugf("Could not build tile index for %s. Skipping bench.\n", pa
th.c_str()); |
| 547 return false; | 549 return false; |
| 548 } | 550 } |
| 549 } | 551 } |
| 550 | 552 |
| 551 // Check if the image is large enough for a meaningful subset benchmark. | 553 // Check if the image is large enough for a meaningful subset benchmark. |
| 552 if (*width <= 512 && *height <= 512) { | 554 if (*width <= 512 && *height <= 512) { |
| 553 // This should not print a message since it is not an error. | 555 // This should not print a message since it is not an error. |
| 554 return false; | 556 return false; |
| 555 } | 557 } |
| 556 | 558 |
| 557 return true; | 559 return true; |
| 558 } | 560 } |
| 559 | 561 |
| 562 static bool valid_brd_bench(SkData* encoded, SkBitmapRegionDecoderInterface::Str
ategy strategy, |
| 563 SkColorType colorType, uint32_t sampleSize, uint32_t minOutputSize, int*
width, |
| 564 int* height) { |
| 565 SkStreamRewindable* stream = new SkMemoryStream(encoded); |
| 566 SkAutoTDelete<SkBitmapRegionDecoderInterface> brd( |
| 567 SkBitmapRegionDecoderInterface::CreateBitmapRegionDecoder(stream, st
rategy)); |
| 568 if (nullptr == brd.get()) { |
| 569 // This is indicates that subset decoding is not supported for a particu
lar image format. |
| 570 return false; |
| 571 } |
| 572 |
| 573 SkAutoTDelete<SkBitmap> bitmap(brd->decodeRegion(0, 0, brd->width(), brd->he
ight(), 1, |
| 574 colorType)); |
| 575 if (nullptr == bitmap.get() || colorType != bitmap->colorType()) { |
| 576 // This indicates that conversion to the requested color type is not sup
ported for the |
| 577 // particular image. |
| 578 return false; |
| 579 } |
| 580 |
| 581 if (sampleSize * minOutputSize > (uint32_t) brd->width() || sampleSize * min
OutputSize > |
| 582 (uint32_t) brd->height()) { |
| 583 // This indicates that the image is not large enough to decode a |
| 584 // minOutputSize x minOutputSize subset at the given sampleSize. |
| 585 return false; |
| 586 } |
| 587 |
| 588 // Set the image width and height. The calling code will use this to choose
subsets to decode. |
| 589 *width = brd->width(); |
| 590 *height = brd->height(); |
| 591 return true; |
| 592 } |
| 593 |
| 560 static void cleanup_run(Target* target) { | 594 static void cleanup_run(Target* target) { |
| 561 delete target; | 595 delete target; |
| 562 #if SK_SUPPORT_GPU | 596 #if SK_SUPPORT_GPU |
| 563 if (FLAGS_abandonGpuContext) { | 597 if (FLAGS_abandonGpuContext) { |
| 564 gGrFactory->abandonContexts(); | 598 gGrFactory->abandonContexts(); |
| 565 } | 599 } |
| 566 if (FLAGS_resetGpuContext || FLAGS_abandonGpuContext) { | 600 if (FLAGS_resetGpuContext || FLAGS_abandonGpuContext) { |
| 567 gGrFactory->destroyContexts(); | 601 gGrFactory->destroyContexts(); |
| 568 } | 602 } |
| 569 #endif | 603 #endif |
| 570 } | 604 } |
| 571 | 605 |
| 572 class BenchmarkStream { | 606 class BenchmarkStream { |
| 573 public: | 607 public: |
| 574 BenchmarkStream() : fBenches(BenchRegistry::Head()) | 608 BenchmarkStream() : fBenches(BenchRegistry::Head()) |
| 575 , fGMs(skiagm::GMRegistry::Head()) | 609 , fGMs(skiagm::GMRegistry::Head()) |
| 576 , fCurrentRecording(0) | 610 , fCurrentRecording(0) |
| 577 , fCurrentScale(0) | 611 , fCurrentScale(0) |
| 578 , fCurrentSKP(0) | 612 , fCurrentSKP(0) |
| 579 , fCurrentUseMPD(0) | 613 , fCurrentUseMPD(0) |
| 580 , fCurrentCodec(0) | 614 , fCurrentCodec(0) |
| 581 , fCurrentImage(0) | 615 , fCurrentImage(0) |
| 582 , fCurrentSubsetImage(0) | 616 , fCurrentSubsetImage(0) |
| 617 , fCurrentBRDImage(0) |
| 583 , fCurrentColorType(0) | 618 , fCurrentColorType(0) |
| 584 , fCurrentSubsetType(0) | 619 , fCurrentSubsetType(0) |
| 585 , fUseCodec(0) | 620 , fUseCodec(0) |
| 621 , fCurrentBRDStrategy(0) |
| 622 , fCurrentBRDSampleSize(0) |
| 586 , fCurrentAnimSKP(0) { | 623 , fCurrentAnimSKP(0) { |
| 587 for (int i = 0; i < FLAGS_skps.count(); i++) { | 624 for (int i = 0; i < FLAGS_skps.count(); i++) { |
| 588 if (SkStrEndsWith(FLAGS_skps[i], ".skp")) { | 625 if (SkStrEndsWith(FLAGS_skps[i], ".skp")) { |
| 589 fSKPs.push_back() = FLAGS_skps[i]; | 626 fSKPs.push_back() = FLAGS_skps[i]; |
| 590 } else { | 627 } else { |
| 591 SkOSFile::Iter it(FLAGS_skps[i], ".skp"); | 628 SkOSFile::Iter it(FLAGS_skps[i], ".skp"); |
| 592 SkString path; | 629 SkString path; |
| 593 while (it.next(&path)) { | 630 while (it.next(&path)) { |
| 594 fSKPs.push_back() = SkOSPath::Join(FLAGS_skps[0], path.c_str
()); | 631 fSKPs.push_back() = SkOSPath::Join(FLAGS_skps[0], path.c_str
()); |
| 595 } | 632 } |
| (...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 869 fCurrentSubsetType = 0; | 906 fCurrentSubsetType = 0; |
| 870 fCurrentColorType++; | 907 fCurrentColorType++; |
| 871 } | 908 } |
| 872 fCurrentColorType = 0; | 909 fCurrentColorType = 0; |
| 873 fCurrentSubsetImage++; | 910 fCurrentSubsetImage++; |
| 874 } | 911 } |
| 875 fCurrentSubsetImage = 0; | 912 fCurrentSubsetImage = 0; |
| 876 fUseCodec++; | 913 fUseCodec++; |
| 877 } | 914 } |
| 878 | 915 |
| 916 // Run the BRDBenches |
| 917 // We will benchmark multiple BRD strategies. |
| 918 const SkBitmapRegionDecoderInterface::Strategy strategies[] = { |
| 919 SkBitmapRegionDecoderInterface::kOriginal_Strategy, |
| 920 SkBitmapRegionDecoderInterface::kCanvas_Strategy, |
| 921 }; |
| 922 |
| 923 // We intend to create benchmarks that model the use cases in |
| 924 // android/libraries/social/tiledimage. In this library, an image is de
coded in 512x512 |
| 925 // tiles. The image can be translated freely, so the location of a tile
may be anywhere in |
| 926 // the image. For that reason, we will benchmark decodes in five repres
entative locations |
| 927 // in the image. Additionally, this use case utilizes power of two scal
ing, so we will |
| 928 // test on power of two sample sizes. The output tile is always 512x512
, so, when a |
| 929 // sampleSize is used, the size of the subset that is decoded is always |
| 930 // (sampleSize*512)x(sampleSize*512). |
| 931 // There are a few good reasons to only test on power of two sample size
s at this time: |
| 932 // JPEG decodes using kOriginal_Strategy are broken for non-powers o
f two. |
| 933 // skbug.com/4319 |
| 934 // All use cases we are aware of only scale by powers of two. |
| 935 // PNG decodes use the indicated sampling strategy regardless of the
sample size, so |
| 936 // these tests are sufficient to provide good coverage of our sc
aling options. |
| 937 const uint32_t sampleSizes[] = { 1, 2, 4, 8, 16 }; |
| 938 const uint32_t minOutputSize = 512; |
| 939 while (fCurrentBRDImage < fImages.count()) { |
| 940 while (fCurrentBRDStrategy < (int) SK_ARRAY_COUNT(strategies)) { |
| 941 while (fCurrentColorType < fColorTypes.count()) { |
| 942 while (fCurrentBRDSampleSize < (int) SK_ARRAY_COUNT(sampleSi
zes)) { |
| 943 while (fCurrentSubsetType <= kLastSingle_SubsetType) { |
| 944 const SkString& path = fImages[fCurrentBRDImage]; |
| 945 const SkBitmapRegionDecoderInterface::Strategy strat
egy = |
| 946 strategies[fCurrentBRDStrategy]; |
| 947 SkAutoTUnref<SkData> encoded(SkData::NewFromFileName
(path.c_str())); |
| 948 const SkColorType colorType = fColorTypes[fCurrentCo
lorType]; |
| 949 uint32_t sampleSize = sampleSizes[fCurrentBRDSampleS
ize]; |
| 950 int currentSubsetType = fCurrentSubsetType++; |
| 951 |
| 952 int width = 0; |
| 953 int height = 0; |
| 954 if (!valid_brd_bench(encoded.get(), strategy, colorT
ype, sampleSize, |
| 955 minOutputSize, &width, &height)) { |
| 956 break; |
| 957 } |
| 958 |
| 959 SkString basename = SkOSPath::Basename(path.c_str())
; |
| 960 SkIRect subset; |
| 961 const uint32_t subsetSize = sampleSize * minOutputSi
ze; |
| 962 switch (currentSubsetType) { |
| 963 case kTopLeft_SubsetType: |
| 964 basename.append("_TopLeft"); |
| 965 subset = SkIRect::MakeXYWH(0, 0, subsetSize,
subsetSize); |
| 966 break; |
| 967 case kTopRight_SubsetType: |
| 968 basename.append("_TopRight"); |
| 969 subset = SkIRect::MakeXYWH(width - subsetSiz
e, 0, subsetSize, |
| 970 subsetSize); |
| 971 break; |
| 972 case kMiddle_SubsetType: |
| 973 basename.append("_Middle"); |
| 974 subset = SkIRect::MakeXYWH((width - subsetSi
ze) / 2, |
| 975 (height - subsetSize) / 2, subsetSiz
e, subsetSize); |
| 976 break; |
| 977 case kBottomLeft_SubsetType: |
| 978 basename.append("_BottomLeft"); |
| 979 subset = SkIRect::MakeXYWH(0, height - subse
tSize, subsetSize, |
| 980 subsetSize); |
| 981 break; |
| 982 case kBottomRight_SubsetType: |
| 983 basename.append("_BottomRight"); |
| 984 subset = SkIRect::MakeXYWH(width - subsetSiz
e, |
| 985 height - subsetSize, subsetSize, sub
setSize); |
| 986 break; |
| 987 default: |
| 988 SkASSERT(false); |
| 989 } |
| 990 |
| 991 return new BitmapRegionDecoderBench(basename.c_str()
, encoded.get(), |
| 992 strategy, colorType, sampleSize, subset); |
| 993 } |
| 994 fCurrentSubsetType = 0; |
| 995 fCurrentBRDSampleSize++; |
| 996 } |
| 997 fCurrentBRDSampleSize = 0; |
| 998 fCurrentColorType++; |
| 999 } |
| 1000 fCurrentColorType = 0; |
| 1001 fCurrentBRDStrategy++; |
| 1002 } |
| 1003 fCurrentBRDStrategy = 0; |
| 1004 fCurrentBRDImage++; |
| 1005 } |
| 1006 |
| 879 return nullptr; | 1007 return nullptr; |
| 880 } | 1008 } |
| 881 | 1009 |
| 882 void fillCurrentOptions(ResultsWriter* log) const { | 1010 void fillCurrentOptions(ResultsWriter* log) const { |
| 883 log->configOption("source_type", fSourceType); | 1011 log->configOption("source_type", fSourceType); |
| 884 log->configOption("bench_type", fBenchType); | 1012 log->configOption("bench_type", fBenchType); |
| 885 if (0 == strcmp(fSourceType, "skp")) { | 1013 if (0 == strcmp(fSourceType, "skp")) { |
| 886 log->configOption("clip", | 1014 log->configOption("clip", |
| 887 SkStringPrintf("%d %d %d %d", fClip.fLeft, fClip.fTop, | 1015 SkStringPrintf("%d %d %d %d", fClip.fLeft, fClip.fTop, |
| 888 fClip.fRight, fClip.fBottom).c
_str()); | 1016 fClip.fRight, fClip.fBottom).c
_str()); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 900 | 1028 |
| 901 private: | 1029 private: |
| 902 enum SubsetType { | 1030 enum SubsetType { |
| 903 kTopLeft_SubsetType = 0, | 1031 kTopLeft_SubsetType = 0, |
| 904 kTopRight_SubsetType = 1, | 1032 kTopRight_SubsetType = 1, |
| 905 kMiddle_SubsetType = 2, | 1033 kMiddle_SubsetType = 2, |
| 906 kBottomLeft_SubsetType = 3, | 1034 kBottomLeft_SubsetType = 3, |
| 907 kBottomRight_SubsetType = 4, | 1035 kBottomRight_SubsetType = 4, |
| 908 kTranslate_SubsetType = 5, | 1036 kTranslate_SubsetType = 5, |
| 909 kZoom_SubsetType = 6, | 1037 kZoom_SubsetType = 6, |
| 910 kLast_SubsetType = kZoom_SubsetType | 1038 kLast_SubsetType = kZoom_SubsetType, |
| 1039 kLastSingle_SubsetType = kBottomRight_SubsetType, |
| 911 }; | 1040 }; |
| 912 | 1041 |
| 913 const BenchRegistry* fBenches; | 1042 const BenchRegistry* fBenches; |
| 914 const skiagm::GMRegistry* fGMs; | 1043 const skiagm::GMRegistry* fGMs; |
| 915 SkIRect fClip; | 1044 SkIRect fClip; |
| 916 SkTArray<SkScalar> fScales; | 1045 SkTArray<SkScalar> fScales; |
| 917 SkTArray<SkString> fSKPs; | 1046 SkTArray<SkString> fSKPs; |
| 918 SkTArray<bool> fUseMPDs; | 1047 SkTArray<bool> fUseMPDs; |
| 919 SkTArray<SkString> fImages; | 1048 SkTArray<SkString> fImages; |
| 920 SkTArray<SkColorType> fColorTypes; | 1049 SkTArray<SkColorType> fColorTypes; |
| 921 SkScalar fZoomMax; | 1050 SkScalar fZoomMax; |
| 922 double fZoomPeriodMs; | 1051 double fZoomPeriodMs; |
| 923 | 1052 |
| 924 double fSKPBytes, fSKPOps; | 1053 double fSKPBytes, fSKPOps; |
| 925 | 1054 |
| 926 const char* fSourceType; // What we're benching: bench, GM, SKP, ... | 1055 const char* fSourceType; // What we're benching: bench, GM, SKP, ... |
| 927 const char* fBenchType; // How we bench it: micro, recording, playback, ..
. | 1056 const char* fBenchType; // How we bench it: micro, recording, playback, ..
. |
| 928 int fCurrentRecording; | 1057 int fCurrentRecording; |
| 929 int fCurrentScale; | 1058 int fCurrentScale; |
| 930 int fCurrentSKP; | 1059 int fCurrentSKP; |
| 931 int fCurrentUseMPD; | 1060 int fCurrentUseMPD; |
| 932 int fCurrentCodec; | 1061 int fCurrentCodec; |
| 933 int fCurrentImage; | 1062 int fCurrentImage; |
| 934 int fCurrentSubsetImage; | 1063 int fCurrentSubsetImage; |
| 1064 int fCurrentBRDImage; |
| 935 int fCurrentColorType; | 1065 int fCurrentColorType; |
| 936 int fCurrentSubsetType; | 1066 int fCurrentSubsetType; |
| 937 int fUseCodec; | 1067 int fUseCodec; |
| 1068 int fCurrentBRDStrategy; |
| 1069 int fCurrentBRDSampleSize; |
| 938 int fCurrentAnimSKP; | 1070 int fCurrentAnimSKP; |
| 939 }; | 1071 }; |
| 940 | 1072 |
| 941 int nanobench_main(); | 1073 int nanobench_main(); |
| 942 int nanobench_main() { | 1074 int nanobench_main() { |
| 943 SetupCrashHandler(); | 1075 SetupCrashHandler(); |
| 944 SkAutoGraphics ag; | 1076 SkAutoGraphics ag; |
| 945 SkTaskGroup::Enabler enabled(FLAGS_threads); | 1077 SkTaskGroup::Enabler enabled(FLAGS_threads); |
| 946 | 1078 |
| 947 #if SK_SUPPORT_GPU | 1079 #if SK_SUPPORT_GPU |
| (...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1161 | 1293 |
| 1162 return 0; | 1294 return 0; |
| 1163 } | 1295 } |
| 1164 | 1296 |
| 1165 #if !defined SK_BUILD_FOR_IOS | 1297 #if !defined SK_BUILD_FOR_IOS |
| 1166 int main(int argc, char** argv) { | 1298 int main(int argc, char** argv) { |
| 1167 SkCommandLineFlags::Parse(argc, argv); | 1299 SkCommandLineFlags::Parse(argc, argv); |
| 1168 return nanobench_main(); | 1300 return nanobench_main(); |
| 1169 } | 1301 } |
| 1170 #endif | 1302 #endif |
| OLD | NEW |