/*
* Copyright 2014 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 "GrContext.h"
#include "GrLayerCache.h"
#include "GrResourceCache.h"
#include "SkPictureRecorder.h"
#include "Test.h"

class TestingAccess {
public:
    static int NumPlots() {
        return GrLayerCache::kNumPlotsX * GrLayerCache::kNumPlotsY;
    }
    static SkISize PlotSize() {
        return SkISize::Make(GrLayerCache::kAtlasTextureWidth / GrLayerCache::kNumPlotsX,
                             GrLayerCache::kAtlasTextureHeight / GrLayerCache::kNumPlotsY);
    }

    static GrTexture* GetBackingTexture(GrLayerCache* cache) {
        return cache->fAtlas->getTextureOrNull();
    }

    static int NumLayers(GrLayerCache* cache) {
        return cache->numLayers();
    }
    static void Purge(GrLayerCache* cache, uint32_t pictureID) {
        cache->purge(pictureID);
    }
    static int Uses(GrCachedLayer* layer) {
        return layer->uses();
    }
    static GrCachedLayer* Find(GrLayerCache* cache, uint32_t pictureID,
                               const SkMatrix& initialMat,
                               const int* key, int keySize) {
        return cache->findLayer(pictureID, initialMat, key, keySize);
    }
};

// Add several layers to the cache
static void create_layers(skiatest::Reporter* reporter,
                          GrLayerCache* cache,
                          const SkPicture& picture,
                          int numToAdd,
                          int idOffset) {

    for (int i = 0; i < numToAdd; ++i) {
        int key[1] = { idOffset+i+1 };
        GrCachedLayer* layer = cache->findLayerOrCreate(picture.uniqueID(),
                                                        idOffset+i+1, idOffset+i+2,
                                                        SkIRect::MakeEmpty(),
                                                        SkIRect::MakeEmpty(),
                                                        SkMatrix::I(),
                                                        key, 1,
                                                        nullptr);
        REPORTER_ASSERT(reporter, layer);
        GrCachedLayer* temp = TestingAccess::Find(cache, picture.uniqueID(), SkMatrix::I(),
                                                  key, 1);
        REPORTER_ASSERT(reporter, temp == layer);

        REPORTER_ASSERT(reporter, TestingAccess::NumLayers(cache) == idOffset + i + 1);

        REPORTER_ASSERT(reporter, picture.uniqueID() == layer->pictureID());
        REPORTER_ASSERT(reporter, layer->start() == idOffset + i + 1);
        REPORTER_ASSERT(reporter, layer->stop() == idOffset + i + 2);
        REPORTER_ASSERT(reporter, nullptr == layer->texture());
        REPORTER_ASSERT(reporter, nullptr == layer->paint());
        REPORTER_ASSERT(reporter, !layer->isAtlased());
    }
}

static void lock_layer(skiatest::Reporter* reporter,
                       GrLayerCache* cache,
                       GrCachedLayer* layer) {
    // Make each layer big enough to consume one whole plot in the atlas
    GrSurfaceDesc desc;
    desc.fFlags = kRenderTarget_GrSurfaceFlag;
    desc.fWidth = TestingAccess::PlotSize().fWidth;
    desc.fHeight = TestingAccess::PlotSize().fHeight;
    desc.fConfig = kSkia8888_GrPixelConfig;

    bool needsRerendering;
    bool inAtlas = cache->tryToAtlas(layer, desc, &needsRerendering);
    if (!inAtlas) {
        cache->lock(layer, desc, &needsRerendering);
    }
    REPORTER_ASSERT(reporter, needsRerendering);

    cache->lock(layer, desc, &needsRerendering);
    REPORTER_ASSERT(reporter, !needsRerendering);

    REPORTER_ASSERT(reporter, layer->texture());
    REPORTER_ASSERT(reporter, layer->locked());

    cache->addUse(layer);

    REPORTER_ASSERT(reporter, 1 == TestingAccess::Uses(layer));
}

// This test case exercises the public API of the GrLayerCache class.
// In particular it checks its interaction with the resource cache (w.r.t.
// locking & unlocking textures).
// TODO: need to add checks on VRAM usage!
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GpuLayerCache, reporter, context) {
    // Add one more layer than can fit in the atlas
    static const int kInitialNumLayers = TestingAccess::NumPlots() + 1;

#if GR_CACHE_STATS
    GrResourceCache::Stats stats;
#endif

    SkAutoTUnref<const SkPicture> picture;

    {
        SkPictureRecorder recorder;
        SkCanvas* c = recorder.beginRecording(1, 1);
        // Draw something, anything, to prevent an empty-picture optimization,
        // which is a singleton and never purged.
        c->drawRect(SkRect::MakeWH(1,1), SkPaint());
        picture.reset(recorder.endRecording());
    }

    GrResourceCache* resourceCache = context->getResourceCache();

    GrLayerCache cache(context);

    create_layers(reporter, &cache, *picture, kInitialNumLayers, 0);

    for (int i = 0; i < kInitialNumLayers; ++i) {
        int key[1] = { i + 1 };
        GrCachedLayer* layer = TestingAccess::Find(&cache, picture->uniqueID(), SkMatrix::I(),
                                                   key, 1);
        REPORTER_ASSERT(reporter, layer);

        lock_layer(reporter, &cache, layer);

#if GR_CACHE_STATS
        resourceCache->getStats(&stats);
#endif

        // The first 4 layers should be in the atlas (and thus have non-empty rects)
        if (i < TestingAccess::NumPlots()) {
            REPORTER_ASSERT(reporter, layer->isAtlased());
#if GR_CACHE_STATS
            REPORTER_ASSERT(reporter, 1 == stats.fTotal);
#endif
        } else {
            // The 5th layer couldn't fit in the atlas
            REPORTER_ASSERT(reporter, !layer->isAtlased());
#if GR_CACHE_STATS
            REPORTER_ASSERT(reporter, 2 == stats.fTotal);
#endif
        }
    }

    // Unlock the textures
    for (int i = 0; i < kInitialNumLayers; ++i) {
        int key[1] = { i+1 };

        GrCachedLayer* layer = TestingAccess::Find(&cache, picture->uniqueID(), SkMatrix::I(),
                                                   key, 1);
        REPORTER_ASSERT(reporter, layer);
        cache.removeUse(layer);
    }

#if GR_CACHE_STATS
    resourceCache->getStats(&stats);
    REPORTER_ASSERT(reporter, 2 == stats.fTotal);
    // The floating layer is purgeable the cache is not
    REPORTER_ASSERT(reporter, 1 == stats.fNumPurgeable);
    REPORTER_ASSERT(reporter, 1 == stats.fNumNonPurgeable);
#endif

    for (int i = 0; i < kInitialNumLayers; ++i) {
        int key[1] = { i+1 };

        GrCachedLayer* layer = TestingAccess::Find(&cache, picture->uniqueID(), SkMatrix::I(),
                                                   key, 1);
        REPORTER_ASSERT(reporter, layer);

        // All the layers should be unlocked
        REPORTER_ASSERT(reporter, !layer->locked());

        // When hoisted layers aren't cached they are aggressively removed
        // from the atlas
#if GR_CACHE_HOISTED_LAYERS
        // The first 4 layers should still be in the atlas.
        if (i < 4) {
            REPORTER_ASSERT(reporter, layer->texture());
            REPORTER_ASSERT(reporter, layer->isAtlased());
        } else {
#endif
            // The final layer should not be atlased.
            REPORTER_ASSERT(reporter, nullptr == layer->texture());
            REPORTER_ASSERT(reporter, !layer->isAtlased());
#if GR_CACHE_HOISTED_LAYERS
        }
#endif
    }

    // Let go of the backing texture
    cache.end();
    REPORTER_ASSERT(reporter, nullptr == TestingAccess::GetBackingTexture(&cache));

#if GR_CACHE_STATS
    resourceCache->getStats(&stats);
    REPORTER_ASSERT(reporter, 2 == stats.fTotal);
    // Now both the floater and the atlas are purgeable
    REPORTER_ASSERT(reporter, 2 == stats.fNumPurgeable);
#endif

    // re-attach to the backing texture
    cache.begin();
    REPORTER_ASSERT(reporter, TestingAccess::GetBackingTexture(&cache));

#if GR_CACHE_STATS
    resourceCache->getStats(&stats);
    REPORTER_ASSERT(reporter, 2 == stats.fTotal);
    // The atlas is restored to being non-purgeable
    REPORTER_ASSERT(reporter, 1 == stats.fNumPurgeable);
    REPORTER_ASSERT(reporter, 1 == stats.fNumNonPurgeable);
#endif

    {
        int key[1] = { kInitialNumLayers+1 };

        // Add an additional layer. Since all the layers are unlocked this
        // will force out the first atlased layer
        create_layers(reporter, &cache, *picture, 1, kInitialNumLayers);
        GrCachedLayer* layer = TestingAccess::Find(&cache, picture->uniqueID(), SkMatrix::I(),
                                                   key, 1);
        REPORTER_ASSERT(reporter, layer);

        lock_layer(reporter, &cache, layer);
        cache.removeUse(layer);
    }

    for (int i = 0; i < kInitialNumLayers+1; ++i) {
        int key[1] = { i+1 };

        GrCachedLayer* layer = TestingAccess::Find(&cache, picture->uniqueID(), SkMatrix::I(),
                                                   key, 1);
#if GR_CACHE_HOISTED_LAYERS
        // 3 old layers plus the new one should be in the atlas.
        if (1 == i || 2 == i || 3 == i || 5 == i) {
            REPORTER_ASSERT(reporter, layer);
            REPORTER_ASSERT(reporter, !layer->locked());
            REPORTER_ASSERT(reporter, layer->texture());
            REPORTER_ASSERT(reporter, layer->isAtlased());
        } else if (4 == i) {
#endif
            // The one that was never atlased should still be around
            REPORTER_ASSERT(reporter, layer);

            REPORTER_ASSERT(reporter, nullptr == layer->texture());
            REPORTER_ASSERT(reporter, !layer->isAtlased());
#if GR_CACHE_HOISTED_LAYERS
        } else {
            // The one bumped out of the atlas (i.e., 0) should be gone
            REPORTER_ASSERT(reporter, nullptr == layer);
        }
#endif
    }

    //--------------------------------------------------------------------
    // Free them all SkGpuDevice-style. This will not free up the
    // atlas' texture but will eliminate all the layers.
    TestingAccess::Purge(&cache, picture->uniqueID());

    REPORTER_ASSERT(reporter, TestingAccess::NumLayers(&cache) == 0);

#if GR_CACHE_STATS
    resourceCache->getStats(&stats);
    REPORTER_ASSERT(reporter, 2 == stats.fTotal);
    // Atlas isn't purgeable
    REPORTER_ASSERT(reporter, 1 == stats.fNumPurgeable);
    REPORTER_ASSERT(reporter, 1 == stats.fNumNonPurgeable);
#endif

    //--------------------------------------------------------------------
    // Test out the GrContext-style purge. This should remove all the layers
    // and the atlas.
    // Re-create the layers
    create_layers(reporter, &cache, *picture, kInitialNumLayers, 0);

    // Free them again GrContext-style. This should free up everything.
    cache.freeAll();

    REPORTER_ASSERT(reporter, TestingAccess::NumLayers(&cache) == 0);

    REPORTER_ASSERT(reporter, nullptr == TestingAccess::GetBackingTexture(&cache));

#if GR_CACHE_STATS
    resourceCache->getStats(&stats);
    REPORTER_ASSERT(reporter, 2 == stats.fTotal);
    REPORTER_ASSERT(reporter, 2 == stats.fNumPurgeable);
#endif

    // Purge the resource cache ...
    resourceCache->purgeAllUnlocked();

#if GR_CACHE_STATS
    resourceCache->getStats(&stats);
    REPORTER_ASSERT(reporter, 0 == stats.fTotal);
#endif

    // and try to re-attach to the backing texture. This should fail
    cache.begin();
    REPORTER_ASSERT(reporter, nullptr == TestingAccess::GetBackingTexture(&cache));

    //--------------------------------------------------------------------
    // Test out the MessageBus-style purge. This will not free the atlas
    // but should eliminate the free-floating layers.
    create_layers(reporter, &cache, *picture, kInitialNumLayers, 0);

    // Allocate/use the layers
    for (int i = 0; i < kInitialNumLayers; ++i) {
        int key[1] = { i + 1 };
        GrCachedLayer* layer = TestingAccess::Find(&cache, picture->uniqueID(), SkMatrix::I(),
                                                   key, 1);
        REPORTER_ASSERT(reporter, layer);

        lock_layer(reporter, &cache, layer);
    }

#if GR_CACHE_STATS
    resourceCache->getStats(&stats);
    REPORTER_ASSERT(reporter, 2 == stats.fTotal);
    REPORTER_ASSERT(reporter, 2 == stats.fNumNonPurgeable);
#endif

    // Unlock the textures
    for (int i = 0; i < kInitialNumLayers; ++i) {
        int key[1] = { i+1 };

        GrCachedLayer* layer = TestingAccess::Find(&cache, picture->uniqueID(), SkMatrix::I(),
                                                   key, 1);
        REPORTER_ASSERT(reporter, layer);
        cache.removeUse(layer);
    }

    picture.reset(nullptr);
    cache.processDeletedPictures();

    REPORTER_ASSERT(reporter, TestingAccess::NumLayers(&cache) == 0);

#if GR_CACHE_STATS
    resourceCache->getStats(&stats);
    REPORTER_ASSERT(reporter, 2 == stats.fTotal);
    REPORTER_ASSERT(reporter, 1 == stats.fNumPurgeable);
    REPORTER_ASSERT(reporter, 1 == stats.fNumNonPurgeable);
#endif

    cache.end();

#if GR_CACHE_STATS
    resourceCache->getStats(&stats);
    REPORTER_ASSERT(reporter, 2 == stats.fTotal);
    REPORTER_ASSERT(reporter, 2 == stats.fNumPurgeable);
#endif
}

#endif
