added emitChild() to GrGLFragmentProcessor; removed AutoFragmentChildProcAdvance class

BUG=skia:4182

Review URL: https://codereview.chromium.org/1301523003
This commit is contained in:
wangyix 2015-08-18 12:00:12 -07:00 committed by Commit bot
parent f39c9b2ccf
commit 2a378433eb
4 changed files with 82 additions and 113 deletions

View File

@ -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();
}

View File

@ -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

View File

@ -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();
}

View File

@ -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