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

#ifndef GrVkImage_DEFINED
#define GrVkImage_DEFINED

#include "include/core/SkTypes.h"
#include "include/gpu/GrBackendSurface.h"
#include "include/gpu/vk/GrVkTypes.h"
#include "include/private/GrTypesPriv.h"
#include "include/private/GrVkTypesPriv.h"
#include "src/gpu/GrAttachment.h"
#include "src/gpu/GrBackendSurfaceMutableStateImpl.h"
#include "src/gpu/GrManagedResource.h"
#include "src/gpu/GrRefCnt.h"
#include "src/gpu/GrTexture.h"
#include "src/gpu/vk/GrVkDescriptorSet.h"

#include <cinttypes>

class GrVkGpu;
class GrVkImageView;

class GrVkImage : public GrAttachment {
private:
    class Resource;

public:
    static sk_sp<GrVkImage> MakeStencil(GrVkGpu* gpu,
                                        SkISize dimensions,
                                        int sampleCnt,
                                        VkFormat format);

    static sk_sp<GrVkImage> MakeMSAA(GrVkGpu* gpu,
                                     SkISize dimensions,
                                     int numSamples,
                                     VkFormat format,
                                     GrProtected isProtected);

    static sk_sp<GrVkImage> MakeTexture(GrVkGpu* gpu,
                                        SkISize dimensions,
                                        VkFormat format,
                                        uint32_t mipLevels,
                                        GrRenderable renderable,
                                        int numSamples,
                                        SkBudgeted budgeted,
                                        GrProtected isProtected);

    static sk_sp<GrVkImage> MakeWrapped(GrVkGpu* gpu,
                                        SkISize dimensions,
                                        const GrVkImageInfo&,
                                        sk_sp<GrBackendSurfaceMutableStateImpl>,
                                        UsageFlags attachmentUsages,
                                        GrWrapOwnership,
                                        GrWrapCacheable,
                                        bool forSecondaryCB = false);

    ~GrVkImage() override;

    VkImage image() const {
        // Should only be called when we have a real fResource object, i.e. never when being used as
        // a RT in an external secondary command buffer.
        SkASSERT(fResource);
        return fInfo.fImage;
    }
    const GrVkAlloc& alloc() const {
        // Should only be called when we have a real fResource object, i.e. never when being used as
        // a RT in an external secondary command buffer.
        SkASSERT(fResource);
        return fInfo.fAlloc;
    }
    const GrVkImageInfo& vkImageInfo() const { return fInfo; }
    VkFormat imageFormat() const { return fInfo.fFormat; }
    GrBackendFormat backendFormat() const override {
        if (fResource && this->ycbcrConversionInfo().isValid()) {
            SkASSERT(this->imageFormat() == this->ycbcrConversionInfo().fFormat);
            return GrBackendFormat::MakeVk(this->ycbcrConversionInfo());
        }
        SkASSERT(this->imageFormat() != VK_FORMAT_UNDEFINED);
        return GrBackendFormat::MakeVk(this->imageFormat());
    }
    uint32_t mipLevels() const { return fInfo.fLevelCount; }
    const GrVkYcbcrConversionInfo& ycbcrConversionInfo() const {
        // Should only be called when we have a real fResource object, i.e. never when being used as
        // a RT in an external secondary command buffer.
        SkASSERT(fResource);
        return fInfo.fYcbcrConversionInfo;
    }
    VkImageUsageFlags vkUsageFlags() { return fInfo.fImageUsageFlags; }
    bool supportsInputAttachmentUsage() const {
        return fInfo.fImageUsageFlags & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
    }

    const GrVkImageView* framebufferView() const { return fFramebufferView.get(); }
    const GrVkImageView* textureView() const { return fTextureView.get(); }

