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

#include "GrGLProgramEffects.h"
#include "gl/GrGLEffect.h"
#include "gl/GrGLPathRendering.h"
#include "gl/builders/GrGLFullProgramBuilder.h"
#include "gl/builders/GrGLFragmentOnlyProgramBuilder.h"
#include "gl/GrGLGeometryProcessor.h"
#include "gl/GrGpuGL.h"

typedef GrGLProgramEffects::TransformedCoords TransformedCoords;
typedef GrGLProgramEffects::TransformedCoordsArray TransformedCoordsArray;
typedef GrGLProgramEffects::TextureSampler TextureSampler;
typedef GrGLProgramEffects::TextureSamplerArray TextureSamplerArray;

/**
 * We specialize the vertex code for each of these matrix types.
 */
enum MatrixType {
    kNoPersp_MatrixType  = 0,
    kGeneral_MatrixType  = 1,
};

/**
 * The key for an individual coord transform is made up of a matrix type and a bit that
 * indicates the source of the input coords.
 */
enum {
    kMatrixTypeKeyBits   = 1,
    kMatrixTypeKeyMask   = (1 << kMatrixTypeKeyBits) - 1,
    kPositionCoords_Flag = (1 << kMatrixTypeKeyBits),
    kTransformKeyBits    = kMatrixTypeKeyBits + 1,
};

namespace {

/**
 * Do we need to either map r,g,b->a or a->r. configComponentMask indicates which channels are
 * present in the texture's config. swizzleComponentMask indicates the channels present in the
 * shader swizzle.
 */
inline bool swizzle_requires_alpha_remapping(const GrGLCaps& caps,
                                             uint32_t configComponentMask,
                                             uint32_t swizzleComponentMask) {
    if (caps.textureSwizzleSupport()) {
        // Any remapping is handled using texture swizzling not shader modifications.
        return false;
    }
    // check if the texture is alpha-only
    if (kA_GrColorComponentFlag == configComponentMask) {
        if (caps.textureRedSupport() && (kA_GrColorComponentFlag & swizzleComponentMask)) {
            // we must map the swizzle 'a's to 'r'.
            return true;
        }
        if (kRGB_GrColorComponentFlags & swizzleComponentMask) {
            // The 'r', 'g', and/or 'b's must be mapped to 'a' according to our semantics that
            // alpha-only textures smear alpha across all four channels when read.
            return true;
        }
    }
    return false;
}

/**
 * Retrieves the matrix type from transformKey for the transform at transformIdx.
 */
MatrixType get_matrix_type(uint32_t transformKey, int transformIdx) {
    return static_cast<MatrixType>(
               (transformKey >> (kTransformKeyBits * transformIdx)) & kMatrixTypeKeyMask);
}

/**
 * Retrieves the source coords from transformKey for the transform at transformIdx. It may not be
 * the same coordinate set as the original GrCoordTransform if the position and local coords are
 * identical for this program.
 */
GrCoordSet get_source_coords(uint32_t transformKey, int transformIdx) {
    return (transformKey >> (kTransformKeyBits * transformIdx)) & kPositionCoords_Flag ?
               kPosition_GrCoordSet :
               kLocal_GrCoordSet;
}

/**
 * Retrieves the final matrix that a transform needs to apply to its source coords.
 */
SkMatrix get_transform_matrix(const GrEffectStage& effectStage,
                              bool useExplicitLocalCoords,
                              int transformIdx) {
    const GrCoordTransform& coordTransform = effectStage.getEffect()->coordTransform(transformIdx);
    SkMatrix combined;

    if (kLocal_GrCoordSet == coordTransform.sourceCoords()) {
        // If we have explicit local coords then we shouldn't need a coord change.
        const SkMatrix& ccm =
                useExplicitLocalCoords ? SkMatrix::I() : effectStage.getCoordChangeMatrix();
        combined.setConcat(coordTransform.getMatrix(), ccm);
    } else {
        combined = coordTransform.getMatrix();
    }
    if (coordTransform.reverseY()) {
        // combined.postScale(1,-1);
        // combined.postTranslate(0,1);
        combined.set(SkMatrix::kMSkewY,
            combined[SkMatrix::kMPersp0] - combined[SkMatrix::kMSkewY]);
        combined.set(SkMatrix::kMScaleY,
            combined[SkMatrix::kMPersp1] - combined[SkMatrix::kMScaleY]);
        combined.set(SkMatrix::kMTransY,
            combined[SkMatrix::kMPersp2] - combined[SkMatrix::kMTransY]);
    }
    return combined;
}
}

