1 // SwiftShader Software Renderer
\r
3 // Copyright(c) 2005-2013 TransGaming Inc.
\r
5 // All rights reserved. No part of this software may be copied, distributed, transmitted,
\r
6 // transcribed, stored in a retrieval system, translated into any human or computer
\r
7 // language by any means, or disclosed to third parties without the explicit written
\r
8 // agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express
\r
9 // or implied, including but not limited to any patent rights, are granted to you.
\r
12 // Program.cpp: Implements the Program class. Implements GL program objects
\r
13 // and related functionality. [OpenGL ES 2.0.24] section 2.10.3 page 28.
\r
15 #include "Program.h"
\r
19 #include "utilities.h"
\r
20 #include "common/debug.h"
\r
21 #include "Shader/PixelShader.hpp"
\r
22 #include "Shader/VertexShader.hpp"
\r
29 unsigned int Program::currentSerial = 1;
\r
31 std::string str(int i)
\r
34 sprintf(buffer, "%d", i);
\r
38 Uniform::Uniform(GLenum type, GLenum precision, const std::string &name, unsigned int arraySize) : type(type), precision(precision), name(name), arraySize(arraySize)
\r
40 int bytes = UniformTypeSize(type) * size();
\r
41 data = new unsigned char[bytes];
\r
42 memset(data, 0, bytes);
\r
45 psRegisterIndex = -1;
\r
46 vsRegisterIndex = -1;
\r
54 bool Uniform::isArray() const
\r
56 return arraySize >= 1;
\r
59 int Uniform::size() const
\r
61 return arraySize > 0 ? arraySize : 1;
\r
64 int Uniform::registerCount() const
\r
66 return size() * VariableRowCount(type);
\r
69 UniformLocation::UniformLocation(const std::string &name, unsigned int element, unsigned int index) : name(name), element(element), index(index)
\r
73 Program::Program(ResourceManager *manager, GLuint handle) : resourceManager(manager), handle(handle), serial(issueSerial())
\r
75 device = getDevice();
\r
97 vertexShader->release();
\r
102 fragmentShader->release();
\r
106 bool Program::attachShader(Shader *shader)
\r
108 if(shader->getType() == GL_VERTEX_SHADER)
\r
115 vertexShader = (VertexShader*)shader;
\r
116 vertexShader->addRef();
\r
118 else if(shader->getType() == GL_FRAGMENT_SHADER)
\r
125 fragmentShader = (FragmentShader*)shader;
\r
126 fragmentShader->addRef();
\r
128 else UNREACHABLE();
\r
133 bool Program::detachShader(Shader *shader)
\r
135 if(shader->getType() == GL_VERTEX_SHADER)
\r
137 if(vertexShader != shader)
\r
142 vertexShader->release();
\r
145 else if(shader->getType() == GL_FRAGMENT_SHADER)
\r
147 if(fragmentShader != shader)
\r
152 fragmentShader->release();
\r
153 fragmentShader = 0;
\r
155 else UNREACHABLE();
\r
160 int Program::getAttachedShadersCount() const
\r
162 return (vertexShader ? 1 : 0) + (fragmentShader ? 1 : 0);
\r
165 sw::PixelShader *Program::getPixelShader()
\r
167 return pixelBinary;
\r
170 sw::VertexShader *Program::getVertexShader()
\r
172 return vertexBinary;
\r
175 void Program::bindAttributeLocation(GLuint index, const char *name)
\r
177 if(index < MAX_VERTEX_ATTRIBS)
\r
179 for(int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
\r
181 attributeBinding[i].erase(name);
\r
184 attributeBinding[index].insert(name);
\r
188 GLuint Program::getAttributeLocation(const char *name)
\r
192 for(int index = 0; index < MAX_VERTEX_ATTRIBS; index++)
\r
194 if(linkedAttribute[index].name == std::string(name))
\r
204 int Program::getAttributeStream(int attributeIndex)
\r
206 ASSERT(attributeIndex >= 0 && attributeIndex < MAX_VERTEX_ATTRIBS);
\r
208 return attributeStream[attributeIndex];
\r
211 // Returns the index of the texture image unit (0-19) corresponding to a sampler index (0-15 for the pixel shader and 0-3 for the vertex shader)
\r
212 GLint Program::getSamplerMapping(sw::SamplerType type, unsigned int samplerIndex)
\r
214 GLuint logicalTextureUnit = -1;
\r
218 case sw::SAMPLER_PIXEL:
\r
219 ASSERT(samplerIndex < sizeof(samplersPS) / sizeof(samplersPS[0]));
\r
221 if(samplersPS[samplerIndex].active)
\r
223 logicalTextureUnit = samplersPS[samplerIndex].logicalTextureUnit;
\r
226 case sw::SAMPLER_VERTEX:
\r
227 ASSERT(samplerIndex < sizeof(samplersVS) / sizeof(samplersVS[0]));
\r
229 if(samplersVS[samplerIndex].active)
\r
231 logicalTextureUnit = samplersVS[samplerIndex].logicalTextureUnit;
\r
234 default: UNREACHABLE();
\r
237 if(logicalTextureUnit >= 0 && logicalTextureUnit < MAX_COMBINED_TEXTURE_IMAGE_UNITS)
\r
239 return logicalTextureUnit;
\r
245 // Returns the texture type for a given sampler type and index (0-15 for the pixel shader and 0-3 for the vertex shader)
\r
246 TextureType Program::getSamplerTextureType(sw::SamplerType type, unsigned int samplerIndex)
\r
250 case sw::SAMPLER_PIXEL:
\r
251 ASSERT(samplerIndex < sizeof(samplersPS)/sizeof(samplersPS[0]));
\r
252 ASSERT(samplersPS[samplerIndex].active);
\r
253 return samplersPS[samplerIndex].textureType;
\r
254 case sw::SAMPLER_VERTEX:
\r
255 ASSERT(samplerIndex < sizeof(samplersVS)/sizeof(samplersVS[0]));
\r
256 ASSERT(samplersVS[samplerIndex].active);
\r
257 return samplersVS[samplerIndex].textureType;
\r
258 default: UNREACHABLE();
\r
264 GLint Program::getUniformLocation(std::string name)
\r
268 // Strip any trailing array operator and retrieve the subscript
\r
269 size_t open = name.find_last_of('[');
\r
270 size_t close = name.find_last_of(']');
\r
271 if(open != std::string::npos && close == name.length() - 1)
\r
273 subscript = atoi(name.substr(open + 1).c_str());
\r
277 unsigned int numUniforms = uniformIndex.size();
\r
278 for(unsigned int location = 0; location < numUniforms; location++)
\r
280 if(uniformIndex[location].name == name &&
\r
281 uniformIndex[location].element == subscript)
\r
290 bool Program::setUniform1fv(GLint location, GLsizei count, const GLfloat* v)
\r
292 if(location < 0 || location >= (int)uniformIndex.size())
\r
297 Uniform *targetUniform = uniforms[uniformIndex[location].index];
\r
298 targetUniform->dirty = true;
\r
300 int size = targetUniform->size();
\r
302 if(size == 1 && count > 1)
\r
304 return false; // Attempting to write an array to a non-array uniform is an INVALID_OPERATION
\r
307 count = std::min(size - (int)uniformIndex[location].element, count);
\r
309 if(targetUniform->type == GL_FLOAT)
\r
311 memcpy(targetUniform->data + uniformIndex[location].element * sizeof(GLfloat),
\r
312 v, sizeof(GLfloat) * count);
\r
314 else if(targetUniform->type == GL_BOOL)
\r
316 GLboolean *boolParams = (GLboolean*)targetUniform->data + uniformIndex[location].element;
\r
318 for(int i = 0; i < count; i++)
\r
322 boolParams[i] = GL_FALSE;
\r
326 boolParams[i] = GL_TRUE;
\r
338 bool Program::setUniform2fv(GLint location, GLsizei count, const GLfloat *v)
\r
340 if(location < 0 || location >= (int)uniformIndex.size())
\r
345 Uniform *targetUniform = uniforms[uniformIndex[location].index];
\r
346 targetUniform->dirty = true;
\r
348 int size = targetUniform->size();
\r
350 if(size == 1 && count > 1)
\r
352 return false; // Attempting to write an array to a non-array uniform is an INVALID_OPERATION
\r
355 count = std::min(size - (int)uniformIndex[location].element, count);
\r
357 if(targetUniform->type == GL_FLOAT_VEC2)
\r
359 memcpy(targetUniform->data + uniformIndex[location].element * sizeof(GLfloat) * 2,
\r
360 v, 2 * sizeof(GLfloat) * count);
\r
362 else if(targetUniform->type == GL_BOOL_VEC2)
\r
364 GLboolean *boolParams = (GLboolean*)targetUniform->data + uniformIndex[location].element * 2;
\r
366 for(int i = 0; i < count * 2; i++)
\r
370 boolParams[i] = GL_FALSE;
\r
374 boolParams[i] = GL_TRUE;
\r
386 bool Program::setUniform3fv(GLint location, GLsizei count, const GLfloat *v)
\r
388 if(location < 0 || location >= (int)uniformIndex.size())
\r
393 Uniform *targetUniform = uniforms[uniformIndex[location].index];
\r
394 targetUniform->dirty = true;
\r
396 int size = targetUniform->size();
\r
398 if(size == 1 && count > 1)
\r
400 return false; // Attempting to write an array to a non-array uniform is an INVALID_OPERATION
\r
403 count = std::min(size - (int)uniformIndex[location].element, count);
\r
405 if(targetUniform->type == GL_FLOAT_VEC3)
\r
407 memcpy(targetUniform->data + uniformIndex[location].element * sizeof(GLfloat) * 3,
\r
408 v, 3 * sizeof(GLfloat) * count);
\r
410 else if(targetUniform->type == GL_BOOL_VEC3)
\r
412 GLboolean *boolParams = (GLboolean*)targetUniform->data + uniformIndex[location].element * 3;
\r
414 for(int i = 0; i < count * 3; i++)
\r
418 boolParams[i] = GL_FALSE;
\r
422 boolParams[i] = GL_TRUE;
\r
434 bool Program::setUniform4fv(GLint location, GLsizei count, const GLfloat *v)
\r
436 if(location < 0 || location >= (int)uniformIndex.size())
\r
441 Uniform *targetUniform = uniforms[uniformIndex[location].index];
\r
442 targetUniform->dirty = true;
\r
444 int size = targetUniform->size();
\r
446 if(size == 1 && count > 1)
\r
448 return false; // Attempting to write an array to a non-array uniform is an INVALID_OPERATION
\r
451 count = std::min(size - (int)uniformIndex[location].element, count);
\r
453 if(targetUniform->type == GL_FLOAT_VEC4)
\r
455 memcpy(targetUniform->data + uniformIndex[location].element * sizeof(GLfloat) * 4,
\r
456 v, 4 * sizeof(GLfloat) * count);
\r
458 else if(targetUniform->type == GL_BOOL_VEC4)
\r
460 GLboolean *boolParams = (GLboolean*)targetUniform->data + uniformIndex[location].element * 4;
\r
462 for(int i = 0; i < count * 4; i++)
\r
466 boolParams[i] = GL_FALSE;
\r
470 boolParams[i] = GL_TRUE;
\r
482 bool Program::setUniformMatrix2fv(GLint location, GLsizei count, const GLfloat *value)
\r
484 if(location < 0 || location >= (int)uniformIndex.size())
\r
489 Uniform *targetUniform = uniforms[uniformIndex[location].index];
\r
490 targetUniform->dirty = true;
\r
492 if(targetUniform->type != GL_FLOAT_MAT2)
\r
497 int size = targetUniform->size();
\r
499 if(size == 1 && count > 1)
\r
501 return false; // Attempting to write an array to a non-array uniform is an INVALID_OPERATION
\r
504 count = std::min(size - (int)uniformIndex[location].element, count);
\r
506 memcpy(targetUniform->data + uniformIndex[location].element * sizeof(GLfloat) * 4,
\r
507 value, 4 * sizeof(GLfloat) * count);
\r
512 bool Program::setUniformMatrix3fv(GLint location, GLsizei count, const GLfloat *value)
\r
514 if(location < 0 || location >= (int)uniformIndex.size())
\r
519 Uniform *targetUniform = uniforms[uniformIndex[location].index];
\r
520 targetUniform->dirty = true;
\r
522 if(targetUniform->type != GL_FLOAT_MAT3)
\r
527 int size = targetUniform->size();
\r
529 if(size == 1 && count > 1)
\r
531 return false; // Attempting to write an array to a non-array uniform is an INVALID_OPERATION
\r
534 count = std::min(size - (int)uniformIndex[location].element, count);
\r
536 memcpy(targetUniform->data + uniformIndex[location].element * sizeof(GLfloat) * 9,
\r
537 value, 9 * sizeof(GLfloat) * count);
\r
542 bool Program::setUniformMatrix4fv(GLint location, GLsizei count, const GLfloat *value)
\r
544 if(location < 0 || location >= (int)uniformIndex.size())
\r
549 Uniform *targetUniform = uniforms[uniformIndex[location].index];
\r
550 targetUniform->dirty = true;
\r
552 if(targetUniform->type != GL_FLOAT_MAT4)
\r
557 int size = targetUniform->size();
\r
559 if(size == 1 && count > 1)
\r
561 return false; // Attempting to write an array to a non-array uniform is an INVALID_OPERATION
\r
564 count = std::min(size - (int)uniformIndex[location].element, count);
\r
566 memcpy(targetUniform->data + uniformIndex[location].element * sizeof(GLfloat) * 16,
\r
567 value, 16 * sizeof(GLfloat) * count);
\r
572 bool Program::setUniform1iv(GLint location, GLsizei count, const GLint *v)
\r
574 if(location < 0 || location >= (int)uniformIndex.size())
\r
579 Uniform *targetUniform = uniforms[uniformIndex[location].index];
\r
580 targetUniform->dirty = true;
\r
582 int size = targetUniform->size();
\r
584 if(size == 1 && count > 1)
\r
586 return false; // Attempting to write an array to a non-array uniform is an INVALID_OPERATION
\r
589 count = std::min(size - (int)uniformIndex[location].element, count);
\r
591 if(targetUniform->type == GL_INT ||
\r
592 targetUniform->type == GL_SAMPLER_2D ||
\r
593 targetUniform->type == GL_SAMPLER_CUBE ||
\r
594 targetUniform->type == GL_SAMPLER_EXTERNAL_OES)
\r
596 memcpy(targetUniform->data + uniformIndex[location].element * sizeof(GLint),
\r
597 v, sizeof(GLint) * count);
\r
599 else if(targetUniform->type == GL_BOOL)
\r
601 GLboolean *boolParams = new GLboolean[count];
\r
603 for(int i = 0; i < count; i++)
\r
607 boolParams[i] = GL_FALSE;
\r
611 boolParams[i] = GL_TRUE;
\r
615 memcpy(targetUniform->data + uniformIndex[location].element * sizeof(GLboolean),
\r
616 boolParams, sizeof(GLboolean) * count);
\r
618 delete[] boolParams;
\r
628 bool Program::setUniform2iv(GLint location, GLsizei count, const GLint *v)
\r
630 if(location < 0 || location >= (int)uniformIndex.size())
\r
635 Uniform *targetUniform = uniforms[uniformIndex[location].index];
\r
636 targetUniform->dirty = true;
\r
638 int size = targetUniform->size();
\r
640 if(size == 1 && count > 1)
\r
642 return false; // Attempting to write an array to a non-array uniform is an INVALID_OPERATION
\r
645 count = std::min(size - (int)uniformIndex[location].element, count);
\r
647 if(targetUniform->type == GL_INT_VEC2)
\r
649 memcpy(targetUniform->data + uniformIndex[location].element * sizeof(GLint) * 2,
\r
650 v, 2 * sizeof(GLint) * count);
\r
652 else if(targetUniform->type == GL_BOOL_VEC2)
\r
654 GLboolean *boolParams = new GLboolean[count * 2];
\r
656 for(int i = 0; i < count * 2; i++)
\r
660 boolParams[i] = GL_FALSE;
\r
664 boolParams[i] = GL_TRUE;
\r
668 memcpy(targetUniform->data + uniformIndex[location].element * sizeof(GLboolean) * 2,
\r
669 boolParams, 2 * sizeof(GLboolean) * count);
\r
671 delete[] boolParams;
\r
681 bool Program::setUniform3iv(GLint location, GLsizei count, const GLint *v)
\r
683 if(location < 0 || location >= (int)uniformIndex.size())
\r
688 Uniform *targetUniform = uniforms[uniformIndex[location].index];
\r
689 targetUniform->dirty = true;
\r
691 int size = targetUniform->size();
\r
693 if(size == 1 && count > 1)
\r
695 return false; // Attempting to write an array to a non-array uniform is an INVALID_OPERATION
\r
698 count = std::min(size - (int)uniformIndex[location].element, count);
\r
700 if(targetUniform->type == GL_INT_VEC3)
\r
702 memcpy(targetUniform->data + uniformIndex[location].element * sizeof(GLint) * 3,
\r
703 v, 3 * sizeof(GLint) * count);
\r
705 else if(targetUniform->type == GL_BOOL_VEC3)
\r
707 GLboolean *boolParams = new GLboolean[count * 3];
\r
709 for(int i = 0; i < count * 3; i++)
\r
713 boolParams[i] = GL_FALSE;
\r
717 boolParams[i] = GL_TRUE;
\r
721 memcpy(targetUniform->data + uniformIndex[location].element * sizeof(GLboolean) * 3,
\r
722 boolParams, 3 * sizeof(GLboolean) * count);
\r
724 delete[] boolParams;
\r
734 bool Program::setUniform4iv(GLint location, GLsizei count, const GLint *v)
\r
736 if(location < 0 || location >= (int)uniformIndex.size())
\r
741 Uniform *targetUniform = uniforms[uniformIndex[location].index];
\r
742 targetUniform->dirty = true;
\r
744 int size = targetUniform->size();
\r
746 if(size == 1 && count > 1)
\r
748 return false; // Attempting to write an array to a non-array uniform is an INVALID_OPERATION
\r
751 count = std::min(size - (int)uniformIndex[location].element, count);
\r
753 if(targetUniform->type == GL_INT_VEC4)
\r
755 memcpy(targetUniform->data + uniformIndex[location].element * sizeof(GLint) * 4,
\r
756 v, 4 * sizeof(GLint) * count);
\r
758 else if(targetUniform->type == GL_BOOL_VEC4)
\r
760 GLboolean *boolParams = new GLboolean[count * 4];
\r
762 for(int i = 0; i < count * 4; i++)
\r
766 boolParams[i] = GL_FALSE;
\r
770 boolParams[i] = GL_TRUE;
\r
774 memcpy(targetUniform->data + uniformIndex[location].element * sizeof(GLboolean) * 4,
\r
775 boolParams, 4 * sizeof(GLboolean) * count);
\r
777 delete[] boolParams;
\r
787 bool Program::getUniformfv(GLint location, GLsizei *bufSize, GLfloat *params)
\r
789 if(location < 0 || location >= (int)uniformIndex.size())
\r
794 Uniform *targetUniform = uniforms[uniformIndex[location].index];
\r
795 unsigned int count = UniformComponentCount(targetUniform->type);
\r
797 // Sized query - ensure the provided buffer is large enough
\r
798 if(bufSize && *bufSize < count * sizeof(GLfloat))
\r
803 switch (UniformComponentType(targetUniform->type))
\r
807 GLboolean *boolParams = (GLboolean*)targetUniform->data + uniformIndex[location].element * count;
\r
809 for(unsigned int i = 0; i < count; i++)
\r
811 params[i] = (boolParams[i] == GL_FALSE) ? 0.0f : 1.0f;
\r
816 memcpy(params, targetUniform->data + uniformIndex[location].element * count * sizeof(GLfloat),
\r
817 count * sizeof(GLfloat));
\r
821 GLint *intParams = (GLint*)targetUniform->data + uniformIndex[location].element * count;
\r
823 for(unsigned int i = 0; i < count; i++)
\r
825 params[i] = (float)intParams[i];
\r
829 default: UNREACHABLE();
\r
835 bool Program::getUniformiv(GLint location, GLsizei *bufSize, GLint *params)
\r
837 if(location < 0 || location >= (int)uniformIndex.size())
\r
842 Uniform *targetUniform = uniforms[uniformIndex[location].index];
\r
843 unsigned int count = UniformComponentCount(targetUniform->type);
\r
845 // Sized query - ensure the provided buffer is large enough
\r
846 if(bufSize && *bufSize < count * sizeof(GLint))
\r
851 switch (UniformComponentType(targetUniform->type))
\r
855 GLboolean *boolParams = targetUniform->data + uniformIndex[location].element * count;
\r
857 for(unsigned int i = 0; i < count; i++)
\r
859 params[i] = (GLint)boolParams[i];
\r
865 GLfloat *floatParams = (GLfloat*)targetUniform->data + uniformIndex[location].element * count;
\r
867 for(unsigned int i = 0; i < count; i++)
\r
869 params[i] = (GLint)floatParams[i];
\r
874 memcpy(params, targetUniform->data + uniformIndex[location].element * count * sizeof(GLint),
\r
875 count * sizeof(GLint));
\r
877 default: UNREACHABLE();
\r
883 void Program::dirtyAllUniforms()
\r
885 unsigned int numUniforms = uniforms.size();
\r
886 for(unsigned int index = 0; index < numUniforms; index++)
\r
888 uniforms[index]->dirty = true;
\r
892 // Applies all the uniforms set for this program object to the device
\r
893 void Program::applyUniforms()
\r
895 unsigned int numUniforms = uniformIndex.size();
\r
896 for(unsigned int location = 0; location < numUniforms; location++)
\r
898 if(uniformIndex[location].element != 0)
\r
903 Uniform *targetUniform = uniforms[uniformIndex[location].index];
\r
905 if(targetUniform->dirty)
\r
907 int size = targetUniform->size();
\r
908 GLfloat *f = (GLfloat*)targetUniform->data;
\r
909 GLint *i = (GLint*)targetUniform->data;
\r
910 GLboolean *b = (GLboolean*)targetUniform->data;
\r
912 switch(targetUniform->type)
\r
914 case GL_BOOL: applyUniform1bv(location, size, b); break;
\r
915 case GL_BOOL_VEC2: applyUniform2bv(location, size, b); break;
\r
916 case GL_BOOL_VEC3: applyUniform3bv(location, size, b); break;
\r
917 case GL_BOOL_VEC4: applyUniform4bv(location, size, b); break;
\r
918 case GL_FLOAT: applyUniform1fv(location, size, f); break;
\r
919 case GL_FLOAT_VEC2: applyUniform2fv(location, size, f); break;
\r
920 case GL_FLOAT_VEC3: applyUniform3fv(location, size, f); break;
\r
921 case GL_FLOAT_VEC4: applyUniform4fv(location, size, f); break;
\r
922 case GL_FLOAT_MAT2: applyUniformMatrix2fv(location, size, f); break;
\r
923 case GL_FLOAT_MAT3: applyUniformMatrix3fv(location, size, f); break;
\r
924 case GL_FLOAT_MAT4: applyUniformMatrix4fv(location, size, f); break;
\r
925 case GL_SAMPLER_2D:
\r
926 case GL_SAMPLER_CUBE:
\r
927 case GL_SAMPLER_EXTERNAL_OES:
\r
928 case GL_INT: applyUniform1iv(location, size, i); break;
\r
929 case GL_INT_VEC2: applyUniform2iv(location, size, i); break;
\r
930 case GL_INT_VEC3: applyUniform3iv(location, size, i); break;
\r
931 case GL_INT_VEC4: applyUniform4iv(location, size, i); break;
\r
936 targetUniform->dirty = false;
\r
941 // Packs varyings into generic varying registers, using the algorithm from [OpenGL ES Shading Language 1.00 rev. 17] appendix A section 7 page 111
\r
942 // Returns the number of used varying registers, or -1 if unsuccesful
\r
943 int Program::packVaryings(const Varying *packing[][4])
\r
945 for(VaryingList::iterator varying = fragmentShader->varyings.begin(); varying != fragmentShader->varyings.end(); varying++)
\r
947 int n = VariableRowCount(varying->type) * varying->size();
\r
948 int m = VariableColumnCount(varying->type);
\r
949 bool success = false;
\r
951 if(m == 2 || m == 3 || m == 4)
\r
953 for(int r = 0; r <= MAX_VARYING_VECTORS - n && !success; r++)
\r
955 bool available = true;
\r
957 for(int y = 0; y < n && available; y++)
\r
959 for(int x = 0; x < m && available; x++)
\r
961 if(packing[r + y][x])
\r
973 for(int y = 0; y < n; y++)
\r
975 for(int x = 0; x < m; x++)
\r
977 packing[r + y][x] = &*varying;
\r
985 if(!success && m == 2)
\r
987 for(int r = MAX_VARYING_VECTORS - n; r >= 0 && !success; r--)
\r
989 bool available = true;
\r
991 for(int y = 0; y < n && available; y++)
\r
993 for(int x = 2; x < 4 && available; x++)
\r
995 if(packing[r + y][x])
\r
1007 for(int y = 0; y < n; y++)
\r
1009 for(int x = 2; x < 4; x++)
\r
1011 packing[r + y][x] = &*varying;
\r
1022 int space[4] = {0};
\r
1024 for(int y = 0; y < MAX_VARYING_VECTORS; y++)
\r
1026 for(int x = 0; x < 4; x++)
\r
1028 space[x] += packing[y][x] ? 0 : 1;
\r
1034 for(int x = 0; x < 4; x++)
\r
1036 if(space[x] >= n && space[x] < space[column])
\r
1042 if(space[column] >= n)
\r
1044 for(int r = 0; r < MAX_VARYING_VECTORS; r++)
\r
1046 if(!packing[r][column])
\r
1050 for(int y = r; y < r + n; y++)
\r
1052 packing[y][column] = &*varying;
\r
1059 varying->col = column;
\r
1064 else UNREACHABLE();
\r
1068 appendToInfoLog("Could not pack varying %s", varying->name.c_str());
\r
1074 // Return the number of used registers
\r
1075 int registers = 0;
\r
1077 for(int r = 0; r < MAX_VARYING_VECTORS; r++)
\r
1079 if(packing[r][0] || packing[r][1] || packing[r][2] || packing[r][3])
\r
1088 bool Program::linkVaryings()
\r
1090 for(VaryingList::iterator input = fragmentShader->varyings.begin(); input != fragmentShader->varyings.end(); input++)
\r
1092 bool matched = false;
\r
1094 for(VaryingList::iterator output = vertexShader->varyings.begin(); output != vertexShader->varyings.end(); output++)
\r
1096 if(output->name == input->name)
\r
1098 if(output->type != input->type || output->size() != input->size())
\r
1100 appendToInfoLog("Type of vertex varying %s does not match that of the fragment varying", output->name.c_str());
\r
1112 appendToInfoLog("Fragment varying %s does not match any vertex varying", input->name.c_str());
\r
1118 VaryingList &psVaryings = fragmentShader->varyings;
\r
1119 VaryingList &vsVaryings = vertexShader->varyings;
\r
1121 for(VaryingList::iterator output = vsVaryings.begin(); output != vsVaryings.end(); output++)
\r
1123 for(VaryingList::iterator input = psVaryings.begin(); input != psVaryings.end(); input++)
\r
1125 if(output->name == input->name)
\r
1127 int in = input->reg;
\r
1128 int out = output->reg;
\r
1129 int components = VariableColumnCount(output->type);
\r
1130 int registers = VariableRowCount(output->type) * output->size();
\r
1134 if(in + registers > MAX_VARYING_VECTORS)
\r
1136 appendToInfoLog("Too many varyings");
\r
1142 if(out + registers > MAX_VARYING_VECTORS)
\r
1144 appendToInfoLog("Too many varyings");
\r
1148 for(int i = 0; i < registers; i++)
\r
1150 if(components >= 1) vertexBinary->output[out + i][0] = sw::Shader::Semantic(sw::Shader::USAGE_COLOR, in + i);
\r
1151 if(components >= 2) vertexBinary->output[out + i][1] = sw::Shader::Semantic(sw::Shader::USAGE_COLOR, in + i);
\r
1152 if(components >= 3) vertexBinary->output[out + i][2] = sw::Shader::Semantic(sw::Shader::USAGE_COLOR, in + i);
\r
1153 if(components >= 4) vertexBinary->output[out + i][3] = sw::Shader::Semantic(sw::Shader::USAGE_COLOR, in + i);
\r
1156 else // Vertex varying is declared but not written to
\r
1158 for(int i = 0; i < registers; i++)
\r
1160 if(components >= 1) pixelBinary->semantic[in + i][0] = sw::Shader::Semantic();
\r
1161 if(components >= 2) pixelBinary->semantic[in + i][1] = sw::Shader::Semantic();
\r
1162 if(components >= 3) pixelBinary->semantic[in + i][2] = sw::Shader::Semantic();
\r
1163 if(components >= 4) pixelBinary->semantic[in + i][3] = sw::Shader::Semantic();
\r
1175 // Links the code of the vertex and pixel shader by matching up their varyings,
\r
1176 // compiling them into binaries, determining the attribute mappings, and collecting
\r
1177 // a list of uniforms
\r
1178 void Program::link()
\r
1182 if(!fragmentShader || !fragmentShader->isCompiled())
\r
1187 if(!vertexShader || !vertexShader->isCompiled())
\r
1192 vertexBinary = new sw::VertexShader(vertexShader->getVertexShader());
\r
1193 pixelBinary = new sw::PixelShader(fragmentShader->getPixelShader());
\r
1195 if(!linkVaryings())
\r
1200 if(!linkAttributes())
\r
1205 if(!linkUniforms(fragmentShader))
\r
1210 if(!linkUniforms(vertexShader))
\r
1215 linked = true; // Success
\r
1218 // Determines the mapping between GL attributes and vertex stream usage indices
\r
1219 bool Program::linkAttributes()
\r
1221 unsigned int usedLocations = 0;
\r
1223 // Link attributes that have a binding location
\r
1224 for(sh::ActiveAttributes::iterator attribute = vertexShader->activeAttributes.begin(); attribute != vertexShader->activeAttributes.end(); attribute++)
\r
1226 int location = getAttributeBinding(attribute->name);
\r
1228 if(location != -1) // Set by glBindAttribLocation
\r
1230 if(!linkedAttribute[location].name.empty())
\r
1232 // Multiple active attributes bound to the same location; not an error
\r
1235 linkedAttribute[location] = *attribute;
\r
1237 int rows = VariableRowCount(attribute->type);
\r
1239 if(rows + location > MAX_VERTEX_ATTRIBS)
\r
1241 appendToInfoLog("Active attribute (%s) at location %d is too big to fit", attribute->name.c_str(), location);
\r
1245 for(int i = 0; i < rows; i++)
\r
1247 usedLocations |= 1 << (location + i);
\r
1252 // Link attributes that don't have a binding location
\r
1253 for(sh::ActiveAttributes::iterator attribute = vertexShader->activeAttributes.begin(); attribute != vertexShader->activeAttributes.end(); attribute++)
\r
1255 int location = getAttributeBinding(attribute->name);
\r
1257 if(location == -1) // Not set by glBindAttribLocation
\r
1259 int rows = VariableRowCount(attribute->type);
\r
1260 int availableIndex = AllocateFirstFreeBits(&usedLocations, rows, MAX_VERTEX_ATTRIBS);
\r
1262 if(availableIndex == -1 || availableIndex + rows > MAX_VERTEX_ATTRIBS)
\r
1264 appendToInfoLog("Too many active attributes (%s)", attribute->name.c_str());
\r
1265 return false; // Fail to link
\r
1268 linkedAttribute[availableIndex] = *attribute;
\r
1272 for(int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; )
\r
1274 int index = vertexShader->getSemanticIndex(linkedAttribute[attributeIndex].name);
\r
1275 int rows = std::max(VariableRowCount(linkedAttribute[attributeIndex].type), 1);
\r
1277 for(int r = 0; r < rows; r++)
\r
1279 attributeStream[attributeIndex++] = index++;
\r
1286 int Program::getAttributeBinding(const std::string &name)
\r
1288 for(int location = 0; location < MAX_VERTEX_ATTRIBS; location++)
\r
1290 if(attributeBinding[location].find(name) != attributeBinding[location].end())
\r
1299 bool Program::linkUniforms(Shader *shader)
\r
1301 const sh::ActiveUniforms &activeUniforms = shader->activeUniforms;
\r
1303 for(unsigned int uniformIndex = 0; uniformIndex < activeUniforms.size(); uniformIndex++)
\r
1305 const sh::Uniform &uniform = activeUniforms[uniformIndex];
\r
1307 if(!defineUniform(shader->getType(), uniform.type, uniform.precision, uniform.name, uniform.arraySize, uniform.registerIndex))
\r
1316 bool Program::defineUniform(GLenum shader, GLenum type, GLenum precision, const std::string &name, unsigned int arraySize, int registerIndex)
\r
1318 if(type == GL_SAMPLER_2D || type == GL_SAMPLER_CUBE || type == GL_SAMPLER_EXTERNAL_OES)
\r
1320 int index = registerIndex;
\r
1324 if(shader == GL_VERTEX_SHADER)
\r
1326 if(index < MAX_VERTEX_TEXTURE_IMAGE_UNITS)
\r
1328 samplersVS[index].active = true;
\r
1329 samplersVS[index].textureType = (type == GL_SAMPLER_CUBE) ? TEXTURE_CUBE : TEXTURE_2D;
\r
1330 samplersVS[index].logicalTextureUnit = 0;
\r
1334 appendToInfoLog("Vertex shader sampler count exceeds MAX_VERTEX_TEXTURE_IMAGE_UNITS (%d).", MAX_VERTEX_TEXTURE_IMAGE_UNITS);
\r
1338 else if(shader == GL_FRAGMENT_SHADER)
\r
1340 if(index < MAX_TEXTURE_IMAGE_UNITS)
\r
1342 samplersPS[index].active = true;
\r
1343 samplersPS[index].textureType = (type == GL_SAMPLER_CUBE) ? TEXTURE_CUBE : TEXTURE_2D;
\r
1344 samplersPS[index].logicalTextureUnit = 0;
\r
1348 appendToInfoLog("Pixel shader sampler count exceeds MAX_TEXTURE_IMAGE_UNITS (%d).", MAX_TEXTURE_IMAGE_UNITS);
\r
1352 else UNREACHABLE();
\r
1356 while(index < registerIndex + arraySize);
\r
1359 Uniform *uniform = 0;
\r
1360 GLint location = getUniformLocation(name);
\r
1362 if(location >= 0) // Previously defined, types must match
\r
1364 uniform = uniforms[uniformIndex[location].index];
\r
1366 if(uniform->type != type)
\r
1368 appendToInfoLog("Types for uniform %s do not match between the vertex and fragment shader", uniform->name.c_str());
\r
1372 if(uniform->precision != precision)
\r
1374 appendToInfoLog("Precisions for uniform %s do not match between the vertex and fragment shader", uniform->name.c_str());
\r
1380 uniform = new Uniform(type, precision, name, arraySize);
\r
1388 if(shader == GL_VERTEX_SHADER)
\r
1390 uniform->vsRegisterIndex = registerIndex;
\r
1392 else if(shader == GL_FRAGMENT_SHADER)
\r
1394 uniform->psRegisterIndex = registerIndex;
\r
1396 else UNREACHABLE();
\r
1398 if(location == -1) // Not previously defined
\r
1400 uniforms.push_back(uniform);
\r
1401 unsigned int index = uniforms.size() - 1;
\r
1403 for(unsigned int i = 0; i < uniform->size(); i++)
\r
1405 uniformIndex.push_back(UniformLocation(name, i, index));
\r
1409 if(shader == GL_VERTEX_SHADER)
\r
1411 if(registerIndex + uniform->registerCount() > MAX_VERTEX_UNIFORM_VECTORS)
\r
1413 appendToInfoLog("Vertex shader active uniforms exceed GL_MAX_VERTEX_UNIFORM_VECTORS (%d)", MAX_VERTEX_UNIFORM_VECTORS);
\r
1417 else if(shader == GL_FRAGMENT_SHADER)
\r
1419 if(registerIndex + uniform->registerCount() > MAX_FRAGMENT_UNIFORM_VECTORS)
\r
1421 appendToInfoLog("Fragment shader active uniforms exceed GL_MAX_FRAGMENT_UNIFORM_VECTORS (%d)", MAX_FRAGMENT_UNIFORM_VECTORS);
\r
1425 else UNREACHABLE();
\r
1430 bool Program::applyUniform1bv(GLint location, GLsizei count, const GLboolean *v)
\r
1432 int vector[MAX_UNIFORM_VECTORS][4];
\r
1434 for(int i = 0; i < count; i++)
\r
1436 vector[i][0] = (v[0] == GL_FALSE ? 0x00000000 : 0xFFFFFFFF);
\r
1444 Uniform *targetUniform = uniforms[uniformIndex[location].index];
\r
1446 if(targetUniform->psRegisterIndex != -1)
\r
1448 device->setPixelShaderConstantF(targetUniform->psRegisterIndex, (float*)vector, targetUniform->registerCount());
\r
1451 if(targetUniform->vsRegisterIndex != -1)
\r
1453 device->setVertexShaderConstantF(targetUniform->vsRegisterIndex, (float*)vector, targetUniform->registerCount());
\r
1459 bool Program::applyUniform2bv(GLint location, GLsizei count, const GLboolean *v)
\r
1461 int vector[MAX_UNIFORM_VECTORS][4];
\r
1463 for(int i = 0; i < count; i++)
\r
1465 vector[i][0] = (v[0] == GL_FALSE ? 0x00000000 : 0xFFFFFFFF);
\r
1466 vector[i][1] = (v[1] == GL_FALSE ? 0x00000000 : 0xFFFFFFFF);
\r
1473 Uniform *targetUniform = uniforms[uniformIndex[location].index];
\r
1475 if(targetUniform->psRegisterIndex != -1)
\r
1477 device->setPixelShaderConstantF(targetUniform->psRegisterIndex, (float*)vector, targetUniform->registerCount());
\r
1480 if(targetUniform->vsRegisterIndex != -1)
\r
1482 device->setVertexShaderConstantF(targetUniform->vsRegisterIndex, (float*)vector, targetUniform->registerCount());
\r
1488 bool Program::applyUniform3bv(GLint location, GLsizei count, const GLboolean *v)
\r
1490 int vector[MAX_UNIFORM_VECTORS][4];
\r
1492 for(int i = 0; i < count; i++)
\r
1494 vector[i][0] = (v[0] == GL_FALSE ? 0x00000000 : 0xFFFFFFFF);
\r
1495 vector[i][1] = (v[1] == GL_FALSE ? 0x00000000 : 0xFFFFFFFF);
\r
1496 vector[i][2] = (v[2] == GL_FALSE ? 0x00000000 : 0xFFFFFFFF);
\r
1502 Uniform *targetUniform = uniforms[uniformIndex[location].index];
\r
1504 if(targetUniform->psRegisterIndex != -1)
\r
1506 device->setPixelShaderConstantF(targetUniform->psRegisterIndex, (float*)vector, targetUniform->registerCount());
\r
1509 if(targetUniform->vsRegisterIndex != -1)
\r
1511 device->setVertexShaderConstantF(targetUniform->vsRegisterIndex, (float*)vector, targetUniform->registerCount());
\r
1517 bool Program::applyUniform4bv(GLint location, GLsizei count, const GLboolean *v)
\r
1519 int vector[MAX_UNIFORM_VECTORS][4];
\r
1521 for(int i = 0; i < count; i++)
\r
1523 vector[i][0] = (v[0] == GL_FALSE ? 0x00000000 : 0xFFFFFFFF);
\r
1524 vector[i][1] = (v[1] == GL_FALSE ? 0x00000000 : 0xFFFFFFFF);
\r
1525 vector[i][2] = (v[2] == GL_FALSE ? 0x00000000 : 0xFFFFFFFF);
\r
1526 vector[i][3] = (v[3] == GL_FALSE ? 0x00000000 : 0xFFFFFFFF);
\r
1531 Uniform *targetUniform = uniforms[uniformIndex[location].index];
\r
1533 if(targetUniform->psRegisterIndex != -1)
\r
1535 device->setPixelShaderConstantF(targetUniform->psRegisterIndex, (float*)vector, targetUniform->registerCount());
\r
1538 if(targetUniform->vsRegisterIndex != -1)
\r
1540 device->setVertexShaderConstantF(targetUniform->vsRegisterIndex, (float*)vector, targetUniform->registerCount());
\r
1546 bool Program::applyUniform1fv(GLint location, GLsizei count, const GLfloat *v)
\r
1548 float vector[MAX_UNIFORM_VECTORS][4];
\r
1550 for(int i = 0; i < count; i++)
\r
1552 vector[i][0] = v[0];
\r
1560 Uniform *targetUniform = uniforms[uniformIndex[location].index];
\r
1562 if(targetUniform->psRegisterIndex != -1)
\r
1564 device->setPixelShaderConstantF(targetUniform->psRegisterIndex, (float*)vector, targetUniform->registerCount());
\r
1567 if(targetUniform->vsRegisterIndex != -1)
\r
1569 device->setVertexShaderConstantF(targetUniform->vsRegisterIndex, (float*)vector, targetUniform->registerCount());
\r
1575 bool Program::applyUniform2fv(GLint location, GLsizei count, const GLfloat *v)
\r
1577 float vector[MAX_UNIFORM_VECTORS][4];
\r
1579 for(int i = 0; i < count; i++)
\r
1581 vector[i][0] = v[0];
\r
1582 vector[i][1] = v[1];
\r
1589 Uniform *targetUniform = uniforms[uniformIndex[location].index];
\r
1591 if(targetUniform->psRegisterIndex != -1)
\r
1593 device->setPixelShaderConstantF(targetUniform->psRegisterIndex, (float*)vector, targetUniform->registerCount());
\r
1596 if(targetUniform->vsRegisterIndex != -1)
\r
1598 device->setVertexShaderConstantF(targetUniform->vsRegisterIndex, (float*)vector, targetUniform->registerCount());
\r
1604 bool Program::applyUniform3fv(GLint location, GLsizei count, const GLfloat *v)
\r
1606 float vector[MAX_UNIFORM_VECTORS][4];
\r
1608 for(int i = 0; i < count; i++)
\r
1610 vector[i][0] = v[0];
\r
1611 vector[i][1] = v[1];
\r
1612 vector[i][2] = v[2];
\r
1618 Uniform *targetUniform = uniforms[uniformIndex[location].index];
\r
1620 if(targetUniform->psRegisterIndex != -1)
\r
1622 device->setPixelShaderConstantF(targetUniform->psRegisterIndex, (float*)vector, targetUniform->registerCount());
\r
1625 if(targetUniform->vsRegisterIndex != -1)
\r
1627 device->setVertexShaderConstantF(targetUniform->vsRegisterIndex, (float*)vector, targetUniform->registerCount());
\r
1633 bool Program::applyUniform4fv(GLint location, GLsizei count, const GLfloat *v)
\r
1635 Uniform *targetUniform = uniforms[uniformIndex[location].index];
\r
1637 if(targetUniform->psRegisterIndex != -1)
\r
1639 device->setPixelShaderConstantF(targetUniform->psRegisterIndex, (float*)v, targetUniform->registerCount());
\r
1642 if(targetUniform->vsRegisterIndex != -1)
\r
1644 device->setVertexShaderConstantF(targetUniform->vsRegisterIndex, (float*)v, targetUniform->registerCount());
\r
1650 bool Program::applyUniformMatrix2fv(GLint location, GLsizei count, const GLfloat *value)
\r
1652 float matrix[(MAX_UNIFORM_VECTORS + 1) / 2][2][4];
\r
1654 for(int i = 0; i < count; i++)
\r
1656 matrix[i][0][0] = value[0]; matrix[i][0][1] = value[1]; matrix[i][0][2] = 0; matrix[i][0][3] = 0;
\r
1657 matrix[i][1][0] = value[2]; matrix[i][1][1] = value[3]; matrix[i][1][2] = 0; matrix[i][1][3] = 0;
\r
1662 Uniform *targetUniform = uniforms[uniformIndex[location].index];
\r
1664 if(targetUniform->psRegisterIndex != -1)
\r
1666 device->setPixelShaderConstantF(targetUniform->psRegisterIndex, (float*)matrix, targetUniform->registerCount());
\r
1669 if(targetUniform->vsRegisterIndex != -1)
\r
1671 device->setVertexShaderConstantF(targetUniform->vsRegisterIndex, (float*)matrix, targetUniform->registerCount());
\r
1677 bool Program::applyUniformMatrix3fv(GLint location, GLsizei count, const GLfloat *value)
\r
1679 float matrix[(MAX_UNIFORM_VECTORS + 2) / 3][3][4];
\r
1681 for(int i = 0; i < count; i++)
\r
1683 matrix[i][0][0] = value[0]; matrix[i][0][1] = value[1]; matrix[i][0][2] = value[2]; matrix[i][0][3] = 0;
\r
1684 matrix[i][1][0] = value[3]; matrix[i][1][1] = value[4]; matrix[i][1][2] = value[5]; matrix[i][1][3] = 0;
\r
1685 matrix[i][2][0] = value[6]; matrix[i][2][1] = value[7]; matrix[i][2][2] = value[8]; matrix[i][2][3] = 0;
\r
1690 Uniform *targetUniform = uniforms[uniformIndex[location].index];
\r
1692 if(targetUniform->psRegisterIndex != -1)
\r
1694 device->setPixelShaderConstantF(targetUniform->psRegisterIndex, (float*)matrix, targetUniform->registerCount());
\r
1697 if(targetUniform->vsRegisterIndex != -1)
\r
1699 device->setVertexShaderConstantF(targetUniform->vsRegisterIndex, (float*)matrix, targetUniform->registerCount());
\r
1705 bool Program::applyUniformMatrix4fv(GLint location, GLsizei count, const GLfloat *value)
\r
1707 Uniform *targetUniform = uniforms[uniformIndex[location].index];
\r
1709 if(targetUniform->psRegisterIndex != -1)
\r
1711 device->setPixelShaderConstantF(targetUniform->psRegisterIndex, (float*)value, targetUniform->registerCount());
\r
1714 if(targetUniform->vsRegisterIndex != -1)
\r
1716 device->setVertexShaderConstantF(targetUniform->vsRegisterIndex, (float*)value, targetUniform->registerCount());
\r
1722 bool Program::applyUniform1iv(GLint location, GLsizei count, const GLint *v)
\r
1724 float vector[MAX_UNIFORM_VECTORS][4];
\r
1726 for(int i = 0; i < count; i++)
\r
1728 vector[i][0] = (float)v[i];
\r
1734 Uniform *targetUniform = uniforms[uniformIndex[location].index];
\r
1736 if(targetUniform->psRegisterIndex != -1)
\r
1738 if(targetUniform->type == GL_SAMPLER_2D ||
\r
1739 targetUniform->type == GL_SAMPLER_CUBE ||
\r
1740 targetUniform->type == GL_SAMPLER_EXTERNAL_OES)
\r
1742 for(int i = 0; i < count; i++)
\r
1744 unsigned int samplerIndex = targetUniform->psRegisterIndex + i;
\r
1746 if(samplerIndex < MAX_TEXTURE_IMAGE_UNITS)
\r
1748 ASSERT(samplersPS[samplerIndex].active);
\r
1749 samplersPS[samplerIndex].logicalTextureUnit = v[i];
\r
1755 device->setPixelShaderConstantF(targetUniform->psRegisterIndex, (float*)vector, targetUniform->registerCount());
\r
1759 if(targetUniform->vsRegisterIndex != -1)
\r
1761 if(targetUniform->type == GL_SAMPLER_2D ||
\r
1762 targetUniform->type == GL_SAMPLER_CUBE ||
\r
1763 targetUniform->type == GL_SAMPLER_EXTERNAL_OES)
\r
1765 for(int i = 0; i < count; i++)
\r
1767 unsigned int samplerIndex = targetUniform->vsRegisterIndex + i;
\r
1769 if(samplerIndex < MAX_VERTEX_TEXTURE_IMAGE_UNITS)
\r
1771 ASSERT(samplersVS[samplerIndex].active);
\r
1772 samplersVS[samplerIndex].logicalTextureUnit = v[i];
\r
1778 device->setVertexShaderConstantF(targetUniform->vsRegisterIndex, (float*)vector, targetUniform->registerCount());
\r
1785 bool Program::applyUniform2iv(GLint location, GLsizei count, const GLint *v)
\r
1787 float vector[MAX_UNIFORM_VECTORS][4];
\r
1789 for(int i = 0; i < count; i++)
\r
1791 vector[i][0] = (float)v[0];
\r
1792 vector[i][1] = (float)v[1];
\r
1799 Uniform *targetUniform = uniforms[uniformIndex[location].index];
\r
1801 if(targetUniform->psRegisterIndex != -1)
\r
1803 device->setPixelShaderConstantF(targetUniform->psRegisterIndex, (float*)vector, targetUniform->registerCount());
\r
1806 if(targetUniform->vsRegisterIndex != -1)
\r
1808 device->setVertexShaderConstantF(targetUniform->vsRegisterIndex, (float*)vector, targetUniform->registerCount());
\r
1814 bool Program::applyUniform3iv(GLint location, GLsizei count, const GLint *v)
\r
1816 float vector[MAX_UNIFORM_VECTORS][4];
\r
1818 for(int i = 0; i < count; i++)
\r
1820 vector[i][0] = (float)v[0];
\r
1821 vector[i][1] = (float)v[1];
\r
1822 vector[i][2] = (float)v[2];
\r
1828 Uniform *targetUniform = uniforms[uniformIndex[location].index];
\r
1830 if(targetUniform->psRegisterIndex != -1)
\r
1832 device->setPixelShaderConstantF(targetUniform->psRegisterIndex, (float*)vector, targetUniform->registerCount());
\r
1835 if(targetUniform->vsRegisterIndex != -1)
\r
1837 device->setVertexShaderConstantF(targetUniform->vsRegisterIndex, (float*)vector, targetUniform->registerCount());
\r
1843 bool Program::applyUniform4iv(GLint location, GLsizei count, const GLint *v)
\r
1845 float vector[MAX_UNIFORM_VECTORS][4];
\r
1847 for(int i = 0; i < count; i++)
\r
1849 vector[i][0] = (float)v[0];
\r
1850 vector[i][1] = (float)v[1];
\r
1851 vector[i][2] = (float)v[2];
\r
1852 vector[i][3] = (float)v[3];
\r
1857 Uniform *targetUniform = uniforms[uniformIndex[location].index];
\r
1859 if(targetUniform->psRegisterIndex != -1)
\r
1861 device->setPixelShaderConstantF(targetUniform->psRegisterIndex, (float*)vector, targetUniform->registerCount());
\r
1864 if(targetUniform->vsRegisterIndex != -1)
\r
1866 device->setVertexShaderConstantF(targetUniform->vsRegisterIndex, (float*)vector, targetUniform->registerCount());
\r
1872 void Program::appendToInfoLog(const char *format, ...)
\r
1882 va_start(vararg, format);
\r
1883 vsnprintf(info, sizeof(info), format, vararg);
\r
1886 size_t infoLength = strlen(info);
\r
1890 infoLog = new char[infoLength + 2];
\r
1891 strcpy(infoLog, info);
\r
1892 strcpy(infoLog + infoLength, "\n");
\r
1896 size_t logLength = strlen(infoLog);
\r
1897 char *newLog = new char[logLength + infoLength + 2];
\r
1898 strcpy(newLog, infoLog);
\r
1899 strcpy(newLog + logLength, info);
\r
1900 strcpy(newLog + logLength + infoLength, "\n");
\r
1907 void Program::resetInfoLog()
\r
1916 // Returns the program object to an unlinked state, before re-linking, or at destruction
\r
1917 void Program::unlink()
\r
1919 delete vertexBinary;
\r
1921 delete pixelBinary;
\r
1924 for(int index = 0; index < MAX_VERTEX_ATTRIBS; index++)
\r
1926 linkedAttribute[index].name.clear();
\r
1927 attributeStream[index] = -1;
\r
1930 for(int index = 0; index < MAX_TEXTURE_IMAGE_UNITS; index++)
\r
1932 samplersPS[index].active = false;
\r
1935 for(int index = 0; index < MAX_VERTEX_TEXTURE_IMAGE_UNITS; index++)
\r
1937 samplersVS[index].active = false;
\r
1940 while(!uniforms.empty())
\r
1942 delete uniforms.back();
\r
1943 uniforms.pop_back();
\r
1946 uniformIndex.clear();
\r
1954 bool Program::isLinked()
\r
1959 bool Program::isValidated() const
\r
1964 void Program::release()
\r
1968 if(referenceCount == 0 && orphaned)
\r
1970 resourceManager->deleteProgram(handle);
\r
1974 void Program::addRef()
\r
1979 unsigned int Program::getRefCount() const
\r
1981 return referenceCount;
\r
1984 unsigned int Program::getSerial() const
\r
1989 unsigned int Program::issueSerial()
\r
1991 return currentSerial++;
\r
1994 int Program::getInfoLogLength() const
\r
2002 return strlen(infoLog) + 1;
\r
2006 void Program::getInfoLog(GLsizei bufSize, GLsizei *length, char *buffer)
\r
2014 index = std::min(bufSize - 1, (int)strlen(infoLog));
\r
2015 memcpy(buffer, infoLog, index);
\r
2018 buffer[index] = '\0';
\r
2027 void Program::getAttachedShaders(GLsizei maxCount, GLsizei *count, GLuint *shaders)
\r
2033 if(total < maxCount)
\r
2035 shaders[total] = vertexShader->getHandle();
\r
2041 if(fragmentShader)
\r
2043 if(total < maxCount)
\r
2045 shaders[total] = fragmentShader->getHandle();
\r
2057 void Program::getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) const
\r
2059 // Skip over inactive attributes
\r
2060 unsigned int activeAttribute = 0;
\r
2061 unsigned int attribute;
\r
2062 for(attribute = 0; attribute < MAX_VERTEX_ATTRIBS; attribute++)
\r
2064 if(linkedAttribute[attribute].name.empty())
\r
2069 if(activeAttribute == index)
\r
2074 activeAttribute++;
\r
2079 const char *string = linkedAttribute[attribute].name.c_str();
\r
2081 strncpy(name, string, bufsize);
\r
2082 name[bufsize - 1] = '\0';
\r
2086 *length = strlen(name);
\r
2090 *size = 1; // Always a single 'type' instance
\r
2092 *type = linkedAttribute[attribute].type;
\r
2095 GLint Program::getActiveAttributeCount() const
\r
2099 for(int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
\r
2101 if(!linkedAttribute[attributeIndex].name.empty())
\r
2110 GLint Program::getActiveAttributeMaxLength() const
\r
2112 int maxLength = 0;
\r
2114 for(int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
\r
2116 if(!linkedAttribute[attributeIndex].name.empty())
\r
2118 maxLength = std::max((int)(linkedAttribute[attributeIndex].name.length() + 1), maxLength);
\r
2125 void Program::getActiveUniform(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) const
\r
2129 std::string string = uniforms[index]->name;
\r
2131 if(uniforms[index]->isArray())
\r
2136 strncpy(name, string.c_str(), bufsize);
\r
2137 name[bufsize - 1] = '\0';
\r
2141 *length = strlen(name);
\r
2145 *size = uniforms[index]->size();
\r
2147 *type = uniforms[index]->type;
\r
2150 GLint Program::getActiveUniformCount() const
\r
2152 return uniforms.size();
\r
2155 GLint Program::getActiveUniformMaxLength() const
\r
2157 int maxLength = 0;
\r
2159 unsigned int numUniforms = uniforms.size();
\r
2160 for(unsigned int uniformIndex = 0; uniformIndex < numUniforms; uniformIndex++)
\r
2162 if(!uniforms[uniformIndex]->name.empty())
\r
2164 int length = (int)(uniforms[uniformIndex]->name.length() + 1);
\r
2165 if(uniforms[uniformIndex]->isArray())
\r
2167 length += 3; // Counting in "[0]".
\r
2169 maxLength = std::max(length, maxLength);
\r
2176 void Program::flagForDeletion()
\r
2181 bool Program::isFlaggedForDeletion() const
\r
2186 void Program::validate()
\r
2192 appendToInfoLog("Program has not been successfully linked.");
\r
2193 validated = false;
\r
2198 if(!validateSamplers(true))
\r
2200 validated = false;
\r
2209 bool Program::validateSamplers(bool logErrors)
\r
2211 // if any two active samplers in a program are of different types, but refer to the same
\r
2212 // texture image unit, and this is the current program, then ValidateProgram will fail, and
\r
2213 // DrawArrays and DrawElements will issue the INVALID_OPERATION error.
\r
2215 TextureType textureUnitType[MAX_COMBINED_TEXTURE_IMAGE_UNITS];
\r
2217 for(unsigned int i = 0; i < MAX_COMBINED_TEXTURE_IMAGE_UNITS; i++)
\r
2219 textureUnitType[i] = TEXTURE_UNKNOWN;
\r
2222 for(unsigned int i = 0; i < MAX_TEXTURE_IMAGE_UNITS; i++)
\r
2224 if(samplersPS[i].active)
\r
2226 unsigned int unit = samplersPS[i].logicalTextureUnit;
\r
2228 if(unit >= MAX_COMBINED_TEXTURE_IMAGE_UNITS)
\r
2232 appendToInfoLog("Sampler uniform (%d) exceeds MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, MAX_COMBINED_TEXTURE_IMAGE_UNITS);
\r
2238 if(textureUnitType[unit] != TEXTURE_UNKNOWN)
\r
2240 if(samplersPS[i].textureType != textureUnitType[unit])
\r
2244 appendToInfoLog("Samplers of conflicting types refer to the same texture image unit (%d).", unit);
\r
2252 textureUnitType[unit] = samplersPS[i].textureType;
\r
2257 for(unsigned int i = 0; i < MAX_VERTEX_TEXTURE_IMAGE_UNITS; i++)
\r
2259 if(samplersVS[i].active)
\r
2261 unsigned int unit = samplersVS[i].logicalTextureUnit;
\r
2263 if(unit >= MAX_COMBINED_TEXTURE_IMAGE_UNITS)
\r
2267 appendToInfoLog("Sampler uniform (%d) exceeds MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, MAX_COMBINED_TEXTURE_IMAGE_UNITS);
\r
2273 if(textureUnitType[unit] != TEXTURE_UNKNOWN)
\r
2275 if(samplersVS[i].textureType != textureUnitType[unit])
\r
2279 appendToInfoLog("Samplers of conflicting types refer to the same texture image unit (%d).", unit);
\r
2287 textureUnitType[unit] = samplersVS[i].textureType;
\r