/*
 * Copyright 2011 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/gl/GrGLRenderTarget.h"

#include "include/core/SkTraceMemoryDump.h"
#include "include/gpu/GrDirectContext.h"
#include "src/gpu/GrBackendUtils.h"
#include "src/gpu/GrDirectContextPriv.h"
#include "src/gpu/GrGpuResourcePriv.h"
#include "src/gpu/GrResourceProvider.h"
#include "src/gpu/gl/GrGLGpu.h"
#include "src/gpu/gl/GrGLUtil.h"

#define GPUGL static_cast<GrGLGpu*>(this->getGpu())
#define GL_CALL(X) GR_GL_CALL(GPUGL->glInterface(), X)
#define GL_CALL_RET(RET, X) GR_GL_CALL_RET(GPUGL->glInterface(), RET, X)

// Because this class is virtually derived from GrSurface we must explicitly call its constructor.
// Constructor for wrapped render targets.
GrGLRenderTarget::GrGLRenderTarget(GrGLGpu* gpu,
                                   const SkISize& dimensions,
                                   GrGLFormat format,
                                   int sampleCount,
                                   const IDs& ids,
                                   sk_sp<GrGLAttachment> stencil)
        : GrSurface(gpu, dimensions, GrProtected::kNo)
        , INHERITED(gpu, dimensions, sampleCount, GrProtected::kNo, std::move(stencil)) {
    this->init(format, ids);
    this->setFlags(gpu->glCaps(), ids);
    this->registerWithCacheWrapped(GrWrapCacheable::kNo);
}

GrGLRenderTarget::GrGLRenderTarget(GrGLGpu* gpu,
                                   const SkISize& dimensions,
                                   GrGLFormat format,
                                   int sampleCount,
                                   const IDs& ids)
        : GrSurface(gpu, dimensions, GrProtected::kNo)
        , INHERITED(gpu, dimensions, sampleCount, GrProtected::kNo) {
    this->init(format, ids);
    this->setFlags(gpu->glCaps(), ids);
}

inline void GrGLRenderTarget::setFlags(const GrGLCaps& glCaps, const IDs& idDesc) {
    if ((fMultisampleFBOID | fSingleSampleFBOID) == 0) {
        this->setGLRTFBOIDIs0();
    }
}

void GrGLRenderTarget::init(GrGLFormat format, const IDs& idDesc) {
    fMultisampleFBOID = idDesc.fMultisampleFBOID;
    fSingleSampleFBOID = idDesc.fSingleSampleFBOID;
    fMSColorRenderbufferID = idDesc.fMSColorRenderbufferID;
    fRTFBOOwnership = idDesc.fRTFBOOwnership;
    fRTFormat = format;
    fTotalMemorySamplesPerPixel = idDesc.fTotalMemorySamplesPerPixel;
}

GrGLFormat stencil_bits_to_format(int stencilBits) {
    SkASSERT(stencilBits);
    switch (stencilBits) {
        case 8:
            // We pick the packed format here so when we query total size we are at least not
            // underestimating the total size of the stencil buffer. However, in reality this
            // rarely matters since we usually don't care about the size of wrapped objects.
            return GrGLFormat::kDEPTH24_STENCIL8;
        case 16:
            return GrGLFormat::kSTENCIL_INDEX16;
        default:
            SkASSERT(false);
            return GrGLFormat::kUnknown;
    }
}

sk_sp<GrGLRenderTarget> GrGLRenderTarget::MakeWrapped(GrGLGpu* gpu,
                                                      const SkISize& dimensions,
                                                      GrGLFormat format,
                                                      int sampleCount,
                                                      const IDs& idDesc,
                                                      int stencilBits) {
    sk_sp<GrGLAttachment> sb;
    if (stencilBits) {
        // We pick a "fake" actual format that matches the number of stencil bits. When wrapping
        // an FBO with some number of stencil bits all we care about in the future is that we have
        // a format with the same number of stencil bits. We don't even directly use the format or
        // any other properties. Thus it is fine for us to just assign an arbitrary format that
        // matches the stencil bit count.
        GrGLFormat sFmt = stencil_bits_to_format(stencilBits);

        // We don't have the actual renderbufferID but we need to make an attachment for the stencil
        // so we just set it to an invalid value of 0 to make sure we don't explicitly use it or try
        // and delete it.
        sb = GrGLAttachment::MakeWrappedRenderBuffer(gpu,
                                                     /*renderbufferID=*/0,
                                                     dimensions,
                                                     GrAttachment::UsageFlags::kStencilAttachment,
                                                     sampleCount,
                                                     sFmt);
    }
    return sk_sp<GrGLRenderTarget>(
            new GrGLRenderTarget(gpu, dimensions, format, sampleCount, idDesc, std::move(sb)));
}

