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

#include "src/gpu/ganesh/vk/GrVkRenderTarget.h"

#include "include/gpu/GrBackendSurface.h"
#include "include/gpu/GrDirectContext.h"
#include "src/gpu/MutableTextureStateRef.h"
#include "src/gpu/ganesh/GrDirectContextPriv.h"
#include "src/gpu/ganesh/GrResourceProvider.h"
#include "src/gpu/ganesh/vk/GrVkCommandBuffer.h"
#include "src/gpu/ganesh/vk/GrVkDescriptorSet.h"
#include "src/gpu/ganesh/vk/GrVkFramebuffer.h"
#include "src/gpu/ganesh/vk/GrVkGpu.h"
#include "src/gpu/ganesh/vk/GrVkImageView.h"
#include "src/gpu/ganesh/vk/GrVkResourceProvider.h"
#include "src/gpu/ganesh/vk/GrVkUtil.h"

#include "include/gpu/vk/GrVkTypes.h"

#define VK_CALL(GPU, X) GR_VK_CALL(GPU->vkInterface(), X)

static int renderpass_features_to_index(bool hasResolve, bool hasStencil,
                                        GrVkRenderPass::SelfDependencyFlags selfDepFlags,
                                        GrVkRenderPass::LoadFromResolve loadFromReslove) {
    int index = 0;
    if (hasResolve) {
        index += 1;
    }
    if (hasStencil) {
        index += 2;
    }
    if (selfDepFlags & GrVkRenderPass::SelfDependencyFlags::kForInputAttachment) {
        index += 4;
    }
    if (selfDepFlags & GrVkRenderPass::SelfDependencyFlags::kForNonCoherentAdvBlend) {
        index += 8;
    }
    if (loadFromReslove == GrVkRenderPass::LoadFromResolve::kLoad) {
        index += 16;
    }
    return index;
}

// We're virtually derived from GrSurface (via GrRenderTarget) so its
// constructor must be explicitly called.
GrVkRenderTarget::GrVkRenderTarget(GrVkGpu* gpu,
                                   SkISize dimensions,
                                   sk_sp<GrVkImage> colorAttachment,
                                   sk_sp<GrVkImage> resolveAttachment,
                                   CreateType createType,
                                   std::string_view label)
        : GrSurface(gpu,
                    dimensions,
                    colorAttachment->isProtected() ? GrProtected::kYes : GrProtected::kNo,
                    label)
        // for the moment we only support 1:1 color to stencil
        , GrRenderTarget(gpu,
                         dimensions,
                         colorAttachment->numSamples(),
                         colorAttachment->isProtected() ? GrProtected::kYes : GrProtected::kNo,
                         label)
        , fColorAttachment(std::move(colorAttachment))
        , fResolveAttachment(std::move(resolveAttachment))
        , fCachedFramebuffers() {
    SkASSERT(fColorAttachment);

    if (fColorAttachment->numSamples() == 1 && fColorAttachment->supportsInputAttachmentUsage()) {
        SkASSERT(!fResolveAttachment);
        // When we have a single sampled color attachment, we set both the color and resolve
        // to the same attachment. This way if we use DMAA on this render target we will resolve
        // to the single target attachment.
        fResolveAttachment = fColorAttachment;
    }

    SkASSERT(!fResolveAttachment ||
             (fResolveAttachment->isProtected() == fColorAttachment->isProtected()));
    SkASSERT(SkToBool(fColorAttachment->vkUsageFlags() & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT));
    this->setFlags();
    if (createType == CreateType::kDirectlyWrapped) {
        this->registerWithCacheWrapped(GrWrapCacheable::kNo);
    }
}

GrVkRenderTarget::GrVkRenderTarget(GrVkGpu* gpu,
                                   SkISize dimensions,
                                   sk_sp<GrVkFramebuffer> externalFramebuffer,
                                   std::string_view label)
        : GrSurface(gpu,
                    dimensions,
                    externalFramebuffer->colorAttachment()->isProtected() ? GrProtected::kYes
                                                                          : GrProtected::kNo,
                    label)
        , GrRenderTarget(gpu,
                         dimensions,
                         1,
                         externalFramebuffer->colorAttachment()->isProtected() ? GrProtected::kYes
                                                                               : GrProtected::kNo,
                         label)
        , fCachedFramebuffers()
        , fExternalFramebuffer(externalFramebuffer) {
    SkASSERT(fExternalFramebuffer);
    SkASSERT(!fColorAttachment);
    SkDEBUGCODE(auto colorAttachment = fExternalFramebuffer->colorAttachment());
    SkASSERT(colorAttachment);
    SkASSERT(colorAttachment->numSamples() == 1);
    SkASSERT(SkToBool(colorAttachment->vkUsageFlags() & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT));
    SkASSERT(!SkToBool(colorAttachment->vkUsageFlags() & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT));
    this->setFlags();
    this->registerWithCacheWrapped(GrWrapCacheable::kNo);
}

