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

#include "GrGLEffect.h"
#include "SkMatrix.h"

class GrTexture;

/**
 * This is a helper to implement a matrix in a GrGLEffect that operates on incoming coords in the
 * vertex shader and writes them to an attribute to be used in the fragment shader. When the input
 * coords in the vertex shader are local coordinates this class accounts for the coord change matrix
 * communicated via GrDrawEffect. The input coords may also be positions and in this case the coord
 * change matrix is ignored. The GrGLEffectMatrix will emit different code based on the type of
 * matrix and thus must contribute to the effect's key.
 *
 * This class cannot be used to apply a matrix to coordinates that come in the form of custom vertex
 * attributes.
 */
class GrGLEffectMatrix {
private:
    // We specialize the generated code for each of these matrix types.
    enum MatrixTypes {
        kIdentity_MatrixType    = 0,
        kTrans_MatrixType       = 1,
        kNoPersp_MatrixType     = 2,
        kGeneral_MatrixType     = 3,
    };
    // The key for is made up of a matrix type and a bit that indicates the source of the input
    // coords.
    enum {
        kMatrixTypeKeyBits      = 2,
        kMatrixTypeKeyMask      = (1 << kMatrixTypeKeyBits) - 1,
        kPositionCoords_Flag    = (1 << kMatrixTypeKeyBits),
        kKeyBitsPrivate         = kMatrixTypeKeyBits + 1,
    };

public:

    typedef GrEffect::CoordsType CoordsType;

    typedef GrGLEffect::EffectKey EffectKey;

    /**
     * The matrix uses kKeyBits of the effect's EffectKey. A GrGLEffect may place these bits at an
     * arbitrary shift in its final key. However, when GrGLEffectMatrix::emitCode*() code is called
     * the relevant bits must be in the lower kKeyBits of the key parameter.
     */
    enum {
        kKeyBits = kKeyBitsPrivate,
        kKeyMask = (1 << kKeyBits) - 1,
    };

    GrGLEffectMatrix(CoordsType coordsType)
        : fCoordsType(coordsType) {
        fPrevMatrix = SkMatrix::InvalidMatrix();
    }

    /**
     * Generates the key for the portion of the code emitted by this class's emitCode() function.
     * Pass a texture to make GrGLEffectMatrix automatically adjust for the texture's origin. Pass
     * NULL when not using the EffectMatrix for a texture lookup, or if the GrGLEffect subclass
     * wants to handle origin adjustments in some other manner. The coords type param must match the
     * param that would be used to initialize GrGLEffectMatrix for the generating GrEffect.
     */
    static EffectKey GenKey(const SkMatrix& effectMatrix,
                            const GrDrawEffect&,
                            CoordsType,
                            const GrTexture*);

    /**
     * Emits code to implement the matrix in the VS. A varying is added as an output of the VS and
     * input to the FS. The varying may be either a vec2f or vec3f depending upon whether
     * perspective interpolation is required or not. The names of the varying in the VS and FS are
     * are returned as output parameters and the type of the varying is the return value. The suffix
     * is an optional parameter that can be used to make all variables emitted by the object
     * unique within a stage. It is only necessary if multiple GrGLEffectMatrix objects are used by
     * a single GrGLEffect.
     */
    GrSLType emitCode(GrGLShaderBuilder*,
                      EffectKey,
                      SkString* fsCoordName, /* optional */
                      SkString* vsCoordName = NULL,
                      const char* suffix = NULL);

    /**
     * This is similar to emitCode except that it performs perspective division in the FS if the
     * texture coordinates have a w coordinate. The fsCoordName always refers to a vec2f.
     */
    void emitCodeMakeFSCoords2D(GrGLShaderBuilder*,
                                EffectKey,
                                SkString* fsCoordName, /* optional */
                                SkString* vsVaryingName = NULL,
                                GrSLType* vsVaryingType = NULL,
                                const char* suffix = NULL);
    /**
     * Call from a GrGLEffect's subclass to update the texture matrix. The effectMatrix and texture
     * params should match those used with GenKey.
     */
    void setData(const GrGLUniformManager& uniformManager,
                 const SkMatrix& effectMatrix,
                 const GrDrawEffect& drawEffect,
                 const GrTexture*);

    GrGLUniformManager::UniformHandle fUni;
    GrSLType                          fUniType;
    SkMatrix                          fPrevMatrix;
    CoordsType                        fCoordsType;
};

#endif
