Home | History | Annotate | Download | only in bench
      1 /*
      2  * Copyright 2015 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 "DecodingBench.h"
      9 #include "SkBitmap.h"
     10 #include "SkData.h"
     11 #include "SkImageDecoder.h"
     12 #include "SkMallocPixelRef.h"
     13 #include "SkOSFile.h"
     14 #include "SkStream.h"
     15 
     16 /*
     17  *
     18  * This benchmark is designed to test the performance of image decoding.
     19  * It is invoked from the nanobench.cpp file.
     20  *
     21  */
     22 DecodingBench::DecodingBench(SkString path, SkColorType colorType)
     23     : fColorType(colorType)
     24     , fData(SkData::NewFromFileName(path.c_str()))
     25 {
     26     // Parse filename and the color type to give the benchmark a useful name
     27     SkString baseName = SkOSPath::Basename(path.c_str());
     28     const char* colorName;
     29     switch(colorType) {
     30         case kN32_SkColorType:
     31             colorName = "N32";
     32             break;
     33         case kRGB_565_SkColorType:
     34             colorName = "565";
     35             break;
     36         case kAlpha_8_SkColorType:
     37             colorName = "Alpha8";
     38             break;
     39         default:
     40             colorName = "Unknown";
     41     }
     42     fName.printf("Decode_%s_%s", baseName.c_str(), colorName);
     43 
     44 #ifdef SK_DEBUG
     45     // Ensure that we can create a decoder.
     46     SkAutoTDelete<SkStreamRewindable> stream(new SkMemoryStream(fData));
     47     SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factory(stream));
     48     SkASSERT(decoder != NULL);
     49 #endif
     50 }
     51 
     52 const char* DecodingBench::onGetName() {
     53     return fName.c_str();
     54 }
     55 
     56 bool DecodingBench::isSuitableFor(Backend backend) {
     57     return kNonRendering_Backend == backend;
     58 }
     59 
     60 void DecodingBench::onPreDraw() {
     61     // Allocate the pixels now, to remove it from the loop.
     62     SkAutoTDelete<SkStreamRewindable> stream(new SkMemoryStream(fData));
     63     SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factory(stream));
     64     SkBitmap bm;
     65 #ifdef SK_DEBUG
     66     SkImageDecoder::Result result =
     67 #endif
     68     decoder->decode(stream, &bm, fColorType, SkImageDecoder::kDecodeBounds_Mode);
     69     SkASSERT(SkImageDecoder::kFailure != result);
     70 
     71     const size_t rowBytes = bm.info().minRowBytes();
     72     fPixelStorage.reset(bm.info().getSafeSize(rowBytes));
     73 }
     74 
     75 // Allocator which just uses an existing block of memory.
     76 class TargetAllocator : public SkBitmap::Allocator {
     77 public:
     78     explicit TargetAllocator(void* storage)
     79         : fPixelStorage(storage) {}
     80 
     81     bool allocPixelRef(SkBitmap* bm, SkColorTable* ct) override {
     82         // We depend on the fact that this will only ever be used to
     83         // decode to a bitmap with the same settings used to create
     84         // fPixelStorage.
     85         bm->setPixelRef(SkMallocPixelRef::NewDirect(bm->info(),
     86                 fPixelStorage, bm->rowBytes(), ct))->unref();
     87         return true;
     88     }
     89 
     90 private:
     91     void* fPixelStorage; // Unowned. DecodingBench owns this.
     92 };
     93 
     94 void DecodingBench::onDraw(const int n, SkCanvas* canvas) {
     95     SkBitmap bitmap;
     96     // Declare the allocator before the decoder, so it will outlive the
     97     // decoder, which will unref it.
     98     TargetAllocator allocator(fPixelStorage.get());
     99     SkAutoTDelete<SkImageDecoder> decoder;
    100     SkAutoTDelete<SkStreamRewindable> stream;
    101     for (int i = 0; i < n; i++) {
    102         // create a new stream and a new decoder to mimic the behavior of
    103         // CodecBench.
    104         stream.reset(new SkMemoryStream(fData));
    105         decoder.reset(SkImageDecoder::Factory(stream));
    106         decoder->setAllocator(&allocator);
    107         decoder->decode(stream, &bitmap, fColorType,
    108                         SkImageDecoder::kDecodePixels_Mode);
    109     }
    110 }
    111