1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program OpenGL ES 2.0 Module
3  * -------------------------------------------------
4  *
5  * Copyright 2014 The Android Open Source Project
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*!
20  * \file
21  * \brief Rbo state query tests.
22  *//*--------------------------------------------------------------------*/
23 
24 #include "es2fShaderStateQueryTests.hpp"
25 #include "glsStateQueryUtil.hpp"
26 #include "es2fApiCase.hpp"
27 #include "gluRenderContext.hpp"
28 #include "gluShaderProgram.hpp"
29 #include "glwEnums.hpp"
30 #include "glwFunctions.hpp"
31 #include "deRandom.hpp"
32 #include "deMath.h"
33 #include "deString.h"
34 
35 using namespace glw; // GLint and other GL types
36 using deqp::gls::StateQueryUtil::StateQueryMemoryWriteGuard;
37 
38 namespace deqp
39 {
40 namespace gles2
41 {
42 namespace Functional
43 {
44 namespace
45 {
46 
47 static const char* commonTestVertSource		=	"void main (void)\n"
48 												"{\n"
49 												"	gl_Position = vec4(0.0);\n"
50 												"}\n";
51 static const char* commonTestFragSource		=	"void main (void)\n"
52 												"{\n"
53 												"	gl_FragColor = vec4(0.0);\n"
54 												"}\n";
55 
56 static const char* brokenShader				=	"broken, this should not compile!\n"
57 												"\n";
58 
59 // rounds x.1 to x+1
60 template <typename T>
roundGLfloatToNearestIntegerUp(GLfloat val)61 T roundGLfloatToNearestIntegerUp (GLfloat val)
62 {
63 	return (T)(ceil(val));
64 }
65 
66 // rounds x.9 to x
67 template <typename T>
roundGLfloatToNearestIntegerDown(GLfloat val)68 T roundGLfloatToNearestIntegerDown (GLfloat val)
69 {
70 	return (T)(floor(val));
71 }
72 
checkIntEquals(tcu::TestContext & testCtx,GLint got,GLint expected)73 bool checkIntEquals (tcu::TestContext& testCtx, GLint got, GLint expected)
74 {
75 	using tcu::TestLog;
76 
77 	if (got != expected)
78 	{
79 		testCtx.getLog() << TestLog::Message << "// ERROR: Expected " << expected << "; got " << got << TestLog::EndMessage;
80 		if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
81 			testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid value");
82 		return false;
83 	}
84 	return true;
85 }
86 
checkPointerEquals(tcu::TestContext & testCtx,const void * got,const void * expected)87 void checkPointerEquals (tcu::TestContext& testCtx, const void* got, const void* expected)
88 {
89 	using tcu::TestLog;
90 
91 	if (got != expected)
92 	{
93 		testCtx.getLog() << TestLog::Message << "// ERROR: Expected " << expected << "; got " << got << TestLog::EndMessage;
94 		if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
95 			testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid value");
96 	}
97 }
98 
verifyShaderParam(tcu::TestContext & testCtx,glu::CallLogWrapper & gl,GLuint shader,GLenum pname,GLenum reference)99 void verifyShaderParam (tcu::TestContext& testCtx, glu::CallLogWrapper& gl, GLuint shader, GLenum pname, GLenum reference)
100 {
101 	StateQueryMemoryWriteGuard<GLint> state;
102 	gl.glGetShaderiv(shader, pname, &state);
103 
104 	if (state.verifyValidity(testCtx))
105 		checkIntEquals(testCtx, state, reference);
106 }
107 
verifyProgramParam(tcu::TestContext & testCtx,glu::CallLogWrapper & gl,GLuint program,GLenum pname,GLenum reference)108 bool verifyProgramParam (tcu::TestContext& testCtx, glu::CallLogWrapper& gl, GLuint program, GLenum pname, GLenum reference)
109 {
110 	StateQueryMemoryWriteGuard<GLint> state;
111 	gl.glGetProgramiv(program, pname, &state);
112 
113 	if (state.verifyValidity(testCtx))
114 		return checkIntEquals(testCtx, state, reference);
115 	return false;
116 }
117 
verifyCurrentVertexAttribf(tcu::TestContext & testCtx,glu::CallLogWrapper & gl,GLint index,GLfloat x,GLfloat y,GLfloat z,GLfloat w)118 void verifyCurrentVertexAttribf (tcu::TestContext& testCtx, glu::CallLogWrapper& gl, GLint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
119 {
120 	using tcu::TestLog;
121 
122 	StateQueryMemoryWriteGuard<GLfloat[4]> attribValue;
123 	gl.glGetVertexAttribfv(index, GL_CURRENT_VERTEX_ATTRIB, attribValue);
124 
125 	attribValue.verifyValidity(testCtx);
126 
127 	if (attribValue[0] != x || attribValue[1] != y || attribValue[2] != z || attribValue[3] != w)
128 	{
129 		testCtx.getLog() << TestLog::Message
130 			<< "// ERROR: Expected [" << x << "," << y << "," << z << "," << w << "];"
131 			<< "got [" << attribValue[0] << "," << attribValue[1] << "," << attribValue[2] << "," << attribValue[3] << "]"
132 			<< TestLog::EndMessage;
133 		if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
134 			testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid attribute value");
135 	}
136 }
137 
verifyCurrentVertexAttribConversion(tcu::TestContext & testCtx,glu::CallLogWrapper & gl,GLint index,GLfloat x,GLfloat y,GLfloat z,GLfloat w)138 void verifyCurrentVertexAttribConversion (tcu::TestContext& testCtx, glu::CallLogWrapper& gl, GLint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
139 {
140 	using tcu::TestLog;
141 
142 	StateQueryMemoryWriteGuard<GLint[4]> attribValue;
143 	gl.glGetVertexAttribiv(index, GL_CURRENT_VERTEX_ATTRIB, attribValue);
144 
145 	attribValue.verifyValidity(testCtx);
146 
147 	const GLint referenceAsGLintMin[] =
148 	{
149 		roundGLfloatToNearestIntegerDown<GLint>(x),
150 		roundGLfloatToNearestIntegerDown<GLint>(y),
151 		roundGLfloatToNearestIntegerDown<GLint>(z),
152 		roundGLfloatToNearestIntegerDown<GLint>(w)
153 	};
154 	const GLint referenceAsGLintMax[] =
155 	{
156 		roundGLfloatToNearestIntegerUp<GLint>(x),
157 		roundGLfloatToNearestIntegerUp<GLint>(y),
158 		roundGLfloatToNearestIntegerUp<GLint>(z),
159 		roundGLfloatToNearestIntegerUp<GLint>(w)
160 	};
161 
162 	if (attribValue[0] < referenceAsGLintMin[0] || attribValue[0] > referenceAsGLintMax[0] ||
163 		attribValue[1] < referenceAsGLintMin[1] || attribValue[1] > referenceAsGLintMax[1] ||
164 		attribValue[2] < referenceAsGLintMin[2] || attribValue[2] > referenceAsGLintMax[2] ||
165 		attribValue[3] < referenceAsGLintMin[3] || attribValue[3] > referenceAsGLintMax[3])
166 	{
167 		testCtx.getLog() << TestLog::Message
168 			<< "// ERROR: expected in range "
169 			<< "[" << referenceAsGLintMin[0] << " " << referenceAsGLintMax[0] << "], "
170 			<< "[" << referenceAsGLintMin[1] << " " << referenceAsGLintMax[1] << "], "
171 			<< "[" << referenceAsGLintMin[2] << " " << referenceAsGLintMax[2] << "], "
172 			<< "[" << referenceAsGLintMin[3] << " " << referenceAsGLintMax[3] << "]"
173 			<< "; got "
174 			<< attribValue[0] << ", "
175 			<< attribValue[1] << ", "
176 			<< attribValue[2] << ", "
177 			<< attribValue[3] << " "
178 			<< "; Input="
179 			<< x << "; "
180 			<< y << "; "
181 			<< z << "; "
182 			<< w << " " << TestLog::EndMessage;
183 
184 		if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
185 			testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid attribute value");
186 	}
187 }
188 
verifyVertexAttrib(tcu::TestContext & testCtx,glu::CallLogWrapper & gl,GLint index,GLenum pname,GLenum reference)189 void verifyVertexAttrib (tcu::TestContext& testCtx, glu::CallLogWrapper& gl, GLint index, GLenum pname, GLenum reference)
190 {
191 	StateQueryMemoryWriteGuard<GLint> state;
192 	gl.glGetVertexAttribiv(index, pname, &state);
193 
194 	if (state.verifyValidity(testCtx))
195 		checkIntEquals(testCtx, state, reference);
196 }
197 
verifyUniformValue1f(tcu::TestContext & testCtx,glu::CallLogWrapper & gl,GLuint program,GLint location,float x)198 void verifyUniformValue1f (tcu::TestContext& testCtx, glu::CallLogWrapper& gl, GLuint program, GLint location, float x)
199 {
200 	using tcu::TestLog;
201 
202 	StateQueryMemoryWriteGuard<GLfloat[1]> state;
203 	gl.glGetUniformfv(program, location, state);
204 
205 	if (!state.verifyValidity(testCtx))
206 		return;
207 
208 	if (state[0] != x)
209 	{
210 		testCtx.getLog() << TestLog::Message
211 		<< "// ERROR: expected ["
212 		<< x
213 		<< "]; got ["
214 		<< state[0]
215 		<< "]"
216 		<< TestLog::EndMessage;
217 
218 		if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
219 			testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid uniform value");
220 	}
221 }
222 
verifyUniformValue2f(tcu::TestContext & testCtx,glu::CallLogWrapper & gl,GLuint program,GLint location,float x,float y)223 void verifyUniformValue2f (tcu::TestContext& testCtx, glu::CallLogWrapper& gl, GLuint program, GLint location, float x, float y)
224 {
225 	using tcu::TestLog;
226 
227 	StateQueryMemoryWriteGuard<GLfloat[2]> state;
228 	gl.glGetUniformfv(program, location, state);
229 
230 	if (!state.verifyValidity(testCtx))
231 		return;
232 
233 	if (state[0] != x ||
234 		state[1] != y)
235 	{
236 		testCtx.getLog() << TestLog::Message
237 		<< "// ERROR: expected ["
238 		<< x << ", "
239 		<< y
240 		<< "]; got ["
241 		<< state[0] << ", "
242 		<< state[1]
243 		<< "]"
244 		<< TestLog::EndMessage;
245 
246 		if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
247 			testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid uniform value");
248 	}
249 }
250 
verifyUniformValue3f(tcu::TestContext & testCtx,glu::CallLogWrapper & gl,GLuint program,GLint location,float x,float y,float z)251 void verifyUniformValue3f (tcu::TestContext& testCtx, glu::CallLogWrapper& gl, GLuint program, GLint location, float x, float y, float z)
252 {
253 	using tcu::TestLog;
254 
255 	StateQueryMemoryWriteGuard<GLfloat[3]> state;
256 	gl.glGetUniformfv(program, location, state);
257 
258 	if (!state.verifyValidity(testCtx))
259 		return;
260 
261 	if (state[0] != x ||
262 		state[1] != y ||
263 		state[2] != z)
264 	{
265 		testCtx.getLog() << TestLog::Message
266 		<< "// ERROR: expected ["
267 		<< x << ", "
268 		<< y << ", "
269 		<< z
270 		<< "]; got ["
271 		<< state[0] << ", "
272 		<< state[1] << ", "
273 		<< state[2]
274 		<< "]"
275 		<< TestLog::EndMessage;
276 
277 		if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
278 			testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid uniform value");
279 	}
280 }
281 
verifyUniformValue4f(tcu::TestContext & testCtx,glu::CallLogWrapper & gl,GLuint program,GLint location,float x,float y,float z,float w)282 void verifyUniformValue4f (tcu::TestContext& testCtx, glu::CallLogWrapper& gl, GLuint program, GLint location, float x, float y, float z, float w)
283 {
284 	using tcu::TestLog;
285 
286 	StateQueryMemoryWriteGuard<GLfloat[4]> state;
287 	gl.glGetUniformfv(program, location, state);
288 
289 	if (!state.verifyValidity(testCtx))
290 		return;
291 
292 	if (state[0] != x ||
293 		state[1] != y ||
294 		state[2] != z ||
295 		state[3] != w)
296 	{
297 		testCtx.getLog() << TestLog::Message
298 		<< "// ERROR: expected ["
299 		<< x << ", "
300 		<< y << ", "
301 		<< z << ", "
302 		<< w
303 		<< "]; got ["
304 		<< state[0] << ", "
305 		<< state[1] << ", "
306 		<< state[2] << ", "
307 		<< state[3]
308 		<< "]"
309 		<< TestLog::EndMessage;
310 
311 		if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
312 			testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid uniform value");
313 	}
314 }
315 
verifyUniformValue1i(tcu::TestContext & testCtx,glu::CallLogWrapper & gl,GLuint program,GLint location,GLint x)316 void verifyUniformValue1i (tcu::TestContext& testCtx, glu::CallLogWrapper& gl, GLuint program, GLint location, GLint x)
317 {
318 	using tcu::TestLog;
319 
320 	StateQueryMemoryWriteGuard<GLint[1]> state;
321 	gl.glGetUniformiv(program, location, state);
322 
323 	if (!state.verifyValidity(testCtx))
324 		return;
325 
326 	if (state[0] != x)
327 	{
328 		testCtx.getLog() << TestLog::Message
329 		<< "// ERROR: expected ["
330 		<< x
331 		<< "]; got ["
332 		<< state[0]
333 		<< "]"
334 		<< TestLog::EndMessage;
335 
336 		if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
337 			testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid uniform value");
338 	}
339 }
340 
verifyUniformValue2i(tcu::TestContext & testCtx,glu::CallLogWrapper & gl,GLuint program,GLint location,GLint x,GLint y)341 void verifyUniformValue2i (tcu::TestContext& testCtx, glu::CallLogWrapper& gl, GLuint program, GLint location, GLint x, GLint y)
342 {
343 	using tcu::TestLog;
344 
345 	StateQueryMemoryWriteGuard<GLint[2]> state;
346 	gl.glGetUniformiv(program, location, state);
347 
348 	if (!state.verifyValidity(testCtx))
349 		return;
350 
351 	if (state[0] != x ||
352 		state[1] != y)
353 	{
354 		testCtx.getLog() << TestLog::Message
355 		<< "// ERROR: expected ["
356 		<< x << ", "
357 		<< y
358 		<< "]; got ["
359 		<< state[0] << ", "
360 		<< state[1]
361 		<< "]"
362 		<< TestLog::EndMessage;
363 
364 		if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
365 			testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid uniform value");
366 	}
367 }
368 
verifyUniformValue3i(tcu::TestContext & testCtx,glu::CallLogWrapper & gl,GLuint program,GLint location,GLint x,GLint y,GLint z)369 void verifyUniformValue3i (tcu::TestContext& testCtx, glu::CallLogWrapper& gl, GLuint program, GLint location, GLint x, GLint y, GLint z)
370 {
371 	using tcu::TestLog;
372 
373 	StateQueryMemoryWriteGuard<GLint[3]> state;
374 	gl.glGetUniformiv(program, location, state);
375 
376 	if (!state.verifyValidity(testCtx))
377 		return;
378 
379 	if (state[0] != x ||
380 		state[1] != y ||
381 		state[2] != z)
382 	{
383 		testCtx.getLog() << TestLog::Message
384 		<< "// ERROR: expected ["
385 		<< x << ", "
386 		<< y << ", "
387 		<< z
388 		<< "]; got ["
389 		<< state[0] << ", "
390 		<< state[1] << ", "
391 		<< state[2]
392 		<< "]"
393 		<< TestLog::EndMessage;
394 
395 		if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
396 			testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid uniform value");
397 	}
398 }
399 
verifyUniformValue4i(tcu::TestContext & testCtx,glu::CallLogWrapper & gl,GLuint program,GLint location,GLint x,GLint y,GLint z,GLint w)400 void verifyUniformValue4i (tcu::TestContext& testCtx, glu::CallLogWrapper& gl, GLuint program, GLint location, GLint x, GLint y, GLint z, GLint w)
401 {
402 	using tcu::TestLog;
403 
404 	StateQueryMemoryWriteGuard<GLint[4]> state;
405 	gl.glGetUniformiv(program, location, state);
406 
407 	if (!state.verifyValidity(testCtx))
408 		return;
409 
410 	if (state[0] != x ||
411 		state[1] != y ||
412 		state[2] != z ||
413 		state[3] != w)
414 	{
415 		testCtx.getLog() << TestLog::Message
416 		<< "// ERROR: expected ["
417 		<< x << ", "
418 		<< y << ", "
419 		<< z << ", "
420 		<< w
421 		<< "]; got ["
422 		<< state[0] << ", "
423 		<< state[1] << ", "
424 		<< state[2] << ", "
425 		<< state[3]
426 		<< "]"
427 		<< TestLog::EndMessage;
428 
429 		if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
430 			testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid uniform value");
431 	}
432 }
433 
434 template <int Count>
verifyUniformValues(tcu::TestContext & testCtx,glu::CallLogWrapper & gl,GLuint program,GLint location,const GLfloat * values)435 void verifyUniformValues (tcu::TestContext& testCtx, glu::CallLogWrapper& gl, GLuint program, GLint location, const GLfloat* values)
436 {
437 	using tcu::TestLog;
438 
439 	StateQueryMemoryWriteGuard<GLfloat[Count]> state;
440 	gl.glGetUniformfv(program, location, state);
441 
442 	if (!state.verifyValidity(testCtx))
443 		return;
444 
445 	for (int ndx = 0; ndx < Count; ++ndx)
446 	{
447 		if (values[ndx] != state[ndx])
448 		{
449 			testCtx.getLog() << TestLog::Message << "// ERROR: at index " << ndx << " expected " << values[ndx] << "; got " << state[ndx] << TestLog::EndMessage;
450 
451 			if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
452 				testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid uniform value");
453 		}
454 	}
455 }
456 
457 template <int N>
verifyUniformMatrixValues(tcu::TestContext & testCtx,glu::CallLogWrapper & gl,GLuint program,GLint location,const GLfloat * values,bool transpose)458 void verifyUniformMatrixValues (tcu::TestContext& testCtx, glu::CallLogWrapper& gl, GLuint program, GLint location, const GLfloat* values, bool transpose)
459 {
460 	using tcu::TestLog;
461 
462 	StateQueryMemoryWriteGuard<GLfloat[N*N]> state;
463 	gl.glGetUniformfv(program, location, state);
464 
465 	if (!state.verifyValidity(testCtx))
466 		return;
467 
468 	for (int y = 0; y < N; ++y)
469 		for (int x = 0; x < N; ++x)
470 		{
471 			const int refIndex = y*N + x;
472 			const int stateIndex = transpose ? (x*N + y) : (y*N + x);
473 
474 			if (values[refIndex] != state[stateIndex])
475 			{
476 				testCtx.getLog() << TestLog::Message << "// ERROR: at index [" << y << "][" << x << "] expected " << values[refIndex] << "; got " << state[stateIndex] << TestLog::EndMessage;
477 
478 				if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
479 					testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid uniform value");
480 			}
481 		}
482 }
483 
requireShaderCompiler(tcu::TestContext & testCtx,glu::CallLogWrapper & gl)484 void requireShaderCompiler (tcu::TestContext& testCtx, glu::CallLogWrapper& gl)
485 {
486 	StateQueryMemoryWriteGuard<GLboolean> state;
487 	gl.glGetBooleanv(GL_SHADER_COMPILER, &state);
488 
489 	if (!state.verifyValidity(testCtx) || state != GL_TRUE)
490 		throw tcu::NotSupportedError("Test requires SHADER_COMPILER = TRUE");
491 }
492 
493 class ShaderTypeCase : public ApiCase
494 {
495 public:
ShaderTypeCase(Context & context,const char * name,const char * description)496 	ShaderTypeCase (Context& context, const char* name, const char* description)
497 		: ApiCase(context, name, description)
498 	{
499 	}
500 
test(void)501 	void test (void)
502 	{
503 		const GLenum shaderTypes[] = {GL_VERTEX_SHADER, GL_FRAGMENT_SHADER};
504 		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(shaderTypes); ++ndx)
505 		{
506 			const GLuint shader = glCreateShader(shaderTypes[ndx]);
507 			verifyShaderParam(m_testCtx, *this, shader, GL_SHADER_TYPE, shaderTypes[ndx]);
508 			glDeleteShader(shader);
509 		}
510 	}
511 };
512 
513 class ShaderCompileStatusCase : public ApiCase
514 {
515 public:
ShaderCompileStatusCase(Context & context,const char * name,const char * description)516 	ShaderCompileStatusCase (Context& context, const char* name, const char* description)
517 		: ApiCase(context, name, description)
518 	{
519 	}
520 
test(void)521 	void test (void)
522 	{
523 		requireShaderCompiler(m_testCtx, *this);
524 
525 		GLuint shaderVert = glCreateShader(GL_VERTEX_SHADER);
526 		GLuint shaderFrag = glCreateShader(GL_FRAGMENT_SHADER);
527 
528 		verifyShaderParam(m_testCtx, *this, shaderVert, GL_COMPILE_STATUS, GL_FALSE);
529 		verifyShaderParam(m_testCtx, *this, shaderFrag, GL_COMPILE_STATUS, GL_FALSE);
530 
531 		glShaderSource(shaderVert, 1, &commonTestVertSource, DE_NULL);
532 		glShaderSource(shaderFrag, 1, &commonTestFragSource, DE_NULL);
533 
534 		glCompileShader(shaderVert);
535 		glCompileShader(shaderFrag);
536 		expectError(GL_NO_ERROR);
537 
538 		verifyShaderParam(m_testCtx, *this, shaderVert, GL_COMPILE_STATUS, GL_TRUE);
539 		verifyShaderParam(m_testCtx, *this, shaderFrag, GL_COMPILE_STATUS, GL_TRUE);
540 
541 		glDeleteShader(shaderVert);
542 		glDeleteShader(shaderFrag);
543 		expectError(GL_NO_ERROR);
544 	}
545 };
546 
547 class ShaderInfoLogCase : public ApiCase
548 {
549 public:
ShaderInfoLogCase(Context & context,const char * name,const char * description)550 	ShaderInfoLogCase (Context& context, const char* name, const char* description)
551 		: ApiCase(context, name, description)
552 	{
553 	}
554 
test(void)555 	void test (void)
556 	{
557 		requireShaderCompiler(m_testCtx, *this);
558 
559 		using tcu::TestLog;
560 
561 		// INFO_LOG_LENGTH is 0 by default and it includes null-terminator
562 		const GLuint shader = glCreateShader(GL_VERTEX_SHADER);
563 		verifyShaderParam(m_testCtx, *this, shader, GL_INFO_LOG_LENGTH, 0);
564 
565 		glShaderSource(shader, 1, &brokenShader, DE_NULL);
566 		glCompileShader(shader);
567 		expectError(GL_NO_ERROR);
568 
569 		// check the log length
570 		StateQueryMemoryWriteGuard<GLint> logLength;
571 		glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &logLength);
572 		if (!logLength.verifyValidity(m_testCtx))
573 		{
574 			glDeleteShader(shader);
575 			return;
576 		}
577 		if (logLength == 0)
578 		{
579 			glDeleteShader(shader);
580 			return;
581 		}
582 
583 		// check normal case
584 		{
585 			char buffer[2048] = {'x'}; // non-zero initialization
586 
587 			GLint written = 0; // written does not include null terminator
588 			glGetShaderInfoLog(shader, DE_LENGTH_OF_ARRAY(buffer), &written, buffer);
589 
590 			// check lengths are consistent
591 			if (logLength <= DE_LENGTH_OF_ARRAY(buffer))
592 			{
593 				if (written != logLength-1)
594 				{
595 					m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected length " << logLength-1 << "; got " << written << TestLog::EndMessage;
596 					if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
597 						m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid log length");
598 				}
599 			}
600 
601 			// check null-terminator, either at end of buffer or at buffer[written]
602 			const char* terminator = &buffer[DE_LENGTH_OF_ARRAY(buffer) - 1];
603 			if (logLength < DE_LENGTH_OF_ARRAY(buffer))
604 				terminator = &buffer[written];
605 
606 			if (*terminator != '\0')
607 			{
608 				m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected null terminator, got " << (int)*terminator << TestLog::EndMessage;
609 				if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
610 					m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid log terminator");
611 			}
612 		}
613 
614 		// check with too small buffer
615 		{
616 			char buffer[2048] = {'x'}; // non-zero initialization
617 
618 			// check string always ends with \0, even with small buffers
619 			GLint written = 0;
620 			glGetShaderInfoLog(shader, 1, &written, buffer);
621 			if (written != 0)
622 			{
623 				m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected length 0; got " << written << TestLog::EndMessage;
624 				if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
625 					m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid log length");
626 			}
627 			if (buffer[0] != '\0')
628 			{
629 				m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected null terminator, got " << (int)buffer[0] << TestLog::EndMessage;
630 				if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
631 					m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid log terminator");
632 			}
633 		}
634 
635 		glDeleteShader(shader);
636 		expectError(GL_NO_ERROR);
637 	}
638 };
639 
640 class ShaderSourceCase : public ApiCase
641 {
642 public:
ShaderSourceCase(Context & context,const char * name,const char * description)643 	ShaderSourceCase (Context& context, const char* name, const char* description)
644 		: ApiCase(context, name, description)
645 	{
646 	}
647 
test(void)648 	void test (void)
649 	{
650 		requireShaderCompiler(m_testCtx, *this);
651 
652 		using tcu::TestLog;
653 
654 		// SHADER_SOURCE_LENGTH does include 0-terminator
655 		const GLuint shader = glCreateShader(GL_VERTEX_SHADER);
656 		verifyShaderParam(m_testCtx, *this, shader, GL_SHADER_SOURCE_LENGTH, 0);
657 
658 		// check the SHADER_SOURCE_LENGTH
659 		{
660 			glShaderSource(shader, 1, &brokenShader, DE_NULL);
661 			expectError(GL_NO_ERROR);
662 
663 			StateQueryMemoryWriteGuard<GLint> sourceLength;
664 			glGetShaderiv(shader, GL_SHADER_SOURCE_LENGTH, &sourceLength);
665 
666 			sourceLength.verifyValidity(m_testCtx);
667 
668 			const GLint referenceLength = (GLint)std::string(brokenShader).length() + 1; // including the null terminator
669 			if (sourceLength != referenceLength)
670 			{
671 				m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected length " << referenceLength	<< "; got " << sourceLength << TestLog::EndMessage;
672 				if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
673 					m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid source length");
674 			}
675 		}
676 
677 		// check the concat source SHADER_SOURCE_LENGTH
678 		{
679 			const char* shaders[] = {brokenShader, brokenShader};
680 			glShaderSource(shader, 2, shaders, DE_NULL);
681 			expectError(GL_NO_ERROR);
682 
683 			StateQueryMemoryWriteGuard<GLint> sourceLength;
684 			glGetShaderiv(shader, GL_SHADER_SOURCE_LENGTH, &sourceLength);
685 
686 			sourceLength.verifyValidity(m_testCtx);
687 
688 			const GLint referenceLength = 2 * (GLint)std::string(brokenShader).length() + 1; // including the null terminator
689 			if (sourceLength != referenceLength)
690 			{
691 				m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected length " << referenceLength << "; got " << sourceLength << TestLog::EndMessage;
692 				if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
693 					m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid source length");
694 			}
695 		}
696 
697 		// check the string length
698 		{
699 			char buffer[2048] = {'x'};
700 			DE_ASSERT(DE_LENGTH_OF_ARRAY(buffer) > 2 * (int)std::string(brokenShader).length());
701 
702 			GLint written = 0; // not inluding null-terminator
703 			glGetShaderSource(shader, DE_LENGTH_OF_ARRAY(buffer), &written, buffer);
704 
705 			const GLint referenceLength = 2 * (GLint)std::string(brokenShader).length();
706 			if (written != referenceLength)
707 			{
708 				m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected write length " << referenceLength << "; got " << written << TestLog::EndMessage;
709 				if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
710 					m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid source length");
711 			}
712 			// check null pointer at
713 			else
714 			{
715 				if (buffer[referenceLength] != '\0')
716 				{
717 					m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected null terminator at " << referenceLength << TestLog::EndMessage;
718 					if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
719 						m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "did not get a null terminator");
720 				}
721 			}
722 		}
723 
724 		// check with small buffer
725 		{
726 			char buffer[2048] = {'x'};
727 
728 			GLint written = 0;
729 			glGetShaderSource(shader, 1, &written, buffer);
730 
731 			if (written != 0)
732 			{
733 				m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected write length 0; got " << written << TestLog::EndMessage;
734 				if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
735 					m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid source length");
736 			}
737 			if (buffer[0] != '\0')
738 			{
739 				m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected null terminator; got=" << int(buffer[0]) << ", char=" << buffer[0] << TestLog::EndMessage;
740 				if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
741 					m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid terminator");
742 			}
743 		}
744 
745 		glDeleteShader(shader);
746 		expectError(GL_NO_ERROR);
747 	}
748 };
749 
750 class DeleteStatusCase : public ApiCase
751 {
752 public:
DeleteStatusCase(Context & context,const char * name,const char * description)753 	DeleteStatusCase (Context& context, const char* name, const char* description)
754 		: ApiCase(context, name, description)
755 	{
756 	}
757 
test(void)758 	void test (void)
759 	{
760 		GLuint shaderVert = glCreateShader(GL_VERTEX_SHADER);
761 		GLuint shaderFrag = glCreateShader(GL_FRAGMENT_SHADER);
762 
763 		glShaderSource(shaderVert, 1, &commonTestVertSource, DE_NULL);
764 		glShaderSource(shaderFrag, 1, &commonTestFragSource, DE_NULL);
765 
766 		glCompileShader(shaderVert);
767 		glCompileShader(shaderFrag);
768 		expectError(GL_NO_ERROR);
769 
770 		verifyShaderParam(m_testCtx, *this, shaderVert, GL_COMPILE_STATUS, GL_TRUE);
771 		verifyShaderParam(m_testCtx, *this, shaderFrag, GL_COMPILE_STATUS, GL_TRUE);
772 
773 		GLuint shaderProg = glCreateProgram();
774 		glAttachShader(shaderProg, shaderVert);
775 		glAttachShader(shaderProg, shaderFrag);
776 		glLinkProgram(shaderProg);
777 		expectError(GL_NO_ERROR);
778 
779 		verifyProgramParam	(m_testCtx, *this, shaderProg, GL_LINK_STATUS, GL_TRUE);
780 
781 		verifyShaderParam	(m_testCtx, *this, shaderVert, GL_DELETE_STATUS, GL_FALSE);
782 		verifyShaderParam	(m_testCtx, *this, shaderFrag, GL_DELETE_STATUS, GL_FALSE);
783 		verifyProgramParam	(m_testCtx, *this, shaderProg, GL_DELETE_STATUS, GL_FALSE);
784 		expectError(GL_NO_ERROR);
785 
786 		glUseProgram(shaderProg);
787 
788 		glDeleteShader(shaderVert);
789 		glDeleteShader(shaderFrag);
790 		glDeleteProgram(shaderProg);
791 		expectError(GL_NO_ERROR);
792 
793 		verifyShaderParam	(m_testCtx, *this, shaderVert, GL_DELETE_STATUS, GL_TRUE);
794 		verifyShaderParam	(m_testCtx, *this, shaderFrag, GL_DELETE_STATUS, GL_TRUE);
795 		verifyProgramParam	(m_testCtx, *this, shaderProg, GL_DELETE_STATUS, GL_TRUE);
796 		expectError(GL_NO_ERROR);
797 
798 		glUseProgram(0);
799 		expectError(GL_NO_ERROR);
800 	}
801 };
802 
803 class CurrentVertexAttribInitialCase : public ApiCase
804 {
805 public:
CurrentVertexAttribInitialCase(Context & context,const char * name,const char * description)806 	CurrentVertexAttribInitialCase (Context& context, const char* name, const char* description)
807 		: ApiCase(context, name, description)
808 	{
809 	}
810 
test(void)811 	void test (void)
812 	{
813 		using tcu::TestLog;
814 
815 		int attribute_count = 16;
816 		glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &attribute_count);
817 
818 		// initial
819 
820 		for (int index = 0; index < attribute_count; ++index)
821 		{
822 			StateQueryMemoryWriteGuard<GLfloat[4]> attribValue;
823 			glGetVertexAttribfv(index, GL_CURRENT_VERTEX_ATTRIB, attribValue);
824 			attribValue.verifyValidity(m_testCtx);
825 
826 			if (attribValue[0] != 0.0f || attribValue[1] != 0.0f || attribValue[2] != 0.0f || attribValue[3] != 1.0f)
827 			{
828 				m_testCtx.getLog() << TestLog::Message
829 					<< "// ERROR: Expected [0, 0, 0, 1];"
830 					<< "got [" << attribValue[0] << "," << attribValue[1] << "," << attribValue[2] << "," << attribValue[3] << "]"
831 					<< TestLog::EndMessage;
832 				if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
833 					m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid attribute value");
834 			}
835 		}
836 	}
837 };
838 
839 class CurrentVertexAttribFloatCase : public ApiCase
840 {
841 public:
CurrentVertexAttribFloatCase(Context & context,const char * name,const char * description)842 	CurrentVertexAttribFloatCase (Context& context, const char* name, const char* description)
843 		: ApiCase(context, name, description)
844 	{
845 	}
846 
test(void)847 	void test (void)
848 	{
849 		using tcu::TestLog;
850 
851 		de::Random rnd(0xabcdef);
852 
853 		int attribute_count = 16;
854 		glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &attribute_count);
855 
856 		// test write float/read float
857 
858 		for (int index = 0; index < attribute_count; ++index)
859 		{
860 			const GLfloat x = rnd.getFloat(-64000, 64000);
861 			const GLfloat y = rnd.getFloat(-64000, 64000);
862 			const GLfloat z = rnd.getFloat(-64000, 64000);
863 			const GLfloat w = rnd.getFloat(-64000, 64000);
864 
865 			glVertexAttrib4f(index, x, y, z, w);
866 			verifyCurrentVertexAttribf(m_testCtx, *this, index, x, y, z, w);
867 		}
868 		for (int index = 0; index < attribute_count; ++index)
869 		{
870 			const GLfloat x = rnd.getFloat(-64000, 64000);
871 			const GLfloat y = rnd.getFloat(-64000, 64000);
872 			const GLfloat z = rnd.getFloat(-64000, 64000);
873 			const GLfloat w = 1.0f;
874 
875 			glVertexAttrib3f(index, x, y, z);
876 			verifyCurrentVertexAttribf(m_testCtx, *this, index, x, y, z, w);
877 		}
878 		for (int index = 0; index < attribute_count; ++index)
879 		{
880 			const GLfloat x = rnd.getFloat(-64000, 64000);
881 			const GLfloat y = rnd.getFloat(-64000, 64000);
882 			const GLfloat z = 0.0f;
883 			const GLfloat w = 1.0f;
884 
885 			glVertexAttrib2f(index, x, y);
886 			verifyCurrentVertexAttribf(m_testCtx, *this, index, x, y, z, w);
887 		}
888 		for (int index = 0; index < attribute_count; ++index)
889 		{
890 			const GLfloat x = rnd.getFloat(-64000, 64000);
891 			const GLfloat y = 0.0f;
892 			const GLfloat z = 0.0f;
893 			const GLfloat w = 1.0f;
894 
895 			glVertexAttrib1f(index, x);
896 			verifyCurrentVertexAttribf(m_testCtx, *this, index, x, y, z, w);
897 		}
898 	}
899 };
900 
901 class CurrentVertexAttribConversionCase : public ApiCase
902 {
903 public:
CurrentVertexAttribConversionCase(Context & context,const char * name,const char * description)904 	CurrentVertexAttribConversionCase (Context& context, const char* name, const char* description)
905 		: ApiCase(context, name, description)
906 	{
907 	}
908 
test(void)909 	void test (void)
910 	{
911 		using tcu::TestLog;
912 
913 		de::Random rnd(0xabcdef);
914 
915 		int attribute_count = 16;
916 		glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &attribute_count);
917 
918 		// test write float/read float
919 
920 		for (int index = 0; index < attribute_count; ++index)
921 		{
922 			const GLfloat x = rnd.getFloat(-64000, 64000);
923 			const GLfloat y = rnd.getFloat(-64000, 64000);
924 			const GLfloat z = rnd.getFloat(-64000, 64000);
925 			const GLfloat w = rnd.getFloat(-64000, 64000);
926 
927 			glVertexAttrib4f(index, x, y, z, w);
928 			verifyCurrentVertexAttribConversion(m_testCtx, *this, index, x, y, z, w);
929 		}
930 		for (int index = 0; index < attribute_count; ++index)
931 		{
932 			const GLfloat x = rnd.getFloat(-64000, 64000);
933 			const GLfloat y = rnd.getFloat(-64000, 64000);
934 			const GLfloat z = rnd.getFloat(-64000, 64000);
935 			const GLfloat w = 1.0f;
936 
937 			glVertexAttrib3f(index, x, y, z);
938 			verifyCurrentVertexAttribConversion(m_testCtx, *this, index, x, y, z, w);
939 		}
940 		for (int index = 0; index < attribute_count; ++index)
941 		{
942 			const GLfloat x = rnd.getFloat(-64000, 64000);
943 			const GLfloat y = rnd.getFloat(-64000, 64000);
944 			const GLfloat z = 0.0f;
945 			const GLfloat w = 1.0f;
946 
947 			glVertexAttrib2f(index, x, y);
948 			verifyCurrentVertexAttribConversion(m_testCtx, *this, index, x, y, z, w);
949 		}
950 		for (int index = 0; index < attribute_count; ++index)
951 		{
952 			const GLfloat x = rnd.getFloat(-64000, 64000);
953 			const GLfloat y = 0.0f;
954 			const GLfloat z = 0.0f;
955 			const GLfloat w = 1.0f;
956 
957 			glVertexAttrib1f(index, x);
958 			verifyCurrentVertexAttribConversion(m_testCtx, *this, index, x, y, z, w);
959 		}
960 	}
961 };
962 
963 class ProgramInfoLogCase : public ApiCase
964 {
965 public:
ProgramInfoLogCase(Context & context,const char * name,const char * description)966 	ProgramInfoLogCase (Context& context, const char* name, const char* description)
967 		: ApiCase(context, name, description)
968 	{
969 	}
970 
test(void)971 	void test (void)
972 	{
973 		using tcu::TestLog;
974 
975 		GLuint shaderVert = glCreateShader(GL_VERTEX_SHADER);
976 		GLuint shaderFrag = glCreateShader(GL_FRAGMENT_SHADER);
977 
978 		glShaderSource(shaderVert, 1, &brokenShader, DE_NULL);
979 		glShaderSource(shaderFrag, 1, &brokenShader, DE_NULL);
980 
981 		glCompileShader(shaderVert);
982 		glCompileShader(shaderFrag);
983 		expectError(GL_NO_ERROR);
984 
985 		GLuint program = glCreateProgram();
986 		glAttachShader(program, shaderVert);
987 		glAttachShader(program, shaderFrag);
988 		glLinkProgram(program);
989 
990 		// check INFO_LOG_LENGTH == GetProgramInfoLog len
991 		{
992 			char buffer[2048] = {'x'};
993 
994 			GLint written = 0;
995 			glGetProgramInfoLog(program, DE_LENGTH_OF_ARRAY(buffer), &written, buffer);
996 
997 			StateQueryMemoryWriteGuard<GLint> logLength;
998 			glGetProgramiv(program, GL_INFO_LOG_LENGTH, &logLength);
999 			logLength.verifyValidity(m_testCtx);
1000 
1001 			if (logLength != 0 && written+1 != logLength) // INFO_LOG_LENGTH contains 0-terminator
1002 			{
1003 				m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected INFO_LOG_LENGTH " << written+1 << "; got " << logLength << TestLog::EndMessage;
1004 				if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
1005 					m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid log length");
1006 			}
1007 		}
1008 
1009 		// check GetProgramInfoLog works with too small buffer
1010 		{
1011 			char buffer[2048] = {'x'};
1012 
1013 			GLint written = 0;
1014 			glGetProgramInfoLog(program, 1, &written, buffer);
1015 
1016 			if (written != 0)
1017 			{
1018 				m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected write length 0; got " << written << TestLog::EndMessage;
1019 				if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
1020 					m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid log length");
1021 			}
1022 		}
1023 
1024 		glDeleteShader(shaderVert);
1025 		glDeleteShader(shaderFrag);
1026 		glDeleteProgram(program);
1027 		expectError(GL_NO_ERROR);
1028 	}
1029 };
1030 
1031 class ProgramValidateStatusCase : public ApiCase
1032 {
1033 public:
ProgramValidateStatusCase(Context & context,const char * name,const char * description)1034 	ProgramValidateStatusCase (Context& context, const char* name, const char* description)
1035 		: ApiCase(context, name, description)
1036 	{
1037 	}
1038 
test(void)1039 	void test (void)
1040 	{
1041 		// test validate ok
1042 		{
1043 			GLuint shaderVert = glCreateShader(GL_VERTEX_SHADER);
1044 			GLuint shaderFrag = glCreateShader(GL_FRAGMENT_SHADER);
1045 
1046 			glShaderSource(shaderVert, 1, &commonTestVertSource, DE_NULL);
1047 			glShaderSource(shaderFrag, 1, &commonTestFragSource, DE_NULL);
1048 
1049 			glCompileShader(shaderVert);
1050 			glCompileShader(shaderFrag);
1051 			expectError(GL_NO_ERROR);
1052 
1053 			GLuint program = glCreateProgram();
1054 			glAttachShader(program, shaderVert);
1055 			glAttachShader(program, shaderFrag);
1056 			glLinkProgram(program);
1057 			expectError(GL_NO_ERROR);
1058 
1059 			verifyShaderParam	(m_testCtx, *this, shaderVert,	GL_COMPILE_STATUS,	GL_TRUE);
1060 			verifyShaderParam	(m_testCtx, *this, shaderFrag,	GL_COMPILE_STATUS,	GL_TRUE);
1061 			verifyProgramParam	(m_testCtx, *this, program,		GL_LINK_STATUS,		GL_TRUE);
1062 
1063 			glValidateProgram(program);
1064 			verifyProgramParam(m_testCtx, *this, program, GL_VALIDATE_STATUS, GL_TRUE);
1065 
1066 			glDeleteShader(shaderVert);
1067 			glDeleteShader(shaderFrag);
1068 			glDeleteProgram(program);
1069 			expectError(GL_NO_ERROR);
1070 		}
1071 
1072 		// test with broken shader
1073 		{
1074 			GLuint shaderVert = glCreateShader(GL_VERTEX_SHADER);
1075 			GLuint shaderFrag = glCreateShader(GL_FRAGMENT_SHADER);
1076 
1077 			glShaderSource(shaderVert, 1, &commonTestVertSource,	DE_NULL);
1078 			glShaderSource(shaderFrag, 1, &brokenShader,			DE_NULL);
1079 
1080 			glCompileShader(shaderVert);
1081 			glCompileShader(shaderFrag);
1082 			expectError(GL_NO_ERROR);
1083 
1084 			GLuint program = glCreateProgram();
1085 			glAttachShader(program, shaderVert);
1086 			glAttachShader(program, shaderFrag);
1087 			glLinkProgram(program);
1088 			expectError(GL_NO_ERROR);
1089 
1090 			verifyShaderParam	(m_testCtx, *this, shaderVert,	GL_COMPILE_STATUS,	GL_TRUE);
1091 			verifyShaderParam	(m_testCtx, *this, shaderFrag,	GL_COMPILE_STATUS,	GL_FALSE);
1092 			verifyProgramParam	(m_testCtx, *this, program,		GL_LINK_STATUS,		GL_FALSE);
1093 
1094 			glValidateProgram(program);
1095 			verifyProgramParam(m_testCtx, *this, program, GL_VALIDATE_STATUS, GL_FALSE);
1096 
1097 			glDeleteShader(shaderVert);
1098 			glDeleteShader(shaderFrag);
1099 			glDeleteProgram(program);
1100 			expectError(GL_NO_ERROR);
1101 		}
1102 	}
1103 };
1104 
1105 class ProgramAttachedShadersCase : public ApiCase
1106 {
1107 public:
ProgramAttachedShadersCase(Context & context,const char * name,const char * description)1108 	ProgramAttachedShadersCase (Context& context, const char* name, const char* description)
1109 		: ApiCase(context, name, description)
1110 	{
1111 	}
1112 
test(void)1113 	void test (void)
1114 	{
1115 		using tcu::TestLog;
1116 
1117 		GLuint shaderVert = glCreateShader(GL_VERTEX_SHADER);
1118 		GLuint shaderFrag = glCreateShader(GL_FRAGMENT_SHADER);
1119 
1120 		glShaderSource(shaderVert, 1, &commonTestVertSource, DE_NULL);
1121 		glShaderSource(shaderFrag, 1, &commonTestFragSource, DE_NULL);
1122 
1123 		glCompileShader(shaderVert);
1124 		glCompileShader(shaderFrag);
1125 		expectError(GL_NO_ERROR);
1126 
1127 		// check ATTACHED_SHADERS
1128 
1129 		GLuint program = glCreateProgram();
1130 		verifyProgramParam(m_testCtx, *this, program, GL_ATTACHED_SHADERS, 0);
1131 		expectError(GL_NO_ERROR);
1132 
1133 		glAttachShader(program, shaderVert);
1134 		verifyProgramParam(m_testCtx, *this, program, GL_ATTACHED_SHADERS, 1);
1135 		expectError(GL_NO_ERROR);
1136 
1137 		glAttachShader(program, shaderFrag);
1138 		verifyProgramParam(m_testCtx, *this, program, GL_ATTACHED_SHADERS, 2);
1139 		expectError(GL_NO_ERROR);
1140 
1141 		// check GetAttachedShaders
1142 		{
1143 			GLuint shaders[2] = {0, 0};
1144 			GLint count = 0;
1145 			glGetAttachedShaders(program, DE_LENGTH_OF_ARRAY(shaders), &count, shaders);
1146 
1147 			if (count != 2)
1148 			{
1149 				m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected 2; got " << count << TestLog::EndMessage;
1150 				if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
1151 					m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got wrong shader count");
1152 			}
1153 			// shaders are the attached shaders?
1154 			if (!((shaders[0] == shaderVert && shaders[1] == shaderFrag) ||
1155 				  (shaders[0] == shaderFrag && shaders[1] == shaderVert)))
1156 			{
1157 				m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected {" << shaderVert << ", " << shaderFrag << "}; got {" << shaders[0] << ", " << shaders[1] << "}" << TestLog::EndMessage;
1158 				if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
1159 					m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got wrong shader count");
1160 			}
1161 		}
1162 
1163 		// check GetAttachedShaders with too small buffer
1164 		{
1165 			GLuint shaders[2] = {0, 0};
1166 			GLint count = 0;
1167 
1168 			glGetAttachedShaders(program, 0, &count, shaders);
1169 			if (count != 0)
1170 			{
1171 				m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected 0; got " << count << TestLog::EndMessage;
1172 				if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
1173 					m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got wrong shader count");
1174 			}
1175 
1176 			count = 0;
1177 			glGetAttachedShaders(program, 1, &count, shaders);
1178 			if (count != 1)
1179 			{
1180 				m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected 1; got " << count << TestLog::EndMessage;
1181 				if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
1182 					m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got wrong shader count");
1183 			}
1184 		}
1185 
1186 		glDeleteShader(shaderVert);
1187 		glDeleteShader(shaderFrag);
1188 		glDeleteProgram(program);
1189 		expectError(GL_NO_ERROR);
1190 	}
1191 };
1192 
1193 class ProgramActiveUniformNameCase : public ApiCase
1194 {
1195 public:
ProgramActiveUniformNameCase(Context & context,const char * name,const char * description)1196 	ProgramActiveUniformNameCase (Context& context, const char* name, const char* description)
1197 		: ApiCase(context, name, description)
1198 	{
1199 	}
1200 
test(void)1201 	void test (void)
1202 	{
1203 		using tcu::TestLog;
1204 
1205 		static const char* testVertSource =
1206 			"uniform highp float uniformNameWithLength23;\n"
1207 			"uniform highp vec2 uniformVec2;\n"
1208 			"uniform highp mat4 uniformMat4;\n"
1209 			"void main (void)\n"
1210 			"{\n"
1211 			"	gl_Position = vec4(0.0) + vec4(uniformNameWithLength23) + vec4(uniformVec2.x) + vec4(uniformMat4[2][3]);\n"
1212 			"}\n\0";
1213 		static const char* testFragSource =
1214 
1215 			"void main (void)\n"
1216 			"{\n"
1217 			"	gl_FragColor = vec4(0.0);\n"
1218 			"}\n\0";
1219 
1220 		GLuint shaderVert = glCreateShader(GL_VERTEX_SHADER);
1221 		GLuint shaderFrag = glCreateShader(GL_FRAGMENT_SHADER);
1222 
1223 		glShaderSource(shaderVert, 1, &testVertSource, DE_NULL);
1224 		glShaderSource(shaderFrag, 1, &testFragSource, DE_NULL);
1225 
1226 		glCompileShader(shaderVert);
1227 		glCompileShader(shaderFrag);
1228 		expectError(GL_NO_ERROR);
1229 
1230 		GLuint program = glCreateProgram();
1231 		glAttachShader(program, shaderVert);
1232 		glAttachShader(program, shaderFrag);
1233 		glLinkProgram(program);
1234 		expectError(GL_NO_ERROR);
1235 
1236 		verifyProgramParam(m_testCtx, *this, program, GL_ACTIVE_UNIFORMS, 3);
1237 		verifyProgramParam(m_testCtx, *this, program, GL_ACTIVE_UNIFORM_MAX_LENGTH, (GLint)std::string("uniformNameWithLength23").length() + 1); // including a null terminator
1238 		expectError(GL_NO_ERROR);
1239 
1240 		const char* uniformNames[] =
1241 		{
1242 			"uniformNameWithLength23",
1243 			"uniformVec2",
1244 			"uniformMat4"
1245 		};
1246 
1247 		// check names
1248 		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(uniformNames); ++ndx)
1249 		{
1250 			char  buffer[2048]	= {'x'};
1251 			char* bufferEnd		= (buffer + 1);
1252 
1253 			GLint written = 0; // null terminator not included
1254 			GLint size = 0;
1255 			GLenum type = 0;
1256 			glGetActiveUniform(program, ndx, DE_LENGTH_OF_ARRAY(buffer), &written, &size, &type, buffer);
1257 
1258 			if (written < DE_LENGTH_OF_ARRAY(buffer))
1259 				bufferEnd = &buffer[written];
1260 
1261 			// find matching uniform
1262 			{
1263 				const std::string uniformName(buffer, bufferEnd);
1264 				bool found = false;
1265 
1266 				for (int uniformNdx = 0; uniformNdx < DE_LENGTH_OF_ARRAY(uniformNames); ++uniformNdx)
1267 				{
1268 					if (uniformName == uniformNames[uniformNdx])
1269 					{
1270 						found = true;
1271 						break;
1272 					}
1273 				}
1274 
1275 				if (!found)
1276 				{
1277 					m_testCtx.getLog() << TestLog::Message << "// ERROR: Got unknown uniform name: " << uniformName << TestLog::EndMessage;
1278 					if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
1279 						m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got wrong uniform name");
1280 				}
1281 			}
1282 
1283 			// and with too small buffer
1284 			written = 0;
1285 			glGetActiveUniform(program, ndx, 1, &written, &size, &type, buffer);
1286 
1287 			if (written != 0)
1288 			{
1289 				m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected 0 got " << written << TestLog::EndMessage;
1290 				if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
1291 					m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got wrong uniform name length");
1292 			}
1293 		}
1294 
1295 
1296 		glDeleteShader(shaderVert);
1297 		glDeleteShader(shaderFrag);
1298 		glDeleteProgram(program);
1299 		expectError(GL_NO_ERROR);
1300 	}
1301 };
1302 
1303 class ProgramUniformCase : public ApiCase
1304 {
1305 public:
ProgramUniformCase(Context & context,const char * name,const char * description)1306 	ProgramUniformCase (Context& context, const char* name, const char* description)
1307 		: ApiCase(context, name, description)
1308 	{
1309 	}
1310 
test(void)1311 	void test (void)
1312 	{
1313 		const struct UniformType
1314 		{
1315 			const char* declaration;
1316 			const char* postDeclaration;
1317 			const char* precision;
1318 			const char* layout;
1319 			const char* getter;
1320 			GLenum		type;
1321 			GLint		size;
1322 			GLint		isRowMajor;
1323 		} uniformTypes[] =
1324 		{
1325 			{ "float",					"",			"highp",	"",				"uniformValue",													GL_FLOAT,							1, GL_FALSE },
1326 			{ "float",					"[2]",		"highp",	"",				"uniformValue[1]",												GL_FLOAT,							2, GL_FALSE },
1327 			{ "vec2",					"",			"highp",	"",				"uniformValue.x",												GL_FLOAT_VEC2,						1, GL_FALSE },
1328 			{ "vec3",					"",			"highp",	"",				"uniformValue.x",												GL_FLOAT_VEC3,						1, GL_FALSE },
1329 			{ "vec4",					"",			"highp",	"",				"uniformValue.x",												GL_FLOAT_VEC4,						1, GL_FALSE },
1330 			{ "int",					"",			"highp",	"",				"float(uniformValue)",											GL_INT,								1, GL_FALSE },
1331 			{ "ivec2",					"",			"highp",	"",				"float(uniformValue.x)",										GL_INT_VEC2,						1, GL_FALSE },
1332 			{ "ivec3",					"",			"highp",	"",				"float(uniformValue.x)",										GL_INT_VEC3,						1, GL_FALSE },
1333 			{ "ivec4",					"",			"highp",	"",				"float(uniformValue.x)",										GL_INT_VEC4,						1, GL_FALSE },
1334 			{ "bool",					"",			"",			"",				"float(uniformValue)",											GL_BOOL,							1, GL_FALSE },
1335 			{ "bvec2",					"",			"",			"",				"float(uniformValue.x)",										GL_BOOL_VEC2,						1, GL_FALSE },
1336 			{ "bvec3",					"",			"",			"",				"float(uniformValue.x)",										GL_BOOL_VEC3,						1, GL_FALSE },
1337 			{ "bvec4",					"",			"",			"",				"float(uniformValue.x)",										GL_BOOL_VEC4,						1, GL_FALSE },
1338 			{ "mat2",					"",			"highp",	"",				"float(uniformValue[0][0])",									GL_FLOAT_MAT2,						1, GL_FALSE },
1339 			{ "mat3",					"",			"highp",	"",				"float(uniformValue[0][0])",									GL_FLOAT_MAT3,						1, GL_FALSE },
1340 			{ "mat4",					"",			"highp",	"",				"float(uniformValue[0][0])",									GL_FLOAT_MAT4,						1, GL_FALSE },
1341 			{ "sampler2D",				"",			"highp",	"",				"float(texture2D(uniformValue, vec2(0.0, 0.0)).r)",				GL_SAMPLER_2D,						1, GL_FALSE },
1342 			{ "samplerCube",			"",			"highp",	"",				"float(textureCube(uniformValue, vec3(0.0, 0.0, 0.0)).r)",		GL_SAMPLER_CUBE,					1, GL_FALSE },
1343 		};
1344 
1345 		static const char* vertSource =
1346 			"void main (void)\n"
1347 			"{\n"
1348 			"	gl_Position = vec4(0.0);\n"
1349 			"}\n\0";
1350 
1351 		GLuint shaderVert	= glCreateShader(GL_VERTEX_SHADER);
1352 		GLuint shaderFrag	= glCreateShader(GL_FRAGMENT_SHADER);
1353 		GLuint program		= glCreateProgram();
1354 
1355 		glAttachShader(program, shaderVert);
1356 		glAttachShader(program, shaderFrag);
1357 
1358 		glShaderSource(shaderVert, 1, &vertSource, DE_NULL);
1359 		glCompileShader(shaderVert);
1360 		expectError(GL_NO_ERROR);
1361 
1362 		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(uniformTypes); ++ndx)
1363 		{
1364 			tcu::ScopedLogSection(m_log, uniformTypes[ndx].declaration, std::string("Verify type of ") + uniformTypes[ndx].declaration + " variable" + uniformTypes[ndx].postDeclaration );
1365 
1366 			// gen fragment shader
1367 
1368 			std::ostringstream frag;
1369 			frag << uniformTypes[ndx].layout << "uniform " << uniformTypes[ndx].precision << " " << uniformTypes[ndx].declaration << " uniformValue" << uniformTypes[ndx].postDeclaration << ";\n";
1370 			frag << "void main (void)\n";
1371 			frag << "{\n";
1372 			frag << "	gl_FragColor = vec4(" << uniformTypes[ndx].getter << ");\n";
1373 			frag << "}\n";
1374 
1375 			{
1376 				std::string fragmentSource = frag.str();
1377 				const char* fragmentSourceCStr = fragmentSource.c_str();
1378 				glShaderSource(shaderFrag, 1, &fragmentSourceCStr, DE_NULL);
1379 			}
1380 
1381 			// compile & link
1382 
1383 			glCompileShader(shaderFrag);
1384 			glLinkProgram(program);
1385 
1386 			// test
1387 			if (verifyProgramParam(m_testCtx, *this, program, GL_LINK_STATUS, GL_TRUE))
1388 			{
1389 				const GLint index = 0; // first and only active uniform
1390 
1391 				char buffer[]	= "not written to"; // not written to
1392 				GLint written	= 0;
1393 				GLint size		= 0;
1394 				GLenum type		= 0;
1395 				glGetActiveUniform(program, index, 0, &written, &size, &type, buffer);
1396 
1397 				checkIntEquals(m_testCtx, type, uniformTypes[ndx].type);
1398 				checkIntEquals(m_testCtx, size, uniformTypes[ndx].size);
1399 			}
1400 		}
1401 
1402 		glDeleteShader(shaderVert);
1403 		glDeleteShader(shaderFrag);
1404 		glDeleteProgram(program);
1405 		expectError(GL_NO_ERROR);
1406 	}
1407 };
1408 
1409 class ActiveAttributesCase : public ApiCase
1410 {
1411 public:
ActiveAttributesCase(Context & context,const char * name,const char * description)1412 	ActiveAttributesCase (Context& context, const char* name, const char* description)
1413 		: ApiCase(context, name, description)
1414 	{
1415 	}
1416 
test(void)1417 	void test (void)
1418 	{
1419 		using tcu::TestLog;
1420 
1421 		static const char* testVertSource =
1422 			"attribute highp vec2 longInputAttributeName;\n"
1423 			"attribute highp vec2 shortName;\n"
1424 			"void main (void)\n"
1425 			"{\n"
1426 			"	gl_Position = longInputAttributeName.yxxy + shortName.xyxy;\n"
1427 			"}\n\0";
1428 		static const char* testFragSource =
1429 			"void main (void)\n"
1430 			"{\n"
1431 			"	gl_FragColor = vec4(0.0);\n"
1432 			"}\n\0";
1433 
1434 		GLuint shaderVert = glCreateShader(GL_VERTEX_SHADER);
1435 		GLuint shaderFrag = glCreateShader(GL_FRAGMENT_SHADER);
1436 
1437 		glShaderSource(shaderVert, 1, &testVertSource, DE_NULL);
1438 		glShaderSource(shaderFrag, 1, &testFragSource, DE_NULL);
1439 
1440 		glCompileShader(shaderVert);
1441 		glCompileShader(shaderFrag);
1442 		expectError(GL_NO_ERROR);
1443 
1444 		GLuint program = glCreateProgram();
1445 		glAttachShader(program, shaderVert);
1446 		glAttachShader(program, shaderFrag);
1447 		glLinkProgram(program);
1448 		expectError(GL_NO_ERROR);
1449 
1450 		verifyProgramParam(m_testCtx, *this, program, GL_ACTIVE_ATTRIBUTES, 2);
1451 		verifyProgramParam(m_testCtx, *this, program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, (GLint)std::string("longInputAttributeName").length() + 1); // does include null-terminator
1452 
1453 		// check names
1454 		for (int attributeNdx = 0; attributeNdx < 2; ++attributeNdx)
1455 		{
1456 			char buffer[2048] = {'x'};
1457 
1458 			GLint written = 0;
1459 			GLint size = 0;
1460 			GLenum type = 0;
1461 			glGetActiveAttrib(program, attributeNdx, DE_LENGTH_OF_ARRAY(buffer), &written, &size, &type, buffer);
1462 			expectError(GL_NO_ERROR);
1463 
1464 			if (deStringBeginsWith(buffer, "longInputAttributeName"))
1465 			{
1466 				checkIntEquals(m_testCtx, written, (GLint)std::string("longInputAttributeName").length()); // does NOT include null-terminator
1467 			}
1468 			else if (deStringBeginsWith(buffer, "shortName"))
1469 			{
1470 				checkIntEquals(m_testCtx, written, (GLint)std::string("shortName").length()); // does NOT include null-terminator
1471 			}
1472 			else
1473 			{
1474 				m_testCtx.getLog() << TestLog::Message << "// ERROR: Got unexpected attribute name." << TestLog::EndMessage;
1475 				if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
1476 					m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got unexpected name");
1477 			}
1478 		}
1479 
1480 		// and with too short buffer
1481 		{
1482 			char buffer[2048] = {'x'};
1483 
1484 			GLint written = 0;
1485 			GLint size = 0;
1486 			GLenum type = 0;
1487 
1488 			glGetActiveAttrib(program, 0, 1, &written, &size, &type, buffer);
1489 			expectError(GL_NO_ERROR);
1490 			checkIntEquals(m_testCtx, written, 0);
1491 		}
1492 
1493 		glDeleteShader(shaderVert);
1494 		glDeleteShader(shaderFrag);
1495 		glDeleteProgram(program);
1496 		expectError(GL_NO_ERROR);
1497 	}
1498 };
1499 
1500 struct PointerData
1501 {
1502 	GLint		size;
1503 	GLenum		type;
1504 	GLint		stride;
1505 	GLboolean	normalized;
1506 	void*		pointer;
1507 };
1508 
1509 class VertexAttributeSizeCase : public ApiCase
1510 {
1511 public:
VertexAttributeSizeCase(Context & context,const char * name,const char * description)1512 	VertexAttributeSizeCase (Context& context, const char* name, const char* description)
1513 		: ApiCase(context, name, description)
1514 	{
1515 	}
1516 
test(void)1517 	void test (void)
1518 	{
1519 		GLfloat vertexData[4] = {0.0f}; // never accessed
1520 
1521 		// test VertexAttribPointer
1522 		const PointerData pointers[] =
1523 		{
1524 			// size test
1525 			{ 4, GL_FLOAT,		0,	GL_FALSE, vertexData },
1526 			{ 3, GL_FLOAT,		0,	GL_FALSE, vertexData },
1527 			{ 2, GL_FLOAT,		0,	GL_FALSE, vertexData },
1528 			{ 1, GL_FLOAT,		0,	GL_FALSE, vertexData },
1529 			{ 4, GL_SHORT,		0,	GL_FALSE, vertexData },
1530 			{ 3, GL_SHORT,		0,	GL_FALSE, vertexData },
1531 			{ 2, GL_SHORT,		0,	GL_FALSE, vertexData },
1532 			{ 1, GL_SHORT,		0,	GL_FALSE, vertexData },
1533 		};
1534 
1535 		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(pointers); ++ndx)
1536 		{
1537 			glVertexAttribPointer(0, pointers[ndx].size, pointers[ndx].type, pointers[ndx].normalized, pointers[ndx].stride, pointers[ndx].pointer);
1538 			expectError(GL_NO_ERROR);
1539 
1540 			verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_SIZE, pointers[ndx].size);
1541 		}
1542 	}
1543 };
1544 
1545 class VertexAttributeTypeCase : public ApiCase
1546 {
1547 public:
VertexAttributeTypeCase(Context & context,const char * name,const char * description)1548 	VertexAttributeTypeCase (Context& context, const char* name, const char* description)
1549 		: ApiCase(context, name, description)
1550 	{
1551 	}
1552 
test(void)1553 	void test (void)
1554 	{
1555 		GLfloat vertexData[4] = {0.0f}; // never accessed
1556 
1557 		const PointerData pointers[] =
1558 		{
1559 			{ 1, GL_BYTE,								0,	GL_FALSE, vertexData	},
1560 			{ 1, GL_UNSIGNED_BYTE,						0,	GL_FALSE, vertexData	},
1561 			{ 1, GL_SHORT,								0,	GL_FALSE, vertexData	},
1562 			{ 1, GL_UNSIGNED_SHORT,						0,	GL_FALSE, vertexData	},
1563 			{ 1, GL_FIXED,								0,	GL_FALSE, vertexData	},
1564 			{ 1, GL_FLOAT,								0,	GL_FALSE, vertexData	},
1565 		};
1566 
1567 		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(pointers); ++ndx)
1568 		{
1569 			glVertexAttribPointer(0, pointers[ndx].size, pointers[ndx].type, pointers[ndx].normalized, pointers[ndx].stride, pointers[ndx].pointer);
1570 			expectError(GL_NO_ERROR);
1571 
1572 			verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_TYPE, pointers[ndx].type);
1573 		}
1574 	}
1575 };
1576 
1577 class VertexAttributeStrideCase : public ApiCase
1578 {
1579 public:
VertexAttributeStrideCase(Context & context,const char * name,const char * description)1580 	VertexAttributeStrideCase (Context& context, const char* name, const char* description)
1581 		: ApiCase(context, name, description)
1582 	{
1583 	}
1584 
test(void)1585 	void test (void)
1586 	{
1587 		GLfloat vertexData[4] = {0.0f}; // never accessed
1588 
1589 		struct StridePointerData
1590 		{
1591 			GLint		size;
1592 			GLenum		type;
1593 			GLint		stride;
1594 			void*		pointer;
1595 		};
1596 
1597 		// test VertexAttribPointer
1598 		{
1599 			const StridePointerData pointers[] =
1600 			{
1601 				{ 1, GL_FLOAT,				0,	vertexData },
1602 				{ 1, GL_FLOAT,				1,	vertexData },
1603 				{ 1, GL_FLOAT,				4,	vertexData },
1604 				{ 1, GL_SHORT,				0,	vertexData },
1605 				{ 1, GL_SHORT,				1,	vertexData },
1606 				{ 1, GL_SHORT,				4,	vertexData },
1607 				{ 1, GL_FIXED,				0,	vertexData },
1608 				{ 1, GL_FIXED,				1,	vertexData },
1609 				{ 1, GL_FIXED,				4,	vertexData },
1610 				{ 1, GL_BYTE,				0,	vertexData },
1611 				{ 1, GL_UNSIGNED_SHORT,		1,	vertexData },
1612 				{ 1, GL_UNSIGNED_SHORT,		4,	vertexData },
1613 				{ 4, GL_UNSIGNED_BYTE,		0,	vertexData },
1614 				{ 4, GL_UNSIGNED_BYTE,		1,	vertexData },
1615 				{ 4, GL_UNSIGNED_BYTE,		4,	vertexData },
1616 			};
1617 
1618 			for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(pointers); ++ndx)
1619 			{
1620 				glVertexAttribPointer(0, pointers[ndx].size, pointers[ndx].type, GL_FALSE, pointers[ndx].stride, pointers[ndx].pointer);
1621 				expectError(GL_NO_ERROR);
1622 
1623 				verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_STRIDE, pointers[ndx].stride);
1624 			}
1625 		}
1626 	}
1627 };
1628 
1629 class VertexAttributeNormalizedCase : public ApiCase
1630 {
1631 public:
VertexAttributeNormalizedCase(Context & context,const char * name,const char * description)1632 	VertexAttributeNormalizedCase (Context& context, const char* name, const char* description)
1633 		: ApiCase(context, name, description)
1634 	{
1635 	}
1636 
test(void)1637 	void test (void)
1638 	{
1639 		GLfloat vertexData[4] = {0.0f}; // never accessed
1640 
1641 		// test VertexAttribPointer
1642 		{
1643 			const PointerData pointers[] =
1644 			{
1645 				{ 1, GL_BYTE,								0,	GL_FALSE,	vertexData	},
1646 				{ 1, GL_SHORT,								0,	GL_FALSE,	vertexData	},
1647 				{ 1, GL_UNSIGNED_BYTE,						0,	GL_FALSE,	vertexData	},
1648 				{ 1, GL_UNSIGNED_SHORT,						0,	GL_FALSE,	vertexData	},
1649 				{ 1, GL_BYTE,								0,	GL_TRUE,	vertexData	},
1650 				{ 1, GL_SHORT,								0,	GL_TRUE,	vertexData	},
1651 				{ 1, GL_UNSIGNED_BYTE,						0,	GL_TRUE,	vertexData	},
1652 				{ 1, GL_UNSIGNED_SHORT,						0,	GL_TRUE,	vertexData	},
1653 			};
1654 
1655 			for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(pointers); ++ndx)
1656 			{
1657 				glVertexAttribPointer(0, pointers[ndx].size, pointers[ndx].type, pointers[ndx].normalized, pointers[ndx].stride, pointers[ndx].pointer);
1658 				expectError(GL_NO_ERROR);
1659 
1660 				verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, pointers[ndx].normalized);
1661 			}
1662 		}
1663 	}
1664 };
1665 
1666 class VertexAttributeEnabledCase : public ApiCase
1667 {
1668 public:
VertexAttributeEnabledCase(Context & context,const char * name,const char * description)1669 	VertexAttributeEnabledCase (Context& context, const char* name, const char* description)
1670 		: ApiCase(context, name, description)
1671 	{
1672 	}
1673 
test(void)1674 	void test (void)
1675 	{
1676 		// VERTEX_ATTRIB_ARRAY_ENABLED
1677 
1678 		verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_ENABLED, GL_FALSE);
1679 		glEnableVertexAttribArray(0);
1680 		verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_ENABLED, GL_TRUE);
1681 		glDisableVertexAttribArray(0);
1682 		verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_ENABLED, GL_FALSE);
1683 	}
1684 };
1685 
1686 class VertexAttributeBufferBindingCase : public ApiCase
1687 {
1688 public:
VertexAttributeBufferBindingCase(Context & context,const char * name,const char * description)1689 	VertexAttributeBufferBindingCase (Context& context, const char* name, const char* description)
1690 		: ApiCase(context, name, description)
1691 	{
1692 	}
1693 
test(void)1694 	void test (void)
1695 	{
1696 		// initial
1697 		verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, 0);
1698 
1699 		GLuint bufferID;
1700 		glGenBuffers(1, &bufferID);
1701 		glBindBuffer(GL_ARRAY_BUFFER, bufferID);
1702 		expectError(GL_NO_ERROR);
1703 
1704 		glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, DE_NULL);
1705 		expectError(GL_NO_ERROR);
1706 
1707 		verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, bufferID);
1708 
1709 		glDeleteBuffers(1, &bufferID);
1710 		expectError(GL_NO_ERROR);
1711 	}
1712 };
1713 
1714 class VertexAttributePointerCase : public ApiCase
1715 {
1716 public:
VertexAttributePointerCase(Context & context,const char * name,const char * description)1717 	VertexAttributePointerCase (Context& context, const char* name, const char* description)
1718 		: ApiCase(context, name, description)
1719 	{
1720 	}
1721 
test(void)1722 	void test (void)
1723 	{
1724 		StateQueryMemoryWriteGuard<GLvoid*> initialState;
1725 		glGetVertexAttribPointerv(0, GL_VERTEX_ATTRIB_ARRAY_POINTER, &initialState);
1726 		initialState.verifyValidity(m_testCtx);
1727 		checkPointerEquals(m_testCtx, initialState, 0);
1728 
1729 		GLfloat vertexData[4] = {0.0f}; // never accessed
1730 		const PointerData pointers[] =
1731 		{
1732 			{ 1, GL_BYTE,				0,	GL_FALSE, &vertexData[2] },
1733 			{ 1, GL_SHORT,				0,	GL_FALSE, &vertexData[1] },
1734 			{ 1, GL_FIXED,				0,	GL_FALSE, &vertexData[2] },
1735 			{ 1, GL_FIXED,				0,	GL_FALSE, &vertexData[1] },
1736 			{ 1, GL_FLOAT,				0,	GL_FALSE, &vertexData[0] },
1737 			{ 1, GL_FLOAT,				0,	GL_FALSE, &vertexData[3] },
1738 			{ 1, GL_FLOAT,				0,	GL_FALSE, &vertexData[2] },
1739 			{ 1, GL_UNSIGNED_SHORT,		0,	GL_FALSE, &vertexData[0] },
1740 			{ 4, GL_UNSIGNED_SHORT,		0,	GL_FALSE, &vertexData[1] },
1741 			{ 4, GL_UNSIGNED_SHORT,		0,	GL_FALSE, &vertexData[2] },
1742 		};
1743 
1744 		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(pointers); ++ndx)
1745 		{
1746 			glVertexAttribPointer(0, pointers[ndx].size, pointers[ndx].type, pointers[ndx].normalized, pointers[ndx].stride, pointers[ndx].pointer);
1747 			expectError(GL_NO_ERROR);
1748 
1749 			StateQueryMemoryWriteGuard<GLvoid*> state;
1750 			glGetVertexAttribPointerv(0, GL_VERTEX_ATTRIB_ARRAY_POINTER, &state);
1751 			state.verifyValidity(m_testCtx);
1752 			checkPointerEquals(m_testCtx, state, pointers[ndx].pointer);
1753 		}
1754 	}
1755 };
1756 
1757 class UniformValueFloatCase : public ApiCase
1758 {
1759 public:
UniformValueFloatCase(Context & context,const char * name,const char * description)1760 	UniformValueFloatCase (Context& context, const char* name, const char* description)
1761 		: ApiCase(context, name, description)
1762 	{
1763 	}
1764 
test(void)1765 	void test (void)
1766 	{
1767 		static const char* testVertSource =
1768 			"uniform highp float floatUniform;\n"
1769 			"uniform highp vec2 float2Uniform;\n"
1770 			"uniform highp vec3 float3Uniform;\n"
1771 			"uniform highp vec4 float4Uniform;\n"
1772 			"void main (void)\n"
1773 			"{\n"
1774 			"	gl_Position = vec4(floatUniform + float2Uniform.x + float3Uniform.x + float4Uniform.x);\n"
1775 			"}\n";
1776 		static const char* testFragSource =
1777 
1778 			"void main (void)\n"
1779 			"{\n"
1780 			"	gl_FragColor = vec4(0.0);\n"
1781 			"}\n";
1782 
1783 		glu::ShaderProgram program(m_context.getRenderContext(), glu::makeVtxFragSources(testVertSource, testFragSource));
1784 		if (!program.isOk())
1785 		{
1786 			m_log << program;
1787 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Failed to compile shader");
1788 			return;
1789 		}
1790 
1791 		glUseProgram(program.getProgram());
1792 		expectError(GL_NO_ERROR);
1793 
1794 		GLint location;
1795 
1796 		location = glGetUniformLocation(program.getProgram(), "floatUniform");
1797 		glUniform1f(location, 1.0f);
1798 		verifyUniformValue1f(m_testCtx, *this, program.getProgram(), location, 1.0f);
1799 
1800 		location = glGetUniformLocation(program.getProgram(), "float2Uniform");
1801 		glUniform2f(location, 1.0f, 2.0f);
1802 		verifyUniformValue2f(m_testCtx, *this, program.getProgram(), location, 1.0f, 2.0f);
1803 
1804 		location = glGetUniformLocation(program.getProgram(), "float3Uniform");
1805 		glUniform3f(location, 1.0f, 2.0f, 3.0f);
1806 		verifyUniformValue3f(m_testCtx, *this, program.getProgram(), location, 1.0f, 2.0f, 3.0f);
1807 
1808 		location = glGetUniformLocation(program.getProgram(), "float4Uniform");
1809 		glUniform4f(location, 1.0f, 2.0f, 3.0f, 4.0f);
1810 		verifyUniformValue4f(m_testCtx, *this, program.getProgram(), location, 1.0f, 2.0f, 3.0f, 4.0f);
1811 
1812 		glUseProgram(0);
1813 		expectError(GL_NO_ERROR);
1814 	}
1815 };
1816 
1817 class UniformValueIntCase : public ApiCase
1818 {
1819 public:
UniformValueIntCase(Context & context,const char * name,const char * description)1820 	UniformValueIntCase (Context& context, const char* name, const char* description)
1821 		: ApiCase(context, name, description)
1822 	{
1823 	}
1824 
test(void)1825 	void test (void)
1826 	{
1827 		static const char* testVertSource =
1828 			"uniform highp int intUniform;\n"
1829 			"uniform highp ivec2 int2Uniform;\n"
1830 			"uniform highp ivec3 int3Uniform;\n"
1831 			"uniform highp ivec4 int4Uniform;\n"
1832 			"void main (void)\n"
1833 			"{\n"
1834 			"	gl_Position = vec4(float(intUniform + int2Uniform.x + int3Uniform.x + int4Uniform.x));\n"
1835 			"}\n";
1836 		static const char* testFragSource =
1837 			"void main (void)\n"
1838 			"{\n"
1839 			"	gl_FragColor = vec4(0.0);\n"
1840 			"}\n";
1841 
1842 		glu::ShaderProgram program(m_context.getRenderContext(), glu::makeVtxFragSources(testVertSource, testFragSource));
1843 		if (!program.isOk())
1844 		{
1845 			m_log << program;
1846 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Failed to compile shader");
1847 			return;
1848 		}
1849 
1850 		glUseProgram(program.getProgram());
1851 		expectError(GL_NO_ERROR);
1852 
1853 		GLint location;
1854 
1855 		location = glGetUniformLocation(program.getProgram(), "intUniform");
1856 		glUniform1i(location, 1);
1857 		verifyUniformValue1i(m_testCtx, *this, program.getProgram(), location, 1);
1858 
1859 		location = glGetUniformLocation(program.getProgram(), "int2Uniform");
1860 		glUniform2i(location, 1, 2);
1861 		verifyUniformValue2i(m_testCtx, *this, program.getProgram(), location, 1, 2);
1862 
1863 		location = glGetUniformLocation(program.getProgram(), "int3Uniform");
1864 		glUniform3i(location, 1, 2, 3);
1865 		verifyUniformValue3i(m_testCtx, *this, program.getProgram(), location, 1, 2, 3);
1866 
1867 		location = glGetUniformLocation(program.getProgram(), "int4Uniform");
1868 		glUniform4i(location, 1, 2, 3, 4);
1869 		verifyUniformValue4i(m_testCtx, *this, program.getProgram(), location, 1, 2, 3, 4);
1870 
1871 		glUseProgram(0);
1872 		expectError(GL_NO_ERROR);
1873 	}
1874 };
1875 
1876 class UniformValueBooleanCase : public ApiCase
1877 {
1878 public:
UniformValueBooleanCase(Context & context,const char * name,const char * description)1879 	UniformValueBooleanCase (Context& context, const char* name, const char* description)
1880 		: ApiCase(context, name, description)
1881 	{
1882 	}
1883 
test(void)1884 	void test (void)
1885 	{
1886 		static const char* testVertSource =
1887 			"uniform bool boolUniform;\n"
1888 			"uniform bvec2 bool2Uniform;\n"
1889 			"uniform bvec3 bool3Uniform;\n"
1890 			"uniform bvec4 bool4Uniform;\n"
1891 			"void main (void)\n"
1892 			"{\n"
1893 			"	gl_Position = vec4(float(boolUniform) + float(bool2Uniform.x) + float(bool3Uniform.x) + float(bool4Uniform.x));\n"
1894 			"}\n";
1895 		static const char* testFragSource =
1896 			"void main (void)\n"
1897 			"{\n"
1898 			"	gl_FragColor = vec4(0.0);\n"
1899 			"}\n";
1900 
1901 		glu::ShaderProgram program(m_context.getRenderContext(), glu::makeVtxFragSources(testVertSource, testFragSource));
1902 		if (!program.isOk())
1903 		{
1904 			m_log << program;
1905 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Failed to compile shader");
1906 			return;
1907 		}
1908 
1909 		glUseProgram(program.getProgram());
1910 		expectError(GL_NO_ERROR);
1911 
1912 		GLint location;
1913 
1914 		// int conversion
1915 
1916 		location = glGetUniformLocation(program.getProgram(), "boolUniform");
1917 		glUniform1i(location, 1);
1918 		verifyUniformValue1i(m_testCtx, *this, program.getProgram(), location, 1);
1919 
1920 		location = glGetUniformLocation(program.getProgram(), "bool2Uniform");
1921 		glUniform2i(location, 1, 2);
1922 		verifyUniformValue2i(m_testCtx, *this, program.getProgram(), location, 1, 1);
1923 
1924 		location = glGetUniformLocation(program.getProgram(), "bool3Uniform");
1925 		glUniform3i(location, 0, 1, 2);
1926 		verifyUniformValue3i(m_testCtx, *this, program.getProgram(), location, 0, 1, 1);
1927 
1928 		location = glGetUniformLocation(program.getProgram(), "bool4Uniform");
1929 		glUniform4i(location, 1, 0, 1, -1);
1930 		verifyUniformValue4i(m_testCtx, *this, program.getProgram(), location, 1, 0, 1, 1);
1931 
1932 		// float conversion
1933 
1934 		location = glGetUniformLocation(program.getProgram(), "boolUniform");
1935 		glUniform1f(location, 1.0f);
1936 		verifyUniformValue1i(m_testCtx, *this, program.getProgram(), location, 1);
1937 
1938 		location = glGetUniformLocation(program.getProgram(), "bool2Uniform");
1939 		glUniform2f(location, 1.0f, 0.1f);
1940 		verifyUniformValue2i(m_testCtx, *this, program.getProgram(), location, 1, 1);
1941 
1942 		location = glGetUniformLocation(program.getProgram(), "bool3Uniform");
1943 		glUniform3f(location, 0.0f, 0.1f, -0.1f);
1944 		verifyUniformValue3i(m_testCtx, *this, program.getProgram(), location, 0, 1, 1);
1945 
1946 		location = glGetUniformLocation(program.getProgram(), "bool4Uniform");
1947 		glUniform4f(location, 1.0f, 0.0f, 0.1f, -0.9f);
1948 		verifyUniformValue4i(m_testCtx, *this, program.getProgram(), location, 1, 0, 1, 1);
1949 
1950 		glUseProgram(0);
1951 		expectError(GL_NO_ERROR);
1952 	}
1953 };
1954 
1955 class UniformValueSamplerCase : public ApiCase
1956 {
1957 public:
UniformValueSamplerCase(Context & context,const char * name,const char * description)1958 	UniformValueSamplerCase (Context& context, const char* name, const char* description)
1959 		: ApiCase(context, name, description)
1960 	{
1961 	}
1962 
test(void)1963 	void test (void)
1964 	{
1965 		static const char* testVertSource =
1966 			"void main (void)\n"
1967 			"{\n"
1968 			"	gl_Position = vec4(0.0);\n"
1969 			"}\n";
1970 		static const char* testFragSource =
1971 			"uniform highp sampler2D uniformSampler;\n"
1972 
1973 			"void main (void)\n"
1974 			"{\n"
1975 			"	gl_FragColor = vec4(texture2D(uniformSampler, vec2(0.0, 0.0)).x);\n"
1976 			"}\n";
1977 
1978 		glu::ShaderProgram program(m_context.getRenderContext(), glu::makeVtxFragSources(testVertSource, testFragSource));
1979 		if (!program.isOk())
1980 		{
1981 			m_log << program;
1982 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Failed to compile shader");
1983 			return;
1984 		}
1985 
1986 		glUseProgram(program.getProgram());
1987 		expectError(GL_NO_ERROR);
1988 
1989 		GLint location;
1990 
1991 		location = glGetUniformLocation(program.getProgram(), "uniformSampler");
1992 		glUniform1i(location, 1);
1993 		verifyUniformValue1i(m_testCtx, *this, program.getProgram(), location, 1);
1994 
1995 		glUseProgram(0);
1996 		expectError(GL_NO_ERROR);
1997 	}
1998 };
1999 
2000 class UniformValueArrayCase : public ApiCase
2001 {
2002 public:
UniformValueArrayCase(Context & context,const char * name,const char * description)2003 	UniformValueArrayCase (Context& context, const char* name, const char* description)
2004 		: ApiCase(context, name, description)
2005 	{
2006 	}
2007 
test(void)2008 	void test (void)
2009 	{
2010 		static const char* testVertSource =
2011 			"uniform highp float arrayUniform[5];"
2012 			"uniform highp vec2 array2Uniform[5];"
2013 			"uniform highp vec3 array3Uniform[5];"
2014 			"uniform highp vec4 array4Uniform[5];"
2015 			"void main (void)\n"
2016 			"{\n"
2017 			"	gl_Position = \n"
2018 			"		+ vec4(arrayUniform[0]		+ arrayUniform[1]		+ arrayUniform[2]		+ arrayUniform[3]		+ arrayUniform[4])\n"
2019 			"		+ vec4(array2Uniform[0].x	+ array2Uniform[1].x	+ array2Uniform[2].x	+ array2Uniform[3].x	+ array2Uniform[4].x)\n"
2020 			"		+ vec4(array3Uniform[0].x	+ array3Uniform[1].x	+ array3Uniform[2].x	+ array3Uniform[3].x	+ array3Uniform[4].x)\n"
2021 			"		+ vec4(array4Uniform[0].x	+ array4Uniform[1].x	+ array4Uniform[2].x	+ array4Uniform[3].x	+ array4Uniform[4].x);\n"
2022 			"}\n";
2023 		static const char* testFragSource =
2024 
2025 			"void main (void)\n"
2026 			"{\n"
2027 			"	gl_FragColor = vec4(0.0);\n"
2028 			"}\n";
2029 
2030 		glu::ShaderProgram program(m_context.getRenderContext(), glu::makeVtxFragSources(testVertSource, testFragSource));
2031 		if (!program.isOk())
2032 		{
2033 			m_log << program;
2034 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Failed to compile shader");
2035 			return;
2036 		}
2037 
2038 		glUseProgram(program.getProgram());
2039 		expectError(GL_NO_ERROR);
2040 
2041 		GLint location;
2042 
2043 		float uniformValue[5 * 4] =
2044 		{
2045 			-1.0f,	0.1f,	4.0f,	800.0f,
2046 			13.0f,	55.0f,	12.0f,	91.0f,
2047 			-55.1f,	1.1f,	98.0f,	19.0f,
2048 			41.0f,	65.0f,	4.0f,	12.2f,
2049 			95.0f,	77.0f,	32.0f,	48.0f
2050 		};
2051 
2052 		location = glGetUniformLocation(program.getProgram(), "arrayUniform");
2053 		glUniform1fv(location, 5, uniformValue);
2054 		expectError(GL_NO_ERROR);
2055 
2056 		verifyUniformValue1f(m_testCtx, *this, program.getProgram(), glGetUniformLocation(program.getProgram(), "arrayUniform[0]"), uniformValue[0]);
2057 		verifyUniformValue1f(m_testCtx, *this, program.getProgram(), glGetUniformLocation(program.getProgram(), "arrayUniform[1]"), uniformValue[1]);
2058 		verifyUniformValue1f(m_testCtx, *this, program.getProgram(), glGetUniformLocation(program.getProgram(), "arrayUniform[2]"), uniformValue[2]);
2059 		verifyUniformValue1f(m_testCtx, *this, program.getProgram(), glGetUniformLocation(program.getProgram(), "arrayUniform[3]"), uniformValue[3]);
2060 		verifyUniformValue1f(m_testCtx, *this, program.getProgram(), glGetUniformLocation(program.getProgram(), "arrayUniform[4]"), uniformValue[4]);
2061 		expectError(GL_NO_ERROR);
2062 
2063 		location = glGetUniformLocation(program.getProgram(),"array2Uniform");
2064 		glUniform2fv(location, 5, uniformValue);
2065 		expectError(GL_NO_ERROR);
2066 
2067 		verifyUniformValue2f(m_testCtx, *this, program.getProgram(), glGetUniformLocation(program.getProgram(), "array2Uniform[0]"), uniformValue[2 * 0], uniformValue[(2 * 0) + 1]);
2068 		verifyUniformValue2f(m_testCtx, *this, program.getProgram(), glGetUniformLocation(program.getProgram(), "array2Uniform[1]"), uniformValue[2 * 1], uniformValue[(2 * 1) + 1]);
2069 		verifyUniformValue2f(m_testCtx, *this, program.getProgram(), glGetUniformLocation(program.getProgram(), "array2Uniform[2]"), uniformValue[2 * 2], uniformValue[(2 * 2) + 1]);
2070 		verifyUniformValue2f(m_testCtx, *this, program.getProgram(), glGetUniformLocation(program.getProgram(), "array2Uniform[3]"), uniformValue[2 * 3], uniformValue[(2 * 3) + 1]);
2071 		verifyUniformValue2f(m_testCtx, *this, program.getProgram(), glGetUniformLocation(program.getProgram(), "array2Uniform[4]"), uniformValue[2 * 4], uniformValue[(2 * 4) + 1]);
2072 		expectError(GL_NO_ERROR);
2073 
2074 		location = glGetUniformLocation(program.getProgram(),"array3Uniform");
2075 		glUniform3fv(location, 5, uniformValue);
2076 		expectError(GL_NO_ERROR);
2077 
2078 		verifyUniformValue3f(m_testCtx, *this, program.getProgram(), glGetUniformLocation(program.getProgram(), "array3Uniform[0]"), uniformValue[3 * 0], uniformValue[(3 * 0) + 1], uniformValue[(3 * 0) + 2]);
2079 		verifyUniformValue3f(m_testCtx, *this, program.getProgram(), glGetUniformLocation(program.getProgram(), "array3Uniform[1]"), uniformValue[3 * 1], uniformValue[(3 * 1) + 1], uniformValue[(3 * 1) + 2]);
2080 		verifyUniformValue3f(m_testCtx, *this, program.getProgram(), glGetUniformLocation(program.getProgram(), "array3Uniform[2]"), uniformValue[3 * 2], uniformValue[(3 * 2) + 1], uniformValue[(3 * 2) + 2]);
2081 		verifyUniformValue3f(m_testCtx, *this, program.getProgram(), glGetUniformLocation(program.getProgram(), "array3Uniform[3]"), uniformValue[3 * 3], uniformValue[(3 * 3) + 1], uniformValue[(3 * 3) + 2]);
2082 		verifyUniformValue3f(m_testCtx, *this, program.getProgram(), glGetUniformLocation(program.getProgram(), "array3Uniform[4]"), uniformValue[3 * 4], uniformValue[(3 * 4) + 1], uniformValue[(3 * 4) + 2]);
2083 		expectError(GL_NO_ERROR);
2084 
2085 		location = glGetUniformLocation(program.getProgram(),"array4Uniform");
2086 		glUniform4fv(location, 5, uniformValue);
2087 		expectError(GL_NO_ERROR);
2088 
2089 		verifyUniformValue4f(m_testCtx, *this, program.getProgram(), glGetUniformLocation(program.getProgram(), "array4Uniform[0]"), uniformValue[4 * 0], uniformValue[(4 * 0) + 1], uniformValue[(4 * 0) + 2], uniformValue[(4 * 0) + 3]);
2090 		verifyUniformValue4f(m_testCtx, *this, program.getProgram(), glGetUniformLocation(program.getProgram(), "array4Uniform[1]"), uniformValue[4 * 1], uniformValue[(4 * 1) + 1], uniformValue[(4 * 1) + 2], uniformValue[(4 * 1) + 3]);
2091 		verifyUniformValue4f(m_testCtx, *this, program.getProgram(), glGetUniformLocation(program.getProgram(), "array4Uniform[2]"), uniformValue[4 * 2], uniformValue[(4 * 2) + 1], uniformValue[(4 * 2) + 2], uniformValue[(4 * 2) + 3]);
2092 		verifyUniformValue4f(m_testCtx, *this, program.getProgram(), glGetUniformLocation(program.getProgram(), "array4Uniform[3]"), uniformValue[4 * 3], uniformValue[(4 * 3) + 1], uniformValue[(4 * 3) + 2], uniformValue[(4 * 3) + 3]);
2093 		verifyUniformValue4f(m_testCtx, *this, program.getProgram(), glGetUniformLocation(program.getProgram(), "array4Uniform[4]"), uniformValue[4 * 4], uniformValue[(4 * 4) + 1], uniformValue[(4 * 4) + 2], uniformValue[(4 * 4) + 3]);
2094 		expectError(GL_NO_ERROR);
2095 
2096 		glUseProgram(0);
2097 		expectError(GL_NO_ERROR);
2098 	}
2099 };
2100 
2101 class UniformValueMatrixCase : public ApiCase
2102 {
2103 public:
UniformValueMatrixCase(Context & context,const char * name,const char * description)2104 	UniformValueMatrixCase (Context& context, const char* name, const char* description)
2105 		: ApiCase(context, name, description)
2106 	{
2107 	}
2108 
test(void)2109 	void test (void)
2110 	{
2111 		static const char* testVertSource =
2112 			"uniform highp mat2 mat2Uniform;"
2113 			"uniform highp mat3 mat3Uniform;"
2114 			"uniform highp mat4 mat4Uniform;"
2115 			"void main (void)\n"
2116 			"{\n"
2117 			"	gl_Position = vec4(mat2Uniform[0][0] + mat3Uniform[0][0] + mat4Uniform[0][0]);\n"
2118 			"}\n";
2119 		static const char* testFragSource =
2120 
2121 			"void main (void)\n"
2122 			"{\n"
2123 			"	gl_FragColor = vec4(0.0);\n"
2124 			"}\n";
2125 
2126 		glu::ShaderProgram program(m_context.getRenderContext(), glu::makeVtxFragSources(testVertSource, testFragSource));
2127 		if (!program.isOk())
2128 		{
2129 			m_log << program;
2130 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Failed to compile shader");
2131 			return;
2132 		}
2133 
2134 		glUseProgram(program.getProgram());
2135 		expectError(GL_NO_ERROR);
2136 
2137 		GLint location;
2138 
2139 		float matrixValues[4 * 4] =
2140 		{
2141 			-1.0f,	0.1f,	4.0f,	800.0f,
2142 			13.0f,	55.0f,	12.0f,	91.0f,
2143 			-55.1f,	1.1f,	98.0f,	19.0f,
2144 			41.0f,	65.0f,	4.0f,	12.2f,
2145 		};
2146 
2147 		// the values of the matrix are returned in column major order but they can be given in either order
2148 
2149 		location = glGetUniformLocation(program.getProgram(), "mat2Uniform");
2150 		glUniformMatrix2fv(location, 1, GL_FALSE, matrixValues);
2151 		verifyUniformMatrixValues<2>(m_testCtx, *this, program.getProgram(), location, matrixValues, false);
2152 
2153 		location = glGetUniformLocation(program.getProgram(), "mat3Uniform");
2154 		glUniformMatrix3fv(location, 1, GL_FALSE, matrixValues);
2155 		verifyUniformMatrixValues<3>(m_testCtx, *this, program.getProgram(), location, matrixValues, false);
2156 
2157 		location = glGetUniformLocation(program.getProgram(), "mat4Uniform");
2158 		glUniformMatrix4fv(location, 1, GL_FALSE, matrixValues);
2159 		verifyUniformMatrixValues<4>(m_testCtx, *this, program.getProgram(), location, matrixValues, false);
2160 
2161 		glUseProgram(0);
2162 		expectError(GL_NO_ERROR);
2163 	}
2164 };
2165 
2166 class PrecisionFormatCase : public ApiCase
2167 {
2168 public:
2169 	struct RequiredFormat
2170 	{
2171 		int negativeRange;
2172 		int positiveRange;
2173 		int precision;
2174 	};
2175 
PrecisionFormatCase(Context & context,const char * name,const char * description,glw::GLenum shaderType,glw::GLenum precisionType)2176 	PrecisionFormatCase (Context& context, const char* name, const char* description, glw::GLenum shaderType, glw::GLenum precisionType)
2177 		: ApiCase			(context, name, description)
2178 		, m_shaderType		(shaderType)
2179 		, m_precisionType	(precisionType)
2180 	{
2181 	}
2182 
2183 private:
test(void)2184 	void test (void)
2185 	{
2186 		const RequiredFormat											expected = getRequiredFormat();
2187 		bool															error = false;
2188 		gls::StateQueryUtil::StateQueryMemoryWriteGuard<glw::GLboolean>	shaderCompiler;
2189 		gls::StateQueryUtil::StateQueryMemoryWriteGuard<glw::GLint[2]>	range;
2190 		gls::StateQueryUtil::StateQueryMemoryWriteGuard<glw::GLint>		precision;
2191 
2192 		// requires SHADER_COMPILER = true
2193 		glGetBooleanv(GL_SHADER_COMPILER, &shaderCompiler);
2194 		expectError(GL_NO_ERROR);
2195 
2196 		if (!shaderCompiler.verifyValidity(m_testCtx))
2197 			return;
2198 		if (shaderCompiler != GL_TRUE)
2199 			throw tcu::NotSupportedError("SHADER_COMPILER = TRUE required");
2200 
2201 		// query values
2202 		glGetShaderPrecisionFormat(m_shaderType, m_precisionType, range, &precision);
2203 		expectError(GL_NO_ERROR);
2204 
2205 		if (!range.verifyValidity(m_testCtx))
2206 			return;
2207 		if (!precision.verifyValidity(m_testCtx))
2208 			return;
2209 
2210 		m_log
2211 			<< tcu::TestLog::Message
2212 			<< "range[0] = " << range[0] << "\n"
2213 			<< "range[1] = " << range[1] << "\n"
2214 			<< "precision = " << precision
2215 			<< tcu::TestLog::EndMessage;
2216 
2217 		// special case for highp and fragment shader
2218 
2219 		if (m_shaderType == GL_FRAGMENT_SHADER && (m_precisionType == GL_HIGH_FLOAT || m_precisionType == GL_HIGH_INT))
2220 		{
2221 			// not supported is a valid return value
2222 			if (range[0] == 0 && range[1] == 0 && precision == 0)
2223 				return;
2224 		}
2225 
2226 		// verify the returned values
2227 
2228 		if (range[0] < expected.negativeRange)
2229 		{
2230 			m_log << tcu::TestLog::Message << "// ERROR: Invalid range[0], expected greater or equal to " << expected.negativeRange << tcu::TestLog::EndMessage;
2231 			error = true;
2232 		}
2233 
2234 		if (range[1] < expected.positiveRange)
2235 		{
2236 			m_log << tcu::TestLog::Message << "// ERROR: Invalid range[1], expected greater or equal to " << expected.positiveRange << tcu::TestLog::EndMessage;
2237 			error = true;
2238 		}
2239 
2240 		if (precision < expected.precision)
2241 		{
2242 			m_log << tcu::TestLog::Message << "// ERROR: Invalid precision, expected greater or equal to " << expected.precision << tcu::TestLog::EndMessage;
2243 			error = true;
2244 		}
2245 
2246 		if (error)
2247 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid precision/range");
2248 	}
2249 
getRequiredFormat(void) const2250 	RequiredFormat getRequiredFormat (void) const
2251 	{
2252 		// Precisions for different types.
2253 		// For example highp float: range: (-2^62, 2^62) => min = -2^62 + e, max = 2^62 - e
2254 		const RequiredFormat requirements[] =
2255 		{
2256 			{  0,  0,  8 }, //!< lowp float
2257 			{ 13, 13, 10 }, //!< mediump float
2258 			{ 61, 61, 16 }, //!< highp float
2259 			{ 7,   7,  0 }, //!< lowp int
2260 			{ 9,   9,  0 }, //!< mediump int
2261 			{ 15, 15,  0 }, //!< highp int
2262 		};
2263 		const int ndx = (int)m_precisionType - (int)GL_LOW_FLOAT;
2264 
2265 		DE_ASSERT(ndx >= 0);
2266 		DE_ASSERT(ndx < DE_LENGTH_OF_ARRAY(requirements));
2267 		return requirements[ndx];
2268 	}
2269 
2270 	const glw::GLenum m_shaderType;
2271 	const glw::GLenum m_precisionType;
2272 };
2273 
2274 } // anonymous
2275 
2276 
ShaderStateQueryTests(Context & context)2277 ShaderStateQueryTests::ShaderStateQueryTests (Context& context)
2278 	: TestCaseGroup(context, "shader", "Shader State Query tests")
2279 {
2280 }
2281 
init(void)2282 void ShaderStateQueryTests::init (void)
2283 {
2284 	// shader
2285 	addChild(new ShaderTypeCase						(m_context, "shader_type",							"SHADER_TYPE"));
2286 	addChild(new ShaderCompileStatusCase			(m_context, "shader_compile_status",				"COMPILE_STATUS"));
2287 	addChild(new ShaderInfoLogCase					(m_context, "shader_info_log_length",				"INFO_LOG_LENGTH"));
2288 	addChild(new ShaderSourceCase					(m_context, "shader_source_length",					"SHADER_SOURCE_LENGTH"));
2289 
2290 	// shader and program
2291 	addChild(new DeleteStatusCase					(m_context, "delete_status",						"DELETE_STATUS"));
2292 
2293 	// vertex-attrib
2294 	addChild(new CurrentVertexAttribInitialCase		(m_context, "current_vertex_attrib_initial",		"CURRENT_VERTEX_ATTRIB"));
2295 	addChild(new CurrentVertexAttribFloatCase		(m_context, "current_vertex_attrib_float",			"CURRENT_VERTEX_ATTRIB"));
2296 	addChild(new CurrentVertexAttribConversionCase	(m_context, "current_vertex_attrib_float_to_int",	"CURRENT_VERTEX_ATTRIB"));
2297 
2298 	// program
2299 	addChild(new ProgramInfoLogCase					(m_context, "program_info_log_length",				"INFO_LOG_LENGTH"));
2300 	addChild(new ProgramValidateStatusCase			(m_context, "program_validate_status",				"VALIDATE_STATUS"));
2301 	addChild(new ProgramAttachedShadersCase			(m_context, "program_attached_shaders",				"ATTACHED_SHADERS"));
2302 
2303 	addChild(new ProgramActiveUniformNameCase		(m_context, "program_active_uniform_name",			"ACTIVE_UNIFORMS and ACTIVE_UNIFORM_MAX_LENGTH"));
2304 	addChild(new ProgramUniformCase					(m_context, "program_active_uniform_types",			"UNIFORM_TYPE and UNIFORM_SIZE"));
2305 
2306 	// attribute related
2307 	addChild(new ActiveAttributesCase				(m_context, "active_attributes",					"ACTIVE_ATTRIBUTES and ACTIVE_ATTRIBUTE_MAX_LENGTH"));
2308 	addChild(new VertexAttributeSizeCase			(m_context, "vertex_attrib_size",					"VERTEX_ATTRIB_ARRAY_SIZE"));
2309 	addChild(new VertexAttributeTypeCase			(m_context, "vertex_attrib_type",					"VERTEX_ATTRIB_ARRAY_TYPE"));
2310 	addChild(new VertexAttributeStrideCase			(m_context, "vertex_attrib_stride",					"VERTEX_ATTRIB_ARRAY_STRIDE"));
2311 	addChild(new VertexAttributeNormalizedCase		(m_context, "vertex_attrib_normalized",				"VERTEX_ATTRIB_ARRAY_NORMALIZED"));
2312 	addChild(new VertexAttributeEnabledCase			(m_context, "vertex_attrib_array_enabled",			"VERTEX_ATTRIB_ARRAY_ENABLED"));
2313 	addChild(new VertexAttributeBufferBindingCase	(m_context, "vertex_attrib_array_buffer_binding",	"VERTEX_ATTRIB_ARRAY_BUFFER_BINDING"));
2314 	addChild(new VertexAttributePointerCase			(m_context, "vertex_attrib_pointerv",				"GetVertexAttribPointerv"));
2315 
2316 	// uniform values
2317 	addChild(new UniformValueFloatCase				(m_context, "uniform_value_float",					"GetUniform*"));
2318 	addChild(new UniformValueIntCase				(m_context, "uniform_value_int",					"GetUniform*"));
2319 	addChild(new UniformValueBooleanCase			(m_context, "uniform_value_boolean",				"GetUniform*"));
2320 	addChild(new UniformValueSamplerCase			(m_context, "uniform_value_sampler",				"GetUniform*"));
2321 	addChild(new UniformValueArrayCase				(m_context, "uniform_value_array",					"GetUniform*"));
2322 	addChild(new UniformValueMatrixCase				(m_context, "uniform_value_matrix",					"GetUniform*"));
2323 
2324 	// precision format query
2325 	addChild(new PrecisionFormatCase				(m_context, "precision_vertex_lowp_float",			"GetShaderPrecisionFormat",		GL_VERTEX_SHADER,	GL_LOW_FLOAT));
2326 	addChild(new PrecisionFormatCase				(m_context, "precision_vertex_mediump_float",		"GetShaderPrecisionFormat",		GL_VERTEX_SHADER,	GL_MEDIUM_FLOAT));
2327 	addChild(new PrecisionFormatCase				(m_context, "precision_vertex_highp_float",			"GetShaderPrecisionFormat",		GL_VERTEX_SHADER,	GL_HIGH_FLOAT));
2328 	addChild(new PrecisionFormatCase				(m_context, "precision_vertex_lowp_int",			"GetShaderPrecisionFormat",		GL_VERTEX_SHADER,	GL_LOW_INT));
2329 	addChild(new PrecisionFormatCase				(m_context, "precision_vertex_mediump_int",			"GetShaderPrecisionFormat",		GL_VERTEX_SHADER,	GL_MEDIUM_INT));
2330 	addChild(new PrecisionFormatCase				(m_context, "precision_vertex_highp_int",			"GetShaderPrecisionFormat",		GL_VERTEX_SHADER,	GL_HIGH_INT));
2331 	addChild(new PrecisionFormatCase				(m_context, "precision_fragment_lowp_float",		"GetShaderPrecisionFormat",		GL_FRAGMENT_SHADER,	GL_LOW_FLOAT));
2332 	addChild(new PrecisionFormatCase				(m_context, "precision_fragment_mediump_float",		"GetShaderPrecisionFormat",		GL_FRAGMENT_SHADER,	GL_MEDIUM_FLOAT));
2333 	addChild(new PrecisionFormatCase				(m_context, "precision_fragment_highp_float",		"GetShaderPrecisionFormat",		GL_FRAGMENT_SHADER,	GL_HIGH_FLOAT));
2334 	addChild(new PrecisionFormatCase				(m_context, "precision_fragment_lowp_int",			"GetShaderPrecisionFormat",		GL_FRAGMENT_SHADER,	GL_LOW_INT));
2335 	addChild(new PrecisionFormatCase				(m_context, "precision_fragment_mediump_int",		"GetShaderPrecisionFormat",		GL_FRAGMENT_SHADER,	GL_MEDIUM_INT));
2336 	addChild(new PrecisionFormatCase				(m_context, "precision_fragment_highp_int",			"GetShaderPrecisionFormat",		GL_FRAGMENT_SHADER,	GL_HIGH_INT));
2337 }
2338 
2339 } // Functional
2340 } // gles2
2341 } // deqp
2342