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
GrGLProgram(GrGLGpu * gpu,const GrProgramDesc & desc,const BuiltinUniformHandles & builtinUniforms,GrGLuint programID,const UniformInfoArray & uniforms,const UniformInfoArray & textureSamplers,const UniformInfoArray & texelBuffers,const VaryingInfoArray & pathProcVaryings,std::unique_ptr<GrGLSLPrimitiveProcessor> geometryProcessor,std::unique_ptr<GrGLSLXferProcessor> xferProcessor,const GrGLSLFragProcs & fragmentProcessors)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
~GrGLProgram()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
abandon()64 void GrGLProgram::abandon() {
65 fProgramID = 0;
66 }
67
68 ///////////////////////////////////////////////////////////////////////////////
69
setData(const GrPrimitiveProcessor & primProc,const GrPipeline & pipeline)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
generateMipmaps(const GrPrimitiveProcessor & primProc,const GrPipeline & pipeline)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
setFragmentData(const GrPrimitiveProcessor & primProc,const GrPipeline & pipeline,int * nextTexSamplerIdx,int * nextTexelBufferIdx)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
setRenderTargetState(const GrPrimitiveProcessor & primProc,const GrRenderTargetProxy * proxy)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
bindTextures(const GrResourceIOProcessor & processor,bool allowSRGBInputs,int * nextTexSamplerIdx,int * nextTexelBufferIdx)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
generateMipmaps(const GrResourceIOProcessor & processor,bool allowSRGBInputs)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