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
35using namespace glw; // GLint and other GL types
36using deqp::gls::StateQueryUtil::StateQueryMemoryWriteGuard;
37
38namespace deqp
39{
40namespace gles2
41{
42namespace Functional
43{
44namespace
45{
46
47static const char* commonTestVertSource		=	"void main (void)\n"
48												"{\n"
49												"	gl_Position = vec4(0.0);\n"
50												"}\n";
51static const char* commonTestFragSource		=	"void main (void)\n"
52												"{\n"
53												"	gl_FragColor = vec4(0.0);\n"
54												"}\n";
55
56static const char* brokenShader				=	"broken, this should not compile!\n"
57												"\n";
58
59// rounds x.1 to x+1
60template <typename T>
61T roundGLfloatToNearestIntegerUp (GLfloat val)
62{
63	return (T)(ceil(val));
64}
65
66// rounds x.9 to x
67template <typename T>
68T roundGLfloatToNearestIntegerDown (GLfloat val)
69{
70	return (T)(floor(val));
71}
72
73bool 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
87void 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
99void 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
108bool 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
118void 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
138void 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
189void 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
198void 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
223void 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
251void 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
282void 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
316void 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
341void 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
369void 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
400void 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
434template <int Count>
435void 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
457template <int N>
458void 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
484void 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
493class ShaderTypeCase : public ApiCase
494{
495public:
496	ShaderTypeCase (Context& context, const char* name, const char* description)
497		: ApiCase(context, name, description)
498	{
499	}
500
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
513class ShaderCompileStatusCase : public ApiCase
514{
515public:
516	ShaderCompileStatusCase (Context& context, const char* name, const char* description)
517		: ApiCase(context, name, description)
518	{
519	}
520
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
547class ShaderInfoLogCase : public ApiCase
548{
549public:
550	ShaderInfoLogCase (Context& context, const char* name, const char* description)
551		: ApiCase(context, name, description)
552	{
553	}
554
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
640class ShaderSourceCase : public ApiCase
641{
642public:
643	ShaderSourceCase (Context& context, const char* name, const char* description)
644		: ApiCase(context, name, description)
645	{
646	}
647
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
750class DeleteStatusCase : public ApiCase
751{
752public:
753	DeleteStatusCase (Context& context, const char* name, const char* description)
754		: ApiCase(context, name, description)
755	{
756	}
757
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
803class CurrentVertexAttribInitialCase : public ApiCase
804{
805public:
806	CurrentVertexAttribInitialCase (Context& context, const char* name, const char* description)
807		: ApiCase(context, name, description)
808	{
809	}
810
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
839class CurrentVertexAttribFloatCase : public ApiCase
840{
841public:
842	CurrentVertexAttribFloatCase (Context& context, const char* name, const char* description)
843		: ApiCase(context, name, description)
844	{
845	}
846
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
901class CurrentVertexAttribConversionCase : public ApiCase
902{
903public:
904	CurrentVertexAttribConversionCase (Context& context, const char* name, const char* description)
905		: ApiCase(context, name, description)
906	{
907	}
908
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
963class ProgramInfoLogCase : public ApiCase
964{
965public:
966	ProgramInfoLogCase (Context& context, const char* name, const char* description)
967		: ApiCase(context, name, description)
968	{
969	}
970
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
1031class ProgramValidateStatusCase : public ApiCase
1032{
1033public:
1034	ProgramValidateStatusCase (Context& context, const char* name, const char* description)
1035		: ApiCase(context, name, description)
1036	{
1037	}
1038
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
1105class ProgramAttachedShadersCase : public ApiCase
1106{
1107public:
1108	ProgramAttachedShadersCase (Context& context, const char* name, const char* description)
1109		: ApiCase(context, name, description)
1110	{
1111	}
1112
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
1193class ProgramActiveUniformNameCase : public ApiCase
1194{
1195public:
1196	ProgramActiveUniformNameCase (Context& context, const char* name, const char* description)
1197		: ApiCase(context, name, description)
1198	{
1199	}
1200
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
1303class ProgramUniformCase : public ApiCase
1304{
1305public:
1306	ProgramUniformCase (Context& context, const char* name, const char* description)
1307		: ApiCase(context, name, description)
1308	{
1309	}
1310
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
1409class ActiveAttributesCase : public ApiCase
1410{
1411public:
1412	ActiveAttributesCase (Context& context, const char* name, const char* description)
1413		: ApiCase(context, name, description)
1414	{
1415	}
1416
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
1500struct PointerData
1501{
1502	GLint		size;
1503	GLenum		type;
1504	GLint		stride;
1505	GLboolean	normalized;
1506	void*		pointer;
1507};
1508
1509class VertexAttributeSizeCase : public ApiCase
1510{
1511public:
1512	VertexAttributeSizeCase (Context& context, const char* name, const char* description)
1513		: ApiCase(context, name, description)
1514	{
1515	}
1516
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
1545class VertexAttributeTypeCase : public ApiCase
1546{
1547public:
1548	VertexAttributeTypeCase (Context& context, const char* name, const char* description)
1549		: ApiCase(context, name, description)
1550	{
1551	}
1552
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
1577class VertexAttributeStrideCase : public ApiCase
1578{
1579public:
1580	VertexAttributeStrideCase (Context& context, const char* name, const char* description)
1581		: ApiCase(context, name, description)
1582	{
1583	}
1584
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
1629class VertexAttributeNormalizedCase : public ApiCase
1630{
1631public:
1632	VertexAttributeNormalizedCase (Context& context, const char* name, const char* description)
1633		: ApiCase(context, name, description)
1634	{
1635	}
1636
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
1666class VertexAttributeEnabledCase : public ApiCase
1667{
1668public:
1669	VertexAttributeEnabledCase (Context& context, const char* name, const char* description)
1670		: ApiCase(context, name, description)
1671	{
1672	}
1673
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
1686class VertexAttributeBufferBindingCase : public ApiCase
1687{
1688public:
1689	VertexAttributeBufferBindingCase (Context& context, const char* name, const char* description)
1690		: ApiCase(context, name, description)
1691	{
1692	}
1693
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
1714class VertexAttributePointerCase : public ApiCase
1715{
1716public:
1717	VertexAttributePointerCase (Context& context, const char* name, const char* description)
1718		: ApiCase(context, name, description)
1719	{
1720	}
1721
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
1757class UniformValueFloatCase : public ApiCase
1758{
1759public:
1760	UniformValueFloatCase (Context& context, const char* name, const char* description)
1761		: ApiCase(context, name, description)
1762	{
1763	}
1764
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
1817class UniformValueIntCase : public ApiCase
1818{
1819public:
1820	UniformValueIntCase (Context& context, const char* name, const char* description)
1821		: ApiCase(context, name, description)
1822	{
1823	}
1824
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
1876class UniformValueBooleanCase : public ApiCase
1877{
1878public:
1879	UniformValueBooleanCase (Context& context, const char* name, const char* description)
1880		: ApiCase(context, name, description)
1881	{
1882	}
1883
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
1955class UniformValueSamplerCase : public ApiCase
1956{
1957public:
1958	UniformValueSamplerCase (Context& context, const char* name, const char* description)
1959		: ApiCase(context, name, description)
1960	{
1961	}
1962
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
2000class UniformValueArrayCase : public ApiCase
2001{
2002public:
2003	UniformValueArrayCase (Context& context, const char* name, const char* description)
2004		: ApiCase(context, name, description)
2005	{
2006	}
2007
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
2101class UniformValueMatrixCase : public ApiCase
2102{
2103public:
2104	UniformValueMatrixCase (Context& context, const char* name, const char* description)
2105		: ApiCase(context, name, description)
2106	{
2107	}
2108
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
2166class PrecisionFormatCase : public ApiCase
2167{
2168public:
2169	struct RequiredFormat
2170	{
2171		int negativeRange;
2172		int positiveRange;
2173		int precision;
2174	};
2175
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
2183private:
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
2250	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
2277ShaderStateQueryTests::ShaderStateQueryTests (Context& context)
2278	: TestCaseGroup(context, "shader", "Shader State Query tests")
2279{
2280}
2281
2282void 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