diff options
-rw-r--r-- | bench/CodecBench.cpp | 66 | ||||
-rw-r--r-- | bench/CodecBench.h | 39 | ||||
-rw-r--r-- | bench/DecodingBench.cpp | 61 | ||||
-rw-r--r-- | bench/DecodingBench.h | 19 | ||||
-rw-r--r-- | bench/nanobench.cpp | 49 | ||||
-rw-r--r-- | gyp/bench.gyp | 1 | ||||
-rw-r--r-- | gyp/iOSShell.gyp | 1 |
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', |