/*
 * 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 GrRenderTarget_DEFINED
#define GrRenderTarget_DEFINED

#include "include/core/SkRect.h"
#include "src/gpu/GrSurface.h"

class GrCaps;
class GrAttachment;
class GrBackendRenderTarget;

/**
 * GrRenderTarget represents a 2D buffer of pixels that can be rendered to.
 * A context's render target is set by setRenderTarget(). Render targets are
 * created by a createTexture with the kRenderTarget_SurfaceFlag flag.
 * Additionally, GrContext provides methods for creating GrRenderTargets
 * that wrap externally created render targets.
 */
class GrRenderTarget : virtual public GrSurface {
public:
    // Make manual MSAA resolve publicly accessible from GrRenderTarget.
    using GrSurface::setRequiresManualMSAAResolve;
    using GrSurface::requiresManualMSAAResolve;

    virtual bool alwaysClearStencil() const { return false; }

    // GrSurface overrides
    GrRenderTarget* asRenderTarget() override { return this; }
    const GrRenderTarget* asRenderTarget() const  override { return this; }

    /**
     * Returns the number of samples/pixel in the color buffer (One if non-MSAA).
     */
    int numSamples() const { return fSampleCnt; }

    virtual GrBackendRenderTarget getBackendRenderTarget() const = 0;

    GrAttachment* getStencilAttachment(bool useMSAASurface) const {
        return (useMSAASurface) ? fMSAAStencilAttachment.get() : fStencilAttachment.get();
    }

    GrAttachment* getStencilAttachment() const {
        return getStencilAttachment(this->numSamples() > 1);
    }

    // Checked when this object is asked to attach a stencil buffer.
    virtual bool canAttemptStencilAttachment(bool useMSAASurface) const = 0;

    void attachStencilAttachment(sk_sp<GrAttachment> stencil, bool useMSAASurface);

    int numStencilBits(bool useMSAASurface) const;

    /**
     * Returns a unique key that identifies this render target's sample pattern. (Must be
     * multisampled.)
     */
    int getSamplePatternKey();

    /**
     * Retrieves the per-pixel HW sample locations for this render target, and, as a by-product, the
     * actual number of samples in use. (This may differ from fSampleCnt.) Sample locations are
     * returned as 0..1 offsets relative to the top-left corner of the pixel.
     */
    const SkTArray<SkPoint>& getSampleLocations();

protected:
    GrRenderTarget(GrGpu*, const SkISize&, int sampleCount, GrProtected,
                   sk_sp<GrAttachment> stenicl = nullptr);
    ~GrRenderTarget() override;

    // override of GrResource
    void onAbandon() override;
    void onRelease() override;

private:
    // Allows the backends to perform any additional work that is required for attaching a
    // GrAttachment. When this is called, the GrAttachment has already been put onto
    // the GrRenderTarget. This function must return false if any failures occur when completing the
    // stencil attachment.
    virtual bool completeStencilAttachment(GrAttachment* stencil, bool useMSAASurface) = 0;

    sk_sp<GrAttachment> fStencilAttachment;
    sk_sp<GrAttachment> fMSAAStencilAttachment;
    int fSampleCnt;

    using INHERITED = GrSurface;
};

#endif
