/*
 * 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 "CodecBenchPriv.h"
#include "DecodingBench.h"
#include "SkBitmap.h"
#include "SkData.h"
#include "SkImageDecoder.h"
#include "SkMallocPixelRef.h"
#include "SkOSFile.h"
#include "SkStream.h"

/*
 *
 * This benchmark is designed to test the performance of image decoding.
 * It is invoked from the nanobench.cpp file.
 *
 */
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());
    fName.printf("Decode_%s_%s", baseName.c_str(), color_type_to_str(colorType));
    
#ifdef SK_DEBUG
    // Ensure that we can create a decoder.
    SkAutoTDelete<SkStreamRewindable> stream(new SkMemoryStream(fData));
    SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factory(stream));
    SkASSERT(decoder != nullptr);
#endif
}

const char* DecodingBench::onGetName() {
    return fName.c_str();
}

bool DecodingBench::isSuitableFor(Backend backend) {
    return kNonRendering_Backend == backend;
}

void DecodingBench::onDelayedSetup() {
    // Allocate the pixels now, to remove it from the loop.
    SkAutoTDelete<SkStreamRewindable> stream(new SkMemoryStream(fData));
    SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factory(stream));
    SkBitmap bm;
#ifdef SK_DEBUG
    SkImageDecoder::Result result =
#endif
    decoder->decode(stream, &bm, fColorType, SkImageDecoder::kDecodeBounds_Mode);
    SkASSERT(SkImageDecoder::kFailure != result);

    const size_t rowBytes = bm.info().minRowBytes();
    fPixelStorage.reset(bm.info().getSafeSize(rowBytes));
}

// Allocator which just uses an existing block of memory.
class TargetAllocator : public SkBitmap::Allocator {
public:
    explicit TargetAllocator(void* storage)
        : fPixelStorage(storage) {}

    bool allocPixelRef(SkBitmap* bm, SkColorTable* ct) override {
        // We depend on the fact that this will only ever be used to
        // decode to a bitmap with the same settings used to create
        // fPixelStorage.
        bm->setPixelRef(SkMallocPixelRef::NewDirect(bm->info(),
                fPixelStorage, bm->rowBytes(), ct))->unref();
        return true;
    }

private:
    void* fPixelStorage; // Unowned. DecodingBench owns this.
};

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.
    TargetAllocator allocator(fPixelStorage.get());
    SkAutoTDelete<SkImageDecoder> decoder;
    SkAutoTDelete<SkStreamRewindable> stream;
    for (int i = 0; i < n; i++) {
        // 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);
    }
}
