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

#include "GrBackendEffectFactory.h"
#include "GrGLShaderBuilder.h"
#include "GrGLShaderVar.h"
#include "GrGLSL.h"

class GrGLTexture;

/** @file
    This file contains specializations for OpenGL of the shader stages declared in
    include/gpu/GrEffect.h. Objects of type GrGLEffect are responsible for emitting the
    GLSL code that implements a GrEffect and for uploading uniforms at draw time. They also
    must have a function:
        static inline EffectKey GenKey(const GrDrawEffect&, const GrGLCaps&)
    that is used to implement a program cache. When two GrEffects produce the same key this means
    that their GrGLEffects would emit the same GLSL code.

    The GrGLEffect subclass must also have a constructor of the form:
        EffectSubclass::EffectSubclass(const GrBackendEffectFactory&, const GrDrawEffect&)
    The effect held by the GrDrawEffect is guaranteed to be of the type that generated the
    GrGLEffect subclass instance.

    These objects are created by the factory object returned by the GrEffect::getFactory().
*/

class GrDrawEffect;

class GrGLEffect {

public:
    typedef GrBackendEffectFactory::EffectKey EffectKey;

    enum {
        kNoEffectKey = GrBackendEffectFactory::kNoEffectKey,
        // the number of bits in EffectKey available to GenKey
        kEffectKeyBits = GrBackendEffectFactory::kEffectKeyBits,
    };

    typedef GrGLShaderBuilder::TextureSamplerArray TextureSamplerArray;

    GrGLEffect(const GrBackendEffectFactory&);

    virtual ~GrGLEffect();

    /** Called when GrGLProgram is about to create its GrGLShaderBuilder. When possible, effects
        should handle programs that don't have a vertex shader. But if an effect requires special
        vertex processing that can't be accomplished with the fixed pipeline, it can override this
        method and return true to guarantee the GrGLShaderBuilder in emitCode has a VertexBuilder.
        */
    virtual bool requiresVertexShader(const GrDrawEffect&) const { return false; }

    /** Called when the program stage should insert its code into the shaders. The code in each
        shader will be in its own block ({}) and so locally scoped names will not collide across
        stages.

        @param builder      Interface used to emit code in the shaders.
        @param drawEffect   A wrapper on the effect that generated this program stage.
        @param key          The key that was computed by GenKey() from the generating GrEffect.
                            Only the bits indicated by GrBackendEffectFactory::kEffectKeyBits are
                            guaranteed to match the value produced by GenKey();
        @param outputColor  A predefined vec4 in the FS in which the stage should place its output
                            color (or coverage).
        @param inputColor   A vec4 that holds the input color to the stage in the FS. This may be
                            NULL in which case the implied input is solid white (all ones).
                            TODO: Better system for communicating optimization info (e.g. input
                            color is solid white, trans black, known to be opaque, etc.) that allows
                            the effect to communicate back similar known info about its output.
        @param samplers     One entry for each GrTextureAccess of the GrEffect that generated the
                            GrGLEffect. These can be passed to the builder to emit texture
                            reads in the generated code.
        */
    virtual void emitCode(GrGLShaderBuilder* builder,
                          const GrDrawEffect& drawEffect,
                          EffectKey key,
                          const char* outputColor,
                          const char* inputColor,
                          const TextureSamplerArray& samplers) = 0;

    /** A GrGLEffect instance can be reused with any GrEffect that produces the same stage
        key; this function reads data from a stage and uploads any uniform variables required
        by the shaders created in emitCode(). The GrEffect installed in the GrEffectStage is
        guaranteed to be of the same type that created this GrGLEffect and to have an identical
        EffectKey as the one that created this GrGLEffect. Effects that use local coords have
        to consider whether the GrEffectStage's coord change matrix should be used. When explicit
        local coordinates are used it can be ignored. */
    virtual void setData(const GrGLUniformManager&, const GrDrawEffect&);

    const char* name() const { return fFactory.name(); }

    static EffectKey GenTextureKey(const GrDrawEffect&, const GrGLCaps&);
    static EffectKey GenAttribKey(const GrDrawEffect& stage);

protected:
    const GrBackendEffectFactory& fFactory;
};

#endif
