added emitChild() to GrGLFragmentProcessor; removed AutoFragmentChildProcAdvance class
BUG=skia:4182 Review URL: https://codereview.chromium.org/1301523003
This commit is contained in:
parent
f39c9b2ccf
commit
2a378433eb
@ -7,6 +7,8 @@
|
||||
|
||||
#include "GrGLFragmentProcessor.h"
|
||||
#include "GrFragmentProcessor.h"
|
||||
#include "builders/GrGLFragmentShaderBuilder.h"
|
||||
#include "builders/GrGLProgramBuilder.h"
|
||||
|
||||
void GrGLFragmentProcessor::setData(const GrGLProgramDataManager& pdman,
|
||||
const GrFragmentProcessor& processor) {
|
||||
@ -16,3 +18,81 @@ void GrGLFragmentProcessor::setData(const GrGLProgramDataManager& pdman,
|
||||
fChildProcessors[i]->setData(pdman, processor.childProcessor(i));
|
||||
}
|
||||
}
|
||||
|
||||
void GrGLFragmentProcessor::emitChild(int childIndex, const char* inputColor,
|
||||
SkString* outputColor, EmitArgs& args) {
|
||||
GrGLFragmentBuilder* fb = args.fBuilder->getFragmentShaderBuilder();
|
||||
fb->onBeforeChildProcEmitCode(); // call first so mangleString is updated
|
||||
|
||||
const GrFragmentProcessor& childProc = args.fFp.childProcessor(childIndex);
|
||||
|
||||
// Mangle the name of the outputColor
|
||||
outputColor->set(args.fOutputColor);
|
||||
outputColor->append(fb->getMangleStringThisLevel());
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* Explanation:
|
||||
* Each GrFragmentProcessor has a copy of all the transforms and textures of itself and
|
||||
* all procs in its subtree. For example, suppose we have frag proc A, who has two children B
|
||||
* and D. B has a child C, and D has two children E and F. Each frag proc's transforms array
|
||||
* contains its own transforms, followed by the transforms of all its descendants (i.e. preorder
|
||||
* traversal). Suppose procs A, B, C, D, E, F have 1, 2, 1, 1, 3, 2 transforms respectively.
|
||||
*
|
||||
* (A)
|
||||
* [a1,b1,b2,c1,d1,e1,e2,e3,f1,f2]
|
||||
* / \
|
||||
* / \
|
||||
* (B) (D)
|
||||
* [b1,b2,c1] [d1,e1,e2,e3,f1,f2]
|
||||
* / / \
|
||||
* / / \
|
||||
* (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
|
||||
* 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.
|
||||
* 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();
|
||||
}
|
||||
TransformedCoordsArray childCoords;
|
||||
TextureSamplerArray childSamplers;
|
||||
if (childProc.numTransforms() > 0) {
|
||||
childCoords.push_back_n(childProc.numTransforms(), &args.fCoords[firstCoordAt]);
|
||||
}
|
||||
if (childProc.numTextures() > 0) {
|
||||
childSamplers.push_back_n(childProc.numTextures(), &args.fSamplers[firstSamplerAt]);
|
||||
}
|
||||
|
||||
// emit the code for the child in its own scope
|
||||
fb->codeAppendf("vec4 %s;\n", outputColor->c_str());
|
||||
fb->codeAppend("{\n");
|
||||
fb->codeAppendf("// Child Index %d (mangle: %s): %s\n", childIndex,
|
||||
fb->getMangleString().c_str(), childProc.name());
|
||||
EmitArgs childArgs(args.fBuilder,
|
||||
childProc,
|
||||
outputColor->c_str(),
|
||||
inputColor,
|
||||
childCoords,
|
||||
childSamplers);
|
||||
this->childProcessor(childIndex)->emitCode(childArgs);
|
||||
fb->codeAppend("}\n");
|
||||
|
||||
fb->onAfterChildProcEmitCode();
|
||||
}
|
||||
|
@ -80,6 +80,8 @@ public:
|
||||
return fChildProcessors[index];
|
||||
}
|
||||
|
||||
void emitChild(int childIndex, const char* inputColor, SkString* outputColor, EmitArgs& args);
|
||||
|
||||
protected:
|
||||
/** A GrGLFragmentProcessor instance can be reused with any GrFragmentProcessor that produces
|
||||
the same stage key; this function reads data from a GrFragmentProcessor and uploads any
|
||||
|
@ -312,85 +312,3 @@ void GrGLFragmentBuilder::onAfterChildProcEmitCode() {
|
||||
int removeAt = fMangleString.findLastOf('_');
|
||||
fMangleString.remove(removeAt, fMangleString.size() - removeAt);
|
||||
}
|
||||
|
||||
GrGLFragmentBuilder::AutoFragmentChildProcAdvance::AutoFragmentChildProcAdvance(
|
||||
int childProcIndex,
|
||||
GrGLFPBuilder* builder,
|
||||
const GrFragmentProcessor& fp,
|
||||
const char* outputColor,
|
||||
const TransformedCoordsArray& coords,
|
||||
const TextureSamplerArray& samplers,
|
||||
const GrFragmentProcessor** childFp,
|
||||
SkString* childOutputColor,
|
||||
TransformedCoordsArray* childCoords,
|
||||
TextureSamplerArray* childSamplers
|
||||
) {
|
||||
fFsb = builder->getFragmentShaderBuilder();
|
||||
fFsb->onBeforeChildProcEmitCode(); // call first so mangleString is updated
|
||||
|
||||
const GrFragmentProcessor& childProc = fp.childProcessor(childProcIndex);
|
||||
*childFp = &childProc;
|
||||
|
||||
// Mangle the name of the outputColor
|
||||
childOutputColor->set(outputColor);
|
||||
childOutputColor->append(fFsb->getMangleStringThisLevel());
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* Explanation:
|
||||
* Each GrFragmentProcessor has a copy of all the transforms and textures of itself and
|
||||
* all procs in its subtree. For example, suppose we have frag proc A, who has two children B
|
||||
* and D. B has a child C, and D has two children E and F. Each frag proc's transforms array
|
||||
* contains its own transforms, followed by the transforms of all its descendants (i.e. preorder
|
||||
* traversal). Suppose procs A, B, C, D, E, F have 1, 2, 1, 1, 3, 2 transforms respectively.
|
||||
*
|
||||
* (A)
|
||||
* [a1,b1,b2,c1,d1,e1,e2,e3,f1,f2]
|
||||
* / \
|
||||
* / \
|
||||
* (B) (D)
|
||||
* [b1,b2,c1] [d1,e1,e2,e3,f1,f2]
|
||||
* / / \
|
||||
* / / \
|
||||
* (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
|
||||
* 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.
|
||||
* Textures work the same way as transforms.
|
||||
*/
|
||||
SkASSERT(childCoords->empty());
|
||||
SkASSERT(childSamplers->empty());
|
||||
int firstCoordAt = fp.numTransforms();
|
||||
int firstSamplerAt = fp.numTextures();
|
||||
for (int i = fp.numChildProcessors() - 1; i >= childProcIndex; --i) {
|
||||
firstCoordAt -= fp.childProcessor(i).numTransforms();
|
||||
firstSamplerAt -= fp.childProcessor(i).numTextures();
|
||||
}
|
||||
if (!coords.empty()) {
|
||||
childCoords->push_back_n(childProc.numTransforms(), &coords[firstCoordAt]);
|
||||
}
|
||||
if (!samplers.empty()) {
|
||||
childSamplers->push_back_n(childProc.numTextures(), &samplers[firstSamplerAt]);
|
||||
}
|
||||
|
||||
fFsb->codeAppendf("vec4 %s;\n", childOutputColor->c_str());
|
||||
fFsb->codeAppend("{\n");
|
||||
fFsb->codeAppendf("// Child %d: %s\n", fFsb->getChildNumberThisLevel(), childProc.name());
|
||||
}
|
||||
|
||||
GrGLFragmentBuilder::AutoFragmentChildProcAdvance::~AutoFragmentChildProcAdvance() {
|
||||
fFsb->codeAppend("}\n");
|
||||
fFsb->onAfterChildProcEmitCode();
|
||||
}
|
||||
|
@ -77,37 +77,6 @@ public:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* This class is like AutoStageAdvance but used for the child procs of a fragment proc.
|
||||
* Before a proc calls emitCode on one of its children, it should instantiate this
|
||||
* class inside its own scope. This which will update a state in GrGLFragmentBuilder that tracks
|
||||
* which proc in the tree is about to emit code (it does so by calling GrGLFragmentBuilder::
|
||||
* onBeforeChildProcEmitCode() in the constructor).
|
||||
*
|
||||
* After the child proc emitCode is called, the parent proc should end the scope so the
|
||||
* AutoFragmentChildProcAdvance destructor is called, which will again update a state in
|
||||
* GrGLFragmentShaderBuilder notifying it that the child proc's code has been emitted (it does
|
||||
* so by calling GrGLFragmentBuilder::onAfterChildProcEmitCode()).
|
||||
*/
|
||||
class AutoFragmentChildProcAdvance {
|
||||
typedef GrGLProcessor::TransformedCoordsArray TransformedCoordsArray;
|
||||
typedef GrGLProcessor::TextureSamplerArray TextureSamplerArray;
|
||||
public:
|
||||
AutoFragmentChildProcAdvance(int childProcIndex,
|
||||
GrGLFPBuilder* builder,
|
||||
const GrFragmentProcessor& fp,
|
||||
const char* outputColor,
|
||||
const TransformedCoordsArray& coords,
|
||||
const TextureSamplerArray& samplers,
|
||||
const GrFragmentProcessor** childFp,
|
||||
SkString* childOutputColor,
|
||||
TransformedCoordsArray* childCoords,
|
||||
TextureSamplerArray* childSamplers);
|
||||
|
||||
~AutoFragmentChildProcAdvance();
|
||||
private:
|
||||
GrGLFragmentBuilder* fFsb;
|
||||
};
|
||||
|
||||
private:
|
||||
/*
|
||||
* State that tracks which child proc in the proc tree is currently emitting code. This is
|
||||
|
Loading…
Reference in New Issue
Block a user