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