michael@0: /* michael@0: * Copyright 2013 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 GrGLProgramEffects_DEFINED michael@0: #define GrGLProgramEffects_DEFINED michael@0: michael@0: #include "GrBackendEffectFactory.h" michael@0: #include "GrTexture.h" michael@0: #include "GrTextureAccess.h" michael@0: #include "GrGLUniformManager.h" michael@0: michael@0: class GrEffectStage; michael@0: class GrGLVertexProgramEffectsBuilder; michael@0: class GrGLShaderBuilder; michael@0: class GrGLFullShaderBuilder; michael@0: class GrGLFragmentOnlyShaderBuilder; michael@0: michael@0: /** michael@0: * This class encapsulates an array of GrGLEffects and their supporting data (coord transforms michael@0: * and textures). It is built with GrGLProgramEffectsBuilder, then used to manage the necessary GL michael@0: * state and shader uniforms. michael@0: */ michael@0: class GrGLProgramEffects { michael@0: public: michael@0: typedef GrBackendEffectFactory::EffectKey EffectKey; michael@0: typedef GrGLUniformManager::UniformHandle UniformHandle; michael@0: michael@0: /** michael@0: * These methods generate different portions of an effect's final key. michael@0: */ michael@0: static EffectKey GenAttribKey(const GrDrawEffect&); michael@0: static EffectKey GenTransformKey(const GrDrawEffect&); michael@0: static EffectKey GenTextureKey(const GrDrawEffect&, const GrGLCaps&); michael@0: michael@0: virtual ~GrGLProgramEffects(); michael@0: michael@0: /** michael@0: * Assigns a texture unit to each sampler. It starts on *texUnitIdx and writes the next michael@0: * available unit to *texUnitIdx when it returns. michael@0: */ michael@0: void initSamplers(const GrGLUniformManager&, int* texUnitIdx); michael@0: michael@0: /** michael@0: * Calls setData() on each effect, and sets their transformation matrices and texture bindings. michael@0: */ michael@0: virtual void setData(GrGpuGL*, michael@0: const GrGLUniformManager&, michael@0: const GrEffectStage* effectStages[]) = 0; michael@0: michael@0: /** michael@0: * Passed to GrGLEffects so they can add transformed coordinates to their shader code. michael@0: */ michael@0: class TransformedCoords { michael@0: public: michael@0: TransformedCoords(const SkString& name, GrSLType type) michael@0: : fName(name), fType(type) { michael@0: } michael@0: michael@0: const char* c_str() const { return fName.c_str(); } michael@0: GrSLType type() const { return fType; } michael@0: const SkString& getName() const { return fName; } michael@0: michael@0: private: michael@0: SkString fName; michael@0: GrSLType fType; michael@0: }; michael@0: michael@0: typedef SkTArray TransformedCoordsArray; michael@0: michael@0: /** michael@0: * Passed to GrGLEffects so they can add texture reads to their shader code. michael@0: */ michael@0: class TextureSampler { michael@0: public: michael@0: TextureSampler(UniformHandle uniform, const GrTextureAccess& access) michael@0: : fSamplerUniform(uniform) michael@0: , fConfigComponentMask(GrPixelConfigComponentMask(access.getTexture()->config())) { michael@0: SkASSERT(0 != fConfigComponentMask); michael@0: memcpy(fSwizzle, access.getSwizzle(), 5); michael@0: } michael@0: michael@0: UniformHandle samplerUniform() const { return fSamplerUniform; } michael@0: // bitfield of GrColorComponentFlags present in the texture's config. michael@0: uint32_t configComponentMask() const { return fConfigComponentMask; } michael@0: const char* swizzle() const { return fSwizzle; } michael@0: michael@0: private: michael@0: UniformHandle fSamplerUniform; michael@0: uint32_t fConfigComponentMask; michael@0: char fSwizzle[5]; michael@0: }; michael@0: michael@0: typedef SkTArray TextureSamplerArray; michael@0: michael@0: protected: michael@0: GrGLProgramEffects(int reserveCount) michael@0: : fGLEffects(reserveCount) michael@0: , fSamplers(reserveCount) { michael@0: } michael@0: michael@0: /** michael@0: * Helper for emitEffect() in a subclasses. Emits uniforms for an effect's texture accesses and michael@0: * appends the necessary data to the TextureSamplerArray* object so effects can add texture michael@0: * lookups to their code. This method is only meant to be called during the construction phase. michael@0: */ michael@0: void emitSamplers(GrGLShaderBuilder*, const GrEffectRef&, TextureSamplerArray*); michael@0: michael@0: /** michael@0: * Helper for setData(). Binds all the textures for an effect. michael@0: */ michael@0: void bindTextures(GrGpuGL*, const GrEffectRef&, int effectIdx); michael@0: michael@0: struct Sampler { michael@0: SkDEBUGCODE(Sampler() : fTextureUnit(-1) {}) michael@0: UniformHandle fUniform; michael@0: int fTextureUnit; michael@0: }; michael@0: michael@0: SkTArray fGLEffects; michael@0: SkTArray > fSamplers; michael@0: }; michael@0: michael@0: /** michael@0: * This is an abstract base class for constructing different types of GrGLProgramEffects objects. michael@0: */ michael@0: class GrGLProgramEffectsBuilder { michael@0: public: michael@0: virtual ~GrGLProgramEffectsBuilder() { } michael@0: michael@0: /** michael@0: * Emits the effect's shader code, and stores the necessary uniforms internally. michael@0: */ michael@0: virtual void emitEffect(const GrEffectStage&, michael@0: GrGLProgramEffects::EffectKey, michael@0: const char* outColor, michael@0: const char* inColor, michael@0: int stageIndex) = 0; michael@0: }; michael@0: michael@0: //////////////////////////////////////////////////////////////////////////////// michael@0: michael@0: /** michael@0: * This is a GrGLProgramEffects implementation that does coord transforms with the vertex shader. michael@0: */ michael@0: class GrGLVertexProgramEffects : public GrGLProgramEffects { michael@0: public: michael@0: virtual void setData(GrGpuGL*, michael@0: const GrGLUniformManager&, michael@0: const GrEffectStage* effectStages[]) SK_OVERRIDE; michael@0: michael@0: private: michael@0: friend class GrGLVertexProgramEffectsBuilder; michael@0: michael@0: GrGLVertexProgramEffects(int reserveCount, bool explicitLocalCoords) michael@0: : INHERITED(reserveCount) michael@0: , fTransforms(reserveCount) michael@0: , fHasExplicitLocalCoords(explicitLocalCoords) { michael@0: } michael@0: michael@0: /** michael@0: * Helper for GrGLProgramEffectsBuilder::emitEfffect(). This method is meant to only be called michael@0: * during the construction phase. michael@0: */ michael@0: void emitEffect(GrGLFullShaderBuilder*, michael@0: const GrEffectStage&, michael@0: GrGLProgramEffects::EffectKey, michael@0: const char* outColor, michael@0: const char* inColor, michael@0: int stageIndex); michael@0: michael@0: /** michael@0: * Helper for emitEffect(). Emits any attributes an effect may have. michael@0: */ michael@0: void emitAttributes(GrGLFullShaderBuilder*, const GrEffectStage&); michael@0: michael@0: /** michael@0: * Helper for emitEffect(). Emits code to implement an effect's coord transforms in the VS. michael@0: * Varyings are added as an outputs of the VS and inputs to the FS. The varyings may be either a michael@0: * vec2f or vec3f depending upon whether perspective interpolation is required or not. The names michael@0: * of the varyings in the VS and FS as well their types are appended to the michael@0: * TransformedCoordsArray* object, which is in turn passed to the effect's emitCode() function. michael@0: */ michael@0: void emitTransforms(GrGLFullShaderBuilder*, michael@0: const GrEffectRef&, michael@0: EffectKey, michael@0: TransformedCoordsArray*); michael@0: michael@0: /** michael@0: * Helper for setData(). Sets all the transform matrices for an effect. michael@0: */ michael@0: void setTransformData(const GrGLUniformManager&, const GrDrawEffect&, int effectIdx); michael@0: michael@0: struct Transform { michael@0: Transform() { fCurrentValue = SkMatrix::InvalidMatrix(); } michael@0: UniformHandle fHandle; michael@0: GrSLType fType; michael@0: SkMatrix fCurrentValue; michael@0: }; michael@0: michael@0: SkTArray > fTransforms; michael@0: bool fHasExplicitLocalCoords; michael@0: michael@0: typedef GrGLProgramEffects INHERITED; michael@0: }; michael@0: michael@0: /** michael@0: * This class is used to construct a GrGLVertexProgramEffects* object. michael@0: */ michael@0: class GrGLVertexProgramEffectsBuilder : public GrGLProgramEffectsBuilder { michael@0: public: michael@0: GrGLVertexProgramEffectsBuilder(GrGLFullShaderBuilder*, int reserveCount); michael@0: virtual ~GrGLVertexProgramEffectsBuilder() { } michael@0: michael@0: virtual void emitEffect(const GrEffectStage&, michael@0: GrGLProgramEffects::EffectKey, michael@0: const char* outColor, michael@0: const char* inColor, michael@0: int stageIndex) SK_OVERRIDE; michael@0: michael@0: /** michael@0: * Finalizes the building process and returns the effect array. After this call, the builder michael@0: * becomes invalid. michael@0: */ michael@0: GrGLProgramEffects* finish() { return fProgramEffects.detach(); } michael@0: michael@0: private: michael@0: GrGLFullShaderBuilder* fBuilder; michael@0: SkAutoTDelete fProgramEffects; michael@0: michael@0: typedef GrGLProgramEffectsBuilder INHERITED; michael@0: }; michael@0: michael@0: //////////////////////////////////////////////////////////////////////////////// michael@0: michael@0: /** michael@0: * This is a GrGLProgramEffects implementation that does coord transforms with the the built-in GL michael@0: * TexGen functionality. michael@0: */ michael@0: class GrGLTexGenProgramEffects : public GrGLProgramEffects { michael@0: public: michael@0: virtual void setData(GrGpuGL*, michael@0: const GrGLUniformManager&, michael@0: const GrEffectStage* effectStages[]) SK_OVERRIDE; michael@0: michael@0: private: michael@0: friend class GrGLTexGenProgramEffectsBuilder; michael@0: michael@0: GrGLTexGenProgramEffects(int reserveCount) michael@0: : INHERITED(reserveCount) michael@0: , fTransforms(reserveCount) { michael@0: } michael@0: michael@0: /** michael@0: * Helper for GrGLProgramEffectsBuilder::emitEfffect(). This method is meant to only be called michael@0: * during the construction phase. michael@0: */ michael@0: void emitEffect(GrGLFragmentOnlyShaderBuilder*, michael@0: const GrEffectStage&, michael@0: GrGLProgramEffects::EffectKey, michael@0: const char* outColor, michael@0: const char* inColor, michael@0: int stageIndex); michael@0: michael@0: /** michael@0: * Helper for emitEffect(). Allocates texture units from the builder for each transform in an michael@0: * effect. The transforms all use adjacent texture units. They either use two or three of the michael@0: * coordinates at a given texture unit, depending on if they need perspective interpolation. michael@0: * The expressions to access the transformed coords (i.e. 'vec2(gl_TexCoord[0])') as well as the michael@0: * types are appended to the TransformedCoordsArray* object, which is in turn passed to the michael@0: * effect's emitCode() function. michael@0: */ michael@0: void setupTexGen(GrGLFragmentOnlyShaderBuilder*, michael@0: const GrEffectRef&, michael@0: EffectKey, michael@0: TransformedCoordsArray*); michael@0: michael@0: /** michael@0: * Helper for setData(). Sets the TexGen state for each transform in an effect. michael@0: */ michael@0: void setTexGenState(GrGpuGL*, const GrDrawEffect&, int effectIdx); michael@0: michael@0: struct Transforms { michael@0: Transforms(EffectKey transformKey, int texCoordIndex) michael@0: : fTransformKey(transformKey), fTexCoordIndex(texCoordIndex) {} michael@0: EffectKey fTransformKey; michael@0: int fTexCoordIndex; michael@0: }; michael@0: michael@0: SkTArray fTransforms; michael@0: michael@0: typedef GrGLProgramEffects INHERITED; michael@0: }; michael@0: michael@0: /** michael@0: * This class is used to construct a GrGLTexGenProgramEffects* object. michael@0: */ michael@0: class GrGLTexGenProgramEffectsBuilder : public GrGLProgramEffectsBuilder { michael@0: public: michael@0: GrGLTexGenProgramEffectsBuilder(GrGLFragmentOnlyShaderBuilder*, int reserveCount); michael@0: virtual ~GrGLTexGenProgramEffectsBuilder() { } michael@0: michael@0: virtual void emitEffect(const GrEffectStage&, michael@0: GrGLProgramEffects::EffectKey, michael@0: const char* outColor, michael@0: const char* inColor, michael@0: int stageIndex) SK_OVERRIDE; michael@0: michael@0: /** michael@0: * Finalizes the building process and returns the effect array. After this call, the builder michael@0: * becomes invalid. michael@0: */ michael@0: GrGLProgramEffects* finish() { return fProgramEffects.detach(); } michael@0: michael@0: private: michael@0: GrGLFragmentOnlyShaderBuilder* fBuilder; michael@0: SkAutoTDelete fProgramEffects; michael@0: michael@0: typedef GrGLProgramEffectsBuilder INHERITED; michael@0: }; michael@0: michael@0: #endif