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

#ifndef GrProxyProvider_DEFINED
#define GrProxyProvider_DEFINED

#include "include/gpu/GrTypes.h"
#include "src/core/SkTDynamicHash.h"
#include "src/gpu/ResourceKey.h"
#include "src/gpu/ganesh/GrTextureProxy.h"

class GrBackendRenderTarget;
class GrContextThreadSafeProxy;
class GrImageContext;
class GrSurfaceProxyView;
class SkBitmap;
class SkImage;
enum class SkTextureCompressionType;
struct GrVkDrawableInfo;

/*
 * A factory for creating GrSurfaceProxy-derived objects.
 */
class GrProxyProvider {
public:
    using UseAllocator = GrSurfaceProxy::UseAllocator;

    GrProxyProvider(GrImageContext*);

    ~GrProxyProvider();

    /*
     * Assigns a unique key to a proxy. The proxy will be findable via this key using
     * findProxyByUniqueKey(). It is an error if an existing proxy already has a key.
     */
    bool assignUniqueKeyToProxy(const skgpu::UniqueKey&, GrTextureProxy*);

    /*
     * Sets the unique key of the provided proxy to the unique key of the surface. The surface must
     * have a valid unique key.
     */
    void adoptUniqueKeyFromSurface(GrTextureProxy* proxy, const GrSurface*);

    /*
     * Removes a unique key from a proxy. If the proxy has already been instantiated, it will
     * also remove the unique key from the target GrSurface.
     */
    void removeUniqueKeyFromProxy(GrTextureProxy*);

    /*
     * Finds a proxy by unique key.
     */
    sk_sp<GrTextureProxy> findProxyByUniqueKey(const skgpu::UniqueKey&);

    /*
     * Finds a proxy by unique key or creates a new one that wraps a resource matching the unique
     * key.
     */
    sk_sp<GrTextureProxy> findOrCreateProxyByUniqueKey(const skgpu::UniqueKey&,
                                                       UseAllocator = UseAllocator::kYes);

    /**
     * A helper that uses findOrCreateProxyByUniqueKey() to find a proxy and, if found, creates
     * a view for the found proxy using the passed in origin and color type. It is assumed that if
     * the proxy is renderable then it was created via a fallback code path so the fallback
     * color type will be used to create the view.
     */
    GrSurfaceProxyView findCachedProxyWithColorTypeFallback(const skgpu::UniqueKey&,
                                                            GrSurfaceOrigin,
                                                            GrColorType,
                                                            int sampleCnt);

    /*
     * Creates a new texture proxy for the bitmap, optionally with mip levels generated by the cpu.
     * The bitmap is uploaded to the texture proxy assuming a kTopLeft_GrSurfaceOrigin.
     */
    sk_sp<GrTextureProxy> createProxyFromBitmap(const SkBitmap&,
                                                GrMipmapped,
                                                SkBackingFit,
                                                skgpu::Budgeted);

    /*
     * Create a GrSurfaceProxy without any data.
     */
    sk_sp<GrTextureProxy> createProxy(const GrBackendFormat&,
                                      SkISize dimensions,
                                      GrRenderable,
                                      int renderTargetSampleCnt,
                                      GrMipmapped,
                                      SkBackingFit,
                                      skgpu::Budgeted,
                                      GrProtected,
                                      std::string_view label,
                                      GrInternalSurfaceFlags = GrInternalSurfaceFlags::kNone,
                                      UseAllocator useAllocator = UseAllocator::kYes);

    /*
     * Create a texture proxy from compressed texture data.
     */
    sk_sp<GrTextureProxy> createCompressedTextureProxy(SkISize dimensions,
                                                       skgpu::Budgeted,
                                                       GrMipmapped,
                                                       GrProtected,
                                                       SkTextureCompressionType,
                                                       sk_sp<SkData> data);

    // These match the definitions in SkImage & GrTexture.h, for whence they came
    typedef void* ReleaseContext;
    typedef void (*ReleaseProc)(ReleaseContext);

    /*
     * Create a texture proxy that wraps a (non-renderable) backend texture. GrIOType must be
     * kRead or kRW.
     */
    sk_sp<GrTextureProxy> wrapBackendTexture(const GrBackendTexture&,
                                             GrWrapOwnership,
                                             GrWrapCacheable,
                                             GrIOType,
                                             sk_sp<skgpu::RefCntedCallback> = nullptr);

