diff --git a/include/gpu/GrFragmentProcessor.h b/include/gpu/GrFragmentProcessor.h index 8d2a4d42b1..f08d3656b7 100644 --- a/include/gpu/GrFragmentProcessor.h +++ b/include/gpu/GrFragmentProcessor.h @@ -25,7 +25,9 @@ class GrFragmentProcessor : public GrProcessor { public: GrFragmentProcessor() : INHERITED() - , fUsesLocalCoords(false) {} + , fUsesLocalCoords(false) + , fNumTexturesExclChildren(0) + , fNumTransformsExclChildren(0) {} GrGLFragmentProcessor* createGLInstance() const; @@ -40,6 +42,10 @@ public: } } + int numTexturesExclChildren() const { return fNumTexturesExclChildren; } + + int numTransformsExclChildren() const { return fNumTransformsExclChildren; } + int numTransforms() const { return fCoordTransforms.count(); } /** Returns the coordinate transformation at index. index must be valid according to @@ -84,6 +90,8 @@ public: void computeInvariantOutput(GrInvariantOutput* inout) const; protected: + void addTextureAccess(const GrTextureAccess* textureAccess) override; + /** * Fragment Processor subclasses call this from their constructor to register coordinate * transformations. Coord transforms provide a mechanism for a processor to receive coordinates @@ -105,7 +113,8 @@ protected: /** * FragmentProcessor subclasses call this from their constructor to register any child - * FragmentProcessors they have. + * FragmentProcessors they have. This must be called AFTER all texture accesses and coord + * transforms have been added. * This is for processors whose shader code will be composed of nested processors whose output * colors will be combined somehow to produce its output color. Registering these child * processors will allow the ProgramBuilder to automatically handle their transformed coords and @@ -168,6 +177,9 @@ private: */ SkSTArray<4, const GrCoordTransform*, true> fCoordTransforms; + int fNumTexturesExclChildren; + int fNumTransformsExclChildren; + SkTArray fChildProcessors; typedef GrProcessor INHERITED; diff --git a/include/gpu/GrProcessor.h b/include/gpu/GrProcessor.h index 29d648cec8..c1f4aa0256 100644 --- a/include/gpu/GrProcessor.h +++ b/include/gpu/GrProcessor.h @@ -101,7 +101,7 @@ protected: * GrTextureAccess is typically a member field of the GrProcessor subclass. This must only be * called from the constructor because GrProcessors are immutable. */ - void addTextureAccess(const GrTextureAccess* textureAccess); + virtual void addTextureAccess(const GrTextureAccess* textureAccess); bool hasSameTextureAccesses(const GrProcessor&) const; diff --git a/src/gpu/GrProcessor.cpp b/src/gpu/GrProcessor.cpp index 0eaab75b61..6716ab1d12 100644 --- a/src/gpu/GrProcessor.cpp +++ b/src/gpu/GrProcessor.cpp @@ -166,10 +166,24 @@ GrGLFragmentProcessor* GrFragmentProcessor::createGLInstance() const { return glFragProc; } +void GrFragmentProcessor::addTextureAccess(const GrTextureAccess* textureAccess) { + // Can't add texture accesses after registering any children since their texture accesses have + // already been bubbled up into our fTextureAccesses array + SkASSERT(fChildProcessors.empty()); + + INHERITED::addTextureAccess(textureAccess); + fNumTexturesExclChildren++; +} + void GrFragmentProcessor::addCoordTransform(const GrCoordTransform* transform) { + // Can't add transforms after registering any children since their transforms have already been + // bubbled up into our fCoordTransforms array + SkASSERT(fChildProcessors.empty()); + fCoordTransforms.push_back(transform); fUsesLocalCoords = fUsesLocalCoords || transform->sourceCoords() == kLocal_GrCoordSet; SkDEBUGCODE(transform->setInProcessor();) + fNumTransformsExclChildren++; } int GrFragmentProcessor::registerChildProcessor(const GrFragmentProcessor* child) { diff --git a/src/gpu/gl/GrGLFragmentProcessor.cpp b/src/gpu/gl/GrGLFragmentProcessor.cpp index d2902c26ac..078491a5bf 100644 --- a/src/gpu/gl/GrGLFragmentProcessor.cpp +++ b/src/gpu/gl/GrGLFragmentProcessor.cpp @@ -32,8 +32,8 @@ void GrGLFragmentProcessor::emitChild(int childIndex, const char* inputColor, /* * 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 must do a - * backwards linear search on coords and samplers. + * 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 @@ -53,23 +53,20 @@ void GrGLFragmentProcessor::emitChild(int childIndex, const char* inputColor, * (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 B, we want the - * EmitArgs that's passed onto B to only contain its and its descendants' coords. The + * 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 [b1,b2,c1] to pass on to B. We can do this with a backwards linear - * search since we know that D's subtree has 6 transforms and B's subtree has 3 transforms (by - * calling D.numTextures() and B.numTextures()), so we know the start of B's transforms is 9 - * from the end of A's transforms. We cannot do this with a forwards linear search since we - * don't know how many transforms belong to A (A.numTextures() will return 10, not 1), so - * we wouldn't know how many transforms to initially skip in A's array if using a forward linear - * search. + * 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.numTransforms(); - int firstSamplerAt = args.fFp.numTextures(); - for (int i = args.fFp.numChildProcessors() - 1; i >= childIndex; --i) { - firstCoordAt -= args.fFp.childProcessor(i).numTransforms(); - firstSamplerAt -= args.fFp.childProcessor(i).numTextures(); + 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;