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