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 #include "GrAllocator.h"
10 #include "GrCoordTransform.h"
11 #include "GrGLBuffer.h"
12 #include "GrGLGpu.h"
13 #include "GrGLPathRendering.h"
14 #include "GrPathProcessor.h"
15 #include "GrPipeline.h"
16 #include "GrProcessor.h"
17 #include "GrTexturePriv.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 GrGLSLBuiltinUniformHandles & builtinUniforms,GrGLuint programID,const UniformInfoArray & uniforms,const UniformInfoArray & textureSamplers,const VaryingInfoArray & pathProcVaryings,std::unique_ptr<GrGLSLPrimitiveProcessor> geometryProcessor,std::unique_ptr<GrGLSLXferProcessor> xferProcessor,std::unique_ptr<std::unique_ptr<GrGLSLFragmentProcessor>[]> fragmentProcessors,int fragmentProcessorCnt,std::unique_ptr<Attribute[]> attributes,int vertexAttributeCnt,int instanceAttributeCnt,int vertexStride,int instanceStride)28 GrGLProgram::GrGLProgram(
29         GrGLGpu* gpu,
30         const GrGLSLBuiltinUniformHandles& builtinUniforms,
31         GrGLuint programID,
32         const UniformInfoArray& uniforms,
33         const UniformInfoArray& textureSamplers,
34         const VaryingInfoArray& pathProcVaryings,
35         std::unique_ptr<GrGLSLPrimitiveProcessor> geometryProcessor,
36         std::unique_ptr<GrGLSLXferProcessor> xferProcessor,
37         std::unique_ptr<std::unique_ptr<GrGLSLFragmentProcessor>[]> fragmentProcessors,
38         int fragmentProcessorCnt,
39         std::unique_ptr<Attribute[]> attributes,
40         int vertexAttributeCnt,
41         int instanceAttributeCnt,
42         int vertexStride,
43         int instanceStride)
44         : fBuiltinUniformHandles(builtinUniforms)
45         , fProgramID(programID)
46         , fPrimitiveProcessor(std::move(geometryProcessor))
47         , fXferProcessor(std::move(xferProcessor))
48         , fFragmentProcessors(std::move(fragmentProcessors))
49         , fFragmentProcessorCnt(fragmentProcessorCnt)
50         , fAttributes(std::move(attributes))
51         , fVertexAttributeCnt(vertexAttributeCnt)
52         , fInstanceAttributeCnt(instanceAttributeCnt)
53         , fVertexStride(vertexStride)
54         , fInstanceStride(instanceStride)
55         , fGpu(gpu)
56         , fProgramDataManager(gpu, programID, uniforms, pathProcVaryings)
57         , fNumTextureSamplers(textureSamplers.count()) {
58     // Assign texture units to sampler uniforms one time up front.
59     GL_CALL(UseProgram(fProgramID));
60     fProgramDataManager.setSamplerUniforms(textureSamplers, 0);
61 }
62 
~GrGLProgram()63 GrGLProgram::~GrGLProgram() {
64     if (fProgramID) {
65         GL_CALL(DeleteProgram(fProgramID));
66     }
67 }
68 
abandon()69 void GrGLProgram::abandon() {
70     fProgramID = 0;
71 }
72 
73 ///////////////////////////////////////////////////////////////////////////////
74 
updateUniformsAndTextureBindings(const GrRenderTarget * renderTarget,GrSurfaceOrigin origin,const GrPrimitiveProcessor & primProc,const GrPipeline & pipeline,const GrTextureProxy * const primProcTextures[])75 void GrGLProgram::updateUniformsAndTextureBindings(const GrRenderTarget* renderTarget,
76                                                    GrSurfaceOrigin origin,
77                                                    const GrPrimitiveProcessor& primProc,
78                                                    const GrPipeline& pipeline,
79                                                    const GrTextureProxy* const primProcTextures[]) {
80     this->setRenderTargetState(renderTarget, origin, primProc);
81 
82     // we set the textures, and uniforms for installed processors in a generic way, but subclasses
83     // of GLProgram determine how to set coord transforms
84 
85     // We must bind to texture units in the same order in which we set the uniforms in
86     // GrGLProgramDataManager. That is, we bind textures for processors in this order:
87     // primProc, fragProcs, XP.
88     fPrimitiveProcessor->setData(fProgramDataManager, primProc,
89                                  GrFragmentProcessor::CoordTransformIter(pipeline));
90     if (primProcTextures) {
91         this->updatePrimitiveProcessorTextureBindings(primProc, primProcTextures);
92     }
93     int nextTexSamplerIdx = primProc.numTextureSamplers();
94 
95     this->setFragmentData(pipeline, &nextTexSamplerIdx);
96 
97     const GrXferProcessor& xp = pipeline.getXferProcessor();
98     SkIPoint offset;
99     GrTexture* dstTexture = pipeline.peekDstTexture(&offset);
100 
101     fXferProcessor->setData(fProgramDataManager, xp, dstTexture, offset);
102     if (dstTexture) {
103         fGpu->bindTexture(nextTexSamplerIdx++, GrSamplerState::ClampNearest(),
104                           static_cast<GrGLTexture*>(dstTexture));
105     }
106     SkASSERT(nextTexSamplerIdx == fNumTextureSamplers);
107 }
108 
updatePrimitiveProcessorTextureBindings(const GrPrimitiveProcessor & primProc,const GrTextureProxy * const proxies[])109 void GrGLProgram::updatePrimitiveProcessorTextureBindings(const GrPrimitiveProcessor& primProc,
110                                                           const GrTextureProxy* const proxies[]) {
111     for (int i = 0; i < primProc.numTextureSamplers(); ++i) {
112         auto* tex = static_cast<GrGLTexture*>(proxies[i]->peekTexture());
113         fGpu->bindTexture(i, primProc.textureSampler(i).samplerState(), tex);
114     }
115 }
116 
setFragmentData(const GrPipeline & pipeline,int * nextTexSamplerIdx)117 void GrGLProgram::setFragmentData(const GrPipeline& pipeline, int* nextTexSamplerIdx) {
118     GrFragmentProcessor::Iter iter(pipeline);
119     GrGLSLFragmentProcessor::Iter glslIter(fFragmentProcessors.get(), fFragmentProcessorCnt);
120     const GrFragmentProcessor* fp = iter.next();
121     GrGLSLFragmentProcessor* glslFP = glslIter.next();
122     while (fp && glslFP) {
123         glslFP->setData(fProgramDataManager, *fp);
124         for (int i = 0; i < fp->numTextureSamplers(); ++i) {
125             const GrFragmentProcessor::TextureSampler& sampler = fp->textureSampler(i);
126             fGpu->bindTexture((*nextTexSamplerIdx)++, sampler.samplerState(),
127                               static_cast<GrGLTexture*>(sampler.peekTexture()));
128         }
129         fp = iter.next();
130         glslFP = glslIter.next();
131     }
132     SkASSERT(!fp && !glslFP);
133 }
134 
setRenderTargetState(const GrRenderTarget * rt,GrSurfaceOrigin origin,const GrPrimitiveProcessor & primProc)135 void GrGLProgram::setRenderTargetState(const GrRenderTarget* rt, GrSurfaceOrigin origin,
136                                        const GrPrimitiveProcessor& primProc) {
137     // Load the RT size uniforms if they are needed
138     if (fBuiltinUniformHandles.fRTWidthUni.isValid() &&
139         fRenderTargetState.fRenderTargetSize.fWidth != rt->width()) {
140         fProgramDataManager.set1f(fBuiltinUniformHandles.fRTWidthUni, SkIntToScalar(rt->width()));
141     }
142     if (fBuiltinUniformHandles.fRTHeightUni.isValid() &&
143         fRenderTargetState.fRenderTargetSize.fHeight != rt->height()) {
144         fProgramDataManager.set1f(fBuiltinUniformHandles.fRTHeightUni, SkIntToScalar(rt->height()));
145     }
146 
147     // set RT adjustment
148     SkISize size;
149     size.set(rt->width(), rt->height());
150     if (!primProc.isPathRendering()) {
151         if (fRenderTargetState.fRenderTargetOrigin != origin ||
152             fRenderTargetState.fRenderTargetSize != size) {
153             fRenderTargetState.fRenderTargetSize = size;
154             fRenderTargetState.fRenderTargetOrigin = origin;
155 
156             float rtAdjustmentVec[4];
157             fRenderTargetState.getRTAdjustmentVec(rtAdjustmentVec);
158             fProgramDataManager.set4fv(fBuiltinUniformHandles.fRTAdjustmentUni, 1, rtAdjustmentVec);
159         }
160     } else {
161         SkASSERT(fGpu->glCaps().shaderCaps()->pathRenderingSupport());
162         const GrPathProcessor& pathProc = primProc.cast<GrPathProcessor>();
163         fGpu->glPathRendering()->setProjectionMatrix(pathProc.viewMatrix(),
164                                                      size, origin);
165     }
166 }
167