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

#if SK_SUPPORT_GPU

#include "GrContextFactory.h"
#include "GrResourceCache.h"
#include "SkGpuDevice.h"
#include "Test.h"

static const int gWidth = 640;
static const int gHeight = 480;

////////////////////////////////////////////////////////////////////////////////
static void test_cache(skiatest::Reporter* reporter,
                       GrContext* context,
                       SkCanvas* canvas) {
    const SkIRect size = SkIRect::MakeWH(gWidth, gHeight);

    SkBitmap src;
    src.allocN32Pixels(size.width(), size.height());
    src.eraseColor(SK_ColorBLACK);
    size_t srcSize = src.getSize();

    size_t initialCacheSize;
    context->getResourceCacheUsage(NULL, &initialCacheSize);

    int oldMaxNum;
    size_t oldMaxBytes;
    context->getResourceCacheLimits(&oldMaxNum, &oldMaxBytes);

    // Set the cache limits so we can fit 10 "src" images and the
    // max number of textures doesn't matter
    size_t maxCacheSize = initialCacheSize + 10*srcSize;
    context->setResourceCacheLimits(1000, maxCacheSize);

    SkBitmap readback;
    readback.allocN32Pixels(size.width(), size.height());

    for (int i = 0; i < 100; ++i) {
        canvas->drawBitmap(src, 0, 0);
        canvas->readPixels(size, &readback);

        // "modify" the src texture
        src.notifyPixelsChanged();

        size_t curCacheSize;
        context->getResourceCacheUsage(NULL, &curCacheSize);

        // we should never go over the size limit
        REPORTER_ASSERT(reporter, curCacheSize <= maxCacheSize);
    }

    context->setResourceCacheLimits(oldMaxNum, oldMaxBytes);
}

class TestResource : public GrGpuResource {
    static const size_t kDefaultSize = 100;

public:
    SK_DECLARE_INST_COUNT(TestResource);
    TestResource(GrGpu* gpu, size_t size = kDefaultSize)
        : INHERITED(gpu, false)
        , fCache(NULL)
        , fToDelete(NULL)
        , fSize(size) {
        ++fAlive;
        this->registerWithCache();
    }

    ~TestResource() {
        --fAlive;
        if (NULL != fToDelete) {
            // Breaks our little 2-element cycle below.
            fToDelete->setDeleteWhenDestroyed(NULL, NULL);
            fCache->deleteResource(fToDelete->getCacheEntry());
        }
        this->release();
    }

    void setSize(size_t size) {
        fSize = size;
        this->didChangeGpuMemorySize();
    }

    size_t gpuMemorySize() const SK_OVERRIDE { return fSize; }

    static int alive() { return fAlive; }

    void setDeleteWhenDestroyed(GrResourceCache* cache, TestResource* resource) {
        fCache = cache;
        fToDelete = resource;
    }

private:
    GrResourceCache* fCache;
    TestResource* fToDelete;
    size_t fSize;
    static int fAlive;

    typedef GrGpuResource INHERITED;
};
int TestResource::fAlive = 0;

static void test_purge_invalidated(skiatest::Reporter* reporter, GrContext* context) {
    GrCacheID::Domain domain = GrCacheID::GenerateDomain();
    GrCacheID::Key keyData;
    keyData.fData64[0] = 5;
    keyData.fData64[1] = 18;
    GrResourceKey::ResourceType t = GrResourceKey::GenerateResourceType();
    GrResourceKey key(GrCacheID(domain, keyData), t, 0);

    GrResourceCache cache(5, 30000);

    // Add two resources with the same key that delete each other from the cache when destroyed.
    TestResource* a = new TestResource(context->getGpu());
    TestResource* b = new TestResource(context->getGpu());
    cache.addResource(key, a);
    cache.addResource(key, b);
    // Circle back.
    a->setDeleteWhenDestroyed(&cache, b);
    b->setDeleteWhenDestroyed(&cache, a);
    a->unref();
    b->unref();

    // Add a third independent resource also with the same key.
    GrGpuResource* r = new TestResource(context->getGpu());
    cache.addResource(key, r);
    r->unref();

    // Invalidate all three, all three should be purged and destroyed.
    REPORTER_ASSERT(reporter, 3 == TestResource::alive());
    const GrResourceInvalidatedMessage msg = { key };
    SkMessageBus<GrResourceInvalidatedMessage>::Post(msg);
    cache.purgeAsNeeded();
    REPORTER_ASSERT(reporter, 0 == TestResource::alive());
}

static void test_cache_delete_on_destruction(skiatest::Reporter* reporter,
                                             GrContext* context) {
    GrCacheID::Domain domain = GrCacheID::GenerateDomain();
    GrCacheID::Key keyData;
    keyData.fData64[0] = 5;
    keyData.fData64[1] = 0;
    GrResourceKey::ResourceType t = GrResourceKey::GenerateResourceType();

    GrResourceKey key(GrCacheID(domain, keyData), t, 0);

    {
        {
            GrResourceCache cache(3, 30000);
            TestResource* a = new TestResource(context->getGpu());
            TestResource* b = new TestResource(context->getGpu());
            cache.addResource(key, a);
            cache.addResource(key, b);

            a->setDeleteWhenDestroyed(&cache, b);
            b->setDeleteWhenDestroyed(&cache, a);

            a->unref();
            b->unref();
            REPORTER_ASSERT(reporter, 2 == TestResource::alive());
        }
        REPORTER_ASSERT(reporter, 0 == TestResource::alive());
    }
    {
        GrResourceCache cache(3, 30000);
        TestResource* a = new TestResource(context->getGpu());
        TestResource* b = new TestResource(context->getGpu());
        cache.addResource(key, a);
        cache.addResource(key, b);

        a->setDeleteWhenDestroyed(&cache, b);
        b->setDeleteWhenDestroyed(&cache, a);

        a->unref();
        b->unref();

        cache.deleteResource(a->getCacheEntry());

        REPORTER_ASSERT(reporter, 0 == TestResource::alive());
    }
}

