| /* |
| * 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 "GrGpu.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; |
| typedef GrGLProgramDataManager::VaryingHandle VaryingHandle; |
| |
| /** |
| * 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 GrEffectStage&, |
| bool, |
| 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*, |
| GrGpu::DrawType, |
| const GrGLProgramDataManager&, |
| const GrEffectStage* effectStages[]) = 0; |
| |
| virtual void setData(GrGpuGL*, |
| GrGpu::DrawType, |
| const GrGLProgramDataManager&, |
| const GrEffectStage* effectStages) { SkFAIL("DO NOT USE"); } |
| |
| 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<TransformedCoords> 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<TextureSampler> TextureSamplerArray; |
| |
| protected: |
| |
| /** |
| * Helpers for GenEffectMetaKey. |
| */ |
| static uint32_t GenAttribKey(const GrEffect*); |
| static uint32_t GenTransformKey(const GrEffectStage&, bool useExplicitLocalCoords); |
| static uint32_t GenTextureKey(const GrEffect*, 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<GrGLEffect*> fGLEffects; |
| SkTArray<SkSTArray<4, Sampler, true> > fSamplers; |
| |
| private: |
| 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*, |
| GrGpu::DrawType, |
| const GrGLProgramDataManager&, |
| const GrEffectStage* effectStages[]) SK_OVERRIDE; |
| |
| virtual void setData(GrGpuGL*, |
| GrGpu::DrawType, |
| 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 GrEffectStage&, |
| TransformedCoordsArray*); |
| |
| /** |
| * Helper for setData(). Sets all the transform matrices for an effect. |
| */ |
| void setTransformData(GrGpuGL* gpu, const GrGLProgramDataManager&, const GrEffectStage&, |
| int effectIdx); |
| void setPathTransformData(GrGpuGL* gpu, const GrGLProgramDataManager&, const GrEffectStage&, |
| int effectIdx); |
| |
| struct Transform { |
| Transform() { fCurrentValue = SkMatrix::InvalidMatrix(); } |
| UniformHandle fHandle; |
| SkMatrix fCurrentValue; |
| }; |
| |
| struct PathTransform { |
| PathTransform() { fCurrentValue = SkMatrix::InvalidMatrix(); } |
| VaryingHandle fHandle; |
| SkMatrix fCurrentValue; |
| GrSLType fType; |
| }; |
| |
| SkTArray<SkSTArray<2, Transform, true> > fTransforms; |
| SkTArray<SkTArray<PathTransform, true> > fPathTransforms; |
| 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<GrGLVertexProgramEffects> 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*, |
| GrGpu::DrawType, |
| 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 GrEffectStage&, |
| TransformedCoordsArray*); |
| |
| /** |
| * Helper for setData(). Sets the PathTexGen state for each transform in an effect. |
| */ |
| void setPathTexGenState(GrGpuGL*, const GrEffectStage&, int effectIdx); |
| |
| struct Transforms { |
| Transforms(uint32_t transformKey, int texCoordIndex) |
| : fTransformKey(transformKey), fTexCoordIndex(texCoordIndex) {} |
| uint32_t fTransformKey; |
| int fTexCoordIndex; |
| }; |
| |
| SkTArray<Transforms> 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<GrGLPathTexGenProgramEffects> fProgramEffects; |
| typedef GrGLProgramEffectsBuilder INHERITED; |
| }; |
| |
| |
| #endif |