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		const glu::ContextType& contextType = m_context.getRenderContext().getType();
2193		const bool isCoreGL45 = glu::contextSupports(contextType, glu::ApiType::core(4, 5));
2194
2195		// Test with default VAO
2196		if (!isCoreGL45)
2197		{
2198			const tcu::ScopedLogSection section(m_log, "DefaultVAO", "Test with default VAO");
2199
2200			for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(pointers); ++ndx)
2201			{
2202				glVertexAttribPointer(0, pointers[ndx].size, pointers[ndx].type, pointers[ndx].normalized, pointers[ndx].stride, pointers[ndx].pointer);
2203				expectError(GL_NO_ERROR);
2204
2205				verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_SIZE, pointers[ndx].size);
2206			}
2207		}
2208
2209		// Test with multiple VAOs
2210		{
2211			const tcu::ScopedLogSection section(m_log, "WithVAO", "Test with VAO");
2212
2213			GLuint buf		= 0;
2214			GLuint vaos[2]	= {0};
2215
2216			glGenVertexArrays(2, vaos);
2217			glGenBuffers(1, &buf);
2218			glBindBuffer(GL_ARRAY_BUFFER, buf);
2219			expectError(GL_NO_ERROR);
2220
2221			// initial
2222			glBindVertexArray(vaos[0]);
2223			verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_SIZE, 4);
2224			expectError(GL_NO_ERROR);
2225
2226			// set vao 0 to some value
2227			glVertexAttribPointer(0, pointers[0].size, pointers[0].type, pointers[0].normalized, pointers[0].stride, DE_NULL);
2228			expectError(GL_NO_ERROR);
2229
2230			// set vao 1 to some other value
2231			glBindVertexArray(vaos[1]);
2232			glVertexAttribPointer(0, pointers[1].size, pointers[1].type, pointers[1].normalized, pointers[1].stride, DE_NULL);
2233			expectError(GL_NO_ERROR);
2234
2235			// verify vao 1 state
2236			verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_SIZE, pointers[1].size);
2237			expectError(GL_NO_ERROR);
2238
2239			// verify vao 0 state
2240			glBindVertexArray(vaos[0]);
2241			verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_SIZE, pointers[0].size);
2242			expectError(GL_NO_ERROR);
2243
2244			glDeleteVertexArrays(2, vaos);
2245			glDeleteBuffers(1, &buf);
2246			expectError(GL_NO_ERROR);
2247		}
2248	}
2249};
2250
2251class VertexAttributeTypeCase : public ApiCase
2252{
2253public:
2254	VertexAttributeTypeCase (Context& context, const char* name, const char* description)
2255		: ApiCase(context, name, description)
2256	{
2257	}
2258
2259	void test (void)
2260	{
2261		const glu::ContextType& contextType = m_context.getRenderContext().getType();
2262		const bool isCoreGL45 = glu::contextSupports(contextType, glu::ApiType::core(4, 5));
2263
2264		// Test with default VAO
2265		if (!isCoreGL45)
2266		{
2267			const tcu::ScopedLogSection section(m_log, "DefaultVAO", "Test with default VAO");
2268
2269			const GLfloat vertexData[4] = {0.0f}; // never accessed
2270
2271			// test VertexAttribPointer
2272			{
2273				const PointerData pointers[] =
2274				{
2275					{ 1, GL_BYTE,								0,	GL_FALSE, vertexData	},
2276					{ 1, GL_SHORT,								0,	GL_FALSE, vertexData	},
2277					{ 1, GL_INT,								0,	GL_FALSE, vertexData	},
2278					{ 1, GL_FIXED,								0,	GL_FALSE, vertexData	},
2279					{ 1, GL_FLOAT,								0,	GL_FALSE, vertexData	},
2280					{ 1, GL_HALF_FLOAT,							0,	GL_FALSE, vertexData	},
2281					{ 1, GL_UNSIGNED_BYTE,						0,	GL_FALSE, vertexData	},
2282					{ 1, GL_UNSIGNED_SHORT,						0,	GL_FALSE, vertexData	},
2283					{ 1, GL_UNSIGNED_INT,						0,	GL_FALSE, vertexData	},
2284					{ 4, GL_INT_2_10_10_10_REV,					0,	GL_FALSE, vertexData	},
2285					{ 4, GL_UNSIGNED_INT_2_10_10_10_REV,		0,	GL_FALSE, vertexData	},
2286				};
2287
2288				for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(pointers); ++ndx)
2289				{
2290					glVertexAttribPointer(0, pointers[ndx].size, pointers[ndx].type, pointers[ndx].normalized, pointers[ndx].stride, pointers[ndx].pointer);
2291					expectError(GL_NO_ERROR);
2292
2293					verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_TYPE, pointers[ndx].type);
2294				}
2295			}
2296
2297			// test glVertexAttribIPointer
2298			{
2299				const PointerData pointers[] =
2300				{
2301					{ 1, GL_BYTE,								0,	GL_FALSE, vertexData	},
2302					{ 1, GL_SHORT,								0,	GL_FALSE, vertexData	},
2303					{ 1, GL_INT,								0,	GL_FALSE, vertexData	},
2304					{ 1, GL_UNSIGNED_BYTE,						0,	GL_FALSE, vertexData	},
2305					{ 1, GL_UNSIGNED_SHORT,						0,	GL_FALSE, vertexData	},
2306					{ 1, GL_UNSIGNED_INT,						0,	GL_FALSE, vertexData	},
2307				};
2308
2309				for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(pointers); ++ndx)
2310				{
2311					glVertexAttribIPointer(0, pointers[ndx].size, pointers[ndx].type, pointers[ndx].stride, pointers[ndx].pointer);
2312					expectError(GL_NO_ERROR);
2313
2314					verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_TYPE, pointers[ndx].type);
2315				}
2316			}
2317		}
2318
2319		// Test with multiple VAOs
2320		{
2321			const tcu::ScopedLogSection section(m_log, "WithVAO", "Test with VAO");
2322
2323			GLuint buf		= 0;
2324			GLuint vaos[2]	= {0};
2325
2326			glGenVertexArrays(2, vaos);
2327			glGenBuffers(1, &buf);
2328			glBindBuffer(GL_ARRAY_BUFFER, buf);
2329			expectError(GL_NO_ERROR);
2330
2331			// initial
2332			glBindVertexArray(vaos[0]);
2333			verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_TYPE, GL_FLOAT);
2334			expectError(GL_NO_ERROR);
2335
2336			// set vao 0 to some value
2337			glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, DE_NULL);
2338			expectError(GL_NO_ERROR);
2339
2340			// set vao 1 to some other value
2341			glBindVertexArray(vaos[1]);
2342			glVertexAttribPointer(0, 1, GL_SHORT, GL_FALSE, 0, DE_NULL);
2343			expectError(GL_NO_ERROR);
2344
2345			// verify vao 1 state
2346			verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_TYPE, GL_SHORT);
2347			expectError(GL_NO_ERROR);
2348
2349			// verify vao 0 state
2350			glBindVertexArray(vaos[0]);
2351			verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_TYPE, GL_FLOAT);
2352			expectError(GL_NO_ERROR);
2353
2354			glDeleteVertexArrays(2, vaos);
2355			glDeleteBuffers(1, &buf);
2356			expectError(GL_NO_ERROR);
2357		}
2358	}
2359};
2360
2361class VertexAttributeStrideCase : public ApiCase
2362{
2363public:
2364	VertexAttributeStrideCase (Context& context, const char* name, const char* description)
2365		: ApiCase(context, name, description)
2366	{
2367	}
2368
2369	void test (void)
2370	{
2371		const glu::ContextType& contextType = m_context.getRenderContext().getType();
2372		const bool isCoreGL45 = glu::contextSupports(contextType, glu::ApiType::core(4, 5));
2373
2374		// Test with default VAO
2375		if (!isCoreGL45)
2376		{
2377			const tcu::ScopedLogSection section(m_log, "DefaultVAO", "Test with default VAO");
2378
2379			const GLfloat vertexData[4] = {0.0f}; // never accessed
2380
2381			struct StridePointerData
2382			{
2383				GLint		size;
2384				GLenum		type;
2385				GLint		stride;
2386				const void*	pointer;
2387			};
2388
2389			// test VertexAttribPointer
2390			{
2391				const StridePointerData pointers[] =
2392				{
2393					{ 1, GL_FLOAT,			0,	vertexData },
2394					{ 1, GL_FLOAT,			1,	vertexData },
2395					{ 1, GL_FLOAT,			4,	vertexData },
2396					{ 1, GL_HALF_FLOAT,		0,	vertexData },
2397					{ 1, GL_HALF_FLOAT,		1,	vertexData },
2398					{ 1, GL_HALF_FLOAT,		4,	vertexData },
2399					{ 1, GL_FIXED,			0,	vertexData },
2400					{ 1, GL_FIXED,			1,	vertexData },
2401					{ 1, GL_FIXED,			4,	vertexData },
2402				};
2403
2404				for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(pointers); ++ndx)
2405				{
2406					glVertexAttribPointer(0, pointers[ndx].size, pointers[ndx].type, GL_FALSE, pointers[ndx].stride, pointers[ndx].pointer);
2407					expectError(GL_NO_ERROR);
2408
2409					verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_STRIDE, pointers[ndx].stride);
2410				}
2411			}
2412
2413			// test glVertexAttribIPointer
2414			{
2415				const StridePointerData pointers[] =
2416				{
2417					{ 1, GL_INT,				0,	vertexData },
2418					{ 1, GL_INT,				1,	vertexData },
2419					{ 1, GL_INT,				4,	vertexData },
2420					{ 4, GL_UNSIGNED_BYTE,		0,	vertexData },
2421					{ 4, GL_UNSIGNED_BYTE,		1,	vertexData },
2422					{ 4, GL_UNSIGNED_BYTE,		4,	vertexData },
2423					{ 2, GL_SHORT,				0,	vertexData },
2424					{ 2, GL_SHORT,				1,	vertexData },
2425					{ 2, GL_SHORT,				4,	vertexData },
2426				};
2427
2428				for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(pointers); ++ndx)
2429				{
2430					glVertexAttribIPointer(0, pointers[ndx].size, pointers[ndx].type, pointers[ndx].stride, pointers[ndx].pointer);
2431					expectError(GL_NO_ERROR);
2432
2433					verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_STRIDE, pointers[ndx].stride);
2434				}
2435			}
2436		}
2437
2438		// Test with multiple VAOs
2439		{
2440			const tcu::ScopedLogSection section(m_log, "WithVAO", "Test with VAO");
2441
2442			GLuint buf		= 0;
2443			GLuint vaos[2]	= {0};
2444
2445			glGenVertexArrays(2, vaos);
2446			glGenBuffers(1, &buf);
2447			glBindBuffer(GL_ARRAY_BUFFER, buf);
2448			expectError(GL_NO_ERROR);
2449
2450			// initial
2451			glBindVertexArray(vaos[0]);
2452			verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_STRIDE, 0);
2453			expectError(GL_NO_ERROR);
2454
2455			// set vao 0 to some value
2456			glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 4, DE_NULL);
2457			expectError(GL_NO_ERROR);
2458
2459			// set vao 1 to some other value
2460			glBindVertexArray(vaos[1]);
2461			glVertexAttribPointer(0, 1, GL_SHORT, GL_FALSE, 8, DE_NULL);
2462			expectError(GL_NO_ERROR);
2463
2464			// verify vao 1 state
2465			verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_STRIDE, 8);
2466			expectError(GL_NO_ERROR);
2467
2468			// verify vao 0 state
2469			glBindVertexArray(vaos[0]);
2470			verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_STRIDE, 4);
2471			expectError(GL_NO_ERROR);
2472
2473			glDeleteVertexArrays(2, vaos);
2474			glDeleteBuffers(1, &buf);
2475			expectError(GL_NO_ERROR);
2476		}
2477	}
2478};
2479
2480class VertexAttributeNormalizedCase : public ApiCase
2481{
2482public:
2483	VertexAttributeNormalizedCase (Context& context, const char* name, const char* description)
2484		: ApiCase(context, name, description)
2485	{
2486	}
2487
2488	void test (void)
2489	{
2490		const glu::ContextType& contextType = m_context.getRenderContext().getType();
2491		const bool isCoreGL45 = glu::contextSupports(contextType, glu::ApiType::core(4, 5));
2492
2493		// Test with default VAO
2494		if (!isCoreGL45)
2495		{
2496			const tcu::ScopedLogSection section(m_log, "DefaultVAO", "Test with default VAO");
2497
2498			const GLfloat vertexData[4] = {0.0f}; // never accessed
2499
2500			// test VertexAttribPointer
2501			{
2502				const PointerData pointers[] =
2503				{
2504					{ 1, GL_BYTE,								0,	GL_FALSE,	vertexData	},
2505					{ 1, GL_SHORT,								0,	GL_FALSE,	vertexData	},
2506					{ 1, GL_INT,								0,	GL_FALSE,	vertexData	},
2507					{ 1, GL_UNSIGNED_BYTE,						0,	GL_FALSE,	vertexData	},
2508					{ 1, GL_UNSIGNED_SHORT,						0,	GL_FALSE,	vertexData	},
2509					{ 1, GL_UNSIGNED_INT,						0,	GL_FALSE,	vertexData	},
2510					{ 4, GL_INT_2_10_10_10_REV,					0,	GL_FALSE,	vertexData	},
2511					{ 4, GL_UNSIGNED_INT_2_10_10_10_REV,		0,	GL_FALSE,	vertexData	},
2512					{ 1, GL_BYTE,								0,	GL_TRUE,	vertexData	},
2513					{ 1, GL_SHORT,								0,	GL_TRUE,	vertexData	},
2514					{ 1, GL_INT,								0,	GL_TRUE,	vertexData	},
2515					{ 1, GL_UNSIGNED_BYTE,						0,	GL_TRUE,	vertexData	},
2516					{ 1, GL_UNSIGNED_SHORT,						0,	GL_TRUE,	vertexData	},
2517					{ 1, GL_UNSIGNED_INT,						0,	GL_TRUE,	vertexData	},
2518					{ 4, GL_INT_2_10_10_10_REV,					0,	GL_TRUE,	vertexData	},
2519					{ 4, GL_UNSIGNED_INT_2_10_10_10_REV,		0,	GL_TRUE,	vertexData	},
2520				};
2521
2522				for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(pointers); ++ndx)
2523				{
2524					glVertexAttribPointer(0, pointers[ndx].size, pointers[ndx].type, pointers[ndx].normalized, pointers[ndx].stride, pointers[ndx].pointer);
2525					expectError(GL_NO_ERROR);
2526
2527					verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, pointers[ndx].normalized);
2528				}
2529			}
2530
2531			// test glVertexAttribIPointer
2532			{
2533				const PointerData pointers[] =
2534				{
2535					{ 1, GL_BYTE,				0,	GL_FALSE, vertexData	},
2536					{ 1, GL_SHORT,				0,	GL_FALSE, vertexData	},
2537					{ 1, GL_INT,				0,	GL_FALSE, vertexData	},
2538					{ 1, GL_UNSIGNED_BYTE,		0,	GL_FALSE, vertexData	},
2539					{ 1, GL_UNSIGNED_SHORT,		0,	GL_FALSE, vertexData	},
2540					{ 1, GL_UNSIGNED_INT,		0,	GL_FALSE, vertexData	},
2541				};
2542
2543				for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(pointers); ++ndx)
2544				{
2545					glVertexAttribIPointer(0, pointers[ndx].size, pointers[ndx].type, pointers[ndx].stride, pointers[ndx].pointer);
2546					expectError(GL_NO_ERROR);
2547
2548					verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, GL_FALSE);
2549				}
2550			}
2551		}
2552
2553		// Test with multiple VAOs
2554		{
2555			const tcu::ScopedLogSection section(m_log, "WithVAO", "Test with VAO");
2556
2557			GLuint buf		= 0;
2558			GLuint vaos[2]	= {0};
2559
2560			glGenVertexArrays(2, vaos);
2561			glGenBuffers(1, &buf);
2562			glBindBuffer(GL_ARRAY_BUFFER, buf);
2563			expectError(GL_NO_ERROR);
2564
2565			// initial
2566			glBindVertexArray(vaos[0]);
2567			verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, GL_FALSE);
2568			expectError(GL_NO_ERROR);
2569
2570			// set vao 0 to some value
2571			glVertexAttribPointer(0, 1, GL_INT, GL_TRUE, 0, DE_NULL);
2572			expectError(GL_NO_ERROR);
2573
2574			// set vao 1 to some other value
2575			glBindVertexArray(vaos[1]);
2576			glVertexAttribPointer(0, 1, GL_INT, GL_FALSE, 0, DE_NULL);
2577			expectError(GL_NO_ERROR);
2578
2579			// verify vao 1 state
2580			verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, GL_FALSE);
2581			expectError(GL_NO_ERROR);
2582
2583			// verify vao 0 state
2584			glBindVertexArray(vaos[0]);
2585			verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, GL_TRUE);
2586			expectError(GL_NO_ERROR);
2587
2588			glDeleteVertexArrays(2, vaos);
2589			glDeleteBuffers(1, &buf);
2590			expectError(GL_NO_ERROR);
2591		}
2592	}
2593};
2594
2595class VertexAttributeIntegerCase : public ApiCase
2596{
2597public:
2598	VertexAttributeIntegerCase (Context& context, const char* name, const char* description)
2599		: ApiCase(context, name, description)
2600	{
2601	}
2602
2603	void test (void)
2604	{
2605		const glu::ContextType& contextType = m_context.getRenderContext().getType();
2606		const bool isCoreGL45 = glu::contextSupports(contextType, glu::ApiType::core(4, 5));
2607
2608		// Test with default VAO
2609		if (!isCoreGL45)
2610		{
2611			const tcu::ScopedLogSection section(m_log, "DefaultVAO", "Test with default VAO");
2612
2613			const GLfloat vertexData[4] = {0.0f}; // never accessed
2614
2615			// test VertexAttribPointer
2616			{
2617				const PointerData pointers[] =
2618				{
2619					{ 1, GL_BYTE,								0,	GL_FALSE, vertexData	},
2620					{ 1, GL_SHORT,								0,	GL_FALSE, vertexData	},
2621					{ 1, GL_INT,								0,	GL_FALSE, vertexData	},
2622					{ 1, GL_FIXED,								0,	GL_FALSE, vertexData	},
2623					{ 1, GL_FLOAT,								0,	GL_FALSE, vertexData	},
2624					{ 1, GL_HALF_FLOAT,							0,	GL_FALSE, vertexData	},
2625					{ 1, GL_UNSIGNED_BYTE,						0,	GL_FALSE, vertexData	},
2626					{ 1, GL_UNSIGNED_SHORT,						0,	GL_FALSE, vertexData	},
2627					{ 1, GL_UNSIGNED_INT,						0,	GL_FALSE, vertexData	},
2628					{ 4, GL_INT_2_10_10_10_REV,					0,	GL_FALSE, vertexData	},
2629					{ 4, GL_UNSIGNED_INT_2_10_10_10_REV,		0,	GL_FALSE, vertexData	},
2630				};
2631
2632				for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(pointers); ++ndx)
2633				{
2634					glVertexAttribPointer(0, pointers[ndx].size, pointers[ndx].type, pointers[ndx].normalized, pointers[ndx].stride, pointers[ndx].pointer);
2635					expectError(GL_NO_ERROR);
2636
2637					verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_INTEGER, GL_FALSE);
2638				}
2639			}
2640
2641			// test glVertexAttribIPointer
2642			{
2643				const PointerData pointers[] =
2644				{
2645					{ 1, GL_BYTE,								0,	GL_FALSE, vertexData	},
2646					{ 1, GL_SHORT,								0,	GL_FALSE, vertexData	},
2647					{ 1, GL_INT,								0,	GL_FALSE, vertexData	},
2648					{ 1, GL_UNSIGNED_BYTE,						0,	GL_FALSE, vertexData	},
2649					{ 1, GL_UNSIGNED_SHORT,						0,	GL_FALSE, vertexData	},
2650					{ 1, GL_UNSIGNED_INT,						0,	GL_FALSE, vertexData	},
2651				};
2652
2653				for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(pointers); ++ndx)
2654				{
2655					glVertexAttribIPointer(0, pointers[ndx].size, pointers[ndx].type, pointers[ndx].stride, pointers[ndx].pointer);
2656					expectError(GL_NO_ERROR);
2657
2658					verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_INTEGER, GL_TRUE);
2659				}
2660			}
2661		}
2662
2663		// Test with multiple VAOs
2664		{
2665			const tcu::ScopedLogSection section(m_log, "WithVAO", "Test with VAO");
2666
2667			GLuint buf		= 0;
2668			GLuint vaos[2]	= {0};
2669
2670			glGenVertexArrays(2, vaos);
2671			glGenBuffers(1, &buf);
2672			glBindBuffer(GL_ARRAY_BUFFER, buf);
2673			expectError(GL_NO_ERROR);
2674
2675			// initial
2676			glBindVertexArray(vaos[0]);
2677			verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_INTEGER, GL_FALSE);
2678			expectError(GL_NO_ERROR);
2679
2680			// set vao 0 to some value
2681			glVertexAttribIPointer(0, 1, GL_INT, 0, DE_NULL);
2682			expectError(GL_NO_ERROR);
2683
2684			// set vao 1 to some other value
2685			glBindVertexArray(vaos[1]);
2686			glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, DE_NULL);
2687			expectError(GL_NO_ERROR);
2688
2689			// verify vao 1 state
2690			verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_INTEGER, GL_FALSE);
2691			expectError(GL_NO_ERROR);
2692
2693			// verify vao 0 state
2694			glBindVertexArray(vaos[0]);
2695			verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_INTEGER, GL_TRUE);
2696			expectError(GL_NO_ERROR);
2697
2698			glDeleteVertexArrays(2, vaos);
2699			glDeleteBuffers(1, &buf);
2700			expectError(GL_NO_ERROR);
2701		}
2702	}
2703};
2704
2705class VertexAttributeEnabledCase : public ApiCase
2706{
2707public:
2708	VertexAttributeEnabledCase (Context& context, const char* name, const char* description)
2709		: ApiCase(context, name, description)
2710	{
2711	}
2712
2713	void test (void)
2714	{
2715		// VERTEX_ATTRIB_ARRAY_ENABLED
2716
2717		const glu::ContextType& contextType = m_context.getRenderContext().getType();
2718		const bool isCoreGL45 = glu::contextSupports(contextType, glu::ApiType::core(4, 5));
2719
2720		// Test with default VAO
2721		if (!isCoreGL45)
2722		{
2723			const tcu::ScopedLogSection section(m_log, "DefaultVAO", "Test with default VAO");
2724
2725			verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_ENABLED, GL_FALSE);
2726			glEnableVertexAttribArray(0);
2727			verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_ENABLED, GL_TRUE);
2728			glDisableVertexAttribArray(0);
2729			verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_ENABLED, GL_FALSE);
2730		}
2731
2732		// Test with multiple VAOs
2733		{
2734			const tcu::ScopedLogSection section(m_log, "WithVAO", "Test with VAO");
2735
2736			GLuint vaos[2] = {0};
2737
2738			glGenVertexArrays(2, vaos);
2739			expectError(GL_NO_ERROR);
2740
2741			// set vao 0 to some value
2742			glBindVertexArray(vaos[0]);
2743			glEnableVertexAttribArray(0);
2744			expectError(GL_NO_ERROR);
2745
2746			// set vao 1 to some other value
2747			glBindVertexArray(vaos[1]);
2748			glDisableVertexAttribArray(0);
2749			expectError(GL_NO_ERROR);
2750
2751			// verify vao 1 state
2752			verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_ENABLED, GL_FALSE);
2753			expectError(GL_NO_ERROR);
2754
2755			// verify vao 0 state
2756			glBindVertexArray(vaos[0]);
2757			verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_ENABLED, GL_TRUE);
2758			expectError(GL_NO_ERROR);
2759
2760			glDeleteVertexArrays(2, vaos);
2761			expectError(GL_NO_ERROR);
2762		}
2763	}
2764};
2765
2766class VertexAttributeDivisorCase : public ApiCase
2767{
2768public:
2769	VertexAttributeDivisorCase (Context& context, const char* name, const char* description)
2770		: ApiCase(context, name, description)
2771	{
2772	}
2773
2774	void test (void)
2775	{
2776		const glu::ContextType& contextType = m_context.getRenderContext().getType();
2777		const bool isCoreGL45 = glu::contextSupports(contextType, glu::ApiType::core(4, 5));
2778
2779		// Test with default VAO
2780		if (!isCoreGL45)
2781		{
2782			const tcu::ScopedLogSection section(m_log, "DefaultVAO", "Test with default VAO");
2783
2784			verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_DIVISOR,	0);
2785			glVertexAttribDivisor(0, 1);
2786			verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_DIVISOR,	1);
2787			glVertexAttribDivisor(0, 5);
2788			verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_DIVISOR,	5);
2789		}
2790
2791		// Test with multiple VAOs
2792		{
2793			const tcu::ScopedLogSection section(m_log, "WithVAO", "Test with VAO");
2794
2795			GLuint vaos[2] = {0};
2796
2797			glGenVertexArrays(2, vaos);
2798			expectError(GL_NO_ERROR);
2799
2800			// set vao 0 to some value
2801			glBindVertexArray(vaos[0]);
2802			glVertexAttribDivisor(0, 1);
2803			expectError(GL_NO_ERROR);
2804
2805			// set vao 1 to some other value
2806			glBindVertexArray(vaos[1]);
2807			glVertexAttribDivisor(0, 5);
2808			expectError(GL_NO_ERROR);
2809
2810			// verify vao 1 state
2811			verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_DIVISOR, 5);
2812			expectError(GL_NO_ERROR);
2813
2814			// verify vao 0 state
2815			glBindVertexArray(vaos[0]);
2816			verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_DIVISOR, 1);
2817			expectError(GL_NO_ERROR);
2818
2819			glDeleteVertexArrays(2, vaos);
2820			expectError(GL_NO_ERROR);
2821		}
2822	}
2823};
2824
2825class VertexAttributeBufferBindingCase : public ApiCase
2826{
2827public:
2828	VertexAttributeBufferBindingCase (Context& context, const char* name, const char* description)
2829		: ApiCase(context, name, description)
2830	{
2831	}
2832
2833	void test (void)
2834	{
2835		const glu::ContextType& contextType = m_context.getRenderContext().getType();
2836		const bool isCoreGL45 = glu::contextSupports(contextType, glu::ApiType::core(4, 5));
2837
2838		// Test with default VAO
2839		if (!isCoreGL45)
2840		{
2841			const tcu::ScopedLogSection section(m_log, "DefaultVAO", "Test with default VAO");
2842
2843			// initial
2844			verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, 0);
2845
2846			GLuint bufferID;
2847			glGenBuffers(1, &bufferID);
2848			glBindBuffer(GL_ARRAY_BUFFER, bufferID);
2849			expectError(GL_NO_ERROR);
2850
2851			glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, DE_NULL);
2852			expectError(GL_NO_ERROR);
2853
2854			verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, bufferID);
2855
2856			glDeleteBuffers(1, &bufferID);
2857			expectError(GL_NO_ERROR);
2858		}
2859
2860		// Test with multiple VAOs
2861		{
2862			const tcu::ScopedLogSection section(m_log, "WithVAO", "Test with VAO");
2863
2864			GLuint vaos[2] = {0};
2865			GLuint bufs[2] = {0};
2866
2867			glGenBuffers(2, bufs);
2868			expectError(GL_NO_ERROR);
2869
2870			glGenVertexArrays(2, vaos);
2871			expectError(GL_NO_ERROR);
2872
2873			// set vao 0 to some value
2874			glBindVertexArray(vaos[0]);
2875			glBindBuffer(GL_ARRAY_BUFFER, bufs[0]);
2876			glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, DE_NULL);
2877			expectError(GL_NO_ERROR);
2878
2879			// set vao 1 to some other value
2880			glBindVertexArray(vaos[1]);
2881			glBindBuffer(GL_ARRAY_BUFFER, bufs[1]);
2882			glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, DE_NULL);
2883			expectError(GL_NO_ERROR);
2884
2885			// verify vao 1 state
2886			verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, bufs[1]);
2887			expectError(GL_NO_ERROR);
2888
2889			// verify vao 0 state
2890			glBindVertexArray(vaos[0]);
2891			verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, bufs[0]);
2892			expectError(GL_NO_ERROR);
2893
2894			glDeleteVertexArrays(2, vaos);
2895			glDeleteBuffers(2, bufs);
2896			expectError(GL_NO_ERROR);
2897		}
2898	}
2899};
2900
2901class VertexAttributePointerCase : public ApiCase
2902{
2903public:
2904	VertexAttributePointerCase (Context& context, const char* name, const char* description)
2905		: ApiCase(context, name, description)
2906	{
2907	}
2908
2909	void test (void)
2910	{
2911		const glu::ContextType& contextType = m_context.getRenderContext().getType();
2912		const bool isCoreGL45 = glu::contextSupports(contextType, glu::ApiType::core(4, 5));
2913
2914		// Test with default VAO
2915		if (!isCoreGL45)
2916		{
2917			const tcu::ScopedLogSection section(m_log, "DefaultVAO", "Test with default VAO");
2918
2919			StateQueryMemoryWriteGuard<GLvoid*> initialState;
2920			glGetVertexAttribPointerv(0, GL_VERTEX_ATTRIB_ARRAY_POINTER, &initialState);
2921			initialState.verifyValidity(m_testCtx);
2922			checkPointerEquals(m_testCtx, initialState, 0);
2923
2924			const GLfloat vertexData[4] = {0.0f}; // never accessed
2925			const PointerData pointers[] =
2926			{
2927				{ 1, GL_BYTE,				0,	GL_FALSE, &vertexData[2] },
2928				{ 1, GL_SHORT,				0,	GL_FALSE, &vertexData[1] },
2929				{ 1, GL_INT,				0,	GL_FALSE, &vertexData[2] },
2930				{ 1, GL_FIXED,				0,	GL_FALSE, &vertexData[2] },
2931				{ 1, GL_FIXED,				0,	GL_FALSE, &vertexData[1] },
2932				{ 1, GL_FLOAT,				0,	GL_FALSE, &vertexData[0] },
2933				{ 1, GL_FLOAT,				0,	GL_FALSE, &vertexData[3] },
2934				{ 1, GL_FLOAT,				0,	GL_FALSE, &vertexData[2] },
2935				{ 1, GL_HALF_FLOAT,			0,	GL_FALSE, &vertexData[0] },
2936				{ 4, GL_HALF_FLOAT,			0,	GL_FALSE, &vertexData[1] },
2937				{ 4, GL_HALF_FLOAT,			0,	GL_FALSE, &vertexData[2] },
2938			};
2939
2940			for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(pointers); ++ndx)
2941			{
2942				glVertexAttribPointer(0, pointers[ndx].size, pointers[ndx].type, pointers[ndx].normalized, pointers[ndx].stride, pointers[ndx].pointer);
2943				expectError(GL_NO_ERROR);
2944
2945				StateQueryMemoryWriteGuard<GLvoid*> state;
2946				glGetVertexAttribPointerv(0, GL_VERTEX_ATTRIB_ARRAY_POINTER, &state);
2947				state.verifyValidity(m_testCtx);
2948				checkPointerEquals(m_testCtx, state, pointers[ndx].pointer);
2949			}
2950		}
2951
2952		// Test with multiple VAOs
2953		{
2954			const tcu::ScopedLogSection section(m_log, "WithVAO", "Test with VAO");
2955
2956			GLuint vaos[2] = {0};
2957			GLuint bufs[2] = {0};
2958
2959			glGenBuffers(2, bufs);
2960			expectError(GL_NO_ERROR);
2961
2962			glGenVertexArrays(2, vaos);
2963			expectError(GL_NO_ERROR);
2964
2965			// set vao 0 to some value
2966			glBindVertexArray(vaos[0]);
2967			glBindBuffer(GL_ARRAY_BUFFER, bufs[0]);
2968			glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, glu::BufferOffsetAsPointer(8));
2969			expectError(GL_NO_ERROR);
2970
2971			// set vao 1 to some other value
2972			glBindVertexArray(vaos[1]);
2973			glBindBuffer(GL_ARRAY_BUFFER, bufs[1]);
2974			glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, glu::BufferOffsetAsPointer(4));
2975			expectError(GL_NO_ERROR);
2976
2977			// verify vao 1 state
2978			{
2979				StateQueryMemoryWriteGuard<GLvoid*> state;
2980				glGetVertexAttribPointerv(0, GL_VERTEX_ATTRIB_ARRAY_POINTER, &state);
2981				state.verifyValidity(m_testCtx);
2982				checkPointerEquals(m_testCtx, state, glu::BufferOffsetAsPointer(4));
2983			}
2984			expectError(GL_NO_ERROR);
2985
2986			// verify vao 0 state
2987			glBindVertexArray(vaos[0]);
2988			{
2989				StateQueryMemoryWriteGuard<GLvoid*> state;
2990				glGetVertexAttribPointerv(0, GL_VERTEX_ATTRIB_ARRAY_POINTER, &state);
2991				state.verifyValidity(m_testCtx);
2992				checkPointerEquals(m_testCtx, state, glu::BufferOffsetAsPointer(8));
2993			}
2994			expectError(GL_NO_ERROR);
2995
2996			glDeleteVertexArrays(2, vaos);
2997			glDeleteBuffers(2, bufs);
2998			expectError(GL_NO_ERROR);
2999		}
3000	}
3001};
3002
3003class UniformValueFloatCase : public ApiCase
3004{
3005public:
3006	UniformValueFloatCase (Context& context, const char* name, const char* description)
3007		: ApiCase(context, name, description)
3008	{
3009	}
3010
3011	void test (void)
3012	{
3013		static const char* testVertSource =
3014			"#version 300 es\n"
3015			"uniform highp float floatUniform;\n"
3016			"uniform highp vec2 float2Uniform;\n"
3017			"uniform highp vec3 float3Uniform;\n"
3018			"uniform highp vec4 float4Uniform;\n"
3019			"void main (void)\n"
3020			"{\n"
3021			"	gl_Position = vec4(floatUniform + float2Uniform.x + float3Uniform.x + float4Uniform.x);\n"
3022			"}\n";
3023		static const char* testFragSource =
3024			"#version 300 es\n"
3025			"layout(location = 0) out mediump vec4 fragColor;"
3026			"void main (void)\n"
3027			"{\n"
3028			"	fragColor = vec4(0.0);\n"
3029			"}\n";
3030
3031		GLuint shaderVert = glCreateShader(GL_VERTEX_SHADER);
3032		GLuint shaderFrag = glCreateShader(GL_FRAGMENT_SHADER);
3033
3034		glShaderSource(shaderVert, 1, &testVertSource, DE_NULL);
3035		glShaderSource(shaderFrag, 1, &testFragSource, DE_NULL);
3036
3037		glCompileShader(shaderVert);
3038		glCompileShader(shaderFrag);
3039		expectError(GL_NO_ERROR);
3040
3041		GLuint program = glCreateProgram();
3042		glAttachShader(program, shaderVert);
3043		glAttachShader(program, shaderFrag);
3044		glLinkProgram(program);
3045		glUseProgram(program);
3046		expectError(GL_NO_ERROR);
3047
3048		GLint location;
3049
3050		location = glGetUniformLocation(program,"floatUniform");
3051		glUniform1f(location, 1.0f);
3052		verifyUniformValue1f(m_testCtx, *this, program, location, 1.0f);
3053
3054		location = glGetUniformLocation(program,"float2Uniform");
3055		glUniform2f(location, 1.0f, 2.0f);
3056		verifyUniformValue2f(m_testCtx, *this, program, location, 1.0f, 2.0f);
3057
3058		location = glGetUniformLocation(program,"float3Uniform");
3059		glUniform3f(location, 1.0f, 2.0f, 3.0f);
3060		verifyUniformValue3f(m_testCtx, *this, program, location, 1.0f, 2.0f, 3.0f);
3061
3062		location = glGetUniformLocation(program,"float4Uniform");
3063		glUniform4f(location, 1.0f, 2.0f, 3.0f, 4.0f);
3064		verifyUniformValue4f(m_testCtx, *this, program, location, 1.0f, 2.0f, 3.0f, 4.0f);
3065
3066		glUseProgram(0);
3067		glDeleteShader(shaderVert);
3068		glDeleteShader(shaderFrag);
3069		glDeleteProgram(program);
3070		expectError(GL_NO_ERROR);
3071	}
3072};
3073
3074class UniformValueIntCase : public ApiCase
3075{
3076public:
3077	UniformValueIntCase (Context& context, const char* name, const char* description)
3078		: ApiCase(context, name, description)
3079	{
3080	}
3081
3082	void test (void)
3083	{
3084		static const char* testVertSource =
3085			"#version 300 es\n"
3086			"uniform highp int intUniform;\n"
3087			"uniform highp ivec2 int2Uniform;\n"
3088			"uniform highp ivec3 int3Uniform;\n"
3089			"uniform highp ivec4 int4Uniform;\n"
3090			"void main (void)\n"
3091			"{\n"
3092			"	gl_Position = vec4(float(intUniform + int2Uniform.x + int3Uniform.x + int4Uniform.x));\n"
3093			"}\n";
3094		static const char* testFragSource =
3095			"#version 300 es\n"
3096			"layout(location = 0) out mediump vec4 fragColor;"
3097			"void main (void)\n"
3098			"{\n"
3099			"	fragColor = vec4(0.0);\n"
3100			"}\n";
3101
3102		GLuint shaderVert = glCreateShader(GL_VERTEX_SHADER);
3103		GLuint shaderFrag = glCreateShader(GL_FRAGMENT_SHADER);
3104
3105		glShaderSource(shaderVert, 1, &testVertSource, DE_NULL);
3106		glShaderSource(shaderFrag, 1, &testFragSource, DE_NULL);
3107
3108		glCompileShader(shaderVert);
3109		glCompileShader(shaderFrag);
3110		expectError(GL_NO_ERROR);
3111
3112		GLuint program = glCreateProgram();
3113		glAttachShader(program, shaderVert);
3114		glAttachShader(program, shaderFrag);
3115		glLinkProgram(program);
3116		glUseProgram(program);
3117		expectError(GL_NO_ERROR);
3118
3119		GLint location;
3120
3121		location = glGetUniformLocation(program,"intUniform");
3122		glUniform1i(location, 1);
3123		verifyUniformValue1i(m_testCtx, *this, program, location, 1);
3124
3125		location = glGetUniformLocation(program,"int2Uniform");
3126		glUniform2i(location, 1, 2);
3127		verifyUniformValue2i(m_testCtx, *this, program, location, 1, 2);
3128
3129		location = glGetUniformLocation(program,"int3Uniform");
3130		glUniform3i(location, 1, 2, 3);
3131		verifyUniformValue3i(m_testCtx, *this, program, location, 1, 2, 3);
3132
3133		location = glGetUniformLocation(program,"int4Uniform");
3134		glUniform4i(location, 1, 2, 3, 4);
3135		verifyUniformValue4i(m_testCtx, *this, program, location, 1, 2, 3, 4);
3136
3137		glUseProgram(0);
3138		glDeleteShader(shaderVert);
3139		glDeleteShader(shaderFrag);
3140		glDeleteProgram(program);
3141		expectError(GL_NO_ERROR);
3142	}
3143};
3144
3145class UniformValueUintCase : public ApiCase
3146{
3147public:
3148	UniformValueUintCase (Context& context, const char* name, const char* description)
3149		: ApiCase(context, name, description)
3150	{
3151	}
3152
3153	void test (void)
3154	{
3155		static const char* testVertSource =
3156			"#version 300 es\n"
3157			"uniform highp uint uintUniform;\n"
3158			"uniform highp uvec2 uint2Uniform;\n"
3159			"uniform highp uvec3 uint3Uniform;\n"
3160			"uniform highp uvec4 uint4Uniform;\n"
3161			"void main (void)\n"
3162			"{\n"
3163			"	gl_Position = vec4(float(uintUniform + uint2Uniform.x + uint3Uniform.x + uint4Uniform.x));\n"
3164			"}\n";
3165		static const char* testFragSource =
3166			"#version 300 es\n"
3167			"layout(location = 0) out mediump vec4 fragColor;"
3168			"void main (void)\n"
3169			"{\n"
3170			"	fragColor = vec4(0.0);\n"
3171			"}\n";
3172
3173		GLuint shaderVert = glCreateShader(GL_VERTEX_SHADER);
3174		GLuint shaderFrag = glCreateShader(GL_FRAGMENT_SHADER);
3175
3176		glShaderSource(shaderVert, 1, &testVertSource, DE_NULL);
3177		glShaderSource(shaderFrag, 1, &testFragSource, DE_NULL);
3178
3179		glCompileShader(shaderVert);
3180		glCompileShader(shaderFrag);
3181		expectError(GL_NO_ERROR);
3182
3183		GLuint program = glCreateProgram();
3184		glAttachShader(program, shaderVert);
3185		glAttachShader(program, shaderFrag);
3186		glLinkProgram(program);
3187		glUseProgram(program);
3188		expectError(GL_NO_ERROR);
3189
3190		GLint location;
3191
3192		location = glGetUniformLocation(program,"uintUniform");
3193		glUniform1ui(location, 1);
3194		verifyUniformValue1ui(m_testCtx, *this, program, location, 1);
3195
3196		location = glGetUniformLocation(program,"uint2Uniform");
3197		glUniform2ui(location, 1, 2);
3198		verifyUniformValue2ui(m_testCtx, *this, program, location, 1, 2);
3199
3200		location = glGetUniformLocation(program,"uint3Uniform");
3201		glUniform3ui(location, 1, 2, 3);
3202		verifyUniformValue3ui(m_testCtx, *this, program, location, 1, 2, 3);
3203
3204		location = glGetUniformLocation(program,"uint4Uniform");
3205		glUniform4ui(location, 1, 2, 3, 4);
3206		verifyUniformValue4ui(m_testCtx, *this, program, location, 1, 2, 3, 4);
3207
3208		glUseProgram(0);
3209		glDeleteShader(shaderVert);
3210		glDeleteShader(shaderFrag);
3211		glDeleteProgram(program);
3212		expectError(GL_NO_ERROR);
3213	}
3214};
3215
3216
3217class UniformValueBooleanCase : public ApiCase
3218{
3219public:
3220	UniformValueBooleanCase (Context& context, const char* name, const char* description)
3221		: ApiCase(context, name, description)
3222	{
3223	}
3224
3225	void test (void)
3226	{
3227		static const char* testVertSource =
3228			"#version 300 es\n"
3229			"uniform bool boolUniform;\n"
3230			"uniform bvec2 bool2Uniform;\n"
3231			"uniform bvec3 bool3Uniform;\n"
3232			"uniform bvec4 bool4Uniform;\n"
3233			"void main (void)\n"
3234			"{\n"
3235			"	gl_Position = vec4(float(boolUniform) + float(bool2Uniform.x) + float(bool3Uniform.x) + float(bool4Uniform.x));\n"
3236			"}\n";
3237		static const char* testFragSource =
3238			"#version 300 es\n"
3239			"layout(location = 0) out mediump vec4 fragColor;"
3240			"void main (void)\n"
3241			"{\n"
3242			"	fragColor = vec4(0.0);\n"
3243			"}\n";
3244
3245		GLuint shaderVert = glCreateShader(GL_VERTEX_SHADER);
3246		GLuint shaderFrag = glCreateShader(GL_FRAGMENT_SHADER);
3247
3248		glShaderSource(shaderVert, 1, &testVertSource, DE_NULL);
3249		glShaderSource(shaderFrag, 1, &testFragSource, DE_NULL);
3250
3251		glCompileShader(shaderVert);
3252		glCompileShader(shaderFrag);
3253		expectError(GL_NO_ERROR);
3254
3255		GLuint program = glCreateProgram();
3256		glAttachShader(program, shaderVert);
3257		glAttachShader(program, shaderFrag);
3258		glLinkProgram(program);
3259		glUseProgram(program);
3260		expectError(GL_NO_ERROR);
3261
3262		GLint location;
3263
3264		// int conversion
3265
3266		location = glGetUniformLocation(program,"boolUniform");
3267		glUniform1i(location, 1);
3268		verifyUniformValue1i(m_testCtx, *this, program, location, 1);
3269
3270		location = glGetUniformLocation(program,"bool2Uniform");
3271		glUniform2i(location, 1, 2);
3272		verifyUniformValue2i(m_testCtx, *this, program, location, 1, 1);
3273
3274		location = glGetUniformLocation(program,"bool3Uniform");
3275		glUniform3i(location, 0, 1, 2);
3276		verifyUniformValue3i(m_testCtx, *this, program, location, 0, 1, 1);
3277
3278		location = glGetUniformLocation(program,"bool4Uniform");
3279		glUniform4i(location, 1, 0, 1, -1);
3280		verifyUniformValue4i(m_testCtx, *this, program, location, 1, 0, 1, 1);
3281
3282		// float conversion
3283
3284		location = glGetUniformLocation(program,"boolUniform");
3285		glUniform1f(location, 1.0f);
3286		verifyUniformValue1i(m_testCtx, *this, program, location, 1);
3287
3288		location = glGetUniformLocation(program,"bool2Uniform");
3289		glUniform2f(location, 1.0f, 0.1f);
3290		verifyUniformValue2i(m_testCtx, *this, program, location, 1, 1);
3291
3292		location = glGetUniformLocation(program,"bool3Uniform");
3293		glUniform3f(location, 0.0f, 0.1f, -0.1f);
3294		verifyUniformValue3i(m_testCtx, *this, program, location, 0, 1, 1);
3295
3296		location = glGetUniformLocation(program,"bool4Uniform");
3297		glUniform4f(location, 1.0f, 0.0f, 0.1f, -0.9f);
3298		verifyUniformValue4i(m_testCtx, *this, program, location, 1, 0, 1, 1);
3299
3300		glUseProgram(0);
3301		glDeleteShader(shaderVert);
3302		glDeleteShader(shaderFrag);
3303		glDeleteProgram(program);
3304		expectError(GL_NO_ERROR);
3305	}
3306};
3307
3308class UniformValueSamplerCase : public ApiCase
3309{
3310public:
3311	UniformValueSamplerCase (Context& context, const char* name, const char* description)
3312		: ApiCase(context, name, description)
3313	{
3314	}
3315
3316	void test (void)
3317	{
3318		static const char* testVertSource =
3319			"#version 300 es\n"
3320			"void main (void)\n"
3321			"{\n"
3322			"	gl_Position = vec4(0.0);\n"
3323			"}\n";
3324		static const char* testFragSource =
3325			"#version 300 es\n"
3326			"uniform highp sampler2D uniformSampler;\n"
3327			"layout(location = 0) out mediump vec4 fragColor;"
3328			"void main (void)\n"
3329			"{\n"
3330			"	fragColor = vec4(textureSize(uniformSampler, 0).x);\n"
3331			"}\n";
3332
3333		GLuint shaderVert = glCreateShader(GL_VERTEX_SHADER);
3334		GLuint shaderFrag = glCreateShader(GL_FRAGMENT_SHADER);
3335
3336		glShaderSource(shaderVert, 1, &testVertSource, DE_NULL);
3337		glShaderSource(shaderFrag, 1, &testFragSource, DE_NULL);
3338
3339		glCompileShader(shaderVert);
3340		glCompileShader(shaderFrag);
3341		expectError(GL_NO_ERROR);
3342
3343		GLuint program = glCreateProgram();
3344		glAttachShader(program, shaderVert);
3345		glAttachShader(program, shaderFrag);
3346		glLinkProgram(program);
3347		glUseProgram(program);
3348		expectError(GL_NO_ERROR);
3349
3350		GLint location;
3351
3352		location = glGetUniformLocation(program,"uniformSampler");
3353		glUniform1i(location, 1);
3354		verifyUniformValue1i(m_testCtx, *this, program, location, 1);
3355
3356		glUseProgram(0);
3357		glDeleteShader(shaderVert);
3358		glDeleteShader(shaderFrag);
3359		glDeleteProgram(program);
3360		expectError(GL_NO_ERROR);
3361	}
3362};
3363
3364class UniformValueArrayCase : public ApiCase
3365{
3366public:
3367	UniformValueArrayCase (Context& context, const char* name, const char* description)
3368		: ApiCase(context, name, description)
3369	{
3370	}
3371
3372	void test (void)
3373	{
3374		static const char* testVertSource =
3375			"#version 300 es\n"
3376			"uniform highp float arrayUniform[5];"
3377			"uniform highp vec2 array2Uniform[5];"
3378			"uniform highp vec3 array3Uniform[5];"
3379			"uniform highp vec4 array4Uniform[5];"
3380			"void main (void)\n"
3381			"{\n"
3382			"	gl_Position = \n"
3383			"		+ vec4(arrayUniform[0]		+ arrayUniform[1]		+ arrayUniform[2]		+ arrayUniform[3]		+ arrayUniform[4])\n"
3384			"		+ vec4(array2Uniform[0].x	+ array2Uniform[1].x	+ array2Uniform[2].x	+ array2Uniform[3].x	+ array2Uniform[4].x)\n"
3385			"		+ vec4(array3Uniform[0].x	+ array3Uniform[1].x	+ array3Uniform[2].x	+ array3Uniform[3].x	+ array3Uniform[4].x)\n"
3386			"		+ vec4(array4Uniform[0].x	+ array4Uniform[1].x	+ array4Uniform[2].x	+ array4Uniform[3].x	+ array4Uniform[4].x);\n"
3387			"}\n";
3388		static const char* testFragSource =
3389			"#version 300 es\n"
3390			"layout(location = 0) out mediump vec4 fragColor;"
3391			"void main (void)\n"
3392			"{\n"
3393			"	fragColor = vec4(0.0);\n"
3394			"}\n";
3395
3396		GLuint shaderVert = glCreateShader(GL_VERTEX_SHADER);
3397		GLuint shaderFrag = glCreateShader(GL_FRAGMENT_SHADER);
3398
3399		glShaderSource(shaderVert, 1, &testVertSource, DE_NULL);
3400		glShaderSource(shaderFrag, 1, &testFragSource, DE_NULL);
3401
3402		glCompileShader(shaderVert);
3403		glCompileShader(shaderFrag);
3404		expectError(GL_NO_ERROR);
3405
3406		GLuint program = glCreateProgram();
3407		glAttachShader(program, shaderVert);
3408		glAttachShader(program, shaderFrag);
3409		glLinkProgram(program);
3410		glUseProgram(program);
3411		expectError(GL_NO_ERROR);
3412
3413		GLint location;
3414
3415		float uniformValue[5 * 4] =
3416		{
3417			-1.0f,	0.1f,	4.0f,	800.0f,
3418			13.0f,	55.0f,	12.0f,	91.0f,
3419			-55.1f,	1.1f,	98.0f,	19.0f,
3420			41.0f,	65.0f,	4.0f,	12.2f,
3421			95.0f,	77.0f,	32.0f,	48.0f
3422		};
3423
3424		location = glGetUniformLocation(program,"arrayUniform");
3425		glUniform1fv(location, 5, uniformValue);
3426		expectError(GL_NO_ERROR);
3427
3428		verifyUniformValue1f(m_testCtx, *this, program, glGetUniformLocation(program,"arrayUniform[0]"), uniformValue[0]);
3429		verifyUniformValue1f(m_testCtx, *this, program, glGetUniformLocation(program,"arrayUniform[1]"), uniformValue[1]);
3430		verifyUniformValue1f(m_testCtx, *this, program, glGetUniformLocation(program,"arrayUniform[2]"), uniformValue[2]);
3431		verifyUniformValue1f(m_testCtx, *this, program, glGetUniformLocation(program,"arrayUniform[3]"), uniformValue[3]);
3432		verifyUniformValue1f(m_testCtx, *this, program, glGetUniformLocation(program,"arrayUniform[4]"), uniformValue[4]);
3433		expectError(GL_NO_ERROR);
3434
3435		location = glGetUniformLocation(program,"array2Uniform");
3436		glUniform2fv(location, 5, uniformValue);
3437		expectError(GL_NO_ERROR);
3438
3439		verifyUniformValue2f(m_testCtx, *this, program, glGetUniformLocation(program,"array2Uniform[0]"), uniformValue[2 * 0], uniformValue[(2 * 0) + 1]);
3440		verifyUniformValue2f(m_testCtx, *this, program, glGetUniformLocation(program,"array2Uniform[1]"), uniformValue[2 * 1], uniformValue[(2 * 1) + 1]);
3441		verifyUniformValue2f(m_testCtx, *this, program, glGetUniformLocation(program,"array2Uniform[2]"), uniformValue[2 * 2], uniformValue[(2 * 2) + 1]);
3442		verifyUniformValue2f(m_testCtx, *this, program, glGetUniformLocation(program,"array2Uniform[3]"), uniformValue[2 * 3], uniformValue[(2 * 3) + 1]);
3443		verifyUniformValue2f(m_testCtx, *this, program, glGetUniformLocation(program,"array2Uniform[4]"), uniformValue[2 * 4], uniformValue[(2 * 4) + 1]);
3444		expectError(GL_NO_ERROR);
3445
3446		location = glGetUniformLocation(program,"array3Uniform");
3447		glUniform3fv(location, 5, uniformValue);
3448		expectError(GL_NO_ERROR);
3449
3450		verifyUniformValue3f(m_testCtx, *this, program, glGetUniformLocation(program,"array3Uniform[0]"), uniformValue[3 * 0], uniformValue[(3 * 0) + 1], uniformValue[(3 * 0) + 2]);
3451		verifyUniformValue3f(m_testCtx, *this, program, glGetUniformLocation(program,"array3Uniform[1]"), uniformValue[3 * 1], uniformValue[(3 * 1) + 1], uniformValue[(3 * 1) + 2]);
3452		verifyUniformValue3f(m_testCtx, *this, program, glGetUniformLocation(program,"array3Uniform[2]"), uniformValue[3 * 2], uniformValue[(3 * 2) + 1], uniformValue[(3 * 2) + 2]);
3453		verifyUniformValue3f(m_testCtx, *this, program, glGetUniformLocation(program,"array3Uniform[3]"), uniformValue[3 * 3], uniformValue[(3 * 3) + 1], uniformValue[(3 * 3) + 2]);
3454		verifyUniformValue3f(m_testCtx, *this, program, glGetUniformLocation(program,"array3Uniform[4]"), uniformValue[3 * 4], uniformValue[(3 * 4) + 1], uniformValue[(3 * 4) + 2]);
3455		expectError(GL_NO_ERROR);
3456
3457		location = glGetUniformLocation(program,"array4Uniform");
3458		glUniform4fv(location, 5, uniformValue);
3459		expectError(GL_NO_ERROR);
3460
3461		verifyUniformValue4f(m_testCtx, *this, program, glGetUniformLocation(program,"array4Uniform[0]"), uniformValue[4 * 0], uniformValue[(4 * 0) + 1], uniformValue[(4 * 0) + 2], uniformValue[(4 * 0) + 3]);
3462		verifyUniformValue4f(m_testCtx, *this, program, glGetUniformLocation(program,"array4Uniform[1]"), uniformValue[4 * 1], uniformValue[(4 * 1) + 1], uniformValue[(4 * 1) + 2], uniformValue[(4 * 1) + 3]);
3463		verifyUniformValue4f(m_testCtx, *this, program, glGetUniformLocation(program,"array4Uniform[2]"), uniformValue[4 * 2], uniformValue[(4 * 2) + 1], uniformValue[(4 * 2) + 2], uniformValue[(4 * 2) + 3]);
3464		verifyUniformValue4f(m_testCtx, *this, program, glGetUniformLocation(program,"array4Uniform[3]"), uniformValue[4 * 3], uniformValue[(4 * 3) + 1], uniformValue[(4 * 3) + 2], uniformValue[(4 * 3) + 3]);
3465		verifyUniformValue4f(m_testCtx, *this, program, glGetUniformLocation(program,"array4Uniform[4]"), uniformValue[4 * 4], uniformValue[(4 * 4) + 1], uniformValue[(4 * 4) + 2], uniformValue[(4 * 4) + 3]);
3466		expectError(GL_NO_ERROR);
3467
3468		glUseProgram(0);
3469		glDeleteShader(shaderVert);
3470		glDeleteShader(shaderFrag);
3471		glDeleteProgram(program);
3472		expectError(GL_NO_ERROR);
3473	}
3474};
3475
3476class UniformValueMatrixCase : public ApiCase
3477{
3478public:
3479	UniformValueMatrixCase (Context& context, const char* name, const char* description)
3480		: ApiCase(context, name, description)
3481	{
3482	}
3483
3484	void test (void)
3485	{
3486		static const char* testVertSource =
3487			"#version 300 es\n"
3488			"uniform highp mat2 mat2Uniform;"
3489			"uniform highp mat3 mat3Uniform;"
3490			"uniform highp mat4 mat4Uniform;"
3491			"void main (void)\n"
3492			"{\n"
3493			"	gl_Position = vec4(mat2Uniform[0][0] + mat3Uniform[0][0] + mat4Uniform[0][0]);\n"
3494			"}\n";
3495		static const char* testFragSource =
3496			"#version 300 es\n"
3497			"layout(location = 0) out mediump vec4 fragColor;"
3498			"void main (void)\n"
3499			"{\n"
3500			"	fragColor = vec4(0.0);\n"
3501			"}\n";
3502
3503		GLuint shaderVert = glCreateShader(GL_VERTEX_SHADER);
3504		GLuint shaderFrag = glCreateShader(GL_FRAGMENT_SHADER);
3505
3506		glShaderSource(shaderVert, 1, &testVertSource, DE_NULL);
3507		glShaderSource(shaderFrag, 1, &testFragSource, DE_NULL);
3508
3509		glCompileShader(shaderVert);
3510		glCompileShader(shaderFrag);
3511		expectError(GL_NO_ERROR);
3512
3513		GLuint program = glCreateProgram();
3514		glAttachShader(program, shaderVert);
3515		glAttachShader(program, shaderFrag);
3516		glLinkProgram(program);
3517		glUseProgram(program);
3518		expectError(GL_NO_ERROR);
3519
3520		GLint location;
3521
3522		float matrixValues[4 * 4] =
3523		{
3524			-1.0f,	0.1f,	4.0f,	800.0f,
3525			13.0f,	55.0f,	12.0f,	91.0f,
3526			-55.1f,	1.1f,	98.0f,	19.0f,
3527			41.0f,	65.0f,	4.0f,	12.2f,
3528		};
3529
3530		// the values of the matrix are returned in column major order but they can be given in either order
3531
3532		location = glGetUniformLocation(program,"mat2Uniform");
3533		glUniformMatrix2fv(location, 1, GL_FALSE, matrixValues);
3534		verifyUniformMatrixValues<2>(m_testCtx, *this, program, location, matrixValues, false);
3535		glUniformMatrix2fv(location, 1, GL_TRUE, matrixValues);
3536		verifyUniformMatrixValues<2>(m_testCtx, *this, program, location, matrixValues, true);
3537
3538		location = glGetUniformLocation(program,"mat3Uniform");
3539		glUniformMatrix3fv(location, 1, GL_FALSE, matrixValues);
3540		verifyUniformMatrixValues<3>(m_testCtx, *this, program, location, matrixValues, false);
3541		glUniformMatrix3fv(location, 1, GL_TRUE, matrixValues);
3542		verifyUniformMatrixValues<3>(m_testCtx, *this, program, location, matrixValues, true);
3543
3544		location = glGetUniformLocation(program,"mat4Uniform");
3545		glUniformMatrix4fv(location, 1, GL_FALSE, matrixValues);
3546		verifyUniformMatrixValues<4>(m_testCtx, *this, program, location, matrixValues, false);
3547		glUniformMatrix4fv(location, 1, GL_TRUE, matrixValues);
3548		verifyUniformMatrixValues<4>(m_testCtx, *this, program, location, matrixValues, true);
3549
3550		glUseProgram(0);
3551		glDeleteShader(shaderVert);
3552		glDeleteShader(shaderFrag);
3553		glDeleteProgram(program);
3554		expectError(GL_NO_ERROR);
3555	}
3556};
3557
3558class PrecisionFormatCase : public ApiCase
3559{
3560public:
3561	struct RequiredFormat
3562	{
3563		int negativeRange;
3564		int positiveRange;
3565		int precision;
3566	};
3567
3568	PrecisionFormatCase (Context& context, const char* name, const char* description, glw::GLenum shaderType, glw::GLenum precisionType)
3569		: ApiCase			(context, name, description)
3570		, m_shaderType		(shaderType)
3571		, m_precisionType	(precisionType)
3572	{
3573	}
3574
3575private:
3576	void test (void)
3577	{
3578		const RequiredFormat											expected = getRequiredFormat();
3579		bool															error = false;
3580		gls::StateQueryUtil::StateQueryMemoryWriteGuard<glw::GLboolean>	shaderCompiler;
3581		gls::StateQueryUtil::StateQueryMemoryWriteGuard<glw::GLint[2]>	range;
3582		gls::StateQueryUtil::StateQueryMemoryWriteGuard<glw::GLint>		precision;
3583
3584		// query values
3585		glGetShaderPrecisionFormat(m_shaderType, m_precisionType, range, &precision);
3586		expectError(GL_NO_ERROR);
3587
3588		if (!range.verifyValidity(m_testCtx))
3589			return;
3590		if (!precision.verifyValidity(m_testCtx))
3591			return;
3592
3593		m_log
3594			<< tcu::TestLog::Message
3595			<< "range[0] = " << range[0] << "\n"
3596			<< "range[1] = " << range[1] << "\n"
3597			<< "precision = " << precision
3598			<< tcu::TestLog::EndMessage;
3599
3600		// verify values
3601
3602		if (m_precisionType == GL_HIGH_FLOAT)
3603		{
3604			// highp float must be IEEE 754 single
3605
3606			if (range[0] != expected.negativeRange ||
3607				range[1] != expected.positiveRange ||
3608				precision != expected.precision)
3609			{
3610				m_log
3611					<< tcu::TestLog::Message
3612					<< "// ERROR: Invalid precision format, expected:\n"
3613					<< "\trange[0] = " << expected.negativeRange << "\n"
3614					<< "\trange[1] = " << expected.positiveRange << "\n"
3615					<< "\tprecision = " << expected.precision
3616					<< tcu::TestLog::EndMessage;
3617				error = true;
3618			}
3619		}
3620		else
3621		{
3622			if (range[0] < expected.negativeRange)
3623			{
3624				m_log << tcu::TestLog::Message << "// ERROR: Invalid range[0], expected greater or equal to " << expected.negativeRange << tcu::TestLog::EndMessage;
3625				error = true;
3626			}
3627
3628			if (range[1] < expected.positiveRange)
3629			{
3630				m_log << tcu::TestLog::Message << "// ERROR: Invalid range[1], expected greater or equal to " << expected.positiveRange << tcu::TestLog::EndMessage;
3631				error = true;
3632			}
3633
3634			if (precision < expected.precision)
3635			{
3636				m_log << tcu::TestLog::Message << "// ERROR: Invalid precision, expected greater or equal to " << expected.precision << tcu::TestLog::EndMessage;
3637				error = true;
3638			}
3639		}
3640
3641		if (error)
3642			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid precision/range");
3643	}
3644
3645	RequiredFormat getRequiredFormat (void) const
3646	{
3647		// Precisions for different types.
3648		const RequiredFormat requirements[] =
3649		{
3650			{   0,   0,  8 }, //!< lowp float
3651			{  13,  13, 10 }, //!< mediump float
3652			{ 127, 127, 23 }, //!< highp float
3653			{   8,   7,  0 }, //!< lowp int
3654			{  15,  14,  0 }, //!< mediump int
3655			{  31,  30,  0 }, //!< highp int
3656		};
3657		const int ndx = (int)m_precisionType - (int)GL_LOW_FLOAT;
3658
3659		DE_ASSERT(ndx >= 0);
3660		DE_ASSERT(ndx < DE_LENGTH_OF_ARRAY(requirements));
3661		return requirements[ndx];
3662	}
3663
3664	const glw::GLenum m_shaderType;
3665	const glw::GLenum m_precisionType;
3666};
3667
3668} // anonymous
3669
3670
3671ShaderStateQueryTests::ShaderStateQueryTests (Context& context)
3672	: TestCaseGroup(context, "shader", "Shader State Query tests")
3673{
3674}
3675
3676void ShaderStateQueryTests::init (void)
3677{
3678	// shader
3679	addChild(new ShaderTypeCase						(m_context, "shader_type",							"SHADER_TYPE"));
3680	addChild(new ShaderCompileStatusCase			(m_context, "shader_compile_status",				"COMPILE_STATUS"));
3681	addChild(new ShaderInfoLogCase					(m_context, "shader_info_log_length",				"INFO_LOG_LENGTH"));
3682	addChild(new ShaderSourceCase					(m_context, "shader_source_length",					"SHADER_SOURCE_LENGTH"));
3683
3684	// shader and program
3685	addChild(new DeleteStatusCase					(m_context, "delete_status",						"DELETE_STATUS"));
3686
3687	// vertex-attrib
3688	addChild(new CurrentVertexAttribInitialCase		(m_context, "current_vertex_attrib_initial",		"CURRENT_VERTEX_ATTRIB"));
3689	addChild(new CurrentVertexAttribFloatCase		(m_context, "current_vertex_attrib_float",			"CURRENT_VERTEX_ATTRIB"));
3690	addChild(new CurrentVertexAttribIntCase			(m_context, "current_vertex_attrib_int",			"CURRENT_VERTEX_ATTRIB"));
3691	addChild(new CurrentVertexAttribUintCase		(m_context, "current_vertex_attrib_uint",			"CURRENT_VERTEX_ATTRIB"));
3692	addChild(new CurrentVertexAttribConversionCase	(m_context, "current_vertex_attrib_float_to_int",	"CURRENT_VERTEX_ATTRIB"));
3693
3694	// program
3695	addChild(new ProgramInfoLogCase					(m_context, "program_info_log_length",				"INFO_LOG_LENGTH",	ProgramInfoLogCase::BUILDERROR_COMPILE));
3696	addChild(new ProgramInfoLogCase					(m_context, "program_info_log_length_link_error",	"INFO_LOG_LENGTH",	ProgramInfoLogCase::BUILDERROR_LINK));
3697	addChild(new ProgramValidateStatusCase			(m_context, "program_validate_status",				"VALIDATE_STATUS"));
3698	addChild(new ProgramAttachedShadersCase			(m_context, "program_attached_shaders",				"ATTACHED_SHADERS"));
3699
3700	addChild(new ProgramActiveUniformNameCase		(m_context, "program_active_uniform_name",			"ACTIVE_UNIFORMS and ACTIVE_UNIFORM_MAX_LENGTH"));
3701	addChild(new ProgramUniformCase					(m_context, "program_active_uniform_types",			"UNIFORM_TYPE, UNIFORM_SIZE, and UNIFORM_IS_ROW_MAJOR"));
3702	addChild(new ProgramActiveUniformBlocksCase		(m_context, "program_active_uniform_blocks",		"ACTIVE_UNIFORM_BLOCK_x"));
3703	addChild(new ProgramBinaryCase					(m_context, "program_binary",						"PROGRAM_BINARY_LENGTH and PROGRAM_BINARY_RETRIEVABLE_HINT"));
3704
3705	// transform feedback
3706	addChild(new TransformFeedbackCase				(m_context, "transform_feedback",					"TRANSFORM_FEEDBACK_BUFFER_MODE, TRANSFORM_FEEDBACK_VARYINGS, TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH"));
3707
3708	// attribute related
3709	addChild(new ActiveAttributesCase				(m_context, "active_attributes",					"ACTIVE_ATTRIBUTES and ACTIVE_ATTRIBUTE_MAX_LENGTH"));
3710	addChild(new VertexAttributeSizeCase			(m_context, "vertex_attrib_size",					"VERTEX_ATTRIB_ARRAY_SIZE"));
3711	addChild(new VertexAttributeTypeCase			(m_context, "vertex_attrib_type",					"VERTEX_ATTRIB_ARRAY_TYPE"));
3712	addChild(new VertexAttributeStrideCase			(m_context, "vertex_attrib_stride",					"VERTEX_ATTRIB_ARRAY_STRIDE"));
3713	addChild(new VertexAttributeNormalizedCase		(m_context, "vertex_attrib_normalized",				"VERTEX_ATTRIB_ARRAY_NORMALIZED"));
3714	addChild(new VertexAttributeIntegerCase			(m_context, "vertex_attrib_integer",				"VERTEX_ATTRIB_ARRAY_INTEGER"));
3715	addChild(new VertexAttributeEnabledCase			(m_context, "vertex_attrib_array_enabled",			"VERTEX_ATTRIB_ARRAY_ENABLED"));
3716	addChild(new VertexAttributeDivisorCase			(m_context, "vertex_attrib_array_divisor",			"VERTEX_ATTRIB_ARRAY_DIVISOR"));
3717	addChild(new VertexAttributeBufferBindingCase	(m_context, "vertex_attrib_array_buffer_binding",	"VERTEX_ATTRIB_ARRAY_BUFFER_BINDING"));
3718	addChild(new VertexAttributePointerCase			(m_context, "vertex_attrib_pointerv",				"GetVertexAttribPointerv"));
3719
3720	// uniform values
3721	addChild(new UniformValueFloatCase				(m_context, "uniform_value_float",					"GetUniform*"));
3722	addChild(new UniformValueIntCase				(m_context, "uniform_value_int",					"GetUniform*"));
3723	addChild(new UniformValueUintCase				(m_context, "uniform_value_uint",					"GetUniform*"));
3724	addChild(new UniformValueBooleanCase			(m_context, "uniform_value_boolean",				"GetUniform*"));
3725	addChild(new UniformValueSamplerCase			(m_context, "uniform_value_sampler",				"GetUniform*"));
3726	addChild(new UniformValueArrayCase				(m_context, "uniform_value_array",					"GetUniform*"));
3727	addChild(new UniformValueMatrixCase				(m_context, "uniform_value_matrix",					"GetUniform*"));
3728
3729	// precision format query
3730	addChild(new PrecisionFormatCase				(m_context, "precision_vertex_lowp_float",			"GetShaderPrecisionFormat",		GL_VERTEX_SHADER,	GL_LOW_FLOAT));
3731	addChild(new PrecisionFormatCase				(m_context, "precision_vertex_mediump_float",		"GetShaderPrecisionFormat",		GL_VERTEX_SHADER,	GL_MEDIUM_FLOAT));
3732	addChild(new PrecisionFormatCase				(m_context, "precision_vertex_highp_float",			"GetShaderPrecisionFormat",		GL_VERTEX_SHADER,	GL_HIGH_FLOAT));
3733	addChild(new PrecisionFormatCase				(m_context, "precision_vertex_lowp_int",			"GetShaderPrecisionFormat",		GL_VERTEX_SHADER,	GL_LOW_INT));
3734	addChild(new PrecisionFormatCase				(m_context, "precision_vertex_mediump_int",			"GetShaderPrecisionFormat",		GL_VERTEX_SHADER,	GL_MEDIUM_INT));
3735	addChild(new PrecisionFormatCase				(m_context, "precision_vertex_highp_int",			"GetShaderPrecisionFormat",		GL_VERTEX_SHADER,	GL_HIGH_INT));
3736	addChild(new PrecisionFormatCase				(m_context, "precision_fragment_lowp_float",		"GetShaderPrecisionFormat",		GL_FRAGMENT_SHADER,	GL_LOW_FLOAT));
3737	addChild(new PrecisionFormatCase				(m_context, "precision_fragment_mediump_float",		"GetShaderPrecisionFormat",		GL_FRAGMENT_SHADER,	GL_MEDIUM_FLOAT));
3738	addChild(new PrecisionFormatCase				(m_context, "precision_fragment_highp_float",		"GetShaderPrecisionFormat",		GL_FRAGMENT_SHADER,	GL_HIGH_FLOAT));
3739	addChild(new PrecisionFormatCase				(m_context, "precision_fragment_lowp_int",			"GetShaderPrecisionFormat",		GL_FRAGMENT_SHADER,	GL_LOW_INT));
3740	addChild(new PrecisionFormatCase				(m_context, "precision_fragment_mediump_int",		"GetShaderPrecisionFormat",		GL_FRAGMENT_SHADER,	GL_MEDIUM_INT));
3741	addChild(new PrecisionFormatCase				(m_context, "precision_fragment_highp_int",			"GetShaderPrecisionFormat",		GL_FRAGMENT_SHADER,	GL_HIGH_INT));
3742}
3743
3744} // Functional
3745} // gles3
3746} // deqp
3747