aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu
diff options
context:
space:
mode:
authorGravatar joshualitt <joshualitt@chromium.org>2014-12-15 14:16:27 -0800
committerGravatar Commit bot <commit-bot@chromium.org>2014-12-15 14:16:27 -0800
commit9b98932adaceb7ad0a617ade16616923f6bffe84 (patch)
treec9a7a19ca9555e3284d67b01ad1ad448a963ad17 /src/gpu
parentbc3d0de755c4164563d136fc6b28fc186d275db7 (diff)
This change will ultimately pull uniform color, and to a much lesser degree uniform coverage, into GPs. There are still some loose ends because drawstate has the ability to override the GP, but fixing these cleanly will have to wait until we have deferred geometry in place and can make attribute / uniform decisions on the fly.
Diffstat (limited to 'src/gpu')
-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
29 files changed, 1217 insertions, 563 deletions
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&,