michael@0: /* michael@0: * Copyright 2011 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: michael@0: #ifndef GrGLProgram_DEFINED michael@0: #define GrGLProgram_DEFINED michael@0: michael@0: #include "GrDrawState.h" michael@0: #include "GrGLContext.h" michael@0: #include "GrGLProgramDesc.h" michael@0: #include "GrGLShaderBuilder.h" michael@0: #include "GrGLSL.h" michael@0: #include "GrGLTexture.h" michael@0: #include "GrGLUniformManager.h" michael@0: michael@0: #include "SkString.h" michael@0: #include "SkXfermode.h" michael@0: michael@0: class GrBinHashKeyBuilder; michael@0: class GrGLEffect; michael@0: class GrGLProgramEffects; michael@0: class GrGLShaderBuilder; michael@0: michael@0: /** michael@0: * This class manages a GPU program and records per-program information. michael@0: * We can specify the attribute locations so that they are constant michael@0: * across our shaders. But the driver determines the uniform locations michael@0: * at link time. We don't need to remember the sampler uniform location michael@0: * because we will bind a texture slot to it and never change it michael@0: * Uniforms are program-local so we can't rely on fHWState to hold the michael@0: * previous uniform state after a program change. michael@0: */ michael@0: class GrGLProgram : public SkRefCnt { michael@0: public: michael@0: SK_DECLARE_INST_COUNT(GrGLProgram) michael@0: michael@0: static GrGLProgram* Create(GrGpuGL* gpu, michael@0: const GrGLProgramDesc& desc, michael@0: const GrEffectStage* colorStages[], michael@0: const GrEffectStage* coverageStages[]); michael@0: michael@0: virtual ~GrGLProgram(); michael@0: michael@0: /** michael@0: * Call to abandon GL objects owned by this program. michael@0: */ michael@0: void abandon(); michael@0: michael@0: /** michael@0: * The shader may modify the blend coefficients. Params are in/out. michael@0: */ michael@0: void overrideBlend(GrBlendCoeff* srcCoeff, GrBlendCoeff* dstCoeff) const; michael@0: michael@0: const GrGLProgramDesc& getDesc() { return fDesc; } michael@0: michael@0: /** michael@0: * Gets the GL program ID for this program. michael@0: */ michael@0: GrGLuint programID() const { return fProgramID; } michael@0: michael@0: bool hasVertexShader() const { return fHasVertexShader; } michael@0: michael@0: /** michael@0: * Some GL state that is relevant to programs is not stored per-program. In particular color michael@0: * and coverage attributes can be global state. This struct is read and updated by michael@0: * GrGLProgram::setColor and GrGLProgram::setCoverage to allow us to avoid setting this state michael@0: * redundantly. michael@0: */ michael@0: struct SharedGLState { michael@0: GrColor fConstAttribColor; michael@0: int fConstAttribColorIndex; michael@0: GrColor fConstAttribCoverage; michael@0: int fConstAttribCoverageIndex; michael@0: michael@0: SharedGLState() { this->invalidate(); } michael@0: void invalidate() { michael@0: fConstAttribColor = GrColor_ILLEGAL; michael@0: fConstAttribColorIndex = -1; michael@0: fConstAttribCoverage = GrColor_ILLEGAL; michael@0: fConstAttribCoverageIndex = -1; michael@0: } michael@0: }; michael@0: michael@0: /** michael@0: * The GrDrawState's view matrix along with the aspects of the render target determine the michael@0: * matrix sent to GL. The size of the render target affects the GL matrix because we must michael@0: * convert from Skia device coords to GL's normalized coords. Also the origin of the render michael@0: * target may require us to perform a mirror-flip. michael@0: */ michael@0: struct MatrixState { michael@0: SkMatrix fViewMatrix; michael@0: SkISize fRenderTargetSize; michael@0: GrSurfaceOrigin fRenderTargetOrigin; michael@0: michael@0: MatrixState() { this->invalidate(); } michael@0: void invalidate() { michael@0: fViewMatrix = SkMatrix::InvalidMatrix(); michael@0: fRenderTargetSize.fWidth = -1; michael@0: fRenderTargetSize.fHeight = -1; michael@0: fRenderTargetOrigin = (GrSurfaceOrigin) -1; michael@0: } michael@0: template void getGLMatrix(GrGLfloat* destMatrix) { michael@0: SkMatrix combined; michael@0: if (kBottomLeft_GrSurfaceOrigin == fRenderTargetOrigin) { michael@0: combined.setAll(SkIntToScalar(2) / fRenderTargetSize.fWidth, 0, -SK_Scalar1, michael@0: 0, -SkIntToScalar(2) / fRenderTargetSize.fHeight, SK_Scalar1, michael@0: 0, 0, SkMatrix::I()[8]); michael@0: } else { michael@0: combined.setAll(SkIntToScalar(2) / fRenderTargetSize.fWidth, 0, -SK_Scalar1, michael@0: 0, SkIntToScalar(2) / fRenderTargetSize.fHeight, -SK_Scalar1, michael@0: 0, 0, SkMatrix::I()[8]); michael@0: } michael@0: combined.setConcat(combined, fViewMatrix); michael@0: GrGLGetMatrix(destMatrix, combined); michael@0: } michael@0: }; michael@0: michael@0: /** michael@0: * This function uploads uniforms and calls each GrGLEffect's setData. It is called before a michael@0: * draw occurs using the program after the program has already been bound. It also uses the michael@0: * GrGpuGL object to bind the textures required by the GrGLEffects. The color and coverage michael@0: * stages come from GrGLProgramDesc::Build(). michael@0: */ michael@0: void setData(GrDrawState::BlendOptFlags, michael@0: const GrEffectStage* colorStages[], michael@0: const GrEffectStage* coverageStages[], michael@0: const GrDeviceCoordTexture* dstCopy, // can be NULL michael@0: SharedGLState*); michael@0: michael@0: private: michael@0: typedef GrGLUniformManager::UniformHandle UniformHandle; michael@0: michael@0: // handles for uniforms (aside from per-effect samplers) michael@0: struct UniformHandles { michael@0: UniformHandle fViewMatrixUni; michael@0: UniformHandle fColorUni; michael@0: UniformHandle fCoverageUni; michael@0: michael@0: // We use the render target height to provide a y-down frag coord when specifying michael@0: // origin_upper_left is not supported. michael@0: UniformHandle fRTHeightUni; michael@0: michael@0: // Uniforms for computing texture coords to do the dst-copy lookup michael@0: UniformHandle fDstCopyTopLeftUni; michael@0: UniformHandle fDstCopyScaleUni; michael@0: UniformHandle fDstCopySamplerUni; michael@0: }; michael@0: michael@0: GrGLProgram(GrGpuGL* gpu, michael@0: const GrGLProgramDesc& desc, michael@0: const GrEffectStage* colorStages[], michael@0: const GrEffectStage* coverageStages[]); michael@0: michael@0: bool succeeded() const { return 0 != fProgramID; } michael@0: michael@0: /** michael@0: * This is the heavy initialization routine for building a GLProgram. colorStages and michael@0: * coverageStages correspond to the output of GrGLProgramDesc::Build(). michael@0: */ michael@0: bool genProgram(GrGLShaderBuilder* builder, michael@0: const GrEffectStage* colorStages[], michael@0: const GrEffectStage* coverageStages[]); michael@0: michael@0: // Sets the texture units for samplers michael@0: void initSamplerUniforms(); michael@0: michael@0: // Helper for setData(). Makes GL calls to specify the initial color when there is not michael@0: // per-vertex colors. michael@0: void setColor(const GrDrawState&, GrColor color, SharedGLState*); michael@0: michael@0: // Helper for setData(). Makes GL calls to specify the initial coverage when there is not michael@0: // per-vertex coverages. michael@0: void setCoverage(const GrDrawState&, GrColor coverage, SharedGLState*); michael@0: michael@0: // Helper for setData() that sets the view matrix and loads the render target height uniform michael@0: void setMatrixAndRenderTargetHeight(const GrDrawState&); michael@0: michael@0: // GL program ID michael@0: GrGLuint fProgramID; michael@0: michael@0: // these reflect the current values of uniforms (GL uniform values travel with program) michael@0: MatrixState fMatrixState; michael@0: GrColor fColor; michael@0: GrColor fCoverage; michael@0: int fDstCopyTexUnit; michael@0: michael@0: SkAutoTDelete fColorEffects; michael@0: SkAutoTDelete fCoverageEffects; michael@0: michael@0: GrGLProgramDesc fDesc; michael@0: GrGpuGL* fGpu; michael@0: michael@0: GrGLUniformManager fUniformManager; michael@0: UniformHandles fUniformHandles; michael@0: michael@0: bool fHasVertexShader; michael@0: int fNumTexCoordSets; michael@0: michael@0: typedef SkRefCnt INHERITED; michael@0: }; michael@0: michael@0: #endif