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