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


#ifndef GrShaderCaps_DEFINED
#define GrShaderCaps_DEFINED

#include "../private/GrSwizzle.h"
#include "../private/GrGLSL.h"

namespace SkSL {
    class ShaderCapsFactory;
}
struct GrContextOptions;

class GrShaderCaps : public SkRefCnt {
public:
    /** Info about shader variable precision within a given shader stage. That is, this info
        is relevant to a float (or vecNf) variable declared with a GrSLPrecision
        in a given GrShaderType. The info here is hoisted from the OpenGL spec. */
    struct PrecisionInfo {
        PrecisionInfo() {
            fLogRangeLow = 0;
            fLogRangeHigh = 0;
            fBits = 0;
        }

        /** Is this precision level allowed in the shader stage? */
        bool supported() const { return 0 != fBits; }

        bool operator==(const PrecisionInfo& that) const {
            return fLogRangeLow == that.fLogRangeLow && fLogRangeHigh == that.fLogRangeHigh &&
                   fBits == that.fBits;
        }
        bool operator!=(const PrecisionInfo& that) const { return !(*this == that); }

        /** floor(log2(|min_value|)) */
        int fLogRangeLow;
        /** floor(log2(|max_value|)) */
        int fLogRangeHigh;
        /** Number of bits of precision. As defined in OpenGL (with names modified to reflect this
            struct) :
            """
            If the smallest representable value greater than 1 is 1 + e, then fBits will
            contain floor(log2(e)), and every value in the range [2^fLogRangeLow,
            2^fLogRangeHigh] can be represented to at least one part in 2^fBits.
            """
          */
        int fBits;
    };

    /**
    * Indicates how GLSL must interact with advanced blend equations. The KHR extension requires
    * special layout qualifiers in the fragment shader.
    */
    enum AdvBlendEqInteraction {
        kNotSupported_AdvBlendEqInteraction,     //<! No _blend_equation_advanced extension
        kAutomatic_AdvBlendEqInteraction,        //<! No interaction required
        kGeneralEnable_AdvBlendEqInteraction,    //<! layout(blend_support_all_equations) out
        kSpecificEnables_AdvBlendEqInteraction,  //<! Specific layout qualifiers per equation

        kLast_AdvBlendEqInteraction = kSpecificEnables_AdvBlendEqInteraction
    };

    GrShaderCaps(const GrContextOptions&);

    SkString dump() const;

    bool shaderDerivativeSupport() const { return fShaderDerivativeSupport; }
    bool geometryShaderSupport() const { return fGeometryShaderSupport; }
    bool pathRenderingSupport() const { return fPathRenderingSupport; }
    bool dstReadInShaderSupport() const { return fDstReadInShaderSupport; }
    bool dualSourceBlendingSupport() const { return fDualSourceBlendingSupport; }
    bool integerSupport() const { return fIntegerSupport; }
    bool texelBufferSupport() const { return fTexelBufferSupport; }
    int imageLoadStoreSupport() const { return fImageLoadStoreSupport; }

    /**
    * Get the precision info for a variable of type kFloat_GrSLType, kVec2f_GrSLType, etc in a
    * given shader type. If the shader type is not supported or the precision level is not
    * supported in that shader type then the returned struct will report false when supported() is
    * called.
    */
    const PrecisionInfo& getFloatShaderPrecisionInfo(GrShaderType shaderType,
                                                     GrSLPrecision precision) const {
        return fFloatPrecisions[shaderType][precision];
    }

    /**
    * Is there any difference between the float shader variable precision types? If this is true
    * then unless the shader type is not supported, any call to getFloatShaderPrecisionInfo() would
    * report the same info for all precisions in all shader types.
    */
    bool floatPrecisionVaries() const { return fShaderPrecisionVaries; }

    /**
     * PLS storage size in bytes (0 when not supported). The PLS spec defines a minimum size of 16
     * bytes whenever PLS is supported.
     */
    int pixelLocalStorageSize() const { return fPixelLocalStorageSize; }

    /**
     * True if this context supports the necessary extensions and features to enable the PLS path
     * renderer.
     */
    bool plsPathRenderingSupport() const {
#if GR_ENABLE_PLS_PATH_RENDERING
        return fPLSPathRenderingSupport;
#else
        return false;
#endif
    }

    /**
     * Some helper functions for encapsulating various extensions to read FB Buffer on openglES
     *
     * TODO(joshualitt) On desktop opengl 4.2+ we can achieve something similar to this effect
     */
    bool fbFetchSupport() const { return fFBFetchSupport; }

