aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar joshualitt <joshualitt@chromium.org>2014-10-10 14:11:59 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2014-10-10 14:11:59 -0700
commit89c7a2ec3e9f7e1b9705214f450bb12288799da9 (patch)
tree846fda99f953334024ec35a748bc307a3a1cb936
parent93bee71a41701eb6cb55fe6df50f3a4081cc8a01 (diff)
Revert of Opt state takes a GP instead of a GeometryStage (patchset #18 id:1500001 of https://codereview.chromium.org/637003003/)
Reason for revert: Revert because this may be causing a break in a chrome gpu test Original issue's description: > Opt state takes a GP instead of a GeometryStage > > BUG=skia: > > Committed: https://skia.googlesource.com/skia/+/71856d520461ae025a0332aa0ce9735a096d9baf TBR=bsalomon@google.com,egdaniel@google.com,danakj@chromium.org NOTREECHECKS=true NOTRY=true BUG=skia: Review URL: https://codereview.chromium.org/647183002
-rw-r--r--include/gpu/GrProcessor.h35
-rw-r--r--include/gpu/GrProcessorStage.h44
-rw-r--r--src/effects/gradients/SkGradientShaderPriv.h2
-rw-r--r--src/gpu/GrDrawState.cpp42
-rw-r--r--src/gpu/GrDrawState.h16
-rw-r--r--src/gpu/GrDrawTarget.cpp2
-rw-r--r--src/gpu/GrOptDrawState.cpp14
-rw-r--r--src/gpu/GrOptDrawState.h9
-rw-r--r--src/gpu/GrProcessor.cpp17
-rw-r--r--src/gpu/effects/GrConfigConversionEffect.h2
-rw-r--r--src/gpu/gl/GrGLProcessor.h1
-rw-r--r--src/gpu/gl/GrGLProgram.cpp124
-rw-r--r--src/gpu/gl/GrGLProgram.h52
-rw-r--r--src/gpu/gl/GrGLProgramDesc.cpp149
-rw-r--r--src/gpu/gl/GrGLProgramDesc.h26
-rw-r--r--src/gpu/gl/GrGpuGL.h5
-rw-r--r--src/gpu/gl/GrGpuGL_program.cpp38
-rw-r--r--src/gpu/gl/builders/GrGLLegacyNvprProgramBuilder.cpp13
-rw-r--r--src/gpu/gl/builders/GrGLLegacyNvprProgramBuilder.h4
-rw-r--r--src/gpu/gl/builders/GrGLNvprProgramBuilder.cpp28
-rw-r--r--src/gpu/gl/builders/GrGLNvprProgramBuilder.h6
-rw-r--r--src/gpu/gl/builders/GrGLProgramBuilder.cpp243
-rw-r--r--src/gpu/gl/builders/GrGLProgramBuilder.h131
-rw-r--r--src/gpu/gl/builders/GrGLVertexShaderBuilder.h2
-rw-r--r--tests/GLProgramsTest.cpp17
25 files changed, 620 insertions, 402 deletions
diff --git a/include/gpu/GrProcessor.h b/include/gpu/GrProcessor.h
index a5c834168b..c1755a8954 100644
--- a/include/gpu/GrProcessor.h
+++ b/include/gpu/GrProcessor.h
@@ -124,6 +124,12 @@ public:
in generated shader code. */
const char* name() const;
+ int numTransforms() const { return fCoordTransforms.count(); }
+
+ /** Returns the coordinate transformation at index. index must be valid according to
+ numTransforms(). */
+ const GrCoordTransform& coordTransform(int index) const { return *fCoordTransforms[index]; }
+
int numTextures() const { return fTextureAccesses.count(); }
/** Returns the access pattern for the texture at index. index must be valid according to
@@ -153,6 +159,16 @@ public:
protected:
/**
+ * Subclasses call this from their constructor to register coordinate transformations. The
+ * effect subclass manages the lifetime of the transformations (this function only stores a
+ * pointer). The GrCoordTransform is typically a member field of the GrProcessor subclass. When
+ * the matrix has perspective, the transformed coordinates will have 3 components. Otherwise
+ * they'll have 2. This must only be called from the constructor because GrProcessors are
+ * immutable.
+ */
+ void addCoordTransform(const GrCoordTransform* coordTransform);
+
+ /**
* Subclasses call this from their constructor to register GrTextureAccesses. The effect
* subclass manages the lifetime of the accesses (this function only stores a pointer). The
* GrTextureAccess is typically a member field of the GrProcessor subclass. This must only be
@@ -182,7 +198,9 @@ private:
* Subclass implements this to support getConstantColorComponents(...).
*/
virtual void onComputeInvariantOutput(InvariantOutput* inout) const = 0;
+ friend class GrGeometryProcessor; // to set fRequiresVertexShader and build fVertexAttribTypes.
+ SkSTArray<4, const GrCoordTransform*, true> fCoordTransforms;
SkSTArray<4, const GrTextureAccess*, true> fTextureAccesses;
bool fWillReadFragmentPosition;
@@ -198,12 +216,6 @@ public:
virtual const GrBackendFragmentProcessorFactory& getFactory() const = 0;
- int numTransforms() const { return fCoordTransforms.count(); }
-
- /** Returns the coordinate transformation at index. index must be valid according to
- numTransforms(). */
- const GrCoordTransform& coordTransform(int index) const { return *fCoordTransforms[index]; }
-
/** Will this effect read the destination pixel value? */
bool willReadDstColor() const { return fWillReadDstColor; }
@@ -212,16 +224,6 @@ public:
protected:
/**
- * Fragment Processor subclasses call this from their constructor to register coordinate
- * transformations. The processor subclass manages the lifetime of the transformations (this
- * function only stores a pointer). The GrCoordTransform is typically a member field of the
- * GrProcessor subclass. When the matrix has perspective, the transformed coordinates will have
- * 3 components. Otherwise they'll have 2. This must only be called from the constructor because
- * GrProcessors are immutable.
- */
- void addCoordTransform(const GrCoordTransform*);
-
- /**
* If the effect subclass will read the destination pixel value then it must call this function
* from its constructor. Otherwise, when its generated backend-specific effect class attempts
* to generate code that reads the destination pixel it will fail.
@@ -236,7 +238,6 @@ protected:
void setWillNotUseInputColor() { fWillUseInputColor = false; }
private:
- SkSTArray<4, const GrCoordTransform*, true> fCoordTransforms;
bool fWillReadDstColor;
bool fWillUseInputColor;
diff --git a/include/gpu/GrProcessorStage.h b/include/gpu/GrProcessorStage.h
index c961572c1d..5cc06e78db 100644
--- a/include/gpu/GrProcessorStage.h
+++ b/include/gpu/GrProcessorStage.h
@@ -24,14 +24,16 @@
// is immutable, and only owns pending execution refs. This requries removing the common base
// class from GrDrawState and GrOptDrawState called GrRODrawState and converting to GrOptDrawState
// when draws are enqueued in the GrInOrderDrawBuffer.
-class GrFragmentStage {
+class GrProcessorStage {
public:
- explicit GrFragmentStage(const GrFragmentProcessor* proc)
+ explicit GrProcessorStage(const GrProcessor* proc)
: fProc(SkRef(proc)) {
fCoordChangeMatrixSet = false;
}
- GrFragmentStage(const GrFragmentStage& other) {
+ virtual ~GrProcessorStage() {}
+
+ GrProcessorStage(const GrProcessorStage& other) {
fCoordChangeMatrixSet = other.fCoordChangeMatrixSet;
if (other.fCoordChangeMatrixSet) {
fCoordChangeMatrix = other.fCoordChangeMatrix;
@@ -39,7 +41,7 @@ public:
fProc.initAndRef(other.fProc);
}
- static bool AreCompatible(const GrFragmentStage& a, const GrFragmentStage& b,
+ static bool AreCompatible(const GrProcessorStage& a, const GrProcessorStage& b,
bool usingExplicitLocalCoords) {
SkASSERT(a.fProc.get());
SkASSERT(b.fProc.get());
@@ -88,7 +90,7 @@ public:
SkMatrix fCoordChangeMatrix;
SkDEBUGCODE(mutable uint32_t fEffectUniqueID;)
- friend class GrFragmentStage;
+ friend class GrProcessorStage;
};
/**
@@ -147,14 +149,38 @@ public:
}
}
- const GrFragmentProcessor* getProcessor() const { return fProc.get(); }
+ virtual const GrProcessor* getProcessor() const = 0;
void convertToPendingExec() { fProc.convertToPendingExec(); }
protected:
- bool fCoordChangeMatrixSet;
- SkMatrix fCoordChangeMatrix;
- GrProgramElementRef<const GrFragmentProcessor> fProc;
+ bool fCoordChangeMatrixSet;
+ SkMatrix fCoordChangeMatrix;
+ GrProgramElementRef<const GrProcessor> fProc;
+};
+
+class GrFragmentStage : public GrProcessorStage {
+public:
+ GrFragmentStage(const GrFragmentProcessor* fp) : GrProcessorStage(fp) {}
+
+ virtual const GrFragmentProcessor* getProcessor() const {
+ return static_cast<const GrFragmentProcessor*>(fProc.get());
+ }
+
+ typedef GrFragmentProcessor Processor;
+ typedef GrGLFragmentProcessor GLProcessor;
+};
+
+class GrGeometryStage : public GrProcessorStage {
+public:
+ GrGeometryStage(const GrGeometryProcessor* gp) : GrProcessorStage(gp) {}
+
+ virtual const GrGeometryProcessor* getProcessor() const {
+ return static_cast<const GrGeometryProcessor*>(fProc.get());
+ }
+
+ typedef GrGeometryProcessor Processor;
+ typedef GrGLGeometryProcessor GLProcessor;
};
#endif
diff --git a/src/effects/gradients/SkGradientShaderPriv.h b/src/effects/gradients/SkGradientShaderPriv.h
index b3ad6f4b34..d1ac77bc92 100644
--- a/src/effects/gradients/SkGradientShaderPriv.h
+++ b/src/effects/gradients/SkGradientShaderPriv.h
@@ -300,7 +300,7 @@ static inline int next_dither_toggle16(int toggle) {
#include "GrCoordTransform.h"
#include "gl/GrGLProcessor.h"
-class GrFragmentStage;
+class GrProcessorStage;
class GrBackendProcessorFactory;
/*
diff --git a/src/gpu/GrDrawState.cpp b/src/gpu/GrDrawState.cpp
index e1fa6da877..288fa12730 100644
--- a/src/gpu/GrDrawState.cpp
+++ b/src/gpu/GrDrawState.cpp
@@ -43,7 +43,9 @@ bool GrDrawState::isEqual(const GrDrawState& that) const {
if (this->hasGeometryProcessor()) {
if (!that.hasGeometryProcessor()) {
return false;
- } else if (!this->getGeometryProcessor()->isEqual(*that.getGeometryProcessor())) {
+ } else if (!GrProcessorStage::AreCompatible(*this->getGeometryProcessor(),
+ *that.getGeometryProcessor(),
+ explicitLocalCoords)) {
return false;
}
} else if (that.hasGeometryProcessor()) {
@@ -51,13 +53,13 @@ bool GrDrawState::isEqual(const GrDrawState& that) const {
}
for (int i = 0; i < this->numColorStages(); i++) {
- if (!GrFragmentStage::AreCompatible(this->getColorStage(i), that.getColorStage(i),
+ if (!GrProcessorStage::AreCompatible(this->getColorStage(i), that.getColorStage(i),
explicitLocalCoords)) {
return false;
}
}
for (int i = 0; i < this->numCoverageStages(); i++) {
- if (!GrFragmentStage::AreCompatible(this->getCoverageStage(i), that.getCoverageStage(i),
+ if (!GrProcessorStage::AreCompatible(this->getCoverageStage(i), that.getCoverageStage(i),
explicitLocalCoords)) {
return false;
}
@@ -114,6 +116,9 @@ GrDrawState::GrDrawState(const GrDrawState& state, const SkMatrix& preConcatMatr
SkDEBUGCODE(fBlockEffectRemovalCnt = 0;)
*this = state;
if (!preConcatMatrix.isIdentity()) {
+ if (this->hasGeometryProcessor()) {
+ fGeometryProcessor->localCoordChange(preConcatMatrix);
+ }
for (int i = 0; i < this->numColorStages(); ++i) {
fColorStages[i].localCoordChange(preConcatMatrix);
}
@@ -142,7 +147,7 @@ GrDrawState& GrDrawState::operator=(const GrDrawState& that) {
fCoverage = that.fCoverage;
fDrawFace = that.fDrawFace;
if (that.hasGeometryProcessor()) {
- fGeometryProcessor.initAndRef(that.fGeometryProcessor);
+ fGeometryProcessor.reset(SkNEW_ARGS(GrGeometryStage, (*that.fGeometryProcessor.get())));
} else {
fGeometryProcessor.reset(NULL);
}
@@ -197,6 +202,9 @@ bool GrDrawState::setIdentityViewMatrix() {
// sad trombone sound
return false;
}
+ if (this->hasGeometryProcessor()) {
+ fGeometryProcessor->localCoordChange(invVM);
+ }
for (int s = 0; s < this->numColorStages(); ++s) {
fColorStages[s].localCoordChange(invVM);
}
@@ -257,7 +265,9 @@ bool GrDrawState::validateVertexAttribs() const {
}
if (this->hasGeometryProcessor()) {
- const GrGeometryProcessor* gp = this->getGeometryProcessor();
+ const GrGeometryStage& stage = *this->getGeometryProcessor();
+ const GrGeometryProcessor* gp = stage.getProcessor();
+ SkASSERT(gp);
// make sure that any attribute indices have the correct binding type, that the attrib
// type and effect's shader lang type are compatible, and that attributes shared by
// multiple effects use the same shader lang type.
@@ -400,7 +410,8 @@ bool GrDrawState::hasSolidCoverage() const {
// Run through the coverage stages and see if the coverage will be all ones at the end.
if (this->hasGeometryProcessor()) {
- fGeometryProcessor->computeInvariantOutput(&inout);
+ const GrGeometryProcessor* gp = fGeometryProcessor->getProcessor();
+ gp->computeInvariantOutput(&inout);
}
for (int s = 0; s < this->numCoverageStages(); ++s) {
@@ -445,7 +456,7 @@ void GrDrawState::AutoRestoreEffects::set(GrDrawState* ds) {
if (SK_InvalidUniqueID == fOriginalGPID) {
fDrawState->fGeometryProcessor.reset(NULL);
} else {
- SkASSERT(fDrawState->getGeometryProcessor()->getUniqueID() ==
+ SkASSERT(fDrawState->getGeometryProcessor()->getProcessor()->getUniqueID() ==
fOriginalGPID);
fOriginalGPID = SK_InvalidUniqueID;
}
@@ -466,7 +477,7 @@ void GrDrawState::AutoRestoreEffects::set(GrDrawState* ds) {
if (NULL != ds) {
SkASSERT(SK_InvalidUniqueID == fOriginalGPID);
if (NULL != ds->getGeometryProcessor()) {
- fOriginalGPID = ds->getGeometryProcessor()->getUniqueID();
+ fOriginalGPID = ds->getGeometryProcessor()->getProcessor()->getUniqueID();
}
fColorEffectCnt = ds->numColorStages();
fCoverageEffectCnt = ds->numCoverageStages();
@@ -504,9 +515,14 @@ void GrDrawState::AutoViewMatrixRestore::restore() {
fDrawState->fViewMatrix = fViewMatrix;
SkASSERT(fDrawState->numColorStages() >= fNumColorStages);
int numCoverageStages = fSavedCoordChanges.count() - fNumColorStages;
+ numCoverageStages -= fHasGeometryProcessor ? 1 : 0;
SkASSERT(fDrawState->numCoverageStages() >= numCoverageStages);
int i = 0;
+ if (fHasGeometryProcessor) {
+ SkASSERT(fDrawState->hasGeometryProcessor());
+ fDrawState->fGeometryProcessor->restoreCoordChange(fSavedCoordChanges[i++]);
+ }
for (int s = 0; s < fNumColorStages; ++s, ++i) {
fDrawState->fColorStages[s].restoreCoordChange(fSavedCoordChanges[i]);
}
@@ -552,6 +568,7 @@ bool GrDrawState::AutoViewMatrixRestore::setIdentity(GrDrawState* drawState) {
if (0 == drawState->numTotalStages()) {
drawState->fViewMatrix.reset();
fDrawState = drawState;
+ fHasGeometryProcessor = false;
fNumColorStages = 0;
fSavedCoordChanges.reset(0);
SkDEBUGCODE(++fDrawState->fBlockEffectRemovalCnt;)
@@ -573,6 +590,13 @@ void GrDrawState::AutoViewMatrixRestore::doEffectCoordChanges(const SkMatrix& co
fSavedCoordChanges.reset(fDrawState->numTotalStages());
int i = 0;
+ fHasGeometryProcessor = false;
+ if (fDrawState->hasGeometryProcessor()) {
+ fDrawState->fGeometryProcessor->saveCoordChange(&fSavedCoordChanges[i++]);
+ fDrawState->fGeometryProcessor->localCoordChange(coordChangeMatrix);
+ fHasGeometryProcessor = true;
+ }
+
fNumColorStages = fDrawState->numColorStages();
for (int s = 0; s < fNumColorStages; ++s, ++i) {
fDrawState->getColorStage(s).saveCoordChange(&fSavedCoordChanges[i]);
@@ -595,7 +619,7 @@ void GrDrawState::convertToPendingExec() {
fColorStages[i].convertToPendingExec();
}
if (fGeometryProcessor) {
- fGeometryProcessor.convertToPendingExec();
+ fGeometryProcessor->convertToPendingExec();
}
for (int i = 0; i < fCoverageStages.count(); ++i) {
fCoverageStages[i].convertToPendingExec();
diff --git a/src/gpu/GrDrawState.h b/src/gpu/GrDrawState.h
index d58d8c64e7..03af7b532f 100644
--- a/src/gpu/GrDrawState.h
+++ b/src/gpu/GrDrawState.h
@@ -221,7 +221,7 @@ public:
const GrGeometryProcessor* setGeometryProcessor(const GrGeometryProcessor* geometryProcessor) {
SkASSERT(geometryProcessor);
SkASSERT(!this->hasGeometryProcessor());
- fGeometryProcessor.reset(SkRef(geometryProcessor));
+ fGeometryProcessor.reset(new GrGeometryStage(geometryProcessor));
this->invalidateOptState();
return geometryProcessor;
}
@@ -254,7 +254,7 @@ public:
}
bool hasGeometryProcessor() const { return SkToBool(fGeometryProcessor.get()); }
- const GrGeometryProcessor* getGeometryProcessor() const { return fGeometryProcessor.get(); }
+ const GrGeometryStage* getGeometryProcessor() const { return fGeometryProcessor.get(); }
const GrFragmentStage& getColorStage(int idx) const { return fColorStages[idx]; }
const GrFragmentStage& getCoverageStage(int idx) const { return fCoverageStages[idx]; }
@@ -485,7 +485,8 @@ public:
GrDrawState* fDrawState;
SkMatrix fViewMatrix;
int fNumColorStages;
- SkAutoSTArray<8, GrFragmentStage::SavedCoordChange> fSavedCoordChanges;
+ bool fHasGeometryProcessor;
+ SkAutoSTArray<8, GrProcessorStage::SavedCoordChange> fSavedCoordChanges;
};
/// @}
@@ -809,11 +810,10 @@ private:
GrBlendCoeff fSrcBlend;
GrBlendCoeff fDstBlend;
- typedef SkSTArray<4, GrFragmentStage> FragmentStageArray;
- typedef GrProgramElementRef<const GrGeometryProcessor> ProgramGeometryProcessor;
- ProgramGeometryProcessor fGeometryProcessor;
- FragmentStageArray fColorStages;
- FragmentStageArray fCoverageStages;
+ typedef SkSTArray<4, GrFragmentStage> FragmentStageArray;
+ SkAutoTDelete<GrGeometryStage> fGeometryProcessor;
+ FragmentStageArray fColorStages;
+ FragmentStageArray fCoverageStages;
uint32_t fHints;
diff --git a/src/gpu/GrDrawTarget.cpp b/src/gpu/GrDrawTarget.cpp
index b144caf63e..7265f4d23a 100644
--- a/src/gpu/GrDrawTarget.cpp
+++ b/src/gpu/GrDrawTarget.cpp
@@ -391,7 +391,7 @@ bool GrDrawTarget::checkDraw(GrPrimitiveType type, int startVertex,
SkASSERT(drawState.getRenderTarget());
if (drawState.hasGeometryProcessor()) {
- const GrGeometryProcessor* gp = drawState.getGeometryProcessor();
+ const GrGeometryProcessor* gp = drawState.getGeometryProcessor()->getProcessor();
int numTextures = gp->numTextures();
for (int t = 0; t < numTextures; ++t) {
GrTexture* texture = gp->texture(t);
diff --git a/src/gpu/GrOptDrawState.cpp b/src/gpu/GrOptDrawState.cpp
index 7c8710f7d6..b3d90f7310 100644
--- a/src/gpu/GrOptDrawState.cpp
+++ b/src/gpu/GrOptDrawState.cpp
@@ -54,7 +54,7 @@ GrOptDrawState::GrOptDrawState(const GrDrawState& drawState,
// Copy GeometryProcesssor from DS or ODS
if (drawState.hasGeometryProcessor()) {
- fGeometryProcessor.initAndRef(drawState.fGeometryProcessor);
+ fGeometryProcessor.reset(SkNEW_ARGS(GrGeometryStage, (*drawState.getGeometryProcessor())));
} else {
fGeometryProcessor.reset(NULL);
}
@@ -305,8 +305,8 @@ void GrOptDrawState::getStageStats(const GrDrawState& ds, int firstColorStageIdx
get_stage_stats(stage, &fReadsDst, &fReadsFragPosition);
}
if (ds.hasGeometryProcessor()) {
- const GrGeometryProcessor& gp = *ds.getGeometryProcessor();
- fReadsFragPosition = fReadsFragPosition || gp.willReadFragmentPosition();
+ const GrGeometryStage& stage = *ds.getGeometryProcessor();
+ fReadsFragPosition = fReadsFragPosition || stage.getProcessor()->willReadFragmentPosition();
}
}
@@ -354,7 +354,9 @@ bool GrOptDrawState::isEqual(const GrOptDrawState& that) const {
if (this->hasGeometryProcessor()) {
if (!that.hasGeometryProcessor()) {
return false;
- } else if (!this->getGeometryProcessor()->isEqual(*that.getGeometryProcessor())) {
+ } else if (!GrProcessorStage::AreCompatible(*this->getGeometryProcessor(),
+ *that.getGeometryProcessor(),
+ explicitLocalCoords)) {
return false;
}
} else if (that.hasGeometryProcessor()) {
@@ -362,8 +364,8 @@ bool GrOptDrawState::isEqual(const GrOptDrawState& that) const {
}
for (int i = 0; i < this->numFragmentStages(); i++) {
- if (!GrFragmentStage::AreCompatible(this->getFragmentStage(i), that.getFragmentStage(i),
- explicitLocalCoords)) {
+ if (!GrProcessorStage::AreCompatible(this->getFragmentStage(i), that.getFragmentStage(i),
+ explicitLocalCoords)) {
return false;
}
}
diff --git a/src/gpu/GrOptDrawState.h b/src/gpu/GrOptDrawState.h
index f47913a41a..1c439bbff1 100644
--- a/src/gpu/GrOptDrawState.h
+++ b/src/gpu/GrOptDrawState.h
@@ -127,7 +127,7 @@ public:
}
bool hasGeometryProcessor() const { return SkToBool(fGeometryProcessor.get()); }
- const GrGeometryProcessor* getGeometryProcessor() const { return fGeometryProcessor.get(); }
+ const GrGeometryStage* getGeometryProcessor() const { return fGeometryProcessor.get(); }
const GrFragmentStage& getColorStage(int idx) const {
SkASSERT(idx < this->numColorStages());
return fFragmentStages[idx];
@@ -441,12 +441,11 @@ private:
GrBlendCoeff fDstBlend;
typedef SkSTArray<8, GrFragmentStage> FragmentStageArray;
- typedef GrProgramElementRef<const GrGeometryProcessor> ProgramGeometryProcessor;
- ProgramGeometryProcessor fGeometryProcessor;
- FragmentStageArray fFragmentStages;
+ SkAutoTDelete<GrGeometryStage> fGeometryProcessor;
+ FragmentStageArray fFragmentStages;
// This function is equivalent to the offset into fFragmentStages where coverage stages begin.
- int fNumColorStages;
+ int fNumColorStages;
// This is simply a different representation of info in fVertexAttribs and thus does
// not need to be compared in op==.
diff --git a/src/gpu/GrProcessor.cpp b/src/gpu/GrProcessor.cpp
index 1732e3a27a..71dfaae912 100644
--- a/src/gpu/GrProcessor.cpp
+++ b/src/gpu/GrProcessor.cpp
@@ -103,6 +103,11 @@ const char* GrProcessor::name() const {
return this->getFactory().name();
}
+void GrProcessor::addCoordTransform(const GrCoordTransform* transform) {
+ fCoordTransforms.push_back(transform);
+ SkDEBUGCODE(transform->setInEffect();)
+}
+
void GrProcessor::addTextureAccess(const GrTextureAccess* access) {
fTextureAccesses.push_back(access);
this->addGpuResource(access->getProgramTexture());
@@ -118,6 +123,10 @@ void GrProcessor::operator delete(void* target) {
#ifdef SK_DEBUG
void GrProcessor::assertEquality(const GrProcessor& other) const {
+ SkASSERT(this->numTransforms() == other.numTransforms());
+ for (int i = 0; i < this->numTransforms(); ++i) {
+ SkASSERT(this->coordTransform(i) == other.coordTransform(i));
+ }
SkASSERT(this->numTextures() == other.numTextures());
for (int i = 0; i < this->numTextures(); ++i) {
SkASSERT(this->textureAccess(i) == other.textureAccess(i));
@@ -164,11 +173,5 @@ bool GrProcessor::InvariantOutput::validPreMulColor() const {
}
return true;
}
-#endif // end DEBUG
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
+#endif
-void GrFragmentProcessor::addCoordTransform(const GrCoordTransform* transform) {
- fCoordTransforms.push_back(transform);
- SkDEBUGCODE(transform->setInEffect();)
-}
diff --git a/src/gpu/effects/GrConfigConversionEffect.h b/src/gpu/effects/GrConfigConversionEffect.h
index 8c65dce506..aa2c87482e 100644
--- a/src/gpu/effects/GrConfigConversionEffect.h
+++ b/src/gpu/effects/GrConfigConversionEffect.h
@@ -10,7 +10,7 @@
#include "GrSingleTextureEffect.h"
-class GrFragmentStage;
+class GrProcessorStage;
class GrGLConfigConversionEffect;
/**
diff --git a/src/gpu/gl/GrGLProcessor.h b/src/gpu/gl/GrGLProcessor.h
index 04870779a3..5f698325fb 100644
--- a/src/gpu/gl/GrGLProcessor.h
+++ b/src/gpu/gl/GrGLProcessor.h
@@ -114,7 +114,6 @@ public:
@param samplers Contains one entry for each GrTextureAccess of the GrProcessor. These
can be passed to the builder to emit texture reads in the generated
code.
- TODO this should take a struct
*/
virtual void emitCode(GrGLFPBuilder* builder,
const GrFragmentProcessor& effect,
diff --git a/src/gpu/gl/GrGLProgram.cpp b/src/gpu/gl/GrGLProgram.cpp
index 2216fb1c5a..e0d4939323 100644
--- a/src/gpu/gl/GrGLProgram.cpp
+++ b/src/gpu/gl/GrGLProgram.cpp
@@ -10,7 +10,6 @@
#include "GrAllocator.h"
#include "GrProcessor.h"
#include "GrCoordTransform.h"
-#include "GrGLGeometryProcessor.h"
#include "GrGLProcessor.h"
#include "GrGpuGL.h"
#include "GrGLPathRendering.h"
@@ -25,7 +24,7 @@
/**
* Retrieves the final matrix that a transform needs to apply to its source coords.
*/
-static SkMatrix get_transform_matrix(const GrFragmentStage& processorStage,
+static SkMatrix get_transform_matrix(const GrProcessorStage& processorStage,
bool useExplicitLocalCoords,
int transformIdx) {
const GrCoordTransform& coordTransform =
@@ -60,15 +59,17 @@ GrGLProgram::GrGLProgram(GrGpuGL* gpu,
const BuiltinUniformHandles& builtinUniforms,
GrGLuint programID,
const UniformInfoArray& uniforms,
- GrGLInstalledGeoProc* geometryProcessor,
- GrGLInstalledFragProcs* fragmentProcessors)
+ GrGLInstalledProcessors* geometryProcessor,
+ GrGLInstalledProcessors* colorProcessors,
+ GrGLInstalledProcessors* coverageProcessors)
: fColor(GrColor_ILLEGAL)
, fCoverage(GrColor_ILLEGAL)
, fDstCopyTexUnit(-1)
, fBuiltinUniformHandles(builtinUniforms)
, fProgramID(programID)
- , fGeometryProcessor(geometryProcessor)
- , fFragmentProcessors(SkRef(fragmentProcessors))
+ , fGeometryProcessor(SkSafeRef(geometryProcessor))
+ , fColorEffects(SkRef(colorProcessors))
+ , fCoverageEffects(SkRef(coverageProcessors))
, fDesc(desc)
, fGpu(gpu)
, fProgramDataManager(gpu, uniforms) {
@@ -95,24 +96,28 @@ void GrGLProgram::initSamplerUniforms() {
if (fGeometryProcessor.get()) {
this->initSamplers(fGeometryProcessor.get(), &texUnitIdx);
}
- int numProcs = fFragmentProcessors->fProcs.count();
- for (int i = 0; i < numProcs; i++) {
- this->initSamplers(fFragmentProcessors->fProcs[i], &texUnitIdx);
- }
+ this->initSamplers(fColorEffects.get(), &texUnitIdx);
+ this->initSamplers(fCoverageEffects.get(), &texUnitIdx);
}
-void GrGLProgram::initSamplers(GrGLInstalledProc* ip, int* texUnitIdx) {
- SkTArray<GrGLInstalledProc::Sampler, true>& samplers = ip->fSamplers;
- int numSamplers = samplers.count();
- for (int s = 0; s < numSamplers; ++s) {
- SkASSERT(samplers[s].fUniform.isValid());
- fProgramDataManager.setSampler(samplers[s].fUniform, *texUnitIdx);
- samplers[s].fTextureUnit = (*texUnitIdx)++;
+void GrGLProgram::initSamplers(GrGLInstalledProcessors* ip, int* texUnitIdx) {
+ int numEffects = ip->fGLProcessors.count();
+ SkASSERT(numEffects == ip->fSamplers.count());
+ for (int e = 0; e < numEffects; ++e) {
+ SkTArray<GrGLInstalledProcessors::Sampler, true>& samplers = ip->fSamplers[e];
+ int numSamplers = samplers.count();
+ for (int s = 0; s < numSamplers; ++s) {
+ SkASSERT(samplers[s].fUniform.isValid());
+ fProgramDataManager.setSampler(samplers[s].fUniform, *texUnitIdx);
+ samplers[s].fTextureUnit = (*texUnitIdx)++;
+ }
}
}
-void GrGLProgram::bindTextures(const GrGLInstalledProc* ip, const GrProcessor& processor) {
- const SkTArray<GrGLInstalledProc::Sampler, true>& samplers = ip->fSamplers;
+void GrGLProgram::bindTextures(const GrGLInstalledProcessors* ip,
+ const GrProcessor& processor,
+ int effectIdx) {
+ const SkTArray<GrGLInstalledProcessors::Sampler, true>& samplers = ip->fSamplers[effectIdx];
int numSamplers = samplers.count();
SkASSERT(numSamplers == processor.numTextures());
for (int s = 0; s < numSamplers; ++s) {
@@ -129,6 +134,9 @@ void GrGLProgram::bindTextures(const GrGLInstalledProc* ip, const GrProcessor& p
void GrGLProgram::setData(const GrOptDrawState& optState,
GrGpu::DrawType drawType,
+ const GrGeometryStage* geometryProcessor,
+ const GrFragmentStage* colorStages[],
+ const GrFragmentStage* coverageStages[],
const GrDeviceCoordTexture* dstCopy,
SharedGLState* sharedState) {
GrColor color = optState.getColor();
@@ -162,34 +170,25 @@ void GrGLProgram::setData(const GrOptDrawState& optState,
// we set the textures, and uniforms for installed processors in a generic way, but subclasses
// of GLProgram determine how to set coord transforms
if (fGeometryProcessor.get()) {
- SkASSERT(optState.hasGeometryProcessor());
- const GrGeometryProcessor& gp = *optState.getGeometryProcessor();
- fGeometryProcessor->fGLProc->setData(fProgramDataManager, gp);
- this->bindTextures(fGeometryProcessor, gp);
+ SkASSERT(geometryProcessor);
+ this->setData<GrGeometryStage>(&geometryProcessor, fGeometryProcessor.get());
}
- this->setFragmentData(optState);
+ this->setData<GrFragmentStage>(colorStages, fColorEffects.get());
+ this->setData<GrFragmentStage>(coverageStages, fCoverageEffects.get());
// Some of GrGLProgram subclasses need to update state here
this->didSetData(drawType);
}
-void GrGLProgram::setFragmentData(const GrOptDrawState& optState) {
- int numProcessors = fFragmentProcessors->fProcs.count();
- for (int e = 0; e < numProcessors; ++e) {
- const GrFragmentStage& stage = optState.getFragmentStage(e);
- const GrProcessor& processor = *stage.getProcessor();
- fFragmentProcessors->fProcs[e]->fGLProc->setData(fProgramDataManager, processor);
- this->setTransformData(stage, fFragmentProcessors->fProcs[e]);
- this->bindTextures(fFragmentProcessors->fProcs[e], processor);
- }
-}
-void GrGLProgram::setTransformData(const GrFragmentStage& processor, GrGLInstalledFragProc* ip) {
- SkTArray<GrGLInstalledFragProc::Transform, true>& transforms = ip->fTransforms;
+void GrGLProgram::setTransformData(const GrProcessorStage& processor,
+ int effectIdx,
+ GrGLInstalledProcessors* ip) {
+ SkTArray<GrGLInstalledProcessors::Transform, true>& transforms = ip->fTransforms[effectIdx];
int numTransforms = transforms.count();
SkASSERT(numTransforms == processor.getProcessor()->numTransforms());
for (int t = 0; t < numTransforms; ++t) {
SkASSERT(transforms[t].fHandle.isValid());
- const SkMatrix& matrix = get_transform_matrix(processor, ip->fLocalCoordAttrib, t);
+ const SkMatrix& matrix = get_transform_matrix(processor, ip->fHasExplicitLocalCoords, t);
if (!transforms[t].fCurrentValue.cheapEqualTo(matrix)) {
fProgramDataManager.setSkMatrix(transforms[t].fHandle.convertToUniformHandle(), matrix);
transforms[t].fCurrentValue = matrix;
@@ -322,8 +321,10 @@ GrGLNvprProgramBase::GrGLNvprProgramBase(GrGpuGL* gpu,
const BuiltinUniformHandles& builtinUniforms,
GrGLuint programID,
const UniformInfoArray& uniforms,
- GrGLInstalledFragProcs* fragmentProcessors)
- : INHERITED(gpu, desc, builtinUniforms, programID, uniforms, NULL, fragmentProcessors) {
+ GrGLInstalledProcessors* colorProcessors,
+ GrGLInstalledProcessors* coverageProcessors)
+ : INHERITED(gpu, desc, builtinUniforms, programID, uniforms, NULL, colorProcessors,
+ coverageProcessors) {
}
void GrGLNvprProgramBase::onSetMatrixAndRenderTargetHeight(GrGpu::DrawType drawType,
@@ -342,9 +343,11 @@ GrGLNvprProgram::GrGLNvprProgram(GrGpuGL* gpu,
const BuiltinUniformHandles& builtinUniforms,
GrGLuint programID,
const UniformInfoArray& uniforms,
- GrGLInstalledFragProcs* fragmentProcessors,
+ GrGLInstalledProcessors* colorProcessors,
+ GrGLInstalledProcessors* coverageProcessors,
const SeparableVaryingInfoArray& separableVaryings)
- : INHERITED(gpu, desc, builtinUniforms, programID, uniforms, fragmentProcessors) {
+ : INHERITED(gpu, desc, builtinUniforms, programID, uniforms, colorProcessors,
+ coverageProcessors) {
int count = separableVaryings.count();
fVaryings.push_back_n(count);
for (int i = 0; i < count; i++) {
@@ -362,13 +365,15 @@ void GrGLNvprProgram::didSetData(GrGpu::DrawType drawType) {
SkASSERT(GrGpu::IsPathRenderingDrawType(drawType));
}
-void GrGLNvprProgram::setTransformData(const GrFragmentStage& proc, GrGLInstalledFragProc* ip) {
- SkTArray<GrGLInstalledFragProc::Transform, true>& transforms = ip->fTransforms;
+void GrGLNvprProgram::setTransformData(const GrProcessorStage& processor,
+ int effectIdx,
+ GrGLInstalledProcessors* ip) {
+ SkTArray<GrGLInstalledProcessors::Transform, true>& transforms = ip->fTransforms[effectIdx];
int numTransforms = transforms.count();
- SkASSERT(numTransforms == proc.getProcessor()->numTransforms());
+ SkASSERT(numTransforms == processor.getProcessor()->numTransforms());
for (int t = 0; t < numTransforms; ++t) {
SkASSERT(transforms[t].fHandle.isValid());
- const SkMatrix& transform = get_transform_matrix(proc, ip->fLocalCoordAttrib, t);
+ const SkMatrix& transform = get_transform_matrix(processor, ip->fHasExplicitLocalCoords, t);
if (transforms[t].fCurrentValue.cheapEqualTo(transform)) {
continue;
}
@@ -387,13 +392,15 @@ void GrGLNvprProgram::setTransformData(const GrFragmentStage& proc, GrGLInstalle
//////////////////////////////////////////////////////////////////////////////////////
GrGLLegacyNvprProgram::GrGLLegacyNvprProgram(GrGpuGL* gpu,
- const GrGLProgramDesc& desc,
- const BuiltinUniformHandles& builtinUniforms,
- GrGLuint programID,
- const UniformInfoArray& uniforms,
- GrGLInstalledFragProcs* fps,
- int texCoordSetCnt)
- : INHERITED(gpu, desc, builtinUniforms, programID, uniforms, fps)
+ const GrGLProgramDesc& desc,
+ const BuiltinUniformHandles& builtinUniforms,
+ GrGLuint programID,
+ const UniformInfoArray& uniforms,
+ GrGLInstalledProcessors* colorProcessors,
+ GrGLInstalledProcessors* coverageProcessors,
+ int texCoordSetCnt)
+ : INHERITED(gpu, desc, builtinUniforms, programID, uniforms, colorProcessors,
+ coverageProcessors)
, fTexCoordSetCnt(texCoordSetCnt) {
}
@@ -402,16 +409,17 @@ void GrGLLegacyNvprProgram::didSetData(GrGpu::DrawType drawType) {
fGpu->glPathRendering()->flushPathTexGenSettings(fTexCoordSetCnt);
}
-void
-GrGLLegacyNvprProgram::setTransformData(const GrFragmentStage& proc, GrGLInstalledFragProc* ip) {
+void GrGLLegacyNvprProgram::setTransformData(const GrProcessorStage& processorStage,
+ int effectIdx,
+ GrGLInstalledProcessors* ip) {
// We've hidden the texcoord index in the first entry of the transforms array for each effect
- int texCoordIndex = ip->fTransforms[0].fHandle.handle();
- int numTransforms = proc.getProcessor()->numTransforms();
+ int texCoordIndex = ip->fTransforms[effectIdx][0].fHandle.handle();
+ int numTransforms = processorStage.getProcessor()->numTransforms();
for (int t = 0; t < numTransforms; ++t) {
- const SkMatrix& transform = get_transform_matrix(proc, false, t);
+ const SkMatrix& transform = get_transform_matrix(processorStage, false, t);
GrGLPathRendering::PathTexGenComponents components =
GrGLPathRendering::kST_PathTexGenComponents;
- if (proc.isPerspectiveCoordTransform(t, false)) {
+ if (processorStage.isPerspectiveCoordTransform(t, false)) {
components = GrGLPathRendering::kSTR_PathTexGenComponents;
}
fGpu->glPathRendering()->enablePathTexGen(texCoordIndex++, components, transform);
diff --git a/src/gpu/gl/GrGLProgram.h b/src/gpu/gl/GrGLProgram.h
index e8aef35f1d..fc441e5d76 100644
--- a/src/gpu/gl/GrGLProgram.h
+++ b/src/gpu/gl/GrGLProgram.h
@@ -152,6 +152,9 @@ public:
*/
void setData(const GrOptDrawState&,
GrGpu::DrawType,
+ const GrGeometryStage* geometryProcessor,
+ const GrFragmentStage* colorStages[],
+ const GrFragmentStage* coverageStages[],
const GrDeviceCoordTexture* dstCopy, // can be NULL
SharedGLState*);
@@ -164,12 +167,13 @@ protected:
const BuiltinUniformHandles&,
GrGLuint programID,
const UniformInfoArray&,
- GrGLInstalledGeoProc* geometryProcessor,
- GrGLInstalledFragProcs* fragmentProcessors);
+ GrGLInstalledProcessors* geometryProcessor,
+ GrGLInstalledProcessors* colorProcessors,
+ GrGLInstalledProcessors* coverageProcessors);
// Sets the texture units for samplers.
void initSamplerUniforms();
- void initSamplers(GrGLInstalledProc*, int* texUnitIdx);
+ void initSamplers(GrGLInstalledProcessors* processors, int* texUnitIdx);
// Helper for setData(). Makes GL calls to specify the initial color when there is not
// per-vertex colors.
@@ -180,9 +184,23 @@ protected:
void setCoverage(const GrOptDrawState&, GrColor coverage, SharedGLState*);
// A templated helper to loop over effects, set the transforms(via subclass) and bind textures
- void setFragmentData(const GrOptDrawState&);
- virtual void setTransformData(const GrFragmentStage& effectStage, GrGLInstalledFragProc* pe);
- void bindTextures(const GrGLInstalledProc*, const GrProcessor&);
+ template <class ProcessorStage>
+ void setData(const ProcessorStage* effectStages[],
+ GrGLInstalledProcessors* installedProcessors) {
+ int numEffects = installedProcessors->fGLProcessors.count();
+ SkASSERT(numEffects == installedProcessors->fTransforms.count());
+ SkASSERT(numEffects == installedProcessors->fSamplers.count());
+ for (int e = 0; e < numEffects; ++e) {
+ const GrProcessor& effect = *effectStages[e]->getProcessor();
+ installedProcessors->fGLProcessors[e]->setData(fProgramDataManager, effect);
+ this->setTransformData(*effectStages[e], e, installedProcessors);
+ this->bindTextures(installedProcessors, effect, e);
+ }
+ }
+ virtual void setTransformData(const GrProcessorStage& effectStage,
+ int effectIdx,
+ GrGLInstalledProcessors* pe);
+ void bindTextures(const GrGLInstalledProcessors*, const GrProcessor&, int effectIdx);
/*
* Legacy NVPR needs a hook here to flush path tex gen settings.
@@ -203,8 +221,9 @@ protected:
GrGLuint fProgramID;
// the installed effects
- SkAutoTDelete<GrGLInstalledGeoProc> fGeometryProcessor;
- SkAutoTUnref<GrGLInstalledFragProcs> fFragmentProcessors;
+ SkAutoTUnref<GrGLInstalledProcessors> fGeometryProcessor;
+ SkAutoTUnref<GrGLInstalledProcessors> fColorEffects;
+ SkAutoTUnref<GrGLInstalledProcessors> fCoverageEffects;
GrGLProgramDesc fDesc;
GrGpuGL* fGpu;
@@ -229,7 +248,8 @@ protected:
const BuiltinUniformHandles&,
GrGLuint programID,
const UniformInfoArray&,
- GrGLInstalledFragProcs* fragmentProcessors);
+ GrGLInstalledProcessors* colorProcessors,
+ GrGLInstalledProcessors* coverageProcessors);
virtual void onSetMatrixAndRenderTargetHeight(GrGpu::DrawType, const GrOptDrawState&);
typedef GrGLProgram INHERITED;
@@ -247,10 +267,13 @@ private:
const BuiltinUniformHandles&,
GrGLuint programID,
const UniformInfoArray&,
- GrGLInstalledFragProcs* fragmentProcessors,
+ GrGLInstalledProcessors* colorProcessors,
+ GrGLInstalledProcessors* coverageProcessors,
const SeparableVaryingInfoArray& separableVaryings);
virtual void didSetData(GrGpu::DrawType) SK_OVERRIDE;
- virtual void setTransformData(const GrFragmentStage&, GrGLInstalledFragProc*) SK_OVERRIDE;
+ virtual void setTransformData(const GrProcessorStage&,
+ int effectIdx,
+ GrGLInstalledProcessors*) SK_OVERRIDE;
struct Varying {
GrGLint fLocation;
@@ -275,10 +298,13 @@ private:
const BuiltinUniformHandles&,
GrGLuint programID,
const UniformInfoArray&,
- GrGLInstalledFragProcs* fragmentProcessors,
+ GrGLInstalledProcessors* colorProcessors,
+ GrGLInstalledProcessors* coverageProcessors,
int texCoordSetCnt);
virtual void didSetData(GrGpu::DrawType) SK_OVERRIDE;
- virtual void setTransformData(const GrFragmentStage&, GrGLInstalledFragProc*) SK_OVERRIDE;
+ virtual void setTransformData(const GrProcessorStage&,
+ int effectIdx,
+ GrGLInstalledProcessors*) SK_OVERRIDE;
int fTexCoordSetCnt;
diff --git a/src/gpu/gl/GrGLProgramDesc.cpp b/src/gpu/gl/GrGLProgramDesc.cpp
index 224411e51c..0c85c99a8a 100644
--- a/src/gpu/gl/GrGLProgramDesc.cpp
+++ b/src/gpu/gl/GrGLProgramDesc.cpp
@@ -60,10 +60,10 @@ static bool swizzle_requires_alpha_remapping(const GrGLCaps& caps,
return false;
}
-static uint32_t gen_attrib_key(const GrGeometryProcessor& proc) {
+static uint32_t gen_attrib_key(const GrGeometryProcessor* effect) {
uint32_t key = 0;
- const GrGeometryProcessor::VertexAttribArray& vars = proc.getVertexAttribs();
+ const GrGeometryProcessor::VertexAttribArray& vars = effect->getVertexAttribs();
int numAttributes = vars.count();
SkASSERT(numAttributes <= 2);
for (int a = 0; a < numAttributes; ++a) {
@@ -73,7 +73,7 @@ static uint32_t gen_attrib_key(const GrGeometryProcessor& proc) {
return key;
}
-static uint32_t gen_transform_key(const GrFragmentStage& effectStage,
+static uint32_t gen_transform_key(const GrProcessorStage& effectStage,
bool useExplicitLocalCoords) {
uint32_t totalKey = 0;
int numTransforms = effectStage.getProcessor()->numTransforms();
@@ -96,11 +96,11 @@ static uint32_t gen_transform_key(const GrFragmentStage& effectStage,
return totalKey;
}
-static uint32_t gen_texture_key(const GrProcessor& proc, const GrGLCaps& caps) {
+static uint32_t gen_texture_key(const GrProcessor* effect, const GrGLCaps& caps) {
uint32_t key = 0;
- int numTextures = proc.numTextures();
+ int numTextures = effect->numTextures();
for (int t = 0; t < numTextures; ++t) {
- const GrTextureAccess& access = proc.textureAccess(t);
+ const GrTextureAccess& access = effect->textureAccess(t);
uint32_t configComponentMask = GrPixelConfigComponentMask(access.getTexture()->config());
if (swizzle_requires_alpha_remapping(caps, configComponentMask, access.swizzleMask())) {
key |= 1 << t;
@@ -115,61 +115,101 @@ static uint32_t gen_texture_key(const GrProcessor& proc, const GrGLCaps& caps) {
* in its key (e.g. the pixel format of textures used). So we create a meta-key for
* every effect using this function. It is also responsible for inserting the effect's class ID
* which must be different for every GrProcessor subclass. It can fail if an effect uses too many
- * textures, transforms, etc, for the space allotted in the meta-key. NOTE, both FPs and GPs share
- * this function because it is hairy, though FPs do not have attribs, and GPs do not have transforms
+ * textures, transforms, etc, for the space allotted in the meta-key.
*/
-static bool get_meta_key(const GrProcessor& proc,
- const GrGLCaps& caps,
- uint32_t transformKey,
- uint32_t attribKey,
- GrProcessorKeyBuilder* b,
- uint16_t* processorKeySize) {
- const GrBackendProcessorFactory& factory = proc.getFactory();
- factory.getGLProcessorKey(proc, caps, b);
+
+static uint32_t* get_processor_meta_key(const GrProcessorStage& processorStage,
+ bool useExplicitLocalCoords,
+ const GrGLCaps& caps,
+ GrProcessorKeyBuilder* b) {
+
+ uint32_t textureKey = gen_texture_key(processorStage.getProcessor(), caps);
+ uint32_t transformKey = gen_transform_key(processorStage,useExplicitLocalCoords);
+ uint32_t classID = processorStage.getProcessor()->getFactory().effectClassID();
+
+ // Currently we allow 16 bits for each of the above portions of the meta-key. Fail if they
+ // don't fit.
+ static const uint32_t kMetaKeyInvalidMask = ~((uint32_t) SK_MaxU16);
+ if ((textureKey | transformKey | classID) & kMetaKeyInvalidMask) {
+ return NULL;
+ }
+
+ uint32_t* key = b->add32n(2);
+ key[0] = (textureKey << 16 | transformKey);
+ key[1] = (classID << 16);
+ return key;
+}
+
+static bool get_fp_key(const GrProcessorStage& stage,
+ const GrGLCaps& caps,
+ bool useExplicitLocalCoords,
+ GrProcessorKeyBuilder* b,
+ uint16_t* processorKeySize) {
+ const GrProcessor& effect = *stage.getProcessor();
+ const GrBackendProcessorFactory& factory = effect.getFactory();
+ factory.getGLProcessorKey(effect, caps, b);
+ size_t size = b->size();
+ if (size > SK_MaxU16) {
+ *processorKeySize = 0; // suppresses a warning.
+ return false;
+ }
+ *processorKeySize = SkToU16(size);
+ if (NULL == get_processor_meta_key(stage, useExplicitLocalCoords, caps, b)) {
+ return false;
+ }
+ return true;
+}
+
+static bool get_gp_key(const GrGeometryStage& stage,
+ const GrGLCaps& caps,
+ bool useExplicitLocalCoords,
+ GrProcessorKeyBuilder* b,
+ uint16_t* processorKeySize) {
+ const GrProcessor& effect = *stage.getProcessor();
+ const GrBackendProcessorFactory& factory = effect.getFactory();
+ factory.getGLProcessorKey(effect, caps, b);
size_t size = b->size();
if (size > SK_MaxU16) {
*processorKeySize = 0; // suppresses a warning.
return false;
}
*processorKeySize = SkToU16(size);
- uint32_t textureKey = gen_texture_key(proc, caps);
- uint32_t classID = proc.getFactory().effectClassID();
+ uint32_t* key = get_processor_meta_key(stage, useExplicitLocalCoords, caps, b);
+ if (NULL == key) {
+ return false;
+ }
+ uint32_t attribKey = gen_attrib_key(stage.getProcessor());
// Currently we allow 16 bits for each of the above portions of the meta-key. Fail if they
// don't fit.
static const uint32_t kMetaKeyInvalidMask = ~((uint32_t) SK_MaxU16);
- if ((textureKey | transformKey | classID) & kMetaKeyInvalidMask) {
- return false;
+ if ((attribKey) & kMetaKeyInvalidMask) {
+ return false;
}
- uint32_t* key = b->add32n(2);
- key[0] = (textureKey << 16 | transformKey);
- key[1] = (classID << 16);
+ key[1] |= attribKey;
return true;
}
struct GeometryProcessorKeyBuilder {
- typedef GrGeometryProcessor StagedProcessor;
- static bool GetProcessorKey(const GrGeometryProcessor& gp,
+ typedef GrGeometryStage StagedProcessor;
+ static bool GetProcessorKey(const GrGeometryStage& gpStage,
const GrGLCaps& caps,
- bool,
+ bool requiresLocalCoordAttrib,
GrProcessorKeyBuilder* b,
- uint16_t* keySize) {
- /* 0 because no transforms on a GP */
- return get_meta_key(gp, caps, 0, gen_attrib_key(gp), b, keySize);
+ uint16_t* processorKeySize) {
+ return get_gp_key(gpStage, caps, requiresLocalCoordAttrib, b, processorKeySize);
}
};
struct FragmentProcessorKeyBuilder {
typedef GrFragmentStage StagedProcessor;
- static bool GetProcessorKey(const GrFragmentStage& fps,
+ static bool GetProcessorKey(const GrFragmentStage& fpStage,
const GrGLCaps& caps,
- bool useLocalCoords,
+ bool requiresLocalCoordAttrib,
GrProcessorKeyBuilder* b,
- uint16_t* keySize) {
- /* 0 because no attribs on a fP */
- return get_meta_key(*fps.getProcessor(), caps, gen_transform_key(fps, useLocalCoords), 0,
- b, keySize);
+ uint16_t* processorKeySize) {
+ return get_fp_key(fpStage, caps, requiresLocalCoordAttrib, b, processorKeySize);
}
};
@@ -202,9 +242,17 @@ GrGLProgramDesc::BuildStagedProcessorKey(const typename ProcessorKeyBuilder::Sta
bool GrGLProgramDesc::Build(const GrOptDrawState& optState,
GrGpu::DrawType drawType,
+ GrBlendCoeff srcCoeff,
+ GrBlendCoeff dstCoeff,
GrGpuGL* gpu,
const GrDeviceCoordTexture* dstCopy,
+ const GrGeometryStage** geometryProcessor,
+ SkTArray<const GrFragmentStage*, true>* colorStages,
+ SkTArray<const GrFragmentStage*, true>* coverageStages,
GrGLProgramDesc* desc) {
+ colorStages->reset();
+ coverageStages->reset();
+
bool inputColorIsUsed = optState.inputColorIsUsed();
bool inputCoverageIsUsed = optState.inputCoverageIsUsed();
@@ -226,17 +274,29 @@ bool GrGLProgramDesc::Build(const GrOptDrawState& optState,
// We can only have one effect which touches the vertex shader
if (optState.hasGeometryProcessor()) {
- if (!BuildStagedProcessorKey<GeometryProcessorKeyBuilder>(*optState.getGeometryProcessor(),
+ const GrGeometryStage& gpStage = *optState.getGeometryProcessor();
+ if (!BuildStagedProcessorKey<GeometryProcessorKeyBuilder>(gpStage,
gpu->glCaps(),
- false,
+ requiresLocalCoordAttrib,
desc,
&offsetAndSizeIndex)) {
return false;
}
+ *geometryProcessor = &gpStage;
}
- for (int s = 0; s < optState.numFragmentStages(); ++s) {
- if (!BuildStagedProcessorKey<FragmentProcessorKeyBuilder>(optState.getFragmentStage(s),
+ for (int s = 0; s < optState.numColorStages(); ++s) {
+ if (!BuildStagedProcessorKey<FragmentProcessorKeyBuilder>(optState.getColorStage(s),
+ gpu->glCaps(),
+ requiresLocalCoordAttrib,
+ desc,
+ &offsetAndSizeIndex)) {
+ return false;
+ }
+ }
+
+ for (int s = 0; s < optState.numCoverageStages(); ++s) {
+ if (!BuildStagedProcessorKey<FragmentProcessorKeyBuilder>(optState.getCoverageStage(s),
gpu->glCaps(),
requiresLocalCoordAttrib,
desc,
@@ -339,8 +399,15 @@ bool GrGLProgramDesc::Build(const GrOptDrawState& optState,
header->fPrimaryOutputType = optState.getPrimaryOutputType();
header->fSecondaryOutputType = optState.getSecondaryOutputType();
- header->fColorEffectCnt = optState.numColorStages();
- header->fCoverageEffectCnt = optState.numCoverageStages();
+ for (int s = 0; s < optState.numColorStages(); ++s) {
+ colorStages->push_back(&optState.getColorStage(s));
+ }
+ for (int s = 0; s < optState.numCoverageStages(); ++s) {
+ coverageStages->push_back(&optState.getCoverageStage(s));
+ }
+
+ header->fColorEffectCnt = colorStages->count();
+ header->fCoverageEffectCnt = coverageStages->count();
desc->finalize();
return true;
}
diff --git a/src/gpu/gl/GrGLProgramDesc.h b/src/gpu/gl/GrGLProgramDesc.h
index 4e1be5b2f9..9bf7553b61 100644
--- a/src/gpu/gl/GrGLProgramDesc.h
+++ b/src/gpu/gl/GrGLProgramDesc.h
@@ -43,8 +43,13 @@ public:
*/
static bool Build(const GrOptDrawState&,
GrGpu::DrawType,
+ GrBlendCoeff srcCoeff,
+ GrBlendCoeff dstCoeff,
GrGpuGL*,
- const GrDeviceCoordTexture*,
+ const GrDeviceCoordTexture* dstCopy,
+ const GrGeometryStage** geometryProcessor,
+ SkTArray<const GrFragmentStage*, true>* colorStages,
+ SkTArray<const GrFragmentStage*, true>* coverageStages,
GrGLProgramDesc*);
bool hasGeometryProcessor() const {
@@ -155,23 +160,26 @@ private:
const KeyHeader& getHeader() const { return *this->atOffset<KeyHeader, kHeaderOffset>(); }
/** Used to provide effects' keys to their emitCode() function. */
- class ProcKeyProvider {
+ class EffectKeyProvider {
public:
- enum ProcessorType {
- kGeometry_ProcessorType,
- kFragment_ProcessorType,
+ enum EffectType {
+ kGeometryProcessor_EffectType,
+ kColor_EffectType,
+ kCoverage_EffectType,
};
- ProcKeyProvider(const GrGLProgramDesc* desc, ProcessorType type)
- : fDesc(desc), fBaseIndex(0) {
+ EffectKeyProvider(const GrGLProgramDesc* desc, EffectType type) : fDesc(desc) {
switch (type) {
- case kGeometry_ProcessorType:
+ case kGeometryProcessor_EffectType:
// there can be only one
fBaseIndex = 0;
break;
- case kFragment_ProcessorType:
+ case kColor_EffectType:
fBaseIndex = desc->hasGeometryProcessor() ? 1 : 0;
break;
+ case kCoverage_EffectType:
+ fBaseIndex = desc->numColorEffects() + (desc->hasGeometryProcessor() ? 1 : 0);
+ break;
}
}
diff --git a/src/gpu/gl/GrGpuGL.h b/src/gpu/gl/GrGpuGL.h
index 24ab4ec14d..056f0935ec 100644
--- a/src/gpu/gl/GrGpuGL.h
+++ b/src/gpu/gl/GrGpuGL.h
@@ -181,7 +181,10 @@ private:
void abandon();
GrGLProgram* getProgram(const GrOptDrawState&,
const GrGLProgramDesc&,
- DrawType);
+ DrawType,
+ const GrGeometryStage* geometryProcessor,
+ const GrFragmentStage* colorStages[],
+ const GrFragmentStage* coverageStages[]);
private:
enum {
diff --git a/src/gpu/gl/GrGpuGL_program.cpp b/src/gpu/gl/GrGpuGL_program.cpp
index 6a09ebf64e..7dba5316a4 100644
--- a/src/gpu/gl/GrGpuGL_program.cpp
+++ b/src/gpu/gl/GrGpuGL_program.cpp
@@ -93,7 +93,10 @@ int GrGpuGL::ProgramCache::search(const GrGLProgramDesc& desc) const {
GrGLProgram* GrGpuGL::ProgramCache::getProgram(const GrOptDrawState& optState,
const GrGLProgramDesc& desc,
- DrawType type) {
+ DrawType type,
+ const GrGeometryStage* geometryProcessor,
+ const GrFragmentStage* colorStages[],
+ const GrFragmentStage* coverageStages[]) {
#ifdef PROGRAM_CACHE_STATS
++fTotalRequests;
#endif
@@ -128,7 +131,9 @@ GrGLProgram* GrGpuGL::ProgramCache::getProgram(const GrOptDrawState& optState,
#ifdef PROGRAM_CACHE_STATS
++fCacheMisses;
#endif
- GrGLProgram* program = GrGLProgramBuilder::CreateProgram(optState, desc, type, fGpu);
+ GrGLProgram* program = GrGLProgramBuilder::CreateProgram(optState, desc, type,
+ geometryProcessor, colorStages,
+ coverageStages, fGpu);
if (NULL == program) {
return NULL;
}
@@ -232,13 +237,30 @@ bool GrGpuGL::flushGraphicsState(DrawType type, const GrDeviceCoordTexture* dstC
return false;
}
+ const GrGeometryStage* geometryProcessor = NULL;
+ SkSTArray<8, const GrFragmentStage*, true> colorStages;
+ SkSTArray<8, const GrFragmentStage*, true> coverageStages;
GrGLProgramDesc desc;
- if (!GrGLProgramDesc::Build(*optState.get(), type, this, dstCopy, &desc)) {
+ if (!GrGLProgramDesc::Build(*optState.get(),
+ type,
+ srcCoeff,
+ dstCoeff,
+ this,
+ dstCopy,
+ &geometryProcessor,
+ &colorStages,
+ &coverageStages,
+ &desc)) {
SkDEBUGFAIL("Failed to generate GL program descriptor");
return false;
}
- fCurrentProgram.reset(fProgramCache->getProgram(*optState.get(), desc, type));
+ fCurrentProgram.reset(fProgramCache->getProgram(*optState.get(),
+ desc,
+ type,
+ geometryProcessor,
+ colorStages.begin(),
+ coverageStages.begin()));
if (NULL == fCurrentProgram.get()) {
SkDEBUGFAIL("Failed to create program!");
return false;
@@ -254,7 +276,13 @@ bool GrGpuGL::flushGraphicsState(DrawType type, const GrDeviceCoordTexture* dstC
this->flushBlend(*optState.get(), kDrawLines_DrawType == type, srcCoeff, dstCoeff);
- fCurrentProgram->setData(*optState.get(), type, dstCopy, &fSharedGLProgramState);
+ fCurrentProgram->setData(*optState.get(),
+ type,
+ geometryProcessor,
+ colorStages.begin(),
+ coverageStages.begin(),
+ dstCopy,
+ &fSharedGLProgramState);
}
GrGLRenderTarget* glRT = static_cast<GrGLRenderTarget*>(optState->getRenderTarget());
diff --git a/src/gpu/gl/builders/GrGLLegacyNvprProgramBuilder.cpp b/src/gpu/gl/builders/GrGLLegacyNvprProgramBuilder.cpp
index 1c1cb42122..acb4af10be 100644
--- a/src/gpu/gl/builders/GrGLLegacyNvprProgramBuilder.cpp
+++ b/src/gpu/gl/builders/GrGLLegacyNvprProgramBuilder.cpp
@@ -24,17 +24,20 @@ int GrGLLegacyNvprProgramBuilder::addTexCoordSets(int count) {
return firstFreeCoordSet;
}
-void GrGLLegacyNvprProgramBuilder::emitTransforms(const GrFragmentStage& processorStage,
+void GrGLLegacyNvprProgramBuilder::emitTransforms(const GrProcessorStage& processorStage,
GrGLProcessor::TransformedCoordsArray* outCoords,
- GrGLInstalledFragProc* ifp) {
+ GrGLInstalledProcessors* installedProcessors) {
int numTransforms = processorStage.getProcessor()->numTransforms();
int texCoordIndex = this->addTexCoordSets(numTransforms);
+ SkTArray<GrGLInstalledProcessors::Transform, true>& transforms =
+ installedProcessors->addTransforms();
+
// Use the first uniform location as the texcoord index. This may seem a bit hacky but it
// allows us to use one program effects object for all of our programs which really simplifies
// the code overall
- ifp->fTransforms.push_back_n(1);
- ifp->fTransforms[0].fHandle = GrGLInstalledFragProc::ShaderVarHandle(texCoordIndex);
+ transforms.push_back_n(1);
+ transforms[0].fHandle = GrGLInstalledProcessors::ShaderVarHandle(texCoordIndex);
SkString name;
for (int t = 0; t < numTransforms; ++t) {
@@ -48,5 +51,5 @@ void GrGLLegacyNvprProgramBuilder::emitTransforms(const GrFragmentStage& process
GrGLProgram* GrGLLegacyNvprProgramBuilder::createProgram(GrGLuint programID) {
return SkNEW_ARGS(GrGLLegacyNvprProgram, (fGpu, fDesc, fUniformHandles, programID, fUniforms,
- fFragmentProcessors.get(), fTexCoordSetCnt));
+ fColorEffects, fCoverageEffects, fTexCoordSetCnt));
}
diff --git a/src/gpu/gl/builders/GrGLLegacyNvprProgramBuilder.h b/src/gpu/gl/builders/GrGLLegacyNvprProgramBuilder.h
index dabec081b4..496fbd8726 100644
--- a/src/gpu/gl/builders/GrGLLegacyNvprProgramBuilder.h
+++ b/src/gpu/gl/builders/GrGLLegacyNvprProgramBuilder.h
@@ -18,9 +18,9 @@ public:
private:
int addTexCoordSets(int count);
- void emitTransforms(const GrFragmentStage&,
+ void emitTransforms(const GrProcessorStage&,
GrGLProcessor::TransformedCoordsArray* outCoords,
- GrGLInstalledFragProc*);
+ GrGLInstalledProcessors*);
int fTexCoordSetCnt;
diff --git a/src/gpu/gl/builders/GrGLNvprProgramBuilder.cpp b/src/gpu/gl/builders/GrGLNvprProgramBuilder.cpp
index a20b0d6b0d..e5eae9d884 100644
--- a/src/gpu/gl/builders/GrGLNvprProgramBuilder.cpp
+++ b/src/gpu/gl/builders/GrGLNvprProgramBuilder.cpp
@@ -18,13 +18,15 @@ GrGLNvprProgramBuilder::GrGLNvprProgramBuilder(GrGpuGL* gpu,
, fSeparableVaryingInfos(kVarsPerBlock) {
}
-void GrGLNvprProgramBuilder::emitTransforms(const GrFragmentStage& processorStage,
+void GrGLNvprProgramBuilder::emitTransforms(const GrProcessorStage& processorStage,
GrGLProcessor::TransformedCoordsArray* outCoords,
- GrGLInstalledFragProc* ifp) {
- const GrFragmentProcessor* effect = processorStage.getProcessor();
+ GrGLInstalledProcessors* installedProcessors) {
+ const GrProcessor* effect = processorStage.getProcessor();
int numTransforms = effect->numTransforms();
- ifp->fTransforms.push_back_n(numTransforms);
+ SkTArray<GrGLInstalledProcessors::Transform, true>& transforms =
+ installedProcessors->addTransforms();
+ transforms.push_back_n(numTransforms);
for (int t = 0; t < numTransforms; t++) {
GrSLType varyingType =
@@ -41,24 +43,24 @@ void GrGLNvprProgramBuilder::emitTransforms(const GrFragmentStage& processorStag
}
const char* vsVaryingName;
const char* fsVaryingName;
- ifp->fTransforms[t].fHandle = this->addSeparableVarying(varyingType, varyingName,
- &vsVaryingName, &fsVaryingName);
- ifp->fTransforms[t].fType = varyingType;
+ transforms[t].fHandle = this->addSeparableVarying(varyingType, varyingName,
+ &vsVaryingName, &fsVaryingName);
+ transforms[t].fType = varyingType;
SkNEW_APPEND_TO_TARRAY(outCoords, GrGLProcessor::TransformedCoords,
(SkString(fsVaryingName), varyingType));
}
}
-GrGLInstalledFragProc::ShaderVarHandle
+GrGLInstalledProcessors::ShaderVarHandle
GrGLNvprProgramBuilder::addSeparableVarying(GrSLType type,
- const char* name,
- const char** vsOutName,
- const char** fsInName) {
+ const char* name,
+ const char** vsOutName,
+ const char** fsInName) {
addVarying(type, name, vsOutName, fsInName);
SeparableVaryingInfo& varying = fSeparableVaryingInfos.push_back();
varying.fVariable = fFS.fInputs.back();
- return GrGLInstalledFragProc::ShaderVarHandle(fSeparableVaryingInfos.count() - 1);
+ return GrGLInstalledProcessors::ShaderVarHandle(fSeparableVaryingInfos.count() - 1);
}
void GrGLNvprProgramBuilder::resolveSeparableVaryings(GrGLuint programId) {
@@ -78,5 +80,5 @@ GrGLProgram* GrGLNvprProgramBuilder::createProgram(GrGLuint programID) {
// building
this->resolveSeparableVaryings(programID);
return SkNEW_ARGS(GrGLNvprProgram, (fGpu, fDesc, fUniformHandles, programID, fUniforms,
- fFragmentProcessors.get(), fSeparableVaryingInfos));
+ fColorEffects, fCoverageEffects, fSeparableVaryingInfos));
}
diff --git a/src/gpu/gl/builders/GrGLNvprProgramBuilder.h b/src/gpu/gl/builders/GrGLNvprProgramBuilder.h
index 4bf7e02414..cb1337521d 100644
--- a/src/gpu/gl/builders/GrGLNvprProgramBuilder.h
+++ b/src/gpu/gl/builders/GrGLNvprProgramBuilder.h
@@ -28,11 +28,11 @@ public:
virtual GrGLProgram* createProgram(GrGLuint programID);
private:
- virtual void emitTransforms(const GrFragmentStage&,
+ virtual void emitTransforms(const GrProcessorStage&,
GrGLProcessor::TransformedCoordsArray* outCoords,
- GrGLInstalledFragProc*) SK_OVERRIDE;
+ GrGLInstalledProcessors*) SK_OVERRIDE;
- typedef GrGLInstalledFragProc::ShaderVarHandle ShaderVarHandle;
+ typedef GrGLInstalledProcessors::ShaderVarHandle ShaderVarHandle;
/**
* Add a separable varying input variable to the current program.
diff --git a/src/gpu/gl/builders/GrGLProgramBuilder.cpp b/src/gpu/gl/builders/GrGLProgramBuilder.cpp
index 687c2fd4c9..fbf78d7634 100644
--- a/src/gpu/gl/builders/GrGLProgramBuilder.cpp
+++ b/src/gpu/gl/builders/GrGLProgramBuilder.cpp
@@ -32,13 +32,16 @@ const int GrGLProgramBuilder::kVarsPerBlock = 8;
GrGLProgram* GrGLProgramBuilder::CreateProgram(const GrOptDrawState& optState,
const GrGLProgramDesc& desc,
GrGpu::DrawType drawType,
+ const GrGeometryStage* geometryProcessor,
+ const GrFragmentStage* colorStages[],
+ const GrFragmentStage* coverageStages[],
GrGpuGL* gpu) {
// create a builder. This will be handed off to effects so they can use it to add
// uniforms, varyings, textures, etc
SkAutoTDelete<GrGLProgramBuilder> builder(CreateProgramBuilder(desc,
optState,
drawType,
- optState.hasGeometryProcessor(),
+ SkToBool(geometryProcessor),
gpu));
GrGLProgramBuilder* pb = builder.get();
@@ -71,7 +74,8 @@ GrGLProgram* GrGLProgramBuilder::CreateProgram(const GrOptDrawState& optState,
}
}
- pb->emitAndInstallProcs(optState, &inputColor, &inputCoverage);
+ pb->createAndEmitProcessors(geometryProcessor, colorStages, coverageStages, &inputColor,
+ &inputCoverage);
if (hasVertexShader) {
pb->fVS.transformSkiaToGLCoords();
@@ -112,15 +116,13 @@ GrGLProgramBuilder::CreateProgramBuilder(const GrGLProgramDesc& desc,
/////////////////////////////////////////////////////////////////////////////
-GrGLProgramBuilder::GrGLProgramBuilder(GrGpuGL* gpu,
- const GrOptDrawState& optState,
+GrGLProgramBuilder::GrGLProgramBuilder(GrGpuGL* gpu, const GrOptDrawState& optState,
const GrGLProgramDesc& desc)
: fVS(this)
, fGS(this)
, fFS(this, desc)
, fOutOfStage(true)
, fStageIndex(-1)
- , fGeometryProcessor(NULL)
, fOptState(optState)
, fDesc(desc)
, fGpu(gpu)
@@ -223,106 +225,104 @@ void GrGLProgramBuilder::setupUniformColorAndCoverageIfNeeded(GrGLSLExpr4* input
}
}
-void GrGLProgramBuilder::emitAndInstallProcs(const GrOptDrawState& optState,
- GrGLSLExpr4* inputColor,
- GrGLSLExpr4* inputCoverage) {
- fFragmentProcessors.reset(SkNEW(GrGLInstalledFragProcs));
- int numProcs = optState.numFragmentStages();
- this->emitAndInstallFragProcs(0, optState.numColorStages(), inputColor);
- if (optState.hasGeometryProcessor()) {
- const GrGeometryProcessor& gp = *optState.getGeometryProcessor();
- fVS.emitAttributes(gp);
- ProcKeyProvider keyProvider(&fDesc, ProcKeyProvider::kGeometry_ProcessorType);
- GrGLSLExpr4 output;
- this->emitAndInstallProc<GrGeometryProcessor>(gp, 0, keyProvider, *inputCoverage, &output);
- *inputCoverage = output;
+void GrGLProgramBuilder::createAndEmitProcessors(const GrGeometryStage* geometryProcessor,
+ const GrFragmentStage* colorStages[],
+ const GrFragmentStage* coverageStages[],
+ GrGLSLExpr4* inputColor,
+ GrGLSLExpr4* inputCoverage) {
+ bool useLocalCoords = fVS.hasExplicitLocalCoords();
+
+ EffectKeyProvider colorKeyProvider(&fDesc, EffectKeyProvider::kColor_EffectType);
+ int numColorEffects = fDesc.numColorEffects();
+ GrGLInstalledProcessors* ip = SkNEW_ARGS(GrGLInstalledProcessors, (numColorEffects,
+ useLocalCoords));
+ this->createAndEmitProcessors<GrFragmentStage>(colorStages, numColorEffects, colorKeyProvider,
+ inputColor, ip);
+ fColorEffects.reset(ip);
+
+ if (geometryProcessor) {
+ fVS.emitAttributes(*geometryProcessor->getProcessor());
+ EffectKeyProvider gpKeyProvider(&fDesc, EffectKeyProvider::kGeometryProcessor_EffectType);
+ ip = SkNEW_ARGS(GrGLInstalledProcessors, (1, useLocalCoords));
+ this->createAndEmitProcessors<GrGeometryStage>(&geometryProcessor, 1, gpKeyProvider,
+ inputCoverage, ip);
+ fGeometryProcessor.reset(ip);
}
- this->emitAndInstallFragProcs(optState.numColorStages(), numProcs, inputCoverage);
-}
-void GrGLProgramBuilder::emitAndInstallFragProcs(int procOffset, int numProcs, GrGLSLExpr4* inOut) {
- ProcKeyProvider keyProvider(&fDesc, ProcKeyProvider::kFragment_ProcessorType);
- for (int e = procOffset; e < numProcs; ++e) {
- GrGLSLExpr4 output;
- const GrFragmentStage& stage = fOptState.getFragmentStage(e);
- this->emitAndInstallProc<GrFragmentStage>(stage, e, keyProvider, *inOut, &output);
- *inOut = output;
- }
+ EffectKeyProvider coverageKeyProvider(&fDesc, EffectKeyProvider::kCoverage_EffectType);
+ int numCoverageEffects = fDesc.numCoverageEffects();
+ ip = SkNEW_ARGS(GrGLInstalledProcessors, (numCoverageEffects, useLocalCoords));
+ this->createAndEmitProcessors<GrFragmentStage>(coverageStages, numCoverageEffects,
+ coverageKeyProvider, inputCoverage, ip);
+ fCoverageEffects.reset(ip);
}
-// TODO Processors cannot output zeros because an empty string is all 1s
-// the fix is to allow effects to take the GrGLSLExpr4 directly
-template <class Proc>
-void GrGLProgramBuilder::emitAndInstallProc(const Proc& proc,
- int index,
- const ProcKeyProvider keyProvider,
- const GrGLSLExpr4& input,
- GrGLSLExpr4* output) {
- // Program builders have a bit of state we need to clear with each effect
- AutoStageAdvance adv(this);
-
- // create var to hold stage result
- SkString outColorName;
- this->nameVariable(&outColorName, '\0', "output");
- fFS.codeAppendf("vec4 %s;", outColorName.c_str());
- *output = outColorName;
-
- // Enclose custom code in a block to avoid namespace conflicts
- SkString openBrace;
- openBrace.printf("{ // Stage %d\n", fStageIndex);
- fFS.codeAppend(openBrace.c_str());
-
- this->emitAndInstallProc(proc, keyProvider.get(index), output->c_str(),
- input.isOnes() ? NULL : input.c_str());
-
- fFS.codeAppend("}");
-}
-
-void GrGLProgramBuilder::emitAndInstallProc(const GrFragmentStage& fs,
- const GrProcessorKey& key,
- const char* outColor,
- const char* inColor) {
- GrGLInstalledFragProc* ifp = SkNEW_ARGS(GrGLInstalledFragProc, (fVS.hasLocalCoords()));
-
- const GrFragmentProcessor& fp = *fs.getProcessor();
- ifp->fGLProc = fp.getFactory().createGLInstance(fp);
-
- SkSTArray<4, GrGLProcessor::TextureSampler> samplers(fp.numTextures());
- this->emitSamplers(fp, &samplers, ifp);
-
- // Fragment processors can have coord transforms
- SkSTArray<2, GrGLProcessor::TransformedCoords> coords(fp.numTransforms());
- this->emitTransforms(fs, &coords, ifp);
-
- ifp->fGLProc->emitCode(this, fp, key, outColor, inColor, coords, samplers);
-
- // We have to check that effects and the code they emit are consistent, ie if an effect
- // asks for dst color, then the emit code needs to follow suit
- verify(fp);
- fFragmentProcessors->fProcs.push_back(ifp);
-}
-
-void GrGLProgramBuilder::emitAndInstallProc(const GrGeometryProcessor& gp,
- const GrProcessorKey& key,
- const char* outColor,
- const char* inColor) {
- SkASSERT(!fGeometryProcessor);
- fGeometryProcessor = SkNEW(GrGLInstalledGeoProc);
-
- fGeometryProcessor->fGLProc = gp.getFactory().createGLInstance(gp);
-
- SkSTArray<4, GrGLProcessor::TextureSampler> samplers(gp.numTextures());
- this->emitSamplers(gp, &samplers, fGeometryProcessor);
-
- SkSTArray<2, GrGLProcessor::TransformedCoords> coords;
+template <class ProcessorStage>
+void GrGLProgramBuilder::createAndEmitProcessors(const ProcessorStage* processStages[],
+ int effectCnt,
+ const EffectKeyProvider& keyProvider,
+ GrGLSLExpr4* fsInOutColor,
+ GrGLInstalledProcessors* installedProcessors) {
+ bool effectEmitted = false;
+
+ GrGLSLExpr4 inColor = *fsInOutColor;
+ GrGLSLExpr4 outColor;
+
+ for (int e = 0; e < effectCnt; ++e) {
+ // Program builders have a bit of state we need to clear with each effect
+ AutoStageAdvance adv(this);
+ const ProcessorStage& stage = *processStages[e];
+ SkASSERT(stage.getProcessor());
+
+ if (inColor.isZeros()) {
+ SkString inColorName;
+
+ // Effects have no way to communicate zeros, they treat an empty string as ones.
+ this->nameVariable(&inColorName, '\0', "input");
+ fFS.codeAppendf("vec4 %s = %s;", inColorName.c_str(), inColor.c_str());
+ inColor = inColorName;
+ }
- // TODO remove coords from emit code signature, probably best to use a struct here so these
- // updates are less painful
- fGeometryProcessor->fGLProc->emitCode(this, gp, key, outColor, inColor, coords, samplers);
+ // create var to hold stage result
+ SkString outColorName;
+ this->nameVariable(&outColorName, '\0', "output");
+ fFS.codeAppendf("vec4 %s;", outColorName.c_str());
+ outColor = outColorName;
+
+ SkASSERT(installedProcessors);
+ const typename ProcessorStage::Processor& processor = *stage.getProcessor();
+ SkSTArray<2, GrGLProcessor::TransformedCoords> coords(processor.numTransforms());
+ SkSTArray<4, GrGLProcessor::TextureSampler> samplers(processor.numTextures());
+
+ this->emitTransforms(stage, &coords, installedProcessors);
+ this->emitSamplers(processor, &samplers, installedProcessors);
+
+ typename ProcessorStage::GLProcessor* glEffect =
+ processor.getFactory().createGLInstance(processor);
+ installedProcessors->addEffect(glEffect);
+
+ // Enclose custom code in a block to avoid namespace conflicts
+ SkString openBrace;
+ openBrace.printf("{ // Stage %d: %s\n", fStageIndex, glEffect->name());
+ fFS.codeAppend(openBrace.c_str());
+ fVS.codeAppend(openBrace.c_str());
+
+ glEffect->emitCode(this, processor, keyProvider.get(e), outColor.c_str(),
+ inColor.isOnes() ? NULL : inColor.c_str(), coords, samplers);
+
+ // We have to check that effects and the code they emit are consistent, ie if an effect
+ // asks for dst color, then the emit code needs to follow suit
+ verify(processor);
+ fFS.codeAppend("}");
+ fVS.codeAppend("}");
+
+ inColor = outColor;
+ effectEmitted = true;
+ }
- // We have to check that effects and the code they emit are consistent, ie if an effect
- // asks for dst color, then the emit code needs to follow suit
- verify(gp);
+ if (effectEmitted) {
+ *fsInOutColor = outColor;
+ }
}
void GrGLProgramBuilder::verify(const GrGeometryProcessor& gp) {
@@ -334,17 +334,19 @@ void GrGLProgramBuilder::verify(const GrFragmentProcessor& fp) {
SkASSERT(fFS.hasReadDstColor() == fp.willReadDstColor());
}
-void GrGLProgramBuilder::emitTransforms(const GrFragmentStage& effectStage,
+void GrGLProgramBuilder::emitTransforms(const GrProcessorStage& effectStage,
GrGLProcessor::TransformedCoordsArray* outCoords,
- GrGLInstalledFragProc* ifp) {
- const GrFragmentProcessor* effect = effectStage.getProcessor();
+ GrGLInstalledProcessors* installedProcessors) {
+ SkTArray<GrGLInstalledProcessors::Transform, true>& transforms =
+ installedProcessors->addTransforms();
+ const GrProcessor* effect = effectStage.getProcessor();
int numTransforms = effect->numTransforms();
- ifp->fTransforms.push_back_n(numTransforms);
+ transforms.push_back_n(numTransforms);
for (int t = 0; t < numTransforms; t++) {
const char* uniName = "StageMatrix";
GrSLType varyingType =
- effectStage.isPerspectiveCoordTransform(t, fVS.hasLocalCoords()) ?
+ effectStage.isPerspectiveCoordTransform(t, fVS.hasExplicitLocalCoords()) ?
kVec3f_GrSLType :
kVec2f_GrSLType;
@@ -354,10 +356,10 @@ void GrGLProgramBuilder::emitTransforms(const GrFragmentStage& effectStage,
suffixedUniName.appendf("_%i", t);
uniName = suffixedUniName.c_str();
}
- ifp->fTransforms[t].fHandle = this->addUniform(GrGLProgramBuilder::kVertex_Visibility,
- kMat33f_GrSLType,
- uniName,
- &uniName).toShaderBuilderIndex();
+ transforms[t].fHandle = this->addUniform(GrGLProgramBuilder::kVertex_Visibility,
+ kMat33f_GrSLType,
+ uniName,
+ &uniName).toShaderBuilderIndex();
const char* varyingName = "MatrixCoord";
SkString suffixedVaryingName;
@@ -391,17 +393,18 @@ void GrGLProgramBuilder::emitTransforms(const GrFragmentStage& effectStage,
void GrGLProgramBuilder::emitSamplers(const GrProcessor& processor,
GrGLProcessor::TextureSamplerArray* outSamplers,
- GrGLInstalledProc* ip) {
+ GrGLInstalledProcessors* installedProcessors) {
+ SkTArray<GrGLInstalledProcessors::Sampler, true>& samplers = installedProcessors->addSamplers();
int numTextures = processor.numTextures();
- ip->fSamplers.push_back_n(numTextures);
+ samplers.push_back_n(numTextures);
SkString name;
for (int t = 0; t < numTextures; ++t) {
name.printf("Sampler%d", t);
- ip->fSamplers[t].fUniform = this->addUniform(GrGLProgramBuilder::kFragment_Visibility,
- kSampler2D_GrSLType,
- name.c_str());
+ samplers[t].fUniform = this->addUniform(GrGLProgramBuilder::kFragment_Visibility,
+ kSampler2D_GrSLType,
+ name.c_str());
SkNEW_APPEND_TO_TARRAY(outSamplers, GrGLProcessor::TextureSampler,
- (ip->fSamplers[t].fUniform, processor.textureAccess(t)));
+ (samplers[t].fUniform, processor.textureAccess(t)));
}
}
@@ -503,14 +506,14 @@ void GrGLProgramBuilder::cleanupShaders(const SkTDArray<GrGLuint>& shaderIDs) {
GrGLProgram* GrGLProgramBuilder::createProgram(GrGLuint programID) {
return SkNEW_ARGS(GrGLProgram, (fGpu, fDesc, fUniformHandles, programID, fUniforms,
- fGeometryProcessor, fFragmentProcessors.get()));
+ fGeometryProcessor, fColorEffects, fCoverageEffects));
}
-///////////////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
-GrGLInstalledFragProcs::~GrGLInstalledFragProcs() {
- int numProcs = fProcs.count();
- for (int e = 0; e < numProcs; ++e) {
- SkDELETE(fProcs[e]->fGLProc);
+GrGLInstalledProcessors::~GrGLInstalledProcessors() {
+ int numEffects = fGLProcessors.count();
+ for (int e = 0; e < numEffects; ++e) {
+ SkDELETE(fGLProcessors[e]);
}
}
diff --git a/src/gpu/gl/builders/GrGLProgramBuilder.h b/src/gpu/gl/builders/GrGLProgramBuilder.h
index a8293545b2..6141058152 100644
--- a/src/gpu/gl/builders/GrGLProgramBuilder.h
+++ b/src/gpu/gl/builders/GrGLProgramBuilder.h
@@ -14,6 +14,8 @@
#include "../GrGLProgramDataManager.h"
#include "../GrGLUniformHandle.h"
+class GrGLInstalledProcessors;
+
/*
* This is the base class for a series of interfaces. This base class *MUST* remain abstract with
* NO data members because it is used in multiple interface inheritance.
@@ -96,11 +98,6 @@ public:
*/
};
-struct GrGLInstalledProc;
-struct GrGLInstalledGeoProc;
-struct GrGLInstalledFragProc;
-struct GrGLInstalledFragProcs;
-
/*
* Please note - no diamond problems because of virtual inheritance. Also, both base classes
* are pure virtual with no data members. This is the base class for program building.
@@ -121,6 +118,9 @@ public:
static GrGLProgram* CreateProgram(const GrOptDrawState&,
const GrGLProgramDesc&,
GrGpu::DrawType,
+ const GrGeometryStage* inGeometryProcessor,
+ const GrFragmentStage* inColorStages[],
+ const GrFragmentStage* inCoverageStages[],
GrGpuGL* gpu);
virtual UniformHandle addUniform(uint32_t visibility,
@@ -150,12 +150,11 @@ public:
virtual GrGLFPFragmentBuilder* getFragmentShaderBuilder() SK_OVERRIDE { return &fFS; }
virtual GrGLVertexBuilder* getVertexShaderBuilder() SK_OVERRIDE { return &fVS; }
- virtual void addVarying(
- GrSLType type,
- const char* name,
- const char** vsOutName = NULL,
- const char** fsInName = NULL,
- GrGLShaderVar::Precision fsPrecision=GrGLShaderVar::kDefault_Precision) SK_OVERRIDE;
+ virtual void addVarying(GrSLType type,
+ const char* name,
+ const char** vsOutName = NULL,
+ const char** fsInName = NULL,
+ GrGLShaderVar::Precision fsPrecision=GrGLShaderVar::kDefault_Precision);
// Handles for program uniforms (other than per-effect uniforms)
struct BuiltinUniformHandles {
@@ -175,10 +174,6 @@ public:
};
protected:
- typedef GrGLProgramDesc::ProcKeyProvider ProcKeyProvider;
- typedef GrGLProgramDataManager::UniformInfo UniformInfo;
- typedef GrGLProgramDataManager::UniformInfoArray UniformInfoArray;
-
static GrGLProgramBuilder* CreateProgramBuilder(const GrGLProgramDesc&,
const GrOptDrawState&,
GrGpu::DrawType,
@@ -196,40 +191,32 @@ protected:
// generating stage code.
void nameVariable(SkString* out, char prefix, const char* name);
void setupUniformColorAndCoverageIfNeeded(GrGLSLExpr4* inputColor, GrGLSLExpr4* inputCoverage);
- void emitAndInstallProcs(const GrOptDrawState& optState,
- GrGLSLExpr4* inputColor,
- GrGLSLExpr4* inputCoverage);
- void emitAndInstallFragProcs(int procOffset, int numProcs, GrGLSLExpr4* inOut);
- template <class Proc>
- void emitAndInstallProc(const Proc&,
- int index,
- const ProcKeyProvider,
- const GrGLSLExpr4& input,
- GrGLSLExpr4* output);
-
- // these emit functions help to keep the createAndEmitProcessors template general
- void emitAndInstallProc(const GrFragmentStage&,
- const GrProcessorKey&,
- const char* outColor,
- const char* inColor);
- void emitAndInstallProc(const GrGeometryProcessor&,
- const GrProcessorKey&,
- const char* outColor,
- const char* inColor);
+ void createAndEmitProcessors(const GrGeometryStage* geometryProcessor,
+ const GrFragmentStage* colorStages[],
+ const GrFragmentStage* coverageStages[],
+ GrGLSLExpr4* inputColor,
+ GrGLSLExpr4* inputCoverage);
+ template <class ProcessorStage>
+ void createAndEmitProcessors(const ProcessorStage*[],
+ int effectCnt,
+ const GrGLProgramDesc::EffectKeyProvider&,
+ GrGLSLExpr4* fsInOutColor,
+ GrGLInstalledProcessors*);
void verify(const GrGeometryProcessor&);
void verify(const GrFragmentProcessor&);
void emitSamplers(const GrProcessor&,
GrGLProcessor::TextureSamplerArray* outSamplers,
- GrGLInstalledProc*);
+ GrGLInstalledProcessors*);
// each specific program builder has a distinct transform and must override this function
- virtual void emitTransforms(const GrFragmentStage&,
+ virtual void emitTransforms(const GrProcessorStage&,
GrGLProcessor::TransformedCoordsArray* outCoords,
- GrGLInstalledFragProc*);
+ GrGLInstalledProcessors*);
GrGLProgram* finalize();
void bindUniformLocations(GrGLuint programID);
bool checkLinkStatus(GrGLuint programID);
void resolveUniformLocations(GrGLuint programID);
+
void cleanupProgram(GrGLuint programID, const SkTDArray<GrGLuint>& shaderIDs);
void cleanupShaders(const SkTDArray<GrGLuint>& shaderIDs);
@@ -269,6 +256,10 @@ protected:
void enterStage() { fOutOfStage = false; }
int stageIndex() const { return fStageIndex; }
+ typedef GrGLProgramDesc::EffectKeyProvider EffectKeyProvider;
+ typedef GrGLProgramDataManager::UniformInfo UniformInfo;
+ typedef GrGLProgramDataManager::UniformInfoArray UniformInfoArray;
+
// number of each input/output type in a single allocation block, used by many builders
static const int kVarsPerBlock;
@@ -279,8 +270,9 @@ protected:
bool fOutOfStage;
int fStageIndex;
- GrGLInstalledGeoProc* fGeometryProcessor;
- SkAutoTUnref<GrGLInstalledFragProcs> fFragmentProcessors;
+ SkAutoTUnref<GrGLInstalledProcessors> fGeometryProcessor;
+ SkAutoTUnref<GrGLInstalledProcessors> fColorEffects;
+ SkAutoTUnref<GrGLInstalledProcessors> fCoverageEffects;
const GrOptDrawState& fOptState;
const GrGLProgramDesc& fDesc;
@@ -294,26 +286,32 @@ protected:
};
/**
- * The below structs represent processors installed in programs. All processors can have texture
- * samplers, but only frag processors have coord transforms, hence the need for different structs
+ * This class encapsulates an array of GrGLProcessors and their supporting data (coord transforms
+ * and textures). It is built by GrGLProgramBuilder, then used to manage the necessary GL
+ * state and shader uniforms in GLPrograms. Its just Plain old data, and as such is entirely public
+ *
+ * TODO We really don't need this class to have an array of processors. It makes sense for it
+ * to just have one, also break out the transforms
*/
-struct GrGLInstalledProc {
- typedef GrGLProgramDataManager::UniformHandle UniformHandle;
-
- struct Sampler {
- SkDEBUGCODE(Sampler() : fTextureUnit(-1) {})
- UniformHandle fUniform;
- int fTextureUnit;
- };
- SkSTArray<4, Sampler, true> fSamplers;
-};
+class GrGLInstalledProcessors : public SkRefCnt {
+public:
+ GrGLInstalledProcessors(int reserveCount, bool hasExplicitLocalCoords = false)
+ : fGLProcessors(reserveCount)
+ , fSamplers(reserveCount)
+ , fTransforms(reserveCount)
+ , fHasExplicitLocalCoords(hasExplicitLocalCoords) {
+ }
-struct GrGLInstalledGeoProc : public GrGLInstalledProc {
- GrGLGeometryProcessor* fGLProc;
-};
+ virtual ~GrGLInstalledProcessors();
+
+ typedef GrGLProgramDataManager::UniformHandle UniformHandle;
+
+ struct Sampler {
+ SkDEBUGCODE(Sampler() : fTextureUnit(-1) {})
+ UniformHandle fUniform;
+ int fTextureUnit;
+ };
-struct GrGLInstalledFragProc : public GrGLInstalledProc {
- GrGLInstalledFragProc(bool useLocalCoords) : fGLProc(NULL), fLocalCoordAttrib(useLocalCoords) {}
class ShaderVarHandle {
public:
bool isValid() const { return fHandle > -1; }
@@ -336,14 +334,19 @@ struct GrGLInstalledFragProc : public GrGLInstalledProc {
GrSLType fType;
};
- GrGLFragmentProcessor* fGLProc;
- SkSTArray<2, Transform, true> fTransforms;
- bool fLocalCoordAttrib;
-};
+ void addEffect(GrGLProcessor* effect) { fGLProcessors.push_back(effect); }
+ SkTArray<Sampler, true>& addSamplers() { return fSamplers.push_back(); }
+ SkTArray<Transform, true>& addTransforms() { return fTransforms.push_back(); }
-struct GrGLInstalledFragProcs : public SkRefCnt {
- ~GrGLInstalledFragProcs();
- SkSTArray<8, GrGLInstalledFragProc*, true> fProcs;
+ SkTArray<GrGLProcessor*> fGLProcessors;
+ SkTArray<SkSTArray<4, Sampler, true> > fSamplers;
+ SkTArray<SkSTArray<2, Transform, true> > fTransforms;
+ bool fHasExplicitLocalCoords;
+
+ friend class GrGLShaderBuilder;
+ friend class GrGLVertexShaderBuilder;
+ friend class GrGLFragmentShaderBuilder;
+ friend class GrGLGeometryShaderBuilder;
};
#endif
diff --git a/src/gpu/gl/builders/GrGLVertexShaderBuilder.h b/src/gpu/gl/builders/GrGLVertexShaderBuilder.h
index 6e1495a746..0b85b84dfb 100644
--- a/src/gpu/gl/builders/GrGLVertexShaderBuilder.h
+++ b/src/gpu/gl/builders/GrGLVertexShaderBuilder.h
@@ -21,7 +21,7 @@ public:
/**
* Are explicit local coordinates provided as input to the vertex shader.
*/
- bool hasLocalCoords() const { return (fLocalCoordsVar != fPositionVar); }
+ bool hasExplicitLocalCoords() const { return (fLocalCoordsVar != fPositionVar); }
/** Returns a vertex attribute that represents the local coords in the VS. This may be the same
as positionAttribute() or it may not be. It depends upon whether the rendering code
diff --git a/tests/GLProgramsTest.cpp b/tests/GLProgramsTest.cpp
index 75032bdbe6..5ab35b7d22 100644
--- a/tests/GLProgramsTest.cpp
+++ b/tests/GLProgramsTest.cpp
@@ -456,6 +456,9 @@ bool GrGpuGL::programUnitTest(int maxStages) {
ds->reset();
continue;
}
+ const GrGeometryStage* geometryProcessor = NULL;
+ SkSTArray<8, const GrFragmentStage*, true> colorStages;
+ SkSTArray<8, const GrFragmentStage*, true> coverageStages;
GrGLProgramDesc desc;
GrDeviceCoordTexture dstCopy;
@@ -465,14 +468,24 @@ bool GrGpuGL::programUnitTest(int maxStages) {
}
if (!GrGLProgramDesc::Build(*ods,
drawType,
+ ods->getSrcBlendCoeff(),
+ ods->getDstBlendCoeff(),
this,
dstCopy.texture() ? &dstCopy : NULL,
+ &geometryProcessor,
+ &colorStages,
+ &coverageStages,
&desc)) {
SkDebugf("Failed to generate GL program descriptor");
return false;
}
- SkAutoTUnref<GrGLProgram> program(
- GrGLProgramBuilder::CreateProgram(*ods, desc, drawType, this));
+ SkAutoTUnref<GrGLProgram> program(GrGLProgramBuilder::CreateProgram(*ods,
+ desc,
+ drawType,
+ geometryProcessor,
+ colorStages.begin(),
+ coverageStages.begin(),
+ this));
if (NULL == program.get()) {
SkDebugf("Failed to create program!");
return false;