GrBackendRenderTarget GrGLRenderTarget::getBackendRenderTarget() const {
    bool useMultisampleFBO = (this->numSamples() > 1);
    GrGLFramebufferInfo fbi;
    fbi.fFBOID = (useMultisampleFBO) ? fMultisampleFBOID : fSingleSampleFBOID;
    fbi.fFormat = GrGLFormatToEnum(this->format());
    int numStencilBits = 0;
    if (GrAttachment* stencil = this->getStencilAttachment(useMultisampleFBO)) {
        numStencilBits = GrBackendFormatStencilBits(stencil->backendFormat());
    }

    return GrBackendRenderTarget(
            this->width(), this->height(), this->numSamples(), numStencilBits, fbi);
}

GrBackendFormat GrGLRenderTarget::backendFormat() const {
    // We should never have a GrGLRenderTarget (even a textureable one with a target that is not
    // texture 2D.
    return GrBackendFormat::MakeGL(GrGLFormatToEnum(fRTFormat), GR_GL_TEXTURE_2D);
}

size_t GrGLRenderTarget::onGpuMemorySize() const {
    return GrSurface::ComputeSize(this->backendFormat(), this->dimensions(),
                                  fTotalMemorySamplesPerPixel, GrMipmapped::kNo);
}

bool GrGLRenderTarget::completeStencilAttachment(GrAttachment* stencil, bool useMultisampleFBO) {
    // We defer attaching the new stencil buffer until the next time our framebuffer is bound.
    if (this->getStencilAttachment(useMultisampleFBO) != stencil) {
        fNeedsStencilAttachmentBind[useMultisampleFBO] = true;
    }
    return true;
}

bool GrGLRenderTarget::ensureDynamicMSAAAttachment() {
    SkASSERT(this->numSamples() == 1);
    if (fMultisampleFBOID) {
        return true;
    }
    SkASSERT(!fDynamicMSAAAttachment);

    GrResourceProvider* resourceProvider = this->getContext()->priv().resourceProvider();
    const GrCaps& caps = *this->getGpu()->caps();

    int internalSampleCount = caps.internalMultisampleCount(this->backendFormat());
    if (internalSampleCount <= 1) {
        return false;
    }

    if (resourceProvider->caps()->msaaResolvesAutomatically() && this->asTexture()) {
        // We can use EXT_multisampled_render_to_texture for MSAA. We will configure the FBO as MSAA
        // or not during bindFBO().
        fMultisampleFBOID = fSingleSampleFBOID;
        return true;
    }

    GL_CALL(GenFramebuffers(1, &fMultisampleFBOID));
    if (!fMultisampleFBOID) {
        return false;
    }

    this->getGLGpu()->bindFramebuffer(GR_GL_FRAMEBUFFER, fMultisampleFBOID);

    fDynamicMSAAAttachment.reset(
            static_cast<GrGLAttachment*>(resourceProvider->getDiscardableMSAAAttachment(
                    this->dimensions(), this->backendFormat(), internalSampleCount,
                    GrProtected(this->isProtected()), GrMemoryless::kNo).release()));
    if (!fDynamicMSAAAttachment) {
        return false;
    }

    GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER, GR_GL_COLOR_ATTACHMENT0, GR_GL_RENDERBUFFER,
                                    fDynamicMSAAAttachment->renderbufferID()));
    return true;
}

