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