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