Block/non-block uniforms match
[platform/upstream/VK-GL-CTS.git] / external / openglcts / modules / common / glcViewportArrayTests.cpp
1 /*-------------------------------------------------------------------------
2  * OpenGL Conformance Test Suite
3  * -----------------------------
4  *
5  * Copyright (c) 2014-2016 The Khronos Group Inc.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  */ /*!
20  * \file
21  * \brief
22  */ /*-------------------------------------------------------------------*/
23
24 /**
25  * \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 */