    sk_sp<GrTextureProxy> wrapCompressedBackendTexture(const GrBackendTexture&,
                                                       GrWrapOwnership,
                                                       GrWrapCacheable,
                                                       sk_sp<skgpu::RefCntedCallback>);

    /*
     * Create a texture proxy that wraps a backend texture and is both texture-able and renderable
     */
    sk_sp<GrTextureProxy> wrapRenderableBackendTexture(const GrBackendTexture&,
                                                       int sampleCnt,
                                                       GrWrapOwnership,
                                                       GrWrapCacheable,
                                                       sk_sp<skgpu::RefCntedCallback> releaseHelper);

    /*
     * Create a render target proxy that wraps a backend render target
     */
    sk_sp<GrSurfaceProxy> wrapBackendRenderTarget(const GrBackendRenderTarget&,
                                                  sk_sp<skgpu::RefCntedCallback> releaseHelper);

    sk_sp<GrRenderTargetProxy> wrapVulkanSecondaryCBAsRenderTarget(const SkImageInfo&,
                                                                   const GrVkDrawableInfo&);

    using LazyInstantiationKeyMode = GrSurfaceProxy::LazyInstantiationKeyMode;
    using LazySurfaceDesc = GrSurfaceProxy::LazySurfaceDesc;
    using LazyCallbackResult = GrSurfaceProxy::LazyCallbackResult;
    using LazyInstantiateCallback = GrSurfaceProxy::LazyInstantiateCallback;

    struct TextureInfo {
        GrMipmapped fMipmapped;
        GrTextureType fTextureType;
    };

    /**
     * Similar to createLazyProxy below, except narrowed to the use case of shared promise images
     * i.e. static so it doesn't have access to mutable state. Used by MakePromiseImageLazyProxy().
     */
    static sk_sp<GrTextureProxy> CreatePromiseProxy(GrContextThreadSafeProxy*,
                                                    LazyInstantiateCallback&&,
                                                    const GrBackendFormat&,
                                                    SkISize dimensions,
                                                    GrMipmapped);

    /**
     * Creates a texture proxy that will be instantiated by a user-supplied callback during flush.
     * The width and height must either both be greater than 0 or both less than or equal to zero. A
     * non-positive value is a signal that the width height are currently unknown. The texture will
     * not be renderable.
     *
     * When called, the callback must be able to cleanup any resources that it captured at creation.
     * It also must support being passed in a null GrResourceProvider. When this happens, the
     * callback should cleanup any resources it captured and return an empty sk_sp<GrTextureProxy>.
     */
    sk_sp<GrTextureProxy> createLazyProxy(LazyInstantiateCallback&&,
                                          const GrBackendFormat&,
                                          SkISize dimensions,
                                          GrMipmapped,
                                          GrMipmapStatus,
                                          GrInternalSurfaceFlags,
                                          SkBackingFit,
                                          skgpu::Budgeted,
                                          GrProtected,
                                          UseAllocator,
                                          std::string_view label);

    /** A null TextureInfo indicates a non-textureable render target. */
    sk_sp<GrRenderTargetProxy> createLazyRenderTargetProxy(LazyInstantiateCallback&&,
                                                           const GrBackendFormat&,
                                                           SkISize dimensions,
                                                           int renderTargetSampleCnt,
                                                           GrInternalSurfaceFlags,
                                                           const TextureInfo*,
                                                           GrMipmapStatus,
                                                           SkBackingFit,
                                                           skgpu::Budgeted,
                                                           GrProtected,
                                                           bool wrapsVkSecondaryCB,
                                                           UseAllocator useAllocator);

    /**
     * Fully lazy proxies have unspecified width and height. Methods that rely on those values
     * (e.g., width, height, getBoundsRect) should be avoided.
     */
    static sk_sp<GrTextureProxy> MakeFullyLazyProxy(LazyInstantiateCallback&&,
                                                    const GrBackendFormat&,
                                                    GrRenderable,
                                                    int renderTargetSampleCnt,
                                                    GrProtected,
                                                    const GrCaps&,
                                                    UseAllocator);

    enum class InvalidateGPUResource : bool { kNo = false, kYes = true };

