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