////////////////////////////////////////////////////////////////////////////////

bool GrGLProgramEffects::GenEffectMetaKey(const GrEffectStage& effectStage,
                                          bool useExplicitLocalCoords,
                                          const GrGLCaps& caps,
                                          GrEffectKeyBuilder* b) {

    uint32_t textureKey = GrGLProgramEffects::GenTextureKey(effectStage.getEffect(), caps);
    uint32_t transformKey = GrGLProgramEffects::GenTransformKey(effectStage,useExplicitLocalCoords);
    uint32_t attribKey = GrGLProgramEffects::GenAttribKey(effectStage.getEffect());
    uint32_t classID = effectStage.getEffect()->getFactory().effectClassID();

    // Currently we allow 16 bits for each of the above portions of the meta-key. Fail if they
    // don't fit.
    static const uint32_t kMetaKeyInvalidMask = ~((uint32_t) SK_MaxU16);
    if ((textureKey | transformKey | attribKey | classID) & kMetaKeyInvalidMask) {
        return false;
    }

    uint32_t* key = b->add32n(2);
    key[0] = (textureKey << 16 | transformKey);
    key[1] = (classID << 16 | attribKey);
    return true;
}

uint32_t GrGLProgramEffects::GenAttribKey(const GrEffect* effect) {
    uint32_t key = 0;

    const GrEffect::VertexAttribArray& vars = effect->getVertexAttribs();
    int numAttributes = vars.count();
    SkASSERT(numAttributes <= 2);
    for (int a = 0; a < numAttributes; ++a) {
        uint32_t value = 1 << a;
        key |= value;
    }
    return key;
}

uint32_t GrGLProgramEffects::GenTransformKey(const GrEffectStage& effectStage,
                                             bool useExplicitLocalCoords) {
    uint32_t totalKey = 0;
    int numTransforms = effectStage.getEffect()->numTransforms();
    for (int t = 0; t < numTransforms; ++t) {
        uint32_t key = 0;
        const GrCoordTransform& coordTransform = effectStage.getEffect()->coordTransform(t);
        SkMatrix::TypeMask type0 = coordTransform.getMatrix().getType();
        SkMatrix::TypeMask type1 = SkMatrix::kIdentity_Mask;
        if (kLocal_GrCoordSet == coordTransform.sourceCoords() && !useExplicitLocalCoords) {
            type1 = effectStage.getCoordChangeMatrix().getType();
        } else if (kPosition_GrCoordSet == coordTransform.sourceCoords() && useExplicitLocalCoords) {
            // We only make the key indicate that device coords are referenced when the local coords
            // are not actually determined by positions. Otherwise the local coords var and position
            // var are identical.
            key |= kPositionCoords_Flag;
        }

        int combinedTypes = type0 | type1;

        if (SkMatrix::kPerspective_Mask & combinedTypes) {
            key |= kGeneral_MatrixType;
        } else {
            key |= kNoPersp_MatrixType;
        }
        key <<= kTransformKeyBits * t;
        SkASSERT(0 == (totalKey & key)); // keys for each transform ought not to overlap
        totalKey |= key;
    }
    return totalKey;
}

uint32_t GrGLProgramEffects::GenTextureKey(const GrEffect* effect, const GrGLCaps& caps) {
    uint32_t key = 0;
    int numTextures = effect->numTextures();
    for (int t = 0; t < numTextures; ++t) {
        const GrTextureAccess& access = effect->textureAccess(t);
        uint32_t configComponentMask = GrPixelConfigComponentMask(access.getTexture()->config());
        if (swizzle_requires_alpha_remapping(caps, configComponentMask, access.swizzleMask())) {
            key |= 1 << t;
        }
    }
    return key;
}

GrGLProgramEffects::~GrGLProgramEffects() {
    int numEffects = fGLEffects.count();
    for (int e = 0; e < numEffects; ++e) {
        SkDELETE(fGLEffects[e]);
    }
}

