blob: 5a0e1ba0d3096403db84053ec04a64c069f8f407 [file] [log] [blame]
Geoff Langf9a6f082015-01-22 13:32:49 -05001//
2// Copyright 2015 The ANGLE Project Authors. All rights reserved.
3// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// ProgramGL.cpp: Implements the class methods for ProgramGL.
8
9#include "libANGLE/renderer/gl/ProgramGL.h"
10
Sami Väisänen46eaa942016-06-29 10:26:37 +030011#include "common/angleutils.h"
Geoff Langf9a6f082015-01-22 13:32:49 -050012#include "common/debug.h"
Sami Väisänen46eaa942016-06-29 10:26:37 +030013#include "common/string_utils.h"
Geoff Lang5ed74cf2015-04-14 13:57:07 -040014#include "common/utilities.h"
Geoff Langb1f435e2015-02-20 10:01:01 -050015#include "libANGLE/renderer/gl/FunctionsGL.h"
16#include "libANGLE/renderer/gl/ShaderGL.h"
17#include "libANGLE/renderer/gl/StateManagerGL.h"
Philippe Hamel40911192016-04-07 16:45:50 -040018#include "libANGLE/renderer/gl/WorkaroundsGL.h"
Jamie Madill53ea9cc2016-05-17 10:12:52 -040019#include "libANGLE/Uniform.h"
unknownb4a3af22015-11-25 15:02:51 -050020#include "platform/Platform.h"
Geoff Langf9a6f082015-01-22 13:32:49 -050021
22namespace rx
23{
24
Jamie Madill48ef11b2016-04-27 15:21:52 -040025ProgramGL::ProgramGL(const gl::ProgramState &data,
Jamie Madill5c6b7bf2015-08-17 12:53:35 -040026 const FunctionsGL *functions,
Philippe Hamel40911192016-04-07 16:45:50 -040027 const WorkaroundsGL &workarounds,
Sami Väisänen46eaa942016-06-29 10:26:37 +030028 StateManagerGL *stateManager,
29 bool enablePathRendering)
Philippe Hamel40911192016-04-07 16:45:50 -040030 : ProgramImpl(data),
31 mFunctions(functions),
32 mWorkarounds(workarounds),
33 mStateManager(stateManager),
Sami Väisänen46eaa942016-06-29 10:26:37 +030034 mEnablePathRendering(enablePathRendering),
Philippe Hamel40911192016-04-07 16:45:50 -040035 mProgramID(0)
Geoff Langb1f435e2015-02-20 10:01:01 -050036{
37 ASSERT(mFunctions);
38 ASSERT(mStateManager);
Geoff Lang0ca53782015-05-07 13:49:39 -040039
40 mProgramID = mFunctions->createProgram();
Geoff Langb1f435e2015-02-20 10:01:01 -050041}
Geoff Langf9a6f082015-01-22 13:32:49 -050042
43ProgramGL::~ProgramGL()
Geoff Langb1f435e2015-02-20 10:01:01 -050044{
Geoff Lang0ca53782015-05-07 13:49:39 -040045 mFunctions->deleteProgram(mProgramID);
46 mProgramID = 0;
Geoff Langb1f435e2015-02-20 10:01:01 -050047}
Geoff Langf9a6f082015-01-22 13:32:49 -050048
Geoff Langf9a6f082015-01-22 13:32:49 -050049LinkResult ProgramGL::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream)
50{
Geoff Lang65a0be92015-10-02 09:57:30 -040051 preLink();
52
53 // Read the binary format, size and blob
54 GLenum binaryFormat = stream->readInt<GLenum>();
55 GLint binaryLength = stream->readInt<GLint>();
56 const uint8_t *binary = stream->data() + stream->offset();
57 stream->skip(binaryLength);
58
59 // Load the binary
60 mFunctions->programBinary(mProgramID, binaryFormat, binary, binaryLength);
61
62 // Verify that the program linked
63 if (!checkLinkStatus(infoLog))
64 {
65 return LinkResult(false, gl::Error(GL_NO_ERROR));
66 }
67
68 postLink();
69
70 return LinkResult(true, gl::Error(GL_NO_ERROR));
Geoff Langf9a6f082015-01-22 13:32:49 -050071}
72
73gl::Error ProgramGL::save(gl::BinaryOutputStream *stream)
74{
Geoff Lang65a0be92015-10-02 09:57:30 -040075 GLint binaryLength = 0;
76 mFunctions->getProgramiv(mProgramID, GL_PROGRAM_BINARY_LENGTH, &binaryLength);
77
78 std::vector<uint8_t> binary(binaryLength);
79 GLenum binaryFormat = GL_NONE;
80 mFunctions->getProgramBinary(mProgramID, binaryLength, &binaryLength, &binaryFormat,
81 &binary[0]);
82
83 stream->writeInt(binaryFormat);
84 stream->writeInt(binaryLength);
85 stream->writeBytes(&binary[0], binaryLength);
86
87 return gl::Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -050088}
89
Geoff Langc5629752015-12-07 16:29:04 -050090void ProgramGL::setBinaryRetrievableHint(bool retrievable)
91{
Geoff Lang65a0be92015-10-02 09:57:30 -040092 // glProgramParameteri isn't always available on ES backends.
93 if (mFunctions->programParameteri)
94 {
95 mFunctions->programParameteri(mProgramID, GL_PROGRAM_BINARY_RETRIEVABLE_HINT,
96 retrievable ? GL_TRUE : GL_FALSE);
97 }
Geoff Langc5629752015-12-07 16:29:04 -050098}
99
Jamie Madill9082b982016-04-27 15:21:51 -0400100LinkResult ProgramGL::link(const gl::ContextState &data, gl::InfoLog &infoLog)
Geoff Langf9a6f082015-01-22 13:32:49 -0500101{
Geoff Lang65a0be92015-10-02 09:57:30 -0400102 preLink();
Geoff Langb1f435e2015-02-20 10:01:01 -0500103
Geoff Lang1a683462015-09-29 15:09:59 -0400104 // Set the transform feedback state
105 std::vector<const GLchar *> transformFeedbackVaryings;
Jamie Madill48ef11b2016-04-27 15:21:52 -0400106 for (const auto &tfVarying : mState.getTransformFeedbackVaryingNames())
Geoff Lang1a683462015-09-29 15:09:59 -0400107 {
108 transformFeedbackVaryings.push_back(tfVarying.c_str());
109 }
110
111 if (transformFeedbackVaryings.empty())
112 {
113 if (mFunctions->transformFeedbackVaryings)
114 {
115 mFunctions->transformFeedbackVaryings(mProgramID, 0, nullptr,
Jamie Madill48ef11b2016-04-27 15:21:52 -0400116 mState.getTransformFeedbackBufferMode());
Geoff Lang1a683462015-09-29 15:09:59 -0400117 }
118 }
119 else
120 {
121 ASSERT(mFunctions->transformFeedbackVaryings);
122 mFunctions->transformFeedbackVaryings(
123 mProgramID, static_cast<GLsizei>(transformFeedbackVaryings.size()),
Jamie Madill48ef11b2016-04-27 15:21:52 -0400124 &transformFeedbackVaryings[0], mState.getTransformFeedbackBufferMode());
Geoff Lang1a683462015-09-29 15:09:59 -0400125 }
126
Jamie Madill48ef11b2016-04-27 15:21:52 -0400127 const ShaderGL *vertexShaderGL = GetImplAs<ShaderGL>(mState.getAttachedVertexShader());
128 const ShaderGL *fragmentShaderGL = GetImplAs<ShaderGL>(mState.getAttachedFragmentShader());
Geoff Langb1f435e2015-02-20 10:01:01 -0500129
Geoff Langb1f435e2015-02-20 10:01:01 -0500130 // Attach the shaders
131 mFunctions->attachShader(mProgramID, vertexShaderGL->getShaderID());
132 mFunctions->attachShader(mProgramID, fragmentShaderGL->getShaderID());
133
Geoff Lang1528e562015-08-24 15:10:58 -0400134 // Bind attribute locations to match the GL layer.
Jamie Madill48ef11b2016-04-27 15:21:52 -0400135 for (const sh::Attribute &attribute : mState.getAttributes())
Geoff Lang1528e562015-08-24 15:10:58 -0400136 {
137 if (!attribute.staticUse)
138 {
139 continue;
140 }
141
142 mFunctions->bindAttribLocation(mProgramID, attribute.location, attribute.name.c_str());
Geoff Lang1528e562015-08-24 15:10:58 -0400143 }
144
Geoff Langb1f435e2015-02-20 10:01:01 -0500145 // Link and verify
146 mFunctions->linkProgram(mProgramID);
147
Geoff Lang0ca53782015-05-07 13:49:39 -0400148 // Detach the shaders
149 mFunctions->detachShader(mProgramID, vertexShaderGL->getShaderID());
150 mFunctions->detachShader(mProgramID, fragmentShaderGL->getShaderID());
151
152 // Verify the link
Geoff Lang65a0be92015-10-02 09:57:30 -0400153 if (!checkLinkStatus(infoLog))
Geoff Langb1f435e2015-02-20 10:01:01 -0500154 {
Geoff Langb1f435e2015-02-20 10:01:01 -0500155 return LinkResult(false, gl::Error(GL_NO_ERROR));
156 }
157
Philippe Hamel40911192016-04-07 16:45:50 -0400158 if (mWorkarounds.alwaysCallUseProgramAfterLink)
159 {
160 mStateManager->forceUseProgram(mProgramID);
161 }
162
Geoff Lang65a0be92015-10-02 09:57:30 -0400163 postLink();
Geoff Langb1f435e2015-02-20 10:01:01 -0500164
Geoff Langb1f435e2015-02-20 10:01:01 -0500165 return LinkResult(true, gl::Error(GL_NO_ERROR));
Geoff Langf9a6f082015-01-22 13:32:49 -0500166}
167
Jamie Madill36cfd6a2015-08-18 10:46:20 -0400168GLboolean ProgramGL::validate(const gl::Caps & /*caps*/, gl::InfoLog * /*infoLog*/)
169{
170 // TODO(jmadill): implement validate
171 return true;
172}
173
Geoff Langf9a6f082015-01-22 13:32:49 -0500174void ProgramGL::setUniform1fv(GLint location, GLsizei count, const GLfloat *v)
175{
Geoff Lang63cbace2015-02-26 10:03:12 -0500176 mStateManager->useProgram(mProgramID);
Jamie Madill62d31cb2015-09-11 13:25:51 -0400177 mFunctions->uniform1fv(uniLoc(location), count, v);
Geoff Langf9a6f082015-01-22 13:32:49 -0500178}
179
180void ProgramGL::setUniform2fv(GLint location, GLsizei count, const GLfloat *v)
181{
Geoff Lang63cbace2015-02-26 10:03:12 -0500182 mStateManager->useProgram(mProgramID);
Jamie Madill62d31cb2015-09-11 13:25:51 -0400183 mFunctions->uniform2fv(uniLoc(location), count, v);
Geoff Langf9a6f082015-01-22 13:32:49 -0500184}
185
186void ProgramGL::setUniform3fv(GLint location, GLsizei count, const GLfloat *v)
187{
Geoff Lang63cbace2015-02-26 10:03:12 -0500188 mStateManager->useProgram(mProgramID);
Jamie Madill62d31cb2015-09-11 13:25:51 -0400189 mFunctions->uniform3fv(uniLoc(location), count, v);
Geoff Langf9a6f082015-01-22 13:32:49 -0500190}
191
192void ProgramGL::setUniform4fv(GLint location, GLsizei count, const GLfloat *v)
193{
Geoff Lang63cbace2015-02-26 10:03:12 -0500194 mStateManager->useProgram(mProgramID);
Jamie Madill62d31cb2015-09-11 13:25:51 -0400195 mFunctions->uniform4fv(uniLoc(location), count, v);
Geoff Langf9a6f082015-01-22 13:32:49 -0500196}
197
198void ProgramGL::setUniform1iv(GLint location, GLsizei count, const GLint *v)
199{
Geoff Lang63cbace2015-02-26 10:03:12 -0500200 mStateManager->useProgram(mProgramID);
Jamie Madill62d31cb2015-09-11 13:25:51 -0400201 mFunctions->uniform1iv(uniLoc(location), count, v);
Geoff Langf51bc792015-05-04 14:57:03 -0400202
Jamie Madill48ef11b2016-04-27 15:21:52 -0400203 const gl::VariableLocation &locationEntry = mState.getUniformLocations()[location];
Jamie Madill62d31cb2015-09-11 13:25:51 -0400204
205 size_t samplerIndex = mUniformIndexToSamplerIndex[locationEntry.index];
206 if (samplerIndex != GL_INVALID_INDEX)
Geoff Langf51bc792015-05-04 14:57:03 -0400207 {
Jamie Madill62d31cb2015-09-11 13:25:51 -0400208 std::vector<GLuint> &boundTextureUnits = mSamplerBindings[samplerIndex].boundTextureUnits;
Geoff Langf51bc792015-05-04 14:57:03 -0400209
Jamie Madill62d31cb2015-09-11 13:25:51 -0400210 size_t copyCount =
211 std::max<size_t>(count, boundTextureUnits.size() - locationEntry.element);
212 std::copy(v, v + copyCount, boundTextureUnits.begin() + locationEntry.element);
Geoff Langf51bc792015-05-04 14:57:03 -0400213 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500214}
215
216void ProgramGL::setUniform2iv(GLint location, GLsizei count, const GLint *v)
217{
Geoff Lang63cbace2015-02-26 10:03:12 -0500218 mStateManager->useProgram(mProgramID);
Jamie Madill62d31cb2015-09-11 13:25:51 -0400219 mFunctions->uniform2iv(uniLoc(location), count, v);
Geoff Langf9a6f082015-01-22 13:32:49 -0500220}
221
222void ProgramGL::setUniform3iv(GLint location, GLsizei count, const GLint *v)
223{
Geoff Lang63cbace2015-02-26 10:03:12 -0500224 mStateManager->useProgram(mProgramID);
Jamie Madill62d31cb2015-09-11 13:25:51 -0400225 mFunctions->uniform3iv(uniLoc(location), count, v);
Geoff Langf9a6f082015-01-22 13:32:49 -0500226}
227
228void ProgramGL::setUniform4iv(GLint location, GLsizei count, const GLint *v)
229{
Geoff Lang63cbace2015-02-26 10:03:12 -0500230 mStateManager->useProgram(mProgramID);
Jamie Madill62d31cb2015-09-11 13:25:51 -0400231 mFunctions->uniform4iv(uniLoc(location), count, v);
Geoff Langf9a6f082015-01-22 13:32:49 -0500232}
233
234void ProgramGL::setUniform1uiv(GLint location, GLsizei count, const GLuint *v)
235{
Geoff Lang63cbace2015-02-26 10:03:12 -0500236 mStateManager->useProgram(mProgramID);
Corentin Wallez171e6a52016-06-02 09:57:13 -0400237 mFunctions->uniform1uiv(uniLoc(location), count, v);
Geoff Langf9a6f082015-01-22 13:32:49 -0500238}
239
240void ProgramGL::setUniform2uiv(GLint location, GLsizei count, const GLuint *v)
241{
Geoff Lang63cbace2015-02-26 10:03:12 -0500242 mStateManager->useProgram(mProgramID);
Jamie Madill62d31cb2015-09-11 13:25:51 -0400243 mFunctions->uniform2uiv(uniLoc(location), count, v);
Geoff Langf9a6f082015-01-22 13:32:49 -0500244}
245
246void ProgramGL::setUniform3uiv(GLint location, GLsizei count, const GLuint *v)
247{
Geoff Lang63cbace2015-02-26 10:03:12 -0500248 mStateManager->useProgram(mProgramID);
Jamie Madill62d31cb2015-09-11 13:25:51 -0400249 mFunctions->uniform3uiv(uniLoc(location), count, v);
Geoff Langf9a6f082015-01-22 13:32:49 -0500250}
251
252void ProgramGL::setUniform4uiv(GLint location, GLsizei count, const GLuint *v)
253{
Geoff Lang63cbace2015-02-26 10:03:12 -0500254 mStateManager->useProgram(mProgramID);
Jamie Madill62d31cb2015-09-11 13:25:51 -0400255 mFunctions->uniform4uiv(uniLoc(location), count, v);
Geoff Langf9a6f082015-01-22 13:32:49 -0500256}
257
258void ProgramGL::setUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
259{
Geoff Lang63cbace2015-02-26 10:03:12 -0500260 mStateManager->useProgram(mProgramID);
Jamie Madill62d31cb2015-09-11 13:25:51 -0400261 mFunctions->uniformMatrix2fv(uniLoc(location), count, transpose, value);
Geoff Langf9a6f082015-01-22 13:32:49 -0500262}
263
264void ProgramGL::setUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
265{
Geoff Lang63cbace2015-02-26 10:03:12 -0500266 mStateManager->useProgram(mProgramID);
Jamie Madill62d31cb2015-09-11 13:25:51 -0400267 mFunctions->uniformMatrix3fv(uniLoc(location), count, transpose, value);
Geoff Langf9a6f082015-01-22 13:32:49 -0500268}
269
270void ProgramGL::setUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
271{
Geoff Lang63cbace2015-02-26 10:03:12 -0500272 mStateManager->useProgram(mProgramID);
Jamie Madill62d31cb2015-09-11 13:25:51 -0400273 mFunctions->uniformMatrix4fv(uniLoc(location), count, transpose, value);
Geoff Langf9a6f082015-01-22 13:32:49 -0500274}
275
276void ProgramGL::setUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
277{
Geoff Lang63cbace2015-02-26 10:03:12 -0500278 mStateManager->useProgram(mProgramID);
Jamie Madill62d31cb2015-09-11 13:25:51 -0400279 mFunctions->uniformMatrix2x3fv(uniLoc(location), count, transpose, value);
Geoff Langf9a6f082015-01-22 13:32:49 -0500280}
281
282void ProgramGL::setUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
283{
Geoff Lang63cbace2015-02-26 10:03:12 -0500284 mStateManager->useProgram(mProgramID);
Jamie Madill62d31cb2015-09-11 13:25:51 -0400285 mFunctions->uniformMatrix3x2fv(uniLoc(location), count, transpose, value);
Geoff Langf9a6f082015-01-22 13:32:49 -0500286}
287
288void ProgramGL::setUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
289{
Geoff Lang63cbace2015-02-26 10:03:12 -0500290 mStateManager->useProgram(mProgramID);
Jamie Madill62d31cb2015-09-11 13:25:51 -0400291 mFunctions->uniformMatrix2x4fv(uniLoc(location), count, transpose, value);
Geoff Langf9a6f082015-01-22 13:32:49 -0500292}
293
294void ProgramGL::setUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
295{
Geoff Lang63cbace2015-02-26 10:03:12 -0500296 mStateManager->useProgram(mProgramID);
Jamie Madill62d31cb2015-09-11 13:25:51 -0400297 mFunctions->uniformMatrix4x2fv(uniLoc(location), count, transpose, value);
Geoff Langf9a6f082015-01-22 13:32:49 -0500298}
299
300void ProgramGL::setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
301{
Geoff Lang63cbace2015-02-26 10:03:12 -0500302 mStateManager->useProgram(mProgramID);
Jamie Madill62d31cb2015-09-11 13:25:51 -0400303 mFunctions->uniformMatrix3x4fv(uniLoc(location), count, transpose, value);
Geoff Langf9a6f082015-01-22 13:32:49 -0500304}
305
306void ProgramGL::setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
307{
Geoff Lang63cbace2015-02-26 10:03:12 -0500308 mStateManager->useProgram(mProgramID);
Jamie Madill62d31cb2015-09-11 13:25:51 -0400309 mFunctions->uniformMatrix4x3fv(uniLoc(location), count, transpose, value);
Geoff Langf9a6f082015-01-22 13:32:49 -0500310}
311
Geoff Lang5d124a62015-09-15 13:03:27 -0400312void ProgramGL::setUniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformBlockBinding)
313{
Jamie Madill4a3c2342015-10-08 12:58:45 -0400314 // Lazy init
315 if (mUniformBlockRealLocationMap.empty())
316 {
Jamie Madill48ef11b2016-04-27 15:21:52 -0400317 mUniformBlockRealLocationMap.reserve(mState.getUniformBlocks().size());
318 for (const gl::UniformBlock &uniformBlock : mState.getUniformBlocks())
Jamie Madill4a3c2342015-10-08 12:58:45 -0400319 {
320 const std::string &nameWithIndex = uniformBlock.nameWithArrayIndex();
321 GLuint blockIndex = mFunctions->getUniformBlockIndex(mProgramID, nameWithIndex.c_str());
322 mUniformBlockRealLocationMap.push_back(blockIndex);
323 }
324 }
325
326 GLuint realBlockIndex = mUniformBlockRealLocationMap[uniformBlockIndex];
327 if (realBlockIndex != GL_INVALID_INDEX)
328 {
329 mFunctions->uniformBlockBinding(mProgramID, realBlockIndex, uniformBlockBinding);
330 }
Geoff Lang5d124a62015-09-15 13:03:27 -0400331}
332
Geoff Langb1f435e2015-02-20 10:01:01 -0500333GLuint ProgramGL::getProgramID() const
334{
335 return mProgramID;
336}
337
Geoff Langf51bc792015-05-04 14:57:03 -0400338const std::vector<SamplerBindingGL> &ProgramGL::getAppliedSamplerUniforms() const
339{
340 return mSamplerBindings;
341}
342
Jamie Madill4a3c2342015-10-08 12:58:45 -0400343bool ProgramGL::getUniformBlockSize(const std::string &blockName, size_t *sizeOut) const
Jamie Madill62d31cb2015-09-11 13:25:51 -0400344{
Jamie Madill4a3c2342015-10-08 12:58:45 -0400345 ASSERT(mProgramID != 0u);
Geoff Lang5d124a62015-09-15 13:03:27 -0400346
Jamie Madill4a3c2342015-10-08 12:58:45 -0400347 GLuint blockIndex = mFunctions->getUniformBlockIndex(mProgramID, blockName.c_str());
348 if (blockIndex == GL_INVALID_INDEX)
Geoff Lang5d124a62015-09-15 13:03:27 -0400349 {
Jamie Madill4a3c2342015-10-08 12:58:45 -0400350 *sizeOut = 0;
351 return false;
Geoff Lang5d124a62015-09-15 13:03:27 -0400352 }
353
Jamie Madill4a3c2342015-10-08 12:58:45 -0400354 GLint dataSize = 0;
355 mFunctions->getActiveUniformBlockiv(mProgramID, blockIndex, GL_UNIFORM_BLOCK_DATA_SIZE,
356 &dataSize);
357 *sizeOut = static_cast<size_t>(dataSize);
358 return true;
359}
360
361bool ProgramGL::getUniformBlockMemberInfo(const std::string &memberUniformName,
362 sh::BlockMemberInfo *memberInfoOut) const
363{
364 GLuint uniformIndex;
365 const GLchar *memberNameGLStr = memberUniformName.c_str();
366 mFunctions->getUniformIndices(mProgramID, 1, &memberNameGLStr, &uniformIndex);
367
368 if (uniformIndex == GL_INVALID_INDEX)
Geoff Lang5d124a62015-09-15 13:03:27 -0400369 {
Jamie Madill4a3c2342015-10-08 12:58:45 -0400370 *memberInfoOut = sh::BlockMemberInfo::getDefaultBlockInfo();
371 return false;
Geoff Lang5d124a62015-09-15 13:03:27 -0400372 }
Jamie Madill4a3c2342015-10-08 12:58:45 -0400373
374 mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_OFFSET,
375 &memberInfoOut->offset);
376 mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_ARRAY_STRIDE,
377 &memberInfoOut->arrayStride);
378 mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_MATRIX_STRIDE,
379 &memberInfoOut->matrixStride);
380
381 // TODO(jmadill): possibly determine this at the gl::Program level.
382 GLint isRowMajorMatrix = 0;
383 mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_IS_ROW_MAJOR,
384 &isRowMajorMatrix);
385 memberInfoOut->isRowMajorMatrix = isRowMajorMatrix != GL_FALSE;
386 return true;
Jamie Madill62d31cb2015-09-11 13:25:51 -0400387}
Jamie Madill4a3c2342015-10-08 12:58:45 -0400388
Sami Väisänen46eaa942016-06-29 10:26:37 +0300389void ProgramGL::setPathFragmentInputGen(const std::string &inputName,
390 GLenum genMode,
391 GLint components,
392 const GLfloat *coeffs)
393{
394 ASSERT(mEnablePathRendering);
395
396 for (const auto &input : mPathRenderingFragmentInputs)
397 {
398 if (input.name == inputName)
399 {
400 mFunctions->programPathFragmentInputGenNV(mProgramID, input.location, genMode,
401 components, coeffs);
402 ASSERT(mFunctions->getError() == GL_NO_ERROR);
403 return;
404 }
405 }
406
407}
408
Geoff Lang65a0be92015-10-02 09:57:30 -0400409void ProgramGL::preLink()
410{
411 // Reset the program state
412 mUniformRealLocationMap.clear();
413 mUniformBlockRealLocationMap.clear();
414 mSamplerBindings.clear();
415 mUniformIndexToSamplerIndex.clear();
Sami Väisänen46eaa942016-06-29 10:26:37 +0300416 mPathRenderingFragmentInputs.clear();
Geoff Lang65a0be92015-10-02 09:57:30 -0400417}
418
419bool ProgramGL::checkLinkStatus(gl::InfoLog &infoLog)
420{
421 GLint linkStatus = GL_FALSE;
422 mFunctions->getProgramiv(mProgramID, GL_LINK_STATUS, &linkStatus);
423 if (linkStatus == GL_FALSE)
424 {
425 // Linking failed, put the error into the info log
426 GLint infoLogLength = 0;
427 mFunctions->getProgramiv(mProgramID, GL_INFO_LOG_LENGTH, &infoLogLength);
428
429 std::string warning;
430
431 // Info log length includes the null terminator, so 1 means that the info log is an empty
432 // string.
433 if (infoLogLength > 1)
434 {
435 std::vector<char> buf(infoLogLength);
436 mFunctions->getProgramInfoLog(mProgramID, infoLogLength, nullptr, &buf[0]);
437
438 mFunctions->deleteProgram(mProgramID);
439 mProgramID = 0;
440
441 infoLog << buf.data();
442
443 warning = FormatString("Program link failed unexpectedly: %s", buf.data());
444 }
445 else
446 {
447 warning = "Program link failed unexpectedly with no info log.";
448 }
449 ANGLEPlatformCurrent()->logWarning(warning.c_str());
450 TRACE("\n%s", warning.c_str());
451
452 // TODO, return GL_OUT_OF_MEMORY or just fail the link? This is an unexpected case
453 return false;
454 }
455
456 return true;
457}
458
459void ProgramGL::postLink()
460{
461 // Query the uniform information
462 ASSERT(mUniformRealLocationMap.empty());
Jamie Madill48ef11b2016-04-27 15:21:52 -0400463 const auto &uniformLocations = mState.getUniformLocations();
464 const auto &uniforms = mState.getUniforms();
Geoff Lang65a0be92015-10-02 09:57:30 -0400465 mUniformRealLocationMap.resize(uniformLocations.size(), GL_INVALID_INDEX);
466 for (size_t uniformLocation = 0; uniformLocation < uniformLocations.size(); uniformLocation++)
467 {
468 const auto &entry = uniformLocations[uniformLocation];
469 if (!entry.used)
470 {
471 continue;
472 }
473
474 // From the spec:
475 // "Locations for sequential array indices are not required to be sequential."
476 const gl::LinkedUniform &uniform = uniforms[entry.index];
477 std::stringstream fullNameStr;
478 fullNameStr << uniform.name;
479 if (uniform.isArray())
480 {
481 fullNameStr << "[" << entry.element << "]";
482 }
483 const std::string &fullName = fullNameStr.str();
484
485 GLint realLocation = mFunctions->getUniformLocation(mProgramID, fullName.c_str());
486 mUniformRealLocationMap[uniformLocation] = realLocation;
487 }
488
Jamie Madill48ef11b2016-04-27 15:21:52 -0400489 mUniformIndexToSamplerIndex.resize(mState.getUniforms().size(), GL_INVALID_INDEX);
Geoff Lang65a0be92015-10-02 09:57:30 -0400490
491 for (size_t uniformId = 0; uniformId < uniforms.size(); ++uniformId)
492 {
493 const gl::LinkedUniform &linkedUniform = uniforms[uniformId];
494
495 if (!linkedUniform.isSampler() || !linkedUniform.staticUse)
496 continue;
497
498 mUniformIndexToSamplerIndex[uniformId] = mSamplerBindings.size();
499
500 // If uniform is a sampler type, insert it into the mSamplerBindings array
501 SamplerBindingGL samplerBinding;
502 samplerBinding.textureType = gl::SamplerTypeToTextureType(linkedUniform.type);
503 samplerBinding.boundTextureUnits.resize(linkedUniform.elementCount(), 0);
504 mSamplerBindings.push_back(samplerBinding);
505 }
Sami Väisänen46eaa942016-06-29 10:26:37 +0300506
507 // Discover CHROMIUM_path_rendering fragment inputs if enabled.
508 if (!mEnablePathRendering)
509 return;
510
511 GLint numFragmentInputs = 0;
512 mFunctions->getProgramInterfaceiv(mProgramID, GL_FRAGMENT_INPUT_NV, GL_ACTIVE_RESOURCES,
513 &numFragmentInputs);
514 if (numFragmentInputs <= 0)
515 return;
516
517 GLint maxNameLength = 0;
518 mFunctions->getProgramInterfaceiv(mProgramID, GL_FRAGMENT_INPUT_NV, GL_MAX_NAME_LENGTH,
519 &maxNameLength);
520 ASSERT(maxNameLength);
521
522 for (GLint i = 0; i < numFragmentInputs; ++i)
523 {
524 std::string name;
525 name.resize(maxNameLength);
526
527 GLsizei nameLen = 0;
528 mFunctions->getProgramResourceName(mProgramID, GL_FRAGMENT_INPUT_NV, i, maxNameLength,
529 &nameLen, &name[0]);
530 name.resize(nameLen);
531
532 // Ignore built-ins
533 if (angle::BeginsWith(name, "gl_"))
534 continue;
535
536 const GLenum kQueryProperties[] = {GL_LOCATION, GL_ARRAY_SIZE};
537 GLint queryResults[ArraySize(kQueryProperties)];
538 GLsizei queryLength = 0;
539
Geoff Lang3f6a3982016-07-15 15:20:45 -0400540 mFunctions->getProgramResourceiv(
541 mProgramID, GL_FRAGMENT_INPUT_NV, i, static_cast<GLsizei>(ArraySize(kQueryProperties)),
542 kQueryProperties, static_cast<GLsizei>(ArraySize(queryResults)), &queryLength,
543 queryResults);
Sami Väisänen46eaa942016-06-29 10:26:37 +0300544
Olli Etuahoe3191712016-07-18 16:01:10 +0300545 ASSERT(queryLength == static_cast<GLsizei>(ArraySize(kQueryProperties)));
Sami Väisänen46eaa942016-06-29 10:26:37 +0300546
Geoff Lang3f6a3982016-07-15 15:20:45 -0400547 PathRenderingFragmentInput baseElementInput;
548 baseElementInput.name = name;
549 baseElementInput.location = queryResults[0];
550 mPathRenderingFragmentInputs.push_back(std::move(baseElementInput));
Sami Väisänen46eaa942016-06-29 10:26:37 +0300551
552 // If the input is an array it's denoted by [0] suffix on the variable
553 // name. We'll then create an entry per each array index where index > 0
554 if (angle::EndsWith(name, "[0]"))
555 {
556 // drop the suffix
557 name.resize(name.size() - 3);
558
559 const auto arraySize = queryResults[1];
560 const auto baseLocation = queryResults[0];
561
Geoff Lang3f6a3982016-07-15 15:20:45 -0400562 for (GLint arrayIndex = 1; arrayIndex < arraySize; ++arrayIndex)
Sami Väisänen46eaa942016-06-29 10:26:37 +0300563 {
Geoff Lang3f6a3982016-07-15 15:20:45 -0400564 PathRenderingFragmentInput arrayElementInput;
565 arrayElementInput.name = name + "[" + std::to_string(arrayIndex) + "]";
566 arrayElementInput.location = baseLocation + arrayIndex;
567 mPathRenderingFragmentInputs.push_back(std::move(arrayElementInput));
Sami Väisänen46eaa942016-06-29 10:26:37 +0300568 }
569 }
570 }
Geoff Lang65a0be92015-10-02 09:57:30 -0400571}
572
Jamie Madill4a3c2342015-10-08 12:58:45 -0400573} // namespace rx