/*
 * Copyright 2012 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */
#include "bench/Benchmark.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkString.h"
#include "include/private/SkTemplates.h"
#include "src/core/SkChecksum.h"
#include "src/core/SkMD5.h"
#include "src/core/SkRandom.h"

#include <memory>

enum ChecksumType {
    kMD5_ChecksumType,
    kWyhash_ChecksumType,
};

class ComputeChecksumBench : public Benchmark {
public:
    // All instances of this benchmark compute a checksum over 64K (or slightly less, if the
    // block size doesn't divide evenly).
    constexpr static size_t kBufferSize = 64 * 1024;

    ChecksumType fType;
    size_t fBlockSize;
    SkString fName;
    std::unique_ptr<uint8_t[]> fData;

    ComputeChecksumBench(ChecksumType type, size_t blockSize) : fType(type), fBlockSize(blockSize) {
        SkASSERT(blockSize <= kBufferSize);

        switch (fType) {
            case kMD5_ChecksumType: fName = "compute_md5"; break;
            case kWyhash_ChecksumType: fName = "compute_wyhash"; break;
        }
        fName.appendf("_%d", static_cast<int>(fBlockSize));
    }

    bool isSuitableFor(Backend backend) override { return backend == Backend::kNonRendering; }
    const char* onGetName() override { return fName.c_str(); }

    void onPreDraw(SkCanvas*) override {
        fData.reset(new uint8_t[kBufferSize]);

        SkRandom rand;
        for (size_t i = 0; i < kBufferSize; ++i) {
            fData[i] = rand.nextBits(8);
        }
    }

    void onPostDraw(SkCanvas*) override {
        fData.reset();
    }

    void onDraw(int loops, SkCanvas*) override {
        volatile uint32_t result = 0;
        const size_t blockCount = kBufferSize / fBlockSize;
        const uint8_t* bufEnd = fData.get() + (blockCount * fBlockSize);
        for (int i = 0; i < loops; i++) {
            for (const uint8_t* buf = fData.get(); buf < bufEnd; buf += fBlockSize) {
                switch (fType) {
                    case kMD5_ChecksumType: {
                        SkMD5 md5;
                        md5.write(buf, fBlockSize);
                        (void)md5.finish();
                        break;
                    }
                    case kWyhash_ChecksumType:
                        result = SkChecksum::Hash32(buf, fBlockSize);
                        break;
                }
            }
        }
        sk_ignore_unused_variable(result);
    }
};

///////////////////////////////////////////////////////////////////////////////

DEF_BENCH( return new ComputeChecksumBench(kMD5_ChecksumType, 1024); )

#define DEF_CHECKSUM_BENCH(T) \
    DEF_BENCH( return new ComputeChecksumBench(T, 4); ) \
    DEF_BENCH( return new ComputeChecksumBench(T, 8); ) \
    DEF_BENCH( return new ComputeChecksumBench(T, 15); ) \
    DEF_BENCH( return new ComputeChecksumBench(T, 16); ) \
    DEF_BENCH( return new ComputeChecksumBench(T, 31); ) \
    DEF_BENCH( return new ComputeChecksumBench(T, 32); ) \
    DEF_BENCH( return new ComputeChecksumBench(T, 96); ) \
    DEF_BENCH( return new ComputeChecksumBench(T, 1024); )

DEF_CHECKSUM_BENCH(kWyhash_ChecksumType)