void GrGLProgramEffects::emitSamplers(GrGLProgramBuilder* builder,
                                      const GrEffect& effect,
                                      TextureSamplerArray* outSamplers) {
    SkTArray<Sampler, true>& samplers = fSamplers.push_back();
    int numTextures = effect.numTextures();
    samplers.push_back_n(numTextures);
    SkString name;
    for (int t = 0; t < numTextures; ++t) {
        name.printf("Sampler%d", t);
        samplers[t].fUniform = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
                                                   kSampler2D_GrSLType,
                                                   name.c_str());
        SkNEW_APPEND_TO_TARRAY(outSamplers, TextureSampler,
                               (samplers[t].fUniform, effect.textureAccess(t)));
    }
}

void GrGLProgramEffects::initSamplers(const GrGLProgramDataManager& programResourceManager, int* texUnitIdx) {
    int numEffects = fGLEffects.count();
    SkASSERT(numEffects == fSamplers.count());
    for (int e = 0; e < numEffects; ++e) {
        SkTArray<Sampler, true>& samplers = fSamplers[e];
        int numSamplers = samplers.count();
        for (int s = 0; s < numSamplers; ++s) {
            SkASSERT(samplers[s].fUniform.isValid());
            programResourceManager.setSampler(samplers[s].fUniform, *texUnitIdx);
            samplers[s].fTextureUnit = (*texUnitIdx)++;
        }
    }
}

void GrGLProgramEffects::bindTextures(GrGpuGL* gpu, const GrEffect& effect, int effectIdx) {
    const SkTArray<Sampler, true>& samplers = fSamplers[effectIdx];
    int numSamplers = samplers.count();
    SkASSERT(numSamplers == effect.numTextures());
    for (int s = 0; s < numSamplers; ++s) {
        SkASSERT(samplers[s].fTextureUnit >= 0);
        const GrTextureAccess& textureAccess = effect.textureAccess(s);
        gpu->bindTexture(samplers[s].fTextureUnit,
                         textureAccess.getParams(),
                         static_cast<GrGLTexture*>(textureAccess.getTexture()));
    }
}

////////////////////////////////////////////////////////////////////////////////

void GrGLVertexProgramEffects::emitEffect(GrGLFullProgramBuilder* builder,
                                          const GrEffectStage& stage,
                                          const GrEffectKey& key,
                                          const char* outColor,
                                          const char* inColor,
                                          int stageIndex) {
    const GrEffect& effect = *stage.getEffect();
    SkSTArray<2, TransformedCoords> coords(effect.numTransforms());
    SkSTArray<4, TextureSampler> samplers(effect.numTextures());

    GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder();
    GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
    vsBuilder->emitAttributes(stage);
    this->emitTransforms(builder, stage, &coords);
    this->emitSamplers(builder, effect, &samplers);

    GrGLEffect* glEffect = effect.getFactory().createGLInstance(effect);
    fGLEffects.push_back(glEffect);

    // Enclose custom code in a block to avoid namespace conflicts
    SkString openBrace;
    openBrace.printf("\t{ // Stage %d: %s\n", stageIndex, glEffect->name());
    fsBuilder->codeAppend(openBrace.c_str());
    vsBuilder->codeAppend(openBrace.c_str());

    if (glEffect->isVertexEffect()) {
        GrGLGeometryProcessor* vertexEffect = static_cast<GrGLGeometryProcessor*>(glEffect);
        vertexEffect->emitCode(builder, effect, key, outColor, inColor, coords, samplers);
    } else {
        glEffect->emitCode(builder, effect, key, outColor, inColor, coords, samplers);
    }

    vsBuilder->codeAppend("\t}\n");
    fsBuilder->codeAppend("\t}\n");
}

