1 /*-------------------------------------------------------------------------
2 * OpenGL Conformance Test Suite
3 * -----------------------------
5 * Copyright (c) 2014-2016 The Khronos Group Inc.
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
22 */ /*-------------------------------------------------------------------*/
25 * \file glcViewportArrayTests.cpp
26 * \brief Implements conformance tests for "Viewport Array" functionality.
27 */ /*-------------------------------------------------------------------*/
29 #include "glcViewportArrayTests.hpp"
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"
49 namespace ViewportArray
51 /** Check if extension is supported
53 * @param context Test context
54 * @param extension_name Name of extension
56 * @return true if extension is supported, false otherwise
58 bool Utils::isExtensionSupported(deqp::Context& context, const GLchar* extension_name)
60 const std::vector<std::string>& extensions = context.getContextInfo().getExtensions();
62 if (std::find(extensions.begin(), extensions.end(), extension_name) == extensions.end())
70 /** Check if GL context meets version requirements
73 * @param required_major Minimum required MAJOR_VERSION
74 * @param required_minor Minimum required MINOR_VERSION
76 * @return true if GL context version is at least as requested, false otherwise
78 bool Utils::isGLVersionAtLeast(const glw::Functions& gl, glw::GLint required_major, glw::GLint required_minor)
83 gl.getIntegerv(GL_MAJOR_VERSION, &major);
84 gl.getIntegerv(GL_MINOR_VERSION, &minor);
86 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
88 if (major > required_major)
90 /* Major is higher than required one */
93 else if (major == required_major)
95 if (minor >= required_minor)
97 /* Major is equal to required one */
98 /* Minor is higher than or equal to required one */
103 /* Major is equal to required one */
104 /* Minor is lower than required one */
110 /* Major is lower than required one */
115 /** Replace first occurance of <token> with <text> in <string> starting at <search_posistion>
117 * @param token Token string
118 * @param search_position Position at which find will start, it is updated to position at which replaced text ends
119 * @param text String that will be used as replacement for <token>
120 * @param string String to work on
122 void Utils::replaceToken(const glw::GLchar* token, size_t& search_position, const glw::GLchar* text,
125 const size_t text_length = strlen(text);
126 const size_t token_length = strlen(token);
127 const size_t token_position = string.find(token, search_position);
129 string.replace(token_position, token_length, text, text_length);
131 search_position = token_position + text_length;
134 /** Replace all occurances of <token> with <text> in <string>
136 * @param token Token string
137 * @param text String that will be used as replacement for <token>
138 * @param string String to work on
140 void Utils::replaceAllTokens(const glw::GLchar* token, const glw::GLchar* text, std::string& string)
142 const size_t text_length = strlen(text);
143 const size_t token_length = strlen(token);
145 size_t search_position = 0;
149 const size_t token_position = string.find(token, search_position);
151 if (std::string::npos == token_position)
156 search_position = token_position + text_length;
158 string.replace(token_position, token_length, text, text_length);
164 * @param context CTS context.
166 Utils::buffer::buffer(deqp::Context& context) : m_id(0), m_context(context), m_target(0)
173 Utils::buffer::~buffer()
177 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
179 gl.deleteBuffers(1, &m_id);
184 /** Execute BindBuffer
187 void Utils::buffer::bind() const
189 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
191 gl.bindBuffer(m_target, m_id);
192 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
195 /** Execute BindBufferRange
197 * @param index <index> parameter
198 * @param offset <offset> parameter
199 * @param size <size> parameter
201 void Utils::buffer::bindRange(glw::GLuint index, glw::GLintptr offset, glw::GLsizeiptr size)
203 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
205 gl.bindBufferRange(m_target, index, m_id, offset, size);
206 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBufferRange");
209 /** Execute GenBuffer
211 * @param target Target that will be used by this buffer
213 void Utils::buffer::generate(glw::GLenum target)
215 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
219 gl.genBuffers(1, &m_id);
220 GLU_EXPECT_NO_ERROR(gl.getError(), "GenBuffers");
223 /** Maps buffer content
225 * @param access Access rights for mapped region
227 * @return Mapped memory
229 void* Utils::buffer::map(GLenum access) const
231 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
233 gl.bindBuffer(m_target, m_id);
234 GLU_EXPECT_NO_ERROR(gl.getError(), "bindBuffer");
236 void* result = gl.mapBuffer(m_target, access);
237 GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
245 void Utils::buffer::unmap() const
247 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
249 gl.bindBuffer(m_target, m_id);
250 GLU_EXPECT_NO_ERROR(gl.getError(), "bindBuffer");
252 gl.unmapBuffer(m_target);
253 GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer");
256 /** Execute BufferData
258 * @param size <size> parameter
259 * @param data <data> parameter
260 * @param usage <usage> parameter
262 void Utils::buffer::update(glw::GLsizeiptr size, glw::GLvoid* data, glw::GLenum usage)
264 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
266 gl.bindBuffer(m_target, m_id);
267 GLU_EXPECT_NO_ERROR(gl.getError(), "bindBuffer");
269 gl.bufferData(m_target, size, data, usage);
270 GLU_EXPECT_NO_ERROR(gl.getError(), "bufferData");
275 * @param context CTS context
277 Utils::framebuffer::framebuffer(deqp::Context& context) : m_id(0), m_context(context)
279 /* Nothing to be done here */
285 Utils::framebuffer::~framebuffer()
289 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
291 gl.deleteFramebuffers(1, &m_id);
296 /** Attach texture to specified attachment
298 * @param attachment Attachment
299 * @param texture_id Texture id
300 * @param width Texture width
301 * @param height Texture height
303 void Utils::framebuffer::attachTexture(glw::GLenum attachment, glw::GLuint texture_id, glw::GLuint width,
306 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
310 gl.framebufferTexture(GL_DRAW_FRAMEBUFFER, attachment, texture_id, 0 /* level */);
311 GLU_EXPECT_NO_ERROR(gl.getError(), "FramebufferTexture");
313 gl.viewport(0 /* x */, 0 /* y */, width, height);
314 GLU_EXPECT_NO_ERROR(gl.getError(), "Viewport");
317 /** Binds framebuffer to DRAW_FRAMEBUFFER
320 void Utils::framebuffer::bind()
322 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
324 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, m_id);
325 GLU_EXPECT_NO_ERROR(gl.getError(), "BindFramebuffer");
328 /** Clear framebuffer
330 * @param mask <mask> parameter of glClear. Decides which shall be cleared
332 void Utils::framebuffer::clear(glw::GLenum mask)
334 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
337 GLU_EXPECT_NO_ERROR(gl.getError(), "Clear");
340 /** Specifies clear color
342 * @param red Red channel
343 * @param green Green channel
344 * @param blue Blue channel
345 * @param alpha Alpha channel
347 void Utils::framebuffer::clearColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha)
349 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
351 gl.clearColor(red, green, blue, alpha);
352 GLU_EXPECT_NO_ERROR(gl.getError(), "ClearColor");
355 /** Generate framebuffer
358 void Utils::framebuffer::generate()
360 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
362 gl.genFramebuffers(1, &m_id);
363 GLU_EXPECT_NO_ERROR(gl.getError(), "GenFramebuffers");
366 Utils::shaderCompilationException::shaderCompilationException(const glw::GLchar* source, const glw::GLchar* message)
367 : m_shader_source(source), m_error_message(message)
369 /* Nothing to be done */
372 const char* Utils::shaderCompilationException::what() const throw()
374 return "Shader compilation failed";
377 Utils::programLinkageException::programLinkageException(const glw::GLchar* message) : m_error_message(message)
379 /* Nothing to be done */
382 const char* Utils::programLinkageException::what() const throw()
384 return "Program linking failed";
387 const glw::GLenum Utils::program::ARB_COMPUTE_SHADER = 0x91B9;
391 * @param context CTS context.
393 Utils::program::program(deqp::Context& context)
394 : m_compute_shader_id(0)
395 , m_fragment_shader_id(0)
396 , m_geometry_shader_id(0)
397 , m_program_object_id(0)
398 , m_tesselation_control_shader_id(0)
399 , m_tesselation_evaluation_shader_id(0)
400 , m_vertex_shader_id(0)
403 /* Nothing to be done here */
409 Utils::program::~program()
416 * @param compute_shader_code Compute shader source code
417 * @param fragment_shader_code Fragment shader source code
418 * @param geometry_shader_code Geometry shader source code
419 * @param tesselation_control_shader_code Tesselation control shader source code
420 * @param tesselation_evaluation_shader_code Tesselation evaluation shader source code
421 * @param vertex_shader_code Vertex shader source code
422 * @param varying_names Array of strings containing names of varyings to be captured with transfrom feedback
423 * @param n_varying_names Number of varyings to be captured with transfrom feedback
424 * @param is_separable Selects if monolithis or separable program should be built. Defaults to false
426 void Utils::program::build(const glw::GLchar* compute_shader_code, const glw::GLchar* fragment_shader_code,
427 const glw::GLchar* geometry_shader_code, const glw::GLchar* tesselation_control_shader_code,
428 const glw::GLchar* tesselation_evaluation_shader_code, const glw::GLchar* vertex_shader_code,
429 const glw::GLchar* const* varying_names, glw::GLuint n_varying_names, bool is_separable)
431 /* GL entry points */
432 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
434 /* Create shader objects and compile */
435 if (0 != compute_shader_code)
437 m_compute_shader_id = gl.createShader(ARB_COMPUTE_SHADER);
438 GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader");
440 compile(m_compute_shader_id, compute_shader_code);
443 if (0 != fragment_shader_code)
445 m_fragment_shader_id = gl.createShader(GL_FRAGMENT_SHADER);
446 GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader");
448 compile(m_fragment_shader_id, fragment_shader_code);
451 if (0 != geometry_shader_code)
453 m_geometry_shader_id = gl.createShader(GL_GEOMETRY_SHADER);
454 GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader");
456 compile(m_geometry_shader_id, geometry_shader_code);
459 if (0 != tesselation_control_shader_code)
461 m_tesselation_control_shader_id = gl.createShader(GL_TESS_CONTROL_SHADER);
462 GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader");
464 compile(m_tesselation_control_shader_id, tesselation_control_shader_code);
467 if (0 != tesselation_evaluation_shader_code)
469 m_tesselation_evaluation_shader_id = gl.createShader(GL_TESS_EVALUATION_SHADER);
470 GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader");
472 compile(m_tesselation_evaluation_shader_id, tesselation_evaluation_shader_code);
475 if (0 != vertex_shader_code)
477 m_vertex_shader_id = gl.createShader(GL_VERTEX_SHADER);
478 GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader");
480 compile(m_vertex_shader_id, vertex_shader_code);
483 /* Create program object */
484 m_program_object_id = gl.createProgram();
485 GLU_EXPECT_NO_ERROR(gl.getError(), "CreateProgram");
487 /* Set up captyured varyings' names */
488 if (0 != n_varying_names)
490 gl.transformFeedbackVaryings(m_program_object_id, n_varying_names, varying_names, GL_INTERLEAVED_ATTRIBS);
491 GLU_EXPECT_NO_ERROR(gl.getError(), "TransformFeedbackVaryings");
494 /* Set separable parameter */
495 if (true == is_separable)
497 gl.programParameteri(m_program_object_id, GL_PROGRAM_SEPARABLE, GL_TRUE);
498 GLU_EXPECT_NO_ERROR(gl.getError(), "ProgramParameteri");
505 void Utils::program::compile(GLuint shader_id, const GLchar* source) const
507 /* GL entry points */
508 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
510 /* Compilation status */
511 glw::GLint status = GL_FALSE;
513 /* Set source code */
514 gl.shaderSource(shader_id, 1 /* count */, &source, 0 /* lengths */);
515 GLU_EXPECT_NO_ERROR(gl.getError(), "ShaderSource");
518 gl.compileShader(shader_id);
519 GLU_EXPECT_NO_ERROR(gl.getError(), "CompileShader");
521 /* Get compilation status */
522 gl.getShaderiv(shader_id, GL_COMPILE_STATUS, &status);
523 GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderiv");
525 /* Log compilation error */
526 if (GL_TRUE != status)
528 glw::GLint length = 0;
529 std::vector<glw::GLchar> message;
531 /* Error log length */
532 gl.getShaderiv(shader_id, GL_INFO_LOG_LENGTH, &length);
533 GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderiv");
535 /* Prepare storage */
536 message.resize(length);
539 gl.getShaderInfoLog(shader_id, length, 0, &message[0]);
540 GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderInfoLog");
542 throw shaderCompilationException(source, &message[0]);
546 glw::GLint Utils::program::getAttribLocation(const glw::GLchar* name) const
548 /* GL entry points */
549 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
551 GLint location = gl.getAttribLocation(m_program_object_id, name);
552 GLU_EXPECT_NO_ERROR(gl.getError(), "GetAttribLocation");
557 /** Get subroutine index
559 * @param subroutine_name Subroutine name
561 * @return Index of subroutine
563 GLuint Utils::program::getSubroutineIndex(const glw::GLchar* subroutine_name, glw::GLenum shader_stage) const
565 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
568 index = gl.getSubroutineIndex(m_program_object_id, shader_stage, subroutine_name);
569 GLU_EXPECT_NO_ERROR(gl.getError(), "GetSubroutineIndex");
571 if (GL_INVALID_INDEX == index)
573 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Subroutine: " << subroutine_name
574 << " is not available" << tcu::TestLog::EndMessage;
576 TCU_FAIL("Subroutine is not available");
582 /** Get subroutine uniform location
584 * @param uniform_name Subroutine uniform name
586 * @return Location of subroutine uniform
588 GLint Utils::program::getSubroutineUniformLocation(const glw::GLchar* uniform_name, glw::GLenum shader_stage) const
590 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
593 location = gl.getSubroutineUniformLocation(m_program_object_id, shader_stage, uniform_name);
594 GLU_EXPECT_NO_ERROR(gl.getError(), "GetSubroutineUniformLocation");
598 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Subroutine uniform: " << uniform_name
599 << " is not available" << tcu::TestLog::EndMessage;
601 TCU_FAIL("Subroutine uniform is not available");
607 /** Get uniform location
609 * @param uniform_name Subroutine uniform name
611 * @return Location of uniform
613 GLint Utils::program::getUniformLocation(const glw::GLchar* uniform_name) const
615 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
618 location = gl.getUniformLocation(m_program_object_id, uniform_name);
619 GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformLocation");
623 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Uniform: " << uniform_name
624 << " is not available" << tcu::TestLog::EndMessage;
626 TCU_FAIL("Uniform is not available");
632 /** Attach shaders and link program
635 void Utils::program::link() const
637 /* GL entry points */
638 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
641 glw::GLint status = GL_FALSE;
644 if (0 != m_compute_shader_id)
646 gl.attachShader(m_program_object_id, m_compute_shader_id);
647 GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader");
650 if (0 != m_fragment_shader_id)
652 gl.attachShader(m_program_object_id, m_fragment_shader_id);
653 GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader");
656 if (0 != m_geometry_shader_id)
658 gl.attachShader(m_program_object_id, m_geometry_shader_id);
659 GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader");
662 if (0 != m_tesselation_control_shader_id)
664 gl.attachShader(m_program_object_id, m_tesselation_control_shader_id);
665 GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader");
668 if (0 != m_tesselation_evaluation_shader_id)
670 gl.attachShader(m_program_object_id, m_tesselation_evaluation_shader_id);
671 GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader");
674 if (0 != m_vertex_shader_id)
676 gl.attachShader(m_program_object_id, m_vertex_shader_id);
677 GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader");
681 gl.linkProgram(m_program_object_id);
682 GLU_EXPECT_NO_ERROR(gl.getError(), "LinkProgram");
684 /* Get link status */
685 gl.getProgramiv(m_program_object_id, GL_LINK_STATUS, &status);
686 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramiv");
689 if (GL_TRUE != status)
691 glw::GLint length = 0;
692 std::vector<glw::GLchar> message;
694 /* Get error log length */
695 gl.getProgramiv(m_program_object_id, GL_INFO_LOG_LENGTH, &length);
696 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramiv");
698 message.resize(length);
701 gl.getProgramInfoLog(m_program_object_id, length, 0, &message[0]);
702 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramInfoLog");
704 throw programLinkageException(&message[0]);
708 /** Delete program object and all attached shaders
711 void Utils::program::remove()
713 /* GL entry points */
714 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
716 /* Make sure program object is no longer used by GL */
719 /* Clean program object */
720 if (0 != m_program_object_id)
722 gl.deleteProgram(m_program_object_id);
723 m_program_object_id = 0;
727 if (0 != m_compute_shader_id)
729 gl.deleteShader(m_compute_shader_id);
730 m_compute_shader_id = 0;
733 if (0 != m_fragment_shader_id)
735 gl.deleteShader(m_fragment_shader_id);
736 m_fragment_shader_id = 0;
739 if (0 != m_geometry_shader_id)
741 gl.deleteShader(m_geometry_shader_id);
742 m_geometry_shader_id = 0;
745 if (0 != m_tesselation_control_shader_id)
747 gl.deleteShader(m_tesselation_control_shader_id);
748 m_tesselation_control_shader_id = 0;
751 if (0 != m_tesselation_evaluation_shader_id)
753 gl.deleteShader(m_tesselation_evaluation_shader_id);
754 m_tesselation_evaluation_shader_id = 0;
757 if (0 != m_vertex_shader_id)
759 gl.deleteShader(m_vertex_shader_id);
760 m_vertex_shader_id = 0;
764 /** Execute UseProgram
767 void Utils::program::use() const
769 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
771 gl.useProgram(m_program_object_id);
772 GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
775 void Utils::program::printShaderSource(const GLchar* source, tcu::MessageBuilder& log)
777 GLuint line_number = 0;
779 log << "Shader source.";
781 log << "\nLine||Source\n";
786 const GLchar* next_line = strchr(source, '\n');
791 line.assign(source, next_line - source);
800 log << std::setw(4) << line_number << "||" << line;
810 * @param context CTS context.
812 Utils::texture::texture(deqp::Context& context) : m_id(0), m_context(context), m_is_array(false)
814 /* Nothing to done here */
820 Utils::texture::~texture()
825 /** Bind texture to GL_TEXTURE_2D
828 void Utils::texture::bind() const
830 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
832 if (false == m_is_array)
834 gl.bindTexture(GL_TEXTURE_2D, m_id);
835 GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
839 gl.bindTexture(GL_TEXTURE_2D_ARRAY, m_id);
840 GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
844 /** Create 2d texture
846 * @param width Width of texture
847 * @param height Height of texture
848 * @param internal_format Internal format of texture
850 void Utils::texture::create(GLuint width, GLuint height, GLenum internal_format)
852 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
858 gl.genTextures(1, &m_id);
859 GLU_EXPECT_NO_ERROR(gl.getError(), "GenTextures");
863 gl.texStorage2D(GL_TEXTURE_2D, 1 /* levels */, internal_format, width, height);
864 GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage2D");
867 /** Create 2d texture array
869 * @param width Width of texture
870 * @param height Height of texture
871 * @param depth Depth of texture
872 * @param internal_format Internal format of texture
874 void Utils::texture::create(GLuint width, GLuint height, GLuint depth, GLenum internal_format)
876 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
882 gl.genTextures(1, &m_id);
883 GLU_EXPECT_NO_ERROR(gl.getError(), "GenTextures");
887 gl.texStorage3D(GL_TEXTURE_2D_ARRAY, 1 /* levels */, internal_format, width, height, depth);
888 GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage3D");
891 /** Get contents of texture
893 * @param format Format of image
894 * @param type Type of image
895 * @param out_data Buffer for image
897 void Utils::texture::get(glw::GLenum format, glw::GLenum type, glw::GLvoid* out_data) const
899 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
903 GLenum textarget = GL_TEXTURE_2D;
905 if (true == m_is_array)
907 textarget = GL_TEXTURE_2D_ARRAY;
910 gl.getTexImage(textarget, 0 /* level */, format, type, out_data);
911 GLU_EXPECT_NO_ERROR(gl.getError(), "GetTexImage");
917 void Utils::texture::release()
921 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
923 gl.deleteTextures(1, &m_id);
928 /** Update contents of texture
930 * @param width Width of texture
931 * @param height Height of texture
932 * @param depth Depth of texture
933 * @param format Format of data
934 * @param type Type of data
935 * @param data Buffer with image
937 void Utils::texture::update(glw::GLuint width, glw::GLuint height, glw::GLuint depth, glw::GLenum format,
938 glw::GLenum type, glw::GLvoid* data)
940 static const GLuint level = 0;
942 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
946 if (false == m_is_array)
948 gl.texSubImage2D(GL_TEXTURE_2D, level, 0 /* x */, 0 /* y */, width, height, format, type, data);
949 GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage2D");
953 gl.texSubImage3D(GL_TEXTURE_2D_ARRAY, level, 0 /* x */, 0 /* y */, 0 /* z */, width, height, depth, format,
955 GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage2D");
961 * @param context CTS context.
963 Utils::vertexArray::vertexArray(deqp::Context& context) : m_id(0), m_context(context)
970 Utils::vertexArray::~vertexArray()
974 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
976 gl.deleteVertexArrays(1, &m_id);
982 /** Execute BindVertexArray
985 void Utils::vertexArray::bind()
987 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
989 gl.bindVertexArray(m_id);
990 GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexArray");
993 /** Execute GenVertexArrays
996 void Utils::vertexArray::generate()
998 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1000 gl.genVertexArrays(1, &m_id);
1001 GLU_EXPECT_NO_ERROR(gl.getError(), "GenVertexArrays");
1006 * @param context Test context
1008 APIErrors::APIErrors(deqp::Context& context) : TestCase(context, "api_errors", "Test verifies error generated by API")
1010 /* Nothing to be done here */
1015 * @return tcu::TestNode::CONTINUE after executing test case, tcu::TestNode::STOP otherwise
1017 tcu::TestNode::IterateResult APIErrors::iterate()
1019 /* GL entry points */
1020 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1023 bool test_result = true;
1025 GLint max_viewports = 0;
1026 gl.getIntegerv(GL_MAX_VIEWPORTS, &max_viewports);
1027 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
1030 * * DepthRangeArrayv generates INVALID_VALUE when <first> + <count> is greater
1031 * than or equal to the value of MAX_VIEWPORTS;
1034 std::vector<GLdouble> data;
1035 data.resize(max_viewports * 2 /* near + far */);
1037 for (GLint i = 0; i < max_viewports; ++i)
1040 data[i * 2 + 1] = 1.0;
1043 gl.depthRangeArrayv(0, max_viewports - 1, &data[0]);
1044 checkGLError(GL_NO_ERROR, "depthRangeArrayv, correct parameters", test_result);
1046 gl.depthRangeArrayv(max_viewports, 1, &data[0]);
1047 checkGLError(GL_INVALID_VALUE, "depthRangeArrayv, <first> == GL_MAX_VIEWPORTS", test_result);
1049 gl.depthRangeArrayv(1, max_viewports - 1, &data[0]);
1050 checkGLError(GL_NO_ERROR, "depthRangeArrayv, <first> + <count> == GL_MAX_VIEWPORTS", test_result);
1052 gl.depthRangeArrayv(1, max_viewports, &data[0]);
1053 checkGLError(GL_INVALID_VALUE, "depthRangeArrayv, <first> + <count> > GL_MAX_VIEWPORTS", test_result);
1057 * * DepthRangeIndexed generates INVALID_VALUE when <index> is greater than or
1058 * equal to the value of MAX_VIEWPORTS;
1061 gl.depthRangeIndexed(0 /* index */, 0.0, 1.0);
1062 checkGLError(GL_NO_ERROR, "depthRangeIndexed, <index> == 0", test_result);
1064 gl.depthRangeIndexed(max_viewports - 1 /* index */, 0.0, 1.0);
1065 checkGLError(GL_NO_ERROR, "depthRangeIndexed, <index> == GL_MAX_VIEWPORTS - 1", test_result);
1067 gl.depthRangeIndexed(max_viewports /* index */, 0.0, 1.0);
1068 checkGLError(GL_INVALID_VALUE, "depthRangeIndexed, <index> == GL_MAX_VIEWPORTS", test_result);
1070 gl.depthRangeIndexed(max_viewports + 1 /* index */, 0.0, 1.0);
1071 checkGLError(GL_INVALID_VALUE, "depthRangeIndexed, <index> > GL_MAX_VIEWPORTS", test_result);
1075 * * ViewportArrayv generates INVALID_VALUE when <first> + <count> is greater
1076 * than or equal to the value of MAX_VIEWPORTS;
1079 std::vector<GLfloat> data;
1080 data.resize(max_viewports * 4 /* x + y + w + h */);
1082 for (GLint i = 0; i < max_viewports; ++i)
1084 data[i * 4 + 0] = 0.0f;
1085 data[i * 4 + 1] = 0.0f;
1086 data[i * 4 + 2] = 1.0f;
1087 data[i * 4 + 3] = 1.0f;
1090 gl.viewportArrayv(0, max_viewports - 1, &data[0]);
1091 checkGLError(GL_NO_ERROR, "viewportArrayv, correct parameters", test_result);
1093 gl.viewportArrayv(max_viewports, 1, &data[0]);
1094 checkGLError(GL_INVALID_VALUE, "viewportArrayv, <first> == GL_MAX_VIEWPORTS", test_result);
1096 gl.viewportArrayv(1, max_viewports - 1, &data[0]);
1097 checkGLError(GL_NO_ERROR, "viewportArrayv, <first> + <count> == GL_MAX_VIEWPORTS", test_result);
1099 gl.viewportArrayv(1, max_viewports, &data[0]);
1100 checkGLError(GL_INVALID_VALUE, "viewportArrayv, <first> + <count> > GL_MAX_VIEWPORTS", test_result);
1104 * * ViewportIndexedf and ViewportIndexedfv generate INVALID_VALUE when <index>
1105 * is greater than or equal to the value of MAX_VIEWPORTS;
1108 GLfloat data[4 /* x + y + w + h */];
1115 gl.viewportIndexedf(0 /* index */, 0.0f, 0.0f, 1.0f, 1.0f);
1116 checkGLError(GL_NO_ERROR, "viewportIndexedf, <index> == 0", test_result);
1118 gl.viewportIndexedf(max_viewports - 1 /* index */, 0.0f, 0.0f, 1.0f, 1.0f);
1119 checkGLError(GL_NO_ERROR, "viewportIndexedf, <index> == GL_MAX_VIEWPORTS - 1", test_result);
1121 gl.viewportIndexedf(max_viewports /* index */, 0.0f, 0.0f, 1.0f, 1.0f);
1122 checkGLError(GL_INVALID_VALUE, "viewportIndexedf, <index> == GL_MAX_VIEWPORTS", test_result);
1124 gl.viewportIndexedf(max_viewports + 1 /* index */, 0.0f, 0.0f, 1.0f, 1.0f);
1125 checkGLError(GL_INVALID_VALUE, "viewportIndexedf, <index> > GL_MAX_VIEWPORTS", test_result);
1127 gl.viewportIndexedfv(0 /* index */, data);
1128 checkGLError(GL_NO_ERROR, "viewportIndexedfv, <index> == 0", test_result);
1130 gl.viewportIndexedfv(max_viewports - 1 /* index */, data);
1131 checkGLError(GL_NO_ERROR, "viewportIndexedfv, <index> == GL_MAX_VIEWPORTS - 1", test_result);
1133 gl.viewportIndexedfv(max_viewports /* index */, data);
1134 checkGLError(GL_INVALID_VALUE, "viewportIndexedfv, <index> == GL_MAX_VIEWPORTS", test_result);
1136 gl.viewportIndexedfv(max_viewports + 1 /* index */, data);
1137 checkGLError(GL_INVALID_VALUE, "viewportIndexedfv, <index> > GL_MAX_VIEWPORTS", test_result);
1141 * * ViewportArrayv, Viewport, ViewportIndexedf and ViewportIndexedfv generate
1142 * INVALID_VALUE when <w> or <h> values are negative;
1145 gl.viewport(0, 0, -1, 1);
1146 checkGLError(GL_INVALID_VALUE, "viewport, negative width", test_result);
1148 gl.viewport(0, 0, 1, -1);
1149 checkGLError(GL_INVALID_VALUE, "viewport, negative height", test_result);
1151 for (GLint i = 0; i < max_viewports; ++i)
1153 std::vector<GLfloat> data;
1154 data.resize(max_viewports * 4 /* x + y + w + h */);
1156 for (GLint j = 0; j < max_viewports; ++j)
1158 data[j * 4 + 0] = 0.0f;
1159 data[j * 4 + 1] = 0.0f;
1160 data[j * 4 + 2] = 1.0f;
1161 data[j * 4 + 3] = 1.0f;
1164 /* Set width to -1 */
1165 data[i * 4 + 2] = -1.0f;
1167 gl.viewportArrayv(0, max_viewports, &data[0]);
1168 checkGLError(GL_INVALID_VALUE, "viewportArrayv, negative width", test_result);
1170 gl.viewportIndexedf(i /* index */, 0.0f, 0.0f, -1.0f, 1.0f);
1171 checkGLError(GL_INVALID_VALUE, "viewportIndexedf, negative width", test_result);
1173 gl.viewportIndexedfv(i /* index */, &data[i * 4]);
1174 checkGLError(GL_INVALID_VALUE, "viewportIndexedfv, negative width", test_result);
1176 /* Set width to 1 and height to -1*/
1177 data[i * 4 + 2] = 1.0f;
1178 data[i * 4 + 3] = -1.0f;
1180 gl.viewportArrayv(0, max_viewports, &data[0]);
1181 checkGLError(GL_INVALID_VALUE, "viewportArrayv, negative height", test_result);
1183 gl.viewportIndexedf(i /* index */, 0.0f, 0.0f, 1.0f, -1.0f);
1184 checkGLError(GL_INVALID_VALUE, "viewportIndexedf, negative height", test_result);
1186 gl.viewportIndexedfv(i /* index */, &data[i * 4]);
1187 checkGLError(GL_INVALID_VALUE, "viewportIndexedfv, negative height", test_result);
1192 * * ScissorArrayv generates INVALID_VALUE when <first> + <count> is greater
1193 * than or equal to the value of MAX_VIEWPORTS;
1196 std::vector<GLint> data;
1197 data.resize(max_viewports * 4 /* x + y + w + h */);
1199 for (GLint i = 0; i < max_viewports; ++i)
1201 data[i * 4 + 0] = 0;
1202 data[i * 4 + 1] = 0;
1203 data[i * 4 + 2] = 1;
1204 data[i * 4 + 3] = 1;
1207 gl.scissorArrayv(0, max_viewports - 1, &data[0]);
1208 checkGLError(GL_NO_ERROR, "scissorArrayv, correct parameters", test_result);
1210 gl.scissorArrayv(max_viewports, 1, &data[0]);
1211 checkGLError(GL_INVALID_VALUE, "scissorArrayv, <first> == GL_MAX_VIEWPORTS", test_result);
1213 gl.scissorArrayv(1, max_viewports - 1, &data[0]);
1214 checkGLError(GL_NO_ERROR, "scissorArrayv, <first> + <count> == GL_MAX_VIEWPORTS", test_result);
1216 gl.scissorArrayv(1, max_viewports, &data[0]);
1217 checkGLError(GL_INVALID_VALUE, "scissorArrayv, <first> + <count> > GL_MAX_VIEWPORTS", test_result);
1221 * * ScissorIndexed and ScissorIndexedv generate INVALID_VALUE when <index> is
1222 * greater than or equal to the value of MAX_VIEWPORTS;
1225 GLint data[4 /* x + y + w + h */];
1232 gl.scissorIndexed(0 /* index */, 0, 0, 1, 1);
1233 checkGLError(GL_NO_ERROR, "scissorIndexed, <index> == 0", test_result);
1235 gl.scissorIndexed(max_viewports - 1 /* index */, 0, 0, 1, 1);
1236 checkGLError(GL_NO_ERROR, "scissorIndexed, <index> == GL_MAX_VIEWPORTS - 1", test_result);
1238 gl.scissorIndexed(max_viewports /* index */, 0, 0, 1, 1);
1239 checkGLError(GL_INVALID_VALUE, "scissorIndexed, <index> == GL_MAX_VIEWPORTS", test_result);
1241 gl.scissorIndexed(max_viewports + 1 /* index */, 0, 0, 1, 1);
1242 checkGLError(GL_INVALID_VALUE, "scissorIndexed, <index> > GL_MAX_VIEWPORTS", test_result);
1244 gl.scissorIndexedv(0 /* index */, data);
1245 checkGLError(GL_NO_ERROR, "scissorIndexedv, <index> == 0", test_result);
1247 gl.scissorIndexedv(max_viewports - 1 /* index */, data);
1248 checkGLError(GL_NO_ERROR, "scissorIndexedv, <index> == GL_MAX_VIEWPORTS - 1", test_result);
1250 gl.scissorIndexedv(max_viewports /* index */, data);
1251 checkGLError(GL_INVALID_VALUE, "scissorIndexedv, <index> == GL_MAX_VIEWPORTS", test_result);
1253 gl.scissorIndexedv(max_viewports + 1 /* index */, data);
1254 checkGLError(GL_INVALID_VALUE, "scissorIndexedv, <index> > GL_MAX_VIEWPORTS", test_result);
1258 * * ScissorArrayv, ScissorIndexed, ScissorIndexedv and Scissor generate
1259 * INVALID_VALUE when <width> or <height> values are negative;
1262 gl.scissor(0, 0, -1, 1);
1263 checkGLError(GL_INVALID_VALUE, "scissor, negative width", test_result);
1265 gl.scissor(0, 0, 1, -1);
1266 checkGLError(GL_INVALID_VALUE, "scissor, negative height", test_result);
1268 for (GLint i = 0; i < max_viewports; ++i)
1270 std::vector<GLint> data;
1271 data.resize(max_viewports * 4 /* x + y + w + h */);
1273 for (GLint j = 0; j < max_viewports; ++j)
1275 data[j * 4 + 0] = 0;
1276 data[j * 4 + 1] = 0;
1277 data[j * 4 + 2] = 1;
1278 data[j * 4 + 3] = 1;
1281 /* Set width to -1 */
1282 data[i * 4 + 2] = -1;
1284 gl.scissorArrayv(0, max_viewports, &data[0]);
1285 checkGLError(GL_INVALID_VALUE, "scissorArrayv, negative width", test_result);
1287 gl.scissorIndexed(i /* index */, 0, 0, -1, 1);
1288 checkGLError(GL_INVALID_VALUE, "scissorIndexed, negative width", test_result);
1290 gl.scissorIndexedv(i /* index */, &data[i * 4]);
1291 checkGLError(GL_INVALID_VALUE, "scissorIndexedv, negative width", test_result);
1293 /* Set width to 1 and height to -1*/
1294 data[i * 4 + 2] = 1;
1295 data[i * 4 + 3] = -1;
1297 gl.scissorArrayv(0, max_viewports, &data[0]);
1298 checkGLError(GL_INVALID_VALUE, "scissorArrayv, negative height", test_result);
1300 gl.scissorIndexed(i /* index */, 0, 0, 1, -1);
1301 checkGLError(GL_INVALID_VALUE, "scissorIndexed, negative height", test_result);
1303 gl.scissorIndexedv(i /* index */, &data[i * 4]);
1304 checkGLError(GL_INVALID_VALUE, "scissorIndexedv, negative height", test_result);
1309 * * Disablei, Enablei and IsEnabledi generate INVALID_VALUE when <cap> is
1310 * SCISSOR_TEST and <index> is greater than or equal to the
1311 * value of MAX_VIEWPORTS;
1314 gl.disablei(GL_SCISSOR_TEST, max_viewports - 1);
1315 checkGLError(GL_NO_ERROR, "disablei, <index> == GL_MAX_VIEWPORTS - 1", test_result);
1317 gl.disablei(GL_SCISSOR_TEST, max_viewports);
1318 checkGLError(GL_INVALID_VALUE, "disablei, <index> == GL_MAX_VIEWPORTS", test_result);
1320 gl.enablei(GL_SCISSOR_TEST, max_viewports - 1);
1321 checkGLError(GL_NO_ERROR, "enablei, <index> == GL_MAX_VIEWPORTS - 1", test_result);
1323 gl.enablei(GL_SCISSOR_TEST, max_viewports);
1324 checkGLError(GL_INVALID_VALUE, "enablei, <index> == GL_MAX_VIEWPORTS", test_result);
1326 gl.isEnabledi(GL_SCISSOR_TEST, max_viewports - 1);
1327 checkGLError(GL_NO_ERROR, "isEnabledi, <index> == GL_MAX_VIEWPORTS - 1", test_result);
1329 gl.isEnabledi(GL_SCISSOR_TEST, max_viewports);
1330 checkGLError(GL_INVALID_VALUE, "isEnabledi, <index> == GL_MAX_VIEWPORTS", test_result);
1334 * * GetIntegeri_v generates INVALID_VALUE when <target> is SCISSOR_BOX and
1335 * <index> is greater than or equal to the value of MAX_VIEWPORTS;
1340 gl.getIntegeri_v(GL_SCISSOR_BOX, max_viewports - 1, data);
1341 checkGLError(GL_NO_ERROR, "getIntegeri_v, <index> == GL_MAX_VIEWPORTS - 1", test_result);
1343 gl.getIntegeri_v(GL_SCISSOR_BOX, max_viewports, data);
1344 checkGLError(GL_INVALID_VALUE, "getIntegeri_v, <index> == GL_MAX_VIEWPORTS", test_result);
1348 * * GetFloati_v generates INVALID_VALUE when <target> is VIEWPORT and <index>
1349 * is greater than or equal to the value of MAX_VIEWPORTS;
1354 gl.getFloati_v(GL_VIEWPORT, max_viewports - 1, data);
1355 checkGLError(GL_NO_ERROR, "getFloati_v, <index> == GL_MAX_VIEWPORTS - 1", test_result);
1357 gl.getFloati_v(GL_VIEWPORT, max_viewports, data);
1358 checkGLError(GL_INVALID_VALUE, "getFloati_v, <index> == GL_MAX_VIEWPORTS", test_result);
1362 * * GetDoublei_v generates INVALID_VALUE when <target> is DEPTH_RANGE and
1363 * <index> is greater than or equal to the value of MAX_VIEWPORTS;
1368 gl.getDoublei_v(GL_DEPTH_RANGE, max_viewports - 1, data);
1369 checkGLError(GL_NO_ERROR, "getDoublei_v, <index> == GL_MAX_VIEWPORTS - 1", test_result);
1371 gl.getDoublei_v(GL_DEPTH_RANGE, max_viewports, data);
1372 checkGLError(GL_INVALID_VALUE, "getDoublei_v, <index> == GL_MAX_VIEWPORTS", test_result);
1376 if (true == test_result)
1378 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
1382 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1386 return tcu::TestNode::STOP;
1389 /** Check if glGetError returns expected error
1391 * @param expected_error Expected error code
1392 * @param description Description of test case
1393 * @param out_result Set to false if the current error is not equal to expected one
1395 void APIErrors::checkGLError(GLenum expected_error, const GLchar* description, bool& out_result)
1397 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1399 GLenum error = gl.getError();
1401 if (expected_error != error)
1403 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Test case fail. Description: " << description
1404 << " Invalid error: " << glu::getErrorStr(error)
1405 << " expected: " << glu::getErrorStr(expected_error)
1406 << tcu::TestLog::EndMessage;
1414 * @param context Test context
1416 Queries::Queries(deqp::Context& context) : TestCase(context, "queries", "Test verifies initial state of API")
1418 /* Nothing to be done here */
1423 * @return tcu::TestNode::CONTINUE after executing test case, tcu::TestNode::STOP otherwise
1425 tcu::TestNode::IterateResult Queries::iterate()
1427 /* GL entry points */
1428 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1431 bool test_result = true;
1433 GLint layer_provoking_vertex = 0;
1434 GLint max_viewports = 0;
1435 GLfloat max_renderbuffer_size = 0.0f;
1436 GLfloat max_viewport_dims[2] = { 0.0f, 0.0f };
1437 GLfloat viewport_bounds_range[2] = { 0.0, 0.0f };
1438 GLint viewport_provoking_vertex = 0;
1439 GLint viewport_subpixel_bits = -1;
1441 gl.getIntegerv(GL_LAYER_PROVOKING_VERTEX, &layer_provoking_vertex);
1442 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
1444 gl.getIntegerv(GL_MAX_VIEWPORTS, &max_viewports);
1445 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
1447 gl.getFloatv(GL_MAX_RENDERBUFFER_SIZE, &max_renderbuffer_size);
1448 GLU_EXPECT_NO_ERROR(gl.getError(), "getFloatv");
1450 gl.getFloatv(GL_MAX_VIEWPORT_DIMS, max_viewport_dims);
1451 GLU_EXPECT_NO_ERROR(gl.getError(), "GetFloatv");
1453 gl.getFloatv(GL_VIEWPORT_BOUNDS_RANGE, viewport_bounds_range);
1454 GLU_EXPECT_NO_ERROR(gl.getError(), "GetFloatv");
1456 gl.getIntegerv(GL_VIEWPORT_INDEX_PROVOKING_VERTEX, &viewport_provoking_vertex);
1457 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
1459 gl.getIntegerv(GL_VIEWPORT_SUBPIXEL_BITS, &viewport_subpixel_bits);
1460 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
1462 const GLint window_width = m_context.getRenderContext().getRenderTarget().getWidth();
1463 const GLint window_height = m_context.getRenderContext().getRenderTarget().getHeight();
1466 * * Initial dimensions of VIEWPORT returned by GetFloati_v match dimensions of
1467 * the window into which GL is rendering;
1470 std::vector<GLfloat> data;
1471 data.resize(max_viewports * 4 /* x + y + w+ h */);
1473 for (GLint i = 0; i < max_viewports; ++i)
1475 gl.getFloati_v(GL_VIEWPORT, i, &data[i * 4]);
1476 GLU_EXPECT_NO_ERROR(gl.getError(), "GetFloati_v");
1479 for (GLint i = 0; i < max_viewports; ++i)
1481 GLint viewport_width = (GLint)data[4 * i + 2];
1482 GLint viewport_height = (GLint)data[4 * i + 3];
1484 if ((window_width != viewport_width) || (window_height != viewport_height))
1486 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid initial viewport [" << i
1487 << "] dimennsions: " << viewport_width << " x " << viewport_height
1488 << " expected: " << window_width << " x " << window_height
1489 << tcu::TestLog::EndMessage;
1491 test_result = false;
1498 * * Initial values of DEPTH_RANGE returned by GetDoublei_v are [0, 1];
1501 std::vector<GLdouble> data;
1502 data.resize(max_viewports * 2 /* near + far */);
1504 for (GLint i = 0; i < max_viewports; ++i)
1506 gl.getDoublei_v(GL_DEPTH_RANGE, i, &data[i * 2]);
1507 GLU_EXPECT_NO_ERROR(gl.getError(), "getDoublei_v");
1510 for (GLint i = 0; i < max_viewports; ++i)
1512 GLint near = (GLint)data[2 * i + 0];
1513 GLint far = (GLint)data[2 * i + 1];
1515 if ((0.0 != near) || (1.0 != far))
1517 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid initial depth range [" << i
1518 << "]: " << near << " : " << far << " expected: 0.0 : 1.0"
1519 << tcu::TestLog::EndMessage;
1521 test_result = false;
1528 * * Initial state of SCISSOR_TEST returned by IsEnabledi is FALSE;
1531 for (GLint i = 0; i < max_viewports; ++i)
1533 if (GL_FALSE != gl.isEnabledi(GL_SCISSOR_TEST, i))
1535 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Scissor test is enabled at " << i
1536 << ". Expected disabled." << tcu::TestLog::EndMessage;
1538 test_result = false;
1545 * * Initial dimensions of SCISSOR_BOX returned by GetIntegeri_v are either
1546 * zeros or match dimensions of the window into which GL is rendering;
1549 std::vector<GLint> data;
1550 data.resize(max_viewports * 4 /* x + y + w+ h */);
1552 for (GLint i = 0; i < max_viewports; ++i)
1554 gl.getIntegeri_v(GL_VIEWPORT, i, &data[i * 4]);
1555 GLU_EXPECT_NO_ERROR(gl.getError(), "getIntegeri_v");
1558 for (GLint i = 0; i < max_viewports; ++i)
1560 GLint scissor_width = data[4 * i + 2];
1561 GLint scissor_height = data[4 * i + 3];
1563 if ((window_width != scissor_width) || (window_height != scissor_height))
1565 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid initial scissor box [" << i
1566 << "] dimennsions: " << scissor_width << " x " << scissor_height
1567 << " expected: " << window_width << " x " << window_height
1568 << tcu::TestLog::EndMessage;
1570 test_result = false;
1577 * * Dimensions of MAX_VIEWPORT_DIMS returned by GetFloati_v are at least
1578 * as big as supported dimensions of render buffers, see MAX_RENDERBUFFER_SIZE;
1581 if ((max_viewport_dims[0] < max_renderbuffer_size) || (max_viewport_dims[1] < max_renderbuffer_size))
1583 m_context.getTestContext().getLog()
1584 << tcu::TestLog::Message << "Invalid MAX_VIEWPORT_DIMS: " << max_viewport_dims[0] << " x "
1585 << max_viewport_dims[1] << " expected: " << max_renderbuffer_size << " x " << max_renderbuffer_size
1586 << tcu::TestLog::EndMessage;
1588 test_result = false;
1593 * * Value of MAX_VIEWPORTS returned by GetIntegeri_v is at least 16;
1596 if (16 > max_viewports)
1598 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid MAX_VIEWPORTS: " << max_viewports
1599 << " expected at least 16." << tcu::TestLog::EndMessage;
1601 test_result = false;
1606 * * Value of VIEWPORT_SUBPIXEL_BITS returned by GetIntegeri_v is at least 0;
1609 if (0 > viewport_subpixel_bits)
1611 m_context.getTestContext().getLog() << tcu::TestLog::Message
1612 << "Invalid VIEWPORT_SUBPIXEL_BITS: " << viewport_subpixel_bits
1613 << " expected at least 0." << tcu::TestLog::EndMessage;
1615 test_result = false;
1620 * * Values of VIEWPORT_BOUNDS_RANGE returned by GetFloatv are
1621 * at least [-32768, 32767];
1624 if ((-32768.0f < viewport_bounds_range[0]) || (32768.0f > viewport_bounds_range[1]))
1626 m_context.getTestContext().getLog()
1627 << tcu::TestLog::Message << "Invalid VIEWPORT_BOUNDS_RANGE: " << viewport_bounds_range[0] << " : "
1628 << viewport_bounds_range[1] << " expected at least: -32768.0f : 32768.0f" << tcu::TestLog::EndMessage;
1630 test_result = false;
1635 * * Values of LAYER_PROVOKING_VERTEX and VIEWPORT_INDEX_PROVOKING_VERTEX
1636 * returned by GetIntegerv are located in the following set
1637 * { FIRST_VERTEX_CONVENTION, LAST_VERTEX_CONVENTION, PROVOKING_VERTEX,
1638 * UNDEFINED_VERTEX };
1641 switch (layer_provoking_vertex)
1643 case GL_FIRST_VERTEX_CONVENTION:
1644 case GL_LAST_VERTEX_CONVENTION:
1645 case GL_PROVOKING_VERTEX:
1646 case GL_UNDEFINED_VERTEX:
1649 m_context.getTestContext().getLog() << tcu::TestLog::Message
1650 << "Invalid LAYER_PROVOKING_VERTEX: " << layer_provoking_vertex
1651 << tcu::TestLog::EndMessage;
1653 test_result = false;
1656 switch (viewport_provoking_vertex)
1658 case GL_FIRST_VERTEX_CONVENTION:
1659 case GL_LAST_VERTEX_CONVENTION:
1660 case GL_PROVOKING_VERTEX:
1661 case GL_UNDEFINED_VERTEX:
1664 m_context.getTestContext().getLog() << tcu::TestLog::Message
1665 << "Invalid LAYER_PROVOKING_VERTEX: " << layer_provoking_vertex
1666 << tcu::TestLog::EndMessage;
1668 test_result = false;
1673 if (true == test_result)
1675 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
1679 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1683 return tcu::TestNode::STOP;
1686 /* Constants used by ViewportAPI */
1687 const GLuint ViewportAPI::m_n_elements = 4;
1691 * @param context Test context
1693 ViewportAPI::ViewportAPI(deqp::Context& context)
1694 : TestCase(context, "viewport_api", "Test verifies that \viewport api\" works as expected")
1696 /* Nothing to be done here */
1701 * @return tcu::TestNode::CONTINUE after executing test case, tcu::TestNode::STOP otherwise
1703 tcu::TestNode::IterateResult ViewportAPI::iterate()
1705 /* GL entry points */
1706 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1709 bool test_result = true;
1711 GLint max_viewports = 0;
1713 gl.getIntegerv(GL_MAX_VIEWPORTS, &max_viewports);
1714 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
1716 std::vector<GLfloat> scissor_box_data_a;
1717 std::vector<GLfloat> scissor_box_data_b;
1719 scissor_box_data_a.resize(max_viewports * m_n_elements);
1720 scissor_box_data_b.resize(max_viewports * m_n_elements);
1723 * - get initial dimensions of VIEWPORT for all MAX_VIEWPORTS indices;
1724 * - change location and dimensions of all indices at once with
1726 * - get VIEWPORT for all MAX_VIEWPORTS indices and verify results;
1728 getViewports(max_viewports, scissor_box_data_a);
1730 for (GLint i = 0; i < max_viewports; ++i)
1732 scissor_box_data_a[i * m_n_elements + 0] += 0.125f;
1733 scissor_box_data_a[i * m_n_elements + 1] += 0.125f;
1734 scissor_box_data_a[i * m_n_elements + 2] -= 0.125f;
1735 scissor_box_data_a[i * m_n_elements + 3] -= 0.125f;
1738 gl.viewportArrayv(0, max_viewports, &scissor_box_data_a[0]);
1739 GLU_EXPECT_NO_ERROR(gl.getError(), "viewportArrayv");
1741 getViewports(max_viewports, scissor_box_data_b);
1742 compareViewports(scissor_box_data_a, scissor_box_data_b, "viewportArrayv", test_result);
1746 * * modify with ViewportIndexedf,
1747 * * get VIEWPORT for all MAX_VIEWPORTS indices and verify results;
1749 for (GLint i = 0; i < max_viewports; ++i)
1751 scissor_box_data_b[i * m_n_elements + 0] = 0.25f;
1752 scissor_box_data_b[i * m_n_elements + 1] = 0.25f;
1753 scissor_box_data_b[i * m_n_elements + 2] = 0.75f;
1754 scissor_box_data_b[i * m_n_elements + 3] = 0.75f;
1756 gl.viewportIndexedf(i, 0.25f, 0.25f, 0.75f, 0.75f);
1757 GLU_EXPECT_NO_ERROR(gl.getError(), "viewportIndexedf");
1759 getViewports(max_viewports, scissor_box_data_a);
1760 compareViewports(scissor_box_data_a, scissor_box_data_b, "viewportIndexedf", test_result);
1765 * * modify with ViewportIndexedfv,
1766 * * get VIEWPORT for all MAX_VIEWPORTS indices and verify results;
1768 for (GLint i = 0; i < max_viewports; ++i)
1770 scissor_box_data_a[i * m_n_elements + 0] = 0.375f;
1771 scissor_box_data_a[i * m_n_elements + 1] = 0.375f;
1772 scissor_box_data_a[i * m_n_elements + 2] = 0.625f;
1773 scissor_box_data_a[i * m_n_elements + 3] = 0.625f;
1775 gl.viewportIndexedfv(i, &scissor_box_data_a[i * m_n_elements]);
1776 GLU_EXPECT_NO_ERROR(gl.getError(), "viewportIndexedfv");
1778 getViewports(max_viewports, scissor_box_data_b);
1779 compareViewports(scissor_box_data_a, scissor_box_data_b, "viewportIndexedfv", test_result);
1784 * * modify all indices before and after current one with ViewportArrayv,
1785 * * get VIEWPORT for all MAX_VIEWPORTS indices and verify results;
1787 for (GLint i = 0; i < max_viewports; ++i)
1789 const GLfloat value = (0 == i % 2) ? 1.0f : 0.25f;
1791 for (GLint j = 0; j < i; ++j)
1793 scissor_box_data_b[j * m_n_elements + 0] = value;
1794 scissor_box_data_b[j * m_n_elements + 1] = value;
1795 scissor_box_data_b[j * m_n_elements + 2] = value;
1796 scissor_box_data_b[j * m_n_elements + 3] = value;
1799 for (GLint j = i + 1; j < max_viewports; ++j)
1801 scissor_box_data_b[j * m_n_elements + 0] = value;
1802 scissor_box_data_b[j * m_n_elements + 1] = value;
1803 scissor_box_data_b[j * m_n_elements + 2] = value;
1804 scissor_box_data_b[j * m_n_elements + 3] = value;
1807 gl.viewportArrayv(0, max_viewports, &scissor_box_data_b[0]);
1808 GLU_EXPECT_NO_ERROR(gl.getError(), "viewportArrayv");
1810 getViewports(max_viewports, scissor_box_data_a);
1811 compareViewports(scissor_box_data_a, scissor_box_data_b, "viewportArrayv", test_result);
1815 * - change location and dimensions of all indices at once with Viewport;
1816 * - get VIEWPORT for all MAX_VIEWPORTS indices and verify results;
1818 for (GLint i = 0; i < max_viewports; ++i)
1820 scissor_box_data_a[i * m_n_elements + 0] = 0.0f;
1821 scissor_box_data_a[i * m_n_elements + 1] = 0.0f;
1822 scissor_box_data_a[i * m_n_elements + 2] = 1.0f;
1823 scissor_box_data_a[i * m_n_elements + 3] = 1.0f;
1826 gl.viewport(0, 0, 1, 1);
1827 GLU_EXPECT_NO_ERROR(gl.getError(), "viewport");
1829 getViewports(max_viewports, scissor_box_data_b);
1830 compareViewports(scissor_box_data_a, scissor_box_data_b, "viewport", test_result);
1833 if (true == test_result)
1835 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
1839 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1843 return tcu::TestNode::STOP;
1846 /** Compare two sets of viewport data (simple vector comparison)
1848 * @param left Left set
1849 * @param right Right set
1850 * @param description Test case description
1851 * @param out_result Set to false if sets are different, not modified otherwise
1853 void ViewportAPI::compareViewports(std::vector<GLfloat>& left, std::vector<GLfloat>& right, const GLchar* description,
1856 for (size_t i = 0; i < left.size(); ++i)
1858 if (left[i] != right[i])
1860 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Test case: " << description
1861 << " Invalid values [" << i << "] " << left[i] << " " << right[i]
1862 << tcu::TestLog::EndMessage;
1869 /** Get position of all viewports
1871 * @param max_viewports Number of viewports to capture, MAX_VIEWPORTS
1872 * @param data Memory buffer prepared for captured data
1874 void ViewportAPI::getViewports(GLint max_viewports, std::vector<GLfloat>& out_data)
1876 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1878 for (GLint i = 0; i < max_viewports; ++i)
1880 gl.getFloati_v(GL_VIEWPORT, i, &out_data[i * 4]);
1881 GLU_EXPECT_NO_ERROR(gl.getError(), "getFloati_v");
1885 /* Constants used by ScissorAPI */
1886 const GLuint ScissorAPI::m_n_elements = 4;
1890 * @param context Test context
1892 ScissorAPI::ScissorAPI(deqp::Context& context)
1893 : TestCase(context, "scissor_api", "Test verifies that \"scissor api\" works as expected")
1895 /* Nothing to be done here */
1900 * @return tcu::TestNode::CONTINUE after executing test case, tcu::TestNode::STOP otherwise
1902 tcu::TestNode::IterateResult ScissorAPI::iterate()
1904 /* GL entry points */
1905 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1908 bool test_result = true;
1910 GLint max_viewports = 0;
1912 gl.getIntegerv(GL_MAX_VIEWPORTS, &max_viewports);
1913 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
1915 std::vector<GLint> scissor_box_data_a;
1916 std::vector<GLint> scissor_box_data_b;
1918 scissor_box_data_a.resize(max_viewports * m_n_elements);
1919 scissor_box_data_b.resize(max_viewports * m_n_elements);
1922 * - get initial dimensions of SCISSOR_BOX for all MAX_VIEWPORTS indices;
1923 * - change location and dimensions of all indices at once with
1925 * - get SCISSOR_BOX for all MAX_VIEWPORTS indices and verify results;
1927 getScissorBoxes(max_viewports, scissor_box_data_a);
1929 for (GLint i = 0; i < max_viewports; ++i)
1931 scissor_box_data_a[i * m_n_elements + 0] += 1;
1932 scissor_box_data_a[i * m_n_elements + 1] += 1;
1933 scissor_box_data_a[i * m_n_elements + 2] -= 1;
1934 scissor_box_data_a[i * m_n_elements + 3] -= 1;
1937 gl.scissorArrayv(0, max_viewports, &scissor_box_data_a[0]);
1938 GLU_EXPECT_NO_ERROR(gl.getError(), "scissorArrayv");
1940 getScissorBoxes(max_viewports, scissor_box_data_b);
1941 compareScissorBoxes(scissor_box_data_a, scissor_box_data_b, "scissorArrayv", test_result);
1945 * * modify with ScissorIndexed,
1946 * * get SCISSOR_BOX for all MAX_VIEWPORTS indices and verify results;
1948 for (GLint i = 0; i < max_viewports; ++i)
1950 scissor_box_data_b[i * m_n_elements + 0] = 4;
1951 scissor_box_data_b[i * m_n_elements + 1] = 4;
1952 scissor_box_data_b[i * m_n_elements + 2] = 8;
1953 scissor_box_data_b[i * m_n_elements + 3] = 8;
1955 gl.scissorIndexed(i, 4, 4, 8, 8);
1956 GLU_EXPECT_NO_ERROR(gl.getError(), "scissorIndexed");
1958 getScissorBoxes(max_viewports, scissor_box_data_a);
1959 compareScissorBoxes(scissor_box_data_a, scissor_box_data_b, "scissorIndexed", test_result);
1964 * * modify with ScissorIndexedv,
1965 * * get SCISSOR_BOX for all MAX_VIEWPORTS indices and verify results;
1967 for (GLint i = 0; i < max_viewports; ++i)
1969 scissor_box_data_a[i * m_n_elements + 0] = 8;
1970 scissor_box_data_a[i * m_n_elements + 1] = 8;
1971 scissor_box_data_a[i * m_n_elements + 2] = 12;
1972 scissor_box_data_a[i * m_n_elements + 3] = 12;
1974 gl.scissorIndexedv(i, &scissor_box_data_a[i * m_n_elements]);
1975 GLU_EXPECT_NO_ERROR(gl.getError(), "scissorIndexedv");
1977 getScissorBoxes(max_viewports, scissor_box_data_b);
1978 compareScissorBoxes(scissor_box_data_a, scissor_box_data_b, "scissorIndexedv", test_result);
1983 * * modify all indices before and after current one with ScissorArrayv,
1984 * * get SCISSOR_BOX for all MAX_VIEWPORTS indices and verify results;
1986 for (GLint i = 0; i < max_viewports; ++i)
1988 const GLint value = (0 == i % 2) ? 1 : 4;
1990 for (GLint j = 0; j < i; ++j)
1992 scissor_box_data_b[j * m_n_elements + 0] = value;
1993 scissor_box_data_b[j * m_n_elements + 1] = value;
1994 scissor_box_data_b[j * m_n_elements + 2] = value;
1995 scissor_box_data_b[j * m_n_elements + 3] = value;
1998 for (GLint j = i + 1; j < max_viewports; ++j)
2000 scissor_box_data_b[j * m_n_elements + 0] = value;
2001 scissor_box_data_b[j * m_n_elements + 1] = value;
2002 scissor_box_data_b[j * m_n_elements + 2] = value;
2003 scissor_box_data_b[j * m_n_elements + 3] = value;
2006 gl.scissorArrayv(0, max_viewports, &scissor_box_data_b[0]);
2007 GLU_EXPECT_NO_ERROR(gl.getError(), "scissorArrayv");
2009 getScissorBoxes(max_viewports, scissor_box_data_a);
2010 compareScissorBoxes(scissor_box_data_a, scissor_box_data_b, "scissorArrayv", test_result);
2014 * - change location and dimensions of all indices at once with Scissor;
2015 * - get SCISSOR_BOX for all MAX_VIEWPORTS indices and verify results;
2017 for (GLint i = 0; i < max_viewports; ++i)
2019 scissor_box_data_a[i * m_n_elements + 0] = 0;
2020 scissor_box_data_a[i * m_n_elements + 1] = 0;
2021 scissor_box_data_a[i * m_n_elements + 2] = 1;
2022 scissor_box_data_a[i * m_n_elements + 3] = 1;
2025 gl.scissor(0, 0, 1, 1);
2026 GLU_EXPECT_NO_ERROR(gl.getError(), "scissor");
2028 getScissorBoxes(max_viewports, scissor_box_data_b);
2029 compareScissorBoxes(scissor_box_data_a, scissor_box_data_b, "scissor", test_result);
2032 if (true == test_result)
2034 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
2038 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2042 return tcu::TestNode::STOP;
2045 /** Compare two sets of scissor box data (simple vector comparison)
2047 * @param left Left set
2048 * @param right Right set
2049 * @param description Test case description
2050 * @param out_result Set to false if sets are different, not modified otherwise
2052 void ScissorAPI::compareScissorBoxes(std::vector<GLint>& left, std::vector<GLint>& right, const GLchar* description,
2055 for (size_t i = 0; i < left.size(); ++i)
2057 if (left[i] != right[i])
2059 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Test case: " << description
2060 << " Invalid values [" << i << "] " << left[i] << " " << right[i]
2061 << tcu::TestLog::EndMessage;
2068 /** Get position of all scissor boxes
2070 * @param max_viewports Number of scissor boxes to capture, MAX_VIEWPORTS
2071 * @param data Memory buffer prepared for captured data
2073 void ScissorAPI::getScissorBoxes(GLint max_viewports, std::vector<GLint>& out_data)
2075 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2077 for (GLint i = 0; i < max_viewports; ++i)
2079 gl.getIntegeri_v(GL_SCISSOR_BOX, i, &out_data[i * 4]);
2080 GLU_EXPECT_NO_ERROR(gl.getError(), "getIntegeri_v");
2084 /* Constants used by DepthRangeAPI */
2085 const GLuint DepthRangeAPI::m_n_elements = 2 /* near + far */;
2089 * @param context Test context
2091 DepthRangeAPI::DepthRangeAPI(deqp::Context& context)
2092 : TestCase(context, "depth_range_api", "Test verifies that \"depth range api\" works as expected")
2094 /* Nothing to be done here */
2099 * @return tcu::TestNode::CONTINUE after executing test case, tcu::TestNode::STOP otherwise
2101 tcu::TestNode::IterateResult DepthRangeAPI::iterate()
2103 /* GL entry points */
2104 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2107 bool test_result = true;
2109 GLint max_viewports = 0;
2111 gl.getIntegerv(GL_MAX_VIEWPORTS, &max_viewports);
2112 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
2114 std::vector<GLdouble> depth_range_data_a;
2115 std::vector<GLdouble> depth_range_data_b;
2117 depth_range_data_a.resize(max_viewports * m_n_elements);
2118 depth_range_data_b.resize(max_viewports * m_n_elements);
2121 * - get initial values of DEPTH_RANGE for all MAX_VIEWPORTS indices;
2122 * - change values of all indices at once with DepthRangeArrayv;
2123 * - get DEPTH_RANGE for all MAX_VIEWPORTS indices and verify results;
2125 getDepthRanges(max_viewports, depth_range_data_a);
2127 for (GLint i = 0; i < max_viewports; ++i)
2129 depth_range_data_a[i * m_n_elements + 0] += 0.125;
2130 depth_range_data_a[i * m_n_elements + 1] -= 0.125;
2133 gl.depthRangeArrayv(0, max_viewports, &depth_range_data_a[0]);
2134 GLU_EXPECT_NO_ERROR(gl.getError(), "depthRangeArrayv");
2136 getDepthRanges(max_viewports, depth_range_data_b);
2137 compareDepthRanges(depth_range_data_a, depth_range_data_b, "depthRangeArrayv", test_result);
2141 * * modify with DepthRangeIndexed,
2142 * * get DEPTH_RANGE for all MAX_VIEWPORTS indices and verify results;
2144 for (GLint i = 0; i < max_viewports; ++i)
2146 depth_range_data_b[i * m_n_elements + 0] = 0.25;
2147 depth_range_data_b[i * m_n_elements + 1] = 0.75;
2149 gl.depthRangeIndexed(i, 0.25f, 0.75f);
2150 GLU_EXPECT_NO_ERROR(gl.getError(), "depthRangeIndexed");
2152 getDepthRanges(max_viewports, depth_range_data_a);
2153 compareDepthRanges(depth_range_data_a, depth_range_data_b, "depthRangeIndexed", test_result);
2158 * * modify all indices before and after current one with DepthRangeArrayv,
2159 * * get DEPTH_RANGE for all MAX_VIEWPORTS indices and verify results;
2161 for (GLint i = 0; i < max_viewports; ++i)
2163 const GLdouble value = (0 == i % 2) ? 1.0 : 0.25;
2165 for (GLint j = 0; j < i; ++j)
2167 depth_range_data_b[j * m_n_elements + 0] = value;
2168 depth_range_data_b[j * m_n_elements + 1] = value;
2171 for (GLint j = i + 1; j < max_viewports; ++j)
2173 depth_range_data_b[j * m_n_elements + 0] = value;
2174 depth_range_data_b[j * m_n_elements + 1] = value;
2177 gl.depthRangeArrayv(0, max_viewports, &depth_range_data_b[0]);
2178 GLU_EXPECT_NO_ERROR(gl.getError(), "depthRangeArrayv");
2180 getDepthRanges(max_viewports, depth_range_data_a);
2181 compareDepthRanges(depth_range_data_a, depth_range_data_b, "depthRangeArrayv", test_result);
2185 * - change values of all indices at once with DepthRange;
2186 * - get DEPTH_RANGE for all MAX_VIEWPORTS indices and verify results;
2188 for (GLint i = 0; i < max_viewports; ++i)
2190 depth_range_data_a[i * m_n_elements + 0] = 0.0f;
2191 depth_range_data_a[i * m_n_elements + 1] = 1.0f;
2194 gl.depthRange(0.0, 1.0);
2195 GLU_EXPECT_NO_ERROR(gl.getError(), "depthRange");
2197 getDepthRanges(max_viewports, depth_range_data_b);
2198 compareDepthRanges(depth_range_data_a, depth_range_data_b, "depthRange", test_result);
2201 if (true == test_result)
2203 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
2207 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2211 return tcu::TestNode::STOP;
2214 /** Compare two sets of depth range data (simple vector comparison)
2216 * @param left Left set
2217 * @param right Right set
2218 * @param description Test case description
2219 * @param out_result Set to false if sets are different, not modified otherwise
2221 void DepthRangeAPI::compareDepthRanges(std::vector<GLdouble>& left, std::vector<GLdouble>& right,
2222 const GLchar* description, bool& out_result)
2224 for (size_t i = 0; i < left.size(); ++i)
2226 if (left[i] != right[i])
2228 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Test case: " << description
2229 << " Invalid values [" << i << "] " << left[i] << " " << right[i]
2230 << tcu::TestLog::EndMessage;
2237 /** Get all depth ranges
2239 * @param max_viewports Number of viewports to capture, MAX_VIEWPORTS
2240 * @param data Memory buffer prepared for captured data
2242 void DepthRangeAPI::getDepthRanges(GLint max_viewports, std::vector<GLdouble>& out_data)
2244 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2246 for (GLint i = 0; i < max_viewports; ++i)
2248 gl.getDoublei_v(GL_DEPTH_RANGE, i, &out_data[i * m_n_elements]);
2249 GLU_EXPECT_NO_ERROR(gl.getError(), "getDoublei_v");
2255 * @param context Test context
2257 ScissorTestStateAPI::ScissorTestStateAPI(deqp::Context& context)
2258 : TestCase(context, "scissor_test_state_api",
2259 "Test verifies that \"enable/disable api\" works as expected for scissor test")
2261 /* Nothing to be done here */
2266 * @return tcu::TestNode::CONTINUE after executing test case, tcu::TestNode::STOP otherwise
2268 tcu::TestNode::IterateResult ScissorTestStateAPI::iterate()
2270 /* GL entry points */
2271 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2274 bool test_result = true;
2276 GLint max_viewports = 0;
2278 gl.getIntegerv(GL_MAX_VIEWPORTS, &max_viewports);
2279 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
2281 std::vector<GLboolean> scissor_test_states_a;
2282 std::vector<GLboolean> scissor_test_states_b;
2284 scissor_test_states_a.resize(max_viewports);
2285 scissor_test_states_b.resize(max_viewports);
2288 * - get initial state of SCISSOR_TEST for all MAX_VIEWPORTS indices;
2290 * * toggle SCISSOR_TEST,
2291 * * get state of SCISSOR_TEST for all MAX_VIEWPORTS indices and verify;
2293 * * toggle SCISSOR_TEST,
2294 * * get state of SCISSOR_TEST for all MAX_VIEWPORTS indices and verify;
2296 getScissorTestStates(max_viewports, scissor_test_states_a);
2298 for (GLint i = 0; i < max_viewports; ++i)
2300 if (GL_FALSE == scissor_test_states_a[i])
2302 gl.enablei(GL_SCISSOR_TEST, i);
2303 GLU_EXPECT_NO_ERROR(gl.getError(), "Enablei");
2305 scissor_test_states_a[i] = GL_TRUE;
2309 gl.disablei(GL_SCISSOR_TEST, i);
2310 GLU_EXPECT_NO_ERROR(gl.getError(), "Disablei");
2312 scissor_test_states_a[i] = GL_FALSE;
2315 getScissorTestStates(max_viewports, scissor_test_states_b);
2316 compareScissorTestStates(scissor_test_states_a, scissor_test_states_b, "1st toggle", test_result);
2319 for (GLint i = 0; i < max_viewports; ++i)
2321 if (GL_FALSE == scissor_test_states_a[i])
2323 gl.enablei(GL_SCISSOR_TEST, i);
2324 GLU_EXPECT_NO_ERROR(gl.getError(), "Enablei");
2326 scissor_test_states_a[i] = GL_TRUE;
2330 gl.disablei(GL_SCISSOR_TEST, i);
2331 GLU_EXPECT_NO_ERROR(gl.getError(), "Disablei");
2333 scissor_test_states_a[i] = GL_FALSE;
2336 getScissorTestStates(max_viewports, scissor_test_states_b);
2337 compareScissorTestStates(scissor_test_states_a, scissor_test_states_b, "2nd toggle", test_result);
2341 * - enable SCISSOR_TEST for all indices at once with Enable;
2342 * - get state of SCISSOR_TEST for all MAX_VIEWPORTS indices and verify;
2344 for (GLint i = 0; i < max_viewports; ++i)
2346 scissor_test_states_a[i] = GL_TRUE;
2349 gl.enable(GL_SCISSOR_TEST);
2350 GLU_EXPECT_NO_ERROR(gl.getError(), "Enable");
2352 getScissorTestStates(max_viewports, scissor_test_states_b);
2353 compareScissorTestStates(scissor_test_states_a, scissor_test_states_b, "1st enable all", test_result);
2356 * - disable SCISSOR_TEST for all indices at once with Disable;
2357 * - get state of SCISSOR_TEST for all MAX_VIEWPORTS indices and verify;
2359 for (GLint i = 0; i < max_viewports; ++i)
2361 scissor_test_states_a[i] = GL_FALSE;
2364 gl.disable(GL_SCISSOR_TEST);
2365 GLU_EXPECT_NO_ERROR(gl.getError(), "Disable");
2367 getScissorTestStates(max_viewports, scissor_test_states_b);
2368 compareScissorTestStates(scissor_test_states_a, scissor_test_states_b, "Disable all", test_result);
2371 * - enable SCISSOR_TEST for all indices at once with Enable;
2372 * - get state of SCISSOR_TEST for all MAX_VIEWPORTS indices and verify;
2374 for (GLint i = 0; i < max_viewports; ++i)
2376 scissor_test_states_a[i] = GL_TRUE;
2379 gl.enable(GL_SCISSOR_TEST);
2380 GLU_EXPECT_NO_ERROR(gl.getError(), "Enable");
2382 getScissorTestStates(max_viewports, scissor_test_states_b);
2383 compareScissorTestStates(scissor_test_states_a, scissor_test_states_b, "2nd enable all", test_result);
2386 if (true == test_result)
2388 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
2392 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2396 return tcu::TestNode::STOP;
2399 /** Compare two sets of depth range data (simple vector comparison)
2401 * @param left Left set
2402 * @param right Right set
2403 * @param description Test case description
2404 * @param out_result Set to false if sets are different, not modified otherwise
2406 void ScissorTestStateAPI::compareScissorTestStates(std::vector<GLboolean>& left, std::vector<GLboolean>& right,
2407 const GLchar* description, bool& out_result)
2409 for (size_t i = 0; i < left.size(); ++i)
2411 if (left[i] != right[i])
2413 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Test case: " << description
2414 << " Invalid values [" << i << "] " << left[i] << " " << right[i]
2415 << tcu::TestLog::EndMessage;
2422 /** Get all depth ranges
2424 * @param max_viewports Number of viewports to capture, MAX_VIEWPORTS
2425 * @param data Memory buffer prepared for captured data
2427 void ScissorTestStateAPI::getScissorTestStates(GLint max_viewports, std::vector<GLboolean>& out_data)
2429 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2431 for (GLint i = 0; i < max_viewports; ++i)
2433 out_data[i] = gl.isEnabledi(GL_SCISSOR_TEST, i);
2434 GLU_EXPECT_NO_ERROR(gl.getError(), "isEnabledi");
2438 /* Constants used by DrawTestBase */
2439 const GLuint DrawTestBase::m_depth = 16;
2440 const GLuint DrawTestBase::m_height = 128;
2441 const GLuint DrawTestBase::m_width = 128;
2442 const GLuint DrawTestBase::m_r32f_height = 2;
2443 const GLuint DrawTestBase::m_r32f_width = 16;
2444 const GLuint DrawTestBase::m_r32ix4_depth = 4;
2448 * @param context Test context
2449 * @param test_name Test name
2450 * @param test_description Test description
2452 DrawTestBase::DrawTestBase(deqp::Context& context, const GLchar* test_name, const GLchar* test_description)
2453 : TestCase(context, test_name, test_description)
2455 /* Nothing to be done here */
2460 * @return tcu::TestNode::CONTINUE after executing test case, tcu::TestNode::STOP otherwise
2462 tcu::TestNode::IterateResult DrawTestBase::iterate()
2464 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2467 bool test_result = true;
2469 /* Get type of test */
2470 const TEST_TYPE test_type = getTestType();
2472 GLuint n_draw_calls = getDrawCallsNumber();
2473 GLuint n_iterations = 0;
2485 TCU_FAIL("Invalid enum");
2488 /* Get shader sources */
2489 const std::string& fragment = getFragmentShader();
2490 const std::string& geometry = getGeometryShader();
2491 const std::string& vertex = getVertexShader();
2493 /* Prepare program */
2494 Utils::program program(m_context);
2498 program.build(0 /* compute */, fragment.c_str(), geometry.c_str(), 0 /* tess ctrl */, 0 /* tess eval */,
2499 vertex.c_str(), 0 /* varying names */, 0 /* n_varyings */);
2501 catch (Utils::shaderCompilationException& exc)
2503 /* Something wrong with compilation, test case failed */
2504 tcu::MessageBuilder message = m_context.getTestContext().getLog() << tcu::TestLog::Message;
2506 message << "Shader compilation failed. Error message: " << exc.m_error_message;
2508 Utils::program::printShaderSource(exc.m_shader_source.c_str(), message);
2510 message << tcu::TestLog::EndMessage;
2512 TCU_FAIL("Shader compilation failed");
2514 catch (Utils::programLinkageException& exc)
2516 /* Something wrong with linking, test case failed */
2517 m_context.getTestContext().getLog() << tcu::TestLog::Message
2518 << "Program linking failed. Error message: " << exc.m_error_message
2519 << tcu::TestLog::EndMessage;
2520 TCU_FAIL("Program linking failed");
2526 Utils::vertexArray vao(m_context);
2530 /* For each iteration from test type */
2531 for (GLuint i = 0; i < n_iterations; ++i)
2533 /* Prepare textures */
2534 Utils::texture texture_0(m_context);
2535 Utils::texture texture_1(m_context);
2537 prepareTextures(texture_0, texture_1);
2539 /* Prepare framebuffer */
2540 Utils::framebuffer framebuffer(m_context);
2541 framebuffer.generate();
2542 setupFramebuffer(framebuffer, texture_0, texture_1);
2545 /* Set up viewports */
2546 setupViewports(test_type, i);
2548 if (false == isClearTest())
2550 /* For each draw call */
2551 for (GLuint draw_call = 0; draw_call < n_draw_calls; ++draw_call)
2553 prepareUniforms(program, draw_call);
2556 GLdouble depth_value;
2558 getClearSettings(is_clear, draw_call, depth_value);
2560 if (true == is_clear)
2562 gl.clearDepth(depth_value);
2563 GLU_EXPECT_NO_ERROR(gl.getError(), "ClearDepth");
2565 gl.clear(GL_DEPTH_BUFFER_BIT);
2566 GLU_EXPECT_NO_ERROR(gl.getError(), "Clear");
2569 gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
2570 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
2572 bool result = checkResults(texture_0, texture_1, draw_call);
2574 if (false == result)
2576 test_result = false;
2583 gl.clearColor(0.0f, 0.0f, 0.0f, 0.0f);
2584 GLU_EXPECT_NO_ERROR(gl.getError(), "ClearColor");
2586 gl.clear(GL_COLOR_BUFFER_BIT);
2587 GLU_EXPECT_NO_ERROR(gl.getError(), "Clear");
2589 bool result = checkResults(texture_0, texture_1, 0);
2591 if (false == result)
2593 test_result = false;
2601 if (true == test_result)
2603 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
2607 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2611 return tcu::TestNode::STOP;
2614 /** Check if R32I texture is filled with 4x4 regions of increasing values <0:15>
2616 * @param texture_0 Verified texture
2620 * @return True if texture_0 is filled with expected pattern
2622 bool DrawTestBase::checkResults(Utils::texture& texture_0, Utils::texture& /* texture_1 */, GLuint /*draw_call_index */)
2624 bool check_result = true;
2627 std::vector<GLint> texture_data;
2628 texture_data.resize(m_width * m_height);
2629 texture_0.get(GL_RED_INTEGER, GL_INT, &texture_data[0]);
2631 for (GLuint y = 0; y < 4; ++y)
2633 for (GLuint x = 0; x < 4; ++x)
2635 bool result = checkRegionR32I(x, y, index, &texture_data[0]);
2637 if (false == result)
2639 check_result = false;
2648 return check_result;
2651 /** Get settings of clear operation
2653 * @param clear_depth_before_draw Selects if clear depth should be executed before draw.
2657 void DrawTestBase::getClearSettings(bool& clear_depth_before_draw, GLuint /* iteration_index */,
2658 GLdouble& /* depth_value */)
2660 clear_depth_before_draw = false;
2663 /** Get number of draw call to be executed during test
2667 GLuint DrawTestBase::getDrawCallsNumber()
2676 DrawTestBase::TEST_TYPE DrawTestBase::getTestType()
2681 /** Selects if test should do draw or clear operation
2683 * @return false - draw operation
2685 bool DrawTestBase::isClearTest()
2690 /** Prepare textures used as framebuffer's attachments for current draw call
2692 * @param texture_0 R32I texture
2695 void DrawTestBase::prepareTextures(Utils::texture& texture_0, Utils::texture& /* texture_1 */)
2697 prepareTextureR32I(texture_0);
2700 /** Prepare uniforms for given draw call
2705 void DrawTestBase::prepareUniforms(Utils::program& /* program */, GLuint /* draw_call_index */)
2710 /** Attach textures to framebuffer
2712 * @param framebuffer Framebuffer instance
2713 * @param texture_0 Texture attached as color 0
2716 void DrawTestBase::setupFramebuffer(Utils::framebuffer& framebuffer, Utils::texture& texture_0,
2717 Utils::texture& /* texture_1 */)
2719 framebuffer.attachTexture(GL_COLOR_ATTACHMENT0, texture_0.m_id, m_width, m_height);
2722 /** Check if region specified with <x and <y> is filled with expected value.
2723 * Note: there is assumption that there are 4x4 regions
2725 * @param x X coordinate of region
2726 * @param y Y coordinate of region
2727 * @param expected_value Expected value
2728 * @param data Texture data (not region, but whole texture)
2730 * @return True if region is filled with <expected_value>, false otherwise
2732 bool DrawTestBase::checkRegionR32I(GLuint x, GLuint y, GLint expected_value, GLint* data)
2734 static GLuint width = m_width / 4;
2735 static GLuint height = m_height / 4;
2737 return checkRegionR32I(x, y, width, height, expected_value, data);
2740 /** Check if region specified with <x and <y> is filled with expected value.
2741 * Note: there is assumption that there are 4x4 regions
2743 * @param x X coordinate of region
2744 * @param y Y coordinate of region
2745 * @param width Width of region
2746 * @param height Height of region
2747 * @param expected_value Expected value
2748 * @param data Texture data (not region, but whole texture)
2750 * @return True if region is filled with <expected_value>, false otherwise
2752 bool DrawTestBase::checkRegionR32I(GLuint x, GLuint y, GLuint width, GLuint height, GLint expected_value, GLint* data)
2756 const GLuint offset = (y * height * m_width) + (x * width);
2758 for (GLuint line = 0; line < height; ++line)
2760 const GLuint line_offset = offset + line * m_width;
2762 for (GLuint texel = 0; texel < width; ++texel)
2764 const GLuint texel_offset = line_offset + texel;
2766 const GLint value = data[texel_offset];
2768 if (expected_value != value)
2770 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid result. Region (" << x << "x"
2771 << y << "). Expected: " << expected_value << " got " << value
2772 << tcu::TestLog::EndMessage;
2784 /** Return boiler-plate vertex shader
2786 * @return Source code of vertex shader
2788 std::string DrawTestBase::getVertexShader()
2790 static const GLchar* source = "#version 410 core\n"
2798 std::string result = source;
2803 /** Set up viewports
2805 * @param type Type of test
2806 * @param iteration_index Index of iteration for given test type
2808 void DrawTestBase::setupViewports(TEST_TYPE type, GLuint iteration_index)
2814 VIEWPORT_METHOD method;
2815 switch (iteration_index)
2820 method = (VIEWPORT_METHOD)iteration_index;
2823 TCU_FAIL("Invalid value");
2825 setup4x4Viewport(method);
2830 SCISSOR_METHOD method;
2831 switch (iteration_index)
2836 method = (SCISSOR_METHOD)iteration_index;
2839 TCU_FAIL("Invalid value");
2841 setup4x4Scissor(method, false /* set_zeros */);
2846 DEPTH_RANGE_METHOD method;
2847 switch (iteration_index)
2851 method = (DEPTH_RANGE_METHOD)iteration_index;
2854 TCU_FAIL("Invalid value");
2856 setup16x2Depths(method);
2861 PROVOKING_VERTEX provoking;
2862 switch (iteration_index)
2866 provoking = (PROVOKING_VERTEX)iteration_index;
2869 TCU_FAIL("Invalid value");
2871 setup2x2Viewport(provoking);
2875 TCU_FAIL("Invalid enum");
2879 /** Prepare R32I texture filled with value -1
2881 * @param texture Texture instance
2883 void DrawTestBase::prepareTextureR32I(Utils::texture& texture)
2885 static const GLuint size = m_width * m_height;
2888 for (GLuint i = 0; i < size; ++i)
2893 texture.create(m_width, m_height, GL_R32I);
2894 texture.update(m_width, m_height, 0 /* depth */, GL_RED_INTEGER, GL_INT, data);
2897 /** Prepare R32I array texture filled with value -1, 4 layers
2899 * @param texture Texture instance
2901 void DrawTestBase::prepareTextureR32Ix4(Utils::texture& texture)
2903 static const GLuint size = m_width * m_height * m_r32ix4_depth;
2905 std::vector<GLint> data;
2908 for (GLuint i = 0; i < size; ++i)
2913 texture.create(m_width, m_height, m_r32ix4_depth, GL_R32I);
2914 texture.update(m_width, m_height, m_r32ix4_depth, GL_RED_INTEGER, GL_INT, &data[0]);
2917 /** Prepare R32I array texture filled with value -1
2919 * @param texture Texture instance
2921 void DrawTestBase::prepareTextureArrayR32I(Utils::texture& texture)
2923 static const GLuint size = m_width * m_height * m_depth;
2925 std::vector<GLint> data;
2928 for (GLuint i = 0; i < size; ++i)
2933 texture.create(m_width, m_height, m_depth, GL_R32I);
2934 texture.update(m_width, m_height, m_depth, GL_RED_INTEGER, GL_INT, &data[0]);
2937 /** Prepare R32F texture filled with value -1
2939 * @param texture Texture instance
2941 void DrawTestBase::prepareTextureR32F(Utils::texture& texture)
2943 static const GLuint size = m_r32f_width * m_r32f_height;
2946 for (GLuint i = 0; i < size; ++i)
2951 texture.create(m_r32f_width, m_r32f_height, GL_R32F);
2952 texture.update(m_r32f_width, m_r32f_height, 0 /* depth */, GL_RED, GL_FLOAT, data);
2955 /** Prepare D32F texture filled with value -1
2957 * @param texture Texture instance
2959 void DrawTestBase::prepareTextureD32F(Utils::texture& texture)
2961 static const GLuint size = m_width * m_height;
2964 for (GLuint i = 0; i < size; ++i)
2969 texture.create(m_width, m_height, GL_DEPTH_COMPONENT32F);
2970 texture.update(m_width, m_height, 0 /* depth */, GL_DEPTH_COMPONENT, GL_FLOAT, data);
2973 /** Set up 16 viewports and depth ranges horizontally
2975 * @param method Method used to set depth ranges
2977 void DrawTestBase::setup16x2Depths(DEPTH_RANGE_METHOD method)
2979 static const GLdouble step = 1.0 / 16.0;
2981 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2983 GLdouble depth_data[16 * 2];
2984 GLfloat viewport_data[16 * 4];
2986 for (GLuint i = 0; i < 16; ++i)
2988 const GLdouble near = step * (GLdouble)i;
2990 depth_data[i * 2 + 0] = near;
2991 depth_data[i * 2 + 1] = 1.0 - near;
2993 viewport_data[i * 4 + 0] = (GLfloat)i;
2994 viewport_data[i * 4 + 1] = 0.0f;
2995 viewport_data[i * 4 + 2] = 1.0f;
2996 viewport_data[i * 4 + 3] = 2.0f;
2999 gl.viewportArrayv(0 /* first */, 16 /* count */, viewport_data);
3000 GLU_EXPECT_NO_ERROR(gl.getError(), "ViewportArrayv");
3004 case DEPTHRANGEINDEXED:
3005 for (GLuint i = 0; i < 16; ++i)
3007 gl.depthRangeIndexed(i, depth_data[i * 2 + 0], depth_data[i * 2 + 1]);
3008 GLU_EXPECT_NO_ERROR(gl.getError(), "DepthRangeIndexed");
3012 case DEPTHRANGEARRAYV:
3013 gl.depthRangeArrayv(0 /* first */, 16 /* count */, depth_data);
3014 GLU_EXPECT_NO_ERROR(gl.getError(), "DepthRangeArrayv");
3018 TCU_FAIL("Invalid enum");
3022 /** Set up 4x4 scissor boxes with enabled test
3024 * @param method Method used to set scissor boxes
3025 * @param set_zeros Select if width and height should be 0 or image_dim / 4
3027 void DrawTestBase::setup4x4Scissor(SCISSOR_METHOD method, bool set_zeros)
3029 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3031 for (GLuint i = 0; i < 16; ++i)
3033 gl.enablei(GL_SCISSOR_TEST, i);
3034 GLU_EXPECT_NO_ERROR(gl.getError(), "Enablei");
3038 GLint data[16 * 4 /* 4x4 * (x + y + w + h) */];
3040 GLint width = m_width / 4;
3041 GLint height = m_height / 4;
3043 for (GLuint y = 0; y < 4; ++y)
3045 for (GLuint x = 0; x < 4; ++x)
3047 data[index * 4 + 0] = x * width;
3048 data[index * 4 + 1] = y * height;
3049 if (false == set_zeros)
3051 data[index * 4 + 2] = width;
3052 data[index * 4 + 3] = height;
3056 data[index * 4 + 2] = 0;
3057 data[index * 4 + 3] = 0;
3067 gl.scissorArrayv(0 /* first */, 16 /*count */, data);
3068 GLU_EXPECT_NO_ERROR(gl.getError(), "ScissorArrayv");
3070 case SCISSORINDEXEDF:
3071 for (GLuint i = 0; i < 16; ++i)
3073 const GLint x = data[i * 4 + 0];
3074 const GLint y = data[i * 4 + 1];
3075 const GLint w = data[i * 4 + 2];
3076 const GLint h = data[i * 4 + 3];
3078 gl.scissorIndexed(i, x, y, w, h);
3079 GLU_EXPECT_NO_ERROR(gl.getError(), "ScissorIndexed");
3082 case SCISSORINDEXEDF_V:
3083 for (GLuint i = 0; i < 16; ++i)
3085 gl.scissorIndexedv(i, &data[i * 4]);
3086 GLU_EXPECT_NO_ERROR(gl.getError(), "ScissorIndexedv");
3090 TCU_FAIL("Invalid enum");
3094 /** Set up 4x4 viewports
3096 * @param method Method used to set viewports
3098 void DrawTestBase::setup4x4Viewport(VIEWPORT_METHOD method)
3100 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3103 GLfloat data[16 * 4 /* 4x4 * (x + y + w + h) */];
3105 GLfloat width = (GLfloat)(m_width / 4);
3106 GLfloat height = (GLfloat)(m_height / 4);
3108 for (GLuint y = 0; y < 4; ++y)
3110 for (GLuint x = 0; x < 4; ++x)
3112 data[index * 4 + 0] = (GLfloat)((GLfloat)x * width);
3113 data[index * 4 + 1] = (GLfloat)((GLfloat)y * height);
3114 data[index * 4 + 2] = width;
3115 data[index * 4 + 3] = height;
3123 case VIEWPORTARRAYV:
3124 gl.viewportArrayv(0 /* first */, 16 /*count */, data);
3125 GLU_EXPECT_NO_ERROR(gl.getError(), "ViewportArrayv");
3127 case VIEWPORTINDEXEDF:
3128 for (GLuint i = 0; i < 16; ++i)
3130 const GLfloat x = data[i * 4 + 0];
3131 const GLfloat y = data[i * 4 + 1];
3132 const GLfloat w = data[i * 4 + 2];
3133 const GLfloat h = data[i * 4 + 3];
3135 gl.viewportIndexedf(i, x, y, w, h);
3136 GLU_EXPECT_NO_ERROR(gl.getError(), "ViewportIndexedf");
3139 case VIEWPORTINDEXEDF_V:
3140 for (GLuint i = 0; i < 16; ++i)
3142 gl.viewportIndexedfv(i, &data[i * 4]);
3143 GLU_EXPECT_NO_ERROR(gl.getError(), "ViewportIndexedfv");
3147 TCU_FAIL("Invalid enum");
3151 /** Set up 4x4 viewports
3153 * @param method Method used to set viewports
3155 void DrawTestBase::setup2x2Viewport(PROVOKING_VERTEX provoking)
3157 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3160 GLfloat data[4 * 4 /* 4x4 * (x + y + w + h) */];
3162 GLfloat width = (GLfloat)(m_width / 2);
3163 GLfloat height = (GLfloat)(m_height / 2);
3165 for (GLuint y = 0; y < 2; ++y)
3167 for (GLuint x = 0; x < 2; ++x)
3169 data[index * 4 + 0] = (GLfloat)((GLfloat)x * width);
3170 data[index * 4 + 1] = (GLfloat)((GLfloat)y * height);
3171 data[index * 4 + 2] = width;
3172 data[index * 4 + 3] = height;
3178 gl.viewportArrayv(0 /* first */, 4 /*count */, data);
3179 GLU_EXPECT_NO_ERROR(gl.getError(), "ViewportArrayv");
3185 mode = GL_FIRST_VERTEX_CONVENTION;
3188 mode = GL_LAST_VERTEX_CONVENTION;
3191 TCU_FAIL("Invalid enum");
3194 gl.provokingVertex(mode);
3195 GLU_EXPECT_NO_ERROR(gl.getError(), "ProvokingVertex");
3200 * @param context Test context
3202 DrawToSingleLayerWithMultipleViewports::DrawToSingleLayerWithMultipleViewports(deqp::Context& context)
3203 : DrawTestBase(context, "draw_to_single_layer_with_multiple_viewports",
3204 "Test verifies that multiple viewports can be used to draw to single layer")
3206 /* Nothing to be done here */
3209 /** Get string with fragment shader source code
3211 * @return Fragment shader source
3213 std::string DrawToSingleLayerWithMultipleViewports::getFragmentShader()
3215 static const GLchar* source = "#version 410 core\n"
3217 "flat in int gs_fs_color;\n"
3218 " out int fs_out_color;\n"
3222 " fs_out_color = gs_fs_color;\n"
3226 std::string result = source;
3231 /** Get string with geometry shader source code
3233 * @return Geometry shader source
3235 std::string DrawToSingleLayerWithMultipleViewports::getGeometryShader()
3237 static const GLchar* source = "#version 410 core\n"
3239 "layout(points, invocations = 16) in;\n"
3240 "layout(triangle_strip, max_vertices = 4) out;\n"
3242 "flat out int gs_fs_color;\n"
3246 " gs_fs_color = gl_InvocationID;\n"
3247 " gl_ViewportIndex = gl_InvocationID;\n"
3248 " gl_Position = vec4(-1, -1, 0, 1);\n"
3250 " gs_fs_color = gl_InvocationID;\n"
3251 " gl_ViewportIndex = gl_InvocationID;\n"
3252 " gl_Position = vec4(-1, 1, 0, 1);\n"
3254 " gs_fs_color = gl_InvocationID;\n"
3255 " gl_ViewportIndex = gl_InvocationID;\n"
3256 " gl_Position = vec4(1, -1, 0, 1);\n"
3258 " gs_fs_color = gl_InvocationID;\n"
3259 " gl_ViewportIndex = gl_InvocationID;\n"
3260 " gl_Position = vec4(1, 1, 0, 1);\n"
3265 std::string result = source;
3272 * @param context Test context
3274 DynamicViewportIndex::DynamicViewportIndex(deqp::Context& context)
3275 : DrawTestBase(context, "dynamic_viewport_index",
3276 "Test verifies that gl_ViewportIndex can be assigned with dynamic value")
3278 /* Nothing to be done here */
3281 /** Get string with fragment shader source code
3283 * @return Fragment shader source
3285 std::string DynamicViewportIndex::getFragmentShader()
3287 static const GLchar* source = "#version 410 core\n"
3289 "flat in int gs_fs_color;\n"
3290 " out int fs_out_color;\n"
3294 " fs_out_color = gs_fs_color;\n"
3298 std::string result = source;
3303 /** Get string with geometry shader source code
3305 * @return Geometry shader source
3307 std::string DynamicViewportIndex::getGeometryShader()
3309 static const GLchar* source = "#version 410 core\n"
3311 "layout(points, invocations = 1) in;\n"
3312 "layout(triangle_strip, max_vertices = 4) out;\n"
3314 "uniform int uni_index;\n"
3316 "flat out int gs_fs_color;\n"
3320 " gs_fs_color = uni_index;\n"
3321 " gl_ViewportIndex = uni_index;\n"
3322 " gl_Position = vec4(-1, -1, 0, 1);\n"
3324 " gs_fs_color = uni_index;\n"
3325 " gl_ViewportIndex = uni_index;\n"
3326 " gl_Position = vec4(-1, 1, 0, 1);\n"
3328 " gs_fs_color = uni_index;\n"
3329 " gl_ViewportIndex = uni_index;\n"
3330 " gl_Position = vec4(1, -1, 0, 1);\n"
3332 " gs_fs_color = uni_index;\n"
3333 " gl_ViewportIndex = uni_index;\n"
3334 " gl_Position = vec4(1, 1, 0, 1);\n"
3339 std::string result = source;
3344 /** Check if R32I texture is filled with 4x4 regions of increasing values <0:15>
3346 * @param texture_0 Verified texture
3348 * @param draw_call_index Draw call that was executed
3350 * @return True if texture_0 is filled with expected pattern
3352 bool DynamicViewportIndex::checkResults(Utils::texture& texture_0, Utils::texture& /* texture_1 */,
3353 GLuint draw_call_index)
3355 bool check_result = true;
3358 std::vector<GLint> texture_data;
3359 texture_data.resize(m_width * m_height);
3360 texture_0.get(GL_RED_INTEGER, GL_INT, &texture_data[0]);
3362 for (GLuint y = 0; y < 4; ++y)
3364 for (GLuint x = 0; x < 4; ++x)
3366 GLint expected_value = -1;
3367 if (index <= draw_call_index)
3369 expected_value = index;
3372 bool result = checkRegionR32I(x, y, expected_value, &texture_data[0]);
3374 if (false == result)
3376 check_result = false;
3385 return check_result;
3388 /** Get number of draw call to be executed during test
3392 GLuint DynamicViewportIndex::getDrawCallsNumber()
3397 /** Prepare uniforms for given draw call
3399 * @param program Program object
3400 * @param draw_call_index Index of draw call to be executed
3402 void DynamicViewportIndex::prepareUniforms(Utils::program& program, GLuint draw_call_index)
3404 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3406 GLint location = program.getUniformLocation("uni_index");
3408 gl.uniform1i(location, (GLint)draw_call_index);
3409 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform1i");
3414 * @param context Test context
3416 DrawMulitpleViewportsWithSingleInvocation::DrawMulitpleViewportsWithSingleInvocation(deqp::Context& context)
3417 : DrawTestBase(context, "draw_mulitple_viewports_with_single_invocation",
3418 "Test verifies that single invocation can output to multiple viewports")
3420 /* Nothing to be done here */
3423 /** Get string with fragment shader source code
3425 * @return Fragment shader source
3427 std::string DrawMulitpleViewportsWithSingleInvocation::getFragmentShader()
3429 static const GLchar* source = "#version 410 core\n"
3431 "flat in int gs_fs_color;\n"
3432 " out int fs_out_color;\n"
3436 " fs_out_color = gs_fs_color;\n"
3440 std::string result = source;
3445 /** Get string with geometry shader source code
3447 * @return Geometry shader source
3449 std::string DrawMulitpleViewportsWithSingleInvocation::getGeometryShader()
3451 static const GLchar* source = "#version 410 core\n"
3453 "layout(points, invocations = 1) in;\n"
3454 "layout(triangle_strip, max_vertices = 64) out;\n"
3456 "flat out int gs_fs_color;\n"
3458 "void routine(int index)\n"
3460 " gs_fs_color = index;\n"
3461 " gl_ViewportIndex = index;\n"
3462 " gl_Position = vec4(-1, -1, 0, 1);\n"
3464 " gs_fs_color = index;\n"
3465 " gl_ViewportIndex = index;\n"
3466 " gl_Position = vec4(-1, 1, 0, 1);\n"
3468 " gs_fs_color = index;\n"
3469 " gl_ViewportIndex = index;\n"
3470 " gl_Position = vec4(1, -1, 0, 1);\n"
3472 " gs_fs_color = index;\n"
3473 " gl_ViewportIndex = index;\n"
3474 " gl_Position = vec4(1, 1, 0, 1);\n"
3476 " EndPrimitive();\n"
3481 " for(int i = 0; i < 16; ++i)\n"
3488 std::string result = source;
3495 * @param context Test context
3497 ViewportIndexSubroutine::ViewportIndexSubroutine(deqp::Context& context)
3498 : DrawTestBase(context, "viewport_index_subroutine",
3499 "Test verifies subroutines can be used to output data to specific viewport")
3501 /* Nothing to be done here */
3504 /** Get string with fragment shader source code
3506 * @return Fragment shader source
3508 std::string ViewportIndexSubroutine::getFragmentShader()
3510 static const GLchar* source = "#version 410 core\n"
3512 "flat in int gs_fs_color;\n"
3513 " out int fs_out_color;\n"
3517 " fs_out_color = gs_fs_color;\n"
3521 std::string result = source;
3526 /** Get string with geometry shader source code
3528 * @return Geometry shader source
3530 std::string ViewportIndexSubroutine::getGeometryShader()
3532 static const GLchar* source = "#version 410 core\n"
3534 "layout(points, invocations = 1) in;\n"
3535 "layout(triangle_strip, max_vertices = 4) out;\n"
3537 "flat out int gs_fs_color;\n"
3539 "subroutine void indexSetter(void);\n"
3541 "subroutine(indexSetter) void four()\n"
3543 " gs_fs_color = 4;\n"
3544 " gl_ViewportIndex = 4;\n"
3547 "subroutine(indexSetter) void five()\n"
3549 " gs_fs_color = 5;\n"
3550 " gl_ViewportIndex = 5;\n"
3553 "subroutine uniform indexSetter routine;\n"
3558 " gl_Position = vec4(-1, -1, 0, 1);\n"
3561 " gl_Position = vec4(-1, 1, 0, 1);\n"
3564 " gl_Position = vec4(1, -1, 0, 1);\n"
3567 " gl_Position = vec4(1, 1, 0, 1);\n"
3572 std::string result = source;
3577 /** Check if R32I texture is filled with two halves, left is 4, right is either -1 or 5
3579 * @param texture_0 Verified texture
3581 * @param draw_call_index Draw call that was executed
3583 * @return True if texture_0 is filled with expected pattern
3585 bool ViewportIndexSubroutine::checkResults(Utils::texture& texture_0, Utils::texture& /* texture_1 */,
3586 GLuint draw_call_index)
3588 bool check_result = true;
3590 std::vector<GLint> texture_data;
3591 texture_data.resize(m_width * m_height);
3592 texture_0.get(GL_RED_INTEGER, GL_INT, &texture_data[0]);
3594 /* Left is 4 and right is -1, or left is 4 and right is 5 */
3595 GLint expected_left = 4;
3596 GLint expected_right = (1 == draw_call_index) ? 5 : -1;
3598 for (GLuint y = 0; y < 4; ++y)
3600 for (GLuint x = 0; x < 2; ++x)
3602 bool result = checkRegionR32I(x, y, expected_left, &texture_data[0]);
3604 if (false == result)
3606 check_result = false;
3612 for (GLuint y = 0; y < 4; ++y)
3614 for (GLuint x = 2; x < 4; ++x)
3616 bool result = checkRegionR32I(x, y, expected_right, &texture_data[0]);
3618 if (false == result)
3620 check_result = false;
3627 return check_result;
3630 /** Get number of draw call to be executed during test
3634 GLuint ViewportIndexSubroutine::getDrawCallsNumber()
3639 /** Prepare uniforms for given draw call
3641 * @param program Program object
3642 * @param draw_call_index Index of draw call to be executed
3644 void ViewportIndexSubroutine::prepareUniforms(Utils::program& program, GLuint draw_call_index)
3646 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3648 const GLchar* subroutine_name = (0 == draw_call_index) ? "four" : "five";
3650 GLint location = program.getSubroutineUniformLocation("routine", GL_GEOMETRY_SHADER);
3651 GLuint index = program.getSubroutineIndex(subroutine_name, GL_GEOMETRY_SHADER);
3655 TCU_FAIL("Something wrong, subroutine uniform location is not 0. Mistake in geometry shader?");
3658 gl.uniformSubroutinesuiv(GL_GEOMETRY_SHADER, 1, &index);
3659 GLU_EXPECT_NO_ERROR(gl.getError(), "UniformSubroutinesuiv");
3662 /** Set 4th viewport on left half and 5 on right half of framebuffer. Rest span over whole image.
3665 * @param iteration_index Index of iteration, used to select "viewport" method
3667 void ViewportIndexSubroutine::setupViewports(TEST_TYPE /* type */, glw::GLuint iteration_index)
3669 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3671 GLfloat data[2 * 4] = { 0.0f, 0.0f, 64.0f, 128.0f, 64.0f, 0.0f, 64.0f, 128.0f };
3673 gl.viewport(0, 0, m_width, m_height);
3674 GLU_EXPECT_NO_ERROR(gl.getError(), "Viewport");
3676 switch (iteration_index)
3680 gl.viewportArrayv(4, 2, data);
3681 GLU_EXPECT_NO_ERROR(gl.getError(), "ViewportArrayv");
3687 gl.viewportIndexedf(4, data[0], data[1], data[2], data[3]);
3688 GLU_EXPECT_NO_ERROR(gl.getError(), "ViewportIndexedf");
3690 gl.viewportIndexedf(5, data[4], data[5], data[6], data[7]);
3691 GLU_EXPECT_NO_ERROR(gl.getError(), "ViewportIndexedf");
3697 gl.viewportIndexedfv(4, &data[0]);
3698 GLU_EXPECT_NO_ERROR(gl.getError(), "ViewportIndexedfv");
3700 gl.viewportIndexedfv(5, &data[4]);
3701 GLU_EXPECT_NO_ERROR(gl.getError(), "ViewportIndexedfv");
3706 TCU_FAIL("Invalid value");
3712 * @param context Test context
3714 DrawMultipleLayers::DrawMultipleLayers(deqp::Context& context)
3715 : DrawTestBase(context, "draw_multiple_layers",
3716 "Test verifies that single viewport affects multiple layers in the same way")
3718 /* Nothing to be done here */
3723 * @param context Test context
3724 * @param test_name Test name
3725 * @param test_description Test description
3727 DrawMultipleLayers::DrawMultipleLayers(deqp::Context& context, const GLchar* test_name, const GLchar* test_description)
3728 : DrawTestBase(context, test_name, test_description)
3730 /* Nothing to be done here */
3733 /** Get string with fragment shader source code
3735 * @return Fragment shader source
3737 std::string DrawMultipleLayers::getFragmentShader()
3739 static const GLchar* source = "#version 410 core\n"
3741 "flat in int gs_fs_color;\n"
3742 " out int fs_out_color;\n"
3746 " fs_out_color = gs_fs_color;\n"
3750 std::string result = source;
3755 /** Get string with geometry shader source code
3757 * @return Geometry shader source
3759 std::string DrawMultipleLayers::getGeometryShader()
3761 static const GLchar* source = "#version 410 core\n"
3763 "layout(points, invocations = 16) in;\n"
3764 "layout(triangle_strip, max_vertices = 4) out;\n"
3766 "flat out int gs_fs_color;\n"
3770 " gs_fs_color = gl_InvocationID;\n"
3771 " gl_ViewportIndex = gl_InvocationID;\n"
3772 " gl_Layer = gl_InvocationID;\n"
3773 " gl_Position = vec4(-1, -1, 0, 1);\n"
3775 " gs_fs_color = gl_InvocationID;\n"
3776 " gl_ViewportIndex = gl_InvocationID;\n"
3777 " gl_Layer = gl_InvocationID;\n"
3778 " gl_Position = vec4(-1, 1, 0, 1);\n"
3780 " gs_fs_color = gl_InvocationID;\n"
3781 " gl_ViewportIndex = gl_InvocationID;\n"
3782 " gl_Layer = gl_InvocationID;\n"
3783 " gl_Position = vec4(1, -1, 0, 1);\n"
3785 " gs_fs_color = gl_InvocationID;\n"
3786 " gl_ViewportIndex = gl_InvocationID;\n"
3787 " gl_Layer = gl_InvocationID;\n"
3788 " gl_Position = vec4(1, 1, 0, 1);\n"
3793 std::string result = source;
3798 /** Check if R32I texture is filled with 4x4 regions of increasing values <0:15>
3800 * @param texture_0 Verified texture
3804 * @return True if texture_0 is filled with expected pattern
3806 bool DrawMultipleLayers::checkResults(Utils::texture& texture_0, Utils::texture& /* texture_1 */,
3807 GLuint /* draw_call_index */)
3809 static const GLuint layer_size = m_width * m_height;
3811 bool check_result = true;
3813 std::vector<GLint> texture_data;
3814 texture_data.resize(layer_size * m_depth);
3815 texture_0.get(GL_RED_INTEGER, GL_INT, &texture_data[0]);
3817 /* 16 layers, only region corresponding with layer index should be modified */
3818 for (GLuint layer = 0; layer < m_depth; ++layer)
3822 for (GLuint y = 0; y < 4; ++y)
3824 for (GLuint x = 0; x < 4; ++x)
3826 GLint* layer_data = &texture_data[layer * layer_size];
3828 GLint expected_value = -1;
3831 expected_value = index;
3834 bool result = checkRegionR32I(x, y, expected_value, layer_data);
3836 if (false == result)
3838 check_result = false;
3848 return check_result;
3851 /** Prepare textures used as framebuffer's attachments for current draw call
3853 * @param texture_0 R32I texture
3856 void DrawMultipleLayers::prepareTextures(Utils::texture& texture_0, Utils::texture& /* texture_1 */)
3858 prepareTextureArrayR32I(texture_0);
3863 * @param context Test context
3864 * @param test_name Test name
3865 * @param test_description Test description
3867 Scissor::Scissor(deqp::Context& context)
3868 : DrawMultipleLayers(context, "scissor", "Test verifies that scissor test is applied as expected")
3870 /* Nothing to be done here */
3877 DrawTestBase::TEST_TYPE Scissor::getTestType()
3884 * @param context Test context
3885 * @param test_name Test name
3886 * @param test_description Test description
3888 ScissorZeroDimension::ScissorZeroDimension(deqp::Context& context)
3889 : DrawMultipleLayers(context, "scissor_zero_dimension",
3890 "Test verifies that scissor test discard all fragments when width and height is set to zero")
3892 /* Nothing to be done here */
3895 /** Check if R32I texture is filled with 4x4 regions of increasing values <0:15>
3897 * @param texture_0 Verified texture
3901 * @return True if texture_0 is filled with expected pattern
3903 bool ScissorZeroDimension::checkResults(Utils::texture& texture_0, Utils::texture& /* texture_1 */,
3904 GLuint /* draw_call_index */)
3906 static const GLuint layer_size = m_width * m_height;
3908 bool check_result = true;
3910 std::vector<GLint> texture_data;
3911 texture_data.resize(layer_size * m_depth);
3912 texture_0.get(GL_RED_INTEGER, GL_INT, &texture_data[0]);
3914 /* 16 layers, all regions were not modified */
3915 for (GLuint layer = 0; layer < m_depth; ++layer)
3917 for (GLuint y = 0; y < 4; ++y)
3919 for (GLuint x = 0; x < 4; ++x)
3921 GLint* layer_data = &texture_data[layer * layer_size];
3923 GLint expected_value = -1;
3925 bool result = checkRegionR32I(x, y, expected_value, layer_data);
3927 if (false == result)
3929 check_result = false;
3937 return check_result;
3944 DrawTestBase::TEST_TYPE ScissorZeroDimension::getTestType()
3949 /** Set up viewports
3952 * @param iteration_index Index of iteration for given test type
3954 void ScissorZeroDimension::setupViewports(TEST_TYPE /* type */, GLuint iteration_index)
3956 SCISSOR_METHOD method;
3957 switch (iteration_index)
3962 method = (SCISSOR_METHOD)iteration_index;
3965 TCU_FAIL("Invalid value");
3968 setup4x4Scissor(method, true /* set_zeros */);
3973 * @param context Test context
3974 * @param test_name Test name
3975 * @param test_description Test description
3977 ScissorClear::ScissorClear(deqp::Context& context)
3978 : DrawMultipleLayers(context, "scissor_clear",
3979 "Test verifies that Clear is affected only by settings of scissor test in first viewport")
3981 /* Nothing to be done here */
3984 /** Check if R32I texture is filled with 4x4 regions of increasing values <0:15>
3986 * @param texture_0 Verified texture
3990 * @return True if texture_0 is filled with expected pattern
3992 bool ScissorClear::checkResults(Utils::texture& texture_0, Utils::texture& /* texture_1 */, GLuint /*draw_call_index */)
3994 static const GLuint layer_size = m_width * m_height;
3996 bool check_result = true;
3998 std::vector<GLint> texture_data;
3999 texture_data.resize(layer_size * m_depth);
4000 texture_0.get(GL_RED_INTEGER, GL_INT, &texture_data[0]);
4002 /* 16 layers, only region corresponding with scissor box 0 should be modified */
4003 for (GLuint layer = 0; layer < m_depth; ++layer)
4005 for (GLuint y = 0; y < 4; ++y)
4007 for (GLuint x = 0; x < 4; ++x)
4009 GLint* layer_data = &texture_data[layer * layer_size];
4011 GLint expected_value = -1;
4012 if ((0 == x) && (0 == y))
4017 bool result = checkRegionR32I(x, y, expected_value, layer_data);
4019 if (false == result)
4021 check_result = false;
4029 return check_result;
4036 DrawTestBase::TEST_TYPE ScissorClear::getTestType()
4041 /** Selects if test should do draw or clear operation
4043 * @return true - clear operation
4045 bool ScissorClear::isClearTest()
4052 * @param context Test context
4053 * @param test_name Test name
4054 * @param test_description Test description
4056 DepthRange::DepthRange(deqp::Context& context)
4057 : DrawTestBase(context, "depth_range", "Test verifies that depth range is applied as expected")
4059 /* Nothing to be done here */
4062 /** Check if R32F texture is filled with two rows, top with decreasing values, bottom with incresing values
4064 * @param texture_0 Verified texture
4068 * @return True if texture_0 is filled with expected pattern
4070 bool DepthRange::checkResults(Utils::texture& texture_0, Utils::texture& /* texture_1 */, GLuint /*draw_call_index */)
4072 static const GLfloat step = 1.0f / 16.0f;
4074 bool check_result = true;
4076 std::vector<GLfloat> texture_data;
4077 texture_data.resize(m_r32f_width * m_r32f_height);
4078 texture_0.get(GL_RED, GL_FLOAT, &texture_data[0]);
4080 GLfloat depth_data[16 * 2];
4082 for (GLuint i = 0; i < 16; ++i)
4084 const GLfloat near = step * (GLfloat)i;
4086 depth_data[i * 2 + 0] = near;
4087 depth_data[i * 2 + 1] = 1.0f - near;
4090 for (GLuint i = 0; i < 16; ++i)
4092 const GLfloat expected_near = depth_data[i * 2 + 0];
4093 const GLfloat expected_far = depth_data[i * 2 + 1];
4095 /* Bottom row should contain near values, top one should contain far values */
4096 const GLfloat near = texture_data[i];
4097 const GLfloat far = texture_data[i + 16];
4099 if ((expected_near != near) || (expected_far != far))
4101 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid values at " << i << " expected ["
4102 << expected_near << ", " << expected_far << "] got [" << near << ", "
4103 << far << "]" << tcu::TestLog::EndMessage;
4105 check_result = false;
4110 return check_result;
4113 /** Get string with fragment shader source code
4115 * @return Fragment shader source
4117 std::string DepthRange::getFragmentShader()
4119 static const GLchar* source = "#version 410 core\n"
4121 "out float fs_out_color;\n"
4125 " fs_out_color = gl_FragCoord.z;\n"
4129 std::string result = source;
4134 /** Get string with geometry shader source code
4136 * @return Geometry shader source
4138 std::string DepthRange::getGeometryShader()
4140 static const GLchar* source = "#version 410 core\n"
4142 "layout(points, invocations = 16) in;\n"
4143 "layout(triangle_strip, max_vertices = 8) out;\n"
4147 " const float top_z = 1.0;\n"
4148 " const float bottom_z = -1.0;\n"
4151 " gl_ViewportIndex = gl_InvocationID;\n"
4152 " gl_Position = vec4(-1, -1, bottom_z, 1);\n"
4154 " gl_ViewportIndex = gl_InvocationID;\n"
4155 " gl_Position = vec4(-1, 0, bottom_z, 1);\n"
4157 " gl_ViewportIndex = gl_InvocationID;\n"
4158 " gl_Position = vec4(1, -1, bottom_z, 1);\n"
4160 " gl_ViewportIndex = gl_InvocationID;\n"
4161 " gl_Position = vec4(1, 0, bottom_z, 1);\n"
4163 " EndPrimitive();\n"
4166 " gl_ViewportIndex = gl_InvocationID;\n"
4167 " gl_Position = vec4(-1, 0, top_z, 1);\n"
4169 " gl_ViewportIndex = gl_InvocationID;\n"
4170 " gl_Position = vec4(-1, 1, top_z, 1);\n"
4172 " gl_ViewportIndex = gl_InvocationID;\n"
4173 " gl_Position = vec4(1, 0, top_z, 1);\n"
4175 " gl_ViewportIndex = gl_InvocationID;\n"
4176 " gl_Position = vec4(1, 1, top_z, 1);\n"
4178 " EndPrimitive();\n"
4182 std::string result = source;
4189 * @return DEPTHRANGE
4191 DrawTestBase::TEST_TYPE DepthRange::getTestType()
4196 /** Prepare textures used as framebuffer's attachments for current draw call
4198 * @param texture_0 R32F texture
4201 void DepthRange::prepareTextures(Utils::texture& texture_0, Utils::texture& /* texture_1 */)
4203 prepareTextureR32F(texture_0);
4208 * @param context Test context
4209 * @param test_name Test name
4210 * @param test_description Test description
4212 DepthRangeDepthTest::DepthRangeDepthTest(deqp::Context& context)
4213 : DrawTestBase(context, "depth_range_depth_test",
4214 "Test verifies that depth test work as expected with multiple viewports")
4216 /* Nothing to be done here */
4219 /** Check if R32F texture is filled with two rows of values less than expected depth
4221 * @param texture_0 Verified texture
4223 * @param draw_call_index Index of draw call
4225 * @return True if texture_0 is filled with expected pattern
4227 bool DepthRangeDepthTest::checkResults(Utils::texture& texture_0, Utils::texture& /* texture_1 */,
4228 GLuint draw_call_index)
4230 static const GLfloat step = 1.0f / 16.0f;
4232 const GLfloat depth_value = step * (GLfloat)draw_call_index;
4234 bool check_result = true;
4236 std::vector<GLfloat> texture_data;
4237 texture_data.resize(m_r32f_width * m_r32f_height);
4238 texture_0.get(GL_RED, GL_FLOAT, &texture_data[0]);
4240 for (GLuint i = 0; i < 16; ++i)
4242 /* Bottom row should contain near values, top one should contain far values */
4243 const GLfloat near = texture_data[i];
4244 const GLfloat far = texture_data[i + 16];
4246 if ((depth_value <= near) || (depth_value <= far))
4248 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Invalid values at " << i << " depth value "
4249 << depth_value << " got [" << near << ", " << far << "]"
4250 << tcu::TestLog::EndMessage;
4252 check_result = false;
4257 return check_result;
4260 /** Get settings of clear operation
4262 * @param clear_depth_before_draw Selects if clear should be executed before draw.
4263 * @param iteration_index Index of draw call
4264 * @param depth_value Value that will be used to clear depth buffer
4266 void DepthRangeDepthTest::getClearSettings(bool& clear_depth_before_draw, GLuint iteration_index, GLdouble& depth_value)
4268 static const GLdouble step = 1.0 / 16.0;
4270 clear_depth_before_draw = true;
4272 depth_value = step * (GLdouble)iteration_index;
4275 /** Get number of draw call to be executed during test
4279 GLuint DepthRangeDepthTest::getDrawCallsNumber()
4284 /** Get string with fragment shader source code
4286 * @return Fragment shader source
4288 std::string DepthRangeDepthTest::getFragmentShader()
4290 static const GLchar* source = "#version 410 core\n"
4292 "out float fs_out_color;\n"
4296 " fs_out_color = gl_FragCoord.z;\n"
4300 std::string result = source;
4305 /** Get string with geometry shader source code
4307 * @return Geometry shader source
4309 std::string DepthRangeDepthTest::getGeometryShader()
4311 static const GLchar* source = "#version 410 core\n"
4313 "layout(points, invocations = 16) in;\n"
4314 "layout(triangle_strip, max_vertices = 8) out;\n"
4318 " const float top_z = 1.0;\n"
4319 " const float bottom_z = -1.0;\n"
4322 " gl_ViewportIndex = gl_InvocationID;\n"
4323 " gl_Position = vec4(-1, -1, bottom_z, 1);\n"
4325 " gl_ViewportIndex = gl_InvocationID;\n"
4326 " gl_Position = vec4(-1, 0, bottom_z, 1);\n"
4328 " gl_ViewportIndex = gl_InvocationID;\n"
4329 " gl_Position = vec4(1, -1, bottom_z, 1);\n"
4331 " gl_ViewportIndex = gl_InvocationID;\n"
4332 " gl_Position = vec4(1, 0, bottom_z, 1);\n"
4336 " gl_ViewportIndex = gl_InvocationID;\n"
4337 " gl_Position = vec4(-1, 0, top_z, 1);\n"
4339 " gl_ViewportIndex = gl_InvocationID;\n"
4340 " gl_Position = vec4(-1, 1, top_z, 1);\n"
4342 " gl_ViewportIndex = gl_InvocationID;\n"
4343 " gl_Position = vec4(1, 0, top_z, 1);\n"
4345 " gl_ViewportIndex = gl_InvocationID;\n"
4346 " gl_Position = vec4(1, 1, top_z, 1);\n"
4348 " EndPrimitive();\n"
4352 std::string result = source;
4359 * @return DEPTHRANGE
4361 DrawTestBase::TEST_TYPE DepthRangeDepthTest::getTestType()
4366 /** Prepare textures used as framebuffer's attachments for current draw call
4368 * @param texture_0 R32F texture
4369 * @param texture_1 D32F texture
4371 void DepthRangeDepthTest::prepareTextures(Utils::texture& texture_0, Utils::texture& texture_1)
4373 prepareTextureR32F(texture_0);
4374 prepareTextureD32F(texture_1);
4377 /** Attach textures to framebuffer
4379 * @param framebuffer Framebuffer instance
4380 * @param texture_0 Texture attached as color 0
4381 * @param texture_1 Texture attached as depth
4383 void DepthRangeDepthTest::setupFramebuffer(Utils::framebuffer& framebuffer, Utils::texture& texture_0,
4384 Utils::texture& texture_1)
4386 framebuffer.attachTexture(GL_COLOR_ATTACHMENT0, texture_0.m_id, m_width, m_height);
4387 framebuffer.attachTexture(GL_DEPTH_ATTACHMENT, texture_1.m_id, m_width, m_height);
4390 /** Set up viewports
4393 * @param iteration_index Index of iteration for given test type
4395 void DepthRangeDepthTest::setupViewports(TEST_TYPE /* type */, GLuint iteration_index)
4397 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4399 DEPTH_RANGE_METHOD method;
4400 switch (iteration_index)
4404 method = (DEPTH_RANGE_METHOD)iteration_index;
4407 TCU_FAIL("Invalid value");
4409 setup16x2Depths(method);
4411 gl.enable(GL_DEPTH_TEST);
4412 GLU_EXPECT_NO_ERROR(gl.getError(), "Enable");
4417 * @param context Test context
4418 * @param test_name Test name
4419 * @param test_description Test description
4421 ProvokingVertex::ProvokingVertex(deqp::Context& context)
4422 : DrawTestBase(context, "provoking_vertex", "Test verifies that provoking vertex work as expected")
4424 /* Nothing to be done here */
4427 /** Check if R32I texture is filled with 4x4 regions of increasing values <0:15>
4429 * @param texture_0 Verified texture
4433 * @return True if texture_0 is filled with expected pattern
4435 bool ProvokingVertex::checkResults(Utils::texture& texture_0, Utils::texture& /* texture_1 */,
4436 GLuint /*draw_call_index */)
4438 static const GLuint layer_size = m_width * m_height;
4440 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4442 GLint layer_mode = 0;
4443 GLint viewport_mode = 0;
4444 gl.getIntegerv(GL_LAYER_PROVOKING_VERTEX, &layer_mode);
4445 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
4446 gl.getIntegerv(GL_VIEWPORT_INDEX_PROVOKING_VERTEX, &viewport_mode);
4447 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
4449 if ((GL_UNDEFINED_VERTEX == layer_mode) || (GL_UNDEFINED_VERTEX == viewport_mode))
4451 /* Results are undefined, therefore it does not make sense to verify them */
4455 bool check_result = true;
4456 GLint provoking = 0;
4458 std::vector<GLint> texture_data;
4459 texture_data.resize(layer_size * m_r32ix4_depth);
4460 texture_0.get(GL_RED_INTEGER, GL_INT, &texture_data[0]);
4462 gl.getIntegerv(GL_PROVOKING_VERTEX, &provoking);
4463 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
4465 GLuint expected_layer = 0;
4466 GLint expected_viewport = 0;
4468 /* Mode is 1st, or mode is provoking and provoking is 1st */
4469 if ((GL_FIRST_VERTEX_CONVENTION == layer_mode) ||
4470 ((GL_PROVOKING_VERTEX == layer_mode) && (GL_FIRST_VERTEX_CONVENTION == provoking)))
4479 if ((GL_FIRST_VERTEX_CONVENTION == viewport_mode) ||
4480 ((GL_PROVOKING_VERTEX == viewport_mode) && (GL_FIRST_VERTEX_CONVENTION == provoking)))
4482 expected_viewport = 0;
4486 expected_viewport = 2;
4489 for (GLuint layer = 0; layer < m_r32ix4_depth; ++layer)
4491 GLint* layer_data = &texture_data[layer * layer_size];
4494 for (GLuint y = 0; y < 2; ++y)
4496 for (GLuint x = 0; x < 2; ++x)
4498 /* If layer and viewport are expected ones, than result shall be 1, otherwise -1. */
4499 const GLint expected_value = ((expected_viewport == viewport) && (expected_layer == layer)) ? 1 : -1;
4501 bool result = checkRegionR32I(x, y, m_width / 2, m_height / 2, expected_value, layer_data);
4503 if (false == result)
4505 check_result = false;
4515 return check_result;
4518 /** Get string with fragment shader source code
4520 * @return Fragment shader source
4522 std::string ProvokingVertex::getFragmentShader()
4524 static const GLchar* source = "#version 410 core\n"
4526 "flat in int gs_fs_color;\n"
4527 " out int fs_out_color;\n"
4531 " fs_out_color = gs_fs_color;\n"
4535 std::string result = source;
4540 /** Get string with geometry shader source code
4542 * @return Geometry shader source
4544 std::string ProvokingVertex::getGeometryShader()
4546 static const GLchar* source = "#version 410 core\n"
4548 "layout(points, invocations = 1) in;\n"
4549 "layout(triangle_strip, max_vertices = 6) out;\n"
4551 "flat out int gs_fs_color;\n"
4555 " /* Left-bottom half */\n"
4556 " gs_fs_color = 1;\n"
4557 " gl_ViewportIndex = 0;\n"
4559 " gl_Position = vec4(-1, -1, 0, 1);\n"
4561 " gs_fs_color = 1;\n"
4562 " gl_ViewportIndex = 1;\n"
4564 " gl_Position = vec4(-1, 1, 0, 1);\n"
4566 " gs_fs_color = 1;\n"
4567 " gl_ViewportIndex = 2;\n"
4569 " gl_Position = vec4(1, -1, 0, 1);\n"
4571 " EndPrimitive();\n"
4573 " /* Right-top half */\n"
4574 " gs_fs_color = 1;\n"
4575 " gl_ViewportIndex = 0;\n"
4577 " gl_Position = vec4(-1, 1, 0, 1);\n"
4579 " gs_fs_color = 1;\n"
4580 " gl_ViewportIndex = 1;\n"
4582 " gl_Position = vec4(1, 1, 0, 1);\n"
4584 " gs_fs_color = 1;\n"
4585 " gl_ViewportIndex = 2;\n"
4587 " gl_Position = vec4(1, -1, 0, 1);\n"
4589 " EndPrimitive();\n"
4593 std::string result = source;
4602 DrawTestBase::TEST_TYPE ProvokingVertex::getTestType()
4607 /** Prepare textures used as framebuffer's attachments for current draw call
4609 * @param texture_0 R32I texture
4612 void ProvokingVertex::prepareTextures(Utils::texture& texture_0, Utils::texture& /* texture_1 */)
4614 prepareTextureR32Ix4(texture_0);
4617 } /* ViewportArray namespace */
4621 * @param context Rendering context.
4623 ViewportArrayTests::ViewportArrayTests(deqp::Context& context)
4624 : TestCaseGroup(context, "viewport_array", "Verifies \"viewport_array\" functionality")
4626 /* Left blank on purpose */
4629 /** Initializes a texture_storage_multisample test group.
4632 void ViewportArrayTests::init(void)
4634 addChild(new ViewportArray::APIErrors(m_context));
4635 addChild(new ViewportArray::Queries(m_context));
4636 addChild(new ViewportArray::ViewportAPI(m_context));
4637 addChild(new ViewportArray::ScissorAPI(m_context));
4638 addChild(new ViewportArray::DepthRangeAPI(m_context));
4639 addChild(new ViewportArray::ScissorTestStateAPI(m_context));
4640 addChild(new ViewportArray::DrawToSingleLayerWithMultipleViewports(m_context));
4641 addChild(new ViewportArray::DynamicViewportIndex(m_context));
4642 addChild(new ViewportArray::DrawMulitpleViewportsWithSingleInvocation(m_context));
4643 addChild(new ViewportArray::ViewportIndexSubroutine(m_context));
4644 addChild(new ViewportArray::DrawMultipleLayers(m_context));
4645 addChild(new ViewportArray::Scissor(m_context));
4646 addChild(new ViewportArray::ScissorZeroDimension(m_context));
4647 addChild(new ViewportArray::ScissorClear(m_context));
4648 addChild(new ViewportArray::DepthRange(m_context));
4649 addChild(new ViewportArray::DepthRangeDepthTest(m_context));
4650 addChild(new ViewportArray::ProvokingVertex(m_context));
4653 } /* glcts namespace */