• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2016 The SwiftShader Authors. All Rights Reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //    http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 // Program.cpp: Implements the Program class. Implements GL program objects
16 // and related functionality.
17 
18 #include "Program.h"
19 
20 #include "main.h"
21 #include "Shader.h"
22 #include "utilities.h"
23 #include "common/debug.h"
24 #include "Shader/PixelShader.hpp"
25 #include "Shader/VertexShader.hpp"
26 
27 #include <string>
28 #include <stdlib.h>
29 
30 namespace gl
31 {
32 	unsigned int Program::currentSerial = 1;
33 
str(int i)34 	std::string str(int i)
35 	{
36 		char buffer[20];
37 		sprintf(buffer, "%d", i);
38 		return buffer;
39 	}
40 
Uniform(GLenum type,GLenum precision,const std::string & name,unsigned int arraySize)41 	Uniform::Uniform(GLenum type, GLenum precision, const std::string &name, unsigned int arraySize) : type(type), precision(precision), name(name), arraySize(arraySize)
42 	{
43 		int bytes = UniformTypeSize(type) * size();
44 		data = new unsigned char[bytes];
45 		memset(data, 0, bytes);
46 		dirty = true;
47 
48 		psRegisterIndex = -1;
49 		vsRegisterIndex = -1;
50 	}
51 
~Uniform()52 	Uniform::~Uniform()
53 	{
54 		delete[] data;
55 	}
56 
isArray() const57 	bool Uniform::isArray() const
58 	{
59 		return arraySize >= 1;
60 	}
61 
size() const62 	int Uniform::size() const
63 	{
64 		return arraySize > 0 ? arraySize : 1;
65 	}
66 
registerCount() const67 	int Uniform::registerCount() const
68 	{
69 		return size() * VariableRowCount(type);
70 	}
71 
UniformLocation(const std::string & name,unsigned int element,unsigned int index)72 	UniformLocation::UniformLocation(const std::string &name, unsigned int element, unsigned int index) : name(name), element(element), index(index)
73 	{
74 	}
75 
Program(ResourceManager * manager,GLuint handle)76 	Program::Program(ResourceManager *manager, GLuint handle) : resourceManager(manager), handle(handle), serial(issueSerial())
77 	{
78 		device = getDevice();
79 
80 		fragmentShader = 0;
81 		vertexShader = 0;
82 		pixelBinary = 0;
83 		vertexBinary = 0;
84 
85 		infoLog = 0;
86 		validated = false;
87 
88 		unlink();
89 
90 		orphaned = false;
91 		referenceCount = 0;
92 	}
93 
~Program()94 	Program::~Program()
95 	{
96 		unlink();
97 
98 		if(vertexShader)
99 		{
100 			vertexShader->release();
101 		}
102 
103 		if(fragmentShader)
104 		{
105 			fragmentShader->release();
106 		}
107 	}
108 
attachShader(Shader * shader)109 	bool Program::attachShader(Shader *shader)
110 	{
111 		if(shader->getType() == GL_VERTEX_SHADER)
112 		{
113 			if(vertexShader)
114 			{
115 				return false;
116 			}
117 
118 			vertexShader = (VertexShader*)shader;
119 			vertexShader->addRef();
120 		}
121 		else if(shader->getType() == GL_FRAGMENT_SHADER)
122 		{
123 			if(fragmentShader)
124 			{
125 				return false;
126 			}
127 
128 			fragmentShader = (FragmentShader*)shader;
129 			fragmentShader->addRef();
130 		}
131 		else UNREACHABLE(shader->getType());
132 
133 		return true;
134 	}
135 
detachShader(Shader * shader)136 	bool Program::detachShader(Shader *shader)
137 	{
138 		if(shader->getType() == GL_VERTEX_SHADER)
139 		{
140 			if(vertexShader != shader)
141 			{
142 				return false;
143 			}
144 
145 			vertexShader->release();
146 			vertexShader = 0;
147 		}
148 		else if(shader->getType() == GL_FRAGMENT_SHADER)
149 		{
150 			if(fragmentShader != shader)
151 			{
152 				return false;
153 			}
154 
155 			fragmentShader->release();
156 			fragmentShader = 0;
157 		}
158 		else UNREACHABLE(shader->getType());
159 
160 		return true;
161 	}
162 
getAttachedShadersCount() const163 	int Program::getAttachedShadersCount() const
164 	{
165 		return (vertexShader ? 1 : 0) + (fragmentShader ? 1 : 0);
166 	}
167 
getPixelShader()168 	sw::PixelShader *Program::getPixelShader()
169 	{
170 		return pixelBinary;
171 	}
172 
getVertexShader()173 	sw::VertexShader *Program::getVertexShader()
174 	{
175 		return vertexBinary;
176 	}
177 
bindAttributeLocation(GLuint index,const char * name)178 	void Program::bindAttributeLocation(GLuint index, const char *name)
179 	{
180 		if(index < MAX_VERTEX_ATTRIBS)
181 		{
182 			for(int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
183 			{
184 				attributeBinding[i].erase(name);
185 			}
186 
187 			attributeBinding[index].insert(name);
188 		}
189 	}
190 
getAttributeLocation(const char * name)191 	GLuint Program::getAttributeLocation(const char *name)
192 	{
193 		if(name)
194 		{
195 			for(int index = 0; index < MAX_VERTEX_ATTRIBS; index++)
196 			{
197 				if(linkedAttribute[index].name == std::string(name))
198 				{
199 					return index;
200 				}
201 			}
202 		}
203 
204 		return -1;
205 	}
206 
getAttributeStream(int attributeIndex)207 	int Program::getAttributeStream(int attributeIndex)
208 	{
209 		ASSERT(attributeIndex >= 0 && attributeIndex < MAX_VERTEX_ATTRIBS);
210 
211 		return attributeStream[attributeIndex];
212 	}
213 
214 	// 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)
getSamplerMapping(sw::SamplerType type,unsigned int samplerIndex)215 	GLint Program::getSamplerMapping(sw::SamplerType type, unsigned int samplerIndex)
216 	{
217 		GLuint logicalTextureUnit = -1;
218 
219 		switch(type)
220 		{
221 		case sw::SAMPLER_PIXEL:
222 			ASSERT(samplerIndex < sizeof(samplersPS) / sizeof(samplersPS[0]));
223 
224 			if(samplersPS[samplerIndex].active)
225 			{
226 				logicalTextureUnit = samplersPS[samplerIndex].logicalTextureUnit;
227 			}
228 			break;
229 		case sw::SAMPLER_VERTEX:
230 			ASSERT(samplerIndex < sizeof(samplersVS) / sizeof(samplersVS[0]));
231 
232 			if(samplersVS[samplerIndex].active)
233 			{
234 				logicalTextureUnit = samplersVS[samplerIndex].logicalTextureUnit;
235 			}
236 			break;
237 		default: UNREACHABLE(type);
238 		}
239 
240 		if(logicalTextureUnit < MAX_COMBINED_TEXTURE_IMAGE_UNITS)
241 		{
242 			return logicalTextureUnit;
243 		}
244 
245 		return -1;
246 	}
247 
248 	// Returns the texture type for a given sampler type and index (0-15 for the pixel shader and 0-3 for the vertex shader)
getSamplerTextureType(sw::SamplerType type,unsigned int samplerIndex)249 	TextureType Program::getSamplerTextureType(sw::SamplerType type, unsigned int samplerIndex)
250 	{
251 		switch(type)
252 		{
253 		case sw::SAMPLER_PIXEL:
254 			ASSERT(samplerIndex < sizeof(samplersPS)/sizeof(samplersPS[0]));
255 			ASSERT(samplersPS[samplerIndex].active);
256 			return samplersPS[samplerIndex].textureType;
257 		case sw::SAMPLER_VERTEX:
258 			ASSERT(samplerIndex < sizeof(samplersVS)/sizeof(samplersVS[0]));
259 			ASSERT(samplersVS[samplerIndex].active);
260 			return samplersVS[samplerIndex].textureType;
261 		default: UNREACHABLE(type);
262 		}
263 
264 		return TEXTURE_2D;
265 	}
266 
getUniformLocation(std::string name)267 	GLint Program::getUniformLocation(std::string name)
268 	{
269 		int subscript = 0;
270 
271 		// Strip any trailing array operator and retrieve the subscript
272 		size_t open = name.find_last_of('[');
273 		size_t close = name.find_last_of(']');
274 		if(open != std::string::npos && close == name.length() - 1)
275 		{
276 			subscript = atoi(name.substr(open + 1).c_str());
277 			name.erase(open);
278 		}
279 
280 		unsigned int numUniforms = uniformIndex.size();
281 		for(unsigned int location = 0; location < numUniforms; location++)
282 		{
283 			if(uniformIndex[location].name == name &&
284 			   uniformIndex[location].element == subscript)
285 			{
286 				return location;
287 			}
288 		}
289 
290 		return -1;
291 	}
292 
setUniform1fv(GLint location,GLsizei count,const GLfloat * v)293 	bool Program::setUniform1fv(GLint location, GLsizei count, const GLfloat* v)
294 	{
295 		if(location < 0 || location >= (int)uniformIndex.size())
296 		{
297 			return false;
298 		}
299 
300 		Uniform *targetUniform = uniforms[uniformIndex[location].index];
301 		targetUniform->dirty = true;
302 
303 		int size = targetUniform->size();
304 
305 		if(size == 1 && count > 1)
306 		{
307 			return false;   // Attempting to write an array to a non-array uniform is an INVALID_OPERATION
308 		}
309 
310 		count = std::min(size - (int)uniformIndex[location].element, count);
311 
312 		if(targetUniform->type == GL_FLOAT)
313 		{
314 			memcpy(targetUniform->data + uniformIndex[location].element * sizeof(GLfloat),
315 				   v, sizeof(GLfloat) * count);
316 		}
317 		else if(targetUniform->type == GL_BOOL)
318 		{
319 			GLboolean *boolParams = (GLboolean*)targetUniform->data + uniformIndex[location].element;
320 
321 			for(int i = 0; i < count; i++)
322 			{
323 				if(v[i] == 0.0f)
324 				{
325 					boolParams[i] = GL_FALSE;
326 				}
327 				else
328 				{
329 					boolParams[i] = GL_TRUE;
330 				}
331 			}
332 		}
333 		else
334 		{
335 			return false;
336 		}
337 
338 		return true;
339 	}
340 
setUniform2fv(GLint location,GLsizei count,const GLfloat * v)341 	bool Program::setUniform2fv(GLint location, GLsizei count, const GLfloat *v)
342 	{
343 		if(location < 0 || location >= (int)uniformIndex.size())
344 		{
345 			return false;
346 		}
347 
348 		Uniform *targetUniform = uniforms[uniformIndex[location].index];
349 		targetUniform->dirty = true;
350 
351 		int size = targetUniform->size();
352 
353 		if(size == 1 && count > 1)
354 		{
355 			return false;   // Attempting to write an array to a non-array uniform is an INVALID_OPERATION
356 		}
357 
358 		count = std::min(size - (int)uniformIndex[location].element, count);
359 
360 		if(targetUniform->type == GL_FLOAT_VEC2)
361 		{
362 			memcpy(targetUniform->data + uniformIndex[location].element * sizeof(GLfloat) * 2,
363 				   v, 2 * sizeof(GLfloat) * count);
364 		}
365 		else if(targetUniform->type == GL_BOOL_VEC2)
366 		{
367 			GLboolean *boolParams = (GLboolean*)targetUniform->data + uniformIndex[location].element * 2;
368 
369 			for(int i = 0; i < count * 2; i++)
370 			{
371 				if(v[i] == 0.0f)
372 				{
373 					boolParams[i] = GL_FALSE;
374 				}
375 				else
376 				{
377 					boolParams[i] = GL_TRUE;
378 				}
379 			}
380 		}
381 		else
382 		{
383 			return false;
384 		}
385 
386 		return true;
387 	}
388 
setUniform3fv(GLint location,GLsizei count,const GLfloat * v)389 	bool Program::setUniform3fv(GLint location, GLsizei count, const GLfloat *v)
390 	{
391 		if(location < 0 || location >= (int)uniformIndex.size())
392 		{
393 			return false;
394 		}
395 
396 		Uniform *targetUniform = uniforms[uniformIndex[location].index];
397 		targetUniform->dirty = true;
398 
399 		int size = targetUniform->size();
400 
401 		if(size == 1 && count > 1)
402 		{
403 			return false;   // Attempting to write an array to a non-array uniform is an INVALID_OPERATION
404 		}
405 
406 		count = std::min(size - (int)uniformIndex[location].element, count);
407 
408 		if(targetUniform->type == GL_FLOAT_VEC3)
409 		{
410 			memcpy(targetUniform->data + uniformIndex[location].element * sizeof(GLfloat) * 3,
411 				   v, 3 * sizeof(GLfloat) * count);
412 		}
413 		else if(targetUniform->type == GL_BOOL_VEC3)
414 		{
415 			GLboolean *boolParams = (GLboolean*)targetUniform->data + uniformIndex[location].element * 3;
416 
417 			for(int i = 0; i < count * 3; i++)
418 			{
419 				if(v[i] == 0.0f)
420 				{
421 					boolParams[i] = GL_FALSE;
422 				}
423 				else
424 				{
425 					boolParams[i] = GL_TRUE;
426 				}
427 			}
428 		}
429 		else
430 		{
431 			return false;
432 		}
433 
434 		return true;
435 	}
436 
setUniform4fv(GLint location,GLsizei count,const GLfloat * v)437 	bool Program::setUniform4fv(GLint location, GLsizei count, const GLfloat *v)
438 	{
439 		if(location < 0 || location >= (int)uniformIndex.size())
440 		{
441 			return false;
442 		}
443 
444 		Uniform *targetUniform = uniforms[uniformIndex[location].index];
445 		targetUniform->dirty = true;
446 
447 		int size = targetUniform->size();
448 
449 		if(size == 1 && count > 1)
450 		{
451 			return false;   // Attempting to write an array to a non-array uniform is an INVALID_OPERATION
452 		}
453 
454 		count = std::min(size - (int)uniformIndex[location].element, count);
455 
456 		if(targetUniform->type == GL_FLOAT_VEC4)
457 		{
458 			memcpy(targetUniform->data + uniformIndex[location].element * sizeof(GLfloat) * 4,
459 				   v, 4 * sizeof(GLfloat) * count);
460 		}
461 		else if(targetUniform->type == GL_BOOL_VEC4)
462 		{
463 			GLboolean *boolParams = (GLboolean*)targetUniform->data + uniformIndex[location].element * 4;
464 
465 			for(int i = 0; i < count * 4; i++)
466 			{
467 				if(v[i] == 0.0f)
468 				{
469 					boolParams[i] = GL_FALSE;
470 				}
471 				else
472 				{
473 					boolParams[i] = GL_TRUE;
474 				}
475 			}
476 		}
477 		else
478 		{
479 			return false;
480 		}
481 
482 		return true;
483 	}
484 
setUniformMatrix2fv(GLint location,GLsizei count,const GLfloat * value)485 	bool Program::setUniformMatrix2fv(GLint location, GLsizei count, const GLfloat *value)
486 	{
487 		if(location < 0 || location >= (int)uniformIndex.size())
488 		{
489 			return false;
490 		}
491 
492 		Uniform *targetUniform = uniforms[uniformIndex[location].index];
493 		targetUniform->dirty = true;
494 
495 		if(targetUniform->type != GL_FLOAT_MAT2)
496 		{
497 			return false;
498 		}
499 
500 		int size = targetUniform->size();
501 
502 		if(size == 1 && count > 1)
503 		{
504 			return false;   // Attempting to write an array to a non-array uniform is an INVALID_OPERATION
505 		}
506 
507 		count = std::min(size - (int)uniformIndex[location].element, count);
508 
509 		memcpy(targetUniform->data + uniformIndex[location].element * sizeof(GLfloat) * 4,
510 			   value, 4 * sizeof(GLfloat) * count);
511 
512 		return true;
513 	}
514 
setUniformMatrix3fv(GLint location,GLsizei count,const GLfloat * value)515 	bool Program::setUniformMatrix3fv(GLint location, GLsizei count, const GLfloat *value)
516 	{
517 		if(location < 0 || location >= (int)uniformIndex.size())
518 		{
519 			return false;
520 		}
521 
522 		Uniform *targetUniform = uniforms[uniformIndex[location].index];
523 		targetUniform->dirty = true;
524 
525 		if(targetUniform->type != GL_FLOAT_MAT3)
526 		{
527 			return false;
528 		}
529 
530 		int size = targetUniform->size();
531 
532 		if(size == 1 && count > 1)
533 		{
534 			return false;   // Attempting to write an array to a non-array uniform is an INVALID_OPERATION
535 		}
536 
537 		count = std::min(size - (int)uniformIndex[location].element, count);
538 
539 		memcpy(targetUniform->data + uniformIndex[location].element * sizeof(GLfloat) * 9,
540 			   value, 9 * sizeof(GLfloat) * count);
541 
542 		return true;
543 	}
544 
setUniformMatrix4fv(GLint location,GLsizei count,const GLfloat * value)545 	bool Program::setUniformMatrix4fv(GLint location, GLsizei count, const GLfloat *value)
546 	{
547 		if(location < 0 || location >= (int)uniformIndex.size())
548 		{
549 			return false;
550 		}
551 
552 		Uniform *targetUniform = uniforms[uniformIndex[location].index];
553 		targetUniform->dirty = true;
554 
555 		if(targetUniform->type != GL_FLOAT_MAT4)
556 		{
557 			return false;
558 		}
559 
560 		int size = targetUniform->size();
561 
562 		if(size == 1 && count > 1)
563 		{
564 			return false;   // Attempting to write an array to a non-array uniform is an INVALID_OPERATION
565 		}
566 
567 		count = std::min(size - (int)uniformIndex[location].element, count);
568 
569 		memcpy(targetUniform->data + uniformIndex[location].element * sizeof(GLfloat) * 16,
570 			   value, 16 * sizeof(GLfloat) * count);
571 
572 		return true;
573 	}
574 
setUniform1iv(GLint location,GLsizei count,const GLint * v)575 	bool Program::setUniform1iv(GLint location, GLsizei count, const GLint *v)
576 	{
577 		if(location < 0 || location >= (int)uniformIndex.size())
578 		{
579 			return false;
580 		}
581 
582 		Uniform *targetUniform = uniforms[uniformIndex[location].index];
583 		targetUniform->dirty = true;
584 
585 		int size = targetUniform->size();
586 
587 		if(size == 1 && count > 1)
588 		{
589 			return false;   // Attempting to write an array to a non-array uniform is an INVALID_OPERATION
590 		}
591 
592 		count = std::min(size - (int)uniformIndex[location].element, count);
593 
594 		if(targetUniform->type == GL_INT ||
595 		   targetUniform->type == GL_SAMPLER_2D ||
596 		   targetUniform->type == GL_SAMPLER_CUBE)
597 		{
598 			memcpy(targetUniform->data + uniformIndex[location].element * sizeof(GLint),
599 				   v, sizeof(GLint) * count);
600 		}
601 		else if(targetUniform->type == GL_BOOL)
602 		{
603 			GLboolean *boolParams = new GLboolean[count];
604 
605 			for(int i = 0; i < count; i++)
606 			{
607 				if(v[i] == 0)
608 				{
609 					boolParams[i] = GL_FALSE;
610 				}
611 				else
612 				{
613 					boolParams[i] = GL_TRUE;
614 				}
615 			}
616 
617 			memcpy(targetUniform->data + uniformIndex[location].element * sizeof(GLboolean),
618 				   boolParams, sizeof(GLboolean) * count);
619 
620 			delete[] boolParams;
621 		}
622 		else
623 		{
624 			return false;
625 		}
626 
627 		return true;
628 	}
629 
setUniform2iv(GLint location,GLsizei count,const GLint * v)630 	bool Program::setUniform2iv(GLint location, GLsizei count, const GLint *v)
631 	{
632 		if(location < 0 || location >= (int)uniformIndex.size())
633 		{
634 			return false;
635 		}
636 
637 		Uniform *targetUniform = uniforms[uniformIndex[location].index];
638 		targetUniform->dirty = true;
639 
640 		int size = targetUniform->size();
641 
642 		if(size == 1 && count > 1)
643 		{
644 			return false;   // Attempting to write an array to a non-array uniform is an INVALID_OPERATION
645 		}
646 
647 		count = std::min(size - (int)uniformIndex[location].element, count);
648 
649 		if(targetUniform->type == GL_INT_VEC2)
650 		{
651 			memcpy(targetUniform->data + uniformIndex[location].element * sizeof(GLint) * 2,
652 				   v, 2 * sizeof(GLint) * count);
653 		}
654 		else if(targetUniform->type == GL_BOOL_VEC2)
655 		{
656 			GLboolean *boolParams = new GLboolean[count * 2];
657 
658 			for(int i = 0; i < count * 2; i++)
659 			{
660 				if(v[i] == 0)
661 				{
662 					boolParams[i] = GL_FALSE;
663 				}
664 				else
665 				{
666 					boolParams[i] = GL_TRUE;
667 				}
668 			}
669 
670 			memcpy(targetUniform->data + uniformIndex[location].element * sizeof(GLboolean) * 2,
671 				   boolParams, 2 * sizeof(GLboolean) * count);
672 
673 			delete[] boolParams;
674 		}
675 		else
676 		{
677 			return false;
678 		}
679 
680 		return true;
681 	}
682 
setUniform3iv(GLint location,GLsizei count,const GLint * v)683 	bool Program::setUniform3iv(GLint location, GLsizei count, const GLint *v)
684 	{
685 		if(location < 0 || location >= (int)uniformIndex.size())
686 		{
687 			return false;
688 		}
689 
690 		Uniform *targetUniform = uniforms[uniformIndex[location].index];
691 		targetUniform->dirty = true;
692 
693 		int size = targetUniform->size();
694 
695 		if(size == 1 && count > 1)
696 		{
697 			return false;   // Attempting to write an array to a non-array uniform is an INVALID_OPERATION
698 		}
699 
700 		count = std::min(size - (int)uniformIndex[location].element, count);
701 
702 		if(targetUniform->type == GL_INT_VEC3)
703 		{
704 			memcpy(targetUniform->data + uniformIndex[location].element * sizeof(GLint) * 3,
705 				   v, 3 * sizeof(GLint) * count);
706 		}
707 		else if(targetUniform->type == GL_BOOL_VEC3)
708 		{
709 			GLboolean *boolParams = new GLboolean[count * 3];
710 
711 			for(int i = 0; i < count * 3; i++)
712 			{
713 				if(v[i] == 0)
714 				{
715 					boolParams[i] = GL_FALSE;
716 				}
717 				else
718 				{
719 					boolParams[i] = GL_TRUE;
720 				}
721 			}
722 
723 			memcpy(targetUniform->data + uniformIndex[location].element * sizeof(GLboolean) * 3,
724 				   boolParams, 3 * sizeof(GLboolean) * count);
725 
726 			delete[] boolParams;
727 		}
728 		else
729 		{
730 			return false;
731 		}
732 
733 		return true;
734 	}
735 
setUniform4iv(GLint location,GLsizei count,const GLint * v)736 	bool Program::setUniform4iv(GLint location, GLsizei count, const GLint *v)
737 	{
738 		if(location < 0 || location >= (int)uniformIndex.size())
739 		{
740 			return false;
741 		}
742 
743 		Uniform *targetUniform = uniforms[uniformIndex[location].index];
744 		targetUniform->dirty = true;
745 
746 		int size = targetUniform->size();
747 
748 		if(size == 1 && count > 1)
749 		{
750 			return false;   // Attempting to write an array to a non-array uniform is an INVALID_OPERATION
751 		}
752 
753 		count = std::min(size - (int)uniformIndex[location].element, count);
754 
755 		if(targetUniform->type == GL_INT_VEC4)
756 		{
757 			memcpy(targetUniform->data + uniformIndex[location].element * sizeof(GLint) * 4,
758 				   v, 4 * sizeof(GLint) * count);
759 		}
760 		else if(targetUniform->type == GL_BOOL_VEC4)
761 		{
762 			GLboolean *boolParams = new GLboolean[count * 4];
763 
764 			for(int i = 0; i < count * 4; i++)
765 			{
766 				if(v[i] == 0)
767 				{
768 					boolParams[i] = GL_FALSE;
769 				}
770 				else
771 				{
772 					boolParams[i] = GL_TRUE;
773 				}
774 			}
775 
776 			memcpy(targetUniform->data + uniformIndex[location].element * sizeof(GLboolean) * 4,
777 				   boolParams, 4 * sizeof(GLboolean) * count);
778 
779 			delete[] boolParams;
780 		}
781 		else
782 		{
783 			return false;
784 		}
785 
786 		return true;
787 	}
788 
getUniformfv(GLint location,GLsizei * bufSize,GLfloat * params)789 	bool Program::getUniformfv(GLint location, GLsizei *bufSize, GLfloat *params)
790 	{
791 		if(location < 0 || location >= (int)uniformIndex.size())
792 		{
793 			return false;
794 		}
795 
796 		Uniform *targetUniform = uniforms[uniformIndex[location].index];
797 		unsigned int count = UniformComponentCount(targetUniform->type);
798 
799 		// Sized query - ensure the provided buffer is large enough
800 		if(bufSize && static_cast<unsigned int>(*bufSize) < count * sizeof(GLfloat))
801 		{
802 			return false;
803 		}
804 
805 		switch(UniformComponentType(targetUniform->type))
806 		{
807 		case GL_BOOL:
808 			{
809 				GLboolean *boolParams = (GLboolean*)targetUniform->data + uniformIndex[location].element * count;
810 
811 				for(unsigned int i = 0; i < count; i++)
812 				{
813 					params[i] = (boolParams[i] == GL_FALSE) ? 0.0f : 1.0f;
814 				}
815 			}
816 			break;
817 		case GL_FLOAT:
818 			memcpy(params, targetUniform->data + uniformIndex[location].element * count * sizeof(GLfloat),
819 				   count * sizeof(GLfloat));
820 			break;
821 		case GL_INT:
822 			{
823 				GLint *intParams = (GLint*)targetUniform->data + uniformIndex[location].element * count;
824 
825 				for(unsigned int i = 0; i < count; i++)
826 				{
827 					params[i] = (float)intParams[i];
828 				}
829 			}
830 			break;
831 		default: UNREACHABLE(targetUniform->type);
832 		}
833 
834 		return true;
835 	}
836 
getUniformiv(GLint location,GLsizei * bufSize,GLint * params)837 	bool Program::getUniformiv(GLint location, GLsizei *bufSize, GLint *params)
838 	{
839 		if(location < 0 || location >= (int)uniformIndex.size())
840 		{
841 			return false;
842 		}
843 
844 		Uniform *targetUniform = uniforms[uniformIndex[location].index];
845 		unsigned int count = UniformComponentCount(targetUniform->type);
846 
847 		// Sized query - ensure the provided buffer is large enough
848 		if(bufSize && static_cast<unsigned int>(*bufSize) < count *sizeof(GLint))
849 		{
850 			return false;
851 		}
852 
853 		switch(UniformComponentType(targetUniform->type))
854 		{
855 		case GL_BOOL:
856 			{
857 				GLboolean *boolParams = targetUniform->data + uniformIndex[location].element * count;
858 
859 				for(unsigned int i = 0; i < count; i++)
860 				{
861 					params[i] = (GLint)boolParams[i];
862 				}
863 			}
864 			break;
865 		case GL_FLOAT:
866 			{
867 				GLfloat *floatParams = (GLfloat*)targetUniform->data + uniformIndex[location].element * count;
868 
869 				for(unsigned int i = 0; i < count; i++)
870 				{
871 					params[i] = (GLint)floatParams[i];
872 				}
873 			}
874 			break;
875 		case GL_INT:
876 			memcpy(params, targetUniform->data + uniformIndex[location].element * count * sizeof(GLint),
877 				   count * sizeof(GLint));
878 			break;
879 		default: UNREACHABLE(targetUniform->type);
880 		}
881 
882 		return true;
883 	}
884 
dirtyAllUniforms()885 	void Program::dirtyAllUniforms()
886 	{
887 		unsigned int numUniforms = uniforms.size();
888 		for(unsigned int index = 0; index < numUniforms; index++)
889 		{
890 			uniforms[index]->dirty = true;
891 		}
892 	}
893 
894 	// Applies all the uniforms set for this program object to the device
applyUniforms()895 	void Program::applyUniforms()
896 	{
897 		unsigned int numUniforms = uniformIndex.size();
898 		for(unsigned int location = 0; location < numUniforms; location++)
899 		{
900 			if(uniformIndex[location].element != 0)
901 			{
902 				continue;
903 			}
904 
905 			Uniform *targetUniform = uniforms[uniformIndex[location].index];
906 
907 			if(targetUniform->dirty)
908 			{
909 				int size = targetUniform->size();
910 				GLfloat *f = (GLfloat*)targetUniform->data;
911 				GLint *i = (GLint*)targetUniform->data;
912 				GLboolean *b = (GLboolean*)targetUniform->data;
913 
914 				switch(targetUniform->type)
915 				{
916 				case GL_BOOL:       applyUniform1bv(location, size, b);       break;
917 				case GL_BOOL_VEC2:  applyUniform2bv(location, size, b);       break;
918 				case GL_BOOL_VEC3:  applyUniform3bv(location, size, b);       break;
919 				case GL_BOOL_VEC4:  applyUniform4bv(location, size, b);       break;
920 				case GL_FLOAT:      applyUniform1fv(location, size, f);       break;
921 				case GL_FLOAT_VEC2: applyUniform2fv(location, size, f);       break;
922 				case GL_FLOAT_VEC3: applyUniform3fv(location, size, f);       break;
923 				case GL_FLOAT_VEC4: applyUniform4fv(location, size, f);       break;
924 				case GL_FLOAT_MAT2: applyUniformMatrix2fv(location, size, f); break;
925 				case GL_FLOAT_MAT3: applyUniformMatrix3fv(location, size, f); break;
926 				case GL_FLOAT_MAT4: applyUniformMatrix4fv(location, size, f); break;
927 				case GL_SAMPLER_2D:
928 				case GL_SAMPLER_CUBE:
929 				case GL_INT:        applyUniform1iv(location, size, i);       break;
930 				case GL_INT_VEC2:   applyUniform2iv(location, size, i);       break;
931 				case GL_INT_VEC3:   applyUniform3iv(location, size, i);       break;
932 				case GL_INT_VEC4:   applyUniform4iv(location, size, i);       break;
933 				default:
934 					UNREACHABLE(targetUniform->type);
935 				}
936 
937 				targetUniform->dirty = false;
938 			}
939 		}
940 	}
941 
942 	// Packs varyings into generic varying registers.
943 	// Returns the number of used varying registers, or -1 if unsuccesful
packVaryings(const glsl::Varying * packing[][4])944 	int Program::packVaryings(const glsl::Varying *packing[][4])
945 	{
946 		for(glsl::VaryingList::iterator varying = fragmentShader->varyings.begin(); varying != fragmentShader->varyings.end(); varying++)
947 		{
948 			int n = VariableRowCount(varying->type) * varying->size();
949 			int m = VariableColumnCount(varying->type);
950 			bool success = false;
951 
952 			if(m == 2 || m == 3 || m == 4)
953 			{
954 				for(int r = 0; r <= MAX_VARYING_VECTORS - n && !success; r++)
955 				{
956 					bool available = true;
957 
958 					for(int y = 0; y < n && available; y++)
959 					{
960 						for(int x = 0; x < m && available; x++)
961 						{
962 							if(packing[r + y][x])
963 							{
964 								available = false;
965 							}
966 						}
967 					}
968 
969 					if(available)
970 					{
971 						varying->reg = r;
972 						varying->col = 0;
973 
974 						for(int y = 0; y < n; y++)
975 						{
976 							for(int x = 0; x < m; x++)
977 							{
978 								packing[r + y][x] = &*varying;
979 							}
980 						}
981 
982 						success = true;
983 					}
984 				}
985 
986 				if(!success && m == 2)
987 				{
988 					for(int r = MAX_VARYING_VECTORS - n; r >= 0 && !success; r--)
989 					{
990 						bool available = true;
991 
992 						for(int y = 0; y < n && available; y++)
993 						{
994 							for(int x = 2; x < 4 && available; x++)
995 							{
996 								if(packing[r + y][x])
997 								{
998 									available = false;
999 								}
1000 							}
1001 						}
1002 
1003 						if(available)
1004 						{
1005 							varying->reg = r;
1006 							varying->col = 2;
1007 
1008 							for(int y = 0; y < n; y++)
1009 							{
1010 								for(int x = 2; x < 4; x++)
1011 								{
1012 									packing[r + y][x] = &*varying;
1013 								}
1014 							}
1015 
1016 							success = true;
1017 						}
1018 					}
1019 				}
1020 			}
1021 			else if(m == 1)
1022 			{
1023 				int space[4] = {0};
1024 
1025 				for(int y = 0; y < MAX_VARYING_VECTORS; y++)
1026 				{
1027 					for(int x = 0; x < 4; x++)
1028 					{
1029 						space[x] += packing[y][x] ? 0 : 1;
1030 					}
1031 				}
1032 
1033 				int column = 0;
1034 
1035 				for(int x = 0; x < 4; x++)
1036 				{
1037 					if(space[x] >= n && space[x] < space[column])
1038 					{
1039 						column = x;
1040 					}
1041 				}
1042 
1043 				if(space[column] >= n)
1044 				{
1045 					for(int r = 0; r < MAX_VARYING_VECTORS; r++)
1046 					{
1047 						if(!packing[r][column])
1048 						{
1049 							varying->reg = r;
1050 
1051 							for(int y = r; y < r + n; y++)
1052 							{
1053 								packing[y][column] = &*varying;
1054 							}
1055 
1056 							break;
1057 						}
1058 					}
1059 
1060 					varying->col = column;
1061 
1062 					success = true;
1063 				}
1064 			}
1065 			else UNREACHABLE(m);
1066 
1067 			if(!success)
1068 			{
1069 				appendToInfoLog("Could not pack varying %s", varying->name.c_str());
1070 
1071 				return -1;
1072 			}
1073 		}
1074 
1075 		// Return the number of used registers
1076 		int registers = 0;
1077 
1078 		for(int r = 0; r < MAX_VARYING_VECTORS; r++)
1079 		{
1080 			if(packing[r][0] || packing[r][1] || packing[r][2] || packing[r][3])
1081 			{
1082 				registers++;
1083 			}
1084 		}
1085 
1086 		return registers;
1087 	}
1088 
linkVaryings()1089 	bool Program::linkVaryings()
1090 	{
1091 		for(glsl::VaryingList::iterator input = fragmentShader->varyings.begin(); input != fragmentShader->varyings.end(); input++)
1092 		{
1093 			bool matched = false;
1094 
1095 			for(glsl::VaryingList::iterator output = vertexShader->varyings.begin(); output != vertexShader->varyings.end(); output++)
1096 			{
1097 				if(output->name == input->name)
1098 				{
1099 					if(output->type != input->type || output->size() != input->size())
1100 					{
1101 						appendToInfoLog("Type of vertex varying %s does not match that of the fragment varying", output->name.c_str());
1102 
1103 						return false;
1104 					}
1105 
1106 					matched = true;
1107 					break;
1108 				}
1109 			}
1110 
1111 			if(!matched)
1112 			{
1113 				appendToInfoLog("Fragment varying %s does not match any vertex varying", input->name.c_str());
1114 
1115 				return false;
1116 			}
1117 		}
1118 
1119 		glsl::VaryingList &psVaryings = fragmentShader->varyings;
1120 		glsl::VaryingList &vsVaryings = vertexShader->varyings;
1121 
1122 		for(glsl::VaryingList::iterator output = vsVaryings.begin(); output != vsVaryings.end(); output++)
1123 		{
1124 			for(glsl::VaryingList::iterator input = psVaryings.begin(); input != psVaryings.end(); input++)
1125 			{
1126 				if(output->name == input->name)
1127 				{
1128 					int in = input->reg;
1129 					int out = output->reg;
1130 					int components = VariableColumnCount(output->type);
1131 					int registers = VariableRowCount(output->type) * output->size();
1132 
1133 					ASSERT(in >= 0);
1134 
1135 					if(in + registers > MAX_VARYING_VECTORS)
1136 					{
1137 						appendToInfoLog("Too many varyings");
1138 						return false;
1139 					}
1140 
1141 					if(out >= 0)
1142 					{
1143 						if(out + registers > MAX_VARYING_VECTORS)
1144 						{
1145 							appendToInfoLog("Too many varyings");
1146 							return false;
1147 						}
1148 
1149 						for(int i = 0; i < registers; i++)
1150 						{
1151 							if(components >= 1) vertexBinary->output[out + i][0] = sw::Shader::Semantic(sw::Shader::USAGE_COLOR, in + i);
1152 							if(components >= 2) vertexBinary->output[out + i][1] = sw::Shader::Semantic(sw::Shader::USAGE_COLOR, in + i);
1153 							if(components >= 3) vertexBinary->output[out + i][2] = sw::Shader::Semantic(sw::Shader::USAGE_COLOR, in + i);
1154 							if(components >= 4) vertexBinary->output[out + i][3] = sw::Shader::Semantic(sw::Shader::USAGE_COLOR, in + i);
1155 						}
1156 					}
1157 					else   // Vertex varying is declared but not written to
1158 					{
1159 						for(int i = 0; i < registers; i++)
1160 						{
1161 							if(components >= 1) pixelBinary->semantic[in + i][0] = sw::Shader::Semantic();
1162 							if(components >= 2) pixelBinary->semantic[in + i][1] = sw::Shader::Semantic();
1163 							if(components >= 3) pixelBinary->semantic[in + i][2] = sw::Shader::Semantic();
1164 							if(components >= 4) pixelBinary->semantic[in + i][3] = sw::Shader::Semantic();
1165 						}
1166 					}
1167 
1168 					break;
1169 				}
1170 			}
1171 		}
1172 
1173 		return true;
1174 	}
1175 
1176 	// Links the code of the vertex and pixel shader by matching up their varyings,
1177 	// compiling them into binaries, determining the attribute mappings, and collecting
1178 	// a list of uniforms
link()1179 	void Program::link()
1180 	{
1181 		unlink();
1182 
1183 		if(!fragmentShader || !fragmentShader->isCompiled())
1184 		{
1185 			return;
1186 		}
1187 
1188 		if(!vertexShader || !vertexShader->isCompiled())
1189 		{
1190 			return;
1191 		}
1192 
1193 		vertexBinary = new sw::VertexShader(vertexShader->getVertexShader());
1194 		pixelBinary = new sw::PixelShader(fragmentShader->getPixelShader());
1195 
1196 		if(!linkVaryings())
1197 		{
1198 			return;
1199 		}
1200 
1201 		if(!linkAttributes())
1202 		{
1203 			return;
1204 		}
1205 
1206 		if(!linkUniforms(fragmentShader))
1207 		{
1208 			return;
1209 		}
1210 
1211 		if(!linkUniforms(vertexShader))
1212 		{
1213 			return;
1214 		}
1215 
1216 		linked = true;   // Success
1217 	}
1218 
1219 	// Determines the mapping between GL attributes and vertex stream usage indices
linkAttributes()1220 	bool Program::linkAttributes()
1221 	{
1222 		unsigned int usedLocations = 0;
1223 
1224 		// Link attributes that have a binding location
1225 		for(glsl::ActiveAttributes::iterator attribute = vertexShader->activeAttributes.begin(); attribute != vertexShader->activeAttributes.end(); attribute++)
1226 		{
1227 			int location = getAttributeBinding(attribute->name);
1228 
1229 			if(location != -1)   // Set by glBindAttribLocation
1230 			{
1231 				if(!linkedAttribute[location].name.empty())
1232 				{
1233 					// Multiple active attributes bound to the same location; not an error
1234 				}
1235 
1236 				linkedAttribute[location] = *attribute;
1237 
1238 				int rows = VariableRowCount(attribute->type);
1239 
1240 				if(rows + location > MAX_VERTEX_ATTRIBS)
1241 				{
1242 					appendToInfoLog("Active attribute (%s) at location %d is too big to fit", attribute->name.c_str(), location);
1243 					return false;
1244 				}
1245 
1246 				for(int i = 0; i < rows; i++)
1247 				{
1248 					usedLocations |= 1 << (location + i);
1249 				}
1250 			}
1251 		}
1252 
1253 		// Link attributes that don't have a binding location
1254 		for(glsl::ActiveAttributes::iterator attribute = vertexShader->activeAttributes.begin(); attribute != vertexShader->activeAttributes.end(); attribute++)
1255 		{
1256 			int location = getAttributeBinding(attribute->name);
1257 
1258 			if(location == -1)   // Not set by glBindAttribLocation
1259 			{
1260 				int rows = VariableRowCount(attribute->type);
1261 				int availableIndex = AllocateFirstFreeBits(&usedLocations, rows, MAX_VERTEX_ATTRIBS);
1262 
1263 				if(availableIndex == -1 || availableIndex + rows > MAX_VERTEX_ATTRIBS)
1264 				{
1265 					appendToInfoLog("Too many active attributes (%s)", attribute->name.c_str());
1266 					return false;   // Fail to link
1267 				}
1268 
1269 				linkedAttribute[availableIndex] = *attribute;
1270 			}
1271 		}
1272 
1273 		for(int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; )
1274 		{
1275 			int index = vertexShader->getSemanticIndex(linkedAttribute[attributeIndex].name);
1276 			int rows = std::max(VariableRowCount(linkedAttribute[attributeIndex].type), 1);
1277 
1278 			for(int r = 0; r < rows; r++)
1279 			{
1280 				attributeStream[attributeIndex++] = index++;
1281 			}
1282 		}
1283 
1284 		return true;
1285 	}
1286 
getAttributeBinding(const std::string & name)1287 	int Program::getAttributeBinding(const std::string &name)
1288 	{
1289 		for(int location = 0; location < MAX_VERTEX_ATTRIBS; location++)
1290 		{
1291 			if(attributeBinding[location].find(name) != attributeBinding[location].end())
1292 			{
1293 				return location;
1294 			}
1295 		}
1296 
1297 		return -1;
1298 	}
1299 
linkUniforms(Shader * shader)1300 	bool Program::linkUniforms(Shader *shader)
1301 	{
1302 		const glsl::ActiveUniforms &activeUniforms = shader->activeUniforms;
1303 
1304 		for(unsigned int uniformIndex = 0; uniformIndex < activeUniforms.size(); uniformIndex++)
1305 		{
1306 			const glsl::Uniform &uniform = activeUniforms[uniformIndex];
1307 
1308 			if(!defineUniform(shader->getType(), uniform.type, uniform.precision, uniform.name, uniform.arraySize, uniform.registerIndex))
1309 			{
1310 				return false;
1311 			}
1312 		}
1313 
1314 		return true;
1315 	}
1316 
defineUniform(GLenum shader,GLenum type,GLenum precision,const std::string & name,unsigned int arraySize,int registerIndex)1317 	bool Program::defineUniform(GLenum shader, GLenum type, GLenum precision, const std::string &name, unsigned int arraySize, int registerIndex)
1318 	{
1319 		if(type == GL_SAMPLER_2D || type == GL_SAMPLER_CUBE)
1320 		{
1321 			int index = registerIndex;
1322 
1323 			do
1324 			{
1325 				if(shader == GL_VERTEX_SHADER)
1326 				{
1327 					if(index < MAX_VERTEX_TEXTURE_IMAGE_UNITS)
1328 					{
1329 						samplersVS[index].active = true;
1330 						samplersVS[index].textureType = (type == GL_SAMPLER_CUBE) ? TEXTURE_CUBE : TEXTURE_2D;
1331 						samplersVS[index].logicalTextureUnit = 0;
1332 					}
1333 					else
1334 					{
1335 					   appendToInfoLog("Vertex shader sampler count exceeds MAX_VERTEX_TEXTURE_IMAGE_UNITS (%d).", MAX_VERTEX_TEXTURE_IMAGE_UNITS);
1336 					   return false;
1337 					}
1338 				}
1339 				else if(shader == GL_FRAGMENT_SHADER)
1340 				{
1341 					if(index < MAX_TEXTURE_IMAGE_UNITS)
1342 					{
1343 						samplersPS[index].active = true;
1344 						samplersPS[index].textureType = (type == GL_SAMPLER_CUBE) ? TEXTURE_CUBE : TEXTURE_2D;
1345 						samplersPS[index].logicalTextureUnit = 0;
1346 					}
1347 					else
1348 					{
1349 						appendToInfoLog("Pixel shader sampler count exceeds MAX_TEXTURE_IMAGE_UNITS (%d).", MAX_TEXTURE_IMAGE_UNITS);
1350 						return false;
1351 					}
1352 				}
1353 				else UNREACHABLE(shader);
1354 
1355 				index++;
1356 			}
1357 			while(index < registerIndex + static_cast<int>(arraySize));
1358 		}
1359 
1360 		Uniform *uniform = 0;
1361 		GLint location = getUniformLocation(name);
1362 
1363 		if(location >= 0)   // Previously defined, types must match
1364 		{
1365 			uniform = uniforms[uniformIndex[location].index];
1366 
1367 			if(uniform->type != type)
1368 			{
1369 				appendToInfoLog("Types for uniform %s do not match between the vertex and fragment shader", uniform->name.c_str());
1370 				return false;
1371 			}
1372 
1373 			if(uniform->precision != precision)
1374 			{
1375 				appendToInfoLog("Precisions for uniform %s do not match between the vertex and fragment shader", uniform->name.c_str());
1376 				return false;
1377 			}
1378 		}
1379 		else
1380 		{
1381 			uniform = new Uniform(type, precision, name, arraySize);
1382 		}
1383 
1384 		if(!uniform)
1385 		{
1386 			return false;
1387 		}
1388 
1389 		if(shader == GL_VERTEX_SHADER)
1390 		{
1391 			uniform->vsRegisterIndex = registerIndex;
1392 		}
1393 		else if(shader == GL_FRAGMENT_SHADER)
1394 		{
1395 			uniform->psRegisterIndex = registerIndex;
1396 		}
1397 		else UNREACHABLE(shader);
1398 
1399 		if(location == -1)   // Not previously defined
1400 		{
1401 			uniforms.push_back(uniform);
1402 			unsigned int index = uniforms.size() - 1;
1403 
1404 			for(int i = 0; i < uniform->size(); i++)
1405 			{
1406 				uniformIndex.push_back(UniformLocation(name, i, index));
1407 			}
1408 		}
1409 
1410 		if(shader == GL_VERTEX_SHADER)
1411 		{
1412 			if(registerIndex + uniform->registerCount() > MAX_VERTEX_UNIFORM_VECTORS)
1413 			{
1414 				appendToInfoLog("Vertex shader active uniforms exceed GL_MAX_VERTEX_UNIFORM_VECTORS (%d)", MAX_VERTEX_UNIFORM_VECTORS);
1415 				return false;
1416 			}
1417 		}
1418 		else if(shader == GL_FRAGMENT_SHADER)
1419 		{
1420 			if(registerIndex + uniform->registerCount() > MAX_FRAGMENT_UNIFORM_VECTORS)
1421 			{
1422 				appendToInfoLog("Fragment shader active uniforms exceed GL_MAX_FRAGMENT_UNIFORM_VECTORS (%d)", MAX_FRAGMENT_UNIFORM_VECTORS);
1423 				return false;
1424 			}
1425 		}
1426 		else UNREACHABLE(shader);
1427 
1428 		return true;
1429 	}
1430 
applyUniform1bv(GLint location,GLsizei count,const GLboolean * v)1431 	bool Program::applyUniform1bv(GLint location, GLsizei count, const GLboolean *v)
1432 	{
1433 		int vector[MAX_UNIFORM_VECTORS][4];
1434 
1435 		for(int i = 0; i < count; i++)
1436 		{
1437 			vector[i][0] = (v[0] == GL_FALSE ? 0x00000000 : 0xFFFFFFFF);
1438 			vector[i][1] = 0;
1439 			vector[i][2] = 0;
1440 			vector[i][3] = 0;
1441 
1442 			v += 1;
1443 		}
1444 
1445 		Uniform *targetUniform = uniforms[uniformIndex[location].index];
1446 
1447 		if(targetUniform->psRegisterIndex != -1)
1448 		{
1449 			device->setPixelShaderConstantF(targetUniform->psRegisterIndex, (float*)vector, targetUniform->registerCount());
1450 		}
1451 
1452 		if(targetUniform->vsRegisterIndex != -1)
1453 		{
1454 			device->setVertexShaderConstantF(targetUniform->vsRegisterIndex, (float*)vector, targetUniform->registerCount());
1455 		}
1456 
1457 		return true;
1458 	}
1459 
applyUniform2bv(GLint location,GLsizei count,const GLboolean * v)1460 	bool Program::applyUniform2bv(GLint location, GLsizei count, const GLboolean *v)
1461 	{
1462 		int vector[MAX_UNIFORM_VECTORS][4];
1463 
1464 		for(int i = 0; i < count; i++)
1465 		{
1466 			vector[i][0] = (v[0] == GL_FALSE ? 0x00000000 : 0xFFFFFFFF);
1467 			vector[i][1] = (v[1] == GL_FALSE ? 0x00000000 : 0xFFFFFFFF);
1468 			vector[i][2] = 0;
1469 			vector[i][3] = 0;
1470 
1471 			v += 2;
1472 		}
1473 
1474 		Uniform *targetUniform = uniforms[uniformIndex[location].index];
1475 
1476 		if(targetUniform->psRegisterIndex != -1)
1477 		{
1478 			device->setPixelShaderConstantF(targetUniform->psRegisterIndex, (float*)vector, targetUniform->registerCount());
1479 		}
1480 
1481 		if(targetUniform->vsRegisterIndex != -1)
1482 		{
1483 			device->setVertexShaderConstantF(targetUniform->vsRegisterIndex, (float*)vector, targetUniform->registerCount());
1484 		}
1485 
1486 		return true;
1487 	}
1488 
applyUniform3bv(GLint location,GLsizei count,const GLboolean * v)1489 	bool Program::applyUniform3bv(GLint location, GLsizei count, const GLboolean *v)
1490 	{
1491 		int vector[MAX_UNIFORM_VECTORS][4];
1492 
1493 		for(int i = 0; i < count; i++)
1494 		{
1495 			vector[i][0] = (v[0] == GL_FALSE ? 0x00000000 : 0xFFFFFFFF);
1496 			vector[i][1] = (v[1] == GL_FALSE ? 0x00000000 : 0xFFFFFFFF);
1497 			vector[i][2] = (v[2] == GL_FALSE ? 0x00000000 : 0xFFFFFFFF);
1498 			vector[i][3] = 0;
1499 
1500 			v += 3;
1501 		}
1502 
1503 		Uniform *targetUniform = uniforms[uniformIndex[location].index];
1504 
1505 		if(targetUniform->psRegisterIndex != -1)
1506 		{
1507 			device->setPixelShaderConstantF(targetUniform->psRegisterIndex, (float*)vector, targetUniform->registerCount());
1508 		}
1509 
1510 		if(targetUniform->vsRegisterIndex != -1)
1511 		{
1512 			device->setVertexShaderConstantF(targetUniform->vsRegisterIndex, (float*)vector, targetUniform->registerCount());
1513 		}
1514 
1515 		return true;
1516 	}
1517 
applyUniform4bv(GLint location,GLsizei count,const GLboolean * v)1518 	bool Program::applyUniform4bv(GLint location, GLsizei count, const GLboolean *v)
1519 	{
1520 		int vector[MAX_UNIFORM_VECTORS][4];
1521 
1522 		for(int i = 0; i < count; i++)
1523 		{
1524 			vector[i][0] = (v[0] == GL_FALSE ? 0x00000000 : 0xFFFFFFFF);
1525 			vector[i][1] = (v[1] == GL_FALSE ? 0x00000000 : 0xFFFFFFFF);
1526 			vector[i][2] = (v[2] == GL_FALSE ? 0x00000000 : 0xFFFFFFFF);
1527 			vector[i][3] = (v[3] == GL_FALSE ? 0x00000000 : 0xFFFFFFFF);
1528 
1529 			v += 4;
1530 		}
1531 
1532 		Uniform *targetUniform = uniforms[uniformIndex[location].index];
1533 
1534 		if(targetUniform->psRegisterIndex != -1)
1535 		{
1536 			device->setPixelShaderConstantF(targetUniform->psRegisterIndex, (float*)vector, targetUniform->registerCount());
1537 		}
1538 
1539 		if(targetUniform->vsRegisterIndex != -1)
1540 		{
1541 			device->setVertexShaderConstantF(targetUniform->vsRegisterIndex, (float*)vector, targetUniform->registerCount());
1542 		}
1543 
1544 		return true;
1545 	}
1546 
applyUniform1fv(GLint location,GLsizei count,const GLfloat * v)1547 	bool Program::applyUniform1fv(GLint location, GLsizei count, const GLfloat *v)
1548 	{
1549 		float vector[MAX_UNIFORM_VECTORS][4];
1550 
1551 		for(int i = 0; i < count; i++)
1552 		{
1553 			vector[i][0] = v[0];
1554 			vector[i][1] = 0;
1555 			vector[i][2] = 0;
1556 			vector[i][3] = 0;
1557 
1558 			v += 1;
1559 		}
1560 
1561 		Uniform *targetUniform = uniforms[uniformIndex[location].index];
1562 
1563 		if(targetUniform->psRegisterIndex != -1)
1564 		{
1565 			device->setPixelShaderConstantF(targetUniform->psRegisterIndex, (float*)vector, targetUniform->registerCount());
1566 		}
1567 
1568 		if(targetUniform->vsRegisterIndex != -1)
1569 		{
1570 			device->setVertexShaderConstantF(targetUniform->vsRegisterIndex, (float*)vector, targetUniform->registerCount());
1571 		}
1572 
1573 		return true;
1574 	}
1575 
applyUniform2fv(GLint location,GLsizei count,const GLfloat * v)1576 	bool Program::applyUniform2fv(GLint location, GLsizei count, const GLfloat *v)
1577 	{
1578 		float vector[MAX_UNIFORM_VECTORS][4];
1579 
1580 		for(int i = 0; i < count; i++)
1581 		{
1582 			vector[i][0] = v[0];
1583 			vector[i][1] = v[1];
1584 			vector[i][2] = 0;
1585 			vector[i][3] = 0;
1586 
1587 			v += 2;
1588 		}
1589 
1590 		Uniform *targetUniform = uniforms[uniformIndex[location].index];
1591 
1592 		if(targetUniform->psRegisterIndex != -1)
1593 		{
1594 			device->setPixelShaderConstantF(targetUniform->psRegisterIndex, (float*)vector, targetUniform->registerCount());
1595 		}
1596 
1597 		if(targetUniform->vsRegisterIndex != -1)
1598 		{
1599 			device->setVertexShaderConstantF(targetUniform->vsRegisterIndex, (float*)vector, targetUniform->registerCount());
1600 		}
1601 
1602 		return true;
1603 	}
1604 
applyUniform3fv(GLint location,GLsizei count,const GLfloat * v)1605 	bool Program::applyUniform3fv(GLint location, GLsizei count, const GLfloat *v)
1606 	{
1607 		float vector[MAX_UNIFORM_VECTORS][4];
1608 
1609 		for(int i = 0; i < count; i++)
1610 		{
1611 			vector[i][0] = v[0];
1612 			vector[i][1] = v[1];
1613 			vector[i][2] = v[2];
1614 			vector[i][3] = 0;
1615 
1616 			v += 3;
1617 		}
1618 
1619 		Uniform *targetUniform = uniforms[uniformIndex[location].index];
1620 
1621 		if(targetUniform->psRegisterIndex != -1)
1622 		{
1623 			device->setPixelShaderConstantF(targetUniform->psRegisterIndex, (float*)vector, targetUniform->registerCount());
1624 		}
1625 
1626 		if(targetUniform->vsRegisterIndex != -1)
1627 		{
1628 			device->setVertexShaderConstantF(targetUniform->vsRegisterIndex, (float*)vector, targetUniform->registerCount());
1629 		}
1630 
1631 		return true;
1632 	}
1633 
applyUniform4fv(GLint location,GLsizei count,const GLfloat * v)1634 	bool Program::applyUniform4fv(GLint location, GLsizei count, const GLfloat *v)
1635 	{
1636 		Uniform *targetUniform = uniforms[uniformIndex[location].index];
1637 
1638 		if(targetUniform->psRegisterIndex != -1)
1639 		{
1640 			device->setPixelShaderConstantF(targetUniform->psRegisterIndex, (float*)v, targetUniform->registerCount());
1641 		}
1642 
1643 		if(targetUniform->vsRegisterIndex != -1)
1644 		{
1645 			device->setVertexShaderConstantF(targetUniform->vsRegisterIndex, (float*)v, targetUniform->registerCount());
1646 		}
1647 
1648 		return true;
1649 	}
1650 
applyUniformMatrix2fv(GLint location,GLsizei count,const GLfloat * value)1651 	bool Program::applyUniformMatrix2fv(GLint location, GLsizei count, const GLfloat *value)
1652 	{
1653 		float matrix[(MAX_UNIFORM_VECTORS + 1) / 2][2][4];
1654 
1655 		for(int i = 0; i < count; i++)
1656 		{
1657 			matrix[i][0][0] = value[0];	matrix[i][0][1] = value[1];	matrix[i][0][2] = 0; matrix[i][0][3] = 0;
1658 			matrix[i][1][0] = value[2];	matrix[i][1][1] = value[3];	matrix[i][1][2] = 0; matrix[i][1][3] = 0;
1659 
1660 			value += 4;
1661 		}
1662 
1663 		Uniform *targetUniform = uniforms[uniformIndex[location].index];
1664 
1665 		if(targetUniform->psRegisterIndex != -1)
1666 		{
1667 			device->setPixelShaderConstantF(targetUniform->psRegisterIndex, (float*)matrix, targetUniform->registerCount());
1668 		}
1669 
1670 		if(targetUniform->vsRegisterIndex != -1)
1671 		{
1672 			device->setVertexShaderConstantF(targetUniform->vsRegisterIndex, (float*)matrix, targetUniform->registerCount());
1673 		}
1674 
1675 		return true;
1676 	}
1677 
applyUniformMatrix3fv(GLint location,GLsizei count,const GLfloat * value)1678 	bool Program::applyUniformMatrix3fv(GLint location, GLsizei count, const GLfloat *value)
1679 	{
1680 		float matrix[(MAX_UNIFORM_VECTORS + 2) / 3][3][4];
1681 
1682 		for(int i = 0; i < count; i++)
1683 		{
1684 			matrix[i][0][0] = value[0];	matrix[i][0][1] = value[1];	matrix[i][0][2] = value[2];	matrix[i][0][3] = 0;
1685 			matrix[i][1][0] = value[3];	matrix[i][1][1] = value[4];	matrix[i][1][2] = value[5];	matrix[i][1][3] = 0;
1686 			matrix[i][2][0] = value[6];	matrix[i][2][1] = value[7];	matrix[i][2][2] = value[8];	matrix[i][2][3] = 0;
1687 
1688 			value += 9;
1689 		}
1690 
1691 		Uniform *targetUniform = uniforms[uniformIndex[location].index];
1692 
1693 		if(targetUniform->psRegisterIndex != -1)
1694 		{
1695 			device->setPixelShaderConstantF(targetUniform->psRegisterIndex, (float*)matrix, targetUniform->registerCount());
1696 		}
1697 
1698 		if(targetUniform->vsRegisterIndex != -1)
1699 		{
1700 			device->setVertexShaderConstantF(targetUniform->vsRegisterIndex, (float*)matrix, targetUniform->registerCount());
1701 		}
1702 
1703 		return true;
1704 	}
1705 
applyUniformMatrix4fv(GLint location,GLsizei count,const GLfloat * value)1706 	bool Program::applyUniformMatrix4fv(GLint location, GLsizei count, const GLfloat *value)
1707 	{
1708 		Uniform *targetUniform = uniforms[uniformIndex[location].index];
1709 
1710 		if(targetUniform->psRegisterIndex != -1)
1711 		{
1712 			device->setPixelShaderConstantF(targetUniform->psRegisterIndex, (float*)value, targetUniform->registerCount());
1713 		}
1714 
1715 		if(targetUniform->vsRegisterIndex != -1)
1716 		{
1717 			device->setVertexShaderConstantF(targetUniform->vsRegisterIndex, (float*)value, targetUniform->registerCount());
1718 		}
1719 
1720 		return true;
1721 	}
1722 
applyUniform1iv(GLint location,GLsizei count,const GLint * v)1723 	bool Program::applyUniform1iv(GLint location, GLsizei count, const GLint *v)
1724 	{
1725 		float vector[MAX_UNIFORM_VECTORS][4];
1726 
1727 		for(int i = 0; i < count; i++)
1728 		{
1729 			vector[i][0] = (float)v[i];
1730 			vector[i][1] = 0;
1731 			vector[i][2] = 0;
1732 			vector[i][3] = 0;
1733 		}
1734 
1735 		Uniform *targetUniform = uniforms[uniformIndex[location].index];
1736 
1737 		if(targetUniform->psRegisterIndex != -1)
1738 		{
1739 			if(targetUniform->type == GL_SAMPLER_2D ||
1740 			   targetUniform->type == GL_SAMPLER_CUBE)
1741 			{
1742 				for(int i = 0; i < count; i++)
1743 				{
1744 					unsigned int samplerIndex = targetUniform->psRegisterIndex + i;
1745 
1746 					if(samplerIndex < MAX_TEXTURE_IMAGE_UNITS)
1747 					{
1748 						ASSERT(samplersPS[samplerIndex].active);
1749 						samplersPS[samplerIndex].logicalTextureUnit = v[i];
1750 					}
1751 				}
1752 			}
1753 			else
1754 			{
1755 				device->setPixelShaderConstantF(targetUniform->psRegisterIndex, (float*)vector, targetUniform->registerCount());
1756 			}
1757 		}
1758 
1759 		if(targetUniform->vsRegisterIndex != -1)
1760 		{
1761 			if(targetUniform->type == GL_SAMPLER_2D ||
1762 			   targetUniform->type == GL_SAMPLER_CUBE)
1763 			{
1764 				for(int i = 0; i < count; i++)
1765 				{
1766 					unsigned int samplerIndex = targetUniform->vsRegisterIndex + i;
1767 
1768 					if(samplerIndex < MAX_VERTEX_TEXTURE_IMAGE_UNITS)
1769 					{
1770 						ASSERT(samplersVS[samplerIndex].active);
1771 						samplersVS[samplerIndex].logicalTextureUnit = v[i];
1772 					}
1773 				}
1774 			}
1775 			else
1776 			{
1777 				device->setVertexShaderConstantF(targetUniform->vsRegisterIndex, (float*)vector, targetUniform->registerCount());
1778 			}
1779 		}
1780 
1781 		return true;
1782 	}
1783 
applyUniform2iv(GLint location,GLsizei count,const GLint * v)1784 	bool Program::applyUniform2iv(GLint location, GLsizei count, const GLint *v)
1785 	{
1786 		float vector[MAX_UNIFORM_VECTORS][4];
1787 
1788 		for(int i = 0; i < count; i++)
1789 		{
1790 			vector[i][0] = (float)v[0];
1791 			vector[i][1] = (float)v[1];
1792 			vector[i][2] = 0;
1793 			vector[i][3] = 0;
1794 
1795 			v += 2;
1796 		}
1797 
1798 		Uniform *targetUniform = uniforms[uniformIndex[location].index];
1799 
1800 		if(targetUniform->psRegisterIndex != -1)
1801 		{
1802 			device->setPixelShaderConstantF(targetUniform->psRegisterIndex, (float*)vector, targetUniform->registerCount());
1803 		}
1804 
1805 		if(targetUniform->vsRegisterIndex != -1)
1806 		{
1807 			device->setVertexShaderConstantF(targetUniform->vsRegisterIndex, (float*)vector, targetUniform->registerCount());
1808 		}
1809 
1810 		return true;
1811 	}
1812 
applyUniform3iv(GLint location,GLsizei count,const GLint * v)1813 	bool Program::applyUniform3iv(GLint location, GLsizei count, const GLint *v)
1814 	{
1815 		float vector[MAX_UNIFORM_VECTORS][4];
1816 
1817 		for(int i = 0; i < count; i++)
1818 		{
1819 			vector[i][0] = (float)v[0];
1820 			vector[i][1] = (float)v[1];
1821 			vector[i][2] = (float)v[2];
1822 			vector[i][3] = 0;
1823 
1824 			v += 3;
1825 		}
1826 
1827 		Uniform *targetUniform = uniforms[uniformIndex[location].index];
1828 
1829 		if(targetUniform->psRegisterIndex != -1)
1830 		{
1831 			device->setPixelShaderConstantF(targetUniform->psRegisterIndex, (float*)vector, targetUniform->registerCount());
1832 		}
1833 
1834 		if(targetUniform->vsRegisterIndex != -1)
1835 		{
1836 			device->setVertexShaderConstantF(targetUniform->vsRegisterIndex, (float*)vector, targetUniform->registerCount());
1837 		}
1838 
1839 		return true;
1840 	}
1841 
applyUniform4iv(GLint location,GLsizei count,const GLint * v)1842 	bool Program::applyUniform4iv(GLint location, GLsizei count, const GLint *v)
1843 	{
1844 		float vector[MAX_UNIFORM_VECTORS][4];
1845 
1846 		for(int i = 0; i < count; i++)
1847 		{
1848 			vector[i][0] = (float)v[0];
1849 			vector[i][1] = (float)v[1];
1850 			vector[i][2] = (float)v[2];
1851 			vector[i][3] = (float)v[3];
1852 
1853 			v += 4;
1854 		}
1855 
1856 		Uniform *targetUniform = uniforms[uniformIndex[location].index];
1857 
1858 		if(targetUniform->psRegisterIndex != -1)
1859 		{
1860 			device->setPixelShaderConstantF(targetUniform->psRegisterIndex, (float*)vector, targetUniform->registerCount());
1861 		}
1862 
1863 		if(targetUniform->vsRegisterIndex != -1)
1864 		{
1865 			device->setVertexShaderConstantF(targetUniform->vsRegisterIndex, (float*)vector, targetUniform->registerCount());
1866 		}
1867 
1868 		return true;
1869 	}
1870 
appendToInfoLog(const char * format,...)1871 	void Program::appendToInfoLog(const char *format, ...)
1872 	{
1873 		if(!format)
1874 		{
1875 			return;
1876 		}
1877 
1878 		char info[1024];
1879 
1880 		va_list vararg;
1881 		va_start(vararg, format);
1882 		vsnprintf(info, sizeof(info), format, vararg);
1883 		va_end(vararg);
1884 
1885 		size_t infoLength = strlen(info);
1886 
1887 		if(!infoLog)
1888 		{
1889 			infoLog = new char[infoLength + 2];
1890 			strcpy(infoLog, info);
1891 			strcpy(infoLog + infoLength, "\n");
1892 		}
1893 		else
1894 		{
1895 			size_t logLength = strlen(infoLog);
1896 			char *newLog = new char[logLength + infoLength + 2];
1897 			strcpy(newLog, infoLog);
1898 			strcpy(newLog + logLength, info);
1899 			strcpy(newLog + logLength + infoLength, "\n");
1900 
1901 			delete[] infoLog;
1902 			infoLog = newLog;
1903 		}
1904 	}
1905 
resetInfoLog()1906 	void Program::resetInfoLog()
1907 	{
1908 		if(infoLog)
1909 		{
1910 			delete[] infoLog;
1911 			infoLog = 0;
1912 		}
1913 	}
1914 
1915 	// Returns the program object to an unlinked state, before re-linking, or at destruction
unlink()1916 	void Program::unlink()
1917 	{
1918 		delete vertexBinary;
1919 		vertexBinary = 0;
1920 		delete pixelBinary;
1921 		pixelBinary = 0;
1922 
1923 		for(int index = 0; index < MAX_VERTEX_ATTRIBS; index++)
1924 		{
1925 			linkedAttribute[index].name.clear();
1926 			attributeStream[index] = -1;
1927 		}
1928 
1929 		for(int index = 0; index < MAX_TEXTURE_IMAGE_UNITS; index++)
1930 		{
1931 			samplersPS[index].active = false;
1932 		}
1933 
1934 		for(int index = 0; index < MAX_VERTEX_TEXTURE_IMAGE_UNITS; index++)
1935 		{
1936 			samplersVS[index].active = false;
1937 		}
1938 
1939 		while(!uniforms.empty())
1940 		{
1941 			delete uniforms.back();
1942 			uniforms.pop_back();
1943 		}
1944 
1945 		uniformIndex.clear();
1946 
1947 		delete[] infoLog;
1948 		infoLog = 0;
1949 
1950 		linked = false;
1951 	}
1952 
isLinked()1953 	bool Program::isLinked()
1954 	{
1955 		return linked;
1956 	}
1957 
isValidated() const1958 	bool Program::isValidated() const
1959 	{
1960 		return validated;
1961 	}
1962 
release()1963 	void Program::release()
1964 	{
1965 		referenceCount--;
1966 
1967 		if(referenceCount == 0 && orphaned)
1968 		{
1969 			resourceManager->deleteProgram(handle);
1970 		}
1971 	}
1972 
addRef()1973 	void Program::addRef()
1974 	{
1975 		referenceCount++;
1976 	}
1977 
getRefCount() const1978 	unsigned int Program::getRefCount() const
1979 	{
1980 		return referenceCount;
1981 	}
1982 
getSerial() const1983 	unsigned int Program::getSerial() const
1984 	{
1985 		return serial;
1986 	}
1987 
issueSerial()1988 	unsigned int Program::issueSerial()
1989 	{
1990 		return currentSerial++;
1991 	}
1992 
getInfoLogLength() const1993 	int Program::getInfoLogLength() const
1994 	{
1995 		if(!infoLog)
1996 		{
1997 			return 0;
1998 		}
1999 		else
2000 		{
2001 		   return strlen(infoLog) + 1;
2002 		}
2003 	}
2004 
getInfoLog(GLsizei bufSize,GLsizei * length,char * buffer)2005 	void Program::getInfoLog(GLsizei bufSize, GLsizei *length, char *buffer)
2006 	{
2007 		int index = 0;
2008 
2009 		if(bufSize > 0)
2010 		{
2011 			if(infoLog)
2012 			{
2013 				index = std::min(bufSize - 1, (int)strlen(infoLog));
2014 				memcpy(buffer, infoLog, index);
2015 			}
2016 
2017 			buffer[index] = '\0';
2018 		}
2019 
2020 		if(length)
2021 		{
2022 			*length = index;
2023 		}
2024 	}
2025 
getAttachedShaders(GLsizei maxCount,GLsizei * count,GLuint * shaders)2026 	void Program::getAttachedShaders(GLsizei maxCount, GLsizei *count, GLuint *shaders)
2027 	{
2028 		int total = 0;
2029 
2030 		if(vertexShader)
2031 		{
2032 			if(total < maxCount)
2033 			{
2034 				shaders[total] = vertexShader->getName();
2035 			}
2036 
2037 			total++;
2038 		}
2039 
2040 		if(fragmentShader)
2041 		{
2042 			if(total < maxCount)
2043 			{
2044 				shaders[total] = fragmentShader->getName();
2045 			}
2046 
2047 			total++;
2048 		}
2049 
2050 		if(count)
2051 		{
2052 			*count = total;
2053 		}
2054 	}
2055 
getActiveAttribute(GLuint index,GLsizei bufsize,GLsizei * length,GLint * size,GLenum * type,GLchar * name) const2056 	void Program::getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) const
2057 	{
2058 		// Skip over inactive attributes
2059 		unsigned int activeAttribute = 0;
2060 		unsigned int attribute;
2061 		for(attribute = 0; attribute < MAX_VERTEX_ATTRIBS; attribute++)
2062 		{
2063 			if(linkedAttribute[attribute].name.empty())
2064 			{
2065 				continue;
2066 			}
2067 
2068 			if(activeAttribute == index)
2069 			{
2070 				break;
2071 			}
2072 
2073 			activeAttribute++;
2074 		}
2075 
2076 		if(bufsize > 0)
2077 		{
2078 			const char *string = linkedAttribute[attribute].name.c_str();
2079 
2080 			strncpy(name, string, bufsize);
2081 			name[bufsize - 1] = '\0';
2082 
2083 			if(length)
2084 			{
2085 				*length = strlen(name);
2086 			}
2087 		}
2088 
2089 		*size = 1;   // Always a single 'type' instance
2090 
2091 		*type = linkedAttribute[attribute].type;
2092 	}
2093 
getActiveAttributeCount() const2094 	size_t Program::getActiveAttributeCount() const
2095 	{
2096 		size_t count = 0;
2097 
2098 		for(size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; ++attributeIndex)
2099 		{
2100 			if(!linkedAttribute[attributeIndex].name.empty())
2101 			{
2102 				count++;
2103 			}
2104 		}
2105 
2106 		return count;
2107 	}
2108 
getActiveAttributeMaxLength() const2109 	GLint Program::getActiveAttributeMaxLength() const
2110 	{
2111 		int maxLength = 0;
2112 
2113 		for(int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
2114 		{
2115 			if(!linkedAttribute[attributeIndex].name.empty())
2116 			{
2117 				maxLength = std::max((int)(linkedAttribute[attributeIndex].name.length() + 1), maxLength);
2118 			}
2119 		}
2120 
2121 		return maxLength;
2122 	}
2123 
getActiveUniform(GLuint index,GLsizei bufsize,GLsizei * length,GLint * size,GLenum * type,GLchar * name) const2124 	void Program::getActiveUniform(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) const
2125 	{
2126 		if(bufsize > 0)
2127 		{
2128 			std::string string = uniforms[index]->name;
2129 
2130 			if(uniforms[index]->isArray())
2131 			{
2132 				string += "[0]";
2133 			}
2134 
2135 			strncpy(name, string.c_str(), bufsize);
2136 			name[bufsize - 1] = '\0';
2137 
2138 			if(length)
2139 			{
2140 				*length = strlen(name);
2141 			}
2142 		}
2143 
2144 		*size = uniforms[index]->size();
2145 
2146 		*type = uniforms[index]->type;
2147 	}
2148 
getActiveUniformCount() const2149 	size_t Program::getActiveUniformCount() const
2150 	{
2151 		return uniforms.size();
2152 	}
2153 
getActiveUniformMaxLength() const2154 	GLint Program::getActiveUniformMaxLength() const
2155 	{
2156 		int maxLength = 0;
2157 
2158 		unsigned int numUniforms = uniforms.size();
2159 		for(unsigned int uniformIndex = 0; uniformIndex < numUniforms; uniformIndex++)
2160 		{
2161 			if(!uniforms[uniformIndex]->name.empty())
2162 			{
2163 				int length = (int)(uniforms[uniformIndex]->name.length() + 1);
2164 				if(uniforms[uniformIndex]->isArray())
2165 				{
2166 					length += 3;  // Counting in "[0]".
2167 				}
2168 				maxLength = std::max(length, maxLength);
2169 			}
2170 		}
2171 
2172 		return maxLength;
2173 	}
2174 
flagForDeletion()2175 	void Program::flagForDeletion()
2176 	{
2177 		orphaned = true;
2178 	}
2179 
isFlaggedForDeletion() const2180 	bool Program::isFlaggedForDeletion() const
2181 	{
2182 		return orphaned;
2183 	}
2184 
validate()2185 	void Program::validate()
2186 	{
2187 		resetInfoLog();
2188 
2189 		if(!isLinked())
2190 		{
2191 			appendToInfoLog("Program has not been successfully linked.");
2192 			validated = false;
2193 		}
2194 		else
2195 		{
2196 			applyUniforms();
2197 			if(!validateSamplers(true))
2198 			{
2199 				validated = false;
2200 			}
2201 			else
2202 			{
2203 				validated = true;
2204 			}
2205 		}
2206 	}
2207 
validateSamplers(bool logErrors)2208 	bool Program::validateSamplers(bool logErrors)
2209 	{
2210 		// if any two active samplers in a program are of different types, but refer to the same
2211 		// texture image unit, and this is the current program, then ValidateProgram will fail, and
2212 		// DrawArrays and DrawElements will issue the INVALID_OPERATION error.
2213 
2214 		TextureType textureUnitType[MAX_COMBINED_TEXTURE_IMAGE_UNITS];
2215 
2216 		for(unsigned int i = 0; i < MAX_COMBINED_TEXTURE_IMAGE_UNITS; i++)
2217 		{
2218 			textureUnitType[i] = TEXTURE_UNKNOWN;
2219 		}
2220 
2221 		for(unsigned int i = 0; i < MAX_TEXTURE_IMAGE_UNITS; i++)
2222 		{
2223 			if(samplersPS[i].active)
2224 			{
2225 				unsigned int unit = samplersPS[i].logicalTextureUnit;
2226 
2227 				if(unit >= MAX_COMBINED_TEXTURE_IMAGE_UNITS)
2228 				{
2229 					if(logErrors)
2230 					{
2231 						appendToInfoLog("Sampler uniform (%d) exceeds MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, MAX_COMBINED_TEXTURE_IMAGE_UNITS);
2232 					}
2233 
2234 					return false;
2235 				}
2236 
2237 				if(textureUnitType[unit] != TEXTURE_UNKNOWN)
2238 				{
2239 					if(samplersPS[i].textureType != textureUnitType[unit])
2240 					{
2241 						if(logErrors)
2242 						{
2243 							appendToInfoLog("Samplers of conflicting types refer to the same texture image unit (%d).", unit);
2244 						}
2245 
2246 						return false;
2247 					}
2248 				}
2249 				else
2250 				{
2251 					textureUnitType[unit] = samplersPS[i].textureType;
2252 				}
2253 			}
2254 		}
2255 
2256 		for(unsigned int i = 0; i < MAX_VERTEX_TEXTURE_IMAGE_UNITS; i++)
2257 		{
2258 			if(samplersVS[i].active)
2259 			{
2260 				unsigned int unit = samplersVS[i].logicalTextureUnit;
2261 
2262 				if(unit >= MAX_COMBINED_TEXTURE_IMAGE_UNITS)
2263 				{
2264 					if(logErrors)
2265 					{
2266 						appendToInfoLog("Sampler uniform (%d) exceeds MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, MAX_COMBINED_TEXTURE_IMAGE_UNITS);
2267 					}
2268 
2269 					return false;
2270 				}
2271 
2272 				if(textureUnitType[unit] != TEXTURE_UNKNOWN)
2273 				{
2274 					if(samplersVS[i].textureType != textureUnitType[unit])
2275 					{
2276 						if(logErrors)
2277 						{
2278 							appendToInfoLog("Samplers of conflicting types refer to the same texture image unit (%d).", unit);
2279 						}
2280 
2281 						return false;
2282 					}
2283 				}
2284 				else
2285 				{
2286 					textureUnitType[unit] = samplersVS[i].textureType;
2287 				}
2288 			}
2289 		}
2290 
2291 		return true;
2292 	}
2293 }
2294