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 "GrGLGeometryProcessor.h"
14 #include "GrGLGpu.h"
15 #include "GrGLPathProcessor.h"
16 #include "GrGLPathRendering.h"
17 #include "GrGLShaderVar.h"
18 #include "GrGLSL.h"
19 #include "GrGLXferProcessor.h"
20 #include "GrPipeline.h"
21 #include "GrXferProcessor.h"
22 #include "SkXfermode.h"
23 
24 #define GL_CALL(X) GR_GL_CALL(fGpu->glInterface(), X)
25 #define GL_CALL_RET(R, X) GR_GL_CALL_RET(fGpu->glInterface(), R, X)
26 
27 ///////////////////////////////////////////////////////////////////////////////////////////////////
28 
GrGLProgram(GrGLGpu * gpu,const GrProgramDesc & desc,const BuiltinUniformHandles & builtinUniforms,GrGLuint programID,const UniformInfoArray & uniforms,GrGLInstalledGeoProc * geometryProcessor,GrGLInstalledXferProc * xferProcessor,GrGLInstalledFragProcs * fragmentProcessors)29 GrGLProgram::GrGLProgram(GrGLGpu* gpu,
30                          const GrProgramDesc& desc,
31                          const BuiltinUniformHandles& builtinUniforms,
32                          GrGLuint programID,
33                          const UniformInfoArray& uniforms,
34                          GrGLInstalledGeoProc* geometryProcessor,
35                          GrGLInstalledXferProc* xferProcessor,
36                          GrGLInstalledFragProcs* fragmentProcessors)
37     : fColor(GrColor_ILLEGAL)
38     , fCoverage(0)
39     , fDstCopyTexUnit(-1)
40     , fBuiltinUniformHandles(builtinUniforms)
41     , fProgramID(programID)
42     , fGeometryProcessor(geometryProcessor)
43     , fXferProcessor(xferProcessor)
44     , fFragmentProcessors(SkRef(fragmentProcessors))
45     , fDesc(desc)
46     , fGpu(gpu)
47     , fProgramDataManager(gpu, uniforms) {
48     this->initSamplerUniforms();
49 }
50 
~GrGLProgram()51 GrGLProgram::~GrGLProgram() {
52     if (fProgramID) {
53         GL_CALL(DeleteProgram(fProgramID));
54     }
55 }
56 
abandon()57 void GrGLProgram::abandon() {
58     fProgramID = 0;
59 }
60 
initSamplerUniforms()61 void GrGLProgram::initSamplerUniforms() {
62     GL_CALL(UseProgram(fProgramID));
63     GrGLint texUnitIdx = 0;
64     this->initSamplers(fGeometryProcessor.get(), &texUnitIdx);
65     if (fXferProcessor.get()) {
66         this->initSamplers(fXferProcessor.get(), &texUnitIdx);
67     }
68     int numProcs = fFragmentProcessors->fProcs.count();
69     for (int i = 0; i < numProcs; i++) {
70         this->initSamplers(fFragmentProcessors->fProcs[i], &texUnitIdx);
71     }
72 }
73 
74 template <class Proc>
initSamplers(Proc * ip,int * texUnitIdx)75 void GrGLProgram::initSamplers(Proc* ip, int* texUnitIdx) {
76     SkTArray<typename Proc::Sampler, true>& samplers = ip->fSamplers;
77     int numSamplers = samplers.count();
78     for (int s = 0; s < numSamplers; ++s) {
79         SkASSERT(samplers[s].fUniform.isValid());
80         fProgramDataManager.setSampler(samplers[s].fUniform, *texUnitIdx);
81         samplers[s].fTextureUnit = (*texUnitIdx)++;
82     }
83 }
84 
85 template <class Proc>
bindTextures(const Proc * ip,const GrProcessor & processor)86 void GrGLProgram::bindTextures(const Proc* ip, const GrProcessor& processor) {
87     const SkTArray<typename Proc::Sampler, true>& samplers = ip->fSamplers;
88     int numSamplers = samplers.count();
89     SkASSERT(numSamplers == processor.numTextures());
90     for (int s = 0; s < numSamplers; ++s) {
91         SkASSERT(samplers[s].fTextureUnit >= 0);
92         const GrTextureAccess& textureAccess = processor.textureAccess(s);
93         fGpu->bindTexture(samplers[s].fTextureUnit,
94                           textureAccess.getParams(),
95                           static_cast<GrGLTexture*>(textureAccess.getTexture()));
96     }
97 }
98 
99 
100 ///////////////////////////////////////////////////////////////////////////////
101 
setData(const GrPrimitiveProcessor & primProc,const GrPipeline & pipeline,const GrBatchTracker & batchTracker)102 void GrGLProgram::setData(const GrPrimitiveProcessor& primProc, const GrPipeline& pipeline,
103                           const GrBatchTracker& batchTracker) {
104     this->setRenderTargetState(primProc, pipeline);
105 
106     // we set the textures, and uniforms for installed processors in a generic way, but subclasses
107     // of GLProgram determine how to set coord transforms
108     fGeometryProcessor->fGLProc->setData(fProgramDataManager, primProc, batchTracker);
109     this->bindTextures(fGeometryProcessor.get(), primProc);
110 
111     const GrXferProcessor& xp = *pipeline.getXferProcessor();
112     fXferProcessor->fGLProc->setData(fProgramDataManager, xp);
113     this->bindTextures(fXferProcessor.get(), xp);
114 
115     this->setFragmentData(primProc, pipeline);
116 
117     // Some of GrGLProgram subclasses need to update state here
118     this->didSetData();
119 }
120 
setFragmentData(const GrPrimitiveProcessor & primProc,const GrPipeline & pipeline)121 void GrGLProgram::setFragmentData(const GrPrimitiveProcessor& primProc,
122                                   const GrPipeline& pipeline) {
123     int numProcessors = fFragmentProcessors->fProcs.count();
124     for (int e = 0; e < numProcessors; ++e) {
125         const GrPendingFragmentStage& stage = pipeline.getFragmentStage(e);
126         const GrProcessor& processor = *stage.processor();
127         fFragmentProcessors->fProcs[e]->fGLProc->setData(fProgramDataManager, processor);
128         this->setTransformData(primProc,
129                                stage,
130                                e,
131                                fFragmentProcessors->fProcs[e]);
132         this->bindTextures(fFragmentProcessors->fProcs[e], processor);
133     }
134 }
setTransformData(const GrPrimitiveProcessor & primProc,const GrPendingFragmentStage & processor,int index,GrGLInstalledFragProc * ip)135 void GrGLProgram::setTransformData(const GrPrimitiveProcessor& primProc,
136                                    const GrPendingFragmentStage& processor,
137                                    int index,
138                                    GrGLInstalledFragProc* ip) {
139     GrGLGeometryProcessor* gp =
140             static_cast<GrGLGeometryProcessor*>(fGeometryProcessor.get()->fGLProc.get());
141     gp->setTransformData(primProc, fProgramDataManager, index,
142                          processor.processor()->coordTransforms());
143 }
144 
setRenderTargetState(const GrPrimitiveProcessor & primProc,const GrPipeline & pipeline)145 void GrGLProgram::setRenderTargetState(const GrPrimitiveProcessor& primProc,
146                                        const GrPipeline& pipeline) {
147     // Load the RT height uniform if it is needed to y-flip gl_FragCoord.
148     if (fBuiltinUniformHandles.fRTHeightUni.isValid() &&
149         fRenderTargetState.fRenderTargetSize.fHeight != pipeline.getRenderTarget()->height()) {
150         fProgramDataManager.set1f(fBuiltinUniformHandles.fRTHeightUni,
151                                    SkIntToScalar(pipeline.getRenderTarget()->height()));
152     }
153 
154     // call subclasses to set the actual view matrix
155     this->onSetRenderTargetState(primProc, pipeline);
156 }
157 
onSetRenderTargetState(const GrPrimitiveProcessor &,const GrPipeline & pipeline)158 void GrGLProgram::onSetRenderTargetState(const GrPrimitiveProcessor&,
159                                          const GrPipeline& pipeline) {
160     const GrRenderTarget* rt = pipeline.getRenderTarget();
161     SkISize size;
162     size.set(rt->width(), rt->height());
163     if (fRenderTargetState.fRenderTargetOrigin != rt->origin() ||
164         fRenderTargetState.fRenderTargetSize != size) {
165         fRenderTargetState.fRenderTargetSize = size;
166         fRenderTargetState.fRenderTargetOrigin = rt->origin();
167 
168         GrGLfloat rtAdjustmentVec[4];
169         fRenderTargetState.getRTAdjustmentVec(rtAdjustmentVec);
170         fProgramDataManager.set4fv(fBuiltinUniformHandles.fRTAdjustmentUni, 1, rtAdjustmentVec);
171     }
172 }
173 
174 /////////////////////////////////////////////////////////////////////////////////////////
175 
GrGLNvprProgram(GrGLGpu * gpu,const GrProgramDesc & desc,const BuiltinUniformHandles & builtinUniforms,GrGLuint programID,const UniformInfoArray & uniforms,GrGLInstalledGeoProc * primProc,GrGLInstalledXferProc * xferProcessor,GrGLInstalledFragProcs * fragmentProcessors)176 GrGLNvprProgram::GrGLNvprProgram(GrGLGpu* gpu,
177                                  const GrProgramDesc& desc,
178                                  const BuiltinUniformHandles& builtinUniforms,
179                                  GrGLuint programID,
180                                  const UniformInfoArray& uniforms,
181                                  GrGLInstalledGeoProc* primProc,
182                                  GrGLInstalledXferProc* xferProcessor,
183                                  GrGLInstalledFragProcs* fragmentProcessors)
184     : INHERITED(gpu, desc, builtinUniforms, programID, uniforms, primProc,
185                 xferProcessor, fragmentProcessors) {
186 }
didSetData()187 void GrGLNvprProgram::didSetData() {
188     GrGLPathProcessor* pathProc =
189             static_cast<GrGLPathProcessor*>(fGeometryProcessor.get()->fGLProc.get());
190     pathProc->didSetData(fGpu->glPathRendering());
191 }
192 
setTransformData(const GrPrimitiveProcessor & primProc,const GrPendingFragmentStage & proc,int index,GrGLInstalledFragProc * ip)193 void GrGLNvprProgram::setTransformData(const GrPrimitiveProcessor& primProc,
194                                        const GrPendingFragmentStage& proc,
195                                        int index,
196                                        GrGLInstalledFragProc* ip) {
197     GrGLPathProcessor* pathProc =
198             static_cast<GrGLPathProcessor*>(fGeometryProcessor.get()->fGLProc.get());
199     pathProc->setTransformData(primProc, index, proc.processor()->coordTransforms(),
200                                fGpu->glPathRendering(), fProgramID);
201 }
202 
onSetRenderTargetState(const GrPrimitiveProcessor & primProc,const GrPipeline & pipeline)203 void GrGLNvprProgram::onSetRenderTargetState(const GrPrimitiveProcessor& primProc,
204                                              const GrPipeline& pipeline) {
205     SkASSERT(!primProc.willUseGeoShader() && primProc.numAttribs() == 0);
206     const GrRenderTarget* rt = pipeline.getRenderTarget();
207     SkISize size;
208     size.set(rt->width(), rt->height());
209     const GrPathProcessor& pathProc = primProc.cast<GrPathProcessor>();
210     fGpu->glPathRendering()->setProjectionMatrix(pathProc.viewMatrix(),
211                                                  size, rt->origin());
212 }
213