void GrGLRenderTarget::bindInternal(GrGLenum fboTarget, bool useMultisampleFBO) {
    GrGLuint fboId = useMultisampleFBO ? fMultisampleFBOID : fSingleSampleFBOID;
    this->getGLGpu()->bindFramebuffer(fboTarget, fboId);

    if (fSingleSampleFBOID != 0 &&
        fSingleSampleFBOID == fMultisampleFBOID &&
        useMultisampleFBO != fDMSAARenderToTextureFBOIsMultisample) {
        auto* glTex = static_cast<GrGLTexture*>(this->asTexture());
        if (this->getGLGpu()->glCaps().bindTexture0WhenChangingTextureFBOMultisampleCount()) {
            GL_CALL(FramebufferTexture2D(fboTarget,
                                         GR_GL_COLOR_ATTACHMENT0,
                                         GR_GL_TEXTURE_2D,
                                         0 /*texture*/,
                                         0 /*mipMapLevel*/));
        }
        if (useMultisampleFBO) {
            int internalSampleCount =
                    this->getGpu()->caps()->internalMultisampleCount(this->backendFormat());
            GL_CALL(FramebufferTexture2DMultisample(fboTarget,
                                                    GR_GL_COLOR_ATTACHMENT0,
                                                    glTex->target(),
                                                    glTex->textureID(),
                                                    0 /*mipMapLevel*/,
                                                    internalSampleCount));
        } else {
            GL_CALL(FramebufferTexture2D(fboTarget,
                                         GR_GL_COLOR_ATTACHMENT0,
                                         glTex->target(),
                                         glTex->textureID(),
                                         0 /*mipMapLevel*/));
        }
        fDMSAARenderToTextureFBOIsMultisample = useMultisampleFBO;
        fNeedsStencilAttachmentBind[useMultisampleFBO] = true;
    }

    // Make sure the stencil attachment is valid. Even though a color buffer op doesn't use stencil,
    // our FBO still needs to be "framebuffer complete".
    if (fNeedsStencilAttachmentBind[useMultisampleFBO]) {
        if (auto stencil = this->getStencilAttachment(useMultisampleFBO)) {
            const GrGLAttachment* glStencil = static_cast<const GrGLAttachment*>(stencil);
            GL_CALL(FramebufferRenderbuffer(fboTarget,
                                            GR_GL_STENCIL_ATTACHMENT,
                                            GR_GL_RENDERBUFFER,
                                            glStencil->renderbufferID()));
            if (GrGLFormatIsPackedDepthStencil(glStencil->format())) {
                GL_CALL(FramebufferRenderbuffer(fboTarget,
                                                GR_GL_DEPTH_ATTACHMENT,
                                                GR_GL_RENDERBUFFER,
                                                glStencil->renderbufferID()));
            } else {
                GL_CALL(FramebufferRenderbuffer(fboTarget,
                                                GR_GL_DEPTH_ATTACHMENT,
                                                GR_GL_RENDERBUFFER,
                                                0));
            }
        } else {
            GL_CALL(FramebufferRenderbuffer(fboTarget,
                                            GR_GL_STENCIL_ATTACHMENT,
                                            GR_GL_RENDERBUFFER,
                                            0));
            GL_CALL(FramebufferRenderbuffer(fboTarget,
                                            GR_GL_DEPTH_ATTACHMENT,
                                            GR_GL_RENDERBUFFER,
                                            0));
        }
#ifdef SK_DEBUG
        if (!this->getGLGpu()->glCaps().skipErrorChecks() &&
            !this->getGLGpu()->glCaps().rebindColorAttachmentAfterCheckFramebufferStatus()) {
            GrGLenum status;
            GL_CALL_RET(status, CheckFramebufferStatus(fboTarget));
            if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
                // This can fail if the context has been asynchronously abandoned (see
                // skbug.com/5200).
                SkDebugf("WARNING: failed to attach stencil.\n");
            }
        }
#endif
        fNeedsStencilAttachmentBind[useMultisampleFBO] = false;
    }
}

