1 /*
2  * Copyright 2015 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #include "GrGLSLFragmentProcessor.h"
9 #include "GrFragmentProcessor.h"
10 #include "GrProcessor.h"
11 #include "glsl/GrGLSLFragmentShaderBuilder.h"
12 #include "glsl/GrGLSLUniformHandler.h"
13 
setData(const GrGLSLProgramDataManager & pdman,const GrFragmentProcessor & processor)14 void GrGLSLFragmentProcessor::setData(const GrGLSLProgramDataManager& pdman,
15                                       const GrFragmentProcessor& processor) {
16     this->onSetData(pdman, processor);
17 }
18 
emitChild(int childIndex,const char * inputColor,EmitArgs & args)19 void GrGLSLFragmentProcessor::emitChild(int childIndex, const char* inputColor, EmitArgs& args) {
20     this->internalEmitChild(childIndex, inputColor, args.fOutputColor, args);
21 }
22 
emitChild(int childIndex,const char * inputColor,SkString * outputColor,EmitArgs & args)23 void GrGLSLFragmentProcessor::emitChild(int childIndex, const char* inputColor,
24                                         SkString* outputColor, EmitArgs& args) {
25     SkASSERT(outputColor);
26     GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
27     outputColor->append(fragBuilder->getMangleString());
28     fragBuilder->codeAppendf("half4 %s;", outputColor->c_str());
29     this->internalEmitChild(childIndex, inputColor, outputColor->c_str(), args);
30 }
31 
internalEmitChild(int childIndex,const char * inputColor,const char * outputColor,EmitArgs & args)32 void GrGLSLFragmentProcessor::internalEmitChild(int childIndex, const char* inputColor,
33                                                 const char* outputColor, EmitArgs& args) {
34     GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
35 
36     fragBuilder->onBeforeChildProcEmitCode();  // call first so mangleString is updated
37 
38     // Prepare a mangled input color variable if the default is not used,
39     // inputName remains the empty string if no variable is needed.
40     SkString inputName;
41     if (inputColor&& strcmp("half4(1.0)", inputColor) != 0 && strcmp("half4(1)", inputColor) != 0) {
42         // The input name is based off of the current mangle string, and
43         // since this is called after onBeforeChildProcEmitCode(), it will be
44         // unique to the child processor (exactly what we want for its input).
45         inputName.appendf("_childInput%s", fragBuilder->getMangleString().c_str());
46         fragBuilder->codeAppendf("half4 %s = %s;", inputName.c_str(), inputColor);
47     }
48 
49     const GrFragmentProcessor& childProc = args.fFp.childProcessor(childIndex);
50 
51     // emit the code for the child in its own scope
52     fragBuilder->codeAppend("{\n");
53     fragBuilder->codeAppendf("// Child Index %d (mangle: %s): %s\n", childIndex,
54                              fragBuilder->getMangleString().c_str(), childProc.name());
55     TransformedCoordVars coordVars = args.fTransformedCoords.childInputs(childIndex);
56     TextureSamplers textureSamplers = args.fTexSamplers.childInputs(childIndex);
57 
58     // EmitArgs properly updates inputColor to half4(1) if it was null
59     EmitArgs childArgs(fragBuilder,
60                        args.fUniformHandler,
61                        args.fShaderCaps,
62                        childProc,
63                        outputColor,
64                        inputName.size() > 0 ? inputName.c_str() : nullptr,
65                        coordVars,
66                        textureSamplers);
67     this->childProcessor(childIndex)->emitCode(childArgs);
68     fragBuilder->codeAppend("}\n");
69 
70     fragBuilder->onAfterChildProcEmitCode();
71 }
72 
73 //////////////////////////////////////////////////////////////////////////////
74 
next()75 GrGLSLFragmentProcessor* GrGLSLFragmentProcessor::Iter::next() {
76     if (fFPStack.empty()) {
77         return nullptr;
78     }
79     GrGLSLFragmentProcessor* back = fFPStack.back();
80     fFPStack.pop_back();
81     for (int i = back->numChildProcessors() - 1; i >= 0; --i) {
82         fFPStack.push_back(back->childProcessor(i));
83     }
84     return back;
85 }
86