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