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 14 void GrGLSLFragmentProcessor::setData(const GrGLSLProgramDataManager& pdman, 15 const GrFragmentProcessor& processor) { 16 this->onSetData(pdman, processor); 17 SkASSERT(fChildProcessors.count() == processor.numChildProcessors()); 18 for (int i = 0; i < fChildProcessors.count(); ++i) { 19 fChildProcessors[i]->setData(pdman, processor.childProcessor(i)); 20 } 21 } 22 23 void GrGLSLFragmentProcessor::emitChild(int childIndex, const char* inputColor, EmitArgs& args) { 24 this->internalEmitChild(childIndex, inputColor, args.fOutputColor, args); 25 } 26 27 void GrGLSLFragmentProcessor::emitChild(int childIndex, const char* inputColor, 28 SkString* outputColor, EmitArgs& args) { 29 30 SkASSERT(outputColor); 31 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; 32 outputColor->append(fragBuilder->getMangleString()); 33 fragBuilder->codeAppendf("vec4 %s;", outputColor->c_str()); 34 this->internalEmitChild(childIndex, inputColor, outputColor->c_str(), args); 35 } 36 37 void GrGLSLFragmentProcessor::internalEmitChild(int childIndex, const char* inputColor, 38 const char* outputColor, EmitArgs& args) { 39 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; 40 41 fragBuilder->onBeforeChildProcEmitCode(); // call first so mangleString is updated 42 43 const GrFragmentProcessor& childProc = args.fFp.childProcessor(childIndex); 44 45 /* 46 * We now want to find the subset of coords and samplers that belong to the child and its 47 * descendants and put that into childCoords and childSamplers. To do so, we'll do a forwards 48 * linear search. 49 * 50 * Explanation: 51 * Each GrFragmentProcessor has a copy of all the transforms and textures of itself and 52 * all procs in its subtree. For example, suppose we have frag proc A, who has two children B 53 * and D. B has a child C, and D has two children E and F. Each frag proc's transforms array 54 * contains its own transforms, followed by the transforms of all its descendants (i.e. preorder 55 * traversal). Suppose procs A, B, C, D, E, F have 1, 2, 1, 1, 3, 2 transforms respectively. 56 * 57 * (A) 58 * [a1,b1,b2,c1,d1,e1,e2,e3,f1,f2] 59 * / \ 60 * / \ 61 * (B) (D) 62 * [b1,b2,c1] [d1,e1,e2,e3,f1,f2] 63 * / / \ 64 * / / \ 65 * (C) (E) (F) 66 * [c1] [e1,e2,e3] [f1,f2] 67 * 68 * So if we're inside proc A's emitCode, and A is about to call emitCode on proc D, we want the 69 * EmitArgs that's passed onto D to only contain its and its descendants' coords. The 70 * EmitArgs given to A would contain the transforms [a1,b1,b2,c1,d1,e1,e2,e3,f1,f2], and we want 71 * to extract the subset [d1,e1,e2,e3,f1,f2] to pass on to D. We can do this with a linear 72 * search since we know that A has 1 transform (using A.numTransformsExclChildren()), and B's 73 * subtree has 3 transforms (using B.numTransforms()), so we know the start of D's transforms is 74 * 4 after the start of A's transforms. 75 * Textures work the same way as transforms. 76 */ 77 int firstCoordAt = args.fFp.numTransformsExclChildren(); 78 int firstSamplerAt = args.fFp.numTexturesExclChildren(); 79 for (int i = 0; i < childIndex; ++i) { 80 firstCoordAt += args.fFp.childProcessor(i).numTransforms(); 81 firstSamplerAt += args.fFp.childProcessor(i).numTextures(); 82 } 83 GrGLSLTransformedCoordsArray childCoords; 84 TextureSamplerArray childSamplers; 85 if (childProc.numTransforms() > 0) { 86 childCoords.push_back_n(childProc.numTransforms(), &args.fCoords[firstCoordAt]); 87 } 88 if (childProc.numTextures() > 0) { 89 childSamplers.push_back_n(childProc.numTextures(), &args.fSamplers[firstSamplerAt]); 90 } 91 92 // emit the code for the child in its own scope 93 fragBuilder->codeAppend("{\n"); 94 fragBuilder->codeAppendf("// Child Index %d (mangle: %s): %s\n", childIndex, 95 fragBuilder->getMangleString().c_str(), childProc.name()); 96 EmitArgs childArgs(fragBuilder, 97 args.fUniformHandler, 98 args.fGLSLCaps, 99 childProc, 100 outputColor, 101 inputColor, 102 childCoords, 103 childSamplers); 104 this->childProcessor(childIndex)->emitCode(childArgs); 105 fragBuilder->codeAppend("}\n"); 106 107 fragBuilder->onAfterChildProcEmitCode(); 108 } 109