void GrGLRenderTarget::bindForResolve(GrGLGpu::ResolveDirection resolveDirection) {
    // If the multisample FBO is nonzero, it means we always have something to resolve (even if the
    // single sample buffer is FBO 0). If it's zero, then there's nothing to resolve.
    SkASSERT(fMultisampleFBOID != 0);

    // In the EXT_multisampled_render_to_texture case, we shouldn't be resolving anything.
    SkASSERT(!this->isMultisampledRenderToTexture());

    if (resolveDirection == GrGLGpu::ResolveDirection::kMSAAToSingle) {
        this->bindInternal(GR_GL_READ_FRAMEBUFFER, true);
        this->bindInternal(GR_GL_DRAW_FRAMEBUFFER, false);
    } else {
        SkASSERT(resolveDirection == GrGLGpu::ResolveDirection::kSingleToMSAA);
        SkASSERT(this->getGLGpu()->glCaps().canResolveSingleToMSAA());
        this->bindInternal(GR_GL_READ_FRAMEBUFFER, false);
        this->bindInternal(GR_GL_DRAW_FRAMEBUFFER, true);
    }
}

void GrGLRenderTarget::onRelease() {
    if (GrBackendObjectOwnership::kBorrowed != fRTFBOOwnership) {
        GrGLGpu* gpu = this->getGLGpu();
        if (fSingleSampleFBOID) {
            gpu->deleteFramebuffer(fSingleSampleFBOID);
        }
        if (fMultisampleFBOID && fMultisampleFBOID != fSingleSampleFBOID) {
            gpu->deleteFramebuffer(fMultisampleFBOID);
        }
        if (fMSColorRenderbufferID) {
            GL_CALL(DeleteRenderbuffers(1, &fMSColorRenderbufferID));
        }
    }
    fMultisampleFBOID       = 0;
    fSingleSampleFBOID      = 0;
    fMSColorRenderbufferID  = 0;
    INHERITED::onRelease();
}

void GrGLRenderTarget::onAbandon() {
    fMultisampleFBOID       = 0;
    fSingleSampleFBOID      = 0;
    fMSColorRenderbufferID  = 0;
    INHERITED::onAbandon();
}

GrGLGpu* GrGLRenderTarget::getGLGpu() const {
    SkASSERT(!this->wasDestroyed());
    return static_cast<GrGLGpu*>(this->getGpu());
}

bool GrGLRenderTarget::canAttemptStencilAttachment(bool useMultisampleFBO) const {
    // This cap should have been handled at a higher level.
    SkASSERT(!this->getGpu()->getContext()->priv().caps()->avoidStencilBuffers());
    // Only modify the FBO's attachments if we have created the FBO. Public APIs do not currently
    // allow for borrowed FBO ownership, so we can safely assume that if an object is owned,
    // Skia created it.
    return this->fRTFBOOwnership == GrBackendObjectOwnership::kOwned ||
           // The dmsaa attachment is always owned and always supports adding stencil.
           (this->numSamples() == 1 && useMultisampleFBO);
}

void GrGLRenderTarget::dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const {
    // Don't check this->fRefsWrappedObjects, as we might be the base of a GrGLTextureRenderTarget
    // which is multiply inherited from both ourselves and a texture. In these cases, one part
    // (texture, rt) may be wrapped, while the other is owned by Skia.
    bool refsWrappedRenderTargetObjects =
            this->fRTFBOOwnership == GrBackendObjectOwnership::kBorrowed;
    if (refsWrappedRenderTargetObjects && !traceMemoryDump->shouldDumpWrappedObjects()) {
        return;
    }

    int numSamplesNotInTexture = fTotalMemorySamplesPerPixel;
    if (this->asTexture()) {
        --numSamplesNotInTexture;  // GrGLTexture::dumpMemoryStatistics accounts for 1 sample.
    }
    if (numSamplesNotInTexture >= 1) {
        size_t size = GrSurface::ComputeSize(this->backendFormat(), this->dimensions(),
                                             numSamplesNotInTexture, GrMipmapped::kNo);

        // Due to this resource having both a texture and a renderbuffer component, dump as
        // skia/gpu_resources/resource_#/renderbuffer
        SkString resourceName = this->getResourceName();
        resourceName.append("/renderbuffer");

        this->dumpMemoryStatisticsPriv(traceMemoryDump, resourceName, "RenderTarget", size);

        SkString renderbuffer_id;
        renderbuffer_id.appendU32(fMSColorRenderbufferID);
        traceMemoryDump->setMemoryBacking(resourceName.c_str(), "gl_renderbuffer",
                                          renderbuffer_id.c_str());
    }
}
