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