1 /*-------------------------------------------------------------------------
2  * OpenGL Conformance Test Suite
3  * -----------------------------
4  *
5  * Copyright (c) 2014-2016 The Khronos Group Inc.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  */ /*!
20  * \file
21  * \brief
22  */ /*-------------------------------------------------------------------*/
23 
24 /**
25  * \file  glcViewportArrayTests.cpp
26  * \brief Implements conformance tests for "Viewport Array" functionality.
27  */ /*-------------------------------------------------------------------*/
28 
29 #include "glcViewportArrayTests.hpp"
30 
31 #include "gluContextInfo.hpp"
32 #include "gluDefs.hpp"
33 #include "gluStrUtil.hpp"
34 #include "glwEnums.hpp"
35 #include "glwFunctions.hpp"
36 #include "tcuRenderTarget.hpp"
37 #include "tcuTestLog.hpp"
38 
39 #include <algorithm>
40 #include <iomanip>
41 #include <string>
42 #include <vector>
43 
44 using namespace glw;
45 
46 namespace glcts
47 {
48 
49 namespace ViewportArray
50 {
51 /** Constructor.
52  *
53  * @param context CTS context.
54  **/
buffer(deqp::Context & context)55 Utils::buffer::buffer(deqp::Context& context) : m_id(0), m_context(context), m_target(0)
56 {
57 }
58 
59 /** Destructor
60  *
61  **/
~buffer()62 Utils::buffer::~buffer()
63 {
64 	if (0 != m_id)
65 	{
66 		const glw::Functions& gl = m_context.getRenderContext().getFunctions();
67 
68 		gl.deleteBuffers(1, &m_id);
69 		m_id = 0;
70 	}
71 }
72 
73 /** Execute BindBuffer
74  *
75  **/
bind() const76 void Utils::buffer::bind() const
77 {
78 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
79 
80 	gl.bindBuffer(m_target, m_id);
81 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
82 }
83 
84 /** Execute BindBufferRange
85  *
86  * @param index  <index> parameter
87  * @param offset <offset> parameter
88  * @param size   <size> parameter
89  **/
bindRange(glw::GLuint index,glw::GLintptr offset,glw::GLsizeiptr size)90 void Utils::buffer::bindRange(glw::GLuint index, glw::GLintptr offset, glw::GLsizeiptr size)
91 {
92 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
93 
94 	gl.bindBufferRange(m_target, index, m_id, offset, size);
95 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindBufferRange");
96 }
97 
98 /** Execute GenBuffer
99  *
100  * @param target Target that will be used by this buffer
101  **/
generate(glw::GLenum target)102 void Utils::buffer::generate(glw::GLenum target)
103 {
104 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
105 
106 	m_target = target;
107 
108 	gl.genBuffers(1, &m_id);
109 	GLU_EXPECT_NO_ERROR(gl.getError(), "GenBuffers");
110 }
111 
112 /** Maps buffer content
113  *
114  * @param access Access rights for mapped region
115  *
116  * @return Mapped memory
117  **/
map(GLenum access) const118 void* Utils::buffer::map(GLenum access) const
119 {
120 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
121 
122 	gl.bindBuffer(m_target, m_id);
123 	GLU_EXPECT_NO_ERROR(gl.getError(), "bindBuffer");
124 
125 	void* result = gl.mapBuffer(m_target, access);
126 	GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
127 
128 	return result;
129 }
130 
131 /** Unmaps buffer
132  *
133  **/
unmap() const134 void Utils::buffer::unmap() const
135 {
136 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
137 
138 	gl.bindBuffer(m_target, m_id);
139 	GLU_EXPECT_NO_ERROR(gl.getError(), "bindBuffer");
140 
141 	gl.unmapBuffer(m_target);
142 	GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer");
143 }
144 
145 /** Execute BufferData
146  *
147  * @param size   <size> parameter
148  * @param data   <data> parameter
149  * @param usage  <usage> parameter
150  **/
update(glw::GLsizeiptr size,glw::GLvoid * data,glw::GLenum usage)151 void Utils::buffer::update(glw::GLsizeiptr size, glw::GLvoid* data, glw::GLenum usage)
152 {
153 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
154 
155 	gl.bindBuffer(m_target, m_id);
156 	GLU_EXPECT_NO_ERROR(gl.getError(), "bindBuffer");
157 
158 	gl.bufferData(m_target, size, data, usage);
159 	GLU_EXPECT_NO_ERROR(gl.getError(), "bufferData");
160 }
161 
162 /** Constructor
163  *
164  * @param context CTS context
165  **/
framebuffer(deqp::Context & context)166 Utils::framebuffer::framebuffer(deqp::Context& context) : m_id(0), m_context(context)
167 {
168 	/* Nothing to be done here */
169 }
170 
171 /** Destructor
172  *
173  **/
~framebuffer()174 Utils::framebuffer::~framebuffer()
175 {
176 	if (0 != m_id)
177 	{
178 		const glw::Functions& gl = m_context.getRenderContext().getFunctions();
179 
180 		gl.deleteFramebuffers(1, &m_id);
181 		m_id = 0;
182 	}
183 }
184 
185 /** Attach texture to specified attachment
186  *
187  * @param attachment Attachment
188  * @param texture_id Texture id
189  * @param width      Texture width
190  * @param height     Texture height
191  **/
attachTexture(glw::GLenum attachment,glw::GLuint texture_id,glw::GLuint width,glw::GLuint height)192 void Utils::framebuffer::attachTexture(glw::GLenum attachment, glw::GLuint texture_id, glw::GLuint width,
193 									   glw::GLuint height)
194 {
195 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
196 
197 	bind();
198 
199 	gl.framebufferTexture(GL_DRAW_FRAMEBUFFER, attachment, texture_id, 0 /* level */);
200 	GLU_EXPECT_NO_ERROR(gl.getError(), "FramebufferTexture");
201 
202 	gl.viewport(0 /* x */, 0 /* y */, width, height);
203 	GLU_EXPECT_NO_ERROR(gl.getError(), "Viewport");
204 }
205 
206 /** Binds framebuffer to DRAW_FRAMEBUFFER
207  *
208  **/
bind()209 void Utils::framebuffer::bind()
210 {
211 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
212 
213 	gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, m_id);
214 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindFramebuffer");
215 }
216 
217 /** Clear framebuffer
218  *
219  * @param mask <mask> parameter of glClear. Decides which shall be cleared
220  **/
clear(glw::GLenum mask)221 void Utils::framebuffer::clear(glw::GLenum mask)
222 {
223 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
224 
225 	gl.clear(mask);
226 	GLU_EXPECT_NO_ERROR(gl.getError(), "Clear");
227 }
228 
229 /** Specifies clear color
230  *
231  * @param red   Red channel
232  * @param green Green channel
233  * @param blue  Blue channel
234  * @param alpha Alpha channel
235  **/
clearColor(GLfloat red,GLfloat green,GLfloat blue,GLfloat alpha)236 void Utils::framebuffer::clearColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha)
237 {
238 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
239 
240 	gl.clearColor(red, green, blue, alpha);
241 	GLU_EXPECT_NO_ERROR(gl.getError(), "ClearColor");
242 }
243 
244 /** Generate framebuffer
245  *
246  **/
generate()247 void Utils::framebuffer::generate()
248 {
249 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
250 
251 	gl.genFramebuffers(1, &m_id);
252 	GLU_EXPECT_NO_ERROR(gl.getError(), "GenFramebuffers");
253 }
254 
shaderCompilationException(const glw::GLchar * source,const glw::GLchar * message)255 Utils::shaderCompilationException::shaderCompilationException(const glw::GLchar* source, const glw::GLchar* message)
256 	: m_shader_source(source), m_error_message(message)
257 {
258 	/* Nothing to be done */
259 }
260 
what() const261 const char* Utils::shaderCompilationException::what() const throw()
262 {
263 	return "Shader compilation failed";
264 }
265 
programLinkageException(const glw::GLchar * message)266 Utils::programLinkageException::programLinkageException(const glw::GLchar* message) : m_error_message(message)
267 {
268 	/* Nothing to be done */
269 }
270 
what() const271 const char* Utils::programLinkageException::what() const throw()
272 {
273 	return "Program linking failed";
274 }
275 
276 const glw::GLenum Utils::program::ARB_COMPUTE_SHADER = 0x91B9;
277 
278 /** Constructor.
279  *
280  * @param context CTS context.
281  **/
program(deqp::Context & context)282 Utils::program::program(deqp::Context& context)
283 	: m_compute_shader_id(0)
284 	, m_fragment_shader_id(0)
285 	, m_geometry_shader_id(0)
286 	, m_program_object_id(0)
287 	, m_tesselation_control_shader_id(0)
288 	, m_tesselation_evaluation_shader_id(0)
289 	, m_vertex_shader_id(0)
290 	, m_context(context)
291 {
292 	/* Nothing to be done here */
293 }
294 
295 /** Destructor
296  *
297  **/
~program()298 Utils::program::~program()
299 {
300 	remove();
301 }
302 
303 /** Build program
304  *
305  * @param compute_shader_code                Compute shader source code
306  * @param fragment_shader_code               Fragment shader source code
307  * @param geometry_shader_code               Geometry shader source code
308  * @param tesselation_control_shader_code    Tesselation control shader source code
309  * @param tesselation_evaluation_shader_code Tesselation evaluation shader source code
310  * @param vertex_shader_code                 Vertex shader source code
311  * @param varying_names                      Array of strings containing names of varyings to be captured with transfrom feedback
312  * @param n_varying_names                    Number of varyings to be captured with transfrom feedback
313  * @param is_separable                       Selects if monolithis or separable program should be built. Defaults to false
314  **/
build(const glw::GLchar * compute_shader_code,const glw::GLchar * fragment_shader_code,const glw::GLchar * geometry_shader_code,const glw::GLchar * tesselation_control_shader_code,const glw::GLchar * tesselation_evaluation_shader_code,const glw::GLchar * vertex_shader_code,const glw::GLchar * const * varying_names,glw::GLuint n_varying_names,bool is_separable)315 void Utils::program::build(const glw::GLchar* compute_shader_code, const glw::GLchar* fragment_shader_code,
316 						   const glw::GLchar* geometry_shader_code, const glw::GLchar* tesselation_control_shader_code,
317 						   const glw::GLchar* tesselation_evaluation_shader_code, const glw::GLchar* vertex_shader_code,
318 						   const glw::GLchar* const* varying_names, glw::GLuint n_varying_names, bool is_separable)
319 {
320 	/* GL entry points */
321 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
322 
323 	/* Create shader objects and compile */
324 	if (0 != compute_shader_code)
325 	{
326 		m_compute_shader_id = gl.createShader(ARB_COMPUTE_SHADER);
327 		GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader");
328 
329 		compile(m_compute_shader_id, compute_shader_code);
330 	}
331 
332 	if (0 != fragment_shader_code)
333 	{
334 		m_fragment_shader_id = gl.createShader(GL_FRAGMENT_SHADER);
335 		GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader");
336 
337 		compile(m_fragment_shader_id, fragment_shader_code);
338 	}
339 
340 	if (0 != geometry_shader_code)
341 	{
342 		m_geometry_shader_id = gl.createShader(GL_GEOMETRY_SHADER);
343 		GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader");
344 
345 		compile(m_geometry_shader_id, geometry_shader_code);
346 	}
347 
348 	if (0 != tesselation_control_shader_code)
349 	{
350 		m_tesselation_control_shader_id = gl.createShader(GL_TESS_CONTROL_SHADER);
351 		GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader");
352 
353 		compile(m_tesselation_control_shader_id, tesselation_control_shader_code);
354 	}
355 
356 	if (0 != tesselation_evaluation_shader_code)
357 	{
358 		m_tesselation_evaluation_shader_id = gl.createShader(GL_TESS_EVALUATION_SHADER);
359 		GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader");
360 
361 		compile(m_tesselation_evaluation_shader_id, tesselation_evaluation_shader_code);
362 	}
363 
364 	if (0 != vertex_shader_code)
365 	{
366 		m_vertex_shader_id = gl.createShader(GL_VERTEX_SHADER);
367 		GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader");
368 
369 		compile(m_vertex_shader_id, vertex_shader_code);
370 	}
371 
372 	/* Create program object */
373 	m_program_object_id = gl.createProgram();
374 	GLU_EXPECT_NO_ERROR(gl.getError(), "CreateProgram");
375 
376 	/* Set up captyured varyings' names */
377 	if (0 != n_varying_names)
378 	{
379 		gl.transformFeedbackVaryings(m_program_object_id, n_varying_names, varying_names, GL_INTERLEAVED_ATTRIBS);
380 		GLU_EXPECT_NO_ERROR(gl.getError(), "TransformFeedbackVaryings");
381 	}
382 
383 	/* Set separable parameter */
384 	if (true == is_separable)
385 	{
386 		gl.programParameteri(m_program_object_id, GL_PROGRAM_SEPARABLE, GL_TRUE);
387 		GLU_EXPECT_NO_ERROR(gl.getError(), "ProgramParameteri");
388 	}
389 
390 	/* Link program */
391 	link();
392 }
393 
compile(GLuint shader_id,const GLchar * source) const394 void Utils::program::compile(GLuint shader_id, const GLchar* source) const
395 {
396 	/* GL entry points */
397 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
398 
399 	/* Compilation status */
400 	glw::GLint status = GL_FALSE;
401 
402 	/* Set source code */
403 	gl.shaderSource(shader_id, 1 /* count */, &source, 0 /* lengths */);
404 	GLU_EXPECT_NO_ERROR(gl.getError(), "ShaderSource");
405 
406 	/* Compile */
407 	gl.compileShader(shader_id);
408 	GLU_EXPECT_NO_ERROR(gl.getError(), "CompileShader");
409 
410 	/* Get compilation status */
411 	gl.getShaderiv(shader_id, GL_COMPILE_STATUS, &status);
412 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderiv");
413 
414 	/* Log compilation error */
415 	if (GL_TRUE != status)
416 	{
417 		glw::GLint				 length = 0;
418 		std::vector<glw::GLchar> message;
419 
420 		/* Error log length */
421 		gl.getShaderiv(shader_id, GL_INFO_LOG_LENGTH, &length);
422 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderiv");
423 
424 		/* Prepare storage */
425 		message.resize(length);
426 
427 		/* Get error log */
428 		gl.getShaderInfoLog(shader_id, length, 0, &message[0]);
429 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderInfoLog");
430 
431 		throw shaderCompilationException(source, &message[0]);
432 	}
433 }
434 
getAttribLocation(const glw::GLchar * name) const435 glw::GLint Utils::program::getAttribLocation(const glw::GLchar* name) const
436 {
437 	/* GL entry points */
438 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
439 
440 	GLint location = gl.getAttribLocation(m_program_object_id, name);
441 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetAttribLocation");
442 
443 	return location;
444 }
445 
446 /** Get subroutine index
447  *
448  * @param subroutine_name Subroutine name
449  *
450  * @return Index of subroutine
451  **/
getSubroutineIndex(const glw::GLchar * subroutine_name,glw::GLenum shader_stage) const452 GLuint Utils::program::getSubroutineIndex(const glw::GLchar* subroutine_name, glw::GLenum shader_stage) const
453 {
454 	const glw::Functions& gl	= m_context.getRenderContext().getFunctions();
455 	GLuint				  index = -1;
456 
457 	index = gl.getSubroutineIndex(m_program_object_id, shader_stage, subroutine_name);
458 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetSubroutineIndex");
459 
460 	if (GL_INVALID_INDEX == index)
461 	{
462 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Subroutine: " << subroutine_name
463 											<< " is not available" << tcu::TestLog::EndMessage;
464 
465 		TCU_FAIL("Subroutine is not available");
466 	}
467 
468 	return index;
469 }
470 
471 /** Get subroutine uniform location
472  *
473  * @param uniform_name Subroutine uniform name
474  *
475  * @return Location of subroutine uniform
476  **/
getSubroutineUniformLocation(const glw::GLchar * uniform_name,glw::GLenum shader_stage) const477 GLint Utils::program::getSubroutineUniformLocation(const glw::GLchar* uniform_name, glw::GLenum shader_stage) const
478 {
479 	const glw::Functions& gl	   = m_context.getRenderContext().getFunctions();
480 	GLint				  location = -1;
481 
482 	location = gl.getSubroutineUniformLocation(m_program_object_id, shader_stage, uniform_name);
483 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetSubroutineUniformLocation");
484 
485 	if (-1 == location)
486 	{
487 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Subroutine uniform: " << uniform_name
488 											<< " is not available" << tcu::TestLog::EndMessage;
489 
490 		TCU_FAIL("Subroutine uniform is not available");
491 	}
492 
493 	return location;
494 }
495 
496 /** Get uniform location
497  *
498  * @param uniform_name Subroutine uniform name
499  *
500  * @return Location of uniform
501  **/
getUniformLocation(const glw::GLchar * uniform_name) const502 GLint Utils::program::getUniformLocation(const glw::GLchar* uniform_name) const
503 {
504 	const glw::Functions& gl	   = m_context.getRenderContext().getFunctions();
505 	GLint				  location = -1;
506 
507 	location = gl.getUniformLocation(m_program_object_id, uniform_name);
508 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformLocation");
509 
510 	if (-1 == location)
511 	{
512 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Uniform: " << uniform_name
513 											<< " is not available" << tcu::TestLog::EndMessage;
514 
515 		TCU_FAIL("Uniform is not available");
516 	}
517 
518 	return location;
519 }
520 
521 /** Attach shaders and link program
522  *
523  **/
link() const524 void Utils::program::link() const
525 {
526 	/* GL entry points */
527 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
528 
529 	/* Link status */
530 	glw::GLint status = GL_FALSE;
531 
532 	/* Attach shaders */
533 	if (0 != m_compute_shader_id)
534 	{
535 		gl.attachShader(m_program_object_id, m_compute_shader_id);
536 		GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader");
537 	}
538 
539 	if (0 != m_fragment_shader_id)
540 	{
541 		gl.attachShader(m_program_object_id, m_fragment_shader_id);
542 		GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader");
543 	}
544 
545 	if (0 != m_geometry_shader_id)
546 	{
547 		gl.attachShader(m_program_object_id, m_geometry_shader_id);
548 		GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader");
549 	}
550 
551 	if (0 != m_tesselation_control_shader_id)
552 	{
553 		gl.attachShader(m_program_object_id, m_tesselation_control_shader_id);
554 		GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader");
555 	}
556 
557 	if (0 != m_tesselation_evaluation_shader_id)
558 	{
559 		gl.attachShader(m_program_object_id, m_tesselation_evaluation_shader_id);
560 		GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader");
561 	}
562 
563 	if (0 != m_vertex_shader_id)
564 	{
565 		gl.attachShader(m_program_object_id, m_vertex_shader_id);
566 		GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader");
567 	}
568 
569 	/* Link */
570 	gl.linkProgram(m_program_object_id);
571 	GLU_EXPECT_NO_ERROR(gl.getError(), "LinkProgram");
572 
573 	/* Get link status */
574 	gl.getProgramiv(m_program_object_id, GL_LINK_STATUS, &status);
575 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramiv");
576 
577 	/* Log link error */
578 	if (GL_TRUE != status)
579 	{
580 		glw::GLint				 length = 0;
581 		std::vector<glw::GLchar> message;
582 
583 		/* Get error log length */
584 		gl.getProgramiv(m_program_object_id, GL_INFO_LOG_LENGTH, &length);
585 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramiv");
586 
587 		message.resize(length);
588 
589 		/* Get error log */
590 		gl.getProgramInfoLog(m_program_object_id, length, 0, &message[0]);
591 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramInfoLog");
592 
593 		throw programLinkageException(&message[0]);
594 	}
595 }
596 
597 /** Delete program object and all attached shaders
598  *
599  **/
remove()600 void Utils::program::remove()
601 {
602 	/* GL entry points */
603 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
604 
605 	/* Make sure program object is no longer used by GL */
606 	gl.useProgram(0);
607 
608 	/* Clean program object */
609 	if (0 != m_program_object_id)
610 	{
611 		gl.deleteProgram(m_program_object_id);
612 		m_program_object_id = 0;
613 	}
614 
615 	/* Clean shaders */
616 	if (0 != m_compute_shader_id)
617 	{
618 		gl.deleteShader(m_compute_shader_id);
619 		m_compute_shader_id = 0;
620 	}
621 
622 	if (0 != m_fragment_shader_id)
623 	{
624 		gl.deleteShader(m_fragment_shader_id);
625 		m_fragment_shader_id = 0;
626 	}
627 
628 	if (0 != m_geometry_shader_id)
629 	{
630 		gl.deleteShader(m_geometry_shader_id);
631 		m_geometry_shader_id = 0;
632 	}
633 
634 	if (0 != m_tesselation_control_shader_id)
635 	{
636 		gl.deleteShader(m_tesselation_control_shader_id);
637 		m_tesselation_control_shader_id = 0;
638 	}
639 
640 	if (0 != m_tesselation_evaluation_shader_id)
641 	{
642 		gl.deleteShader(m_tesselation_evaluation_shader_id);
643 		m_tesselation_evaluation_shader_id = 0;
644 	}
645 
646 	if (0 != m_vertex_shader_id)
647 	{
648 		gl.deleteShader(m_vertex_shader_id);
649 		m_vertex_shader_id = 0;
650 	}
651 }
652 
653 /** Execute UseProgram
654  *
655  **/
use() const656 void Utils::program::use() const
657 {
658 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
659 
660 	gl.useProgram(m_program_object_id);
661 	GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
662 }
663 
printShaderSource(const GLchar * source,tcu::MessageBuilder & log)664 void Utils::program::printShaderSource(const GLchar* source, tcu::MessageBuilder& log)
665 {
666 	GLuint line_number = 0;
667 
668 	log << "Shader source.";
669 
670 	log << "\nLine||Source\n";
671 
672 	while (0 != source)
673 	{
674 		std::string   line;
675 		const GLchar* next_line = strchr(source, '\n');
676 
677 		if (0 != next_line)
678 		{
679 			next_line += 1;
680 			line.assign(source, next_line - source);
681 		}
682 		else
683 		{
684 			line = source;
685 		}
686 
687 		if (0 != *source)
688 		{
689 			log << std::setw(4) << line_number << "||" << line;
690 		}
691 
692 		source = next_line;
693 		line_number += 1;
694 	}
695 }
696 
697 /** Constructor.
698  *
699  * @param context CTS context.
700  **/
texture(deqp::Context & context)701 Utils::texture::texture(deqp::Context& context)
702 	: m_id(0), m_width(0), m_height(0), m_depth(0), m_context(context), m_is_array(false)
703 {
704 	/* Nothing to done here */
705 }
706 
707 /** Destructor
708  *
709  **/
~texture()710 Utils::texture::~texture()
711 {
712 	release();
713 }
714 
715 /** Bind texture to GL_TEXTURE_2D
716  *
717  **/
bind() const718 void Utils::texture::bind() const
719 {
720 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
721 
722 	if (false == m_is_array)
723 	{
724 		gl.bindTexture(GL_TEXTURE_2D, m_id);
725 		GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
726 	}
727 	else
728 	{
729 		gl.bindTexture(GL_TEXTURE_2D_ARRAY, m_id);
730 		GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
731 	}
732 }
733 
734 /** Create 2d texture
735  *
736  * @param width           Width of texture
737  * @param height          Height of texture
738  * @param internal_format Internal format of texture
739  **/
create(GLuint width,GLuint height,GLenum internal_format)740 void Utils::texture::create(GLuint width, GLuint height, GLenum internal_format)
741 {
742 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
743 
744 	release();
745 
746 	m_width	= width;
747 	m_height   = height;
748 	m_depth	= 1;
749 	m_is_array = false;
750 
751 	gl.genTextures(1, &m_id);
752 	GLU_EXPECT_NO_ERROR(gl.getError(), "GenTextures");
753 
754 	bind();
755 
756 	gl.texStorage2D(GL_TEXTURE_2D, 1 /* levels */, internal_format, width, height);
757 	GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage2D");
758 }
759 
760 /** Create 2d texture array
761  *
762  * @param width           Width of texture
763  * @param height          Height of texture
764  * @param depth           Depth of texture
765  * @param internal_format Internal format of texture
766  **/
create(GLuint width,GLuint height,GLuint depth,GLenum internal_format)767 void Utils::texture::create(GLuint width, GLuint height, GLuint depth, GLenum internal_format)
768 {
769 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
770 
771 	release();
772 
773 	m_width	= width;
774 	m_height   = height;
775 	m_depth	= depth;
776 	m_is_array = true;
777 
778 	gl.genTextures(1, &m_id);
779 	GLU_EXPECT_NO_ERROR(gl.getError(), "GenTextures");
780 
781 	bind();
782 
783 	gl.texStorage3D(GL_TEXTURE_2D_ARRAY, 1 /* levels */, internal_format, width, height, depth);
784 	GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage3D");
785 }
786 
787 /** Get contents of texture
788  *
789  * @param format   Format of image
790  * @param type     Type of image
791  * @param out_data Buffer for image
792  **/
get(glw::GLenum format,glw::GLenum type,glw::GLvoid * out_data) const793 void Utils::texture::get(glw::GLenum format, glw::GLenum type, glw::GLvoid* out_data) const
794 {
795 	const glw::Functions&   gl			 = m_context.getRenderContext().getFunctions();
796 	const glu::ContextType& context_type = m_context.getRenderContext().getType();
797 
798 	bind();
799 
800 	GLenum textarget = GL_TEXTURE_2D;
801 
802 	if (true == m_is_array)
803 	{
804 		textarget = GL_TEXTURE_2D_ARRAY;
805 	}
806 
807 	if (glu::isContextTypeGLCore(context_type))
808 	{
809 		gl.getTexImage(textarget, 0 /* level */, format, type, out_data);
810 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetTexImage");
811 	}
812 	else
813 	{
814 		DE_ASSERT(glu::isContextTypeES(context_type));
815 
816 		GLuint temp_fbo = 0;
817 		gl.genFramebuffers(1, &temp_fbo);
818 		gl.bindFramebuffer(GL_READ_FRAMEBUFFER, temp_fbo);
819 
820 		/* OpenGL ES only guarantees support for RGBA formats of each type.
821 		Since the tests are only expecting single-channel formats, we read them back
822 		in RGBA to a temporary buffer and then copy only the first component
823 		to the actual output buffer */
824 		GLenum read_format = format;
825 		switch (format)
826 		{
827 		case GL_RED:
828 			read_format = GL_RGBA;
829 			break;
830 		case GL_RED_INTEGER:
831 			read_format = GL_RGBA_INTEGER;
832 			break;
833 		default:
834 			TCU_FAIL("unexpected format");
835 		}
836 		/* we can get away just handling one type of data, as long as the components are the same size */
837 		if (type != GL_INT && type != GL_FLOAT)
838 		{
839 			TCU_FAIL("unexpected type");
840 		}
841 		std::vector<GLint> read_data;
842 		const GLuint	   layer_size = m_width * m_height * 4;
843 		read_data.resize(layer_size * m_depth);
844 
845 		if (m_is_array)
846 		{
847 			for (GLuint layer = 0; layer < m_depth; ++layer)
848 			{
849 				gl.framebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_id, 0, layer);
850 				gl.readPixels(0, 0, m_width, m_height, read_format, type, &read_data[layer * layer_size]);
851 			}
852 		}
853 		else
854 		{
855 			gl.framebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, textarget, m_id, 0);
856 			gl.readPixels(0, 0, m_width, m_height, read_format, type, &read_data[0]);
857 		}
858 		GLU_EXPECT_NO_ERROR(gl.getError(), "ReadPixels");
859 		gl.deleteFramebuffers(1, &temp_fbo);
860 
861 		/* copy the first channel from the readback buffer to the output buffer */
862 		GLint* out_data_int = (GLint*)out_data;
863 		for (GLuint elem = 0; elem < (m_width * m_height * m_depth); ++elem)
864 		{
865 			out_data_int[elem] = read_data[elem * 4];
866 		}
867 	}
868 }
869 
870 /** Delete texture
871  *
872  **/
release()873 void Utils::texture::release()
874 {
875 	if (0 != m_id)
876 	{
877 		const glw::Functions& gl = m_context.getRenderContext().getFunctions();
878 
879 		gl.deleteTextures(1, &m_id);
880 		m_id = 0;
881 	}
882 }
883 
884 /** Update contents of texture
885  *
886  * @param width  Width of texture
887  * @param height Height of texture
888  * @param depth  Depth of texture
889  * @param format Format of data
890  * @param type   Type of data
891  * @param data   Buffer with image
892  **/
update(glw::GLuint width,glw::GLuint height,glw::GLuint depth,glw::GLenum format,glw::GLenum type,glw::GLvoid * data)893 void Utils::texture::update(glw::GLuint width, glw::GLuint height, glw::GLuint depth, glw::GLenum format,
894 							glw::GLenum type, glw::GLvoid* data)
895 {
896 	static const GLuint level = 0;
897 
898 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
899 
900 	bind();
901 
902 	if (false == m_is_array)
903 	{
904 		gl.texSubImage2D(GL_TEXTURE_2D, level, 0 /* x */, 0 /* y */, width, height, format, type, data);
905 		GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage2D");
906 	}
907 	else
908 	{
909 		gl.texSubImage3D(GL_TEXTURE_2D_ARRAY, level, 0 /* x */, 0 /* y */, 0 /* z */, width, height, depth, format,
910 						 type, data);
911 		GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage2D");
912 	}
913 }
914 
915 /** Constructor.
916  *
917  * @param context CTS context.
918  **/
vertexArray(deqp::Context & context)919 Utils::vertexArray::vertexArray(deqp::Context& context) : m_id(0), m_context(context)
920 {
921 }
922 
923 /** Destructor
924  *
925  **/
~vertexArray()926 Utils::vertexArray::~vertexArray()
927 {
928 	if (0 != m_id)
929 	{
930 		const glw::Functions& gl = m_context.getRenderContext().getFunctions();
931 
932 		gl.deleteVertexArrays(1, &m_id);
933 
934 		m_id = 0;
935 	}
936 }
937 
938 /** Execute BindVertexArray
939  *
940  **/
bind()941 void Utils::vertexArray::bind()
942 {
943 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
944 
945 	gl.bindVertexArray(m_id);
946 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexArray");
947 }
948 
949 /** Execute GenVertexArrays
950  *
951  **/
generate()952 void Utils::vertexArray::generate()
953 {
954 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
955 
956 	gl.genVertexArrays(1, &m_id);
957 	GLU_EXPECT_NO_ERROR(gl.getError(), "GenVertexArrays");
958 }
959 
960 /** Constructor
961  *
962  * @param context          Test context
963  **/
APIErrors(deqp::Context & context,const glcts::ExtParameters & extParams)964 APIErrors::APIErrors(deqp::Context& context, const glcts::ExtParameters& extParams)
965 	: TestCaseBase(context, extParams, "api_errors", "Test verifies error generated by API")
966 {
967 	/* Nothing to be done here */
968 }
969 
970 template <typename T>
depthRangeArrayHelper(Utils::DepthFuncWrapper & depthFunc,GLint max_viewports,bool & test_result,T *)971 void APIErrors::depthRangeArrayHelper(Utils::DepthFuncWrapper& depthFunc, GLint max_viewports, bool& test_result, T*)
972 {
973 	std::vector<T> data;
974 	data.resize(max_viewports * 2 /* near + far */);
975 
976 	for (GLint i = 0; i < max_viewports; ++i)
977 	{
978 		data[i * 2]		= (T)0.0;
979 		data[i * 2 + 1] = (T)1.0;
980 	}
981 
982 	depthFunc.depthRangeArray(0, max_viewports - 1, &data[0]);
983 	checkGLError(GL_NO_ERROR, "depthRangeArray, correct parameters", test_result);
984 
985 	depthFunc.depthRangeArray(max_viewports, 1, &data[0]);
986 	checkGLError(GL_INVALID_VALUE, "depthRangeArray, <first> == GL_MAX_VIEWPORTS", test_result);
987 
988 	depthFunc.depthRangeArray(1, max_viewports - 1, &data[0]);
989 	checkGLError(GL_NO_ERROR, "depthRangeArray, <first> + <count> == GL_MAX_VIEWPORTS", test_result);
990 
991 	depthFunc.depthRangeArray(1, max_viewports, &data[0]);
992 	checkGLError(GL_INVALID_VALUE, "depthRangeArray, <first> + <count> > GL_MAX_VIEWPORTS", test_result);
993 }
994 
995 template <typename T>
depthRangeIndexedHelper(Utils::DepthFuncWrapper & depthFunc,GLint max_viewports,bool & test_result,T *)996 void APIErrors::depthRangeIndexedHelper(Utils::DepthFuncWrapper& depthFunc, GLint max_viewports, bool& test_result, T*)
997 {
998 	depthFunc.depthRangeIndexed(0 /* index */, (T)0.0, (T)1.0);
999 	checkGLError(GL_NO_ERROR, "depthRangeIndexed, <index> == 0", test_result);
1000 
1001 	depthFunc.depthRangeIndexed(max_viewports - 1 /* index */, (T)0.0, (T)1.0);
1002 	checkGLError(GL_NO_ERROR, "depthRangeIndexed, <index> == GL_MAX_VIEWPORTS - 1", test_result);
1003 
1004 	depthFunc.depthRangeIndexed(max_viewports /* index */, (T)0.0, (T)1.0);
1005 	checkGLError(GL_INVALID_VALUE, "depthRangeIndexed, <index> == GL_MAX_VIEWPORTS", test_result);
1006 
1007 	depthFunc.depthRangeIndexed(max_viewports + 1 /* index */, (T)0.0, (T)1.0);
1008 	checkGLError(GL_INVALID_VALUE, "depthRangeIndexed, <index> > GL_MAX_VIEWPORTS", test_result);
1009 }
1010 
1011 template <typename T>
getDepthHelper(Utils::DepthFuncWrapper & depthFunc,GLint max_viewports,bool & test_result,T *)1012 void APIErrors::getDepthHelper(Utils::DepthFuncWrapper& depthFunc, GLint max_viewports, bool& test_result, T*)
1013 {
1014 	T data[4];
1015 
1016 	depthFunc.getDepthi_v(GL_DEPTH_RANGE, max_viewports - 1, data);
1017 	checkGLError(GL_NO_ERROR, "getDouble/Floati_v, <index> == GL_MAX_VIEWPORTS - 1", test_result);
1018 
1019 	depthFunc.getDepthi_v(GL_DEPTH_RANGE, max_viewports, data);
1020 	checkGLError(GL_INVALID_VALUE, "getDouble/Floati_v, <index> == GL_MAX_VIEWPORTS", test_result);
1021 }
1022 
1023 /** Execute test
1024  *
1025  * @return tcu::TestNode::CONTINUE after executing test case, tcu::TestNode::STOP otherwise
1026  **/
iterate()1027 tcu::TestNode::IterateResult APIErrors::iterate()
1028 {
1029 	if (!m_is_viewport_array_supported)
1030 	{
1031 		throw tcu::NotSupportedError(VIEWPORT_ARRAY_NOT_SUPPORTED, "", __FILE__, __LINE__);
1032 	}
1033 
1034 	/* GL entry points */
1035 	const glw::Functions&   gl			 = m_context.getRenderContext().getFunctions();
1036 	const glu::ContextType& context_type = m_context.getRenderContext().getType();
1037 	Utils::DepthFuncWrapper depthFunc(m_context);
1038 
1039 	/* Test result */
1040 	bool test_result = true;
1041 
1042 	GLint max_viewports = 0;
1043 	gl.getIntegerv(GL_MAX_VIEWPORTS, &max_viewports);
1044 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
1045 
1046 	/*
1047 	 *   * DepthRangeArrayv generates INVALID_VALUE when <first> + <count> is greater
1048 	 *   than or equal to the value of MAX_VIEWPORTS;
1049 	 */
1050 	if (glu::isContextTypeGLCore(context_type))
1051 	{
1052 		depthRangeArrayHelper<GLdouble>(depthFunc, max_viewports, test_result);
1053 	}
1054 	else
1055 	{
1056 		DE_ASSERT(glu::isContextTypeES(context_type));
1057 		depthRangeArrayHelper<GLfloat>(depthFunc, max_viewports, test_result);
1058 	}
1059 
1060 	/*
1061 	 *   * DepthRangeIndexed generates INVALID_VALUE when <index> is greater than or
1062 	 *   equal to the value of MAX_VIEWPORTS;
1063 	 */
1064 	if (glu::isContextTypeGLCore(context_type))
1065 	{
1066 		depthRangeIndexedHelper<GLdouble>(depthFunc, max_viewports, test_result);
1067 	}
1068 	else
1069 	{
1070 		DE_ASSERT(glu::isContextTypeES(context_type));
1071 		depthRangeIndexedHelper<GLfloat>(depthFunc, max_viewports, test_result);
1072 	}
1073 
1074 	/*
1075 	 *   * ViewportArrayv generates INVALID_VALUE when <first> + <count> is greater
1076 	 *   than or equal to the value of MAX_VIEWPORTS;
1077 	 */
1078 	{
1079 		std::vector<GLfloat> data;
1080 		data.resize(max_viewports * 4 /* x + y + w + h */);
1081 
1082 		for (GLint i = 0; i < max_viewports; ++i)
1083 		{
1084 			data[i * 4 + 0] = 0.0f;
1085 			data[i * 4 + 1] = 0.0f;
1086 			data[i * 4 + 2] = 1.0f;
1087 			data[i * 4 + 3] = 1.0f;
1088 		}
1089 
1090 		gl.viewportArrayv(0, max_viewports - 1, &data[0]);
1091 		checkGLError(GL_NO_ERROR, "viewportArrayv, correct parameters", test_result);
1092 
1093 		gl.viewportArrayv(max_viewports, 1, &data[0]);
1094 		checkGLError(GL_INVALID_VALUE, "viewportArrayv, <first> == GL_MAX_VIEWPORTS", test_result);
1095 
1096 		gl.viewportArrayv(1, max_viewports - 1, &data[0]);
1097 		checkGLError(GL_NO_ERROR, "viewportArrayv, <first> + <count> == GL_MAX_VIEWPORTS", test_result);
1098 
1099 		gl.viewportArrayv(1, max_viewports, &data[0]);
1100 		checkGLError(GL_INVALID_VALUE, "viewportArrayv, <first> + <count> > GL_MAX_VIEWPORTS", test_result);
1101 	}
1102 
1103 	/*
1104 	 *   * ViewportIndexedf and ViewportIndexedfv generate INVALID_VALUE when <index>
1105 	 *   is greater than or equal to the value of MAX_VIEWPORTS;
1106 	 */
1107 	{
1108 		GLfloat data[4 /* x + y + w + h */];
1109 
1110 		data[0] = 0.0f;
1111 		data[1] = 0.0f;
1112 		data[2] = 1.0f;
1113 		data[3] = 1.0f;
1114 
1115 		gl.viewportIndexedf(0 /* index */, 0.0f, 0.0f, 1.0f, 1.0f);
1116 		checkGLError(GL_NO_ERROR, "viewportIndexedf, <index> == 0", test_result);
1117 
1118 		gl.viewportIndexedf(max_viewports - 1 /* index */, 0.0f, 0.0f, 1.0f, 1.0f);
1119 		checkGLError(GL_NO_ERROR, "viewportIndexedf, <index> == GL_MAX_VIEWPORTS - 1", test_result);
1120 
1121 		gl.viewportIndexedf(max_viewports /* index */, 0.0f, 0.0f, 1.0f, 1.0f);
1122 		checkGLError(GL_INVALID_VALUE, "viewportIndexedf, <index> == GL_MAX_VIEWPORTS", test_result);
1123 
1124 		gl.viewportIndexedf(max_viewports + 1 /* index */, 0.0f, 0.0f, 1.0f, 1.0f);
1125 		checkGLError(GL_INVALID_VALUE, "viewportIndexedf, <index> > GL_MAX_VIEWPORTS", test_result);
1126 
1127 		gl.viewportIndexedfv(0 /* index */, data);
1128 		checkGLError(GL_NO_ERROR, "viewportIndexedfv, <index> == 0", test_result);
1129 
1130 		gl.viewportIndexedfv(max_viewports - 1 /* index */, data);
1131 		checkGLError(GL_NO_ERROR, "viewportIndexedfv, <index> == GL_MAX_VIEWPORTS - 1", test_result);
1132 
1133 		gl.viewportIndexedfv(max_viewports /* index */, data);
1134 		checkGLError(GL_INVALID_VALUE, "viewportIndexedfv, <index> == GL_MAX_VIEWPORTS", test_result);
1135 
1136 		gl.viewportIndexedfv(max_viewports + 1 /* index */, data);
1137 		checkGLError(GL_INVALID_VALUE, "viewportIndexedfv, <index> > GL_MAX_VIEWPORTS", test_result);
1138 	}
1139 
1140 	/*
1141 	 *   * ViewportArrayv, Viewport, ViewportIndexedf and ViewportIndexedfv generate
1142 	 *   INVALID_VALUE when <w> or <h> values are negative;
1143 	 */
1144 	{
1145 		gl.viewport(0, 0, -1, 1);
1146 		checkGLError(GL_INVALID_VALUE, "viewport, negative width", test_result);
1147 
1148 		gl.viewport(0, 0, 1, -1);
1149 		checkGLError(GL_INVALID_VALUE, "viewport, negative height", test_result);
1150 
1151 		for (GLint i = 0; i < max_viewports; ++i)
1152 		{
1153 			std::vector<GLfloat> data;
1154 			data.resize(max_viewports * 4 /* x + y + w + h */);
1155 
1156 			for (GLint j = 0; j < max_viewports; ++j)
1157 			{
1158 				data[j * 4 + 0] = 0.0f;
1159 				data[j * 4 + 1] = 0.0f;
1160 				data[j * 4 + 2] = 1.0f;
1161 				data[j * 4 + 3] = 1.0f;
1162 			}
1163 
1164 			/* Set width to -1 */
1165 			data[i * 4 + 2] = -1.0f;
1166 
1167 			gl.viewportArrayv(0, max_viewports, &data[0]);
1168 			checkGLError(GL_INVALID_VALUE, "viewportArrayv, negative width", test_result);
1169 
1170 			gl.viewportIndexedf(i /* index */, 0.0f, 0.0f, -1.0f, 1.0f);
1171 			checkGLError(GL_INVALID_VALUE, "viewportIndexedf, negative width", test_result);
1172 
1173 			gl.viewportIndexedfv(i /* index */, &data[i * 4]);
1174 			checkGLError(GL_INVALID_VALUE, "viewportIndexedfv, negative width", test_result);
1175 
1176 			/* Set width to 1 and height to -1*/
1177 			data[i * 4 + 2] = 1.0f;
1178 			data[i * 4 + 3] = -1.0f;
1179 
1180 			gl.viewportArrayv(0, max_viewports, &data[0]);
1181 			checkGLError(GL_INVALID_VALUE, "viewportArrayv, negative height", test_result);
1182 
1183 			gl.viewportIndexedf(i /* index */, 0.0f, 0.0f, 1.0f, -1.0f);
1184 			checkGLError(GL_INVALID_VALUE, "viewportIndexedf, negative height", test_result);
1185 
1186 			gl.viewportIndexedfv(i /* index */, &data[i * 4]);
1187 			checkGLError(GL_INVALID_VALUE, "viewportIndexedfv, negative height", test_result);
1188 		}
1189 	}
1190 
1191 	/*
1192 	 *   * ScissorArrayv generates INVALID_VALUE when <first> + <count> is greater
1193 	 *   than or equal to the value of MAX_VIEWPORTS;
1194 	 */
1195 	{
1196 		std::vector<GLint> data;
1197 		data.resize(max_viewports * 4 /* x + y + w + h */);
1198 
1199 		for (GLint i = 0; i < max_viewports; ++i)
1200 		{
1201 			data[i * 4 + 0] = 0;
1202 			data[i * 4 + 1] = 0;
1203 			data[i * 4 + 2] = 1;
1204 			data[i * 4 + 3] = 1;
1205 		}
1206 
1207 		gl.scissorArrayv(0, max_viewports - 1, &data[0]);
1208 		checkGLError(GL_NO_ERROR, "scissorArrayv, correct parameters", test_result);
1209 
1210 		gl.scissorArrayv(max_viewports, 1, &data[0]);
1211 		checkGLError(GL_INVALID_VALUE, "scissorArrayv, <first> == GL_MAX_VIEWPORTS", test_result);
1212 
1213 		gl.scissorArrayv(1, max_viewports - 1, &data[0]);
1214 		checkGLError(GL_NO_ERROR, "scissorArrayv, <first> + <count> == GL_MAX_VIEWPORTS", test_result);
1215 
1216 		gl.scissorArrayv(1, max_viewports, &data[0]);
1217 		checkGLError(GL_INVALID_VALUE, "scissorArrayv, <first> + <count> > GL_MAX_VIEWPORTS", test_result);
1218 	}
1219 
1220 	/*
1221 	 *   * ScissorIndexed and ScissorIndexedv generate INVALID_VALUE when <index> is
1222 	 *   greater than or equal to the value of MAX_VIEWPORTS;
1223 	 */
1224 	{
1225 		GLint data[4 /* x + y + w + h */];
1226 
1227 		data[0] = 0;
1228 		data[1] = 0;
1229 		data[2] = 1;
1230 		data[3] = 1;
1231 
1232 		gl.scissorIndexed(0 /* index */, 0, 0, 1, 1);
1233 		checkGLError(GL_NO_ERROR, "scissorIndexed, <index> == 0", test_result);
1234 
1235 		gl.scissorIndexed(max_viewports - 1 /* index */, 0, 0, 1, 1);
1236 		checkGLError(GL_NO_ERROR, "scissorIndexed, <index> == GL_MAX_VIEWPORTS - 1", test_result);
1237 
1238 		gl.scissorIndexed(max_viewports /* index */, 0, 0, 1, 1);
1239 		checkGLError(GL_INVALID_VALUE, "scissorIndexed, <index> == GL_MAX_VIEWPORTS", test_result);
1240 
1241 		gl.scissorIndexed(max_viewports + 1 /* index */, 0, 0, 1, 1);
1242 		checkGLError(GL_INVALID_VALUE, "scissorIndexed, <index> > GL_MAX_VIEWPORTS", test_result);
1243 
1244 		gl.scissorIndexedv(0 /* index */, data);
1245 		checkGLError(GL_NO_ERROR, "scissorIndexedv, <index> == 0", test_result);
1246 
1247 		gl.scissorIndexedv(max_viewports - 1 /* index */, data);
1248 		checkGLError(GL_NO_ERROR, "scissorIndexedv, <index> == GL_MAX_VIEWPORTS - 1", test_result);
1249 
1250 		gl.scissorIndexedv(max_viewports /* index */, data);
1251 		checkGLError(GL_INVALID_VALUE, "scissorIndexedv, <index> == GL_MAX_VIEWPORTS", test_result);
1252 
1253 		gl.scissorIndexedv(max_viewports + 1 /* index */, data);
1254 		checkGLError(GL_INVALID_VALUE, "scissorIndexedv, <index> > GL_MAX_VIEWPORTS", test_result);
1255 	}
1256 
1257 	/*
1258 	 *   * ScissorArrayv, ScissorIndexed, ScissorIndexedv and Scissor generate
1259 	 *   INVALID_VALUE when <width> or <height> values are negative;
1260 	 */
1261 	{
1262 		gl.scissor(0, 0, -1, 1);
1263 		checkGLError(GL_INVALID_VALUE, "scissor, negative width", test_result);
1264 
1265 		gl.scissor(0, 0, 1, -1);
1266 		checkGLError(GL_INVALID_VALUE, "scissor, negative height", test_result);
1267 
1268 		for (GLint i = 0; i < max_viewports; ++i)
1269 		{
1270 			std::vector<GLint> data;
1271 			data.resize(max_viewports * 4 /* x + y + w + h */);
1272 
1273 			for (GLint j = 0; j < max_viewports; ++j)
1274 			{
1275 				data[j * 4 + 0] = 0;
1276 				data[j * 4 + 1] = 0;
1277 				data[j * 4 + 2] = 1;
1278 				data[j * 4 + 3] = 1;
1279 			}
1280 
1281 			/* Set width to -1 */
1282 			data[i * 4 + 2] = -1;
1283 
1284 			gl.scissorArrayv(0, max_viewports, &data[0]);
1285 			checkGLError(GL_INVALID_VALUE, "scissorArrayv, negative width", test_result);
1286 
1287 			gl.scissorIndexed(i /* index */, 0, 0, -1, 1);
1288 			checkGLError(GL_INVALID_VALUE, "scissorIndexed, negative width", test_result);
1289 
1290 			gl.scissorIndexedv(i /* index */, &data[i * 4]);
1291 			checkGLError(GL_INVALID_VALUE, "scissorIndexedv, negative width", test_result);
1292 
1293 			/* Set width to 1 and height to -1*/
1294 			data[i * 4 + 2] = 1;
1295 			data[i * 4 + 3] = -1;
1296 
1297 			gl.scissorArrayv(0, max_viewports, &data[0]);
1298 			checkGLError(GL_INVALID_VALUE, "scissorArrayv, negative height", test_result);
1299 
1300 			gl.scissorIndexed(i /* index */, 0, 0, 1, -1);
1301 			checkGLError(GL_INVALID_VALUE, "scissorIndexed, negative height", test_result);
1302 
1303 			gl.scissorIndexedv(i /* index */, &data[i * 4]);
1304 			checkGLError(GL_INVALID_VALUE, "scissorIndexedv, negative height", test_result);
1305 		}
1306 	}
1307 
1308 	/*
1309 	 *   * Disablei, Enablei and IsEnabledi generate INVALID_VALUE when <cap> is
1310 	 *   SCISSOR_TEST and <index> is greater than or equal to the
1311 	 *   value of MAX_VIEWPORTS;
1312 	 */
1313 	{
1314 		gl.disablei(GL_SCISSOR_TEST, max_viewports - 1);
1315 		checkGLError(GL_NO_ERROR, "disablei, <index> == GL_MAX_VIEWPORTS - 1", test_result);
1316 
1317 		gl.disablei(GL_SCISSOR_TEST, max_viewports);
1318 		checkGLError(GL_INVALID_VALUE, "disablei, <index> == GL_MAX_VIEWPORTS", test_result);
1319 
1320 		gl.enablei(GL_SCISSOR_TEST, max_viewports - 1);
1321 		checkGLError(GL_NO_ERROR, "enablei, <index> == GL_MAX_VIEWPORTS - 1", test_result);
1322 
1323 		gl.enablei(GL_SCISSOR_TEST, max_viewports);
1324 		checkGLError(GL_INVALID_VALUE, "enablei, <index> == GL_MAX_VIEWPORTS", test_result);
1325 
1326 		gl.isEnabledi(GL_SCISSOR_TEST, max_viewports - 1);
1327 		checkGLError(GL_NO_ERROR, "isEnabledi, <index> == GL_MAX_VIEWPORTS - 1", test_result);
1328 
1329 		gl.isEnabledi(GL_SCISSOR_TEST, max_viewports);
1330 		checkGLError(GL_INVALID_VALUE, "isEnabledi, <index> == GL_MAX_VIEWPORTS", test_result);
1331 	}
1332 
1333 	/*
1334 	 *   * GetIntegeri_v generates INVALID_VALUE when <target> is SCISSOR_BOX and
1335 	 *   <index> is greater than or equal to the value of MAX_VIEWPORTS;
1336 	 */
1337 	{
1338 		GLint data[4];
1339 
1340 		gl.getIntegeri_v(GL_SCISSOR_BOX, max_viewports - 1, data);
1341 		checkGLError(GL_NO_ERROR, "getIntegeri_v, <index> == GL_MAX_VIEWPORTS - 1", test_result);
1342 
1343 		gl.getIntegeri_v(GL_SCISSOR_BOX, max_viewports, data);
1344 		checkGLError(GL_INVALID_VALUE, "getIntegeri_v, <index> == GL_MAX_VIEWPORTS", test_result);
1345 	}
1346 
1347 	/*
1348 	 *   * GetFloati_v generates INVALID_VALUE when <target> is VIEWPORT and <index>
1349 	 *   is greater than or equal to the value of MAX_VIEWPORTS;
1350 	 */
1351 	{
1352 		GLfloat data[4];
1353 
1354 		gl.getFloati_v(GL_VIEWPORT, max_viewports - 1, data);
1355 		checkGLError(GL_NO_ERROR, "getFloati_v, <index> == GL_MAX_VIEWPORTS - 1", test_result);
1356 
1357 		gl.getFloati_v(GL_VIEWPORT, max_viewports, data);
1358 		checkGLError(GL_INVALID_VALUE, "getFloati_v, <index> == GL_MAX_VIEWPORTS", test_result);
1359 	}
1360 
1361 	/*
1362 	 *   * GetDoublei_v generates INVALID_VALUE when <target> is DEPTH_RANGE and
1363 	 *   <index> is greater than or equal to the value of MAX_VIEWPORTS;
1364 	 */
1365 	if (glu::isContextTypeGLCore(context_type))
1366 	{
1367 		getDepthHelper<GLdouble>(depthFunc, max_viewports, test_result);
1368 	}
1369 	else
1370 	{
1371 		DE_ASSERT(glu::isContextTypeES(context_type));
1372 		getDepthHelper<GLfloat>(depthFunc, max_viewports, test_result);
1373 	}
1374 
1375 	/* Set result */
1376 	if (true == test_result)
1377 	{
1378 		m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
1379 	}
1380 	else
1381 	{
1382 		m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1383 	}
1384 
1385 	/* Done */
1386 	return tcu::TestNode::STOP;
1387 }
1388 
1389 /** Check if glGetError returns expected error
1390  *
1391  * @param expected_error Expected error code
1392  * @param description    Description of test case
1393  * @param out_result     Set to false if the current error is not equal to expected one
1394  **/
checkGLError(GLenum expected_error,const GLchar * description,bool & out_result)1395 void APIErrors::checkGLError(GLenum expected_error, const GLchar* description, bool& out_result)
1396 {
1397 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1398 
1399 	GLenum error = gl.getError();
1400 
1401 	if (expected_error != error)
1402 	{
1403 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Test case fail. Description: " << description
1404 											<< " Invalid error: " << glu::getErrorStr(error)
1405 											<< " expected: " << glu::getErrorStr(expected_error)
1406 											<< tcu::TestLog::EndMessage;
1407 
1408 		out_result = false;
1409 	}
1410 }
1411 
1412 /** Constructor
1413  *
1414  * @param context          Test context
1415  **/
Queries(deqp::Context & context,const glcts::ExtParameters & extParams)1416 Queries::Queries(deqp::Context& context, const glcts::ExtParameters& extParams)
1417 	: TestCaseBase(context, extParams, "queries", "Test verifies initial state of API")
1418 {
1419 	/* Nothing to be done here */
1420 }
1421 
1422 template <typename T>
depthRangeInitialValuesHelper(Utils::DepthFuncWrapper & depthFunc,GLint max_viewports,bool & test_result,T *)1423 void Queries::depthRangeInitialValuesHelper(Utils::DepthFuncWrapper& depthFunc, GLint max_viewports, bool& test_result,
1424 											T*)
1425 {
1426 	std::vector<T> data;
1427 	data.resize(max_viewports * 2 /* near + far */);
1428 
1429 	for (GLint i = 0; i < max_viewports; ++i)
1430 	{
1431 		depthFunc.getDepthi_v(GL_DEPTH_RANGE, i, &data[i * 2]);
1432 		GLU_EXPECT_NO_ERROR(depthFunc.getFunctions().getError(), "getDouble/Floati_v");
1433 	}
1434 
1435 	for (GLint i = 0; i < max_viewports; ++i)
1436 	{
1437 		GLint near = (GLint)data[2 * i + 0];
1438 		GLint far  = (GLint)data[2 * i + 1];
1439 
1440 		if ((0.0 != near) || (1.0 != far))
1441 		{
1442 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid initial depth range [" << i
1443 												<< "]: " << near << " : " << far << " expected: 0.0 : 1.0"
1444 												<< tcu::TestLog::EndMessage;
1445 
1446 			test_result = false;
1447 			break;
1448 		}
1449 	}
1450 }
1451 /** Execute test
1452  *
1453  * @return tcu::TestNode::CONTINUE after executing test case, tcu::TestNode::STOP otherwise
1454  **/
iterate()1455 tcu::TestNode::IterateResult Queries::iterate()
1456 {
1457 	if (!m_is_viewport_array_supported)
1458 	{
1459 		throw tcu::NotSupportedError(VIEWPORT_ARRAY_NOT_SUPPORTED, "", __FILE__, __LINE__);
1460 	}
1461 
1462 	/* GL entry points */
1463 	const glw::Functions&   gl			 = m_context.getRenderContext().getFunctions();
1464 	const glu::ContextType& context_type = m_context.getRenderContext().getType();
1465 	Utils::DepthFuncWrapper depthFunc(m_context);
1466 
1467 	/* Test result */
1468 	bool test_result = true;
1469 
1470 	GLint   layer_provoking_vertex	= 0;
1471 	GLint   max_viewports			  = 0;
1472 	GLfloat max_renderbuffer_size	 = 0.0f;
1473 	GLfloat max_viewport_dims[2]	  = { 0.0f, 0.0f };
1474 	GLfloat viewport_bounds_range[2]  = { 0.0, 0.0f };
1475 	GLint   viewport_provoking_vertex = 0;
1476 	GLint   viewport_subpixel_bits	= -1;
1477 
1478 	gl.getIntegerv(GL_LAYER_PROVOKING_VERTEX, &layer_provoking_vertex);
1479 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
1480 
1481 	gl.getIntegerv(GL_MAX_VIEWPORTS, &max_viewports);
1482 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
1483 
1484 	gl.getFloatv(GL_MAX_RENDERBUFFER_SIZE, &max_renderbuffer_size);
1485 	GLU_EXPECT_NO_ERROR(gl.getError(), "getFloatv");
1486 
1487 	gl.getFloatv(GL_MAX_VIEWPORT_DIMS, max_viewport_dims);
1488 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetFloatv");
1489 
1490 	gl.getFloatv(GL_VIEWPORT_BOUNDS_RANGE, viewport_bounds_range);
1491 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetFloatv");
1492 
1493 	gl.getIntegerv(GL_VIEWPORT_INDEX_PROVOKING_VERTEX, &viewport_provoking_vertex);
1494 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
1495 
1496 	gl.getIntegerv(GL_VIEWPORT_SUBPIXEL_BITS, &viewport_subpixel_bits);
1497 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
1498 
1499 	const GLint window_width  = m_context.getRenderContext().getRenderTarget().getWidth();
1500 	const GLint window_height = m_context.getRenderContext().getRenderTarget().getHeight();
1501 
1502 	/*
1503 	 *   * Initial dimensions of VIEWPORT returned by GetFloati_v match dimensions of
1504 	 *   the window into which GL is rendering;
1505 	 */
1506 	{
1507 		std::vector<GLfloat> data;
1508 		data.resize(max_viewports * 4 /* x + y + w+ h */);
1509 
1510 		for (GLint i = 0; i < max_viewports; ++i)
1511 		{
1512 			gl.getFloati_v(GL_VIEWPORT, i, &data[i * 4]);
1513 			GLU_EXPECT_NO_ERROR(gl.getError(), "GetFloati_v");
1514 		}
1515 
1516 		for (GLint i = 0; i < max_viewports; ++i)
1517 		{
1518 			GLint viewport_width  = (GLint)data[4 * i + 2];
1519 			GLint viewport_height = (GLint)data[4 * i + 3];
1520 
1521 			if ((window_width != viewport_width) || (window_height != viewport_height))
1522 			{
1523 				m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid initial viewport [" << i
1524 													<< "] dimennsions: " << viewport_width << " x " << viewport_height
1525 													<< " expected: " << window_width << " x " << window_height
1526 													<< tcu::TestLog::EndMessage;
1527 
1528 				test_result = false;
1529 				break;
1530 			}
1531 		}
1532 	}
1533 
1534 	/*
1535 	 *   * Initial values of DEPTH_RANGE returned by GetDoublei_v are [0, 1];
1536 	 */
1537 	if (glu::isContextTypeGLCore(context_type))
1538 	{
1539 		depthRangeInitialValuesHelper<GLdouble>(depthFunc, max_viewports, test_result);
1540 	}
1541 	else
1542 	{
1543 		DE_ASSERT(glu::isContextTypeES(context_type));
1544 		depthRangeInitialValuesHelper<GLfloat>(depthFunc, max_viewports, test_result);
1545 	}
1546 
1547 	/*
1548 	 *   * Initial state of SCISSOR_TEST returned by IsEnabledi is FALSE;
1549 	 */
1550 	{
1551 		for (GLint i = 0; i < max_viewports; ++i)
1552 		{
1553 			if (GL_FALSE != gl.isEnabledi(GL_SCISSOR_TEST, i))
1554 			{
1555 				m_context.getTestContext().getLog() << tcu::TestLog::Message << "Scissor test is enabled at " << i
1556 													<< ". Expected disabled." << tcu::TestLog::EndMessage;
1557 
1558 				test_result = false;
1559 				break;
1560 			}
1561 		}
1562 	}
1563 
1564 	/*
1565 	 *   * Initial dimensions of SCISSOR_BOX returned by GetIntegeri_v are either
1566 	 *   zeros or match dimensions of the window into which GL is rendering;
1567 	 */
1568 	{
1569 		std::vector<GLint> data;
1570 		data.resize(max_viewports * 4 /* x + y + w+ h */);
1571 
1572 		for (GLint i = 0; i < max_viewports; ++i)
1573 		{
1574 			gl.getIntegeri_v(GL_SCISSOR_BOX, i, &data[i * 4]);
1575 			GLU_EXPECT_NO_ERROR(gl.getError(), "getIntegeri_v");
1576 		}
1577 
1578 		for (GLint i = 0; i < max_viewports; ++i)
1579 		{
1580 			GLint scissor_width  = data[4 * i + 2];
1581 			GLint scissor_height = data[4 * i + 3];
1582 
1583 			if ((window_width != scissor_width) || (window_height != scissor_height))
1584 			{
1585 				m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid initial scissor box [" << i
1586 													<< "] dimennsions: " << scissor_width << " x " << scissor_height
1587 													<< " expected: " << window_width << " x " << window_height
1588 													<< tcu::TestLog::EndMessage;
1589 
1590 				test_result = false;
1591 				break;
1592 			}
1593 		}
1594 	}
1595 
1596 	/*
1597 	 *   * Dimensions of MAX_VIEWPORT_DIMS returned by GetFloati_v are at least
1598 	 *   as big as supported dimensions of render buffers, see MAX_RENDERBUFFER_SIZE;
1599 	 */
1600 	{
1601 		if ((max_viewport_dims[0] < max_renderbuffer_size) || (max_viewport_dims[1] < max_renderbuffer_size))
1602 		{
1603 			m_context.getTestContext().getLog()
1604 				<< tcu::TestLog::Message << "Invalid MAX_VIEWPORT_DIMS: " << max_viewport_dims[0] << " x "
1605 				<< max_viewport_dims[1] << " expected: " << max_renderbuffer_size << " x " << max_renderbuffer_size
1606 				<< tcu::TestLog::EndMessage;
1607 
1608 			test_result = false;
1609 		}
1610 	}
1611 
1612 	/*
1613 	 *   * Value of MAX_VIEWPORTS returned by GetIntegeri_v is at least 16;
1614 	 */
1615 	{
1616 		if (16 > max_viewports)
1617 		{
1618 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid MAX_VIEWPORTS: " << max_viewports
1619 												<< " expected at least 16." << tcu::TestLog::EndMessage;
1620 
1621 			test_result = false;
1622 		}
1623 	}
1624 
1625 	/*
1626 	 *   * Value of VIEWPORT_SUBPIXEL_BITS returned by GetIntegeri_v is at least 0;
1627 	 */
1628 	{
1629 		if (0 > viewport_subpixel_bits)
1630 		{
1631 			m_context.getTestContext().getLog() << tcu::TestLog::Message
1632 												<< "Invalid VIEWPORT_SUBPIXEL_BITS: " << viewport_subpixel_bits
1633 												<< " expected at least 0." << tcu::TestLog::EndMessage;
1634 
1635 			test_result = false;
1636 		}
1637 	}
1638 
1639 	/*
1640 	 *   * Values of VIEWPORT_BOUNDS_RANGE returned by GetFloatv are
1641 	 *   at least [-32768, 32767];
1642 	 */
1643 	{
1644 		if ((-32768.0f < viewport_bounds_range[0]) || (32767.0f > viewport_bounds_range[1]))
1645 		{
1646 			m_context.getTestContext().getLog()
1647 				<< tcu::TestLog::Message << "Invalid VIEWPORT_BOUNDS_RANGE: " << viewport_bounds_range[0] << " : "
1648 				<< viewport_bounds_range[1] << " expected at least: -32768.0f : 32767.0f" << tcu::TestLog::EndMessage;
1649 
1650 			test_result = false;
1651 		}
1652 	}
1653 
1654 	/*
1655 	 *   * Values of LAYER_PROVOKING_VERTEX and VIEWPORT_INDEX_PROVOKING_VERTEX
1656 	 *   returned by GetIntegerv are located in the following set
1657 	 *   { FIRST_VERTEX_CONVENTION, LAST_VERTEX_CONVENTION, PROVOKING_VERTEX,
1658 	 *   UNDEFINED_VERTEX };
1659 	 */
1660 	{
1661 		switch (layer_provoking_vertex)
1662 		{
1663 		case GL_FIRST_VERTEX_CONVENTION:
1664 		case GL_LAST_VERTEX_CONVENTION:
1665 		case GL_PROVOKING_VERTEX:
1666 		case GL_UNDEFINED_VERTEX:
1667 			break;
1668 		default:
1669 			m_context.getTestContext().getLog() << tcu::TestLog::Message
1670 												<< "Invalid LAYER_PROVOKING_VERTEX: " << layer_provoking_vertex
1671 												<< tcu::TestLog::EndMessage;
1672 
1673 			test_result = false;
1674 		}
1675 
1676 		switch (viewport_provoking_vertex)
1677 		{
1678 		case GL_FIRST_VERTEX_CONVENTION:
1679 		case GL_LAST_VERTEX_CONVENTION:
1680 		case GL_PROVOKING_VERTEX:
1681 		case GL_UNDEFINED_VERTEX:
1682 			break;
1683 		default:
1684 			m_context.getTestContext().getLog() << tcu::TestLog::Message
1685 												<< "Invalid LAYER_PROVOKING_VERTEX: " << layer_provoking_vertex
1686 												<< tcu::TestLog::EndMessage;
1687 
1688 			test_result = false;
1689 		}
1690 	}
1691 
1692 	/* Set result */
1693 	if (true == test_result)
1694 	{
1695 		m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
1696 	}
1697 	else
1698 	{
1699 		m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1700 	}
1701 
1702 	/* Done */
1703 	return tcu::TestNode::STOP;
1704 }
1705 
1706 /* Constants used by ViewportAPI */
1707 const GLuint ViewportAPI::m_n_elements = 4;
1708 
1709 /** Constructor
1710  *
1711  * @param context          Test context
1712  **/
ViewportAPI(deqp::Context & context,const glcts::ExtParameters & extParams)1713 ViewportAPI::ViewportAPI(deqp::Context& context, const glcts::ExtParameters& extParams)
1714 	: TestCaseBase(context, extParams, "viewport_api", "Test verifies that \viewport api\" works as expected")
1715 {
1716 	/* Nothing to be done here */
1717 }
1718 
1719 /** Execute test
1720  *
1721  * @return tcu::TestNode::CONTINUE after executing test case, tcu::TestNode::STOP otherwise
1722  **/
iterate()1723 tcu::TestNode::IterateResult ViewportAPI::iterate()
1724 {
1725 	if (!m_is_viewport_array_supported)
1726 	{
1727 		throw tcu::NotSupportedError(VIEWPORT_ARRAY_NOT_SUPPORTED, "", __FILE__, __LINE__);
1728 	}
1729 
1730 	/* GL entry points */
1731 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1732 
1733 	/* Test result */
1734 	bool test_result = true;
1735 
1736 	GLint max_viewports = 0;
1737 
1738 	gl.getIntegerv(GL_MAX_VIEWPORTS, &max_viewports);
1739 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
1740 
1741 	std::vector<GLfloat> scissor_box_data_a;
1742 	std::vector<GLfloat> scissor_box_data_b;
1743 
1744 	scissor_box_data_a.resize(max_viewports * m_n_elements);
1745 	scissor_box_data_b.resize(max_viewports * m_n_elements);
1746 
1747 	/*
1748 	 *   - get initial dimensions of VIEWPORT for all MAX_VIEWPORTS indices;
1749 	 *   - change location and dimensions of all indices at once with
1750 	 *   ViewportArrayv;
1751 	 *   - get VIEWPORT for all MAX_VIEWPORTS indices and verify results;
1752 	 */
1753 	getViewports(max_viewports, scissor_box_data_a);
1754 
1755 	for (GLint i = 0; i < max_viewports; ++i)
1756 	{
1757 		scissor_box_data_a[i * m_n_elements + 0] += 0.125f;
1758 		scissor_box_data_a[i * m_n_elements + 1] += 0.125f;
1759 		scissor_box_data_a[i * m_n_elements + 2] -= 0.125f;
1760 		scissor_box_data_a[i * m_n_elements + 3] -= 0.125f;
1761 	}
1762 
1763 	gl.viewportArrayv(0, max_viewports, &scissor_box_data_a[0]);
1764 	GLU_EXPECT_NO_ERROR(gl.getError(), "viewportArrayv");
1765 
1766 	getViewports(max_viewports, scissor_box_data_b);
1767 	compareViewports(scissor_box_data_a, scissor_box_data_b, "viewportArrayv", test_result);
1768 
1769 	/*
1770 	 *   - for each index:
1771 	 *     * modify with ViewportIndexedf,
1772 	 *     * get VIEWPORT for all MAX_VIEWPORTS indices and verify results;
1773 	 */
1774 	for (GLint i = 0; i < max_viewports; ++i)
1775 	{
1776 		scissor_box_data_b[i * m_n_elements + 0] = 0.25f;
1777 		scissor_box_data_b[i * m_n_elements + 1] = 0.25f;
1778 		scissor_box_data_b[i * m_n_elements + 2] = 0.75f;
1779 		scissor_box_data_b[i * m_n_elements + 3] = 0.75f;
1780 
1781 		gl.viewportIndexedf(i, 0.25f, 0.25f, 0.75f, 0.75f);
1782 		GLU_EXPECT_NO_ERROR(gl.getError(), "viewportIndexedf");
1783 
1784 		getViewports(max_viewports, scissor_box_data_a);
1785 		compareViewports(scissor_box_data_a, scissor_box_data_b, "viewportIndexedf", test_result);
1786 	}
1787 
1788 	/*
1789 	 *   - for each index:
1790 	 *     * modify with ViewportIndexedfv,
1791 	 *     * get VIEWPORT for all MAX_VIEWPORTS indices and verify results;
1792 	 */
1793 	for (GLint i = 0; i < max_viewports; ++i)
1794 	{
1795 		scissor_box_data_a[i * m_n_elements + 0] = 0.375f;
1796 		scissor_box_data_a[i * m_n_elements + 1] = 0.375f;
1797 		scissor_box_data_a[i * m_n_elements + 2] = 0.625f;
1798 		scissor_box_data_a[i * m_n_elements + 3] = 0.625f;
1799 
1800 		gl.viewportIndexedfv(i, &scissor_box_data_a[i * m_n_elements]);
1801 		GLU_EXPECT_NO_ERROR(gl.getError(), "viewportIndexedfv");
1802 
1803 		getViewports(max_viewports, scissor_box_data_b);
1804 		compareViewports(scissor_box_data_a, scissor_box_data_b, "viewportIndexedfv", test_result);
1805 	}
1806 
1807 	/*
1808 	 *   - for each index:
1809 	 *     * modify all indices before and after current one with ViewportArrayv,
1810 	 *     * get VIEWPORT for all MAX_VIEWPORTS indices and verify results;
1811 	 */
1812 	for (GLint i = 0; i < max_viewports; ++i)
1813 	{
1814 		const GLfloat value = (0 == i % 2) ? 1.0f : 0.25f;
1815 
1816 		for (GLint j = 0; j < i; ++j)
1817 		{
1818 			scissor_box_data_b[j * m_n_elements + 0] = value;
1819 			scissor_box_data_b[j * m_n_elements + 1] = value;
1820 			scissor_box_data_b[j * m_n_elements + 2] = value;
1821 			scissor_box_data_b[j * m_n_elements + 3] = value;
1822 		}
1823 
1824 		for (GLint j = i + 1; j < max_viewports; ++j)
1825 		{
1826 			scissor_box_data_b[j * m_n_elements + 0] = value;
1827 			scissor_box_data_b[j * m_n_elements + 1] = value;
1828 			scissor_box_data_b[j * m_n_elements + 2] = value;
1829 			scissor_box_data_b[j * m_n_elements + 3] = value;
1830 		}
1831 
1832 		gl.viewportArrayv(0, max_viewports, &scissor_box_data_b[0]);
1833 		GLU_EXPECT_NO_ERROR(gl.getError(), "viewportArrayv");
1834 
1835 		getViewports(max_viewports, scissor_box_data_a);
1836 		compareViewports(scissor_box_data_a, scissor_box_data_b, "viewportArrayv", test_result);
1837 	}
1838 
1839 	/*
1840 	 *   - change location and dimensions of all indices at once with Viewport;
1841 	 *   - get VIEWPORT for all MAX_VIEWPORTS indices and verify results;
1842 	 */
1843 	for (GLint i = 0; i < max_viewports; ++i)
1844 	{
1845 		scissor_box_data_a[i * m_n_elements + 0] = 0.0f;
1846 		scissor_box_data_a[i * m_n_elements + 1] = 0.0f;
1847 		scissor_box_data_a[i * m_n_elements + 2] = 1.0f;
1848 		scissor_box_data_a[i * m_n_elements + 3] = 1.0f;
1849 	}
1850 
1851 	gl.viewport(0, 0, 1, 1);
1852 	GLU_EXPECT_NO_ERROR(gl.getError(), "viewport");
1853 
1854 	getViewports(max_viewports, scissor_box_data_b);
1855 	compareViewports(scissor_box_data_a, scissor_box_data_b, "viewport", test_result);
1856 
1857 	/* Set result */
1858 	if (true == test_result)
1859 	{
1860 		m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
1861 	}
1862 	else
1863 	{
1864 		m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1865 	}
1866 
1867 	/* Done */
1868 	return tcu::TestNode::STOP;
1869 }
1870 
1871 /** Compare two sets of viewport data (simple vector comparison)
1872  *
1873  * @param left        Left set
1874  * @param right       Right set
1875  * @param description Test case description
1876  * @param out_result  Set to false if sets are different, not modified otherwise
1877  **/
compareViewports(std::vector<GLfloat> & left,std::vector<GLfloat> & right,const GLchar * description,bool & out_result)1878 void ViewportAPI::compareViewports(std::vector<GLfloat>& left, std::vector<GLfloat>& right, const GLchar* description,
1879 								   bool& out_result)
1880 {
1881 	for (size_t i = 0; i < left.size(); ++i)
1882 	{
1883 		if (left[i] != right[i])
1884 		{
1885 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "Test case: " << description
1886 												<< " Invalid values [" << i << "] " << left[i] << " " << right[i]
1887 												<< tcu::TestLog::EndMessage;
1888 
1889 			out_result = false;
1890 		}
1891 	}
1892 }
1893 
1894 /** Get position of all viewports
1895  *
1896  * @param max_viewports Number of viewports to capture, MAX_VIEWPORTS
1897  * @param data          Memory buffer prepared for captured data
1898  **/
getViewports(GLint max_viewports,std::vector<GLfloat> & out_data)1899 void ViewportAPI::getViewports(GLint max_viewports, std::vector<GLfloat>& out_data)
1900 {
1901 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1902 
1903 	for (GLint i = 0; i < max_viewports; ++i)
1904 	{
1905 		gl.getFloati_v(GL_VIEWPORT, i, &out_data[i * 4]);
1906 		GLU_EXPECT_NO_ERROR(gl.getError(), "getFloati_v");
1907 	}
1908 }
1909 
1910 /* Constants used by ScissorAPI */
1911 const GLuint ScissorAPI::m_n_elements = 4;
1912 
1913 /** Constructor
1914  *
1915  * @param context          Test context
1916  **/
ScissorAPI(deqp::Context & context,const glcts::ExtParameters & extParams)1917 ScissorAPI::ScissorAPI(deqp::Context& context, const glcts::ExtParameters& extParams)
1918 	: TestCaseBase(context, extParams, "scissor_api", "Test verifies that \"scissor api\" works as expected")
1919 {
1920 	/* Nothing to be done here */
1921 }
1922 
1923 /** Execute test
1924  *
1925  * @return tcu::TestNode::CONTINUE after executing test case, tcu::TestNode::STOP otherwise
1926  **/
iterate()1927 tcu::TestNode::IterateResult ScissorAPI::iterate()
1928 {
1929 	if (!m_is_viewport_array_supported)
1930 	{
1931 		throw tcu::NotSupportedError(VIEWPORT_ARRAY_NOT_SUPPORTED, "", __FILE__, __LINE__);
1932 	}
1933 
1934 	/* GL entry points */
1935 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1936 
1937 	/* Test result */
1938 	bool test_result = true;
1939 
1940 	GLint max_viewports = 0;
1941 
1942 	gl.getIntegerv(GL_MAX_VIEWPORTS, &max_viewports);
1943 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
1944 
1945 	std::vector<GLint> scissor_box_data_a;
1946 	std::vector<GLint> scissor_box_data_b;
1947 
1948 	scissor_box_data_a.resize(max_viewports * m_n_elements);
1949 	scissor_box_data_b.resize(max_viewports * m_n_elements);
1950 
1951 	/*
1952 	 *   - get initial dimensions of SCISSOR_BOX for all MAX_VIEWPORTS indices;
1953 	 *   - change location and dimensions of all indices at once with
1954 	 *   ScissorArrayv;
1955 	 *   - get SCISSOR_BOX for all MAX_VIEWPORTS indices and verify results;
1956 	 */
1957 	getScissorBoxes(max_viewports, scissor_box_data_a);
1958 
1959 	for (GLint i = 0; i < max_viewports; ++i)
1960 	{
1961 		scissor_box_data_a[i * m_n_elements + 0] += 1;
1962 		scissor_box_data_a[i * m_n_elements + 1] += 1;
1963 		scissor_box_data_a[i * m_n_elements + 2] -= 1;
1964 		scissor_box_data_a[i * m_n_elements + 3] -= 1;
1965 	}
1966 
1967 	gl.scissorArrayv(0, max_viewports, &scissor_box_data_a[0]);
1968 	GLU_EXPECT_NO_ERROR(gl.getError(), "scissorArrayv");
1969 
1970 	getScissorBoxes(max_viewports, scissor_box_data_b);
1971 	compareScissorBoxes(scissor_box_data_a, scissor_box_data_b, "scissorArrayv", test_result);
1972 
1973 	/*
1974 	 *   - for each index:
1975 	 *     * modify with ScissorIndexed,
1976 	 *     * get SCISSOR_BOX for all MAX_VIEWPORTS indices and verify results;
1977 	 */
1978 	for (GLint i = 0; i < max_viewports; ++i)
1979 	{
1980 		scissor_box_data_b[i * m_n_elements + 0] = 4;
1981 		scissor_box_data_b[i * m_n_elements + 1] = 4;
1982 		scissor_box_data_b[i * m_n_elements + 2] = 8;
1983 		scissor_box_data_b[i * m_n_elements + 3] = 8;
1984 
1985 		gl.scissorIndexed(i, 4, 4, 8, 8);
1986 		GLU_EXPECT_NO_ERROR(gl.getError(), "scissorIndexed");
1987 
1988 		getScissorBoxes(max_viewports, scissor_box_data_a);
1989 		compareScissorBoxes(scissor_box_data_a, scissor_box_data_b, "scissorIndexed", test_result);
1990 	}
1991 
1992 	/*
1993 	 *   - for each index:
1994 	 *     * modify with ScissorIndexedv,
1995 	 *     * get SCISSOR_BOX for all MAX_VIEWPORTS indices and verify results;
1996 	 */
1997 	for (GLint i = 0; i < max_viewports; ++i)
1998 	{
1999 		scissor_box_data_a[i * m_n_elements + 0] = 8;
2000 		scissor_box_data_a[i * m_n_elements + 1] = 8;
2001 		scissor_box_data_a[i * m_n_elements + 2] = 12;
2002 		scissor_box_data_a[i * m_n_elements + 3] = 12;
2003 
2004 		gl.scissorIndexedv(i, &scissor_box_data_a[i * m_n_elements]);
2005 		GLU_EXPECT_NO_ERROR(gl.getError(), "scissorIndexedv");
2006 
2007 		getScissorBoxes(max_viewports, scissor_box_data_b);
2008 		compareScissorBoxes(scissor_box_data_a, scissor_box_data_b, "scissorIndexedv", test_result);
2009 	}
2010 
2011 	/*
2012 	 *   - for each index:
2013 	 *     * modify all indices before and after current one with ScissorArrayv,
2014 	 *     * get SCISSOR_BOX for all MAX_VIEWPORTS indices and verify results;
2015 	 */
2016 	for (GLint i = 0; i < max_viewports; ++i)
2017 	{
2018 		const GLint value = (0 == i % 2) ? 1 : 4;
2019 
2020 		for (GLint j = 0; j < i; ++j)
2021 		{
2022 			scissor_box_data_b[j * m_n_elements + 0] = value;
2023 			scissor_box_data_b[j * m_n_elements + 1] = value;
2024 			scissor_box_data_b[j * m_n_elements + 2] = value;
2025 			scissor_box_data_b[j * m_n_elements + 3] = value;
2026 		}
2027 
2028 		for (GLint j = i + 1; j < max_viewports; ++j)
2029 		{
2030 			scissor_box_data_b[j * m_n_elements + 0] = value;
2031 			scissor_box_data_b[j * m_n_elements + 1] = value;
2032 			scissor_box_data_b[j * m_n_elements + 2] = value;
2033 			scissor_box_data_b[j * m_n_elements + 3] = value;
2034 		}
2035 
2036 		gl.scissorArrayv(0, max_viewports, &scissor_box_data_b[0]);
2037 		GLU_EXPECT_NO_ERROR(gl.getError(), "scissorArrayv");
2038 
2039 		getScissorBoxes(max_viewports, scissor_box_data_a);
2040 		compareScissorBoxes(scissor_box_data_a, scissor_box_data_b, "scissorArrayv", test_result);
2041 	}
2042 
2043 	/*
2044 	 *   - change location and dimensions of all indices at once with Scissor;
2045 	 *   - get SCISSOR_BOX for all MAX_VIEWPORTS indices and verify results;
2046 	 */
2047 	for (GLint i = 0; i < max_viewports; ++i)
2048 	{
2049 		scissor_box_data_a[i * m_n_elements + 0] = 0;
2050 		scissor_box_data_a[i * m_n_elements + 1] = 0;
2051 		scissor_box_data_a[i * m_n_elements + 2] = 1;
2052 		scissor_box_data_a[i * m_n_elements + 3] = 1;
2053 	}
2054 
2055 	gl.scissor(0, 0, 1, 1);
2056 	GLU_EXPECT_NO_ERROR(gl.getError(), "scissor");
2057 
2058 	getScissorBoxes(max_viewports, scissor_box_data_b);
2059 	compareScissorBoxes(scissor_box_data_a, scissor_box_data_b, "scissor", test_result);
2060 
2061 	/* Set result */
2062 	if (true == test_result)
2063 	{
2064 		m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
2065 	}
2066 	else
2067 	{
2068 		m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2069 	}
2070 
2071 	/* Done */
2072 	return tcu::TestNode::STOP;
2073 }
2074 
2075 /** Compare two sets of scissor box data (simple vector comparison)
2076  *
2077  * @param left        Left set
2078  * @param right       Right set
2079  * @param description Test case description
2080  * @param out_result  Set to false if sets are different, not modified otherwise
2081  **/
compareScissorBoxes(std::vector<GLint> & left,std::vector<GLint> & right,const GLchar * description,bool & out_result)2082 void ScissorAPI::compareScissorBoxes(std::vector<GLint>& left, std::vector<GLint>& right, const GLchar* description,
2083 									 bool& out_result)
2084 {
2085 	for (size_t i = 0; i < left.size(); ++i)
2086 	{
2087 		if (left[i] != right[i])
2088 		{
2089 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "Test case: " << description
2090 												<< " Invalid values [" << i << "] " << left[i] << " " << right[i]
2091 												<< tcu::TestLog::EndMessage;
2092 
2093 			out_result = false;
2094 		}
2095 	}
2096 }
2097 
2098 /** Get position of all scissor boxes
2099  *
2100  * @param max_viewports Number of scissor boxes to capture, MAX_VIEWPORTS
2101  * @param data          Memory buffer prepared for captured data
2102  **/
getScissorBoxes(GLint max_viewports,std::vector<GLint> & out_data)2103 void ScissorAPI::getScissorBoxes(GLint max_viewports, std::vector<GLint>& out_data)
2104 {
2105 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2106 
2107 	for (GLint i = 0; i < max_viewports; ++i)
2108 	{
2109 		gl.getIntegeri_v(GL_SCISSOR_BOX, i, &out_data[i * 4]);
2110 		GLU_EXPECT_NO_ERROR(gl.getError(), "getIntegeri_v");
2111 	}
2112 }
2113 
2114 /* Constants used by DepthRangeAPI */
2115 const GLuint DepthRangeAPI::m_n_elements = 2 /* near + far */;
2116 
2117 /** Constructor
2118  *
2119  * @param context          Test context
2120  **/
DepthRangeAPI(deqp::Context & context,const glcts::ExtParameters & extParams)2121 DepthRangeAPI::DepthRangeAPI(deqp::Context& context, const glcts::ExtParameters& extParams)
2122 	: TestCaseBase(context, extParams, "depth_range_api", "Test verifies that \"depth range api\" works as expected")
2123 {
2124 	/* Nothing to be done here */
2125 }
2126 
2127 /** Execute test
2128  *
2129  * @return tcu::TestNode::CONTINUE after executing test case, tcu::TestNode::STOP otherwise
2130  **/
iterate()2131 tcu::TestNode::IterateResult DepthRangeAPI::iterate()
2132 {
2133 	if (!m_is_viewport_array_supported)
2134 	{
2135 		throw tcu::NotSupportedError(VIEWPORT_ARRAY_NOT_SUPPORTED, "", __FILE__, __LINE__);
2136 	}
2137 
2138 	bool					test_result;
2139 	const glu::ContextType& context_type = m_context.getRenderContext().getType();
2140 
2141 	if (glu::isContextTypeGLCore(context_type))
2142 	{
2143 		test_result = iterateHelper<GLdouble>();
2144 	}
2145 	else
2146 	{
2147 		DE_ASSERT(glu::isContextTypeES(context_type));
2148 		test_result = iterateHelper<GLfloat>();
2149 	}
2150 
2151 	/* Set result */
2152 	if (true == test_result)
2153 	{
2154 		m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
2155 	}
2156 	else
2157 	{
2158 		m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2159 	}
2160 
2161 	/* Done */
2162 	return tcu::TestNode::STOP;
2163 }
2164 
2165 template <typename T>
iterateHelper(T *)2166 bool DepthRangeAPI::iterateHelper(T*)
2167 {
2168 	/* GL entry points */
2169 	const glw::Functions&   gl = m_context.getRenderContext().getFunctions();
2170 	Utils::DepthFuncWrapper depthFunc(m_context);
2171 
2172 	bool test_result = true;
2173 
2174 	GLint max_viewports = 0;
2175 
2176 	gl.getIntegerv(GL_MAX_VIEWPORTS, &max_viewports);
2177 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
2178 
2179 	std::vector<T> depth_range_data_a;
2180 	std::vector<T> depth_range_data_b;
2181 
2182 	depth_range_data_a.resize(max_viewports * m_n_elements);
2183 	depth_range_data_b.resize(max_viewports * m_n_elements);
2184 
2185 	/*
2186 	 *   - get initial values of DEPTH_RANGE for all MAX_VIEWPORTS indices;
2187 	 *   - change values of all indices at once with DepthRangeArrayv;
2188 	 *   - get DEPTH_RANGE for all MAX_VIEWPORTS indices and verify results;
2189 	 */
2190 	getDepthRanges(depthFunc, max_viewports, depth_range_data_a);
2191 
2192 	for (GLint i = 0; i < max_viewports; ++i)
2193 	{
2194 		depth_range_data_a[i * m_n_elements + 0] += 0.125;
2195 		depth_range_data_a[i * m_n_elements + 1] -= 0.125;
2196 	}
2197 
2198 	depthFunc.depthRangeArray(0, max_viewports, &depth_range_data_a[0]);
2199 	GLU_EXPECT_NO_ERROR(gl.getError(), "depthRangeArray");
2200 
2201 	getDepthRanges(depthFunc, max_viewports, depth_range_data_b);
2202 	compareDepthRanges(depth_range_data_a, depth_range_data_b, "depthRangeArray", test_result);
2203 
2204 	/*
2205 	 *   - for each index:
2206 	 *     * modify with DepthRangeIndexed,
2207 	 *     * get DEPTH_RANGE for all MAX_VIEWPORTS indices and verify results;
2208 	 */
2209 	for (GLint i = 0; i < max_viewports; ++i)
2210 	{
2211 		depth_range_data_b[i * m_n_elements + 0] = 0.25;
2212 		depth_range_data_b[i * m_n_elements + 1] = 0.75;
2213 
2214 		depthFunc.depthRangeIndexed(i, (T)0.25, (T)0.75);
2215 		GLU_EXPECT_NO_ERROR(gl.getError(), "depthRangeIndexed");
2216 
2217 		getDepthRanges(depthFunc, max_viewports, depth_range_data_a);
2218 		compareDepthRanges(depth_range_data_a, depth_range_data_b, "depthRangeIndexed", test_result);
2219 	}
2220 
2221 	/*
2222 	 *   - for each index:
2223 	 *     * modify all indices before and after current one with DepthRangeArrayv,
2224 	 *     * get DEPTH_RANGE for all MAX_VIEWPORTS indices and verify results;
2225 	 */
2226 	for (GLint i = 0; i < max_viewports; ++i)
2227 	{
2228 		const T value = (0 == i % 2) ? T(1.0) : T(0.25);
2229 
2230 		for (GLint j = 0; j < i; ++j)
2231 		{
2232 			depth_range_data_b[j * m_n_elements + 0] = value;
2233 			depth_range_data_b[j * m_n_elements + 1] = value;
2234 		}
2235 
2236 		for (GLint j = i + 1; j < max_viewports; ++j)
2237 		{
2238 			depth_range_data_b[j * m_n_elements + 0] = value;
2239 			depth_range_data_b[j * m_n_elements + 1] = value;
2240 		}
2241 
2242 		depthFunc.depthRangeArray(0, max_viewports, &depth_range_data_b[0]);
2243 		GLU_EXPECT_NO_ERROR(gl.getError(), "depthRangeArray");
2244 
2245 		getDepthRanges(depthFunc, max_viewports, depth_range_data_a);
2246 		compareDepthRanges(depth_range_data_a, depth_range_data_b, "depthRangeArray", test_result);
2247 	}
2248 
2249 	/*
2250 	 *   - change values of all indices at once with DepthRange;
2251 	 *   - get DEPTH_RANGE for all MAX_VIEWPORTS indices and verify results;
2252 	 */
2253 	for (GLint i = 0; i < max_viewports; ++i)
2254 	{
2255 		depth_range_data_a[i * m_n_elements + 0] = 0.0f;
2256 		depth_range_data_a[i * m_n_elements + 1] = 1.0f;
2257 	}
2258 
2259 	depthFunc.depthRange((T)0.0, (T)1.0);
2260 	GLU_EXPECT_NO_ERROR(gl.getError(), "depthRange");
2261 
2262 	getDepthRanges(depthFunc, max_viewports, depth_range_data_b);
2263 	compareDepthRanges(depth_range_data_a, depth_range_data_b, "depthRange", test_result);
2264 
2265 	return test_result;
2266 }
2267 
2268 /** Compare two sets of depth range data (simple vector comparison)
2269  *
2270  * @param left        Left set
2271  * @param right       Right set
2272  * @param description Test case description
2273  * @param out_result  Set to false if sets are different, not modified otherwise
2274  **/
2275 template <typename T>
compareDepthRanges(std::vector<T> & left,std::vector<T> & right,const GLchar * description,bool & out_result)2276 void DepthRangeAPI::compareDepthRanges(std::vector<T>& left, std::vector<T>& right, const GLchar* description,
2277 									   bool& out_result)
2278 {
2279 	for (size_t i = 0; i < left.size(); ++i)
2280 	{
2281 		if (left[i] != right[i])
2282 		{
2283 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "Test case: " << description
2284 												<< " Invalid values [" << i << "] " << left[i] << " " << right[i]
2285 												<< tcu::TestLog::EndMessage;
2286 			out_result = false;
2287 		}
2288 	}
2289 }
2290 
2291 /** Get all depth ranges
2292  *
2293  * @param max_viewports Number of viewports to capture, MAX_VIEWPORTS
2294  * @param data          Memory buffer prepared for captured data
2295  **/
2296 template <typename T>
getDepthRanges(Utils::DepthFuncWrapper & depthFunc,GLint max_viewports,std::vector<T> & out_data)2297 void DepthRangeAPI::getDepthRanges(Utils::DepthFuncWrapper& depthFunc, GLint max_viewports, std::vector<T>& out_data)
2298 {
2299 	for (GLint i = 0; i < max_viewports; ++i)
2300 	{
2301 		depthFunc.getDepthi_v(GL_DEPTH_RANGE, i, &out_data[i * m_n_elements]);
2302 		GLU_EXPECT_NO_ERROR(depthFunc.getFunctions().getError(), "getDouble/Floati_v");
2303 	}
2304 }
2305 
2306 /** Constructor
2307  *
2308  * @param context          Test context
2309  **/
ScissorTestStateAPI(deqp::Context & context,const glcts::ExtParameters & extParams)2310 ScissorTestStateAPI::ScissorTestStateAPI(deqp::Context& context, const glcts::ExtParameters& extParams)
2311 	: TestCaseBase(context, extParams, "scissor_test_state_api",
2312 				   "Test verifies that \"enable/disable api\" works as expected for scissor test")
2313 {
2314 	/* Nothing to be done here */
2315 }
2316 
2317 /** Execute test
2318  *
2319  * @return tcu::TestNode::CONTINUE after executing test case, tcu::TestNode::STOP otherwise
2320  **/
iterate()2321 tcu::TestNode::IterateResult ScissorTestStateAPI::iterate()
2322 {
2323 	if (!m_is_viewport_array_supported)
2324 	{
2325 		throw tcu::NotSupportedError(VIEWPORT_ARRAY_NOT_SUPPORTED, "", __FILE__, __LINE__);
2326 	}
2327 
2328 	/* GL entry points */
2329 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2330 
2331 	/* Test result */
2332 	bool test_result = true;
2333 
2334 	GLint max_viewports = 0;
2335 
2336 	gl.getIntegerv(GL_MAX_VIEWPORTS, &max_viewports);
2337 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
2338 
2339 	std::vector<GLboolean> scissor_test_states_a;
2340 	std::vector<GLboolean> scissor_test_states_b;
2341 
2342 	scissor_test_states_a.resize(max_viewports);
2343 	scissor_test_states_b.resize(max_viewports);
2344 
2345 	/*
2346 	 *   - get initial state of SCISSOR_TEST for all MAX_VIEWPORTS indices;
2347 	 *   - for each index:
2348 	 *     * toggle SCISSOR_TEST,
2349 	 *     * get state of SCISSOR_TEST for all MAX_VIEWPORTS indices and verify;
2350 	 *   - for each index:
2351 	 *     * toggle SCISSOR_TEST,
2352 	 *     * get state of SCISSOR_TEST for all MAX_VIEWPORTS indices and verify;
2353 	 */
2354 	getScissorTestStates(max_viewports, scissor_test_states_a);
2355 
2356 	for (GLint i = 0; i < max_viewports; ++i)
2357 	{
2358 		if (GL_FALSE == scissor_test_states_a[i])
2359 		{
2360 			gl.enablei(GL_SCISSOR_TEST, i);
2361 			GLU_EXPECT_NO_ERROR(gl.getError(), "Enablei");
2362 
2363 			scissor_test_states_a[i] = GL_TRUE;
2364 		}
2365 		else
2366 		{
2367 			gl.disablei(GL_SCISSOR_TEST, i);
2368 			GLU_EXPECT_NO_ERROR(gl.getError(), "Disablei");
2369 
2370 			scissor_test_states_a[i] = GL_FALSE;
2371 		}
2372 
2373 		getScissorTestStates(max_viewports, scissor_test_states_b);
2374 		compareScissorTestStates(scissor_test_states_a, scissor_test_states_b, "1st toggle", test_result);
2375 	}
2376 
2377 	for (GLint i = 0; i < max_viewports; ++i)
2378 	{
2379 		if (GL_FALSE == scissor_test_states_a[i])
2380 		{
2381 			gl.enablei(GL_SCISSOR_TEST, i);
2382 			GLU_EXPECT_NO_ERROR(gl.getError(), "Enablei");
2383 
2384 			scissor_test_states_a[i] = GL_TRUE;
2385 		}
2386 		else
2387 		{
2388 			gl.disablei(GL_SCISSOR_TEST, i);
2389 			GLU_EXPECT_NO_ERROR(gl.getError(), "Disablei");
2390 
2391 			scissor_test_states_a[i] = GL_FALSE;
2392 		}
2393 
2394 		getScissorTestStates(max_viewports, scissor_test_states_b);
2395 		compareScissorTestStates(scissor_test_states_a, scissor_test_states_b, "2nd toggle", test_result);
2396 	}
2397 
2398 	/*
2399 	 *   - enable SCISSOR_TEST for all indices at once with Enable;
2400 	 *   - get state of SCISSOR_TEST for all MAX_VIEWPORTS indices and verify;
2401 	 */
2402 	for (GLint i = 0; i < max_viewports; ++i)
2403 	{
2404 		scissor_test_states_a[i] = GL_TRUE;
2405 	}
2406 
2407 	gl.enable(GL_SCISSOR_TEST);
2408 	GLU_EXPECT_NO_ERROR(gl.getError(), "Enable");
2409 
2410 	getScissorTestStates(max_viewports, scissor_test_states_b);
2411 	compareScissorTestStates(scissor_test_states_a, scissor_test_states_b, "1st enable all", test_result);
2412 
2413 	/*
2414 	 *   - disable SCISSOR_TEST for all indices at once with Disable;
2415 	 *   - get state of SCISSOR_TEST for all MAX_VIEWPORTS indices and verify;
2416 	 */
2417 	for (GLint i = 0; i < max_viewports; ++i)
2418 	{
2419 		scissor_test_states_a[i] = GL_FALSE;
2420 	}
2421 
2422 	gl.disable(GL_SCISSOR_TEST);
2423 	GLU_EXPECT_NO_ERROR(gl.getError(), "Disable");
2424 
2425 	getScissorTestStates(max_viewports, scissor_test_states_b);
2426 	compareScissorTestStates(scissor_test_states_a, scissor_test_states_b, "Disable all", test_result);
2427 
2428 	/*
2429 	 *   - enable SCISSOR_TEST for all indices at once with Enable;
2430 	 *   - get state of SCISSOR_TEST for all MAX_VIEWPORTS indices and verify;
2431 	 */
2432 	for (GLint i = 0; i < max_viewports; ++i)
2433 	{
2434 		scissor_test_states_a[i] = GL_TRUE;
2435 	}
2436 
2437 	gl.enable(GL_SCISSOR_TEST);
2438 	GLU_EXPECT_NO_ERROR(gl.getError(), "Enable");
2439 
2440 	getScissorTestStates(max_viewports, scissor_test_states_b);
2441 	compareScissorTestStates(scissor_test_states_a, scissor_test_states_b, "2nd enable all", test_result);
2442 
2443 	/* Set result */
2444 	if (true == test_result)
2445 	{
2446 		m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
2447 	}
2448 	else
2449 	{
2450 		m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2451 	}
2452 
2453 	/* Done */
2454 	return tcu::TestNode::STOP;
2455 }
2456 
2457 /** Compare two sets of depth range data (simple vector comparison)
2458  *
2459  * @param left        Left set
2460  * @param right       Right set
2461  * @param description Test case description
2462  * @param out_result  Set to false if sets are different, not modified otherwise
2463  **/
compareScissorTestStates(std::vector<GLboolean> & left,std::vector<GLboolean> & right,const GLchar * description,bool & out_result)2464 void ScissorTestStateAPI::compareScissorTestStates(std::vector<GLboolean>& left, std::vector<GLboolean>& right,
2465 												   const GLchar* description, bool& out_result)
2466 {
2467 	for (size_t i = 0; i < left.size(); ++i)
2468 	{
2469 		if (left[i] != right[i])
2470 		{
2471 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "Test case: " << description
2472 												<< " Invalid values [" << i << "] " << left[i] << " " << right[i]
2473 												<< tcu::TestLog::EndMessage;
2474 
2475 			out_result = false;
2476 		}
2477 	}
2478 }
2479 
2480 /** Get all depth ranges
2481  *
2482  * @param max_viewports Number of viewports to capture, MAX_VIEWPORTS
2483  * @param data          Memory buffer prepared for captured data
2484  **/
getScissorTestStates(GLint max_viewports,std::vector<GLboolean> & out_data)2485 void ScissorTestStateAPI::getScissorTestStates(GLint max_viewports, std::vector<GLboolean>& out_data)
2486 {
2487 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2488 
2489 	for (GLint i = 0; i < max_viewports; ++i)
2490 	{
2491 		out_data[i] = gl.isEnabledi(GL_SCISSOR_TEST, i);
2492 		GLU_EXPECT_NO_ERROR(gl.getError(), "isEnabledi");
2493 	}
2494 }
2495 
2496 /* Constants used by DrawTestBase */
2497 const GLuint DrawTestBase::m_depth		  = 16;
2498 const GLuint DrawTestBase::m_height		  = 128;
2499 const GLuint DrawTestBase::m_width		  = 128;
2500 const GLuint DrawTestBase::m_r32f_height  = 2;
2501 const GLuint DrawTestBase::m_r32f_width   = 16;
2502 const GLuint DrawTestBase::m_r32ix4_depth = 4;
2503 
2504 /** Constructor
2505  *
2506  * @param context          Test context
2507  * @param test_name        Test name
2508  * @param test_description Test description
2509  **/
DrawTestBase(deqp::Context & context,const glcts::ExtParameters & extParams,const GLchar * test_name,const GLchar * test_description)2510 DrawTestBase::DrawTestBase(deqp::Context& context, const glcts::ExtParameters& extParams, const GLchar* test_name,
2511 						   const GLchar* test_description)
2512 	: TestCaseBase(context, extParams, test_name, test_description)
2513 {
2514 	/* Nothing to be done here */
2515 }
2516 
2517 /** Execute test
2518  *
2519  * @return tcu::TestNode::CONTINUE after executing test case, tcu::TestNode::STOP otherwise
2520  **/
iterate()2521 tcu::TestNode::IterateResult DrawTestBase::iterate()
2522 {
2523 	if (!m_is_viewport_array_supported)
2524 	{
2525 		throw tcu::NotSupportedError(VIEWPORT_ARRAY_NOT_SUPPORTED, "", __FILE__, __LINE__);
2526 	}
2527 
2528 	const glw::Functions&   gl			 = m_context.getRenderContext().getFunctions();
2529 	const glu::ContextType& context_type = m_context.getRenderContext().getType();
2530 
2531 	/* Test result */
2532 	bool test_result = true;
2533 
2534 	/* Get type of test */
2535 	const TEST_TYPE test_type = getTestType();
2536 
2537 	GLuint n_draw_calls = getDrawCallsNumber();
2538 	GLuint n_iterations = 0;
2539 	switch (test_type)
2540 	{
2541 	case VIEWPORT:
2542 	case SCISSOR:
2543 		n_iterations = 3;
2544 		break;
2545 	case DEPTHRANGE:
2546 	case PROVOKING:
2547 		n_iterations = 2;
2548 		break;
2549 	default:
2550 		TCU_FAIL("Invalid enum");
2551 	}
2552 
2553 	/* Get shader sources and specialize them */
2554 	const std::string& frag = getFragmentShader();
2555 	const std::string& geom = getGeometryShader();
2556 	const std::string& vert = getVertexShader();
2557 
2558 	const GLchar* frag_template = frag.c_str();
2559 	const GLchar* geom_template = geom.c_str();
2560 	const GLchar* vert_template = vert.c_str();
2561 
2562 	std::string fragment = specializeShader(1, &frag_template);
2563 	std::string geometry = specializeShader(1, &geom_template);
2564 	std::string vertex   = specializeShader(1, &vert_template);
2565 
2566 	/* Prepare program */
2567 	Utils::program program(m_context);
2568 
2569 	try
2570 	{
2571 		program.build(0 /* compute */, fragment.c_str(), geometry.c_str(), 0 /* tess ctrl */, 0 /* tess eval */,
2572 					  vertex.c_str(), 0 /* varying names */, 0 /* n_varyings */);
2573 	}
2574 	catch (Utils::shaderCompilationException& exc)
2575 	{
2576 		/* Something wrong with compilation, test case failed */
2577 		tcu::MessageBuilder message = m_context.getTestContext().getLog() << tcu::TestLog::Message;
2578 
2579 		message << "Shader compilation failed. Error message: " << exc.m_error_message;
2580 
2581 		Utils::program::printShaderSource(exc.m_shader_source.c_str(), message);
2582 
2583 		message << tcu::TestLog::EndMessage;
2584 
2585 		TCU_FAIL("Shader compilation failed");
2586 	}
2587 	catch (Utils::programLinkageException& exc)
2588 	{
2589 		/* Something wrong with linking, test case failed */
2590 		m_context.getTestContext().getLog() << tcu::TestLog::Message
2591 											<< "Program linking failed. Error message: " << exc.m_error_message
2592 											<< tcu::TestLog::EndMessage;
2593 		TCU_FAIL("Program linking failed");
2594 	}
2595 
2596 	program.use();
2597 
2598 	/* Prepare VAO */
2599 	Utils::vertexArray vao(m_context);
2600 	vao.generate();
2601 	vao.bind();
2602 
2603 	/* For each iteration from test type */
2604 	for (GLuint i = 0; i < n_iterations; ++i)
2605 	{
2606 		/* Prepare textures */
2607 		Utils::texture texture_0(m_context);
2608 		Utils::texture texture_1(m_context);
2609 
2610 		prepareTextures(texture_0, texture_1);
2611 
2612 		/* Prepare framebuffer */
2613 		Utils::framebuffer framebuffer(m_context);
2614 		framebuffer.generate();
2615 		setupFramebuffer(framebuffer, texture_0, texture_1);
2616 		framebuffer.bind();
2617 
2618 		/* Set up viewports */
2619 		setupViewports(test_type, i);
2620 
2621 		if (false == isClearTest())
2622 		{
2623 			/* For each draw call */
2624 			for (GLuint draw_call = 0; draw_call < n_draw_calls; ++draw_call)
2625 			{
2626 				prepareUniforms(program, draw_call);
2627 
2628 				bool	is_clear;
2629 				GLfloat depth_value;
2630 
2631 				getClearSettings(is_clear, draw_call, depth_value);
2632 
2633 				if (true == is_clear)
2634 				{
2635 					if (glu::isContextTypeGLCore(context_type))
2636 					{
2637 						gl.clearDepth((GLdouble)depth_value);
2638 					}
2639 					else
2640 					{
2641 						gl.clearDepthf(depth_value);
2642 					}
2643 					GLU_EXPECT_NO_ERROR(gl.getError(), "ClearDepth");
2644 
2645 					gl.clear(GL_DEPTH_BUFFER_BIT);
2646 					GLU_EXPECT_NO_ERROR(gl.getError(), "Clear");
2647 				}
2648 
2649 				gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
2650 				GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
2651 
2652 				bool result = checkResults(texture_0, texture_1, draw_call);
2653 
2654 				if (false == result)
2655 				{
2656 					test_result = false;
2657 					goto end;
2658 				}
2659 			}
2660 		}
2661 		else
2662 		{
2663 			gl.clearColor(0.0f, 0.0f, 0.0f, 0.0f);
2664 			GLU_EXPECT_NO_ERROR(gl.getError(), "ClearColor");
2665 
2666 			gl.clear(GL_COLOR_BUFFER_BIT);
2667 			GLU_EXPECT_NO_ERROR(gl.getError(), "Clear");
2668 
2669 			bool result = checkResults(texture_0, texture_1, 0);
2670 
2671 			if (false == result)
2672 			{
2673 				test_result = false;
2674 				goto end;
2675 			}
2676 		}
2677 	}
2678 
2679 end:
2680 	/* Set result */
2681 	if (true == test_result)
2682 	{
2683 		m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
2684 	}
2685 	else
2686 	{
2687 		m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2688 	}
2689 
2690 	/* Done */
2691 	return tcu::TestNode::STOP;
2692 }
2693 
2694 /** Check if R32I texture is filled with 4x4 regions of increasing values <0:15>
2695  *
2696  * @param texture_0 Verified texture
2697  * @param ignored
2698  * @param ignored
2699  *
2700  * @return True if texture_0 is filled with expected pattern
2701  **/
checkResults(Utils::texture & texture_0,Utils::texture &,GLuint)2702 bool DrawTestBase::checkResults(Utils::texture& texture_0, Utils::texture& /* texture_1 */, GLuint /*draw_call_index */)
2703 {
2704 	bool  check_result = true;
2705 	GLint index		   = 0;
2706 
2707 	std::vector<GLint> texture_data;
2708 	texture_data.resize(m_width * m_height);
2709 	texture_0.get(GL_RED_INTEGER, GL_INT, &texture_data[0]);
2710 
2711 	for (GLuint y = 0; y < 4; ++y)
2712 	{
2713 		for (GLuint x = 0; x < 4; ++x)
2714 		{
2715 			bool result = checkRegionR32I(x, y, index, &texture_data[0]);
2716 
2717 			if (false == result)
2718 			{
2719 				check_result = false;
2720 				goto end;
2721 			}
2722 
2723 			index += 1;
2724 		}
2725 	}
2726 
2727 end:
2728 	return check_result;
2729 }
2730 
2731 /** Get settings of clear operation
2732  *
2733  * @param clear_depth_before_draw Selects if clear depth should be executed before draw.
2734  * @param ignored
2735  * @param ignored
2736  **/
getClearSettings(bool & clear_depth_before_draw,GLuint,GLfloat &)2737 void DrawTestBase::getClearSettings(bool& clear_depth_before_draw, GLuint /* iteration_index */,
2738 									GLfloat& /* depth_value */)
2739 {
2740 	clear_depth_before_draw = false;
2741 }
2742 
2743 /** Get number of draw call to be executed during test
2744  *
2745  * @return 1
2746  **/
getDrawCallsNumber()2747 GLuint DrawTestBase::getDrawCallsNumber()
2748 {
2749 	return 1;
2750 }
2751 
2752 /** Get test type
2753  *
2754  * @return VIEWPORT
2755  **/
getTestType()2756 DrawTestBase::TEST_TYPE DrawTestBase::getTestType()
2757 {
2758 	return VIEWPORT;
2759 }
2760 
2761 /** Selects if test should do draw or clear operation
2762  *
2763  * @return false - draw operation
2764  **/
isClearTest()2765 bool DrawTestBase::isClearTest()
2766 {
2767 	return false;
2768 }
2769 
2770 /** Prepare textures used as framebuffer's attachments for current draw call
2771  *
2772  * @param texture_0 R32I texture
2773  * @param ignored
2774  **/
prepareTextures(Utils::texture & texture_0,Utils::texture &)2775 void DrawTestBase::prepareTextures(Utils::texture& texture_0, Utils::texture& /* texture_1 */)
2776 {
2777 	prepareTextureR32I(texture_0);
2778 }
2779 
2780 /** Prepare uniforms for given draw call
2781  *
2782  * @param ignored
2783  * @param ignored
2784  **/
prepareUniforms(Utils::program &,GLuint)2785 void DrawTestBase::prepareUniforms(Utils::program& /* program */, GLuint /* draw_call_index */)
2786 {
2787 	/* empty */
2788 }
2789 
2790 /** Attach textures to framebuffer
2791  *
2792  * @param framebuffer Framebuffer instance
2793  * @param texture_0   Texture attached as color 0
2794  * @param ignored
2795  **/
setupFramebuffer(Utils::framebuffer & framebuffer,Utils::texture & texture_0,Utils::texture &)2796 void DrawTestBase::setupFramebuffer(Utils::framebuffer& framebuffer, Utils::texture& texture_0,
2797 									Utils::texture& /* texture_1 */)
2798 {
2799 	framebuffer.attachTexture(GL_COLOR_ATTACHMENT0, texture_0.m_id, m_width, m_height);
2800 }
2801 
2802 /** Check if region specified with <x and <y> is filled with expected value.
2803  * Note: there is assumption that there are 4x4 regions
2804  *
2805  * @param x              X coordinate of region
2806  * @param y              Y coordinate of region
2807  * @param expected_value Expected value
2808  * @param data           Texture data (not region, but whole texture)
2809  *
2810  * @return True if region is filled with <expected_value>, false otherwise
2811  **/
checkRegionR32I(GLuint x,GLuint y,GLint expected_value,GLint * data)2812 bool DrawTestBase::checkRegionR32I(GLuint x, GLuint y, GLint expected_value, GLint* data)
2813 {
2814 	static GLuint width  = m_width / 4;
2815 	static GLuint height = m_height / 4;
2816 
2817 	return checkRegionR32I(x, y, width, height, expected_value, data);
2818 }
2819 
2820 /** Check if region specified with <x and <y> is filled with expected value.
2821  * Note: there is assumption that there are 4x4 regions
2822  *
2823  * @param x              X coordinate of region
2824  * @param y              Y coordinate of region
2825  * @param width          Width of region
2826  * @param height         Height of region
2827  * @param expected_value Expected value
2828  * @param data           Texture data (not region, but whole texture)
2829  *
2830  * @return True if region is filled with <expected_value>, false otherwise
2831  **/
checkRegionR32I(GLuint x,GLuint y,GLuint width,GLuint height,GLint expected_value,GLint * data)2832 bool DrawTestBase::checkRegionR32I(GLuint x, GLuint y, GLuint width, GLuint height, GLint expected_value, GLint* data)
2833 {
2834 	bool result = true;
2835 
2836 	const GLuint offset = (y * height * m_width) + (x * width);
2837 
2838 	for (GLuint line = 0; line < height; ++line)
2839 	{
2840 		const GLuint line_offset = offset + line * m_width;
2841 
2842 		for (GLuint texel = 0; texel < width; ++texel)
2843 		{
2844 			const GLuint texel_offset = line_offset + texel;
2845 
2846 			const GLint value = data[texel_offset];
2847 
2848 			if (expected_value != value)
2849 			{
2850 				m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid result. Region (" << x << "x"
2851 													<< y << "). Expected: " << expected_value << " got " << value
2852 													<< tcu::TestLog::EndMessage;
2853 
2854 				result = false;
2855 				goto end;
2856 			}
2857 		}
2858 	}
2859 
2860 end:
2861 	return result;
2862 }
2863 
2864 /** Return boiler-plate vertex shader
2865  *
2866  * @return Source code of vertex shader
2867  **/
getVertexShader()2868 std::string DrawTestBase::getVertexShader()
2869 {
2870 	static const GLchar* source = "${VERSION}\n"
2871 								  "\n"
2872 								  "void main()\n"
2873 								  "{\n"
2874 								  "    /* empty */;\n"
2875 								  "}\n"
2876 								  "\n";
2877 
2878 	std::string result = source;
2879 
2880 	return result;
2881 }
2882 
2883 /** Set up viewports
2884  *
2885  * @param type            Type of test
2886  * @param iteration_index Index of iteration for given test type
2887  **/
setupViewports(TEST_TYPE type,GLuint iteration_index)2888 void DrawTestBase::setupViewports(TEST_TYPE type, GLuint iteration_index)
2889 {
2890 	switch (type)
2891 	{
2892 	case VIEWPORT:
2893 	{
2894 		VIEWPORT_METHOD method;
2895 		switch (iteration_index)
2896 		{
2897 		case 0:
2898 		case 1:
2899 		case 2:
2900 			method = (VIEWPORT_METHOD)iteration_index;
2901 			break;
2902 		default:
2903 			TCU_FAIL("Invalid value");
2904 		}
2905 		setup4x4Viewport(method);
2906 	}
2907 	break;
2908 	case SCISSOR:
2909 	{
2910 		SCISSOR_METHOD method;
2911 		switch (iteration_index)
2912 		{
2913 		case 0:
2914 		case 1:
2915 		case 2:
2916 			method = (SCISSOR_METHOD)iteration_index;
2917 			break;
2918 		default:
2919 			TCU_FAIL("Invalid value");
2920 		}
2921 		setup4x4Scissor(method, false /* set_zeros */);
2922 	}
2923 	break;
2924 	case DEPTHRANGE:
2925 	{
2926 		DEPTH_RANGE_METHOD method;
2927 		switch (iteration_index)
2928 		{
2929 		case 0:
2930 		case 1:
2931 			method = (DEPTH_RANGE_METHOD)iteration_index;
2932 			break;
2933 		default:
2934 			TCU_FAIL("Invalid value");
2935 		}
2936 		setup16x2Depths(method);
2937 	}
2938 	break;
2939 	case PROVOKING:
2940 	{
2941 		PROVOKING_VERTEX provoking;
2942 		switch (iteration_index)
2943 		{
2944 		case 0:
2945 		case 1:
2946 			provoking = (PROVOKING_VERTEX)iteration_index;
2947 			break;
2948 		default:
2949 			TCU_FAIL("Invalid value");
2950 		}
2951 		setup2x2Viewport(provoking);
2952 	}
2953 	break;
2954 	default:
2955 		TCU_FAIL("Invalid enum");
2956 	}
2957 }
2958 
2959 /** Prepare R32I texture filled with value -1
2960  *
2961  * @param texture Texture instance
2962  **/
prepareTextureR32I(Utils::texture & texture)2963 void DrawTestBase::prepareTextureR32I(Utils::texture& texture)
2964 {
2965 	static const GLuint size = m_width * m_height;
2966 	GLint				data[size];
2967 
2968 	for (GLuint i = 0; i < size; ++i)
2969 	{
2970 		data[i] = -1;
2971 	}
2972 
2973 	texture.create(m_width, m_height, GL_R32I);
2974 	texture.update(m_width, m_height, 0 /* depth */, GL_RED_INTEGER, GL_INT, data);
2975 }
2976 
2977 /** Prepare R32I array texture filled with value -1, 4 layers
2978  *
2979  * @param texture Texture instance
2980  **/
prepareTextureR32Ix4(Utils::texture & texture)2981 void DrawTestBase::prepareTextureR32Ix4(Utils::texture& texture)
2982 {
2983 	static const GLuint size = m_width * m_height * m_r32ix4_depth;
2984 
2985 	std::vector<GLint> data;
2986 	data.resize(size);
2987 
2988 	for (GLuint i = 0; i < size; ++i)
2989 	{
2990 		data[i] = -1;
2991 	}
2992 
2993 	texture.create(m_width, m_height, m_r32ix4_depth, GL_R32I);
2994 	texture.update(m_width, m_height, m_r32ix4_depth, GL_RED_INTEGER, GL_INT, &data[0]);
2995 }
2996 
2997 /** Prepare R32I array texture filled with value -1
2998  *
2999  * @param texture Texture instance
3000  **/
prepareTextureArrayR32I(Utils::texture & texture)3001 void DrawTestBase::prepareTextureArrayR32I(Utils::texture& texture)
3002 {
3003 	static const GLuint size = m_width * m_height * m_depth;
3004 
3005 	std::vector<GLint> data;
3006 	data.resize(size);
3007 
3008 	for (GLuint i = 0; i < size; ++i)
3009 	{
3010 		data[i] = -1;
3011 	}
3012 
3013 	texture.create(m_width, m_height, m_depth, GL_R32I);
3014 	texture.update(m_width, m_height, m_depth, GL_RED_INTEGER, GL_INT, &data[0]);
3015 }
3016 
3017 /** Prepare R32F texture filled with value -1
3018  *
3019  * @param texture Texture instance
3020  **/
prepareTextureR32F(Utils::texture & texture)3021 void DrawTestBase::prepareTextureR32F(Utils::texture& texture)
3022 {
3023 	static const GLuint size = m_r32f_width * m_r32f_height;
3024 	GLfloat				data[size];
3025 
3026 	for (GLuint i = 0; i < size; ++i)
3027 	{
3028 		data[i] = -1.0f;
3029 	}
3030 
3031 	texture.create(m_r32f_width, m_r32f_height, GL_R32F);
3032 	texture.update(m_r32f_width, m_r32f_height, 0 /* depth */, GL_RED, GL_FLOAT, data);
3033 }
3034 
3035 /** Prepare D32F texture filled with value -1
3036  *
3037  * @param texture Texture instance
3038  **/
prepareTextureD32F(Utils::texture & texture)3039 void DrawTestBase::prepareTextureD32F(Utils::texture& texture)
3040 {
3041 	static const GLuint size = m_width * m_height;
3042 	GLfloat				data[size];
3043 
3044 	for (GLuint i = 0; i < size; ++i)
3045 	{
3046 		data[i] = -1.0f;
3047 	}
3048 
3049 	texture.create(m_width, m_height, GL_DEPTH_COMPONENT32F);
3050 	texture.update(m_width, m_height, 0 /* depth */, GL_DEPTH_COMPONENT, GL_FLOAT, data);
3051 }
3052 
3053 /** Set up 16 viewports and depth ranges horizontally
3054  *
3055  * @param method Method used to set depth ranges
3056  **/
setup16x2Depths(DEPTH_RANGE_METHOD method)3057 void DrawTestBase::setup16x2Depths(DEPTH_RANGE_METHOD method)
3058 {
3059 	const glu::ContextType& context_type = m_context.getRenderContext().getType();
3060 
3061 	if (glu::isContextTypeGLCore(context_type))
3062 	{
3063 		setup16x2DepthsHelper<GLdouble>(method);
3064 	}
3065 	else
3066 	{
3067 		DE_ASSERT(glu::isContextTypeES(context_type));
3068 		setup16x2DepthsHelper<GLfloat>(method);
3069 	}
3070 }
3071 
3072 template <typename T>
setup16x2DepthsHelper(DEPTH_RANGE_METHOD method,T *)3073 void DrawTestBase::setup16x2DepthsHelper(DEPTH_RANGE_METHOD method, T*)
3074 {
3075 	static const T step = 1.0 / 16.0;
3076 
3077 	const glw::Functions&   gl = m_context.getRenderContext().getFunctions();
3078 	Utils::DepthFuncWrapper depthFunc(m_context);
3079 
3080 	T		depth_data[16 * 2];
3081 	GLfloat viewport_data[16 * 4];
3082 
3083 	for (GLuint i = 0; i < 16; ++i)
3084 	{
3085 		const T near = step * (T)i;
3086 
3087 		depth_data[i * 2 + 0] = near;
3088 		depth_data[i * 2 + 1] = T(1.0) - near;
3089 
3090 		viewport_data[i * 4 + 0] = (GLfloat)i;
3091 		viewport_data[i * 4 + 1] = 0.0f;
3092 		viewport_data[i * 4 + 2] = 1.0f;
3093 		viewport_data[i * 4 + 3] = 2.0f;
3094 	}
3095 
3096 	gl.viewportArrayv(0 /* first */, 16 /* count */, viewport_data);
3097 	GLU_EXPECT_NO_ERROR(gl.getError(), "ViewportArrayv");
3098 
3099 	switch (method)
3100 	{
3101 	case DEPTHRANGEINDEXED:
3102 		for (GLuint i = 0; i < 16; ++i)
3103 		{
3104 			depthFunc.depthRangeIndexed(i, depth_data[i * 2 + 0], depth_data[i * 2 + 1]);
3105 			GLU_EXPECT_NO_ERROR(gl.getError(), "DepthRangeIndexed");
3106 		}
3107 		break;
3108 
3109 	case DEPTHRANGEARRAYV:
3110 		depthFunc.depthRangeArray(0 /* first */, 16 /* count */, depth_data);
3111 		GLU_EXPECT_NO_ERROR(gl.getError(), "DepthRangeArray");
3112 		break;
3113 
3114 	default:
3115 		TCU_FAIL("Invalid enum");
3116 	}
3117 }
3118 
3119 /** Set up 4x4 scissor boxes with enabled test
3120  *
3121  * @param method    Method used to set scissor boxes
3122  * @param set_zeros Select if width and height should be 0 or image_dim / 4
3123  **/
setup4x4Scissor(SCISSOR_METHOD method,bool set_zeros)3124 void DrawTestBase::setup4x4Scissor(SCISSOR_METHOD method, bool set_zeros)
3125 {
3126 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3127 
3128 	for (GLuint i = 0; i < 16; ++i)
3129 	{
3130 		gl.enablei(GL_SCISSOR_TEST, i);
3131 		GLU_EXPECT_NO_ERROR(gl.getError(), "Enablei");
3132 	}
3133 
3134 	GLint index = 0;
3135 	GLint data[16 * 4 /* 4x4 * (x + y + w + h) */];
3136 
3137 	GLint width  = m_width / 4;
3138 	GLint height = m_height / 4;
3139 
3140 	for (GLuint y = 0; y < 4; ++y)
3141 	{
3142 		for (GLuint x = 0; x < 4; ++x)
3143 		{
3144 			data[index * 4 + 0] = x * width;
3145 			data[index * 4 + 1] = y * height;
3146 			if (false == set_zeros)
3147 			{
3148 				data[index * 4 + 2] = width;
3149 				data[index * 4 + 3] = height;
3150 			}
3151 			else
3152 			{
3153 				data[index * 4 + 2] = 0;
3154 				data[index * 4 + 3] = 0;
3155 			}
3156 
3157 			index += 1;
3158 		}
3159 	}
3160 
3161 	switch (method)
3162 	{
3163 	case SCISSORARRAYV:
3164 		gl.scissorArrayv(0 /* first */, 16 /*count */, data);
3165 		GLU_EXPECT_NO_ERROR(gl.getError(), "ScissorArrayv");
3166 		break;
3167 	case SCISSORINDEXEDF:
3168 		for (GLuint i = 0; i < 16; ++i)
3169 		{
3170 			const GLint x = data[i * 4 + 0];
3171 			const GLint y = data[i * 4 + 1];
3172 			const GLint w = data[i * 4 + 2];
3173 			const GLint h = data[i * 4 + 3];
3174 
3175 			gl.scissorIndexed(i, x, y, w, h);
3176 			GLU_EXPECT_NO_ERROR(gl.getError(), "ScissorIndexed");
3177 		}
3178 		break;
3179 	case SCISSORINDEXEDF_V:
3180 		for (GLuint i = 0; i < 16; ++i)
3181 		{
3182 			gl.scissorIndexedv(i, &data[i * 4]);
3183 			GLU_EXPECT_NO_ERROR(gl.getError(), "ScissorIndexedv");
3184 		}
3185 		break;
3186 	default:
3187 		TCU_FAIL("Invalid enum");
3188 	}
3189 }
3190 
3191 /** Set up 4x4 viewports
3192  *
3193  * @param method Method used to set viewports
3194  **/
setup4x4Viewport(VIEWPORT_METHOD method)3195 void DrawTestBase::setup4x4Viewport(VIEWPORT_METHOD method)
3196 {
3197 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3198 
3199 	GLint   index = 0;
3200 	GLfloat data[16 * 4 /* 4x4 * (x + y + w + h) */];
3201 
3202 	GLfloat width  = (GLfloat)(m_width / 4);
3203 	GLfloat height = (GLfloat)(m_height / 4);
3204 
3205 	for (GLuint y = 0; y < 4; ++y)
3206 	{
3207 		for (GLuint x = 0; x < 4; ++x)
3208 		{
3209 			data[index * 4 + 0] = (GLfloat)((GLfloat)x * width);
3210 			data[index * 4 + 1] = (GLfloat)((GLfloat)y * height);
3211 			data[index * 4 + 2] = width;
3212 			data[index * 4 + 3] = height;
3213 
3214 			index += 1;
3215 		}
3216 	}
3217 
3218 	switch (method)
3219 	{
3220 	case VIEWPORTARRAYV:
3221 		gl.viewportArrayv(0 /* first */, 16 /*count */, data);
3222 		GLU_EXPECT_NO_ERROR(gl.getError(), "ViewportArrayv");
3223 		break;
3224 	case VIEWPORTINDEXEDF:
3225 		for (GLuint i = 0; i < 16; ++i)
3226 		{
3227 			const GLfloat x = data[i * 4 + 0];
3228 			const GLfloat y = data[i * 4 + 1];
3229 			const GLfloat w = data[i * 4 + 2];
3230 			const GLfloat h = data[i * 4 + 3];
3231 
3232 			gl.viewportIndexedf(i, x, y, w, h);
3233 			GLU_EXPECT_NO_ERROR(gl.getError(), "ViewportIndexedf");
3234 		}
3235 		break;
3236 	case VIEWPORTINDEXEDF_V:
3237 		for (GLuint i = 0; i < 16; ++i)
3238 		{
3239 			gl.viewportIndexedfv(i, &data[i * 4]);
3240 			GLU_EXPECT_NO_ERROR(gl.getError(), "ViewportIndexedfv");
3241 		}
3242 		break;
3243 	default:
3244 		TCU_FAIL("Invalid enum");
3245 	}
3246 }
3247 
3248 /** Set up 4x4 viewports
3249  *
3250  * @param method Method used to set viewports
3251  **/
setup2x2Viewport(PROVOKING_VERTEX provoking)3252 void DrawTestBase::setup2x2Viewport(PROVOKING_VERTEX provoking)
3253 {
3254 	const glw::Functions&   gl			 = m_context.getRenderContext().getFunctions();
3255 	const glu::ContextType& context_type = m_context.getRenderContext().getType();
3256 
3257 	GLint   index = 0;
3258 	GLfloat data[4 * 4 /* 4x4 * (x + y + w + h) */];
3259 
3260 	GLfloat width  = (GLfloat)(m_width / 2);
3261 	GLfloat height = (GLfloat)(m_height / 2);
3262 
3263 	for (GLuint y = 0; y < 2; ++y)
3264 	{
3265 		for (GLuint x = 0; x < 2; ++x)
3266 		{
3267 			data[index * 4 + 0] = (GLfloat)((GLfloat)x * width);
3268 			data[index * 4 + 1] = (GLfloat)((GLfloat)y * height);
3269 			data[index * 4 + 2] = width;
3270 			data[index * 4 + 3] = height;
3271 
3272 			index += 1;
3273 		}
3274 	}
3275 
3276 	gl.viewportArrayv(0 /* first */, 4 /*count */, data);
3277 	GLU_EXPECT_NO_ERROR(gl.getError(), "ViewportArrayv");
3278 
3279 	if (glu::isContextTypeGLCore(context_type))
3280 	{
3281 		GLenum mode = 0;
3282 		switch (provoking)
3283 		{
3284 		case FIRST:
3285 			mode = GL_FIRST_VERTEX_CONVENTION;
3286 			break;
3287 		case LAST:
3288 			mode = GL_LAST_VERTEX_CONVENTION;
3289 			break;
3290 		default:
3291 			TCU_FAIL("Invalid enum");
3292 		}
3293 
3294 		gl.provokingVertex(mode);
3295 		GLU_EXPECT_NO_ERROR(gl.getError(), "ProvokingVertex");
3296 	}
3297 	else
3298 	{
3299 		/* can't control the provoking vertex in ES yet - it stays as LAST */
3300 		DE_ASSERT(glu::isContextTypeES(context_type));
3301 		DE_UNREF(provoking);
3302 	}
3303 }
3304 
3305 /** Constructor
3306  *
3307  * @param context          Test context
3308  **/
DrawToSingleLayerWithMultipleViewports(deqp::Context & context,const glcts::ExtParameters & extParams)3309 DrawToSingleLayerWithMultipleViewports::DrawToSingleLayerWithMultipleViewports(deqp::Context&			   context,
3310 																			   const glcts::ExtParameters& extParams)
3311 	: DrawTestBase(context, extParams, "draw_to_single_layer_with_multiple_viewports",
3312 				   "Test verifies that multiple viewports can be used to draw to single layer")
3313 {
3314 	/* Nothing to be done here */
3315 }
3316 
3317 /** Get string with fragment shader source code
3318  *
3319  * @return Fragment shader source
3320  **/
getFragmentShader()3321 std::string DrawToSingleLayerWithMultipleViewports::getFragmentShader()
3322 {
3323 	static const GLchar* source = "${VERSION}\n"
3324 								  "\n"
3325 								  "flat in  int gs_fs_color;\n"
3326 								  "     out int fs_out_color;\n"
3327 								  "\n"
3328 								  "void main()\n"
3329 								  "{\n"
3330 								  "    fs_out_color = gs_fs_color;\n"
3331 								  "}\n"
3332 								  "\n";
3333 
3334 	std::string result = source;
3335 
3336 	return result;
3337 }
3338 
3339 /** Get string with geometry shader source code
3340  *
3341  * @return Geometry shader source
3342  **/
getGeometryShader()3343 std::string DrawToSingleLayerWithMultipleViewports::getGeometryShader()
3344 {
3345 	static const GLchar* source = "${VERSION}\n"
3346 								  "\n"
3347 								  "${GEOMETRY_SHADER_ENABLE}\n"
3348 								  "${VIEWPORT_ARRAY_ENABLE}\n"
3349 								  "\n"
3350 								  "layout(points, invocations = 16)         in;\n"
3351 								  "layout(triangle_strip, max_vertices = 4) out;\n"
3352 								  "\n"
3353 								  "flat out int gs_fs_color;\n"
3354 								  "\n"
3355 								  "void main()\n"
3356 								  "{\n"
3357 								  "    gs_fs_color      = gl_InvocationID;\n"
3358 								  "    gl_ViewportIndex = gl_InvocationID;\n"
3359 								  "    gl_Position  = vec4(-1, -1, 0, 1);\n"
3360 								  "    EmitVertex();\n"
3361 								  "    gs_fs_color      = gl_InvocationID;\n"
3362 								  "    gl_ViewportIndex = gl_InvocationID;\n"
3363 								  "    gl_Position  = vec4(-1, 1, 0, 1);\n"
3364 								  "    EmitVertex();\n"
3365 								  "    gs_fs_color      = gl_InvocationID;\n"
3366 								  "    gl_ViewportIndex = gl_InvocationID;\n"
3367 								  "    gl_Position  = vec4(1, -1, 0, 1);\n"
3368 								  "    EmitVertex();\n"
3369 								  "    gs_fs_color      = gl_InvocationID;\n"
3370 								  "    gl_ViewportIndex = gl_InvocationID;\n"
3371 								  "    gl_Position  = vec4(1, 1, 0, 1);\n"
3372 								  "    EmitVertex();\n"
3373 								  "}\n"
3374 								  "\n";
3375 
3376 	std::string result = source;
3377 
3378 	return result;
3379 }
3380 
3381 /** Constructor
3382  *
3383  * @param context          Test context
3384  **/
DynamicViewportIndex(deqp::Context & context,const glcts::ExtParameters & extParams)3385 DynamicViewportIndex::DynamicViewportIndex(deqp::Context& context, const glcts::ExtParameters& extParams)
3386 	: DrawTestBase(context, extParams, "dynamic_viewport_index",
3387 				   "Test verifies that gl_ViewportIndex can be assigned with dynamic value")
3388 {
3389 	/* Nothing to be done here */
3390 }
3391 
3392 /** Get string with fragment shader source code
3393  *
3394  * @return Fragment shader source
3395  **/
getFragmentShader()3396 std::string DynamicViewportIndex::getFragmentShader()
3397 {
3398 	static const GLchar* source = "${VERSION}\n"
3399 								  "\n"
3400 								  "flat in  int gs_fs_color;\n"
3401 								  "     out int fs_out_color;\n"
3402 								  "\n"
3403 								  "void main()\n"
3404 								  "{\n"
3405 								  "    fs_out_color = gs_fs_color;\n"
3406 								  "}\n"
3407 								  "\n";
3408 
3409 	std::string result = source;
3410 
3411 	return result;
3412 }
3413 
3414 /** Get string with geometry shader source code
3415  *
3416  * @return Geometry shader source
3417  **/
getGeometryShader()3418 std::string DynamicViewportIndex::getGeometryShader()
3419 {
3420 	static const GLchar* source = "${VERSION}\n"
3421 								  "\n"
3422 								  "${GEOMETRY_SHADER_ENABLE}\n"
3423 								  "${VIEWPORT_ARRAY_ENABLE}\n"
3424 								  "\n"
3425 								  "layout(points, invocations = 1)          in;\n"
3426 								  "layout(triangle_strip, max_vertices = 4) out;\n"
3427 								  "\n"
3428 								  "uniform int uni_index;\n"
3429 								  "\n"
3430 								  "flat out int gs_fs_color;\n"
3431 								  "\n"
3432 								  "void main()\n"
3433 								  "{\n"
3434 								  "    gs_fs_color      = uni_index;\n"
3435 								  "    gl_ViewportIndex = uni_index;\n"
3436 								  "    gl_Position  = vec4(-1, -1, 0, 1);\n"
3437 								  "    EmitVertex();\n"
3438 								  "    gs_fs_color      = uni_index;\n"
3439 								  "    gl_ViewportIndex = uni_index;\n"
3440 								  "    gl_Position  = vec4(-1, 1, 0, 1);\n"
3441 								  "    EmitVertex();\n"
3442 								  "    gs_fs_color      = uni_index;\n"
3443 								  "    gl_ViewportIndex = uni_index;\n"
3444 								  "    gl_Position  = vec4(1, -1, 0, 1);\n"
3445 								  "    EmitVertex();\n"
3446 								  "    gs_fs_color      = uni_index;\n"
3447 								  "    gl_ViewportIndex = uni_index;\n"
3448 								  "    gl_Position  = vec4(1, 1, 0, 1);\n"
3449 								  "    EmitVertex();\n"
3450 								  "}\n"
3451 								  "\n";
3452 
3453 	std::string result = source;
3454 
3455 	return result;
3456 }
3457 
3458 /** Check if R32I texture is filled with 4x4 regions of increasing values <0:15>
3459  *
3460  * @param texture_0       Verified texture
3461  * @param ignored
3462  * @param draw_call_index Draw call that was executed
3463  *
3464  * @return True if texture_0 is filled with expected pattern
3465  **/
checkResults(Utils::texture & texture_0,Utils::texture &,GLuint draw_call_index)3466 bool DynamicViewportIndex::checkResults(Utils::texture& texture_0, Utils::texture& /* texture_1 */,
3467 										GLuint			draw_call_index)
3468 {
3469 	bool   check_result = true;
3470 	GLuint index		= 0;
3471 
3472 	std::vector<GLint> texture_data;
3473 	texture_data.resize(m_width * m_height);
3474 	texture_0.get(GL_RED_INTEGER, GL_INT, &texture_data[0]);
3475 
3476 	for (GLuint y = 0; y < 4; ++y)
3477 	{
3478 		for (GLuint x = 0; x < 4; ++x)
3479 		{
3480 			GLint expected_value = -1;
3481 			if (index <= draw_call_index)
3482 			{
3483 				expected_value = index;
3484 			}
3485 
3486 			bool result = checkRegionR32I(x, y, expected_value, &texture_data[0]);
3487 
3488 			if (false == result)
3489 			{
3490 				check_result = false;
3491 				goto end;
3492 			}
3493 
3494 			index += 1;
3495 		}
3496 	}
3497 
3498 end:
3499 	return check_result;
3500 }
3501 
3502 /** Get number of draw call to be executed during test
3503  *
3504  * @return 16
3505  **/
getDrawCallsNumber()3506 GLuint DynamicViewportIndex::getDrawCallsNumber()
3507 {
3508 	return 16;
3509 }
3510 
3511 /** Prepare uniforms for given draw call
3512  *
3513  * @param program         Program object
3514  * @param draw_call_index Index of draw call to be executed
3515  **/
prepareUniforms(Utils::program & program,GLuint draw_call_index)3516 void DynamicViewportIndex::prepareUniforms(Utils::program& program, GLuint draw_call_index)
3517 {
3518 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3519 
3520 	GLint location = program.getUniformLocation("uni_index");
3521 
3522 	gl.uniform1i(location, (GLint)draw_call_index);
3523 	GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i");
3524 }
3525 
3526 /** Constructor
3527  *
3528  * @param context          Test context
3529  **/
DrawMulitpleViewportsWithSingleInvocation(deqp::Context & context,const glcts::ExtParameters & extParams)3530 DrawMulitpleViewportsWithSingleInvocation::DrawMulitpleViewportsWithSingleInvocation(
3531 	deqp::Context& context, const glcts::ExtParameters& extParams)
3532 	: DrawTestBase(context, extParams, "draw_mulitple_viewports_with_single_invocation",
3533 				   "Test verifies that single invocation can output to multiple viewports")
3534 {
3535 	/* Nothing to be done here */
3536 }
3537 
3538 /** Get string with fragment shader source code
3539  *
3540  * @return Fragment shader source
3541  **/
getFragmentShader()3542 std::string DrawMulitpleViewportsWithSingleInvocation::getFragmentShader()
3543 {
3544 	static const GLchar* source = "${VERSION}\n"
3545 								  "\n"
3546 								  "flat in  int gs_fs_color;\n"
3547 								  "     out int fs_out_color;\n"
3548 								  "\n"
3549 								  "void main()\n"
3550 								  "{\n"
3551 								  "    fs_out_color = gs_fs_color;\n"
3552 								  "}\n"
3553 								  "\n";
3554 
3555 	std::string result = source;
3556 
3557 	return result;
3558 }
3559 
3560 /** Get string with geometry shader source code
3561  *
3562  * @return Geometry shader source
3563  **/
getGeometryShader()3564 std::string DrawMulitpleViewportsWithSingleInvocation::getGeometryShader()
3565 {
3566 	static const GLchar* source = "${VERSION}\n"
3567 								  "\n"
3568 								  "${GEOMETRY_SHADER_ENABLE}\n"
3569 								  "${VIEWPORT_ARRAY_ENABLE}\n"
3570 								  "\n"
3571 								  "layout(points, invocations = 1)           in;\n"
3572 								  "layout(triangle_strip, max_vertices = 64) out;\n"
3573 								  "\n"
3574 								  "flat out int gs_fs_color;\n"
3575 								  "\n"
3576 								  "void routine(int index)\n"
3577 								  "{\n"
3578 								  "    gs_fs_color      = index;\n"
3579 								  "    gl_ViewportIndex = index;\n"
3580 								  "    gl_Position  = vec4(-1, -1, 0, 1);\n"
3581 								  "    EmitVertex();\n"
3582 								  "    gs_fs_color      = index;\n"
3583 								  "    gl_ViewportIndex = index;\n"
3584 								  "    gl_Position  = vec4(-1, 1, 0, 1);\n"
3585 								  "    EmitVertex();\n"
3586 								  "    gs_fs_color      = index;\n"
3587 								  "    gl_ViewportIndex = index;\n"
3588 								  "    gl_Position  = vec4(1, -1, 0, 1);\n"
3589 								  "    EmitVertex();\n"
3590 								  "    gs_fs_color      = index;\n"
3591 								  "    gl_ViewportIndex = index;\n"
3592 								  "    gl_Position  = vec4(1, 1, 0, 1);\n"
3593 								  "    EmitVertex();\n"
3594 								  "    EndPrimitive();\n"
3595 								  "}\n"
3596 								  "\n"
3597 								  "void main()\n"
3598 								  "{\n"
3599 								  "    for(int i = 0; i < 16; ++i)\n"
3600 								  "    {\n"
3601 								  "        routine(i);\n"
3602 								  "    }\n"
3603 								  "}\n"
3604 								  "\n";
3605 
3606 	std::string result = source;
3607 
3608 	return result;
3609 }
3610 
3611 /** Constructor
3612  *
3613  * @param context          Test context
3614  **/
ViewportIndexSubroutine(deqp::Context & context,const glcts::ExtParameters & extParams)3615 ViewportIndexSubroutine::ViewportIndexSubroutine(deqp::Context& context, const glcts::ExtParameters& extParams)
3616 	: DrawTestBase(context, extParams, "viewport_index_subroutine",
3617 				   "Test verifies subroutines can be used to output data to specific viewport")
3618 {
3619 	/* Nothing to be done here */
3620 }
3621 
3622 /** Execute test
3623  *
3624  * @return tcu::TestNode::CONTINUE after executing test case, tcu::TestNode::STOP otherwise
3625  **/
iterate()3626 tcu::TestNode::IterateResult ViewportIndexSubroutine::iterate()
3627 {
3628 	/* this exists solely to check for subroutine support, which is not supported in ES.
3629 	   The real work is done in DrawTestBase::iterate() */
3630 	const glu::ContextType& context_type = m_context.getRenderContext().getType();
3631 	if (!glu::isContextTypeGLCore(context_type))
3632 	{
3633 		throw tcu::NotSupportedError("Subroutines not supported", "", __FILE__, __LINE__);
3634 	}
3635 
3636 	return DrawTestBase::iterate();
3637 }
3638 
3639 /** Get string with fragment shader source code
3640  *
3641  * @return Fragment shader source
3642  **/
getFragmentShader()3643 std::string ViewportIndexSubroutine::getFragmentShader()
3644 {
3645 	static const GLchar* source = "${VERSION}\n"
3646 								  "\n"
3647 								  "flat in  int gs_fs_color;\n"
3648 								  "     out int fs_out_color;\n"
3649 								  "\n"
3650 								  "void main()\n"
3651 								  "{\n"
3652 								  "    fs_out_color = gs_fs_color;\n"
3653 								  "}\n"
3654 								  "\n";
3655 
3656 	std::string result = source;
3657 
3658 	return result;
3659 }
3660 
3661 /** Get string with geometry shader source code
3662  *
3663  * @return Geometry shader source
3664  **/
getGeometryShader()3665 std::string ViewportIndexSubroutine::getGeometryShader()
3666 {
3667 	static const GLchar* source = "${VERSION}\n"
3668 								  "\n"
3669 								  "${GEOMETRY_SHADER_ENABLE}\n"
3670 								  "${VIEWPORT_ARRAY_ENABLE}\n"
3671 								  "\n"
3672 								  "layout(points, invocations = 1)          in;\n"
3673 								  "layout(triangle_strip, max_vertices = 4) out;\n"
3674 								  "\n"
3675 								  "flat out int gs_fs_color;\n"
3676 								  "\n"
3677 								  "subroutine void indexSetter(void);\n"
3678 								  "\n"
3679 								  "subroutine(indexSetter) void four()\n"
3680 								  "{\n"
3681 								  "    gs_fs_color      = 4;\n"
3682 								  "    gl_ViewportIndex = 4;\n"
3683 								  "}\n"
3684 								  "\n"
3685 								  "subroutine(indexSetter) void five()\n"
3686 								  "{\n"
3687 								  "    gs_fs_color      = 5;\n"
3688 								  "    gl_ViewportIndex = 5;\n"
3689 								  "}\n"
3690 								  "\n"
3691 								  "subroutine uniform indexSetter routine;\n"
3692 								  "\n"
3693 								  "void main()\n"
3694 								  "{\n"
3695 								  "    routine();\n"
3696 								  "    gl_Position  = vec4(-1, -1, 0, 1);\n"
3697 								  "    EmitVertex();\n"
3698 								  "    routine();\n"
3699 								  "    gl_Position  = vec4(-1, 1, 0, 1);\n"
3700 								  "    EmitVertex();\n"
3701 								  "    routine();\n"
3702 								  "    gl_Position  = vec4(1, -1, 0, 1);\n"
3703 								  "    EmitVertex();\n"
3704 								  "    routine();\n"
3705 								  "    gl_Position  = vec4(1, 1, 0, 1);\n"
3706 								  "    EmitVertex();\n"
3707 								  "}\n"
3708 								  "\n";
3709 
3710 	std::string result = source;
3711 
3712 	return result;
3713 }
3714 
3715 /** Check if R32I texture is filled with two halves, left is 4, right is either -1 or 5
3716  *
3717  * @param texture_0       Verified texture
3718  * @param ignored
3719  * @param draw_call_index Draw call that was executed
3720  *
3721  * @return True if texture_0 is filled with expected pattern
3722  **/
checkResults(Utils::texture & texture_0,Utils::texture &,GLuint draw_call_index)3723 bool ViewportIndexSubroutine::checkResults(Utils::texture& texture_0, Utils::texture& /* texture_1 */,
3724 										   GLuint		   draw_call_index)
3725 {
3726 	bool check_result = true;
3727 
3728 	std::vector<GLint> texture_data;
3729 	texture_data.resize(m_width * m_height);
3730 	texture_0.get(GL_RED_INTEGER, GL_INT, &texture_data[0]);
3731 
3732 	/* Left is 4 and right is -1, or left is 4 and right is 5 */
3733 	GLint expected_left  = 4;
3734 	GLint expected_right = (1 == draw_call_index) ? 5 : -1;
3735 
3736 	for (GLuint y = 0; y < 4; ++y)
3737 	{
3738 		for (GLuint x = 0; x < 2; ++x)
3739 		{
3740 			bool result = checkRegionR32I(x, y, expected_left, &texture_data[0]);
3741 
3742 			if (false == result)
3743 			{
3744 				check_result = false;
3745 				goto end;
3746 			}
3747 		}
3748 	}
3749 
3750 	for (GLuint y = 0; y < 4; ++y)
3751 	{
3752 		for (GLuint x = 2; x < 4; ++x)
3753 		{
3754 			bool result = checkRegionR32I(x, y, expected_right, &texture_data[0]);
3755 
3756 			if (false == result)
3757 			{
3758 				check_result = false;
3759 				goto end;
3760 			}
3761 		}
3762 	}
3763 
3764 end:
3765 	return check_result;
3766 }
3767 
3768 /** Get number of draw call to be executed during test
3769  *
3770  * @return 2
3771  **/
getDrawCallsNumber()3772 GLuint ViewportIndexSubroutine::getDrawCallsNumber()
3773 {
3774 	return 2;
3775 }
3776 
3777 /** Prepare uniforms for given draw call
3778  *
3779  * @param program         Program object
3780  * @param draw_call_index Index of draw call to be executed
3781  **/
prepareUniforms(Utils::program & program,GLuint draw_call_index)3782 void ViewportIndexSubroutine::prepareUniforms(Utils::program& program, GLuint draw_call_index)
3783 {
3784 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3785 
3786 	const GLchar* subroutine_name = (0 == draw_call_index) ? "four" : "five";
3787 
3788 	GLint  location = program.getSubroutineUniformLocation("routine", GL_GEOMETRY_SHADER);
3789 	GLuint index	= program.getSubroutineIndex(subroutine_name, GL_GEOMETRY_SHADER);
3790 
3791 	if (0 != location)
3792 	{
3793 		TCU_FAIL("Something wrong, subroutine uniform location is not 0. Mistake in geometry shader?");
3794 	}
3795 
3796 	gl.uniformSubroutinesuiv(GL_GEOMETRY_SHADER, 1, &index);
3797 	GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv");
3798 }
3799 
3800 /** Set 4th viewport on left half and 5 on right half of framebuffer. Rest span over whole image.
3801  *
3802  * @param ignored
3803  * @param iteration_index Index of iteration, used to select "viewport" method
3804  **/
setupViewports(TEST_TYPE,glw::GLuint iteration_index)3805 void ViewportIndexSubroutine::setupViewports(TEST_TYPE /* type */, glw::GLuint iteration_index)
3806 {
3807 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3808 
3809 	GLfloat data[2 * 4] = { 0.0f, 0.0f, 64.0f, 128.0f, 64.0f, 0.0f, 64.0f, 128.0f };
3810 
3811 	gl.viewport(0, 0, m_width, m_height);
3812 	GLU_EXPECT_NO_ERROR(gl.getError(), "Viewport");
3813 
3814 	switch (iteration_index)
3815 	{
3816 	case 0:
3817 
3818 		gl.viewportArrayv(4, 2, data);
3819 		GLU_EXPECT_NO_ERROR(gl.getError(), "ViewportArrayv");
3820 
3821 		break;
3822 
3823 	case 1:
3824 
3825 		gl.viewportIndexedf(4, data[0], data[1], data[2], data[3]);
3826 		GLU_EXPECT_NO_ERROR(gl.getError(), "ViewportIndexedf");
3827 
3828 		gl.viewportIndexedf(5, data[4], data[5], data[6], data[7]);
3829 		GLU_EXPECT_NO_ERROR(gl.getError(), "ViewportIndexedf");
3830 
3831 		break;
3832 
3833 	case 2:
3834 
3835 		gl.viewportIndexedfv(4, &data[0]);
3836 		GLU_EXPECT_NO_ERROR(gl.getError(), "ViewportIndexedfv");
3837 
3838 		gl.viewportIndexedfv(5, &data[4]);
3839 		GLU_EXPECT_NO_ERROR(gl.getError(), "ViewportIndexedfv");
3840 
3841 		break;
3842 
3843 	default:
3844 		TCU_FAIL("Invalid value");
3845 	}
3846 }
3847 
3848 /** Constructor
3849  *
3850  * @param context Test context
3851  **/
DrawMultipleLayers(deqp::Context & context,const glcts::ExtParameters & extParams)3852 DrawMultipleLayers::DrawMultipleLayers(deqp::Context& context, const glcts::ExtParameters& extParams)
3853 	: DrawTestBase(context, extParams, "draw_multiple_layers",
3854 				   "Test verifies that single viewport affects multiple layers in the same way")
3855 {
3856 	/* Nothing to be done here */
3857 }
3858 
3859 /** Constructor
3860  *
3861  * @param context          Test context
3862  * @param test_name        Test name
3863  * @param test_description Test description
3864  **/
DrawMultipleLayers(deqp::Context & context,const glcts::ExtParameters & extParams,const GLchar * test_name,const GLchar * test_description)3865 DrawMultipleLayers::DrawMultipleLayers(deqp::Context& context, const glcts::ExtParameters& extParams,
3866 									   const GLchar* test_name, const GLchar* test_description)
3867 	: DrawTestBase(context, extParams, test_name, test_description)
3868 {
3869 	/* Nothing to be done here */
3870 }
3871 
3872 /** Get string with fragment shader source code
3873  *
3874  * @return Fragment shader source
3875  **/
getFragmentShader()3876 std::string DrawMultipleLayers::getFragmentShader()
3877 {
3878 	static const GLchar* source = "${VERSION}\n"
3879 								  "\n"
3880 								  "flat in  int gs_fs_color;\n"
3881 								  "     out int fs_out_color;\n"
3882 								  "\n"
3883 								  "void main()\n"
3884 								  "{\n"
3885 								  "    fs_out_color = gs_fs_color;\n"
3886 								  "}\n"
3887 								  "\n";
3888 
3889 	std::string result = source;
3890 
3891 	return result;
3892 }
3893 
3894 /** Get string with geometry shader source code
3895  *
3896  * @return Geometry shader source
3897  **/
getGeometryShader()3898 std::string DrawMultipleLayers::getGeometryShader()
3899 {
3900 	static const GLchar* source = "${VERSION}\n"
3901 								  "\n"
3902 								  "${GEOMETRY_SHADER_ENABLE}\n"
3903 								  "${VIEWPORT_ARRAY_ENABLE}\n"
3904 								  "\n"
3905 								  "layout(points, invocations = 16)         in;\n"
3906 								  "layout(triangle_strip, max_vertices = 4) out;\n"
3907 								  "\n"
3908 								  "flat out int gs_fs_color;\n"
3909 								  "\n"
3910 								  "void main()\n"
3911 								  "{\n"
3912 								  "    gs_fs_color      = gl_InvocationID;\n"
3913 								  "    gl_ViewportIndex = gl_InvocationID;\n"
3914 								  "    gl_Layer         = gl_InvocationID;\n"
3915 								  "    gl_Position  = vec4(-1, -1, 0, 1);\n"
3916 								  "    EmitVertex();\n"
3917 								  "    gs_fs_color      = gl_InvocationID;\n"
3918 								  "    gl_ViewportIndex = gl_InvocationID;\n"
3919 								  "    gl_Layer         = gl_InvocationID;\n"
3920 								  "    gl_Position  = vec4(-1, 1, 0, 1);\n"
3921 								  "    EmitVertex();\n"
3922 								  "    gs_fs_color      = gl_InvocationID;\n"
3923 								  "    gl_ViewportIndex = gl_InvocationID;\n"
3924 								  "    gl_Layer         = gl_InvocationID;\n"
3925 								  "    gl_Position  = vec4(1, -1, 0, 1);\n"
3926 								  "    EmitVertex();\n"
3927 								  "    gs_fs_color      = gl_InvocationID;\n"
3928 								  "    gl_ViewportIndex = gl_InvocationID;\n"
3929 								  "    gl_Layer         = gl_InvocationID;\n"
3930 								  "    gl_Position  = vec4(1, 1, 0, 1);\n"
3931 								  "    EmitVertex();\n"
3932 								  "}\n"
3933 								  "\n";
3934 
3935 	std::string result = source;
3936 
3937 	return result;
3938 }
3939 
3940 /** Check if R32I texture is filled with 4x4 regions of increasing values <0:15>
3941  *
3942  * @param texture_0       Verified texture
3943  * @param ignored
3944  * @param ignored
3945  *
3946  * @return True if texture_0 is filled with expected pattern
3947  **/
checkResults(Utils::texture & texture_0,Utils::texture &,GLuint)3948 bool DrawMultipleLayers::checkResults(Utils::texture& texture_0, Utils::texture& /* texture_1 */,
3949 									  GLuint /* draw_call_index */)
3950 {
3951 	static const GLuint layer_size = m_width * m_height;
3952 
3953 	bool check_result = true;
3954 
3955 	std::vector<GLint> texture_data;
3956 	texture_data.resize(layer_size * m_depth);
3957 	texture_0.get(GL_RED_INTEGER, GL_INT, &texture_data[0]);
3958 
3959 	/* 16 layers, only region corresponding with layer index should be modified */
3960 	for (GLuint layer = 0; layer < m_depth; ++layer)
3961 	{
3962 		GLuint index = 0;
3963 
3964 		for (GLuint y = 0; y < 4; ++y)
3965 		{
3966 			for (GLuint x = 0; x < 4; ++x)
3967 			{
3968 				GLint* layer_data = &texture_data[layer * layer_size];
3969 
3970 				GLint expected_value = -1;
3971 				if (index == layer)
3972 				{
3973 					expected_value = index;
3974 				}
3975 
3976 				bool result = checkRegionR32I(x, y, expected_value, layer_data);
3977 
3978 				if (false == result)
3979 				{
3980 					check_result = false;
3981 					goto end;
3982 				}
3983 
3984 				index += 1;
3985 			}
3986 		}
3987 	}
3988 
3989 end:
3990 	return check_result;
3991 }
3992 
3993 /** Prepare textures used as framebuffer's attachments for current draw call
3994  *
3995  * @param texture_0 R32I texture
3996  * @param ignored
3997  **/
prepareTextures(Utils::texture & texture_0,Utils::texture &)3998 void DrawMultipleLayers::prepareTextures(Utils::texture& texture_0, Utils::texture& /* texture_1 */)
3999 {
4000 	prepareTextureArrayR32I(texture_0);
4001 }
4002 
4003 /** Constructor
4004  *
4005  * @param context          Test context
4006  * @param test_name        Test name
4007  * @param test_description Test description
4008  **/
Scissor(deqp::Context & context,const glcts::ExtParameters & extParams)4009 Scissor::Scissor(deqp::Context& context, const glcts::ExtParameters& extParams)
4010 	: DrawMultipleLayers(context, extParams, "scissor", "Test verifies that scissor test is applied as expected")
4011 {
4012 	/* Nothing to be done here */
4013 }
4014 
4015 /** Get test type
4016  *
4017  * @return SCISSOR
4018  **/
getTestType()4019 DrawTestBase::TEST_TYPE Scissor::getTestType()
4020 {
4021 	return SCISSOR;
4022 }
4023 
4024 /** Constructor
4025  *
4026  * @param context          Test context
4027  * @param test_name        Test name
4028  * @param test_description Test description
4029  **/
ScissorZeroDimension(deqp::Context & context,const glcts::ExtParameters & extParams)4030 ScissorZeroDimension::ScissorZeroDimension(deqp::Context& context, const glcts::ExtParameters& extParams)
4031 	: DrawMultipleLayers(context, extParams, "scissor_zero_dimension",
4032 						 "Test verifies that scissor test discard all fragments when width and height is set to zero")
4033 {
4034 	/* Nothing to be done here */
4035 }
4036 
4037 /** Check if R32I texture is filled with 4x4 regions of increasing values <0:15>
4038  *
4039  * @param texture_0       Verified texture
4040  * @param ignored
4041  * @param ignored
4042  *
4043  * @return True if texture_0 is filled with expected pattern
4044  **/
checkResults(Utils::texture & texture_0,Utils::texture &,GLuint)4045 bool ScissorZeroDimension::checkResults(Utils::texture& texture_0, Utils::texture& /* texture_1 */,
4046 										GLuint /* draw_call_index */)
4047 {
4048 	static const GLuint layer_size = m_width * m_height;
4049 
4050 	bool check_result = true;
4051 
4052 	std::vector<GLint> texture_data;
4053 	texture_data.resize(layer_size * m_depth);
4054 	texture_0.get(GL_RED_INTEGER, GL_INT, &texture_data[0]);
4055 
4056 	/* 16 layers, all regions were not modified */
4057 	for (GLuint layer = 0; layer < m_depth; ++layer)
4058 	{
4059 		for (GLuint y = 0; y < 4; ++y)
4060 		{
4061 			for (GLuint x = 0; x < 4; ++x)
4062 			{
4063 				GLint* layer_data = &texture_data[layer * layer_size];
4064 
4065 				GLint expected_value = -1;
4066 
4067 				bool result = checkRegionR32I(x, y, expected_value, layer_data);
4068 
4069 				if (false == result)
4070 				{
4071 					check_result = false;
4072 					goto end;
4073 				}
4074 			}
4075 		}
4076 	}
4077 
4078 end:
4079 	return check_result;
4080 }
4081 
4082 /** Get test type
4083  *
4084  * @return SCISSOR
4085  **/
getTestType()4086 DrawTestBase::TEST_TYPE ScissorZeroDimension::getTestType()
4087 {
4088 	return SCISSOR;
4089 }
4090 
4091 /** Set up viewports
4092  *
4093  * @param Ignored
4094  * @param iteration_index Index of iteration for given test type
4095  **/
setupViewports(TEST_TYPE,GLuint iteration_index)4096 void ScissorZeroDimension::setupViewports(TEST_TYPE /* type */, GLuint iteration_index)
4097 {
4098 	SCISSOR_METHOD method;
4099 	switch (iteration_index)
4100 	{
4101 	case 0:
4102 	case 1:
4103 	case 2:
4104 		method = (SCISSOR_METHOD)iteration_index;
4105 		break;
4106 	default:
4107 		TCU_FAIL("Invalid value");
4108 	}
4109 
4110 	setup4x4Scissor(method, true /* set_zeros */);
4111 }
4112 
4113 /** Constructor
4114  *
4115  * @param context          Test context
4116  * @param test_name        Test name
4117  * @param test_description Test description
4118  **/
ScissorClear(deqp::Context & context,const glcts::ExtParameters & extParams)4119 ScissorClear::ScissorClear(deqp::Context& context, const glcts::ExtParameters& extParams)
4120 	: DrawMultipleLayers(context, extParams, "scissor_clear",
4121 						 "Test verifies that Clear is affected only by settings of scissor test in first viewport")
4122 {
4123 	/* Nothing to be done here */
4124 }
4125 
4126 /** Check if R32I texture is filled with 4x4 regions of increasing values <0:15>
4127  *
4128  * @param texture_0 Verified texture
4129  * @param ignored
4130  * @param ignored
4131  *
4132  * @return True if texture_0 is filled with expected pattern
4133  **/
checkResults(Utils::texture & texture_0,Utils::texture &,GLuint)4134 bool ScissorClear::checkResults(Utils::texture& texture_0, Utils::texture& /* texture_1 */, GLuint /*draw_call_index */)
4135 {
4136 	static const GLuint layer_size = m_width * m_height;
4137 
4138 	bool check_result = true;
4139 
4140 	std::vector<GLint> texture_data;
4141 	texture_data.resize(layer_size * m_depth);
4142 	texture_0.get(GL_RED_INTEGER, GL_INT, &texture_data[0]);
4143 
4144 	/* 16 layers, only region corresponding with scissor box 0 should be modified */
4145 	for (GLuint layer = 0; layer < m_depth; ++layer)
4146 	{
4147 		for (GLuint y = 0; y < 4; ++y)
4148 		{
4149 			for (GLuint x = 0; x < 4; ++x)
4150 			{
4151 				GLint* layer_data = &texture_data[layer * layer_size];
4152 
4153 				GLint expected_value = -1;
4154 				if ((0 == x) && (0 == y))
4155 				{
4156 					expected_value = 0;
4157 				}
4158 
4159 				bool result = checkRegionR32I(x, y, expected_value, layer_data);
4160 
4161 				if (false == result)
4162 				{
4163 					check_result = false;
4164 					goto end;
4165 				}
4166 			}
4167 		}
4168 	}
4169 
4170 end:
4171 	return check_result;
4172 }
4173 
4174 /** Get test type
4175  *
4176  * @return SCISSOR
4177  **/
getTestType()4178 DrawTestBase::TEST_TYPE ScissorClear::getTestType()
4179 {
4180 	return SCISSOR;
4181 }
4182 
4183 /** Selects if test should do draw or clear operation
4184  *
4185  * @return true - clear operation
4186  **/
isClearTest()4187 bool ScissorClear::isClearTest()
4188 {
4189 	return true;
4190 }
4191 
4192 /** Constructor
4193  *
4194  * @param context          Test context
4195  * @param test_name        Test name
4196  * @param test_description Test description
4197  **/
DepthRange(deqp::Context & context,const glcts::ExtParameters & extParams)4198 DepthRange::DepthRange(deqp::Context& context, const glcts::ExtParameters& extParams)
4199 	: DrawTestBase(context, extParams, "depth_range", "Test verifies that depth range is applied as expected")
4200 {
4201 	/* Nothing to be done here */
4202 }
4203 
4204 /** Check if R32F texture is filled with two rows, top with decreasing values, bottom with incresing values
4205  *
4206  * @param texture_0 Verified texture
4207  * @param ignored
4208  * @param ignored
4209  *
4210  * @return True if texture_0 is filled with expected pattern
4211  **/
checkResults(Utils::texture & texture_0,Utils::texture &,GLuint)4212 bool DepthRange::checkResults(Utils::texture& texture_0, Utils::texture& /* texture_1 */, GLuint /*draw_call_index */)
4213 {
4214 	static const GLfloat step = 1.0f / 16.0f;
4215 
4216 	bool check_result = true;
4217 
4218 	std::vector<GLfloat> texture_data;
4219 	texture_data.resize(m_r32f_width * m_r32f_height);
4220 	texture_0.get(GL_RED, GL_FLOAT, &texture_data[0]);
4221 
4222 	GLfloat depth_data[16 * 2];
4223 
4224 	for (GLuint i = 0; i < 16; ++i)
4225 	{
4226 		const GLfloat near = step * (GLfloat)i;
4227 
4228 		depth_data[i * 2 + 0] = near;
4229 		depth_data[i * 2 + 1] = 1.0f - near;
4230 	}
4231 
4232 	for (GLuint i = 0; i < 16; ++i)
4233 	{
4234 		const GLfloat expected_near = depth_data[i * 2 + 0];
4235 		const GLfloat expected_far  = depth_data[i * 2 + 1];
4236 
4237 		/* Bottom row should contain near values, top one should contain far values */
4238 		const GLfloat near = texture_data[i];
4239 		const GLfloat far  = texture_data[i + 16];
4240 
4241 		if ((expected_near != near) || (expected_far != far))
4242 		{
4243 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid values at " << i << " expected ["
4244 												<< expected_near << ", " << expected_far << "] got [" << near << ", "
4245 												<< far << "]" << tcu::TestLog::EndMessage;
4246 
4247 			check_result = false;
4248 			break;
4249 		}
4250 	}
4251 
4252 	return check_result;
4253 }
4254 
4255 /** Get string with fragment shader source code
4256  *
4257  * @return Fragment shader source
4258  **/
getFragmentShader()4259 std::string DepthRange::getFragmentShader()
4260 {
4261 	static const GLchar* source = "${VERSION}\n"
4262 								  "\n"
4263 								  "#ifdef GL_ES\n"
4264 								  "precision highp float;\n"
4265 								  "#endif\n"
4266 								  "out float fs_out_color;\n"
4267 								  "\n"
4268 								  "void main()\n"
4269 								  "{\n"
4270 								  "    fs_out_color = gl_FragCoord.z;\n"
4271 								  "}\n"
4272 								  "\n";
4273 
4274 	std::string result = source;
4275 
4276 	return result;
4277 }
4278 
4279 /** Get string with geometry shader source code
4280  *
4281  * @return Geometry shader source
4282  **/
getGeometryShader()4283 std::string DepthRange::getGeometryShader()
4284 {
4285 	static const GLchar* source = "${VERSION}\n"
4286 								  "\n"
4287 								  "${GEOMETRY_SHADER_ENABLE}\n"
4288 								  "${VIEWPORT_ARRAY_ENABLE}\n"
4289 								  "\n"
4290 								  "layout(points, invocations = 16)         in;\n"
4291 								  "layout(triangle_strip, max_vertices = 8) out;\n"
4292 								  "\n"
4293 								  "void main()\n"
4294 								  "{\n"
4295 								  "    const float top_z    = 1.0;\n"
4296 								  "    const float bottom_z = -1.0;\n"
4297 								  "\n"
4298 								  "    /* Bottom */\n"
4299 								  "    gl_ViewportIndex = gl_InvocationID;\n"
4300 								  "    gl_Position  = vec4(-1, -1, bottom_z, 1);\n"
4301 								  "    EmitVertex();\n"
4302 								  "    gl_ViewportIndex = gl_InvocationID;\n"
4303 								  "    gl_Position  = vec4(-1, 0, bottom_z, 1);\n"
4304 								  "    EmitVertex();\n"
4305 								  "    gl_ViewportIndex = gl_InvocationID;\n"
4306 								  "    gl_Position  = vec4(1, -1, bottom_z, 1);\n"
4307 								  "    EmitVertex();\n"
4308 								  "    gl_ViewportIndex = gl_InvocationID;\n"
4309 								  "    gl_Position  = vec4(1, 0, bottom_z, 1);\n"
4310 								  "    EmitVertex();\n"
4311 								  "    EndPrimitive();\n"
4312 								  "\n"
4313 								  "    /* Top */\n"
4314 								  "    gl_ViewportIndex = gl_InvocationID;\n"
4315 								  "    gl_Position  = vec4(-1, 0, top_z, 1);\n"
4316 								  "    EmitVertex();\n"
4317 								  "    gl_ViewportIndex = gl_InvocationID;\n"
4318 								  "    gl_Position  = vec4(-1, 1, top_z, 1);\n"
4319 								  "    EmitVertex();\n"
4320 								  "    gl_ViewportIndex = gl_InvocationID;\n"
4321 								  "    gl_Position  = vec4(1, 0, top_z, 1);\n"
4322 								  "    EmitVertex();\n"
4323 								  "    gl_ViewportIndex = gl_InvocationID;\n"
4324 								  "    gl_Position  = vec4(1, 1, top_z, 1);\n"
4325 								  "    EmitVertex();\n"
4326 								  "    EndPrimitive();\n"
4327 								  "}\n"
4328 								  "\n";
4329 
4330 	std::string result = source;
4331 
4332 	return result;
4333 }
4334 
4335 /** Get test type
4336  *
4337  * @return DEPTHRANGE
4338  **/
getTestType()4339 DrawTestBase::TEST_TYPE DepthRange::getTestType()
4340 {
4341 	return DEPTHRANGE;
4342 }
4343 
4344 /** Prepare textures used as framebuffer's attachments for current draw call
4345  *
4346  * @param texture_0 R32F texture
4347  * @param ignored
4348  **/
prepareTextures(Utils::texture & texture_0,Utils::texture &)4349 void DepthRange::prepareTextures(Utils::texture& texture_0, Utils::texture& /* texture_1 */)
4350 {
4351 	prepareTextureR32F(texture_0);
4352 }
4353 
4354 /** Constructor
4355  *
4356  * @param context          Test context
4357  * @param test_name        Test name
4358  * @param test_description Test description
4359  **/
DepthRangeDepthTest(deqp::Context & context,const glcts::ExtParameters & extParams)4360 DepthRangeDepthTest::DepthRangeDepthTest(deqp::Context& context, const glcts::ExtParameters& extParams)
4361 	: DrawTestBase(context, extParams, "depth_range_depth_test",
4362 				   "Test verifies that depth test work as expected with multiple viewports")
4363 {
4364 	/* Nothing to be done here */
4365 }
4366 
4367 /** Check if R32F texture is filled with two rows of values less than expected depth
4368  *
4369  * @param texture_0       Verified texture
4370  * @param ignored
4371  * @param draw_call_index Index of draw call
4372  *
4373  * @return True if texture_0 is filled with expected pattern
4374  **/
checkResults(Utils::texture & texture_0,Utils::texture &,GLuint draw_call_index)4375 bool DepthRangeDepthTest::checkResults(Utils::texture& texture_0, Utils::texture& /* texture_1 */,
4376 									   GLuint		   draw_call_index)
4377 {
4378 	static const GLfloat step = 1.0f / 16.0f;
4379 
4380 	const GLfloat depth_value = step * (GLfloat)draw_call_index;
4381 
4382 	bool check_result = true;
4383 
4384 	std::vector<GLfloat> texture_data;
4385 	texture_data.resize(m_r32f_width * m_r32f_height);
4386 	texture_0.get(GL_RED, GL_FLOAT, &texture_data[0]);
4387 
4388 	for (GLuint i = 0; i < 16; ++i)
4389 	{
4390 		/* Bottom row should contain near values, top one should contain far values */
4391 		const GLfloat near = texture_data[i];
4392 		const GLfloat far  = texture_data[i + 16];
4393 
4394 		if ((depth_value <= near) || (depth_value <= far))
4395 		{
4396 			m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid values at " << i << " depth value "
4397 												<< depth_value << " got [" << near << ", " << far << "]"
4398 												<< tcu::TestLog::EndMessage;
4399 
4400 			check_result = false;
4401 			break;
4402 		}
4403 	}
4404 
4405 	return check_result;
4406 }
4407 
4408 /** Get settings of clear operation
4409  *
4410  * @param clear_depth_before_draw Selects if clear should be executed before draw.
4411  * @param iteration_index         Index of draw call
4412  * @param depth_value             Value that will be used to clear depth buffer
4413  **/
getClearSettings(bool & clear_depth_before_draw,GLuint iteration_index,GLfloat & depth_value)4414 void DepthRangeDepthTest::getClearSettings(bool& clear_depth_before_draw, GLuint iteration_index, GLfloat& depth_value)
4415 {
4416 	static const GLfloat step = 1.0 / 16.0;
4417 
4418 	clear_depth_before_draw = true;
4419 
4420 	depth_value = step * (GLfloat)iteration_index;
4421 }
4422 
4423 /** Get number of draw call to be executed during test
4424  *
4425  * @return 18
4426  **/
getDrawCallsNumber()4427 GLuint DepthRangeDepthTest::getDrawCallsNumber()
4428 {
4429 	return 18;
4430 }
4431 
4432 /** Get string with fragment shader source code
4433  *
4434  * @return Fragment shader source
4435  **/
getFragmentShader()4436 std::string DepthRangeDepthTest::getFragmentShader()
4437 {
4438 	static const GLchar* source = "${VERSION}\n"
4439 								  "\n"
4440 								  "#ifdef GL_ES\n"
4441 								  "precision highp float;\n"
4442 								  "#endif\n"
4443 								  "out float fs_out_color;\n"
4444 								  "\n"
4445 								  "void main()\n"
4446 								  "{\n"
4447 								  "    fs_out_color = gl_FragCoord.z;\n"
4448 								  "}\n"
4449 								  "\n";
4450 
4451 	std::string result = source;
4452 
4453 	return result;
4454 }
4455 
4456 /** Get string with geometry shader source code
4457  *
4458  * @return Geometry shader source
4459  **/
getGeometryShader()4460 std::string DepthRangeDepthTest::getGeometryShader()
4461 {
4462 	static const GLchar* source = "${VERSION}\n"
4463 								  "\n"
4464 								  "${GEOMETRY_SHADER_ENABLE}\n"
4465 								  "${VIEWPORT_ARRAY_ENABLE}\n"
4466 								  "\n"
4467 								  "layout(points, invocations = 16)         in;\n"
4468 								  "layout(triangle_strip, max_vertices = 8) out;\n"
4469 								  "\n"
4470 								  "void main()\n"
4471 								  "{\n"
4472 								  "    const float top_z    = 1.0;\n"
4473 								  "    const float bottom_z = -1.0;\n"
4474 								  "\n"
4475 								  "    /* Bottom */\n"
4476 								  "    gl_ViewportIndex = gl_InvocationID;\n"
4477 								  "    gl_Position  = vec4(-1, -1, bottom_z, 1);\n"
4478 								  "    EmitVertex();\n"
4479 								  "    gl_ViewportIndex = gl_InvocationID;\n"
4480 								  "    gl_Position  = vec4(-1, 0, bottom_z, 1);\n"
4481 								  "    EmitVertex();\n"
4482 								  "    gl_ViewportIndex = gl_InvocationID;\n"
4483 								  "    gl_Position  = vec4(1, -1, bottom_z, 1);\n"
4484 								  "    EmitVertex();\n"
4485 								  "    gl_ViewportIndex = gl_InvocationID;\n"
4486 								  "    gl_Position  = vec4(1, 0, bottom_z, 1);\n"
4487 								  "    EmitVertex();\n"
4488 								  "\n"
4489 								  "    /* Top */\n"
4490 								  "    gl_ViewportIndex = gl_InvocationID;\n"
4491 								  "    gl_Position  = vec4(-1, 0, top_z, 1);\n"
4492 								  "    EmitVertex();\n"
4493 								  "    gl_ViewportIndex = gl_InvocationID;\n"
4494 								  "    gl_Position  = vec4(-1, 1, top_z, 1);\n"
4495 								  "    EmitVertex();\n"
4496 								  "    gl_ViewportIndex = gl_InvocationID;\n"
4497 								  "    gl_Position  = vec4(1, 0, top_z, 1);\n"
4498 								  "    EmitVertex();\n"
4499 								  "    gl_ViewportIndex = gl_InvocationID;\n"
4500 								  "    gl_Position  = vec4(1, 1, top_z, 1);\n"
4501 								  "    EmitVertex();\n"
4502 								  "    EndPrimitive();\n"
4503 								  "}\n"
4504 								  "\n";
4505 
4506 	std::string result = source;
4507 
4508 	return result;
4509 }
4510 
4511 /** Get test type
4512  *
4513  * @return DEPTHRANGE
4514  **/
getTestType()4515 DrawTestBase::TEST_TYPE DepthRangeDepthTest::getTestType()
4516 {
4517 	return DEPTHRANGE;
4518 }
4519 
4520 /** Prepare textures used as framebuffer's attachments for current draw call
4521  *
4522  * @param texture_0 R32F texture
4523  * @param texture_1 D32F texture
4524  **/
prepareTextures(Utils::texture & texture_0,Utils::texture & texture_1)4525 void DepthRangeDepthTest::prepareTextures(Utils::texture& texture_0, Utils::texture& texture_1)
4526 {
4527 	prepareTextureR32F(texture_0);
4528 	prepareTextureD32F(texture_1);
4529 }
4530 
4531 /** Attach textures to framebuffer
4532  *
4533  * @param framebuffer Framebuffer instance
4534  * @param texture_0   Texture attached as color 0
4535  * @param texture_1   Texture attached as depth
4536  **/
setupFramebuffer(Utils::framebuffer & framebuffer,Utils::texture & texture_0,Utils::texture & texture_1)4537 void DepthRangeDepthTest::setupFramebuffer(Utils::framebuffer& framebuffer, Utils::texture& texture_0,
4538 										   Utils::texture& texture_1)
4539 {
4540 	framebuffer.attachTexture(GL_COLOR_ATTACHMENT0, texture_0.m_id, m_width, m_height);
4541 	framebuffer.attachTexture(GL_DEPTH_ATTACHMENT, texture_1.m_id, m_width, m_height);
4542 }
4543 
4544 /** Set up viewports
4545  *
4546  * @param ignored
4547  * @param iteration_index Index of iteration for given test type
4548  **/
setupViewports(TEST_TYPE,GLuint iteration_index)4549 void DepthRangeDepthTest::setupViewports(TEST_TYPE /* type */, GLuint iteration_index)
4550 {
4551 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4552 
4553 	DEPTH_RANGE_METHOD method;
4554 	switch (iteration_index)
4555 	{
4556 	case 0:
4557 	case 1:
4558 		method = (DEPTH_RANGE_METHOD)iteration_index;
4559 		break;
4560 	default:
4561 		TCU_FAIL("Invalid value");
4562 	}
4563 	setup16x2Depths(method);
4564 
4565 	gl.enable(GL_DEPTH_TEST);
4566 	GLU_EXPECT_NO_ERROR(gl.getError(), "Enable");
4567 }
4568 
4569 /** Constructor
4570  *
4571  * @param context          Test context
4572  * @param test_name        Test name
4573  * @param test_description Test description
4574  **/
ProvokingVertex(deqp::Context & context,const glcts::ExtParameters & extParams)4575 ProvokingVertex::ProvokingVertex(deqp::Context& context, const glcts::ExtParameters& extParams)
4576 	: DrawTestBase(context, extParams, "provoking_vertex", "Test verifies that provoking vertex work as expected")
4577 {
4578 	/* Nothing to be done here */
4579 }
4580 
4581 /** Check if R32I texture is filled with 4x4 regions of increasing values <0:15>
4582  *
4583  * @param texture_0 Verified texture
4584  * @param ignored
4585  * @param ignored
4586  *
4587  * @return True if texture_0 is filled with expected pattern
4588  **/
checkResults(Utils::texture & texture_0,Utils::texture &,GLuint)4589 bool ProvokingVertex::checkResults(Utils::texture& texture_0, Utils::texture& /* texture_1 */,
4590 								   GLuint /*draw_call_index */)
4591 {
4592 	static const GLuint layer_size = m_width * m_height;
4593 
4594 	const glw::Functions&   gl			 = m_context.getRenderContext().getFunctions();
4595 	const glu::ContextType& context_type = m_context.getRenderContext().getType();
4596 
4597 	GLint layer_mode	= 0;
4598 	GLint viewport_mode = 0;
4599 	gl.getIntegerv(GL_LAYER_PROVOKING_VERTEX, &layer_mode);
4600 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
4601 	gl.getIntegerv(GL_VIEWPORT_INDEX_PROVOKING_VERTEX, &viewport_mode);
4602 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
4603 
4604 	if ((GL_UNDEFINED_VERTEX == layer_mode) || (GL_UNDEFINED_VERTEX == viewport_mode))
4605 	{
4606 		/* Results are undefined, therefore it does not make sense to verify them */
4607 		return true;
4608 	}
4609 
4610 	bool  check_result = true;
4611 	GLint provoking	= 0;
4612 
4613 	std::vector<GLint> texture_data;
4614 	texture_data.resize(layer_size * m_r32ix4_depth);
4615 	texture_0.get(GL_RED_INTEGER, GL_INT, &texture_data[0]);
4616 
4617 	if (glu::isContextTypeGLCore(context_type))
4618 	{
4619 		gl.getIntegerv(GL_PROVOKING_VERTEX, &provoking);
4620 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
4621 	}
4622 	else
4623 	{
4624 		DE_ASSERT(glu::isContextTypeES(context_type));
4625 		/* ES doesn't have provoking vertex control, so it's always LAST */
4626 		provoking = GL_LAST_VERTEX_CONVENTION;
4627 	}
4628 
4629 	GLuint expected_layer	= 0;
4630 	GLint  expected_viewport = 0;
4631 
4632 	/* Mode is 1st, or mode is provoking and provoking is 1st */
4633 	if ((GL_FIRST_VERTEX_CONVENTION == layer_mode) ||
4634 		((GL_PROVOKING_VERTEX == layer_mode) && (GL_FIRST_VERTEX_CONVENTION == provoking)))
4635 	{
4636 		expected_layer = 0;
4637 	}
4638 	else
4639 	{
4640 		expected_layer = 2;
4641 	}
4642 
4643 	if ((GL_FIRST_VERTEX_CONVENTION == viewport_mode) ||
4644 		((GL_PROVOKING_VERTEX == viewport_mode) && (GL_FIRST_VERTEX_CONVENTION == provoking)))
4645 	{
4646 		expected_viewport = 0;
4647 	}
4648 	else
4649 	{
4650 		expected_viewport = 2;
4651 	}
4652 
4653 	for (GLuint layer = 0; layer < m_r32ix4_depth; ++layer)
4654 	{
4655 		GLint* layer_data = &texture_data[layer * layer_size];
4656 		GLint  viewport   = 0;
4657 
4658 		for (GLuint y = 0; y < 2; ++y)
4659 		{
4660 			for (GLuint x = 0; x < 2; ++x)
4661 			{
4662 				/* If layer and viewport are expected ones, than result shall be 1, otherwise -1. */
4663 				const GLint expected_value = ((expected_viewport == viewport) && (expected_layer == layer)) ? 1 : -1;
4664 
4665 				bool result = checkRegionR32I(x, y, m_width / 2, m_height / 2, expected_value, layer_data);
4666 
4667 				if (false == result)
4668 				{
4669 					check_result = false;
4670 					goto end;
4671 				}
4672 
4673 				viewport += 1;
4674 			}
4675 		}
4676 	}
4677 
4678 end:
4679 	return check_result;
4680 }
4681 
4682 /** Get string with fragment shader source code
4683  *
4684  * @return Fragment shader source
4685  **/
getFragmentShader()4686 std::string ProvokingVertex::getFragmentShader()
4687 {
4688 	static const GLchar* source = "${VERSION}\n"
4689 								  "\n"
4690 								  "flat in  int gs_fs_color;\n"
4691 								  "     out int fs_out_color;\n"
4692 								  "\n"
4693 								  "void main()\n"
4694 								  "{\n"
4695 								  "    fs_out_color = gs_fs_color;\n"
4696 								  "}\n"
4697 								  "\n";
4698 
4699 	std::string result = source;
4700 
4701 	return result;
4702 }
4703 
4704 /** Get string with geometry shader source code
4705  *
4706  * @return Geometry shader source
4707  **/
getGeometryShader()4708 std::string ProvokingVertex::getGeometryShader()
4709 {
4710 	static const GLchar* source = "${VERSION}\n"
4711 								  "\n"
4712 								  "${GEOMETRY_SHADER_ENABLE}\n"
4713 								  "${VIEWPORT_ARRAY_ENABLE}\n"
4714 								  "\n"
4715 								  "layout(points, invocations = 1)          in;\n"
4716 								  "layout(triangle_strip, max_vertices = 6) out;\n"
4717 								  "\n"
4718 								  "flat out int gs_fs_color;\n"
4719 								  "\n"
4720 								  "void main()\n"
4721 								  "{\n"
4722 								  "    /* Left-bottom half */\n"
4723 								  "    gs_fs_color      = 1;\n"
4724 								  "    gl_ViewportIndex = 0;\n"
4725 								  "    gl_Layer         = 0;\n"
4726 								  "    gl_Position  = vec4(-1, -1, 0, 1);\n"
4727 								  "    EmitVertex();\n"
4728 								  "    gs_fs_color      = 1;\n"
4729 								  "    gl_ViewportIndex = 1;\n"
4730 								  "    gl_Layer         = 1;\n"
4731 								  "    gl_Position  = vec4(-1, 1, 0, 1);\n"
4732 								  "    EmitVertex();\n"
4733 								  "    gs_fs_color      = 1;\n"
4734 								  "    gl_ViewportIndex = 2;\n"
4735 								  "    gl_Layer         = 2;\n"
4736 								  "    gl_Position  = vec4(1, -1, 0, 1);\n"
4737 								  "    EmitVertex();\n"
4738 								  "    EndPrimitive();\n"
4739 								  "\n"
4740 								  "    /* Right-top half */\n"
4741 								  "    gs_fs_color      = 1;\n"
4742 								  "    gl_ViewportIndex = 0;\n"
4743 								  "    gl_Layer         = 0;\n"
4744 								  "    gl_Position  = vec4(-1, 1, 0, 1);\n"
4745 								  "    EmitVertex();\n"
4746 								  "    gs_fs_color      = 1;\n"
4747 								  "    gl_ViewportIndex = 1;\n"
4748 								  "    gl_Layer         = 1;\n"
4749 								  "    gl_Position  = vec4(1, 1, 0, 1);\n"
4750 								  "    EmitVertex();\n"
4751 								  "    gs_fs_color      = 1;\n"
4752 								  "    gl_ViewportIndex = 2;\n"
4753 								  "    gl_Layer         = 2;\n"
4754 								  "    gl_Position  = vec4(1, -1, 0, 1);\n"
4755 								  "    EmitVertex();\n"
4756 								  "    EndPrimitive();\n"
4757 								  "}\n"
4758 								  "\n";
4759 
4760 	std::string result = source;
4761 
4762 	return result;
4763 }
4764 
4765 /** Get test type
4766  *
4767  * @return PROVOKING
4768  **/
getTestType()4769 DrawTestBase::TEST_TYPE ProvokingVertex::getTestType()
4770 {
4771 	return PROVOKING;
4772 }
4773 
4774 /** Prepare textures used as framebuffer's attachments for current draw call
4775  *
4776  * @param texture_0 R32I texture
4777  * @param ignored
4778  **/
prepareTextures(Utils::texture & texture_0,Utils::texture &)4779 void ProvokingVertex::prepareTextures(Utils::texture& texture_0, Utils::texture& /* texture_1 */)
4780 {
4781 	prepareTextureR32Ix4(texture_0);
4782 }
4783 
4784 } /* ViewportArray namespace */
4785 
4786 /** Constructor.
4787  *
4788  *  @param context Rendering context.
4789  **/
ViewportArrayTests(deqp::Context & context,const glcts::ExtParameters & extParams)4790 ViewportArrayTests::ViewportArrayTests(deqp::Context& context, const glcts::ExtParameters& extParams)
4791 	: TestCaseGroupBase(context, extParams, "viewport_array", "Verifies \"viewport_array\" functionality")
4792 {
4793 	/* Left blank on purpose */
4794 }
4795 
4796 /** Initializes a texture_storage_multisample test group.
4797  *
4798  **/
init(void)4799 void ViewportArrayTests::init(void)
4800 {
4801 	addChild(new ViewportArray::APIErrors(m_context, m_extParams));
4802 	addChild(new ViewportArray::Queries(m_context, m_extParams));
4803 	addChild(new ViewportArray::ViewportAPI(m_context, m_extParams));
4804 	addChild(new ViewportArray::ScissorAPI(m_context, m_extParams));
4805 	addChild(new ViewportArray::DepthRangeAPI(m_context, m_extParams));
4806 	addChild(new ViewportArray::ScissorTestStateAPI(m_context, m_extParams));
4807 	addChild(new ViewportArray::DrawToSingleLayerWithMultipleViewports(m_context, m_extParams));
4808 	addChild(new ViewportArray::DynamicViewportIndex(m_context, m_extParams));
4809 	addChild(new ViewportArray::DrawMulitpleViewportsWithSingleInvocation(m_context, m_extParams));
4810 	addChild(new ViewportArray::ViewportIndexSubroutine(m_context, m_extParams));
4811 	addChild(new ViewportArray::DrawMultipleLayers(m_context, m_extParams));
4812 	addChild(new ViewportArray::Scissor(m_context, m_extParams));
4813 	addChild(new ViewportArray::ScissorZeroDimension(m_context, m_extParams));
4814 	addChild(new ViewportArray::ScissorClear(m_context, m_extParams));
4815 	addChild(new ViewportArray::DepthRange(m_context, m_extParams));
4816 	addChild(new ViewportArray::DepthRangeDepthTest(m_context, m_extParams));
4817 	addChild(new ViewportArray::ProvokingVertex(m_context, m_extParams));
4818 }
4819 
4820 } /* glcts namespace */
4821