/*
 * Copyright 2014 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "Benchmark.h"
#include "Resources.h"
#include "SkCanvas.h"
#include "SkData.h"
#include "SkDecodingImageGenerator.h"
#include "SkImageDecoder.h"
#include "SkOSFile.h"
#include "SkPixelRef.h"

#ifndef SK_IGNORE_ETC1_SUPPORT

#include "etc1.h"

// This takes the etc1 data pointed to by orig, and copies it `factor` times in each
// dimension. The return value is the new data or NULL on error.
static etc1_byte* create_expanded_etc1_bitmap(const uint8_t* orig, int factor) {
    SkASSERT(NULL != orig);
    SkASSERT(factor > 1);

    const etc1_byte* origData = reinterpret_cast<const etc1_byte*>(orig);
    if (!etc1_pkm_is_valid(orig)) {
        return NULL;
    }

    etc1_uint32 origWidth = etc1_pkm_get_width(origData);
    etc1_uint32 origHeight = etc1_pkm_get_height(origData);

    // The width and height must be aligned along block boundaries
    static const etc1_uint32 kETC1BlockWidth = 4;
    static const etc1_uint32 kETC1BlockHeight = 4;
    if ((origWidth % kETC1BlockWidth) != 0 ||
        (origHeight % kETC1BlockHeight) != 0) {
        return NULL;
    }

    // The picture must be at least as large as a block.
    if (origWidth <= kETC1BlockWidth || origHeight <= kETC1BlockHeight) {
        return NULL;
    }

    etc1_uint32 newWidth = origWidth * factor;
    etc1_uint32 newHeight = origHeight * factor;

    etc1_uint32 newDataSz = etc1_get_encoded_data_size(newWidth, newHeight);
    etc1_byte* newData = reinterpret_cast<etc1_byte *>(
        sk_malloc_throw(newDataSz + ETC_PKM_HEADER_SIZE));
    etc1_pkm_format_header(newData, newWidth, newHeight);

    etc1_byte* copyInto = newData;

    copyInto += ETC_PKM_HEADER_SIZE;
    origData += ETC_PKM_HEADER_SIZE;

    etc1_uint32 origBlocksX = (origWidth >> 2);
    etc1_uint32 origBlocksY = (origHeight >> 2);
    etc1_uint32 newBlocksY = (newHeight >> 2);
    etc1_uint32 origRowSzInBytes = origBlocksX * ETC1_ENCODED_BLOCK_SIZE;

    for (etc1_uint32 j = 0; j < newBlocksY; ++j) {
        const etc1_byte* rowStart = origData + ((j % origBlocksY) * origRowSzInBytes);
        for(etc1_uint32 i = 0; i < newWidth; i += origWidth) {
            memcpy(copyInto, rowStart, origRowSzInBytes);
            copyInto += origRowSzInBytes;
        }
    }
    return newData;
}

// This is the base class for all of the benches in this file. In general
// the ETC1 benches should all be working on the same data. Due to the
// simplicity of the PKM file, that data is the 128x128 mandrill etc1
// compressed texture repeated by some factor (currently 8 -> 1024x1024)
class ETCBitmapBenchBase : public Benchmark {
public:
    ETCBitmapBenchBase() : fPKMData(loadPKM()) {
        if (NULL == fPKMData) {
            SkDebugf("Could not load PKM data!");
        }
    }

protected:
    SkAutoDataUnref fPKMData;

private:
    SkData* loadPKM() {
        SkString pkmFilename = GetResourcePath("mandrill_128.pkm");
        // Expand the data
        SkAutoDataUnref fileData(SkData::NewFromFileName(pkmFilename.c_str()));
        if (NULL == fileData) {
            SkDebugf("Could not open the file. Did you forget to set the resourcePath?\n");
            return NULL;
        }

        const etc1_uint32 kExpansionFactor = 8;
        etc1_byte* expandedETC1 =
            create_expanded_etc1_bitmap(fileData->bytes(), kExpansionFactor);
        if (NULL == expandedETC1) {
            SkDebugf("Error expanding ETC1 data by factor of %d\n", kExpansionFactor);
            return NULL;
        }

        etc1_uint32 width = etc1_pkm_get_width(expandedETC1);
        etc1_uint32 height = etc1_pkm_get_width(expandedETC1);
        etc1_uint32 dataSz = ETC_PKM_HEADER_SIZE + etc1_get_encoded_data_size(width, height);
        return SkData::NewFromMalloc(expandedETC1, dataSz);
    }

    typedef Benchmark INHERITED;
};

// This is the rendering benchmark. Prior to rendering the data, create a
// bitmap using the etc1 data.
class ETCBitmapBench : public ETCBitmapBenchBase {
public:
    ETCBitmapBench(bool decompress, Backend backend)
        : fDecompress(decompress), fBackend(backend) { }

    virtual bool isSuitableFor(Backend backend) SK_OVERRIDE {
        return backend == this->fBackend;
    }

protected:
    virtual const char* onGetName() SK_OVERRIDE {
        if (kGPU_Backend == this->fBackend) {
            if (this->fDecompress) {
                return "etc1bitmap_render_gpu_decompressed";
            } else {
                return "etc1bitmap_render_gpu_compressed";
            }
        } else {
            SkASSERT(kRaster_Backend == this->fBackend);
            if (this->fDecompress) {
                return "etc1bitmap_render_raster_decompressed";
            } else {
                return "etc1bitmap_render_raster_compressed";
            }
        }
    }

    virtual void onPreDraw() SK_OVERRIDE {
        if (NULL == fPKMData) {
            SkDebugf("Failed to load PKM data!\n");
            return;
        }

        // Install pixel ref
        if (!SkInstallDiscardablePixelRef(
                SkDecodingImageGenerator::Create(
                    fPKMData, SkDecodingImageGenerator::Options()), &(this->fBitmap))) {
            SkDebugf("Could not install discardable pixel ref.\n");
            return;
        }

        // Decompress it if necessary
        if (this->fDecompress) {
            this->fBitmap.lockPixels();
        }
    }

    virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
        for (int i = 0; i < loops; ++i) {
            canvas->drawBitmap(this->fBitmap, 0, 0, NULL);
        }
    }

protected:
    SkBitmap fBitmap;
    bool decompress() const { return fDecompress; }
    Backend backend() const { return fBackend; }
private:
    const bool fDecompress;
    const Backend fBackend;
    typedef ETCBitmapBenchBase INHERITED;
};

// This benchmark is identical to the previous benchmark, but it explicitly forces
// an upload to the GPU before each draw call. We do this by notifying the bitmap
// that the pixels have changed (even though they haven't).
class ETCBitmapUploadBench : public ETCBitmapBench {
public:
    ETCBitmapUploadBench(bool decompress, Backend backend)
        : ETCBitmapBench(decompress, backend) { }

protected:
    virtual const char* onGetName() SK_OVERRIDE {
        if (kGPU_Backend == this->backend()) {
            if (this->decompress()) {
                return "etc1bitmap_upload_gpu_decompressed";
            } else {
                return "etc1bitmap_upload_gpu_compressed";
            }
        } else {
            SkASSERT(kRaster_Backend == this->backend());
            if (this->decompress()) {
                return "etc1bitmap_upload_raster_decompressed";
            } else {
                return "etc1bitmap_upload_raster_compressed";
            }
        }
    }

    virtual void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
        SkPixelRef* pr = fBitmap.pixelRef();
        for (int i = 0; i < loops; ++i) {
            if (pr) {
                pr->notifyPixelsChanged();
            }
            canvas->drawBitmap(this->fBitmap, 0, 0, NULL);
        }
    }

private:
    typedef ETCBitmapBench INHERITED;
};

DEF_BENCH(return new ETCBitmapBench(false, Benchmark::kRaster_Backend);)
DEF_BENCH(return new ETCBitmapBench(true, Benchmark::kRaster_Backend);)

DEF_BENCH(return new ETCBitmapBench(false, Benchmark::kGPU_Backend);)
DEF_BENCH(return new ETCBitmapBench(true, Benchmark::kGPU_Backend);)

DEF_BENCH(return new ETCBitmapUploadBench(false, Benchmark::kRaster_Backend);)
DEF_BENCH(return new ETCBitmapUploadBench(true, Benchmark::kRaster_Backend);)

DEF_BENCH(return new ETCBitmapUploadBench(false, Benchmark::kGPU_Backend);)
DEF_BENCH(return new ETCBitmapUploadBench(true, Benchmark::kGPU_Backend);)

#endif  // SK_IGNORE_ETC1_SUPPORT
