/*
 * 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;
    }

    ~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
