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