blob: 2ea74e2d722753035f5eb7b6bec98d3e3d24dfa4 [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();
Jamie Madill27a60632017-06-30 15:12:01 -040074 reapplyUBOBindingsIfNeeded(context);
Jamie Madilla7d12dc2016-12-13 15:08:19 -050075
Jamie Madillb0a838b2016-11-13 20:02:12 -050076 return true;
Geoff Langf9a6f082015-01-22 13:32:49 -050077}
78
Jamie Madill27a60632017-06-30 15:12:01 -040079void ProgramGL::save(const gl::Context *context, gl::BinaryOutputStream *stream)
Geoff Langf9a6f082015-01-22 13:32:49 -050080{
Geoff Lang65a0be92015-10-02 09:57:30 -040081 GLint binaryLength = 0;
82 mFunctions->getProgramiv(mProgramID, GL_PROGRAM_BINARY_LENGTH, &binaryLength);
83
84 std::vector<uint8_t> binary(binaryLength);
85 GLenum binaryFormat = GL_NONE;
86 mFunctions->getProgramBinary(mProgramID, binaryLength, &binaryLength, &binaryFormat,
87 &binary[0]);
88
89 stream->writeInt(binaryFormat);
90 stream->writeInt(binaryLength);
91 stream->writeBytes(&binary[0], binaryLength);
Jamie Madill27a60632017-06-30 15:12:01 -040092
93 reapplyUBOBindingsIfNeeded(context);
94}
95
96void ProgramGL::reapplyUBOBindingsIfNeeded(const gl::Context *context)
97{
98 // Re-apply UBO bindings to work around driver bugs.
99 const WorkaroundsGL &workaroundsGL = GetImplAs<ContextGL>(context)->getWorkaroundsGL();
100 if (workaroundsGL.reapplyUBOBindingsAfterUsingBinaryProgram)
101 {
102 const auto &blocks = mState.getUniformBlocks();
103 for (size_t blockIndex : mState.getActiveUniformBlockBindingsMask())
104 {
105 setUniformBlockBinding(static_cast<GLuint>(blockIndex), blocks[blockIndex].binding);
106 }
107 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500108}
109
Geoff Langc5629752015-12-07 16:29:04 -0500110void ProgramGL::setBinaryRetrievableHint(bool retrievable)
111{
Geoff Lang65a0be92015-10-02 09:57:30 -0400112 // glProgramParameteri isn't always available on ES backends.
113 if (mFunctions->programParameteri)
114 {
115 mFunctions->programParameteri(mProgramID, GL_PROGRAM_BINARY_RETRIEVABLE_HINT,
116 retrievable ? GL_TRUE : GL_FALSE);
117 }
Geoff Langc5629752015-12-07 16:29:04 -0500118}
119
Yunchao He61afff12017-03-14 15:34:03 +0800120void ProgramGL::setSeparable(bool separable)
121{
122 mFunctions->programParameteri(mProgramID, GL_PROGRAM_SEPARABLE, separable ? GL_TRUE : GL_FALSE);
123}
124
Jamie Madill9cf9e872017-06-05 12:59:25 -0400125gl::LinkResult ProgramGL::link(const gl::Context *context,
126 const gl::VaryingPacking &packing,
127 gl::InfoLog &infoLog)
Geoff Langf9a6f082015-01-22 13:32:49 -0500128{
Geoff Lang65a0be92015-10-02 09:57:30 -0400129 preLink();
Geoff Langb1f435e2015-02-20 10:01:01 -0500130
Martin Radev4c4c8e72016-08-04 12:25:34 +0300131 if (mState.getAttachedComputeShader())
Geoff Lang1a683462015-09-29 15:09:59 -0400132 {
Martin Radev4c4c8e72016-08-04 12:25:34 +0300133 const ShaderGL *computeShaderGL = GetImplAs<ShaderGL>(mState.getAttachedComputeShader());
Geoff Lang1a683462015-09-29 15:09:59 -0400134
Martin Radev4c4c8e72016-08-04 12:25:34 +0300135 mFunctions->attachShader(mProgramID, computeShaderGL->getShaderID());
136
137 // Link and verify
138 mFunctions->linkProgram(mProgramID);
139
140 // Detach the shaders
141 mFunctions->detachShader(mProgramID, computeShaderGL->getShaderID());
Geoff Lang1a683462015-09-29 15:09:59 -0400142 }
143 else
144 {
Martin Radev4c4c8e72016-08-04 12:25:34 +0300145 // Set the transform feedback state
146 std::vector<const GLchar *> transformFeedbackVaryings;
147 for (const auto &tfVarying : mState.getTransformFeedbackVaryingNames())
Geoff Lang1528e562015-08-24 15:10:58 -0400148 {
Martin Radev4c4c8e72016-08-04 12:25:34 +0300149 transformFeedbackVaryings.push_back(tfVarying.c_str());
Geoff Lang1528e562015-08-24 15:10:58 -0400150 }
151
Martin Radev4c4c8e72016-08-04 12:25:34 +0300152 if (transformFeedbackVaryings.empty())
153 {
154 if (mFunctions->transformFeedbackVaryings)
155 {
156 mFunctions->transformFeedbackVaryings(mProgramID, 0, nullptr,
157 mState.getTransformFeedbackBufferMode());
158 }
159 }
160 else
161 {
162 ASSERT(mFunctions->transformFeedbackVaryings);
163 mFunctions->transformFeedbackVaryings(
164 mProgramID, static_cast<GLsizei>(transformFeedbackVaryings.size()),
165 &transformFeedbackVaryings[0], mState.getTransformFeedbackBufferMode());
166 }
167
168 const ShaderGL *vertexShaderGL = GetImplAs<ShaderGL>(mState.getAttachedVertexShader());
169 const ShaderGL *fragmentShaderGL = GetImplAs<ShaderGL>(mState.getAttachedFragmentShader());
170
171 // Attach the shaders
172 mFunctions->attachShader(mProgramID, vertexShaderGL->getShaderID());
173 mFunctions->attachShader(mProgramID, fragmentShaderGL->getShaderID());
174
175 // Bind attribute locations to match the GL layer.
176 for (const sh::Attribute &attribute : mState.getAttributes())
177 {
Corentin Wallez6c1cbf52016-11-23 12:44:35 -0500178 if (!attribute.staticUse || attribute.isBuiltIn())
Martin Radev4c4c8e72016-08-04 12:25:34 +0300179 {
180 continue;
181 }
182
183 mFunctions->bindAttribLocation(mProgramID, attribute.location, attribute.name.c_str());
184 }
185
186 // Link and verify
187 mFunctions->linkProgram(mProgramID);
188
189 // Detach the shaders
190 mFunctions->detachShader(mProgramID, vertexShaderGL->getShaderID());
191 mFunctions->detachShader(mProgramID, fragmentShaderGL->getShaderID());
Geoff Lang1528e562015-08-24 15:10:58 -0400192 }
193
Geoff Lang0ca53782015-05-07 13:49:39 -0400194 // Verify the link
Geoff Lang65a0be92015-10-02 09:57:30 -0400195 if (!checkLinkStatus(infoLog))
Geoff Langb1f435e2015-02-20 10:01:01 -0500196 {
Jamie Madillb0a838b2016-11-13 20:02:12 -0500197 return false;
Geoff Langb1f435e2015-02-20 10:01:01 -0500198 }
199
Philippe Hamel40911192016-04-07 16:45:50 -0400200 if (mWorkarounds.alwaysCallUseProgramAfterLink)
201 {
202 mStateManager->forceUseProgram(mProgramID);
203 }
204
Geoff Lang65a0be92015-10-02 09:57:30 -0400205 postLink();
Geoff Langb1f435e2015-02-20 10:01:01 -0500206
Jamie Madillb0a838b2016-11-13 20:02:12 -0500207 return true;
Geoff Langf9a6f082015-01-22 13:32:49 -0500208}
209
Jamie Madill36cfd6a2015-08-18 10:46:20 -0400210GLboolean ProgramGL::validate(const gl::Caps & /*caps*/, gl::InfoLog * /*infoLog*/)
211{
212 // TODO(jmadill): implement validate
213 return true;
214}
215
Geoff Langf9a6f082015-01-22 13:32:49 -0500216void ProgramGL::setUniform1fv(GLint location, GLsizei count, const GLfloat *v)
217{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800218 if (mFunctions->programUniform1fv != nullptr)
219 {
220 mFunctions->programUniform1fv(mProgramID, uniLoc(location), count, v);
221 }
222 else
223 {
224 mStateManager->useProgram(mProgramID);
225 mFunctions->uniform1fv(uniLoc(location), count, v);
226 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500227}
228
229void ProgramGL::setUniform2fv(GLint location, GLsizei count, const GLfloat *v)
230{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800231 if (mFunctions->programUniform2fv != nullptr)
232 {
233 mFunctions->programUniform2fv(mProgramID, uniLoc(location), count, v);
234 }
235 else
236 {
237 mStateManager->useProgram(mProgramID);
238 mFunctions->uniform2fv(uniLoc(location), count, v);
239 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500240}
241
242void ProgramGL::setUniform3fv(GLint location, GLsizei count, const GLfloat *v)
243{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800244 if (mFunctions->programUniform3fv != nullptr)
245 {
246 mFunctions->programUniform3fv(mProgramID, uniLoc(location), count, v);
247 }
248 else
249 {
250 mStateManager->useProgram(mProgramID);
251 mFunctions->uniform3fv(uniLoc(location), count, v);
252 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500253}
254
255void ProgramGL::setUniform4fv(GLint location, GLsizei count, const GLfloat *v)
256{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800257 if (mFunctions->programUniform4fv != nullptr)
258 {
259 mFunctions->programUniform4fv(mProgramID, uniLoc(location), count, v);
260 }
261 else
262 {
263 mStateManager->useProgram(mProgramID);
264 mFunctions->uniform4fv(uniLoc(location), count, v);
265 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500266}
267
268void ProgramGL::setUniform1iv(GLint location, GLsizei count, const GLint *v)
269{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800270 if (mFunctions->programUniform1iv != nullptr)
271 {
272 mFunctions->programUniform1iv(mProgramID, uniLoc(location), count, v);
273 }
274 else
275 {
276 mStateManager->useProgram(mProgramID);
277 mFunctions->uniform1iv(uniLoc(location), count, v);
278 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500279}
280
281void ProgramGL::setUniform2iv(GLint location, GLsizei count, const GLint *v)
282{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800283 if (mFunctions->programUniform2iv != nullptr)
284 {
285 mFunctions->programUniform2iv(mProgramID, uniLoc(location), count, v);
286 }
287 else
288 {
289 mStateManager->useProgram(mProgramID);
290 mFunctions->uniform2iv(uniLoc(location), count, v);
291 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500292}
293
294void ProgramGL::setUniform3iv(GLint location, GLsizei count, const GLint *v)
295{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800296 if (mFunctions->programUniform3iv != nullptr)
297 {
298 mFunctions->programUniform3iv(mProgramID, uniLoc(location), count, v);
299 }
300 else
301 {
302 mStateManager->useProgram(mProgramID);
303 mFunctions->uniform3iv(uniLoc(location), count, v);
304 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500305}
306
307void ProgramGL::setUniform4iv(GLint location, GLsizei count, const GLint *v)
308{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800309 if (mFunctions->programUniform4iv != nullptr)
310 {
311 mFunctions->programUniform4iv(mProgramID, uniLoc(location), count, v);
312 }
313 else
314 {
315 mStateManager->useProgram(mProgramID);
316 mFunctions->uniform4iv(uniLoc(location), count, v);
317 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500318}
319
320void ProgramGL::setUniform1uiv(GLint location, GLsizei count, const GLuint *v)
321{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800322 if (mFunctions->programUniform1uiv != nullptr)
323 {
324 mFunctions->programUniform1uiv(mProgramID, uniLoc(location), count, v);
325 }
326 else
327 {
328 mStateManager->useProgram(mProgramID);
329 mFunctions->uniform1uiv(uniLoc(location), count, v);
330 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500331}
332
333void ProgramGL::setUniform2uiv(GLint location, GLsizei count, const GLuint *v)
334{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800335 if (mFunctions->programUniform2uiv != nullptr)
336 {
337 mFunctions->programUniform2uiv(mProgramID, uniLoc(location), count, v);
338 }
339 else
340 {
341 mStateManager->useProgram(mProgramID);
342 mFunctions->uniform2uiv(uniLoc(location), count, v);
343 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500344}
345
346void ProgramGL::setUniform3uiv(GLint location, GLsizei count, const GLuint *v)
347{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800348 if (mFunctions->programUniform3uiv != nullptr)
349 {
350 mFunctions->programUniform3uiv(mProgramID, uniLoc(location), count, v);
351 }
352 else
353 {
354 mStateManager->useProgram(mProgramID);
355 mFunctions->uniform3uiv(uniLoc(location), count, v);
356 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500357}
358
359void ProgramGL::setUniform4uiv(GLint location, GLsizei count, const GLuint *v)
360{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800361 if (mFunctions->programUniform4uiv != nullptr)
362 {
363 mFunctions->programUniform4uiv(mProgramID, uniLoc(location), count, v);
364 }
365 else
366 {
367 mStateManager->useProgram(mProgramID);
368 mFunctions->uniform4uiv(uniLoc(location), count, v);
369 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500370}
371
372void ProgramGL::setUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
373{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800374 if (mFunctions->programUniformMatrix2fv != nullptr)
375 {
376 mFunctions->programUniformMatrix2fv(mProgramID, uniLoc(location), count, transpose, value);
377 }
378 else
379 {
380 mStateManager->useProgram(mProgramID);
381 mFunctions->uniformMatrix2fv(uniLoc(location), count, transpose, value);
382 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500383}
384
385void ProgramGL::setUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
386{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800387 if (mFunctions->programUniformMatrix3fv != nullptr)
388 {
389 mFunctions->programUniformMatrix3fv(mProgramID, uniLoc(location), count, transpose, value);
390 }
391 else
392 {
393 mStateManager->useProgram(mProgramID);
394 mFunctions->uniformMatrix3fv(uniLoc(location), count, transpose, value);
395 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500396}
397
398void ProgramGL::setUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
399{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800400 if (mFunctions->programUniformMatrix4fv != nullptr)
401 {
402 mFunctions->programUniformMatrix4fv(mProgramID, uniLoc(location), count, transpose, value);
403 }
404 else
405 {
406 mStateManager->useProgram(mProgramID);
407 mFunctions->uniformMatrix4fv(uniLoc(location), count, transpose, value);
408 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500409}
410
411void ProgramGL::setUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
412{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800413 if (mFunctions->programUniformMatrix2x3fv != nullptr)
414 {
415 mFunctions->programUniformMatrix2x3fv(mProgramID, uniLoc(location), count, transpose,
416 value);
417 }
418 else
419 {
420 mStateManager->useProgram(mProgramID);
421 mFunctions->uniformMatrix2x3fv(uniLoc(location), count, transpose, value);
422 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500423}
424
425void ProgramGL::setUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
426{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800427 if (mFunctions->programUniformMatrix3x2fv != nullptr)
428 {
429 mFunctions->programUniformMatrix3x2fv(mProgramID, uniLoc(location), count, transpose,
430 value);
431 }
432 else
433 {
434 mStateManager->useProgram(mProgramID);
435 mFunctions->uniformMatrix3x2fv(uniLoc(location), count, transpose, value);
436 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500437}
438
439void ProgramGL::setUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
440{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800441 if (mFunctions->programUniformMatrix2x4fv != nullptr)
442 {
443 mFunctions->programUniformMatrix2x4fv(mProgramID, uniLoc(location), count, transpose,
444 value);
445 }
446 else
447 {
448 mStateManager->useProgram(mProgramID);
449 mFunctions->uniformMatrix2x4fv(uniLoc(location), count, transpose, value);
450 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500451}
452
453void ProgramGL::setUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
454{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800455 if (mFunctions->programUniformMatrix4x2fv != nullptr)
456 {
457 mFunctions->programUniformMatrix4x2fv(mProgramID, uniLoc(location), count, transpose,
458 value);
459 }
460 else
461 {
462 mStateManager->useProgram(mProgramID);
463 mFunctions->uniformMatrix4x2fv(uniLoc(location), count, transpose, value);
464 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500465}
466
467void ProgramGL::setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
468{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800469 if (mFunctions->programUniformMatrix3x4fv != nullptr)
470 {
471 mFunctions->programUniformMatrix3x4fv(mProgramID, uniLoc(location), count, transpose,
472 value);
473 }
474 else
475 {
476 mStateManager->useProgram(mProgramID);
477 mFunctions->uniformMatrix3x4fv(uniLoc(location), count, transpose, value);
478 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500479}
480
481void ProgramGL::setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
482{
Jiajia Qinee9f08c2016-11-16 10:06:10 +0800483 if (mFunctions->programUniformMatrix4x3fv != nullptr)
484 {
485 mFunctions->programUniformMatrix4x3fv(mProgramID, uniLoc(location), count, transpose,
486 value);
487 }
488 else
489 {
490 mStateManager->useProgram(mProgramID);
491 mFunctions->uniformMatrix4x3fv(uniLoc(location), count, transpose, value);
492 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500493}
494
Geoff Lang5d124a62015-09-15 13:03:27 -0400495void ProgramGL::setUniformBlockBinding(GLuint uniformBlockIndex, GLuint uniformBlockBinding)
496{
Jamie Madill4a3c2342015-10-08 12:58:45 -0400497 // Lazy init
498 if (mUniformBlockRealLocationMap.empty())
499 {
Jamie Madill48ef11b2016-04-27 15:21:52 -0400500 mUniformBlockRealLocationMap.reserve(mState.getUniformBlocks().size());
501 for (const gl::UniformBlock &uniformBlock : mState.getUniformBlocks())
Jamie Madill4a3c2342015-10-08 12:58:45 -0400502 {
503 const std::string &nameWithIndex = uniformBlock.nameWithArrayIndex();
504 GLuint blockIndex = mFunctions->getUniformBlockIndex(mProgramID, nameWithIndex.c_str());
505 mUniformBlockRealLocationMap.push_back(blockIndex);
506 }
507 }
508
509 GLuint realBlockIndex = mUniformBlockRealLocationMap[uniformBlockIndex];
510 if (realBlockIndex != GL_INVALID_INDEX)
511 {
512 mFunctions->uniformBlockBinding(mProgramID, realBlockIndex, uniformBlockBinding);
513 }
Geoff Lang5d124a62015-09-15 13:03:27 -0400514}
515
Geoff Langb1f435e2015-02-20 10:01:01 -0500516GLuint ProgramGL::getProgramID() const
517{
518 return mProgramID;
519}
520
Jamie Madill4a3c2342015-10-08 12:58:45 -0400521bool ProgramGL::getUniformBlockSize(const std::string &blockName, size_t *sizeOut) const
Jamie Madill62d31cb2015-09-11 13:25:51 -0400522{
Jamie Madill4a3c2342015-10-08 12:58:45 -0400523 ASSERT(mProgramID != 0u);
Geoff Lang5d124a62015-09-15 13:03:27 -0400524
Jamie Madill4a3c2342015-10-08 12:58:45 -0400525 GLuint blockIndex = mFunctions->getUniformBlockIndex(mProgramID, blockName.c_str());
526 if (blockIndex == GL_INVALID_INDEX)
Geoff Lang5d124a62015-09-15 13:03:27 -0400527 {
Jamie Madill4a3c2342015-10-08 12:58:45 -0400528 *sizeOut = 0;
529 return false;
Geoff Lang5d124a62015-09-15 13:03:27 -0400530 }
531
Jamie Madill4a3c2342015-10-08 12:58:45 -0400532 GLint dataSize = 0;
533 mFunctions->getActiveUniformBlockiv(mProgramID, blockIndex, GL_UNIFORM_BLOCK_DATA_SIZE,
534 &dataSize);
535 *sizeOut = static_cast<size_t>(dataSize);
536 return true;
537}
538
539bool ProgramGL::getUniformBlockMemberInfo(const std::string &memberUniformName,
540 sh::BlockMemberInfo *memberInfoOut) const
541{
542 GLuint uniformIndex;
543 const GLchar *memberNameGLStr = memberUniformName.c_str();
544 mFunctions->getUniformIndices(mProgramID, 1, &memberNameGLStr, &uniformIndex);
545
546 if (uniformIndex == GL_INVALID_INDEX)
Geoff Lang5d124a62015-09-15 13:03:27 -0400547 {
Jamie Madill4a3c2342015-10-08 12:58:45 -0400548 *memberInfoOut = sh::BlockMemberInfo::getDefaultBlockInfo();
549 return false;
Geoff Lang5d124a62015-09-15 13:03:27 -0400550 }
Jamie Madill4a3c2342015-10-08 12:58:45 -0400551
552 mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_OFFSET,
553 &memberInfoOut->offset);
554 mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_ARRAY_STRIDE,
555 &memberInfoOut->arrayStride);
556 mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_MATRIX_STRIDE,
557 &memberInfoOut->matrixStride);
558
559 // TODO(jmadill): possibly determine this at the gl::Program level.
560 GLint isRowMajorMatrix = 0;
561 mFunctions->getActiveUniformsiv(mProgramID, 1, &uniformIndex, GL_UNIFORM_IS_ROW_MAJOR,
562 &isRowMajorMatrix);
563 memberInfoOut->isRowMajorMatrix = isRowMajorMatrix != GL_FALSE;
564 return true;
Jamie Madill62d31cb2015-09-11 13:25:51 -0400565}
Jamie Madill4a3c2342015-10-08 12:58:45 -0400566
Sami Väisänen46eaa942016-06-29 10:26:37 +0300567void ProgramGL::setPathFragmentInputGen(const std::string &inputName,
568 GLenum genMode,
569 GLint components,
570 const GLfloat *coeffs)
571{
572 ASSERT(mEnablePathRendering);
573
574 for (const auto &input : mPathRenderingFragmentInputs)
575 {
576 if (input.name == inputName)
577 {
578 mFunctions->programPathFragmentInputGenNV(mProgramID, input.location, genMode,
579 components, coeffs);
580 ASSERT(mFunctions->getError() == GL_NO_ERROR);
581 return;
582 }
583 }
584
585}
586
Geoff Lang65a0be92015-10-02 09:57:30 -0400587void ProgramGL::preLink()
588{
589 // Reset the program state
590 mUniformRealLocationMap.clear();
591 mUniformBlockRealLocationMap.clear();
Sami Väisänen46eaa942016-06-29 10:26:37 +0300592 mPathRenderingFragmentInputs.clear();
Geoff Lang65a0be92015-10-02 09:57:30 -0400593}
594
595bool ProgramGL::checkLinkStatus(gl::InfoLog &infoLog)
596{
597 GLint linkStatus = GL_FALSE;
598 mFunctions->getProgramiv(mProgramID, GL_LINK_STATUS, &linkStatus);
599 if (linkStatus == GL_FALSE)
600 {
601 // Linking failed, put the error into the info log
602 GLint infoLogLength = 0;
603 mFunctions->getProgramiv(mProgramID, GL_INFO_LOG_LENGTH, &infoLogLength);
604
Geoff Lang65a0be92015-10-02 09:57:30 -0400605 // Info log length includes the null terminator, so 1 means that the info log is an empty
606 // string.
607 if (infoLogLength > 1)
608 {
609 std::vector<char> buf(infoLogLength);
610 mFunctions->getProgramInfoLog(mProgramID, infoLogLength, nullptr, &buf[0]);
611
612 mFunctions->deleteProgram(mProgramID);
613 mProgramID = 0;
614
615 infoLog << buf.data();
616
Yuly Novikovbcb3f9b2017-01-27 22:45:18 -0500617 WARN() << "Program link failed unexpectedly: " << buf.data();
Geoff Lang65a0be92015-10-02 09:57:30 -0400618 }
619 else
620 {
Yuly Novikovbcb3f9b2017-01-27 22:45:18 -0500621 WARN() << "Program link failed unexpectedly with no info log.";
Geoff Lang65a0be92015-10-02 09:57:30 -0400622 }
Geoff Lang65a0be92015-10-02 09:57:30 -0400623
624 // TODO, return GL_OUT_OF_MEMORY or just fail the link? This is an unexpected case
625 return false;
626 }
627
628 return true;
629}
630
631void ProgramGL::postLink()
632{
633 // Query the uniform information
634 ASSERT(mUniformRealLocationMap.empty());
Jamie Madill48ef11b2016-04-27 15:21:52 -0400635 const auto &uniformLocations = mState.getUniformLocations();
636 const auto &uniforms = mState.getUniforms();
Geoff Lang65a0be92015-10-02 09:57:30 -0400637 mUniformRealLocationMap.resize(uniformLocations.size(), GL_INVALID_INDEX);
638 for (size_t uniformLocation = 0; uniformLocation < uniformLocations.size(); uniformLocation++)
639 {
640 const auto &entry = uniformLocations[uniformLocation];
641 if (!entry.used)
642 {
643 continue;
644 }
645
646 // From the spec:
647 // "Locations for sequential array indices are not required to be sequential."
648 const gl::LinkedUniform &uniform = uniforms[entry.index];
649 std::stringstream fullNameStr;
650 fullNameStr << uniform.name;
651 if (uniform.isArray())
652 {
653 fullNameStr << "[" << entry.element << "]";
654 }
655 const std::string &fullName = fullNameStr.str();
656
657 GLint realLocation = mFunctions->getUniformLocation(mProgramID, fullName.c_str());
658 mUniformRealLocationMap[uniformLocation] = realLocation;
659 }
660
Sami Väisänen46eaa942016-06-29 10:26:37 +0300661 // Discover CHROMIUM_path_rendering fragment inputs if enabled.
662 if (!mEnablePathRendering)
663 return;
664
665 GLint numFragmentInputs = 0;
666 mFunctions->getProgramInterfaceiv(mProgramID, GL_FRAGMENT_INPUT_NV, GL_ACTIVE_RESOURCES,
667 &numFragmentInputs);
668 if (numFragmentInputs <= 0)
669 return;
670
671 GLint maxNameLength = 0;
672 mFunctions->getProgramInterfaceiv(mProgramID, GL_FRAGMENT_INPUT_NV, GL_MAX_NAME_LENGTH,
673 &maxNameLength);
674 ASSERT(maxNameLength);
675
676 for (GLint i = 0; i < numFragmentInputs; ++i)
677 {
678 std::string name;
679 name.resize(maxNameLength);
680
681 GLsizei nameLen = 0;
682 mFunctions->getProgramResourceName(mProgramID, GL_FRAGMENT_INPUT_NV, i, maxNameLength,
683 &nameLen, &name[0]);
684 name.resize(nameLen);
685
686 // Ignore built-ins
687 if (angle::BeginsWith(name, "gl_"))
688 continue;
689
690 const GLenum kQueryProperties[] = {GL_LOCATION, GL_ARRAY_SIZE};
691 GLint queryResults[ArraySize(kQueryProperties)];
692 GLsizei queryLength = 0;
693
Geoff Lang3f6a3982016-07-15 15:20:45 -0400694 mFunctions->getProgramResourceiv(
695 mProgramID, GL_FRAGMENT_INPUT_NV, i, static_cast<GLsizei>(ArraySize(kQueryProperties)),
696 kQueryProperties, static_cast<GLsizei>(ArraySize(queryResults)), &queryLength,
697 queryResults);
Sami Väisänen46eaa942016-06-29 10:26:37 +0300698
Olli Etuahoe3191712016-07-18 16:01:10 +0300699 ASSERT(queryLength == static_cast<GLsizei>(ArraySize(kQueryProperties)));
Sami Väisänen46eaa942016-06-29 10:26:37 +0300700
Geoff Lang3f6a3982016-07-15 15:20:45 -0400701 PathRenderingFragmentInput baseElementInput;
702 baseElementInput.name = name;
703 baseElementInput.location = queryResults[0];
704 mPathRenderingFragmentInputs.push_back(std::move(baseElementInput));
Sami Väisänen46eaa942016-06-29 10:26:37 +0300705
706 // If the input is an array it's denoted by [0] suffix on the variable
707 // name. We'll then create an entry per each array index where index > 0
708 if (angle::EndsWith(name, "[0]"))
709 {
710 // drop the suffix
711 name.resize(name.size() - 3);
712
713 const auto arraySize = queryResults[1];
714 const auto baseLocation = queryResults[0];
715
Geoff Lang3f6a3982016-07-15 15:20:45 -0400716 for (GLint arrayIndex = 1; arrayIndex < arraySize; ++arrayIndex)
Sami Väisänen46eaa942016-06-29 10:26:37 +0300717 {
Geoff Lang3f6a3982016-07-15 15:20:45 -0400718 PathRenderingFragmentInput arrayElementInput;
Corentin Wallez054f7ed2016-09-20 17:15:59 -0400719 arrayElementInput.name = name + "[" + ToString(arrayIndex) + "]";
Geoff Lang3f6a3982016-07-15 15:20:45 -0400720 arrayElementInput.location = baseLocation + arrayIndex;
721 mPathRenderingFragmentInputs.push_back(std::move(arrayElementInput));
Sami Väisänen46eaa942016-06-29 10:26:37 +0300722 }
723 }
724 }
Geoff Lang65a0be92015-10-02 09:57:30 -0400725}
726
Jamie Madill4a3c2342015-10-08 12:58:45 -0400727} // namespace rx