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 
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 
updateUniforms(const GrRenderTarget * renderTarget,const GrProgramInfo & programInfo)76 void 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 
bindTextures(const GrPrimitiveProcessor & primProc,const GrSurfaceProxy * const primProcTextures[],const GrPipeline & pipeline)103 void 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 
setRenderTargetState(const GrRenderTarget * rt,GrSurfaceOrigin origin,const GrPrimitiveProcessor & primProc)132 void 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