void GrVkRenderTarget::setFlags() {
    if (this->wrapsSecondaryCommandBuffer()) {
        return;
    }
    GrVkImage* nonMSAAAttachment = this->nonMSAAAttachment();
    if (nonMSAAAttachment && nonMSAAAttachment->supportsInputAttachmentUsage()) {
        this->setVkRTSupportsInputAttachment();
    }
}

sk_sp<GrVkRenderTarget> GrVkRenderTarget::MakeWrappedRenderTarget(
        GrVkGpu* gpu,
        SkISize dimensions,
        int sampleCnt,
        const GrVkImageInfo& info,
        sk_sp<skgpu::MutableTextureStateRef> mutableState) {
    SkASSERT(VK_NULL_HANDLE != info.fImage);
    SkASSERT(1 == info.fLevelCount);
    SkASSERT(sampleCnt >= 1 && info.fSampleCount >= 1);

    int wrappedImageSampleCnt = static_cast<int>(info.fSampleCount);
    if (sampleCnt != wrappedImageSampleCnt && wrappedImageSampleCnt != 1) {
        return nullptr;
    }

    sk_sp<GrVkImage> wrappedAttachment =
            GrVkImage::MakeWrapped(gpu,
                                   dimensions,
                                   info,
                                   std::move(mutableState),
                                   GrAttachment::UsageFlags::kColorAttachment,
                                   kBorrow_GrWrapOwnership,
                                   GrWrapCacheable::kNo,
                                   /*label=*/"VkImage_WrappedAttachment");
    if (!wrappedAttachment) {
        return nullptr;
    }

    sk_sp<GrVkImage> colorAttachment;
    colorAttachment = std::move(wrappedAttachment);

    if (!colorAttachment) {
        return nullptr;
    }

    GrVkRenderTarget* vkRT = new GrVkRenderTarget(gpu,
                                                  dimensions,
                                                  std::move(colorAttachment),
                                                  nullptr,
                                                  CreateType::kDirectlyWrapped,
                                                  /*label=*/"Vk_MakeWrappedRenderTarget");
    return sk_sp<GrVkRenderTarget>(vkRT);
}

sk_sp<GrVkRenderTarget> GrVkRenderTarget::MakeSecondaryCBRenderTarget(
        GrVkGpu* gpu, SkISize dimensions, const GrVkDrawableInfo& vkInfo) {
    const GrVkRenderPass* rp = gpu->resourceProvider().findCompatibleExternalRenderPass(
            vkInfo.fCompatibleRenderPass, vkInfo.fColorAttachmentIndex);
    if (!rp) {
        return nullptr;
    }

    if (vkInfo.fSecondaryCommandBuffer == VK_NULL_HANDLE) {
        return nullptr;
    }

    // We only set the few properties of the GrVkImageInfo that we know like layout and format. The
    // others we keep at the default "null" values.
    GrVkImageInfo info;
    info.fImageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
    info.fFormat = vkInfo.fFormat;
    info.fImageUsageFlags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
                            VK_IMAGE_USAGE_TRANSFER_SRC_BIT;

    sk_sp<skgpu::MutableTextureStateRef> mutableState(new skgpu::MutableTextureStateRef(
            VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_QUEUE_FAMILY_IGNORED));

    sk_sp<GrVkImage> colorAttachment =
            GrVkImage::MakeWrapped(gpu,
                                   dimensions,
                                   info,
                                   std::move(mutableState),
                                   GrAttachment::UsageFlags::kColorAttachment,
                                   kBorrow_GrWrapOwnership,
                                   GrWrapCacheable::kNo,
                                   "VkImage_ColorAttachment",
                                   true);

    std::unique_ptr<GrVkSecondaryCommandBuffer> scb(
            GrVkSecondaryCommandBuffer::Create(vkInfo.fSecondaryCommandBuffer, rp));
    if (!scb) {
        return nullptr;
    }

    sk_sp<GrVkFramebuffer> framebuffer(new GrVkFramebuffer(
            gpu, std::move(colorAttachment), sk_sp<const GrVkRenderPass>(rp),
            std::move(scb)));

    GrVkRenderTarget* vkRT =
            new GrVkRenderTarget(gpu, dimensions, std::move(framebuffer),
                                 /*label=*/"Vk_MakeSecondaryCBRenderTarget");

    return sk_sp<GrVkRenderTarget>(vkRT);
}

