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

#include "GrGLSLFragmentProcessor.h"
#include "GrFragmentProcessor.h"
#include "GrProcessor.h"
#include "glsl/GrGLSLFragmentShaderBuilder.h"
#include "glsl/GrGLSLUniformHandler.h"

void GrGLSLFragmentProcessor::setData(const GrGLSLProgramDataManager& pdman,
                                      const GrFragmentProcessor& processor) {
    this->onSetData(pdman, processor);
    SkASSERT(fChildProcessors.count() == processor.numChildProcessors());
    for (int i = 0; i < fChildProcessors.count(); ++i) {
        fChildProcessors[i]->setData(pdman, processor.childProcessor(i));
    }
}

void GrGLSLFragmentProcessor::emitChild(int childIndex, const char* inputColor, EmitArgs& args) {
    this->internalEmitChild(childIndex, inputColor, args.fOutputColor, args);
}

void GrGLSLFragmentProcessor::emitChild(int childIndex, const char* inputColor,
                                        SkString* outputColor, EmitArgs& args) {

    SkASSERT(outputColor);
    GrGLSLFragmentBuilder* fragBuilder = args.fFragBuilder;
    outputColor->append(fragBuilder->getMangleString());
    fragBuilder->codeAppendf("vec4 %s;", outputColor->c_str());
    this->internalEmitChild(childIndex, inputColor, outputColor->c_str(), args);
}

void GrGLSLFragmentProcessor::internalEmitChild(int childIndex, const char* inputColor,
                                                const char* outputColor, EmitArgs& args) {
    GrGLSLFragmentBuilder* fragBuilder = args.fFragBuilder;

    fragBuilder->onBeforeChildProcEmitCode();  // call first so mangleString is updated

    const GrFragmentProcessor& childProc = args.fFp.childProcessor(childIndex);

    /*
     * We now want to find the subset of coords and samplers that belong to the child and its
     * descendants and put that into childCoords and childSamplers. To do so, we'll do a forwards
     * linear search.
     *
     * Explanation:
     * Each GrFragmentProcessor has a copy of all the transforms and textures of itself and
     * all procs in its subtree. For example, suppose we have frag proc A, who has two children B
     * and D. B has a child C, and D has two children E and F. Each frag proc's transforms array
     * contains its own transforms, followed by the transforms of all its descendants (i.e. preorder
     * traversal). Suppose procs A, B, C, D, E, F have 1, 2, 1, 1, 3, 2 transforms respectively.
     *
     *                                   (A)
     *                        [a1,b1,b2,c1,d1,e1,e2,e3,f1,f2]
     *                                  /    \
     *                                /        \
     *                            (B)           (D)
     *                        [b1,b2,c1]   [d1,e1,e2,e3,f1,f2]
     *                          /             /    \
     *                        /             /        \
     *                      (C)          (E)          (F)
     *                     [c1]      [e1,e2,e3]      [f1,f2]
     *
     * So if we're inside proc A's emitCode, and A is about to call emitCode on proc D, we want the
     * EmitArgs that's passed onto D to only contain its and its descendants' coords. The
     * EmitArgs given to A would contain the transforms [a1,b1,b2,c1,d1,e1,e2,e3,f1,f2], and we want
     * to extract the subset [d1,e1,e2,e3,f1,f2] to pass on to D. We can do this with a linear
     * search since we know that A has 1 transform (using A.numTransformsExclChildren()), and B's
     * subtree has 3 transforms (using B.numTransforms()), so we know the start of D's transforms is
     * 4 after the start of A's transforms.
     * Textures work the same way as transforms.
     */
    int firstCoordAt = args.fFp.numTransformsExclChildren();
    int firstSamplerAt = args.fFp.numTexturesExclChildren();
    for (int i = 0; i < childIndex; ++i) {
        firstCoordAt += args.fFp.childProcessor(i).numTransforms();
        firstSamplerAt += args.fFp.childProcessor(i).numTextures();
    }
    GrGLSLTransformedCoordsArray childCoords;
    TextureSamplerArray childSamplers;
    if (childProc.numTransforms() > 0) {
        childCoords.push_back_n(childProc.numTransforms(), &args.fCoords[firstCoordAt]);
    }
    if (childProc.numTextures() > 0) {
        childSamplers.push_back_n(childProc.numTextures(), &args.fSamplers[firstSamplerAt]);
    }

    // emit the code for the child in its own scope
    fragBuilder->codeAppend("{\n");
    fragBuilder->codeAppendf("// Child Index %d (mangle: %s): %s\n", childIndex,
                             fragBuilder->getMangleString().c_str(), childProc.name());
    EmitArgs childArgs(fragBuilder,
                       args.fUniformHandler,
                       args.fGLSLCaps,
                       childProc,
                       outputColor,
                       inputColor,
                       childCoords,
                       childSamplers);
    this->childProcessor(childIndex)->emitCode(childArgs);
    fragBuilder->codeAppend("}\n");

    fragBuilder->onAfterChildProcEmitCode();
}
