1/*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL ES 3.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 "es3fShaderStateQueryTests.hpp"
25#include "glsStateQueryUtil.hpp"
26#include "es3fApiCase.hpp"
27#include "gluRenderContext.hpp"
28#include "glwEnums.hpp"
29#include "glwFunctions.hpp"
30#include "deRandom.hpp"
31#include "deMath.h"
32#include "deString.h"
33
34using namespace glw; // GLint and other GL types
35using deqp::gls::StateQueryUtil::StateQueryMemoryWriteGuard;
36
37namespace deqp
38{
39namespace gles3
40{
41namespace Functional
42{
43namespace
44{
45
46static const char* commonTestVertSource		=	"#version 300 es\n"
47												"void main (void)\n"
48												"{\n"
49												"	gl_Position = vec4(0.0);\n"
50												"}\n\0";
51static const char* commonTestFragSource		=	"#version 300 es\n"
52												"layout(location = 0) out mediump vec4 fragColor;\n"
53												"void main (void)\n"
54												"{\n"
55												"	fragColor = vec4(0.0);\n"
56												"}\n\0";
57
58static const char* brokenShader				=	"#version 300 es\n"
59												"broken, this should not compile!\n"
60												"\n\0";
61
62// rounds x.1 to x+1
63template <typename T>
64T roundGLfloatToNearestIntegerUp (GLfloat val)
65{
66	return (T)(ceil(val));
67}
68
69// rounds x.9 to x
70template <typename T>
71T roundGLfloatToNearestIntegerDown (GLfloat val)
72{
73	return (T)(floor(val));
74}
75
76bool checkIntEquals (tcu::TestContext& testCtx, GLint got, GLint expected)
77{
78	using tcu::TestLog;
79
80	if (got != expected)
81	{
82		testCtx.getLog() << TestLog::Message << "// ERROR: Expected " << expected << "; got " << got << TestLog::EndMessage;
83		if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
84			testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid value");
85		return false;
86	}
87	return true;
88}
89
90void checkPointerEquals (tcu::TestContext& testCtx, const void* got, const void* expected)
91{
92	using tcu::TestLog;
93
94	if (got != expected)
95	{
96		testCtx.getLog() << TestLog::Message << "// ERROR: Expected " << expected << "; got " << got << TestLog::EndMessage;
97		if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
98			testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid value");
99	}
100}
101
102void verifyShaderParam (tcu::TestContext& testCtx, glu::CallLogWrapper& gl, GLuint shader, GLenum pname, GLenum reference)
103{
104	StateQueryMemoryWriteGuard<GLint> state;
105	gl.glGetShaderiv(shader, pname, &state);
106
107	if (state.verifyValidity(testCtx))
108		checkIntEquals(testCtx, state, reference);
109}
110
111bool verifyProgramParam (tcu::TestContext& testCtx, glu::CallLogWrapper& gl, GLuint program, GLenum pname, GLenum reference)
112{
113	StateQueryMemoryWriteGuard<GLint> state;
114	gl.glGetProgramiv(program, pname, &state);
115
116	return state.verifyValidity(testCtx) && checkIntEquals(testCtx, state, reference);
117}
118
119void verifyActiveUniformParam  (tcu::TestContext& testCtx, glu::CallLogWrapper& gl, GLuint program, GLuint index, GLenum pname, GLenum reference)
120{
121	StateQueryMemoryWriteGuard<GLint> state;
122	gl.glGetActiveUniformsiv(program, 1, &index, pname, &state);
123
124	if (state.verifyValidity(testCtx))
125		checkIntEquals(testCtx, state, reference);
126}
127
128void verifyActiveUniformBlockParam  (tcu::TestContext& testCtx, glu::CallLogWrapper& gl, GLuint program, GLuint blockIndex, GLenum pname, GLenum reference)
129{
130	StateQueryMemoryWriteGuard<GLint> state;
131	gl.glGetActiveUniformBlockiv(program, blockIndex, pname, &state);
132
133	if (state.verifyValidity(testCtx))
134		checkIntEquals(testCtx, state, reference);
135}
136
137void verifyCurrentVertexAttribf (tcu::TestContext& testCtx, glu::CallLogWrapper& gl, GLint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
138{
139	using tcu::TestLog;
140
141	StateQueryMemoryWriteGuard<GLfloat[4]> attribValue;
142	gl.glGetVertexAttribfv(index, GL_CURRENT_VERTEX_ATTRIB, attribValue);
143
144	attribValue.verifyValidity(testCtx);
145
146	if (attribValue[0] != x || attribValue[1] != y || attribValue[2] != z || attribValue[3] != w)
147	{
148		testCtx.getLog() << TestLog::Message
149			<< "// ERROR: Expected [" << x << "," << y << "," << z << "," << w << "];"
150			<< "got [" << attribValue[0] << "," << attribValue[1] << "," << attribValue[2] << "," << attribValue[3] << "]"
151			<< TestLog::EndMessage;
152		if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
153			testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid attribute value");
154	}
155}
156
157void verifyCurrentVertexAttribIi (tcu::TestContext& testCtx, glu::CallLogWrapper& gl, GLint index, GLint x, GLint y, GLint z, GLint w)
158{
159	using tcu::TestLog;
160
161	StateQueryMemoryWriteGuard<GLint[4]> attribValue;
162	gl.glGetVertexAttribIiv(index, GL_CURRENT_VERTEX_ATTRIB, attribValue);
163
164	attribValue.verifyValidity(testCtx);
165
166	if (attribValue[0] != x || attribValue[1] != y || attribValue[2] != z || attribValue[3] != w)
167	{
168		testCtx.getLog() << TestLog::Message
169			<< "// ERROR: Expected [" << x << "," << y << "," << z << "," << w << "];"
170			<< "got [" << attribValue[0] << "," << attribValue[1] << "," << attribValue[2] << "," << attribValue[3] << "]"
171			<< TestLog::EndMessage;
172		if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
173			testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid attribute value");
174	}
175}
176
177void verifyCurrentVertexAttribIui (tcu::TestContext& testCtx, glu::CallLogWrapper& gl, GLint index, GLuint x, GLuint y, GLuint z, GLuint w)
178{
179	using tcu::TestLog;
180
181	StateQueryMemoryWriteGuard<GLuint[4]> attribValue;
182	gl.glGetVertexAttribIuiv(index, GL_CURRENT_VERTEX_ATTRIB, attribValue);
183
184	attribValue.verifyValidity(testCtx);
185
186	if (attribValue[0] != x || attribValue[1] != y || attribValue[2] != z || attribValue[3] != w)
187	{
188		testCtx.getLog() << TestLog::Message
189			<< "// ERROR: Expected [" << x << "," << y << "," << z << "," << w << "];"
190			<< "got [" << attribValue[0] << "," << attribValue[1] << "," << attribValue[2] << "," << attribValue[3] << "]"
191			<< TestLog::EndMessage;
192		if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
193			testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid attribute value");
194	}
195}
196
197void verifyCurrentVertexAttribConversion (tcu::TestContext& testCtx, glu::CallLogWrapper& gl, GLint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
198{
199	using tcu::TestLog;
200
201	StateQueryMemoryWriteGuard<GLint[4]> attribValue;
202	gl.glGetVertexAttribiv(index, GL_CURRENT_VERTEX_ATTRIB, attribValue);
203
204	attribValue.verifyValidity(testCtx);
205
206	const GLint referenceAsGLintMin[] =
207	{
208		roundGLfloatToNearestIntegerDown<GLint>(x),
209		roundGLfloatToNearestIntegerDown<GLint>(y),
210		roundGLfloatToNearestIntegerDown<GLint>(z),
211		roundGLfloatToNearestIntegerDown<GLint>(w)
212	};
213	const GLint referenceAsGLintMax[] =
214	{
215		roundGLfloatToNearestIntegerUp<GLint>(x),
216		roundGLfloatToNearestIntegerUp<GLint>(y),
217		roundGLfloatToNearestIntegerUp<GLint>(z),
218		roundGLfloatToNearestIntegerUp<GLint>(w)
219	};
220
221	if (attribValue[0] < referenceAsGLintMin[0] || attribValue[0] > referenceAsGLintMax[0] ||
222		attribValue[1] < referenceAsGLintMin[1] || attribValue[1] > referenceAsGLintMax[1] ||
223		attribValue[2] < referenceAsGLintMin[2] || attribValue[2] > referenceAsGLintMax[2] ||
224		attribValue[3] < referenceAsGLintMin[3] || attribValue[3] > referenceAsGLintMax[3])
225	{
226		testCtx.getLog() << TestLog::Message
227			<< "// ERROR: expected in range "
228			<< "[" << referenceAsGLintMin[0] << " " << referenceAsGLintMax[0] << "], "
229			<< "[" << referenceAsGLintMin[1] << " " << referenceAsGLintMax[1] << "], "
230			<< "[" << referenceAsGLintMin[2] << " " << referenceAsGLintMax[2] << "], "
231			<< "[" << referenceAsGLintMin[3] << " " << referenceAsGLintMax[3] << "]"
232			<< "; got "
233			<< attribValue[0] << ", "
234			<< attribValue[1] << ", "
235			<< attribValue[2] << ", "
236			<< attribValue[3] << " "
237			<< "; Input="
238			<< x << "; "
239			<< y << "; "
240			<< z << "; "
241			<< w << " " << TestLog::EndMessage;
242
243		if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
244			testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid attribute value");
245	}
246}
247
248void verifyVertexAttrib (tcu::TestContext& testCtx, glu::CallLogWrapper& gl, GLint index, GLenum pname, GLenum reference)
249{
250	StateQueryMemoryWriteGuard<GLint> state;
251	gl.glGetVertexAttribIiv(index, pname, &state);
252
253	if (state.verifyValidity(testCtx))
254		checkIntEquals(testCtx, state, reference);
255}
256
257void verifyUniformValue1f (tcu::TestContext& testCtx, glu::CallLogWrapper& gl, GLuint program, GLint location, float x)
258{
259	using tcu::TestLog;
260
261	StateQueryMemoryWriteGuard<GLfloat[1]> state;
262	gl.glGetUniformfv(program, location, state);
263
264	if (!state.verifyValidity(testCtx))
265		return;
266
267	if (state[0] != x)
268	{
269		testCtx.getLog() << TestLog::Message
270		<< "// ERROR: expected ["
271		<< x
272		<< "]; got ["
273		<< state[0]
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 verifyUniformValue2f (tcu::TestContext& testCtx, glu::CallLogWrapper& gl, GLuint program, GLint location, float x, float y)
283{
284	using tcu::TestLog;
285
286	StateQueryMemoryWriteGuard<GLfloat[2]> 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	{
295		testCtx.getLog() << TestLog::Message
296		<< "// ERROR: expected ["
297		<< x << ", "
298		<< y
299		<< "]; got ["
300		<< state[0] << ", "
301		<< state[1]
302		<< "]"
303		<< TestLog::EndMessage;
304
305		if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
306			testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid uniform value");
307	}
308}
309
310void verifyUniformValue3f (tcu::TestContext& testCtx, glu::CallLogWrapper& gl, GLuint program, GLint location, float x, float y, float z)
311{
312	using tcu::TestLog;
313
314	StateQueryMemoryWriteGuard<GLfloat[3]> state;
315	gl.glGetUniformfv(program, location, state);
316
317	if (!state.verifyValidity(testCtx))
318		return;
319
320	if (state[0] != x ||
321		state[1] != y ||
322		state[2] != z)
323	{
324		testCtx.getLog() << TestLog::Message
325		<< "// ERROR: expected ["
326		<< x << ", "
327		<< y << ", "
328		<< z
329		<< "]; got ["
330		<< state[0] << ", "
331		<< state[1] << ", "
332		<< state[2]
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 verifyUniformValue4f (tcu::TestContext& testCtx, glu::CallLogWrapper& gl, GLuint program, GLint location, float x, float y, float z, float w)
342{
343	using tcu::TestLog;
344
345	StateQueryMemoryWriteGuard<GLfloat[4]> state;
346	gl.glGetUniformfv(program, location, state);
347
348	if (!state.verifyValidity(testCtx))
349		return;
350
351	if (state[0] != x ||
352		state[1] != y ||
353		state[2] != z ||
354		state[3] != w)
355	{
356		testCtx.getLog() << TestLog::Message
357		<< "// ERROR: expected ["
358		<< x << ", "
359		<< y << ", "
360		<< z << ", "
361		<< w
362		<< "]; got ["
363		<< state[0] << ", "
364		<< state[1] << ", "
365		<< state[2] << ", "
366		<< state[3]
367		<< "]"
368		<< TestLog::EndMessage;
369
370		if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
371			testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid uniform value");
372	}
373}
374
375void verifyUniformValue1i (tcu::TestContext& testCtx, glu::CallLogWrapper& gl, GLuint program, GLint location, GLint x)
376{
377	using tcu::TestLog;
378
379	StateQueryMemoryWriteGuard<GLint[1]> state;
380	gl.glGetUniformiv(program, location, state);
381
382	if (!state.verifyValidity(testCtx))
383		return;
384
385	if (state[0] != x)
386	{
387		testCtx.getLog() << TestLog::Message
388		<< "// ERROR: expected ["
389		<< x
390		<< "]; got ["
391		<< state[0]
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 verifyUniformValue2i (tcu::TestContext& testCtx, glu::CallLogWrapper& gl, GLuint program, GLint location, GLint x, GLint y)
401{
402	using tcu::TestLog;
403
404	StateQueryMemoryWriteGuard<GLint[2]> 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	{
413		testCtx.getLog() << TestLog::Message
414		<< "// ERROR: expected ["
415		<< x << ", "
416		<< y
417		<< "]; got ["
418		<< state[0] << ", "
419		<< state[1]
420		<< "]"
421		<< TestLog::EndMessage;
422
423		if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
424			testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid uniform value");
425	}
426}
427
428void verifyUniformValue3i (tcu::TestContext& testCtx, glu::CallLogWrapper& gl, GLuint program, GLint location, GLint x, GLint y, GLint z)
429{
430	using tcu::TestLog;
431
432	StateQueryMemoryWriteGuard<GLint[3]> state;
433	gl.glGetUniformiv(program, location, state);
434
435	if (!state.verifyValidity(testCtx))
436		return;
437
438	if (state[0] != x ||
439		state[1] != y ||
440		state[2] != z)
441	{
442		testCtx.getLog() << TestLog::Message
443		<< "// ERROR: expected ["
444		<< x << ", "
445		<< y << ", "
446		<< z
447		<< "]; got ["
448		<< state[0] << ", "
449		<< state[1] << ", "
450		<< state[2]
451		<< "]"
452		<< TestLog::EndMessage;
453
454		if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
455			testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid uniform value");
456	}
457}
458
459void verifyUniformValue4i (tcu::TestContext& testCtx, glu::CallLogWrapper& gl, GLuint program, GLint location, GLint x, GLint y, GLint z, GLint w)
460{
461	using tcu::TestLog;
462
463	StateQueryMemoryWriteGuard<GLint[4]> state;
464	gl.glGetUniformiv(program, location, state);
465
466	if (!state.verifyValidity(testCtx))
467		return;
468
469	if (state[0] != x ||
470		state[1] != y ||
471		state[2] != z ||
472		state[3] != w)
473	{
474		testCtx.getLog() << TestLog::Message
475		<< "// ERROR: expected ["
476		<< x << ", "
477		<< y << ", "
478		<< z << ", "
479		<< w
480		<< "]; got ["
481		<< state[0] << ", "
482		<< state[1] << ", "
483		<< state[2] << ", "
484		<< state[3]
485		<< "]"
486		<< TestLog::EndMessage;
487
488		if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
489			testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid uniform value");
490	}
491}
492
493void verifyUniformValue1ui (tcu::TestContext& testCtx, glu::CallLogWrapper& gl, GLuint program, GLint location, GLuint x)
494{
495	using tcu::TestLog;
496
497	StateQueryMemoryWriteGuard<GLuint[1]> state;
498	gl.glGetUniformuiv(program, location, state);
499
500	if (!state.verifyValidity(testCtx))
501		return;
502
503	if (state[0] != x)
504	{
505		testCtx.getLog() << TestLog::Message
506		<< "// ERROR: expected ["
507		<< x
508		<< "]; got ["
509		<< state[0]
510		<< "]"
511		<< TestLog::EndMessage;
512
513		if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
514			testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid uniform value");
515	}
516}
517
518void verifyUniformValue2ui (tcu::TestContext& testCtx, glu::CallLogWrapper& gl, GLuint program, GLint location, GLuint x, GLuint y)
519{
520	using tcu::TestLog;
521
522	StateQueryMemoryWriteGuard<GLuint[2]> state;
523	gl.glGetUniformuiv(program, location, state);
524
525	if (!state.verifyValidity(testCtx))
526		return;
527
528	if (state[0] != x ||
529		state[1] != y)
530	{
531		testCtx.getLog() << TestLog::Message
532		<< "// ERROR: expected ["
533		<< x << ", "
534		<< y
535		<< "]; got ["
536		<< state[0] << ", "
537		<< state[1]
538		<< "]"
539		<< TestLog::EndMessage;
540
541		if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
542			testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid uniform value");
543	}
544}
545
546void verifyUniformValue3ui (tcu::TestContext& testCtx, glu::CallLogWrapper& gl, GLuint program, GLint location, GLuint x, GLuint y, GLuint z)
547{
548	using tcu::TestLog;
549
550	StateQueryMemoryWriteGuard<GLuint[3]> state;
551	gl.glGetUniformuiv(program, location, state);
552
553	if (!state.verifyValidity(testCtx))
554		return;
555
556	if (state[0] != x ||
557		state[1] != y ||
558		state[2] != z)
559	{
560		testCtx.getLog() << TestLog::Message
561		<< "// ERROR: expected ["
562		<< x << ", "
563		<< y << ", "
564		<< z
565		<< "]; got ["
566		<< state[0] << ", "
567		<< state[1] << ", "
568		<< state[2]
569		<< "]"
570		<< TestLog::EndMessage;
571
572		if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
573			testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid uniform value");
574	}
575}
576
577void verifyUniformValue4ui (tcu::TestContext& testCtx, glu::CallLogWrapper& gl, GLuint program, GLint location, GLuint x, GLuint y, GLuint z, GLuint w)
578{
579	using tcu::TestLog;
580
581	StateQueryMemoryWriteGuard<GLuint[4]> state;
582	gl.glGetUniformuiv(program, location, state);
583
584	if (!state.verifyValidity(testCtx))
585		return;
586
587	if (state[0] != x ||
588		state[1] != y ||
589		state[2] != z ||
590		state[3] != w)
591	{
592		testCtx.getLog() << TestLog::Message
593		<< "// ERROR: expected ["
594		<< x << ", "
595		<< y << ", "
596		<< z << ", "
597		<< w
598		<< "]; got ["
599		<< state[0] << ", "
600		<< state[1] << ", "
601		<< state[2] << ", "
602		<< state[3]
603		<< "]"
604		<< TestLog::EndMessage;
605
606		if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
607			testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid uniform value");
608	}
609}
610
611template <int Count>
612void verifyUniformValues (tcu::TestContext& testCtx, glu::CallLogWrapper& gl, GLuint program, GLint location, const GLfloat* values)
613{
614	using tcu::TestLog;
615
616	StateQueryMemoryWriteGuard<GLfloat[Count]> state;
617	gl.glGetUniformfv(program, location, state);
618
619	if (!state.verifyValidity(testCtx))
620		return;
621
622	for (int ndx = 0; ndx < Count; ++ndx)
623	{
624		if (values[ndx] != state[ndx])
625		{
626			testCtx.getLog() << TestLog::Message << "// ERROR: at index " << ndx << " expected " << values[ndx] << "; got " << state[ndx] << TestLog::EndMessage;
627
628			if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
629				testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid uniform value");
630		}
631	}
632}
633
634template <int N>
635void verifyUniformMatrixValues (tcu::TestContext& testCtx, glu::CallLogWrapper& gl, GLuint program, GLint location, const GLfloat* values, bool transpose)
636{
637	using tcu::TestLog;
638
639	StateQueryMemoryWriteGuard<GLfloat[N*N]> state;
640	gl.glGetUniformfv(program, location, state);
641
642	if (!state.verifyValidity(testCtx))
643		return;
644
645	for (int y = 0; y < N; ++y)
646		for (int x = 0; x < N; ++x)
647		{
648			const int refIndex = y*N + x;
649			const int stateIndex = transpose ? (x*N + y) : (y*N + x);
650
651			if (values[refIndex] != state[stateIndex])
652			{
653				testCtx.getLog() << TestLog::Message << "// ERROR: at index [" << y << "][" << x << "] expected " << values[refIndex] << "; got " << state[stateIndex] << TestLog::EndMessage;
654
655				if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
656					testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid uniform value");
657			}
658		}
659}
660
661class ShaderTypeCase : public ApiCase
662{
663public:
664	ShaderTypeCase (Context& context, const char* name, const char* description)
665		: ApiCase(context, name, description)
666	{
667	}
668
669	void test (void)
670	{
671		const GLenum shaderTypes[] = {GL_VERTEX_SHADER, GL_FRAGMENT_SHADER};
672		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(shaderTypes); ++ndx)
673		{
674			const GLuint shader = glCreateShader(shaderTypes[ndx]);
675			verifyShaderParam(m_testCtx, *this, shader, GL_SHADER_TYPE, shaderTypes[ndx]);
676			glDeleteShader(shader);
677		}
678	}
679};
680
681class ShaderCompileStatusCase : public ApiCase
682{
683public:
684	ShaderCompileStatusCase (Context& context, const char* name, const char* description)
685		: ApiCase(context, name, description)
686	{
687	}
688
689	void test (void)
690	{
691		GLuint shaderVert = glCreateShader(GL_VERTEX_SHADER);
692		GLuint shaderFrag = glCreateShader(GL_FRAGMENT_SHADER);
693
694		verifyShaderParam(m_testCtx, *this, shaderVert, GL_COMPILE_STATUS, GL_FALSE);
695		verifyShaderParam(m_testCtx, *this, shaderFrag, GL_COMPILE_STATUS, GL_FALSE);
696
697		glShaderSource(shaderVert, 1, &commonTestVertSource, DE_NULL);
698		glShaderSource(shaderFrag, 1, &commonTestFragSource, DE_NULL);
699
700		glCompileShader(shaderVert);
701		glCompileShader(shaderFrag);
702		expectError(GL_NO_ERROR);
703
704		verifyShaderParam(m_testCtx, *this, shaderVert, GL_COMPILE_STATUS, GL_TRUE);
705		verifyShaderParam(m_testCtx, *this, shaderFrag, GL_COMPILE_STATUS, GL_TRUE);
706
707		glDeleteShader(shaderVert);
708		glDeleteShader(shaderFrag);
709		expectError(GL_NO_ERROR);
710	}
711};
712
713class ShaderInfoLogCase : public ApiCase
714{
715public:
716	ShaderInfoLogCase (Context& context, const char* name, const char* description)
717		: ApiCase(context, name, description)
718	{
719	}
720
721	void test (void)
722	{
723		using tcu::TestLog;
724
725		// INFO_LOG_LENGTH is 0 by default and it includes null-terminator
726		const GLuint shader = glCreateShader(GL_VERTEX_SHADER);
727		verifyShaderParam(m_testCtx, *this, shader, GL_INFO_LOG_LENGTH, 0);
728
729		glShaderSource(shader, 1, &brokenShader, DE_NULL);
730		glCompileShader(shader);
731		expectError(GL_NO_ERROR);
732
733		// check the log length
734		StateQueryMemoryWriteGuard<GLint> logLength;
735		glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &logLength);
736		if (!logLength.verifyValidity(m_testCtx))
737		{
738			glDeleteShader(shader);
739			return;
740		}
741		if (logLength == 0)
742		{
743			glDeleteShader(shader);
744			return;
745		}
746
747		// check normal case
748		{
749			char buffer[2048] = {'x'}; // non-zero initialization
750
751			GLint written = 0; // written does not include null terminator
752			glGetShaderInfoLog(shader, DE_LENGTH_OF_ARRAY(buffer), &written, buffer);
753
754			// check lengths are consistent
755			if (logLength <= DE_LENGTH_OF_ARRAY(buffer))
756			{
757				if (written != logLength-1)
758				{
759					m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected length " << logLength-1 << "; got " << written << TestLog::EndMessage;
760					if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
761						m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid log length");
762				}
763			}
764
765			// check null-terminator, either at end of buffer or at buffer[written]
766			const char* terminator = &buffer[DE_LENGTH_OF_ARRAY(buffer) - 1];
767			if (logLength < DE_LENGTH_OF_ARRAY(buffer))
768				terminator = &buffer[written];
769
770			if (*terminator != '\0')
771			{
772				m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected null terminator, got " << (int)*terminator << TestLog::EndMessage;
773				if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
774					m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid log terminator");
775			}
776		}
777
778		// check with too small buffer
779		{
780			char buffer[2048] = {'x'}; // non-zero initialization
781
782			// check string always ends with \0, even with small buffers
783			GLint written = 0;
784			glGetShaderInfoLog(shader, 1, &written, buffer);
785			if (written != 0)
786			{
787				m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected length 0; got " << written << TestLog::EndMessage;
788				if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
789					m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid log length");
790			}
791			if (buffer[0] != '\0')
792			{
793				m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected null terminator, got " << (int)buffer[0] << TestLog::EndMessage;
794				if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
795					m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid log terminator");
796			}
797		}
798
799		glDeleteShader(shader);
800		expectError(GL_NO_ERROR);
801	}
802};
803
804class ShaderSourceCase : public ApiCase
805{
806public:
807	ShaderSourceCase (Context& context, const char* name, const char* description)
808		: ApiCase(context, name, description)
809	{
810	}
811
812	void test (void)
813	{
814		using tcu::TestLog;
815
816		// SHADER_SOURCE_LENGTH does include 0-terminator
817		const GLuint shader = glCreateShader(GL_VERTEX_SHADER);
818		verifyShaderParam(m_testCtx, *this, shader, GL_SHADER_SOURCE_LENGTH, 0);
819
820		// check the SHADER_SOURCE_LENGTH
821		{
822			glShaderSource(shader, 1, &brokenShader, DE_NULL);
823			expectError(GL_NO_ERROR);
824
825			StateQueryMemoryWriteGuard<GLint> sourceLength;
826			glGetShaderiv(shader, GL_SHADER_SOURCE_LENGTH, &sourceLength);
827
828			sourceLength.verifyValidity(m_testCtx);
829
830			const GLint referenceLength = (GLint)std::string(brokenShader).length() + 1; // including the null terminator
831			if (sourceLength != referenceLength)
832			{
833				m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected length " << referenceLength	<< "; got " << sourceLength << TestLog::EndMessage;
834				if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
835					m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid source length");
836			}
837		}
838
839		// check the concat source SHADER_SOURCE_LENGTH
840		{
841			const char* shaders[] = {brokenShader, brokenShader};
842			glShaderSource(shader, 2, shaders, DE_NULL);
843			expectError(GL_NO_ERROR);
844
845			StateQueryMemoryWriteGuard<GLint> sourceLength;
846			glGetShaderiv(shader, GL_SHADER_SOURCE_LENGTH, &sourceLength);
847
848			sourceLength.verifyValidity(m_testCtx);
849
850			const GLint referenceLength = 2 * (GLint)std::string(brokenShader).length() + 1; // including the null terminator
851			if (sourceLength != referenceLength)
852			{
853				m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected length " << referenceLength << "; got " << sourceLength << TestLog::EndMessage;
854				if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
855					m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid source length");
856			}
857		}
858
859		// check the string length
860		{
861			char buffer[2048] = {'x'};
862			DE_ASSERT(DE_LENGTH_OF_ARRAY(buffer) > 2 * (int)std::string(brokenShader).length());
863
864			GLint written = 0; // not inluding null-terminator
865			glGetShaderSource(shader, DE_LENGTH_OF_ARRAY(buffer), &written, buffer);
866
867			const GLint referenceLength = 2 * (GLint)std::string(brokenShader).length();
868			if (written != referenceLength)
869			{
870				m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected write length " << referenceLength << "; got " << written << TestLog::EndMessage;
871				if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
872					m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid source length");
873			}
874			// check null pointer at
875			else
876			{
877				if (buffer[referenceLength] != '\0')
878				{
879					m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected null terminator at " << referenceLength << TestLog::EndMessage;
880					if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
881						m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "did not get a null terminator");
882				}
883			}
884		}
885
886		// check with small buffer
887		{
888			char buffer[2048] = {'x'};
889
890			GLint written = 0;
891			glGetShaderSource(shader, 1, &written, buffer);
892
893			if (written != 0)
894			{
895				m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected write length 0; got " << written << TestLog::EndMessage;
896				if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
897					m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid source length");
898			}
899			if (buffer[0] != '\0')
900			{
901				m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected null terminator; got=" << int(buffer[0]) << ", char=" << buffer[0] << TestLog::EndMessage;
902				if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
903					m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid terminator");
904			}
905		}
906
907		glDeleteShader(shader);
908		expectError(GL_NO_ERROR);
909	}
910};
911
912class DeleteStatusCase : public ApiCase
913{
914public:
915	DeleteStatusCase (Context& context, const char* name, const char* description)
916		: ApiCase(context, name, description)
917	{
918	}
919
920	void test (void)
921	{
922		GLuint shaderVert = glCreateShader(GL_VERTEX_SHADER);
923		GLuint shaderFrag = glCreateShader(GL_FRAGMENT_SHADER);
924
925		glShaderSource(shaderVert, 1, &commonTestVertSource, DE_NULL);
926		glShaderSource(shaderFrag, 1, &commonTestFragSource, DE_NULL);
927
928		glCompileShader(shaderVert);
929		glCompileShader(shaderFrag);
930		expectError(GL_NO_ERROR);
931
932		verifyShaderParam(m_testCtx, *this, shaderVert, GL_COMPILE_STATUS, GL_TRUE);
933		verifyShaderParam(m_testCtx, *this, shaderFrag, GL_COMPILE_STATUS, GL_TRUE);
934
935		GLuint shaderProg = glCreateProgram();
936		glAttachShader(shaderProg, shaderVert);
937		glAttachShader(shaderProg, shaderFrag);
938		glLinkProgram(shaderProg);
939		expectError(GL_NO_ERROR);
940
941		verifyProgramParam	(m_testCtx, *this, shaderProg, GL_LINK_STATUS, GL_TRUE);
942
943		verifyShaderParam	(m_testCtx, *this, shaderVert, GL_DELETE_STATUS, GL_FALSE);
944		verifyShaderParam	(m_testCtx, *this, shaderFrag, GL_DELETE_STATUS, GL_FALSE);
945		verifyProgramParam	(m_testCtx, *this, shaderProg, GL_DELETE_STATUS, GL_FALSE);
946		expectError(GL_NO_ERROR);
947
948		glUseProgram(shaderProg);
949
950		glDeleteShader(shaderVert);
951		glDeleteShader(shaderFrag);
952		glDeleteProgram(shaderProg);
953		expectError(GL_NO_ERROR);
954
955		verifyShaderParam	(m_testCtx, *this, shaderVert, GL_DELETE_STATUS, GL_TRUE);
956		verifyShaderParam	(m_testCtx, *this, shaderFrag, GL_DELETE_STATUS, GL_TRUE);
957		verifyProgramParam	(m_testCtx, *this, shaderProg, GL_DELETE_STATUS, GL_TRUE);
958		expectError(GL_NO_ERROR);
959
960		glUseProgram(0);
961		expectError(GL_NO_ERROR);
962	}
963};
964
965class CurrentVertexAttribInitialCase : public ApiCase
966{
967public:
968	CurrentVertexAttribInitialCase (Context& context, const char* name, const char* description)
969		: ApiCase(context, name, description)
970	{
971	}
972
973	void test (void)
974	{
975		using tcu::TestLog;
976
977		int attribute_count = 16;
978		glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &attribute_count);
979
980		// initial
981
982		for (int index = 0; index < attribute_count; ++index)
983		{
984			StateQueryMemoryWriteGuard<GLfloat[4]> attribValue;
985			glGetVertexAttribfv(index, GL_CURRENT_VERTEX_ATTRIB, attribValue);
986			attribValue.verifyValidity(m_testCtx);
987
988			if (attribValue[0] != 0.0f || attribValue[1] != 0.0f || attribValue[2] != 0.0f || attribValue[3] != 1.0f)
989			{
990				m_testCtx.getLog() << TestLog::Message
991					<< "// ERROR: Expected [0, 0, 0, 1];"
992					<< "got [" << attribValue[0] << "," << attribValue[1] << "," << attribValue[2] << "," << attribValue[3] << "]"
993					<< TestLog::EndMessage;
994				if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
995					m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid attribute value");
996			}
997		}
998	}
999};
1000
1001class CurrentVertexAttribFloatCase : public ApiCase
1002{
1003public:
1004	CurrentVertexAttribFloatCase (Context& context, const char* name, const char* description)
1005		: ApiCase(context, name, description)
1006	{
1007	}
1008
1009	void test (void)
1010	{
1011		using tcu::TestLog;
1012
1013		de::Random rnd(0xabcdef);
1014
1015		int attribute_count = 16;
1016		glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &attribute_count);
1017
1018		// test write float/read float
1019
1020		for (int index = 0; index < attribute_count; ++index)
1021		{
1022			const GLfloat x = rnd.getFloat(-64000, 64000);
1023			const GLfloat y = rnd.getFloat(-64000, 64000);
1024			const GLfloat z = rnd.getFloat(-64000, 64000);
1025			const GLfloat w = rnd.getFloat(-64000, 64000);
1026
1027			glVertexAttrib4f(index, x, y, z, w);
1028			verifyCurrentVertexAttribf(m_testCtx, *this, index, x, y, z, w);
1029		}
1030		for (int index = 0; index < attribute_count; ++index)
1031		{
1032			const GLfloat x = rnd.getFloat(-64000, 64000);
1033			const GLfloat y = rnd.getFloat(-64000, 64000);
1034			const GLfloat z = rnd.getFloat(-64000, 64000);
1035			const GLfloat w = 1.0f;
1036
1037			glVertexAttrib3f(index, x, y, z);
1038			verifyCurrentVertexAttribf(m_testCtx, *this, index, x, y, z, w);
1039		}
1040		for (int index = 0; index < attribute_count; ++index)
1041		{
1042			const GLfloat x = rnd.getFloat(-64000, 64000);
1043			const GLfloat y = rnd.getFloat(-64000, 64000);
1044			const GLfloat z = 0.0f;
1045			const GLfloat w = 1.0f;
1046
1047			glVertexAttrib2f(index, x, y);
1048			verifyCurrentVertexAttribf(m_testCtx, *this, index, x, y, z, w);
1049		}
1050		for (int index = 0; index < attribute_count; ++index)
1051		{
1052			const GLfloat x = rnd.getFloat(-64000, 64000);
1053			const GLfloat y = 0.0f;
1054			const GLfloat z = 0.0f;
1055			const GLfloat w = 1.0f;
1056
1057			glVertexAttrib1f(index, x);
1058			verifyCurrentVertexAttribf(m_testCtx, *this, index, x, y, z, w);
1059		}
1060	}
1061};
1062
1063class CurrentVertexAttribIntCase : public ApiCase
1064{
1065public:
1066	CurrentVertexAttribIntCase (Context& context, const char* name, const char* description)
1067		: ApiCase(context, name, description)
1068	{
1069	}
1070
1071	void test (void)
1072	{
1073		using tcu::TestLog;
1074
1075		de::Random rnd(0xabcdef);
1076
1077		int attribute_count = 16;
1078		glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &attribute_count);
1079
1080		// test write float/read float
1081
1082		for (int index = 0; index < attribute_count; ++index)
1083		{
1084			const GLint x = rnd.getInt(-64000, 64000);
1085			const GLint y = rnd.getInt(-64000, 64000);
1086			const GLint z = rnd.getInt(-64000, 64000);
1087			const GLint w = rnd.getInt(-64000, 64000);
1088
1089			glVertexAttribI4i(index, x, y, z, w);
1090			verifyCurrentVertexAttribIi(m_testCtx, *this, index, x, y, z, w);
1091		}
1092	}
1093};
1094
1095class CurrentVertexAttribUintCase : public ApiCase
1096{
1097public:
1098	CurrentVertexAttribUintCase (Context& context, const char* name, const char* description)
1099		: ApiCase(context, name, description)
1100	{
1101	}
1102
1103	void test (void)
1104	{
1105		using tcu::TestLog;
1106
1107		de::Random rnd(0xabcdef);
1108
1109		int attribute_count = 16;
1110		glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &attribute_count);
1111
1112		// test write float/read float
1113
1114		for (int index = 0; index < attribute_count; ++index)
1115		{
1116			const GLuint x = rnd.getInt(0, 64000);
1117			const GLuint y = rnd.getInt(0, 64000);
1118			const GLuint z = rnd.getInt(0, 64000);
1119			const GLuint w = rnd.getInt(0, 64000);
1120
1121			glVertexAttribI4ui(index, x, y, z, w);
1122			verifyCurrentVertexAttribIui(m_testCtx, *this, index, x, y, z, w);
1123		}
1124	}
1125};
1126
1127class CurrentVertexAttribConversionCase : public ApiCase
1128{
1129public:
1130	CurrentVertexAttribConversionCase (Context& context, const char* name, const char* description)
1131		: ApiCase(context, name, description)
1132	{
1133	}
1134
1135	void test (void)
1136	{
1137		using tcu::TestLog;
1138
1139		de::Random rnd(0xabcdef);
1140
1141		int attribute_count = 16;
1142		glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &attribute_count);
1143
1144		// test write float/read float
1145
1146		for (int index = 0; index < attribute_count; ++index)
1147		{
1148			const GLfloat x = rnd.getFloat(-64000, 64000);
1149			const GLfloat y = rnd.getFloat(-64000, 64000);
1150			const GLfloat z = rnd.getFloat(-64000, 64000);
1151			const GLfloat w = rnd.getFloat(-64000, 64000);
1152
1153			glVertexAttrib4f(index, x, y, z, w);
1154			verifyCurrentVertexAttribConversion(m_testCtx, *this, index, x, y, z, w);
1155		}
1156		for (int index = 0; index < attribute_count; ++index)
1157		{
1158			const GLfloat x = rnd.getFloat(-64000, 64000);
1159			const GLfloat y = rnd.getFloat(-64000, 64000);
1160			const GLfloat z = rnd.getFloat(-64000, 64000);
1161			const GLfloat w = 1.0f;
1162
1163			glVertexAttrib3f(index, x, y, z);
1164			verifyCurrentVertexAttribConversion(m_testCtx, *this, index, x, y, z, w);
1165		}
1166		for (int index = 0; index < attribute_count; ++index)
1167		{
1168			const GLfloat x = rnd.getFloat(-64000, 64000);
1169			const GLfloat y = rnd.getFloat(-64000, 64000);
1170			const GLfloat z = 0.0f;
1171			const GLfloat w = 1.0f;
1172
1173			glVertexAttrib2f(index, x, y);
1174			verifyCurrentVertexAttribConversion(m_testCtx, *this, index, x, y, z, w);
1175		}
1176		for (int index = 0; index < attribute_count; ++index)
1177		{
1178			const GLfloat x = rnd.getFloat(-64000, 64000);
1179			const GLfloat y = 0.0f;
1180			const GLfloat z = 0.0f;
1181			const GLfloat w = 1.0f;
1182
1183			glVertexAttrib1f(index, x);
1184			verifyCurrentVertexAttribConversion(m_testCtx, *this, index, x, y, z, w);
1185		}
1186	}
1187};
1188
1189class ProgramInfoLogCase : public ApiCase
1190{
1191public:
1192	enum BuildErrorType
1193	{
1194		BUILDERROR_COMPILE = 0,
1195		BUILDERROR_LINK
1196	};
1197
1198	ProgramInfoLogCase (Context& context, const char* name, const char* description, BuildErrorType buildErrorType)
1199		: ApiCase			(context, name, description)
1200		, m_buildErrorType	(buildErrorType)
1201	{
1202	}
1203
1204	void test (void)
1205	{
1206		using tcu::TestLog;
1207
1208		enum
1209		{
1210			BUF_SIZE = 2048
1211		};
1212
1213		static const char* const linkErrorVtxSource = "#version 300 es\n"
1214													  "in highp vec4 a_pos;\n"
1215													  "uniform highp vec4 u_uniform;\n"
1216													  "void main ()\n"
1217													  "{\n"
1218													  "	gl_Position = a_pos + u_uniform;\n"
1219													  "}\n";
1220		static const char* const linkErrorFrgSource = "#version 300 es\n"
1221													  "in highp vec4 v_missingVar;\n"
1222													  "uniform highp int u_uniform;\n"
1223													  "layout(location = 0) out mediump vec4 fragColor;\n"
1224													  "void main ()\n"
1225													  "{\n"
1226													  "	fragColor = v_missingVar + vec4(float(u_uniform));\n"
1227													  "}\n";
1228
1229		const char* vtxSource = (m_buildErrorType == BUILDERROR_COMPILE) ? (brokenShader) : (linkErrorVtxSource);
1230		const char* frgSource = (m_buildErrorType == BUILDERROR_COMPILE) ? (brokenShader) : (linkErrorFrgSource);
1231
1232		GLuint shaderVert = glCreateShader(GL_VERTEX_SHADER);
1233		GLuint shaderFrag = glCreateShader(GL_FRAGMENT_SHADER);
1234
1235		glShaderSource(shaderVert, 1, &vtxSource, DE_NULL);
1236		glShaderSource(shaderFrag, 1, &frgSource, DE_NULL);
1237
1238		glCompileShader(shaderVert);
1239		glCompileShader(shaderFrag);
1240		expectError(GL_NO_ERROR);
1241
1242		GLuint program = glCreateProgram();
1243		glAttachShader(program, shaderVert);
1244		glAttachShader(program, shaderFrag);
1245		glLinkProgram(program);
1246
1247		StateQueryMemoryWriteGuard<GLint> logLength;
1248		glGetProgramiv(program, GL_INFO_LOG_LENGTH, &logLength);
1249		logLength.verifyValidity(m_testCtx);
1250
1251		// check INFO_LOG_LENGTH == GetProgramInfoLog len
1252		{
1253			const tcu::ScopedLogSection	section				(m_testCtx.getLog(), "QueryLarge", "Query to large buffer");
1254			char						buffer[BUF_SIZE]	= {'x'};
1255			GLint						written				= 0;
1256
1257			glGetProgramInfoLog(program, BUF_SIZE, &written, buffer);
1258
1259			if (logLength != 0 && written+1 != logLength) // INFO_LOG_LENGTH contains 0-terminator
1260			{
1261				m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected INFO_LOG_LENGTH " << written+1 << "; got " << logLength << TestLog::EndMessage;
1262				if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
1263					m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid log length");
1264			}
1265			else if (logLength != 0 && buffer[written] != '\0')
1266			{
1267				m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected null terminator at index " << written << TestLog::EndMessage;
1268				if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
1269					m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "missing null terminator");
1270			}
1271		}
1272
1273		// check query to just correct sized buffer
1274		if (BUF_SIZE > logLength)
1275		{
1276			const tcu::ScopedLogSection	section				(m_testCtx.getLog(), "QueryAll", "Query all to exactly right sized buffer");
1277			char						buffer[BUF_SIZE]	= {'x'};
1278			GLint						written				= 0;
1279
1280			glGetProgramInfoLog(program, logLength, &written, buffer);
1281
1282			if (logLength != 0 && written+1 != logLength) // INFO_LOG_LENGTH contains 0-terminator
1283			{
1284				m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected INFO_LOG_LENGTH " << written+1 << "; got " << logLength << TestLog::EndMessage;
1285				if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
1286					m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid log length");
1287			}
1288			else if (logLength != 0 && buffer[written] != '\0')
1289			{
1290				m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected null terminator at index " << written << TestLog::EndMessage;
1291				if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
1292					m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "missing null terminator");
1293			}
1294		}
1295
1296		// check GetProgramInfoLog works with too small buffer
1297		{
1298			const tcu::ScopedLogSection	section				(m_testCtx.getLog(), "QueryNone", "Query none");
1299			char						buffer[BUF_SIZE]	= {'x'};
1300			GLint						written				= 0;
1301
1302			glGetProgramInfoLog(program, 1, &written, buffer);
1303
1304			if (written != 0)
1305			{
1306				m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected write length 0; got " << written << TestLog::EndMessage;
1307				if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
1308					m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid log length");
1309			}
1310		}
1311
1312		glDeleteShader(shaderVert);
1313		glDeleteShader(shaderFrag);
1314		glDeleteProgram(program);
1315		expectError(GL_NO_ERROR);
1316	}
1317
1318	const BuildErrorType m_buildErrorType;
1319};
1320
1321class ProgramValidateStatusCase : public ApiCase
1322{
1323public:
1324	ProgramValidateStatusCase (Context& context, const char* name, const char* description)
1325		: ApiCase(context, name, description)
1326	{
1327	}
1328
1329	void test (void)
1330	{
1331		// test validate ok
1332		{
1333			GLuint shaderVert = glCreateShader(GL_VERTEX_SHADER);
1334			GLuint shaderFrag = glCreateShader(GL_FRAGMENT_SHADER);
1335
1336			glShaderSource(shaderVert, 1, &commonTestVertSource, DE_NULL);
1337			glShaderSource(shaderFrag, 1, &commonTestFragSource, DE_NULL);
1338
1339			glCompileShader(shaderVert);
1340			glCompileShader(shaderFrag);
1341			expectError(GL_NO_ERROR);
1342
1343			GLuint program = glCreateProgram();
1344			glAttachShader(program, shaderVert);
1345			glAttachShader(program, shaderFrag);
1346			glLinkProgram(program);
1347			expectError(GL_NO_ERROR);
1348
1349			verifyShaderParam	(m_testCtx, *this, shaderVert,	GL_COMPILE_STATUS,	GL_TRUE);
1350			verifyShaderParam	(m_testCtx, *this, shaderFrag,	GL_COMPILE_STATUS,	GL_TRUE);
1351			verifyProgramParam	(m_testCtx, *this, program,		GL_LINK_STATUS,		GL_TRUE);
1352
1353			glValidateProgram(program);
1354			verifyProgramParam(m_testCtx, *this, program, GL_VALIDATE_STATUS, GL_TRUE);
1355
1356			glDeleteShader(shaderVert);
1357			glDeleteShader(shaderFrag);
1358			glDeleteProgram(program);
1359			expectError(GL_NO_ERROR);
1360		}
1361
1362		// test with broken shader
1363		{
1364			GLuint shaderVert = glCreateShader(GL_VERTEX_SHADER);
1365			GLuint shaderFrag = glCreateShader(GL_FRAGMENT_SHADER);
1366
1367			glShaderSource(shaderVert, 1, &commonTestVertSource,	DE_NULL);
1368			glShaderSource(shaderFrag, 1, &brokenShader,			DE_NULL);
1369
1370			glCompileShader(shaderVert);
1371			glCompileShader(shaderFrag);
1372			expectError(GL_NO_ERROR);
1373
1374			GLuint program = glCreateProgram();
1375			glAttachShader(program, shaderVert);
1376			glAttachShader(program, shaderFrag);
1377			glLinkProgram(program);
1378			expectError(GL_NO_ERROR);
1379
1380			verifyShaderParam	(m_testCtx, *this, shaderVert,	GL_COMPILE_STATUS,	GL_TRUE);
1381			verifyShaderParam	(m_testCtx, *this, shaderFrag,	GL_COMPILE_STATUS,	GL_FALSE);
1382			verifyProgramParam	(m_testCtx, *this, program,		GL_LINK_STATUS,		GL_FALSE);
1383
1384			glValidateProgram(program);
1385			verifyProgramParam(m_testCtx, *this, program, GL_VALIDATE_STATUS, GL_FALSE);
1386
1387			glDeleteShader(shaderVert);
1388			glDeleteShader(shaderFrag);
1389			glDeleteProgram(program);
1390			expectError(GL_NO_ERROR);
1391		}
1392	}
1393};
1394
1395class ProgramAttachedShadersCase : public ApiCase
1396{
1397public:
1398	ProgramAttachedShadersCase (Context& context, const char* name, const char* description)
1399		: ApiCase(context, name, description)
1400	{
1401	}
1402
1403	void test (void)
1404	{
1405		using tcu::TestLog;
1406
1407		GLuint shaderVert = glCreateShader(GL_VERTEX_SHADER);
1408		GLuint shaderFrag = glCreateShader(GL_FRAGMENT_SHADER);
1409
1410		glShaderSource(shaderVert, 1, &commonTestVertSource, DE_NULL);
1411		glShaderSource(shaderFrag, 1, &commonTestFragSource, DE_NULL);
1412
1413		glCompileShader(shaderVert);
1414		glCompileShader(shaderFrag);
1415		expectError(GL_NO_ERROR);
1416
1417		// check ATTACHED_SHADERS
1418
1419		GLuint program = glCreateProgram();
1420		verifyProgramParam(m_testCtx, *this, program, GL_ATTACHED_SHADERS, 0);
1421		expectError(GL_NO_ERROR);
1422
1423		glAttachShader(program, shaderVert);
1424		verifyProgramParam(m_testCtx, *this, program, GL_ATTACHED_SHADERS, 1);
1425		expectError(GL_NO_ERROR);
1426
1427		glAttachShader(program, shaderFrag);
1428		verifyProgramParam(m_testCtx, *this, program, GL_ATTACHED_SHADERS, 2);
1429		expectError(GL_NO_ERROR);
1430
1431		// check GetAttachedShaders
1432		{
1433			GLuint shaders[2] = {0, 0};
1434			GLint count = 0;
1435			glGetAttachedShaders(program, DE_LENGTH_OF_ARRAY(shaders), &count, shaders);
1436
1437			if (count != 2)
1438			{
1439				m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected 2; got " << count << TestLog::EndMessage;
1440				if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
1441					m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got wrong shader count");
1442			}
1443			// shaders are the attached shaders?
1444			if (!((shaders[0] == shaderVert && shaders[1] == shaderFrag) ||
1445				  (shaders[0] == shaderFrag && shaders[1] == shaderVert)))
1446			{
1447				m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected {" << shaderVert << ", " << shaderFrag << "}; got {" << shaders[0] << ", " << shaders[1] << "}" << TestLog::EndMessage;
1448				if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
1449					m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got wrong shader count");
1450			}
1451		}
1452
1453		// check GetAttachedShaders with too small buffer
1454		{
1455			GLuint shaders[2] = {0, 0};
1456			GLint count = 0;
1457
1458			glGetAttachedShaders(program, 0, &count, shaders);
1459			if (count != 0)
1460			{
1461				m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected 0; got " << count << TestLog::EndMessage;
1462				if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
1463					m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got wrong shader count");
1464			}
1465
1466			count = 0;
1467			glGetAttachedShaders(program, 1, &count, shaders);
1468			if (count != 1)
1469			{
1470				m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected 1; got " << count << TestLog::EndMessage;
1471				if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
1472					m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got wrong shader count");
1473			}
1474		}
1475
1476		glDeleteShader(shaderVert);
1477		glDeleteShader(shaderFrag);
1478		glDeleteProgram(program);
1479		expectError(GL_NO_ERROR);
1480	}
1481};
1482
1483class ProgramActiveUniformNameCase : public ApiCase
1484{
1485public:
1486	ProgramActiveUniformNameCase (Context& context, const char* name, const char* description)
1487		: ApiCase(context, name, description)
1488	{
1489	}
1490
1491	void test (void)
1492	{
1493		using tcu::TestLog;
1494
1495		static const char* testVertSource =
1496			"#version 300 es\n"
1497			"uniform highp float uniformNameWithLength23;\n"
1498			"uniform highp vec2 uniformVec2;\n"
1499			"uniform highp mat4 uniformMat4;\n"
1500			"void main (void)\n"
1501			"{\n"
1502			"	gl_Position = vec4(0.0) + vec4(uniformNameWithLength23) + vec4(uniformVec2.x) + vec4(uniformMat4[2][3]);\n"
1503			"}\n\0";
1504		static const char* testFragSource =
1505			"#version 300 es\n"
1506			"layout(location = 0) out mediump vec4 fragColor;"
1507			"void main (void)\n"
1508			"{\n"
1509			"	fragColor = vec4(0.0);\n"
1510			"}\n\0";
1511
1512		GLuint shaderVert = glCreateShader(GL_VERTEX_SHADER);
1513		GLuint shaderFrag = glCreateShader(GL_FRAGMENT_SHADER);
1514
1515		glShaderSource(shaderVert, 1, &testVertSource, DE_NULL);
1516		glShaderSource(shaderFrag, 1, &testFragSource, DE_NULL);
1517
1518		glCompileShader(shaderVert);
1519		glCompileShader(shaderFrag);
1520		expectError(GL_NO_ERROR);
1521
1522		GLuint program = glCreateProgram();
1523		glAttachShader(program, shaderVert);
1524		glAttachShader(program, shaderFrag);
1525		glLinkProgram(program);
1526		expectError(GL_NO_ERROR);
1527
1528		verifyProgramParam(m_testCtx, *this, program, GL_ACTIVE_UNIFORMS, 3);
1529		verifyProgramParam(m_testCtx, *this, program, GL_ACTIVE_UNIFORM_MAX_LENGTH, (GLint)std::string("uniformNameWithLength23").length() + 1); // including a null terminator
1530		expectError(GL_NO_ERROR);
1531
1532		const char* uniformNames[] =
1533		{
1534			"uniformNameWithLength23",
1535			"uniformVec2",
1536			"uniformMat4"
1537		};
1538		StateQueryMemoryWriteGuard<GLuint[DE_LENGTH_OF_ARRAY(uniformNames)]> uniformIndices;
1539		glGetUniformIndices(program, DE_LENGTH_OF_ARRAY(uniformNames), uniformNames, uniformIndices);
1540		uniformIndices.verifyValidity(m_testCtx);
1541
1542		// check name lengths
1543		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(uniformNames); ++ndx)
1544		{
1545			const GLuint uniformIndex = uniformIndices[ndx];
1546
1547			StateQueryMemoryWriteGuard<GLint> uniformNameLen;
1548			glGetActiveUniformsiv(program, 1, &uniformIndex, GL_UNIFORM_NAME_LENGTH, &uniformNameLen);
1549
1550			uniformNameLen.verifyValidity(m_testCtx);
1551
1552			const GLint referenceLength = (GLint)std::string(uniformNames[ndx]).length() + 1;
1553			if (referenceLength != uniformNameLen) // uniformNameLen is with null terminator
1554			{
1555				m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected " << referenceLength << "got " << uniformNameLen << TestLog::EndMessage;
1556				if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
1557					m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got wrong uniform name length");
1558			}
1559		}
1560
1561		// check names
1562		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(uniformNames); ++ndx)
1563		{
1564			char buffer[2048] = {'x'};
1565
1566			const GLuint uniformIndex = uniformIndices[ndx];
1567
1568			GLint written = 0; // null terminator not included
1569			GLint size = 0;
1570			GLenum type = 0;
1571			glGetActiveUniform(program, uniformIndex, DE_LENGTH_OF_ARRAY(buffer), &written, &size, &type, buffer);
1572
1573			const GLint referenceLength = (GLint)std::string(uniformNames[ndx]).length();
1574			if (referenceLength != written)
1575			{
1576				m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected " << referenceLength << "got " << written << TestLog::EndMessage;
1577				if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
1578					m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got wrong uniform name length");
1579			}
1580
1581			// and with too small buffer
1582			written = 0;
1583			glGetActiveUniform(program, uniformIndex, 1, &written, &size, &type, buffer);
1584
1585			if (written != 0)
1586			{
1587				m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected 0 got " << written << TestLog::EndMessage;
1588				if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
1589					m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got wrong uniform name length");
1590			}
1591		}
1592
1593
1594		glDeleteShader(shaderVert);
1595		glDeleteShader(shaderFrag);
1596		glDeleteProgram(program);
1597		expectError(GL_NO_ERROR);
1598	}
1599};
1600
1601class ProgramUniformCase : public ApiCase
1602{
1603public:
1604	ProgramUniformCase (Context& context, const char* name, const char* description)
1605		: ApiCase(context, name, description)
1606	{
1607	}
1608
1609	void test (void)
1610	{
1611		const struct UniformType
1612		{
1613			const char* declaration;
1614			const char* postDeclaration;
1615			const char* precision;
1616			const char* layout;
1617			const char* getter;
1618			GLenum		type;
1619			GLint		size;
1620			GLint		isRowMajor;
1621		} uniformTypes[] =
1622		{
1623			{ "float",					"",			"highp",	"",						"uniformValue",							GL_FLOAT,							1, GL_FALSE },
1624			{ "float[2]",				"",			"highp",	"",						"uniformValue[1]",						GL_FLOAT,							2, GL_FALSE },
1625			{ "vec2",					"",			"highp",	"",						"uniformValue.x",						GL_FLOAT_VEC2,						1, GL_FALSE },
1626			{ "vec3",					"",			"highp",	"",						"uniformValue.x",						GL_FLOAT_VEC3,						1, GL_FALSE },
1627			{ "vec4",					"",			"highp",	"",						"uniformValue.x",						GL_FLOAT_VEC4,						1, GL_FALSE },
1628			{ "int",					"",			"highp",	"",						"float(uniformValue)",					GL_INT,								1, GL_FALSE },
1629			{ "ivec2",					"",			"highp",	"",						"float(uniformValue.x)",				GL_INT_VEC2,						1, GL_FALSE },
1630			{ "ivec3",					"",			"highp",	"",						"float(uniformValue.x)",				GL_INT_VEC3,						1, GL_FALSE },
1631			{ "ivec4",					"",			"highp",	"",						"float(uniformValue.x)",				GL_INT_VEC4,						1, GL_FALSE },
1632			{ "uint",					"",			"highp",	"",						"float(uniformValue)",					GL_UNSIGNED_INT,					1, GL_FALSE },
1633			{ "uvec2",					"",			"highp",	"",						"float(uniformValue.x)",				GL_UNSIGNED_INT_VEC2,				1, GL_FALSE },
1634			{ "uvec3",					"",			"highp",	"",						"float(uniformValue.x)",				GL_UNSIGNED_INT_VEC3,				1, GL_FALSE },
1635			{ "uvec4",					"",			"highp",	"",						"float(uniformValue.x)",				GL_UNSIGNED_INT_VEC4,				1, GL_FALSE },
1636			{ "bool",					"",			"",			"",						"float(uniformValue)",					GL_BOOL,							1, GL_FALSE },
1637			{ "bvec2",					"",			"",			"",						"float(uniformValue.x)",				GL_BOOL_VEC2,						1, GL_FALSE },
1638			{ "bvec3",					"",			"",			"",						"float(uniformValue.x)",				GL_BOOL_VEC3,						1, GL_FALSE },
1639			{ "bvec4",					"",			"",			"",						"float(uniformValue.x)",				GL_BOOL_VEC4,						1, GL_FALSE },
1640			{ "mat2",					"",			"highp",	"",						"float(uniformValue[0][0])",			GL_FLOAT_MAT2,						1, GL_FALSE },
1641			{ "mat3",					"",			"highp",	"",						"float(uniformValue[0][0])",			GL_FLOAT_MAT3,						1, GL_FALSE },
1642			{ "mat4",					"",			"highp",	"",						"float(uniformValue[0][0])",			GL_FLOAT_MAT4,						1, GL_FALSE },
1643			{ "mat2x3",					"",			"highp",	"",						"float(uniformValue[0][0])",			GL_FLOAT_MAT2x3,					1, GL_FALSE },
1644			{ "mat2x4",					"",			"highp",	"",						"float(uniformValue[0][0])",			GL_FLOAT_MAT2x4,					1, GL_FALSE },
1645			{ "mat3x2",					"",			"highp",	"",						"float(uniformValue[0][0])",			GL_FLOAT_MAT3x2,					1, GL_FALSE },
1646			{ "mat3x4",					"",			"highp",	"",						"float(uniformValue[0][0])",			GL_FLOAT_MAT3x4,					1, GL_FALSE },
1647			{ "mat4x2",					"",			"highp",	"",						"float(uniformValue[0][0])",			GL_FLOAT_MAT4x2,					1, GL_FALSE },
1648			{ "mat4x3",					"",			"highp",	"",						"float(uniformValue[0][0])",			GL_FLOAT_MAT4x3,					1, GL_FALSE },
1649			{ "sampler2D",				"",			"highp",	"",						"float(textureSize(uniformValue,0).r)",	GL_SAMPLER_2D,						1, GL_FALSE },
1650			{ "sampler3D",				"",			"highp",	"",						"float(textureSize(uniformValue,0).r)",	GL_SAMPLER_3D,						1, GL_FALSE },
1651			{ "samplerCube",			"",			"highp",	"",						"float(textureSize(uniformValue,0).r)",	GL_SAMPLER_CUBE,					1, GL_FALSE },
1652			{ "sampler2DShadow",		"",			"highp",	"",						"float(textureSize(uniformValue,0).r)",	GL_SAMPLER_2D_SHADOW,				1, GL_FALSE },
1653			{ "sampler2DArray",			"",			"highp",	"",						"float(textureSize(uniformValue,0).r)",	GL_SAMPLER_2D_ARRAY,				1, GL_FALSE },
1654			{ "sampler2DArrayShadow",	"",			"highp",	"",						"float(textureSize(uniformValue,0).r)",	GL_SAMPLER_2D_ARRAY_SHADOW,			1, GL_FALSE },
1655			{ "samplerCubeShadow",		"",			"highp",	"",						"float(textureSize(uniformValue,0).r)",	GL_SAMPLER_CUBE_SHADOW,				1, GL_FALSE },
1656			{ "isampler2D",				"",			"highp",	"",						"float(textureSize(uniformValue,0).r)",	GL_INT_SAMPLER_2D,					1, GL_FALSE },
1657			{ "isampler3D",				"",			"highp",	"",						"float(textureSize(uniformValue,0).r)",	GL_INT_SAMPLER_3D,					1, GL_FALSE },
1658			{ "isamplerCube",			"",			"highp",	"",						"float(textureSize(uniformValue,0).r)",	GL_INT_SAMPLER_CUBE,				1, GL_FALSE },
1659			{ "isampler2DArray",		"",			"highp",	"",						"float(textureSize(uniformValue,0).r)",	GL_INT_SAMPLER_2D_ARRAY,			1, GL_FALSE },
1660			{ "usampler2D",				"",			"highp",	"",						"float(textureSize(uniformValue,0).r)",	GL_UNSIGNED_INT_SAMPLER_2D,			1, GL_FALSE },
1661			{ "usampler3D",				"",			"highp",	"",						"float(textureSize(uniformValue,0).r)",	GL_UNSIGNED_INT_SAMPLER_3D,			1, GL_FALSE },
1662			{ "usamplerCube",			"",			"highp",	"",						"float(textureSize(uniformValue,0).r)",	GL_UNSIGNED_INT_SAMPLER_CUBE,		1, GL_FALSE },
1663			{ "usampler2DArray",		"",			"highp",	"",						"float(textureSize(uniformValue,0).r)",	GL_UNSIGNED_INT_SAMPLER_2D_ARRAY,	1, GL_FALSE },
1664		};
1665
1666		static const char* vertSource =
1667			"#version 300 es\n"
1668			"void main (void)\n"
1669			"{\n"
1670			"	gl_Position = vec4(0.0);\n"
1671			"}\n\0";
1672
1673		GLuint shaderVert	= glCreateShader(GL_VERTEX_SHADER);
1674		GLuint shaderFrag	= glCreateShader(GL_FRAGMENT_SHADER);
1675		GLuint program		= glCreateProgram();
1676
1677		glAttachShader(program, shaderVert);
1678		glAttachShader(program, shaderFrag);
1679
1680		glShaderSource(shaderVert, 1, &vertSource, DE_NULL);
1681		glCompileShader(shaderVert);
1682		expectError(GL_NO_ERROR);
1683
1684		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(uniformTypes); ++ndx)
1685		{
1686			tcu::ScopedLogSection(m_log, uniformTypes[ndx].declaration, std::string("Verify type of ") + uniformTypes[ndx].declaration + " variable" + uniformTypes[ndx].postDeclaration );
1687
1688			// gen fragment shader
1689
1690			std::ostringstream frag;
1691			frag << "#version 300 es\n";
1692			frag << uniformTypes[ndx].layout << "uniform " << uniformTypes[ndx].precision << " " << uniformTypes[ndx].declaration << " uniformValue" << uniformTypes[ndx].postDeclaration << ";\n";
1693			frag << "layout(location = 0) out mediump vec4 fragColor;\n";
1694			frag << "void main (void)\n";
1695			frag << "{\n";
1696			frag << "	fragColor = vec4(" << uniformTypes[ndx].getter << ");\n";
1697			frag << "}\n";
1698
1699			{
1700				std::string fragmentSource = frag.str();
1701				const char* fragmentSourceCStr = fragmentSource.c_str();
1702				glShaderSource(shaderFrag, 1, &fragmentSourceCStr, DE_NULL);
1703			}
1704
1705			// compile & link
1706
1707			glCompileShader(shaderFrag);
1708			glLinkProgram(program);
1709
1710			// test
1711			if (verifyProgramParam(m_testCtx, *this, program, GL_LINK_STATUS, GL_TRUE))
1712			{
1713				const char* uniformNames[] = {"uniformValue"};
1714				StateQueryMemoryWriteGuard<GLuint> uniformIndex;
1715				glGetUniformIndices(program, 1, uniformNames, &uniformIndex);
1716				uniformIndex.verifyValidity(m_testCtx);
1717
1718				verifyActiveUniformParam(m_testCtx, *this, program, uniformIndex, GL_UNIFORM_TYPE,			uniformTypes[ndx].type);
1719				verifyActiveUniformParam(m_testCtx, *this, program, uniformIndex, GL_UNIFORM_SIZE,			uniformTypes[ndx].size);
1720				verifyActiveUniformParam(m_testCtx, *this, program, uniformIndex, GL_UNIFORM_IS_ROW_MAJOR,	uniformTypes[ndx].isRowMajor);
1721			}
1722		}
1723
1724		glDeleteShader(shaderVert);
1725		glDeleteShader(shaderFrag);
1726		glDeleteProgram(program);
1727		expectError(GL_NO_ERROR);
1728	}
1729};
1730
1731class ProgramActiveUniformBlocksCase : public ApiCase
1732{
1733public:
1734	ProgramActiveUniformBlocksCase (Context& context, const char* name, const char* description)
1735		: ApiCase(context, name, description)
1736	{
1737	}
1738
1739	void test (void)
1740	{
1741		using tcu::TestLog;
1742
1743		static const char* testVertSource =
1744			"#version 300 es\n"
1745			"uniform longlongUniformBlockName {highp vec2 vector2;} longlongUniformInstanceName;\n"
1746			"uniform shortUniformBlockName {highp vec2 vector2;highp vec4 vector4;} shortUniformInstanceName;\n"
1747			"void main (void)\n"
1748			"{\n"
1749			"	gl_Position = shortUniformInstanceName.vector4 + vec4(longlongUniformInstanceName.vector2.x) + vec4(shortUniformInstanceName.vector2.x);\n"
1750			"}\n\0";
1751		static const char* testFragSource =
1752			"#version 300 es\n"
1753			"uniform longlongUniformBlockName {highp vec2 vector2;} longlongUniformInstanceName;\n"
1754			"layout(location = 0) out mediump vec4 fragColor;"
1755			"void main (void)\n"
1756			"{\n"
1757			"	fragColor = vec4(longlongUniformInstanceName.vector2.y);\n"
1758			"}\n\0";
1759
1760		GLuint shaderVert = glCreateShader(GL_VERTEX_SHADER);
1761		GLuint shaderFrag = glCreateShader(GL_FRAGMENT_SHADER);
1762
1763		glShaderSource(shaderVert, 1, &testVertSource, DE_NULL);
1764		glShaderSource(shaderFrag, 1, &testFragSource, DE_NULL);
1765
1766		glCompileShader(shaderVert);
1767		glCompileShader(shaderFrag);
1768		expectError(GL_NO_ERROR);
1769
1770		GLuint program = glCreateProgram();
1771		glAttachShader(program, shaderVert);
1772		glAttachShader(program, shaderFrag);
1773		glLinkProgram(program);
1774		expectError(GL_NO_ERROR);
1775
1776		verifyShaderParam	(m_testCtx, *this, shaderVert,	GL_COMPILE_STATUS,	GL_TRUE);
1777		verifyShaderParam	(m_testCtx, *this, shaderFrag,	GL_COMPILE_STATUS,	GL_TRUE);
1778		verifyProgramParam	(m_testCtx, *this, program,		GL_LINK_STATUS,		GL_TRUE);
1779
1780		verifyProgramParam	(m_testCtx, *this, program,		GL_ACTIVE_UNIFORM_BLOCKS, 2);
1781		verifyProgramParam	(m_testCtx, *this, program,		GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH, (GLint)std::string("longlongUniformBlockName").length() + 1); // including a null terminator
1782		expectError(GL_NO_ERROR);
1783
1784		GLint longlongUniformBlockIndex	= glGetUniformBlockIndex(program, "longlongUniformBlockName");
1785		GLint shortUniformBlockIndex	= glGetUniformBlockIndex(program, "shortUniformBlockName");
1786
1787		const char* uniformNames[] =
1788		{
1789			"longlongUniformBlockName.vector2",
1790			"shortUniformBlockName.vector2",
1791			"shortUniformBlockName.vector4"
1792		};
1793
1794		// test UNIFORM_BLOCK_INDEX
1795
1796		DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(uniformNames) == 3);
1797
1798		StateQueryMemoryWriteGuard<GLuint[DE_LENGTH_OF_ARRAY(uniformNames)]> uniformIndices;
1799		StateQueryMemoryWriteGuard<GLint[DE_LENGTH_OF_ARRAY(uniformNames)]> uniformsBlockIndices;
1800
1801		glGetUniformIndices(program, DE_LENGTH_OF_ARRAY(uniformNames), uniformNames, uniformIndices);
1802		uniformIndices.verifyValidity(m_testCtx);
1803		expectError(GL_NO_ERROR);
1804
1805		glGetActiveUniformsiv(program, DE_LENGTH_OF_ARRAY(uniformNames), uniformIndices, GL_UNIFORM_BLOCK_INDEX, uniformsBlockIndices);
1806		uniformsBlockIndices.verifyValidity(m_testCtx);
1807		expectError(GL_NO_ERROR);
1808
1809		if (uniformsBlockIndices[0] != longlongUniformBlockIndex ||
1810			uniformsBlockIndices[1] != shortUniformBlockIndex ||
1811			uniformsBlockIndices[2] != shortUniformBlockIndex)
1812		{
1813			m_testCtx.getLog() << TestLog::Message
1814				<< "// ERROR: Expected ["	<< longlongUniformBlockIndex	<< ", " << shortUniformBlockIndex	<< ", " << shortUniformBlockIndex	<< "];"
1815				<<	"got ["					<< uniformsBlockIndices[0]		<< ", " << uniformsBlockIndices[1]	<< ", " << uniformsBlockIndices[2]	<< "]" << TestLog::EndMessage;
1816			if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
1817				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got wrong uniform block index");
1818		}
1819
1820		// test UNIFORM_BLOCK_NAME_LENGTH
1821
1822		verifyActiveUniformBlockParam(m_testCtx, *this, program, longlongUniformBlockIndex,	GL_UNIFORM_BLOCK_NAME_LENGTH, (GLint)std::string("longlongUniformBlockName").length() + 1); // including null-terminator
1823		verifyActiveUniformBlockParam(m_testCtx, *this, program, shortUniformBlockIndex,	GL_UNIFORM_BLOCK_NAME_LENGTH, (GLint)std::string("shortUniformBlockName").length() + 1); // including null-terminator
1824		expectError(GL_NO_ERROR);
1825
1826		// test UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER & UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER
1827
1828		verifyActiveUniformBlockParam(m_testCtx, *this, program, longlongUniformBlockIndex,	GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER,	GL_TRUE);
1829		verifyActiveUniformBlockParam(m_testCtx, *this, program, longlongUniformBlockIndex,	GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER,	GL_TRUE);
1830		verifyActiveUniformBlockParam(m_testCtx, *this, program, shortUniformBlockIndex,	GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER,	GL_TRUE);
1831		verifyActiveUniformBlockParam(m_testCtx, *this, program, shortUniformBlockIndex,	GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER,	GL_FALSE);
1832		expectError(GL_NO_ERROR);
1833
1834		// test UNIFORM_BLOCK_ACTIVE_UNIFORMS
1835
1836		verifyActiveUniformBlockParam(m_testCtx, *this, program, longlongUniformBlockIndex,	GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS,	1);
1837		verifyActiveUniformBlockParam(m_testCtx, *this, program, shortUniformBlockIndex,	GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS,	2);
1838		expectError(GL_NO_ERROR);
1839
1840		// test UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES
1841
1842		{
1843			StateQueryMemoryWriteGuard<GLint> longlongUniformBlockUniforms;
1844			glGetActiveUniformBlockiv(program, longlongUniformBlockIndex, GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, &longlongUniformBlockUniforms);
1845			longlongUniformBlockUniforms.verifyValidity(m_testCtx);
1846
1847			if (longlongUniformBlockUniforms == 2)
1848			{
1849				StateQueryMemoryWriteGuard<GLint[2]> longlongUniformBlockUniformIndices;
1850				glGetActiveUniformBlockiv(program, longlongUniformBlockIndex, GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES, longlongUniformBlockUniformIndices);
1851				longlongUniformBlockUniformIndices.verifyValidity(m_testCtx);
1852
1853				if ((GLuint(longlongUniformBlockUniformIndices[0]) != uniformIndices[0] || GLuint(longlongUniformBlockUniformIndices[1]) != uniformIndices[1]) &&
1854					(GLuint(longlongUniformBlockUniformIndices[1]) != uniformIndices[0] || GLuint(longlongUniformBlockUniformIndices[0]) != uniformIndices[1]))
1855				{
1856					m_testCtx.getLog() << TestLog::Message
1857						<< "// ERROR: Expected {"	<< uniformIndices[0]						<< ", " << uniformIndices[1] << "};"
1858						<<	"got {"					<< longlongUniformBlockUniformIndices[0]	<< ", " << longlongUniformBlockUniformIndices[1] << "}" << TestLog::EndMessage;
1859
1860					if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
1861						m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got wrong uniform indices");
1862				}
1863
1864			}
1865		}
1866
1867		// check block names
1868
1869		{
1870			char buffer[2048] = {'x'};
1871			GLint written = 0;
1872			glGetActiveUniformBlockName(program, longlongUniformBlockIndex, DE_LENGTH_OF_ARRAY(buffer), &written, buffer);
1873			checkIntEquals(m_testCtx, written, (GLint)std::string("longlongUniformBlockName").length());
1874
1875			written = 0;
1876			glGetActiveUniformBlockName(program, shortUniformBlockIndex, DE_LENGTH_OF_ARRAY(buffer), &written, buffer);
1877			checkIntEquals(m_testCtx, written, (GLint)std::string("shortUniformBlockName").length());
1878
1879			// and one with too small buffer
1880			written = 0;
1881			glGetActiveUniformBlockName(program, longlongUniformBlockIndex, 1, &written, buffer);
1882			checkIntEquals(m_testCtx, written, 0);
1883		}
1884
1885		expectError(GL_NO_ERROR);
1886		glDeleteShader(shaderVert);
1887		glDeleteShader(shaderFrag);
1888		glDeleteProgram(program);
1889		expectError(GL_NO_ERROR);
1890	}
1891};
1892
1893class ProgramBinaryCase : public ApiCase
1894{
1895public:
1896	ProgramBinaryCase (Context& context, const char* name, const char* description)
1897		: ApiCase(context, name, description)
1898	{
1899	}
1900
1901	void test (void)
1902	{
1903		using tcu::TestLog;
1904
1905		GLuint shaderVert = glCreateShader(GL_VERTEX_SHADER);
1906		GLuint shaderFrag = glCreateShader(GL_FRAGMENT_SHADER);
1907
1908		glShaderSource(shaderVert, 1, &commonTestVertSource, DE_NULL);
1909		glShaderSource(shaderFrag, 1, &commonTestFragSource, DE_NULL);
1910
1911		glCompileShader(shaderVert);
1912		glCompileShader(shaderFrag);
1913		expectError(GL_NO_ERROR);
1914
1915		GLuint program = glCreateProgram();
1916		glAttachShader(program, shaderVert);
1917		glAttachShader(program, shaderFrag);
1918		glLinkProgram(program);
1919		expectError(GL_NO_ERROR);
1920
1921		// test PROGRAM_BINARY_RETRIEVABLE_HINT
1922		verifyProgramParam(m_testCtx, *this, program, GL_PROGRAM_BINARY_RETRIEVABLE_HINT, GL_FALSE);
1923
1924		glProgramParameteri(program, GL_PROGRAM_BINARY_RETRIEVABLE_HINT, GL_TRUE);
1925		expectError(GL_NO_ERROR);
1926
1927		glLinkProgram(program);
1928		expectError(GL_NO_ERROR);
1929
1930		verifyProgramParam(m_testCtx, *this, program, GL_PROGRAM_BINARY_RETRIEVABLE_HINT, GL_TRUE);
1931
1932		// test PROGRAM_BINARY_LENGTH does something
1933
1934		StateQueryMemoryWriteGuard<GLint> programLength;
1935		glGetProgramiv(program, GL_PROGRAM_BINARY_LENGTH, &programLength);
1936		expectError(GL_NO_ERROR);
1937		programLength.verifyValidity(m_testCtx);
1938
1939		glDeleteShader(shaderVert);
1940		glDeleteShader(shaderFrag);
1941		glDeleteProgram(program);
1942		expectError(GL_NO_ERROR);
1943	}
1944};
1945
1946class TransformFeedbackCase : public ApiCase
1947{
1948public:
1949	TransformFeedbackCase (Context& context, const char* name, const char* description)
1950		: ApiCase(context, name, description)
1951	{
1952	}
1953
1954	void test (void)
1955	{
1956		using tcu::TestLog;
1957
1958		static const char* transformFeedbackTestVertSource =
1959			"#version 300 es\n"
1960			"out highp vec4 tfOutput2withLongName;\n"
1961			"void main (void)\n"
1962			"{\n"
1963			"	gl_Position = vec4(0.0);\n"
1964			"	tfOutput2withLongName = vec4(0.0);\n"
1965			"}\n";
1966		static const char* transformFeedbackTestFragSource =
1967			"#version 300 es\n"
1968			"layout(location = 0) out highp vec4 fragColor;\n"
1969			"void main (void)\n"
1970			"{\n"
1971			"	fragColor = vec4(0.0);\n"
1972			"}\n";
1973
1974		GLuint shaderVert = glCreateShader(GL_VERTEX_SHADER);
1975		GLuint shaderFrag = glCreateShader(GL_FRAGMENT_SHADER);
1976		GLuint shaderProg = glCreateProgram();
1977
1978		verifyProgramParam(m_testCtx, *this, shaderProg, GL_TRANSFORM_FEEDBACK_BUFFER_MODE, GL_INTERLEAVED_ATTRIBS);
1979
1980		glShaderSource(shaderVert, 1, &transformFeedbackTestVertSource, DE_NULL);
1981		glShaderSource(shaderFrag, 1, &transformFeedbackTestFragSource, DE_NULL);
1982
1983		glCompileShader(shaderVert);
1984		glCompileShader(shaderFrag);
1985
1986		verifyShaderParam(m_testCtx, *this, shaderVert, GL_COMPILE_STATUS, GL_TRUE);
1987		verifyShaderParam(m_testCtx, *this, shaderFrag, GL_COMPILE_STATUS, GL_TRUE);
1988
1989		glAttachShader(shaderProg, shaderVert);
1990		glAttachShader(shaderProg, shaderFrag);
1991
1992		// check TRANSFORM_FEEDBACK_BUFFER_MODE
1993
1994		const char* transform_feedback_outputs[] = {"gl_Position", "tfOutput2withLongName"};
1995		const char* longest_output = transform_feedback_outputs[1];
1996		const GLenum bufferModes[] = {GL_SEPARATE_ATTRIBS, GL_INTERLEAVED_ATTRIBS};
1997
1998		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(bufferModes); ++ndx)
1999		{
2000			glTransformFeedbackVaryings(shaderProg, DE_LENGTH_OF_ARRAY(transform_feedback_outputs), transform_feedback_outputs, bufferModes[ndx]);
2001			glLinkProgram(shaderProg);
2002			expectError(GL_NO_ERROR);
2003
2004			verifyProgramParam(m_testCtx, *this, shaderProg, GL_LINK_STATUS, GL_TRUE);
2005			verifyProgramParam(m_testCtx, *this, shaderProg, GL_TRANSFORM_FEEDBACK_BUFFER_MODE, bufferModes[ndx]);
2006		}
2007
2008		// TRANSFORM_FEEDBACK_VARYINGS
2009		verifyProgramParam(m_testCtx, *this, shaderProg, GL_TRANSFORM_FEEDBACK_VARYINGS, 2);
2010
2011		// TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH
2012		{
2013			StateQueryMemoryWriteGuard<GLint> maxOutputLen;
2014			glGetProgramiv(shaderProg, GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH, &maxOutputLen);
2015
2016			maxOutputLen.verifyValidity(m_testCtx);
2017
2018			const GLint referenceLength = (GLint)std::string(longest_output).length() + 1;
2019			checkIntEquals(m_testCtx, maxOutputLen, referenceLength);
2020		}
2021
2022		// check varyings
2023		{
2024			StateQueryMemoryWriteGuard<GLint> varyings;
2025			glGetProgramiv(shaderProg, GL_TRANSFORM_FEEDBACK_VARYINGS, &varyings);
2026
2027			if (!varyings.isUndefined())
2028				for (int index = 0; index < varyings; ++index)
2029				{
2030					char buffer[2048] = {'x'};
2031
2032					GLint written = 0;
2033					GLint size = 0;
2034					GLenum type = 0;
2035					glGetTransformFeedbackVarying(shaderProg, index, DE_LENGTH_OF_ARRAY(buffer), &written, &size, &type, buffer);
2036
2037					if (written < DE_LENGTH_OF_ARRAY(buffer) && buffer[written] != '\0')
2038					{
2039						m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected null terminator" << TestLog::EndMessage;
2040						if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
2041							m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid string terminator");
2042					}
2043
2044					// check with too small buffer
2045					written = 0;
2046					glGetTransformFeedbackVarying(shaderProg, index, 1, &written, &size, &type, buffer);
2047					if (written != 0)
2048					{
2049						m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected 0; got " << written << TestLog::EndMessage;
2050						if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
2051							m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid write length");
2052					}
2053				}
2054		}
2055
2056
2057		glDeleteShader(shaderVert);
2058		glDeleteShader(shaderFrag);
2059		glDeleteProgram(shaderProg);
2060		expectError(GL_NO_ERROR);
2061	}
2062};
2063
2064class ActiveAttributesCase : public ApiCase
2065{
2066public:
2067	ActiveAttributesCase (Context& context, const char* name, const char* description)
2068		: ApiCase(context, name, description)
2069	{
2070	}
2071
2072	void test (void)
2073	{
2074		using tcu::TestLog;
2075
2076		static const char* testVertSource =
2077			"#version 300 es\n"
2078			"in highp vec2 longInputAttributeName;\n"
2079			"in highp vec2 shortName;\n"
2080			"void main (void)\n"
2081			"{\n"
2082			"	gl_Position = longInputAttributeName.yxxy + shortName.xyxy;\n"
2083			"}\n\0";
2084		static const char* testFragSource =
2085			"#version 300 es\n"
2086			"layout(location = 0) out mediump vec4 fragColor;"
2087			"void main (void)\n"
2088			"{\n"
2089			"	fragColor = vec4(0.0);\n"
2090			"}\n\0";
2091
2092		GLuint shaderVert = glCreateShader(GL_VERTEX_SHADER);
2093		GLuint shaderFrag = glCreateShader(GL_FRAGMENT_SHADER);
2094
2095		glShaderSource(shaderVert, 1, &testVertSource, DE_NULL);
2096		glShaderSource(shaderFrag, 1, &testFragSource, DE_NULL);
2097
2098		glCompileShader(shaderVert);
2099		glCompileShader(shaderFrag);
2100		expectError(GL_NO_ERROR);
2101
2102		GLuint program = glCreateProgram();
2103		glAttachShader(program, shaderVert);
2104		glAttachShader(program, shaderFrag);
2105		glLinkProgram(program);
2106		expectError(GL_NO_ERROR);
2107
2108		verifyProgramParam(m_testCtx, *this, program, GL_ACTIVE_ATTRIBUTES, 2);
2109		verifyProgramParam(m_testCtx, *this, program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, (GLint)std::string("longInputAttributeName").length() + 1); // does include null-terminator
2110
2111		// check names
2112		for (int attributeNdx = 0; attributeNdx < 2; ++attributeNdx)
2113		{
2114			char buffer[2048] = {'x'};
2115
2116			GLint written = 0;
2117			GLint size = 0;
2118			GLenum type = 0;
2119			glGetActiveAttrib(program, attributeNdx, DE_LENGTH_OF_ARRAY(buffer), &written, &size, &type, buffer);
2120			expectError(GL_NO_ERROR);
2121
2122			if (deStringBeginsWith(buffer, "longInputAttributeName"))
2123			{
2124				checkIntEquals(m_testCtx, written, (GLint)std::string("longInputAttributeName").length()); // does NOT include null-terminator
2125			}
2126			else if (deStringBeginsWith(buffer, "shortName"))
2127			{
2128				checkIntEquals(m_testCtx, written, (GLint)std::string("shortName").length()); // does NOT include null-terminator
2129			}
2130			else
2131			{
2132				m_testCtx.getLog() << TestLog::Message << "// ERROR: Got unexpected attribute name." << TestLog::EndMessage;
2133				if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
2134					m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got unexpected name");
2135			}
2136		}
2137
2138		// and with too short buffer
2139		{
2140			char buffer[2048] = {'x'};
2141
2142			GLint written = 0;
2143			GLint size = 0;
2144			GLenum type = 0;
2145
2146			glGetActiveAttrib(program, 0, 1, &written, &size, &type, buffer);
2147			expectError(GL_NO_ERROR);
2148			checkIntEquals(m_testCtx, written, 0);
2149		}
2150
2151		glDeleteShader(shaderVert);
2152		glDeleteShader(shaderFrag);
2153		glDeleteProgram(program);
2154		expectError(GL_NO_ERROR);
2155	}
2156};
2157
2158struct PointerData
2159{
2160	GLint		size;
2161	GLenum		type;
2162	GLint		stride;
2163	GLboolean	normalized;
2164	const void*	pointer;
2165};
2166
2167class VertexAttributeSizeCase : public ApiCase
2168{
2169public:
2170	VertexAttributeSizeCase (Context& context, const char* name, const char* description)
2171		: ApiCase(context, name, description)
2172	{
2173	}
2174
2175	void test (void)
2176	{
2177		GLfloat vertexData[4] = {0.0f}; // never accessed
2178
2179		const PointerData pointers[] =
2180		{
2181			// size test
2182			{ 4, GL_FLOAT,		0,	GL_FALSE, vertexData },
2183			{ 3, GL_FLOAT,		0,	GL_FALSE, vertexData },
2184			{ 2, GL_FLOAT,		0,	GL_FALSE, vertexData },
2185			{ 1, GL_FLOAT,		0,	GL_FALSE, vertexData },
2186			{ 4, GL_INT,		0,	GL_FALSE, vertexData },
2187			{ 3, GL_INT,		0,	GL_FALSE, vertexData },
2188			{ 2, GL_INT,		0,	GL_FALSE, vertexData },
2189			{ 1, GL_INT,		0,	GL_FALSE, vertexData },
2190		};
2191
2192		// Test with default VAO
2193		{
2194			const tcu::ScopedLogSection section(m_log, "DefaultVAO", "Test with default VAO");
2195
2196			for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(pointers); ++ndx)
2197			{
2198				glVertexAttribPointer(0, pointers[ndx].size, pointers[ndx].type, pointers[ndx].normalized, pointers[ndx].stride, pointers[ndx].pointer);
2199				expectError(GL_NO_ERROR);
2200
2201				verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_SIZE, pointers[ndx].size);
2202			}
2203		}
2204
2205		// Test with multiple VAOs
2206		{
2207			const tcu::ScopedLogSection section(m_log, "WithVAO", "Test with VAO");
2208
2209			GLuint buf		= 0;
2210			GLuint vaos[2]	= {0};
2211
2212			glGenVertexArrays(2, vaos);
2213			glGenBuffers(1, &buf);
2214			glBindBuffer(GL_ARRAY_BUFFER, buf);
2215			expectError(GL_NO_ERROR);
2216
2217			// initial
2218			glBindVertexArray(vaos[0]);
2219			verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_SIZE, 4);
2220			expectError(GL_NO_ERROR);
2221
2222			// set vao 0 to some value
2223			glVertexAttribPointer(0, pointers[0].size, pointers[0].type, pointers[0].normalized, pointers[0].stride, DE_NULL);
2224			expectError(GL_NO_ERROR);
2225
2226			// set vao 1 to some other value
2227			glBindVertexArray(vaos[1]);
2228			glVertexAttribPointer(0, pointers[1].size, pointers[1].type, pointers[1].normalized, pointers[1].stride, DE_NULL);
2229			expectError(GL_NO_ERROR);
2230
2231			// verify vao 1 state
2232			verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_SIZE, pointers[1].size);
2233			expectError(GL_NO_ERROR);
2234
2235			// verify vao 0 state
2236			glBindVertexArray(vaos[0]);
2237			verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_SIZE, pointers[0].size);
2238			expectError(GL_NO_ERROR);
2239
2240			glDeleteVertexArrays(2, vaos);
2241			glDeleteBuffers(1, &buf);
2242			expectError(GL_NO_ERROR);
2243		}
2244	}
2245};
2246
2247class VertexAttributeTypeCase : public ApiCase
2248{
2249public:
2250	VertexAttributeTypeCase (Context& context, const char* name, const char* description)
2251		: ApiCase(context, name, description)
2252	{
2253	}
2254
2255	void test (void)
2256	{
2257		// Test with default VAO
2258		{
2259			const tcu::ScopedLogSection section(m_log, "DefaultVAO", "Test with default VAO");
2260
2261			const GLfloat vertexData[4] = {0.0f}; // never accessed
2262
2263			// test VertexAttribPointer
2264			{
2265				const PointerData pointers[] =
2266				{
2267					{ 1, GL_BYTE,								0,	GL_FALSE, vertexData	},
2268					{ 1, GL_SHORT,								0,	GL_FALSE, vertexData	},
2269					{ 1, GL_INT,								0,	GL_FALSE, vertexData	},
2270					{ 1, GL_FIXED,								0,	GL_FALSE, vertexData	},
2271					{ 1, GL_FLOAT,								0,	GL_FALSE, vertexData	},
2272					{ 1, GL_HALF_FLOAT,							0,	GL_FALSE, vertexData	},
2273					{ 1, GL_UNSIGNED_BYTE,						0,	GL_FALSE, vertexData	},
2274					{ 1, GL_UNSIGNED_SHORT,						0,	GL_FALSE, vertexData	},
2275					{ 1, GL_UNSIGNED_INT,						0,	GL_FALSE, vertexData	},
2276					{ 4, GL_INT_2_10_10_10_REV,					0,	GL_FALSE, vertexData	},
2277					{ 4, GL_UNSIGNED_INT_2_10_10_10_REV,		0,	GL_FALSE, vertexData	},
2278				};
2279
2280				for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(pointers); ++ndx)
2281				{
2282					glVertexAttribPointer(0, pointers[ndx].size, pointers[ndx].type, pointers[ndx].normalized, pointers[ndx].stride, pointers[ndx].pointer);
2283					expectError(GL_NO_ERROR);
2284
2285					verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_TYPE, pointers[ndx].type);
2286				}
2287			}
2288
2289			// test glVertexAttribIPointer
2290			{
2291				const PointerData pointers[] =
2292				{
2293					{ 1, GL_BYTE,								0,	GL_FALSE, vertexData	},
2294					{ 1, GL_SHORT,								0,	GL_FALSE, vertexData	},
2295					{ 1, GL_INT,								0,	GL_FALSE, vertexData	},
2296					{ 1, GL_UNSIGNED_BYTE,						0,	GL_FALSE, vertexData	},
2297					{ 1, GL_UNSIGNED_SHORT,						0,	GL_FALSE, vertexData	},
2298					{ 1, GL_UNSIGNED_INT,						0,	GL_FALSE, vertexData	},
2299				};
2300
2301				for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(pointers); ++ndx)
2302				{
2303					glVertexAttribIPointer(0, pointers[ndx].size, pointers[ndx].type, pointers[ndx].stride, pointers[ndx].pointer);
2304					expectError(GL_NO_ERROR);
2305
2306					verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_TYPE, pointers[ndx].type);
2307				}
2308			}
2309		}
2310
2311		// Test with multiple VAOs
2312		{
2313			const tcu::ScopedLogSection section(m_log, "WithVAO", "Test with VAO");
2314
2315			GLuint buf		= 0;
2316			GLuint vaos[2]	= {0};
2317
2318			glGenVertexArrays(2, vaos);
2319			glGenBuffers(1, &buf);
2320			glBindBuffer(GL_ARRAY_BUFFER, buf);
2321			expectError(GL_NO_ERROR);
2322
2323			// initial
2324			glBindVertexArray(vaos[0]);
2325			verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_TYPE, GL_FLOAT);
2326			expectError(GL_NO_ERROR);
2327
2328			// set vao 0 to some value
2329			glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, DE_NULL);
2330			expectError(GL_NO_ERROR);
2331
2332			// set vao 1 to some other value
2333			glBindVertexArray(vaos[1]);
2334			glVertexAttribPointer(0, 1, GL_SHORT, GL_FALSE, 0, DE_NULL);
2335			expectError(GL_NO_ERROR);
2336
2337			// verify vao 1 state
2338			verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_TYPE, GL_SHORT);
2339			expectError(GL_NO_ERROR);
2340
2341			// verify vao 0 state
2342			glBindVertexArray(vaos[0]);
2343			verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_TYPE, GL_FLOAT);
2344			expectError(GL_NO_ERROR);
2345
2346			glDeleteVertexArrays(2, vaos);
2347			glDeleteBuffers(1, &buf);
2348			expectError(GL_NO_ERROR);
2349		}
2350	}
2351};
2352
2353class VertexAttributeStrideCase : public ApiCase
2354{
2355public:
2356	VertexAttributeStrideCase (Context& context, const char* name, const char* description)
2357		: ApiCase(context, name, description)
2358	{
2359	}
2360
2361	void test (void)
2362	{
2363		// Test with default VAO
2364		{
2365			const tcu::ScopedLogSection section(m_log, "DefaultVAO", "Test with default VAO");
2366
2367			const GLfloat vertexData[4] = {0.0f}; // never accessed
2368
2369			struct StridePointerData
2370			{
2371				GLint		size;
2372				GLenum		type;
2373				GLint		stride;
2374				const void*	pointer;
2375			};
2376
2377			// test VertexAttribPointer
2378			{
2379				const StridePointerData pointers[] =
2380				{
2381					{ 1, GL_FLOAT,			0,	vertexData },
2382					{ 1, GL_FLOAT,			1,	vertexData },
2383					{ 1, GL_FLOAT,			4,	vertexData },
2384					{ 1, GL_HALF_FLOAT,		0,	vertexData },
2385					{ 1, GL_HALF_FLOAT,		1,	vertexData },
2386					{ 1, GL_HALF_FLOAT,		4,	vertexData },
2387					{ 1, GL_FIXED,			0,	vertexData },
2388					{ 1, GL_FIXED,			1,	vertexData },
2389					{ 1, GL_FIXED,			4,	vertexData },
2390				};
2391
2392				for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(pointers); ++ndx)
2393				{
2394					glVertexAttribPointer(0, pointers[ndx].size, pointers[ndx].type, GL_FALSE, pointers[ndx].stride, pointers[ndx].pointer);
2395					expectError(GL_NO_ERROR);
2396
2397					verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_STRIDE, pointers[ndx].stride);
2398				}
2399			}
2400
2401			// test glVertexAttribIPointer
2402			{
2403				const StridePointerData pointers[] =
2404				{
2405					{ 1, GL_INT,				0,	vertexData },
2406					{ 1, GL_INT,				1,	vertexData },
2407					{ 1, GL_INT,				4,	vertexData },
2408					{ 4, GL_UNSIGNED_BYTE,		0,	vertexData },
2409					{ 4, GL_UNSIGNED_BYTE,		1,	vertexData },
2410					{ 4, GL_UNSIGNED_BYTE,		4,	vertexData },
2411					{ 2, GL_SHORT,				0,	vertexData },
2412					{ 2, GL_SHORT,				1,	vertexData },
2413					{ 2, GL_SHORT,				4,	vertexData },
2414				};
2415
2416				for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(pointers); ++ndx)
2417				{
2418					glVertexAttribIPointer(0, pointers[ndx].size, pointers[ndx].type, pointers[ndx].stride, pointers[ndx].pointer);
2419					expectError(GL_NO_ERROR);
2420
2421					verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_STRIDE, pointers[ndx].stride);
2422				}
2423			}
2424		}
2425
2426		// Test with multiple VAOs
2427		{
2428			const tcu::ScopedLogSection section(m_log, "WithVAO", "Test with VAO");
2429
2430			GLuint buf		= 0;
2431			GLuint vaos[2]	= {0};
2432
2433			glGenVertexArrays(2, vaos);
2434			glGenBuffers(1, &buf);
2435			glBindBuffer(GL_ARRAY_BUFFER, buf);
2436			expectError(GL_NO_ERROR);
2437
2438			// initial
2439			glBindVertexArray(vaos[0]);
2440			verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_STRIDE, 0);
2441			expectError(GL_NO_ERROR);
2442
2443			// set vao 0 to some value
2444			glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 4, DE_NULL);
2445			expectError(GL_NO_ERROR);
2446
2447			// set vao 1 to some other value
2448			glBindVertexArray(vaos[1]);
2449			glVertexAttribPointer(0, 1, GL_SHORT, GL_FALSE, 8, DE_NULL);
2450			expectError(GL_NO_ERROR);
2451
2452			// verify vao 1 state
2453			verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_STRIDE, 8);
2454			expectError(GL_NO_ERROR);
2455
2456			// verify vao 0 state
2457			glBindVertexArray(vaos[0]);
2458			verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_STRIDE, 4);
2459			expectError(GL_NO_ERROR);
2460
2461			glDeleteVertexArrays(2, vaos);
2462			glDeleteBuffers(1, &buf);
2463			expectError(GL_NO_ERROR);
2464		}
2465	}
2466};
2467
2468class VertexAttributeNormalizedCase : public ApiCase
2469{
2470public:
2471	VertexAttributeNormalizedCase (Context& context, const char* name, const char* description)
2472		: ApiCase(context, name, description)
2473	{
2474	}
2475
2476	void test (void)
2477	{
2478		// Test with default VAO
2479		{
2480			const tcu::ScopedLogSection section(m_log, "DefaultVAO", "Test with default VAO");
2481
2482			const GLfloat vertexData[4] = {0.0f}; // never accessed
2483
2484			// test VertexAttribPointer
2485			{
2486				const PointerData pointers[] =
2487				{
2488					{ 1, GL_BYTE,								0,	GL_FALSE,	vertexData	},
2489					{ 1, GL_SHORT,								0,	GL_FALSE,	vertexData	},
2490					{ 1, GL_INT,								0,	GL_FALSE,	vertexData	},
2491					{ 1, GL_UNSIGNED_BYTE,						0,	GL_FALSE,	vertexData	},
2492					{ 1, GL_UNSIGNED_SHORT,						0,	GL_FALSE,	vertexData	},
2493					{ 1, GL_UNSIGNED_INT,						0,	GL_FALSE,	vertexData	},
2494					{ 4, GL_INT_2_10_10_10_REV,					0,	GL_FALSE,	vertexData	},
2495					{ 4, GL_UNSIGNED_INT_2_10_10_10_REV,		0,	GL_FALSE,	vertexData	},
2496					{ 1, GL_BYTE,								0,	GL_TRUE,	vertexData	},
2497					{ 1, GL_SHORT,								0,	GL_TRUE,	vertexData	},
2498					{ 1, GL_INT,								0,	GL_TRUE,	vertexData	},
2499					{ 1, GL_UNSIGNED_BYTE,						0,	GL_TRUE,	vertexData	},
2500					{ 1, GL_UNSIGNED_SHORT,						0,	GL_TRUE,	vertexData	},
2501					{ 1, GL_UNSIGNED_INT,						0,	GL_TRUE,	vertexData	},
2502					{ 4, GL_INT_2_10_10_10_REV,					0,	GL_TRUE,	vertexData	},
2503					{ 4, GL_UNSIGNED_INT_2_10_10_10_REV,		0,	GL_TRUE,	vertexData	},
2504				};
2505
2506				for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(pointers); ++ndx)
2507				{
2508					glVertexAttribPointer(0, pointers[ndx].size, pointers[ndx].type, pointers[ndx].normalized, pointers[ndx].stride, pointers[ndx].pointer);
2509					expectError(GL_NO_ERROR);
2510
2511					verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, pointers[ndx].normalized);
2512				}
2513			}
2514
2515			// test glVertexAttribIPointer
2516			{
2517				const PointerData pointers[] =
2518				{
2519					{ 1, GL_BYTE,				0,	GL_FALSE, vertexData	},
2520					{ 1, GL_SHORT,				0,	GL_FALSE, vertexData	},
2521					{ 1, GL_INT,				0,	GL_FALSE, vertexData	},
2522					{ 1, GL_UNSIGNED_BYTE,		0,	GL_FALSE, vertexData	},
2523					{ 1, GL_UNSIGNED_SHORT,		0,	GL_FALSE, vertexData	},
2524					{ 1, GL_UNSIGNED_INT,		0,	GL_FALSE, vertexData	},
2525				};
2526
2527				for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(pointers); ++ndx)
2528				{
2529					glVertexAttribIPointer(0, pointers[ndx].size, pointers[ndx].type, pointers[ndx].stride, pointers[ndx].pointer);
2530					expectError(GL_NO_ERROR);
2531
2532					verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, GL_FALSE);
2533				}
2534			}
2535		}
2536
2537		// Test with multiple VAOs
2538		{
2539			const tcu::ScopedLogSection section(m_log, "WithVAO", "Test with VAO");
2540
2541			GLuint buf		= 0;
2542			GLuint vaos[2]	= {0};
2543
2544			glGenVertexArrays(2, vaos);
2545			glGenBuffers(1, &buf);
2546			glBindBuffer(GL_ARRAY_BUFFER, buf);
2547			expectError(GL_NO_ERROR);
2548
2549			// initial
2550			glBindVertexArray(vaos[0]);
2551			verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, GL_FALSE);
2552			expectError(GL_NO_ERROR);
2553
2554			// set vao 0 to some value
2555			glVertexAttribPointer(0, 1, GL_INT, GL_TRUE, 0, DE_NULL);
2556			expectError(GL_NO_ERROR);
2557
2558			// set vao 1 to some other value
2559			glBindVertexArray(vaos[1]);
2560			glVertexAttribPointer(0, 1, GL_INT, GL_FALSE, 0, DE_NULL);
2561			expectError(GL_NO_ERROR);
2562
2563			// verify vao 1 state
2564			verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, GL_FALSE);
2565			expectError(GL_NO_ERROR);
2566
2567			// verify vao 0 state
2568			glBindVertexArray(vaos[0]);
2569			verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, GL_TRUE);
2570			expectError(GL_NO_ERROR);
2571
2572			glDeleteVertexArrays(2, vaos);
2573			glDeleteBuffers(1, &buf);
2574			expectError(GL_NO_ERROR);
2575		}
2576	}
2577};
2578
2579class VertexAttributeIntegerCase : public ApiCase
2580{
2581public:
2582	VertexAttributeIntegerCase (Context& context, const char* name, const char* description)
2583		: ApiCase(context, name, description)
2584	{
2585	}
2586
2587	void test (void)
2588	{
2589		// Test with default VAO
2590		{
2591			const tcu::ScopedLogSection section(m_log, "DefaultVAO", "Test with default VAO");
2592
2593			const GLfloat vertexData[4] = {0.0f}; // never accessed
2594
2595			// test VertexAttribPointer
2596			{
2597				const PointerData pointers[] =
2598				{
2599					{ 1, GL_BYTE,								0,	GL_FALSE, vertexData	},
2600					{ 1, GL_SHORT,								0,	GL_FALSE, vertexData	},
2601					{ 1, GL_INT,								0,	GL_FALSE, vertexData	},
2602					{ 1, GL_FIXED,								0,	GL_FALSE, vertexData	},
2603					{ 1, GL_FLOAT,								0,	GL_FALSE, vertexData	},
2604					{ 1, GL_HALF_FLOAT,							0,	GL_FALSE, vertexData	},
2605					{ 1, GL_UNSIGNED_BYTE,						0,	GL_FALSE, vertexData	},
2606					{ 1, GL_UNSIGNED_SHORT,						0,	GL_FALSE, vertexData	},
2607					{ 1, GL_UNSIGNED_INT,						0,	GL_FALSE, vertexData	},
2608					{ 4, GL_INT_2_10_10_10_REV,					0,	GL_FALSE, vertexData	},
2609					{ 4, GL_UNSIGNED_INT_2_10_10_10_REV,		0,	GL_FALSE, vertexData	},
2610				};
2611
2612				for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(pointers); ++ndx)
2613				{
2614					glVertexAttribPointer(0, pointers[ndx].size, pointers[ndx].type, pointers[ndx].normalized, pointers[ndx].stride, pointers[ndx].pointer);
2615					expectError(GL_NO_ERROR);
2616
2617					verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_INTEGER, GL_FALSE);
2618				}
2619			}
2620
2621			// test glVertexAttribIPointer
2622			{
2623				const PointerData pointers[] =
2624				{
2625					{ 1, GL_BYTE,								0,	GL_FALSE, vertexData	},
2626					{ 1, GL_SHORT,								0,	GL_FALSE, vertexData	},
2627					{ 1, GL_INT,								0,	GL_FALSE, vertexData	},
2628					{ 1, GL_UNSIGNED_BYTE,						0,	GL_FALSE, vertexData	},
2629					{ 1, GL_UNSIGNED_SHORT,						0,	GL_FALSE, vertexData	},
2630					{ 1, GL_UNSIGNED_INT,						0,	GL_FALSE, vertexData	},
2631				};
2632
2633				for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(pointers); ++ndx)
2634				{
2635					glVertexAttribIPointer(0, pointers[ndx].size, pointers[ndx].type, pointers[ndx].stride, pointers[ndx].pointer);
2636					expectError(GL_NO_ERROR);
2637
2638					verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_INTEGER, GL_TRUE);
2639				}
2640			}
2641		}
2642
2643		// Test with multiple VAOs
2644		{
2645			const tcu::ScopedLogSection section(m_log, "WithVAO", "Test with VAO");
2646
2647			GLuint buf		= 0;
2648			GLuint vaos[2]	= {0};
2649
2650			glGenVertexArrays(2, vaos);
2651			glGenBuffers(1, &buf);
2652			glBindBuffer(GL_ARRAY_BUFFER, buf);
2653			expectError(GL_NO_ERROR);
2654
2655			// initial
2656			glBindVertexArray(vaos[0]);
2657			verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_INTEGER, GL_FALSE);
2658			expectError(GL_NO_ERROR);
2659
2660			// set vao 0 to some value
2661			glVertexAttribIPointer(0, 1, GL_INT, 0, DE_NULL);
2662			expectError(GL_NO_ERROR);
2663
2664			// set vao 1 to some other value
2665			glBindVertexArray(vaos[1]);
2666			glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, DE_NULL);
2667			expectError(GL_NO_ERROR);
2668
2669			// verify vao 1 state
2670			verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_INTEGER, GL_FALSE);
2671			expectError(GL_NO_ERROR);
2672
2673			// verify vao 0 state
2674			glBindVertexArray(vaos[0]);
2675			verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_INTEGER, GL_TRUE);
2676			expectError(GL_NO_ERROR);
2677
2678			glDeleteVertexArrays(2, vaos);
2679			glDeleteBuffers(1, &buf);
2680			expectError(GL_NO_ERROR);
2681		}
2682	}
2683};
2684
2685class VertexAttributeEnabledCase : public ApiCase
2686{
2687public:
2688	VertexAttributeEnabledCase (Context& context, const char* name, const char* description)
2689		: ApiCase(context, name, description)
2690	{
2691	}
2692
2693	void test (void)
2694	{
2695		// VERTEX_ATTRIB_ARRAY_ENABLED
2696
2697		// Test with default VAO
2698		{
2699			const tcu::ScopedLogSection section(m_log, "DefaultVAO", "Test with default VAO");
2700
2701			verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_ENABLED, GL_FALSE);
2702			glEnableVertexAttribArray(0);
2703			verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_ENABLED, GL_TRUE);
2704			glDisableVertexAttribArray(0);
2705			verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_ENABLED, GL_FALSE);
2706		}
2707
2708		// Test with multiple VAOs
2709		{
2710			const tcu::ScopedLogSection section(m_log, "WithVAO", "Test with VAO");
2711
2712			GLuint vaos[2] = {0};
2713
2714			glGenVertexArrays(2, vaos);
2715			expectError(GL_NO_ERROR);
2716
2717			// set vao 0 to some value
2718			glBindVertexArray(vaos[0]);
2719			glEnableVertexAttribArray(0);
2720			expectError(GL_NO_ERROR);
2721
2722			// set vao 1 to some other value
2723			glBindVertexArray(vaos[1]);
2724			glDisableVertexAttribArray(0);
2725			expectError(GL_NO_ERROR);
2726
2727			// verify vao 1 state
2728			verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_ENABLED, GL_FALSE);
2729			expectError(GL_NO_ERROR);
2730
2731			// verify vao 0 state
2732			glBindVertexArray(vaos[0]);
2733			verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_ENABLED, GL_TRUE);
2734			expectError(GL_NO_ERROR);
2735
2736			glDeleteVertexArrays(2, vaos);
2737			expectError(GL_NO_ERROR);
2738		}
2739	}
2740};
2741
2742class VertexAttributeDivisorCase : public ApiCase
2743{
2744public:
2745	VertexAttributeDivisorCase (Context& context, const char* name, const char* description)
2746		: ApiCase(context, name, description)
2747	{
2748	}
2749
2750	void test (void)
2751	{
2752		// Test with default VAO
2753		{
2754			const tcu::ScopedLogSection section(m_log, "DefaultVAO", "Test with default VAO");
2755
2756			verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_DIVISOR,	0);
2757			glVertexAttribDivisor(0, 1);
2758			verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_DIVISOR,	1);
2759			glVertexAttribDivisor(0, 5);
2760			verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_DIVISOR,	5);
2761		}
2762
2763		// Test with multiple VAOs
2764		{
2765			const tcu::ScopedLogSection section(m_log, "WithVAO", "Test with VAO");
2766
2767			GLuint vaos[2] = {0};
2768
2769			glGenVertexArrays(2, vaos);
2770			expectError(GL_NO_ERROR);
2771
2772			// set vao 0 to some value
2773			glBindVertexArray(vaos[0]);
2774			glVertexAttribDivisor(0, 1);
2775			expectError(GL_NO_ERROR);
2776
2777			// set vao 1 to some other value
2778			glBindVertexArray(vaos[1]);
2779			glVertexAttribDivisor(0, 5);
2780			expectError(GL_NO_ERROR);
2781
2782			// verify vao 1 state
2783			verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_DIVISOR, 5);
2784			expectError(GL_NO_ERROR);
2785
2786			// verify vao 0 state
2787			glBindVertexArray(vaos[0]);
2788			verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_DIVISOR, 1);
2789			expectError(GL_NO_ERROR);
2790
2791			glDeleteVertexArrays(2, vaos);
2792			expectError(GL_NO_ERROR);
2793		}
2794	}
2795};
2796
2797class VertexAttributeBufferBindingCase : public ApiCase
2798{
2799public:
2800	VertexAttributeBufferBindingCase (Context& context, const char* name, const char* description)
2801		: ApiCase(context, name, description)
2802	{
2803	}
2804
2805	void test (void)
2806	{
2807		// Test with default VAO
2808		{
2809			const tcu::ScopedLogSection section(m_log, "DefaultVAO", "Test with default VAO");
2810
2811			// initial
2812			verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, 0);
2813
2814			GLuint bufferID;
2815			glGenBuffers(1, &bufferID);
2816			glBindBuffer(GL_ARRAY_BUFFER, bufferID);
2817			expectError(GL_NO_ERROR);
2818
2819			glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, DE_NULL);
2820			expectError(GL_NO_ERROR);
2821
2822			verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, bufferID);
2823
2824			glDeleteBuffers(1, &bufferID);
2825			expectError(GL_NO_ERROR);
2826		}
2827
2828		// Test with multiple VAOs
2829		{
2830			const tcu::ScopedLogSection section(m_log, "WithVAO", "Test with VAO");
2831
2832			GLuint vaos[2] = {0};
2833			GLuint bufs[2] = {0};
2834
2835			glGenBuffers(2, bufs);
2836			expectError(GL_NO_ERROR);
2837
2838			glGenVertexArrays(2, vaos);
2839			expectError(GL_NO_ERROR);
2840
2841			// set vao 0 to some value
2842			glBindVertexArray(vaos[0]);
2843			glBindBuffer(GL_ARRAY_BUFFER, bufs[0]);
2844			glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, DE_NULL);
2845			expectError(GL_NO_ERROR);
2846
2847			// set vao 1 to some other value
2848			glBindVertexArray(vaos[1]);
2849			glBindBuffer(GL_ARRAY_BUFFER, bufs[1]);
2850			glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, DE_NULL);
2851			expectError(GL_NO_ERROR);
2852
2853			// verify vao 1 state
2854			verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, bufs[1]);
2855			expectError(GL_NO_ERROR);
2856
2857			// verify vao 0 state
2858			glBindVertexArray(vaos[0]);
2859			verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, bufs[0]);
2860			expectError(GL_NO_ERROR);
2861
2862			glDeleteVertexArrays(2, vaos);
2863			glDeleteBuffers(2, bufs);
2864			expectError(GL_NO_ERROR);
2865		}
2866	}
2867};
2868
2869class VertexAttributePointerCase : public ApiCase
2870{
2871public:
2872	VertexAttributePointerCase (Context& context, const char* name, const char* description)
2873		: ApiCase(context, name, description)
2874	{
2875	}
2876
2877	void test (void)
2878	{
2879		// Test with default VAO
2880		{
2881			const tcu::ScopedLogSection section(m_log, "DefaultVAO", "Test with default VAO");
2882
2883			StateQueryMemoryWriteGuard<GLvoid*> initialState;
2884			glGetVertexAttribPointerv(0, GL_VERTEX_ATTRIB_ARRAY_POINTER, &initialState);
2885			initialState.verifyValidity(m_testCtx);
2886			checkPointerEquals(m_testCtx, initialState, 0);
2887
2888			const GLfloat vertexData[4] = {0.0f}; // never accessed
2889			const PointerData pointers[] =
2890			{
2891				{ 1, GL_BYTE,				0,	GL_FALSE, &vertexData[2] },
2892				{ 1, GL_SHORT,				0,	GL_FALSE, &vertexData[1] },
2893				{ 1, GL_INT,				0,	GL_FALSE, &vertexData[2] },
2894				{ 1, GL_FIXED,				0,	GL_FALSE, &vertexData[2] },
2895				{ 1, GL_FIXED,				0,	GL_FALSE, &vertexData[1] },
2896				{ 1, GL_FLOAT,				0,	GL_FALSE, &vertexData[0] },
2897				{ 1, GL_FLOAT,				0,	GL_FALSE, &vertexData[3] },
2898				{ 1, GL_FLOAT,				0,	GL_FALSE, &vertexData[2] },
2899				{ 1, GL_HALF_FLOAT,			0,	GL_FALSE, &vertexData[0] },
2900				{ 4, GL_HALF_FLOAT,			0,	GL_FALSE, &vertexData[1] },
2901				{ 4, GL_HALF_FLOAT,			0,	GL_FALSE, &vertexData[2] },
2902			};
2903
2904			for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(pointers); ++ndx)
2905			{
2906				glVertexAttribPointer(0, pointers[ndx].size, pointers[ndx].type, pointers[ndx].normalized, pointers[ndx].stride, pointers[ndx].pointer);
2907				expectError(GL_NO_ERROR);
2908
2909				StateQueryMemoryWriteGuard<GLvoid*> state;
2910				glGetVertexAttribPointerv(0, GL_VERTEX_ATTRIB_ARRAY_POINTER, &state);
2911				state.verifyValidity(m_testCtx);
2912				checkPointerEquals(m_testCtx, state, pointers[ndx].pointer);
2913			}
2914		}
2915
2916		// Test with multiple VAOs
2917		{
2918			const tcu::ScopedLogSection section(m_log, "WithVAO", "Test with VAO");
2919
2920			GLuint vaos[2] = {0};
2921			GLuint bufs[2] = {0};
2922
2923			glGenBuffers(2, bufs);
2924			expectError(GL_NO_ERROR);
2925
2926			glGenVertexArrays(2, vaos);
2927			expectError(GL_NO_ERROR);
2928
2929			// set vao 0 to some value
2930			glBindVertexArray(vaos[0]);
2931			glBindBuffer(GL_ARRAY_BUFFER, bufs[0]);
2932			glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, ((deUint8*)DE_NULL) + 8);
2933			expectError(GL_NO_ERROR);
2934
2935			// set vao 1 to some other value
2936			glBindVertexArray(vaos[1]);
2937			glBindBuffer(GL_ARRAY_BUFFER, bufs[1]);
2938			glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, ((deUint8*)DE_NULL) + 4);
2939			expectError(GL_NO_ERROR);
2940
2941			// verify vao 1 state
2942			{
2943				StateQueryMemoryWriteGuard<GLvoid*> state;
2944				glGetVertexAttribPointerv(0, GL_VERTEX_ATTRIB_ARRAY_POINTER, &state);
2945				state.verifyValidity(m_testCtx);
2946				checkPointerEquals(m_testCtx, state, ((deUint8*)DE_NULL) + 4);
2947			}
2948			expectError(GL_NO_ERROR);
2949
2950			// verify vao 0 state
2951			glBindVertexArray(vaos[0]);
2952			{
2953				StateQueryMemoryWriteGuard<GLvoid*> state;
2954				glGetVertexAttribPointerv(0, GL_VERTEX_ATTRIB_ARRAY_POINTER, &state);
2955				state.verifyValidity(m_testCtx);
2956				checkPointerEquals(m_testCtx, state, ((deUint8*)DE_NULL) + 8);
2957			}
2958			expectError(GL_NO_ERROR);
2959
2960			glDeleteVertexArrays(2, vaos);
2961			glDeleteBuffers(2, bufs);
2962			expectError(GL_NO_ERROR);
2963		}
2964	}
2965};
2966
2967class UniformValueFloatCase : public ApiCase
2968{
2969public:
2970	UniformValueFloatCase (Context& context, const char* name, const char* description)
2971		: ApiCase(context, name, description)
2972	{
2973	}
2974
2975	void test (void)
2976	{
2977		static const char* testVertSource =
2978			"#version 300 es\n"
2979			"uniform highp float floatUniform;\n"
2980			"uniform highp vec2 float2Uniform;\n"
2981			"uniform highp vec3 float3Uniform;\n"
2982			"uniform highp vec4 float4Uniform;\n"
2983			"void main (void)\n"
2984			"{\n"
2985			"	gl_Position = vec4(floatUniform + float2Uniform.x + float3Uniform.x + float4Uniform.x);\n"
2986			"}\n";
2987		static const char* testFragSource =
2988			"#version 300 es\n"
2989			"layout(location = 0) out mediump vec4 fragColor;"
2990			"void main (void)\n"
2991			"{\n"
2992			"	fragColor = vec4(0.0);\n"
2993			"}\n";
2994
2995		GLuint shaderVert = glCreateShader(GL_VERTEX_SHADER);
2996		GLuint shaderFrag = glCreateShader(GL_FRAGMENT_SHADER);
2997
2998		glShaderSource(shaderVert, 1, &testVertSource, DE_NULL);
2999		glShaderSource(shaderFrag, 1, &testFragSource, DE_NULL);
3000
3001		glCompileShader(shaderVert);
3002		glCompileShader(shaderFrag);
3003		expectError(GL_NO_ERROR);
3004
3005		GLuint program = glCreateProgram();
3006		glAttachShader(program, shaderVert);
3007		glAttachShader(program, shaderFrag);
3008		glLinkProgram(program);
3009		glUseProgram(program);
3010		expectError(GL_NO_ERROR);
3011
3012		GLint location;
3013
3014		location = glGetUniformLocation(program,"floatUniform");
3015		glUniform1f(location, 1.0f);
3016		verifyUniformValue1f(m_testCtx, *this, program, location, 1.0f);
3017
3018		location = glGetUniformLocation(program,"float2Uniform");
3019		glUniform2f(location, 1.0f, 2.0f);
3020		verifyUniformValue2f(m_testCtx, *this, program, location, 1.0f, 2.0f);
3021
3022		location = glGetUniformLocation(program,"float3Uniform");
3023		glUniform3f(location, 1.0f, 2.0f, 3.0f);
3024		verifyUniformValue3f(m_testCtx, *this, program, location, 1.0f, 2.0f, 3.0f);
3025
3026		location = glGetUniformLocation(program,"float4Uniform");
3027		glUniform4f(location, 1.0f, 2.0f, 3.0f, 4.0f);
3028		verifyUniformValue4f(m_testCtx, *this, program, location, 1.0f, 2.0f, 3.0f, 4.0f);
3029
3030		glUseProgram(0);
3031		glDeleteShader(shaderVert);
3032		glDeleteShader(shaderFrag);
3033		glDeleteProgram(program);
3034		expectError(GL_NO_ERROR);
3035	}
3036};
3037
3038class UniformValueIntCase : public ApiCase
3039{
3040public:
3041	UniformValueIntCase (Context& context, const char* name, const char* description)
3042		: ApiCase(context, name, description)
3043	{
3044	}
3045
3046	void test (void)
3047	{
3048		static const char* testVertSource =
3049			"#version 300 es\n"
3050			"uniform highp int intUniform;\n"
3051			"uniform highp ivec2 int2Uniform;\n"
3052			"uniform highp ivec3 int3Uniform;\n"
3053			"uniform highp ivec4 int4Uniform;\n"
3054			"void main (void)\n"
3055			"{\n"
3056			"	gl_Position = vec4(float(intUniform + int2Uniform.x + int3Uniform.x + int4Uniform.x));\n"
3057			"}\n";
3058		static const char* testFragSource =
3059			"#version 300 es\n"
3060			"layout(location = 0) out mediump vec4 fragColor;"
3061			"void main (void)\n"
3062			"{\n"
3063			"	fragColor = vec4(0.0);\n"
3064			"}\n";
3065
3066		GLuint shaderVert = glCreateShader(GL_VERTEX_SHADER);
3067		GLuint shaderFrag = glCreateShader(GL_FRAGMENT_SHADER);
3068
3069		glShaderSource(shaderVert, 1, &testVertSource, DE_NULL);
3070		glShaderSource(shaderFrag, 1, &testFragSource, DE_NULL);
3071
3072		glCompileShader(shaderVert);
3073		glCompileShader(shaderFrag);
3074		expectError(GL_NO_ERROR);
3075
3076		GLuint program = glCreateProgram();
3077		glAttachShader(program, shaderVert);
3078		glAttachShader(program, shaderFrag);
3079		glLinkProgram(program);
3080		glUseProgram(program);
3081		expectError(GL_NO_ERROR);
3082
3083		GLint location;
3084
3085		location = glGetUniformLocation(program,"intUniform");
3086		glUniform1i(location, 1);
3087		verifyUniformValue1i(m_testCtx, *this, program, location, 1);
3088
3089		location = glGetUniformLocation(program,"int2Uniform");
3090		glUniform2i(location, 1, 2);
3091		verifyUniformValue2i(m_testCtx, *this, program, location, 1, 2);
3092
3093		location = glGetUniformLocation(program,"int3Uniform");
3094		glUniform3i(location, 1, 2, 3);
3095		verifyUniformValue3i(m_testCtx, *this, program, location, 1, 2, 3);
3096
3097		location = glGetUniformLocation(program,"int4Uniform");
3098		glUniform4i(location, 1, 2, 3, 4);
3099		verifyUniformValue4i(m_testCtx, *this, program, location, 1, 2, 3, 4);
3100
3101		glUseProgram(0);
3102		glDeleteShader(shaderVert);
3103		glDeleteShader(shaderFrag);
3104		glDeleteProgram(program);
3105		expectError(GL_NO_ERROR);
3106	}
3107};
3108
3109class UniformValueUintCase : public ApiCase
3110{
3111public:
3112	UniformValueUintCase (Context& context, const char* name, const char* description)
3113		: ApiCase(context, name, description)
3114	{
3115	}
3116
3117	void test (void)
3118	{
3119		static const char* testVertSource =
3120			"#version 300 es\n"
3121			"uniform highp uint uintUniform;\n"
3122			"uniform highp uvec2 uint2Uniform;\n"
3123			"uniform highp uvec3 uint3Uniform;\n"
3124			"uniform highp uvec4 uint4Uniform;\n"
3125			"void main (void)\n"
3126			"{\n"
3127			"	gl_Position = vec4(float(uintUniform + uint2Uniform.x + uint3Uniform.x + uint4Uniform.x));\n"
3128			"}\n";
3129		static const char* testFragSource =
3130			"#version 300 es\n"
3131			"layout(location = 0) out mediump vec4 fragColor;"
3132			"void main (void)\n"
3133			"{\n"
3134			"	fragColor = vec4(0.0);\n"
3135			"}\n";
3136
3137		GLuint shaderVert = glCreateShader(GL_VERTEX_SHADER);
3138		GLuint shaderFrag = glCreateShader(GL_FRAGMENT_SHADER);
3139
3140		glShaderSource(shaderVert, 1, &testVertSource, DE_NULL);
3141		glShaderSource(shaderFrag, 1, &testFragSource, DE_NULL);
3142
3143		glCompileShader(shaderVert);
3144		glCompileShader(shaderFrag);
3145		expectError(GL_NO_ERROR);
3146
3147		GLuint program = glCreateProgram();
3148		glAttachShader(program, shaderVert);
3149		glAttachShader(program, shaderFrag);
3150		glLinkProgram(program);
3151		glUseProgram(program);
3152		expectError(GL_NO_ERROR);
3153
3154		GLint location;
3155
3156		location = glGetUniformLocation(program,"uintUniform");
3157		glUniform1ui(location, 1);
3158		verifyUniformValue1ui(m_testCtx, *this, program, location, 1);
3159
3160		location = glGetUniformLocation(program,"uint2Uniform");
3161		glUniform2ui(location, 1, 2);
3162		verifyUniformValue2ui(m_testCtx, *this, program, location, 1, 2);
3163
3164		location = glGetUniformLocation(program,"uint3Uniform");
3165		glUniform3ui(location, 1, 2, 3);
3166		verifyUniformValue3ui(m_testCtx, *this, program, location, 1, 2, 3);
3167
3168		location = glGetUniformLocation(program,"uint4Uniform");
3169		glUniform4ui(location, 1, 2, 3, 4);
3170		verifyUniformValue4ui(m_testCtx, *this, program, location, 1, 2, 3, 4);
3171
3172		glUseProgram(0);
3173		glDeleteShader(shaderVert);
3174		glDeleteShader(shaderFrag);
3175		glDeleteProgram(program);
3176		expectError(GL_NO_ERROR);
3177	}
3178};
3179
3180
3181class UniformValueBooleanCase : public ApiCase
3182{
3183public:
3184	UniformValueBooleanCase (Context& context, const char* name, const char* description)
3185		: ApiCase(context, name, description)
3186	{
3187	}
3188
3189	void test (void)
3190	{
3191		static const char* testVertSource =
3192			"#version 300 es\n"
3193			"uniform bool boolUniform;\n"
3194			"uniform bvec2 bool2Uniform;\n"
3195			"uniform bvec3 bool3Uniform;\n"
3196			"uniform bvec4 bool4Uniform;\n"
3197			"void main (void)\n"
3198			"{\n"
3199			"	gl_Position = vec4(float(boolUniform) + float(bool2Uniform.x) + float(bool3Uniform.x) + float(bool4Uniform.x));\n"
3200			"}\n";
3201		static const char* testFragSource =
3202			"#version 300 es\n"
3203			"layout(location = 0) out mediump vec4 fragColor;"
3204			"void main (void)\n"
3205			"{\n"
3206			"	fragColor = vec4(0.0);\n"
3207			"}\n";
3208
3209		GLuint shaderVert = glCreateShader(GL_VERTEX_SHADER);
3210		GLuint shaderFrag = glCreateShader(GL_FRAGMENT_SHADER);
3211
3212		glShaderSource(shaderVert, 1, &testVertSource, DE_NULL);
3213		glShaderSource(shaderFrag, 1, &testFragSource, DE_NULL);
3214
3215		glCompileShader(shaderVert);
3216		glCompileShader(shaderFrag);
3217		expectError(GL_NO_ERROR);
3218
3219		GLuint program = glCreateProgram();
3220		glAttachShader(program, shaderVert);
3221		glAttachShader(program, shaderFrag);
3222		glLinkProgram(program);
3223		glUseProgram(program);
3224		expectError(GL_NO_ERROR);
3225
3226		GLint location;
3227
3228		// int conversion
3229
3230		location = glGetUniformLocation(program,"boolUniform");
3231		glUniform1i(location, 1);
3232		verifyUniformValue1i(m_testCtx, *this, program, location, 1);
3233
3234		location = glGetUniformLocation(program,"bool2Uniform");
3235		glUniform2i(location, 1, 2);
3236		verifyUniformValue2i(m_testCtx, *this, program, location, 1, 1);
3237
3238		location = glGetUniformLocation(program,"bool3Uniform");
3239		glUniform3i(location, 0, 1, 2);
3240		verifyUniformValue3i(m_testCtx, *this, program, location, 0, 1, 1);
3241
3242		location = glGetUniformLocation(program,"bool4Uniform");
3243		glUniform4i(location, 1, 0, 1, -1);
3244		verifyUniformValue4i(m_testCtx, *this, program, location, 1, 0, 1, 1);
3245
3246		// float conversion
3247
3248		location = glGetUniformLocation(program,"boolUniform");
3249		glUniform1f(location, 1.0f);
3250		verifyUniformValue1i(m_testCtx, *this, program, location, 1);
3251
3252		location = glGetUniformLocation(program,"bool2Uniform");
3253		glUniform2f(location, 1.0f, 0.1f);
3254		verifyUniformValue2i(m_testCtx, *this, program, location, 1, 1);
3255
3256		location = glGetUniformLocation(program,"bool3Uniform");
3257		glUniform3f(location, 0.0f, 0.1f, -0.1f);
3258		verifyUniformValue3i(m_testCtx, *this, program, location, 0, 1, 1);
3259
3260		location = glGetUniformLocation(program,"bool4Uniform");
3261		glUniform4f(location, 1.0f, 0.0f, 0.1f, -0.9f);
3262		verifyUniformValue4i(m_testCtx, *this, program, location, 1, 0, 1, 1);
3263
3264		glUseProgram(0);
3265		glDeleteShader(shaderVert);
3266		glDeleteShader(shaderFrag);
3267		glDeleteProgram(program);
3268		expectError(GL_NO_ERROR);
3269	}
3270};
3271
3272class UniformValueSamplerCase : public ApiCase
3273{
3274public:
3275	UniformValueSamplerCase (Context& context, const char* name, const char* description)
3276		: ApiCase(context, name, description)
3277	{
3278	}
3279
3280	void test (void)
3281	{
3282		static const char* testVertSource =
3283			"#version 300 es\n"
3284			"void main (void)\n"
3285			"{\n"
3286			"	gl_Position = vec4(0.0);\n"
3287			"}\n";
3288		static const char* testFragSource =
3289			"#version 300 es\n"
3290			"uniform highp sampler2D uniformSampler;\n"
3291			"layout(location = 0) out mediump vec4 fragColor;"
3292			"void main (void)\n"
3293			"{\n"
3294			"	fragColor = vec4(textureSize(uniformSampler, 0).x);\n"
3295			"}\n";
3296
3297		GLuint shaderVert = glCreateShader(GL_VERTEX_SHADER);
3298		GLuint shaderFrag = glCreateShader(GL_FRAGMENT_SHADER);
3299
3300		glShaderSource(shaderVert, 1, &testVertSource, DE_NULL);
3301		glShaderSource(shaderFrag, 1, &testFragSource, DE_NULL);
3302
3303		glCompileShader(shaderVert);
3304		glCompileShader(shaderFrag);
3305		expectError(GL_NO_ERROR);
3306
3307		GLuint program = glCreateProgram();
3308		glAttachShader(program, shaderVert);
3309		glAttachShader(program, shaderFrag);
3310		glLinkProgram(program);
3311		glUseProgram(program);
3312		expectError(GL_NO_ERROR);
3313
3314		GLint location;
3315
3316		location = glGetUniformLocation(program,"uniformSampler");
3317		glUniform1i(location, 1);
3318		verifyUniformValue1i(m_testCtx, *this, program, location, 1);
3319
3320		glUseProgram(0);
3321		glDeleteShader(shaderVert);
3322		glDeleteShader(shaderFrag);
3323		glDeleteProgram(program);
3324		expectError(GL_NO_ERROR);
3325	}
3326};
3327
3328class UniformValueArrayCase : public ApiCase
3329{
3330public:
3331	UniformValueArrayCase (Context& context, const char* name, const char* description)
3332		: ApiCase(context, name, description)
3333	{
3334	}
3335
3336	void test (void)
3337	{
3338		static const char* testVertSource =
3339			"#version 300 es\n"
3340			"uniform highp float arrayUniform[5];"
3341			"uniform highp vec2 array2Uniform[5];"
3342			"uniform highp vec3 array3Uniform[5];"
3343			"uniform highp vec4 array4Uniform[5];"
3344			"void main (void)\n"
3345			"{\n"
3346			"	gl_Position = \n"
3347			"		+ vec4(arrayUniform[0]		+ arrayUniform[1]		+ arrayUniform[2]		+ arrayUniform[3]		+ arrayUniform[4])\n"
3348			"		+ vec4(array2Uniform[0].x	+ array2Uniform[1].x	+ array2Uniform[2].x	+ array2Uniform[3].x	+ array2Uniform[4].x)\n"
3349			"		+ vec4(array3Uniform[0].x	+ array3Uniform[1].x	+ array3Uniform[2].x	+ array3Uniform[3].x	+ array3Uniform[4].x)\n"
3350			"		+ vec4(array4Uniform[0].x	+ array4Uniform[1].x	+ array4Uniform[2].x	+ array4Uniform[3].x	+ array4Uniform[4].x);\n"
3351			"}\n";
3352		static const char* testFragSource =
3353			"#version 300 es\n"
3354			"layout(location = 0) out mediump vec4 fragColor;"
3355			"void main (void)\n"
3356			"{\n"
3357			"	fragColor = vec4(0.0);\n"
3358			"}\n";
3359
3360		GLuint shaderVert = glCreateShader(GL_VERTEX_SHADER);
3361		GLuint shaderFrag = glCreateShader(GL_FRAGMENT_SHADER);
3362
3363		glShaderSource(shaderVert, 1, &testVertSource, DE_NULL);
3364		glShaderSource(shaderFrag, 1, &testFragSource, DE_NULL);
3365
3366		glCompileShader(shaderVert);
3367		glCompileShader(shaderFrag);
3368		expectError(GL_NO_ERROR);
3369
3370		GLuint program = glCreateProgram();
3371		glAttachShader(program, shaderVert);
3372		glAttachShader(program, shaderFrag);
3373		glLinkProgram(program);
3374		glUseProgram(program);
3375		expectError(GL_NO_ERROR);
3376
3377		GLint location;
3378
3379		float uniformValue[5 * 4] =
3380		{
3381			-1.0f,	0.1f,	4.0f,	800.0f,
3382			13.0f,	55.0f,	12.0f,	91.0f,
3383			-55.1f,	1.1f,	98.0f,	19.0f,
3384			41.0f,	65.0f,	4.0f,	12.2f,
3385			95.0f,	77.0f,	32.0f,	48.0f
3386		};
3387
3388		location = glGetUniformLocation(program,"arrayUniform");
3389		glUniform1fv(location, 5, uniformValue);
3390		expectError(GL_NO_ERROR);
3391
3392		verifyUniformValue1f(m_testCtx, *this, program, glGetUniformLocation(program,"arrayUniform[0]"), uniformValue[0]);
3393		verifyUniformValue1f(m_testCtx, *this, program, glGetUniformLocation(program,"arrayUniform[1]"), uniformValue[1]);
3394		verifyUniformValue1f(m_testCtx, *this, program, glGetUniformLocation(program,"arrayUniform[2]"), uniformValue[2]);
3395		verifyUniformValue1f(m_testCtx, *this, program, glGetUniformLocation(program,"arrayUniform[3]"), uniformValue[3]);
3396		verifyUniformValue1f(m_testCtx, *this, program, glGetUniformLocation(program,"arrayUniform[4]"), uniformValue[4]);
3397		expectError(GL_NO_ERROR);
3398
3399		location = glGetUniformLocation(program,"array2Uniform");
3400		glUniform2fv(location, 5, uniformValue);
3401		expectError(GL_NO_ERROR);
3402
3403		verifyUniformValue2f(m_testCtx, *this, program, glGetUniformLocation(program,"array2Uniform[0]"), uniformValue[2 * 0], uniformValue[(2 * 0) + 1]);
3404		verifyUniformValue2f(m_testCtx, *this, program, glGetUniformLocation(program,"array2Uniform[1]"), uniformValue[2 * 1], uniformValue[(2 * 1) + 1]);
3405		verifyUniformValue2f(m_testCtx, *this, program, glGetUniformLocation(program,"array2Uniform[2]"), uniformValue[2 * 2], uniformValue[(2 * 2) + 1]);
3406		verifyUniformValue2f(m_testCtx, *this, program, glGetUniformLocation(program,"array2Uniform[3]"), uniformValue[2 * 3], uniformValue[(2 * 3) + 1]);
3407		verifyUniformValue2f(m_testCtx, *this, program, glGetUniformLocation(program,"array2Uniform[4]"), uniformValue[2 * 4], uniformValue[(2 * 4) + 1]);
3408		expectError(GL_NO_ERROR);
3409
3410		location = glGetUniformLocation(program,"array3Uniform");
3411		glUniform3fv(location, 5, uniformValue);
3412		expectError(GL_NO_ERROR);
3413
3414		verifyUniformValue3f(m_testCtx, *this, program, glGetUniformLocation(program,"array3Uniform[0]"), uniformValue[3 * 0], uniformValue[(3 * 0) + 1], uniformValue[(3 * 0) + 2]);
3415		verifyUniformValue3f(m_testCtx, *this, program, glGetUniformLocation(program,"array3Uniform[1]"), uniformValue[3 * 1], uniformValue[(3 * 1) + 1], uniformValue[(3 * 1) + 2]);
3416		verifyUniformValue3f(m_testCtx, *this, program, glGetUniformLocation(program,"array3Uniform[2]"), uniformValue[3 * 2], uniformValue[(3 * 2) + 1], uniformValue[(3 * 2) + 2]);
3417		verifyUniformValue3f(m_testCtx, *this, program, glGetUniformLocation(program,"array3Uniform[3]"), uniformValue[3 * 3], uniformValue[(3 * 3) + 1], uniformValue[(3 * 3) + 2]);
3418		verifyUniformValue3f(m_testCtx, *this, program, glGetUniformLocation(program,"array3Uniform[4]"), uniformValue[3 * 4], uniformValue[(3 * 4) + 1], uniformValue[(3 * 4) + 2]);
3419		expectError(GL_NO_ERROR);
3420
3421		location = glGetUniformLocation(program,"array4Uniform");
3422		glUniform4fv(location, 5, uniformValue);
3423		expectError(GL_NO_ERROR);
3424
3425		verifyUniformValue4f(m_testCtx, *this, program, glGetUniformLocation(program,"array4Uniform[0]"), uniformValue[4 * 0], uniformValue[(4 * 0) + 1], uniformValue[(4 * 0) + 2], uniformValue[(4 * 0) + 3]);
3426		verifyUniformValue4f(m_testCtx, *this, program, glGetUniformLocation(program,"array4Uniform[1]"), uniformValue[4 * 1], uniformValue[(4 * 1) + 1], uniformValue[(4 * 1) + 2], uniformValue[(4 * 1) + 3]);
3427		verifyUniformValue4f(m_testCtx, *this, program, glGetUniformLocation(program,"array4Uniform[2]"), uniformValue[4 * 2], uniformValue[(4 * 2) + 1], uniformValue[(4 * 2) + 2], uniformValue[(4 * 2) + 3]);
3428		verifyUniformValue4f(m_testCtx, *this, program, glGetUniformLocation(program,"array4Uniform[3]"), uniformValue[4 * 3], uniformValue[(4 * 3) + 1], uniformValue[(4 * 3) + 2], uniformValue[(4 * 3) + 3]);
3429		verifyUniformValue4f(m_testCtx, *this, program, glGetUniformLocation(program,"array4Uniform[4]"), uniformValue[4 * 4], uniformValue[(4 * 4) + 1], uniformValue[(4 * 4) + 2], uniformValue[(4 * 4) + 3]);
3430		expectError(GL_NO_ERROR);
3431
3432		glUseProgram(0);
3433		glDeleteShader(shaderVert);
3434		glDeleteShader(shaderFrag);
3435		glDeleteProgram(program);
3436		expectError(GL_NO_ERROR);
3437	}
3438};
3439
3440class UniformValueMatrixCase : public ApiCase
3441{
3442public:
3443	UniformValueMatrixCase (Context& context, const char* name, const char* description)
3444		: ApiCase(context, name, description)
3445	{
3446	}
3447
3448	void test (void)
3449	{
3450		static const char* testVertSource =
3451			"#version 300 es\n"
3452			"uniform highp mat2 mat2Uniform;"
3453			"uniform highp mat3 mat3Uniform;"
3454			"uniform highp mat4 mat4Uniform;"
3455			"void main (void)\n"
3456			"{\n"
3457			"	gl_Position = vec4(mat2Uniform[0][0] + mat3Uniform[0][0] + mat4Uniform[0][0]);\n"
3458			"}\n";
3459		static const char* testFragSource =
3460			"#version 300 es\n"
3461			"layout(location = 0) out mediump vec4 fragColor;"
3462			"void main (void)\n"
3463			"{\n"
3464			"	fragColor = vec4(0.0);\n"
3465			"}\n";
3466
3467		GLuint shaderVert = glCreateShader(GL_VERTEX_SHADER);
3468		GLuint shaderFrag = glCreateShader(GL_FRAGMENT_SHADER);
3469
3470		glShaderSource(shaderVert, 1, &testVertSource, DE_NULL);
3471		glShaderSource(shaderFrag, 1, &testFragSource, DE_NULL);
3472
3473		glCompileShader(shaderVert);
3474		glCompileShader(shaderFrag);
3475		expectError(GL_NO_ERROR);
3476
3477		GLuint program = glCreateProgram();
3478		glAttachShader(program, shaderVert);
3479		glAttachShader(program, shaderFrag);
3480		glLinkProgram(program);
3481		glUseProgram(program);
3482		expectError(GL_NO_ERROR);
3483
3484		GLint location;
3485
3486		float matrixValues[4 * 4] =
3487		{
3488			-1.0f,	0.1f,	4.0f,	800.0f,
3489			13.0f,	55.0f,	12.0f,	91.0f,
3490			-55.1f,	1.1f,	98.0f,	19.0f,
3491			41.0f,	65.0f,	4.0f,	12.2f,
3492		};
3493
3494		// the values of the matrix are returned in column major order but they can be given in either order
3495
3496		location = glGetUniformLocation(program,"mat2Uniform");
3497		glUniformMatrix2fv(location, 1, GL_FALSE, matrixValues);
3498		verifyUniformMatrixValues<2>(m_testCtx, *this, program, location, matrixValues, false);
3499		glUniformMatrix2fv(location, 1, GL_TRUE, matrixValues);
3500		verifyUniformMatrixValues<2>(m_testCtx, *this, program, location, matrixValues, true);
3501
3502		location = glGetUniformLocation(program,"mat3Uniform");
3503		glUniformMatrix3fv(location, 1, GL_FALSE, matrixValues);
3504		verifyUniformMatrixValues<3>(m_testCtx, *this, program, location, matrixValues, false);
3505		glUniformMatrix3fv(location, 1, GL_TRUE, matrixValues);
3506		verifyUniformMatrixValues<3>(m_testCtx, *this, program, location, matrixValues, true);
3507
3508		location = glGetUniformLocation(program,"mat4Uniform");
3509		glUniformMatrix4fv(location, 1, GL_FALSE, matrixValues);
3510		verifyUniformMatrixValues<4>(m_testCtx, *this, program, location, matrixValues, false);
3511		glUniformMatrix4fv(location, 1, GL_TRUE, matrixValues);
3512		verifyUniformMatrixValues<4>(m_testCtx, *this, program, location, matrixValues, true);
3513
3514		glUseProgram(0);
3515		glDeleteShader(shaderVert);
3516		glDeleteShader(shaderFrag);
3517		glDeleteProgram(program);
3518		expectError(GL_NO_ERROR);
3519	}
3520};
3521
3522class PrecisionFormatCase : public ApiCase
3523{
3524public:
3525	struct RequiredFormat
3526	{
3527		int negativeRange;
3528		int positiveRange;
3529		int precision;
3530	};
3531
3532	PrecisionFormatCase (Context& context, const char* name, const char* description, glw::GLenum shaderType, glw::GLenum precisionType)
3533		: ApiCase			(context, name, description)
3534		, m_shaderType		(shaderType)
3535		, m_precisionType	(precisionType)
3536	{
3537	}
3538
3539private:
3540	void test (void)
3541	{
3542		const RequiredFormat											expected = getRequiredFormat();
3543		bool															error = false;
3544		gls::StateQueryUtil::StateQueryMemoryWriteGuard<glw::GLboolean>	shaderCompiler;
3545		gls::StateQueryUtil::StateQueryMemoryWriteGuard<glw::GLint[2]>	range;
3546		gls::StateQueryUtil::StateQueryMemoryWriteGuard<glw::GLint>		precision;
3547
3548		// query values
3549		glGetShaderPrecisionFormat(m_shaderType, m_precisionType, range, &precision);
3550		expectError(GL_NO_ERROR);
3551
3552		if (!range.verifyValidity(m_testCtx))
3553			return;
3554		if (!precision.verifyValidity(m_testCtx))
3555			return;
3556
3557		m_log
3558			<< tcu::TestLog::Message
3559			<< "range[0] = " << range[0] << "\n"
3560			<< "range[1] = " << range[1] << "\n"
3561			<< "precision = " << precision
3562			<< tcu::TestLog::EndMessage;
3563
3564		// verify values
3565
3566		if (m_precisionType == GL_HIGH_FLOAT)
3567		{
3568			// highp float must be IEEE 754 single
3569
3570			if (range[0] != expected.negativeRange ||
3571				range[1] != expected.positiveRange ||
3572				precision != expected.precision)
3573			{
3574				m_log
3575					<< tcu::TestLog::Message
3576					<< "// ERROR: Invalid precision format, expected:\n"
3577					<< "\trange[0] = " << expected.negativeRange << "\n"
3578					<< "\trange[1] = " << expected.positiveRange << "\n"
3579					<< "\tprecision = " << expected.precision
3580					<< tcu::TestLog::EndMessage;
3581				error = true;
3582			}
3583		}
3584		else
3585		{
3586			if (range[0] < expected.negativeRange)
3587			{
3588				m_log << tcu::TestLog::Message << "// ERROR: Invalid range[0], expected greater or equal to " << expected.negativeRange << tcu::TestLog::EndMessage;
3589				error = true;
3590			}
3591
3592			if (range[1] < expected.positiveRange)
3593			{
3594				m_log << tcu::TestLog::Message << "// ERROR: Invalid range[1], expected greater or equal to " << expected.positiveRange << tcu::TestLog::EndMessage;
3595				error = true;
3596			}
3597
3598			if (precision < expected.precision)
3599			{
3600				m_log << tcu::TestLog::Message << "// ERROR: Invalid precision, expected greater or equal to " << expected.precision << tcu::TestLog::EndMessage;
3601				error = true;
3602			}
3603		}
3604
3605		if (error)
3606			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid precision/range");
3607	}
3608
3609	RequiredFormat getRequiredFormat (void) const
3610	{
3611		// Precisions for different types.
3612		const RequiredFormat requirements[] =
3613		{
3614			{   0,   0,  8 }, //!< lowp float
3615			{  13,  13, 10 }, //!< mediump float
3616			{ 127, 127, 23 }, //!< highp float
3617			{   8,   7,  0 }, //!< lowp int
3618			{  15,  14,  0 }, //!< mediump int
3619			{  31,  30,  0 }, //!< highp int
3620		};
3621		const int ndx = (int)m_precisionType - (int)GL_LOW_FLOAT;
3622
3623		DE_ASSERT(ndx >= 0);
3624		DE_ASSERT(ndx < DE_LENGTH_OF_ARRAY(requirements));
3625		return requirements[ndx];
3626	}
3627
3628	const glw::GLenum m_shaderType;
3629	const glw::GLenum m_precisionType;
3630};
3631
3632} // anonymous
3633
3634
3635ShaderStateQueryTests::ShaderStateQueryTests (Context& context)
3636	: TestCaseGroup(context, "shader", "Shader State Query tests")
3637{
3638}
3639
3640void ShaderStateQueryTests::init (void)
3641{
3642	// shader
3643	addChild(new ShaderTypeCase						(m_context, "shader_type",							"SHADER_TYPE"));
3644	addChild(new ShaderCompileStatusCase			(m_context, "shader_compile_status",				"COMPILE_STATUS"));
3645	addChild(new ShaderInfoLogCase					(m_context, "shader_info_log_length",				"INFO_LOG_LENGTH"));
3646	addChild(new ShaderSourceCase					(m_context, "shader_source_length",					"SHADER_SOURCE_LENGTH"));
3647
3648	// shader and program
3649	addChild(new DeleteStatusCase					(m_context, "delete_status",						"DELETE_STATUS"));
3650
3651	// vertex-attrib
3652	addChild(new CurrentVertexAttribInitialCase		(m_context, "current_vertex_attrib_initial",		"CURRENT_VERTEX_ATTRIB"));
3653	addChild(new CurrentVertexAttribFloatCase		(m_context, "current_vertex_attrib_float",			"CURRENT_VERTEX_ATTRIB"));
3654	addChild(new CurrentVertexAttribIntCase			(m_context, "current_vertex_attrib_int",			"CURRENT_VERTEX_ATTRIB"));
3655	addChild(new CurrentVertexAttribUintCase		(m_context, "current_vertex_attrib_uint",			"CURRENT_VERTEX_ATTRIB"));
3656	addChild(new CurrentVertexAttribConversionCase	(m_context, "current_vertex_attrib_float_to_int",	"CURRENT_VERTEX_ATTRIB"));
3657
3658	// program
3659	addChild(new ProgramInfoLogCase					(m_context, "program_info_log_length",				"INFO_LOG_LENGTH",	ProgramInfoLogCase::BUILDERROR_COMPILE));
3660	addChild(new ProgramInfoLogCase					(m_context, "program_info_log_length_link_error",	"INFO_LOG_LENGTH",	ProgramInfoLogCase::BUILDERROR_LINK));
3661	addChild(new ProgramValidateStatusCase			(m_context, "program_validate_status",				"VALIDATE_STATUS"));
3662	addChild(new ProgramAttachedShadersCase			(m_context, "program_attached_shaders",				"ATTACHED_SHADERS"));
3663
3664	addChild(new ProgramActiveUniformNameCase		(m_context, "program_active_uniform_name",			"ACTIVE_UNIFORMS and ACTIVE_UNIFORM_MAX_LENGTH"));
3665	addChild(new ProgramUniformCase					(m_context, "program_active_uniform_types",			"UNIFORM_TYPE, UNIFORM_SIZE, and UNIFORM_IS_ROW_MAJOR"));
3666	addChild(new ProgramActiveUniformBlocksCase		(m_context, "program_active_uniform_blocks",		"ACTIVE_UNIFORM_BLOCK_x"));
3667	addChild(new ProgramBinaryCase					(m_context, "program_binary",						"PROGRAM_BINARY_LENGTH and PROGRAM_BINARY_RETRIEVABLE_HINT"));
3668
3669	// transform feedback
3670	addChild(new TransformFeedbackCase				(m_context, "transform_feedback",					"TRANSFORM_FEEDBACK_BUFFER_MODE, TRANSFORM_FEEDBACK_VARYINGS, TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH"));
3671
3672	// attribute related
3673	addChild(new ActiveAttributesCase				(m_context, "active_attributes",					"ACTIVE_ATTRIBUTES and ACTIVE_ATTRIBUTE_MAX_LENGTH"));
3674	addChild(new VertexAttributeSizeCase			(m_context, "vertex_attrib_size",					"VERTEX_ATTRIB_ARRAY_SIZE"));
3675	addChild(new VertexAttributeTypeCase			(m_context, "vertex_attrib_type",					"VERTEX_ATTRIB_ARRAY_TYPE"));
3676	addChild(new VertexAttributeStrideCase			(m_context, "vertex_attrib_stride",					"VERTEX_ATTRIB_ARRAY_STRIDE"));
3677	addChild(new VertexAttributeNormalizedCase		(m_context, "vertex_attrib_normalized",				"VERTEX_ATTRIB_ARRAY_NORMALIZED"));
3678	addChild(new VertexAttributeIntegerCase			(m_context, "vertex_attrib_integer",				"VERTEX_ATTRIB_ARRAY_INTEGER"));
3679	addChild(new VertexAttributeEnabledCase			(m_context, "vertex_attrib_array_enabled",			"VERTEX_ATTRIB_ARRAY_ENABLED"));
3680	addChild(new VertexAttributeDivisorCase			(m_context, "vertex_attrib_array_divisor",			"VERTEX_ATTRIB_ARRAY_DIVISOR"));
3681	addChild(new VertexAttributeBufferBindingCase	(m_context, "vertex_attrib_array_buffer_binding",	"VERTEX_ATTRIB_ARRAY_BUFFER_BINDING"));
3682	addChild(new VertexAttributePointerCase			(m_context, "vertex_attrib_pointerv",				"GetVertexAttribPointerv"));
3683
3684	// uniform values
3685	addChild(new UniformValueFloatCase				(m_context, "uniform_value_float",					"GetUniform*"));
3686	addChild(new UniformValueIntCase				(m_context, "uniform_value_int",					"GetUniform*"));
3687	addChild(new UniformValueUintCase				(m_context, "uniform_value_uint",					"GetUniform*"));
3688	addChild(new UniformValueBooleanCase			(m_context, "uniform_value_boolean",				"GetUniform*"));
3689	addChild(new UniformValueSamplerCase			(m_context, "uniform_value_sampler",				"GetUniform*"));
3690	addChild(new UniformValueArrayCase				(m_context, "uniform_value_array",					"GetUniform*"));
3691	addChild(new UniformValueMatrixCase				(m_context, "uniform_value_matrix",					"GetUniform*"));
3692
3693	// precision format query
3694	addChild(new PrecisionFormatCase				(m_context, "precision_vertex_lowp_float",			"GetShaderPrecisionFormat",		GL_VERTEX_SHADER,	GL_LOW_FLOAT));
3695	addChild(new PrecisionFormatCase				(m_context, "precision_vertex_mediump_float",		"GetShaderPrecisionFormat",		GL_VERTEX_SHADER,	GL_MEDIUM_FLOAT));
3696	addChild(new PrecisionFormatCase				(m_context, "precision_vertex_highp_float",			"GetShaderPrecisionFormat",		GL_VERTEX_SHADER,	GL_HIGH_FLOAT));
3697	addChild(new PrecisionFormatCase				(m_context, "precision_vertex_lowp_int",			"GetShaderPrecisionFormat",		GL_VERTEX_SHADER,	GL_LOW_INT));
3698	addChild(new PrecisionFormatCase				(m_context, "precision_vertex_mediump_int",			"GetShaderPrecisionFormat",		GL_VERTEX_SHADER,	GL_MEDIUM_INT));
3699	addChild(new PrecisionFormatCase				(m_context, "precision_vertex_highp_int",			"GetShaderPrecisionFormat",		GL_VERTEX_SHADER,	GL_HIGH_INT));
3700	addChild(new PrecisionFormatCase				(m_context, "precision_fragment_lowp_float",		"GetShaderPrecisionFormat",		GL_FRAGMENT_SHADER,	GL_LOW_FLOAT));
3701	addChild(new PrecisionFormatCase				(m_context, "precision_fragment_mediump_float",		"GetShaderPrecisionFormat",		GL_FRAGMENT_SHADER,	GL_MEDIUM_FLOAT));
3702	addChild(new PrecisionFormatCase				(m_context, "precision_fragment_highp_float",		"GetShaderPrecisionFormat",		GL_FRAGMENT_SHADER,	GL_HIGH_FLOAT));
3703	addChild(new PrecisionFormatCase				(m_context, "precision_fragment_lowp_int",			"GetShaderPrecisionFormat",		GL_FRAGMENT_SHADER,	GL_LOW_INT));
3704	addChild(new PrecisionFormatCase				(m_context, "precision_fragment_mediump_int",		"GetShaderPrecisionFormat",		GL_FRAGMENT_SHADER,	GL_MEDIUM_INT));
3705	addChild(new PrecisionFormatCase				(m_context, "precision_fragment_highp_int",			"GetShaderPrecisionFormat",		GL_FRAGMENT_SHADER,	GL_HIGH_INT));
3706}
3707
3708} // Functional
3709} // gles3
3710} // deqp
3711