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