• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 << ";\n"
865 							 "\n"
866 							 "uniform "
867 		   << samplerType << " test_sampler;\n"
868 							 "in  "
869 		   << coordType << " texture_coords_out;\n"
870 						   "layout(location = 0) out "
871 		   << outType << " color;\n"
872 						 "\n"
873 						 "void main()\n"
874 						 "{\n"
875 						 "   color = "
876 		   << outCommand << ";\n"
877 							"}\n";
878 
879 	return result.str();
880 }
881 
882 /** Create vertex shader code
883  *
884  * @return string with vertex shader code
885  */
886 template <typename InputType, typename OutputType>
getVertexShaderCode(void)887 std::string TextureBorderClampSamplingTexture<InputType, OutputType>::getVertexShaderCode(void)
888 {
889 	std::stringstream result;
890 	std::string		  coordType;
891 	std::string		  coordAssignment;
892 
893 	/* Check input texture target and prepare approperiate coordinate type and coordinate assignment method */
894 	switch (m_test_configuration.get_target())
895 	{
896 	case GL_TEXTURE_2D:
897 		coordType		= "vec2";
898 		coordAssignment = "texture_coords_in";
899 		break;
900 
901 	case GL_TEXTURE_2D_ARRAY:
902 	case GL_TEXTURE_3D:
903 		coordType		= "vec3";
904 		coordAssignment = "vec3(texture_coords_in, layer)";
905 		break;
906 
907 	default:
908 		throw tcu::TestError("Not allowed texture target!", "", __FILE__, __LINE__);
909 	}
910 
911 	result << "${VERSION}\n"
912 			  "\n"
913 			  "precision highp float;\n"
914 			  "\n"
915 			  "layout (location = 0) in vec4 vertex_position_in;\n"
916 			  "layout (location = 1) in vec2 texture_coords_in;\n"
917 			  "out "
918 		   << coordType << " texture_coords_out;\n"
919 						   "uniform float layer;\n"
920 						   "\n"
921 						   "void main()\n"
922 						   "{\n"
923 						   "    gl_Position = vertex_position_in;\n"
924 						   "    texture_coords_out = "
925 		   << coordAssignment << ";\n"
926 								 "}\n";
927 
928 	return result.str();
929 }
930 
931 /** Check if result data is the same as expected data when GL_NEAREST filtering is set
932  * @param buffer              reference to the buffer with result data
933  * @param expectedValue       it is the value which should be read from texture if coordinates are inside of [0,1]
934  * @param expectedBorderColor it is the value which should be read from texture if coordinates are outside of [0,1]
935  * @return                    returns true if result data is as expected, otherwise returns false
936  */
937 template <typename InputType, typename OutputType>
checkNearest(std::vector<OutputType> & buffer,OutputType expectedValue,OutputType expectedBorderColor,glw::GLint layer)938 bool TextureBorderClampSamplingTexture<InputType, OutputType>::checkNearest(std::vector<OutputType>& buffer,
939 																			OutputType expectedValue,
940 																			OutputType expectedBorderColor,
941 																			glw::GLint layer)
942 {
943 	glw::GLuint width		   = m_test_configuration.get_width();
944 	glw::GLuint height		   = m_test_configuration.get_height();
945 	glw::GLuint in_components  = m_test_configuration.get_n_in_components();
946 	glw::GLuint out_components = m_test_configuration.get_n_out_components();
947 	glw::GLuint outRowWidth	= m_test_configuration.get_width() * out_components;
948 	glw::GLuint index		   = 0;
949 
950 	/* Check if center point is equal to expectedValue */
951 	std::pair<glw::GLuint, glw::GLuint> centerPoint(width / 2, height / 2);
952 
953 	for (glw::GLuint i = 0; i < deMinu32(out_components, in_components); ++i)
954 	{
955 		index = centerPoint.second * outRowWidth + centerPoint.first * out_components + i;
956 		if (buffer[index] != expectedValue)
957 		{
958 			m_testCtx.getLog() << tcu::TestLog::Message << "Wrong value for layer (" << layer << ") at point (x,y)  = ("
959 							   << centerPoint.first << "," << centerPoint.second << ") , component (" << i << ")\n"
960 							   << "Expected value [" << (glw::GLint)expectedValue << "]\n"
961 							   << "Result   value [" << (glw::GLint)buffer[index] << "]\n"
962 							   << tcu::TestLog::EndMessage;
963 			return false;
964 		}
965 	}
966 
967 	/* Check if following points (marked as BC) contain values equal border color
968 	 *
969 	 *                 (-1, -1)    (0, -1)  (1,  -1)     (2, -1)
970 	 *                         *-------+-------+-------*
971 	 *                         |       |       |       |
972 	 *                         |  BC   |  BC   |   BC  |
973 	 *                         |       |       |       |
974 	 *                 (-1, 0) +-------+-------+-------+ (2, 0)
975 	 *                         |       |       |       |
976 	 *                         |  BC   |   0   |   BC  |
977 	 *                         |       |       |       |
978 	 *                 (-1, 1) +-------+-------+-------+ (2, 1)
979 	 *                         |       |       |       |
980 	 *                         |  BC   |  BC   |   BC  |
981 	 *                         |       |       |       |
982 	 *                         *-------+-------+-------*
983 	 *                 (-1, 2)      (0, 2)  (1, 2)       (2, 2)
984 	 */
985 
986 	std::vector<std::pair<glw::GLuint, glw::GLuint> > borderPoints;
987 
988 	borderPoints.push_back(std::pair<glw::GLuint, glw::GLuint>(width / 6, height / 6));
989 	borderPoints.push_back(std::pair<glw::GLuint, glw::GLuint>(width / 2, height / 6));
990 	borderPoints.push_back(std::pair<glw::GLuint, glw::GLuint>((glw::GLuint)(width / 6.0 * 5), height / 6));
991 	borderPoints.push_back(std::pair<glw::GLuint, glw::GLuint>(width / 6, height / 2));
992 	borderPoints.push_back(std::pair<glw::GLuint, glw::GLuint>((glw::GLuint)(width / 6.0 * 5), height / 2));
993 	borderPoints.push_back(std::pair<glw::GLuint, glw::GLuint>(width / 6, (glw::GLuint)(height / 6.0 * 5)));
994 	borderPoints.push_back(std::pair<glw::GLuint, glw::GLuint>(width / 2, (glw::GLuint)(height / 6.0 * 5)));
995 	borderPoints.push_back(
996 		std::pair<glw::GLuint, glw::GLuint>((glw::GLuint)(width / 6.0 * 5), (glw::GLuint)(height / 6.0 * 5)));
997 
998 	for (glw::GLuint j = 0; j < borderPoints.size(); ++j)
999 	{
1000 		for (glw::GLuint i = 0; i < deMinu32(out_components, in_components); ++i)
1001 		{
1002 			index = borderPoints[j].second * outRowWidth + borderPoints[j].first * out_components + i;
1003 			if (buffer[index] != expectedBorderColor)
1004 			{
1005 				m_testCtx.getLog() << tcu::TestLog::Message << "Wrong value for layer (" << layer
1006 								   << ") at point (x,y)  = (" << borderPoints[j].first << "," << borderPoints[j].second
1007 								   << ") , component (" << i << ")\n"
1008 								   << "Expected value [" << (glw::GLint)expectedBorderColor << "]\n"
1009 								   << "Result   value [" << (glw::GLint)buffer[index] << "]\n"
1010 								   << tcu::TestLog::EndMessage;
1011 				return false;
1012 			}
1013 		}
1014 	}
1015 
1016 	return true;
1017 }
1018 
1019 /** Check if result data is as expected when GL_LINEAR filtering is set
1020  *
1021  * @param buffer reference to the buffer with result data
1022  * @return       returns true if result data is as expected, otherwise return false
1023  */
1024 template <typename InputType, typename OutputType>
checkLinear(std::vector<OutputType> & buffer,glw::GLint layer)1025 bool TextureBorderClampSamplingTexture<InputType, OutputType>::checkLinear(std::vector<OutputType>& buffer,
1026 																		   glw::GLint layer)
1027 {
1028 	glw::GLuint w		= m_test_configuration.get_width();
1029 	glw::GLuint h		= m_test_configuration.get_height();
1030 	glw::GLuint centerX = w / 2;
1031 	glw::GLuint centerY = h / 2;
1032 	glw::GLuint stepX   = w / 3;
1033 	glw::GLuint stepY   = h / 3;
1034 
1035 	glw::GLuint index = 0;
1036 
1037 	glw::GLuint in_components  = m_test_configuration.get_n_in_components();
1038 	glw::GLuint out_components = m_test_configuration.get_n_out_components();
1039 	glw::GLuint outRowWidth	= w * out_components;
1040 
1041 	/* Check that some points well within the texture are 0.  Not applicable for
1042 	 * 3D, where some slices are blended with border along the depth coordinate.
1043 	 */
1044 	if (m_test_configuration.get_target() != GL_TEXTURE_3D)
1045 	{
1046 		glw::GLuint texture_samples[4][2] = {
1047 			{ centerX + w / 6, centerY },
1048 			{ centerX - w / 6, centerY },
1049 			{ centerX, centerY + h / 6 },
1050 			{ centerX, centerY - h / 6 },
1051 		};
1052 		for (glw::GLuint i = 0; i < 4; i++)
1053 		{
1054 			for (glw::GLuint c = 0; c < deMinu32(out_components, in_components); ++c)
1055 			{
1056 				if (buffer[texture_samples[i][1] * outRowWidth + texture_samples[i][0] * out_components + c] != 0)
1057 				{
1058 					m_testCtx.getLog() << tcu::TestLog::Message << "Texture sample at (x, y) = ("
1059 									   << texture_samples[i][0] << "," << texture_samples[i][1] << ") not black\n"
1060 									   << tcu::TestLog::EndMessage;
1061 					return false;
1062 				}
1063 			}
1064 		}
1065 	}
1066 
1067 	/* Check values from center to the bottom */
1068 	for (glw::GLuint y = centerY; y < centerY + stepY; ++y)
1069 	{
1070 		for (glw::GLuint c = 0; c < deMinu32(out_components, in_components); ++c)
1071 		{
1072 			index = y * outRowWidth + centerX * out_components + c;
1073 			if (buffer[index + outRowWidth] - buffer[index] < 0)
1074 			{
1075 				m_testCtx.getLog() << tcu::TestLog::Message << "For layer (" << layer
1076 								   << ") when moving from center point  (x, y)  = (" << centerX << "," << centerY
1077 								   << ") to the bottom\n"
1078 								   << "at point (x, y)  = (" << centerX << "," << y
1079 								   << ") - texel values stopped to be monotonically increasing\n"
1080 								   << tcu::TestLog::EndMessage;
1081 				return false;
1082 			}
1083 		}
1084 	}
1085 
1086 	/* Check values from center to the top */
1087 	for (glw::GLuint y = centerY; y > centerY - stepY; --y)
1088 	{
1089 		for (glw::GLuint c = 0; c < deMinu32(out_components, in_components); ++c)
1090 		{
1091 			index = y * outRowWidth + centerX * out_components + c;
1092 			if (buffer[index - outRowWidth] - buffer[index] < 0)
1093 			{
1094 				m_testCtx.getLog() << tcu::TestLog::Message << "For layer (" << layer
1095 								   << ") when moving from center point  (x, y)  = (" << centerX << "," << centerY
1096 								   << ") to the top\n"
1097 								   << "at point (x, y)  = (" << centerX << "," << y
1098 								   << ")- texel values stopped to be monotonically increasing\n"
1099 								   << tcu::TestLog::EndMessage;
1100 				return false;
1101 			}
1102 		}
1103 	}
1104 
1105 	/* Check values from center to the right */
1106 	for (glw::GLuint x = centerX; x < centerX + stepX; ++x)
1107 	{
1108 		for (glw::GLuint c = 0; c < deMinu32(out_components, in_components); ++c)
1109 		{
1110 			index = centerY + x * out_components + c;
1111 			if (buffer[index + out_components] - buffer[index] < 0)
1112 			{
1113 				m_testCtx.getLog() << tcu::TestLog::Message << "For layer (" << layer
1114 								   << ") when moving from center point  (x, y) = (" << centerX << "," << centerY
1115 								   << ") to the right\n"
1116 								   << "at point (x, y)  = (" << x << "," << centerY
1117 								   << ")- texel values stopped to be monotonically increasing\n"
1118 								   << tcu::TestLog::EndMessage;
1119 				return false;
1120 			}
1121 		}
1122 	}
1123 
1124 	/* Check values from center to the left */
1125 	for (glw::GLuint x = centerY; x > centerX - stepX; --x)
1126 	{
1127 		for (glw::GLuint c = 0; c < deMinu32(out_components, in_components); ++c)
1128 		{
1129 			index = centerY + x * out_components + c;
1130 			if (buffer[index - out_components] - buffer[index] < 0)
1131 			{
1132 				m_testCtx.getLog() << tcu::TestLog::Message << "For layer (" << layer
1133 								   << ") when moving from center point  (x, y) = (" << centerX << "," << centerY
1134 								   << ") to the left\n"
1135 								   << "at point (x, y)  = (" << x << "," << centerY
1136 								   << ")- texel values stopped to be monotonically increasing\n"
1137 								   << tcu::TestLog::EndMessage;
1138 				return false;
1139 			}
1140 		}
1141 	}
1142 
1143 	return true;
1144 }
1145 
1146 /** Returns start layer index
1147  *
1148  * @return returns start layer index (0 for GL_TEXTURE_2D target , otherwise -1)
1149  */
1150 template <typename InputType, typename OutputType>
getStartingLayerIndex()1151 glw::GLint TextureBorderClampSamplingTexture<InputType, OutputType>::getStartingLayerIndex()
1152 {
1153 	switch (m_test_configuration.get_target())
1154 	{
1155 	case GL_TEXTURE_2D:
1156 	case GL_TEXTURE_2D_ARRAY:
1157 		return 0;
1158 
1159 	case GL_TEXTURE_3D:
1160 		return -1;
1161 
1162 	default:
1163 		TCU_FAIL("Not allowed texture target - should be one of GL_TEXTURE_2D, GL_TEXTURE_2D_ARRAY, GL_TEXTURE_3D");
1164 	}
1165 }
1166 
1167 /** Returns last layer index
1168  *
1169  * @return returns last layer index (1 for GL_TEXTURE_2D target , otherwise depth + 1)
1170  */
1171 template <typename InputType, typename OutputType>
getLastLayerIndex()1172 glw::GLint TextureBorderClampSamplingTexture<InputType, OutputType>::getLastLayerIndex()
1173 {
1174 	switch (m_test_configuration.get_target())
1175 	{
1176 	case GL_TEXTURE_2D:
1177 	case GL_TEXTURE_2D_ARRAY:
1178 		return m_test_configuration.get_depth();
1179 
1180 	case GL_TEXTURE_3D:
1181 		return m_test_configuration.get_depth() + 1;
1182 
1183 	default:
1184 		TCU_FAIL("Not allowed texture target - should be one of GL_TEXTURE_2D, GL_TEXTURE_2D_ARRAY, GL_TEXTURE_3D");
1185 	}
1186 }
1187 
1188 /** Returns third texture coordinate to access a particular layer in a texture
1189  *
1190  * @return returns third texture coordinate
1191  */
1192 template <typename InputType, typename OutputType>
getCoordinateValue(glw::GLint index)1193 glw::GLfloat TextureBorderClampSamplingTexture<InputType, OutputType>::getCoordinateValue(glw::GLint index)
1194 {
1195 	switch (m_test_configuration.get_target())
1196 	{
1197 	case GL_TEXTURE_2D:
1198 		return 0.0f;
1199 		break;
1200 
1201 	case GL_TEXTURE_2D_ARRAY:
1202 		return (glw::GLfloat)index;
1203 
1204 	case GL_TEXTURE_3D:
1205 		return static_cast<glw::GLfloat>(index) / static_cast<glw::GLfloat>(m_test_configuration.get_depth());
1206 
1207 	default:
1208 		TCU_FAIL("Not allowed texture target - should be one of GL_TEXTURE_2D, GL_TEXTURE_2D_ARRAY, GL_TEXTURE_3D");
1209 	}
1210 }
1211 
1212 } // namespace glcts
1213