1/*------------------------------------------------------------------------- 2 * OpenGL Conformance Test Suite 3 * ----------------------------- 4 * 5 * Copyright (c) 2015-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 */ /*! 26 * \file gl4cDirectStateAccessProgramPipelinesTests.cpp 27 * \brief Conformance tests for the Direct State Access feature functionality (Program Pipelines part). 28 */ /*-----------------------------------------------------------------------------------------------------------*/ 29 30/* Includes. */ 31#include "gl4cDirectStateAccessTests.hpp" 32 33#include "deSharedPtr.hpp" 34 35#include "gluContextInfo.hpp" 36#include "gluDefs.hpp" 37#include "gluPixelTransfer.hpp" 38#include "gluStrUtil.hpp" 39 40#include "tcuFuzzyImageCompare.hpp" 41#include "tcuImageCompare.hpp" 42#include "tcuRenderTarget.hpp" 43#include "tcuSurface.hpp" 44#include "tcuTestLog.hpp" 45 46#include "glw.h" 47#include "glwFunctions.hpp" 48 49namespace gl4cts 50{ 51namespace DirectStateAccess 52{ 53namespace ProgramPipelines 54{ 55/******************************** Creation Test Implementation ********************************/ 56 57/** @brief Creation Test constructor. 58 * 59 * @param [in] context OpenGL context. 60 */ 61CreationTest::CreationTest(deqp::Context& context) 62 : deqp::TestCase(context, "program_pipelines_creation", "Program Pipeline Objects Creation Test") 63{ 64 /* Intentionally left blank. */ 65} 66 67/** @brief Iterate Creation Test cases. 68 * 69 * @return Iteration result. 70 */ 71tcu::TestNode::IterateResult CreationTest::iterate() 72{ 73 /* Shortcut for GL functionality */ 74 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 75 76 /* Get context setup. */ 77 bool is_at_least_gl_45 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 5))); 78 bool is_arb_direct_state_access = m_context.getContextInfo().isExtensionSupported("GL_ARB_direct_state_access"); 79 80 if ((!is_at_least_gl_45) && (!is_arb_direct_state_access)) 81 { 82 m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported"); 83 84 return STOP; 85 } 86 87 /* Running tests. */ 88 bool is_ok = true; 89 bool is_error = false; 90 91 /* Program pipeline objects */ 92 static const glw::GLuint program_pipelines_count = 2; 93 94 glw::GLuint program_pipelines_legacy[program_pipelines_count] = {}; 95 glw::GLuint program_pipelines_dsa[program_pipelines_count] = {}; 96 97 try 98 { 99 /* Check legacy state creation. */ 100 gl.genProgramPipelines(program_pipelines_count, program_pipelines_legacy); 101 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenProgramPipelines have failed"); 102 103 for (glw::GLuint i = 0; i < program_pipelines_count; ++i) 104 { 105 if (gl.isProgramPipeline(program_pipelines_legacy[i])) 106 { 107 is_ok = false; 108 109 /* Log. */ 110 m_context.getTestContext().getLog() 111 << tcu::TestLog::Message 112 << "GenProgramPipelines has created default objects, but it should create only a names." 113 << tcu::TestLog::EndMessage; 114 } 115 } 116 117 /* Check direct state creation. */ 118 gl.createProgramPipelines(program_pipelines_count, program_pipelines_dsa); 119 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgramPipelines have failed"); 120 121 for (glw::GLuint i = 0; i < program_pipelines_count; ++i) 122 { 123 if (!gl.isProgramPipeline(program_pipelines_dsa[i])) 124 { 125 is_ok = false; 126 127 /* Log. */ 128 m_context.getTestContext().getLog() << tcu::TestLog::Message 129 << "CreateProgramPipelines has not created default objects." 130 << tcu::TestLog::EndMessage; 131 } 132 } 133 } 134 catch (...) 135 { 136 is_ok = false; 137 is_error = true; 138 } 139 140 /* Cleanup. */ 141 for (glw::GLuint i = 0; i < program_pipelines_count; ++i) 142 { 143 if (program_pipelines_legacy[i]) 144 { 145 gl.deleteProgramPipelines(1, &program_pipelines_legacy[i]); 146 147 program_pipelines_legacy[i] = 0; 148 } 149 150 if (program_pipelines_dsa[i]) 151 { 152 gl.deleteProgramPipelines(1, &program_pipelines_dsa[i]); 153 154 program_pipelines_dsa[i] = 0; 155 } 156 } 157 158 /* Result's setup. */ 159 if (is_ok) 160 { 161 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 162 } 163 else 164 { 165 if (is_error) 166 { 167 m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error"); 168 } 169 else 170 { 171 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 172 } 173 } 174 175 return STOP; 176} 177 178/******************************** Defaults Test Implementation ********************************/ 179 180/** @brief Defaults Test constructor. 181 * 182 * @param [in] context OpenGL context. 183 */ 184DefaultsTest::DefaultsTest(deqp::Context& context) 185 : deqp::TestCase(context, "program_pipelines_defaults", "Program Pipelines Defaults Test") 186 , m_program_pipeline_dsa(0) 187{ 188 /* Intentionally left blank. */ 189} 190 191/** @brief Iterate Defaults Test cases. 192 * 193 * @return Iteration result. 194 */ 195tcu::TestNode::IterateResult DefaultsTest::iterate() 196{ 197 /* Get context setup. */ 198 bool is_at_least_gl_45 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 5))); 199 bool is_arb_direct_state_access = m_context.getContextInfo().isExtensionSupported("GL_ARB_direct_state_access"); 200 201 if ((!is_at_least_gl_45) && (!is_arb_direct_state_access)) 202 { 203 m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported"); 204 205 return STOP; 206 } 207 208 /* Running tests. */ 209 bool is_ok = true; 210 bool is_error = false; 211 212 try 213 { 214 prepare(); 215 216 is_ok &= testProgramPipelineParameter(GL_ACTIVE_PROGRAM, 0); 217 is_ok &= testProgramPipelineParameter(GL_VERTEX_SHADER, 0); 218 is_ok &= testProgramPipelineParameter(GL_GEOMETRY_SHADER, 0); 219 is_ok &= testProgramPipelineParameter(GL_FRAGMENT_SHADER, 0); 220 is_ok &= testProgramPipelineParameter(GL_COMPUTE_SHADER, 0); 221 is_ok &= testProgramPipelineParameter(GL_TESS_CONTROL_SHADER, 0); 222 is_ok &= testProgramPipelineParameter(GL_TESS_EVALUATION_SHADER, 0); 223 is_ok &= testProgramPipelineParameter(GL_VALIDATE_STATUS, 0); 224 is_ok &= testProgramPipelineParameter(GL_INFO_LOG_LENGTH, 0); 225 226 is_ok &= testProgramPipelineInfoLog(DE_NULL); 227 } 228 catch (...) 229 { 230 is_ok = false; 231 is_error = true; 232 } 233 234 /* Clean up. */ 235 clean(); 236 237 /* Result's setup. */ 238 if (is_ok) 239 { 240 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 241 } 242 else 243 { 244 if (is_error) 245 { 246 m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error"); 247 } 248 else 249 { 250 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 251 } 252 } 253 254 return STOP; 255} 256 257/** @brief Create Program Pipeline Objects. 258 * 259 * @note The function may throw if unexpected error has occured. 260 * 261 * @return True if test succeeded, false otherwise. 262 */ 263void DefaultsTest::prepare() 264{ 265 /* Shortcut for GL functionality */ 266 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 267 268 /* Program Pipeline object creation */ 269 gl.createProgramPipelines(1, &m_program_pipeline_dsa); 270 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgramPipelines have failed"); 271} 272 273/** @brief Test if Program Pipeline Parameter has value as expected. 274 * 275 * @note The function may throw if unexpected error has occured. 276 * 277 * @param [in] pname Parameter name enumeration. Must be one of 278 * GL_ACTIVE_PROGRAM, GL_VERTEX_SHADER, GL_TESS_CONTROL_SHADER, 279 * GL_TESS_EVALUATION_SHADER, GL_GEOMETRY_SHADER, 280 * GL_FRAGMENT_SHADER, GL_INFO_LOG_LENGTH. 281 * @param [in] expected_value Reference value to be compared. 282 * 283 * @return True if test succeeded, false otherwise. 284 */ 285bool DefaultsTest::testProgramPipelineParameter(glw::GLenum pname, glw::GLint expected_value) 286{ 287 /* Shortcut for GL functionality */ 288 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 289 290 /* Get data. */ 291 glw::GLint value = -1; 292 293 gl.getProgramPipelineiv(m_program_pipeline_dsa, pname, &value); 294 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramPipelineiv have failed"); 295 296 if (-1 == value) 297 { 298 m_context.getTestContext().getLog() << tcu::TestLog::Message << "glGetProgramPipelineiv with parameter " 299 << pname << " has not returned anything and error has not been generated." 300 << tcu::TestLog::EndMessage; 301 302 return false; 303 } 304 else 305 { 306 if (expected_value != value) 307 { 308 m_context.getTestContext().getLog() << tcu::TestLog::Message << "glGetProgramPipelineiv with parameter " 309 << pname << " has returned " << value << ", however " << expected_value 310 << " was expected." << tcu::TestLog::EndMessage; 311 312 return false; 313 } 314 } 315 316 return true; 317} 318 319/** @brief Test if Program Pipeline Parameter has value as expected. 320 * 321 * @note The function may throw if unexpected error has occured. 322 * 323 * @param [in] expected_value Reference value to be compared. 324 * 325 * @return True if test succeeded, false otherwise. 326 */ 327bool DefaultsTest::testProgramPipelineInfoLog(glw::GLchar* expected_value) 328{ 329 /* Shortcut for GL functionality */ 330 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 331 332 /* Comparison limit. */ 333 static const glw::GLsizei max_log_size = 4096; 334 335 /* Storage for data. */ 336 glw::GLchar log[max_log_size] = { 0 }; 337 338 /* Storage fetched length. */ 339 glw::GLsizei log_size = 0; 340 341 /* Fetch. */ 342 gl.getProgramPipelineInfoLog(m_program_pipeline_dsa, max_log_size, &log_size, log); 343 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramPipelineInfoLog have failed"); 344 345 /* Comparison. */ 346 if (DE_NULL == expected_value) 347 { 348 if (0 != log_size) 349 { 350 m_context.getTestContext().getLog() 351 << tcu::TestLog::Message 352 << "glGetProgramPipelineInfoLog returned unexpectedly non-empty string: " << log << "." 353 << tcu::TestLog::EndMessage; 354 355 return false; 356 } 357 358 return true; 359 } 360 361 if (0 != strcmp(log, expected_value)) 362 { 363 m_context.getTestContext().getLog() 364 << tcu::TestLog::Message << "glGetProgramPipelineInfoLog returned string: " << log 365 << ", but is not the same as expected: " << expected_value << "." << tcu::TestLog::EndMessage; 366 367 return false; 368 } 369 370 return true; 371} 372 373/** @brief Release GL objects. 374 */ 375void DefaultsTest::clean() 376{ 377 /* Shortcut for GL functionality */ 378 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 379 380 if (m_program_pipeline_dsa) 381 { 382 gl.deleteProgramPipelines(1, &m_program_pipeline_dsa); 383 384 m_program_pipeline_dsa = 0; 385 } 386} 387 388/******************************** Errors Test Implementation ********************************/ 389 390/** @brief Errors Test constructor. 391 * 392 * @param [in] context OpenGL context. 393 */ 394ErrorsTest::ErrorsTest(deqp::Context& context) 395 : deqp::TestCase(context, "program_pipelines_errors", "Program Pipeline Objects Errors Test") 396{ 397 /* Intentionally left blank. */ 398} 399 400/** @brief Iterate Errors Test cases. 401 * 402 * @return Iteration result. 403 */ 404tcu::TestNode::IterateResult ErrorsTest::iterate() 405{ 406 /* Shortcut for GL functionality */ 407 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 408 409 /* Get context setup. */ 410 bool is_at_least_gl_45 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 5))); 411 bool is_arb_direct_state_access = m_context.getContextInfo().isExtensionSupported("GL_ARB_direct_state_access"); 412 413 if ((!is_at_least_gl_45) && (!is_arb_direct_state_access)) 414 { 415 m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported"); 416 417 return STOP; 418 } 419 420 /* Running tests. */ 421 bool is_ok = true; 422 bool is_error = false; 423 424 glw::GLuint program_pipeline_dsa = 0; 425 426 try 427 { 428 /* Check direct state creation. */ 429 gl.createProgramPipelines(-1, &program_pipeline_dsa); 430 431 glw::GLenum error = GL_NO_ERROR; 432 433 if (GL_INVALID_VALUE != (error = gl.getError())) 434 { 435 is_ok = false; 436 437 /* Log. */ 438 m_context.getTestContext().getLog() 439 << tcu::TestLog::Message << "CreateProgramPipelines has not generated INVALID_VALUE error when callded " 440 "with negative number of objects to be created." 441 << "Instead, " << glu::getErrorStr(error) << " error value was generated." << tcu::TestLog::EndMessage; 442 } 443 } 444 catch (...) 445 { 446 is_ok = false; 447 is_error = true; 448 } 449 450 /* Cleanup. */ 451 if (program_pipeline_dsa) 452 { 453 gl.deleteProgramPipelines(1, &program_pipeline_dsa); 454 455 program_pipeline_dsa = 0; 456 } 457 458 /* Result's setup. */ 459 if (is_ok) 460 { 461 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 462 } 463 else 464 { 465 if (is_error) 466 { 467 m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error"); 468 } 469 else 470 { 471 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 472 } 473 } 474 475 return STOP; 476} 477 478/******************************** Functional Test Implementation ********************************/ 479 480/** @brief Functional Test constructor. 481 * 482 * @param [in] context OpenGL context. 483 */ 484FunctionalTest::FunctionalTest(deqp::Context& context) 485 : deqp::TestCase(context, "program_pipelines_functional", "Program Pipeline Objects Functional Test") 486 , m_fbo(0) 487 , m_rbo(0) 488 , m_vao(0) 489 , m_spo_v(0) 490 , m_spo_f(0) 491 , m_ppo(0) 492{ 493 /* Intentionally left blank. */ 494} 495 496/** @brief Iterate Functional Test cases. 497 * 498 * @return Iteration result. 499 */ 500tcu::TestNode::IterateResult FunctionalTest::iterate() 501{ 502 /* Get context setup. */ 503 bool is_at_least_gl_45 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 5))); 504 bool is_arb_direct_state_access = m_context.getContextInfo().isExtensionSupported("GL_ARB_direct_state_access"); 505 506 if ((!is_at_least_gl_45) && (!is_arb_direct_state_access)) 507 { 508 m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported"); 509 510 return STOP; 511 } 512 513 /* Running tests. */ 514 bool is_ok = true; 515 bool is_error = false; 516 517 try 518 { 519 prepareFramebuffer(); 520 prepareVertexArrayObject(); 521 prepareShaderPrograms(); 522 preparePipeline(); 523 draw(); 524 525 is_ok &= checkFramebufferContent(); 526 } 527 catch (...) 528 { 529 is_ok = false; 530 is_error = true; 531 } 532 533 /* Clean-up. */ 534 clean(); 535 536 /* Result's setup. */ 537 if (is_ok) 538 { 539 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 540 } 541 else 542 { 543 if (is_error) 544 { 545 m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error"); 546 } 547 else 548 { 549 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 550 } 551 } 552 553 return STOP; 554} 555 556/** @brief Function prepares framebuffer with RGBA8 color attachment. 557 * Viewport is set up. Content of the framebuffer is cleared. 558 * 559 * @note The function may throw if unexpected error has occured. 560 */ 561void FunctionalTest::prepareFramebuffer() 562{ 563 /* Shortcut for GL functionality. */ 564 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 565 566 /* Prepare framebuffer. */ 567 gl.genFramebuffers(1, &m_fbo); 568 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers call failed."); 569 570 gl.genRenderbuffers(1, &m_rbo); 571 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenRenderbuffers call failed."); 572 573 gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo); 574 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer call failed."); 575 576 gl.bindRenderbuffer(GL_RENDERBUFFER, m_rbo); 577 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindRenderbuffer call failed."); 578 579 gl.renderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1 /* x size */, 1 /* y size */); 580 GLU_EXPECT_NO_ERROR(gl.getError(), "glRenderbufferStorage call failed."); 581 582 gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_rbo); 583 GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferRenderbuffer call failed."); 584 585 if (gl.checkFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) 586 { 587 throw 0; 588 } 589 590 gl.viewport(0, 0, 1, 1); 591 GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport call failed."); 592 593 /* Clear framebuffer's content. */ 594 gl.clearColor(0.0f, 0.0f, 0.0f, 0.0f); 595 GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor call failed."); 596 597 gl.clear(GL_COLOR_BUFFER_BIT); 598 GLU_EXPECT_NO_ERROR(gl.getError(), "glClear call failed."); 599} 600 601/** @brief Function generate and bind empty vertex array object. 602 * 603 * @note The function may throw if unexpected error has occured. 604 */ 605void FunctionalTest::prepareVertexArrayObject() 606{ 607 /* Shortcut for GL functionality */ 608 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 609 610 gl.genVertexArrays(1, &m_vao); 611 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays call failed."); 612 613 gl.bindVertexArray(m_vao); 614 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed."); 615} 616 617/** @brief Function builds test's GLSL shader program. 618 * If succeded, the program will be set to be used. 619 * 620 * @note The function may throw if unexpected error has occured. 621 */ 622void FunctionalTest::prepareShaderPrograms() 623{ 624 /* Shortcut for GL functionality. */ 625 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 626 627 /* Log size limit. */ 628 static const glw::GLsizei max_log_size = 4096; 629 630 /* Quick check. */ 631 if (m_spo_v || m_spo_f) 632 { 633 throw 0; 634 } 635 636 /* Create Vertex Shader Program. */ 637 m_spo_v = gl.createShaderProgramv(GL_VERTEX_SHADER, 1, &s_vertex_shader); 638 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShaderProgramv call failed."); 639 640 glw::GLint status = GL_TRUE; 641 642 gl.validateProgram(m_spo_v); 643 GLU_EXPECT_NO_ERROR(gl.getError(), "glValidateProgram call failed."); 644 645 gl.getProgramiv(m_spo_v, GL_VALIDATE_STATUS, &status); 646 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv call failed."); 647 648 if (GL_FALSE == status) 649 { 650 /* Storage for data. */ 651 glw::GLchar log[max_log_size] = { 0 }; 652 653 /* Storage fetched length. */ 654 glw::GLsizei log_size = 0; 655 656 gl.getProgramInfoLog(m_spo_v, max_log_size, &log_size, log); 657 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramInfoLog call failed."); 658 659 m_context.getTestContext().getLog() << tcu::TestLog::Message 660 << "Vertex shader program building failed with log: " << log 661 << tcu::TestLog::EndMessage; 662 663 throw 0; 664 } 665 666 m_spo_f = gl.createShaderProgramv(GL_FRAGMENT_SHADER, 1, &s_fragment_shader); 667 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShaderProgramv call failed."); 668 669 status = GL_TRUE; 670 671 gl.validateProgram(m_spo_f); 672 GLU_EXPECT_NO_ERROR(gl.getError(), "glValidateProgram call failed."); 673 674 gl.getProgramiv(m_spo_f, GL_VALIDATE_STATUS, &status); 675 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv call failed."); 676 677 if (GL_FALSE == status) 678 { 679 /* Storage for data. */ 680 glw::GLchar log[max_log_size] = { 0 }; 681 682 /* Storage fetched length. */ 683 glw::GLsizei log_size = 0; 684 685 gl.getProgramInfoLog(m_spo_f, max_log_size, &log_size, log); 686 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramInfoLog call failed."); 687 688 m_context.getTestContext().getLog() << tcu::TestLog::Message 689 << "Fragment shader program building failed with log: " << log 690 << tcu::TestLog::EndMessage; 691 692 throw 0; 693 } 694} 695 696/** @brief Function prepares program pipeline object. 697 * 698 * @note The function may throw if unexpected error has occured. 699 */ 700void FunctionalTest::preparePipeline() 701{ 702 /* Shortcut for GL functionality. */ 703 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 704 705 /* Quick check. */ 706 if (m_ppo) 707 { 708 throw 0; 709 } 710 711 /* Create, use and set up program pipeline. */ 712 gl.createProgramPipelines(1, &m_ppo); 713 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgramPipelines call failed."); 714 715 gl.bindProgramPipeline(m_ppo); 716 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindProgramPipeline call failed."); 717 718 gl.useProgramStages(m_ppo, GL_VERTEX_SHADER_BIT, m_spo_v); 719 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages call failed."); 720 721 gl.useProgramStages(m_ppo, GL_FRAGMENT_SHADER_BIT, m_spo_f); 722 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages call failed."); 723} 724 725/** @brief Function draws a quad. 726 * 727 * @note The function may throw if unexpected error has occured. 728 */ 729void FunctionalTest::draw() 730{ 731 /* Shortcut for GL functionality. */ 732 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 733 734 gl.drawArrays(GL_TRIANGLE_STRIP, 0, 4); 735 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays have failed"); 736} 737 738/** @brief Check content of the framebuffer and compare it with expected data. 739 * 740 * @note The function may throw if unexpected error has occured. 741 * 742 * @return True if succeeded, false otherwise. 743 */ 744bool FunctionalTest::checkFramebufferContent() 745{ 746 /* Shortcut for GL functionality. */ 747 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 748 749 /* Fetch framebuffer data. */ 750 glw::GLubyte pixel[4] = { 0 }; 751 752 gl.readPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel); 753 GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels have failed"); 754 755 /* Comparison with expected values. */ 756 if ((255 != pixel[0]) || (0 != pixel[1]) || (0 != pixel[2]) || (255 != pixel[3])) 757 { 758 m_context.getTestContext().getLog() 759 << tcu::TestLog::Message << "Frameuffer content (" << (unsigned int)pixel[0] << ", " 760 << (unsigned int)pixel[1] << ", " << (unsigned int)pixel[2] << ", " << (unsigned int)pixel[3] 761 << ") is different than expected (255, 0, 0, 255)." << tcu::TestLog::EndMessage; 762 763 return false; 764 } 765 766 return true; 767} 768 769/** @brief Release all GL objects. 770 */ 771void FunctionalTest::clean() 772{ 773 /* Shortcut for GL functionality. */ 774 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 775 776 /* Release framebuffer. */ 777 if (m_fbo) 778 { 779 gl.deleteFramebuffers(1, &m_fbo); 780 781 m_fbo = 0; 782 } 783 784 /* Release renderbuffer. */ 785 if (m_rbo) 786 { 787 gl.deleteRenderbuffers(1, &m_rbo); 788 789 m_rbo = 0; 790 } 791 792 /* Release vertex array object. */ 793 if (m_vao) 794 { 795 gl.deleteVertexArrays(1, &m_vao); 796 797 m_vao = 0; 798 } 799 800 /* Release shader programs. */ 801 if (m_spo_v) 802 { 803 gl.deleteProgram(m_spo_v); 804 805 m_spo_v = 0; 806 } 807 808 if (m_spo_f) 809 { 810 gl.deleteProgram(m_spo_f); 811 812 m_spo_f = 0; 813 } 814 815 /* Release program pipelines. */ 816 if (m_ppo) 817 { 818 gl.bindProgramPipeline(0); 819 820 gl.deleteProgramPipelines(1, &m_ppo); 821 822 m_ppo = 0; 823 } 824} 825 826/* Vertex shader source code. */ 827const glw::GLchar* FunctionalTest::s_vertex_shader = "#version 450\n" 828 "\n" 829 "out gl_PerVertex\n" 830 "{\n" 831 " vec4 gl_Position;\n" 832 " float gl_PointSize;\n" 833 " float gl_ClipDistance[];\n" 834 "};\n" 835 "\n" 836 "void main()\n" 837 "{\n" 838 " switch(gl_VertexID)\n" 839 " {\n" 840 " case 0:\n" 841 " gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n" 842 " break;\n" 843 " case 1:\n" 844 " gl_Position = vec4( 1.0, 1.0, 0.0, 1.0);\n" 845 " break;\n" 846 " case 2:\n" 847 " gl_Position = vec4(-1.0,-1.0, 0.0, 1.0);\n" 848 " break;\n" 849 " case 3:\n" 850 " gl_Position = vec4( 1.0,-1.0, 0.0, 1.0);\n" 851 " break;\n" 852 " }\n" 853 "}\n"; 854 855/* Fragment shader source program. */ 856const glw::GLchar* FunctionalTest::s_fragment_shader = "#version 450\n" 857 "\n" 858 "out vec4 color;\n" 859 "\n" 860 "void main()\n" 861 "{\n" 862 " color = vec4(1.0, 0.0, 0.0, 1.0);\n" 863 "}\n"; 864 865} /* ProgramPipelines namespace. */ 866} /* DirectStateAccess namespace. */ 867} /* gl4cts namespace. */ 868