| wangyix | b1daa86 | 2015-08-18 11:29:31 -0700 | [diff] [blame] | 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 |  | 
| egdaniel | 64c4728 | 2015-11-13 06:54:19 -0800 | [diff] [blame] | 8 | #include "GrGLSLFragmentProcessor.h" | 
| wangyix | b1daa86 | 2015-08-18 11:29:31 -0700 | [diff] [blame] | 9 | #include "GrFragmentProcessor.h" | 
| egdaniel | 7dc4bd0 | 2015-10-29 07:57:01 -0700 | [diff] [blame] | 10 | #include "GrProcessor.h" | 
| egdaniel | 2d721d3 | 2015-11-11 13:06:05 -0800 | [diff] [blame] | 11 | #include "glsl/GrGLSLFragmentShaderBuilder.h" | 
| egdaniel | 7ea439b | 2015-12-03 09:20:44 -0800 | [diff] [blame] | 12 | #include "glsl/GrGLSLUniformHandler.h" | 
| wangyix | b1daa86 | 2015-08-18 11:29:31 -0700 | [diff] [blame] | 13 |  | 
| egdaniel | 64c4728 | 2015-11-13 06:54:19 -0800 | [diff] [blame] | 14 | void GrGLSLFragmentProcessor::setData(const GrGLSLProgramDataManager& pdman, | 
 | 15 |                                       const GrFragmentProcessor& processor) { | 
| wangyix | b1daa86 | 2015-08-18 11:29:31 -0700 | [diff] [blame] | 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 | } | 
| wangyix | 2a37843 | 2015-08-18 12:00:12 -0700 | [diff] [blame] | 22 |  | 
| egdaniel | 64c4728 | 2015-11-13 06:54:19 -0800 | [diff] [blame] | 23 | void GrGLSLFragmentProcessor::emitChild(int childIndex, const char* inputColor, EmitArgs& args) { | 
| bsalomon | 38ddbad | 2015-09-24 06:00:00 -0700 | [diff] [blame] | 24 |     this->internalEmitChild(childIndex, inputColor, args.fOutputColor, args); | 
 | 25 | } | 
 | 26 |  | 
| egdaniel | 64c4728 | 2015-11-13 06:54:19 -0800 | [diff] [blame] | 27 | void GrGLSLFragmentProcessor::emitChild(int childIndex, const char* inputColor, | 
| egdaniel | 4ca2e60 | 2015-11-18 08:01:26 -0800 | [diff] [blame] | 28 |                                         SkString* outputColor, EmitArgs& args) { | 
| bsalomon | 38ddbad | 2015-09-24 06:00:00 -0700 | [diff] [blame] | 29 |  | 
 | 30 |     SkASSERT(outputColor); | 
| cdalton | 8528541 | 2016-02-18 12:37:07 -0800 | [diff] [blame^] | 31 |     GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; | 
| egdaniel | 4ca2e60 | 2015-11-18 08:01:26 -0800 | [diff] [blame] | 32 |     outputColor->append(fragBuilder->getMangleString()); | 
 | 33 |     fragBuilder->codeAppendf("vec4 %s;", outputColor->c_str()); | 
| bsalomon | 38ddbad | 2015-09-24 06:00:00 -0700 | [diff] [blame] | 34 |     this->internalEmitChild(childIndex, inputColor, outputColor->c_str(), args); | 
 | 35 | } | 
 | 36 |  | 