GrBackendFormat GrVkRenderTarget::backendFormat() const {
    if (this->wrapsSecondaryCommandBuffer()) {
        return fExternalFramebuffer->colorAttachment()->backendFormat();
    }
    return fColorAttachment->backendFormat();
}

GrVkImage* GrVkRenderTarget::nonMSAAAttachment() const {
    if (fColorAttachment->numSamples() == 1) {
        return fColorAttachment.get();
    } else {
        return fResolveAttachment.get();
    }
}

GrVkImage* GrVkRenderTarget::dynamicMSAAAttachment() {
    if (fDynamicMSAAAttachment) {
        return fDynamicMSAAAttachment.get();
    }
    const GrVkImage* nonMSAAColorAttachment = this->colorAttachment();
    SkASSERT(nonMSAAColorAttachment->numSamples() == 1);

    GrVkGpu* gpu = this->getVkGpu();
    auto rp = gpu->getContext()->priv().resourceProvider();

    const GrBackendFormat& format = nonMSAAColorAttachment->backendFormat();

    GrMemoryless memoryless =
            gpu->vkCaps().supportsMemorylessAttachments() ? GrMemoryless::kYes : GrMemoryless::kNo;

    sk_sp<GrAttachment> msaaAttachment =
            rp->getDiscardableMSAAAttachment(nonMSAAColorAttachment->dimensions(),
                                             format,
                                             gpu->caps()->internalMultisampleCount(format),
                                             GrProtected(nonMSAAColorAttachment->isProtected()),
                                             memoryless);
    if (!msaaAttachment) {
        return nullptr;
    }
    fDynamicMSAAAttachment = sk_sp<GrVkImage>(static_cast<GrVkImage*>(msaaAttachment.release()));
    return fDynamicMSAAAttachment.get();
}

GrVkImage* GrVkRenderTarget::msaaAttachment() {
    return this->colorAttachment()->numSamples() == 1 ? this->dynamicMSAAAttachment()
                                                      : this->colorAttachment();
}

bool GrVkRenderTarget::canAttemptStencilAttachment(bool useMSAASurface) const {
    SkASSERT(!useMSAASurface || this->numSamples() > 1 ||
             this->getVkGpu()->vkCaps().supportsDiscardableMSAAForDMSAA());
    if (!useMSAASurface && this->numSamples() > 1) {
        return false;
    }
    bool validMSAA = true;
    if (useMSAASurface) {
        validMSAA = this->numSamples() > 1 ||
                    (this->getVkGpu()->vkCaps().supportsDiscardableMSAAForDMSAA() &&
                     this->colorAttachment()->supportsInputAttachmentUsage());
    }
    // We don't know the status of the stencil attachment for wrapped external secondary command
    // buffers so we just assume we don't have one.
    return validMSAA && !this->wrapsSecondaryCommandBuffer();
}

bool GrVkRenderTarget::completeStencilAttachment(GrAttachment* stencil, bool useMSAASurface) {
    SkASSERT(!this->wrapsSecondaryCommandBuffer());
    SkASSERT(!useMSAASurface ||
             this->numSamples() > 1 ||
             this->getVkGpu()->vkCaps().supportsDiscardableMSAAForDMSAA());
    return true;
}

sk_sp<GrVkFramebuffer> GrVkRenderTarget::externalFramebuffer() const {
    return fExternalFramebuffer;
}

GrVkResourceProvider::CompatibleRPHandle GrVkRenderTarget::compatibleRenderPassHandle(
        bool withResolve,
        bool withStencil,
        SelfDependencyFlags selfDepFlags,
        LoadFromResolve loadFromResolve) {
    SkASSERT(!this->wrapsSecondaryCommandBuffer());

    const GrVkFramebuffer* fb =
            this->getFramebuffer(withResolve, withStencil, selfDepFlags, loadFromResolve);
    if (!fb) {
        return {};
    }

    return fb->compatibleRenderPassHandle();
}