    // So that we don't need to rewrite descriptor sets each time, we keep cached input descriptor
    // sets on the attachment and simply reuse those descriptor sets for this attachment only. These
    // calls will fail if the attachment does not support being used as an input attachment. These
    // calls do not ref the GrVkDescriptorSet so they called will need to manually ref them if they
    // need to be kept alive.
    gr_rp<const GrVkDescriptorSet> inputDescSetForBlending(GrVkGpu* gpu);
    // Input descripotr set used when needing to read a resolve attachment to load data into a
    // discardable msaa attachment.
    gr_rp<const GrVkDescriptorSet> inputDescSetForMSAALoad(GrVkGpu* gpu);

    const Resource* resource() const {
        SkASSERT(fResource);
        return fResource;
    }
    bool isLinearTiled() const {
        // Should only be called when we have a real fResource object, i.e. never when being used as
        // a RT in an external secondary command buffer.
        SkASSERT(fResource);
        return SkToBool(VK_IMAGE_TILING_LINEAR == fInfo.fImageTiling);
    }
    bool isBorrowed() const { return fIsBorrowed; }

    sk_sp<GrBackendSurfaceMutableStateImpl> getMutableState() const { return fMutableState; }

    VkImageLayout currentLayout() const { return fMutableState->getImageLayout(); }

    void setImageLayoutAndQueueIndex(const GrVkGpu* gpu,
                                     VkImageLayout newLayout,
                                     VkAccessFlags dstAccessMask,
                                     VkPipelineStageFlags dstStageMask,
                                     bool byRegion,
                                     uint32_t newQueueFamilyIndex);

    void setImageLayout(const GrVkGpu* gpu,
                        VkImageLayout newLayout,
                        VkAccessFlags dstAccessMask,
                        VkPipelineStageFlags dstStageMask,
                        bool byRegion) {
        this->setImageLayoutAndQueueIndex(gpu, newLayout, dstAccessMask, dstStageMask, byRegion,
                                          VK_QUEUE_FAMILY_IGNORED);
    }

    uint32_t currentQueueFamilyIndex() const { return fMutableState->getQueueFamilyIndex(); }

    void setQueueFamilyIndex(uint32_t queueFamilyIndex) {
        fMutableState->setQueueFamilyIndex(queueFamilyIndex);
    }

    // Returns the image to its original queue family and changes the layout to present if the queue
    // family is not external or foreign.
    void prepareForPresent(GrVkGpu* gpu);

    // Returns the image to its original queue family
    void prepareForExternal(GrVkGpu* gpu);

    // This simply updates our tracking of the image layout and does not actually do any gpu work.
    // This is only used for mip map generation where we are manually changing the layouts as we
    // blit each layer, and then at the end need to update our tracking.
    void updateImageLayout(VkImageLayout newLayout) {
        // Should only be called when we have a real fResource object, i.e. never when being used as
        // a RT in an external secondary command buffer.
        SkASSERT(fResource);
        fMutableState->setImageLayout(newLayout);
    }

    struct ImageDesc {
        VkImageType         fImageType;
        VkFormat            fFormat;
        uint32_t            fWidth;
        uint32_t            fHeight;
        uint32_t            fLevels;
        uint32_t            fSamples;
        VkImageTiling       fImageTiling;
        VkImageUsageFlags   fUsageFlags;
        VkFlags             fMemProps;
        GrProtected         fIsProtected;

        ImageDesc()
                : fImageType(VK_IMAGE_TYPE_2D)
                , fFormat(VK_FORMAT_UNDEFINED)
                , fWidth(0)
                , fHeight(0)
                , fLevels(1)
                , fSamples(1)
                , fImageTiling(VK_IMAGE_TILING_OPTIMAL)
                , fUsageFlags(0)
                , fMemProps(VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)
                , fIsProtected(GrProtected::kNo) {}
    };

    static bool InitImageInfo(GrVkGpu* gpu, const ImageDesc& imageDesc, GrVkImageInfo*);
    // Destroys the internal VkImage and VkDeviceMemory in the GrVkImageInfo
    static void DestroyImageInfo(const GrVkGpu* gpu, GrVkImageInfo*);

    // These match the definitions in SkImage, for whence they came
    typedef void* ReleaseCtx;
    typedef void (*ReleaseProc)(ReleaseCtx);

    void setResourceRelease(sk_sp<GrRefCntedCallback> releaseHelper);

