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

#ifndef GrGLSLGeometryProcessor_DEFINED
#define GrGLSLGeometryProcessor_DEFINED

#include "GrGLSLPrimitiveProcessor.h"

class GrGLSLGPBuilder;

/**
 * If a GL effect needs a GrGLFullShaderBuilder* object to emit vertex code, then it must inherit
 * from this class. Since paths don't have vertices, this class is only meant to be used internally
 * by skia, for special cases.
 */
class GrGLSLGeometryProcessor : public GrGLSLPrimitiveProcessor {
public:
    /* Any general emit code goes in the base class emitCode.  Subclasses override onEmitCode */
    void emitCode(EmitArgs&) final;

protected:
    // A helper which subclasses can use to upload coord transform matrices in setData().
    void setTransformDataHelper(const SkMatrix& localMatrix,
                                const GrGLSLProgramDataManager& pdman,
                                FPCoordTransformIter*);

    // Emit transformed local coords from the vertex shader as a uniform matrix and varying per
    // coord-transform. localCoordsVar must be a 2- or 3-component vector. If it is 3 then it is
    // assumed to be a 2D homogeneous coordinate.
    void emitTransforms(GrGLSLVertexBuilder*,
                        GrGLSLVaryingHandler*,
                        GrGLSLUniformHandler*,
                        const GrShaderVar& localCoordsVar,
                        const SkMatrix& localMatrix,
                        FPCoordTransformHandler*);

    // Version of above that assumes identity for the local matrix.
    void emitTransforms(GrGLSLVertexBuilder* vb,
                        GrGLSLVaryingHandler* varyingHandler,
                        GrGLSLUniformHandler* uniformHandler,
                        const GrShaderVar& localCoordsVar,
                        FPCoordTransformHandler* handler) {
        this->emitTransforms(vb, varyingHandler, uniformHandler, localCoordsVar, SkMatrix::I(),
                             handler);
    }

    struct GrGPArgs {
        // Used to specify the output variable used by the GP to store its device position. It can
        // either be a float2 or a float3 (in order to handle perspective). The subclass sets this
        // in its onEmitCode().
        GrShaderVar fPositionVar;
    };

    // Helpers for adding code to write the transformed vertex position. The first simple version
    // just writes a variable named by 'posName' into the position output variable with the
    // assumption that the position is 2D. The second version transforms the input position by a
    // view matrix and the output variable is 2D or 3D depending on whether the view matrix is
    // perspective. Both versions declare the output position variable and will set
    // GrGPArgs::fPositionVar.
    void writeOutputPosition(GrGLSLVertexBuilder*, GrGPArgs*, const char* posName);
    void writeOutputPosition(GrGLSLVertexBuilder*,
                             GrGLSLUniformHandler* uniformHandler,
                             GrGPArgs*,
                             const char* posName,
                             const SkMatrix& mat,
                             UniformHandle* viewMatrixUniform);

    static uint32_t ComputePosKey(const SkMatrix& mat) {
        if (mat.isIdentity()) {
            return 0x0;
        } else if (!mat.hasPerspective()) {
            return 0x01;
        } else {
            return 0x02;
        }
    }

private:
    virtual void onEmitCode(EmitArgs&, GrGPArgs*) = 0;

    struct TransformUniform {
        UniformHandle  fHandle;
        SkMatrix       fCurrentValue = SkMatrix::InvalidMatrix();
    };

    SkTArray<TransformUniform, true> fInstalledTransforms;

    typedef GrGLSLPrimitiveProcessor INHERITED;
};

#endif
