1 /* 2 * Copyright 2011 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #include "GrGLProgram.h" 9 10 #include "GrAllocator.h" 11 #include "GrProcessor.h" 12 #include "GrCoordTransform.h" 13 #include "GrGLGpu.h" 14 #include "GrGLBuffer.h" 15 #include "GrGLPathRendering.h" 16 #include "GrPathProcessor.h" 17 #include "GrPipeline.h" 18 #include "GrXferProcessor.h" 19 #include "glsl/GrGLSLFragmentProcessor.h" 20 #include "glsl/GrGLSLGeometryProcessor.h" 21 #include "glsl/GrGLSLXferProcessor.h" 22 23 #define GL_CALL(X) GR_GL_CALL(fGpu->glInterface(), X) 24 #define GL_CALL_RET(R, X) GR_GL_CALL_RET(fGpu->glInterface(), R, X) 25 26 /////////////////////////////////////////////////////////////////////////////////////////////////// 27 28 GrGLProgram::GrGLProgram(GrGLGpu* gpu, 29 const GrProgramDesc& desc, 30 const BuiltinUniformHandles& builtinUniforms, 31 GrGLuint programID, 32 const UniformInfoArray& uniforms, 33 const UniformInfoArray& textureSamplers, 34 const UniformInfoArray& texelBuffers, 35 const VaryingInfoArray& pathProcVaryings, 36 std::unique_ptr<GrGLSLPrimitiveProcessor> geometryProcessor, 37 std::unique_ptr<GrGLSLXferProcessor> xferProcessor, 38 const GrGLSLFragProcs& fragmentProcessors) 39 : fBuiltinUniformHandles(builtinUniforms) 40 , fProgramID(programID) 41 , fGeometryProcessor(std::move(geometryProcessor)) 42 , fXferProcessor(std::move(xferProcessor)) 43 , fFragmentProcessors(fragmentProcessors) 44 , fDesc(desc) 45 , fGpu(gpu) 46 , fProgramDataManager(gpu, programID, uniforms, pathProcVaryings) 47 , fNumTextureSamplers(textureSamplers.count()) 48 , fNumTexelBuffers(texelBuffers.count()) { 49 // Assign texture units to sampler uniforms one time up front. 50 GL_CALL(UseProgram(fProgramID)); 51 fProgramDataManager.setSamplerUniforms(textureSamplers, 0); 52 fProgramDataManager.setSamplerUniforms(texelBuffers, fNumTextureSamplers); 53 } 54 55 GrGLProgram::~GrGLProgram() { 56 if (fProgramID) { 57 GL_CALL(DeleteProgram(fProgramID)); 58 } 59 for (int i = 0; i < fFragmentProcessors.count(); ++i) { 60 delete fFragmentProcessors[i]; 61 } 62 } 63 64 void GrGLProgram::abandon() { 65 fProgramID = 0; 66 } 67 68 /////////////////////////////////////////////////////////////////////////////// 69 70 void GrGLProgram::setData(const GrPrimitiveProcessor& primProc, const GrPipeline& pipeline) { 71 this->setRenderTargetState(primProc, pipeline.proxy()); 72 73 // we set the textures, and uniforms for installed processors in a generic way, but subclasses 74 // of GLProgram determine how to set coord transforms 75 76 // We must bind to texture units in the same order in which we set the uniforms in 77 // GrGLProgramDataManager. That is first all texture samplers and then texel buffers. 78 // Within each group we will bind them in primProc, fragProcs, XP order. 79 int nextTexSamplerIdx = 0; 80 int nextTexelBufferIdx = fNumTextureSamplers; 81 fGeometryProcessor->setData(fProgramDataManager, primProc, 82 GrFragmentProcessor::CoordTransformIter(pipeline)); 83 this->bindTextures(primProc, pipeline.getAllowSRGBInputs(), &nextTexSamplerIdx, 84 &nextTexelBufferIdx); 85 86 this->setFragmentData(primProc, pipeline, &nextTexSamplerIdx, &nextTexelBufferIdx); 87 88 const GrXferProcessor& xp = pipeline.getXferProcessor(); 89 SkIPoint offset; 90 GrTexture* dstTexture = pipeline.peekDstTexture(&offset); 91 92 fXferProcessor->setData(fProgramDataManager, xp, dstTexture, offset); 93 if (dstTexture) { 94 fGpu->bindTexture(nextTexSamplerIdx++, GrSamplerState::ClampNearest(), true, 95 static_cast<GrGLTexture*>(dstTexture), 96 pipeline.dstTextureProxy()->origin()); 97 } 98 SkASSERT(nextTexSamplerIdx == fNumTextureSamplers); 99 SkASSERT(nextTexelBufferIdx == fNumTextureSamplers + fNumTexelBuffers); 100 } 101 102 void GrGLProgram::generateMipmaps(const GrPrimitiveProcessor& primProc, 103 const GrPipeline& pipeline) { 104 this->generateMipmaps(primProc, pipeline.getAllowSRGBInputs()); 105 106 GrFragmentProcessor::Iter iter(pipeline); 107 while (const GrFragmentProcessor* fp = iter.next()) { 108 this->generateMipmaps(*fp, pipeline.getAllowSRGBInputs()); 109 } 110 } 111 112 void GrGLProgram::setFragmentData(const GrPrimitiveProcessor& primProc, 113 const GrPipeline& pipeline, 114 int* nextTexSamplerIdx, 115 int* nextTexelBufferIdx) { 116 GrFragmentProcessor::Iter iter(pipeline); 117 GrGLSLFragmentProcessor::Iter glslIter(fFragmentProcessors.begin(), 118 fFragmentProcessors.count()); 119 const GrFragmentProcessor* fp = iter.next(); 120 GrGLSLFragmentProcessor* glslFP = glslIter.next(); 121 while (fp && glslFP) { 122 glslFP->setData(fProgramDataManager, *fp); 123 this->bindTextures(*fp, pipeline.getAllowSRGBInputs(), nextTexSamplerIdx, 124 nextTexelBufferIdx); 125 fp = iter.next(); 126 glslFP = glslIter.next(); 127 } 128 SkASSERT(!fp && !glslFP); 129 } 130 131 132 void GrGLProgram::setRenderTargetState(const GrPrimitiveProcessor& primProc, 133 const GrRenderTargetProxy* proxy) { 134 GrRenderTarget* rt = proxy->priv().peekRenderTarget(); 135 // Load the RT height uniform if it is needed to y-flip gl_FragCoord. 136 if (fBuiltinUniformHandles.fRTHeightUni.isValid() && 137 fRenderTargetState.fRenderTargetSize.fHeight != rt->height()) { 138 fProgramDataManager.set1f(fBuiltinUniformHandles.fRTHeightUni, SkIntToScalar(rt->height())); 139 } 140 141 // set RT adjustment 142 SkISize size; 143 size.set(rt->width(), rt->height()); 144 if (!primProc.isPathRendering()) { 145 if (fRenderTargetState.fRenderTargetOrigin != proxy->origin() || 146 fRenderTargetState.fRenderTargetSize != size) { 147 fRenderTargetState.fRenderTargetSize = size; 148 fRenderTargetState.fRenderTargetOrigin = proxy->origin(); 149 150 float rtAdjustmentVec[4]; 151 fRenderTargetState.getRTAdjustmentVec(rtAdjustmentVec); 152 fProgramDataManager.set4fv(fBuiltinUniformHandles.fRTAdjustmentUni, 1, rtAdjustmentVec); 153 } 154 } else { 155 SkASSERT(fGpu->glCaps().shaderCaps()->pathRenderingSupport()); 156 const GrPathProcessor& pathProc = primProc.cast<GrPathProcessor>(); 157 fGpu->glPathRendering()->setProjectionMatrix(pathProc.viewMatrix(), 158 size, proxy->origin()); 159 } 160 } 161 162 void GrGLProgram::bindTextures(const GrResourceIOProcessor& processor, 163 bool allowSRGBInputs, 164 int* nextTexSamplerIdx, 165 int* nextTexelBufferIdx) { 166 for (int i = 0; i < processor.numTextureSamplers(); ++i) { 167 const GrResourceIOProcessor::TextureSampler& sampler = processor.textureSampler(i); 168 fGpu->bindTexture((*nextTexSamplerIdx)++, sampler.samplerState(), allowSRGBInputs, 169 static_cast<GrGLTexture*>(sampler.peekTexture()), 170 sampler.proxy()->origin()); 171 } 172 for (int i = 0; i < processor.numBuffers(); ++i) { 173 const GrResourceIOProcessor::BufferAccess& access = processor.bufferAccess(i); 174 fGpu->bindTexelBuffer((*nextTexelBufferIdx)++, access.texelConfig(), 175 static_cast<GrGLBuffer*>(access.buffer())); 176 } 177 } 178 179 void GrGLProgram::generateMipmaps(const GrResourceIOProcessor& processor, bool allowSRGBInputs) { 180 for (int i = 0; i < processor.numTextureSamplers(); ++i) { 181 const GrResourceIOProcessor::TextureSampler& sampler = processor.textureSampler(i); 182 fGpu->generateMipmaps(sampler.samplerState(), allowSRGBInputs, 183 static_cast<GrGLTexture*>(sampler.peekTexture()), 184 sampler.proxy()->origin()); 185 } 186 } 187