const GrVkRenderPass* GrVkRenderTarget::getSimpleRenderPass(bool withResolve,
                                                            bool withStencil,
                                                            SelfDependencyFlags selfDepFlags,
                                                            LoadFromResolve loadFromResolve) {
    if (this->wrapsSecondaryCommandBuffer()) {
         return fExternalFramebuffer->externalRenderPass();
    }

    const GrVkFramebuffer* fb =
            this->getFramebuffer(withResolve, withStencil, selfDepFlags, loadFromResolve);
    if (!fb) {
        return nullptr;
    }

    return fb->compatibleRenderPass();
}

std::pair<const GrVkRenderPass*, GrVkResourceProvider::CompatibleRPHandle>
GrVkRenderTarget::createSimpleRenderPass(bool withResolve,
                                         bool withStencil,
                                         SelfDependencyFlags selfDepFlags,
                                         LoadFromResolve loadFromResolve) {
    SkASSERT(!this->wrapsSecondaryCommandBuffer());

    GrVkResourceProvider& rp = this->getVkGpu()->resourceProvider();

    GrVkResourceProvider::CompatibleRPHandle handle;
    const GrVkRenderPass* renderPass = rp.findCompatibleRenderPass(
            this, &handle, withResolve, withStencil, selfDepFlags,
            loadFromResolve);
    SkASSERT(!renderPass || handle.isValid());
    return {renderPass, handle};
}

const GrVkFramebuffer* GrVkRenderTarget::getFramebuffer(bool withResolve,
                                                        bool withStencil,
                                                        SelfDependencyFlags selfDepFlags,
                                                        LoadFromResolve loadFromResolve) {
    int cacheIndex =
            renderpass_features_to_index(withResolve, withStencil, selfDepFlags, loadFromResolve);
    SkASSERT(cacheIndex < GrVkRenderTarget::kNumCachedFramebuffers);
    if (auto fb = fCachedFramebuffers[cacheIndex]) {
        return fb.get();
    }

    this->createFramebuffer(withResolve, withStencil, selfDepFlags, loadFromResolve);
    return fCachedFramebuffers[cacheIndex].get();
}

void GrVkRenderTarget::createFramebuffer(bool withResolve,
                                         bool withStencil,
                                         SelfDependencyFlags selfDepFlags,
                                         LoadFromResolve loadFromResolve) {
    SkASSERT(!this->wrapsSecondaryCommandBuffer());
    GrVkGpu* gpu = this->getVkGpu();

    auto[renderPass, compatibleHandle] =
            this->createSimpleRenderPass(withResolve, withStencil, selfDepFlags, loadFromResolve);
    if (!renderPass) {
        return;
    }
    SkASSERT(compatibleHandle.isValid());

    int cacheIndex =
            renderpass_features_to_index(withResolve, withStencil, selfDepFlags, loadFromResolve);
    SkASSERT(cacheIndex < GrVkRenderTarget::kNumCachedFramebuffers);

    GrVkImage* resolve = withResolve ? this->resolveAttachment() : nullptr;
    GrVkImage* colorAttachment = withResolve ? this->msaaAttachment() : this->colorAttachment();

    // Stencil attachment view is stored in the base RT stencil attachment
    bool useMSAA = this->numSamples() > 1 || withResolve;
    GrVkImage* stencil =  withStencil ? static_cast<GrVkImage*>(this->getStencilAttachment(useMSAA))
                                      : nullptr;
    fCachedFramebuffers[cacheIndex] =
            GrVkFramebuffer::Make(gpu, this->dimensions(),
                                  sk_sp<const GrVkRenderPass>(renderPass),
                                  colorAttachment, resolve, stencil, compatibleHandle);
}

bool GrVkRenderTarget::getAttachmentsDescriptor(GrVkRenderPass::AttachmentsDescriptor* desc,
                                                GrVkRenderPass::AttachmentFlags* attachmentFlags,
                                                bool withResolve,
                                                bool withStencil) {
    SkASSERT(!this->wrapsSecondaryCommandBuffer());
    const GrVkImage* colorAttachment =
            withResolve ? this->msaaAttachment() : this->colorAttachment();
    if (!colorAttachment) {
        SkDebugf("WARNING: Invalid color attachment -- possibly dmsaa attachment creation failed?");
        return false;
    }

    desc->fColor.fFormat = colorAttachment->imageFormat();
    desc->fColor.fSamples = colorAttachment->numSamples();
    *attachmentFlags = GrVkRenderPass::kColor_AttachmentFlag;
    uint32_t attachmentCount = 1;

    if (withResolve) {
        desc->fResolve.fFormat = desc->fColor.fFormat;
        desc->fResolve.fSamples = 1;
        *attachmentFlags |= GrVkRenderPass::kResolve_AttachmentFlag;
        ++attachmentCount;
    }

    if (withStencil) {
        bool useMSAA = this->numSamples() > 1 || withResolve;
        const GrAttachment* stencil = this->getStencilAttachment(useMSAA);
        SkASSERT(stencil);
        const GrVkImage* vkStencil = static_cast<const GrVkImage*>(stencil);
        desc->fStencil.fFormat = vkStencil->imageFormat();
        desc->fStencil.fSamples = vkStencil->numSamples();
        SkASSERT(desc->fStencil.fSamples == desc->fColor.fSamples);
        *attachmentFlags |= GrVkRenderPass::kStencil_AttachmentFlag;
        ++attachmentCount;
    }
    desc->fAttachmentCount = attachmentCount;

    return true;
}

