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