/*
* 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, ctxInfo) {
    // 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

    sk_sp<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 = recorder.finishRecordingAsPicture();
    }

    GrResourceCache* resourceCache = ctxInfo.fGrContext->getResourceCache();

    GrLayerCache cache(ctxInfo.fGrContext);

    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
