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

#ifndef GrXferProcessor_DEFINED
#define GrXferProcessor_DEFINED

#include "GrBlend.h"
#include "GrColor.h"
#include "GrProcessor.h"
#include "GrProcessorSet.h"
#include "GrTexture.h"
#include "GrTypes.h"

class GrShaderCaps;
class GrGLSLXferProcessor;
class GrProcOptInfo;

/**
 * Barriers for blending. When a shader reads the dst directly, an Xfer barrier is sometimes
 * required after a pixel has been written, before it can be safely read again.
 */
enum GrXferBarrierType {
    kNone_GrXferBarrierType = 0, //<! No barrier is required
    kTexture_GrXferBarrierType,  //<! Required when a shader reads and renders to the same texture.
    kBlend_GrXferBarrierType,    //<! Required by certain blend extensions.
};
/** Should be able to treat kNone as false in boolean expressions */
GR_STATIC_ASSERT(SkToBool(kNone_GrXferBarrierType) == false);

/**
 * GrXferProcessor is responsible for implementing the xfer mode that blends the src color and dst
 * color, and for applying any coverage. It does this by emitting fragment shader code and
 * controlling the fixed-function blend state. When dual-source blending is available, it may also
 * write a seconday fragment shader output color. GrXferProcessor has two modes of operation:
 *
 * Dst read: When allowed by the backend API, or when supplied a texture of the destination, the
 * GrXferProcessor may read the destination color. While operating in this mode, the subclass only
 * provides shader code that blends the src and dst colors, and the base class applies coverage.
 *
 * No dst read: When not performing a dst read, the subclass is given full control of the fixed-
 * function blend state and/or secondary output, and is responsible to apply coverage on its own.
 *
 * A GrXferProcessor is never installed directly into our draw state, but instead is created from a
 * GrXPFactory once we have finalized the state of our draw.
 */
class GrXferProcessor : public GrProcessor {
public:
    using FragmentProcessorAnalysis = GrProcessorSet::FragmentProcessorAnalysis;

    /**
     * A texture that contains the dst pixel values and an integer coord offset from device space
     * to the space of the texture. Depending on GPU capabilities a DstTexture may be used by a
     * GrXferProcessor for blending in the fragment shader.
     */
    class DstTexture {
    public:
        DstTexture() { fOffset.set(0, 0); }

        DstTexture(const DstTexture& other) {
            *this = other;
        }

        DstTexture(GrTexture* texture, const SkIPoint& offset)
            : fTexture(SkSafeRef(texture))
            , fOffset(offset) {
        }

        DstTexture& operator=(const DstTexture& other) {
            fTexture = other.fTexture;
            fOffset = other.fOffset;
            return *this;
        }

        const SkIPoint& offset() const { return fOffset; }

        void setOffset(const SkIPoint& offset) { fOffset = offset; }
        void setOffset(int ox, int oy) { fOffset.set(ox, oy); }

        GrTexture* texture() const { return fTexture.get(); }

        void setTexture(sk_sp<GrTexture> texture) {
            fTexture = std::move(texture);
        }

    private:
        sk_sp<GrTexture> fTexture;
        SkIPoint         fOffset;
    };

    /**
     * Sets a unique key on the GrProcessorKeyBuilder calls onGetGLSLProcessorKey(...) to get the
     * specific subclass's key.
     */ 
    void getGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const;

    /** Returns a new instance of the appropriate *GL* implementation class
        for the given GrXferProcessor; caller is responsible for deleting
        the object. */
    virtual GrGLSLXferProcessor* createGLSLInstance() const = 0;

    /**
     * Optimizations for blending / coverage that an OptDrawState should apply to itself.
     */
    enum OptFlags {
        /**
         * The draw can be skipped completely.
         */
        kSkipDraw_OptFlag = 0x1,
        /**
         * GrXferProcessor will ignore color, thus no need to provide
         */
        kIgnoreColor_OptFlag = 0x2,
        /**
         * Clear color stages and override input color to that returned by getOptimizations
         */
        kOverrideColor_OptFlag = 0x4,
        /**
         * Can tweak alpha for coverage. Currently this flag should only be used by a GrDrawOp.
         */
        kCanTweakAlphaForCoverage_OptFlag = 0x8,
    };

    static const OptFlags kNone_OptFlags = (OptFlags)0;

