Home | History | Annotate | Download | only in functional
      1 /*-------------------------------------------------------------------------
      2  * drawElements Quality Program OpenGL ES 3.1 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 Vertex attribute binding state query tests.
     22  *//*--------------------------------------------------------------------*/
     23 
     24 #include "es31fVertexAttributeBindingStateQueryTests.hpp"
     25 #include "tcuTestLog.hpp"
     26 #include "gluCallLogWrapper.hpp"
     27 #include "gluRenderContext.hpp"
     28 #include "gluObjectWrapper.hpp"
     29 #include "gluStrUtil.hpp"
     30 #include "glsStateQueryUtil.hpp"
     31 #include "glwEnums.hpp"
     32 #include "glwFunctions.hpp"
     33 #include "deRandom.hpp"
     34 
     35 namespace deqp
     36 {
     37 namespace gles31
     38 {
     39 namespace Functional
     40 {
     41 namespace
     42 {
     43 
     44 class AttributeBindingCase : public TestCase
     45 {
     46 public:
     47 					AttributeBindingCase	(Context& context, const char* name, const char* desc);
     48 	IterateResult	iterate					(void);
     49 };
     50 
     51 AttributeBindingCase::AttributeBindingCase (Context& context, const char* name, const char* desc)
     52 	: TestCase(context, name, desc)
     53 {
     54 }
     55 
     56 AttributeBindingCase::IterateResult AttributeBindingCase::iterate (void)
     57 {
     58 	glu::CallLogWrapper gl			(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
     59 	glu::VertexArray	vao			(m_context.getRenderContext());
     60 	glw::GLenum			error		= 0;
     61 	glw::GLint			maxAttrs	= -1;
     62 	bool				allOk		= true;
     63 
     64 	gl.enableLogging(true);
     65 
     66 	gl.glBindVertexArray(*vao);
     67 	gl.glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxAttrs);
     68 
     69 	// initial
     70 	{
     71 		const tcu::ScopedLogSection section(m_testCtx.getLog(), "initial", "Initial values");
     72 
     73 		for (int attr = 0; attr < de::max(16, maxAttrs); ++attr)
     74 		{
     75 			glw::GLint bindingState = -1;
     76 
     77 			gl.glGetVertexAttribiv(attr, GL_VERTEX_ATTRIB_BINDING, &bindingState);
     78 			error = gl.glGetError();
     79 
     80 			if (error != GL_NO_ERROR)
     81 			{
     82 				m_testCtx.getLog() << tcu::TestLog::Message << "// ERROR: Got error " << glu::getErrorStr(error) << tcu::TestLog::EndMessage;
     83 				allOk = false;
     84 			}
     85 			else if (bindingState != attr)
     86 			{
     87 				m_testCtx.getLog() << tcu::TestLog::Message << "// ERROR: Expected " << attr << ", got " << bindingState << tcu::TestLog::EndMessage;
     88 				allOk = false;
     89 			}
     90 		}
     91 	}
     92 
     93 	// is part of vao
     94 	{
     95 		const tcu::ScopedLogSection section			(m_testCtx.getLog(), "vao", "VAO state");
     96 		glu::VertexArray			otherVao		(m_context.getRenderContext());
     97 		glw::GLint					bindingState	= -1;
     98 
     99 		// set to value A in vao1
    100 		gl.glVertexAttribBinding(1, 4);
    101 
    102 		// set to value B in vao2
    103 		gl.glBindVertexArray(*otherVao);
    104 		gl.glVertexAttribBinding(1, 7);
    105 
    106 		// check value is still ok in original vao
    107 		gl.glBindVertexArray(*vao);
    108 		gl.glGetVertexAttribiv(1, GL_VERTEX_ATTRIB_BINDING, &bindingState);
    109 		error = gl.glGetError();
    110 
    111 		if (error != GL_NO_ERROR)
    112 		{
    113 			m_testCtx.getLog() << tcu::TestLog::Message << "// ERROR: Got error " << glu::getErrorStr(error) << tcu::TestLog::EndMessage;
    114 			allOk = false;
    115 		}
    116 		else if (bindingState != 4)
    117 		{
    118 			m_testCtx.getLog() << tcu::TestLog::Message << "// ERROR: Expected 4, got " << bindingState << tcu::TestLog::EndMessage;
    119 			allOk = false;
    120 		}
    121 	}
    122 
    123 	// random values
    124 	{
    125 		const tcu::ScopedLogSection	section			(m_testCtx.getLog(), "random", "Random values");
    126 		de::Random					rnd				(0xabc);
    127 		const int					numRandomTests	= 10;
    128 
    129 		for (int randomTestNdx = 0; randomTestNdx < numRandomTests; ++randomTestNdx)
    130 		{
    131 			// switch random va to random binding
    132 			const int	va				= rnd.getInt(0, de::max(16, maxAttrs)-1);
    133 			const int	binding			= rnd.getInt(0, 16);
    134 			glw::GLint	bindingState	= -1;
    135 
    136 			gl.glVertexAttribBinding(va, binding);
    137 			gl.glGetVertexAttribiv(va, GL_VERTEX_ATTRIB_BINDING, &bindingState);
    138 			error = gl.glGetError();
    139 
    140 			if (error != GL_NO_ERROR)
    141 			{
    142 				m_testCtx.getLog() << tcu::TestLog::Message << "// ERROR: Got error " << glu::getErrorStr(error) << tcu::TestLog::EndMessage;
    143 				allOk = false;
    144 			}
    145 			else if (bindingState != binding)
    146 			{
    147 				m_testCtx.getLog() << tcu::TestLog::Message << "// ERROR: Expected " << binding << ", got " << bindingState << tcu::TestLog::EndMessage;
    148 				allOk = false;
    149 			}
    150 		}
    151 	}
    152 
    153 	if (allOk)
    154 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
    155 	else
    156 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid value");
    157 	return STOP;
    158 }
    159 
    160 class AttributeRelativeOffsetCase : public TestCase
    161 {
    162 public:
    163 					AttributeRelativeOffsetCase	(Context& context, const char* name, const char* desc);
    164 	IterateResult	iterate						(void);
    165 };
    166 
    167 AttributeRelativeOffsetCase::AttributeRelativeOffsetCase (Context& context, const char* name, const char* desc)
    168 	: TestCase(context, name, desc)
    169 {
    170 }
    171 
    172 AttributeRelativeOffsetCase::IterateResult AttributeRelativeOffsetCase::iterate (void)
    173 {
    174 	glu::CallLogWrapper gl			(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
    175 	glu::VertexArray	vao			(m_context.getRenderContext());
    176 	glw::GLenum			error		= 0;
    177 	glw::GLint			maxAttrs	= -1;
    178 	bool				allOk		= true;
    179 
    180 	gl.enableLogging(true);
    181 
    182 	gl.glBindVertexArray(*vao);
    183 	gl.glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxAttrs);
    184 
    185 	// initial
    186 	{
    187 		const tcu::ScopedLogSection section(m_testCtx.getLog(), "initial", "Initial values");
    188 
    189 		for (int attr = 0; attr < de::max(16, maxAttrs); ++attr)
    190 		{
    191 			glw::GLint relOffsetState = -1;
    192 
    193 			gl.glGetVertexAttribiv(attr, GL_VERTEX_ATTRIB_RELATIVE_OFFSET, &relOffsetState);
    194 			error = gl.glGetError();
    195 
    196 			if (error != GL_NO_ERROR)
    197 			{
    198 				m_testCtx.getLog() << tcu::TestLog::Message << "// ERROR: Got error " << glu::getErrorStr(error) << tcu::TestLog::EndMessage;
    199 				allOk = false;
    200 			}
    201 			else if (relOffsetState != 0)
    202 			{
    203 				m_testCtx.getLog() << tcu::TestLog::Message << "// ERROR: Expected 0, got " << relOffsetState << tcu::TestLog::EndMessage;
    204 				allOk = false;
    205 			}
    206 		}
    207 	}
    208 
    209 	// is part of vao
    210 	{
    211 		const tcu::ScopedLogSection section			(m_testCtx.getLog(), "vao", "VAO state");
    212 		glu::VertexArray			otherVao		(m_context.getRenderContext());
    213 		glw::GLint					relOffsetState	= -1;
    214 
    215 		// set to value A in vao1
    216 		gl.glVertexAttribFormat(1, 4, GL_FLOAT, GL_FALSE, 9);
    217 
    218 		// set to value B in vao2
    219 		gl.glBindVertexArray(*otherVao);
    220 		gl.glVertexAttribFormat(1, 4, GL_FLOAT, GL_FALSE, 21);
    221 
    222 		// check value is still ok in original vao
    223 		gl.glBindVertexArray(*vao);
    224 		gl.glGetVertexAttribiv(1, GL_VERTEX_ATTRIB_RELATIVE_OFFSET, &relOffsetState);
    225 		error = gl.glGetError();
    226 
    227 		if (error != GL_NO_ERROR)
    228 		{
    229 			m_testCtx.getLog() << tcu::TestLog::Message << "// ERROR: Got error " << glu::getErrorStr(error) << tcu::TestLog::EndMessage;
    230 			allOk = false;
    231 		}
    232 		else if (relOffsetState != 9)
    233 		{
    234 			m_testCtx.getLog() << tcu::TestLog::Message << "// ERROR: Expected 9, got " << relOffsetState << tcu::TestLog::EndMessage;
    235 			allOk = false;
    236 		}
    237 	}
    238 
    239 	// random values
    240 	{
    241 		const tcu::ScopedLogSection	section			(m_testCtx.getLog(), "random", "Random values");
    242 		de::Random					rnd				(0xabc);
    243 		const int					numRandomTests	= 10;
    244 
    245 		for (int randomTestNdx = 0; randomTestNdx < numRandomTests; ++randomTestNdx)
    246 		{
    247 			const int	va				= rnd.getInt(0, de::max(16, maxAttrs)-1);
    248 			const int	offset			= rnd.getInt(0, 2047);
    249 			glw::GLint	relOffsetState	= -1;
    250 
    251 			gl.glVertexAttribFormat(va, 4, GL_FLOAT, GL_FALSE, offset);
    252 			gl.glGetVertexAttribiv(va, GL_VERTEX_ATTRIB_RELATIVE_OFFSET, &relOffsetState);
    253 			error = gl.glGetError();
    254 
    255 			if (error != GL_NO_ERROR)
    256 			{
    257 				m_testCtx.getLog() << tcu::TestLog::Message << "// ERROR: Got error " << glu::getErrorStr(error) << tcu::TestLog::EndMessage;
    258 				allOk = false;
    259 			}
    260 			else if (relOffsetState != offset)
    261 			{
    262 				m_testCtx.getLog() << tcu::TestLog::Message << "// ERROR: Expected " << offset << ", got " << relOffsetState << tcu::TestLog::EndMessage;
    263 				allOk = false;
    264 			}
    265 		}
    266 	}
    267 
    268 	if (allOk)
    269 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
    270 	else
    271 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid value");
    272 	return STOP;
    273 }
    274 
    275 class IndexedCase : public TestCase
    276 {
    277 public:
    278 	enum VerifierType
    279 	{
    280 		VERIFIER_INT,
    281 		VERIFIER_INT64,
    282 
    283 		VERIFIER_LAST
    284 	};
    285 
    286 						IndexedCase			(Context& context, const char* name, const char* desc, VerifierType verifier);
    287 
    288 	IterateResult		iterate				(void);
    289 	void				verifyValue			(glu::CallLogWrapper& gl, glw::GLenum name, int index, int expected);
    290 
    291 	virtual void		test				(void) = 0;
    292 private:
    293 	const VerifierType	m_verifier;
    294 };
    295 
    296 IndexedCase::IndexedCase (Context& context, const char* name, const char* desc, VerifierType verifier)
    297 	: TestCase		(context, name, desc)
    298 	, m_verifier	(verifier)
    299 {
    300 	DE_ASSERT(verifier < VERIFIER_LAST);
    301 }
    302 
    303 IndexedCase::IterateResult IndexedCase::iterate (void)
    304 {
    305 	// default value
    306 	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
    307 
    308 	test();
    309 
    310 	return STOP;
    311 }
    312 
    313 void IndexedCase::verifyValue (glu::CallLogWrapper& gl, glw::GLenum name, int index, int expected)
    314 {
    315 	if (m_verifier == VERIFIER_INT)
    316 	{
    317 		gls::StateQueryUtil::StateQueryMemoryWriteGuard<glw::GLint>	value;
    318 		glw::GLenum													error = 0;
    319 
    320 		gl.glGetIntegeri_v(name, index, &value);
    321 		error = gl.glGetError();
    322 
    323 		if (error != GL_NO_ERROR)
    324 		{
    325 			m_testCtx.getLog() << tcu::TestLog::Message << "// ERROR: Got unexpected error: " << glu::getErrorStr(error) << tcu::TestLog::EndMessage;
    326 			if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
    327 				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got unexpected error");
    328 		}
    329 		else if (!value.verifyValidity(m_testCtx))
    330 		{
    331 			// verifyValidity sets error
    332 		}
    333 		else
    334 		{
    335 			if (value != expected)
    336 			{
    337 				m_testCtx.getLog() << tcu::TestLog::Message << "// ERROR: Expected " << expected << ", got " << value << tcu::TestLog::EndMessage;
    338 				if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
    339 					m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got unexpected value");
    340 			}
    341 		}
    342 	}
    343 	else if (m_verifier == VERIFIER_INT64)
    344 	{
    345 		gls::StateQueryUtil::StateQueryMemoryWriteGuard<glw::GLint64>	value;
    346 		glw::GLenum														error = 0;
    347 
    348 		gl.glGetInteger64i_v(name, index, &value);
    349 		error = gl.glGetError();
    350 
    351 		if (error != GL_NO_ERROR)
    352 		{
    353 			m_testCtx.getLog() << tcu::TestLog::Message << "// ERROR: Got unexpected error: " << glu::getErrorStr(error) << tcu::TestLog::EndMessage;
    354 			if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
    355 				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got unexpected error");
    356 		}
    357 		else if (!value.verifyValidity(m_testCtx))
    358 		{
    359 			// verifyValidity sets error
    360 		}
    361 		else
    362 		{
    363 			if (value != expected)
    364 			{
    365 				m_testCtx.getLog() << tcu::TestLog::Message << "// ERROR: Expected " << expected << ", got " << value << tcu::TestLog::EndMessage;
    366 				if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS)
    367 					m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got unexpected value");
    368 			}
    369 		}
    370 	}
    371 	else
    372 		DE_ASSERT(false);
    373 }
    374 
    375 class VertexBindingDivisorCase : public IndexedCase
    376 {
    377 public:
    378 			VertexBindingDivisorCase	(Context& context, const char* name, const char* desc, VerifierType verifier);
    379 	void	test						(void);
    380 };
    381 
    382 VertexBindingDivisorCase::VertexBindingDivisorCase (Context& context, const char* name, const char* desc, VerifierType verifier)
    383 	: IndexedCase(context, name, desc, verifier)
    384 {
    385 }
    386 
    387 void VertexBindingDivisorCase::test (void)
    388 {
    389 	glu::CallLogWrapper gl					(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
    390 	glu::VertexArray	vao					(m_context.getRenderContext());
    391 	glw::GLint			reportedMaxBindings	= -1;
    392 	glw::GLint			maxBindings;
    393 
    394 	gl.enableLogging(true);
    395 
    396 	gl.glBindVertexArray(*vao);
    397 	gl.glGetIntegerv(GL_MAX_VERTEX_ATTRIB_BINDINGS, &reportedMaxBindings);
    398 	maxBindings = de::max(16, reportedMaxBindings);
    399 
    400 	// initial
    401 	{
    402 		const tcu::ScopedLogSection section(m_testCtx.getLog(), "initial", "Initial values");
    403 
    404 		for (int binding = 0; binding < maxBindings; ++binding)
    405 			verifyValue(gl, GL_VERTEX_BINDING_DIVISOR, binding, 0);
    406 	}
    407 
    408 	// is part of vao
    409 	{
    410 		const tcu::ScopedLogSection section			(m_testCtx.getLog(), "vao", "VAO state");
    411 		glu::VertexArray			otherVao		(m_context.getRenderContext());
    412 
    413 		// set to value A in vao1
    414 		gl.glVertexBindingDivisor(1, 4);
    415 
    416 		// set to value B in vao2
    417 		gl.glBindVertexArray(*otherVao);
    418 		gl.glVertexBindingDivisor(1, 9);
    419 
    420 		// check value is still ok in original vao
    421 		gl.glBindVertexArray(*vao);
    422 		verifyValue(gl, GL_VERTEX_BINDING_DIVISOR, 1, 4);
    423 	}
    424 
    425 	// random values
    426 	{
    427 		const tcu::ScopedLogSection	section			(m_testCtx.getLog(), "random", "Random values");
    428 		de::Random					rnd				(0xabc);
    429 		const int					numRandomTests	= 10;
    430 
    431 		for (int randomTestNdx = 0; randomTestNdx < numRandomTests; ++randomTestNdx)
    432 		{
    433 			const int	binding			= rnd.getInt(0, maxBindings-1);
    434 			const int	divisor			= rnd.getInt(0, 2047);
    435 
    436 			gl.glVertexBindingDivisor(binding, divisor);
    437 			verifyValue(gl, GL_VERTEX_BINDING_DIVISOR, binding, divisor);
    438 		}
    439 	}
    440 }
    441 
    442 class VertexBindingOffsetCase : public IndexedCase
    443 {
    444 public:
    445 			VertexBindingOffsetCase		(Context& context, const char* name, const char* desc, VerifierType verifier);
    446 	void	test						(void);
    447 };
    448 
    449 VertexBindingOffsetCase::VertexBindingOffsetCase (Context& context, const char* name, const char* desc, VerifierType verifier)
    450 	: IndexedCase(context, name, desc, verifier)
    451 {
    452 }
    453 
    454 void VertexBindingOffsetCase::test (void)
    455 {
    456 	glu::CallLogWrapper gl					(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
    457 	glu::VertexArray	vao					(m_context.getRenderContext());
    458 	glu::Buffer			buffer				(m_context.getRenderContext());
    459 	glw::GLint			reportedMaxBindings	= -1;
    460 	glw::GLint			maxBindings;
    461 
    462 	gl.enableLogging(true);
    463 
    464 	gl.glBindVertexArray(*vao);
    465 	gl.glGetIntegerv(GL_MAX_VERTEX_ATTRIB_BINDINGS, &reportedMaxBindings);
    466 	maxBindings = de::max(16, reportedMaxBindings);
    467 
    468 	// initial
    469 	{
    470 		const tcu::ScopedLogSection section(m_testCtx.getLog(), "initial", "Initial values");
    471 
    472 		for (int binding = 0; binding < maxBindings; ++binding)
    473 			verifyValue(gl, GL_VERTEX_BINDING_OFFSET, binding, 0);
    474 	}
    475 
    476 	// is part of vao
    477 	{
    478 		const tcu::ScopedLogSection section			(m_testCtx.getLog(), "vao", "VAO state");
    479 		glu::VertexArray			otherVao		(m_context.getRenderContext());
    480 
    481 		// set to value A in vao1
    482 		gl.glBindVertexBuffer(1, *buffer, 4, 32);
    483 
    484 		// set to value B in vao2
    485 		gl.glBindVertexArray(*otherVao);
    486 		gl.glBindVertexBuffer(1, *buffer, 13, 32);
    487 
    488 		// check value is still ok in original vao
    489 		gl.glBindVertexArray(*vao);
    490 		verifyValue(gl, GL_VERTEX_BINDING_OFFSET, 1, 4);
    491 	}
    492 
    493 	// random values
    494 	{
    495 		const tcu::ScopedLogSection	section			(m_testCtx.getLog(), "random", "Random values");
    496 		de::Random					rnd				(0xabc);
    497 		const int					numRandomTests	= 10;
    498 
    499 		for (int randomTestNdx = 0; randomTestNdx < numRandomTests; ++randomTestNdx)
    500 		{
    501 			const int	binding			= rnd.getInt(0, maxBindings-1);
    502 			const int	offset			= rnd.getInt(0, 4000);
    503 
    504 			gl.glBindVertexBuffer(binding, *buffer, offset, 32);
    505 			verifyValue(gl, GL_VERTEX_BINDING_OFFSET, binding, offset);
    506 		}
    507 	}
    508 }
    509 
    510 class VertexBindingStrideCase : public IndexedCase
    511 {
    512 public:
    513 			VertexBindingStrideCase		(Context& context, const char* name, const char* desc, VerifierType verifier);
    514 	void	test						(void);
    515 };
    516 
    517 VertexBindingStrideCase::VertexBindingStrideCase (Context& context, const char* name, const char* desc, VerifierType verifier)
    518 	: IndexedCase(context, name, desc, verifier)
    519 {
    520 }
    521 
    522 void VertexBindingStrideCase::test (void)
    523 {
    524 	glu::CallLogWrapper gl					(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
    525 	glu::VertexArray	vao					(m_context.getRenderContext());
    526 	glu::Buffer			buffer				(m_context.getRenderContext());
    527 	glw::GLint			reportedMaxBindings	= -1;
    528 	glw::GLint			maxBindings;
    529 
    530 	gl.enableLogging(true);
    531 
    532 	gl.glBindVertexArray(*vao);
    533 	gl.glGetIntegerv(GL_MAX_VERTEX_ATTRIB_BINDINGS, &reportedMaxBindings);
    534 	maxBindings = de::max(16, reportedMaxBindings);
    535 
    536 	// initial
    537 	{
    538 		const tcu::ScopedLogSection section(m_testCtx.getLog(), "initial", "Initial values");
    539 
    540 		for (int binding = 0; binding < maxBindings; ++binding)
    541 			verifyValue(gl, GL_VERTEX_BINDING_STRIDE, binding, 16);
    542 	}
    543 
    544 	// is part of vao
    545 	{
    546 		const tcu::ScopedLogSection section			(m_testCtx.getLog(), "vao", "VAO state");
    547 		glu::VertexArray			otherVao		(m_context.getRenderContext());
    548 
    549 		// set to value A in vao1
    550 		gl.glBindVertexBuffer(1, *buffer, 0, 32);
    551 
    552 		// set to value B in vao2
    553 		gl.glBindVertexArray(*otherVao);
    554 		gl.glBindVertexBuffer(1, *buffer, 0, 64);
    555 
    556 		// check value is still ok in original vao
    557 		gl.glBindVertexArray(*vao);
    558 		verifyValue(gl, GL_VERTEX_BINDING_STRIDE, 1, 32);
    559 	}
    560 
    561 	// random values
    562 	{
    563 		const tcu::ScopedLogSection	section			(m_testCtx.getLog(), "random", "Random values");
    564 		de::Random					rnd				(0xabc);
    565 		const int					numRandomTests	= 10;
    566 
    567 		for (int randomTestNdx = 0; randomTestNdx < numRandomTests; ++randomTestNdx)
    568 		{
    569 			const int	binding			= rnd.getInt(0, maxBindings-1);
    570 			const int	stride			= rnd.getInt(0, 2048);
    571 
    572 			gl.glBindVertexBuffer(binding, *buffer, 0, stride);
    573 			verifyValue(gl, GL_VERTEX_BINDING_STRIDE, binding, stride);
    574 		}
    575 	}
    576 }
    577 
    578 class VertexBindingBufferCase : public IndexedCase
    579 {
    580 public:
    581 			VertexBindingBufferCase		(Context& context, const char* name, const char* desc, VerifierType verifier);
    582 	void	test						(void);
    583 };
    584 
    585 VertexBindingBufferCase::VertexBindingBufferCase (Context& context, const char* name, const char* desc, VerifierType verifier)
    586 	: IndexedCase(context, name, desc, verifier)
    587 {
    588 }
    589 
    590 void VertexBindingBufferCase::test (void)
    591 {
    592 	glu::CallLogWrapper gl					(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
    593 	glu::VertexArray	vao					(m_context.getRenderContext());
    594 	glu::Buffer			buffer				(m_context.getRenderContext());
    595 	glw::GLint			reportedMaxBindings	= -1;
    596 	glw::GLint			maxBindings;
    597 
    598 	gl.enableLogging(true);
    599 
    600 	gl.glBindVertexArray(*vao);
    601 	gl.glGetIntegerv(GL_MAX_VERTEX_ATTRIB_BINDINGS, &reportedMaxBindings);
    602 	maxBindings = de::max(16, reportedMaxBindings);
    603 
    604 	// initial
    605 	{
    606 		const tcu::ScopedLogSection section(m_testCtx.getLog(), "initial", "Initial values");
    607 
    608 		for (int binding = 0; binding < maxBindings; ++binding)
    609 			verifyValue(gl, GL_VERTEX_BINDING_BUFFER, binding, 0);
    610 	}
    611 
    612 	// is part of vao
    613 	{
    614 		const tcu::ScopedLogSection section			(m_testCtx.getLog(), "vao", "VAO state");
    615 		glu::VertexArray			otherVao		(m_context.getRenderContext());
    616 		glu::Buffer					otherBuffer		(m_context.getRenderContext());
    617 
    618 		// set to value A in vao1
    619 		gl.glBindVertexBuffer(1, *buffer, 0, 32);
    620 
    621 		// set to value B in vao2
    622 		gl.glBindVertexArray(*otherVao);
    623 		gl.glBindVertexBuffer(1, *otherBuffer, 0, 32);
    624 
    625 		// check value is still ok in original vao
    626 		gl.glBindVertexArray(*vao);
    627 		verifyValue(gl, GL_VERTEX_BINDING_BUFFER, 1, *buffer);
    628 	}
    629 
    630 	// Is detached in delete from active vao and not from deactive
    631 	{
    632 		const tcu::ScopedLogSection section			(m_testCtx.getLog(), "autoUnbind", "Unbind on delete");
    633 		glu::VertexArray			otherVao		(m_context.getRenderContext());
    634 		glw::GLuint					otherBuffer		= -1;
    635 
    636 		gl.glGenBuffers(1, &otherBuffer);
    637 
    638 		// set in vao1 and vao2
    639 		gl.glBindVertexBuffer(1, otherBuffer, 0, 32);
    640 		gl.glBindVertexArray(*otherVao);
    641 		gl.glBindVertexBuffer(1, otherBuffer, 0, 32);
    642 
    643 		// delete buffer. This unbinds it from active (vao2) but not from unactive
    644 		gl.glDeleteBuffers(1, &otherBuffer);
    645 		verifyValue(gl, GL_VERTEX_BINDING_BUFFER, 1, 0);
    646 		gl.glBindVertexArray(*vao);
    647 		verifyValue(gl, GL_VERTEX_BINDING_BUFFER, 1, otherBuffer);
    648 	}
    649 }
    650 
    651 class MixedVertexBindingDivisorCase : public IndexedCase
    652 {
    653 public:
    654 			MixedVertexBindingDivisorCase	(Context& context, const char* name, const char* desc);
    655 	void	test							(void);
    656 };
    657 
    658 MixedVertexBindingDivisorCase::MixedVertexBindingDivisorCase (Context& context, const char* name, const char* desc)
    659 	: IndexedCase(context, name, desc, VERIFIER_INT)
    660 {
    661 }
    662 
    663 void MixedVertexBindingDivisorCase::test (void)
    664 {
    665 	glu::CallLogWrapper gl					(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
    666 	glu::VertexArray	vao					(m_context.getRenderContext());
    667 
    668 	gl.enableLogging(true);
    669 
    670 	gl.glVertexAttribDivisor(1, 4);
    671 	verifyValue(gl, GL_VERTEX_BINDING_DIVISOR, 1, 4);
    672 }
    673 
    674 class MixedVertexBindingOffsetCase : public IndexedCase
    675 {
    676 public:
    677 			MixedVertexBindingOffsetCase	(Context& context, const char* name, const char* desc);
    678 	void	test							(void);
    679 };
    680 
    681 MixedVertexBindingOffsetCase::MixedVertexBindingOffsetCase (Context& context, const char* name, const char* desc)
    682 	: IndexedCase(context, name, desc, VERIFIER_INT)
    683 {
    684 }
    685 
    686 void MixedVertexBindingOffsetCase::test (void)
    687 {
    688 	glu::CallLogWrapper gl					(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
    689 	glu::VertexArray	vao					(m_context.getRenderContext());
    690 	glu::Buffer			buffer				(m_context.getRenderContext());
    691 
    692 	gl.enableLogging(true);
    693 
    694 	gl.glBindBuffer(GL_ARRAY_BUFFER, *buffer);
    695 	gl.glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, (const deUint8*)DE_NULL + 12);
    696 
    697 	verifyValue(gl, GL_VERTEX_BINDING_OFFSET, 1, 12);
    698 }
    699 
    700 class MixedVertexBindingStrideCase : public IndexedCase
    701 {
    702 public:
    703 			MixedVertexBindingStrideCase	(Context& context, const char* name, const char* desc);
    704 	void	test							(void);
    705 };
    706 
    707 MixedVertexBindingStrideCase::MixedVertexBindingStrideCase (Context& context, const char* name, const char* desc)
    708 	: IndexedCase(context, name, desc, VERIFIER_INT)
    709 {
    710 }
    711 
    712 void MixedVertexBindingStrideCase::test (void)
    713 {
    714 	glu::CallLogWrapper gl					(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
    715 	glu::VertexArray	vao					(m_context.getRenderContext());
    716 	glu::Buffer			buffer				(m_context.getRenderContext());
    717 
    718 	gl.enableLogging(true);
    719 
    720 	gl.glBindBuffer(GL_ARRAY_BUFFER, *buffer);
    721 	gl.glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 12, 0);
    722 	verifyValue(gl, GL_VERTEX_BINDING_STRIDE, 1, 12);
    723 
    724 	// test effectiveStride
    725 	gl.glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, 0);
    726 	verifyValue(gl, GL_VERTEX_BINDING_STRIDE, 1, 16);
    727 }
    728 
    729 class MixedVertexBindingBufferCase : public IndexedCase
    730 {
    731 public:
    732 			MixedVertexBindingBufferCase	(Context& context, const char* name, const char* desc);
    733 	void	test							(void);
    734 };
    735 
    736 MixedVertexBindingBufferCase::MixedVertexBindingBufferCase (Context& context, const char* name, const char* desc)
    737 	: IndexedCase(context, name, desc, VERIFIER_INT)
    738 {
    739 }
    740 
    741 void MixedVertexBindingBufferCase::test (void)
    742 {
    743 	glu::CallLogWrapper gl					(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
    744 	glu::VertexArray	vao					(m_context.getRenderContext());
    745 	glu::Buffer			buffer				(m_context.getRenderContext());
    746 
    747 	gl.enableLogging(true);
    748 
    749 	gl.glBindBuffer(GL_ARRAY_BUFFER, *buffer);
    750 	gl.glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, 0);
    751 	verifyValue(gl, GL_VERTEX_BINDING_BUFFER, 1, *buffer);
    752 }
    753 
    754 } // anonymous
    755 
    756 VertexAttributeBindingStateQueryTests::VertexAttributeBindingStateQueryTests (Context& context)
    757 	: TestCaseGroup(context, "vertex_attribute_binding", "Query vertex attribute binding state.")
    758 {
    759 }
    760 
    761 VertexAttributeBindingStateQueryTests::~VertexAttributeBindingStateQueryTests (void)
    762 {
    763 }
    764 
    765 void VertexAttributeBindingStateQueryTests::init (void)
    766 {
    767 	tcu::TestCaseGroup* const attributeGroup	= new TestCaseGroup(m_context, "vertex_attrib", "Vertex attribute state");
    768 	tcu::TestCaseGroup* const indexedGroup		= new TestCaseGroup(m_context, "indexed", "Indexed state");
    769 
    770 	addChild(attributeGroup);
    771 	addChild(indexedGroup);
    772 
    773 	// .vertex_attrib
    774 	{
    775 		attributeGroup->addChild(new AttributeBindingCase		(m_context,	"vertex_attrib_binding",			"Test VERTEX_ATTRIB_BINDING"));
    776 		attributeGroup->addChild(new AttributeRelativeOffsetCase(m_context,	"vertex_attrib_relative_offset",	"Test VERTEX_ATTRIB_RELATIVE_OFFSET"));
    777 	}
    778 
    779 	// .indexed (and 64)
    780 	{
    781 		static const struct Verifier
    782 		{
    783 			const char*					name;
    784 			IndexedCase::VerifierType	type;
    785 		} verifiers[] =
    786 		{
    787 			{ "getintegeri",	IndexedCase::VERIFIER_INT	},
    788 			{ "getintegeri64",	IndexedCase::VERIFIER_INT64	},
    789 		};
    790 
    791 		// states
    792 
    793 		for (int verifierNdx = 0; verifierNdx < DE_LENGTH_OF_ARRAY(verifiers); ++verifierNdx)
    794 		{
    795 			indexedGroup->addChild(new VertexBindingDivisorCase	(m_context, (std::string("vertex_binding_divisor_") + verifiers[verifierNdx].name).c_str(),	"Test VERTEX_BINDING_DIVISOR",	verifiers[verifierNdx].type));
    796 			indexedGroup->addChild(new VertexBindingOffsetCase	(m_context, (std::string("vertex_binding_offset_") + verifiers[verifierNdx].name).c_str(),	"Test VERTEX_BINDING_OFFSET",	verifiers[verifierNdx].type));
    797 			indexedGroup->addChild(new VertexBindingStrideCase	(m_context, (std::string("vertex_binding_stride_") + verifiers[verifierNdx].name).c_str(),	"Test VERTEX_BINDING_STRIDE",	verifiers[verifierNdx].type));
    798 			indexedGroup->addChild(new VertexBindingBufferCase	(m_context, (std::string("vertex_binding_buffer_") + verifiers[verifierNdx].name).c_str(),	"Test VERTEX_BINDING_BUFFER",	verifiers[verifierNdx].type));
    799 		}
    800 
    801 		// mixed apis
    802 
    803 		indexedGroup->addChild(new MixedVertexBindingDivisorCase(m_context, "vertex_binding_divisor_mixed",	"Test VERTEX_BINDING_DIVISOR"));
    804 		indexedGroup->addChild(new MixedVertexBindingOffsetCase	(m_context, "vertex_binding_offset_mixed",	"Test VERTEX_BINDING_OFFSET"));
    805 		indexedGroup->addChild(new MixedVertexBindingStrideCase	(m_context, "vertex_binding_stride_mixed",	"Test VERTEX_BINDING_STRIDE"));
    806 		indexedGroup->addChild(new MixedVertexBindingBufferCase	(m_context, "vertex_binding_buffer_mixed",	"Test VERTEX_BINDING_BUFFER"));
    807 	}
    808 }
    809 
    810 } // Functional
    811 } // gles31
    812 } // deqp
    813