Stop flattening GrCoordTransforms in parent GrFragmentProcessors.

This changes moves to a model that iterates over GrCTs in a GrFP hierarchy when inserting transformations by GrGLSLPrimitiveProcessors.
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2339203002

Committed: https://skia.googlesource.com/skia/+/d91237ee051523f439238042674ade99207fe4a6
Review-Url: https://codereview.chromium.org/2339203002
This commit is contained in:
bsalomon 2016-09-20 09:12:47 -07:00 committed by Commit bot
parent be9d82161d
commit a624bf3d1c
27 changed files with 437 additions and 403 deletions

View File

@ -14,6 +14,7 @@ class GrCoordTransform;
class GrGLSLCaps;
class GrGLSLFragmentProcessor;
class GrInvariantOutput;
class GrPipeline;
class GrProcessorKeyBuilder;
/** Provides custom fragment shader code. Fragment processors receive an input color (vec4f) and
@ -68,8 +69,7 @@ public:
, fUsesDistanceVectorField(false)
, fUsesLocalCoords(false)
, fNumTexturesExclChildren(0)
, fNumBuffersExclChildren(0)
, fNumTransformsExclChildren(0) {}
, fNumBuffersExclChildren(0) {}
~GrFragmentProcessor() override;
@ -86,9 +86,7 @@ public:
int numBuffersExclChildren() const { return fNumBuffersExclChildren; }
int numTransformsExclChildren() const { return fNumTransformsExclChildren; }
int numTransforms() const { return fCoordTransforms.count(); }
int numCoordTransforms() const { return fCoordTransforms.count(); }
/** Returns the coordinate transformation at index. index must be valid according to
numTransforms(). */
@ -135,6 +133,40 @@ public:
this->onComputeInvariantOutput(inout);
}
/**
* Pre-order traversal of a FP hierarchy, or of the forest of FPs in a GrPipeline. In the latter
* case the tree rooted at each FP in the GrPipeline is visited successively.
* */
class Iter : public SkNoncopyable {
public:
explicit Iter(const GrFragmentProcessor* fp) { fFPStack.push_back(fp); }
explicit Iter(const GrPipeline& pipeline);
const GrFragmentProcessor* next();
private:
SkSTArray<4, const GrFragmentProcessor*, true> fFPStack;
};
/**
* Iterates over all the GrCoordTransforms in a GrPipeline's GrFragmentProcessors. FPs are
* visited in the same order as Iter and each of an FP's coord transforms are visited linearly.
*/
class CoordTransformIter : public SkNoncopyable {
public:
explicit CoordTransformIter(const GrPipeline& pipeline)
: fCurrFP(nullptr)
, fCTIdx(0)
, fFPIter(pipeline) {
fCurrFP = fFPIter.next();
}
const GrCoordTransform* next();
private:
const GrFragmentProcessor* fCurrFP;
int fCTIdx;
GrFragmentProcessor::Iter fFPIter;
};
protected:
void addTextureAccess(const GrTextureAccess* textureAccess) override;
void addBufferAccess(const GrBufferAccess*) override;
@ -206,15 +238,18 @@ private:
bool fUsesLocalCoords;
SkSTArray<4, const GrCoordTransform*, true> fCoordTransforms;
/**
* fCoordTransforms stores the transforms of this proc, followed by all the transforms of this
* proc's children. In other words, each proc stores all the transforms of its subtree as if
* A processor stores the texture accesses of this proc, followed by all the accesses of this
* proc's children. In other words, each proc stores all the accesses of its subtree as if
* they were collected using preorder traversal.
*
* 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. Suppose procs A, B, C, D, E, F have 1, 2, 1, 1, 3, 2 transforms
* respectively. The following shows what the fCoordTransforms array of each proc would contain:
* two children E and F. Suppose procs A, B, C, D, E, F have 1, 2, 1, 1, 3, 2 accesses
* respectively. The following shows what the array of each proc's texture accesses would
* contain:
*
* (A)
* [a1,b1,b2,c1,d1,e1,e2,e3,f1,f2]
@ -227,12 +262,10 @@ private:
* (C) (E) (F)
* [c1] [e1,e2,e3] [f1,f2]
*
* The same goes for fTextureAccesses with textures.
* The same goes for buffer accesses.
*/
SkSTArray<4, const GrCoordTransform*, true> fCoordTransforms;
int fNumTexturesExclChildren;
int fNumBuffersExclChildren;
int fNumTransformsExclChildren;
/**
* This is not SkSTArray<1, sk_sp<GrFragmentProcessor>> because this class holds strong

View File

@ -99,8 +99,7 @@ public:
gpArgs->fPositionVar,
gp.inLocalCoords()->fName,
gp.localMatrix(),
args.fTransformsIn,
args.fTransformsOut);
args.fFPCoordTransformHandler);
} else {
// emit transforms with position
this->emitTransforms(vertBuilder,
@ -109,8 +108,7 @@ public:
gpArgs->fPositionVar,
gp.inPosition()->fName,
gp.localMatrix(),
args.fTransformsIn,
args.fTransformsOut);
args.fFPCoordTransformHandler);
}
// Setup coverage as pass through
@ -150,7 +148,8 @@ public:
}
void setData(const GrGLSLProgramDataManager& pdman,
const GrPrimitiveProcessor& gp) override {
const GrPrimitiveProcessor& gp,
FPCoordTransformIter&& transformIter) override {
const DefaultGeoProc& dgp = gp.cast<DefaultGeoProc>();
if (!dgp.viewMatrix().isIdentity() && !fViewMatrix.cheapEqualTo(dgp.viewMatrix())) {
@ -172,14 +171,7 @@ public:
pdman.set1f(fCoverageUniform, GrNormalizeByteToFloat(dgp.coverage()));
fCoverage = dgp.coverage();
}
}
void setTransformData(const GrPrimitiveProcessor& primProc,
const GrGLSLProgramDataManager& pdman,
int index,
const SkTArray<const GrCoordTransform*, true>& transforms) override {
this->setTransformDataHelper(primProc.cast<DefaultGeoProc>().fLocalMatrix, pdman, index,
transforms);
this->setTransformDataHelper(dgp.fLocalMatrix, pdman, &transformIter);
}
private:

View File

@ -8,6 +8,7 @@
#include "GrFragmentProcessor.h"
#include "GrCoordTransform.h"
#include "GrInvariantOutput.h"
#include "GrPipeline.h"
#include "GrProcOptInfo.h"
#include "glsl/GrGLSLFragmentProcessor.h"
#include "glsl/GrGLSLFragmentShaderBuilder.h"
@ -81,16 +82,10 @@ void GrFragmentProcessor::addCoordTransform(const GrCoordTransform* transform) {
fCoordTransforms.push_back(transform);
fUsesLocalCoords = fUsesLocalCoords || transform->sourceCoords() == kLocal_GrCoordSet;
SkDEBUGCODE(transform->setInProcessor();)
fNumTransformsExclChildren++;
}
int GrFragmentProcessor::registerChildProcessor(sk_sp<GrFragmentProcessor> child) {
// Append the child's transforms to our transforms array and the child's textures array to our
// textures array
if (!child->fCoordTransforms.empty()) {
fCoordTransforms.push_back_n(child->fCoordTransforms.count(),
child->fCoordTransforms.begin());
}
// Append the child's textures array to our textures array
if (!child->fTextureAccesses.empty()) {
fTextureAccesses.push_back_n(child->fTextureAccesses.count(),
child->fTextureAccesses.begin());
@ -120,10 +115,10 @@ void GrFragmentProcessor::notifyRefCntIsZero() const {
}
bool GrFragmentProcessor::hasSameTransforms(const GrFragmentProcessor& that) const {
if (this->numTransforms() != that.numTransforms()) {
if (this->numCoordTransforms() != that.numCoordTransforms()) {
return false;
}
int count = this->numTransforms();
int count = this->numCoordTransforms();
for (int i = 0; i < count; ++i) {
if (this->coordTransform(i) != that.coordTransform(i)) {
return false;
@ -408,3 +403,39 @@ sk_sp<GrFragmentProcessor> GrFragmentProcessor::RunInSeries(sk_sp<GrFragmentProc
}
return sk_sp<GrFragmentProcessor>(new SeriesFragmentProcessor(series, cnt));
}
//////////////////////////////////////////////////////////////////////////////
GrFragmentProcessor::Iter::Iter(const GrPipeline& pipeline) {
for (int i = pipeline.numFragmentProcessors() - 1; i >= 0; --i) {
fFPStack.push_back(&pipeline.getFragmentProcessor(i));
}
}
const GrFragmentProcessor* GrFragmentProcessor::Iter::next() {
if (fFPStack.empty()) {
return nullptr;
}
const GrFragmentProcessor* back = fFPStack.back();
fFPStack.pop_back();
for (int i = back->numChildProcessors() - 1; i >= 0; --i) {
fFPStack.push_back(&back->childProcessor(i));
}
return back;
}
//////////////////////////////////////////////////////////////////////////////
const GrCoordTransform* GrFragmentProcessor::CoordTransformIter::next() {
if (!fCurrFP) {
return nullptr;
}
while (fCTIdx == fCurrFP->numCoordTransforms()) {
fCTIdx = 0;
fCurrFP = fFPIter.next();
if (!fCurrFP) {
return nullptr;
}
}
return &fCurrFP->coordTransform(fCTIdx++);
}

View File

@ -161,8 +161,7 @@ private:
gpArgs->fPositionVar,
cgp.fInPosition->fName,
cgp.fLocalMatrix,
args.fTransformsIn,
args.fTransformsOut);
args.fFPCoordTransformHandler);
fragBuilder->codeAppend("float d = length(circleEdge.xy);");
fragBuilder->codeAppend("float distanceToOuterEdge = circleEdge.z * (1.0 - d);");
@ -210,14 +209,10 @@ private:
b->add32(key);
}
void setData(const GrGLSLProgramDataManager&, const GrPrimitiveProcessor&) override {}
void setTransformData(const GrPrimitiveProcessor& primProc,
const GrGLSLProgramDataManager& pdman,
int index,
const SkTArray<const GrCoordTransform*, true>& transforms) override {
void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor& primProc,
FPCoordTransformIter&& transformIter) override {
this->setTransformDataHelper(primProc.cast<CircleGeometryProcessor>().fLocalMatrix,
pdman, index, transforms);
pdman, &transformIter);
}
private:
@ -319,8 +314,7 @@ private:
gpArgs->fPositionVar,
egp.fInPosition->fName,
egp.fLocalMatrix,
args.fTransformsIn,
args.fTransformsOut);
args.fFPCoordTransformHandler);
// for outer curve
fragBuilder->codeAppendf("vec2 scaledOffset = %s*%s.xy;", ellipseOffsets.fsIn(),
@ -357,15 +351,10 @@ private:
b->add32(key);
}
void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor& gp) override {
}
void setTransformData(const GrPrimitiveProcessor& primProc,
const GrGLSLProgramDataManager& pdman,
int index,
const SkTArray<const GrCoordTransform*, true>& transforms) override {
this->setTransformDataHelper(primProc.cast<EllipseGeometryProcessor>().fLocalMatrix,
pdman, index, transforms);
void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor& primProc,
FPCoordTransformIter&& transformIter) override {
const EllipseGeometryProcessor& egp = primProc.cast<EllipseGeometryProcessor>();
this->setTransformDataHelper(egp.fLocalMatrix, pdman, &transformIter);
}
private:
@ -472,8 +461,7 @@ private:
uniformHandler,
gpArgs->fPositionVar,
diegp.fInPosition->fName,
args.fTransformsIn,
args.fTransformsOut);
args.fFPCoordTransformHandler);
SkAssertResult(fragBuilder->enableFeature(
GrGLSLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature));
@ -525,8 +513,8 @@ private:
b->add32(key);
}
void setData(const GrGLSLProgramDataManager& pdman,
const GrPrimitiveProcessor& gp) override {
void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor& gp,
FPCoordTransformIter&& transformIter) override {
const DIEllipseGeometryProcessor& diegp = gp.cast<DIEllipseGeometryProcessor>();
if (!diegp.fViewMatrix.isIdentity() && !fViewMatrix.cheapEqualTo(diegp.fViewMatrix)) {
@ -535,6 +523,7 @@ private:
GrGLSLGetMatrix<3>(viewMatrix, fViewMatrix);
pdman.setMatrix3f(fViewMatrixUniform, viewMatrix);
}
this->setTransformDataHelper(SkMatrix::I(), pdman, &transformIter);
}
private:

View File

@ -34,7 +34,7 @@ public:
}
// emit transforms
this->emitTransforms(args.fVaryingHandler, args.fTransformsIn, args.fTransformsOut);
this->emitTransforms(args.fVaryingHandler, args.fFPCoordTransformHandler);
// Setup uniform color
if (pathProc.overrides().readsColor()) {
@ -54,34 +54,30 @@ public:
}
void emitTransforms(GrGLSLVaryingHandler* varyingHandler,
const TransformsIn& tin,
TransformsOut* tout) {
tout->push_back_n(tin.count());
fInstalledTransforms.push_back_n(tin.count());
for (int i = 0; i < tin.count(); i++) {
const ProcCoords& coordTransforms = tin[i];
fInstalledTransforms[i].push_back_n(coordTransforms.count());
for (int t = 0; t < coordTransforms.count(); t++) {
GrSLType varyingType =
coordTransforms[t]->getMatrix().hasPerspective() ? kVec3f_GrSLType :
kVec2f_GrSLType;
FPCoordTransformHandler* transformHandler) {
int i = 0;
while (const GrCoordTransform* coordTransform = transformHandler->nextCoordTransform()) {
GrSLType varyingType =
coordTransform->getMatrix().hasPerspective() ? kVec3f_GrSLType
: kVec2f_GrSLType;
SkString strVaryingName("MatrixCoord");
strVaryingName.appendf("_%i_%i", i, t);
GrGLSLVertToFrag v(varyingType);
GrGLVaryingHandler* glVaryingHandler = (GrGLVaryingHandler*) varyingHandler;
fInstalledTransforms[i][t].fHandle =
glVaryingHandler->addPathProcessingVarying(strVaryingName.c_str(),
&v).toIndex();
fInstalledTransforms[i][t].fType = varyingType;
SkString strVaryingName;
strVaryingName.printf("TransformedCoord_%d", i);
GrGLSLVertToFrag v(varyingType);
GrGLVaryingHandler* glVaryingHandler = (GrGLVaryingHandler*) varyingHandler;
fInstalledTransforms.push_back().fHandle =
glVaryingHandler->addPathProcessingVarying(strVaryingName.c_str(),
&v).toIndex();
fInstalledTransforms.back().fType = varyingType;
(*tout)[i].emplace_back(SkString(v.fsIn()), varyingType);
}
transformHandler->specifyCoordsForCurrCoordTransform(SkString(v.fsIn()), varyingType);
++i;
}
}
void setData(const GrGLSLProgramDataManager& pd,
const GrPrimitiveProcessor& primProc) override {
const GrPrimitiveProcessor& primProc,
FPCoordTransformIter&& transformIter) override {
const GrPathProcessor& pathProc = primProc.cast<GrPathProcessor>();
if (pathProc.overrides().readsColor() && pathProc.color() != fColor) {
float c[4];
@ -89,28 +85,21 @@ public:
pd.set4fv(fColorUniform, 1, c);
fColor = pathProc.color();
}
}
void setTransformData(const GrPrimitiveProcessor& primProc,
const GrGLSLProgramDataManager& pdman,
int index,
const SkTArray<const GrCoordTransform*, true>& coordTransforms) override {
const GrPathProcessor& pathProc = primProc.cast<GrPathProcessor>();
SkTArray<TransformVarying, true>& transforms = fInstalledTransforms[index];
int numTransforms = transforms.count();
for (int t = 0; t < numTransforms; ++t) {
SkASSERT(transforms[t].fHandle.isValid());
const SkMatrix& transform = GetTransformMatrix(pathProc.localMatrix(),
*coordTransforms[t]);
if (transforms[t].fCurrentValue.cheapEqualTo(transform)) {
int t = 0;
while (const GrCoordTransform* coordTransform = transformIter.next()) {
SkASSERT(fInstalledTransforms[t].fHandle.isValid());
const SkMatrix& m = GetTransformMatrix(pathProc.localMatrix(), *coordTransform);
if (fInstalledTransforms[t].fCurrentValue.cheapEqualTo(m)) {
continue;
}
transforms[t].fCurrentValue = transform;
fInstalledTransforms[t].fCurrentValue = m;
SkASSERT(transforms[t].fType == kVec2f_GrSLType ||
transforms[t].fType == kVec3f_GrSLType);
unsigned components = transforms[t].fType == kVec2f_GrSLType ? 2 : 3;
pdman.setPathFragmentInputTransform(transforms[t].fHandle, components, transform);
SkASSERT(fInstalledTransforms[t].fType == kVec2f_GrSLType ||
fInstalledTransforms[t].fType == kVec3f_GrSLType);
unsigned components = fInstalledTransforms[t].fType == kVec2f_GrSLType ? 2 : 3;
pd.setPathFragmentInputTransform(fInstalledTransforms[t].fHandle, components, m);
++t;
}
}
@ -122,7 +111,7 @@ private:
GrSLType fType = kVoid_GrSLType;
};
SkSTArray<8, SkSTArray<2, TransformVarying, true> > fInstalledTransforms;
SkTArray<TransformVarying, true> fInstalledTransforms;
UniformHandle fColorUniform;
GrColor fColor;

View File

@ -101,7 +101,7 @@ static bool gen_frag_proc_and_meta_keys(const GrPrimitiveProcessor& primProc,
fp.getGLSLProcessorKey(glslCaps, b);
return gen_meta_key(fp, glslCaps, primProc.getTransformKey(fp.coordTransforms(),
fp.numTransformsExclChildren()), b);
fp.numCoordTransforms()), b);
}
bool GrProgramDesc::Build(GrProgramDesc* desc,

View File

@ -577,8 +577,7 @@ public:
gpArgs->fPositionVar,
qe.inPosition()->fName,
qe.localMatrix(),
args.fTransformsIn,
args.fTransformsOut);
args.fFPCoordTransformHandler);
SkAssertResult(fragBuilder->enableFeature(
GrGLSLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature));
@ -614,7 +613,8 @@ public:
}
void setData(const GrGLSLProgramDataManager& pdman,
const GrPrimitiveProcessor& gp) override {
const GrPrimitiveProcessor& gp,
FPCoordTransformIter&& transformIter) override {
const QuadEdgeEffect& qe = gp.cast<QuadEdgeEffect>();
if (qe.color() != fColor) {
float c[4];
@ -622,14 +622,7 @@ public:
pdman.set4fv(fColorUniform, 1, c);
fColor = qe.color();
}
}
void setTransformData(const GrPrimitiveProcessor& primProc,
const GrGLSLProgramDataManager& pdman,
int index,
const SkTArray<const GrCoordTransform*, true>& transforms) override {
this->setTransformDataHelper(primProc.cast<QuadEdgeEffect>().fLocalMatrix, pdman, index,
transforms);
this->setTransformDataHelper(qe.fLocalMatrix, pdman, &transformIter);
}
private:

View File

@ -18,6 +18,7 @@
#include "batches/GrVertexBatch.h"
#include "glsl/GrGLSLFragmentShaderBuilder.h"
#include "glsl/GrGLSLGeometryProcessor.h"
#include "glsl/GrGLSLGeometryProcessor.h"
#include "glsl/GrGLSLProgramDataManager.h"
#include "glsl/GrGLSLVarying.h"
#include "glsl/GrGLSLVertexShaderBuilder.h"
@ -120,8 +121,7 @@ public:
gpArgs->fPositionVar,
rgp.inPosition()->fName,
rgp.localMatrix(),
args.fTransformsIn,
args.fTransformsOut);
args.fFPCoordTransformHandler);
// TODO: compute all these offsets, spans, and scales in the VS
fragBuilder->codeAppendf("float insetW = min(1.0, %s.x) - 0.5;",
@ -194,15 +194,10 @@ public:
b->add32(0x0);
}
void setData(const GrGLSLProgramDataManager& pdman,
const GrPrimitiveProcessor& gp) override {}
void setTransformData(const GrPrimitiveProcessor& primProc,
const GrGLSLProgramDataManager& pdman,
int index,
const SkTArray<const GrCoordTransform*, true>& transforms) override {
this->setTransformDataHelper(primProc.cast<RectGeometryProcessor>().fLocalMatrix, pdman,
index, transforms);
void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor& primProc,
FPCoordTransformIter&& transformIter) override {
const RectGeometryProcessor& rgp = primProc.cast<RectGeometryProcessor>();
this->setTransformDataHelper(rgp.fLocalMatrix, pdman,&transformIter);
}
private:

View File

@ -148,8 +148,8 @@ public:
// emit transforms
this->emitTransforms(vsBuilder, varyingHandler, uniformHandler, gpArgs->fPositionVar,
qp.inPosition()->fName, SkMatrix::I(), args.fTransformsIn,
args.fTransformsOut);
qp.inPosition()->fName, SkMatrix::I(),
args.fFPCoordTransformHandler);
GrGLSLPPFragmentBuilder* fsBuilder = args.fFragBuilder;
fsBuilder->codeAppendf("if (%s.x * %s.x >= %s.y) discard;", uv.fsIn(), uv.fsIn(),
@ -167,14 +167,15 @@ public:
b->add32(key);
}
virtual void setData(const GrGLSLProgramDataManager& pdman,
const GrPrimitiveProcessor& gp) override {
void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor& gp,
FPCoordTransformIter&& transformIter) override {
const MSAAQuadProcessor& qp = gp.cast<MSAAQuadProcessor>();
if (!qp.viewMatrix().isIdentity()) {
float viewMatrix[3 * 3];
GrGLSLGetMatrix<3>(viewMatrix, qp.viewMatrix());
pdman.setMatrix3f(fViewMatrixUniform, viewMatrix);
}
this->setTransformDataHelper(SkMatrix::I(), pdman, &transformIter);
}
private:

View File

@ -333,8 +333,8 @@ public:
// emit transforms
this->emitTransforms(vsBuilder, varyingHandler, uniformHandler, gpArgs->fPositionVar,
te.inPosition()->fName, te.localMatrix(), args.fTransformsIn,
args.fTransformsOut);
te.inPosition()->fName, te.localMatrix(),
args.fFPCoordTransformHandler);
GrGLSLPPFragmentBuilder* fsBuilder = args.fFragBuilder;
SkAssertResult(fsBuilder->enableFeature(
@ -391,16 +391,10 @@ public:
b->add32(key);
}
virtual void setData(const GrGLSLProgramDataManager& pdman,
const GrPrimitiveProcessor& gp) override {
}
void setTransformData(const GrPrimitiveProcessor& primProc,
const GrGLSLProgramDataManager& pdman,
int index,
const SkTArray<const GrCoordTransform*, true>& transforms) override {
this->setTransformDataHelper(primProc.cast<PLSAATriangleEffect>().fLocalMatrix, pdman,
index, transforms);
void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor& gp,
FPCoordTransformIter&& transformIter) override {
this->setTransformDataHelper(gp.cast<PLSAATriangleEffect>().fLocalMatrix, pdman,
&transformIter);
}
private:
@ -522,8 +516,8 @@ public:
// emit transforms
this->emitTransforms(vsBuilder, varyingHandler, uniformHandler, gpArgs->fPositionVar,
qe.inPosition()->fName, qe.localMatrix(), args.fTransformsIn,
args.fTransformsOut);
qe.inPosition()->fName, qe.localMatrix(),
args.fFPCoordTransformHandler);
GrGLSLPPFragmentBuilder* fsBuilder = args.fFragBuilder;
SkAssertResult(fsBuilder->enableFeature(
@ -581,16 +575,10 @@ public:
b->add32(key);
}
virtual void setData(const GrGLSLProgramDataManager& pdman,
const GrPrimitiveProcessor& gp) override {
}
void setTransformData(const GrPrimitiveProcessor& primProc,
const GrGLSLProgramDataManager& pdman,
int index,
const SkTArray<const GrCoordTransform*, true>& transforms) override {
this->setTransformDataHelper(primProc.cast<PLSQuadEdgeEffect>().fLocalMatrix, pdman,
index, transforms);
void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor& gp,
FPCoordTransformIter&& transformIter) override {
this->setTransformDataHelper(gp.cast<PLSQuadEdgeEffect>().fLocalMatrix, pdman,
&transformIter);
}
private:
@ -680,8 +668,8 @@ public:
varyingHandler->emitAttributes(fe);
this->setupPosition(vsBuilder, gpArgs, fe.inPosition()->fName);
this->emitTransforms(vsBuilder, varyingHandler, uniformHandler, gpArgs->fPositionVar,
fe.inPosition()->fName, fe.localMatrix(), args.fTransformsIn,
args.fTransformsOut);
fe.inPosition()->fName, fe.localMatrix(),
args.fFPCoordTransformHandler);
GrGLSLPPFragmentBuilder* fsBuilder = args.fFragBuilder;
SkAssertResult(fsBuilder->enableFeature(
@ -716,8 +704,8 @@ public:
b->add32(key);
}
virtual void setData(const GrGLSLProgramDataManager& pdman,
const GrPrimitiveProcessor& gp) override {
void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor& gp,
FPCoordTransformIter&& transformIter) override {
const PLSFinishEffect& fe = gp.cast<PLSFinishEffect>();
pdman.set1f(fUseEvenOdd, fe.fUseEvenOdd);
if (fe.color() != fColor && !fe.colorIgnored()) {
@ -726,14 +714,7 @@ public:
pdman.set4fv(fColorUniform, 1, c);
fColor = fe.color();
}
}
void setTransformData(const GrPrimitiveProcessor& primProc,
const GrGLSLProgramDataManager& pdman,
int index,
const SkTArray<const GrCoordTransform*, true>& transforms) override {
this->setTransformDataHelper(primProc.cast<PLSFinishEffect>().fLocalMatrix, pdman,
index, transforms);
this->setTransformDataHelper(fe.fLocalMatrix, pdman, &transformIter);
}
private:

View File

@ -25,8 +25,8 @@ public:
const GrGLSLCaps&,
GrProcessorKeyBuilder*);
void setData(const GrGLSLProgramDataManager& pdman,
const GrPrimitiveProcessor& primProc) override {
void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor& primProc,
FPCoordTransformIter&& transformIter) override {
const GrConicEffect& ce = primProc.cast<GrConicEffect>();
if (!ce.viewMatrix().isIdentity() && !fViewMatrix.cheapEqualTo(ce.viewMatrix())) {
@ -47,14 +47,7 @@ public:
pdman.set1f(fCoverageScaleUniform, GrNormalizeByteToFloat(ce.coverageScale()));
fCoverageScale = ce.coverageScale();
}
}
void setTransformData(const GrPrimitiveProcessor& primProc,
const GrGLSLProgramDataManager& pdman,
int index,
const SkTArray<const GrCoordTransform*, true>& transforms) override {
this->setTransformDataHelper(primProc.cast<GrConicEffect>().localMatrix(), pdman, index,
transforms);
this->setTransformDataHelper(ce.localMatrix(), pdman, &transformIter);
}
private:
@ -109,8 +102,7 @@ void GrGLConicEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
gpArgs->fPositionVar,
gp.inPosition()->fName,
gp.localMatrix(),
args.fTransformsIn,
args.fTransformsOut);
args.fFPCoordTransformHandler);
// TODO: this precision check should actually be a check on the number of bits
// high and medium provide and the selection of the lowest level that suffices.
@ -299,8 +291,8 @@ public:
const GrGLSLCaps&,
GrProcessorKeyBuilder*);
void setData(const GrGLSLProgramDataManager& pdman,
const GrPrimitiveProcessor& primProc) override {
void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor& primProc,
FPCoordTransformIter&& transformIter) override {
const GrQuadEffect& qe = primProc.cast<GrQuadEffect>();
if (!qe.viewMatrix().isIdentity() && !fViewMatrix.cheapEqualTo(qe.viewMatrix())) {
@ -321,14 +313,7 @@ public:
pdman.set1f(fCoverageScaleUniform, GrNormalizeByteToFloat(qe.coverageScale()));
fCoverageScale = qe.coverageScale();
}
}
void setTransformData(const GrPrimitiveProcessor& primProc,
const GrGLSLProgramDataManager& pdman,
int index,
const SkTArray<const GrCoordTransform*, true>& transforms) override {
this->setTransformDataHelper(primProc.cast<GrQuadEffect>().localMatrix(), pdman, index,
transforms);
this->setTransformDataHelper(qe.localMatrix(), pdman, &transformIter);
}
private:
@ -383,8 +368,7 @@ void GrGLQuadEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
gpArgs->fPositionVar,
gp.inPosition()->fName,
gp.localMatrix(),
args.fTransformsIn,
args.fTransformsOut);
args.fFPCoordTransformHandler);
fragBuilder->codeAppendf("float edgeAlpha;");
@ -516,8 +500,8 @@ public:
const GrGLSLCaps&,
GrProcessorKeyBuilder*);
void setData(const GrGLSLProgramDataManager& pdman,
const GrPrimitiveProcessor& primProc) override {
void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor& primProc,
FPCoordTransformIter&& transformIter) override {
const GrCubicEffect& ce = primProc.cast<GrCubicEffect>();
if (!ce.viewMatrix().isIdentity() && !fViewMatrix.cheapEqualTo(ce.viewMatrix())) {
@ -533,6 +517,7 @@ public:
pdman.set4fv(fColorUniform, 1, c);
fColor = ce.color();
}
this->setTransformDataHelper(SkMatrix::I(), pdman, &transformIter);
}
private:
@ -584,8 +569,7 @@ void GrGLCubicEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
uniformHandler,
gpArgs->fPositionVar,
gp.inPosition()->fName,
args.fTransformsIn,
args.fTransformsOut);
args.fFPCoordTransformHandler);
GrGLSLShaderVar edgeAlpha("edgeAlpha", kFloat_GrSLType, 0, kHigh_GrSLPrecision);

View File

@ -60,8 +60,7 @@ public:
gpArgs->fPositionVar,
cte.inPosition()->fName,
cte.localMatrix(),
args.fTransformsIn,
args.fTransformsOut);
args.fFPCoordTransformHandler);
if (cte.maskFormat() == kARGB_GrMaskFormat) {
fragBuilder->codeAppendf("%s = ", args.fOutputColor);
@ -84,7 +83,8 @@ public:
}
}
void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor& gp) override {
void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor& gp,
FPCoordTransformIter&& transformIter) override {
const GrBitmapTextGeoProc& btgp = gp.cast<GrBitmapTextGeoProc>();
if (btgp.color() != fColor && !btgp.hasVertexColor()) {
float c[4];
@ -92,14 +92,7 @@ public:
pdman.set4fv(fColorUniform, 1, c);
fColor = btgp.color();
}
}
void setTransformData(const GrPrimitiveProcessor& primProc,
const GrGLSLProgramDataManager& pdman,
int index,
const SkTArray<const GrCoordTransform*, true>& transforms) override {
this->setTransformDataHelper(primProc.cast<GrBitmapTextGeoProc>().localMatrix(), pdman,
index, transforms);
this->setTransformDataHelper(btgp.localMatrix(), pdman, &transformIter);
}
static inline void GenKey(const GrGeometryProcessor& proc,

View File

@ -817,16 +817,8 @@ public:
const GrGLSLCaps&,
GrProcessorKeyBuilder*);
void setData(const GrGLSLProgramDataManager&, const GrPrimitiveProcessor&) override;
void setTransformData(const GrPrimitiveProcessor& primProc,
const GrGLSLProgramDataManager& pdman,
int index,
const SkTArray<const GrCoordTransform*, true>& transforms) override {
this->setTransformDataHelper(primProc.cast<DashingCircleEffect>().localMatrix(), pdman,
index, transforms);
}
void setData(const GrGLSLProgramDataManager&, const GrPrimitiveProcessor&,
FPCoordTransformIter&& transformIter) override;
private:
UniformHandle fParamUniform;
UniformHandle fColorUniform;
@ -879,8 +871,7 @@ void GLDashingCircleEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
gpArgs->fPositionVar,
dce.inPosition()->fName,
dce.localMatrix(),
args.fTransformsIn,
args.fTransformsOut);
args.fFPCoordTransformHandler);
// transforms all points so that we can compare them to our test circle
fragBuilder->codeAppendf("float xShifted = %s.x - floor(%s.x / %s.z) * %s.z;",
@ -901,7 +892,8 @@ void GLDashingCircleEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
}
void GLDashingCircleEffect::setData(const GrGLSLProgramDataManager& pdman,
const GrPrimitiveProcessor& processor) {
const GrPrimitiveProcessor& processor,
FPCoordTransformIter&& transformIter) {
const DashingCircleEffect& dce = processor.cast<DashingCircleEffect>();
if (dce.color() != fColor) {
float c[4];
@ -909,6 +901,7 @@ void GLDashingCircleEffect::setData(const GrGLSLProgramDataManager& pdman,
pdman.set4fv(fColorUniform, 1, c);
fColor = dce.color();
}
this->setTransformDataHelper(dce.localMatrix(), pdman, &transformIter);
}
void GLDashingCircleEffect::GenKey(const GrGeometryProcessor& gp,
@ -1037,15 +1030,8 @@ public:
const GrGLSLCaps&,
GrProcessorKeyBuilder*);
void setData(const GrGLSLProgramDataManager&, const GrPrimitiveProcessor&) override;
void setTransformData(const GrPrimitiveProcessor& primProc,
const GrGLSLProgramDataManager& pdman,
int index,
const SkTArray<const GrCoordTransform*, true>& transforms) override {
this->setTransformDataHelper(primProc.cast<DashingLineEffect>().localMatrix(), pdman, index,
transforms);
}
void setData(const GrGLSLProgramDataManager&, const GrPrimitiveProcessor&,
FPCoordTransformIter&& iter) override;
private:
GrColor fColor;
@ -1094,8 +1080,7 @@ void GLDashingLineEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
gpArgs->fPositionVar,
de.inPosition()->fName,
de.localMatrix(),
args.fTransformsIn,
args.fTransformsOut);
args.fFPCoordTransformHandler);
// transforms all points so that we can compare them to our test rect
fragBuilder->codeAppendf("float xShifted = %s.x - floor(%s.x / %s.z) * %s.z;",
@ -1134,7 +1119,8 @@ void GLDashingLineEffect::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
}
void GLDashingLineEffect::setData(const GrGLSLProgramDataManager& pdman,
const GrPrimitiveProcessor& processor) {
const GrPrimitiveProcessor& processor,
FPCoordTransformIter&& transformIter) {
const DashingLineEffect& de = processor.cast<DashingLineEffect>();
if (de.color() != fColor) {
float c[4];
@ -1142,6 +1128,7 @@ void GLDashingLineEffect::setData(const GrGLSLProgramDataManager& pdman,
pdman.set4fv(fColorUniform, 1, c);
fColor = de.color();
}
this->setTransformDataHelper(de.localMatrix(), pdman, &transformIter);
}
void GLDashingLineEffect::GenKey(const GrGeometryProcessor& gp,

View File

@ -73,8 +73,7 @@ public:
uniformHandler,
gpArgs->fPositionVar,
dfTexEffect.inPosition()->fName,
args.fTransformsIn,
args.fTransformsOut);
args.fFPCoordTransformHandler);
// add varyings
GrGLSLVertToFrag recipScale(kFloat_GrSLType);
@ -179,7 +178,8 @@ public:
fragBuilder->codeAppendf("%s = vec4(val);", args.fOutputCoverage);
}
void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor& proc) override {
void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor& proc,
FPCoordTransformIter&& transformIter) override {
#ifdef SK_GAMMA_APPLY_TO_A8
const GrDistanceFieldA8TextGeoProc& dfTexEffect = proc.cast<GrDistanceFieldA8TextGeoProc>();
float distanceAdjust = dfTexEffect.getDistanceAdjust();
@ -196,6 +196,7 @@ public:
GrGLSLGetMatrix<3>(viewMatrix, fViewMatrix);
pdman.setMatrix3f(fViewMatrixUniform, viewMatrix);
}
this->setTransformDataHelper(SkMatrix::I(), pdman, &transformIter);
}
static inline void GenKey(const GrGeometryProcessor& gp,
@ -345,8 +346,7 @@ public:
uniformHandler,
gpArgs->fPositionVar,
dfTexEffect.inPosition()->fName,
args.fTransformsIn,
args.fTransformsOut);
args.fFPCoordTransformHandler);
const char* textureSizeUniName = nullptr;
fTextureSizeUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
@ -433,7 +433,8 @@ public:
fragBuilder->codeAppendf("%s = vec4(val);", args.fOutputCoverage);
}
void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor& proc) override {
void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor& proc,
FPCoordTransformIter&& transformIter) override {
SkASSERT(fTextureSizeUni.isValid());
GrTexture* texture = proc.texture(0);
@ -453,6 +454,7 @@ public:
GrGLSLGetMatrix<3>(viewMatrix, fViewMatrix);
pdman.setMatrix3f(fViewMatrixUniform, viewMatrix);
}
this->setTransformDataHelper(SkMatrix::I(), pdman, &transformIter);
}
static inline void GenKey(const GrGeometryProcessor& gp,
@ -582,8 +584,7 @@ public:
uniformHandler,
gpArgs->fPositionVar,
dfTexEffect.inPosition()->fName,
args.fTransformsIn,
args.fTransformsOut);
args.fFPCoordTransformHandler);
// set up varyings
bool isUniformScale = (dfTexEffect.getFlags() & kUniformScale_DistanceFieldEffectMask) ==
@ -732,8 +733,8 @@ public:
fragBuilder->codeAppendf("%s = val;", args.fOutputCoverage);
}
void setData(const GrGLSLProgramDataManager& pdman,
const GrPrimitiveProcessor& processor) override {
void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor& processor,
FPCoordTransformIter&& transformIter) override {
SkASSERT(fDistanceAdjustUni.isValid());
const GrDistanceFieldLCDTextGeoProc& dflcd = processor.cast<GrDistanceFieldLCDTextGeoProc>();
@ -752,6 +753,7 @@ public:
GrGLSLGetMatrix<3>(viewMatrix, fViewMatrix);
pdman.setMatrix3f(fViewMatrixUniform, viewMatrix);
}
this->setTransformDataHelper(SkMatrix::I(), pdman, &transformIter);
}
static inline void GenKey(const GrGeometryProcessor& gp,

View File

@ -70,7 +70,8 @@ void GrGLProgram::setData(const GrPrimitiveProcessor& primProc, const GrPipeline
// we set the textures, and uniforms for installed processors in a generic way, but subclasses
// of GLProgram determine how to set coord transforms
int nextSamplerIdx = 0;
fGeometryProcessor->setData(fProgramDataManager, primProc);
fGeometryProcessor->setData(fProgramDataManager, primProc,
GrFragmentProcessor::CoordTransformIter(pipeline));
this->bindTextures(primProc, pipeline.getAllowSRGBInputs(), &nextSamplerIdx);
this->setFragmentData(primProc, pipeline, &nextSamplerIdx);
@ -107,16 +108,10 @@ void GrGLProgram::setFragmentData(const GrPrimitiveProcessor& primProc,
for (int i = 0; i < numProcessors; ++i) {
const GrFragmentProcessor& processor = pipeline.getFragmentProcessor(i);
fFragmentProcessors[i]->setData(fProgramDataManager, processor);
this->setTransformData(primProc, processor, i);
this->bindTextures(processor, pipeline.getAllowSRGBInputs(), nextSamplerIdx);
}
}
void GrGLProgram::setTransformData(const GrPrimitiveProcessor& primProc,
const GrFragmentProcessor& processor,
int index) {
fGeometryProcessor->setTransformData(primProc, fProgramDataManager, index,
processor.coordTransforms());
}
void GrGLProgram::setRenderTargetState(const GrPrimitiveProcessor& primProc,
const GrPipeline& pipeline) {

View File

@ -120,7 +120,6 @@ protected:
// A helper to loop over effects, set the transforms (via subclass) and bind textures
void setFragmentData(const GrPrimitiveProcessor&, const GrPipeline&, int* nextSamplerIdx);
void setTransformData(const GrPrimitiveProcessor&, const GrFragmentProcessor&, int index);
// Helper for setData() that sets the view matrix and loads the render target height uniform
void setRenderTargetState(const GrPrimitiveProcessor&, const GrPipeline&);

View File

@ -43,16 +43,16 @@ void GrGLSLFragmentProcessor::internalEmitChild(int childIndex, const char* inpu
const GrFragmentProcessor& childProc = args.fFp.childProcessor(childIndex);
/*
* 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'll do a forwards
* linear search.
* TODO: Move textures and buffers to the iterator model used by coords.
* We now want to find the subset of samplers that belong to the child and its descendants and
* put that into 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
* 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.
* Each GrFragmentProcessor has a copy of all the 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 textures array contains its own
* textures, followed by the textures of all its descendants (i.e. preorder traversal). Suppose
* procs A, B, C, D, E, F have 1, 2, 1, 1, 3, 2 textures respectively.
*
* (A)
* [a1,b1,b2,c1,d1,e1,e2,e3,f1,f2]
@ -66,28 +66,22 @@ void GrGLSLFragmentProcessor::internalEmitChild(int childIndex, const char* inpu
* [c1] [e1,e2,e3] [f1,f2]
*
* 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
* EmitArgs that's passed onto D to only contain its and its descendants' textures. The
* EmitArgs given to A would contain the textures [a1,b1,b2,c1,d1,e1,e2,e3,f1,f2], and we want
* 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.
* search since we know that A has 1 texture (using A.numTexturesExclChildren()), and B's
* subtree has 3 textures (using B.numTextures()), so we know the start of D's textures is
* 4 after the start of A's textures.
* Textures work the same way as textures.
*/
int firstCoordAt = args.fFp.numTransformsExclChildren();
int firstTextureAt = args.fFp.numTexturesExclChildren();
int firstBufferAt = args.fFp.numBuffersExclChildren();
for (int i = 0; i < childIndex; ++i) {
firstCoordAt += args.fFp.childProcessor(i).numTransforms();
firstTextureAt += args.fFp.childProcessor(i).numTextures();
firstBufferAt += args.fFp.childProcessor(i).numBuffers();
}
SkTArray<GrShaderVar> childCoords;
const SamplerHandle* childTexSamplers = nullptr;
const SamplerHandle* childBufferSamplers = nullptr;
if (childProc.numTransforms() > 0) {
childCoords.push_back_n(childProc.numTransforms(), &args.fTransformedCoords[firstCoordAt]);
}
if (childProc.numTextures() > 0) {
childTexSamplers = &args.fTexSamplers[firstTextureAt];
}
@ -99,13 +93,14 @@ void GrGLSLFragmentProcessor::internalEmitChild(int childIndex, const char* inpu
fragBuilder->codeAppend("{\n");
fragBuilder->codeAppendf("// Child Index %d (mangle: %s): %s\n", childIndex,
fragBuilder->getMangleString().c_str(), childProc.name());
TransformedCoordVars coordVars = args.fTransformedCoords.childTransforms(childIndex);
EmitArgs childArgs(fragBuilder,
args.fUniformHandler,
args.fGLSLCaps,
childProc,
outputColor,
inputColor,
childCoords,
coordVars,
childTexSamplers,
childBufferSamplers,
args.fGpImplementsDistanceVector);
@ -114,3 +109,19 @@ void GrGLSLFragmentProcessor::internalEmitChild(int childIndex, const char* inpu
fragBuilder->onAfterChildProcEmitCode();
}
//////////////////////////////////////////////////////////////////////////////
using TransformedCoordVars = GrGLSLFragmentProcessor::TransformedCoordVars;
TransformedCoordVars TransformedCoordVars::childTransforms(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 TransformedCoordVars(child, fTransformedVars + numToSkip);
}
numToSkip += fp->numCoordTransforms();
}
}