    /*
     * This method ensures that, if a proxy w/ the supplied unique key exists, it is removed from
     * the proxy provider's map and its unique key is removed. If 'invalidateSurface' is true, it
     * will independently ensure that the unique key is removed from any GrGpuResources that may
     * have it.
     *
     * If 'proxy' is provided (as an optimization to stop re-looking it up), its unique key must be
     * valid and match the provided unique key.
     *
     * This method is called if either the proxy attached to the unique key is being deleted
     * (in which case we don't want it cluttering up the hash table) or the client has indicated
     * that it will never refer to the unique key again.
     */
    void processInvalidUniqueKey(const skgpu::UniqueKey&, GrTextureProxy*, InvalidateGPUResource);

    GrDDLProvider isDDLProvider() const;

    // TODO: remove these entry points - it is a bit sloppy to be getting context info from here
    uint32_t contextID() const;
    const GrCaps* caps() const;
    sk_sp<const GrCaps> refCaps() const;

    int numUniqueKeyProxies_TestOnly() const;

    // This is called on a DDL's proxyprovider when the DDL is finished. The uniquely keyed
    // proxies need to keep their unique key but cannot hold on to the proxy provider unique
    // pointer.
    void orphanAllUniqueKeys();
    // This is only used by GrContext::releaseResourcesAndAbandonContext()
    void removeAllUniqueKeys();

    /**
     * Does the proxy provider have access to a GrDirectContext? If so, proxies will be
     * instantiated immediately.
     */
    bool renderingDirectly() const;

#if GR_TEST_UTILS
    /**
     * Create a texture proxy that is backed by an instantiated GrSurface.
     */
    sk_sp<GrTextureProxy> testingOnly_createInstantiatedProxy(SkISize dimensions,
                                                              const GrBackendFormat& format,
                                                              GrRenderable renderable,
                                                              int renderTargetSampleCnt,
                                                              SkBackingFit fit,
                                                              skgpu::Budgeted budgeted,
                                                              GrProtected isProtected);

    /** Version of above that picks the default format for the color type. */
    sk_sp<GrTextureProxy> testingOnly_createInstantiatedProxy(SkISize dimensions,
                                                              GrColorType colorType,
                                                              GrRenderable renderable,
                                                              int renderTargetSampleCnt,
                                                              SkBackingFit fit,
                                                              skgpu::Budgeted budgeted,
                                                              GrProtected isProtected);

    sk_sp<GrTextureProxy> testingOnly_createWrapped(sk_sp<GrTexture>);
#endif

private:
    friend class GrAHardwareBufferImageGenerator; // for createWrapped
    friend class GrResourceProvider; // for createWrapped

    // processInvalidUniqueKey() with control over removing hash table entries,
    // which is not safe while iterating with foreach().
    enum class RemoveTableEntry { kNo, kYes };
    void processInvalidUniqueKeyImpl(const skgpu::UniqueKey&, GrTextureProxy*,
                                     InvalidateGPUResource, RemoveTableEntry);

    bool isAbandoned() const;

    /*
     * Create an un-mipmapped texture proxy for the bitmap.
     */
    sk_sp<GrTextureProxy> createNonMippedProxyFromBitmap(const SkBitmap&,
                                                         SkBackingFit,
                                                         skgpu::Budgeted);
    /*
     * Create an mipmapped texture proxy for the bitmap.
     */
    sk_sp<GrTextureProxy> createMippedProxyFromBitmap(const SkBitmap&, skgpu::Budgeted);

    sk_sp<GrTextureProxy> createWrapped(sk_sp<GrTexture> tex, UseAllocator useAllocator);

    struct UniquelyKeyedProxyHashTraits {
        static const skgpu::UniqueKey& GetKey(const GrTextureProxy& p) { return p.getUniqueKey(); }

        static uint32_t Hash(const skgpu::UniqueKey& key) { return key.hash(); }
    };
    typedef SkTDynamicHash<GrTextureProxy, skgpu::UniqueKey, UniquelyKeyedProxyHashTraits> UniquelyKeyedProxyHash;

    // This holds the texture proxies that have unique keys. The resourceCache does not get a ref
    // on these proxies but they must send a message to the resourceCache when they are deleted.
    UniquelyKeyedProxyHash fUniquelyKeyedProxies;

    GrImageContext*        fImageContext;
};

#endif
