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

#ifndef skgpu_graphite_ProxyCache_DEFINED
#define skgpu_graphite_ProxyCache_DEFINED

#include "include/core/SkRefCnt.h"
#include "src/core/SkMessageBus.h"
#include "src/core/SkTHash.h"
#include "src/gpu/GpuTypesPriv.h"
#include "src/gpu/ResourceKey.h"

#include <optional>

class SkBitmap;
class SkIDChangeListener;

namespace skgpu {
    enum class Mipmapped : bool;
    class UniqueKey;
}

namespace skgpu::graphite {

class Image;
class Recorder;
class TextureProxy;

// This class encapsulates the _internal_ Recorder-local caching of utility proxies.
// For simplicity it does not support generating mipmapped cached proxies. Internal utility data
// does not typically require mipmapping, and unlike Ganesh, the internal proxy cache is not used
// for uploaded client-provided bitmaps (which may require generating mipmaps).
class ProxyCache {
public:
    ProxyCache(uint32_t recorderID);
    ~ProxyCache();

    sk_sp<TextureProxy> findOrCreateCachedProxy(Recorder*,
                                                const SkBitmap&,
                                                std::string_view label);

    // Find or create a cached TextureProxy that's associated with an externally managed UniqueKey.
    // If there is not a cached proxy available, the bitmap generator function will be called with
    // the provided context argument. The successfully generated bitmap is then uploaded to a
    // a new texture proxy on the Recorder and cached. If the bitmap generation fails, null is
    // returned.
    //
    // The texture proxy's label defaults to the tag of the unique key if not otherwise provided.
    using GeneratorContext = const void*;
    using BitmapGeneratorFn = SkBitmap (*) (GeneratorContext);
    sk_sp<TextureProxy> findOrCreateCachedProxy(Recorder* recorder,
                                                const UniqueKey& key,
                                                GeneratorContext context,
                                                BitmapGeneratorFn fn,
                                                std::string_view label = {});

    // As above but returns a GPU image instead of a CPU bitmap for the proxy's content.
    using GPUGeneratorFn = sk_sp<Image> (*) (Recorder*, GeneratorContext);
    sk_sp<TextureProxy> findOrCreateCachedProxy(Recorder* recorder,
                                                const UniqueKey& key,
                                                GeneratorContext context,
                                                GPUGeneratorFn fn,
                                                std::string_view label = {});

    void purgeAll();

#if defined(GPU_TEST_UTILS)
    int numCached() const;
    sk_sp<TextureProxy> find(const SkBitmap&);
    void forceProcessInvalidKeyMsgs();
    void forceFreeUniquelyHeld();
    void forcePurgeProxiesNotUsedSince(skgpu::StdSteadyClock::time_point purgeTime);
#endif

private:
    friend class ResourceCache; // for freeUniquelyHeld

    void processInvalidKeyMsgs();
    void freeUniquelyHeld();
    void purgeProxiesNotUsedSince(
            const skgpu::StdSteadyClock::time_point* purgeTime,
            std::optional<StdSteadyClock::time_point> quitPurgingTime = std::nullopt);
    void removeEntriesAndListeners(
        SkSpan<const UniqueKey> toRemove,
        std::optional<StdSteadyClock::time_point> quitPurgingTime = std::nullopt);

    struct UniqueKeyHash {
        uint32_t operator()(const UniqueKey& key) const;
    };
    struct CacheEntry {
        sk_sp<TextureProxy> fProxy;
        sk_sp<SkIDChangeListener> fListener; // null if source bitmap won't change
    };

    template <typename CreateEntryFn> // = CacheEntry (*) (std::string_view)
    sk_sp<TextureProxy> findOrCreateCacheEntry(const UniqueKey& key,
                                               std::string_view label,
                                               CreateEntryFn);

    skia_private::THashMap<UniqueKey, CacheEntry, UniqueKeyHash> fCache;
    SkMessageBus<UniqueKeyInvalidatedMsg_Graphite, uint32_t>::Inbox fInvalidUniqueKeyInbox;
};

} // namespace skgpu::graphite

#endif // skgpu_graphite_ProxyCache_DEFINED
