blob: 3faa8c56f6f8a5ec8007bac1d212320b0fb61c8c [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"
Brandon Jonesc9610c52014-08-25 17:02:59 -070013#include "libGLESv2/renderer/Renderer.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
Brandon Jones71620962014-08-20 14:04:59 -0700176 mVertexShader = 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
Brandon Jones71620962014-08-20 14:04:59 -0700186 mFragmentShader = 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
Jamie Madillde8892b2014-11-11 13:00:22 -0500247Error Program::link(const Data &data)
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
Brandon Jonesc9610c52014-08-25 17:02:59 -0700254 mProgramBinary.set(new ProgramBinary(mRenderer->createProgram()));
Jamie Madillde8892b2014-11-11 13:00:22 -0500255 LinkResult result = mProgramBinary->link(data, mInfoLog, mAttributeBindings, mFragmentShader, mVertexShader,
256 mTransformFeedbackVaryings, mTransformFeedbackBufferMode);
Geoff Langb543aff2014-09-30 14:52:54 -0400257 if (result.error.isError())
258 {
259 return result.error;
260 }
daniel@transgaming.com4c962bf2012-07-24 18:37:02 +0000261
Geoff Langb543aff2014-09-30 14:52:54 -0400262 mLinked = result.linkSuccess;
263 return gl::Error(GL_NO_ERROR);
apatrick@chromium.org9a30b092012-06-06 20:21:55 +0000264}
265
apatrick@chromium.org9a30b092012-06-06 20:21:55 +0000266int AttributeBindings::getAttributeBinding(const std::string &name) const
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +0000267{
268 for (int location = 0; location < MAX_VERTEX_ATTRIBS; location++)
269 {
270 if (mAttributeBinding[location].find(name) != mAttributeBinding[location].end())
271 {
272 return location;
273 }
274 }
275
276 return -1;
277}
278
daniel@transgaming.comaa5e59b2011-10-04 18:43:12 +0000279// Returns the program object to an unlinked state, before re-linking, or at destruction
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000280void Program::unlink(bool destroy)
281{
282 if (destroy) // Object being destructed
283 {
284 if (mFragmentShader)
285 {
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000286 mFragmentShader->release();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000287 mFragmentShader = NULL;
288 }
289
290 if (mVertexShader)
291 {
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000292 mVertexShader->release();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000293 mVertexShader = NULL;
294 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000295 }
296
daniel@transgaming.com989c1c82012-07-24 18:40:38 +0000297 mProgramBinary.set(NULL);
daniel@transgaming.com716056c2012-07-24 18:38:59 +0000298 mLinked = false;
299}
300
301bool Program::isLinked()
302{
303 return mLinked;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000304}
305
Geoff Lang48dcae72014-02-05 16:28:24 -0500306ProgramBinary* Program::getProgramBinary() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000307{
daniel@transgaming.com989c1c82012-07-24 18:40:38 +0000308 return mProgramBinary.get();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000309}
310
Geoff Langb543aff2014-09-30 14:52:54 -0400311Error Program::setProgramBinary(GLenum binaryFormat, const void *binary, GLsizei length)
apatrick@chromium.org3ce8dbc2012-06-08 17:52:30 +0000312{
313 unlink(false);
apatrick@chromium.org90080e32012-07-09 22:15:33 +0000314
315 mInfoLog.reset();
316
Brandon Jonesc9610c52014-08-25 17:02:59 -0700317 mProgramBinary.set(new ProgramBinary(mRenderer->createProgram()));
Geoff Langb543aff2014-09-30 14:52:54 -0400318 LinkResult result = mProgramBinary->load(mInfoLog, binaryFormat, binary, length);
319 if (result.error.isError())
apatrick@chromium.org90080e32012-07-09 22:15:33 +0000320 {
daniel@transgaming.com989c1c82012-07-24 18:40:38 +0000321 mProgramBinary.set(NULL);
Geoff Langb543aff2014-09-30 14:52:54 -0400322 return result.error;
apatrick@chromium.org90080e32012-07-09 22:15:33 +0000323 }
daniel@transgaming.com4c962bf2012-07-24 18:37:02 +0000324
Geoff Langb543aff2014-09-30 14:52:54 -0400325 mLinked = result.linkSuccess;
326 return Error(GL_NO_ERROR);
apatrick@chromium.org3ce8dbc2012-06-08 17:52:30 +0000327}
328
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000329void Program::release()
330{
331 mRefCount--;
332
333 if (mRefCount == 0 && mDeleteStatus)
334 {
335 mResourceManager->deleteProgram(mHandle);
336 }
337}
338
339void Program::addRef()
340{
341 mRefCount++;
342}
343
344unsigned int Program::getRefCount() const
345{
346 return mRefCount;
347}
348
apatrick@chromium.org90080e32012-07-09 22:15:33 +0000349GLint Program::getProgramBinaryLength() const
350{
daniel@transgaming.com989c1c82012-07-24 18:40:38 +0000351 ProgramBinary *programBinary = mProgramBinary.get();
352 if (programBinary)
apatrick@chromium.org90080e32012-07-09 22:15:33 +0000353 {
daniel@transgaming.com989c1c82012-07-24 18:40:38 +0000354 return programBinary->getLength();
apatrick@chromium.org90080e32012-07-09 22:15:33 +0000355 }
356 else
357 {
358 return 0;
359 }
360}
361
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000362int Program::getInfoLogLength() const
363{
apatrick@chromium.org253b8d22012-06-22 19:27:21 +0000364 return mInfoLog.getLength();
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000365}
366
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000367void Program::getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog)
368{
apatrick@chromium.org253b8d22012-06-22 19:27:21 +0000369 return mInfoLog.getLog(bufSize, length, infoLog);
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000370}
371
daniel@transgaming.com6c785212010-03-30 03:36:17 +0000372void Program::getAttachedShaders(GLsizei maxCount, GLsizei *count, GLuint *shaders)
373{
374 int total = 0;
375
376 if (mVertexShader)
377 {
378 if (total < maxCount)
379 {
380 shaders[total] = mVertexShader->getHandle();
381 }
382
383 total++;
384 }
385
386 if (mFragmentShader)
387 {
388 if (total < maxCount)
389 {
390 shaders[total] = mFragmentShader->getHandle();
391 }
392
393 total++;
394 }
395
396 if (count)
397 {
398 *count = total;
399 }
400}
401
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000402void Program::getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name)
403{
daniel@transgaming.com989c1c82012-07-24 18:40:38 +0000404 ProgramBinary *programBinary = getProgramBinary();
405 if (programBinary)
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000406 {
daniel@transgaming.com989c1c82012-07-24 18:40:38 +0000407 programBinary->getActiveAttribute(index, bufsize, length, size, type, name);
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000408 }
409 else
410 {
411 if (bufsize > 0)
412 {
413 name[0] = '\0';
414 }
415
416 if (length)
417 {
418 *length = 0;
419 }
420
421 *type = GL_NONE;
422 *size = 1;
423 }
424}
425
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000426GLint Program::getActiveAttributeCount()
427{
daniel@transgaming.com989c1c82012-07-24 18:40:38 +0000428 ProgramBinary *programBinary = getProgramBinary();
429 if (programBinary)
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000430 {
daniel@transgaming.com989c1c82012-07-24 18:40:38 +0000431 return programBinary->getActiveAttributeCount();
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000432 }
433 else
434 {
435 return 0;
436 }
437}
438
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000439GLint Program::getActiveAttributeMaxLength()
440{
daniel@transgaming.com989c1c82012-07-24 18:40:38 +0000441 ProgramBinary *programBinary = getProgramBinary();
442 if (programBinary)
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000443 {
daniel@transgaming.com989c1c82012-07-24 18:40:38 +0000444 return programBinary->getActiveAttributeMaxLength();
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000445 }
446 else
447 {
448 return 0;
449 }
450}
451
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000452void Program::getActiveUniform(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name)
453{
daniel@transgaming.com989c1c82012-07-24 18:40:38 +0000454 ProgramBinary *programBinary = getProgramBinary();
455 if (programBinary)
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000456 {
daniel@transgaming.com989c1c82012-07-24 18:40:38 +0000457 return programBinary->getActiveUniform(index, bufsize, length, size, type, name);
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000458 }
459 else
460 {
461 if (bufsize > 0)
462 {
463 name[0] = '\0';
464 }
465
466 if (length)
467 {
468 *length = 0;
469 }
470
471 *size = 0;
472 *type = GL_NONE;
473 }
474}
475
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000476GLint Program::getActiveUniformCount()
477{
daniel@transgaming.com989c1c82012-07-24 18:40:38 +0000478 ProgramBinary *programBinary = getProgramBinary();
479 if (programBinary)
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000480 {
daniel@transgaming.com989c1c82012-07-24 18:40:38 +0000481 return programBinary->getActiveUniformCount();
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000482 }
483 else
484 {
485 return 0;
486 }
487}
488
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000489GLint Program::getActiveUniformMaxLength()
490{
daniel@transgaming.com989c1c82012-07-24 18:40:38 +0000491 ProgramBinary *programBinary = getProgramBinary();
492 if (programBinary)
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000493 {
daniel@transgaming.com989c1c82012-07-24 18:40:38 +0000494 return programBinary->getActiveUniformMaxLength();
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000495 }
496 else
497 {
498 return 0;
499 }
500}
501
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000502void Program::flagForDeletion()
503{
504 mDeleteStatus = true;
505}
506
507bool Program::isFlaggedForDeletion() const
508{
509 return mDeleteStatus;
510}
daniel@transgaming.com86a7a132010-04-29 03:32:32 +0000511
Brandon Jones43a53e22014-08-28 16:23:22 -0700512void Program::validate(const Caps &caps)
apatrick@chromium.org253b8d22012-06-22 19:27:21 +0000513{
514 mInfoLog.reset();
515
daniel@transgaming.com989c1c82012-07-24 18:40:38 +0000516 ProgramBinary *programBinary = getProgramBinary();
517 if (isLinked() && programBinary)
apatrick@chromium.org253b8d22012-06-22 19:27:21 +0000518 {
Brandon Jones43a53e22014-08-28 16:23:22 -0700519 programBinary->validate(mInfoLog, caps);
apatrick@chromium.org253b8d22012-06-22 19:27:21 +0000520 }
521 else
522 {
523 mInfoLog.append("Program has not been successfully linked.");
524 }
525}
526
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000527bool Program::isValidated() const
528{
daniel@transgaming.com989c1c82012-07-24 18:40:38 +0000529 ProgramBinary *programBinary = mProgramBinary.get();
530 if (programBinary)
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000531 {
daniel@transgaming.com989c1c82012-07-24 18:40:38 +0000532 return programBinary->isValidated();
apatrick@chromium.orge2a59bb2012-06-07 21:09:53 +0000533 }
534 else
535 {
536 return false;
537 }
538}
539
shannonwoods@chromium.orge684b582013-05-30 00:07:42 +0000540GLint Program::getActiveUniformBlockCount()
541{
542 ProgramBinary *programBinary = getProgramBinary();
543 if (programBinary)
544 {
545 return static_cast<GLint>(programBinary->getActiveUniformBlockCount());
546 }
547 else
548 {
549 return 0;
550 }
551}
552
553GLint Program::getActiveUniformBlockMaxLength()
554{
555 ProgramBinary *programBinary = getProgramBinary();
556 if (programBinary)
557 {
558 return static_cast<GLint>(programBinary->getActiveUniformBlockMaxLength());
559 }
560 else
561 {
562 return 0;
563 }
564}
565
shannonwoods@chromium.org70eb1ea2013-05-30 00:07:20 +0000566void Program::bindUniformBlock(GLuint uniformBlockIndex, GLuint uniformBlockBinding)
567{
568 mUniformBlockBindings[uniformBlockIndex] = uniformBlockBinding;
569}
570
571GLuint Program::getUniformBlockBinding(GLuint uniformBlockIndex) const
572{
573 return mUniformBlockBindings[uniformBlockIndex];
574}
575
576void Program::resetUniformBlockBindings()
577{
578 for (unsigned int blockId = 0; blockId < IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS; blockId++)
579 {
580 mUniformBlockBindings[blockId] = 0;
581 }
582}
583
Geoff Lang48dcae72014-02-05 16:28:24 -0500584void Program::setTransformFeedbackVaryings(GLsizei count, const GLchar *const *varyings, GLenum bufferMode)
585{
586 mTransformFeedbackVaryings.resize(count);
587 for (GLsizei i = 0; i < count; i++)
588 {
589 mTransformFeedbackVaryings[i] = varyings[i];
590 }
591
592 mTransformFeedbackBufferMode = bufferMode;
593}
594
595void Program::getTransformFeedbackVarying(GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name) const
596{
597 ProgramBinary *programBinary = getProgramBinary();
598 if (programBinary && index < programBinary->getTransformFeedbackVaryingCount())
599 {
600 const LinkedVarying &varying = programBinary->getTransformFeedbackVarying(index);
601 GLsizei lastNameIdx = std::min(bufSize - 1, static_cast<GLsizei>(varying.name.length()));
602 if (length)
603 {
604 *length = lastNameIdx;
605 }
606 if (size)
607 {
608 *size = varying.size;
609 }
610 if (type)
611 {
612 *type = varying.type;
613 }
614 if (name)
615 {
616 memcpy(name, varying.name.c_str(), lastNameIdx);
617 name[lastNameIdx] = '\0';
618 }
619 }
620}
621
Geoff Lang1b6edcb2014-02-03 14:27:56 -0500622GLsizei Program::getTransformFeedbackVaryingCount() const
623{
Geoff Lang48dcae72014-02-05 16:28:24 -0500624 ProgramBinary *programBinary = getProgramBinary();
625 if (programBinary)
626 {
627 return static_cast<GLsizei>(programBinary->getTransformFeedbackVaryingCount());
628 }
629 else
630 {
631 return 0;
632 }
Geoff Lang1b6edcb2014-02-03 14:27:56 -0500633}
634
635GLsizei Program::getTransformFeedbackVaryingMaxLength() const
636{
Geoff Lang48dcae72014-02-05 16:28:24 -0500637 ProgramBinary *programBinary = getProgramBinary();
638 if (programBinary)
639 {
640 GLsizei maxSize = 0;
641 for (size_t i = 0; i < programBinary->getTransformFeedbackVaryingCount(); i++)
642 {
643 const LinkedVarying &varying = programBinary->getTransformFeedbackVarying(i);
644 maxSize = std::max(maxSize, static_cast<GLsizei>(varying.name.length() + 1));
645 }
646
647 return maxSize;
648 }
649 else
650 {
651 return 0;
652 }
Geoff Lang1b6edcb2014-02-03 14:27:56 -0500653}
654
655GLenum Program::getTransformFeedbackBufferMode() const
656{
Geoff Lang48dcae72014-02-05 16:28:24 -0500657 ProgramBinary *programBinary = getProgramBinary();
658 if (programBinary)
659 {
660 return programBinary->getTransformFeedbackBufferMode();
661 }
662 else
663 {
664 return mTransformFeedbackBufferMode;
665 }
Geoff Lang1b6edcb2014-02-03 14:27:56 -0500666}
667
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000668}