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/GrAllocator.h"
9 #include "src/gpu/GrCoordTransform.h"
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/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
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)29 GrGLProgram::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
~GrGLProgram()64 GrGLProgram::~GrGLProgram() {
65 if (fProgramID) {
66 GL_CALL(DeleteProgram(fProgramID));
67 }
68 }
69
abandon()70 void GrGLProgram::abandon() {
71 fProgramID = 0;
72 }
73
74 ///////////////////////////////////////////////////////////////////////////////
75
updateUniformsAndTextureBindings(const GrRenderTarget * renderTarget,const GrProgramInfo & programInfo)76 void GrGLProgram::updateUniformsAndTextureBindings(const GrRenderTarget* renderTarget,
77 const GrProgramInfo& programInfo) {
78
79 this->setRenderTargetState(renderTarget, programInfo.origin(), programInfo.primProc());
80
81 // we set the textures, and uniforms for installed processors in a generic way, but subclasses
82 // of GLProgram determine how to set coord transforms
83
84 // We must bind to texture units in the same order in which we set the uniforms in
85 // GrGLProgramDataManager. That is, we bind textures for processors in this order:
86 // primProc, fragProcs, XP.
87 fPrimitiveProcessor->setData(fProgramDataManager, programInfo.primProc(),
88 GrFragmentProcessor::CoordTransformIter(programInfo.pipeline()));
89 if (programInfo.hasFixedPrimProcTextures()) {
90 this->updatePrimitiveProcessorTextureBindings(programInfo.primProc(),
91 programInfo.fixedPrimProcTextures());
92 }
93 int nextTexSamplerIdx = programInfo.primProc().numTextureSamplers();
94
95 this->setFragmentData(programInfo.pipeline(), &nextTexSamplerIdx);
96
97 const GrXferProcessor& xp = programInfo.pipeline().getXferProcessor();
98 SkIPoint offset;
99 GrTexture* dstTexture = programInfo.pipeline().peekDstTexture(&offset);
100
101 fXferProcessor->setData(fProgramDataManager, xp, dstTexture, offset);
102 if (dstTexture) {
103 fGpu->bindTexture(nextTexSamplerIdx++, GrSamplerState::ClampNearest(),
104 programInfo.pipeline().dstTextureProxy()->textureSwizzle(),
105 static_cast<GrGLTexture*>(dstTexture));
106 }
107 SkASSERT(nextTexSamplerIdx == fNumTextureSamplers);
108 }
109
updatePrimitiveProcessorTextureBindings(const GrPrimitiveProcessor & primProc,const GrTextureProxy * const proxies[])110 void GrGLProgram::updatePrimitiveProcessorTextureBindings(const GrPrimitiveProcessor& primProc,
111 const GrTextureProxy* const proxies[]) {
112 for (int i = 0; i < primProc.numTextureSamplers(); ++i) {
113 auto* tex = static_cast<GrGLTexture*>(proxies[i]->peekTexture());
114 fGpu->bindTexture(i, primProc.textureSampler(i).samplerState(),
115 primProc.textureSampler(i).swizzle(), tex);
116 }
117 }
118
setFragmentData(const GrPipeline & pipeline,int * nextTexSamplerIdx)119 void GrGLProgram::setFragmentData(const GrPipeline& pipeline, int* nextTexSamplerIdx) {
120 GrFragmentProcessor::Iter iter(pipeline);
121 GrGLSLFragmentProcessor::Iter glslIter(fFragmentProcessors.get(), fFragmentProcessorCnt);
122 const GrFragmentProcessor* fp = iter.next();
123 GrGLSLFragmentProcessor* glslFP = glslIter.next();
124 while (fp && glslFP) {
125 glslFP->setData(fProgramDataManager, *fp);
126 for (int i = 0; i < fp->numTextureSamplers(); ++i) {
127 const GrFragmentProcessor::TextureSampler& sampler = fp->textureSampler(i);
128 fGpu->bindTexture((*nextTexSamplerIdx)++, sampler.samplerState(), sampler.swizzle(),
129 static_cast<GrGLTexture*>(sampler.peekTexture()));
130 }
131 fp = iter.next();
132 glslFP = glslIter.next();
133 }
134 SkASSERT(!fp && !glslFP);
135 }
136
setRenderTargetState(const GrRenderTarget * rt,GrSurfaceOrigin origin,const GrPrimitiveProcessor & primProc)137 void GrGLProgram::setRenderTargetState(const GrRenderTarget* rt, GrSurfaceOrigin origin,
138 const GrPrimitiveProcessor& primProc) {
139 // Load the RT size uniforms if they are needed
140 if (fBuiltinUniformHandles.fRTWidthUni.isValid() &&
141 fRenderTargetState.fRenderTargetSize.fWidth != rt->width()) {
142 fProgramDataManager.set1f(fBuiltinUniformHandles.fRTWidthUni, SkIntToScalar(rt->width()));
143 }
144 if (fBuiltinUniformHandles.fRTHeightUni.isValid() &&
145 fRenderTargetState.fRenderTargetSize.fHeight != rt->height()) {
146 fProgramDataManager.set1f(fBuiltinUniformHandles.fRTHeightUni, SkIntToScalar(rt->height()));
147 }
148
149 // set RT adjustment
150 SkISize size;
151 size.set(rt->width(), rt->height());
152 if (!primProc.isPathRendering()) {
153 if (fRenderTargetState.fRenderTargetOrigin != origin ||
154 fRenderTargetState.fRenderTargetSize != size) {
155 fRenderTargetState.fRenderTargetSize = size;
156 fRenderTargetState.fRenderTargetOrigin = origin;
157
158 float rtAdjustmentVec[4];
159 fRenderTargetState.getRTAdjustmentVec(rtAdjustmentVec);
160 fProgramDataManager.set4fv(fBuiltinUniformHandles.fRTAdjustmentUni, 1, rtAdjustmentVec);
161 }
162 } else {
163 SkASSERT(fGpu->glCaps().shaderCaps()->pathRenderingSupport());
164 const GrPathProcessor& pathProc = primProc.cast<GrPathProcessor>();
165 fGpu->glPathRendering()->setProjectionMatrix(pathProc.viewMatrix(),
166 size, origin);
167 }
168 }
169