View File

@ -33,6 +33,30 @@ public:
typedef GrGLSLProgramDataManager::UniformHandle UniformHandle;
typedef GrGLSLProgramDataManager::UniformHandle SamplerHandle;
/**
* 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.
*/
class TransformedCoordVars {
public:
TransformedCoordVars(const GrFragmentProcessor* fp, const GrShaderVar* vars)
: fFP(fp)
, fTransformedVars(vars) {}
const GrShaderVar& operator[] (int i) const {
SkASSERT(i >= 0 && i < fFP->numCoordTransforms());
return fTransformedVars[i];
}
TransformedCoordVars childTransforms(int childIdx) const;
private:
const GrFragmentProcessor* fFP;
const GrShaderVar* fTransformedVars;
};
/** 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.
@ -50,7 +74,7 @@ public:
etc.) that allows the processor to communicate back similar known
info about its output.
@param transformedCoords Fragment shader variables containing the coords computed using
each of the GrFragmentProcessor's Coord Transforms.
each of the GrFragmentProcessor's GrCoordTransforms.
@param texSamplers Contains one entry for each GrTextureAccess of the GrProcessor.
These can be passed to the builder to emit texture reads in the
generated code.
@ -65,7 +89,7 @@ public:
const GrFragmentProcessor& fp,
const char* outputColor,
const char* inputColor,
const SkTArray<GrShaderVar>& transformedCoords,
const TransformedCoordVars& transformedCoordVars,
const SamplerHandle* texSamplers,
const SamplerHandle* bufferSamplers,
bool gpImplementsDistanceVector)
@ -75,7 +99,7 @@ public:
, fFp(fp)
, fOutputColor(outputColor)
, fInputColor(inputColor)
, fTransformedCoords(transformedCoords)
, fTransformedCoords(transformedCoordVars)
, fTexSamplers(texSamplers)
, fBufferSamplers(bufferSamplers)
, fGpImplementsDistanceVector(gpImplementsDistanceVector) {}
@ -85,7 +109,7 @@ public:
const GrFragmentProcessor& fFp;
const char* fOutputColor;
const char* fInputColor;
const SkTArray<GrShaderVar>& fTransformedCoords;
const TransformedCoordVars& fTransformedCoords;
const SamplerHandle* fTexSamplers;
const SamplerHandle* fBufferSamplers;
bool fGpImplementsDistanceVector;

View File

@ -29,73 +29,84 @@ void GrGLSLGeometryProcessor::emitTransforms(GrGLSLVertexBuilder* vb,
const GrShaderVar& posVar,
const char* localCoords,
const SkMatrix& localMatrix,
const TransformsIn& tin,
TransformsOut* tout) {
tout->push_back_n(tin.count());
fInstalledTransforms.push_back_n(tin.count());
for (int i = 0; i < tin.count(); i++) {
const ProcCoords& coordTransforms = tin[i];
fInstalledTransforms[i].push_back_n(coordTransforms.count());
for (int t = 0; t < coordTransforms.count(); t++) {
SkString strUniName("StageMatrix");
strUniName.appendf("_%i_%i", i, t);
GrSLType varyingType;
FPCoordTransformHandler* handler) {
int i = 0;
while (const GrCoordTransform* coordTransform = handler->nextCoordTransform()) {
SkString strUniName;
strUniName.printf("CoordTransformMatrix_%d", i);
GrSLType varyingType;
GrCoordSet coordType = coordTransforms[t]->sourceCoords();
uint32_t type = coordTransforms[t]->getMatrix().getType();
if (kLocal_GrCoordSet == coordType) {
type |= localMatrix.getType();
}
varyingType = SkToBool(SkMatrix::kPerspective_Mask & type) ? kVec3f_GrSLType :
kVec2f_GrSLType;
GrSLPrecision precision = coordTransforms[t]->precision();
GrCoordSet coordType = coordTransform->sourceCoords();
uint32_t type = coordTransform->getMatrix().getType();
if (kLocal_GrCoordSet == coordType) {
type |= localMatrix.getType();
}
varyingType = SkToBool(SkMatrix::kPerspective_Mask & type) ? kVec3f_GrSLType :
kVec2f_GrSLType;
GrSLPrecision precision = coordTransform->precision();
const char* uniName;
fInstalledTransforms[i][t].fHandle =
uniformHandler->addUniform(kVertex_GrShaderFlag,
kMat33f_GrSLType, precision,
strUniName.c_str(),
&uniName).toIndex();
const char* uniName;
SkString strVaryingName("MatrixCoord");
strVaryingName.appendf("_%i_%i", i, t);
GrGLSLVertToFrag v(varyingType);
varyingHandler->addVarying(strVaryingName.c_str(), &v, precision);
fInstalledTransforms.push_back().fHandle = uniformHandler->addUniform(kVertex_GrShaderFlag,
kMat33f_GrSLType,
precision,
strUniName.c_str(),
&uniName).toIndex();
SkString strVaryingName;
strVaryingName.printf("TransformedCoords_%d", i);
SkASSERT(kVec2f_GrSLType == varyingType || kVec3f_GrSLType == varyingType);
(*tout)[i].emplace_back(SkString(v.fsIn()), varyingType);
GrGLSLVertToFrag v(varyingType);
varyingHandler->addVarying(strVaryingName.c_str(), &v, precision);
// varying = matrix * coords (logically)
if (kDevice_GrCoordSet == coordType) {
if (kVec2f_GrSLType == varyingType) {
if (kVec2f_GrSLType == posVar.getType()) {
vb->codeAppendf("%s = (%s * vec3(%s, 1)).xy;",
v.vsOut(), uniName, posVar.c_str());
} else {
// The brackets here are just to scope the temp variable
vb->codeAppendf("{ vec3 temp = %s * %s;", uniName, posVar.c_str());
vb->codeAppendf("%s = vec2(temp.x/temp.z, temp.y/temp.z); }", v.vsOut());
}
SkASSERT(kVec2f_GrSLType == varyingType || kVec3f_GrSLType == varyingType);
handler->specifyCoordsForCurrCoordTransform(SkString(v.fsIn()), varyingType);
// varying = matrix * coords (logically)
if (kDevice_GrCoordSet == coordType) {
if (kVec2f_GrSLType == varyingType) {
if (kVec2f_GrSLType == posVar.getType()) {
vb->codeAppendf("%s = (%s * vec3(%s, 1)).xy;",
v.vsOut(), uniName, posVar.c_str());
} else {
if (kVec2f_GrSLType == posVar.getType()) {
vb->codeAppendf("%s = %s * vec3(%s, 1);",
v.vsOut(), uniName, posVar.c_str());
} else {
vb->codeAppendf("%s = %s * %s;", v.vsOut(), uniName, posVar.c_str());
}
// The brackets here are just to scope the temp variable
vb->codeAppendf("{ vec3 temp = %s * %s;", uniName, posVar.c_str());
vb->codeAppendf("%s = vec2(temp.x/temp.z, temp.y/temp.z); }", v.vsOut());
}
} else {
if (kVec2f_GrSLType == varyingType) {
vb->codeAppendf("%s = (%s * vec3(%s, 1)).xy;", v.vsOut(), uniName, localCoords);
if (kVec2f_GrSLType == posVar.getType()) {
vb->codeAppendf("%s = %s * vec3(%s, 1);",
v.vsOut(), uniName, posVar.c_str());
} else {
vb->codeAppendf("%s = %s * vec3(%s, 1);", v.vsOut(), uniName, localCoords);
vb->codeAppendf("%s = %s * %s;", v.vsOut(), uniName, posVar.c_str());
}
}
} else {
if (kVec2f_GrSLType == varyingType) {
vb->codeAppendf("%s = (%s * vec3(%s, 1)).xy;", v.vsOut(), uniName, localCoords);
} else {
vb->codeAppendf("%s = %s * vec3(%s, 1);", v.vsOut(), uniName, localCoords);
}
}
++i;
}
}
void GrGLSLGeometryProcessor::setTransformDataHelper(const SkMatrix& localMatrix,
const GrGLSLProgramDataManager& pdman,
FPCoordTransformIter* transformIter) {
int i = 0;
while (const GrCoordTransform* coordTransform = transformIter->next()) {
const SkMatrix& m = GetTransformMatrix(localMatrix, *coordTransform);
if (!fInstalledTransforms[i].fCurrentValue.cheapEqualTo(m)) {
pdman.setSkMatrix(fInstalledTransforms[i].fHandle.toIndex(), m);
fInstalledTransforms[i].fCurrentValue = m;
}
++i;
}
SkASSERT(i == fInstalledTransforms.count());
}
void GrGLSLGeometryProcessor::setupPosition(GrGLSLVertexBuilder* vertBuilder,
GrGPArgs* gpArgs,
const char* posName) {

View File

@ -22,31 +22,11 @@ public:
/* Any general emit code goes in the base class emitCode. Subclasses override onEmitCode */
void emitCode(EmitArgs&) override;
// By default we use the identity matrix
void setTransformData(const GrPrimitiveProcessor&,
const GrGLSLProgramDataManager& pdman,
int index,
const SkTArray<const GrCoordTransform*, true>& transforms) override {
this->setTransformDataHelper(SkMatrix::I(), pdman, index, transforms);
}
protected:
// A helper which subclasses can use if needed and used above in the default setTransformData().
void setTransformDataHelper(const SkMatrix& localMatrix,
const GrGLSLProgramDataManager& pdman,
int index,
const SkTArray<const GrCoordTransform*, true>& transforms) {
SkTArray<TransformUniform, true>& procTransforms = fInstalledTransforms[index];
int numTransforms = transforms.count();
for (int t = 0; t < numTransforms; ++t) {
SkASSERT(procTransforms[t].fHandle.isValid());
const SkMatrix& transform = GetTransformMatrix(localMatrix, *transforms[t]);
if (!procTransforms[t].fCurrentValue.cheapEqualTo(transform)) {
pdman.setSkMatrix(procTransforms[t].fHandle.toIndex(), transform);
procTransforms[t].fCurrentValue = transform;
}
}
}
FPCoordTransformIter*);
// Emit a uniform matrix for each coord transform.
void emitTransforms(GrGLSLVertexBuilder* vb,
@ -54,10 +34,9 @@ protected:
GrGLSLUniformHandler* uniformHandler,
const GrShaderVar& posVar,
const char* localCoords,
const TransformsIn& tin,
TransformsOut* tout) {
FPCoordTransformHandler* handler) {
this->emitTransforms(vb, varyingHandler, uniformHandler,
posVar, localCoords, SkMatrix::I(), tin, tout);
posVar, localCoords, SkMatrix::I(), handler);
}
// Emit pre-transformed coords as a vertex attribute per coord-transform.
@ -67,8 +46,7 @@ protected:
const GrShaderVar& posVar,
const char* localCoords,
const SkMatrix& localMatrix,
const TransformsIn&,
TransformsOut*);
FPCoordTransformHandler*);
struct GrGPArgs {
// The variable used by a GP to store its position. It can be
@ -103,7 +81,7 @@ private:
SkMatrix fCurrentValue = SkMatrix::InvalidMatrix();
};
SkSTArray<8, SkSTArray<2, TransformUniform, true> > fInstalledTransforms;
SkTArray<TransformUniform, true> fInstalledTransforms;
typedef GrGLSLPrimitiveProcessor INHERITED;
};

