xref: /aosp_15_r20/external/deqp/modules/gles2/functional/es2fShaderStateQueryTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program OpenGL ES 2.0 Module
3  * -------------------------------------------------
4  *
5  * Copyright 2014 The Android Open Source Project
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*!
20  * \file
21  * \brief Rbo state query tests.
22  *//*--------------------------------------------------------------------*/
23 
24 #include "es2fShaderStateQueryTests.hpp"
25 #include "glsStateQueryUtil.hpp"
26 #include "es2fApiCase.hpp"
27 #include "gluRenderContext.hpp"
28 #include "gluShaderProgram.hpp"
29 #include "glwEnums.hpp"
30 #include "glwFunctions.hpp"
31 #include "deRandom.hpp"
32 #include "deMath.h"
33 #include "deString.h"
34 
35 using namespace glw; // GLint and other GL types
36 using deqp::gls::StateQueryUtil::StateQueryMemoryWriteGuard;
37 
38 namespace deqp
39 {
40 namespace gles2
41 {
42 namespace Functional
43 {
44 namespace
45 {
46 
47 static const char *commonTestVertSource = "void main (void)\n"
48                                           "{\n"
49                                           "    gl_Position = vec4(0.0);\n"
50                                           "}\n";
51 static const char *commonTestFragSource = "void main (void)\n"
52                                           "{\n"
53                                           "    gl_FragColor = vec4(0.0);\n"
54                                           "}\n";
55 
56 static const char *brokenShader = "broken, this should not compile!\n"
57                                   "\n";
58 
59 // rounds x.1 to x+1
60 template <typename T>
roundGLfloatToNearestIntegerUp(GLfloat val)61 T roundGLfloatToNearestIntegerUp(GLfloat val)
62 {
63     return (T)(ceil(val));
64 }
65 
66 // rounds x.9 to x
67 template <typename T>
roundGLfloatToNearestIntegerDown(GLfloat val)68 T roundGLfloatToNearestIntegerDown(GLfloat val)
69 {
70     return (T)(floor(val));
71 }
72 
checkIntEquals(tcu::TestContext & testCtx,GLint got,GLint expected)73 bool checkIntEquals(tcu::TestContext &testCtx, GLint got, GLint expected)
74 {
75     using tcu::TestLog;
76 
77     if (got != expected)
78     {
79         testCtx.getLog() << TestLog::Message << "// ERROR: Expected " << expected << "; got " << got
80                          << TestLog::EndMessage;
81         if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
82             testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid value");
83         return false;
84     }
85     return true;
86 }
87 
checkPointerEquals(tcu::TestContext & testCtx,const void * got,const void * expected)88 void checkPointerEquals(tcu::TestContext &testCtx, const void *got, const void *expected)
89 {
90     using tcu::TestLog;
91 
92     if (got != expected)
93     {
94         testCtx.getLog() << TestLog::Message << "// ERROR: Expected " << expected << "; got " << got
95                          << TestLog::EndMessage;
96         if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
97             testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid value");
98     }
99 }
100 
verifyShaderParam(tcu::TestContext & testCtx,glu::CallLogWrapper & gl,GLuint shader,GLenum pname,GLenum reference)101 void verifyShaderParam(tcu::TestContext &testCtx, glu::CallLogWrapper &gl, GLuint shader, GLenum pname,
102                        GLenum reference)
103 {
104     StateQueryMemoryWriteGuard<GLint> state;
105     gl.glGetShaderiv(shader, pname, &state);
106 
107     if (state.verifyValidity(testCtx))
108         checkIntEquals(testCtx, state, reference);
109 }
110 
verifyProgramParam(tcu::TestContext & testCtx,glu::CallLogWrapper & gl,GLuint program,GLenum pname,GLenum reference)111 bool verifyProgramParam(tcu::TestContext &testCtx, glu::CallLogWrapper &gl, GLuint program, GLenum pname,
112                         GLenum reference)
113 {
114     StateQueryMemoryWriteGuard<GLint> state;
115     gl.glGetProgramiv(program, pname, &state);
116 
117     if (state.verifyValidity(testCtx))
118         return checkIntEquals(testCtx, state, reference);
119     return false;
120 }
121 
verifyCurrentVertexAttribf(tcu::TestContext & testCtx,glu::CallLogWrapper & gl,GLint index,GLfloat x,GLfloat y,GLfloat z,GLfloat w)122 void verifyCurrentVertexAttribf(tcu::TestContext &testCtx, glu::CallLogWrapper &gl, GLint index, GLfloat x, GLfloat y,
123                                 GLfloat z, GLfloat w)
124 {
125     using tcu::TestLog;
126 
127     StateQueryMemoryWriteGuard<GLfloat[4]> attribValue;
128     gl.glGetVertexAttribfv(index, GL_CURRENT_VERTEX_ATTRIB, attribValue);
129 
130     attribValue.verifyValidity(testCtx);
131 
132     if (attribValue[0] != x || attribValue[1] != y || attribValue[2] != z || attribValue[3] != w)
133     {
134         testCtx.getLog() << TestLog::Message << "// ERROR: Expected [" << x << "," << y << "," << z << "," << w << "];"
135                          << "got [" << attribValue[0] << "," << attribValue[1] << "," << attribValue[2] << ","
136                          << attribValue[3] << "]" << TestLog::EndMessage;
137         if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
138             testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid attribute value");
139     }
140 }
141 
verifyCurrentVertexAttribConversion(tcu::TestContext & testCtx,glu::CallLogWrapper & gl,GLint index,GLfloat x,GLfloat y,GLfloat z,GLfloat w)142 void verifyCurrentVertexAttribConversion(tcu::TestContext &testCtx, glu::CallLogWrapper &gl, GLint index, GLfloat x,
143                                          GLfloat y, GLfloat z, GLfloat w)
144 {
145     using tcu::TestLog;
146 
147     StateQueryMemoryWriteGuard<GLint[4]> attribValue;
148     gl.glGetVertexAttribiv(index, GL_CURRENT_VERTEX_ATTRIB, attribValue);
149 
150     attribValue.verifyValidity(testCtx);
151 
152     const GLint referenceAsGLintMin[] = {
153         roundGLfloatToNearestIntegerDown<GLint>(x), roundGLfloatToNearestIntegerDown<GLint>(y),
154         roundGLfloatToNearestIntegerDown<GLint>(z), roundGLfloatToNearestIntegerDown<GLint>(w)};
155     const GLint referenceAsGLintMax[] = {
156         roundGLfloatToNearestIntegerUp<GLint>(x), roundGLfloatToNearestIntegerUp<GLint>(y),
157         roundGLfloatToNearestIntegerUp<GLint>(z), roundGLfloatToNearestIntegerUp<GLint>(w)};
158 
159     if (attribValue[0] < referenceAsGLintMin[0] || attribValue[0] > referenceAsGLintMax[0] ||
160         attribValue[1] < referenceAsGLintMin[1] || attribValue[1] > referenceAsGLintMax[1] ||
161         attribValue[2] < referenceAsGLintMin[2] || attribValue[2] > referenceAsGLintMax[2] ||
162         attribValue[3] < referenceAsGLintMin[3] || attribValue[3] > referenceAsGLintMax[3])
163     {
164         testCtx.getLog() << TestLog::Message << "// ERROR: expected in range "
165                          << "[" << referenceAsGLintMin[0] << " " << referenceAsGLintMax[0] << "], "
166                          << "[" << referenceAsGLintMin[1] << " " << referenceAsGLintMax[1] << "], "
167                          << "[" << referenceAsGLintMin[2] << " " << referenceAsGLintMax[2] << "], "
168                          << "[" << referenceAsGLintMin[3] << " " << referenceAsGLintMax[3] << "]"
169                          << "; got " << attribValue[0] << ", " << attribValue[1] << ", " << attribValue[2] << ", "
170                          << attribValue[3] << " "
171                          << "; Input=" << x << "; " << y << "; " << z << "; " << w << " " << TestLog::EndMessage;
172 
173         if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
174             testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid attribute value");
175     }
176 }
177 
verifyVertexAttrib(tcu::TestContext & testCtx,glu::CallLogWrapper & gl,GLint index,GLenum pname,GLenum reference)178 void verifyVertexAttrib(tcu::TestContext &testCtx, glu::CallLogWrapper &gl, GLint index, GLenum pname, GLenum reference)
179 {
180     StateQueryMemoryWriteGuard<GLint> state;
181     gl.glGetVertexAttribiv(index, pname, &state);
182 
183     if (state.verifyValidity(testCtx))
184         checkIntEquals(testCtx, state, reference);
185 }
186 
verifyUniformValue1f(tcu::TestContext & testCtx,glu::CallLogWrapper & gl,GLuint program,GLint location,float x)187 void verifyUniformValue1f(tcu::TestContext &testCtx, glu::CallLogWrapper &gl, GLuint program, GLint location, float x)
188 {
189     using tcu::TestLog;
190 
191     StateQueryMemoryWriteGuard<GLfloat[1]> state;
192     gl.glGetUniformfv(program, location, state);
193 
194     if (!state.verifyValidity(testCtx))
195         return;
196 
197     if (state[0] != x)
198     {
199         testCtx.getLog() << TestLog::Message << "// ERROR: expected [" << x << "]; got [" << state[0] << "]"
200                          << TestLog::EndMessage;
201 
202         if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
203             testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid uniform value");
204     }
205 }
206 
verifyUniformValue2f(tcu::TestContext & testCtx,glu::CallLogWrapper & gl,GLuint program,GLint location,float x,float y)207 void verifyUniformValue2f(tcu::TestContext &testCtx, glu::CallLogWrapper &gl, GLuint program, GLint location, float x,
208                           float y)
209 {
210     using tcu::TestLog;
211 
212     StateQueryMemoryWriteGuard<GLfloat[2]> state;
213     gl.glGetUniformfv(program, location, state);
214 
215     if (!state.verifyValidity(testCtx))
216         return;
217 
218     if (state[0] != x || state[1] != y)
219     {
220         testCtx.getLog() << TestLog::Message << "// ERROR: expected [" << x << ", " << y << "]; got [" << state[0]
221                          << ", " << state[1] << "]" << TestLog::EndMessage;
222 
223         if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
224             testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid uniform value");
225     }
226 }
227 
verifyUniformValue3f(tcu::TestContext & testCtx,glu::CallLogWrapper & gl,GLuint program,GLint location,float x,float y,float z)228 void verifyUniformValue3f(tcu::TestContext &testCtx, glu::CallLogWrapper &gl, GLuint program, GLint location, float x,
229                           float y, float z)
230 {
231     using tcu::TestLog;
232 
233     StateQueryMemoryWriteGuard<GLfloat[3]> state;
234     gl.glGetUniformfv(program, location, state);
235 
236     if (!state.verifyValidity(testCtx))
237         return;
238 
239     if (state[0] != x || state[1] != y || state[2] != z)
240     {
241         testCtx.getLog() << TestLog::Message << "// ERROR: expected [" << x << ", " << y << ", " << z << "]; got ["
242                          << state[0] << ", " << state[1] << ", " << state[2] << "]" << TestLog::EndMessage;
243 
244         if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
245             testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid uniform value");
246     }
247 }
248 
verifyUniformValue4f(tcu::TestContext & testCtx,glu::CallLogWrapper & gl,GLuint program,GLint location,float x,float y,float z,float w)249 void verifyUniformValue4f(tcu::TestContext &testCtx, glu::CallLogWrapper &gl, GLuint program, GLint location, float x,
250                           float y, float z, float w)
251 {
252     using tcu::TestLog;
253 
254     StateQueryMemoryWriteGuard<GLfloat[4]> state;
255     gl.glGetUniformfv(program, location, state);
256 
257     if (!state.verifyValidity(testCtx))
258         return;
259 
260     if (state[0] != x || state[1] != y || state[2] != z || state[3] != w)
261     {
262         testCtx.getLog() << TestLog::Message << "// ERROR: expected [" << x << ", " << y << ", " << z << ", " << w
263                          << "]; got [" << state[0] << ", " << state[1] << ", " << state[2] << ", " << state[3] << "]"
264                          << TestLog::EndMessage;
265 
266         if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
267             testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid uniform value");
268     }
269 }
270 
verifyUniformValue1i(tcu::TestContext & testCtx,glu::CallLogWrapper & gl,GLuint program,GLint location,GLint x)271 void verifyUniformValue1i(tcu::TestContext &testCtx, glu::CallLogWrapper &gl, GLuint program, GLint location, GLint x)
272 {
273     using tcu::TestLog;
274 
275     StateQueryMemoryWriteGuard<GLint[1]> state;
276     gl.glGetUniformiv(program, location, state);
277 
278     if (!state.verifyValidity(testCtx))
279         return;
280 
281     if (state[0] != x)
282     {
283         testCtx.getLog() << TestLog::Message << "// ERROR: expected [" << x << "]; got [" << state[0] << "]"
284                          << TestLog::EndMessage;
285 
286         if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
287             testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid uniform value");
288     }
289 }
290 
verifyUniformValue2i(tcu::TestContext & testCtx,glu::CallLogWrapper & gl,GLuint program,GLint location,GLint x,GLint y)291 void verifyUniformValue2i(tcu::TestContext &testCtx, glu::CallLogWrapper &gl, GLuint program, GLint location, GLint x,
292                           GLint y)
293 {
294     using tcu::TestLog;
295 
296     StateQueryMemoryWriteGuard<GLint[2]> state;
297     gl.glGetUniformiv(program, location, state);
298 
299     if (!state.verifyValidity(testCtx))
300         return;
301 
302     if (state[0] != x || state[1] != y)
303     {
304         testCtx.getLog() << TestLog::Message << "// ERROR: expected [" << x << ", " << y << "]; got [" << state[0]
305                          << ", " << state[1] << "]" << TestLog::EndMessage;
306 
307         if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
308             testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid uniform value");
309     }
310 }
311 
verifyUniformValue3i(tcu::TestContext & testCtx,glu::CallLogWrapper & gl,GLuint program,GLint location,GLint x,GLint y,GLint z)312 void verifyUniformValue3i(tcu::TestContext &testCtx, glu::CallLogWrapper &gl, GLuint program, GLint location, GLint x,
313                           GLint y, GLint z)
314 {
315     using tcu::TestLog;
316 
317     StateQueryMemoryWriteGuard<GLint[3]> state;
318     gl.glGetUniformiv(program, location, state);
319 
320     if (!state.verifyValidity(testCtx))
321         return;
322 
323     if (state[0] != x || state[1] != y || state[2] != z)
324     {
325         testCtx.getLog() << TestLog::Message << "// ERROR: expected [" << x << ", " << y << ", " << z << "]; got ["
326                          << state[0] << ", " << state[1] << ", " << state[2] << "]" << TestLog::EndMessage;
327 
328         if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
329             testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid uniform value");
330     }
331 }
332 
verifyUniformValue4i(tcu::TestContext & testCtx,glu::CallLogWrapper & gl,GLuint program,GLint location,GLint x,GLint y,GLint z,GLint w)333 void verifyUniformValue4i(tcu::TestContext &testCtx, glu::CallLogWrapper &gl, GLuint program, GLint location, GLint x,
334                           GLint y, GLint z, GLint w)
335 {
336     using tcu::TestLog;
337 
338     StateQueryMemoryWriteGuard<GLint[4]> state;
339     gl.glGetUniformiv(program, location, state);
340 
341     if (!state.verifyValidity(testCtx))
342         return;
343 
344     if (state[0] != x || state[1] != y || state[2] != z || state[3] != w)
345     {
346         testCtx.getLog() << TestLog::Message << "// ERROR: expected [" << x << ", " << y << ", " << z << ", " << w
347                          << "]; got [" << state[0] << ", " << state[1] << ", " << state[2] << ", " << state[3] << "]"
348                          << TestLog::EndMessage;
349 
350         if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
351             testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid uniform value");
352     }
353 }
354 
355 template <int Count>
verifyUniformValues(tcu::TestContext & testCtx,glu::CallLogWrapper & gl,GLuint program,GLint location,const GLfloat * values)356 void verifyUniformValues(tcu::TestContext &testCtx, glu::CallLogWrapper &gl, GLuint program, GLint location,
357                          const GLfloat *values)
358 {
359     using tcu::TestLog;
360 
361     StateQueryMemoryWriteGuard<GLfloat[Count]> state;
362     gl.glGetUniformfv(program, location, state);
363 
364     if (!state.verifyValidity(testCtx))
365         return;
366 
367     for (int ndx = 0; ndx < Count; ++ndx)
368     {
369         if (values[ndx] != state[ndx])
370         {
371             testCtx.getLog() << TestLog::Message << "// ERROR: at index " << ndx << " expected " << values[ndx]
372                              << "; got " << state[ndx] << TestLog::EndMessage;
373 
374             if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
375                 testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid uniform value");
376         }
377     }
378 }
379 
380 template <int N>
verifyUniformMatrixValues(tcu::TestContext & testCtx,glu::CallLogWrapper & gl,GLuint program,GLint location,const GLfloat * values,bool transpose)381 void verifyUniformMatrixValues(tcu::TestContext &testCtx, glu::CallLogWrapper &gl, GLuint program, GLint location,
382                                const GLfloat *values, bool transpose)
383 {
384     using tcu::TestLog;
385 
386     StateQueryMemoryWriteGuard<GLfloat[N * N]> state;
387     gl.glGetUniformfv(program, location, state);
388 
389     if (!state.verifyValidity(testCtx))
390         return;
391 
392     for (int y = 0; y < N; ++y)
393         for (int x = 0; x < N; ++x)
394         {
395             const int refIndex   = y * N + x;
396             const int stateIndex = transpose ? (x * N + y) : (y * N + x);
397 
398             if (values[refIndex] != state[stateIndex])
399             {
400                 testCtx.getLog() << TestLog::Message << "// ERROR: at index [" << y << "][" << x << "] expected "
401                                  << values[refIndex] << "; got " << state[stateIndex] << TestLog::EndMessage;
402 
403                 if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
404                     testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid uniform value");
405             }
406         }
407 }
408 
requireShaderCompiler(tcu::TestContext & testCtx,glu::CallLogWrapper & gl)409 void requireShaderCompiler(tcu::TestContext &testCtx, glu::CallLogWrapper &gl)
410 {
411     StateQueryMemoryWriteGuard<GLboolean> state;
412     gl.glGetBooleanv(GL_SHADER_COMPILER, &state);
413 
414     if (!state.verifyValidity(testCtx) || state != GL_TRUE)
415         throw tcu::NotSupportedError("Test requires SHADER_COMPILER = TRUE");
416 }
417 
418 class ShaderTypeCase : public ApiCase
419 {
420 public:
ShaderTypeCase(Context & context,const char * name,const char * description)421     ShaderTypeCase(Context &context, const char *name, const char *description) : ApiCase(context, name, description)
422     {
423     }
424 
test(void)425     void test(void)
426     {
427         const GLenum shaderTypes[] = {GL_VERTEX_SHADER, GL_FRAGMENT_SHADER};
428         for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(shaderTypes); ++ndx)
429         {
430             const GLuint shader = glCreateShader(shaderTypes[ndx]);
431             verifyShaderParam(m_testCtx, *this, shader, GL_SHADER_TYPE, shaderTypes[ndx]);
432             glDeleteShader(shader);
433         }
434     }
435 };
436 
437 class ShaderCompileStatusCase : public ApiCase
438 {
439 public:
ShaderCompileStatusCase(Context & context,const char * name,const char * description)440     ShaderCompileStatusCase(Context &context, const char *name, const char *description)
441         : ApiCase(context, name, description)
442     {
443     }
444 
test(void)445     void test(void)
446     {
447         requireShaderCompiler(m_testCtx, *this);
448 
449         GLuint shaderVert = glCreateShader(GL_VERTEX_SHADER);
450         GLuint shaderFrag = glCreateShader(GL_FRAGMENT_SHADER);
451 
452         verifyShaderParam(m_testCtx, *this, shaderVert, GL_COMPILE_STATUS, GL_FALSE);
453         verifyShaderParam(m_testCtx, *this, shaderFrag, GL_COMPILE_STATUS, GL_FALSE);
454 
455         glShaderSource(shaderVert, 1, &commonTestVertSource, DE_NULL);
456         glShaderSource(shaderFrag, 1, &commonTestFragSource, DE_NULL);
457 
458         glCompileShader(shaderVert);
459         glCompileShader(shaderFrag);
460         expectError(GL_NO_ERROR);
461 
462         verifyShaderParam(m_testCtx, *this, shaderVert, GL_COMPILE_STATUS, GL_TRUE);
463         verifyShaderParam(m_testCtx, *this, shaderFrag, GL_COMPILE_STATUS, GL_TRUE);
464 
465         glDeleteShader(shaderVert);
466         glDeleteShader(shaderFrag);
467         expectError(GL_NO_ERROR);
468     }
469 };
470 
471 class ShaderInfoLogCase : public ApiCase
472 {
473 public:
ShaderInfoLogCase(Context & context,const char * name,const char * description)474     ShaderInfoLogCase(Context &context, const char *name, const char *description) : ApiCase(context, name, description)
475     {
476     }
477 
test(void)478     void test(void)
479     {
480         requireShaderCompiler(m_testCtx, *this);
481 
482         using tcu::TestLog;
483 
484         // INFO_LOG_LENGTH is 0 by default and it includes null-terminator
485         const GLuint shader = glCreateShader(GL_VERTEX_SHADER);
486         verifyShaderParam(m_testCtx, *this, shader, GL_INFO_LOG_LENGTH, 0);
487 
488         glShaderSource(shader, 1, &brokenShader, DE_NULL);
489         glCompileShader(shader);
490         expectError(GL_NO_ERROR);
491 
492         // check the log length
493         StateQueryMemoryWriteGuard<GLint> logLength;
494         glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &logLength);
495         if (!logLength.verifyValidity(m_testCtx))
496         {
497             glDeleteShader(shader);
498             return;
499         }
500         if (logLength == 0)
501         {
502             glDeleteShader(shader);
503             return;
504         }
505 
506         // check normal case
507         {
508             char buffer[2048] = {'x'}; // non-zero initialization
509 
510             GLint written = 0; // written does not include null terminator
511             glGetShaderInfoLog(shader, DE_LENGTH_OF_ARRAY(buffer), &written, buffer);
512 
513             // check lengths are consistent
514             if (logLength <= DE_LENGTH_OF_ARRAY(buffer))
515             {
516                 if (written != logLength - 1)
517                 {
518                     m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected length " << logLength - 1 << "; got "
519                                        << written << TestLog::EndMessage;
520                     if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
521                         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid log length");
522                 }
523             }
524 
525             // check null-terminator, either at end of buffer or at buffer[written]
526             const char *terminator = &buffer[DE_LENGTH_OF_ARRAY(buffer) - 1];
527             if (logLength < DE_LENGTH_OF_ARRAY(buffer))
528                 terminator = &buffer[written];
529 
530             if (*terminator != '\0')
531             {
532                 m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected null terminator, got " << (int)*terminator
533                                    << TestLog::EndMessage;
534                 if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
535                     m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid log terminator");
536             }
537         }
538 
539         // check with too small buffer
540         {
541             char buffer[2048] = {'x'}; // non-zero initialization
542 
543             // check string always ends with \0, even with small buffers
544             GLint written = 0;
545             glGetShaderInfoLog(shader, 1, &written, buffer);
546             if (written != 0)
547             {
548                 m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected length 0; got " << written
549                                    << TestLog::EndMessage;
550                 if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
551                     m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid log length");
552             }
553             if (buffer[0] != '\0')
554             {
555                 m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected null terminator, got " << (int)buffer[0]
556                                    << TestLog::EndMessage;
557                 if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
558                     m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid log terminator");
559             }
560         }
561 
562         glDeleteShader(shader);
563         expectError(GL_NO_ERROR);
564     }
565 };
566 
567 class ShaderSourceCase : public ApiCase
568 {
569 public:
ShaderSourceCase(Context & context,const char * name,const char * description)570     ShaderSourceCase(Context &context, const char *name, const char *description) : ApiCase(context, name, description)
571     {
572     }
573 
test(void)574     void test(void)
575     {
576         requireShaderCompiler(m_testCtx, *this);
577 
578         using tcu::TestLog;
579 
580         // SHADER_SOURCE_LENGTH does include 0-terminator
581         const GLuint shader = glCreateShader(GL_VERTEX_SHADER);
582         verifyShaderParam(m_testCtx, *this, shader, GL_SHADER_SOURCE_LENGTH, 0);
583 
584         // check the SHADER_SOURCE_LENGTH
585         {
586             glShaderSource(shader, 1, &brokenShader, DE_NULL);
587             expectError(GL_NO_ERROR);
588 
589             StateQueryMemoryWriteGuard<GLint> sourceLength;
590             glGetShaderiv(shader, GL_SHADER_SOURCE_LENGTH, &sourceLength);
591 
592             sourceLength.verifyValidity(m_testCtx);
593 
594             const GLint referenceLength =
595                 (GLint)std::string(brokenShader).length() + 1; // including the null terminator
596             if (sourceLength != referenceLength)
597             {
598                 m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected length " << referenceLength << "; got "
599                                    << sourceLength << TestLog::EndMessage;
600                 if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
601                     m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid source length");
602             }
603         }
604 
605         // check the concat source SHADER_SOURCE_LENGTH
606         {
607             const char *shaders[] = {brokenShader, brokenShader};
608             glShaderSource(shader, 2, shaders, DE_NULL);
609             expectError(GL_NO_ERROR);
610 
611             StateQueryMemoryWriteGuard<GLint> sourceLength;
612             glGetShaderiv(shader, GL_SHADER_SOURCE_LENGTH, &sourceLength);
613 
614             sourceLength.verifyValidity(m_testCtx);
615 
616             const GLint referenceLength =
617                 2 * (GLint)std::string(brokenShader).length() + 1; // including the null terminator
618             if (sourceLength != referenceLength)
619             {
620                 m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected length " << referenceLength << "; got "
621                                    << sourceLength << TestLog::EndMessage;
622                 if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
623                     m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid source length");
624             }
625         }
626 
627         // check the string length
628         {
629             char buffer[2048] = {'x'};
630             DE_ASSERT(DE_LENGTH_OF_ARRAY(buffer) > 2 * (int)std::string(brokenShader).length());
631 
632             GLint written = 0; // not inluding null-terminator
633             glGetShaderSource(shader, DE_LENGTH_OF_ARRAY(buffer), &written, buffer);
634 
635             const GLint referenceLength = 2 * (GLint)std::string(brokenShader).length();
636             if (written != referenceLength)
637             {
638                 m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected write length " << referenceLength
639                                    << "; got " << written << TestLog::EndMessage;
640                 if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
641                     m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid source length");
642             }
643             // check null pointer at
644             else
645             {
646                 if (buffer[referenceLength] != '\0')
647                 {
648                     m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected null terminator at "
649                                        << referenceLength << TestLog::EndMessage;
650                     if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
651                         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "did not get a null terminator");
652                 }
653             }
654         }
655 
656         // check with small buffer
657         {
658             char buffer[2048] = {'x'};
659 
660             GLint written = 0;
661             glGetShaderSource(shader, 1, &written, buffer);
662 
663             if (written != 0)
664             {
665                 m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected write length 0; got " << written
666                                    << TestLog::EndMessage;
667                 if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
668                     m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid source length");
669             }
670             if (buffer[0] != '\0')
671             {
672                 m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected null terminator; got=" << int(buffer[0])
673                                    << ", char=" << buffer[0] << TestLog::EndMessage;
674                 if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
675                     m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid terminator");
676             }
677         }
678 
679         glDeleteShader(shader);
680         expectError(GL_NO_ERROR);
681     }
682 };
683 
684 class DeleteStatusCase : public ApiCase
685 {
686 public:
DeleteStatusCase(Context & context,const char * name,const char * description)687     DeleteStatusCase(Context &context, const char *name, const char *description) : ApiCase(context, name, description)
688     {
689     }
690 
test(void)691     void test(void)
692     {
693         GLuint shaderVert = glCreateShader(GL_VERTEX_SHADER);
694         GLuint shaderFrag = glCreateShader(GL_FRAGMENT_SHADER);
695 
696         glShaderSource(shaderVert, 1, &commonTestVertSource, DE_NULL);
697         glShaderSource(shaderFrag, 1, &commonTestFragSource, DE_NULL);
698 
699         glCompileShader(shaderVert);
700         glCompileShader(shaderFrag);
701         expectError(GL_NO_ERROR);
702 
703         verifyShaderParam(m_testCtx, *this, shaderVert, GL_COMPILE_STATUS, GL_TRUE);
704         verifyShaderParam(m_testCtx, *this, shaderFrag, GL_COMPILE_STATUS, GL_TRUE);
705 
706         GLuint shaderProg = glCreateProgram();
707         glAttachShader(shaderProg, shaderVert);
708         glAttachShader(shaderProg, shaderFrag);
709         glLinkProgram(shaderProg);
710         expectError(GL_NO_ERROR);
711 
712         verifyProgramParam(m_testCtx, *this, shaderProg, GL_LINK_STATUS, GL_TRUE);
713 
714         verifyShaderParam(m_testCtx, *this, shaderVert, GL_DELETE_STATUS, GL_FALSE);
715         verifyShaderParam(m_testCtx, *this, shaderFrag, GL_DELETE_STATUS, GL_FALSE);
716         verifyProgramParam(m_testCtx, *this, shaderProg, GL_DELETE_STATUS, GL_FALSE);
717         expectError(GL_NO_ERROR);
718 
719         glUseProgram(shaderProg);
720 
721         glDeleteShader(shaderVert);
722         glDeleteShader(shaderFrag);
723         glDeleteProgram(shaderProg);
724         expectError(GL_NO_ERROR);
725 
726         verifyShaderParam(m_testCtx, *this, shaderVert, GL_DELETE_STATUS, GL_TRUE);
727         verifyShaderParam(m_testCtx, *this, shaderFrag, GL_DELETE_STATUS, GL_TRUE);
728         verifyProgramParam(m_testCtx, *this, shaderProg, GL_DELETE_STATUS, GL_TRUE);
729         expectError(GL_NO_ERROR);
730 
731         glUseProgram(0);
732         expectError(GL_NO_ERROR);
733     }
734 };
735 
736 class CurrentVertexAttribInitialCase : public ApiCase
737 {
738 public:
CurrentVertexAttribInitialCase(Context & context,const char * name,const char * description)739     CurrentVertexAttribInitialCase(Context &context, const char *name, const char *description)
740         : ApiCase(context, name, description)
741     {
742     }
743 
test(void)744     void test(void)
745     {
746         using tcu::TestLog;
747 
748         int attribute_count = 16;
749         glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &attribute_count);
750 
751         // initial
752 
753         for (int index = 0; index < attribute_count; ++index)
754         {
755             StateQueryMemoryWriteGuard<GLfloat[4]> attribValue;
756             glGetVertexAttribfv(index, GL_CURRENT_VERTEX_ATTRIB, attribValue);
757             attribValue.verifyValidity(m_testCtx);
758 
759             if (attribValue[0] != 0.0f || attribValue[1] != 0.0f || attribValue[2] != 0.0f || attribValue[3] != 1.0f)
760             {
761                 m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected [0, 0, 0, 1];"
762                                    << "got [" << attribValue[0] << "," << attribValue[1] << "," << attribValue[2] << ","
763                                    << attribValue[3] << "]" << TestLog::EndMessage;
764                 if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
765                     m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid attribute value");
766             }
767         }
768     }
769 };
770 
771 class CurrentVertexAttribFloatCase : public ApiCase
772 {
773 public:
CurrentVertexAttribFloatCase(Context & context,const char * name,const char * description)774     CurrentVertexAttribFloatCase(Context &context, const char *name, const char *description)
775         : ApiCase(context, name, description)
776     {
777     }
778 
test(void)779     void test(void)
780     {
781         using tcu::TestLog;
782 
783         de::Random rnd(0xabcdef);
784 
785         int attribute_count = 16;
786         glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &attribute_count);
787 
788         // test write float/read float
789 
790         for (int index = 0; index < attribute_count; ++index)
791         {
792             const GLfloat x = rnd.getFloat(-64000, 64000);
793             const GLfloat y = rnd.getFloat(-64000, 64000);
794             const GLfloat z = rnd.getFloat(-64000, 64000);
795             const GLfloat w = rnd.getFloat(-64000, 64000);
796 
797             glVertexAttrib4f(index, x, y, z, w);
798             verifyCurrentVertexAttribf(m_testCtx, *this, index, x, y, z, w);
799         }
800         for (int index = 0; index < attribute_count; ++index)
801         {
802             const GLfloat x = rnd.getFloat(-64000, 64000);
803             const GLfloat y = rnd.getFloat(-64000, 64000);
804             const GLfloat z = rnd.getFloat(-64000, 64000);
805             const GLfloat w = 1.0f;
806 
807             glVertexAttrib3f(index, x, y, z);
808             verifyCurrentVertexAttribf(m_testCtx, *this, index, x, y, z, w);
809         }
810         for (int index = 0; index < attribute_count; ++index)
811         {
812             const GLfloat x = rnd.getFloat(-64000, 64000);
813             const GLfloat y = rnd.getFloat(-64000, 64000);
814             const GLfloat z = 0.0f;
815             const GLfloat w = 1.0f;
816 
817             glVertexAttrib2f(index, x, y);
818             verifyCurrentVertexAttribf(m_testCtx, *this, index, x, y, z, w);
819         }
820         for (int index = 0; index < attribute_count; ++index)
821         {
822             const GLfloat x = rnd.getFloat(-64000, 64000);
823             const GLfloat y = 0.0f;
824             const GLfloat z = 0.0f;
825             const GLfloat w = 1.0f;
826 
827             glVertexAttrib1f(index, x);
828             verifyCurrentVertexAttribf(m_testCtx, *this, index, x, y, z, w);
829         }
830     }
831 };
832 
833 class CurrentVertexAttribConversionCase : public ApiCase
834 {
835 public:
CurrentVertexAttribConversionCase(Context & context,const char * name,const char * description)836     CurrentVertexAttribConversionCase(Context &context, const char *name, const char *description)
837         : ApiCase(context, name, description)
838     {
839     }
840 
test(void)841     void test(void)
842     {
843         using tcu::TestLog;
844 
845         de::Random rnd(0xabcdef);
846 
847         int attribute_count = 16;
848         glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &attribute_count);
849 
850         // test write float/read float
851 
852         for (int index = 0; index < attribute_count; ++index)
853         {
854             const GLfloat x = rnd.getFloat(-64000, 64000);
855             const GLfloat y = rnd.getFloat(-64000, 64000);
856             const GLfloat z = rnd.getFloat(-64000, 64000);
857             const GLfloat w = rnd.getFloat(-64000, 64000);
858 
859             glVertexAttrib4f(index, x, y, z, w);
860             verifyCurrentVertexAttribConversion(m_testCtx, *this, index, x, y, z, w);
861         }
862         for (int index = 0; index < attribute_count; ++index)
863         {
864             const GLfloat x = rnd.getFloat(-64000, 64000);
865             const GLfloat y = rnd.getFloat(-64000, 64000);
866             const GLfloat z = rnd.getFloat(-64000, 64000);
867             const GLfloat w = 1.0f;
868 
869             glVertexAttrib3f(index, x, y, z);
870             verifyCurrentVertexAttribConversion(m_testCtx, *this, index, x, y, z, w);
871         }
872         for (int index = 0; index < attribute_count; ++index)
873         {
874             const GLfloat x = rnd.getFloat(-64000, 64000);
875             const GLfloat y = rnd.getFloat(-64000, 64000);
876             const GLfloat z = 0.0f;
877             const GLfloat w = 1.0f;
878 
879             glVertexAttrib2f(index, x, y);
880             verifyCurrentVertexAttribConversion(m_testCtx, *this, index, x, y, z, w);
881         }
882         for (int index = 0; index < attribute_count; ++index)
883         {
884             const GLfloat x = rnd.getFloat(-64000, 64000);
885             const GLfloat y = 0.0f;
886             const GLfloat z = 0.0f;
887             const GLfloat w = 1.0f;
888 
889             glVertexAttrib1f(index, x);
890             verifyCurrentVertexAttribConversion(m_testCtx, *this, index, x, y, z, w);
891         }
892     }
893 };
894 
895 class ProgramInfoLogCase : public ApiCase
896 {
897 public:
ProgramInfoLogCase(Context & context,const char * name,const char * description)898     ProgramInfoLogCase(Context &context, const char *name, const char *description)
899         : ApiCase(context, name, description)
900     {
901     }
902 
test(void)903     void test(void)
904     {
905         using tcu::TestLog;
906 
907         GLuint shaderVert = glCreateShader(GL_VERTEX_SHADER);
908         GLuint shaderFrag = glCreateShader(GL_FRAGMENT_SHADER);
909 
910         glShaderSource(shaderVert, 1, &brokenShader, DE_NULL);
911         glShaderSource(shaderFrag, 1, &brokenShader, DE_NULL);
912 
913         glCompileShader(shaderVert);
914         glCompileShader(shaderFrag);
915         expectError(GL_NO_ERROR);
916 
917         GLuint program = glCreateProgram();
918         glAttachShader(program, shaderVert);
919         glAttachShader(program, shaderFrag);
920         glLinkProgram(program);
921 
922         // check INFO_LOG_LENGTH == GetProgramInfoLog len
923         {
924             char buffer[2048] = {'x'};
925 
926             GLint written = 0;
927             glGetProgramInfoLog(program, DE_LENGTH_OF_ARRAY(buffer), &written, buffer);
928 
929             StateQueryMemoryWriteGuard<GLint> logLength;
930             glGetProgramiv(program, GL_INFO_LOG_LENGTH, &logLength);
931             logLength.verifyValidity(m_testCtx);
932 
933             if (logLength != 0 && written + 1 != logLength) // INFO_LOG_LENGTH contains 0-terminator
934             {
935                 m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected INFO_LOG_LENGTH " << written + 1
936                                    << "; got " << logLength << TestLog::EndMessage;
937                 if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
938                     m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid log length");
939             }
940         }
941 
942         // check GetProgramInfoLog works with too small buffer
943         {
944             char buffer[2048] = {'x'};
945 
946             GLint written = 0;
947             glGetProgramInfoLog(program, 1, &written, buffer);
948 
949             if (written != 0)
950             {
951                 m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected write length 0; got " << written
952                                    << TestLog::EndMessage;
953                 if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
954                     m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid log length");
955             }
956         }
957 
958         glDeleteShader(shaderVert);
959         glDeleteShader(shaderFrag);
960         glDeleteProgram(program);
961         expectError(GL_NO_ERROR);
962     }
963 };
964 
965 class ProgramValidateStatusCase : public ApiCase
966 {
967 public:
ProgramValidateStatusCase(Context & context,const char * name,const char * description)968     ProgramValidateStatusCase(Context &context, const char *name, const char *description)
969         : ApiCase(context, name, description)
970     {
971     }
972 
test(void)973     void test(void)
974     {
975         // test validate ok
976         {
977             GLuint shaderVert = glCreateShader(GL_VERTEX_SHADER);
978             GLuint shaderFrag = glCreateShader(GL_FRAGMENT_SHADER);
979 
980             glShaderSource(shaderVert, 1, &commonTestVertSource, DE_NULL);
981             glShaderSource(shaderFrag, 1, &commonTestFragSource, DE_NULL);
982 
983             glCompileShader(shaderVert);
984             glCompileShader(shaderFrag);
985             expectError(GL_NO_ERROR);
986 
987             GLuint program = glCreateProgram();
988             glAttachShader(program, shaderVert);
989             glAttachShader(program, shaderFrag);
990             glLinkProgram(program);
991             expectError(GL_NO_ERROR);
992 
993             verifyShaderParam(m_testCtx, *this, shaderVert, GL_COMPILE_STATUS, GL_TRUE);
994             verifyShaderParam(m_testCtx, *this, shaderFrag, GL_COMPILE_STATUS, GL_TRUE);
995             verifyProgramParam(m_testCtx, *this, program, GL_LINK_STATUS, GL_TRUE);
996 
997             glValidateProgram(program);
998             verifyProgramParam(m_testCtx, *this, program, GL_VALIDATE_STATUS, GL_TRUE);
999 
1000             glDeleteShader(shaderVert);
1001             glDeleteShader(shaderFrag);
1002             glDeleteProgram(program);
1003             expectError(GL_NO_ERROR);
1004         }
1005 
1006         // test with broken shader
1007         {
1008             GLuint shaderVert = glCreateShader(GL_VERTEX_SHADER);
1009             GLuint shaderFrag = glCreateShader(GL_FRAGMENT_SHADER);
1010 
1011             glShaderSource(shaderVert, 1, &commonTestVertSource, DE_NULL);
1012             glShaderSource(shaderFrag, 1, &brokenShader, DE_NULL);
1013 
1014             glCompileShader(shaderVert);
1015             glCompileShader(shaderFrag);
1016             expectError(GL_NO_ERROR);
1017 
1018             GLuint program = glCreateProgram();
1019             glAttachShader(program, shaderVert);
1020             glAttachShader(program, shaderFrag);
1021             glLinkProgram(program);
1022             expectError(GL_NO_ERROR);
1023 
1024             verifyShaderParam(m_testCtx, *this, shaderVert, GL_COMPILE_STATUS, GL_TRUE);
1025             verifyShaderParam(m_testCtx, *this, shaderFrag, GL_COMPILE_STATUS, GL_FALSE);
1026             verifyProgramParam(m_testCtx, *this, program, GL_LINK_STATUS, GL_FALSE);
1027 
1028             glValidateProgram(program);
1029             verifyProgramParam(m_testCtx, *this, program, GL_VALIDATE_STATUS, GL_FALSE);
1030 
1031             glDeleteShader(shaderVert);
1032             glDeleteShader(shaderFrag);
1033             glDeleteProgram(program);
1034             expectError(GL_NO_ERROR);
1035         }
1036     }
1037 };
1038 
1039 class ProgramAttachedShadersCase : public ApiCase
1040 {
1041 public:
ProgramAttachedShadersCase(Context & context,const char * name,const char * description)1042     ProgramAttachedShadersCase(Context &context, const char *name, const char *description)
1043         : ApiCase(context, name, description)
1044     {
1045     }
1046 
test(void)1047     void test(void)
1048     {
1049         using tcu::TestLog;
1050 
1051         GLuint shaderVert = glCreateShader(GL_VERTEX_SHADER);
1052         GLuint shaderFrag = glCreateShader(GL_FRAGMENT_SHADER);
1053 
1054         glShaderSource(shaderVert, 1, &commonTestVertSource, DE_NULL);
1055         glShaderSource(shaderFrag, 1, &commonTestFragSource, DE_NULL);
1056 
1057         glCompileShader(shaderVert);
1058         glCompileShader(shaderFrag);
1059         expectError(GL_NO_ERROR);
1060 
1061         // check ATTACHED_SHADERS
1062 
1063         GLuint program = glCreateProgram();
1064         verifyProgramParam(m_testCtx, *this, program, GL_ATTACHED_SHADERS, 0);
1065         expectError(GL_NO_ERROR);
1066 
1067         glAttachShader(program, shaderVert);
1068         verifyProgramParam(m_testCtx, *this, program, GL_ATTACHED_SHADERS, 1);
1069         expectError(GL_NO_ERROR);
1070 
1071         glAttachShader(program, shaderFrag);
1072         verifyProgramParam(m_testCtx, *this, program, GL_ATTACHED_SHADERS, 2);
1073         expectError(GL_NO_ERROR);
1074 
1075         // check GetAttachedShaders
1076         {
1077             GLuint shaders[2] = {0, 0};
1078             GLint count       = 0;
1079             glGetAttachedShaders(program, DE_LENGTH_OF_ARRAY(shaders), &count, shaders);
1080 
1081             if (count != 2)
1082             {
1083                 m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected 2; got " << count << TestLog::EndMessage;
1084                 if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
1085                     m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got wrong shader count");
1086             }
1087             // shaders are the attached shaders?
1088             if (!((shaders[0] == shaderVert && shaders[1] == shaderFrag) ||
1089                   (shaders[0] == shaderFrag && shaders[1] == shaderVert)))
1090             {
1091                 m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected {" << shaderVert << ", " << shaderFrag
1092                                    << "}; got {" << shaders[0] << ", " << shaders[1] << "}" << TestLog::EndMessage;
1093                 if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
1094                     m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got wrong shader count");
1095             }
1096         }
1097 
1098         // check GetAttachedShaders with too small buffer
1099         {
1100             GLuint shaders[2] = {0, 0};
1101             GLint count       = 0;
1102 
1103             glGetAttachedShaders(program, 0, &count, shaders);
1104             if (count != 0)
1105             {
1106                 m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected 0; got " << count << TestLog::EndMessage;
1107                 if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
1108                     m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got wrong shader count");
1109             }
1110 
1111             count = 0;
1112             glGetAttachedShaders(program, 1, &count, shaders);
1113             if (count != 1)
1114             {
1115                 m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected 1; got " << count << TestLog::EndMessage;
1116                 if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
1117                     m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got wrong shader count");
1118             }
1119         }
1120 
1121         glDeleteShader(shaderVert);
1122         glDeleteShader(shaderFrag);
1123         glDeleteProgram(program);
1124         expectError(GL_NO_ERROR);
1125     }
1126 };
1127 
1128 class ProgramActiveUniformNameCase : public ApiCase
1129 {
1130 public:
ProgramActiveUniformNameCase(Context & context,const char * name,const char * description)1131     ProgramActiveUniformNameCase(Context &context, const char *name, const char *description)
1132         : ApiCase(context, name, description)
1133     {
1134     }
1135 
test(void)1136     void test(void)
1137     {
1138         using tcu::TestLog;
1139 
1140         static const char *testVertSource = "uniform highp float uniformNameWithLength23;\n"
1141                                             "uniform highp vec2 uniformVec2;\n"
1142                                             "uniform highp mat4 uniformMat4;\n"
1143                                             "void main (void)\n"
1144                                             "{\n"
1145                                             "    gl_Position = vec4(0.0) + vec4(uniformNameWithLength23) + "
1146                                             "vec4(uniformVec2.x) + vec4(uniformMat4[2][3]);\n"
1147                                             "}\n\0";
1148         static const char *testFragSource =
1149 
1150             "void main (void)\n"
1151             "{\n"
1152             "    gl_FragColor = vec4(0.0);\n"
1153             "}\n\0";
1154 
1155         GLuint shaderVert = glCreateShader(GL_VERTEX_SHADER);
1156         GLuint shaderFrag = glCreateShader(GL_FRAGMENT_SHADER);
1157 
1158         glShaderSource(shaderVert, 1, &testVertSource, DE_NULL);
1159         glShaderSource(shaderFrag, 1, &testFragSource, DE_NULL);
1160 
1161         glCompileShader(shaderVert);
1162         glCompileShader(shaderFrag);
1163         expectError(GL_NO_ERROR);
1164 
1165         GLuint program = glCreateProgram();
1166         glAttachShader(program, shaderVert);
1167         glAttachShader(program, shaderFrag);
1168         glLinkProgram(program);
1169         expectError(GL_NO_ERROR);
1170 
1171         verifyProgramParam(m_testCtx, *this, program, GL_ACTIVE_UNIFORMS, 3);
1172         verifyProgramParam(m_testCtx, *this, program, GL_ACTIVE_UNIFORM_MAX_LENGTH,
1173                            (GLint)std::string("uniformNameWithLength23").length() + 1); // including a null terminator
1174         expectError(GL_NO_ERROR);
1175 
1176         const char *uniformNames[] = {"uniformNameWithLength23", "uniformVec2", "uniformMat4"};
1177 
1178         // check names
1179         for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(uniformNames); ++ndx)
1180         {
1181             char buffer[2048] = {'x'};
1182             char *bufferEnd   = (buffer + 1);
1183 
1184             GLint written = 0; // null terminator not included
1185             GLint size    = 0;
1186             GLenum type   = 0;
1187             glGetActiveUniform(program, ndx, DE_LENGTH_OF_ARRAY(buffer), &written, &size, &type, buffer);
1188 
1189             if (written < DE_LENGTH_OF_ARRAY(buffer))
1190                 bufferEnd = &buffer[written];
1191 
1192             // find matching uniform
1193             {
1194                 const std::string uniformName(buffer, bufferEnd);
1195                 bool found = false;
1196 
1197                 for (int uniformNdx = 0; uniformNdx < DE_LENGTH_OF_ARRAY(uniformNames); ++uniformNdx)
1198                 {
1199                     if (uniformName == uniformNames[uniformNdx])
1200                     {
1201                         found = true;
1202                         break;
1203                     }
1204                 }
1205 
1206                 if (!found)
1207                 {
1208                     m_testCtx.getLog() << TestLog::Message << "// ERROR: Got unknown uniform name: " << uniformName
1209                                        << TestLog::EndMessage;
1210                     if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
1211                         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got wrong uniform name");
1212                 }
1213             }
1214 
1215             // and with too small buffer
1216             written = 0;
1217             glGetActiveUniform(program, ndx, 1, &written, &size, &type, buffer);
1218 
1219             if (written != 0)
1220             {
1221                 m_testCtx.getLog() << TestLog::Message << "// ERROR: Expected 0 got " << written << TestLog::EndMessage;
1222                 if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
1223                     m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got wrong uniform name length");
1224             }
1225         }
1226 
1227         glDeleteShader(shaderVert);
1228         glDeleteShader(shaderFrag);
1229         glDeleteProgram(program);
1230         expectError(GL_NO_ERROR);
1231     }
1232 };
1233 
1234 class ProgramUniformCase : public ApiCase
1235 {
1236 public:
ProgramUniformCase(Context & context,const char * name,const char * description)1237     ProgramUniformCase(Context &context, const char *name, const char *description)
1238         : ApiCase(context, name, description)
1239     {
1240     }
1241 
test(void)1242     void test(void)
1243     {
1244         const struct UniformType
1245         {
1246             const char *declaration;
1247             const char *postDeclaration;
1248             const char *precision;
1249             const char *layout;
1250             const char *getter;
1251             GLenum type;
1252             GLint size;
1253             GLint isRowMajor;
1254         } uniformTypes[] = {
1255             {"float", "", "highp", "", "uniformValue", GL_FLOAT, 1, GL_FALSE},
1256             {"float", "[2]", "highp", "", "uniformValue[1]", GL_FLOAT, 2, GL_FALSE},
1257             {"vec2", "", "highp", "", "uniformValue.x", GL_FLOAT_VEC2, 1, GL_FALSE},
1258             {"vec3", "", "highp", "", "uniformValue.x", GL_FLOAT_VEC3, 1, GL_FALSE},
1259             {"vec4", "", "highp", "", "uniformValue.x", GL_FLOAT_VEC4, 1, GL_FALSE},
1260             {"int", "", "highp", "", "float(uniformValue)", GL_INT, 1, GL_FALSE},
1261             {"ivec2", "", "highp", "", "float(uniformValue.x)", GL_INT_VEC2, 1, GL_FALSE},
1262             {"ivec3", "", "highp", "", "float(uniformValue.x)", GL_INT_VEC3, 1, GL_FALSE},
1263             {"ivec4", "", "highp", "", "float(uniformValue.x)", GL_INT_VEC4, 1, GL_FALSE},
1264             {"bool", "", "", "", "float(uniformValue)", GL_BOOL, 1, GL_FALSE},
1265             {"bvec2", "", "", "", "float(uniformValue.x)", GL_BOOL_VEC2, 1, GL_FALSE},
1266             {"bvec3", "", "", "", "float(uniformValue.x)", GL_BOOL_VEC3, 1, GL_FALSE},
1267             {"bvec4", "", "", "", "float(uniformValue.x)", GL_BOOL_VEC4, 1, GL_FALSE},
1268             {"mat2", "", "highp", "", "float(uniformValue[0][0])", GL_FLOAT_MAT2, 1, GL_FALSE},
1269             {"mat3", "", "highp", "", "float(uniformValue[0][0])", GL_FLOAT_MAT3, 1, GL_FALSE},
1270             {"mat4", "", "highp", "", "float(uniformValue[0][0])", GL_FLOAT_MAT4, 1, GL_FALSE},
1271             {"sampler2D", "", "highp", "", "float(texture2D(uniformValue, vec2(0.0, 0.0)).r)", GL_SAMPLER_2D, 1,
1272              GL_FALSE},
1273             {"samplerCube", "", "highp", "", "float(textureCube(uniformValue, vec3(0.0, 0.0, 0.0)).r)", GL_SAMPLER_CUBE,
1274              1, GL_FALSE},
1275         };
1276 
1277         static const char *vertSource = "void main (void)\n"
1278                                         "{\n"
1279                                         "    gl_Position = vec4(0.0);\n"
1280                                         "}\n\0";
1281 
1282         GLuint shaderVert = glCreateShader(GL_VERTEX_SHADER);
1283         GLuint shaderFrag = glCreateShader(GL_FRAGMENT_SHADER);
1284         GLuint program    = glCreateProgram();
1285 
1286         glAttachShader(program, shaderVert);
1287         glAttachShader(program, shaderFrag);
1288 
1289         glShaderSource(shaderVert, 1, &vertSource, DE_NULL);
1290         glCompileShader(shaderVert);
1291         expectError(GL_NO_ERROR);
1292 
1293         for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(uniformTypes); ++ndx)
1294         {
1295             tcu::ScopedLogSection(m_log, uniformTypes[ndx].declaration,
1296                                   std::string("Verify type of ") + uniformTypes[ndx].declaration + " variable" +
1297                                       uniformTypes[ndx].postDeclaration);
1298 
1299             // gen fragment shader
1300 
1301             std::ostringstream frag;
1302             frag << uniformTypes[ndx].layout << "uniform " << uniformTypes[ndx].precision << " "
1303                  << uniformTypes[ndx].declaration << " uniformValue" << uniformTypes[ndx].postDeclaration << ";\n";
1304             frag << "void main (void)\n";
1305             frag << "{\n";
1306             frag << "    gl_FragColor = vec4(" << uniformTypes[ndx].getter << ");\n";
1307             frag << "}\n";
1308 
1309             {
1310                 std::string fragmentSource     = frag.str();
1311                 const char *fragmentSourceCStr = fragmentSource.c_str();
1312                 glShaderSource(shaderFrag, 1, &fragmentSourceCStr, DE_NULL);
1313             }
1314 
1315             // compile & link
1316 
1317             glCompileShader(shaderFrag);
1318             glLinkProgram(program);
1319 
1320             // test
1321             if (verifyProgramParam(m_testCtx, *this, program, GL_LINK_STATUS, GL_TRUE))
1322             {
1323                 const GLint index = 0; // first and only active uniform
1324 
1325                 char buffer[] = "not written to"; // not written to
1326                 GLint written = 0;
1327                 GLint size    = 0;
1328                 GLenum type   = 0;
1329                 glGetActiveUniform(program, index, 0, &written, &size, &type, buffer);
1330 
1331                 checkIntEquals(m_testCtx, type, uniformTypes[ndx].type);
1332                 checkIntEquals(m_testCtx, size, uniformTypes[ndx].size);
1333             }
1334         }
1335 
1336         glDeleteShader(shaderVert);
1337         glDeleteShader(shaderFrag);
1338         glDeleteProgram(program);
1339         expectError(GL_NO_ERROR);
1340     }
1341 };
1342 
1343 class ActiveAttributesCase : public ApiCase
1344 {
1345 public:
ActiveAttributesCase(Context & context,const char * name,const char * description)1346     ActiveAttributesCase(Context &context, const char *name, const char *description)
1347         : ApiCase(context, name, description)
1348     {
1349     }
1350 
test(void)1351     void test(void)
1352     {
1353         using tcu::TestLog;
1354 
1355         static const char *testVertSource = "attribute highp vec2 longInputAttributeName;\n"
1356                                             "attribute highp vec2 shortName;\n"
1357                                             "void main (void)\n"
1358                                             "{\n"
1359                                             "    gl_Position = longInputAttributeName.yxxy + shortName.xyxy;\n"
1360                                             "}\n\0";
1361         static const char *testFragSource = "void main (void)\n"
1362                                             "{\n"
1363                                             "    gl_FragColor = vec4(0.0);\n"
1364                                             "}\n\0";
1365 
1366         GLuint shaderVert = glCreateShader(GL_VERTEX_SHADER);
1367         GLuint shaderFrag = glCreateShader(GL_FRAGMENT_SHADER);
1368 
1369         glShaderSource(shaderVert, 1, &testVertSource, DE_NULL);
1370         glShaderSource(shaderFrag, 1, &testFragSource, DE_NULL);
1371 
1372         glCompileShader(shaderVert);
1373         glCompileShader(shaderFrag);
1374         expectError(GL_NO_ERROR);
1375 
1376         GLuint program = glCreateProgram();
1377         glAttachShader(program, shaderVert);
1378         glAttachShader(program, shaderFrag);
1379         glLinkProgram(program);
1380         expectError(GL_NO_ERROR);
1381 
1382         verifyProgramParam(m_testCtx, *this, program, GL_ACTIVE_ATTRIBUTES, 2);
1383         verifyProgramParam(m_testCtx, *this, program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH,
1384                            (GLint)std::string("longInputAttributeName").length() + 1); // does include null-terminator
1385 
1386         // check names
1387         for (int attributeNdx = 0; attributeNdx < 2; ++attributeNdx)
1388         {
1389             char buffer[2048] = {'x'};
1390 
1391             GLint written = 0;
1392             GLint size    = 0;
1393             GLenum type   = 0;
1394             glGetActiveAttrib(program, attributeNdx, DE_LENGTH_OF_ARRAY(buffer), &written, &size, &type, buffer);
1395             expectError(GL_NO_ERROR);
1396 
1397             if (deStringBeginsWith(buffer, "longInputAttributeName"))
1398             {
1399                 checkIntEquals(
1400                     m_testCtx, written,
1401                     (GLint)std::string("longInputAttributeName").length()); // does NOT include null-terminator
1402             }
1403             else if (deStringBeginsWith(buffer, "shortName"))
1404             {
1405                 checkIntEquals(m_testCtx, written,
1406                                (GLint)std::string("shortName").length()); // does NOT include null-terminator
1407             }
1408             else
1409             {
1410                 m_testCtx.getLog() << TestLog::Message << "// ERROR: Got unexpected attribute name."
1411                                    << TestLog::EndMessage;
1412                 if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
1413                     m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got unexpected name");
1414             }
1415         }
1416 
1417         // and with too short buffer
1418         {
1419             char buffer[2048] = {'x'};
1420 
1421             GLint written = 0;
1422             GLint size    = 0;
1423             GLenum type   = 0;
1424 
1425             glGetActiveAttrib(program, 0, 1, &written, &size, &type, buffer);
1426             expectError(GL_NO_ERROR);
1427             checkIntEquals(m_testCtx, written, 0);
1428         }
1429 
1430         glDeleteShader(shaderVert);
1431         glDeleteShader(shaderFrag);
1432         glDeleteProgram(program);
1433         expectError(GL_NO_ERROR);
1434     }
1435 };
1436 
1437 struct PointerData
1438 {
1439     GLint size;
1440     GLenum type;
1441     GLint stride;
1442     GLboolean normalized;
1443     void *pointer;
1444 };
1445 
1446 class VertexAttributeSizeCase : public ApiCase
1447 {
1448 public:
VertexAttributeSizeCase(Context & context,const char * name,const char * description)1449     VertexAttributeSizeCase(Context &context, const char *name, const char *description)
1450         : ApiCase(context, name, description)
1451     {
1452     }
1453 
test(void)1454     void test(void)
1455     {
1456         GLfloat vertexData[4] = {0.0f}; // never accessed
1457 
1458         // test VertexAttribPointer
1459         const PointerData pointers[] = {
1460             // size test
1461             {4, GL_FLOAT, 0, GL_FALSE, vertexData}, {3, GL_FLOAT, 0, GL_FALSE, vertexData},
1462             {2, GL_FLOAT, 0, GL_FALSE, vertexData}, {1, GL_FLOAT, 0, GL_FALSE, vertexData},
1463             {4, GL_SHORT, 0, GL_FALSE, vertexData}, {3, GL_SHORT, 0, GL_FALSE, vertexData},
1464             {2, GL_SHORT, 0, GL_FALSE, vertexData}, {1, GL_SHORT, 0, GL_FALSE, vertexData},
1465         };
1466 
1467         for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(pointers); ++ndx)
1468         {
1469             glVertexAttribPointer(0, pointers[ndx].size, pointers[ndx].type, pointers[ndx].normalized,
1470                                   pointers[ndx].stride, pointers[ndx].pointer);
1471             expectError(GL_NO_ERROR);
1472 
1473             verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_SIZE, pointers[ndx].size);
1474         }
1475     }
1476 };
1477 
1478 class VertexAttributeTypeCase : public ApiCase
1479 {
1480 public:
VertexAttributeTypeCase(Context & context,const char * name,const char * description)1481     VertexAttributeTypeCase(Context &context, const char *name, const char *description)
1482         : ApiCase(context, name, description)
1483     {
1484     }
1485 
test(void)1486     void test(void)
1487     {
1488         GLfloat vertexData[4] = {0.0f}; // never accessed
1489 
1490         const PointerData pointers[] = {
1491             {1, GL_BYTE, 0, GL_FALSE, vertexData},  {1, GL_UNSIGNED_BYTE, 0, GL_FALSE, vertexData},
1492             {1, GL_SHORT, 0, GL_FALSE, vertexData}, {1, GL_UNSIGNED_SHORT, 0, GL_FALSE, vertexData},
1493             {1, GL_FIXED, 0, GL_FALSE, vertexData}, {1, GL_FLOAT, 0, GL_FALSE, vertexData},
1494         };
1495 
1496         for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(pointers); ++ndx)
1497         {
1498             glVertexAttribPointer(0, pointers[ndx].size, pointers[ndx].type, pointers[ndx].normalized,
1499                                   pointers[ndx].stride, pointers[ndx].pointer);
1500             expectError(GL_NO_ERROR);
1501 
1502             verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_TYPE, pointers[ndx].type);
1503         }
1504     }
1505 };
1506 
1507 class VertexAttributeStrideCase : public ApiCase
1508 {
1509 public:
VertexAttributeStrideCase(Context & context,const char * name,const char * description)1510     VertexAttributeStrideCase(Context &context, const char *name, const char *description)
1511         : ApiCase(context, name, description)
1512     {
1513     }
1514 
test(void)1515     void test(void)
1516     {
1517         GLfloat vertexData[4] = {0.0f}; // never accessed
1518 
1519         struct StridePointerData
1520         {
1521             GLint size;
1522             GLenum type;
1523             GLint stride;
1524             void *pointer;
1525         };
1526 
1527         // test VertexAttribPointer
1528         {
1529             const StridePointerData pointers[] = {
1530                 {1, GL_FLOAT, 0, vertexData},          {1, GL_FLOAT, 1, vertexData},
1531                 {1, GL_FLOAT, 4, vertexData},          {1, GL_SHORT, 0, vertexData},
1532                 {1, GL_SHORT, 1, vertexData},          {1, GL_SHORT, 4, vertexData},
1533                 {1, GL_FIXED, 0, vertexData},          {1, GL_FIXED, 1, vertexData},
1534                 {1, GL_FIXED, 4, vertexData},          {1, GL_BYTE, 0, vertexData},
1535                 {1, GL_UNSIGNED_SHORT, 1, vertexData}, {1, GL_UNSIGNED_SHORT, 4, vertexData},
1536                 {4, GL_UNSIGNED_BYTE, 0, vertexData},  {4, GL_UNSIGNED_BYTE, 1, vertexData},
1537                 {4, GL_UNSIGNED_BYTE, 4, vertexData},
1538             };
1539 
1540             for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(pointers); ++ndx)
1541             {
1542                 glVertexAttribPointer(0, pointers[ndx].size, pointers[ndx].type, GL_FALSE, pointers[ndx].stride,
1543                                       pointers[ndx].pointer);
1544                 expectError(GL_NO_ERROR);
1545 
1546                 verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_STRIDE, pointers[ndx].stride);
1547             }
1548         }
1549     }
1550 };
1551 
1552 class VertexAttributeNormalizedCase : public ApiCase
1553 {
1554 public:
VertexAttributeNormalizedCase(Context & context,const char * name,const char * description)1555     VertexAttributeNormalizedCase(Context &context, const char *name, const char *description)
1556         : ApiCase(context, name, description)
1557     {
1558     }
1559 
test(void)1560     void test(void)
1561     {
1562         GLfloat vertexData[4] = {0.0f}; // never accessed
1563 
1564         // test VertexAttribPointer
1565         {
1566             const PointerData pointers[] = {
1567                 {1, GL_BYTE, 0, GL_FALSE, vertexData},          {1, GL_SHORT, 0, GL_FALSE, vertexData},
1568                 {1, GL_UNSIGNED_BYTE, 0, GL_FALSE, vertexData}, {1, GL_UNSIGNED_SHORT, 0, GL_FALSE, vertexData},
1569                 {1, GL_BYTE, 0, GL_TRUE, vertexData},           {1, GL_SHORT, 0, GL_TRUE, vertexData},
1570                 {1, GL_UNSIGNED_BYTE, 0, GL_TRUE, vertexData},  {1, GL_UNSIGNED_SHORT, 0, GL_TRUE, vertexData},
1571             };
1572 
1573             for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(pointers); ++ndx)
1574             {
1575                 glVertexAttribPointer(0, pointers[ndx].size, pointers[ndx].type, pointers[ndx].normalized,
1576                                       pointers[ndx].stride, pointers[ndx].pointer);
1577                 expectError(GL_NO_ERROR);
1578 
1579                 verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, pointers[ndx].normalized);
1580             }
1581         }
1582     }
1583 };
1584 
1585 class VertexAttributeEnabledCase : public ApiCase
1586 {
1587 public:
VertexAttributeEnabledCase(Context & context,const char * name,const char * description)1588     VertexAttributeEnabledCase(Context &context, const char *name, const char *description)
1589         : ApiCase(context, name, description)
1590     {
1591     }
1592 
test(void)1593     void test(void)
1594     {
1595         // VERTEX_ATTRIB_ARRAY_ENABLED
1596 
1597         verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_ENABLED, GL_FALSE);
1598         glEnableVertexAttribArray(0);
1599         verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_ENABLED, GL_TRUE);
1600         glDisableVertexAttribArray(0);
1601         verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_ENABLED, GL_FALSE);
1602     }
1603 };
1604 
1605 class VertexAttributeBufferBindingCase : public ApiCase
1606 {
1607 public:
VertexAttributeBufferBindingCase(Context & context,const char * name,const char * description)1608     VertexAttributeBufferBindingCase(Context &context, const char *name, const char *description)
1609         : ApiCase(context, name, description)
1610     {
1611     }
1612 
test(void)1613     void test(void)
1614     {
1615         // initial
1616         verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, 0);
1617 
1618         GLuint bufferID;
1619         glGenBuffers(1, &bufferID);
1620         glBindBuffer(GL_ARRAY_BUFFER, bufferID);
1621         expectError(GL_NO_ERROR);
1622 
1623         glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, DE_NULL);
1624         expectError(GL_NO_ERROR);
1625 
1626         verifyVertexAttrib(m_testCtx, *this, 0, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, bufferID);
1627 
1628         glDeleteBuffers(1, &bufferID);
1629         expectError(GL_NO_ERROR);
1630     }
1631 };
1632 
1633 class VertexAttributePointerCase : public ApiCase
1634 {
1635 public:
VertexAttributePointerCase(Context & context,const char * name,const char * description)1636     VertexAttributePointerCase(Context &context, const char *name, const char *description)
1637         : ApiCase(context, name, description)
1638     {
1639     }
1640 
test(void)1641     void test(void)
1642     {
1643         StateQueryMemoryWriteGuard<GLvoid *> initialState;
1644         glGetVertexAttribPointerv(0, GL_VERTEX_ATTRIB_ARRAY_POINTER, &initialState);
1645         initialState.verifyValidity(m_testCtx);
1646         checkPointerEquals(m_testCtx, initialState, 0);
1647 
1648         GLfloat vertexData[4]        = {0.0f}; // never accessed
1649         const PointerData pointers[] = {
1650             {1, GL_BYTE, 0, GL_FALSE, &vertexData[2]},           {1, GL_SHORT, 0, GL_FALSE, &vertexData[1]},
1651             {1, GL_FIXED, 0, GL_FALSE, &vertexData[2]},          {1, GL_FIXED, 0, GL_FALSE, &vertexData[1]},
1652             {1, GL_FLOAT, 0, GL_FALSE, &vertexData[0]},          {1, GL_FLOAT, 0, GL_FALSE, &vertexData[3]},
1653             {1, GL_FLOAT, 0, GL_FALSE, &vertexData[2]},          {1, GL_UNSIGNED_SHORT, 0, GL_FALSE, &vertexData[0]},
1654             {4, GL_UNSIGNED_SHORT, 0, GL_FALSE, &vertexData[1]}, {4, GL_UNSIGNED_SHORT, 0, GL_FALSE, &vertexData[2]},
1655         };
1656 
1657         for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(pointers); ++ndx)
1658         {
1659             glVertexAttribPointer(0, pointers[ndx].size, pointers[ndx].type, pointers[ndx].normalized,
1660                                   pointers[ndx].stride, pointers[ndx].pointer);
1661             expectError(GL_NO_ERROR);
1662 
1663             StateQueryMemoryWriteGuard<GLvoid *> state;
1664             glGetVertexAttribPointerv(0, GL_VERTEX_ATTRIB_ARRAY_POINTER, &state);
1665             state.verifyValidity(m_testCtx);
1666             checkPointerEquals(m_testCtx, state, pointers[ndx].pointer);
1667         }
1668     }
1669 };
1670 
1671 class UniformValueFloatCase : public ApiCase
1672 {
1673 public:
UniformValueFloatCase(Context & context,const char * name,const char * description)1674     UniformValueFloatCase(Context &context, const char *name, const char *description)
1675         : ApiCase(context, name, description)
1676     {
1677     }
1678 
test(void)1679     void test(void)
1680     {
1681         static const char *testVertSource =
1682             "uniform highp float floatUniform;\n"
1683             "uniform highp vec2 float2Uniform;\n"
1684             "uniform highp vec3 float3Uniform;\n"
1685             "uniform highp vec4 float4Uniform;\n"
1686             "void main (void)\n"
1687             "{\n"
1688             "    gl_Position = vec4(floatUniform + float2Uniform.x + float3Uniform.x + float4Uniform.x);\n"
1689             "}\n";
1690         static const char *testFragSource =
1691 
1692             "void main (void)\n"
1693             "{\n"
1694             "    gl_FragColor = vec4(0.0);\n"
1695             "}\n";
1696 
1697         glu::ShaderProgram program(m_context.getRenderContext(),
1698                                    glu::makeVtxFragSources(testVertSource, testFragSource));
1699         if (!program.isOk())
1700         {
1701             m_log << program;
1702             m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Failed to compile shader");
1703             return;
1704         }
1705 
1706         glUseProgram(program.getProgram());
1707         expectError(GL_NO_ERROR);
1708 
1709         GLint location;
1710 
1711         location = glGetUniformLocation(program.getProgram(), "floatUniform");
1712         glUniform1f(location, 1.0f);
1713         verifyUniformValue1f(m_testCtx, *this, program.getProgram(), location, 1.0f);
1714 
1715         location = glGetUniformLocation(program.getProgram(), "float2Uniform");
1716         glUniform2f(location, 1.0f, 2.0f);
1717         verifyUniformValue2f(m_testCtx, *this, program.getProgram(), location, 1.0f, 2.0f);
1718 
1719         location = glGetUniformLocation(program.getProgram(), "float3Uniform");
1720         glUniform3f(location, 1.0f, 2.0f, 3.0f);
1721         verifyUniformValue3f(m_testCtx, *this, program.getProgram(), location, 1.0f, 2.0f, 3.0f);
1722 
1723         location = glGetUniformLocation(program.getProgram(), "float4Uniform");
1724         glUniform4f(location, 1.0f, 2.0f, 3.0f, 4.0f);
1725         verifyUniformValue4f(m_testCtx, *this, program.getProgram(), location, 1.0f, 2.0f, 3.0f, 4.0f);
1726 
1727         glUseProgram(0);
1728         expectError(GL_NO_ERROR);
1729     }
1730 };
1731 
1732 class UniformValueIntCase : public ApiCase
1733 {
1734 public:
UniformValueIntCase(Context & context,const char * name,const char * description)1735     UniformValueIntCase(Context &context, const char *name, const char *description)
1736         : ApiCase(context, name, description)
1737     {
1738     }
1739 
test(void)1740     void test(void)
1741     {
1742         static const char *testVertSource =
1743             "uniform highp int intUniform;\n"
1744             "uniform highp ivec2 int2Uniform;\n"
1745             "uniform highp ivec3 int3Uniform;\n"
1746             "uniform highp ivec4 int4Uniform;\n"
1747             "void main (void)\n"
1748             "{\n"
1749             "    gl_Position = vec4(float(intUniform + int2Uniform.x + int3Uniform.x + int4Uniform.x));\n"
1750             "}\n";
1751         static const char *testFragSource = "void main (void)\n"
1752                                             "{\n"
1753                                             "    gl_FragColor = vec4(0.0);\n"
1754                                             "}\n";
1755 
1756         glu::ShaderProgram program(m_context.getRenderContext(),
1757                                    glu::makeVtxFragSources(testVertSource, testFragSource));
1758         if (!program.isOk())
1759         {
1760             m_log << program;
1761             m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Failed to compile shader");
1762             return;
1763         }
1764 
1765         glUseProgram(program.getProgram());
1766         expectError(GL_NO_ERROR);
1767 
1768         GLint location;
1769 
1770         location = glGetUniformLocation(program.getProgram(), "intUniform");
1771         glUniform1i(location, 1);
1772         verifyUniformValue1i(m_testCtx, *this, program.getProgram(), location, 1);
1773 
1774         location = glGetUniformLocation(program.getProgram(), "int2Uniform");
1775         glUniform2i(location, 1, 2);
1776         verifyUniformValue2i(m_testCtx, *this, program.getProgram(), location, 1, 2);
1777 
1778         location = glGetUniformLocation(program.getProgram(), "int3Uniform");
1779         glUniform3i(location, 1, 2, 3);
1780         verifyUniformValue3i(m_testCtx, *this, program.getProgram(), location, 1, 2, 3);
1781 
1782         location = glGetUniformLocation(program.getProgram(), "int4Uniform");
1783         glUniform4i(location, 1, 2, 3, 4);
1784         verifyUniformValue4i(m_testCtx, *this, program.getProgram(), location, 1, 2, 3, 4);
1785 
1786         glUseProgram(0);
1787         expectError(GL_NO_ERROR);
1788     }
1789 };
1790 
1791 class UniformValueBooleanCase : public ApiCase
1792 {
1793 public:
UniformValueBooleanCase(Context & context,const char * name,const char * description)1794     UniformValueBooleanCase(Context &context, const char *name, const char *description)
1795         : ApiCase(context, name, description)
1796     {
1797     }
1798 
test(void)1799     void test(void)
1800     {
1801         static const char *testVertSource = "uniform bool boolUniform;\n"
1802                                             "uniform bvec2 bool2Uniform;\n"
1803                                             "uniform bvec3 bool3Uniform;\n"
1804                                             "uniform bvec4 bool4Uniform;\n"
1805                                             "void main (void)\n"
1806                                             "{\n"
1807                                             "    gl_Position = vec4(float(boolUniform) + float(bool2Uniform.x) + "
1808                                             "float(bool3Uniform.x) + float(bool4Uniform.x));\n"
1809                                             "}\n";
1810         static const char *testFragSource = "void main (void)\n"
1811                                             "{\n"
1812                                             "    gl_FragColor = vec4(0.0);\n"
1813                                             "}\n";
1814 
1815         glu::ShaderProgram program(m_context.getRenderContext(),
1816                                    glu::makeVtxFragSources(testVertSource, testFragSource));
1817         if (!program.isOk())
1818         {
1819             m_log << program;
1820             m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Failed to compile shader");
1821             return;
1822         }
1823 
1824         glUseProgram(program.getProgram());
1825         expectError(GL_NO_ERROR);
1826 
1827         GLint location;
1828 
1829         // int conversion
1830 
1831         location = glGetUniformLocation(program.getProgram(), "boolUniform");
1832         glUniform1i(location, 1);
1833         verifyUniformValue1i(m_testCtx, *this, program.getProgram(), location, 1);
1834 
1835         location = glGetUniformLocation(program.getProgram(), "bool2Uniform");
1836         glUniform2i(location, 1, 2);
1837         verifyUniformValue2i(m_testCtx, *this, program.getProgram(), location, 1, 1);
1838 
1839         location = glGetUniformLocation(program.getProgram(), "bool3Uniform");
1840         glUniform3i(location, 0, 1, 2);
1841         verifyUniformValue3i(m_testCtx, *this, program.getProgram(), location, 0, 1, 1);
1842 
1843         location = glGetUniformLocation(program.getProgram(), "bool4Uniform");
1844         glUniform4i(location, 1, 0, 1, -1);
1845         verifyUniformValue4i(m_testCtx, *this, program.getProgram(), location, 1, 0, 1, 1);
1846 
1847         // float conversion
1848 
1849         location = glGetUniformLocation(program.getProgram(), "boolUniform");
1850         glUniform1f(location, 1.0f);
1851         verifyUniformValue1i(m_testCtx, *this, program.getProgram(), location, 1);
1852 
1853         location = glGetUniformLocation(program.getProgram(), "bool2Uniform");
1854         glUniform2f(location, 1.0f, 0.1f);
1855         verifyUniformValue2i(m_testCtx, *this, program.getProgram(), location, 1, 1);
1856 
1857         location = glGetUniformLocation(program.getProgram(), "bool3Uniform");
1858         glUniform3f(location, 0.0f, 0.1f, -0.1f);
1859         verifyUniformValue3i(m_testCtx, *this, program.getProgram(), location, 0, 1, 1);
1860 
1861         location = glGetUniformLocation(program.getProgram(), "bool4Uniform");
1862         glUniform4f(location, 1.0f, 0.0f, 0.1f, -0.9f);
1863         verifyUniformValue4i(m_testCtx, *this, program.getProgram(), location, 1, 0, 1, 1);
1864 
1865         glUseProgram(0);
1866         expectError(GL_NO_ERROR);
1867     }
1868 };
1869 
1870 class UniformValueSamplerCase : public ApiCase
1871 {
1872 public:
UniformValueSamplerCase(Context & context,const char * name,const char * description)1873     UniformValueSamplerCase(Context &context, const char *name, const char *description)
1874         : ApiCase(context, name, description)
1875     {
1876     }
1877 
test(void)1878     void test(void)
1879     {
1880         static const char *testVertSource = "void main (void)\n"
1881                                             "{\n"
1882                                             "    gl_Position = vec4(0.0);\n"
1883                                             "}\n";
1884         static const char *testFragSource = "uniform highp sampler2D uniformSampler;\n"
1885 
1886                                             "void main (void)\n"
1887                                             "{\n"
1888                                             "    gl_FragColor = vec4(texture2D(uniformSampler, vec2(0.0, 0.0)).x);\n"
1889                                             "}\n";
1890 
1891         glu::ShaderProgram program(m_context.getRenderContext(),
1892                                    glu::makeVtxFragSources(testVertSource, testFragSource));
1893         if (!program.isOk())
1894         {
1895             m_log << program;
1896             m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Failed to compile shader");
1897             return;
1898         }
1899 
1900         glUseProgram(program.getProgram());
1901         expectError(GL_NO_ERROR);
1902 
1903         GLint location;
1904 
1905         location = glGetUniformLocation(program.getProgram(), "uniformSampler");
1906         glUniform1i(location, 1);
1907         verifyUniformValue1i(m_testCtx, *this, program.getProgram(), location, 1);
1908 
1909         glUseProgram(0);
1910         expectError(GL_NO_ERROR);
1911     }
1912 };
1913 
1914 class UniformValueArrayCase : public ApiCase
1915 {
1916 public:
UniformValueArrayCase(Context & context,const char * name,const char * description)1917     UniformValueArrayCase(Context &context, const char *name, const char *description)
1918         : ApiCase(context, name, description)
1919     {
1920     }
1921 
test(void)1922     void test(void)
1923     {
1924         static const char *testVertSource = "uniform highp float arrayUniform[5];"
1925                                             "uniform highp vec2 array2Uniform[5];"
1926                                             "uniform highp vec3 array3Uniform[5];"
1927                                             "uniform highp vec4 array4Uniform[5];"
1928                                             "void main (void)\n"
1929                                             "{\n"
1930                                             "    gl_Position = \n"
1931                                             "        + vec4(arrayUniform[0]        + arrayUniform[1]        + "
1932                                             "arrayUniform[2]        + arrayUniform[3]        + arrayUniform[4])\n"
1933                                             "        + vec4(array2Uniform[0].x    + array2Uniform[1].x    + "
1934                                             "array2Uniform[2].x    + array2Uniform[3].x    + array2Uniform[4].x)\n"
1935                                             "        + vec4(array3Uniform[0].x    + array3Uniform[1].x    + "
1936                                             "array3Uniform[2].x    + array3Uniform[3].x    + array3Uniform[4].x)\n"
1937                                             "        + vec4(array4Uniform[0].x    + array4Uniform[1].x    + "
1938                                             "array4Uniform[2].x    + array4Uniform[3].x    + array4Uniform[4].x);\n"
1939                                             "}\n";
1940         static const char *testFragSource =
1941 
1942             "void main (void)\n"
1943             "{\n"
1944             "    gl_FragColor = vec4(0.0);\n"
1945             "}\n";
1946 
1947         glu::ShaderProgram program(m_context.getRenderContext(),
1948                                    glu::makeVtxFragSources(testVertSource, testFragSource));
1949         if (!program.isOk())
1950         {
1951             m_log << program;
1952             m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Failed to compile shader");
1953             return;
1954         }
1955 
1956         glUseProgram(program.getProgram());
1957         expectError(GL_NO_ERROR);
1958 
1959         GLint location;
1960 
1961         float uniformValue[5 * 4] = {-1.0f, 0.1f,  4.0f,  800.0f, 13.0f, 55.0f, 12.0f, 91.0f, -55.1f, 1.1f,
1962                                      98.0f, 19.0f, 41.0f, 65.0f,  4.0f,  12.2f, 95.0f, 77.0f, 32.0f,  48.0f};
1963 
1964         location = glGetUniformLocation(program.getProgram(), "arrayUniform");
1965         glUniform1fv(location, 5, uniformValue);
1966         expectError(GL_NO_ERROR);
1967 
1968         verifyUniformValue1f(m_testCtx, *this, program.getProgram(),
1969                              glGetUniformLocation(program.getProgram(), "arrayUniform[0]"), uniformValue[0]);
1970         verifyUniformValue1f(m_testCtx, *this, program.getProgram(),
1971                              glGetUniformLocation(program.getProgram(), "arrayUniform[1]"), uniformValue[1]);
1972         verifyUniformValue1f(m_testCtx, *this, program.getProgram(),
1973                              glGetUniformLocation(program.getProgram(), "arrayUniform[2]"), uniformValue[2]);
1974         verifyUniformValue1f(m_testCtx, *this, program.getProgram(),
1975                              glGetUniformLocation(program.getProgram(), "arrayUniform[3]"), uniformValue[3]);
1976         verifyUniformValue1f(m_testCtx, *this, program.getProgram(),
1977                              glGetUniformLocation(program.getProgram(), "arrayUniform[4]"), uniformValue[4]);
1978         expectError(GL_NO_ERROR);
1979 
1980         location = glGetUniformLocation(program.getProgram(), "array2Uniform");
1981         glUniform2fv(location, 5, uniformValue);
1982         expectError(GL_NO_ERROR);
1983 
1984         verifyUniformValue2f(m_testCtx, *this, program.getProgram(),
1985                              glGetUniformLocation(program.getProgram(), "array2Uniform[0]"), uniformValue[2 * 0],
1986                              uniformValue[(2 * 0) + 1]);
1987         verifyUniformValue2f(m_testCtx, *this, program.getProgram(),
1988                              glGetUniformLocation(program.getProgram(), "array2Uniform[1]"), uniformValue[2 * 1],
1989                              uniformValue[(2 * 1) + 1]);
1990         verifyUniformValue2f(m_testCtx, *this, program.getProgram(),
1991                              glGetUniformLocation(program.getProgram(), "array2Uniform[2]"), uniformValue[2 * 2],
1992                              uniformValue[(2 * 2) + 1]);
1993         verifyUniformValue2f(m_testCtx, *this, program.getProgram(),
1994                              glGetUniformLocation(program.getProgram(), "array2Uniform[3]"), uniformValue[2 * 3],
1995                              uniformValue[(2 * 3) + 1]);
1996         verifyUniformValue2f(m_testCtx, *this, program.getProgram(),
1997                              glGetUniformLocation(program.getProgram(), "array2Uniform[4]"), uniformValue[2 * 4],
1998                              uniformValue[(2 * 4) + 1]);
1999         expectError(GL_NO_ERROR);
2000 
2001         location = glGetUniformLocation(program.getProgram(), "array3Uniform");
2002         glUniform3fv(location, 5, uniformValue);
2003         expectError(GL_NO_ERROR);
2004 
2005         verifyUniformValue3f(m_testCtx, *this, program.getProgram(),
2006                              glGetUniformLocation(program.getProgram(), "array3Uniform[0]"), uniformValue[3 * 0],
2007                              uniformValue[(3 * 0) + 1], uniformValue[(3 * 0) + 2]);
2008         verifyUniformValue3f(m_testCtx, *this, program.getProgram(),
2009                              glGetUniformLocation(program.getProgram(), "array3Uniform[1]"), uniformValue[3 * 1],
2010                              uniformValue[(3 * 1) + 1], uniformValue[(3 * 1) + 2]);
2011         verifyUniformValue3f(m_testCtx, *this, program.getProgram(),
2012                              glGetUniformLocation(program.getProgram(), "array3Uniform[2]"), uniformValue[3 * 2],
2013                              uniformValue[(3 * 2) + 1], uniformValue[(3 * 2) + 2]);
2014         verifyUniformValue3f(m_testCtx, *this, program.getProgram(),
2015                              glGetUniformLocation(program.getProgram(), "array3Uniform[3]"), uniformValue[3 * 3],
2016                              uniformValue[(3 * 3) + 1], uniformValue[(3 * 3) + 2]);
2017         verifyUniformValue3f(m_testCtx, *this, program.getProgram(),
2018                              glGetUniformLocation(program.getProgram(), "array3Uniform[4]"), uniformValue[3 * 4],
2019                              uniformValue[(3 * 4) + 1], uniformValue[(3 * 4) + 2]);
2020         expectError(GL_NO_ERROR);
2021 
2022         location = glGetUniformLocation(program.getProgram(), "array4Uniform");
2023         glUniform4fv(location, 5, uniformValue);
2024         expectError(GL_NO_ERROR);
2025 
2026         verifyUniformValue4f(m_testCtx, *this, program.getProgram(),
2027                              glGetUniformLocation(program.getProgram(), "array4Uniform[0]"), uniformValue[4 * 0],
2028                              uniformValue[(4 * 0) + 1], uniformValue[(4 * 0) + 2], uniformValue[(4 * 0) + 3]);
2029         verifyUniformValue4f(m_testCtx, *this, program.getProgram(),
2030                              glGetUniformLocation(program.getProgram(), "array4Uniform[1]"), uniformValue[4 * 1],
2031                              uniformValue[(4 * 1) + 1], uniformValue[(4 * 1) + 2], uniformValue[(4 * 1) + 3]);
2032         verifyUniformValue4f(m_testCtx, *this, program.getProgram(),
2033                              glGetUniformLocation(program.getProgram(), "array4Uniform[2]"), uniformValue[4 * 2],
2034                              uniformValue[(4 * 2) + 1], uniformValue[(4 * 2) + 2], uniformValue[(4 * 2) + 3]);
2035         verifyUniformValue4f(m_testCtx, *this, program.getProgram(),
2036                              glGetUniformLocation(program.getProgram(), "array4Uniform[3]"), uniformValue[4 * 3],
2037                              uniformValue[(4 * 3) + 1], uniformValue[(4 * 3) + 2], uniformValue[(4 * 3) + 3]);
2038         verifyUniformValue4f(m_testCtx, *this, program.getProgram(),
2039                              glGetUniformLocation(program.getProgram(), "array4Uniform[4]"), uniformValue[4 * 4],
2040                              uniformValue[(4 * 4) + 1], uniformValue[(4 * 4) + 2], uniformValue[(4 * 4) + 3]);
2041         expectError(GL_NO_ERROR);
2042 
2043         glUseProgram(0);
2044         expectError(GL_NO_ERROR);
2045     }
2046 };
2047 
2048 class UniformValueMatrixCase : public ApiCase
2049 {
2050 public:
UniformValueMatrixCase(Context & context,const char * name,const char * description)2051     UniformValueMatrixCase(Context &context, const char *name, const char *description)
2052         : ApiCase(context, name, description)
2053     {
2054     }
2055 
test(void)2056     void test(void)
2057     {
2058         static const char *testVertSource =
2059             "uniform highp mat2 mat2Uniform;"
2060             "uniform highp mat3 mat3Uniform;"
2061             "uniform highp mat4 mat4Uniform;"
2062             "void main (void)\n"
2063             "{\n"
2064             "    gl_Position = vec4(mat2Uniform[0][0] + mat3Uniform[0][0] + mat4Uniform[0][0]);\n"
2065             "}\n";
2066         static const char *testFragSource =
2067 
2068             "void main (void)\n"
2069             "{\n"
2070             "    gl_FragColor = vec4(0.0);\n"
2071             "}\n";
2072 
2073         glu::ShaderProgram program(m_context.getRenderContext(),
2074                                    glu::makeVtxFragSources(testVertSource, testFragSource));
2075         if (!program.isOk())
2076         {
2077             m_log << program;
2078             m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Failed to compile shader");
2079             return;
2080         }
2081 
2082         glUseProgram(program.getProgram());
2083         expectError(GL_NO_ERROR);
2084 
2085         GLint location;
2086 
2087         float matrixValues[4 * 4] = {
2088             -1.0f,  0.1f, 4.0f,  800.0f, 13.0f, 55.0f, 12.0f, 91.0f,
2089             -55.1f, 1.1f, 98.0f, 19.0f,  41.0f, 65.0f, 4.0f,  12.2f,
2090         };
2091 
2092         // the values of the matrix are returned in column major order but they can be given in either order
2093 
2094         location = glGetUniformLocation(program.getProgram(), "mat2Uniform");
2095         glUniformMatrix2fv(location, 1, GL_FALSE, matrixValues);
2096         verifyUniformMatrixValues<2>(m_testCtx, *this, program.getProgram(), location, matrixValues, false);
2097 
2098         location = glGetUniformLocation(program.getProgram(), "mat3Uniform");
2099         glUniformMatrix3fv(location, 1, GL_FALSE, matrixValues);
2100         verifyUniformMatrixValues<3>(m_testCtx, *this, program.getProgram(), location, matrixValues, false);
2101 
2102         location = glGetUniformLocation(program.getProgram(), "mat4Uniform");
2103         glUniformMatrix4fv(location, 1, GL_FALSE, matrixValues);
2104         verifyUniformMatrixValues<4>(m_testCtx, *this, program.getProgram(), location, matrixValues, false);
2105 
2106         glUseProgram(0);
2107         expectError(GL_NO_ERROR);
2108     }
2109 };
2110 
2111 class PrecisionFormatCase : public ApiCase
2112 {
2113 public:
2114     struct RequiredFormat
2115     {
2116         int negativeRange;
2117         int positiveRange;
2118         int precision;
2119     };
2120 
PrecisionFormatCase(Context & context,const char * name,const char * description,glw::GLenum shaderType,glw::GLenum precisionType)2121     PrecisionFormatCase(Context &context, const char *name, const char *description, glw::GLenum shaderType,
2122                         glw::GLenum precisionType)
2123         : ApiCase(context, name, description)
2124         , m_shaderType(shaderType)
2125         , m_precisionType(precisionType)
2126     {
2127     }
2128 
2129 private:
test(void)2130     void test(void)
2131     {
2132         const RequiredFormat expected = getRequiredFormat();
2133         bool error                    = false;
2134         gls::StateQueryUtil::StateQueryMemoryWriteGuard<glw::GLboolean> shaderCompiler;
2135         gls::StateQueryUtil::StateQueryMemoryWriteGuard<glw::GLint[2]> range;
2136         gls::StateQueryUtil::StateQueryMemoryWriteGuard<glw::GLint> precision;
2137 
2138         // requires SHADER_COMPILER = true
2139         glGetBooleanv(GL_SHADER_COMPILER, &shaderCompiler);
2140         expectError(GL_NO_ERROR);
2141 
2142         if (!shaderCompiler.verifyValidity(m_testCtx))
2143             return;
2144         if (shaderCompiler != GL_TRUE)
2145             throw tcu::NotSupportedError("SHADER_COMPILER = TRUE required");
2146 
2147         // query values
2148         glGetShaderPrecisionFormat(m_shaderType, m_precisionType, range, &precision);
2149         expectError(GL_NO_ERROR);
2150 
2151         if (!range.verifyValidity(m_testCtx))
2152             return;
2153         if (!precision.verifyValidity(m_testCtx))
2154             return;
2155 
2156         m_log << tcu::TestLog::Message << "range[0] = " << range[0] << "\n"
2157               << "range[1] = " << range[1] << "\n"
2158               << "precision = " << precision << tcu::TestLog::EndMessage;
2159 
2160         // special case for highp and fragment shader
2161 
2162         if (m_shaderType == GL_FRAGMENT_SHADER && (m_precisionType == GL_HIGH_FLOAT || m_precisionType == GL_HIGH_INT))
2163         {
2164             // not supported is a valid return value
2165             if (range[0] == 0 && range[1] == 0 && precision == 0)
2166                 return;
2167         }
2168 
2169         // verify the returned values
2170 
2171         if (range[0] < expected.negativeRange)
2172         {
2173             m_log << tcu::TestLog::Message << "// ERROR: Invalid range[0], expected greater or equal to "
2174                   << expected.negativeRange << tcu::TestLog::EndMessage;
2175             error = true;
2176         }
2177 
2178         if (range[1] < expected.positiveRange)
2179         {
2180             m_log << tcu::TestLog::Message << "// ERROR: Invalid range[1], expected greater or equal to "
2181                   << expected.positiveRange << tcu::TestLog::EndMessage;
2182             error = true;
2183         }
2184 
2185         if (precision < expected.precision)
2186         {
2187             m_log << tcu::TestLog::Message << "// ERROR: Invalid precision, expected greater or equal to "
2188                   << expected.precision << tcu::TestLog::EndMessage;
2189             error = true;
2190         }
2191 
2192         if (error)
2193             m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid precision/range");
2194     }
2195 
getRequiredFormat(void) const2196     RequiredFormat getRequiredFormat(void) const
2197     {
2198         // Precisions for different types.
2199         // For example highp float: range: (-2^62, 2^62) => min = -2^62 + e, max = 2^62 - e
2200         const RequiredFormat requirements[] = {
2201             {0, 0, 8},    //!< lowp float
2202             {13, 13, 10}, //!< mediump float
2203             {61, 61, 16}, //!< highp float
2204             {7, 7, 0},    //!< lowp int
2205             {9, 9, 0},    //!< mediump int
2206             {15, 15, 0},  //!< highp int
2207         };
2208         const int ndx = (int)m_precisionType - (int)GL_LOW_FLOAT;
2209 
2210         DE_ASSERT(ndx >= 0);
2211         DE_ASSERT(ndx < DE_LENGTH_OF_ARRAY(requirements));
2212         return requirements[ndx];
2213     }
2214 
2215     const glw::GLenum m_shaderType;
2216     const glw::GLenum m_precisionType;
2217 };
2218 
2219 } // namespace
2220 
ShaderStateQueryTests(Context & context)2221 ShaderStateQueryTests::ShaderStateQueryTests(Context &context)
2222     : TestCaseGroup(context, "shader", "Shader State Query tests")
2223 {
2224 }
2225 
init(void)2226 void ShaderStateQueryTests::init(void)
2227 {
2228     // shader
2229     addChild(new ShaderTypeCase(m_context, "shader_type", "SHADER_TYPE"));
2230     addChild(new ShaderCompileStatusCase(m_context, "shader_compile_status", "COMPILE_STATUS"));
2231     addChild(new ShaderInfoLogCase(m_context, "shader_info_log_length", "INFO_LOG_LENGTH"));
2232     addChild(new ShaderSourceCase(m_context, "shader_source_length", "SHADER_SOURCE_LENGTH"));
2233 
2234     // shader and program
2235     addChild(new DeleteStatusCase(m_context, "delete_status", "DELETE_STATUS"));
2236 
2237     // vertex-attrib
2238     addChild(new CurrentVertexAttribInitialCase(m_context, "current_vertex_attrib_initial", "CURRENT_VERTEX_ATTRIB"));
2239     addChild(new CurrentVertexAttribFloatCase(m_context, "current_vertex_attrib_float", "CURRENT_VERTEX_ATTRIB"));
2240     addChild(new CurrentVertexAttribConversionCase(m_context, "current_vertex_attrib_float_to_int",
2241                                                    "CURRENT_VERTEX_ATTRIB"));
2242 
2243     // program
2244     addChild(new ProgramInfoLogCase(m_context, "program_info_log_length", "INFO_LOG_LENGTH"));
2245     addChild(new ProgramValidateStatusCase(m_context, "program_validate_status", "VALIDATE_STATUS"));
2246     addChild(new ProgramAttachedShadersCase(m_context, "program_attached_shaders", "ATTACHED_SHADERS"));
2247 
2248     addChild(new ProgramActiveUniformNameCase(m_context, "program_active_uniform_name",
2249                                               "ACTIVE_UNIFORMS and ACTIVE_UNIFORM_MAX_LENGTH"));
2250     addChild(new ProgramUniformCase(m_context, "program_active_uniform_types", "UNIFORM_TYPE and UNIFORM_SIZE"));
2251 
2252     // attribute related
2253     addChild(
2254         new ActiveAttributesCase(m_context, "active_attributes", "ACTIVE_ATTRIBUTES and ACTIVE_ATTRIBUTE_MAX_LENGTH"));
2255     addChild(new VertexAttributeSizeCase(m_context, "vertex_attrib_size", "VERTEX_ATTRIB_ARRAY_SIZE"));
2256     addChild(new VertexAttributeTypeCase(m_context, "vertex_attrib_type", "VERTEX_ATTRIB_ARRAY_TYPE"));
2257     addChild(new VertexAttributeStrideCase(m_context, "vertex_attrib_stride", "VERTEX_ATTRIB_ARRAY_STRIDE"));
2258     addChild(
2259         new VertexAttributeNormalizedCase(m_context, "vertex_attrib_normalized", "VERTEX_ATTRIB_ARRAY_NORMALIZED"));
2260     addChild(new VertexAttributeEnabledCase(m_context, "vertex_attrib_array_enabled", "VERTEX_ATTRIB_ARRAY_ENABLED"));
2261     addChild(new VertexAttributeBufferBindingCase(m_context, "vertex_attrib_array_buffer_binding",
2262                                                   "VERTEX_ATTRIB_ARRAY_BUFFER_BINDING"));
2263     addChild(new VertexAttributePointerCase(m_context, "vertex_attrib_pointerv", "GetVertexAttribPointerv"));
2264 
2265     // uniform values
2266     addChild(new UniformValueFloatCase(m_context, "uniform_value_float", "GetUniform*"));
2267     addChild(new UniformValueIntCase(m_context, "uniform_value_int", "GetUniform*"));
2268     addChild(new UniformValueBooleanCase(m_context, "uniform_value_boolean", "GetUniform*"));
2269     addChild(new UniformValueSamplerCase(m_context, "uniform_value_sampler", "GetUniform*"));
2270     addChild(new UniformValueArrayCase(m_context, "uniform_value_array", "GetUniform*"));
2271     addChild(new UniformValueMatrixCase(m_context, "uniform_value_matrix", "GetUniform*"));
2272 
2273     // precision format query
2274     addChild(new PrecisionFormatCase(m_context, "precision_vertex_lowp_float", "GetShaderPrecisionFormat",
2275                                      GL_VERTEX_SHADER, GL_LOW_FLOAT));
2276     addChild(new PrecisionFormatCase(m_context, "precision_vertex_mediump_float", "GetShaderPrecisionFormat",
2277                                      GL_VERTEX_SHADER, GL_MEDIUM_FLOAT));
2278     addChild(new PrecisionFormatCase(m_context, "precision_vertex_highp_float", "GetShaderPrecisionFormat",
2279                                      GL_VERTEX_SHADER, GL_HIGH_FLOAT));
2280     addChild(new PrecisionFormatCase(m_context, "precision_vertex_lowp_int", "GetShaderPrecisionFormat",
2281                                      GL_VERTEX_SHADER, GL_LOW_INT));
2282     addChild(new PrecisionFormatCase(m_context, "precision_vertex_mediump_int", "GetShaderPrecisionFormat",
2283                                      GL_VERTEX_SHADER, GL_MEDIUM_INT));
2284     addChild(new PrecisionFormatCase(m_context, "precision_vertex_highp_int", "GetShaderPrecisionFormat",
2285                                      GL_VERTEX_SHADER, GL_HIGH_INT));
2286     addChild(new PrecisionFormatCase(m_context, "precision_fragment_lowp_float", "GetShaderPrecisionFormat",
2287                                      GL_FRAGMENT_SHADER, GL_LOW_FLOAT));
2288     addChild(new PrecisionFormatCase(m_context, "precision_fragment_mediump_float", "GetShaderPrecisionFormat",
2289                                      GL_FRAGMENT_SHADER, GL_MEDIUM_FLOAT));
2290     addChild(new PrecisionFormatCase(m_context, "precision_fragment_highp_float", "GetShaderPrecisionFormat",
2291                                      GL_FRAGMENT_SHADER, GL_HIGH_FLOAT));
2292     addChild(new PrecisionFormatCase(m_context, "precision_fragment_lowp_int", "GetShaderPrecisionFormat",
2293                                      GL_FRAGMENT_SHADER, GL_LOW_INT));
2294     addChild(new PrecisionFormatCase(m_context, "precision_fragment_mediump_int", "GetShaderPrecisionFormat",
2295                                      GL_FRAGMENT_SHADER, GL_MEDIUM_INT));
2296     addChild(new PrecisionFormatCase(m_context, "precision_fragment_highp_int", "GetShaderPrecisionFormat",
2297                                      GL_FRAGMENT_SHADER, GL_HIGH_INT));
2298 }
2299 
2300 } // namespace Functional
2301 } // namespace gles2
2302 } // namespace deqp
2303