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

#ifndef GrGLSLUniformHandler_DEFINED
#define GrGLSLUniformHandler_DEFINED

#include "src/gpu/GrShaderVar.h"
#include "src/gpu/GrSwizzle.h"
#include "src/gpu/glsl/GrGLSLProgramDataManager.h"

// variable names beginning with this prefix will not be mangled
#define GR_NO_MANGLE_PREFIX "sk_"

class GrGLSLProgramBuilder;
class GrGLSLShaderBuilder;
class GrSamplerState;
class GrSurfaceProxy;

// Handles for program uniforms (other than per-effect uniforms)
struct GrGLSLBuiltinUniformHandles {
    GrGLSLProgramDataManager::UniformHandle fRTAdjustmentUni;
    // Render target height, used to implement u_skRTHeight and to calculate sk_FragCoord when
    // origin_upper_left is not supported.
    GrGLSLProgramDataManager::UniformHandle fRTHeightUni;
};

class GrGLSLUniformHandler {
public:
    struct UniformInfo {
        GrShaderVar                fVariable;
        uint32_t                   fVisibility;
        const GrFragmentProcessor* fOwner;
        SkString                   fRawName;
    };

    virtual ~GrGLSLUniformHandler() {}

    using UniformHandle = GrGLSLProgramDataManager::UniformHandle;

    GR_DEFINE_RESOURCE_HANDLE_CLASS(SamplerHandle);

    /** Add a uniform variable to the current program, that has visibility in one or more shaders.
        visibility is a bitfield of GrShaderFlag values indicating from which shaders the uniform
        should be accessible. At least one bit must be set. Geometry shader uniforms are not
        supported at this time. The actual uniform name will be mangled. If outName is not nullptr
        then it will refer to the final uniform name after return. Use the addUniformArray variant
        to add an array of uniforms. */
    UniformHandle addUniform(const GrFragmentProcessor* owner,
                             uint32_t visibility,
                             GrSLType type,
                             const char* name,
                             const char** outName = nullptr) {
        SkASSERT(!GrSLTypeIsCombinedSamplerType(type));
        return this->addUniformArray(owner, visibility, type, name, 0, outName);
    }

    UniformHandle addUniformArray(const GrFragmentProcessor* owner,
                                  uint32_t visibility,
                                  GrSLType type,
                                  const char* name,
                                  int arrayCount,
                                  const char** outName = nullptr) {
        SkASSERT(!GrSLTypeIsCombinedSamplerType(type));
        bool mangle = strncmp(name, GR_NO_MANGLE_PREFIX, strlen(GR_NO_MANGLE_PREFIX));
        return this->internalAddUniformArray(owner, visibility, type, name, mangle, arrayCount,
                                             outName);
    }

    virtual const GrShaderVar& getUniformVariable(UniformHandle u) const = 0;

    /**
     * Shortcut for getUniformVariable(u).c_str()
     */
    virtual const char* getUniformCStr(UniformHandle u) const = 0;

    virtual int numUniforms() const = 0;

    virtual UniformInfo& uniform(int idx) = 0;
    virtual const UniformInfo& uniform(int idx) const = 0;

    // Looks up a uniform that was added by 'owner' with the given 'rawName' (pre-mangling).
    // If there is no such uniform, a variable with type kVoid is returned.
    GrShaderVar getUniformMapping(const GrFragmentProcessor& owner, SkString rawName) const;

    // Like getUniformMapping(), but if the uniform is found it also marks it as accessible in
    // the vertex shader.
    GrShaderVar liftUniformToVertexShader(const GrFragmentProcessor& owner, SkString rawName);

protected:
    struct UniformMapping {
        const GrFragmentProcessor* fOwner;
        int fInfoIndex;
        SkString fRawName;
        const char* fFinalName;
        GrSLType fType;
    };

    explicit GrGLSLUniformHandler(GrGLSLProgramBuilder* program) : fProgramBuilder(program) {}

    // This is not owned by the class
    GrGLSLProgramBuilder* fProgramBuilder;

private:
    virtual const char * samplerVariable(SamplerHandle) const = 0;
    virtual GrSwizzle samplerSwizzle(SamplerHandle) const = 0;

    virtual const char* inputSamplerVariable(SamplerHandle) const {
        SkDEBUGFAIL("Trying to get input sampler from unsupported backend");
        return nullptr;
    }
    virtual GrSwizzle inputSamplerSwizzle(SamplerHandle) const {
        SkDEBUGFAIL("Trying to get input sampler swizzle from unsupported backend");
        return {};
    }

    virtual SamplerHandle addSampler(const GrBackendFormat&, GrSamplerState, const GrSwizzle&,
                                     const char* name, const GrShaderCaps*) = 0;

    virtual SamplerHandle addInputSampler(const GrSwizzle& swizzle, const char* name) {
        SkDEBUGFAIL("Trying to add input sampler to unsupported backend");
        return {};
    }

    virtual UniformHandle internalAddUniformArray(const GrFragmentProcessor* owner,
                                                  uint32_t visibility,
                                                  GrSLType type,
                                                  const char* name,
                                                  bool mangleName,
                                                  int arrayCount,
                                                  const char** outName) = 0;

    virtual void appendUniformDecls(GrShaderFlags visibility, SkString*) const = 0;

    friend class GrGLSLProgramBuilder;
};

#endif