    GR_DECL_BITFIELD_OPS_FRIENDS(OptFlags);

    /**
     * Determines which optimizations (as described by the ptFlags above) can be performed by
     * the draw with this xfer processor. If this function is called, the xfer processor may change
     * its state to reflected the given blend optimizations. If the XP needs to see a specific input
     * color to blend correctly, it will set the OverrideColor flag and the output parameter
     * overrideColor will be the required value that should be passed into the XP.
     * A caller who calls this function on a XP is required to honor the returned OptFlags
     * and color values for its draw.
     */
    OptFlags getOptimizations(const FragmentProcessorAnalysis&,
                              bool doesStencilWrite,
                              GrColor* overrideColor,
                              const GrCaps& caps) const;

    /**
     * Returns whether this XP will require an Xfer barrier on the given rt. If true, outBarrierType
     * is updated to contain the type of barrier needed.
     */
    GrXferBarrierType xferBarrierType(const GrRenderTarget* rt, const GrCaps& caps) const;

    struct BlendInfo {
        void reset() {
            fEquation = kAdd_GrBlendEquation;
            fSrcBlend = kOne_GrBlendCoeff;
            fDstBlend = kZero_GrBlendCoeff;
            fBlendConstant = 0;
            fWriteColor = true;
        }

        SkDEBUGCODE(SkString dump() const;)

        GrBlendEquation fEquation;
        GrBlendCoeff    fSrcBlend;
        GrBlendCoeff    fDstBlend;
        GrColor         fBlendConstant;
        bool            fWriteColor;
    };

    void getBlendInfo(BlendInfo* blendInfo) const;

    bool willReadDstColor() const { return fWillReadDstColor; }

    /**
     * Returns the texture to be used as the destination when reading the dst in the fragment
     * shader. If the returned texture is NULL then the XP is either not reading the dst or we have
     * extentions that support framebuffer fetching and thus don't need a copy of the dst texture.
     */
    const GrTexture* getDstTexture() const { return fDstTexture.texture(); }

    /**
     * Returns the offset in device coords to use when accessing the dst texture to get the dst
     * pixel color in the shader. This value is only valid if getDstTexture() != NULL.
     */
    const SkIPoint& dstTextureOffset() const {
        SkASSERT(this->getDstTexture());
        return fDstTextureOffset;
    }

    /**
     * If we are performing a dst read, returns whether the base class will use mixed samples to
     * antialias the shader's final output. If not doing a dst read, the subclass is responsible
     * for antialiasing and this returns false.
     */
    bool dstReadUsesMixedSamples() const { return fDstReadUsesMixedSamples; }

    /**
     * Returns whether or not this xferProcossor will set a secondary output to be used with dual
     * source blending.
     */
    bool hasSecondaryOutput() const;

    /** Returns true if this and other processor conservatively draw identically. It can only return
        true when the two processor are of the same subclass (i.e. they return the same object from
        from getFactory()).

        A return value of true from isEqual() should not be used to test whether the processor would
        generate the same shader code. To test for identical code generation use getGLSLProcessorKey
      */
    
    bool isEqual(const GrXferProcessor& that) const {
        if (this->classID() != that.classID()) {
            return false;
        }
        if (this->fWillReadDstColor != that.fWillReadDstColor) {
            return false;
        }
        if (this->fDstTexture.texture() != that.fDstTexture.texture()) {
            return false;
        }
        if (this->fDstTextureOffset != that.fDstTextureOffset) {
            return false;
        }
        if (this->fDstReadUsesMixedSamples != that.fDstReadUsesMixedSamples) {
            return false;
        }
        return this->onIsEqual(that);
    }

protected:
    GrXferProcessor();
    GrXferProcessor(const DstTexture*, bool willReadDstColor, bool hasMixedSamples);

private:
    void notifyRefCntIsZero() const final {}

    virtual OptFlags onGetOptimizations(const FragmentProcessorAnalysis&,
                                        bool doesStencilWrite,
                                        GrColor* overrideColor,
                                        const GrCaps& caps) const = 0;

    /**
     * Sets a unique key on the GrProcessorKeyBuilder that is directly associated with this xfer
     * processor's GL backend implementation.
     */
    virtual void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const = 0;