    // Helpers to use for setting the layout of the VkImage
    static VkPipelineStageFlags LayoutToPipelineSrcStageFlags(const VkImageLayout layout);
    static VkAccessFlags LayoutToSrcAccessMask(const VkImageLayout layout);

#if GR_TEST_UTILS
    void setCurrentQueueFamilyToGraphicsQueue(GrVkGpu* gpu);
#endif

private:
    static sk_sp<GrVkImage> Make(GrVkGpu* gpu,
                                 SkISize dimensions,
                                 UsageFlags attachmentUsages,
                                 int sampleCnt,
                                 VkFormat format,
                                 uint32_t mipLevels,
                                 VkImageUsageFlags vkUsageFlags,
                                 GrProtected isProtected,
                                 SkBudgeted);

    GrVkImage(GrVkGpu* gpu,
              SkISize dimensions,
              UsageFlags supportedUsages,
              const GrVkImageInfo&,
              sk_sp<GrBackendSurfaceMutableStateImpl> mutableState,
              sk_sp<const GrVkImageView> framebufferView,
              sk_sp<const GrVkImageView> textureView,
              SkBudgeted);

    GrVkImage(GrVkGpu* gpu,
              SkISize dimensions,
              UsageFlags supportedUsages,
              const GrVkImageInfo&,
              sk_sp<GrBackendSurfaceMutableStateImpl> mutableState,
              sk_sp<const GrVkImageView> framebufferView,
              sk_sp<const GrVkImageView> textureView,
              GrBackendObjectOwnership,
              GrWrapCacheable,
              bool forSecondaryCB);

    void init(GrVkGpu*, bool forSecondaryCB);

    void onRelease() override;
    void onAbandon() override;

    void releaseImage();
    bool hasResource() const { return fResource; }

    GrVkGpu* getVkGpu() const;

    GrVkImageInfo                           fInfo;
    uint32_t                                fInitialQueueFamily;
    sk_sp<GrBackendSurfaceMutableStateImpl> fMutableState;

    sk_sp<const GrVkImageView>              fFramebufferView;
    sk_sp<const GrVkImageView>              fTextureView;

    bool fIsBorrowed;

    // Descriptor set used when this is used as an input attachment for reading the dst in blending.
    gr_rp<const GrVkDescriptorSet> fCachedBlendingInputDescSet;
    // Descriptor set used when this is used as an input attachment for loading an msaa attachment.
    gr_rp<const GrVkDescriptorSet> fCachedMSAALoadInputDescSet;

    class Resource : public GrTextureResource {
    public:
        explicit Resource(const GrVkGpu* gpu)
                : fGpu(gpu)
                , fImage(VK_NULL_HANDLE) {
            fAlloc.fMemory = VK_NULL_HANDLE;
            fAlloc.fOffset = 0;
        }

        Resource(const GrVkGpu* gpu, VkImage image, const GrVkAlloc& alloc, VkImageTiling tiling)
            : fGpu(gpu)
            , fImage(image)
            , fAlloc(alloc) {}

        ~Resource() override {}

#ifdef SK_TRACE_MANAGED_RESOURCES
        void dumpInfo() const override {
            SkDebugf("GrVkImage: %" PRIdPTR " (%d refs)\n", (intptr_t)fImage, this->getRefCnt());
        }
#endif

#ifdef SK_DEBUG
        const GrManagedResource* asVkImageResource() const override { return this; }
#endif

    private:
        void freeGPUData() const override;

        const GrVkGpu* fGpu;
        VkImage        fImage;
        GrVkAlloc      fAlloc;

        using INHERITED = GrTextureResource;
    };

    // for wrapped textures
    class BorrowedResource : public Resource {
    public:
        BorrowedResource(const GrVkGpu* gpu, VkImage image, const GrVkAlloc& alloc,
                         VkImageTiling tiling)
            : Resource(gpu, image, alloc, tiling) {
        }
    private:
        void freeGPUData() const override;
    };

    Resource* fResource;

    friend class GrVkRenderTarget;
};

#endif
