aboutsummaryrefslogtreecommitdiffhomepage
path: root/bench
diff options
context:
space:
mode:
authorGravatar scroggo <scroggo@google.com>2015-10-08 12:01:39 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2015-10-08 12:01:39 -0700
commitab12c2715886e7f04c415028a7db49fb0b1e67f3 (patch)
tree11fadb9c46bf034ae7824da722aaba77983036b7 /bench
parent33366974d43eae80e22284a2e445225c343859da (diff)
Update Subset benches to support interlacing and fix bugs
Instead of decoding one line at a time, if the ScanlineOrder is kNone, decode all of the lines in one pass, and then copy the subset into the output. This will allow us to more realistically test subset decodes for interlaced png. It also makes running them not take forever. Do *not* support other modes (besides kTopDown), since they are not used by the big three we need to replace BitmapRegionDecoder implementation (skbug.com/4428). Fix a bug in SubsetTranslateBench and SubsetZoomBench: When we decode another subset, we need to reset the scanline decode first. This bug appears to have been present since the introduction of these tests in crrev.com/1160953002 BUG=skia:4205 BUG=skia:3418 Review URL: https://codereview.chromium.org/1387233002
Diffstat (limited to 'bench')
-rw-r--r--bench/nanobench.cpp27
-rw-r--r--bench/subset/SubsetSingleBench.cpp53
-rw-r--r--bench/subset/SubsetTranslateBench.cpp69
-rw-r--r--bench/subset/SubsetZoomBench.cpp56
4 files changed, 175 insertions, 30 deletions
diff --git a/bench/nanobench.cpp b/bench/nanobench.cpp
index 4ab6ca0b88..b16fb13b57 100644
--- a/bench/nanobench.cpp
+++ b/bench/nanobench.cpp
@@ -501,6 +501,27 @@ static Target* is_enabled(Benchmark* bench, const Config& config) {
}
/*
+ * We only run our subset benches on files that are supported by BitmapRegionDecoder:
+ * i.e. PNG, JPEG, and WEBP. We do *not* test WEBP when using codec, since we do not
+ * have a scanline decoder for WEBP, which is necessary for running the subset bench.
+ * (Another bench must be used to test WEBP, which decodes subsets natively.)
+ */
+static bool run_subset_bench(const SkString& path, bool useCodec) {
+ static const char* const exts[] = {
+ "jpg", "jpeg", "png",
+ "JPG", "JPEG", "PNG",
+ };
+
+ for (uint32_t i = 0; i < SK_ARRAY_COUNT(exts); i++) {
+ if (path.endsWith(exts[i])) {
+ return true;
+ }
+ }
+
+ return !useCodec && (path.endsWith("webp") || path.endsWith("WEBP"));
+}
+
+/*
* Returns true if set up for a subset decode succeeds, false otherwise
* If the set-up succeeds, the width and height parameters will be set
*/
@@ -872,8 +893,12 @@ public:
fSourceType = "image";
fBenchType = useCodec ? "skcodec" : "skimagedecoder";
while (fCurrentSubsetImage < fImages.count()) {
+ const SkString& path = fImages[fCurrentSubsetImage];
+ if (!run_subset_bench(path, useCodec)) {
+ fCurrentSubsetImage++;
+ continue;
+ }
while (fCurrentColorType < fColorTypes.count()) {
- const SkString& path = fImages[fCurrentSubsetImage];
SkColorType colorType = fColorTypes[fCurrentColorType];
while (fCurrentSubsetType <= kLast_SubsetType) {
int width = 0;
diff --git a/bench/subset/SubsetSingleBench.cpp b/bench/subset/SubsetSingleBench.cpp
index 232c159a0b..735effa100 100644
--- a/bench/subset/SubsetSingleBench.cpp
+++ b/bench/subset/SubsetSingleBench.cpp
@@ -66,30 +66,65 @@ void SubsetSingleBench::onDraw(int n, SkCanvas* canvas) {
for (int count = 0; count < n; count++) {
SkAutoTDelete<SkCodec> codec(SkCodec::NewFromStream(fStream->duplicate()));
const SkImageInfo info = codec->getInfo().makeColorType(fColorType);
- SkAutoTDeleteArray<uint8_t> row(new uint8_t[info.minRowBytes()]);
+
+ SkDEBUGCODE(SkCodec::Result result =)
codec->startScanlineDecode(info, nullptr, colors, &colorCount);
+ SkASSERT(result == SkCodec::kSuccess);
SkBitmap bitmap;
SkImageInfo subsetInfo = info.makeWH(fSubsetWidth, fSubsetHeight);
alloc_pixels(&bitmap, subsetInfo, colors, colorCount);
- codec->skipScanlines(fOffsetTop);
- uint32_t bpp = info.bytesPerPixel();
- for (uint32_t y = 0; y < fSubsetHeight; y++) {
- codec->getScanlines(row.get(), 1, 0);
- memcpy(bitmap.getAddr(0, y), row.get() + fOffsetLeft * bpp,
- fSubsetWidth * bpp);
+ SkDEBUGCODE(result = ) codec->skipScanlines(fOffsetTop);
+ SkASSERT(result == SkCodec::kSuccess);
+
+ const uint32_t bpp = info.bytesPerPixel();
+
+ switch (codec->getScanlineOrder()) {
+ case SkCodec::kTopDown_SkScanlineOrder: {
+ SkAutoTDeleteArray<uint8_t> row(new uint8_t[info.minRowBytes()]);
+ for (uint32_t y = 0; y < fSubsetHeight; y++) {
+ SkDEBUGCODE(result = ) codec->getScanlines(row.get(), 1, 0);
+ SkASSERT(result == SkCodec::kSuccess);
+
+ memcpy(bitmap.getAddr(0, y), row.get() + fOffsetLeft * bpp,
+ fSubsetWidth * bpp);
+ }
+ break;
+ }
+ case SkCodec::kNone_SkScanlineOrder: {
+ // decode all scanlines that intersect the subset, and copy the subset
+ // into the output.
+ SkImageInfo stripeInfo = info.makeWH(info.width(), fSubsetHeight);
+ SkBitmap stripeBm;
+ alloc_pixels(&stripeBm, stripeInfo, colors, colorCount);
+
+ SkDEBUGCODE(result = ) codec->getScanlines(stripeBm.getPixels(), fSubsetHeight,
+ stripeBm.rowBytes());
+ SkASSERT(result == SkCodec::kSuccess);
+
+ for (uint32_t y = 0; y < fSubsetHeight; y++) {
+ memcpy(bitmap.getAddr(0, y), stripeBm.getAddr(fOffsetLeft, y),
+ fSubsetWidth * bpp);
+ }
+ break;
+ }
+ default:
+ // We currently are only testing kTopDown and kNone, which are the only
+ // two used by the subsets we care about. skbug.com/4428
+ SkASSERT(false);
+
}
}
} else {
for (int count = 0; count < n; count++) {
SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factory(fStream));
int width, height;
- decoder->buildTileIndex(fStream->duplicate(), &width, &height);
+ SkAssertResult(decoder->buildTileIndex(fStream->duplicate(), &width, &height));
SkBitmap bitmap;
SkIRect rect = SkIRect::MakeXYWH(fOffsetLeft, fOffsetTop, fSubsetWidth,
fSubsetHeight);
- decoder->decodeSubset(&bitmap, rect, fColorType);
+ SkAssertResult(decoder->decodeSubset(&bitmap, rect, fColorType));
}
}
}
diff --git a/bench/subset/SubsetTranslateBench.cpp b/bench/subset/SubsetTranslateBench.cpp
index 8f29ba8fa0..d13f31a86d 100644
--- a/bench/subset/SubsetTranslateBench.cpp
+++ b/bench/subset/SubsetTranslateBench.cpp
@@ -53,17 +53,29 @@ bool SubsetTranslateBench::isSuitableFor(Backend backend) {
return kNonRendering_Backend == backend;
}
+// Allows allocating the bitmap first, and then writing to them later (in startScanlineDecode)
+static SkPMColor* get_colors(SkBitmap* bm) {
+ SkColorTable* ct = bm->getColorTable();
+ if (!ct) {
+ return nullptr;
+ }
+
+ return const_cast<SkPMColor*>(ct->readColors());
+}
+
void SubsetTranslateBench::onDraw(int n, SkCanvas* canvas) {
// When the color type is kIndex8, we will need to store the color table. If it is
// used, it will be initialized by the codec.
- int colorCount;
+ int colorCount = 256;
SkPMColor colors[256];
if (fUseCodec) {
for (int count = 0; count < n; count++) {
SkAutoTDelete<SkCodec> codec(SkCodec::NewFromStream(fStream->duplicate()));
const SkImageInfo info = codec->getInfo().makeColorType(fColorType);
- SkAutoTDeleteArray<uint8_t> row(new uint8_t[info.minRowBytes()]);
- codec->startScanlineDecode(info, nullptr, colors, &colorCount);
+ SkAutoTDeleteArray<uint8_t> row(nullptr);
+ if (codec->getScanlineOrder() == SkCodec::kTopDown_SkScanlineOrder) {
+ row.reset(new uint8_t[info.minRowBytes()]);
+ }
SkBitmap bitmap;
// Note that we use the same bitmap for all of the subsets.
@@ -71,20 +83,55 @@ void SubsetTranslateBench::onDraw(int n, SkCanvas* canvas) {
SkImageInfo subsetInfo = info.makeWH(fSubsetWidth, fSubsetHeight);
alloc_pixels(&bitmap, subsetInfo, colors, colorCount);
+ const uint32_t bpp = info.bytesPerPixel();
+
for (int x = 0; x < info.width(); x += fSubsetWidth) {
for (int y = 0; y < info.height(); y += fSubsetHeight) {
- codec->skipScanlines(y);
+ SkDEBUGCODE(SkCodec::Result result =)
+ codec->startScanlineDecode(info, nullptr, get_colors(&bitmap), &colorCount);
+ SkASSERT(SkCodec::kSuccess == result);
+
+ SkDEBUGCODE(result =) codec->skipScanlines(y);
+ SkASSERT(SkCodec::kSuccess == result);
+
const uint32_t currSubsetWidth =
x + (int) fSubsetWidth > info.width() ?
info.width() - x : fSubsetWidth;
const uint32_t currSubsetHeight =
y + (int) fSubsetHeight > info.height() ?
info.height() - y : fSubsetHeight;
- const uint32_t bpp = info.bytesPerPixel();
- for (uint32_t y = 0; y < currSubsetHeight; y++) {
- codec->getScanlines(row.get(), 1, 0);
- memcpy(bitmap.getAddr(0, y), row.get() + x * bpp,
- currSubsetWidth * bpp);
+
+ switch (codec->getScanlineOrder()) {
+ case SkCodec::kTopDown_SkScanlineOrder:
+ for (uint32_t y = 0; y < currSubsetHeight; y++) {
+ SkDEBUGCODE(result =) codec->getScanlines(row.get(), 1, 0);
+ SkASSERT(SkCodec::kSuccess == result);
+
+ memcpy(bitmap.getAddr(0, y), row.get() + x * bpp,
+ currSubsetWidth * bpp);
+ }
+ break;
+ case SkCodec::kNone_SkScanlineOrder: {
+ // decode all scanlines that intersect the subset, and copy the subset
+ // into the output.
+ SkImageInfo stripeInfo = info.makeWH(info.width(), currSubsetHeight);
+ SkBitmap stripeBm;
+ alloc_pixels(&stripeBm, stripeInfo, colors, colorCount);
+
+ SkDEBUGCODE(result =) codec->getScanlines(stripeBm.getPixels(),
+ currSubsetHeight, stripeBm.rowBytes());
+ SkASSERT(SkCodec::kSuccess == result);
+
+ for (uint32_t subsetY = 0; subsetY < currSubsetHeight; subsetY++) {
+ memcpy(bitmap.getAddr(0, subsetY), stripeBm.getAddr(x, subsetY),
+ currSubsetWidth * bpp);
+ }
+ break;
+ }
+ default:
+ // We currently are only testing kTopDown and kNone, which are the only
+ // two used by the subsets we care about. skbug.com/4428
+ SkASSERT(false);
}
}
}
@@ -97,7 +144,7 @@ void SubsetTranslateBench::onDraw(int n, SkCanvas* canvas) {
for (int count = 0; count < n; count++) {
int width, height;
SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factory(fStream));
- decoder->buildTileIndex(fStream->duplicate(), &width, &height);
+ SkAssertResult(decoder->buildTileIndex(fStream->duplicate(), &width, &height));
SkBitmap bitmap;
// Note that we use the same bitmap for all of the subsets.
// It might be larger than necessary for the end subsets.
@@ -117,7 +164,7 @@ void SubsetTranslateBench::onDraw(int n, SkCanvas* canvas) {
height - y : fSubsetHeight;
SkIRect rect = SkIRect::MakeXYWH(x, y, currSubsetWidth,
currSubsetHeight);
- decoder->decodeSubset(&bitmap, rect, fColorType);
+ SkAssertResult(decoder->decodeSubset(&bitmap, rect, fColorType));
}
}
}
diff --git a/bench/subset/SubsetZoomBench.cpp b/bench/subset/SubsetZoomBench.cpp
index ffd86703ec..901fbb6082 100644
--- a/bench/subset/SubsetZoomBench.cpp
+++ b/bench/subset/SubsetZoomBench.cpp
@@ -62,14 +62,20 @@ void SubsetZoomBench::onDraw(int n, SkCanvas* canvas) {
for (int count = 0; count < n; count++) {
SkAutoTDelete<SkCodec> codec(SkCodec::NewFromStream(fStream->duplicate()));
const SkImageInfo info = codec->getInfo().makeColorType(fColorType);
- SkAutoTDeleteArray<uint8_t> row(new uint8_t[info.minRowBytes()]);
- codec->startScanlineDecode(info, nullptr, colors, &colorCount);
+ SkAutoTDeleteArray<uint8_t> row(nullptr);
+ if (codec->getScanlineOrder() == SkCodec::kTopDown_SkScanlineOrder) {
+ row.reset(new uint8_t[info.minRowBytes()]);
+ }
const int centerX = info.width() / 2;
const int centerY = info.height() / 2;
int w = fSubsetWidth;
int h = fSubsetHeight;
do {
+ SkDEBUGCODE(SkCodec::Result result = )
+ codec->startScanlineDecode(info, nullptr, colors, &colorCount);
+ SkASSERT(SkCodec::kSuccess == result);
+
const int subsetStartX = SkTMax(0, centerX - w / 2);
const int subsetStartY = SkTMax(0, centerY - h / 2);
const int subsetWidth = SkTMin(w, info.width() - subsetStartX);
@@ -81,12 +87,44 @@ void SubsetZoomBench::onDraw(int n, SkCanvas* canvas) {
alloc_pixels(&bitmap, subsetInfo, colors, colorCount);
uint32_t bpp = info.bytesPerPixel();
- codec->skipScanlines(subsetStartY);
- for (int y = 0; y < subsetHeight; y++) {
- codec->getScanlines(row.get(), 1, 0);
- memcpy(bitmap.getAddr(0, y), row.get() + subsetStartX * bpp,
- subsetWidth * bpp);
+
+ SkDEBUGCODE(result = ) codec->skipScanlines(subsetStartY);
+ SkASSERT(SkCodec::kSuccess == result);
+
+ switch (codec->getScanlineOrder()) {
+ case SkCodec::kTopDown_SkScanlineOrder:
+ for (int y = 0; y < subsetHeight; y++) {
+ SkDEBUGCODE(result = ) codec->getScanlines(row.get(), 1, 0);
+ SkASSERT(SkCodec::kSuccess == result);
+
+ memcpy(bitmap.getAddr(0, y), row.get() + subsetStartX * bpp,
+ subsetWidth * bpp);
+ }
+ break;
+ case SkCodec::kNone_SkScanlineOrder: {
+ // decode all scanlines that intersect the subset, and copy the subset
+ // into the output.
+ SkImageInfo stripeInfo = info.makeWH(info.width(), subsetHeight);
+ SkBitmap stripeBm;
+ alloc_pixels(&stripeBm, stripeInfo, colors, colorCount);
+
+ SkDEBUGCODE(result = ) codec->getScanlines(stripeBm.getPixels(),
+ subsetHeight, stripeBm.rowBytes());
+ SkASSERT(SkCodec::kSuccess == result);
+
+ for (int y = 0; y < subsetHeight; y++) {
+ memcpy(bitmap.getAddr(0, y),
+ stripeBm.getAddr(subsetStartX, y),
+ subsetWidth * bpp);
+ }
+ break;
+ }
+ default:
+ // We currently are only testing kTopDown and kNone, which are the only
+ // two used by the subsets we care about. skbug.com/4428
+ SkASSERT(false);
}
+
w <<= 1;
h <<= 1;
} while (w < 2 * info.width() || h < 2 * info.height());
@@ -95,7 +133,7 @@ void SubsetZoomBench::onDraw(int n, SkCanvas* canvas) {
for (int count = 0; count < n; count++) {
int width, height;
SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factory(fStream));
- decoder->buildTileIndex(fStream->duplicate(), &width, &height);
+ SkAssertResult(decoder->buildTileIndex(fStream->duplicate(), &width, &height));
const int centerX = width / 2;
const int centerY = height / 2;
@@ -109,7 +147,7 @@ void SubsetZoomBench::onDraw(int n, SkCanvas* canvas) {
SkBitmap bitmap;
SkIRect rect = SkIRect::MakeXYWH(subsetStartX, subsetStartY, subsetWidth,
subsetHeight);
- decoder->decodeSubset(&bitmap, rect, fColorType);
+ SkAssertResult(decoder->decodeSubset(&bitmap, rect, fColorType));
w <<= 1;
h <<= 1;
} while (w < 2 * width || h < 2 * height);