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 esextcTextureCubeMapArrayStencilAttachments.cpp 26 * \brief Texture Cube Map Array Stencil Attachments (Test 3) 27 */ /*-------------------------------------------------------------------*/ 28 29 #include "esextcTextureCubeMapArrayStencilAttachments.hpp" 30 #include "gluContextInfo.hpp" 31 #include "gluDefs.hpp" 32 #include "glwEnums.hpp" 33 #include "glwFunctions.hpp" 34 #include "tcuTestLog.hpp" 35 #include <string.h> 36 37 namespace glcts 38 { 39 40 /** Number of byte for one vec4 position */ 41 const glw::GLuint TextureCubeMapArrayStencilAttachments::m_n_components = 4; 42 /** Number of configuration different cube map array textures*/ 43 const glw::GLuint TextureCubeMapArrayStencilAttachments::m_n_cube_map_array_configurations = 4; 44 /** Number of vertices per triangle use in gemoetry shader*/ 45 const glw::GLuint TextureCubeMapArrayStencilAttachments::m_n_vertices_gs = 3; 46 47 /** Constructor **/ 48 CubeMapArrayDataStorage::CubeMapArrayDataStorage() : m_data_array(DE_NULL), m_depth(0), m_height(0), m_width(0) 49 { 50 } 51 52 /** Destructor **/ 53 CubeMapArrayDataStorage::~CubeMapArrayDataStorage() 54 { 55 deinit(); 56 } 57 58 /** Initializes data array 59 * 60 * @param width width of the texture; 61 * @param height height of the texture; 62 * @param depth number of layers in the texture (for cube map array must be multiple of 6); 63 * @param initial_value value which the allocated storage should be cleared with; 64 **/ 65 void CubeMapArrayDataStorage::init(const glw::GLuint width, const glw::GLuint height, const glw::GLuint depth, 66 glw::GLubyte initial_value) 67 { 68 deinit(); 69 70 m_width = width; 71 m_height = height; 72 m_depth = depth; 73 74 m_data_array = new glw::GLubyte[getArraySize()]; 75 76 memset(m_data_array, initial_value, getArraySize() * sizeof(glw::GLubyte)); 77 } 78 79 /** Deinitializes data array **/ 80 void CubeMapArrayDataStorage::deinit(void) 81 { 82 if (m_data_array != DE_NULL) 83 { 84 delete[] m_data_array; 85 86 m_data_array = DE_NULL; 87 } 88 89 m_width = 0; 90 m_height = 0; 91 m_depth = 0; 92 } 93 94 /** Returns pointer to array. 95 * 96 * @return As per description. 97 **/ 98 glw::GLubyte* CubeMapArrayDataStorage::getDataArray() const 99 { 100 return m_data_array; 101 } 102 103 /** Returns size of the array in bytes **/ 104 glw::GLuint CubeMapArrayDataStorage::getArraySize() const 105 { 106 return m_width * m_height * m_depth * TextureCubeMapArrayStencilAttachments::m_n_components; 107 } 108 109 /* Fragment shader code */ 110 const char* TextureCubeMapArrayStencilAttachments::m_fragment_shader_code = "${VERSION}\n" 111 "\n" 112 "${TEXTURE_CUBE_MAP_ARRAY_REQUIRE}\n" 113 "\n" 114 "precision highp float;\n" 115 "\n" 116 "layout(location = 0) out vec4 color;\n" 117 "\n" 118 "void main()\n" 119 "{\n" 120 " color = vec4(0, 1, 1, 0);\n" 121 "}\n"; 122 123 /* Vertex shader code */ 124 const char* TextureCubeMapArrayStencilAttachments::m_vertex_shader_code = "${VERSION}\n" 125 "\n" 126 "${TEXTURE_CUBE_MAP_ARRAY_REQUIRE}\n" 127 "\n" 128 "precision highp float;\n" 129 "\n" 130 "in vec4 vertex_position;\n" 131 "\n" 132 "void main()\n" 133 "{\n" 134 " gl_Position = vertex_position;\n" 135 "}\n"; 136 137 /** Constructor 138 * 139 * @param context Test context 140 * @param name Test case's name 141 * @param description Test case's description 142 * @param immutable_storage if set to true, immutable textures will be used; 143 * @param fbo_layered if set to true, a layered draw framebuffer will be used; 144 **/ 145 TextureCubeMapArrayStencilAttachments::TextureCubeMapArrayStencilAttachments(Context& context, 146 const ExtParameters& extParams, 147 const char* name, const char* description, 148 glw::GLboolean immutable_storage, 149 glw::GLboolean fbo_layered) 150 : TestCaseBase(context, extParams, name, description) 151 , m_fbo_layered(fbo_layered) 152 , m_immutable_storage(immutable_storage) 153 , m_fbo_draw_id(0) 154 , m_fbo_read_id(0) 155 , m_fragment_shader_id(0) 156 , m_geometry_shader_id(0) 157 , m_program_id(0) 158 , m_texture_cube_array_stencil_id(0) 159 , m_texture_cube_array_color_id(0) 160 , m_vao_id(0) 161 , m_vbo_id(0) 162 , m_vertex_shader_id(0) 163 , m_cube_map_array_data(DE_NULL) 164 , m_result_data(DE_NULL) 165 { 166 /* Nothing to be done here */ 167 } 168 169 /** Executes the test. 170 * 171 * Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise. 172 * 173 * Note the function throws exception should an error occur! 174 * 175 * @return STOP if the test has finished, CONTINUE to indicate iterate() should be called once again. 176 **/ 177 tcu::TestNode::IterateResult TextureCubeMapArrayStencilAttachments::iterate(void) 178 { 179 initTest(); 180 181 /* Retrieve ES entry-points */ 182 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 183 184 /* Set up stencil function */ 185 gl.stencilFunc(GL_LESS, 0 /* ref */, 0xFF /* mask */); 186 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not setup stencil function"); 187 188 /* Set up stencil operation */ 189 gl.stencilOp(GL_KEEP, GL_KEEP, GL_KEEP); 190 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not setup stencil operation"); 191 192 /* Set up clear color */ 193 gl.clearColor(1 /* red */, 0 /* green */, 0 /* blue */, 1 /* alpha */); 194 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set stencil color value!"); 195 196 bool has_test_failed = false; 197 198 /* Iterate through all defined configurations */ 199 for (glw::GLuint test_index = 0; test_index < m_n_cube_map_array_configurations; test_index++) 200 { 201 /* Build and activate a test-specific program object */ 202 buildAndUseProgram(test_index); 203 204 /* Create textures, framebuffer... before for every test iteration */ 205 initTestIteration(test_index); 206 207 /* Clear the color buffer with (1, 0, 0, 1) color */ 208 gl.clear(GL_COLOR_BUFFER_BIT); 209 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not clear color buffer"); 210 211 /* Draw a full-screen quad */ 212 gl.drawArrays(GL_TRIANGLE_STRIP, 0 /* first */, 4 /* count */); 213 GLU_EXPECT_NO_ERROR(gl.getError(), "Rendering failed!"); 214 215 /* Read the rendered data */ 216 glw::GLuint array_size = 217 m_cube_map_array_data[test_index].getArraySize() / m_cube_map_array_data[test_index].getDepth(); 218 219 m_result_data = new glw::GLubyte[array_size]; 220 221 memset(m_result_data, 0, sizeof(glw::GLubyte) * array_size); 222 223 gl.bindFramebuffer(GL_READ_FRAMEBUFFER, m_fbo_read_id); 224 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not bind read framebuffer"); 225 226 if (m_fbo_layered) 227 { 228 for (glw::GLuint n_layer = 0; n_layer < m_cube_map_array_data[test_index].getDepth(); ++n_layer) 229 { 230 gl.framebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_texture_cube_array_color_id, 231 0, /* level */ 232 n_layer); 233 GLU_EXPECT_NO_ERROR(gl.getError(), 234 "Could not attach texture layer to color attachment of read framebuffer"); 235 236 /* Is the data correct? */ 237 has_test_failed = readPixelsAndCompareWithExpectedResult(test_index); 238 239 if (has_test_failed) 240 { 241 break; 242 } 243 } /* for (all layers) */ 244 } /* if (m_fbo_layered) */ 245 else 246 { 247 gl.framebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_texture_cube_array_color_id, 248 0 /* level */, 0); 249 GLU_EXPECT_NO_ERROR(gl.getError(), 250 "Could not attach texture layer to color attachment of read framebuffer"); 251 252 /* Is the data correct? */ 253 has_test_failed = readPixelsAndCompareWithExpectedResult(test_index); 254 } 255 256 /* Clean up */ 257 cleanAfterTest(); 258 259 if (has_test_failed) 260 { 261 break; 262 } 263 } /* for (all configurations) */ 264 265 if (has_test_failed) 266 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 267 else 268 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 269 270 return STOP; 271 } 272 273 /** Deinitializes GLES objects created during the test. 274 * 275 */ 276 void TextureCubeMapArrayStencilAttachments::deinit(void) 277 { 278 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 279 280 /* Disable the stencil test */ 281 gl.disable(GL_STENCIL_TEST); 282 283 /* If any of the iterations have broken, we should clean up here. */ 284 cleanAfterTest(); 285 286 gl.bindVertexArray(0); 287 288 /* Release test-wide objects */ 289 if (m_vbo_id != 0) 290 { 291 gl.deleteBuffers(1, &m_vbo_id); 292 293 m_vbo_id = 0; 294 } 295 296 if (m_fbo_draw_id != 0) 297 { 298 gl.deleteFramebuffers(1, &m_fbo_draw_id); 299 300 m_fbo_draw_id = 0; 301 } 302 303 if (m_fbo_read_id != 0) 304 { 305 gl.deleteFramebuffers(1, &m_fbo_read_id); 306 307 m_fbo_read_id = 0; 308 } 309 310 if (m_vao_id != 0) 311 { 312 gl.deleteVertexArrays(1, &m_vao_id); 313 314 m_vao_id = 0; 315 } 316 317 if (m_cube_map_array_data != DE_NULL) 318 { 319 delete[] m_cube_map_array_data; 320 321 m_cube_map_array_data = DE_NULL; 322 } 323 324 /* Deinitialize base class */ 325 TestCaseBase::deinit(); 326 } 327 328 /** Build and use a program object **/ 329 void TextureCubeMapArrayStencilAttachments::buildAndUseProgram(glw::GLuint test_index) 330 { 331 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 332 333 /* Create a program object */ 334 m_program_id = gl.createProgram(); 335 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create a program object"); 336 337 /* Create shader objects that will make up the program object */ 338 m_fragment_shader_id = gl.createShader(GL_FRAGMENT_SHADER); 339 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create a fragment shader object"); 340 341 m_vertex_shader_id = gl.createShader(GL_VERTEX_SHADER); 342 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create a vertex shader object"); 343 344 if (m_fbo_layered) 345 { 346 std::string geometry_shader_code; 347 const char* geometry_shader_code_ptr = DE_NULL; 348 std::stringstream max_vertices_sstream; 349 std::stringstream n_iterations_sstream; 350 351 max_vertices_sstream << m_cube_map_array_data[test_index].getDepth() * m_n_vertices_gs; 352 n_iterations_sstream << m_cube_map_array_data[test_index].getDepth(); 353 354 geometry_shader_code = getGeometryShaderCode(max_vertices_sstream.str(), n_iterations_sstream.str()); 355 geometry_shader_code_ptr = geometry_shader_code.c_str(); 356 357 m_geometry_shader_id = gl.createShader(m_glExtTokens.GEOMETRY_SHADER); 358 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create a geometry shader object"); 359 360 /* Build a program object */ 361 if (!buildProgram(m_program_id, m_fragment_shader_id, 1, &m_fragment_shader_code, m_geometry_shader_id, 1, 362 &geometry_shader_code_ptr, m_vertex_shader_id, 1, &m_vertex_shader_code)) 363 { 364 TCU_FAIL("Program could not have been created sucessfully from valid vertex/geometry/fragment shaders"); 365 } 366 } /* if (m_fbo_layered) */ 367 else 368 { 369 /* Build a program object */ 370 if (!buildProgram(m_program_id, m_fragment_shader_id, 1, &m_fragment_shader_code, m_vertex_shader_id, 1, 371 &m_vertex_shader_code)) 372 { 373 TCU_FAIL("Program could not have been created sucessfully from valid vertex/fragment shaders"); 374 } 375 } 376 377 /* Use program */ 378 glw::GLint posAttrib = -1; 379 380 gl.useProgram(m_program_id); 381 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed"); 382 383 posAttrib = gl.getAttribLocation(m_program_id, "vertex_position"); 384 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not get attribute location!"); 385 386 if (posAttrib == -1) 387 { 388 TCU_FAIL("vertex_position attribute is considered inactive"); 389 } 390 391 gl.vertexAttribPointer(posAttrib, 4, GL_FLOAT, GL_FALSE, 0, 0); 392 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not configure vertex_position vertex attribute array"); 393 394 gl.enableVertexAttribArray(posAttrib); 395 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not enable vertex attribute array!"); 396 } 397 398 /** Check Framebuffer Status. Throws a TestError exception, should the framebuffer status 399 * be found incomplete. 400 * 401 * @param framebuffer_status FBO status, as returned by glCheckFramebufferStatus(), to check. 402 * 403 */ 404 void TextureCubeMapArrayStencilAttachments::checkFramebufferStatus(glw::GLenum framebuffer_status) 405 { 406 if (GL_FRAMEBUFFER_COMPLETE != framebuffer_status) 407 { 408 switch (framebuffer_status) 409 { 410 case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: 411 { 412 TCU_FAIL("Framebuffer incomplete, status: GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT"); 413 } 414 415 case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS: 416 { 417 TCU_FAIL("Framebuffer incomplete, status: GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS"); 418 } 419 420 case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: 421 { 422 TCU_FAIL("Framebuffer incomplete, status: GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT"); 423 } 424 425 case GL_FRAMEBUFFER_UNSUPPORTED: 426 { 427 TCU_FAIL("Framebuffer incomplete, status: Error: GL_FRAMEBUFFER_UNSUPPORTED"); 428 } 429 430 default: 431 { 432 TCU_FAIL("Framebuffer incomplete, status not recognized"); 433 } 434 }; /* switch (framebuffer_status) */ 435 } /* if (GL_FRAMEBUFFER_COMPLETE != framebuffer_status) */ 436 } 437 438 /** Clean after test **/ 439 void TextureCubeMapArrayStencilAttachments::cleanAfterTest(void) 440 { 441 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 442 443 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); 444 gl.bindFramebuffer(GL_READ_FRAMEBUFFER, 0); 445 gl.bindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, 0); 446 gl.useProgram(0); 447 448 if (m_program_id != 0) 449 { 450 gl.deleteProgram(m_program_id); 451 452 m_program_id = 0; 453 } 454 455 if (m_fragment_shader_id != 0) 456 { 457 gl.deleteShader(m_fragment_shader_id); 458 459 m_fragment_shader_id = 0; 460 } 461 462 if (m_geometry_shader_id != 0) 463 { 464 gl.deleteShader(m_geometry_shader_id); 465 466 m_geometry_shader_id = 0; 467 } 468 469 if (m_vertex_shader_id != 0) 470 { 471 gl.deleteShader(m_vertex_shader_id); 472 473 m_vertex_shader_id = 0; 474 } 475 476 if (m_texture_cube_array_color_id != 0) 477 { 478 gl.deleteTextures(1, &m_texture_cube_array_color_id); 479 480 m_texture_cube_array_color_id = 0; 481 } 482 483 if (m_texture_cube_array_stencil_id != 0) 484 { 485 gl.deleteTextures(1, &m_texture_cube_array_stencil_id); 486 487 m_texture_cube_array_stencil_id = 0; 488 } 489 490 if (m_result_data != DE_NULL) 491 { 492 delete[] m_result_data; 493 494 m_result_data = DE_NULL; 495 } 496 } 497 498 /** Create an immutable texture storage for a color texture. 499 * 500 * @param test_index number of the test configuration to use texture properties from. 501 **/ 502 void TextureCubeMapArrayStencilAttachments::createImmutableCubeArrayColor(glw::GLuint test_index) 503 { 504 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 505 506 gl.texStorage3D(GL_TEXTURE_CUBE_MAP_ARRAY, /* target */ 507 1, /* levels */ 508 GL_RGBA8, /* internalformat */ 509 m_cube_map_array_data[test_index].getWidth(), /* width */ 510 m_cube_map_array_data[test_index].getHeight(), /* height */ 511 m_cube_map_array_data[test_index].getDepth()); /* depth */ 512 513 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create an immutable color texture storage!"); 514 } 515 516 /** Create an immutable texture storage for a stencil texture. 517 * 518 * @param test_index number of the test configuration to use texture properties from. 519 **/ 520 void TextureCubeMapArrayStencilAttachments::createImmutableCubeArrayStencil(glw::GLuint test_index) 521 { 522 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 523 524 fillStencilData(test_index); 525 526 gl.texStorage3D(GL_TEXTURE_CUBE_MAP_ARRAY, /* target */ 527 1, /* levels */ 528 GL_DEPTH24_STENCIL8, /* internalformat */ 529 m_cube_map_array_data[test_index].getWidth(), /* width */ 530 m_cube_map_array_data[test_index].getHeight(), /* height */ 531 m_cube_map_array_data[test_index].getDepth()); /* depth */ 532 533 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create an immutable stencil texture storage!"); 534 535 gl.texSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, /* target */ 536 0, /* level */ 537 0, /* xoffset */ 538 0, /* yoffset */ 539 0, /* zoffset */ 540 m_cube_map_array_data[test_index].getWidth(), /* width */ 541 m_cube_map_array_data[test_index].getHeight(), /* height */ 542 m_cube_map_array_data[test_index].getDepth(), /* depth */ 543 GL_DEPTH_STENCIL, /* format */ 544 GL_UNSIGNED_INT_24_8, /* type */ 545 m_cube_map_array_data[test_index].getDataArray()); /* data */ 546 547 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not fill allocated texture storage with texture data!"); 548 } 549 550 /** Create a mutable texture storage for a color texture. 551 * 552 * @param test_index number of the test configuration to use texture properties from. 553 * 554 **/ 555 void TextureCubeMapArrayStencilAttachments::createMutableCubeArrayColor(glw::GLuint test_index) 556 { 557 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 558 559 gl.texImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, /* target */ 560 0, /* level */ 561 GL_RGBA8, /* internal format */ 562 m_cube_map_array_data[test_index].getWidth(), /* width */ 563 m_cube_map_array_data[test_index].getHeight(), /* height */ 564 m_cube_map_array_data[test_index].getDepth(), /* depth */ 565 0, /* border */ 566 GL_RGBA, /* format */ 567 GL_UNSIGNED_BYTE, /* type */ 568 m_cube_map_array_data[test_index].getDataArray()); /* pixel data */ 569 570 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create a mutable color texture storage!"); 571 } 572 573 /** Create a mutable texture storage for a stencil texture. 574 * 575 * @param test_index number of the test configuration to use texture properties from. 576 **/ 577 void TextureCubeMapArrayStencilAttachments::createMutableCubeArrayStencil(glw::GLuint test_index) 578 { 579 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 580 581 fillStencilData(test_index); 582 583 gl.texImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, /* target */ 584 0, /* level */ 585 GL_DEPTH24_STENCIL8, /* internal format */ 586 m_cube_map_array_data[test_index].getWidth(), /* width */ 587 m_cube_map_array_data[test_index].getHeight(), /* height */ 588 m_cube_map_array_data[test_index].getDepth(), /* depth */ 589 0, /* border */ 590 GL_DEPTH_STENCIL, /* format */ 591 GL_UNSIGNED_INT_24_8, /* type */ 592 m_cube_map_array_data[test_index].getDataArray()); /* pixel data */ 593 594 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create a mutable stencil texture storage!"); 595 } 596 597 /** Fill the texture used as stencil attachment with reference values 598 * 599 * @param test_index index of the test configuration this call is being made for. 600 * 601 **/ 602 void TextureCubeMapArrayStencilAttachments::fillStencilData(glw::GLuint test_index) 603 { 604 glw::GLubyte* const data = m_cube_map_array_data[test_index].getDataArray(); 605 606 memset(data, 0, m_cube_map_array_data[test_index].getArraySize() * sizeof(glw::GLubyte)); 607 608 for (glw::GLuint depth_index = 0; depth_index < m_cube_map_array_data[test_index].getDepth(); depth_index++) 609 { 610 for (glw::GLuint x = 0; x < m_cube_map_array_data[test_index].getWidth(); x++) 611 { 612 for (glw::GLuint y = m_cube_map_array_data[test_index].getHeight() / 2; 613 y < m_cube_map_array_data[test_index].getHeight(); y++) 614 { 615 glw::GLuint depth_position_in_array = m_cube_map_array_data[test_index].getWidth() * 616 m_cube_map_array_data[test_index].getHeight() * m_n_components * 617 depth_index; 618 619 glw::GLuint y_position_in_array = m_cube_map_array_data[test_index].getHeight() * m_n_components * y; 620 621 glw::GLuint x_position_in_array = m_n_components * x; 622 623 glw::GLuint index_array = depth_position_in_array + y_position_in_array + x_position_in_array; 624 625 memset((data + index_array), 1, m_n_components); 626 627 } /* for (all rows) */ 628 } /* for (all columns) */ 629 } /* for (all layers) */ 630 } 631 632 /** Returns a geometry shader code, adapted to user-specific values. 633 * 634 * @param max_vertices String storing maximum amount of vertices that geometry shader can output; 635 * @param n_layers String storing number of layer-faces in cube map array texture; 636 */ 637 std::string TextureCubeMapArrayStencilAttachments::getGeometryShaderCode(const std::string& max_vertices, 638 const std::string& n_layers) 639 { 640 /* Geometry shader template code */ 641 std::string m_geometry_shader_template = "${VERSION}\n" 642 "\n" 643 "${GEOMETRY_SHADER_REQUIRE}\n" 644 "\n" 645 "layout(triangles) in;\n" 646 "layout(triangle_strip, max_vertices = <-MAX-VERTICES->) out;\n" 647 "\n" 648 "void main(void)\n" 649 "{\n" 650 " int layer;\n" 651 "\n" 652 " for (layer = 0; layer < <-N_LAYERS->; layer++)\n" 653 " {\n" 654 " gl_Layer = layer;\n" 655 " gl_Position = gl_in[0].gl_Position;\n" 656 " EmitVertex();\n" 657 "\n" 658 " gl_Layer = layer;\n" 659 " gl_Position = gl_in[1].gl_Position;\n" 660 " EmitVertex();\n" 661 "\n" 662 " gl_Layer = layer;\n" 663 " gl_Position = gl_in[2].gl_Position;\n" 664 " EmitVertex();\n" 665 "\n" 666 " EndPrimitive();\n" 667 " }\n" 668 "}\n"; 669 670 /* Replace a "maximum number of emitted vertices" token with user-provided value */ 671 std::string template_name = "<-MAX-VERTICES->"; 672 std::size_t template_position = m_geometry_shader_template.find(template_name); 673 674 while (template_position != std::string::npos) 675 { 676 m_geometry_shader_template = 677 m_geometry_shader_template.replace(template_position, template_name.length(), max_vertices); 678 679 template_position = m_geometry_shader_template.find(template_name); 680 } 681 682 /* Do the same for the number of layers we want the geometry shader to modify. */ 683 template_name = "<-N_LAYERS->"; 684 template_position = m_geometry_shader_template.find(template_name); 685 686 while (template_position != std::string::npos) 687 { 688 m_geometry_shader_template = 689 m_geometry_shader_template.replace(template_position, template_name.length(), n_layers); 690 691 template_position = m_geometry_shader_template.find(template_name); 692 } 693 if (!m_is_geometry_shader_extension_supported && m_fbo_layered) 694 { 695 throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED); 696 } 697 698 return m_geometry_shader_template; 699 } 700 701 /** Initializes GLES objects created during the test. **/ 702 void TextureCubeMapArrayStencilAttachments::initTest(void) 703 { 704 /* Check if EXT_texture_cube_map_array extension is supported */ 705 if (!m_is_texture_cube_map_array_supported) 706 { 707 throw tcu::NotSupportedError(TEXTURE_CUBE_MAP_ARRAY_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__); 708 } 709 if (!m_is_geometry_shader_extension_supported && m_fbo_layered) 710 { 711 throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED); 712 } 713 714 /* Retrieve ES entry-points */ 715 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 716 717 /* Create 4 different configurations of cube map array texture */ 718 m_cube_map_array_data = new CubeMapArrayDataStorage[m_n_cube_map_array_configurations]; 719 720 m_cube_map_array_data[0].init(64, 64, 18); 721 m_cube_map_array_data[1].init(117, 117, 6); 722 m_cube_map_array_data[2].init(256, 256, 6); 723 m_cube_map_array_data[3].init(173, 173, 12); 724 725 /* full screen square */ 726 glw::GLfloat vertices[] = { -1.0f, -1.0f, 0.0f, 1.0f, -1.0f, 1.0f, 0.0f, 1.0f, 727 1.0f, -1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f }; 728 729 /* Generate and bind VAO */ 730 gl.genVertexArrays(1, &m_vao_id); 731 gl.bindVertexArray(m_vao_id); 732 733 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create vertex array object"); 734 735 gl.genBuffers(1, &m_vbo_id); 736 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not generate buffer object!"); 737 738 gl.bindBuffer(GL_ARRAY_BUFFER, m_vbo_id); 739 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not bind buffer object!"); 740 741 gl.bufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); 742 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set data for buffer object!"); 743 744 /* Create and configure framebuffer object */ 745 gl.genFramebuffers(1, &m_fbo_read_id); 746 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not generate framebuffer object!"); 747 748 gl.genFramebuffers(1, &m_fbo_draw_id); 749 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not generate framebuffer object!"); 750 751 gl.enable(GL_STENCIL_TEST); 752 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not enable stencil test!"); 753 } 754 755 /** Create and set OpenGL object need for one test iteration 756 * 757 * @param test_index number of the test configuration to use texture properties from. 758 **/ 759 void TextureCubeMapArrayStencilAttachments::initTestIteration(glw::GLuint test_index) 760 { 761 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 762 763 /* Set up texture storage for color data */ 764 gl.genTextures(1, &m_texture_cube_array_color_id); 765 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not generate texture object!"); 766 767 gl.bindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, m_texture_cube_array_color_id); 768 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not bind a texture object to GL_TEXTURE_CUBE_MAP_ARRAY_EXT target"); 769 770 if (m_immutable_storage) 771 { 772 createImmutableCubeArrayColor(test_index); 773 } 774 else 775 { 776 createMutableCubeArrayColor(test_index); 777 } 778 779 /* Set up texture storage for stencil data */ 780 gl.genTextures(1, &m_texture_cube_array_stencil_id); 781 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not generate texture object!"); 782 783 gl.bindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, m_texture_cube_array_stencil_id); 784 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not bind texture object to GL_TEXTURE_CUBE_MAP_ARRAY_EXT target"); 785 786 if (m_immutable_storage) 787 { 788 createImmutableCubeArrayStencil(test_index); 789 } 790 else 791 { 792 createMutableCubeArrayStencil(test_index); 793 } 794 795 /* Set up the draw framebuffer */ 796 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, m_fbo_draw_id); 797 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not bind draw framebuffer!"); 798 799 gl.viewport(0, 0, m_cube_map_array_data[test_index].getWidth(), m_cube_map_array_data[test_index].getHeight()); 800 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set viewport"); 801 802 if (m_fbo_layered) 803 { 804 setupLayeredFramebuffer(); 805 } 806 else 807 { 808 setupNonLayeredFramebuffer(); 809 } 810 811 /* Is the draw FBO complete, now that we're done with configuring it? */ 812 checkFramebufferStatus(gl.checkFramebufferStatus(GL_DRAW_FRAMEBUFFER)); 813 } 814 815 /** Read pixels from color attachment of read framebuffer and compare them with expected result. 816 * 817 * @param test_index index of cube map array configuration 818 * 819 * @return true if failed, false otherwise. 820 */ 821 bool TextureCubeMapArrayStencilAttachments::readPixelsAndCompareWithExpectedResult(glw::GLuint test_index) 822 { 823 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 824 bool has_test_failed = false; 825 826 gl.readPixels(0 /* x */, 0 /* y */, m_cube_map_array_data[test_index].getWidth(), 827 m_cube_map_array_data[test_index].getHeight(), GL_RGBA, GL_UNSIGNED_BYTE, m_result_data); 828 829 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not read pixel data from color buffer"); 830 831 glw::GLubyte expectedData[] = { 0, 0, 0, 0 }; 832 833 /* Loop over all pixels and compare the rendered data with reference values */ 834 for (glw::GLuint y = 0; y < m_cube_map_array_data[test_index].getHeight(); ++y) 835 { 836 /* Top half should be filled with different data than the bottom half */ 837 if (y >= m_cube_map_array_data[test_index].getHeight() / 2) 838 { 839 expectedData[0] = 0; 840 expectedData[1] = 255; 841 expectedData[2] = 255; 842 expectedData[3] = 0; 843 } 844 else 845 { 846 expectedData[0] = 255; 847 expectedData[1] = 0; 848 expectedData[2] = 0; 849 expectedData[3] = 255; 850 } 851 852 const glw::GLubyte* data_row = 853 m_result_data + y * m_cube_map_array_data[test_index].getHeight() * m_n_cube_map_array_configurations; 854 855 for (glw::GLuint x = 0; x < m_cube_map_array_data[test_index].getWidth(); ++x) 856 { 857 const glw::GLubyte* data = data_row + x * m_n_components; 858 859 if (data[0] != expectedData[0] || data[1] != expectedData[1] || data[2] != expectedData[2] || 860 data[3] != expectedData[3]) 861 { 862 m_testCtx.getLog() << tcu::TestLog::Message << "Expected Data ( " << (unsigned int)expectedData[0] 863 << "," << (unsigned int)expectedData[1] << "," << (unsigned int)expectedData[2] 864 << "," << (unsigned int)expectedData[3] << ") " 865 << "Result Data ( " << (unsigned int)data[0] << "," << (unsigned int)data[1] << "," 866 << (unsigned int)data[2] << "," << (unsigned int)data[3] << ")" 867 << tcu::TestLog::EndMessage; 868 869 has_test_failed = true; 870 } 871 } /* for (all pixels in a row) */ 872 } /* for (all rows) */ 873 874 return has_test_failed; 875 } 876 877 /** Attach color and stencil attachments to a layer framebuffer **/ 878 void TextureCubeMapArrayStencilAttachments::setupLayeredFramebuffer() 879 { 880 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 881 882 gl.framebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_texture_cube_array_color_id, 0 /* level */); 883 GLU_EXPECT_NO_ERROR(gl.getError(), "Error attaching texture to GL_COLOR_ATTACHMENT0!"); 884 885 gl.framebufferTexture(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, m_texture_cube_array_stencil_id, 886 0 /* level */); 887 GLU_EXPECT_NO_ERROR(gl.getError(), "Error attaching texture to GL_DEPTH_STENCIL_ATTACHMENT! "); 888 } 889 890 /** Attach color and stencil attachments to a non-layered framebuffer. **/ 891 void TextureCubeMapArrayStencilAttachments::setupNonLayeredFramebuffer() 892 { 893 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 894 895 gl.framebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_texture_cube_array_color_id, 0 /* level */, 896 0 /* layer */); 897 GLU_EXPECT_NO_ERROR(gl.getError(), "Error attaching texture layer 0 to GL_COLOR_ATTACHMENT0!"); 898 899 gl.framebufferTextureLayer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, m_texture_cube_array_stencil_id, 900 0 /* level */, 0 /* layer */); 901 GLU_EXPECT_NO_ERROR(gl.getError(), "Error attaching texture layer 0 to GL_DEPTH_STENCIL_ATTACHMENT! "); 902 } 903 904 } // namespace glcts 905