Fix existing viewport_array bugs
[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) : m_id(0), m_context(context), m_is_array(false)
702 {
703         /* Nothing to done here */
704 }
705
706 /** Destructor
707  *
708  **/
709 Utils::texture::~texture()
710 {
711         release();
712 }
713
714 /** Bind texture to GL_TEXTURE_2D
715  *
716  **/
717 void Utils::texture::bind() const
718 {
719         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
720
721         if (false == m_is_array)
722         {
723                 gl.bindTexture(GL_TEXTURE_2D, m_id);
724                 GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
725         }
726         else
727         {
728                 gl.bindTexture(GL_TEXTURE_2D_ARRAY, m_id);
729                 GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
730         }
731 }
732
733 /** Create 2d texture
734  *
735  * @param width           Width of texture
736  * @param height          Height of texture
737  * @param internal_format Internal format of texture
738  **/
739 void Utils::texture::create(GLuint width, GLuint height, GLenum internal_format)
740 {
741         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
742
743         release();
744
745         m_is_array = false;
746
747         gl.genTextures(1, &m_id);
748         GLU_EXPECT_NO_ERROR(gl.getError(), "GenTextures");
749
750         bind();
751
752         gl.texStorage2D(GL_TEXTURE_2D, 1 /* levels */, internal_format, width, height);
753         GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage2D");
754 }
755
756 /** Create 2d texture array
757  *
758  * @param width           Width of texture
759  * @param height          Height of texture
760  * @param depth           Depth of texture
761  * @param internal_format Internal format of texture
762  **/
763 void Utils::texture::create(GLuint width, GLuint height, GLuint depth, GLenum internal_format)
764 {
765         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
766
767         release();
768
769         m_is_array = true;
770
771         gl.genTextures(1, &m_id);
772         GLU_EXPECT_NO_ERROR(gl.getError(), "GenTextures");
773
774         bind();
775
776         gl.texStorage3D(GL_TEXTURE_2D_ARRAY, 1 /* levels */, internal_format, width, height, depth);
777         GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage3D");
778 }
779
780 /** Get contents of texture
781  *
782  * @param format   Format of image
783  * @param type     Type of image
784  * @param out_data Buffer for image
785  **/
786 void Utils::texture::get(glw::GLenum format, glw::GLenum type, glw::GLvoid* out_data) const
787 {
788         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
789
790         bind();
791
792         GLenum textarget = GL_TEXTURE_2D;
793
794         if (true == m_is_array)
795         {
796                 textarget = GL_TEXTURE_2D_ARRAY;
797         }
798
799         gl.getTexImage(textarget, 0 /* level */, format, type, out_data);
800         GLU_EXPECT_NO_ERROR(gl.getError(), "GetTexImage");
801 }
802
803 /** Delete texture
804  *
805  **/
806 void Utils::texture::release()
807 {
808         if (0 != m_id)
809         {
810                 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
811
812                 gl.deleteTextures(1, &m_id);
813                 m_id = 0;
814         }
815 }
816
817 /** Update contents of texture
818  *
819  * @param width  Width of texture
820  * @param height Height of texture
821  * @param depth  Depth of texture
822  * @param format Format of data
823  * @param type   Type of data
824  * @param data   Buffer with image
825  **/
826 void Utils::texture::update(glw::GLuint width, glw::GLuint height, glw::GLuint depth, glw::GLenum format,
827                                                         glw::GLenum type, glw::GLvoid* data)
828 {
829         static const GLuint level = 0;
830
831         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
832
833         bind();
834
835         if (false == m_is_array)
836         {
837                 gl.texSubImage2D(GL_TEXTURE_2D, level, 0 /* x */, 0 /* y */, width, height, format, type, data);
838                 GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage2D");
839         }
840         else
841         {
842                 gl.texSubImage3D(GL_TEXTURE_2D_ARRAY, level, 0 /* x */, 0 /* y */, 0 /* z */, width, height, depth, format,
843                                                  type, data);
844                 GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage2D");
845         }
846 }
847
848 /** Constructor.
849  *
850  * @param context CTS context.
851  **/
852 Utils::vertexArray::vertexArray(deqp::Context& context) : m_id(0), m_context(context)
853 {
854 }
855
856 /** Destructor
857  *
858  **/
859 Utils::vertexArray::~vertexArray()
860 {
861         if (0 != m_id)
862         {
863                 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
864
865                 gl.deleteVertexArrays(1, &m_id);
866
867                 m_id = 0;
868         }
869 }
870
871 /** Execute BindVertexArray
872  *
873  **/
874 void Utils::vertexArray::bind()
875 {
876         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
877
878         gl.bindVertexArray(m_id);
879         GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexArray");
880 }
881
882 /** Execute GenVertexArrays
883  *
884  **/
885 void Utils::vertexArray::generate()
886 {
887         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
888
889         gl.genVertexArrays(1, &m_id);
890         GLU_EXPECT_NO_ERROR(gl.getError(), "GenVertexArrays");
891 }
892
893 /** Constructor
894  *
895  * @param context          Test context
896  **/
897 APIErrors::APIErrors(deqp::Context& context, const glcts::ExtParameters& extParams)
898         : TestCaseBase(context, extParams, "api_errors", "Test verifies error generated by API")
899 {
900         /* Nothing to be done here */
901 }
902
903 /** Execute test
904  *
905  * @return tcu::TestNode::CONTINUE after executing test case, tcu::TestNode::STOP otherwise
906  **/
907 tcu::TestNode::IterateResult APIErrors::iterate()
908 {
909         /* GL entry points */
910         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
911
912         /* Test result */
913         bool test_result = true;
914
915         GLint max_viewports = 0;
916         gl.getIntegerv(GL_MAX_VIEWPORTS, &max_viewports);
917         GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
918
919         /*
920          *   * DepthRangeArrayv generates INVALID_VALUE when <first> + <count> is greater
921          *   than or equal to the value of MAX_VIEWPORTS;
922          */
923         {
924                 std::vector<GLdouble> data;
925                 data.resize(max_viewports * 2 /* near + far */);
926
927                 for (GLint i = 0; i < max_viewports; ++i)
928                 {
929                         data[i * 2]             = 0.0;
930                         data[i * 2 + 1] = 1.0;
931                 }
932
933                 gl.depthRangeArrayv(0, max_viewports - 1, &data[0]);
934                 checkGLError(GL_NO_ERROR, "depthRangeArrayv, correct parameters", test_result);
935
936                 gl.depthRangeArrayv(max_viewports, 1, &data[0]);
937                 checkGLError(GL_INVALID_VALUE, "depthRangeArrayv, <first> == GL_MAX_VIEWPORTS", test_result);
938
939                 gl.depthRangeArrayv(1, max_viewports - 1, &data[0]);
940                 checkGLError(GL_NO_ERROR, "depthRangeArrayv, <first> + <count> == GL_MAX_VIEWPORTS", test_result);
941
942                 gl.depthRangeArrayv(1, max_viewports, &data[0]);
943                 checkGLError(GL_INVALID_VALUE, "depthRangeArrayv, <first> + <count> > GL_MAX_VIEWPORTS", test_result);
944         }
945
946         /*
947          *   * DepthRangeIndexed generates INVALID_VALUE when <index> is greater than or
948          *   equal to the value of MAX_VIEWPORTS;
949          */
950         {
951                 gl.depthRangeIndexed(0 /* index */, 0.0, 1.0);
952                 checkGLError(GL_NO_ERROR, "depthRangeIndexed, <index> == 0", test_result);
953
954                 gl.depthRangeIndexed(max_viewports - 1 /* index */, 0.0, 1.0);
955                 checkGLError(GL_NO_ERROR, "depthRangeIndexed, <index> == GL_MAX_VIEWPORTS - 1", test_result);
956
957                 gl.depthRangeIndexed(max_viewports /* index */, 0.0, 1.0);
958                 checkGLError(GL_INVALID_VALUE, "depthRangeIndexed, <index> == GL_MAX_VIEWPORTS", test_result);
959
960                 gl.depthRangeIndexed(max_viewports + 1 /* index */, 0.0, 1.0);
961                 checkGLError(GL_INVALID_VALUE, "depthRangeIndexed, <index> > GL_MAX_VIEWPORTS", test_result);
962         }
963
964         /*
965          *   * ViewportArrayv generates INVALID_VALUE when <first> + <count> is greater
966          *   than or equal to the value of MAX_VIEWPORTS;
967          */
968         {
969                 std::vector<GLfloat> data;
970                 data.resize(max_viewports * 4 /* x + y + w + h */);
971
972                 for (GLint i = 0; i < max_viewports; ++i)
973                 {
974                         data[i * 4 + 0] = 0.0f;
975                         data[i * 4 + 1] = 0.0f;
976                         data[i * 4 + 2] = 1.0f;
977                         data[i * 4 + 3] = 1.0f;
978                 }
979
980                 gl.viewportArrayv(0, max_viewports - 1, &data[0]);
981                 checkGLError(GL_NO_ERROR, "viewportArrayv, correct parameters", test_result);
982
983                 gl.viewportArrayv(max_viewports, 1, &data[0]);
984                 checkGLError(GL_INVALID_VALUE, "viewportArrayv, <first> == GL_MAX_VIEWPORTS", test_result);
985
986                 gl.viewportArrayv(1, max_viewports - 1, &data[0]);
987                 checkGLError(GL_NO_ERROR, "viewportArrayv, <first> + <count> == GL_MAX_VIEWPORTS", test_result);
988
989                 gl.viewportArrayv(1, max_viewports, &data[0]);
990                 checkGLError(GL_INVALID_VALUE, "viewportArrayv, <first> + <count> > GL_MAX_VIEWPORTS", test_result);
991         }
992
993         /*
994          *   * ViewportIndexedf and ViewportIndexedfv generate INVALID_VALUE when <index>
995          *   is greater than or equal to the value of MAX_VIEWPORTS;
996          */
997         {
998                 GLfloat data[4 /* x + y + w + h */];
999
1000                 data[0] = 0.0f;
1001                 data[1] = 0.0f;
1002                 data[2] = 1.0f;
1003                 data[3] = 1.0f;
1004
1005                 gl.viewportIndexedf(0 /* index */, 0.0f, 0.0f, 1.0f, 1.0f);
1006                 checkGLError(GL_NO_ERROR, "viewportIndexedf, <index> == 0", test_result);
1007
1008                 gl.viewportIndexedf(max_viewports - 1 /* index */, 0.0f, 0.0f, 1.0f, 1.0f);
1009                 checkGLError(GL_NO_ERROR, "viewportIndexedf, <index> == GL_MAX_VIEWPORTS - 1", test_result);
1010
1011                 gl.viewportIndexedf(max_viewports /* index */, 0.0f, 0.0f, 1.0f, 1.0f);
1012                 checkGLError(GL_INVALID_VALUE, "viewportIndexedf, <index> == GL_MAX_VIEWPORTS", test_result);
1013
1014                 gl.viewportIndexedf(max_viewports + 1 /* index */, 0.0f, 0.0f, 1.0f, 1.0f);
1015                 checkGLError(GL_INVALID_VALUE, "viewportIndexedf, <index> > GL_MAX_VIEWPORTS", test_result);
1016
1017                 gl.viewportIndexedfv(0 /* index */, data);
1018                 checkGLError(GL_NO_ERROR, "viewportIndexedfv, <index> == 0", test_result);
1019
1020                 gl.viewportIndexedfv(max_viewports - 1 /* index */, data);
1021                 checkGLError(GL_NO_ERROR, "viewportIndexedfv, <index> == GL_MAX_VIEWPORTS - 1", test_result);
1022
1023                 gl.viewportIndexedfv(max_viewports /* index */, data);
1024                 checkGLError(GL_INVALID_VALUE, "viewportIndexedfv, <index> == GL_MAX_VIEWPORTS", test_result);
1025
1026                 gl.viewportIndexedfv(max_viewports + 1 /* index */, data);
1027                 checkGLError(GL_INVALID_VALUE, "viewportIndexedfv, <index> > GL_MAX_VIEWPORTS", test_result);
1028         }
1029
1030         /*
1031          *   * ViewportArrayv, Viewport, ViewportIndexedf and ViewportIndexedfv generate
1032          *   INVALID_VALUE when <w> or <h> values are negative;
1033          */
1034         {
1035                 gl.viewport(0, 0, -1, 1);
1036                 checkGLError(GL_INVALID_VALUE, "viewport, negative width", test_result);
1037
1038                 gl.viewport(0, 0, 1, -1);
1039                 checkGLError(GL_INVALID_VALUE, "viewport, negative height", test_result);
1040
1041                 for (GLint i = 0; i < max_viewports; ++i)
1042                 {
1043                         std::vector<GLfloat> data;
1044                         data.resize(max_viewports * 4 /* x + y + w + h */);
1045
1046                         for (GLint j = 0; j < max_viewports; ++j)
1047                         {
1048                                 data[j * 4 + 0] = 0.0f;
1049                                 data[j * 4 + 1] = 0.0f;
1050                                 data[j * 4 + 2] = 1.0f;
1051                                 data[j * 4 + 3] = 1.0f;
1052                         }
1053
1054                         /* Set width to -1 */
1055                         data[i * 4 + 2] = -1.0f;
1056
1057                         gl.viewportArrayv(0, max_viewports, &data[0]);
1058                         checkGLError(GL_INVALID_VALUE, "viewportArrayv, negative width", test_result);
1059
1060                         gl.viewportIndexedf(i /* index */, 0.0f, 0.0f, -1.0f, 1.0f);
1061                         checkGLError(GL_INVALID_VALUE, "viewportIndexedf, negative width", test_result);
1062
1063                         gl.viewportIndexedfv(i /* index */, &data[i * 4]);
1064                         checkGLError(GL_INVALID_VALUE, "viewportIndexedfv, negative width", test_result);
1065
1066                         /* Set width to 1 and height to -1*/
1067                         data[i * 4 + 2] = 1.0f;
1068                         data[i * 4 + 3] = -1.0f;
1069
1070                         gl.viewportArrayv(0, max_viewports, &data[0]);
1071                         checkGLError(GL_INVALID_VALUE, "viewportArrayv, negative height", test_result);
1072
1073                         gl.viewportIndexedf(i /* index */, 0.0f, 0.0f, 1.0f, -1.0f);
1074                         checkGLError(GL_INVALID_VALUE, "viewportIndexedf, negative height", test_result);
1075
1076                         gl.viewportIndexedfv(i /* index */, &data[i * 4]);
1077                         checkGLError(GL_INVALID_VALUE, "viewportIndexedfv, negative height", test_result);
1078                 }
1079         }
1080
1081         /*
1082          *   * ScissorArrayv generates INVALID_VALUE when <first> + <count> is greater
1083          *   than or equal to the value of MAX_VIEWPORTS;
1084          */
1085         {
1086                 std::vector<GLint> data;
1087                 data.resize(max_viewports * 4 /* x + y + w + h */);
1088
1089                 for (GLint i = 0; i < max_viewports; ++i)
1090                 {
1091                         data[i * 4 + 0] = 0;
1092                         data[i * 4 + 1] = 0;
1093                         data[i * 4 + 2] = 1;
1094                         data[i * 4 + 3] = 1;
1095                 }
1096
1097                 gl.scissorArrayv(0, max_viewports - 1, &data[0]);
1098                 checkGLError(GL_NO_ERROR, "scissorArrayv, correct parameters", test_result);
1099
1100                 gl.scissorArrayv(max_viewports, 1, &data[0]);
1101                 checkGLError(GL_INVALID_VALUE, "scissorArrayv, <first> == GL_MAX_VIEWPORTS", test_result);
1102
1103                 gl.scissorArrayv(1, max_viewports - 1, &data[0]);
1104                 checkGLError(GL_NO_ERROR, "scissorArrayv, <first> + <count> == GL_MAX_VIEWPORTS", test_result);
1105
1106                 gl.scissorArrayv(1, max_viewports, &data[0]);
1107                 checkGLError(GL_INVALID_VALUE, "scissorArrayv, <first> + <count> > GL_MAX_VIEWPORTS", test_result);
1108         }
1109
1110         /*
1111          *   * ScissorIndexed and ScissorIndexedv generate INVALID_VALUE when <index> is
1112          *   greater than or equal to the value of MAX_VIEWPORTS;
1113          */
1114         {
1115                 GLint data[4 /* x + y + w + h */];
1116
1117                 data[0] = 0;
1118                 data[1] = 0;
1119                 data[2] = 1;
1120                 data[3] = 1;
1121
1122                 gl.scissorIndexed(0 /* index */, 0, 0, 1, 1);
1123                 checkGLError(GL_NO_ERROR, "scissorIndexed, <index> == 0", test_result);
1124
1125                 gl.scissorIndexed(max_viewports - 1 /* index */, 0, 0, 1, 1);
1126                 checkGLError(GL_NO_ERROR, "scissorIndexed, <index> == GL_MAX_VIEWPORTS - 1", test_result);
1127
1128                 gl.scissorIndexed(max_viewports /* index */, 0, 0, 1, 1);
1129                 checkGLError(GL_INVALID_VALUE, "scissorIndexed, <index> == GL_MAX_VIEWPORTS", test_result);
1130
1131                 gl.scissorIndexed(max_viewports + 1 /* index */, 0, 0, 1, 1);
1132                 checkGLError(GL_INVALID_VALUE, "scissorIndexed, <index> > GL_MAX_VIEWPORTS", test_result);
1133
1134                 gl.scissorIndexedv(0 /* index */, data);
1135                 checkGLError(GL_NO_ERROR, "scissorIndexedv, <index> == 0", test_result);
1136
1137                 gl.scissorIndexedv(max_viewports - 1 /* index */, data);
1138                 checkGLError(GL_NO_ERROR, "scissorIndexedv, <index> == GL_MAX_VIEWPORTS - 1", test_result);
1139
1140                 gl.scissorIndexedv(max_viewports /* index */, data);
1141                 checkGLError(GL_INVALID_VALUE, "scissorIndexedv, <index> == GL_MAX_VIEWPORTS", test_result);
1142
1143                 gl.scissorIndexedv(max_viewports + 1 /* index */, data);
1144                 checkGLError(GL_INVALID_VALUE, "scissorIndexedv, <index> > GL_MAX_VIEWPORTS", test_result);
1145         }
1146
1147         /*
1148          *   * ScissorArrayv, ScissorIndexed, ScissorIndexedv and Scissor generate
1149          *   INVALID_VALUE when <width> or <height> values are negative;
1150          */
1151         {
1152                 gl.scissor(0, 0, -1, 1);
1153                 checkGLError(GL_INVALID_VALUE, "scissor, negative width", test_result);
1154
1155                 gl.scissor(0, 0, 1, -1);
1156                 checkGLError(GL_INVALID_VALUE, "scissor, negative height", test_result);
1157
1158                 for (GLint i = 0; i < max_viewports; ++i)
1159                 {
1160                         std::vector<GLint> data;
1161                         data.resize(max_viewports * 4 /* x + y + w + h */);
1162
1163                         for (GLint j = 0; j < max_viewports; ++j)
1164                         {
1165                                 data[j * 4 + 0] = 0;
1166                                 data[j * 4 + 1] = 0;
1167                                 data[j * 4 + 2] = 1;
1168                                 data[j * 4 + 3] = 1;
1169                         }
1170
1171                         /* Set width to -1 */
1172                         data[i * 4 + 2] = -1;
1173
1174                         gl.scissorArrayv(0, max_viewports, &data[0]);
1175                         checkGLError(GL_INVALID_VALUE, "scissorArrayv, negative width", test_result);
1176
1177                         gl.scissorIndexed(i /* index */, 0, 0, -1, 1);
1178                         checkGLError(GL_INVALID_VALUE, "scissorIndexed, negative width", test_result);
1179
1180                         gl.scissorIndexedv(i /* index */, &data[i * 4]);
1181                         checkGLError(GL_INVALID_VALUE, "scissorIndexedv, negative width", test_result);
1182
1183                         /* Set width to 1 and height to -1*/
1184                         data[i * 4 + 2] = 1;
1185                         data[i * 4 + 3] = -1;
1186
1187                         gl.scissorArrayv(0, max_viewports, &data[0]);
1188                         checkGLError(GL_INVALID_VALUE, "scissorArrayv, negative height", test_result);
1189
1190                         gl.scissorIndexed(i /* index */, 0, 0, 1, -1);
1191                         checkGLError(GL_INVALID_VALUE, "scissorIndexed, negative height", test_result);
1192
1193                         gl.scissorIndexedv(i /* index */, &data[i * 4]);
1194                         checkGLError(GL_INVALID_VALUE, "scissorIndexedv, negative height", test_result);
1195                 }
1196         }
1197
1198         /*
1199          *   * Disablei, Enablei and IsEnabledi generate INVALID_VALUE when <cap> is
1200          *   SCISSOR_TEST and <index> is greater than or equal to the
1201          *   value of MAX_VIEWPORTS;
1202          */
1203         {
1204                 gl.disablei(GL_SCISSOR_TEST, max_viewports - 1);
1205                 checkGLError(GL_NO_ERROR, "disablei, <index> == GL_MAX_VIEWPORTS - 1", test_result);
1206
1207                 gl.disablei(GL_SCISSOR_TEST, max_viewports);
1208                 checkGLError(GL_INVALID_VALUE, "disablei, <index> == GL_MAX_VIEWPORTS", test_result);
1209
1210                 gl.enablei(GL_SCISSOR_TEST, max_viewports - 1);
1211                 checkGLError(GL_NO_ERROR, "enablei, <index> == GL_MAX_VIEWPORTS - 1", test_result);
1212
1213                 gl.enablei(GL_SCISSOR_TEST, max_viewports);
1214                 checkGLError(GL_INVALID_VALUE, "enablei, <index> == GL_MAX_VIEWPORTS", test_result);
1215
1216                 gl.isEnabledi(GL_SCISSOR_TEST, max_viewports - 1);
1217                 checkGLError(GL_NO_ERROR, "isEnabledi, <index> == GL_MAX_VIEWPORTS - 1", test_result);
1218
1219                 gl.isEnabledi(GL_SCISSOR_TEST, max_viewports);
1220                 checkGLError(GL_INVALID_VALUE, "isEnabledi, <index> == GL_MAX_VIEWPORTS", test_result);
1221         }
1222
1223         /*
1224          *   * GetIntegeri_v generates INVALID_VALUE when <target> is SCISSOR_BOX and
1225          *   <index> is greater than or equal to the value of MAX_VIEWPORTS;
1226          */
1227         {
1228                 GLint data[4];
1229
1230                 gl.getIntegeri_v(GL_SCISSOR_BOX, max_viewports - 1, data);
1231                 checkGLError(GL_NO_ERROR, "getIntegeri_v, <index> == GL_MAX_VIEWPORTS - 1", test_result);
1232
1233                 gl.getIntegeri_v(GL_SCISSOR_BOX, max_viewports, data);
1234                 checkGLError(GL_INVALID_VALUE, "getIntegeri_v, <index> == GL_MAX_VIEWPORTS", test_result);
1235         }
1236
1237         /*
1238          *   * GetFloati_v generates INVALID_VALUE when <target> is VIEWPORT and <index>
1239          *   is greater than or equal to the value of MAX_VIEWPORTS;
1240          */
1241         {
1242                 GLfloat data[4];
1243
1244                 gl.getFloati_v(GL_VIEWPORT, max_viewports - 1, data);
1245                 checkGLError(GL_NO_ERROR, "getFloati_v, <index> == GL_MAX_VIEWPORTS - 1", test_result);
1246
1247                 gl.getFloati_v(GL_VIEWPORT, max_viewports, data);
1248                 checkGLError(GL_INVALID_VALUE, "getFloati_v, <index> == GL_MAX_VIEWPORTS", test_result);
1249         }
1250
1251         /*
1252          *   * GetDoublei_v generates INVALID_VALUE when <target> is DEPTH_RANGE and
1253          *   <index> is greater than or equal to the value of MAX_VIEWPORTS;
1254          */
1255         {
1256                 GLdouble data[4];
1257
1258                 gl.getDoublei_v(GL_DEPTH_RANGE, max_viewports - 1, data);
1259                 checkGLError(GL_NO_ERROR, "getDoublei_v, <index> == GL_MAX_VIEWPORTS - 1", test_result);
1260
1261                 gl.getDoublei_v(GL_DEPTH_RANGE, max_viewports, data);
1262                 checkGLError(GL_INVALID_VALUE, "getDoublei_v, <index> == GL_MAX_VIEWPORTS", test_result);
1263         }
1264
1265         /* Set result */
1266         if (true == test_result)
1267         {
1268                 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
1269         }
1270         else
1271         {
1272                 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1273         }
1274
1275         /* Done */
1276         return tcu::TestNode::STOP;
1277 }
1278
1279 /** Check if glGetError returns expected error
1280  *
1281  * @param expected_error Expected error code
1282  * @param description    Description of test case
1283  * @param out_result     Set to false if the current error is not equal to expected one
1284  **/
1285 void APIErrors::checkGLError(GLenum expected_error, const GLchar* description, bool& out_result)
1286 {
1287         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1288
1289         GLenum error = gl.getError();
1290
1291         if (expected_error != error)
1292         {
1293                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Test case fail. Description: " << description
1294                                                                                         << " Invalid error: " << glu::getErrorStr(error)
1295                                                                                         << " expected: " << glu::getErrorStr(expected_error)
1296                                                                                         << tcu::TestLog::EndMessage;
1297
1298                 out_result = false;
1299         }
1300 }
1301
1302 /** Constructor
1303  *
1304  * @param context          Test context
1305  **/
1306 Queries::Queries(deqp::Context& context, const glcts::ExtParameters& extParams)
1307         : TestCaseBase(context, extParams, "queries", "Test verifies initial state of API")
1308 {
1309         /* Nothing to be done here */
1310 }
1311
1312 /** Execute test
1313  *
1314  * @return tcu::TestNode::CONTINUE after executing test case, tcu::TestNode::STOP otherwise
1315  **/
1316 tcu::TestNode::IterateResult Queries::iterate()
1317 {
1318         /* GL entry points */
1319         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1320
1321         /* Test result */
1322         bool test_result = true;
1323
1324         GLint   layer_provoking_vertex  = 0;
1325         GLint   max_viewports                     = 0;
1326         GLfloat max_renderbuffer_size    = 0.0f;
1327         GLfloat max_viewport_dims[2]      = { 0.0f, 0.0f };
1328         GLfloat viewport_bounds_range[2]  = { 0.0, 0.0f };
1329         GLint   viewport_provoking_vertex = 0;
1330         GLint   viewport_subpixel_bits  = -1;
1331
1332         gl.getIntegerv(GL_LAYER_PROVOKING_VERTEX, &layer_provoking_vertex);
1333         GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
1334
1335         gl.getIntegerv(GL_MAX_VIEWPORTS, &max_viewports);
1336         GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
1337
1338         gl.getFloatv(GL_MAX_RENDERBUFFER_SIZE, &max_renderbuffer_size);
1339         GLU_EXPECT_NO_ERROR(gl.getError(), "getFloatv");
1340
1341         gl.getFloatv(GL_MAX_VIEWPORT_DIMS, max_viewport_dims);
1342         GLU_EXPECT_NO_ERROR(gl.getError(), "GetFloatv");
1343
1344         gl.getFloatv(GL_VIEWPORT_BOUNDS_RANGE, viewport_bounds_range);
1345         GLU_EXPECT_NO_ERROR(gl.getError(), "GetFloatv");
1346
1347         gl.getIntegerv(GL_VIEWPORT_INDEX_PROVOKING_VERTEX, &viewport_provoking_vertex);
1348         GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
1349
1350         gl.getIntegerv(GL_VIEWPORT_SUBPIXEL_BITS, &viewport_subpixel_bits);
1351         GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
1352
1353         const GLint window_width  = m_context.getRenderContext().getRenderTarget().getWidth();
1354         const GLint window_height = m_context.getRenderContext().getRenderTarget().getHeight();
1355
1356         /*
1357          *   * Initial dimensions of VIEWPORT returned by GetFloati_v match dimensions of
1358          *   the window into which GL is rendering;
1359          */
1360         {
1361                 std::vector<GLfloat> data;
1362                 data.resize(max_viewports * 4 /* x + y + w+ h */);
1363
1364                 for (GLint i = 0; i < max_viewports; ++i)
1365                 {
1366                         gl.getFloati_v(GL_VIEWPORT, i, &data[i * 4]);
1367                         GLU_EXPECT_NO_ERROR(gl.getError(), "GetFloati_v");
1368                 }
1369
1370                 for (GLint i = 0; i < max_viewports; ++i)
1371                 {
1372                         GLint viewport_width  = (GLint)data[4 * i + 2];
1373                         GLint viewport_height = (GLint)data[4 * i + 3];
1374
1375                         if ((window_width != viewport_width) || (window_height != viewport_height))
1376                         {
1377                                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid initial viewport [" << i
1378                                                                                                         << "] dimennsions: " << viewport_width << " x " << viewport_height
1379                                                                                                         << " expected: " << window_width << " x " << window_height
1380                                                                                                         << tcu::TestLog::EndMessage;
1381
1382                                 test_result = false;
1383                                 break;
1384                         }
1385                 }
1386         }
1387
1388         /*
1389          *   * Initial values of DEPTH_RANGE returned by GetDoublei_v are [0, 1];
1390          */
1391         {
1392                 std::vector<GLdouble> data;
1393                 data.resize(max_viewports * 2 /* near + far */);
1394
1395                 for (GLint i = 0; i < max_viewports; ++i)
1396                 {
1397                         gl.getDoublei_v(GL_DEPTH_RANGE, i, &data[i * 2]);
1398                         GLU_EXPECT_NO_ERROR(gl.getError(), "getDoublei_v");
1399                 }
1400
1401                 for (GLint i = 0; i < max_viewports; ++i)
1402                 {
1403                         GLint near = (GLint)data[2 * i + 0];
1404                         GLint far  = (GLint)data[2 * i + 1];
1405
1406                         if ((0.0 != near) || (1.0 != far))
1407                         {
1408                                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid initial depth range [" << i
1409                                                                                                         << "]: " << near << " : " << far << " expected: 0.0 : 1.0"
1410                                                                                                         << tcu::TestLog::EndMessage;
1411
1412                                 test_result = false;
1413                                 break;
1414                         }
1415                 }
1416         }
1417
1418         /*
1419          *   * Initial state of SCISSOR_TEST returned by IsEnabledi is FALSE;
1420          */
1421         {
1422                 for (GLint i = 0; i < max_viewports; ++i)
1423                 {
1424                         if (GL_FALSE != gl.isEnabledi(GL_SCISSOR_TEST, i))
1425                         {
1426                                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Scissor test is enabled at " << i
1427                                                                                                         << ". Expected disabled." << tcu::TestLog::EndMessage;
1428
1429                                 test_result = false;
1430                                 break;
1431                         }
1432                 }
1433         }
1434
1435         /*
1436          *   * Initial dimensions of SCISSOR_BOX returned by GetIntegeri_v are either
1437          *   zeros or match dimensions of the window into which GL is rendering;
1438          */
1439         {
1440                 std::vector<GLint> data;
1441                 data.resize(max_viewports * 4 /* x + y + w+ h */);
1442
1443                 for (GLint i = 0; i < max_viewports; ++i)
1444                 {
1445                         gl.getIntegeri_v(GL_SCISSOR_BOX, i, &data[i * 4]);
1446                         GLU_EXPECT_NO_ERROR(gl.getError(), "getIntegeri_v");
1447                 }
1448
1449                 for (GLint i = 0; i < max_viewports; ++i)
1450                 {
1451                         GLint scissor_width  = data[4 * i + 2];
1452                         GLint scissor_height = data[4 * i + 3];
1453
1454                         if ((window_width != scissor_width) || (window_height != scissor_height))
1455                         {
1456                                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid initial scissor box [" << i
1457                                                                                                         << "] dimennsions: " << scissor_width << " x " << scissor_height
1458                                                                                                         << " expected: " << window_width << " x " << window_height
1459                                                                                                         << tcu::TestLog::EndMessage;
1460
1461                                 test_result = false;
1462                                 break;
1463                         }
1464                 }
1465         }
1466
1467         /*
1468          *   * Dimensions of MAX_VIEWPORT_DIMS returned by GetFloati_v are at least
1469          *   as big as supported dimensions of render buffers, see MAX_RENDERBUFFER_SIZE;
1470          */
1471         {
1472                 if ((max_viewport_dims[0] < max_renderbuffer_size) || (max_viewport_dims[1] < max_renderbuffer_size))
1473                 {
1474                         m_context.getTestContext().getLog()
1475                                 << tcu::TestLog::Message << "Invalid MAX_VIEWPORT_DIMS: " << max_viewport_dims[0] << " x "
1476                                 << max_viewport_dims[1] << " expected: " << max_renderbuffer_size << " x " << max_renderbuffer_size
1477                                 << tcu::TestLog::EndMessage;
1478
1479                         test_result = false;
1480                 }
1481         }
1482
1483         /*
1484          *   * Value of MAX_VIEWPORTS returned by GetIntegeri_v is at least 16;
1485          */
1486         {
1487                 if (16 > max_viewports)
1488                 {
1489                         m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid MAX_VIEWPORTS: " << max_viewports
1490                                                                                                 << " expected at least 16." << tcu::TestLog::EndMessage;
1491
1492                         test_result = false;
1493                 }
1494         }
1495
1496         /*
1497          *   * Value of VIEWPORT_SUBPIXEL_BITS returned by GetIntegeri_v is at least 0;
1498          */
1499         {
1500                 if (0 > viewport_subpixel_bits)
1501                 {
1502                         m_context.getTestContext().getLog() << tcu::TestLog::Message
1503                                                                                                 << "Invalid VIEWPORT_SUBPIXEL_BITS: " << viewport_subpixel_bits
1504                                                                                                 << " expected at least 0." << tcu::TestLog::EndMessage;
1505
1506                         test_result = false;
1507                 }
1508         }
1509
1510         /*
1511          *   * Values of VIEWPORT_BOUNDS_RANGE returned by GetFloatv are
1512          *   at least [-32768, 32767];
1513          */
1514         {
1515                 if ((-32768.0f < viewport_bounds_range[0]) || (32767.0f > viewport_bounds_range[1]))
1516                 {
1517                         m_context.getTestContext().getLog()
1518                                 << tcu::TestLog::Message << "Invalid VIEWPORT_BOUNDS_RANGE: " << viewport_bounds_range[0] << " : "
1519                                 << viewport_bounds_range[1] << " expected at least: -32768.0f : 32767.0f" << tcu::TestLog::EndMessage;
1520
1521                         test_result = false;
1522                 }
1523         }
1524
1525         /*
1526          *   * Values of LAYER_PROVOKING_VERTEX and VIEWPORT_INDEX_PROVOKING_VERTEX
1527          *   returned by GetIntegerv are located in the following set
1528          *   { FIRST_VERTEX_CONVENTION, LAST_VERTEX_CONVENTION, PROVOKING_VERTEX,
1529          *   UNDEFINED_VERTEX };
1530          */
1531         {
1532                 switch (layer_provoking_vertex)
1533                 {
1534                 case GL_FIRST_VERTEX_CONVENTION:
1535                 case GL_LAST_VERTEX_CONVENTION:
1536                 case GL_PROVOKING_VERTEX:
1537                 case GL_UNDEFINED_VERTEX:
1538                         break;
1539                 default:
1540                         m_context.getTestContext().getLog() << tcu::TestLog::Message
1541                                                                                                 << "Invalid LAYER_PROVOKING_VERTEX: " << layer_provoking_vertex
1542                                                                                                 << tcu::TestLog::EndMessage;
1543
1544                         test_result = false;
1545                 }
1546
1547                 switch (viewport_provoking_vertex)
1548                 {
1549                 case GL_FIRST_VERTEX_CONVENTION:
1550                 case GL_LAST_VERTEX_CONVENTION:
1551                 case GL_PROVOKING_VERTEX:
1552                 case GL_UNDEFINED_VERTEX:
1553                         break;
1554                 default:
1555                         m_context.getTestContext().getLog() << tcu::TestLog::Message
1556                                                                                                 << "Invalid LAYER_PROVOKING_VERTEX: " << layer_provoking_vertex
1557                                                                                                 << tcu::TestLog::EndMessage;
1558
1559                         test_result = false;
1560                 }
1561         }
1562
1563         /* Set result */
1564         if (true == test_result)
1565         {
1566                 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
1567         }
1568         else
1569         {
1570                 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1571         }
1572
1573         /* Done */
1574         return tcu::TestNode::STOP;
1575 }
1576
1577 /* Constants used by ViewportAPI */
1578 const GLuint ViewportAPI::m_n_elements = 4;
1579
1580 /** Constructor
1581  *
1582  * @param context          Test context
1583  **/
1584 ViewportAPI::ViewportAPI(deqp::Context& context, const glcts::ExtParameters& extParams)
1585         : TestCaseBase(context, extParams, "viewport_api", "Test verifies that \viewport api\" works as expected")
1586 {
1587         /* Nothing to be done here */
1588 }
1589
1590 /** Execute test
1591  *
1592  * @return tcu::TestNode::CONTINUE after executing test case, tcu::TestNode::STOP otherwise
1593  **/
1594 tcu::TestNode::IterateResult ViewportAPI::iterate()
1595 {
1596         /* GL entry points */
1597         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1598
1599         /* Test result */
1600         bool test_result = true;
1601
1602         GLint max_viewports = 0;
1603
1604         gl.getIntegerv(GL_MAX_VIEWPORTS, &max_viewports);
1605         GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
1606
1607         std::vector<GLfloat> scissor_box_data_a;
1608         std::vector<GLfloat> scissor_box_data_b;
1609
1610         scissor_box_data_a.resize(max_viewports * m_n_elements);
1611         scissor_box_data_b.resize(max_viewports * m_n_elements);
1612
1613         /*
1614          *   - get initial dimensions of VIEWPORT for all MAX_VIEWPORTS indices;
1615          *   - change location and dimensions of all indices at once with
1616          *   ViewportArrayv;
1617          *   - get VIEWPORT for all MAX_VIEWPORTS indices and verify results;
1618          */
1619         getViewports(max_viewports, scissor_box_data_a);
1620
1621         for (GLint i = 0; i < max_viewports; ++i)
1622         {
1623                 scissor_box_data_a[i * m_n_elements + 0] += 0.125f;
1624                 scissor_box_data_a[i * m_n_elements + 1] += 0.125f;
1625                 scissor_box_data_a[i * m_n_elements + 2] -= 0.125f;
1626                 scissor_box_data_a[i * m_n_elements + 3] -= 0.125f;
1627         }
1628
1629         gl.viewportArrayv(0, max_viewports, &scissor_box_data_a[0]);
1630         GLU_EXPECT_NO_ERROR(gl.getError(), "viewportArrayv");
1631
1632         getViewports(max_viewports, scissor_box_data_b);
1633         compareViewports(scissor_box_data_a, scissor_box_data_b, "viewportArrayv", test_result);
1634
1635         /*
1636          *   - for each index:
1637          *     * modify with ViewportIndexedf,
1638          *     * get VIEWPORT for all MAX_VIEWPORTS indices and verify results;
1639          */
1640         for (GLint i = 0; i < max_viewports; ++i)
1641         {
1642                 scissor_box_data_b[i * m_n_elements + 0] = 0.25f;
1643                 scissor_box_data_b[i * m_n_elements + 1] = 0.25f;
1644                 scissor_box_data_b[i * m_n_elements + 2] = 0.75f;
1645                 scissor_box_data_b[i * m_n_elements + 3] = 0.75f;
1646
1647                 gl.viewportIndexedf(i, 0.25f, 0.25f, 0.75f, 0.75f);
1648                 GLU_EXPECT_NO_ERROR(gl.getError(), "viewportIndexedf");
1649
1650                 getViewports(max_viewports, scissor_box_data_a);
1651                 compareViewports(scissor_box_data_a, scissor_box_data_b, "viewportIndexedf", test_result);
1652         }
1653
1654         /*
1655          *   - for each index:
1656          *     * modify with ViewportIndexedfv,
1657          *     * get VIEWPORT for all MAX_VIEWPORTS indices and verify results;
1658          */
1659         for (GLint i = 0; i < max_viewports; ++i)
1660         {
1661                 scissor_box_data_a[i * m_n_elements + 0] = 0.375f;
1662                 scissor_box_data_a[i * m_n_elements + 1] = 0.375f;
1663                 scissor_box_data_a[i * m_n_elements + 2] = 0.625f;
1664                 scissor_box_data_a[i * m_n_elements + 3] = 0.625f;
1665
1666                 gl.viewportIndexedfv(i, &scissor_box_data_a[i * m_n_elements]);
1667                 GLU_EXPECT_NO_ERROR(gl.getError(), "viewportIndexedfv");
1668
1669                 getViewports(max_viewports, scissor_box_data_b);
1670                 compareViewports(scissor_box_data_a, scissor_box_data_b, "viewportIndexedfv", test_result);
1671         }
1672
1673         /*
1674          *   - for each index:
1675          *     * modify all indices before and after current one with ViewportArrayv,
1676          *     * get VIEWPORT for all MAX_VIEWPORTS indices and verify results;
1677          */
1678         for (GLint i = 0; i < max_viewports; ++i)
1679         {
1680                 const GLfloat value = (0 == i % 2) ? 1.0f : 0.25f;
1681
1682                 for (GLint j = 0; j < i; ++j)
1683                 {
1684                         scissor_box_data_b[j * m_n_elements + 0] = value;
1685                         scissor_box_data_b[j * m_n_elements + 1] = value;
1686                         scissor_box_data_b[j * m_n_elements + 2] = value;
1687                         scissor_box_data_b[j * m_n_elements + 3] = value;
1688                 }
1689
1690                 for (GLint j = i + 1; j < max_viewports; ++j)
1691                 {
1692                         scissor_box_data_b[j * m_n_elements + 0] = value;
1693                         scissor_box_data_b[j * m_n_elements + 1] = value;
1694                         scissor_box_data_b[j * m_n_elements + 2] = value;
1695                         scissor_box_data_b[j * m_n_elements + 3] = value;
1696                 }
1697
1698                 gl.viewportArrayv(0, max_viewports, &scissor_box_data_b[0]);
1699                 GLU_EXPECT_NO_ERROR(gl.getError(), "viewportArrayv");
1700
1701                 getViewports(max_viewports, scissor_box_data_a);
1702                 compareViewports(scissor_box_data_a, scissor_box_data_b, "viewportArrayv", test_result);
1703         }
1704
1705         /*
1706          *   - change location and dimensions of all indices at once with Viewport;
1707          *   - get VIEWPORT for all MAX_VIEWPORTS indices and verify results;
1708          */
1709         for (GLint i = 0; i < max_viewports; ++i)
1710         {
1711                 scissor_box_data_a[i * m_n_elements + 0] = 0.0f;
1712                 scissor_box_data_a[i * m_n_elements + 1] = 0.0f;
1713                 scissor_box_data_a[i * m_n_elements + 2] = 1.0f;
1714                 scissor_box_data_a[i * m_n_elements + 3] = 1.0f;
1715         }
1716
1717         gl.viewport(0, 0, 1, 1);
1718         GLU_EXPECT_NO_ERROR(gl.getError(), "viewport");
1719
1720         getViewports(max_viewports, scissor_box_data_b);
1721         compareViewports(scissor_box_data_a, scissor_box_data_b, "viewport", test_result);
1722
1723         /* Set result */
1724         if (true == test_result)
1725         {
1726                 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
1727         }
1728         else
1729         {
1730                 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1731         }
1732
1733         /* Done */
1734         return tcu::TestNode::STOP;
1735 }
1736
1737 /** Compare two sets of viewport data (simple vector comparison)
1738  *
1739  * @param left        Left set
1740  * @param right       Right set
1741  * @param description Test case description
1742  * @param out_result  Set to false if sets are different, not modified otherwise
1743  **/
1744 void ViewportAPI::compareViewports(std::vector<GLfloat>& left, std::vector<GLfloat>& right, const GLchar* description,
1745                                                                    bool& out_result)
1746 {
1747         for (size_t i = 0; i < left.size(); ++i)
1748         {
1749                 if (left[i] != right[i])
1750                 {
1751                         m_context.getTestContext().getLog() << tcu::TestLog::Message << "Test case: " << description
1752                                                                                                 << " Invalid values [" << i << "] " << left[i] << " " << right[i]
1753                                                                                                 << tcu::TestLog::EndMessage;
1754
1755                         out_result = false;
1756                 }
1757         }
1758 }
1759
1760 /** Get position of all viewports
1761  *
1762  * @param max_viewports Number of viewports to capture, MAX_VIEWPORTS
1763  * @param data          Memory buffer prepared for captured data
1764  **/
1765 void ViewportAPI::getViewports(GLint max_viewports, std::vector<GLfloat>& out_data)
1766 {
1767         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1768
1769         for (GLint i = 0; i < max_viewports; ++i)
1770         {
1771                 gl.getFloati_v(GL_VIEWPORT, i, &out_data[i * 4]);
1772                 GLU_EXPECT_NO_ERROR(gl.getError(), "getFloati_v");
1773         }
1774 }
1775
1776 /* Constants used by ScissorAPI */
1777 const GLuint ScissorAPI::m_n_elements = 4;
1778
1779 /** Constructor
1780  *
1781  * @param context          Test context
1782  **/
1783 ScissorAPI::ScissorAPI(deqp::Context& context, const glcts::ExtParameters& extParams)
1784         : TestCaseBase(context, extParams, "scissor_api", "Test verifies that \"scissor api\" works as expected")
1785 {
1786         /* Nothing to be done here */
1787 }
1788
1789 /** Execute test
1790  *
1791  * @return tcu::TestNode::CONTINUE after executing test case, tcu::TestNode::STOP otherwise
1792  **/
1793 tcu::TestNode::IterateResult ScissorAPI::iterate()
1794 {
1795         /* GL entry points */
1796         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1797
1798         /* Test result */
1799         bool test_result = true;
1800
1801         GLint max_viewports = 0;
1802
1803         gl.getIntegerv(GL_MAX_VIEWPORTS, &max_viewports);
1804         GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
1805
1806         std::vector<GLint> scissor_box_data_a;
1807         std::vector<GLint> scissor_box_data_b;
1808
1809         scissor_box_data_a.resize(max_viewports * m_n_elements);
1810         scissor_box_data_b.resize(max_viewports * m_n_elements);
1811
1812         /*
1813          *   - get initial dimensions of SCISSOR_BOX for all MAX_VIEWPORTS indices;
1814          *   - change location and dimensions of all indices at once with
1815          *   ScissorArrayv;
1816          *   - get SCISSOR_BOX for all MAX_VIEWPORTS indices and verify results;
1817          */
1818         getScissorBoxes(max_viewports, scissor_box_data_a);
1819
1820         for (GLint i = 0; i < max_viewports; ++i)
1821         {
1822                 scissor_box_data_a[i * m_n_elements + 0] += 1;
1823                 scissor_box_data_a[i * m_n_elements + 1] += 1;
1824                 scissor_box_data_a[i * m_n_elements + 2] -= 1;
1825                 scissor_box_data_a[i * m_n_elements + 3] -= 1;
1826         }
1827
1828         gl.scissorArrayv(0, max_viewports, &scissor_box_data_a[0]);
1829         GLU_EXPECT_NO_ERROR(gl.getError(), "scissorArrayv");
1830
1831         getScissorBoxes(max_viewports, scissor_box_data_b);
1832         compareScissorBoxes(scissor_box_data_a, scissor_box_data_b, "scissorArrayv", test_result);
1833
1834         /*
1835          *   - for each index:
1836          *     * modify with ScissorIndexed,
1837          *     * get SCISSOR_BOX for all MAX_VIEWPORTS indices and verify results;
1838          */
1839         for (GLint i = 0; i < max_viewports; ++i)
1840         {
1841                 scissor_box_data_b[i * m_n_elements + 0] = 4;
1842                 scissor_box_data_b[i * m_n_elements + 1] = 4;
1843                 scissor_box_data_b[i * m_n_elements + 2] = 8;
1844                 scissor_box_data_b[i * m_n_elements + 3] = 8;
1845
1846                 gl.scissorIndexed(i, 4, 4, 8, 8);
1847                 GLU_EXPECT_NO_ERROR(gl.getError(), "scissorIndexed");
1848
1849                 getScissorBoxes(max_viewports, scissor_box_data_a);
1850                 compareScissorBoxes(scissor_box_data_a, scissor_box_data_b, "scissorIndexed", test_result);
1851         }
1852
1853         /*
1854          *   - for each index:
1855          *     * modify with ScissorIndexedv,
1856          *     * get SCISSOR_BOX for all MAX_VIEWPORTS indices and verify results;
1857          */
1858         for (GLint i = 0; i < max_viewports; ++i)
1859         {
1860                 scissor_box_data_a[i * m_n_elements + 0] = 8;
1861                 scissor_box_data_a[i * m_n_elements + 1] = 8;
1862                 scissor_box_data_a[i * m_n_elements + 2] = 12;
1863                 scissor_box_data_a[i * m_n_elements + 3] = 12;
1864
1865                 gl.scissorIndexedv(i, &scissor_box_data_a[i * m_n_elements]);
1866                 GLU_EXPECT_NO_ERROR(gl.getError(), "scissorIndexedv");
1867
1868                 getScissorBoxes(max_viewports, scissor_box_data_b);
1869                 compareScissorBoxes(scissor_box_data_a, scissor_box_data_b, "scissorIndexedv", test_result);
1870         }
1871
1872         /*
1873          *   - for each index:
1874          *     * modify all indices before and after current one with ScissorArrayv,
1875          *     * get SCISSOR_BOX for all MAX_VIEWPORTS indices and verify results;
1876          */
1877         for (GLint i = 0; i < max_viewports; ++i)
1878         {
1879                 const GLint value = (0 == i % 2) ? 1 : 4;
1880
1881                 for (GLint j = 0; j < i; ++j)
1882                 {
1883                         scissor_box_data_b[j * m_n_elements + 0] = value;
1884                         scissor_box_data_b[j * m_n_elements + 1] = value;
1885                         scissor_box_data_b[j * m_n_elements + 2] = value;
1886                         scissor_box_data_b[j * m_n_elements + 3] = value;
1887                 }
1888
1889                 for (GLint j = i + 1; j < max_viewports; ++j)
1890                 {
1891                         scissor_box_data_b[j * m_n_elements + 0] = value;
1892                         scissor_box_data_b[j * m_n_elements + 1] = value;
1893                         scissor_box_data_b[j * m_n_elements + 2] = value;
1894                         scissor_box_data_b[j * m_n_elements + 3] = value;
1895                 }
1896
1897                 gl.scissorArrayv(0, max_viewports, &scissor_box_data_b[0]);
1898                 GLU_EXPECT_NO_ERROR(gl.getError(), "scissorArrayv");
1899
1900                 getScissorBoxes(max_viewports, scissor_box_data_a);
1901                 compareScissorBoxes(scissor_box_data_a, scissor_box_data_b, "scissorArrayv", test_result);
1902         }
1903
1904         /*
1905          *   - change location and dimensions of all indices at once with Scissor;
1906          *   - get SCISSOR_BOX for all MAX_VIEWPORTS indices and verify results;
1907          */
1908         for (GLint i = 0; i < max_viewports; ++i)
1909         {
1910                 scissor_box_data_a[i * m_n_elements + 0] = 0;
1911                 scissor_box_data_a[i * m_n_elements + 1] = 0;
1912                 scissor_box_data_a[i * m_n_elements + 2] = 1;
1913                 scissor_box_data_a[i * m_n_elements + 3] = 1;
1914         }
1915
1916         gl.scissor(0, 0, 1, 1);
1917         GLU_EXPECT_NO_ERROR(gl.getError(), "scissor");
1918
1919         getScissorBoxes(max_viewports, scissor_box_data_b);
1920         compareScissorBoxes(scissor_box_data_a, scissor_box_data_b, "scissor", test_result);
1921
1922         /* Set result */
1923         if (true == test_result)
1924         {
1925                 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
1926         }
1927         else
1928         {
1929                 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1930         }
1931
1932         /* Done */
1933         return tcu::TestNode::STOP;
1934 }
1935
1936 /** Compare two sets of scissor box data (simple vector comparison)
1937  *
1938  * @param left        Left set
1939  * @param right       Right set
1940  * @param description Test case description
1941  * @param out_result  Set to false if sets are different, not modified otherwise
1942  **/
1943 void ScissorAPI::compareScissorBoxes(std::vector<GLint>& left, std::vector<GLint>& right, const GLchar* description,
1944                                                                          bool& out_result)
1945 {
1946         for (size_t i = 0; i < left.size(); ++i)
1947         {
1948                 if (left[i] != right[i])
1949                 {
1950                         m_context.getTestContext().getLog() << tcu::TestLog::Message << "Test case: " << description
1951                                                                                                 << " Invalid values [" << i << "] " << left[i] << " " << right[i]
1952                                                                                                 << tcu::TestLog::EndMessage;
1953
1954                         out_result = false;
1955                 }
1956         }
1957 }
1958
1959 /** Get position of all scissor boxes
1960  *
1961  * @param max_viewports Number of scissor boxes to capture, MAX_VIEWPORTS
1962  * @param data          Memory buffer prepared for captured data
1963  **/
1964 void ScissorAPI::getScissorBoxes(GLint max_viewports, std::vector<GLint>& out_data)
1965 {
1966         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1967
1968         for (GLint i = 0; i < max_viewports; ++i)
1969         {
1970                 gl.getIntegeri_v(GL_SCISSOR_BOX, i, &out_data[i * 4]);
1971                 GLU_EXPECT_NO_ERROR(gl.getError(), "getIntegeri_v");
1972         }
1973 }
1974
1975 /* Constants used by DepthRangeAPI */
1976 const GLuint DepthRangeAPI::m_n_elements = 2 /* near + far */;
1977
1978 /** Constructor
1979  *
1980  * @param context          Test context
1981  **/
1982 DepthRangeAPI::DepthRangeAPI(deqp::Context& context, const glcts::ExtParameters& extParams)
1983         : TestCaseBase(context, extParams, "depth_range_api", "Test verifies that \"depth range api\" works as expected")
1984 {
1985         /* Nothing to be done here */
1986 }
1987
1988 /** Execute test
1989  *
1990  * @return tcu::TestNode::CONTINUE after executing test case, tcu::TestNode::STOP otherwise
1991  **/
1992 tcu::TestNode::IterateResult DepthRangeAPI::iterate()
1993 {
1994         /* GL entry points */
1995         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1996
1997         /* Test result */
1998         bool test_result = true;
1999
2000         GLint max_viewports = 0;
2001
2002         gl.getIntegerv(GL_MAX_VIEWPORTS, &max_viewports);
2003         GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
2004
2005         std::vector<GLdouble> depth_range_data_a;
2006         std::vector<GLdouble> depth_range_data_b;
2007
2008         depth_range_data_a.resize(max_viewports * m_n_elements);
2009         depth_range_data_b.resize(max_viewports * m_n_elements);
2010
2011         /*
2012          *   - get initial values of DEPTH_RANGE for all MAX_VIEWPORTS indices;
2013          *   - change values of all indices at once with DepthRangeArrayv;
2014          *   - get DEPTH_RANGE for all MAX_VIEWPORTS indices and verify results;
2015          */
2016         getDepthRanges(max_viewports, depth_range_data_a);
2017
2018         for (GLint i = 0; i < max_viewports; ++i)
2019         {
2020                 depth_range_data_a[i * m_n_elements + 0] += 0.125;
2021                 depth_range_data_a[i * m_n_elements + 1] -= 0.125;
2022         }
2023
2024         gl.depthRangeArrayv(0, max_viewports, &depth_range_data_a[0]);
2025         GLU_EXPECT_NO_ERROR(gl.getError(), "depthRangeArrayv");
2026
2027         getDepthRanges(max_viewports, depth_range_data_b);
2028         compareDepthRanges(depth_range_data_a, depth_range_data_b, "depthRangeArrayv", test_result);
2029
2030         /*
2031          *   - for each index:
2032          *     * modify with DepthRangeIndexed,
2033          *     * get DEPTH_RANGE for all MAX_VIEWPORTS indices and verify results;
2034          */
2035         for (GLint i = 0; i < max_viewports; ++i)
2036         {
2037                 depth_range_data_b[i * m_n_elements + 0] = 0.25;
2038                 depth_range_data_b[i * m_n_elements + 1] = 0.75;
2039
2040                 gl.depthRangeIndexed(i, 0.25f, 0.75f);
2041                 GLU_EXPECT_NO_ERROR(gl.getError(), "depthRangeIndexed");
2042
2043                 getDepthRanges(max_viewports, depth_range_data_a);
2044                 compareDepthRanges(depth_range_data_a, depth_range_data_b, "depthRangeIndexed", test_result);
2045         }
2046
2047         /*
2048          *   - for each index:
2049          *     * modify all indices before and after current one with DepthRangeArrayv,
2050          *     * get DEPTH_RANGE for all MAX_VIEWPORTS indices and verify results;
2051          */
2052         for (GLint i = 0; i < max_viewports; ++i)
2053         {
2054                 const GLdouble value = (0 == i % 2) ? 1.0 : 0.25;
2055
2056                 for (GLint j = 0; j < i; ++j)
2057                 {
2058                         depth_range_data_b[j * m_n_elements + 0] = value;
2059                         depth_range_data_b[j * m_n_elements + 1] = value;
2060                 }
2061
2062                 for (GLint j = i + 1; j < max_viewports; ++j)
2063                 {
2064                         depth_range_data_b[j * m_n_elements + 0] = value;
2065                         depth_range_data_b[j * m_n_elements + 1] = value;
2066                 }
2067
2068                 gl.depthRangeArrayv(0, max_viewports, &depth_range_data_b[0]);
2069                 GLU_EXPECT_NO_ERROR(gl.getError(), "depthRangeArrayv");
2070
2071                 getDepthRanges(max_viewports, depth_range_data_a);
2072                 compareDepthRanges(depth_range_data_a, depth_range_data_b, "depthRangeArrayv", test_result);
2073         }
2074
2075         /*
2076          *   - change values of all indices at once with DepthRange;
2077          *   - get DEPTH_RANGE for all MAX_VIEWPORTS indices and verify results;
2078          */
2079         for (GLint i = 0; i < max_viewports; ++i)
2080         {
2081                 depth_range_data_a[i * m_n_elements + 0] = 0.0f;
2082                 depth_range_data_a[i * m_n_elements + 1] = 1.0f;
2083         }
2084
2085         gl.depthRange(0.0, 1.0);
2086         GLU_EXPECT_NO_ERROR(gl.getError(), "depthRange");
2087
2088         getDepthRanges(max_viewports, depth_range_data_b);
2089         compareDepthRanges(depth_range_data_a, depth_range_data_b, "depthRange", test_result);
2090
2091         /* Set result */
2092         if (true == test_result)
2093         {
2094                 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
2095         }
2096         else
2097         {
2098                 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2099         }
2100
2101         /* Done */
2102         return tcu::TestNode::STOP;
2103 }
2104
2105 /** Compare two sets of depth range data (simple vector comparison)
2106  *
2107  * @param left        Left set
2108  * @param right       Right set
2109  * @param description Test case description
2110  * @param out_result  Set to false if sets are different, not modified otherwise
2111  **/
2112 void DepthRangeAPI::compareDepthRanges(std::vector<GLdouble>& left, std::vector<GLdouble>& right,
2113                                                                            const GLchar* description, bool& out_result)
2114 {
2115         for (size_t i = 0; i < left.size(); ++i)
2116         {
2117                 if (left[i] != right[i])
2118                 {
2119                         m_context.getTestContext().getLog() << tcu::TestLog::Message << "Test case: " << description
2120                                                                                                 << " Invalid values [" << i << "] " << left[i] << " " << right[i]
2121                                                                                                 << tcu::TestLog::EndMessage;
2122
2123                         out_result = false;
2124                 }
2125         }
2126 }
2127
2128 /** Get all depth ranges
2129  *
2130  * @param max_viewports Number of viewports to capture, MAX_VIEWPORTS
2131  * @param data          Memory buffer prepared for captured data
2132  **/
2133 void DepthRangeAPI::getDepthRanges(GLint max_viewports, std::vector<GLdouble>& out_data)
2134 {
2135         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2136
2137         for (GLint i = 0; i < max_viewports; ++i)
2138         {
2139                 gl.getDoublei_v(GL_DEPTH_RANGE, i, &out_data[i * m_n_elements]);
2140                 GLU_EXPECT_NO_ERROR(gl.getError(), "getDoublei_v");
2141         }
2142 }
2143
2144 /** Constructor
2145  *
2146  * @param context          Test context
2147  **/
2148 ScissorTestStateAPI::ScissorTestStateAPI(deqp::Context& context, const glcts::ExtParameters& extParams)
2149         : TestCaseBase(context, extParams, "scissor_test_state_api",
2150                                    "Test verifies that \"enable/disable api\" works as expected for scissor test")
2151 {
2152         /* Nothing to be done here */
2153 }
2154
2155 /** Execute test
2156  *
2157  * @return tcu::TestNode::CONTINUE after executing test case, tcu::TestNode::STOP otherwise
2158  **/
2159 tcu::TestNode::IterateResult ScissorTestStateAPI::iterate()
2160 {
2161         /* GL entry points */
2162         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2163
2164         /* Test result */
2165         bool test_result = true;
2166
2167         GLint max_viewports = 0;
2168
2169         gl.getIntegerv(GL_MAX_VIEWPORTS, &max_viewports);
2170         GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
2171
2172         std::vector<GLboolean> scissor_test_states_a;
2173         std::vector<GLboolean> scissor_test_states_b;
2174
2175         scissor_test_states_a.resize(max_viewports);
2176         scissor_test_states_b.resize(max_viewports);
2177
2178         /*
2179          *   - get initial state of SCISSOR_TEST for all MAX_VIEWPORTS indices;
2180          *   - for each index:
2181          *     * toggle SCISSOR_TEST,
2182          *     * get state of SCISSOR_TEST for all MAX_VIEWPORTS indices and verify;
2183          *   - for each index:
2184          *     * toggle SCISSOR_TEST,
2185          *     * get state of SCISSOR_TEST for all MAX_VIEWPORTS indices and verify;
2186          */
2187         getScissorTestStates(max_viewports, scissor_test_states_a);
2188
2189         for (GLint i = 0; i < max_viewports; ++i)
2190         {
2191                 if (GL_FALSE == scissor_test_states_a[i])
2192                 {
2193                         gl.enablei(GL_SCISSOR_TEST, i);
2194                         GLU_EXPECT_NO_ERROR(gl.getError(), "Enablei");
2195
2196                         scissor_test_states_a[i] = GL_TRUE;
2197                 }
2198                 else
2199                 {
2200                         gl.disablei(GL_SCISSOR_TEST, i);
2201                         GLU_EXPECT_NO_ERROR(gl.getError(), "Disablei");
2202
2203                         scissor_test_states_a[i] = GL_FALSE;
2204                 }
2205
2206                 getScissorTestStates(max_viewports, scissor_test_states_b);
2207                 compareScissorTestStates(scissor_test_states_a, scissor_test_states_b, "1st toggle", test_result);
2208         }
2209
2210         for (GLint i = 0; i < max_viewports; ++i)
2211         {
2212                 if (GL_FALSE == scissor_test_states_a[i])
2213                 {
2214                         gl.enablei(GL_SCISSOR_TEST, i);
2215                         GLU_EXPECT_NO_ERROR(gl.getError(), "Enablei");
2216
2217                         scissor_test_states_a[i] = GL_TRUE;
2218                 }
2219                 else
2220                 {
2221                         gl.disablei(GL_SCISSOR_TEST, i);
2222                         GLU_EXPECT_NO_ERROR(gl.getError(), "Disablei");
2223
2224                         scissor_test_states_a[i] = GL_FALSE;
2225                 }
2226
2227                 getScissorTestStates(max_viewports, scissor_test_states_b);
2228                 compareScissorTestStates(scissor_test_states_a, scissor_test_states_b, "2nd toggle", test_result);
2229         }
2230
2231         /*
2232          *   - enable SCISSOR_TEST for all indices at once with Enable;
2233          *   - get state of SCISSOR_TEST for all MAX_VIEWPORTS indices and verify;
2234          */
2235         for (GLint i = 0; i < max_viewports; ++i)
2236         {
2237                 scissor_test_states_a[i] = GL_TRUE;
2238         }
2239
2240         gl.enable(GL_SCISSOR_TEST);
2241         GLU_EXPECT_NO_ERROR(gl.getError(), "Enable");
2242
2243         getScissorTestStates(max_viewports, scissor_test_states_b);
2244         compareScissorTestStates(scissor_test_states_a, scissor_test_states_b, "1st enable all", test_result);
2245
2246         /*
2247          *   - disable SCISSOR_TEST for all indices at once with Disable;
2248          *   - get state of SCISSOR_TEST for all MAX_VIEWPORTS indices and verify;
2249          */
2250         for (GLint i = 0; i < max_viewports; ++i)
2251         {
2252                 scissor_test_states_a[i] = GL_FALSE;
2253         }
2254
2255         gl.disable(GL_SCISSOR_TEST);
2256         GLU_EXPECT_NO_ERROR(gl.getError(), "Disable");
2257
2258         getScissorTestStates(max_viewports, scissor_test_states_b);
2259         compareScissorTestStates(scissor_test_states_a, scissor_test_states_b, "Disable all", test_result);
2260
2261         /*
2262          *   - enable SCISSOR_TEST for all indices at once with Enable;
2263          *   - get state of SCISSOR_TEST for all MAX_VIEWPORTS indices and verify;
2264          */
2265         for (GLint i = 0; i < max_viewports; ++i)
2266         {
2267                 scissor_test_states_a[i] = GL_TRUE;
2268         }
2269
2270         gl.enable(GL_SCISSOR_TEST);
2271         GLU_EXPECT_NO_ERROR(gl.getError(), "Enable");
2272
2273         getScissorTestStates(max_viewports, scissor_test_states_b);
2274         compareScissorTestStates(scissor_test_states_a, scissor_test_states_b, "2nd enable all", test_result);
2275
2276         /* Set result */
2277         if (true == test_result)
2278         {
2279                 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
2280         }
2281         else
2282         {
2283                 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2284         }
2285
2286         /* Done */
2287         return tcu::TestNode::STOP;
2288 }
2289
2290 /** Compare two sets of depth range data (simple vector comparison)
2291  *
2292  * @param left        Left set
2293  * @param right       Right set
2294  * @param description Test case description
2295  * @param out_result  Set to false if sets are different, not modified otherwise
2296  **/
2297 void ScissorTestStateAPI::compareScissorTestStates(std::vector<GLboolean>& left, std::vector<GLboolean>& right,
2298                                                                                                    const GLchar* description, bool& out_result)
2299 {
2300         for (size_t i = 0; i < left.size(); ++i)
2301         {
2302                 if (left[i] != right[i])
2303                 {
2304                         m_context.getTestContext().getLog() << tcu::TestLog::Message << "Test case: " << description
2305                                                                                                 << " Invalid values [" << i << "] " << left[i] << " " << right[i]
2306                                                                                                 << tcu::TestLog::EndMessage;
2307
2308                         out_result = false;
2309                 }
2310         }
2311 }
2312
2313 /** Get all depth ranges
2314  *
2315  * @param max_viewports Number of viewports to capture, MAX_VIEWPORTS
2316  * @param data          Memory buffer prepared for captured data
2317  **/
2318 void ScissorTestStateAPI::getScissorTestStates(GLint max_viewports, std::vector<GLboolean>& out_data)
2319 {
2320         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2321
2322         for (GLint i = 0; i < max_viewports; ++i)
2323         {
2324                 out_data[i] = gl.isEnabledi(GL_SCISSOR_TEST, i);
2325                 GLU_EXPECT_NO_ERROR(gl.getError(), "isEnabledi");
2326         }
2327 }
2328
2329 /* Constants used by DrawTestBase */
2330 const GLuint DrawTestBase::m_depth                = 16;
2331 const GLuint DrawTestBase::m_height               = 128;
2332 const GLuint DrawTestBase::m_width                = 128;
2333 const GLuint DrawTestBase::m_r32f_height  = 2;
2334 const GLuint DrawTestBase::m_r32f_width   = 16;
2335 const GLuint DrawTestBase::m_r32ix4_depth = 4;
2336
2337 /** Constructor
2338  *
2339  * @param context          Test context
2340  * @param test_name        Test name
2341  * @param test_description Test description
2342  **/
2343 DrawTestBase::DrawTestBase(deqp::Context& context, const glcts::ExtParameters& extParams, const GLchar* test_name,
2344                                                    const GLchar* test_description)
2345         : TestCaseBase(context, extParams, test_name, test_description)
2346 {
2347         /* Nothing to be done here */
2348 }
2349
2350 /** Execute test
2351  *
2352  * @return tcu::TestNode::CONTINUE after executing test case, tcu::TestNode::STOP otherwise
2353  **/
2354 tcu::TestNode::IterateResult DrawTestBase::iterate()
2355 {
2356         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2357
2358         /* Test result */
2359         bool test_result = true;
2360
2361         /* Get type of test */
2362         const TEST_TYPE test_type = getTestType();
2363
2364         GLuint n_draw_calls = getDrawCallsNumber();
2365         GLuint n_iterations = 0;
2366         switch (test_type)
2367         {
2368         case VIEWPORT:
2369         case SCISSOR:
2370                 n_iterations = 3;
2371                 break;
2372         case DEPTHRANGE:
2373         case PROVOKING:
2374                 n_iterations = 2;
2375                 break;
2376         default:
2377                 TCU_FAIL("Invalid enum");
2378         }
2379
2380         /* Get shader sources */
2381         const std::string& fragment = getFragmentShader();
2382         const std::string& geometry = getGeometryShader();
2383         const std::string& vertex   = getVertexShader();
2384
2385         /* Prepare program */
2386         Utils::program program(m_context);
2387
2388         try
2389         {
2390                 program.build(0 /* compute */, fragment.c_str(), geometry.c_str(), 0 /* tess ctrl */, 0 /* tess eval */,
2391                                           vertex.c_str(), 0 /* varying names */, 0 /* n_varyings */);
2392         }
2393         catch (Utils::shaderCompilationException& exc)
2394         {
2395                 /* Something wrong with compilation, test case failed */
2396                 tcu::MessageBuilder message = m_context.getTestContext().getLog() << tcu::TestLog::Message;
2397
2398                 message << "Shader compilation failed. Error message: " << exc.m_error_message;
2399
2400                 Utils::program::printShaderSource(exc.m_shader_source.c_str(), message);
2401
2402                 message << tcu::TestLog::EndMessage;
2403
2404                 TCU_FAIL("Shader compilation failed");
2405         }
2406         catch (Utils::programLinkageException& exc)
2407         {
2408                 /* Something wrong with linking, test case failed */
2409                 m_context.getTestContext().getLog() << tcu::TestLog::Message
2410                                                                                         << "Program linking failed. Error message: " << exc.m_error_message
2411                                                                                         << tcu::TestLog::EndMessage;
2412                 TCU_FAIL("Program linking failed");
2413         }
2414
2415         program.use();
2416
2417         /* Prepare VAO */
2418         Utils::vertexArray vao(m_context);
2419         vao.generate();
2420         vao.bind();
2421
2422         /* For each iteration from test type */
2423         for (GLuint i = 0; i < n_iterations; ++i)
2424         {
2425                 /* Prepare textures */
2426                 Utils::texture texture_0(m_context);
2427                 Utils::texture texture_1(m_context);
2428
2429                 prepareTextures(texture_0, texture_1);
2430
2431                 /* Prepare framebuffer */
2432                 Utils::framebuffer framebuffer(m_context);
2433                 framebuffer.generate();
2434                 setupFramebuffer(framebuffer, texture_0, texture_1);
2435                 framebuffer.bind();
2436
2437                 /* Set up viewports */
2438                 setupViewports(test_type, i);
2439
2440                 if (false == isClearTest())
2441                 {
2442                         /* For each draw call */
2443                         for (GLuint draw_call = 0; draw_call < n_draw_calls; ++draw_call)
2444                         {
2445                                 prepareUniforms(program, draw_call);
2446
2447                                 bool     is_clear;
2448                                 GLdouble depth_value;
2449
2450                                 getClearSettings(is_clear, draw_call, depth_value);
2451
2452                                 if (true == is_clear)
2453                                 {
2454                                         gl.clearDepth(depth_value);
2455                                         GLU_EXPECT_NO_ERROR(gl.getError(), "ClearDepth");
2456
2457                                         gl.clear(GL_DEPTH_BUFFER_BIT);
2458                                         GLU_EXPECT_NO_ERROR(gl.getError(), "Clear");
2459                                 }
2460
2461                                 gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
2462                                 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
2463
2464                                 bool result = checkResults(texture_0, texture_1, draw_call);
2465
2466                                 if (false == result)
2467                                 {
2468                                         test_result = false;
2469                                         goto end;
2470                                 }
2471                         }
2472                 }
2473                 else
2474                 {
2475                         gl.clearColor(0.0f, 0.0f, 0.0f, 0.0f);
2476                         GLU_EXPECT_NO_ERROR(gl.getError(), "ClearColor");
2477
2478                         gl.clear(GL_COLOR_BUFFER_BIT);
2479                         GLU_EXPECT_NO_ERROR(gl.getError(), "Clear");
2480
2481                         bool result = checkResults(texture_0, texture_1, 0);
2482
2483                         if (false == result)
2484                         {
2485                                 test_result = false;
2486                                 goto end;
2487                         }
2488                 }
2489         }
2490
2491 end:
2492         /* Set result */
2493         if (true == test_result)
2494         {
2495                 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
2496         }
2497         else
2498         {
2499                 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2500         }
2501
2502         /* Done */
2503         return tcu::TestNode::STOP;
2504 }
2505
2506 /** Check if R32I texture is filled with 4x4 regions of increasing values <0:15>
2507  *
2508  * @param texture_0 Verified texture
2509  * @param ignored
2510  * @param ignored
2511  *
2512  * @return True if texture_0 is filled with expected pattern
2513  **/
2514 bool DrawTestBase::checkResults(Utils::texture& texture_0, Utils::texture& /* texture_1 */, GLuint /*draw_call_index */)
2515 {
2516         bool  check_result = true;
2517         GLint index                = 0;
2518
2519         std::vector<GLint> texture_data;
2520         texture_data.resize(m_width * m_height);
2521         texture_0.get(GL_RED_INTEGER, GL_INT, &texture_data[0]);
2522
2523         for (GLuint y = 0; y < 4; ++y)
2524         {
2525                 for (GLuint x = 0; x < 4; ++x)
2526                 {
2527                         bool result = checkRegionR32I(x, y, index, &texture_data[0]);
2528
2529                         if (false == result)
2530                         {
2531                                 check_result = false;
2532                                 goto end;
2533                         }
2534
2535                         index += 1;
2536                 }
2537         }
2538
2539 end:
2540         return check_result;
2541 }
2542
2543 /** Get settings of clear operation
2544  *
2545  * @param clear_depth_before_draw Selects if clear depth should be executed before draw.
2546  * @param ignored
2547  * @param ignored
2548  **/
2549 void DrawTestBase::getClearSettings(bool& clear_depth_before_draw, GLuint /* iteration_index */,
2550                                                                         GLdouble& /* depth_value */)
2551 {
2552         clear_depth_before_draw = false;
2553 }
2554
2555 /** Get number of draw call to be executed during test
2556  *
2557  * @return 1
2558  **/
2559 GLuint DrawTestBase::getDrawCallsNumber()
2560 {
2561         return 1;
2562 }
2563
2564 /** Get test type
2565  *
2566  * @return VIEWPORT
2567  **/
2568 DrawTestBase::TEST_TYPE DrawTestBase::getTestType()
2569 {
2570         return VIEWPORT;
2571 }
2572
2573 /** Selects if test should do draw or clear operation
2574  *
2575  * @return false - draw operation
2576  **/
2577 bool DrawTestBase::isClearTest()
2578 {
2579         return false;
2580 }
2581
2582 /** Prepare textures used as framebuffer's attachments for current draw call
2583  *
2584  * @param texture_0 R32I texture
2585  * @param ignored
2586  **/
2587 void DrawTestBase::prepareTextures(Utils::texture& texture_0, Utils::texture& /* texture_1 */)
2588 {
2589         prepareTextureR32I(texture_0);
2590 }
2591
2592 /** Prepare uniforms for given draw call
2593  *
2594  * @param ignored
2595  * @param ignored
2596  **/
2597 void DrawTestBase::prepareUniforms(Utils::program& /* program */, GLuint /* draw_call_index */)
2598 {
2599         /* empty */
2600 }
2601
2602 /** Attach textures to framebuffer
2603  *
2604  * @param framebuffer Framebuffer instance
2605  * @param texture_0   Texture attached as color 0
2606  * @param ignored
2607  **/
2608 void DrawTestBase::setupFramebuffer(Utils::framebuffer& framebuffer, Utils::texture& texture_0,
2609                                                                         Utils::texture& /* texture_1 */)
2610 {
2611         framebuffer.attachTexture(GL_COLOR_ATTACHMENT0, texture_0.m_id, m_width, m_height);
2612 }
2613
2614 /** Check if region specified with <x and <y> is filled with expected value.
2615  * Note: there is assumption that there are 4x4 regions
2616  *
2617  * @param x              X coordinate of region
2618  * @param y              Y coordinate of region
2619  * @param expected_value Expected value
2620  * @param data           Texture data (not region, but whole texture)
2621  *
2622  * @return True if region is filled with <expected_value>, false otherwise
2623  **/
2624 bool DrawTestBase::checkRegionR32I(GLuint x, GLuint y, GLint expected_value, GLint* data)
2625 {
2626         static GLuint width  = m_width / 4;
2627         static GLuint height = m_height / 4;
2628
2629         return checkRegionR32I(x, y, width, height, expected_value, data);
2630 }
2631
2632 /** Check if region specified with <x and <y> is filled with expected value.
2633  * Note: there is assumption that there are 4x4 regions
2634  *
2635  * @param x              X coordinate of region
2636  * @param y              Y coordinate of region
2637  * @param width          Width of region
2638  * @param height         Height of region
2639  * @param expected_value Expected value
2640  * @param data           Texture data (not region, but whole texture)
2641  *
2642  * @return True if region is filled with <expected_value>, false otherwise
2643  **/
2644 bool DrawTestBase::checkRegionR32I(GLuint x, GLuint y, GLuint width, GLuint height, GLint expected_value, GLint* data)
2645 {
2646         bool result = true;
2647
2648         const GLuint offset = (y * height * m_width) + (x * width);
2649
2650         for (GLuint line = 0; line < height; ++line)
2651         {
2652                 const GLuint line_offset = offset + line * m_width;
2653
2654                 for (GLuint texel = 0; texel < width; ++texel)
2655                 {
2656                         const GLuint texel_offset = line_offset + texel;
2657
2658                         const GLint value = data[texel_offset];
2659
2660                         if (expected_value != value)
2661                         {
2662                                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid result. Region (" << x << "x"
2663                                                                                                         << y << "). Expected: " << expected_value << " got " << value
2664                                                                                                         << tcu::TestLog::EndMessage;
2665
2666                                 result = false;
2667                                 goto end;
2668                         }
2669                 }
2670         }
2671
2672 end:
2673         return result;
2674 }
2675
2676 /** Return boiler-plate vertex shader
2677  *
2678  * @return Source code of vertex shader
2679  **/
2680 std::string DrawTestBase::getVertexShader()
2681 {
2682         static const GLchar* source = "#version 410 core\n"
2683                                                                   "\n"
2684                                                                   "void main()\n"
2685                                                                   "{\n"
2686                                                                   "    /* empty */;\n"
2687                                                                   "}\n"
2688                                                                   "\n";
2689
2690         std::string result = source;
2691
2692         return result;
2693 }
2694
2695 /** Set up viewports
2696  *
2697  * @param type            Type of test
2698  * @param iteration_index Index of iteration for given test type
2699  **/
2700 void DrawTestBase::setupViewports(TEST_TYPE type, GLuint iteration_index)
2701 {
2702         switch (type)
2703         {
2704         case VIEWPORT:
2705         {
2706                 VIEWPORT_METHOD method;
2707                 switch (iteration_index)
2708                 {
2709                 case 0:
2710                 case 1:
2711                 case 2:
2712                         method = (VIEWPORT_METHOD)iteration_index;
2713                         break;
2714                 default:
2715                         TCU_FAIL("Invalid value");
2716                 }
2717                 setup4x4Viewport(method);
2718         }
2719         break;
2720         case SCISSOR:
2721         {
2722                 SCISSOR_METHOD method;
2723                 switch (iteration_index)
2724                 {
2725                 case 0:
2726                 case 1:
2727                 case 2:
2728                         method = (SCISSOR_METHOD)iteration_index;
2729                         break;
2730                 default:
2731                         TCU_FAIL("Invalid value");
2732                 }
2733                 setup4x4Scissor(method, false /* set_zeros */);
2734         }
2735         break;
2736         case DEPTHRANGE:
2737         {
2738                 DEPTH_RANGE_METHOD method;
2739                 switch (iteration_index)
2740                 {
2741                 case 0:
2742                 case 1:
2743                         method = (DEPTH_RANGE_METHOD)iteration_index;
2744                         break;
2745                 default:
2746                         TCU_FAIL("Invalid value");
2747                 }
2748                 setup16x2Depths(method);
2749         }
2750         break;
2751         case PROVOKING:
2752         {
2753                 PROVOKING_VERTEX provoking;
2754                 switch (iteration_index)
2755                 {
2756                 case 0:
2757                 case 1:
2758                         provoking = (PROVOKING_VERTEX)iteration_index;
2759                         break;
2760                 default:
2761                         TCU_FAIL("Invalid value");
2762                 }
2763                 setup2x2Viewport(provoking);
2764         }
2765         break;
2766         default:
2767                 TCU_FAIL("Invalid enum");
2768         }
2769 }
2770
2771 /** Prepare R32I texture filled with value -1
2772  *
2773  * @param texture Texture instance
2774  **/
2775 void DrawTestBase::prepareTextureR32I(Utils::texture& texture)
2776 {
2777         static const GLuint size = m_width * m_height;
2778         GLint                           data[size];
2779
2780         for (GLuint i = 0; i < size; ++i)
2781         {
2782                 data[i] = -1;
2783         }
2784
2785         texture.create(m_width, m_height, GL_R32I);
2786         texture.update(m_width, m_height, 0 /* depth */, GL_RED_INTEGER, GL_INT, data);
2787 }
2788
2789 /** Prepare R32I array texture filled with value -1, 4 layers
2790  *
2791  * @param texture Texture instance
2792  **/
2793 void DrawTestBase::prepareTextureR32Ix4(Utils::texture& texture)
2794 {
2795         static const GLuint size = m_width * m_height * m_r32ix4_depth;
2796
2797         std::vector<GLint> data;
2798         data.resize(size);
2799
2800         for (GLuint i = 0; i < size; ++i)
2801         {
2802                 data[i] = -1;
2803         }
2804
2805         texture.create(m_width, m_height, m_r32ix4_depth, GL_R32I);
2806         texture.update(m_width, m_height, m_r32ix4_depth, GL_RED_INTEGER, GL_INT, &data[0]);
2807 }
2808
2809 /** Prepare R32I array texture filled with value -1
2810  *
2811  * @param texture Texture instance
2812  **/
2813 void DrawTestBase::prepareTextureArrayR32I(Utils::texture& texture)
2814 {
2815         static const GLuint size = m_width * m_height * m_depth;
2816
2817         std::vector<GLint> data;
2818         data.resize(size);
2819
2820         for (GLuint i = 0; i < size; ++i)
2821         {
2822                 data[i] = -1;
2823         }
2824
2825         texture.create(m_width, m_height, m_depth, GL_R32I);
2826         texture.update(m_width, m_height, m_depth, GL_RED_INTEGER, GL_INT, &data[0]);
2827 }
2828
2829 /** Prepare R32F texture filled with value -1
2830  *
2831  * @param texture Texture instance
2832  **/
2833 void DrawTestBase::prepareTextureR32F(Utils::texture& texture)
2834 {
2835         static const GLuint size = m_r32f_width * m_r32f_height;
2836         GLfloat                         data[size];
2837
2838         for (GLuint i = 0; i < size; ++i)
2839         {
2840                 data[i] = -1.0f;
2841         }
2842
2843         texture.create(m_r32f_width, m_r32f_height, GL_R32F);
2844         texture.update(m_r32f_width, m_r32f_height, 0 /* depth */, GL_RED, GL_FLOAT, data);
2845 }
2846
2847 /** Prepare D32F texture filled with value -1
2848  *
2849  * @param texture Texture instance
2850  **/
2851 void DrawTestBase::prepareTextureD32F(Utils::texture& texture)
2852 {
2853         static const GLuint size = m_width * m_height;
2854         GLfloat                         data[size];
2855
2856         for (GLuint i = 0; i < size; ++i)
2857         {
2858                 data[i] = -1.0f;
2859         }
2860
2861         texture.create(m_width, m_height, GL_DEPTH_COMPONENT32F);
2862         texture.update(m_width, m_height, 0 /* depth */, GL_DEPTH_COMPONENT, GL_FLOAT, data);
2863 }
2864
2865 /** Set up 16 viewports and depth ranges horizontally
2866  *
2867  * @param method Method used to set depth ranges
2868  **/
2869 void DrawTestBase::setup16x2Depths(DEPTH_RANGE_METHOD method)
2870 {
2871         static const GLdouble step = 1.0 / 16.0;
2872
2873         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2874
2875         GLdouble depth_data[16 * 2];
2876         GLfloat  viewport_data[16 * 4];
2877
2878         for (GLuint i = 0; i < 16; ++i)
2879         {
2880                 const GLdouble near = step * (GLdouble)i;
2881
2882                 depth_data[i * 2 + 0] = near;
2883                 depth_data[i * 2 + 1] = 1.0 - near;
2884
2885                 viewport_data[i * 4 + 0] = (GLfloat)i;
2886                 viewport_data[i * 4 + 1] = 0.0f;
2887                 viewport_data[i * 4 + 2] = 1.0f;
2888                 viewport_data[i * 4 + 3] = 2.0f;
2889         }
2890
2891         gl.viewportArrayv(0 /* first */, 16 /* count */, viewport_data);
2892         GLU_EXPECT_NO_ERROR(gl.getError(), "ViewportArrayv");
2893
2894         switch (method)
2895         {
2896         case DEPTHRANGEINDEXED:
2897                 for (GLuint i = 0; i < 16; ++i)
2898                 {
2899                         gl.depthRangeIndexed(i, depth_data[i * 2 + 0], depth_data[i * 2 + 1]);
2900                         GLU_EXPECT_NO_ERROR(gl.getError(), "DepthRangeIndexed");
2901                 }
2902                 break;
2903
2904         case DEPTHRANGEARRAYV:
2905                 gl.depthRangeArrayv(0 /* first */, 16 /* count */, depth_data);
2906                 GLU_EXPECT_NO_ERROR(gl.getError(), "DepthRangeArrayv");
2907                 break;
2908
2909         default:
2910                 TCU_FAIL("Invalid enum");
2911         }
2912 }
2913
2914 /** Set up 4x4 scissor boxes with enabled test
2915  *
2916  * @param method    Method used to set scissor boxes
2917  * @param set_zeros Select if width and height should be 0 or image_dim / 4
2918  **/
2919 void DrawTestBase::setup4x4Scissor(SCISSOR_METHOD method, bool set_zeros)
2920 {
2921         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2922
2923         for (GLuint i = 0; i < 16; ++i)
2924         {
2925                 gl.enablei(GL_SCISSOR_TEST, i);
2926                 GLU_EXPECT_NO_ERROR(gl.getError(), "Enablei");
2927         }
2928
2929         GLint index = 0;
2930         GLint data[16 * 4 /* 4x4 * (x + y + w + h) */];
2931
2932         GLint width  = m_width / 4;
2933         GLint height = m_height / 4;
2934
2935         for (GLuint y = 0; y < 4; ++y)
2936         {
2937                 for (GLuint x = 0; x < 4; ++x)
2938                 {
2939                         data[index * 4 + 0] = x * width;
2940                         data[index * 4 + 1] = y * height;
2941                         if (false == set_zeros)
2942                         {
2943                                 data[index * 4 + 2] = width;
2944                                 data[index * 4 + 3] = height;
2945                         }
2946                         else
2947                         {
2948                                 data[index * 4 + 2] = 0;
2949                                 data[index * 4 + 3] = 0;
2950                         }
2951
2952                         index += 1;
2953                 }
2954         }
2955
2956         switch (method)
2957         {
2958         case SCISSORARRAYV:
2959                 gl.scissorArrayv(0 /* first */, 16 /*count */, data);
2960                 GLU_EXPECT_NO_ERROR(gl.getError(), "ScissorArrayv");
2961                 break;
2962         case SCISSORINDEXEDF:
2963                 for (GLuint i = 0; i < 16; ++i)
2964                 {
2965                         const GLint x = data[i * 4 + 0];
2966                         const GLint y = data[i * 4 + 1];
2967                         const GLint w = data[i * 4 + 2];
2968                         const GLint h = data[i * 4 + 3];
2969
2970                         gl.scissorIndexed(i, x, y, w, h);
2971                         GLU_EXPECT_NO_ERROR(gl.getError(), "ScissorIndexed");
2972                 }
2973                 break;
2974         case SCISSORINDEXEDF_V:
2975                 for (GLuint i = 0; i < 16; ++i)
2976                 {
2977                         gl.scissorIndexedv(i, &data[i * 4]);
2978                         GLU_EXPECT_NO_ERROR(gl.getError(), "ScissorIndexedv");
2979                 }
2980                 break;
2981         default:
2982                 TCU_FAIL("Invalid enum");
2983         }
2984 }
2985
2986 /** Set up 4x4 viewports
2987  *
2988  * @param method Method used to set viewports
2989  **/
2990 void DrawTestBase::setup4x4Viewport(VIEWPORT_METHOD method)
2991 {
2992         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2993
2994         GLint   index = 0;
2995         GLfloat data[16 * 4 /* 4x4 * (x + y + w + h) */];
2996
2997         GLfloat width  = (GLfloat)(m_width / 4);
2998         GLfloat height = (GLfloat)(m_height / 4);
2999
3000         for (GLuint y = 0; y < 4; ++y)
3001         {
3002                 for (GLuint x = 0; x < 4; ++x)
3003                 {
3004                         data[index * 4 + 0] = (GLfloat)((GLfloat)x * width);
3005                         data[index * 4 + 1] = (GLfloat)((GLfloat)y * height);
3006                         data[index * 4 + 2] = width;
3007                         data[index * 4 + 3] = height;
3008
3009                         index += 1;
3010                 }
3011         }
3012
3013         switch (method)
3014         {
3015         case VIEWPORTARRAYV:
3016                 gl.viewportArrayv(0 /* first */, 16 /*count */, data);
3017                 GLU_EXPECT_NO_ERROR(gl.getError(), "ViewportArrayv");
3018                 break;
3019         case VIEWPORTINDEXEDF:
3020                 for (GLuint i = 0; i < 16; ++i)
3021                 {
3022                         const GLfloat x = data[i * 4 + 0];
3023                         const GLfloat y = data[i * 4 + 1];
3024                         const GLfloat w = data[i * 4 + 2];
3025                         const GLfloat h = data[i * 4 + 3];
3026
3027                         gl.viewportIndexedf(i, x, y, w, h);
3028                         GLU_EXPECT_NO_ERROR(gl.getError(), "ViewportIndexedf");
3029                 }
3030                 break;
3031         case VIEWPORTINDEXEDF_V:
3032                 for (GLuint i = 0; i < 16; ++i)
3033                 {
3034                         gl.viewportIndexedfv(i, &data[i * 4]);
3035                         GLU_EXPECT_NO_ERROR(gl.getError(), "ViewportIndexedfv");
3036                 }
3037                 break;
3038         default:
3039                 TCU_FAIL("Invalid enum");
3040         }
3041 }
3042
3043 /** Set up 4x4 viewports
3044  *
3045  * @param method Method used to set viewports
3046  **/
3047 void DrawTestBase::setup2x2Viewport(PROVOKING_VERTEX provoking)
3048 {
3049         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3050
3051         GLint   index = 0;
3052         GLfloat data[4 * 4 /* 4x4 * (x + y + w + h) */];
3053
3054         GLfloat width  = (GLfloat)(m_width / 2);
3055         GLfloat height = (GLfloat)(m_height / 2);
3056
3057         for (GLuint y = 0; y < 2; ++y)
3058         {
3059                 for (GLuint x = 0; x < 2; ++x)
3060                 {
3061                         data[index * 4 + 0] = (GLfloat)((GLfloat)x * width);
3062                         data[index * 4 + 1] = (GLfloat)((GLfloat)y * height);
3063                         data[index * 4 + 2] = width;
3064                         data[index * 4 + 3] = height;
3065
3066                         index += 1;
3067                 }
3068         }
3069
3070         gl.viewportArrayv(0 /* first */, 4 /*count */, data);
3071         GLU_EXPECT_NO_ERROR(gl.getError(), "ViewportArrayv");
3072
3073         GLenum mode = 0;
3074         switch (provoking)
3075         {
3076         case FIRST:
3077                 mode = GL_FIRST_VERTEX_CONVENTION;
3078                 break;
3079         case LAST:
3080                 mode = GL_LAST_VERTEX_CONVENTION;
3081                 break;
3082         default:
3083                 TCU_FAIL("Invalid enum");
3084         }
3085
3086         gl.provokingVertex(mode);
3087         GLU_EXPECT_NO_ERROR(gl.getError(), "ProvokingVertex");
3088 }
3089
3090 /** Constructor
3091  *
3092  * @param context          Test context
3093  **/
3094 DrawToSingleLayerWithMultipleViewports::DrawToSingleLayerWithMultipleViewports(deqp::Context&                      context,
3095                                                                                                                                                            const glcts::ExtParameters& extParams)
3096         : DrawTestBase(context, extParams, "draw_to_single_layer_with_multiple_viewports",
3097                                    "Test verifies that multiple viewports can be used to draw to single layer")
3098 {
3099         /* Nothing to be done here */
3100 }
3101
3102 /** Get string with fragment shader source code
3103  *
3104  * @return Fragment shader source
3105  **/
3106 std::string DrawToSingleLayerWithMultipleViewports::getFragmentShader()
3107 {
3108         static const GLchar* source = "#version 410 core\n"
3109                                                                   "\n"
3110                                                                   "flat in  int gs_fs_color;\n"
3111                                                                   "     out int fs_out_color;\n"
3112                                                                   "\n"
3113                                                                   "void main()\n"
3114                                                                   "{\n"
3115                                                                   "    fs_out_color = gs_fs_color;\n"
3116                                                                   "}\n"
3117                                                                   "\n";
3118
3119         std::string result = source;
3120
3121         return result;
3122 }
3123
3124 /** Get string with geometry shader source code
3125  *
3126  * @return Geometry shader source
3127  **/
3128 std::string DrawToSingleLayerWithMultipleViewports::getGeometryShader()
3129 {
3130         static const GLchar* source = "#version 410 core\n"
3131                                                                   "\n"
3132                                                                   "layout(points, invocations = 16)         in;\n"
3133                                                                   "layout(triangle_strip, max_vertices = 4) out;\n"
3134                                                                   "\n"
3135                                                                   "flat out int gs_fs_color;\n"
3136                                                                   "\n"
3137                                                                   "void main()\n"
3138                                                                   "{\n"
3139                                                                   "    gs_fs_color      = gl_InvocationID;\n"
3140                                                                   "    gl_ViewportIndex = gl_InvocationID;\n"
3141                                                                   "    gl_Position  = vec4(-1, -1, 0, 1);\n"
3142                                                                   "    EmitVertex();\n"
3143                                                                   "    gs_fs_color      = gl_InvocationID;\n"
3144                                                                   "    gl_ViewportIndex = gl_InvocationID;\n"
3145                                                                   "    gl_Position  = vec4(-1, 1, 0, 1);\n"
3146                                                                   "    EmitVertex();\n"
3147                                                                   "    gs_fs_color      = gl_InvocationID;\n"
3148                                                                   "    gl_ViewportIndex = gl_InvocationID;\n"
3149                                                                   "    gl_Position  = vec4(1, -1, 0, 1);\n"
3150                                                                   "    EmitVertex();\n"
3151                                                                   "    gs_fs_color      = gl_InvocationID;\n"
3152                                                                   "    gl_ViewportIndex = gl_InvocationID;\n"
3153                                                                   "    gl_Position  = vec4(1, 1, 0, 1);\n"
3154                                                                   "    EmitVertex();\n"
3155                                                                   "}\n"
3156                                                                   "\n";
3157
3158         std::string result = source;
3159
3160         return result;
3161 }
3162
3163 /** Constructor
3164  *
3165  * @param context          Test context
3166  **/
3167 DynamicViewportIndex::DynamicViewportIndex(deqp::Context& context, const glcts::ExtParameters& extParams)
3168         : DrawTestBase(context, extParams, "dynamic_viewport_index",
3169                                    "Test verifies that gl_ViewportIndex can be assigned with dynamic value")
3170 {
3171         /* Nothing to be done here */
3172 }
3173
3174 /** Get string with fragment shader source code
3175  *
3176  * @return Fragment shader source
3177  **/
3178 std::string DynamicViewportIndex::getFragmentShader()
3179 {
3180         static const GLchar* source = "#version 410 core\n"
3181                                                                   "\n"
3182                                                                   "flat in  int gs_fs_color;\n"
3183                                                                   "     out int fs_out_color;\n"
3184                                                                   "\n"
3185                                                                   "void main()\n"
3186                                                                   "{\n"
3187                                                                   "    fs_out_color = gs_fs_color;\n"
3188                                                                   "}\n"
3189                                                                   "\n";
3190
3191         std::string result = source;
3192
3193         return result;
3194 }
3195
3196 /** Get string with geometry shader source code
3197  *
3198  * @return Geometry shader source
3199  **/
3200 std::string DynamicViewportIndex::getGeometryShader()
3201 {
3202         static const GLchar* source = "#version 410 core\n"
3203                                                                   "\n"
3204                                                                   "layout(points, invocations = 1)          in;\n"
3205                                                                   "layout(triangle_strip, max_vertices = 4) out;\n"
3206                                                                   "\n"
3207                                                                   "uniform int uni_index;\n"
3208                                                                   "\n"
3209                                                                   "flat out int gs_fs_color;\n"
3210                                                                   "\n"
3211                                                                   "void main()\n"
3212                                                                   "{\n"
3213                                                                   "    gs_fs_color      = uni_index;\n"
3214                                                                   "    gl_ViewportIndex = uni_index;\n"
3215                                                                   "    gl_Position  = vec4(-1, -1, 0, 1);\n"
3216                                                                   "    EmitVertex();\n"
3217                                                                   "    gs_fs_color      = uni_index;\n"
3218                                                                   "    gl_ViewportIndex = uni_index;\n"
3219                                                                   "    gl_Position  = vec4(-1, 1, 0, 1);\n"
3220                                                                   "    EmitVertex();\n"
3221                                                                   "    gs_fs_color      = uni_index;\n"
3222                                                                   "    gl_ViewportIndex = uni_index;\n"
3223                                                                   "    gl_Position  = vec4(1, -1, 0, 1);\n"
3224                                                                   "    EmitVertex();\n"
3225                                                                   "    gs_fs_color      = uni_index;\n"
3226                                                                   "    gl_ViewportIndex = uni_index;\n"
3227                                                                   "    gl_Position  = vec4(1, 1, 0, 1);\n"
3228                                                                   "    EmitVertex();\n"
3229                                                                   "}\n"
3230                                                                   "\n";
3231
3232         std::string result = source;
3233
3234         return result;
3235 }
3236
3237 /** Check if R32I texture is filled with 4x4 regions of increasing values <0:15>
3238  *
3239  * @param texture_0       Verified texture
3240  * @param ignored
3241  * @param draw_call_index Draw call that was executed
3242  *
3243  * @return True if texture_0 is filled with expected pattern
3244  **/
3245 bool DynamicViewportIndex::checkResults(Utils::texture& texture_0, Utils::texture& /* texture_1 */,
3246                                                                                 GLuint                  draw_call_index)
3247 {
3248         bool   check_result = true;
3249         GLuint index            = 0;
3250
3251         std::vector<GLint> texture_data;
3252         texture_data.resize(m_width * m_height);
3253         texture_0.get(GL_RED_INTEGER, GL_INT, &texture_data[0]);
3254
3255         for (GLuint y = 0; y < 4; ++y)
3256         {
3257                 for (GLuint x = 0; x < 4; ++x)
3258                 {
3259                         GLint expected_value = -1;
3260                         if (index <= draw_call_index)
3261                         {
3262                                 expected_value = index;
3263                         }
3264
3265                         bool result = checkRegionR32I(x, y, expected_value, &texture_data[0]);
3266
3267                         if (false == result)
3268                         {
3269                                 check_result = false;
3270                                 goto end;
3271                         }
3272
3273                         index += 1;
3274                 }
3275         }
3276
3277 end:
3278         return check_result;
3279 }
3280
3281 /** Get number of draw call to be executed during test
3282  *
3283  * @return 16
3284  **/
3285 GLuint DynamicViewportIndex::getDrawCallsNumber()
3286 {
3287         return 16;
3288 }
3289
3290 /** Prepare uniforms for given draw call
3291  *
3292  * @param program         Program object
3293  * @param draw_call_index Index of draw call to be executed
3294  **/
3295 void DynamicViewportIndex::prepareUniforms(Utils::program& program, GLuint draw_call_index)
3296 {
3297         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3298
3299         GLint location = program.getUniformLocation("uni_index");
3300
3301         gl.uniform1i(location, (GLint)draw_call_index);
3302         GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i");
3303 }
3304
3305 /** Constructor
3306  *
3307  * @param context          Test context
3308  **/
3309 DrawMulitpleViewportsWithSingleInvocation::DrawMulitpleViewportsWithSingleInvocation(
3310         deqp::Context& context, const glcts::ExtParameters& extParams)
3311         : DrawTestBase(context, extParams, "draw_mulitple_viewports_with_single_invocation",
3312                                    "Test verifies that single invocation can output to multiple viewports")
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 DrawMulitpleViewportsWithSingleInvocation::getFragmentShader()
3322 {
3323         static const GLchar* source = "#version 410 core\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 DrawMulitpleViewportsWithSingleInvocation::getGeometryShader()
3344 {
3345         static const GLchar* source = "#version 410 core\n"
3346                                                                   "\n"
3347                                                                   "layout(points, invocations = 1)           in;\n"
3348                                                                   "layout(triangle_strip, max_vertices = 64) out;\n"
3349                                                                   "\n"
3350                                                                   "flat out int gs_fs_color;\n"
3351                                                                   "\n"
3352                                                                   "void routine(int index)\n"
3353                                                                   "{\n"
3354                                                                   "    gs_fs_color      = index;\n"
3355                                                                   "    gl_ViewportIndex = index;\n"
3356                                                                   "    gl_Position  = vec4(-1, -1, 0, 1);\n"
3357                                                                   "    EmitVertex();\n"
3358                                                                   "    gs_fs_color      = index;\n"
3359                                                                   "    gl_ViewportIndex = index;\n"
3360                                                                   "    gl_Position  = vec4(-1, 1, 0, 1);\n"
3361                                                                   "    EmitVertex();\n"
3362                                                                   "    gs_fs_color      = index;\n"
3363                                                                   "    gl_ViewportIndex = index;\n"
3364                                                                   "    gl_Position  = vec4(1, -1, 0, 1);\n"
3365                                                                   "    EmitVertex();\n"
3366                                                                   "    gs_fs_color      = index;\n"
3367                                                                   "    gl_ViewportIndex = index;\n"
3368                                                                   "    gl_Position  = vec4(1, 1, 0, 1);\n"
3369                                                                   "    EmitVertex();\n"
3370                                                                   "    EndPrimitive();\n"
3371                                                                   "}\n"
3372                                                                   "\n"
3373                                                                   "void main()\n"
3374                                                                   "{\n"
3375                                                                   "    for(int i = 0; i < 16; ++i)\n"
3376                                                                   "    {\n"
3377                                                                   "        routine(i);\n"
3378                                                                   "    }\n"
3379                                                                   "}\n"
3380                                                                   "\n";
3381
3382         std::string result = source;
3383
3384         return result;
3385 }
3386
3387 /** Constructor
3388  *
3389  * @param context          Test context
3390  **/
3391 ViewportIndexSubroutine::ViewportIndexSubroutine(deqp::Context& context, const glcts::ExtParameters& extParams)
3392         : DrawTestBase(context, extParams, "viewport_index_subroutine",
3393                                    "Test verifies subroutines can be used to output data to specific viewport")
3394 {
3395         /* Nothing to be done here */
3396 }
3397
3398 /** Get string with fragment shader source code
3399  *
3400  * @return Fragment shader source
3401  **/
3402 std::string ViewportIndexSubroutine::getFragmentShader()
3403 {
3404         static const GLchar* source = "#version 410 core\n"
3405                                                                   "\n"
3406                                                                   "flat in  int gs_fs_color;\n"
3407                                                                   "     out int fs_out_color;\n"
3408                                                                   "\n"
3409                                                                   "void main()\n"
3410                                                                   "{\n"
3411                                                                   "    fs_out_color = gs_fs_color;\n"
3412                                                                   "}\n"
3413                                                                   "\n";
3414
3415         std::string result = source;
3416
3417         return result;
3418 }
3419
3420 /** Get string with geometry shader source code
3421  *
3422  * @return Geometry shader source
3423  **/
3424 std::string ViewportIndexSubroutine::getGeometryShader()
3425 {
3426         static const GLchar* source = "#version 410 core\n"
3427                                                                   "\n"
3428                                                                   "layout(points, invocations = 1)          in;\n"
3429                                                                   "layout(triangle_strip, max_vertices = 4) out;\n"
3430                                                                   "\n"
3431                                                                   "flat out int gs_fs_color;\n"
3432                                                                   "\n"
3433                                                                   "subroutine void indexSetter(void);\n"
3434                                                                   "\n"
3435                                                                   "subroutine(indexSetter) void four()\n"
3436                                                                   "{\n"
3437                                                                   "    gs_fs_color      = 4;\n"
3438                                                                   "    gl_ViewportIndex = 4;\n"
3439                                                                   "}\n"
3440                                                                   "\n"
3441                                                                   "subroutine(indexSetter) void five()\n"
3442                                                                   "{\n"
3443                                                                   "    gs_fs_color      = 5;\n"
3444                                                                   "    gl_ViewportIndex = 5;\n"
3445                                                                   "}\n"
3446                                                                   "\n"
3447                                                                   "subroutine uniform indexSetter routine;\n"
3448                                                                   "\n"
3449                                                                   "void main()\n"
3450                                                                   "{\n"
3451                                                                   "    routine();\n"
3452                                                                   "    gl_Position  = vec4(-1, -1, 0, 1);\n"
3453                                                                   "    EmitVertex();\n"
3454                                                                   "    routine();\n"
3455                                                                   "    gl_Position  = vec4(-1, 1, 0, 1);\n"
3456                                                                   "    EmitVertex();\n"
3457                                                                   "    routine();\n"
3458                                                                   "    gl_Position  = vec4(1, -1, 0, 1);\n"
3459                                                                   "    EmitVertex();\n"
3460                                                                   "    routine();\n"
3461                                                                   "    gl_Position  = vec4(1, 1, 0, 1);\n"
3462                                                                   "    EmitVertex();\n"
3463                                                                   "}\n"
3464                                                                   "\n";
3465
3466         std::string result = source;
3467
3468         return result;
3469 }
3470
3471 /** Check if R32I texture is filled with two halves, left is 4, right is either -1 or 5
3472  *
3473  * @param texture_0       Verified texture
3474  * @param ignored
3475  * @param draw_call_index Draw call that was executed
3476  *
3477  * @return True if texture_0 is filled with expected pattern
3478  **/
3479 bool ViewportIndexSubroutine::checkResults(Utils::texture& texture_0, Utils::texture& /* texture_1 */,
3480                                                                                    GLuint                  draw_call_index)
3481 {
3482         bool check_result = true;
3483
3484         std::vector<GLint> texture_data;
3485         texture_data.resize(m_width * m_height);
3486         texture_0.get(GL_RED_INTEGER, GL_INT, &texture_data[0]);
3487
3488         /* Left is 4 and right is -1, or left is 4 and right is 5 */
3489         GLint expected_left  = 4;
3490         GLint expected_right = (1 == draw_call_index) ? 5 : -1;
3491
3492         for (GLuint y = 0; y < 4; ++y)
3493         {
3494                 for (GLuint x = 0; x < 2; ++x)
3495                 {
3496                         bool result = checkRegionR32I(x, y, expected_left, &texture_data[0]);
3497
3498                         if (false == result)
3499                         {
3500                                 check_result = false;
3501                                 goto end;
3502                         }
3503                 }
3504         }
3505
3506         for (GLuint y = 0; y < 4; ++y)
3507         {
3508                 for (GLuint x = 2; x < 4; ++x)
3509                 {
3510                         bool result = checkRegionR32I(x, y, expected_right, &texture_data[0]);
3511
3512                         if (false == result)
3513                         {
3514                                 check_result = false;
3515                                 goto end;
3516                         }
3517                 }
3518         }
3519
3520 end:
3521         return check_result;
3522 }
3523
3524 /** Get number of draw call to be executed during test
3525  *
3526  * @return 2
3527  **/
3528 GLuint ViewportIndexSubroutine::getDrawCallsNumber()
3529 {
3530         return 2;
3531 }
3532
3533 /** Prepare uniforms for given draw call
3534  *
3535  * @param program         Program object
3536  * @param draw_call_index Index of draw call to be executed
3537  **/
3538 void ViewportIndexSubroutine::prepareUniforms(Utils::program& program, GLuint draw_call_index)
3539 {
3540         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3541
3542         const GLchar* subroutine_name = (0 == draw_call_index) ? "four" : "five";
3543
3544         GLint  location = program.getSubroutineUniformLocation("routine", GL_GEOMETRY_SHADER);
3545         GLuint index    = program.getSubroutineIndex(subroutine_name, GL_GEOMETRY_SHADER);
3546
3547         if (0 != location)
3548         {
3549                 TCU_FAIL("Something wrong, subroutine uniform location is not 0. Mistake in geometry shader?");
3550         }
3551
3552         gl.uniformSubroutinesuiv(GL_GEOMETRY_SHADER, 1, &index);
3553         GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv");
3554 }
3555
3556 /** Set 4th viewport on left half and 5 on right half of framebuffer. Rest span over whole image.
3557  *
3558  * @param ignored
3559  * @param iteration_index Index of iteration, used to select "viewport" method
3560  **/
3561 void ViewportIndexSubroutine::setupViewports(TEST_TYPE /* type */, glw::GLuint iteration_index)
3562 {
3563         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3564
3565         GLfloat data[2 * 4] = { 0.0f, 0.0f, 64.0f, 128.0f, 64.0f, 0.0f, 64.0f, 128.0f };
3566
3567         gl.viewport(0, 0, m_width, m_height);
3568         GLU_EXPECT_NO_ERROR(gl.getError(), "Viewport");
3569
3570         switch (iteration_index)
3571         {
3572         case 0:
3573
3574                 gl.viewportArrayv(4, 2, data);
3575                 GLU_EXPECT_NO_ERROR(gl.getError(), "ViewportArrayv");
3576
3577                 break;
3578
3579         case 1:
3580
3581                 gl.viewportIndexedf(4, data[0], data[1], data[2], data[3]);
3582                 GLU_EXPECT_NO_ERROR(gl.getError(), "ViewportIndexedf");
3583
3584                 gl.viewportIndexedf(5, data[4], data[5], data[6], data[7]);
3585                 GLU_EXPECT_NO_ERROR(gl.getError(), "ViewportIndexedf");
3586
3587                 break;
3588
3589         case 2:
3590
3591                 gl.viewportIndexedfv(4, &data[0]);
3592                 GLU_EXPECT_NO_ERROR(gl.getError(), "ViewportIndexedfv");
3593
3594                 gl.viewportIndexedfv(5, &data[4]);
3595                 GLU_EXPECT_NO_ERROR(gl.getError(), "ViewportIndexedfv");
3596
3597                 break;
3598
3599         default:
3600                 TCU_FAIL("Invalid value");
3601         }
3602 }
3603
3604 /** Constructor
3605  *
3606  * @param context Test context
3607  **/
3608 DrawMultipleLayers::DrawMultipleLayers(deqp::Context& context, const glcts::ExtParameters& extParams)
3609         : DrawTestBase(context, extParams, "draw_multiple_layers",
3610                                    "Test verifies that single viewport affects multiple layers in the same way")
3611 {
3612         /* Nothing to be done here */
3613 }
3614
3615 /** Constructor
3616  *
3617  * @param context          Test context
3618  * @param test_name        Test name
3619  * @param test_description Test description
3620  **/
3621 DrawMultipleLayers::DrawMultipleLayers(deqp::Context& context, const glcts::ExtParameters& extParams,
3622                                                                            const GLchar* test_name, const GLchar* test_description)
3623         : DrawTestBase(context, extParams, test_name, test_description)
3624 {
3625         /* Nothing to be done here */
3626 }
3627
3628 /** Get string with fragment shader source code
3629  *
3630  * @return Fragment shader source
3631  **/
3632 std::string DrawMultipleLayers::getFragmentShader()
3633 {
3634         static const GLchar* source = "#version 410 core\n"
3635                                                                   "\n"
3636                                                                   "flat in  int gs_fs_color;\n"
3637                                                                   "     out int fs_out_color;\n"
3638                                                                   "\n"
3639                                                                   "void main()\n"
3640                                                                   "{\n"
3641                                                                   "    fs_out_color = gs_fs_color;\n"
3642                                                                   "}\n"
3643                                                                   "\n";
3644
3645         std::string result = source;
3646
3647         return result;
3648 }
3649
3650 /** Get string with geometry shader source code
3651  *
3652  * @return Geometry shader source
3653  **/
3654 std::string DrawMultipleLayers::getGeometryShader()
3655 {
3656         static const GLchar* source = "#version 410 core\n"
3657                                                                   "\n"
3658                                                                   "layout(points, invocations = 16)         in;\n"
3659                                                                   "layout(triangle_strip, max_vertices = 4) out;\n"
3660                                                                   "\n"
3661                                                                   "flat out int gs_fs_color;\n"
3662                                                                   "\n"
3663                                                                   "void main()\n"
3664                                                                   "{\n"
3665                                                                   "    gs_fs_color      = gl_InvocationID;\n"
3666                                                                   "    gl_ViewportIndex = gl_InvocationID;\n"
3667                                                                   "    gl_Layer         = gl_InvocationID;\n"
3668                                                                   "    gl_Position  = vec4(-1, -1, 0, 1);\n"
3669                                                                   "    EmitVertex();\n"
3670                                                                   "    gs_fs_color      = gl_InvocationID;\n"
3671                                                                   "    gl_ViewportIndex = gl_InvocationID;\n"
3672                                                                   "    gl_Layer         = gl_InvocationID;\n"
3673                                                                   "    gl_Position  = vec4(-1, 1, 0, 1);\n"
3674                                                                   "    EmitVertex();\n"
3675                                                                   "    gs_fs_color      = gl_InvocationID;\n"
3676                                                                   "    gl_ViewportIndex = gl_InvocationID;\n"
3677                                                                   "    gl_Layer         = gl_InvocationID;\n"
3678                                                                   "    gl_Position  = vec4(1, -1, 0, 1);\n"
3679                                                                   "    EmitVertex();\n"
3680                                                                   "    gs_fs_color      = gl_InvocationID;\n"
3681                                                                   "    gl_ViewportIndex = gl_InvocationID;\n"
3682                                                                   "    gl_Layer         = gl_InvocationID;\n"
3683                                                                   "    gl_Position  = vec4(1, 1, 0, 1);\n"
3684                                                                   "    EmitVertex();\n"
3685                                                                   "}\n"
3686                                                                   "\n";
3687
3688         std::string result = source;
3689
3690         return result;
3691 }
3692
3693 /** Check if R32I texture is filled with 4x4 regions of increasing values <0:15>
3694  *
3695  * @param texture_0       Verified texture
3696  * @param ignored
3697  * @param ignored
3698  *
3699  * @return True if texture_0 is filled with expected pattern
3700  **/
3701 bool DrawMultipleLayers::checkResults(Utils::texture& texture_0, Utils::texture& /* texture_1 */,
3702                                                                           GLuint /* draw_call_index */)
3703 {
3704         static const GLuint layer_size = m_width * m_height;
3705
3706         bool check_result = true;
3707
3708         std::vector<GLint> texture_data;
3709         texture_data.resize(layer_size * m_depth);
3710         texture_0.get(GL_RED_INTEGER, GL_INT, &texture_data[0]);
3711
3712         /* 16 layers, only region corresponding with layer index should be modified */
3713         for (GLuint layer = 0; layer < m_depth; ++layer)
3714         {
3715                 GLuint index = 0;
3716
3717                 for (GLuint y = 0; y < 4; ++y)
3718                 {
3719                         for (GLuint x = 0; x < 4; ++x)
3720                         {
3721                                 GLint* layer_data = &texture_data[layer * layer_size];
3722
3723                                 GLint expected_value = -1;
3724                                 if (index == layer)
3725                                 {
3726                                         expected_value = index;
3727                                 }
3728
3729                                 bool result = checkRegionR32I(x, y, expected_value, layer_data);
3730
3731                                 if (false == result)
3732                                 {
3733                                         check_result = false;
3734                                         goto end;
3735                                 }
3736
3737                                 index += 1;
3738                         }
3739                 }
3740         }
3741
3742 end:
3743         return check_result;
3744 }
3745
3746 /** Prepare textures used as framebuffer's attachments for current draw call
3747  *
3748  * @param texture_0 R32I texture
3749  * @param ignored
3750  **/
3751 void DrawMultipleLayers::prepareTextures(Utils::texture& texture_0, Utils::texture& /* texture_1 */)
3752 {
3753         prepareTextureArrayR32I(texture_0);
3754 }
3755
3756 /** Constructor
3757  *
3758  * @param context          Test context
3759  * @param test_name        Test name
3760  * @param test_description Test description
3761  **/
3762 Scissor::Scissor(deqp::Context& context, const glcts::ExtParameters& extParams)
3763         : DrawMultipleLayers(context, extParams, "scissor", "Test verifies that scissor test is applied as expected")
3764 {
3765         /* Nothing to be done here */
3766 }
3767
3768 /** Get test type
3769  *
3770  * @return SCISSOR
3771  **/
3772 DrawTestBase::TEST_TYPE Scissor::getTestType()
3773 {
3774         return SCISSOR;
3775 }
3776
3777 /** Constructor
3778  *
3779  * @param context          Test context
3780  * @param test_name        Test name
3781  * @param test_description Test description
3782  **/
3783 ScissorZeroDimension::ScissorZeroDimension(deqp::Context& context, const glcts::ExtParameters& extParams)
3784         : DrawMultipleLayers(context, extParams, "scissor_zero_dimension",
3785                                                  "Test verifies that scissor test discard all fragments when width and height is set to zero")
3786 {
3787         /* Nothing to be done here */
3788 }
3789
3790 /** Check if R32I texture is filled with 4x4 regions of increasing values <0:15>
3791  *
3792  * @param texture_0       Verified texture
3793  * @param ignored
3794  * @param ignored
3795  *
3796  * @return True if texture_0 is filled with expected pattern
3797  **/
3798 bool ScissorZeroDimension::checkResults(Utils::texture& texture_0, Utils::texture& /* texture_1 */,
3799                                                                                 GLuint /* draw_call_index */)
3800 {
3801         static const GLuint layer_size = m_width * m_height;
3802
3803         bool check_result = true;
3804
3805         std::vector<GLint> texture_data;
3806         texture_data.resize(layer_size * m_depth);
3807         texture_0.get(GL_RED_INTEGER, GL_INT, &texture_data[0]);
3808
3809         /* 16 layers, all regions were not modified */
3810         for (GLuint layer = 0; layer < m_depth; ++layer)
3811         {
3812                 for (GLuint y = 0; y < 4; ++y)
3813                 {
3814                         for (GLuint x = 0; x < 4; ++x)
3815                         {
3816                                 GLint* layer_data = &texture_data[layer * layer_size];
3817
3818                                 GLint expected_value = -1;
3819
3820                                 bool result = checkRegionR32I(x, y, expected_value, layer_data);
3821
3822                                 if (false == result)
3823                                 {
3824                                         check_result = false;
3825                                         goto end;
3826                                 }
3827                         }
3828                 }
3829         }
3830
3831 end:
3832         return check_result;
3833 }
3834
3835 /** Get test type
3836  *
3837  * @return SCISSOR
3838  **/
3839 DrawTestBase::TEST_TYPE ScissorZeroDimension::getTestType()
3840 {
3841         return SCISSOR;
3842 }
3843
3844 /** Set up viewports
3845  *
3846  * @param Ignored
3847  * @param iteration_index Index of iteration for given test type
3848  **/
3849 void ScissorZeroDimension::setupViewports(TEST_TYPE /* type */, GLuint iteration_index)
3850 {
3851         SCISSOR_METHOD method;
3852         switch (iteration_index)
3853         {
3854         case 0:
3855         case 1:
3856         case 2:
3857                 method = (SCISSOR_METHOD)iteration_index;
3858                 break;
3859         default:
3860                 TCU_FAIL("Invalid value");
3861         }
3862
3863         setup4x4Scissor(method, true /* set_zeros */);
3864 }
3865
3866 /** Constructor
3867  *
3868  * @param context          Test context
3869  * @param test_name        Test name
3870  * @param test_description Test description
3871  **/
3872 ScissorClear::ScissorClear(deqp::Context& context, const glcts::ExtParameters& extParams)
3873         : DrawMultipleLayers(context, extParams, "scissor_clear",
3874                                                  "Test verifies that Clear is affected only by settings of scissor test in first viewport")
3875 {
3876         /* Nothing to be done here */
3877 }
3878
3879 /** Check if R32I texture is filled with 4x4 regions of increasing values <0:15>
3880  *
3881  * @param texture_0 Verified texture
3882  * @param ignored
3883  * @param ignored
3884  *
3885  * @return True if texture_0 is filled with expected pattern
3886  **/
3887 bool ScissorClear::checkResults(Utils::texture& texture_0, Utils::texture& /* texture_1 */, GLuint /*draw_call_index */)
3888 {
3889         static const GLuint layer_size = m_width * m_height;
3890
3891         bool check_result = true;
3892
3893         std::vector<GLint> texture_data;
3894         texture_data.resize(layer_size * m_depth);
3895         texture_0.get(GL_RED_INTEGER, GL_INT, &texture_data[0]);
3896
3897         /* 16 layers, only region corresponding with scissor box 0 should be modified */
3898         for (GLuint layer = 0; layer < m_depth; ++layer)
3899         {
3900                 for (GLuint y = 0; y < 4; ++y)
3901                 {
3902                         for (GLuint x = 0; x < 4; ++x)
3903                         {
3904                                 GLint* layer_data = &texture_data[layer * layer_size];
3905
3906                                 GLint expected_value = -1;
3907                                 if ((0 == x) && (0 == y))
3908                                 {
3909                                         expected_value = 0;
3910                                 }
3911
3912                                 bool result = checkRegionR32I(x, y, expected_value, layer_data);
3913
3914                                 if (false == result)
3915                                 {
3916                                         check_result = false;
3917                                         goto end;
3918                                 }
3919                         }
3920                 }
3921         }
3922
3923 end:
3924         return check_result;
3925 }
3926
3927 /** Get test type
3928  *
3929  * @return SCISSOR
3930  **/
3931 DrawTestBase::TEST_TYPE ScissorClear::getTestType()
3932 {
3933         return SCISSOR;
3934 }
3935
3936 /** Selects if test should do draw or clear operation
3937  *
3938  * @return true - clear operation
3939  **/
3940 bool ScissorClear::isClearTest()
3941 {
3942         return true;
3943 }
3944
3945 /** Constructor
3946  *
3947  * @param context          Test context
3948  * @param test_name        Test name
3949  * @param test_description Test description
3950  **/
3951 DepthRange::DepthRange(deqp::Context& context, const glcts::ExtParameters& extParams)
3952         : DrawTestBase(context, extParams, "depth_range", "Test verifies that depth range is applied as expected")
3953 {
3954         /* Nothing to be done here */
3955 }
3956
3957 /** Check if R32F texture is filled with two rows, top with decreasing values, bottom with incresing values
3958  *
3959  * @param texture_0 Verified texture
3960  * @param ignored
3961  * @param ignored
3962  *
3963  * @return True if texture_0 is filled with expected pattern
3964  **/
3965 bool DepthRange::checkResults(Utils::texture& texture_0, Utils::texture& /* texture_1 */, GLuint /*draw_call_index */)
3966 {
3967         static const GLfloat step = 1.0f / 16.0f;
3968
3969         bool check_result = true;
3970
3971         std::vector<GLfloat> texture_data;
3972         texture_data.resize(m_r32f_width * m_r32f_height);
3973         texture_0.get(GL_RED, GL_FLOAT, &texture_data[0]);
3974
3975         GLfloat depth_data[16 * 2];
3976
3977         for (GLuint i = 0; i < 16; ++i)
3978         {
3979                 const GLfloat near = step * (GLfloat)i;
3980
3981                 depth_data[i * 2 + 0] = near;
3982                 depth_data[i * 2 + 1] = 1.0f - near;
3983         }
3984
3985         for (GLuint i = 0; i < 16; ++i)
3986         {
3987                 const GLfloat expected_near = depth_data[i * 2 + 0];
3988                 const GLfloat expected_far  = depth_data[i * 2 + 1];
3989
3990                 /* Bottom row should contain near values, top one should contain far values */
3991                 const GLfloat near = texture_data[i];
3992                 const GLfloat far  = texture_data[i + 16];
3993
3994                 if ((expected_near != near) || (expected_far != far))
3995                 {
3996                         m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid values at " << i << " expected ["
3997                                                                                                 << expected_near << ", " << expected_far << "] got [" << near << ", "
3998                                                                                                 << far << "]" << tcu::TestLog::EndMessage;
3999
4000                         check_result = false;
4001                         break;
4002                 }
4003         }
4004
4005         return check_result;
4006 }
4007
4008 /** Get string with fragment shader source code
4009  *
4010  * @return Fragment shader source
4011  **/
4012 std::string DepthRange::getFragmentShader()
4013 {
4014         static const GLchar* source = "#version 410 core\n"
4015                                                                   "\n"
4016                                                                   "out float fs_out_color;\n"
4017                                                                   "\n"
4018                                                                   "void main()\n"
4019                                                                   "{\n"
4020                                                                   "    fs_out_color = gl_FragCoord.z;\n"
4021                                                                   "}\n"
4022                                                                   "\n";
4023
4024         std::string result = source;
4025
4026         return result;
4027 }
4028
4029 /** Get string with geometry shader source code
4030  *
4031  * @return Geometry shader source
4032  **/
4033 std::string DepthRange::getGeometryShader()
4034 {
4035         static const GLchar* source = "#version 410 core\n"
4036                                                                   "\n"
4037                                                                   "layout(points, invocations = 16)         in;\n"
4038                                                                   "layout(triangle_strip, max_vertices = 8) out;\n"
4039                                                                   "\n"
4040                                                                   "void main()\n"
4041                                                                   "{\n"
4042                                                                   "    const float top_z    = 1.0;\n"
4043                                                                   "    const float bottom_z = -1.0;\n"
4044                                                                   "\n"
4045                                                                   "    /* Bottom */\n"
4046                                                                   "    gl_ViewportIndex = gl_InvocationID;\n"
4047                                                                   "    gl_Position  = vec4(-1, -1, bottom_z, 1);\n"
4048                                                                   "    EmitVertex();\n"
4049                                                                   "    gl_ViewportIndex = gl_InvocationID;\n"
4050                                                                   "    gl_Position  = vec4(-1, 0, bottom_z, 1);\n"
4051                                                                   "    EmitVertex();\n"
4052                                                                   "    gl_ViewportIndex = gl_InvocationID;\n"
4053                                                                   "    gl_Position  = vec4(1, -1, bottom_z, 1);\n"
4054                                                                   "    EmitVertex();\n"
4055                                                                   "    gl_ViewportIndex = gl_InvocationID;\n"
4056                                                                   "    gl_Position  = vec4(1, 0, bottom_z, 1);\n"
4057                                                                   "    EmitVertex();\n"
4058                                                                   "    EndPrimitive();\n"
4059                                                                   "\n"
4060                                                                   "    /* Top */\n"
4061                                                                   "    gl_ViewportIndex = gl_InvocationID;\n"
4062                                                                   "    gl_Position  = vec4(-1, 0, top_z, 1);\n"
4063                                                                   "    EmitVertex();\n"
4064                                                                   "    gl_ViewportIndex = gl_InvocationID;\n"
4065                                                                   "    gl_Position  = vec4(-1, 1, top_z, 1);\n"
4066                                                                   "    EmitVertex();\n"
4067                                                                   "    gl_ViewportIndex = gl_InvocationID;\n"
4068                                                                   "    gl_Position  = vec4(1, 0, top_z, 1);\n"
4069                                                                   "    EmitVertex();\n"
4070                                                                   "    gl_ViewportIndex = gl_InvocationID;\n"
4071                                                                   "    gl_Position  = vec4(1, 1, top_z, 1);\n"
4072                                                                   "    EmitVertex();\n"
4073                                                                   "    EndPrimitive();\n"
4074                                                                   "}\n"
4075                                                                   "\n";
4076
4077         std::string result = source;
4078
4079         return result;
4080 }
4081
4082 /** Get test type
4083  *
4084  * @return DEPTHRANGE
4085  **/
4086 DrawTestBase::TEST_TYPE DepthRange::getTestType()
4087 {
4088         return DEPTHRANGE;
4089 }
4090
4091 /** Prepare textures used as framebuffer's attachments for current draw call
4092  *
4093  * @param texture_0 R32F texture
4094  * @param ignored
4095  **/
4096 void DepthRange::prepareTextures(Utils::texture& texture_0, Utils::texture& /* texture_1 */)
4097 {
4098         prepareTextureR32F(texture_0);
4099 }
4100
4101 /** Constructor
4102  *
4103  * @param context          Test context
4104  * @param test_name        Test name
4105  * @param test_description Test description
4106  **/
4107 DepthRangeDepthTest::DepthRangeDepthTest(deqp::Context& context, const glcts::ExtParameters& extParams)
4108         : DrawTestBase(context, extParams, "depth_range_depth_test",
4109                                    "Test verifies that depth test work as expected with multiple viewports")
4110 {
4111         /* Nothing to be done here */
4112 }
4113
4114 /** Check if R32F texture is filled with two rows of values less than expected depth
4115  *
4116  * @param texture_0       Verified texture
4117  * @param ignored
4118  * @param draw_call_index Index of draw call
4119  *
4120  * @return True if texture_0 is filled with expected pattern
4121  **/
4122 bool DepthRangeDepthTest::checkResults(Utils::texture& texture_0, Utils::texture& /* texture_1 */,
4123                                                                            GLuint                  draw_call_index)
4124 {
4125         static const GLfloat step = 1.0f / 16.0f;
4126
4127         const GLfloat depth_value = step * (GLfloat)draw_call_index;
4128
4129         bool check_result = true;
4130
4131         std::vector<GLfloat> texture_data;
4132         texture_data.resize(m_r32f_width * m_r32f_height);
4133         texture_0.get(GL_RED, GL_FLOAT, &texture_data[0]);
4134
4135         for (GLuint i = 0; i < 16; ++i)
4136         {
4137                 /* Bottom row should contain near values, top one should contain far values */
4138                 const GLfloat near = texture_data[i];
4139                 const GLfloat far  = texture_data[i + 16];
4140
4141                 if ((depth_value <= near) || (depth_value <= far))
4142                 {
4143                         m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid values at " << i << " depth value "
4144                                                                                                 << depth_value << " got [" << near << ", " << far << "]"
4145                                                                                                 << tcu::TestLog::EndMessage;
4146
4147                         check_result = false;
4148                         break;
4149                 }
4150         }
4151
4152         return check_result;
4153 }
4154
4155 /** Get settings of clear operation
4156  *
4157  * @param clear_depth_before_draw Selects if clear should be executed before draw.
4158  * @param iteration_index         Index of draw call
4159  * @param depth_value             Value that will be used to clear depth buffer
4160  **/
4161 void DepthRangeDepthTest::getClearSettings(bool& clear_depth_before_draw, GLuint iteration_index, GLdouble& depth_value)
4162 {
4163         static const GLdouble step = 1.0 / 16.0;
4164
4165         clear_depth_before_draw = true;
4166
4167         depth_value = step * (GLdouble)iteration_index;
4168 }
4169
4170 /** Get number of draw call to be executed during test
4171  *
4172  * @return 18
4173  **/
4174 GLuint DepthRangeDepthTest::getDrawCallsNumber()
4175 {
4176         return 18;
4177 }
4178
4179 /** Get string with fragment shader source code
4180  *
4181  * @return Fragment shader source
4182  **/
4183 std::string DepthRangeDepthTest::getFragmentShader()
4184 {
4185         static const GLchar* source = "#version 410 core\n"
4186                                                                   "\n"
4187                                                                   "out float fs_out_color;\n"
4188                                                                   "\n"
4189                                                                   "void main()\n"
4190                                                                   "{\n"
4191                                                                   "    fs_out_color = gl_FragCoord.z;\n"
4192                                                                   "}\n"
4193                                                                   "\n";
4194
4195         std::string result = source;
4196
4197         return result;
4198 }
4199
4200 /** Get string with geometry shader source code
4201  *
4202  * @return Geometry shader source
4203  **/
4204 std::string DepthRangeDepthTest::getGeometryShader()
4205 {
4206         static const GLchar* source = "#version 410 core\n"
4207                                                                   "\n"
4208                                                                   "layout(points, invocations = 16)         in;\n"
4209                                                                   "layout(triangle_strip, max_vertices = 8) out;\n"
4210                                                                   "\n"
4211                                                                   "void main()\n"
4212                                                                   "{\n"
4213                                                                   "    const float top_z    = 1.0;\n"
4214                                                                   "    const float bottom_z = -1.0;\n"
4215                                                                   "\n"
4216                                                                   "    /* Bottom */\n"
4217                                                                   "    gl_ViewportIndex = gl_InvocationID;\n"
4218                                                                   "    gl_Position  = vec4(-1, -1, bottom_z, 1);\n"
4219                                                                   "    EmitVertex();\n"
4220                                                                   "    gl_ViewportIndex = gl_InvocationID;\n"
4221                                                                   "    gl_Position  = vec4(-1, 0, bottom_z, 1);\n"
4222                                                                   "    EmitVertex();\n"
4223                                                                   "    gl_ViewportIndex = gl_InvocationID;\n"
4224                                                                   "    gl_Position  = vec4(1, -1, bottom_z, 1);\n"
4225                                                                   "    EmitVertex();\n"
4226                                                                   "    gl_ViewportIndex = gl_InvocationID;\n"
4227                                                                   "    gl_Position  = vec4(1, 0, bottom_z, 1);\n"
4228                                                                   "    EmitVertex();\n"
4229                                                                   "\n"
4230                                                                   "    /* Top */\n"
4231                                                                   "    gl_ViewportIndex = gl_InvocationID;\n"
4232                                                                   "    gl_Position  = vec4(-1, 0, top_z, 1);\n"
4233                                                                   "    EmitVertex();\n"
4234                                                                   "    gl_ViewportIndex = gl_InvocationID;\n"
4235                                                                   "    gl_Position  = vec4(-1, 1, top_z, 1);\n"
4236                                                                   "    EmitVertex();\n"
4237                                                                   "    gl_ViewportIndex = gl_InvocationID;\n"
4238                                                                   "    gl_Position  = vec4(1, 0, top_z, 1);\n"
4239                                                                   "    EmitVertex();\n"
4240                                                                   "    gl_ViewportIndex = gl_InvocationID;\n"
4241                                                                   "    gl_Position  = vec4(1, 1, top_z, 1);\n"
4242                                                                   "    EmitVertex();\n"
4243                                                                   "    EndPrimitive();\n"
4244                                                                   "}\n"
4245                                                                   "\n";
4246
4247         std::string result = source;
4248
4249         return result;
4250 }
4251
4252 /** Get test type
4253  *
4254  * @return DEPTHRANGE
4255  **/
4256 DrawTestBase::TEST_TYPE DepthRangeDepthTest::getTestType()
4257 {
4258         return DEPTHRANGE;
4259 }
4260
4261 /** Prepare textures used as framebuffer's attachments for current draw call
4262  *
4263  * @param texture_0 R32F texture
4264  * @param texture_1 D32F texture
4265  **/
4266 void DepthRangeDepthTest::prepareTextures(Utils::texture& texture_0, Utils::texture& texture_1)
4267 {
4268         prepareTextureR32F(texture_0);
4269         prepareTextureD32F(texture_1);
4270 }
4271
4272 /** Attach textures to framebuffer
4273  *
4274  * @param framebuffer Framebuffer instance
4275  * @param texture_0   Texture attached as color 0
4276  * @param texture_1   Texture attached as depth
4277  **/
4278 void DepthRangeDepthTest::setupFramebuffer(Utils::framebuffer& framebuffer, Utils::texture& texture_0,
4279                                                                                    Utils::texture& texture_1)
4280 {
4281         framebuffer.attachTexture(GL_COLOR_ATTACHMENT0, texture_0.m_id, m_width, m_height);
4282         framebuffer.attachTexture(GL_DEPTH_ATTACHMENT, texture_1.m_id, m_width, m_height);
4283 }
4284
4285 /** Set up viewports
4286  *
4287  * @param ignored
4288  * @param iteration_index Index of iteration for given test type
4289  **/
4290 void DepthRangeDepthTest::setupViewports(TEST_TYPE /* type */, GLuint iteration_index)
4291 {
4292         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4293
4294         DEPTH_RANGE_METHOD method;
4295         switch (iteration_index)
4296         {
4297         case 0:
4298         case 1:
4299                 method = (DEPTH_RANGE_METHOD)iteration_index;
4300                 break;
4301         default:
4302                 TCU_FAIL("Invalid value");
4303         }
4304         setup16x2Depths(method);
4305
4306         gl.enable(GL_DEPTH_TEST);
4307         GLU_EXPECT_NO_ERROR(gl.getError(), "Enable");
4308 }
4309
4310 /** Constructor
4311  *
4312  * @param context          Test context
4313  * @param test_name        Test name
4314  * @param test_description Test description
4315  **/
4316 ProvokingVertex::ProvokingVertex(deqp::Context& context, const glcts::ExtParameters& extParams)
4317         : DrawTestBase(context, extParams, "provoking_vertex", "Test verifies that provoking vertex work as expected")
4318 {
4319         /* Nothing to be done here */
4320 }
4321
4322 /** Check if R32I texture is filled with 4x4 regions of increasing values <0:15>
4323  *
4324  * @param texture_0 Verified texture
4325  * @param ignored
4326  * @param ignored
4327  *
4328  * @return True if texture_0 is filled with expected pattern
4329  **/
4330 bool ProvokingVertex::checkResults(Utils::texture& texture_0, Utils::texture& /* texture_1 */,
4331                                                                    GLuint /*draw_call_index */)
4332 {
4333         static const GLuint layer_size = m_width * m_height;
4334
4335         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4336
4337         GLint layer_mode        = 0;
4338         GLint viewport_mode = 0;
4339         gl.getIntegerv(GL_LAYER_PROVOKING_VERTEX, &layer_mode);
4340         GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
4341         gl.getIntegerv(GL_VIEWPORT_INDEX_PROVOKING_VERTEX, &viewport_mode);
4342         GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
4343
4344         if ((GL_UNDEFINED_VERTEX == layer_mode) || (GL_UNDEFINED_VERTEX == viewport_mode))
4345         {
4346                 /* Results are undefined, therefore it does not make sense to verify them */
4347                 return true;
4348         }
4349
4350         bool  check_result = true;
4351         GLint provoking = 0;
4352
4353         std::vector<GLint> texture_data;
4354         texture_data.resize(layer_size * m_r32ix4_depth);
4355         texture_0.get(GL_RED_INTEGER, GL_INT, &texture_data[0]);
4356
4357         gl.getIntegerv(GL_PROVOKING_VERTEX, &provoking);
4358         GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
4359
4360         GLuint expected_layer   = 0;
4361         GLint  expected_viewport = 0;
4362
4363         /* Mode is 1st, or mode is provoking and provoking is 1st */
4364         if ((GL_FIRST_VERTEX_CONVENTION == layer_mode) ||
4365                 ((GL_PROVOKING_VERTEX == layer_mode) && (GL_FIRST_VERTEX_CONVENTION == provoking)))
4366         {
4367                 expected_layer = 0;
4368         }
4369         else
4370         {
4371                 expected_layer = 2;
4372         }
4373
4374         if ((GL_FIRST_VERTEX_CONVENTION == viewport_mode) ||
4375                 ((GL_PROVOKING_VERTEX == viewport_mode) && (GL_FIRST_VERTEX_CONVENTION == provoking)))
4376         {
4377                 expected_viewport = 0;
4378         }
4379         else
4380         {
4381                 expected_viewport = 2;
4382         }
4383
4384         for (GLuint layer = 0; layer < m_r32ix4_depth; ++layer)
4385         {
4386                 GLint* layer_data = &texture_data[layer * layer_size];
4387                 GLint  viewport   = 0;
4388
4389                 for (GLuint y = 0; y < 2; ++y)
4390                 {
4391                         for (GLuint x = 0; x < 2; ++x)
4392                         {
4393                                 /* If layer and viewport are expected ones, than result shall be 1, otherwise -1. */
4394                                 const GLint expected_value = ((expected_viewport == viewport) && (expected_layer == layer)) ? 1 : -1;
4395
4396                                 bool result = checkRegionR32I(x, y, m_width / 2, m_height / 2, expected_value, layer_data);
4397
4398                                 if (false == result)
4399                                 {
4400                                         check_result = false;
4401                                         goto end;
4402                                 }
4403
4404                                 viewport += 1;
4405                         }
4406                 }
4407         }
4408
4409 end:
4410         return check_result;
4411 }
4412
4413 /** Get string with fragment shader source code
4414  *
4415  * @return Fragment shader source
4416  **/
4417 std::string ProvokingVertex::getFragmentShader()
4418 {
4419         static const GLchar* source = "#version 410 core\n"
4420                                                                   "\n"
4421                                                                   "flat in  int gs_fs_color;\n"
4422                                                                   "     out int fs_out_color;\n"
4423                                                                   "\n"
4424                                                                   "void main()\n"
4425                                                                   "{\n"
4426                                                                   "    fs_out_color = gs_fs_color;\n"
4427                                                                   "}\n"
4428                                                                   "\n";
4429
4430         std::string result = source;
4431
4432         return result;
4433 }
4434
4435 /** Get string with geometry shader source code
4436  *
4437  * @return Geometry shader source
4438  **/
4439 std::string ProvokingVertex::getGeometryShader()
4440 {
4441         static const GLchar* source = "#version 410 core\n"
4442                                                                   "\n"
4443                                                                   "layout(points, invocations = 1)          in;\n"
4444                                                                   "layout(triangle_strip, max_vertices = 6) out;\n"
4445                                                                   "\n"
4446                                                                   "flat out int gs_fs_color;\n"
4447                                                                   "\n"
4448                                                                   "void main()\n"
4449                                                                   "{\n"
4450                                                                   "    /* Left-bottom half */\n"
4451                                                                   "    gs_fs_color      = 1;\n"
4452                                                                   "    gl_ViewportIndex = 0;\n"
4453                                                                   "    gl_Layer         = 0;\n"
4454                                                                   "    gl_Position  = vec4(-1, -1, 0, 1);\n"
4455                                                                   "    EmitVertex();\n"
4456                                                                   "    gs_fs_color      = 1;\n"
4457                                                                   "    gl_ViewportIndex = 1;\n"
4458                                                                   "    gl_Layer         = 1;\n"
4459                                                                   "    gl_Position  = vec4(-1, 1, 0, 1);\n"
4460                                                                   "    EmitVertex();\n"
4461                                                                   "    gs_fs_color      = 1;\n"
4462                                                                   "    gl_ViewportIndex = 2;\n"
4463                                                                   "    gl_Layer         = 2;\n"
4464                                                                   "    gl_Position  = vec4(1, -1, 0, 1);\n"
4465                                                                   "    EmitVertex();\n"
4466                                                                   "    EndPrimitive();\n"
4467                                                                   "\n"
4468                                                                   "    /* Right-top half */\n"
4469                                                                   "    gs_fs_color      = 1;\n"
4470                                                                   "    gl_ViewportIndex = 0;\n"
4471                                                                   "    gl_Layer         = 0;\n"
4472                                                                   "    gl_Position  = vec4(-1, 1, 0, 1);\n"
4473                                                                   "    EmitVertex();\n"
4474                                                                   "    gs_fs_color      = 1;\n"
4475                                                                   "    gl_ViewportIndex = 1;\n"
4476                                                                   "    gl_Layer         = 1;\n"
4477                                                                   "    gl_Position  = vec4(1, 1, 0, 1);\n"
4478                                                                   "    EmitVertex();\n"
4479                                                                   "    gs_fs_color      = 1;\n"
4480                                                                   "    gl_ViewportIndex = 2;\n"
4481                                                                   "    gl_Layer         = 2;\n"
4482                                                                   "    gl_Position  = vec4(1, -1, 0, 1);\n"
4483                                                                   "    EmitVertex();\n"
4484                                                                   "    EndPrimitive();\n"
4485                                                                   "}\n"
4486                                                                   "\n";
4487
4488         std::string result = source;
4489
4490         return result;
4491 }
4492
4493 /** Get test type
4494  *
4495  * @return PROVOKING
4496  **/
4497 DrawTestBase::TEST_TYPE ProvokingVertex::getTestType()
4498 {
4499         return PROVOKING;
4500 }
4501
4502 /** Prepare textures used as framebuffer's attachments for current draw call
4503  *
4504  * @param texture_0 R32I texture
4505  * @param ignored
4506  **/
4507 void ProvokingVertex::prepareTextures(Utils::texture& texture_0, Utils::texture& /* texture_1 */)
4508 {
4509         prepareTextureR32Ix4(texture_0);
4510 }
4511
4512 } /* ViewportArray namespace */
4513
4514 /** Constructor.
4515  *
4516  *  @param context Rendering context.
4517  **/
4518 ViewportArrayTests::ViewportArrayTests(deqp::Context& context, const glcts::ExtParameters& extParams)
4519         : TestCaseGroupBase(context, extParams, "viewport_array", "Verifies \"viewport_array\" functionality")
4520 {
4521         /* Left blank on purpose */
4522 }
4523
4524 /** Initializes a texture_storage_multisample test group.
4525  *
4526  **/
4527 void ViewportArrayTests::init(void)
4528 {
4529         addChild(new ViewportArray::APIErrors(m_context, m_extParams));
4530         addChild(new ViewportArray::Queries(m_context, m_extParams));
4531         addChild(new ViewportArray::ViewportAPI(m_context, m_extParams));
4532         addChild(new ViewportArray::ScissorAPI(m_context, m_extParams));
4533         addChild(new ViewportArray::DepthRangeAPI(m_context, m_extParams));
4534         addChild(new ViewportArray::ScissorTestStateAPI(m_context, m_extParams));
4535         addChild(new ViewportArray::DrawToSingleLayerWithMultipleViewports(m_context, m_extParams));
4536         addChild(new ViewportArray::DynamicViewportIndex(m_context, m_extParams));
4537         addChild(new ViewportArray::DrawMulitpleViewportsWithSingleInvocation(m_context, m_extParams));
4538         addChild(new ViewportArray::ViewportIndexSubroutine(m_context, m_extParams));
4539         addChild(new ViewportArray::DrawMultipleLayers(m_context, m_extParams));
4540         addChild(new ViewportArray::Scissor(m_context, m_extParams));
4541         addChild(new ViewportArray::ScissorZeroDimension(m_context, m_extParams));
4542         addChild(new ViewportArray::ScissorClear(m_context, m_extParams));
4543         addChild(new ViewportArray::DepthRange(m_context, m_extParams));
4544         addChild(new ViewportArray::DepthRangeDepthTest(m_context, m_extParams));
4545         addChild(new ViewportArray::ProvokingVertex(m_context, m_extParams));
4546 }
4547
4548 } /* glcts namespace */