/* * 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 GrProgramStageFactory_DEFINED #define GrProgramStageFactory_DEFINED #include "GrTypes.h" #include "SkTemplates.h" #include "GrNoncopyable.h" /** Given a GrEffect of a particular type, creates the corresponding graphics-backend-specific GrProgramStage. Also tracks equivalence of shaders generated via a key. */ class GrEffect; class GrGLProgramStage; class GrGLCaps; class GrProgramStageFactory : public GrNoncopyable { public: typedef uint32_t StageKey; enum { kProgramStageKeyBits = 10, kTexturingStageKeyBits = 6 }; virtual StageKey glStageKey(const GrEffect& stage, const GrGLCaps& caps ) const = 0; virtual GrGLProgramStage* createGLInstance( const GrEffect& stage) const = 0; bool operator ==(const GrProgramStageFactory& b) const { return fStageClassID == b.fStageClassID; } bool operator !=(const GrProgramStageFactory& b) const { return !(*this == b); } virtual const char* name() const = 0; protected: enum { kIllegalStageClassID = 0, }; GrProgramStageFactory() { fStageClassID = kIllegalStageClassID; } static StageKey GenID() { // fCurrStageClassID has been initialized to kIllegalStageClassID. 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(&fCurrStageClassID) + 1; GrAssert(id < (1 << (8 * sizeof(StageKey) - kProgramStageKeyBits))); return id; } StageKey fStageClassID; private: static int32_t fCurrStageClassID; }; template class GrTProgramStageFactory : public GrProgramStageFactory { public: typedef typename StageClass::GLProgramStage GLProgramStage; /** Returns a human-readable name that is accessible via GrEffect or GrGLProgramStage and is consistent between the two of them. */ virtual const char* name() const SK_OVERRIDE { return StageClass::Name(); } /** Returns a value that idenitifes the GLSL shader code generated by a GrEffect. This enables caching of generated shaders. Part of the id identifies the GrCustomShader subclass. The remainder is based on the aspects of the GrEffect object's configuration that affect GLSL code generation. */ virtual StageKey glStageKey(const GrEffect& stage, const GrGLCaps& caps) const SK_OVERRIDE { GrAssert(kIllegalStageClassID != fStageClassID); StageKey stageID = GLProgramStage::GenKey(stage, caps); StageKey textureKey = GLProgramStage::GenTextureKey(stage, caps); #if GR_DEBUG static const StageKey kIllegalIDMask = (uint16_t) (~((1U << kProgramStageKeyBits) - 1)); GrAssert(!(kIllegalIDMask & stageID)); static const StageKey kIllegalTextureKeyMask = (uint16_t) (~((1U << kTexturingStageKeyBits) - 1)); GrAssert(!(kIllegalTextureKeyMask & textureKey)); #endif return fStageClassID | (textureKey << kProgramStageKeyBits) | stageID; } /** Returns a new instance of the appropriate *GL* implementation class for the given GrEffect; caller is responsible for deleting the object. */ virtual GLProgramStage* createGLInstance( const GrEffect& stage) const SK_OVERRIDE { return SkNEW_ARGS(GLProgramStage, (*this, stage)); } /** This class is a singleton. This function returns the single instance. */ static const GrProgramStageFactory& getInstance() { static SkAlignedSTStorage<1, GrTProgramStageFactory> gInstanceMem; static const GrTProgramStageFactory* gInstance; if (!gInstance) { gInstance = SkNEW_PLACEMENT(gInstanceMem.get(), GrTProgramStageFactory); } return *gInstance; } protected: GrTProgramStageFactory() { fStageClassID = GenID() << (kProgramStageKeyBits + kTexturingStageKeyBits) ; } }; #endif