xref: /aosp_15_r20/external/skia/src/gpu/ganesh/gl/GrGLUniformHandler.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1 /*
2  * Copyright 2015 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/ganesh/gl/GrGLUniformHandler.h"
9 
10 #include "include/core/SkString.h"
11 #include "include/gpu/ganesh/GrBackendSurface.h"
12 #include "include/gpu/ganesh/gl/GrGLFunctions.h"
13 #include "include/gpu/ganesh/gl/GrGLInterface.h"
14 #include "include/private/base/SkAssert.h"
15 #include "src/gpu/ganesh/GrUtil.h"
16 #include "src/gpu/ganesh/gl/GrGLCaps.h"
17 #include "src/gpu/ganesh/gl/GrGLGpu.h"
18 #include "src/gpu/ganesh/gl/GrGLUtil.h"
19 #include "src/gpu/ganesh/gl/builders/GrGLProgramBuilder.h"
20 #include "src/gpu/ganesh/glsl/GrGLSLProgramBuilder.h"
21 #include "src/sksl/SkSLCompiler.h"
22 
23 #include <string.h>
24 #include <utility>
25 
26 #define GL_CALL(X) GR_GL_CALL(this->glGpu()->glInterface(), X)
27 #define GL_CALL_RET(R, X) GR_GL_CALL_RET(this->glGpu()->glInterface(), R, X)
28 
valid_name(const char * name)29 bool valid_name(const char* name) {
30     // disallow unknown names that start with "sk_"
31     if (!strncmp(name, GR_NO_MANGLE_PREFIX, strlen(GR_NO_MANGLE_PREFIX))) {
32         return !strcmp(name, SkSL::Compiler::RTADJUST_NAME);
33     }
34     return true;
35 }
36 
internalAddUniformArray(const GrProcessor * owner,uint32_t visibility,SkSLType type,const char * name,bool mangleName,int arrayCount,const char ** outName)37 GrGLSLUniformHandler::UniformHandle GrGLUniformHandler::internalAddUniformArray(
38                                                                    const GrProcessor* owner,
39                                                                    uint32_t visibility,
40                                                                    SkSLType type,
41                                                                    const char* name,
42                                                                    bool mangleName,
43                                                                    int arrayCount,
44                                                                    const char** outName) {
45     SkASSERT(name && strlen(name));
46     SkASSERT(valid_name(name));
47     SkASSERT(0 != visibility);
48 
49     // TODO this is a bit hacky, lets think of a better way.  Basically we need to be able to use
50     // the uniform view matrix name in the GP, and the GP is immutable so it has to tell the PB
51     // exactly what name it wants to use for the uniform view matrix.  If we prefix anythings, then
52     // the names will mismatch.  I think the correct solution is to have all GPs which need the
53     // uniform view matrix, they should upload the view matrix in their setData along with regular
54     // uniforms.
55     char prefix = 'u';
56     if ('u' == name[0] || !strncmp(name, GR_NO_MANGLE_PREFIX, strlen(GR_NO_MANGLE_PREFIX))) {
57         prefix = '\0';
58     }
59     SkString resolvedName = fProgramBuilder->nameVariable(prefix, name, mangleName);
60 
61     GLUniformInfo tempInfo;
62     tempInfo.fVariable = GrShaderVar{std::move(resolvedName),
63                                      type,
64                                      GrShaderVar::TypeModifier::Uniform,
65                                      arrayCount};
66 
67     tempInfo.fVisibility = visibility;
68     tempInfo.fOwner      = owner;
69     tempInfo.fRawName    = SkString(name);
70     tempInfo.fLocation   = -1;
71 
72     fUniforms.push_back(tempInfo);
73 
74     if (outName) {
75         *outName = fUniforms.back().fVariable.c_str();
76     }
77     return GrGLSLUniformHandler::UniformHandle(fUniforms.count() - 1);
78 }
79 
addSampler(const GrBackendFormat & backendFormat,GrSamplerState,const skgpu::Swizzle & swizzle,const char * name,const GrShaderCaps * shaderCaps)80 GrGLSLUniformHandler::SamplerHandle GrGLUniformHandler::addSampler(
81         const GrBackendFormat& backendFormat,
82         GrSamplerState,
83         const skgpu::Swizzle& swizzle,
84         const char* name,
85         const GrShaderCaps* shaderCaps) {
86     SkASSERT(name && strlen(name));
87 
88     constexpr char prefix = 'u';
89     SkString mangleName = fProgramBuilder->nameVariable(prefix, name, true);
90 
91     GrTextureType type = backendFormat.textureType();
92 
93     GLUniformInfo tempInfo;
94     tempInfo.fVariable = GrShaderVar{std::move(mangleName),
95                                      SkSLCombinedSamplerTypeForTextureType(type)};
96 
97     tempInfo.fVisibility = kFragment_GrShaderFlag;
98     tempInfo.fOwner      = nullptr;
99     tempInfo.fRawName    = SkString(name);
100     tempInfo.fLocation   = -1;
101 
102     fSamplers.push_back(tempInfo);
103     fSamplerSwizzles.push_back(swizzle);
104     SkASSERT(fSamplers.count() == fSamplerSwizzles.size());
105 
106     return GrGLSLUniformHandler::SamplerHandle(fSamplers.count() - 1);
107 }
108 
appendUniformDecls(GrShaderFlags visibility,SkString * out) const109 void GrGLUniformHandler::appendUniformDecls(GrShaderFlags visibility, SkString* out) const {
110     for (const UniformInfo& uniform : fUniforms.items()) {
111         if (uniform.fVisibility & visibility) {
112             uniform.fVariable.appendDecl(fProgramBuilder->shaderCaps(), out);
113             out->append(";");
114         }
115     }
116     for (const UniformInfo& sampler : fSamplers.items()) {
117         if (sampler.fVisibility & visibility) {
118             sampler.fVariable.appendDecl(fProgramBuilder->shaderCaps(), out);
119             out->append(";\n");
120         }
121     }
122 }
123 
bindUniformLocations(GrGLuint programID,const GrGLCaps & caps)124 void GrGLUniformHandler::bindUniformLocations(GrGLuint programID, const GrGLCaps& caps) {
125     if (caps.bindUniformLocationSupport()) {
126         int currUniform = 0;
127         for (GLUniformInfo& uniform : fUniforms.items()) {
128             GL_CALL(BindUniformLocation(programID, currUniform, uniform.fVariable.c_str()));
129             uniform.fLocation = currUniform;
130             ++currUniform;
131         }
132         for (GLUniformInfo& sampler : fSamplers.items()) {
133             GL_CALL(BindUniformLocation(programID, currUniform, sampler.fVariable.c_str()));
134             sampler.fLocation = currUniform;
135             ++currUniform;
136         }
137     }
138 }
139 
getUniformLocations(GrGLuint programID,const GrGLCaps & caps,bool force)140 void GrGLUniformHandler::getUniformLocations(GrGLuint programID, const GrGLCaps& caps, bool force) {
141     if (!caps.bindUniformLocationSupport() || force) {
142         for (GLUniformInfo& uniform : fUniforms.items()) {
143             GrGLint location;
144             GL_CALL_RET(location, GetUniformLocation(programID, uniform.fVariable.c_str()));
145             uniform.fLocation = location;
146         }
147         for (GLUniformInfo& sampler : fSamplers.items()) {
148             GrGLint location;
149             GL_CALL_RET(location, GetUniformLocation(programID, sampler.fVariable.c_str()));
150             sampler.fLocation = location;
151         }
152     }
153 }
154 
glGpu() const155 const GrGLGpu* GrGLUniformHandler::glGpu() const {
156     GrGLProgramBuilder* glPB = (GrGLProgramBuilder*) fProgramBuilder;
157     return glPB->gpu();
158 }
159