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


#ifndef GrGLRenderTarget_DEFINED
#define GrGLRenderTarget_DEFINED

#include "include/core/SkScalar.h"
#include "include/gpu/GrBackendSurface.h"
#include "src/gpu/ganesh/GrRenderTarget.h"
#include "src/gpu/ganesh/gl/GrGLDefines_impl.h"

class GrGLCaps;
class GrGLGpu;
class GrGLAttachment;

class GrGLRenderTarget : public GrRenderTarget {
public:
    using GrSurface::glRTFBOIDis0;
    bool alwaysClearStencil() const override { return this->glRTFBOIDis0(); }

    // set fSingleSampleFBOID to this value to indicate that it is multisampled but
    // Gr doesn't know how to resolve it.
    enum { kUnresolvableFBOID = 0 };

    struct IDs {
        GrGLuint                   fMultisampleFBOID;
        GrBackendObjectOwnership   fRTFBOOwnership;
        GrGLuint                   fSingleSampleFBOID;
        GrGLuint                   fMSColorRenderbufferID;
        int                        fTotalMemorySamplesPerPixel;
    };

    static sk_sp<GrGLRenderTarget> MakeWrapped(GrGLGpu*,
                                               const SkISize&,
                                               GrGLFormat,
                                               int sampleCount,
                                               const IDs&,
                                               int stencilBits,
                                               std::string_view label);

    bool isFBO0(bool multisample) const {
        return (multisample ? fMultisampleFBOID : fSingleSampleFBOID) == 0;
    }

    bool isMultisampledRenderToTexture() const {
        return fMultisampleFBOID != 0 && fMultisampleFBOID == fSingleSampleFBOID;
    }

    GrBackendRenderTarget getBackendRenderTarget() const override;

    GrBackendFormat backendFormat() const override;

    bool canAttemptStencilAttachment(bool useMultisampleFBO) const override;

    // GrGLRenderTarget overrides dumpMemoryStatistics so it can log its texture and renderbuffer
    // components separately.
    void dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const override;

    GrGLFormat format() const { return fRTFormat; }

    bool hasDynamicMSAAAttachment() const { return SkToBool(fDynamicMSAAAttachment); }
    bool ensureDynamicMSAAAttachment();

    // Binds the render target to GL_FRAMEBUFFER for rendering.
    void bind(bool useMultisampleFBO) {
        this->bindInternal(GR_GL_FRAMEBUFFER, useMultisampleFBO);
    }

    // Must be rebound even if this is already the currently bound render target.
    bool mustRebind(bool useMultisampleFBO) const {
        return fNeedsStencilAttachmentBind[useMultisampleFBO];
    }

    // Binds the render target for copying, reading, or clearing pixel values. If we are an MSAA
    // render target with a separate resolve texture, we bind the multisampled FBO. Otherwise we
    // bind the single sample FBO.
    void bindForPixelOps(GrGLenum fboTarget) {
        this->bindInternal(fboTarget,
                           this->numSamples() > 1 && !this->isMultisampledRenderToTexture());
    }

    enum class ResolveDirection : bool {
        kSingleToMSAA,  // glCaps.canResolveSingleToMSAA() must be true.
        kMSAAToSingle
    };

    // Binds the multisampled and single sample FBOs, one to GL_DRAW_FRAMEBUFFER and the other to
    // GL_READ_FRAMEBUFFER, depending on ResolveDirection.
    void bindForResolve(ResolveDirection);

protected:
    // Constructor for subclasses.
    GrGLRenderTarget(GrGLGpu*,
                     const SkISize&,
                     GrGLFormat,
                     int sampleCount,
                     const IDs&,
                     std::string_view label);

    void init(GrGLFormat, const IDs&);

    // Binds the render target to the given target and ensures its stencil attachment is valid.
    void bindInternal(GrGLenum fboTarget, bool useMultisampleFBO);

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

    int totalMemorySamplesPerPixel() const { return fTotalMemorySamplesPerPixel; }

private:
    // Constructor for instances wrapping backend objects.
    GrGLRenderTarget(GrGLGpu*,
                     const SkISize&,
                     GrGLFormat,
                     int sampleCount,
                     const IDs&,
                     sk_sp<GrGLAttachment> stencil,
                     std::string_view label);

    void setFlags(const GrGLCaps&, const IDs&);

    GrGLGpu* getGLGpu() const;
    bool completeStencilAttachment(GrAttachment* stencil, bool useMultisampleFBO) override;

    size_t onGpuMemorySize() const override;

    void onSetLabel() override;

    sk_sp<GrGLAttachment> fDynamicMSAAAttachment;

    GrGLuint    fMultisampleFBOID;
    GrGLuint    fSingleSampleFBOID;
    GrGLuint    fMSColorRenderbufferID;
    GrGLFormat  fRTFormat;
    bool        fNeedsStencilAttachmentBind[2] = {false, false};
    bool        fDMSAARenderToTextureFBOIsMultisample = false;

    GrBackendObjectOwnership fRTFBOOwnership;

    // The RenderTarget needs to be able to report its VRAM footprint even after abandon and
    // release have potentially zeroed out the IDs (e.g., so the cache can reset itself). Since
    // the IDs are just required for the computation in totalSamples we cache that result here.
    int fTotalMemorySamplesPerPixel;

    using INHERITED = GrRenderTarget;
};

#endif