| egdaniel | 64c4728 | 2015-11-13 06:54:19 -0800 | [diff] [blame] | 37 | void GrGLSLFragmentProcessor::internalEmitChild(int childIndex, const char* inputColor, | 
 | 38 |                                                 const char* outputColor, EmitArgs& args) { | 
| cdalton | 8528541 | 2016-02-18 12:37:07 -0800 | [diff] [blame^] | 39 |     GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; | 
| bsalomon | 38ddbad | 2015-09-24 06:00:00 -0700 | [diff] [blame] | 40 |  | 
| egdaniel | 4ca2e60 | 2015-11-18 08:01:26 -0800 | [diff] [blame] | 41 |     fragBuilder->onBeforeChildProcEmitCode();  // call first so mangleString is updated | 
| wangyix | 2a37843 | 2015-08-18 12:00:12 -0700 | [diff] [blame] | 42 |  | 
 | 43 |     const GrFragmentProcessor& childProc = args.fFp.childProcessor(childIndex); | 
 | 44 |  | 
| wangyix | 2a37843 | 2015-08-18 12:00:12 -0700 | [diff] [blame] | 45 |     /* | 
 | 46 |      * We now want to find the subset of coords and samplers that belong to the child and its | 
| wangyix | 93ab254 | 2015-08-19 08:23:12 -0700 | [diff] [blame] | 47 |      * descendants and put that into childCoords and childSamplers. To do so, we'll do a forwards | 
 | 48 |      * linear search. | 
| wangyix | 2a37843 | 2015-08-18 12:00:12 -0700 | [diff] [blame] | 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 |      * | 
| wangyix | 93ab254 | 2015-08-19 08:23:12 -0700 | [diff] [blame] | 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 | 
| wangyix | 2a37843 | 2015-08-18 12:00:12 -0700 | [diff] [blame] | 70 |      * EmitArgs given to A would contain the transforms [a1,b1,b2,c1,d1,e1,e2,e3,f1,f2], and we want | 
| wangyix | 93ab254 | 2015-08-19 08:23:12 -0700 | [diff] [blame] | 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. | 
| wangyix | 2a37843 | 2015-08-18 12:00:12 -0700 | [diff] [blame] | 75 |      * Textures work the same way as transforms. | 
 | 76 |      */ | 
| wangyix | 93ab254 | 2015-08-19 08:23:12 -0700 | [diff] [blame] | 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(); | 
| wangyix | 2a37843 | 2015-08-18 12:00:12 -0700 | [diff] [blame] | 82 |     } | 
| egdaniel | 7dc4bd0 | 2015-10-29 07:57:01 -0700 | [diff] [blame] | 83 |     GrGLSLTransformedCoordsArray childCoords; | 
| wangyix | 2a37843 | 2015-08-18 12:00:12 -0700 | [diff] [blame] | 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 | 
| egdaniel | 4ca2e60 | 2015-11-18 08:01:26 -0800 | [diff] [blame] | 93 |     fragBuilder->codeAppend("{\n"); | 
 | 94 |     fragBuilder->codeAppendf("// Child Index %d (mangle: %s): %s\n", childIndex, | 
 | 95 |                              fragBuilder->getMangleString().c_str(), childProc.name()); | 
| egdaniel | 7ea439b | 2015-12-03 09:20:44 -0800 | [diff] [blame] | 96 |     EmitArgs childArgs(fragBuilder, | 
 | 97 |                        args.fUniformHandler, | 
| egdaniel | a2e3e0f | 2015-11-19 07:23:45 -0800 | [diff] [blame] | 98 |                        args.fGLSLCaps, | 
| wangyix | 2a37843 | 2015-08-18 12:00:12 -0700 | [diff] [blame] | 99 |                        childProc, | 
| wangyix | 54a6b1a | 2015-09-08 08:41:51 -0700 | [diff] [blame] | 100 |                        outputColor, | 
| wangyix | 2a37843 | 2015-08-18 12:00:12 -0700 | [diff] [blame] | 101 |                        inputColor, | 
 | 102 |                        childCoords, | 
 | 103 |                        childSamplers); | 
 | 104 |     this->childProcessor(childIndex)->emitCode(childArgs); | 
| egdaniel | 4ca2e60 | 2015-11-18 08:01:26 -0800 | [diff] [blame] | 105 |     fragBuilder->codeAppend("}\n"); | 
| wangyix | 2a37843 | 2015-08-18 12:00:12 -0700 | [diff] [blame] | 106 |  | 
| egdaniel | 4ca2e60 | 2015-11-18 08:01:26 -0800 | [diff] [blame] | 107 |     fragBuilder->onAfterChildProcEmitCode(); | 
| wangyix | 2a37843 | 2015-08-18 12:00:12 -0700 | [diff] [blame] | 108 | } |