aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--gyp/gpu.gypi8
-rw-r--r--include/core/SkTArray.h17
-rw-r--r--include/gpu/GrBackendEffectFactory.h3
-rw-r--r--include/gpu/GrEffect.h27
-rw-r--r--include/gpu/GrEffectStage.h25
-rw-r--r--include/gpu/GrTBackendEffectFactory.h7
-rw-r--r--include/gpu/GrTypesPriv.h27
-rw-r--r--src/gpu/GrContext.cpp19
-rw-r--r--src/gpu/GrDrawState.cpp79
-rw-r--r--src/gpu/GrDrawState.h29
-rw-r--r--src/gpu/GrDrawTarget.cpp2
-rw-r--r--src/gpu/GrEffect.cpp5
-rw-r--r--src/gpu/GrSWMaskHelper.cpp3
-rw-r--r--src/gpu/GrTextContext.cpp3
-rw-r--r--src/gpu/effects/GrEllipseEdgeEffect.cpp80
-rw-r--r--src/gpu/effects/GrEllipseEdgeEffect.h50
-rw-r--r--src/gpu/gl/GrGLEffect.cpp15
-rw-r--r--src/gpu/gl/GrGLEffect.h1
-rw-r--r--src/gpu/gl/GrGLProgram.cpp35
-rw-r--r--src/gpu/gl/GrGLSL.h17
-rw-r--r--src/gpu/gl/GrGLShaderBuilder.cpp41
-rw-r--r--src/gpu/gl/GrGLShaderBuilder.h21
-rw-r--r--tests/GLProgramsTest.cpp7
23 files changed, 446 insertions, 75 deletions
diff --git a/gyp/gpu.gypi b/gyp/gpu.gypi
index 41f0f09ee2..d9b4b22e07 100644
--- a/gyp/gpu.gypi
+++ b/gyp/gpu.gypi
@@ -122,19 +122,21 @@
'<(skia_src_path)/gpu/gr_unittests.cpp',
'<(skia_src_path)/gpu/effects/Gr1DKernelEffect.h',
- '<(skia_src_path)/gpu/effects/GrTextureStripAtlas.h',
- '<(skia_src_path)/gpu/effects/GrTextureStripAtlas.cpp',
'<(skia_src_path)/gpu/effects/GrConfigConversionEffect.cpp',
'<(skia_src_path)/gpu/effects/GrConfigConversionEffect.h',
'<(skia_src_path)/gpu/effects/GrConvolutionEffect.cpp',
'<(skia_src_path)/gpu/effects/GrConvolutionEffect.h',
+ '<(skia_src_path)/gpu/effects/GrEllipseEdgeEffect.cpp',
+ '<(skia_src_path)/gpu/effects/GrEllipseEdgeEffect.h',
'<(skia_src_path)/gpu/effects/GrSimpleTextureEffect.cpp',
'<(skia_src_path)/gpu/effects/GrSimpleTextureEffect.h',
'<(skia_src_path)/gpu/effects/GrSingleTextureEffect.cpp',
'<(skia_src_path)/gpu/effects/GrSingleTextureEffect.h',
'<(skia_src_path)/gpu/effects/GrTextureDomainEffect.cpp',
'<(skia_src_path)/gpu/effects/GrTextureDomainEffect.h',
-
+ '<(skia_src_path)/gpu/effects/GrTextureStripAtlas.cpp',
+ '<(skia_src_path)/gpu/effects/GrTextureStripAtlas.h',
+
'<(skia_src_path)/gpu/gl/GrGLBufferImpl.cpp',
'<(skia_src_path)/gpu/gl/GrGLBufferImpl.h',
'<(skia_src_path)/gpu/gl/GrGLCaps.cpp',
diff --git a/include/core/SkTArray.h b/include/core/SkTArray.h
index 89f4c9d304..45808d4b60 100644
--- a/include/core/SkTArray.h
+++ b/include/core/SkTArray.h
@@ -280,6 +280,23 @@ public:
return fItemArray[fCount - i - 1];
}
+ bool operator==(const SkTArray<T, MEM_COPY>& right) const {
+ int leftCount = this->count();
+ if (leftCount != right.count()) {
+ return false;
+ }
+ for (int index = 0; index < leftCount; ++index) {
+ if (fItemArray[index] != right.fItemArray[index]) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ bool operator!=(const SkTArray<T, MEM_COPY>& right) const {
+ return !(*this == right);
+ }
+
protected:
/**
* Creates an empty array that will use the passed storage block until it
diff --git a/include/gpu/GrBackendEffectFactory.h b/include/gpu/GrBackendEffectFactory.h
index a2913870b4..f5e638fef3 100644
--- a/include/gpu/GrBackendEffectFactory.h
+++ b/include/gpu/GrBackendEffectFactory.h
@@ -40,7 +40,8 @@ public:
* GrGLEffects' control. So there is a dedicated part of the key which is combined
* automatically with the bits produced by GrGLEffect::GenKey().
*/
- kTextureKeyBits = 6
+ kTextureKeyBits = 6,
+ kAttribKeyBits = 4
};
virtual EffectKey glEffectKey(const GrEffectStage&, const GrGLCaps&) const = 0;
diff --git a/include/gpu/GrEffect.h b/include/gpu/GrEffect.h
index 7b7cd33b17..2792476a6d 100644
--- a/include/gpu/GrEffect.h
+++ b/include/gpu/GrEffect.h
@@ -14,6 +14,7 @@
#include "GrRefCnt.h"
#include "GrTexture.h"
#include "GrTextureAccess.h"
+#include "GrTypesPriv.h"
class GrBackendEffectFactory;
class GrContext;
@@ -136,6 +137,14 @@ public:
/** Shortcut for textureAccess(index).texture(); */
GrTexture* texture(int index) const { return this->textureAccess(index).getTexture(); }
+
+ int numVertexAttribs() const { return fVertexAttribTypes.count(); }
+
+ GrSLType vertexAttribType(int index) const { return fVertexAttribTypes[index]; }
+
+ static const int kMaxVertexAttribs = 2;
+
+
/** Useful for effects that want to insert a texture matrix that is implied by the texture
dimensions */
static inline SkMatrix MakeDivByTextureWHMatrix(const GrTexture* texture) {
@@ -168,12 +177,19 @@ public:
protected:
/**
- * Subclasses call this from their constructor to register GrTextureAcceses. The effect subclass
- * manages the lifetime of the accesses (this function only stores a pointer). This must only be
- * called from the constructor because GrEffects are supposed to be immutable.
+ * Subclasses call this from their constructor to register GrTextureAccesses. The effect
+ * subclass manages the lifetime of the accesses (this function only stores a pointer). This
+ * must only be called from the constructor because GrEffects are immutable.
*/
void addTextureAccess(const GrTextureAccess* textureAccess);
+ /**
+ * Subclasses call this from their constructor to register vertex attributes (at most
+ * kMaxVertexAttribs). This must only be called from the constructor because GrEffects are
+ * immutable.
+ */
+ void addVertexAttrib(GrSLType type);
+
GrEffect() : fEffectRef(NULL) {};
/** This should be called by GrEffect subclass factories. See the comment on AutoEffectUnref for
@@ -246,8 +262,9 @@ private:
// from deferred state, to call isEqual on naked GrEffects, and
// to inc/dec deferred ref counts.
- SkSTArray<4, const GrTextureAccess*, true> fTextureAccesses;
- GrEffectRef* fEffectRef;
+ SkSTArray<4, const GrTextureAccess*, true> fTextureAccesses;
+ SkSTArray<kMaxVertexAttribs, GrSLType, true> fVertexAttribTypes;
+ GrEffectRef* fEffectRef;
typedef GrRefCnt INHERITED;
};
diff --git a/include/gpu/GrEffectStage.h b/include/gpu/GrEffectStage.h
index 05bc313091..05bf40c4bc 100644
--- a/include/gpu/GrEffectStage.h
+++ b/include/gpu/GrEffectStage.h
@@ -116,6 +116,7 @@ public:
stage.fEffectRef->get()->incDeferredRefCounts();
fEffect = stage.fEffectRef->get();
fCoordChangeMatrix = stage.fCoordChangeMatrix;
+ fVertexAttribIndices = stage.fVertexAttribIndices;
}
SkDEBUGCODE(fInitialized = true;)
}
@@ -126,6 +127,7 @@ public:
if (NULL != fEffect) {
stage->fEffectRef = GrEffect::CreateEffectRef(fEffect);
stage->fCoordChangeMatrix = fCoordChangeMatrix;
+ stage->fVertexAttribIndices = fVertexAttribIndices;
} else {
stage->fEffectRef = NULL;
}
@@ -139,16 +141,21 @@ public:
return false;
}
- if (!(*stage.getEffect())->isEqual(*fEffect)) {
+ if (fVertexAttribIndices != stage.fVertexAttribIndices) {
return false;
}
+ if (!(*stage.getEffect())->isEqual(*fEffect)) {
+ return false;
+ }
+
return fCoordChangeMatrix == stage.fCoordChangeMatrix;
}
private:
const GrEffect* fEffect;
SkMatrix fCoordChangeMatrix;
+ SkSTArray<GrEffect::kMaxVertexAttribs, int, true> fVertexAttribIndices;
SkDEBUGCODE(bool fInitialized;)
};
@@ -162,18 +169,28 @@ public:
GrSafeSetNull(fEffectRef);
}
- const GrEffectRef* setEffect(const GrEffectRef* EffectRef) {
+ const GrEffectRef* setEffect(const GrEffectRef* EffectRef, const int* attribIndices = NULL) {
GrAssert(0 == fSavedCoordChangeCnt);
GrSafeAssign(fEffectRef, EffectRef);
fCoordChangeMatrix.reset();
+
+ fVertexAttribIndices.reset();
+ int numVertexAttribs = (EffectRef == NULL) ? 0 : EffectRef->get()->numVertexAttribs();
+ GrAssert(numVertexAttribs == 0 || attribIndices != NULL);
+ fVertexAttribIndices.push_back_n(numVertexAttribs, attribIndices);
+
return EffectRef;
}
const GrEffectRef* getEffect() const { return fEffectRef; }
+ const int* getVertexAttribIndices() const { return fVertexAttribIndices.begin(); }
+ int getVertexAttribIndexCount() const { return fVertexAttribIndices.count(); }
+
private:
- SkMatrix fCoordChangeMatrix;
- const GrEffectRef* fEffectRef;
+ SkMatrix fCoordChangeMatrix;
+ const GrEffectRef* fEffectRef;
+ SkSTArray<2, int, true> fVertexAttribIndices;
GR_DEBUGCODE(mutable int fSavedCoordChangeCnt;)
};
diff --git a/include/gpu/GrTBackendEffectFactory.h b/include/gpu/GrTBackendEffectFactory.h
index 7ea7e39ebc..72b2aeaa27 100644
--- a/include/gpu/GrTBackendEffectFactory.h
+++ b/include/gpu/GrTBackendEffectFactory.h
@@ -35,14 +35,19 @@ public:
GrAssert(kIllegalEffectClassID != fEffectClassID);
EffectKey effectKey = GLEffect::GenKey(stage, caps);
EffectKey textureKey = GLEffect::GenTextureKey(stage.getEffect(), caps);
+ EffectKey attribKey = GLEffect::GenAttribKey(stage);
#if GR_DEBUG
static const EffectKey kIllegalIDMask = (uint16_t) (~((1U << kEffectKeyBits) - 1));
GrAssert(!(kIllegalIDMask & effectKey));
static const EffectKey kIllegalTextureKeyMask = (uint16_t) (~((1U << kTextureKeyBits) - 1));
GrAssert(!(kIllegalTextureKeyMask & textureKey));
+
+ static const EffectKey kIllegalAttribKeyMask = (uint16_t) (~((1U << kAttribKeyBits) - 1));
+ GrAssert(!(kIllegalAttribKeyMask & textureKey));
#endif
- return fEffectClassID | (textureKey << kEffectKeyBits) | effectKey;
+ return fEffectClassID | (attribKey << (kEffectKeyBits+kTextureKeyBits)) |
+ (textureKey << kEffectKeyBits) | effectKey;
}
/** Returns a new instance of the appropriate *GL* implementation class
diff --git a/include/gpu/GrTypesPriv.h b/include/gpu/GrTypesPriv.h
new file mode 100644
index 0000000000..fea80f8f46
--- /dev/null
+++ b/include/gpu/GrTypesPriv.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrTypesPriv_DEFINED
+#define GrTypesPriv_DEFINED
+
+/**
+ * Types of shader-language-specific boxed variables we can create.
+ * (Currently only GrGLShaderVars, but should be applicable to other shader
+ * languages.)
+ */
+enum GrSLType {
+ kVoid_GrSLType,
+ kFloat_GrSLType,
+ kVec2f_GrSLType,
+ kVec3f_GrSLType,
+ kVec4f_GrSLType,
+ kMat33f_GrSLType,
+ kMat44f_GrSLType,
+ kSampler2D_GrSLType
+};
+
+#endif
diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp
index 046e067cfc..7c852124e8 100644
--- a/src/gpu/GrContext.cpp
+++ b/src/gpu/GrContext.cpp
@@ -12,6 +12,7 @@
#include "effects/GrConvolutionEffect.h"
#include "effects/GrSingleTextureEffect.h"
#include "effects/GrConfigConversionEffect.h"
+#include "effects/GrEllipseEdgeEffect.h"
#include "GrBufferAllocPool.h"
#include "GrGpu.h"
@@ -1072,12 +1073,8 @@ void GrContext::internalDrawOval(const GrPaint& paint,
{kVec2f_GrVertexAttribType, 0},
{kVec4f_GrVertexAttribType, sizeof(GrPoint)}
};
- static const GrAttribBindings kAttributeBindings = GrDrawState::kEdge_AttribBindingsBit;
-
drawState->setVertexAttribs(kVertexAttribs, SK_ARRAY_COUNT(kVertexAttribs));
drawState->setAttribIndex(GrDrawState::kPosition_AttribIndex, 0);
- drawState->setAttribIndex(GrDrawState::kEdge_AttribIndex, 1);
- drawState->setAttribBindings(kAttributeBindings);
GrAssert(sizeof(CircleVertex) == drawState->getVertexSize());
GrDrawTarget::AutoReleaseGeometry geo(target, 4, 0);
@@ -1097,7 +1094,9 @@ void GrContext::internalDrawOval(const GrPaint& paint,
SkScalar B;
if (isCircle) {
+ drawState->setAttribBindings(GrDrawState::kEdge_AttribBindingsBit);
drawState->setVertexEdgeType(GrDrawState::kCircle_EdgeType);
+ drawState->setAttribIndex(GrDrawState::kEdge_AttribIndex, 1);
xRadius = vm.mapRadius(xRadius);
@@ -1129,7 +1128,17 @@ void GrContext::internalDrawOval(const GrPaint& paint,
T = -outerRadius;
B = +outerRadius;
} else { // is axis-aligned ellipse
- drawState->setVertexEdgeType(GrDrawState::kEllipse_EdgeType);
+ drawState->setAttribBindings(GrDrawState::kDefault_AttribBindings);
+
+ enum {
+ // the edge effects share this stage with glyph rendering
+ // (kGlyphMaskStage in GrTextContext) && SW path rendering
+ // (kPathMaskStage in GrSWMaskHelper)
+ kEdgeEffectStage = GrPaint::kTotalStages,
+ };
+ GrEffectRef* effect = GrEllipseEdgeEffect::Create();
+ static const int kEdgeAttrIndex = 1;
+ drawState->setEffect(kEdgeEffectStage, effect, &kEdgeAttrIndex)->unref();
SkRect xformedRect;
vm.mapRect(&xformedRect, oval);
diff --git a/src/gpu/GrDrawState.cpp b/src/gpu/GrDrawState.cpp
index e797546118..fddce41099 100644
--- a/src/gpu/GrDrawState.cpp
+++ b/src/gpu/GrDrawState.cpp
@@ -133,6 +133,85 @@ void GrDrawState::setDefaultVertexAttribs() {
////////////////////////////////////////////////////////////////////////////////
+bool GrDrawState::validateVertexAttribs() const {
+ // color and coverage can set indices beyond the standard count
+ static const int kMaxValidAttribIndex = kVertexAttribCnt+2;
+ int attributeTypes[kMaxValidAttribIndex];
+ for (int i = 0; i < kMaxValidAttribIndex; ++i) {
+ attributeTypes[i] = -1;
+ }
+
+ // sentinel to make sure effects don't try to use built-in attributes
+ static const int kBuiltInAttributeType = 10000;
+
+ // check our built-in indices
+ if (fAttribIndices[kPosition_AttribIndex] >= kVertexAttribCnt) {
+ return false;
+ }
+ attributeTypes[fAttribIndices[kPosition_AttribIndex]] = kBuiltInAttributeType;
+ for (int j = kColor_AttribIndex; j <= kCoverage_AttribIndex; ++j) {
+ if (fCommon.fAttribBindings & kAttribIndexMasks[j]) {
+ int attributeIndex = fAttribIndices[j];
+ if (attributeIndex >= kMaxValidAttribIndex) {
+ return false;
+ }
+ // they should not be shared at all
+ if (attributeTypes[attributeIndex] != -1) {
+ return false;
+ }
+ attributeTypes[attributeIndex] = kBuiltInAttributeType;
+ }
+ }
+ for (int j = kEdge_AttribIndex; j < kAttribIndexCount; ++j) {
+ if (fCommon.fAttribBindings & kAttribIndexMasks[j]) {
+ int attributeIndex = fAttribIndices[j];
+ if (attributeIndex >= kVertexAttribCnt) {
+ return false;
+ }
+ // they should not be shared at all
+ if (attributeTypes[attributeIndex] != -1) {
+ return false;
+ }
+ attributeTypes[attributeIndex] = kBuiltInAttributeType;
+ }
+ }
+
+ // now those set by effects
+ for (int s = 0; s < kNumStages; ++s) {
+ const GrEffectStage& stage = fStages[s];
+ const GrEffectRef* effect = stage.getEffect();
+ if (effect == NULL) {
+ continue;
+ }
+
+ // make sure that the count in the stage and the effect matches
+ int numAttributes = stage.getVertexAttribIndexCount();
+ if (numAttributes != effect->get()->numVertexAttribs()) {
+ return false;
+ }
+
+ // make sure that any shared indices have the same type
+ const int* attributeIndices = stage.getVertexAttribIndices();
+ for (int i = 0; i < numAttributes; ++i) {
+ int attributeIndex = attributeIndices[i];
+ if (attributeIndex >= kVertexAttribCnt) {
+ return false;
+ }
+
+ GrSLType attributeType = effect->get()->vertexAttribType(i);
+ if (attributeTypes[attributeIndex] != -1 &&
+ attributeTypes[attributeIndex] != attributeType) {
+ return false;
+ }
+ attributeTypes[attributeIndex] = attributeType;
+ }
+ }
+
+ return true;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
bool GrDrawState::AttributesBindExplicitTexCoords(GrAttribBindings attribBindings) {
return SkToBool(kTexCoord_AttribBindingsMask & attribBindings);
}
diff --git a/src/gpu/GrDrawState.h b/src/gpu/GrDrawState.h
index 3f372973ab..220e290a83 100644
--- a/src/gpu/GrDrawState.h
+++ b/src/gpu/GrDrawState.h
@@ -181,6 +181,8 @@ public:
*/
void setDefaultVertexAttribs();
+ bool validateVertexAttribs() const;
+
////////////////////////////////////////////////////////////////////////////
// Helpers for picking apart vertex attributes
@@ -332,7 +334,7 @@ public:
bool hasSolidCoverage(GrAttribBindings) const;
static void VertexAttributesUnitTest();
-
+
/// @}
///////////////////////////////////////////////////////////////////////////
@@ -483,8 +485,9 @@ public:
/// @name Effect Stages
////
- const GrEffectRef* setEffect(int stageIdx, const GrEffectRef* effect) {
- fStages[stageIdx].setEffect(effect);
+ const GrEffectRef* setEffect(int stageIdx, const GrEffectRef* effect,
+ const int* indices = NULL) {
+ fStages[stageIdx].setEffect(effect, indices);
return effect;
}
@@ -514,7 +517,9 @@ public:
return true;
}
- void disableStage(int stageIdx) { this->setEffect(stageIdx, NULL); }
+ void disableStage(int stageIdx) {
+ this->setEffect(stageIdx, NULL, NULL);
+ }
/**
* Release all the GrEffects referred to by this draw state.
@@ -1021,9 +1026,6 @@ public:
/* Circle specified as center_x, center_y, outer_radius, inner_radius
all in window space (y-down). */
kCircle_EdgeType,
- /* Axis-aligned ellipse specified as center_x, center_y, x_radius, x_radius/y_radius
- all in window space (y-down). */
- kEllipse_EdgeType,
kVertexEdgeTypeCnt
};
@@ -1189,14 +1191,9 @@ public:
if (fRenderTarget.get() != s.fRenderTarget.get() || fCommon != s.fCommon) {
return false;
}
- if (fVertexAttribs.count() != s.fVertexAttribs.count()) {
+ if (fVertexAttribs != s.fVertexAttribs) {
return false;
}
- for (int i = 0; i < fVertexAttribs.count(); ++i) {
- if (fVertexAttribs[i] != s.fVertexAttribs[i]) {
- return false;
- }
- }
for (int i = 0; i < kAttribIndexCount; ++i) {
if ((i == kPosition_AttribIndex ||
s.fCommon.fAttribBindings & kAttribIndexMasks[i]) &&
@@ -1335,13 +1332,9 @@ public:
return false;
}
}
- if (fVertexAttribs.count() != state.fVertexAttribs.count()) {
+ if (fVertexAttribs != state.fVertexAttribs) {
return false;
}
- for (int i = 0; i < fVertexAttribs.count(); ++i)
- if (fVertexAttribs[i] != state.fVertexAttribs[i]) {
- return false;
- }
for (int i = 0; i < kNumStages; ++i) {
if (!fStages[i].isEqual(state.fStages[i])) {
return false;
diff --git a/src/gpu/GrDrawTarget.cpp b/src/gpu/GrDrawTarget.cpp
index 954a4e7687..6fdc3a080f 100644
--- a/src/gpu/GrDrawTarget.cpp
+++ b/src/gpu/GrDrawTarget.cpp
@@ -392,6 +392,8 @@ bool GrDrawTarget::checkDraw(GrPrimitiveType type, int startVertex,
}
}
}
+
+ GrAssert(drawState.validateVertexAttribs());
#endif
if (NULL == drawState.getRenderTarget()) {
return false;
diff --git a/src/gpu/GrEffect.cpp b/src/gpu/GrEffect.cpp
index 6e743e7f95..2aad7cf00e 100644
--- a/src/gpu/GrEffect.cpp
+++ b/src/gpu/GrEffect.cpp
@@ -90,6 +90,11 @@ void GrEffect::addTextureAccess(const GrTextureAccess* access) {
fTextureAccesses.push_back(access);
}
+void GrEffect::addVertexAttrib(GrSLType type) {
+ GrAssert(fVertexAttribTypes.count() < kMaxVertexAttribs);
+ fVertexAttribTypes.push_back(type);
+}
+
void* GrEffect::operator new(size_t size) {
return GrEffect_Globals::GetTLS()->allocate(size);
}
diff --git a/src/gpu/GrSWMaskHelper.cpp b/src/gpu/GrSWMaskHelper.cpp
index 9682ec427f..fe9fd8228b 100644
--- a/src/gpu/GrSWMaskHelper.cpp
+++ b/src/gpu/GrSWMaskHelper.cpp
@@ -193,7 +193,8 @@ void GrSWMaskHelper::DrawToTargetWithPathMask(GrTexture* texture,
}
enum {
// the SW path renderer shares this stage with glyph
- // rendering (kGlyphMaskStage in GrBatchedTextContext)
+ // rendering (kGlyphMaskStage in GrTextContext)
+ // && edge rendering (kEdgeEffectStage in GrContext)
kPathMaskStage = GrPaint::kTotalStages,
};
GrAssert(!drawState->isStageEnabled(kPathMaskStage));
diff --git a/src/gpu/GrTextContext.cpp b/src/gpu/GrTextContext.cpp
index db5abb40b3..a8defcb4ba 100644
--- a/src/gpu/GrTextContext.cpp
+++ b/src/gpu/GrTextContext.cpp
@@ -19,6 +19,9 @@
#include "SkStrokeRec.h"
enum {
+ // glyph rendering shares this stage with edge rendering
+ // (kEdgeEffectStage in GrContext) && SW path rendering
+ // (kPathMaskStage in GrSWMaskHelper)
kGlyphMaskStage = GrPaint::kTotalStages,
};
diff --git a/src/gpu/effects/GrEllipseEdgeEffect.cpp b/src/gpu/effects/GrEllipseEdgeEffect.cpp
new file mode 100644
index 0000000000..002753e203
--- /dev/null
+++ b/src/gpu/effects/GrEllipseEdgeEffect.cpp
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "GrEllipseEdgeEffect.h"
+#include "gl/GrGLEffect.h"
+#include "gl/GrGLEffectMatrix.h"
+#include "gl/GrGLSL.h"
+#include "gl/GrGLTexture.h"
+#include "GrTBackendEffectFactory.h"
+#include "GrTexture.h"
+
+class GrGLEllipseEdgeEffect : public GrGLEffect {
+public:
+ GrGLEllipseEdgeEffect(const GrBackendEffectFactory& factory, const GrEffectRef&)
+ : INHERITED (factory) {}
+
+ virtual void emitCode(GrGLShaderBuilder* builder,
+ const GrEffectStage& stage,
+ EffectKey key,
+ const char* vertexCoords,
+ const char* outputColor,
+ const char* inputColor,
+ const TextureSamplerArray& samplers) SK_OVERRIDE {
+ const char *vsName, *fsName;
+ builder->addVarying(kVec4f_GrSLType, "EllipseEdge", &vsName, &fsName);
+
+ const SkString* attrName = builder->getEffectAttributeName(stage.getVertexAttribIndices()[0]);
+ builder->vsCodeAppendf("\t%s = %s;\n", vsName, attrName->c_str());
+
+ builder->fsCodeAppend("\tfloat edgeAlpha;\n");
+ // translate to origin
+ builder->fsCodeAppendf("\tvec2 offset = (%s.xy - %s.xy);\n", builder->fragmentPosition(), fsName);
+ // scale y by xRadius/yRadius
+ builder->fsCodeAppendf("\toffset.y *= %s.w;\n", fsName);
+ builder->fsCodeAppend("\tfloat d = length(offset);\n");
+ // compare length against xRadius
+ builder->fsCodeAppendf("\tedgeAlpha = smoothstep(d - 0.5, d + 0.5, %s.z);\n", fsName);
+ SkString modulate;
+ GrGLSLModulate4f(&modulate, inputColor, "edgeAlpha");
+ builder->fsCodeAppendf("\t%s = %s;\n", outputColor, modulate.c_str());
+ }
+
+ static inline EffectKey GenKey(const GrEffectStage& stage, const GrGLCaps&) {
+ return 0;
+ }
+
+ virtual void setData(const GrGLUniformManager& uman, const GrEffectStage& stage) SK_OVERRIDE {
+ }
+
+private:
+ typedef GrGLEffect INHERITED;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+GrEllipseEdgeEffect::GrEllipseEdgeEffect() : GrEffect() {
+ this->addVertexAttrib(kVec4f_GrSLType);
+}
+
+void GrEllipseEdgeEffect::getConstantColorComponents(GrColor* color, uint32_t* validFlags) const {
+ *validFlags = 0;
+}
+
+const GrBackendEffectFactory& GrEllipseEdgeEffect::getFactory() const {
+ return GrTBackendEffectFactory<GrEllipseEdgeEffect>::getInstance();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+GR_DEFINE_EFFECT_TEST(GrEllipseEdgeEffect);
+
+GrEffectRef* GrEllipseEdgeEffect::TestCreate(SkMWCRandom* random,
+ GrContext* context,
+ GrTexture* textures[]) {
+ return GrEllipseEdgeEffect::Create();
+}
diff --git a/src/gpu/effects/GrEllipseEdgeEffect.h b/src/gpu/effects/GrEllipseEdgeEffect.h
new file mode 100644
index 0000000000..8f56d771df
--- /dev/null
+++ b/src/gpu/effects/GrEllipseEdgeEffect.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrEllipseEdgeEffect_DEFINED
+#define GrEllipseEdgeEffect_DEFINED
+
+#include "GrEffect.h"
+
+class GrGLEllipseEdgeEffect;
+
+/**
+ * The output of this effect is a modulation of the input color and coverage for an axis-aligned
+ * ellipse, specified as center_x, center_y, x_radius, x_radius/y_radius in window space (y-down).
+ */
+
+class GrEllipseEdgeEffect : public GrEffect {
+public:
+ static GrEffectRef* Create() {
+ // maybe only have one static copy?
+ AutoEffectUnref effect(SkNEW(GrEllipseEdgeEffect));
+ return CreateEffectRef(effect);
+ }
+
+ virtual ~GrEllipseEdgeEffect() {}
+
+ static const char* Name() { return "EllipseEdge"; }
+
+ virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags) const SK_OVERRIDE;
+
+ typedef GrGLEllipseEdgeEffect GLEffect;
+
+ virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE;
+
+private:
+ GrEllipseEdgeEffect();
+
+ virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE {
+ return true;
+ }
+
+ GR_DECLARE_EFFECT_TEST;
+
+ typedef GrEffect INHERITED;
+};
+
+#endif
diff --git a/src/gpu/gl/GrGLEffect.cpp b/src/gpu/gl/GrGLEffect.cpp
index ccea2698e2..f2cd37c93e 100644
--- a/src/gpu/gl/GrGLEffect.cpp
+++ b/src/gpu/gl/GrGLEffect.cpp
@@ -31,3 +31,18 @@ GrGLEffect::EffectKey GrGLEffect::GenTextureKey(const GrEffectRef* effect,
}
return key;
}
+
+GrGLEffect::EffectKey GrGLEffect::GenAttribKey(const GrEffectStage& stage) {
+ EffectKey key = 0;
+
+ int numAttributes = stage.getVertexAttribIndexCount();
+ GrAssert(numAttributes <= 2);
+ const int* attributeIndices = stage.getVertexAttribIndices();
+ for (int index = 0; index < numAttributes; ++index) {
+ EffectKey value = attributeIndices[index] << 2*index;
+ GrAssert(0 == (value & key)); // keys for each attribute ought not to overlap
+ key |= value;
+ }
+
+ return key;
+}
diff --git a/src/gpu/gl/GrGLEffect.h b/src/gpu/gl/GrGLEffect.h
index 76f865e57c..869fbdad7f 100644
--- a/src/gpu/gl/GrGLEffect.h
+++ b/src/gpu/gl/GrGLEffect.h
@@ -87,6 +87,7 @@ public:
const char* name() const { return fFactory.name(); }
static EffectKey GenTextureKey(const GrEffectRef*, const GrGLCaps&);
+ static EffectKey GenAttribKey(const GrEffectStage& stage);
/**
* GrGLEffect subclasses get passed a GrEffectStage in their emitCode and setData functions.
diff --git a/src/gpu/gl/GrGLProgram.cpp b/src/gpu/gl/GrGLProgram.cpp
index 2b6ccbd0b2..c1643578ad 100644
--- a/src/gpu/gl/GrGLProgram.cpp
+++ b/src/gpu/gl/GrGLProgram.cpp
@@ -419,9 +419,7 @@ bool GrGLProgram::genEdgeCoverage(SkString* coverageVar,
if (fDesc.fAttribBindings & GrDrawState::kEdge_AttribBindingsBit) {
const char *vsName, *fsName;
builder->addVarying(kVec4f_GrSLType, "Edge", &vsName, &fsName);
- builder->fVSAttrs.push_back().set(kVec4f_GrSLType,
- GrGLShaderVar::kAttribute_TypeModifier,
- EDGE_ATTR_NAME);
+ builder->addAttribute(kVec4f_GrSLType, EDGE_ATTR_NAME);
builder->vsCodeAppendf("\t%s = " EDGE_ATTR_NAME ";\n", vsName);
switch (fDesc.fVertexEdgeType) {
case GrDrawState::kHairLine_EdgeType:
@@ -467,13 +465,6 @@ bool GrGLProgram::genEdgeCoverage(SkString* coverageVar,
builder->fsCodeAppendf("\tfloat innerAlpha = %s.w == 0.0 ? 1.0 : smoothstep(%s.w - 0.5, %s.w + 0.5, d);\n", fsName, fsName, fsName);
builder->fsCodeAppend("\tedgeAlpha = outerAlpha * innerAlpha;\n");
break;
- case GrDrawState::kEllipse_EdgeType:
- builder->fsCodeAppend("\tfloat edgeAlpha;\n");
- builder->fsCodeAppendf("\tvec2 offset = (%s.xy - %s.xy);\n", builder->fragmentPosition(), fsName);
- builder->fsCodeAppendf("\toffset.y *= %s.w;\n", fsName);
- builder->fsCodeAppend("\tfloat d = length(offset);\n");
- builder->fsCodeAppendf("\tedgeAlpha = smoothstep(d - 0.5, d + 0.5, %s.z);\n", fsName);
- break;
default:
GrCrash("Unknown Edge Type!");
break;
@@ -492,9 +483,7 @@ bool GrGLProgram::genEdgeCoverage(SkString* coverageVar,
void GrGLProgram::genInputColor(GrGLShaderBuilder* builder, SkString* inColor) {
switch (fDesc.fColorInput) {
case GrGLProgram::Desc::kAttribute_ColorInput: {
- builder->fVSAttrs.push_back().set(kVec4f_GrSLType,
- GrGLShaderVar::kAttribute_TypeModifier,
- COL_ATTR_NAME);
+ builder->addAttribute(kVec4f_GrSLType, COL_ATTR_NAME);
const char *vsName, *fsName;
builder->addVarying(kVec4f_GrSLType, "Color", &vsName, &fsName);
builder->vsCodeAppendf("\t%s = " COL_ATTR_NAME ";\n", vsName);
@@ -534,9 +523,7 @@ void GrGLProgram::genUniformCoverage(GrGLShaderBuilder* builder, SkString* inOut
namespace {
void gen_attribute_coverage(GrGLShaderBuilder* builder,
SkString* inOutCoverage) {
- builder->fVSAttrs.push_back().set(kVec4f_GrSLType,
- GrGLShaderVar::kAttribute_TypeModifier,
- COV_ATTR_NAME);
+ builder->addAttribute(kVec4f_GrSLType, COV_ATTR_NAME);
const char *vsName, *fsName;
builder->addVarying(kVec4f_GrSLType, "Coverage", &vsName, &fsName);
builder->vsCodeAppendf("\t%s = " COV_ATTR_NAME ";\n", vsName);
@@ -777,9 +764,7 @@ bool GrGLProgram::genProgram(const GrEffectStage* stages[]) {
// add texture coordinates that are used to the list of vertex attr decls
if (GrDrawState::AttributesBindExplicitTexCoords(attribBindings)) {
- builder.fVSAttrs.push_back().set(kVec2f_GrSLType,
- GrGLShaderVar::kAttribute_TypeModifier,
- TEX_ATTR_NAME);
+ builder.addAttribute(kVec2f_GrSLType, TEX_ATTR_NAME);
}
///////////////////////////////////////////////////////////////////////////
@@ -917,6 +902,11 @@ bool GrGLProgram::genProgram(const GrEffectStage* stages[]) {
inCoverage = outCoverage;
}
}
+
+ // discard if coverage is zero
+ if (fDesc.fDiscardIfOutsideEdge && !outCoverage.isEmpty()) {
+ builder.fsCodeAppendf("\tif (all(lessThanEqual(%s, vec4(0.0)))) {\n\t\tdiscard;\n\t}\n", outCoverage.c_str());
+ }
}
if (Desc::kNone_DualSrcOutput != fDesc.fDualSrcOutput) {
@@ -1022,6 +1012,13 @@ bool GrGLProgram::bindOutputsAttribsAndLinkProgram(const GrGLShaderBuilder& buil
GL_CALL(BindAttribLocation(fProgramID, fDesc.fTexCoordAttributeIndex, TEX_ATTR_NAME));
}
+ const GrGLShaderBuilder::AttributePair* attribEnd = builder.getEffectAttributes().end();
+ for (const GrGLShaderBuilder::AttributePair* attrib = builder.getEffectAttributes().begin();
+ attrib != attribEnd;
+ ++attrib) {
+ GL_CALL(BindAttribLocation(fProgramID, attrib->fIndex, attrib->fName.c_str()));
+ }
+
GL_CALL(LinkProgram(fProgramID));
GrGLint linked = GR_GL_INIT_ZERO;
diff --git a/src/gpu/gl/GrGLSL.h b/src/gpu/gl/GrGLSL.h
index 4559fddd36..940501cd3e 100644
--- a/src/gpu/gl/GrGLSL.h
+++ b/src/gpu/gl/GrGLSL.h
@@ -9,6 +9,7 @@
#define GrGLSL_DEFINED
#include "gl/GrGLInterface.h"
+#include "GrTypesPriv.h"
class GrGLShaderVar;
class SkString;
@@ -34,22 +35,6 @@ enum GrGLSLGeneration {
k150_GrGLSLGeneration,
};
-/**
- * Types of shader-language-specific boxed variables we can create.
- * (Currently only GrGLShaderVars, but should be applicable to other shader
- * languages.)
- */
-enum GrSLType {
- kVoid_GrSLType,
- kFloat_GrSLType,
- kVec2f_GrSLType,
- kVec3f_GrSLType,
- kVec4f_GrSLType,
- kMat33f_GrSLType,
- kMat44f_GrSLType,
- kSampler2D_GrSLType
-};
-
enum GrSLConstantVec {
kZeros_GrSLConstantVec,
kOnes_GrSLConstantVec,
diff --git a/src/gpu/gl/GrGLShaderBuilder.cpp b/src/gpu/gl/GrGLShaderBuilder.cpp
index 5c3f5b3fe8..1a238ae04b 100644
--- a/src/gpu/gl/GrGLShaderBuilder.cpp
+++ b/src/gpu/gl/GrGLShaderBuilder.cpp
@@ -258,6 +258,22 @@ const GrGLShaderVar& GrGLShaderBuilder::getUniformVariable(UniformHandle u) cons
return fUniforms[handle_to_index(u)].fVariable;
}
+bool GrGLShaderBuilder::addAttribute(GrSLType type,
+ const char* name) {
+ for (int i = 0; i < fVSAttrs.count(); ++i) {
+ const GrGLShaderVar& attr = fVSAttrs[i];
+ // if attribute already added, don't add it again
+ if (attr.getName().equals(name)) {
+ GrAssert(attr.getType() == type);
+ return false;
+ }
+ }
+ fVSAttrs.push_back().set(type,
+ GrGLShaderVar::kAttribute_TypeModifier,
+ name);
+ return true;
+}
+
void GrGLShaderBuilder::addVarying(GrSLType type,
const char* name,
const char** vsOutName,
@@ -491,6 +507,18 @@ GrGLEffect* GrGLShaderBuilder::createAndEmitGLEffect(
samplerHandles->push_back(textureSamplers[i].fSamplerUniform);
}
+ int numAttributes = stage.getVertexAttribIndexCount();
+ const int* attributeIndices = stage.getVertexAttribIndices();
+ SkSTArray<GrEffect::kMaxVertexAttribs, SkString> attributeNames;
+ for (int i = 0; i < numAttributes; ++i) {
+ SkString attributeName("aAttr");
+ attributeName.appendS32(attributeIndices[i]);
+
+ if (this->addAttribute(effect->vertexAttribType(i), attributeName.c_str())) {
+ fEffectAttributes.push_back().set(attributeIndices[i], attributeName);
+ }
+ }
+
GrGLEffect* glEffect = effect->getFactory().createGLInstance(effect);
// Enclose custom code in a block to avoid namespace conflicts
@@ -508,3 +536,16 @@ GrGLEffect* GrGLShaderBuilder::createAndEmitGLEffect(
return glEffect;
}
+
+const SkString* GrGLShaderBuilder::getEffectAttributeName(int attributeIndex) const {
+ const AttributePair* attribEnd = this->getEffectAttributes().end();
+ for (const AttributePair* attrib = this->getEffectAttributes().begin();
+ attrib != attribEnd;
+ ++attrib) {
+ if (attrib->fIndex == attributeIndex) {
+ return &attrib->fName;
+ }
+ }
+
+ return NULL;
+}
diff --git a/src/gpu/gl/GrGLShaderBuilder.h b/src/gpu/gl/GrGLShaderBuilder.h
index 08b3ef5ef5..524a8853ca 100644
--- a/src/gpu/gl/GrGLShaderBuilder.h
+++ b/src/gpu/gl/GrGLShaderBuilder.h
@@ -184,7 +184,11 @@ public:
return this->getUniformVariable(u).c_str();
}
- /** Add a varying variable to the current program to pass values between vertex and fragment
+ /** Add a vertex attribute to the current program that is passed in from the vertex data.
+ Returns false if the attribute was already there, true otherwise. */
+ bool addAttribute(GrSLType type, const char* name);
+
+ /** Add a varying variable to the current program to pass values between vertex and fragment
shaders. If the last two parameters are non-NULL, they are filled in with the name
generated. */
void addVarying(GrSLType type,
@@ -222,6 +226,19 @@ public:
const char* vsInCoord,
SkTArray<GrGLUniformManager::UniformHandle, true>* samplerHandles);
GrGLUniformManager::UniformHandle getRTHeightUniform() const { return fRTHeightUniform; }
+
+ struct AttributePair {
+ void set(int index, const SkString& name) {
+ fIndex = index; fName = name;
+ }
+ int fIndex;
+ SkString fName;
+ };
+ const SkSTArray<10, AttributePair, true>& getEffectAttributes() const {
+ return fEffectAttributes;
+ }
+ const SkString* getEffectAttributeName(int attributeIndex) const;
+
// TODO: Make this do all the compiling, linking, etc.
void finished(GrGLuint programID);
@@ -270,6 +287,8 @@ private:
bool fSetupFragPosition;
GrGLUniformManager::UniformHandle fRTHeightUniform;
+ SkSTArray<10, AttributePair, true> fEffectAttributes;
+
GrGLShaderVar* fPositionVar;
};
diff --git a/tests/GLProgramsTest.cpp b/tests/GLProgramsTest.cpp
index 45c5f2d162..b56c788513 100644
--- a/tests/GLProgramsTest.cpp
+++ b/tests/GLProgramsTest.cpp
@@ -121,6 +121,8 @@ bool GrGpuGL::programUnitTest(int maxStages) {
GrGLProgram::Desc pdesc;
GrEffectStage stages[GrDrawState::kNumStages];
+ int currAttribIndex = GrDrawState::kAttribIndexCount;
+ int attribIndices[2];
for (int s = 0; s < maxStages; ++s) {
// enable the stage?
if (random.nextBool()) {
@@ -129,7 +131,10 @@ bool GrGpuGL::programUnitTest(int maxStages) {
&random,
this->getContext(),
dummyTextures));
- stages[s].setEffect(effect.get());
+ for (int i = 0; i < effect.get()->get()->numVertexAttribs(); ++i) {
+ attribIndices[i] = currAttribIndex++;
+ }
+ stages[s].setEffect(effect.get(), attribIndices);
}
}
pdesc.setRandom(&random, this, stages);