View File

@ -47,3 +47,16 @@ void GrGLSLPrimitiveProcessor::setupUniformColor(GrGLSLPPFragmentBuilder* fragBu
&stagedLocalVarName);
fragBuilder->codeAppendf("%s = %s;", outputName, stagedLocalVarName);
}
//////////////////////////////////////////////////////////////////////////////
const GrCoordTransform* GrGLSLPrimitiveProcessor::FPCoordTransformHandler::nextCoordTransform() {
#ifdef SK_DEBUG
SkASSERT(nullptr == fCurr || fAddedCoord);
fAddedCoord = false;
fCurr = fIter.next();
return fCurr;
#else
return fIter.next();
#endif
}

View File

@ -8,6 +8,7 @@
#ifndef GrGLSLPrimitiveProcessor_DEFINED
#define GrGLSLPrimitiveProcessor_DEFINED
#include "GrFragmentProcessor.h"
#include "GrPrimitiveProcessor.h"
#include "glsl/GrGLSLProgramDataManager.h"
#include "glsl/GrGLSLSampler.h"
@ -23,14 +24,45 @@ class GrGLSLVertexBuilder;
class GrGLSLPrimitiveProcessor {
public:
using FPCoordTransformIter = GrFragmentProcessor::CoordTransformIter;
virtual ~GrGLSLPrimitiveProcessor() {}
typedef GrGLSLProgramDataManager::UniformHandle UniformHandle;
typedef GrGLSLProgramDataManager::UniformHandle SamplerHandle;
typedef SkSTArray<2, const GrCoordTransform*, true> ProcCoords;
typedef SkSTArray<8, ProcCoords> TransformsIn;
typedef SkSTArray<8, SkTArray<GrShaderVar>> TransformsOut;
/**
* This class provides access to the GrCoordTransforms across all GrFragmentProcessors in a
* GrPipeline. It is also used by the primitive processor to specify the fragment shader
* variable that will hold the transformed coords for each GrCoordTransform. It is required that
* the primitive processor iterate over each coord transform and insert a shader var result for
* each. The GrGLSLFragmentProcessors will reference these variables in their fragment code.
*/
class FPCoordTransformHandler : public SkNoncopyable {
public:
FPCoordTransformHandler(const GrPipeline& pipeline,
SkTArray<GrShaderVar>* transformedCoordVars)
: fIter(pipeline)
, fTransformedCoordVars(transformedCoordVars) {}
~FPCoordTransformHandler() { SkASSERT(!this->nextCoordTransform());}
const GrCoordTransform* nextCoordTransform();
// 'args' are constructor params to GrShaderVar.
template<typename... Args>
void specifyCoordsForCurrCoordTransform(Args&&... args) {
SkASSERT(!fAddedCoord);
fTransformedCoordVars->emplace_back(std::forward<Args>(args)...);
SkDEBUGCODE(fAddedCoord = true;)
}
private:
GrFragmentProcessor::CoordTransformIter fIter;
SkDEBUGCODE(bool fAddedCoord = false;)
SkDEBUGCODE(const GrCoordTransform* fCurr = nullptr;)
SkTArray<GrShaderVar>* fTransformedCoordVars;
};
struct EmitArgs {
EmitArgs(GrGLSLVertexBuilder* vertBuilder,
@ -44,8 +76,7 @@ public:
const char* distanceVectorName,
const SamplerHandle* texSamplers,
const SamplerHandle* bufferSamplers,
const TransformsIn& transformsIn,
TransformsOut* transformsOut)
FPCoordTransformHandler* transformHandler)
: fVertBuilder(vertBuilder)
, fFragBuilder(fragBuilder)
, fVaryingHandler(varyingHandler)
@ -57,8 +88,7 @@ public:
, fDistanceVectorName(distanceVectorName)
, fTexSamplers(texSamplers)
, fBufferSamplers(bufferSamplers)
, fTransformsIn(transformsIn)
, fTransformsOut(transformsOut) {}
, fFPCoordTransformHandler(transformHandler) {}
GrGLSLVertexBuilder* fVertBuilder;
GrGLSLPPFragmentBuilder* fFragBuilder;
GrGLSLVaryingHandler* fVaryingHandler;
@ -70,8 +100,7 @@ public:
const char* fDistanceVectorName;
const SamplerHandle* fTexSamplers;
const SamplerHandle* fBufferSamplers;
const TransformsIn& fTransformsIn;
TransformsOut* fTransformsOut;
FPCoordTransformHandler* fFPCoordTransformHandler;
};
/**
@ -80,21 +109,22 @@ public:
*/
virtual void emitCode(EmitArgs&) = 0;
/** A GrGLSLPrimitiveProcessor instance can be reused with any GrGLSLPrimitiveProcessor that
produces the same stage key; this function reads data from a GrGLSLPrimitiveProcessor and
uploads any uniform variables required by the shaders created in emitCode(). The
GrPrimitiveProcessor parameter is guaranteed to be of the same type that created this
GrGLSLPrimitiveProcessor and to have an identical processor key as the one that created this
GrGLSLPrimitiveProcessor. */
virtual void setData(const GrGLSLProgramDataManager&, const GrPrimitiveProcessor&) = 0;
/**
* A GrGLSLPrimitiveProcessor instance can be reused with any GrGLSLPrimitiveProcessor that
* produces the same stage key; this function reads data from a GrGLSLPrimitiveProcessor and
* uploads any uniform variables required by the shaders created in emitCode(). The
* GrPrimitiveProcessor parameter is guaranteed to be of the same type and to have an
* identical processor key as the GrPrimitiveProcessor that created this
* GrGLSLPrimitiveProcessor.
* The subclass may use the transform iterator to perform any setup required for the particular
* set of fp transform matrices, such as uploading via uniforms. The iterator will iterate over
* the transforms in the same order as the TransformHandler passed to emitCode.
*/
virtual void setData(const GrGLSLProgramDataManager&, const GrPrimitiveProcessor&,
FPCoordTransformIter&&) = 0;
static SkMatrix GetTransformMatrix(const SkMatrix& localMatrix, const GrCoordTransform&);
virtual void setTransformData(const GrPrimitiveProcessor&,
const GrGLSLProgramDataManager& pdman,
int index,
const SkTArray<const GrCoordTransform*, true>& transforms) = 0;
protected:
void setupUniformColor(GrGLSLPPFragmentBuilder* fragBuilder,
GrGLSLUniformHandler* uniformHandler,

View File

@ -53,19 +53,9 @@ bool GrGLSLProgramBuilder::emitAndInstallProcs(GrGLSLExpr4* inputColor,
// be sent to the GrGLSLPrimitiveProcessor in its emitCode function
const GrPrimitiveProcessor& primProc = this->primitiveProcessor();
for (int i = 0; i < this->pipeline().numFragmentProcessors(); i++) {
const GrFragmentProcessor& processor = this->pipeline().getFragmentProcessor(i);
SkTArray<const GrCoordTransform*, true>& procCoords = fCoordTransforms.push_back();
processor.gatherCoordTransforms(&procCoords);
}
this->emitAndInstallPrimProc(primProc, inputColor, inputCoverage);
int numProcs = this->pipeline().numFragmentProcessors();
this->emitAndInstallFragProcs(0, this->pipeline().numColorFragmentProcessors(), inputColor);
this->emitAndInstallFragProcs(this->pipeline().numColorFragmentProcessors(), numProcs,
inputCoverage);
this->emitAndInstallFragProcs(inputColor, inputCoverage);
if (primProc.getPixelLocalStorageState() !=
GrPixelLocalStorageState::kDraw_GrPixelLocalStorageState) {
this->emitAndInstallXferProc(this->pipeline().getXferProcessor(), *inputColor,
@ -109,6 +99,8 @@ void GrGLSLProgramBuilder::emitAndInstallPrimProc(const GrPrimitiveProcessor& pr
SkSTArray<2, SamplerHandle> bufferSamplers(proc.numBuffers());
this->emitSamplers(proc, &texSamplers, &bufferSamplers);
GrGLSLPrimitiveProcessor::FPCoordTransformHandler transformHandler(fPipeline,
&fTransformedCoordVars);
GrGLSLGeometryProcessor::EmitArgs args(&fVS,
&fFS,
this->varyingHandler(),
@ -120,8 +112,7 @@ void GrGLSLProgramBuilder::emitAndInstallPrimProc(const GrPrimitiveProcessor& pr
distanceVectorName,
texSamplers.begin(),
bufferSamplers.begin(),
fCoordTransforms,
&fOutCoords);
&transformHandler);
fGeometryProcessor->emitCode(args);
// We have to check that effects and the code they emit are consistent, ie if an effect
@ -131,14 +122,21 @@ void GrGLSLProgramBuilder::emitAndInstallPrimProc(const GrPrimitiveProcessor& pr
fFS.codeAppend("}");
}
void GrGLSLProgramBuilder::emitAndInstallFragProcs(int procOffset,
int numProcs,
GrGLSLExpr4* inOut) {
for (int i = procOffset; i < numProcs; ++i) {
void GrGLSLProgramBuilder::emitAndInstallFragProcs(GrGLSLExpr4* color, GrGLSLExpr4* coverage) {
int transformedCoordVarsIdx = 0;
GrGLSLExpr4** inOut = &color;
for (int i = 0; i < this->pipeline().numFragmentProcessors(); ++i) {
if (i == this->pipeline().numColorFragmentProcessors()) {
inOut = &coverage;
}
GrGLSLExpr4 output;
const GrFragmentProcessor& fp = this->pipeline().getFragmentProcessor(i);
this->emitAndInstallFragProc(fp, i, *inOut, &output);
*inOut = output;
this->emitAndInstallFragProc(fp, i, transformedCoordVarsIdx, **inOut, &output);
GrFragmentProcessor::Iter iter(&fp);
while (const GrFragmentProcessor* fp = iter.next()) {
transformedCoordVarsIdx += fp->numCoordTransforms();
}
**inOut = output;
}
}
@ -146,6 +144,7 @@ void GrGLSLProgramBuilder::emitAndInstallFragProcs(int procOffset,
// the fix is to allow effects to take the GrGLSLExpr4 directly
void GrGLSLProgramBuilder::emitAndInstallFragProc(const GrFragmentProcessor& fp,
int index,
int transformedCoordVarsIdx,
const GrGLSLExpr4& input,
GrGLSLExpr4* output) {
// Program builders have a bit of state we need to clear with each effect
@ -163,13 +162,15 @@ void GrGLSLProgramBuilder::emitAndInstallFragProc(const GrFragmentProcessor& fp,
SkSTArray<2, SamplerHandle> bufferSamplers(fp.numBuffers());
this->emitSamplers(fp, &texSamplers, &bufferSamplers);
const GrShaderVar* coordVars = fTransformedCoordVars.begin() + transformedCoordVarsIdx;
GrGLSLFragmentProcessor::TransformedCoordVars coords(&fp, coordVars);
GrGLSLFragmentProcessor::EmitArgs args(&fFS,
this->uniformHandler(),
this->glslCaps(),
fp,
output->c_str(),
input.isOnes() ? nullptr : input.c_str(),
fOutCoords[index],
coords,
texSamplers.begin(),
bufferSamplers.begin(),
this->primitiveProcessor().implementsDistanceVector());
@ -418,5 +419,4 @@ void GrGLSLProgramBuilder::finalizeShaders() {
this->varyingHandler()->finalize();
fVS.finalize(kVertex_GrShaderFlag);
fFS.finalize(kFragment_GrShaderFlag);
}

View File

@ -139,9 +139,10 @@ private:
void emitAndInstallPrimProc(const GrPrimitiveProcessor&,
GrGLSLExpr4* outputColor,
GrGLSLExpr4* outputCoverage);
void emitAndInstallFragProcs(int procOffset, int numProcs, GrGLSLExpr4* inOut);
void emitAndInstallFragProcs(GrGLSLExpr4* colorInOut, GrGLSLExpr4* coverageInOut);
void emitAndInstallFragProc(const GrFragmentProcessor&,
int index,
int transformedCoordVarsIdx,
const GrGLSLExpr4& input,
GrGLSLExpr4* output);
void emitAndInstallXferProc(const GrXferProcessor&,
@ -167,11 +168,10 @@ private:
void verify(const GrFragmentProcessor&);
#endif
GrGLSLPrimitiveProcessor::TransformsIn fCoordTransforms;
GrGLSLPrimitiveProcessor::TransformsOut fOutCoords;
int fNumVertexSamplers;
int fNumGeometrySamplers;
int fNumFragmentSamplers;
int fNumVertexSamplers;
int fNumGeometrySamplers;
int fNumFragmentSamplers;
SkSTArray<4, GrShaderVar> fTransformedCoordVars;
};
#endif

View File

@ -80,7 +80,10 @@ public:
void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override;
private:
void setData(const GrGLSLProgramDataManager&, const GrPrimitiveProcessor&) override {}
void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor&,
FPCoordTransformIter&& transformIter) override {
this->setTransformDataHelper(SkMatrix::I(), pdman, &transformIter);
}
class VertexInputs;
class Backend;
@ -388,7 +391,7 @@ void GLSLInstanceProcessor::onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) {
gpArgs->fPositionVar.set(positionType, "deviceCoords");
this->emitTransforms(v, varyingHandler, uniHandler, gpArgs->fPositionVar, localCoords,
args.fTransformsIn, args.fTransformsOut);
args.fFPCoordTransformHandler);
}
////////////////////////////////////////////////////////////////////////////////////////////////////

View File

@ -194,14 +194,13 @@ void GrVkPipelineState::setData(GrVkGpu* gpu,
SkSTArray<8, const GrTextureAccess*> textureBindings;
fGeometryProcessor->setData(fDataManager, primProc);
fGeometryProcessor->setData(fDataManager, primProc,
GrFragmentProcessor::CoordTransformIter(pipeline));
append_texture_bindings(primProc, &textureBindings);
for (int i = 0; i < fFragmentProcessors.count(); ++i) {
const GrFragmentProcessor& processor = pipeline.getFragmentProcessor(i);
fFragmentProcessors[i]->setData(fDataManager, processor);
fGeometryProcessor->setTransformData(primProc, fDataManager, i,
processor.coordTransforms());
append_texture_bindings(processor, &textureBindings);
}

View File

@ -70,7 +70,8 @@ private:
this->setupPosition(args.fVertBuilder, gpArgs, gp.fAttribs[0].fName);
}
void setData(const GrGLSLProgramDataManager& pdman,
const GrPrimitiveProcessor& primProc) override {}
const GrPrimitiveProcessor& primProc,
FPCoordTransformIter&&) override {}
};
return new GLSLGP();
}