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