diff --git a/include/gpu/GrEffect.h b/include/gpu/GrEffect.h index e7590b6793..4dc294bfe8 100644 --- a/include/gpu/GrEffect.h +++ b/include/gpu/GrEffect.h @@ -17,6 +17,7 @@ class GrBackendEffectFactory; class GrContext; class GrEffect; +class GrVertexEffect; class SkString; /** @@ -152,7 +153,14 @@ public: /** Will this effect read the fragment position? */ bool willReadFragmentPosition() const { return fWillReadFragmentPosition; } - int numVertexAttribs() const { return fVertexAttribTypes.count(); } + /** Will this effect emit custom vertex shader code? + (To set this value the effect must inherit from GrVertexEffect.) */ + bool hasVertexCode() const { return fHasVertexCode; } + + int numVertexAttribs() const { + SkASSERT(0 == fVertexAttribTypes.count() || fHasVertexCode); + return fVertexAttribTypes.count(); + } GrSLType vertexAttribType(int index) const { return fVertexAttribTypes[index]; } @@ -204,14 +212,11 @@ protected: */ void addTextureAccess(const GrTextureAccess* textureAccess); - /** - * Subclasses call this from their constructor to register vertex attributes (at most - * kMaxVertexAttribs). This must only be called from the constructor because GrEffects are - * immutable. - */ - void addVertexAttrib(GrSLType type); - - GrEffect() : fWillReadDstColor(false), fWillReadFragmentPosition(false), fEffectRef(NULL) {} + GrEffect() + : fWillReadDstColor(false) + , fWillReadFragmentPosition(false) + , fHasVertexCode(false) + , fEffectRef(NULL) {} /** This should be called by GrEffect subclass factories. See the comment on AutoEffectUnref for an example factory function. */ @@ -300,15 +305,17 @@ private: void EffectRefDestroyed() { fEffectRef = NULL; } - friend class GrEffectRef; // to call EffectRefDestroyed() - friend class GrEffectStage; // to rewrap GrEffect in GrEffectRef when restoring an effect-stage - // from deferred state, to call isEqual on naked GrEffects, and - // to inc/dec deferred ref counts. + friend class GrEffectRef; // to call EffectRefDestroyed() + friend class GrEffectStage; // to rewrap GrEffect in GrEffectRef when restoring an effect-stage + // from deferred state, to call isEqual on naked GrEffects, and + // to inc/dec deferred ref counts. + friend class GrVertexEffect; // to set fHasVertexCode and build fVertexAttribTypes. SkSTArray<4, const GrTextureAccess*, true> fTextureAccesses; SkSTArray fVertexAttribTypes; bool fWillReadDstColor; bool fWillReadFragmentPosition; + bool fHasVertexCode; GrEffectRef* fEffectRef; typedef SkRefCnt INHERITED; diff --git a/src/gpu/GrAAConvexPathRenderer.cpp b/src/gpu/GrAAConvexPathRenderer.cpp index 6749b46539..7063440ba4 100644 --- a/src/gpu/GrAAConvexPathRenderer.cpp +++ b/src/gpu/GrAAConvexPathRenderer.cpp @@ -21,6 +21,8 @@ #include "gl/GrGLEffect.h" #include "gl/GrGLSL.h" +#include "effects/GrVertexEffect.h" + GrAAConvexPathRenderer::GrAAConvexPathRenderer() { } @@ -497,7 +499,7 @@ static void create_vertices(const SegmentArray& segments, * Requires shader derivative instruction support. */ -class QuadEdgeEffect : public GrEffect { +class QuadEdgeEffect : public GrVertexEffect { public: static GrEffectRef* Create() { @@ -586,7 +588,7 @@ private: GR_DECLARE_EFFECT_TEST; - typedef GrEffect INHERITED; + typedef GrVertexEffect INHERITED; }; GR_DEFINE_EFFECT_TEST(QuadEdgeEffect); diff --git a/src/gpu/GrAARectRenderer.cpp b/src/gpu/GrAARectRenderer.cpp index 4856bb5418..e4bf853e36 100644 --- a/src/gpu/GrAARectRenderer.cpp +++ b/src/gpu/GrAARectRenderer.cpp @@ -10,6 +10,7 @@ #include "gl/GrGLEffect.h" #include "GrTBackendEffectFactory.h" #include "SkColorPriv.h" +#include "effects/GrVertexEffect.h" SK_DEFINE_INST_COUNT(GrAARectRenderer) @@ -17,7 +18,7 @@ SK_DEFINE_INST_COUNT(GrAARectRenderer) class GrGLAlignedRectEffect; // Axis Aligned special case -class GrAlignedRectEffect : public GrEffect { +class GrAlignedRectEffect : public GrVertexEffect { public: static GrEffectRef* Create() { GR_CREATE_STATIC_EFFECT(gAlignedRectEffect, GrAlignedRectEffect, ()); @@ -101,7 +102,7 @@ public: private: - GrAlignedRectEffect() : GrEffect() { + GrAlignedRectEffect() : GrVertexEffect() { this->addVertexAttrib(kVec4f_GrSLType); } @@ -109,7 +110,7 @@ private: GR_DECLARE_EFFECT_TEST; - typedef GrEffect INHERITED; + typedef GrVertexEffect INHERITED; }; @@ -137,7 +138,7 @@ class GrGLRectEffect; * The munged width and height are stored in a vec2 varying ("WidthHeight") * with the width in x and the height in y. */ -class GrRectEffect : public GrEffect { +class GrRectEffect : public GrVertexEffect { public: static GrEffectRef* Create() { GR_CREATE_STATIC_EFFECT(gRectEffect, GrRectEffect, ()); @@ -236,7 +237,7 @@ public: private: - GrRectEffect() : GrEffect() { + GrRectEffect() : GrVertexEffect() { this->addVertexAttrib(kVec4f_GrSLType); this->addVertexAttrib(kVec2f_GrSLType); this->setWillReadFragmentPosition(); @@ -246,7 +247,7 @@ private: GR_DECLARE_EFFECT_TEST; - typedef GrEffect INHERITED; + typedef GrVertexEffect INHERITED; }; diff --git a/src/gpu/GrEffect.cpp b/src/gpu/GrEffect.cpp index dc83f7b7cb..53dabb619c 100644 --- a/src/gpu/GrEffect.cpp +++ b/src/gpu/GrEffect.cpp @@ -90,11 +90,6 @@ void GrEffect::addTextureAccess(const GrTextureAccess* access) { fTextureAccesses.push_back(access); } -void GrEffect::addVertexAttrib(GrSLType type) { - SkASSERT(fVertexAttribTypes.count() < kMaxVertexAttribs); - fVertexAttribTypes.push_back(type); -} - void* GrEffect::operator new(size_t size) { return GrEffect_Globals::GetTLS()->allocate(size); } diff --git a/src/gpu/GrOvalRenderer.cpp b/src/gpu/GrOvalRenderer.cpp index 013c7ab7e8..66ca05351a 100644 --- a/src/gpu/GrOvalRenderer.cpp +++ b/src/gpu/GrOvalRenderer.cpp @@ -19,6 +19,8 @@ #include "SkRRect.h" #include "SkStrokeRec.h" +#include "effects/GrVertexEffect.h" + SK_DEFINE_INST_COUNT(GrOvalRenderer) namespace { @@ -56,7 +58,7 @@ inline bool circle_stays_circle(const SkMatrix& m) { * specified as offset_x, offset_y (both from center point), outer radius and inner radius. */ -class CircleEdgeEffect : public GrEffect { +class CircleEdgeEffect : public GrVertexEffect { public: static GrEffectRef* Create(bool stroke) { GR_CREATE_STATIC_EFFECT(gCircleStrokeEdge, CircleEdgeEffect, (true)); @@ -134,7 +136,7 @@ public: private: - CircleEdgeEffect(bool stroke) : GrEffect() { + CircleEdgeEffect(bool stroke) : GrVertexEffect() { this->addVertexAttrib(kVec4f_GrSLType); fStroke = stroke; } @@ -148,7 +150,7 @@ private: GR_DECLARE_EFFECT_TEST; - typedef GrEffect INHERITED; + typedef GrVertexEffect INHERITED; }; GR_DEFINE_EFFECT_TEST(CircleEdgeEffect); @@ -170,7 +172,7 @@ GrEffectRef* CircleEdgeEffect::TestCreate(SkRandom* random, * We are using an implicit function of x^2/a^2 + y^2/b^2 - 1 = 0. */ -class EllipseEdgeEffect : public GrEffect { +class EllipseEdgeEffect : public GrVertexEffect { public: static GrEffectRef* Create(bool stroke) { GR_CREATE_STATIC_EFFECT(gEllipseStrokeEdge, EllipseEdgeEffect, (true)); @@ -269,7 +271,7 @@ public: }; private: - EllipseEdgeEffect(bool stroke) : GrEffect() { + EllipseEdgeEffect(bool stroke) : GrVertexEffect() { this->addVertexAttrib(kVec2f_GrSLType); this->addVertexAttrib(kVec4f_GrSLType); fStroke = stroke; @@ -284,7 +286,7 @@ private: GR_DECLARE_EFFECT_TEST; - typedef GrEffect INHERITED; + typedef GrVertexEffect INHERITED; }; GR_DEFINE_EFFECT_TEST(EllipseEdgeEffect); @@ -307,7 +309,7 @@ GrEffectRef* EllipseEdgeEffect::TestCreate(SkRandom* random, * The result is device-independent and can be used with any affine matrix. */ -class DIEllipseEdgeEffect : public GrEffect { +class DIEllipseEdgeEffect : public GrVertexEffect { public: enum Mode { kStroke = 0, kHairline, kFill }; @@ -430,7 +432,7 @@ public: }; private: - DIEllipseEdgeEffect(Mode mode) : GrEffect() { + DIEllipseEdgeEffect(Mode mode) : GrVertexEffect() { this->addVertexAttrib(kVec2f_GrSLType); this->addVertexAttrib(kVec2f_GrSLType); fMode = mode; @@ -445,7 +447,7 @@ private: GR_DECLARE_EFFECT_TEST; - typedef GrEffect INHERITED; + typedef GrVertexEffect INHERITED; }; GR_DEFINE_EFFECT_TEST(DIEllipseEdgeEffect); diff --git a/src/gpu/effects/GrBezierEffect.cpp b/src/gpu/effects/GrBezierEffect.cpp index c7eadb783a..b3e9f62f69 100644 --- a/src/gpu/effects/GrBezierEffect.cpp +++ b/src/gpu/effects/GrBezierEffect.cpp @@ -128,7 +128,7 @@ const GrBackendEffectFactory& GrConicEffect::getFactory() const { return GrTBackendEffectFactory::getInstance(); } -GrConicEffect::GrConicEffect(GrBezierEdgeType edgeType) : GrEffect() { +GrConicEffect::GrConicEffect(GrBezierEdgeType edgeType) : GrVertexEffect() { this->addVertexAttrib(kVec4f_GrSLType); fEdgeType = edgeType; } @@ -260,7 +260,7 @@ const GrBackendEffectFactory& GrQuadEffect::getFactory() const { return GrTBackendEffectFactory::getInstance(); } -GrQuadEffect::GrQuadEffect(GrBezierEdgeType edgeType) : GrEffect() { +GrQuadEffect::GrQuadEffect(GrBezierEdgeType edgeType) : GrVertexEffect() { this->addVertexAttrib(kVec4f_GrSLType); fEdgeType = edgeType; } @@ -403,7 +403,7 @@ const GrBackendEffectFactory& GrCubicEffect::getFactory() const { return GrTBackendEffectFactory::getInstance(); } -GrCubicEffect::GrCubicEffect(GrBezierEdgeType edgeType) : GrEffect() { +GrCubicEffect::GrCubicEffect(GrBezierEdgeType edgeType) : GrVertexEffect() { this->addVertexAttrib(kVec4f_GrSLType); fEdgeType = edgeType; } diff --git a/src/gpu/effects/GrBezierEffect.h b/src/gpu/effects/GrBezierEffect.h index d31cd7e4c8..5de7b80b75 100644 --- a/src/gpu/effects/GrBezierEffect.h +++ b/src/gpu/effects/GrBezierEffect.h @@ -8,8 +8,9 @@ #ifndef GrBezierEffect_DEFINED #define GrBezierEffect_DEFINED -#include "GrEffect.h" #include "GrDrawTargetCaps.h" +#include "GrEffect.h" +#include "GrVertexEffect.h" enum GrBezierEdgeType { kFillAA_GrBezierEdgeType, @@ -67,7 +68,7 @@ static inline bool GrBezierEdgeTypeIsAA(const GrBezierEdgeType edgeType) { */ class GrGLConicEffect; -class GrConicEffect : public GrEffect { +class GrConicEffect : public GrVertexEffect { public: static GrEffectRef* Create(const GrBezierEdgeType edgeType, const GrDrawTargetCaps& caps) { GR_CREATE_STATIC_EFFECT(gConicFillAA, GrConicEffect, (kFillAA_GrBezierEdgeType)); @@ -117,7 +118,7 @@ private: GR_DECLARE_EFFECT_TEST; - typedef GrEffect INHERITED; + typedef GrVertexEffect INHERITED; }; /////////////////////////////////////////////////////////////////////////////// @@ -131,7 +132,7 @@ private: */ class GrGLQuadEffect; -class GrQuadEffect : public GrEffect { +class GrQuadEffect : public GrVertexEffect { public: static GrEffectRef* Create(const GrBezierEdgeType edgeType, const GrDrawTargetCaps& caps) { GR_CREATE_STATIC_EFFECT(gQuadFillAA, GrQuadEffect, (kFillAA_GrBezierEdgeType)); @@ -181,7 +182,7 @@ private: GR_DECLARE_EFFECT_TEST; - typedef GrEffect INHERITED; + typedef GrVertexEffect INHERITED; }; ////////////////////////////////////////////////////////////////////////////// @@ -197,7 +198,7 @@ private: */ class GrGLCubicEffect; -class GrCubicEffect : public GrEffect { +class GrCubicEffect : public GrVertexEffect { public: static GrEffectRef* Create(const GrBezierEdgeType edgeType, const GrDrawTargetCaps& caps) { GR_CREATE_STATIC_EFFECT(gCubicFillAA, GrCubicEffect, (kFillAA_GrBezierEdgeType)); @@ -247,7 +248,7 @@ private: GR_DECLARE_EFFECT_TEST; - typedef GrEffect INHERITED; + typedef GrVertexEffect INHERITED; }; #endif diff --git a/src/gpu/effects/GrCustomCoordsTextureEffect.h b/src/gpu/effects/GrCustomCoordsTextureEffect.h index fad35c8804..1caecf2f6d 100644 --- a/src/gpu/effects/GrCustomCoordsTextureEffect.h +++ b/src/gpu/effects/GrCustomCoordsTextureEffect.h @@ -9,6 +9,7 @@ #define GrCustomCoordsTextureEffect_DEFINED #include "GrEffect.h" +#include "GrVertexEffect.h" class GrGLCustomCoordsTextureEffect; @@ -17,7 +18,7 @@ class GrGLCustomCoordsTextureEffect; * It allows explicit specification of the filtering and wrap modes (GrTextureParams). The input * coords are a custom attribute. */ -class GrCustomCoordsTextureEffect : public GrEffect { +class GrCustomCoordsTextureEffect : public GrVertexEffect { public: static GrEffectRef* Create(GrTexture* tex, const GrTextureParams& p) { AutoEffectUnref effect(SkNEW_ARGS(GrCustomCoordsTextureEffect, (tex, p))); @@ -43,7 +44,7 @@ private: GR_DECLARE_EFFECT_TEST; - typedef GrEffect INHERITED; + typedef GrVertexEffect INHERITED; }; #endif diff --git a/src/gpu/effects/GrVertexEffect.h b/src/gpu/effects/GrVertexEffect.h new file mode 100644 index 0000000000..387ec7aee9 --- /dev/null +++ b/src/gpu/effects/GrVertexEffect.h @@ -0,0 +1,37 @@ +/* + * Copyright 2013 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef GrVertexEffect_DEFINED +#define GrVertexEffect_DEFINED + +#include "GrEffect.h" + +/** + * If an effect needs specialized vertex shader code, then it must inherit from this class. + * Otherwise it won't be able to add vertex attribs, and it might be given a vertexless shader + * program in emitCode. + */ +class GrVertexEffect : public GrEffect { +public: + GrVertexEffect() { fHasVertexCode = true; } + +protected: + /** + * Subclasses call this from their constructor to register vertex attributes (at most + * kMaxVertexAttribs). This must only be called from the constructor because GrEffects are + * immutable. + */ + void addVertexAttrib(GrSLType type) { + SkASSERT(fVertexAttribTypes.count() < kMaxVertexAttribs); + fVertexAttribTypes.push_back(type); + } + +private: + typedef GrEffect INHERITED; +}; + +#endif diff --git a/src/gpu/gl/GrGLProgramDesc.cpp b/src/gpu/gl/GrGLProgramDesc.cpp index 91ac266093..8b731fbc2c 100644 --- a/src/gpu/gl/GrGLProgramDesc.cpp +++ b/src/gpu/gl/GrGLProgramDesc.cpp @@ -19,7 +19,8 @@ inline GrGLEffect::EffectKey get_key_and_update_stats(const GrEffectStage& stage const GrGLCaps& caps, bool useExplicitLocalCoords, bool* setTrueIfReadsDst, - bool* setTrueIfReadsPos) { + bool* setTrueIfReadsPos, + bool* setTrueIfHasVertexCode) { const GrEffectRef& effect = *stage.getEffect(); const GrBackendEffectFactory& factory = effect->getFactory(); GrDrawEffect drawEffect(stage, useExplicitLocalCoords); @@ -29,6 +30,9 @@ inline GrGLEffect::EffectKey get_key_and_update_stats(const GrEffectStage& stage if (effect->willReadFragmentPosition()) { *setTrueIfReadsPos = true; } + if (effect->hasVertexCode()) { + *setTrueIfHasVertexCode = true; + } return factory.glEffectKey(drawEffect, caps); } } @@ -87,21 +91,25 @@ void GrGLProgramDesc::Build(const GrDrawState& drawState, int currEffectKey = 0; bool readsDst = false; bool readFragPosition = false; + bool hasVertexCode = false; if (!skipColor) { for (int s = 0; s < drawState.numColorStages(); ++s) { effectKeys[currEffectKey++] = get_key_and_update_stats(drawState.getColorStage(s), gpu->glCaps(), - requiresLocalCoordAttrib, &readsDst, &readFragPosition); + requiresLocalCoordAttrib, &readsDst, &readFragPosition, + &hasVertexCode); } } if (!skipCoverage) { for (int s = 0; s < drawState.numCoverageStages(); ++s) { effectKeys[currEffectKey++] = get_key_and_update_stats(drawState.getCoverageStage(s), gpu->glCaps(), - requiresLocalCoordAttrib, &readsDst, &readFragPosition); + requiresLocalCoordAttrib, &readsDst, &readFragPosition, + &hasVertexCode); } } + header->fHasVertexCode = hasVertexCode || requiresLocalCoordAttrib; header->fEmitsPointSize = isPoints; header->fColorFilterXfermode = skipColor ? SkXfermode::kDst_Mode : drawState.getColorFilterMode(); @@ -122,6 +130,7 @@ void GrGLProgramDesc::Build(const GrDrawState& drawState, header->fColorInput = kUniform_ColorInput; } else { header->fColorInput = kAttribute_ColorInput; + header->fHasVertexCode = true; } bool covIsSolidWhite = !requiresCoverageAttrib && 0xffffffff == drawState.getCoverage(); @@ -134,6 +143,7 @@ void GrGLProgramDesc::Build(const GrDrawState& drawState, header->fCoverageInput = kUniform_ColorInput; } else { header->fCoverageInput = kAttribute_ColorInput; + header->fHasVertexCode = true; } if (readsDst) { diff --git a/src/gpu/gl/GrGLProgramDesc.h b/src/gpu/gl/GrGLProgramDesc.h index fb67a97e85..308b0c787f 100644 --- a/src/gpu/gl/GrGLProgramDesc.h +++ b/src/gpu/gl/GrGLProgramDesc.h @@ -158,6 +158,7 @@ private: uint8_t fCoverageInput; // casts to enum ColorInput uint8_t fCoverageOutput; // casts to enum CoverageOutput + SkBool8 fHasVertexCode; SkBool8 fEmitsPointSize; uint8_t fColorFilterXfermode; // casts to enum SkXfermode::Mode