• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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