• 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 "src/gpu/gl/GrGLProgram.h"
9 
10 #include "src/gpu/GrFragmentProcessor.h"
11 #include "src/gpu/GrGeometryProcessor.h"
12 #include "src/gpu/GrPipeline.h"
13 #include "src/gpu/GrProcessor.h"
14 #include "src/gpu/GrProgramInfo.h"
15 #include "src/gpu/GrTexture.h"
16 #include "src/gpu/GrXferProcessor.h"
17 #include "src/gpu/effects/GrTextureEffect.h"
18 #include "src/gpu/gl/GrGLBuffer.h"
19 #include "src/gpu/gl/GrGLGpu.h"
20 #include "src/sksl/SkSLCompiler.h"
21 
22 #define GL_CALL(X) GR_GL_CALL(fGpu->glInterface(), X)
23 #define GL_CALL_RET(R, X) GR_GL_CALL_RET(fGpu->glInterface(), R, X)
24 
25 ///////////////////////////////////////////////////////////////////////////////////////////////////
26 
Make(GrGLGpu * gpu,const GrGLSLBuiltinUniformHandles & builtinUniforms,GrGLuint programID,const UniformInfoArray & uniforms,const UniformInfoArray & textureSamplers,std::unique_ptr<GrGeometryProcessor::ProgramImpl> gpImpl,std::unique_ptr<GrXferProcessor::ProgramImpl> xpImpl,std::vector<std::unique_ptr<GrFragmentProcessor::ProgramImpl>> fpImpls,std::unique_ptr<Attribute[]> attributes,int vertexAttributeCnt,int instanceAttributeCnt,int vertexStride,int instanceStride)27 sk_sp<GrGLProgram> GrGLProgram::Make(
28         GrGLGpu* gpu,
29         const GrGLSLBuiltinUniformHandles& builtinUniforms,
30         GrGLuint programID,
31         const UniformInfoArray& uniforms,
32         const UniformInfoArray& textureSamplers,
33         std::unique_ptr<GrGeometryProcessor::ProgramImpl> gpImpl,
34         std::unique_ptr<GrXferProcessor::ProgramImpl> xpImpl,
35         std::vector<std::unique_ptr<GrFragmentProcessor::ProgramImpl>> fpImpls,
36         std::unique_ptr<Attribute[]> attributes,
37         int vertexAttributeCnt,
38         int instanceAttributeCnt,
39         int vertexStride,
40         int instanceStride) {
41     sk_sp<GrGLProgram> program(new GrGLProgram(gpu,
42                                                builtinUniforms,
43                                                programID,
44                                                uniforms,
45                                                textureSamplers,
46                                                std::move(gpImpl),
47                                                std::move(xpImpl),
48                                                std::move(fpImpls),
49                                                std::move(attributes),
50                                                vertexAttributeCnt,
51                                                instanceAttributeCnt,
52                                                vertexStride,
53                                                instanceStride));
54     // Assign texture units to sampler uniforms one time up front.
55     gpu->flushProgram(program);
56     program->fProgramDataManager.setSamplerUniforms(textureSamplers, 0);
57     return program;
58 }
59 
GrGLProgram(GrGLGpu * gpu,const GrGLSLBuiltinUniformHandles & builtinUniforms,GrGLuint programID,const UniformInfoArray & uniforms,const UniformInfoArray & textureSamplers,std::unique_ptr<GrGeometryProcessor::ProgramImpl> gpImpl,std::unique_ptr<GrXferProcessor::ProgramImpl> xpImpl,std::vector<std::unique_ptr<GrFragmentProcessor::ProgramImpl>> fpImpls,std::unique_ptr<Attribute[]> attributes,int vertexAttributeCnt,int instanceAttributeCnt,int vertexStride,int instanceStride)60 GrGLProgram::GrGLProgram(GrGLGpu* gpu,
61                          const GrGLSLBuiltinUniformHandles& builtinUniforms,
62                          GrGLuint programID,
63                          const UniformInfoArray& uniforms,
64                          const UniformInfoArray& textureSamplers,
65                          std::unique_ptr<GrGeometryProcessor::ProgramImpl> gpImpl,
66                          std::unique_ptr<GrXferProcessor::ProgramImpl> xpImpl,
67                          std::vector<std::unique_ptr<GrFragmentProcessor::ProgramImpl>> fpImpls,
68                          std::unique_ptr<Attribute[]> attributes,
69                          int vertexAttributeCnt,
70                          int instanceAttributeCnt,
71                          int vertexStride,
72                          int instanceStride)
73         : fBuiltinUniformHandles(builtinUniforms)
74         , fProgramID(programID)
75         , fGPImpl(std::move(gpImpl))
76         , fXPImpl(std::move(xpImpl))
77         , fFPImpls(std::move(fpImpls))
78         , fAttributes(std::move(attributes))
79         , fVertexAttributeCnt(vertexAttributeCnt)
80         , fInstanceAttributeCnt(instanceAttributeCnt)
81         , fVertexStride(vertexStride)
82         , fInstanceStride(instanceStride)
83         , fGpu(gpu)
84         , fProgramDataManager(gpu, uniforms)
85         , fNumTextureSamplers(textureSamplers.count()) {}
86 
~GrGLProgram()87 GrGLProgram::~GrGLProgram() {
88     if (fProgramID) {
89         GL_CALL(DeleteProgram(fProgramID));
90     }
91 }
92 
abandon()93 void GrGLProgram::abandon() {
94     fProgramID = 0;
95 }
96 
97 ///////////////////////////////////////////////////////////////////////////////
98 
updateUniforms(const GrRenderTarget * renderTarget,const GrProgramInfo & programInfo)99 void GrGLProgram::updateUniforms(const GrRenderTarget* renderTarget,
100                                  const GrProgramInfo& programInfo) {
101     this->setRenderTargetState(renderTarget, programInfo.origin(), programInfo.geomProc());
102 
103     // we set the uniforms for installed processors in a generic way, but subclasses of GLProgram
104     // determine how to set coord transforms
105 
106     // We must bind to texture units in the same order in which we set the uniforms in
107     // GrGLProgramDataManager. That is, we bind textures for processors in this order:
108     // primProc, fragProcs, XP.
109     fGPImpl->setData(fProgramDataManager, *fGpu->caps()->shaderCaps(), programInfo.geomProc());
110 
111     for (int i = 0; i < programInfo.pipeline().numFragmentProcessors(); ++i) {
112         const auto& fp = programInfo.pipeline().getFragmentProcessor(i);
113         fp.visitWithImpls([&](const GrFragmentProcessor& fp,
114                               GrFragmentProcessor::ProgramImpl& impl) {
115             impl.setData(fProgramDataManager, fp);
116         }, *fFPImpls[i]);
117     }
118 
119     programInfo.pipeline().setDstTextureUniforms(fProgramDataManager, &fBuiltinUniformHandles);
120     fXPImpl->setData(fProgramDataManager, programInfo.pipeline().getXferProcessor());
121 }
122 
bindTextures(const GrGeometryProcessor & geomProc,const GrSurfaceProxy * const geomProcTextures[],const GrPipeline & pipeline)123 void GrGLProgram::bindTextures(const GrGeometryProcessor& geomProc,
124                                const GrSurfaceProxy* const geomProcTextures[],
125                                const GrPipeline& pipeline) {
126     // Bind textures from the geometry processor.
127     for (int i = 0; i < geomProc.numTextureSamplers(); ++i) {
128         SkASSERT(geomProcTextures[i]->asTextureProxy());
129         auto* overrideTexture = static_cast<GrGLTexture*>(geomProcTextures[i]->peekTexture());
130         fGpu->bindTexture(i, geomProc.textureSampler(i).samplerState(),
131                           geomProc.textureSampler(i).swizzle(), overrideTexture);
132     }
133     int nextTexSamplerIdx = geomProc.numTextureSamplers();
134     // Bind texture from the destination proxy view.
135     GrTexture* dstTexture = pipeline.peekDstTexture();
136     if (dstTexture) {
137         fGpu->bindTexture(nextTexSamplerIdx++, GrSamplerState::Filter::kNearest,
138                           pipeline.dstProxyView().swizzle(), static_cast<GrGLTexture*>(dstTexture));
139     }
140     // Bind textures from all of the fragment processors.
141     pipeline.visitTextureEffects([&](const GrTextureEffect& te) {
142         GrSamplerState samplerState = te.samplerState();
143         GrSwizzle swizzle = te.view().swizzle();
144         auto* texture = static_cast<GrGLTexture*>(te.texture());
145         fGpu->bindTexture(nextTexSamplerIdx++, samplerState, swizzle, texture);
146     });
147 
148     SkASSERT(nextTexSamplerIdx == fNumTextureSamplers);
149 }
150 
setRenderTargetState(const GrRenderTarget * rt,GrSurfaceOrigin origin,const GrGeometryProcessor & geomProc)151 void GrGLProgram::setRenderTargetState(const GrRenderTarget* rt,
152                                        GrSurfaceOrigin origin,
153                                        const GrGeometryProcessor& geomProc) {
154     // Set RT adjustment and RT flip
155     SkISize dimensions = rt->dimensions();
156     if (fRenderTargetState.fRenderTargetOrigin != origin ||
157         fRenderTargetState.fRenderTargetSize != dimensions) {
158         fRenderTargetState.fRenderTargetSize = dimensions;
159         fRenderTargetState.fRenderTargetOrigin = origin;
160 
161         // The client will mark a swap buffer as kBottomLeft when making a SkSurface because
162         // GL's framebuffer space has (0, 0) at the bottom left. In NDC (-1, -1) is also the
163         // bottom left. However, Skia's device coords has (0, 0) at the top left, so a flip is
164         // required when the origin is kBottomLeft.
165         bool flip = (origin == kBottomLeft_GrSurfaceOrigin);
166         std::array<float, 4> v = SkSL::Compiler::GetRTAdjustVector(dimensions, flip);
167         fProgramDataManager.set4fv(fBuiltinUniformHandles.fRTAdjustmentUni, 1, v.data());
168         if (fBuiltinUniformHandles.fRTFlipUni.isValid()) {
169             std::array<float, 2> d = SkSL::Compiler::GetRTFlipVector(dimensions.height(), flip);
170             fProgramDataManager.set2fv(fBuiltinUniformHandles.fRTFlipUni, 1, d.data());
171         }
172     }
173 }
174