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

#ifndef GrThreadSafeCache_DEFINED
#define GrThreadSafeCache_DEFINED

#include "include/core/SkRefCnt.h"
#include "include/private/SkSpinlock.h"
#include "src/core/SkArenaAlloc.h"
#include "src/core/SkTDynamicHash.h"
#include "src/core/SkTInternalLList.h"
#include "src/gpu/GrGpuBuffer.h"
#include "src/gpu/GrSurfaceProxyView.h"

// Ganesh creates a lot of utility textures (e.g., blurred-rrect masks) that need to be shared
// between the direct context and all the DDL recording contexts. This thread-safe cache
// allows this sharing.
//
// In operation, each thread will first check if the threaded cache possesses the required texture.
//
// If a DDL thread doesn't find a needed texture it will go off and create it on the cpu and then
// attempt to add it to the cache. If another thread had added it in the interim, the losing thread
// will discard its work and use the texture the winning thread had created.
//
// If the thread in possession of the direct context doesn't find the needed texture it should
// add a place holder view and then queue up the draw calls to complete it. In this way the
// gpu-thread has precedence over the recording threads.
//
// The invariants for this cache differ a bit from those of the proxy and resource caches.
// For this cache:
//
//   only this cache knows the unique key - neither the proxy nor backing resource should
//              be discoverable in any other cache by the unique key
//   if a backing resource resides in the resource cache then there should be an entry in this
//              cache
//   an entry in this cache, however, doesn't guarantee that there is a corresponding entry in
//              the resource cache - although the entry here should be able to generate that entry
//              (i.e., be a lazy proxy)
//
// Wrt interactions w/ GrContext/GrResourceCache purging, we have:
//
//    Both GrContext::abandonContext and GrContext::releaseResourcesAndAbandonContext will cause
//    all the refs held in this cache to be dropped prior to clearing out the resource cache.
//
//    For the size_t-variant of GrContext::purgeUnlockedResources, after an initial attempt
//    to purge the requested amount of resources fails, uniquely held resources in this cache
//    will be dropped in LRU to MRU order until the cache is under budget. Note that this
//    prioritizes the survival of resources in this cache over those just in the resource cache.
//
//    For the 'scratchResourcesOnly' variant of GrContext::purgeUnlockedResources, this cache
//    won't be modified in the scratch-only case unless the resource cache is over budget (in
//    which case it will purge uniquely-held resources in LRU to MRU order to get
//    back under budget). In the non-scratch-only case, all uniquely held resources in this cache
//    will be released prior to the resource cache being cleared out.
//
//    For GrContext::setResourceCacheLimit, if an initial pass through the resource cache doesn't
//    reach the budget, uniquely held resources in this cache will be released in LRU to MRU order.
//
//    For GrContext::performDeferredCleanup, any uniquely held resources that haven't been accessed
//    w/in 'msNotUsed' will be released from this cache prior to the resource cache being cleaned.
class GrThreadSafeCache {
public:
    GrThreadSafeCache();
    ~GrThreadSafeCache();

#if GR_TEST_UTILS
    int numEntries() const  SK_EXCLUDES(fSpinLock);

    size_t approxBytesUsedForHash() const  SK_EXCLUDES(fSpinLock);
#endif

    void dropAllRefs()  SK_EXCLUDES(fSpinLock);

    // Drop uniquely held refs until under the resource cache's budget.
    // A null parameter means drop all uniquely held refs.
    void dropUniqueRefs(GrResourceCache* resourceCache)  SK_EXCLUDES(fSpinLock);

    // Drop uniquely held refs that were last accessed before 'purgeTime'
    void dropUniqueRefsOlderThan(GrStdSteadyClock::time_point purgeTime)  SK_EXCLUDES(fSpinLock);

    SkDEBUGCODE(bool has(const GrUniqueKey&)  SK_EXCLUDES(fSpinLock);)

    GrSurfaceProxyView find(const GrUniqueKey&)  SK_EXCLUDES(fSpinLock);
    std::tuple<GrSurfaceProxyView, sk_sp<SkData>> findWithData(
                                                      const GrUniqueKey&)  SK_EXCLUDES(fSpinLock);

    GrSurfaceProxyView add(const GrUniqueKey&, const GrSurfaceProxyView&)  SK_EXCLUDES(fSpinLock);
    std::tuple<GrSurfaceProxyView, sk_sp<SkData>> addWithData(
                            const GrUniqueKey&, const GrSurfaceProxyView&)  SK_EXCLUDES(fSpinLock);