    /**
     * Determines the type of barrier (if any) required by the subclass. Note that the possibility
     * that a kTexture type barrier is required is handled by the base class and need not be
     * considered by subclass overrides of this function.
     */
    virtual GrXferBarrierType onXferBarrier(const GrRenderTarget*, const GrCaps&) const {
        return kNone_GrXferBarrierType;
    }

    /**
     * If we are not performing a dst read, returns whether the subclass will set a secondary
     * output. When using dst reads, the base class controls the secondary output and this method
     * will not be called.
     */
    virtual bool onHasSecondaryOutput() const { return false; }

    /**
     * If we are not performing a dst read, retrieves the fixed-function blend state required by the
     * subclass. When using dst reads, the base class controls the fixed-function blend state and
     * this method will not be called. The BlendInfo struct comes initialized to "no blending".
     */
    virtual void onGetBlendInfo(BlendInfo*) const {}

    virtual bool onIsEqual(const GrXferProcessor&) const = 0;

    bool                    fWillReadDstColor;
    bool                    fDstReadUsesMixedSamples;
    SkIPoint                fDstTextureOffset;
    TextureSampler          fDstTexture;

    typedef GrFragmentProcessor INHERITED;
};

GR_MAKE_BITFIELD_OPS(GrXferProcessor::OptFlags);

///////////////////////////////////////////////////////////////////////////////

/**
 * We install a GrXPFactory (XPF) early on in the pipeline before all the final draw information is
 * known (e.g. whether there is fractional pixel coverage, will coverage be 1 or 4 channel, is the
 * draw opaque, etc.). Once the state of the draw is finalized, we use the XPF along with all the
 * draw information to create a GrXferProcessor (XP) which can implement the desired blending for
 * the draw.
 *
 * Before the XP is created, the XPF is able to answer queries about what functionality the XPs it
 * creates will have. For example, can it create an XP that supports RGB coverage or will the XP
 * blend with the destination color.
 *
 * GrXPFactories are intended to be static immutable objects. We pass them around as raw pointers
 * and expect the pointers to always be valid and for the factories to be reusable and thread safe.
 * Equality is tested for using pointer comparison. GrXPFactory destructors must be no-ops.
 */

// In order to construct GrXPFactory subclass instances as constexpr the subclass, and therefore
// GrXPFactory, must be a literal type. One requirement is having a trivial destructor. This is ok
// since these objects have no need for destructors. However, GCC and clang throw a warning when a
// class has virtual functions and a non-virtual destructor. We suppress that warning here and
// for the subclasses.
#if defined(__GNUC__) || defined(__clang)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wnon-virtual-dtor"
#endif
class GrXPFactory {
public:
    using FragmentProcessorAnalysis = GrProcessorSet::FragmentProcessorAnalysis;

    typedef GrXferProcessor::DstTexture DstTexture;

    GrXferProcessor* createXferProcessor(const FragmentProcessorAnalysis&,
                                         bool hasMixedSamples,
                                         const DstTexture*,
                                         const GrCaps& caps) const;

    /**
     * Is the destination color required either in the shader or fixed function blending.
     */
    static bool WillReadDst(const GrXPFactory*, const FragmentProcessorAnalysis&);

    /**
    * This will return true if the xfer processor needs the dst color in the shader and the way
    * that the color will be made available to the xfer processor is by sampling a texture.
    */
    static bool WillNeedDstTexture(const GrXPFactory*,
                                   const GrCaps&,
                                   const FragmentProcessorAnalysis&);

protected:
    constexpr GrXPFactory() {}

private:
    /** Subclass-specific implementation of WillReadDst(). */
    virtual bool willReadsDst(const FragmentProcessorAnalysis& pipelineAnalysis) const = 0;

    virtual GrXferProcessor* onCreateXferProcessor(const GrCaps& caps,
                                                   const FragmentProcessorAnalysis&,
                                                   bool hasMixedSamples,
                                                   const DstTexture*) const = 0;

    bool willReadDstInShader(const GrCaps& caps, const FragmentProcessorAnalysis& analysis) const;

    /**
     *  Returns true if the XP generated by this factory will explicitly read dst in the fragment
     *  shader. This will not be called for draws that read from PLS since the dst color is always
     *  available in such draws.
     */
    virtual bool onWillReadDstInShader(const GrCaps&, const FragmentProcessorAnalysis&) const = 0;
};
#if defined(__GNUC__) || defined(__clang)
#pragma GCC diagnostic pop
#endif

#endif

