Fix missing dependency on sparse binds
[platform/upstream/VK-GL-CTS.git] / external / openglcts / modules / glesext / draw_elements_base_vertex / esextcDrawElementsBaseVertexTests.cpp
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
42 namespace glcts
43 {
44 /** Constructor.
45  *
46  *  @param context     Rendering context
47  *  @param name        Test name
48  *  @param description Test description
49  */
50 DrawElementsBaseVertexTestBase::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  */
216 void 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  **/
360 void 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  */
457 void 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
506 void 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. */
515 void 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  */
591 void 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  **/
635 void 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  */
835 std::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                 else
848                 {
849                         result = "glDrawElementsBaseVertex()";
850                 }
851
852                 break;
853         }
854
855         case FUNCTION_GL_DRAW_ELEMENTS_INSTANCED_BASE_VERTEX:
856         {
857                 if (glu::isContextTypeES(m_context.getRenderContext().getType()))
858                 {
859                         result = "glDrawElementsInstancedBaseVertexEXT()";
860                 }
861                 else
862                 {
863                         result = "glDrawElementsInstancedBaseVertex()";
864                 }
865
866                 break;
867         }
868
869         case FUNCTION_GL_DRAW_RANGE_ELEMENTS_BASE_VERTEX:
870         {
871                 if (glu::isContextTypeES(m_context.getRenderContext().getType()))
872                 {
873                         result = "glDrawRangeElementsBaseVertexEXT()";
874                 }
875                 else
876                 {
877                         result = "glDrawRangeElementsBaseVertex()";
878                 }
879
880                 break;
881         }
882
883         case FUNCTION_GL_MULTI_DRAW_ELEMENTS_BASE_VERTEX:
884         {
885                 if (glu::isContextTypeES(m_context.getRenderContext().getType()))
886                 {
887                         result = "glMultiDrawElementsBaseVertexEXT()";
888                 }
889                 else
890                 {
891                         result = "glMultiDrawElementsBaseVertex()";
892                 }
893
894                 break;
895         }
896
897         default:
898         {
899                 TCU_FAIL("Unknown function type");
900         }
901         } /* switch (function_type) */
902
903         return result;
904 }
905
906 /** Initializes extension-specific function pointers and caches information about
907  *  extension availability.
908  *
909  *  Function pointers for the following extensions are retrieved & stored:
910  *
911  *  - GL_EXT_draw_elements_base_vertex (ES) or GL_ARB_draw_elements_base_vertex (GL)
912  *  - GL_EXT_multi_draw_arrays         (ES & GL)
913  *
914  *  Availability of the following extensions is checked & cached:
915  *
916  *  - GL_EXT_draw_elements_base_vertex (ES) or GL_ARB_draw_elements_base_vertex (GL)
917  *  - GL_EXT_geometry_shader           (ES) or GL_ARB_geometry_shader4          (GL)
918  *  - GL_EXT_multi_draw_arrays         (ES & GL)
919  *  - GL_EXT_tessellation_shader       (ES) or GL_ARB_tessellation_shader (GL)
920  */
921 void DrawElementsBaseVertexTestBase::init()
922 {
923         TestCaseBase::init();
924
925         const glu::ContextInfo& context_info = m_context.getContextInfo();
926
927         if ((glu::isContextTypeES(m_context.getRenderContext().getType()) &&
928                  (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2)) ||
929                   context_info.isExtensionSupported("GL_EXT_draw_elements_base_vertex"))) ||
930                 context_info.isExtensionSupported("GL_ARB_draw_elements_base_vertex"))
931         {
932 #if defined(DE_DEBUG) && !defined(DE_COVERAGE_BUILD)
933                 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
934 #endif
935
936                 m_is_draw_elements_base_vertex_supported = true;
937
938                 DE_ASSERT(gl.drawElementsBaseVertex != NULL);
939                 DE_ASSERT(gl.drawElementsInstancedBaseVertex != NULL);
940                 DE_ASSERT(gl.drawRangeElementsBaseVertex != NULL);
941
942                 /* NOTE: glMultiDrawElementsBaseVertex() is a part of the draw_elements_base_vertex extension in GL,
943                  *       but requires a separate extension under ES.
944                  */
945                 if (!glu::isContextTypeES(m_context.getRenderContext().getType()) ||
946                         context_info.isExtensionSupported("GL_EXT_multi_draw_arrays"))
947                 {
948                         m_is_ext_multi_draw_arrays_supported = true;
949
950                         DE_ASSERT(gl.multiDrawElementsBaseVertex != NULL);
951                 } /* if (GL_EXT_multi_draw_arrays is supported or GL context is being tested) */
952
953                 if (glu::isContextTypeES(m_context.getRenderContext().getType()))
954                 {
955                         /* This conformance test needs to be adjusted in order to run under < ES3.1 contexts */
956                         DE_ASSERT(glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 1)));
957                 }
958                 else
959                 {
960                         m_is_vertex_attrib_binding_supported = context_info.isExtensionSupported("GL_ARB_vertex_attrib_binding");
961                 }
962         } /* if (GL_{ARB, EXT}_draw_elements_base_vertex is supported) */
963
964         if ((glu::isContextTypeES(m_context.getRenderContext().getType()) &&
965                  (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2)) ||
966                   context_info.isExtensionSupported("GL_EXT_geometry_shader"))) ||
967                 context_info.isExtensionSupported("GL_ARB_geometry_shader4"))
968         {
969                 m_is_geometry_shader_supported = true;
970         }
971
972         if ((glu::isContextTypeES(m_context.getRenderContext().getType()) &&
973                  (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2)) ||
974                   context_info.isExtensionSupported("GL_EXT_tessellation_shader"))) ||
975                 context_info.isExtensionSupported("GL_ARB_tessellation_shader"))
976         {
977                 m_is_tessellation_shader_supported = true;
978         }
979
980         if (!m_is_draw_elements_base_vertex_supported)
981         {
982                 throw tcu::NotSupportedError("draw_elements_base_vertex functionality is not supported");
983         }
984 }
985
986 /** Sets up all ES objects required to run a single functional test case iteration.
987  *
988  *  @param use_clientside_vertex_data    true if the test case requires client-side buffers to
989  *                                       back the color/vertex vertex attribute arrays; false
990  *                                       to use buffer object storage.
991  *  @param use_clientside_index_data     true if the test case requires client-side buffers to
992  *                                       be used as index data source; false to use buffer object
993  *                                       storage.
994  *  @param use_tessellation_shader_stage true if the program object used for the test should include
995  *                                       tessellation control & evaluation shader stages; false to
996  *                                       not to include these shader stages in the pipeline.
997  *  @param use_geometry_shader_stage     true if the program object used for the test should include
998  *                                       geometry shader stage; false to not to include the shader
999  *                                       stage in the pipeline.
1000  *  @param use_vertex_attrib_binding     true if vertex attribute bindings should be used for
1001  *                                       vertex array object configuration. This also modifies the
1002  *                                       vertex shader, so that instead of calculating vertex color
1003  *                                       on a per-vertex basis, contents of the "color" input
1004  *                                       will be used as a data source for the color data.
1005  *                                       false to use a vertex attribute array configured with
1006  *                                       a casual glVertexAttribPointer() call.
1007  * @param use_overflow_test_vertices     true if using an especially large vertex array to test
1008  *                                       overflow behavior.
1009  *
1010  *  This method can throw an exception if any of the ES calls fail.
1011  **/
1012 void DrawElementsBaseVertexTestBase::setUpFunctionalTestObjects(
1013         bool use_clientside_vertex_data, bool use_clientside_index_data, bool use_tessellation_shader_stage,
1014         bool use_geometry_shader_stage, bool use_vertex_attrib_binding, bool use_overflow_test_vertices)
1015 {
1016         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1017
1018         /* Set up a texture object that we will use as a color attachment */
1019         gl.genTextures(1, &m_to_base_id);
1020         gl.genTextures(1, &m_to_ref_id);
1021         GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call(s) failed.");
1022
1023         const glw::GLuint  to_ids[] = { m_to_base_id, m_to_ref_id };
1024         const unsigned int n_to_ids = sizeof(to_ids) / sizeof(to_ids[0]);
1025
1026         for (unsigned int n_to_id = 0; n_to_id < n_to_ids; ++n_to_id)
1027         {
1028                 gl.bindTexture(GL_TEXTURE_2D, to_ids[n_to_id]);
1029                 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");
1030
1031                 gl.texStorage2D(GL_TEXTURE_2D, 1, /* levels */
1032                                                 GL_RGBA8, m_to_width, m_to_height);
1033                 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D() call failed.");
1034         }
1035
1036         /* Also set up some buffers we will use for data comparison */
1037         m_to_base_data = new unsigned char[m_to_width * m_to_height * 4 /* components */];
1038         m_to_ref_data  = new unsigned char[m_to_width * m_to_height * 4 /* components */];
1039
1040         /* Finally, for glReadPixels() operations, we need to make sure that pack alignment is set to 1 */
1041         gl.pixelStorei(GL_PACK_ALIGNMENT, 1);
1042         GLU_EXPECT_NO_ERROR(gl.getError(), "glPixelStorei() call failed.");
1043
1044         /* Proceed with framebuffer object initialization. Since we will be rendering to different
1045          * render-targets, there's not much point in attaching any of the textures at this point.
1046          */
1047         gl.genFramebuffers(1, &m_fbo_id);
1048         GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers() call failed.");
1049
1050         gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo_id);
1051         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebufer() call failed");
1052
1053         gl.viewport(0, /* x */
1054                                 0, /* y */
1055                                 m_to_width, m_to_height);
1056         GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport() call failed");
1057
1058         /* Set up buffer object we will use for the draw calls. Use the data
1059          * from the test specification.
1060          *
1061          * NOTE: If you need to change the data layout here, make sure you also update
1062          *       m_draw_call_color_offset, m_draw_call_index*_offset, and
1063          *       m_draw_call_vertex*_offset setter calls elsewhere.
1064          **/
1065         if (m_bo_id == 0)
1066         {
1067                 unsigned int current_offset = 0;
1068
1069                 gl.genBuffers(1, &m_bo_id);
1070                 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed.");
1071
1072                 gl.bindBuffer(GL_ARRAY_BUFFER, m_bo_id);
1073                 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
1074
1075                 gl.bufferData(GL_ARRAY_BUFFER,
1076                                           m_bo_functional_data_index_size + m_bo_functional_data_vertex_size +
1077                                                   m_bo_functional2_data_vertex_size + m_bo_functional2_data_index_size +
1078                                                   m_bo_functional3_data_index_size + m_bo_functional4_data_index_size +
1079                                                   m_bo_functional5_data_index_size + m_bo_functional_data_color_size,
1080                                           DE_NULL, /* data */
1081                                           GL_STATIC_DRAW);
1082                 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
1083
1084                 gl.bufferSubData(GL_ARRAY_BUFFER, current_offset, m_bo_functional_data_vertex_size,
1085                                                  m_bo_functional_data_vertex);
1086                 current_offset += m_bo_functional_data_vertex_size;
1087
1088                 gl.bufferSubData(GL_ARRAY_BUFFER, current_offset, m_bo_functional2_data_vertex_size,
1089                                                  m_bo_functional2_data_vertex);
1090                 current_offset += m_bo_functional2_data_vertex_size;
1091
1092                 gl.bufferSubData(GL_ARRAY_BUFFER, current_offset, m_bo_functional_data_index_size, m_bo_functional_data_index);
1093                 current_offset += m_bo_functional_data_index_size;
1094
1095                 gl.bufferSubData(GL_ARRAY_BUFFER, current_offset, m_bo_functional2_data_index_size,
1096                                                  m_bo_functional2_data_index);
1097                 current_offset += m_bo_functional2_data_index_size;
1098
1099                 gl.bufferSubData(GL_ARRAY_BUFFER, current_offset, m_bo_functional3_data_index_size,
1100                                                  m_bo_functional3_data_index);
1101                 current_offset += m_bo_functional3_data_index_size;
1102
1103                 gl.bufferSubData(GL_ARRAY_BUFFER, current_offset, m_bo_functional4_data_index_size,
1104                                                  m_bo_functional4_data_index);
1105                 current_offset += m_bo_functional4_data_index_size;
1106
1107                 gl.bufferSubData(GL_ARRAY_BUFFER, current_offset, m_bo_functional5_data_index_size,
1108                                                  m_bo_functional5_data_index);
1109                 current_offset += m_bo_functional5_data_index_size;
1110
1111                 gl.bufferSubData(GL_ARRAY_BUFFER, current_offset, m_bo_functional_data_color_size, m_bo_functional_data_color);
1112                 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferSubData() call(s) failed.");
1113         }
1114
1115         if (use_overflow_test_vertices && m_bo_id_2 == 0)
1116         {
1117                 /* Create a special buffer that only has vertex data in a few slots */
1118                 gl.genBuffers(1, &m_bo_id_2);
1119                 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed");
1120
1121                 gl.bindBuffer(GL_ARRAY_BUFFER, m_bo_id_2);
1122                 gl.bufferData(GL_ARRAY_BUFFER, 2 * 65550 * sizeof(glw::GLfloat), NULL, GL_STATIC_DRAW);
1123                 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed");
1124
1125                 /*
1126                  * Upload to offset 0:     regular draw call indices for making sure ubyte
1127                  *                         and ushort indices don't wrap around too early
1128                  * Upload to offset 256:   base draw call indices of type ubyte
1129                  * Upload to offset 65536: base draw call indices of type ushort
1130                  */
1131                 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,
1132                                                                   -0.9f, -0.9f, 0.9f,  -0.9f, 0.9f,  0.9f,  -0.9f, 0.9f,  -0.9f, -0.9f, 0.9f,  -0.9f };
1133                 gl.bufferSubData(GL_ARRAY_BUFFER, 0, sizeof(badVtx), badVtx);
1134                 gl.bufferSubData(GL_ARRAY_BUFFER, 2 * 256 * sizeof(glw::GLfloat), 2 * 12 * sizeof(glw::GLfloat),
1135                                                  m_bo_functional_data_vertex);
1136                 gl.bufferSubData(GL_ARRAY_BUFFER, 2 * 65536 * sizeof(glw::GLfloat), 2 * 12 * sizeof(glw::GLfloat),
1137                                                  m_bo_functional_data_vertex);
1138                 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferSubData() call failed");
1139         }
1140
1141         /* Set up the test program object */
1142         if (m_po_id == 0 || m_po_uses_gs_stage != use_geometry_shader_stage ||
1143                 m_po_uses_tc_te_stages != use_tessellation_shader_stage ||
1144                 m_po_uses_vertex_attrib_binding != use_vertex_attrib_binding)
1145
1146         {
1147                 static const char* functional_fs_code = "${VERSION}\n"
1148                                                                                                 "\n"
1149                                                                                                 "precision highp float;\n"
1150                                                                                                 "\n"
1151                                                                                                 "in  vec4 FS_COLOR_INPUT_NAME;\n"
1152                                                                                                 "out vec4 result;\n"
1153                                                                                                 "\n"
1154                                                                                                 "void main()\n"
1155                                                                                                 "{\n"
1156                                                                                                 "    result = FS_COLOR_INPUT_NAME;\n"
1157                                                                                                 "}\n";
1158                 static const char* functional_gs_code = "${VERSION}\n"
1159                                                                                                 "${GEOMETRY_SHADER_REQUIRE}\n"
1160                                                                                                 "\n"
1161                                                                                                 "layout(triangles)                        in;\n"
1162                                                                                                 "layout(triangle_strip, max_vertices = 3) out;\n"
1163                                                                                                 "\n"
1164                                                                                                 "in  vec4 GS_COLOR_INPUT_NAME[];\n"
1165                                                                                                 "out vec4 FS_COLOR_INPUT_NAME;\n"
1166                                                                                                 "\n"
1167                                                                                                 "void main()\n"
1168                                                                                                 "{\n"
1169                                                                                                 "    for (int n = 0; n < 3; ++n)\n"
1170                                                                                                 "    {\n"
1171                                                                                                 "        gl_Position         = vec4(gl_in[n].gl_Position.x, "
1172                                                                                                 "-gl_in[n].gl_Position.y, gl_in[n].gl_Position.zw);\n"
1173                                                                                                 "        FS_COLOR_INPUT_NAME = GS_COLOR_INPUT_NAME[n];\n"
1174                                                                                                 "\n"
1175                                                                                                 "        EmitVertex();\n"
1176                                                                                                 "    }\n"
1177                                                                                                 "\n"
1178                                                                                                 "    EndPrimitive();\n"
1179                                                                                                 "}\n";
1180                 static const char* functional_tc_code =
1181                         "${VERSION}\n"
1182                         "${TESSELLATION_SHADER_REQUIRE}\n"
1183                         "\n"
1184                         "in  vec4 TC_COLOR_INPUT_NAME[];\n"
1185                         "out vec4 TE_COLOR_INPUT_NAME[];\n"
1186                         "\n"
1187                         "layout(vertices = 3) out;\n"
1188                         "\n"
1189                         "void main()\n"
1190                         "{\n"
1191                         "    gl_out             [gl_InvocationID].gl_Position = gl_in              [gl_InvocationID].gl_Position;\n"
1192                         "    TE_COLOR_INPUT_NAME[gl_InvocationID]             = TC_COLOR_INPUT_NAME[gl_InvocationID];\n"
1193                         "\n"
1194                         "    gl_TessLevelInner[0] = 3.0;\n"
1195                         "    gl_TessLevelOuter[0] = 3.0;\n"
1196                         "    gl_TessLevelOuter[1] = 3.0;\n"
1197                         "    gl_TessLevelOuter[2] = 3.0;\n"
1198                         "}\n";
1199                 static const char* functional_te_code =
1200                         "${VERSION}\n"
1201                         "\n"
1202                         "${TESSELLATION_SHADER_REQUIRE}\n"
1203                         "\n"
1204                         "layout(triangles, equal_spacing, cw) in;\n"
1205                         "\n"
1206                         "in  vec4 TE_COLOR_INPUT_NAME[];\n"
1207                         "out vec4 TE_COLOR_OUTPUT_NAME;\n"
1208                         "\n"
1209                         "void main()\n"
1210                         "{\n"
1211                         "    vec2 p1 = gl_in[0].gl_Position.xy;\n"
1212                         "    vec2 p2 = gl_in[1].gl_Position.xy;\n"
1213                         "    vec2 p3 = gl_in[2].gl_Position.xy;\n"
1214                         "\n"
1215                         "    TE_COLOR_OUTPUT_NAME = TE_COLOR_INPUT_NAME[0] + TE_COLOR_INPUT_NAME[1] + TE_COLOR_INPUT_NAME[2];\n"
1216                         "    gl_Position          = vec4(gl_TessCoord.x * p1.x + gl_TessCoord.y * p2.x + gl_TessCoord.z * p3.x,\n"
1217                         "                                gl_TessCoord.x * p1.y + gl_TessCoord.y * p2.y + gl_TessCoord.z * p3.y,\n"
1218                         "                                0.0,\n"
1219                         "                                1.0);\n"
1220                         "}\n";
1221                 static const char* functional_vs_code = "${VERSION}\n"
1222                                                                                                 "\n"
1223                                                                                                 "out vec4 VS_COLOR_OUTPUT_NAME;\n"
1224                                                                                                 "in  vec4 vertex;\n"
1225                                                                                                 "\n"
1226                                                                                                 "OPTIONAL_USE_VERTEX_ATTRIB_BINDING_DEFINITIONS\n"
1227                                                                                                 "\n"
1228                                                                                                 "void main()\n"
1229                                                                                                 "{\n"
1230                                                                                                 "    float vertex_id_float = float(gl_VertexID);\n"
1231                                                                                                 "\n"
1232                                                                                                 "#ifdef USE_VERTEX_ATTRIB_BINDING\n"
1233                                                                                                 "    vec4  color           = in_color;\n"
1234                                                                                                 "#else\n"
1235                                                                                                 "    vec4  color           = vec4(vertex_id_float / 7.0,\n"
1236                                                                                                 "                                 vertex_id_float / 3.0,\n"
1237                                                                                                 "                                 vertex_id_float / 17.0,\n"
1238                                                                                                 "                                 1.0);\n"
1239                                                                                                 "#endif\n"
1240                                                                                                 "    float scale           = (gl_InstanceID == 0) ? 1.0 :\n"
1241                                                                                                 "                            (gl_InstanceID == 1) ? 0.8 :\n"
1242                                                                                                 "                                                   0.5;\n"
1243                                                                                                 "\n"
1244                                                                                                 "    VS_COLOR_OUTPUT_NAME = color;\n"
1245                                                                                                 "    gl_Position          = vec4(vertex.xy * scale, vertex.zw);\n"
1246                                                                                                 "}\n";
1247
1248                 /* Release a program object if one has already been set up for the running test */
1249                 deinitProgramAndShaderObjects();
1250
1251                 /* Replace the tokens with actual variable names */
1252                 std::string fs_body                                       = specializeShader(1, &functional_fs_code);
1253                 std::string fs_color_input_name_token = "FS_COLOR_INPUT_NAME";
1254                 std::string fs_color_input_name_token_value;
1255                 std::string gs_body                                       = specializeShader(1, &functional_gs_code);
1256                 std::string gs_color_input_name_token = "GS_COLOR_INPUT_NAME";
1257                 std::string gs_color_input_name_token_value;
1258                 std::string tc_body                                       = specializeShader(1, &functional_tc_code);
1259                 std::string tc_color_input_name_token = "TC_COLOR_INPUT_NAME";
1260                 std::string tc_color_input_name_token_value;
1261                 std::string te_body                                       = specializeShader(1, &functional_te_code);
1262                 std::string te_color_input_name_token = "TE_COLOR_INPUT_NAME";
1263                 std::string te_color_input_name_token_value;
1264                 std::string te_color_output_name_token = "TE_COLOR_OUTPUT_NAME";
1265                 std::string te_color_output_name_token_value;
1266                 std::string vs_body                                        = specializeShader(1, &functional_vs_code);
1267                 std::string vs_color_output_name_token = "VS_COLOR_OUTPUT_NAME";
1268                 std::string vs_color_output_name_token_value;
1269                 std::string vs_optional_use_vertex_attrib_binding_definitions_token =
1270                         "OPTIONAL_USE_VERTEX_ATTRIB_BINDING_DEFINITIONS";
1271                 std::string vs_optional_use_vertex_attrib_binding_definitions_token_value;
1272
1273                 std::string*       bodies[] = { &fs_body, &gs_body, &tc_body, &te_body, &vs_body };
1274                 const unsigned int n_bodies = sizeof(bodies) / sizeof(bodies[0]);
1275
1276                 std::string* token_value_pairs[] = { &fs_color_input_name_token,
1277                                                                                          &fs_color_input_name_token_value,
1278                                                                                          &gs_color_input_name_token,
1279                                                                                          &gs_color_input_name_token_value,
1280                                                                                          &tc_color_input_name_token,
1281                                                                                          &tc_color_input_name_token_value,
1282                                                                                          &te_color_input_name_token,
1283                                                                                          &te_color_input_name_token_value,
1284                                                                                          &te_color_output_name_token,
1285                                                                                          &te_color_output_name_token_value,
1286                                                                                          &vs_color_output_name_token,
1287                                                                                          &vs_color_output_name_token_value,
1288                                                                                          &vs_optional_use_vertex_attrib_binding_definitions_token,
1289                                                                                          &vs_optional_use_vertex_attrib_binding_definitions_token_value };
1290                 const unsigned int n_token_value_pairs =
1291                         sizeof(token_value_pairs) / sizeof(token_value_pairs[0]) / 2 /* token+value */;
1292
1293                 if (!use_tessellation_shader_stage)
1294                 {
1295                         if (!use_geometry_shader_stage)
1296                         {
1297                                 /* Geometry & tessellation shader stages are not required.
1298                                  *
1299                                  * NOTE: This code-path is also used by Functional Test VII which verifies that
1300                                  *       vertex attribute bindings work correctly with basevertex draw calls.
1301                                  *       The test only uses FS & VS in its rendering pipeline and consumes a color
1302                                  *       taken from an enabled vertex attribute array instead of a vector value
1303                                  *       calculated in vertex shader stage,
1304                                  */
1305                                 vs_color_output_name_token_value = "out_vs_color";
1306                                 fs_color_input_name_token_value  = vs_color_output_name_token_value;
1307
1308                                 if (use_vertex_attrib_binding)
1309                                 {
1310                                         vs_optional_use_vertex_attrib_binding_definitions_token_value =
1311                                                 "#define USE_VERTEX_ATTRIB_BINDING\n"
1312                                                 "in vec4 in_color;\n";
1313                                 }
1314                         } /* if (!use_geometry_shader_stage) */
1315                         else
1316                         {
1317                                 /* Geometry shader stage is needed, but tessellation shader stage
1318                                  * can be skipped */
1319                                 fs_color_input_name_token_value  = "out_fs_color";
1320                                 gs_color_input_name_token_value  = "out_vs_color";
1321                                 vs_color_output_name_token_value = "out_vs_color";
1322
1323                                 DE_ASSERT(!use_vertex_attrib_binding);
1324                         }
1325                 } /* if (!use_tessellation_shader_stage) */
1326                 else
1327                 {
1328                         DE_ASSERT(!use_vertex_attrib_binding);
1329
1330                         if (!use_geometry_shader_stage)
1331                         {
1332                                 /* Tessellation shader stage is needed, but geometry shader stage
1333                                  * can be skipped */
1334                                 fs_color_input_name_token_value  = "out_fs_color";
1335                                 tc_color_input_name_token_value  = "out_vs_color";
1336                                 te_color_input_name_token_value  = "out_tc_color";
1337                                 te_color_output_name_token_value = "out_fs_color";
1338                                 vs_color_output_name_token_value = "out_vs_color";
1339                         } /* if (!use_geometry_shader_stage) */
1340                         else
1341                         {
1342                                 /* Both tessellation and geometry shader stages are needed */
1343                                 fs_color_input_name_token_value  = "out_fs_color";
1344                                 gs_color_input_name_token_value  = "out_te_color";
1345                                 tc_color_input_name_token_value  = "out_vs_color";
1346                                 te_color_input_name_token_value  = "out_tc_color";
1347                                 te_color_output_name_token_value = "out_te_color";
1348                                 vs_color_output_name_token_value = "out_vs_color";
1349                         }
1350                 }
1351
1352                 for (unsigned int n_body = 0; n_body < n_bodies; ++n_body)
1353                 {
1354                         std::string* body_ptr = bodies[n_body];
1355
1356                         for (unsigned int n_token_value_pair = 0; n_token_value_pair < n_token_value_pairs; ++n_token_value_pair)
1357                         {
1358                                 std::string token                  = *token_value_pairs[2 * n_token_value_pair + 0];
1359                                 std::size_t token_location = std::string::npos;
1360                                 std::string value                  = *token_value_pairs[2 * n_token_value_pair + 1];
1361
1362                                 while ((token_location = body_ptr->find(token)) != std::string::npos)
1363                                 {
1364                                         body_ptr->replace(token_location, token.length(), value);
1365                                 } /* while (tokens are found) */
1366                         }        /* for (all token+value pairs) */
1367                 }                 /* for (all bodies) */
1368
1369                 /* Build the actual program */
1370                 buildProgram(fs_body.c_str(), vs_body.c_str(), use_tessellation_shader_stage ? tc_body.c_str() : DE_NULL,
1371                                          use_tessellation_shader_stage ? te_body.c_str() : DE_NULL,
1372                                          use_geometry_shader_stage ? gs_body.c_str() : DE_NULL);
1373
1374                 m_po_uses_gs_stage                              = use_geometry_shader_stage;
1375                 m_po_uses_tc_te_stages                  = use_tessellation_shader_stage;
1376                 m_po_uses_vertex_attrib_binding = use_vertex_attrib_binding;
1377         }
1378
1379         /* Set up the vertex array object */
1380         if (m_vao_id != 0)
1381         {
1382                 gl.deleteVertexArrays(1, &m_vao_id);
1383                 GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteVertexArrays() call failed.");
1384
1385                 m_vao_id = 0;
1386         }
1387
1388         if (!use_clientside_vertex_data)
1389         {
1390                 gl.genVertexArrays(1, &m_vao_id);
1391                 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
1392         }
1393         gl.bindVertexArray(m_vao_id);
1394         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
1395
1396         if (m_po_color_attribute_location != -1)
1397         {
1398                 DE_ASSERT(use_vertex_attrib_binding);
1399
1400                 gl.enableVertexAttribArray(m_po_color_attribute_location);
1401         }
1402
1403         gl.enableVertexAttribArray(m_po_vertex_attribute_location);
1404         GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray() call(s) failed.");
1405
1406         /* Configure the VAO */
1407         if (use_clientside_index_data)
1408         {
1409                 gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
1410                 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
1411         }
1412         else
1413         {
1414                 gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_bo_id);
1415                 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
1416         }
1417
1418         if (use_clientside_vertex_data)
1419         {
1420                 gl.bindBuffer(GL_ARRAY_BUFFER, 0);
1421                 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
1422         }
1423         else
1424         {
1425                 gl.bindBuffer(GL_ARRAY_BUFFER, use_overflow_test_vertices ? m_bo_id_2 : m_bo_id);
1426                 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
1427         }
1428
1429         if (!use_vertex_attrib_binding)
1430         {
1431                 DE_ASSERT(m_po_color_attribute_location == -1);
1432
1433                 gl.vertexAttribPointer(m_po_vertex_attribute_location, 2, /* size */
1434                                                            GL_FLOAT, GL_FALSE,                            /* normalized */
1435                                                            0,                                                             /* stride */
1436                                                            m_draw_call_vertex_offset);
1437                 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer() call failed.");
1438         } /* if (!use_vertex_attrib_binding) */
1439         else
1440         {
1441                 DE_ASSERT(m_po_color_attribute_location != -1);
1442                 DE_ASSERT(m_draw_call_vertex_offset < m_draw_call_color_offset);
1443
1444                 gl.vertexAttribFormat(m_po_color_attribute_location, 2, /* size */
1445                                                           GL_FLOAT,                                                     /* type */
1446                                                           GL_FALSE,                                                     /* normalized */
1447                                                           (glw::GLuint)((const glw::GLubyte*)m_draw_call_color_offset -
1448                                                                                         (const glw::GLubyte*)m_draw_call_vertex_offset));
1449                 gl.vertexAttribFormat(m_po_vertex_attribute_location, 2, /* size */
1450                                                           GL_FLOAT,                                                      /* type */
1451                                                           GL_FALSE,                                                      /* normalized */
1452                                                           0);                                                            /* relativeoffset */
1453                 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribFormat() call(s) failed.");
1454
1455                 gl.vertexAttribBinding(m_po_color_attribute_location, 0);  /* bindingindex */
1456                 gl.vertexAttribBinding(m_po_vertex_attribute_location, 0); /* bindingindex */
1457                 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribBinding() call(s) failed.");
1458
1459                 gl.bindVertexBuffer(0, /* bindingindex */
1460                                                         (use_clientside_vertex_data) ? 0 : (use_overflow_test_vertices ? m_bo_id_2 : m_bo_id),
1461                                                         (glw::GLintptr)m_draw_call_vertex_offset, sizeof(float) * 2);
1462                 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexBuffer() call failed.");
1463         }
1464
1465         /* Bind the program object to the rendering context */
1466         gl.useProgram(m_po_id);
1467         GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
1468 }
1469
1470 /** Sets up all ES objects required to run a single negative test case iteration.
1471  *
1472  *  @param use_clientside_vertex_data    true if the test case requires client-side buffers to
1473  *                                       back the color/vertex vertex attribute arrays; false
1474  *                                       to use buffer object storage.
1475  *  @param use_clientside_index_data     true if the test case requires client-side buffers to
1476  *                                       be used as index data source; false to use buffer object
1477  *                                       storage.
1478  */
1479 void DrawElementsBaseVertexTestBase::setUpNegativeTestObjects(bool use_clientside_vertex_data,
1480                                                                                                                           bool use_clientside_index_data)
1481 {
1482         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1483
1484         /* Set up buffer object we will use for the draw calls. Use the data
1485          * from the test specification */
1486         if (m_bo_id == 0)
1487         {
1488                 gl.genBuffers(1, &m_bo_id);
1489                 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed.");
1490
1491                 gl.bindBuffer(GL_ARRAY_BUFFER, m_bo_id);
1492                 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
1493
1494                 gl.bufferData(GL_ARRAY_BUFFER, m_bo_negative_data_index_size + m_bo_negative_data_vertex_size,
1495                                           DE_NULL, /* data */
1496                                           GL_STATIC_DRAW);
1497                 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
1498
1499                 gl.bufferSubData(GL_ARRAY_BUFFER, 0, /* offset */
1500                                                  m_bo_negative_data_vertex_size, m_bo_negative_data_vertex);
1501                 gl.bufferSubData(GL_ARRAY_BUFFER, m_bo_negative_data_vertex_size, /* offset */
1502                                                  m_bo_negative_data_index_size, m_bo_negative_data_index);
1503                 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferSubData() call(s) failed.");
1504         }
1505
1506         if (use_clientside_index_data)
1507         {
1508                 m_draw_call_index_offset = m_bo_negative_data_index;
1509         }
1510         else
1511         {
1512                 m_draw_call_index_offset = (const glw::GLuint*)(deUintptr)m_bo_negative_data_vertex_size;
1513         }
1514
1515         if (use_clientside_vertex_data)
1516         {
1517                 m_draw_call_vertex_offset = m_bo_negative_data_vertex;
1518         }
1519         else
1520         {
1521                 m_draw_call_vertex_offset = DE_NULL;
1522         }
1523
1524         /* Set up the test program object */
1525         if (m_po_id == 0)
1526         {
1527                 static const char* negative_fs_code = "${VERSION}\n"
1528                                                                                           "precision highp float;\n"
1529                                                                                           "\n"
1530                                                                                           "out vec4 result;\n"
1531                                                                                           "\n"
1532                                                                                           "void main()\n"
1533                                                                                           "{\n"
1534                                                                                           "    result = vec4(1.0);\n"
1535                                                                                           "}\n";
1536                 static const char* negative_vs_code = "${VERSION}\n"
1537                                                                                           "\n"
1538                                                                                           "in vec4 vertex;\n"
1539                                                                                           "\n"
1540                                                                                           "void main()\n"
1541                                                                                           "{\n"
1542                                                                                           "    gl_Position = vertex;\n"
1543                                                                                           "}\n";
1544
1545                 std::string fs_specialized_code         = specializeShader(1, &negative_fs_code);
1546                 const char* fs_specialized_code_raw = fs_specialized_code.c_str();
1547                 std::string vs_specialized_code         = specializeShader(1, &negative_vs_code);
1548                 const char* vs_specialized_code_raw = vs_specialized_code.c_str();
1549
1550                 buildProgram(fs_specialized_code_raw, vs_specialized_code_raw, DE_NULL, /* tc_code */
1551                                          DE_NULL,                                                                                                       /* te_code */
1552                                          DE_NULL);                                                                                                      /* gs_code */
1553         }
1554
1555         /* Set up a vertex array object */
1556         if (m_vao_id == 0)
1557         {
1558                 gl.genVertexArrays(1, &m_vao_id);
1559                 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
1560
1561                 gl.bindVertexArray(m_vao_id);
1562                 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
1563
1564                 gl.enableVertexAttribArray(m_po_vertex_attribute_location);
1565                 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray() call failed.");
1566         }
1567
1568         /* Configure the VAO */
1569         if (use_clientside_index_data)
1570         {
1571                 gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
1572                 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
1573         }
1574         else
1575         {
1576                 gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_bo_id);
1577                 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
1578         }
1579
1580         if (use_clientside_vertex_data)
1581         {
1582                 gl.bindBuffer(GL_ARRAY_BUFFER, 0);
1583                 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
1584
1585                 gl.bindVertexArray(0);
1586                 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
1587         }
1588         else
1589         {
1590                 gl.bindBuffer(GL_ARRAY_BUFFER, m_bo_id);
1591                 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
1592         }
1593
1594         gl.vertexAttribPointer(m_po_vertex_attribute_location, 2, /* size */
1595                                                    GL_FLOAT, GL_FALSE,                            /* normalized */
1596                                                    0,                                                             /* stride */
1597                                                    m_draw_call_vertex_offset);
1598         GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer() call failed.");
1599
1600         /* Bind the program object to the rendering context */
1601         gl.useProgram(m_po_id);
1602         GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
1603 }
1604
1605 /** Constructor.
1606  *
1607  *  @param context Rendering context handle.
1608  **/
1609 DrawElementsBaseVertexFunctionalCorrectBaseVertexBehavior::DrawElementsBaseVertexFunctionalCorrectBaseVertexBehavior(
1610         Context& context, const ExtParameters& extParams)
1611         : DrawElementsBaseVertexTestBase(context, extParams, "basevertex_behavior1",
1612                                                                          "Verifies basevertex draw calls work correctly for a number of "
1613                                                                          "different rendering pipeline and VAO configurations")
1614 {
1615         /* Left blank on purpose */
1616 }
1617
1618 /** Sets up test case descriptors for the test instance. These will later be used
1619  *  as input for DrawElementsBaseVertexTestBase::executeTestCases(), which performs
1620  *  the actual testing.
1621  **/
1622 void DrawElementsBaseVertexFunctionalCorrectBaseVertexBehavior::setUpTestCases()
1623 {
1624         /* Set up test case descriptors */
1625         const glw::GLint   basevertex_values[] = { 10, 0 };
1626         const unsigned int n_basevertex_values = sizeof(basevertex_values) / sizeof(basevertex_values[0]);
1627
1628         /* The test needs to be run in two iterations, using client-side memory and buffer object
1629          * for index data respectively
1630          */
1631         for (int vao_iteration = 0; vao_iteration < 2; ++vao_iteration)
1632         {
1633                 /* Skip client-side vertex array as gl_VertexID is undefined when no buffer bound to ARRAY_BUFFER
1634                  *  See section 11.1.3.9 in OpenGL ES 3.1 spec
1635                  */
1636                 bool use_clientside_vertex_data = 0;
1637                 bool use_clientside_index_data  = ((vao_iteration & (1 << 0)) != 0);
1638
1639                 /* OpenGL does not support client-side data. */
1640                 if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
1641                 {
1642                         if (use_clientside_index_data || use_clientside_vertex_data)
1643                         {
1644                                 continue;
1645                         }
1646                 }
1647
1648                 /* Compute the offsets */
1649                 computeVBODataOffsets(use_clientside_index_data, use_clientside_vertex_data);
1650
1651                 /* There are two index data sets we need to iterate over */
1652                 const glw::GLuint* index_offsets[] = { m_draw_call_index_offset, m_draw_call_index2_offset };
1653                 const unsigned int n_index_offsets = sizeof(index_offsets) / sizeof(index_offsets[0]);
1654
1655                 for (unsigned int n_index_offset = 0; n_index_offset < n_index_offsets; ++n_index_offset)
1656                 {
1657                         const glw::GLuint* current_index_offset = index_offsets[n_index_offset];
1658
1659                         /* We need to test four different functions:
1660                          *
1661                          * a)    glDrawElementsBaseVertex()             (GL)
1662                          *    or glDrawElementsBaseVertexEXT()          (ES)
1663                          * b)    glDrawRangeElementsBaseVertex()        (GL)
1664                          *    or glDrawRangeElementsBaseVertexEXT()     (ES)
1665                          * c)    glDrawElementsInstancedBaseVertex()    (GL)
1666                          *    or glDrawElementsInstancedBaseVertexEXT() (ES)
1667                          * d)    glMultiDrawElementsBaseVertex()        (GL)
1668                          *    or glMultiDrawElementsBaseVertexEXT()     (ES) (if supported)
1669                          **/
1670                         for (int n_function = 0; n_function < FUNCTION_COUNT; ++n_function)
1671                         {
1672                                 /* Do not try to use the multi draw call if relevant extension is
1673                                  * not supported. */
1674                                 if (!m_is_ext_multi_draw_arrays_supported && n_function == FUNCTION_GL_MULTI_DRAW_ELEMENTS_BASE_VERTEX)
1675                                 {
1676                                         continue;
1677                                 }
1678
1679                                 /* We need to run the test for a number of different basevertex values. */
1680                                 for (unsigned int n_basevertex_value = 0; n_basevertex_value < n_basevertex_values;
1681                                          ++n_basevertex_value)
1682                                 {
1683                                         /* Finally, we want to verify that basevertex draw calls work correctly both when vertex attribute
1684                                          * bindings are enabled and disabled */
1685                                         bool             vertex_attrib_binding_statuses[] = { false, true };
1686                                         unsigned int n_vertex_attrib_binding_statuses =
1687                                                 sizeof(vertex_attrib_binding_statuses) / sizeof(vertex_attrib_binding_statuses[0]);
1688
1689                                         for (unsigned int n_vertex_attrib_binding_status = 0;
1690                                                  n_vertex_attrib_binding_status < n_vertex_attrib_binding_statuses;
1691                                                  ++n_vertex_attrib_binding_status)
1692                                         {
1693                                                 bool use_vertex_attrib_binding = vertex_attrib_binding_statuses[n_vertex_attrib_binding_status];
1694
1695                                                 /* Under GL, "vertex attrib binding" functionality is only available if GL_ARB_vertex_attrib_binding
1696                                                  * extension is supported.
1697                                                  */
1698                                                 if (!m_is_vertex_attrib_binding_supported && use_vertex_attrib_binding)
1699                                                 {
1700                                                         continue;
1701                                                 }
1702
1703                                                 /* Prepare a few arrays so that we can handle the multi draw call and its emulated version.. */
1704                                                 const glw::GLsizei multi_draw_call_count_array[3]   = { 3, 6, 3 };
1705                                                 const glw::GLuint* multi_draw_call_indices_array[3] = {
1706                                                         (glw::GLuint*)(current_index_offset), (glw::GLuint*)(current_index_offset + 3),
1707                                                         (glw::GLuint*)(current_index_offset + 9)
1708                                                 };
1709
1710                                                 /* Reference texture should always reflect basevertex=10 behavior. */
1711                                                 const glw::GLuint  regular_draw_call_offset                                      = basevertex_values[0];
1712                                                 const glw::GLuint* regular_multi_draw_call_offseted_array[3] = {
1713                                                         multi_draw_call_indices_array[0] + regular_draw_call_offset,
1714                                                         multi_draw_call_indices_array[1] + regular_draw_call_offset,
1715                                                         multi_draw_call_indices_array[2] + regular_draw_call_offset,
1716                                                 };
1717
1718                                                 /* Construct the test case descriptor */
1719                                                 _test_case new_test_case;
1720
1721                                                 new_test_case.basevertex                           = basevertex_values[n_basevertex_value];
1722                                                 new_test_case.function_type                        = (_function_type)n_function;
1723                                                 new_test_case.index_offset                         = current_index_offset;
1724                                                 new_test_case.range_start                          = n_index_offset == 0 ? 0 : 10;
1725                                                 new_test_case.range_end                            = n_index_offset == 0 ? 22 : 32;
1726                                                 new_test_case.index_type                           = GL_UNSIGNED_INT;
1727                                                 new_test_case.primitive_mode               = GL_TRIANGLES;
1728                                                 new_test_case.regular_draw_call_offset = basevertex_values[0];
1729                                                 new_test_case.should_base_texture_match_reference_texture =
1730                                                         ((glw::GLuint)new_test_case.basevertex == new_test_case.regular_draw_call_offset);
1731                                                 new_test_case.use_clientside_index_data         = use_clientside_index_data;
1732                                                 new_test_case.use_clientside_vertex_data        = use_clientside_vertex_data;
1733                                                 new_test_case.use_geometry_shader_stage         = false;
1734                                                 new_test_case.use_tessellation_shader_stage = false;
1735                                                 new_test_case.use_vertex_attrib_binding         = use_vertex_attrib_binding;
1736
1737                                                 memcpy(new_test_case.multi_draw_call_count_array, multi_draw_call_count_array,
1738                                                            sizeof(multi_draw_call_count_array));
1739                                                 memcpy(new_test_case.multi_draw_call_indices_array, multi_draw_call_indices_array,
1740                                                            sizeof(multi_draw_call_indices_array));
1741                                                 memcpy(new_test_case.regular_multi_draw_call_offseted_array,
1742                                                            regular_multi_draw_call_offseted_array, sizeof(regular_multi_draw_call_offseted_array));
1743
1744                                                 m_test_cases.push_back(new_test_case);
1745                                         } /* for (all vertex_attrib_binding statuses) */
1746                                 }        /* for (all basevertex values) */
1747                         }                 /* for (all four functions) */
1748                 }                         /* for (all index data sets) */
1749         }                                 /* for (all VAO iterations) */
1750 }
1751
1752 /** Executes test iteration.
1753  *
1754  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
1755  */
1756 tcu::TestNode::IterateResult DrawElementsBaseVertexFunctionalCorrectBaseVertexBehavior::iterate()
1757 {
1758         setUpTestCases();
1759         executeTestCases();
1760
1761         /* Test case passed */
1762         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1763
1764         return STOP;
1765 }
1766
1767 /** Constructor.
1768  *
1769  *  @param context Rendering context handle.
1770  **/
1771 DrawElementsBaseVertexFunctionalCorrectBaseVertexBehavior2::DrawElementsBaseVertexFunctionalCorrectBaseVertexBehavior2(
1772         Context& context, const ExtParameters& extParams)
1773         : DrawElementsBaseVertexTestBase(context, extParams, "basevertex_behavior2",
1774                                                                          "Verifies basevertex draw calls work correctly for a number of "
1775                                                                          "different rendering pipeline and VAO configurations. Uses slightly "
1776                                                                          "different data set than basevertex_behavior.")
1777 {
1778         /* Left blank on purpose */
1779 }
1780
1781 /** Sets up test case descriptors for the test instance. These will later be used
1782  *  as input for DrawElementsBaseVertexTestBase::executeTestCases(), which performs
1783  *  the actual testing.
1784  **/
1785 void DrawElementsBaseVertexFunctionalCorrectBaseVertexBehavior2::setUpTestCases()
1786 {
1787         /* Set up test case descriptors */
1788         const glw::GLint basevertex = 5;
1789
1790         /* The test needs to be run in two iterations, using client-side memory and buffer object
1791          * for index data respectively
1792          */
1793         for (int vao_iteration = 0; vao_iteration < 2; ++vao_iteration)
1794         {
1795                 /* Skip client-side vertex array as gl_VertexID is undefined when no buffer bound to ARRAY_BUFFER
1796                  *  See section 11.1.3.9 in OpenGL ES 3.1 spec
1797                  */
1798                 bool use_clientside_vertex_data = 0;
1799                 bool use_clientside_index_data  = ((vao_iteration & (1 << 0)) != 0);
1800
1801                 /* OpenGL does not support client-side data. */
1802                 if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
1803                 {
1804                         if (use_clientside_index_data || use_clientside_vertex_data)
1805                         {
1806                                 continue;
1807                         }
1808                 }
1809
1810                 /* Compute the offsets */
1811                 computeVBODataOffsets(use_clientside_index_data, use_clientside_vertex_data);
1812
1813                 /* We need to test four different functions:
1814                  *
1815                  * a)    glDrawElementsBaseVertex()             (GL)
1816                  *    or glDrawElementsBaseVertexEXT()          (ES)
1817                  * b)    glDrawRangeElementsBaseVertex()        (GL)
1818                  *    or glDrawRangeElementsBaseVertexEXT()     (ES)
1819                  * c)    glDrawElementsInstancedBaseVertex()    (GL)
1820                  *    or glDrawElementsInstancedBaseVertexEXT() (ES)
1821                  * d)    glMultiDrawElementsBaseVertex()        (GL)
1822                  *    or glMultiDrawElementsBaseVertexEXT()     (ES) (if supported)
1823                  **/
1824                 for (int n_function = 0; n_function < FUNCTION_COUNT; ++n_function)
1825                 {
1826                         /* Do not try to use the multi draw call if relevant extension is
1827                          * not supported. */
1828                         if (!m_is_ext_multi_draw_arrays_supported && n_function == FUNCTION_GL_MULTI_DRAW_ELEMENTS_BASE_VERTEX)
1829                         {
1830                                 continue;
1831                         }
1832
1833                         /* Prepare a few arrays so that we can handle the multi draw call and its emulated version.. */
1834                         const glw::GLsizei multi_draw_call_count_array[3]   = { 3, 6, 3 };
1835                         const glw::GLuint* multi_draw_call_indices_array[3] = { (glw::GLuint*)(m_draw_call_index_offset),
1836                                                                                                                                         (glw::GLuint*)(m_draw_call_index_offset + 3),
1837                                                                                                                                         (glw::GLuint*)(m_draw_call_index_offset + 9) };
1838
1839                         /* Reference texture should always reflect basevertex=10 behavior. */
1840                         const glw::GLuint  regular_draw_call_offset                                      = 0;
1841                         const glw::GLuint* regular_multi_draw_call_offseted_array[3] = {
1842                                 multi_draw_call_indices_array[0] + regular_draw_call_offset,
1843                                 multi_draw_call_indices_array[1] + regular_draw_call_offset,
1844                                 multi_draw_call_indices_array[2] + regular_draw_call_offset,
1845                         };
1846
1847                         /* Construct the test case descriptor */
1848                         _test_case new_test_case;
1849
1850                         new_test_case.basevertex                           = basevertex;
1851                         new_test_case.function_type                        = (_function_type)n_function;
1852                         new_test_case.index_offset                         = m_draw_call_index_offset;
1853                         new_test_case.range_start                          = 0;
1854                         new_test_case.range_end                            = 22;
1855                         new_test_case.index_type                           = GL_UNSIGNED_INT;
1856                         new_test_case.primitive_mode               = GL_TRIANGLES;
1857                         new_test_case.regular_draw_call_offset = regular_draw_call_offset;
1858                         new_test_case.should_base_texture_match_reference_texture =
1859                                 ((glw::GLuint)new_test_case.basevertex == new_test_case.regular_draw_call_offset);
1860                         new_test_case.use_clientside_index_data         = use_clientside_index_data;
1861                         new_test_case.use_clientside_vertex_data        = use_clientside_vertex_data;
1862                         new_test_case.use_geometry_shader_stage         = false;
1863                         new_test_case.use_tessellation_shader_stage = false;
1864                         new_test_case.use_vertex_attrib_binding         = false;
1865
1866                         memcpy(new_test_case.multi_draw_call_count_array, multi_draw_call_count_array,
1867                                    sizeof(multi_draw_call_count_array));
1868                         memcpy(new_test_case.multi_draw_call_indices_array, multi_draw_call_indices_array,
1869                                    sizeof(multi_draw_call_indices_array));
1870                         memcpy(new_test_case.regular_multi_draw_call_offseted_array, regular_multi_draw_call_offseted_array,
1871                                    sizeof(regular_multi_draw_call_offseted_array));
1872
1873                         m_test_cases.push_back(new_test_case);
1874                 } /* for (all four functions) */
1875         }        /* for (all VAO iterations) */
1876 }
1877
1878 /** Executes test iteration.
1879  *
1880  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
1881  */
1882 tcu::TestNode::IterateResult DrawElementsBaseVertexFunctionalCorrectBaseVertexBehavior2::iterate()
1883 {
1884         setUpTestCases();
1885         executeTestCases();
1886
1887         /* Test case passed */
1888         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1889
1890         return STOP;
1891 }
1892
1893 /** Constructor.
1894  *
1895  *  @param context Rendering context handle.
1896  **/
1897 DrawElementsBaseVertexFunctionalCorrectBaseVertexBehaviorUnderflow::
1898         DrawElementsBaseVertexFunctionalCorrectBaseVertexBehaviorUnderflow(Context& context, const ExtParameters& extParams)
1899         : DrawElementsBaseVertexTestBase(context, extParams, "underflow",
1900                                                                          "Verifies basevertex draw calls work correctly for negative "
1901                                                                          "basevertex values")
1902 {
1903         /* Left blank on purpose */
1904 }
1905
1906 /** Sets up test case descriptors for the test instance. These will later be used
1907  *  as input for DrawElementsBaseVertexTestBase::executeTestCases(), which performs
1908  *  the actual testing.
1909  **/
1910 void DrawElementsBaseVertexFunctionalCorrectBaseVertexBehaviorUnderflow::setUpTestCases()
1911 {
1912         /* Set up test case descriptors */
1913         const glw::GLint basevertex = -10;
1914
1915         /* The test needs to be run in two iterations, using client-side memory and buffer object
1916          * for index data respectively
1917          */
1918         for (int vao_iteration = 0; vao_iteration < 2; ++vao_iteration)
1919         {
1920                 /* Skip client-side vertex array as gl_VertexID is undefined when no buffer bound to ARRAY_BUFFER
1921                  *  See section 11.1.3.9 in OpenGL ES 3.1 spec
1922                  */
1923                 bool use_clientside_vertex_data = 0;
1924                 bool use_clientside_index_data  = ((vao_iteration & (1 << 0)) != 0);
1925
1926                 /* OpenGL does not support client-side data. */
1927                 if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
1928                 {
1929                         if (use_clientside_index_data || use_clientside_vertex_data)
1930                         {
1931                                 continue;
1932                         }
1933                 }
1934
1935                 /* Compute the offsets */
1936                 computeVBODataOffsets(use_clientside_index_data, use_clientside_vertex_data);
1937
1938                 /* We need to test four different functions:
1939                  *
1940                  * a)    glDrawElementsBaseVertex()             (GL)
1941                  *    or glDrawElementsBaseVertexEXT()          (ES)
1942                  * b)    glDrawRangeElementsBaseVertex()        (GL)
1943                  *    or glDrawRangeElementsBaseVertexEXT()     (ES)
1944                  * c)    glDrawElementsInstancedBaseVertex()    (GL)
1945                  *    or glDrawElementsInstancedBaseVertexEXT() (ES)
1946                  * d)    glMultiDrawElementsBaseVertex()        (GL)
1947                  *    or glMultiDrawElementsBaseVertexEXT()     (ES) (if supported)
1948                  **/
1949                 for (int n_function = 0; n_function < FUNCTION_COUNT; ++n_function)
1950                 {
1951                         /* Do not try to use the multi draw call if relevant extension is
1952                          * not supported. */
1953                         if (!m_is_ext_multi_draw_arrays_supported && n_function == FUNCTION_GL_MULTI_DRAW_ELEMENTS_BASE_VERTEX)
1954                         {
1955                                 continue;
1956                         }
1957
1958                         /* Prepare a few arrays so that we can handle the multi draw call and its emulated version.. */
1959                         unsigned int offset_from_10_to_0_index = 23; /* this offset moves us from the start index of 10 to a zero
1960                          * index, given the second index data set we will be using.
1961                          * Please see declaration of functional2_index_data if you
1962                          * need to verify this by yourself. */
1963
1964                         const glw::GLsizei multi_draw_call_count_array[3]   = { 3, 6, 3 };
1965                         const glw::GLuint* multi_draw_call_indices_array[3] = { (glw::GLuint*)(m_draw_call_index2_offset),
1966                                                                                                                                         (glw::GLuint*)(m_draw_call_index2_offset + 3),
1967                                                                                                                                         (glw::GLuint*)(m_draw_call_index2_offset + 9) };
1968                         const glw::GLuint* regular_multi_draw_call_offseted_array[3] = {
1969                                 multi_draw_call_indices_array[0] + offset_from_10_to_0_index,
1970                                 multi_draw_call_indices_array[1] + offset_from_10_to_0_index,
1971                                 multi_draw_call_indices_array[2] + offset_from_10_to_0_index,
1972                         };
1973
1974                         /* Construct the test case descriptor */
1975                         _test_case new_test_case;
1976
1977                         new_test_case.basevertex                                                                  = basevertex;
1978                         new_test_case.function_type                                                               = (_function_type)n_function;
1979                         new_test_case.index_offset                                                                = m_draw_call_index2_offset;
1980                         new_test_case.range_start                                                                 = 10;
1981                         new_test_case.range_end                                                                   = 32;
1982                         new_test_case.index_type                                                                  = GL_UNSIGNED_INT;
1983                         new_test_case.primitive_mode                                                      = GL_TRIANGLES;
1984                         new_test_case.regular_draw_call_offset                                    = offset_from_10_to_0_index;
1985                         new_test_case.should_base_texture_match_reference_texture = true;
1986                         new_test_case.use_clientside_index_data                                   = use_clientside_index_data;
1987                         new_test_case.use_clientside_vertex_data                                  = use_clientside_vertex_data;
1988                         new_test_case.use_geometry_shader_stage                                   = false;
1989                         new_test_case.use_tessellation_shader_stage                               = false;
1990                         new_test_case.use_vertex_attrib_binding                                   = false;
1991
1992                         memcpy(new_test_case.multi_draw_call_count_array, multi_draw_call_count_array,
1993                                    sizeof(multi_draw_call_count_array));
1994                         memcpy(new_test_case.multi_draw_call_indices_array, multi_draw_call_indices_array,
1995                                    sizeof(multi_draw_call_indices_array));
1996                         memcpy(new_test_case.regular_multi_draw_call_offseted_array, regular_multi_draw_call_offseted_array,
1997                                    sizeof(regular_multi_draw_call_offseted_array));
1998
1999                         m_test_cases.push_back(new_test_case);
2000                 } /* for (all four functions) */
2001         }        /* for (all VAO iterations) */
2002 }
2003
2004 /** Executes test iteration.
2005  *
2006  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
2007  */
2008 tcu::TestNode::IterateResult DrawElementsBaseVertexFunctionalCorrectBaseVertexBehaviorUnderflow::iterate()
2009 {
2010         setUpTestCases();
2011         executeTestCases();
2012
2013         /* Test case passed */
2014         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2015
2016         return STOP;
2017 }
2018
2019 /** Constructor.
2020  *
2021  *  @param context Rendering context handle.
2022  **/
2023 DrawElementsBaseVertexFunctionalCorrectBaseVertexBehaviorOverflow::
2024         DrawElementsBaseVertexFunctionalCorrectBaseVertexBehaviorOverflow(Context& context, const ExtParameters& extParams)
2025         : DrawElementsBaseVertexTestBase(context, extParams, "overflow",
2026                                                                          "Verifies basevertex draw calls work correctly for overflowing "
2027                                                                          "basevertex values")
2028 {
2029         /* Left blank on purpose */
2030 }
2031
2032 /** Sets up test case descriptors for the test instance. These will later be used
2033  *  as input for DrawElementsBaseVertexTestBase::executeTestCases(), which performs
2034  *  the actual testing.
2035  **/
2036 void DrawElementsBaseVertexFunctionalCorrectBaseVertexBehaviorOverflow::setUpTestCases()
2037 {
2038         /* The test needs to be run in two iterations, using client-side memory and buffer object
2039          * for index data respectively
2040          */
2041         for (int vao_iteration = 0; vao_iteration < 2; ++vao_iteration)
2042         {
2043                 /* Skip client-side vertex array as gl_VertexID is undefined when no buffer bound to ARRAY_BUFFER
2044                  *  See section 11.1.3.9 in OpenGL ES 3.1 spec
2045                  */
2046                 bool use_clientside_vertex_data = 0;
2047                 bool use_clientside_index_data  = ((vao_iteration & (1 << 0)) != 0);
2048
2049                 /* OpenGL does not support client-side data. */
2050                 if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
2051                 {
2052                         if (use_clientside_index_data || use_clientside_vertex_data)
2053                         {
2054                                 continue;
2055                         }
2056                 }
2057
2058                 /* Compute the offsets */
2059                 computeVBODataOffsets(use_clientside_index_data, use_clientside_vertex_data);
2060
2061                 /* We need to test four different functions:
2062                  *
2063                  * a)    glDrawElementsBaseVertex()             (GL)
2064                  *    or glDrawElementsBaseVertexEXT()          (ES)
2065                  * b)    glDrawRangeElementsBaseVertex()        (GL)
2066                  *    or glDrawRangeElementsBaseVertexEXT()     (ES)
2067                  * c)    glDrawElementsInstancedBaseVertex()    (GL)
2068                  *    or glDrawElementsInstancedBaseVertexEXT() (ES)
2069                  * d)    glMultiDrawElementsBaseVertex()        (GL)
2070                  *    or glMultiDrawElementsBaseVertexEXT()     (ES) (if supported)
2071                  **/
2072                 for (int n_function = 0; n_function < FUNCTION_COUNT; ++n_function)
2073                 {
2074                         /* Do not try to use the multi draw call if relevant extension is
2075                          * not supported. */
2076                         if (!m_is_ext_multi_draw_arrays_supported && n_function == FUNCTION_GL_MULTI_DRAW_ELEMENTS_BASE_VERTEX)
2077                         {
2078                                 continue;
2079                         }
2080
2081                         const glw::GLenum index_types[] = { GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT, GL_UNSIGNED_INT };
2082
2083                         const unsigned int n_index_types = sizeof(index_types) / sizeof(index_types[0]);
2084
2085                         for (unsigned int n_index_type = 0; n_index_type < n_index_types; ++n_index_type)
2086                         {
2087
2088                                 glw::GLint                      basevertex                                       = -1;
2089                                 const glw::GLubyte* index_offset                                 = NULL;
2090                                 int                                     index_size                                       = 0;
2091                                 glw::GLenum                     index_type                                       = index_types[n_index_type];
2092                                 glw::GLenum                     regular_draw_call_index_type = 0;
2093                                 int                                     regular_draw_call_index_size = 0;
2094                                 glw::GLboolean          use_overflow_test_vertices   = false;
2095
2096                                 /* To meet requirements of tests IX.1-IX.2 and IX.3, we need to use two basevertex deltas. */
2097                                 const glw::GLint basevertex_deltas[] = {
2098                                         0, /* IX.1-IX.2 */
2099                                         1  /* IX.3 */
2100                                 };
2101                                 const unsigned int n_basevertex_deltas = sizeof(basevertex_deltas) / sizeof(basevertex_deltas[0]);
2102
2103                                 for (unsigned int n_basevertex_delta = 0; n_basevertex_delta < n_basevertex_deltas;
2104                                          ++n_basevertex_delta)
2105                                 {
2106                                         const glw::GLint basevertex_delta                  = basevertex_deltas[n_basevertex_delta];
2107                                         glw::GLuint              regular_draw_call_offset  = 0;
2108                                         glw::GLuint*     regular_draw_call_offset2 = NULL;
2109                                         glw::GLuint              range_start                       = 0;
2110                                         glw::GLuint              range_end                                 = 0;
2111                                         bool                     shouldMatch;
2112
2113                                         switch (index_type)
2114                                         {
2115                                         /*
2116                                          * UBYTE base draw indices: 0, 1, 2
2117                                          *              baseVertex: 256+0
2118                                          *    regular draw indices: 0, 1, 2
2119                                          *         expected result: ubyte indices should not wrap around at 8-bit width,
2120                                          *                          base draw result should not match regular draw result
2121                                          *
2122                                          * UBYTE base draw indices: 0, 1, 2
2123                                          *              baseVertex: 256+1
2124                                          *    regular draw indices: 257, 258, 259 (uint)
2125                                          *         expected result: ubyte indices should be upconverted to 32-bit uint,
2126                                          *                          base draw result should match regular draw result
2127                                          */
2128                                         case GL_UNSIGNED_BYTE:
2129                                         {
2130                                                 basevertex                                       = 256 + basevertex_delta;
2131                                                 index_offset                             = (const glw::GLubyte*)m_draw_call_index3_offset;
2132                                                 index_size                                       = 1;
2133                                                 range_start                                      = 0;
2134                                                 range_end                                        = 2;
2135                                                 regular_draw_call_index_type = (basevertex_delta == 0) ? GL_UNSIGNED_BYTE : GL_UNSIGNED_INT;
2136                                                 regular_draw_call_index_size = (regular_draw_call_index_type == GL_UNSIGNED_BYTE) ? 1 : 4;
2137                                                 regular_draw_call_offset2 =
2138                                                         (basevertex_delta == 0) ?
2139                                                                 (glw::GLuint*)(m_draw_call_index3_offset) :
2140                                                                 (glw::GLuint*)(m_draw_call_index5_offset + 12); // 12th in functional5_index_data
2141                                                 shouldMatch                                = (basevertex_delta == 1) ? true : false;
2142                                                 use_overflow_test_vertices = true;
2143                                                 break;
2144                                         }
2145
2146                                         /*
2147                                                  * USHORT base draw indices: 0, 1, 2
2148                                                  *               baseVertex: 65536+0
2149                                                  *     regular draw indices: 0, 1, 2
2150                                                  *          expected result: ubyte indices should not wrap around at 16-bit width,
2151                                                  *                           base draw result should not match regular draw result
2152                                                  *
2153                                                  * USHORT base draw indices: 0, 1, 2
2154                                                  *               baseVertex: 65536+1
2155                                                  *     regular draw indices: 65537, 65538, 65539 (uint)
2156                                                  *          expected result: ushort indices should be upconverted to 32-bit uint,
2157                                                  *                           base draw result should match regular draw result
2158                                                  */
2159                                         case GL_UNSIGNED_SHORT:
2160                                         {
2161                                                 basevertex                                       = 65536 + basevertex_delta;
2162                                                 index_offset                             = (const glw::GLubyte*)m_draw_call_index4_offset;
2163                                                 index_size                                       = 2;
2164                                                 range_start                                      = 0;
2165                                                 range_end                                        = 2;
2166                                                 regular_draw_call_index_type = (basevertex_delta == 0) ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT;
2167                                                 regular_draw_call_index_size = (regular_draw_call_index_type == GL_UNSIGNED_SHORT) ? 2 : 4;
2168                                                 regular_draw_call_offset2 =
2169                                                         (basevertex_delta == 0) ?
2170                                                                 (glw::GLuint*)(m_draw_call_index4_offset) :
2171                                                                 (glw::GLuint*)(m_draw_call_index5_offset + 24); // 24th in functional5_index_data
2172                                                 shouldMatch                                = (basevertex_delta == 1) ? true : false;
2173                                                 use_overflow_test_vertices = true;
2174                                                 break;
2175                                         }
2176
2177                                         /*
2178                                                  * UINT base draw indices: 2^31+2, 2^31+3, 2^31+4
2179                                                  *             baseVertex: 2^31-2
2180                                                  *   regular draw indices: 0, 1, 2
2181                                                  *        expected result: uint indices should wrap to {0, 1, 2},
2182                                                  *                         base draw result should match regular draw result
2183                                                  *
2184                                                  * UINT base draw indices: 2^31+2, 2^31+3, 2^31+4
2185                                                  *             baseVertex: 2^31-1
2186                                                  *   regular draw indices: 0, 1, 2
2187                                                  *        expected result: uint indices should wrap to {1, 2, 3},
2188                                                  *                         base draw result should not match regular draw result
2189                                                  */
2190                                         case GL_UNSIGNED_INT:
2191                                         {
2192                                                 basevertex                                       = 2147483647 - 1 + basevertex_delta;
2193                                                 index_offset                             = (const glw::GLubyte*)m_draw_call_index5_offset;
2194                                                 index_size                                       = 4;
2195                                                 range_start                                      = 2147483647 + 3u; // 2^31+2
2196                                                 range_end                                        = 2147483647 + 5u; // 2^31+4
2197                                                 regular_draw_call_index_type = GL_UNSIGNED_INT;
2198                                                 regular_draw_call_index_size = 4;
2199                                                 regular_draw_call_offset         = 36; // 36th in functional5_index_data
2200                                                 shouldMatch                                      = (basevertex_delta == 0) ? true : false;
2201                                                 use_overflow_test_vertices   = false;
2202                                                 break;
2203                                         }
2204
2205                                         default:
2206                                         {
2207                                                 TCU_FAIL("Unrecognized index type");
2208                                         }
2209                                         } /* switch (index_type) */
2210
2211                                         /* Prepare a few arrays so that we can handle the multi draw call and its emulated version.. */
2212                                         const glw::GLsizei  multi_draw_call_count_array[3]   = { 3, 6, 3 };
2213                                         const glw::GLubyte* multi_draw_call_indices_array[3] = { index_offset,
2214                                                                                                                                                          index_offset + 3 * index_size,
2215                                                                                                                                                          index_offset + 9 * index_size };
2216                                         const glw::GLubyte* regular_multi_draw_call_offseted_array[3];
2217                                         if (use_overflow_test_vertices)
2218                                         {
2219                                                 regular_multi_draw_call_offseted_array[0] = (glw::GLubyte*)regular_draw_call_offset2;
2220                                                 regular_multi_draw_call_offseted_array[1] =
2221                                                         (glw::GLubyte*)regular_draw_call_offset2 + 3 * regular_draw_call_index_size;
2222                                                 regular_multi_draw_call_offseted_array[2] =
2223                                                         (glw::GLubyte*)regular_draw_call_offset2 + 9 * regular_draw_call_index_size;
2224                                         }
2225                                         else
2226                                         {
2227                                                 regular_multi_draw_call_offseted_array[0] =
2228                                                         multi_draw_call_indices_array[0] + index_size * regular_draw_call_offset;
2229                                                 regular_multi_draw_call_offseted_array[1] =
2230                                                         multi_draw_call_indices_array[1] + index_size * regular_draw_call_offset;
2231                                                 regular_multi_draw_call_offseted_array[2] =
2232                                                         multi_draw_call_indices_array[2] + index_size * regular_draw_call_offset;
2233                                         }
2234
2235                                         /* Construct the test case descriptor */
2236                                         _test_case new_test_case;
2237
2238                                         new_test_case.basevertex                                                                  = basevertex;
2239                                         new_test_case.function_type                                                               = (_function_type)n_function;
2240                                         new_test_case.index_offset                                                                = (const glw::GLuint*)index_offset;
2241                                         new_test_case.range_start                                                                 = range_start;
2242                                         new_test_case.range_end                                                                   = range_end;
2243                                         new_test_case.index_type                                                                  = index_type;
2244                                         new_test_case.primitive_mode                                                      = GL_TRIANGLES;
2245                                         new_test_case.regular_draw_call_offset                                    = regular_draw_call_offset;
2246                                         new_test_case.regular_draw_call_offset2                                   = regular_draw_call_offset2;
2247                                         new_test_case.regular_draw_call_index_type                                = regular_draw_call_index_type;
2248                                         new_test_case.should_base_texture_match_reference_texture = shouldMatch;
2249                                         new_test_case.use_clientside_index_data                                   = use_clientside_index_data;
2250                                         new_test_case.use_clientside_vertex_data                                  = use_clientside_vertex_data;
2251                                         new_test_case.use_geometry_shader_stage                                   = false;
2252                                         new_test_case.use_tessellation_shader_stage                               = false;
2253                                         new_test_case.use_vertex_attrib_binding                                   = false;
2254                                         new_test_case.use_overflow_test_vertices                                  = use_overflow_test_vertices != GL_FALSE;
2255
2256                                         memcpy(new_test_case.multi_draw_call_count_array, multi_draw_call_count_array,
2257                                                    sizeof(multi_draw_call_count_array));
2258                                         memcpy(new_test_case.multi_draw_call_indices_array, multi_draw_call_indices_array,
2259                                                    sizeof(multi_draw_call_indices_array));
2260                                         memcpy(new_test_case.regular_multi_draw_call_offseted_array, regular_multi_draw_call_offseted_array,
2261                                                    sizeof(regular_multi_draw_call_offseted_array));
2262
2263                                         m_test_cases.push_back(new_test_case);
2264                                 } /* for (all basevertex deltas) */
2265                         }        /* for (all index types) */
2266                 }                 /* for (all four functions) */
2267         }                         /* for (all VAO iterations) */
2268 }
2269
2270 /** Executes test iteration.
2271  *
2272  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
2273  */
2274 tcu::TestNode::IterateResult DrawElementsBaseVertexFunctionalCorrectBaseVertexBehaviorOverflow::iterate()
2275 {
2276         setUpTestCases();
2277         executeTestCases();
2278
2279         /* Test case passed */
2280         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2281
2282         return STOP;
2283 }
2284
2285 /** Constructor.
2286  *
2287  *  @param context Rendering context handle.
2288  **/
2289 DrawElementsBaseVertexFunctionalCorrectBaseVertexBehaviorAEPShaderStages::
2290         DrawElementsBaseVertexFunctionalCorrectBaseVertexBehaviorAEPShaderStages(Context&                         context,
2291                                                                                                                                                          const ExtParameters& extParams)
2292         : DrawElementsBaseVertexTestBase(context, extParams, "AEP_shader_stages",
2293                                                                          "Verifies basevertex draw calls work correctly when geometry & "
2294                                                                          "tessellation shader stages are used in the rendering pipeline.")
2295 {
2296         /* Left blank intentionally */
2297 }
2298
2299 /** Sets up test case descriptors for the test instance. These will later be used
2300  *  as input for DrawElementsBaseVertexTestBase::executeTestCases(), which performs
2301  *  the actual testing.
2302  **/
2303 void DrawElementsBaseVertexFunctionalCorrectBaseVertexBehaviorAEPShaderStages::setUpTestCases()
2304 {
2305         /* Set up test case descriptors */
2306         const glw::GLuint basevertex_values[] = {
2307                 10, /* VI.1-VI.4 */
2308                 0   /* VI.5 */
2309         };
2310         const unsigned int n_basevertex_values = sizeof(basevertex_values) / sizeof(basevertex_values[0]);
2311
2312         /* The test needs to be run in two iterations, using client-side memory and buffer object
2313          * for index data respectively
2314          */
2315         for (int vao_iteration = 0; vao_iteration < 2; ++vao_iteration)
2316         {
2317                 /* Skip client-side vertex array as gl_VertexID is undefined when zero buffer is bound to ARRAY_BUFFER */
2318                 bool use_clientside_vertex_data = 0;
2319                 bool use_clientside_index_data  = ((vao_iteration & (1 << 0)) != 0);
2320
2321                 /* OpenGL does not support client-side data. */
2322                 if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
2323                 {
2324                         if (use_clientside_index_data || use_clientside_vertex_data)
2325                         {
2326                                 continue;
2327                         }
2328                 }
2329
2330                 /* Compute the offsets */
2331                 computeVBODataOffsets(use_clientside_index_data, use_clientside_vertex_data);
2332
2333                 /* There are two index data sets we need to iterate over */
2334                 const glw::GLuint* index_offsets[] = { m_draw_call_index_offset, m_draw_call_index2_offset };
2335                 const unsigned int n_index_offsets = sizeof(index_offsets) / sizeof(index_offsets[0]);
2336
2337                 for (unsigned int n_index_offset = 0; n_index_offset < n_index_offsets; ++n_index_offset)
2338                 {
2339                         const glw::GLuint* current_index_offset = index_offsets[n_index_offset];
2340
2341                         /* We need to test four different functions:
2342                          *
2343                          * a)    glDrawElementsBaseVertex()             (GL)
2344                          *    or glDrawElementsBaseVertexEXT()          (ES)
2345                          * b)    glDrawRangeElementsBaseVertex()        (GL)
2346                          *    or glDrawRangeElementsBaseVertexEXT()     (ES)
2347                          * c)    glDrawElementsInstancedBaseVertex()    (GL)
2348                          *    or glDrawElementsInstancedBaseVertexEXT() (ES)
2349                          * d)    glMultiDrawElementsBaseVertex()        (GL)
2350                          *    or glMultiDrawElementsBaseVertexEXT()     (ES) (if supported)
2351                          **/
2352                         for (int n_function = 0; n_function < FUNCTION_COUNT; ++n_function)
2353                         {
2354                                 /* Iterate over all basevertex values */
2355                                 for (unsigned int n_basevertex_value = 0; n_basevertex_value < n_basevertex_values;
2356                                          ++n_basevertex_value)
2357                                 {
2358
2359                                         /* Iterate over all GS+(TC & TE) stage combinations */
2360                                         for (unsigned int n_stage_combination = 0; n_stage_combination < 4; ++n_stage_combination)
2361                                         {
2362                                                 bool should_include_gs  = (n_stage_combination & 1) != 0;
2363                                                 bool should_include_tc_te = (n_stage_combination & 2) != 0;
2364
2365                                                 /* Skip iterations, for which we'd need to use extensions not supported
2366                                                  * by the running implementation */
2367                                                 if (should_include_gs && !m_is_geometry_shader_supported)
2368                                                 {
2369                                                         continue;
2370                                                 }
2371
2372                                                 if (should_include_tc_te && !m_is_tessellation_shader_supported)
2373                                                 {
2374                                                         continue;
2375                                                 }
2376
2377                                                 /* Do not try to use the multi draw call if relevant extension is
2378                                                  * not supported. */
2379                                                 if (!m_is_ext_multi_draw_arrays_supported &&
2380                                                         n_function == FUNCTION_GL_MULTI_DRAW_ELEMENTS_BASE_VERTEX)
2381                                                 {
2382                                                         continue;
2383                                                 }
2384
2385                                                 /* Prepare a few arrays so that we can handle the multi draw call and its emulated version.. */
2386                                                 const glw::GLsizei multi_draw_call_count_array[3]   = { 3, 6, 3 };
2387                                                 const glw::GLuint* multi_draw_call_indices_array[3] = {
2388                                                         (glw::GLuint*)(current_index_offset), (glw::GLuint*)(current_index_offset + 3),
2389                                                         (glw::GLuint*)(current_index_offset + 9)
2390                                                 };
2391
2392                                                 /* Reference texture should always reflect basevertex=10 behavior. */
2393                                                 const glw::GLuint  regular_draw_call_offset                                      = basevertex_values[0];
2394                                                 const glw::GLuint* regular_multi_draw_call_offseted_array[3] = {
2395                                                         multi_draw_call_indices_array[0] + regular_draw_call_offset,
2396                                                         multi_draw_call_indices_array[1] + regular_draw_call_offset,
2397                                                         multi_draw_call_indices_array[2] + regular_draw_call_offset,
2398                                                 };
2399
2400                                                 /* Construct the test case descriptor */
2401                                                 _test_case new_test_case;
2402
2403                                                 new_test_case.basevertex                           = basevertex_values[n_basevertex_value];
2404                                                 new_test_case.function_type                        = (_function_type)n_function;
2405                                                 new_test_case.index_offset                         = current_index_offset;
2406                                                 new_test_case.range_start                          = n_index_offset == 0 ? 0 : 10;
2407                                                 new_test_case.range_end                            = n_index_offset == 0 ? 22 : 32;
2408                                                 new_test_case.index_type                           = GL_UNSIGNED_INT;
2409                                                 new_test_case.primitive_mode               = (should_include_tc_te) ? GL_PATCHES : GL_TRIANGLES;
2410                                                 new_test_case.regular_draw_call_offset = regular_draw_call_offset;
2411                                                 new_test_case.should_base_texture_match_reference_texture =
2412                                                         ((glw::GLuint)new_test_case.basevertex == new_test_case.regular_draw_call_offset);
2413                                                 new_test_case.use_clientside_index_data         = use_clientside_index_data;
2414                                                 new_test_case.use_clientside_vertex_data        = use_clientside_vertex_data;
2415                                                 new_test_case.use_geometry_shader_stage         = should_include_gs;
2416                                                 new_test_case.use_tessellation_shader_stage = should_include_tc_te;
2417                                                 new_test_case.use_vertex_attrib_binding         = false;
2418
2419                                                 memcpy(new_test_case.multi_draw_call_count_array, multi_draw_call_count_array,
2420                                                            sizeof(multi_draw_call_count_array));
2421                                                 memcpy(new_test_case.multi_draw_call_indices_array, multi_draw_call_indices_array,
2422                                                            sizeof(multi_draw_call_indices_array));
2423                                                 memcpy(new_test_case.regular_multi_draw_call_offseted_array,
2424                                                            regular_multi_draw_call_offseted_array, sizeof(regular_multi_draw_call_offseted_array));
2425
2426                                                 m_test_cases.push_back(new_test_case);
2427                                         } /* for (all shader stage combinations) */
2428                                 }        /* for (all basevertex values) */
2429                         }                 /* for (all four functions) */
2430                 }                         /* for (all index data sets) */
2431         }                                 /* for (all VAO iterations) */
2432 }
2433
2434 /** Executes test iteration.
2435  *
2436  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
2437  */
2438 tcu::TestNode::IterateResult DrawElementsBaseVertexFunctionalCorrectBaseVertexBehaviorAEPShaderStages::iterate()
2439 {
2440         /* This test should not be run on implementations that don't support both tessellation and geometry
2441          * shader stages
2442          */
2443         if (!m_is_geometry_shader_supported && !m_is_tessellation_shader_supported)
2444         {
2445                 throw tcu::NotSupportedError("Geometry shader and tessellation shader functionality is not supported");
2446         }
2447
2448         setUpTestCases();
2449         executeTestCases();
2450
2451         /* Test case passed */
2452         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2453
2454         return STOP;
2455 }
2456
2457 /** Constructor.
2458  *
2459  *  @param context Rendering context handle.
2460  **/
2461 DrawElementsBaseVertexNegativeActiveTransformFeedbackTest::DrawElementsBaseVertexNegativeActiveTransformFeedbackTest(
2462         Context& context, const ExtParameters& extParams)
2463         : DrawElementsBaseVertexTestBase(context, extParams, "valid_active_tf",
2464                                                                          "Tries to do \"base vertex\" draw calls while Transform Feedback is active")
2465         , m_bo_tf_result_id(0)
2466 {
2467         /* Left blank on purpose */
2468 }
2469
2470 /** Deinitializes all ES objects per test case if test fails and exit through exception path */
2471 void DrawElementsBaseVertexNegativeActiveTransformFeedbackTest::deinit()
2472 {
2473         deinitPerTestObjects();
2474 }
2475
2476 /** Deinitializes all ES objects that may have been created by the test */
2477 void DrawElementsBaseVertexNegativeActiveTransformFeedbackTest::deinitPerTestObjects()
2478 {
2479         /* Call the base class' deinitPerTestObjects() first. */
2480         DrawElementsBaseVertexTestBase::deinitPerTestObjects();
2481
2482         /* Proceed with internal deinitialization */
2483         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2484
2485         if (m_bo_tf_result_id != 0)
2486         {
2487                 gl.deleteBuffers(1, &m_bo_tf_result_id);
2488
2489                 m_bo_tf_result_id = 0;
2490         }
2491 }
2492
2493 /** Initializes all ES objects used by the test. */
2494 void DrawElementsBaseVertexNegativeActiveTransformFeedbackTest::init()
2495 {
2496         /* Call the base class' init() first. */
2497         DrawElementsBaseVertexTestBase::init();
2498
2499         /* Proceed with internal initialization */
2500         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2501
2502         gl.genBuffers(1, &m_bo_tf_result_id);
2503         GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed");
2504
2505         gl.bindBuffer(GL_ARRAY_BUFFER, m_bo_tf_result_id);
2506         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed");
2507
2508         gl.bufferData(GL_ARRAY_BUFFER, 3 /* count */ * sizeof(float) * 4 /* components used by gl_Position */,
2509                                   DE_NULL, /* data */
2510                                   GL_STATIC_DRAW);
2511         GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
2512
2513         gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, /* index */
2514                                           m_bo_tf_result_id);
2515         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed");
2516 }
2517
2518 /** Executes test iteration.
2519  *
2520  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
2521  */
2522 tcu::TestNode::IterateResult DrawElementsBaseVertexNegativeActiveTransformFeedbackTest::iterate()
2523 {
2524         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2525
2526         /* this test doesn't apply to OpenGL contexts */
2527         if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
2528         {
2529                 m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported");
2530                 return STOP;
2531         }
2532
2533         /* Set up the work environment */
2534         setUpNegativeTestObjects(false,  /* use_clientside_vertex_data */
2535                                                          false); /* use_clientside_index_data */
2536
2537         /* Kick off transform feedback */
2538         gl.beginTransformFeedback(GL_TRIANGLES);
2539         GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call failed.");
2540
2541         /* Try to perform indiced draw calls which are invalid when TF is active.
2542          */
2543         glw::GLenum error_code = GL_NONE;
2544
2545         gl.drawElementsBaseVertex(GL_TRIANGLES, 3,                                                               /* count */
2546                                                           GL_UNSIGNED_INT, m_draw_call_index_offset, 0); /* basevertex */
2547
2548         error_code = gl.getError();
2549
2550         /* The error for using DrawElements* commands while transform feedback is
2551          active is lifted in OES/EXT_geometry_shader. See issue 13 in the spec.
2552          */
2553         glw::GLenum expected_error_code = m_is_geometry_shader_supported ? GL_NO_ERROR : GL_INVALID_OPERATION;
2554
2555         if (error_code != expected_error_code)
2556         {
2557                 std::stringstream error_sstream;
2558
2559                 error_sstream << "Invalid error code generated by " << getFunctionName(FUNCTION_GL_DRAW_ELEMENTS_BASE_VERTEX);
2560
2561                 m_testCtx.getLog() << tcu::TestLog::Message << getFunctionName(FUNCTION_GL_DRAW_ELEMENTS_BASE_VERTEX)
2562                                                    << " returned error code [" << error_code << "] instead of [" << expected_error_code << "]."
2563                                                    << tcu::TestLog::EndMessage;
2564
2565                 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, error_sstream.str().c_str());
2566
2567                 goto end;
2568         }
2569
2570         gl.drawElementsInstancedBaseVertex(GL_TRIANGLES, 3,                                                              /* count */
2571                                                                            GL_UNSIGNED_INT, m_draw_call_index_offset, 1, /* instancecount */
2572                                                                            0);                                                                                   /* basevertex */
2573
2574         error_code = gl.getError();
2575         if (error_code != expected_error_code)
2576         {
2577                 std::stringstream error_sstream;
2578
2579                 error_sstream << "Invalid error code generated by "
2580                                           << getFunctionName(FUNCTION_GL_DRAW_ELEMENTS_INSTANCED_BASE_VERTEX);
2581
2582                 m_testCtx.getLog() << tcu::TestLog::Message << getFunctionName(FUNCTION_GL_DRAW_ELEMENTS_INSTANCED_BASE_VERTEX)
2583                                                    << " returned error code [" << error_code << "] instead of [" << expected_error_code << "]."
2584                                                    << tcu::TestLog::EndMessage;
2585
2586                 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, error_sstream.str().c_str());
2587
2588                 goto end;
2589         }
2590
2591         gl.drawRangeElementsBaseVertex(GL_TRIANGLES, 0, 2,                                                        /* end */
2592                                                                    3,                                                                                     /* count */
2593                                                                    GL_UNSIGNED_INT, m_draw_call_index_offset, 0); /* basevertex */
2594
2595         error_code = gl.getError();
2596         if (error_code != expected_error_code)
2597         {
2598                 std::stringstream error_sstream;
2599
2600                 error_sstream << "Invalid error code generated by "
2601                                           << getFunctionName(FUNCTION_GL_DRAW_RANGE_ELEMENTS_BASE_VERTEX);
2602
2603                 m_testCtx.getLog() << tcu::TestLog::Message << getFunctionName(FUNCTION_GL_DRAW_RANGE_ELEMENTS_BASE_VERTEX)
2604                                                    << " returned error code [" << error_code << "] instead of [" << expected_error_code << "]."
2605                                                    << tcu::TestLog::EndMessage;
2606
2607                 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, error_sstream.str().c_str());
2608
2609                 goto end;
2610         }
2611
2612         /* Test case passed */
2613         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2614
2615 end:
2616         gl.endTransformFeedback();
2617         return STOP;
2618 }
2619
2620 /** Constructor.
2621  *
2622  *  @param context Rendering context handle.
2623  **/
2624 DrawElementsBaseVertexNegativeInvalidCountArgumentTest::DrawElementsBaseVertexNegativeInvalidCountArgumentTest(
2625         Context& context, const ExtParameters& extParams)
2626         : DrawElementsBaseVertexTestBase(context, extParams, "invalid_count_argument",
2627                                                                          "Tries to use invalid 'count' argument values for the \"base vertex\" draw calls")
2628 {
2629         /* Left blank on purpose */
2630 }
2631
2632 /** Executes test iteration.
2633  *
2634  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
2635  */
2636 tcu::TestNode::IterateResult DrawElementsBaseVertexNegativeInvalidCountArgumentTest::iterate()
2637 {
2638         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2639
2640         /* The test needs to be run in four iterations, where for each iteration we configure the VAO
2641          * in a slightly different manner.
2642          */
2643         for (int iteration = 0; iteration < 4; ++iteration)
2644         {
2645                 bool use_clientside_index_data  = ((iteration & (1 << 0)) != 0);
2646                 bool use_clientside_vertex_data = ((iteration & (1 << 1)) != 0);
2647
2648                 /* OpenGL does not support client-side data. */
2649                 if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
2650                 {
2651                         if (use_clientside_index_data || use_clientside_vertex_data)
2652                         {
2653                                 continue;
2654                         }
2655                 }
2656
2657                 /* Set up the work environment */
2658                 setUpNegativeTestObjects(use_clientside_vertex_data, use_clientside_index_data);
2659
2660                 /* Try to execute the invalid draw calls */
2661                 glw::GLenum error_code = GL_NONE;
2662
2663                 gl.drawElementsBaseVertex(GL_TRIANGLES, -1,                                                                                                      /* count */
2664                                                                   GL_UNSIGNED_INT, (const glw::GLvoid*)m_draw_call_index_offset, 0); /* basevertex */
2665
2666                 error_code = gl.getError();
2667                 if (error_code != GL_INVALID_VALUE)
2668                 {
2669                         std::stringstream error_sstream;
2670
2671                         error_sstream << "Invalid error code reported for an invalid "
2672                                                   << getFunctionName(FUNCTION_GL_DRAW_ELEMENTS_BASE_VERTEX) << " call";
2673
2674                         m_testCtx.getLog() << tcu::TestLog::Message << error_sstream.str().c_str()
2675                                                            << ": expected GL_INVALID_VALUE, got:"
2676                                                                   "["
2677                                                            << error_code << "]" << tcu::TestLog::EndMessage;
2678
2679                         TCU_FAIL(error_sstream.str().c_str());
2680                 }
2681
2682                 gl.drawRangeElementsBaseVertex(GL_TRIANGLES, /* mode */
2683                                                                            -1,                   /* start */
2684                                                                            2,                    /* end */
2685                                                                            1,                    /* count */
2686                                                                            GL_UNSIGNED_INT, (const glw::GLvoid*)m_draw_call_index_offset,
2687                                                                            0); /* basevertex */
2688
2689                 error_code = gl.getError();
2690                 if (error_code != GL_INVALID_VALUE)
2691                 {
2692                         std::stringstream error_sstream;
2693
2694                         error_sstream << "Invalid error code reported for an invalid "
2695                                                   << getFunctionName(FUNCTION_GL_DRAW_RANGE_ELEMENTS_BASE_VERTEX) << " call";
2696
2697                         m_testCtx.getLog() << tcu::TestLog::Message << error_sstream.str().c_str()
2698                                                            << ": expected GL_INVALID_VALUE, got:"
2699                                                                   "["
2700                                                            << error_code << "]" << tcu::TestLog::EndMessage;
2701
2702                         TCU_FAIL(error_sstream.str().c_str());
2703                 }
2704
2705                 gl.drawElementsInstancedBaseVertex(GL_TRIANGLES, /* mode */
2706                                                                                    -1,                   /* count */
2707                                                                                    GL_UNSIGNED_INT, (const glw::GLvoid*)m_draw_call_index_offset,
2708                                                                                    1,  /* instancecount */
2709                                                                                    0); /* basevertex */
2710
2711                 error_code = gl.getError();
2712                 if (error_code != GL_INVALID_VALUE)
2713                 {
2714                         std::stringstream error_sstream;
2715
2716                         error_sstream << "Invalid error code reported for an invalid "
2717                                                   << getFunctionName(FUNCTION_GL_DRAW_ELEMENTS_INSTANCED_BASE_VERTEX) << " call";
2718
2719                         m_testCtx.getLog() << tcu::TestLog::Message << error_sstream.str().c_str()
2720                                                            << ": expected GL_INVALID_VALUE, got:"
2721                                                                   "["
2722                                                            << error_code << "]" << tcu::TestLog::EndMessage;
2723
2724                         TCU_FAIL(error_sstream.str().c_str());
2725                 }
2726
2727                 if (m_is_ext_multi_draw_arrays_supported)
2728                 {
2729                         const glw::GLsizei count         = -1;
2730                         const glw::GLvoid* offsets[] = { (const glw::GLvoid*)m_draw_call_index_offset };
2731
2732                         gl.multiDrawElementsBaseVertex(GL_TRIANGLES,                                            /* mode */
2733                                                                                    &count, GL_UNSIGNED_INT, offsets, 1, /* primcount */
2734                                                                                    0);                                                                  /* basevertex */
2735
2736                         error_code = gl.getError();
2737                         if (error_code != GL_INVALID_VALUE)
2738                         {
2739                                 std::stringstream error_sstream;
2740
2741                                 error_sstream << "Invalid error code reported for an invalid "
2742                                                           << getFunctionName(FUNCTION_GL_MULTI_DRAW_ELEMENTS_BASE_VERTEX) << " call";
2743
2744                                 m_testCtx.getLog() << tcu::TestLog::Message << error_sstream.str().c_str()
2745                                                                    << ": expected GL_INVALID_VALUE, got:"
2746                                                                           "["
2747                                                                    << error_code << "]" << tcu::TestLog::EndMessage;
2748
2749                                 TCU_FAIL("Invalid error code reported for an invalid glMultiDrawElementsBaseVertexEXT() call.");
2750                         }
2751                 } /* if (m_is_ext_multi_draw_arrays_supported) */
2752         }        /* for (all iterations) */
2753
2754         /* Test case passed */
2755         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2756
2757         return STOP;
2758 }
2759
2760 /** Constructor.
2761  *
2762  *  @param context Rendering context handle.
2763  **/
2764 DrawElementsBaseVertexNegativeInvalidInstanceCountArgumentTest::
2765         DrawElementsBaseVertexNegativeInvalidInstanceCountArgumentTest(Context& context, const ExtParameters& extParams)
2766         : DrawElementsBaseVertexTestBase(context, extParams, "invalid_instancecount_argument",
2767                                                                          "Tries to use invalid 'instancecount' argument values for "
2768                                                                          "glDrawElementsInstancedBaseVertexEXT (ES) or "
2769                                                                          "glDrawElementsInstancedBaseVertex (GL) draw call")
2770 {
2771         /* Left blank on purpose */
2772 }
2773
2774 /** Executes test iteration.
2775  *
2776  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
2777  */
2778 tcu::TestNode::IterateResult DrawElementsBaseVertexNegativeInvalidInstanceCountArgumentTest::iterate()
2779 {
2780         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2781
2782         /* The test needs to be run in four iterations, where for each iteration we configure the VAO
2783          * in a slightly different manner.
2784          */
2785         for (int iteration = 0; iteration < 4; ++iteration)
2786         {
2787                 bool use_clientside_index_data  = ((iteration & (1 << 0)) != 0);
2788                 bool use_clientside_vertex_data = ((iteration & (1 << 1)) != 0);
2789
2790                 /* OpenGL does not support client-side data. */
2791                 if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
2792                 {
2793                         if (use_clientside_index_data || use_clientside_vertex_data)
2794                         {
2795                                 continue;
2796                         }
2797                 }
2798
2799                 /* Set up the work environment */
2800                 setUpNegativeTestObjects(use_clientside_vertex_data, use_clientside_index_data);
2801
2802                 /* Try to execute the invalid draw call */
2803                 glw::GLenum error_code = GL_NONE;
2804
2805                 gl.drawElementsInstancedBaseVertex(GL_TRIANGLES, /* mode */
2806                                                                                    3,                    /* count */
2807                                                                                    GL_UNSIGNED_INT, (const glw::GLvoid*)m_draw_call_index_offset,
2808                                                                                    -1, /* instancecount */
2809                                                                                    0); /* basevertex */
2810
2811                 error_code = gl.getError();
2812                 if (error_code != GL_INVALID_VALUE)
2813                 {
2814                         std::stringstream error_sstream;
2815
2816                         error_sstream << "Invalid error code reported for an invalid "
2817                                                   << getFunctionName(FUNCTION_GL_DRAW_ELEMENTS_INSTANCED_BASE_VERTEX) << " call";
2818
2819                         m_testCtx.getLog() << tcu::TestLog::Message << error_sstream.str().c_str()
2820                                                            << ": expected GL_INVALID_VALUE, got:"
2821                                                                   "["
2822                                                            << error_code << "]" << tcu::TestLog::EndMessage;
2823
2824                         TCU_FAIL(error_sstream.str().c_str());
2825                 }
2826         } /* for (all test iterations) */
2827
2828         /* Test case passed */
2829         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2830
2831         return STOP;
2832 }
2833
2834 /** Constructor.
2835  *
2836  *  @param context Rendering context handle.
2837  **/
2838 DrawElementsBaseVertexNegativeInvalidModeArgumentTest::DrawElementsBaseVertexNegativeInvalidModeArgumentTest(
2839         Context& context, const ExtParameters& extParams)
2840         : DrawElementsBaseVertexTestBase(context, extParams, "invalid_mode_argument",
2841                                                                          "Tries to use invalid 'mode' argument values for the \"base vertex\" draw calls")
2842 {
2843         /* Left blank on purpose */
2844 }
2845
2846 /** Executes test iteration.
2847  *
2848  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
2849  */
2850 tcu::TestNode::IterateResult DrawElementsBaseVertexNegativeInvalidModeArgumentTest::iterate()
2851 {
2852         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2853
2854         /* The test needs to be run in four iterations, where for each iteration we configure the VAO
2855          * in a slightly different manner.
2856          */
2857         for (int iteration = 0; iteration < 4; ++iteration)
2858         {
2859                 bool use_clientside_index_data  = ((iteration & (1 << 0)) != 0);
2860                 bool use_clientside_vertex_data = ((iteration & (1 << 1)) != 0);
2861
2862                 /* OpenGL does not support client-side data. */
2863                 if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
2864                 {
2865                         if (use_clientside_index_data || use_clientside_vertex_data)
2866                         {
2867                                 continue;
2868                         }
2869                 }
2870
2871                 /* Set up the work environment */
2872                 setUpNegativeTestObjects(use_clientside_vertex_data, use_clientside_index_data);
2873
2874                 /* Try to execute the invalid draw calls */
2875                 glw::GLenum error_code = GL_NONE;
2876
2877                 gl.drawElementsBaseVertex(GL_GREATER,                                                                                                            /* mode */
2878                                                                   3,                                                                                                                             /* count */
2879                                                                   GL_UNSIGNED_INT, (const glw::GLvoid*)m_draw_call_index_offset, 0); /* basevertex */
2880
2881                 error_code = gl.getError();
2882                 if (error_code != GL_INVALID_ENUM)
2883                 {
2884                         std::stringstream error_sstream;
2885
2886                         error_sstream << "Invalid error code reported for an invalid "
2887                                                   << getFunctionName(FUNCTION_GL_DRAW_ELEMENTS_BASE_VERTEX) << " call";
2888
2889                         m_testCtx.getLog() << tcu::TestLog::Message << error_sstream.str().c_str()
2890                                                            << ": expected GL_INVALID_ENUM, got:"
2891                                                                   "["
2892                                                            << error_code << "]" << tcu::TestLog::EndMessage;
2893
2894                         TCU_FAIL(error_sstream.str().c_str());
2895                 }
2896
2897                 gl.drawRangeElementsBaseVertex(GL_GREATER, /* mode */
2898                                                                            0,              /* start */
2899                                                                            2,              /* end */
2900                                                                            3,              /* count */
2901                                                                            GL_UNSIGNED_INT, (const glw::GLvoid*)m_draw_call_index_offset,
2902                                                                            0); /* basevertex */
2903
2904                 error_code = gl.getError();
2905                 if (error_code != GL_INVALID_ENUM)
2906                 {
2907                         std::stringstream error_sstream;
2908
2909                         error_sstream << "Invalid error code reported for an invalid "
2910                                                   << getFunctionName(FUNCTION_GL_DRAW_RANGE_ELEMENTS_BASE_VERTEX) << " call";
2911
2912                         m_testCtx.getLog() << tcu::TestLog::Message << error_sstream.str().c_str()
2913                                                            << ": expected GL_INVALID_ENUM, got:"
2914                                                                   "["
2915                                                            << error_code << "]" << tcu::TestLog::EndMessage;
2916
2917                         TCU_FAIL(error_sstream.str().c_str());
2918                 }
2919
2920                 gl.drawElementsInstancedBaseVertex(GL_GREATER, /* mode */
2921                                                                                    3,              /* count */
2922                                                                                    GL_UNSIGNED_INT, (const glw::GLvoid*)m_draw_call_index_offset,
2923                                                                                    1,  /* instancecount */
2924                                                                                    0); /* basevertex */
2925
2926                 error_code = gl.getError();
2927                 if (error_code != GL_INVALID_ENUM)
2928                 {
2929                         std::stringstream error_sstream;
2930
2931                         error_sstream << "Invalid error code reported for an invalid "
2932                                                   << getFunctionName(FUNCTION_GL_DRAW_ELEMENTS_INSTANCED_BASE_VERTEX) << " call";
2933
2934                         m_testCtx.getLog() << tcu::TestLog::Message << error_sstream.str().c_str()
2935                                                            << ": expected GL_INVALID_ENUM, got:"
2936                                                                   "["
2937                                                            << error_code << "]" << tcu::TestLog::EndMessage;
2938
2939                         TCU_FAIL(error_sstream.str().c_str());
2940                 }
2941
2942                 if (m_is_ext_multi_draw_arrays_supported)
2943                 {
2944                         const glw::GLsizei count         = 3;
2945                         const glw::GLvoid* offsets[] = { (const glw::GLvoid*)m_draw_call_index_offset };
2946
2947                         gl.multiDrawElementsBaseVertex(GL_GREATER,                                                      /* mode */
2948                                                                                    &count, GL_UNSIGNED_INT, offsets, 1, /* primcount */
2949                                                                                    0);                                                                  /* basevertex */
2950
2951                         error_code = gl.getError();
2952                         if (error_code != GL_INVALID_ENUM)
2953                         {
2954                                 std::stringstream error_sstream;
2955
2956                                 error_sstream << "Invalid error code reported for an invalid "
2957                                                           << getFunctionName(FUNCTION_GL_MULTI_DRAW_ELEMENTS_BASE_VERTEX) << " call";
2958
2959                                 m_testCtx.getLog() << tcu::TestLog::Message << error_sstream.str().c_str()
2960                                                                    << ": expected GL_INVALID_ENUM, got:"
2961                                                                           "["
2962                                                                    << error_code << "]" << tcu::TestLog::EndMessage;
2963
2964                                 TCU_FAIL(error_sstream.str().c_str());
2965                         }
2966                 } /* if (m_is_ext_multi_draw_arrays_supported) */
2967         }        /* for (all test iterations) */
2968
2969         /* Test case passed */
2970         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2971
2972         return STOP;
2973 }
2974
2975 /** Constructor.
2976  *
2977  *  @param context Rendering context handle.
2978  **/
2979 DrawElementsBaseVertexNegativeInvalidPrimcountArgumentTest::DrawElementsBaseVertexNegativeInvalidPrimcountArgumentTest(
2980         Context& context, const ExtParameters& extParams)
2981         : DrawElementsBaseVertexTestBase(
2982                   context, extParams, "invalid_primcount_argument",
2983                   "Tries to use invalid 'primcount' argument values for the \"base vertex\" draw calls")
2984 {
2985         /* Left blank on purpose */
2986 }
2987
2988 /** Executes test iteration.
2989  *
2990  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
2991  */
2992 tcu::TestNode::IterateResult DrawElementsBaseVertexNegativeInvalidPrimcountArgumentTest::iterate()
2993 {
2994         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2995
2996         /* This test requires presence of GL_EXT_multi_draw_arrays under ES contexts */
2997         if (glu::isContextTypeES(m_context.getRenderContext().getType()))
2998         {
2999                 if (!m_is_ext_multi_draw_arrays_supported)
3000                 {
3001                         throw tcu::NotSupportedError("GL_EXT_multi_draw_arrays is not supported");
3002                 }
3003         }
3004
3005         /* The test needs to be run in four iterations, where for each iteration we configure the VAO
3006          * in a slightly different manner.
3007          */
3008         for (int iteration = 0; iteration < 4; ++iteration)
3009         {
3010                 bool use_clientside_index_data  = ((iteration & (1 << 0)) != 0);
3011                 bool use_clientside_vertex_data = ((iteration & (1 << 1)) != 0);
3012
3013                 /* OpenGL does not support client-side data. */
3014                 if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
3015                 {
3016                         if (use_clientside_index_data || use_clientside_vertex_data)
3017                         {
3018                                 continue;
3019                         }
3020                 }
3021
3022                 /* Set up the work environment */
3023                 setUpNegativeTestObjects(use_clientside_vertex_data, use_clientside_index_data);
3024
3025                 /* Perform the test */
3026                 const glw::GLsizei count          = 3;
3027                 glw::GLenum                error_code = GL_NO_ERROR;
3028                 const glw::GLvoid* offsets[]  = { (const glw::GLvoid*)m_draw_call_index_offset };
3029
3030                 gl.multiDrawElementsBaseVertex(GL_TRIANGLES,                                             /* mode */
3031                                                                            &count, GL_UNSIGNED_INT, offsets, -1, /* primcount */
3032                                                                            0);                                                                   /* basevertex */
3033
3034                 error_code = gl.getError();
3035                 if (error_code != GL_INVALID_VALUE)
3036                 {
3037                         std::stringstream error_sstream;
3038
3039                         error_sstream << "Invalid error code reported for an invalid "
3040                                                   << getFunctionName(FUNCTION_GL_MULTI_DRAW_ELEMENTS_BASE_VERTEX) << " call";
3041
3042                         m_testCtx.getLog() << tcu::TestLog::Message << error_sstream.str().c_str()
3043                                                            << ": expected GL_INVALID_VALUE, got:"
3044                                                                   "["
3045                                                            << error_code << "]" << tcu::TestLog::EndMessage;
3046
3047                         TCU_FAIL(error_sstream.str().c_str());
3048                 }
3049         } /* for (all test iterations) */
3050
3051         /* Test case passed */
3052         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
3053
3054         return STOP;
3055 }
3056
3057 /** Constructor.
3058  *
3059  *  @param context Rendering context handle.
3060  **/
3061 DrawElementsBaseVertexNegativeInvalidStartEndArgumentsTest::DrawElementsBaseVertexNegativeInvalidStartEndArgumentsTest(
3062         Context& context, const ExtParameters& extParams)
3063         : DrawElementsBaseVertexTestBase(context, extParams, "invalid_start_end_arguments",
3064                                                                          "Tries to use invalid 'start' and 'end' argument values for the "
3065                                                                          "glDrawRangeElementsBaseVertexEXT() (under ES) or "
3066                                                                          "glDrawRangeElementsBaseVertex() (under GL) draw call")
3067 {
3068         /* Left blank on purpose */
3069 }
3070
3071 /** Executes test iteration.
3072  *
3073  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
3074  */
3075 tcu::TestNode::IterateResult DrawElementsBaseVertexNegativeInvalidStartEndArgumentsTest::iterate()
3076 {
3077         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3078
3079         /* The test needs to be run in four iterations, where for each iteration we configure the VAO
3080          * in a slightly different manner.
3081          */
3082         for (int iteration = 0; iteration < 4; ++iteration)
3083         {
3084                 bool use_clientside_index_data  = ((iteration & (1 << 0)) != 0);
3085                 bool use_clientside_vertex_data = ((iteration & (1 << 1)) != 0);
3086
3087                 /* OpenGL does not support client-side data. */
3088                 if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
3089                 {
3090                         if (use_clientside_index_data || use_clientside_vertex_data)
3091                         {
3092                                 continue;
3093                         }
3094                 }
3095
3096                 /* Set up the work environment */
3097                 setUpNegativeTestObjects(use_clientside_vertex_data, use_clientside_index_data);
3098
3099                 /* Try to execute the invalid draw call */
3100                 glw::GLenum error_code = GL_NONE;
3101
3102                 gl.drawRangeElementsBaseVertex(GL_TRIANGLES, /* mode */
3103                                                                            3,                    /* start */
3104                                                                            0,                    /* end */
3105                                                                            3,                    /* count */
3106                                                                            GL_UNSIGNED_INT, (const glw::GLvoid*)m_draw_call_index_offset,
3107                                                                            0); /* basevertex */
3108
3109                 error_code = gl.getError();
3110                 if (error_code != GL_INVALID_VALUE)
3111                 {
3112                         std::stringstream error_sstream;
3113
3114                         error_sstream << "Invalid error code reported for an invalid "
3115                                                   << getFunctionName(FUNCTION_GL_DRAW_RANGE_ELEMENTS_BASE_VERTEX) << " call";
3116
3117                         m_testCtx.getLog() << tcu::TestLog::Message << error_sstream.str().c_str()
3118                                                            << ": expected GL_INVALID_VALUE, got:"
3119                                                                   "["
3120                                                            << error_code << "]" << tcu::TestLog::EndMessage;
3121
3122                         TCU_FAIL(error_sstream.str().c_str());
3123                 }
3124         } /* for (all test iterations) */
3125
3126         /* Test case passed */
3127         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
3128
3129         return STOP;
3130 }
3131
3132 /** Constructor.
3133  *
3134  *  @param context Rendering context handle.
3135  **/
3136 DrawElementsBaseVertexNegativeInvalidTypeArgumentTest::DrawElementsBaseVertexNegativeInvalidTypeArgumentTest(
3137         Context& context, const ExtParameters& extParams)
3138         : DrawElementsBaseVertexTestBase(context, extParams, "invalid_type_argument",
3139                                                                          "Tries to use invalid 'type' argument values for the \"base vertex\" draw calls")
3140 {
3141         /* Left blank on purpose */
3142 }
3143
3144 /** Executes test iteration.
3145  *
3146  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
3147  */
3148 tcu::TestNode::IterateResult DrawElementsBaseVertexNegativeInvalidTypeArgumentTest::iterate()
3149 {
3150         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3151
3152         /* The test needs to be run in four iterations, where for each iteration we configure the VAO
3153          * in a slightly different manner.
3154          */
3155         for (int iteration = 0; iteration < 4; ++iteration)
3156         {
3157                 bool use_clientside_index_data  = ((iteration & (1 << 0)) != 0);
3158                 bool use_clientside_vertex_data = ((iteration & (1 << 1)) != 0);
3159
3160                 /* OpenGL does not support client-side data. */
3161                 if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
3162                 {
3163                         if (use_clientside_index_data || use_clientside_vertex_data)
3164                         {
3165                                 continue;
3166                         }
3167                 }
3168
3169                 /* Set up the work environment */
3170                 setUpNegativeTestObjects(use_clientside_vertex_data, use_clientside_index_data);
3171
3172                 /* Try to execute the invalid draw calls */
3173                 glw::GLenum error_code = GL_NONE;
3174
3175                 gl.drawElementsBaseVertex(GL_TRIANGLES,                                                                                          /* mode */
3176                                                                   3,                                                                                                             /* count */
3177                                                                   GL_NONE, (const glw::GLvoid*)m_draw_call_index_offset, 0); /* basevertex */
3178
3179                 error_code = gl.getError();
3180                 if (error_code != GL_INVALID_ENUM)
3181                 {
3182                         std::stringstream error_sstream;
3183
3184                         error_sstream << "Invalid error code reported for an invalid "
3185                                                   << getFunctionName(FUNCTION_GL_DRAW_ELEMENTS_BASE_VERTEX) << " call";
3186
3187                         m_testCtx.getLog() << tcu::TestLog::Message << error_sstream.str().c_str()
3188                                                            << ": expected GL_INVALID_ENUM, got:"
3189                                                                   "["
3190                                                            << error_code << "]" << tcu::TestLog::EndMessage;
3191
3192                         TCU_FAIL(error_sstream.str().c_str());
3193                 }
3194
3195                 gl.drawRangeElementsBaseVertex(GL_TRIANGLES,                                                                                      /* mode */
3196                                                                            0,                                                                                                             /* start */
3197                                                                            2,                                                                                                             /* end */
3198                                                                            3,                                                                                                             /* count */
3199                                                                            GL_NONE, (const glw::GLvoid*)m_draw_call_index_offset, 0); /* basevertex */
3200
3201                 error_code = gl.getError();
3202                 if (error_code != GL_INVALID_ENUM)
3203                 {
3204                         std::stringstream error_sstream;
3205
3206                         error_sstream << "Invalid error code reported for an invalid "
3207                                                   << getFunctionName(FUNCTION_GL_DRAW_RANGE_ELEMENTS_BASE_VERTEX) << " call";
3208
3209                         m_testCtx.getLog() << tcu::TestLog::Message << error_sstream.str().c_str()
3210                                                            << ": expected GL_INVALID_ENUM, got:"
3211                                                                   "["
3212                                                            << error_code << "]" << tcu::TestLog::EndMessage;
3213
3214                         TCU_FAIL(error_sstream.str().c_str());
3215                 }
3216
3217                 gl.drawElementsInstancedBaseVertex(GL_TRIANGLES,                                                                                         /* mode */
3218                                                                                    3,                                                                                                            /* count */
3219                                                                                    GL_NONE, (const glw::GLvoid*)m_draw_call_index_offset, 1, /* instancecount */
3220                                                                                    0);                                                                                                           /* basevertex */
3221
3222                 error_code = gl.getError();
3223                 if (error_code != GL_INVALID_ENUM)
3224                 {
3225                         std::stringstream error_sstream;
3226
3227                         error_sstream << "Invalid error code reported for an invalid "
3228                                                   << getFunctionName(FUNCTION_GL_DRAW_ELEMENTS_INSTANCED_BASE_VERTEX) << " call";
3229
3230                         m_testCtx.getLog() << tcu::TestLog::Message << error_sstream.str().c_str()
3231                                                            << ": expected GL_INVALID_ENUM, got:"
3232                                                                   "["
3233                                                            << error_code << "]" << tcu::TestLog::EndMessage;
3234
3235                         TCU_FAIL(error_sstream.str().c_str());
3236                 }
3237
3238                 if (m_is_ext_multi_draw_arrays_supported)
3239                 {
3240                         const glw::GLsizei count         = 3;
3241                         const glw::GLvoid* offsets[] = { (const glw::GLvoid*)m_draw_call_index_offset };
3242
3243                         gl.multiDrawElementsBaseVertex(GL_TRIANGLES,                            /* mode */
3244                                                                                    &count, GL_NONE, offsets, 1, /* primcount */
3245                                                                                    0);                                                  /* basevertex */
3246
3247                         error_code = gl.getError();
3248                         if (error_code != GL_INVALID_ENUM)
3249                         {
3250                                 std::stringstream error_sstream;
3251
3252                                 error_sstream << "Invalid error code reported for an invalid "
3253                                                           << getFunctionName(FUNCTION_GL_MULTI_DRAW_ELEMENTS_BASE_VERTEX) << " call";
3254
3255                                 m_testCtx.getLog() << tcu::TestLog::Message << error_sstream.str().c_str()
3256                                                                    << ": expected GL_INVALID_ENUM, got:"
3257                                                                           "["
3258                                                                    << error_code << "]" << tcu::TestLog::EndMessage;
3259
3260                                 TCU_FAIL(error_sstream.str().c_str());
3261                         }
3262                 } /* if (m_is_ext_multi_draw_arrays_supported) */
3263         }        /* for (all test iterations) */
3264
3265         /* Test case passed */
3266         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
3267
3268         return STOP;
3269 }
3270
3271 /** Constructor.
3272  *
3273  *  @param context Rendering context.
3274  */
3275 DrawElementsBaseVertexTests::DrawElementsBaseVertexTests(glcts::Context& context, const ExtParameters& extParams)
3276         : TestCaseGroupBase(context, extParams, "draw_elements_base_vertex_tests",
3277                                                 "Contains conformance tests that verify ES and GL implementation's support "
3278                                                 "for GL_EXT_draw_elements_base_vertex (ES) and "
3279                                                 "GL_ARB_draw_elements_base_vertex (GL) extensions.")
3280 {
3281 }
3282
3283 /** Initializes the test group contents. */
3284 void DrawElementsBaseVertexTests::init()
3285 {
3286         addChild(new DrawElementsBaseVertexFunctionalCorrectBaseVertexBehavior(m_context, m_extParams));
3287         addChild(new DrawElementsBaseVertexFunctionalCorrectBaseVertexBehavior2(m_context, m_extParams));
3288         addChild(new DrawElementsBaseVertexFunctionalCorrectBaseVertexBehaviorAEPShaderStages(m_context, m_extParams));
3289         addChild(new DrawElementsBaseVertexFunctionalCorrectBaseVertexBehaviorUnderflow(m_context, m_extParams));
3290         addChild(new DrawElementsBaseVertexFunctionalCorrectBaseVertexBehaviorOverflow(m_context, m_extParams));
3291         addChild(new DrawElementsBaseVertexNegativeActiveTransformFeedbackTest(m_context, m_extParams));
3292         addChild(new DrawElementsBaseVertexNegativeInvalidCountArgumentTest(m_context, m_extParams));
3293         addChild(new DrawElementsBaseVertexNegativeInvalidInstanceCountArgumentTest(m_context, m_extParams));
3294         addChild(new DrawElementsBaseVertexNegativeInvalidModeArgumentTest(m_context, m_extParams));
3295         addChild(new DrawElementsBaseVertexNegativeInvalidPrimcountArgumentTest(m_context, m_extParams));
3296         addChild(new DrawElementsBaseVertexNegativeInvalidStartEndArgumentsTest(m_context, m_extParams));
3297         addChild(new DrawElementsBaseVertexNegativeInvalidTypeArgumentTest(m_context, m_extParams));
3298 }
3299
3300 } /* glcts namespace */