Chromium Code Reviews| 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" |
| (...skipping 481 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 492 | 492 |
| 493 if (!target->init(info, bench)) { | 493 if (!target->init(info, bench)) { |
| 494 delete target; | 494 delete target; |
| 495 return nullptr; | 495 return nullptr; |
| 496 } | 496 } |
| 497 return target; | 497 return target; |
| 498 } | 498 } |
| 499 | 499 |
| 500 /* | 500 /* |
| 501 * We only run our subset benches on files that are supported by BitmapRegionDec oder: | 501 * We only run our subset benches on files that are supported by BitmapRegionDec oder: |
| 502 * i.e. PNG, JPEG, and WEBP. We do *not* test WEBP when using codec, since we do not | 502 * i.e. PNG, JPEG, and WEBP. We do *not* test WEBP, since we do not have a scanl ine |
| 503 * have a scanline decoder for WEBP, which is necessary for running the subset b ench. | 503 * decoder for WEBP, which is necessary for running the subset bench. (Another b ench |
| 504 * (Another bench must be used to test WEBP, which decodes subsets natively.) | 504 * must be used to test WEBP, which decodes subsets natively.) |
| 505 */ | 505 */ |
| 506 static bool run_subset_bench(const SkString& path, bool useCodec) { | 506 static bool run_subset_bench(const SkString& path) { |
| 507 static const char* const exts[] = { | 507 static const char* const exts[] = { |
| 508 "jpg", "jpeg", | 508 "jpg", "jpeg", "png", |
| 509 "JPG", "JPEG", | 509 "JPG", "JPEG", "PNG", |
| 510 }; | 510 }; |
| 511 | 511 |
| 512 if (useCodec || FLAGS_jpgBuildTileIndex) { | 512 for (uint32_t i = 0; i < SK_ARRAY_COUNT(exts); i++) { |
| 513 for (uint32_t i = 0; i < SK_ARRAY_COUNT(exts); i++) { | 513 if (path.endsWith(exts[i])) { |
| 514 if (path.endsWith(exts[i])) { | 514 return true; |
| 515 return true; | |
| 516 } | |
| 517 } | 515 } |
| 518 } | 516 } |
| 519 | 517 |
| 520 // Test png in SkCodec, and optionally on SkImageDecoder. SkImageDecoder is | |
| 521 // disabled by default because it leaks memory. | |
| 522 // https://bug.skia.org/4360 | |
| 523 if ((useCodec || FLAGS_pngBuildTileIndex) && (path.endsWith("png") || path.e ndsWith("PNG"))) { | |
|
scroggo
2015/11/10 22:13:17
Please remove FLAGS_pngBuildTileIndex and FLAGS_jp
msarett
2015/11/10 22:37:25
Done.
| |
| 524 return true; | |
| 525 } | |
| 526 | |
| 527 if (!useCodec && (path.endsWith("webp") || path.endsWith("WEBP"))) { | |
| 528 return true; | |
| 529 } | |
| 530 | |
| 531 return false; | 518 return false; |
| 532 } | 519 } |
| 533 | 520 |
| 534 /* | 521 /* |
| 535 * Returns true if set up for a subset decode succeeds, false otherwise | 522 * Returns true if set up for a subset decode succeeds, false otherwise |
| 536 * If the set-up succeeds, the width and height parameters will be set | 523 * If the set-up succeeds, the width and height parameters will be set |
| 537 */ | 524 */ |
| 538 static bool valid_subset_bench(const SkString& path, SkColorType colorType, bool useCodec, | 525 static bool valid_subset_bench(const SkString& path, SkColorType colorType, |
| 539 int* width, int* height) { | 526 int* width, int* height) { |
| 540 SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(path.c_str())); | 527 SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(path.c_str())); |
| 541 SkAutoTDelete<SkMemoryStream> stream(new SkMemoryStream(encoded)); | 528 SkAutoTDelete<SkMemoryStream> stream(new SkMemoryStream(encoded)); |
| 542 | 529 |
| 543 // Check that we can create a codec or image decoder. | 530 // Check that we can create a codec. |
| 544 if (useCodec) { | 531 SkAutoTDelete<SkCodec> codec(SkCodec::NewFromStream(stream.detach())); |
| 545 SkAutoTDelete<SkCodec> codec(SkCodec::NewFromStream(stream.detach())); | 532 if (nullptr == codec) { |
| 546 if (nullptr == codec) { | 533 SkDebugf("Could not create codec for %s. Skipping bench.\n", path.c_str ()); |
| 547 SkDebugf("Could not create codec for %s. Skipping bench.\n", path.c _str()); | 534 return false; |
| 548 return false; | 535 } |
| 549 } | |
| 550 | 536 |
| 551 // These will be initialized by SkCodec if the color type is kIndex8 and | 537 // These will be initialized by SkCodec if the color type is kIndex8 and |
| 552 // unused otherwise. | 538 // unused otherwise. |
| 553 SkPMColor colors[256]; | 539 SkPMColor colors[256]; |
| 554 int colorCount; | 540 int colorCount; |
| 555 const SkImageInfo info = codec->getInfo().makeColorType(colorType); | 541 const SkImageInfo info = codec->getInfo().makeColorType(colorType); |
| 556 if (codec->startScanlineDecode(info, nullptr, colors, &colorCount) != Sk Codec::kSuccess) | 542 if (codec->startScanlineDecode(info, nullptr, colors, &colorCount) != SkCode c::kSuccess) |
| 557 { | 543 { |
| 558 SkDebugf("Could not create scanline decoder for %s with color type % s. " | 544 SkDebugf("Could not create scanline decoder for %s with color type %s. " |
| 559 "Skipping bench.\n", path.c_str(), color_type_to_str(colorTy pe)); | 545 "Skipping bench.\n", path.c_str(), color_type_to_str(colorType)) ; |
| 560 return false; | 546 return false; |
| 561 } | |
| 562 *width = info.width(); | |
| 563 *height = info.height(); | |
| 564 } else { | |
| 565 SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factory(stream)); | |
| 566 if (nullptr == decoder) { | |
| 567 SkDebugf("Could not create decoder for %s. Skipping bench.\n", path .c_str()); | |
| 568 return false; | |
| 569 } | |
| 570 //FIXME: See https://bug.skia.org/3921 | |
| 571 if (kIndex_8_SkColorType == colorType || kGray_8_SkColorType == colorTyp e) { | |
| 572 SkDebugf("Cannot use image subset decoder for %s with color type %s. " | |
| 573 "Skipping bench.\n", path.c_str(), color_type_to_str(colorTy pe)); | |
| 574 return false; | |
| 575 } | |
| 576 if (!decoder->buildTileIndex(stream.detach(), width, height)) { | |
| 577 SkDebugf("Could not build tile index for %s. Skipping bench.\n", pa th.c_str()); | |
| 578 return false; | |
| 579 } | |
| 580 } | 547 } |
| 548 *width = info.width(); | |
| 549 *height = info.height(); | |
| 581 | 550 |
| 582 // Check if the image is large enough for a meaningful subset benchmark. | 551 // Check if the image is large enough for a meaningful subset benchmark. |
| 583 if (*width <= 512 && *height <= 512) { | 552 if (*width <= 512 && *height <= 512) { |
| 584 // This should not print a message since it is not an error. | 553 // This should not print a message since it is not an error. |
| 585 return false; | 554 return false; |
| 586 } | 555 } |
| 587 | 556 |
| 588 return true; | 557 return true; |
| 589 } | 558 } |
| 590 | 559 |
| 591 static bool valid_brd_bench(SkData* encoded, SkBitmapRegionDecoder::Strategy str ategy, | 560 static bool valid_brd_bench(SkData* encoded, SkBitmapRegionDecoder::Strategy str ategy, |
| 592 SkColorType colorType, uint32_t sampleSize, uint32_t minOutputSize, int* width, | 561 SkColorType colorType, uint32_t sampleSize, uint32_t minOutputSize, int* width, |
| 593 int* height) { | 562 int* height) { |
| 594 SkAutoTDelete<SkBitmapRegionDecoder> brd( | 563 SkAutoTDelete<SkBitmapRegionDecoder> brd( |
| 595 SkBitmapRegionDecoder::Create(encoded, strategy)); | 564 SkBitmapRegionDecoder::Create(encoded, strategy)); |
| 596 if (nullptr == brd.get()) { | 565 if (nullptr == brd.get()) { |
| 597 // This is indicates that subset decoding is not supported for a particu lar image format. | 566 // This is indicates that subset decoding is not supported for a particu lar image format. |
| 598 return false; | 567 return false; |
| 599 } | 568 } |
| 600 | 569 |
| 601 SkBitmap bitmap; | 570 SkBitmap bitmap; |
| 602 if (!brd->decodeRegion(&bitmap, nullptr, SkIRect::MakeXYWH(0, 0, brd->width( ), brd->height()), | 571 if (!brd->decodeRegion(&bitmap, nullptr, SkIRect::MakeXYWH(0, 0, brd->width( ), brd->height()), |
| 603 1, colorType, false)) { | 572 1, colorType, false)) { |
| 604 return false; | 573 return false; |
| 605 } | 574 } |
| 606 if (colorType != bitmap.colorType()) { | |
| 607 // This indicates that conversion to the requested color type is not sup ported for the | |
| 608 // particular image. | |
| 609 return false; | |
| 610 } | |
| 611 | 575 |
| 612 if (sampleSize * minOutputSize > (uint32_t) brd->width() || sampleSize * min OutputSize > | 576 if (sampleSize * minOutputSize > (uint32_t) brd->width() || sampleSize * min OutputSize > |
| 613 (uint32_t) brd->height()) { | 577 (uint32_t) brd->height()) { |
| 614 // This indicates that the image is not large enough to decode a | 578 // This indicates that the image is not large enough to decode a |
| 615 // minOutputSize x minOutputSize subset at the given sampleSize. | 579 // minOutputSize x minOutputSize subset at the given sampleSize. |
| 616 return false; | 580 return false; |
| 617 } | 581 } |
| 618 | 582 |
| 619 // Set the image width and height. The calling code will use this to choose subsets to decode. | 583 // Set the image width and height. The calling code will use this to choose subsets to decode. |
| 620 *width = brd->width(); | 584 *width = brd->width(); |
| (...skipping 270 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 891 colorType, SkImageDecoder::kDecodePixels_Mode) | 855 colorType, SkImageDecoder::kDecodePixels_Mode) |
| 892 && bitmap.colorType() == colorType) { | 856 && bitmap.colorType() == colorType) { |
| 893 return new DecodingBench(path, colorType); | 857 return new DecodingBench(path, colorType); |
| 894 } | 858 } |
| 895 } | 859 } |
| 896 fCurrentColorType = 0; | 860 fCurrentColorType = 0; |
| 897 fCurrentImage++; | 861 fCurrentImage++; |
| 898 } | 862 } |
| 899 | 863 |
| 900 // Run the SubsetBenches | 864 // Run the SubsetBenches |
| 901 bool useCodecOpts[] = { true, false }; | 865 while (fCurrentSubsetImage < fImages.count()) { |
| 902 while (fUseCodec < 2) { | |
| 903 bool useCodec = useCodecOpts[fUseCodec]; | |
| 904 fSourceType = "image"; | 866 fSourceType = "image"; |
| 905 fBenchType = useCodec ? "skcodec" : "skimagedecoder"; | 867 fBenchType = "skcodec"; |
| 906 while (fCurrentSubsetImage < fImages.count()) { | 868 const SkString& path = fImages[fCurrentSubsetImage]; |
| 907 const SkString& path = fImages[fCurrentSubsetImage]; | 869 if (!run_subset_bench(path)) { |
| 908 if (!run_subset_bench(path, useCodec)) { | 870 fCurrentSubsetImage++; |
| 909 fCurrentSubsetImage++; | 871 continue; |
| 910 continue; | 872 } |
| 873 while (fCurrentColorType < fColorTypes.count()) { | |
| 874 SkColorType colorType = fColorTypes[fCurrentColorType]; | |
| 875 while (fCurrentSubsetType <= kLast_SubsetType) { | |
| 876 int width = 0; | |
| 877 int height = 0; | |
| 878 int currentSubsetType = fCurrentSubsetType++; | |
| 879 if (valid_subset_bench(path, colorType, &width, &height)) { | |
| 880 switch (currentSubsetType) { | |
| 881 case kTopLeft_SubsetType: | |
| 882 return new SubsetSingleBench(path, colorType, wi dth/3, | |
| 883 height/3, 0, 0); | |
| 884 case kTopRight_SubsetType: | |
| 885 return new SubsetSingleBench(path, colorType, wi dth/3, | |
| 886 height/3, 2*width/3, 0); | |
| 887 case kMiddle_SubsetType: | |
| 888 return new SubsetSingleBench(path, colorType, wi dth/3, | |
| 889 height/3, width/3, height/3); | |
| 890 case kBottomLeft_SubsetType: | |
| 891 return new SubsetSingleBench(path, colorType, wi dth/3, | |
| 892 height/3, 0, 2*height/3); | |
| 893 case kBottomRight_SubsetType: | |
| 894 return new SubsetSingleBench(path, colorType, wi dth/3, | |
| 895 height/3, 2*width/3, 2*height/3); | |
| 896 case kTranslate_SubsetType: | |
| 897 return new SubsetTranslateBench(path, colorType, 512, 512); | |
| 898 case kZoom_SubsetType: | |
| 899 return new SubsetZoomBench(path, colorType, 512, 512); | |
| 900 } | |
| 901 } else { | |
| 902 break; | |
| 903 } | |
| 911 } | 904 } |
| 912 while (fCurrentColorType < fColorTypes.count()) { | 905 fCurrentSubsetType = 0; |
| 913 SkColorType colorType = fColorTypes[fCurrentColorType]; | 906 fCurrentColorType++; |
| 914 while (fCurrentSubsetType <= kLast_SubsetType) { | |
| 915 int width = 0; | |
| 916 int height = 0; | |
| 917 int currentSubsetType = fCurrentSubsetType++; | |
| 918 if (valid_subset_bench(path, colorType, useCodec, &width , &height)) { | |
| 919 switch (currentSubsetType) { | |
| 920 case kTopLeft_SubsetType: | |
| 921 return new SubsetSingleBench(path, colorType , width/3, | |
| 922 height/3, 0, 0, useCodec); | |
| 923 case kTopRight_SubsetType: | |
| 924 return new SubsetSingleBench(path, colorType , width/3, | |
| 925 height/3, 2*width/3, 0, useCodec); | |
| 926 case kMiddle_SubsetType: | |
| 927 return new SubsetSingleBench(path, colorType , width/3, | |
| 928 height/3, width/3, height/3, useCode c); | |
| 929 case kBottomLeft_SubsetType: | |
| 930 return new SubsetSingleBench(path, colorType , width/3, | |
| 931 height/3, 0, 2*height/3, useCodec); | |
| 932 case kBottomRight_SubsetType: | |
| 933 return new SubsetSingleBench(path, colorType , width/3, | |
| 934 height/3, 2*width/3, 2*height/3, use Codec); | |
| 935 case kTranslate_SubsetType: | |
| 936 return new SubsetTranslateBench(path, colorT ype, 512, 512, | |
| 937 useCodec); | |
| 938 case kZoom_SubsetType: | |
| 939 return new SubsetZoomBench(path, colorType, 512, 512, | |
| 940 useCodec); | |
| 941 } | |
| 942 } else { | |
| 943 break; | |
| 944 } | |
| 945 } | |
| 946 fCurrentSubsetType = 0; | |
| 947 fCurrentColorType++; | |
| 948 } | |
| 949 fCurrentColorType = 0; | |
| 950 fCurrentSubsetImage++; | |
| 951 } | 907 } |
| 952 fCurrentSubsetImage = 0; | 908 fCurrentColorType = 0; |
| 953 fUseCodec++; | 909 fCurrentSubsetImage++; |
| 954 } | 910 } |
| 955 | 911 |
| 956 // Run the BRDBenches | 912 // Run the BRDBenches |
| 957 // We will benchmark multiple BRD strategies. | 913 // We will benchmark multiple BRD strategies. |
| 958 static const struct { | 914 static const struct { |
| 959 SkBitmapRegionDecoder::Strategy fStrategy; | 915 SkBitmapRegionDecoder::Strategy fStrategy; |
| 960 const char* fName; | 916 const char* fName; |
| 961 } strategies[] = { | 917 } strategies[] = { |
| 962 { SkBitmapRegionDecoder::kOriginal_Strategy, "BRD" }, | 918 { SkBitmapRegionDecoder::kCanvas_Strategy, "BRD_canvas" }, |
| 963 { SkBitmapRegionDecoder::kCanvas_Strategy, "BRD_canvas" }, | |
| 964 { SkBitmapRegionDecoder::kAndroidCodec_Strategy, "BRD_android_codec" }, | 919 { SkBitmapRegionDecoder::kAndroidCodec_Strategy, "BRD_android_codec" }, |
| 965 }; | 920 }; |
| 966 | 921 |
| 967 // We intend to create benchmarks that model the use cases in | 922 // We intend to create benchmarks that model the use cases in |
| 968 // android/libraries/social/tiledimage. In this library, an image is de coded in 512x512 | 923 // android/libraries/social/tiledimage. In this library, an image is de coded in 512x512 |
| 969 // tiles. The image can be translated freely, so the location of a tile may be anywhere in | 924 // tiles. The image can be translated freely, so the location of a tile may be anywhere in |
| 970 // the image. For that reason, we will benchmark decodes in five repres entative locations | 925 // the image. For that reason, we will benchmark decodes in five repres entative locations |
| 971 // in the image. Additionally, this use case utilizes power of two scal ing, so we will | 926 // in the image. Additionally, this use case utilizes power of two scal ing, so we will |
| 972 // test on power of two sample sizes. The output tile is always 512x512 , so, when a | 927 // test on power of two sample sizes. The output tile is always 512x512 , so, when a |
| 973 // sampleSize is used, the size of the subset that is decoded is always | 928 // sampleSize is used, the size of the subset that is decoded is always |
| 974 // (sampleSize*512)x(sampleSize*512). | 929 // (sampleSize*512)x(sampleSize*512). |
| 975 // There are a few good reasons to only test on power of two sample size s at this time: | 930 // There are a few good reasons to only test on power of two sample size s at this time: |
| 976 // JPEG decodes using kOriginal_Strategy are broken for non-powers o f two. | 931 // JPEG decodes using kOriginal_Strategy are broken for non-powers o f two. |
| 977 // https://bug.skia.org/4319 | 932 // https://bug.skia.org/4319 |
| 978 // All use cases we are aware of only scale by powers of two. | 933 // All use cases we are aware of only scale by powers of two. |
| 979 // PNG decodes use the indicated sampling strategy regardless of the sample size, so | 934 // PNG decodes use the indicated sampling strategy regardless of the sample size, so |
| 980 // these tests are sufficient to provide good coverage of our sc aling options. | 935 // these tests are sufficient to provide good coverage of our sc aling options. |
| 981 const uint32_t sampleSizes[] = { 1, 2, 4, 8, 16, 32, 64 }; | 936 const uint32_t sampleSizes[] = { 1, 2, 4, 8, 16, 32, 64 }; |
| 982 const uint32_t minOutputSize = 512; | 937 const uint32_t minOutputSize = 512; |
| 983 while (fCurrentBRDImage < fImages.count()) { | 938 while (fCurrentBRDImage < fImages.count()) { |
| 984 while (fCurrentBRDStrategy < (int) SK_ARRAY_COUNT(strategies)) { | 939 while (fCurrentBRDStrategy < (int) SK_ARRAY_COUNT(strategies)) { |
| 985 fSourceType = "image"; | 940 fSourceType = "image"; |
| 986 fBenchType = strategies[fCurrentBRDStrategy].fName; | 941 fBenchType = strategies[fCurrentBRDStrategy].fName; |
| 987 | 942 |
| 988 const SkString& path = fImages[fCurrentBRDImage]; | 943 const SkString& path = fImages[fCurrentBRDImage]; |
| 989 const SkBitmapRegionDecoder::Strategy strategy = | 944 const SkBitmapRegionDecoder::Strategy strategy = |
| 990 strategies[fCurrentBRDStrategy].fStrategy; | 945 strategies[fCurrentBRDStrategy].fStrategy; |
| 991 | 946 |
| 992 if (SkBitmapRegionDecoder::kOriginal_Strategy == strategy) { | |
| 993 // Disable png and jpeg for SkImageDecoder: | |
| 994 if (!FLAGS_jpgBuildTileIndex) { | |
| 995 if (path.endsWith("JPEG") || path.endsWith("JPG") || | |
| 996 path.endsWith("jpeg") || path.endsWith("jpg")) | |
| 997 { | |
| 998 fCurrentBRDStrategy++; | |
| 999 continue; | |
| 1000 } | |
| 1001 } | |
| 1002 if (!FLAGS_pngBuildTileIndex) { | |
| 1003 if (path.endsWith("PNG") || path.endsWith("png")) { | |
| 1004 fCurrentBRDStrategy++; | |
| 1005 continue; | |
| 1006 } | |
| 1007 } | |
| 1008 } | |
| 1009 | |
| 1010 while (fCurrentColorType < fColorTypes.count()) { | 947 while (fCurrentColorType < fColorTypes.count()) { |
| 1011 while (fCurrentBRDSampleSize < (int) SK_ARRAY_COUNT(sampleSi zes)) { | 948 while (fCurrentBRDSampleSize < (int) SK_ARRAY_COUNT(sampleSi zes)) { |
| 1012 while (fCurrentSubsetType <= kLastSingle_SubsetType) { | 949 while (fCurrentSubsetType <= kLastSingle_SubsetType) { |
| 1013 | 950 |
| 1014 | 951 |
| 1015 SkAutoTUnref<SkData> encoded(SkData::NewFromFileName (path.c_str())); | 952 SkAutoTUnref<SkData> encoded(SkData::NewFromFileName (path.c_str())); |
| 1016 const SkColorType colorType = fColorTypes[fCurrentCo lorType]; | 953 const SkColorType colorType = fColorTypes[fCurrentCo lorType]; |
| 1017 uint32_t sampleSize = sampleSizes[fCurrentBRDSampleS ize]; | 954 uint32_t sampleSize = sampleSizes[fCurrentBRDSampleS ize]; |
| 1018 int currentSubsetType = fCurrentSubsetType++; | 955 int currentSubsetType = fCurrentSubsetType++; |
| 1019 | 956 |
| (...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1337 | 1274 |
| 1338 return 0; | 1275 return 0; |
| 1339 } | 1276 } |
| 1340 | 1277 |
| 1341 #if !defined SK_BUILD_FOR_IOS | 1278 #if !defined SK_BUILD_FOR_IOS |
| 1342 int main(int argc, char** argv) { | 1279 int main(int argc, char** argv) { |
| 1343 SkCommandLineFlags::Parse(argc, argv); | 1280 SkCommandLineFlags::Parse(argc, argv); |
| 1344 return nanobench_main(); | 1281 return nanobench_main(); |
| 1345 } | 1282 } |
| 1346 #endif | 1283 #endif |
| OLD | NEW |