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 |