Home | History | Annotate | Download | only in functional
      1 /*-------------------------------------------------------------------------
      2  * drawElements Quality Program OpenGL ES 3.0 Module
      3  * -------------------------------------------------
      4  *
      5  * Copyright 2014 The Android Open Source Project
      6  *
      7  * Licensed under the Apache License, Version 2.0 (the "License");
      8  * you may not use this file except in compliance with the License.
      9  * You may obtain a copy of the License at
     10  *
     11  *      http://www.apache.org/licenses/LICENSE-2.0
     12  *
     13  * Unless required by applicable law or agreed to in writing, software
     14  * distributed under the License is distributed on an "AS IS" BASIS,
     15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     16  * See the License for the specific language governing permissions and
     17  * limitations under the License.
     18  *
     19  *//*!
     20  * \file
     21  * \brief Vertex array object tests
     22  *//*--------------------------------------------------------------------*/
     23 #include "es3fVertexArrayObjectTests.hpp"
     24 
     25 #include "gluShaderProgram.hpp"
     26 #include "gluPixelTransfer.hpp"
     27 #include "gluRenderContext.hpp"
     28 
     29 #include "tcuTestLog.hpp"
     30 #include "tcuImageCompare.hpp"
     31 #include "tcuSurface.hpp"
     32 #include "tcuRenderTarget.hpp"
     33 
     34 #include "deRandom.hpp"
     35 #include "deString.h"
     36 #include "deMemory.h"
     37 
     38 #include <vector>
     39 #include <string>
     40 #include <memory>
     41 
     42 #include "glw.h"
     43 
     44 using std::vector;
     45 using std::string;
     46 
     47 namespace deqp
     48 {
     49 namespace gles3
     50 {
     51 namespace Functional
     52 {
     53 
     54 namespace
     55 {
     56 struct Attribute
     57 {
     58 				Attribute (void);
     59 	GLboolean	enabled;
     60 	GLint		size;
     61 	GLint		stride;
     62 	GLenum		type;
     63 	GLboolean	integer;
     64 	GLint		divisor;
     65 	GLint		offset;
     66 	GLboolean	normalized;
     67 
     68 	int			bufferNdx;
     69 };
     70 
     71 struct VertexArrayState
     72 {
     73 						VertexArrayState	(void);
     74 
     75 	vector<Attribute>	attributes;
     76 	int					elementArrayBuffer;
     77 };
     78 
     79 VertexArrayState::VertexArrayState (void)
     80 	: elementArrayBuffer(-1)
     81 {
     82 }
     83 
     84 Attribute::Attribute (void)
     85 	: enabled		(GL_FALSE)
     86 	, size			(1)
     87 	, stride		(0)
     88 	, type			(GL_FLOAT)
     89 	, integer		(GL_FALSE)
     90 	, divisor		(0)
     91 	, offset		(0)
     92 	, normalized	(GL_FALSE)
     93 	, bufferNdx		(0)
     94 {
     95 }
     96 
     97 struct BufferSpec
     98 {
     99 	int		count;
    100 	int		size;
    101 	int		componentCount;
    102 	int		stride;
    103 	int		offset;
    104 
    105 	GLenum	type;
    106 
    107 	int		intRangeMin;
    108 	int		intRangeMax;
    109 
    110 	float	floatRangeMin;
    111 	float	floatRangeMax;
    112 };
    113 
    114 struct Spec
    115 {
    116 						Spec	(void);
    117 
    118 	int					count;
    119 	int					instances;
    120 	bool				useDrawElements;
    121 	GLenum				indexType;
    122 	int					indexOffset;
    123 	int					indexRangeMin;
    124 	int					indexRangeMax;
    125 	int					indexCount;
    126 	VertexArrayState	state;
    127 	VertexArrayState	vao;
    128 	vector<BufferSpec>	buffers;
    129 };
    130 
    131 Spec::Spec (void)
    132 	: count				(-1)
    133 	, instances			(-1)
    134 	, useDrawElements	(false)
    135 	, indexType			(GL_NONE)
    136 	, indexOffset		(-1)
    137 	, indexRangeMin		(-1)
    138 	, indexRangeMax		(-1)
    139 	, indexCount		(-1)
    140 {
    141 }
    142 
    143 } // anonymous
    144 
    145 class VertexArrayObjectTest : public TestCase
    146 {
    147 public:
    148 
    149 							VertexArrayObjectTest	(Context& context, const Spec& spec, const char* name, const char* description);
    150 							~VertexArrayObjectTest	(void);
    151 	virtual void			init					(void);
    152 	virtual void			deinit					(void);
    153 	virtual IterateResult	iterate					(void);
    154 
    155 private:
    156 	Spec					m_spec;
    157 	tcu::TestLog&			m_log;
    158 	vector<GLuint>			m_buffers;
    159 	glu::ShaderProgram*		m_vaoProgram;
    160 	glu::ShaderProgram*		m_stateProgram;
    161 	de::Random				m_random;
    162 	deUint8*				m_indices;
    163 
    164 	void					logVertexArrayState (tcu::TestLog& log, const VertexArrayState& state, const std::string& msg);
    165 	deUint8*				createRandomBufferData	(const BufferSpec& buffer);
    166 	deUint8*				generateIndices			(void);
    167 	glu::ShaderProgram*		createProgram			(const VertexArrayState& state);
    168 	void					setState				(const VertexArrayState& state);
    169 	void					render					(tcu::Surface& vaoResult, tcu::Surface& defaultResult);
    170 	void					makeDrawCall			(const VertexArrayState& state);
    171 	void					genReferences			(tcu::Surface& vaoRef, tcu::Surface& defaultRef);
    172 
    173 							VertexArrayObjectTest	(const VertexArrayObjectTest&);
    174 	VertexArrayObjectTest&	operator=				(const VertexArrayObjectTest&);
    175 };
    176 
    177 VertexArrayObjectTest::VertexArrayObjectTest (Context& context, const Spec& spec, const char* name, const char* description)
    178 	: TestCase			(context, name, description)
    179 	, m_spec			(spec)
    180 	, m_log				(context.getTestContext().getLog())
    181 	, m_vaoProgram		(NULL)
    182 	, m_stateProgram	(NULL)
    183 	, m_random			(deStringHash(name))
    184 	, m_indices			(NULL)
    185 {
    186 	// Makes zero to zero mapping for buffers
    187 	m_buffers.push_back(0);
    188 }
    189 
    190 VertexArrayObjectTest::~VertexArrayObjectTest (void)
    191 {
    192 }
    193 
    194 void VertexArrayObjectTest::logVertexArrayState (tcu::TestLog& log, const VertexArrayState& state, const std::string& msg)
    195 {
    196 	std::stringstream message;
    197 
    198 	message << msg << "\n";
    199 	message << "GL_ELEMENT_ARRAY_BUFFER : " << state.elementArrayBuffer << "\n";
    200 
    201 	for (int attribNdx = 0; attribNdx < (int)state.attributes.size(); attribNdx++)
    202 	{
    203 		message
    204 		<< "attribute : " << attribNdx << "\n"
    205 		<< "\tGL_VERTEX_ATTRIB_ARRAY_ENABLED : " << (state.attributes[attribNdx].enabled ? "GL_TRUE" : "GL_FALSE") <<  "\n"
    206 		<< "\tGL_VERTEX_ATTRIB_ARRAY_SIZE : " << state.attributes[attribNdx].size <<  "\n"
    207 		<< "\tGL_VERTEX_ATTRIB_ARRAY_STRIDE : " << state.attributes[attribNdx].stride <<  "\n"
    208 		<< "\tGL_VERTEX_ATTRIB_ARRAY_TYPE : " << state.attributes[attribNdx].type <<  "\n"
    209 		<< "\tGL_VERTEX_ATTRIB_ARRAY_NORMALIZED : " << (state.attributes[attribNdx].normalized ? "GL_TRUE" : "GL_FALSE") <<  "\n"
    210 		<< "\tGL_VERTEX_ATTRIB_ARRAY_INTEGER : " << (state.attributes[attribNdx].integer ? "GL_TRUE" : "GL_FALSE") <<  "\n"
    211 		<< "\tGL_VERTEX_ATTRIB_ARRAY_DIVISOR : " << state.attributes[attribNdx].divisor <<  "\n"
    212 		<< "\tGL_VERTEX_ATTRIB_ARRAY_POINTER : " << state.attributes[attribNdx].offset <<  "\n"
    213 		<< "\tGL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING : " << m_buffers[state.attributes[attribNdx].bufferNdx] <<  "\n";
    214 	}
    215 	log << tcu::TestLog::Message << message.str() << tcu::TestLog::EndMessage;
    216 }
    217 
    218 
    219 void VertexArrayObjectTest::init (void)
    220 {
    221 	// \note [mika] Index 0 is reserved for 0 buffer
    222 	for (int bufferNdx = 0; bufferNdx < (int)m_spec.buffers.size(); bufferNdx++)
    223 	{
    224 		deUint8* data = createRandomBufferData(m_spec.buffers[bufferNdx]);
    225 
    226 		try
    227 		{
    228 			GLuint buffer;
    229 			GLU_CHECK_CALL(glGenBuffers(1, &buffer));
    230 			m_buffers.push_back(buffer);
    231 
    232 			GLU_CHECK_CALL(glBindBuffer(GL_ARRAY_BUFFER, buffer));
    233 			GLU_CHECK_CALL(glBufferData(GL_ARRAY_BUFFER, m_spec.buffers[bufferNdx].size, data, GL_DYNAMIC_DRAW));
    234 			GLU_CHECK_CALL(glBindBuffer(GL_ARRAY_BUFFER, 0));
    235 
    236 		} catch (...) {
    237 			delete[] data;
    238 			throw;
    239 		}
    240 
    241 		delete[] data;
    242 	}
    243 
    244 	m_vaoProgram	= createProgram(m_spec.vao);
    245 	m_log << tcu::TestLog::Message << "Program used with Vertex Array Object" << tcu::TestLog::EndMessage;
    246 	m_log << *m_vaoProgram;
    247 	m_stateProgram	= createProgram(m_spec.state);
    248 	m_log << tcu::TestLog::Message << "Program used with Vertex Array State" << tcu::TestLog::EndMessage;
    249 	m_log << *m_stateProgram;
    250 
    251 	if (!m_vaoProgram->isOk() || !m_stateProgram->isOk())
    252 		TCU_FAIL("Failed to compile shaders");
    253 
    254 	if (m_spec.useDrawElements && (m_spec.vao.elementArrayBuffer == 0 || m_spec.state.elementArrayBuffer == 0))
    255 		m_indices = generateIndices();
    256 }
    257 
    258 void VertexArrayObjectTest::deinit (void)
    259 {
    260 	GLU_CHECK_CALL(glDeleteBuffers((GLsizei)m_buffers.size(), &(m_buffers[0])));
    261 	m_buffers.clear();
    262 	delete m_vaoProgram;
    263 	delete m_stateProgram;
    264 	delete[] m_indices;
    265 }
    266 
    267 deUint8* VertexArrayObjectTest::generateIndices (void)
    268 {
    269 	int typeSize = 0;
    270 	switch (m_spec.indexType)
    271 	{
    272 		case GL_UNSIGNED_INT:	typeSize = sizeof(GLuint);		break;
    273 		case GL_UNSIGNED_SHORT:	typeSize = sizeof(GLushort);	break;
    274 		case GL_UNSIGNED_BYTE:	typeSize = sizeof(GLubyte);		break;
    275 		default:
    276 			DE_ASSERT(false);
    277 	}
    278 
    279 	deUint8* indices = new deUint8[m_spec.indexCount * typeSize];
    280 
    281 	for (int i = 0; i < m_spec.indexCount; i++)
    282 	{
    283 		deUint8* pos = indices + typeSize * i;
    284 
    285 		switch (m_spec.indexType)
    286 		{
    287 			case GL_UNSIGNED_INT:
    288 			{
    289 				GLuint v = (GLuint)m_random.getInt(m_spec.indexRangeMin, m_spec.indexRangeMax);
    290 				deMemcpy(pos, &v, sizeof(v));
    291 				break;
    292 			}
    293 
    294 			case GL_UNSIGNED_SHORT:
    295 			{
    296 				GLushort v = (GLushort)m_random.getInt(m_spec.indexRangeMin, m_spec.indexRangeMax);
    297 				deMemcpy(pos, &v, sizeof(v));
    298 				break;
    299 			}
    300 
    301 			case GL_UNSIGNED_BYTE:
    302 			{
    303 				GLubyte v = (GLubyte)m_random.getInt(m_spec.indexRangeMin, m_spec.indexRangeMax);
    304 				deMemcpy(pos, &v, sizeof(v));
    305 				break;
    306 			}
    307 
    308 			default:
    309 				DE_ASSERT(false);
    310 		}
    311 	}
    312 
    313 	return indices;
    314 }
    315 
    316 deUint8* VertexArrayObjectTest::createRandomBufferData (const BufferSpec& buffer)
    317 {
    318 	deUint8* data = new deUint8[buffer.size];
    319 
    320 	int stride;
    321 
    322 	if (buffer.stride != 0)
    323 	{
    324 		stride = buffer.stride;
    325 	}
    326 	else
    327 	{
    328 		switch (buffer.type)
    329 		{
    330 			case GL_FLOAT:			stride = buffer.componentCount * (int)sizeof(GLfloat);	break;
    331 			case GL_INT:			stride = buffer.componentCount * (int)sizeof(GLint);	break;
    332 			case GL_UNSIGNED_INT:	stride = buffer.componentCount * (int)sizeof(GLuint);	break;
    333 			case GL_SHORT:			stride = buffer.componentCount * (int)sizeof(GLshort);	break;
    334 			case GL_UNSIGNED_SHORT:	stride = buffer.componentCount * (int)sizeof(GLushort);	break;
    335 			case GL_BYTE:			stride = buffer.componentCount * (int)sizeof(GLbyte);	break;
    336 			case GL_UNSIGNED_BYTE:	stride = buffer.componentCount * (int)sizeof(GLubyte);	break;
    337 
    338 			default:
    339 				stride = 0;
    340 				DE_ASSERT(DE_FALSE);
    341 		}
    342 	}
    343 
    344 	deUint8* itr = data;
    345 
    346 	for (int pos = 0; pos < buffer.count; pos++)
    347 	{
    348 		deUint8* componentItr = itr;
    349 		for (int componentNdx = 0; componentNdx < buffer.componentCount; componentNdx++)
    350 		{
    351 			switch (buffer.type)
    352 			{
    353 				case GL_FLOAT:
    354 				{
    355 					float v = buffer.floatRangeMin + (buffer.floatRangeMax - buffer.floatRangeMin) * m_random.getFloat();
    356 					deMemcpy(componentItr, &v, sizeof(v));
    357 					componentItr += sizeof(v);
    358 					break;
    359 				}
    360 
    361 				case GL_INT:
    362 				{
    363 					GLint v = m_random.getInt(buffer.intRangeMin, buffer.intRangeMax);
    364 					deMemcpy(componentItr, &v, sizeof(v));
    365 					componentItr += sizeof(v);
    366 					break;
    367 				}
    368 
    369 				case GL_UNSIGNED_INT:
    370 				{
    371 					GLuint v = m_random.getInt(buffer.intRangeMin, buffer.intRangeMax);
    372 					deMemcpy(componentItr, &v, sizeof(v));
    373 					componentItr += sizeof(v);
    374 					break;
    375 				}
    376 
    377 				case GL_SHORT:
    378 				{
    379 					GLshort v = (GLshort)m_random.getInt(buffer.intRangeMin, buffer.intRangeMax);
    380 					deMemcpy(componentItr, &v, sizeof(v));
    381 					componentItr += sizeof(v);
    382 					break;
    383 				}
    384 
    385 				case GL_UNSIGNED_SHORT:
    386 				{
    387 					GLushort v = (GLushort)m_random.getInt(buffer.intRangeMin, buffer.intRangeMax);
    388 					deMemcpy(componentItr, &v, sizeof(v));
    389 					componentItr += sizeof(v);
    390 					break;
    391 				}
    392 
    393 				case GL_BYTE:
    394 				{
    395 					GLbyte v = (GLbyte)m_random.getInt(buffer.intRangeMin, buffer.intRangeMax);
    396 					deMemcpy(componentItr, &v, sizeof(v));
    397 					componentItr += sizeof(v);
    398 					break;
    399 				}
    400 
    401 				case GL_UNSIGNED_BYTE:
    402 				{
    403 					GLubyte v = (GLubyte)m_random.getInt(buffer.intRangeMin, buffer.intRangeMax);
    404 					deMemcpy(componentItr, &v, sizeof(v));
    405 					componentItr += sizeof(v);
    406 					break;
    407 				}
    408 
    409 				default:
    410 					DE_ASSERT(false);
    411 			};
    412 		}
    413 
    414 		itr += stride;
    415 	}
    416 
    417 	return data;
    418 }
    419 
    420 glu::ShaderProgram* VertexArrayObjectTest::createProgram (const VertexArrayState& state)
    421 {
    422 	std::stringstream vertexShaderStream;
    423 	std::stringstream value;
    424 
    425 	vertexShaderStream << "#version 300 es\n";
    426 
    427 	for (int attribNdx = 0; attribNdx < (int)state.attributes.size(); attribNdx++)
    428 	{
    429 		if (state.attributes[attribNdx].integer)
    430 			vertexShaderStream << "layout(location = " << attribNdx << ") in mediump ivec4 a_attrib" << attribNdx << ";\n";
    431 		else
    432 			vertexShaderStream << "layout(location = " << attribNdx << ") in mediump vec4 a_attrib" << attribNdx << ";\n";
    433 
    434 		if (state.attributes[attribNdx].integer)
    435 		{
    436 			float scale = 0.0f;
    437 
    438 			switch (state.attributes[0].type)
    439 			{
    440 				case GL_SHORT:			scale  = (1.0f/float((1u<<14)-1u));	break;
    441 				case GL_UNSIGNED_SHORT:	scale  = (1.0f/float((1u<<15)-1u));	break;
    442 				case GL_INT:			scale  = (1.0f/float((1u<<30)-1u));	break;
    443 				case GL_UNSIGNED_INT:	scale  = (1.0f/float((1u<<31)-1u));	break;
    444 				case GL_BYTE:			scale  = (1.0f/float((1u<<6)-1u));	break;
    445 				case GL_UNSIGNED_BYTE:	scale  = (1.0f/float((1u<<7)-1u));	break;
    446 
    447 				default:
    448 					DE_ASSERT(DE_FALSE);
    449 			}
    450 			value << (attribNdx != 0 ? " + " : "" ) << scale << " * vec4(a_attrib" << attribNdx << ")";
    451 		}
    452 		else if (state.attributes[attribNdx].type != GL_FLOAT && !state.attributes[attribNdx].normalized)
    453 		{
    454 			float scale = 0.0f;
    455 
    456 			switch (state.attributes[0].type)
    457 			{
    458 				case GL_SHORT:			scale  = (0.5f/float((1u<<14)-1u));	break;
    459 				case GL_UNSIGNED_SHORT:	scale  = (0.5f/float((1u<<15)-1u));	break;
    460 				case GL_INT:			scale  = (0.5f/float((1u<<30)-1u));	break;
    461 				case GL_UNSIGNED_INT:	scale  = (0.5f/float((1u<<31)-1u));	break;
    462 				case GL_BYTE:			scale  = (0.5f/float((1u<<6)-1u));	break;
    463 				case GL_UNSIGNED_BYTE:	scale  = (0.5f/float((1u<<7)-1u));	break;
    464 
    465 				default:
    466 					DE_ASSERT(DE_FALSE);
    467 			}
    468 			value << (attribNdx != 0 ? " + " : "" ) << scale << " * a_attrib" << attribNdx;
    469 		}
    470 		else
    471 			value << (attribNdx != 0 ? " + " : "" ) << "a_attrib" << attribNdx;
    472 	}
    473 
    474 	vertexShaderStream
    475 		<< "out mediump vec4 v_value;\n"
    476 		<< "void main (void)\n"
    477 		<< "{\n"
    478 		<< "\tv_value = " << value.str() << ";\n";
    479 
    480 	if (state.attributes[0].integer)
    481 	{
    482 		float scale = 0.0f;
    483 
    484 		switch (state.attributes[0].type)
    485 		{
    486 			case GL_SHORT:			scale  = (1.0f/float((1u<<14)-1u));	break;
    487 			case GL_UNSIGNED_SHORT:	scale  = (1.0f/float((1u<<15)-1u));	break;
    488 			case GL_INT:			scale  = (1.0f/float((1u<<30)-1u));	break;
    489 			case GL_UNSIGNED_INT:	scale  = (1.0f/float((1u<<31)-1u));	break;
    490 			case GL_BYTE:			scale  = (1.0f/float((1u<<6)-1u));	break;
    491 			case GL_UNSIGNED_BYTE:	scale  = (1.0f/float((1u<<7)-1u));	break;
    492 
    493 			default:
    494 				DE_ASSERT(DE_FALSE);
    495 		}
    496 
    497 		vertexShaderStream
    498 			<< "\tgl_Position = vec4(" << scale << " * " <<  "vec3(a_attrib0.xyz), 1.0);\n"
    499 			<< "}";
    500 	}
    501 	else
    502 	{
    503 		if (state.attributes[0].normalized || state.attributes[0].type == GL_FLOAT)
    504 		{
    505 			vertexShaderStream
    506 				<< "\tgl_Position = vec4(a_attrib0.xyz, 1.0);\n"
    507 				<< "}";
    508 		}
    509 		else
    510 		{
    511 			float scale = 0.0f;
    512 
    513 			switch (state.attributes[0].type)
    514 			{
    515 				case GL_SHORT:			scale  = (1.0f/float((1u<<14)-1u));	break;
    516 				case GL_UNSIGNED_SHORT:	scale  = (1.0f/float((1u<<15)-1u));	break;
    517 				case GL_INT:			scale  = (1.0f/float((1u<<30)-1u));	break;
    518 				case GL_UNSIGNED_INT:	scale  = (1.0f/float((1u<<31)-1u));	break;
    519 				case GL_BYTE:			scale  = (1.0f/float((1u<<6)-1u));	break;
    520 				case GL_UNSIGNED_BYTE:	scale  = (1.0f/float((1u<<7)-1u));	break;
    521 
    522 				default:
    523 					DE_ASSERT(DE_FALSE);
    524 			}
    525 
    526 			scale *= 0.5f;
    527 
    528 			vertexShaderStream
    529 				<< "\tgl_Position = vec4(" << scale << " * " <<  "a_attrib0.xyz, 1.0);\n"
    530 				<< "}";
    531 		}
    532 	}
    533 
    534 	const char* fragmentShader =
    535 	"#version 300 es\n"
    536 	"in mediump vec4 v_value;\n"
    537 	"layout(location = 0) out mediump vec4 fragColor;\n"
    538 	"void main (void)\n"
    539 	"{\n"
    540 	"\tfragColor = vec4(v_value.xyz, 1.0);\n"
    541 	"}";
    542 
    543 	return new glu::ShaderProgram(m_context.getRenderContext(), glu::makeVtxFragSources(vertexShaderStream.str(), fragmentShader));
    544 }
    545 
    546 void VertexArrayObjectTest::setState (const VertexArrayState& state)
    547 {
    548 	GLU_CHECK_CALL(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_buffers[state.elementArrayBuffer]));
    549 
    550 	for (int attribNdx = 0; attribNdx < (int)state.attributes.size(); attribNdx++)
    551 	{
    552 		GLU_CHECK_CALL(glBindBuffer(GL_ARRAY_BUFFER, m_buffers[state.attributes[attribNdx].bufferNdx]));
    553 		if (state.attributes[attribNdx].enabled)
    554 			GLU_CHECK_CALL(glEnableVertexAttribArray(attribNdx));
    555 		else
    556 			GLU_CHECK_CALL(glDisableVertexAttribArray(attribNdx));
    557 
    558 		if (state.attributes[attribNdx].integer)
    559 			GLU_CHECK_CALL(glVertexAttribIPointer(attribNdx, state.attributes[attribNdx].size, state.attributes[attribNdx].type, state.attributes[attribNdx].stride, (const GLvoid*)((GLintptr)state.attributes[attribNdx].offset)));
    560 		else
    561 			GLU_CHECK_CALL(glVertexAttribPointer(attribNdx, state.attributes[attribNdx].size, state.attributes[attribNdx].type, state.attributes[attribNdx].normalized, state.attributes[attribNdx].stride, (const GLvoid*)((GLintptr)state.attributes[attribNdx].offset)));
    562 
    563 		GLU_CHECK_CALL(glVertexAttribDivisor(attribNdx, state.attributes[attribNdx].divisor));
    564 	}
    565 }
    566 
    567 void VertexArrayObjectTest::makeDrawCall (const VertexArrayState& state)
    568 {
    569 	GLU_CHECK_CALL(glClearColor(0.7f, 0.7f, 0.7f, 1.0f));
    570 	GLU_CHECK_CALL(glClear(GL_COLOR_BUFFER_BIT));
    571 
    572 	if (m_spec.useDrawElements)
    573 	{
    574 		if (state.elementArrayBuffer == 0)
    575 		{
    576 			if (m_spec.instances == 0)
    577 				GLU_CHECK_CALL(glDrawElements(GL_TRIANGLES, m_spec.count, m_spec.indexType, m_indices));
    578 			else
    579 				GLU_CHECK_CALL(glDrawElementsInstanced(GL_TRIANGLES, m_spec.count, m_spec.indexType, m_indices, m_spec.instances));
    580 		}
    581 		else
    582 		{
    583 			if (m_spec.instances == 0)
    584 				GLU_CHECK_CALL(glDrawElements(GL_TRIANGLES, m_spec.count, m_spec.indexType, (GLvoid*)((GLintptr)m_spec.indexOffset)));
    585 			else
    586 				GLU_CHECK_CALL(glDrawElementsInstanced(GL_TRIANGLES, m_spec.count, m_spec.indexType, (GLvoid*)((GLintptr)m_spec.indexOffset), m_spec.instances));
    587 		}
    588 	}
    589 	else
    590 	{
    591 		if (m_spec.instances == 0)
    592 			GLU_CHECK_CALL(glDrawArrays(GL_TRIANGLES, 0, m_spec.count));
    593 		else
    594 			GLU_CHECK_CALL(glDrawArraysInstanced(GL_TRIANGLES, 0, m_spec.count, m_spec.instances));
    595 	}
    596 }
    597 
    598 void VertexArrayObjectTest::render (tcu::Surface& vaoResult, tcu::Surface& defaultResult)
    599 {
    600 	GLuint vao = 0;
    601 
    602 	GLU_CHECK_CALL(glGenVertexArrays(1, &vao));
    603 	GLU_CHECK_CALL(glBindVertexArray(vao));
    604 	setState(m_spec.vao);
    605 	GLU_CHECK_CALL(glBindVertexArray(0));
    606 
    607 	setState(m_spec.state);
    608 
    609 	GLU_CHECK_CALL(glBindVertexArray(vao));
    610 	GLU_CHECK_CALL(glUseProgram(m_vaoProgram->getProgram()));
    611 	makeDrawCall(m_spec.vao);
    612 	glu::readPixels(m_context.getRenderContext(), 0, 0, vaoResult.getAccess());
    613 	setState(m_spec.vao);
    614 	GLU_CHECK_CALL(glBindVertexArray(0));
    615 
    616 	GLU_CHECK_CALL(glUseProgram(m_stateProgram->getProgram()));
    617 	makeDrawCall(m_spec.state);
    618 	glu::readPixels(m_context.getRenderContext(), 0, 0, defaultResult.getAccess());
    619 }
    620 
    621 void VertexArrayObjectTest::genReferences (tcu::Surface& vaoRef, tcu::Surface& defaultRef)
    622 {
    623 	setState(m_spec.vao);
    624 	GLU_CHECK_CALL(glUseProgram(m_vaoProgram->getProgram()));
    625 	makeDrawCall(m_spec.vao);
    626 	glu::readPixels(m_context.getRenderContext(), 0, 0, vaoRef.getAccess());
    627 
    628 	setState(m_spec.state);
    629 	GLU_CHECK_CALL(glUseProgram(m_stateProgram->getProgram()));
    630 	makeDrawCall(m_spec.state);
    631 	glu::readPixels(m_context.getRenderContext(), 0, 0, defaultRef.getAccess());
    632 }
    633 
    634 TestCase::IterateResult VertexArrayObjectTest::iterate (void)
    635 {
    636 	tcu::Surface	vaoReference	(m_context.getRenderContext().getRenderTarget().getWidth(), m_context.getRenderContext().getRenderTarget().getHeight());
    637 	tcu::Surface	stateReference	(m_context.getRenderContext().getRenderTarget().getWidth(), m_context.getRenderContext().getRenderTarget().getHeight());
    638 
    639 	tcu::Surface	vaoResult		(m_context.getRenderContext().getRenderTarget().getWidth(), m_context.getRenderContext().getRenderTarget().getHeight());
    640 	tcu::Surface	stateResult		(m_context.getRenderContext().getRenderTarget().getWidth(), m_context.getRenderContext().getRenderTarget().getHeight());
    641 
    642 	bool			isOk;
    643 
    644 	logVertexArrayState(m_log, m_spec.vao, "Vertex Array Object State");
    645 	logVertexArrayState(m_log, m_spec.state, "OpenGL Vertex Array State");
    646 	genReferences(stateReference, vaoReference);
    647 	render(stateResult, vaoResult);
    648 
    649 	isOk = tcu::pixelThresholdCompare (m_log, "Results", "Comparison result from rendering with Vertex Array State", stateReference, stateResult, tcu::RGBA(0,0,0,0), tcu::COMPARE_LOG_RESULT);
    650 	isOk = isOk && tcu::pixelThresholdCompare (m_log, "Results", "Comparison result from rendering with Vertex Array Object", vaoReference, vaoResult, tcu::RGBA(0,0,0,0), tcu::COMPARE_LOG_RESULT);
    651 
    652 	if (isOk)
    653 	{
    654 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
    655 		return STOP;
    656 	}
    657 	else
    658 	{
    659 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
    660 		return STOP;
    661 	}
    662 }
    663 
    664 class MultiVertexArrayObjectTest : public TestCase
    665 {
    666 public:
    667 
    668 							MultiVertexArrayObjectTest	(Context& context, const char* name, const char* description);
    669 							~MultiVertexArrayObjectTest	(void);
    670 	virtual void			init						(void);
    671 	virtual void			deinit						(void);
    672 	virtual IterateResult	iterate						(void);
    673 
    674 private:
    675 	Spec					m_spec;
    676 	tcu::TestLog&			m_log;
    677 	vector<GLuint>			m_buffers;
    678 	glu::ShaderProgram*		m_vaoProgram;
    679 	glu::ShaderProgram*		m_stateProgram;
    680 	de::Random				m_random;
    681 	deUint8*				m_indices;
    682 
    683 	void					logVertexArrayState			(tcu::TestLog& log, const VertexArrayState& state, const std::string& msg);
    684 	deUint8*				createRandomBufferData		(const BufferSpec& buffer);
    685 	deUint8*				generateIndices				(void);
    686 	glu::ShaderProgram*		createProgram				(const VertexArrayState& state);
    687 	void					setState					(const VertexArrayState& state);
    688 	void					render						(tcu::Surface& vaoResult, tcu::Surface& defaultResult);
    689 	void					makeDrawCall				(const VertexArrayState& state);
    690 	void					genReferences				(tcu::Surface& vaoRef, tcu::Surface& defaultRef);
    691 
    692 							MultiVertexArrayObjectTest	(const MultiVertexArrayObjectTest&);
    693 	MultiVertexArrayObjectTest&	operator=				(const MultiVertexArrayObjectTest&);
    694 };
    695 
    696 MultiVertexArrayObjectTest::MultiVertexArrayObjectTest (Context& context, const char* name, const char* description)
    697 	: TestCase			(context, name, description)
    698 	, m_log				(context.getTestContext().getLog())
    699 	, m_vaoProgram		(NULL)
    700 	, m_stateProgram	(NULL)
    701 	, m_random			(deStringHash(name))
    702 	, m_indices			(NULL)
    703 {
    704 	// Makes zero to zero mapping for buffers
    705 	m_buffers.push_back(0);
    706 }
    707 
    708 MultiVertexArrayObjectTest::~MultiVertexArrayObjectTest (void)
    709 {
    710 }
    711 
    712 void MultiVertexArrayObjectTest::logVertexArrayState (tcu::TestLog& log, const VertexArrayState& state, const std::string& msg)
    713 {
    714 	std::stringstream message;
    715 
    716 	message << msg << "\n";
    717 	message << "GL_ELEMENT_ARRAY_BUFFER : " << state.elementArrayBuffer << "\n";
    718 
    719 	for (int attribNdx = 0; attribNdx < (int)state.attributes.size(); attribNdx++)
    720 	{
    721 		message
    722 		<< "attribute : " << attribNdx << "\n"
    723 		<< "\tGL_VERTEX_ATTRIB_ARRAY_ENABLED : " << (state.attributes[attribNdx].enabled ? "GL_TRUE" : "GL_FALSE") <<  "\n"
    724 		<< "\tGL_VERTEX_ATTRIB_ARRAY_SIZE : " << state.attributes[attribNdx].size <<  "\n"
    725 		<< "\tGL_VERTEX_ATTRIB_ARRAY_STRIDE : " << state.attributes[attribNdx].stride <<  "\n"
    726 		<< "\tGL_VERTEX_ATTRIB_ARRAY_TYPE : " << state.attributes[attribNdx].type <<  "\n"
    727 		<< "\tGL_VERTEX_ATTRIB_ARRAY_NORMALIZED : " << (state.attributes[attribNdx].normalized ? "GL_TRUE" : "GL_FALSE") <<  "\n"
    728 		<< "\tGL_VERTEX_ATTRIB_ARRAY_INTEGER : " << (state.attributes[attribNdx].integer ? "GL_TRUE" : "GL_FALSE") <<  "\n"
    729 		<< "\tGL_VERTEX_ATTRIB_ARRAY_DIVISOR : " << state.attributes[attribNdx].divisor <<  "\n"
    730 		<< "\tGL_VERTEX_ATTRIB_ARRAY_POINTER : " << state.attributes[attribNdx].offset <<  "\n"
    731 		<< "\t GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING : " << m_buffers[state.attributes[attribNdx].bufferNdx] <<  "\n";
    732 	}
    733 	log << tcu::TestLog::Message << message.str() << tcu::TestLog::EndMessage;
    734 }
    735 
    736 
    737 void MultiVertexArrayObjectTest::init (void)
    738 {
    739 	GLint attribCount;
    740 
    741 	GLU_CHECK_CALL(glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &attribCount));
    742 
    743 	m_spec.useDrawElements			= false;
    744 	m_spec.instances				= 0;
    745 	m_spec.count					= 24;
    746 	m_spec.indexOffset				= 0;
    747 	m_spec.indexRangeMin			= 0;
    748 	m_spec.indexRangeMax			= 0;
    749 	m_spec.indexType				= GL_NONE;
    750 	m_spec.indexCount				= 0;
    751 	m_spec.vao.elementArrayBuffer	= 0;
    752 	m_spec.state.elementArrayBuffer	= 0;
    753 
    754 	for (int attribNdx = 0; attribNdx < attribCount; attribNdx++)
    755 	{
    756 		BufferSpec shortCoordBuffer48 = { 48, 2*384, 4, 0, 0, GL_SHORT, -32768, 32768, 0.0f, 0.0f };
    757 		m_spec.buffers.push_back(shortCoordBuffer48);
    758 
    759 		m_spec.state.attributes.push_back(Attribute());
    760 		m_spec.state.attributes[attribNdx].enabled		= (m_random.getInt(0, 4) == 0) ? GL_FALSE : GL_TRUE;
    761 		m_spec.state.attributes[attribNdx].size			= m_random.getInt(2,4);
    762 		m_spec.state.attributes[attribNdx].stride		= 2*m_random.getInt(1, 3);
    763 		m_spec.state.attributes[attribNdx].type			= GL_SHORT;
    764 		m_spec.state.attributes[attribNdx].integer		= m_random.getBool();
    765 		m_spec.state.attributes[attribNdx].divisor		= m_random.getInt(0, 1);
    766 		m_spec.state.attributes[attribNdx].offset		= 2*m_random.getInt(0, 2);
    767 		m_spec.state.attributes[attribNdx].normalized	= m_random.getBool();
    768 		m_spec.state.attributes[attribNdx].bufferNdx	= attribNdx+1;
    769 
    770 		if (attribNdx == 0)
    771 		{
    772 			m_spec.state.attributes[attribNdx].divisor	= 0;
    773 			m_spec.state.attributes[attribNdx].enabled	= GL_TRUE;
    774 			m_spec.state.attributes[attribNdx].size		= 2;
    775 		}
    776 
    777 		m_spec.vao.attributes.push_back(Attribute());
    778 		m_spec.vao.attributes[attribNdx].enabled		= (m_random.getInt(0, 4) == 0) ? GL_FALSE : GL_TRUE;
    779 		m_spec.vao.attributes[attribNdx].size			= m_random.getInt(2,4);
    780 		m_spec.vao.attributes[attribNdx].stride			= 2*m_random.getInt(1, 3);
    781 		m_spec.vao.attributes[attribNdx].type			= GL_SHORT;
    782 		m_spec.vao.attributes[attribNdx].integer		= m_random.getBool();
    783 		m_spec.vao.attributes[attribNdx].divisor		= m_random.getInt(0, 1);
    784 		m_spec.vao.attributes[attribNdx].offset			= 2*m_random.getInt(0, 2);
    785 		m_spec.vao.attributes[attribNdx].normalized		= m_random.getBool();
    786 		m_spec.vao.attributes[attribNdx].bufferNdx		= attribCount - attribNdx;
    787 
    788 		if (attribNdx == 0)
    789 		{
    790 			m_spec.vao.attributes[attribNdx].divisor	= 0;
    791 			m_spec.vao.attributes[attribNdx].enabled	= GL_TRUE;
    792 			m_spec.vao.attributes[attribNdx].size		= 2;
    793 		}
    794 
    795 	}
    796 
    797 	// \note [mika] Index 0 is reserved for 0 buffer
    798 	for (int bufferNdx = 0; bufferNdx < (int)m_spec.buffers.size(); bufferNdx++)
    799 	{
    800 		deUint8* data = createRandomBufferData(m_spec.buffers[bufferNdx]);
    801 
    802 		try
    803 		{
    804 			GLuint buffer;
    805 			GLU_CHECK_CALL(glGenBuffers(1, &buffer));
    806 			m_buffers.push_back(buffer);
    807 
    808 			GLU_CHECK_CALL(glBindBuffer(GL_ARRAY_BUFFER, buffer));
    809 			GLU_CHECK_CALL(glBufferData(GL_ARRAY_BUFFER, m_spec.buffers[bufferNdx].size, data, GL_DYNAMIC_DRAW));
    810 			GLU_CHECK_CALL(glBindBuffer(GL_ARRAY_BUFFER, 0));
    811 
    812 		} catch (...) {
    813 			delete[] data;
    814 			throw;
    815 		}
    816 
    817 		delete[] data;
    818 	}
    819 
    820 	m_vaoProgram	= createProgram(m_spec.vao);
    821 	m_log << tcu::TestLog::Message << "Program used with Vertex Array Object" << tcu::TestLog::EndMessage;
    822 	m_log << *m_vaoProgram;
    823 	m_stateProgram	= createProgram(m_spec.state);
    824 	m_log << tcu::TestLog::Message << "Program used with Vertex Array State" << tcu::TestLog::EndMessage;
    825 	m_log << *m_stateProgram;
    826 
    827 	if (!m_vaoProgram->isOk() || !m_stateProgram->isOk())
    828 		TCU_FAIL("Failed to compile shaders");
    829 
    830 	if (m_spec.useDrawElements && (m_spec.vao.elementArrayBuffer == 0 || m_spec.state.elementArrayBuffer == 0))
    831 		m_indices = generateIndices();
    832 }
    833 
    834 void MultiVertexArrayObjectTest::deinit (void)
    835 {
    836 	GLU_CHECK_CALL(glDeleteBuffers((GLsizei)m_buffers.size(), &(m_buffers[0])));
    837 	m_buffers.clear();
    838 	delete m_vaoProgram;
    839 	delete m_stateProgram;
    840 	delete[] m_indices;
    841 }
    842 
    843 deUint8* MultiVertexArrayObjectTest::generateIndices (void)
    844 {
    845 	int typeSize = 0;
    846 	switch (m_spec.indexType)
    847 	{
    848 		case GL_UNSIGNED_INT:	typeSize = sizeof(GLuint);		break;
    849 		case GL_UNSIGNED_SHORT:	typeSize = sizeof(GLushort);	break;
    850 		case GL_UNSIGNED_BYTE:	typeSize = sizeof(GLubyte);		break;
    851 		default:
    852 			DE_ASSERT(false);
    853 	}
    854 
    855 	deUint8* indices = new deUint8[m_spec.indexCount * typeSize];
    856 
    857 	for (int i = 0; i < m_spec.indexCount; i++)
    858 	{
    859 		deUint8* pos = indices + typeSize * i;
    860 
    861 		switch (m_spec.indexType)
    862 		{
    863 			case GL_UNSIGNED_INT:
    864 			{
    865 				GLuint v = (GLuint)m_random.getInt(m_spec.indexRangeMin, m_spec.indexRangeMax);
    866 				deMemcpy(pos, &v, sizeof(v));
    867 				break;
    868 			}
    869 
    870 			case GL_UNSIGNED_SHORT:
    871 			{
    872 				GLushort v = (GLushort)m_random.getInt(m_spec.indexRangeMin, m_spec.indexRangeMax);
    873 				deMemcpy(pos, &v, sizeof(v));
    874 				break;
    875 			}
    876 
    877 			case GL_UNSIGNED_BYTE:
    878 			{
    879 				GLubyte v = (GLubyte)m_random.getInt(m_spec.indexRangeMin, m_spec.indexRangeMax);
    880 				deMemcpy(pos, &v, sizeof(v));
    881 				break;
    882 			}
    883 
    884 			default:
    885 				DE_ASSERT(false);
    886 		}
    887 	}
    888 
    889 	return indices;
    890 }
    891 
    892 deUint8* MultiVertexArrayObjectTest::createRandomBufferData (const BufferSpec& buffer)
    893 {
    894 	deUint8* data = new deUint8[buffer.size];
    895 
    896 	int stride;
    897 
    898 	if (buffer.stride != 0)
    899 	{
    900 		stride = buffer.stride;
    901 	}
    902 	else
    903 	{
    904 		switch (buffer.type)
    905 		{
    906 			case GL_FLOAT:			stride = buffer.componentCount * (int)sizeof(GLfloat);	break;
    907 			case GL_INT:			stride = buffer.componentCount * (int)sizeof(GLint);	break;
    908 			case GL_UNSIGNED_INT:	stride = buffer.componentCount * (int)sizeof(GLuint);	break;
    909 			case GL_SHORT:			stride = buffer.componentCount * (int)sizeof(GLshort);	break;
    910 			case GL_UNSIGNED_SHORT:	stride = buffer.componentCount * (int)sizeof(GLushort);	break;
    911 			case GL_BYTE:			stride = buffer.componentCount * (int)sizeof(GLbyte);	break;
    912 			case GL_UNSIGNED_BYTE:	stride = buffer.componentCount * (int)sizeof(GLubyte);	break;
    913 
    914 			default:
    915 				stride = 0;
    916 				DE_ASSERT(DE_FALSE);
    917 		}
    918 	}
    919 
    920 	deUint8* itr = data;
    921 
    922 	for (int pos = 0; pos < buffer.count; pos++)
    923 	{
    924 		deUint8* componentItr = itr;
    925 		for (int componentNdx = 0; componentNdx < buffer.componentCount; componentNdx++)
    926 		{
    927 			switch (buffer.type)
    928 			{
    929 				case GL_FLOAT:
    930 				{
    931 					float v = buffer.floatRangeMin + (buffer.floatRangeMax - buffer.floatRangeMin) * m_random.getFloat();
    932 					deMemcpy(componentItr, &v, sizeof(v));
    933 					componentItr += sizeof(v);
    934 					break;
    935 				}
    936 
    937 				case GL_INT:
    938 				{
    939 					GLint v = m_random.getInt(buffer.intRangeMin, buffer.intRangeMax);
    940 					deMemcpy(componentItr, &v, sizeof(v));
    941 					componentItr += sizeof(v);
    942 					break;
    943 				}
    944 
    945 				case GL_UNSIGNED_INT:
    946 				{
    947 					GLuint v = (GLuint)m_random.getInt(buffer.intRangeMin, buffer.intRangeMax);
    948 					deMemcpy(componentItr, &v, sizeof(v));
    949 					componentItr += sizeof(v);
    950 					break;
    951 				}
    952 
    953 				case GL_SHORT:
    954 				{
    955 					GLshort v = (GLshort)m_random.getInt(buffer.intRangeMin, buffer.intRangeMax);
    956 					deMemcpy(componentItr, &v, sizeof(v));
    957 					componentItr += sizeof(v);
    958 					break;
    959 				}
    960 
    961 				case GL_UNSIGNED_SHORT:
    962 				{
    963 					GLushort v = (GLushort)m_random.getInt(buffer.intRangeMin, buffer.intRangeMax);
    964 					deMemcpy(componentItr, &v, sizeof(v));
    965 					componentItr += sizeof(v);
    966 					break;
    967 				}
    968 
    969 				case GL_BYTE:
    970 				{
    971 					GLbyte v = (GLbyte)m_random.getInt(buffer.intRangeMin, buffer.intRangeMax);
    972 					deMemcpy(componentItr, &v, sizeof(v));
    973 					componentItr += sizeof(v);
    974 					break;
    975 				}
    976 
    977 				case GL_UNSIGNED_BYTE:
    978 				{
    979 					GLubyte v = (GLubyte)m_random.getInt(buffer.intRangeMin, buffer.intRangeMax);
    980 					deMemcpy(componentItr, &v, sizeof(v));
    981 					componentItr += sizeof(v);
    982 					break;
    983 				}
    984 
    985 				default:
    986 					DE_ASSERT(false);
    987 			};
    988 		}
    989 
    990 		itr += stride;
    991 	}
    992 
    993 	return data;
    994 }
    995 
    996 glu::ShaderProgram* MultiVertexArrayObjectTest::createProgram (const VertexArrayState& state)
    997 {
    998 	std::stringstream vertexShaderStream;
    999 	std::stringstream value;
   1000 
   1001 	vertexShaderStream << "#version 300 es\n";
   1002 
   1003 	for (int attribNdx = 0; attribNdx < (int)state.attributes.size(); attribNdx++)
   1004 	{
   1005 		if (state.attributes[attribNdx].integer)
   1006 			vertexShaderStream << "layout(location = " << attribNdx << ") in mediump ivec4 a_attrib" << attribNdx << ";\n";
   1007 		else
   1008 			vertexShaderStream << "layout(location = " << attribNdx << ") in mediump vec4 a_attrib" << attribNdx << ";\n";
   1009 
   1010 		if (state.attributes[attribNdx].integer)
   1011 		{
   1012 			float scale = 0.0f;
   1013 
   1014 			switch (state.attributes[0].type)
   1015 			{
   1016 				case GL_SHORT:			scale  = (1.0f/float((1u<<14)-1u));	break;
   1017 				case GL_UNSIGNED_SHORT:	scale  = (1.0f/float((1u<<15)-1u));	break;
   1018 				case GL_INT:			scale  = (1.0f/float((1u<<30)-1u));	break;
   1019 				case GL_UNSIGNED_INT:	scale  = (1.0f/float((1u<<31)-1u));	break;
   1020 				case GL_BYTE:			scale  = (1.0f/float((1u<<6)-1u));	break;
   1021 				case GL_UNSIGNED_BYTE:	scale  = (1.0f/float((1u<<7)-1u));	break;
   1022 
   1023 				default:
   1024 					DE_ASSERT(DE_FALSE);
   1025 			}
   1026 			value << (attribNdx != 0 ? " + " : "" ) << scale << " * vec4(a_attrib" << attribNdx << ")";
   1027 		}
   1028 		else if (state.attributes[attribNdx].type != GL_FLOAT && !state.attributes[attribNdx].normalized)
   1029 		{
   1030 			float scale = 0.0f;
   1031 
   1032 			switch (state.attributes[0].type)
   1033 			{
   1034 				case GL_SHORT:			scale  = (0.5f/float((1u<<14)-1u));	break;
   1035 				case GL_UNSIGNED_SHORT:	scale  = (0.5f/float((1u<<15)-1u));	break;
   1036 				case GL_INT:			scale  = (0.5f/float((1u<<30)-1u));	break;
   1037 				case GL_UNSIGNED_INT:	scale  = (0.5f/float((1u<<31)-1u));	break;
   1038 				case GL_BYTE:			scale  = (0.5f/float((1u<<6)-1u));	break;
   1039 				case GL_UNSIGNED_BYTE:	scale  = (0.5f/float((1u<<7)-1u));	break;
   1040 
   1041 				default:
   1042 					DE_ASSERT(DE_FALSE);
   1043 			}
   1044 			value << (attribNdx != 0 ? " + " : "" ) << scale << " * a_attrib" << attribNdx;
   1045 		}
   1046 		else
   1047 			value << (attribNdx != 0 ? " + " : "" ) << "a_attrib" << attribNdx;
   1048 	}
   1049 
   1050 	vertexShaderStream
   1051 		<< "out mediump vec4 v_value;\n"
   1052 		<< "void main (void)\n"
   1053 		<< "{\n"
   1054 		<< "\tv_value = " << value.str() << ";\n";
   1055 
   1056 	if (state.attributes[0].integer)
   1057 	{
   1058 		float scale = 0.0f;
   1059 
   1060 		switch (state.attributes[0].type)
   1061 		{
   1062 			case GL_SHORT:			scale  = (1.0f/float((1u<<14)-1u));	break;
   1063 			case GL_UNSIGNED_SHORT:	scale  = (1.0f/float((1u<<15)-1u));	break;
   1064 			case GL_INT:			scale  = (1.0f/float((1u<<30)-1u));	break;
   1065 			case GL_UNSIGNED_INT:	scale  = (1.0f/float((1u<<31)-1u));	break;
   1066 			case GL_BYTE:			scale  = (1.0f/float((1u<<6)-1u));	break;
   1067 			case GL_UNSIGNED_BYTE:	scale  = (1.0f/float((1u<<7)-1u));	break;
   1068 
   1069 
   1070 			default:
   1071 				DE_ASSERT(DE_FALSE);
   1072 		}
   1073 
   1074 		vertexShaderStream
   1075 			<< "\tgl_Position = vec4(" << scale << " * " <<  "a_attrib0.xyz, 1.0);\n"
   1076 			<< "}";
   1077 	}
   1078 	else
   1079 	{
   1080 		if (state.attributes[0].normalized || state.attributes[0].type == GL_FLOAT)
   1081 		{
   1082 			vertexShaderStream
   1083 				<< "\tgl_Position = vec4(a_attrib0.xyz, 1.0);\n"
   1084 				<< "}";
   1085 		}
   1086 		else
   1087 		{
   1088 			float scale = 0.0f;
   1089 
   1090 			switch (state.attributes[0].type)
   1091 			{
   1092 				case GL_SHORT:			scale  = (1.0f/float((1u<<14)-1u));	break;
   1093 				case GL_UNSIGNED_SHORT:	scale  = (1.0f/float((1u<<15)-1u));	break;
   1094 				case GL_INT:			scale  = (1.0f/float((1u<<30)-1u));	break;
   1095 				case GL_UNSIGNED_INT:	scale  = (1.0f/float((1u<<31)-1u));	break;
   1096 				case GL_BYTE:			scale  = (1.0f/float((1u<<6)-1u));	break;
   1097 				case GL_UNSIGNED_BYTE:	scale  = (1.0f/float((1u<<7)-1u));	break;
   1098 
   1099 				default:
   1100 					DE_ASSERT(DE_FALSE);
   1101 			}
   1102 
   1103 			scale *= 0.5f;
   1104 
   1105 			vertexShaderStream
   1106 				<< "\tgl_Position = vec4(" << scale << " * " <<  "vec3(a_attrib0.xyz), 1.0);\n"
   1107 				<< "}";
   1108 		}
   1109 	}
   1110 
   1111 	const char* fragmentShader =
   1112 	"#version 300 es\n"
   1113 	"in mediump vec4 v_value;\n"
   1114 	"layout(location = 0) out mediump vec4 fragColor;\n"
   1115 	"void main (void)\n"
   1116 	"{\n"
   1117 	"\tfragColor = vec4(v_value.xyz, 1.0);\n"
   1118 	"}";
   1119 
   1120 	return new glu::ShaderProgram(m_context.getRenderContext(), glu::makeVtxFragSources(vertexShaderStream.str(), fragmentShader));
   1121 }
   1122 
   1123 void MultiVertexArrayObjectTest::setState (const VertexArrayState& state)
   1124 {
   1125 	GLU_CHECK_CALL(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_buffers[state.elementArrayBuffer]));
   1126 
   1127 	for (int attribNdx = 0; attribNdx < (int)state.attributes.size(); attribNdx++)
   1128 	{
   1129 		GLU_CHECK_CALL(glBindBuffer(GL_ARRAY_BUFFER, m_buffers[state.attributes[attribNdx].bufferNdx]));
   1130 		if (state.attributes[attribNdx].enabled)
   1131 			GLU_CHECK_CALL(glEnableVertexAttribArray(attribNdx));
   1132 		else
   1133 			GLU_CHECK_CALL(glDisableVertexAttribArray(attribNdx));
   1134 
   1135 		if (state.attributes[attribNdx].integer)
   1136 			GLU_CHECK_CALL(glVertexAttribIPointer(attribNdx, state.attributes[attribNdx].size, state.attributes[attribNdx].type, state.attributes[attribNdx].stride, (const GLvoid*)((GLintptr)state.attributes[attribNdx].offset)));
   1137 		else
   1138 			GLU_CHECK_CALL(glVertexAttribPointer(attribNdx, state.attributes[attribNdx].size, state.attributes[attribNdx].type, state.attributes[attribNdx].normalized, state.attributes[attribNdx].stride, (const GLvoid*)((GLintptr)state.attributes[attribNdx].offset)));
   1139 
   1140 		GLU_CHECK_CALL(glVertexAttribDivisor(attribNdx, state.attributes[attribNdx].divisor));
   1141 	}
   1142 }
   1143 
   1144 void MultiVertexArrayObjectTest::makeDrawCall (const VertexArrayState& state)
   1145 {
   1146 	GLU_CHECK_CALL(glClearColor(0.7f, 0.7f, 0.7f, 1.0f));
   1147 	GLU_CHECK_CALL(glClear(GL_COLOR_BUFFER_BIT));
   1148 
   1149 	if (m_spec.useDrawElements)
   1150 	{
   1151 		if (state.elementArrayBuffer == 0)
   1152 		{
   1153 			if (m_spec.instances == 0)
   1154 				GLU_CHECK_CALL(glDrawElements(GL_TRIANGLES, m_spec.count, m_spec.indexType, m_indices));
   1155 			else
   1156 				GLU_CHECK_CALL(glDrawElementsInstanced(GL_TRIANGLES, m_spec.count, m_spec.indexType, m_indices, m_spec.instances));
   1157 		}
   1158 		else
   1159 		{
   1160 			if (m_spec.instances == 0)
   1161 				GLU_CHECK_CALL(glDrawElements(GL_TRIANGLES, m_spec.count, m_spec.indexType, (GLvoid*)((GLintptr)m_spec.indexOffset)));
   1162 			else
   1163 				GLU_CHECK_CALL(glDrawElementsInstanced(GL_TRIANGLES, m_spec.count, m_spec.indexType, (GLvoid*)((GLintptr)m_spec.indexOffset), m_spec.instances));
   1164 		}
   1165 	}
   1166 	else
   1167 	{
   1168 		if (m_spec.instances == 0)
   1169 			GLU_CHECK_CALL(glDrawArrays(GL_TRIANGLES, 0, m_spec.count));
   1170 		else
   1171 			GLU_CHECK_CALL(glDrawArraysInstanced(GL_TRIANGLES, 0, m_spec.count, m_spec.instances));
   1172 	}
   1173 }
   1174 
   1175 void MultiVertexArrayObjectTest::render (tcu::Surface& vaoResult, tcu::Surface& defaultResult)
   1176 {
   1177 	GLuint vao = 0;
   1178 
   1179 	GLU_CHECK_CALL(glGenVertexArrays(1, &vao));
   1180 	GLU_CHECK_CALL(glBindVertexArray(vao));
   1181 	setState(m_spec.vao);
   1182 	GLU_CHECK_CALL(glBindVertexArray(0));
   1183 
   1184 	setState(m_spec.state);
   1185 
   1186 	GLU_CHECK_CALL(glBindVertexArray(vao));
   1187 	GLU_CHECK_CALL(glUseProgram(m_vaoProgram->getProgram()));
   1188 	makeDrawCall(m_spec.vao);
   1189 	glu::readPixels(m_context.getRenderContext(), 0, 0, vaoResult.getAccess());
   1190 	setState(m_spec.vao);
   1191 	GLU_CHECK_CALL(glBindVertexArray(0));
   1192 
   1193 	GLU_CHECK_CALL(glUseProgram(m_stateProgram->getProgram()));
   1194 	makeDrawCall(m_spec.state);
   1195 	glu::readPixels(m_context.getRenderContext(), 0, 0, defaultResult.getAccess());
   1196 }
   1197 
   1198 void MultiVertexArrayObjectTest::genReferences (tcu::Surface& vaoRef, tcu::Surface& defaultRef)
   1199 {
   1200 	setState(m_spec.vao);
   1201 	GLU_CHECK_CALL(glUseProgram(m_vaoProgram->getProgram()));
   1202 	makeDrawCall(m_spec.vao);
   1203 	glu::readPixels(m_context.getRenderContext(), 0, 0, vaoRef.getAccess());
   1204 
   1205 	setState(m_spec.state);
   1206 	GLU_CHECK_CALL(glUseProgram(m_stateProgram->getProgram()));
   1207 	makeDrawCall(m_spec.state);
   1208 	glu::readPixels(m_context.getRenderContext(), 0, 0, defaultRef.getAccess());
   1209 }
   1210 
   1211 TestCase::IterateResult MultiVertexArrayObjectTest::iterate (void)
   1212 {
   1213 	tcu::Surface	vaoReference	(m_context.getRenderContext().getRenderTarget().getWidth(), m_context.getRenderContext().getRenderTarget().getHeight());
   1214 	tcu::Surface	stateReference	(m_context.getRenderContext().getRenderTarget().getWidth(), m_context.getRenderContext().getRenderTarget().getHeight());
   1215 
   1216 	tcu::Surface	vaoResult		(m_context.getRenderContext().getRenderTarget().getWidth(), m_context.getRenderContext().getRenderTarget().getHeight());
   1217 	tcu::Surface	stateResult		(m_context.getRenderContext().getRenderTarget().getWidth(), m_context.getRenderContext().getRenderTarget().getHeight());
   1218 
   1219 	bool			isOk;
   1220 
   1221 	logVertexArrayState(m_log, m_spec.vao, "Vertex Array Object State");
   1222 	logVertexArrayState(m_log, m_spec.state, "OpenGL Vertex Array State");
   1223 	genReferences(stateReference, vaoReference);
   1224 	render(stateResult, vaoResult);
   1225 
   1226 	isOk = tcu::pixelThresholdCompare (m_log, "Results", "Comparison result from rendering with Vertex Array State", stateReference, stateResult, tcu::RGBA(0,0,0,0), tcu::COMPARE_LOG_RESULT);
   1227 	isOk = isOk && tcu::pixelThresholdCompare (m_log, "Results", "Comparison result from rendering with Vertex Array Object", vaoReference, vaoResult, tcu::RGBA(0,0,0,0), tcu::COMPARE_LOG_RESULT);
   1228 
   1229 	if (isOk)
   1230 	{
   1231 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
   1232 		return STOP;
   1233 	}
   1234 	else
   1235 	{
   1236 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
   1237 		return STOP;
   1238 	}
   1239 }
   1240 
   1241 VertexArrayObjectTestGroup::VertexArrayObjectTestGroup (Context& context)
   1242 	: TestCaseGroup(context, "vertex_array_objects", "Vertex array object test cases")
   1243 {
   1244 }
   1245 
   1246 VertexArrayObjectTestGroup::~VertexArrayObjectTestGroup (void)
   1247 {
   1248 }
   1249 
   1250 void VertexArrayObjectTestGroup::init (void)
   1251 {
   1252 	BufferSpec floatCoordBuffer48_1 = { 48, 384, 2, 0, 0, GL_FLOAT, 0, 0, -1.0f, 1.0f };
   1253 	BufferSpec floatCoordBuffer48_2 = { 48, 384, 2, 0, 0, GL_FLOAT, 0, 0, -1.0f, 1.0f };
   1254 
   1255 	BufferSpec shortCoordBuffer48 = { 48, 192, 2, 0, 0, GL_SHORT, -32768, 32768, 0.0f, 0.0f };
   1256 
   1257 	// Different buffer
   1258 	{
   1259 		Spec spec;
   1260 
   1261 		VertexArrayState state;
   1262 
   1263 		state.attributes.push_back(Attribute());
   1264 
   1265 		state.attributes[0].enabled		= true;
   1266 		state.attributes[0].size		= 2;
   1267 		state.attributes[0].stride		= 0;
   1268 		state.attributes[0].type		= GL_FLOAT;
   1269 		state.attributes[0].integer		= GL_FALSE;
   1270 		state.attributes[0].divisor		= 0;
   1271 		state.attributes[0].offset		= 0;
   1272 		state.attributes[0].normalized	= GL_FALSE;
   1273 
   1274 		state.elementArrayBuffer = 0;
   1275 
   1276 		spec.buffers.push_back(floatCoordBuffer48_1);
   1277 		spec.buffers.push_back(floatCoordBuffer48_2);
   1278 
   1279 		spec.useDrawElements	= false;
   1280 		spec.instances			= 0;
   1281 		spec.count				= 48;
   1282 		spec.vao				= state;
   1283 		spec.state				= state;
   1284 		spec.indexOffset		= 0;
   1285 		spec.indexRangeMin		= 0;
   1286 		spec.indexRangeMax		= 0;
   1287 		spec.indexType			= GL_NONE;
   1288 		spec.indexCount			= 0;
   1289 
   1290 		spec.state.attributes[0].bufferNdx	= 1;
   1291 		spec.vao.attributes[0].bufferNdx	= 2;
   1292 		addChild(new VertexArrayObjectTest(m_context, spec, "diff_buffer", "diff_buffer"));
   1293 	}
   1294 	// Different size
   1295 	{
   1296 		Spec spec;
   1297 
   1298 		VertexArrayState state;
   1299 
   1300 		state.attributes.push_back(Attribute());
   1301 
   1302 		state.attributes[0].enabled		= true;
   1303 		state.attributes[0].size		= 2;
   1304 		state.attributes[0].stride		= 0;
   1305 		state.attributes[0].type		= GL_FLOAT;
   1306 		state.attributes[0].integer		= GL_FALSE;
   1307 		state.attributes[0].divisor		= 0;
   1308 		state.attributes[0].offset		= 0;
   1309 		state.attributes[0].normalized	= GL_FALSE;
   1310 		state.attributes[0].bufferNdx	= 1;
   1311 
   1312 		state.elementArrayBuffer = 0;
   1313 
   1314 		spec.buffers.push_back(floatCoordBuffer48_1);
   1315 
   1316 		spec.useDrawElements	= false;
   1317 		spec.instances			= 0;
   1318 		spec.count				= 24;
   1319 		spec.vao				= state;
   1320 		spec.state				= state;
   1321 		spec.indexOffset		= 0;
   1322 		spec.indexRangeMin		= 0;
   1323 		spec.indexRangeMax		= 0;
   1324 		spec.indexType			= GL_NONE;
   1325 		spec.indexCount			= 0;
   1326 
   1327 		spec.state.attributes[0].size		= 2;
   1328 		spec.vao.attributes[0].size			= 3;
   1329 		addChild(new VertexArrayObjectTest(m_context, spec, "diff_size", "diff_size"));
   1330 	}
   1331 
   1332 	// Different stride
   1333 	{
   1334 		Spec spec;
   1335 
   1336 		VertexArrayState state;
   1337 
   1338 		state.attributes.push_back(Attribute());
   1339 
   1340 		state.attributes[0].enabled		= true;
   1341 		state.attributes[0].size		= 2;
   1342 		state.attributes[0].stride		= 0;
   1343 		state.attributes[0].type		= GL_SHORT;
   1344 		state.attributes[0].integer		= GL_FALSE;
   1345 		state.attributes[0].divisor		= 0;
   1346 		state.attributes[0].offset		= 0;
   1347 		state.attributes[0].normalized	= GL_TRUE;
   1348 		state.attributes[0].bufferNdx	= 1;
   1349 
   1350 		state.elementArrayBuffer = 0;
   1351 
   1352 		spec.buffers.push_back(shortCoordBuffer48);
   1353 
   1354 		spec.useDrawElements	= false;
   1355 		spec.instances			= 0;
   1356 		spec.count				= 24;
   1357 		spec.vao				= state;
   1358 		spec.state				= state;
   1359 		spec.indexOffset		= 0;
   1360 		spec.indexRangeMin		= 0;
   1361 		spec.indexRangeMax		= 0;
   1362 		spec.indexType			= GL_NONE;
   1363 		spec.indexCount			= 0;
   1364 
   1365 		spec.vao.attributes[0].stride	= 2;
   1366 		spec.state.attributes[0].stride	= 4;
   1367 		addChild(new VertexArrayObjectTest(m_context, spec, "diff_stride", "diff_stride"));
   1368 	}
   1369 
   1370 	// Different types
   1371 	{
   1372 		Spec spec;
   1373 
   1374 		VertexArrayState state;
   1375 
   1376 		state.attributes.push_back(Attribute());
   1377 
   1378 		state.attributes[0].enabled		= true;
   1379 		state.attributes[0].size		= 2;
   1380 		state.attributes[0].stride		= 0;
   1381 		state.attributes[0].type		= GL_SHORT;
   1382 		state.attributes[0].integer		= GL_FALSE;
   1383 		state.attributes[0].divisor		= 0;
   1384 		state.attributes[0].offset		= 0;
   1385 		state.attributes[0].normalized	= GL_TRUE;
   1386 		state.attributes[0].bufferNdx	= 1;
   1387 
   1388 		state.elementArrayBuffer = 0;
   1389 
   1390 		spec.buffers.push_back(shortCoordBuffer48);
   1391 
   1392 		spec.useDrawElements	= false;
   1393 		spec.instances			= 0;
   1394 		spec.count				= 24;
   1395 		spec.vao				= state;
   1396 		spec.state				= state;
   1397 		spec.indexOffset		= 0;
   1398 		spec.indexRangeMin		= 0;
   1399 		spec.indexRangeMax		= 0;
   1400 		spec.indexType			= GL_NONE;
   1401 		spec.indexCount			= 0;
   1402 
   1403 		spec.vao.attributes[0].type		= GL_SHORT;
   1404 		spec.state.attributes[0].type	= GL_BYTE;
   1405 		addChild(new VertexArrayObjectTest(m_context, spec, "diff_type", "diff_type"));
   1406 	}
   1407 	// Different "integer"
   1408 	{
   1409 		Spec spec;
   1410 
   1411 		VertexArrayState state;
   1412 
   1413 		state.attributes.push_back(Attribute());
   1414 
   1415 		state.attributes[0].enabled		= true;
   1416 		state.attributes[0].size		= 2;
   1417 		state.attributes[0].stride		= 0;
   1418 		state.attributes[0].type		= GL_BYTE;
   1419 		state.attributes[0].integer		= GL_TRUE;
   1420 		state.attributes[0].divisor		= 0;
   1421 		state.attributes[0].offset		= 0;
   1422 		state.attributes[0].normalized	= GL_FALSE;
   1423 		state.attributes[0].bufferNdx	= 1;
   1424 
   1425 		state.elementArrayBuffer = 0;
   1426 
   1427 		spec.buffers.push_back(shortCoordBuffer48);
   1428 
   1429 		spec.useDrawElements	= false;
   1430 		spec.count				= 24;
   1431 		spec.vao				= state;
   1432 		spec.state				= state;
   1433 		spec.instances			= 0;
   1434 		spec.indexOffset		= 0;
   1435 		spec.indexRangeMin		= 0;
   1436 		spec.indexRangeMax		= 0;
   1437 		spec.indexType			= GL_NONE;
   1438 		spec.indexCount			= 0;
   1439 
   1440 		spec.state.attributes[0].integer	= GL_FALSE;
   1441 		spec.vao.attributes[0].integer		= GL_TRUE;
   1442 		addChild(new VertexArrayObjectTest(m_context, spec, "diff_integer", "diff_integer"));
   1443 	}
   1444 	// Different divisor
   1445 	{
   1446 		Spec spec;
   1447 
   1448 		VertexArrayState state;
   1449 
   1450 		state.attributes.push_back(Attribute());
   1451 		state.attributes.push_back(Attribute());
   1452 
   1453 		state.attributes[0].enabled		= true;
   1454 		state.attributes[0].size		= 2;
   1455 		state.attributes[0].stride		= 0;
   1456 		state.attributes[0].type		= GL_SHORT;
   1457 		state.attributes[0].integer		= GL_FALSE;
   1458 		state.attributes[0].divisor		= 0;
   1459 		state.attributes[0].offset		= 0;
   1460 		state.attributes[0].normalized	= GL_TRUE;
   1461 		state.attributes[0].bufferNdx	= 1;
   1462 
   1463 		state.attributes[1].enabled		= true;
   1464 		state.attributes[1].size		= 4;
   1465 		state.attributes[1].stride		= 0;
   1466 		state.attributes[1].type		= GL_FLOAT;
   1467 		state.attributes[1].integer		= GL_FALSE;
   1468 		state.attributes[1].divisor		= 0;
   1469 		state.attributes[1].offset		= 0;
   1470 		state.attributes[1].normalized	= GL_FALSE;
   1471 		state.attributes[1].bufferNdx	= 2;
   1472 
   1473 		state.elementArrayBuffer = 0;
   1474 
   1475 		spec.buffers.push_back(shortCoordBuffer48);
   1476 		spec.buffers.push_back(floatCoordBuffer48_1);
   1477 
   1478 		spec.useDrawElements	= false;
   1479 		spec.instances			= 10;
   1480 		spec.count				= 12;
   1481 		spec.vao				= state;
   1482 		spec.state				= state;
   1483 		spec.indexOffset		= 0;
   1484 		spec.indexRangeMin		= 0;
   1485 		spec.indexRangeMax		= 0;
   1486 		spec.indexType			= GL_NONE;
   1487 		spec.indexCount			= 0;
   1488 
   1489 		spec.vao.attributes[1].divisor		= 3;
   1490 		spec.state.attributes[1].divisor	= 2;
   1491 
   1492 		addChild(new VertexArrayObjectTest(m_context, spec, "diff_divisor", "diff_divisor"));
   1493 	}
   1494 	// Different offset
   1495 	{
   1496 		Spec spec;
   1497 
   1498 		VertexArrayState state;
   1499 
   1500 		state.attributes.push_back(Attribute());
   1501 
   1502 		state.attributes[0].enabled		= true;
   1503 		state.attributes[0].size		= 2;
   1504 		state.attributes[0].stride		= 0;
   1505 		state.attributes[0].type		= GL_SHORT;
   1506 		state.attributes[0].integer		= GL_FALSE;
   1507 		state.attributes[0].divisor		= 0;
   1508 		state.attributes[0].offset		= 0;
   1509 		state.attributes[0].normalized	= GL_TRUE;
   1510 		state.attributes[0].bufferNdx	= 1;
   1511 
   1512 		state.elementArrayBuffer = 0;
   1513 
   1514 		spec.buffers.push_back(shortCoordBuffer48);
   1515 
   1516 		spec.useDrawElements	= false;
   1517 		spec.instances			= 0;
   1518 		spec.count				= 24;
   1519 		spec.vao				= state;
   1520 		spec.state				= state;
   1521 		spec.indexOffset		= 0;
   1522 		spec.indexRangeMin		= 0;
   1523 		spec.indexRangeMax		= 0;
   1524 		spec.indexType			= GL_NONE;
   1525 		spec.indexCount			= 0;
   1526 
   1527 		spec.vao.attributes[0].offset	= 2;
   1528 		spec.state.attributes[0].offset	= 4;
   1529 		addChild(new VertexArrayObjectTest(m_context, spec, "diff_offset", "diff_offset"));
   1530 	}
   1531 	// Different normalize
   1532 	{
   1533 		Spec spec;
   1534 
   1535 		VertexArrayState state;
   1536 
   1537 		state.attributes.push_back(Attribute());
   1538 
   1539 		state.attributes[0].enabled		= true;
   1540 		state.attributes[0].size		= 2;
   1541 		state.attributes[0].stride		= 0;
   1542 		state.attributes[0].type		= GL_SHORT;
   1543 		state.attributes[0].integer		= GL_FALSE;
   1544 		state.attributes[0].divisor		= 0;
   1545 		state.attributes[0].offset		= 0;
   1546 		state.attributes[0].normalized	= GL_TRUE;
   1547 		state.attributes[0].bufferNdx	= 1;
   1548 
   1549 		state.elementArrayBuffer = 0;
   1550 
   1551 		spec.buffers.push_back(shortCoordBuffer48);
   1552 
   1553 		spec.useDrawElements	= false;
   1554 		spec.instances			= 0;
   1555 		spec.count				= 48;
   1556 		spec.vao				= state;
   1557 		spec.state				= state;
   1558 		spec.indexOffset		= 0;
   1559 		spec.indexRangeMin		= 0;
   1560 		spec.indexRangeMax		= 0;
   1561 		spec.indexType			= GL_NONE;
   1562 		spec.indexCount			= 0;
   1563 
   1564 		spec.vao.attributes[0].normalized	= GL_TRUE;
   1565 		spec.state.attributes[0].normalized	= GL_FALSE;;
   1566 		addChild(new VertexArrayObjectTest(m_context, spec, "diff_normalize", "diff_normalize"));
   1567 	}
   1568 	// DrawElements with buffer / Pointer
   1569 	{
   1570 		Spec spec;
   1571 
   1572 		VertexArrayState state;
   1573 
   1574 		state.attributes.push_back(Attribute());
   1575 
   1576 		state.attributes[0].enabled		= true;
   1577 		state.attributes[0].size		= 2;
   1578 		state.attributes[0].stride		= 0;
   1579 		state.attributes[0].type		= GL_FLOAT;
   1580 		state.attributes[0].integer		= GL_FALSE;
   1581 		state.attributes[0].divisor		= 0;
   1582 		state.attributes[0].offset		= 0;
   1583 		state.attributes[0].normalized	= GL_TRUE;
   1584 		state.attributes[0].bufferNdx	= 1;
   1585 
   1586 		state.elementArrayBuffer = 0;
   1587 
   1588 		spec.buffers.push_back(floatCoordBuffer48_1);
   1589 
   1590 		BufferSpec indexBuffer = { 24, 192, 1, 0, 0, GL_UNSIGNED_SHORT, 0, 48, 0.0f, 0.0f };
   1591 		spec.buffers.push_back(indexBuffer);
   1592 
   1593 		spec.useDrawElements	= true;
   1594 		spec.count				= 24;
   1595 		spec.vao				= state;
   1596 		spec.state				= state;
   1597 		spec.instances			= 0;
   1598 		spec.indexOffset		= 0;
   1599 		spec.indexRangeMin		= 0;
   1600 		spec.indexRangeMax		= 48;
   1601 		spec.indexType			= GL_UNSIGNED_SHORT;
   1602 		spec.indexCount			= 24;
   1603 
   1604 		spec.state.elementArrayBuffer	= 0;
   1605 		spec.vao.elementArrayBuffer		= 2;
   1606 		addChild(new VertexArrayObjectTest(m_context, spec, "diff_indices", "diff_indices"));
   1607 	}
   1608 	// Use all attributes
   1609 
   1610 	addChild(new MultiVertexArrayObjectTest(m_context, "all_attributes", "all_attributes"));
   1611 }
   1612 
   1613 } // Functional
   1614 } // gles3
   1615 } // deqp
   1616