Home | History | Annotate | Download | only in texture_cube_map_array
      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  esextcTextureCubeMapArrayGenerateMipMap.cpp
     26  * \brief texture_cube_map_array extenstion - glGenerateMipmap() (Test 7)
     27  */ /*-------------------------------------------------------------------*/
     28 
     29 #include "esextcTextureCubeMapArrayGenerateMipMap.hpp"
     30 
     31 #include "gluContextInfo.hpp"
     32 #include "glwEnums.hpp"
     33 #include "glwFunctions.hpp"
     34 #include "tcuTestLog.hpp"
     35 #include <cmath>
     36 #include <cstring>
     37 #include <vector>
     38 
     39 namespace glcts
     40 {
     41 
     42 /* Defines two pattern colors for each layer-face */
     43 const unsigned char TextureCubeMapArrayGenerateMipMapFilterable::m_layer_face_data
     44 	[m_n_max_faces][m_n_colors_per_layer_face][m_n_components] = {
     45 		/* Color 1           ---      Color 2      */
     46 		{ { 0, 0, 0, 0 }, { 255, 255, 255, 255 } },   /* Layer-face 0 */
     47 		{ { 255, 0, 0, 0 }, { 0, 255, 255, 255 } },   /* Layer-face 1 */
     48 		{ { 0, 255, 0, 0 }, { 255, 0, 255, 255 } },   /* Layer-face 2 */
     49 		{ { 0, 0, 255, 0 }, { 255, 255, 0, 255 } },   /* Layer-face 3 */
     50 		{ { 0, 0, 0, 255 }, { 255, 255, 255, 0 } },   /* Layer-face 4 */
     51 		{ { 255, 255, 0, 0 }, { 0, 0, 255, 255 } },   /* Layer-face 5 */
     52 		{ { 255, 0, 255, 0 }, { 0, 255, 0, 255 } },   /* Layer-face 6 */
     53 		{ { 255, 0, 0, 255 }, { 0, 255, 255, 0 } },   /* Layer-face 7 */
     54 		{ { 0, 255, 255, 0 }, { 255, 0, 0, 255 } },   /* Layer-face 8 */
     55 		{ { 0, 255, 0, 255 }, { 255, 0, 255, 0 } },   /* Layer-face 9 */
     56 		{ { 255, 255, 255, 0 }, { 0, 0, 0, 255 } },   /* Layer-face 10 */
     57 		{ { 255, 255, 0, 255 }, { 0, 0, 255, 0 } },   /* Layer-face 11 */
     58 		{ { 255, 255, 255, 255 }, { 0, 0, 0, 0 } },   /* Layer-face 12 */
     59 		{ { 0, 0, 0, 255 }, { 255, 0, 0, 0 } },		  /* Layer-face 13 */
     60 		{ { 0, 0, 0, 255 }, { 255, 255, 0, 0 } },	 /* Layer-face 14 */
     61 		{ { 0, 0, 255, 0 }, { 255, 255, 255, 0 } },   /* Layer-face 15 */
     62 		{ { 0, 255, 0, 0 }, { 255, 255, 255, 255 } }, /* Layer-face 16 */
     63 		{ { 255, 0, 0, 0 }, { 255, 0, 255, 255 } }	/* Layer-face 17 */
     64 	};
     65 
     66 /** Retrieves maximum amount of levels that should be defined for
     67  *  a texture of user-provided dimensions.
     68  *
     69  *  @param width  Width of the texture in question.
     70  *  @param height Height of the texture in question.
     71  *
     72  *  @return Requested value.
     73  **/
     74 static int getAmountOfLevelsForTexture(int width, int height)
     75 {
     76 	return (int)floor(log((float)(de::max(width, height))) / log(2.0f)) + 1;
     77 }
     78 
     79 /** Constructor
     80  *
     81  *  @param context     Test context;
     82  *  @param name        Test case's name;
     83  *  @param description Test case's description;
     84  *  @param storageType Precises whether texture objects used by this
     85  *                     test instance should be created as immutable or
     86  *                     mutable objects.
     87  **/
     88 TextureCubeMapArrayGenerateMipMapFilterable::TextureCubeMapArrayGenerateMipMapFilterable(Context&			  context,
     89 																						 const ExtParameters& extParams,
     90 																						 const char*		  name,
     91 																						 const char*  description,
     92 																						 STORAGE_TYPE storageType)
     93 	: TestCaseBase(context, extParams, name, description)
     94 	, m_fbo_id(0)
     95 	, m_storage_type(storageType)
     96 	, m_reference_data_ptr(DE_NULL)
     97 	, m_rendered_data_ptr(DE_NULL)
     98 {
     99 	/* Nothing to be done here */
    100 }
    101 
    102 /** Deinitialize test case **/
    103 void TextureCubeMapArrayGenerateMipMapFilterable::deinit()
    104 {
    105 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
    106 
    107 	/* Reset texture and FBO bindings */
    108 	gl.bindFramebuffer(GL_READ_FRAMEBUFFER, 0);
    109 	gl.bindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, 0);
    110 
    111 	/* Release any ES objects that may have been created. */
    112 	if (m_fbo_id != 0)
    113 	{
    114 		gl.deleteFramebuffers(1, &m_fbo_id);
    115 
    116 		m_fbo_id = 0;
    117 	}
    118 
    119 	for (unsigned int i = 0; i < m_storage_configs.size(); ++i)
    120 	{
    121 		if (m_storage_configs[i].m_to_id != 0)
    122 		{
    123 			gl.deleteTextures(1, &m_storage_configs[i].m_to_id);
    124 
    125 			m_storage_configs[i].m_to_id = 0;
    126 		}
    127 	}
    128 
    129 	/* Release buffers the test may have allocated */
    130 	if (m_reference_data_ptr != DE_NULL)
    131 	{
    132 		delete[] m_reference_data_ptr;
    133 
    134 		m_reference_data_ptr = DE_NULL;
    135 	}
    136 
    137 	if (m_rendered_data_ptr != DE_NULL)
    138 	{
    139 		delete[] m_rendered_data_ptr;
    140 
    141 		m_rendered_data_ptr = DE_NULL;
    142 	}
    143 
    144 	/* Restore pixel pack/unpack settings */
    145 	gl.pixelStorei(GL_PACK_ALIGNMENT, 4);
    146 	gl.pixelStorei(GL_UNPACK_ALIGNMENT, 4);
    147 
    148 	/* Call base class' deinitialization routine. */
    149 	TestCaseBase::deinit();
    150 }
    151 
    152 /** Fills user-provided buffer with expected pixel data for user-specified
    153  *  layer index.
    154  *
    155  * @param n_layer Layer index to return expected data for.
    156  * @param data    Pointer to a buffer that will be filled with
    157  *                result data. Must not be NULL.
    158  * @param width   Render-target width.
    159  * @param height  Render-target height.
    160  */
    161 void TextureCubeMapArrayGenerateMipMapFilterable::generateTestData(int n_layer, unsigned char* data, int width,
    162 																   int height)
    163 {
    164 	DE_ASSERT(data != DE_NULL);
    165 
    166 	for (int x = 0; x < width; ++x)
    167 	{
    168 		for (int y = 0; y < height; ++y)
    169 		{
    170 			for (int n_component = 0; n_component < m_n_components; ++n_component)
    171 			{
    172 				const unsigned int pixel_size = m_n_components;
    173 				unsigned char*	 result_ptr = data + ((y * width + x) * pixel_size + n_component);
    174 				unsigned int	   n_color	= ((x % m_n_colors_per_layer_face) + y) % m_n_colors_per_layer_face;
    175 
    176 				*result_ptr = m_layer_face_data[n_layer][n_color][n_component];
    177 			}
    178 		}
    179 	}
    180 }
    181 
    182 /** Initialize test case **/
    183 void TextureCubeMapArrayGenerateMipMapFilterable::init()
    184 {
    185 	/* Base class initialization */
    186 	TestCaseBase::init();
    187 
    188 	/* Check if texture_cube_map_array extension is supported */
    189 	if (!m_is_texture_cube_map_array_supported)
    190 	{
    191 		throw tcu::NotSupportedError(TEXTURE_CUBE_MAP_ARRAY_EXTENSION_NOT_SUPPORTED);
    192 	}
    193 }
    194 
    195 /** Initializes all ES objects that will be used by the test */
    196 void TextureCubeMapArrayGenerateMipMapFilterable::initTest()
    197 {
    198 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
    199 
    200 	/* Make sure the storage config container is empty */
    201 	m_storage_configs.clear();
    202 
    203 	/* Update pixel pack/unpack settings */
    204 	gl.pixelStorei(GL_PACK_ALIGNMENT, 1);
    205 	gl.pixelStorei(GL_UNPACK_ALIGNMENT, 1);
    206 
    207 	GLU_EXPECT_NO_ERROR(gl.getError(), "glPixelStorei() call(s) failed");
    208 
    209 	/* Define following texture configurations
    210 	 *
    211 	 *    [width x height x depth]
    212 	 * 1)   64   x   64   x  18;
    213 	 * 2)  117   x  117   x   6;
    214 	 * 3)  256   x  256   x   6;
    215 	 * 4)  173   x  173   x  12;
    216 	 *
    217 	 * We use GL_RGBA8 internal format in all cases.
    218 	 */
    219 
    220 	/* Resolution 64 x 64 x 18 */
    221 	StorageConfig storage_config_1;
    222 
    223 	storage_config_1.m_width  = 64;
    224 	storage_config_1.m_height = 64;
    225 	storage_config_1.m_depth  = 18;
    226 	storage_config_1.m_to_id  = 0;
    227 	storage_config_1.m_levels = getAmountOfLevelsForTexture(storage_config_1.m_width, storage_config_1.m_height);
    228 
    229 	/* Resolution 117 x 117 x 6 */
    230 	StorageConfig storage_config_2;
    231 
    232 	storage_config_2.m_width  = 117;
    233 	storage_config_2.m_height = 117;
    234 	storage_config_2.m_depth  = 6;
    235 	storage_config_2.m_to_id  = 0;
    236 	storage_config_2.m_levels = getAmountOfLevelsForTexture(storage_config_2.m_width, storage_config_2.m_height);
    237 
    238 	/* Resolution 256 x 256 x 6 */
    239 	StorageConfig storage_config_3;
    240 
    241 	storage_config_3.m_width  = 256;
    242 	storage_config_3.m_height = 256;
    243 	storage_config_3.m_depth  = 6;
    244 	storage_config_3.m_to_id  = 0;
    245 	storage_config_3.m_levels = getAmountOfLevelsForTexture(storage_config_3.m_width, storage_config_3.m_height);
    246 
    247 	/* Resolution 173 x 173 x 12 */
    248 	StorageConfig storage_config_4;
    249 
    250 	storage_config_4.m_width  = 173;
    251 	storage_config_4.m_height = 173;
    252 	storage_config_4.m_depth  = 12;
    253 	storage_config_4.m_to_id  = 0;
    254 	storage_config_4.m_levels = getAmountOfLevelsForTexture(storage_config_4.m_width, storage_config_4.m_height);
    255 
    256 	m_storage_configs.push_back(storage_config_1);
    257 	m_storage_configs.push_back(storage_config_2);
    258 	m_storage_configs.push_back(storage_config_3);
    259 	m_storage_configs.push_back(storage_config_4);
    260 
    261 	/* Generate and configure a texture object for each storage config. */
    262 	for (unsigned int n_storage_config = 0; n_storage_config < m_storage_configs.size(); n_storage_config++)
    263 	{
    264 		StorageConfig& config = m_storage_configs[n_storage_config];
    265 
    266 		gl.genTextures(1, &config.m_to_id);
    267 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call failed");
    268 
    269 		gl.bindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, config.m_to_id);
    270 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed");
    271 
    272 		gl.texParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    273 		gl.texParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    274 		GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri() call(s) failed");
    275 
    276 		if (m_storage_type == ST_MUTABLE)
    277 		{
    278 			gl.texImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0,									/* level */
    279 						  GL_RGBA8, config.m_width, config.m_height, config.m_depth, 0, /* border */
    280 						  GL_RGBA, GL_UNSIGNED_BYTE, DE_NULL);
    281 
    282 			GLU_EXPECT_NO_ERROR(gl.getError(), "glTexImage3D() call failed");
    283 		}
    284 		else
    285 		{
    286 			DE_ASSERT(m_storage_type == ST_IMMUTABLE);
    287 
    288 			gl.texStorage3D(GL_TEXTURE_CUBE_MAP_ARRAY, config.m_levels, GL_RGBA8, config.m_width, config.m_height,
    289 							config.m_depth);
    290 
    291 			GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage3D() call failed");
    292 		}
    293 	} /* for (all storage configs) */
    294 
    295 	/* Generate a frame-buffer object */
    296 	gl.genFramebuffers(1, &m_fbo_id);
    297 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers() call failed");
    298 }
    299 
    300 /** Executes the test.
    301  *
    302  *  Note the function throws exception should an error occur!
    303  *
    304  *  @return Always STOP.
    305  **/
    306 tcu::TestCase::IterateResult TextureCubeMapArrayGenerateMipMapFilterable::iterate()
    307 {
    308 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
    309 
    310 	/* Initialize ES objects we will need to run the test */
    311 	initTest();
    312 
    313 	/* Iterate through all configuration descriptors */
    314 	unsigned int n_storage_config = 0;
    315 
    316 	for (std::vector<StorageConfig>::const_iterator storage_config_iterator = m_storage_configs.begin();
    317 		 storage_config_iterator != m_storage_configs.end(); storage_config_iterator++, n_storage_config++)
    318 	{
    319 		const StorageConfig& storage_config = *storage_config_iterator;
    320 
    321 		gl.bindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, storage_config.m_to_id);
    322 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed");
    323 
    324 		/* Fill each base layer-face with pattern data */
    325 		for (unsigned int n_layer_face = 0; n_layer_face < storage_config.m_depth; ++n_layer_face)
    326 		{
    327 			/* Allocate buffer we will use to store the layer data */
    328 			const int data_size = static_cast<int>(storage_config.m_width * storage_config.m_height * m_n_components *
    329 												   sizeof(unsigned char));
    330 			unsigned char* data_ptr = new unsigned char[data_size];
    331 
    332 			if (data_ptr == DE_NULL)
    333 			{
    334 				TCU_FAIL("Out of memory");
    335 			}
    336 
    337 			generateTestData(n_layer_face, data_ptr, storage_config.m_width, storage_config.m_height);
    338 
    339 			/* Fill base texture-layer Texture */
    340 			gl.texSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0,						 /* level */
    341 							 0,													 /* xoffset */
    342 							 0,													 /* yoffset */
    343 							 n_layer_face,										 /* zoffset */
    344 							 storage_config.m_width, storage_config.m_height, 1, /* depth */
    345 							 GL_RGBA, GL_UNSIGNED_BYTE, data_ptr);
    346 
    347 			/* Release the data buffer */
    348 			delete[] data_ptr;
    349 
    350 			data_ptr = DE_NULL;
    351 
    352 			/* Make sure the call was successful */
    353 			GLU_EXPECT_NO_ERROR(gl.getError(), "glTexSubImage3D() call failed");
    354 		}
    355 
    356 		/* Generate mip-maps */
    357 		gl.generateMipmap(GL_TEXTURE_CUBE_MAP_ARRAY);
    358 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGenerateMipmap() call failed");
    359 
    360 		/* Attach a FBO to GL_READ_FRAMEBUFFER binding point. */
    361 		gl.bindFramebuffer(GL_READ_FRAMEBUFFER, m_fbo_id);
    362 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer() call failed");
    363 
    364 		/* Allocate buffers to hold reference & rendered data */
    365 		unsigned char	  last_level_data_buffer[m_n_components] = { 0 };
    366 		const unsigned int size =
    367 			static_cast<int>(storage_config.m_width * storage_config.m_height * m_n_components * sizeof(unsigned char));
    368 
    369 		m_reference_data_ptr = new unsigned char[size];
    370 		m_rendered_data_ptr  = new unsigned char[size];
    371 
    372 		if (m_reference_data_ptr == DE_NULL || m_rendered_data_ptr == DE_NULL)
    373 		{
    374 			TCU_FAIL("Out of memory");
    375 		}
    376 
    377 		/* Verify correctness of layer-face data */
    378 		for (unsigned int n_layer_face = 0; n_layer_face < storage_config.m_depth; ++n_layer_face)
    379 		{
    380 			/* Generate reference data */
    381 			generateTestData(n_layer_face, m_reference_data_ptr, storage_config.m_width, storage_config.m_height);
    382 
    383 			/* Attach iteration-specific base layer-face to the read frame-buffer */
    384 			gl.framebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, storage_config.m_to_id, 0, /* level */
    385 									   n_layer_face);
    386 
    387 			GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTextureLayer() call failed.");
    388 
    389 			/* Read the layer-face data */
    390 			gl.readPixels(0, /* x */
    391 						  0, /* y */
    392 						  storage_config.m_width, storage_config.m_height, GL_RGBA, GL_UNSIGNED_BYTE,
    393 						  m_rendered_data_ptr);
    394 
    395 			GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels() call failed.");
    396 
    397 			/* Make sure the base layer-face contents reported with the call is as was uploaded */
    398 			const unsigned int base_layer_data_size = static_cast<int>(
    399 				storage_config.m_width * storage_config.m_height * m_n_components * sizeof(unsigned char));
    400 
    401 			if (memcmp(m_reference_data_ptr, m_rendered_data_ptr, base_layer_data_size))
    402 			{
    403 				m_testCtx.getLog() << tcu::TestLog::Message << "Data stored in base layer mip-map for storage config ["
    404 								   << n_storage_config << "]"
    405 														  "and layer-face index ["
    406 								   << n_layer_face << "]"
    407 													  " is different than was uploaded"
    408 								   << tcu::TestLog::EndMessage;
    409 
    410 				TCU_FAIL("Invalid data found for base layer mip-map");
    411 			}
    412 
    413 			/* Update the read framebuffer's color attachment to read from
    414 			 * the last mip-map available for currently processed layer-face
    415 			 */
    416 			gl.framebufferTextureLayer(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, storage_config.m_to_id, /* texture */
    417 									   storage_config.m_levels - 1,										  /* level */
    418 									   n_layer_face);													  /* layer */
    419 
    420 			GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTextureLayer() call failed.");
    421 
    422 			/* Read the data */
    423 			gl.readPixels(0, /* x */
    424 						  0, /* y */
    425 						  1, /* width */
    426 						  1, /* height */
    427 						  GL_RGBA, GL_UNSIGNED_BYTE, last_level_data_buffer);
    428 			GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels() call failed");
    429 
    430 			/* Make sure that the data read from the last layer is not equal to either
    431 			 * of the pattern colors used for the layer-face
    432 			 */
    433 			for (int n_pattern_color = 0; n_pattern_color < m_n_colors_per_layer_face; ++n_pattern_color)
    434 			{
    435 				if (!memcmp(m_layer_face_data[n_layer_face][n_pattern_color], last_level_data_buffer,
    436 							m_n_components * sizeof(unsigned char)))
    437 				{
    438 					m_testCtx.getLog()
    439 						<< tcu::TestLog::Message << "Texel stored in layer-face's smallest mip-map for storage config ["
    440 						<< n_storage_config << "]"
    441 											   "and layer-face index ["
    442 						<< n_layer_face
    443 						<< "]"
    444 						   "describes one of the colors used for the pattern used in base mip-map, which is invalid."
    445 						<< tcu::TestLog::EndMessage;
    446 
    447 					TCU_FAIL("Invalid color found in the layer-face's smallest mip-map");
    448 				}
    449 			} /* for (all pattern colors) */
    450 		}	 /* for (all layer-faces) */
    451 
    452 		/* Release the buffers we allocated specifically for currently processed
    453 		 * storage config.
    454 		 */
    455 		if (m_reference_data_ptr != DE_NULL)
    456 		{
    457 			delete[] m_reference_data_ptr;
    458 
    459 			m_reference_data_ptr = DE_NULL;
    460 		}
    461 
    462 		if (m_rendered_data_ptr != DE_NULL)
    463 		{
    464 			delete[] m_rendered_data_ptr;
    465 
    466 			m_rendered_data_ptr = DE_NULL;
    467 		}
    468 	} /* for (all storage configs) */
    469 
    470 	/* Test has passed */
    471 	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
    472 	return STOP;
    473 }
    474 
    475 /** Constructor
    476  *
    477  *  @param context     Test context
    478  *  @param name        Test case's name
    479  *  @param description Test case's description
    480  *  @param storageType Precises whether texture objects used by this
    481  *                     test instance should be created as immutable or
    482  *                     mutable objects.
    483  **/
    484 TextureCubeMapArrayGenerateMipMapNonFilterable::TextureCubeMapArrayGenerateMipMapNonFilterable(
    485 	Context& context, const ExtParameters& extParams, const char* name, const char* description,
    486 	STORAGE_TYPE storageType)
    487 	: TestCaseBase(context, extParams, name, description), m_storage_type(storageType)
    488 {
    489 	/* Nothing to be done here */
    490 }
    491 
    492 /** Deinitialize test case **/
    493 void TextureCubeMapArrayGenerateMipMapNonFilterable::deinit()
    494 {
    495 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
    496 
    497 	/* Restore default bindings */
    498 	gl.bindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, 0);
    499 
    500 	/* Restore default pixel pack/unpack settings */
    501 	gl.pixelStorei(GL_PACK_ALIGNMENT, 4);
    502 	gl.pixelStorei(GL_UNPACK_ALIGNMENT, 4);
    503 
    504 	/* Delete all textures the test may have created. */
    505 	for (unsigned int n_storage_config = 0; n_storage_config < m_non_filterable_texture_configs.size();
    506 		 ++n_storage_config)
    507 	{
    508 		if (m_non_filterable_texture_configs[n_storage_config].m_to_id != 0)
    509 		{
    510 			gl.deleteTextures(1, &m_non_filterable_texture_configs[n_storage_config].m_to_id);
    511 
    512 			m_non_filterable_texture_configs[n_storage_config].m_to_id = 0;
    513 		}
    514 	}
    515 
    516 	/* Call base class' deinit() implementation */
    517 	TestCaseBase::deinit();
    518 }
    519 
    520 /** Initialize test case **/
    521 void TextureCubeMapArrayGenerateMipMapNonFilterable::init()
    522 {
    523 	/* Base class initialization */
    524 	TestCaseBase::init();
    525 
    526 	if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
    527 	{
    528 		throw tcu::NotSupportedError("The test can be run only in ES context");
    529 	}
    530 
    531 	/* Check if texture_cube_map_array extension is supported */
    532 	if (!m_is_texture_cube_map_array_supported)
    533 	{
    534 		throw tcu::NotSupportedError(TEXTURE_CUBE_MAP_ARRAY_EXTENSION_NOT_SUPPORTED);
    535 	}
    536 }
    537 
    538 /** Initializes all ES objects used by the test **/
    539 void TextureCubeMapArrayGenerateMipMapNonFilterable::initTest()
    540 {
    541 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
    542 
    543 	/* Make sure no configs are already in place */
    544 	m_non_filterable_texture_configs.clear();
    545 
    546 	/* Update pixel pack/unpack settings */
    547 	gl.pixelStorei(GL_PACK_ALIGNMENT, 1);
    548 	gl.pixelStorei(GL_UNPACK_ALIGNMENT, 1);
    549 
    550 	GLU_EXPECT_NO_ERROR(gl.getError(), "glPixelStorei() call(s) failed");
    551 
    552 	/* Define a number of storage configurations, all using GL_RGBA32I
    553 	 * internalformat:
    554 	 *
    555 	 *    [width x height x depth]
    556 	 * 1)   64   x   64   x  18;
    557 	 * 2)  117   x  117   x   6;
    558 	 * 3)  256   x  256   x   6;
    559 	 * 4)  173   x  173   x  12;
    560 	 */
    561 
    562 	/* Size 64 x 64 x 18 */
    563 	StorageConfig storage_config1;
    564 
    565 	storage_config1.m_width  = 64;
    566 	storage_config1.m_height = 64;
    567 	storage_config1.m_depth  = 18;
    568 	storage_config1.m_to_id  = 0;
    569 	storage_config1.m_levels = getAmountOfLevelsForTexture(storage_config1.m_width, storage_config1.m_height);
    570 
    571 	/* Size 117 x 117 x 6 */
    572 	StorageConfig storage_config2;
    573 
    574 	storage_config2.m_width  = 117;
    575 	storage_config2.m_height = 117;
    576 	storage_config2.m_depth  = 6;
    577 	storage_config2.m_to_id  = 0;
    578 	storage_config2.m_levels = getAmountOfLevelsForTexture(storage_config2.m_width, storage_config2.m_height);
    579 
    580 	/* Size 256 x 256 x 6 */
    581 	StorageConfig storage_config3;
    582 
    583 	storage_config3.m_width  = 256;
    584 	storage_config3.m_height = 256;
    585 	storage_config3.m_depth  = 6;
    586 	storage_config3.m_to_id  = 0;
    587 	storage_config3.m_levels = getAmountOfLevelsForTexture(storage_config3.m_width, storage_config3.m_height);
    588 
    589 	/* Size 173 x 173 x 12 */
    590 	StorageConfig storage_config4;
    591 
    592 	storage_config4.m_width  = 173;
    593 	storage_config4.m_height = 173;
    594 	storage_config4.m_depth  = 12;
    595 	storage_config4.m_to_id  = 0;
    596 	storage_config4.m_levels = getAmountOfLevelsForTexture(storage_config4.m_width, storage_config4.m_height);
    597 
    598 	m_non_filterable_texture_configs.push_back(storage_config1);
    599 	m_non_filterable_texture_configs.push_back(storage_config2);
    600 	m_non_filterable_texture_configs.push_back(storage_config3);
    601 	m_non_filterable_texture_configs.push_back(storage_config4);
    602 
    603 	/* Generate and configure a texture object for each storage config. */
    604 	for (std::vector<StorageConfig>::iterator storage_config_iterator = m_non_filterable_texture_configs.begin();
    605 		 storage_config_iterator != m_non_filterable_texture_configs.end(); storage_config_iterator++)
    606 	{
    607 		StorageConfig& storage_config = *storage_config_iterator;
    608 
    609 		gl.genTextures(1, &storage_config.m_to_id);
    610 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call failed.");
    611 
    612 		gl.bindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, storage_config.m_to_id);
    613 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");
    614 
    615 		gl.texParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    616 		gl.texParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    617 		GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri() call(s) failed.");
    618 
    619 		/* Initialize texture storage. */
    620 		if (m_storage_type == ST_MUTABLE)
    621 		{
    622 			gl.texImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, /* level */
    623 						  GL_RGBA32I, storage_config.m_width, storage_config.m_height, storage_config.m_depth, 0,
    624 						  GL_RGBA_INTEGER, GL_INT, 0); /* data */
    625 
    626 			GLU_EXPECT_NO_ERROR(gl.getError(), "glTexImage3D() call failed.");
    627 		}
    628 		else
    629 		{
    630 			gl.texStorage3D(GL_TEXTURE_CUBE_MAP_ARRAY, storage_config.m_levels, GL_RGBA32I, storage_config.m_width,
    631 							storage_config.m_height, storage_config.m_depth);
    632 
    633 			GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage3D() call failed.");
    634 		}
    635 	} /* for (all storage configs) */
    636 }
    637 
    638 /** Executes the test.
    639  *
    640  *  Note the function throws exception should an error occur!
    641  *
    642  *  @return Always STOP.
    643  **/
    644 tcu::TestCase::IterateResult TextureCubeMapArrayGenerateMipMapNonFilterable::iterate()
    645 {
    646 	/* Initialize ES objects used by the test */
    647 	initTest();
    648 
    649 	/* Verify that glGenerateMipmap() always throws GL_INVALID_OPERATION, if the
    650 	 * texture object the call would operate on uses non-filterable internalformat.
    651 	 */
    652 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
    653 
    654 	for (unsigned int n_storage_config = 0; n_storage_config < m_non_filterable_texture_configs.size();
    655 		 ++n_storage_config)
    656 	{
    657 		gl.bindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, m_non_filterable_texture_configs[n_storage_config].m_to_id);
    658 
    659 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");
    660 
    661 		gl.generateMipmap(GL_TEXTURE_CUBE_MAP_ARRAY);
    662 
    663 		/* What's the error code at this point? */
    664 		int error_code = gl.getError();
    665 
    666 		if (error_code != GL_INVALID_OPERATION)
    667 		{
    668 			m_testCtx.getLog() << tcu::TestLog::Message
    669 							   << "glGenerateMipmap() operating on an non-filterable internalformat "
    670 								  "did not report GL_INVALID_OPERATION as per spec but "
    671 							   << error_code << " instead." << tcu::TestLog::EndMessage;
    672 
    673 			TCU_FAIL("Invalid error code reported for an invalid glGenerateMipmap() call.");
    674 		}
    675 	} /* for (all storage configs) */
    676 
    677 	/* The test has passed */
    678 	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
    679 
    680 	return STOP;
    681 }
    682 
    683 } /* glcts */
    684