static void test_resource_size_changed(skiatest::Reporter* reporter,
                                       GrContext* context) {
    GrCacheID::Domain domain = GrCacheID::GenerateDomain();
    GrResourceKey::ResourceType t = GrResourceKey::GenerateResourceType();

    GrCacheID::Key key1Data;
    key1Data.fData64[0] = 0;
    key1Data.fData64[1] = 0;
    GrResourceKey key1(GrCacheID(domain, key1Data), t, 0);

    GrCacheID::Key key2Data;
    key2Data.fData64[0] = 1;
    key2Data.fData64[1] = 0;
    GrResourceKey key2(GrCacheID(domain, key2Data), t, 0);

    // Test changing resources sizes (both increase & decrease).
    {
        GrResourceCache cache(2, 300);

        TestResource* a = new TestResource(context->getGpu());
        a->setSize(100); // Test didChangeGpuMemorySize() when not in the cache.
        cache.addResource(key1, a);
        a->unref();

        TestResource* b = new TestResource(context->getGpu());
        b->setSize(100);
        cache.addResource(key2, b);
        b->unref();

        REPORTER_ASSERT(reporter, 200 == cache.getCachedResourceBytes());
        REPORTER_ASSERT(reporter, 2 == cache.getCachedResourceCount());

        static_cast<TestResource*>(cache.find(key2))->setSize(200);
        static_cast<TestResource*>(cache.find(key1))->setSize(50);

        REPORTER_ASSERT(reporter, 250 == cache.getCachedResourceBytes());
        REPORTER_ASSERT(reporter, 2 == cache.getCachedResourceCount());
    }

    // Test increasing a resources size beyond the cache budget.
    {
        GrResourceCache cache(2, 300);

        TestResource* a = new TestResource(context->getGpu(), 100);
        cache.addResource(key1, a);
        a->unref();

        TestResource* b = new TestResource(context->getGpu(), 100);
        cache.addResource(key2, b);
        b->unref();

        REPORTER_ASSERT(reporter, 200 == cache.getCachedResourceBytes());
        REPORTER_ASSERT(reporter, 2 == cache.getCachedResourceCount());

        static_cast<TestResource*>(cache.find(key2))->setSize(201);
        REPORTER_ASSERT(reporter, NULL == cache.find(key1));

        REPORTER_ASSERT(reporter, 201 == cache.getCachedResourceBytes());
        REPORTER_ASSERT(reporter, 1 == cache.getCachedResourceCount());
    }

    // Test changing the size of an exclusively-held resource.
    {
        GrResourceCache cache(2, 300);

        TestResource* a = new TestResource(context->getGpu(), 100);
        cache.addResource(key1, a);
        cache.makeExclusive(a->getCacheEntry());

        TestResource* b = new TestResource(context->getGpu(), 100);
        cache.addResource(key2, b);
        b->unref();

        REPORTER_ASSERT(reporter, 200 == cache.getCachedResourceBytes());
        REPORTER_ASSERT(reporter, 2 == cache.getCachedResourceCount());
        REPORTER_ASSERT(reporter, NULL == cache.find(key1));

        a->setSize(200);

        REPORTER_ASSERT(reporter, 300 == cache.getCachedResourceBytes());
        REPORTER_ASSERT(reporter, 2 == cache.getCachedResourceCount());
        // Internal resource cache validation will test the detached size (debug mode only).

        cache.makeNonExclusive(a->getCacheEntry());
        a->unref();

        REPORTER_ASSERT(reporter, 300 == cache.getCachedResourceBytes());
        REPORTER_ASSERT(reporter, 2 == cache.getCachedResourceCount());
        REPORTER_ASSERT(reporter, NULL != cache.find(key1));
        // Internal resource cache validation will test the detached size (debug mode only).
    }
}

////////////////////////////////////////////////////////////////////////////////
DEF_GPUTEST(ResourceCache, reporter, factory) {
    for (int type = 0; type < GrContextFactory::kLastGLContextType; ++type) {
        GrContextFactory::GLContextType glType = static_cast<GrContextFactory::GLContextType>(type);
        if (!GrContextFactory::IsRenderingGLContext(glType)) {
            continue;
        }
        GrContext* context = factory->get(glType);
        if (NULL == context) {
            continue;
        }

        GrTextureDesc desc;
        desc.fConfig = kSkia8888_GrPixelConfig;
        desc.fFlags = kRenderTarget_GrTextureFlagBit;
        desc.fWidth = gWidth;
        desc.fHeight = gHeight;

        SkAutoTUnref<GrTexture> texture(context->createUncachedTexture(desc, NULL, 0));
        SkAutoTUnref<SkGpuDevice> device(SkNEW_ARGS(SkGpuDevice, (context, texture.get())));
        SkCanvas canvas(device.get());

        test_cache(reporter, context, &canvas);
        test_purge_invalidated(reporter, context);
        test_cache_delete_on_destruction(reporter, context);
        test_resource_size_changed(reporter, context);
    }
}

#endif
