blob: c6964f837d6a97ece7a914dee5b83ce1c1d39421 [file] [log] [blame]
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001//
Geoff Lang48dcae72014-02-05 16:28:24 -05002// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00003// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// Program.cpp: Implements the gl::Program class. Implements GL program objects
8// and related functionality. [OpenGL ES 2.0.24] section 2.10.3 page 28.
9
shannon.woods@transgaming.comd2811d62013-02-28 23:11:19 +000010#include "libGLESv2/Program.h"
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +000011#include "libGLESv2/ProgramBinary.h"
shannon.woods@transgaming.com486d9e92013-02-28 23:15:41 +000012#include "libGLESv2/ResourceManager.h"
daniel@transgaming.com87891f72011-06-01 15:28:35 +000013
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000014namespace gl
15{
apatrick@chromium.org253b8d22012-06-22 19:27:21 +000016const char * const g_fakepath = "C:\\fakepath";
17
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +000018AttributeBindings::AttributeBindings()
19{
20}
21
22AttributeBindings::~AttributeBindings()
23{
apatrick@chromium.org9a30b092012-06-06 20:21:55 +000024}
25
apatrick@chromium.org253b8d22012-06-22 19:27:21 +000026InfoLog::InfoLog() : mInfoLog(NULL)
27{
28}
29
30InfoLog::~InfoLog()
31{
32 delete[] mInfoLog;
33}
34
35
36int InfoLog::getLength() const
37{
38 if (!mInfoLog)
39 {
40 return 0;
41 }
42 else
43 {
44 return strlen(mInfoLog) + 1;
45 }
46}
47
48void InfoLog::getLog(GLsizei bufSize, GLsizei *length, char *infoLog)
49{
50 int index = 0;
51
52 if (bufSize > 0)
53 {
54 if (mInfoLog)
55 {
56 index = std::min(bufSize - 1, (int)strlen(mInfoLog));
57 memcpy(infoLog, mInfoLog, index);
58 }
59
60 infoLog[index] = '\0';
61 }
62
63 if (length)
64 {
65 *length = index;
66 }
67}
68
69// append a santized message to the program info log.
70// The D3D compiler includes a fake file path in some of the warning or error
71// messages, so lets remove all occurrences of this fake file path from the log.
72void InfoLog::appendSanitized(const char *message)
73{
74 std::string msg(message);
75
76 size_t found;
77 do
78 {
79 found = msg.find(g_fakepath);
80 if (found != std::string::npos)
81 {
82 msg.erase(found, strlen(g_fakepath));
83 }
84 }
85 while (found != std::string::npos);
86
shannon.woods@transgaming.come16e6512013-02-28 23:19:02 +000087 append("%s", msg.c_str());
apatrick@chromium.org253b8d22012-06-22 19:27:21 +000088}
89
90void InfoLog::append(const char *format, ...)
91{
92 if (!format)
93 {
94 return;
95 }
96
apatrick@chromium.org253b8d22012-06-22 19:27:21 +000097 va_list vararg;
98 va_start(vararg, format);
Jamie Madilld4505052014-02-24 15:26:49 -050099 size_t infoLength = vsnprintf(NULL, 0, format, vararg);
apatrick@chromium.org253b8d22012-06-22 19:27:21 +0000100 va_end(vararg);
101
Jamie Madilld4505052014-02-24 15:26:49 -0500102 char *logPointer = NULL;
apatrick@chromium.org253b8d22012-06-22 19:27:21 +0000103
104 if (!mInfoLog)
105 {
shannon.woods@transgaming.come16e6512013-02-28 23:19:02 +0000106 mInfoLog = new char[infoLength + 2];
Jamie Madilld4505052014-02-24 15:26:49 -0500107 logPointer = mInfoLog;
apatrick@chromium.org253b8d22012-06-22 19:27:21 +0000108 }
109 else
110 {
Jamie Madilld4505052014-02-24 15:26:49 -0500111 size_t currentlogLength = strlen(mInfoLog);
112 char *newLog = new char[currentlogLength + infoLength + 2];
apatrick@chromium.org253b8d22012-06-22 19:27:21 +0000113 strcpy(newLog, mInfoLog);
apatrick@chromium.org253b8d22012-06-22 19:27:21 +0000114
115 delete[] mInfoLog;
116 mInfoLog = newLog;
Jamie Madilld4505052014-02-24 15:26:49 -0500117
118 logPointer = mInfoLog + currentlogLength;
apatrick@chromium.org253b8d22012-06-22 19:27:21 +0000119 }
Jamie Madilld4505052014-02-24 15:26:49 -0500120
121 va_start(vararg, format);
122 vsnprintf(logPointer, infoLength, format, vararg);
123 va_end(vararg);
124
125 logPointer[infoLength] = 0;
126 strcpy(logPointer + infoLength, "\n");
apatrick@chromium.org253b8d22012-06-22 19:27:21 +0000127}
128
129void InfoLog::reset()
130{
131 if (mInfoLog)
132 {
133 delete [] mInfoLog;
134 mInfoLog = NULL;
135 }
136}
137
daniel@transgaming.com70062c92012-11-28 19:32:30 +0000138Program::Program(rx::Renderer *renderer, ResourceManager *manager, GLuint handle) : mResourceManager(manager), mHandle(handle)
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000139{
140 mFragmentShader = NULL;
141 mVertexShader = NULL;
daniel@transgaming.com989c1c82012-07-24 18:40:38 +0000142 mProgramBinary.set(NULL);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000143 mDeleteStatus = false;
daniel@transgaming.com716056c2012-07-24 18:38:59 +0000144 mLinked = false;
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000145 mRefCount = 0;
daniel@transgaming.com70062c92012-11-28 19:32:30 +0000146 mRenderer = renderer;
shannonwoods@chromium.org70eb1ea2013-05-30 00:07:20 +0000147
148 resetUniformBlockBindings();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000149}
150
151Program::~Program()
152{
153 unlink(true);
daniel@transgaming.com71cd8682010-04-29 03:35:25 +0000154
155 if (mVertexShader != NULL)
156 {
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000157 mVertexShader->release();
daniel@transgaming.com71cd8682010-04-29 03:35:25 +0000158 }
159
160 if (mFragmentShader != NULL)
161 {
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000162 mFragmentShader->release();
daniel@transgaming.com71cd8682010-04-29 03:35:25 +0000163 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000164}
165
166bool Program::attachShader(Shader *shader)
167{
168 if (shader->getType() == GL_VERTEX_SHADER)
169 {
170 if (mVertexShader)
171 {
172 return false;
173 }
174
Brandon Jones71620962014-08-20 14:04:59 -0700175 mVertexShader = shader;
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000176 mVertexShader->addRef();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000177 }
178 else if (shader->getType() == GL_FRAGMENT_SHADER)
179 {
180 if (mFragmentShader)
181 {
182 return false;
183 }
184
Brandon Jones71620962014-08-20 14:04:59 -0700185 mFragmentShader = shader;
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000186 mFragmentShader->addRef();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000187 }
188 else UNREACHABLE();
189
190 return true;
191}
192
193bool Program::detachShader(Shader *shader)
194{
195 if (shader->getType() == GL_VERTEX_SHADER)
196 {
197 if (mVertexShader != shader)
198 {
199 return false;
200 }
201
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000202 mVertexShader->release();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000203 mVertexShader = NULL;
204 }
205 else if (shader->getType() == GL_FRAGMENT_SHADER)
206 {
207 if (mFragmentShader != shader)
208 {
209 return false;
210 }
211
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000212 mFragmentShader->release();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000213 mFragmentShader = NULL;
214 }
215 else UNREACHABLE();
216
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000217 return true;
218}
219
daniel@transgaming.comcba50572010-03-28 19:36:09 +0000220int Program::getAttachedShadersCount() const
221{
222 return (mVertexShader ? 1 : 0) + (mFragmentShader ? 1 : 0);
223}
224
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000225void AttributeBindings::bindAttributeLocation(GLuint index, const char *name)
226{
227 if (index < MAX_VERTEX_ATTRIBS)
228 {
229 for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
230 {
231 mAttributeBinding[i].erase(name);
232 }
233
234 mAttributeBinding[index].insert(name);
235 }
apatrick@chromium.org9a30b092012-06-06 20:21:55 +0000236}
237
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000238void Program::bindAttributeLocation(GLuint index, const char *name)
239{
apatrick@chromium.org9a30b092012-06-06 20:21:55 +0000240 mAttributeBindings.bindAttributeLocation(index, name);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000241}
242
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000243// Links the HLSL code of the vertex and pixel shader by matching up their varyings,
244// compiling them into binaries, determining the attribute mappings, and collecting
245// a list of uniforms
daniel@transgaming.com4c962bf2012-07-24 18:37:02 +0000246bool Program::link()
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000247{
248 unlink(false);
249
apatrick@chromium.org253b8d22012-06-22 19:27:21 +0000250 mInfoLog.reset();
shannonwoods@chromium.org70eb1ea2013-05-30 00:07:20 +0000251 resetUniformBlockBindings();
apatrick@chromium.org253b8d22012-06-22 19:27:21 +0000252
daniel@transgaming.com70062c92012-11-28 19:32:30 +0000253 mProgramBinary.set(new ProgramBinary(mRenderer));
Geoff Lang48dcae72014-02-05 16:28:24 -0500254 mLinked = mProgramBinary->link(mInfoLog, mAttributeBindings, mFragmentShader, mVertexShader,
255 mTransformFeedbackVaryings, mTransformFeedbackBufferMode);
daniel@transgaming.com4c962bf2012-07-24 18:37:02 +0000256
daniel@transgaming.com716056c2012-07-24 18:38:59 +0000257 return mLinked;
apatrick@chromium.org9a30b092012-06-06 20:21:55 +0000258}
259
apatrick@chromium.org9a30b092012-06-06 20:21:55 +0000260int AttributeBindings::getAttributeBinding(const std::string &name) const
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +0000261{
262 for (int location = 0; location < MAX_VERTEX_ATTRIBS; location++)
263 {
264 if (mAttributeBinding[location].find(name) != mAttributeBinding[location].end())
265 {
266 return location;
267 }
268 }
269
270 return -1;
271}
272
daniel@transgaming.comaa5e59b2011-10-04 18:43:12 +0000273// Returns the program object to an unlinked state, before re-linking, or at destruction
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000274void Program::unlink(bool destroy)
275{
276 if (destroy) // Object being destructed
277 {
278 if (mFragmentShader)
279 {
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000280 mFragmentShader->release();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000281 mFragmentShader = NULL;
282 }
283
284 if (mVertexShader)
285 {
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000286 mVertexShader->release();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000287 mVertexShader = NULL;
288 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000289 }
290
daniel@transgaming.com989c1c82012-07-24 18:40:38 +0000291 mProgramBinary.set(NULL);
daniel@transgaming.com716056c2012-07-24 18:38:59 +0000292 mLinked = false;
293}
294
295bool Program::isLinked()
296{
297 return mLinked;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000298}
299
Geoff Lang48dcae72014-02-05 16:28:24 -0500300ProgramBinary* Program::getProgramBinary() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000301{
daniel@transgaming.com989c1c82012-07-24 18:40:38 +0000302 return mProgramBinary.get();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000303}
304
Geoff Lang900013c2014-07-07 11:32:19 -0400305bool Program::setProgramBinary(GLenum binaryFormat, const void *binary, GLsizei length)
apatrick@chromium.org3ce8dbc2012-06-08 17:52:30 +0000306{
307 unlink(false);
apatrick@chromium.org90080e32012-07-09 22:15:33 +0000308
309 mInfoLog.reset();
310
daniel@transgaming.com70062c92012-11-28 19:32:30 +0000311 mProgramBinary.set(new ProgramBinary(mRenderer));
Geoff Lang900013c2014-07-07 11:32:19 -0400312 mLinked = mProgramBinary->load(mInfoLog, binaryFormat, binary, length);
daniel@transgaming.com716056c2012-07-24 18:38:59 +0000313 if (!mLinked)
apatrick@chromium.org90080e32012-07-09 22:15:33 +0000314 {
daniel@transgaming.com989c1c82012-07-24 18:40:38 +0000315 mProgramBinary.set(NULL);
apatrick@chromium.org90080e32012-07-09 22:15:33 +0000316 }
daniel@transgaming.com4c962bf2012-07-24 18:37:02 +0000317
daniel@transgaming.com716056c2012-07-24 18:38:59 +0000318 return mLinked;
apatrick@chromium.org3ce8dbc2012-06-08 17:52:30 +0000319}
320
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000321void Program::release()
322{
323 mRefCount--;
324
325 if (mRefCount == 0 && mDeleteStatus)
326 {
327 mResourceManager->deleteProgram(mHandle);
328 }
329}
330
331void Program::addRef()
332{
333 mRefCount++;
334}
335
336unsigned int Program::getRefCount() const
337{
338 return mRefCount;
339}
340
apatrick@chromium.org90080e32012-07-09 22:15:33 +0000341GLint Program::getProgramBinaryLength() const
342{
daniel@transgaming.com989c1c82012-07-24 18:40:38 +0000343 ProgramBinary *programBinary = mProgramBinary.get();
344 if (programBinary)
apatrick@chromium.org90080e32012-07-09 22:15:33 +0000345 {
daniel@transgaming.com989c1c82012-07-24 18:40:38 +0000346 return programBinary->getLength();
apatrick@chromium.org90080e32012-07-09 22:15:33 +0000347 }
348 else
349 {
350 return 0;
351 }
352}
353
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000354int Program::getInfoLogLength() const
355{
apatrick@chromium.org253b8d22012-06-22 19:27:21 +0000356 return mInfoLog.getLength();
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000357}
358
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000359void Program::getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog)
360{
apatrick@chromium.org253b8d22012-06-22 19:27:21 +0000361 return mInfoLog.getLog(bufSize, length, infoLog);
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000362}
363
daniel@transgaming.com6c785212010-03-30 03:36:17 +0000364void Program::getAttachedShaders(GLsizei maxCount, GLsizei *count, GLuint *shaders)
365{
366 int total = 0;
367
368 if (mVertexShader)
369 {
370 if (total < maxCount)
371 {
372 shaders[total] = mVertexShader->getHandle();
373 }
374
375 total++;
376 }
377
378 if (mFragmentShader)
379 {
380 if (total < maxCount)
381 {
382 shaders[total] = mFragmentShader->getHandle();
383 }
384
385 total++;
386 }
387
388 if (count)
389 {
390 *count = total;
391 }
392}
393
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000394void Program::getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name)
395{
daniel@transgaming.com989c1c82012-07-24 18:40:38 +0000396 ProgramBinary *programBinary = getProgramBinary();
397 if (programBinary)
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000398 {
daniel@transgaming.com989c1c82012-07-24 18:40:38 +0000399 programBinary->getActiveAttribute(index, bufsize, length, size, type, name);
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000400 }
401 else
402 {
403 if (bufsize > 0)
404 {
405 name[0] = '\0';
406 }
407
408 if (length)
409 {
410 *length = 0;
411 }
412
413 *type = GL_NONE;
414 *size = 1;
415 }
416}
417
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000418GLint Program::getActiveAttributeCount()
419{
daniel@transgaming.com989c1c82012-07-24 18:40:38 +0000420 ProgramBinary *programBinary = getProgramBinary();
421 if (programBinary)
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000422 {
daniel@transgaming.com989c1c82012-07-24 18:40:38 +0000423 return programBinary->getActiveAttributeCount();
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000424 }
425 else
426 {
427 return 0;
428 }
429}
430
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000431GLint Program::getActiveAttributeMaxLength()
432{
daniel@transgaming.com989c1c82012-07-24 18:40:38 +0000433 ProgramBinary *programBinary = getProgramBinary();
434 if (programBinary)
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000435 {
daniel@transgaming.com989c1c82012-07-24 18:40:38 +0000436 return programBinary->getActiveAttributeMaxLength();
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000437 }
438 else
439 {
440 return 0;
441 }
442}
443
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000444void Program::getActiveUniform(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name)
445{
daniel@transgaming.com989c1c82012-07-24 18:40:38 +0000446 ProgramBinary *programBinary = getProgramBinary();
447 if (programBinary)
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000448 {
daniel@transgaming.com989c1c82012-07-24 18:40:38 +0000449 return programBinary->getActiveUniform(index, bufsize, length, size, type, name);
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000450 }
451 else
452 {
453 if (bufsize > 0)
454 {
455 name[0] = '\0';
456 }
457
458 if (length)
459 {
460 *length = 0;
461 }
462
463 *size = 0;
464 *type = GL_NONE;
465 }
466}
467
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000468GLint Program::getActiveUniformCount()
469{
daniel@transgaming.com989c1c82012-07-24 18:40:38 +0000470 ProgramBinary *programBinary = getProgramBinary();
471 if (programBinary)
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000472 {
daniel@transgaming.com989c1c82012-07-24 18:40:38 +0000473 return programBinary->getActiveUniformCount();
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000474 }
475 else
476 {
477 return 0;
478 }
479}
480
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000481GLint Program::getActiveUniformMaxLength()
482{
daniel@transgaming.com989c1c82012-07-24 18:40:38 +0000483 ProgramBinary *programBinary = getProgramBinary();
484 if (programBinary)
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000485 {
daniel@transgaming.com989c1c82012-07-24 18:40:38 +0000486 return programBinary->getActiveUniformMaxLength();
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000487 }
488 else
489 {
490 return 0;
491 }
492}
493
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000494void Program::flagForDeletion()
495{
496 mDeleteStatus = true;
497}
498
499bool Program::isFlaggedForDeletion() const
500{
501 return mDeleteStatus;
502}
daniel@transgaming.com86a7a132010-04-29 03:32:32 +0000503
apatrick@chromium.org253b8d22012-06-22 19:27:21 +0000504void Program::validate()
505{
506 mInfoLog.reset();
507
daniel@transgaming.com989c1c82012-07-24 18:40:38 +0000508 ProgramBinary *programBinary = getProgramBinary();
509 if (isLinked() && programBinary)
apatrick@chromium.org253b8d22012-06-22 19:27:21 +0000510 {
daniel@transgaming.com989c1c82012-07-24 18:40:38 +0000511 programBinary->validate(mInfoLog);
apatrick@chromium.org253b8d22012-06-22 19:27:21 +0000512 }
513 else
514 {
515 mInfoLog.append("Program has not been successfully linked.");
516 }
517}
518
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000519bool Program::isValidated() const
520{
daniel@transgaming.com989c1c82012-07-24 18:40:38 +0000521 ProgramBinary *programBinary = mProgramBinary.get();
522 if (programBinary)
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000523 {
daniel@transgaming.com989c1c82012-07-24 18:40:38 +0000524 return programBinary->isValidated();
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000525 }
526 else
527 {
528 return false;
529 }
530}
531
shannonwoods@chromium.orge684b582013-05-30 00:07:42 +0000532GLint Program::getActiveUniformBlockCount()
533{
534 ProgramBinary *programBinary = getProgramBinary();
535 if (programBinary)
536 {
537 return static_cast<GLint>(programBinary->getActiveUniformBlockCount());
538 }
539 else
540 {
541 return 0;
542 }
543}
544
545GLint Program::getActiveUniformBlockMaxLength()
546{
547 ProgramBinary *programBinary = getProgramBinary();
548 if (programBinary)
549 {
550 return static_cast<GLint>(programBinary->getActiveUniformBlockMaxLength());
551 }
552 else
553 {
554 return 0;
555 }
556}
557
shannonwoods@chromium.org70eb1ea2013-05-30 00:07:20 +0000558void Program::bindUniformBlock(GLuint uniformBlockIndex, GLuint uniformBlockBinding)
559{
560 mUniformBlockBindings[uniformBlockIndex] = uniformBlockBinding;
561}
562
563GLuint Program::getUniformBlockBinding(GLuint uniformBlockIndex) const
564{
565 return mUniformBlockBindings[uniformBlockIndex];
566}
567
568void Program::resetUniformBlockBindings()
569{
570 for (unsigned int blockId = 0; blockId < IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS; blockId++)
571 {
572 mUniformBlockBindings[blockId] = 0;
573 }
574}
575
Geoff Lang48dcae72014-02-05 16:28:24 -0500576void Program::setTransformFeedbackVaryings(GLsizei count, const GLchar *const *varyings, GLenum bufferMode)
577{
578 mTransformFeedbackVaryings.resize(count);
579 for (GLsizei i = 0; i < count; i++)
580 {
581 mTransformFeedbackVaryings[i] = varyings[i];
582 }
583
584 mTransformFeedbackBufferMode = bufferMode;
585}
586
587void Program::getTransformFeedbackVarying(GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name) const
588{
589 ProgramBinary *programBinary = getProgramBinary();
590 if (programBinary && index < programBinary->getTransformFeedbackVaryingCount())
591 {
592 const LinkedVarying &varying = programBinary->getTransformFeedbackVarying(index);
593 GLsizei lastNameIdx = std::min(bufSize - 1, static_cast<GLsizei>(varying.name.length()));
594 if (length)
595 {
596 *length = lastNameIdx;
597 }
598 if (size)
599 {
600 *size = varying.size;
601 }
602 if (type)
603 {
604 *type = varying.type;
605 }
606 if (name)
607 {
608 memcpy(name, varying.name.c_str(), lastNameIdx);
609 name[lastNameIdx] = '\0';
610 }
611 }
612}
613
Geoff Lang1b6edcb2014-02-03 14:27:56 -0500614GLsizei Program::getTransformFeedbackVaryingCount() const
615{
Geoff Lang48dcae72014-02-05 16:28:24 -0500616 ProgramBinary *programBinary = getProgramBinary();
617 if (programBinary)
618 {
619 return static_cast<GLsizei>(programBinary->getTransformFeedbackVaryingCount());
620 }
621 else
622 {
623 return 0;
624 }
Geoff Lang1b6edcb2014-02-03 14:27:56 -0500625}
626
627GLsizei Program::getTransformFeedbackVaryingMaxLength() const
628{
Geoff Lang48dcae72014-02-05 16:28:24 -0500629 ProgramBinary *programBinary = getProgramBinary();
630 if (programBinary)
631 {
632 GLsizei maxSize = 0;
633 for (size_t i = 0; i < programBinary->getTransformFeedbackVaryingCount(); i++)
634 {
635 const LinkedVarying &varying = programBinary->getTransformFeedbackVarying(i);
636 maxSize = std::max(maxSize, static_cast<GLsizei>(varying.name.length() + 1));
637 }
638
639 return maxSize;
640 }
641 else
642 {
643 return 0;
644 }
Geoff Lang1b6edcb2014-02-03 14:27:56 -0500645}
646
647GLenum Program::getTransformFeedbackBufferMode() const
648{
Geoff Lang48dcae72014-02-05 16:28:24 -0500649 ProgramBinary *programBinary = getProgramBinary();
650 if (programBinary)
651 {
652 return programBinary->getTransformFeedbackBufferMode();
653 }
654 else
655 {
656 return mTransformFeedbackBufferMode;
657 }
Geoff Lang1b6edcb2014-02-03 14:27:56 -0500658}
659
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000660}