blob: 337bc4822d03c7315e23897c409d8ddc46c19b42 [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"
Jamie Madillc564c072017-06-01 12:45:42 -040012#include "common/bitset_utils.h"
Geoff Langf9a6f082015-01-22 13:32:49 -050013#include "common/debug.h"
Sami Väisänen46eaa942016-06-29 10:26:37 +030014#include "common/string_utils.h"
Geoff Lang5ed74cf2015-04-14 13:57:07 -040015#include "common/utilities.h"
Jamie Madillc564c072017-06-01 12:45:42 -040016#include "libANGLE/Context.h"
17#include "libANGLE/Uniform.h"
Jamie Madilla7d12dc2016-12-13 15:08:19 -050018#include "libANGLE/renderer/gl/ContextGL.h"
Geoff Langb1f435e2015-02-20 10:01:01 -050019#include "libANGLE/renderer/gl/FunctionsGL.h"
20#include "libANGLE/renderer/gl/ShaderGL.h"
21#include "libANGLE/renderer/gl/StateManagerGL.h"
Philippe Hamel40911192016-04-07 16:45:50 -040022#include "libANGLE/renderer/gl/WorkaroundsGL.h"
unknownb4a3af22015-11-25 15:02:51 -050023#include "platform/Platform.h"
Geoff Langf9a6f082015-01-22 13:32:49 -050024
25namespace rx
26{
27
Jamie Madill48ef11b2016-04-27 15:21:52 -040028ProgramGL::ProgramGL(const gl::ProgramState &data,
Jamie Madill5c6b7bf2015-08-17 12:53:35 -040029 const FunctionsGL *functions,
Philippe Hamel40911192016-04-07 16:45:50 -040030 const WorkaroundsGL &workarounds,
Sami Väisänen46eaa942016-06-29 10:26:37 +030031 StateManagerGL *stateManager,
32 bool enablePathRendering)
Philippe Hamel40911192016-04-07 16:45:50 -040033 : ProgramImpl(data),
34 mFunctions(functions),
35 mWorkarounds(workarounds),
36 mStateManager(stateManager),
Sami Väisänen46eaa942016-06-29 10:26:37 +030037 mEnablePathRendering(enablePathRendering),
Philippe Hamel40911192016-04-07 16:45:50 -040038 mProgramID(0)
Geoff Langb1f435e2015-02-20 10:01:01 -050039{
40 ASSERT(mFunctions);
41 ASSERT(mStateManager);
Geoff Lang0ca53782015-05-07 13:49:39 -040042
43 mProgramID = mFunctions->createProgram();
Geoff Langb1f435e2015-02-20 10:01:01 -050044}
Geoff Langf9a6f082015-01-22 13:32:49 -050045
46ProgramGL::~ProgramGL()
Geoff Langb1f435e2015-02-20 10:01:01 -050047{
Geoff Lang0ca53782015-05-07 13:49:39 -040048 mFunctions->deleteProgram(mProgramID);
49 mProgramID = 0;
Geoff Langb1f435e2015-02-20 10:01:01 -050050}
Geoff Langf9a6f082015-01-22 13:32:49 -050051
Jamie Madill9cf9e872017-06-05 12:59:25 -040052gl::LinkResult ProgramGL::load(const gl::Context *context,
53 gl::InfoLog &infoLog,
54 gl::BinaryInputStream *stream)
Geoff Langf9a6f082015-01-22 13:32:49 -050055{
Geoff Lang65a0be92015-10-02 09:57:30 -040056 preLink();
57
58 // Read the binary format, size and blob
59 GLenum binaryFormat = stream->readInt<GLenum>();
60 GLint binaryLength = stream->readInt<GLint>();
61 const uint8_t *binary = stream->data() + stream->offset();
62 stream->skip(binaryLength);
63
64 // Load the binary
65 mFunctions->programBinary(mProgramID, binaryFormat, binary, binaryLength);
66
67 // Verify that the program linked
68 if (!checkLinkStatus(infoLog))
69 {
Jamie Madillb0a838b2016-11-13 20:02:12 -050070 return false;
Geoff Lang65a0be92015-10-02 09:57:30 -040071 }
72
73 postLink();
74
Jamie Madilla7d12dc2016-12-13 15:08:19 -050075 // Re-apply UBO bindings to work around driver bugs.
Jamie Madillc564c072017-06-01 12:45:42 -040076 const WorkaroundsGL &workaroundsGL = GetImplAs<ContextGL>(context)->getWorkaroundsGL();
Jamie Madilla7d12dc2016-12-13 15:08:19 -050077 if (workaroundsGL.reapplyUBOBindingsAfterLoadingBinaryProgram)
78 {
Jamie Madill6de51852017-04-12 09:53:01 -040079 for (size_t bindingIndex : mState.getActiveUniformBlockBindingsMask())
Jamie Madilla7d12dc2016-12-13 15:08:19 -050080 {
Jamie Madill6de51852017-04-12 09:53:01 -040081 GLuint uintIndex = static_cast<GLuint>(bindingIndex);
82 setUniformBlockBinding(uintIndex, mState.getUniformBlockBinding(uintIndex));
Jamie Madilla7d12dc2016-12-13 15:08:19 -050083 }
84 }
85
Jamie Madillb0a838b2016-11-13 20:02:12 -050086 return true;
Geoff Langf9a6f082015-01-22 13:32:49 -050087}
88
Jamie Madill83418fb2017-06-05 12:59:24 -040089void ProgramGL::save(gl::BinaryOutputStream *stream)
Geoff Langf9a6f082015-01-22 13:32:49 -050090{
Geoff Lang65a0be92015-10-02 09:57:30 -040091 GLint binaryLength = 0;
92 mFunctions->getProgramiv(mProgramID, GL_PROGRAM_BINARY_LENGTH, &binaryLength);
93
94 std::vector<uint8_t> binary(binaryLength);
95 GLenum binaryFormat = GL_NONE;
96 mFunctions->getProgramBinary(mProgramID, binaryLength, &binaryLength, &binaryFormat,
97 &binary[0]);
98
99 stream->writeInt(binaryFormat);
100 stream->writeInt(binaryLength);
101 stream->writeBytes(&binary[0], binaryLength);
Geoff Langf9a6f082015-01-22 13:32:49 -0500102}
103
Geoff Langc5629752015-12-07 16:29:04 -0500104void ProgramGL::setBinaryRetrievableHint(bool retrievable)
105{
Geoff Lang65a0be92015-10-02 09:57:30 -0400106 // glProgramParameteri isn't always available on ES backends.
107 if (mFunctions->programParameteri)
108 {
109 mFunctions->programParameteri(mProgramID, GL_PROGRAM_BINARY_RETRIEVABLE_HINT,
110 retrievable ? GL_TRUE : GL_FALSE);
111 }
Geoff Langc5629752015-12-07 16:29:04 -0500112}
113
Yunchao He61afff12017-03-14 15:34:03 +0800114void ProgramGL::setSeparable(bool separable)
115{
116 mFunctions->programParameteri(mProgramID, GL_PROGRAM_SEPARABLE, separable ? GL_TRUE : GL_FALSE);
117}
118
Jamie Madill9cf9e872017-06-05 12:59:25 -0400119gl::LinkResult ProgramGL::link(const gl::Context *context,
120 const gl::VaryingPacking &packing,
121 gl::InfoLog &infoLog)
Geoff Langf9a6f082015-01-22 13:32:49 -0500122{
Geoff Lang65a0be92015-10-02 09:57:30 -0400123 preLink();
Geoff Langb1f435e2015-02-20 10:01:01 -0500124
Martin Radev4c4c8e72016-08-04 12:25:34 +0300125 if (mState.getAttachedComputeShader())
Geoff Lang1a683462015-09-29 15:09:59 -0400126 {
Martin Radev4c4c8e72016-08-04 12:25:34 +0300127 const ShaderGL *computeShaderGL = GetImplAs<ShaderGL>(mState.getAttachedComputeShader());
Geoff Lang1a683462015-09-29 15:09:59 -0400128
Martin Radev4c4c8e72016-08-04 12:25:34 +0300129 mFunctions->attachShader(mProgramID, computeShaderGL->getShaderID());
130
131 // Link and verify
132 mFunctions->linkProgram(mProgramID);
133
134 // Detach the shaders
135 mFunctions->detachShader(mProgramID, computeShaderGL->getShaderID());
Geoff Lang1a683462015-09-29 15:09:59 -0400136 }
137 else
138 {
Martin Radev4c4c8e72016-08-04 12:25:34 +0300139 // Set the transform feedback state
140 std::vector<const GLchar *> transformFeedbackVaryings;
141 for (const auto &tfVarying : mState.getTransformFeedbackVaryingNames())
Geoff Lang1528e562015-08-24 15:10:58 -0400142 {
Martin Radev4c4c8e72016-08-04 12:25:34 +0300143 transformFeedbackVaryings.push_back(tfVarying.c_str());
Geoff Lang1528e562015-08-24 15:10:58 -0400144 }
145
Martin Radev4c4c8e72016-08-04 12:25:34 +0300146 if (transformFeedbackVaryings.empty())
147 {
148 if (mFunctions->transformFeedbackVaryings)
149 {
150 mFunctions->transformFeedbackVaryings(mProgramID, 0, nullptr,
151 mState.getTransformFeedbackBufferMode());
152 }
153 }
154 else
155 {
156 ASSERT(mFunctions->transformFeedbackVaryings);
157 mFunctions->transformFeedbackVaryings(
158 mProgramID, static_cast<GLsizei>(transformFeedbackVaryings.size()),
159 &transformFeedbackVaryings[0], mState.getTransformFeedbackBufferMode());
160 }
161
162 const ShaderGL *vertexShaderGL = GetImplAs<ShaderGL>(mState.getAttachedVertexShader());
163 const ShaderGL *fragmentShaderGL = GetImplAs<ShaderGL>(mState.getAttachedFragmentShader());
164
165 // Attach the shaders
166 mFunctions->attachShader(mProgramID, vertexShaderGL->getShaderID());
167 mFunctions->attachShader(mProgramID, fragmentShaderGL->getShaderID());
168
169 // Bind attribute locations to match the GL layer.
170 for (const sh::Attribute &attribute : mState.getAttributes())
171 {
Corentin Wallez6c1cbf52016-11-23 12:44:35 -0500172 if (!attribute.staticUse || attribute.isBuiltIn())
Martin Radev4c4c8e72016-08-04 12:25:34 +0300173 {
174 continue;
175 }
176
177 mFunctions->bindAttribLocation(mProgramID, attribute.location, attribute.name.c_str());
178 }
179
180 // Link and verify
181 mFunctions->linkProgram(mProgramID);
182
183 // Detach the shaders
184 mFunctions->detachShader(mProgramID, vertexShaderGL->getShaderID());
185 mFunctions->detachShader(mProgramID, fragmentShaderGL->getShaderID());
Geoff Lang1528e562015-08-24 15:10:58 -0400186 }
187
Geoff Lang0ca53782015-05-07 13:49:39 -0400188 // Verify the link
Geoff Lang65a0be92015-10-02 09:57:30 -0400189 if (!checkLinkStatus(infoLog))
Geoff Langb1f435e2015-02-20 10:01:01 -0500190 {
Jamie Madillb0a838b2016-11-13 20:02:12 -0500191 return false;
Geoff Langb1f435e2015-02-20 10:01:01 -0500192 }
193
Philippe Hamel40911192016-04-07 16:45:50 -0400194 if (mWorkarounds.alwaysCallUseProgramAfterLink)
195 {
196 mStateManager->forceUseProgram(mProgramID);
197 }
198
Geoff Lang65a0be92015-10-02 09:57:30 -0400199 postLink();
Geoff Langb1f435e2015-02-20 10:01:01 -0500200
Jamie Madillb0a838b2016-11-13 20:02:12 -0500201 return true;
Geoff Langf9a6f082015-01-22 13:32:49 -0500202}
203
Jamie Madill36cfd6a2015-08-18 10:46:20 -0400204GLboolean ProgramGL::validate(const gl::Caps & /*caps*/, gl::InfoLog * /*infoLog*/)
205{
206 // TODO(jmadill): implement validate
207 return true;
208}
209
Geoff Langf9a6f082015-01-22 13:32:49 -0500210void ProgramGL::setUniform1fv(GLint location, GLsizei count, const GLfloat *v)
211{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800212 if (mFunctions->programUniform1fv != nullptr)
213 {
214 mFunctions->programUniform1fv(mProgramID, uniLoc(location), count, v);
215 }
216 else
217 {
218 mStateManager->useProgram(mProgramID);
219 mFunctions->uniform1fv(uniLoc(location), count, v);
220 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500221}
222
223void ProgramGL::setUniform2fv(GLint location, GLsizei count, const GLfloat *v)
224{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800225 if (mFunctions->programUniform2fv != nullptr)
226 {
227 mFunctions->programUniform2fv(mProgramID, uniLoc(location), count, v);
228 }
229 else
230 {
231 mStateManager->useProgram(mProgramID);
232 mFunctions->uniform2fv(uniLoc(location), count, v);
233 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500234}
235
236void ProgramGL::setUniform3fv(GLint location, GLsizei count, const GLfloat *v)
237{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800238 if (mFunctions->programUniform3fv != nullptr)
239 {
240 mFunctions->programUniform3fv(mProgramID, uniLoc(location), count, v);
241 }
242 else
243 {
244 mStateManager->useProgram(mProgramID);
245 mFunctions->uniform3fv(uniLoc(location), count, v);
246 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500247}
248
249void ProgramGL::setUniform4fv(GLint location, GLsizei count, const GLfloat *v)
250{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800251 if (mFunctions->programUniform4fv != nullptr)
252 {
253 mFunctions->programUniform4fv(mProgramID, uniLoc(location), count, v);
254 }
255 else
256 {
257 mStateManager->useProgram(mProgramID);
258 mFunctions->uniform4fv(uniLoc(location), count, v);
259 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500260}
261
262void ProgramGL::setUniform1iv(GLint location, GLsizei count, const GLint *v)
263{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800264 if (mFunctions->programUniform1iv != nullptr)
265 {
266 mFunctions->programUniform1iv(mProgramID, uniLoc(location), count, v);
267 }
268 else
269 {
270 mStateManager->useProgram(mProgramID);
271 mFunctions->uniform1iv(uniLoc(location), count, v);
272 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500273}
274
275void ProgramGL::setUniform2iv(GLint location, GLsizei count, const GLint *v)
276{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800277 if (mFunctions->programUniform2iv != nullptr)
278 {
279 mFunctions->programUniform2iv(mProgramID, uniLoc(location), count, v);
280 }
281 else
282 {
283 mStateManager->useProgram(mProgramID);
284 mFunctions->uniform2iv(uniLoc(location), count, v);
285 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500286}
287
288void ProgramGL::setUniform3iv(GLint location, GLsizei count, const GLint *v)
289{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800290 if (mFunctions->programUniform3iv != nullptr)
291 {
292 mFunctions->programUniform3iv(mProgramID, uniLoc(location), count, v);
293 }
294 else
295 {
296 mStateManager->useProgram(mProgramID);
297 mFunctions->uniform3iv(uniLoc(location), count, v);
298 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500299}
300
301void ProgramGL::setUniform4iv(GLint location, GLsizei count, const GLint *v)
302{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800303 if (mFunctions->programUniform4iv != nullptr)
304 {
305 mFunctions->programUniform4iv(mProgramID, uniLoc(location), count, v);
306 }
307 else
308 {
309 mStateManager->useProgram(mProgramID);
310 mFunctions->uniform4iv(uniLoc(location), count, v);
311 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500312}
313
314void ProgramGL::setUniform1uiv(GLint location, GLsizei count, const GLuint *v)
315{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800316 if (mFunctions->programUniform1uiv != nullptr)
317 {
318 mFunctions->programUniform1uiv(mProgramID, uniLoc(location), count, v);
319 }
320 else
321 {
322 mStateManager->useProgram(mProgramID);
323 mFunctions->uniform1uiv(uniLoc(location), count, v);
324 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500325}
326
327void ProgramGL::setUniform2uiv(GLint location, GLsizei count, const GLuint *v)
328{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800329 if (mFunctions->programUniform2uiv != nullptr)
330 {
331 mFunctions->programUniform2uiv(mProgramID, uniLoc(location), count, v);
332 }
333 else
334 {
335 mStateManager->useProgram(mProgramID);
336 mFunctions->uniform2uiv(uniLoc(location), count, v);
337 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500338}
339
340void ProgramGL::setUniform3uiv(GLint location, GLsizei count, const GLuint *v)
341{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800342 if (mFunctions->programUniform3uiv != nullptr)
343 {
344 mFunctions->programUniform3uiv(mProgramID, uniLoc(location), count, v);
345 }
346 else
347 {
348 mStateManager->useProgram(mProgramID);
349 mFunctions->uniform3uiv(uniLoc(location), count, v);
350 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500351}
352
353void ProgramGL::setUniform4uiv(GLint location, GLsizei count, const GLuint *v)
354{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800355 if (mFunctions->programUniform4uiv != nullptr)
356 {
357 mFunctions->programUniform4uiv(mProgramID, uniLoc(location), count, v);
358 }
359 else
360 {
361 mStateManager->useProgram(mProgramID);
362 mFunctions->uniform4uiv(uniLoc(location), count, v);
363 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500364}
365
366void ProgramGL::setUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
367{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800368 if (mFunctions->programUniformMatrix2fv != nullptr)
369 {
370 mFunctions->programUniformMatrix2fv(mProgramID, uniLoc(location), count, transpose, value);
371 }
372 else
373 {
374 mStateManager->useProgram(mProgramID);
375 mFunctions->uniformMatrix2fv(uniLoc(location), count, transpose, value);
376 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500377}
378
379void ProgramGL::setUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
380{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800381 if (mFunctions->programUniformMatrix3fv != nullptr)
382 {
383 mFunctions->programUniformMatrix3fv(mProgramID, uniLoc(location), count, transpose, value);
384 }
385 else
386 {
387 mStateManager->useProgram(mProgramID);
388 mFunctions->uniformMatrix3fv(uniLoc(location), count, transpose, value);
389 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500390}
391
392void ProgramGL::setUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
393{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800394 if (mFunctions->programUniformMatrix4fv != nullptr)
395 {
396 mFunctions->programUniformMatrix4fv(mProgramID, uniLoc(location), count, transpose, value);
397 }
398 else
399 {
400 mStateManager->useProgram(mProgramID);
401 mFunctions->uniformMatrix4fv(uniLoc(location), count, transpose, value);
402 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500403}
404
405void ProgramGL::setUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
406{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800407 if (mFunctions->programUniformMatrix2x3fv != nullptr)
408 {
409 mFunctions->programUniformMatrix2x3fv(mProgramID, uniLoc(location), count, transpose,
410 value);
411 }
412 else
413 {
414 mStateManager->useProgram(mProgramID);
415 mFunctions->uniformMatrix2x3fv(uniLoc(location), count, transpose, value);
416 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500417}
418
419void ProgramGL::setUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
420{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800421 if (mFunctions->programUniformMatrix3x2fv != nullptr)
422 {
423 mFunctions->programUniformMatrix3x2fv(mProgramID, uniLoc(location), count, transpose,
424 value);
425 }
426 else
427 {
428 mStateManager->useProgram(mProgramID);
429 mFunctions->uniformMatrix3x2fv(uniLoc(location), count, transpose, value);
430 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500431}
432
433void ProgramGL::setUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
434{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800435 if (mFunctions->programUniformMatrix2x4fv != nullptr)
436 {
437 mFunctions->programUniformMatrix2x4fv(mProgramID, uniLoc(location), count, transpose,
438 value);
439 }
440 else
441 {
442 mStateManager->useProgram(mProgramID);
443 mFunctions->uniformMatrix2x4fv(uniLoc(location), count, transpose, value);
444 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500445}
446
447void ProgramGL::setUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
448{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800449 if (mFunctions->programUniformMatrix4x2fv != nullptr)
450 {
451 mFunctions->programUniformMatrix4x2fv(mProgramID, uniLoc(location), count, transpose,
452 value);
453 }
454 else
455 {
456 mStateManager->useProgram(mProgramID);
457 mFunctions->uniformMatrix4x2fv(uniLoc(location), count, transpose, value);
458 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500459}
460
461void ProgramGL::setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
462{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800463 if (mFunctions->programUniformMatrix3x4fv != nullptr)
464 {
465 mFunctions->programUniformMatrix3x4fv(mProgramID, uniLoc(location), count, transpose,
466 value);
467 }
468 else
469 {
470 mStateManager->useProgram(mProgramID);
471 mFunctions->uniformMatrix3x4fv(uniLoc(location), count, transpose, value);
472 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500473}
474
475void ProgramGL::setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
476{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800477 if (mFunctions->programUniformMatrix4x3fv != nullptr)
478 {
479 mFunctions->programUniformMatrix4x3fv(mProgramID, uniLoc(location), count, transpose,
480 value);
481 }
482 else
483 {
484 mStateManager->useProgram(mProgramID);
485 mFunctions->uniformMatrix4x3fv(uniLoc(location), count, transpose, value);
486 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500487}
488
Geoff Lang5d124a62015-09-15 13:03:27 -0400489void ProgramGL::setUniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformBlockBinding)
490{
Jamie Madill4a3c2342015-10-08 12:58:45 -0400491 // Lazy init
492 if (mUniformBlockRealLocationMap.empty())
493 {
Jamie Madill48ef11b2016-04-27 15:21:52 -0400494 mUniformBlockRealLocationMap.reserve(mState.getUniformBlocks().size());
495 for (const gl::UniformBlock &uniformBlock : mState.getUniformBlocks())
Jamie Madill4a3c2342015-10-08 12:58:45 -0400496 {
497 const std::string &nameWithIndex = uniformBlock.nameWithArrayIndex();
498 GLuint blockIndex = mFunctions->getUniformBlockIndex(mProgramID, nameWithIndex.c_str());
499 mUniformBlockRealLocationMap.push_back(blockIndex);
500 }
501 }
502
503 GLuint realBlockIndex = mUniformBlockRealLocationMap[uniformBlockIndex];
504 if (realBlockIndex != GL_INVALID_INDEX)
505 {
506 mFunctions->uniformBlockBinding(mProgramID, realBlockIndex, uniformBlockBinding);
507 }
Geoff Lang5d124a62015-09-15 13:03:27 -0400508}
509
Geoff Langb1f435e2015-02-20 10:01:01 -0500510GLuint ProgramGL::getProgramID() const
511{
512 return mProgramID;
513}
514
Jamie Madill4a3c2342015-10-08 12:58:45 -0400515bool ProgramGL::getUniformBlockSize(const std::string &blockName, size_t *sizeOut) const
Jamie Madill62d31cb2015-09-11 13:25:51 -0400516{
Jamie Madill4a3c2342015-10-08 12:58:45 -0400517 ASSERT(mProgramID != 0u);
Geoff Lang5d124a62015-09-15 13:03:27 -0400518
Jamie Madill4a3c2342015-10-08 12:58:45 -0400519 GLuint blockIndex = mFunctions->getUniformBlockIndex(mProgramID, blockName.c_str());
520 if (blockIndex == GL_INVALID_INDEX)
Geoff Lang5d124a62015-09-15 13:03:27 -0400521 {
Jamie Madill4a3c2342015-10-08 12:58:45 -0400522 *sizeOut = 0;
523 return false;
Geoff Lang5d124a62015-09-15 13:03:27 -0400524 }
525
Jamie Madill4a3c2342015-10-08 12:58:45 -0400526 GLint dataSize = 0;
527 mFunctions->getActiveUniformBlockiv(mProgramID, blockIndex, GL_UNIFORM_BLOCK_DATA_SIZE,
528 &dataSize);
529 *sizeOut = static_cast<size_t>(dataSize);
530 return true;
531}
532
533bool ProgramGL::getUniformBlockMemberInfo(const std::string &memberUniformName,
534 sh::BlockMemberInfo *memberInfoOut) const
535{
536 GLuint uniformIndex;
537 const GLchar *memberNameGLStr = memberUniformName.c_str();
538 mFunctions->getUniformIndices(mProgramID, 1, &memberNameGLStr, &uniformIndex);
539
540 if (uniformIndex == GL_INVALID_INDEX)
Geoff Lang5d124a62015-09-15 13:03:27 -0400541 {
Jamie Madill4a3c2342015-10-08 12:58:45 -0400542 *memberInfoOut = sh::BlockMemberInfo::getDefaultBlockInfo();
543 return false;
Geoff Lang5d124a62015-09-15 13:03:27 -0400544 }
Jamie Madill4a3c2342015-10-08 12:58:45 -0400545
546 mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_OFFSET,
547 &memberInfoOut->offset);
548 mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_ARRAY_STRIDE,
549 &memberInfoOut->arrayStride);
550 mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_MATRIX_STRIDE,
551 &memberInfoOut->matrixStride);
552
553 // TODO(jmadill): possibly determine this at the gl::Program level.
554 GLint isRowMajorMatrix = 0;
555 mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_IS_ROW_MAJOR,
556 &isRowMajorMatrix);
557 memberInfoOut->isRowMajorMatrix = isRowMajorMatrix != GL_FALSE;
558 return true;
Jamie Madill62d31cb2015-09-11 13:25:51 -0400559}
Jamie Madill4a3c2342015-10-08 12:58:45 -0400560
Sami Väisänen46eaa942016-06-29 10:26:37 +0300561void ProgramGL::setPathFragmentInputGen(const std::string &inputName,
562 GLenum genMode,
563 GLint components,
564 const GLfloat *coeffs)
565{
566 ASSERT(mEnablePathRendering);
567
568 for (const auto &input : mPathRenderingFragmentInputs)
569 {
570 if (input.name == inputName)
571 {
572 mFunctions->programPathFragmentInputGenNV(mProgramID, input.location, genMode,
573 components, coeffs);
574 ASSERT(mFunctions->getError() == GL_NO_ERROR);
575 return;
576 }
577 }
578
579}
580
Geoff Lang65a0be92015-10-02 09:57:30 -0400581void ProgramGL::preLink()
582{
583 // Reset the program state
584 mUniformRealLocationMap.clear();
585 mUniformBlockRealLocationMap.clear();
Sami Väisänen46eaa942016-06-29 10:26:37 +0300586 mPathRenderingFragmentInputs.clear();
Geoff Lang65a0be92015-10-02 09:57:30 -0400587}
588
589bool ProgramGL::checkLinkStatus(gl::InfoLog &infoLog)
590{
591 GLint linkStatus = GL_FALSE;
592 mFunctions->getProgramiv(mProgramID, GL_LINK_STATUS, &linkStatus);
593 if (linkStatus == GL_FALSE)
594 {
595 // Linking failed, put the error into the info log
596 GLint infoLogLength = 0;
597 mFunctions->getProgramiv(mProgramID, GL_INFO_LOG_LENGTH, &infoLogLength);
598
Geoff Lang65a0be92015-10-02 09:57:30 -0400599 // Info log length includes the null terminator, so 1 means that the info log is an empty
600 // string.
601 if (infoLogLength > 1)
602 {
603 std::vector<char> buf(infoLogLength);
604 mFunctions->getProgramInfoLog(mProgramID, infoLogLength, nullptr, &buf[0]);
605
606 mFunctions->deleteProgram(mProgramID);
607 mProgramID = 0;
608
609 infoLog << buf.data();
610
Yuly Novikovbcb3f9b2017-01-27 22:45:18 -0500611 WARN() << "Program link failed unexpectedly: " << buf.data();
Geoff Lang65a0be92015-10-02 09:57:30 -0400612 }
613 else
614 {
Yuly Novikovbcb3f9b2017-01-27 22:45:18 -0500615 WARN() << "Program link failed unexpectedly with no info log.";
Geoff Lang65a0be92015-10-02 09:57:30 -0400616 }
Geoff Lang65a0be92015-10-02 09:57:30 -0400617
618 // TODO, return GL_OUT_OF_MEMORY or just fail the link? This is an unexpected case
619 return false;
620 }
621
622 return true;
623}
624
625void ProgramGL::postLink()
626{
627 // Query the uniform information
628 ASSERT(mUniformRealLocationMap.empty());
Jamie Madill48ef11b2016-04-27 15:21:52 -0400629 const auto &uniformLocations = mState.getUniformLocations();
630 const auto &uniforms = mState.getUniforms();
Geoff Lang65a0be92015-10-02 09:57:30 -0400631 mUniformRealLocationMap.resize(uniformLocations.size(), GL_INVALID_INDEX);
632 for (size_t uniformLocation = 0; uniformLocation < uniformLocations.size(); uniformLocation++)
633 {
634 const auto &entry = uniformLocations[uniformLocation];
635 if (!entry.used)
636 {
637 continue;
638 }
639
640 // From the spec:
641 // "Locations for sequential array indices are not required to be sequential."
642 const gl::LinkedUniform &uniform = uniforms[entry.index];
643 std::stringstream fullNameStr;
644 fullNameStr << uniform.name;
645 if (uniform.isArray())
646 {
647 fullNameStr << "[" << entry.element << "]";
648 }
649 const std::string &fullName = fullNameStr.str();
650
651 GLint realLocation = mFunctions->getUniformLocation(mProgramID, fullName.c_str());
652 mUniformRealLocationMap[uniformLocation] = realLocation;
653 }
654
Sami Väisänen46eaa942016-06-29 10:26:37 +0300655 // Discover CHROMIUM_path_rendering fragment inputs if enabled.
656 if (!mEnablePathRendering)
657 return;
658
659 GLint numFragmentInputs = 0;
660 mFunctions->getProgramInterfaceiv(mProgramID, GL_FRAGMENT_INPUT_NV, GL_ACTIVE_RESOURCES,
661 &numFragmentInputs);
662 if (numFragmentInputs <= 0)
663 return;
664
665 GLint maxNameLength = 0;
666 mFunctions->getProgramInterfaceiv(mProgramID, GL_FRAGMENT_INPUT_NV, GL_MAX_NAME_LENGTH,
667 &maxNameLength);
668 ASSERT(maxNameLength);
669
670 for (GLint i = 0; i < numFragmentInputs; ++i)
671 {
672 std::string name;
673 name.resize(maxNameLength);
674
675 GLsizei nameLen = 0;
676 mFunctions->getProgramResourceName(mProgramID, GL_FRAGMENT_INPUT_NV, i, maxNameLength,
677 &nameLen, &name[0]);
678 name.resize(nameLen);
679
680 // Ignore built-ins
681 if (angle::BeginsWith(name, "gl_"))
682 continue;
683
684 const GLenum kQueryProperties[] = {GL_LOCATION, GL_ARRAY_SIZE};
685 GLint queryResults[ArraySize(kQueryProperties)];
686 GLsizei queryLength = 0;
687
Geoff Lang3f6a3982016-07-15 15:20:45 -0400688 mFunctions->getProgramResourceiv(
689 mProgramID, GL_FRAGMENT_INPUT_NV, i, static_cast<GLsizei>(ArraySize(kQueryProperties)),
690 kQueryProperties, static_cast<GLsizei>(ArraySize(queryResults)), &queryLength,
691 queryResults);
Sami Väisänen46eaa942016-06-29 10:26:37 +0300692
Olli Etuahoe3191712016-07-18 16:01:10 +0300693 ASSERT(queryLength == static_cast<GLsizei>(ArraySize(kQueryProperties)));
Sami Väisänen46eaa942016-06-29 10:26:37 +0300694
Geoff Lang3f6a3982016-07-15 15:20:45 -0400695 PathRenderingFragmentInput baseElementInput;
696 baseElementInput.name = name;
697 baseElementInput.location = queryResults[0];
698 mPathRenderingFragmentInputs.push_back(std::move(baseElementInput));
Sami Väisänen46eaa942016-06-29 10:26:37 +0300699
700 // If the input is an array it's denoted by [0] suffix on the variable
701 // name. We'll then create an entry per each array index where index > 0
702 if (angle::EndsWith(name, "[0]"))
703 {
704 // drop the suffix
705 name.resize(name.size() - 3);
706
707 const auto arraySize = queryResults[1];
708 const auto baseLocation = queryResults[0];
709
Geoff Lang3f6a3982016-07-15 15:20:45 -0400710 for (GLint arrayIndex = 1; arrayIndex < arraySize; ++arrayIndex)
Sami Väisänen46eaa942016-06-29 10:26:37 +0300711 {
Geoff Lang3f6a3982016-07-15 15:20:45 -0400712 PathRenderingFragmentInput arrayElementInput;
Corentin Wallez054f7ed2016-09-20 17:15:59 -0400713 arrayElementInput.name = name + "[" + ToString(arrayIndex) + "]";
Geoff Lang3f6a3982016-07-15 15:20:45 -0400714 arrayElementInput.location = baseLocation + arrayIndex;
715 mPathRenderingFragmentInputs.push_back(std::move(arrayElementInput));
Sami Väisänen46eaa942016-06-29 10:26:37 +0300716 }
717 }
718 }
Geoff Lang65a0be92015-10-02 09:57:30 -0400719}
720
Jamie Madill4a3c2342015-10-08 12:58:45 -0400721} // namespace rx