/*
 * 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 "GrVkRenderTarget.h"

#include "GrRenderTargetPriv.h"
#include "GrVkCommandBuffer.h"
#include "GrVkFramebuffer.h"
#include "GrVkGpu.h"
#include "GrVkImageView.h"
#include "GrVkResourceProvider.h"
#include "GrVkUtil.h"

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

// We're virtually derived from GrSurface (via GrRenderTarget) so its
// constructor must be explicitly called.
GrVkRenderTarget::GrVkRenderTarget(GrVkGpu* gpu,
                                   const GrSurfaceDesc& desc,
                                   GrGpuResource::LifeCycle lifeCycle,
                                   const GrVkImage::Resource* imageResource,
                                   const GrVkImage::Resource* msaaResource,
                                   const GrVkImageView* colorAttachmentView,
                                   const GrVkImageView* resolveAttachmentView)
    : GrSurface(gpu, lifeCycle, desc)
    , GrVkImage(imageResource)
    // for the moment we only support 1:1 color to stencil
    , GrRenderTarget(gpu, lifeCycle, desc, kUnified_SampleConfig)
    , fFramebuffer(nullptr)
    , fColorAttachmentView(colorAttachmentView)
    , fMSAAImageResource(msaaResource)
    , fResolveAttachmentView(resolveAttachmentView)
    , fCachedSimpleRenderPass(nullptr) {
    SkASSERT(desc.fSampleCnt);
    // The plus 1 is to account for the resolve texture.
    fColorValuesPerPixel = desc.fSampleCnt + 1; // TODO: this still correct?
    this->createFramebuffer(gpu);
    this->registerWithCache();
    msaaResource->ref();
}

// We're virtually derived from GrSurface (via GrRenderTarget) so its
// constructor must be explicitly called.
GrVkRenderTarget::GrVkRenderTarget(GrVkGpu* gpu,
                                   const GrSurfaceDesc& desc,
                                   GrGpuResource::LifeCycle lifeCycle,
                                   const GrVkImage::Resource* imageResource,
                                   const GrVkImage::Resource* msaaResource,
                                   const GrVkImageView* colorAttachmentView,
                                   const GrVkImageView* resolveAttachmentView,
                                   Derived)
    : GrSurface(gpu, lifeCycle, desc)
    , GrVkImage(imageResource)
    // for the moment we only support 1:1 color to stencil
    , GrRenderTarget(gpu, lifeCycle, desc, kUnified_SampleConfig)
    , fFramebuffer(nullptr)
    , fColorAttachmentView(colorAttachmentView)
    , fMSAAImageResource(msaaResource)
    , fResolveAttachmentView(resolveAttachmentView)
    , fCachedSimpleRenderPass(nullptr) {
    SkASSERT(desc.fSampleCnt);
    // The plus 1 is to account for the resolve texture.
    fColorValuesPerPixel = desc.fSampleCnt + 1; // TODO: this still correct?
    this->createFramebuffer(gpu);
    msaaResource->ref();
}

// We're virtually derived from GrSurface (via GrRenderTarget) so its
// constructor must be explicitly called.
GrVkRenderTarget::GrVkRenderTarget(GrVkGpu* gpu,
                                   const GrSurfaceDesc& desc,
                                   GrGpuResource::LifeCycle lifeCycle,
                                   const GrVkImage::Resource* imageResource,
                                   const GrVkImageView* colorAttachmentView)
    : GrSurface(gpu, lifeCycle, desc)
    , GrVkImage(imageResource)
    , GrRenderTarget(gpu, lifeCycle, desc, kUnified_SampleConfig)
    , fFramebuffer(nullptr)
    , fColorAttachmentView(colorAttachmentView)
    , fMSAAImageResource(nullptr)
    , fResolveAttachmentView(nullptr)
    , fCachedSimpleRenderPass(nullptr) {
    SkASSERT(!desc.fSampleCnt);
    fColorValuesPerPixel = 1;
    this->createFramebuffer(gpu);
    this->registerWithCache();
}

// We're virtually derived from GrSurface (via GrRenderTarget) so its
// constructor must be explicitly called.
GrVkRenderTarget::GrVkRenderTarget(GrVkGpu* gpu,
                                   const GrSurfaceDesc& desc,
                                   GrGpuResource::LifeCycle lifeCycle,
                                   const GrVkImage::Resource* imageResource,
                                   const GrVkImageView* colorAttachmentView,
                                   Derived)
    : GrSurface(gpu, lifeCycle, desc)
    , GrVkImage(imageResource)
    , GrRenderTarget(gpu, lifeCycle, desc, kUnified_SampleConfig)
    , fFramebuffer(nullptr)
    , fColorAttachmentView(colorAttachmentView)
    , fMSAAImageResource(nullptr)
    , fResolveAttachmentView(nullptr)
    , fCachedSimpleRenderPass(nullptr) {
    SkASSERT(!desc.fSampleCnt);
    fColorValuesPerPixel = 1;
    this->createFramebuffer(gpu);
}

GrVkRenderTarget*
GrVkRenderTarget::Create(GrVkGpu* gpu,
                         const GrSurfaceDesc& desc,
                         GrGpuResource::LifeCycle lifeCycle,
                         const GrVkImage::Resource* imageResource) {
    VkFormat pixelFormat;
    GrPixelConfigToVkFormat(desc.fConfig, &pixelFormat);
    
    VkImage colorImage;

    // create msaa surface if necessary
    const GrVkImage::Resource* msaaResource = nullptr;
    const GrVkImageView* resolveAttachmentView = nullptr;
    if (desc.fSampleCnt) {
        GrVkImage::ImageDesc msImageDesc;
        msImageDesc.fImageType = VK_IMAGE_TYPE_2D;
        msImageDesc.fFormat = pixelFormat;
        msImageDesc.fWidth = desc.fWidth;
        msImageDesc.fHeight = desc.fHeight;
        msImageDesc.fLevels = 1;
        msImageDesc.fSamples = desc.fSampleCnt;
        msImageDesc.fImageTiling = VK_IMAGE_TILING_OPTIMAL;
        msImageDesc.fUsageFlags = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
        msImageDesc.fMemProps = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;

        msaaResource = GrVkImage::CreateResource(gpu, msImageDesc);

        if (!msaaResource) {
            return nullptr;
        }

        // Set color attachment image
        colorImage = msaaResource->fImage;

        // Create Resolve attachment view
        resolveAttachmentView = GrVkImageView::Create(gpu, imageResource->fImage, pixelFormat,
                                                      GrVkImageView::kColor_Type);
        if (!resolveAttachmentView) {
            msaaResource->unref(gpu);
            return nullptr;
        }
    } else {
        // Set color attachment image
        colorImage = imageResource->fImage;
    }

    // Get color attachment view
    const GrVkImageView* colorAttachmentView = GrVkImageView::Create(gpu, colorImage, pixelFormat,
                                                                     GrVkImageView::kColor_Type);
    if (!colorAttachmentView) {
        if (msaaResource) {
            resolveAttachmentView->unref(gpu);
            msaaResource->unref(gpu);
        }
        return NULL;
    }

    GrVkRenderTarget* texRT;
    if (msaaResource) {
        texRT = new GrVkRenderTarget(gpu, desc, lifeCycle, imageResource, msaaResource,
                                     colorAttachmentView, resolveAttachmentView);
        msaaResource->unref(gpu);
    } else {
        texRT = new GrVkRenderTarget(gpu, desc, lifeCycle, imageResource,
                                     colorAttachmentView);
    }

    return texRT;
}

GrVkRenderTarget*
GrVkRenderTarget::CreateNewRenderTarget(GrVkGpu* gpu,
                                        const GrSurfaceDesc& desc,
                                        GrGpuResource::LifeCycle lifeCycle,
                                        const GrVkImage::ImageDesc& imageDesc) {
    SkASSERT(imageDesc.fUsageFlags & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);

    const GrVkImage::Resource* imageResource = GrVkImage::CreateResource(gpu, imageDesc);
    if (!imageResource) {
        return nullptr;
    }

    GrVkRenderTarget* rt = GrVkRenderTarget::Create(gpu, desc, lifeCycle, imageResource);
    // Create() will increment the refCount of the image resource if it succeeds
    imageResource->unref(gpu);
    return rt;
}

GrVkRenderTarget*
GrVkRenderTarget::CreateWrappedRenderTarget(GrVkGpu* gpu,
                                            const GrSurfaceDesc& desc,
                                            GrGpuResource::LifeCycle lifeCycle,
                                            const GrVkImage::Resource* imageResource) {
    SkASSERT(imageResource);

    // Note: we assume the caller will unref the imageResource
    // Create() will increment the refCount, and we'll unref when we're done with it
    return GrVkRenderTarget::Create(gpu, desc, lifeCycle, imageResource);
}

bool GrVkRenderTarget::completeStencilAttachment() {
    this->createFramebuffer(this->getVkGpu());
    return true;
}

void GrVkRenderTarget::createFramebuffer(GrVkGpu* gpu) {
    if (fFramebuffer) {
        fFramebuffer->unref(gpu);
    }
    if (fCachedSimpleRenderPass) {
        fCachedSimpleRenderPass->unref(gpu);
    }

    // Vulkan requires us to create a compatible renderpass before we can create our framebuffer,
    // so we use this to get a (cached) basic renderpass, only for creation.
    fCachedSimpleRenderPass = gpu->resourceProvider().findOrCreateCompatibleRenderPass(*this);

    // Stencil attachment view is stored in the base RT stencil attachment
    const GrVkImageView* stencilView = this->stencilAttachmentView();
    fFramebuffer = GrVkFramebuffer::Create(gpu, this->width(), this->height(),
                                           fCachedSimpleRenderPass, fColorAttachmentView,
                                           fResolveAttachmentView, stencilView);
    SkASSERT(fFramebuffer);
}

void GrVkRenderTarget::getAttachmentsDescriptor(
                                           GrVkRenderPass::AttachmentsDescriptor* desc,
                                           GrVkRenderPass::AttachmentFlags* attachmentFlags) const {
    int colorSamples = this->numColorSamples();
    VkFormat colorFormat;
    GrPixelConfigToVkFormat(this->config(), &colorFormat);
    desc->fColor.fFormat = colorFormat;
    desc->fColor.fSamples = colorSamples ? colorSamples : 1;
    *attachmentFlags = GrVkRenderPass::kColor_AttachmentFlag;
    uint32_t attachmentCount = 1;
    if (colorSamples > 0) {
        desc->fResolve.fFormat = colorFormat;
        desc->fResolve.fSamples = 1;
        *attachmentFlags |= GrVkRenderPass::kResolve_AttachmentFlag;
        ++attachmentCount;
    }

    const GrStencilAttachment* stencil = this->renderTargetPriv().getStencilAttachment();
    if (stencil) {
        const GrVkStencilAttachment* vkStencil = static_cast<const GrVkStencilAttachment*>(stencil);
        desc->fStencil.fFormat = vkStencil->vkFormat();
        desc->fStencil.fSamples = vkStencil->numSamples() ? vkStencil->numSamples() : 1;
        // Currently in vulkan stencil and color attachments must all have same number of samples
        SkASSERT(desc->fColor.fSamples == desc->fStencil.fSamples);
        *attachmentFlags |= GrVkRenderPass::kStencil_AttachmentFlag;
        ++attachmentCount;
    }
    desc->fAttachmentCount = attachmentCount;
}

GrVkRenderTarget::~GrVkRenderTarget() {
    // either release or abandon should have been called by the owner of this object.
    SkASSERT(!fMSAAImageResource);
    SkASSERT(!fResolveAttachmentView);
    SkASSERT(!fColorAttachmentView);
    SkASSERT(!fFramebuffer);
    SkASSERT(!fCachedSimpleRenderPass);
}

void GrVkRenderTarget::addResources(GrVkCommandBuffer& commandBuffer) const {
    commandBuffer.addResource(this->framebuffer());
    commandBuffer.addResource(this->resource());
    commandBuffer.addResource(this->colorAttachmentView());
    if (this->msaaImageResource()) {
        commandBuffer.addResource(this->msaaImageResource());
        commandBuffer.addResource(this->resolveAttachmentView());
    }
    if (this->stencilImageResource()) {
        commandBuffer.addResource(this->stencilImageResource());
        commandBuffer.addResource(this->stencilAttachmentView());
    }
}

void GrVkRenderTarget::releaseInternalObjects() {
    GrVkGpu* gpu = this->getVkGpu();

    if (fMSAAImageResource) {
        fMSAAImageResource->unref(gpu);
        fMSAAImageResource = nullptr;
    }

    if (fResolveAttachmentView) {
        fResolveAttachmentView->unref(gpu);
        fResolveAttachmentView = nullptr;
    }
    if (fColorAttachmentView) {
        fColorAttachmentView->unref(gpu);
        fColorAttachmentView = nullptr;
    }
    if (fFramebuffer) {
        fFramebuffer->unref(gpu);
        fFramebuffer = nullptr;
    }
    if (fCachedSimpleRenderPass) {
        fCachedSimpleRenderPass->unref(gpu);
        fCachedSimpleRenderPass = nullptr;
    }
}

void GrVkRenderTarget::abandonInternalObjects() {
    if (fMSAAImageResource) {
        fMSAAImageResource->unrefAndAbandon();
        fMSAAImageResource = nullptr;
    }

    if (fResolveAttachmentView) {
        fResolveAttachmentView->unrefAndAbandon();
        fResolveAttachmentView = nullptr;
    }
    if (fColorAttachmentView) {
        fColorAttachmentView->unrefAndAbandon();
        fColorAttachmentView = nullptr;
    }
    if (fFramebuffer) {
        fFramebuffer->unrefAndAbandon();
        fFramebuffer = nullptr;
    }
    if (fCachedSimpleRenderPass) {
        fCachedSimpleRenderPass->unrefAndAbandon();
        fCachedSimpleRenderPass = nullptr;
    }
}

void GrVkRenderTarget::onRelease() {
    this->releaseInternalObjects();
    if (this->shouldFreeResources()) {
        this->releaseImage(this->getVkGpu());
    } else {
        this->abandonImage();
    }

    GrRenderTarget::onRelease();
}

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


GrBackendObject GrVkRenderTarget::getRenderTargetHandle() const {
    // Currently just passing back the pointer to the main Image::Resource as the handle
    return (GrBackendObject)&fResource;
}

const GrVkImage::Resource* GrVkRenderTarget::stencilImageResource() const {
    const GrStencilAttachment* stencil = this->renderTargetPriv().getStencilAttachment();
    if (stencil) {
        const GrVkStencilAttachment* vkStencil = static_cast<const GrVkStencilAttachment*>(stencil);
        return vkStencil->imageResource();
    }

    return nullptr;
}

const GrVkImageView* GrVkRenderTarget::stencilAttachmentView() const {
    const GrStencilAttachment* stencil = this->renderTargetPriv().getStencilAttachment();
    if (stencil) {
        const GrVkStencilAttachment* vkStencil = static_cast<const GrVkStencilAttachment*>(stencil);
        return vkStencil->stencilView();
    }

    return nullptr;
}


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