    bool fbFetchNeedsCustomOutput() const { return fFBFetchNeedsCustomOutput; }

    bool bindlessTextureSupport() const { return fBindlessTextureSupport; }

    const char* versionDeclString() const { return fVersionDeclString; }

    const char* fbFetchColorName() const { return fFBFetchColorName; }

    const char* fbFetchExtensionString() const { return fFBFetchExtensionString; }

    bool dropsTileOnZeroDivide() const { return fDropsTileOnZeroDivide; }

    bool flatInterpolationSupport() const { return fFlatInterpolationSupport; }

    bool noperspectiveInterpolationSupport() const { return fNoPerspectiveInterpolationSupport; }

    bool multisampleInterpolationSupport() const { return fMultisampleInterpolationSupport; }

    bool sampleVariablesSupport() const { return fSampleVariablesSupport; }

    bool sampleMaskOverrideCoverageSupport() const { return fSampleMaskOverrideCoverageSupport; }

    bool externalTextureSupport() const { return fExternalTextureSupport; }

    bool texelFetchSupport() const { return fTexelFetchSupport; }

    AdvBlendEqInteraction advBlendEqInteraction() const { return fAdvBlendEqInteraction; }

    bool mustEnableAdvBlendEqs() const {
        return fAdvBlendEqInteraction >= kGeneralEnable_AdvBlendEqInteraction;
    }

    bool mustEnableSpecificAdvBlendEqs() const {
        return fAdvBlendEqInteraction == kSpecificEnables_AdvBlendEqInteraction;
    }

    bool mustDeclareFragmentShaderOutput() const {
        return fGLSLGeneration > k110_GrGLSLGeneration;
    }

    bool usesPrecisionModifiers() const { return fUsesPrecisionModifiers; }

    // Returns whether we can use the glsl funciton any() in our shader code.
    bool canUseAnyFunctionInShader() const { return fCanUseAnyFunctionInShader; }

    bool canUseMinAndAbsTogether() const { return fCanUseMinAndAbsTogether; }

    bool mustForceNegatedAtanParamToFloat() const { return fMustForceNegatedAtanParamToFloat; }

    bool requiresLocalOutputColorForFBFetch() const { return fRequiresLocalOutputColorForFBFetch; }

    // Returns the string of an extension that must be enabled in the shader to support
    // derivatives. If nullptr is returned then no extension needs to be enabled. Before calling
    // this function, the caller should check that shaderDerivativeSupport exists.
    const char* shaderDerivativeExtensionString() const {
        SkASSERT(this->shaderDerivativeSupport());
        return fShaderDerivativeExtensionString;
    }

    // Returns the string of an extension that will do all necessary coord transfomations needed
    // when reading the fragment position. If such an extension does not exisits, this function
    // returns a nullptr, and all transforms of the frag position must be done manually in the
    // shader.
    const char* fragCoordConventionsExtensionString() const {
        return fFragCoordConventionsExtensionString;
    }

    // This returns the name of an extension that must be enabled in the shader, if such a thing is
    // required in order to use a secondary output in the shader. This returns a nullptr if no such
    // extension is required. However, the return value of this function does not say whether dual
    // source blending is supported.
    const char* secondaryOutputExtensionString() const {
        return fSecondaryOutputExtensionString;
    }

    const char* externalTextureExtensionString() const {
        SkASSERT(this->externalTextureSupport());
        return fExternalTextureExtensionString;
    }

    const char* texelBufferExtensionString() const {
        SkASSERT(this->texelBufferSupport());
        return fTexelBufferExtensionString;
    }

    const char* noperspectiveInterpolationExtensionString() const {
        SkASSERT(this->noperspectiveInterpolationSupport());
        return fNoPerspectiveInterpolationExtensionString;
    }

    const char* multisampleInterpolationExtensionString() const {
        SkASSERT(this->multisampleInterpolationSupport());
        return fMultisampleInterpolationExtensionString;
    }

    const char* sampleVariablesExtensionString() const {
        SkASSERT(this->sampleVariablesSupport());
        return fSampleVariablesExtensionString;
    }

    const char* imageLoadStoreExtensionString() const {
        SkASSERT(this->imageLoadStoreSupport());
        return fImageLoadStoreExtensionString;
    }

    int maxVertexSamplers() const { return fMaxVertexSamplers; }

    int maxGeometrySamplers() const { return fMaxGeometrySamplers; }

    int maxFragmentSamplers() const { return fMaxFragmentSamplers; }

    int maxCombinedSamplers() const { return fMaxCombinedSamplers; }

