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  **/
getAmountOfLevelsForTexture(int width,int height)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  **/
TextureCubeMapArrayGenerateMipMapFilterable(Context & context,const ExtParameters & extParams,const char * name,const char * description,STORAGE_TYPE storageType)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 **/
deinit()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  */
generateTestData(int n_layer,unsigned char * data,int width,int height)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 **/
init()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 */
initTest()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  **/
iterate()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  **/
TextureCubeMapArrayGenerateMipMapNonFilterable(Context & context,const ExtParameters & extParams,const char * name,const char * description,STORAGE_TYPE storageType)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 **/
deinit()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 **/
init()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 **/
initTest()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  **/
iterate()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