aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar joshualitt <joshualitt@chromium.org>2014-09-04 08:56:46 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2014-09-04 08:56:46 -0700
commitbd769d0f1c8cf6ccbb2738dfad1624a4c828e4eb (patch)
tree1fb4cd896c5d63bf3eb0dddbbd7259edab8703e3
parentc5ba71d2e5cd426def66fa49dcf003e5b2c98dc7 (diff)
Initial change to create GeometryProcessor
BUG=skia: R=bsalomon@google.com, robertphillips@google.com, egdaniel@google.com, jvanverth@google.com Author: joshualitt@chromium.org Review URL: https://codereview.chromium.org/509153002
-rw-r--r--expectations/gm/ignored-tests.txt3
-rw-r--r--gm/beziereffects.cpp6
-rw-r--r--src/gpu/GrAAConvexPathRenderer.cpp2
-rw-r--r--src/gpu/GrAAHairLinePathRenderer.cpp4
-rw-r--r--src/gpu/GrAARectRenderer.cpp4
-rwxr-xr-xsrc/gpu/GrBitmapTextContext.cpp2
-rwxr-xr-xsrc/gpu/GrContext.cpp3
-rw-r--r--src/gpu/GrDrawState.cpp36
-rw-r--r--src/gpu/GrDrawState.h16
-rw-r--r--src/gpu/GrDrawTarget.cpp9
-rw-r--r--src/gpu/GrOvalRenderer.cpp15
-rw-r--r--src/gpu/GrRODrawState.cpp29
-rw-r--r--src/gpu/GrRODrawState.h8
-rw-r--r--src/gpu/effects/GrDashingEffect.cpp2
-rw-r--r--src/gpu/gl/GrGLProgram.cpp13
-rw-r--r--src/gpu/gl/GrGLProgram.h3
-rw-r--r--src/gpu/gl/GrGLProgramDesc.cpp53
-rw-r--r--src/gpu/gl/GrGLProgramDesc.h22
-rw-r--r--src/gpu/gl/GrGLProgramEffects.cpp18
-rw-r--r--src/gpu/gl/GrGLProgramEffects.h11
-rw-r--r--src/gpu/gl/GrGpuGL.h1
-rw-r--r--src/gpu/gl/GrGpuGL_program.cpp8
-rw-r--r--src/gpu/gl/builders/GrGLProgramBuilder.cpp70
-rw-r--r--src/gpu/gl/builders/GrGLProgramBuilder.h49
-rw-r--r--tests/GLProgramsTest.cpp87
25 files changed, 409 insertions, 65 deletions
diff --git a/expectations/gm/ignored-tests.txt b/expectations/gm/ignored-tests.txt
index ad56781c99..2fd0339b24 100644
--- a/expectations/gm/ignored-tests.txt
+++ b/expectations/gm/ignored-tests.txt
@@ -36,3 +36,6 @@
# jvanverth
fontcache
+# joshualitt
+convex_poly_clip
+bezier_cubic_effects \ No newline at end of file
diff --git a/gm/beziereffects.cpp b/gm/beziereffects.cpp
index e0a1d8726e..f150b7c9df 100644
--- a/gm/beziereffects.cpp
+++ b/gm/beziereffects.cpp
@@ -170,7 +170,7 @@ protected:
GrDrawState* drawState = tt.target()->drawState();
drawState->setVertexAttribs<kAttribs>(2, sizeof(Vertex));
- drawState->addCoverageEffect(effect, 1);
+ drawState->setGeometryProcessor(effect, 1);
drawState->setRenderTarget(rt);
drawState->setColor(0xff000000);
@@ -325,7 +325,7 @@ protected:
GrDrawState* drawState = tt.target()->drawState();
drawState->setVertexAttribs<kAttribs>(2, sizeof(Vertex));
- drawState->addCoverageEffect(effect, 1);
+ drawState->setGeometryProcessor(effect, 1);
drawState->setRenderTarget(rt);
drawState->setColor(0xff000000);
@@ -509,7 +509,7 @@ protected:
GrDrawState* drawState = tt.target()->drawState();
drawState->setVertexAttribs<kAttribs>(2, sizeof(Vertex));
- drawState->addCoverageEffect(effect, 1);
+ drawState->setGeometryProcessor(effect, 1);
drawState->setRenderTarget(rt);
drawState->setColor(0xff000000);
diff --git a/src/gpu/GrAAConvexPathRenderer.cpp b/src/gpu/GrAAConvexPathRenderer.cpp
index c260382dbb..e4fc6ec87d 100644
--- a/src/gpu/GrAAConvexPathRenderer.cpp
+++ b/src/gpu/GrAAConvexPathRenderer.cpp
@@ -678,7 +678,7 @@ bool GrAAConvexPathRenderer::onDrawPath(const SkPath& origPath,
static const int kEdgeAttrIndex = 1;
GrEffect* quadEffect = QuadEdgeEffect::Create();
- drawState->addCoverageEffect(quadEffect, kEdgeAttrIndex)->unref();
+ drawState->setGeometryProcessor(quadEffect, kEdgeAttrIndex)->unref();
GrDrawTarget::AutoReleaseGeometry arg(target, vCount, iCount);
if (!arg.succeeded()) {
diff --git a/src/gpu/GrAAHairLinePathRenderer.cpp b/src/gpu/GrAAHairLinePathRenderer.cpp
index 2114720f34..9986ac87f0 100644
--- a/src/gpu/GrAAHairLinePathRenderer.cpp
+++ b/src/gpu/GrAAHairLinePathRenderer.cpp
@@ -1002,7 +1002,7 @@ bool GrAAHairLinePathRenderer::onDrawPath(const SkPath& path,
SkASSERT(NULL != hairQuadEffect);
GrDrawState::AutoRestoreEffects are(drawState);
target->setIndexSourceToBuffer(fQuadsIndexBuffer);
- drawState->addCoverageEffect(hairQuadEffect, kEdgeAttrIndex)->unref();
+ drawState->setGeometryProcessor(hairQuadEffect, kEdgeAttrIndex)->unref();
int quads = 0;
while (quads < quadCnt) {
int n = SkTMin(quadCnt - quads, kNumQuadsInIdxBuffer);
@@ -1021,7 +1021,7 @@ bool GrAAHairLinePathRenderer::onDrawPath(const SkPath& path,
GrEffect* hairConicEffect = GrConicEffect::Create(kHairlineAA_GrEffectEdgeType,
*target->caps());
SkASSERT(NULL != hairConicEffect);
- drawState->addCoverageEffect(hairConicEffect, 1, 2)->unref();
+ drawState->setGeometryProcessor(hairConicEffect, 1, 2)->unref();
int conics = 0;
while (conics < conicCnt) {
int n = SkTMin(conicCnt - conics, kNumQuadsInIdxBuffer);
diff --git a/src/gpu/GrAARectRenderer.cpp b/src/gpu/GrAARectRenderer.cpp
index a7ddfde7cc..9384457a1e 100644
--- a/src/gpu/GrAARectRenderer.cpp
+++ b/src/gpu/GrAARectRenderer.cpp
@@ -648,7 +648,7 @@ void GrAARectRenderer::shaderFillAARect(GrGpu* gpu,
GrEffect* effect = GrRectEffect::Create();
static const int kRectAttrIndex = 1;
static const int kWidthIndex = 2;
- drawState->addCoverageEffect(effect, kRectAttrIndex, kWidthIndex)->unref();
+ drawState->setGeometryProcessor(effect, kRectAttrIndex, kWidthIndex)->unref();
for (int i = 0; i < 4; ++i) {
verts[i].fCenter = center;
@@ -697,7 +697,7 @@ void GrAARectRenderer::shaderFillAlignedAARect(GrGpu* gpu,
GrEffect* effect = GrAlignedRectEffect::Create();
static const int kOffsetIndex = 1;
- drawState->addCoverageEffect(effect, kOffsetIndex)->unref();
+ drawState->setGeometryProcessor(effect, kOffsetIndex)->unref();
SkRect devRect;
combinedMatrix.mapRect(&devRect, rect);
diff --git a/src/gpu/GrBitmapTextContext.cpp b/src/gpu/GrBitmapTextContext.cpp
index 6599d4ea47..ac4c078275 100755
--- a/src/gpu/GrBitmapTextContext.cpp
+++ b/src/gpu/GrBitmapTextContext.cpp
@@ -108,7 +108,7 @@ void GrBitmapTextContext::flushGlyphs() {
// This effect could be stored with one of the cache objects (atlas?)
int coordsIdx = drawState->hasColorVertexAttribute() ? kGlyphCoordsWithColorAttributeIndex :
kGlyphCoordsNoColorAttributeIndex;
- drawState->addCoverageEffect(fCachedEffect.get(), coordsIdx);
+ drawState->setGeometryProcessor(fCachedEffect.get(), coordsIdx);
SkASSERT(NULL != fStrike);
switch (fStrike->getMaskFormat()) {
// Color bitmap text
diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp
index 322ea87dcb..85d53119b6 100755
--- a/src/gpu/GrContext.cpp
+++ b/src/gpu/GrContext.cpp
@@ -1738,7 +1738,8 @@ GrDrawTarget* GrContext::prepareToDraw(const GrPaint* paint,
AutoCheckFlush* acf) {
// All users of this draw state should be freeing up all effects when they're done.
// Otherwise effects that own resources may keep those resources alive indefinitely.
- SkASSERT(0 == fDrawState->numColorStages() && 0 == fDrawState->numCoverageStages());
+ SkASSERT(0 == fDrawState->numColorStages() && 0 == fDrawState->numCoverageStages() &&
+ !fDrawState->hasGeometryProcessor());
if (NULL == fGpu) {
return NULL;
diff --git a/src/gpu/GrDrawState.cpp b/src/gpu/GrDrawState.cpp
index 0c2b1c3684..236d48f229 100644
--- a/src/gpu/GrDrawState.cpp
+++ b/src/gpu/GrDrawState.cpp
@@ -54,6 +54,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);
}
@@ -79,6 +82,11 @@ GrDrawState& GrDrawState::operator=(const GrDrawState& that) {
fStencilSettings = that.fStencilSettings;
fCoverage = that.fCoverage;
fDrawFace = that.fDrawFace;
+ if (that.hasGeometryProcessor()) {
+ fGeometryProcessor.reset(SkNEW_ARGS(GrEffectStage, (*that.fGeometryProcessor.get())));
+ } else {
+ fGeometryProcessor.reset(NULL);
+ }
fColorStages = that.fColorStages;
fCoverageStages = that.fCoverageStages;
fOptSrcBlend = that.fOptSrcBlend;
@@ -95,6 +103,7 @@ GrDrawState& GrDrawState::operator=(const GrDrawState& that) {
void GrDrawState::onReset(const SkMatrix* initialViewMatrix) {
SkASSERT(0 == fBlockEffectRemovalCnt || 0 == this->numTotalStages());
+ fGeometryProcessor.reset(NULL);
fColorStages.reset();
fCoverageStages.reset();
@@ -128,6 +137,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);
}
@@ -142,6 +154,7 @@ bool GrDrawState::setIdentityViewMatrix() {
void GrDrawState::setFromPaint(const GrPaint& paint, const SkMatrix& vm, GrRenderTarget* rt) {
SkASSERT(0 == fBlockEffectRemovalCnt || 0 == this->numTotalStages());
+ fGeometryProcessor.reset(NULL);
fColorStages.reset();
fCoverageStages.reset();
@@ -286,6 +299,8 @@ GrDrawState::AutoVertexAttribRestore::AutoVertexAttribRestore(
void GrDrawState::AutoRestoreEffects::set(GrDrawState* ds) {
if (NULL != fDrawState) {
+ fDrawState->fGeometryProcessor.reset(fGeometryProcessor.detach());
+
int m = fDrawState->numColorStages() - fColorEffectCnt;
SkASSERT(m >= 0);
fDrawState->fColorStages.pop_back_n(m);
@@ -300,6 +315,11 @@ void GrDrawState::AutoRestoreEffects::set(GrDrawState* ds) {
}
fDrawState = ds;
if (NULL != ds) {
+ if (ds->hasGeometryProcessor()) {
+ fGeometryProcessor.reset(SkNEW_ARGS(GrEffectStage, (*ds->getGeometryProcessor())));
+ } else {
+ fGeometryProcessor.reset(NULL);
+ }
fColorEffectCnt = ds->numColorStages();
fCoverageEffectCnt = ds->numCoverageStages();
SkDEBUGCODE(++ds->fBlockEffectRemovalCnt;)
@@ -429,6 +449,10 @@ void GrDrawState::AutoViewMatrixRestore::restore() {
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]);
}
@@ -471,6 +495,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;)
@@ -492,6 +517,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]);
@@ -543,6 +575,10 @@ bool GrDrawState::srcAlphaWillBeOne() const {
}
// Run through the coverage stages
+ if (this->hasGeometryProcessor()) {
+ const GrEffect* effect = fGeometryProcessor->getEffect();
+ effect->getConstantColorComponents(&coverage, &coverageComponentFlags);
+ }
for (int s = 0; s < this->numCoverageStages(); ++s) {
const GrEffect* effect = this->getCoverageStage(s).getEffect();
effect->getConstantColorComponents(&coverage, &coverageComponentFlags);
diff --git a/src/gpu/GrDrawState.h b/src/gpu/GrDrawState.h
index 00bec9f7c2..a1b07de6d6 100644
--- a/src/gpu/GrDrawState.h
+++ b/src/gpu/GrDrawState.h
@@ -165,6 +165,20 @@ public:
/// @}
+ /**
+ * The geometry processor is the sole element of the skia pipeline which can use the vertex,
+ * geometry, and tesselation shaders. The GP may also compute a coverage in its fragment shader
+ * but is never put in the color processing pipeline.
+ */
+
+ const GrEffect* setGeometryProcessor(const GrEffect* effect, int attr0 = -1, int attr1 = -1) {
+ SkASSERT(NULL != effect);
+ SkASSERT(!this->hasGeometryProcessor());
+ fGeometryProcessor.reset(new GrEffectStage(effect, attr0, attr1));
+ this->invalidateBlendOptFlags();
+ return effect;
+ }
+
///////////////////////////////////////////////////////////////////////////
/// @name Effect Stages
/// Each stage hosts a GrEffect. The effect produces an output color or coverage in the fragment
@@ -242,6 +256,7 @@ public:
private:
GrDrawState* fDrawState;
+ SkAutoTDelete<GrEffectStage> fGeometryProcessor;
int fColorEffectCnt;
int fCoverageEffectCnt;
};
@@ -364,6 +379,7 @@ public:
GrDrawState* fDrawState;
SkMatrix fViewMatrix;
int fNumColorStages;
+ bool fHasGeometryProcessor;
SkAutoSTArray<8, GrEffectStage::SavedCoordChange> fSavedCoordChanges;
};
diff --git a/src/gpu/GrDrawTarget.cpp b/src/gpu/GrDrawTarget.cpp
index 9605781d34..191194eb50 100644
--- a/src/gpu/GrDrawTarget.cpp
+++ b/src/gpu/GrDrawTarget.cpp
@@ -389,6 +389,15 @@ bool GrDrawTarget::checkDraw(GrPrimitiveType type, int startVertex,
SkASSERT(NULL != drawState.getRenderTarget());
+ if (drawState.hasGeometryProcessor()) {
+ const GrEffect* effect = drawState.getGeometryProcessor()->getEffect();
+ int numTextures = effect->numTextures();
+ for (int t = 0; t < numTextures; ++t) {
+ GrTexture* texture = effect->texture(t);
+ SkASSERT(texture->asRenderTarget() != drawState.getRenderTarget());
+ }
+ }
+
for (int s = 0; s < drawState.numColorStages(); ++s) {
const GrEffect* effect = drawState.getColorStage(s).getEffect();
int numTextures = effect->numTextures();
diff --git a/src/gpu/GrOvalRenderer.cpp b/src/gpu/GrOvalRenderer.cpp
index f368dc8d89..330d4e9289 100644
--- a/src/gpu/GrOvalRenderer.cpp
+++ b/src/gpu/GrOvalRenderer.cpp
@@ -553,7 +553,7 @@ void GrOvalRenderer::drawCircle(GrDrawTarget* target,
GrEffect* effect = CircleEdgeEffect::Create(isStrokeOnly && innerRadius > 0);
static const int kCircleEdgeAttrIndex = 1;
- drawState->addCoverageEffect(effect, kCircleEdgeAttrIndex)->unref();
+ drawState->setGeometryProcessor(effect, kCircleEdgeAttrIndex)->unref();
// The radii are outset for two reasons. First, it allows the shader to simply perform
// clamp(distance-to-center - radius, 0, 1). Second, the outer radius is used to compute the
@@ -696,7 +696,7 @@ bool GrOvalRenderer::drawEllipse(GrDrawTarget* target,
static const int kEllipseCenterAttrIndex = 1;
static const int kEllipseEdgeAttrIndex = 2;
- drawState->addCoverageEffect(effect, kEllipseCenterAttrIndex, kEllipseEdgeAttrIndex)->unref();
+ drawState->setGeometryProcessor(effect, kEllipseCenterAttrIndex, kEllipseEdgeAttrIndex)->unref();
// Compute the reciprocals of the radii here to save time in the shader
SkScalar xRadRecip = SkScalarInvert(xRadius);
@@ -814,8 +814,8 @@ bool GrOvalRenderer::drawDIEllipse(GrDrawTarget* target,
static const int kEllipseOuterOffsetAttrIndex = 1;
static const int kEllipseInnerOffsetAttrIndex = 2;
- drawState->addCoverageEffect(effect, kEllipseOuterOffsetAttrIndex,
- kEllipseInnerOffsetAttrIndex)->unref();
+ drawState->setGeometryProcessor(effect, kEllipseOuterOffsetAttrIndex,
+ kEllipseInnerOffsetAttrIndex)->unref();
// This expands the outer rect so that after CTM we end up with a half-pixel border
SkScalar a = vm[SkMatrix::kMScaleX];
@@ -1063,7 +1063,7 @@ bool GrOvalRenderer::drawRRect(GrDrawTarget* target, GrContext* context, bool us
GrEffect* effect = CircleEdgeEffect::Create(isStrokeOnly);
static const int kCircleEdgeAttrIndex = 1;
- drawState->addCoverageEffect(effect, kCircleEdgeAttrIndex)->unref();
+ drawState->setGeometryProcessor(effect, kCircleEdgeAttrIndex)->unref();
// The radii are outset for two reasons. First, it allows the shader to simply perform
// clamp(distance-to-center - radius, 0, 1). Second, the outer radius is used to compute the
@@ -1168,8 +1168,9 @@ bool GrOvalRenderer::drawRRect(GrDrawTarget* target, GrContext* context, bool us
GrEffect* effect = EllipseEdgeEffect::Create(isStrokeOnly);
static const int kEllipseOffsetAttrIndex = 1;
static const int kEllipseRadiiAttrIndex = 2;
- drawState->addCoverageEffect(effect,
- kEllipseOffsetAttrIndex, kEllipseRadiiAttrIndex)->unref();
+ drawState->setGeometryProcessor(effect,
+ kEllipseOffsetAttrIndex,
+ kEllipseRadiiAttrIndex)->unref();
// Compute the reciprocals of the radii here to save time in the shader
SkScalar xRadRecip = SkScalarInvert(xRadius);
diff --git a/src/gpu/GrRODrawState.cpp b/src/gpu/GrRODrawState.cpp
index 9118d0dc8d..f6a235517a 100644
--- a/src/gpu/GrRODrawState.cpp
+++ b/src/gpu/GrRODrawState.cpp
@@ -38,6 +38,18 @@ bool GrRODrawState::isEqual(const GrRODrawState& that) const {
}
bool explicitLocalCoords = this->hasLocalCoordAttribute();
+ if (this->hasGeometryProcessor()) {
+ if (!that.hasGeometryProcessor()) {
+ return kIncompatible_CombinedState;
+ } else if (!GrEffectStage::AreCompatible(*this->getGeometryProcessor(),
+ *that.getGeometryProcessor(),
+ explicitLocalCoords)) {
+ return kIncompatible_CombinedState;
+ }
+ } else if (that.hasGeometryProcessor()) {
+ return kIncompatible_CombinedState;
+ }
+
for (int i = 0; i < this->numColorStages(); i++) {
if (!GrEffectStage::AreCompatible(this->getColorStage(i), that.getColorStage(i),
explicitLocalCoords)) {
@@ -66,11 +78,9 @@ bool GrRODrawState::validateVertexAttribs() const {
for (int i = 0; i < kMaxVertexAttribCnt; ++i) {
slTypes[i] = static_cast<GrSLType>(-1);
}
- int totalStages = this->numTotalStages();
- for (int s = 0; s < totalStages; ++s) {
- int covIdx = s - this->numColorStages();
- const GrEffectStage& stage = covIdx < 0 ? this->getColorStage(s) :
- this->getCoverageStage(covIdx);
+
+ if (this->hasGeometryProcessor()) {
+ const GrEffectStage& stage = *this->getGeometryProcessor();
const GrEffect* effect = stage.getEffect();
SkASSERT(NULL != effect);
// make sure that any attribute indices have the correct binding type, that the attrib
@@ -118,6 +128,10 @@ bool GrRODrawState::hasSolidCoverage() const {
}
// Run through the coverage stages and see if the coverage will be all ones at the end.
+ if (this->hasGeometryProcessor()) {
+ const GrEffect* effect = fGeometryProcessor->getEffect();
+ effect->getConstantColorComponents(&coverage, &validComponentFlags);
+ }
for (int s = 0; s < this->numCoverageStages(); ++s) {
const GrEffect* effect = this->getCoverageStage(s).getEffect();
effect->getConstantColorComponents(&coverage, &validComponentFlags);
@@ -140,6 +154,11 @@ bool GrRODrawState::willEffectReadDstColor() const {
return true;
}
}
+ if (this->hasGeometryProcessor()) {
+ if (fGeometryProcessor->getEffect()->willReadDstColor()) {
+ return true;
+ }
+ }
return false;
}
diff --git a/src/gpu/GrRODrawState.h b/src/gpu/GrRODrawState.h
index 54d87bdfc8..88392ba35f 100644
--- a/src/gpu/GrRODrawState.h
+++ b/src/gpu/GrRODrawState.h
@@ -121,8 +121,13 @@ public:
int numColorStages() const { return fColorStages.count(); }
int numCoverageStages() const { return fCoverageStages.count(); }
- int numTotalStages() const { return this->numColorStages() + this->numCoverageStages(); }
+ int numTotalStages() const {
+ return this->numColorStages() + this->numCoverageStages() +
+ (this->hasGeometryProcessor() ? 1 : 0);
+ }
+ bool hasGeometryProcessor() const { return NULL != fGeometryProcessor.get(); }
+ const GrEffectStage* getGeometryProcessor() const { return fGeometryProcessor.get(); }
const GrEffectStage& getColorStage(int stageIdx) const { return fColorStages[stageIdx]; }
const GrEffectStage& getCoverageStage(int stageIdx) const { return fCoverageStages[stageIdx]; }
@@ -358,6 +363,7 @@ protected:
GrBlendCoeff fDstBlend;
typedef SkSTArray<4, GrEffectStage> EffectStageArray;
+ SkAutoTDelete<GrEffectStage> fGeometryProcessor;
EffectStageArray fColorStages;
EffectStageArray fCoverageStages;
diff --git a/src/gpu/effects/GrDashingEffect.cpp b/src/gpu/effects/GrDashingEffect.cpp
index adee4aec96..f4298eb4a0 100644
--- a/src/gpu/effects/GrDashingEffect.cpp
+++ b/src/gpu/effects/GrDashingEffect.cpp
@@ -345,7 +345,7 @@ bool GrDashingEffect::DrawDashLine(const SkPoint pts[2], const GrPaint& paint,
bool isRoundCap = SkPaint::kRound_Cap == cap;
GrDashingEffect::DashCap capType = isRoundCap ? GrDashingEffect::kRound_DashCap :
GrDashingEffect::kNonRound_DashCap;
- drawState->addCoverageEffect(
+ drawState->setGeometryProcessor(
GrDashingEffect::Create(edgeType, devInfo, strokeWidth, capType), 1)->unref();
}
diff --git a/src/gpu/gl/GrGLProgram.cpp b/src/gpu/gl/GrGLProgram.cpp
index 534e3c38a1..7b5dbb4c94 100644
--- a/src/gpu/gl/GrGLProgram.cpp
+++ b/src/gpu/gl/GrGLProgram.cpp
@@ -23,17 +23,19 @@
GrGLProgram* GrGLProgram::Create(GrGpuGL* gpu,
const GrGLProgramDesc& desc,
+ const GrEffectStage* geometryProcessor,
const GrEffectStage* colorStages[],
const GrEffectStage* coverageStages[]) {
SkAutoTDelete<GrGLProgramBuilder> builder;
if (!desc.getHeader().fRequiresVertexShader &&
gpu->glCaps().pathRenderingSupport() &&
gpu->glPathRendering()->texturingMode() == GrGLPathRendering::FixedFunction_TexturingMode) {
+ SkASSERT(NULL == geometryProcessor);
builder.reset(SkNEW_ARGS(GrGLFragmentOnlyProgramBuilder, (gpu, desc)));
} else {
builder.reset(SkNEW_ARGS(GrGLFullProgramBuilder, (gpu, desc)));
}
- if (builder->genProgram(colorStages, coverageStages)) {
+ if (builder->genProgram(geometryProcessor, colorStages, coverageStages)) {
SkASSERT(0 != builder->getProgramID());
return SkNEW_ARGS(GrGLProgram, (gpu, desc, *builder));
}
@@ -47,6 +49,7 @@ GrGLProgram::GrGLProgram(GrGpuGL* gpu,
, fCoverage(GrColor_ILLEGAL)
, fDstCopyTexUnit(-1)
, fBuiltinUniformHandles(builder.getBuiltinUniformHandles())
+ , fGeometryProcessor(SkSafeRef(builder.getGeometryProcessor()))
, fColorEffects(SkRef(builder.getColorEffects()))
, fCoverageEffects(SkRef(builder.getCoverageEffects()))
, fProgramID(builder.getProgramID())
@@ -97,6 +100,9 @@ void GrGLProgram::initSamplerUniforms() {
fProgramDataManager.setSampler(fBuiltinUniformHandles.fDstCopySamplerUni, texUnitIdx);
fDstCopyTexUnit = texUnitIdx++;
}
+ if (NULL != fGeometryProcessor.get()) {
+ fGeometryProcessor->initSamplers(fProgramDataManager, &texUnitIdx);
+ }
fColorEffects->initSamplers(fProgramDataManager, &texUnitIdx);
fCoverageEffects->initSamplers(fProgramDataManager, &texUnitIdx);
}
@@ -105,6 +111,7 @@ void GrGLProgram::initSamplerUniforms() {
void GrGLProgram::setData(GrGpu::DrawType drawType,
GrDrawState::BlendOptFlags blendOpts,
+ const GrEffectStage* geometryProcessor,
const GrEffectStage* colorStages[],
const GrEffectStage* coverageStages[],
const GrDeviceCoordTexture* dstCopy,
@@ -149,6 +156,10 @@ void GrGLProgram::setData(GrGpu::DrawType drawType,
SkASSERT(!fBuiltinUniformHandles.fDstCopySamplerUni.isValid());
}
+ if (NULL != fGeometryProcessor.get()) {
+ SkASSERT(NULL != geometryProcessor);
+ fGeometryProcessor->setData(fGpu, drawType,fProgramDataManager, geometryProcessor);
+ }
fColorEffects->setData(fGpu, drawType,fProgramDataManager, colorStages);
fCoverageEffects->setData(fGpu, drawType,fProgramDataManager, coverageStages);
diff --git a/src/gpu/gl/GrGLProgram.h b/src/gpu/gl/GrGLProgram.h
index 5b9deb9f91..0f89e07b0d 100644
--- a/src/gpu/gl/GrGLProgram.h
+++ b/src/gpu/gl/GrGLProgram.h
@@ -41,6 +41,7 @@ public:
static GrGLProgram* Create(GrGpuGL* gpu,
const GrGLProgramDesc& desc,
+ const GrEffectStage* geometryProcessor,
const GrEffectStage* colorStages[],
const GrEffectStage* coverageStages[]);
@@ -158,6 +159,7 @@ public:
*/
void setData(GrGpu::DrawType,
GrDrawState::BlendOptFlags,
+ const GrEffectStage* geometryProcessor,
const GrEffectStage* colorStages[],
const GrEffectStage* coverageStages[],
const GrDeviceCoordTexture* dstCopy, // can be NULL
@@ -191,6 +193,7 @@ private:
int fDstCopyTexUnit;
BuiltinUniformHandles fBuiltinUniformHandles;
+ SkAutoTUnref<GrGLProgramEffects> fGeometryProcessor;
SkAutoTUnref<GrGLProgramEffects> fColorEffects;
SkAutoTUnref<GrGLProgramEffects> fCoverageEffects;
GrGLuint fProgramID;
diff --git a/src/gpu/gl/GrGLProgramDesc.cpp b/src/gpu/gl/GrGLProgramDesc.cpp
index 545ed2114c..8d0ea3d6b3 100644
--- a/src/gpu/gl/GrGLProgramDesc.cpp
+++ b/src/gpu/gl/GrGLProgramDesc.cpp
@@ -53,6 +53,7 @@ bool GrGLProgramDesc::Build(const GrDrawState& drawState,
GrBlendCoeff dstCoeff,
const GrGpuGL* gpu,
const GrDeviceCoordTexture* dstCopy,
+ const GrEffectStage** geometryProcessor,
SkTArray<const GrEffectStage*, true>* colorStages,
SkTArray<const GrEffectStage*, true>* coverageStages,
GrGLProgramDesc* desc) {
@@ -69,6 +70,7 @@ bool GrGLProgramDesc::Build(const GrDrawState& drawState,
int firstEffectiveColorStage = 0;
bool inputColorIsUsed = true;
+
if (!skipColor) {
firstEffectiveColorStage = drawState.numColorStages();
while (firstEffectiveColorStage > 0 && inputColorIsUsed) {
@@ -107,6 +109,9 @@ bool GrGLProgramDesc::Build(const GrDrawState& drawState,
bool requiresVertexShader = !GrGpu::IsPathRenderingDrawType(drawType);
int numStages = 0;
+ if (drawState.hasGeometryProcessor()) {
+ numStages++;
+ }
if (!skipColor) {
numStages += drawState.numColorStages() - firstEffectiveColorStage;
}
@@ -120,12 +125,42 @@ bool GrGLProgramDesc::Build(const GrDrawState& drawState,
int offsetAndSizeIndex = 0;
bool effectKeySuccess = true;
+
+ KeyHeader* header = desc->header();
+ // make sure any padding in the header is zeroed.
+ memset(desc->header(), 0, kHeaderSize);
+
+ // We can only have one effect which touches the vertex shader
+ if (drawState.hasGeometryProcessor()) {
+ uint16_t* offsetAndSize =
+ reinterpret_cast<uint16_t*>(desc->fKey.begin() + kEffectKeyOffsetsAndLengthOffset +
+ offsetAndSizeIndex * 2 * sizeof(uint16_t));
+
+ GrEffectKeyBuilder b(&desc->fKey);
+ uint16_t effectKeySize;
+ uint32_t effectOffset = desc->fKey.count();
+ effectKeySuccess |= GetEffectKeyAndUpdateStats(
+ *drawState.getGeometryProcessor(), gpu->glCaps(),
+ requiresLocalCoordAttrib, &b,
+ &effectKeySize, &readsDst,
+ &readFragPosition, &requiresVertexShader);
+ effectKeySuccess |= (effectOffset <= SK_MaxU16);
+
+ offsetAndSize[0] = SkToU16(effectOffset);
+ offsetAndSize[1] = effectKeySize;
+ ++offsetAndSizeIndex;
+ *geometryProcessor = drawState.getGeometryProcessor();
+ SkASSERT(requiresVertexShader);
+ header->fHasGeometryProcessor = true;
+ }
+
if (!skipColor) {
for (int s = firstEffectiveColorStage; s < drawState.numColorStages(); ++s) {
uint16_t* offsetAndSize =
reinterpret_cast<uint16_t*>(desc->fKey.begin() + kEffectKeyOffsetsAndLengthOffset +
offsetAndSizeIndex * 2 * sizeof(uint16_t));
+ bool effectRequiresVertexShader = false;
GrEffectKeyBuilder b(&desc->fKey);
uint16_t effectKeySize;
uint32_t effectOffset = desc->fKey.count();
@@ -133,12 +168,13 @@ bool GrGLProgramDesc::Build(const GrDrawState& drawState,
drawState.getColorStage(s), gpu->glCaps(),
requiresLocalCoordAttrib, &b,
&effectKeySize, &readsDst,
- &readFragPosition, &requiresVertexShader);
+ &readFragPosition, &effectRequiresVertexShader);
effectKeySuccess |= (effectOffset <= SK_MaxU16);
offsetAndSize[0] = SkToU16(effectOffset);
offsetAndSize[1] = effectKeySize;
++offsetAndSizeIndex;
+ SkASSERT(!effectRequiresVertexShader);
}
}
if (!skipCoverage) {
@@ -147,6 +183,7 @@ bool GrGLProgramDesc::Build(const GrDrawState& drawState,
reinterpret_cast<uint16_t*>(desc->fKey.begin() + kEffectKeyOffsetsAndLengthOffset +
offsetAndSizeIndex * 2 * sizeof(uint16_t));
+ bool effectRequiresVertexShader = false;
GrEffectKeyBuilder b(&desc->fKey);
uint16_t effectKeySize;
uint32_t effectOffset = desc->fKey.count();
@@ -154,12 +191,13 @@ bool GrGLProgramDesc::Build(const GrDrawState& drawState,
drawState.getCoverageStage(s), gpu->glCaps(),
requiresLocalCoordAttrib, &b,
&effectKeySize, &readsDst,
- &readFragPosition, &requiresVertexShader);
+ &readFragPosition, &effectRequiresVertexShader);
effectKeySuccess |= (effectOffset <= SK_MaxU16);
offsetAndSize[0] = SkToU16(effectOffset);
offsetAndSize[1] = effectKeySize;
++offsetAndSizeIndex;
+ SkASSERT(!effectRequiresVertexShader);
}
}
if (!effectKeySuccess) {
@@ -167,10 +205,6 @@ bool GrGLProgramDesc::Build(const GrDrawState& drawState,
return false;
}
- KeyHeader* header = desc->header();
- // make sure any padding in the header is zeroed.
- memset(desc->header(), 0, kHeaderSize);
-
// Because header is a pointer into the dynamic array, we can't push any new data into the key
// below here.
@@ -259,9 +293,11 @@ bool GrGLProgramDesc::Build(const GrDrawState& drawState,
header->fCoverageOutput = kModulate_CoverageOutput;
// If we do have coverage determine whether it matters.
- bool separateCoverageFromColor = false;
+ bool separateCoverageFromColor = drawState.hasGeometryProcessor();
if (!drawState.isCoverageDrawing() && !skipCoverage &&
- (drawState.numCoverageStages() > 0 || requiresCoverageAttrib)) {
+ (drawState.numCoverageStages() > 0 ||
+ drawState.hasGeometryProcessor() ||
+ requiresCoverageAttrib)) {
if (gpu->caps()->dualSourceBlendingSupport() &&
!(blendOpts & (GrDrawState::kEmitCoverage_BlendOptFlag |
@@ -286,6 +322,7 @@ bool GrGLProgramDesc::Build(const GrDrawState& drawState,
separateCoverageFromColor = true;
}
}
+
if (!skipColor) {
for (int s = firstEffectiveColorStage; s < drawState.numColorStages(); ++s) {
colorStages->push_back(&drawState.getColorStage(s));
diff --git a/src/gpu/gl/GrGLProgramDesc.h b/src/gpu/gl/GrGLProgramDesc.h
index aefcb508e2..b1f54b7e29 100644
--- a/src/gpu/gl/GrGLProgramDesc.h
+++ b/src/gpu/gl/GrGLProgramDesc.h
@@ -48,6 +48,7 @@ public:
const GrGpuGL* gpu,
const GrRenderTarget* dummyDstRenderTarget,
const GrTexture* dummyDstCopyTexture,
+ const GrEffectStage* geometryProcessor,
const GrEffectStage* stages[],
int numColorStages,
int numCoverageStages,
@@ -67,10 +68,15 @@ public:
GrBlendCoeff dstCoeff,
const GrGpuGL* gpu,
const GrDeviceCoordTexture* dstCopy,
+ const GrEffectStage** outGeometryProcessor,
SkTArray<const GrEffectStage*, true>* outColorStages,
SkTArray<const GrEffectStage*, true>* outCoverageStages,
GrGLProgramDesc* outDesc);
+ bool hasGeometryProcessor() const {
+ return SkToBool(this->getHeader().fHasGeometryProcessor);
+ }
+
int numColorEffects() const {
return this->getHeader().fColorEffectCnt;
}
@@ -161,6 +167,7 @@ private:
int8_t fColorAttributeIndex;
int8_t fCoverageAttributeIndex;
+ SkBool8 fHasGeometryProcessor;
int8_t fColorEffectCnt;
int8_t fCoverageEffectCnt;
};
@@ -213,13 +220,24 @@ private:
class EffectKeyProvider {
public:
enum EffectType {
+ kGeometryProcessor_EffectType,
kColor_EffectType,
kCoverage_EffectType,
};
EffectKeyProvider(const GrGLProgramDesc* desc, EffectType type) : fDesc(desc) {
- // Coverage effect key offsets begin immediately after those of the color effects.
- fBaseIndex = kColor_EffectType == type ? 0 : desc->numColorEffects();
+ switch (type) {
+ case kGeometryProcessor_EffectType:
+ // there can be only one
+ fBaseIndex = 0;
+ break;
+ case kColor_EffectType:
+ fBaseIndex = desc->hasGeometryProcessor() ? 1 : 0;
+ break;
+ case kCoverage_EffectType:
+ fBaseIndex = desc->numColorEffects() + (desc->hasGeometryProcessor() ? 1 : 0);
+ break;
+ }
}
GrEffectKey get(int index) const {
diff --git a/src/gpu/gl/GrGLProgramEffects.cpp b/src/gpu/gl/GrGLProgramEffects.cpp
index 8d97b42329..45edca8106 100644
--- a/src/gpu/gl/GrGLProgramEffects.cpp
+++ b/src/gpu/gl/GrGLProgramEffects.cpp
@@ -387,6 +387,24 @@ void GrGLVertexProgramEffects::setData(GrGpuGL* gpu,
}
}
+void GrGLVertexProgramEffects::setData(GrGpuGL* gpu,
+ GrGpu::DrawType drawType,
+ const GrGLProgramDataManager& programDataManager,
+ const GrEffectStage* effectStage) {
+ SkASSERT(1 == fTransforms.count());
+ SkASSERT(1 == fSamplers.count());
+ SkASSERT(1 == fGLEffects.count());
+ GrDrawEffect drawEffect(*effectStage, fHasExplicitLocalCoords);
+ fGLEffects[0]->setData(programDataManager, drawEffect);
+ if (GrGpu::IsPathRenderingDrawType(drawType)) {
+ this->setPathTransformData(gpu, programDataManager, drawEffect, 0);
+ } else {
+ this->setTransformData(gpu, programDataManager, drawEffect, 0);
+ }
+
+ this->bindTextures(gpu, drawEffect.effect(), 0);
+}
+
void GrGLVertexProgramEffects::setTransformData(GrGpuGL* gpu,
const GrGLProgramDataManager& pdman,
const GrDrawEffect& drawEffect,
diff --git a/src/gpu/gl/GrGLProgramEffects.h b/src/gpu/gl/GrGLProgramEffects.h
index 0eaff53b76..daaebd6b37 100644
--- a/src/gpu/gl/GrGLProgramEffects.h
+++ b/src/gpu/gl/GrGLProgramEffects.h
@@ -57,6 +57,11 @@ public:
const GrGLProgramDataManager&,
const GrEffectStage* effectStages[]) = 0;
+ virtual void setData(GrGpuGL*,
+ GrGpu::DrawType,
+ const GrGLProgramDataManager&,
+ const GrEffectStage* effectStages) { SkFAIL("DO NOT USE"); }
+
void addEffect(GrGLEffect* effect) { fGLEffects.push_back(effect); }
/**
@@ -140,7 +145,6 @@ protected:
SkTArray<SkSTArray<4, Sampler, true> > fSamplers;
private:
- friend class GrGLFragmentO;
typedef SkRefCnt INHERITED;
};
@@ -172,6 +176,11 @@ public:
const GrGLProgramDataManager&,
const GrEffectStage* effectStages[]) SK_OVERRIDE;
+ virtual void setData(GrGpuGL*,
+ GrGpu::DrawType,
+ const GrGLProgramDataManager&,
+ const GrEffectStage* effectStages) SK_OVERRIDE;
+
private:
friend class GrGLFullProgramBuilder;
diff --git a/src/gpu/gl/GrGpuGL.h b/src/gpu/gl/GrGpuGL.h
index 1f748bb826..004ce254bf 100644
--- a/src/gpu/gl/GrGpuGL.h
+++ b/src/gpu/gl/GrGpuGL.h
@@ -179,6 +179,7 @@ private:
void abandon();
GrGLProgram* getProgram(const GrGLProgramDesc& desc,
+ const GrEffectStage* geometryProcessor,
const GrEffectStage* colorStages[],
const GrEffectStage* coverageStages[]);
diff --git a/src/gpu/gl/GrGpuGL_program.cpp b/src/gpu/gl/GrGpuGL_program.cpp
index 8cdceb86af..67c0cd3a47 100644
--- a/src/gpu/gl/GrGpuGL_program.cpp
+++ b/src/gpu/gl/GrGpuGL_program.cpp
@@ -90,6 +90,7 @@ int GrGpuGL::ProgramCache::search(const GrGLProgramDesc& desc) const {
}
GrGLProgram* GrGpuGL::ProgramCache::getProgram(const GrGLProgramDesc& desc,
+ const GrEffectStage* geometryProcessor,
const GrEffectStage* colorStages[],
const GrEffectStage* coverageStages[]) {
#ifdef PROGRAM_CACHE_STATS
@@ -126,7 +127,8 @@ GrGLProgram* GrGpuGL::ProgramCache::getProgram(const GrGLProgramDesc& desc,
#ifdef PROGRAM_CACHE_STATS
++fCacheMisses;
#endif
- GrGLProgram* program = GrGLProgram::Create(fGpu, desc, colorStages, coverageStages);
+ GrGLProgram* program = GrGLProgram::Create(fGpu, desc, geometryProcessor,
+ colorStages, coverageStages);
if (NULL == program) {
return NULL;
}
@@ -222,6 +224,7 @@ bool GrGpuGL::flushGraphicsState(DrawType type, const GrDeviceCoordTexture* dstC
return false;
}
+ const GrEffectStage* geometryProcessor = NULL;
SkSTArray<8, const GrEffectStage*, true> colorStages;
SkSTArray<8, const GrEffectStage*, true> coverageStages;
GrGLProgramDesc desc;
@@ -232,6 +235,7 @@ bool GrGpuGL::flushGraphicsState(DrawType type, const GrDeviceCoordTexture* dstC
dstCoeff,
this,
dstCopy,
+ &geometryProcessor,
&colorStages,
&coverageStages,
&desc)) {
@@ -240,6 +244,7 @@ bool GrGpuGL::flushGraphicsState(DrawType type, const GrDeviceCoordTexture* dstC
}
fCurrentProgram.reset(fProgramCache->getProgram(desc,
+ geometryProcessor,
colorStages.begin(),
coverageStages.begin()));
if (NULL == fCurrentProgram.get()) {
@@ -260,6 +265,7 @@ bool GrGpuGL::flushGraphicsState(DrawType type, const GrDeviceCoordTexture* dstC
fCurrentProgram->setData(type,
blendOpts,
+ geometryProcessor,
colorStages.begin(),
coverageStages.begin(),
dstCopy,
diff --git a/src/gpu/gl/builders/GrGLProgramBuilder.cpp b/src/gpu/gl/builders/GrGLProgramBuilder.cpp
index 7664bab90f..ab64e28a78 100644
--- a/src/gpu/gl/builders/GrGLProgramBuilder.cpp
+++ b/src/gpu/gl/builders/GrGLProgramBuilder.cpp
@@ -31,7 +31,8 @@ static const GrGLShaderVar::Precision kDefaultFragmentPrecision = GrGLShaderVar:
///////////////////////////////////////////////////////////////////////////////////////////////////
-bool GrGLProgramBuilder::genProgram(const GrEffectStage* colorStages[],
+bool GrGLProgramBuilder::genProgram(const GrEffectStage* geometryProcessor,
+ const GrEffectStage* colorStages[],
const GrEffectStage* coverageStages[]) {
const GrGLProgramDesc::KeyHeader& header = this->desc().getHeader();
@@ -79,6 +80,8 @@ bool GrGLProgramBuilder::genProgram(const GrEffectStage* colorStages[],
colorKeyProvider,
&inputColor));
+ this->emitGeometryProcessor(geometryProcessor, &inputCoverage);
+
GrGLProgramDesc::EffectKeyProvider coverageKeyProvider(
&this->desc(), GrGLProgramDesc::EffectKeyProvider::kCoverage_EffectType);
fCoverageEffects.reset(this->createAndEmitEffects(coverageStages,
@@ -334,10 +337,23 @@ GrGLFullProgramBuilder::GrGLFullProgramBuilder(GrGpuGL* gpu,
, fVS(this) {
}
-void GrGLFullProgramBuilder::emitCodeBeforeEffects(GrGLSLExpr4* color, GrGLSLExpr4* coverage) {
+void GrGLFullProgramBuilder::emitCodeBeforeEffects(GrGLSLExpr4* color,
+ GrGLSLExpr4* coverage) {
fVS.emitCodeBeforeEffects(color, coverage);
}
+void GrGLFullProgramBuilder::emitGeometryProcessor(const GrEffectStage* geometryProcessor,
+ GrGLSLExpr4* coverage) {
+ if (NULL != geometryProcessor) {
+ GrGLProgramDesc::EffectKeyProvider geometryProcessorKeyProvider(
+ &this->desc(), GrGLProgramDesc::EffectKeyProvider::kGeometryProcessor_EffectType);
+ fGeometryProcessor.reset(this->createAndEmitEffect(
+ geometryProcessor,
+ geometryProcessorKeyProvider,
+ coverage));
+ }
+}
+
void GrGLFullProgramBuilder::emitCodeAfterEffects() {
fVS.emitCodeAfterEffects();
}
@@ -388,6 +404,56 @@ GrGLProgramEffects* GrGLFullProgramBuilder::createAndEmitEffects(
return programEffectsBuilder.finish();
}
+void GrGLFullProgramBuilder::createAndEmitEffect(GrGLProgramEffectsBuilder* programEffectsBuilder,
+ const GrEffectStage* effectStages,
+ const GrGLProgramDesc::EffectKeyProvider& keyProvider,
+ GrGLSLExpr4* fsInOutColor) {
+ GrGLSLExpr4 inColor = *fsInOutColor;
+ GrGLSLExpr4 outColor;
+
+ SkASSERT(NULL != effectStages && NULL != effectStages->getEffect());
+ const GrEffectStage& stage = *effectStages;
+
+ // Using scope to force ASR destructor to be triggered
+ {
+ CodeStage::AutoStageRestore csar(&fCodeStage, &stage);
+
+ 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;
+ }
+
+ // create var to hold stage result
+ SkString outColorName;
+ this->nameVariable(&outColorName, '\0', "output");
+ fFS.codeAppendf("vec4 %s;", outColorName.c_str());
+ outColor = outColorName;
+
+
+ programEffectsBuilder->emitEffect(stage,
+ keyProvider.get(0),
+ outColor.c_str(),
+ inColor.isOnes() ? NULL : inColor.c_str(),
+ fCodeStage.stageIndex());
+ }
+
+ *fsInOutColor = outColor;
+}
+
+GrGLProgramEffects* GrGLFullProgramBuilder::createAndEmitEffect(
+ const GrEffectStage* geometryProcessor,
+ const GrGLProgramDesc::EffectKeyProvider& keyProvider,
+ GrGLSLExpr4* inOutFSColor) {
+
+ GrGLVertexProgramEffectsBuilder programEffectsBuilder(this, 1);
+ this->createAndEmitEffect(&programEffectsBuilder, geometryProcessor, keyProvider, inOutFSColor);
+ return programEffectsBuilder.finish();
+}
+
bool GrGLFullProgramBuilder::compileAndAttachShaders(GrGLuint programId,
SkTDArray<GrGLuint>* shaderIds) const {
return INHERITED::compileAndAttachShaders(programId, shaderIds)
diff --git a/src/gpu/gl/builders/GrGLProgramBuilder.h b/src/gpu/gl/builders/GrGLProgramBuilder.h
index 00193efc45..deb3708bd1 100644
--- a/src/gpu/gl/builders/GrGLProgramBuilder.h
+++ b/src/gpu/gl/builders/GrGLProgramBuilder.h
@@ -84,11 +84,14 @@ public:
* to be used.
* @return true if generation was successful.
*/
- bool genProgram(const GrEffectStage* inColorStages[],
- const GrEffectStage* inCoverageStages[]);
- // Below are the results of the shader generation.
+ bool genProgram(const GrEffectStage* inGeometryProcessor,
+ const GrEffectStage* inColorStages[],
+ const GrEffectStage* inCoverageStages[]);
+ GrGLProgramEffects* getGeometryProcessor() const {
+ SkASSERT(fProgramID); return fGeometryProcessor.get();
+ }
GrGLProgramEffects* getColorEffects() const { SkASSERT(fProgramID); return fColorEffects.get(); }
GrGLProgramEffects* getCoverageEffects() const { SkASSERT(fProgramID); return fCoverageEffects.get(); }
const BuiltinUniformHandles& getBuiltinUniformHandles() const {
@@ -165,6 +168,7 @@ protected:
void appendDecls(const VarArray&, SkString*) const;
void appendUniformDecls(ShaderVisibility, SkString*) const;
+ SkAutoTUnref<GrGLProgramEffects> fGeometryProcessor;
SkAutoTUnref<GrGLProgramEffects> fColorEffects;
SkAutoTUnref<GrGLProgramEffects> fCoverageEffects;
BuiltinUniformHandles fUniformHandles;
@@ -173,7 +177,7 @@ protected:
GrGLuint fProgramID;
GrGLFragmentShaderBuilder fFS;
SeparableVaryingInfoArray fSeparableVaryingInfos;
-private:
+
class CodeStage : SkNoncopyable {
public:
CodeStage() : fNextIndex(0), fCurrentIndex(-1), fEffectStage(NULL) {}
@@ -224,6 +228,7 @@ private:
int fCurrentIndex;
const GrEffectStage* fEffectStage;
} fCodeStage;
+private:
/**
* The base class will emit the fragment code that precedes the per-effect code and then call
@@ -232,7 +237,14 @@ private:
*
* The subclass can modify the initial color or coverage
*/
- virtual void emitCodeBeforeEffects(GrGLSLExpr4* color, GrGLSLExpr4* coverage) = 0;
+ virtual void emitCodeBeforeEffects(GrGLSLExpr4* color,
+ GrGLSLExpr4* coverage) = 0;
+
+ /*
+ * Full shader builder needs to emit code after the color stages and before the coverage stages
+ */
+ virtual void emitGeometryProcessor(const GrEffectStage* geometryProcessor,
+ GrGLSLExpr4* coverage) = 0;
/**
* Adds code for effects and returns a GrGLProgramEffects* object. The caller is responsible for
@@ -297,13 +309,30 @@ public:
GrGLVertexShaderBuilder* getVertexShaderBuilder() { return &fVS; }
private:
- virtual void emitCodeBeforeEffects(GrGLSLExpr4* color, GrGLSLExpr4* coverage) SK_OVERRIDE;
+ virtual void emitCodeBeforeEffects(GrGLSLExpr4* color,
+ GrGLSLExpr4* coverage) SK_OVERRIDE;
+
+ virtual void emitGeometryProcessor(const GrEffectStage* geometryProcessor,
+ GrGLSLExpr4* coverage) SK_OVERRIDE;
virtual GrGLProgramEffects* createAndEmitEffects(const GrEffectStage* effectStages[],
int effectCnt,
const GrGLProgramDesc::EffectKeyProvider&,
GrGLSLExpr4* inOutFSColor) SK_OVERRIDE;
+ /*
+ * These functions are temporary and will eventually operate not on effects but on
+ * geometry processors
+ */
+ void createAndEmitEffect(GrGLProgramEffectsBuilder*,
+ const GrEffectStage* effectStage,
+ const GrGLProgramDesc::EffectKeyProvider&,
+ GrGLSLExpr4* inOutFSColor);
+
+ GrGLProgramEffects* createAndEmitEffect(const GrEffectStage* geometryProcessor,
+ const GrGLProgramDesc::EffectKeyProvider&,
+ GrGLSLExpr4* inOutFSColor);
+
virtual void emitCodeAfterEffects() SK_OVERRIDE;
virtual bool compileAndAttachShaders(GrGLuint programId,
@@ -326,7 +355,13 @@ public:
int addTexCoordSets(int count);
private:
- virtual void emitCodeBeforeEffects(GrGLSLExpr4* color, GrGLSLExpr4* coverage) SK_OVERRIDE {}
+ virtual void emitCodeBeforeEffects(GrGLSLExpr4* color,
+ GrGLSLExpr4* coverage) SK_OVERRIDE {}
+
+ virtual void emitGeometryProcessor(const GrEffectStage* geometryProcessor,
+ GrGLSLExpr4* coverage) SK_OVERRIDE {
+ SkASSERT(NULL == geometryProcessor);
+ }
virtual GrGLProgramEffects* createAndEmitEffects(const GrEffectStage* effectStages[],
int effectCnt,
diff --git a/tests/GLProgramsTest.cpp b/tests/GLProgramsTest.cpp
index af280466ae..6efd7d5b5b 100644
--- a/tests/GLProgramsTest.cpp
+++ b/tests/GLProgramsTest.cpp
@@ -26,6 +26,7 @@ bool GrGLProgramDesc::setRandom(SkRandom* random,
const GrGpuGL* gpu,
const GrRenderTarget* dstRenderTarget,
const GrTexture* dstCopyTexture,
+ const GrEffectStage* geometryProcessor,
const GrEffectStage* stages[],
int numColorStages,
int numCoverageStages,
@@ -38,24 +39,50 @@ bool GrGLProgramDesc::setRandom(SkRandom* random,
GR_STATIC_ASSERT(0 == kEffectKeyOffsetsAndLengthOffset % sizeof(uint32_t));
// Make room for everything up to and including the array of offsets to effect keys.
- fKey.push_back_n(kEffectKeyOffsetsAndLengthOffset + 2 * sizeof(uint16_t) * numStages);
+ fKey.push_back_n(kEffectKeyOffsetsAndLengthOffset + 2 * sizeof(uint16_t) * (numStages +
+ (geometryProcessor ? 1 : 0)));
bool dstRead = false;
bool fragPos = false;
- bool vertexShader = false;
- for (int s = 0; s < numStages; ++s) {
+ bool vertexShader = (NULL != geometryProcessor);
+ int offset = 0;
+ if (NULL != geometryProcessor) {
+ const GrEffectStage* stage = geometryProcessor;
uint16_t* offsetAndSize = reinterpret_cast<uint16_t*>(fKey.begin() +
kEffectKeyOffsetsAndLengthOffset +
- s * 2 * sizeof(uint16_t));
+ offset * 2 * sizeof(uint16_t));
uint32_t effectKeyOffset = fKey.count();
if (effectKeyOffset > SK_MaxU16) {
fKey.reset();
return false;
}
- GrDrawEffect drawEffect(*stages[s], useLocalCoords);
+ GrDrawEffect drawEffect(*stage, useLocalCoords);
GrEffectKeyBuilder b(&fKey);
uint16_t effectKeySize;
- if (!GetEffectKeyAndUpdateStats(*stages[s], gpu->glCaps(), useLocalCoords, &b,
+ if (!GetEffectKeyAndUpdateStats(*stage, gpu->glCaps(), useLocalCoords, &b,
+ &effectKeySize, &dstRead, &fragPos, &vertexShader)) {
+ fKey.reset();
+ return false;
+ }
+ offsetAndSize[0] = effectKeyOffset;
+ offsetAndSize[1] = effectKeySize;
+ offset++;
+ }
+
+ for (int s = 0; s < numStages; ++s, ++offset) {
+ const GrEffectStage* stage = stages[s];
+ uint16_t* offsetAndSize = reinterpret_cast<uint16_t*>(fKey.begin() +
+ kEffectKeyOffsetsAndLengthOffset +
+ offset * 2 * sizeof(uint16_t));
+ uint32_t effectKeyOffset = fKey.count();
+ if (effectKeyOffset > SK_MaxU16) {
+ fKey.reset();
+ return false;
+ }
+ GrDrawEffect drawEffect(*stage, useLocalCoords);
+ GrEffectKeyBuilder b(&fKey);
+ uint16_t effectKeySize;
+ if (!GetEffectKeyAndUpdateStats(*stage, gpu->glCaps(), useLocalCoords, &b,
&effectKeySize, &dstRead, &fragPos, &vertexShader)) {
fKey.reset();
return false;
@@ -118,6 +145,7 @@ bool GrGLProgramDesc::setRandom(SkRandom* random,
useLocalCoords ||
kAttribute_ColorInput == header->fColorInput ||
kAttribute_ColorInput == header->fCoverageInput;
+ header->fHasGeometryProcessor = vertexShader;
CoverageOutput coverageOutput;
bool illegalCoverageOutput;
@@ -179,8 +207,35 @@ bool GrGpuGL::programUnitTest(int maxStages) {
SkAutoSTMalloc<8, const GrEffectStage*> stages(numStages);
bool useFixedFunctionPathRendering = this->glCaps().pathRenderingSupport() &&
- this->glPathRendering()->texturingMode() == GrGLPathRendering::FixedFunction_TexturingMode;
+ this->glPathRendering()->texturingMode() == GrGLPathRendering::FixedFunction_TexturingMode &&
+ random.nextBool();
+
+ SkAutoTDelete<GrEffectStage> geometryProcessor;
+ bool hasGeometryProcessor = useFixedFunctionPathRendering ? false : random.nextBool();
+ if (hasGeometryProcessor) {
+ while (true) {
+ SkAutoTUnref<const GrEffect> effect(GrEffectTestFactory::CreateStage(
+ &random,
+ this->getContext(),
+ *this->caps(),
+ dummyTextures));
+ SkASSERT(effect);
+
+ // Only geometryProcessor can use vertex shader
+ if (!effect->requiresVertexShader()) {
+ continue;
+ }
+ int numAttribs = effect->numVertexAttribs();
+ for (int i = 0; i < numAttribs; ++i) {
+ attribIndices[i] = currAttribIndex++;
+ }
+ GrEffectStage* stage = SkNEW_ARGS(GrEffectStage,
+ (effect.get(), attribIndices[0], attribIndices[1]));
+ geometryProcessor.reset(stage);
+ break;
+ }
+ }
for (int s = 0; s < numStages;) {
SkAutoTUnref<const GrEffect> effect(GrEffectTestFactory::CreateStage(
&random,
@@ -188,32 +243,24 @@ bool GrGpuGL::programUnitTest(int maxStages) {
*this->caps(),
dummyTextures));
SkASSERT(effect);
- int numAttribs = effect->numVertexAttribs();
- // If adding this effect would exceed the max attrib count then generate a
- // new random effect.
- if (currAttribIndex + numAttribs > GrDrawState::kMaxVertexAttribCnt) {
+ // Only geometryProcessor can use vertex shader
+ if (effect->requiresVertexShader()) {
continue;
}
-
// If adding this effect would exceed the max texture coord set count then generate a
// new random effect.
- if (useFixedFunctionPathRendering && !effect->requiresVertexShader()) {
+ if (useFixedFunctionPathRendering) {
int numTransforms = effect->numTransforms();
if (currTextureCoordSet + numTransforms > this->glCaps().maxFixedFunctionTextureCoords()) {
continue;
}
currTextureCoordSet += numTransforms;
}
-
- useFixedFunctionPathRendering = useFixedFunctionPathRendering && !effect->requiresVertexShader();
-
- for (int i = 0; i < numAttribs; ++i) {
- attribIndices[i] = currAttribIndex++;
- }
GrEffectStage* stage = SkNEW_ARGS(GrEffectStage,
(effect.get(), attribIndices[0], attribIndices[1]));
+
stages[s] = stage;
++s;
}
@@ -222,6 +269,7 @@ bool GrGpuGL::programUnitTest(int maxStages) {
this,
dummyTextures[0]->asRenderTarget(),
dstTexture,
+ geometryProcessor.get(),
stages.get(),
numColorStages,
numCoverageStages,
@@ -231,6 +279,7 @@ bool GrGpuGL::programUnitTest(int maxStages) {
SkAutoTUnref<GrGLProgram> program(GrGLProgram::Create(this,
pdesc,
+ geometryProcessor.get(),
stages,
stages + numColorStages));
for (int s = 0; s < numStages; ++s) {