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