| /* |
| * Copyright 2012 Google Inc. |
| * |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| #ifndef GrBackendEffectFactory_DEFINED |
| #define GrBackendEffectFactory_DEFINED |
| |
| #include "GrTypes.h" |
| #include "SkTemplates.h" |
| #include "GrNoncopyable.h" |
| |
| /** Given a GrEffect of a particular type, creates the corresponding |
| graphics-backend-specific GrGLEffect. Also tracks equivalence |
| of shaders generated via a key. |
| */ |
| |
| class GrEffect; |
| class GrGLEffect; |
| class GrGLCaps; |
| |
| class GrBackendEffectFactory : public GrNoncopyable { |
| public: |
| typedef uint32_t EffectKey; |
| enum { |
| kEffectKeyBits = 10, |
| /** |
| * Some aspects of the generated code may be determined by the particular textures that are |
| * associated with the effect. These manipulations are performed by GrGLShaderBuilder beyond |
| * GrGLEffects' control. So there is a dedicated part of the key which is combined |
| * automatically with the bits produced by GrGLEffect::GenKey(). |
| */ |
| kTextureKeyBits = 6 |
| }; |
| |
| virtual EffectKey glEffectKey(const GrEffect&, const GrGLCaps&) const = 0; |
| virtual GrGLEffect* createGLInstance(const GrEffect&) const = 0; |
| |
| bool operator ==(const GrBackendEffectFactory& b) const { |
| return fEffectClassID == b.fEffectClassID; |
| } |
| bool operator !=(const GrBackendEffectFactory& b) const { |
| return !(*this == b); |
| } |
| |
| virtual const char* name() const = 0; |
| |
| protected: |
| enum { |
| kIllegalEffectClassID = 0, |
| }; |
| |
| GrBackendEffectFactory() { |
| fEffectClassID = kIllegalEffectClassID; |
| } |
| |
| static EffectKey GenID() { |
| // fCurrEffectClassID has been initialized to kIllegalEffectClassID. The |
| // atomic inc returns the old value not the incremented value. So we add |
| // 1 to the returned value. |
| int32_t id = sk_atomic_inc(&fCurrEffectClassID) + 1; |
| GrAssert(id < (1 << (8 * sizeof(EffectKey) - kEffectKeyBits))); |
| return id; |
| } |
| |
| EffectKey fEffectClassID; |
| |
| private: |
| static int32_t fCurrEffectClassID; |
| }; |
| |
| template <typename EffectClass> |
| class GrTBackendEffectFactory : public GrBackendEffectFactory { |
| |
| public: |
| typedef typename EffectClass::GLEffect GLEffect; |
| |
| /** Returns a human-readable name that is accessible via GrEffect or |
| GrGLEffect and is consistent between the two of them. |
| */ |
| virtual const char* name() const SK_OVERRIDE { return EffectClass::Name(); } |
| |
| /** Returns a value that identifies the GLSL shader code generated by |
| a GrEffect. This enables caching of generated shaders. Part of the |
| id identifies the GrEffect subclass. The remainder is based |
| on the aspects of the GrEffect object's configuration that affect |
| GLSL code generation. */ |
| virtual EffectKey glEffectKey(const GrEffect& effect, const GrGLCaps& caps) const SK_OVERRIDE { |
| GrAssert(kIllegalEffectClassID != fEffectClassID); |
| EffectKey effectKey = GLEffect::GenKey(effect, caps); |
| EffectKey textureKey = GLEffect::GenTextureKey(effect, caps); |
| #if GR_DEBUG |
| static const EffectKey kIllegalIDMask = (uint16_t) (~((1U << kEffectKeyBits) - 1)); |
| GrAssert(!(kIllegalIDMask & effectKey)); |
| |
| static const EffectKey kIllegalTextureKeyMask = (uint16_t) (~((1U << kTextureKeyBits) - 1)); |
| GrAssert(!(kIllegalTextureKeyMask & textureKey)); |
| #endif |
| return fEffectClassID | (textureKey << kEffectKeyBits) | effectKey; |
| } |
| |
| /** Returns a new instance of the appropriate *GL* implementation class |
| for the given GrEffect; caller is responsible for deleting |
| the object. */ |
| virtual GLEffect* createGLInstance(const GrEffect& effect) const SK_OVERRIDE { |
| return SkNEW_ARGS(GLEffect, (*this, effect)); |
| } |
| |
| /** This class is a singleton. This function returns the single instance. |
| */ |
| static const GrBackendEffectFactory& getInstance() { |
| static SkAlignedSTStorage<1, GrTBackendEffectFactory> gInstanceMem; |
| static const GrTBackendEffectFactory* gInstance; |
| if (!gInstance) { |
| gInstance = SkNEW_PLACEMENT(gInstanceMem.get(), |
| GrTBackendEffectFactory); |
| } |
| return *gInstance; |
| } |
| |
| protected: |
| GrTBackendEffectFactory() { |
| fEffectClassID = GenID() << (kEffectKeyBits + kTextureKeyBits) ; |
| } |
| }; |
| |
| #endif |