blob: 8a9fb048007a7ccb270be888b294c32105c18db3 [file] [log] [blame]
shannon.woods@transgaming.combdf2d802013-02-28 23:16:20 +00001#include "precompiled.h"
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002//
Geoff Lang48dcae72014-02-05 16:28:24 -05003// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00004// Use of this source code is governed by a BSD-style license that can be
5// found in the LICENSE file.
6//
7
8// Program.cpp: Implements the gl::Program class. Implements GL program objects
9// and related functionality. [OpenGL ES 2.0.24] section 2.10.3 page 28.
10
shannon.woods@transgaming.comd2811d62013-02-28 23:11:19 +000011#include "libGLESv2/Program.h"
apatrick@chromium.orgea09f9b2012-06-08 00:45:32 +000012#include "libGLESv2/ProgramBinary.h"
shannon.woods@transgaming.com486d9e92013-02-28 23:15:41 +000013#include "libGLESv2/ResourceManager.h"
daniel@transgaming.com87891f72011-06-01 15:28:35 +000014
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000015namespace gl
16{
apatrick@chromium.org253b8d22012-06-22 19:27:21 +000017const char * const g_fakepath = "C:\\fakepath";
18
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +000019AttributeBindings::AttributeBindings()
20{
21}
22
23AttributeBindings::~AttributeBindings()
24{
apatrick@chromium.org9a30b092012-06-06 20:21:55 +000025}
26
apatrick@chromium.org253b8d22012-06-22 19:27:21 +000027InfoLog::InfoLog() : mInfoLog(NULL)
28{
29}
30
31InfoLog::~InfoLog()
32{
33 delete[] mInfoLog;
34}
35
36
37int InfoLog::getLength() const
38{
39 if (!mInfoLog)
40 {
41 return 0;
42 }
43 else
44 {
45 return strlen(mInfoLog) + 1;
46 }
47}
48
49void InfoLog::getLog(GLsizei bufSize, GLsizei *length, char *infoLog)
50{
51 int index = 0;
52
53 if (bufSize > 0)
54 {
55 if (mInfoLog)
56 {
57 index = std::min(bufSize - 1, (int)strlen(mInfoLog));
58 memcpy(infoLog, mInfoLog, index);
59 }
60
61 infoLog[index] = '\0';
62 }
63
64 if (length)
65 {
66 *length = index;
67 }
68}
69
70// append a santized message to the program info log.
71// The D3D compiler includes a fake file path in some of the warning or error
72// messages, so lets remove all occurrences of this fake file path from the log.
73void InfoLog::appendSanitized(const char *message)
74{
75 std::string msg(message);
76
77 size_t found;
78 do
79 {
80 found = msg.find(g_fakepath);
81 if (found != std::string::npos)
82 {
83 msg.erase(found, strlen(g_fakepath));
84 }
85 }
86 while (found != std::string::npos);
87
shannon.woods@transgaming.come16e6512013-02-28 23:19:02 +000088 append("%s", msg.c_str());
apatrick@chromium.org253b8d22012-06-22 19:27:21 +000089}
90
91void InfoLog::append(const char *format, ...)
92{
93 if (!format)
94 {
95 return;
96 }
97
apatrick@chromium.org253b8d22012-06-22 19:27:21 +000098 va_list vararg;
99 va_start(vararg, format);
Jamie Madilld4505052014-02-24 15:26:49 -0500100 size_t infoLength = vsnprintf(NULL, 0, format, vararg);
apatrick@chromium.org253b8d22012-06-22 19:27:21 +0000101 va_end(vararg);
102
Jamie Madilld4505052014-02-24 15:26:49 -0500103 char *logPointer = NULL;
apatrick@chromium.org253b8d22012-06-22 19:27:21 +0000104
105 if (!mInfoLog)
106 {
shannon.woods@transgaming.come16e6512013-02-28 23:19:02 +0000107 mInfoLog = new char[infoLength + 2];
Jamie Madilld4505052014-02-24 15:26:49 -0500108 logPointer = mInfoLog;
apatrick@chromium.org253b8d22012-06-22 19:27:21 +0000109 }
110 else
111 {
Jamie Madilld4505052014-02-24 15:26:49 -0500112 size_t currentlogLength = strlen(mInfoLog);
113 char *newLog = new char[currentlogLength + infoLength + 2];
apatrick@chromium.org253b8d22012-06-22 19:27:21 +0000114 strcpy(newLog, mInfoLog);
apatrick@chromium.org253b8d22012-06-22 19:27:21 +0000115
116 delete[] mInfoLog;
117 mInfoLog = newLog;
Jamie Madilld4505052014-02-24 15:26:49 -0500118
119 logPointer = mInfoLog + currentlogLength;
apatrick@chromium.org253b8d22012-06-22 19:27:21 +0000120 }
Jamie Madilld4505052014-02-24 15:26:49 -0500121
122 va_start(vararg, format);
123 vsnprintf(logPointer, infoLength, format, vararg);
124 va_end(vararg);
125
126 logPointer[infoLength] = 0;
127 strcpy(logPointer + infoLength, "\n");
apatrick@chromium.org253b8d22012-06-22 19:27:21 +0000128}
129
130void InfoLog::reset()
131{
132 if (mInfoLog)
133 {
134 delete [] mInfoLog;
135 mInfoLog = NULL;
136 }
137}
138
daniel@transgaming.com70062c92012-11-28 19:32:30 +0000139Program::Program(rx::Renderer *renderer, ResourceManager *manager, GLuint handle) : mResourceManager(manager), mHandle(handle)
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000140{
141 mFragmentShader = NULL;
142 mVertexShader = NULL;
daniel@transgaming.com989c1c82012-07-24 18:40:38 +0000143 mProgramBinary.set(NULL);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000144 mDeleteStatus = false;
daniel@transgaming.com716056c2012-07-24 18:38:59 +0000145 mLinked = false;
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000146 mRefCount = 0;
daniel@transgaming.com70062c92012-11-28 19:32:30 +0000147 mRenderer = renderer;
shannonwoods@chromium.org70eb1ea2013-05-30 00:07:20 +0000148
149 resetUniformBlockBindings();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000150}
151
152Program::~Program()
153{
154 unlink(true);
daniel@transgaming.com71cd8682010-04-29 03:35:25 +0000155
156 if (mVertexShader != NULL)
157 {
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000158 mVertexShader->release();
daniel@transgaming.com71cd8682010-04-29 03:35:25 +0000159 }
160
161 if (mFragmentShader != NULL)
162 {
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000163 mFragmentShader->release();
daniel@transgaming.com71cd8682010-04-29 03:35:25 +0000164 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000165}
166
167bool Program::attachShader(Shader *shader)
168{
169 if (shader->getType() == GL_VERTEX_SHADER)
170 {
171 if (mVertexShader)
172 {
173 return false;
174 }
175
176 mVertexShader = (VertexShader*)shader;
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000177 mVertexShader->addRef();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000178 }
179 else if (shader->getType() == GL_FRAGMENT_SHADER)
180 {
181 if (mFragmentShader)
182 {
183 return false;
184 }
185
186 mFragmentShader = (FragmentShader*)shader;
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000187 mFragmentShader->addRef();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000188 }
189 else UNREACHABLE();
190
191 return true;
192}
193
194bool Program::detachShader(Shader *shader)
195{
196 if (shader->getType() == GL_VERTEX_SHADER)
197 {
198 if (mVertexShader != shader)
199 {
200 return false;
201 }
202
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000203 mVertexShader->release();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000204 mVertexShader = NULL;
205 }
206 else if (shader->getType() == GL_FRAGMENT_SHADER)
207 {
208 if (mFragmentShader != shader)
209 {
210 return false;
211 }
212
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000213 mFragmentShader->release();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000214 mFragmentShader = NULL;
215 }
216 else UNREACHABLE();
217
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000218 return true;
219}
220
daniel@transgaming.comcba50572010-03-28 19:36:09 +0000221int Program::getAttachedShadersCount() const
222{
223 return (mVertexShader ? 1 : 0) + (mFragmentShader ? 1 : 0);
224}
225
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000226void AttributeBindings::bindAttributeLocation(GLuint index, const char *name)
227{
228 if (index < MAX_VERTEX_ATTRIBS)
229 {
230 for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
231 {
232 mAttributeBinding[i].erase(name);
233 }
234
235 mAttributeBinding[index].insert(name);
236 }
apatrick@chromium.org9a30b092012-06-06 20:21:55 +0000237}
238
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000239void Program::bindAttributeLocation(GLuint index, const char *name)
240{
apatrick@chromium.org9a30b092012-06-06 20:21:55 +0000241 mAttributeBindings.bindAttributeLocation(index, name);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000242}
243
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000244// Links the HLSL code of the vertex and pixel shader by matching up their varyings,
245// compiling them into binaries, determining the attribute mappings, and collecting
246// a list of uniforms
daniel@transgaming.com4c962bf2012-07-24 18:37:02 +0000247bool Program::link()
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000248{
249 unlink(false);
250
apatrick@chromium.org253b8d22012-06-22 19:27:21 +0000251 mInfoLog.reset();
shannonwoods@chromium.org70eb1ea2013-05-30 00:07:20 +0000252 resetUniformBlockBindings();
apatrick@chromium.org253b8d22012-06-22 19:27:21 +0000253
daniel@transgaming.com70062c92012-11-28 19:32:30 +0000254 mProgramBinary.set(new ProgramBinary(mRenderer));
Geoff Lang48dcae72014-02-05 16:28:24 -0500255 mLinked = mProgramBinary->link(mInfoLog, mAttributeBindings, mFragmentShader, mVertexShader,
256 mTransformFeedbackVaryings, mTransformFeedbackBufferMode);
daniel@transgaming.com4c962bf2012-07-24 18:37:02 +0000257
daniel@transgaming.com716056c2012-07-24 18:38:59 +0000258 return mLinked;
apatrick@chromium.org9a30b092012-06-06 20:21:55 +0000259}
260
apatrick@chromium.org9a30b092012-06-06 20:21:55 +0000261int AttributeBindings::getAttributeBinding(const std::string &name) const
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +0000262{
263 for (int location = 0; location < MAX_VERTEX_ATTRIBS; location++)
264 {
265 if (mAttributeBinding[location].find(name) != mAttributeBinding[location].end())
266 {
267 return location;
268 }
269 }
270
271 return -1;
272}
273
daniel@transgaming.comaa5e59b2011-10-04 18:43:12 +0000274// Returns the program object to an unlinked state, before re-linking, or at destruction
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000275void Program::unlink(bool destroy)
276{
277 if (destroy) // Object being destructed
278 {
279 if (mFragmentShader)
280 {
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000281 mFragmentShader->release();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000282 mFragmentShader = NULL;
283 }
284
285 if (mVertexShader)
286 {
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000287 mVertexShader->release();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000288 mVertexShader = NULL;
289 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000290 }
291
daniel@transgaming.com989c1c82012-07-24 18:40:38 +0000292 mProgramBinary.set(NULL);
daniel@transgaming.com716056c2012-07-24 18:38:59 +0000293 mLinked = false;
294}
295
296bool Program::isLinked()
297{
298 return mLinked;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000299}
300
Geoff Lang48dcae72014-02-05 16:28:24 -0500301ProgramBinary* Program::getProgramBinary() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000302{
daniel@transgaming.com989c1c82012-07-24 18:40:38 +0000303 return mProgramBinary.get();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000304}
305
daniel@transgaming.com4c962bf2012-07-24 18:37:02 +0000306bool Program::setProgramBinary(const void *binary, GLsizei length)
apatrick@chromium.org3ce8dbc2012-06-08 17:52:30 +0000307{
308 unlink(false);
apatrick@chromium.org90080e32012-07-09 22:15:33 +0000309
310 mInfoLog.reset();
311
daniel@transgaming.com70062c92012-11-28 19:32:30 +0000312 mProgramBinary.set(new ProgramBinary(mRenderer));
daniel@transgaming.com716056c2012-07-24 18:38:59 +0000313 mLinked = mProgramBinary->load(mInfoLog, binary, length);
314 if (!mLinked)
apatrick@chromium.org90080e32012-07-09 22:15:33 +0000315 {
daniel@transgaming.com989c1c82012-07-24 18:40:38 +0000316 mProgramBinary.set(NULL);
apatrick@chromium.org90080e32012-07-09 22:15:33 +0000317 }
daniel@transgaming.com4c962bf2012-07-24 18:37:02 +0000318
daniel@transgaming.com716056c2012-07-24 18:38:59 +0000319 return mLinked;
apatrick@chromium.org3ce8dbc2012-06-08 17:52:30 +0000320}
321
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000322void Program::release()
323{
324 mRefCount--;
325
326 if (mRefCount == 0 && mDeleteStatus)
327 {
328 mResourceManager->deleteProgram(mHandle);
329 }
330}
331
332void Program::addRef()
333{
334 mRefCount++;
335}
336
337unsigned int Program::getRefCount() const
338{
339 return mRefCount;
340}
341
apatrick@chromium.org90080e32012-07-09 22:15:33 +0000342GLint Program::getProgramBinaryLength() const
343{
daniel@transgaming.com989c1c82012-07-24 18:40:38 +0000344 ProgramBinary *programBinary = mProgramBinary.get();
345 if (programBinary)
apatrick@chromium.org90080e32012-07-09 22:15:33 +0000346 {
daniel@transgaming.com989c1c82012-07-24 18:40:38 +0000347 return programBinary->getLength();
apatrick@chromium.org90080e32012-07-09 22:15:33 +0000348 }
349 else
350 {
351 return 0;
352 }
353}
354
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000355int Program::getInfoLogLength() const
356{
apatrick@chromium.org253b8d22012-06-22 19:27:21 +0000357 return mInfoLog.getLength();
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000358}
359
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000360void Program::getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog)
361{
apatrick@chromium.org253b8d22012-06-22 19:27:21 +0000362 return mInfoLog.getLog(bufSize, length, infoLog);
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000363}
364
daniel@transgaming.com6c785212010-03-30 03:36:17 +0000365void Program::getAttachedShaders(GLsizei maxCount, GLsizei *count, GLuint *shaders)
366{
367 int total = 0;
368
369 if (mVertexShader)
370 {
371 if (total < maxCount)
372 {
373 shaders[total] = mVertexShader->getHandle();
374 }
375
376 total++;
377 }
378
379 if (mFragmentShader)
380 {
381 if (total < maxCount)
382 {
383 shaders[total] = mFragmentShader->getHandle();
384 }
385
386 total++;
387 }
388
389 if (count)
390 {
391 *count = total;
392 }
393}
394
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000395void Program::getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name)
396{
daniel@transgaming.com989c1c82012-07-24 18:40:38 +0000397 ProgramBinary *programBinary = getProgramBinary();
398 if (programBinary)
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000399 {
daniel@transgaming.com989c1c82012-07-24 18:40:38 +0000400 programBinary->getActiveAttribute(index, bufsize, length, size, type, name);
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000401 }
402 else
403 {
404 if (bufsize > 0)
405 {
406 name[0] = '\0';
407 }
408
409 if (length)
410 {
411 *length = 0;
412 }
413
414 *type = GL_NONE;
415 *size = 1;
416 }
417}
418
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000419GLint Program::getActiveAttributeCount()
420{
daniel@transgaming.com989c1c82012-07-24 18:40:38 +0000421 ProgramBinary *programBinary = getProgramBinary();
422 if (programBinary)
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000423 {
daniel@transgaming.com989c1c82012-07-24 18:40:38 +0000424 return programBinary->getActiveAttributeCount();
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000425 }
426 else
427 {
428 return 0;
429 }
430}
431
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000432GLint Program::getActiveAttributeMaxLength()
433{
daniel@transgaming.com989c1c82012-07-24 18:40:38 +0000434 ProgramBinary *programBinary = getProgramBinary();
435 if (programBinary)
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000436 {
daniel@transgaming.com989c1c82012-07-24 18:40:38 +0000437 return programBinary->getActiveAttributeMaxLength();
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000438 }
439 else
440 {
441 return 0;
442 }
443}
444
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000445void Program::getActiveUniform(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name)
446{
daniel@transgaming.com989c1c82012-07-24 18:40:38 +0000447 ProgramBinary *programBinary = getProgramBinary();
448 if (programBinary)
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000449 {
daniel@transgaming.com989c1c82012-07-24 18:40:38 +0000450 return programBinary->getActiveUniform(index, bufsize, length, size, type, name);
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000451 }
452 else
453 {
454 if (bufsize > 0)
455 {
456 name[0] = '\0';
457 }
458
459 if (length)
460 {
461 *length = 0;
462 }
463
464 *size = 0;
465 *type = GL_NONE;
466 }
467}
468
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000469GLint Program::getActiveUniformCount()
470{
daniel@transgaming.com989c1c82012-07-24 18:40:38 +0000471 ProgramBinary *programBinary = getProgramBinary();
472 if (programBinary)
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000473 {
daniel@transgaming.com989c1c82012-07-24 18:40:38 +0000474 return programBinary->getActiveUniformCount();
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000475 }
476 else
477 {
478 return 0;
479 }
480}
481
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000482GLint Program::getActiveUniformMaxLength()
483{
daniel@transgaming.com989c1c82012-07-24 18:40:38 +0000484 ProgramBinary *programBinary = getProgramBinary();
485 if (programBinary)
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000486 {
daniel@transgaming.com989c1c82012-07-24 18:40:38 +0000487 return programBinary->getActiveUniformMaxLength();
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000488 }
489 else
490 {
491 return 0;
492 }
493}
494
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000495void Program::flagForDeletion()
496{
497 mDeleteStatus = true;
498}
499
500bool Program::isFlaggedForDeletion() const
501{
502 return mDeleteStatus;
503}
daniel@transgaming.com86a7a132010-04-29 03:32:32 +0000504
apatrick@chromium.org253b8d22012-06-22 19:27:21 +0000505void Program::validate()
506{
507 mInfoLog.reset();
508
daniel@transgaming.com989c1c82012-07-24 18:40:38 +0000509 ProgramBinary *programBinary = getProgramBinary();
510 if (isLinked() && programBinary)
apatrick@chromium.org253b8d22012-06-22 19:27:21 +0000511 {
daniel@transgaming.com989c1c82012-07-24 18:40:38 +0000512 programBinary->validate(mInfoLog);
apatrick@chromium.org253b8d22012-06-22 19:27:21 +0000513 }
514 else
515 {
516 mInfoLog.append("Program has not been successfully linked.");
517 }
518}
519
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000520bool Program::isValidated() const
521{
daniel@transgaming.com989c1c82012-07-24 18:40:38 +0000522 ProgramBinary *programBinary = mProgramBinary.get();
523 if (programBinary)
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000524 {
daniel@transgaming.com989c1c82012-07-24 18:40:38 +0000525 return programBinary->isValidated();
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000526 }
527 else
528 {
529 return false;
530 }
531}
532
shannonwoods@chromium.orge684b582013-05-30 00:07:42 +0000533GLint Program::getActiveUniformBlockCount()
534{
535 ProgramBinary *programBinary = getProgramBinary();
536 if (programBinary)
537 {
538 return static_cast<GLint>(programBinary->getActiveUniformBlockCount());
539 }
540 else
541 {
542 return 0;
543 }
544}
545
546GLint Program::getActiveUniformBlockMaxLength()
547{
548 ProgramBinary *programBinary = getProgramBinary();
549 if (programBinary)
550 {
551 return static_cast<GLint>(programBinary->getActiveUniformBlockMaxLength());
552 }
553 else
554 {
555 return 0;
556 }
557}
558
shannonwoods@chromium.org70eb1ea2013-05-30 00:07:20 +0000559void Program::bindUniformBlock(GLuint uniformBlockIndex, GLuint uniformBlockBinding)
560{
561 mUniformBlockBindings[uniformBlockIndex] = uniformBlockBinding;
562}
563
564GLuint Program::getUniformBlockBinding(GLuint uniformBlockIndex) const
565{
566 return mUniformBlockBindings[uniformBlockIndex];
567}
568
569void Program::resetUniformBlockBindings()
570{
571 for (unsigned int blockId = 0; blockId < IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS; blockId++)
572 {
573 mUniformBlockBindings[blockId] = 0;
574 }
575}
576
Geoff Lang48dcae72014-02-05 16:28:24 -0500577void Program::setTransformFeedbackVaryings(GLsizei count, const GLchar *const *varyings, GLenum bufferMode)
578{
579 mTransformFeedbackVaryings.resize(count);
580 for (GLsizei i = 0; i < count; i++)
581 {
582 mTransformFeedbackVaryings[i] = varyings[i];
583 }
584
585 mTransformFeedbackBufferMode = bufferMode;
586}
587
588void Program::getTransformFeedbackVarying(GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name) const
589{
590 ProgramBinary *programBinary = getProgramBinary();
591 if (programBinary && index < programBinary->getTransformFeedbackVaryingCount())
592 {
593 const LinkedVarying &varying = programBinary->getTransformFeedbackVarying(index);
594 GLsizei lastNameIdx = std::min(bufSize - 1, static_cast<GLsizei>(varying.name.length()));
595 if (length)
596 {
597 *length = lastNameIdx;
598 }
599 if (size)
600 {
601 *size = varying.size;
602 }
603 if (type)
604 {
605 *type = varying.type;
606 }
607 if (name)
608 {
609 memcpy(name, varying.name.c_str(), lastNameIdx);
610 name[lastNameIdx] = '\0';
611 }
612 }
613}
614
Geoff Lang1b6edcb2014-02-03 14:27:56 -0500615GLsizei Program::getTransformFeedbackVaryingCount() const
616{
Geoff Lang48dcae72014-02-05 16:28:24 -0500617 ProgramBinary *programBinary = getProgramBinary();
618 if (programBinary)
619 {
620 return static_cast<GLsizei>(programBinary->getTransformFeedbackVaryingCount());
621 }
622 else
623 {
624 return 0;
625 }
Geoff Lang1b6edcb2014-02-03 14:27:56 -0500626}
627
628GLsizei Program::getTransformFeedbackVaryingMaxLength() const
629{
Geoff Lang48dcae72014-02-05 16:28:24 -0500630 ProgramBinary *programBinary = getProgramBinary();
631 if (programBinary)
632 {
633 GLsizei maxSize = 0;
634 for (size_t i = 0; i < programBinary->getTransformFeedbackVaryingCount(); i++)
635 {
636 const LinkedVarying &varying = programBinary->getTransformFeedbackVarying(i);
637 maxSize = std::max(maxSize, static_cast<GLsizei>(varying.name.length() + 1));
638 }
639
640 return maxSize;
641 }
642 else
643 {
644 return 0;
645 }
Geoff Lang1b6edcb2014-02-03 14:27:56 -0500646}
647
648GLenum Program::getTransformFeedbackBufferMode() const
649{
Geoff Lang48dcae72014-02-05 16:28:24 -0500650 ProgramBinary *programBinary = getProgramBinary();
651 if (programBinary)
652 {
653 return programBinary->getTransformFeedbackBufferMode();
654 }
655 else
656 {
657 return mTransformFeedbackBufferMode;
658 }
Geoff Lang1b6edcb2014-02-03 14:27:56 -0500659}
660
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000661}