Index: bench/nanobench.cpp |
diff --git a/bench/nanobench.cpp b/bench/nanobench.cpp |
index e7019dcb8c97c0713ce653a7b3a35865e6696ef7..a1db0acd80b4e6616b87ae8261cb51a570618e0e 100644 |
--- a/bench/nanobench.cpp |
+++ b/bench/nanobench.cpp |
@@ -10,7 +10,9 @@ |
#include "nanobench.h" |
#include "Benchmark.h" |
+#include "BitmapRegionDecoderBench.h" |
#include "CodecBench.h" |
+#include "CodecBenchPriv.h" |
#include "CrashHandler.h" |
#include "DecodingBench.h" |
#include "GMBench.h" |
@@ -19,13 +21,13 @@ |
#include "RecordingBench.h" |
#include "SKPAnimationBench.h" |
#include "SKPBench.h" |
-#include "SubsetBenchPriv.h" |
#include "SubsetSingleBench.h" |
#include "SubsetTranslateBench.h" |
#include "SubsetZoomBench.h" |
#include "Stats.h" |
#include "Timer.h" |
+#include "SkBitmapRegionDecoderInterface.h" |
#include "SkBBoxHierarchy.h" |
#include "SkCanvas.h" |
#include "SkCodec.h" |
@@ -525,7 +527,7 @@ static bool valid_subset_bench(const SkString& path, SkColorType colorType, bool |
colors, &colorCount) != SkCodec::kSuccess) |
{ |
SkDebugf("Could not create scanline decoder for %s with color type %s. " |
- "Skipping bench.\n", path.c_str(), get_color_name(colorType)); |
+ "Skipping bench.\n", path.c_str(), color_type_to_str(colorType)); |
return false; |
} |
*width = info.width(); |
@@ -539,7 +541,7 @@ static bool valid_subset_bench(const SkString& path, SkColorType colorType, bool |
//FIXME: See skbug.com/3921 |
if (kIndex_8_SkColorType == colorType || kGray_8_SkColorType == colorType) { |
SkDebugf("Cannot use image subset decoder for %s with color type %s. " |
- "Skipping bench.\n", path.c_str(), get_color_name(colorType)); |
+ "Skipping bench.\n", path.c_str(), color_type_to_str(colorType)); |
return false; |
} |
if (!decoder->buildTileIndex(stream.detach(), width, height)) { |
@@ -557,6 +559,38 @@ static bool valid_subset_bench(const SkString& path, SkColorType colorType, bool |
return true; |
} |
+static bool valid_brd_bench(SkData* encoded, SkBitmapRegionDecoderInterface::Strategy strategy, |
+ SkColorType colorType, uint32_t sampleSize, uint32_t minOutputSize, int* width, |
+ int* height) { |
+ SkStreamRewindable* stream = new SkMemoryStream(encoded); |
+ SkAutoTDelete<SkBitmapRegionDecoderInterface> brd( |
+ SkBitmapRegionDecoderInterface::CreateBitmapRegionDecoder(stream, strategy)); |
+ if (nullptr == brd.get()) { |
+ // This is indicates that subset decoding is not supported for a particular image format. |
+ return false; |
+ } |
+ |
+ SkAutoTDelete<SkBitmap> bitmap(brd->decodeRegion(0, 0, brd->width(), brd->height(), 1, |
+ colorType)); |
+ if (nullptr == bitmap.get() || colorType != bitmap->colorType()) { |
+ // This indicates that conversion to the requested color type is not supported for the |
+ // particular image. |
+ return false; |
+ } |
+ |
+ if (sampleSize * minOutputSize > (uint32_t) brd->width() || sampleSize * minOutputSize > |
+ (uint32_t) brd->height()) { |
+ // This indicates that the image is not large enough to decode a |
+ // minOutputSize x minOutputSize subset at the given sampleSize. |
+ return false; |
+ } |
+ |
+ // Set the image width and height. The calling code will use this to choose subsets to decode. |
+ *width = brd->width(); |
+ *height = brd->height(); |
+ return true; |
+} |
+ |
static void cleanup_run(Target* target) { |
delete target; |
#if SK_SUPPORT_GPU |
@@ -580,9 +614,12 @@ public: |
, fCurrentCodec(0) |
, fCurrentImage(0) |
, fCurrentSubsetImage(0) |
+ , fCurrentBRDImage(0) |
, fCurrentColorType(0) |
, fCurrentSubsetType(0) |
, fUseCodec(0) |
+ , fCurrentBRDStrategy(0) |
+ , fCurrentBRDSampleSize(0) |
, fCurrentAnimSKP(0) { |
for (int i = 0; i < FLAGS_skps.count(); i++) { |
if (SkStrEndsWith(FLAGS_skps[i], ".skp")) { |
@@ -876,6 +913,97 @@ public: |
fUseCodec++; |
} |
+ // Run the BRDBenches |
+ // We will benchmark multiple BRD strategies. |
+ const SkBitmapRegionDecoderInterface::Strategy strategies[] = { |
+ SkBitmapRegionDecoderInterface::kOriginal_Strategy, |
+ SkBitmapRegionDecoderInterface::kCanvas_Strategy, |
+ }; |
+ |
+ // We intend to create benchmarks that model the use cases in |
+ // android/libraries/social/tiledimage. In this library, an image is decoded in 512x512 |
+ // tiles. The image can be translated freely, so the location of a tile may be anywhere in |
+ // the image. For that reason, we will benchmark decodes in five representative locations |
+ // in the image. Additionally, this use case utilizes power of two scaling, so we will |
+ // test on power of two sample sizes. The output tile is always 512x512, so, when a |
+ // sampleSize is used, the size of the subset that is decoded is always |
+ // (sampleSize*512)x(sampleSize*512). |
+ // There are a few good reasons to only test on power of two sample sizes at this time: |
+ // JPEG decodes using kOriginal_Strategy are broken for non-powers of two. |
+ // skbug.com/4319 |
+ // All use cases we are aware of only scale by powers of two. |
+ // PNG decodes use the indicated sampling strategy regardless of the sample size, so |
+ // these tests are sufficient to provide good coverage of our scaling options. |
+ const uint32_t sampleSizes[] = { 1, 2, 4, 8, 16 }; |
+ const uint32_t minOutputSize = 512; |
+ while (fCurrentBRDImage < fImages.count()) { |
+ while (fCurrentBRDStrategy < (int) SK_ARRAY_COUNT(strategies)) { |
+ while (fCurrentColorType < fColorTypes.count()) { |
+ while (fCurrentBRDSampleSize < (int) SK_ARRAY_COUNT(sampleSizes)) { |
+ while (fCurrentSubsetType <= kLastSingle_SubsetType) { |
+ const SkString& path = fImages[fCurrentBRDImage]; |
+ const SkBitmapRegionDecoderInterface::Strategy strategy = |
+ strategies[fCurrentBRDStrategy]; |
+ SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(path.c_str())); |
+ const SkColorType colorType = fColorTypes[fCurrentColorType]; |
+ uint32_t sampleSize = sampleSizes[fCurrentBRDSampleSize]; |
+ int currentSubsetType = fCurrentSubsetType++; |
+ |
+ int width = 0; |
+ int height = 0; |
+ if (!valid_brd_bench(encoded.get(), strategy, colorType, sampleSize, |
+ minOutputSize, &width, &height)) { |
+ break; |
+ } |
+ |
+ SkString basename = SkOSPath::Basename(path.c_str()); |
+ SkIRect subset; |
+ const uint32_t subsetSize = sampleSize * minOutputSize; |
+ switch (currentSubsetType) { |
+ case kTopLeft_SubsetType: |
+ basename.append("_TopLeft"); |
+ subset = SkIRect::MakeXYWH(0, 0, subsetSize, subsetSize); |
+ break; |
+ case kTopRight_SubsetType: |
+ basename.append("_TopRight"); |
+ subset = SkIRect::MakeXYWH(width - subsetSize, 0, subsetSize, |
+ subsetSize); |
+ break; |
+ case kMiddle_SubsetType: |
+ basename.append("_Middle"); |
+ subset = SkIRect::MakeXYWH((width - subsetSize) / 2, |
+ (height - subsetSize) / 2, subsetSize, subsetSize); |
+ break; |
+ case kBottomLeft_SubsetType: |
+ basename.append("_BottomLeft"); |
+ subset = SkIRect::MakeXYWH(0, height - subsetSize, subsetSize, |
+ subsetSize); |
+ break; |
+ case kBottomRight_SubsetType: |
+ basename.append("_BottomRight"); |
+ subset = SkIRect::MakeXYWH(width - subsetSize, |
+ height - subsetSize, subsetSize, subsetSize); |
+ break; |
+ default: |
+ SkASSERT(false); |
+ } |
+ |
+ return new BitmapRegionDecoderBench(basename.c_str(), encoded.get(), |
+ strategy, colorType, sampleSize, subset); |
+ } |
+ fCurrentSubsetType = 0; |
+ fCurrentBRDSampleSize++; |
+ } |
+ fCurrentBRDSampleSize = 0; |
+ fCurrentColorType++; |
+ } |
+ fCurrentColorType = 0; |
+ fCurrentBRDStrategy++; |
+ } |
+ fCurrentBRDStrategy = 0; |
+ fCurrentBRDImage++; |
+ } |
+ |
return nullptr; |
} |
@@ -907,7 +1035,8 @@ private: |
kBottomRight_SubsetType = 4, |
kTranslate_SubsetType = 5, |
kZoom_SubsetType = 6, |
- kLast_SubsetType = kZoom_SubsetType |
+ kLast_SubsetType = kZoom_SubsetType, |
+ kLastSingle_SubsetType = kBottomRight_SubsetType, |
}; |
const BenchRegistry* fBenches; |
@@ -932,9 +1061,12 @@ private: |
int fCurrentCodec; |
int fCurrentImage; |
int fCurrentSubsetImage; |
+ int fCurrentBRDImage; |
int fCurrentColorType; |
int fCurrentSubsetType; |
int fUseCodec; |
+ int fCurrentBRDStrategy; |
+ int fCurrentBRDSampleSize; |
int fCurrentAnimSKP; |
}; |