Index: src/gpu/glsl/GrGLSLFragmentProcessor.h |
diff --git a/src/gpu/glsl/GrGLSLFragmentProcessor.h b/src/gpu/glsl/GrGLSLFragmentProcessor.h |
index 9889bcc9c64546498323714b09bcd53ff1718237..d2f00f8b336cd531ccdc2daed1aad3062d594e1a 100644 |
--- a/src/gpu/glsl/GrGLSLFragmentProcessor.h |
+++ b/src/gpu/glsl/GrGLSLFragmentProcessor.h |
@@ -33,30 +33,49 @@ public: |
typedef GrGLSLProgramDataManager::UniformHandle UniformHandle; |
typedef GrGLSLProgramDataManager::UniformHandle SamplerHandle; |
+private: |
/** |
- * When building a program from a GrPipeline this is used to provide the GrShaderVars that |
- * contain the resulting transformed coords from each of a GrFragmentProcessor's |
- * GrCoordTransforms. This allows the GrFragmentProcessor subclasses to refer to the transformed |
- * coords in fragment code. |
+ * This class allows the shader builder to provide each GrGLSLFragmentProcesor with an array of |
+ * generated variables where each generated variable corresponds to an element of an array on |
+ * the GrFragmentProcessor that generated the GLSLFP. For example, this is used to provide a |
+ * variable holding transformed coords for each GrCoordTransform owned by the FP. |
*/ |
- class TransformedCoordVars { |
+ template <typename T, typename FPBASE, int (FPBASE::*COUNT)() const> |
+ class BuilderInputProvider { |
public: |
- TransformedCoordVars(const GrFragmentProcessor* fp, const GrShaderVar* vars) |
- : fFP(fp) |
- , fTransformedVars(vars) {} |
+ BuilderInputProvider(const GrFragmentProcessor* fp, const T* ts) : fFP(fp) , fTs(ts) {} |
- const GrShaderVar& operator[] (int i) const { |
- SkASSERT(i >= 0 && i < fFP->numCoordTransforms()); |
- return fTransformedVars[i]; |
+ const T& operator[] (int i) const { |
+ SkASSERT(i >= 0 && i < (fFP->*COUNT)()); |
+ return fTs[i]; |
} |
- TransformedCoordVars childTransforms(int childIdx) const; |
+ BuilderInputProvider childInputs(int childIdx) const { |
+ const GrFragmentProcessor* child = &fFP->childProcessor(childIdx); |
+ GrFragmentProcessor::Iter iter(fFP); |
+ int numToSkip = 0; |
+ while (true) { |
+ const GrFragmentProcessor* fp = iter.next(); |
+ if (fp == child) { |
+ return BuilderInputProvider(child, fTs + numToSkip); |
+ } |
+ numToSkip += (fp->*COUNT)(); |
+ } |
+ } |
private: |
const GrFragmentProcessor* fFP; |
- const GrShaderVar* fTransformedVars; |
+ const T* fTs; |
}; |
+public: |
+ using TransformedCoordVars = BuilderInputProvider<GrShaderVar, GrFragmentProcessor, |
+ &GrFragmentProcessor::numCoordTransforms>; |
+ using TextureSamplers = BuilderInputProvider<SamplerHandle, GrProcessor, |
+ &GrProcessor::numTextures>; |
+ using BufferSamplers = BuilderInputProvider<SamplerHandle, GrProcessor, |
+ &GrProcessor::numBuffers>; |
+ |
/** Called when the program stage should insert its code into the shaders. The code in each |
shader will be in its own block ({}) and so locally scoped names will not collide across |
stages. |
@@ -90,8 +109,8 @@ public: |
const char* outputColor, |
const char* inputColor, |
const TransformedCoordVars& transformedCoordVars, |
- const SamplerHandle* texSamplers, |
- const SamplerHandle* bufferSamplers, |
+ const TextureSamplers& textureSamplers, |
+ const BufferSamplers& bufferSamplers, |
bool gpImplementsDistanceVector) |
: fFragBuilder(fragBuilder) |
, fUniformHandler(uniformHandler) |
@@ -100,7 +119,7 @@ public: |
, fOutputColor(outputColor) |
, fInputColor(inputColor) |
, fTransformedCoords(transformedCoordVars) |
- , fTexSamplers(texSamplers) |
+ , fTexSamplers(textureSamplers) |
, fBufferSamplers(bufferSamplers) |
, fGpImplementsDistanceVector(gpImplementsDistanceVector) {} |
GrGLSLFPFragmentBuilder* fFragBuilder; |
@@ -110,8 +129,8 @@ public: |
const char* fOutputColor; |
const char* fInputColor; |
const TransformedCoordVars& fTransformedCoords; |
- const SamplerHandle* fTexSamplers; |
- const SamplerHandle* fBufferSamplers; |
+ const TextureSamplers& fTexSamplers; |
+ const BufferSamplers& fBufferSamplers; |
bool fGpImplementsDistanceVector; |
}; |
@@ -123,7 +142,7 @@ public: |
int numChildProcessors() const { return fChildProcessors.count(); } |
- GrGLSLFragmentProcessor* childProcessor(int index) const { |
+ GrGLSLFragmentProcessor* childProcessor(int index) { |
return fChildProcessors[index]; |
} |
@@ -141,6 +160,24 @@ public: |
/** Variation that uses the parent's output color variable to hold the child's output.*/ |
void emitChild(int childIndex, const char* inputColor, EmitArgs& parentArgs); |
+ /** |
+ * Pre-order traversal of a GLSLFP hierarchy, or of multiple trees with roots in an array of |
+ * GLSLFPS. This agrees with the traversal order of GrFragmentProcessor::Iter |
+ */ |
+ class Iter : public SkNoncopyable { |
+ public: |
+ explicit Iter(GrGLSLFragmentProcessor* fp) { fFPStack.push_back(fp); } |
+ explicit Iter(GrGLSLFragmentProcessor* fps[], int cnt) { |
+ for (int i = cnt - 1; i >= 0; --i) { |
+ fFPStack.push_back(fps[i]); |
+ } |
+ } |
+ GrGLSLFragmentProcessor* next(); |
+ |
+ private: |
+ SkSTArray<4, GrGLSLFragmentProcessor*, true> fFPStack; |
+ }; |
+ |
protected: |
/** A GrGLSLFragmentProcessor instance can be reused with any GrFragmentProcessor that produces |
the same stage key; this function reads data from a GrFragmentProcessor and uploads any |