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

#include "GrGLGeometryProcessor.h"

#include "glsl/GrGLSLFragmentShaderBuilder.h"
#include "glsl/GrGLSLProcessorTypes.h"
#include "glsl/GrGLSLProgramBuilder.h"
#include "glsl/GrGLSLVertexShaderBuilder.h"

void GrGLGeometryProcessor::emitCode(EmitArgs& args) {
    GrGLSLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder();
    GrGPArgs gpArgs;
    this->onEmitCode(args, &gpArgs);
    vsBuilder->transformToNormalizedDeviceSpace(gpArgs.fPositionVar);
}

void GrGLGeometryProcessor::emitTransforms(GrGLSLGPBuilder* pb,
                                           const GrShaderVar& posVar,
                                           const char* localCoords,
                                           const SkMatrix& localMatrix,
                                           const TransformsIn& tin,
                                           TransformsOut* tout) {
    GrGLSLVertexBuilder* vb = pb->getVertexShaderBuilder();
    tout->push_back_n(tin.count());
    fInstalledTransforms.push_back_n(tin.count());
    for (int i = 0; i < tin.count(); i++) {
        const ProcCoords& coordTransforms = tin[i];
        fInstalledTransforms[i].push_back_n(coordTransforms.count());
        for (int t = 0; t < coordTransforms.count(); t++) {
            SkString strUniName("StageMatrix");
            strUniName.appendf("_%i_%i", i, t);
            GrSLType varyingType;

            GrCoordSet coordType = coordTransforms[t]->sourceCoords();
            uint32_t type = coordTransforms[t]->getMatrix().getType();
            if (kLocal_GrCoordSet == coordType) {
                type |= localMatrix.getType();
            }
            varyingType = SkToBool(SkMatrix::kPerspective_Mask & type) ? kVec3f_GrSLType :
                                                                         kVec2f_GrSLType;
            GrSLPrecision precision = coordTransforms[t]->precision();

            const char* uniName;
            fInstalledTransforms[i][t].fHandle =
                    pb->addUniform(GrGLSLProgramBuilder::kVertex_Visibility,
                                   kMat33f_GrSLType, precision,
                                   strUniName.c_str(),
                                   &uniName).toIndex();

            SkString strVaryingName("MatrixCoord");
            strVaryingName.appendf("_%i_%i", i, t);

            GrGLSLVertToFrag v(varyingType);
            pb->addVarying(strVaryingName.c_str(), &v, precision);

            SkASSERT(kVec2f_GrSLType == varyingType || kVec3f_GrSLType == varyingType);
            SkNEW_APPEND_TO_TARRAY(&(*tout)[i], GrGLSLTransformedCoords,
                                   (SkString(v.fsIn()), varyingType));

            // varying = matrix * coords (logically)
            if (kDevice_GrCoordSet == coordType) {
                if (kVec2f_GrSLType == varyingType) {
                    if (kVec2f_GrSLType == posVar.getType()) {
                        vb->codeAppendf("%s = (%s * vec3(%s, 1)).xy;",
                                        v.vsOut(), uniName, posVar.c_str());
                    } else {
                        // The brackets here are just to scope the temp variable
                        vb->codeAppendf("{ vec3 temp = %s * %s;", uniName, posVar.c_str());
                        vb->codeAppendf("%s = vec2(temp.x/temp.z, temp.y/temp.z); }", v.vsOut());
                    }
                } else {
                    if (kVec2f_GrSLType == posVar.getType()) {
                        vb->codeAppendf("%s = %s * vec3(%s, 1);",
                                        v.vsOut(), uniName, posVar.c_str());
                    } else {
                        vb->codeAppendf("%s = %s * %s;", v.vsOut(), uniName, posVar.c_str());
                    }
                }
            } else {
                if (kVec2f_GrSLType == varyingType) {
                    vb->codeAppendf("%s = (%s * vec3(%s, 1)).xy;", v.vsOut(), uniName, localCoords);
                } else {
                    vb->codeAppendf("%s = %s * vec3(%s, 1);", v.vsOut(), uniName, localCoords);
                }
            }
        }
    }
}

void GrGLGeometryProcessor::emitTransforms(GrGLSLGPBuilder* pb,
                                           const char* localCoords,
                                           const TransformsIn& tin,
                                           TransformsOut* tout) {
    GrGLSLVertexBuilder* vb = pb->getVertexShaderBuilder();
    tout->push_back_n(tin.count());
    for (int i = 0; i < tin.count(); i++) {
        const ProcCoords& coordTransforms = tin[i];
        for (int t = 0; t < coordTransforms.count(); t++) {
            GrSLType varyingType = kVec2f_GrSLType;

            // Device coords aren't supported
            SkASSERT(kDevice_GrCoordSet != coordTransforms[t]->sourceCoords());
            GrSLPrecision precision = coordTransforms[t]->precision();

            SkString strVaryingName("MatrixCoord");
            strVaryingName.appendf("_%i_%i", i, t);

            GrGLSLVertToFrag v(varyingType);
            pb->addVarying(strVaryingName.c_str(), &v, precision);
            vb->codeAppendf("%s = %s;", v.vsOut(), localCoords);

            SkNEW_APPEND_TO_TARRAY(&(*tout)[i],
                                   GrGLSLTransformedCoords,
                                   (SkString(v.fsIn()), varyingType));
        }
    }
}

void GrGLGeometryProcessor::setupPosition(GrGLSLGPBuilder* pb,
                                          GrGPArgs* gpArgs,
                                          const char* posName) {
    GrGLSLVertexBuilder* vsBuilder = pb->getVertexShaderBuilder();
    gpArgs->fPositionVar.set(kVec2f_GrSLType, "pos2");
    vsBuilder->codeAppendf("vec2 %s = %s;", gpArgs->fPositionVar.c_str(), posName);
}

void GrGLGeometryProcessor::setupPosition(GrGLSLGPBuilder* pb,
                                          GrGPArgs* gpArgs,
                                          const char* posName,
                                          const SkMatrix& mat,
                                          UniformHandle* viewMatrixUniform) {
    GrGLSLVertexBuilder* vsBuilder = pb->getVertexShaderBuilder();
    if (mat.isIdentity()) {
        gpArgs->fPositionVar.set(kVec2f_GrSLType, "pos2");
        vsBuilder->codeAppendf("vec2 %s = %s;", gpArgs->fPositionVar.c_str(), posName);
    } else {
        const char* viewMatrixName;
        *viewMatrixUniform = pb->addUniform(GrGLSLProgramBuilder::kVertex_Visibility,
                                            kMat33f_GrSLType, kHigh_GrSLPrecision,
                                            "uViewM",
                                            &viewMatrixName);
        if (!mat.hasPerspective()) {
            gpArgs->fPositionVar.set(kVec2f_GrSLType, "pos2");
            vsBuilder->codeAppendf("vec2 %s = vec2(%s * vec3(%s, 1));",
                                   gpArgs->fPositionVar.c_str(), viewMatrixName, posName);
        } else {
            gpArgs->fPositionVar.set(kVec3f_GrSLType, "pos3");
            vsBuilder->codeAppendf("vec3 %s = %s * vec3(%s, 1);",
                                   gpArgs->fPositionVar.c_str(), viewMatrixName, posName);
        }
    }
}
