diff options
Diffstat (limited to 'src/gpu/GrGLProgram.h')
-rw-r--r-- | src/gpu/GrGLProgram.h | 347 |
1 files changed, 347 insertions, 0 deletions
diff --git a/src/gpu/GrGLProgram.h b/src/gpu/GrGLProgram.h new file mode 100644 index 0000000000..dafa79dc29 --- /dev/null +++ b/src/gpu/GrGLProgram.h @@ -0,0 +1,347 @@ + +/* + * Copyright 2011 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + + +#ifndef GrGLProgram_DEFINED +#define GrGLProgram_DEFINED + +#include "GrGLInterface.h" +#include "GrStringBuilder.h" +#include "GrGpu.h" + +#include "SkXfermode.h" + +class GrBinHashKeyBuilder; + +struct ShaderCodeSegments; + +// optionally compile the experimental GS code. Set to GR_DEBUG +// so that debug build bots will execute the code. +#define GR_GL_EXPERIMENTAL_GS GR_DEBUG + +/** + * This class manages a GPU program and records per-program information. + * We can specify the attribute locations so that they are constant + * across our shaders. But the driver determines the uniform locations + * at link time. We don't need to remember the sampler uniform location + * because we will bind a texture slot to it and never change it + * Uniforms are program-local so we can't rely on fHWState to hold the + * previous uniform state after a program change. + */ +class GrGLProgram { +public: + enum GLSLVersion { + k120_GLSLVersion, // Desktop GLSL 1.20 and ES2 shading lang + k130_GLSLVersion, // Desktop GLSL 1.30 + k150_GLSLVersion // Dekstop GLSL 1.50 + }; + + class CachedData; + + GrGLProgram(); + ~GrGLProgram(); + + /** + * This is the heavy initilization routine for building a GLProgram. + * The result of heavy init is not stored in datamembers of GrGLProgam, + * but in a separate cacheable container. + */ + bool genProgram(const GrGLInterface* gl, + GLSLVersion glslVersion, + CachedData* programData) const; + + /** + * The shader may modify the blend coeffecients. Params are in/out + */ + void overrideBlend(GrBlendCoeff* srcCoeff, GrBlendCoeff* dstCoeff) const; + + /** + * Attribute indices + */ + static int PositionAttributeIdx() { return 0; } + static int TexCoordAttributeIdx(int tcIdx) { return 1 + tcIdx; } + static int ColorAttributeIdx() { return 1 + GrDrawTarget::kMaxTexCoords; } + static int CoverageAttributeIdx() { + return 2 + GrDrawTarget::kMaxTexCoords; + } + static int EdgeAttributeIdx() { return 3 + GrDrawTarget::kMaxTexCoords; } + + static int ViewMatrixAttributeIdx() { + return 2 + GrDrawTarget::kMaxTexCoords; + } + static int TextureMatrixAttributeIdx(int stage) { + return 5 + GrDrawTarget::kMaxTexCoords + 3 * stage; + } + +private: + + // Parameters that affect code generation + // These structs should be kept compact; they are the input to an + // expensive hash key generator. + struct ProgramDesc { + ProgramDesc() { + // since we use this as part of a key we can't have any unitialized + // padding + memset(this, 0, sizeof(ProgramDesc)); + } + + struct StageDesc { + enum OptFlagBits { + kNoPerspective_OptFlagBit = 1 << 0, + kIdentityMatrix_OptFlagBit = 1 << 1, + kCustomTextureDomain_OptFlagBit = 1 << 2, + kIsEnabled_OptFlagBit = 1 << 7 + }; + enum Modulation { + kColor_Modulation, + kAlpha_Modulation, + + kModulationCnt + }; + enum FetchMode { + kSingle_FetchMode, + k2x2_FetchMode, + kConvolution_FetchMode, + + kFetchModeCnt, + }; + enum CoordMapping { + kIdentity_CoordMapping, + kRadialGradient_CoordMapping, + kSweepGradient_CoordMapping, + kRadial2Gradient_CoordMapping, + // need different shader computation when quadratic + // eq describing the gradient degenerates to a linear eq. + kRadial2GradientDegenerate_CoordMapping, + kCoordMappingCnt + }; + + uint8_t fOptFlags; + uint8_t fModulation; // casts to enum Modulation + uint8_t fFetchMode; // casts to enum FetchMode + uint8_t fCoordMapping; // casts to enum CoordMapping + uint8_t fKernelWidth; + + inline bool isEnabled() const { + return SkToBool(fOptFlags & kIsEnabled_OptFlagBit); + } + inline void setEnabled(bool newValue) { + if (newValue) { + fOptFlags |= kIsEnabled_OptFlagBit; + } else { + fOptFlags &= ~kIsEnabled_OptFlagBit; + } + } + }; + + // Specifies where the intitial color comes from before the stages are + // applied. + enum ColorType { + kSolidWhite_ColorType, + kTransBlack_ColorType, + kAttribute_ColorType, + kUniform_ColorType, + + kColorTypeCnt + }; + // Dual-src blending makes use of a secondary output color that can be + // used as a per-pixel blend coeffecient. This controls whether a + // secondary source is output and what value it holds. + enum DualSrcOutput { + kNone_DualSrcOutput, + kCoverage_DualSrcOutput, + kCoverageISA_DualSrcOutput, + kCoverageISC_DualSrcOutput, + + kDualSrcOutputCnt + }; + + GrDrawTarget::VertexEdgeType fVertexEdgeType; + + // stripped of bits that don't affect prog generation + GrVertexLayout fVertexLayout; + + StageDesc fStages[GrDrawTarget::kNumStages]; + + // To enable experimental geometry shader code (not for use in + // production) +#if GR_GL_EXPERIMENTAL_GS + bool fExperimentalGS; +#endif + + uint8_t fColorType; // casts to enum ColorType + uint8_t fDualSrcOutput; // casts to enum DualSrcOutput + int8_t fFirstCoverageStage; + SkBool8 fEmitsPointSize; + SkBool8 fEdgeAAConcave; + + int8_t fEdgeAANumEdges; + uint8_t fColorFilterXfermode; // casts to enum SkXfermode::Mode + + uint8_t fPadTo32bLengthMultiple [1]; + + } fProgramDesc; + GR_STATIC_ASSERT(!(sizeof(ProgramDesc) % 4)); + + const ProgramDesc& getDesc() { return fProgramDesc; } + + // for code readability + typedef ProgramDesc::StageDesc StageDesc; + +public: + enum { + kUnusedUniform = -1, + kSetAsAttribute = 1000, + }; + + struct StageUniLocations { + GrGLint fTextureMatrixUni; + GrGLint fNormalizedTexelSizeUni; + GrGLint fSamplerUni; + GrGLint fRadial2Uni; + GrGLint fTexDomUni; + GrGLint fKernelUni; + GrGLint fImageIncrementUni; + void reset() { + fTextureMatrixUni = kUnusedUniform; + fNormalizedTexelSizeUni = kUnusedUniform; + fSamplerUni = kUnusedUniform; + fRadial2Uni = kUnusedUniform; + fTexDomUni = kUnusedUniform; + fKernelUni = kUnusedUniform; + fImageIncrementUni = kUnusedUniform; + } + }; + + struct UniLocations { + GrGLint fViewMatrixUni; + GrGLint fColorUni; + GrGLint fEdgesUni; + GrGLint fColorFilterUni; + StageUniLocations fStages[GrDrawTarget::kNumStages]; + void reset() { + fViewMatrixUni = kUnusedUniform; + fColorUni = kUnusedUniform; + fEdgesUni = kUnusedUniform; + fColorFilterUni = kUnusedUniform; + for (int s = 0; s < GrDrawTarget::kNumStages; ++s) { + fStages[s].reset(); + } + } + }; + + class CachedData : public ::GrNoncopyable { + public: + CachedData() { + } + + ~CachedData() { + } + + void copyAndTakeOwnership(CachedData& other) { + memcpy(this, &other, sizeof(*this)); + } + + public: + + // IDs + GrGLuint fVShaderID; + GrGLuint fGShaderID; + GrGLuint fFShaderID; + GrGLuint fProgramID; + // shader uniform locations (-1 if shader doesn't use them) + UniLocations fUniLocations; + + GrMatrix fViewMatrix; + + // these reflect the current values of uniforms + // (GL uniform values travel with program) + GrColor fColor; + GrColor fColorFilterColor; + GrMatrix fTextureMatrices[GrDrawTarget::kNumStages]; + // width and height used for normalized texel size + int fTextureWidth[GrDrawTarget::kNumStages]; + int fTextureHeight[GrDrawTarget::kNumStages]; + GrScalar fRadial2CenterX1[GrDrawTarget::kNumStages]; + GrScalar fRadial2Radius0[GrDrawTarget::kNumStages]; + bool fRadial2PosRoot[GrDrawTarget::kNumStages]; + GrRect fTextureDomain[GrDrawTarget::kNumStages]; + + private: + enum Constants { + kUniLocationPreAllocSize = 8 + }; + + }; // CachedData + + enum Constants { + kProgramKeySize = sizeof(ProgramDesc) + }; + + // Provide an opaque ProgramDesc + const uint32_t* keyData() const{ + return reinterpret_cast<const uint32_t*>(&fProgramDesc); + } + +private: + enum { + kUseUniform = 2000 + }; + + // should set all fields in locations var to kUseUniform if the + // corresponding uniform is required for the program. + void genStageCode(const GrGLInterface* gl, + int stageNum, + const ProgramDesc::StageDesc& desc, + const char* fsInColor, // NULL means no incoming color + const char* fsOutColor, + const char* vsInCoord, + ShaderCodeSegments* segments, + StageUniLocations* locations) const; + + void genGeometryShader(const GrGLInterface* gl, + GLSLVersion glslVersion, + ShaderCodeSegments* segments) const; + + // generates code to compute coverage based on edge AA. + void genEdgeCoverage(const GrGLInterface* gl, + GrVertexLayout layout, + CachedData* programData, + GrStringBuilder* coverageVar, + ShaderCodeSegments* segments) const; + + static bool CompileShaders(const GrGLInterface* gl, + GLSLVersion glslVersion, + const ShaderCodeSegments& segments, + CachedData* programData); + + // Compiles a GL shader, returns shader ID or 0 if failed + // params have same meaning as glShaderSource + static GrGLuint CompileShader(const GrGLInterface* gl, + GrGLenum type, int stringCnt, + const char** strings, + int* stringLengths); + + // Creates a GL program ID, binds shader attributes to GL vertex attrs, and + // links the program + bool bindOutputsAttribsAndLinkProgram( + const GrGLInterface* gl, + GrStringBuilder texCoordAttrNames[GrDrawTarget::kMaxTexCoords], + bool bindColorOut, + bool bindDualSrcOut, + CachedData* programData) const; + + // Gets locations for all uniforms set to kUseUniform and initializes cache + // to invalid values. + void getUniformLocationsAndInitCache(const GrGLInterface* gl, + CachedData* programData) const; + + friend class GrGpuGLShaders; +}; + +#endif |