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 esextcTextureBorderClampSamplingTexture.cpp 26 * \brief Verify that sampling a texture with GL_CLAMP_TO_BORDER_EXT 27 * wrap mode enabled gives correct results (Test 7) 28 */ /*-------------------------------------------------------------------*/ 29 30 #include "esextcTextureBorderClampSamplingTexture.hpp" 31 #include "esextcTextureBorderClampCompressedResources.hpp" 32 #include "gluDefs.hpp" 33 #include "glwEnums.hpp" 34 #include "glwFunctions.hpp" 35 #include "tcuTestLog.hpp" 36 37 namespace glcts 38 { 39 40 template <typename InputType, typename OutputType> 41 const glw::GLuint TextureBorderClampSamplingTexture<InputType, OutputType>::m_texture_unit = 0; 42 43 /** Constructor 44 * 45 * @param nComponents number of components 46 * @param target texture target 47 * @param inputInternalFormat input texture internal format 48 * @param outputInternalFormat output texture internal format 49 * @param filtering contains parameters for GL_TEXTURE_MAG_FILTER and GL_TEXTURE_MIN_FILTER - in our case can be GL_NEAREST or GL_LINEAR 50 * @param inputFormat input texture format 51 * @param outputFormat output texture format 52 * @param width texture/viewport width 53 * @param height texture/viewport height 54 * @param initValue value used for input texture to fill all texels with 55 * @param initBorderColor value of border color for input texture 56 * @param expectedValue expected value for texture texels for points taken from inside of input texture 57 * @param expectedBorderColor expected value for texture texels for points taken from outside of input texture 58 * @param inputType enum representing data type for input texture 59 * @param outputType enum representing data type for output texture 60 **/ 61 template <typename InputType, typename OutputType> 62 TestConfiguration<InputType, OutputType>::TestConfiguration( 63 glw::GLsizei nInComponents, glw::GLsizei nOutComponents, glw::GLenum target, glw::GLenum inputInternalFormat, 64 glw::GLenum outputInternalFormat, glw::GLenum filtering, glw::GLenum inputFormat, glw::GLenum outputFormat, 65 glw::GLuint width, glw::GLuint height, glw::GLuint depth, InputType initValue, InputType initBorderColor, 66 OutputType expectedValue, OutputType expectedBorderColor, glw::GLenum inputType, glw::GLenum outputType) 67 : m_n_in_components(nInComponents) 68 , m_n_out_components(nOutComponents) 69 , m_target(target) 70 , m_input_internal_format(inputInternalFormat) 71 , m_output_internal_format(outputInternalFormat) 72 , m_filtering(filtering) 73 , m_input_format(inputFormat) 74 , m_output_format(outputFormat) 75 , m_width(width) 76 , m_height(height) 77 , m_depth(depth) 78 , m_init_value(initValue) 79 , m_init_border_color(initBorderColor) 80 , m_expected_value(expectedValue) 81 , m_expected_border_color(expectedBorderColor) 82 , m_input_type(inputType) 83 , m_output_type(outputType) 84 { 85 /* Nothing to be done here */ 86 } 87 88 /** Copy Contructor 89 * 90 * @param configuration const reference to the configuration which will be copied 91 */ 92 template <typename InputType, typename OutputType> 93 TestConfiguration<InputType, OutputType>::TestConfiguration(const TestConfiguration& configuration) 94 { 95 m_n_in_components = configuration.get_n_in_components(); 96 m_n_out_components = configuration.get_n_out_components(); 97 m_target = configuration.get_target(); 98 m_input_internal_format = configuration.get_input_internal_format(); 99 m_output_internal_format = configuration.get_output_internal_format(); 100 m_filtering = configuration.get_filtering(); 101 m_input_format = configuration.get_input_format(); 102 m_output_format = configuration.get_output_format(); 103 m_width = configuration.get_width(); 104 m_height = configuration.get_height(); 105 m_depth = configuration.get_depth(); 106 m_init_value = configuration.get_init_value(); 107 m_init_border_color = configuration.get_init_border_color(); 108 m_expected_value = configuration.get_expected_value(); 109 m_expected_border_color = configuration.get_expected_border_color(); 110 m_input_type = configuration.get_input_type(); 111 m_output_type = configuration.get_output_type(); 112 } 113 114 /** Constructor 115 * 116 * @param context Test context 117 * @param name Test case's name 118 * @param description Test case's description 119 **/ 120 template <typename InputType, typename OutputType> 121 TextureBorderClampSamplingTexture<InputType, OutputType>::TextureBorderClampSamplingTexture( 122 Context& context, const ExtParameters& extParams, const char* name, const char* description, 123 const TestConfiguration<InputType, OutputType>& configuration) 124 : TestCaseBase(context, extParams, name, description) 125 , m_attr_position_location(-1) 126 , m_attr_texcoord_location(-1) 127 , m_fbo_id(0) 128 , m_fs_id(0) 129 , m_po_id(0) 130 , m_sampler_id(0) 131 , m_test_configuration(configuration) 132 , m_input_to_id(0) 133 , m_output_to_id(0) 134 , m_position_vbo_id(0) 135 , m_text_coord_vbo_id(0) 136 , m_vs_id(0) 137 , m_vao_id(0) 138 { 139 /* Nothing to be done here */ 140 } 141 142 /** Initializes GLES objects used during the test. 143 * 144 **/ 145 template <typename InputType, typename OutputType> 146 void TextureBorderClampSamplingTexture<InputType, OutputType>::initTest(void) 147 { 148 if (!m_is_texture_border_clamp_supported) 149 { 150 throw tcu::NotSupportedError(TEXTURE_BORDER_CLAMP_NOT_SUPPORTED, "", __FILE__, __LINE__); 151 } 152 153 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 154 155 /* Generate and bind VAO */ 156 gl.genVertexArrays(1, &m_vao_id); 157 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not generate vertex array object"); 158 gl.bindVertexArray(m_vao_id); 159 GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding vertex array object!"); 160 161 /* Generate sampler object */ 162 gl.genSamplers(1, &m_sampler_id); 163 GLU_EXPECT_NO_ERROR(gl.getError(), "Error generating sampler object!"); 164 165 /* Create framebuffer object */ 166 gl.genFramebuffers(1, &m_fbo_id); 167 GLU_EXPECT_NO_ERROR(gl.getError(), "Error generating framebuffer object!"); 168 169 /* Set up clear color */ 170 gl.clearColor(0.5 /* red */, 0.5 /* green */, 0.5 /* blue */, 1 /* alpha */); 171 GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting clear color value!"); 172 173 /* Input attributes for vertex shader */ 174 175 /* Full screen quad */ 176 glw::GLfloat vertices[] = { -1.0f, -1.0f, 0.0f, 1.0f, -1.0f, 1.0f, 0.0f, 1.0f, 177 1.0f, -1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f }; 178 179 /* Texture coords */ 180 glw::GLfloat coords[] = { 181 -1.0f, -1.0f, /* for bottom-left corner of the viewport */ 182 -1.0f, 2.0f, /* for top-left corner of the viewport */ 183 2.0f, -1.0f, /* for bottom-right corner of the viewport */ 184 2.0f, 2.0f /* for top-right corner of the viewport */ 185 }; 186 187 /* Generate buffer object */ 188 gl.genBuffers(1, &m_position_vbo_id); 189 GLU_EXPECT_NO_ERROR(gl.getError(), "Error generating buffer object!"); 190 191 /* Bind buffer object */ 192 gl.bindBuffer(GL_ARRAY_BUFFER, m_position_vbo_id); 193 GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding buffer object!"); 194 195 /* Set data for buffer object */ 196 gl.bufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); 197 GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting data for buffer object!"); 198 199 /* Generate buffer object */ 200 gl.genBuffers(1, &m_text_coord_vbo_id); 201 GLU_EXPECT_NO_ERROR(gl.getError(), "Error generating buffer object!"); 202 203 /* Bind buffer object */ 204 gl.bindBuffer(GL_ARRAY_BUFFER, m_text_coord_vbo_id); 205 GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding buffer object!"); 206 207 /* Set data for buffer object */ 208 gl.bufferData(GL_ARRAY_BUFFER, sizeof(coords), coords, GL_STATIC_DRAW); 209 GLU_EXPECT_NO_ERROR(gl.getError(), "Error seting data for buffer object!"); 210 211 /* Create program object */ 212 m_po_id = gl.createProgram(); 213 214 /* Create shader objects */ 215 m_vs_id = gl.createShader(GL_VERTEX_SHADER); 216 m_fs_id = gl.createShader(GL_FRAGMENT_SHADER); 217 218 /* Get vertex shader code */ 219 std::string vsCode = getVertexShaderCode(); 220 const char* vsCodePtr = (const char*)vsCode.c_str(); 221 222 /* Get fragment shader code */ 223 std::string fshaderCode = getFragmentShaderCode(); 224 const char* fshaderCodePtr = (const char*)fshaderCode.c_str(); 225 226 /* Build program */ 227 if (!buildProgram(m_po_id, m_fs_id, 1, &fshaderCodePtr, m_vs_id, 1, &vsCodePtr)) 228 { 229 TCU_FAIL("Program could not have been created sucessfully from a valid vertex/fragment shader!"); 230 } 231 232 createTextures(); 233 } 234 235 /** Set data for input texture 236 * 237 * @param buffer reference to buffer where initial data will be stored 238 */ 239 template <typename InputType, typename OutputType> 240 void TextureBorderClampSamplingTexture<InputType, OutputType>::setInitData(std::vector<InputType>& buffer) 241 { 242 const InputType initDataTexel = m_test_configuration.get_init_value(); 243 244 glw::GLuint size = m_test_configuration.get_width() * m_test_configuration.get_height() * 245 m_test_configuration.get_depth() * m_test_configuration.get_n_in_components(); 246 247 for (glw::GLuint i = 0; i < size; ++i) 248 { 249 buffer[i] = initDataTexel; 250 } 251 } 252 253 /** Create input and output textures 254 * 255 */ 256 template <typename InputType, typename OutputType> 257 void TextureBorderClampSamplingTexture<InputType, OutputType>::createTextures(void) 258 { 259 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 260 261 /* Generate input texture */ 262 gl.genTextures(1, &m_input_to_id); 263 GLU_EXPECT_NO_ERROR(gl.getError(), "Error generating texture object!"); 264 265 /* Bind input texture */ 266 gl.bindTexture(m_test_configuration.get_target(), m_input_to_id); 267 GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding texture object!"); 268 269 glw::GLsizei components = m_test_configuration.get_n_in_components(); 270 glw::GLsizei texelsNumber = 271 m_test_configuration.get_width() * m_test_configuration.get_height() * m_test_configuration.get_depth(); 272 273 /* Allocate storage for input texture and fill it with data */ 274 { 275 switch (m_test_configuration.get_target()) 276 { 277 case GL_TEXTURE_2D: 278 { 279 gl.texStorage2D(m_test_configuration.get_target(), /* target */ 280 1, /* levels */ 281 m_test_configuration.get_input_internal_format(), /* internalformat */ 282 m_test_configuration.get_width(), /* width */ 283 m_test_configuration.get_height()); /* height */ 284 GLU_EXPECT_NO_ERROR(gl.getError(), "Error allocating storage for texture object!"); 285 286 if (m_test_configuration.get_input_internal_format() == GL_COMPRESSED_RGBA8_ETC2_EAC) 287 { 288 gl.compressedTexSubImage2D(m_test_configuration.get_target(), /* target */ 289 0, /* level */ 290 0, /* xoffset */ 291 0, /* yoffset */ 292 m_test_configuration.get_width(), /* width */ 293 m_test_configuration.get_height(), /* height */ 294 m_test_configuration.get_input_internal_format(), /* internalformat */ 295 sizeof(compressed_image_data_2D), /* image size */ 296 compressed_image_data_2D); /* data */ 297 GLU_EXPECT_NO_ERROR(gl.getError(), "Error filling texture with compressed data!"); 298 } 299 else 300 { 301 std::vector<InputType> inputData(components * texelsNumber); 302 setInitData(inputData); 303 304 gl.texSubImage2D(m_test_configuration.get_target(), /* target */ 305 0, /* level */ 306 0, /* xoffset */ 307 0, /* yoffset */ 308 m_test_configuration.get_width(), /* width */ 309 m_test_configuration.get_height(), /* height */ 310 m_test_configuration.get_input_format(), /* format */ 311 m_test_configuration.get_input_type(), /* type */ 312 &inputData[0]); /* data */ 313 GLU_EXPECT_NO_ERROR(gl.getError(), "Error filling texture with data!"); 314 } 315 break; 316 } 317 case GL_TEXTURE_2D_ARRAY: 318 case GL_TEXTURE_3D: 319 { 320 gl.texStorage3D(m_test_configuration.get_target(), /* target */ 321 1, /* levels */ 322 m_test_configuration.get_input_internal_format(), /* internalformat*/ 323 m_test_configuration.get_width(), /* width */ 324 m_test_configuration.get_height(), /* height */ 325 m_test_configuration.get_depth()); /* depth */ 326 GLU_EXPECT_NO_ERROR(gl.getError(), "Error allocating storage for texture object!"); 327 328 if (m_test_configuration.get_input_internal_format() == GL_COMPRESSED_RGBA8_ETC2_EAC) 329 { 330 gl.compressedTexSubImage3D(m_test_configuration.get_target(), /* target */ 331 0, /* level */ 332 0, /* xoffset */ 333 0, /* yoffset */ 334 0, /* zoffset */ 335 m_test_configuration.get_width(), /* width */ 336 m_test_configuration.get_height(), /* height */ 337 m_test_configuration.get_depth(), /* depth */ 338 m_test_configuration.get_input_internal_format(), /* internalformat */ 339 sizeof(compressed_image_data_2D_array), /* image size */ 340 compressed_image_data_2D_array); /* data */ 341 GLU_EXPECT_NO_ERROR(gl.getError(), "Error filling texture with compressed data!"); 342 } 343 else 344 { 345 std::vector<InputType> inputData(components * texelsNumber); 346 setInitData(inputData); 347 348 gl.texSubImage3D(m_test_configuration.get_target(), /* target */ 349 0, /* level */ 350 0, /* xoffset */ 351 0, /* yoffset */ 352 0, /* zoffset */ 353 m_test_configuration.get_width(), /* width */ 354 m_test_configuration.get_height(), /* height */ 355 m_test_configuration.get_depth(), /* depth */ 356 m_test_configuration.get_input_format(), /* format */ 357 m_test_configuration.get_input_type(), /* type */ 358 &inputData[0]); /* data */ 359 GLU_EXPECT_NO_ERROR(gl.getError(), "Error filling texture with data!"); 360 } 361 break; 362 } 363 default: 364 TCU_FAIL("Test parameters can contain only following targets: GL_TEXTURE_2D, GL_TEXTURE_2D_ARRAY, " 365 "GL_TEXTURE_3D!"); 366 } 367 } 368 369 /* Generate output texture */ 370 gl.genTextures(1, &m_output_to_id); 371 GLU_EXPECT_NO_ERROR(gl.getError(), "Error generating texture object!"); 372 373 /* Bind output texture */ 374 gl.bindTexture(GL_TEXTURE_2D, m_output_to_id); 375 GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding texture object!"); 376 377 /* Allocate storage for output texture */ 378 gl.texStorage2D(GL_TEXTURE_2D, 1, m_test_configuration.get_output_internal_format(), 379 m_test_configuration.get_width(), m_test_configuration.get_height()); 380 GLU_EXPECT_NO_ERROR(gl.getError(), "Error allocating storage for texture object!"); 381 } 382 383 /** Executes the test. 384 * 385 * Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise. 386 * 387 * Note the function throws exception should an error occur! 388 * 389 * @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again. 390 **/ 391 template <typename InputType, typename OutputType> 392 tcu::TestNode::IterateResult TextureBorderClampSamplingTexture<InputType, OutputType>::iterate(void) 393 { 394 /* Initialize test case */ 395 initTest(); 396 397 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 398 399 bool testResult = true; 400 401 gl.useProgram(m_po_id); 402 GLU_EXPECT_NO_ERROR(gl.getError(), "Error using program!"); 403 404 /* Configure vertices position attribute */ 405 gl.bindBuffer(GL_ARRAY_BUFFER, m_position_vbo_id); 406 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not bind buffer object!"); 407 408 m_attr_position_location = gl.getAttribLocation(m_po_id, "vertex_position_in"); 409 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not get attribute location!"); 410 411 gl.vertexAttribPointer(m_attr_position_location, 4, GL_FLOAT, GL_FALSE, 0, 0); 412 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set vertex attribute pointer!"); 413 414 gl.enableVertexAttribArray(m_attr_position_location); 415 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not enable vertex attribute array!"); 416 417 /* Configure texture coordinates attribute */ 418 gl.bindBuffer(GL_ARRAY_BUFFER, m_text_coord_vbo_id); 419 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not bind buffer object!"); 420 421 m_attr_texcoord_location = gl.getAttribLocation(m_po_id, "texture_coords_in"); 422 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not get attribute location!"); 423 424 gl.vertexAttribPointer(m_attr_texcoord_location, 2, GL_FLOAT, GL_FALSE, 0, 0); 425 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not set vertex attribute pointer!"); 426 427 gl.enableVertexAttribArray(m_attr_texcoord_location); 428 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not enable vertex attribute array!"); 429 430 /* Configure and bind sampler to texture unit */ 431 gl.activeTexture(GL_TEXTURE0); 432 GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting active texture unit!"); 433 434 gl.bindTexture(m_test_configuration.get_target(), m_input_to_id); 435 GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding texture!"); 436 437 glw::GLint samplerLocation = gl.getUniformLocation(m_po_id, "test_sampler"); 438 GLU_EXPECT_NO_ERROR(gl.getError(), "Erros getting sampler location!"); 439 440 gl.uniform1i(samplerLocation, m_texture_unit); 441 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not bind sampler location to texture unit!"); 442 443 gl.bindSampler(m_texture_unit, m_sampler_id); 444 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not bind sampler object to texture unit!"); 445 446 /* Set GL_TEXTURE_BORDER_COLOR_EXT for sampler object */ 447 switch (m_test_configuration.get_input_internal_format()) 448 { 449 case GL_RGBA32F: 450 case GL_RGBA8: 451 case GL_DEPTH_COMPONENT32F: 452 case GL_DEPTH_COMPONENT16: 453 case GL_COMPRESSED_RGBA8_ETC2_EAC: 454 { 455 glw::GLfloat val = (glw::GLfloat)m_test_configuration.get_init_border_color(); 456 glw::GLfloat border_color[] = { val, val, val, val }; 457 gl.samplerParameterfv(m_sampler_id, m_glExtTokens.TEXTURE_BORDER_COLOR, border_color); 458 break; 459 } 460 case GL_R32UI: 461 { 462 glw::GLuint val = (glw::GLuint)m_test_configuration.get_init_border_color(); 463 glw::GLuint border_color[] = { val, val, val, val }; 464 gl.samplerParameterIuiv(m_sampler_id, m_glExtTokens.TEXTURE_BORDER_COLOR, border_color); 465 break; 466 } 467 case GL_R32I: 468 { 469 glw::GLint val = (glw::GLint)m_test_configuration.get_init_border_color(); 470 glw::GLint border_color[] = { val, val, val, val }; 471 gl.samplerParameterIiv(m_sampler_id, m_glExtTokens.TEXTURE_BORDER_COLOR, border_color); 472 break; 473 } 474 475 default: 476 throw tcu::TestError("Unsupported sized internal format. Should never happen!", "", __FILE__, __LINE__); 477 break; 478 }; 479 GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting border color parameter!"); 480 481 /* Set sampler's GL_TEXTURE_WRAP_* parameters values to GL_CLAMP_TO_BORDER_EXT */ 482 gl.samplerParameteri(m_sampler_id, GL_TEXTURE_WRAP_S, m_glExtTokens.CLAMP_TO_BORDER); 483 GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting GL_TEXTURE_WRAP_S parameter!"); 484 gl.samplerParameteri(m_sampler_id, GL_TEXTURE_WRAP_R, m_glExtTokens.CLAMP_TO_BORDER); 485 GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting GL_TEXTURE_WRAP_R parameter!"); 486 gl.samplerParameteri(m_sampler_id, GL_TEXTURE_WRAP_T, m_glExtTokens.CLAMP_TO_BORDER); 487 GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting GL_TEXTURE_WRAP_T parameter!"); 488 489 /* Set GL_TEXTURE_MAG_FILTER and GL_TEXTURE_MIN_FILTER parameters values */ 490 gl.samplerParameteri(m_sampler_id, GL_TEXTURE_MAG_FILTER, m_test_configuration.get_filtering()); 491 GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting value for GL_TEXTURE_MAG_FILTER parameter!"); 492 gl.samplerParameteri(m_sampler_id, GL_TEXTURE_MIN_FILTER, m_test_configuration.get_filtering()); 493 GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting value for GL_TEXTURE_MIN_FILTER parameter!"); 494 495 for (glw::GLint i = getStartingLayerIndex(); i < getLastLayerIndex(); ++i) 496 { 497 /* Configure layer (third texture coordinate) */ 498 glw::GLint layerLocation = gl.getUniformLocation(m_po_id, "layer"); 499 GLU_EXPECT_NO_ERROR(gl.getError(), "Error getting layer uniform location!"); 500 501 gl.uniform1f(layerLocation, getCoordinateValue(i)); 502 GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting layer uniform variable!"); 503 504 /* Bind framebuffer object */ 505 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, m_fbo_id); 506 GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding framebuffer object!"); 507 508 /* Set view port */ 509 gl.viewport(0, /* x */ 510 0, /* y */ 511 m_test_configuration.get_width(), /* width */ 512 m_test_configuration.get_height()); /* height */ 513 GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting view port!"); 514 515 /* Attach texture to framebuffer */ 516 gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, /* target */ 517 GL_COLOR_ATTACHMENT0, /* attachment */ 518 GL_TEXTURE_2D, /* textarget */ 519 m_output_to_id, /* texture */ 520 0); /* level */ 521 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not attach texture object to GL_COLOR_ATTACHMENT0!"); 522 523 /* Check framebuffer status */ 524 checkFramebufferStatus(GL_DRAW_FRAMEBUFFER); 525 526 /* Clear the color buffer with (0.5, 0.5, 0.5, 1) color */ 527 gl.clear(GL_COLOR_BUFFER_BIT); 528 GLU_EXPECT_NO_ERROR(gl.getError(), "Error clearing color buffer"); 529 530 /* Render */ 531 gl.drawArrays(GL_TRIANGLE_STRIP, 0, 4); 532 GLU_EXPECT_NO_ERROR(gl.getError(), "Rendering failed!"); 533 534 /* Get data from framebuffer's color attachment and compare with expected values. 535 * For GL_NEAREST filtering and GL_TEXTURE_3D texture target and Layer equal to 536 * -1 or Depth the whole texture is expected to be filled with border color 537 */ 538 OutputType expectedColor; 539 540 switch (m_test_configuration.get_target()) 541 { 542 case GL_TEXTURE_2D: 543 case GL_TEXTURE_2D_ARRAY: 544 expectedColor = m_test_configuration.get_expected_value(); 545 break; 546 547 case GL_TEXTURE_3D: 548 if (i > -1 && i < (glw::GLint)m_test_configuration.get_depth()) 549 expectedColor = m_test_configuration.get_expected_value(); 550 else 551 expectedColor = m_test_configuration.get_expected_border_color(); 552 break; 553 default: 554 TCU_FAIL("Not allowed texture target - should be one of GL_TEXTURE_2D, GL_TEXTURE_2D_ARRAY, GL_TEXTURE_3D"); 555 } 556 557 if (!checkResult(expectedColor, m_test_configuration.get_expected_border_color(), i)) 558 { 559 testResult = false; 560 } 561 } 562 563 if (testResult) 564 { 565 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 566 } 567 else 568 { 569 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail"); 570 } 571 return STOP; 572 } 573 574 /** Deinitializes GLES objects created during the test. 575 * 576 */ 577 template <typename InputType, typename OutputType> 578 void TextureBorderClampSamplingTexture<InputType, OutputType>::deinit(void) 579 { 580 /* Get GL entry points */ 581 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 582 583 /* Reset Gl state */ 584 gl.bindTexture(GL_TEXTURE_2D, 0); 585 gl.bindTexture(GL_TEXTURE_2D_ARRAY, 0); 586 gl.bindTexture(GL_TEXTURE_3D, 0); 587 gl.bindBuffer(GL_ARRAY_BUFFER, 0); 588 gl.bindSampler(m_texture_unit, 0); 589 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); 590 gl.bindFramebuffer(GL_READ_FRAMEBUFFER, 0); 591 gl.bindVertexArray(0); 592 593 if (m_attr_position_location != -1) 594 { 595 gl.disableVertexAttribArray(m_attr_position_location); 596 m_attr_position_location = -1; 597 } 598 599 if (m_attr_texcoord_location != -1) 600 { 601 gl.disableVertexAttribArray(m_attr_texcoord_location); 602 m_attr_texcoord_location = -1; 603 } 604 605 gl.useProgram(0); 606 607 /* Delete Gl objects */ 608 if (m_fbo_id != 0) 609 { 610 gl.deleteFramebuffers(1, &m_fbo_id); 611 m_fbo_id = 0; 612 } 613 614 if (m_po_id != 0) 615 { 616 gl.deleteProgram(m_po_id); 617 m_po_id = 0; 618 } 619 620 if (m_fs_id != 0) 621 { 622 gl.deleteShader(m_fs_id); 623 m_fs_id = 0; 624 } 625 626 if (m_vs_id != 0) 627 { 628 gl.deleteShader(m_vs_id); 629 m_vs_id = 0; 630 } 631 632 if (m_input_to_id != 0) 633 { 634 gl.deleteTextures(1, &m_input_to_id); 635 m_input_to_id = 0; 636 } 637 638 if (m_output_to_id != 0) 639 { 640 gl.deleteTextures(1, &m_output_to_id); 641 m_output_to_id = 0; 642 } 643 644 if (m_sampler_id != 0) 645 { 646 gl.deleteSamplers(1, &m_sampler_id); 647 m_sampler_id = 0; 648 } 649 650 if (m_position_vbo_id != 0) 651 { 652 gl.deleteBuffers(1, &m_position_vbo_id); 653 m_position_vbo_id = 0; 654 } 655 656 if (m_text_coord_vbo_id != 0) 657 { 658 gl.deleteBuffers(1, &m_text_coord_vbo_id); 659 m_text_coord_vbo_id = 0; 660 } 661 662 if (m_vao_id != 0) 663 { 664 gl.deleteVertexArrays(1, &m_vao_id); 665 m_vao_id = 0; 666 } 667 668 /* Deinitialize base class */ 669 TestCaseBase::deinit(); 670 } 671 672 /** Check Framebuffer Status - throw exception if status is different than GL_FRAMEBUFFER_COMPLETE 673 * 674 * @param framebuffer - GL_DRAW_FRAMEBUFFER, GL_READ_FRAMEBUFFER or GL_FRAMEBUFFER 675 * 676 */ 677 template <typename InputType, typename OutputType> 678 void TextureBorderClampSamplingTexture<InputType, OutputType>::checkFramebufferStatus(glw::GLenum framebuffer) 679 { 680 /* Get GL entry points */ 681 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 682 683 /* Check framebuffer status */ 684 glw::GLenum framebufferStatus = gl.checkFramebufferStatus(framebuffer); 685 686 if (GL_FRAMEBUFFER_COMPLETE != framebufferStatus) 687 { 688 switch (framebufferStatus) 689 { 690 case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: 691 { 692 TCU_FAIL("Framebuffer incomplete, status: GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT"); 693 } 694 695 case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS: 696 { 697 TCU_FAIL("Framebuffer incomplete, status: GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS"); 698 } 699 700 case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: 701 { 702 TCU_FAIL("Framebuffer incomplete, status: GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT"); 703 } 704 705 case GL_FRAMEBUFFER_UNSUPPORTED: 706 { 707 TCU_FAIL("Framebuffer incomplete, status: GL_FRAMEBUFFER_UNSUPPORTED"); 708 } 709 710 default: 711 { 712 TCU_FAIL("Framebuffer incomplete, status not recognized"); 713 } 714 } 715 716 } /* if (GL_FRAMEBUFFER_COMPLETE != framebuffer_status) */ 717 } 718 719 /** Get result data and check if it is as expected 720 * 721 * @return returns true if result data is as expected, otherwise returns false 722 */ 723 template <typename InputType, typename OutputType> 724 bool TextureBorderClampSamplingTexture<InputType, OutputType>::checkResult(OutputType expectedValue, 725 OutputType expectedBorderColor, 726 glw::GLint layer) 727 { 728 /* Get GL entry points */ 729 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 730 731 /* Bind draw framebuffer to read framebuffer */ 732 gl.bindFramebuffer(GL_READ_FRAMEBUFFER, m_fbo_id); 733 GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding framebuffer object!"); 734 735 std::vector<OutputType> resultData(m_test_configuration.get_width() * m_test_configuration.get_height() * 736 m_test_configuration.get_n_out_components()); 737 738 /* Read data from framebuffer */ 739 gl.readPixels(0, /* x */ 740 0, /* y */ 741 m_test_configuration.get_width(), /* width */ 742 m_test_configuration.get_height(), /* height */ 743 m_test_configuration.get_output_format(), /* format */ 744 m_test_configuration.get_output_type(), /* type */ 745 &resultData[0]); /* data */ 746 GLU_EXPECT_NO_ERROR(gl.getError(), "Error reading pixels from color buffer"); 747 748 /* Choose comparision method depending on filtering mode */ 749 if (m_test_configuration.get_filtering() == GL_NEAREST) 750 { 751 return checkNearest(resultData, expectedValue, expectedBorderColor, layer); 752 } 753 else 754 { 755 return checkLinear(resultData, layer); 756 } 757 } 758 759 /** Create fragment shader code 760 * 761 * @return string with fragment shader code 762 */ 763 template <typename InputType, typename OutputType> 764 std::string TextureBorderClampSamplingTexture<InputType, OutputType>::getFragmentShaderCode(void) 765 { 766 std::stringstream result; 767 std::string coordType; 768 std::string samplerType; 769 std::string outType; 770 std::string outCommand; 771 772 /* Check input texture format and prepare sampler prefix */ 773 switch (m_test_configuration.get_input_internal_format()) 774 { 775 case GL_RGBA32F: 776 case GL_RGBA8: 777 case GL_DEPTH_COMPONENT32F: 778 case GL_DEPTH_COMPONENT16: 779 case GL_COMPRESSED_RGBA8_ETC2_EAC: 780 samplerType = ""; 781 break; 782 783 case GL_R32UI: 784 samplerType = "u"; 785 break; 786 787 case GL_R32I: 788 samplerType = "i"; 789 break; 790 791 default: 792 throw tcu::TestError("Not allowed internal format", "", __FILE__, __LINE__); 793 } 794 795 /* Check input texture target and prepare approperiate texture coordinate type and sampler type */ 796 switch (m_test_configuration.get_target()) 797 { 798 case GL_TEXTURE_2D: 799 coordType = "vec2"; 800 samplerType += "sampler2D"; 801 break; 802 803 case GL_TEXTURE_2D_ARRAY: 804 coordType = "vec3"; 805 samplerType += "sampler2DArray"; 806 break; 807 808 case GL_TEXTURE_3D: 809 coordType = "vec3"; 810 samplerType += "sampler3D"; 811 break; 812 813 default: 814 throw tcu::TestError("Not allowed texture target!", "", __FILE__, __LINE__); 815 } 816 817 /* Check output texture format and prepare approperiate texel fetching method and output type */ 818 switch (m_test_configuration.get_output_internal_format()) 819 { 820 case GL_RGBA8: 821 outType = "vec4"; 822 outCommand = "texture(test_sampler, texture_coords_out)"; 823 break; 824 825 case GL_R8: 826 outType = "float"; 827 outCommand = "texture(test_sampler, texture_coords_out).x"; 828 break; 829 830 case GL_R32UI: 831 outType = "uint"; 832 outCommand = "uint(texture(test_sampler, texture_coords_out).x)"; 833 break; 834 835 case GL_R32I: 836 outType = "int"; 837 outCommand = "int(texture(test_sampler, texture_coords_out).x)"; 838 break; 839 840 default: 841 throw tcu::TestError("Not allowed internal format!", "", __FILE__, __LINE__); 842 } 843 844 result << "${VERSION}\n" 845 "\n" 846 "precision highp float;\n" 847 "precision highp " 848 << samplerType << ";\n" 849 "\n" 850 "uniform " 851 << samplerType << " test_sampler;\n" 852 "in " 853 << coordType << " texture_coords_out;\n" 854 "layout(location = 0) out " 855 << outType << " color;\n" 856 "\n" 857 "void main()\n" 858 "{\n" 859 " color = " 860 << outCommand << ";\n" 861 "}\n"; 862 863 return result.str(); 864 } 865 866 /** Create vertex shader code 867 * 868 * @return string with vertex shader code 869 */ 870 template <typename InputType, typename OutputType> 871 std::string TextureBorderClampSamplingTexture<InputType, OutputType>::getVertexShaderCode(void) 872 { 873 std::stringstream result; 874 std::string coordType; 875 std::string coordAssignment; 876 877 /* Check input texture target and prepare approperiate coordinate type and coordinate assignment method */ 878 switch (m_test_configuration.get_target()) 879 { 880 case GL_TEXTURE_2D: 881 coordType = "vec2"; 882 coordAssignment = "texture_coords_in"; 883 break; 884 885 case GL_TEXTURE_2D_ARRAY: 886 case GL_TEXTURE_3D: 887 coordType = "vec3"; 888 coordAssignment = "vec3(texture_coords_in, layer)"; 889 break; 890 891 default: 892 throw tcu::TestError("Not allowed texture target!", "", __FILE__, __LINE__); 893 } 894 895 result << "${VERSION}\n" 896 "\n" 897 "precision highp float;\n" 898 "\n" 899 "layout (location = 0) in vec4 vertex_position_in;\n" 900 "layout (location = 1) in vec2 texture_coords_in;\n" 901 "out " 902 << coordType << " texture_coords_out;\n" 903 "uniform float layer;\n" 904 "\n" 905 "void main()\n" 906 "{\n" 907 " gl_Position = vertex_position_in;\n" 908 " texture_coords_out = " 909 << coordAssignment << ";\n" 910 "}\n"; 911 912 return result.str(); 913 } 914 915 /** Check if result data is the same as expected data when GL_NEAREST filtering is set 916 * @param buffer reference to the buffer with result data 917 * @param expectedValue it is the value which should be read from texture if coordinates are inside of [0,1] 918 * @param expectedBorderColor it is the value which should be read from texture if coordinates are outside of [0,1] 919 * @return returns true if result data is as expected, otherwise returns false 920 */ 921 template <typename InputType, typename OutputType> 922 bool TextureBorderClampSamplingTexture<InputType, OutputType>::checkNearest(std::vector<OutputType>& buffer, 923 OutputType expectedValue, 924 OutputType expectedBorderColor, 925 glw::GLint layer) 926 { 927 glw::GLuint width = m_test_configuration.get_width(); 928 glw::GLuint height = m_test_configuration.get_height(); 929 glw::GLuint in_components = m_test_configuration.get_n_in_components(); 930 glw::GLuint out_components = m_test_configuration.get_n_out_components(); 931 glw::GLuint outRowWidth = m_test_configuration.get_width() * out_components; 932 glw::GLuint index = 0; 933 934 /* Check if center point is equal to expectedValue */ 935 std::pair<glw::GLuint, glw::GLuint> centerPoint(width / 2, height / 2); 936 937 for (glw::GLuint i = 0; i < deMinu32(out_components, in_components); ++i) 938 { 939 index = centerPoint.second * outRowWidth + centerPoint.first * out_components + i; 940 if (buffer[index] != expectedValue) 941 { 942 m_testCtx.getLog() << tcu::TestLog::Message << "Wrong value for layer (" << layer << ") at point (x,y) = (" 943 << centerPoint.first << "," << centerPoint.second << ") , component (" << i << ")\n" 944 << "Expected value [" << (glw::GLint)expectedValue << "]\n" 945 << "Result value [" << (glw::GLint)buffer[index] << "]\n" 946 << tcu::TestLog::EndMessage; 947 return false; 948 } 949 } 950 951 /* Check if following points (marked as BC) contain values equal border color 952 * 953 * (-1, -1) (0, -1) (1, -1) (2, -1) 954 * *-------+-------+-------* 955 * | | | | 956 * | BC | BC | BC | 957 * | | | | 958 * (-1, 0) +-------+-------+-------+ (2, 0) 959 * | | | | 960 * | BC | 0 | BC | 961 * | | | | 962 * (-1, 1) +-------+-------+-------+ (2, 1) 963 * | | | | 964 * | BC | BC | BC | 965 * | | | | 966 * *-------+-------+-------* 967 * (-1, 2) (0, 2) (1, 2) (2, 2) 968 */ 969 970 std::vector<std::pair<glw::GLuint, glw::GLuint> > borderPoints; 971 972 borderPoints.push_back(std::pair<glw::GLuint, glw::GLuint>(width / 6, height / 6)); 973 borderPoints.push_back(std::pair<glw::GLuint, glw::GLuint>(width / 2, height / 6)); 974 borderPoints.push_back(std::pair<glw::GLuint, glw::GLuint>((glw::GLuint)(width / 6.0 * 5), height / 6)); 975 borderPoints.push_back(std::pair<glw::GLuint, glw::GLuint>(width / 6, height / 2)); 976 borderPoints.push_back(std::pair<glw::GLuint, glw::GLuint>((glw::GLuint)(width / 6.0 * 5), height / 2)); 977 borderPoints.push_back(std::pair<glw::GLuint, glw::GLuint>(width / 6, (glw::GLuint)(height / 6.0 * 5))); 978 borderPoints.push_back(std::pair<glw::GLuint, glw::GLuint>(width / 2, (glw::GLuint)(height / 6.0 * 5))); 979 borderPoints.push_back( 980 std::pair<glw::GLuint, glw::GLuint>((glw::GLuint)(width / 6.0 * 5), (glw::GLuint)(height / 6.0 * 5))); 981 982 for (glw::GLuint j = 0; j < borderPoints.size(); ++j) 983 { 984 for (glw::GLuint i = 0; i < deMinu32(out_components, in_components); ++i) 985 { 986 index = borderPoints[j].second * outRowWidth + borderPoints[j].first * out_components + i; 987 if (buffer[index] != expectedBorderColor) 988 { 989 m_testCtx.getLog() << tcu::TestLog::Message << "Wrong value for layer (" << layer 990 << ") at point (x,y) = (" << borderPoints[j].first << "," << borderPoints[j].second 991 << ") , component (" << i << ")\n" 992 << "Expected value [" << (glw::GLint)expectedBorderColor << "]\n" 993 << "Result value [" << (glw::GLint)buffer[index] << "]\n" 994 << tcu::TestLog::EndMessage; 995 return false; 996 } 997 } 998 } 999 1000 return true; 1001 } 1002 1003 /** Check if result data is as expected when GL_LINEAR filtering is set 1004 * 1005 * @param buffer reference to the buffer with result data 1006 * @return returns true if result data is as expected, otherwise return false 1007 */ 1008 template <typename InputType, typename OutputType> 1009 bool TextureBorderClampSamplingTexture<InputType, OutputType>::checkLinear(std::vector<OutputType>& buffer, 1010 glw::GLint layer) 1011 { 1012 glw::GLuint centerX = m_test_configuration.get_width() / 2; 1013 glw::GLuint centerY = m_test_configuration.get_height() / 2; 1014 glw::GLuint stepX = m_test_configuration.get_width() / 3; 1015 glw::GLuint stepY = m_test_configuration.get_height() / 3; 1016 1017 glw::GLuint index = 0; 1018 1019 glw::GLuint in_components = m_test_configuration.get_n_in_components(); 1020 glw::GLuint out_components = m_test_configuration.get_n_out_components(); 1021 glw::GLuint outRowWidth = m_test_configuration.get_width() * out_components; 1022 1023 /* Check values from center to the bottom */ 1024 for (glw::GLuint y = centerY; y < centerY + stepY; ++y) 1025 { 1026 for (glw::GLuint c = 0; c < deMinu32(out_components, in_components); ++c) 1027 { 1028 index = y * outRowWidth + centerX * out_components + c; 1029 if (buffer[index + outRowWidth] - buffer[index] < 0) 1030 { 1031 m_testCtx.getLog() << tcu::TestLog::Message << "For layer (" << layer 1032 << ") when moving from center point (x, y) = (" << centerX << "," << centerY 1033 << ") to the bottom\n" 1034 << "at point (x, y) = (" << centerX << "," << y 1035 << ") - texel values stopped to be monotonically increasing\n" 1036 << tcu::TestLog::EndMessage; 1037 return false; 1038 } 1039 } 1040 } 1041 1042 /* Check values from center to the top */ 1043 for (glw::GLuint y = centerY; y > centerY - stepY; --y) 1044 { 1045 for (glw::GLuint c = 0; c < deMinu32(out_components, in_components); ++c) 1046 { 1047 index = y * outRowWidth + centerX * out_components + c; 1048 if (buffer[index - outRowWidth] - buffer[index] < 0) 1049 { 1050 m_testCtx.getLog() << tcu::TestLog::Message << "For layer (" << layer 1051 << ") when moving from center point (x, y) = (" << centerX << "," << centerY 1052 << ") to the top\n" 1053 << "at point (x, y) = (" << centerX << "," << y 1054 << ")- texel values stopped to be monotonically increasing\n" 1055 << tcu::TestLog::EndMessage; 1056 return false; 1057 } 1058 } 1059 } 1060 1061 /* Check values from center to the right */ 1062 for (glw::GLuint x = centerX; x < centerX + stepX; ++x) 1063 { 1064 for (glw::GLuint c = 0; c < deMinu32(out_components, in_components); ++c) 1065 { 1066 index = centerY + x * out_components + c; 1067 if (buffer[index + out_components] - buffer[index] < 0) 1068 { 1069 m_testCtx.getLog() << tcu::TestLog::Message << "For layer (" << layer 1070 << ") when moving from center point (x, y) = (" << centerX << "," << centerY 1071 << ") to the right\n" 1072 << "at point (x, y) = (" << x << "," << centerY 1073 << ")- texel values stopped to be monotonically increasing\n" 1074 << tcu::TestLog::EndMessage; 1075 return false; 1076 } 1077 } 1078 } 1079 1080 /* Check values from center to the left */ 1081 for (glw::GLuint x = centerY; x > centerX - stepX; --x) 1082 { 1083 for (glw::GLuint c = 0; c < deMinu32(out_components, in_components); ++c) 1084 { 1085 index = centerY + x * out_components + c; 1086 if (buffer[index - out_components] - buffer[index] < 0) 1087 { 1088 m_testCtx.getLog() << tcu::TestLog::Message << "For layer (" << layer 1089 << ") when moving from center point (x, y) = (" << centerX << "," << centerY 1090 << ") to the left\n" 1091 << "at point (x, y) = (" << x << "," << centerY 1092 << ")- texel values stopped to be monotonically increasing\n" 1093 << tcu::TestLog::EndMessage; 1094 return false; 1095 } 1096 } 1097 } 1098 1099 return true; 1100 } 1101 1102 /** Returns start layer index 1103 * 1104 * @return returns start layer index (0 for GL_TEXTURE_2D target , otherwise -1) 1105 */ 1106 template <typename InputType, typename OutputType> 1107 glw::GLint TextureBorderClampSamplingTexture<InputType, OutputType>::getStartingLayerIndex() 1108 { 1109 switch (m_test_configuration.get_target()) 1110 { 1111 case GL_TEXTURE_2D: 1112 case GL_TEXTURE_2D_ARRAY: 1113 return 0; 1114 1115 case GL_TEXTURE_3D: 1116 return -1; 1117 1118 default: 1119 TCU_FAIL("Not allowed texture target - should be one of GL_TEXTURE_2D, GL_TEXTURE_2D_ARRAY, GL_TEXTURE_3D"); 1120 } 1121 } 1122 1123 /** Returns last layer index 1124 * 1125 * @return returns last layer index (1 for GL_TEXTURE_2D target , otherwise depth + 1) 1126 */ 1127 template <typename InputType, typename OutputType> 1128 glw::GLint TextureBorderClampSamplingTexture<InputType, OutputType>::getLastLayerIndex() 1129 { 1130 switch (m_test_configuration.get_target()) 1131 { 1132 case GL_TEXTURE_2D: 1133 case GL_TEXTURE_2D_ARRAY: 1134 return m_test_configuration.get_depth(); 1135 1136 case GL_TEXTURE_3D: 1137 return m_test_configuration.get_depth() + 1; 1138 1139 default: 1140 TCU_FAIL("Not allowed texture target - should be one of GL_TEXTURE_2D, GL_TEXTURE_2D_ARRAY, GL_TEXTURE_3D"); 1141 } 1142 } 1143 1144 /** Returns third texture coordinate to access a particular layer in a texture 1145 * 1146 * @return returns third texture coordinate 1147 */ 1148 template <typename InputType, typename OutputType> 1149 glw::GLfloat TextureBorderClampSamplingTexture<InputType, OutputType>::getCoordinateValue(glw::GLint index) 1150 { 1151 switch (m_test_configuration.get_target()) 1152 { 1153 case GL_TEXTURE_2D: 1154 return 0.0f; 1155 break; 1156 1157 case GL_TEXTURE_2D_ARRAY: 1158 return (glw::GLfloat)index; 1159 1160 case GL_TEXTURE_3D: 1161 return static_cast<glw::GLfloat>(index) / static_cast<glw::GLfloat>(m_test_configuration.get_depth()); 1162 1163 default: 1164 TCU_FAIL("Not allowed texture target - should be one of GL_TEXTURE_2D, GL_TEXTURE_2D_ARRAY, GL_TEXTURE_3D"); 1165 } 1166 } 1167 1168 } // namespace glcts 1169