1fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot/*
2fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Copyright 2015 Google Inc.
3fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot *
4fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * Use of this source code is governed by a BSD-style license that can be
5fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot * found in the LICENSE file.
6fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot */
7fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
8fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "gl/GrGLUniformHandler.h"
9fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
10fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "gl/GrGLCaps.h"
11fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "gl/GrGLGpu.h"
12fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "gl/builders/GrGLProgramBuilder.h"
13fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#include "SkSLCompiler.h"
14fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
15fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#define GL_CALL(X) GR_GL_CALL(this->glGpu()->glInterface(), X)
16fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot#define GL_CALL_RET(R, X) GR_GL_CALL_RET(this->glGpu()->glInterface(), R, X)
17fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
18fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotbool valid_name(const char* name) {
19fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // disallow unknown names that start with "sk_"
20fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (!strncmp(name, GR_NO_MANGLE_PREFIX, strlen(GR_NO_MANGLE_PREFIX))) {
21fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        return !strcmp(name, SkSL::Compiler::RTADJUST_NAME);
22fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
23fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return true;
24fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
25fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
26fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotGrGLSLUniformHandler::UniformHandle GrGLUniformHandler::internalAddUniformArray(
27fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                                            uint32_t visibility,
28fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                                            GrSLType type,
29fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                                            GrSLPrecision precision,
30fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                                            const char* name,
31fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                                            bool mangleName,
32fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                                            int arrayCount,
33fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                                            const char** outName) {
34fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkASSERT(name && strlen(name));
35fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkASSERT(valid_name(name));
36fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkASSERT(0 != visibility);
37fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkASSERT(kDefault_GrSLPrecision == precision || GrSLTypeTemporarilyAcceptsPrecision(type));
38fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
39fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    UniformInfo& uni = fUniforms.push_back();
40fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    uni.fVariable.setType(type);
41fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    uni.fVariable.setTypeModifier(GrShaderVar::kUniform_TypeModifier);
42fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // TODO this is a bit hacky, lets think of a better way.  Basically we need to be able to use
43fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // the uniform view matrix name in the GP, and the GP is immutable so it has to tell the PB
44fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // exactly what name it wants to use for the uniform view matrix.  If we prefix anythings, then
45fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // the names will mismatch.  I think the correct solution is to have all GPs which need the
46fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // uniform view matrix, they should upload the view matrix in their setData along with regular
47fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    // uniforms.
48fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    char prefix = 'u';
49fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if ('u' == name[0] || !strncmp(name, GR_NO_MANGLE_PREFIX, strlen(GR_NO_MANGLE_PREFIX))) {
50fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        prefix = '\0';
51fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
52fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    fProgramBuilder->nameVariable(uni.fVariable.accessName(), prefix, name, mangleName);
53fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    uni.fVariable.setArrayCount(arrayCount);
54fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    uni.fVisibility = visibility;
55fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    uni.fVariable.setPrecision(precision);
56fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    uni.fLocation = -1;
57fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
58fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (outName) {
59fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        *outName = uni.fVariable.c_str();
60fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
61fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return GrGLSLUniformHandler::UniformHandle(fUniforms.count() - 1);
62fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
63fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
64fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotGrGLSLUniformHandler::SamplerHandle GrGLUniformHandler::addSampler(uint32_t visibility,
65fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                                   GrSwizzle swizzle,
66fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                                   GrSLType type,
67fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                                   GrSLPrecision precision,
68fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                                   const char* name) {
69fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkASSERT(name && strlen(name));
70fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkASSERT(0 != visibility);
71fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
72fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkString mangleName;
73fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    char prefix = 'u';
74fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    fProgramBuilder->nameVariable(&mangleName, prefix, name, true);
75fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
76fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    UniformInfo& sampler = fSamplers.push_back();
77fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkASSERT(GrSLTypeIsCombinedSamplerType(type));
78fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    sampler.fVariable.setType(type);
79fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    sampler.fVariable.setTypeModifier(GrShaderVar::kUniform_TypeModifier);
80fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    sampler.fVariable.setPrecision(precision);
81fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    sampler.fVariable.setName(mangleName);
82fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    sampler.fLocation = -1;
83fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    sampler.fVisibility = visibility;
84fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    fSamplerSwizzles.push_back(swizzle);
85fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkASSERT(fSamplers.count() == fSamplerSwizzles.count());
86fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return GrGLSLUniformHandler::SamplerHandle(fSamplers.count() - 1);
87fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
88fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
89fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team RobotGrGLSLUniformHandler::TexelBufferHandle GrGLUniformHandler::addTexelBuffer(uint32_t visibility,
90fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                                           GrSLPrecision precision,
91fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                                           const char* name) {
92fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkASSERT(name && strlen(name));
93fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkASSERT(0 != visibility);
94fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
95fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    SkString mangleName;
96fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    char prefix = 'u';
97fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    fProgramBuilder->nameVariable(&mangleName, prefix, name, true);
98fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
99fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    UniformInfo& texelBuffer = fTexelBuffers.push_back();
100fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    texelBuffer.fVariable.setType(kBufferSampler_GrSLType);
101fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    texelBuffer.fVariable.setTypeModifier(GrShaderVar::kUniform_TypeModifier);
102fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    texelBuffer.fVariable.setPrecision(precision);
103fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    texelBuffer.fVariable.setName(mangleName);
104fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    texelBuffer.fLocation = -1;
105fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    texelBuffer.fVisibility = visibility;
106fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return GrGLSLUniformHandler::TexelBufferHandle(fTexelBuffers.count() - 1);
107fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
108fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
109fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid GrGLUniformHandler::appendUniformDecls(GrShaderFlags visibility, SkString* out) const {
110fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    for (int i = 0; i < fUniforms.count(); ++i) {
111fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (fUniforms[i].fVisibility & visibility) {
112fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            fUniforms[i].fVariable.appendDecl(fProgramBuilder->shaderCaps(), out);
113fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            out->append(";");
114fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
115fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
116fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    for (int i = 0; i < fSamplers.count(); ++i) {
117fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (fSamplers[i].fVisibility & visibility) {
118fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            fSamplers[i].fVariable.appendDecl(fProgramBuilder->shaderCaps(), out);
119fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            out->append(";\n");
120fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
121fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
122fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    for (int i = 0; i < fTexelBuffers.count(); ++i) {
123fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        if (fTexelBuffers[i].fVisibility & visibility) {
124fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            fTexelBuffers[i].fVariable.appendDecl(fProgramBuilder->shaderCaps(), out);
125fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            out->append(";\n");
126fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
127fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
128fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
129fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
130fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid GrGLUniformHandler::bindUniformLocations(GrGLuint programID, const GrGLCaps& caps) {
131fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (caps.bindUniformLocationSupport()) {
132fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        int currUniform = 0;
133fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        for (int i = 0; i < fUniforms.count(); ++i, ++currUniform) {
134fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            GL_CALL(BindUniformLocation(programID, currUniform, fUniforms[i].fVariable.c_str()));
135fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            fUniforms[i].fLocation = currUniform;
136fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
137fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        for (int i = 0; i < fSamplers.count(); ++i, ++currUniform) {
138fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            GL_CALL(BindUniformLocation(programID, currUniform, fSamplers[i].fVariable.c_str()));
139fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            fSamplers[i].fLocation = currUniform;
140fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
141fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        for (int i = 0; i < fTexelBuffers.count(); ++i, ++currUniform) {
142fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            GL_CALL(BindUniformLocation(programID, currUniform,
143fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                        fTexelBuffers[i].fVariable.c_str()));
144fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            fTexelBuffers[i].fLocation = currUniform;
145fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
146fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
147fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
148fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
149fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotvoid GrGLUniformHandler::getUniformLocations(GrGLuint programID, const GrGLCaps& caps) {
150fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    if (!caps.bindUniformLocationSupport()) {
151fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        int count = fUniforms.count();
152fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        for (int i = 0; i < count; ++i) {
153fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            GrGLint location;
154fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            GL_CALL_RET(location, GetUniformLocation(programID, fUniforms[i].fVariable.c_str()));
155fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            fUniforms[i].fLocation = location;
156fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
157fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        for (int i = 0; i < fSamplers.count(); ++i) {
158fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            GrGLint location;
159fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            GL_CALL_RET(location, GetUniformLocation(programID, fSamplers[i].fVariable.c_str()));
160fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            fSamplers[i].fLocation = location;
161fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
162fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        for (int i = 0; i < fTexelBuffers.count(); ++i) {
163fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            GrGLint location;
164fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            GL_CALL_RET(location, GetUniformLocation(programID,
165fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot                                                     fTexelBuffers[i].fVariable.c_str()));
166fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot            fTexelBuffers[i].fLocation = location;
167fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot        }
168fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    }
169fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
170fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot
171fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robotconst GrGLGpu* GrGLUniformHandler::glGpu() const {
172fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    GrGLProgramBuilder* glPB = (GrGLProgramBuilder*) fProgramBuilder;
173fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot    return glPB->gpu();
174fe17456d5e528078ce69b5f15cf7adf1fab963fandroid-build-team Robot}
175