    GrSurfaceProxyView findOrAdd(const GrUniqueKey&,
                                 const GrSurfaceProxyView&)  SK_EXCLUDES(fSpinLock);
    std::tuple<GrSurfaceProxyView, sk_sp<SkData>> findOrAddWithData(
                            const GrUniqueKey&, const GrSurfaceProxyView&)  SK_EXCLUDES(fSpinLock);

    // To hold vertex data in the cache and have it transparently transition from cpu-side to
    // gpu-side while being shared between all the threads we need a ref counted object that
    // keeps hold of the cpu-side data but allows deferred filling in of the mirroring gpu buffer.
    class VertexData : public SkNVRefCnt<VertexData> {
    public:
        ~VertexData();

        const void* vertices() const { return fVertices; }
        size_t size() const { return fNumVertices * fVertexSize; }

        int numVertices() const { return fNumVertices; }
        size_t vertexSize() const { return fVertexSize; }

        // TODO: make these return const GrGpuBuffers?
        GrGpuBuffer* gpuBuffer() { return fGpuBuffer.get(); }
        sk_sp<GrGpuBuffer> refGpuBuffer() { return fGpuBuffer; }

        void setGpuBuffer(sk_sp<GrGpuBuffer> gpuBuffer) {
            // TODO: once we add the gpuBuffer we could free 'fVertices'. Deinstantiable
            // DDLs could throw a monkey wrench into that plan though.
            SkASSERT(!fGpuBuffer);
            fGpuBuffer = gpuBuffer;
        }

        void reset() {
            sk_free(const_cast<void*>(fVertices));
            fVertices = nullptr;
            fNumVertices = 0;
            fVertexSize = 0;
            fGpuBuffer.reset();
        }

    private:
        friend class GrThreadSafeCache;  // for access to ctor

        VertexData(const void* vertices, int numVertices, size_t vertexSize)
                : fVertices(vertices)
                , fNumVertices(numVertices)
                , fVertexSize(vertexSize) {
        }

        VertexData(sk_sp<GrGpuBuffer> gpuBuffer, int numVertices, size_t vertexSize)
                : fVertices(nullptr)
                , fNumVertices(numVertices)
                , fVertexSize(vertexSize)
                , fGpuBuffer(std::move(gpuBuffer)) {
        }

        const void*        fVertices;
        int                fNumVertices;
        size_t             fVertexSize;

        sk_sp<GrGpuBuffer> fGpuBuffer;
    };

    // The returned VertexData object takes ownership of 'vertices' which had better have been
    // allocated with malloc!
    static sk_sp<VertexData> MakeVertexData(const void* vertices,
                                            int vertexCount,
                                            size_t vertexSize);
    static sk_sp<VertexData> MakeVertexData(sk_sp<GrGpuBuffer> buffer,
                                            int vertexCount,
                                            size_t vertexSize);

    std::tuple<sk_sp<VertexData>, sk_sp<SkData>> findVertsWithData(
                                                        const GrUniqueKey&)  SK_EXCLUDES(fSpinLock);

    typedef bool (*IsNewerBetter)(SkData* incumbent, SkData* challenger);

    std::tuple<sk_sp<VertexData>, sk_sp<SkData>> addVertsWithData(
                                                        const GrUniqueKey&,
                                                        sk_sp<VertexData>,
                                                        IsNewerBetter)  SK_EXCLUDES(fSpinLock);

    void remove(const GrUniqueKey&)  SK_EXCLUDES(fSpinLock);

    // To allow gpu-created resources to have priority, we pre-emptively place a lazy proxy
    // in the thread-safe cache (with findOrAdd). The Trampoline object allows that lazy proxy to
    // be instantiated with some later generated rendering result.
    class Trampoline : public SkRefCnt {
    public:
        sk_sp<GrTextureProxy> fProxy;
    };

    static std::tuple<GrSurfaceProxyView, sk_sp<Trampoline>> CreateLazyView(GrDirectContext*,
                                                                            GrColorType,
                                                                            SkISize dimensions,
                                                                            GrSurfaceOrigin,
                                                                            SkBackingFit);
private:
    struct Entry {
        Entry(const GrUniqueKey& key, const GrSurfaceProxyView& view)
                : fKey(key)
                , fView(view)
                , fTag(Entry::kView) {
        }

        Entry(const GrUniqueKey& key, sk_sp<VertexData> vertData)
                : fKey(key)
                , fVertData(std::move(vertData))
                , fTag(Entry::kVertData) {
        }

        ~Entry() {
            this->makeEmpty();
        }