    int maxVertexImageStorages() const { return fMaxVertexImageStorages; }

    int maxGeometryImageStorages() const { return fMaxGeometryImageStorages; }

    int maxFragmentImageStorages() const { return fMaxFragmentImageStorages; }

    int maxCombinedImageStorages() const { return fMaxCombinedImageStorages; }

    /**
     * Given a texture's config, this determines what swizzle must be appended to accesses to the
     * texture in generated shader code. Swizzling may be implemented in texture parameters or a
     * sampler rather than in the shader. In this case the returned swizzle will always be "rgba".
     */
    const GrSwizzle& configTextureSwizzle(GrPixelConfig config) const {
        return fConfigTextureSwizzle[config];
    }

    /** Swizzle that should occur on the fragment shader outputs for a given config. */
    const GrSwizzle& configOutputSwizzle(GrPixelConfig config) const {
        return fConfigOutputSwizzle[config];
    }

    /** Precision qualifier that should be used with a sampler, given its config and visibility. */
    GrSLPrecision samplerPrecision(GrPixelConfig config, GrShaderFlags visibility) const {
        return static_cast<GrSLPrecision>(fSamplerPrecisions[visibility][config]);
    }

    GrGLSLGeneration generation() const { return fGLSLGeneration; }

private:
    /** GrCaps subclasses must call this after filling in the shader precision table. */
    void initSamplerPrecisionTable();

    void applyOptionsOverrides(const GrContextOptions& options);

    GrGLSLGeneration fGLSLGeneration;

    bool fShaderDerivativeSupport   : 1;
    bool fGeometryShaderSupport     : 1;
    bool fPathRenderingSupport      : 1;
    bool fDstReadInShaderSupport    : 1;
    bool fDualSourceBlendingSupport : 1;
    bool fIntegerSupport            : 1;
    bool fTexelBufferSupport        : 1;
    bool fImageLoadStoreSupport     : 1;
    bool fPLSPathRenderingSupport   : 1;
    bool fShaderPrecisionVaries     : 1;
    bool fDropsTileOnZeroDivide : 1;
    bool fFBFetchSupport : 1;
    bool fFBFetchNeedsCustomOutput : 1;
    bool fBindlessTextureSupport : 1;
    bool fUsesPrecisionModifiers : 1;
    bool fCanUseAnyFunctionInShader : 1;
    bool fFlatInterpolationSupport : 1;
    bool fNoPerspectiveInterpolationSupport : 1;
    bool fMultisampleInterpolationSupport : 1;
    bool fSampleVariablesSupport : 1;
    bool fSampleMaskOverrideCoverageSupport : 1;
    bool fExternalTextureSupport : 1;
    bool fTexelFetchSupport : 1;

    // Used for specific driver bug work arounds
    bool fCanUseMinAndAbsTogether : 1;
    bool fMustForceNegatedAtanParamToFloat : 1;
    bool fRequiresLocalOutputColorForFBFetch : 1;

    PrecisionInfo fFloatPrecisions[kGrShaderTypeCount][kGrSLPrecisionCount];
    int fPixelLocalStorageSize;

    const char* fVersionDeclString;

    const char* fShaderDerivativeExtensionString;
    const char* fFragCoordConventionsExtensionString;
    const char* fSecondaryOutputExtensionString;
    const char* fExternalTextureExtensionString;
    const char* fTexelBufferExtensionString;
    const char* fNoPerspectiveInterpolationExtensionString;
    const char* fMultisampleInterpolationExtensionString;
    const char* fSampleVariablesExtensionString;
    const char* fImageLoadStoreExtensionString;

    const char* fFBFetchColorName;
    const char* fFBFetchExtensionString;

    int fMaxVertexSamplers;
    int fMaxGeometrySamplers;
    int fMaxFragmentSamplers;
    int fMaxCombinedSamplers;

    int fMaxVertexImageStorages;
    int fMaxGeometryImageStorages;
    int fMaxFragmentImageStorages;
    int fMaxCombinedImageStorages;

    AdvBlendEqInteraction fAdvBlendEqInteraction;

    GrSwizzle fConfigTextureSwizzle[kGrPixelConfigCnt];
    GrSwizzle fConfigOutputSwizzle[kGrPixelConfigCnt];

    uint8_t fSamplerPrecisions[(1 << kGrShaderTypeCount)][kGrPixelConfigCnt];

    friend class GrGLCaps;  // For initialization.
    friend class GrVkCaps;
    friend class SkSL::ShaderCapsFactory;
};

#endif
