195f192d19938b98a45dd1fa4112d965f60d10516msarett/*
295f192d19938b98a45dd1fa4112d965f60d10516msarett * Copyright 2015 Google Inc.
395f192d19938b98a45dd1fa4112d965f60d10516msarett *
495f192d19938b98a45dd1fa4112d965f60d10516msarett * Use of this source code is governed by a BSD-style license that can be
595f192d19938b98a45dd1fa4112d965f60d10516msarett * found in the LICENSE file.
695f192d19938b98a45dd1fa4112d965f60d10516msarett */
795f192d19938b98a45dd1fa4112d965f60d10516msarett
895f192d19938b98a45dd1fa4112d965f60d10516msarett#include "DecodingBench.h"
921027994192f395bbd1507558b84f59b3c7cf0dascroggo#include "SkBitmap.h"
1095f192d19938b98a45dd1fa4112d965f60d10516msarett#include "SkData.h"
1195f192d19938b98a45dd1fa4112d965f60d10516msarett#include "SkImageDecoder.h"
1260869a42a133942f852dd0f1696444c2a5c9ad83scroggo#include "SkMallocPixelRef.h"
1395f192d19938b98a45dd1fa4112d965f60d10516msarett#include "SkOSFile.h"
1495f192d19938b98a45dd1fa4112d965f60d10516msarett#include "SkStream.h"
1595f192d19938b98a45dd1fa4112d965f60d10516msarett
1695f192d19938b98a45dd1fa4112d965f60d10516msarett/*
1795f192d19938b98a45dd1fa4112d965f60d10516msarett *
1895f192d19938b98a45dd1fa4112d965f60d10516msarett * This benchmark is designed to test the performance of image decoding.
1995f192d19938b98a45dd1fa4112d965f60d10516msarett * It is invoked from the nanobench.cpp file.
2095f192d19938b98a45dd1fa4112d965f60d10516msarett *
2195f192d19938b98a45dd1fa4112d965f60d10516msarett */
2295f192d19938b98a45dd1fa4112d965f60d10516msarettDecodingBench::DecodingBench(SkString path, SkColorType colorType)
2395f192d19938b98a45dd1fa4112d965f60d10516msarett    : fColorType(colorType)
2460869a42a133942f852dd0f1696444c2a5c9ad83scroggo    , fData(SkData::NewFromFileName(path.c_str()))
2595f192d19938b98a45dd1fa4112d965f60d10516msarett{
2695f192d19938b98a45dd1fa4112d965f60d10516msarett    // Parse filename and the color type to give the benchmark a useful name
2795f192d19938b98a45dd1fa4112d965f60d10516msarett    SkString baseName = SkOSPath::Basename(path.c_str());
2895f192d19938b98a45dd1fa4112d965f60d10516msarett    const char* colorName;
2995f192d19938b98a45dd1fa4112d965f60d10516msarett    switch(colorType) {
3095f192d19938b98a45dd1fa4112d965f60d10516msarett        case kN32_SkColorType:
3195f192d19938b98a45dd1fa4112d965f60d10516msarett            colorName = "N32";
3295f192d19938b98a45dd1fa4112d965f60d10516msarett            break;
3395f192d19938b98a45dd1fa4112d965f60d10516msarett        case kRGB_565_SkColorType:
3495f192d19938b98a45dd1fa4112d965f60d10516msarett            colorName = "565";
3595f192d19938b98a45dd1fa4112d965f60d10516msarett            break;
3695f192d19938b98a45dd1fa4112d965f60d10516msarett        case kAlpha_8_SkColorType:
3795f192d19938b98a45dd1fa4112d965f60d10516msarett            colorName = "Alpha8";
3895f192d19938b98a45dd1fa4112d965f60d10516msarett            break;
3995f192d19938b98a45dd1fa4112d965f60d10516msarett        default:
4095f192d19938b98a45dd1fa4112d965f60d10516msarett            colorName = "Unknown";
4195f192d19938b98a45dd1fa4112d965f60d10516msarett    }
4295f192d19938b98a45dd1fa4112d965f60d10516msarett    fName.printf("Decode_%s_%s", baseName.c_str(), colorName);
4395f192d19938b98a45dd1fa4112d965f60d10516msarett
4460869a42a133942f852dd0f1696444c2a5c9ad83scroggo#ifdef SK_DEBUG
4560869a42a133942f852dd0f1696444c2a5c9ad83scroggo    // Ensure that we can create a decoder.
4660869a42a133942f852dd0f1696444c2a5c9ad83scroggo    SkAutoTDelete<SkStreamRewindable> stream(new SkMemoryStream(fData));
4760869a42a133942f852dd0f1696444c2a5c9ad83scroggo    SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factory(stream));
4860869a42a133942f852dd0f1696444c2a5c9ad83scroggo    SkASSERT(decoder != NULL);
4960869a42a133942f852dd0f1696444c2a5c9ad83scroggo#endif
5095f192d19938b98a45dd1fa4112d965f60d10516msarett}
5195f192d19938b98a45dd1fa4112d965f60d10516msarett
5295f192d19938b98a45dd1fa4112d965f60d10516msarettconst char* DecodingBench::onGetName() {
5395f192d19938b98a45dd1fa4112d965f60d10516msarett    return fName.c_str();
5495f192d19938b98a45dd1fa4112d965f60d10516msarett}
5595f192d19938b98a45dd1fa4112d965f60d10516msarett
5695f192d19938b98a45dd1fa4112d965f60d10516msarettbool DecodingBench::isSuitableFor(Backend backend) {
5795f192d19938b98a45dd1fa4112d965f60d10516msarett    return kNonRendering_Backend == backend;
5895f192d19938b98a45dd1fa4112d965f60d10516msarett}
5995f192d19938b98a45dd1fa4112d965f60d10516msarett
6060869a42a133942f852dd0f1696444c2a5c9ad83scroggovoid DecodingBench::onPreDraw() {
6160869a42a133942f852dd0f1696444c2a5c9ad83scroggo    // Allocate the pixels now, to remove it from the loop.
6260869a42a133942f852dd0f1696444c2a5c9ad83scroggo    SkAutoTDelete<SkStreamRewindable> stream(new SkMemoryStream(fData));
6360869a42a133942f852dd0f1696444c2a5c9ad83scroggo    SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factory(stream));
6421027994192f395bbd1507558b84f59b3c7cf0dascroggo    SkBitmap bm;
6560869a42a133942f852dd0f1696444c2a5c9ad83scroggo#ifdef SK_DEBUG
6660869a42a133942f852dd0f1696444c2a5c9ad83scroggo    SkImageDecoder::Result result =
6760869a42a133942f852dd0f1696444c2a5c9ad83scroggo#endif
6821027994192f395bbd1507558b84f59b3c7cf0dascroggo    decoder->decode(stream, &bm, fColorType, SkImageDecoder::kDecodeBounds_Mode);
6960869a42a133942f852dd0f1696444c2a5c9ad83scroggo    SkASSERT(SkImageDecoder::kFailure != result);
7021027994192f395bbd1507558b84f59b3c7cf0dascroggo
7121027994192f395bbd1507558b84f59b3c7cf0dascroggo    const size_t rowBytes = bm.info().minRowBytes();
7221027994192f395bbd1507558b84f59b3c7cf0dascroggo    fPixelStorage.reset(bm.info().getSafeSize(rowBytes));
7360869a42a133942f852dd0f1696444c2a5c9ad83scroggo}
7460869a42a133942f852dd0f1696444c2a5c9ad83scroggo
7521027994192f395bbd1507558b84f59b3c7cf0dascroggo// Allocator which just uses an existing block of memory.
7621027994192f395bbd1507558b84f59b3c7cf0dascroggoclass TargetAllocator : public SkBitmap::Allocator {
7760869a42a133942f852dd0f1696444c2a5c9ad83scroggopublic:
7821027994192f395bbd1507558b84f59b3c7cf0dascroggo    explicit TargetAllocator(void* storage)
7921027994192f395bbd1507558b84f59b3c7cf0dascroggo        : fPixelStorage(storage) {}
8060869a42a133942f852dd0f1696444c2a5c9ad83scroggo
8160869a42a133942f852dd0f1696444c2a5c9ad83scroggo    bool allocPixelRef(SkBitmap* bm, SkColorTable* ct) override {
8221027994192f395bbd1507558b84f59b3c7cf0dascroggo        // We depend on the fact that this will only ever be used to
8321027994192f395bbd1507558b84f59b3c7cf0dascroggo        // decode to a bitmap with the same settings used to create
8421027994192f395bbd1507558b84f59b3c7cf0dascroggo        // fPixelStorage.
8560869a42a133942f852dd0f1696444c2a5c9ad83scroggo        bm->setPixelRef(SkMallocPixelRef::NewDirect(bm->info(),
8621027994192f395bbd1507558b84f59b3c7cf0dascroggo                fPixelStorage, bm->rowBytes(), ct))->unref();
8760869a42a133942f852dd0f1696444c2a5c9ad83scroggo        return true;
8860869a42a133942f852dd0f1696444c2a5c9ad83scroggo    }
8960869a42a133942f852dd0f1696444c2a5c9ad83scroggo
9060869a42a133942f852dd0f1696444c2a5c9ad83scroggoprivate:
9121027994192f395bbd1507558b84f59b3c7cf0dascroggo    void* fPixelStorage; // Unowned. DecodingBench owns this.
9260869a42a133942f852dd0f1696444c2a5c9ad83scroggo};
9360869a42a133942f852dd0f1696444c2a5c9ad83scroggo
9495f192d19938b98a45dd1fa4112d965f60d10516msarettvoid DecodingBench::onDraw(const int n, SkCanvas* canvas) {
9595f192d19938b98a45dd1fa4112d965f60d10516msarett    SkBitmap bitmap;
9660869a42a133942f852dd0f1696444c2a5c9ad83scroggo    // Declare the allocator before the decoder, so it will outlive the
9760869a42a133942f852dd0f1696444c2a5c9ad83scroggo    // decoder, which will unref it.
9821027994192f395bbd1507558b84f59b3c7cf0dascroggo    TargetAllocator allocator(fPixelStorage.get());
9960869a42a133942f852dd0f1696444c2a5c9ad83scroggo    SkAutoTDelete<SkImageDecoder> decoder;
10060869a42a133942f852dd0f1696444c2a5c9ad83scroggo    SkAutoTDelete<SkStreamRewindable> stream;
10195f192d19938b98a45dd1fa4112d965f60d10516msarett    for (int i = 0; i < n; i++) {
10260869a42a133942f852dd0f1696444c2a5c9ad83scroggo        // create a new stream and a new decoder to mimic the behavior of
10360869a42a133942f852dd0f1696444c2a5c9ad83scroggo        // CodecBench.
10460869a42a133942f852dd0f1696444c2a5c9ad83scroggo        stream.reset(new SkMemoryStream(fData));
10560869a42a133942f852dd0f1696444c2a5c9ad83scroggo        decoder.reset(SkImageDecoder::Factory(stream));
10660869a42a133942f852dd0f1696444c2a5c9ad83scroggo        decoder->setAllocator(&allocator);
10760869a42a133942f852dd0f1696444c2a5c9ad83scroggo        decoder->decode(stream, &bitmap, fColorType,
10860869a42a133942f852dd0f1696444c2a5c9ad83scroggo                        SkImageDecoder::kDecodePixels_Mode);
10995f192d19938b98a45dd1fa4112d965f60d10516msarett    }
11095f192d19938b98a45dd1fa4112d965f60d10516msarett}
111