1/* 2 * Copyright 2013 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8#include "Benchmark.h" 9#include "Resources.h" 10#include "SkBitmap.h" 11#include "SkData.h" 12#include "SkForceLinking.h" 13#include "SkImageDecoder.h" 14#include "SkOSFile.h" 15#include "SkStream.h" 16#include "SkString.h" 17 18__SK_FORCE_IMAGE_DECODER_LINKING; 19 20class SkCanvas; 21 22class SkipZeroesBench : public Benchmark { 23public: 24 SkipZeroesBench(const char* filename, bool skipZeroes) 25 : fName("SkipZeroes_") 26 , fDecoder(nullptr) 27 , fFilename(filename) 28 , fStream() 29 , fSkipZeroes(skipZeroes) 30 , fValid(false) { 31 fName.append(filename); 32 if (skipZeroes) { 33 fName.append("_skip_zeroes"); 34 } else { 35 fName.append("_write_zeroes"); 36 } 37 } 38 39 bool isSuitableFor(Backend backend) override { 40 return backend == kNonRendering_Backend; 41 } 42 43protected: 44 const char* onGetName() override { 45 return fName.c_str(); 46 } 47 48 void onDelayedSetup() override { 49 SkString resourcePath = GetResourcePath(); 50 if (resourcePath.isEmpty()) { 51 fValid = false; 52 return; 53 } 54 55 SkString fullPath = SkOSPath::Join(resourcePath.c_str(), fFilename.c_str()); 56 SkFILEStream fileStream(fullPath.c_str()); 57 fValid = fileStream.isValid() && fileStream.getLength() > 0; 58 if (fValid) { 59 const size_t size = fileStream.getLength(); 60 void* data = sk_malloc_throw(size); 61 if (fileStream.read(data, size) < size) { 62 fValid = false; 63 } else { 64 SkAutoTUnref<SkData> skdata(SkData::NewFromMalloc(data, size)); 65 fStream.setData(skdata.get()); 66 fDecoder.reset(SkImageDecoder::Factory(&fStream)); 67 if (fDecoder.get()) { 68 fDecoder->setSkipWritingZeroes(fSkipZeroes); 69 } else { 70 fValid = false; 71 } 72 } 73 } 74 } 75 76 void onDraw(int loops, SkCanvas*) override { 77 if (!fValid) { 78#ifdef SK_DEBUG 79 SkDebugf("stream was invalid: %s\n", fFilename.c_str()); 80#endif 81 return; 82 } 83 // Decode a bunch of times 84 SkBitmap bm; 85 for (int i = 0; i < loops; ++i) { 86 SkDEBUGCODE(SkImageDecoder::Result result =) fDecoder->decode(&fStream, &bm, 87 SkImageDecoder::kDecodePixels_Mode); 88#ifdef SK_DEBUG 89 if (SkImageDecoder::kFailure == result) { 90 SkDebugf("failed to decode %s\n", fFilename.c_str()); 91 return; 92 } 93#endif 94 SkDEBUGCODE(bool success =) fStream.rewind(); 95#ifdef SK_DEBUG 96 if (!success) { 97 SkDebugf("failed to rewind %s\n", fFilename.c_str()); 98 return; 99 } 100#endif 101 } 102 } 103 104private: 105 SkString fName; 106 SkAutoTDelete<SkImageDecoder> fDecoder; 107 const SkString fFilename; 108 SkMemoryStream fStream; 109 bool fSkipZeroes; 110 bool fValid; 111 112 typedef Benchmark INHERITED; 113}; 114 115// Enable the true version once the feature is checked in. 116DEF_BENCH(return new SkipZeroesBench("arrow.png", true)); 117DEF_BENCH(return new SkipZeroesBench("arrow.png", false)); 118