
/*
 * Copyright 2013 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"

#if SK_SUPPORT_GPU

#include "GrGpuResource.h"
#include "GrContext.h"
#include "GrGpu.h"
#include "GrResourceCache2.h"
#include "SkCanvas.h"

enum {
    CACHE_SIZE_COUNT = 4096,
};

class BenchResource : public GrGpuResource {
public:
    SK_DECLARE_INST_COUNT(BenchResource);
    BenchResource (GrGpu* gpu)
        : INHERITED(gpu, kCached_LifeCycle) {
        this->registerWithCache();
    }

    static void ComputeKey(int i, GrContentKey* key) {
        static GrContentKey::Domain kDomain = GrContentKey::GenerateDomain();
        GrContentKey::Builder builder(key, kDomain, 1);
        builder[0] = i;
    }

private:
    size_t onGpuMemorySize() const SK_OVERRIDE { return 100; }

    typedef GrGpuResource INHERITED;
};

static void populate_cache(GrGpu* gpu, int resourceCount) {
    for (int i = 0; i < resourceCount; ++i) {
        GrContentKey key;
        BenchResource::ComputeKey(i, &key);
        GrGpuResource* resource = SkNEW_ARGS(BenchResource, (gpu));
        resource->cacheAccess().setContentKey(key);
        resource->unref();
    }
}

class GrResourceCacheBenchAdd : public Benchmark {
public:
    bool isSuitableFor(Backend backend) SK_OVERRIDE {
        return backend == kNonRendering_Backend;
    }

protected:
    const char* onGetName() SK_OVERRIDE {
        return "grresourcecache_add";
    }

    void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
        SkAutoTUnref<GrContext> context(GrContext::CreateMockContext());
        if (NULL == context) {
            return;
        }
        // Set the cache budget to be very large so no purging occurs.
        context->setResourceCacheLimits(CACHE_SIZE_COUNT, 1 << 30);

        GrResourceCache2* cache2 = context->getResourceCache2();

        // Make sure the cache is empty.
        cache2->purgeAllUnlocked();
        SkASSERT(0 == cache2->getResourceCount() && 0 == cache2->getResourceBytes());

        GrGpu* gpu = context->getGpu();

        for (int i = 0; i < loops; ++i) {
            populate_cache(gpu, CACHE_SIZE_COUNT);
            SkASSERT(CACHE_SIZE_COUNT == cache2->getResourceCount());
        }
    }

private:
    typedef Benchmark INHERITED;
};

class GrResourceCacheBenchFind : public Benchmark {
public:
    bool isSuitableFor(Backend backend) SK_OVERRIDE {
        return backend == kNonRendering_Backend;
    }

protected:
    const char* onGetName() SK_OVERRIDE {
        return "grresourcecache_find";
    }

    void onPreDraw() SK_OVERRIDE {
        fContext.reset(GrContext::CreateMockContext());
        if (!fContext) {
            return;
        }
        // Set the cache budget to be very large so no purging occurs.
        fContext->setResourceCacheLimits(CACHE_SIZE_COUNT, 1 << 30);

        GrResourceCache2* cache2 = fContext->getResourceCache2();

        // Make sure the cache is empty.
        cache2->purgeAllUnlocked();
        SkASSERT(0 == cache2->getResourceCount() && 0 == cache2->getResourceBytes());

        GrGpu* gpu = fContext->getGpu();

        populate_cache(gpu, CACHE_SIZE_COUNT);
    }

    void onDraw(const int loops, SkCanvas* canvas) SK_OVERRIDE {
        if (!fContext) {
            return;
        }
        GrResourceCache2* cache2 = fContext->getResourceCache2();
        SkASSERT(CACHE_SIZE_COUNT == cache2->getResourceCount());
        for (int i = 0; i < loops; ++i) {
            for (int k = 0; k < CACHE_SIZE_COUNT; ++k) {
                GrContentKey key;
                BenchResource::ComputeKey(k, &key);
                SkAutoTUnref<GrGpuResource> resource(cache2->findAndRefContentResource(key));
                SkASSERT(resource);
            }
        }
    }

private:
    SkAutoTUnref<GrContext> fContext;
    typedef Benchmark INHERITED;
};

DEF_BENCH( return new GrResourceCacheBenchAdd(); )
DEF_BENCH( return new GrResourceCacheBenchFind(); )

#endif
