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/GrPathProcessor.h"
11#include "src/gpu/GrPipeline.h"
12#include "src/gpu/GrProcessor.h"
13#include "src/gpu/GrProgramInfo.h"
14#include "src/gpu/GrTexture.h"
15#include "src/gpu/GrXferProcessor.h"
16#include "src/gpu/gl/GrGLBuffer.h"
17#include "src/gpu/gl/GrGLGpu.h"
18#include "src/gpu/gl/GrGLPathRendering.h"
19#include "src/gpu/glsl/GrGLSLFragmentProcessor.h"
20#include "src/gpu/glsl/GrGLSLGeometryProcessor.h"
21#include "src/gpu/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
28sk_sp<GrGLProgram> GrGLProgram::Make(
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>[]> fps,
38 std::unique_ptr<Attribute[]> attributes,
39 int vertexAttributeCnt,
40 int instanceAttributeCnt,
41 int vertexStride,
42 int instanceStride) {
43 sk_sp<GrGLProgram> program(new GrGLProgram(gpu,
44 builtinUniforms,
45 programID,
46 uniforms,
47 textureSamplers,
48 pathProcVaryings,
49 std::move(geometryProcessor),
50 std::move(xferProcessor),
51 std::move(fps),
52 std::move(attributes),
53 vertexAttributeCnt,
54 instanceAttributeCnt,
55 vertexStride,
56 instanceStride));
57 // Assign texture units to sampler uniforms one time up front.
58 gpu->flushProgram(program);
59 program->fProgramDataManager.setSamplerUniforms(textureSamplers, 0);
60 return program;
61}
62
63GrGLProgram::GrGLProgram(
64 GrGLGpu* gpu,
65 const GrGLSLBuiltinUniformHandles& builtinUniforms,
66 GrGLuint programID,
67 const UniformInfoArray& uniforms,
68 const UniformInfoArray& textureSamplers,
69 const VaryingInfoArray& pathProcVaryings,
70 std::unique_ptr<GrGLSLPrimitiveProcessor> geometryProcessor,
71 std::unique_ptr<GrGLSLXferProcessor> xferProcessor,
72 std::unique_ptr<std::unique_ptr<GrGLSLFragmentProcessor>[]> fps,
73 std::unique_ptr<Attribute[]> attributes,
74 int vertexAttributeCnt,
75 int instanceAttributeCnt,
76 int vertexStride,
77 int instanceStride)
78 : fBuiltinUniformHandles(builtinUniforms)
79 , fProgramID(programID)
80 , fPrimitiveProcessor(std::move(geometryProcessor))
81 , fXferProcessor(std::move(xferProcessor))
82 , fFragmentProcessors(std::move(fps))
83 , fAttributes(std::move(attributes))
84 , fVertexAttributeCnt(vertexAttributeCnt)
85 , fInstanceAttributeCnt(instanceAttributeCnt)
86 , fVertexStride(vertexStride)
87 , fInstanceStride(instanceStride)
88 , fGpu(gpu)
89 , fProgramDataManager(gpu, programID, uniforms, pathProcVaryings)
90 , fNumTextureSamplers(textureSamplers.count()) {
91}
92
93GrGLProgram::~GrGLProgram() {
94 if (fProgramID) {
95 GL_CALL(DeleteProgram(fProgramID));
96 }
97}
98
99void GrGLProgram::abandon() {
100 fProgramID = 0;
101}
102
103///////////////////////////////////////////////////////////////////////////////
104
105void GrGLProgram::updateUniforms(const GrRenderTarget* renderTarget,
106 const GrProgramInfo& programInfo) {
107 this->setRenderTargetState(renderTarget, programInfo.origin(), programInfo.primProc());
108
109 // we set the uniforms for installed processors in a generic way, but subclasses of GLProgram
110 // determine how to set coord transforms
111
112 // We must bind to texture units in the same order in which we set the uniforms in
113 // GrGLProgramDataManager. That is, we bind textures for processors in this order:
114 // primProc, fragProcs, XP.
115 fPrimitiveProcessor->setData(fProgramDataManager, programInfo.primProc());
116
117 for (int i = 0; i < programInfo.pipeline().numFragmentProcessors(); ++i) {
118 auto& pipelineFP = programInfo.pipeline().getFragmentProcessor(i);
119 auto& baseGLSLFP = *fFragmentProcessors[i];
120 for (auto [fp, glslFP] : GrGLSLFragmentProcessor::ParallelRange(pipelineFP, baseGLSLFP)) {
121 glslFP.setData(fProgramDataManager, fp);
122 }
123 }
124
125 const GrXferProcessor& xp = programInfo.pipeline().getXferProcessor();
126 SkIPoint offset;
127 GrTexture* dstTexture = programInfo.pipeline().peekDstTexture(&offset);
128
129 fXferProcessor->setData(fProgramDataManager, xp, dstTexture, offset);
130}
131
132void GrGLProgram::bindTextures(const GrPrimitiveProcessor& primProc,
133 const GrSurfaceProxy* const primProcTextures[],
134 const GrPipeline& pipeline) {
135 for (int i = 0; i < primProc.numTextureSamplers(); ++i) {
136 SkASSERT(primProcTextures[i]->asTextureProxy());
137 auto* overrideTexture = static_cast<GrGLTexture*>(primProcTextures[i]->peekTexture());
138 fGpu->bindTexture(i, primProc.textureSampler(i).samplerState(),
139 primProc.textureSampler(i).swizzle(), overrideTexture);
140 }
141 int nextTexSamplerIdx = primProc.numTextureSamplers();
142
143 pipeline.visitTextureEffects([&](const GrTextureEffect& te) {
144 GrSamplerState samplerState = te.samplerState();
145 GrSwizzle swizzle = te.view().swizzle();
146 auto* texture = static_cast<GrGLTexture*>(te.texture());
147 fGpu->bindTexture(nextTexSamplerIdx++, samplerState, swizzle, texture);
148 });
149
150 SkIPoint offset;
151 GrTexture* dstTexture = pipeline.peekDstTexture(&offset);
152 if (dstTexture) {
153 fGpu->bindTexture(nextTexSamplerIdx++, GrSamplerState::Filter::kNearest,
154 pipeline.dstProxyView().swizzle(), static_cast<GrGLTexture*>(dstTexture));
155 }
156 SkASSERT(nextTexSamplerIdx == fNumTextureSamplers);
157}
158
159void GrGLProgram::setRenderTargetState(const GrRenderTarget* rt, GrSurfaceOrigin origin,
160 const GrPrimitiveProcessor& primProc) {
161 // Load the RT size uniforms if they are needed
162 if (fBuiltinUniformHandles.fRTWidthUni.isValid() &&
163 fRenderTargetState.fRenderTargetSize.fWidth != rt->width()) {
164 fProgramDataManager.set1f(fBuiltinUniformHandles.fRTWidthUni, SkIntToScalar(rt->width()));
165 }
166 if (fBuiltinUniformHandles.fRTHeightUni.isValid() &&
167 fRenderTargetState.fRenderTargetSize.fHeight != rt->height()) {
168 fProgramDataManager.set1f(fBuiltinUniformHandles.fRTHeightUni, SkIntToScalar(rt->height()));
169 }
170
171 // set RT adjustment
172 SkISize dimensions = rt->dimensions();
173 if (!primProc.isPathRendering()) {
174 if (fRenderTargetState.fRenderTargetOrigin != origin ||
175 fRenderTargetState.fRenderTargetSize != dimensions) {
176 fRenderTargetState.fRenderTargetSize = dimensions;
177 fRenderTargetState.fRenderTargetOrigin = origin;
178
179 float rtAdjustmentVec[4];
180 fRenderTargetState.getRTAdjustmentVec(rtAdjustmentVec);
181 fProgramDataManager.set4fv(fBuiltinUniformHandles.fRTAdjustmentUni, 1, rtAdjustmentVec);
182 }
183 } else {
184 SkASSERT(fGpu->glCaps().shaderCaps()->pathRenderingSupport());
185 const GrPathProcessor& pathProc = primProc.cast<GrPathProcessor>();
186 fGpu->glPathRendering()->setProjectionMatrix(pathProc.viewMatrix(), dimensions, origin);
187 }
188}
189