        bool uniquelyHeld() const {
            SkASSERT(fTag != kEmpty);

            if (fTag == kView && fView.proxy()->unique()) {
                return true;
            } else if (fTag == kVertData && fVertData->unique()) {
                return true;
            }

            return false;
        }

        const GrUniqueKey& key() const {
            SkASSERT(fTag != kEmpty);
            return fKey;
        }

        SkData* getCustomData() const {
            SkASSERT(fTag != kEmpty);
            return fKey.getCustomData();
        }

        sk_sp<SkData> refCustomData() const {
            SkASSERT(fTag != kEmpty);
            return fKey.refCustomData();
        }

        GrSurfaceProxyView view() {
            SkASSERT(fTag == kView);
            return fView;
        }

        sk_sp<VertexData> vertexData() {
            SkASSERT(fTag == kVertData);
            return fVertData;
        }

        void set(const GrUniqueKey& key, const GrSurfaceProxyView& view) {
            SkASSERT(fTag == kEmpty);
            fKey = key;
            fView = view;
            fTag = kView;
        }

        void makeEmpty() {
            fKey.reset();
            if (fTag == kView) {
                fView.reset();
            } else if (fTag == kVertData) {
                fVertData.reset();
            }
            fTag = kEmpty;
        }

        void set(const GrUniqueKey& key, sk_sp<VertexData> vertData) {
            SkASSERT(fTag == kEmpty || fTag == kVertData);
            fKey = key;
            fVertData = vertData;
            fTag = kVertData;
        }

        // The thread-safe cache gets to directly manipulate the llist and last-access members
        GrStdSteadyClock::time_point fLastAccess;
        SK_DECLARE_INTERNAL_LLIST_INTERFACE(Entry);

        // for SkTDynamicHash
        static const GrUniqueKey& GetKey(const Entry& e) {
            SkASSERT(e.fTag != kEmpty);
            return e.fKey;
        }
        static uint32_t Hash(const GrUniqueKey& key) { return key.hash(); }

    private:
        // Note: the unique key is stored here bc it is never attached to a proxy or a GrTexture
        GrUniqueKey             fKey;
        union {
            GrSurfaceProxyView  fView;
            sk_sp<VertexData>   fVertData;
        };

        enum {
            kEmpty,
            kView,
            kVertData,
        } fTag { kEmpty };
    };

    void makeExistingEntryMRU(Entry*)  SK_REQUIRES(fSpinLock);
    Entry* makeNewEntryMRU(Entry*)  SK_REQUIRES(fSpinLock);

    Entry* getEntry(const GrUniqueKey&, const GrSurfaceProxyView&)  SK_REQUIRES(fSpinLock);
    Entry* getEntry(const GrUniqueKey&, sk_sp<VertexData>)  SK_REQUIRES(fSpinLock);

    void recycleEntry(Entry*)  SK_REQUIRES(fSpinLock);

    std::tuple<GrSurfaceProxyView, sk_sp<SkData>> internalFind(
                                                        const GrUniqueKey&)  SK_REQUIRES(fSpinLock);
    std::tuple<GrSurfaceProxyView, sk_sp<SkData>> internalAdd(
                                                const GrUniqueKey&,
                                                const GrSurfaceProxyView&)  SK_REQUIRES(fSpinLock);

    std::tuple<sk_sp<VertexData>, sk_sp<SkData>> internalFindVerts(
                                                        const GrUniqueKey&)  SK_REQUIRES(fSpinLock);
    std::tuple<sk_sp<VertexData>, sk_sp<SkData>> internalAddVerts(
                                                        const GrUniqueKey&,
                                                        sk_sp<VertexData>,
                                                        IsNewerBetter)  SK_REQUIRES(fSpinLock);

    mutable SkSpinlock fSpinLock;

    SkTDynamicHash<Entry, GrUniqueKey> fUniquelyKeyedEntryMap  SK_GUARDED_BY(fSpinLock);
    // The head of this list is the MRU
    SkTInternalLList<Entry>            fUniquelyKeyedEntryList  SK_GUARDED_BY(fSpinLock);

    // TODO: empirically determine this from the skps
    static const int kInitialArenaSize = 64 * sizeof(Entry);

    char                         fStorage[kInitialArenaSize];
    SkArenaAlloc                 fEntryAllocator{fStorage, kInitialArenaSize, kInitialArenaSize};
    Entry*                       fFreeEntryList  SK_GUARDED_BY(fSpinLock);
};

#endif // GrThreadSafeCache_DEFINED
