/*
 * 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 "GrGLFragmentProcessor.h"
#include "GrFragmentProcessor.h"
#include "builders/GrGLFragmentShaderBuilder.h"
#include "builders/GrGLProgramBuilder.h"

void GrGLFragmentProcessor::setData(const GrGLProgramDataManager& 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 GrGLFragmentProcessor::emitChild(int childIndex, const char* inputColor, EmitArgs& args) {
    this->internalEmitChild(childIndex, inputColor, args.fOutputColor, args);
}

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

    SkASSERT(outputColor);
    GrGLFragmentBuilder* fb = args.fBuilder->getFragmentShaderBuilder();
    outputColor->append(fb->getMangleString());
    fb->codeAppendf("vec4 %s;", outputColor->c_str());
    this->internalEmitChild(childIndex, inputColor, outputColor->c_str(), args);
}

void GrGLFragmentProcessor::internalEmitChild(int childIndex, const char* inputColor,
                                               const char* outputColor, EmitArgs& args) {
    GrGLFragmentBuilder* fb = args.fBuilder->getFragmentShaderBuilder();

    fb->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();
    }
    TransformedCoordsArray 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
    fb->codeAppend("{\n");
    fb->codeAppendf("// Child Index %d (mangle: %s): %s\n", childIndex,
                    fb->getMangleString().c_str(), childProc.name());
    EmitArgs childArgs(args.fBuilder,
                       childProc,
                       outputColor,
                       inputColor,
                       childCoords,
                       childSamplers);
    this->childProcessor(childIndex)->emitCode(childArgs);
    fb->codeAppend("}\n");

    fb->onAfterChildProcEmitCode();
}
