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>
TestConfiguration(glw::GLsizei nInComponents,glw::GLsizei nOutComponents,glw::GLenum target,glw::GLenum inputInternalFormat,glw::GLenum outputInternalFormat,glw::GLenum filtering,glw::GLenum inputFormat,glw::GLenum outputFormat,glw::GLuint width,glw::GLuint height,glw::GLuint depth,InputType initValue,InputType initBorderColor,OutputType expectedValue,OutputType expectedBorderColor,glw::GLenum inputType,glw::GLenum 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>
TestConfiguration(const TestConfiguration & configuration)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>
TextureBorderClampSamplingTexture(Context & context,const ExtParameters & extParams,const char * name,const char * description,const TestConfiguration<InputType,OutputType> & configuration)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>
initTest(void)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>
setInitData(std::vector<InputType> & buffer)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>
createTextures(void)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>
iterate(void)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>
deinit(void)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>
checkFramebufferStatus(glw::GLenum framebuffer)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>
checkResult(OutputType expectedValue,OutputType expectedBorderColor,glw::GLint layer)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>
getFragmentShaderCode(void)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>
getVertexShaderCode(void)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>
checkNearest(std::vector<OutputType> & buffer,OutputType expectedValue,OutputType expectedBorderColor,glw::GLint layer)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>
checkLinear(std::vector<OutputType> & buffer,glw::GLint layer)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>
getStartingLayerIndex()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>
getLastLayerIndex()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>
getCoordinateValue(glw::GLint index)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