Home | History | Annotate | Download | only in common
      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  **/
     55 Utils::buffer::buffer(deqp::Context& context) : m_id(0), m_context(context), m_target(0)
     56 {
     57 }
     58 
     59 /** Destructor
     60  *
     61  **/
     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  **/
     76 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  **/
     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  **/
    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  **/
    118 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  **/
    134 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  **/
    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  **/
    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  **/
    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  **/
    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  **/
    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  **/
    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  **/
    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  **/
    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 
    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 
    261 const char* Utils::shaderCompilationException::what() const throw()
    262 {
    263 	return "Shader compilation failed";
    264 }
    265 
    266 Utils::programLinkageException::programLinkageException(const glw::GLchar* message) : m_error_message(message)
    267 {
    268 	/* Nothing to be done */
    269 }
    270 
    271 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  **/
    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  **/
    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  **/
    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 
    394 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 
    435 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  **/
    452 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  **/
    477 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  **/
    502 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  **/
    524 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  **/
    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  **/
    656 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 
    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  **/
    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  **/
    710 Utils::texture::~texture()
    711 {
    712 	release();
    713 }
    714 
    715 /** Bind texture to GL_TEXTURE_2D
    716  *
    717  **/
    718 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  **/
    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  **/
    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  **/
    793 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  **/
    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  **/
    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  **/
    919 Utils::vertexArray::vertexArray(deqp::Context& context) : m_id(0), m_context(context)
    920 {
    921 }
    922 
    923 /** Destructor
    924  *
    925  **/
    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  **/
    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  **/
    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  **/
    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>
    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>
    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>
   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  **/
   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  **/
   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  **/
   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>
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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>
   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>
   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>
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   2747 GLuint DrawTestBase::getDrawCallsNumber()
   2748 {
   2749 	return 1;
   2750 }
   2751 
   2752 /** Get test type
   2753  *
   2754  * @return VIEWPORT
   2755  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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>
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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