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