17ea439b2203855db97330b25945b87dd4b170b8begdaniel/*
27ea439b2203855db97330b25945b87dd4b170b8begdaniel * Copyright 2015 Google Inc.
37ea439b2203855db97330b25945b87dd4b170b8begdaniel *
47ea439b2203855db97330b25945b87dd4b170b8begdaniel * Use of this source code is governed by a BSD-style license that can be
57ea439b2203855db97330b25945b87dd4b170b8begdaniel * found in the LICENSE file.
67ea439b2203855db97330b25945b87dd4b170b8begdaniel */
77ea439b2203855db97330b25945b87dd4b170b8begdaniel
87ea439b2203855db97330b25945b87dd4b170b8begdaniel#include "gl/GrGLUniformHandler.h"
97ea439b2203855db97330b25945b87dd4b170b8begdaniel
107ea439b2203855db97330b25945b87dd4b170b8begdaniel#include "gl/GrGLCaps.h"
117ea439b2203855db97330b25945b87dd4b170b8begdaniel#include "gl/GrGLGpu.h"
127ea439b2203855db97330b25945b87dd4b170b8begdaniel#include "gl/builders/GrGLProgramBuilder.h"
137ea439b2203855db97330b25945b87dd4b170b8begdaniel
147ea439b2203855db97330b25945b87dd4b170b8begdaniel#define GL_CALL(X) GR_GL_CALL(this->glGpu()->glInterface(), X)
157ea439b2203855db97330b25945b87dd4b170b8begdaniel#define GL_CALL_RET(R, X) GR_GL_CALL_RET(this->glGpu()->glInterface(), R, X)
167ea439b2203855db97330b25945b87dd4b170b8begdaniel
177ea439b2203855db97330b25945b87dd4b170b8begdanielGrGLSLUniformHandler::UniformHandle GrGLUniformHandler::internalAddUniformArray(
187ea439b2203855db97330b25945b87dd4b170b8begdaniel                                                                            uint32_t visibility,
197ea439b2203855db97330b25945b87dd4b170b8begdaniel                                                                            GrSLType type,
207ea439b2203855db97330b25945b87dd4b170b8begdaniel                                                                            GrSLPrecision precision,
217ea439b2203855db97330b25945b87dd4b170b8begdaniel                                                                            const char* name,
227ea439b2203855db97330b25945b87dd4b170b8begdaniel                                                                            bool mangleName,
237ea439b2203855db97330b25945b87dd4b170b8begdaniel                                                                            int arrayCount,
247ea439b2203855db97330b25945b87dd4b170b8begdaniel                                                                            const char** outName) {
257ea439b2203855db97330b25945b87dd4b170b8begdaniel    SkASSERT(name && strlen(name));
267ea439b2203855db97330b25945b87dd4b170b8begdaniel    SkASSERT(0 != visibility);
275f2d8e28c4f8ec0ead92eb613254063ace4e90b4cdalton    SkASSERT(kDefault_GrSLPrecision == precision || GrSLTypeAcceptsPrecision(type));
287ea439b2203855db97330b25945b87dd4b170b8begdaniel
297ea439b2203855db97330b25945b87dd4b170b8begdaniel    UniformInfo& uni = fUniforms.push_back();
307ea439b2203855db97330b25945b87dd4b170b8begdaniel    uni.fVariable.setType(type);
3199938a8ef24e2dd5b39f78638742e9b50ab6d9bfBrian Salomon    uni.fVariable.setTypeModifier(GrShaderVar::kUniform_TypeModifier);
327ea439b2203855db97330b25945b87dd4b170b8begdaniel    // TODO this is a bit hacky, lets think of a better way.  Basically we need to be able to use
337ea439b2203855db97330b25945b87dd4b170b8begdaniel    // the uniform view matrix name in the GP, and the GP is immutable so it has to tell the PB
347ea439b2203855db97330b25945b87dd4b170b8begdaniel    // exactly what name it wants to use for the uniform view matrix.  If we prefix anythings, then
357ea439b2203855db97330b25945b87dd4b170b8begdaniel    // the names will mismatch.  I think the correct solution is to have all GPs which need the
367ea439b2203855db97330b25945b87dd4b170b8begdaniel    // uniform view matrix, they should upload the view matrix in their setData along with regular
377ea439b2203855db97330b25945b87dd4b170b8begdaniel    // uniforms.
387ea439b2203855db97330b25945b87dd4b170b8begdaniel    char prefix = 'u';
397ea439b2203855db97330b25945b87dd4b170b8begdaniel    if ('u' == name[0]) {
407ea439b2203855db97330b25945b87dd4b170b8begdaniel        prefix = '\0';
417ea439b2203855db97330b25945b87dd4b170b8begdaniel    }
427ea439b2203855db97330b25945b87dd4b170b8begdaniel    fProgramBuilder->nameVariable(uni.fVariable.accessName(), prefix, name, mangleName);
437ea439b2203855db97330b25945b87dd4b170b8begdaniel    uni.fVariable.setArrayCount(arrayCount);
447ea439b2203855db97330b25945b87dd4b170b8begdaniel    uni.fVisibility = visibility;
457ea439b2203855db97330b25945b87dd4b170b8begdaniel    uni.fVariable.setPrecision(precision);
46101b844d6ba031de5c4e95b43f9292f266799237Brian Salomon    uni.fLocation = -1;
477ea439b2203855db97330b25945b87dd4b170b8begdaniel
487ea439b2203855db97330b25945b87dd4b170b8begdaniel    if (outName) {
497ea439b2203855db97330b25945b87dd4b170b8begdaniel        *outName = uni.fVariable.c_str();
507ea439b2203855db97330b25945b87dd4b170b8begdaniel    }
517ea439b2203855db97330b25945b87dd4b170b8begdaniel    return GrGLSLUniformHandler::UniformHandle(fUniforms.count() - 1);
527ea439b2203855db97330b25945b87dd4b170b8begdaniel}
537ea439b2203855db97330b25945b87dd4b170b8begdaniel
54101b844d6ba031de5c4e95b43f9292f266799237Brian SalomonGrGLSLUniformHandler::SamplerHandle GrGLUniformHandler::addSampler(uint32_t visibility,
55101b844d6ba031de5c4e95b43f9292f266799237Brian Salomon                                                                   GrSwizzle swizzle,
56101b844d6ba031de5c4e95b43f9292f266799237Brian Salomon                                                                   GrSLType type,
57101b844d6ba031de5c4e95b43f9292f266799237Brian Salomon                                                                   GrSLPrecision precision,
58101b844d6ba031de5c4e95b43f9292f266799237Brian Salomon                                                                   const char* name) {
5909aa1fce69b214714171db12c341aebd78dd29eaegdaniel    SkASSERT(name && strlen(name));
6009aa1fce69b214714171db12c341aebd78dd29eaegdaniel    SkASSERT(0 != visibility);
61101b844d6ba031de5c4e95b43f9292f266799237Brian Salomon
6209aa1fce69b214714171db12c341aebd78dd29eaegdaniel    SkString mangleName;
6309aa1fce69b214714171db12c341aebd78dd29eaegdaniel    char prefix = 'u';
6409aa1fce69b214714171db12c341aebd78dd29eaegdaniel    fProgramBuilder->nameVariable(&mangleName, prefix, name, true);
65101b844d6ba031de5c4e95b43f9292f266799237Brian Salomon
66101b844d6ba031de5c4e95b43f9292f266799237Brian Salomon    UniformInfo& sampler = fSamplers.push_back();
67101b844d6ba031de5c4e95b43f9292f266799237Brian Salomon    SkASSERT(GrSLTypeIsCombinedSamplerType(type));
68101b844d6ba031de5c4e95b43f9292f266799237Brian Salomon    sampler.fVariable.setType(type);
6999938a8ef24e2dd5b39f78638742e9b50ab6d9bfBrian Salomon    sampler.fVariable.setTypeModifier(GrShaderVar::kUniform_TypeModifier);
70101b844d6ba031de5c4e95b43f9292f266799237Brian Salomon    sampler.fVariable.setPrecision(precision);
71101b844d6ba031de5c4e95b43f9292f266799237Brian Salomon    sampler.fVariable.setName(mangleName);
72101b844d6ba031de5c4e95b43f9292f266799237Brian Salomon    sampler.fLocation = -1;
73101b844d6ba031de5c4e95b43f9292f266799237Brian Salomon    sampler.fVisibility = visibility;
74101b844d6ba031de5c4e95b43f9292f266799237Brian Salomon    fSamplerSwizzles.push_back(swizzle);
75101b844d6ba031de5c4e95b43f9292f266799237Brian Salomon    SkASSERT(fSamplers.count() == fSamplerSwizzles.count());
7609aa1fce69b214714171db12c341aebd78dd29eaegdaniel    return GrGLSLUniformHandler::SamplerHandle(fSamplers.count() - 1);
7709aa1fce69b214714171db12c341aebd78dd29eaegdaniel}
7809aa1fce69b214714171db12c341aebd78dd29eaegdaniel
79f9f451213a3951d8a61568998de2ddbd643f6693Brian SalomonGrGLSLUniformHandler::ImageStorageHandle GrGLUniformHandler::addImageStorage(
80f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon        uint32_t visibility, GrSLType type, GrImageStorageFormat format, GrSLMemoryModel model,
81f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon        GrSLRestrict restrict, GrIOType ioType, const char* name) {
82f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon    SkASSERT(name && strlen(name));
83f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon    SkASSERT(0 != visibility);
84f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon    SkString mangleName;
85f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon    char prefix = 'u';
86f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon    fProgramBuilder->nameVariable(&mangleName, prefix, name, true);
87f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon
88f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon    UniformInfo& imageStorage = fImageStorages.push_back();
89f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon    imageStorage.fVariable.setName(mangleName);
90f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon
91f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon    SkASSERT(GrSLTypeIsImageStorage(type));
92f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon    imageStorage.fVariable.setType(type);
93f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon    imageStorage.fVariable.setTypeModifier(GrShaderVar::kUniform_TypeModifier);
94f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon    imageStorage.fVariable.setImageStorageFormat(format);
95f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon    imageStorage.fVariable.setMemoryModel(model);
96f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon    imageStorage.fVariable.setRestrict(restrict);
97f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon    imageStorage.fVariable.setIOType(ioType);
98f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon    imageStorage.fVariable.setPrecision(kHigh_GrSLPrecision);
99f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon    imageStorage.fLocation = -1;
100f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon    imageStorage.fVisibility = visibility;
101f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon    return GrGLSLUniformHandler::ImageStorageHandle(fImageStorages.count() - 1);
102f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon}
103f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon
1045e58ceea8569f0d90ff7e3daf5de2def50407212cdaltonvoid GrGLUniformHandler::appendUniformDecls(GrShaderFlags visibility, SkString* out) const {
1057ea439b2203855db97330b25945b87dd4b170b8begdaniel    for (int i = 0; i < fUniforms.count(); ++i) {
1067ea439b2203855db97330b25945b87dd4b170b8begdaniel        if (fUniforms[i].fVisibility & visibility) {
10794efbf51f5a88d9e8aa961d3fbe38c5e335d6108Brian Salomon            fUniforms[i].fVariable.appendDecl(fProgramBuilder->shaderCaps(), out);
108f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon            out->append(";");
1097ea439b2203855db97330b25945b87dd4b170b8begdaniel        }
1107ea439b2203855db97330b25945b87dd4b170b8begdaniel    }
11109aa1fce69b214714171db12c341aebd78dd29eaegdaniel    for (int i = 0; i < fSamplers.count(); ++i) {
112101b844d6ba031de5c4e95b43f9292f266799237Brian Salomon        if (fSamplers[i].fVisibility & visibility) {
11394efbf51f5a88d9e8aa961d3fbe38c5e335d6108Brian Salomon            fSamplers[i].fVariable.appendDecl(fProgramBuilder->shaderCaps(), out);
11409aa1fce69b214714171db12c341aebd78dd29eaegdaniel            out->append(";\n");
11509aa1fce69b214714171db12c341aebd78dd29eaegdaniel        }
11609aa1fce69b214714171db12c341aebd78dd29eaegdaniel    }
117f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon    for (int i = 0; i < fImageStorages.count(); ++i) {
118f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon        if (fImageStorages[i].fVisibility & visibility) {
11994efbf51f5a88d9e8aa961d3fbe38c5e335d6108Brian Salomon            fImageStorages[i].fVariable.appendDecl(fProgramBuilder->shaderCaps(), out);
120f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon            out->append(";");
121f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon        }
122f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon    }
1237ea439b2203855db97330b25945b87dd4b170b8begdaniel}
1247ea439b2203855db97330b25945b87dd4b170b8begdaniel
1257ea439b2203855db97330b25945b87dd4b170b8begdanielvoid GrGLUniformHandler::bindUniformLocations(GrGLuint programID, const GrGLCaps& caps) {
1267ea439b2203855db97330b25945b87dd4b170b8begdaniel    if (caps.bindUniformLocationSupport()) {
127f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon        int currUniform = 0;
128f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon        for (int i = 0; i < fUniforms.count(); ++i, ++currUniform) {
129f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon            GL_CALL(BindUniformLocation(programID, currUniform, fUniforms[i].fVariable.c_str()));
130f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon            fUniforms[i].fLocation = currUniform;
131be34882042048db096baca32ddf4a8b472529804Brian Salomon        }
132f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon        for (int i = 0; i < fSamplers.count(); ++i, ++currUniform) {
133f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon            GL_CALL(BindUniformLocation(programID, currUniform, fSamplers[i].fVariable.c_str()));
134f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon            fSamplers[i].fLocation = currUniform;
135f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon        }
136f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon        for (int i = 0; i < fImageStorages.count(); ++i) {
137f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon            GL_CALL(BindUniformLocation(programID, currUniform,
138f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon                                        fImageStorages[i].fVariable.c_str()));
139f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon            fImageStorages[i].fLocation = currUniform;
14009aa1fce69b214714171db12c341aebd78dd29eaegdaniel        }
1417ea439b2203855db97330b25945b87dd4b170b8begdaniel    }
1427ea439b2203855db97330b25945b87dd4b170b8begdaniel}
1437ea439b2203855db97330b25945b87dd4b170b8begdaniel
1447ea439b2203855db97330b25945b87dd4b170b8begdanielvoid GrGLUniformHandler::getUniformLocations(GrGLuint programID, const GrGLCaps& caps) {
1457ea439b2203855db97330b25945b87dd4b170b8begdaniel    if (!caps.bindUniformLocationSupport()) {
1467ea439b2203855db97330b25945b87dd4b170b8begdaniel        int count = fUniforms.count();
1477ea439b2203855db97330b25945b87dd4b170b8begdaniel        for (int i = 0; i < count; ++i) {
1487ea439b2203855db97330b25945b87dd4b170b8begdaniel            GrGLint location;
1497ea439b2203855db97330b25945b87dd4b170b8begdaniel            GL_CALL_RET(location, GetUniformLocation(programID, fUniforms[i].fVariable.c_str()));
1507ea439b2203855db97330b25945b87dd4b170b8begdaniel            fUniforms[i].fLocation = location;
1517ea439b2203855db97330b25945b87dd4b170b8begdaniel        }
15209aa1fce69b214714171db12c341aebd78dd29eaegdaniel        for (int i = 0; i < fSamplers.count(); ++i) {
15309aa1fce69b214714171db12c341aebd78dd29eaegdaniel            GrGLint location;
154101b844d6ba031de5c4e95b43f9292f266799237Brian Salomon            GL_CALL_RET(location, GetUniformLocation(programID, fSamplers[i].fVariable.c_str()));
15509aa1fce69b214714171db12c341aebd78dd29eaegdaniel            fSamplers[i].fLocation = location;
15609aa1fce69b214714171db12c341aebd78dd29eaegdaniel        }
157f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon        for (int i = 0; i < fImageStorages.count(); ++i) {
158f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon            GrGLint location;
159f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon            GL_CALL_RET(location, GetUniformLocation(programID,
160f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon                                                     fImageStorages[i].fVariable.c_str()));
161f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon            fImageStorages[i].fLocation = location;
162f9f451213a3951d8a61568998de2ddbd643f6693Brian Salomon        }
1637ea439b2203855db97330b25945b87dd4b170b8begdaniel    }
1647ea439b2203855db97330b25945b87dd4b170b8begdaniel}
1657ea439b2203855db97330b25945b87dd4b170b8begdaniel
1667ea439b2203855db97330b25945b87dd4b170b8begdanielconst GrGLGpu* GrGLUniformHandler::glGpu() const {
1677ea439b2203855db97330b25945b87dd4b170b8begdaniel    GrGLProgramBuilder* glPB = (GrGLProgramBuilder*) fProgramBuilder;
1687ea439b2203855db97330b25945b87dd4b170b8begdaniel    return glPB->gpu();
1697ea439b2203855db97330b25945b87dd4b170b8begdaniel}
170