void GrGLVertexProgramEffects::emitTransforms(GrGLFullProgramBuilder* builder,
                                              const GrEffectStage& effectStage,
                                              TransformedCoordsArray* outCoords) {
    SkTArray<Transform, true>& transforms = fTransforms.push_back();
    uint32_t totalKey = GenTransformKey(effectStage, fHasExplicitLocalCoords);
    int numTransforms = effectStage.getEffect()->numTransforms();
    transforms.push_back_n(numTransforms);

    SkTArray<PathTransform, true>* pathTransforms = NULL;
    const GrGLCaps* glCaps = builder->ctxInfo().caps();
    if (glCaps->pathRenderingSupport() &&
        builder->gpu()->glPathRendering()->texturingMode() ==
           GrGLPathRendering::SeparableShaders_TexturingMode) {
        pathTransforms = &fPathTransforms.push_back();
        pathTransforms->push_back_n(numTransforms);
    }

    for (int t = 0; t < numTransforms; t++) {
        GrSLType varyingType = kVoid_GrSLType;
        const char* uniName;
        switch (get_matrix_type(totalKey, t)) {
            case kNoPersp_MatrixType:
                uniName = "StageMatrix";
                varyingType = kVec2f_GrSLType;
                break;
            case kGeneral_MatrixType:
                uniName = "StageMatrix";
                varyingType = kVec3f_GrSLType;
                break;
            default:
                SkFAIL("Unexpected key.");
        }
        SkString suffixedUniName;
        if (0 != t) {
            suffixedUniName.append(uniName);
            suffixedUniName.appendf("_%i", t);
            uniName = suffixedUniName.c_str();
        }
        transforms[t].fHandle = builder->addUniform(GrGLProgramBuilder::kVertex_Visibility,
                                                    kMat33f_GrSLType,
                                                    uniName,
                                                    &uniName);

        const char* varyingName = "MatrixCoord";
        SkString suffixedVaryingName;
        if (0 != t) {
            suffixedVaryingName.append(varyingName);
            suffixedVaryingName.appendf("_%i", t);
            varyingName = suffixedVaryingName.c_str();
        }
        const char* vsVaryingName;
        const char* fsVaryingName;
        GrGLVertexShaderBuilder* vsBuilder = builder->getVertexShaderBuilder();
        if (pathTransforms) {
            (*pathTransforms)[t].fHandle =
                builder->addSeparableVarying(varyingType, varyingName, &vsVaryingName, &fsVaryingName);
            (*pathTransforms)[t].fType = varyingType;
        } else {
            builder->addVarying(varyingType, varyingName, &vsVaryingName, &fsVaryingName);
        }

        const GrGLShaderVar& coords = kPosition_GrCoordSet == get_source_coords(totalKey, t) ?
                                          vsBuilder->positionAttribute() :
                                          vsBuilder->localCoordsAttribute();
        // varying = matrix * coords (logically)
        SkASSERT(kVec2f_GrSLType == varyingType || kVec3f_GrSLType == varyingType);
        if (kVec2f_GrSLType == varyingType) {
            vsBuilder->codeAppendf("\t%s = (%s * vec3(%s, 1)).xy;\n",
                                   vsVaryingName, uniName, coords.c_str());
        } else {
            vsBuilder->codeAppendf("\t%s = %s * vec3(%s, 1);\n",
                                   vsVaryingName, uniName, coords.c_str());
        }
        SkNEW_APPEND_TO_TARRAY(outCoords, TransformedCoords,
                               (SkString(fsVaryingName), varyingType));
    }
}

void GrGLVertexProgramEffects::setData(GrGpuGL* gpu,
                                       GrGpu::DrawType drawType,
                                       const GrGLProgramDataManager& programDataManager,
                                       const GrEffectStage* effectStages[]) {
    int numEffects = fGLEffects.count();
    SkASSERT(numEffects == fTransforms.count());
    SkASSERT(numEffects == fSamplers.count());
    for (int e = 0; e < numEffects; ++e) {
        const GrEffectStage& effectStage = *effectStages[e];
        const GrEffect& effect = *effectStage.getEffect();
        fGLEffects[e]->setData(programDataManager, effect);
        if (GrGpu::IsPathRenderingDrawType(drawType)) {
            this->setPathTransformData(gpu, programDataManager, effectStage, e);
        } else {
            this->setTransformData(gpu, programDataManager, effectStage, e);
        }

        this->bindTextures(gpu, effect, e);
    }
}

