• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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