michael@0: /* michael@0: * Copyright 2012 Google Inc. michael@0: * michael@0: * Use of this source code is governed by a BSD-style license that can be michael@0: * found in the LICENSE file. michael@0: */ michael@0: michael@0: #ifndef GrBackendEffectFactory_DEFINED michael@0: #define GrBackendEffectFactory_DEFINED michael@0: michael@0: #include "GrTypes.h" michael@0: #include "SkTemplates.h" michael@0: #include "SkThread.h" michael@0: #include "SkTypes.h" michael@0: michael@0: /** Given a GrEffect of a particular type, creates the corresponding graphics-backend-specific michael@0: effect object. Also tracks equivalence of shaders generated via a key. Each factory instance michael@0: is assigned a generation ID at construction. The ID of the return of GrEffect::getFactory() michael@0: is used as a type identifier. Thus a GrEffect subclass must return a singleton from michael@0: getFactory(). GrEffect subclasses should use the derived class GrTBackendEffectFactory that is michael@0: templated on the GrEffect subclass as their factory object. It requires that the GrEffect michael@0: subclass has a nested class (or typedef) GLEffect which is its GL implementation and a subclass michael@0: of GrGLEffect. michael@0: */ michael@0: michael@0: class GrEffectRef; michael@0: class GrGLEffect; michael@0: class GrGLCaps; michael@0: class GrDrawEffect; michael@0: michael@0: class GrBackendEffectFactory : public SkNoncopyable { michael@0: public: michael@0: typedef uint32_t EffectKey; michael@0: enum { michael@0: kNoEffectKey = 0, michael@0: kEffectKeyBits = 10, michael@0: /** michael@0: * The framework automatically includes coord transforms and texture accesses in their michael@0: * effect's EffectKey, so effects don't need to account for them in GenKey(). michael@0: */ michael@0: kTextureKeyBits = 4, michael@0: kTransformKeyBits = 6, michael@0: kAttribKeyBits = 6, michael@0: kClassIDBits = 6 michael@0: }; michael@0: michael@0: virtual EffectKey glEffectKey(const GrDrawEffect&, const GrGLCaps&) const = 0; michael@0: virtual GrGLEffect* createGLInstance(const GrDrawEffect&) const = 0; michael@0: michael@0: bool operator ==(const GrBackendEffectFactory& b) const { michael@0: return fEffectClassID == b.fEffectClassID; michael@0: } michael@0: bool operator !=(const GrBackendEffectFactory& b) const { michael@0: return !(*this == b); michael@0: } michael@0: michael@0: virtual const char* name() const = 0; michael@0: michael@0: static EffectKey GetTransformKey(EffectKey key) { michael@0: return key >> (kEffectKeyBits + kTextureKeyBits) & ((1U << kTransformKeyBits) - 1); michael@0: } michael@0: michael@0: protected: michael@0: enum { michael@0: kIllegalEffectClassID = 0, michael@0: }; michael@0: michael@0: GrBackendEffectFactory() { michael@0: fEffectClassID = kIllegalEffectClassID; michael@0: } michael@0: virtual ~GrBackendEffectFactory() {} michael@0: michael@0: static EffectKey GenID() { michael@0: SkDEBUGCODE(static const int32_t kClassIDBits = 8 * sizeof(EffectKey) - michael@0: kTextureKeyBits - kEffectKeyBits - kAttribKeyBits); michael@0: // fCurrEffectClassID has been initialized to kIllegalEffectClassID. The michael@0: // atomic inc returns the old value not the incremented value. So we add michael@0: // 1 to the returned value. michael@0: int32_t id = sk_atomic_inc(&fCurrEffectClassID) + 1; michael@0: SkASSERT(id < (1 << kClassIDBits)); michael@0: return static_cast(id); michael@0: } michael@0: michael@0: EffectKey fEffectClassID; michael@0: michael@0: private: michael@0: static int32_t fCurrEffectClassID; michael@0: }; michael@0: michael@0: #endif