void GrGLVertexProgramEffects::setData(GrGpuGL* gpu,
                                       GrGpu::DrawType drawType,
                                       const GrGLProgramDataManager& programDataManager,
                                       const GrEffectStage* effectStage) {
    SkASSERT(1 == fTransforms.count());
    SkASSERT(1 == fSamplers.count());
    SkASSERT(1 == fGLEffects.count());
    const GrEffect& effect = *effectStage->getEffect();
    fGLEffects[0]->setData(programDataManager, effect);
    if (GrGpu::IsPathRenderingDrawType(drawType)) {
        this->setPathTransformData(gpu, programDataManager, *effectStage, 0);
    } else {
        this->setTransformData(gpu, programDataManager, *effectStage, 0);
    }

    this->bindTextures(gpu, effect, 0);
}

void GrGLVertexProgramEffects::setTransformData(GrGpuGL* gpu,
                                                const GrGLProgramDataManager& pdman,
                                                const GrEffectStage& effectStage,
                                                int effectIdx) {
    SkTArray<Transform, true>& transforms = fTransforms[effectIdx];
    int numTransforms = transforms.count();
    SkASSERT(numTransforms == effectStage.getEffect()->numTransforms());
    for (int t = 0; t < numTransforms; ++t) {
        SkASSERT(transforms[t].fHandle.isValid());
        const SkMatrix& matrix = get_transform_matrix(effectStage, fHasExplicitLocalCoords, t);
        if (!transforms[t].fCurrentValue.cheapEqualTo(matrix)) {
            pdman.setSkMatrix(transforms[t].fHandle, matrix);
            transforms[t].fCurrentValue = matrix;
        }
    }
}

void GrGLVertexProgramEffects::setPathTransformData(GrGpuGL* gpu,
                                                    const GrGLProgramDataManager& pdman,
                                                    const GrEffectStage& effectStage,
                                                    int effectIdx) {
    SkTArray<PathTransform, true>& transforms = fPathTransforms[effectIdx];
    int numTransforms = transforms.count();
    SkASSERT(numTransforms == effectStage.getEffect()->numTransforms());
    for (int t = 0; t < numTransforms; ++t) {
        SkASSERT(transforms[t].fHandle.isValid());
        const SkMatrix& transform = get_transform_matrix(effectStage, fHasExplicitLocalCoords, t);
        if (transforms[t].fCurrentValue.cheapEqualTo(transform)) {
            continue;
        }
        transforms[t].fCurrentValue = transform;
        switch (transforms[t].fType) {
            case kVec2f_GrSLType:
                pdman.setProgramPathFragmentInputTransform(transforms[t].fHandle, 2, transform);
                break;
            case kVec3f_GrSLType:
                pdman.setProgramPathFragmentInputTransform(transforms[t].fHandle, 3, transform);
                break;
            default:
                SkFAIL("Unexpected matrix type.");
        }
    }
}

GrGLVertexProgramEffectsBuilder::GrGLVertexProgramEffectsBuilder(GrGLFullProgramBuilder* builder,
                                                                 int reserveCount)
    : fBuilder(builder)
    , fProgramEffects(SkNEW_ARGS(GrGLVertexProgramEffects,
                                 (reserveCount,
                                  fBuilder->getVertexShaderBuilder()->hasExplicitLocalCoords()))) {
}
void GrGLVertexProgramEffectsBuilder::emitEffect(const GrEffectStage& stage,
                                                 const GrEffectKey& key,
                                                 const char* outColor,
                                                 const char* inColor,
                                                 int stageIndex) {
    SkASSERT(fProgramEffects.get());
    fProgramEffects->emitEffect(fBuilder, stage, key, outColor, inColor, stageIndex);
}

////////////////////////////////////////////////////////////////////////////////

void GrGLPathTexGenProgramEffects::emitEffect(GrGLFragmentOnlyProgramBuilder* builder,
                                          const GrEffectStage& stage,
                                          const GrEffectKey& key,
                                          const char* outColor,
                                          const char* inColor,
                                          int stageIndex) {
    const GrEffect& effect = *stage.getEffect();
    SkSTArray<2, TransformedCoords> coords(effect.numTransforms());
    SkSTArray<4, TextureSampler> samplers(effect.numTextures());

    SkASSERT(0 == effect.getVertexAttribs().count());
    this->setupPathTexGen(builder, stage, &coords);
    this->emitSamplers(builder, effect, &samplers);

    GrGLEffect* glEffect = effect.getFactory().createGLInstance(effect);
    fGLEffects.push_back(glEffect);

    GrGLFragmentShaderBuilder* fsBuilder = builder->getFragmentShaderBuilder();
    // Enclose custom code in a block to avoid namespace conflicts
    SkString openBrace;
    openBrace.printf("\t{ // Stage %d: %s\n", stageIndex, glEffect->name());
    fsBuilder->codeAppend(openBrace.c_str());

    SkASSERT(!glEffect->isVertexEffect());
    glEffect->emitCode(builder, effect, key, outColor, inColor, coords, samplers);

    fsBuilder->codeAppend("\t}\n");
}

