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	ProgramInfoLogCase (Context& context, const char* name, const char* description)
1193		: ApiCase(context, name, description)
1194	{
1195	}
1196
1197	void test (void)
1198	{
1199		using tcu::TestLog;
1200
1201		GLuint shaderVert = glCreateShader(GL_VERTEX_SHADER);
1202		GLuint shaderFrag = glCreateShader(GL_FRAGMENT_SHADER);
1203
1204		glShaderSource(shaderVert, 1, &brokenShader, DE_NULL);
1205		glShaderSource(shaderFrag, 1, &brokenShader, DE_NULL);
1206
1207		glCompileShader(shaderVert);
1208		glCompileShader(shaderFrag);
1209		expectError(GL_NO_ERROR);
1210
1211		GLuint program = glCreateProgram();
1212		glAttachShader(program, shaderVert);
1213		glAttachShader(program, shaderFrag);
1214		glLinkProgram(program);
1215
1216		// check INFO_LOG_LENGTH == GetProgramInfoLog len
1217		{
1218			char buffer[2048] = {'x'};
1219
1220			GLint written = 0;
1221			glGetProgramInfoLog(program, DE_LENGTH_OF_ARRAY(buffer), &written, buffer);
1222
1223			StateQueryMemoryWriteGuard<GLint> logLength;
1224			glGetProgramiv(program, GL_INFO_LOG_LENGTH, &logLength);
1225			logLength.verifyValidity(m_testCtx);
1226
1227			if (logLength != 0 && written+1 != logLength) // INFO_LOG_LENGTH contains 0-terminator
1228			{
1229				m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected INFO_LOG_LENGTH " << written+1 << "; got " << logLength << TestLog::EndMessage;
1230				if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
1231					m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid log length");
1232			}
1233		}
1234
1235		// check GetProgramInfoLog works with too small buffer
1236		{
1237			char buffer[2048] = {'x'};
1238
1239			GLint written = 0;
1240			glGetProgramInfoLog(program, 1, &written, buffer);
1241
1242			if (written != 0)
1243			{
1244				m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected write length 0; got " << written << TestLog::EndMessage;
1245				if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
1246					m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid log length");
1247			}
1248		}
1249
1250		glDeleteShader(shaderVert);
1251		glDeleteShader(shaderFrag);
1252		glDeleteProgram(program);
1253		expectError(GL_NO_ERROR);
1254	}
1255};
1256
1257class ProgramValidateStatusCase : public ApiCase
1258{
1259public:
1260	ProgramValidateStatusCase (Context& context, const char* name, const char* description)
1261		: ApiCase(context, name, description)
1262	{
1263	}
1264
1265	void test (void)
1266	{
1267		// test validate ok
1268		{
1269			GLuint shaderVert = glCreateShader(GL_VERTEX_SHADER);
1270			GLuint shaderFrag = glCreateShader(GL_FRAGMENT_SHADER);
1271
1272			glShaderSource(shaderVert, 1, &commonTestVertSource, DE_NULL);
1273			glShaderSource(shaderFrag, 1, &commonTestFragSource, DE_NULL);
1274
1275			glCompileShader(shaderVert);
1276			glCompileShader(shaderFrag);
1277			expectError(GL_NO_ERROR);
1278
1279			GLuint program = glCreateProgram();
1280			glAttachShader(program, shaderVert);
1281			glAttachShader(program, shaderFrag);
1282			glLinkProgram(program);
1283			expectError(GL_NO_ERROR);
1284
1285			verifyShaderParam	(m_testCtx, *this, shaderVert,	GL_COMPILE_STATUS,	GL_TRUE);
1286			verifyShaderParam	(m_testCtx, *this, shaderFrag,	GL_COMPILE_STATUS,	GL_TRUE);
1287			verifyProgramParam	(m_testCtx, *this, program,		GL_LINK_STATUS,		GL_TRUE);
1288
1289			glValidateProgram(program);
1290			verifyProgramParam(m_testCtx, *this, program, GL_VALIDATE_STATUS, GL_TRUE);
1291
1292			glDeleteShader(shaderVert);
1293			glDeleteShader(shaderFrag);
1294			glDeleteProgram(program);
1295			expectError(GL_NO_ERROR);
1296		}
1297
1298		// test with broken shader
1299		{
1300			GLuint shaderVert = glCreateShader(GL_VERTEX_SHADER);
1301			GLuint shaderFrag = glCreateShader(GL_FRAGMENT_SHADER);
1302
1303			glShaderSource(shaderVert, 1, &commonTestVertSource,	DE_NULL);
1304			glShaderSource(shaderFrag, 1, &brokenShader,			DE_NULL);
1305
1306			glCompileShader(shaderVert);
1307			glCompileShader(shaderFrag);
1308			expectError(GL_NO_ERROR);
1309
1310			GLuint program = glCreateProgram();
1311			glAttachShader(program, shaderVert);
1312			glAttachShader(program, shaderFrag);
1313			glLinkProgram(program);
1314			expectError(GL_NO_ERROR);
1315
1316			verifyShaderParam	(m_testCtx, *this, shaderVert,	GL_COMPILE_STATUS,	GL_TRUE);
1317			verifyShaderParam	(m_testCtx, *this, shaderFrag,	GL_COMPILE_STATUS,	GL_FALSE);
1318			verifyProgramParam	(m_testCtx, *this, program,		GL_LINK_STATUS,		GL_FALSE);
1319
1320			glValidateProgram(program);
1321			verifyProgramParam(m_testCtx, *this, program, GL_VALIDATE_STATUS, GL_FALSE);
1322
1323			glDeleteShader(shaderVert);
1324			glDeleteShader(shaderFrag);
1325			glDeleteProgram(program);
1326			expectError(GL_NO_ERROR);
1327		}
1328	}
1329};
1330
1331class ProgramAttachedShadersCase : public ApiCase
1332{
1333public:
1334	ProgramAttachedShadersCase (Context& context, const char* name, const char* description)
1335		: ApiCase(context, name, description)
1336	{
1337	}
1338
1339	void test (void)
1340	{
1341		using tcu::TestLog;
1342
1343		GLuint shaderVert = glCreateShader(GL_VERTEX_SHADER);
1344		GLuint shaderFrag = glCreateShader(GL_FRAGMENT_SHADER);
1345
1346		glShaderSource(shaderVert, 1, &commonTestVertSource, DE_NULL);
1347		glShaderSource(shaderFrag, 1, &commonTestFragSource, DE_NULL);
1348
1349		glCompileShader(shaderVert);
1350		glCompileShader(shaderFrag);
1351		expectError(GL_NO_ERROR);
1352
1353		// check ATTACHED_SHADERS
1354
1355		GLuint program = glCreateProgram();
1356		verifyProgramParam(m_testCtx, *this, program, GL_ATTACHED_SHADERS, 0);
1357		expectError(GL_NO_ERROR);
1358
1359		glAttachShader(program, shaderVert);
1360		verifyProgramParam(m_testCtx, *this, program, GL_ATTACHED_SHADERS, 1);
1361		expectError(GL_NO_ERROR);
1362
1363		glAttachShader(program, shaderFrag);
1364		verifyProgramParam(m_testCtx, *this, program, GL_ATTACHED_SHADERS, 2);
1365		expectError(GL_NO_ERROR);
1366
1367		// check GetAttachedShaders
1368		{
1369			GLuint shaders[2] = {0, 0};
1370			GLint count = 0;
1371			glGetAttachedShaders(program, DE_LENGTH_OF_ARRAY(shaders), &count, shaders);
1372
1373			if (count != 2)
1374			{
1375				m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected 2; got " << count << TestLog::EndMessage;
1376				if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
1377					m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got wrong shader count");
1378			}
1379			// shaders are the attached shaders?
1380			if (!((shaders[0] == shaderVert && shaders[1] == shaderFrag) ||
1381				  (shaders[0] == shaderFrag && shaders[1] == shaderVert)))
1382			{
1383				m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected {" << shaderVert << ", " << shaderFrag << "}; got {" << shaders[0] << ", " << shaders[1] << "}" << TestLog::EndMessage;
1384				if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
1385					m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got wrong shader count");
1386			}
1387		}
1388
1389		// check GetAttachedShaders with too small buffer
1390		{
1391			GLuint shaders[2] = {0, 0};
1392			GLint count = 0;
1393
1394			glGetAttachedShaders(program, 0, &count, shaders);
1395			if (count != 0)
1396			{
1397				m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected 0; got " << count << TestLog::EndMessage;
1398				if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
1399					m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got wrong shader count");
1400			}
1401
1402			count = 0;
1403			glGetAttachedShaders(program, 1, &count, shaders);
1404			if (count != 1)
1405			{
1406				m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected 1; got " << count << TestLog::EndMessage;
1407				if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
1408					m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got wrong shader count");
1409			}
1410		}
1411
1412		glDeleteShader(shaderVert);
1413		glDeleteShader(shaderFrag);
1414		glDeleteProgram(program);
1415		expectError(GL_NO_ERROR);
1416	}
1417};
1418
1419class ProgramActiveUniformNameCase : public ApiCase
1420{
1421public:
1422	ProgramActiveUniformNameCase (Context& context, const char* name, const char* description)
1423		: ApiCase(context, name, description)
1424	{
1425	}
1426
1427	void test (void)
1428	{
1429		using tcu::TestLog;
1430
1431		static const char* testVertSource =
1432			"#version 300 es\n"
1433			"uniform highp float uniformNameWithLength23;\n"
1434			"uniform highp vec2 uniformVec2;\n"
1435			"uniform highp mat4 uniformMat4;\n"
1436			"void main (void)\n"
1437			"{\n"
1438			"	gl_Position = vec4(0.0) + vec4(uniformNameWithLength23) + vec4(uniformVec2.x) + vec4(uniformMat4[2][3]);\n"
1439			"}\n\0";
1440		static const char* testFragSource =
1441			"#version 300 es\n"
1442			"layout(location = 0) out mediump vec4 fragColor;"
1443			"void main (void)\n"
1444			"{\n"
1445			"	fragColor = vec4(0.0);\n"
1446			"}\n\0";
1447
1448		GLuint shaderVert = glCreateShader(GL_VERTEX_SHADER);
1449		GLuint shaderFrag = glCreateShader(GL_FRAGMENT_SHADER);
1450
1451		glShaderSource(shaderVert, 1, &testVertSource, DE_NULL);
1452		glShaderSource(shaderFrag, 1, &testFragSource, DE_NULL);
1453
1454		glCompileShader(shaderVert);
1455		glCompileShader(shaderFrag);
1456		expectError(GL_NO_ERROR);
1457
1458		GLuint program = glCreateProgram();
1459		glAttachShader(program, shaderVert);
1460		glAttachShader(program, shaderFrag);
1461		glLinkProgram(program);
1462		expectError(GL_NO_ERROR);
1463
1464		verifyProgramParam(m_testCtx, *this, program, GL_ACTIVE_UNIFORMS, 3);
1465		verifyProgramParam(m_testCtx, *this, program, GL_ACTIVE_UNIFORM_MAX_LENGTH, (GLint)std::string("uniformNameWithLength23").length() + 1); // including a null terminator
1466		expectError(GL_NO_ERROR);
1467
1468		const char* uniformNames[] =
1469		{
1470			"uniformNameWithLength23",
1471			"uniformVec2",
1472			"uniformMat4"
1473		};
1474		StateQueryMemoryWriteGuard<GLuint[DE_LENGTH_OF_ARRAY(uniformNames)]> uniformIndices;
1475		glGetUniformIndices(program, DE_LENGTH_OF_ARRAY(uniformNames), uniformNames, uniformIndices);
1476		uniformIndices.verifyValidity(m_testCtx);
1477
1478		// check name lengths
1479		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(uniformNames); ++ndx)
1480		{
1481			const GLuint uniformIndex = uniformIndices[ndx];
1482
1483			StateQueryMemoryWriteGuard<GLint> uniformNameLen;
1484			glGetActiveUniformsiv(program, 1, &uniformIndex, GL_UNIFORM_NAME_LENGTH, &uniformNameLen);
1485
1486			uniformNameLen.verifyValidity(m_testCtx);
1487
1488			const GLint referenceLength = (GLint)std::string(uniformNames[ndx]).length() + 1;
1489			if (referenceLength != uniformNameLen) // uniformNameLen is with null terminator
1490			{
1491				m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected " << referenceLength << "got " << uniformNameLen << TestLog::EndMessage;
1492				if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
1493					m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got wrong uniform name length");
1494			}
1495		}
1496
1497		// check names
1498		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(uniformNames); ++ndx)
1499		{
1500			char buffer[2048] = {'x'};
1501
1502			const GLuint uniformIndex = uniformIndices[ndx];
1503
1504			GLint written = 0; // null terminator not included
1505			GLint size = 0;
1506			GLenum type = 0;
1507			glGetActiveUniform(program, uniformIndex, DE_LENGTH_OF_ARRAY(buffer), &written, &size, &type, buffer);
1508
1509			const GLint referenceLength = (GLint)std::string(uniformNames[ndx]).length();
1510			if (referenceLength != written)
1511			{
1512				m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected " << referenceLength << "got " << written << TestLog::EndMessage;
1513				if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
1514					m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got wrong uniform name length");
1515			}
1516
1517			// and with too small buffer
1518			written = 0;
1519			glGetActiveUniform(program, uniformIndex, 1, &written, &size, &type, buffer);
1520
1521			if (written != 0)
1522			{
1523				m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected 0 got " << written << TestLog::EndMessage;
1524				if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
1525					m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got wrong uniform name length");
1526			}
1527		}
1528
1529
1530		glDeleteShader(shaderVert);
1531		glDeleteShader(shaderFrag);
1532		glDeleteProgram(program);
1533		expectError(GL_NO_ERROR);
1534	}
1535};
1536
1537class ProgramUniformCase : public ApiCase
1538{
1539public:
1540	ProgramUniformCase (Context& context, const char* name, const char* description)
1541		: ApiCase(context, name, description)
1542	{
1543	}
1544
1545	void test (void)
1546	{
1547		const struct UniformType
1548		{
1549			const char* declaration;
1550			const char* postDeclaration;
1551			const char* precision;
1552			const char* layout;
1553			const char* getter;
1554			GLenum		type;
1555			GLint		size;
1556			GLint		isRowMajor;
1557		} uniformTypes[] =
1558		{
1559			{ "float",					"",			"highp",	"",						"uniformValue",							GL_FLOAT,							1, GL_FALSE },
1560			{ "float[2]",				"",			"highp",	"",						"uniformValue[1]",						GL_FLOAT,							2, GL_FALSE },
1561			{ "vec2",					"",			"highp",	"",						"uniformValue.x",						GL_FLOAT_VEC2,						1, GL_FALSE },
1562			{ "vec3",					"",			"highp",	"",						"uniformValue.x",						GL_FLOAT_VEC3,						1, GL_FALSE },
1563			{ "vec4",					"",			"highp",	"",						"uniformValue.x",						GL_FLOAT_VEC4,						1, GL_FALSE },
1564			{ "int",					"",			"highp",	"",						"float(uniformValue)",					GL_INT,								1, GL_FALSE },
1565			{ "ivec2",					"",			"highp",	"",						"float(uniformValue.x)",				GL_INT_VEC2,						1, GL_FALSE },
1566			{ "ivec3",					"",			"highp",	"",						"float(uniformValue.x)",				GL_INT_VEC3,						1, GL_FALSE },
1567			{ "ivec4",					"",			"highp",	"",						"float(uniformValue.x)",				GL_INT_VEC4,						1, GL_FALSE },
1568			{ "uint",					"",			"highp",	"",						"float(uniformValue)",					GL_UNSIGNED_INT,					1, GL_FALSE },
1569			{ "uvec2",					"",			"highp",	"",						"float(uniformValue.x)",				GL_UNSIGNED_INT_VEC2,				1, GL_FALSE },
1570			{ "uvec3",					"",			"highp",	"",						"float(uniformValue.x)",				GL_UNSIGNED_INT_VEC3,				1, GL_FALSE },
1571			{ "uvec4",					"",			"highp",	"",						"float(uniformValue.x)",				GL_UNSIGNED_INT_VEC4,				1, GL_FALSE },
1572			{ "bool",					"",			"",			"",						"float(uniformValue)",					GL_BOOL,							1, GL_FALSE },
1573			{ "bvec2",					"",			"",			"",						"float(uniformValue.x)",				GL_BOOL_VEC2,						1, GL_FALSE },
1574			{ "bvec3",					"",			"",			"",						"float(uniformValue.x)",				GL_BOOL_VEC3,						1, GL_FALSE },
1575			{ "bvec4",					"",			"",			"",						"float(uniformValue.x)",				GL_BOOL_VEC4,						1, GL_FALSE },
1576			{ "mat2",					"",			"highp",	"",						"float(uniformValue[0][0])",			GL_FLOAT_MAT2,						1, GL_FALSE },
1577			{ "mat3",					"",			"highp",	"",						"float(uniformValue[0][0])",			GL_FLOAT_MAT3,						1, GL_FALSE },
1578			{ "mat4",					"",			"highp",	"",						"float(uniformValue[0][0])",			GL_FLOAT_MAT4,						1, GL_FALSE },
1579			{ "mat2x3",					"",			"highp",	"",						"float(uniformValue[0][0])",			GL_FLOAT_MAT2x3,					1, GL_FALSE },
1580			{ "mat2x4",					"",			"highp",	"",						"float(uniformValue[0][0])",			GL_FLOAT_MAT2x4,					1, GL_FALSE },
1581			{ "mat3x2",					"",			"highp",	"",						"float(uniformValue[0][0])",			GL_FLOAT_MAT3x2,					1, GL_FALSE },
1582			{ "mat3x4",					"",			"highp",	"",						"float(uniformValue[0][0])",			GL_FLOAT_MAT3x4,					1, GL_FALSE },
1583			{ "mat4x2",					"",			"highp",	"",						"float(uniformValue[0][0])",			GL_FLOAT_MAT4x2,					1, GL_FALSE },
1584			{ "mat4x3",					"",			"highp",	"",						"float(uniformValue[0][0])",			GL_FLOAT_MAT4x3,					1, GL_FALSE },
1585			{ "sampler2D",				"",			"highp",	"",						"float(textureSize(uniformValue,0).r)",	GL_SAMPLER_2D,						1, GL_FALSE },
1586			{ "sampler3D",				"",			"highp",	"",						"float(textureSize(uniformValue,0).r)",	GL_SAMPLER_3D,						1, GL_FALSE },
1587			{ "samplerCube",			"",			"highp",	"",						"float(textureSize(uniformValue,0).r)",	GL_SAMPLER_CUBE,					1, GL_FALSE },
1588			{ "sampler2DShadow",		"",			"highp",	"",						"float(textureSize(uniformValue,0).r)",	GL_SAMPLER_2D_SHADOW,				1, GL_FALSE },
1589			{ "sampler2DArray",			"",			"highp",	"",						"float(textureSize(uniformValue,0).r)",	GL_SAMPLER_2D_ARRAY,				1, GL_FALSE },
1590			{ "sampler2DArrayShadow",	"",			"highp",	"",						"float(textureSize(uniformValue,0).r)",	GL_SAMPLER_2D_ARRAY_SHADOW,			1, GL_FALSE },
1591			{ "samplerCubeShadow",		"",			"highp",	"",						"float(textureSize(uniformValue,0).r)",	GL_SAMPLER_CUBE_SHADOW,				1, GL_FALSE },
1592			{ "isampler2D",				"",			"highp",	"",						"float(textureSize(uniformValue,0).r)",	GL_INT_SAMPLER_2D,					1, GL_FALSE },
1593			{ "isampler3D",				"",			"highp",	"",						"float(textureSize(uniformValue,0).r)",	GL_INT_SAMPLER_3D,					1, GL_FALSE },
1594			{ "isamplerCube",			"",			"highp",	"",						"float(textureSize(uniformValue,0).r)",	GL_INT_SAMPLER_CUBE,				1, GL_FALSE },
1595			{ "isampler2DArray",		"",			"highp",	"",						"float(textureSize(uniformValue,0).r)",	GL_INT_SAMPLER_2D_ARRAY,			1, GL_FALSE },
1596			{ "usampler2D",				"",			"highp",	"",						"float(textureSize(uniformValue,0).r)",	GL_UNSIGNED_INT_SAMPLER_2D,			1, GL_FALSE },
1597			{ "usampler3D",				"",			"highp",	"",						"float(textureSize(uniformValue,0).r)",	GL_UNSIGNED_INT_SAMPLER_3D,			1, GL_FALSE },
1598			{ "usamplerCube",			"",			"highp",	"",						"float(textureSize(uniformValue,0).r)",	GL_UNSIGNED_INT_SAMPLER_CUBE,		1, GL_FALSE },
1599			{ "usampler2DArray",		"",			"highp",	"",						"float(textureSize(uniformValue,0).r)",	GL_UNSIGNED_INT_SAMPLER_2D_ARRAY,	1, GL_FALSE },
1600		};
1601
1602		static const char* vertSource =
1603			"#version 300 es\n"
1604			"void main (void)\n"
1605			"{\n"
1606			"	gl_Position = vec4(0.0);\n"
1607			"}\n\0";
1608
1609		GLuint shaderVert	= glCreateShader(GL_VERTEX_SHADER);
1610		GLuint shaderFrag	= glCreateShader(GL_FRAGMENT_SHADER);
1611		GLuint program		= glCreateProgram();
1612
1613		glAttachShader(program, shaderVert);
1614		glAttachShader(program, shaderFrag);
1615
1616		glShaderSource(shaderVert, 1, &vertSource, DE_NULL);
1617		glCompileShader(shaderVert);
1618		expectError(GL_NO_ERROR);
1619
1620		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(uniformTypes); ++ndx)
1621		{
1622			tcu::ScopedLogSection(m_log, uniformTypes[ndx].declaration, std::string("Verify type of ") + uniformTypes[ndx].declaration + " variable" + uniformTypes[ndx].postDeclaration );
1623
1624			// gen fragment shader
1625
1626			std::ostringstream frag;
1627			frag << "#version 300 es\n";
1628			frag << uniformTypes[ndx].layout << "uniform " << uniformTypes[ndx].precision << " " << uniformTypes[ndx].declaration << " uniformValue" << uniformTypes[ndx].postDeclaration << ";\n";
1629			frag << "layout(location = 0) out mediump vec4 fragColor;\n";
1630			frag << "void main (void)\n";
1631			frag << "{\n";
1632			frag << "	fragColor = vec4(" << uniformTypes[ndx].getter << ");\n";
1633			frag << "}\n";
1634
1635			{
1636				std::string fragmentSource = frag.str();
1637				const char* fragmentSourceCStr = fragmentSource.c_str();
1638				glShaderSource(shaderFrag, 1, &fragmentSourceCStr, DE_NULL);
1639			}
1640
1641			// compile & link
1642
1643			glCompileShader(shaderFrag);
1644			glLinkProgram(program);
1645
1646			// test
1647			if (verifyProgramParam(m_testCtx, *this, program, GL_LINK_STATUS, GL_TRUE))
1648			{
1649				const char* uniformNames[] = {"uniformValue"};
1650				StateQueryMemoryWriteGuard<GLuint> uniformIndex;
1651				glGetUniformIndices(program, 1, uniformNames, &uniformIndex);
1652				uniformIndex.verifyValidity(m_testCtx);
1653
1654				verifyActiveUniformParam(m_testCtx, *this, program, uniformIndex, GL_UNIFORM_TYPE,			uniformTypes[ndx].type);
1655				verifyActiveUniformParam(m_testCtx, *this, program, uniformIndex, GL_UNIFORM_SIZE,			uniformTypes[ndx].size);
1656				verifyActiveUniformParam(m_testCtx, *this, program, uniformIndex, GL_UNIFORM_IS_ROW_MAJOR,	uniformTypes[ndx].isRowMajor);
1657			}
1658		}
1659
1660		glDeleteShader(shaderVert);
1661		glDeleteShader(shaderFrag);
1662		glDeleteProgram(program);
1663		expectError(GL_NO_ERROR);
1664	}
1665};
1666
1667class ProgramActiveUniformBlocksCase : public ApiCase
1668{
1669public:
1670	ProgramActiveUniformBlocksCase (Context& context, const char* name, const char* description)
1671		: ApiCase(context, name, description)
1672	{
1673	}
1674
1675	void test (void)
1676	{
1677		using tcu::TestLog;
1678
1679		static const char* testVertSource =
1680			"#version 300 es\n"
1681			"uniform longlongUniformBlockName {highp vec2 vector2;} longlongUniformInstanceName;\n"
1682			"uniform shortUniformBlockName {highp vec2 vector2;highp vec4 vector4;} shortUniformInstanceName;\n"
1683			"void main (void)\n"
1684			"{\n"
1685			"	gl_Position = shortUniformInstanceName.vector4 + vec4(longlongUniformInstanceName.vector2.x) + vec4(shortUniformInstanceName.vector2.x);\n"
1686			"}\n\0";
1687		static const char* testFragSource =
1688			"#version 300 es\n"
1689			"uniform longlongUniformBlockName {highp vec2 vector2;} longlongUniformInstanceName;\n"
1690			"layout(location = 0) out mediump vec4 fragColor;"
1691			"void main (void)\n"
1692			"{\n"
1693			"	fragColor = vec4(longlongUniformInstanceName.vector2.y);\n"
1694			"}\n\0";
1695
1696		GLuint shaderVert = glCreateShader(GL_VERTEX_SHADER);
1697		GLuint shaderFrag = glCreateShader(GL_FRAGMENT_SHADER);
1698
1699		glShaderSource(shaderVert, 1, &testVertSource, DE_NULL);
1700		glShaderSource(shaderFrag, 1, &testFragSource, DE_NULL);
1701
1702		glCompileShader(shaderVert);
1703		glCompileShader(shaderFrag);
1704		expectError(GL_NO_ERROR);
1705
1706		GLuint program = glCreateProgram();
1707		glAttachShader(program, shaderVert);
1708		glAttachShader(program, shaderFrag);
1709		glLinkProgram(program);
1710		expectError(GL_NO_ERROR);
1711
1712		verifyShaderParam	(m_testCtx, *this, shaderVert,	GL_COMPILE_STATUS,	GL_TRUE);
1713		verifyShaderParam	(m_testCtx, *this, shaderFrag,	GL_COMPILE_STATUS,	GL_TRUE);
1714		verifyProgramParam	(m_testCtx, *this, program,		GL_LINK_STATUS,		GL_TRUE);
1715
1716		verifyProgramParam	(m_testCtx, *this, program,		GL_ACTIVE_UNIFORM_BLOCKS, 2);
1717		verifyProgramParam	(m_testCtx, *this, program,		GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH, (GLint)std::string("longlongUniformBlockName").length() + 1); // including a null terminator
1718		expectError(GL_NO_ERROR);
1719
1720		GLint longlongUniformBlockIndex	= glGetUniformBlockIndex(program, "longlongUniformBlockName");
1721		GLint shortUniformBlockIndex	= glGetUniformBlockIndex(program, "shortUniformBlockName");
1722
1723		const char* uniformNames[] =
1724		{
1725			"longlongUniformBlockName.vector2",
1726			"shortUniformBlockName.vector2",
1727			"shortUniformBlockName.vector4"
1728		};
1729
1730		// test UNIFORM_BLOCK_INDEX
1731
1732		DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(uniformNames) == 3);
1733
1734		StateQueryMemoryWriteGuard<GLuint[DE_LENGTH_OF_ARRAY(uniformNames)]> uniformIndices;
1735		StateQueryMemoryWriteGuard<GLint[DE_LENGTH_OF_ARRAY(uniformNames)]> uniformsBlockIndices;
1736
1737		glGetUniformIndices(program, DE_LENGTH_OF_ARRAY(uniformNames), uniformNames, uniformIndices);
1738		uniformIndices.verifyValidity(m_testCtx);
1739		expectError(GL_NO_ERROR);
1740
1741		glGetActiveUniformsiv(program, DE_LENGTH_OF_ARRAY(uniformNames), uniformIndices, GL_UNIFORM_BLOCK_INDEX, uniformsBlockIndices);
1742		uniformsBlockIndices.verifyValidity(m_testCtx);
1743		expectError(GL_NO_ERROR);
1744
1745		if (uniformsBlockIndices[0] != longlongUniformBlockIndex ||
1746			uniformsBlockIndices[1] != shortUniformBlockIndex ||
1747			uniformsBlockIndices[2] != shortUniformBlockIndex)
1748		{
1749			m_testCtx.getLog() << TestLog::Message
1750				<< "// ERROR: Expected ["	<< longlongUniformBlockIndex	<< ", " << shortUniformBlockIndex	<< ", " << shortUniformBlockIndex	<< "];"
1751				<<	"got ["					<< uniformsBlockIndices[0]		<< ", " << uniformsBlockIndices[1]	<< ", " << uniformsBlockIndices[2]	<< "]" << TestLog::EndMessage;
1752			if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
1753				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got wrong uniform block index");
1754		}
1755
1756		// test UNIFORM_BLOCK_NAME_LENGTH
1757
1758		verifyActiveUniformBlockParam(m_testCtx, *this, program, longlongUniformBlockIndex,	GL_UNIFORM_BLOCK_NAME_LENGTH, (GLint)std::string("longlongUniformBlockName").length() + 1); // including null-terminator
1759		verifyActiveUniformBlockParam(m_testCtx, *this, program, shortUniformBlockIndex,	GL_UNIFORM_BLOCK_NAME_LENGTH, (GLint)std::string("shortUniformBlockName").length() + 1); // including null-terminator
1760		expectError(GL_NO_ERROR);
1761
1762		// test UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER & UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER
1763
1764		verifyActiveUniformBlockParam(m_testCtx, *this, program, longlongUniformBlockIndex,	GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER,	GL_TRUE);
1765		verifyActiveUniformBlockParam(m_testCtx, *this, program, longlongUniformBlockIndex,	GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER,	GL_TRUE);
1766		verifyActiveUniformBlockParam(m_testCtx, *this, program, shortUniformBlockIndex,	GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER,	GL_TRUE);
1767		verifyActiveUniformBlockParam(m_testCtx, *this, program, shortUniformBlockIndex,	GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER,	GL_FALSE);
1768		expectError(GL_NO_ERROR);
1769
1770		// test UNIFORM_BLOCK_ACTIVE_UNIFORMS
1771
1772		verifyActiveUniformBlockParam(m_testCtx, *this, program, longlongUniformBlockIndex,	GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS,	1);
1773		verifyActiveUniformBlockParam(m_testCtx, *this, program, shortUniformBlockIndex,	GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS,	2);
1774		expectError(GL_NO_ERROR);
1775
1776		// test UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES
1777
1778		{
1779			StateQueryMemoryWriteGuard<GLint> longlongUniformBlockUniforms;
1780			glGetActiveUniformBlockiv(program, longlongUniformBlockIndex, GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, &longlongUniformBlockUniforms);
1781			longlongUniformBlockUniforms.verifyValidity(m_testCtx);
1782
1783			if (longlongUniformBlockUniforms == 2)
1784			{
1785				StateQueryMemoryWriteGuard<GLint[2]> longlongUniformBlockUniformIndices;
1786				glGetActiveUniformBlockiv(program, longlongUniformBlockIndex, GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES, longlongUniformBlockUniformIndices);
1787				longlongUniformBlockUniformIndices.verifyValidity(m_testCtx);
1788
1789				if ((GLuint(longlongUniformBlockUniformIndices[0]) != uniformIndices[0] || GLuint(longlongUniformBlockUniformIndices[1]) != uniformIndices[1]) &&
1790					(GLuint(longlongUniformBlockUniformIndices[1]) != uniformIndices[0] || GLuint(longlongUniformBlockUniformIndices[0]) != uniformIndices[1]))
1791				{
1792					m_testCtx.getLog() << TestLog::Message
1793						<< "// ERROR: Expected {"	<< uniformIndices[0]						<< ", " << uniformIndices[1] << "};"
1794						<<	"got {"					<< longlongUniformBlockUniformIndices[0]	<< ", " << longlongUniformBlockUniformIndices[1] << "}" << TestLog::EndMessage;
1795
1796					if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
1797						m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got wrong uniform indices");
1798				}
1799
1800			}
1801		}
1802
1803		// check block names
1804
1805		{
1806			char buffer[2048] = {'x'};
1807			GLint written = 0;
1808			glGetActiveUniformBlockName(program, longlongUniformBlockIndex, DE_LENGTH_OF_ARRAY(buffer), &written, buffer);
1809			checkIntEquals(m_testCtx, written, (GLint)std::string("longlongUniformBlockName").length());
1810
1811			written = 0;
1812			glGetActiveUniformBlockName(program, shortUniformBlockIndex, DE_LENGTH_OF_ARRAY(buffer), &written, buffer);
1813			checkIntEquals(m_testCtx, written, (GLint)std::string("shortUniformBlockName").length());
1814
1815			// and one with too small buffer
1816			written = 0;
1817			glGetActiveUniformBlockName(program, longlongUniformBlockIndex, 1, &written, buffer);
1818			checkIntEquals(m_testCtx, written, 0);
1819		}
1820
1821		expectError(GL_NO_ERROR);
1822		glDeleteShader(shaderVert);
1823		glDeleteShader(shaderFrag);
1824		glDeleteProgram(program);
1825		expectError(GL_NO_ERROR);
1826	}
1827};
1828
1829class ProgramBinaryCase : public ApiCase
1830{
1831public:
1832	ProgramBinaryCase (Context& context, const char* name, const char* description)
1833		: ApiCase(context, name, description)
1834	{
1835	}
1836
1837	void test (void)
1838	{
1839		using tcu::TestLog;
1840
1841		GLuint shaderVert = glCreateShader(GL_VERTEX_SHADER);
1842		GLuint shaderFrag = glCreateShader(GL_FRAGMENT_SHADER);
1843
1844		glShaderSource(shaderVert, 1, &commonTestVertSource, DE_NULL);
1845		glShaderSource(shaderFrag, 1, &commonTestFragSource, DE_NULL);
1846
1847		glCompileShader(shaderVert);
1848		glCompileShader(shaderFrag);
1849		expectError(GL_NO_ERROR);
1850
1851		GLuint program = glCreateProgram();
1852		glAttachShader(program, shaderVert);
1853		glAttachShader(program, shaderFrag);
1854		glLinkProgram(program);
1855		expectError(GL_NO_ERROR);
1856
1857		// test PROGRAM_BINARY_RETRIEVABLE_HINT
1858		verifyProgramParam(m_testCtx, *this, program, GL_PROGRAM_BINARY_RETRIEVABLE_HINT, GL_FALSE);
1859
1860		glProgramParameteri(program, GL_PROGRAM_BINARY_RETRIEVABLE_HINT, GL_TRUE);
1861		expectError(GL_NO_ERROR);
1862
1863		glLinkProgram(program);
1864		expectError(GL_NO_ERROR);
1865
1866		verifyProgramParam(m_testCtx, *this, program, GL_PROGRAM_BINARY_RETRIEVABLE_HINT, GL_TRUE);
1867
1868		// test PROGRAM_BINARY_LENGTH does something
1869
1870		StateQueryMemoryWriteGuard<GLint> programLength;
1871		glGetProgramiv(program, GL_PROGRAM_BINARY_LENGTH, &programLength);
1872		expectError(GL_NO_ERROR);
1873		programLength.verifyValidity(m_testCtx);
1874
1875		glDeleteShader(shaderVert);
1876		glDeleteShader(shaderFrag);
1877		glDeleteProgram(program);
1878		expectError(GL_NO_ERROR);
1879	}
1880};
1881
1882class TransformFeedbackCase : public ApiCase
1883{
1884public:
1885	TransformFeedbackCase (Context& context, const char* name, const char* description)
1886		: ApiCase(context, name, description)
1887	{
1888	}
1889
1890	void test (void)
1891	{
1892		using tcu::TestLog;
1893
1894		static const char* transformFeedbackTestVertSource =
1895			"#version 300 es\n"
1896			"out highp vec4 tfOutput2withLongName;\n"
1897			"void main (void)\n"
1898			"{\n"
1899			"	gl_Position = vec4(0.0);\n"
1900			"	tfOutput2withLongName = vec4(0.0);\n"
1901			"}\n";
1902		static const char* transformFeedbackTestFragSource =
1903			"#version 300 es\n"
1904			"layout(location = 0) out highp vec4 fragColor;\n"
1905			"void main (void)\n"
1906			"{\n"
1907			"	fragColor = vec4(0.0);\n"
1908			"}\n";
1909
1910		GLuint shaderVert = glCreateShader(GL_VERTEX_SHADER);
1911		GLuint shaderFrag = glCreateShader(GL_FRAGMENT_SHADER);
1912		GLuint shaderProg = glCreateProgram();
1913
1914		verifyProgramParam(m_testCtx, *this, shaderProg, GL_TRANSFORM_FEEDBACK_BUFFER_MODE, GL_INTERLEAVED_ATTRIBS);
1915
1916		glShaderSource(shaderVert, 1, &transformFeedbackTestVertSource, DE_NULL);
1917		glShaderSource(shaderFrag, 1, &transformFeedbackTestFragSource, DE_NULL);
1918
1919		glCompileShader(shaderVert);
1920		glCompileShader(shaderFrag);
1921
1922		verifyShaderParam(m_testCtx, *this, shaderVert, GL_COMPILE_STATUS, GL_TRUE);
1923		verifyShaderParam(m_testCtx, *this, shaderFrag, GL_COMPILE_STATUS, GL_TRUE);
1924
1925		glAttachShader(shaderProg, shaderVert);
1926		glAttachShader(shaderProg, shaderFrag);
1927
1928		// check TRANSFORM_FEEDBACK_BUFFER_MODE
1929
1930		const char* transform_feedback_outputs[] = {"gl_Position", "tfOutput2withLongName"};
1931		const char* longest_output = transform_feedback_outputs[1];
1932		const GLenum bufferModes[] = {GL_SEPARATE_ATTRIBS, GL_INTERLEAVED_ATTRIBS};
1933
1934		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(bufferModes); ++ndx)
1935		{
1936			glTransformFeedbackVaryings(shaderProg, DE_LENGTH_OF_ARRAY(transform_feedback_outputs), transform_feedback_outputs, bufferModes[ndx]);
1937			glLinkProgram(shaderProg);
1938			expectError(GL_NO_ERROR);
1939
1940			verifyProgramParam(m_testCtx, *this, shaderProg, GL_LINK_STATUS, GL_TRUE);
1941			verifyProgramParam(m_testCtx, *this, shaderProg, GL_TRANSFORM_FEEDBACK_BUFFER_MODE, bufferModes[ndx]);
1942		}
1943
1944		// TRANSFORM_FEEDBACK_VARYINGS
1945		verifyProgramParam(m_testCtx, *this, shaderProg, GL_TRANSFORM_FEEDBACK_VARYINGS, 2);
1946
1947		// TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH
1948		{
1949			StateQueryMemoryWriteGuard<GLint> maxOutputLen;
1950			glGetProgramiv(shaderProg, GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH, &maxOutputLen);
1951
1952			maxOutputLen.verifyValidity(m_testCtx);
1953
1954			const GLint referenceLength = (GLint)std::string(longest_output).length() + 1;
1955			checkIntEquals(m_testCtx, maxOutputLen, referenceLength);
1956		}
1957
1958		// check varyings
1959		{
1960			StateQueryMemoryWriteGuard<GLint> varyings;
1961			glGetProgramiv(shaderProg, GL_TRANSFORM_FEEDBACK_VARYINGS, &varyings);
1962
1963			if (!varyings.isUndefined())
1964				for (int index = 0; index < varyings; ++index)
1965				{
1966					char buffer[2048] = {'x'};
1967
1968					GLint written = 0;
1969					GLint size = 0;
1970					GLenum type = 0;
1971					glGetTransformFeedbackVarying(shaderProg, index, DE_LENGTH_OF_ARRAY(buffer), &written, &size, &type, buffer);
1972
1973					if (written < DE_LENGTH_OF_ARRAY(buffer) && buffer[written] != '\0')
1974					{
1975						m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected null terminator" << TestLog::EndMessage;
1976						if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
1977							m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid string terminator");
1978					}
1979
1980					// check with too small buffer
1981					written = 0;
1982					glGetTransformFeedbackVarying(shaderProg, index, 1, &written, &size, &type, buffer);
1983					if (written != 0)
1984					{
1985						m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected 0; got " << written << TestLog::EndMessage;
1986						if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
1987							m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid write length");
1988					}
1989				}
1990		}
1991
1992
1993		glDeleteShader(shaderVert);
1994		glDeleteShader(shaderFrag);
1995		glDeleteProgram(shaderProg);
1996		expectError(GL_NO_ERROR);
1997	}
1998};
1999
2000class ActiveAttributesCase : public ApiCase
2001{
2002public:
2003	ActiveAttributesCase (Context& context, const char* name, const char* description)
2004		: ApiCase(context, name, description)
2005	{
2006	}
2007
2008	void test (void)
2009	{
2010		using tcu::TestLog;
2011
2012		static const char* testVertSource =
2013			"#version 300 es\n"
2014			"in highp vec2 longInputAttributeName;\n"
2015			"in highp vec2 shortName;\n"
2016			"void main (void)\n"
2017			"{\n"
2018			"	gl_Position = longInputAttributeName.yxxy + shortName.xyxy;\n"
2019			"}\n\0";
2020		static const char* testFragSource =
2021			"#version 300 es\n"
2022			"layout(location = 0) out mediump vec4 fragColor;"
2023			"void main (void)\n"
2024			"{\n"
2025			"	fragColor = vec4(0.0);\n"
2026			"}\n\0";
2027
2028		GLuint shaderVert = glCreateShader(GL_VERTEX_SHADER);
2029		GLuint shaderFrag = glCreateShader(GL_FRAGMENT_SHADER);
2030
2031		glShaderSource(shaderVert, 1, &testVertSource, DE_NULL);
2032		glShaderSource(shaderFrag, 1, &testFragSource, DE_NULL);
2033
2034		glCompileShader(shaderVert);
2035		glCompileShader(shaderFrag);
2036		expectError(GL_NO_ERROR);
2037
2038		GLuint program = glCreateProgram();
2039		glAttachShader(program, shaderVert);
2040		glAttachShader(program, shaderFrag);
2041		glLinkProgram(program);
2042		expectError(GL_NO_ERROR);
2043
2044		verifyProgramParam(m_testCtx, *this, program, GL_ACTIVE_ATTRIBUTES, 2);
2045		verifyProgramParam(m_testCtx, *this, program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, (GLint)std::string("longInputAttributeName").length() + 1); // does include null-terminator
2046
2047		// check names
2048		for (int attributeNdx = 0; attributeNdx < 2; ++attributeNdx)
2049		{
2050			char buffer[2048] = {'x'};
2051
2052			GLint written = 0;
2053			GLint size = 0;
2054			GLenum type = 0;
2055			glGetActiveAttrib(program, attributeNdx, DE_LENGTH_OF_ARRAY(buffer), &written, &size, &type, buffer);
2056			expectError(GL_NO_ERROR);
2057
2058			if (deStringBeginsWith(buffer, "longInputAttributeName"))
2059			{
2060				checkIntEquals(m_testCtx, written, (GLint)std::string("longInputAttributeName").length()); // does NOT include null-terminator
2061			}
2062			else if (deStringBeginsWith(buffer, "shortName"))
2063			{
2064				checkIntEquals(m_testCtx, written, (GLint)std::string("shortName").length()); // does NOT include null-terminator
2065			}
2066			else
2067			{
2068				m_testCtx.getLog() << TestLog::Message << "// ERROR: Got unexpected attribute name." << TestLog::EndMessage;
2069				if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
2070					m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got unexpected name");
2071			}
2072		}
2073
2074		// and with too short buffer
2075		{
2076			char buffer[2048] = {'x'};
2077
2078			GLint written = 0;
2079			GLint size = 0;
2080			GLenum type = 0;
2081
2082			glGetActiveAttrib(program, 0, 1, &written, &size, &type, buffer);
2083			expectError(GL_NO_ERROR);
2084			checkIntEquals(m_testCtx, written, 0);
2085		}
2086
2087		glDeleteShader(shaderVert);
2088		glDeleteShader(shaderFrag);
2089		glDeleteProgram(program);
2090		expectError(GL_NO_ERROR);
2091	}
2092};
2093
2094struct PointerData
2095{
2096	GLint		size;
2097	GLenum		type;
2098	GLint		stride;
2099	GLboolean	normalized;
2100	const void*	pointer;
2101};
2102
2103class VertexAttributeSizeCase : public ApiCase
2104{
2105public:
2106	VertexAttributeSizeCase (Context& context, const char* name, const char* description)
2107		: ApiCase(context, name, description)
2108	{
2109	}
2110
2111	void test (void)
2112	{
2113		GLfloat vertexData[4] = {0.0f}; // never accessed
2114
2115		const PointerData pointers[] =
2116		{
2117			// size test
2118			{ 4, GL_FLOAT,		0,	GL_FALSE, vertexData },
2119			{ 3, GL_FLOAT,		0,	GL_FALSE, vertexData },
2120			{ 2, GL_FLOAT,		0,	GL_FALSE, vertexData },
2121			{ 1, GL_FLOAT,		0,	GL_FALSE, vertexData },
2122			{ 4, GL_INT,		0,	GL_FALSE, vertexData },
2123			{ 3, GL_INT,		0,	GL_FALSE, vertexData },
2124			{ 2, GL_INT,		0,	GL_FALSE, vertexData },
2125			{ 1, GL_INT,		0,	GL_FALSE, vertexData },
2126		};
2127
2128		// Test with default VAO
2129		{
2130			const tcu::ScopedLogSection section(m_log, "DefaultVAO", "Test with default VAO");
2131
2132			for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(pointers); ++ndx)
2133			{
2134				glVertexAttribPointer(0, pointers[ndx].size, pointers[ndx].type, pointers[ndx].normalized, pointers[ndx].stride, pointers[ndx].pointer);
2135				expectError(GL_NO_ERROR);
2136
2137				verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_SIZE, pointers[ndx].size);
2138			}
2139		}
2140
2141		// Test with multiple VAOs
2142		{
2143			const tcu::ScopedLogSection section(m_log, "WithVAO", "Test with VAO");
2144
2145			GLuint buf		= 0;
2146			GLuint vaos[2]	= {0};
2147
2148			glGenVertexArrays(2, vaos);
2149			glGenBuffers(1, &buf);
2150			glBindBuffer(GL_ARRAY_BUFFER, buf);
2151			expectError(GL_NO_ERROR);
2152
2153			// initial
2154			glBindVertexArray(vaos[0]);
2155			verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_SIZE, 4);
2156			expectError(GL_NO_ERROR);
2157
2158			// set vao 0 to some value
2159			glVertexAttribPointer(0, pointers[0].size, pointers[0].type, pointers[0].normalized, pointers[0].stride, DE_NULL);
2160			expectError(GL_NO_ERROR);
2161
2162			// set vao 1 to some other value
2163			glBindVertexArray(vaos[1]);
2164			glVertexAttribPointer(0, pointers[1].size, pointers[1].type, pointers[1].normalized, pointers[1].stride, DE_NULL);
2165			expectError(GL_NO_ERROR);
2166
2167			// verify vao 1 state
2168			verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_SIZE, pointers[1].size);
2169			expectError(GL_NO_ERROR);
2170
2171			// verify vao 0 state
2172			glBindVertexArray(vaos[0]);
2173			verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_SIZE, pointers[0].size);
2174			expectError(GL_NO_ERROR);
2175
2176			glDeleteVertexArrays(2, vaos);
2177			glDeleteBuffers(1, &buf);
2178			expectError(GL_NO_ERROR);
2179		}
2180	}
2181};
2182
2183class VertexAttributeTypeCase : public ApiCase
2184{
2185public:
2186	VertexAttributeTypeCase (Context& context, const char* name, const char* description)
2187		: ApiCase(context, name, description)
2188	{
2189	}
2190
2191	void test (void)
2192	{
2193		// Test with default VAO
2194		{
2195			const tcu::ScopedLogSection section(m_log, "DefaultVAO", "Test with default VAO");
2196
2197			const GLfloat vertexData[4] = {0.0f}; // never accessed
2198
2199			// test VertexAttribPointer
2200			{
2201				const PointerData pointers[] =
2202				{
2203					{ 1, GL_BYTE,								0,	GL_FALSE, vertexData	},
2204					{ 1, GL_SHORT,								0,	GL_FALSE, vertexData	},
2205					{ 1, GL_INT,								0,	GL_FALSE, vertexData	},
2206					{ 1, GL_FIXED,								0,	GL_FALSE, vertexData	},
2207					{ 1, GL_FLOAT,								0,	GL_FALSE, vertexData	},
2208					{ 1, GL_HALF_FLOAT,							0,	GL_FALSE, vertexData	},
2209					{ 1, GL_UNSIGNED_BYTE,						0,	GL_FALSE, vertexData	},
2210					{ 1, GL_UNSIGNED_SHORT,						0,	GL_FALSE, vertexData	},
2211					{ 1, GL_UNSIGNED_INT,						0,	GL_FALSE, vertexData	},
2212					{ 4, GL_INT_2_10_10_10_REV,					0,	GL_FALSE, vertexData	},
2213					{ 4, GL_UNSIGNED_INT_2_10_10_10_REV,		0,	GL_FALSE, vertexData	},
2214				};
2215
2216				for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(pointers); ++ndx)
2217				{
2218					glVertexAttribPointer(0, pointers[ndx].size, pointers[ndx].type, pointers[ndx].normalized, pointers[ndx].stride, pointers[ndx].pointer);
2219					expectError(GL_NO_ERROR);
2220
2221					verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_TYPE, pointers[ndx].type);
2222				}
2223			}
2224
2225			// test glVertexAttribIPointer
2226			{
2227				const PointerData pointers[] =
2228				{
2229					{ 1, GL_BYTE,								0,	GL_FALSE, vertexData	},
2230					{ 1, GL_SHORT,								0,	GL_FALSE, vertexData	},
2231					{ 1, GL_INT,								0,	GL_FALSE, vertexData	},
2232					{ 1, GL_UNSIGNED_BYTE,						0,	GL_FALSE, vertexData	},
2233					{ 1, GL_UNSIGNED_SHORT,						0,	GL_FALSE, vertexData	},
2234					{ 1, GL_UNSIGNED_INT,						0,	GL_FALSE, vertexData	},
2235				};
2236
2237				for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(pointers); ++ndx)
2238				{
2239					glVertexAttribIPointer(0, pointers[ndx].size, pointers[ndx].type, pointers[ndx].stride, pointers[ndx].pointer);
2240					expectError(GL_NO_ERROR);
2241
2242					verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_TYPE, pointers[ndx].type);
2243				}
2244			}
2245		}
2246
2247		// Test with multiple VAOs
2248		{
2249			const tcu::ScopedLogSection section(m_log, "WithVAO", "Test with VAO");
2250
2251			GLuint buf		= 0;
2252			GLuint vaos[2]	= {0};
2253
2254			glGenVertexArrays(2, vaos);
2255			glGenBuffers(1, &buf);
2256			glBindBuffer(GL_ARRAY_BUFFER, buf);
2257			expectError(GL_NO_ERROR);
2258
2259			// initial
2260			glBindVertexArray(vaos[0]);
2261			verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_TYPE, GL_FLOAT);
2262			expectError(GL_NO_ERROR);
2263
2264			// set vao 0 to some value
2265			glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, DE_NULL);
2266			expectError(GL_NO_ERROR);
2267
2268			// set vao 1 to some other value
2269			glBindVertexArray(vaos[1]);
2270			glVertexAttribPointer(0, 1, GL_SHORT, GL_FALSE, 0, DE_NULL);
2271			expectError(GL_NO_ERROR);
2272
2273			// verify vao 1 state
2274			verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_TYPE, GL_SHORT);
2275			expectError(GL_NO_ERROR);
2276
2277			// verify vao 0 state
2278			glBindVertexArray(vaos[0]);
2279			verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_TYPE, GL_FLOAT);
2280			expectError(GL_NO_ERROR);
2281
2282			glDeleteVertexArrays(2, vaos);
2283			glDeleteBuffers(1, &buf);
2284			expectError(GL_NO_ERROR);
2285		}
2286	}
2287};
2288
2289class VertexAttributeStrideCase : public ApiCase
2290{
2291public:
2292	VertexAttributeStrideCase (Context& context, const char* name, const char* description)
2293		: ApiCase(context, name, description)
2294	{
2295	}
2296
2297	void test (void)
2298	{
2299		// Test with default VAO
2300		{
2301			const tcu::ScopedLogSection section(m_log, "DefaultVAO", "Test with default VAO");
2302
2303			const GLfloat vertexData[4] = {0.0f}; // never accessed
2304
2305			struct StridePointerData
2306			{
2307				GLint		size;
2308				GLenum		type;
2309				GLint		stride;
2310				const void*	pointer;
2311			};
2312
2313			// test VertexAttribPointer
2314			{
2315				const StridePointerData pointers[] =
2316				{
2317					{ 1, GL_FLOAT,			0,	vertexData },
2318					{ 1, GL_FLOAT,			1,	vertexData },
2319					{ 1, GL_FLOAT,			4,	vertexData },
2320					{ 1, GL_HALF_FLOAT,		0,	vertexData },
2321					{ 1, GL_HALF_FLOAT,		1,	vertexData },
2322					{ 1, GL_HALF_FLOAT,		4,	vertexData },
2323					{ 1, GL_FIXED,			0,	vertexData },
2324					{ 1, GL_FIXED,			1,	vertexData },
2325					{ 1, GL_FIXED,			4,	vertexData },
2326				};
2327
2328				for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(pointers); ++ndx)
2329				{
2330					glVertexAttribPointer(0, pointers[ndx].size, pointers[ndx].type, GL_FALSE, pointers[ndx].stride, pointers[ndx].pointer);
2331					expectError(GL_NO_ERROR);
2332
2333					verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_STRIDE, pointers[ndx].stride);
2334				}
2335			}
2336
2337			// test glVertexAttribIPointer
2338			{
2339				const StridePointerData pointers[] =
2340				{
2341					{ 1, GL_INT,				0,	vertexData },
2342					{ 1, GL_INT,				1,	vertexData },
2343					{ 1, GL_INT,				4,	vertexData },
2344					{ 4, GL_UNSIGNED_BYTE,		0,	vertexData },
2345					{ 4, GL_UNSIGNED_BYTE,		1,	vertexData },
2346					{ 4, GL_UNSIGNED_BYTE,		4,	vertexData },
2347					{ 2, GL_SHORT,				0,	vertexData },
2348					{ 2, GL_SHORT,				1,	vertexData },
2349					{ 2, GL_SHORT,				4,	vertexData },
2350				};
2351
2352				for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(pointers); ++ndx)
2353				{
2354					glVertexAttribIPointer(0, pointers[ndx].size, pointers[ndx].type, pointers[ndx].stride, pointers[ndx].pointer);
2355					expectError(GL_NO_ERROR);
2356
2357					verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_STRIDE, pointers[ndx].stride);
2358				}
2359			}
2360		}
2361
2362		// Test with multiple VAOs
2363		{
2364			const tcu::ScopedLogSection section(m_log, "WithVAO", "Test with VAO");
2365
2366			GLuint buf		= 0;
2367			GLuint vaos[2]	= {0};
2368
2369			glGenVertexArrays(2, vaos);
2370			glGenBuffers(1, &buf);
2371			glBindBuffer(GL_ARRAY_BUFFER, buf);
2372			expectError(GL_NO_ERROR);
2373
2374			// initial
2375			glBindVertexArray(vaos[0]);
2376			verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_STRIDE, 0);
2377			expectError(GL_NO_ERROR);
2378
2379			// set vao 0 to some value
2380			glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 4, DE_NULL);
2381			expectError(GL_NO_ERROR);
2382
2383			// set vao 1 to some other value
2384			glBindVertexArray(vaos[1]);
2385			glVertexAttribPointer(0, 1, GL_SHORT, GL_FALSE, 8, DE_NULL);
2386			expectError(GL_NO_ERROR);
2387
2388			// verify vao 1 state
2389			verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_STRIDE, 8);
2390			expectError(GL_NO_ERROR);
2391
2392			// verify vao 0 state
2393			glBindVertexArray(vaos[0]);
2394			verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_STRIDE, 4);
2395			expectError(GL_NO_ERROR);
2396
2397			glDeleteVertexArrays(2, vaos);
2398			glDeleteBuffers(1, &buf);
2399			expectError(GL_NO_ERROR);
2400		}
2401	}
2402};
2403
2404class VertexAttributeNormalizedCase : public ApiCase
2405{
2406public:
2407	VertexAttributeNormalizedCase (Context& context, const char* name, const char* description)
2408		: ApiCase(context, name, description)
2409	{
2410	}
2411
2412	void test (void)
2413	{
2414		// Test with default VAO
2415		{
2416			const tcu::ScopedLogSection section(m_log, "DefaultVAO", "Test with default VAO");
2417
2418			const GLfloat vertexData[4] = {0.0f}; // never accessed
2419
2420			// test VertexAttribPointer
2421			{
2422				const PointerData pointers[] =
2423				{
2424					{ 1, GL_BYTE,								0,	GL_FALSE,	vertexData	},
2425					{ 1, GL_SHORT,								0,	GL_FALSE,	vertexData	},
2426					{ 1, GL_INT,								0,	GL_FALSE,	vertexData	},
2427					{ 1, GL_UNSIGNED_BYTE,						0,	GL_FALSE,	vertexData	},
2428					{ 1, GL_UNSIGNED_SHORT,						0,	GL_FALSE,	vertexData	},
2429					{ 1, GL_UNSIGNED_INT,						0,	GL_FALSE,	vertexData	},
2430					{ 4, GL_INT_2_10_10_10_REV,					0,	GL_FALSE,	vertexData	},
2431					{ 4, GL_UNSIGNED_INT_2_10_10_10_REV,		0,	GL_FALSE,	vertexData	},
2432					{ 1, GL_BYTE,								0,	GL_TRUE,	vertexData	},
2433					{ 1, GL_SHORT,								0,	GL_TRUE,	vertexData	},
2434					{ 1, GL_INT,								0,	GL_TRUE,	vertexData	},
2435					{ 1, GL_UNSIGNED_BYTE,						0,	GL_TRUE,	vertexData	},
2436					{ 1, GL_UNSIGNED_SHORT,						0,	GL_TRUE,	vertexData	},
2437					{ 1, GL_UNSIGNED_INT,						0,	GL_TRUE,	vertexData	},
2438					{ 4, GL_INT_2_10_10_10_REV,					0,	GL_TRUE,	vertexData	},
2439					{ 4, GL_UNSIGNED_INT_2_10_10_10_REV,		0,	GL_TRUE,	vertexData	},
2440				};
2441
2442				for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(pointers); ++ndx)
2443				{
2444					glVertexAttribPointer(0, pointers[ndx].size, pointers[ndx].type, pointers[ndx].normalized, pointers[ndx].stride, pointers[ndx].pointer);
2445					expectError(GL_NO_ERROR);
2446
2447					verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, pointers[ndx].normalized);
2448				}
2449			}
2450
2451			// test glVertexAttribIPointer
2452			{
2453				const PointerData pointers[] =
2454				{
2455					{ 1, GL_BYTE,				0,	GL_FALSE, vertexData	},
2456					{ 1, GL_SHORT,				0,	GL_FALSE, vertexData	},
2457					{ 1, GL_INT,				0,	GL_FALSE, vertexData	},
2458					{ 1, GL_UNSIGNED_BYTE,		0,	GL_FALSE, vertexData	},
2459					{ 1, GL_UNSIGNED_SHORT,		0,	GL_FALSE, vertexData	},
2460					{ 1, GL_UNSIGNED_INT,		0,	GL_FALSE, vertexData	},
2461				};
2462
2463				for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(pointers); ++ndx)
2464				{
2465					glVertexAttribIPointer(0, pointers[ndx].size, pointers[ndx].type, pointers[ndx].stride, pointers[ndx].pointer);
2466					expectError(GL_NO_ERROR);
2467
2468					verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, GL_FALSE);
2469				}
2470			}
2471		}
2472
2473		// Test with multiple VAOs
2474		{
2475			const tcu::ScopedLogSection section(m_log, "WithVAO", "Test with VAO");
2476
2477			GLuint buf		= 0;
2478			GLuint vaos[2]	= {0};
2479
2480			glGenVertexArrays(2, vaos);
2481			glGenBuffers(1, &buf);
2482			glBindBuffer(GL_ARRAY_BUFFER, buf);
2483			expectError(GL_NO_ERROR);
2484
2485			// initial
2486			glBindVertexArray(vaos[0]);
2487			verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, GL_FALSE);
2488			expectError(GL_NO_ERROR);
2489
2490			// set vao 0 to some value
2491			glVertexAttribPointer(0, 1, GL_INT, GL_TRUE, 0, DE_NULL);
2492			expectError(GL_NO_ERROR);
2493
2494			// set vao 1 to some other value
2495			glBindVertexArray(vaos[1]);
2496			glVertexAttribPointer(0, 1, GL_INT, GL_FALSE, 0, DE_NULL);
2497			expectError(GL_NO_ERROR);
2498
2499			// verify vao 1 state
2500			verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, GL_FALSE);
2501			expectError(GL_NO_ERROR);
2502
2503			// verify vao 0 state
2504			glBindVertexArray(vaos[0]);
2505			verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, GL_TRUE);
2506			expectError(GL_NO_ERROR);
2507
2508			glDeleteVertexArrays(2, vaos);
2509			glDeleteBuffers(1, &buf);
2510			expectError(GL_NO_ERROR);
2511		}
2512	}
2513};
2514
2515class VertexAttributeIntegerCase : public ApiCase
2516{
2517public:
2518	VertexAttributeIntegerCase (Context& context, const char* name, const char* description)
2519		: ApiCase(context, name, description)
2520	{
2521	}
2522
2523	void test (void)
2524	{
2525		// Test with default VAO
2526		{
2527			const tcu::ScopedLogSection section(m_log, "DefaultVAO", "Test with default VAO");
2528
2529			const GLfloat vertexData[4] = {0.0f}; // never accessed
2530
2531			// test VertexAttribPointer
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_FIXED,								0,	GL_FALSE, vertexData	},
2539					{ 1, GL_FLOAT,								0,	GL_FALSE, vertexData	},
2540					{ 1, GL_HALF_FLOAT,							0,	GL_FALSE, vertexData	},
2541					{ 1, GL_UNSIGNED_BYTE,						0,	GL_FALSE, vertexData	},
2542					{ 1, GL_UNSIGNED_SHORT,						0,	GL_FALSE, vertexData	},
2543					{ 1, GL_UNSIGNED_INT,						0,	GL_FALSE, vertexData	},
2544					{ 4, GL_INT_2_10_10_10_REV,					0,	GL_FALSE, vertexData	},
2545					{ 4, GL_UNSIGNED_INT_2_10_10_10_REV,		0,	GL_FALSE, vertexData	},
2546				};
2547
2548				for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(pointers); ++ndx)
2549				{
2550					glVertexAttribPointer(0, pointers[ndx].size, pointers[ndx].type, pointers[ndx].normalized, pointers[ndx].stride, pointers[ndx].pointer);
2551					expectError(GL_NO_ERROR);
2552
2553					verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_INTEGER, GL_FALSE);
2554				}
2555			}
2556
2557			// test glVertexAttribIPointer
2558			{
2559				const PointerData pointers[] =
2560				{
2561					{ 1, GL_BYTE,								0,	GL_FALSE, vertexData	},
2562					{ 1, GL_SHORT,								0,	GL_FALSE, vertexData	},
2563					{ 1, GL_INT,								0,	GL_FALSE, vertexData	},
2564					{ 1, GL_UNSIGNED_BYTE,						0,	GL_FALSE, vertexData	},
2565					{ 1, GL_UNSIGNED_SHORT,						0,	GL_FALSE, vertexData	},
2566					{ 1, GL_UNSIGNED_INT,						0,	GL_FALSE, vertexData	},
2567				};
2568
2569				for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(pointers); ++ndx)
2570				{
2571					glVertexAttribIPointer(0, pointers[ndx].size, pointers[ndx].type, pointers[ndx].stride, pointers[ndx].pointer);
2572					expectError(GL_NO_ERROR);
2573
2574					verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_INTEGER, GL_TRUE);
2575				}
2576			}
2577		}
2578
2579		// Test with multiple VAOs
2580		{
2581			const tcu::ScopedLogSection section(m_log, "WithVAO", "Test with VAO");
2582
2583			GLuint buf		= 0;
2584			GLuint vaos[2]	= {0};
2585
2586			glGenVertexArrays(2, vaos);
2587			glGenBuffers(1, &buf);
2588			glBindBuffer(GL_ARRAY_BUFFER, buf);
2589			expectError(GL_NO_ERROR);
2590
2591			// initial
2592			glBindVertexArray(vaos[0]);
2593			verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_INTEGER, GL_FALSE);
2594			expectError(GL_NO_ERROR);
2595
2596			// set vao 0 to some value
2597			glVertexAttribIPointer(0, 1, GL_INT, 0, DE_NULL);
2598			expectError(GL_NO_ERROR);
2599
2600			// set vao 1 to some other value
2601			glBindVertexArray(vaos[1]);
2602			glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, 0, DE_NULL);
2603			expectError(GL_NO_ERROR);
2604
2605			// verify vao 1 state
2606			verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_INTEGER, GL_FALSE);
2607			expectError(GL_NO_ERROR);
2608
2609			// verify vao 0 state
2610			glBindVertexArray(vaos[0]);
2611			verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_INTEGER, GL_TRUE);
2612			expectError(GL_NO_ERROR);
2613
2614			glDeleteVertexArrays(2, vaos);
2615			glDeleteBuffers(1, &buf);
2616			expectError(GL_NO_ERROR);
2617		}
2618	}
2619};
2620
2621class VertexAttributeEnabledCase : public ApiCase
2622{
2623public:
2624	VertexAttributeEnabledCase (Context& context, const char* name, const char* description)
2625		: ApiCase(context, name, description)
2626	{
2627	}
2628
2629	void test (void)
2630	{
2631		// VERTEX_ATTRIB_ARRAY_ENABLED
2632
2633		// Test with default VAO
2634		{
2635			const tcu::ScopedLogSection section(m_log, "DefaultVAO", "Test with default VAO");
2636
2637			verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_ENABLED, GL_FALSE);
2638			glEnableVertexAttribArray(0);
2639			verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_ENABLED, GL_TRUE);
2640			glDisableVertexAttribArray(0);
2641			verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_ENABLED, GL_FALSE);
2642		}
2643
2644		// Test with multiple VAOs
2645		{
2646			const tcu::ScopedLogSection section(m_log, "WithVAO", "Test with VAO");
2647
2648			GLuint vaos[2] = {0};
2649
2650			glGenVertexArrays(2, vaos);
2651			expectError(GL_NO_ERROR);
2652
2653			// set vao 0 to some value
2654			glBindVertexArray(vaos[0]);
2655			glEnableVertexAttribArray(0);
2656			expectError(GL_NO_ERROR);
2657
2658			// set vao 1 to some other value
2659			glBindVertexArray(vaos[1]);
2660			glDisableVertexAttribArray(0);
2661			expectError(GL_NO_ERROR);
2662
2663			// verify vao 1 state
2664			verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_ENABLED, GL_FALSE);
2665			expectError(GL_NO_ERROR);
2666
2667			// verify vao 0 state
2668			glBindVertexArray(vaos[0]);
2669			verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_ENABLED, GL_TRUE);
2670			expectError(GL_NO_ERROR);
2671
2672			glDeleteVertexArrays(2, vaos);
2673			expectError(GL_NO_ERROR);
2674		}
2675	}
2676};
2677
2678class VertexAttributeDivisorCase : public ApiCase
2679{
2680public:
2681	VertexAttributeDivisorCase (Context& context, const char* name, const char* description)
2682		: ApiCase(context, name, description)
2683	{
2684	}
2685
2686	void test (void)
2687	{
2688		// Test with default VAO
2689		{
2690			const tcu::ScopedLogSection section(m_log, "DefaultVAO", "Test with default VAO");
2691
2692			verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_DIVISOR,	0);
2693			glVertexAttribDivisor(0, 1);
2694			verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_DIVISOR,	1);
2695			glVertexAttribDivisor(0, 5);
2696			verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_DIVISOR,	5);
2697		}
2698
2699		// Test with multiple VAOs
2700		{
2701			const tcu::ScopedLogSection section(m_log, "WithVAO", "Test with VAO");
2702
2703			GLuint vaos[2] = {0};
2704
2705			glGenVertexArrays(2, vaos);
2706			expectError(GL_NO_ERROR);
2707
2708			// set vao 0 to some value
2709			glBindVertexArray(vaos[0]);
2710			glVertexAttribDivisor(0, 1);
2711			expectError(GL_NO_ERROR);
2712
2713			// set vao 1 to some other value
2714			glBindVertexArray(vaos[1]);
2715			glVertexAttribDivisor(0, 5);
2716			expectError(GL_NO_ERROR);
2717
2718			// verify vao 1 state
2719			verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_DIVISOR, 5);
2720			expectError(GL_NO_ERROR);
2721
2722			// verify vao 0 state
2723			glBindVertexArray(vaos[0]);
2724			verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_DIVISOR, 1);
2725			expectError(GL_NO_ERROR);
2726
2727			glDeleteVertexArrays(2, vaos);
2728			expectError(GL_NO_ERROR);
2729		}
2730	}
2731};
2732
2733class VertexAttributeBufferBindingCase : public ApiCase
2734{
2735public:
2736	VertexAttributeBufferBindingCase (Context& context, const char* name, const char* description)
2737		: ApiCase(context, name, description)
2738	{
2739	}
2740
2741	void test (void)
2742	{
2743		// Test with default VAO
2744		{
2745			const tcu::ScopedLogSection section(m_log, "DefaultVAO", "Test with default VAO");
2746
2747			// initial
2748			verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, 0);
2749
2750			GLuint bufferID;
2751			glGenBuffers(1, &bufferID);
2752			glBindBuffer(GL_ARRAY_BUFFER, bufferID);
2753			expectError(GL_NO_ERROR);
2754
2755			glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, DE_NULL);
2756			expectError(GL_NO_ERROR);
2757
2758			verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, bufferID);
2759
2760			glDeleteBuffers(1, &bufferID);
2761			expectError(GL_NO_ERROR);
2762		}
2763
2764		// Test with multiple VAOs
2765		{
2766			const tcu::ScopedLogSection section(m_log, "WithVAO", "Test with VAO");
2767
2768			GLuint vaos[2] = {0};
2769			GLuint bufs[2] = {0};
2770
2771			glGenBuffers(2, bufs);
2772			expectError(GL_NO_ERROR);
2773
2774			glGenVertexArrays(2, vaos);
2775			expectError(GL_NO_ERROR);
2776
2777			// set vao 0 to some value
2778			glBindVertexArray(vaos[0]);
2779			glBindBuffer(GL_ARRAY_BUFFER, bufs[0]);
2780			glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, DE_NULL);
2781			expectError(GL_NO_ERROR);
2782
2783			// set vao 1 to some other value
2784			glBindVertexArray(vaos[1]);
2785			glBindBuffer(GL_ARRAY_BUFFER, bufs[1]);
2786			glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, DE_NULL);
2787			expectError(GL_NO_ERROR);
2788
2789			// verify vao 1 state
2790			verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, bufs[1]);
2791			expectError(GL_NO_ERROR);
2792
2793			// verify vao 0 state
2794			glBindVertexArray(vaos[0]);
2795			verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, bufs[0]);
2796			expectError(GL_NO_ERROR);
2797
2798			glDeleteVertexArrays(2, vaos);
2799			glDeleteBuffers(2, bufs);
2800			expectError(GL_NO_ERROR);
2801		}
2802	}
2803};
2804
2805class VertexAttributePointerCase : public ApiCase
2806{
2807public:
2808	VertexAttributePointerCase (Context& context, const char* name, const char* description)
2809		: ApiCase(context, name, description)
2810	{
2811	}
2812
2813	void test (void)
2814	{
2815		// Test with default VAO
2816		{
2817			const tcu::ScopedLogSection section(m_log, "DefaultVAO", "Test with default VAO");
2818
2819			StateQueryMemoryWriteGuard<GLvoid*> initialState;
2820			glGetVertexAttribPointerv(0, GL_VERTEX_ATTRIB_ARRAY_POINTER, &initialState);
2821			initialState.verifyValidity(m_testCtx);
2822			checkPointerEquals(m_testCtx, initialState, 0);
2823
2824			const GLfloat vertexData[4] = {0.0f}; // never accessed
2825			const PointerData pointers[] =
2826			{
2827				{ 1, GL_BYTE,				0,	GL_FALSE, &vertexData[2] },
2828				{ 1, GL_SHORT,				0,	GL_FALSE, &vertexData[1] },
2829				{ 1, GL_INT,				0,	GL_FALSE, &vertexData[2] },
2830				{ 1, GL_FIXED,				0,	GL_FALSE, &vertexData[2] },
2831				{ 1, GL_FIXED,				0,	GL_FALSE, &vertexData[1] },
2832				{ 1, GL_FLOAT,				0,	GL_FALSE, &vertexData[0] },
2833				{ 1, GL_FLOAT,				0,	GL_FALSE, &vertexData[3] },
2834				{ 1, GL_FLOAT,				0,	GL_FALSE, &vertexData[2] },
2835				{ 1, GL_HALF_FLOAT,			0,	GL_FALSE, &vertexData[0] },
2836				{ 4, GL_HALF_FLOAT,			0,	GL_FALSE, &vertexData[1] },
2837				{ 4, GL_HALF_FLOAT,			0,	GL_FALSE, &vertexData[2] },
2838			};
2839
2840			for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(pointers); ++ndx)
2841			{
2842				glVertexAttribPointer(0, pointers[ndx].size, pointers[ndx].type, pointers[ndx].normalized, pointers[ndx].stride, pointers[ndx].pointer);
2843				expectError(GL_NO_ERROR);
2844
2845				StateQueryMemoryWriteGuard<GLvoid*> state;
2846				glGetVertexAttribPointerv(0, GL_VERTEX_ATTRIB_ARRAY_POINTER, &state);
2847				state.verifyValidity(m_testCtx);
2848				checkPointerEquals(m_testCtx, state, pointers[ndx].pointer);
2849			}
2850		}
2851
2852		// Test with multiple VAOs
2853		{
2854			const tcu::ScopedLogSection section(m_log, "WithVAO", "Test with VAO");
2855
2856			GLuint vaos[2] = {0};
2857			GLuint bufs[2] = {0};
2858
2859			glGenBuffers(2, bufs);
2860			expectError(GL_NO_ERROR);
2861
2862			glGenVertexArrays(2, vaos);
2863			expectError(GL_NO_ERROR);
2864
2865			// set vao 0 to some value
2866			glBindVertexArray(vaos[0]);
2867			glBindBuffer(GL_ARRAY_BUFFER, bufs[0]);
2868			glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, ((deUint8*)DE_NULL) + 8);
2869			expectError(GL_NO_ERROR);
2870
2871			// set vao 1 to some other value
2872			glBindVertexArray(vaos[1]);
2873			glBindBuffer(GL_ARRAY_BUFFER, bufs[1]);
2874			glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, ((deUint8*)DE_NULL) + 4);
2875			expectError(GL_NO_ERROR);
2876
2877			// verify vao 1 state
2878			{
2879				StateQueryMemoryWriteGuard<GLvoid*> state;
2880				glGetVertexAttribPointerv(0, GL_VERTEX_ATTRIB_ARRAY_POINTER, &state);
2881				state.verifyValidity(m_testCtx);
2882				checkPointerEquals(m_testCtx, state, ((deUint8*)DE_NULL) + 4);
2883			}
2884			expectError(GL_NO_ERROR);
2885
2886			// verify vao 0 state
2887			glBindVertexArray(vaos[0]);
2888			{
2889				StateQueryMemoryWriteGuard<GLvoid*> state;
2890				glGetVertexAttribPointerv(0, GL_VERTEX_ATTRIB_ARRAY_POINTER, &state);
2891				state.verifyValidity(m_testCtx);
2892				checkPointerEquals(m_testCtx, state, ((deUint8*)DE_NULL) + 8);
2893			}
2894			expectError(GL_NO_ERROR);
2895
2896			glDeleteVertexArrays(2, vaos);
2897			glDeleteBuffers(2, bufs);
2898			expectError(GL_NO_ERROR);
2899		}
2900	}
2901};
2902
2903class UniformValueFloatCase : public ApiCase
2904{
2905public:
2906	UniformValueFloatCase (Context& context, const char* name, const char* description)
2907		: ApiCase(context, name, description)
2908	{
2909	}
2910
2911	void test (void)
2912	{
2913		static const char* testVertSource =
2914			"#version 300 es\n"
2915			"uniform highp float floatUniform;\n"
2916			"uniform highp vec2 float2Uniform;\n"
2917			"uniform highp vec3 float3Uniform;\n"
2918			"uniform highp vec4 float4Uniform;\n"
2919			"void main (void)\n"
2920			"{\n"
2921			"	gl_Position = vec4(floatUniform + float2Uniform.x + float3Uniform.x + float4Uniform.x);\n"
2922			"}\n";
2923		static const char* testFragSource =
2924			"#version 300 es\n"
2925			"layout(location = 0) out mediump vec4 fragColor;"
2926			"void main (void)\n"
2927			"{\n"
2928			"	fragColor = vec4(0.0);\n"
2929			"}\n";
2930
2931		GLuint shaderVert = glCreateShader(GL_VERTEX_SHADER);
2932		GLuint shaderFrag = glCreateShader(GL_FRAGMENT_SHADER);
2933
2934		glShaderSource(shaderVert, 1, &testVertSource, DE_NULL);
2935		glShaderSource(shaderFrag, 1, &testFragSource, DE_NULL);
2936
2937		glCompileShader(shaderVert);
2938		glCompileShader(shaderFrag);
2939		expectError(GL_NO_ERROR);
2940
2941		GLuint program = glCreateProgram();
2942		glAttachShader(program, shaderVert);
2943		glAttachShader(program, shaderFrag);
2944		glLinkProgram(program);
2945		glUseProgram(program);
2946		expectError(GL_NO_ERROR);
2947
2948		GLint location;
2949
2950		location = glGetUniformLocation(program,"floatUniform");
2951		glUniform1f(location, 1.0f);
2952		verifyUniformValue1f(m_testCtx, *this, program, location, 1.0f);
2953
2954		location = glGetUniformLocation(program,"float2Uniform");
2955		glUniform2f(location, 1.0f, 2.0f);
2956		verifyUniformValue2f(m_testCtx, *this, program, location, 1.0f, 2.0f);
2957
2958		location = glGetUniformLocation(program,"float3Uniform");
2959		glUniform3f(location, 1.0f, 2.0f, 3.0f);
2960		verifyUniformValue3f(m_testCtx, *this, program, location, 1.0f, 2.0f, 3.0f);
2961
2962		location = glGetUniformLocation(program,"float4Uniform");
2963		glUniform4f(location, 1.0f, 2.0f, 3.0f, 4.0f);
2964		verifyUniformValue4f(m_testCtx, *this, program, location, 1.0f, 2.0f, 3.0f, 4.0f);
2965
2966		glUseProgram(0);
2967		glDeleteShader(shaderVert);
2968		glDeleteShader(shaderFrag);
2969		glDeleteProgram(program);
2970		expectError(GL_NO_ERROR);
2971	}
2972};
2973
2974class UniformValueIntCase : public ApiCase
2975{
2976public:
2977	UniformValueIntCase (Context& context, const char* name, const char* description)
2978		: ApiCase(context, name, description)
2979	{
2980	}
2981
2982	void test (void)
2983	{
2984		static const char* testVertSource =
2985			"#version 300 es\n"
2986			"uniform highp int intUniform;\n"
2987			"uniform highp ivec2 int2Uniform;\n"
2988			"uniform highp ivec3 int3Uniform;\n"
2989			"uniform highp ivec4 int4Uniform;\n"
2990			"void main (void)\n"
2991			"{\n"
2992			"	gl_Position = vec4(float(intUniform + int2Uniform.x + int3Uniform.x + int4Uniform.x));\n"
2993			"}\n";
2994		static const char* testFragSource =
2995			"#version 300 es\n"
2996			"layout(location = 0) out mediump vec4 fragColor;"
2997			"void main (void)\n"
2998			"{\n"
2999			"	fragColor = vec4(0.0);\n"
3000			"}\n";
3001
3002		GLuint shaderVert = glCreateShader(GL_VERTEX_SHADER);
3003		GLuint shaderFrag = glCreateShader(GL_FRAGMENT_SHADER);
3004
3005		glShaderSource(shaderVert, 1, &testVertSource, DE_NULL);
3006		glShaderSource(shaderFrag, 1, &testFragSource, DE_NULL);
3007
3008		glCompileShader(shaderVert);
3009		glCompileShader(shaderFrag);
3010		expectError(GL_NO_ERROR);
3011
3012		GLuint program = glCreateProgram();
3013		glAttachShader(program, shaderVert);
3014		glAttachShader(program, shaderFrag);
3015		glLinkProgram(program);
3016		glUseProgram(program);
3017		expectError(GL_NO_ERROR);
3018
3019		GLint location;
3020
3021		location = glGetUniformLocation(program,"intUniform");
3022		glUniform1i(location, 1);
3023		verifyUniformValue1i(m_testCtx, *this, program, location, 1);
3024
3025		location = glGetUniformLocation(program,"int2Uniform");
3026		glUniform2i(location, 1, 2);
3027		verifyUniformValue2i(m_testCtx, *this, program, location, 1, 2);
3028
3029		location = glGetUniformLocation(program,"int3Uniform");
3030		glUniform3i(location, 1, 2, 3);
3031		verifyUniformValue3i(m_testCtx, *this, program, location, 1, 2, 3);
3032
3033		location = glGetUniformLocation(program,"int4Uniform");
3034		glUniform4i(location, 1, 2, 3, 4);
3035		verifyUniformValue4i(m_testCtx, *this, program, location, 1, 2, 3, 4);
3036
3037		glUseProgram(0);
3038		glDeleteShader(shaderVert);
3039		glDeleteShader(shaderFrag);
3040		glDeleteProgram(program);
3041		expectError(GL_NO_ERROR);
3042	}
3043};
3044
3045class UniformValueUintCase : public ApiCase
3046{
3047public:
3048	UniformValueUintCase (Context& context, const char* name, const char* description)
3049		: ApiCase(context, name, description)
3050	{
3051	}
3052
3053	void test (void)
3054	{
3055		static const char* testVertSource =
3056			"#version 300 es\n"
3057			"uniform highp uint uintUniform;\n"
3058			"uniform highp uvec2 uint2Uniform;\n"
3059			"uniform highp uvec3 uint3Uniform;\n"
3060			"uniform highp uvec4 uint4Uniform;\n"
3061			"void main (void)\n"
3062			"{\n"
3063			"	gl_Position = vec4(float(uintUniform + uint2Uniform.x + uint3Uniform.x + uint4Uniform.x));\n"
3064			"}\n";
3065		static const char* testFragSource =
3066			"#version 300 es\n"
3067			"layout(location = 0) out mediump vec4 fragColor;"
3068			"void main (void)\n"
3069			"{\n"
3070			"	fragColor = vec4(0.0);\n"
3071			"}\n";
3072
3073		GLuint shaderVert = glCreateShader(GL_VERTEX_SHADER);
3074		GLuint shaderFrag = glCreateShader(GL_FRAGMENT_SHADER);
3075
3076		glShaderSource(shaderVert, 1, &testVertSource, DE_NULL);
3077		glShaderSource(shaderFrag, 1, &testFragSource, DE_NULL);
3078
3079		glCompileShader(shaderVert);
3080		glCompileShader(shaderFrag);
3081		expectError(GL_NO_ERROR);
3082
3083		GLuint program = glCreateProgram();
3084		glAttachShader(program, shaderVert);
3085		glAttachShader(program, shaderFrag);
3086		glLinkProgram(program);
3087		glUseProgram(program);
3088		expectError(GL_NO_ERROR);
3089
3090		GLint location;
3091
3092		location = glGetUniformLocation(program,"uintUniform");
3093		glUniform1ui(location, 1);
3094		verifyUniformValue1ui(m_testCtx, *this, program, location, 1);
3095
3096		location = glGetUniformLocation(program,"uint2Uniform");
3097		glUniform2ui(location, 1, 2);
3098		verifyUniformValue2ui(m_testCtx, *this, program, location, 1, 2);
3099
3100		location = glGetUniformLocation(program,"uint3Uniform");
3101		glUniform3ui(location, 1, 2, 3);
3102		verifyUniformValue3ui(m_testCtx, *this, program, location, 1, 2, 3);
3103
3104		location = glGetUniformLocation(program,"uint4Uniform");
3105		glUniform4ui(location, 1, 2, 3, 4);
3106		verifyUniformValue4ui(m_testCtx, *this, program, location, 1, 2, 3, 4);
3107
3108		glUseProgram(0);
3109		glDeleteShader(shaderVert);
3110		glDeleteShader(shaderFrag);
3111		glDeleteProgram(program);
3112		expectError(GL_NO_ERROR);
3113	}
3114};
3115
3116
3117class UniformValueBooleanCase : public ApiCase
3118{
3119public:
3120	UniformValueBooleanCase (Context& context, const char* name, const char* description)
3121		: ApiCase(context, name, description)
3122	{
3123	}
3124
3125	void test (void)
3126	{
3127		static const char* testVertSource =
3128			"#version 300 es\n"
3129			"uniform bool boolUniform;\n"
3130			"uniform bvec2 bool2Uniform;\n"
3131			"uniform bvec3 bool3Uniform;\n"
3132			"uniform bvec4 bool4Uniform;\n"
3133			"void main (void)\n"
3134			"{\n"
3135			"	gl_Position = vec4(float(boolUniform) + float(bool2Uniform.x) + float(bool3Uniform.x) + float(bool4Uniform.x));\n"
3136			"}\n";
3137		static const char* testFragSource =
3138			"#version 300 es\n"
3139			"layout(location = 0) out mediump vec4 fragColor;"
3140			"void main (void)\n"
3141			"{\n"
3142			"	fragColor = vec4(0.0);\n"
3143			"}\n";
3144
3145		GLuint shaderVert = glCreateShader(GL_VERTEX_SHADER);
3146		GLuint shaderFrag = glCreateShader(GL_FRAGMENT_SHADER);
3147
3148		glShaderSource(shaderVert, 1, &testVertSource, DE_NULL);
3149		glShaderSource(shaderFrag, 1, &testFragSource, DE_NULL);
3150
3151		glCompileShader(shaderVert);
3152		glCompileShader(shaderFrag);
3153		expectError(GL_NO_ERROR);
3154
3155		GLuint program = glCreateProgram();
3156		glAttachShader(program, shaderVert);
3157		glAttachShader(program, shaderFrag);
3158		glLinkProgram(program);
3159		glUseProgram(program);
3160		expectError(GL_NO_ERROR);
3161
3162		GLint location;
3163
3164		// int conversion
3165
3166		location = glGetUniformLocation(program,"boolUniform");
3167		glUniform1i(location, 1);
3168		verifyUniformValue1i(m_testCtx, *this, program, location, 1);
3169
3170		location = glGetUniformLocation(program,"bool2Uniform");
3171		glUniform2i(location, 1, 2);
3172		verifyUniformValue2i(m_testCtx, *this, program, location, 1, 1);
3173
3174		location = glGetUniformLocation(program,"bool3Uniform");
3175		glUniform3i(location, 0, 1, 2);
3176		verifyUniformValue3i(m_testCtx, *this, program, location, 0, 1, 1);
3177
3178		location = glGetUniformLocation(program,"bool4Uniform");
3179		glUniform4i(location, 1, 0, 1, -1);
3180		verifyUniformValue4i(m_testCtx, *this, program, location, 1, 0, 1, 1);
3181
3182		// float conversion
3183
3184		location = glGetUniformLocation(program,"boolUniform");
3185		glUniform1f(location, 1.0f);
3186		verifyUniformValue1i(m_testCtx, *this, program, location, 1);
3187
3188		location = glGetUniformLocation(program,"bool2Uniform");
3189		glUniform2f(location, 1.0f, 0.1f);
3190		verifyUniformValue2i(m_testCtx, *this, program, location, 1, 1);
3191
3192		location = glGetUniformLocation(program,"bool3Uniform");
3193		glUniform3f(location, 0.0f, 0.1f, -0.1f);
3194		verifyUniformValue3i(m_testCtx, *this, program, location, 0, 1, 1);
3195
3196		location = glGetUniformLocation(program,"bool4Uniform");
3197		glUniform4f(location, 1.0f, 0.0f, 0.1f, -0.9f);
3198		verifyUniformValue4i(m_testCtx, *this, program, location, 1, 0, 1, 1);
3199
3200		glUseProgram(0);
3201		glDeleteShader(shaderVert);
3202		glDeleteShader(shaderFrag);
3203		glDeleteProgram(program);
3204		expectError(GL_NO_ERROR);
3205	}
3206};
3207
3208class UniformValueSamplerCase : public ApiCase
3209{
3210public:
3211	UniformValueSamplerCase (Context& context, const char* name, const char* description)
3212		: ApiCase(context, name, description)
3213	{
3214	}
3215
3216	void test (void)
3217	{
3218		static const char* testVertSource =
3219			"#version 300 es\n"
3220			"void main (void)\n"
3221			"{\n"
3222			"	gl_Position = vec4(0.0);\n"
3223			"}\n";
3224		static const char* testFragSource =
3225			"#version 300 es\n"
3226			"uniform highp sampler2D uniformSampler;\n"
3227			"layout(location = 0) out mediump vec4 fragColor;"
3228			"void main (void)\n"
3229			"{\n"
3230			"	fragColor = vec4(textureSize(uniformSampler, 0).x);\n"
3231			"}\n";
3232
3233		GLuint shaderVert = glCreateShader(GL_VERTEX_SHADER);
3234		GLuint shaderFrag = glCreateShader(GL_FRAGMENT_SHADER);
3235
3236		glShaderSource(shaderVert, 1, &testVertSource, DE_NULL);
3237		glShaderSource(shaderFrag, 1, &testFragSource, DE_NULL);
3238
3239		glCompileShader(shaderVert);
3240		glCompileShader(shaderFrag);
3241		expectError(GL_NO_ERROR);
3242
3243		GLuint program = glCreateProgram();
3244		glAttachShader(program, shaderVert);
3245		glAttachShader(program, shaderFrag);
3246		glLinkProgram(program);
3247		glUseProgram(program);
3248		expectError(GL_NO_ERROR);
3249
3250		GLint location;
3251
3252		location = glGetUniformLocation(program,"uniformSampler");
3253		glUniform1i(location, 1);
3254		verifyUniformValue1i(m_testCtx, *this, program, location, 1);
3255
3256		glUseProgram(0);
3257		glDeleteShader(shaderVert);
3258		glDeleteShader(shaderFrag);
3259		glDeleteProgram(program);
3260		expectError(GL_NO_ERROR);
3261	}
3262};
3263
3264class UniformValueArrayCase : public ApiCase
3265{
3266public:
3267	UniformValueArrayCase (Context& context, const char* name, const char* description)
3268		: ApiCase(context, name, description)
3269	{
3270	}
3271
3272	void test (void)
3273	{
3274		static const char* testVertSource =
3275			"#version 300 es\n"
3276			"uniform highp float arrayUniform[5];"
3277			"uniform highp vec2 array2Uniform[5];"
3278			"uniform highp vec3 array3Uniform[5];"
3279			"uniform highp vec4 array4Uniform[5];"
3280			"void main (void)\n"
3281			"{\n"
3282			"	gl_Position = \n"
3283			"		+ vec4(arrayUniform[0]		+ arrayUniform[1]		+ arrayUniform[2]		+ arrayUniform[3]		+ arrayUniform[4])\n"
3284			"		+ vec4(array2Uniform[0].x	+ array2Uniform[1].x	+ array2Uniform[2].x	+ array2Uniform[3].x	+ array2Uniform[4].x)\n"
3285			"		+ vec4(array3Uniform[0].x	+ array3Uniform[1].x	+ array3Uniform[2].x	+ array3Uniform[3].x	+ array3Uniform[4].x)\n"
3286			"		+ vec4(array4Uniform[0].x	+ array4Uniform[1].x	+ array4Uniform[2].x	+ array4Uniform[3].x	+ array4Uniform[4].x);\n"
3287			"}\n";
3288		static const char* testFragSource =
3289			"#version 300 es\n"
3290			"layout(location = 0) out mediump vec4 fragColor;"
3291			"void main (void)\n"
3292			"{\n"
3293			"	fragColor = vec4(0.0);\n"
3294			"}\n";
3295
3296		GLuint shaderVert = glCreateShader(GL_VERTEX_SHADER);
3297		GLuint shaderFrag = glCreateShader(GL_FRAGMENT_SHADER);
3298
3299		glShaderSource(shaderVert, 1, &testVertSource, DE_NULL);
3300		glShaderSource(shaderFrag, 1, &testFragSource, DE_NULL);
3301
3302		glCompileShader(shaderVert);
3303		glCompileShader(shaderFrag);
3304		expectError(GL_NO_ERROR);
3305
3306		GLuint program = glCreateProgram();
3307		glAttachShader(program, shaderVert);
3308		glAttachShader(program, shaderFrag);
3309		glLinkProgram(program);
3310		glUseProgram(program);
3311		expectError(GL_NO_ERROR);
3312
3313		GLint location;
3314
3315		float uniformValue[5 * 4] =
3316		{
3317			-1.0f,	0.1f,	4.0f,	800.0f,
3318			13.0f,	55.0f,	12.0f,	91.0f,
3319			-55.1f,	1.1f,	98.0f,	19.0f,
3320			41.0f,	65.0f,	4.0f,	12.2f,
3321			95.0f,	77.0f,	32.0f,	48.0f
3322		};
3323
3324		location = glGetUniformLocation(program,"arrayUniform");
3325		glUniform1fv(location, 5, uniformValue);
3326		expectError(GL_NO_ERROR);
3327
3328		verifyUniformValue1f(m_testCtx, *this, program, glGetUniformLocation(program,"arrayUniform[0]"), uniformValue[0]);
3329		verifyUniformValue1f(m_testCtx, *this, program, glGetUniformLocation(program,"arrayUniform[1]"), uniformValue[1]);
3330		verifyUniformValue1f(m_testCtx, *this, program, glGetUniformLocation(program,"arrayUniform[2]"), uniformValue[2]);
3331		verifyUniformValue1f(m_testCtx, *this, program, glGetUniformLocation(program,"arrayUniform[3]"), uniformValue[3]);
3332		verifyUniformValue1f(m_testCtx, *this, program, glGetUniformLocation(program,"arrayUniform[4]"), uniformValue[4]);
3333		expectError(GL_NO_ERROR);
3334
3335		location = glGetUniformLocation(program,"array2Uniform");
3336		glUniform2fv(location, 5, uniformValue);
3337		expectError(GL_NO_ERROR);
3338
3339		verifyUniformValue2f(m_testCtx, *this, program, glGetUniformLocation(program,"array2Uniform[0]"), uniformValue[2 * 0], uniformValue[(2 * 0) + 1]);
3340		verifyUniformValue2f(m_testCtx, *this, program, glGetUniformLocation(program,"array2Uniform[1]"), uniformValue[2 * 1], uniformValue[(2 * 1) + 1]);
3341		verifyUniformValue2f(m_testCtx, *this, program, glGetUniformLocation(program,"array2Uniform[2]"), uniformValue[2 * 2], uniformValue[(2 * 2) + 1]);
3342		verifyUniformValue2f(m_testCtx, *this, program, glGetUniformLocation(program,"array2Uniform[3]"), uniformValue[2 * 3], uniformValue[(2 * 3) + 1]);
3343		verifyUniformValue2f(m_testCtx, *this, program, glGetUniformLocation(program,"array2Uniform[4]"), uniformValue[2 * 4], uniformValue[(2 * 4) + 1]);
3344		expectError(GL_NO_ERROR);
3345
3346		location = glGetUniformLocation(program,"array3Uniform");
3347		glUniform3fv(location, 5, uniformValue);
3348		expectError(GL_NO_ERROR);
3349
3350		verifyUniformValue3f(m_testCtx, *this, program, glGetUniformLocation(program,"array3Uniform[0]"), uniformValue[3 * 0], uniformValue[(3 * 0) + 1], uniformValue[(3 * 0) + 2]);
3351		verifyUniformValue3f(m_testCtx, *this, program, glGetUniformLocation(program,"array3Uniform[1]"), uniformValue[3 * 1], uniformValue[(3 * 1) + 1], uniformValue[(3 * 1) + 2]);
3352		verifyUniformValue3f(m_testCtx, *this, program, glGetUniformLocation(program,"array3Uniform[2]"), uniformValue[3 * 2], uniformValue[(3 * 2) + 1], uniformValue[(3 * 2) + 2]);
3353		verifyUniformValue3f(m_testCtx, *this, program, glGetUniformLocation(program,"array3Uniform[3]"), uniformValue[3 * 3], uniformValue[(3 * 3) + 1], uniformValue[(3 * 3) + 2]);
3354		verifyUniformValue3f(m_testCtx, *this, program, glGetUniformLocation(program,"array3Uniform[4]"), uniformValue[3 * 4], uniformValue[(3 * 4) + 1], uniformValue[(3 * 4) + 2]);
3355		expectError(GL_NO_ERROR);
3356
3357		location = glGetUniformLocation(program,"array4Uniform");
3358		glUniform4fv(location, 5, uniformValue);
3359		expectError(GL_NO_ERROR);
3360
3361		verifyUniformValue4f(m_testCtx, *this, program, glGetUniformLocation(program,"array4Uniform[0]"), uniformValue[4 * 0], uniformValue[(4 * 0) + 1], uniformValue[(4 * 0) + 2], uniformValue[(4 * 0) + 3]);
3362		verifyUniformValue4f(m_testCtx, *this, program, glGetUniformLocation(program,"array4Uniform[1]"), uniformValue[4 * 1], uniformValue[(4 * 1) + 1], uniformValue[(4 * 1) + 2], uniformValue[(4 * 1) + 3]);
3363		verifyUniformValue4f(m_testCtx, *this, program, glGetUniformLocation(program,"array4Uniform[2]"), uniformValue[4 * 2], uniformValue[(4 * 2) + 1], uniformValue[(4 * 2) + 2], uniformValue[(4 * 2) + 3]);
3364		verifyUniformValue4f(m_testCtx, *this, program, glGetUniformLocation(program,"array4Uniform[3]"), uniformValue[4 * 3], uniformValue[(4 * 3) + 1], uniformValue[(4 * 3) + 2], uniformValue[(4 * 3) + 3]);
3365		verifyUniformValue4f(m_testCtx, *this, program, glGetUniformLocation(program,"array4Uniform[4]"), uniformValue[4 * 4], uniformValue[(4 * 4) + 1], uniformValue[(4 * 4) + 2], uniformValue[(4 * 4) + 3]);
3366		expectError(GL_NO_ERROR);
3367
3368		glUseProgram(0);
3369		glDeleteShader(shaderVert);
3370		glDeleteShader(shaderFrag);
3371		glDeleteProgram(program);
3372		expectError(GL_NO_ERROR);
3373	}
3374};
3375
3376class UniformValueMatrixCase : public ApiCase
3377{
3378public:
3379	UniformValueMatrixCase (Context& context, const char* name, const char* description)
3380		: ApiCase(context, name, description)
3381	{
3382	}
3383
3384	void test (void)
3385	{
3386		static const char* testVertSource =
3387			"#version 300 es\n"
3388			"uniform highp mat2 mat2Uniform;"
3389			"uniform highp mat3 mat3Uniform;"
3390			"uniform highp mat4 mat4Uniform;"
3391			"void main (void)\n"
3392			"{\n"
3393			"	gl_Position = vec4(mat2Uniform[0][0] + mat3Uniform[0][0] + mat4Uniform[0][0]);\n"
3394			"}\n";
3395		static const char* testFragSource =
3396			"#version 300 es\n"
3397			"layout(location = 0) out mediump vec4 fragColor;"
3398			"void main (void)\n"
3399			"{\n"
3400			"	fragColor = vec4(0.0);\n"
3401			"}\n";
3402
3403		GLuint shaderVert = glCreateShader(GL_VERTEX_SHADER);
3404		GLuint shaderFrag = glCreateShader(GL_FRAGMENT_SHADER);
3405
3406		glShaderSource(shaderVert, 1, &testVertSource, DE_NULL);
3407		glShaderSource(shaderFrag, 1, &testFragSource, DE_NULL);
3408
3409		glCompileShader(shaderVert);
3410		glCompileShader(shaderFrag);
3411		expectError(GL_NO_ERROR);
3412
3413		GLuint program = glCreateProgram();
3414		glAttachShader(program, shaderVert);
3415		glAttachShader(program, shaderFrag);
3416		glLinkProgram(program);
3417		glUseProgram(program);
3418		expectError(GL_NO_ERROR);
3419
3420		GLint location;
3421
3422		float matrixValues[4 * 4] =
3423		{
3424			-1.0f,	0.1f,	4.0f,	800.0f,
3425			13.0f,	55.0f,	12.0f,	91.0f,
3426			-55.1f,	1.1f,	98.0f,	19.0f,
3427			41.0f,	65.0f,	4.0f,	12.2f,
3428		};
3429
3430		// the values of the matrix are returned in column major order but they can be given in either order
3431
3432		location = glGetUniformLocation(program,"mat2Uniform");
3433		glUniformMatrix2fv(location, 1, GL_FALSE, matrixValues);
3434		verifyUniformMatrixValues<2>(m_testCtx, *this, program, location, matrixValues, false);
3435		glUniformMatrix2fv(location, 1, GL_TRUE, matrixValues);
3436		verifyUniformMatrixValues<2>(m_testCtx, *this, program, location, matrixValues, true);
3437
3438		location = glGetUniformLocation(program,"mat3Uniform");
3439		glUniformMatrix3fv(location, 1, GL_FALSE, matrixValues);
3440		verifyUniformMatrixValues<3>(m_testCtx, *this, program, location, matrixValues, false);
3441		glUniformMatrix3fv(location, 1, GL_TRUE, matrixValues);
3442		verifyUniformMatrixValues<3>(m_testCtx, *this, program, location, matrixValues, true);
3443
3444		location = glGetUniformLocation(program,"mat4Uniform");
3445		glUniformMatrix4fv(location, 1, GL_FALSE, matrixValues);
3446		verifyUniformMatrixValues<4>(m_testCtx, *this, program, location, matrixValues, false);
3447		glUniformMatrix4fv(location, 1, GL_TRUE, matrixValues);
3448		verifyUniformMatrixValues<4>(m_testCtx, *this, program, location, matrixValues, true);
3449
3450		glUseProgram(0);
3451		glDeleteShader(shaderVert);
3452		glDeleteShader(shaderFrag);
3453		glDeleteProgram(program);
3454		expectError(GL_NO_ERROR);
3455	}
3456};
3457
3458class PrecisionFormatCase : public ApiCase
3459{
3460public:
3461	struct RequiredFormat
3462	{
3463		int negativeRange;
3464		int positiveRange;
3465		int precision;
3466	};
3467
3468	PrecisionFormatCase (Context& context, const char* name, const char* description, glw::GLenum shaderType, glw::GLenum precisionType)
3469		: ApiCase			(context, name, description)
3470		, m_shaderType		(shaderType)
3471		, m_precisionType	(precisionType)
3472	{
3473	}
3474
3475private:
3476	void test (void)
3477	{
3478		const RequiredFormat											expected = getRequiredFormat();
3479		bool															error = false;
3480		gls::StateQueryUtil::StateQueryMemoryWriteGuard<glw::GLboolean>	shaderCompiler;
3481		gls::StateQueryUtil::StateQueryMemoryWriteGuard<glw::GLint[2]>	range;
3482		gls::StateQueryUtil::StateQueryMemoryWriteGuard<glw::GLint>		precision;
3483
3484		// query values
3485		glGetShaderPrecisionFormat(m_shaderType, m_precisionType, range, &precision);
3486		expectError(GL_NO_ERROR);
3487
3488		if (!range.verifyValidity(m_testCtx))
3489			return;
3490		if (!precision.verifyValidity(m_testCtx))
3491			return;
3492
3493		m_log
3494			<< tcu::TestLog::Message
3495			<< "range[0] = " << range[0] << "\n"
3496			<< "range[1] = " << range[1] << "\n"
3497			<< "precision = " << precision
3498			<< tcu::TestLog::EndMessage;
3499
3500		// verify values
3501
3502		if (m_precisionType == GL_HIGH_FLOAT)
3503		{
3504			// highp float must be IEEE 754 single
3505
3506			if (range[0] != expected.negativeRange ||
3507				range[1] != expected.positiveRange ||
3508				precision != expected.precision)
3509			{
3510				m_log
3511					<< tcu::TestLog::Message
3512					<< "// ERROR: Invalid precision format, expected:\n"
3513					<< "\trange[0] = " << expected.negativeRange << "\n"
3514					<< "\trange[1] = " << expected.positiveRange << "\n"
3515					<< "\tprecision = " << expected.precision
3516					<< tcu::TestLog::EndMessage;
3517				error = true;
3518			}
3519		}
3520		else
3521		{
3522			if (range[0] < expected.negativeRange)
3523			{
3524				m_log << tcu::TestLog::Message << "// ERROR: Invalid range[0], expected greater or equal to " << expected.negativeRange << tcu::TestLog::EndMessage;
3525				error = true;
3526			}
3527
3528			if (range[1] < expected.positiveRange)
3529			{
3530				m_log << tcu::TestLog::Message << "// ERROR: Invalid range[1], expected greater or equal to " << expected.positiveRange << tcu::TestLog::EndMessage;
3531				error = true;
3532			}
3533
3534			if (precision < expected.precision)
3535			{
3536				m_log << tcu::TestLog::Message << "// ERROR: Invalid precision, expected greater or equal to " << expected.precision << tcu::TestLog::EndMessage;
3537				error = true;
3538			}
3539		}
3540
3541		if (error)
3542			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid precision/range");
3543	}
3544
3545	RequiredFormat getRequiredFormat (void) const
3546	{
3547		// Precisions for different types.
3548		const RequiredFormat requirements[] =
3549		{
3550			{   0,   0,  8 }, //!< lowp float
3551			{  13,  13, 10 }, //!< mediump float
3552			{ 127, 127, 23 }, //!< highp float
3553			{   8,   7,  0 }, //!< lowp int
3554			{  15,  14,  0 }, //!< mediump int
3555			{  31,  30,  0 }, //!< highp int
3556		};
3557		const int ndx = (int)m_precisionType - (int)GL_LOW_FLOAT;
3558
3559		DE_ASSERT(ndx >= 0);
3560		DE_ASSERT(ndx < DE_LENGTH_OF_ARRAY(requirements));
3561		return requirements[ndx];
3562	}
3563
3564	const glw::GLenum m_shaderType;
3565	const glw::GLenum m_precisionType;
3566};
3567
3568} // anonymous
3569
3570
3571ShaderStateQueryTests::ShaderStateQueryTests (Context& context)
3572	: TestCaseGroup(context, "shader", "Shader State Query tests")
3573{
3574}
3575
3576void ShaderStateQueryTests::init (void)
3577{
3578	// shader
3579	addChild(new ShaderTypeCase						(m_context, "shader_type",							"SHADER_TYPE"));
3580	addChild(new ShaderCompileStatusCase			(m_context, "shader_compile_status",				"COMPILE_STATUS"));
3581	addChild(new ShaderInfoLogCase					(m_context, "shader_info_log_length",				"INFO_LOG_LENGTH"));
3582	addChild(new ShaderSourceCase					(m_context, "shader_source_length",					"SHADER_SOURCE_LENGTH"));
3583
3584	// shader and program
3585	addChild(new DeleteStatusCase					(m_context, "delete_status",						"DELETE_STATUS"));
3586
3587	// vertex-attrib
3588	addChild(new CurrentVertexAttribInitialCase		(m_context, "current_vertex_attrib_initial",		"CURRENT_VERTEX_ATTRIB"));
3589	addChild(new CurrentVertexAttribFloatCase		(m_context, "current_vertex_attrib_float",			"CURRENT_VERTEX_ATTRIB"));
3590	addChild(new CurrentVertexAttribIntCase			(m_context, "current_vertex_attrib_int",			"CURRENT_VERTEX_ATTRIB"));
3591	addChild(new CurrentVertexAttribUintCase		(m_context, "current_vertex_attrib_uint",			"CURRENT_VERTEX_ATTRIB"));
3592	addChild(new CurrentVertexAttribConversionCase	(m_context, "current_vertex_attrib_float_to_int",	"CURRENT_VERTEX_ATTRIB"));
3593
3594	// program
3595	addChild(new ProgramInfoLogCase					(m_context, "program_info_log_length",				"INFO_LOG_LENGTH"));
3596	addChild(new ProgramValidateStatusCase			(m_context, "program_validate_status",				"VALIDATE_STATUS"));
3597	addChild(new ProgramAttachedShadersCase			(m_context, "program_attached_shaders",				"ATTACHED_SHADERS"));
3598
3599	addChild(new ProgramActiveUniformNameCase		(m_context, "program_active_uniform_name",			"ACTIVE_UNIFORMS and ACTIVE_UNIFORM_MAX_LENGTH"));
3600	addChild(new ProgramUniformCase					(m_context, "program_active_uniform_types",			"UNIFORM_TYPE, UNIFORM_SIZE, and UNIFORM_IS_ROW_MAJOR"));
3601	addChild(new ProgramActiveUniformBlocksCase		(m_context, "program_active_uniform_blocks",		"ACTIVE_UNIFORM_BLOCK_x"));
3602	addChild(new ProgramBinaryCase					(m_context, "program_binary",						"PROGRAM_BINARY_LENGTH and PROGRAM_BINARY_RETRIEVABLE_HINT"));
3603
3604	// transform feedback
3605	addChild(new TransformFeedbackCase				(m_context, "transform_feedback",					"TRANSFORM_FEEDBACK_BUFFER_MODE, TRANSFORM_FEEDBACK_VARYINGS, TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH"));
3606
3607	// attribute related
3608	addChild(new ActiveAttributesCase				(m_context, "active_attributes",					"ACTIVE_ATTRIBUTES and ACTIVE_ATTRIBUTE_MAX_LENGTH"));
3609	addChild(new VertexAttributeSizeCase			(m_context, "vertex_attrib_size",					"VERTEX_ATTRIB_ARRAY_SIZE"));
3610	addChild(new VertexAttributeTypeCase			(m_context, "vertex_attrib_type",					"VERTEX_ATTRIB_ARRAY_TYPE"));
3611	addChild(new VertexAttributeStrideCase			(m_context, "vertex_attrib_stride",					"VERTEX_ATTRIB_ARRAY_STRIDE"));
3612	addChild(new VertexAttributeNormalizedCase		(m_context, "vertex_attrib_normalized",				"VERTEX_ATTRIB_ARRAY_NORMALIZED"));
3613	addChild(new VertexAttributeIntegerCase			(m_context, "vertex_attrib_integer",				"VERTEX_ATTRIB_ARRAY_INTEGER"));
3614	addChild(new VertexAttributeEnabledCase			(m_context, "vertex_attrib_array_enabled",			"VERTEX_ATTRIB_ARRAY_ENABLED"));
3615	addChild(new VertexAttributeDivisorCase			(m_context, "vertex_attrib_array_divisor",			"VERTEX_ATTRIB_ARRAY_DIVISOR"));
3616	addChild(new VertexAttributeBufferBindingCase	(m_context, "vertex_attrib_array_buffer_binding",	"VERTEX_ATTRIB_ARRAY_BUFFER_BINDING"));
3617	addChild(new VertexAttributePointerCase			(m_context, "vertex_attrib_pointerv",				"GetVertexAttribPointerv"));
3618
3619	// uniform values
3620	addChild(new UniformValueFloatCase				(m_context, "uniform_value_float",					"GetUniform*"));
3621	addChild(new UniformValueIntCase				(m_context, "uniform_value_int",					"GetUniform*"));
3622	addChild(new UniformValueUintCase				(m_context, "uniform_value_uint",					"GetUniform*"));
3623	addChild(new UniformValueBooleanCase			(m_context, "uniform_value_boolean",				"GetUniform*"));
3624	addChild(new UniformValueSamplerCase			(m_context, "uniform_value_sampler",				"GetUniform*"));
3625	addChild(new UniformValueArrayCase				(m_context, "uniform_value_array",					"GetUniform*"));
3626	addChild(new UniformValueMatrixCase				(m_context, "uniform_value_matrix",					"GetUniform*"));
3627
3628	// precision format query
3629	addChild(new PrecisionFormatCase				(m_context, "precision_vertex_lowp_float",			"GetShaderPrecisionFormat",		GL_VERTEX_SHADER,	GL_LOW_FLOAT));
3630	addChild(new PrecisionFormatCase				(m_context, "precision_vertex_mediump_float",		"GetShaderPrecisionFormat",		GL_VERTEX_SHADER,	GL_MEDIUM_FLOAT));
3631	addChild(new PrecisionFormatCase				(m_context, "precision_vertex_highp_float",			"GetShaderPrecisionFormat",		GL_VERTEX_SHADER,	GL_HIGH_FLOAT));
3632	addChild(new PrecisionFormatCase				(m_context, "precision_vertex_lowp_int",			"GetShaderPrecisionFormat",		GL_VERTEX_SHADER,	GL_LOW_INT));
3633	addChild(new PrecisionFormatCase				(m_context, "precision_vertex_mediump_int",			"GetShaderPrecisionFormat",		GL_VERTEX_SHADER,	GL_MEDIUM_INT));
3634	addChild(new PrecisionFormatCase				(m_context, "precision_vertex_highp_int",			"GetShaderPrecisionFormat",		GL_VERTEX_SHADER,	GL_HIGH_INT));
3635	addChild(new PrecisionFormatCase				(m_context, "precision_fragment_lowp_float",		"GetShaderPrecisionFormat",		GL_FRAGMENT_SHADER,	GL_LOW_FLOAT));
3636	addChild(new PrecisionFormatCase				(m_context, "precision_fragment_mediump_float",		"GetShaderPrecisionFormat",		GL_FRAGMENT_SHADER,	GL_MEDIUM_FLOAT));
3637	addChild(new PrecisionFormatCase				(m_context, "precision_fragment_highp_float",		"GetShaderPrecisionFormat",		GL_FRAGMENT_SHADER,	GL_HIGH_FLOAT));
3638	addChild(new PrecisionFormatCase				(m_context, "precision_fragment_lowp_int",			"GetShaderPrecisionFormat",		GL_FRAGMENT_SHADER,	GL_LOW_INT));
3639	addChild(new PrecisionFormatCase				(m_context, "precision_fragment_mediump_int",		"GetShaderPrecisionFormat",		GL_FRAGMENT_SHADER,	GL_MEDIUM_INT));
3640	addChild(new PrecisionFormatCase				(m_context, "precision_fragment_highp_int",			"GetShaderPrecisionFormat",		GL_FRAGMENT_SHADER,	GL_HIGH_INT));
3641}
3642
3643} // Functional
3644} // gles3
3645} // deqp
3646