aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-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',