aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--expectations/gm/ignored-tests.txt3
-rw-r--r--gyp/gpu.gypi1
-rw-r--r--include/core/SkTemplates.h1
-rw-r--r--include/gpu/GrXferProcessor.h9
-rw-r--r--include/gpu/effects/GrPorterDuffXferProcessor.h10
-rw-r--r--src/gpu/GrAAConvexPathRenderer.cpp55
-rw-r--r--src/gpu/GrDefaultGeoProcFactory.cpp102
-rw-r--r--src/gpu/GrGeometryProcessor.cpp170
-rw-r--r--src/gpu/GrGeometryProcessor.h246
-rw-r--r--src/gpu/GrInOrderDrawBuffer.cpp2
-rw-r--r--src/gpu/GrInOrderDrawBuffer.h2
-rw-r--r--src/gpu/GrOptDrawState.cpp71
-rw-r--r--src/gpu/GrOptDrawState.h35
-rw-r--r--src/gpu/GrOvalRenderer.cpp145
-rw-r--r--src/gpu/GrProcOptInfo.cpp2
-rw-r--r--src/gpu/GrProcOptInfo.h8
-rw-r--r--src/gpu/GrProcessor.cpp29
-rw-r--r--src/gpu/GrProgramDesc.h35
-rw-r--r--src/gpu/effects/GrBezierEffect.cpp185
-rw-r--r--src/gpu/effects/GrBezierEffect.h11
-rw-r--r--src/gpu/effects/GrBitmapTextGeoProc.cpp62
-rw-r--r--src/gpu/effects/GrBitmapTextGeoProc.h3
-rw-r--r--src/gpu/effects/GrDashingEffect.cpp113
-rwxr-xr-xsrc/gpu/effects/GrDistanceFieldTextureEffect.cpp167
-rw-r--r--src/gpu/effects/GrDistanceFieldTextureEffect.h12
-rw-r--r--src/gpu/effects/GrPorterDuffXferProcessor.cpp61
-rw-r--r--src/gpu/gl/GrGLGeometryProcessor.h21
-rw-r--r--src/gpu/gl/GrGLProgram.cpp71
-rw-r--r--src/gpu/gl/GrGLProgram.h11
-rw-r--r--src/gpu/gl/GrGLProgramDesc.cpp65
-rw-r--r--src/gpu/gl/builders/GrGLLegacyNvprProgramBuilder.cpp2
-rw-r--r--src/gpu/gl/builders/GrGLNvprProgramBuilder.cpp1
-rw-r--r--src/gpu/gl/builders/GrGLProgramBuilder.cpp84
-rw-r--r--src/gpu/gl/builders/GrGLProgramBuilder.h9
34 files changed, 1231 insertions, 573 deletions
diff --git a/expectations/gm/ignored-tests.txt b/expectations/gm/ignored-tests.txt
index a8b19b7191..4974dafa0b 100644
--- a/expectations/gm/ignored-tests.txt
+++ b/expectations/gm/ignored-tests.txt
@@ -60,6 +60,9 @@ drawbitmapmatrix
#junov skbug.com/3176
pictureimagefilter
+#joshualitt
+hairlines
+
#scroggo skbug.com/3241
# replacing SkLCGRandom with SkRandom
beziers
diff --git a/gyp/gpu.gypi b/gyp/gpu.gypi
index 1570ab4cc5..d39054ed5c 100644
--- a/gyp/gpu.gypi
+++ b/gyp/gpu.gypi
@@ -87,6 +87,7 @@
'<(skia_src_path)/gpu/GrGeometryBuffer.h',
'<(skia_src_path)/gpu/GrGeometryData.h',
'<(skia_src_path)/gpu/GrGeometryProcessor.h',
+ '<(skia_src_path)/gpu/GrGeometryProcessor.cpp',
'<(skia_src_path)/gpu/GrGlyph.h',
'<(skia_src_path)/gpu/GrGpu.cpp',
'<(skia_src_path)/gpu/GrGpu.h',
diff --git a/include/core/SkTemplates.h b/include/core/SkTemplates.h
index 5ef28ea4e5..3571af6706 100644
--- a/include/core/SkTemplates.h
+++ b/include/core/SkTemplates.h
@@ -464,6 +464,7 @@ private:
template <size_t N> class SkAlignedSStorage : SkNoncopyable {
public:
void* get() { return fData; }
+ const void* get() const { return fData; }
private:
union {
void* fPtr;
diff --git a/include/gpu/GrXferProcessor.h b/include/gpu/GrXferProcessor.h
index 40629ea08c..bab6141f44 100644
--- a/include/gpu/GrXferProcessor.h
+++ b/include/gpu/GrXferProcessor.h
@@ -58,13 +58,13 @@ public:
*/
kSkipDraw_OptFlag = 0x1,
/**
- * Clear color stages, remove color vertex attribs, and use input color
+ * GrXferProcessor will ignore color, thus no need to provide
*/
- kClearColorStages_OptFlag = 0x2,
+ kIgnoreColor_OptFlag = 0x2,
/**
- * Clear coverage stages, remove coverage vertex attribs, and use input coverage
+ * GrXferProcessor will ignore coverage, thus no need to provide
*/
- kClearCoverageStages_OptFlag = 0x4,
+ kIgnoreCoverage_OptFlag = 0x4,
/**
* Clear color stages and override input color to that returned by getOptimizations
*/
@@ -94,7 +94,6 @@ public:
bool colorWriteDisabled,
bool doesStencilWrite,
GrColor* overrideColor,
- uint8_t* overrideCoverage,
const GrDrawTargetCaps& caps) = 0;
struct BlendInfo {
diff --git a/include/gpu/effects/GrPorterDuffXferProcessor.h b/include/gpu/effects/GrPorterDuffXferProcessor.h
index 6c860b971c..a348a0255b 100644
--- a/include/gpu/effects/GrPorterDuffXferProcessor.h
+++ b/include/gpu/effects/GrPorterDuffXferProcessor.h
@@ -37,6 +37,9 @@ public:
////
enum PrimaryOutputType {
+ kNone_PrimaryOutputType,
+ kColor_PrimaryOutputType,
+ kCoverage_PrimaryOutputType,
// Modulate color and coverage, write result as the color output.
kModulate_PrimaryOutputType,
// Combines the coverage, dst, and color as coverage * color + (1 - coverage) * dst. This
@@ -68,8 +71,7 @@ public:
bool isCoverageDrawing,
bool colorWriteDisabled,
bool doesStencilWrite,
- GrColor* color,
- uint8_t* coverage,
+ GrColor* overrideColor,
const GrDrawTargetCaps& caps) SK_OVERRIDE;
void getBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const SK_OVERRIDE {
@@ -99,9 +101,7 @@ private:
const GrProcOptInfo& coveragePOI,
bool isCoverageDrawing,
bool colorWriteDisabled,
- bool doesStencilWrite,
- GrColor* color,
- uint8_t* coverage);
+ bool doesStencilWrite);
void calcOutputTypes(GrXferProcessor::OptFlags blendOpts, const GrDrawTargetCaps& caps,
bool hasSolidCoverage, bool readDst);
diff --git a/src/gpu/GrAAConvexPathRenderer.cpp b/src/gpu/GrAAConvexPathRenderer.cpp
index 0007e33b7f..93e2b3763c 100644
--- a/src/gpu/GrAAConvexPathRenderer.cpp
+++ b/src/gpu/GrAAConvexPathRenderer.cpp
@@ -519,16 +519,24 @@ public:
class GLProcessor : public GrGLGeometryProcessor {
public:
GLProcessor(const GrGeometryProcessor&,
- const GrBatchTracker&) {}
+ const GrBatchTracker&)
+ : fColor(GrColor_ILLEGAL) {}
virtual void emitCode(const EmitArgs& args) SK_OVERRIDE {
const QuadEdgeEffect& qe = args.fGP.cast<QuadEdgeEffect>();
- GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder();
+ GrGLGPBuilder* pb = args.fPB;
+ GrGLVertexBuilder* vsBuilder = pb->getVertexShaderBuilder();
GrGLVertToFrag v(kVec4f_GrSLType);
args.fPB->addVarying("QuadEdge", &v);
vsBuilder->codeAppendf("%s = %s;", v.vsOut(), qe.inQuadEdge()->fName);
+ const BatchTracker& local = args.fBT.cast<BatchTracker>();
+
+ // Setup pass through color
+ this->setupColorPassThrough(pb, local.fInputColorType, args.fOutputColor, NULL,
+ &fColorUniform);
+
// setup coord outputs
vsBuilder->codeAppendf("%s = %s;", vsBuilder->positionCoords(), qe.inPosition()->fName);
vsBuilder->codeAppendf("%s = %s;", vsBuilder->localCoords(), qe.inPosition()->fName);
@@ -562,16 +570,30 @@ public:
fsBuilder->codeAppendf("%s = vec4(edgeAlpha);", args.fOutputCoverage);
}
- static inline void GenKey(const GrGeometryProcessor&,
- const GrBatchTracker&,
+ static inline void GenKey(const GrGeometryProcessor& gp,
+ const GrBatchTracker& bt,
const GrGLCaps&,
- GrProcessorKeyBuilder*) {}
+ GrProcessorKeyBuilder* b) {
+ const BatchTracker& local = bt.cast<BatchTracker>();
+ b->add32(local.fInputColorType);
+ }
- virtual void setData(const GrGLProgramDataManager&,
- const GrGeometryProcessor&,
- const GrBatchTracker&) SK_OVERRIDE {}
+ virtual void setData(const GrGLProgramDataManager& pdman,
+ const GrPrimitiveProcessor& gp,
+ const GrBatchTracker& bt) SK_OVERRIDE {
+ const BatchTracker& local = bt.cast<BatchTracker>();
+ if (kUniform_GrGPInput == local.fInputColorType && local.fColor != fColor) {
+ GrGLfloat c[4];
+ GrColorToRGBAFloat(local.fColor, c);
+ pdman.set4fv(fColorUniform, 1, c);
+ fColor = local.fColor;
+ }
+ }
private:
+ GrColor fColor;
+ UniformHandle fColorUniform;
+
typedef GrGLGeometryProcessor INHERITED;
};
@@ -585,6 +607,18 @@ public:
return SkNEW_ARGS(GLProcessor, (*this, bt));
}
+ void initBatchTracker(GrBatchTracker* bt, const InitBT& init) const SK_OVERRIDE {
+ BatchTracker* local = bt->cast<BatchTracker>();
+ local->fInputColorType = GetColorInputType(&local->fColor, this->color(), init, false);
+ }
+
+ bool onCanMakeEqual(const GrBatchTracker& m, const GrBatchTracker& t) const SK_OVERRIDE {
+ const BatchTracker& mine = m.cast<BatchTracker>();
+ const BatchTracker& theirs = t.cast<BatchTracker>();
+ return CanCombineOutput(mine.fInputColorType, mine.fColor,
+ theirs.fInputColorType, theirs.fColor);
+ }
+
private:
QuadEdgeEffect(GrColor color) : INHERITED(color) {
this->initClassID<QuadEdgeEffect>();
@@ -600,6 +634,11 @@ private:
out->setUnknownSingleComponent();
}
+ struct BatchTracker {
+ GrGPInput fInputColorType;
+ GrColor fColor;
+ };
+
const GrAttribute* fInPosition;
const GrAttribute* fInQuadEdge;
diff --git a/src/gpu/GrDefaultGeoProcFactory.cpp b/src/gpu/GrDefaultGeoProcFactory.cpp
index cb73959e77..f7b85ee469 100644
--- a/src/gpu/GrDefaultGeoProcFactory.cpp
+++ b/src/gpu/GrDefaultGeoProcFactory.cpp
@@ -32,22 +32,54 @@ public:
const GrAttribute* inColor() const { return fInColor; }
const GrAttribute* inLocalCoords() const { return fInLocalCoords; }
const GrAttribute* inCoverage() const { return fInCoverage; }
+ uint8_t coverage() const { return fCoverage; }
+
+ void initBatchTracker(GrBatchTracker* bt, const InitBT& init) const SK_OVERRIDE {
+ BatchTracker* local = bt->cast<BatchTracker>();
+ local->fInputColorType = GetColorInputType(&local->fColor, this->color(), init,
+ SkToBool(fInColor));
+
+ bool hasVertexCoverage = SkToBool(fInCoverage) && !init.fCoverageIgnored;
+ bool covIsSolidWhite = !hasVertexCoverage && 0xff == this->coverage();
+ if (covIsSolidWhite) {
+ local->fInputCoverageType = kAllOnes_GrGPInput;
+ } else if (!hasVertexCoverage) {
+ local->fInputCoverageType = kUniform_GrGPInput;
+ local->fCoverage = this->coverage();
+ } else if (hasVertexCoverage) {
+ SkASSERT(fInCoverage);
+ local->fInputCoverageType = kAttribute_GrGPInput;
+ } else {
+ local->fInputCoverageType = kIgnored_GrGPInput;
+ }
+ }
+
+ bool onCanMakeEqual(const GrBatchTracker& m, const GrBatchTracker& t) const SK_OVERRIDE {
+ const BatchTracker& mine = m.cast<BatchTracker>();
+ const BatchTracker& theirs = t.cast<BatchTracker>();
+ return CanCombineOutput(mine.fInputColorType, mine.fColor,
+ theirs.fInputColorType, theirs.fColor) &&
+ CanCombineOutput(mine.fInputCoverageType, mine.fCoverage,
+ theirs.fInputCoverageType, theirs.fCoverage);
+ }
class GLProcessor : public GrGLGeometryProcessor {
public:
- GLProcessor(const GrGeometryProcessor&,
- const GrBatchTracker&) {}
+ GLProcessor(const GrGeometryProcessor& gp, const GrBatchTracker&)
+ : fColor(GrColor_ILLEGAL), fCoverage(0xff) {}
virtual void emitCode(const EmitArgs& args) SK_OVERRIDE {
const DefaultGeoProc& gp = args.fGP.cast<DefaultGeoProc>();
- GrGLVertexBuilder* vs = args.fPB->getVertexShaderBuilder();
+ GrGLGPBuilder* pb = args.fPB;
+ GrGLVertexBuilder* vs = pb->getVertexShaderBuilder();
+ GrGLGPFragmentBuilder* fs = args.fPB->getFragmentShaderBuilder();
+ const BatchTracker& local = args.fBT.cast<BatchTracker>();
vs->codeAppendf("%s = %s;", vs->positionCoords(), gp.inPosition()->fName);
// Setup pass through color
- if (gp.inColor()) {
- args.fPB->addPassThroughAttribute(gp.inColor(), args.fOutputColor);
- }
+ this->setupColorPassThrough(pb, local.fInputColorType, args.fOutputColor, gp.inColor(),
+ &fColorUniform);
// Setup local coords if needed
if (gp.inLocalCoords()) {
@@ -61,27 +93,57 @@ public:
gp.inPosition()->fName);
// Setup coverage as pass through
- GrGLGPFragmentBuilder* fs = args.fPB->getFragmentShaderBuilder();
- fs->codeAppendf("float alpha = 1.0;");
- if (gp.inCoverage()) {
+ if (kUniform_GrGPInput == local.fInputCoverageType) {
+ const char* fragCoverage;
+ fCoverageUniform = pb->addUniform(GrGLProgramBuilder::kFragment_Visibility,
+ kFloat_GrSLType,
+ kDefault_GrSLPrecision,
+ "Coverage",
+ &fragCoverage);
+ fs->codeAppendf("%s = vec4(%s);", args.fOutputCoverage, fragCoverage);
+ } else if (kAttribute_GrGPInput == local.fInputCoverageType) {
+ SkASSERT(gp.inCoverage());
+ fs->codeAppendf("float alpha = 1.0;");
args.fPB->addPassThroughAttribute(gp.inCoverage(), "alpha");
+ fs->codeAppendf("%s = vec4(alpha);", args.fOutputCoverage);
+ } else if (kAllOnes_GrGPInput == local.fInputCoverageType) {
+ fs->codeAppendf("%s = vec4(1);", args.fOutputCoverage);
}
- fs->codeAppendf("%s = vec4(alpha);", args.fOutputCoverage);
}
static inline void GenKey(const GrGeometryProcessor& gp,
- const GrBatchTracker&,
+ const GrBatchTracker& bt,
const GrGLCaps&,
GrProcessorKeyBuilder* b) {
const DefaultGeoProc& def = gp.cast<DefaultGeoProc>();
b->add32(def.fFlags);
+
+ const BatchTracker& local = bt.cast<BatchTracker>();
+ b->add32(local.fInputColorType | local.fInputCoverageType << 16);
}
- virtual void setData(const GrGLProgramDataManager&,
- const GrGeometryProcessor&,
- const GrBatchTracker&) SK_OVERRIDE {}
+ virtual void setData(const GrGLProgramDataManager& pdman,
+ const GrPrimitiveProcessor& gp,
+ const GrBatchTracker& bt) SK_OVERRIDE {
+ const BatchTracker& local = bt.cast<BatchTracker>();
+ if (kUniform_GrGPInput == local.fInputColorType && local.fColor != fColor) {
+ GrGLfloat c[4];
+ GrColorToRGBAFloat(local.fColor, c);
+ pdman.set4fv(fColorUniform, 1, c);
+ fColor = local.fColor;
+ }
+ if (kUniform_GrGPInput == local.fInputCoverageType && local.fCoverage != fCoverage) {
+ pdman.set1f(fCoverageUniform, GrNormalizeByteToFloat(local.fCoverage));
+ fCoverage = local.fCoverage;
+ }
+ }
private:
+ GrColor fColor;
+ uint8_t fCoverage;
+ UniformHandle fColorUniform;
+ UniformHandle fCoverageUniform;
+
typedef GrGLGeometryProcessor INHERITED;
};
@@ -97,11 +159,12 @@ public:
private:
DefaultGeoProc(GrColor color, uint8_t coverage, uint32_t gpTypeFlags, bool opaqueVertexColors)
- : INHERITED(color, opaqueVertexColors, coverage)
+ : INHERITED(color, opaqueVertexColors)
, fInPosition(NULL)
, fInColor(NULL)
, fInLocalCoords(NULL)
, fInCoverage(NULL)
+ , fCoverage(coverage)
, fFlags(gpTypeFlags) {
this->initClassID<DefaultGeoProc>();
bool hasColor = SkToBool(gpTypeFlags & GrDefaultGeoProcFactory::kColor_GPType);
@@ -120,7 +183,6 @@ private:
if (hasCoverage) {
fInCoverage = &this->addVertexAttrib(GrAttribute("inCoverage",
kFloat_GrVertexAttribType));
- this->setHasVertexCoverage();
}
}
@@ -138,10 +200,18 @@ private:
}
}
+ struct BatchTracker {
+ GrGPInput fInputColorType;
+ GrGPInput fInputCoverageType;
+ GrColor fColor;
+ GrColor fCoverage;
+ };
+
const GrAttribute* fInPosition;
const GrAttribute* fInColor;
const GrAttribute* fInLocalCoords;
const GrAttribute* fInCoverage;
+ uint8_t fCoverage;
uint32_t fFlags;
GR_DECLARE_GEOMETRY_PROCESSOR_TEST;
diff --git a/src/gpu/GrGeometryProcessor.cpp b/src/gpu/GrGeometryProcessor.cpp
new file mode 100644
index 0000000000..5d9cdaff8f
--- /dev/null
+++ b/src/gpu/GrGeometryProcessor.cpp
@@ -0,0 +1,170 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "GrGeometryProcessor.h"
+
+#include "gl/GrGLGeometryProcessor.h"
+#include "GrInvariantOutput.h"
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+void GrGeometryProcessor::getInvariantOutputColor(GrInitInvariantOutput* out) const {
+ if (fHasVertexColor) {
+ if (fOpaqueVertexColors) {
+ out->setUnknownOpaqueFourComponents();
+ } else {
+ out->setUnknownFourComponents();
+ }
+ } else {
+ out->setKnownFourComponents(fColor);
+ }
+ this->onGetInvariantOutputColor(out);
+}
+
+void GrGeometryProcessor::getInvariantOutputCoverage(GrInitInvariantOutput* out) const {
+ this->onGetInvariantOutputCoverage(out);
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+#include "gl/builders/GrGLProgramBuilder.h"
+
+void GrGLGeometryProcessor::setupColorPassThrough(GrGLGPBuilder* pb,
+ GrGPInput inputType,
+ const char* outputName,
+ const GrGeometryProcessor::GrAttribute* colorAttr,
+ UniformHandle* colorUniform) {
+ GrGLGPFragmentBuilder* fs = pb->getFragmentShaderBuilder();
+ if (kUniform_GrGPInput == inputType) {
+ SkASSERT(colorUniform);
+ const char* stagedLocalVarName;
+ *colorUniform = pb->addUniform(GrGLProgramBuilder::kFragment_Visibility,
+ kVec4f_GrSLType,
+ kDefault_GrSLPrecision,
+ "Color",
+ &stagedLocalVarName);
+ fs->codeAppendf("%s = %s;", outputName, stagedLocalVarName);
+ } else if (kAttribute_GrGPInput == inputType) {
+ SkASSERT(colorAttr);
+ pb->addPassThroughAttribute(colorAttr, outputName);
+ } else if (kAllOnes_GrGPInput == inputType) {
+ fs->codeAppendf("%s = vec4(1);", outputName);
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+struct PathBatchTracker {
+ GrGPInput fInputColorType;
+ GrGPInput fInputCoverageType;
+ GrColor fColor;
+};
+
+class GrGLPathProcessor : public GrGLGeometryProcessor {
+public:
+ GrGLPathProcessor(const GrPathProcessor&, const GrBatchTracker&)
+ : fColor(GrColor_ILLEGAL) {}
+
+ void emitCode(const EmitArgs& args) SK_OVERRIDE {
+ GrGLGPBuilder* pb = args.fPB;
+ GrGLGPFragmentBuilder* fs = args.fPB->getFragmentShaderBuilder();
+ const PathBatchTracker& local = args.fBT.cast<PathBatchTracker>();
+
+ // Setup uniform color
+ if (kUniform_GrGPInput == local.fInputColorType) {
+ const char* stagedLocalVarName;
+ fColorUniform = pb->addUniform(GrGLProgramBuilder::kFragment_Visibility,
+ kVec4f_GrSLType,
+ kDefault_GrSLPrecision,
+ "Color",
+ &stagedLocalVarName);
+ fs->codeAppendf("%s = %s;", args.fOutputColor, stagedLocalVarName);
+ }
+
+ // setup constant solid coverage
+ if (kAllOnes_GrGPInput == local.fInputCoverageType) {
+ fs->codeAppendf("%s = vec4(1);", args.fOutputCoverage);
+ }
+ }
+
+ static inline void GenKey(const GrPathProcessor&,
+ const GrBatchTracker& bt,
+ const GrGLCaps&,
+ GrProcessorKeyBuilder* b) {
+ const PathBatchTracker& local = bt.cast<PathBatchTracker>();
+ b->add32(local.fInputColorType | local.fInputCoverageType << 16);
+ }
+
+ void setData(const GrGLProgramDataManager& pdman,
+ const GrPrimitiveProcessor& primProc,
+ const GrBatchTracker& bt) SK_OVERRIDE {
+ const PathBatchTracker& local = bt.cast<PathBatchTracker>();
+ if (kUniform_GrGPInput == local.fInputColorType && local.fColor != fColor) {
+ GrGLfloat c[4];
+ GrColorToRGBAFloat(local.fColor, c);
+ pdman.set4fv(fColorUniform, 1, c);
+ fColor = local.fColor;
+ }
+ }
+
+private:
+ UniformHandle fColorUniform;
+ GrColor fColor;
+
+ typedef GrGLGeometryProcessor INHERITED;
+};
+
+GrPathProcessor::GrPathProcessor(GrColor color) : fColor(color) {
+ this->initClassID<GrPathProcessor>();
+}
+
+void GrPathProcessor::getInvariantOutputColor(GrInitInvariantOutput* out) const {
+ out->setKnownFourComponents(fColor);
+}
+
+void GrPathProcessor::getInvariantOutputCoverage(GrInitInvariantOutput* out) const {
+ out->setKnownSingleComponent(0xff);
+}
+
+void GrPathProcessor::initBatchTracker(GrBatchTracker* bt, const InitBT& init) const {
+ PathBatchTracker* local = bt->cast<PathBatchTracker>();
+ if (init.fColorIgnored) {
+ local->fInputColorType = kIgnored_GrGPInput;
+ local->fColor = GrColor_ILLEGAL;
+ } else {
+ local->fInputColorType = kUniform_GrGPInput;
+ local->fColor = GrColor_ILLEGAL == init.fOverrideColor ? this->color() :
+ init.fOverrideColor;
+ }
+
+ local->fInputCoverageType = init.fCoverageIgnored ? kIgnored_GrGPInput : kAllOnes_GrGPInput;
+}
+
+bool GrPathProcessor::canMakeEqual(const GrBatchTracker& m,
+ const GrPrimitiveProcessor& that,
+ const GrBatchTracker& t) const {
+ if (this->classID() != that.classID() || !this->hasSameTextureAccesses(that)) {
+ return false;
+ }
+
+ const PathBatchTracker& mine = m.cast<PathBatchTracker>();
+ const PathBatchTracker& theirs = t.cast<PathBatchTracker>();
+ return CanCombineOutput(mine.fInputColorType, mine.fColor,
+ theirs.fInputColorType, theirs.fColor) &&
+ CanCombineOutput(mine.fInputCoverageType, 0xff,
+ theirs.fInputCoverageType, 0xff);
+}
+
+void GrPathProcessor::getGLProcessorKey(const GrBatchTracker& bt,
+ const GrGLCaps& caps,
+ GrProcessorKeyBuilder* b) const {
+ GrGLPathProcessor::GenKey(*this, bt, caps, b);
+}
+
+GrGLGeometryProcessor* GrPathProcessor::createGLInstance(const GrBatchTracker& bt) const {
+ return SkNEW_ARGS(GrGLPathProcessor, (*this, bt));
+}
diff --git a/src/gpu/GrGeometryProcessor.h b/src/gpu/GrGeometryProcessor.h
index 7481515577..f3ae800b80 100644
--- a/src/gpu/GrGeometryProcessor.h
+++ b/src/gpu/GrGeometryProcessor.h
@@ -14,6 +14,36 @@
#include "GrShaderVar.h"
/*
+ * The GrPrimitiveProcessor represents some kind of geometric primitive. This includes the shape
+ * of the primitive and the inherent color of the primitive. The GrPrimitiveProcessor is
+ * responsible for providing a color and coverage input into the Ganesh rendering pipeline. Through
+ * optimization, Ganesh may decide a different color, no color, and / or no coverage are required
+ * from the GrPrimitiveProcessor, so the GrPrimitiveProcessor must be able to support this
+ * functionality. We also use the GrPrimitiveProcessor to make batching decisions.
+ *
+ * There are two feedback loops between the GrFragmentProcessors, the GrXferProcessor, and the
+ * GrPrimitiveProcessor. These loops run on the CPU and compute any invariant components which
+ * might be useful for correctness / optimization decisions. The GrPrimitiveProcessor seeds these
+ * loops, one with initial color and one with initial coverage, in its
+ * onComputeInvariantColor / Coverage calls. These seed values are processed by the subsequent
+ * stages of the rendering pipeline and the output is then fed back into the GrPrimitiveProcessor in
+ * the initBatchTracker call, where the GrPrimitiveProcessor can then initialize the GrBatchTracker
+ * struct with the appropriate values.
+ *
+ * We are evolving this system to move towards generating geometric meshes and their associated
+ * vertex data after we have batched and reordered draws. This system, known as 'deferred geometry'
+ * will allow the GrPrimitiveProcessor much greater control over how data is transmitted to shaders.
+ *
+ * In a deferred geometry world, the GrPrimitiveProcessor can always 'batch' To do this, each
+ * primitive type is associated with one GrPrimitiveProcessor, who has complete control of how
+ * it draws. Each primitive draw will bundle all required data to perform the draw, and these
+ * bundles of data will be owned by an instance of the associated GrPrimitiveProcessor. Bundles
+ * can be updated alongside the GrBatchTracker struct itself, ultimately allowing the
+ * GrPrimitiveProcessor complete control of how it gets data into the fragment shader as long as
+ * it emits the appropriate color, or none at all, as directed.
+ */
+
+/*
* A struct for tracking batching decisions. While this lives on GrOptState, it is managed
* entirely by the derived classes of the GP.
*/
@@ -21,18 +51,18 @@ class GrBatchTracker {
public:
template <typename T> const T& cast() const {
SkASSERT(sizeof(T) <= kMaxSize);
- return *reinterpret_cast<const T*>(fData);
+ return *reinterpret_cast<const T*>(fData.get());
}
template <typename T> T* cast() {
SkASSERT(sizeof(T) <= kMaxSize);
- return reinterpret_cast<T*>(fData);
+ return reinterpret_cast<T*>(fData.get());
}
static const size_t kMaxSize = 32;
private:
- uint8_t fData[kMaxSize];
+ SkAlignedSStorage<kMaxSize> fData;
};
class GrGLCaps;
@@ -41,58 +71,105 @@ class GrOptDrawState;
struct GrInitInvariantOutput;
+
+/*
+ * This enum is shared by GrPrimitiveProcessors and GrGLPrimitiveProcessors to coordinate shaders
+ * with vertex attributes / uniforms.
+ */
+enum GrGPInput {
+ kAllOnes_GrGPInput,
+ kAttribute_GrGPInput,
+ kUniform_GrGPInput,
+ kIgnored_GrGPInput,
+};
+
/*
- * GrGeometryProcessors and GrPathProcessors may effect invariantColor
+ * GrPrimitiveProcessor defines an interface which all subclasses must implement. All
+ * GrPrimitiveProcessors must proivide seed color and coverage for the Ganesh color / coverage
+ * pipelines, and they must provide some notion of equality
*/
class GrPrimitiveProcessor : public GrProcessor {
public:
- // TODO GPs and PPs have to provide an initial coverage because the coverage invariant code is
- // broken right now
- virtual uint8_t coverage() const = 0;
+ /*
+ * This struct allows the optstate to communicate requirements to the GrPrimitiveProcessor.
+ */
+ struct InitBT {
+ bool fColorIgnored;
+ bool fCoverageIgnored;
+ GrColor fOverrideColor;
+ };
+
+ virtual void initBatchTracker(GrBatchTracker*, const InitBT&) const = 0;
+
+ virtual bool canMakeEqual(const GrBatchTracker& mine,
+ const GrPrimitiveProcessor& that,
+ const GrBatchTracker& theirs) const = 0;
+
+ /*
+ * We always call canMakeEqual before makeEqual so there is no need to do any kind of equality
+ * testing here
+ * TODO make this pure virtual when primProcs can actually use it
+ */
+ virtual void makeEqual(GrBatchTracker*, const GrBatchTracker&) const {}
+
virtual void getInvariantOutputColor(GrInitInvariantOutput* out) const = 0;
virtual void getInvariantOutputCoverage(GrInitInvariantOutput* out) const = 0;
+ /**
+ * Sets a unique key on the GrProcessorKeyBuilder that is directly associated with this geometry
+ * processor's GL backend implementation.
+ */
+ virtual void getGLProcessorKey(const GrBatchTracker& bt,
+ const GrGLCaps& caps,
+ GrProcessorKeyBuilder* b) const = 0;
+
+
+ /** Returns a new instance of the appropriate *GL* implementation class
+ for the given GrProcessor; caller is responsible for deleting
+ the object. */
+ virtual GrGLGeometryProcessor* createGLInstance(const GrBatchTracker& bt) const = 0;
+
+protected:
+ /*
+ * CanCombineOutput will return true if two draws are 'batchable' from a color perspective.
+ * TODO remove this when GPs can upgrade to attribute color
+ */
+ static bool CanCombineOutput(GrGPInput left, GrColor lColor, GrGPInput right, GrColor rColor) {
+ if (left != right) {
+ return false;
+ }
+
+ if (kUniform_GrGPInput == left && lColor != rColor) {
+ return false;
+ }
+
+ return true;
+ }
+
private:
typedef GrProcessor INHERITED;
};
/**
- * A GrGeometryProcessor is used to perform computation in the vertex shader and
- * add support for custom vertex attributes. A GrGemeotryProcessor is typically
- * tied to the code that does a specific type of high-level primitive rendering
- * (e.g. anti-aliased circle rendering). The GrGeometryProcessor used for a draw is
- * specified using GrDrawState. There can only be one geometry processor active for
- * a draw. The custom vertex attributes required by the geometry processor must be
- * added to the vertex attribute array specified on the GrDrawState.
- * GrGeometryProcessor subclasses should be immutable after construction.
+ * A GrGeometryProcessor is a flexible method for rendering a primitive. The GrGeometryProcessor
+ * has complete control over vertex attributes and uniforms(aside from the render target) but it
+ * must obey the same contract as any GrPrimitiveProcessor, specifically it must emit a color and
+ * coverage into the fragment shader. Where this color and coverage come from is completely the
+ * responsibility of the GrGeometryProcessor.
*/
class GrGeometryProcessor : public GrPrimitiveProcessor {
public:
// TODO the Hint can be handled in a much more clean way when we have deferred geometry or
// atleast bundles
- GrGeometryProcessor(GrColor color, bool opaqueVertexColors = false, uint8_t coverage = 0xff)
+ GrGeometryProcessor(GrColor color, bool opaqueVertexColors = false)
: fVertexStride(0)
, fColor(color)
- , fCoverage(coverage)
, fOpaqueVertexColors(opaqueVertexColors)
, fWillUseGeoShader(false)
, fHasVertexColor(false)
- , fHasVertexCoverage(false)
, fHasLocalCoords(false) {}
- /**
- * Sets a unique key on the GrProcessorKeyBuilder that is directly associated with this geometry
- * processor's GL backend implementation.
- */
- virtual void getGLProcessorKey(const GrBatchTracker& bt,
- const GrGLCaps& caps,
- GrProcessorKeyBuilder* b) const = 0;
-
-
- /** Returns a new instance of the appropriate *GL* implementation class
- for the given GrProcessor; caller is responsible for deleting
- the object. */
- virtual GrGLGeometryProcessor* createGLInstance(const GrBatchTracker& bt) const = 0;
+ virtual const char* name() const = 0;
/*
* This is a safeguard to prevent GPs from going beyond platform specific attribute limits.
@@ -121,61 +198,87 @@ public:
bool willUseGeoShader() const { return fWillUseGeoShader; }
- /** Returns true if this and other processor conservatively draw identically. It can only return
- true when the two prcoessors are of the same subclass (i.e. they return the same object from
- from getFactory()).
- A return value of true from isEqual() should not be used to test whether the processors
- would generate the same shader code. To test for identical code generation use the
- processors' keys computed by the GrBackendEffectFactory. */
- bool isEqual(const GrGeometryProcessor& that) const {
+ /*
+ * In an ideal world, two GrGeometryProcessors with the same class id and texture accesses
+ * would ALWAYS be able to batch together. If two GrGeometryProcesosrs are the same then we
+ * will only keep one of them. The remaining GrGeometryProcessor then updates its
+ * GrBatchTracker to incorporate the draw information from the GrGeometryProcessor we discard.
+ * Any bundles associated with the discarded GrGeometryProcessor will be attached to the
+ * remaining GrGeometryProcessor.
+ */
+ bool canMakeEqual(const GrBatchTracker& mine,
+ const GrPrimitiveProcessor& that,
+ const GrBatchTracker& theirs) const SK_OVERRIDE {
if (this->classID() != that.classID() || !this->hasSameTextureAccesses(that)) {
return false;
}
// TODO remove the hint
- if (fHasVertexColor && fOpaqueVertexColors != that.fOpaqueVertexColors) {
+ const GrGeometryProcessor& other = that.cast<GrGeometryProcessor>();
+ if (fHasVertexColor && fOpaqueVertexColors != other.fOpaqueVertexColors) {
return false;
}
- if (!fHasVertexColor && this->color() != that.color()) {
+ // TODO this equality test should really be broken up, some of this can live on the batch
+ // tracker test and some of this should be in bundles
+ if (!this->onIsEqual(other)) {
return false;
}
- // TODO this is fragile, most gps set their coverage to 0xff so this is okay. In the long
- // term this should move to subclasses which set explicit coverage
- if (!fHasVertexCoverage && this->coverage() != that.coverage()) {
- return false;
- }
- return this->onIsEqual(that);
+ return this->onCanMakeEqual(mine, theirs);
}
- struct InitBT {
- bool fOutputColor;
- bool fOutputCoverage;
- GrColor fColor;
- GrColor fCoverage;
- };
-
- virtual void initBatchTracker(GrBatchTracker*, const InitBT&) const {}
-
+
+ // TODO we can remove color from the GrGeometryProcessor base class once we have bundles of
+ // primitive data
GrColor color() const { return fColor; }
- uint8_t coverage() const SK_OVERRIDE { return fCoverage; }
- // TODO this is a total hack until the gp can own whether or not it uses uniform
- // color / coverage
+ // TODO this is a total hack until the gp can do deferred geometry
bool hasVertexColor() const { return fHasVertexColor; }
- bool hasVertexCoverage() const { return fHasVertexCoverage; }
+
+ // TODO this is a total hack until gp can setup and manage local coords
bool hasLocalCoords() const { return fHasLocalCoords; }
void getInvariantOutputColor(GrInitInvariantOutput* out) const SK_OVERRIDE;
void getInvariantOutputCoverage(GrInitInvariantOutput* out) const SK_OVERRIDE;
protected:
+ /*
+ * An optional simple helper function to determine by what means the GrGeometryProcessor should
+ * use to provide color. If we are given an override color(ie the given overridecolor is NOT
+ * GrColor_ILLEGAL) then we must always emit that color(currently overrides are only supported
+ * via uniform, but with deferred Geometry we could use attributes). Otherwise, if our color is
+ * ignored then we should not emit a color. Lastly, if we don't have vertex colors then we must
+ * emit a color via uniform
+ * TODO this function changes quite a bit with deferred geometry. There the GrGeometryProcessor
+ * can upload a new color via attribute if needed.
+ */
+ static GrGPInput GetColorInputType(GrColor* color, GrColor primitiveColor, const InitBT& init,
+ bool hasVertexColor) {
+ if (init.fColorIgnored) {
+ *color = GrColor_ILLEGAL;
+ return kIgnored_GrGPInput;
+ } else if (GrColor_ILLEGAL != init.fOverrideColor) {
+ *color = init.fOverrideColor;
+ return kUniform_GrGPInput;
+ }
+
+ *color = primitiveColor;
+ if (hasVertexColor) {
+ return kAttribute_GrGPInput;
+ } else {
+ return kUniform_GrGPInput;
+ }
+ }
+
/**
* Subclasses call this from their constructor to register vertex attributes. Attributes
* will be padded to the nearest 4 bytes for performance reasons.
* TODO After deferred geometry, we should do all of this inline in GenerateGeometry alongside
- * the struct used to actually populate the attributes
+ * the struct used to actually populate the attributes. This is all extremely fragile, vertex
+ * attributes have to be added in the order they will appear in the struct which maps memory.
+ * The processor key should reflect the vertex attributes, or there lack thereof in the
+ * GrGeometryProcessor.
*/
const GrAttribute& addVertexAttrib(const GrAttribute& attribute) {
fVertexStride += attribute.fOffset;
@@ -186,23 +289,22 @@ protected:
// TODO hack see above
void setHasVertexColor() { fHasVertexColor = true; }
- void setHasVertexCoverage() { fHasVertexCoverage = true; }
void setHasLocalCoords() { fHasLocalCoords = true; }
virtual void onGetInvariantOutputColor(GrInitInvariantOutput*) const {}
virtual void onGetInvariantOutputCoverage(GrInitInvariantOutput*) const = 0;
private:
+ virtual bool onCanMakeEqual(const GrBatchTracker& mine, const GrBatchTracker& theirs) const = 0;
+ // TODO delete this when we have more advanced equality testing via bundles and the BT
virtual bool onIsEqual(const GrGeometryProcessor&) const = 0;
SkSTArray<kMaxVertexAttribs, GrAttribute, true> fAttribs;
size_t fVertexStride;
GrColor fColor;
- uint8_t fCoverage;
bool fOpaqueVertexColors;
bool fWillUseGeoShader;
bool fHasVertexColor;
- bool fHasVertexCoverage;
bool fHasLocalCoords;
typedef GrProcessor INHERITED;
@@ -217,14 +319,28 @@ public:
static GrPathProcessor* Create(GrColor color) {
return SkNEW_ARGS(GrPathProcessor, (color));
}
+
+ void initBatchTracker(GrBatchTracker*, const InitBT&) const SK_OVERRIDE;
+
+ bool canMakeEqual(const GrBatchTracker& mine,
+ const GrPrimitiveProcessor& that,
+ const GrBatchTracker& theirs) const SK_OVERRIDE;
const char* name() const SK_OVERRIDE { return "PathProcessor"; }
- uint8_t coverage() const SK_OVERRIDE { return 0xff; }
+
+ GrColor color() const { return fColor; }
+
void getInvariantOutputColor(GrInitInvariantOutput* out) const SK_OVERRIDE;
void getInvariantOutputCoverage(GrInitInvariantOutput* out) const SK_OVERRIDE;
+ virtual void getGLProcessorKey(const GrBatchTracker& bt,
+ const GrGLCaps& caps,
+ GrProcessorKeyBuilder* b) const SK_OVERRIDE;
+
+ virtual GrGLGeometryProcessor* createGLInstance(const GrBatchTracker& bt) const SK_OVERRIDE;
+
private:
- GrPathProcessor(GrColor color) : fColor(color) {}
+ GrPathProcessor(GrColor color);
GrColor fColor;
typedef GrProcessor INHERITED;
diff --git a/src/gpu/GrInOrderDrawBuffer.cpp b/src/gpu/GrInOrderDrawBuffer.cpp
index 62d6818c2b..83e0926b6d 100644
--- a/src/gpu/GrInOrderDrawBuffer.cpp
+++ b/src/gpu/GrInOrderDrawBuffer.cpp
@@ -502,7 +502,7 @@ bool GrInOrderDrawBuffer::recordStateAndShouldDraw(const GrDrawState& ds,
fCmdBuffer.pop_back();
return false;
}
- if (fPrevState && *fPrevState == ss->fState) {
+ if (fPrevState && fPrevState->combineIfPossible(ss->fState)) {
fCmdBuffer.pop_back();
} else {
fPrevState = &ss->fState;
diff --git a/src/gpu/GrInOrderDrawBuffer.h b/src/gpu/GrInOrderDrawBuffer.h
index 060e42ee7a..e2916dd177 100644
--- a/src/gpu/GrInOrderDrawBuffer.h
+++ b/src/gpu/GrInOrderDrawBuffer.h
@@ -260,7 +260,7 @@ private:
};
CmdBuffer fCmdBuffer;
- const GrOptDrawState* fPrevState;
+ GrOptDrawState* fPrevState;
SkTArray<GrTraceMarkerSet, false> fGpuCmdMarkers;
SkTDArray<char> fPathIndexBuffer;
SkTDArray<float> fPathTransformBuffer;
diff --git a/src/gpu/GrOptDrawState.cpp b/src/gpu/GrOptDrawState.cpp
index 93184b4daa..b5fe8d5b60 100644
--- a/src/gpu/GrOptDrawState.cpp
+++ b/src/gpu/GrOptDrawState.cpp
@@ -32,23 +32,23 @@ GrOptDrawState::GrOptDrawState(const GrDrawState& drawState,
fPrimitiveProcessor.reset(gp);
} else {
SkASSERT(!gp && pathProc && (GrGpu::IsPathRenderingDrawType(drawType) ||
- GrGpu::kStencilPath_DrawType == drawType));
+ GrGpu::kStencilPath_DrawType == drawType));
fPrimitiveProcessor.reset(pathProc);
}
const GrProcOptInfo& colorPOI = drawState.colorProcInfo(fPrimitiveProcessor);
const GrProcOptInfo& coveragePOI = drawState.coverageProcInfo(fPrimitiveProcessor);
-
- fColor = colorPOI.inputColorToEffectiveStage();
- // TODO fix this when coverage stages work correctly
- // fCoverage = coveragePOI.inputColorToEffectiveStage();
- fCoverage = fPrimitiveProcessor->coverage();
// Create XferProcessor from DS's XPFactory
SkAutoTUnref<GrXferProcessor> xferProcessor(
drawState.getXPFactory()->createXferProcessor(colorPOI, coveragePOI));
+ GrColor overrideColor = GrColor_ILLEGAL;
+ if (colorPOI.firstEffectiveStageIndex() != 0) {
+ overrideColor = colorPOI.inputColorToEffectiveStage();
+ }
+
GrXferProcessor::OptFlags optFlags;
if (xferProcessor) {
fXferProcessor.reset(xferProcessor.get());
@@ -58,8 +58,7 @@ GrOptDrawState::GrOptDrawState(const GrDrawState& drawState,
drawState.isCoverageDrawing(),
drawState.isColorWriteDisabled(),
drawState.getStencil().doesWrite(),
- &fColor,
- &fCoverage,
+ &overrideColor,
caps);
}
@@ -98,22 +97,14 @@ GrOptDrawState::GrOptDrawState(const GrDrawState& drawState,
fFlags |= kDither_Flag;
}
- fDescInfo.fHasVertexColor = gp && gp->hasVertexColor();
-
- fDescInfo.fHasVertexCoverage = gp && gp->hasVertexCoverage();
-
+ // TODO move local coords completely into GP
bool hasLocalCoords = gp && gp->hasLocalCoords();
int firstColorStageIdx = colorPOI.firstEffectiveStageIndex();
- fDescInfo.fInputColorIsUsed = colorPOI.inputColorIsUsed();
- if (colorPOI.removeVertexAttrib()) {
- fDescInfo.fHasVertexColor = false;
- }
// TODO: Once we can handle single or four channel input into coverage stages then we can use
// drawState's coverageProcInfo (like color above) to set this initial information.
int firstCoverageStageIdx = 0;
- fDescInfo.fInputCoverageIsUsed = true;
GrXferProcessor::BlendInfo blendInfo;
fXferProcessor->getBlendInfo(&blendInfo);
@@ -138,14 +129,11 @@ GrOptDrawState::GrOptDrawState(const GrDrawState& drawState,
}
// let the GP init the batch tracker
- if (gp) {
- GrGeometryProcessor::InitBT init;
- init.fOutputColor = fDescInfo.fInputColorIsUsed;
- init.fOutputCoverage = fDescInfo.fInputCoverageIsUsed;
- init.fColor = this->getColor();
- init.fCoverage = this->getCoverage();
- fGeometryProcessor->initBatchTracker(&fBatchTracker, init);
- }
+ GrGeometryProcessor::InitBT init;
+ init.fColorIgnored = SkToBool(optFlags & GrXferProcessor::kIgnoreColor_OptFlag);
+ init.fOverrideColor = init.fColorIgnored ? GrColor_ILLEGAL : overrideColor;
+ init.fCoverageIgnored = SkToBool(optFlags & GrXferProcessor::kIgnoreCoverage_OptFlag);
+ fPrimitiveProcessor->initBatchTracker(&fBatchTracker, init);
}
void GrOptDrawState::adjustProgramFromOptimizations(const GrDrawState& ds,
@@ -157,20 +145,16 @@ void GrOptDrawState::adjustProgramFromOptimizations(const GrDrawState& ds,
fDescInfo.fReadsDst = false;
fDescInfo.fReadsFragPosition = false;
- if (flags & GrXferProcessor::kClearColorStages_OptFlag ||
- flags & GrXferProcessor::kOverrideColor_OptFlag) {
- fDescInfo.fInputColorIsUsed = true;
+ if ((flags & GrXferProcessor::kIgnoreColor_OptFlag) ||
+ (flags & GrXferProcessor::kOverrideColor_OptFlag)) {
*firstColorStageIdx = ds.numColorStages();
- fDescInfo.fHasVertexColor = false;
} else {
fDescInfo.fReadsDst = colorPOI.readsDst();
fDescInfo.fReadsFragPosition = colorPOI.readsFragPosition();
}
- if (flags & GrXferProcessor::kClearCoverageStages_OptFlag) {
- fDescInfo.fInputCoverageIsUsed = true;
+ if (flags & GrXferProcessor::kIgnoreCoverage_OptFlag) {
*firstCoverageStageIdx = ds.numCoverageStages();
- fDescInfo.fHasVertexCoverage = false;
} else {
if (coveragePOI.readsDst()) {
fDescInfo.fReadsDst = true;
@@ -188,15 +172,11 @@ void GrOptDrawState::finalize(GrGpu* gpu) {
////////////////////////////////////////////////////////////////////////////////
-bool GrOptDrawState::operator== (const GrOptDrawState& that) const {
+bool GrOptDrawState::combineIfPossible(const GrOptDrawState& that) {
if (fDescInfo != that.fDescInfo) {
return false;
}
- if (!fDescInfo.fHasVertexColor && this->fColor != that.fColor) {
- return false;
- }
-
if (this->getRenderTarget() != that.getRenderTarget() ||
this->fFragmentStages.count() != that.fFragmentStages.count() ||
this->fNumColorStages != that.fNumColorStages ||
@@ -210,17 +190,9 @@ bool GrOptDrawState::operator== (const GrOptDrawState& that) const {
return false;
}
- if (!fDescInfo.fHasVertexCoverage && this->fCoverage != that.fCoverage) {
- return false;
- }
-
- if (this->hasGeometryProcessor()) {
- if (!that.hasGeometryProcessor()) {
- return false;
- } else if (!this->getGeometryProcessor()->isEqual(*that.getGeometryProcessor())) {
- return false;
- }
- } else if (that.hasGeometryProcessor()) {
+ if (!this->getPrimitiveProcessor()->canMakeEqual(fBatchTracker,
+ *that.getPrimitiveProcessor(),
+ that.getBatchTracker())) {
return false;
}
@@ -236,6 +208,9 @@ bool GrOptDrawState::operator== (const GrOptDrawState& that) const {
return false;
}
}
+
+ // Now update the GrPrimitiveProcessor's batch tracker
+ fPrimitiveProcessor->makeEqual(&fBatchTracker, that.getBatchTracker());
return true;
}
diff --git a/src/gpu/GrOptDrawState.h b/src/gpu/GrOptDrawState.h
index 876ff52137..95f7fa9c81 100644
--- a/src/gpu/GrOptDrawState.h
+++ b/src/gpu/GrOptDrawState.h
@@ -35,28 +35,11 @@ public:
const GrDrawTargetCaps&, const ScissorState&,
const GrDeviceCoordTexture* dstCopy, GrGpu::DrawType);
- bool operator== (const GrOptDrawState& that) const;
- bool operator!= (const GrOptDrawState& that) const { return !(*this == that); }
-
- /// @}
-
- ///////////////////////////////////////////////////////////////////////////
- /// @name Color
- ////
-
- GrColor getColor() const { return fColor; }
-
- /// @}
-
- ///////////////////////////////////////////////////////////////////////////
- /// @name Coverage
- ////
-
- uint8_t getCoverage() const { return fCoverage; }
-
- GrColor getCoverageColor() const {
- return GrColorPackRGBA(fCoverage, fCoverage, fCoverage, fCoverage);
- }
+ /*
+ * Returns true if it is possible to combine the two GrOptDrawStates and it will update 'this'
+ * to subsume 'that''s draw.
+ */
+ bool combineIfPossible(const GrOptDrawState& that);
/// @}
@@ -80,13 +63,11 @@ public:
int numColorStages() const { return fNumColorStages; }
int numCoverageStages() const { return fFragmentStages.count() - fNumColorStages; }
int numFragmentStages() const { return fFragmentStages.count(); }
- int numTotalStages() const {
- // the + 1 at the end is for the xferProcessor which will always be present
- return this->numFragmentStages() + (this->hasGeometryProcessor() ? 1 : 0) + 1;
- }
+ // TODO remove the GP specific calls when the PathProc can provide the same interface
bool hasGeometryProcessor() const { return SkToBool(fGeometryProcessor.get()); }
const GrGeometryProcessor* getGeometryProcessor() const { return fGeometryProcessor.get(); }
+ const GrPrimitiveProcessor* getPrimitiveProcessor() const { return fPrimitiveProcessor.get(); }
const GrBatchTracker& getBatchTracker() const { return fBatchTracker; }
const GrXferProcessor* getXferProcessor() const { return fXferProcessor.get(); }
@@ -210,10 +191,8 @@ private:
typedef GrPendingProgramElement<const GrXferProcessor> ProgramXferProcessor;
RenderTarget fRenderTarget;
ScissorState fScissorState;
- GrColor fColor;
SkMatrix fViewMatrix;
GrStencilSettings fStencilSettings;
- uint8_t fCoverage;
GrDrawState::DrawFace fDrawFace;
GrDeviceCoordTexture fDstCopy;
uint32_t fFlags;
diff --git a/src/gpu/GrOvalRenderer.cpp b/src/gpu/GrOvalRenderer.cpp
index e1a29f5e5d..659857a9b2 100644
--- a/src/gpu/GrOvalRenderer.cpp
+++ b/src/gpu/GrOvalRenderer.cpp
@@ -80,16 +80,23 @@ public:
class GLProcessor : public GrGLGeometryProcessor {
public:
GLProcessor(const GrGeometryProcessor&,
- const GrBatchTracker&) {}
+ const GrBatchTracker&)
+ : fColor(GrColor_ILLEGAL) {}
virtual void emitCode(const EmitArgs& args) SK_OVERRIDE {
const CircleEdgeEffect& ce = args.fGP.cast<CircleEdgeEffect>();
+ GrGLGPBuilder* pb = args.fPB;
+ const BatchTracker& local = args.fBT.cast<BatchTracker>();
GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder();
GrGLVertToFrag v(kVec4f_GrSLType);
args.fPB->addVarying("CircleEdge", &v);
vsBuilder->codeAppendf("%s = %s;", v.vsOut(), ce.inCircleEdge()->fName);
+ // Setup pass through color
+ this->setupColorPassThrough(pb, local.fInputColorType, args.fOutputColor, NULL,
+ &fColorUniform);
+
// setup coord outputs
vsBuilder->codeAppendf("%s = %s;", vsBuilder->positionCoords(), ce.inPosition()->fName);
vsBuilder->codeAppendf("%s = %s;", vsBuilder->localCoords(), ce.inPosition()->fName);
@@ -111,18 +118,29 @@ public:
}
static void GenKey(const GrGeometryProcessor& processor,
- const GrBatchTracker&,
+ const GrBatchTracker& bt,
const GrGLCaps&,
GrProcessorKeyBuilder* b) {
+ const BatchTracker& local = bt.cast<BatchTracker>();
const CircleEdgeEffect& circleEffect = processor.cast<CircleEdgeEffect>();
- b->add32(circleEffect.isStroked());
+ b->add32(circleEffect.isStroked() << 16 | local.fInputColorType);
}
- virtual void setData(const GrGLProgramDataManager&,
- const GrGeometryProcessor&,
- const GrBatchTracker&) SK_OVERRIDE {}
+ virtual void setData(const GrGLProgramDataManager& pdman,
+ const GrPrimitiveProcessor& gp,
+ const GrBatchTracker& bt) SK_OVERRIDE {
+ const BatchTracker& local = bt.cast<BatchTracker>();
+ if (kUniform_GrGPInput == local.fInputColorType && local.fColor != fColor) {
+ GrGLfloat c[4];
+ GrColorToRGBAFloat(local.fColor, c);
+ pdman.set4fv(fColorUniform, 1, c);
+ fColor = local.fColor;
+ }
+ }
private:
+ GrColor fColor;
+ UniformHandle fColorUniform;
typedef GrGLGeometryProcessor INHERITED;
};
@@ -136,6 +154,19 @@ public:
return SkNEW_ARGS(GLProcessor, (*this, bt));
}
+ void initBatchTracker(GrBatchTracker* bt, const InitBT& init) const SK_OVERRIDE {
+ BatchTracker* local = bt->cast<BatchTracker>();
+ local->fInputColorType = GetColorInputType(&local->fColor, this->color(), init, false);
+
+ }
+
+ bool onCanMakeEqual(const GrBatchTracker& m, const GrBatchTracker& t) const SK_OVERRIDE {
+ const BatchTracker& mine = m.cast<BatchTracker>();
+ const BatchTracker& theirs = t.cast<BatchTracker>();
+ return CanCombineOutput(mine.fInputColorType, mine.fColor,
+ theirs.fInputColorType, theirs.fColor);
+ }
+
private:
CircleEdgeEffect(GrColor color, bool stroke) : INHERITED(color) {
this->initClassID<CircleEdgeEffect>();
@@ -154,6 +185,11 @@ private:
out->setUnknownSingleComponent();
}
+ struct BatchTracker {
+ GrGPInput fInputColorType;
+ GrColor fColor;
+ };
+
const GrAttribute* fInPosition;
const GrAttribute* fInCircleEdge;
bool fStroke;
@@ -201,11 +237,13 @@ public:
class GLProcessor : public GrGLGeometryProcessor {
public:
GLProcessor(const GrGeometryProcessor&,
- const GrBatchTracker&) {}
+ const GrBatchTracker&)
+ : fColor(GrColor_ILLEGAL) {}
virtual void emitCode(const EmitArgs& args) SK_OVERRIDE {
const EllipseEdgeEffect& ee = args.fGP.cast<EllipseEdgeEffect>();
-
+ GrGLGPBuilder* pb = args.fPB;
+ const BatchTracker& local = args.fBT.cast<BatchTracker>();
GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder();
GrGLVertToFrag ellipseOffsets(kVec2f_GrSLType);
@@ -218,6 +256,10 @@ public:
vsBuilder->codeAppendf("%s = %s;", ellipseRadii.vsOut(),
ee.inEllipseRadii()->fName);
+ // Setup pass through color
+ this->setupColorPassThrough(pb, local.fInputColorType, args.fOutputColor, NULL,
+ &fColorUniform);
+
// setup coord outputs
vsBuilder->codeAppendf("%s = %s;", vsBuilder->positionCoords(), ee.inPosition()->fName);
vsBuilder->codeAppendf("%s = %s;", vsBuilder->localCoords(), ee.inPosition()->fName);
@@ -254,19 +296,30 @@ public:
}
static void GenKey(const GrGeometryProcessor& processor,
- const GrBatchTracker&,
+ const GrBatchTracker& bt,
const GrGLCaps&,
GrProcessorKeyBuilder* b) {
+ const BatchTracker& local = bt.cast<BatchTracker>();
const EllipseEdgeEffect& ellipseEffect = processor.cast<EllipseEdgeEffect>();
- b->add32(ellipseEffect.isStroked());
+ b->add32(ellipseEffect.isStroked() << 16 | local.fInputColorType);
}
- virtual void setData(const GrGLProgramDataManager&,
- const GrGeometryProcessor&,
- const GrBatchTracker&) SK_OVERRIDE {
+ virtual void setData(const GrGLProgramDataManager& pdman,
+ const GrPrimitiveProcessor& gp,
+ const GrBatchTracker& bt) SK_OVERRIDE {
+ const BatchTracker& local = bt.cast<BatchTracker>();
+ if (kUniform_GrGPInput == local.fInputColorType && local.fColor != fColor) {
+ GrGLfloat c[4];
+ GrColorToRGBAFloat(local.fColor, c);
+ pdman.set4fv(fColorUniform, 1, c);
+ fColor = local.fColor;
+ }
}
private:
+ GrColor fColor;
+ UniformHandle fColorUniform;
+
typedef GrGLGeometryProcessor INHERITED;
};
@@ -280,6 +333,18 @@ public:
return SkNEW_ARGS(GLProcessor, (*this, bt));
}
+ void initBatchTracker(GrBatchTracker* bt, const InitBT& init) const SK_OVERRIDE {
+ BatchTracker* local = bt->cast<BatchTracker>();
+ local->fInputColorType = GetColorInputType(&local->fColor, this->color(), init, false);
+ }
+
+ bool onCanMakeEqual(const GrBatchTracker& m, const GrBatchTracker& t) const SK_OVERRIDE {
+ const BatchTracker& mine = m.cast<BatchTracker>();
+ const BatchTracker& theirs = t.cast<BatchTracker>();
+ return CanCombineOutput(mine.fInputColorType, mine.fColor,
+ theirs.fInputColorType, theirs.fColor);
+ }
+
private:
EllipseEdgeEffect(GrColor color, bool stroke) : INHERITED(color) {
this->initClassID<EllipseEdgeEffect>();
@@ -300,6 +365,11 @@ private:
out->setUnknownSingleComponent();
}
+ struct BatchTracker {
+ GrGPInput fInputColorType;
+ GrColor fColor;
+ };
+
const GrAttribute* fInPosition;
const GrAttribute* fInEllipseOffset;
const GrAttribute* fInEllipseRadii;
@@ -351,11 +421,13 @@ public:
class GLProcessor : public GrGLGeometryProcessor {
public:
GLProcessor(const GrGeometryProcessor&,
- const GrBatchTracker&) {}
+ const GrBatchTracker&)
+ : fColor(GrColor_ILLEGAL) {}
virtual void emitCode(const EmitArgs& args) SK_OVERRIDE {
const DIEllipseEdgeEffect& ee = args.fGP.cast<DIEllipseEdgeEffect>();
-
+ GrGLGPBuilder* pb = args.fPB;
+ const BatchTracker& local = args.fBT.cast<BatchTracker>();
GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder();
GrGLVertToFrag offsets0(kVec2f_GrSLType);
@@ -368,6 +440,10 @@ public:
vsBuilder->codeAppendf("%s = %s;", offsets1.vsOut(),
ee.inEllipseOffsets1()->fName);
+ // Setup pass through color
+ this->setupColorPassThrough(pb, local.fInputColorType, args.fOutputColor, NULL,
+ &fColorUniform);
+
// setup coord outputs
vsBuilder->codeAppendf("%s = %s;", vsBuilder->positionCoords(), ee.inPosition()->fName);
vsBuilder->codeAppendf("%s = %s;", vsBuilder->localCoords(), ee.inPosition()->fName);
@@ -418,20 +494,30 @@ public:
}
static void GenKey(const GrGeometryProcessor& processor,
- const GrBatchTracker&,
+ const GrBatchTracker& bt,
const GrGLCaps&,
GrProcessorKeyBuilder* b) {
+ const BatchTracker& local = bt.cast<BatchTracker>();
const DIEllipseEdgeEffect& ellipseEffect = processor.cast<DIEllipseEdgeEffect>();
-
- b->add32(ellipseEffect.getMode());
+ b->add32(ellipseEffect.getMode() << 16 | local.fInputColorType);
}
- virtual void setData(const GrGLProgramDataManager&,
- const GrGeometryProcessor&,
- const GrBatchTracker&) SK_OVERRIDE {
+ virtual void setData(const GrGLProgramDataManager& pdman,
+ const GrPrimitiveProcessor& gp,
+ const GrBatchTracker& bt) SK_OVERRIDE {
+ const BatchTracker& local = bt.cast<BatchTracker>();
+ if (kUniform_GrGPInput == local.fInputColorType && local.fColor != fColor) {
+ GrGLfloat c[4];
+ GrColorToRGBAFloat(local.fColor, c);
+ pdman.set4fv(fColorUniform, 1, c);
+ fColor = local.fColor;
+ }
}
private:
+ GrColor fColor;
+ UniformHandle fColorUniform;
+
typedef GrGLGeometryProcessor INHERITED;
};
@@ -445,6 +531,18 @@ public:
return SkNEW_ARGS(GLProcessor, (*this, bt));
}
+ void initBatchTracker(GrBatchTracker* bt, const InitBT& init) const SK_OVERRIDE {
+ BatchTracker* local = bt->cast<BatchTracker>();
+ local->fInputColorType = GetColorInputType(&local->fColor, this->color(), init, false);
+ }
+
+ bool onCanMakeEqual(const GrBatchTracker& m, const GrBatchTracker& t) const SK_OVERRIDE {
+ const BatchTracker& mine = m.cast<BatchTracker>();
+ const BatchTracker& theirs = t.cast<BatchTracker>();
+ return CanCombineOutput(mine.fInputColorType, mine.fColor,
+ theirs.fInputColorType, theirs.fColor);
+ }
+
private:
DIEllipseEdgeEffect(GrColor color, Mode mode) : INHERITED(color) {
this->initClassID<DIEllipseEdgeEffect>();
@@ -465,6 +563,11 @@ private:
out->setUnknownSingleComponent();
}
+ struct BatchTracker {
+ GrGPInput fInputColorType;
+ GrColor fColor;
+ };
+
const GrAttribute* fInPosition;
const GrAttribute* fInEllipseOffsets0;
const GrAttribute* fInEllipseOffsets1;
diff --git a/src/gpu/GrProcOptInfo.cpp b/src/gpu/GrProcOptInfo.cpp
index 4c119b5cb3..6fad760071 100644
--- a/src/gpu/GrProcOptInfo.cpp
+++ b/src/gpu/GrProcOptInfo.cpp
@@ -48,7 +48,6 @@ void GrProcOptInfo::internalCalc(const GrFragmentStage* stages,
fFirstEffectStageIndex = 0;
fInputColorIsUsed = true;
fInputColor = fInOut.color();
- fRemoveVertexAttrib = false;
fReadsDst = false;
fReadsFragPosition = initWillReadFragmentPosition;
@@ -74,7 +73,6 @@ void GrProcOptInfo::internalCalc(const GrFragmentStage* stages,
fFirstEffectStageIndex = i + 1;
fInputColor = fInOut.color();
fInputColorIsUsed = true;
- fRemoveVertexAttrib = true;
// Since we are clearing all previous color stages we are in a state where we have found
// zero stages that don't multiply the inputColor.
fInOut.resetNonMulStageFound();
diff --git a/src/gpu/GrProcOptInfo.h b/src/gpu/GrProcOptInfo.h
index 30b286f3ae..43d6c558f1 100644
--- a/src/gpu/GrProcOptInfo.h
+++ b/src/gpu/GrProcOptInfo.h
@@ -28,7 +28,6 @@ public:
, fFirstEffectStageIndex(0)
, fInputColorIsUsed(true)
, fInputColor(0)
- , fRemoveVertexAttrib(false)
, fReadsDst(false)
, fReadsFragPosition(false) {}
@@ -76,12 +75,6 @@ public:
GrColor inputColorToEffectiveStage() const { return fInputColor; }
/**
- * Given the set of optimizations determined by GrProcOptInfo, should the caller remove the
- * color/coverage vertex attribute that was input to the first stage.
- */
- bool removeVertexAttrib() const { return fRemoveVertexAttrib; }
-
- /**
* Returns true if any of the stages preserved by GrProcOptInfo read the dst color.
*/
bool readsDst() const { return fReadsDst; }
@@ -98,7 +91,6 @@ private:
int fFirstEffectStageIndex;
bool fInputColorIsUsed;
GrColor fInputColor;
- bool fRemoveVertexAttrib;
bool fReadsDst;
bool fReadsFragPosition;
};
diff --git a/src/gpu/GrProcessor.cpp b/src/gpu/GrProcessor.cpp
index 721859b3ef..d2ad7a5293 100644
--- a/src/gpu/GrProcessor.cpp
+++ b/src/gpu/GrProcessor.cpp
@@ -171,35 +171,6 @@ void GrFragmentProcessor::computeInvariantOutput(GrInvariantOutput* inout) const
///////////////////////////////////////////////////////////////////////////////////////////////////
-void GrGeometryProcessor::getInvariantOutputColor(GrInitInvariantOutput* out) const {
- if (fHasVertexColor) {
- if (fOpaqueVertexColors) {
- out->setUnknownOpaqueFourComponents();
- } else {
- out->setUnknownFourComponents();
- }
- } else {
- out->setKnownFourComponents(fColor);
- }
- this->onGetInvariantOutputColor(out);
-}
-
-void GrGeometryProcessor::getInvariantOutputCoverage(GrInitInvariantOutput* out) const {
- this->onGetInvariantOutputCoverage(out);
-}
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-void GrPathProcessor::getInvariantOutputColor(GrInitInvariantOutput* out) const {
- out->setKnownFourComponents(fColor);
-}
-
-void GrPathProcessor::getInvariantOutputCoverage(GrInitInvariantOutput* out) const {
- out->setKnownSingleComponent(0xff);
-}
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
/*
* GrGeometryData shares the same pool so it lives in this file too
*/
diff --git a/src/gpu/GrProgramDesc.h b/src/gpu/GrProgramDesc.h
index 022bbc3d44..8e255275b6 100644
--- a/src/gpu/GrProgramDesc.h
+++ b/src/gpu/GrProgramDesc.h
@@ -54,16 +54,6 @@ public:
return memcmp(a.asKey(), b.asKey(), a.keyLength() & ~0x3) < 0;
}
-
- // Specifies where the initial color comes from before the stages are applied.
- enum ColorInput {
- kAllOnes_ColorInput,
- kAttribute_ColorInput,
- kUniform_ColorInput,
-
- kColorInputCnt
- };
-
struct KeyHeader {
uint8_t fDstReadKey; // set by GrGLShaderBuilder if there
// are effects that must read the dst.
@@ -72,19 +62,10 @@ public:
// effects that read the fragment position.
// Otherwise, 0.
- ColorInput fColorInput : 8;
- ColorInput fCoverageInput : 8;
-
- SkBool8 fHasGeometryProcessor;
int8_t fColorEffectCnt;
int8_t fCoverageEffectCnt;
};
-
- bool hasGeometryProcessor() const {
- return SkToBool(this->header().fHasGeometryProcessor);
- }
-
int numColorEffects() const {
return this->header().fColorEffectCnt;
}
@@ -101,31 +82,17 @@ public:
// A struct to communicate descriptor information to the program descriptor builder
struct DescInfo {
bool operator==(const DescInfo& that) const {
- return fHasVertexColor == that.fHasVertexColor &&
- fHasVertexCoverage == that.fHasVertexCoverage &&
- fInputColorIsUsed == that.fInputColorIsUsed &&
- fInputCoverageIsUsed == that.fInputCoverageIsUsed &&
- fReadsDst == that.fReadsDst &&
+ return fReadsDst == that.fReadsDst &&
fReadsFragPosition == that.fReadsFragPosition &&
fRequiresLocalCoordAttrib == that.fRequiresLocalCoordAttrib;
}
bool operator!=(const DescInfo& that) const { return !(*this == that); };
- // TODO when GPs control uniform / attribute handling of color / coverage, then we can
- // clean this up
- bool fHasVertexColor;
- bool fHasVertexCoverage;
-
- // These flags are needed to protect the code from creating an unused uniform color/coverage
- // which will cause shader compiler errors.
- bool fInputColorIsUsed;
- bool fInputCoverageIsUsed;
// These flags give aggregated info on the processor stages that are used when building
// programs.
bool fReadsDst;
bool fReadsFragPosition;
bool fRequiresLocalCoordAttrib;
-
};
private:
diff --git a/src/gpu/effects/GrBezierEffect.cpp b/src/gpu/effects/GrBezierEffect.cpp
index 6f4f28a109..be1fef76af 100644
--- a/src/gpu/effects/GrBezierEffect.cpp
+++ b/src/gpu/effects/GrBezierEffect.cpp
@@ -12,6 +12,12 @@
#include "gl/GrGLGeometryProcessor.h"
#include "gl/builders/GrGLProgramBuilder.h"
+struct ConicBatchTracker {
+ GrGPInput fInputColorType;
+ GrColor fColor;
+ uint8_t fCoverageScale;
+};
+
class GrGLConicEffect : public GrGLGeometryProcessor {
public:
GrGLConicEffect(const GrGeometryProcessor&,
@@ -24,30 +30,53 @@ public:
const GrGLCaps&,
GrProcessorKeyBuilder*);
- virtual void setData(const GrGLProgramDataManager&,
- const GrGeometryProcessor&,
- const GrBatchTracker&) SK_OVERRIDE {}
+ virtual void setData(const GrGLProgramDataManager& pdman,
+ const GrPrimitiveProcessor&,
+ const GrBatchTracker& bt) SK_OVERRIDE {
+ const ConicBatchTracker& local = bt.cast<ConicBatchTracker>();
+ if (kUniform_GrGPInput == local.fInputColorType && local.fColor != fColor) {
+ GrGLfloat c[4];
+ GrColorToRGBAFloat(local.fColor, c);
+ pdman.set4fv(fColorUniform, 1, c);
+ fColor = local.fColor;
+ }
+ if (0xff != local.fCoverageScale && fCoverageScale != local.fCoverageScale) {
+ pdman.set1f(fCoverageScaleUniform, GrNormalizeByteToFloat(local.fCoverageScale));
+ fCoverageScale = local.fCoverageScale;
+ }
+ }
private:
+ GrColor fColor;
+ uint8_t fCoverageScale;
GrPrimitiveEdgeType fEdgeType;
+ UniformHandle fColorUniform;
+ UniformHandle fCoverageScaleUniform;
typedef GrGLGeometryProcessor INHERITED;
};
GrGLConicEffect::GrGLConicEffect(const GrGeometryProcessor& processor,
- const GrBatchTracker& bt) {
+ const GrBatchTracker& bt)
+ : fColor(GrColor_ILLEGAL), fCoverageScale(0xff) {
const GrConicEffect& ce = processor.cast<GrConicEffect>();
fEdgeType = ce.getEdgeType();
}
void GrGLConicEffect::emitCode(const EmitArgs& args) {
+ GrGLGPBuilder* pb = args.fPB;
GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder();
const GrConicEffect& gp = args.fGP.cast<GrConicEffect>();
+ const ConicBatchTracker& local = args.fBT.cast<ConicBatchTracker>();
GrGLVertToFrag v(kVec4f_GrSLType);
args.fPB->addVarying("ConicCoeffs", &v);
vsBuilder->codeAppendf("%s = %s;", v.vsOut(), gp.inConicCoeffs()->fName);
+ // Setup pass through color
+ this->setupColorPassThrough(args.fPB, local.fInputColorType, args.fOutputColor, NULL,
+ &fColorUniform);
+
// setup coord outputs
vsBuilder->codeAppendf("%s = %s;", vsBuilder->positionCoords(), gp.inPosition()->fName);
vsBuilder->codeAppendf("%s = %s;", vsBuilder->localCoords(), gp.inPosition()->fName);
@@ -113,15 +142,28 @@ void GrGLConicEffect::emitCode(const EmitArgs& args) {
SkFAIL("Shouldn't get here");
}
- fsBuilder->codeAppendf("%s = vec4(edgeAlpha);", args.fOutputCoverage);
+ if (0xff != local.fCoverageScale) {
+ const char* coverageScale;
+ fCoverageScaleUniform = pb->addUniform(GrGLProgramBuilder::kFragment_Visibility,
+ kFloat_GrSLType,
+ kDefault_GrSLPrecision,
+ "Coverage",
+ &coverageScale);
+ fsBuilder->codeAppendf("%s = vec4(%s * edgeAlpha);", args.fOutputCoverage, coverageScale);
+ } else {
+ fsBuilder->codeAppendf("%s = vec4(edgeAlpha);", args.fOutputCoverage);
+ }
}
void GrGLConicEffect::GenKey(const GrGeometryProcessor& processor,
- const GrBatchTracker&,
+ const GrBatchTracker& bt,
const GrGLCaps&,
GrProcessorKeyBuilder* b) {
const GrConicEffect& ce = processor.cast<GrConicEffect>();
+ const ConicBatchTracker& local = bt.cast<ConicBatchTracker>();
uint32_t key = ce.isAntiAliased() ? (ce.isFilled() ? 0x0 : 0x1) : 0x2;
+ key |= kUniform_GrGPInput == local.fInputColorType ? 0x4 : 0x0;
+ key |= 0xff != local.fCoverageScale ? 0x8 : 0x0;
b->add32(key);
}
@@ -140,7 +182,7 @@ GrGLGeometryProcessor* GrConicEffect::createGLInstance(const GrBatchTracker& bt)
}
GrConicEffect::GrConicEffect(GrColor color, uint8_t coverage, GrPrimitiveEdgeType edgeType)
- : INHERITED(color, false, coverage), fEdgeType(edgeType) {
+ : INHERITED(color, false), fCoverageScale(coverage), fEdgeType(edgeType) {
this->initClassID<GrConicEffect>();
fInPosition = &this->addVertexAttrib(GrAttribute("inPosition", kVec2f_GrVertexAttribType));
fInConicCoeffs = &this->addVertexAttrib(GrAttribute("inConicCoeffs",
@@ -152,6 +194,20 @@ bool GrConicEffect::onIsEqual(const GrGeometryProcessor& other) const {
return (ce.fEdgeType == fEdgeType);
}
+void GrConicEffect::initBatchTracker(GrBatchTracker* bt, const InitBT& init) const {
+ ConicBatchTracker* local = bt->cast<ConicBatchTracker>();
+ local->fInputColorType = GetColorInputType(&local->fColor, this->color(), init, false);
+ local->fCoverageScale = fCoverageScale;
+}
+
+bool GrConicEffect::onCanMakeEqual(const GrBatchTracker& m, const GrBatchTracker& t) const {
+ const ConicBatchTracker& mine = m.cast<ConicBatchTracker>();
+ const ConicBatchTracker& theirs = t.cast<ConicBatchTracker>();
+ return CanCombineOutput(mine.fInputColorType, mine.fColor,
+ theirs.fInputColorType, theirs.fColor) &&
+ mine.fCoverageScale == theirs.fCoverageScale;
+}
+
//////////////////////////////////////////////////////////////////////////////
GR_DEFINE_GEOMETRY_PROCESSOR_TEST(GrConicEffect);
@@ -173,6 +229,12 @@ GrGeometryProcessor* GrConicEffect::TestCreate(SkRandom* random,
// Quad
//////////////////////////////////////////////////////////////////////////////
+struct QuadBatchTracker {
+ GrGPInput fInputColorType;
+ GrColor fColor;
+ uint8_t fCoverageScale;
+};
+
class GrGLQuadEffect : public GrGLGeometryProcessor {
public:
GrGLQuadEffect(const GrGeometryProcessor&,
@@ -185,30 +247,53 @@ public:
const GrGLCaps&,
GrProcessorKeyBuilder*);
- virtual void setData(const GrGLProgramDataManager&,
- const GrGeometryProcessor&,
- const GrBatchTracker&) SK_OVERRIDE {}
+ virtual void setData(const GrGLProgramDataManager& pdman,
+ const GrPrimitiveProcessor&,
+ const GrBatchTracker& bt) SK_OVERRIDE {
+ const QuadBatchTracker& local = bt.cast<QuadBatchTracker>();
+ if (kUniform_GrGPInput == local.fInputColorType && local.fColor != fColor) {
+ GrGLfloat c[4];
+ GrColorToRGBAFloat(local.fColor, c);
+ pdman.set4fv(fColorUniform, 1, c);
+ fColor = local.fColor;
+ }
+ if (0xff != local.fCoverageScale && local.fCoverageScale != fCoverageScale) {
+ pdman.set1f(fCoverageScaleUniform, GrNormalizeByteToFloat(local.fCoverageScale));
+ fCoverageScale = local.fCoverageScale;
+ }
+ }
private:
+ GrColor fColor;
+ uint8_t fCoverageScale;
GrPrimitiveEdgeType fEdgeType;
+ UniformHandle fColorUniform;
+ UniformHandle fCoverageScaleUniform;
typedef GrGLGeometryProcessor INHERITED;
};
GrGLQuadEffect::GrGLQuadEffect(const GrGeometryProcessor& processor,
- const GrBatchTracker& bt) {
+ const GrBatchTracker& bt)
+ : fColor(GrColor_ILLEGAL), fCoverageScale(0xff) {
const GrQuadEffect& ce = processor.cast<GrQuadEffect>();
fEdgeType = ce.getEdgeType();
}
void GrGLQuadEffect::emitCode(const EmitArgs& args) {
+ GrGLGPBuilder* pb = args.fPB;
GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder();
const GrQuadEffect& gp = args.fGP.cast<GrQuadEffect>();
+ const QuadBatchTracker& local = args.fBT.cast<QuadBatchTracker>();
GrGLVertToFrag v(kVec4f_GrSLType);
args.fPB->addVarying("HairQuadEdge", &v);
vsBuilder->codeAppendf("%s = %s;", v.vsOut(), gp.inHairQuadEdge()->fName);
+ // Setup pass through color
+ this->setupColorPassThrough(args.fPB, local.fInputColorType, args.fOutputColor, NULL,
+ &fColorUniform);
+
// setup coord outputs
vsBuilder->codeAppendf("%s = %s;", vsBuilder->positionCoords(), gp.inPosition()->fName);
vsBuilder->codeAppendf("%s = %s;", vsBuilder->localCoords(), gp.inPosition()->fName);
@@ -260,15 +345,28 @@ void GrGLQuadEffect::emitCode(const EmitArgs& args) {
SkFAIL("Shouldn't get here");
}
- fsBuilder->codeAppendf("%s = vec4(edgeAlpha);", args.fOutputCoverage);
+ if (0xff != local.fCoverageScale) {
+ const char* coverageScale;
+ fCoverageScaleUniform = pb->addUniform(GrGLProgramBuilder::kFragment_Visibility,
+ kFloat_GrSLType,
+ kDefault_GrSLPrecision,
+ "Coverage",
+ &coverageScale);
+ fsBuilder->codeAppendf("%s = vec4(%s * edgeAlpha);", args.fOutputCoverage, coverageScale);
+ } else {
+ fsBuilder->codeAppendf("%s = vec4(edgeAlpha);", args.fOutputCoverage);
+ }
}
void GrGLQuadEffect::GenKey(const GrGeometryProcessor& processor,
- const GrBatchTracker&,
+ const GrBatchTracker& bt,
const GrGLCaps&,
GrProcessorKeyBuilder* b) {
const GrQuadEffect& ce = processor.cast<GrQuadEffect>();
+ const QuadBatchTracker& local = bt.cast<QuadBatchTracker>();
uint32_t key = ce.isAntiAliased() ? (ce.isFilled() ? 0x0 : 0x1) : 0x2;
+ key |= kUniform_GrGPInput == local.fInputColorType ? 0x4 : 0x0;
+ key |= 0xff != local.fCoverageScale ? 0x8 : 0x0;
b->add32(key);
}
@@ -287,7 +385,7 @@ GrGLGeometryProcessor* GrQuadEffect::createGLInstance(const GrBatchTracker& bt)
}
GrQuadEffect::GrQuadEffect(GrColor color, uint8_t coverage, GrPrimitiveEdgeType edgeType)
- : INHERITED(color, false, coverage), fEdgeType(edgeType) {
+ : INHERITED(color, false), fCoverageScale(coverage), fEdgeType(edgeType) {
this->initClassID<GrQuadEffect>();
fInPosition = &this->addVertexAttrib(GrAttribute("inPosition", kVec2f_GrVertexAttribType));
fInHairQuadEdge = &this->addVertexAttrib(GrAttribute("inHairQuadEdge",
@@ -299,6 +397,20 @@ bool GrQuadEffect::onIsEqual(const GrGeometryProcessor& other) const {
return (ce.fEdgeType == fEdgeType);
}
+void GrQuadEffect::initBatchTracker(GrBatchTracker* bt, const InitBT& init) const {
+ QuadBatchTracker* local = bt->cast<QuadBatchTracker>();
+ local->fInputColorType = GetColorInputType(&local->fColor, this->color(), init, false);
+ local->fCoverageScale = fCoverageScale;
+}
+
+bool GrQuadEffect::onCanMakeEqual(const GrBatchTracker& m, const GrBatchTracker& t) const {
+ const QuadBatchTracker& mine = m.cast<QuadBatchTracker>();
+ const QuadBatchTracker& theirs = t.cast<QuadBatchTracker>();
+ return CanCombineOutput(mine.fInputColorType, mine.fColor,
+ theirs.fInputColorType, theirs.fColor) &&
+ mine.fCoverageScale == theirs.fCoverageScale;
+}
+
//////////////////////////////////////////////////////////////////////////////
GR_DEFINE_GEOMETRY_PROCESSOR_TEST(GrQuadEffect);
@@ -320,6 +432,11 @@ GrGeometryProcessor* GrQuadEffect::TestCreate(SkRandom* random,
// Cubic
//////////////////////////////////////////////////////////////////////////////
+struct CubicBatchTracker {
+ GrGPInput fInputColorType;
+ GrColor fColor;
+};
+
class GrGLCubicEffect : public GrGLGeometryProcessor {
public:
GrGLCubicEffect(const GrGeometryProcessor&,
@@ -332,18 +449,29 @@ public:
const GrGLCaps&,
GrProcessorKeyBuilder*);
- virtual void setData(const GrGLProgramDataManager&,
- const GrGeometryProcessor&,
- const GrBatchTracker&) SK_OVERRIDE {}
+ virtual void setData(const GrGLProgramDataManager& pdman,
+ const GrPrimitiveProcessor&,
+ const GrBatchTracker& bt) SK_OVERRIDE {
+ const CubicBatchTracker& local = bt.cast<CubicBatchTracker>();
+ if (kUniform_GrGPInput == local.fInputColorType && local.fColor != fColor) {
+ GrGLfloat c[4];
+ GrColorToRGBAFloat(local.fColor, c);
+ pdman.set4fv(fColorUniform, 1, c);
+ fColor = local.fColor;
+ }
+ }
private:
+ GrColor fColor;
GrPrimitiveEdgeType fEdgeType;
+ UniformHandle fColorUniform;
typedef GrGLGeometryProcessor INHERITED;
};
GrGLCubicEffect::GrGLCubicEffect(const GrGeometryProcessor& processor,
- const GrBatchTracker&) {
+ const GrBatchTracker&)
+ : fColor(GrColor_ILLEGAL) {
const GrCubicEffect& ce = processor.cast<GrCubicEffect>();
fEdgeType = ce.getEdgeType();
}
@@ -351,11 +479,16 @@ GrGLCubicEffect::GrGLCubicEffect(const GrGeometryProcessor& processor,
void GrGLCubicEffect::emitCode(const EmitArgs& args) {
GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder();
const GrCubicEffect& gp = args.fGP.cast<GrCubicEffect>();
+ const CubicBatchTracker& local = args.fBT.cast<CubicBatchTracker>();
GrGLVertToFrag v(kVec4f_GrSLType);
args.fPB->addVarying("CubicCoeffs", &v, kHigh_GrSLPrecision);
vsBuilder->codeAppendf("%s = %s;", v.vsOut(), gp.inCubicCoeffs()->fName);
+ // Setup pass through color
+ this->setupColorPassThrough(args.fPB, local.fInputColorType, args.fOutputColor, NULL,
+ &fColorUniform);
+
// setup coord outputs
vsBuilder->codeAppendf("%s = %s;", vsBuilder->positionCoords(), gp.inPosition()->fName);
vsBuilder->codeAppendf("%s = %s;", vsBuilder->localCoords(), gp.inPosition()->fName);
@@ -452,11 +585,13 @@ void GrGLCubicEffect::emitCode(const EmitArgs& args) {
}
void GrGLCubicEffect::GenKey(const GrGeometryProcessor& processor,
- const GrBatchTracker&,
+ const GrBatchTracker& bt,
const GrGLCaps&,
GrProcessorKeyBuilder* b) {
const GrCubicEffect& ce = processor.cast<GrCubicEffect>();
+ const CubicBatchTracker& local = bt.cast<CubicBatchTracker>();
uint32_t key = ce.isAntiAliased() ? (ce.isFilled() ? 0x0 : 0x1) : 0x2;
+ key |= kUniform_GrGPInput == local.fInputColorType ? 0x4 : 0x8;
b->add32(key);
}
@@ -487,6 +622,18 @@ bool GrCubicEffect::onIsEqual(const GrGeometryProcessor& other) const {
return (ce.fEdgeType == fEdgeType);
}
+void GrCubicEffect::initBatchTracker(GrBatchTracker* bt, const InitBT& init) const {
+ CubicBatchTracker* local = bt->cast<CubicBatchTracker>();
+ local->fInputColorType = GetColorInputType(&local->fColor, this->color(), init, false);
+}
+
+bool GrCubicEffect::onCanMakeEqual(const GrBatchTracker& m, const GrBatchTracker& t) const {
+ const CubicBatchTracker& mine = m.cast<CubicBatchTracker>();
+ const CubicBatchTracker& theirs = t.cast<CubicBatchTracker>();
+ return CanCombineOutput(mine.fInputColorType, mine.fColor,
+ theirs.fInputColorType, theirs.fColor);
+}
+
//////////////////////////////////////////////////////////////////////////////
GR_DEFINE_GEOMETRY_PROCESSOR_TEST(GrCubicEffect);
diff --git a/src/gpu/effects/GrBezierEffect.h b/src/gpu/effects/GrBezierEffect.h
index 53b1053b0c..a58211b9b6 100644
--- a/src/gpu/effects/GrBezierEffect.h
+++ b/src/gpu/effects/GrBezierEffect.h
@@ -97,6 +97,9 @@ public:
virtual GrGLGeometryProcessor* createGLInstance(const GrBatchTracker& bt) const SK_OVERRIDE;
+ void initBatchTracker(GrBatchTracker*, const InitBT&) const SK_OVERRIDE;
+ bool onCanMakeEqual(const GrBatchTracker&, const GrBatchTracker&) const SK_OVERRIDE;
+
private:
GrConicEffect(GrColor, uint8_t coverage, GrPrimitiveEdgeType);
@@ -106,6 +109,7 @@ private:
out->setUnknownSingleComponent();
}
+ uint8_t fCoverageScale;
GrPrimitiveEdgeType fEdgeType;
const GrAttribute* fInPosition;
const GrAttribute* fInConicCoeffs;
@@ -166,6 +170,9 @@ public:
virtual GrGLGeometryProcessor* createGLInstance(const GrBatchTracker& bt) const SK_OVERRIDE;
+ void initBatchTracker(GrBatchTracker*, const InitBT&) const SK_OVERRIDE;
+ bool onCanMakeEqual(const GrBatchTracker&, const GrBatchTracker&) const SK_OVERRIDE;
+
private:
GrQuadEffect(GrColor, uint8_t coverage, GrPrimitiveEdgeType);
@@ -175,6 +182,7 @@ private:
out->setUnknownSingleComponent();
}
+ uint8_t fCoverageScale;
GrPrimitiveEdgeType fEdgeType;
const GrAttribute* fInPosition;
const GrAttribute* fInHairQuadEdge;
@@ -236,6 +244,9 @@ public:
virtual GrGLGeometryProcessor* createGLInstance(const GrBatchTracker& bt) const SK_OVERRIDE;
+ void initBatchTracker(GrBatchTracker*, const InitBT&) const SK_OVERRIDE;
+ bool onCanMakeEqual(const GrBatchTracker&, const GrBatchTracker&) const SK_OVERRIDE;
+
private:
GrCubicEffect(GrColor, GrPrimitiveEdgeType);
diff --git a/src/gpu/effects/GrBitmapTextGeoProc.cpp b/src/gpu/effects/GrBitmapTextGeoProc.cpp
index c93db90a91..1b393f32a3 100644
--- a/src/gpu/effects/GrBitmapTextGeoProc.cpp
+++ b/src/gpu/effects/GrBitmapTextGeoProc.cpp
@@ -14,22 +14,30 @@
#include "gl/GrGLGeometryProcessor.h"
#include "gl/builders/GrGLProgramBuilder.h"
+struct BitmapTextBatchTracker {
+ GrGPInput fInputColorType;
+ GrColor fColor;
+};
+
class GrGLBitmapTextGeoProc : public GrGLGeometryProcessor {
public:
- GrGLBitmapTextGeoProc(const GrGeometryProcessor&, const GrBatchTracker&) {}
+ GrGLBitmapTextGeoProc(const GrGeometryProcessor&, const GrBatchTracker&)
+ : fColor(GrColor_ILLEGAL) {}
virtual void emitCode(const EmitArgs& args) SK_OVERRIDE {
const GrBitmapTextGeoProc& cte = args.fGP.cast<GrBitmapTextGeoProc>();
+ const BitmapTextBatchTracker& local = args.fBT.cast<BitmapTextBatchTracker>();
- GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder();
+ GrGLGPBuilder* pb = args.fPB;
+ GrGLVertexBuilder* vsBuilder = pb->getVertexShaderBuilder();
GrGLVertToFrag v(kVec2f_GrSLType);
- args.fPB->addVarying("TextureCoords", &v);
+ pb->addVarying("TextureCoords", &v);
vsBuilder->codeAppendf("%s = %s;", v.vsOut(), cte.inTextureCoords()->fName);
- if (cte.inColor()) {
- args.fPB->addPassThroughAttribute(cte.inColor(), args.fOutputColor);
- }
+ // Setup pass through color
+ this->setupColorPassThrough(pb, local.fInputColorType, args.fOutputColor, cte.inColor(),
+ &fColorUniform);
// setup output coords
vsBuilder->codeAppendf("%s = %s;", vsBuilder->positionCoords(), cte.inPosition()->fName);
@@ -39,27 +47,41 @@ public:
vsBuilder->codeAppendf("%s = %s * vec3(%s, 1);", vsBuilder->glPosition(),
vsBuilder->uViewM(), cte.inPosition()->fName);
- GrGLGPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder();
+ GrGLGPFragmentBuilder* fsBuilder = pb->getFragmentShaderBuilder();
fsBuilder->codeAppendf("%s = ", args.fOutputCoverage);
fsBuilder->appendTextureLookup(args.fSamplers[0], v.fsIn(), kVec2f_GrSLType);
fsBuilder->codeAppend(";");
}
- virtual void setData(const GrGLProgramDataManager&,
- const GrGeometryProcessor&,
- const GrBatchTracker&) SK_OVERRIDE {}
+ virtual void setData(const GrGLProgramDataManager& pdman,
+ const GrPrimitiveProcessor& gp,
+ const GrBatchTracker& bt) SK_OVERRIDE {
+ const BitmapTextBatchTracker& local = bt.cast<BitmapTextBatchTracker>();
+ if (kUniform_GrGPInput == local.fInputColorType && local.fColor != fColor) {
+ GrGLfloat c[4];
+ GrColorToRGBAFloat(local.fColor, c);
+ pdman.set4fv(fColorUniform, 1, c);
+ fColor = local.fColor;
+ }
+ }
static inline void GenKey(const GrGeometryProcessor& proc,
- const GrBatchTracker&,
+ const GrBatchTracker& bt,
const GrGLCaps&,
GrProcessorKeyBuilder* b) {
+ const BitmapTextBatchTracker& local = bt.cast<BitmapTextBatchTracker>();
+ // We have to put the optional vertex attribute as part of the key. See the comment
+ // on addVertexAttrib.
+ // TODO When we have deferred geometry we can fix this
const GrBitmapTextGeoProc& gp = proc.cast<GrBitmapTextGeoProc>();
-
b->add32(SkToBool(gp.inColor()));
+ b->add32(local.fInputColorType);
}
-
private:
+ GrColor fColor;
+ UniformHandle fColorUniform;
+
typedef GrGLGeometryProcessor INHERITED;
};
@@ -107,6 +129,20 @@ GrGLGeometryProcessor*
GrBitmapTextGeoProc::createGLInstance(const GrBatchTracker& bt) const {
return SkNEW_ARGS(GrGLBitmapTextGeoProc, (*this, bt));
}
+
+void GrBitmapTextGeoProc::initBatchTracker(GrBatchTracker* bt, const InitBT& init) const {
+ BitmapTextBatchTracker* local = bt->cast<BitmapTextBatchTracker>();
+ local->fInputColorType = GetColorInputType(&local->fColor, this->color(), init,
+ SkToBool(fInColor));
+}
+
+bool GrBitmapTextGeoProc::onCanMakeEqual(const GrBatchTracker& m, const GrBatchTracker& t) const {
+ const BitmapTextBatchTracker& mine = m.cast<BitmapTextBatchTracker>();
+ const BitmapTextBatchTracker& theirs = t.cast<BitmapTextBatchTracker>();
+ return CanCombineOutput(mine.fInputColorType, mine.fColor,
+ theirs.fInputColorType, theirs.fColor);
+}
+
///////////////////////////////////////////////////////////////////////////////
GR_DEFINE_GEOMETRY_PROCESSOR_TEST(GrBitmapTextGeoProc);
diff --git a/src/gpu/effects/GrBitmapTextGeoProc.h b/src/gpu/effects/GrBitmapTextGeoProc.h
index 0c848421c0..42345704cf 100644
--- a/src/gpu/effects/GrBitmapTextGeoProc.h
+++ b/src/gpu/effects/GrBitmapTextGeoProc.h
@@ -40,6 +40,9 @@ public:
virtual GrGLGeometryProcessor* createGLInstance(const GrBatchTracker& bt) const SK_OVERRIDE;
+ void initBatchTracker(GrBatchTracker*, const InitBT&) const SK_OVERRIDE;
+ bool onCanMakeEqual(const GrBatchTracker&, const GrBatchTracker&) const SK_OVERRIDE;
+
private:
GrBitmapTextGeoProc(GrColor, GrTexture* texture, const GrTextureParams& params,
bool useColorAttrib, bool opaqueVertexColors);
diff --git a/src/gpu/effects/GrDashingEffect.cpp b/src/gpu/effects/GrDashingEffect.cpp
index 1641d272fc..69e40eb315 100644
--- a/src/gpu/effects/GrDashingEffect.cpp
+++ b/src/gpu/effects/GrDashingEffect.cpp
@@ -441,6 +441,12 @@ bool GrDashingEffect::DrawDashLine(GrGpu* gpu, GrDrawTarget* target, GrDrawState
//////////////////////////////////////////////////////////////////////////////
class GLDashingCircleEffect;
+
+struct DashingCircleBatchTracker {
+ GrGPInput fInputColorType;
+ GrColor fColor;
+};
+
/*
* This effect will draw a dotted line (defined as a dashed lined with round caps and no on
* interval). The radius of the dots is given by the strokeWidth and the spacing by the DashInfo.
@@ -481,6 +487,10 @@ public:
virtual GrGLGeometryProcessor* createGLInstance(const GrBatchTracker&) const SK_OVERRIDE;
+ void initBatchTracker(GrBatchTracker* bt, const InitBT& init) const SK_OVERRIDE;
+
+ bool onCanMakeEqual(const GrBatchTracker&, const GrBatchTracker&) const SK_OVERRIDE;
+
private:
DashingCircleEffect(GrColor, GrPrimitiveEdgeType edgeType, const DashInfo& info,
SkScalar radius);
@@ -515,19 +525,22 @@ public:
GrProcessorKeyBuilder*);
virtual void setData(const GrGLProgramDataManager&,
- const GrGeometryProcessor&,
+ const GrPrimitiveProcessor&,
const GrBatchTracker&) SK_OVERRIDE;
private:
- GrGLProgramDataManager::UniformHandle fParamUniform;
- SkScalar fPrevRadius;
- SkScalar fPrevCenterX;
- SkScalar fPrevIntervalLength;
+ UniformHandle fParamUniform;
+ UniformHandle fColorUniform;
+ GrColor fColor;
+ SkScalar fPrevRadius;
+ SkScalar fPrevCenterX;
+ SkScalar fPrevIntervalLength;
typedef GrGLGeometryProcessor INHERITED;
};
GLDashingCircleEffect::GLDashingCircleEffect(const GrGeometryProcessor&,
const GrBatchTracker&) {
+ fColor = GrColor_ILLEGAL;
fPrevRadius = SK_ScalarMin;
fPrevCenterX = SK_ScalarMin;
fPrevIntervalLength = SK_ScalarMax;
@@ -535,6 +548,8 @@ GLDashingCircleEffect::GLDashingCircleEffect(const GrGeometryProcessor&,
void GLDashingCircleEffect::emitCode(const EmitArgs& args) {
const DashingCircleEffect& dce = args.fGP.cast<DashingCircleEffect>();
+ const DashingCircleBatchTracker local = args.fBT.cast<DashingCircleBatchTracker>();
+ GrGLGPBuilder* pb = args.fPB;
const char *paramName;
// The param uniforms, xyz, refer to circle radius - 0.5, cicles center x coord, and
// the total interval length of the dash.
@@ -548,6 +563,9 @@ void GLDashingCircleEffect::emitCode(const EmitArgs& args) {
args.fPB->addVarying("Coord", &v);
vsBuilder->codeAppendf("%s = %s;", v.vsOut(), dce.inCoord()->fName);
+ // Setup pass through color
+ this->setupColorPassThrough(pb, local.fInputColorType, args.fOutputColor, NULL, &fColorUniform);
+
// setup coord outputs
vsBuilder->codeAppendf("%s = %s;", vsBuilder->positionCoords(), dce.inPosition()->fName);
vsBuilder->codeAppendf("%s = %s;", vsBuilder->localCoords(), dce.inPosition()->fName);
@@ -575,8 +593,8 @@ void GLDashingCircleEffect::emitCode(const EmitArgs& args) {
}
void GLDashingCircleEffect::setData(const GrGLProgramDataManager& pdman,
- const GrGeometryProcessor& processor,
- const GrBatchTracker&) {
+ const GrPrimitiveProcessor& processor,
+ const GrBatchTracker& bt) {
const DashingCircleEffect& dce = processor.cast<DashingCircleEffect>();
SkScalar radius = dce.getRadius();
SkScalar centerX = dce.getCenterX();
@@ -587,14 +605,23 @@ void GLDashingCircleEffect::setData(const GrGLProgramDataManager& pdman,
fPrevCenterX = centerX;
fPrevIntervalLength = intervalLength;
}
+
+ const DashingCircleBatchTracker& local = bt.cast<DashingCircleBatchTracker>();
+ if (kUniform_GrGPInput == local.fInputColorType && local.fColor != fColor) {
+ GrGLfloat c[4];
+ GrColorToRGBAFloat(local.fColor, c);
+ pdman.set4fv(fColorUniform, 1, c);
+ fColor = local.fColor;
+ }
}
void GLDashingCircleEffect::GenKey(const GrGeometryProcessor& processor,
- const GrBatchTracker&,
+ const GrBatchTracker& bt,
const GrGLCaps&,
GrProcessorKeyBuilder* b) {
+ const DashingCircleBatchTracker& local = bt.cast<DashingCircleBatchTracker>();
const DashingCircleEffect& dce = processor.cast<DashingCircleEffect>();
- b->add32(dce.getEdgeType());
+ b->add32(dce.getEdgeType() << 16 | local.fInputColorType);
}
//////////////////////////////////////////////////////////////////////////////
@@ -649,6 +676,18 @@ bool DashingCircleEffect::onIsEqual(const GrGeometryProcessor& other) const {
fCenterX == dce.fCenterX);
}
+void DashingCircleEffect::initBatchTracker(GrBatchTracker* bt, const InitBT& init) const {
+ DashingCircleBatchTracker* local = bt->cast<DashingCircleBatchTracker>();
+ local->fInputColorType = GetColorInputType(&local->fColor, this->color(), init, false);
+}
+
+bool DashingCircleEffect::onCanMakeEqual(const GrBatchTracker& m, const GrBatchTracker& t) const {
+ const DashingCircleBatchTracker& mine = m.cast<DashingCircleBatchTracker>();
+ const DashingCircleBatchTracker& theirs = t.cast<DashingCircleBatchTracker>();
+ return CanCombineOutput(mine.fInputColorType, mine.fColor,
+ theirs.fInputColorType, theirs.fColor);
+}
+
GR_DEFINE_GEOMETRY_PROCESSOR_TEST(DashingCircleEffect);
GrGeometryProcessor* DashingCircleEffect::TestCreate(SkRandom* random,
@@ -673,6 +712,11 @@ GrGeometryProcessor* DashingCircleEffect::TestCreate(SkRandom* random,
class GLDashingLineEffect;
+struct DashingLineBatchTracker {
+ GrGPInput fInputColorType;
+ GrColor fColor;
+};
+
/*
* This effect will draw a dashed line. The width of the dash is given by the strokeWidth and the
* length and spacing by the DashInfo. Both of the previous two parameters are in device space.
@@ -711,6 +755,10 @@ public:
virtual GrGLGeometryProcessor* createGLInstance(const GrBatchTracker& bt) const SK_OVERRIDE;
+ void initBatchTracker(GrBatchTracker* bt, const InitBT& init) const SK_OVERRIDE;
+
+ bool onCanMakeEqual(const GrBatchTracker&, const GrBatchTracker&) const SK_OVERRIDE;
+
private:
DashingLineEffect(GrColor, GrPrimitiveEdgeType edgeType, const DashInfo& info,
SkScalar strokeWidth);
@@ -744,25 +792,30 @@ public:
GrProcessorKeyBuilder*);
virtual void setData(const GrGLProgramDataManager&,
- const GrGeometryProcessor&,
+ const GrPrimitiveProcessor&,
const GrBatchTracker&) SK_OVERRIDE;
private:
- GrGLProgramDataManager::UniformHandle fRectUniform;
- GrGLProgramDataManager::UniformHandle fIntervalUniform;
- SkRect fPrevRect;
- SkScalar fPrevIntervalLength;
+ GrColor fColor;
+ UniformHandle fRectUniform;
+ UniformHandle fIntervalUniform;
+ UniformHandle fColorUniform;
+ SkRect fPrevRect;
+ SkScalar fPrevIntervalLength;
typedef GrGLGeometryProcessor INHERITED;
};
GLDashingLineEffect::GLDashingLineEffect(const GrGeometryProcessor&,
const GrBatchTracker&) {
+ fColor = GrColor_ILLEGAL;
fPrevRect.fLeft = SK_ScalarNaN;
fPrevIntervalLength = SK_ScalarMax;
}
void GLDashingLineEffect::emitCode(const EmitArgs& args) {
const DashingLineEffect& de = args.fGP.cast<DashingLineEffect>();
+ const DashingLineBatchTracker& local = args.fBT.cast<DashingLineBatchTracker>();
+ GrGLGPBuilder* pb = args.fPB;
const char *rectName;
// The rect uniform's xyzw refer to (left + 0.5, top + 0.5, right - 0.5, bottom - 0.5),
// respectively.
@@ -784,6 +837,9 @@ void GLDashingLineEffect::emitCode(const EmitArgs& args) {
args.fPB->addVarying("Coord", &v);
vsBuilder->codeAppendf("%s = %s;", v.vsOut(), de.inCoord()->fName);
+ // Setup pass through color
+ this->setupColorPassThrough(pb, local.fInputColorType, args.fOutputColor, NULL, &fColorUniform);
+
// setup coord outputs
vsBuilder->codeAppendf("%s = %s;", vsBuilder->positionCoords(), de.inPosition()->fName);
vsBuilder->codeAppendf("%s = %s;", vsBuilder->localCoords(), de.inPosition()->fName);
@@ -818,8 +874,8 @@ void GLDashingLineEffect::emitCode(const EmitArgs& args) {
}
void GLDashingLineEffect::setData(const GrGLProgramDataManager& pdman,
- const GrGeometryProcessor& processor,
- const GrBatchTracker&) {
+ const GrPrimitiveProcessor& processor,
+ const GrBatchTracker& bt) {
const DashingLineEffect& de = processor.cast<DashingLineEffect>();
const SkRect& rect = de.getRect();
SkScalar intervalLength = de.getIntervalLength();
@@ -830,14 +886,23 @@ void GLDashingLineEffect::setData(const GrGLProgramDataManager& pdman,
fPrevRect = rect;
fPrevIntervalLength = intervalLength;
}
+
+ const DashingLineBatchTracker& local = bt.cast<DashingLineBatchTracker>();
+ if (kUniform_GrGPInput == local.fInputColorType && local.fColor != fColor) {
+ GrGLfloat c[4];
+ GrColorToRGBAFloat(local.fColor, c);
+ pdman.set4fv(fColorUniform, 1, c);
+ fColor = local.fColor;
+ }
}
void GLDashingLineEffect::GenKey(const GrGeometryProcessor& processor,
- const GrBatchTracker&,
+ const GrBatchTracker& bt,
const GrGLCaps&,
GrProcessorKeyBuilder* b) {
+ const DashingLineBatchTracker& local = bt.cast<DashingLineBatchTracker>();
const DashingLineEffect& de = processor.cast<DashingLineEffect>();
- b->add32(de.getEdgeType());
+ b->add32(de.getEdgeType() << 16 | local.fInputColorType);
}
//////////////////////////////////////////////////////////////////////////////
@@ -892,6 +957,18 @@ bool DashingLineEffect::onIsEqual(const GrGeometryProcessor& other) const {
fIntervalLength == de.fIntervalLength);
}
+void DashingLineEffect::initBatchTracker(GrBatchTracker* bt, const InitBT& init) const {
+ DashingLineBatchTracker* local = bt->cast<DashingLineBatchTracker>();
+ local->fInputColorType = GetColorInputType(&local->fColor, this->color(), init, false);
+}
+
+bool DashingLineEffect::onCanMakeEqual(const GrBatchTracker& m, const GrBatchTracker& t) const {
+ const DashingLineBatchTracker& mine = m.cast<DashingLineBatchTracker>();
+ const DashingLineBatchTracker& theirs = t.cast<DashingLineBatchTracker>();
+ return CanCombineOutput(mine.fInputColorType, mine.fColor,
+ theirs.fInputColorType, theirs.fColor);
+}
+
GR_DEFINE_GEOMETRY_PROCESSOR_TEST(DashingLineEffect);
GrGeometryProcessor* DashingLineEffect::TestCreate(SkRandom* random,
diff --git a/src/gpu/effects/GrDistanceFieldTextureEffect.cpp b/src/gpu/effects/GrDistanceFieldTextureEffect.cpp
index 66d06b6f70..cc0a80017b 100755
--- a/src/gpu/effects/GrDistanceFieldTextureEffect.cpp
+++ b/src/gpu/effects/GrDistanceFieldTextureEffect.cpp
@@ -18,11 +18,17 @@
// Assuming a radius of the diagonal of the fragment, hence a factor of sqrt(2)/2
#define SK_DistanceFieldAAFactor "0.7071"
+struct DistanceFieldBatchTracker {
+ GrGPInput fInputColorType;
+ GrColor fColor;
+};
+
class GrGLDistanceFieldTextureEffect : public GrGLGeometryProcessor {
public:
GrGLDistanceFieldTextureEffect(const GrGeometryProcessor&,
const GrBatchTracker&)
- : fTextureSize(SkISize::Make(-1,-1))
+ : fColor(GrColor_ILLEGAL)
+ , fTextureSize(SkISize::Make(-1,-1))
#ifdef SK_GAMMA_APPLY_TO_A8
, fLuminance(-1.0f)
#endif
@@ -31,7 +37,8 @@ public:
virtual void emitCode(const EmitArgs& args) SK_OVERRIDE {
const GrDistanceFieldTextureEffect& dfTexEffect =
args.fGP.cast<GrDistanceFieldTextureEffect>();
-
+ const DistanceFieldBatchTracker& local = args.fBT.cast<DistanceFieldBatchTracker>();
+ GrGLGPBuilder* pb = args.fPB;
GrGLGPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder();
SkAssertResult(fsBuilder->enableFeature(
GrGLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature));
@@ -41,10 +48,9 @@ public:
args.fPB->addVarying("TextureCoords", &v);
vsBuilder->codeAppendf("%s = %s;", v.vsOut(), dfTexEffect.inTextureCoords()->fName);
- // setup color attribute
- if(dfTexEffect.inColor()) {
- args.fPB->addPassThroughAttribute(dfTexEffect.inColor(), args.fOutputColor);
- }
+ // Setup pass through color
+ this->setupColorPassThrough(pb, local.fInputColorType, args.fOutputColor,
+ dfTexEffect.inColor(), &fColorUniform);
// setup position varying
vsBuilder->codeAppendf("%s = %s * vec3(%s, 1);", vsBuilder->glPosition(),
@@ -121,8 +127,8 @@ public:
}
virtual void setData(const GrGLProgramDataManager& pdman,
- const GrGeometryProcessor& proc,
- const GrBatchTracker&) SK_OVERRIDE {
+ const GrPrimitiveProcessor& proc,
+ const GrBatchTracker& bt) SK_OVERRIDE {
SkASSERT(fTextureSizeUni.isValid());
GrTexture* texture = proc.texture(0);
@@ -142,23 +148,34 @@ public:
fLuminance = luminance;
}
#endif
+
+ const DistanceFieldBatchTracker& local = bt.cast<DistanceFieldBatchTracker>();
+ if (kUniform_GrGPInput == local.fInputColorType && local.fColor != fColor) {
+ GrGLfloat c[4];
+ GrColorToRGBAFloat(local.fColor, c);
+ pdman.set4fv(fColorUniform, 1, c);
+ fColor = local.fColor;
+ }
}
static inline void GenKey(const GrGeometryProcessor& processor,
- const GrBatchTracker&,
+ const GrBatchTracker& bt,
const GrGLCaps&,
GrProcessorKeyBuilder* b) {
const GrDistanceFieldTextureEffect& dfTexEffect =
processor.cast<GrDistanceFieldTextureEffect>();
-
+ const DistanceFieldBatchTracker& local = bt.cast<DistanceFieldBatchTracker>();
b->add32(dfTexEffect.getFlags());
+ b->add32(local.fInputColorType);
}
private:
- GrGLProgramDataManager::UniformHandle fTextureSizeUni;
- SkISize fTextureSize;
- GrGLProgramDataManager::UniformHandle fLuminanceUni;
- float fLuminance;
+ GrColor fColor;
+ UniformHandle fColorUniform;
+ UniformHandle fTextureSizeUni;
+ SkISize fTextureSize;
+ UniformHandle fLuminanceUni;
+ float fLuminance;
typedef GrGLGeometryProcessor INHERITED;
};
@@ -221,6 +238,20 @@ GrDistanceFieldTextureEffect::createGLInstance(const GrBatchTracker& bt) const {
return SkNEW_ARGS(GrGLDistanceFieldTextureEffect, (*this, bt));
}
+void GrDistanceFieldTextureEffect::initBatchTracker(GrBatchTracker* bt, const InitBT& init) const {
+ DistanceFieldBatchTracker* local = bt->cast<DistanceFieldBatchTracker>();
+ local->fInputColorType = GetColorInputType(&local->fColor, this->color(), init,
+ SkToBool(fInColor));
+}
+
+bool GrDistanceFieldTextureEffect::onCanMakeEqual(const GrBatchTracker& m,
+ const GrBatchTracker& t) const {
+ const DistanceFieldBatchTracker& mine = m.cast<DistanceFieldBatchTracker>();
+ const DistanceFieldBatchTracker& theirs = t.cast<DistanceFieldBatchTracker>();
+ return CanCombineOutput(mine.fInputColorType, mine.fColor,
+ theirs.fInputColorType, theirs.fColor);
+}
+
///////////////////////////////////////////////////////////////////////////////
GR_DEFINE_GEOMETRY_PROCESSOR_TEST(GrDistanceFieldTextureEffect);
@@ -263,16 +294,24 @@ GrGeometryProcessor* GrDistanceFieldTextureEffect::TestCreate(SkRandom* random,
///////////////////////////////////////////////////////////////////////////////
+struct DistanceFieldNoGammaBatchTracker {
+ GrGPInput fInputColorType;
+ GrColor fColor;
+};
+
class GrGLDistanceFieldNoGammaTextureEffect : public GrGLGeometryProcessor {
public:
GrGLDistanceFieldNoGammaTextureEffect(const GrGeometryProcessor&,
const GrBatchTracker&)
- : fTextureSize(SkISize::Make(-1, -1)) {}
+ : fColor(GrColor_ILLEGAL), fTextureSize(SkISize::Make(-1, -1)) {}
virtual void emitCode(const EmitArgs& args) SK_OVERRIDE {
const GrDistanceFieldNoGammaTextureEffect& dfTexEffect =
args.fGP.cast<GrDistanceFieldNoGammaTextureEffect>();
+ const DistanceFieldNoGammaBatchTracker& local =
+ args.fBT.cast<DistanceFieldNoGammaBatchTracker>();
+ GrGLGPBuilder* pb = args.fPB;
GrGLGPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder();
SkAssertResult(fsBuilder->enableFeature(
GrGLFragmentShaderBuilder::kStandardDerivatives_GLSLFeature));
@@ -281,10 +320,9 @@ public:
GrGLVertToFrag v(kVec2f_GrSLType);
args.fPB->addVarying("TextureCoords", &v);
- // setup color attribute
- if(dfTexEffect.inColor()) {
- args.fPB->addPassThroughAttribute(dfTexEffect.inColor(), args.fOutputColor);
- }
+ // setup pass through color
+ this->setupColorPassThrough(pb, local.fInputColorType, args.fOutputColor,
+ dfTexEffect.inColor(), &fColorUniform);
vsBuilder->codeAppendf("%s = %s;", v.vsOut(), dfTexEffect.inTextureCoords()->fName);
@@ -348,8 +386,8 @@ public:
}
virtual void setData(const GrGLProgramDataManager& pdman,
- const GrGeometryProcessor& proc,
- const GrBatchTracker&) SK_OVERRIDE {
+ const GrPrimitiveProcessor& proc,
+ const GrBatchTracker& bt) SK_OVERRIDE {
SkASSERT(fTextureSizeUni.isValid());
GrTexture* texture = proc.texture(0);
@@ -360,21 +398,33 @@ public:
SkIntToScalar(fTextureSize.width()),
SkIntToScalar(fTextureSize.height()));
}
+
+ const DistanceFieldNoGammaBatchTracker& local = bt.cast<DistanceFieldNoGammaBatchTracker>();
+ if (kUniform_GrGPInput == local.fInputColorType && local.fColor != fColor) {
+ GrGLfloat c[4];
+ GrColorToRGBAFloat(local.fColor, c);
+ pdman.set4fv(fColorUniform, 1, c);
+ fColor = local.fColor;
+ }
}
static inline void GenKey(const GrGeometryProcessor& proc,
- const GrBatchTracker&,
+ const GrBatchTracker& bt,
const GrGLCaps&,
GrProcessorKeyBuilder* b) {
const GrDistanceFieldNoGammaTextureEffect& dfTexEffect =
proc.cast<GrDistanceFieldNoGammaTextureEffect>();
+ const DistanceFieldNoGammaBatchTracker& local = bt.cast<DistanceFieldNoGammaBatchTracker>();
b->add32(dfTexEffect.getFlags());
+ b->add32(local.fInputColorType);
}
private:
- GrGLProgramDataManager::UniformHandle fTextureSizeUni;
- SkISize fTextureSize;
+ UniformHandle fColorUniform;
+ UniformHandle fTextureSizeUni;
+ GrColor fColor;
+ SkISize fTextureSize;
typedef GrGLGeometryProcessor INHERITED;
};
@@ -424,6 +474,21 @@ GrDistanceFieldNoGammaTextureEffect::createGLInstance(const GrBatchTracker& bt)
return SkNEW_ARGS(GrGLDistanceFieldNoGammaTextureEffect, (*this, bt));
}
+void GrDistanceFieldNoGammaTextureEffect::initBatchTracker(GrBatchTracker* bt,
+ const InitBT& init) const {
+ DistanceFieldNoGammaBatchTracker* local = bt->cast<DistanceFieldNoGammaBatchTracker>();
+ local->fInputColorType = GetColorInputType(&local->fColor, this->color(), init,
+ SkToBool(fInColor));
+}
+
+bool GrDistanceFieldNoGammaTextureEffect::onCanMakeEqual(const GrBatchTracker& m,
+ const GrBatchTracker& t) const {
+ const DistanceFieldNoGammaBatchTracker& mine = m.cast<DistanceFieldNoGammaBatchTracker>();
+ const DistanceFieldNoGammaBatchTracker& theirs = t.cast<DistanceFieldNoGammaBatchTracker>();
+ return CanCombineOutput(mine.fInputColorType, mine.fColor,
+ theirs.fInputColorType, theirs.fColor);
+}
+
///////////////////////////////////////////////////////////////////////////////
GR_DEFINE_GEOMETRY_PROCESSOR_TEST(GrDistanceFieldNoGammaTextureEffect);
@@ -453,22 +518,34 @@ GrGeometryProcessor* GrDistanceFieldNoGammaTextureEffect::TestCreate(SkRandom* r
///////////////////////////////////////////////////////////////////////////////
+struct DistanceFieldLCDBatchTracker {
+ GrGPInput fInputColorType;
+ GrColor fColor;
+};
+
class GrGLDistanceFieldLCDTextureEffect : public GrGLGeometryProcessor {
public:
GrGLDistanceFieldLCDTextureEffect(const GrGeometryProcessor&,
const GrBatchTracker&)
- : fTextureSize(SkISize::Make(-1,-1))
+ : fColor(GrColor_ILLEGAL)
+ , fTextureSize(SkISize::Make(-1,-1))
, fTextColor(GrColor_ILLEGAL) {}
virtual void emitCode(const EmitArgs& args) SK_OVERRIDE {
const GrDistanceFieldLCDTextureEffect& dfTexEffect =
args.fGP.cast<GrDistanceFieldLCDTextureEffect>();
+ const DistanceFieldLCDBatchTracker& local = args.fBT.cast<DistanceFieldLCDBatchTracker>();
+ GrGLGPBuilder* pb = args.fPB;
GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder();
GrGLVertToFrag v(kVec2f_GrSLType);
args.fPB->addVarying("TextureCoords", &v);
vsBuilder->codeAppendf("%s = %s;", v.vsOut(), dfTexEffect.inTextureCoords()->fName);
+ // setup pass through color
+ this->setupColorPassThrough(pb, local.fInputColorType, args.fOutputColor, NULL,
+ &fColorUniform);
+
// setup coord outputs
vsBuilder->codeAppendf("%s = %s;", vsBuilder->positionCoords(),
dfTexEffect.inPosition()->fName);
@@ -588,8 +665,8 @@ public:
}
virtual void setData(const GrGLProgramDataManager& pdman,
- const GrGeometryProcessor& processor,
- const GrBatchTracker&) SK_OVERRIDE {
+ const GrPrimitiveProcessor& processor,
+ const GrBatchTracker& bt) SK_OVERRIDE {
SkASSERT(fTextureSizeUni.isValid());
SkASSERT(fTextColorUni.isValid());
@@ -618,23 +695,35 @@ public:
GrColorUnpackB(textColor) * ONE_OVER_255);
fTextColor = textColor;
}
+
+ const DistanceFieldLCDBatchTracker& local = bt.cast<DistanceFieldLCDBatchTracker>();
+ if (kUniform_GrGPInput == local.fInputColorType && local.fColor != fColor) {
+ GrGLfloat c[4];
+ GrColorToRGBAFloat(local.fColor, c);
+ pdman.set4fv(fColorUniform, 1, c);
+ fColor = local.fColor;
+ }
}
static inline void GenKey(const GrGeometryProcessor& processor,
- const GrBatchTracker&,
+ const GrBatchTracker& bt,
const GrGLCaps&,
GrProcessorKeyBuilder* b) {
const GrDistanceFieldLCDTextureEffect& dfTexEffect =
processor.cast<GrDistanceFieldLCDTextureEffect>();
+ const DistanceFieldLCDBatchTracker& local = bt.cast<DistanceFieldLCDBatchTracker>();
b->add32(dfTexEffect.getFlags());
+ b->add32(local.fInputColorType);
}
private:
- GrGLProgramDataManager::UniformHandle fTextureSizeUni;
- SkISize fTextureSize;
- GrGLProgramDataManager::UniformHandle fTextColorUni;
- SkColor fTextColor;
+ GrColor fColor;
+ UniformHandle fColorUniform;
+ UniformHandle fTextureSizeUni;
+ SkISize fTextureSize;
+ UniformHandle fTextColorUni;
+ SkColor fTextColor;
typedef GrGLGeometryProcessor INHERITED;
};
@@ -683,6 +772,20 @@ GrDistanceFieldLCDTextureEffect::createGLInstance(const GrBatchTracker& bt) cons
return SkNEW_ARGS(GrGLDistanceFieldLCDTextureEffect, (*this, bt));
}
+void GrDistanceFieldLCDTextureEffect::initBatchTracker(GrBatchTracker* bt,
+ const InitBT& init) const {
+ DistanceFieldLCDBatchTracker* local = bt->cast<DistanceFieldLCDBatchTracker>();
+ local->fInputColorType = GetColorInputType(&local->fColor, this->color(), init, false);
+}
+
+bool GrDistanceFieldLCDTextureEffect::onCanMakeEqual(const GrBatchTracker& m,
+ const GrBatchTracker& t) const {
+ const DistanceFieldLCDBatchTracker& mine = m.cast<DistanceFieldLCDBatchTracker>();
+ const DistanceFieldLCDBatchTracker& theirs = t.cast<DistanceFieldLCDBatchTracker>();
+ return CanCombineOutput(mine.fInputColorType, mine.fColor,
+ theirs.fInputColorType, theirs.fColor);
+}
+
///////////////////////////////////////////////////////////////////////////////
GR_DEFINE_GEOMETRY_PROCESSOR_TEST(GrDistanceFieldLCDTextureEffect);
diff --git a/src/gpu/effects/GrDistanceFieldTextureEffect.h b/src/gpu/effects/GrDistanceFieldTextureEffect.h
index 288da5c760..5650cfc70a 100644
--- a/src/gpu/effects/GrDistanceFieldTextureEffect.h
+++ b/src/gpu/effects/GrDistanceFieldTextureEffect.h
@@ -79,6 +79,10 @@ public:
virtual GrGLGeometryProcessor* createGLInstance(const GrBatchTracker& bt) const SK_OVERRIDE;
+ void initBatchTracker(GrBatchTracker* bt, const InitBT& init) const SK_OVERRIDE;
+
+ bool onCanMakeEqual(const GrBatchTracker&, const GrBatchTracker&) const SK_OVERRIDE;
+
private:
GrDistanceFieldTextureEffect(GrColor, GrTexture* texture, const GrTextureParams& params,
#ifdef SK_GAMMA_APPLY_TO_A8
@@ -135,6 +139,10 @@ public:
virtual GrGLGeometryProcessor* createGLInstance(const GrBatchTracker& bt) const SK_OVERRIDE;
+ void initBatchTracker(GrBatchTracker* bt, const InitBT& init) const SK_OVERRIDE;
+
+ bool onCanMakeEqual(const GrBatchTracker&, const GrBatchTracker&) const SK_OVERRIDE;
+
private:
GrDistanceFieldNoGammaTextureEffect(GrColor, GrTexture* texture, const GrTextureParams& params,
uint32_t flags, bool opaqueVertexColors);
@@ -184,6 +192,10 @@ public:
virtual GrGLGeometryProcessor* createGLInstance(const GrBatchTracker& bt) const SK_OVERRIDE;
+ void initBatchTracker(GrBatchTracker* bt, const InitBT& init) const SK_OVERRIDE;
+
+ bool onCanMakeEqual(const GrBatchTracker&, const GrBatchTracker&) const SK_OVERRIDE;
+
private:
GrDistanceFieldLCDTextureEffect(GrColor, GrTexture* texture, const GrTextureParams& params,
GrTexture* gamma, const GrTextureParams& gammaParams,
diff --git a/src/gpu/effects/GrPorterDuffXferProcessor.cpp b/src/gpu/effects/GrPorterDuffXferProcessor.cpp
index b8259164fd..bf48379bda 100644
--- a/src/gpu/effects/GrPorterDuffXferProcessor.cpp
+++ b/src/gpu/effects/GrPorterDuffXferProcessor.cpp
@@ -66,11 +66,28 @@ public:
}
}
- fsBuilder->codeAppendf("%s = %s * %s;", args.fOutputPrimary, args.fInputColor,
- args.fInputCoverage);
- if (GrPorterDuffXferProcessor::kCombineWithDst_PrimaryOutputType == xp.primaryOutputType()){
- fsBuilder->codeAppendf("%s += (vec4(1.0) - %s) * %s;", args.fOutputPrimary,
- args.fInputCoverage, fsBuilder->dstColor());
+ switch (xp.primaryOutputType()) {
+ case GrPorterDuffXferProcessor::kNone_PrimaryOutputType:
+ fsBuilder->codeAppendf("%s = vec4(0);", args.fOutputPrimary);
+ break;
+ case GrPorterDuffXferProcessor::kColor_PrimaryOutputType:
+ fsBuilder->codeAppendf("%s = %s;", args.fOutputPrimary, args.fInputColor);
+ break;
+ case GrPorterDuffXferProcessor::kCoverage_PrimaryOutputType:
+ fsBuilder->codeAppendf("%s = %s;", args.fOutputPrimary, args.fInputCoverage);
+ break;
+ case GrPorterDuffXferProcessor::kModulate_PrimaryOutputType:
+ case GrPorterDuffXferProcessor::kCombineWithDst_PrimaryOutputType:
+ fsBuilder->codeAppendf("%s = %s * %s;", args.fOutputPrimary, args.fInputColor,
+ args.fInputCoverage);
+ if (GrPorterDuffXferProcessor::kCombineWithDst_PrimaryOutputType ==
+ xp.primaryOutputType()){
+ fsBuilder->codeAppendf("%s += (vec4(1.0) - %s) * %s;", args.fOutputPrimary,
+ args.fInputCoverage, fsBuilder->dstColor());
+ }
+ break;
+ default:
+ SkFAIL("Unexpected Primary Output");
}
}
@@ -122,7 +139,6 @@ GrPorterDuffXferProcessor::getOptimizations(const GrProcOptInfo& colorPOI,
bool colorWriteDisabled,
bool doesStencilWrite,
GrColor* overrideColor,
- uint8_t* overrideCoverage,
const GrDrawTargetCaps& caps) {
GrXferProcessor::OptFlags optFlags;
// Optimizations when doing RGB Coverage
@@ -139,9 +155,7 @@ GrPorterDuffXferProcessor::getOptimizations(const GrProcOptInfo& colorPOI,
coveragePOI,
isCoverageDrawing,
colorWriteDisabled,
- doesStencilWrite,
- overrideColor,
- overrideCoverage);
+ doesStencilWrite);
}
this->calcOutputTypes(optFlags, caps, isCoverageDrawing || coveragePOI.isSolidWhite(),
colorPOI.readsDst() || coveragePOI.readsDst());
@@ -151,6 +165,19 @@ GrPorterDuffXferProcessor::getOptimizations(const GrProcOptInfo& colorPOI,
void GrPorterDuffXferProcessor::calcOutputTypes(GrXferProcessor::OptFlags optFlags,
const GrDrawTargetCaps& caps,
bool hasSolidCoverage, bool readsDst) {
+ if (optFlags & kIgnoreColor_OptFlag) {
+ if (optFlags & kIgnoreCoverage_OptFlag) {
+ fPrimaryOutputType = kNone_PrimaryOutputType;
+ return;
+ } else {
+ fPrimaryOutputType = kCoverage_PrimaryOutputType;
+ return;
+ }
+ } else if (optFlags & kIgnoreCoverage_OptFlag) {
+ fPrimaryOutputType = kColor_PrimaryOutputType;
+ return;
+ }
+
// If we do have coverage determine whether it matters. Dual source blending is expensive so
// we don't do it if we are doing coverage drawing. If we aren't then We always do dual source
// blending if we have any effective coverage stages OR the geometry processor doesn't emits
@@ -183,9 +210,7 @@ GrPorterDuffXferProcessor::internalGetOptimizations(const GrProcOptInfo& colorPO
const GrProcOptInfo& coveragePOI,
bool isCoverageDrawing,
bool colorWriteDisabled,
- bool doesStencilWrite,
- GrColor* overrideColor,
- uint8_t* overrideCoverage) {
+ bool doesStencilWrite) {
if (colorWriteDisabled) {
fSrcBlend = kZero_GrBlendCoeff;
fDstBlend = kOne_GrBlendCoeff;
@@ -211,8 +236,7 @@ GrPorterDuffXferProcessor::internalGetOptimizations(const GrProcOptInfo& colorPO
// (0,1).
if ((kZero_GrBlendCoeff == fSrcBlend && dstCoeffIsOne)) {
if (doesStencilWrite) {
- *overrideColor = 0xffffffff;
- return GrXferProcessor::kClearColorStages_OptFlag |
+ return GrXferProcessor::kIgnoreColor_OptFlag |
GrXferProcessor::kSetCoverageDrawing_OptFlag;
} else {
fDstBlend = kOne_GrBlendCoeff;
@@ -234,10 +258,8 @@ GrPorterDuffXferProcessor::internalGetOptimizations(const GrProcOptInfo& colorPO
// or blend, just write transparent black into the dst.
fSrcBlend = kOne_GrBlendCoeff;
fDstBlend = kZero_GrBlendCoeff;
- *overrideColor = 0;
- *overrideCoverage = 0xff;
- return GrXferProcessor::kClearColorStages_OptFlag |
- GrXferProcessor::kClearCoverageStages_OptFlag;
+ return GrXferProcessor::kIgnoreColor_OptFlag |
+ GrXferProcessor::kIgnoreCoverage_OptFlag;
}
}
} else if (isCoverageDrawing) {
@@ -255,8 +277,7 @@ GrPorterDuffXferProcessor::internalGetOptimizations(const GrProcOptInfo& colorPO
// the dst coeff is effectively zero so blend works out to:
// (c)(0)D + (1-c)D = (1-c)D.
fDstBlend = kISA_GrBlendCoeff;
- *overrideColor = 0xffffffff;
- return GrXferProcessor::kClearColorStages_OptFlag |
+ return GrXferProcessor::kIgnoreColor_OptFlag |
GrXferProcessor::kSetCoverageDrawing_OptFlag;
} else if (srcAIsOne) {
// the dst coeff is effectively zero so blend works out to:
diff --git a/src/gpu/gl/GrGLGeometryProcessor.h b/src/gpu/gl/GrGLGeometryProcessor.h
index aa58cd3d97..a9f5ead4ac 100644
--- a/src/gpu/gl/GrGLGeometryProcessor.h
+++ b/src/gpu/gl/GrGLGeometryProcessor.h
@@ -23,10 +23,12 @@ public:
GrGLGeometryProcessor() {}
virtual ~GrGLGeometryProcessor() {}
+ typedef GrGLProgramDataManager::UniformHandle UniformHandle;
typedef GrGLProcessor::TextureSamplerArray TextureSamplerArray;
+
struct EmitArgs {
EmitArgs(GrGLGPBuilder* pb,
- const GrGeometryProcessor& gp,
+ const GrPrimitiveProcessor& gp,
const GrBatchTracker& bt,
const char* outputColor,
const char* outputCoverage,
@@ -38,12 +40,13 @@ public:
, fOutputCoverage(outputCoverage)
, fSamplers(samplers) {}
GrGLGPBuilder* fPB;
- const GrGeometryProcessor& fGP;
+ const GrPrimitiveProcessor& fGP;
const GrBatchTracker& fBT;
const char* fOutputColor;
const char* fOutputCoverage;
const TextureSamplerArray& fSamplers;
};
+
/**
* This is similar to emitCode() in the base class, except it takes a full shader builder.
* This allows the effect subclass to emit vertex code.
@@ -56,9 +59,21 @@ public:
parameter is guaranteed to be of the same type that created this GrGLGeometryProcessor and
to have an identical processor key as the one that created this GrGLGeometryProcessor. */
virtual void setData(const GrGLProgramDataManager&,
- const GrGeometryProcessor&,
+ const GrPrimitiveProcessor&,
const GrBatchTracker&) = 0;
+protected:
+ /** a helper which can setup vertex, constant, or uniform color depending on inputType.
+ * This function will only do the minimum required to emit the correct shader code. If
+ * inputType == attribute, then colorAttr must not be NULL. Likewise, if inputType == Uniform
+ * then colorUniform must not be NULL.
+ */
+ void setupColorPassThrough(GrGLGPBuilder* pb,
+ GrGPInput inputType,
+ const char* inputName,
+ const GrGeometryProcessor::GrAttribute* colorAttr,
+ UniformHandle* colorUniform);
+
private:
typedef GrGLProcessor INHERITED;
};
diff --git a/src/gpu/gl/GrGLProgram.cpp b/src/gpu/gl/GrGLProgram.cpp
index da687c1eb6..7d5b0d7532 100644
--- a/src/gpu/gl/GrGLProgram.cpp
+++ b/src/gpu/gl/GrGLProgram.cpp
@@ -131,11 +131,6 @@ void GrGLProgram::bindTextures(const GrGLInstalledProc* ip, const GrProcessor& p
///////////////////////////////////////////////////////////////////////////////
void GrGLProgram::setData(const GrOptDrawState& optState) {
- GrColor color = optState.getColor();
- uint8_t coverage = optState.getCoverage();
-
- this->setColor(optState, color);
- this->setCoverage(optState, coverage);
this->setMatrixAndRenderTargetHeight(optState);
const GrDeviceCoordTexture* dstCopy = optState.getDstCopy();
@@ -162,13 +157,11 @@ 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();
- const GrBatchTracker& bt = optState.getBatchTracker();
- fGeometryProcessor->fGLProc->setData(fProgramDataManager, gp, bt);
- this->bindTextures(fGeometryProcessor, gp);
- }
+ const GrPrimitiveProcessor& primProc = *optState.getPrimitiveProcessor();
+ const GrBatchTracker& bt = optState.getBatchTracker();
+ fGeometryProcessor->fGLProc->setData(fProgramDataManager, primProc, bt);
+ this->bindTextures(fGeometryProcessor, primProc);
+
if (fXferProcessor.get()) {
const GrXferProcessor& xp = *optState.getXferProcessor();
fXferProcessor->fGLProc->setData(fProgramDataManager, xp);
@@ -209,51 +202,6 @@ void GrGLProgram::didSetData(GrGpu::DrawType drawType) {
SkASSERT(!GrGpu::IsPathRenderingDrawType(drawType));
}
-void GrGLProgram::setColor(const GrOptDrawState& optState, GrColor color) {
- const GrProgramDesc::KeyHeader& header = fDesc.header();
- switch (header.fColorInput) {
- case GrProgramDesc::kAttribute_ColorInput:
- // Attribute case is handled in GrGpuGL::setupGeometry
- break;
- case GrProgramDesc::kUniform_ColorInput:
- if (fColor != color && fBuiltinUniformHandles.fColorUni.isValid()) {
- // OpenGL ES doesn't support unsigned byte varieties of glUniform
- GrGLfloat c[4];
- GrColorToRGBAFloat(color, c);
- fProgramDataManager.set4fv(fBuiltinUniformHandles.fColorUni, 1, c);
- fColor = color;
- }
- break;
- case GrProgramDesc::kAllOnes_ColorInput:
- // Handled by shader creation
- break;
- default:
- SkFAIL("Unexpected color type.");
- }
-}
-
-void GrGLProgram::setCoverage(const GrOptDrawState& optState, uint8_t coverage) {
- const GrProgramDesc::KeyHeader& header = fDesc.header();
- switch (header.fCoverageInput) {
- case GrProgramDesc::kAttribute_ColorInput:
- // Attribute case is handled in GrGpuGL::setupGeometry
- break;
- case GrProgramDesc::kUniform_ColorInput:
- if (fCoverage != coverage) {
- // OpenGL ES doesn't support unsigned byte varieties of glUniform
- GrGLfloat c = GrNormalizeByteToFloat(coverage);
- fProgramDataManager.set1f(fBuiltinUniformHandles.fCoverageUni, c);
- fCoverage = coverage;
- }
- break;
- case GrProgramDesc::kAllOnes_ColorInput:
- // Handled by shader creation
- break;
- default:
- SkFAIL("Unexpected coverage type.");
- }
-}
-
void GrGLProgram::setMatrixAndRenderTargetHeight(const GrOptDrawState& optState) {
// Load the RT height uniform if it is needed to y-flip gl_FragCoord.
if (fBuiltinUniformHandles.fRTHeightUni.isValid() &&
@@ -296,9 +244,10 @@ GrGLNvprProgramBase::GrGLNvprProgramBase(GrGpuGL* gpu,
const BuiltinUniformHandles& builtinUniforms,
GrGLuint programID,
const UniformInfoArray& uniforms,
+ GrGLInstalledGeoProc* primProc,
GrGLInstalledXferProc* xferProcessor,
GrGLInstalledFragProcs* fragmentProcessors)
- : INHERITED(gpu, desc, builtinUniforms, programID, uniforms, NULL,
+ : INHERITED(gpu, desc, builtinUniforms, programID, uniforms, primProc,
xferProcessor, fragmentProcessors) {
}
@@ -317,10 +266,11 @@ GrGLNvprProgram::GrGLNvprProgram(GrGpuGL* gpu,
const BuiltinUniformHandles& builtinUniforms,
GrGLuint programID,
const UniformInfoArray& uniforms,
+ GrGLInstalledGeoProc* primProc,
GrGLInstalledXferProc* xferProcessor,
GrGLInstalledFragProcs* fragmentProcessors,
const SeparableVaryingInfoArray& separableVaryings)
- : INHERITED(gpu, desc, builtinUniforms, programID, uniforms,
+ : INHERITED(gpu, desc, builtinUniforms, programID, uniforms, primProc,
xferProcessor, fragmentProcessors) {
int count = separableVaryings.count();
fVaryings.push_back_n(count);
@@ -369,10 +319,11 @@ GrGLLegacyNvprProgram::GrGLLegacyNvprProgram(GrGpuGL* gpu,
const BuiltinUniformHandles& builtinUniforms,
GrGLuint programID,
const UniformInfoArray& uniforms,
+ GrGLInstalledGeoProc* primProc,
GrGLInstalledXferProc* xp,
GrGLInstalledFragProcs* fps,
int texCoordSetCnt)
- : INHERITED(gpu, desc, builtinUniforms, programID, uniforms, xp, fps)
+ : INHERITED(gpu, desc, builtinUniforms, programID, uniforms, primProc, xp, fps)
, fTexCoordSetCnt(texCoordSetCnt) {
}
diff --git a/src/gpu/gl/GrGLProgram.h b/src/gpu/gl/GrGLProgram.h
index ea8be85251..bada8fdb30 100644
--- a/src/gpu/gl/GrGLProgram.h
+++ b/src/gpu/gl/GrGLProgram.h
@@ -148,14 +148,6 @@ protected:
void initSamplerUniforms();
void initSamplers(GrGLInstalledProc*, int* texUnitIdx);
- // Helper for setData(). Makes GL calls to specify the initial color when there is not
- // per-vertex colors.
- void setColor(const GrOptDrawState&, GrColor color);
-
- // Helper for setData(). Makes GL calls to specify the initial coverage when there is not
- // per-vertex coverages.
- void setCoverage(const GrOptDrawState&, uint8_t coverage);
-
// A templated helper to loop over effects, set the transforms(via subclass) and bind textures
void setFragmentData(const GrOptDrawState&);
virtual void setTransformData(const GrPendingFragmentStage&, GrGLInstalledFragProc*);
@@ -207,6 +199,7 @@ protected:
const BuiltinUniformHandles&,
GrGLuint programID,
const UniformInfoArray&,
+ GrGLInstalledGeoProc*,
GrGLInstalledXferProc* xferProcessor,
GrGLInstalledFragProcs* fragmentProcessors);
virtual void onSetMatrixAndRenderTargetHeight(const GrOptDrawState&);
@@ -226,6 +219,7 @@ private:
const BuiltinUniformHandles&,
GrGLuint programID,
const UniformInfoArray&,
+ GrGLInstalledGeoProc*,
GrGLInstalledXferProc* xferProcessor,
GrGLInstalledFragProcs* fragmentProcessors,
const SeparableVaryingInfoArray& separableVaryings);
@@ -256,6 +250,7 @@ private:
const BuiltinUniformHandles&,
GrGLuint programID,
const UniformInfoArray&,
+ GrGLInstalledGeoProc*,
GrGLInstalledXferProc* xp,
GrGLInstalledFragProcs* fps,
int texCoordSetCnt);
diff --git a/src/gpu/gl/GrGLProgramDesc.cpp b/src/gpu/gl/GrGLProgramDesc.cpp
index 2476c5532c..c5c31d33ae 100644
--- a/src/gpu/gl/GrGLProgramDesc.cpp
+++ b/src/gpu/gl/GrGLProgramDesc.cpp
@@ -40,19 +40,6 @@ static bool swizzle_requires_alpha_remapping(const GrGLCaps& caps,
return false;
}
-static uint32_t gen_attrib_key(const GrGeometryProcessor& proc) {
- uint32_t key = 0;
-
- const GrGeometryProcessor::VertexAttribArray& vars = proc.getAttribs();
- int numAttributes = vars.count();
- SkASSERT(numAttributes <= GrGeometryProcessor::kMaxVertexAttribs);
- for (int a = 0; a < numAttributes; ++a) {
- uint32_t value = 1 << a;
- key |= value;
- }
- return key;
-}
-
/**
* The key for an individual coord transform is made up of a matrix type, a precision, and a bit
* that indicates the source of the input coords.
@@ -131,7 +118,6 @@ static uint32_t gen_texture_key(const GrProcessor& proc, const GrGLCaps& caps) {
static bool get_meta_key(const GrProcessor& proc,
const GrGLCaps& caps,
uint32_t transformKey,
- uint32_t attribKey,
GrProcessorKeyBuilder* b) {
size_t processorKeySize = b->size();
uint32_t textureKey = gen_texture_key(proc, caps);
@@ -158,9 +144,6 @@ bool GrGLProgramDescBuilder::Build(const GrOptDrawState& optState,
GrGpu::DrawType drawType,
GrGpuGL* gpu,
GrProgramDesc* desc) {
- bool inputColorIsUsed = descInfo.fInputColorIsUsed;
- bool inputCoverageIsUsed = descInfo.fInputCoverageIsUsed;
-
// The descriptor is used as a cache key. Thus when a field of the
// descriptor will not affect program generation (because of the attribute
// bindings in use or other descriptor field settings) it should be set
@@ -173,33 +156,29 @@ bool GrGLProgramDescBuilder::Build(const GrOptDrawState& optState,
desc->fKey.reset();
desc->fKey.push_back_n(kProcessorKeysOffset);
- // We can only have one effect which touches the vertex shader
- if (optState.hasGeometryProcessor()) {
- const GrGeometryProcessor& gp = *optState.getGeometryProcessor();
- GrProcessorKeyBuilder b(&desc->fKey);
- gp.getGLProcessorKey(optState.getBatchTracker(), gpu->glCaps(), &b);
- if (!get_meta_key(gp, gpu->glCaps(), 0, gen_attrib_key(gp), &b)) {
- desc->fKey.reset();
- return false;
- }
+ GrProcessorKeyBuilder b(&desc->fKey);
+
+ const GrPrimitiveProcessor& primProc = *optState.getPrimitiveProcessor();
+ primProc.getGLProcessorKey(optState.getBatchTracker(), gpu->glCaps(), &b);
+ if (!get_meta_key(primProc, gpu->glCaps(), 0, &b)) {
+ desc->fKey.reset();
+ return false;
}
for (int s = 0; s < optState.numFragmentStages(); ++s) {
const GrPendingFragmentStage& fps = optState.getFragmentStage(s);
const GrFragmentProcessor& fp = *fps.getProcessor();
- GrProcessorKeyBuilder b(&desc->fKey);
fp.getGLProcessorKey(gpu->glCaps(), &b);
if (!get_meta_key(fp, gpu->glCaps(),
- gen_transform_key(fps, requiresLocalCoordAttrib), 0, &b)) {
+ gen_transform_key(fps, requiresLocalCoordAttrib), &b)) {
desc->fKey.reset();
return false;
}
}
const GrXferProcessor& xp = *optState.getXferProcessor();
- GrProcessorKeyBuilder b(&desc->fKey);
xp.getGLProcessorKey(gpu->glCaps(), &b);
- if (!get_meta_key(xp, gpu->glCaps(), 0, 0, &b)) {
+ if (!get_meta_key(xp, gpu->glCaps(), 0, &b)) {
desc->fKey.reset();
return false;
}
@@ -212,8 +191,6 @@ bool GrGLProgramDescBuilder::Build(const GrOptDrawState& optState,
// make sure any padding in the header is zeroed.
memset(header, 0, kHeaderSize);
- header->fHasGeometryProcessor = optState.hasGeometryProcessor();
-
bool isPathRendering = GrGpu::IsPathRenderingDrawType(drawType);
if (gpu->caps()->pathRenderingSupport() && isPathRendering) {
header->fUseNvpr = true;
@@ -222,30 +199,6 @@ bool GrGLProgramDescBuilder::Build(const GrOptDrawState& optState,
header->fUseNvpr = false;
}
- bool hasUniformColor = inputColorIsUsed && (isPathRendering || !descInfo.fHasVertexColor);
-
- if (!inputColorIsUsed) {
- header->fColorInput = GrProgramDesc::kAllOnes_ColorInput;
- } else if (hasUniformColor) {
- header->fColorInput = GrProgramDesc::kUniform_ColorInput;
- } else {
- header->fColorInput = GrProgramDesc::kAttribute_ColorInput;
- SkASSERT(!header->fUseNvpr);
- }
-
- bool hasVertexCoverage = !isPathRendering && descInfo.fHasVertexCoverage;
-
- bool covIsSolidWhite = !hasVertexCoverage && 0xffffffff == optState.getCoverageColor();
-
- if (covIsSolidWhite || !inputCoverageIsUsed) {
- header->fCoverageInput = GrProgramDesc::kAllOnes_ColorInput;
- } else if (!hasVertexCoverage) {
- header->fCoverageInput = GrProgramDesc::kUniform_ColorInput;
- } else {
- header->fCoverageInput = GrProgramDesc::kAttribute_ColorInput;
- SkASSERT(!header->fUseNvpr);
- }
-
if (descInfo.fReadsDst) {
const GrDeviceCoordTexture* dstCopy = optState.getDstCopy();
SkASSERT(dstCopy || gpu->caps()->dstReadInShaderSupport());
diff --git a/src/gpu/gl/builders/GrGLLegacyNvprProgramBuilder.cpp b/src/gpu/gl/builders/GrGLLegacyNvprProgramBuilder.cpp
index b90bab2c1d..696c9a5c7f 100644
--- a/src/gpu/gl/builders/GrGLLegacyNvprProgramBuilder.cpp
+++ b/src/gpu/gl/builders/GrGLLegacyNvprProgramBuilder.cpp
@@ -45,6 +45,6 @@ void GrGLLegacyNvprProgramBuilder::emitTransforms(const GrPendingFragmentStage&
GrGLProgram* GrGLLegacyNvprProgramBuilder::createProgram(GrGLuint programID) {
return SkNEW_ARGS(GrGLLegacyNvprProgram, (fGpu, fDesc, fUniformHandles, programID, fUniforms,
- fXferProcessor, fFragmentProcessors.get(),
+ fGeometryProcessor, fXferProcessor, fFragmentProcessors.get(),
fTexCoordSetCnt));
}
diff --git a/src/gpu/gl/builders/GrGLNvprProgramBuilder.cpp b/src/gpu/gl/builders/GrGLNvprProgramBuilder.cpp
index ba19275f6f..063526d464 100644
--- a/src/gpu/gl/builders/GrGLNvprProgramBuilder.cpp
+++ b/src/gpu/gl/builders/GrGLNvprProgramBuilder.cpp
@@ -72,6 +72,7 @@ GrGLProgram* GrGLNvprProgramBuilder::createProgram(GrGLuint programID) {
// building
this->resolveSeparableVaryings(programID);
return SkNEW_ARGS(GrGLNvprProgram, (fGpu, fDesc, fUniformHandles, programID, fUniforms,
+ fGeometryProcessor,
fXferProcessor, fFragmentProcessors.get(),
fSeparableVaryingInfos));
}
diff --git a/src/gpu/gl/builders/GrGLProgramBuilder.cpp b/src/gpu/gl/builders/GrGLProgramBuilder.cpp
index daa0b6ba06..bbae592157 100644
--- a/src/gpu/gl/builders/GrGLProgramBuilder.cpp
+++ b/src/gpu/gl/builders/GrGLProgramBuilder.cpp
@@ -37,24 +37,17 @@ GrGLProgram* GrGLProgramBuilder::CreateProgram(const GrOptDrawState& optState, G
const GrGLProgramDescBuilder::GLKeyHeader& header = GrGLProgramDescBuilder::GetHeader(pb->desc());
// emit code to read the dst copy texture, if necessary
- if (GrGLFragmentShaderBuilder::kNoDstRead_DstReadKey != header.fDstReadKey
- && !gpu->glCaps().fbFetchSupport()) {
+ if (GrGLFragmentShaderBuilder::kNoDstRead_DstReadKey != header.fDstReadKey &&
+ !gpu->glCaps().fbFetchSupport()) {
pb->fFS.emitCodeToReadDstTexture();
}
- // get the initial color and coverage to feed into the first effect in each effect chain
- GrGLSLExpr4 inputColor;
- GrGLSLExpr1 inputCoverage;
- pb->setupUniformColorAndCoverageIfNeeded(&inputColor, &inputCoverage);
-
// TODO: Once all stages can handle taking a float or vec4 and correctly handling them we can
- // remove this cast to a vec4.
- GrGLSLExpr4 inputCoverageVec4;
- if (inputCoverage.isValid()) {
- inputCoverageVec4 = GrGLSLExpr4::VectorCast(inputCoverage);
- }
+ // seed correctly here
+ GrGLSLExpr4 inputColor;
+ GrGLSLExpr4 inputCoverage;
- pb->emitAndInstallProcs(&inputColor, &inputCoverageVec4);
+ pb->emitAndInstallProcs(&inputColor, &inputCoverage);
return pb->finalize();
}
@@ -65,8 +58,6 @@ GrGLProgramBuilder* GrGLProgramBuilder::CreateProgramBuilder(const GrOptDrawStat
const GrProgramDesc& desc = optState.programDesc();
if (GrGLProgramDescBuilder::GetHeader(desc).fUseNvpr) {
SkASSERT(gpu->glCaps().pathRenderingSupport());
- SkASSERT(GrProgramDesc::kAttribute_ColorInput != desc.header().fColorInput);
- SkASSERT(GrProgramDesc::kAttribute_ColorInput != desc.header().fCoverageInput);
SkASSERT(!hasGeometryProcessor);
if (gpu->glPathRendering()->texturingMode() ==
GrGLPathRendering::FixedFunction_TexturingMode) {
@@ -185,36 +176,10 @@ const GrGLContextInfo& GrGLProgramBuilder::ctxInfo() const {
return fGpu->ctxInfo();
}
-void GrGLProgramBuilder::setupUniformColorAndCoverageIfNeeded(GrGLSLExpr4* inputColor,
- GrGLSLExpr1* inputCoverage) {
- const GrProgramDesc::KeyHeader& header = this->header();
- if (GrProgramDesc::kUniform_ColorInput == header.fColorInput) {
- const char* name;
- fUniformHandles.fColorUni =
- this->addUniform(GrGLProgramBuilder::kFragment_Visibility,
- kVec4f_GrSLType, kDefault_GrSLPrecision,
- "Color", &name);
- *inputColor = GrGLSLExpr4(name);
- } else if (GrProgramDesc::kAllOnes_ColorInput == header.fColorInput) {
- *inputColor = GrGLSLExpr4(1);
- }
- if (GrProgramDesc::kUniform_ColorInput == header.fCoverageInput) {
- const char* name;
- fUniformHandles.fCoverageUni =
- this->addUniform(GrGLProgramBuilder::kFragment_Visibility,
- kFloat_GrSLType, kDefault_GrSLPrecision,
- "Coverage",&name);
- *inputCoverage = GrGLSLExpr1(name);
- } else if (GrProgramDesc::kAllOnes_ColorInput == header.fCoverageInput) {
- *inputCoverage = GrGLSLExpr1(1);
- }
-}
-
void GrGLProgramBuilder::emitAndInstallProcs(GrGLSLExpr4* inputColor, GrGLSLExpr4* inputCoverage) {
if (fOptState.hasGeometryProcessor()) {
fVS.setupUniformViewMatrix();
- const GrProgramDesc::KeyHeader& header = this->header();
fVS.codeAppend("gl_PointSize = 1.0;");
// Setup position
@@ -227,25 +192,11 @@ void GrGLProgramBuilder::emitAndInstallProcs(GrGLSLExpr4* inputColor, GrGLSLExpr
const GrGeometryProcessor& gp = *fOptState.getGeometryProcessor();
fVS.emitAttributes(gp);
- GrGLSLExpr4 outputColor;
- GrGLSLExpr4 outputCoverage;
- this->emitAndInstallProc(gp, &outputColor, &outputCoverage);
-
- // We may override color and coverage here if we have unform color or coverage. This is
- // obviously not ideal.
- // TODO lets the GP itself do the override
- if (GrProgramDesc::kAttribute_ColorInput == header.fColorInput) {
- *inputColor = outputColor;
- }
-
- // We may have uniform coverage, if so we need to multiply the GPs output by the uniform
- // coverage
- if (GrProgramDesc::kUniform_ColorInput == header.fCoverageInput) {
- fFS.codeAppendf("%s *= %s;", outputCoverage.c_str(), inputCoverage->c_str());
- }
- *inputCoverage = outputCoverage;
}
+ const GrPrimitiveProcessor& primProc = *fOptState.getPrimitiveProcessor();
+ this->emitAndInstallProc(primProc, inputColor, inputCoverage);
+
fFragmentProcessors.reset(SkNEW(GrGLInstalledFragProcs));
int numProcs = fOptState.numFragmentStages();
this->emitAndInstallFragProcs(0, fOptState.numColorStages(), inputColor);
@@ -303,7 +254,7 @@ void GrGLProgramBuilder::emitAndInstallProc(const GrPendingFragmentStage& proc,
fFS.codeAppend("}");
}
-void GrGLProgramBuilder::emitAndInstallProc(const GrGeometryProcessor& proc,
+void GrGLProgramBuilder::emitAndInstallProc(const GrPrimitiveProcessor& proc,
GrGLSLExpr4* outputColor,
GrGLSLExpr4* outputCoverage) {
// Program builders have a bit of state we need to clear with each effect
@@ -344,7 +295,7 @@ void GrGLProgramBuilder::emitAndInstallProc(const GrPendingFragmentStage& fs,
fFragmentProcessors->fProcs.push_back(ifp);
}
-void GrGLProgramBuilder::emitAndInstallProc(const GrGeometryProcessor& gp,
+void GrGLProgramBuilder::emitAndInstallProc(const GrPrimitiveProcessor& gp,
const char* outColor,
const char* outCoverage) {
SkASSERT(!fGeometryProcessor);
@@ -403,7 +354,7 @@ void GrGLProgramBuilder::emitAndInstallXferProc(const GrXferProcessor& xp,
fFS.codeAppend("}");
}
-void GrGLProgramBuilder::verify(const GrGeometryProcessor& gp) {
+void GrGLProgramBuilder::verify(const GrPrimitiveProcessor& gp) {
SkASSERT(fFS.hasReadFragmentPosition() == gp.willReadFragmentPosition());
}
@@ -489,11 +440,6 @@ GrGLProgram* GrGLProgramBuilder::finalize() {
// compile shaders and bind attributes / uniforms
SkTDArray<GrGLuint> shadersToDelete;
- if (!fFS.compileAndAttachShaders(programID, &shadersToDelete)) {
- this->cleanupProgram(programID, shadersToDelete);
- return NULL;
- }
-
if (!(GrGLProgramDescBuilder::GetHeader(fDesc).fUseNvpr &&
fGpu->glPathRendering()->texturingMode() ==
GrGLPathRendering::FixedFunction_TexturingMode)) {
@@ -507,6 +453,12 @@ GrGLProgram* GrGLProgramBuilder::finalize() {
fVS.bindVertexAttributes(programID);
}
}
+
+ if (!fFS.compileAndAttachShaders(programID, &shadersToDelete)) {
+ this->cleanupProgram(programID, shadersToDelete);
+ return NULL;
+ }
+
bool usingBindUniform = fGpu->glInterface()->fFunctions.fBindUniformLocation != NULL;
if (usingBindUniform) {
this->bindUniformLocations(programID);
diff --git a/src/gpu/gl/builders/GrGLProgramBuilder.h b/src/gpu/gl/builders/GrGLProgramBuilder.h
index 69eed27252..e4c5f3168e 100644
--- a/src/gpu/gl/builders/GrGLProgramBuilder.h
+++ b/src/gpu/gl/builders/GrGLProgramBuilder.h
@@ -242,8 +242,6 @@ public:
struct BuiltinUniformHandles {
UniformHandle fViewMatrixUni;
UniformHandle fRTAdjustmentUni;
- UniformHandle fColorUni;
- UniformHandle fCoverageUni;
// We use the render target height to provide a y-down frag coord when specifying
// origin_upper_left is not supported.
@@ -273,7 +271,6 @@ protected:
// char (unless the prefix is '\0'). It also mangles the name to be stage-specific if we're
// generating stage code.
void nameVariable(SkString* out, char prefix, const char* name);
- void setupUniformColorAndCoverageIfNeeded(GrGLSLExpr4* inputColor, GrGLSLExpr1* inputCoverage);
// Generates a possibly mangled name for a stage variable and writes it to the fragment shader.
// If GrGLSLExpr4 has a valid name then it will use that instead
void nameExpression(GrGLSLExpr4*, const char* baseName);
@@ -285,7 +282,7 @@ protected:
const GrGLSLExpr4& input,
GrGLSLExpr4* output);
- void emitAndInstallProc(const GrGeometryProcessor&,
+ void emitAndInstallProc(const GrPrimitiveProcessor&,
GrGLSLExpr4* outputColor,
GrGLSLExpr4* outputCoverage);
@@ -293,14 +290,14 @@ protected:
void emitAndInstallProc(const GrPendingFragmentStage&,
const char* outColor,
const char* inColor);
- void emitAndInstallProc(const GrGeometryProcessor&,
+ void emitAndInstallProc(const GrPrimitiveProcessor&,
const char* outColor,
const char* outCoverage);
void emitAndInstallXferProc(const GrXferProcessor&,
const GrGLSLExpr4& colorIn,
const GrGLSLExpr4& coverageIn);
- void verify(const GrGeometryProcessor&);
+ void verify(const GrPrimitiveProcessor&);
void verify(const GrXferProcessor&);
void verify(const GrFragmentProcessor&);
void emitSamplers(const GrProcessor&,