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