• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*-------------------------------------------------------------------------
2  * OpenGL Conformance Test Suite
3  * -----------------------------
4  *
5  * Copyright (c) 2015-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  gl4cDirectStateAccessVertexArraysTests.cpp
27  * \brief Conformance tests for the Direct State Access feature functionality (Vertex Array Objects access part).
28  */ /*-----------------------------------------------------------------------------------------------------------*/
29 
30 /* Includes. */
31 #include "gl4cDirectStateAccessTests.hpp"
32 
33 #include "deSharedPtr.hpp"
34 
35 #include "gluContextInfo.hpp"
36 #include "gluDefs.hpp"
37 #include "gluPixelTransfer.hpp"
38 #include "gluStrUtil.hpp"
39 
40 #include "tcuFuzzyImageCompare.hpp"
41 #include "tcuImageCompare.hpp"
42 #include "tcuRenderTarget.hpp"
43 #include "tcuSurface.hpp"
44 #include "tcuTestLog.hpp"
45 
46 #include "glw.h"
47 #include "glwFunctions.hpp"
48 
49 #include <algorithm>
50 #include <climits>
51 #include <cmath>
52 #include <set>
53 #include <sstream>
54 #include <stack>
55 
56 namespace gl4cts
57 {
58 namespace DirectStateAccess
59 {
60 namespace VertexArrays
61 {
62 /******************************** Creation Test Implementation   ********************************/
63 
64 /** @brief Creation Test constructor.
65  *
66  *  @param [in] context     OpenGL context.
67  */
CreationTest(deqp::Context & context)68 CreationTest::CreationTest(deqp::Context& context)
69 	: deqp::TestCase(context, "vertex_arrays_creation", "Vertex Array Objects Creation Test")
70 {
71 	/* Intentionally left blank. */
72 }
73 
74 /** @brief Iterate Creation Test cases.
75  *
76  *  @return Iteration result.
77  */
iterate()78 tcu::TestNode::IterateResult CreationTest::iterate()
79 {
80 	/* Shortcut for GL functionality. */
81 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
82 
83 	/* Get context setup. */
84 	bool is_at_least_gl_45 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 5)));
85 	bool is_arb_direct_state_access = m_context.getContextInfo().isExtensionSupported("GL_ARB_direct_state_access");
86 
87 	if ((!is_at_least_gl_45) && (!is_arb_direct_state_access))
88 	{
89 		m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported");
90 
91 		return STOP;
92 	}
93 
94 	/* Running tests. */
95 	bool is_ok	= true;
96 	bool is_error = false;
97 
98 	/* VertexArrays' objects */
99 	static const glw::GLuint vertex_arrays_count = 2;
100 
101 	glw::GLuint vertex_arrays_legacy[vertex_arrays_count] = {};
102 	glw::GLuint vertex_arrays_dsa[vertex_arrays_count]	= {};
103 
104 	try
105 	{
106 		/* Check legacy state creation. */
107 		gl.genVertexArrays(vertex_arrays_count, vertex_arrays_legacy);
108 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays have failed");
109 
110 		for (glw::GLuint i = 0; i < vertex_arrays_count; ++i)
111 		{
112 			if (gl.isVertexArray(vertex_arrays_legacy[i]))
113 			{
114 				is_ok = false;
115 
116 				/* Log. */
117 				m_context.getTestContext().getLog()
118 					<< tcu::TestLog::Message
119 					<< "GenVertexArrays has created default objects, but it should create only a names."
120 					<< tcu::TestLog::EndMessage;
121 			}
122 		}
123 
124 		/* Check direct state creation. */
125 		gl.createVertexArrays(vertex_arrays_count, vertex_arrays_dsa);
126 		GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateVertexArrays have failed");
127 
128 		for (glw::GLuint i = 0; i < vertex_arrays_count; ++i)
129 		{
130 			if (!gl.isVertexArray(vertex_arrays_dsa[i]))
131 			{
132 				is_ok = false;
133 
134 				/* Log. */
135 				m_context.getTestContext().getLog() << tcu::TestLog::Message
136 													<< "CreateVertexArrays has not created default objects."
137 													<< tcu::TestLog::EndMessage;
138 			}
139 		}
140 	}
141 	catch (...)
142 	{
143 		is_ok	= false;
144 		is_error = true;
145 	}
146 
147 	/* Cleanup. */
148 	for (glw::GLuint i = 0; i < vertex_arrays_count; ++i)
149 	{
150 		if (vertex_arrays_legacy[i])
151 		{
152 			gl.deleteVertexArrays(1, &vertex_arrays_legacy[i]);
153 
154 			vertex_arrays_legacy[i] = 0;
155 		}
156 
157 		if (vertex_arrays_dsa[i])
158 		{
159 			gl.deleteVertexArrays(1, &vertex_arrays_dsa[i]);
160 
161 			vertex_arrays_dsa[i] = 0;
162 		}
163 	}
164 
165 	/* Errors clean up. */
166 	while (gl.getError())
167 		;
168 
169 	/* Result's setup. */
170 	if (is_ok)
171 	{
172 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
173 	}
174 	else
175 	{
176 		if (is_error)
177 		{
178 			m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
179 		}
180 		else
181 		{
182 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
183 		}
184 	}
185 
186 	return STOP;
187 }
188 
189 /******************************** Vertex Array Object Enable Disable Attributes Test Implementation   ********************************/
190 
191 /** @brief Vertex Array Object Enable Disable Attributes Test constructor.
192  *
193  *  @param [in] context     OpenGL context.
194  */
EnableDisableAttributesTest(deqp::Context & context)195 EnableDisableAttributesTest::EnableDisableAttributesTest(deqp::Context& context)
196 	: deqp::TestCase(context, "vertex_arrays_enable_disable_attributes",
197 					 "Vertex Array Objects Enable Disable Attributes Test")
198 	, m_po_even(0)
199 	, m_po_odd(0)
200 	, m_vao(0)
201 	, m_bo(0)
202 	, m_bo_xfb(0)
203 	, m_max_attributes(16) /* Required Minimum: OpenGL 4.5 Table 23.57: Implementation Dependent Vertex Shader Limits */
204 {
205 	/* Intentionally left blank. */
206 }
207 
208 /** @brief Iterate Vertex Array Object Enable Disable Attributes Test cases.
209  *
210  *  @return Iteration result.
211  */
iterate()212 tcu::TestNode::IterateResult EnableDisableAttributesTest::iterate()
213 {
214 	/* Shortcut for GL functionality. */
215 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
216 
217 	/* Get context setup. */
218 	bool is_at_least_gl_45 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 5)));
219 	bool is_arb_direct_state_access = m_context.getContextInfo().isExtensionSupported("GL_ARB_direct_state_access");
220 
221 	if ((!is_at_least_gl_45) && (!is_arb_direct_state_access))
222 	{
223 		m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported");
224 
225 		return STOP;
226 	}
227 
228 	/* Running tests. */
229 	bool is_ok	= true;
230 	bool is_error = false;
231 
232 	try
233 	{
234 		gl.getIntegerv(GL_MAX_VERTEX_ATTRIBS, &m_max_attributes);
235 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, ...) have failed");
236 
237 		m_po_even = PrepareProgram(false);
238 		m_po_odd  = PrepareProgram(true);
239 
240 		PrepareVAO();
241 		PrepareXFB();
242 
243 		is_ok &= TurnOnAttributes(true, false);
244 		is_ok &= DrawAndCheck(false);
245 
246 		is_ok &= TurnOnAttributes(false, true);
247 		is_ok &= DrawAndCheck(true);
248 	}
249 	catch (...)
250 	{
251 		is_ok	= false;
252 		is_error = true;
253 	}
254 
255 	/* Cleanup. */
256 	Clean();
257 
258 	/* Errors clean up. */
259 	while (gl.getError())
260 		;
261 
262 	/* Result's setup. */
263 	if (is_ok)
264 	{
265 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
266 	}
267 	else
268 	{
269 		if (is_error)
270 		{
271 			m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
272 		}
273 		else
274 		{
275 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
276 		}
277 	}
278 
279 	return STOP;
280 }
281 
PrepareProgram(const bool bind_even_or_odd)282 glw::GLuint EnableDisableAttributesTest::PrepareProgram(const bool bind_even_or_odd)
283 {
284 	/* Preprocess vertex shader sources. */
285 	std::string declarations = "";
286 	std::string copies		 = "    sum = 0;\n";
287 
288 	for (glw::GLint i = (glw::GLint)(bind_even_or_odd); i < m_max_attributes; i += 2)
289 	{
290 		declarations.append((std::string("in int a_").append(Utilities::itoa(i))).append(";\n"));
291 		copies.append((std::string("    sum += a_").append(Utilities::itoa(i))).append(";\n"));
292 	}
293 
294 	std::string vs_template(s_vertex_shader_template);
295 
296 	std::string vs_source = Utilities::replace(vs_template, "DECLARATION_TEMPLATE", declarations);
297 	vs_source			  = Utilities::replace(vs_source, "COPY_TEMPLATE", copies);
298 
299 	/* Build and compile. */
300 	return BuildProgram(vs_source.c_str(), bind_even_or_odd);
301 }
302 
303 /** @brief Build test's GLSL program.
304  *
305  *  @note The function may throw if unexpected error has occured.
306  */
BuildProgram(const char * vertex_shader,const bool bind_even_or_odd)307 glw::GLuint EnableDisableAttributesTest::BuildProgram(const char* vertex_shader, const bool bind_even_or_odd)
308 {
309 	/* Shortcut for GL functionality */
310 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
311 
312 	struct Shader
313 	{
314 		glw::GLchar const* const source;
315 		glw::GLenum const		 type;
316 		glw::GLuint				 id;
317 	} shader[] = { { vertex_shader, GL_VERTEX_SHADER, 0 }, { s_fragment_shader, GL_FRAGMENT_SHADER, 0 } };
318 
319 	glw::GLuint const shader_count = DE_LENGTH_OF_ARRAY(shader);
320 
321 	glw::GLuint po = 0;
322 
323 	try
324 	{
325 		/* Create program. */
326 		po = gl.createProgram();
327 		GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram call failed.");
328 
329 		/* Shader compilation. */
330 
331 		for (glw::GLuint i = 0; i < shader_count; ++i)
332 		{
333 			if (DE_NULL != shader[i].source)
334 			{
335 				shader[i].id = gl.createShader(shader[i].type);
336 
337 				GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader call failed.");
338 
339 				gl.attachShader(po, shader[i].id);
340 
341 				GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader call failed.");
342 
343 				gl.shaderSource(shader[i].id, 1, &(shader[i].source), NULL);
344 
345 				GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource call failed.");
346 
347 				gl.compileShader(shader[i].id);
348 
349 				GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader call failed.");
350 
351 				glw::GLint status = GL_FALSE;
352 
353 				gl.getShaderiv(shader[i].id, GL_COMPILE_STATUS, &status);
354 				GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv call failed.");
355 
356 				if (GL_FALSE == status)
357 				{
358 					glw::GLint log_size = 0;
359 					gl.getShaderiv(shader[i].id, GL_INFO_LOG_LENGTH, &log_size);
360 					GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv call failed.");
361 
362 					glw::GLchar* log_text = new glw::GLchar[log_size];
363 
364 					gl.getShaderInfoLog(shader[i].id, log_size, NULL, &log_text[0]);
365 
366 					m_context.getTestContext().getLog() << tcu::TestLog::Message << "Shader compilation has failed.\n"
367 														<< "Shader type: " << glu::getShaderTypeStr(shader[i].type)
368 														<< "\n"
369 														<< "Shader compilation error log:\n"
370 														<< log_text << "\n"
371 														<< "Shader source code:\n"
372 														<< shader[i].source << "\n"
373 														<< tcu::TestLog::EndMessage;
374 
375 					delete[] log_text;
376 
377 					GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderInfoLog call failed.");
378 
379 					throw 0;
380 				}
381 			}
382 		}
383 
384 		/* Transform Feedback setup. */
385 		static const glw::GLchar* xfb_varying = "sum";
386 
387 		gl.transformFeedbackVaryings(po, 1, &xfb_varying, GL_INTERLEAVED_ATTRIBS);
388 		GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings call failed.");
389 
390 		for (glw::GLint i = (glw::GLint)(bind_even_or_odd); i < m_max_attributes; i += 2)
391 		{
392 			std::string attribute = std::string("a_").append(Utilities::itoa(i));
393 
394 			gl.bindAttribLocation(po, i, attribute.c_str());
395 			GLU_EXPECT_NO_ERROR(gl.getError(), "glBindAttribLocation call failed.");
396 		}
397 
398 		/* Link. */
399 		gl.linkProgram(po);
400 
401 		GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings call failed.");
402 
403 		glw::GLint status = GL_FALSE;
404 
405 		gl.getProgramiv(po, GL_LINK_STATUS, &status);
406 
407 		if (GL_TRUE == status)
408 		{
409 			for (glw::GLuint i = 0; i < shader_count; ++i)
410 			{
411 				if (shader[i].id)
412 				{
413 					gl.detachShader(po, shader[i].id);
414 
415 					GLU_EXPECT_NO_ERROR(gl.getError(), "glDetachShader call failed.");
416 				}
417 			}
418 		}
419 		else
420 		{
421 			glw::GLint log_size = 0;
422 
423 			gl.getProgramiv(po, GL_INFO_LOG_LENGTH, &log_size);
424 
425 			GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv call failed.");
426 
427 			glw::GLchar* log_text = new glw::GLchar[log_size];
428 
429 			gl.getProgramInfoLog(po, log_size, NULL, &log_text[0]);
430 
431 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "Program linkage has failed due to:\n"
432 												<< log_text << "\n"
433 												<< tcu::TestLog::EndMessage;
434 
435 			delete[] log_text;
436 
437 			GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramInfoLog call failed.");
438 
439 			throw 0;
440 		}
441 	}
442 	catch (...)
443 	{
444 		if (po)
445 		{
446 			gl.deleteProgram(po);
447 
448 			po = 0;
449 		}
450 	}
451 
452 	for (glw::GLuint i = 0; i < shader_count; ++i)
453 	{
454 		if (0 != shader[i].id)
455 		{
456 			gl.deleteShader(shader[i].id);
457 
458 			shader[i].id = 0;
459 		}
460 	}
461 
462 	if (0 == po)
463 	{
464 		throw 0;
465 	}
466 
467 	return po;
468 }
469 
470 /** @brief Prepare vertex array object for the test.
471  */
PrepareVAO()472 void EnableDisableAttributesTest::PrepareVAO()
473 {
474 	/* Shortcut for GL functionality */
475 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
476 
477 	/* VAO creation. */
478 	gl.genVertexArrays(1, &m_vao);
479 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays call failed.");
480 
481 	gl.bindVertexArray(m_vao);
482 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed.");
483 
484 	/* Buffer creation. */
485 	gl.genBuffers(1, &m_bo);
486 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed.");
487 
488 	gl.bindBuffer(GL_ARRAY_BUFFER, m_bo);
489 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
490 
491 	glw::GLint* reference_data = new glw::GLint[m_max_attributes];
492 
493 	if (DE_NULL == reference_data)
494 	{
495 		throw 0;
496 	}
497 
498 	for (glw::GLint i = 0; i < m_max_attributes; ++i)
499 	{
500 		reference_data[i] = i;
501 	}
502 
503 	gl.bufferData(GL_ARRAY_BUFFER, sizeof(glw::GLint) * m_max_attributes, reference_data, GL_STATIC_DRAW);
504 
505 	delete[] reference_data;
506 
507 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed.");
508 
509 	/* VAO setup. */
510 	for (glw::GLint i = 0; i < m_max_attributes; ++i)
511 	{
512 		gl.vertexAttribIPointer(i, 1, GL_INT, static_cast<glw::GLsizei>(sizeof(glw::GLint) * m_max_attributes),
513 								glu::BufferOffsetAsPointer(i * sizeof(glw::GLint)));
514 
515 		GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribIPointer call failed.");
516 	}
517 }
518 
519 /** @brief Prepare buffer object for test GLSL program transform feedback results.
520  */
PrepareXFB()521 void EnableDisableAttributesTest::PrepareXFB()
522 {
523 	/* Shortcut for GL functionality */
524 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
525 
526 	/* Buffer creation. */
527 	gl.genBuffers(1, &m_bo_xfb);
528 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed.");
529 
530 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_xfb);
531 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
532 
533 	/* Preparing storage. */
534 	gl.bufferStorage(GL_TRANSFORM_FEEDBACK_BUFFER, sizeof(glw::GLint), NULL, GL_MAP_READ_BIT);
535 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferStorage call failed.");
536 
537 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_bo_xfb);
538 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase call failed.");
539 }
540 
541 /** @brief Draw test program, fetch transform feedback results and compare them with expected values.
542  *
543  *  @param [in] bind_even_or_odd         Even or odd attribute are enabled.
544  *
545  *  @return True if expected results are equal to returned by XFB, false otherwise.
546  */
DrawAndCheck(bool bind_even_or_odd)547 bool EnableDisableAttributesTest::DrawAndCheck(bool bind_even_or_odd)
548 {
549 	/* Shortcut for GL functionality */
550 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
551 
552 	/* Setup state. */
553 	gl.useProgram(bind_even_or_odd ? m_po_odd : m_po_even);
554 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed.");
555 
556 	gl.bindVertexArray(m_vao);
557 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed.");
558 
559 	gl.beginTransformFeedback(GL_POINTS);
560 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback call failed.");
561 
562 	/* Draw. */
563 	gl.drawArrays(GL_POINTS, 0, 1);
564 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays call failed.");
565 
566 	/* State reset. */
567 	gl.endTransformFeedback();
568 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback call failed.");
569 
570 	/* Result query. */
571 	glw::GLint* result_ptr = (glw::GLint*)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
572 	GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer call failed.");
573 
574 	glw::GLint result = *result_ptr;
575 
576 	gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
577 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer call failed.");
578 
579 	/* Check result and return. */
580 	if (bind_even_or_odd)
581 	{
582 		glw::GLint reference_sum = 0;
583 
584 		for (glw::GLint i = 1; i < m_max_attributes; i += 2)
585 		{
586 			reference_sum += i;
587 		}
588 
589 		if (reference_sum == result)
590 		{
591 			return true;
592 		}
593 	}
594 	else
595 	{
596 		glw::GLint reference_sum = 0;
597 
598 		for (glw::GLint i = 0; i < m_max_attributes; i += 2)
599 		{
600 			reference_sum += i;
601 		}
602 
603 		if (reference_sum == result)
604 		{
605 			return true;
606 		}
607 	}
608 
609 	return false;
610 }
611 
612 /** @brief Turn on even or odd attributes (up to m_max_attributes) using EnableVertexArrayAttrib function.
613  *
614  *  @param [in] enable_even         Turn on even attribute indexes.
615  *  @param [in] enable_odd          Turn on odd  attribute indexes.
616  *
617  *  @return True if EnableVertexArrayAttrib does not generate any error, false otherwise.
618  */
TurnOnAttributes(bool enable_even,bool enable_odd)619 bool EnableDisableAttributesTest::TurnOnAttributes(bool enable_even, bool enable_odd)
620 {
621 	/* Shortcut for GL functionality */
622 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
623 
624 	gl.bindVertexArray(0);
625 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed.");
626 
627 	for (glw::GLint i = 0; i < m_max_attributes; ++i)
628 	{
629 		bool disable = true;
630 
631 		if (i % 2) /* if odd */
632 		{
633 			if (enable_odd)
634 			{
635 				gl.enableVertexArrayAttrib(m_vao, i);
636 
637 				if (glw::GLenum error = gl.getError())
638 				{
639 					m_context.getTestContext().getLog()
640 						<< tcu::TestLog::Message << "glEnableVertexArrayAttrib generated error "
641 						<< glu::getErrorStr(error) << " when called with VAO " << m_vao << " and index " << i << "."
642 						<< tcu::TestLog::EndMessage;
643 
644 					return false;
645 				}
646 
647 				disable = false;
648 			}
649 		}
650 		else
651 		{
652 			if (enable_even)
653 			{
654 				gl.enableVertexArrayAttrib(m_vao, i);
655 
656 				if (glw::GLenum error = gl.getError())
657 				{
658 					m_context.getTestContext().getLog()
659 						<< tcu::TestLog::Message << "glEnableVertexArrayAttrib generated error "
660 						<< glu::getErrorStr(error) << " when called with VAO " << m_vao << " and index " << i << "."
661 						<< tcu::TestLog::EndMessage;
662 
663 					return false;
664 				}
665 
666 				disable = false;
667 			}
668 		}
669 
670 		if (disable)
671 		{
672 			gl.disableVertexArrayAttrib(m_vao, i);
673 
674 			if (glw::GLenum error = gl.getError())
675 			{
676 				m_context.getTestContext().getLog()
677 					<< tcu::TestLog::Message << "glDisableVertexArrayAttrib generated error " << glu::getErrorStr(error)
678 					<< " when called with VAO " << m_vao << " and index " << i << "." << tcu::TestLog::EndMessage;
679 
680 				return false;
681 			}
682 		}
683 	}
684 
685 	gl.bindVertexArray(m_vao);
686 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed.");
687 
688 	return true;
689 }
690 
691 /** @brief Clean GL objects. */
Clean()692 void EnableDisableAttributesTest::Clean()
693 {
694 	/* Shortcut for GL functionality */
695 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
696 
697 	gl.useProgram(0);
698 
699 	if (m_po_even)
700 	{
701 		gl.deleteProgram(m_po_even);
702 
703 		m_po_even = 0;
704 	}
705 
706 	if (m_po_odd)
707 	{
708 		gl.deleteProgram(m_po_odd);
709 
710 		m_po_odd = 0;
711 	}
712 
713 	if (m_vao)
714 	{
715 		gl.deleteVertexArrays(1, &m_vao);
716 
717 		m_vao = 0;
718 	}
719 
720 	if (m_bo)
721 	{
722 		gl.deleteBuffers(1, &m_bo);
723 
724 		m_bo = 0;
725 	}
726 
727 	if (m_bo_xfb)
728 	{
729 		gl.deleteBuffers(1, &m_bo_xfb);
730 
731 		m_bo_xfb = 0;
732 	}
733 
734 	if (m_max_attributes)
735 	{
736 		m_max_attributes =
737 			16; /* OpenGL 4.5 Required Minimum Table 23.57: Implementation Dependent Vertex Shader Limits */
738 	}
739 
740 	while (gl.getError())
741 		;
742 }
743 
itoa(glw::GLuint i)744 std::string Utilities::itoa(glw::GLuint i)
745 {
746 	std::string s = "";
747 
748 	std::stringstream ss;
749 
750 	ss << i;
751 
752 	s = ss.str();
753 
754 	return s;
755 }
756 
replace(const std::string & src,const std::string & key,const std::string & value)757 std::string Utilities::replace(const std::string& src, const std::string& key, const std::string& value)
758 {
759 	size_t		pos = 0;
760 	std::string dst = src;
761 
762 	while (std::string::npos != (pos = dst.find(key, pos)))
763 	{
764 		dst.replace(pos, key.length(), value);
765 		pos += key.length();
766 	}
767 
768 	return dst;
769 }
770 
771 const glw::GLchar EnableDisableAttributesTest::s_vertex_shader_template[] = "#version 450\n"
772 																			"\n"
773 																			"DECLARATION_TEMPLATE"
774 																			"out int sum;\n"
775 																			"\n"
776 																			"void main()\n"
777 																			"{\n"
778 																			"COPY_TEMPLATE"
779 																			"}\n";
780 
781 const glw::GLchar EnableDisableAttributesTest::s_fragment_shader[] = "#version 450\n"
782 																	 "\n"
783 																	 "out vec4 color;\n"
784 																	 "\n"
785 																	 "void main()\n"
786 																	 "{\n"
787 																	 "    color = vec4(1.0);"
788 																	 "}\n";
789 
790 /******************************** Vertex Array Object Element Buffer Test Implementation   ********************************/
791 
792 /** @brief Vertex Array Object Element Buffer Test constructor.
793  *
794  *  @param [in] context     OpenGL context.
795  */
ElementBufferTest(deqp::Context & context)796 ElementBufferTest::ElementBufferTest(deqp::Context& context)
797 	: deqp::TestCase(context, "vertex_arrays_element_buffer", "Vertex Array Objects Element Buffer Test")
798 	, m_po(0)
799 	, m_vao(0)
800 	, m_bo_array(0)
801 	, m_bo_elements(0)
802 	, m_bo_xfb(0)
803 {
804 	/* Intentionally left blank. */
805 }
806 
807 /** @brief Iterate Vertex Array Object Enable Disable Attributes Test cases.
808  *
809  *  @return Iteration result.
810  */
iterate()811 tcu::TestNode::IterateResult ElementBufferTest::iterate()
812 {
813 	/* Shortcut for GL functionality. */
814 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
815 
816 	/* Get context setup. */
817 	bool is_at_least_gl_45 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 5)));
818 	bool is_arb_direct_state_access = m_context.getContextInfo().isExtensionSupported("GL_ARB_direct_state_access");
819 
820 	if ((!is_at_least_gl_45) && (!is_arb_direct_state_access))
821 	{
822 		m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported");
823 
824 		return STOP;
825 	}
826 
827 	/* Running tests. */
828 	bool is_ok	= true;
829 	bool is_error = false;
830 
831 	try
832 	{
833 		PrepareProgram();
834 		is_ok &= PrepareVAO();
835 		PrepareXFB();
836 		is_ok &= DrawAndCheck();
837 	}
838 	catch (...)
839 	{
840 		is_ok	= false;
841 		is_error = true;
842 	}
843 
844 	/* Cleanup. */
845 	Clean();
846 
847 	/* Errors clean up. */
848 	while (gl.getError())
849 		;
850 
851 	/* Result's setup. */
852 	if (is_ok)
853 	{
854 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
855 	}
856 	else
857 	{
858 		if (is_error)
859 		{
860 			m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
861 		}
862 		else
863 		{
864 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
865 		}
866 	}
867 
868 	return STOP;
869 }
870 
871 /** @brief Build test's GLSL program.
872  *
873  *  @note The function may throw if unexpected error has occured.
874  */
PrepareProgram()875 void ElementBufferTest::PrepareProgram()
876 {
877 	/* Shortcut for GL functionality */
878 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
879 
880 	struct Shader
881 	{
882 		glw::GLchar const* const source;
883 		glw::GLenum const		 type;
884 		glw::GLuint				 id;
885 	} shader[] = { { s_vertex_shader, GL_VERTEX_SHADER, 0 }, { s_fragment_shader, GL_FRAGMENT_SHADER, 0 } };
886 
887 	glw::GLuint const shader_count = DE_LENGTH_OF_ARRAY(shader);
888 
889 	try
890 	{
891 		/* Create program. */
892 		m_po = gl.createProgram();
893 		GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram call failed.");
894 
895 		/* Shader compilation. */
896 
897 		for (glw::GLuint i = 0; i < shader_count; ++i)
898 		{
899 			if (DE_NULL != shader[i].source)
900 			{
901 				shader[i].id = gl.createShader(shader[i].type);
902 
903 				GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader call failed.");
904 
905 				gl.attachShader(m_po, shader[i].id);
906 
907 				GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader call failed.");
908 
909 				gl.shaderSource(shader[i].id, 1, &(shader[i].source), NULL);
910 
911 				GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource call failed.");
912 
913 				gl.compileShader(shader[i].id);
914 
915 				GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader call failed.");
916 
917 				glw::GLint status = GL_FALSE;
918 
919 				gl.getShaderiv(shader[i].id, GL_COMPILE_STATUS, &status);
920 				GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv call failed.");
921 
922 				if (GL_FALSE == status)
923 				{
924 					glw::GLint log_size = 0;
925 					gl.getShaderiv(shader[i].id, GL_INFO_LOG_LENGTH, &log_size);
926 					GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv call failed.");
927 
928 					glw::GLchar* log_text = new glw::GLchar[log_size];
929 
930 					gl.getShaderInfoLog(shader[i].id, log_size, NULL, &log_text[0]);
931 
932 					m_context.getTestContext().getLog() << tcu::TestLog::Message << "Shader compilation has failed.\n"
933 														<< "Shader type: " << glu::getShaderTypeStr(shader[i].type)
934 														<< "\n"
935 														<< "Shader compilation error log:\n"
936 														<< log_text << "\n"
937 														<< "Shader source code:\n"
938 														<< shader[i].source << "\n"
939 														<< tcu::TestLog::EndMessage;
940 
941 					delete[] log_text;
942 
943 					GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderInfoLog call failed.");
944 
945 					throw 0;
946 				}
947 			}
948 		}
949 
950 		/* Transform Feedback setup. */
951 		static const glw::GLchar* xfb_varying = "result";
952 
953 		gl.transformFeedbackVaryings(m_po, 1, &xfb_varying, GL_INTERLEAVED_ATTRIBS);
954 		GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings call failed.");
955 
956 		/* Link. */
957 		gl.linkProgram(m_po);
958 
959 		GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings call failed.");
960 
961 		glw::GLint status = GL_FALSE;
962 
963 		gl.getProgramiv(m_po, GL_LINK_STATUS, &status);
964 
965 		if (GL_TRUE == status)
966 		{
967 			for (glw::GLuint i = 0; i < shader_count; ++i)
968 			{
969 				if (shader[i].id)
970 				{
971 					gl.detachShader(m_po, shader[i].id);
972 
973 					GLU_EXPECT_NO_ERROR(gl.getError(), "glDetachShader call failed.");
974 				}
975 			}
976 		}
977 		else
978 		{
979 			glw::GLint log_size = 0;
980 
981 			gl.getProgramiv(m_po, GL_INFO_LOG_LENGTH, &log_size);
982 
983 			GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv call failed.");
984 
985 			glw::GLchar* log_text = new glw::GLchar[log_size];
986 
987 			gl.getProgramInfoLog(m_po, log_size, NULL, &log_text[0]);
988 
989 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "Program linkage has failed due to:\n"
990 												<< log_text << "\n"
991 												<< tcu::TestLog::EndMessage;
992 
993 			delete[] log_text;
994 
995 			GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramInfoLog call failed.");
996 
997 			throw 0;
998 		}
999 	}
1000 	catch (...)
1001 	{
1002 		if (m_po)
1003 		{
1004 			gl.deleteProgram(m_po);
1005 
1006 			m_po = 0;
1007 		}
1008 	}
1009 
1010 	for (glw::GLuint i = 0; i < shader_count; ++i)
1011 	{
1012 		if (0 != shader[i].id)
1013 		{
1014 			gl.deleteShader(shader[i].id);
1015 
1016 			shader[i].id = 0;
1017 		}
1018 	}
1019 
1020 	if (0 == m_po)
1021 	{
1022 		throw 0;
1023 	}
1024 }
1025 
1026 /** @brief Prepare vertex array object for the test of VertexArrayElementBuffer function.
1027  *
1028  *  @return True if function VertexArrayElementBuffer* does not generate any error.
1029  */
PrepareVAO()1030 bool ElementBufferTest::PrepareVAO()
1031 {
1032 	/* Shortcut for GL functionality */
1033 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1034 
1035 	/* VAO creation. */
1036 	gl.genVertexArrays(1, &m_vao);
1037 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays call failed.");
1038 
1039 	gl.bindVertexArray(m_vao);
1040 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed.");
1041 
1042 	/* Array buffer creation. */
1043 	glw::GLint array_data[3] = { 2, 1, 0 };
1044 
1045 	gl.genBuffers(1, &m_bo_array);
1046 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed.");
1047 
1048 	gl.bindBuffer(GL_ARRAY_BUFFER, m_bo_array);
1049 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
1050 
1051 	gl.bufferData(GL_ARRAY_BUFFER, sizeof(array_data), array_data, GL_STATIC_DRAW);
1052 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed.");
1053 
1054 	gl.vertexAttribIPointer(gl.getAttribLocation(m_po, "a"), 1, GL_INT, 0, NULL);
1055 	GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribIPointer call failed.");
1056 
1057 	gl.enableVertexAttribArray(0);
1058 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray call failed.");
1059 
1060 	gl.bindVertexArray(0);
1061 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed.");
1062 
1063 	/* Element buffer creation. */
1064 	glw::GLuint elements_data[3] = { 2, 1, 0 };
1065 
1066 	gl.genBuffers(1, &m_bo_elements);
1067 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed.");
1068 
1069 	gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_bo_elements);
1070 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
1071 
1072 	gl.bufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(elements_data), elements_data, GL_STATIC_DRAW);
1073 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed.");
1074 
1075 	gl.vertexArrayElementBuffer(m_vao, m_bo_elements);
1076 
1077 	if (glw::GLenum error = gl.getError())
1078 	{
1079 		m_context.getTestContext().getLog() << tcu::TestLog::Message
1080 											<< "VertexArrayElementBuffer has unexpectedly generated "
1081 											<< glu::getErrorStr(error) << "error. Test fails.\n"
1082 											<< tcu::TestLog::EndMessage;
1083 
1084 		return false;
1085 	}
1086 
1087 	return true;
1088 }
1089 
1090 /** @brief Prepare buffer object for test GLSL program transform feedback results.
1091  */
PrepareXFB()1092 void ElementBufferTest::PrepareXFB()
1093 {
1094 	/* Shortcut for GL functionality */
1095 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1096 
1097 	/* Buffer creation. */
1098 	gl.genBuffers(1, &m_bo_xfb);
1099 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed.");
1100 
1101 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_xfb);
1102 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
1103 
1104 	/* Preparing storage. */
1105 	gl.bufferStorage(GL_TRANSFORM_FEEDBACK_BUFFER, 3 * sizeof(glw::GLint), NULL, GL_MAP_READ_BIT);
1106 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferStorage call failed.");
1107 
1108 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_bo_xfb);
1109 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase call failed.");
1110 }
1111 
1112 /** @brief Draw test program, fetch transform feedback results and compare them with expected values.
1113  *
1114  *  @return True if expected results are equal to returned by XFB, false otherwise.
1115  */
DrawAndCheck()1116 bool ElementBufferTest::DrawAndCheck()
1117 {
1118 	/* Shortcut for GL functionality */
1119 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1120 
1121 	/* Setup state. */
1122 	gl.useProgram(m_po);
1123 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed.");
1124 
1125 	gl.bindVertexArray(m_vao);
1126 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed.");
1127 
1128 	gl.beginTransformFeedback(GL_POINTS);
1129 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback call failed.");
1130 
1131 	/* Draw. */
1132 	gl.drawElements(GL_POINTS, 3, GL_UNSIGNED_INT, NULL);
1133 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays call failed.");
1134 
1135 	/* State reset. */
1136 	gl.endTransformFeedback();
1137 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback call failed.");
1138 
1139 	/* Result query. */
1140 	glw::GLint* result_ptr = (glw::GLint*)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
1141 	GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer call failed.");
1142 
1143 	glw::GLint result[3] = { result_ptr[0], result_ptr[1], result_ptr[2] };
1144 
1145 	gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
1146 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer call failed.");
1147 
1148 	/* Check result and return. */
1149 	for (glw::GLint i = 0; i < 3; ++i)
1150 	{
1151 		if (i != result[i])
1152 		{
1153 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "Result vector is equal to [" << result[0]
1154 												<< ", " << result[1] << ", " << result[2]
1155 												<< "], but [0, 1, 2] was expected." << tcu::TestLog::EndMessage;
1156 
1157 			return false;
1158 		}
1159 	}
1160 
1161 	return true;
1162 }
1163 
1164 /** @brief Clean GL objects. */
Clean()1165 void ElementBufferTest::Clean()
1166 {
1167 	/* Shortcut for GL functionality */
1168 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1169 
1170 	gl.useProgram(0);
1171 
1172 	if (m_po)
1173 	{
1174 		gl.deleteProgram(m_po);
1175 
1176 		m_po = 0;
1177 	}
1178 
1179 	if (m_vao)
1180 	{
1181 		gl.deleteVertexArrays(1, &m_vao);
1182 
1183 		m_vao = 0;
1184 	}
1185 
1186 	if (m_bo_array)
1187 	{
1188 		gl.deleteBuffers(1, &m_bo_array);
1189 
1190 		m_bo_array = 0;
1191 	}
1192 
1193 	if (m_bo_elements)
1194 	{
1195 		gl.deleteBuffers(1, &m_bo_elements);
1196 
1197 		m_bo_elements = 0;
1198 	}
1199 
1200 	if (m_bo_xfb)
1201 	{
1202 		gl.deleteBuffers(1, &m_bo_xfb);
1203 
1204 		m_bo_xfb = 0;
1205 	}
1206 
1207 	while (gl.getError())
1208 		;
1209 }
1210 
1211 const glw::GLchar ElementBufferTest::s_vertex_shader[] = "#version 450\n"
1212 														 "\n"
1213 														 "in int a;"
1214 														 "out int result;\n"
1215 														 "\n"
1216 														 "void main()\n"
1217 														 "{\n"
1218 														 "    gl_Position = vec4(1.0);\n"
1219 														 "    result = a;"
1220 														 "}\n";
1221 
1222 const glw::GLchar ElementBufferTest::s_fragment_shader[] = "#version 450\n"
1223 														   "\n"
1224 														   "out vec4 color;\n"
1225 														   "\n"
1226 														   "void main()\n"
1227 														   "{\n"
1228 														   "    color = vec4(1.0);"
1229 														   "}\n";
1230 
1231 /******************************** Vertex Array Object Vertex Buffer and Buffers Test Implementation   ********************************/
1232 
1233 /** @brief Vertex Array Object Element Buffer Test constructor.
1234  *
1235  *  @param [in] context     OpenGL context.
1236  */
VertexBuffersTest(deqp::Context & context)1237 VertexBuffersTest::VertexBuffersTest(deqp::Context& context)
1238 	: deqp::TestCase(context, "vertex_arrays_vertex_buffers", "Vertex Array Object Vertex Buffer and Buffers Test")
1239 	, m_po(0)
1240 	, m_vao(0)
1241 	, m_bo_array_0(0)
1242 	, m_bo_array_1(0)
1243 	, m_bo_xfb(0)
1244 {
1245 	/* Intentionally left blank. */
1246 }
1247 
1248 /** @brief Iterate Vertex Array Object Enable Disable Attributes Test cases.
1249  *
1250  *  @return Iteration result.
1251  */
iterate()1252 tcu::TestNode::IterateResult VertexBuffersTest::iterate()
1253 {
1254 	/* Shortcut for GL functionality. */
1255 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1256 
1257 	/* Get context setup. */
1258 	bool is_at_least_gl_45 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 5)));
1259 	bool is_arb_direct_state_access = m_context.getContextInfo().isExtensionSupported("GL_ARB_direct_state_access");
1260 
1261 	if ((!is_at_least_gl_45) && (!is_arb_direct_state_access))
1262 	{
1263 		m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported");
1264 
1265 		return STOP;
1266 	}
1267 
1268 	/* Running tests. */
1269 	bool is_ok	= true;
1270 	bool is_error = false;
1271 
1272 	try
1273 	{
1274 		PrepareProgram();
1275 		is_ok &= PrepareVAO(false);
1276 		PrepareXFB();
1277 		is_ok &= DrawAndCheck();
1278 		Clean();
1279 
1280 		PrepareProgram();
1281 		is_ok &= PrepareVAO(true);
1282 		PrepareXFB();
1283 		is_ok &= DrawAndCheck();
1284 	}
1285 	catch (...)
1286 	{
1287 		is_ok	= false;
1288 		is_error = true;
1289 	}
1290 
1291 	/* Cleanup. */
1292 	Clean();
1293 
1294 	/* Errors clean up. */
1295 	while (gl.getError())
1296 		;
1297 
1298 	/* Result's setup. */
1299 	if (is_ok)
1300 	{
1301 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1302 	}
1303 	else
1304 	{
1305 		if (is_error)
1306 		{
1307 			m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
1308 		}
1309 		else
1310 		{
1311 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1312 		}
1313 	}
1314 
1315 	return STOP;
1316 }
1317 
1318 /** @brief Build test's GLSL program.
1319  *
1320  *  @note The function may throw if unexpected error has occured.
1321  */
PrepareProgram()1322 void VertexBuffersTest::PrepareProgram()
1323 {
1324 	/* Shortcut for GL functionality */
1325 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1326 
1327 	struct Shader
1328 	{
1329 		glw::GLchar const* const source;
1330 		glw::GLenum const		 type;
1331 		glw::GLuint				 id;
1332 	} shader[] = { { s_vertex_shader, GL_VERTEX_SHADER, 0 }, { s_fragment_shader, GL_FRAGMENT_SHADER, 0 } };
1333 
1334 	glw::GLuint const shader_count = DE_LENGTH_OF_ARRAY(shader);
1335 
1336 	try
1337 	{
1338 		/* Create program. */
1339 		m_po = gl.createProgram();
1340 		GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram call failed.");
1341 
1342 		/* Shader compilation. */
1343 
1344 		for (glw::GLuint i = 0; i < shader_count; ++i)
1345 		{
1346 			if (DE_NULL != shader[i].source)
1347 			{
1348 				shader[i].id = gl.createShader(shader[i].type);
1349 
1350 				GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader call failed.");
1351 
1352 				gl.attachShader(m_po, shader[i].id);
1353 
1354 				GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader call failed.");
1355 
1356 				gl.shaderSource(shader[i].id, 1, &(shader[i].source), NULL);
1357 
1358 				GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource call failed.");
1359 
1360 				gl.compileShader(shader[i].id);
1361 
1362 				GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader call failed.");
1363 
1364 				glw::GLint status = GL_FALSE;
1365 
1366 				gl.getShaderiv(shader[i].id, GL_COMPILE_STATUS, &status);
1367 				GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv call failed.");
1368 
1369 				if (GL_FALSE == status)
1370 				{
1371 					glw::GLint log_size = 0;
1372 					gl.getShaderiv(shader[i].id, GL_INFO_LOG_LENGTH, &log_size);
1373 					GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv call failed.");
1374 
1375 					glw::GLchar* log_text = new glw::GLchar[log_size];
1376 
1377 					gl.getShaderInfoLog(shader[i].id, log_size, NULL, &log_text[0]);
1378 
1379 					m_context.getTestContext().getLog() << tcu::TestLog::Message << "Shader compilation has failed.\n"
1380 														<< "Shader type: " << glu::getShaderTypeStr(shader[i].type)
1381 														<< "\n"
1382 														<< "Shader compilation error log:\n"
1383 														<< log_text << "\n"
1384 														<< "Shader source code:\n"
1385 														<< shader[i].source << "\n"
1386 														<< tcu::TestLog::EndMessage;
1387 
1388 					delete[] log_text;
1389 
1390 					GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderInfoLog call failed.");
1391 
1392 					throw 0;
1393 				}
1394 			}
1395 		}
1396 
1397 		/* Transform Feedback setup. */
1398 		static const glw::GLchar* xfb_varying = "result";
1399 
1400 		gl.transformFeedbackVaryings(m_po, 1, &xfb_varying, GL_INTERLEAVED_ATTRIBS);
1401 		GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings call failed.");
1402 
1403 		/* Link. */
1404 		gl.linkProgram(m_po);
1405 
1406 		GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings call failed.");
1407 
1408 		glw::GLint status = GL_FALSE;
1409 
1410 		gl.getProgramiv(m_po, GL_LINK_STATUS, &status);
1411 
1412 		if (GL_TRUE == status)
1413 		{
1414 			for (glw::GLuint i = 0; i < shader_count; ++i)
1415 			{
1416 				if (shader[i].id)
1417 				{
1418 					gl.detachShader(m_po, shader[i].id);
1419 
1420 					GLU_EXPECT_NO_ERROR(gl.getError(), "glDetachShader call failed.");
1421 				}
1422 			}
1423 		}
1424 		else
1425 		{
1426 			glw::GLint log_size = 0;
1427 
1428 			gl.getProgramiv(m_po, GL_INFO_LOG_LENGTH, &log_size);
1429 
1430 			GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv call failed.");
1431 
1432 			glw::GLchar* log_text = new glw::GLchar[log_size];
1433 
1434 			gl.getProgramInfoLog(m_po, log_size, NULL, &log_text[0]);
1435 
1436 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "Program linkage has failed due to:\n"
1437 												<< log_text << "\n"
1438 												<< tcu::TestLog::EndMessage;
1439 
1440 			delete[] log_text;
1441 
1442 			GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramInfoLog call failed.");
1443 
1444 			throw 0;
1445 		}
1446 	}
1447 	catch (...)
1448 	{
1449 		if (m_po)
1450 		{
1451 			gl.deleteProgram(m_po);
1452 
1453 			m_po = 0;
1454 		}
1455 	}
1456 
1457 	for (glw::GLuint i = 0; i < shader_count; ++i)
1458 	{
1459 		if (0 != shader[i].id)
1460 		{
1461 			gl.deleteShader(shader[i].id);
1462 
1463 			shader[i].id = 0;
1464 		}
1465 	}
1466 
1467 	if (0 == m_po)
1468 	{
1469 		throw 0;
1470 	}
1471 }
1472 
1473 /** @brief Prepare vertex array object for the test of gl.vertexArrayVertexBuffer* functions.
1474  *
1475  *  @param [in] use_multiple_buffers_function    Use gl.vertexArrayVertexBuffers instead of gl.vertexArrayVertexBuffer.
1476  *
1477  *  @return True if functions gl.vertexArrayVertexBuffer* do not generate any error.
1478  */
PrepareVAO(bool use_multiple_buffers_function)1479 bool VertexBuffersTest::PrepareVAO(bool use_multiple_buffers_function)
1480 {
1481 	/* Shortcut for GL functionality */
1482 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1483 
1484 	/* VAO creation. */
1485 	gl.genVertexArrays(1, &m_vao);
1486 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays call failed.");
1487 
1488 	gl.bindVertexArray(m_vao);
1489 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed.");
1490 
1491 	/* Array buffer 0 creation. */
1492 	glw::GLint array_data_0[4] = { 0, 2, 1, 3 };
1493 
1494 	gl.genBuffers(1, &m_bo_array_0);
1495 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed.");
1496 
1497 	gl.bindBuffer(GL_ARRAY_BUFFER, m_bo_array_0);
1498 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
1499 
1500 	gl.bufferData(GL_ARRAY_BUFFER, sizeof(array_data_0), array_data_0, GL_STATIC_DRAW);
1501 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed.");
1502 
1503 	gl.vertexAttribBinding(gl.getAttribLocation(m_po, "a_0"), 0);
1504 
1505 	gl.vertexAttribBinding(gl.getAttribLocation(m_po, "a_1"), 1);
1506 
1507 	gl.vertexAttribIFormat(gl.getAttribLocation(m_po, "a_0"), 1, GL_INT, 0);
1508 
1509 	gl.vertexAttribIFormat(gl.getAttribLocation(m_po, "a_1"), 1, GL_INT, 0);
1510 
1511 	if (use_multiple_buffers_function)
1512 	{
1513 		const glw::GLuint		   buffers[2] = { m_bo_array_0, m_bo_array_0 };
1514 		static const glw::GLintptr offsets[2] = { 0, sizeof(glw::GLint) };
1515 		static const glw::GLsizei  strides[2] = { sizeof(glw::GLint) * 2, sizeof(glw::GLint) * 2 };
1516 
1517 		gl.vertexArrayVertexBuffers(m_vao, 0, 2, buffers, offsets, strides);
1518 
1519 		if (glw::GLenum error = gl.getError())
1520 		{
1521 			m_context.getTestContext().getLog() << tcu::TestLog::Message
1522 												<< "VertexArrayVertexBuffers has unexpectedly generated "
1523 												<< glu::getErrorStr(error) << "error. Test fails.\n"
1524 												<< tcu::TestLog::EndMessage;
1525 
1526 			return false;
1527 		}
1528 	}
1529 	else
1530 	{
1531 		gl.vertexArrayVertexBuffer(m_vao, 0, m_bo_array_0, (glw::GLintptr)NULL, sizeof(glw::GLint) * 2);
1532 
1533 		if (glw::GLenum error = gl.getError())
1534 		{
1535 			m_context.getTestContext().getLog() << tcu::TestLog::Message
1536 												<< "VertexArrayVertexBuffer has unexpectedly generated "
1537 												<< glu::getErrorStr(error) << "error. Test fails.\n"
1538 												<< tcu::TestLog::EndMessage;
1539 
1540 			return false;
1541 		}
1542 
1543 		gl.vertexArrayVertexBuffer(m_vao, 1, m_bo_array_0, sizeof(glw::GLint),
1544 								   sizeof(glw::GLint) * 2);
1545 
1546 		if (glw::GLenum error = gl.getError())
1547 		{
1548 			m_context.getTestContext().getLog() << tcu::TestLog::Message
1549 												<< "VertexArrayVertexBuffer has unexpectedly generated "
1550 												<< glu::getErrorStr(error) << "error. Test fails.\n"
1551 												<< tcu::TestLog::EndMessage;
1552 
1553 			return false;
1554 		}
1555 	}
1556 
1557 	gl.enableVertexAttribArray(0);
1558 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray call failed.");
1559 
1560 	gl.enableVertexAttribArray(1);
1561 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray call failed.");
1562 
1563 	/* Array buffer 1 creation. */
1564 	glw::GLint array_data_1[2] = { 4, 5 };
1565 
1566 	gl.genBuffers(1, &m_bo_array_1);
1567 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed.");
1568 
1569 	gl.bindBuffer(GL_ARRAY_BUFFER, m_bo_array_1);
1570 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
1571 
1572 	gl.bufferData(GL_ARRAY_BUFFER, sizeof(array_data_1), array_data_1, GL_STATIC_DRAW);
1573 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed.");
1574 
1575 	gl.vertexAttribBinding(gl.getAttribLocation(m_po, "a_2"), 2);
1576 	GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribBinding call failed.");
1577 
1578 	gl.vertexAttribIFormat(gl.getAttribLocation(m_po, "a_2"), 1, GL_INT, 0);
1579 	GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribIFormat call failed.");
1580 
1581 	if (use_multiple_buffers_function)
1582 	{
1583 		glw::GLintptr offset = (glw::GLintptr)NULL;
1584 		glw::GLsizei  stride = sizeof(glw::GLint);
1585 
1586 		gl.vertexArrayVertexBuffers(m_vao, 2, 1, &m_bo_array_1, &offset, &stride);
1587 
1588 		if (glw::GLenum error = gl.getError())
1589 		{
1590 			m_context.getTestContext().getLog() << tcu::TestLog::Message
1591 												<< "VertexArrayVertexBuffers has unexpectedly generated "
1592 												<< glu::getErrorStr(error) << "error. Test fails.\n"
1593 												<< tcu::TestLog::EndMessage;
1594 
1595 			return false;
1596 		}
1597 	}
1598 	else
1599 	{
1600 		gl.vertexArrayVertexBuffer(m_vao, 2, m_bo_array_1, (glw::GLintptr)NULL, sizeof(glw::GLint));
1601 
1602 		if (glw::GLenum error = gl.getError())
1603 		{
1604 			m_context.getTestContext().getLog() << tcu::TestLog::Message
1605 												<< "VertexArrayVertexBuffer has unexpectedly generated "
1606 												<< glu::getErrorStr(error) << "error. Test fails.\n"
1607 												<< tcu::TestLog::EndMessage;
1608 
1609 			return false;
1610 		}
1611 	}
1612 
1613 	gl.enableVertexAttribArray(2);
1614 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray call failed.");
1615 
1616 	gl.bindVertexArray(0);
1617 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed.");
1618 
1619 	return true;
1620 }
1621 
1622 /** @brief Prepare buffer object for test GLSL program transform feedback results.
1623  */
PrepareXFB()1624 void VertexBuffersTest::PrepareXFB()
1625 {
1626 	/* Shortcut for GL functionality */
1627 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1628 
1629 	/* Buffer creation. */
1630 	gl.genBuffers(1, &m_bo_xfb);
1631 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed.");
1632 
1633 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_xfb);
1634 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
1635 
1636 	/* Preparing storage. */
1637 	gl.bufferStorage(GL_TRANSFORM_FEEDBACK_BUFFER, 2 * sizeof(glw::GLint), NULL, GL_MAP_READ_BIT);
1638 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferStorage call failed.");
1639 
1640 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_bo_xfb);
1641 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase call failed.");
1642 }
1643 
1644 /** @brief Draw test program, fetch transform feedback results and compare them with expected values.
1645  *
1646  *  @return True if expected results are equal to returned by XFB, false otherwise.
1647  */
DrawAndCheck()1648 bool VertexBuffersTest::DrawAndCheck()
1649 {
1650 	/* Shortcut for GL functionality */
1651 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1652 
1653 	/* Setup state. */
1654 	gl.useProgram(m_po);
1655 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed.");
1656 
1657 	gl.bindVertexArray(m_vao);
1658 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed.");
1659 
1660 	gl.beginTransformFeedback(GL_POINTS);
1661 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback call failed.");
1662 
1663 	/* Draw. */
1664 	gl.drawArrays(GL_POINTS, 0, 2);
1665 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays call failed.");
1666 
1667 	/* State reset. */
1668 	gl.endTransformFeedback();
1669 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback call failed.");
1670 
1671 	/* Result query. */
1672 	glw::GLint* result_ptr = (glw::GLint*)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
1673 	GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer call failed.");
1674 
1675 	glw::GLint result[2] = { result_ptr[0], result_ptr[1] };
1676 
1677 	gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
1678 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer call failed.");
1679 
1680 	static const glw::GLint reference[2] = { 0 + 2 + 4, 1 + 3 + 5 };
1681 
1682 	/* Check result and return. */
1683 	for (glw::GLint i = 0; i < 2; ++i)
1684 	{
1685 		if (reference[i] != result[i])
1686 		{
1687 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "Result vector is equal to [" << result[0]
1688 												<< ", " << result[1] << "], but [" << reference[0] << ", "
1689 												<< reference[1] << "] was expected." << tcu::TestLog::EndMessage;
1690 
1691 			return false;
1692 		}
1693 	}
1694 
1695 	return true;
1696 }
1697 
1698 /** @brief Clean GL objects. */
Clean()1699 void VertexBuffersTest::Clean()
1700 {
1701 	/* Shortcut for GL functionality */
1702 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1703 
1704 	gl.useProgram(0);
1705 
1706 	if (m_po)
1707 	{
1708 		gl.deleteProgram(m_po);
1709 
1710 		m_po = 0;
1711 	}
1712 
1713 	if (m_vao)
1714 	{
1715 		gl.deleteVertexArrays(1, &m_vao);
1716 
1717 		m_vao = 0;
1718 	}
1719 
1720 	if (m_bo_array_0)
1721 	{
1722 		gl.deleteBuffers(1, &m_bo_array_0);
1723 
1724 		m_bo_array_0 = 0;
1725 	}
1726 
1727 	if (m_bo_array_1)
1728 	{
1729 		gl.deleteBuffers(1, &m_bo_array_1);
1730 
1731 		m_bo_array_1 = 0;
1732 	}
1733 
1734 	if (m_bo_xfb)
1735 	{
1736 		gl.deleteBuffers(1, &m_bo_xfb);
1737 
1738 		m_bo_xfb = 0;
1739 	}
1740 
1741 	while (gl.getError())
1742 		;
1743 }
1744 
1745 const glw::GLchar VertexBuffersTest::s_vertex_shader[] = "#version 450\n"
1746 														 "\n"
1747 														 "in  int a_0;"
1748 														 "in  int a_1;"
1749 														 "in  int a_2;"
1750 														 "\n"
1751 														 "out int result;\n"
1752 														 "\n"
1753 														 "void main()\n"
1754 														 "{\n"
1755 														 "    gl_Position = vec4(1.0);\n"
1756 														 "    result = a_0 + a_1 + a_2;"
1757 														 "}\n";
1758 
1759 const glw::GLchar VertexBuffersTest::s_fragment_shader[] = "#version 450\n"
1760 														   "\n"
1761 														   "out vec4 color;\n"
1762 														   "\n"
1763 														   "void main()\n"
1764 														   "{\n"
1765 														   "    color = vec4(1.0);"
1766 														   "}\n";
1767 
1768 /******************************** Vertex Array Object Attribute Format Test Implementation   ********************************/
1769 
1770 /** @brief Vertex Array Object Element Buffer Test constructor.
1771  *
1772  *  @param [in] context     OpenGL context.
1773  */
AttributeFormatTest(deqp::Context & context)1774 AttributeFormatTest::AttributeFormatTest(deqp::Context& context)
1775 	: deqp::TestCase(context, "vertex_arrays_attribute_format", "Vertex Array Object Attribute Format Test")
1776 	, m_po(0)
1777 	, m_vao(0)
1778 	, m_bo_array(0)
1779 	, m_bo_xfb(0)
1780 {
1781 	/* Intentionally left blank. */
1782 }
1783 
1784 /** @brief Iterate Vertex Array Object Enable Disable Attributes Test cases.
1785  *
1786  *  @return Iteration result.
1787  */
iterate()1788 tcu::TestNode::IterateResult AttributeFormatTest::iterate()
1789 {
1790 	/* Shortcut for GL functionality. */
1791 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1792 
1793 	/* Get context setup. */
1794 	bool is_at_least_gl_45 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 5)));
1795 	bool is_arb_direct_state_access = m_context.getContextInfo().isExtensionSupported("GL_ARB_direct_state_access");
1796 
1797 	if ((!is_at_least_gl_45) && (!is_arb_direct_state_access))
1798 	{
1799 		m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported");
1800 
1801 		return STOP;
1802 	}
1803 
1804 	/* Running tests. */
1805 	bool is_ok	= true;
1806 	bool is_error = false;
1807 
1808 	try
1809 	{
1810 		PrepareXFB();
1811 
1812 		/* Test floating function. */
1813 		for (glw::GLuint i = 1; i <= 4 /* max size */; ++i)
1814 		{
1815 			PrepareProgram(i, ATTRIBUTE_FORMAT_FUNCTION_FLOAT);
1816 
1817 			is_ok &= PrepareVAO<glw::GLfloat>(i, GL_FLOAT, false, ATTRIBUTE_FORMAT_FUNCTION_FLOAT);
1818 			is_ok &= DrawAndCheck<glw::GLfloat>(i, false);
1819 
1820 			CleanVAO();
1821 
1822 			is_ok &= PrepareVAO<glw::GLbyte>(i, GL_BYTE, false, ATTRIBUTE_FORMAT_FUNCTION_FLOAT);
1823 			is_ok &= DrawAndCheck<glw::GLfloat>(i, false);
1824 
1825 			CleanVAO();
1826 
1827 			is_ok &= PrepareVAO<glw::GLbyte>(i, GL_BYTE, true, ATTRIBUTE_FORMAT_FUNCTION_FLOAT);
1828 			is_ok &= DrawAndCheck<glw::GLfloat>(i, true);
1829 
1830 			CleanVAO();
1831 
1832 			is_ok &= PrepareVAO<glw::GLubyte>(i, GL_UNSIGNED_BYTE, false, ATTRIBUTE_FORMAT_FUNCTION_FLOAT);
1833 			is_ok &= DrawAndCheck<glw::GLfloat>(i, false);
1834 
1835 			CleanVAO();
1836 
1837 			is_ok &= PrepareVAO<glw::GLshort>(i, GL_SHORT, false, ATTRIBUTE_FORMAT_FUNCTION_FLOAT);
1838 			is_ok &= DrawAndCheck<glw::GLfloat>(i, false);
1839 
1840 			CleanVAO();
1841 
1842 			is_ok &= PrepareVAO<glw::GLushort>(i, GL_UNSIGNED_SHORT, false, ATTRIBUTE_FORMAT_FUNCTION_FLOAT);
1843 			is_ok &= DrawAndCheck<glw::GLfloat>(i, false);
1844 
1845 			CleanVAO();
1846 
1847 			is_ok &= PrepareVAO<glw::GLint>(i, GL_INT, false, ATTRIBUTE_FORMAT_FUNCTION_FLOAT);
1848 			is_ok &= DrawAndCheck<glw::GLfloat>(i, false);
1849 
1850 			CleanVAO();
1851 
1852 			is_ok &= PrepareVAO<glw::GLuint>(i, GL_UNSIGNED_INT, false, ATTRIBUTE_FORMAT_FUNCTION_FLOAT);
1853 			is_ok &= DrawAndCheck<glw::GLfloat>(i, false);
1854 
1855 			CleanVAO();
1856 
1857 			CleanProgram();
1858 		}
1859 
1860 		for (glw::GLuint i = 1; i <= 2 /* max size */; ++i)
1861 		{
1862 			PrepareProgram(i, ATTRIBUTE_FORMAT_FUNCTION_DOUBLE);
1863 
1864 			is_ok &= PrepareVAO<glw::GLdouble>(i, GL_DOUBLE, false, ATTRIBUTE_FORMAT_FUNCTION_DOUBLE);
1865 			is_ok &= DrawAndCheck<glw::GLdouble>(i, false);
1866 
1867 			CleanProgram();
1868 			CleanVAO();
1869 		}
1870 
1871 		for (glw::GLuint i = 1; i <= 4 /* max size */; ++i)
1872 		{
1873 			PrepareProgram(i, ATTRIBUTE_FORMAT_FUNCTION_INTEGER);
1874 
1875 			is_ok &= PrepareVAO<glw::GLbyte>(i, GL_BYTE, false, ATTRIBUTE_FORMAT_FUNCTION_INTEGER);
1876 			is_ok &= DrawAndCheck<glw::GLint>(i, false);
1877 
1878 			CleanVAO();
1879 
1880 			is_ok &= PrepareVAO<glw::GLubyte>(i, GL_UNSIGNED_BYTE, false, ATTRIBUTE_FORMAT_FUNCTION_INTEGER);
1881 			is_ok &= DrawAndCheck<glw::GLint>(i, false);
1882 
1883 			CleanVAO();
1884 
1885 			is_ok &= PrepareVAO<glw::GLshort>(i, GL_SHORT, false, ATTRIBUTE_FORMAT_FUNCTION_INTEGER);
1886 			is_ok &= DrawAndCheck<glw::GLint>(i, false);
1887 
1888 			CleanVAO();
1889 
1890 			is_ok &= PrepareVAO<glw::GLushort>(i, GL_UNSIGNED_SHORT, false, ATTRIBUTE_FORMAT_FUNCTION_INTEGER);
1891 			is_ok &= DrawAndCheck<glw::GLint>(i, false);
1892 
1893 			CleanVAO();
1894 
1895 			is_ok &= PrepareVAO<glw::GLint>(i, GL_INT, false, ATTRIBUTE_FORMAT_FUNCTION_INTEGER);
1896 			is_ok &= DrawAndCheck<glw::GLint>(i, false);
1897 
1898 			CleanVAO();
1899 
1900 			is_ok &= PrepareVAO<glw::GLuint>(i, GL_UNSIGNED_INT, false, ATTRIBUTE_FORMAT_FUNCTION_INTEGER);
1901 			is_ok &= DrawAndCheck<glw::GLint>(i, false);
1902 
1903 			CleanVAO();
1904 
1905 			CleanProgram();
1906 		}
1907 	}
1908 	catch (...)
1909 	{
1910 		is_ok	= false;
1911 		is_error = true;
1912 	}
1913 
1914 	/* Cleanup. */
1915 	CleanProgram();
1916 	CleanVAO();
1917 	CleanXFB();
1918 
1919 	/* Errors clean up. */
1920 	while (gl.getError())
1921 		;
1922 
1923 	/* Result's setup. */
1924 	if (is_ok)
1925 	{
1926 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1927 	}
1928 	else
1929 	{
1930 		if (is_error)
1931 		{
1932 			m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
1933 		}
1934 		else
1935 		{
1936 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1937 		}
1938 	}
1939 
1940 	return STOP;
1941 }
1942 
1943 /** @brief Build test's GLSL program.
1944  *
1945  *  @note The function may throw if unexpected error has occured.
1946  */
PrepareProgram(glw::GLint size,AtributeFormatFunctionType function_selector)1947 void AttributeFormatTest::PrepareProgram(glw::GLint size, AtributeFormatFunctionType function_selector)
1948 {
1949 	/* Shortcut for GL functionality */
1950 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1951 
1952 	struct Shader
1953 	{
1954 		glw::GLchar const* source[3];
1955 		glw::GLuint const  count;
1956 		glw::GLenum const  type;
1957 		glw::GLuint		   id;
1958 	} shader[] = { { { s_vertex_shader_head, s_vertex_shader_declaration[function_selector][size - 1],
1959 					   s_vertex_shader_body },
1960 					 3,
1961 					 GL_VERTEX_SHADER,
1962 					 0 },
1963 				   { { s_fragment_shader, DE_NULL, DE_NULL }, 1, GL_FRAGMENT_SHADER, 0 } };
1964 
1965 	glw::GLuint const shader_count = DE_LENGTH_OF_ARRAY(shader);
1966 
1967 	try
1968 	{
1969 		/* Create program. */
1970 		m_po = gl.createProgram();
1971 		GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram call failed.");
1972 
1973 		/* Shader compilation. */
1974 
1975 		for (glw::GLuint i = 0; i < shader_count; ++i)
1976 		{
1977 			{
1978 				shader[i].id = gl.createShader(shader[i].type);
1979 
1980 				GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader call failed.");
1981 
1982 				gl.attachShader(m_po, shader[i].id);
1983 
1984 				GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader call failed.");
1985 
1986 				gl.shaderSource(shader[i].id, shader[i].count, shader[i].source, NULL);
1987 
1988 				GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource call failed.");
1989 
1990 				gl.compileShader(shader[i].id);
1991 
1992 				GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader call failed.");
1993 
1994 				glw::GLint status = GL_FALSE;
1995 
1996 				gl.getShaderiv(shader[i].id, GL_COMPILE_STATUS, &status);
1997 				GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv call failed.");
1998 
1999 				if (GL_FALSE == status)
2000 				{
2001 					glw::GLint log_size = 0;
2002 					gl.getShaderiv(shader[i].id, GL_INFO_LOG_LENGTH, &log_size);
2003 					GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv call failed.");
2004 
2005 					glw::GLchar* log_text = new glw::GLchar[log_size];
2006 
2007 					gl.getShaderInfoLog(shader[i].id, log_size, NULL, &log_text[0]);
2008 
2009 					m_context.getTestContext().getLog() << tcu::TestLog::Message << "Shader compilation has failed.\n"
2010 														<< "Shader type: " << glu::getShaderTypeStr(shader[i].type)
2011 														<< "\n"
2012 														<< "Shader compilation error log:\n"
2013 														<< log_text << "\n"
2014 														<< "Shader source code:\n"
2015 														<< shader[i].source << "\n"
2016 														<< tcu::TestLog::EndMessage;
2017 
2018 					delete[] log_text;
2019 
2020 					GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderInfoLog call failed.");
2021 
2022 					throw 0;
2023 				}
2024 			}
2025 		}
2026 
2027 		/* Transform Feedback setup. */
2028 		static const glw::GLchar* xfb_varying = "result";
2029 
2030 		gl.transformFeedbackVaryings(m_po, 1, &xfb_varying, GL_INTERLEAVED_ATTRIBS);
2031 		GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings call failed.");
2032 
2033 		/* Link. */
2034 		gl.linkProgram(m_po);
2035 
2036 		GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings call failed.");
2037 
2038 		glw::GLint status = GL_FALSE;
2039 
2040 		gl.getProgramiv(m_po, GL_LINK_STATUS, &status);
2041 
2042 		if (GL_TRUE == status)
2043 		{
2044 			for (glw::GLuint i = 0; i < shader_count; ++i)
2045 			{
2046 				if (shader[i].id)
2047 				{
2048 					gl.detachShader(m_po, shader[i].id);
2049 
2050 					GLU_EXPECT_NO_ERROR(gl.getError(), "glDetachShader call failed.");
2051 				}
2052 			}
2053 		}
2054 		else
2055 		{
2056 			glw::GLint log_size = 0;
2057 
2058 			gl.getProgramiv(m_po, GL_INFO_LOG_LENGTH, &log_size);
2059 
2060 			GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv call failed.");
2061 
2062 			glw::GLchar* log_text = new glw::GLchar[log_size];
2063 
2064 			gl.getProgramInfoLog(m_po, log_size, NULL, &log_text[0]);
2065 
2066 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "Program linkage has failed due to:\n"
2067 												<< log_text << "\n"
2068 												<< tcu::TestLog::EndMessage;
2069 
2070 			delete[] log_text;
2071 
2072 			GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramInfoLog call failed.");
2073 
2074 			throw 0;
2075 		}
2076 	}
2077 	catch (...)
2078 	{
2079 		if (m_po)
2080 		{
2081 			gl.deleteProgram(m_po);
2082 
2083 			m_po = 0;
2084 		}
2085 	}
2086 
2087 	for (glw::GLuint i = 0; i < shader_count; ++i)
2088 	{
2089 		if (0 != shader[i].id)
2090 		{
2091 			gl.deleteShader(shader[i].id);
2092 
2093 			shader[i].id = 0;
2094 		}
2095 	}
2096 
2097 	if (0 == m_po)
2098 	{
2099 		throw 0;
2100 	}
2101 }
2102 
2103 template <>
NormalizationScaleFactor()2104 glw::GLdouble AttributeFormatTest::NormalizationScaleFactor<glw::GLuint>()
2105 {
2106 	return std::pow(2.0, (glw::GLdouble)(CHAR_BIT * sizeof(glw::GLuint) - 4 /* 1.0 / 16.0 */));
2107 }
2108 
2109 template <>
NormalizationScaleFactor()2110 glw::GLdouble AttributeFormatTest::NormalizationScaleFactor<glw::GLushort>()
2111 {
2112 	return std::pow(2.0, (glw::GLdouble)(CHAR_BIT * sizeof(glw::GLushort) - 4 /* 1.0 / 16.0 */));
2113 }
2114 
2115 template <>
NormalizationScaleFactor()2116 glw::GLdouble AttributeFormatTest::NormalizationScaleFactor<glw::GLubyte>()
2117 {
2118 	return std::pow(2.0, (glw::GLdouble)(CHAR_BIT * sizeof(glw::GLubyte) - 4 /* 1.0 / 16.0 */));
2119 }
2120 
2121 template <>
NormalizationScaleFactor()2122 glw::GLdouble AttributeFormatTest::NormalizationScaleFactor<glw::GLint>()
2123 {
2124 	return std::pow(2.0, (glw::GLdouble)(CHAR_BIT * sizeof(glw::GLint) - 4 /* 1.0 / 16.0 */ - 1 /* sign bit */));
2125 }
2126 
2127 template <>
NormalizationScaleFactor()2128 glw::GLdouble AttributeFormatTest::NormalizationScaleFactor<glw::GLshort>()
2129 {
2130 	return std::pow(2.0, (glw::GLdouble)(CHAR_BIT * sizeof(glw::GLshort) - 4 /* 1.0 / 16.0 */ - 1 /* sign bit */));
2131 }
2132 
2133 template <>
NormalizationScaleFactor()2134 glw::GLdouble AttributeFormatTest::NormalizationScaleFactor<glw::GLbyte>()
2135 {
2136 	return std::pow(2.0, (glw::GLdouble)(CHAR_BIT * sizeof(glw::GLbyte) - 4 /* 1.0 / 16.0 */ - 1 /* sign bit */));
2137 }
2138 
2139 template <typename T>
NormalizationScaleFactor()2140 glw::GLdouble AttributeFormatTest::NormalizationScaleFactor()
2141 {
2142 	return 1.0; /* Rest of the types cannot be normalized. */
2143 }
2144 
2145 /** @brief Prepare vertex array object for the test of VertexArrayAttrib*Format function.
2146  *
2147  *  @param [in] size                Size passed to VertexArrayAttrib*Format.
2148  *  @param [in] type_gl_name        Type passed to VertexArrayAttrib*Format.
2149  *  @param [in] function_selector   Selects one of VertexArrayAttrib*Format functions.
2150  *
2151  *  @return True if function VertexArrayAttrib*Format does not generate any error.
2152  */
2153 template <typename T>
PrepareVAO(glw::GLint size,glw::GLenum type_gl_name,bool normalized,AtributeFormatFunctionType function_selector)2154 bool AttributeFormatTest::PrepareVAO(glw::GLint size, glw::GLenum type_gl_name, bool normalized,
2155 									 AtributeFormatFunctionType function_selector)
2156 {
2157 	/* Shortcut for GL functionality */
2158 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2159 
2160 	/* VAO creation. */
2161 	gl.genVertexArrays(1, &m_vao);
2162 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays call failed.");
2163 
2164 	gl.bindVertexArray(m_vao);
2165 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed.");
2166 
2167 	/* Array buffer 0 creation. */
2168 
2169 	const glw::GLdouble scale = normalized ? NormalizationScaleFactor<T>() : 1.0;
2170 
2171 	const T array_data[16] = { (T)(0.0 * scale),  (T)(1.0 * scale),  (T)(2.0 * scale),  (T)(3.0 * scale),
2172 							   (T)(4.0 * scale),  (T)(5.0 * scale),  (T)(6.0 * scale),  (T)(7.0 * scale),
2173 							   (T)(8.0 * scale),  (T)(9.0 * scale),  (T)(10.0 * scale), (T)(11.0 * scale),
2174 							   (T)(12.0 * scale), (T)(13.0 * scale), (T)(14.0 * scale), (T)(15.0 * scale) };
2175 
2176 	gl.genBuffers(1, &m_bo_array);
2177 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed.");
2178 
2179 	gl.bindBuffer(GL_ARRAY_BUFFER, m_bo_array);
2180 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
2181 
2182 	gl.bufferData(GL_ARRAY_BUFFER, sizeof(array_data), array_data, GL_STATIC_DRAW);
2183 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed.");
2184 
2185 	/* Attribute setup. */
2186 	gl.vertexAttribBinding(gl.getAttribLocation(m_po, "a_0"), 0);
2187 	GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribBinding call failed.");
2188 
2189 	gl.vertexAttribBinding(gl.getAttribLocation(m_po, "a_1"), 1);
2190 	GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribBinding call failed.");
2191 
2192 	/* Tested attribute format setup. */
2193 	switch (function_selector)
2194 	{
2195 	case ATTRIBUTE_FORMAT_FUNCTION_FLOAT:
2196 		gl.vertexArrayAttribFormat(m_vao, gl.getAttribLocation(m_po, "a_0"), size, type_gl_name, normalized, 0);
2197 		gl.vertexArrayAttribFormat(m_vao, gl.getAttribLocation(m_po, "a_1"), size, type_gl_name, normalized, 0);
2198 		break;
2199 
2200 	case ATTRIBUTE_FORMAT_FUNCTION_DOUBLE:
2201 		gl.vertexArrayAttribLFormat(m_vao, gl.getAttribLocation(m_po, "a_0"), size, type_gl_name, 0);
2202 		gl.vertexArrayAttribLFormat(m_vao, gl.getAttribLocation(m_po, "a_1"), size, type_gl_name, 0);
2203 		break;
2204 
2205 	case ATTRIBUTE_FORMAT_FUNCTION_INTEGER:
2206 		gl.vertexArrayAttribIFormat(m_vao, gl.getAttribLocation(m_po, "a_0"), size, type_gl_name, 0);
2207 		gl.vertexArrayAttribIFormat(m_vao, gl.getAttribLocation(m_po, "a_1"), size, type_gl_name, 0);
2208 		break;
2209 	default:
2210 		throw 0;
2211 	}
2212 
2213 	if (glw::GLenum error = gl.getError())
2214 	{
2215 		m_context.getTestContext().getLog()
2216 			<< tcu::TestLog::Message
2217 			<< ((ATTRIBUTE_FORMAT_FUNCTION_FLOAT == function_selector) ?
2218 					"VertexArrayAttribFormat" :
2219 					((ATTRIBUTE_FORMAT_FUNCTION_DOUBLE == function_selector) ?
2220 						 "VertexArrayAttribLFormat" :
2221 						 ((ATTRIBUTE_FORMAT_FUNCTION_INTEGER == function_selector) ? "VertexArrayAttribIFormat" :
2222 																					 "VertexArrayAttrib?Format")))
2223 			<< " has unexpectedly generated " << glu::getErrorStr(error) << "error for test with size = " << size
2224 			<< ", type = " << glu::getTypeStr(type_gl_name)
2225 			<< ((ATTRIBUTE_FORMAT_FUNCTION_FLOAT == function_selector) ?
2226 					(normalized ? ", which was normalized." : ", which was not normalized.") :
2227 					".")
2228 			<< " Test fails.\n"
2229 			<< tcu::TestLog::EndMessage;
2230 
2231 		return false;
2232 	}
2233 
2234 	gl.bindVertexBuffer(0, m_bo_array, 0, static_cast<glw::GLsizei>(sizeof(T) * size * 2));
2235 	gl.bindVertexBuffer(1, m_bo_array, size * sizeof(T),
2236 						static_cast<glw::GLsizei>(sizeof(T) * size * 2));
2237 
2238 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed.");
2239 
2240 	gl.enableVertexAttribArray(0);
2241 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray call failed.");
2242 
2243 	gl.enableVertexAttribArray(1);
2244 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray call failed.");
2245 
2246 	gl.bindVertexArray(0);
2247 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed.");
2248 
2249 	return true;
2250 }
2251 
2252 /** @brief Prepare buffer object for test GLSL program transform feedback results.
2253  */
PrepareXFB()2254 void AttributeFormatTest::PrepareXFB()
2255 {
2256 	/* Shortcut for GL functionality */
2257 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2258 
2259 	/* Buffer creation. */
2260 	gl.genBuffers(1, &m_bo_xfb);
2261 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed.");
2262 
2263 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_xfb);
2264 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
2265 
2266 	/* Calculating maximum size. */
2267 	glw::GLsizei size = static_cast<glw::GLsizei>(
2268 		de::max(sizeof(glw::GLubyte),
2269 				de::max(sizeof(glw::GLbyte),
2270 						de::max(sizeof(glw::GLushort),
2271 								de::max(sizeof(glw::GLshort),
2272 										de::max(sizeof(glw::GLhalf),
2273 												de::max(sizeof(glw::GLint),
2274 														de::max(sizeof(glw::GLuint),
2275 																de::max(sizeof(glw::GLfixed),
2276 																		de::max(sizeof(glw::GLfloat),
2277 																				sizeof(glw::GLdouble)))))))))) *
2278 		4 /* maximum number of components */);
2279 
2280 	/* Preparing storage. */
2281 	gl.bufferStorage(GL_TRANSFORM_FEEDBACK_BUFFER, size, NULL, GL_MAP_READ_BIT);
2282 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferStorage call failed.");
2283 
2284 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_bo_xfb);
2285 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase call failed.");
2286 }
2287 
2288 template <>
compare(glw::GLfloat a,glw::GLfloat b)2289 bool AttributeFormatTest::compare<glw::GLfloat>(glw::GLfloat a, glw::GLfloat b)
2290 {
2291 	if (de::abs(a - b) < 0.03125)
2292 	{
2293 		return true;
2294 	}
2295 
2296 	return false;
2297 }
2298 
2299 template <>
compare(glw::GLdouble a,glw::GLdouble b)2300 bool AttributeFormatTest::compare<glw::GLdouble>(glw::GLdouble a, glw::GLdouble b)
2301 {
2302 	if (de::abs(a - b) < 0.03125)
2303 	{
2304 		return true;
2305 	}
2306 
2307 	return false;
2308 }
2309 
2310 template <typename T>
compare(T a,T b)2311 bool AttributeFormatTest::compare(T a, T b)
2312 {
2313 	return (a == b);
2314 }
2315 
2316 /** @brief Draw test program, fetch transform feedback results and compare them with expected values.
2317  *
2318  *  @param [in] size         Count of elements of the XFB vector is expected.
2319  *  @param [in] normalized   Normalized values are expected.
2320  *
2321  *  @return True if expected results are equal to returned by XFB, false otherwise.
2322  */
2323 template <typename T>
DrawAndCheck(glw::GLint size,bool normalized)2324 bool AttributeFormatTest::DrawAndCheck(glw::GLint size, bool normalized)
2325 {
2326 	/* Shortcut for GL functionality */
2327 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2328 
2329 	/* Setup state. */
2330 	gl.useProgram(m_po);
2331 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed.");
2332 
2333 	gl.bindVertexArray(m_vao);
2334 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed.");
2335 
2336 	/* Draw. */
2337 	gl.beginTransformFeedback(GL_POINTS);
2338 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback call failed.");
2339 
2340 	gl.drawArrays(GL_POINTS, 0, 2);
2341 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays call failed.");
2342 
2343 	gl.endTransformFeedback();
2344 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback call failed.");
2345 
2346 	/* Result query. */
2347 	T* result_ptr = (T*)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
2348 	GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer call failed.");
2349 
2350 	T result[8] = { 0 };
2351 
2352 	for (glw::GLint i = 0; i < size * 2 /* two points */; ++i)
2353 	{
2354 		result[i] = result_ptr[i];
2355 	}
2356 
2357 	gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
2358 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer call failed.");
2359 
2360 	const glw::GLdouble scale = normalized ? (1.0 / 16.0) /* Floating point scalling factor. */ : 1.0;
2361 
2362 	const T array_data[16] = { (T)(0.0 * scale),  (T)(1.0 * scale),  (T)(2.0 * scale),  (T)(3.0 * scale),
2363 							   (T)(4.0 * scale),  (T)(5.0 * scale),  (T)(6.0 * scale),  (T)(7.0 * scale),
2364 							   (T)(8.0 * scale),  (T)(9.0 * scale),  (T)(10.0 * scale), (T)(11.0 * scale),
2365 							   (T)(12.0 * scale), (T)(13.0 * scale), (T)(14.0 * scale), (T)(15.0 * scale) };
2366 
2367 	T reference[8] = { 0 };
2368 
2369 	for (glw::GLint i = 0; i < 2 /* two points */; ++i)
2370 	{
2371 		for (glw::GLint j = 0; j < size /* size components */; ++j)
2372 		{
2373 			reference[i * size + j] = array_data[i * size * 2 + j] + array_data[i * size * 2 + j + size];
2374 		}
2375 	}
2376 
2377 	/* Check result and return. */
2378 	for (glw::GLint i = 0; i < size * 2 /* two points */; ++i)
2379 	{
2380 		if (!AttributeFormatTest::compare<T>(reference[i], result[i]))
2381 		{
2382 			std::string reference_str = "[ ";
2383 
2384 			for (glw::GLint j = 0; j < size * 2 /* two points */; ++j)
2385 			{
2386 				std::stringstream ss;
2387 
2388 				ss << reference[j];
2389 
2390 				reference_str.append(ss.str());
2391 
2392 				if (j < size * 2 - 1 /* if it is not the last value */)
2393 				{
2394 					reference_str.append(", ");
2395 				}
2396 				else
2397 				{
2398 					reference_str.append(" ]");
2399 				}
2400 			}
2401 
2402 			std::string result_str = "[ ";
2403 
2404 			for (glw::GLint j = 0; j < size * 2 /* two points */; ++j)
2405 			{
2406 				std::stringstream ss;
2407 
2408 				ss << result[j];
2409 
2410 				result_str.append(ss.str());
2411 
2412 				if (j < size * 2 - 1 /* if it is not the last value */)
2413 				{
2414 					result_str.append(", ");
2415 				}
2416 				else
2417 				{
2418 					result_str.append(" ]");
2419 				}
2420 			}
2421 
2422 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "Result vector is equal to "
2423 												<< result_str.c_str() << ", but " << reference_str.c_str()
2424 												<< " was expected." << tcu::TestLog::EndMessage;
2425 
2426 			return false;
2427 		}
2428 	}
2429 
2430 	return true;
2431 }
2432 
2433 /** @brief Clean GLSL program object. */
CleanProgram()2434 void AttributeFormatTest::CleanProgram()
2435 {
2436 	/* Shortcut for GL functionality */
2437 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2438 
2439 	gl.useProgram(0);
2440 
2441 	if (m_po)
2442 	{
2443 		gl.deleteProgram(m_po);
2444 
2445 		m_po = 0;
2446 	}
2447 }
2448 
2449 /** @brief Clean Vertex Array Object and related buffer. */
CleanVAO()2450 void AttributeFormatTest::CleanVAO()
2451 {
2452 	/* Shortcut for GL functionality */
2453 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2454 
2455 	if (m_vao)
2456 	{
2457 		gl.deleteVertexArrays(1, &m_vao);
2458 
2459 		m_vao = 0;
2460 	}
2461 
2462 	if (m_bo_array)
2463 	{
2464 		gl.deleteBuffers(1, &m_bo_array);
2465 
2466 		m_bo_array = 0;
2467 	}
2468 }
2469 
2470 /** @brief Clean GL objects related to transform feedback. */
CleanXFB()2471 void AttributeFormatTest::CleanXFB()
2472 {
2473 	/* Shortcut for GL functionality */
2474 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2475 
2476 	if (m_bo_xfb)
2477 	{
2478 		gl.deleteBuffers(1, &m_bo_xfb);
2479 
2480 		m_bo_xfb = 0;
2481 	}
2482 
2483 	while (gl.getError())
2484 		;
2485 }
2486 
2487 const glw::GLchar* AttributeFormatTest::s_vertex_shader_head = "#version 450\n"
2488 															   "\n";
2489 
2490 const glw::GLchar* AttributeFormatTest::s_vertex_shader_body = "\n"
2491 															   "void main()\n"
2492 															   "{\n"
2493 															   "    gl_Position = vec4(1.0);\n"
2494 															   "    result = a_0 + a_1;"
2495 															   "}\n";
2496 
2497 const glw::GLchar* AttributeFormatTest::s_vertex_shader_declaration[ATTRIBUTE_FORMAT_FUNCTION_COUNT]
2498 																   [4 /* sizes count */] = { {
2499 																								 "in  float a_0;"
2500 																								 "in  float a_1;"
2501 																								 "out float result;\n",
2502 
2503 																								 "in  vec2 a_0;"
2504 																								 "in  vec2 a_1;"
2505 																								 "out vec2 result;\n",
2506 
2507 																								 "in  vec3 a_0;"
2508 																								 "in  vec3 a_1;"
2509 																								 "out vec3 result;\n",
2510 
2511 																								 "in  vec4 a_0;"
2512 																								 "in  vec4 a_1;"
2513 																								 "out vec4 result;\n",
2514 																							 },
2515 																							 {
2516 																								 "in  double a_0;"
2517 																								 "in  double a_1;"
2518 																								 "out double result;\n",
2519 
2520 																								 "in  dvec2 a_0;"
2521 																								 "in  dvec2 a_1;"
2522 																								 "out dvec2 result;\n",
2523 
2524 																								 "in  dvec3 a_0;"
2525 																								 "in  dvec3 a_1;"
2526 																								 "out dvec3 result;\n",
2527 
2528 																								 "in  dvec4 a_0;"
2529 																								 "in  dvec4 a_1;"
2530 																								 "out dvec4 result;\n",
2531 																							 },
2532 																							 {
2533 																								 "in  int a_0;"
2534 																								 "in  int a_1;"
2535 																								 "out int result;\n",
2536 
2537 																								 "in  ivec2 a_0;"
2538 																								 "in  ivec2 a_1;"
2539 																								 "out ivec2 result;\n",
2540 
2541 																								 "in  ivec3 a_0;"
2542 																								 "in  ivec3 a_1;"
2543 																								 "out ivec3 result;\n",
2544 
2545 																								 "in  ivec4 a_0;"
2546 																								 "in  ivec4 a_1;"
2547 																								 "out ivec4 result;\n",
2548 																							 } };
2549 
2550 const glw::GLchar* AttributeFormatTest::s_fragment_shader = "#version 450\n"
2551 															"\n"
2552 															"out vec4 color;\n"
2553 															"\n"
2554 															"void main()\n"
2555 															"{\n"
2556 															"    color = vec4(1.0);"
2557 															"}\n";
2558 
2559 /******************************** Vertex Array Object Attribute Binding Test Implementation   ********************************/
2560 
2561 /** @brief Attribute Binding Test constructor.
2562  *
2563  *  @param [in] context     OpenGL context.
2564  */
AttributeBindingTest(deqp::Context & context)2565 AttributeBindingTest::AttributeBindingTest(deqp::Context& context)
2566 	: deqp::TestCase(context, "vertex_arrays_attribute_binding", "Vertex Array Objects Attribute Binding Test")
2567 	, m_po(0)
2568 	, m_vao(0)
2569 	, m_bo_array(0)
2570 	, m_bo_xfb(0)
2571 {
2572 	/* Intentionally left blank. */
2573 }
2574 
2575 /** @brief Iterate Attribute Binding Test cases.
2576  *
2577  *  @return Iteration result.
2578  */
iterate()2579 tcu::TestNode::IterateResult AttributeBindingTest::iterate()
2580 {
2581 	/* Shortcut for GL functionality. */
2582 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2583 
2584 	/* Get context setup. */
2585 	bool is_at_least_gl_45 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 5)));
2586 	bool is_arb_direct_state_access = m_context.getContextInfo().isExtensionSupported("GL_ARB_direct_state_access");
2587 
2588 	if ((!is_at_least_gl_45) && (!is_arb_direct_state_access))
2589 	{
2590 		m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported");
2591 
2592 		return STOP;
2593 	}
2594 
2595 	/* Running tests. */
2596 	bool is_ok	= true;
2597 	bool is_error = false;
2598 
2599 	try
2600 	{
2601 		PrepareProgram();
2602 		is_ok &= PrepareVAO();
2603 		PrepareXFB();
2604 		is_ok &= DrawAndCheck();
2605 	}
2606 	catch (...)
2607 	{
2608 		is_ok	= false;
2609 		is_error = true;
2610 	}
2611 
2612 	/* Cleanup. */
2613 	Clean();
2614 
2615 	/* Errors clean up. */
2616 	while (gl.getError())
2617 		;
2618 
2619 	/* Result's setup. */
2620 	if (is_ok)
2621 	{
2622 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2623 	}
2624 	else
2625 	{
2626 		if (is_error)
2627 		{
2628 			m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
2629 		}
2630 		else
2631 		{
2632 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2633 		}
2634 	}
2635 
2636 	return STOP;
2637 }
2638 
2639 /** @brief Build test's GLSL program.
2640  *
2641  *  @note The function may throw if unexpected error has occured.
2642  */
PrepareProgram()2643 void AttributeBindingTest::PrepareProgram()
2644 {
2645 	/* Shortcut for GL functionality */
2646 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2647 
2648 	struct Shader
2649 	{
2650 		glw::GLchar const* const source;
2651 		glw::GLenum const		 type;
2652 		glw::GLuint				 id;
2653 	} shader[] = { { s_vertex_shader, GL_VERTEX_SHADER, 0 }, { s_fragment_shader, GL_FRAGMENT_SHADER, 0 } };
2654 
2655 	glw::GLuint const shader_count = DE_LENGTH_OF_ARRAY(shader);
2656 
2657 	try
2658 	{
2659 		/* Create program. */
2660 		m_po = gl.createProgram();
2661 		GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram call failed.");
2662 
2663 		/* Shader compilation. */
2664 
2665 		for (glw::GLuint i = 0; i < shader_count; ++i)
2666 		{
2667 			if (DE_NULL != shader[i].source)
2668 			{
2669 				shader[i].id = gl.createShader(shader[i].type);
2670 
2671 				GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader call failed.");
2672 
2673 				gl.attachShader(m_po, shader[i].id);
2674 
2675 				GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader call failed.");
2676 
2677 				gl.shaderSource(shader[i].id, 1, &(shader[i].source), NULL);
2678 
2679 				GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource call failed.");
2680 
2681 				gl.compileShader(shader[i].id);
2682 
2683 				GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader call failed.");
2684 
2685 				glw::GLint status = GL_FALSE;
2686 
2687 				gl.getShaderiv(shader[i].id, GL_COMPILE_STATUS, &status);
2688 				GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv call failed.");
2689 
2690 				if (GL_FALSE == status)
2691 				{
2692 					glw::GLint log_size = 0;
2693 					gl.getShaderiv(shader[i].id, GL_INFO_LOG_LENGTH, &log_size);
2694 					GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv call failed.");
2695 
2696 					glw::GLchar* log_text = new glw::GLchar[log_size];
2697 
2698 					gl.getShaderInfoLog(shader[i].id, log_size, NULL, &log_text[0]);
2699 
2700 					m_context.getTestContext().getLog() << tcu::TestLog::Message << "Shader compilation has failed.\n"
2701 														<< "Shader type: " << glu::getShaderTypeStr(shader[i].type)
2702 														<< "\n"
2703 														<< "Shader compilation error log:\n"
2704 														<< log_text << "\n"
2705 														<< "Shader source code:\n"
2706 														<< shader[i].source << "\n"
2707 														<< tcu::TestLog::EndMessage;
2708 
2709 					delete[] log_text;
2710 
2711 					GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderInfoLog call failed.");
2712 
2713 					throw 0;
2714 				}
2715 			}
2716 		}
2717 
2718 		/* Binding attributes. */
2719 		gl.bindAttribLocation(m_po, 0, "a_0");
2720 		gl.bindAttribLocation(m_po, 1, "a_1");
2721 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindAttribLocation call failed.");
2722 
2723 		/* Transform Feedback setup. */
2724 		static const glw::GLchar* xfb_varying = "result";
2725 		gl.transformFeedbackVaryings(m_po, 1, &xfb_varying, GL_INTERLEAVED_ATTRIBS);
2726 		GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings call failed.");
2727 
2728 		/* Link. */
2729 		gl.linkProgram(m_po);
2730 
2731 		GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings call failed.");
2732 
2733 		glw::GLint status = GL_FALSE;
2734 
2735 		gl.getProgramiv(m_po, GL_LINK_STATUS, &status);
2736 
2737 		if (GL_TRUE == status)
2738 		{
2739 			for (glw::GLuint i = 0; i < shader_count; ++i)
2740 			{
2741 				if (shader[i].id)
2742 				{
2743 					gl.detachShader(m_po, shader[i].id);
2744 
2745 					GLU_EXPECT_NO_ERROR(gl.getError(), "glDetachShader call failed.");
2746 				}
2747 			}
2748 		}
2749 		else
2750 		{
2751 			glw::GLint log_size = 0;
2752 
2753 			gl.getProgramiv(m_po, GL_INFO_LOG_LENGTH, &log_size);
2754 
2755 			GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv call failed.");
2756 
2757 			glw::GLchar* log_text = new glw::GLchar[log_size];
2758 
2759 			gl.getProgramInfoLog(m_po, log_size, NULL, &log_text[0]);
2760 
2761 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "Program linkage has failed due to:\n"
2762 												<< log_text << "\n"
2763 												<< tcu::TestLog::EndMessage;
2764 
2765 			delete[] log_text;
2766 
2767 			GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramInfoLog call failed.");
2768 
2769 			throw 0;
2770 		}
2771 	}
2772 	catch (...)
2773 	{
2774 		if (m_po)
2775 		{
2776 			gl.deleteProgram(m_po);
2777 
2778 			m_po = 0;
2779 		}
2780 	}
2781 
2782 	for (glw::GLuint i = 0; i < shader_count; ++i)
2783 	{
2784 		if (0 != shader[i].id)
2785 		{
2786 			gl.deleteShader(shader[i].id);
2787 
2788 			shader[i].id = 0;
2789 		}
2790 	}
2791 
2792 	if (0 == m_po)
2793 	{
2794 		throw 0;
2795 	}
2796 }
2797 
2798 /** @brief Prepare vertex array object for the test.
2799  *
2800  *  @return True if function VertexArrayAttribBinding does not generate any error.
2801  */
PrepareVAO()2802 bool AttributeBindingTest::PrepareVAO()
2803 {
2804 	/* Shortcut for GL functionality */
2805 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2806 
2807 	/* VAO creation. */
2808 	gl.genVertexArrays(1, &m_vao);
2809 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays call failed.");
2810 
2811 	gl.bindVertexArray(m_vao);
2812 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed.");
2813 
2814 	/* Array buffer creation. */
2815 	glw::GLint array_data[2] = { 1, 0 };
2816 
2817 	gl.genBuffers(1, &m_bo_array);
2818 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed.");
2819 
2820 	gl.bindBuffer(GL_ARRAY_BUFFER, m_bo_array);
2821 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
2822 
2823 	gl.bufferData(GL_ARRAY_BUFFER, sizeof(array_data), array_data, GL_STATIC_DRAW);
2824 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed.");
2825 
2826 	gl.vertexAttribIPointer(0, 1, GL_INT, sizeof(glw::GLint) * 2, NULL);
2827 	GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribIPointer call failed.");
2828 
2829 	gl.vertexAttribIPointer(1, 1, GL_INT, sizeof(glw::GLint) * 2, glu::BufferOffsetAsPointer(1 * sizeof(glw::GLint)));
2830 	GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribIPointer call failed.");
2831 
2832 	gl.enableVertexAttribArray(0);
2833 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray call failed.");
2834 
2835 	gl.enableVertexAttribArray(1);
2836 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray call failed.");
2837 
2838 	gl.vertexArrayAttribBinding(m_vao, 0, 1);
2839 	gl.vertexArrayAttribBinding(m_vao, 1, 0);
2840 
2841 	if (glw::GLenum error = gl.getError())
2842 	{
2843 		m_context.getTestContext().getLog() << tcu::TestLog::Message
2844 											<< "VertexArrayAttribBinding has unexpectedly generated "
2845 											<< glu::getErrorStr(error) << "error. Test fails.\n"
2846 											<< tcu::TestLog::EndMessage;
2847 
2848 		return false;
2849 	}
2850 
2851 	return true;
2852 }
2853 
2854 /** @brief Prepare buffer object for test GLSL program transform feedback results.
2855  */
PrepareXFB()2856 void AttributeBindingTest::PrepareXFB()
2857 {
2858 	/* Shortcut for GL functionality */
2859 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2860 
2861 	/* Buffer creation. */
2862 	gl.genBuffers(1, &m_bo_xfb);
2863 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed.");
2864 
2865 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_xfb);
2866 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
2867 
2868 	/* Preparing storage. */
2869 	gl.bufferStorage(GL_TRANSFORM_FEEDBACK_BUFFER, 2 * sizeof(glw::GLint), NULL, GL_MAP_READ_BIT);
2870 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferStorage call failed.");
2871 
2872 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_bo_xfb);
2873 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase call failed.");
2874 }
2875 
2876 /** @brief Draw test program, fetch transform feedback results and compare them with expected values.
2877  *
2878  *  @return True if expected results are equal to returned by XFB, false otherwise.
2879  */
DrawAndCheck()2880 bool AttributeBindingTest::DrawAndCheck()
2881 {
2882 	/* Shortcut for GL functionality */
2883 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2884 
2885 	/* Setup state. */
2886 	gl.useProgram(m_po);
2887 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed.");
2888 
2889 	gl.bindVertexArray(m_vao);
2890 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed.");
2891 
2892 	gl.beginTransformFeedback(GL_POINTS);
2893 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback call failed.");
2894 
2895 	/* Draw. */
2896 	gl.drawArrays(GL_POINTS, 0, 1);
2897 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays call failed.");
2898 
2899 	/* State reset. */
2900 	gl.endTransformFeedback();
2901 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback call failed.");
2902 
2903 	/* Result query. */
2904 	glw::GLint* result_ptr = (glw::GLint*)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
2905 	GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer call failed.");
2906 
2907 	glw::GLint result[2] = { result_ptr[0], result_ptr[1] };
2908 
2909 	gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
2910 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer call failed.");
2911 
2912 	/* Check result and return. */
2913 	if ((0 == result[0]) || (1 == result[1]))
2914 	{
2915 		return true;
2916 	}
2917 
2918 	return false;
2919 }
2920 
2921 /** @brief Clean GL objects. */
Clean()2922 void AttributeBindingTest::Clean()
2923 {
2924 	/* Shortcut for GL functionality */
2925 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2926 
2927 	gl.useProgram(0);
2928 
2929 	if (m_po)
2930 	{
2931 		gl.deleteProgram(m_po);
2932 
2933 		m_po = 0;
2934 	}
2935 
2936 	if (m_vao)
2937 	{
2938 		gl.deleteVertexArrays(1, &m_vao);
2939 
2940 		m_vao = 0;
2941 	}
2942 
2943 	if (m_bo_array)
2944 	{
2945 		gl.deleteBuffers(1, &m_bo_array);
2946 
2947 		m_bo_array = 0;
2948 	}
2949 
2950 	if (m_bo_xfb)
2951 	{
2952 		gl.deleteBuffers(1, &m_bo_xfb);
2953 
2954 		m_bo_xfb = 0;
2955 	}
2956 
2957 	while (gl.getError())
2958 		;
2959 }
2960 
2961 const glw::GLchar AttributeBindingTest::s_vertex_shader[] = "#version 450\n"
2962 															"\n"
2963 															"in int a_0;\n"
2964 															"in int a_1;\n"
2965 															"out ivec2 result;\n"
2966 															"\n"
2967 															"void main()\n"
2968 															"{\n"
2969 															"    gl_Position = vec4(1.0);\n"
2970 															"    result[0] = a_0;\n"
2971 															"    result[1] = a_1;\n"
2972 															"}\n";
2973 
2974 const glw::GLchar AttributeBindingTest::s_fragment_shader[] = "#version 450\n"
2975 															  "\n"
2976 															  "out vec4 color;\n"
2977 															  "\n"
2978 															  "void main()\n"
2979 															  "{\n"
2980 															  "    color = vec4(1.0);"
2981 															  "}\n";
2982 
2983 /******************************** Vertex Array Attribute Binding Divisor Test Implementation   ********************************/
2984 
2985 /** @brief Vertex Array Attribute Binding Divisor Test constructor.
2986  *
2987  *  @param [in] context     OpenGL context.
2988  */
AttributeBindingDivisorTest(deqp::Context & context)2989 AttributeBindingDivisorTest::AttributeBindingDivisorTest(deqp::Context& context)
2990 	: deqp::TestCase(context, "vertex_arrays_attribute_binding_divisor", "Vertex Array Attribute Binding Divisor Test")
2991 	, m_po(0)
2992 	, m_vao(0)
2993 	, m_bo_array(0)
2994 	, m_bo_xfb(0)
2995 {
2996 	/* Intentionally left blank. */
2997 }
2998 
2999 /** @brief Iterate Vertex Array Attribute Binding Divisor Test cases.
3000  *
3001  *  @return Iteration result.
3002  */
iterate()3003 tcu::TestNode::IterateResult AttributeBindingDivisorTest::iterate()
3004 {
3005 	/* Shortcut for GL functionality. */
3006 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3007 
3008 	/* Get context setup. */
3009 	bool is_at_least_gl_45 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 5)));
3010 	bool is_arb_direct_state_access = m_context.getContextInfo().isExtensionSupported("GL_ARB_direct_state_access");
3011 
3012 	if ((!is_at_least_gl_45) && (!is_arb_direct_state_access))
3013 	{
3014 		m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported");
3015 
3016 		return STOP;
3017 	}
3018 
3019 	/* Running tests. */
3020 	bool is_ok	= true;
3021 	bool is_error = false;
3022 
3023 	try
3024 	{
3025 		PrepareProgram();
3026 		PrepareVAO();
3027 		PrepareXFB();
3028 
3029 		{
3030 			glw::GLint reference[] = { 0, 2 };
3031 			is_ok				   = SetDivisor(2);
3032 			Draw(1, 2);
3033 			is_ok = CheckXFB((sizeof(reference) / sizeof(reference[0])), reference,
3034 							 "Draw of 1 point with 2 instances with 2 divisor has failed.");
3035 		}
3036 
3037 		{
3038 			glw::GLint reference[] = { 0, 0, 1, 1 };
3039 			is_ok				   = SetDivisor(1);
3040 			Draw(2, 2);
3041 			is_ok = CheckXFB((sizeof(reference) / sizeof(reference[0])), reference,
3042 							 "Draw of 2 points with 2 instances with 1 divisor has failed.");
3043 		}
3044 
3045 		{
3046 			glw::GLint reference[] = { 0, 1, 2, 3 };
3047 			is_ok				   = SetDivisor(1);
3048 			Draw(1, 4);
3049 			is_ok = CheckXFB((sizeof(reference) / sizeof(reference[0])), reference,
3050 							 "Draw of 1 point with 4 instances with 1 divisor has failed.");
3051 		}
3052 
3053 		{
3054 			glw::GLint reference[] = { 0, 1, 0, 1 };
3055 			is_ok				   = SetDivisor(0);
3056 			Draw(2, 2);
3057 			is_ok = CheckXFB((sizeof(reference) / sizeof(reference[0])), reference,
3058 							 "Draw of 2 points with 2 instances with 0 divisor has failed.");
3059 		}
3060 
3061 		{
3062 			glw::GLint reference[] = { 0, 1, 2, 3 };
3063 			is_ok				   = SetDivisor(0);
3064 			Draw(4, 1);
3065 			is_ok = CheckXFB((sizeof(reference) / sizeof(reference[0])), reference,
3066 							 "Draw of 4 points with 1 instance with 0 divisor has failed.");
3067 		}
3068 	}
3069 	catch (...)
3070 	{
3071 		is_ok	= false;
3072 		is_error = true;
3073 	}
3074 
3075 	/* Cleanup. */
3076 	Clean();
3077 
3078 	/* Errors clean up. */
3079 	while (gl.getError())
3080 		;
3081 
3082 	/* Result's setup. */
3083 	if (is_ok)
3084 	{
3085 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
3086 	}
3087 	else
3088 	{
3089 		if (is_error)
3090 		{
3091 			m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
3092 		}
3093 		else
3094 		{
3095 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
3096 		}
3097 	}
3098 
3099 	return STOP;
3100 }
3101 
3102 /** @brief Build test's GLSL program.
3103  *
3104  *  @note The function may throw if unexpected error has occured.
3105  */
PrepareProgram()3106 void AttributeBindingDivisorTest::PrepareProgram()
3107 {
3108 	/* Shortcut for GL functionality */
3109 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3110 
3111 	struct Shader
3112 	{
3113 		glw::GLchar const* const source;
3114 		glw::GLenum const		 type;
3115 		glw::GLuint				 id;
3116 	} shader[] = { { s_vertex_shader, GL_VERTEX_SHADER, 0 }, { s_fragment_shader, GL_FRAGMENT_SHADER, 0 } };
3117 
3118 	glw::GLuint const shader_count = sizeof(shader) / sizeof(shader[0]);
3119 
3120 	try
3121 	{
3122 		/* Create program. */
3123 		m_po = gl.createProgram();
3124 		GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram call failed.");
3125 
3126 		/* Shader compilation. */
3127 
3128 		for (glw::GLuint i = 0; i < shader_count; ++i)
3129 		{
3130 			if (DE_NULL != shader[i].source)
3131 			{
3132 				shader[i].id = gl.createShader(shader[i].type);
3133 
3134 				GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader call failed.");
3135 
3136 				gl.attachShader(m_po, shader[i].id);
3137 
3138 				GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader call failed.");
3139 
3140 				gl.shaderSource(shader[i].id, 1, &(shader[i].source), NULL);
3141 
3142 				GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource call failed.");
3143 
3144 				gl.compileShader(shader[i].id);
3145 
3146 				GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader call failed.");
3147 
3148 				glw::GLint status = GL_FALSE;
3149 
3150 				gl.getShaderiv(shader[i].id, GL_COMPILE_STATUS, &status);
3151 				GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv call failed.");
3152 
3153 				if (GL_FALSE == status)
3154 				{
3155 					glw::GLint log_size = 0;
3156 					gl.getShaderiv(shader[i].id, GL_INFO_LOG_LENGTH, &log_size);
3157 					GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv call failed.");
3158 
3159 					glw::GLchar* log_text = new glw::GLchar[log_size];
3160 
3161 					gl.getShaderInfoLog(shader[i].id, log_size, NULL, &log_text[0]);
3162 
3163 					m_context.getTestContext().getLog() << tcu::TestLog::Message << "Shader compilation has failed.\n"
3164 														<< "Shader type: " << glu::getShaderTypeStr(shader[i].type)
3165 														<< "\n"
3166 														<< "Shader compilation error log:\n"
3167 														<< log_text << "\n"
3168 														<< "Shader source code:\n"
3169 														<< shader[i].source << "\n"
3170 														<< tcu::TestLog::EndMessage;
3171 
3172 					delete[] log_text;
3173 
3174 					GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderInfoLog call failed.");
3175 
3176 					throw 0;
3177 				}
3178 			}
3179 		}
3180 
3181 		/* Transform Feedback setup. */
3182 		static const glw::GLchar* xfb_varying = "result";
3183 
3184 		gl.transformFeedbackVaryings(m_po, 1, &xfb_varying, GL_INTERLEAVED_ATTRIBS);
3185 		GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings call failed.");
3186 
3187 		/* Link. */
3188 		gl.linkProgram(m_po);
3189 
3190 		GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings call failed.");
3191 
3192 		glw::GLint status = GL_FALSE;
3193 
3194 		gl.getProgramiv(m_po, GL_LINK_STATUS, &status);
3195 
3196 		if (GL_TRUE == status)
3197 		{
3198 			for (glw::GLuint i = 0; i < shader_count; ++i)
3199 			{
3200 				if (shader[i].id)
3201 				{
3202 					gl.detachShader(m_po, shader[i].id);
3203 
3204 					GLU_EXPECT_NO_ERROR(gl.getError(), "glDetachShader call failed.");
3205 				}
3206 			}
3207 		}
3208 		else
3209 		{
3210 			glw::GLint log_size = 0;
3211 
3212 			gl.getProgramiv(m_po, GL_INFO_LOG_LENGTH, &log_size);
3213 
3214 			GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv call failed.");
3215 
3216 			glw::GLchar* log_text = new glw::GLchar[log_size];
3217 
3218 			gl.getProgramInfoLog(m_po, log_size, NULL, &log_text[0]);
3219 
3220 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "Program linkage has failed due to:\n"
3221 												<< log_text << "\n"
3222 												<< tcu::TestLog::EndMessage;
3223 
3224 			delete[] log_text;
3225 
3226 			GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramInfoLog call failed.");
3227 
3228 			throw 0;
3229 		}
3230 	}
3231 	catch (...)
3232 	{
3233 		if (m_po)
3234 		{
3235 			gl.deleteProgram(m_po);
3236 
3237 			m_po = 0;
3238 		}
3239 	}
3240 
3241 	for (glw::GLuint i = 0; i < shader_count; ++i)
3242 	{
3243 		if (0 != shader[i].id)
3244 		{
3245 			gl.deleteShader(shader[i].id);
3246 
3247 			shader[i].id = 0;
3248 		}
3249 	}
3250 
3251 	if (m_po)
3252 	{
3253 		gl.useProgram(m_po);
3254 		GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed.");
3255 	}
3256 
3257 	if (0 == m_po)
3258 	{
3259 		throw 0;
3260 	}
3261 }
3262 
3263 /** @brief Prepare vertex array object for the test.
3264  */
PrepareVAO()3265 void AttributeBindingDivisorTest::PrepareVAO()
3266 {
3267 	/* Shortcut for GL functionality */
3268 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3269 
3270 	/* VAO creation. */
3271 	gl.genVertexArrays(1, &m_vao);
3272 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays call failed.");
3273 
3274 	gl.bindVertexArray(m_vao);
3275 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed.");
3276 
3277 	/* Array buffer 0 creation. */
3278 	glw::GLint array_data[4] = { 0, 1, 2, 3 };
3279 
3280 	gl.genBuffers(1, &m_bo_array);
3281 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed.");
3282 
3283 	gl.bindBuffer(GL_ARRAY_BUFFER, m_bo_array);
3284 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
3285 
3286 	gl.bufferData(GL_ARRAY_BUFFER, sizeof(array_data), array_data, GL_STATIC_DRAW);
3287 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed.");
3288 
3289 	gl.vertexAttribBinding(gl.getAttribLocation(m_po, "a"), 0);
3290 	GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribBinding call failed.");
3291 
3292 	gl.vertexAttribIFormat(gl.getAttribLocation(m_po, "a"), 1, GL_INT, 0);
3293 	GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribIFormat call failed.");
3294 
3295 	gl.bindVertexBuffer(0, m_bo_array, 0, sizeof(glw::GLint));
3296 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexBuffer call failed.");
3297 
3298 	gl.enableVertexAttribArray(gl.getAttribLocation(m_po, "a"));
3299 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray call failed.");
3300 }
3301 
3302 /** @brief Prepare buffer object for test GLSL program transform feedback results.
3303  */
PrepareXFB()3304 void AttributeBindingDivisorTest::PrepareXFB()
3305 {
3306 	/* Shortcut for GL functionality */
3307 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3308 
3309 	/* Buffer creation. */
3310 	gl.genBuffers(1, &m_bo_xfb);
3311 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed.");
3312 
3313 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_xfb);
3314 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
3315 
3316 	/* Preparing storage. */
3317 	gl.bufferStorage(GL_TRANSFORM_FEEDBACK_BUFFER, 4 * sizeof(glw::GLint), NULL, GL_MAP_READ_BIT);
3318 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferStorage call failed.");
3319 
3320 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_bo_xfb);
3321 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase call failed.");
3322 }
3323 
3324 /** @brief Draw number of points and number of instances with XFB environment.
3325  *
3326  *  @param [in] number_of_points        Number of points to be drawn.
3327  *  @param [in] number_of_instances     Number of instances to be drawn.
3328  */
Draw(glw::GLuint number_of_points,glw::GLuint number_of_instances)3329 void AttributeBindingDivisorTest::Draw(glw::GLuint number_of_points, glw::GLuint number_of_instances)
3330 {
3331 	/* Shortcut for GL functionality */
3332 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3333 
3334 	/* Setup state. */
3335 	gl.beginTransformFeedback(GL_POINTS);
3336 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback call failed.");
3337 
3338 	/* Draw. */
3339 	gl.drawArraysInstanced(GL_POINTS, 0, number_of_points, number_of_instances);
3340 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArraysInstanced call failed.");
3341 
3342 	/* State reset. */
3343 	gl.endTransformFeedback();
3344 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback call failed.");
3345 }
3346 
3347 /** @brief Call VertexArrayBindingDivisor on m_vao object and check errors.
3348  *
3349  *  @param [in] divisor        Divisor to be passed.
3350  *
3351  *  @return True if VertexArrayBindingDivisor doe not generate any error, false otherwise.
3352  */
SetDivisor(glw::GLuint divisor)3353 bool AttributeBindingDivisorTest::SetDivisor(glw::GLuint divisor)
3354 {
3355 	/* Shortcut for GL functionality */
3356 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3357 
3358 	/* Setup. */
3359 	gl.vertexArrayBindingDivisor(m_vao, 0, divisor);
3360 
3361 	/* Checking for errors (this is tested function so it fail the test if there is error). */
3362 	if (glw::GLenum error = gl.getError())
3363 	{
3364 		m_context.getTestContext().getLog()
3365 			<< tcu::TestLog::Message << "VertexArrayBindingDivisor unexpectedl generated " << glu::getErrorStr(error)
3366 			<< " error when called with divisor" << divisor << ". " << tcu::TestLog::EndMessage;
3367 
3368 		return false;
3369 	}
3370 
3371 	return true;
3372 }
3373 
3374 /** @brief Check transform feedback results and log.
3375  *
3376  *  @param [in] count           Number of results to be checked.
3377  *  @param [in] expected        Expected results.
3378  *  @param [in] log_message     Message to be logged if expected values are not equal to queried.
3379  *
3380  *  @return True if expected values are equal to queried, false otherwise.
3381  */
CheckXFB(const glw::GLuint count,const glw::GLint expected[],const glw::GLchar * log_message)3382 bool AttributeBindingDivisorTest::CheckXFB(const glw::GLuint count, const glw::GLint expected[],
3383 										   const glw::GLchar* log_message)
3384 {
3385 	/* Shortcut for GL functionality */
3386 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3387 
3388 	/* Result setup */
3389 	bool is_ok = true;
3390 
3391 	/* Result query. */
3392 	glw::GLint* result = (glw::GLint*)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
3393 	GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer call failed.");
3394 
3395 	/* Check result and return. */
3396 	for (glw::GLuint i = 0; i < count; ++i)
3397 	{
3398 		if (expected[i] != result[i])
3399 		{
3400 			std::string expected_str = "[";
3401 			std::string result_str   = "[";
3402 
3403 			for (glw::GLuint j = 0; j < count; ++j)
3404 			{
3405 				expected_str.append(Utilities::itoa((glw::GLuint)expected[j]));
3406 				result_str.append(Utilities::itoa((glw::GLuint)result[j]));
3407 
3408 				if (j < count - 1)
3409 				{
3410 					expected_str.append(", ");
3411 					result_str.append(", ");
3412 				}
3413 				else
3414 				{
3415 					expected_str.append("]");
3416 					result_str.append("]");
3417 				}
3418 			}
3419 
3420 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "Result is " << result_str << ", but "
3421 												<< expected_str << " was expected. " << log_message
3422 												<< tcu::TestLog::EndMessage;
3423 
3424 			is_ok = false;
3425 			break;
3426 		}
3427 	}
3428 
3429 	/* Unmaping GL buffer. */
3430 	gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
3431 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer call failed.");
3432 
3433 	return is_ok;
3434 }
3435 
3436 /** @brief Clean GL objects. */
Clean()3437 void AttributeBindingDivisorTest::Clean()
3438 {
3439 	/* Shortcut for GL functionality */
3440 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3441 
3442 	gl.useProgram(0);
3443 
3444 	if (m_po)
3445 	{
3446 		gl.deleteProgram(m_po);
3447 
3448 		m_po = 0;
3449 	}
3450 
3451 	if (m_vao)
3452 	{
3453 		gl.deleteVertexArrays(1, &m_vao);
3454 
3455 		m_vao = 0;
3456 	}
3457 
3458 	if (m_bo_array)
3459 	{
3460 		gl.deleteBuffers(1, &m_bo_array);
3461 
3462 		m_bo_array = 0;
3463 	}
3464 
3465 	if (m_bo_xfb)
3466 	{
3467 		gl.deleteBuffers(1, &m_bo_xfb);
3468 
3469 		m_bo_xfb = 0;
3470 	}
3471 
3472 	while (gl.getError())
3473 		;
3474 }
3475 
3476 const glw::GLchar AttributeBindingDivisorTest::s_vertex_shader[] = "#version 450\n"
3477 																   "\n"
3478 																   "in  int a;\n"
3479 																   "out int result;\n"
3480 																   "\n"
3481 																   "void main()\n"
3482 																   "{\n"
3483 																   "    gl_Position = vec4(1.0);\n"
3484 																   "    result = a;"
3485 																   "}\n";
3486 
3487 const glw::GLchar AttributeBindingDivisorTest::s_fragment_shader[] = "#version 450\n"
3488 																	 "\n"
3489 																	 "out vec4 color;\n"
3490 																	 "\n"
3491 																	 "void main()\n"
3492 																	 "{\n"
3493 																	 "    color = vec4(1.0);"
3494 																	 "}\n";
3495 
3496 /******************************** Get Vertex Array Test Implementation   ********************************/
3497 
3498 /** @brief Get Vertex Array Test constructor.
3499  *
3500  *  @param [in] context     OpenGL context.
3501  */
GetVertexArrayTest(deqp::Context & context)3502 GetVertexArrayTest::GetVertexArrayTest(deqp::Context& context)
3503 	: deqp::TestCase(context, "vertex_arrays_get_vertex_array", "Get Vertex Array Test")
3504 {
3505 	/* Intentionally left blank. */
3506 }
3507 
3508 /** @brief Iterate Vertex Array Attribute Binding Divisor Test cases.
3509  *
3510  *  @return Iteration result.
3511  */
iterate()3512 tcu::TestNode::IterateResult GetVertexArrayTest::iterate()
3513 {
3514 	/* Shortcut for GL functionality. */
3515 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3516 
3517 	/* Get context setup. */
3518 	bool is_at_least_gl_45 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 5)));
3519 	bool is_arb_direct_state_access = m_context.getContextInfo().isExtensionSupported("GL_ARB_direct_state_access");
3520 
3521 	if ((!is_at_least_gl_45) && (!is_arb_direct_state_access))
3522 	{
3523 		m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported");
3524 
3525 		return STOP;
3526 	}
3527 
3528 	/* Running tests. */
3529 	bool is_ok	= true;
3530 	bool is_error = false;
3531 
3532 	/* Test objects. */
3533 	glw::GLuint vao = 0;
3534 	glw::GLuint bo  = 0;
3535 
3536 	try
3537 	{
3538 		gl.genVertexArrays(1, &vao);
3539 		GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateVertexArrays call failed.");
3540 
3541 		gl.bindVertexArray(vao);
3542 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed.");
3543 
3544 		gl.genBuffers(1, &bo);
3545 		GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateBuffers call failed.");
3546 
3547 		gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, bo);
3548 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
3549 
3550 		glw::GLint result = 0;
3551 		gl.getVertexArrayiv(vao, GL_ELEMENT_ARRAY_BUFFER_BINDING, &result);
3552 
3553 		if (glw::GLenum error = gl.getError())
3554 		{
3555 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "GetVertexArrayiv unexpectedly generated "
3556 												<< glu::getErrorStr(error) << "error. Test fails."
3557 												<< tcu::TestLog::EndMessage;
3558 
3559 			is_ok = false;
3560 		}
3561 
3562 		if ((glw::GLuint)result != bo)
3563 		{
3564 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "GetVertexArrayiv was expected to return "
3565 												<< bo << ", but " << result << " was observed. Test fails."
3566 												<< tcu::TestLog::EndMessage;
3567 
3568 			is_ok = false;
3569 		}
3570 	}
3571 	catch (...)
3572 	{
3573 		is_ok	= false;
3574 		is_error = true;
3575 	}
3576 
3577 	/* Cleanup. */
3578 	if (vao)
3579 	{
3580 		gl.deleteVertexArrays(1, &vao);
3581 	}
3582 
3583 	if (bo)
3584 	{
3585 		gl.deleteBuffers(1, &bo);
3586 	}
3587 
3588 	/* Errors clean up. */
3589 	while (gl.getError())
3590 		;
3591 
3592 	/* Result's setup. */
3593 	if (is_ok)
3594 	{
3595 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
3596 	}
3597 	else
3598 	{
3599 		if (is_error)
3600 		{
3601 			m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
3602 		}
3603 		else
3604 		{
3605 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
3606 		}
3607 	}
3608 
3609 	return STOP;
3610 }
3611 
3612 /******************************** Get Vertex Array Test Indexed Implementation   ********************************/
3613 
3614 /** @brief Get Vertex Array Indexed Test constructor.
3615  *
3616  *  @param [in] context     OpenGL context.
3617  */
GetVertexArrayIndexedTest(deqp::Context & context)3618 GetVertexArrayIndexedTest::GetVertexArrayIndexedTest(deqp::Context& context)
3619 	: deqp::TestCase(context, "vertex_arrays_get_vertex_array_indexed", "Get Vertex Array Indexed Test"), m_vao(0)
3620 {
3621 	m_bo[0] = 0;
3622 	m_bo[1] = 0;
3623 	m_bo[2] = 0;
3624 	m_bo[3] = 0;
3625 }
3626 
3627 /** @brief Iterate Vertex Array Attribute Binding Divisor Test cases.
3628  *
3629  *  @return Iteration result.
3630  */
iterate()3631 tcu::TestNode::IterateResult GetVertexArrayIndexedTest::iterate()
3632 {
3633 	/* Shortcut for GL functionality. */
3634 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3635 
3636 	/* Get context setup. */
3637 	bool is_at_least_gl_45 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 5)));
3638 	bool is_arb_direct_state_access = m_context.getContextInfo().isExtensionSupported("GL_ARB_direct_state_access");
3639 
3640 	if ((!is_at_least_gl_45) && (!is_arb_direct_state_access))
3641 	{
3642 		m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported");
3643 
3644 		return STOP;
3645 	}
3646 
3647 	/* Running tests. */
3648 	bool is_ok	= true;
3649 	bool is_error = false;
3650 
3651 	try
3652 	{
3653 		PrepareVAO();
3654 
3655 		is_ok &= Check(GL_VERTEX_ATTRIB_ARRAY_ENABLED, 0, GL_TRUE);
3656 		is_ok &= Check(GL_VERTEX_ATTRIB_ARRAY_ENABLED, 1, GL_TRUE);
3657 		is_ok &= Check(GL_VERTEX_ATTRIB_ARRAY_ENABLED, 2, GL_TRUE);
3658 		is_ok &= Check(GL_VERTEX_ATTRIB_ARRAY_ENABLED, 3, GL_TRUE);
3659 		is_ok &= Check(GL_VERTEX_ATTRIB_ARRAY_ENABLED, 5, GL_FALSE);
3660 
3661 		is_ok &= Check(GL_VERTEX_ATTRIB_ARRAY_STRIDE, 0, 0);
3662 		is_ok &= Check(GL_VERTEX_ATTRIB_ARRAY_STRIDE, 1, 2);
3663 		is_ok &= Check(GL_VERTEX_ATTRIB_ARRAY_STRIDE, 2, 0);
3664 		is_ok &= Check(GL_VERTEX_ATTRIB_ARRAY_STRIDE, 3, 8);
3665 
3666 		is_ok &= Check(GL_VERTEX_ATTRIB_ARRAY_TYPE, 0, GL_BYTE);
3667 		is_ok &= Check(GL_VERTEX_ATTRIB_ARRAY_TYPE, 1, GL_SHORT);
3668 		is_ok &= Check(GL_VERTEX_ATTRIB_ARRAY_TYPE, 2, GL_FLOAT);
3669 		is_ok &= Check(GL_VERTEX_ATTRIB_ARRAY_TYPE, 3, GL_UNSIGNED_INT_2_10_10_10_REV);
3670 
3671 		is_ok &= Check(GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, 0, GL_TRUE);
3672 		is_ok &= Check(GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, 1, GL_FALSE);
3673 		is_ok &= Check(GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, 2, GL_FALSE);
3674 		is_ok &= Check(GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, 3, GL_FALSE);
3675 
3676 		is_ok &= Check(GL_VERTEX_ATTRIB_ARRAY_INTEGER, 0, GL_FALSE);
3677 		is_ok &= Check(GL_VERTEX_ATTRIB_ARRAY_INTEGER, 1, GL_TRUE);
3678 		is_ok &= Check(GL_VERTEX_ATTRIB_ARRAY_INTEGER, 2, GL_FALSE);
3679 		is_ok &= Check(GL_VERTEX_ATTRIB_ARRAY_INTEGER, 3, GL_FALSE);
3680 
3681 		is_ok &= Check(GL_VERTEX_ATTRIB_ARRAY_DIVISOR, 0, 3);
3682 		is_ok &= Check(GL_VERTEX_ATTRIB_ARRAY_DIVISOR, 1, 2);
3683 		is_ok &= Check(GL_VERTEX_ATTRIB_ARRAY_DIVISOR, 2, 1);
3684 		is_ok &= Check(GL_VERTEX_ATTRIB_ARRAY_DIVISOR, 3, 0);
3685 
3686 		is_ok &= Check(GL_VERTEX_ATTRIB_ARRAY_LONG, 0, GL_FALSE);
3687 		is_ok &= Check(GL_VERTEX_ATTRIB_ARRAY_LONG, 1, GL_FALSE);
3688 		is_ok &= Check(GL_VERTEX_ATTRIB_ARRAY_LONG, 2, GL_FALSE);
3689 		is_ok &= Check(GL_VERTEX_ATTRIB_ARRAY_LONG, 3, GL_FALSE);
3690 
3691 		is_ok &= Check(GL_VERTEX_ATTRIB_RELATIVE_OFFSET, 0, 0);
3692 		is_ok &= Check(GL_VERTEX_ATTRIB_RELATIVE_OFFSET, 1, 0);
3693 		is_ok &= Check(GL_VERTEX_ATTRIB_RELATIVE_OFFSET, 2, 4);
3694 		is_ok &= Check(GL_VERTEX_ATTRIB_RELATIVE_OFFSET, 3, 0);
3695 
3696 		is_ok &= Check64(GL_VERTEX_BINDING_OFFSET, 0, 0);
3697 		is_ok &= Check64(GL_VERTEX_BINDING_OFFSET, 1, 2);
3698 		is_ok &= Check64(GL_VERTEX_BINDING_OFFSET, 2, 8);
3699 		is_ok &= Check64(GL_VERTEX_BINDING_OFFSET, 3, 4);
3700 	}
3701 	catch (...)
3702 	{
3703 		is_ok	= false;
3704 		is_error = true;
3705 	}
3706 
3707 	/* Cleanup. */
3708 	if (m_vao)
3709 	{
3710 		gl.deleteVertexArrays(1, &m_vao);
3711 
3712 		m_vao = 0;
3713 	}
3714 
3715 	if (m_bo[0] || m_bo[1] || m_bo[2] || m_bo[3])
3716 	{
3717 		gl.deleteBuffers(4, m_bo);
3718 
3719 		m_bo[0] = 0;
3720 		m_bo[1] = 0;
3721 		m_bo[2] = 0;
3722 		m_bo[3] = 0;
3723 	}
3724 
3725 	/* Errors clean up. */
3726 	while (gl.getError())
3727 		;
3728 
3729 	/* Result's setup. */
3730 	if (is_ok)
3731 	{
3732 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
3733 	}
3734 	else
3735 	{
3736 		if (is_error)
3737 		{
3738 			m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
3739 		}
3740 		else
3741 		{
3742 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
3743 		}
3744 	}
3745 
3746 	return STOP;
3747 }
3748 
3749 /** @brief Prepare vertex array object for the test.
3750  */
PrepareVAO()3751 void GetVertexArrayIndexedTest::PrepareVAO()
3752 {
3753 	/* Shortcut for GL functionality. */
3754 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3755 
3756 	gl.genVertexArrays(1, &m_vao);
3757 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateVertexArrays call failed.");
3758 
3759 	gl.bindVertexArray(m_vao);
3760 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed.");
3761 
3762 	gl.genBuffers(4, m_bo);
3763 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateBuffers call failed.");
3764 
3765 	/* Attribute 0. */
3766 	gl.bindBuffer(GL_ARRAY_BUFFER, m_bo[0]);
3767 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
3768 
3769 	gl.vertexAttribPointer(0, 1, GL_BYTE, GL_TRUE, 0, NULL);
3770 	GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer call failed.");
3771 
3772 	gl.enableVertexAttribArray(0);
3773 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray call failed.");
3774 
3775 	gl.vertexAttribDivisor(0, 3);
3776 	GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribDivisor call failed.");
3777 
3778 	/* Attribute 1. */
3779 	gl.bindBuffer(GL_ARRAY_BUFFER, m_bo[1]);
3780 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
3781 
3782 	gl.vertexAttribIPointer(1, 2, GL_SHORT, 2, glu::BufferOffsetAsPointer(2 * sizeof(glw::GLchar)));
3783 	GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer call failed.");
3784 
3785 	gl.enableVertexAttribArray(1);
3786 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray call failed.");
3787 
3788 	gl.vertexAttribDivisor(1, 2);
3789 	GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribDivisor call failed.");
3790 
3791 	/* Attribute 2. */
3792 	gl.bindBuffer(GL_ARRAY_BUFFER, m_bo[2]);
3793 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
3794 
3795 	gl.vertexAttribBinding(2, 2);
3796 	GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribBinding call failed.");
3797 
3798 	gl.vertexAttribFormat(2, 3, GL_FLOAT, GL_FALSE, 4);
3799 	GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribIFormat call failed.");
3800 
3801 	gl.bindVertexBuffer(2, m_bo[2], 8, 0);
3802 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexBuffer call failed.");
3803 
3804 	gl.enableVertexAttribArray(2);
3805 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray call failed.");
3806 
3807 	gl.vertexAttribDivisor(2, 1);
3808 	GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribDivisor call failed.");
3809 
3810 	/* Attribute 3. */
3811 	gl.bindBuffer(GL_ARRAY_BUFFER, m_bo[3]);
3812 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
3813 
3814 	gl.vertexAttribPointer(3, 4, GL_UNSIGNED_INT_2_10_10_10_REV, GL_FALSE, 8, glu::BufferOffsetAsPointer(4 * sizeof(glw::GLchar)));
3815 	GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer call failed.");
3816 
3817 	gl.enableVertexAttribArray(3);
3818 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray call failed.");
3819 
3820 	gl.vertexAttribDivisor(3, 0);
3821 	GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribDivisor call failed.");
3822 }
3823 
3824 /** @brief Compare value queried using GetVertexArrayIndexediv with expected value and log.
3825  *
3826  *  @param [in] pname        Parameter to be queried.
3827  *  @param [in] index        Index to be queried.
3828  *  @param [in] expected     Expected error.
3829  *
3830  *  @return True if value is equal to expected, false otherwise.
3831  */
Check(const glw::GLenum pname,const glw::GLuint index,const glw::GLint expected)3832 bool GetVertexArrayIndexedTest::Check(const glw::GLenum pname, const glw::GLuint index, const glw::GLint expected)
3833 {
3834 	/* Shortcut for GL functionality. */
3835 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3836 
3837 	glw::GLint result = 0;
3838 
3839 	gl.getVertexArrayIndexediv(m_vao, index, pname, &result);
3840 
3841 	if (glw::GLenum error = gl.getError())
3842 	{
3843 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "GetVertexArrayIndexediv called with index "
3844 											<< index << ", with pname" << glu::getVertexAttribParameterNameStr(pname)
3845 											<< " unexpectedly generated " << glu::getErrorStr(error)
3846 											<< "error. Test fails." << tcu::TestLog::EndMessage;
3847 
3848 		return false;
3849 	}
3850 
3851 	if (result != expected)
3852 	{
3853 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "GetVertexArrayIndexediv called with index "
3854 											<< index << " and with pname" << glu::getVertexAttribParameterNameStr(pname)
3855 											<< " returned " << result << ", but " << expected
3856 											<< " was expected. Test fails." << tcu::TestLog::EndMessage;
3857 
3858 		return false;
3859 	}
3860 
3861 	return true;
3862 }
3863 
3864 /** @brief Compare value queried using GetVertexArrayIndexed64iv with expected value and log.
3865  *
3866  *  @param [in] pname        Parameter to be queried.
3867  *  @param [in] index        Index to be queried.
3868  *  @param [in] expected     Expected error.
3869  *
3870  *  @return True if value is equal to expected, false otherwise.
3871  */
Check64(const glw::GLenum pname,const glw::GLuint index,const glw::GLint64 expected)3872 bool GetVertexArrayIndexedTest::Check64(const glw::GLenum pname, const glw::GLuint index, const glw::GLint64 expected)
3873 {
3874 	/* Shortcut for GL functionality. */
3875 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3876 
3877 	glw::GLint64 result = 0;
3878 
3879 	gl.getVertexArrayIndexed64iv(m_vao, index, pname, &result);
3880 
3881 	if (glw::GLenum error = gl.getError())
3882 	{
3883 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "GetVertexArrayIndexed64iv called with index "
3884 											<< index << ", with pname" << glu::getVertexAttribParameterNameStr(pname)
3885 											<< " unexpectedly generated " << glu::getErrorStr(error)
3886 											<< "error. Test fails." << tcu::TestLog::EndMessage;
3887 
3888 		return false;
3889 	}
3890 
3891 	if (result != expected)
3892 	{
3893 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "GetVertexArrayIndexed64iv called with index "
3894 											<< index << " and with pname" << glu::getVertexAttribParameterNameStr(pname)
3895 											<< " returned " << result << ", but " << expected
3896 											<< " was expected. Test fails." << tcu::TestLog::EndMessage;
3897 
3898 		return false;
3899 	}
3900 
3901 	return true;
3902 }
3903 
3904 /******************************** Defaults Test Implementation   ********************************/
3905 
3906 /** @brief Defaults Test constructor.
3907  *
3908  *  @param [in] context     OpenGL context.
3909  */
DefaultsTest(deqp::Context & context)3910 DefaultsTest::DefaultsTest(deqp::Context& context)
3911 	: deqp::TestCase(context, "vertex_arrays_defaults", "Defaults Test"), m_vao(0)
3912 {
3913 }
3914 
3915 /** @brief Iterate Defaults Test cases.
3916  *
3917  *  @return Iteration result.
3918  */
iterate()3919 tcu::TestNode::IterateResult DefaultsTest::iterate()
3920 {
3921 	/* Shortcut for GL functionality. */
3922 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3923 
3924 	/* Get context setup. */
3925 	bool is_at_least_gl_45 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 5)));
3926 	bool is_arb_direct_state_access = m_context.getContextInfo().isExtensionSupported("GL_ARB_direct_state_access");
3927 
3928 	if ((!is_at_least_gl_45) && (!is_arb_direct_state_access))
3929 	{
3930 		m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported");
3931 
3932 		return STOP;
3933 	}
3934 
3935 	/* Running tests. */
3936 	bool is_ok	= true;
3937 	bool is_error = false;
3938 
3939 	/* Test objects. */
3940 	glw::GLint max_attributes = 8;
3941 
3942 	try
3943 	{
3944 		/* Query limits. */
3945 		gl.getIntegerv(GL_MAX_VERTEX_ATTRIBS, &max_attributes);
3946 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed.");
3947 
3948 		/* Prepare default Vertex Array Object. */
3949 		PrepareVAO();
3950 
3951 		/* Check default values per attribute index. */
3952 		for (glw::GLint i = 0; i < max_attributes; ++i)
3953 		{
3954 			is_ok &= CheckIndexed(GL_VERTEX_ATTRIB_ARRAY_ENABLED, i, GL_FALSE);
3955 			is_ok &= CheckIndexed(GL_VERTEX_ATTRIB_ARRAY_SIZE, i, 4);
3956 			is_ok &= CheckIndexed(GL_VERTEX_ATTRIB_ARRAY_STRIDE, i, 0);
3957 			is_ok &= CheckIndexed(GL_VERTEX_ATTRIB_ARRAY_TYPE, i, GL_FLOAT);
3958 			is_ok &= CheckIndexed(GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, i, GL_FALSE);
3959 			is_ok &= CheckIndexed(GL_VERTEX_ATTRIB_ARRAY_INTEGER, i, GL_FALSE);
3960 			is_ok &= CheckIndexed(GL_VERTEX_ATTRIB_ARRAY_DIVISOR, i, 0);
3961 			is_ok &= CheckIndexed(GL_VERTEX_ATTRIB_ARRAY_LONG, i, GL_FALSE);
3962 			is_ok &= CheckIndexed(GL_VERTEX_ATTRIB_RELATIVE_OFFSET, i, 0);
3963 			is_ok &= CheckIndexed64(GL_VERTEX_BINDING_OFFSET, i, 0);
3964 		}
3965 
3966 		/* Check default values per vertex array object. */
3967 		is_ok &= Check(GL_ELEMENT_ARRAY_BUFFER_BINDING, 0);
3968 	}
3969 	catch (...)
3970 	{
3971 		is_ok	= false;
3972 		is_error = true;
3973 	}
3974 
3975 	/* Cleanup. */
3976 	if (m_vao)
3977 	{
3978 		gl.deleteVertexArrays(1, &m_vao);
3979 
3980 		m_vao = 0;
3981 	}
3982 
3983 	/* Errors clean up. */
3984 	while (gl.getError())
3985 		;
3986 
3987 	/* Result's setup. */
3988 	if (is_ok)
3989 	{
3990 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
3991 	}
3992 	else
3993 	{
3994 		if (is_error)
3995 		{
3996 			m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
3997 		}
3998 		else
3999 		{
4000 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
4001 		}
4002 	}
4003 
4004 	return STOP;
4005 }
4006 
4007 /** @brief Prepare vertex array object for the test.
4008  */
PrepareVAO()4009 void DefaultsTest::PrepareVAO()
4010 {
4011 	/* Shortcut for GL functionality. */
4012 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4013 
4014 	gl.createVertexArrays(1, &m_vao);
4015 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateVertexArrays call failed.");
4016 }
4017 
4018 /** @brief Compare value queried using GetVertexArrayiv with expected value and log.
4019  *
4020  *  @param [in] pname        Parameter to be queried.
4021  *  @param [in] expected     Expected error.
4022  *
4023  *  @return True if value is equal to expected, false otherwise.
4024  */
Check(const glw::GLenum pname,const glw::GLint expected)4025 bool DefaultsTest::Check(const glw::GLenum pname, const glw::GLint expected)
4026 {
4027 	/* Shortcut for GL functionality. */
4028 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4029 
4030 	glw::GLint result = 0;
4031 
4032 	gl.getVertexArrayiv(m_vao, pname, &result);
4033 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetVertexArrayiv call failed.");
4034 
4035 	if (result != expected)
4036 	{
4037 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Default Vertex Array Object has parameter "
4038 											<< glu::getVertexAttribParameterNameStr(pname) << " equal to " << result
4039 											<< ", but " << expected << " was expected. Test fails."
4040 											<< tcu::TestLog::EndMessage;
4041 
4042 		return false;
4043 	}
4044 
4045 	return true;
4046 }
4047 
4048 /** @brief Compare value queried using GetVertexArrayIndexediv with expected value and log.
4049  *
4050  *  @param [in] pname        Parameter to be queried.
4051  *  @param [in] index        Index to be queried.
4052  *  @param [in] expected     Expected error.
4053  *
4054  *  @return True if value is equal to expected, false otherwise.
4055  */
CheckIndexed(const glw::GLenum pname,const glw::GLuint index,const glw::GLint expected)4056 bool DefaultsTest::CheckIndexed(const glw::GLenum pname, const glw::GLuint index, const glw::GLint expected)
4057 {
4058 	/* Shortcut for GL functionality. */
4059 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4060 
4061 	glw::GLint result = 0;
4062 
4063 	gl.getVertexArrayIndexediv(m_vao, index, pname, &result);
4064 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetVertexArrayIndexediv call failed.");
4065 
4066 	if (result != expected)
4067 	{
4068 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Default Vertex Array Object at index " << index
4069 											<< " has parameter " << glu::getVertexAttribParameterNameStr(pname)
4070 											<< " equal to " << result << ", but " << expected
4071 											<< " was expected. Test fails." << tcu::TestLog::EndMessage;
4072 
4073 		return false;
4074 	}
4075 
4076 	return true;
4077 }
4078 
4079 /** @brief Compare value queried using GetVertexArrayIndexed64iv with expected value and log.
4080  *
4081  *  @param [in] pname        Parameter to be queried.
4082  *  @param [in] index        Index to be queried.
4083  *  @param [in] expected     Expected error.
4084  *
4085  *  @return True if value is equal to expected, false otherwise.
4086  */
CheckIndexed64(const glw::GLenum pname,const glw::GLuint index,const glw::GLint64 expected)4087 bool DefaultsTest::CheckIndexed64(const glw::GLenum pname, const glw::GLuint index, const glw::GLint64 expected)
4088 {
4089 	/* Shortcut for GL functionality. */
4090 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4091 
4092 	glw::GLint64 result = 0;
4093 
4094 	gl.getVertexArrayIndexed64iv(m_vao, index, pname, &result);
4095 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetVertexArrayIndexed64iv call failed.");
4096 
4097 	if (result != expected)
4098 	{
4099 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Default Vertex Array Object at index " << index
4100 											<< " has parameter " << glu::getVertexAttribParameterNameStr(pname)
4101 											<< " equal to " << result << ", but " << expected
4102 											<< " was expected. Test fails." << tcu::TestLog::EndMessage;
4103 
4104 		return false;
4105 	}
4106 
4107 	return true;
4108 }
4109 
4110 /******************************** Creation Error Test Implementation   ********************************/
4111 
4112 /** @brief Creation Error Test constructor.
4113  *
4114  *  @param [in] context     OpenGL context.
4115  */
CreationErrorTest(deqp::Context & context)4116 CreationErrorTest::CreationErrorTest(deqp::Context& context)
4117 	: deqp::TestCase(context, "vertex_arrays_creation_error", "Creation Error Test")
4118 {
4119 }
4120 
4121 /** @brief Iterate Creation Error Test cases.
4122  *
4123  *  @return Iteration result.
4124  */
iterate()4125 tcu::TestNode::IterateResult CreationErrorTest::iterate()
4126 {
4127 	/* Shortcut for GL functionality. */
4128 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4129 
4130 	/* Get context setup. */
4131 	bool is_at_least_gl_45 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 5)));
4132 	bool is_arb_direct_state_access = m_context.getContextInfo().isExtensionSupported("GL_ARB_direct_state_access");
4133 
4134 	if ((!is_at_least_gl_45) && (!is_arb_direct_state_access))
4135 	{
4136 		m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported");
4137 
4138 		return STOP;
4139 	}
4140 
4141 	/* Running tests. */
4142 	bool is_ok	= true;
4143 	bool is_error = false;
4144 
4145 	try
4146 	{
4147 		glw::GLuint negative_vao = 0;
4148 
4149 		gl.createVertexArrays(-1, &negative_vao);
4150 
4151 		is_ok = CheckError(GL_INVALID_VALUE, "INVALID_VALUE was not generated if n is negative.");
4152 	}
4153 	catch (...)
4154 	{
4155 		is_ok	= false;
4156 		is_error = true;
4157 	}
4158 
4159 	/* Errors clean up. */
4160 	while (gl.getError())
4161 		;
4162 
4163 	/* Result's setup. */
4164 	if (is_ok)
4165 	{
4166 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
4167 	}
4168 	else
4169 	{
4170 		if (is_error)
4171 		{
4172 			m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
4173 		}
4174 		else
4175 		{
4176 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
4177 		}
4178 	}
4179 
4180 	return STOP;
4181 }
4182 
4183 /** @brief Compare error returned by GL with expected value and log.
4184  *
4185  *  @param [in] expected        Expected error.
4186  *  @param [in] log_message   Message to be logged if expected error is not the equal to the reported one.
4187  *
4188  *  @return True if GL error is equal to expected, false otherwise.
4189  */
CheckError(const glw::GLenum expected,const glw::GLchar * log_message)4190 bool CreationErrorTest::CheckError(const glw::GLenum expected, const glw::GLchar* log_message)
4191 {
4192 	/* Shortcut for GL functionality. */
4193 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4194 
4195 	glw::GLenum error = 0;
4196 
4197 	if (expected != (error = gl.getError()))
4198 	{
4199 		m_context.getTestContext().getLog() << tcu::TestLog::Message << log_message << " " << glu::getErrorStr(error)
4200 											<< "was observed instead." << tcu::TestLog::EndMessage;
4201 
4202 		return false;
4203 	}
4204 
4205 	return true;
4206 }
4207 
4208 /******************************** Enable Disable Attribute Errors Test Implementation   ********************************/
4209 
4210 /** @brief Enable Disable Attribute Errors Test constructor.
4211  *
4212  *  @param [in] context     OpenGL context.
4213  */
EnableDisableAttributeErrorsTest(deqp::Context & context)4214 EnableDisableAttributeErrorsTest::EnableDisableAttributeErrorsTest(deqp::Context& context)
4215 	: deqp::TestCase(context, "vertex_arrays_enable_disable_attribute_errors", "Enable Disable Attribute Errors Test")
4216 {
4217 }
4218 
4219 /** @brief Enable Disable Attribute Errors Test cases.
4220  *
4221  *  @return Iteration result.
4222  */
iterate()4223 tcu::TestNode::IterateResult EnableDisableAttributeErrorsTest::iterate()
4224 {
4225 	/* Shortcut for GL functionality. */
4226 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4227 
4228 	/* Get context setup. */
4229 	bool is_at_least_gl_45 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 5)));
4230 	bool is_arb_direct_state_access = m_context.getContextInfo().isExtensionSupported("GL_ARB_direct_state_access");
4231 
4232 	if ((!is_at_least_gl_45) && (!is_arb_direct_state_access))
4233 	{
4234 		m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported");
4235 
4236 		return STOP;
4237 	}
4238 
4239 	/* Running tests. */
4240 	bool is_ok	= true;
4241 	bool is_error = false;
4242 
4243 	/* Test objects. */
4244 	glw::GLint max_attributes = 8;
4245 
4246 	/* Tested VAOs. */
4247 	glw::GLuint vao		  = 0;
4248 	glw::GLuint not_a_vao = 0;
4249 	try
4250 	{
4251 		/* Query limits. */
4252 		gl.getIntegerv(GL_MAX_VERTEX_ATTRIBS, &max_attributes);
4253 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed.");
4254 
4255 		/* Prepare valid VAO. */
4256 		gl.createVertexArrays(1, &vao);
4257 		GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateVertexArrays call failed.");
4258 
4259 		/* Prepare invalid VAO. */
4260 		while (gl.isVertexArray(++not_a_vao))
4261 			;
4262 
4263 		/* Test not a VAO. */
4264 		gl.enableVertexArrayAttrib(0, not_a_vao);
4265 
4266 		is_ok &= CheckError(GL_INVALID_OPERATION, "INVALID_OPERATION was not generated by EnableVertexArrayAttrib if "
4267 												  "vaobj is not the name of an existing vertex array object.");
4268 
4269 		gl.disableVertexArrayAttrib(0, not_a_vao);
4270 
4271 		is_ok &= CheckError(GL_INVALID_OPERATION, "INVALID_OPERATION was not generated by DisableVertexArrayAttrib if "
4272 												  "vaobj is not the name of an existing vertex array object.");
4273 
4274 		/* Test to big attribute index. */
4275 		gl.enableVertexArrayAttrib(max_attributes, vao);
4276 
4277 		is_ok &= CheckError(
4278 			GL_INVALID_OPERATION,
4279 			"INVALID_VALUE was not generated by EnableVertexArrayAttrib if index is equal to MAX_VERTEX_ATTRIBS.");
4280 
4281 		gl.disableVertexArrayAttrib(max_attributes, vao);
4282 
4283 		is_ok &= CheckError(
4284 			GL_INVALID_OPERATION,
4285 			"INVALID_VALUE was not generated by DisableVertexArrayAttrib if index is equal to MAX_VERTEX_ATTRIBS.");
4286 
4287 		gl.enableVertexArrayAttrib(max_attributes + 1, vao);
4288 
4289 		is_ok &= CheckError(
4290 			GL_INVALID_OPERATION,
4291 			"INVALID_VALUE was not generated by EnableVertexArrayAttrib if index is greater than MAX_VERTEX_ATTRIBS.");
4292 
4293 		gl.disableVertexArrayAttrib(max_attributes + 1, vao);
4294 
4295 		is_ok &= CheckError(
4296 			GL_INVALID_OPERATION,
4297 			"INVALID_VALUE was not generated by DisableVertexArrayAttrib if index is greater than MAX_VERTEX_ATTRIBS.");
4298 	}
4299 	catch (...)
4300 	{
4301 		is_ok	= false;
4302 		is_error = true;
4303 	}
4304 
4305 	/* Clean up. */
4306 	if (vao)
4307 	{
4308 		gl.deleteVertexArrays(1, &vao);
4309 	}
4310 
4311 	/* Errors clean up. */
4312 	while (gl.getError())
4313 		;
4314 
4315 	/* Result's setup. */
4316 	if (is_ok)
4317 	{
4318 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
4319 	}
4320 	else
4321 	{
4322 		if (is_error)
4323 		{
4324 			m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
4325 		}
4326 		else
4327 		{
4328 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
4329 		}
4330 	}
4331 
4332 	return STOP;
4333 }
4334 
4335 /** @brief Compare error returned by GL with expected value and log.
4336  *
4337  *  @param [in] expected        Expected error.
4338  *  @param [in] log_message   Message to be logged if expected error is not the equal to the reported one.
4339  *
4340  *  @return True if GL error is equal to expected, false otherwise.
4341  */
CheckError(const glw::GLenum expected,const glw::GLchar * log_message)4342 bool EnableDisableAttributeErrorsTest::CheckError(const glw::GLenum expected, const glw::GLchar* log_message)
4343 {
4344 	/* Shortcut for GL functionality. */
4345 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4346 
4347 	glw::GLenum error = 0;
4348 
4349 	if (expected != (error = gl.getError()))
4350 	{
4351 		m_context.getTestContext().getLog() << tcu::TestLog::Message << log_message << " " << glu::getErrorStr(error)
4352 											<< "was observed instead." << tcu::TestLog::EndMessage;
4353 
4354 		return false;
4355 	}
4356 
4357 	return true;
4358 }
4359 
4360 /******************************** Element Buffer Errors Test Implementation   ********************************/
4361 
4362 /** @brief Element Buffer Errors Test constructor.
4363  *
4364  *  @param [in] context     OpenGL context.
4365  */
ElementBufferErrorsTest(deqp::Context & context)4366 ElementBufferErrorsTest::ElementBufferErrorsTest(deqp::Context& context)
4367 	: deqp::TestCase(context, "vertex_arrays_element_buffer_errors", "Element Buffer Errors Test")
4368 {
4369 }
4370 
4371 /** @brief Element Buffer Errors Test cases.
4372  *
4373  *  @return Iteration result.
4374  */
iterate()4375 tcu::TestNode::IterateResult ElementBufferErrorsTest::iterate()
4376 {
4377 	/* Shortcut for GL functionality. */
4378 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4379 
4380 	/* Get context setup. */
4381 	bool is_at_least_gl_45 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 5)));
4382 	bool is_arb_direct_state_access = m_context.getContextInfo().isExtensionSupported("GL_ARB_direct_state_access");
4383 
4384 	if ((!is_at_least_gl_45) && (!is_arb_direct_state_access))
4385 	{
4386 		m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported");
4387 
4388 		return STOP;
4389 	}
4390 
4391 	/* Running tests. */
4392 	bool is_ok	= true;
4393 	bool is_error = false;
4394 
4395 	/* Tested Objects. */
4396 	glw::GLuint vao		  = 0;
4397 	glw::GLuint not_a_vao = 0;
4398 	glw::GLuint bo		  = 0;
4399 	glw::GLuint not_a_bo  = 0;
4400 
4401 	try
4402 	{
4403 		/* Prepare valid Objects. */
4404 		gl.createVertexArrays(1, &vao);
4405 		GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateVertexArrays call failed.");
4406 
4407 		gl.createBuffers(1, &bo);
4408 		GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateBuffers call failed.");
4409 
4410 		/* Prepare invalid VAO. */
4411 		while (gl.isVertexArray(++not_a_vao))
4412 			;
4413 		while (gl.isBuffer(++not_a_bo))
4414 			;
4415 
4416 		/* Test not a VAO. */
4417 		gl.vertexArrayElementBuffer(not_a_vao, bo);
4418 
4419 		is_ok &=
4420 			CheckError(GL_INVALID_OPERATION, "INVALID_OPERATION error was not generated by VertexArrayElementBuffer if "
4421 											 "vaobj is not the name of an existing vertex array object.");
4422 
4423 		/* Test not a BO. */
4424 		gl.vertexArrayElementBuffer(vao, not_a_bo);
4425 
4426 		is_ok &= CheckError(GL_INVALID_OPERATION, "INVALID_OPERATION error is generated by VertexArrayElementBuffer if "
4427 												  "buffer is not zero or the name of an existing buffer object.");
4428 	}
4429 	catch (...)
4430 	{
4431 		is_ok	= false;
4432 		is_error = true;
4433 	}
4434 
4435 	/* Clean up. */
4436 	if (vao)
4437 	{
4438 		gl.deleteVertexArrays(1, &vao);
4439 	}
4440 
4441 	if (bo)
4442 	{
4443 		gl.deleteBuffers(1, &bo);
4444 	}
4445 
4446 	/* Errors clean up. */
4447 	while (gl.getError())
4448 		;
4449 
4450 	/* Result's setup. */
4451 	if (is_ok)
4452 	{
4453 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
4454 	}
4455 	else
4456 	{
4457 		if (is_error)
4458 		{
4459 			m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
4460 		}
4461 		else
4462 		{
4463 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
4464 		}
4465 	}
4466 
4467 	return STOP;
4468 }
4469 
4470 /** @brief Compare error returned by GL with expected value and log.
4471  *
4472  *  @param [in] expected        Expected error.
4473  *  @param [in] log_message   Message to be logged if expected error is not the equal to the reported one.
4474  *
4475  *  @return True if GL error is equal to expected, false otherwise.
4476  */
CheckError(const glw::GLenum expected,const glw::GLchar * log_message)4477 bool ElementBufferErrorsTest::CheckError(const glw::GLenum expected, const glw::GLchar* log_message)
4478 {
4479 	/* Shortcut for GL functionality. */
4480 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4481 
4482 	glw::GLenum error = 0;
4483 
4484 	if (expected != (error = gl.getError()))
4485 	{
4486 		m_context.getTestContext().getLog() << tcu::TestLog::Message << log_message << " " << glu::getErrorStr(error)
4487 											<< " was observed instead." << tcu::TestLog::EndMessage;
4488 
4489 		return false;
4490 	}
4491 
4492 	return true;
4493 }
4494 
4495 /******************************** Vertex Buffers Errors Test Implementation   ********************************/
4496 
4497 /** @brief Vertex Buffers Errors Test constructor.
4498  *
4499  *  @param [in] context     OpenGL context.
4500  */
VertexBuffersErrorsTest(deqp::Context & context)4501 VertexBuffersErrorsTest::VertexBuffersErrorsTest(deqp::Context& context)
4502 	: deqp::TestCase(context, "vertex_arrays_vertex_buffers_errors", "Vertex Buffers Errors Test")
4503 {
4504 }
4505 
4506 /** @brief Vertex Buffers Errors Test cases.
4507  *
4508  *  @return Iteration result.
4509  */
iterate()4510 tcu::TestNode::IterateResult VertexBuffersErrorsTest::iterate()
4511 {
4512 	/* Shortcut for GL functionality. */
4513 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4514 
4515 	/* Get context setup. */
4516 	bool is_at_least_gl_45 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 5)));
4517 	bool is_arb_direct_state_access = m_context.getContextInfo().isExtensionSupported("GL_ARB_direct_state_access");
4518 
4519 	if ((!is_at_least_gl_45) && (!is_arb_direct_state_access))
4520 	{
4521 		m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported");
4522 
4523 		return STOP;
4524 	}
4525 
4526 	/* Running tests. */
4527 	bool is_ok	= true;
4528 	bool is_error = false;
4529 
4530 	/* Tested Objects. */
4531 	glw::GLuint vao		  = 0;
4532 	glw::GLuint not_a_vao = 0;
4533 	glw::GLuint bo		  = 0;
4534 	glw::GLuint not_a_bo  = 0;
4535 
4536 	/* Valid setup. */
4537 	glw::GLintptr valid_offset = 0;
4538 	glw::GLsizei  valid_stride = 1;
4539 
4540 	/* Limits. (Minimum values - OpenGL 4.5 Core Specification, Table 23.55) */
4541 	glw::GLint max_vertex_attrib_bindings = 16;
4542 	glw::GLint max_vertex_attrib_stride   = 2048;
4543 
4544 	try
4545 	{
4546 		/* Prepare valid Objects. */
4547 		gl.createVertexArrays(1, &vao);
4548 		GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateVertexArrays call failed.");
4549 
4550 		gl.createBuffers(1, &bo);
4551 		GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateBuffers call failed.");
4552 
4553 		/* Prepare invalid VAO. */
4554 		while (gl.isVertexArray(++not_a_vao))
4555 			;
4556 		while (gl.isBuffer(++not_a_bo))
4557 			;
4558 
4559 		/* Prepare limits. */
4560 		gl.getIntegerv(GL_MAX_VERTEX_ATTRIB_BINDINGS, &max_vertex_attrib_bindings);
4561 		gl.getIntegerv(GL_MAX_VERTEX_ATTRIB_STRIDE, &max_vertex_attrib_stride);
4562 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed.");
4563 
4564 		/* Invalid setup. */
4565 		glw::GLintptr invalid_offset   = -1;
4566 		glw::GLsizei  invalid_stride_0 = -1;
4567 		glw::GLsizei  invalid_stride_1 = max_vertex_attrib_stride + 1;
4568 
4569 		/* Test not a VAO. */
4570 		gl.vertexArrayVertexBuffer(not_a_vao, 0, bo, valid_offset, valid_stride);
4571 
4572 		is_ok &= CheckError(GL_INVALID_OPERATION, "INVALID_OPERATION was not generated by VertexArrayVertexBuffer if "
4573 												  "vaobj is not the name of an existing vertex array object.");
4574 
4575 		gl.vertexArrayVertexBuffers(not_a_vao, 0, 1, &bo, &valid_offset, &valid_stride);
4576 
4577 		is_ok &= CheckError(GL_INVALID_OPERATION, "INVALID_OPERATION was not generated by VertexArrayVertexBuffers if "
4578 												  "vaobj is not the name of an existing vertex array object.");
4579 
4580 		/* Test not a BO. */
4581 		gl.vertexArrayVertexBuffer(vao, 0, not_a_bo, valid_offset, valid_stride);
4582 
4583 		is_ok &= CheckError(GL_INVALID_OPERATION, "INVALID_OPERATION was not generated by VertexArrayVertexBuffer if "
4584 												  "vaobj is not the name of an existing vertex array object.");
4585 
4586 		gl.vertexArrayVertexBuffers(vao, 0, 1, &not_a_bo, &valid_offset, &valid_stride);
4587 
4588 		is_ok &= CheckError(GL_INVALID_OPERATION, "INVALID_OPERATION was not generated by VertexArrayVertexBuffers if "
4589 												  "vaobj is not the name of an existing vertex array object.");
4590 
4591 		/* Test too big binding index. */
4592 		gl.vertexArrayVertexBuffer(vao, max_vertex_attrib_bindings, bo, valid_offset, valid_stride);
4593 
4594 		is_ok &= CheckError(GL_INVALID_VALUE, "INVALID_VALUE was not generated by VertexArrayVertexBuffer if "
4595 											  "bindingindex is equal to the value of MAX_VERTEX_ATTRIB_BINDINGS.");
4596 
4597 		gl.vertexArrayVertexBuffer(vao, max_vertex_attrib_bindings + 1, bo, valid_offset, valid_stride);
4598 
4599 		is_ok &= CheckError(GL_INVALID_VALUE, "INVALID_VALUE was not generated by VertexArrayVertexBuffer if "
4600 											  "bindingindex is greater than the value of MAX_VERTEX_ATTRIB_BINDINGS.");
4601 
4602 		gl.vertexArrayVertexBuffers(vao, max_vertex_attrib_bindings, 1, &bo, &valid_offset, &valid_stride);
4603 
4604 		is_ok &=
4605 			CheckError(GL_INVALID_OPERATION, "INVALID_OPERATION was not generated by VertexArrayVertexBuffers if "
4606 											 "first+count is greater than the value of MAX_VERTEX_ATTRIB_BINDINGS.");
4607 
4608 		/* Test too big stride. */
4609 		gl.vertexArrayVertexBuffer(vao, 0, bo, -1, valid_stride);
4610 
4611 		is_ok &= CheckError(GL_INVALID_VALUE,
4612 							"INVALID_VALUE is generated by VertexArrayVertexBuffer if offset less than zero.");
4613 
4614 		gl.vertexArrayVertexBuffer(vao, 0, bo, valid_offset, -1);
4615 
4616 		is_ok &= CheckError(GL_INVALID_VALUE,
4617 							"INVALID_VALUE is generated by VertexArrayVertexBuffer if stride is less than zero.");
4618 
4619 		gl.vertexArrayVertexBuffer(vao, 0, bo, valid_offset, max_vertex_attrib_stride + 1);
4620 
4621 		is_ok &= CheckError(GL_INVALID_VALUE, "INVALID_VALUE is generated by VertexArrayVertexBuffer if stride is "
4622 											  "greater than the value of MAX_VERTEX_ATTRIB_STRIDE.");
4623 
4624 		gl.vertexArrayVertexBuffers(vao, 0, 1, &bo, &invalid_offset, &valid_stride);
4625 
4626 		is_ok &=
4627 			CheckError(GL_INVALID_VALUE,
4628 					   "INVALID_VALUE is generated by VertexArrayVertexBuffers if any value in offsets is negative.");
4629 
4630 		gl.vertexArrayVertexBuffers(vao, 0, 1, &bo, &valid_offset, &invalid_stride_0);
4631 
4632 		is_ok &=
4633 			CheckError(GL_INVALID_VALUE,
4634 					   "INVALID_VALUE is generated by VertexArrayVertexBuffers if any value in strides is negative.");
4635 
4636 		gl.vertexArrayVertexBuffers(vao, 0, 1, &bo, &valid_offset, &invalid_stride_1);
4637 
4638 		is_ok &= CheckError(GL_INVALID_VALUE, "INVALID_VALUE is generated by VertexArrayVertexBuffers if a value in "
4639 											  "strides is greater than the value of MAX_VERTEX_ATTRIB_STRIDE.");
4640 	}
4641 	catch (...)
4642 	{
4643 		is_ok	= false;
4644 		is_error = true;
4645 	}
4646 
4647 	/* Clean up. */
4648 	if (vao)
4649 	{
4650 		gl.deleteVertexArrays(1, &vao);
4651 	}
4652 
4653 	if (bo)
4654 	{
4655 		gl.deleteBuffers(1, &bo);
4656 	}
4657 
4658 	/* Errors clean up. */
4659 	while (gl.getError())
4660 		;
4661 
4662 	/* Result's setup. */
4663 	if (is_ok)
4664 	{
4665 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
4666 	}
4667 	else
4668 	{
4669 		if (is_error)
4670 		{
4671 			m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
4672 		}
4673 		else
4674 		{
4675 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
4676 		}
4677 	}
4678 
4679 	return STOP;
4680 }
4681 
4682 /** @brief Compare error returned by GL with expected value and log.
4683  *
4684  *  @param [in] expected        Expected error.
4685  *  @param [in] log_message   Message to be logged if expected error is not the equal to the reported one.
4686  *
4687  *  @return True if GL error is equal to expected, false otherwise.
4688  */
CheckError(const glw::GLenum expected,const glw::GLchar * log_message)4689 bool VertexBuffersErrorsTest::CheckError(const glw::GLenum expected, const glw::GLchar* log_message)
4690 {
4691 	/* Shortcut for GL functionality. */
4692 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4693 
4694 	glw::GLenum error = 0;
4695 
4696 	if (expected != (error = gl.getError()))
4697 	{
4698 		m_context.getTestContext().getLog() << tcu::TestLog::Message << log_message << " " << glu::getErrorStr(error)
4699 											<< " was observed instead." << tcu::TestLog::EndMessage;
4700 
4701 		return false;
4702 	}
4703 
4704 	return true;
4705 }
4706 
4707 /******************************** Attribute Format Errors Test Implementation   ********************************/
4708 
4709 /** @brief Attribute Format Errors Test constructor.
4710  *
4711  *  @param [in] context     OpenGL context.
4712  */
AttributeFormatErrorsTest(deqp::Context & context)4713 AttributeFormatErrorsTest::AttributeFormatErrorsTest(deqp::Context& context)
4714 	: deqp::TestCase(context, "vertex_arrays_attribute_format_errors", "Attribute Format Errors Test")
4715 {
4716 }
4717 
4718 /** @brief Attribute Format Errors Test cases.
4719  *
4720  *  @return Iteration result.
4721  */
iterate()4722 tcu::TestNode::IterateResult AttributeFormatErrorsTest::iterate()
4723 {
4724 	/* Shortcut for GL functionality. */
4725 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4726 
4727 	/* Get context setup. */
4728 	bool is_at_least_gl_45 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 5)));
4729 	bool is_arb_direct_state_access = m_context.getContextInfo().isExtensionSupported("GL_ARB_direct_state_access");
4730 
4731 	if ((!is_at_least_gl_45) && (!is_arb_direct_state_access))
4732 	{
4733 		m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported");
4734 
4735 		return STOP;
4736 	}
4737 
4738 	/* Running tests. */
4739 	bool is_ok	= true;
4740 	bool is_error = false;
4741 
4742 	/* Tested Objects. */
4743 	glw::GLuint vao		  = 0;
4744 	glw::GLuint not_a_vao = 0;
4745 
4746 	/* Limits. (Minimum values - OpenGL 4.5 Core Specification, Table 23.55) */
4747 	glw::GLint max_vertex_attribs				 = 16;
4748 	glw::GLint max_vertex_attrib_relative_offset = 2047;
4749 
4750 	/* Invalid values. */
4751 	glw::GLenum bad_type = 0;
4752 
4753 	static const glw::GLenum accepted_types[] = { GL_BYTE,
4754 												  GL_SHORT,
4755 												  GL_INT,
4756 												  GL_FIXED,
4757 												  GL_FLOAT,
4758 												  GL_HALF_FLOAT,
4759 												  GL_DOUBLE,
4760 												  GL_UNSIGNED_BYTE,
4761 												  GL_UNSIGNED_SHORT,
4762 												  GL_UNSIGNED_INT,
4763 												  GL_INT_2_10_10_10_REV,
4764 												  GL_UNSIGNED_INT_2_10_10_10_REV,
4765 												  GL_UNSIGNED_INT_10F_11F_11F_REV };
4766 
4767 	{
4768 		bool is_accepted_type = true;
4769 		while (is_accepted_type)
4770 		{
4771 			bad_type++;
4772 			is_accepted_type = false;
4773 			for (glw::GLuint i = 0; i < DE_LENGTH_OF_ARRAY(accepted_types); ++i)
4774 			{
4775 				if (accepted_types[i] == bad_type)
4776 				{
4777 					is_accepted_type = true;
4778 					break;
4779 				}
4780 			}
4781 		}
4782 	}
4783 
4784 	try
4785 	{
4786 		/* Prepare valid Objects. */
4787 		gl.createVertexArrays(1, &vao);
4788 		GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateVertexArrays call failed.");
4789 
4790 		/* Prepare invalid VAO. */
4791 		while (gl.isVertexArray(++not_a_vao))
4792 			;
4793 
4794 		/* Prepare limits. */
4795 		gl.getIntegerv(GL_MAX_VERTEX_ATTRIBS, &max_vertex_attribs);
4796 		gl.getIntegerv(GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET, &max_vertex_attrib_relative_offset);
4797 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed.");
4798 
4799 		/* TESTS OF VERTEXARRAYATTRIBFORMAT */
4800 
4801 		/* MAX_VERTEX_ATTRIBS < */
4802 		gl.vertexArrayAttribFormat(vao, max_vertex_attribs, 1, GL_BYTE, GL_FALSE, 0);
4803 
4804 		is_ok &= CheckError(GL_INVALID_VALUE, "INVALID_VALUE was not generated by VertexArrayAttribFormat if "
4805 											  "attribindex is equal to the value of MAX_VERTEX_ATTRIBS.");
4806 
4807 		gl.vertexArrayAttribFormat(vao, max_vertex_attribs + 1, 1, GL_BYTE, GL_FALSE, 0);
4808 
4809 		is_ok &= CheckError(GL_INVALID_VALUE, "INVALID_VALUE was not generated by VertexArrayAttribFormat if "
4810 											  "attribindex is greater than the value of MAX_VERTEX_ATTRIBS.");
4811 
4812 		gl.vertexArrayAttribIFormat(vao, max_vertex_attribs, 1, GL_BYTE, 0);
4813 
4814 		is_ok &= CheckError(GL_INVALID_VALUE, "INVALID_VALUE was not generated by VertexArrayAttribIFormat if "
4815 											  "attribindex is equal to the value of MAX_VERTEX_ATTRIBS.");
4816 
4817 		gl.vertexArrayAttribIFormat(vao, max_vertex_attribs + 1, 1, GL_BYTE, 0);
4818 
4819 		is_ok &= CheckError(GL_INVALID_VALUE, "INVALID_VALUE was not generated by VertexArrayAttribIFormat if "
4820 											  "attribindex is greater than the value of MAX_VERTEX_ATTRIBS.");
4821 
4822 		gl.vertexArrayAttribLFormat(vao, max_vertex_attribs, 1, GL_DOUBLE, 0);
4823 
4824 		is_ok &= CheckError(GL_INVALID_VALUE, "INVALID_VALUE was not generated by VertexArrayAttribLFormat if "
4825 											  "attribindex is equal to the value of MAX_VERTEX_ATTRIBS.");
4826 
4827 		gl.vertexArrayAttribLFormat(vao, max_vertex_attribs + 1, 1, GL_DOUBLE, 0);
4828 
4829 		is_ok &= CheckError(GL_INVALID_VALUE, "INVALID_VALUE was not generated by VertexArrayAttribLFormat if "
4830 											  "attribindex is greater than the value of MAX_VERTEX_ATTRIBS.");
4831 
4832 		/* size */
4833 		gl.vertexArrayAttribFormat(vao, 0, 0, GL_BYTE, GL_FALSE, 0);
4834 
4835 		is_ok &= CheckError(GL_INVALID_VALUE, "INVALID_VALUE was not generated by VertexArrayAttrib*Format if size is "
4836 											  "not one of the accepted values (0).");
4837 
4838 		gl.vertexArrayAttribFormat(vao, 0, 5, GL_BYTE, GL_FALSE, 0);
4839 
4840 		is_ok &= CheckError(GL_INVALID_VALUE, "INVALID_VALUE was not generated by VertexArrayAttrib*Format if size is "
4841 											  "not one of the accepted values (5).");
4842 
4843 		gl.vertexArrayAttribIFormat(vao, 0, 0, GL_BYTE, 0);
4844 
4845 		is_ok &= CheckError(GL_INVALID_VALUE, "INVALID_VALUE was not generated by VertexArrayAttribIFormat if size is "
4846 											  "not one of the accepted values (0).");
4847 
4848 		gl.vertexArrayAttribIFormat(vao, 0, 5, GL_BYTE, 0);
4849 
4850 		is_ok &= CheckError(GL_INVALID_VALUE, "INVALID_VALUE was not generated by VertexArrayAttribIFormat if size is "
4851 											  "not one of the accepted values (5).");
4852 
4853 		gl.vertexArrayAttribLFormat(vao, 0, 0, GL_DOUBLE, 0);
4854 
4855 		is_ok &= CheckError(GL_INVALID_VALUE, "INVALID_VALUE was not generated by VertexArrayAttribLFormat if size is "
4856 											  "not one of the accepted values (0).");
4857 
4858 		gl.vertexArrayAttribLFormat(vao, 0, 5, GL_DOUBLE, 0);
4859 
4860 		is_ok &= CheckError(GL_INVALID_VALUE, "INVALID_VALUE was not generated by VertexArrayAttribLFormat if size is "
4861 											  "not one of the accepted values (5).");
4862 
4863 		/* relative offset */
4864 		gl.vertexArrayAttribFormat(vao, 0, 1, GL_BYTE, GL_FALSE, max_vertex_attrib_relative_offset + 1);
4865 
4866 		is_ok &= CheckError(GL_INVALID_VALUE, "INVALID_VALUE was not generated by VertexArrayAttrib*Format if "
4867 											  "relativeoffset is greater than the value of "
4868 											  "MAX_VERTEX_ATTRIB_RELATIVE_OFFSET.");
4869 
4870 		gl.vertexArrayAttribIFormat(vao, 0, 1, GL_BYTE, max_vertex_attrib_relative_offset + 1);
4871 
4872 		is_ok &= CheckError(GL_INVALID_VALUE, "INVALID_VALUE was not generated by VertexArrayAttribIFormat if "
4873 											  "relativeoffset is greater than the value of "
4874 											  "MAX_VERTEX_ATTRIB_RELATIVE_OFFSET.");
4875 
4876 		gl.vertexArrayAttribLFormat(vao, 0, 1, GL_DOUBLE, max_vertex_attrib_relative_offset + 1);
4877 
4878 		is_ok &= CheckError(GL_INVALID_VALUE, "INVALID_VALUE was not generated by VertexArrayAttribLFormat if "
4879 											  "relativeoffset is greater than the value of "
4880 											  "MAX_VERTEX_ATTRIB_RELATIVE_OFFSET.");
4881 
4882 		/* type */
4883 		gl.vertexArrayAttribFormat(vao, 0, 1, bad_type, GL_FALSE, 0);
4884 
4885 		is_ok &= CheckError(
4886 			GL_INVALID_ENUM,
4887 			"INVALID_ENUM was not generated by VertexArrayAttribFormat if type is not one of the accepted tokens.");
4888 
4889 		gl.vertexArrayAttribIFormat(vao, 0, 1, bad_type, 0);
4890 
4891 		is_ok &= CheckError(
4892 			GL_INVALID_ENUM,
4893 			"INVALID_ENUM was not generated by VertexArrayAttribIFormat if type is not one of the accepted tokens.");
4894 
4895 		gl.vertexArrayAttribLFormat(vao, 0, 1, bad_type, 0);
4896 
4897 		is_ok &= CheckError(
4898 			GL_INVALID_ENUM,
4899 			"INVALID_ENUM was not generated by VertexArrayAttribLFormat if type is not one of the accepted tokens.");
4900 
4901 		/* type UNSIGNED_INT_10F_11F_11F_REV case */
4902 		gl.vertexArrayAttribIFormat(vao, 0, 1, GL_UNSIGNED_INT_10F_11F_11F_REV, 0);
4903 
4904 		is_ok &= CheckError(
4905 			GL_INVALID_ENUM,
4906 			"INVALID_ENUM was not generated by VertexArrayAttribIFormat if type is UNSIGNED_INT_10F_11F_11F_REV.");
4907 
4908 		gl.vertexArrayAttribLFormat(vao, 0, 1, GL_UNSIGNED_INT_10F_11F_11F_REV, 0);
4909 
4910 		is_ok &= CheckError(
4911 			GL_INVALID_ENUM,
4912 			"INVALID_ENUM was not generated by VertexArrayAttribLFormat if type is UNSIGNED_INT_10F_11F_11F_REV.");
4913 
4914 		/* Test not a VAO. */
4915 		gl.vertexArrayAttribFormat(not_a_vao, 0, 1, GL_BYTE, GL_FALSE, 0);
4916 
4917 		is_ok &= CheckError(GL_INVALID_OPERATION, "INVALID_OPERATION was not generated by VertexArrayAttribFormat if "
4918 												  "vaobj is not the name of an existing vertex array object.");
4919 
4920 		gl.vertexArrayAttribIFormat(not_a_vao, 0, 1, GL_BYTE, 0);
4921 
4922 		is_ok &= CheckError(GL_INVALID_OPERATION, "INVALID_OPERATION was not generated by VertexArrayAttribIFormat if "
4923 												  "vaobj is not the name of an existing vertex array object.");
4924 
4925 		gl.vertexArrayAttribLFormat(not_a_vao, 0, 1, GL_DOUBLE, 0);
4926 
4927 		is_ok &= CheckError(GL_INVALID_OPERATION, "INVALID_OPERATION was not generated by VertexArrayAttribLFormat if "
4928 												  "vaobj is not the name of an existing vertex array object.");
4929 
4930 		/* BGRA */
4931 		gl.vertexArrayAttribFormat(vao, 0, GL_BGRA, GL_BYTE, GL_TRUE, 0);
4932 
4933 		is_ok &= CheckError(GL_INVALID_OPERATION, "INVALID_OPERATION was not generated by VertexArrayAttribFormat if "
4934 												  "size is BGRA and type is not UNSIGNED_BYTE, INT_2_10_10_10_REV or "
4935 												  "UNSIGNED_INT_2_10_10_10_REV.");
4936 
4937 		gl.vertexArrayAttribFormat(vao, 0, 1, GL_INT_2_10_10_10_REV, GL_TRUE, 0);
4938 
4939 		is_ok &= CheckError(GL_INVALID_OPERATION, "INVALID_OPERATION was not generated by VertexArrayAttribFormat if "
4940 												  "type is INT_2_10_10_10_REV and size is neither 4 nor BGRA.");
4941 
4942 		gl.vertexArrayAttribFormat(vao, 0, 1, GL_UNSIGNED_INT_2_10_10_10_REV, GL_TRUE, 0);
4943 
4944 		is_ok &=
4945 			CheckError(GL_INVALID_OPERATION, "INVALID_OPERATION was not generated by VertexArrayAttribFormat if type "
4946 											 "is UNSIGNED_INT_2_10_10_10_REV and size is neither 4 nor BGRA.");
4947 
4948 		gl.vertexArrayAttribFormat(vao, 0, 1, GL_UNSIGNED_INT_10F_11F_11F_REV, GL_TRUE, 0);
4949 
4950 		is_ok &= CheckError(GL_INVALID_OPERATION, "INVALID_OPERATION was not generated by VertexArrayAttribFormat if "
4951 												  "type is UNSIGNED_INT_10F_11F_11F_REV and size is not 3.");
4952 
4953 		gl.vertexArrayAttribFormat(vao, 0, GL_BGRA, GL_UNSIGNED_BYTE, GL_FALSE, 0);
4954 
4955 		is_ok &= CheckError(
4956 			GL_INVALID_OPERATION,
4957 			"INVALID_OPERATION was not generated by VertexArrayAttribFormat if size is BGRA and normalized is FALSE.");
4958 	}
4959 	catch (...)
4960 	{
4961 		is_ok	= false;
4962 		is_error = true;
4963 	}
4964 
4965 	/* Clean up. */
4966 	if (vao)
4967 	{
4968 		gl.deleteVertexArrays(1, &vao);
4969 	}
4970 
4971 	/* Errors clean up. */
4972 	while (gl.getError())
4973 		;
4974 
4975 	/* Result's setup. */
4976 	if (is_ok)
4977 	{
4978 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
4979 	}
4980 	else
4981 	{
4982 		if (is_error)
4983 		{
4984 			m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
4985 		}
4986 		else
4987 		{
4988 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
4989 		}
4990 	}
4991 
4992 	return STOP;
4993 }
4994 
4995 /** @brief Compare error returned by GL with expected value and log.
4996  *
4997  *  @param [in] expected        Expected error.
4998  *  @param [in] log_message   Message to be logged if expected error is not the equal to the reported one.
4999  *
5000  *  @return True if GL error is equal to expected, false otherwise.
5001  */
CheckError(const glw::GLenum expected,const glw::GLchar * log_message)5002 bool AttributeFormatErrorsTest::CheckError(const glw::GLenum expected, const glw::GLchar* log_message)
5003 {
5004 	/* Shortcut for GL functionality. */
5005 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5006 
5007 	glw::GLenum error = 0;
5008 
5009 	if (expected != (error = gl.getError()))
5010 	{
5011 		m_context.getTestContext().getLog() << tcu::TestLog::Message << log_message << " " << glu::getErrorStr(error)
5012 											<< " was observed instead." << tcu::TestLog::EndMessage;
5013 
5014 		return false;
5015 	}
5016 
5017 	return true;
5018 }
5019 
5020 /******************************** Attribute Binding Errors Test Implementation   ********************************/
5021 
5022 /** @brief Attribute Binding Errors Test constructor.
5023  *
5024  *  @param [in] context     OpenGL context.
5025  */
AttributeBindingErrorsTest(deqp::Context & context)5026 AttributeBindingErrorsTest::AttributeBindingErrorsTest(deqp::Context& context)
5027 	: deqp::TestCase(context, "vertex_arrays_attribute_binding_errors", "Attribute Binding Errors Test")
5028 {
5029 }
5030 
5031 /** @brief Attribute Binding Errors Test cases.
5032  *
5033  *  @return Iteration result.
5034  */
iterate()5035 tcu::TestNode::IterateResult AttributeBindingErrorsTest::iterate()
5036 {
5037 	/* Shortcut for GL functionality. */
5038 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5039 
5040 	/* Get context setup. */
5041 	bool is_at_least_gl_45 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 5)));
5042 	bool is_arb_direct_state_access = m_context.getContextInfo().isExtensionSupported("GL_ARB_direct_state_access");
5043 
5044 	if ((!is_at_least_gl_45) && (!is_arb_direct_state_access))
5045 	{
5046 		m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported");
5047 
5048 		return STOP;
5049 	}
5050 
5051 	/* Running tests. */
5052 	bool is_ok	= true;
5053 	bool is_error = false;
5054 
5055 	/* Tested Objects. */
5056 	glw::GLuint vao		  = 0;
5057 	glw::GLuint not_a_vao = 0;
5058 
5059 	/* Limits. (Minimum values - OpenGL 4.5 Core Specification, Table 23.55) */
5060 	glw::GLint max_vertex_attribs		  = 16;
5061 	glw::GLint max_vertex_attrib_bindings = 16;
5062 
5063 	try
5064 	{
5065 		/* Prepare valid Objects. */
5066 		gl.createVertexArrays(1, &vao);
5067 		GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateVertexArrays call failed.");
5068 
5069 		/* Prepare invalid VAO. */
5070 		while (gl.isVertexArray(++not_a_vao))
5071 			;
5072 
5073 		/* Prepare limits. */
5074 		gl.getIntegerv(GL_MAX_VERTEX_ATTRIBS, &max_vertex_attribs);
5075 		gl.getIntegerv(GL_MAX_VERTEX_ATTRIB_BINDINGS, &max_vertex_attrib_bindings);
5076 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed.");
5077 
5078 		/* Not a VAO. */
5079 		gl.vertexArrayAttribBinding(not_a_vao, 0, 0);
5080 
5081 		is_ok &= CheckError(GL_INVALID_OPERATION, "INVALID_OPERATION was not generated by VertexArrayAttribBinding if "
5082 												  "vaobj is not the name of an existing vertex array object.");
5083 
5084 		/* Too big attribute index. */
5085 		gl.vertexArrayAttribBinding(vao, max_vertex_attribs, 0);
5086 
5087 		is_ok &= CheckError(GL_INVALID_VALUE, "INVALID_VALUE was not generated by VertexArrayAttribBinding if "
5088 											  "attribindex is equal to the value of MAX_VERTEX_ATTRIBS.");
5089 
5090 		gl.vertexArrayAttribBinding(vao, max_vertex_attribs + 1, 0);
5091 
5092 		is_ok &= CheckError(GL_INVALID_VALUE, "INVALID_VALUE was not generated by VertexArrayAttribBinding if "
5093 											  "attribindex is greater than the value of MAX_VERTEX_ATTRIBS.");
5094 
5095 		/* Too big binding index. */
5096 		gl.vertexArrayAttribBinding(vao, 0, max_vertex_attrib_bindings);
5097 
5098 		is_ok &= CheckError(GL_INVALID_VALUE, "INVALID_VALUE was not generated by VertexArrayAttribBinding if "
5099 											  "bindingindex is equal to the value of MAX_VERTEX_ATTRIB_BINDINGS.");
5100 
5101 		gl.vertexArrayAttribBinding(vao, 0, max_vertex_attrib_bindings + 1);
5102 
5103 		is_ok &= CheckError(GL_INVALID_VALUE, "INVALID_VALUE was not generated by VertexArrayAttribBinding if "
5104 											  "bindingindex is greater than the value of MAX_VERTEX_ATTRIB_BINDINGS.");
5105 	}
5106 	catch (...)
5107 	{
5108 		is_ok	= false;
5109 		is_error = true;
5110 	}
5111 
5112 	/* Clean up. */
5113 	if (vao)
5114 	{
5115 		gl.deleteVertexArrays(1, &vao);
5116 	}
5117 
5118 	/* Errors clean up. */
5119 	while (gl.getError())
5120 		;
5121 
5122 	/* Result's setup. */
5123 	if (is_ok)
5124 	{
5125 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
5126 	}
5127 	else
5128 	{
5129 		if (is_error)
5130 		{
5131 			m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
5132 		}
5133 		else
5134 		{
5135 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
5136 		}
5137 	}
5138 
5139 	return STOP;
5140 }
5141 
5142 /** @brief Compare error returned by GL with expected value and log.
5143  *
5144  *  @param [in] expected        Expected error.
5145  *  @param [in] log_message   Message to be logged if expected error is not the equal to the reported one.
5146  *
5147  *  @return True if GL error is equal to expected, false otherwise.
5148  */
CheckError(const glw::GLenum expected,const glw::GLchar * log_message)5149 bool AttributeBindingErrorsTest::CheckError(const glw::GLenum expected, const glw::GLchar* log_message)
5150 {
5151 	/* Shortcut for GL functionality. */
5152 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5153 
5154 	glw::GLenum error = 0;
5155 
5156 	if (expected != (error = gl.getError()))
5157 	{
5158 		m_context.getTestContext().getLog() << tcu::TestLog::Message << log_message << " " << glu::getErrorStr(error)
5159 											<< " was observed instead." << tcu::TestLog::EndMessage;
5160 
5161 		return false;
5162 	}
5163 
5164 	return true;
5165 }
5166 
5167 /******************************** Attribute Binding Divisor Errors Test Implementation   ********************************/
5168 
5169 /** @brief Attribute Binding Divisor Errors Test constructor.
5170  *
5171  *  @param [in] context     OpenGL context.
5172  */
AttributeBindingDivisorErrorsTest(deqp::Context & context)5173 AttributeBindingDivisorErrorsTest::AttributeBindingDivisorErrorsTest(deqp::Context& context)
5174 	: deqp::TestCase(context, "vertex_arrays_attribute_binding_divisor_errors", "Attribute Binding Divisor Errors Test")
5175 {
5176 }
5177 
5178 /** @brief Attribute Binding Divisor Errors Test cases.
5179  *
5180  *  @return Iteration result.
5181  */
iterate()5182 tcu::TestNode::IterateResult AttributeBindingDivisorErrorsTest::iterate()
5183 {
5184 	/* Shortcut for GL functionality. */
5185 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5186 
5187 	/* Get context setup. */
5188 	bool is_at_least_gl_45 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 5)));
5189 	bool is_arb_direct_state_access = m_context.getContextInfo().isExtensionSupported("GL_ARB_direct_state_access");
5190 
5191 	if ((!is_at_least_gl_45) && (!is_arb_direct_state_access))
5192 	{
5193 		m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported");
5194 
5195 		return STOP;
5196 	}
5197 
5198 	/* Running tests. */
5199 	bool is_ok	= true;
5200 	bool is_error = false;
5201 
5202 	/* Tested Objects. */
5203 	glw::GLuint vao		  = 0;
5204 	glw::GLuint not_a_vao = 0;
5205 
5206 	/* Limits. (Minimum values - OpenGL 4.5 Core Specification, Table 23.55) */
5207 	glw::GLint max_vertex_attrib_bindings = 16;
5208 
5209 	try
5210 	{
5211 		/* Prepare valid Objects. */
5212 		gl.createVertexArrays(1, &vao);
5213 		GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateVertexArrays call failed.");
5214 
5215 		/* Prepare invalid VAO. */
5216 		while (gl.isVertexArray(++not_a_vao))
5217 			;
5218 
5219 		/* Prepare limits. */
5220 		gl.getIntegerv(GL_MAX_VERTEX_ATTRIB_BINDINGS, &max_vertex_attrib_bindings);
5221 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed.");
5222 
5223 		/* Not a VAO. */
5224 		gl.vertexArrayBindingDivisor(not_a_vao, 0, 0);
5225 
5226 		is_ok &= CheckError(GL_INVALID_OPERATION, "INVALID_OPERATION was not generated by VertexArrayBindingDivisor if "
5227 												  "vaobj is not the name of an existing vertex array object.");
5228 
5229 		/* Too big binding index. */
5230 		gl.vertexArrayBindingDivisor(vao, max_vertex_attrib_bindings, 0);
5231 
5232 		is_ok &= CheckError(GL_INVALID_VALUE, "INVALID_VALUE was not generated by VertexArrayBindingDivisor if "
5233 											  "bindingindex is equal to the value of MAX_VERTEX_ATTRIB_BINDINGS.");
5234 
5235 		gl.vertexArrayBindingDivisor(vao, max_vertex_attrib_bindings + 1, 0);
5236 
5237 		is_ok &= CheckError(GL_INVALID_VALUE, "INVALID_VALUE was not generated by VertexArrayBindingDivisor if "
5238 											  "bindingindex is greater than the value of MAX_VERTEX_ATTRIB_BINDINGS.");
5239 	}
5240 	catch (...)
5241 	{
5242 		is_ok	= false;
5243 		is_error = true;
5244 	}
5245 
5246 	/* Clean up. */
5247 	if (vao)
5248 	{
5249 		gl.deleteVertexArrays(1, &vao);
5250 	}
5251 
5252 	/* Errors clean up. */
5253 	while (gl.getError())
5254 		;
5255 
5256 	/* Result's setup. */
5257 	if (is_ok)
5258 	{
5259 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
5260 	}
5261 	else
5262 	{
5263 		if (is_error)
5264 		{
5265 			m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
5266 		}
5267 		else
5268 		{
5269 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
5270 		}
5271 	}
5272 
5273 	return STOP;
5274 }
5275 
5276 /** @brief Compare error returned by GL with expected value and log.
5277  *
5278  *  @param [in] expected        Expected error.
5279  *  @param [in] log_message   Message to be logged if expected error is not the equal to the reported one.
5280  *
5281  *  @return True if GL error is equal to expected, false otherwise.
5282  */
CheckError(const glw::GLenum expected,const glw::GLchar * log_message)5283 bool AttributeBindingDivisorErrorsTest::CheckError(const glw::GLenum expected, const glw::GLchar* log_message)
5284 {
5285 	/* Shortcut for GL functionality. */
5286 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5287 
5288 	glw::GLenum error = 0;
5289 
5290 	if (expected != (error = gl.getError()))
5291 	{
5292 		m_context.getTestContext().getLog() << tcu::TestLog::Message << log_message << " " << glu::getErrorStr(error)
5293 											<< " was observed instead." << tcu::TestLog::EndMessage;
5294 
5295 		return false;
5296 	}
5297 
5298 	return true;
5299 }
5300 
5301 /******************************** Get Vertex Array Errors Test Implementation   ********************************/
5302 
5303 /** @brief Get Vertex Array Errors Test constructor.
5304  *
5305  *  @param [in] context     OpenGL context.
5306  */
GetVertexArrayErrorsTest(deqp::Context & context)5307 GetVertexArrayErrorsTest::GetVertexArrayErrorsTest(deqp::Context& context)
5308 	: deqp::TestCase(context, "vertex_arrays_get_vertex_array_errors", "Get Vertex Array Errors Test")
5309 {
5310 }
5311 
5312 /** @brief Iterate over Get Vertex Array Errors Test cases.
5313  *
5314  *  @return Iteration result.
5315  */
iterate()5316 tcu::TestNode::IterateResult GetVertexArrayErrorsTest::iterate()
5317 {
5318 	/* Shortcut for GL functionality. */
5319 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5320 
5321 	/* Get context setup. */
5322 	bool is_at_least_gl_45 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 5)));
5323 	bool is_arb_direct_state_access = m_context.getContextInfo().isExtensionSupported("GL_ARB_direct_state_access");
5324 
5325 	if ((!is_at_least_gl_45) && (!is_arb_direct_state_access))
5326 	{
5327 		m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported");
5328 
5329 		return STOP;
5330 	}
5331 
5332 	/* Running tests. */
5333 	bool is_ok	= true;
5334 	bool is_error = false;
5335 
5336 	/* Tested Objects. */
5337 	glw::GLuint vao		  = 0;
5338 	glw::GLuint not_a_vao = 0;
5339 
5340 	glw::GLint storage = 0;
5341 
5342 	try
5343 	{
5344 		/* Prepare valid Objects. */
5345 		gl.createVertexArrays(1, &vao);
5346 		GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateVertexArrays call failed.");
5347 
5348 		/* Prepare invalid VAO. */
5349 		while (gl.isVertexArray(++not_a_vao))
5350 			;
5351 
5352 		/* Not a VAO. */
5353 		gl.getVertexArrayiv(not_a_vao, GL_ELEMENT_ARRAY_BUFFER_BINDING, &storage);
5354 
5355 		is_ok &= CheckError(GL_INVALID_OPERATION, "INVALID_OPERATION error was not generated by GetVertexArrayiv if "
5356 												  "vaobj is not the name of an existing vertex array object.");
5357 
5358 		/* Bad parameter. */
5359 		gl.getVertexArrayiv(vao, GL_ELEMENT_ARRAY_BUFFER_BINDING + 1, &storage);
5360 
5361 		is_ok &= CheckError(
5362 			GL_INVALID_ENUM,
5363 			"INVALID_ENUM error was not generated by GetVertexArrayiv if pname is not ELEMENT_ARRAY_BUFFER_BINDING.");
5364 	}
5365 	catch (...)
5366 	{
5367 		is_ok	= false;
5368 		is_error = true;
5369 	}
5370 
5371 	/* Clean up. */
5372 	if (vao)
5373 	{
5374 		gl.deleteVertexArrays(1, &vao);
5375 	}
5376 
5377 	/* Errors clean up. */
5378 	while (gl.getError())
5379 		;
5380 
5381 	/* Result's setup. */
5382 	if (is_ok)
5383 	{
5384 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
5385 	}
5386 	else
5387 	{
5388 		if (is_error)
5389 		{
5390 			m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
5391 		}
5392 		else
5393 		{
5394 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
5395 		}
5396 	}
5397 
5398 	return STOP;
5399 }
5400 
5401 /** @brief Compare error returned by GL with expected value and log.
5402  *
5403  *  @param [in] expected        Expected error.
5404  *  @param [in] log_message   Message to be logged if expected error is not the equal to the reported one.
5405  *
5406  *  @return True if GL error is equal to expected, false otherwise.
5407  */
CheckError(const glw::GLenum expected,const glw::GLchar * log_message)5408 bool GetVertexArrayErrorsTest::CheckError(const glw::GLenum expected, const glw::GLchar* log_message)
5409 {
5410 	/* Shortcut for GL functionality. */
5411 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5412 
5413 	glw::GLenum error = 0;
5414 
5415 	if (expected != (error = gl.getError()))
5416 	{
5417 		m_context.getTestContext().getLog() << tcu::TestLog::Message << log_message << " " << glu::getErrorStr(error)
5418 											<< " was observed instead." << tcu::TestLog::EndMessage;
5419 
5420 		return false;
5421 	}
5422 
5423 	return true;
5424 }
5425 
5426 /******************************** Get Vertex Array Indexed Errors Test Implementation   ********************************/
5427 
5428 /** @brief Get Vertex Array Indexed Errors Test constructor.
5429  *
5430  *  @param [in] context     OpenGL context.
5431  */
GetVertexArrayIndexedErrorsTest(deqp::Context & context)5432 GetVertexArrayIndexedErrorsTest::GetVertexArrayIndexedErrorsTest(deqp::Context& context)
5433 	: deqp::TestCase(context, "vertex_arrays_get_vertex_array_indexed_errors", "Get Vertex Array Indexed Errors Test")
5434 {
5435 }
5436 
5437 /** @brief Iterate over Get Vertex Array Indexed Errors Test cases.
5438  *
5439  *  @return Iteration result.
5440  */
iterate()5441 tcu::TestNode::IterateResult GetVertexArrayIndexedErrorsTest::iterate()
5442 {
5443 	/* Shortcut for GL functionality. */
5444 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5445 
5446 	/* Get context setup. */
5447 	bool is_at_least_gl_45 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 5)));
5448 	bool is_arb_direct_state_access = m_context.getContextInfo().isExtensionSupported("GL_ARB_direct_state_access");
5449 
5450 	if ((!is_at_least_gl_45) && (!is_arb_direct_state_access))
5451 	{
5452 		m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported");
5453 
5454 		return STOP;
5455 	}
5456 
5457 	/* Running tests. */
5458 	bool is_ok	= true;
5459 	bool is_error = false;
5460 
5461 	/* Tested Objects. */
5462 	glw::GLuint vao		  = 0;
5463 	glw::GLuint not_a_vao = 0;
5464 
5465 	/* Dummy storage. */
5466 	glw::GLint   storage   = 0;
5467 	glw::GLint64 storage64 = 0;
5468 
5469 	/* Bad parameter setup. */
5470 	glw::GLenum bad_pname = 0;
5471 
5472 	static const glw::GLenum accepted_pnames[] = { GL_VERTEX_ATTRIB_ARRAY_ENABLED,	GL_VERTEX_ATTRIB_ARRAY_SIZE,
5473 												   GL_VERTEX_ATTRIB_ARRAY_STRIDE,	 GL_VERTEX_ATTRIB_ARRAY_TYPE,
5474 												   GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, GL_VERTEX_ATTRIB_ARRAY_INTEGER,
5475 												   GL_VERTEX_ATTRIB_ARRAY_LONG,		  GL_VERTEX_ATTRIB_ARRAY_DIVISOR,
5476 												   GL_VERTEX_ATTRIB_RELATIVE_OFFSET };
5477 
5478 	{
5479 		bool is_accepted_pname = true;
5480 		while (is_accepted_pname)
5481 		{
5482 			bad_pname++;
5483 			is_accepted_pname = false;
5484 			for (glw::GLuint i = 0; i < DE_LENGTH_OF_ARRAY(accepted_pnames); ++i)
5485 			{
5486 				if (accepted_pnames[i] == bad_pname)
5487 				{
5488 					is_accepted_pname = true;
5489 					break;
5490 				}
5491 			}
5492 		}
5493 	}
5494 
5495 	try
5496 	{
5497 		/* Prepare valid Objects. */
5498 		gl.createVertexArrays(1, &vao);
5499 		GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateVertexArrays call failed.");
5500 
5501 		/* Prepare invalid VAO. */
5502 		while (gl.isVertexArray(++not_a_vao))
5503 			;
5504 
5505 		/* Not a VAO. */
5506 		gl.getVertexArrayIndexediv(not_a_vao, 0, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &storage);
5507 
5508 		is_ok &=
5509 			CheckError(GL_INVALID_OPERATION, "INVALID_OPERATION error was not generated by GetVertexArrayIndexediv if "
5510 											 "vaobj is not the name of an existing vertex array object.");
5511 
5512 		gl.getVertexArrayIndexed64iv(not_a_vao, 0, GL_VERTEX_BINDING_OFFSET, &storage64);
5513 
5514 		is_ok &=
5515 			CheckError(GL_INVALID_OPERATION, "INVALID_OPERATION error was not generated by GetVertexArrayIndexed64iv "
5516 											 "if vaobj is not the name of an existing vertex array object.");
5517 
5518 		/* Bad parameter. */
5519 		gl.getVertexArrayIndexediv(vao, 0, bad_pname, &storage);
5520 
5521 		is_ok &= CheckError(
5522 			GL_INVALID_ENUM,
5523 			"INVALID_ENUM error was not generated by GetVertexArrayIndexediv if pname is not one of the valid values.");
5524 
5525 		/* Bad parameter 64. */
5526 		gl.getVertexArrayIndexed64iv(vao, 0, GL_VERTEX_BINDING_OFFSET + 1, &storage64);
5527 
5528 		is_ok &= CheckError(
5529 			GL_INVALID_ENUM,
5530 			"INVALID_ENUM error was not generated by GetVertexArrayIndexed64iv if pname is not VERTEX_BINDING_OFFSET.");
5531 	}
5532 	catch (...)
5533 	{
5534 		is_ok	= false;
5535 		is_error = true;
5536 	}
5537 
5538 	/* Clean up. */
5539 	if (vao)
5540 	{
5541 		gl.deleteVertexArrays(1, &vao);
5542 	}
5543 
5544 	/* Errors clean up. */
5545 	while (gl.getError())
5546 		;
5547 
5548 	/* Result's setup. */
5549 	if (is_ok)
5550 	{
5551 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
5552 	}
5553 	else
5554 	{
5555 		if (is_error)
5556 		{
5557 			m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
5558 		}
5559 		else
5560 		{
5561 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
5562 		}
5563 	}
5564 
5565 	return STOP;
5566 }
5567 
5568 /** @brief Compare error returned by GL with expected value and log.
5569  *
5570  *  @param [in] expected        Expected error.
5571  *  @param [in] log_message   Message to be logged if expected error is not the equal to the reported one.
5572  *
5573  *  @return True if GL error is equal to expected, false otherwise.
5574  */
CheckError(const glw::GLenum expected,const glw::GLchar * log_message)5575 bool GetVertexArrayIndexedErrorsTest::CheckError(const glw::GLenum expected, const glw::GLchar* log_message)
5576 {
5577 	/* Shortcut for GL functionality. */
5578 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5579 
5580 	glw::GLenum error = 0;
5581 
5582 	if (expected != (error = gl.getError()))
5583 	{
5584 		m_context.getTestContext().getLog() << tcu::TestLog::Message << log_message << " " << glu::getErrorStr(error)
5585 											<< " was observed instead." << tcu::TestLog::EndMessage;
5586 
5587 		return false;
5588 	}
5589 
5590 	return true;
5591 }
5592 } /* VertexArrays namespace. */
5593 } /* DirectStateAccess namespace. */
5594 } /* gl4cts namespace. */
5595