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& samplers, 34 const UniformInfoArray& imageStorages, 35 const VaryingInfoArray& pathProcVaryings, 36 GrGLSLPrimitiveProcessor* geometryProcessor, 37 GrGLSLXferProcessor* xferProcessor, 38 const GrGLSLFragProcs& fragmentProcessors) 39 : fBuiltinUniformHandles(builtinUniforms) 40 , fProgramID(programID) 41 , fGeometryProcessor(geometryProcessor) 42 , fXferProcessor(xferProcessor) 43 , fFragmentProcessors(fragmentProcessors) 44 , fDesc(desc) 45 , fGpu(gpu) 46 , fProgramDataManager(gpu, programID, uniforms, pathProcVaryings) { 47 // Assign texture units to sampler uniforms one time up front. 48 GL_CALL(UseProgram(fProgramID)); 49 fProgramDataManager.setSamplers(samplers); 50 fProgramDataManager.setImageStorages(imageStorages); 51 } 52 53 GrGLProgram::~GrGLProgram() { 54 if (fProgramID) { 55 GL_CALL(DeleteProgram(fProgramID)); 56 } 57 for (int i = 0; i < fFragmentProcessors.count(); ++i) { 58 delete fFragmentProcessors[i]; 59 } 60 } 61 62 void GrGLProgram::abandon() { 63 fProgramID = 0; 64 } 65 66 /////////////////////////////////////////////////////////////////////////////// 67 68 void GrGLProgram::setData(const GrPrimitiveProcessor& primProc, const GrPipeline& pipeline) { 69 this->setRenderTargetState(primProc, pipeline); 70 71 // we set the textures, and uniforms for installed processors in a generic way, but subclasses 72 // of GLProgram determine how to set coord transforms 73 int nextSamplerIdx = 0; 74 fGeometryProcessor->setData(fProgramDataManager, primProc, 75 GrFragmentProcessor::CoordTransformIter(pipeline)); 76 this->bindTextures(primProc, pipeline.getAllowSRGBInputs(), &nextSamplerIdx); 77 78 this->setFragmentData(primProc, pipeline, &nextSamplerIdx); 79 80 const GrXferProcessor& xp = pipeline.getXferProcessor(); 81 fXferProcessor->setData(fProgramDataManager, xp); 82 this->bindTextures(xp, pipeline.getAllowSRGBInputs(), &nextSamplerIdx); 83 } 84 85 void GrGLProgram::generateMipmaps(const GrPrimitiveProcessor& primProc, 86 const GrPipeline& pipeline) { 87 this->generateMipmaps(primProc, pipeline.getAllowSRGBInputs()); 88 89 GrFragmentProcessor::Iter iter(pipeline); 90 while (const GrFragmentProcessor* fp = iter.next()) { 91 this->generateMipmaps(*fp, pipeline.getAllowSRGBInputs()); 92 } 93 } 94 95 void GrGLProgram::setFragmentData(const GrPrimitiveProcessor& primProc, 96 const GrPipeline& pipeline, 97 int* nextSamplerIdx) { 98 GrFragmentProcessor::Iter iter(pipeline); 99 GrGLSLFragmentProcessor::Iter glslIter(fFragmentProcessors.begin(), 100 fFragmentProcessors.count()); 101 const GrFragmentProcessor* fp = iter.next(); 102 GrGLSLFragmentProcessor* glslFP = glslIter.next(); 103 while (fp && glslFP) { 104 glslFP->setData(fProgramDataManager, *fp); 105 this->bindTextures(*fp, pipeline.getAllowSRGBInputs(), nextSamplerIdx); 106 fp = iter.next(); 107 glslFP = glslIter.next(); 108 } 109 SkASSERT(!fp && !glslFP); 110 } 111 112 113 void GrGLProgram::setRenderTargetState(const GrPrimitiveProcessor& primProc, 114 const GrPipeline& pipeline) { 115 // Load the RT height uniform if it is needed to y-flip gl_FragCoord. 116 if (fBuiltinUniformHandles.fRTHeightUni.isValid() && 117 fRenderTargetState.fRenderTargetSize.fHeight != pipeline.getRenderTarget()->height()) { 118 fProgramDataManager.set1f(fBuiltinUniformHandles.fRTHeightUni, 119 SkIntToScalar(pipeline.getRenderTarget()->height())); 120 } 121 122 // set RT adjustment 123 const GrRenderTarget* rt = pipeline.getRenderTarget(); 124 SkISize size; 125 size.set(rt->width(), rt->height()); 126 if (!primProc.isPathRendering()) { 127 if (fRenderTargetState.fRenderTargetOrigin != rt->origin() || 128 fRenderTargetState.fRenderTargetSize != size) { 129 fRenderTargetState.fRenderTargetSize = size; 130 fRenderTargetState.fRenderTargetOrigin = rt->origin(); 131 132 float rtAdjustmentVec[4]; 133 fRenderTargetState.getRTAdjustmentVec(rtAdjustmentVec); 134 fProgramDataManager.set4fv(fBuiltinUniformHandles.fRTAdjustmentUni, 1, rtAdjustmentVec); 135 } 136 } else { 137 SkASSERT(fGpu->glCaps().shaderCaps()->pathRenderingSupport()); 138 const GrPathProcessor& pathProc = primProc.cast<GrPathProcessor>(); 139 fGpu->glPathRendering()->setProjectionMatrix(pathProc.viewMatrix(), 140 size, rt->origin()); 141 } 142 } 143 144 void GrGLProgram::bindTextures(const GrProcessor& processor, 145 bool allowSRGBInputs, 146 int* nextSamplerIdx) { 147 for (int i = 0; i < processor.numTextureSamplers(); ++i) { 148 const GrProcessor::TextureSampler& sampler = processor.textureSampler(i); 149 fGpu->bindTexture((*nextSamplerIdx)++, sampler.params(), 150 allowSRGBInputs, static_cast<GrGLTexture*>(sampler.texture())); 151 } 152 for (int i = 0; i < processor.numBuffers(); ++i) { 153 const GrProcessor::BufferAccess& access = processor.bufferAccess(i); 154 fGpu->bindTexelBuffer((*nextSamplerIdx)++, access.texelConfig(), 155 static_cast<GrGLBuffer*>(access.buffer())); 156 } 157 for (int i = 0; i < processor.numImageStorages(); ++i) { 158 const GrProcessor::ImageStorageAccess& access = processor.imageStorageAccess(i); 159 fGpu->bindImageStorage((*nextSamplerIdx)++, access.ioType(), 160 static_cast<GrGLTexture *>(access.texture())); 161 } 162 } 163 164 void GrGLProgram::generateMipmaps(const GrProcessor& processor, 165 bool allowSRGBInputs) { 166 for (int i = 0; i < processor.numTextureSamplers(); ++i) { 167 const GrProcessor::TextureSampler& sampler = processor.textureSampler(i); 168 fGpu->generateMipmaps(sampler.params(), allowSRGBInputs, 169 static_cast<GrGLTexture*>(sampler.texture())); 170 } 171 } 172