void GrVkRenderTarget::ReconstructAttachmentsDescriptor(const GrVkCaps& vkCaps,
                                                        const GrProgramInfo& programInfo,
                                                        GrVkRenderPass::AttachmentsDescriptor* desc,
                                                        GrVkRenderPass::AttachmentFlags* flags) {
    VkFormat format;
    SkAssertResult(programInfo.backendFormat().asVkFormat(&format));

    desc->fColor.fFormat = format;
    desc->fColor.fSamples = programInfo.numSamples();
    *flags = GrVkRenderPass::kColor_AttachmentFlag;
    uint32_t attachmentCount = 1;

    if (vkCaps.programInfoWillUseDiscardableMSAA(programInfo)) {
        desc->fResolve.fFormat = desc->fColor.fFormat;
        desc->fResolve.fSamples = 1;
        *flags |= GrVkRenderPass::kResolve_AttachmentFlag;
        ++attachmentCount;
    }

    SkASSERT(!programInfo.isStencilEnabled() || programInfo.needsStencil());
    if (programInfo.needsStencil()) {
        VkFormat stencilFormat = vkCaps.preferredStencilFormat();
        desc->fStencil.fFormat = stencilFormat;
        desc->fStencil.fSamples = programInfo.numSamples();
        SkASSERT(desc->fStencil.fSamples == desc->fColor.fSamples);
        *flags |= GrVkRenderPass::kStencil_AttachmentFlag;
        ++attachmentCount;
    }
    desc->fAttachmentCount = attachmentCount;
}

GrVkRenderTarget::~GrVkRenderTarget() {
    // either release or abandon should have been called by the owner of this object.
    SkASSERT(!fColorAttachment);
    SkASSERT(!fResolveAttachment);
    SkASSERT(!fDynamicMSAAAttachment);

    for (int i = 0; i < kNumCachedFramebuffers; ++i) {
        SkASSERT(!fCachedFramebuffers[i]);
    }

    SkASSERT(!fCachedInputDescriptorSet);
}

void GrVkRenderTarget::releaseInternalObjects() {
    fColorAttachment.reset();
    fResolveAttachment.reset();
    fDynamicMSAAAttachment.reset();

    for (int i = 0; i < kNumCachedFramebuffers; ++i) {
        if (fCachedFramebuffers[i]) {
            fCachedFramebuffers[i].reset();
        }
    }

    if (fCachedInputDescriptorSet) {
        fCachedInputDescriptorSet->recycle();
        fCachedInputDescriptorSet = nullptr;
    }

    fExternalFramebuffer.reset();
}

void GrVkRenderTarget::onRelease() {
    this->releaseInternalObjects();
    GrRenderTarget::onRelease();
}

void GrVkRenderTarget::onAbandon() {
    this->releaseInternalObjects();
    GrRenderTarget::onAbandon();
}

GrBackendRenderTarget GrVkRenderTarget::getBackendRenderTarget() const {
    SkASSERT(!this->wrapsSecondaryCommandBuffer());
    // This should only get called with a non-released GrVkRenderTargets.
    SkASSERT(!this->wasDestroyed());
    // If we have a resolve attachment that is what we return for the backend render target
    const GrVkImage* beAttachment = this->externalAttachment();
    return GrBackendRenderTarget(beAttachment->width(), beAttachment->height(),
                                 beAttachment->vkImageInfo(), beAttachment->getMutableState());
}

GrVkGpu* GrVkRenderTarget::getVkGpu() const {
    SkASSERT(!this->wasDestroyed());
    return static_cast<GrVkGpu*>(this->getGpu());
}
