1/*-------------------------------------------------------------------------
2 * OpenGL Conformance Test Suite
3 * -----------------------------
4 *
5 * Copyright (c) 2014-2016 The Khronos Group Inc.
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
22 */ /*-------------------------------------------------------------------*/
23
24/**
25 */ /*!
26 * \file  esextcDrawElementsBaseVertexTests.cpp
27 * \brief Implements conformance tests for "draw elements base vertex" functionality
28 *        for both ES and GL.
29 */ /*-------------------------------------------------------------------*/
30
31#include "esextcDrawElementsBaseVertexTests.hpp"
32#include "gluContextInfo.hpp"
33#include "gluDefs.hpp"
34#include "glwEnums.hpp"
35#include "glwFunctions.hpp"
36#include "tcuRenderTarget.hpp"
37#include "tcuTestLog.hpp"
38
39#include <string>
40#include <vector>
41
42namespace glcts
43{
44/** Constructor.
45 *
46 *  @param context     Rendering context
47 *  @param name        Test name
48 *  @param description Test description
49 */
50DrawElementsBaseVertexTestBase::DrawElementsBaseVertexTestBase(glcts::Context& context, const ExtParameters& extParams,
51															   const char* name, const char* description)
52	: TestCaseBase(context, extParams, name, description)
53	, m_is_draw_elements_base_vertex_supported(false)
54	, m_is_ext_multi_draw_arrays_supported(false)
55	, m_is_geometry_shader_supported(false)
56	, m_is_tessellation_shader_supported(false)
57	, m_is_vertex_attrib_binding_supported(false)
58	, m_bo_id(0)
59	, m_bo_id_2(0)
60	, m_fbo_id(0)
61	, m_fs_id(0)
62	, m_gs_id(0)
63	, m_po_id(0)
64	, m_po_color_attribute_location(-1)
65	, m_po_uses_gs_stage(false)
66	, m_po_uses_tc_te_stages(false)
67	, m_po_uses_vertex_attrib_binding(false)
68	, m_po_vertex_attribute_location(-1)
69	, m_tc_id(0)
70	, m_te_id(0)
71	, m_to_base_id(0)
72	, m_to_ref_id(0)
73	, m_vao_id(0)
74	, m_vs_id(0)
75	, m_bo_negative_data_index_size(-1)
76	, m_bo_negative_data_vertex_size(-1)
77	, m_draw_call_color_offset(DE_NULL)
78	, m_draw_call_index_offset(DE_NULL)
79	, m_draw_call_index2_offset(DE_NULL)
80	, m_draw_call_index3_offset(DE_NULL)
81	, m_draw_call_index4_offset(DE_NULL)
82	, m_draw_call_index5_offset(DE_NULL)
83	, m_draw_call_vertex_offset(DE_NULL)
84	, m_draw_call_vertex2_offset(DE_NULL)
85	, m_to_height(128)
86	, m_to_width(128)
87	, m_to_base_data(DE_NULL)
88	, m_to_ref_data(DE_NULL)
89{
90	static const glw::GLuint functional_index_data[] = /* used for a number of Functional Tests */
91		{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22 };
92	static const glw::GLuint functional2_index_data[] = /* used for Functional Test IV */
93		{ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
94		  30, 31, 32, 0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  10, 11, 12, 13, 14, 15, 16 };
95	static const glw::GLubyte functional3_index_data[] = /* used for Functional Test IX */
96		{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
97	static const glw::GLushort functional4_index_data[] = /* used for Functional Test IX */
98		{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
99	static const glw::GLuint functional5_index_data[] = /* used for Functional Test IX */
100		{ 2147483647 + 3u,								/* 2^31 + 2 */
101		  2147483647 + 4u,
102		  2147483647 + 5u,
103		  2147483647 + 6u,
104		  2147483647 + 7u,
105		  2147483647 + 8u,
106		  2147483647 + 9u,
107		  2147483647 + 10u,
108		  2147483647 + 11u,
109		  2147483647 + 12u,
110		  2147483647 + 13u,
111		  2147483647 + 14u,
112		  257, // regular draw call indices for ubyte ref image
113		  258,
114		  259,
115		  260,
116		  261,
117		  262,
118		  263,
119		  264,
120		  265,
121		  266,
122		  267,
123		  268,
124		  65537, // regular draw call indices for ushort ref image
125		  65538,
126		  65539,
127		  65540,
128		  65541,
129		  65542,
130		  65543,
131		  65544,
132		  65545,
133		  65546,
134		  65547,
135		  65548,
136		  0, // regular draw call indices for uint ref image
137		  1,
138		  2,
139		  3,
140		  4,
141		  5,
142		  6,
143		  7,
144		  8,
145		  9,
146		  10,
147		  11 };
148	static const glw::GLfloat functional_color_data[] = /* used for "vertex attrib binding" Functional Test */
149		{
150		  0.1f, 0.2f, 0.2f, 0.3f, 0.3f, 0.4f, 0.4f, 0.5f, 0.5f, 0.6f, 0.6f, 0.7f, 0.7f, 0.8f, 0.8f, 0.9f, 0.9f,
151		  1.0f, 1.0f, 0.9f, 0.9f, 0.8f, 0.8f, 0.7f, 0.7f, 0.6f, 0.6f, 0.5f, 0.5f, 0.4f, 0.4f, 0.3f, 0.3f, 0.2f,
152		  0.2f, 0.1f, 0.1f, 0.0f, 0.0f, 0.1f, 0.1f, 0.2f, 0.2f, 0.4f, 0.3f, 0.9f, 0.4f, 0.8f, 0.5f, 1.0f, 0.6f,
153		  0.8f, 0.7f, 0.1f, 0.8f, 0.3f, 0.9f, 0.5f, 1.0f, 0.0f, 0.2f, 0.0f, 0.0f, 0.3f, 0.1f, 1.0f,
154		};
155	static const glw::GLfloat functional_vertex_data[] = /* used by a number of Functional Tests */
156		{
157		  0.0f,  0.0f,  -0.1f, -0.1f, 0.2f,  0.8f,  -0.3f, -0.3f, 0.4f,  -0.4f, 0.5f,  0.5f, -0.6f, 0.6f,
158		  0.7f,  -0.7f, -0.8f, 0.8f,  0.9f,  -0.9f, -1.0f, -1.0f, 1.0f,  -1.0f, 0.0f,  1.0f, -0.9f, 0.1f,
159		  0.8f,  -0.2f, -0.7f, 0.3f,  -0.6f, -0.4f, 0.5f,  -0.5f, -0.4f, -0.6f, 0.3f,  0.7f, -0.2f, -0.8f,
160		  -0.1f, -0.9f, 0.0f,  0.0f,  0.5f,  0.5f,  -0.6f, 0.6f,  0.7f,  -0.7f, -0.8f, 0.8f, 0.9f,  -0.9f,
161		  -1.0f, -1.0f, 1.0f,  -1.0f, 0.0f,  1.0f,  -0.9f, 0.1f,  0.8f,  -0.2f,
162		};
163	static const glw::GLfloat functional2_vertex_data[] = /* used by a number of Functional Tests */
164		{
165		  -1.0f, -1.0f, 1.0f, -1.0f, 0.0f, 1.0f, 0.3f, 0.3f, 0.4f, 0.4f, 0.5f, 0.5f, 0.6f, 0.6f, 0.7f, 0.7f,
166		  0.8f,  0.8f,  0.9f, 0.9f,  0.1f, 0.2f, 0.2f, 0.1f, 0.1f, 0.2f, 0.9f, 0.1f, 0.8f, 0.2f, 0.7f, 0.3f,
167		  0.6f,  0.4f,  0.5f, 0.5f,  0.4f, 0.6f, 0.3f, 0.7f, 0.2f, 0.8f, 0.1f, 0.9f, 0.0f, 0.0f,
168
169		};
170	static const glw::GLuint negative_index_data[]  = { 0, 1, 2 };
171	static const float		 negative_vertex_data[] = { -1.0f, -1.0f, 1.0f, -1.0f, 0.0f, 1.0f };
172
173	m_bo_functional_data_color		  = functional_color_data;
174	m_bo_functional_data_color_size   = sizeof(functional_color_data);
175	m_bo_functional_data_index		  = functional_index_data;
176	m_bo_functional_data_index_size   = sizeof(functional_index_data);
177	m_bo_functional_data_vertex		  = functional_vertex_data;
178	m_bo_functional_data_vertex_size  = sizeof(functional_vertex_data);
179	m_bo_functional2_data_index		  = functional2_index_data;
180	m_bo_functional2_data_index_size  = sizeof(functional2_index_data);
181	m_bo_functional3_data_index		  = functional3_index_data;
182	m_bo_functional3_data_index_size  = sizeof(functional3_index_data);
183	m_bo_functional4_data_index		  = functional4_index_data;
184	m_bo_functional4_data_index_size  = sizeof(functional4_index_data);
185	m_bo_functional5_data_index		  = functional5_index_data;
186	m_bo_functional5_data_index_size  = sizeof(functional5_index_data);
187	m_bo_functional2_data_vertex	  = functional2_vertex_data;
188	m_bo_functional2_data_vertex_size = sizeof(functional2_vertex_data);
189	m_bo_negative_data_index		  = negative_index_data;
190	m_bo_negative_data_index_size	 = sizeof(negative_index_data);
191	m_bo_negative_data_vertex		  = negative_vertex_data;
192	m_bo_negative_data_vertex_size	= sizeof(negative_vertex_data);
193}
194
195/** Creates & initializes a number of shader objects, assigns user-provided
196 *  code to relevant shader objects and compiles them. If all shaders are
197 *  compiled successfully, they are later attached to a program object, id
198 *  of which is stored in m_po_id. Finally, the program object is linked.
199 *
200 *  If the compilation process or the linking process fails for any reason,
201 *  the method throws a TestError exception.
202 *
203 *  Fragment shader object ID is stored under m_fs_id.
204 *  Geometry shader object ID is stored under m_gs_id.
205 *  Tessellation control shader object ID is stored under m_tc_id.
206 *  Tessellation evaluation shader object ID is stored under m_te_id.
207 *  Vertex shader object ID is stored under m_vs_id.
208 *
209 *  @param fs_code Code to use for the fragment shader. Must not be NULL.
210 *  @param gs_code Code to use for the geometry shader. Can be NULL.
211 *  @param tc_code Code to use for the tessellation control shader. Can be NULL.
212 *  @param te_code Code to use for the tessellation evaluation shader. Can be NULL.
213 *  @param vs_code Code to use for the vertex shader. Must not be NULL.
214 *
215 */
216void DrawElementsBaseVertexTestBase::buildProgram(const char* fs_code, const char* vs_code, const char* tc_code,
217												  const char* te_code, const char* gs_code)
218{
219	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
220
221	/* Create program & shader objects */
222	m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
223	m_vs_id = gl.createShader(GL_VERTEX_SHADER);
224
225	if (tc_code != DE_NULL)
226	{
227		m_tc_id = gl.createShader(GL_TESS_CONTROL_SHADER);
228	}
229
230	if (te_code != DE_NULL)
231	{
232		m_te_id = gl.createShader(GL_TESS_EVALUATION_SHADER);
233	}
234
235	if (gs_code != DE_NULL)
236	{
237		m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
238	}
239
240	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
241
242	m_po_id = gl.createProgram();
243	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
244
245	/* Assign source code to the shader objects */
246	gl.shaderSource(m_fs_id, 1,			/* count */
247					&fs_code, DE_NULL); /* length */
248	gl.shaderSource(m_vs_id, 1,			/* count */
249					&vs_code, DE_NULL); /* length */
250
251	if (m_tc_id != 0)
252	{
253		gl.shaderSource(m_tc_id, 1,			/* count */
254						&tc_code, DE_NULL); /* length */
255	}
256
257	if (m_te_id != 0)
258	{
259		gl.shaderSource(m_te_id, 1,			/* count */
260						&te_code, DE_NULL); /* length */
261	}
262
263	if (m_gs_id != 0)
264	{
265		gl.shaderSource(m_gs_id, 1,			/* count */
266						&gs_code, DE_NULL); /* length */
267	}
268
269	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call(s) failed.");
270
271	/* Try to compile the shaders */
272	const glw::GLuint  so_ids[] = { m_fs_id, m_vs_id, m_tc_id, m_te_id, m_gs_id };
273	const unsigned int n_so_ids = sizeof(so_ids) / sizeof(so_ids[0]);
274
275	for (unsigned int n_so_id = 0; n_so_id < n_so_ids; ++n_so_id)
276	{
277		glw::GLint  compile_status = GL_FALSE;
278		glw::GLuint so_id		   = so_ids[n_so_id];
279
280		if (so_id != 0)
281		{
282			gl.compileShader(so_id);
283			GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed");
284
285			gl.getShaderiv(so_id, GL_COMPILE_STATUS, &compile_status);
286			GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed.");
287
288			if (compile_status == GL_FALSE)
289			{
290				TCU_FAIL("Shader compilation failed");
291			} /* if (compile_status == GL_FALSE) */
292		}	 /* if (so_id != 0) */
293	}		  /* for (all shader objects) */
294
295	/* Attach the shaders to the program object */
296	gl.attachShader(m_po_id, m_fs_id);
297	gl.attachShader(m_po_id, m_vs_id);
298
299	if (m_tc_id != 0)
300	{
301		gl.attachShader(m_po_id, m_tc_id);
302	}
303
304	if (m_te_id != 0)
305	{
306		gl.attachShader(m_po_id, m_te_id);
307	}
308
309	if (m_gs_id != 0)
310	{
311		gl.attachShader(m_po_id, m_gs_id);
312	}
313
314	GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call failed.");
315
316	/* Set up TFO */
317	const glw::GLchar* tf_varyings[] = { "gl_Position" };
318
319	gl.transformFeedbackVaryings(m_po_id, 1, /* count */
320								 tf_varyings, GL_SEPARATE_ATTRIBS);
321	GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() call failed.");
322
323	/* Try to link the program object */
324	glw::GLint link_status = GL_FALSE;
325
326	gl.linkProgram(m_po_id);
327	GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed.");
328
329	gl.getProgramiv(m_po_id, GL_LINK_STATUS, &link_status);
330	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed.");
331
332	if (link_status == GL_FALSE)
333	{
334		TCU_FAIL("Program linking failed.");
335	}
336
337	/* Retrieve attribute locations */
338	m_po_color_attribute_location =
339		gl.getAttribLocation(m_po_id, "in_color"); /* != -1 only for "vertex attrib binding" tests */
340	m_po_vertex_attribute_location = gl.getAttribLocation(m_po_id, "vertex");
341
342	DE_ASSERT(m_po_vertex_attribute_location != -1);
343}
344
345/** Verifies contents of the base & reference textures. This method can work
346 *  in two modes:
347 *
348 *  a) If @param should_be_equal is true, the method will throw a TestError exception
349 *     if the two textures are not a match.
350 *  b) If @param should_be_equal is false, the method will throw a TestError exception
351 *     if the two extures are a match.
352 *
353 *  Furthermore, in order to verify that the basevertex & regular draw calls actually
354 *  generated at least one sample, the method verifies that at least one texel in both
355 *  of the textures has been modified. If all texels in any of the textures are found
356 *  to be (0, 0, 0) (alpha channel is ignored), TestError exception will be generated.
357 *
358 *  @param should_be_equal Please see description for more details.
359 **/
360void DrawElementsBaseVertexTestBase::compareBaseAndReferenceTextures(bool should_be_equal)
361{
362	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
363
364	/* Read contents of both base and reference textures */
365	gl.framebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_to_base_id, 0); /* level */
366	GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D() call failed.");
367
368	gl.readPixels(0, /* x */
369				  0, /* y */
370				  m_to_width, m_to_height, GL_RGBA, GL_UNSIGNED_BYTE, m_to_base_data);
371	GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels() call failed.");
372
373	gl.framebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_to_ref_id, 0); /* level */
374	GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D() call failed.");
375	gl.readPixels(0, /* x */
376				  0, /* y */
377				  m_to_width, m_to_height, GL_RGBA, GL_UNSIGNED_BYTE, m_to_ref_data);
378	GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels() call failed.");
379
380	/* Both tests should be a match */
381	const unsigned char* base_data_ptr				   = m_to_base_data;
382	bool				 all_base_rgb_texels_zero	  = true;
383	bool				 all_reference_rgb_texels_zero = true;
384	const unsigned int   n_texels					   = m_to_width * m_to_height;
385	const unsigned char* ref_data_ptr				   = m_to_ref_data;
386	bool				 textures_identical			   = true;
387
388	for (unsigned int n_texel = 0; n_texel < n_texels; ++n_texel)
389	{
390		/* Verify something was rendered to one of the render-targets. Note we
391		 * omit alpha channel, since the clear color is set to 0xFF by default */
392		if (base_data_ptr[0] != 0 || base_data_ptr[1] != 0 || base_data_ptr[2] != 0)
393		{
394			all_base_rgb_texels_zero = false;
395		}
396
397		if (ref_data_ptr[0] != 0 || ref_data_ptr[1] != 0 || ref_data_ptr[2] != 0)
398		{
399			all_reference_rgb_texels_zero = false;
400		}
401
402		if (base_data_ptr[0] != ref_data_ptr[0] || base_data_ptr[1] != ref_data_ptr[1] ||
403			base_data_ptr[2] != ref_data_ptr[2] || base_data_ptr[3] != ref_data_ptr[3])
404		{
405			if (should_be_equal)
406			{
407				const unsigned int y = n_texel / m_to_width;
408				const unsigned int x = n_texel % m_to_width;
409
410				m_testCtx.getLog() << tcu::TestLog::Message << "Pixels at (" << x << ", " << y
411								   << ") do not match. Found:"
412								   << "(" << (unsigned int)base_data_ptr[0] << ", " << (unsigned int)base_data_ptr[1]
413								   << ", " << (unsigned int)base_data_ptr[2] << ", " << (unsigned int)base_data_ptr[3]
414								   << "), expected:"
415								   << "(" << (unsigned int)ref_data_ptr[0] << ", " << (unsigned int)ref_data_ptr[1]
416								   << ", " << (unsigned int)ref_data_ptr[2] << ", " << (unsigned int)ref_data_ptr[3]
417								   << ")." << tcu::TestLog::EndMessage;
418
419				TCU_FAIL("Pixel mismatch");
420			}
421			else
422			{
423				/* Base and reference textures are *not* identical. */
424				textures_identical = false;
425			}
426		}
427
428		base_data_ptr += 4; /* components */
429		ref_data_ptr += 4;  /* components */
430	}						/* for (all texels) */
431
432	if (all_base_rgb_texels_zero)
433	{
434		TCU_FAIL("Draw call used to render contents of the base texture did not change the texture");
435	}
436
437	if (all_reference_rgb_texels_zero)
438	{
439		TCU_FAIL("Draw call used to render contents of the reference texture did not change the texture");
440	}
441
442	if (!should_be_equal && textures_identical)
443	{
444		TCU_FAIL("Textures are a match, even though they should not be identical.");
445	}
446}
447
448/** Updates m_draw_call_color_offset, m_draw_call_index*_offset and m_draw_call_vertex*_offset
449 *  members with valid values, depending on the input arguments.
450 *
451 *  @param use_clientside_index_data  true if client-side index data buffer is going to be
452 *                                    used for the test-issued draw calls, false otherwise.
453 *  @param use_clientside_vertex_data true if client-side color & vertex data buffer is going
454 *                                    to be used for the test-issued draw calls, false
455 *                                    otherwise.
456 */
457void DrawElementsBaseVertexTestBase::computeVBODataOffsets(bool use_clientside_index_data,
458														   bool use_clientside_vertex_data)
459{
460	if (use_clientside_index_data)
461	{
462		m_draw_call_index_offset  = m_bo_functional_data_index;
463		m_draw_call_index2_offset = m_bo_functional2_data_index;
464		m_draw_call_index3_offset = m_bo_functional3_data_index;
465		m_draw_call_index4_offset = m_bo_functional4_data_index;
466		m_draw_call_index5_offset = m_bo_functional5_data_index;
467	}
468	else
469	{
470		/* Note that these assignments correspond to how the buffer object storage is constructed.
471		 * If you need to update these offsets, don't forget to update the glBufferSubData() calls
472		 */
473		m_draw_call_index_offset =
474			(const glw::GLuint*)(deUintptr)(m_bo_functional_data_vertex_size + m_bo_functional2_data_vertex_size);
475		m_draw_call_index2_offset = (const glw::GLuint*)(deUintptr)(
476			m_bo_functional_data_vertex_size + m_bo_functional2_data_vertex_size + m_bo_functional_data_index_size);
477		m_draw_call_index3_offset =
478			(const glw::GLubyte*)(deUintptr)(m_bo_functional_data_vertex_size + m_bo_functional2_data_vertex_size +
479											 m_bo_functional_data_index_size + m_bo_functional2_data_index_size);
480		m_draw_call_index4_offset = (const glw::GLushort*)(deUintptr)(
481			m_bo_functional_data_vertex_size + m_bo_functional2_data_vertex_size + m_bo_functional_data_index_size +
482			m_bo_functional2_data_index_size + m_bo_functional3_data_index_size);
483		m_draw_call_index5_offset = (const glw::GLuint*)(deUintptr)(
484			m_bo_functional_data_vertex_size + m_bo_functional2_data_vertex_size + m_bo_functional_data_index_size +
485			m_bo_functional2_data_index_size + m_bo_functional3_data_index_size + m_bo_functional4_data_index_size);
486	}
487
488	if (use_clientside_vertex_data)
489	{
490		m_draw_call_color_offset   = m_bo_functional_data_color;
491		m_draw_call_vertex_offset  = m_bo_functional_data_vertex;
492		m_draw_call_vertex2_offset = m_bo_functional2_data_vertex;
493	}
494	else
495	{
496		/* Note: same observation as above holds. */
497		m_draw_call_color_offset = (const glw::GLfloat*)(deUintptr)(
498			m_bo_functional_data_vertex_size + m_bo_functional2_data_vertex_size + m_bo_functional_data_index_size +
499			m_bo_functional2_data_index_size + m_bo_functional3_data_index_size + m_bo_functional4_data_index_size +
500			m_bo_functional5_data_index_size);
501		m_draw_call_vertex_offset  = DE_NULL;
502		m_draw_call_vertex2_offset = (const glw::GLfloat*)(deUintptr)m_bo_functional_data_vertex_size;
503	}
504}
505
506void DrawElementsBaseVertexTestBase::deinit()
507{
508	/* TCU_FAIL will skip the per test object de-initialization, we need to
509	 * take care of it here
510	 */
511	deinitPerTestObjects();
512}
513
514/** Deinitializes all ES objects created by the test. */
515void DrawElementsBaseVertexTestBase::deinitPerTestObjects()
516{
517	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
518
519	deinitProgramAndShaderObjects();
520
521	if (m_bo_id != 0)
522	{
523		gl.deleteBuffers(1, &m_bo_id);
524
525		m_bo_id = 0;
526	}
527
528	if (m_bo_id_2 != 0)
529	{
530		gl.deleteBuffers(1, &m_bo_id_2);
531
532		m_bo_id_2 = 0;
533	}
534
535	if (m_fbo_id != 0)
536	{
537		gl.deleteFramebuffers(1, &m_fbo_id);
538
539		m_fbo_id = 0;
540	}
541
542	if (m_to_base_data != DE_NULL)
543	{
544		delete[] m_to_base_data;
545
546		m_to_base_data = DE_NULL;
547	}
548
549	if (m_to_base_id != 0)
550	{
551		gl.deleteTextures(1, &m_to_base_id);
552
553		m_to_base_id = 0;
554	}
555
556	if (m_to_ref_data != DE_NULL)
557	{
558		delete[] m_to_ref_data;
559
560		m_to_ref_data = DE_NULL;
561	}
562
563	if (m_to_ref_id != 0)
564	{
565		gl.deleteTextures(1, &m_to_ref_id);
566
567		m_to_ref_id = 0;
568	}
569
570	if (m_vao_id != 0)
571	{
572		gl.deleteVertexArrays(1, &m_vao_id);
573
574		m_vao_id = 0;
575	}
576
577	if (m_vs_id != 0)
578	{
579		gl.deleteShader(m_vs_id);
580
581		m_vs_id = 0;
582	}
583
584	/* Restore the default GL_PACK_ALIGNMENT setting */
585	gl.pixelStorei(GL_PACK_ALIGNMENT, 4);
586}
587
588/** Deinitializes all program & shader objects that may have been initialized
589 *  by the test.
590 */
591void DrawElementsBaseVertexTestBase::deinitProgramAndShaderObjects()
592{
593	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
594
595	if (m_fs_id != 0)
596	{
597		gl.deleteShader(m_fs_id);
598
599		m_fs_id = 0;
600	}
601
602	if (m_gs_id != 0)
603	{
604		gl.deleteShader(m_gs_id);
605
606		m_gs_id = 0;
607	}
608
609	if (m_po_id != 0)
610	{
611		gl.deleteProgram(m_po_id);
612
613		m_po_id = 0;
614	}
615
616	if (m_tc_id != 0)
617	{
618		gl.deleteShader(m_tc_id);
619
620		m_tc_id = 0;
621	}
622
623	if (m_te_id != 0)
624	{
625		gl.deleteShader(m_te_id);
626
627		m_te_id = 0;
628	}
629}
630
631/** Executes all test cases stored in m_test_cases.
632 *
633 *  This method throws a TestError exception upon test failure.
634 **/
635void DrawElementsBaseVertexTestBase::executeTestCases()
636{
637	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
638
639	/* Iterate over all test cases */
640	for (_test_cases_const_iterator test_cases_iterator = m_test_cases.begin();
641		 test_cases_iterator != m_test_cases.end(); ++test_cases_iterator)
642	{
643		const _test_case& test_case = *test_cases_iterator;
644
645		/* What is the size of a single index value? */
646		unsigned int index_size = 0;
647
648		switch (test_case.index_type)
649		{
650		case GL_UNSIGNED_BYTE:
651			index_size = 1;
652			break;
653		case GL_UNSIGNED_SHORT:
654			index_size = 2;
655			break;
656		case GL_UNSIGNED_INT:
657			index_size = 4;
658			break;
659
660		default:
661		{
662			TCU_FAIL("Unrecognized index type");
663		}
664		} /* switch (test_case.index_type) */
665
666		/* Set up the work environment */
667		setUpFunctionalTestObjects(test_case.use_clientside_vertex_data, test_case.use_clientside_index_data,
668								   test_case.use_tessellation_shader_stage, test_case.use_geometry_shader_stage,
669								   test_case.use_vertex_attrib_binding, test_case.use_overflow_test_vertices);
670
671		gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_to_base_id, 0); /* level */
672		GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D() call failed");
673
674		gl.clear(GL_COLOR_BUFFER_BIT);
675		GLU_EXPECT_NO_ERROR(gl.getError(), "glClear() call failed.");
676
677		switch (test_case.function_type)
678		{
679		case FUNCTION_GL_DRAW_ELEMENTS_BASE_VERTEX:
680		{
681			gl.drawElementsBaseVertex(test_case.primitive_mode, 3, /* count */
682									  test_case.index_type, test_case.index_offset, test_case.basevertex);
683
684			break;
685		}
686
687		case FUNCTION_GL_DRAW_ELEMENTS_INSTANCED_BASE_VERTEX:
688		{
689			gl.drawElementsInstancedBaseVertex(test_case.primitive_mode, 3,						/* count */
690											   test_case.index_type, test_case.index_offset, 3, /* instancecount */
691											   test_case.basevertex);
692
693			break;
694		}
695
696		case FUNCTION_GL_DRAW_RANGE_ELEMENTS_BASE_VERTEX:
697		{
698			gl.drawRangeElementsBaseVertex(test_case.primitive_mode, test_case.range_start, test_case.range_end,
699										   3, /* count */
700										   test_case.index_type, test_case.index_offset, test_case.basevertex);
701
702			break;
703		}
704
705		case FUNCTION_GL_MULTI_DRAW_ELEMENTS_BASE_VERTEX:
706		{
707			const glw::GLint basevertex_array[] = { test_case.basevertex, test_case.basevertex, test_case.basevertex };
708
709			gl.multiDrawElementsBaseVertex(
710				test_case.primitive_mode, test_case.multi_draw_call_count_array, test_case.index_type,
711				(const glw::GLvoid**)test_case.multi_draw_call_indices_array, 3, /* primcount */
712				basevertex_array);
713
714			break;
715		}
716
717		default:
718		{
719			TCU_FAIL("Unsupported function index");
720		}
721		} /* switch (n_function) */
722
723		if (gl.getError() != GL_NO_ERROR)
724		{
725			std::stringstream error_sstream;
726
727			error_sstream << getFunctionName(test_case.function_type) << " call failed";
728			TCU_FAIL(error_sstream.str().c_str());
729		}
730
731		/* Now, render the same triangle using glDrawElements() to the reference texture */
732		gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_to_ref_id, 0); /* level */
733		GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D() call failed");
734
735		gl.clear(GL_COLOR_BUFFER_BIT);
736		GLU_EXPECT_NO_ERROR(gl.getError(), "glClear() call failed.");
737
738		glw::GLenum regular_draw_call_index_type = test_case.index_type;
739		if (test_case.regular_draw_call_index_type != 0)
740		{
741			/* Need to use a different index type for regular draw call */
742			regular_draw_call_index_type = test_case.regular_draw_call_index_type;
743
744			switch (test_case.regular_draw_call_index_type)
745			{
746			case GL_UNSIGNED_BYTE:
747				index_size = 1;
748				break;
749			case GL_UNSIGNED_SHORT:
750				index_size = 2;
751				break;
752			case GL_UNSIGNED_INT:
753				index_size = 4;
754				break;
755
756			default:
757			{
758				TCU_FAIL("Unrecognized index type");
759			}
760			}
761		}
762
763		glw::GLubyte* regular_draw_call_offset =
764			(glw::GLubyte*)test_case.index_offset + index_size * test_case.regular_draw_call_offset;
765		if (test_case.use_overflow_test_vertices)
766		{
767			/* Special case for overflow test */
768			regular_draw_call_offset = (glw::GLubyte*)test_case.regular_draw_call_offset2;
769		}
770
771		switch (test_case.function_type)
772		{
773		case FUNCTION_GL_DRAW_ELEMENTS_BASE_VERTEX: /* pass-through */
774		case FUNCTION_GL_DRAW_RANGE_ELEMENTS_BASE_VERTEX:
775		{
776			gl.drawElements(test_case.primitive_mode, 3,							 /* count */
777							regular_draw_call_index_type, regular_draw_call_offset); /* as per test spec */
778			GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawElements() call failed");
779
780			break;
781		}
782
783		case FUNCTION_GL_DRAW_ELEMENTS_INSTANCED_BASE_VERTEX:
784		{
785			gl.drawElementsInstanced(test_case.primitive_mode, 3,								 /* count */
786									 regular_draw_call_index_type, regular_draw_call_offset, 3); /* instancecount */
787			GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawElementsInstanced() call failed");
788
789			break;
790		}
791
792		case FUNCTION_GL_MULTI_DRAW_ELEMENTS_BASE_VERTEX:
793		{
794			/* Normally we'd just use glMultiDrawElements() here but it's not a part
795			 * of ES3.1 core spec and we're trying to avoid any dependencies in the test.
796			 * No damage done under GL, either.
797			 */
798			for (unsigned int n_draw_call = 0; n_draw_call < 3; /* drawcount */
799				 ++n_draw_call)
800			{
801				gl.drawElements(test_case.primitive_mode, test_case.multi_draw_call_count_array[n_draw_call],
802								regular_draw_call_index_type,
803								(const glw::GLvoid*)test_case.regular_multi_draw_call_offseted_array[n_draw_call]);
804
805				GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawElements() call failed.");
806			}
807
808			break;
809		}
810
811		default:
812		{
813			TCU_FAIL("Unrecognized function index");
814		}
815		} /* switch (n_function) */
816
817		/* Compare the two textures and make sure they are either a match or not,
818		 * depending on whether basevertex values match the offsets used for regular
819		 * draw calls.
820		 */
821		compareBaseAndReferenceTextures(test_case.should_base_texture_match_reference_texture);
822
823		/* ES Resources are allocated per test objects, we need to release them here */
824		deinitPerTestObjects();
825	} /* for (all test cases) */
826}
827
828/* Returns name of the function represented by _function_type.
829 *
830 * @param function_type Function type to use for the query.
831 *
832 * @return As per description, or "[?]" (without the quotation marks)
833 *         if @param function_type was not recognized.
834 */
835std::string DrawElementsBaseVertexTestBase::getFunctionName(_function_type function_type)
836{
837	std::string result = "[?]";
838
839	switch (function_type)
840	{
841	case FUNCTION_GL_DRAW_ELEMENTS_BASE_VERTEX:
842	{
843		if (glu::isContextTypeES(m_context.getRenderContext().getType()))
844		{
845			result = "glDrawElementsBaseVertexEXT()";
846
847			break;
848		}
849		else
850		{
851			result = "glDrawElementsBaseVertex()";
852
853			break;
854		}
855
856		break;
857	}
858
859	case FUNCTION_GL_DRAW_ELEMENTS_INSTANCED_BASE_VERTEX:
860	{
861		if (glu::isContextTypeES(m_context.getRenderContext().getType()))
862		{
863			result = "glDrawElementsInstancedBaseVertexEXT()";
864
865			break;
866		}
867		else
868		{
869			result = "glDrawElementsInstancedBaseVertex()";
870
871			break;
872		}
873
874		break;
875	}
876
877	case FUNCTION_GL_DRAW_RANGE_ELEMENTS_BASE_VERTEX:
878	{
879		if (glu::isContextTypeES(m_context.getRenderContext().getType()))
880		{
881			result = "glDrawRangeElementsBaseVertexEXT()";
882
883			break;
884		}
885		else
886		{
887			result = "glDrawRangeElementsBaseVertex()";
888
889			break;
890		}
891
892		break;
893	}
894
895	case FUNCTION_GL_MULTI_DRAW_ELEMENTS_BASE_VERTEX:
896	{
897		if (glu::isContextTypeES(m_context.getRenderContext().getType()))
898		{
899			result = "glMultiDrawElementsBaseVertexEXT()";
900
901			break;
902		}
903		else
904		{
905			result = "glMultiDrawElementsBaseVertex()";
906
907			break;
908		}
909
910		break;
911	}
912
913	default:
914	{
915		TCU_FAIL("Unknown function type");
916
917		break;
918	}
919	} /* switch (function_type) */
920
921	return result;
922}
923
924/** Initializes extension-specific function pointers and caches information about
925 *  extension availability.
926 *
927 *  Function pointers for the following extensions are retrieved & stored:
928 *
929 *  - GL_EXT_draw_elements_base_vertex (ES) or GL_ARB_draw_elements_base_vertex (GL)
930 *  - GL_EXT_multi_draw_arrays         (ES & GL)
931 *
932 *  Availability of the following extensions is checked & cached:
933 *
934 *  - GL_EXT_draw_elements_base_vertex (ES) or GL_ARB_draw_elements_base_vertex (GL)
935 *  - GL_EXT_geometry_shader           (ES) or GL_ARB_geometry_shader4          (GL)
936 *  - GL_EXT_multi_draw_arrays         (ES & GL)
937 *  - GL_EXT_tessellation_shader       (ES) or GL_ARB_tessellation_shader (GL)
938 */
939void DrawElementsBaseVertexTestBase::init()
940{
941	TestCaseBase::init();
942
943	const glu::ContextInfo& context_info = m_context.getContextInfo();
944
945	if ((glu::isContextTypeES(m_context.getRenderContext().getType()) &&
946		 (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2)) ||
947		  context_info.isExtensionSupported("GL_EXT_draw_elements_base_vertex"))) ||
948		context_info.isExtensionSupported("GL_ARB_draw_elements_base_vertex"))
949	{
950#if defined(DE_DEBUG) && !defined(DE_COVERAGE_BUILD)
951		const glw::Functions& gl = m_context.getRenderContext().getFunctions();
952#endif
953
954		m_is_draw_elements_base_vertex_supported = true;
955
956		DE_ASSERT(gl.drawElementsBaseVertex != NULL);
957		DE_ASSERT(gl.drawElementsInstancedBaseVertex != NULL);
958		DE_ASSERT(gl.drawRangeElementsBaseVertex != NULL);
959
960		/* NOTE: glMultiDrawElementsBaseVertex() is a part of the draw_elements_base_vertex extension in GL,
961		 *       but requires a separate extension under ES.
962		 */
963		if (!glu::isContextTypeES(m_context.getRenderContext().getType()) ||
964			context_info.isExtensionSupported("GL_EXT_multi_draw_arrays"))
965		{
966			m_is_ext_multi_draw_arrays_supported = true;
967
968			DE_ASSERT(gl.multiDrawElementsBaseVertex != NULL);
969		} /* if (GL_EXT_multi_draw_arrays is supported or GL context is being tested) */
970
971		if (glu::isContextTypeES(m_context.getRenderContext().getType()))
972		{
973			/* This conformance test needs to be adjusted in order to run under < ES3.1 contexts */
974			DE_ASSERT(glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 1)));
975		}
976		else
977		{
978			m_is_vertex_attrib_binding_supported = context_info.isExtensionSupported("GL_ARB_vertex_attrib_binding");
979		}
980	} /* if (GL_{ARB, EXT}_draw_elements_base_vertex is supported) */
981
982	if ((glu::isContextTypeES(m_context.getRenderContext().getType()) &&
983		 (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2)) ||
984		  context_info.isExtensionSupported("GL_EXT_geometry_shader"))) ||
985		context_info.isExtensionSupported("GL_ARB_geometry_shader4"))
986	{
987		m_is_geometry_shader_supported = true;
988	}
989
990	if ((glu::isContextTypeES(m_context.getRenderContext().getType()) &&
991		 (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2)) ||
992		  context_info.isExtensionSupported("GL_EXT_tessellation_shader"))) ||
993		context_info.isExtensionSupported("GL_ARB_tessellation_shader"))
994	{
995		m_is_tessellation_shader_supported = true;
996	}
997
998	if (!m_is_draw_elements_base_vertex_supported)
999	{
1000		throw tcu::NotSupportedError("draw_elements_base_vertex functionality is not supported");
1001	}
1002}
1003
1004/** Sets up all ES objects required to run a single functional test case iteration.
1005 *
1006 *  @param use_clientside_vertex_data    true if the test case requires client-side buffers to
1007 *                                       back the color/vertex vertex attribute arrays; false
1008 *                                       to use buffer object storage.
1009 *  @param use_clientside_index_data     true if the test case requires client-side buffers to
1010 *                                       be used as index data source; false to use buffer object
1011 *                                       storage.
1012 *  @param use_tessellation_shader_stage true if the program object used for the test should include
1013 *                                       tessellation control & evaluation shader stages; false to
1014 *                                       not to include these shader stages in the pipeline.
1015 *  @param use_geometry_shader_stage     true if the program object used for the test should include
1016 *                                       geometry shader stage; false to not to include the shader
1017 *                                       stage in the pipeline.
1018 *  @param use_vertex_attrib_binding     true if vertex attribute bindings should be used for
1019 *                                       vertex array object configuration. This also modifies the
1020 *                                       vertex shader, so that instead of calculating vertex color
1021 *                                       on a per-vertex basis, contents of the "color" input
1022 *                                       will be used as a data source for the color data.
1023 *                                       false to use a vertex attribute array configured with
1024 *                                       a casual glVertexAttribPointer() call.
1025 * @param use_overflow_test_vertices     true if using an especially large vertex array to test
1026 *                                       overflow behavior.
1027 *
1028 *  This method can throw an exception if any of the ES calls fail.
1029 **/
1030void DrawElementsBaseVertexTestBase::setUpFunctionalTestObjects(
1031	bool use_clientside_vertex_data, bool use_clientside_index_data, bool use_tessellation_shader_stage,
1032	bool use_geometry_shader_stage, bool use_vertex_attrib_binding, bool use_overflow_test_vertices)
1033{
1034	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1035
1036	/* Set up a texture object that we will use as a color attachment */
1037	gl.genTextures(1, &m_to_base_id);
1038	gl.genTextures(1, &m_to_ref_id);
1039	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call(s) failed.");
1040
1041	const glw::GLuint  to_ids[] = { m_to_base_id, m_to_ref_id };
1042	const unsigned int n_to_ids = sizeof(to_ids) / sizeof(to_ids[0]);
1043
1044	for (unsigned int n_to_id = 0; n_to_id < n_to_ids; ++n_to_id)
1045	{
1046		gl.bindTexture(GL_TEXTURE_2D, to_ids[n_to_id]);
1047		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");
1048
1049		gl.texStorage2D(GL_TEXTURE_2D, 1, /* levels */
1050						GL_RGBA8, m_to_width, m_to_height);
1051		GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D() call failed.");
1052	}
1053
1054	/* Also set up some buffers we will use for data comparison */
1055	m_to_base_data = new unsigned char[m_to_width * m_to_height * 4 /* components */];
1056	m_to_ref_data  = new unsigned char[m_to_width * m_to_height * 4 /* components */];
1057
1058	/* Finally, for glReadPixels() operations, we need to make sure that pack alignment is set to 1 */
1059	gl.pixelStorei(GL_PACK_ALIGNMENT, 1);
1060	GLU_EXPECT_NO_ERROR(gl.getError(), "glPixelStorei() call failed.");
1061
1062	/* Proceed with framebuffer object initialization. Since we will be rendering to different
1063	 * render-targets, there's not much point in attaching any of the textures at this point.
1064	 */
1065	gl.genFramebuffers(1, &m_fbo_id);
1066	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers() call failed.");
1067
1068	gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo_id);
1069	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebufer() call failed");
1070
1071	gl.viewport(0, /* x */
1072				0, /* y */
1073				m_to_width, m_to_height);
1074	GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport() call failed");
1075
1076	/* Set up buffer object we will use for the draw calls. Use the data
1077	 * from the test specification.
1078	 *
1079	 * NOTE: If you need to change the data layout here, make sure you also update
1080	 *       m_draw_call_color_offset, m_draw_call_index*_offset, and
1081	 *       m_draw_call_vertex*_offset setter calls elsewhere.
1082	 **/
1083	if (m_bo_id == 0)
1084	{
1085		unsigned int current_offset = 0;
1086
1087		gl.genBuffers(1, &m_bo_id);
1088		GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed.");
1089
1090		gl.bindBuffer(GL_ARRAY_BUFFER, m_bo_id);
1091		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
1092
1093		gl.bufferData(GL_ARRAY_BUFFER,
1094					  m_bo_functional_data_index_size + m_bo_functional_data_vertex_size +
1095						  m_bo_functional2_data_vertex_size + m_bo_functional2_data_index_size +
1096						  m_bo_functional3_data_index_size + m_bo_functional4_data_index_size +
1097						  m_bo_functional5_data_index_size + m_bo_functional_data_color_size,
1098					  DE_NULL, /* data */
1099					  GL_STATIC_DRAW);
1100		GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
1101
1102		gl.bufferSubData(GL_ARRAY_BUFFER, current_offset, m_bo_functional_data_vertex_size,
1103						 m_bo_functional_data_vertex);
1104		current_offset += m_bo_functional_data_vertex_size;
1105
1106		gl.bufferSubData(GL_ARRAY_BUFFER, current_offset, m_bo_functional2_data_vertex_size,
1107						 m_bo_functional2_data_vertex);
1108		current_offset += m_bo_functional2_data_vertex_size;
1109
1110		gl.bufferSubData(GL_ARRAY_BUFFER, current_offset, m_bo_functional_data_index_size, m_bo_functional_data_index);
1111		current_offset += m_bo_functional_data_index_size;
1112
1113		gl.bufferSubData(GL_ARRAY_BUFFER, current_offset, m_bo_functional2_data_index_size,
1114						 m_bo_functional2_data_index);
1115		current_offset += m_bo_functional2_data_index_size;
1116
1117		gl.bufferSubData(GL_ARRAY_BUFFER, current_offset, m_bo_functional3_data_index_size,
1118						 m_bo_functional3_data_index);
1119		current_offset += m_bo_functional3_data_index_size;
1120
1121		gl.bufferSubData(GL_ARRAY_BUFFER, current_offset, m_bo_functional4_data_index_size,
1122						 m_bo_functional4_data_index);
1123		current_offset += m_bo_functional4_data_index_size;
1124
1125		gl.bufferSubData(GL_ARRAY_BUFFER, current_offset, m_bo_functional5_data_index_size,
1126						 m_bo_functional5_data_index);
1127		current_offset += m_bo_functional5_data_index_size;
1128
1129		gl.bufferSubData(GL_ARRAY_BUFFER, current_offset, m_bo_functional_data_color_size, m_bo_functional_data_color);
1130		GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferSubData() call(s) failed.");
1131	}
1132
1133	if (use_overflow_test_vertices && m_bo_id_2 == 0)
1134	{
1135		/* Create a special buffer that only has vertex data in a few slots */
1136		gl.genBuffers(1, &m_bo_id_2);
1137		GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed");
1138
1139		gl.bindBuffer(GL_ARRAY_BUFFER, m_bo_id_2);
1140		gl.bufferData(GL_ARRAY_BUFFER, 2 * 65550 * sizeof(glw::GLfloat), NULL, GL_STATIC_DRAW);
1141		GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed");
1142
1143		/*
1144		 * Upload to offset 0:     regular draw call indices for making sure ubyte
1145		 *                         and ushort indices don't wrap around too early
1146		 * Upload to offset 256:   base draw call indices of type ubyte
1147		 * Upload to offset 65536: base draw call indices of type ushort
1148		 */
1149		glw::GLfloat badVtx[] = { 0.9f,  0.9f,  -0.9f, 0.9f,  -0.9f, -0.9f, 0.9f,  -0.9f, 0.9f,  0.9f,  -0.9f, 0.9f,
1150								  -0.9f, -0.9f, 0.9f,  -0.9f, 0.9f,  0.9f,  -0.9f, 0.9f,  -0.9f, -0.9f, 0.9f,  -0.9f };
1151		gl.bufferSubData(GL_ARRAY_BUFFER, 0, sizeof(badVtx), badVtx);
1152		gl.bufferSubData(GL_ARRAY_BUFFER, 2 * 256 * sizeof(glw::GLfloat), 2 * 12 * sizeof(glw::GLfloat),
1153						 m_bo_functional_data_vertex);
1154		gl.bufferSubData(GL_ARRAY_BUFFER, 2 * 65536 * sizeof(glw::GLfloat), 2 * 12 * sizeof(glw::GLfloat),
1155						 m_bo_functional_data_vertex);
1156		GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferSubData() call failed");
1157	}
1158
1159	/* Set up the test program object */
1160	if (m_po_id == 0 || m_po_uses_gs_stage != use_geometry_shader_stage ||
1161		m_po_uses_tc_te_stages != use_tessellation_shader_stage ||
1162		m_po_uses_vertex_attrib_binding != use_vertex_attrib_binding)
1163
1164	{
1165		static const char* functional_fs_code = "${VERSION}\n"
1166												"\n"
1167												"precision highp float;\n"
1168												"\n"
1169												"in  vec4 FS_COLOR_INPUT_NAME;\n"
1170												"out vec4 result;\n"
1171												"\n"
1172												"void main()\n"
1173												"{\n"
1174												"    result = FS_COLOR_INPUT_NAME;\n"
1175												"}\n";
1176		static const char* functional_gs_code = "${VERSION}\n"
1177												"${GEOMETRY_SHADER_REQUIRE}\n"
1178												"\n"
1179												"layout(triangles)                        in;\n"
1180												"layout(triangle_strip, max_vertices = 3) out;\n"
1181												"\n"
1182												"in  vec4 GS_COLOR_INPUT_NAME[];\n"
1183												"out vec4 FS_COLOR_INPUT_NAME;\n"
1184												"\n"
1185												"void main()\n"
1186												"{\n"
1187												"    for (int n = 0; n < 3; ++n)\n"
1188												"    {\n"
1189												"        gl_Position         = vec4(gl_in[n].gl_Position.x, "
1190												"-gl_in[n].gl_Position.y, gl_in[n].gl_Position.zw);\n"
1191												"        FS_COLOR_INPUT_NAME = GS_COLOR_INPUT_NAME[n];\n"
1192												"\n"
1193												"        EmitVertex();\n"
1194												"    }\n"
1195												"\n"
1196												"    EndPrimitive();\n"
1197												"}\n";
1198		static const char* functional_tc_code =
1199			"${VERSION}\n"
1200			"${TESSELLATION_SHADER_REQUIRE}\n"
1201			"\n"
1202			"in  vec4 TC_COLOR_INPUT_NAME[];\n"
1203			"out vec4 TE_COLOR_INPUT_NAME[];\n"
1204			"\n"
1205			"layout(vertices = 3) out;\n"
1206			"\n"
1207			"void main()\n"
1208			"{\n"
1209			"    gl_out             [gl_InvocationID].gl_Position = gl_in              [gl_InvocationID].gl_Position;\n"
1210			"    TE_COLOR_INPUT_NAME[gl_InvocationID]             = TC_COLOR_INPUT_NAME[gl_InvocationID];\n"
1211			"\n"
1212			"    gl_TessLevelInner[0] = 3.0;\n"
1213			"    gl_TessLevelOuter[0] = 3.0;\n"
1214			"    gl_TessLevelOuter[1] = 3.0;\n"
1215			"    gl_TessLevelOuter[2] = 3.0;\n"
1216			"}\n";
1217		static const char* functional_te_code =
1218			"${VERSION}\n"
1219			"\n"
1220			"${TESSELLATION_SHADER_REQUIRE}\n"
1221			"\n"
1222			"layout(triangles, equal_spacing, cw) in;\n"
1223			"\n"
1224			"in  vec4 TE_COLOR_INPUT_NAME[];\n"
1225			"out vec4 TE_COLOR_OUTPUT_NAME;\n"
1226			"\n"
1227			"void main()\n"
1228			"{\n"
1229			"    vec2 p1 = gl_in[0].gl_Position.xy;\n"
1230			"    vec2 p2 = gl_in[1].gl_Position.xy;\n"
1231			"    vec2 p3 = gl_in[2].gl_Position.xy;\n"
1232			"\n"
1233			"    TE_COLOR_OUTPUT_NAME = TE_COLOR_INPUT_NAME[0] + TE_COLOR_INPUT_NAME[1] + TE_COLOR_INPUT_NAME[2];\n"
1234			"    gl_Position          = vec4(gl_TessCoord.x * p1.x + gl_TessCoord.y * p2.x + gl_TessCoord.z * p3.x,\n"
1235			"                                gl_TessCoord.x * p1.y + gl_TessCoord.y * p2.y + gl_TessCoord.z * p3.y,\n"
1236			"                                0.0,\n"
1237			"                                1.0);\n"
1238			"}\n";
1239		static const char* functional_vs_code = "${VERSION}\n"
1240												"\n"
1241												"out vec4 VS_COLOR_OUTPUT_NAME;\n"
1242												"in  vec4 vertex;\n"
1243												"\n"
1244												"OPTIONAL_USE_VERTEX_ATTRIB_BINDING_DEFINITIONS\n"
1245												"\n"
1246												"void main()\n"
1247												"{\n"
1248												"    float vertex_id_float = float(gl_VertexID);\n"
1249												"\n"
1250												"#ifdef USE_VERTEX_ATTRIB_BINDING\n"
1251												"    vec4  color           = in_color;\n"
1252												"#else\n"
1253												"    vec4  color           = vec4(vertex_id_float / 7.0,\n"
1254												"                                 vertex_id_float / 3.0,\n"
1255												"                                 vertex_id_float / 17.0,\n"
1256												"                                 1.0);\n"
1257												"#endif\n"
1258												"    float scale           = (gl_InstanceID == 0) ? 1.0 :\n"
1259												"                            (gl_InstanceID == 1) ? 0.8 :\n"
1260												"                                                   0.5;\n"
1261												"\n"
1262												"    VS_COLOR_OUTPUT_NAME = color;\n"
1263												"    gl_Position          = vec4(vertex.xy * scale, vertex.zw);\n"
1264												"}\n";
1265
1266		/* Release a program object if one has already been set up for the running test */
1267		deinitProgramAndShaderObjects();
1268
1269		/* Replace the tokens with actual variable names */
1270		std::string fs_body					  = specializeShader(1, &functional_fs_code);
1271		std::string fs_color_input_name_token = "FS_COLOR_INPUT_NAME";
1272		std::string fs_color_input_name_token_value;
1273		std::string gs_body					  = specializeShader(1, &functional_gs_code);
1274		std::string gs_color_input_name_token = "GS_COLOR_INPUT_NAME";
1275		std::string gs_color_input_name_token_value;
1276		std::string tc_body					  = specializeShader(1, &functional_tc_code);
1277		std::string tc_color_input_name_token = "TC_COLOR_INPUT_NAME";
1278		std::string tc_color_input_name_token_value;
1279		std::string te_body					  = specializeShader(1, &functional_te_code);
1280		std::string te_color_input_name_token = "TE_COLOR_INPUT_NAME";
1281		std::string te_color_input_name_token_value;
1282		std::string te_color_output_name_token = "TE_COLOR_OUTPUT_NAME";
1283		std::string te_color_output_name_token_value;
1284		std::string vs_body					   = specializeShader(1, &functional_vs_code);
1285		std::string vs_color_output_name_token = "VS_COLOR_OUTPUT_NAME";
1286		std::string vs_color_output_name_token_value;
1287		std::string vs_optional_use_vertex_attrib_binding_definitions_token =
1288			"OPTIONAL_USE_VERTEX_ATTRIB_BINDING_DEFINITIONS";
1289		std::string vs_optional_use_vertex_attrib_binding_definitions_token_value;
1290
1291		std::string*	   bodies[] = { &fs_body, &gs_body, &tc_body, &te_body, &vs_body };
1292		const unsigned int n_bodies = sizeof(bodies) / sizeof(bodies[0]);
1293
1294		std::string* token_value_pairs[] = { &fs_color_input_name_token,
1295											 &fs_color_input_name_token_value,
1296											 &gs_color_input_name_token,
1297											 &gs_color_input_name_token_value,
1298											 &tc_color_input_name_token,
1299											 &tc_color_input_name_token_value,
1300											 &te_color_input_name_token,
1301											 &te_color_input_name_token_value,
1302											 &te_color_output_name_token,
1303											 &te_color_output_name_token_value,
1304											 &vs_color_output_name_token,
1305											 &vs_color_output_name_token_value,
1306											 &vs_optional_use_vertex_attrib_binding_definitions_token,
1307											 &vs_optional_use_vertex_attrib_binding_definitions_token_value };
1308		const unsigned int n_token_value_pairs =
1309			sizeof(token_value_pairs) / sizeof(token_value_pairs[0]) / 2 /* token+value */;
1310
1311		if (!use_tessellation_shader_stage)
1312		{
1313			if (!use_geometry_shader_stage)
1314			{
1315				/* Geometry & tessellation shader stages are not required.
1316				 *
1317				 * NOTE: This code-path is also used by Functional Test VII which verifies that
1318				 *       vertex attribute bindings work correctly with basevertex draw calls.
1319				 *       The test only uses FS & VS in its rendering pipeline and consumes a color
1320				 *       taken from an enabled vertex attribute array instead of a vector value
1321				 *       calculated in vertex shader stage,
1322				 */
1323				vs_color_output_name_token_value = "out_vs_color";
1324				fs_color_input_name_token_value  = vs_color_output_name_token_value;
1325
1326				if (use_vertex_attrib_binding)
1327				{
1328					vs_optional_use_vertex_attrib_binding_definitions_token_value =
1329						"#define USE_VERTEX_ATTRIB_BINDING\n"
1330						"in vec4 in_color;\n";
1331				}
1332			} /* if (!use_geometry_shader_stage) */
1333			else
1334			{
1335				/* Geometry shader stage is needed, but tessellation shader stage
1336				 * can be skipped */
1337				fs_color_input_name_token_value  = "out_fs_color";
1338				gs_color_input_name_token_value  = "out_vs_color";
1339				vs_color_output_name_token_value = "out_vs_color";
1340
1341				DE_ASSERT(!use_vertex_attrib_binding);
1342			}
1343		} /* if (!use_tessellation_shader_stage) */
1344		else
1345		{
1346			DE_ASSERT(!use_vertex_attrib_binding);
1347
1348			if (!use_geometry_shader_stage)
1349			{
1350				/* Tessellation shader stage is needed, but geometry shader stage
1351				 * can be skipped */
1352				fs_color_input_name_token_value  = "out_fs_color";
1353				tc_color_input_name_token_value  = "out_vs_color";
1354				te_color_input_name_token_value  = "out_tc_color";
1355				te_color_output_name_token_value = "out_fs_color";
1356				vs_color_output_name_token_value = "out_vs_color";
1357			} /* if (!use_geometry_shader_stage) */
1358			else
1359			{
1360				/* Both tessellation and geometry shader stages are needed */
1361				fs_color_input_name_token_value  = "out_fs_color";
1362				gs_color_input_name_token_value  = "out_te_color";
1363				tc_color_input_name_token_value  = "out_vs_color";
1364				te_color_input_name_token_value  = "out_tc_color";
1365				te_color_output_name_token_value = "out_te_color";
1366				vs_color_output_name_token_value = "out_vs_color";
1367			}
1368		}
1369
1370		for (unsigned int n_body = 0; n_body < n_bodies; ++n_body)
1371		{
1372			std::string* body_ptr = bodies[n_body];
1373
1374			for (unsigned int n_token_value_pair = 0; n_token_value_pair < n_token_value_pairs; ++n_token_value_pair)
1375			{
1376				std::string token		   = *token_value_pairs[2 * n_token_value_pair + 0];
1377				std::size_t token_location = std::string::npos;
1378				std::string value		   = *token_value_pairs[2 * n_token_value_pair + 1];
1379
1380				while ((token_location = body_ptr->find(token)) != std::string::npos)
1381				{
1382					body_ptr->replace(token_location, token.length(), value);
1383				} /* while (tokens are found) */
1384			}	 /* for (all token+value pairs) */
1385		}		  /* for (all bodies) */
1386
1387		/* Build the actual program */
1388		buildProgram(fs_body.c_str(), vs_body.c_str(), use_tessellation_shader_stage ? tc_body.c_str() : DE_NULL,
1389					 use_tessellation_shader_stage ? te_body.c_str() : DE_NULL,
1390					 use_geometry_shader_stage ? gs_body.c_str() : DE_NULL);
1391
1392		m_po_uses_gs_stage				= use_geometry_shader_stage;
1393		m_po_uses_tc_te_stages			= use_tessellation_shader_stage;
1394		m_po_uses_vertex_attrib_binding = use_vertex_attrib_binding;
1395	}
1396
1397	/* Set up the vertex array object */
1398	if (m_vao_id != 0)
1399	{
1400		gl.deleteVertexArrays(1, &m_vao_id);
1401		GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteVertexArrays() call failed.");
1402
1403		m_vao_id = 0;
1404	}
1405
1406	if (!use_clientside_vertex_data)
1407	{
1408		gl.genVertexArrays(1, &m_vao_id);
1409		GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
1410	}
1411	gl.bindVertexArray(m_vao_id);
1412	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
1413
1414	if (m_po_color_attribute_location != -1)
1415	{
1416		DE_ASSERT(use_vertex_attrib_binding);
1417
1418		gl.enableVertexAttribArray(m_po_color_attribute_location);
1419	}
1420
1421	gl.enableVertexAttribArray(m_po_vertex_attribute_location);
1422	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray() call(s) failed.");
1423
1424	/* Configure the VAO */
1425	if (use_clientside_index_data)
1426	{
1427		gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
1428		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
1429	}
1430	else
1431	{
1432		gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_bo_id);
1433		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
1434	}
1435
1436	if (use_clientside_vertex_data)
1437	{
1438		gl.bindBuffer(GL_ARRAY_BUFFER, 0);
1439		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
1440	}
1441	else
1442	{
1443		gl.bindBuffer(GL_ARRAY_BUFFER, use_overflow_test_vertices ? m_bo_id_2 : m_bo_id);
1444		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
1445	}
1446
1447	if (!use_vertex_attrib_binding)
1448	{
1449		DE_ASSERT(m_po_color_attribute_location == -1);
1450
1451		gl.vertexAttribPointer(m_po_vertex_attribute_location, 2, /* size */
1452							   GL_FLOAT, GL_FALSE,				  /* normalized */
1453							   0,								  /* stride */
1454							   m_draw_call_vertex_offset);
1455		GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer() call failed.");
1456	} /* if (!use_vertex_attrib_binding) */
1457	else
1458	{
1459		DE_ASSERT(m_po_color_attribute_location != -1);
1460		DE_ASSERT(m_draw_call_vertex_offset < m_draw_call_color_offset);
1461
1462		gl.vertexAttribFormat(m_po_color_attribute_location, 2, /* size */
1463							  GL_FLOAT,							/* type */
1464							  GL_FALSE,							/* normalized */
1465							  (glw::GLuint)((const glw::GLubyte*)m_draw_call_color_offset -
1466											(const glw::GLubyte*)m_draw_call_vertex_offset));
1467		gl.vertexAttribFormat(m_po_vertex_attribute_location, 2, /* size */
1468							  GL_FLOAT,							 /* type */
1469							  GL_FALSE,							 /* normalized */
1470							  0);								 /* relativeoffset */
1471		GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribFormat() call(s) failed.");
1472
1473		gl.vertexAttribBinding(m_po_color_attribute_location, 0);  /* bindingindex */
1474		gl.vertexAttribBinding(m_po_vertex_attribute_location, 0); /* bindingindex */
1475		GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribBinding() call(s) failed.");
1476
1477		gl.bindVertexBuffer(0, /* bindingindex */
1478							(use_clientside_vertex_data) ? 0 : (use_overflow_test_vertices ? m_bo_id_2 : m_bo_id),
1479							(glw::GLintptr)m_draw_call_vertex_offset, sizeof(float) * 2);
1480		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexBuffer() call failed.");
1481	}
1482
1483	/* Bind the program object to the rendering context */
1484	gl.useProgram(m_po_id);
1485	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
1486}
1487
1488/** Sets up all ES objects required to run a single negative test case iteration.
1489 *
1490 *  @param use_clientside_vertex_data    true if the test case requires client-side buffers to
1491 *                                       back the color/vertex vertex attribute arrays; false
1492 *                                       to use buffer object storage.
1493 *  @param use_clientside_index_data     true if the test case requires client-side buffers to
1494 *                                       be used as index data source; false to use buffer object
1495 *                                       storage.
1496 */
1497void DrawElementsBaseVertexTestBase::setUpNegativeTestObjects(bool use_clientside_vertex_data,
1498															  bool use_clientside_index_data)
1499{
1500	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1501
1502	/* Set up buffer object we will use for the draw calls. Use the data
1503	 * from the test specification */
1504	if (m_bo_id == 0)
1505	{
1506		gl.genBuffers(1, &m_bo_id);
1507		GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed.");
1508
1509		gl.bindBuffer(GL_ARRAY_BUFFER, m_bo_id);
1510		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
1511
1512		gl.bufferData(GL_ARRAY_BUFFER, m_bo_negative_data_index_size + m_bo_negative_data_vertex_size,
1513					  DE_NULL, /* data */
1514					  GL_STATIC_DRAW);
1515		GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
1516
1517		gl.bufferSubData(GL_ARRAY_BUFFER, 0, /* offset */
1518						 m_bo_negative_data_vertex_size, m_bo_negative_data_vertex);
1519		gl.bufferSubData(GL_ARRAY_BUFFER, m_bo_negative_data_vertex_size, /* offset */
1520						 m_bo_negative_data_index_size, m_bo_negative_data_index);
1521		GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferSubData() call(s) failed.");
1522	}
1523
1524	if (use_clientside_index_data)
1525	{
1526		m_draw_call_index_offset = m_bo_negative_data_index;
1527	}
1528	else
1529	{
1530		m_draw_call_index_offset = (const glw::GLuint*)(deUintptr)m_bo_negative_data_vertex_size;
1531	}
1532
1533	if (use_clientside_vertex_data)
1534	{
1535		m_draw_call_vertex_offset = m_bo_negative_data_vertex;
1536	}
1537	else
1538	{
1539		m_draw_call_vertex_offset = DE_NULL;
1540	}
1541
1542	/* Set up the test program object */
1543	if (m_po_id == 0)
1544	{
1545		static const char* negative_fs_code = "${VERSION}\n"
1546											  "precision highp float;\n"
1547											  "\n"
1548											  "out vec4 result;\n"
1549											  "\n"
1550											  "void main()\n"
1551											  "{\n"
1552											  "    result = vec4(1.0);\n"
1553											  "}\n";
1554		static const char* negative_vs_code = "${VERSION}\n"
1555											  "\n"
1556											  "in vec4 vertex;\n"
1557											  "\n"
1558											  "void main()\n"
1559											  "{\n"
1560											  "    gl_Position = vertex;\n"
1561											  "}\n";
1562
1563		std::string fs_specialized_code		= specializeShader(1, &negative_fs_code);
1564		const char* fs_specialized_code_raw = fs_specialized_code.c_str();
1565		std::string vs_specialized_code		= specializeShader(1, &negative_vs_code);
1566		const char* vs_specialized_code_raw = vs_specialized_code.c_str();
1567
1568		buildProgram(fs_specialized_code_raw, vs_specialized_code_raw, DE_NULL, /* tc_code */
1569					 DE_NULL,													/* te_code */
1570					 DE_NULL);													/* gs_code */
1571	}
1572
1573	/* Set up a vertex array object */
1574	if (m_vao_id == 0)
1575	{
1576		gl.genVertexArrays(1, &m_vao_id);
1577		GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
1578
1579		gl.bindVertexArray(m_vao_id);
1580		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
1581
1582		gl.enableVertexAttribArray(m_po_vertex_attribute_location);
1583		GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray() call failed.");
1584	}
1585
1586	/* Configure the VAO */
1587	if (use_clientside_index_data)
1588	{
1589		gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
1590		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
1591	}
1592	else
1593	{
1594		gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_bo_id);
1595		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
1596	}
1597
1598	if (use_clientside_vertex_data)
1599	{
1600		gl.bindBuffer(GL_ARRAY_BUFFER, 0);
1601		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
1602
1603		gl.bindVertexArray(0);
1604		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
1605	}
1606	else
1607	{
1608		gl.bindBuffer(GL_ARRAY_BUFFER, m_bo_id);
1609		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
1610	}
1611
1612	gl.vertexAttribPointer(m_po_vertex_attribute_location, 2, /* size */
1613						   GL_FLOAT, GL_FALSE,				  /* normalized */
1614						   0,								  /* stride */
1615						   m_draw_call_vertex_offset);
1616	GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer() call failed.");
1617
1618	/* Bind the program object to the rendering context */
1619	gl.useProgram(m_po_id);
1620	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
1621}
1622
1623/** Constructor.
1624 *
1625 *  @param context Rendering context handle.
1626 **/
1627DrawElementsBaseVertexFunctionalCorrectBaseVertexBehavior::DrawElementsBaseVertexFunctionalCorrectBaseVertexBehavior(
1628	Context& context, const ExtParameters& extParams)
1629	: DrawElementsBaseVertexTestBase(context, extParams, "basevertex_behavior1",
1630									 "Verifies basevertex draw calls work correctly for a number of "
1631									 "different rendering pipeline and VAO configurations")
1632{
1633	/* Left blank on purpose */
1634}
1635
1636/** Sets up test case descriptors for the test instance. These will later be used
1637 *  as input for DrawElementsBaseVertexTestBase::executeTestCases(), which performs
1638 *  the actual testing.
1639 **/
1640void DrawElementsBaseVertexFunctionalCorrectBaseVertexBehavior::setUpTestCases()
1641{
1642	/* Set up test case descriptors */
1643	const glw::GLint   basevertex_values[] = { 10, 0 };
1644	const unsigned int n_basevertex_values = sizeof(basevertex_values) / sizeof(basevertex_values[0]);
1645
1646	/* The test needs to be run in two iterations, using client-side memory and buffer object
1647	 * for index data respectively
1648	 */
1649	for (int vao_iteration = 0; vao_iteration < 2; ++vao_iteration)
1650	{
1651		/* Skip client-side vertex array as gl_VertexID is undefined when no buffer bound to ARRAY_BUFFER
1652		 *  See section 11.1.3.9 in OpenGL ES 3.1 spec
1653		 */
1654		bool use_clientside_vertex_data = 0;
1655		bool use_clientside_index_data  = ((vao_iteration & (1 << 0)) != 0);
1656
1657		/* OpenGL does not support client-side data. */
1658		if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
1659		{
1660			if (use_clientside_index_data || use_clientside_vertex_data)
1661			{
1662				continue;
1663			}
1664		}
1665
1666		/* Compute the offsets */
1667		computeVBODataOffsets(use_clientside_index_data, use_clientside_vertex_data);
1668
1669		/* There are two index data sets we need to iterate over */
1670		const glw::GLuint* index_offsets[] = { m_draw_call_index_offset, m_draw_call_index2_offset };
1671		const unsigned int n_index_offsets = sizeof(index_offsets) / sizeof(index_offsets[0]);
1672
1673		for (unsigned int n_index_offset = 0; n_index_offset < n_index_offsets; ++n_index_offset)
1674		{
1675			const glw::GLuint* current_index_offset = index_offsets[n_index_offset];
1676
1677			/* We need to test four different functions:
1678			 *
1679			 * a)    glDrawElementsBaseVertex()             (GL)
1680			 *    or glDrawElementsBaseVertexEXT()          (ES)
1681			 * b)    glDrawRangeElementsBaseVertex()        (GL)
1682			 *    or glDrawRangeElementsBaseVertexEXT()     (ES)
1683			 * c)    glDrawElementsInstancedBaseVertex()    (GL)
1684			 *    or glDrawElementsInstancedBaseVertexEXT() (ES)
1685			 * d)    glMultiDrawElementsBaseVertex()        (GL)
1686			 *    or glMultiDrawElementsBaseVertexEXT()     (ES) (if supported)
1687			 **/
1688			for (int n_function = 0; n_function < FUNCTION_COUNT; ++n_function)
1689			{
1690				/* Do not try to use the multi draw call if relevant extension is
1691				 * not supported. */
1692				if (!m_is_ext_multi_draw_arrays_supported && n_function == FUNCTION_GL_MULTI_DRAW_ELEMENTS_BASE_VERTEX)
1693				{
1694					continue;
1695				}
1696
1697				/* We need to run the test for a number of different basevertex values. */
1698				for (unsigned int n_basevertex_value = 0; n_basevertex_value < n_basevertex_values;
1699					 ++n_basevertex_value)
1700				{
1701					/* Finally, we want to verify that basevertex draw calls work correctly both when vertex attribute
1702					 * bindings are enabled and disabled */
1703					bool		 vertex_attrib_binding_statuses[] = { false, true };
1704					unsigned int n_vertex_attrib_binding_statuses =
1705						sizeof(vertex_attrib_binding_statuses) / sizeof(vertex_attrib_binding_statuses[0]);
1706
1707					for (unsigned int n_vertex_attrib_binding_status = 0;
1708						 n_vertex_attrib_binding_status < n_vertex_attrib_binding_statuses;
1709						 ++n_vertex_attrib_binding_status)
1710					{
1711						bool use_vertex_attrib_binding = vertex_attrib_binding_statuses[n_vertex_attrib_binding_status];
1712
1713						/* Under GL, "vertex attrib binding" functionality is only available if GL_ARB_vertex_attrib_binding
1714						 * extension is supported.
1715						 */
1716						if (!m_is_vertex_attrib_binding_supported && use_vertex_attrib_binding)
1717						{
1718							continue;
1719						}
1720
1721						/* Prepare a few arrays so that we can handle the multi draw call and its emulated version.. */
1722						const glw::GLsizei multi_draw_call_count_array[3]   = { 3, 6, 3 };
1723						const glw::GLuint* multi_draw_call_indices_array[3] = {
1724							(glw::GLuint*)(current_index_offset), (glw::GLuint*)(current_index_offset + 3),
1725							(glw::GLuint*)(current_index_offset + 9)
1726						};
1727
1728						/* Reference texture should always reflect basevertex=10 behavior. */
1729						const glw::GLuint  regular_draw_call_offset					 = basevertex_values[0];
1730						const glw::GLuint* regular_multi_draw_call_offseted_array[3] = {
1731							multi_draw_call_indices_array[0] + regular_draw_call_offset,
1732							multi_draw_call_indices_array[1] + regular_draw_call_offset,
1733							multi_draw_call_indices_array[2] + regular_draw_call_offset,
1734						};
1735
1736						/* Construct the test case descriptor */
1737						_test_case new_test_case;
1738
1739						new_test_case.basevertex			   = basevertex_values[n_basevertex_value];
1740						new_test_case.function_type			   = (_function_type)n_function;
1741						new_test_case.index_offset			   = current_index_offset;
1742						new_test_case.range_start			   = n_index_offset == 0 ? 0 : 10;
1743						new_test_case.range_end				   = n_index_offset == 0 ? 22 : 32;
1744						new_test_case.index_type			   = GL_UNSIGNED_INT;
1745						new_test_case.primitive_mode		   = GL_TRIANGLES;
1746						new_test_case.regular_draw_call_offset = basevertex_values[0];
1747						new_test_case.should_base_texture_match_reference_texture =
1748							((glw::GLuint)new_test_case.basevertex == new_test_case.regular_draw_call_offset);
1749						new_test_case.use_clientside_index_data		= use_clientside_index_data;
1750						new_test_case.use_clientside_vertex_data	= use_clientside_vertex_data;
1751						new_test_case.use_geometry_shader_stage		= false;
1752						new_test_case.use_tessellation_shader_stage = false;
1753						new_test_case.use_vertex_attrib_binding		= use_vertex_attrib_binding;
1754
1755						memcpy(new_test_case.multi_draw_call_count_array, multi_draw_call_count_array,
1756							   sizeof(multi_draw_call_count_array));
1757						memcpy(new_test_case.multi_draw_call_indices_array, multi_draw_call_indices_array,
1758							   sizeof(multi_draw_call_indices_array));
1759						memcpy(new_test_case.regular_multi_draw_call_offseted_array,
1760							   regular_multi_draw_call_offseted_array, sizeof(regular_multi_draw_call_offseted_array));
1761
1762						m_test_cases.push_back(new_test_case);
1763					} /* for (all vertex_attrib_binding statuses) */
1764				}	 /* for (all basevertex values) */
1765			}		  /* for (all four functions) */
1766		}			  /* for (all index data sets) */
1767	}				  /* for (all VAO iterations) */
1768}
1769
1770/** Executes test iteration.
1771 *
1772 *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
1773 */
1774tcu::TestNode::IterateResult DrawElementsBaseVertexFunctionalCorrectBaseVertexBehavior::iterate()
1775{
1776	setUpTestCases();
1777	executeTestCases();
1778
1779	/* Test case passed */
1780	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1781
1782	return STOP;
1783}
1784
1785/** Constructor.
1786 *
1787 *  @param context Rendering context handle.
1788 **/
1789DrawElementsBaseVertexFunctionalCorrectBaseVertexBehavior2::DrawElementsBaseVertexFunctionalCorrectBaseVertexBehavior2(
1790	Context& context, const ExtParameters& extParams)
1791	: DrawElementsBaseVertexTestBase(context, extParams, "basevertex_behavior2",
1792									 "Verifies basevertex draw calls work correctly for a number of "
1793									 "different rendering pipeline and VAO configurations. Uses slightly "
1794									 "different data set than basevertex_behavior.")
1795{
1796	/* Left blank on purpose */
1797}
1798
1799/** Sets up test case descriptors for the test instance. These will later be used
1800 *  as input for DrawElementsBaseVertexTestBase::executeTestCases(), which performs
1801 *  the actual testing.
1802 **/
1803void DrawElementsBaseVertexFunctionalCorrectBaseVertexBehavior2::setUpTestCases()
1804{
1805	/* Set up test case descriptors */
1806	const glw::GLint basevertex = 5;
1807
1808	/* The test needs to be run in two iterations, using client-side memory and buffer object
1809	 * for index data respectively
1810	 */
1811	for (int vao_iteration = 0; vao_iteration < 2; ++vao_iteration)
1812	{
1813		/* Skip client-side vertex array as gl_VertexID is undefined when no buffer bound to ARRAY_BUFFER
1814		 *  See section 11.1.3.9 in OpenGL ES 3.1 spec
1815		 */
1816		bool use_clientside_vertex_data = 0;
1817		bool use_clientside_index_data  = ((vao_iteration & (1 << 0)) != 0);
1818
1819		/* OpenGL does not support client-side data. */
1820		if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
1821		{
1822			if (use_clientside_index_data || use_clientside_vertex_data)
1823			{
1824				continue;
1825			}
1826		}
1827
1828		/* Compute the offsets */
1829		computeVBODataOffsets(use_clientside_index_data, use_clientside_vertex_data);
1830
1831		/* We need to test four different functions:
1832		 *
1833		 * a)    glDrawElementsBaseVertex()             (GL)
1834		 *    or glDrawElementsBaseVertexEXT()          (ES)
1835		 * b)    glDrawRangeElementsBaseVertex()        (GL)
1836		 *    or glDrawRangeElementsBaseVertexEXT()     (ES)
1837		 * c)    glDrawElementsInstancedBaseVertex()    (GL)
1838		 *    or glDrawElementsInstancedBaseVertexEXT() (ES)
1839		 * d)    glMultiDrawElementsBaseVertex()        (GL)
1840		 *    or glMultiDrawElementsBaseVertexEXT()     (ES) (if supported)
1841		 **/
1842		for (int n_function = 0; n_function < FUNCTION_COUNT; ++n_function)
1843		{
1844			/* Do not try to use the multi draw call if relevant extension is
1845			 * not supported. */
1846			if (!m_is_ext_multi_draw_arrays_supported && n_function == FUNCTION_GL_MULTI_DRAW_ELEMENTS_BASE_VERTEX)
1847			{
1848				continue;
1849			}
1850
1851			/* Prepare a few arrays so that we can handle the multi draw call and its emulated version.. */
1852			const glw::GLsizei multi_draw_call_count_array[3]   = { 3, 6, 3 };
1853			const glw::GLuint* multi_draw_call_indices_array[3] = { (glw::GLuint*)(m_draw_call_index_offset),
1854																	(glw::GLuint*)(m_draw_call_index_offset + 3),
1855																	(glw::GLuint*)(m_draw_call_index_offset + 9) };
1856
1857			/* Reference texture should always reflect basevertex=10 behavior. */
1858			const glw::GLuint  regular_draw_call_offset					 = 0;
1859			const glw::GLuint* regular_multi_draw_call_offseted_array[3] = {
1860				multi_draw_call_indices_array[0] + regular_draw_call_offset,
1861				multi_draw_call_indices_array[1] + regular_draw_call_offset,
1862				multi_draw_call_indices_array[2] + regular_draw_call_offset,
1863			};
1864
1865			/* Construct the test case descriptor */
1866			_test_case new_test_case;
1867
1868			new_test_case.basevertex			   = basevertex;
1869			new_test_case.function_type			   = (_function_type)n_function;
1870			new_test_case.index_offset			   = m_draw_call_index_offset;
1871			new_test_case.range_start			   = 0;
1872			new_test_case.range_end				   = 22;
1873			new_test_case.index_type			   = GL_UNSIGNED_INT;
1874			new_test_case.primitive_mode		   = GL_TRIANGLES;
1875			new_test_case.regular_draw_call_offset = regular_draw_call_offset;
1876			new_test_case.should_base_texture_match_reference_texture =
1877				((glw::GLuint)new_test_case.basevertex == new_test_case.regular_draw_call_offset);
1878			new_test_case.use_clientside_index_data		= use_clientside_index_data;
1879			new_test_case.use_clientside_vertex_data	= use_clientside_vertex_data;
1880			new_test_case.use_geometry_shader_stage		= false;
1881			new_test_case.use_tessellation_shader_stage = false;
1882			new_test_case.use_vertex_attrib_binding		= false;
1883
1884			memcpy(new_test_case.multi_draw_call_count_array, multi_draw_call_count_array,
1885				   sizeof(multi_draw_call_count_array));
1886			memcpy(new_test_case.multi_draw_call_indices_array, multi_draw_call_indices_array,
1887				   sizeof(multi_draw_call_indices_array));
1888			memcpy(new_test_case.regular_multi_draw_call_offseted_array, regular_multi_draw_call_offseted_array,
1889				   sizeof(regular_multi_draw_call_offseted_array));
1890
1891			m_test_cases.push_back(new_test_case);
1892		} /* for (all four functions) */
1893	}	 /* for (all VAO iterations) */
1894}
1895
1896/** Executes test iteration.
1897 *
1898 *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
1899 */
1900tcu::TestNode::IterateResult DrawElementsBaseVertexFunctionalCorrectBaseVertexBehavior2::iterate()
1901{
1902	setUpTestCases();
1903	executeTestCases();
1904
1905	/* Test case passed */
1906	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1907
1908	return STOP;
1909}
1910
1911/** Constructor.
1912 *
1913 *  @param context Rendering context handle.
1914 **/
1915DrawElementsBaseVertexFunctionalCorrectBaseVertexBehaviorUnderflow::
1916	DrawElementsBaseVertexFunctionalCorrectBaseVertexBehaviorUnderflow(Context& context, const ExtParameters& extParams)
1917	: DrawElementsBaseVertexTestBase(context, extParams, "underflow",
1918									 "Verifies basevertex draw calls work correctly for negative "
1919									 "basevertex values")
1920{
1921	/* Left blank on purpose */
1922}
1923
1924/** Sets up test case descriptors for the test instance. These will later be used
1925 *  as input for DrawElementsBaseVertexTestBase::executeTestCases(), which performs
1926 *  the actual testing.
1927 **/
1928void DrawElementsBaseVertexFunctionalCorrectBaseVertexBehaviorUnderflow::setUpTestCases()
1929{
1930	/* Set up test case descriptors */
1931	const glw::GLint basevertex = -10;
1932
1933	/* The test needs to be run in two iterations, using client-side memory and buffer object
1934	 * for index data respectively
1935	 */
1936	for (int vao_iteration = 0; vao_iteration < 2; ++vao_iteration)
1937	{
1938		/* Skip client-side vertex array as gl_VertexID is undefined when no buffer bound to ARRAY_BUFFER
1939		 *  See section 11.1.3.9 in OpenGL ES 3.1 spec
1940		 */
1941		bool use_clientside_vertex_data = 0;
1942		bool use_clientside_index_data  = ((vao_iteration & (1 << 0)) != 0);
1943
1944		/* OpenGL does not support client-side data. */
1945		if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
1946		{
1947			if (use_clientside_index_data || use_clientside_vertex_data)
1948			{
1949				continue;
1950			}
1951		}
1952
1953		/* Compute the offsets */
1954		computeVBODataOffsets(use_clientside_index_data, use_clientside_vertex_data);
1955
1956		/* We need to test four different functions:
1957		 *
1958		 * a)    glDrawElementsBaseVertex()             (GL)
1959		 *    or glDrawElementsBaseVertexEXT()          (ES)
1960		 * b)    glDrawRangeElementsBaseVertex()        (GL)
1961		 *    or glDrawRangeElementsBaseVertexEXT()     (ES)
1962		 * c)    glDrawElementsInstancedBaseVertex()    (GL)
1963		 *    or glDrawElementsInstancedBaseVertexEXT() (ES)
1964		 * d)    glMultiDrawElementsBaseVertex()        (GL)
1965		 *    or glMultiDrawElementsBaseVertexEXT()     (ES) (if supported)
1966		 **/
1967		for (int n_function = 0; n_function < FUNCTION_COUNT; ++n_function)
1968		{
1969			/* Do not try to use the multi draw call if relevant extension is
1970			 * not supported. */
1971			if (!m_is_ext_multi_draw_arrays_supported && n_function == FUNCTION_GL_MULTI_DRAW_ELEMENTS_BASE_VERTEX)
1972			{
1973				continue;
1974			}
1975
1976			/* Prepare a few arrays so that we can handle the multi draw call and its emulated version.. */
1977			unsigned int offset_from_10_to_0_index = 23; /* this offset moves us from the start index of 10 to a zero
1978			 * index, given the second index data set we will be using.
1979			 * Please see declaration of functional2_index_data if you
1980			 * need to verify this by yourself. */
1981
1982			const glw::GLsizei multi_draw_call_count_array[3]   = { 3, 6, 3 };
1983			const glw::GLuint* multi_draw_call_indices_array[3] = { (glw::GLuint*)(m_draw_call_index2_offset),
1984																	(glw::GLuint*)(m_draw_call_index2_offset + 3),
1985																	(glw::GLuint*)(m_draw_call_index2_offset + 9) };
1986			const glw::GLuint* regular_multi_draw_call_offseted_array[3] = {
1987				multi_draw_call_indices_array[0] + offset_from_10_to_0_index,
1988				multi_draw_call_indices_array[1] + offset_from_10_to_0_index,
1989				multi_draw_call_indices_array[2] + offset_from_10_to_0_index,
1990			};
1991
1992			/* Construct the test case descriptor */
1993			_test_case new_test_case;
1994
1995			new_test_case.basevertex								  = basevertex;
1996			new_test_case.function_type								  = (_function_type)n_function;
1997			new_test_case.index_offset								  = m_draw_call_index2_offset;
1998			new_test_case.range_start								  = 10;
1999			new_test_case.range_end									  = 32;
2000			new_test_case.index_type								  = GL_UNSIGNED_INT;
2001			new_test_case.primitive_mode							  = GL_TRIANGLES;
2002			new_test_case.regular_draw_call_offset					  = offset_from_10_to_0_index;
2003			new_test_case.should_base_texture_match_reference_texture = true;
2004			new_test_case.use_clientside_index_data					  = use_clientside_index_data;
2005			new_test_case.use_clientside_vertex_data				  = use_clientside_vertex_data;
2006			new_test_case.use_geometry_shader_stage					  = false;
2007			new_test_case.use_tessellation_shader_stage				  = false;
2008			new_test_case.use_vertex_attrib_binding					  = false;
2009
2010			memcpy(new_test_case.multi_draw_call_count_array, multi_draw_call_count_array,
2011				   sizeof(multi_draw_call_count_array));
2012			memcpy(new_test_case.multi_draw_call_indices_array, multi_draw_call_indices_array,
2013				   sizeof(multi_draw_call_indices_array));
2014			memcpy(new_test_case.regular_multi_draw_call_offseted_array, regular_multi_draw_call_offseted_array,
2015				   sizeof(regular_multi_draw_call_offseted_array));
2016
2017			m_test_cases.push_back(new_test_case);
2018		} /* for (all four functions) */
2019	}	 /* for (all VAO iterations) */
2020}
2021
2022/** Executes test iteration.
2023 *
2024 *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
2025 */
2026tcu::TestNode::IterateResult DrawElementsBaseVertexFunctionalCorrectBaseVertexBehaviorUnderflow::iterate()
2027{
2028	setUpTestCases();
2029	executeTestCases();
2030
2031	/* Test case passed */
2032	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2033
2034	return STOP;
2035}
2036
2037/** Constructor.
2038 *
2039 *  @param context Rendering context handle.
2040 **/
2041DrawElementsBaseVertexFunctionalCorrectBaseVertexBehaviorOverflow::
2042	DrawElementsBaseVertexFunctionalCorrectBaseVertexBehaviorOverflow(Context& context, const ExtParameters& extParams)
2043	: DrawElementsBaseVertexTestBase(context, extParams, "overflow",
2044									 "Verifies basevertex draw calls work correctly for overflowing "
2045									 "basevertex values")
2046{
2047	/* Left blank on purpose */
2048}
2049
2050/** Sets up test case descriptors for the test instance. These will later be used
2051 *  as input for DrawElementsBaseVertexTestBase::executeTestCases(), which performs
2052 *  the actual testing.
2053 **/
2054void DrawElementsBaseVertexFunctionalCorrectBaseVertexBehaviorOverflow::setUpTestCases()
2055{
2056	/* The test needs to be run in two iterations, using client-side memory and buffer object
2057	 * for index data respectively
2058	 */
2059	for (int vao_iteration = 0; vao_iteration < 2; ++vao_iteration)
2060	{
2061		/* Skip client-side vertex array as gl_VertexID is undefined when no buffer bound to ARRAY_BUFFER
2062		 *  See section 11.1.3.9 in OpenGL ES 3.1 spec
2063		 */
2064		bool use_clientside_vertex_data = 0;
2065		bool use_clientside_index_data  = ((vao_iteration & (1 << 0)) != 0);
2066
2067		/* OpenGL does not support client-side data. */
2068		if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
2069		{
2070			if (use_clientside_index_data || use_clientside_vertex_data)
2071			{
2072				continue;
2073			}
2074		}
2075
2076		/* Compute the offsets */
2077		computeVBODataOffsets(use_clientside_index_data, use_clientside_vertex_data);
2078
2079		/* We need to test four different functions:
2080		 *
2081		 * a)    glDrawElementsBaseVertex()             (GL)
2082		 *    or glDrawElementsBaseVertexEXT()          (ES)
2083		 * b)    glDrawRangeElementsBaseVertex()        (GL)
2084		 *    or glDrawRangeElementsBaseVertexEXT()     (ES)
2085		 * c)    glDrawElementsInstancedBaseVertex()    (GL)
2086		 *    or glDrawElementsInstancedBaseVertexEXT() (ES)
2087		 * d)    glMultiDrawElementsBaseVertex()        (GL)
2088		 *    or glMultiDrawElementsBaseVertexEXT()     (ES) (if supported)
2089		 **/
2090		for (int n_function = 0; n_function < FUNCTION_COUNT; ++n_function)
2091		{
2092			/* Do not try to use the multi draw call if relevant extension is
2093			 * not supported. */
2094			if (!m_is_ext_multi_draw_arrays_supported && n_function == FUNCTION_GL_MULTI_DRAW_ELEMENTS_BASE_VERTEX)
2095			{
2096				continue;
2097			}
2098
2099			const glw::GLenum index_types[] = { GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT, GL_UNSIGNED_INT };
2100
2101			const unsigned int n_index_types = sizeof(index_types) / sizeof(index_types[0]);
2102
2103			for (unsigned int n_index_type = 0; n_index_type < n_index_types; ++n_index_type)
2104			{
2105
2106				glw::GLint			basevertex					 = -1;
2107				const glw::GLubyte* index_offset				 = NULL;
2108				int					index_size					 = 0;
2109				glw::GLenum			index_type					 = index_types[n_index_type];
2110				glw::GLenum			regular_draw_call_index_type = 0;
2111				int					regular_draw_call_index_size = 0;
2112				glw::GLboolean		use_overflow_test_vertices   = false;
2113
2114				/* To meet requirements of tests IX.1-IX.2 and IX.3, we need to use two basevertex deltas. */
2115				const glw::GLint basevertex_deltas[] = {
2116					0, /* IX.1-IX.2 */
2117					1  /* IX.3 */
2118				};
2119				const unsigned int n_basevertex_deltas = sizeof(basevertex_deltas) / sizeof(basevertex_deltas[0]);
2120
2121				for (unsigned int n_basevertex_delta = 0; n_basevertex_delta < n_basevertex_deltas;
2122					 ++n_basevertex_delta)
2123				{
2124					const glw::GLint basevertex_delta		   = basevertex_deltas[n_basevertex_delta];
2125					glw::GLuint		 regular_draw_call_offset  = 0;
2126					glw::GLuint*	 regular_draw_call_offset2 = NULL;
2127					glw::GLuint		 range_start			   = 0;
2128					glw::GLuint		 range_end				   = 0;
2129					bool			 shouldMatch;
2130
2131					switch (index_type)
2132					{
2133					/*
2134					 * UBYTE base draw indices: 0, 1, 2
2135					 *              baseVertex: 256+0
2136					 *    regular draw indices: 0, 1, 2
2137					 *         expected result: ubyte indices should not wrap around at 8-bit width,
2138					 *                          base draw result should not match regular draw result
2139					 *
2140					 * UBYTE base draw indices: 0, 1, 2
2141					 *              baseVertex: 256+1
2142					 *    regular draw indices: 257, 258, 259 (uint)
2143					 *         expected result: ubyte indices should be upconverted to 32-bit uint,
2144					 *                          base draw result should match regular draw result
2145					 */
2146					case GL_UNSIGNED_BYTE:
2147					{
2148						basevertex					 = 256 + basevertex_delta;
2149						index_offset				 = (const glw::GLubyte*)m_draw_call_index3_offset;
2150						index_size					 = 1;
2151						range_start					 = 0;
2152						range_end					 = 2;
2153						regular_draw_call_index_type = (basevertex_delta == 0) ? GL_UNSIGNED_BYTE : GL_UNSIGNED_INT;
2154						regular_draw_call_index_size = (regular_draw_call_index_type == GL_UNSIGNED_BYTE) ? 1 : 4;
2155						regular_draw_call_offset2 =
2156							(basevertex_delta == 0) ?
2157								(glw::GLuint*)(m_draw_call_index3_offset) :
2158								(glw::GLuint*)(m_draw_call_index5_offset + 12); // 12th in functional5_index_data
2159						shouldMatch				   = (basevertex_delta == 1) ? true : false;
2160						use_overflow_test_vertices = true;
2161						break;
2162					}
2163
2164					/*
2165						 * USHORT base draw indices: 0, 1, 2
2166						 *               baseVertex: 65536+0
2167						 *     regular draw indices: 0, 1, 2
2168						 *          expected result: ubyte indices should not wrap around at 16-bit width,
2169						 *                           base draw result should not match regular draw result
2170						 *
2171						 * USHORT base draw indices: 0, 1, 2
2172						 *               baseVertex: 65536+1
2173						 *     regular draw indices: 65537, 65538, 65539 (uint)
2174						 *          expected result: ushort indices should be upconverted to 32-bit uint,
2175						 *                           base draw result should match regular draw result
2176						 */
2177					case GL_UNSIGNED_SHORT:
2178					{
2179						basevertex					 = 65536 + basevertex_delta;
2180						index_offset				 = (const glw::GLubyte*)m_draw_call_index4_offset;
2181						index_size					 = 2;
2182						range_start					 = 0;
2183						range_end					 = 2;
2184						regular_draw_call_index_type = (basevertex_delta == 0) ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT;
2185						regular_draw_call_index_size = (regular_draw_call_index_type == GL_UNSIGNED_SHORT) ? 2 : 4;
2186						regular_draw_call_offset2 =
2187							(basevertex_delta == 0) ?
2188								(glw::GLuint*)(m_draw_call_index4_offset) :
2189								(glw::GLuint*)(m_draw_call_index5_offset + 24); // 24th in functional5_index_data
2190						shouldMatch				   = (basevertex_delta == 1) ? true : false;
2191						use_overflow_test_vertices = true;
2192						break;
2193					}
2194
2195					/*
2196						 * UINT base draw indices: 2^31+2, 2^31+3, 2^31+4
2197						 *             baseVertex: 2^31-2
2198						 *   regular draw indices: 0, 1, 2
2199						 *        expected result: uint indices should wrap to {0, 1, 2},
2200						 *                         base draw result should match regular draw result
2201						 *
2202						 * UINT base draw indices: 2^31+2, 2^31+3, 2^31+4
2203						 *             baseVertex: 2^31-1
2204						 *   regular draw indices: 0, 1, 2
2205						 *        expected result: uint indices should wrap to {1, 2, 3},
2206						 *                         base draw result should not match regular draw result
2207						 */
2208					case GL_UNSIGNED_INT:
2209					{
2210						basevertex					 = 2147483647 - 1 + basevertex_delta;
2211						index_offset				 = (const glw::GLubyte*)m_draw_call_index5_offset;
2212						index_size					 = 4;
2213						range_start					 = 2147483647 + 3u; // 2^31+2
2214						range_end					 = 2147483647 + 5u; // 2^31+4
2215						regular_draw_call_index_type = GL_UNSIGNED_INT;
2216						regular_draw_call_index_size = 4;
2217						regular_draw_call_offset	 = 36; // 36th in functional5_index_data
2218						shouldMatch					 = (basevertex_delta == 0) ? true : false;
2219						use_overflow_test_vertices   = false;
2220						break;
2221					}
2222
2223					default:
2224					{
2225						TCU_FAIL("Unrecognized index type");
2226					}
2227					} /* switch (index_type) */
2228
2229					/* Prepare a few arrays so that we can handle the multi draw call and its emulated version.. */
2230					const glw::GLsizei  multi_draw_call_count_array[3]   = { 3, 6, 3 };
2231					const glw::GLubyte* multi_draw_call_indices_array[3] = { index_offset,
2232																			 index_offset + 3 * index_size,
2233																			 index_offset + 9 * index_size };
2234					const glw::GLubyte* regular_multi_draw_call_offseted_array[3];
2235					if (use_overflow_test_vertices)
2236					{
2237						regular_multi_draw_call_offseted_array[0] = (glw::GLubyte*)regular_draw_call_offset2;
2238						regular_multi_draw_call_offseted_array[1] =
2239							(glw::GLubyte*)regular_draw_call_offset2 + 3 * regular_draw_call_index_size;
2240						regular_multi_draw_call_offseted_array[2] =
2241							(glw::GLubyte*)regular_draw_call_offset2 + 9 * regular_draw_call_index_size;
2242					}
2243					else
2244					{
2245						regular_multi_draw_call_offseted_array[0] =
2246							multi_draw_call_indices_array[0] + index_size * regular_draw_call_offset;
2247						regular_multi_draw_call_offseted_array[1] =
2248							multi_draw_call_indices_array[1] + index_size * regular_draw_call_offset;
2249						regular_multi_draw_call_offseted_array[2] =
2250							multi_draw_call_indices_array[2] + index_size * regular_draw_call_offset;
2251					}
2252
2253					/* Construct the test case descriptor */
2254					_test_case new_test_case;
2255
2256					new_test_case.basevertex								  = basevertex;
2257					new_test_case.function_type								  = (_function_type)n_function;
2258					new_test_case.index_offset								  = (const glw::GLuint*)index_offset;
2259					new_test_case.range_start								  = range_start;
2260					new_test_case.range_end									  = range_end;
2261					new_test_case.index_type								  = index_type;
2262					new_test_case.primitive_mode							  = GL_TRIANGLES;
2263					new_test_case.regular_draw_call_offset					  = regular_draw_call_offset;
2264					new_test_case.regular_draw_call_offset2					  = regular_draw_call_offset2;
2265					new_test_case.regular_draw_call_index_type				  = regular_draw_call_index_type;
2266					new_test_case.should_base_texture_match_reference_texture = shouldMatch;
2267					new_test_case.use_clientside_index_data					  = use_clientside_index_data;
2268					new_test_case.use_clientside_vertex_data				  = use_clientside_vertex_data;
2269					new_test_case.use_geometry_shader_stage					  = false;
2270					new_test_case.use_tessellation_shader_stage				  = false;
2271					new_test_case.use_vertex_attrib_binding					  = false;
2272					new_test_case.use_overflow_test_vertices				  = use_overflow_test_vertices != GL_FALSE;
2273
2274					memcpy(new_test_case.multi_draw_call_count_array, multi_draw_call_count_array,
2275						   sizeof(multi_draw_call_count_array));
2276					memcpy(new_test_case.multi_draw_call_indices_array, multi_draw_call_indices_array,
2277						   sizeof(multi_draw_call_indices_array));
2278					memcpy(new_test_case.regular_multi_draw_call_offseted_array, regular_multi_draw_call_offseted_array,
2279						   sizeof(regular_multi_draw_call_offseted_array));
2280
2281					m_test_cases.push_back(new_test_case);
2282				} /* for (all basevertex deltas) */
2283			}	 /* for (all index types) */
2284		}		  /* for (all four functions) */
2285	}			  /* for (all VAO iterations) */
2286}
2287
2288/** Executes test iteration.
2289 *
2290 *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
2291 */
2292tcu::TestNode::IterateResult DrawElementsBaseVertexFunctionalCorrectBaseVertexBehaviorOverflow::iterate()
2293{
2294	setUpTestCases();
2295	executeTestCases();
2296
2297	/* Test case passed */
2298	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2299
2300	return STOP;
2301}
2302
2303/** Constructor.
2304 *
2305 *  @param context Rendering context handle.
2306 **/
2307DrawElementsBaseVertexFunctionalCorrectBaseVertexBehaviorAEPShaderStages::
2308	DrawElementsBaseVertexFunctionalCorrectBaseVertexBehaviorAEPShaderStages(Context&			  context,
2309																			 const ExtParameters& extParams)
2310	: DrawElementsBaseVertexTestBase(context, extParams, "AEP_shader_stages",
2311									 "Verifies basevertex draw calls work correctly when geometry & "
2312									 "tessellation shader stages are used in the rendering pipeline.")
2313{
2314	/* Left blank intentionally */
2315}
2316
2317/** Sets up test case descriptors for the test instance. These will later be used
2318 *  as input for DrawElementsBaseVertexTestBase::executeTestCases(), which performs
2319 *  the actual testing.
2320 **/
2321void DrawElementsBaseVertexFunctionalCorrectBaseVertexBehaviorAEPShaderStages::setUpTestCases()
2322{
2323	/* Set up test case descriptors */
2324	const glw::GLuint basevertex_values[] = {
2325		10, /* VI.1-VI.4 */
2326		0   /* VI.5 */
2327	};
2328	const unsigned int n_basevertex_values = sizeof(basevertex_values) / sizeof(basevertex_values[0]);
2329
2330	/* The test needs to be run in two iterations, using client-side memory and buffer object
2331	 * for index data respectively
2332	 */
2333	for (int vao_iteration = 0; vao_iteration < 2; ++vao_iteration)
2334	{
2335		/* Skip client-side vertex array as gl_VertexID is undefined when zero buffer is bound to ARRAY_BUFFER */
2336		bool use_clientside_vertex_data = 0;
2337		bool use_clientside_index_data  = ((vao_iteration & (1 << 0)) != 0);
2338
2339		/* OpenGL does not support client-side data. */
2340		if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
2341		{
2342			if (use_clientside_index_data || use_clientside_vertex_data)
2343			{
2344				continue;
2345			}
2346		}
2347
2348		/* Compute the offsets */
2349		computeVBODataOffsets(use_clientside_index_data, use_clientside_vertex_data);
2350
2351		/* There are two index data sets we need to iterate over */
2352		const glw::GLuint* index_offsets[] = { m_draw_call_index_offset, m_draw_call_index2_offset };
2353		const unsigned int n_index_offsets = sizeof(index_offsets) / sizeof(index_offsets[0]);
2354
2355		for (unsigned int n_index_offset = 0; n_index_offset < n_index_offsets; ++n_index_offset)
2356		{
2357			const glw::GLuint* current_index_offset = index_offsets[n_index_offset];
2358
2359			/* We need to test four different functions:
2360			 *
2361			 * a)    glDrawElementsBaseVertex()             (GL)
2362			 *    or glDrawElementsBaseVertexEXT()          (ES)
2363			 * b)    glDrawRangeElementsBaseVertex()        (GL)
2364			 *    or glDrawRangeElementsBaseVertexEXT()     (ES)
2365			 * c)    glDrawElementsInstancedBaseVertex()    (GL)
2366			 *    or glDrawElementsInstancedBaseVertexEXT() (ES)
2367			 * d)    glMultiDrawElementsBaseVertex()        (GL)
2368			 *    or glMultiDrawElementsBaseVertexEXT()     (ES) (if supported)
2369			 **/
2370			for (int n_function = 0; n_function < FUNCTION_COUNT; ++n_function)
2371			{
2372				/* Iterate over all basevertex values */
2373				for (unsigned int n_basevertex_value = 0; n_basevertex_value < n_basevertex_values;
2374					 ++n_basevertex_value)
2375				{
2376
2377					/* Iterate over all GS+(TC & TE) stage combinations */
2378					for (unsigned int n_stage_combination = 0; n_stage_combination < 4; ++n_stage_combination)
2379					{
2380						bool should_include_gs	= (n_stage_combination & 1) != 0;
2381						bool should_include_tc_te = (n_stage_combination & 2) != 0;
2382
2383						/* Skip iterations, for which we'd need to use extensions not supported
2384						 * by the running implementation */
2385						if (should_include_gs && !m_is_geometry_shader_supported)
2386						{
2387							continue;
2388						}
2389
2390						if (should_include_tc_te && !m_is_tessellation_shader_supported)
2391						{
2392							continue;
2393						}
2394
2395						/* Do not try to use the multi draw call if relevant extension is
2396						 * not supported. */
2397						if (!m_is_ext_multi_draw_arrays_supported &&
2398							n_function == FUNCTION_GL_MULTI_DRAW_ELEMENTS_BASE_VERTEX)
2399						{
2400							continue;
2401						}
2402
2403						/* Prepare a few arrays so that we can handle the multi draw call and its emulated version.. */
2404						const glw::GLsizei multi_draw_call_count_array[3]   = { 3, 6, 3 };
2405						const glw::GLuint* multi_draw_call_indices_array[3] = {
2406							(glw::GLuint*)(current_index_offset), (glw::GLuint*)(current_index_offset + 3),
2407							(glw::GLuint*)(current_index_offset + 9)
2408						};
2409
2410						/* Reference texture should always reflect basevertex=10 behavior. */
2411						const glw::GLuint  regular_draw_call_offset					 = basevertex_values[0];
2412						const glw::GLuint* regular_multi_draw_call_offseted_array[3] = {
2413							multi_draw_call_indices_array[0] + regular_draw_call_offset,
2414							multi_draw_call_indices_array[1] + regular_draw_call_offset,
2415							multi_draw_call_indices_array[2] + regular_draw_call_offset,
2416						};
2417
2418						/* Construct the test case descriptor */
2419						_test_case new_test_case;
2420
2421						new_test_case.basevertex			   = basevertex_values[n_basevertex_value];
2422						new_test_case.function_type			   = (_function_type)n_function;
2423						new_test_case.index_offset			   = current_index_offset;
2424						new_test_case.range_start			   = n_index_offset == 0 ? 0 : 10;
2425						new_test_case.range_end				   = n_index_offset == 0 ? 22 : 32;
2426						new_test_case.index_type			   = GL_UNSIGNED_INT;
2427						new_test_case.primitive_mode		   = (should_include_tc_te) ? GL_PATCHES : GL_TRIANGLES;
2428						new_test_case.regular_draw_call_offset = regular_draw_call_offset;
2429						new_test_case.should_base_texture_match_reference_texture =
2430							((glw::GLuint)new_test_case.basevertex == new_test_case.regular_draw_call_offset);
2431						new_test_case.use_clientside_index_data		= use_clientside_index_data;
2432						new_test_case.use_clientside_vertex_data	= use_clientside_vertex_data;
2433						new_test_case.use_geometry_shader_stage		= should_include_gs;
2434						new_test_case.use_tessellation_shader_stage = should_include_tc_te;
2435						new_test_case.use_vertex_attrib_binding		= false;
2436
2437						memcpy(new_test_case.multi_draw_call_count_array, multi_draw_call_count_array,
2438							   sizeof(multi_draw_call_count_array));
2439						memcpy(new_test_case.multi_draw_call_indices_array, multi_draw_call_indices_array,
2440							   sizeof(multi_draw_call_indices_array));
2441						memcpy(new_test_case.regular_multi_draw_call_offseted_array,
2442							   regular_multi_draw_call_offseted_array, sizeof(regular_multi_draw_call_offseted_array));
2443
2444						m_test_cases.push_back(new_test_case);
2445					} /* for (all shader stage combinations) */
2446				}	 /* for (all basevertex values) */
2447			}		  /* for (all four functions) */
2448		}			  /* for (all index data sets) */
2449	}				  /* for (all VAO iterations) */
2450}
2451
2452/** Executes test iteration.
2453 *
2454 *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
2455 */
2456tcu::TestNode::IterateResult DrawElementsBaseVertexFunctionalCorrectBaseVertexBehaviorAEPShaderStages::iterate()
2457{
2458	/* This test should not be run on implementations that don't support both tessellation and geometry
2459	 * shader stages
2460	 */
2461	if (!m_is_geometry_shader_supported && !m_is_tessellation_shader_supported)
2462	{
2463		throw tcu::NotSupportedError("Geometry shader and tessellation shader functionality is not supported");
2464	}
2465
2466	setUpTestCases();
2467	executeTestCases();
2468
2469	/* Test case passed */
2470	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2471
2472	return STOP;
2473}
2474
2475/** Constructor.
2476 *
2477 *  @param context Rendering context handle.
2478 **/
2479DrawElementsBaseVertexNegativeActiveTransformFeedbackTest::DrawElementsBaseVertexNegativeActiveTransformFeedbackTest(
2480	Context& context, const ExtParameters& extParams)
2481	: DrawElementsBaseVertexTestBase(context, extParams, "valid_active_tf",
2482									 "Tries to do \"base vertex\" draw calls while Transform Feedback is active")
2483	, m_bo_tf_result_id(0)
2484{
2485	/* Left blank on purpose */
2486}
2487
2488/** Deinitializes all ES objects per test case if test fails and exit through exception path */
2489void DrawElementsBaseVertexNegativeActiveTransformFeedbackTest::deinit()
2490{
2491	deinitPerTestObjects();
2492}
2493
2494/** Deinitializes all ES objects that may have been created by the test */
2495void DrawElementsBaseVertexNegativeActiveTransformFeedbackTest::deinitPerTestObjects()
2496{
2497	/* Call the base class' deinitPerTestObjects() first. */
2498	DrawElementsBaseVertexTestBase::deinitPerTestObjects();
2499
2500	/* Proceed with internal deinitialization */
2501	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2502
2503	if (m_bo_tf_result_id != 0)
2504	{
2505		gl.deleteBuffers(1, &m_bo_tf_result_id);
2506
2507		m_bo_tf_result_id = 0;
2508	}
2509}
2510
2511/** Initializes all ES objects used by the test. */
2512void DrawElementsBaseVertexNegativeActiveTransformFeedbackTest::init()
2513{
2514	/* Call the base class' init() first. */
2515	DrawElementsBaseVertexTestBase::init();
2516
2517	/* Proceed with internal initialization */
2518	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2519
2520	gl.genBuffers(1, &m_bo_tf_result_id);
2521	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed");
2522
2523	gl.bindBuffer(GL_ARRAY_BUFFER, m_bo_tf_result_id);
2524	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed");
2525
2526	gl.bufferData(GL_ARRAY_BUFFER, 3 /* count */ * sizeof(float) * 4 /* components used by gl_Position */,
2527				  DE_NULL, /* data */
2528				  GL_STATIC_DRAW);
2529	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
2530
2531	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, /* index */
2532					  m_bo_tf_result_id);
2533	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed");
2534}
2535
2536/** Executes test iteration.
2537 *
2538 *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
2539 */
2540tcu::TestNode::IterateResult DrawElementsBaseVertexNegativeActiveTransformFeedbackTest::iterate()
2541{
2542	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2543
2544	/* this test doesn't apply to OpenGL contexts */
2545	if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
2546	{
2547		m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported");
2548		return STOP;
2549	}
2550
2551	/* Set up the work environment */
2552	setUpNegativeTestObjects(false,  /* use_clientside_vertex_data */
2553							 false); /* use_clientside_index_data */
2554
2555	/* Kick off transform feedback */
2556	gl.beginTransformFeedback(GL_TRIANGLES);
2557	GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call failed.");
2558
2559	/* Try to perform indiced draw calls which are invalid when TF is active.
2560	 */
2561	glw::GLenum error_code = GL_NONE;
2562
2563	gl.drawElementsBaseVertex(GL_TRIANGLES, 3,								 /* count */
2564							  GL_UNSIGNED_INT, m_draw_call_index_offset, 0); /* basevertex */
2565
2566	error_code = gl.getError();
2567
2568	/* The error for using DrawElements* commands while transform feedback is
2569	 active is lifted in OES/EXT_geometry_shader. See issue 13 in the spec.
2570	 */
2571	glw::GLenum expected_error_code = m_is_geometry_shader_supported ? GL_NO_ERROR : GL_INVALID_OPERATION;
2572
2573	if (error_code != expected_error_code)
2574	{
2575		std::stringstream error_sstream;
2576
2577		error_sstream << "Invalid error code generated by " << getFunctionName(FUNCTION_GL_DRAW_ELEMENTS_BASE_VERTEX);
2578
2579		m_testCtx.getLog() << tcu::TestLog::Message << getFunctionName(FUNCTION_GL_DRAW_ELEMENTS_BASE_VERTEX)
2580						   << " returned error code [" << error_code << "] instead of [" << expected_error_code << "]."
2581						   << tcu::TestLog::EndMessage;
2582
2583		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, error_sstream.str().c_str());
2584
2585		goto end;
2586	}
2587
2588	gl.drawElementsInstancedBaseVertex(GL_TRIANGLES, 3,								 /* count */
2589									   GL_UNSIGNED_INT, m_draw_call_index_offset, 1, /* instancecount */
2590									   0);											 /* basevertex */
2591
2592	error_code = gl.getError();
2593	if (error_code != expected_error_code)
2594	{
2595		std::stringstream error_sstream;
2596
2597		error_sstream << "Invalid error code generated by "
2598					  << getFunctionName(FUNCTION_GL_DRAW_ELEMENTS_INSTANCED_BASE_VERTEX);
2599
2600		m_testCtx.getLog() << tcu::TestLog::Message << getFunctionName(FUNCTION_GL_DRAW_ELEMENTS_INSTANCED_BASE_VERTEX)
2601						   << " returned error code [" << error_code << "] instead of [" << expected_error_code << "]."
2602						   << tcu::TestLog::EndMessage;
2603
2604		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, error_sstream.str().c_str());
2605
2606		goto end;
2607	}
2608
2609	gl.drawRangeElementsBaseVertex(GL_TRIANGLES, 0, 2,							  /* end */
2610								   3,											  /* count */
2611								   GL_UNSIGNED_INT, m_draw_call_index_offset, 0); /* basevertex */
2612
2613	error_code = gl.getError();
2614	if (error_code != expected_error_code)
2615	{
2616		std::stringstream error_sstream;
2617
2618		error_sstream << "Invalid error code generated by "
2619					  << getFunctionName(FUNCTION_GL_DRAW_RANGE_ELEMENTS_BASE_VERTEX);
2620
2621		m_testCtx.getLog() << tcu::TestLog::Message << getFunctionName(FUNCTION_GL_DRAW_RANGE_ELEMENTS_BASE_VERTEX)
2622						   << " returned error code [" << error_code << "] instead of [" << expected_error_code << "]."
2623						   << tcu::TestLog::EndMessage;
2624
2625		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, error_sstream.str().c_str());
2626
2627		goto end;
2628	}
2629
2630	/* Test case passed */
2631	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2632
2633end:
2634	gl.endTransformFeedback();
2635	return STOP;
2636}
2637
2638/** Constructor.
2639 *
2640 *  @param context Rendering context handle.
2641 **/
2642DrawElementsBaseVertexNegativeInvalidCountArgumentTest::DrawElementsBaseVertexNegativeInvalidCountArgumentTest(
2643	Context& context, const ExtParameters& extParams)
2644	: DrawElementsBaseVertexTestBase(context, extParams, "invalid_count_argument",
2645									 "Tries to use invalid 'count' argument values for the \"base vertex\" draw calls")
2646{
2647	/* Left blank on purpose */
2648}
2649
2650/** Executes test iteration.
2651 *
2652 *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
2653 */
2654tcu::TestNode::IterateResult DrawElementsBaseVertexNegativeInvalidCountArgumentTest::iterate()
2655{
2656	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2657
2658	/* The test needs to be run in four iterations, where for each iteration we configure the VAO
2659	 * in a slightly different manner.
2660	 */
2661	for (int iteration = 0; iteration < 4; ++iteration)
2662	{
2663		bool use_clientside_index_data  = ((iteration & (1 << 0)) != 0);
2664		bool use_clientside_vertex_data = ((iteration & (1 << 1)) != 0);
2665
2666		/* OpenGL does not support client-side data. */
2667		if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
2668		{
2669			if (use_clientside_index_data || use_clientside_vertex_data)
2670			{
2671				continue;
2672			}
2673		}
2674
2675		/* Set up the work environment */
2676		setUpNegativeTestObjects(use_clientside_vertex_data, use_clientside_index_data);
2677
2678		/* Try to execute the invalid draw calls */
2679		glw::GLenum error_code = GL_NONE;
2680
2681		gl.drawElementsBaseVertex(GL_TRIANGLES, -1,													 /* count */
2682								  GL_UNSIGNED_INT, (const glw::GLvoid*)m_draw_call_index_offset, 0); /* basevertex */
2683
2684		error_code = gl.getError();
2685		if (error_code != GL_INVALID_VALUE)
2686		{
2687			std::stringstream error_sstream;
2688
2689			error_sstream << "Invalid error code reported for an invalid "
2690						  << getFunctionName(FUNCTION_GL_DRAW_ELEMENTS_BASE_VERTEX) << " call";
2691
2692			m_testCtx.getLog() << tcu::TestLog::Message << error_sstream.str().c_str()
2693							   << ": expected GL_INVALID_VALUE, got:"
2694								  "["
2695							   << error_code << "]" << tcu::TestLog::EndMessage;
2696
2697			TCU_FAIL(error_sstream.str().c_str());
2698		}
2699
2700		gl.drawRangeElementsBaseVertex(GL_TRIANGLES, /* mode */
2701									   -1,			 /* start */
2702									   2,			 /* end */
2703									   1,			 /* count */
2704									   GL_UNSIGNED_INT, (const glw::GLvoid*)m_draw_call_index_offset,
2705									   0); /* basevertex */
2706
2707		error_code = gl.getError();
2708		if (error_code != GL_INVALID_VALUE)
2709		{
2710			std::stringstream error_sstream;
2711
2712			error_sstream << "Invalid error code reported for an invalid "
2713						  << getFunctionName(FUNCTION_GL_DRAW_RANGE_ELEMENTS_BASE_VERTEX) << " call";
2714
2715			m_testCtx.getLog() << tcu::TestLog::Message << error_sstream.str().c_str()
2716							   << ": expected GL_INVALID_VALUE, got:"
2717								  "["
2718							   << error_code << "]" << tcu::TestLog::EndMessage;
2719
2720			TCU_FAIL(error_sstream.str().c_str());
2721		}
2722
2723		gl.drawElementsInstancedBaseVertex(GL_TRIANGLES, /* mode */
2724										   -1,			 /* count */
2725										   GL_UNSIGNED_INT, (const glw::GLvoid*)m_draw_call_index_offset,
2726										   1,  /* instancecount */
2727										   0); /* basevertex */
2728
2729		error_code = gl.getError();
2730		if (error_code != GL_INVALID_VALUE)
2731		{
2732			std::stringstream error_sstream;
2733
2734			error_sstream << "Invalid error code reported for an invalid "
2735						  << getFunctionName(FUNCTION_GL_DRAW_ELEMENTS_INSTANCED_BASE_VERTEX) << " call";
2736
2737			m_testCtx.getLog() << tcu::TestLog::Message << error_sstream.str().c_str()
2738							   << ": expected GL_INVALID_VALUE, got:"
2739								  "["
2740							   << error_code << "]" << tcu::TestLog::EndMessage;
2741
2742			TCU_FAIL(error_sstream.str().c_str());
2743		}
2744
2745		if (m_is_ext_multi_draw_arrays_supported)
2746		{
2747			const glw::GLsizei count	 = -1;
2748			const glw::GLvoid* offsets[] = { (const glw::GLvoid*)m_draw_call_index_offset };
2749
2750			gl.multiDrawElementsBaseVertex(GL_TRIANGLES,						/* mode */
2751										   &count, GL_UNSIGNED_INT, offsets, 1, /* primcount */
2752										   0);									/* basevertex */
2753
2754			error_code = gl.getError();
2755			if (error_code != GL_INVALID_VALUE)
2756			{
2757				std::stringstream error_sstream;
2758
2759				error_sstream << "Invalid error code reported for an invalid "
2760							  << getFunctionName(FUNCTION_GL_MULTI_DRAW_ELEMENTS_BASE_VERTEX) << " call";
2761
2762				m_testCtx.getLog() << tcu::TestLog::Message << error_sstream.str().c_str()
2763								   << ": expected GL_INVALID_VALUE, got:"
2764									  "["
2765								   << error_code << "]" << tcu::TestLog::EndMessage;
2766
2767				TCU_FAIL("Invalid error code reported for an invalid glMultiDrawElementsBaseVertexEXT() call.");
2768			}
2769		} /* if (m_is_ext_multi_draw_arrays_supported) */
2770	}	 /* for (all iterations) */
2771
2772	/* Test case passed */
2773	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2774
2775	return STOP;
2776}
2777
2778/** Constructor.
2779 *
2780 *  @param context Rendering context handle.
2781 **/
2782DrawElementsBaseVertexNegativeInvalidInstanceCountArgumentTest::
2783	DrawElementsBaseVertexNegativeInvalidInstanceCountArgumentTest(Context& context, const ExtParameters& extParams)
2784	: DrawElementsBaseVertexTestBase(context, extParams, "invalid_instancecount_argument",
2785									 "Tries to use invalid 'instancecount' argument values for "
2786									 "glDrawElementsInstancedBaseVertexEXT (ES) or "
2787									 "glDrawElementsInstancedBaseVertex (GL) draw call")
2788{
2789	/* Left blank on purpose */
2790}
2791
2792/** Executes test iteration.
2793 *
2794 *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
2795 */
2796tcu::TestNode::IterateResult DrawElementsBaseVertexNegativeInvalidInstanceCountArgumentTest::iterate()
2797{
2798	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2799
2800	/* The test needs to be run in four iterations, where for each iteration we configure the VAO
2801	 * in a slightly different manner.
2802	 */
2803	for (int iteration = 0; iteration < 4; ++iteration)
2804	{
2805		bool use_clientside_index_data  = ((iteration & (1 << 0)) != 0);
2806		bool use_clientside_vertex_data = ((iteration & (1 << 1)) != 0);
2807
2808		/* OpenGL does not support client-side data. */
2809		if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
2810		{
2811			if (use_clientside_index_data || use_clientside_vertex_data)
2812			{
2813				continue;
2814			}
2815		}
2816
2817		/* Set up the work environment */
2818		setUpNegativeTestObjects(use_clientside_vertex_data, use_clientside_index_data);
2819
2820		/* Try to execute the invalid draw call */
2821		glw::GLenum error_code = GL_NONE;
2822
2823		gl.drawElementsInstancedBaseVertex(GL_TRIANGLES, /* mode */
2824										   3,			 /* count */
2825										   GL_UNSIGNED_INT, (const glw::GLvoid*)m_draw_call_index_offset,
2826										   -1, /* instancecount */
2827										   0); /* basevertex */
2828
2829		error_code = gl.getError();
2830		if (error_code != GL_INVALID_VALUE)
2831		{
2832			std::stringstream error_sstream;
2833
2834			error_sstream << "Invalid error code reported for an invalid "
2835						  << getFunctionName(FUNCTION_GL_DRAW_ELEMENTS_INSTANCED_BASE_VERTEX) << " call";
2836
2837			m_testCtx.getLog() << tcu::TestLog::Message << error_sstream.str().c_str()
2838							   << ": expected GL_INVALID_VALUE, got:"
2839								  "["
2840							   << error_code << "]" << tcu::TestLog::EndMessage;
2841
2842			TCU_FAIL(error_sstream.str().c_str());
2843		}
2844	} /* for (all test iterations) */
2845
2846	/* Test case passed */
2847	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2848
2849	return STOP;
2850}
2851
2852/** Constructor.
2853 *
2854 *  @param context Rendering context handle.
2855 **/
2856DrawElementsBaseVertexNegativeInvalidModeArgumentTest::DrawElementsBaseVertexNegativeInvalidModeArgumentTest(
2857	Context& context, const ExtParameters& extParams)
2858	: DrawElementsBaseVertexTestBase(context, extParams, "invalid_mode_argument",
2859									 "Tries to use invalid 'mode' argument values for the \"base vertex\" draw calls")
2860{
2861	/* Left blank on purpose */
2862}
2863
2864/** Executes test iteration.
2865 *
2866 *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
2867 */
2868tcu::TestNode::IterateResult DrawElementsBaseVertexNegativeInvalidModeArgumentTest::iterate()
2869{
2870	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2871
2872	/* The test needs to be run in four iterations, where for each iteration we configure the VAO
2873	 * in a slightly different manner.
2874	 */
2875	for (int iteration = 0; iteration < 4; ++iteration)
2876	{
2877		bool use_clientside_index_data  = ((iteration & (1 << 0)) != 0);
2878		bool use_clientside_vertex_data = ((iteration & (1 << 1)) != 0);
2879
2880		/* OpenGL does not support client-side data. */
2881		if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
2882		{
2883			if (use_clientside_index_data || use_clientside_vertex_data)
2884			{
2885				continue;
2886			}
2887		}
2888
2889		/* Set up the work environment */
2890		setUpNegativeTestObjects(use_clientside_vertex_data, use_clientside_index_data);
2891
2892		/* Try to execute the invalid draw calls */
2893		glw::GLenum error_code = GL_NONE;
2894
2895		gl.drawElementsBaseVertex(GL_GREATER,														 /* mode */
2896								  3,																 /* count */
2897								  GL_UNSIGNED_INT, (const glw::GLvoid*)m_draw_call_index_offset, 0); /* basevertex */
2898
2899		error_code = gl.getError();
2900		if (error_code != GL_INVALID_ENUM)
2901		{
2902			std::stringstream error_sstream;
2903
2904			error_sstream << "Invalid error code reported for an invalid "
2905						  << getFunctionName(FUNCTION_GL_DRAW_ELEMENTS_BASE_VERTEX) << " call";
2906
2907			m_testCtx.getLog() << tcu::TestLog::Message << error_sstream.str().c_str()
2908							   << ": expected GL_INVALID_ENUM, got:"
2909								  "["
2910							   << error_code << "]" << tcu::TestLog::EndMessage;
2911
2912			TCU_FAIL(error_sstream.str().c_str());
2913		}
2914
2915		gl.drawRangeElementsBaseVertex(GL_GREATER, /* mode */
2916									   0,		   /* start */
2917									   2,		   /* end */
2918									   3,		   /* count */
2919									   GL_UNSIGNED_INT, (const glw::GLvoid*)m_draw_call_index_offset,
2920									   0); /* basevertex */
2921
2922		error_code = gl.getError();
2923		if (error_code != GL_INVALID_ENUM)
2924		{
2925			std::stringstream error_sstream;
2926
2927			error_sstream << "Invalid error code reported for an invalid "
2928						  << getFunctionName(FUNCTION_GL_DRAW_RANGE_ELEMENTS_BASE_VERTEX) << " call";
2929
2930			m_testCtx.getLog() << tcu::TestLog::Message << error_sstream.str().c_str()
2931							   << ": expected GL_INVALID_ENUM, got:"
2932								  "["
2933							   << error_code << "]" << tcu::TestLog::EndMessage;
2934
2935			TCU_FAIL(error_sstream.str().c_str());
2936		}
2937
2938		gl.drawElementsInstancedBaseVertex(GL_GREATER, /* mode */
2939										   3,		   /* count */
2940										   GL_UNSIGNED_INT, (const glw::GLvoid*)m_draw_call_index_offset,
2941										   1,  /* instancecount */
2942										   0); /* basevertex */
2943
2944		error_code = gl.getError();
2945		if (error_code != GL_INVALID_ENUM)
2946		{
2947			std::stringstream error_sstream;
2948
2949			error_sstream << "Invalid error code reported for an invalid "
2950						  << getFunctionName(FUNCTION_GL_DRAW_ELEMENTS_INSTANCED_BASE_VERTEX) << " call";
2951
2952			m_testCtx.getLog() << tcu::TestLog::Message << error_sstream.str().c_str()
2953							   << ": expected GL_INVALID_ENUM, got:"
2954								  "["
2955							   << error_code << "]" << tcu::TestLog::EndMessage;
2956
2957			TCU_FAIL(error_sstream.str().c_str());
2958		}
2959
2960		if (m_is_ext_multi_draw_arrays_supported)
2961		{
2962			const glw::GLsizei count	 = 3;
2963			const glw::GLvoid* offsets[] = { (const glw::GLvoid*)m_draw_call_index_offset };
2964
2965			gl.multiDrawElementsBaseVertex(GL_GREATER,							/* mode */
2966										   &count, GL_UNSIGNED_INT, offsets, 1, /* primcount */
2967										   0);									/* basevertex */
2968
2969			error_code = gl.getError();
2970			if (error_code != GL_INVALID_ENUM)
2971			{
2972				std::stringstream error_sstream;
2973
2974				error_sstream << "Invalid error code reported for an invalid "
2975							  << getFunctionName(FUNCTION_GL_MULTI_DRAW_ELEMENTS_BASE_VERTEX) << " call";
2976
2977				m_testCtx.getLog() << tcu::TestLog::Message << error_sstream.str().c_str()
2978								   << ": expected GL_INVALID_ENUM, got:"
2979									  "["
2980								   << error_code << "]" << tcu::TestLog::EndMessage;
2981
2982				TCU_FAIL(error_sstream.str().c_str());
2983			}
2984		} /* if (m_is_ext_multi_draw_arrays_supported) */
2985	}	 /* for (all test iterations) */
2986
2987	/* Test case passed */
2988	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2989
2990	return STOP;
2991}
2992
2993/** Constructor.
2994 *
2995 *  @param context Rendering context handle.
2996 **/
2997DrawElementsBaseVertexNegativeInvalidPrimcountArgumentTest::DrawElementsBaseVertexNegativeInvalidPrimcountArgumentTest(
2998	Context& context, const ExtParameters& extParams)
2999	: DrawElementsBaseVertexTestBase(
3000		  context, extParams, "invalid_primcount_argument",
3001		  "Tries to use invalid 'primcount' argument values for the \"base vertex\" draw calls")
3002{
3003	/* Left blank on purpose */
3004}
3005
3006/** Executes test iteration.
3007 *
3008 *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
3009 */
3010tcu::TestNode::IterateResult DrawElementsBaseVertexNegativeInvalidPrimcountArgumentTest::iterate()
3011{
3012	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3013
3014	/* This test requires presence of GL_EXT_multi_draw_arrays under ES contexts */
3015	if (glu::isContextTypeES(m_context.getRenderContext().getType()))
3016	{
3017		if (!m_is_ext_multi_draw_arrays_supported)
3018		{
3019			throw tcu::NotSupportedError("GL_EXT_multi_draw_arrays is not supported");
3020		}
3021	}
3022
3023	/* The test needs to be run in four iterations, where for each iteration we configure the VAO
3024	 * in a slightly different manner.
3025	 */
3026	for (int iteration = 0; iteration < 4; ++iteration)
3027	{
3028		bool use_clientside_index_data  = ((iteration & (1 << 0)) != 0);
3029		bool use_clientside_vertex_data = ((iteration & (1 << 1)) != 0);
3030
3031		/* OpenGL does not support client-side data. */
3032		if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
3033		{
3034			if (use_clientside_index_data || use_clientside_vertex_data)
3035			{
3036				continue;
3037			}
3038		}
3039
3040		/* Set up the work environment */
3041		setUpNegativeTestObjects(use_clientside_vertex_data, use_clientside_index_data);
3042
3043		/* Perform the test */
3044		const glw::GLsizei count	  = 3;
3045		glw::GLenum		   error_code = GL_NO_ERROR;
3046		const glw::GLvoid* offsets[]  = { (const glw::GLvoid*)m_draw_call_index_offset };
3047
3048		gl.multiDrawElementsBaseVertex(GL_TRIANGLES,						 /* mode */
3049									   &count, GL_UNSIGNED_INT, offsets, -1, /* primcount */
3050									   0);									 /* basevertex */
3051
3052		error_code = gl.getError();
3053		if (error_code != GL_INVALID_VALUE)
3054		{
3055			std::stringstream error_sstream;
3056
3057			error_sstream << "Invalid error code reported for an invalid "
3058						  << getFunctionName(FUNCTION_GL_MULTI_DRAW_ELEMENTS_BASE_VERTEX) << " call";
3059
3060			m_testCtx.getLog() << tcu::TestLog::Message << error_sstream.str().c_str()
3061							   << ": expected GL_INVALID_VALUE, got:"
3062								  "["
3063							   << error_code << "]" << tcu::TestLog::EndMessage;
3064
3065			TCU_FAIL(error_sstream.str().c_str());
3066		}
3067	} /* for (all test iterations) */
3068
3069	/* Test case passed */
3070	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
3071
3072	return STOP;
3073}
3074
3075/** Constructor.
3076 *
3077 *  @param context Rendering context handle.
3078 **/
3079DrawElementsBaseVertexNegativeInvalidStartEndArgumentsTest::DrawElementsBaseVertexNegativeInvalidStartEndArgumentsTest(
3080	Context& context, const ExtParameters& extParams)
3081	: DrawElementsBaseVertexTestBase(context, extParams, "invalid_start_end_arguments",
3082									 "Tries to use invalid 'start' and 'end' argument values for the "
3083									 "glDrawRangeElementsBaseVertexEXT() (under ES) or "
3084									 "glDrawRangeElementsBaseVertex() (under GL) draw call")
3085{
3086	/* Left blank on purpose */
3087}
3088
3089/** Executes test iteration.
3090 *
3091 *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
3092 */
3093tcu::TestNode::IterateResult DrawElementsBaseVertexNegativeInvalidStartEndArgumentsTest::iterate()
3094{
3095	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3096
3097	/* The test needs to be run in four iterations, where for each iteration we configure the VAO
3098	 * in a slightly different manner.
3099	 */
3100	for (int iteration = 0; iteration < 4; ++iteration)
3101	{
3102		bool use_clientside_index_data  = ((iteration & (1 << 0)) != 0);
3103		bool use_clientside_vertex_data = ((iteration & (1 << 1)) != 0);
3104
3105		/* OpenGL does not support client-side data. */
3106		if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
3107		{
3108			if (use_clientside_index_data || use_clientside_vertex_data)
3109			{
3110				continue;
3111			}
3112		}
3113
3114		/* Set up the work environment */
3115		setUpNegativeTestObjects(use_clientside_vertex_data, use_clientside_index_data);
3116
3117		/* Try to execute the invalid draw call */
3118		glw::GLenum error_code = GL_NONE;
3119
3120		gl.drawRangeElementsBaseVertex(GL_TRIANGLES, /* mode */
3121									   3,			 /* start */
3122									   0,			 /* end */
3123									   3,			 /* count */
3124									   GL_UNSIGNED_INT, (const glw::GLvoid*)m_draw_call_index_offset,
3125									   0); /* basevertex */
3126
3127		error_code = gl.getError();
3128		if (error_code != GL_INVALID_VALUE)
3129		{
3130			std::stringstream error_sstream;
3131
3132			error_sstream << "Invalid error code reported for an invalid "
3133						  << getFunctionName(FUNCTION_GL_DRAW_RANGE_ELEMENTS_BASE_VERTEX) << " call";
3134
3135			m_testCtx.getLog() << tcu::TestLog::Message << error_sstream.str().c_str()
3136							   << ": expected GL_INVALID_VALUE, got:"
3137								  "["
3138							   << error_code << "]" << tcu::TestLog::EndMessage;
3139
3140			TCU_FAIL(error_sstream.str().c_str());
3141		}
3142	} /* for (all test iterations) */
3143
3144	/* Test case passed */
3145	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
3146
3147	return STOP;
3148}
3149
3150/** Constructor.
3151 *
3152 *  @param context Rendering context handle.
3153 **/
3154DrawElementsBaseVertexNegativeInvalidTypeArgumentTest::DrawElementsBaseVertexNegativeInvalidTypeArgumentTest(
3155	Context& context, const ExtParameters& extParams)
3156	: DrawElementsBaseVertexTestBase(context, extParams, "invalid_type_argument",
3157									 "Tries to use invalid 'type' argument values for the \"base vertex\" draw calls")
3158{
3159	/* Left blank on purpose */
3160}
3161
3162/** Executes test iteration.
3163 *
3164 *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
3165 */
3166tcu::TestNode::IterateResult DrawElementsBaseVertexNegativeInvalidTypeArgumentTest::iterate()
3167{
3168	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3169
3170	/* The test needs to be run in four iterations, where for each iteration we configure the VAO
3171	 * in a slightly different manner.
3172	 */
3173	for (int iteration = 0; iteration < 4; ++iteration)
3174	{
3175		bool use_clientside_index_data  = ((iteration & (1 << 0)) != 0);
3176		bool use_clientside_vertex_data = ((iteration & (1 << 1)) != 0);
3177
3178		/* OpenGL does not support client-side data. */
3179		if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
3180		{
3181			if (use_clientside_index_data || use_clientside_vertex_data)
3182			{
3183				continue;
3184			}
3185		}
3186
3187		/* Set up the work environment */
3188		setUpNegativeTestObjects(use_clientside_vertex_data, use_clientside_index_data);
3189
3190		/* Try to execute the invalid draw calls */
3191		glw::GLenum error_code = GL_NONE;
3192
3193		gl.drawElementsBaseVertex(GL_TRIANGLES,												 /* mode */
3194								  3,														 /* count */
3195								  GL_NONE, (const glw::GLvoid*)m_draw_call_index_offset, 0); /* basevertex */
3196
3197		error_code = gl.getError();
3198		if (error_code != GL_INVALID_ENUM)
3199		{
3200			std::stringstream error_sstream;
3201
3202			error_sstream << "Invalid error code reported for an invalid "
3203						  << getFunctionName(FUNCTION_GL_DRAW_ELEMENTS_BASE_VERTEX) << " call";
3204
3205			m_testCtx.getLog() << tcu::TestLog::Message << error_sstream.str().c_str()
3206							   << ": expected GL_INVALID_ENUM, got:"
3207								  "["
3208							   << error_code << "]" << tcu::TestLog::EndMessage;
3209
3210			TCU_FAIL(error_sstream.str().c_str());
3211		}
3212
3213		gl.drawRangeElementsBaseVertex(GL_TRIANGLES,											  /* mode */
3214									   0,														  /* start */
3215									   2,														  /* end */
3216									   3,														  /* count */
3217									   GL_NONE, (const glw::GLvoid*)m_draw_call_index_offset, 0); /* basevertex */
3218
3219		error_code = gl.getError();
3220		if (error_code != GL_INVALID_ENUM)
3221		{
3222			std::stringstream error_sstream;
3223
3224			error_sstream << "Invalid error code reported for an invalid "
3225						  << getFunctionName(FUNCTION_GL_DRAW_RANGE_ELEMENTS_BASE_VERTEX) << " call";
3226
3227			m_testCtx.getLog() << tcu::TestLog::Message << error_sstream.str().c_str()
3228							   << ": expected GL_INVALID_ENUM, got:"
3229								  "["
3230							   << error_code << "]" << tcu::TestLog::EndMessage;
3231
3232			TCU_FAIL(error_sstream.str().c_str());
3233		}
3234
3235		gl.drawElementsInstancedBaseVertex(GL_TRIANGLES,											 /* mode */
3236										   3,														 /* count */
3237										   GL_NONE, (const glw::GLvoid*)m_draw_call_index_offset, 1, /* instancecount */
3238										   0);														 /* basevertex */
3239
3240		error_code = gl.getError();
3241		if (error_code != GL_INVALID_ENUM)
3242		{
3243			std::stringstream error_sstream;
3244
3245			error_sstream << "Invalid error code reported for an invalid "
3246						  << getFunctionName(FUNCTION_GL_DRAW_ELEMENTS_INSTANCED_BASE_VERTEX) << " call";
3247
3248			m_testCtx.getLog() << tcu::TestLog::Message << error_sstream.str().c_str()
3249							   << ": expected GL_INVALID_ENUM, got:"
3250								  "["
3251							   << error_code << "]" << tcu::TestLog::EndMessage;
3252
3253			TCU_FAIL(error_sstream.str().c_str());
3254		}
3255
3256		if (m_is_ext_multi_draw_arrays_supported)
3257		{
3258			const glw::GLsizei count	 = 3;
3259			const glw::GLvoid* offsets[] = { (const glw::GLvoid*)m_draw_call_index_offset };
3260
3261			gl.multiDrawElementsBaseVertex(GL_TRIANGLES,				/* mode */
3262										   &count, GL_NONE, offsets, 1, /* primcount */
3263										   0);							/* basevertex */
3264
3265			error_code = gl.getError();
3266			if (error_code != GL_INVALID_ENUM)
3267			{
3268				std::stringstream error_sstream;
3269
3270				error_sstream << "Invalid error code reported for an invalid "
3271							  << getFunctionName(FUNCTION_GL_MULTI_DRAW_ELEMENTS_BASE_VERTEX) << " call";
3272
3273				m_testCtx.getLog() << tcu::TestLog::Message << error_sstream.str().c_str()
3274								   << ": expected GL_INVALID_ENUM, got:"
3275									  "["
3276								   << error_code << "]" << tcu::TestLog::EndMessage;
3277
3278				TCU_FAIL(error_sstream.str().c_str());
3279			}
3280		} /* if (m_is_ext_multi_draw_arrays_supported) */
3281	}	 /* for (all test iterations) */
3282
3283	/* Test case passed */
3284	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
3285
3286	return STOP;
3287}
3288
3289/** Constructor.
3290 *
3291 *  @param context Rendering context handle.
3292 **/
3293DrawElementsBaseVertexNegativeMappedBufferObjectsTest::DrawElementsBaseVertexNegativeMappedBufferObjectsTest(
3294	Context& context, const ExtParameters& extParams)
3295	: DrawElementsBaseVertexTestBase(
3296		  context, extParams, "invalid_mapped_bos",
3297		  "Tries to use mapped VBO and Index Buffer Object for the \"base vertex\" draw calls")
3298{
3299	/* Left blank on purpose */
3300}
3301
3302/** Executes test iteration.
3303 *
3304 *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
3305 */
3306tcu::TestNode::IterateResult DrawElementsBaseVertexNegativeMappedBufferObjectsTest::iterate()
3307{
3308	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3309
3310	/* The test needs to be run in four iterations, where for each iteration we configure the VAO
3311	 * in a slightly different manner.
3312	 */
3313	for (int iteration = 0; iteration < 4; ++iteration)
3314	{
3315		bool use_clientside_index_data  = ((iteration & (1 << 0)) != 0);
3316		bool use_clientside_vertex_data = ((iteration & (1 << 1)) != 0);
3317
3318		/* OpenGL does not support client-side data. */
3319		if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
3320		{
3321			if (use_clientside_index_data || use_clientside_vertex_data)
3322			{
3323				continue;
3324			}
3325		}
3326
3327		/* Skip the iteration where no array buffer is used */
3328		if (use_clientside_vertex_data)
3329		{
3330			continue;
3331		}
3332
3333		/* Set up the work environment */
3334		setUpNegativeTestObjects(use_clientside_vertex_data, use_clientside_index_data);
3335
3336		/* Map the buffer object into process space */
3337		const glw::GLvoid* bo_ptr = gl.mapBufferRange(GL_ARRAY_BUFFER, 0, /* offset */
3338													  m_bo_negative_data_vertex_size, GL_MAP_READ_BIT);
3339		(void)bo_ptr;
3340		GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange() call failed.");
3341
3342		/* Perform draw calls that would otherwise have been valid, if it
3343		 * were not for the mapped VBO
3344		 */
3345		glw::GLenum error_code = GL_NONE;
3346
3347		gl.drawElementsBaseVertex(GL_TRIANGLES, 3,								 /* count */
3348								  GL_UNSIGNED_INT, m_draw_call_index_offset, 0); /* basevertex */
3349
3350		error_code = gl.getError();
3351		if (error_code != GL_INVALID_OPERATION)
3352		{
3353			std::stringstream error_sstream;
3354
3355			error_sstream << "Invalid error code generated by "
3356						  << getFunctionName(FUNCTION_GL_DRAW_ELEMENTS_BASE_VERTEX);
3357
3358			m_testCtx.getLog() << tcu::TestLog::Message << getFunctionName(FUNCTION_GL_DRAW_ELEMENTS_BASE_VERTEX)
3359							   << " returned error code [" << error_code << "] instead of GL_INVALID_OPERATION."
3360							   << tcu::TestLog::EndMessage;
3361
3362			TCU_FAIL(error_sstream.str().c_str());
3363		} /* if (error_code != GL_INVALID_OPERATION) */
3364
3365		gl.drawElementsInstancedBaseVertex(GL_TRIANGLES, 3,								 /* count */
3366										   GL_UNSIGNED_INT, m_draw_call_index_offset, 1, /* instancecount */
3367										   0);											 /* basevertex */
3368
3369		error_code = gl.getError();
3370		if (error_code != GL_INVALID_OPERATION)
3371		{
3372			std::stringstream error_sstream;
3373
3374			error_sstream << "Invalid error code generated by "
3375						  << getFunctionName(FUNCTION_GL_DRAW_ELEMENTS_INSTANCED_BASE_VERTEX);
3376
3377			m_testCtx.getLog() << tcu::TestLog::Message
3378							   << getFunctionName(FUNCTION_GL_DRAW_ELEMENTS_INSTANCED_BASE_VERTEX)
3379							   << " returned error code [" << error_code << "] instead of GL_INVALID_OPERATION."
3380							   << tcu::TestLog::EndMessage;
3381
3382			TCU_FAIL(error_sstream.str().c_str());
3383		}
3384
3385		gl.drawRangeElementsBaseVertex(GL_TRIANGLES, 0, 2,							  /* end */
3386									   3,											  /* count */
3387									   GL_UNSIGNED_INT, m_draw_call_index_offset, 0); /* basevertex */
3388
3389		error_code = gl.getError();
3390		if (error_code != GL_INVALID_OPERATION)
3391		{
3392			std::stringstream error_sstream;
3393
3394			error_sstream << "Invalid error code generated by "
3395						  << getFunctionName(FUNCTION_GL_DRAW_RANGE_ELEMENTS_BASE_VERTEX);
3396
3397			m_testCtx.getLog() << tcu::TestLog::Message << getFunctionName(FUNCTION_GL_DRAW_RANGE_ELEMENTS_BASE_VERTEX)
3398							   << " returned error code [" << error_code << "] instead of GL_INVALID_OPERATION."
3399							   << tcu::TestLog::EndMessage;
3400
3401			TCU_FAIL(error_sstream.str().c_str());
3402		}
3403
3404		/* Unmap the BO before we proceed */
3405		gl.unmapBuffer(GL_ARRAY_BUFFER);
3406		GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed");
3407
3408	} /* for (all test iterations) */
3409
3410	/* Test case passed */
3411	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
3412
3413	return STOP;
3414}
3415
3416/** Constructor.
3417 *
3418 *  @param context Rendering context.
3419 */
3420DrawElementsBaseVertexTests::DrawElementsBaseVertexTests(glcts::Context& context, const ExtParameters& extParams)
3421	: TestCaseGroupBase(context, extParams, "draw_elements_base_vertex_tests",
3422						"Contains conformance tests that verify ES and GL implementation's support "
3423						"for GL_EXT_draw_elements_base_vertex (ES) and "
3424						"GL_ARB_draw_elements_base_vertex (GL) extensions.")
3425{
3426}
3427
3428/** Initializes the test group contents. */
3429void DrawElementsBaseVertexTests::init()
3430{
3431	addChild(new DrawElementsBaseVertexFunctionalCorrectBaseVertexBehavior(m_context, m_extParams));
3432	addChild(new DrawElementsBaseVertexFunctionalCorrectBaseVertexBehavior2(m_context, m_extParams));
3433	addChild(new DrawElementsBaseVertexFunctionalCorrectBaseVertexBehaviorAEPShaderStages(m_context, m_extParams));
3434	addChild(new DrawElementsBaseVertexFunctionalCorrectBaseVertexBehaviorUnderflow(m_context, m_extParams));
3435	addChild(new DrawElementsBaseVertexFunctionalCorrectBaseVertexBehaviorOverflow(m_context, m_extParams));
3436	addChild(new DrawElementsBaseVertexNegativeActiveTransformFeedbackTest(m_context, m_extParams));
3437	addChild(new DrawElementsBaseVertexNegativeInvalidCountArgumentTest(m_context, m_extParams));
3438	addChild(new DrawElementsBaseVertexNegativeInvalidInstanceCountArgumentTest(m_context, m_extParams));
3439	addChild(new DrawElementsBaseVertexNegativeInvalidModeArgumentTest(m_context, m_extParams));
3440	addChild(new DrawElementsBaseVertexNegativeInvalidPrimcountArgumentTest(m_context, m_extParams));
3441	addChild(new DrawElementsBaseVertexNegativeInvalidStartEndArgumentsTest(m_context, m_extParams));
3442	addChild(new DrawElementsBaseVertexNegativeInvalidTypeArgumentTest(m_context, m_extParams));
3443	addChild(new DrawElementsBaseVertexNegativeMappedBufferObjectsTest(m_context, m_extParams));
3444}
3445
3446} /* glcts namespace */
3447