void GrGLPathTexGenProgramEffects::setupPathTexGen(GrGLFragmentOnlyProgramBuilder* builder,
                                           const GrEffectStage& effectStage,
                                           TransformedCoordsArray* outCoords) {
    int numTransforms = effectStage.getEffect()->numTransforms();
    uint32_t totalKey = GenTransformKey(effectStage, false);
    int texCoordIndex = builder->addTexCoordSets(numTransforms);
    SkNEW_APPEND_TO_TARRAY(&fTransforms, Transforms, (totalKey, texCoordIndex));
    SkString name;
    for (int t = 0; t < numTransforms; ++t) {
        GrSLType type = kGeneral_MatrixType == get_matrix_type(totalKey, t) ?
                            kVec3f_GrSLType :
                            kVec2f_GrSLType;
        name.printf("%s(gl_TexCoord[%i])", GrGLSLTypeString(type), texCoordIndex++);
        SkNEW_APPEND_TO_TARRAY(outCoords, TransformedCoords, (name, type));
    }
}

void GrGLPathTexGenProgramEffects::setData(GrGpuGL* gpu,
                                           GrGpu::DrawType,
                                           const GrGLProgramDataManager& pdman,
                                           const GrEffectStage* effectStages[]) {
    int numEffects = fGLEffects.count();
    SkASSERT(numEffects == fTransforms.count());
    SkASSERT(numEffects == fSamplers.count());
    for (int e = 0; e < numEffects; ++e) {
        const GrEffectStage& effectStage = *effectStages[e];
        const GrEffect& effect = *effectStage.getEffect();
        fGLEffects[e]->setData(pdman, effect);
        this->setPathTexGenState(gpu, effectStage, e);
        this->bindTextures(gpu, effect, e);
    }
}

void GrGLPathTexGenProgramEffects::setPathTexGenState(GrGpuGL* gpu,
                                              const GrEffectStage& effectStage,
                                              int effectIdx) {
    uint32_t totalKey = fTransforms[effectIdx].fTransformKey;
    int texCoordIndex = fTransforms[effectIdx].fTexCoordIndex;
    int numTransforms = effectStage.getEffect()->numTransforms();
    for (int t = 0; t < numTransforms; ++t) {
        switch (get_matrix_type(totalKey, t)) {
            case kNoPersp_MatrixType: {
                const SkMatrix& transform = get_transform_matrix(effectStage, false, t);
                gpu->glPathRendering()->enablePathTexGen(
                        texCoordIndex++,
                        GrGLPathRendering::kST_PathTexGenComponents,
                        transform);
                break;
            }
            case kGeneral_MatrixType: {
                const SkMatrix& transform = get_transform_matrix(effectStage, false, t);
                gpu->glPathRendering()->enablePathTexGen(
                        texCoordIndex++,
                        GrGLPathRendering::kSTR_PathTexGenComponents,
                        transform);
                break;
            }
            default:
                SkFAIL("Unexpected matrixs type.");
        }
    }
}

GrGLPathTexGenProgramEffectsBuilder::GrGLPathTexGenProgramEffectsBuilder(
        GrGLFragmentOnlyProgramBuilder* builder,
        int reserveCount)
    : fBuilder(builder)
    , fProgramEffects(SkNEW_ARGS(GrGLPathTexGenProgramEffects, (reserveCount))) {
}
void GrGLPathTexGenProgramEffectsBuilder::emitEffect(const GrEffectStage& stage,
                                                     const GrEffectKey& key,
                                                     const char* outColor,
                                                     const char* inColor,
                                                     int stageIndex) {
    SkASSERT(fProgramEffects.get());
    fProgramEffects->emitEffect(fBuilder, stage, key, outColor, inColor, stageIndex);
}

