aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar scroggo <scroggo@google.com>2015-04-01 12:09:17 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2015-04-01 12:09:17 -0700
commit60869a42a133942f852dd0f1696444c2a5c9ad83 (patch)
treea7320359778214a324d323138f4b3c5c49a59b2f
parent2b6acb4ed52483bc2a89dbbaa6f0db4fdb217cd3 (diff)
Add timing SkCodec to nanobench.
CodecBench: Add new class for timing using SkCodec. DecodingBench: Include creating a decoder inside the loop. This is to have a better comparison against SkCodec. SkCodec's factory function does not necessarily read the same amount as SkImageDecoder's, so in order to have a meaningful comparison, read the entire stream from the beginning. Also for comparison, create a new SkStream from the SkData each time. Add a debugging check to make sure we have an SkImageDecoder. Add include guards. nanobench.cpp: Decode using SkCodec. When decoding using SkImageDecoder, exclude benches where we decoded to a different color type than requested. SkImageDecoder may decide to decode to a different type, in which case the name is misleading. TODOs: Now that we ignore color types that do not match the desired color type, we should add Index8. This also means calling the more complex version of getPixels so CodecBench can support kIndex8. BUG=skia:3257 Review URL: https://codereview.chromium.org/1044363002
-rw-r--r--bench/CodecBench.cpp66
-rw-r--r--bench/CodecBench.h39
-rw-r--r--bench/DecodingBench.cpp61
-rw-r--r--bench/DecodingBench.h19
-rw-r--r--bench/nanobench.cpp49
-rw-r--r--gyp/bench.gyp1
-rw-r--r--gyp/iOSShell.gyp1
7 files changed, 221 insertions, 15 deletions
diff --git a/bench/CodecBench.cpp b/bench/CodecBench.cpp
new file mode 100644
index 0000000000..e68c5de6fa
--- /dev/null
+++ b/bench/CodecBench.cpp
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2015 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "CodecBench.h"
+#include "SkBitmap.h"
+#include "SkCodec.h"
+#include "SkImageGenerator.h"
+#include "SkOSFile.h"
+
+CodecBench::CodecBench(SkString baseName, SkData* encoded, SkColorType colorType)
+ : fColorType(colorType)
+ , fData(SkRef(encoded))
+{
+ // Parse filename and the color type to give the benchmark a useful name
+ const char* colorName;
+ switch(colorType) {
+ case kN32_SkColorType:
+ colorName = "N32";
+ break;
+ case kRGB_565_SkColorType:
+ colorName = "565";
+ break;
+ case kAlpha_8_SkColorType:
+ colorName = "Alpha8";
+ break;
+ default:
+ colorName = "Unknown";
+ }
+ fName.printf("Codec_%s_%s", baseName.c_str(), colorName);
+#ifdef SK_DEBUG
+ // Ensure that we can create an SkCodec from this data.
+ SkAutoTDelete<SkCodec> codec(SkCodec::NewFromData(fData));
+ SkASSERT(codec);
+#endif
+}
+
+const char* CodecBench::onGetName() {
+ return fName.c_str();
+}
+
+bool CodecBench::isSuitableFor(Backend backend) {
+ return kNonRendering_Backend == backend;
+}
+
+void CodecBench::onPreDraw() {
+ SkAutoTDelete<SkCodec> codec(SkCodec::NewFromData(fData));
+ fBitmap.allocPixels(codec->getInfo().makeColorType(fColorType));
+}
+
+void CodecBench::onDraw(const int n, SkCanvas* canvas) {
+ SkAutoTDelete<SkCodec> codec;
+ for (int i = 0; i < n; i++) {
+ codec.reset(SkCodec::NewFromData(fData));
+#ifdef SK_DEBUG
+ const SkImageGenerator::Result result =
+#endif
+ // fBitmap.info() was set to use fColorType in onPreDraw.
+ codec->getPixels(fBitmap.info(), fBitmap.getPixels(), fBitmap.rowBytes());
+ SkASSERT(result == SkImageGenerator::kSuccess
+ || result == SkImageGenerator::kIncompleteInput);
+ }
+}
diff --git a/bench/CodecBench.h b/bench/CodecBench.h
new file mode 100644
index 0000000000..2bc4ba9a6f
--- /dev/null
+++ b/bench/CodecBench.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2015 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef CodecBench_DEFINED
+#define CodecBench_DEFINED
+
+#include "Benchmark.h"
+#include "SkBitmap.h"
+#include "SkData.h"
+#include "SkImageInfo.h"
+#include "SkRefCnt.h"
+#include "SkString.h"
+
+/**
+ * Time SkCodec.
+ */
+class CodecBench : public Benchmark {
+public:
+ // Calls encoded->ref()
+ CodecBench(SkString basename, SkData* encoded, SkColorType colorType);
+
+protected:
+ const char* onGetName() override;
+ bool isSuitableFor(Backend backend) override;
+ void onDraw(const int n, SkCanvas* canvas) override;
+ void onPreDraw() override;
+
+private:
+ SkString fName;
+ const SkColorType fColorType;
+ SkAutoTUnref<SkData> fData;
+ SkBitmap fBitmap;
+ typedef Benchmark INHERITED;
+};
+#endif // CodecBench_DEFINED
diff --git a/bench/DecodingBench.cpp b/bench/DecodingBench.cpp
index c8490ca7a8..60535cea2a 100644
--- a/bench/DecodingBench.cpp
+++ b/bench/DecodingBench.cpp
@@ -8,7 +8,9 @@
#include "DecodingBench.h"
#include "SkData.h"
#include "SkImageDecoder.h"
+#include "SkMallocPixelRef.h"
#include "SkOSFile.h"
+#include "SkPixelRef.h"
#include "SkStream.h"
/*
@@ -19,6 +21,7 @@
*/
DecodingBench::DecodingBench(SkString path, SkColorType colorType)
: fColorType(colorType)
+ , fData(SkData::NewFromFileName(path.c_str()))
{
// Parse filename and the color type to give the benchmark a useful name
SkString baseName = SkOSPath::Basename(path.c_str());
@@ -38,10 +41,12 @@ DecodingBench::DecodingBench(SkString path, SkColorType colorType)
}
fName.printf("Decode_%s_%s", baseName.c_str(), colorName);
- // Perform setup for the decode
- SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(path.c_str()));
- fStream.reset(new SkMemoryStream(encoded));
- fDecoder.reset(SkImageDecoder::Factory(fStream.get()));
+#ifdef SK_DEBUG
+ // Ensure that we can create a decoder.
+ SkAutoTDelete<SkStreamRewindable> stream(new SkMemoryStream(fData));
+ SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factory(stream));
+ SkASSERT(decoder != NULL);
+#endif
}
const char* DecodingBench::onGetName() {
@@ -52,11 +57,53 @@ bool DecodingBench::isSuitableFor(Backend backend) {
return kNonRendering_Backend == backend;
}
+void DecodingBench::onPreDraw() {
+ // Allocate the pixels now, to remove it from the loop.
+ SkAutoTDelete<SkStreamRewindable> stream(new SkMemoryStream(fData));
+ SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factory(stream));
+#ifdef SK_DEBUG
+ SkImageDecoder::Result result =
+#endif
+ decoder->decode(stream, &fBitmap, fColorType,
+ SkImageDecoder::kDecodeBounds_Mode);
+ SkASSERT(SkImageDecoder::kFailure != result);
+ fBitmap.allocPixels(fBitmap.info());
+}
+
+// Allocator which just reuses the pixels from an existing SkPixelRef.
+class UseExistingAllocator : public SkBitmap::Allocator {
+public:
+ explicit UseExistingAllocator(SkPixelRef* pr)
+ : fPixelRef(SkRef(pr)) {}
+
+ bool allocPixelRef(SkBitmap* bm, SkColorTable* ct) override {
+ // We depend on the fact that fPixelRef is an SkMallocPixelRef, which
+ // is always locked, and the fact that this will only ever be used to
+ // decode to a bitmap with the same settings used to create the
+ // original pixel ref.
+ bm->setPixelRef(SkMallocPixelRef::NewDirect(bm->info(),
+ fPixelRef->pixels(), bm->rowBytes(), ct))->unref();
+ return true;
+ }
+
+private:
+ SkAutoTUnref<SkPixelRef> fPixelRef;
+};
+
void DecodingBench::onDraw(const int n, SkCanvas* canvas) {
SkBitmap bitmap;
+ // Declare the allocator before the decoder, so it will outlive the
+ // decoder, which will unref it.
+ UseExistingAllocator allocator(fBitmap.pixelRef());
+ SkAutoTDelete<SkImageDecoder> decoder;
+ SkAutoTDelete<SkStreamRewindable> stream;
for (int i = 0; i < n; i++) {
- fStream->rewind();
- fDecoder->decode(fStream, &bitmap, fColorType,
- SkImageDecoder::kDecodePixels_Mode);
+ // create a new stream and a new decoder to mimic the behavior of
+ // CodecBench.
+ stream.reset(new SkMemoryStream(fData));
+ decoder.reset(SkImageDecoder::Factory(stream));
+ decoder->setAllocator(&allocator);
+ decoder->decode(stream, &bitmap, fColorType,
+ SkImageDecoder::kDecodePixels_Mode);
}
}
diff --git a/bench/DecodingBench.h b/bench/DecodingBench.h
index 80a474df32..61b90a1235 100644
--- a/bench/DecodingBench.h
+++ b/bench/DecodingBench.h
@@ -5,10 +5,15 @@
* found in the LICENSE file.
*/
+#ifndef DecodingBench_DEFINED
+#define DecodingBench_DEFINED
+
#include "Benchmark.h"
+#include "SkBitmap.h"
+#include "SkData.h"
#include "SkImageDecoder.h"
#include "SkImageInfo.h"
-#include "SkStream.h"
+#include "SkRefCnt.h"
#include "SkString.h"
/*
@@ -25,11 +30,13 @@ protected:
const char* onGetName() override;
bool isSuitableFor(Backend backend) override;
void onDraw(const int n, SkCanvas* canvas) override;
-
+ void onPreDraw() override;
+
private:
- SkString fName;
- SkColorType fColorType;
- SkAutoTDelete<SkMemoryStream> fStream;
- SkAutoTDelete<SkImageDecoder> fDecoder;
+ SkString fName;
+ SkColorType fColorType;
+ SkAutoTUnref<SkData> fData;
+ SkBitmap fBitmap;
typedef Benchmark INHERITED;
};
+#endif // DecodingBench_DEFINED
diff --git a/bench/nanobench.cpp b/bench/nanobench.cpp
index 07600ef3a4..a627b50a3a 100644
--- a/bench/nanobench.cpp
+++ b/bench/nanobench.cpp
@@ -10,6 +10,7 @@
#include "nanobench.h"
#include "Benchmark.h"
+#include "CodecBench.h"
#include "CrashHandler.h"
#include "DecodingBench.h"
#include "DecodingSubsetBench.h"
@@ -23,6 +24,7 @@
#include "SkBBoxHierarchy.h"
#include "SkCanvas.h"
+#include "SkCodec.h"
#include "SkCommonFlags.h"
#include "SkData.h"
#include "SkForceLinking.h"
@@ -485,6 +487,7 @@ public:
, fCurrentScale(0)
, fCurrentSKP(0)
, fCurrentUseMPD(0)
+ , fCurrentCodec(0)
, fCurrentImage(0)
, fCurrentSubsetImage(0)
, fCurrentColorType(0)
@@ -632,16 +635,57 @@ public:
fCurrentScale++;
}
+ for (; fCurrentCodec < fImages.count(); fCurrentCodec++) {
+ const SkString& path = fImages[fCurrentCodec];
+ SkAutoTUnref<SkData> encoded(SkData::NewFromFileName(path.c_str()));
+ SkAutoTDelete<SkCodec> codec(SkCodec::NewFromData(encoded));
+ SkASSERT(codec);
+ if (!codec) {
+ // Nothing to time.
+ continue;
+ }
+ while (fCurrentColorType < fColorTypes.count()) {
+ SkColorType colorType = fColorTypes[fCurrentColorType];
+ fCurrentColorType++;
+ // Make sure we can decode to this color type.
+ SkBitmap bitmap;
+ SkImageInfo info = codec->getInfo().makeColorType(colorType);
+ bitmap.allocPixels(info);
+ const SkImageGenerator::Result result = codec->getPixels(
+ bitmap.info(), bitmap.getPixels(), bitmap.rowBytes());
+ switch (result) {
+ case SkImageGenerator::kSuccess:
+ case SkImageGenerator::kIncompleteInput:
+ return new CodecBench(SkOSPath::Basename(path.c_str()),
+ encoded, colorType);
+ case SkImageGenerator::kInvalidConversion:
+ // This is okay. Not all conversions are valid.
+ break;
+ case SkImageGenerator::kCouldNotRewind:
+ // FIXME: This is due to a bug in some implementations
+ // of SkCodec. All should support rewinding.
+ break;
+ default:
+ // This represents some sort of failure.
+ SkASSERT(false);
+ break;
+ }
+ }
+ fCurrentColorType = 0;
+ }
+
// Run the DecodingBenches
while (fCurrentImage < fImages.count()) {
while (fCurrentColorType < fColorTypes.count()) {
const SkString& path = fImages[fCurrentImage];
SkColorType colorType = fColorTypes[fCurrentColorType];
fCurrentColorType++;
- // Check if the image decodes before creating the benchmark
+ // Check if the image decodes to the right color type
+ // before creating the benchmark
SkBitmap bitmap;
if (SkImageDecoder::DecodeFile(path.c_str(), &bitmap,
- colorType, SkImageDecoder::kDecodePixels_Mode)) {
+ colorType, SkImageDecoder::kDecodePixels_Mode)
+ && bitmap.colorType() == colorType) {
return new DecodingBench(path, colorType);
}
}
@@ -741,6 +785,7 @@ private:
int fCurrentScale;
int fCurrentSKP;
int fCurrentUseMPD;
+ int fCurrentCodec;
int fCurrentImage;
int fCurrentSubsetImage;
int fCurrentColorType;
diff --git a/gyp/bench.gyp b/gyp/bench.gyp
index 1370b5383a..3453db679d 100644
--- a/gyp/bench.gyp
+++ b/gyp/bench.gyp
@@ -14,6 +14,7 @@
'type': 'executable',
'sources': [
'../gm/gm.cpp',
+ '../bench/CodecBench.cpp',
'../bench/DecodingBench.cpp',
'../bench/DecodingSubsetBench.cpp',
'../bench/GMBench.cpp',
diff --git a/gyp/iOSShell.gyp b/gyp/iOSShell.gyp
index d2ebc005f1..842cd2d207 100644
--- a/gyp/iOSShell.gyp
+++ b/gyp/iOSShell.gyp
@@ -22,6 +22,7 @@
'xml.gyp:xml',
],
'sources': [
+ '../bench/CodecBench.cpp',
'../bench/DecodingBench.cpp',
'../bench/DecodingSubsetBench.cpp',
'../bench/GMBench.cpp',