/* * 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 GrGLProgramEffects_DEFINED #define GrGLProgramEffects_DEFINED #include "GrBackendEffectFactory.h" #include "GrGLProgramDataManager.h" #include "GrTexture.h" #include "GrTextureAccess.h" class GrEffect; class GrEffectStage; class GrGLVertexProgramEffectsBuilder; class GrGLProgramBuilder; class GrGLFullProgramBuilder; class GrGLFragmentOnlyProgramBuilder; /** * This class encapsulates an array of GrGLEffects and their supporting data (coord transforms * and textures). It is built with GrGLProgramEffectsBuilder, then used to manage the necessary GL * state and shader uniforms. */ class GrGLProgramEffects : public SkRefCnt { public: typedef GrGLProgramDataManager::UniformHandle UniformHandle; /** * This class emits some of the code inserted into the shaders for an effect. The code it * creates may be dependent on properties of the effect that the effect itself doesn't use * in its key (e.g. the pixel format of textures used). So this class inserts a meta-key for * every effect using this function. It is also responsible for inserting the effect's class ID * which must be different for every GrEffect subclass. It can fail if an effect uses too many * textures, attributes, etc for the space allotted in the meta-key. */ static bool GenEffectMetaKey(const GrDrawEffect&, const GrGLCaps&, GrEffectKeyBuilder*); virtual ~GrGLProgramEffects(); /** * Assigns a texture unit to each sampler. It starts on *texUnitIdx and writes the next * available unit to *texUnitIdx when it returns. */ void initSamplers(const GrGLProgramDataManager&, int* texUnitIdx); /** * Calls setData() on each effect, and sets their transformation matrices and texture bindings. */ virtual void setData(GrGpuGL*, const GrGLProgramDataManager&, const GrEffectStage* effectStages[]) = 0; void addEffect(GrGLEffect* effect) { fGLEffects.push_back(effect); } /** * Passed to GrGLEffects so they can add transformed coordinates to their shader code. */ class TransformedCoords { public: TransformedCoords(const SkString& name, GrSLType type) : fName(name), fType(type) { } const char* c_str() const { return fName.c_str(); } GrSLType type() const { return fType; } const SkString& getName() const { return fName; } private: SkString fName; GrSLType fType; }; typedef SkTArray TransformedCoordsArray; /** * Passed to GrGLEffects so they can add texture reads to their shader code. */ class TextureSampler { public: TextureSampler(UniformHandle uniform, const GrTextureAccess& access) : fSamplerUniform(uniform) , fConfigComponentMask(GrPixelConfigComponentMask(access.getTexture()->config())) { SkASSERT(0 != fConfigComponentMask); memcpy(fSwizzle, access.getSwizzle(), 5); } UniformHandle samplerUniform() const { return fSamplerUniform; } // bitfield of GrColorComponentFlags present in the texture's config. uint32_t configComponentMask() const { return fConfigComponentMask; } const char* swizzle() const { return fSwizzle; } private: UniformHandle fSamplerUniform; uint32_t fConfigComponentMask; char fSwizzle[5]; }; typedef SkTArray TextureSamplerArray; protected: /** * Helpers for GenEffectMetaKey. */ static uint32_t GenAttribKey(const GrDrawEffect&); static uint32_t GenTransformKey(const GrDrawEffect&); static uint32_t GenTextureKey(const GrDrawEffect&, const GrGLCaps&); GrGLProgramEffects(int reserveCount) : fGLEffects(reserveCount) , fSamplers(reserveCount) { } /** * Helper for emitEffect() in a subclasses. Emits uniforms for an effect's texture accesses and * appends the necessary data to the TextureSamplerArray* object so effects can add texture * lookups to their code. This method is only meant to be called during the construction phase. */ void emitSamplers(GrGLProgramBuilder*, const GrEffect*, TextureSamplerArray*); /** * Helper for setData(). Binds all the textures for an effect. */ void bindTextures(GrGpuGL*, const GrEffect*, int effectIdx); struct Sampler { SkDEBUGCODE(Sampler() : fTextureUnit(-1) {}) UniformHandle fUniform; int fTextureUnit; }; SkTArray fGLEffects; SkTArray > fSamplers; private: friend class GrGLFragmentO; typedef SkRefCnt INHERITED; }; /** * This is an abstract base class for constructing different types of GrGLProgramEffects objects. */ class GrGLProgramEffectsBuilder { public: virtual ~GrGLProgramEffectsBuilder() { } /** * Emits the effect's shader code, and stores the necessary uniforms internally. */ virtual void emitEffect(const GrEffectStage&, const GrEffectKey&, const char* outColor, const char* inColor, int stageIndex) = 0; }; //////////////////////////////////////////////////////////////////////////////// /** * This is a GrGLProgramEffects implementation that does coord transforms with the vertex shader. */ class GrGLVertexProgramEffects : public GrGLProgramEffects { public: virtual void setData(GrGpuGL*, const GrGLProgramDataManager&, const GrEffectStage* effectStages[]) SK_OVERRIDE; private: friend class GrGLFullProgramBuilder; GrGLVertexProgramEffects(int reserveCount, bool explicitLocalCoords) : INHERITED(reserveCount) , fTransforms(reserveCount) , fHasExplicitLocalCoords(explicitLocalCoords) { } /** * This method is meant to only be called during the construction phase. */ void emitEffect(GrGLFullProgramBuilder*, const GrEffectStage&, const GrEffectKey&, const char* outColor, const char* inColor, int stageIndex); /** * Helper for emitEffect(). Emits any attributes an effect may have. */ void emitAttributes(GrGLFullProgramBuilder*, const GrEffectStage&); /** * Helper for emitEffect(). Emits code to implement an effect's coord transforms in the VS. * Varyings are added as an outputs of the VS and inputs to the FS. The varyings may be either a * vec2f or vec3f depending upon whether perspective interpolation is required or not. The names * of the varyings in the VS and FS as well their types are appended to the * TransformedCoordsArray* object, which is in turn passed to the effect's emitCode() function. */ void emitTransforms(GrGLFullProgramBuilder*, const GrDrawEffect&, TransformedCoordsArray*); /** * Helper for setData(). Sets all the transform matrices for an effect. */ void setTransformData(const GrGLProgramDataManager&, const GrDrawEffect&, int effectIdx); struct Transform { Transform() { fCurrentValue = SkMatrix::InvalidMatrix(); } UniformHandle fHandle; SkMatrix fCurrentValue; }; SkTArray > fTransforms; bool fHasExplicitLocalCoords; friend class GrGLVertexProgramEffectsBuilder; typedef GrGLProgramEffects INHERITED; }; /** * This class is used to construct a GrGLVertexProgramEffects* object. */ class GrGLVertexProgramEffectsBuilder : public GrGLProgramEffectsBuilder { public: GrGLVertexProgramEffectsBuilder(GrGLFullProgramBuilder*, int reserveCount); virtual ~GrGLVertexProgramEffectsBuilder() { } virtual void emitEffect(const GrEffectStage&, const GrEffectKey&, const char* outColor, const char* inColor, int stageIndex) SK_OVERRIDE; /** * Finalizes the building process and returns the effect array. After this call, the builder * becomes invalid. */ GrGLProgramEffects* finish() { return fProgramEffects.detach(); } private: GrGLFullProgramBuilder* fBuilder; SkAutoTDelete fProgramEffects; typedef GrGLProgramEffectsBuilder INHERITED; }; //////////////////////////////////////////////////////////////////////////////// /** * This is a GrGLProgramEffects implementation that does coord transforms with * the the NV_path_rendering PathTexGen functionality. */ class GrGLPathTexGenProgramEffects : public GrGLProgramEffects { public: virtual void setData(GrGpuGL*, const GrGLProgramDataManager&, const GrEffectStage* effectStages[]) SK_OVERRIDE; private: friend class GrGLFragmentOnlyProgramBuilder; GrGLPathTexGenProgramEffects(int reserveCount) : INHERITED(reserveCount) , fTransforms(reserveCount) { } /** * This method is meant to only be called during the construction phase. */ void emitEffect(GrGLFragmentOnlyProgramBuilder*, const GrEffectStage&, const GrEffectKey&, const char* outColor, const char* inColor, int stageIndex); /** * Helper for emitEffect(). Allocates texture units from the builder for each transform in an * effect. The transforms all use adjacent texture units. They either use two or three of the * coordinates at a given texture unit, depending on if they need perspective interpolation. * The expressions to access the transformed coords (i.e. 'vec2(gl_TexCoord[0])') as well as the * types are appended to the TransformedCoordsArray* object, which is in turn passed to the * effect's emitCode() function. */ void setupPathTexGen(GrGLFragmentOnlyProgramBuilder*, const GrDrawEffect&, TransformedCoordsArray*); /** * Helper for setData(). Sets the PathTexGen state for each transform in an effect. */ void setPathTexGenState(GrGpuGL*, const GrDrawEffect&, int effectIdx); struct Transforms { Transforms(uint32_t transformKey, int texCoordIndex) : fTransformKey(transformKey), fTexCoordIndex(texCoordIndex) {} uint32_t fTransformKey; int fTexCoordIndex; }; SkTArray fTransforms; friend class GrGLPathTexGenProgramEffectsBuilder; typedef GrGLProgramEffects INHERITED; }; /** * This class is used to construct a GrGLPathTexGenProgramEffects* object. */ class GrGLPathTexGenProgramEffectsBuilder : public GrGLProgramEffectsBuilder { public: GrGLPathTexGenProgramEffectsBuilder(GrGLFragmentOnlyProgramBuilder*, int reserveCount); virtual ~GrGLPathTexGenProgramEffectsBuilder() { } virtual void emitEffect(const GrEffectStage&, const GrEffectKey&, const char* outColor, const char* inColor, int stageIndex) SK_OVERRIDE; /** * Finalizes the building process and returns the effect array. After this call, the builder * becomes invalid. */ GrGLProgramEffects* finish() { return fProgramEffects.detach(); } private: GrGLFragmentOnlyProgramBuilder* fBuilder; SkAutoTDelete fProgramEffects; typedef GrGLProgramEffectsBuilder INHERITED; }; #endif