1/*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL ES 3.1 Module
3 * -------------------------------------------------
4 *
5 * Copyright 2014 The Android Open Source Project
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 Texture level state query tests
22 *//*--------------------------------------------------------------------*/
23
24#include "es31fTextureLevelStateQueryTests.hpp"
25#include "glsStateQueryUtil.hpp"
26#include "tcuTestLog.hpp"
27#include "gluRenderContext.hpp"
28#include "gluCallLogWrapper.hpp"
29#include "gluTextureUtil.hpp"
30#include "gluStrUtil.hpp"
31#include "gluContextInfo.hpp"
32#include "glwFunctions.hpp"
33#include "glwEnums.hpp"
34#include "deStringUtil.hpp"
35#include "tcuTextureUtil.hpp"
36
37namespace deqp
38{
39namespace gles31
40{
41namespace Functional
42{
43namespace
44{
45
46enum VerifierType
47{
48	VERIFIER_INT = 0,
49	VERIFIER_FLOAT
50};
51
52struct TextureGenerationSpec
53{
54	struct TextureLevelSpec
55	{
56		int			width;
57		int			height;
58		int			depth;
59		int			level;
60		glw::GLenum internalFormat;
61		bool		compressed;
62	};
63
64	glw::GLenum						bindTarget;
65	glw::GLenum						queryTarget;
66	bool							immutable;
67	bool							fixedSamplePos;	// !< fixed sample pos argument for multisample textures
68	int								sampleCount;
69	std::vector<TextureLevelSpec>	levels;
70	std::string						description;
71};
72
73static bool textureTypeHasDepth (glw::GLenum textureBindTarget)
74{
75	switch (textureBindTarget)
76	{
77		case GL_TEXTURE_2D:						return false;
78		case GL_TEXTURE_3D:						return true;
79		case GL_TEXTURE_2D_ARRAY:				return true;
80		case GL_TEXTURE_CUBE_MAP:				return false;
81		case GL_TEXTURE_2D_MULTISAMPLE:			return false;
82		case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:	return true;
83		default:
84			DE_ASSERT(DE_FALSE);
85			return false;
86	}
87}
88
89struct IntegerPrinter
90{
91	static std::string	getIntegerName	(int v)		{ return de::toString(v); }
92	static std::string	getFloatName	(float v)	{ return de::toString(v); }
93};
94
95struct PixelFormatPrinter
96{
97	static std::string	getIntegerName	(int v)		{ return de::toString(glu::getPixelFormatStr(v));		}
98	static std::string	getFloatName	(float v)	{ return de::toString(glu::getPixelFormatStr((int)v));	}
99};
100
101template <typename Printer>
102static bool verifyTextureLevelParameterEqualWithPrinter (glu::CallLogWrapper& gl, glw::GLenum target, int level, glw::GLenum pname, int refValue, VerifierType type)
103{
104	gl.getLog() << tcu::TestLog::Message << "Verifying " << glu::getTextureLevelParameterStr(pname) << ", expecting " << Printer::getIntegerName(refValue) << tcu::TestLog::EndMessage;
105
106	if (type == VERIFIER_INT)
107	{
108		gls::StateQueryUtil::StateQueryMemoryWriteGuard<int> result;
109
110		gl.glGetTexLevelParameteriv(target, level, pname, &result);
111		GLU_EXPECT_NO_ERROR(gl.glGetError(), "glGetTexLevelParameteriv");
112
113		if (result.isUndefined())
114		{
115			gl.getLog() << tcu::TestLog::Message << "Error: Get* did not write a value." << tcu::TestLog::EndMessage;
116			return false;
117		}
118		else if (result.isMemoryContaminated())
119		{
120			gl.getLog() << tcu::TestLog::Message << "Error: detected illegal memory write." << tcu::TestLog::EndMessage;
121			return false;
122		}
123
124		if (result == refValue)
125			return true;
126
127		gl.getLog() << tcu::TestLog::Message << "Error: Expected " << Printer::getIntegerName(refValue) << ", got " << Printer::getIntegerName(result) << tcu::TestLog::EndMessage;
128		return false;
129	}
130	else if (type == VERIFIER_FLOAT)
131	{
132		gls::StateQueryUtil::StateQueryMemoryWriteGuard<float> result;
133
134		gl.glGetTexLevelParameterfv(target, level, pname, &result);
135		GLU_EXPECT_NO_ERROR(gl.glGetError(), "glGetTexLevelParameterfv");
136
137		if (result.isUndefined())
138		{
139			gl.getLog() << tcu::TestLog::Message << "Error: Get* did not write a value." << tcu::TestLog::EndMessage;
140			return false;
141		}
142		else if (result.isMemoryContaminated())
143		{
144			gl.getLog() << tcu::TestLog::Message << "Error: detected illegal memory write." << tcu::TestLog::EndMessage;
145			return false;
146		}
147
148		if (result == (float)refValue)
149			return true;
150
151		gl.getLog() << tcu::TestLog::Message << "Error: Expected " << Printer::getIntegerName(refValue) << ", got " << Printer::getFloatName(result) << tcu::TestLog::EndMessage;
152		return false;
153	}
154
155	DE_ASSERT(DE_FALSE);
156	return false;
157}
158
159static bool verifyTextureLevelParameterEqual (glu::CallLogWrapper& gl, glw::GLenum target, int level, glw::GLenum pname, int refValue, VerifierType type)
160{
161	return verifyTextureLevelParameterEqualWithPrinter<IntegerPrinter>(gl, target, level, pname, refValue, type);
162}
163
164static bool verifyTextureLevelParameterInternalFormatEqual (glu::CallLogWrapper& gl, glw::GLenum target, int level, glw::GLenum pname, int refValue, VerifierType type)
165{
166	return verifyTextureLevelParameterEqualWithPrinter<PixelFormatPrinter>(gl, target, level, pname, refValue, type);
167}
168
169static bool verifyTextureLevelParameterGreaterOrEqual (glu::CallLogWrapper& gl, glw::GLenum target, int level, glw::GLenum pname, int refValue, VerifierType type)
170{
171	gl.getLog() << tcu::TestLog::Message << "Verifying " << glu::getTextureLevelParameterStr(pname) << ", expecting " << refValue << " or greater" << tcu::TestLog::EndMessage;
172
173	if (type == VERIFIER_INT)
174	{
175		gls::StateQueryUtil::StateQueryMemoryWriteGuard<int> result;
176
177		gl.glGetTexLevelParameteriv(target, level, pname, &result);
178		GLU_EXPECT_NO_ERROR(gl.glGetError(), "glGetTexLevelParameteriv");
179
180		if (result.isUndefined())
181		{
182			gl.getLog() << tcu::TestLog::Message << "Error: Get* did not write a value." << tcu::TestLog::EndMessage;
183			return false;
184		}
185		else if (result.isMemoryContaminated())
186		{
187			gl.getLog() << tcu::TestLog::Message << "Error: detected illegal memory write." << tcu::TestLog::EndMessage;
188			return false;
189		}
190
191		if (result >= refValue)
192			return true;
193
194		gl.getLog() << tcu::TestLog::Message << "Error: Expected " << refValue << " or larger, got " << result << tcu::TestLog::EndMessage;
195		return false;
196	}
197	else if (type == VERIFIER_FLOAT)
198	{
199		gls::StateQueryUtil::StateQueryMemoryWriteGuard<float> result;
200
201		gl.glGetTexLevelParameterfv(target, level, pname, &result);
202		GLU_EXPECT_NO_ERROR(gl.glGetError(), "glGetTexLevelParameterfv");
203
204		if (result.isUndefined())
205		{
206			gl.getLog() << tcu::TestLog::Message << "Error: Get* did not write a value." << tcu::TestLog::EndMessage;
207			return false;
208		}
209		else if (result.isMemoryContaminated())
210		{
211			gl.getLog() << tcu::TestLog::Message << "Error: detected illegal memory write." << tcu::TestLog::EndMessage;
212			return false;
213		}
214
215		if (result >= (float)refValue)
216			return true;
217
218		gl.getLog() << tcu::TestLog::Message << "Error: Expected " << refValue << " or larger, got " << result << tcu::TestLog::EndMessage;
219		return false;
220	}
221
222	DE_ASSERT(DE_FALSE);
223	return false;
224}
225
226static bool verifyTextureLevelParameterInternalFormatAnyOf (glu::CallLogWrapper& gl, glw::GLenum target, int level, glw::GLenum pname, const int* refValues, int numRefValues, VerifierType type)
227{
228	// Log what we try to do
229	{
230		tcu::MessageBuilder msg(&gl.getLog());
231
232		msg << "Verifying " << glu::getTextureLevelParameterStr(pname) << ", expecting any of {";
233		for (int ndx = 0; ndx < numRefValues; ++ndx)
234		{
235			if (ndx != 0)
236				msg << ", ";
237			msg << glu::getPixelFormatStr(refValues[ndx]);
238		}
239		msg << "}";
240		msg << tcu::TestLog::EndMessage;
241	}
242
243	// verify
244	if (type == VERIFIER_INT)
245	{
246		gls::StateQueryUtil::StateQueryMemoryWriteGuard<int> result;
247
248		gl.glGetTexLevelParameteriv(target, level, pname, &result);
249		GLU_EXPECT_NO_ERROR(gl.glGetError(), "glGetTexLevelParameteriv");
250
251		if (result.isUndefined())
252		{
253			gl.getLog() << tcu::TestLog::Message << "Error: Get* did not write a value." << tcu::TestLog::EndMessage;
254			return false;
255		}
256		else if (result.isMemoryContaminated())
257		{
258			gl.getLog() << tcu::TestLog::Message << "Error: detected illegal memory write." << tcu::TestLog::EndMessage;
259			return false;
260		}
261
262		for (int ndx = 0; ndx < numRefValues; ++ndx)
263			if (result == refValues[ndx])
264				return true;
265
266		gl.getLog() << tcu::TestLog::Message << "Error: got " << result << ", (" << glu::getPixelFormatStr(result) << ")" << tcu::TestLog::EndMessage;
267		return false;
268	}
269	else if (type == VERIFIER_FLOAT)
270	{
271		gls::StateQueryUtil::StateQueryMemoryWriteGuard<float> result;
272
273		gl.glGetTexLevelParameterfv(target, level, pname, &result);
274		GLU_EXPECT_NO_ERROR(gl.glGetError(), "glGetTexLevelParameterfv");
275
276		if (result.isUndefined())
277		{
278			gl.getLog() << tcu::TestLog::Message << "Error: Get* did not write a value." << tcu::TestLog::EndMessage;
279			return false;
280		}
281		else if (result.isMemoryContaminated())
282		{
283			gl.getLog() << tcu::TestLog::Message << "Error: detected illegal memory write." << tcu::TestLog::EndMessage;
284			return false;
285		}
286
287		for (int ndx = 0; ndx < numRefValues; ++ndx)
288			if (result == (float)refValues[ndx])
289				return true;
290
291		gl.getLog() << tcu::TestLog::Message << "Error: got " << result << ", (" << glu::getPixelFormatStr((int)result) << ")" << tcu::TestLog::EndMessage;
292		return false;
293	}
294
295	DE_ASSERT(DE_FALSE);
296	return false;
297
298}
299
300static void generateColorTextureGenerationGroup (std::vector<TextureGenerationSpec>& group, int max2DSamples, int max2DArraySamples, glw::GLenum internalFormat)
301{
302	// initial setups
303	static const struct InitialSetup
304	{
305		glw::GLenum	bindTarget;
306		glw::GLenum	queryTarget;
307		bool		immutable;
308		const char*	description;
309	} initialSetups[] =
310	{
311		{ GL_TEXTURE_2D,					GL_TEXTURE_2D,					true,	"GL_TEXTURE_2D, initial values"						},
312		{ GL_TEXTURE_3D,					GL_TEXTURE_3D,					true,	"GL_TEXTURE_3D, initial values"						},
313		{ GL_TEXTURE_2D_ARRAY,				GL_TEXTURE_2D_ARRAY,			true,	"GL_TEXTURE_2D_ARRAY, initial values"				},
314		{ GL_TEXTURE_CUBE_MAP,				GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,	true,	"GL_TEXTURE_CUBE_MAP, initial values"				},
315		{ GL_TEXTURE_2D_MULTISAMPLE,		GL_TEXTURE_2D_MULTISAMPLE,		true,	"GL_TEXTURE_2D_MULTISAMPLE, initial values"			},
316		{ GL_TEXTURE_2D_MULTISAMPLE_ARRAY,	GL_TEXTURE_2D_MULTISAMPLE_ARRAY,true,	"GL_TEXTURE_2D_MULTISAMPLE_ARRAY, initial values"	},
317	};
318
319	// multisample setups
320	static const struct MultisampleSetup
321	{
322		glw::GLenum	bindTarget;
323		int			sampleCount;
324		const char*	description;
325	} msSetups[] =
326	{
327		{ GL_TEXTURE_2D_MULTISAMPLE,		1,					"immutable GL_TEXTURE_2D_MULTISAMPLE, low sample count"			},
328		{ GL_TEXTURE_2D_MULTISAMPLE,		max2DSamples,		"immutable GL_TEXTURE_2D_MULTISAMPLE, max sample count"			},
329		{ GL_TEXTURE_2D_MULTISAMPLE_ARRAY,	1,					"immutable GL_TEXTURE_2D_MULTISAMPLE_ARRAY, low sample count"	},
330		{ GL_TEXTURE_2D_MULTISAMPLE_ARRAY,	max2DArraySamples,	"immutable GL_TEXTURE_2D_MULTISAMPLE_ARRAY, max sample count"	},
331	};
332
333	// normal setups
334	static const struct NormalSetup
335	{
336		glw::GLenum	bindTarget;
337		glw::GLenum	queryTarget;
338		bool		immutable;
339		int			level;
340		const char*	description;
341	} normalSetups[] =
342	{
343		{ GL_TEXTURE_2D,					GL_TEXTURE_2D,					true,	0,	"immutable GL_TEXTURE_2D"					},
344		{ GL_TEXTURE_3D,					GL_TEXTURE_3D,					true,	0,	"immutable GL_TEXTURE_3D"					},
345		{ GL_TEXTURE_2D_ARRAY,				GL_TEXTURE_2D_ARRAY,			true,	0,	"immutable GL_TEXTURE_2D_ARRAY"				},
346		{ GL_TEXTURE_CUBE_MAP,				GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,	true,	0,	"immutable GL_TEXTURE_CUBE_MAP"				},
347		{ GL_TEXTURE_2D,					GL_TEXTURE_2D,					false,	0,	"mutable GL_TEXTURE_2D"						},
348		{ GL_TEXTURE_3D,					GL_TEXTURE_3D,					false,	0,	"mutable GL_TEXTURE_3D"						},
349		{ GL_TEXTURE_2D_ARRAY,				GL_TEXTURE_2D_ARRAY,			false,	0,	"mutable GL_TEXTURE_2D_ARRAY"				},
350		{ GL_TEXTURE_CUBE_MAP,				GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,	false,	0,	"mutable GL_TEXTURE_CUBE_MAP"				},
351		{ GL_TEXTURE_2D,					GL_TEXTURE_2D,					false,	3,	"mutable GL_TEXTURE_2D, mip level 3"		},
352		{ GL_TEXTURE_3D,					GL_TEXTURE_3D,					false,	3,	"mutable GL_TEXTURE_3D, mip level 3"		},
353		{ GL_TEXTURE_2D_ARRAY,				GL_TEXTURE_2D_ARRAY,			false,	3,	"mutable GL_TEXTURE_2D_ARRAY, mip level 3"	},
354		{ GL_TEXTURE_CUBE_MAP,				GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,	false,	3,	"mutable GL_TEXTURE_CUBE_MAP, mip level 3"	},
355	};
356
357	for (int initialSetupNdx = 0; initialSetupNdx < DE_LENGTH_OF_ARRAY(initialSetups); ++initialSetupNdx)
358	{
359		TextureGenerationSpec texGen;
360		texGen.bindTarget		= initialSetups[initialSetupNdx].bindTarget;
361		texGen.queryTarget		= initialSetups[initialSetupNdx].queryTarget;
362		texGen.immutable		= initialSetups[initialSetupNdx].immutable;
363		texGen.sampleCount		= 0;
364		texGen.description		= initialSetups[initialSetupNdx].description;
365
366		group.push_back(texGen);
367	}
368
369	for (int msSetupNdx = 0; msSetupNdx < DE_LENGTH_OF_ARRAY(msSetups); ++msSetupNdx)
370	{
371		TextureGenerationSpec					texGen;
372		TextureGenerationSpec::TextureLevelSpec	level;
373
374		texGen.bindTarget		= msSetups[msSetupNdx].bindTarget;
375		texGen.queryTarget		= msSetups[msSetupNdx].bindTarget;
376		texGen.immutable		= true;
377		texGen.sampleCount		= msSetups[msSetupNdx].sampleCount;
378		texGen.fixedSamplePos	= false;
379		texGen.description		= msSetups[msSetupNdx].description;
380
381		level.width				= 32;
382		level.height			= 32;
383		level.depth				= (textureTypeHasDepth(texGen.bindTarget)) ? (8) : (0);
384		level.level				= 0;
385		level.internalFormat	= internalFormat;
386		level.compressed		= false;
387
388		texGen.levels.push_back(level);
389		group.push_back(texGen);
390	}
391
392	for (int normalSetupNdx = 0; normalSetupNdx < DE_LENGTH_OF_ARRAY(normalSetups); ++normalSetupNdx)
393	{
394		TextureGenerationSpec					texGen;
395		TextureGenerationSpec::TextureLevelSpec	level;
396
397		texGen.bindTarget		= normalSetups[normalSetupNdx].bindTarget;
398		texGen.queryTarget		= normalSetups[normalSetupNdx].queryTarget;
399		texGen.immutable		= normalSetups[normalSetupNdx].immutable;
400		texGen.sampleCount		= 0;
401		texGen.description		= normalSetups[normalSetupNdx].description;
402
403		level.width				= 32;
404		level.height			= 32;
405		level.depth				= (textureTypeHasDepth(texGen.bindTarget)) ? (8) : (0);
406		level.level				= normalSetups[normalSetupNdx].level;
407		level.internalFormat	= internalFormat;
408		level.compressed		= false;
409
410		texGen.levels.push_back(level);
411		group.push_back(texGen);
412	}
413}
414
415static void generateColorMultisampleTextureGenerationGroup (std::vector<TextureGenerationSpec>& group, int max2DSamples, int max2DArraySamples, glw::GLenum internalFormat)
416{
417	// multisample setups
418	static const struct MultisampleSetup
419	{
420		glw::GLenum	bindTarget;
421		bool		initialized;
422		int			sampleCount;
423		bool		fixedSamples;
424		const char*	description;
425	} msSetups[] =
426	{
427		{ GL_TEXTURE_2D_MULTISAMPLE,		false,	0,					false,	"GL_TEXTURE_2D_MULTISAMPLE, initial values"					},
428		{ GL_TEXTURE_2D_MULTISAMPLE,		true,	1,					false,	"GL_TEXTURE_2D_MULTISAMPLE, low sample count"				},
429		{ GL_TEXTURE_2D_MULTISAMPLE,		true,	max2DSamples,		false,	"GL_TEXTURE_2D_MULTISAMPLE, max sample count"				},
430		{ GL_TEXTURE_2D_MULTISAMPLE,		true,	max2DSamples,		true,	"GL_TEXTURE_2D_MULTISAMPLE, fixed sample positions"			},
431		{ GL_TEXTURE_2D_MULTISAMPLE_ARRAY,	false,	0,					false,	"GL_TEXTURE_2D_MULTISAMPLE_ARRAY, initial values"			},
432		{ GL_TEXTURE_2D_MULTISAMPLE_ARRAY,	true,	1,					false,	"GL_TEXTURE_2D_MULTISAMPLE_ARRAY, low sample count"			},
433		{ GL_TEXTURE_2D_MULTISAMPLE_ARRAY,	true,	max2DArraySamples,	false,	"GL_TEXTURE_2D_MULTISAMPLE_ARRAY, max sample count"			},
434		{ GL_TEXTURE_2D_MULTISAMPLE_ARRAY,	true,	max2DArraySamples,	true,	"GL_TEXTURE_2D_MULTISAMPLE_ARRAY, fixed sample positions"	},
435	};
436
437	for (int msSetupNdx = 0; msSetupNdx < DE_LENGTH_OF_ARRAY(msSetups); ++msSetupNdx)
438	{
439		TextureGenerationSpec texGen;
440
441		texGen.bindTarget		= msSetups[msSetupNdx].bindTarget;
442		texGen.queryTarget		= msSetups[msSetupNdx].bindTarget;
443		texGen.immutable		= true;
444		texGen.sampleCount		= msSetups[msSetupNdx].sampleCount;
445		texGen.fixedSamplePos	= msSetups[msSetupNdx].fixedSamples;
446		texGen.description		= msSetups[msSetupNdx].description;
447
448		if (msSetups[msSetupNdx].initialized)
449		{
450			TextureGenerationSpec::TextureLevelSpec	level;
451			level.width				= 32;
452			level.height			= 32;
453			level.depth				= (textureTypeHasDepth(texGen.bindTarget)) ? (8) : (0);
454			level.level				= 0;
455			level.internalFormat	= internalFormat;
456			level.compressed		= false;
457
458			texGen.levels.push_back(level);
459		}
460
461		group.push_back(texGen);
462	}
463}
464
465static void generateInternalFormatTextureGenerationGroup (std::vector<TextureGenerationSpec>& group)
466{
467	// initial setups
468	static const struct InitialSetup
469	{
470		glw::GLenum	bindTarget;
471		glw::GLenum	queryTarget;
472		bool		immutable;
473		const char*	description;
474	} initialSetups[] =
475	{
476		{ GL_TEXTURE_2D,					GL_TEXTURE_2D,					true,	"GL_TEXTURE_2D, initial values"						},
477		{ GL_TEXTURE_3D,					GL_TEXTURE_3D,					true,	"GL_TEXTURE_3D, initial values"						},
478		{ GL_TEXTURE_2D_ARRAY,				GL_TEXTURE_2D_ARRAY,			true,	"GL_TEXTURE_2D_ARRAY, initial values"				},
479		{ GL_TEXTURE_CUBE_MAP,				GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,	true,	"GL_TEXTURE_CUBE_MAP, initial values"				},
480		{ GL_TEXTURE_2D_MULTISAMPLE,		GL_TEXTURE_2D_MULTISAMPLE,		true,	"GL_TEXTURE_2D_MULTISAMPLE, initial values"			},
481		{ GL_TEXTURE_2D_MULTISAMPLE_ARRAY,	GL_TEXTURE_2D_MULTISAMPLE_ARRAY,true,	"GL_TEXTURE_2D_MULTISAMPLE_ARRAY, initial values"	},
482	};
483
484	// Renderable internal formats (subset)
485	static const glw::GLenum renderableInternalFormats[] =
486	{
487		GL_R8, GL_RGB565, GL_RGB5_A1, GL_RGB10_A2UI, GL_SRGB8_ALPHA8, GL_RG32I,
488		GL_RGBA16UI, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT24,
489		GL_DEPTH_COMPONENT32F, GL_DEPTH24_STENCIL8, GL_DEPTH32F_STENCIL8
490	};
491
492	// Internal formats
493	static const glw::GLenum internalFormats[] =
494	{
495		GL_R8, GL_R8_SNORM, GL_RG8, GL_RG8_SNORM, GL_RGB8, GL_RGB8_SNORM, GL_RGB565, GL_RGBA4, GL_RGB5_A1,
496		GL_RGBA8, GL_RGBA8_SNORM, GL_RGB10_A2, GL_RGB10_A2UI, GL_SRGB8, GL_SRGB8_ALPHA8, GL_R16F, GL_RG16F,
497		GL_RGB16F, GL_RGBA16F, GL_R32F, GL_RG32F, GL_RGB32F, GL_RGBA32F, GL_R11F_G11F_B10F, GL_RGB9_E5, GL_R8I,
498		GL_R8UI, GL_R16I, GL_R16UI, GL_R32I, GL_R32UI, GL_RG8I, GL_RG8UI, GL_RG16I, GL_RG16UI, GL_RG32I, GL_RG32UI,
499		GL_RGB8I, GL_RGB8UI, GL_RGB16I, GL_RGB16UI, GL_RGB32I, GL_RGB32UI, GL_RGBA8I, GL_RGBA8UI, GL_RGBA16I,
500		GL_RGBA16UI, GL_RGBA32I, GL_RGBA32UI,
501
502		GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT16,
503		GL_DEPTH32F_STENCIL8, GL_DEPTH24_STENCIL8
504	};
505
506	for (int initialSetupNdx = 0; initialSetupNdx < DE_LENGTH_OF_ARRAY(initialSetups); ++initialSetupNdx)
507	{
508		TextureGenerationSpec texGen;
509		texGen.bindTarget		= initialSetups[initialSetupNdx].bindTarget;
510		texGen.queryTarget		= initialSetups[initialSetupNdx].queryTarget;
511		texGen.immutable		= initialSetups[initialSetupNdx].immutable;
512		texGen.sampleCount		= 0;
513		texGen.description		= initialSetups[initialSetupNdx].description;
514
515		group.push_back(texGen);
516	}
517
518	// test some color/stencil/depth renderable with multisample texture2d
519	for (int internalFormatNdx = 0; internalFormatNdx < DE_LENGTH_OF_ARRAY(renderableInternalFormats); ++internalFormatNdx)
520	{
521		TextureGenerationSpec					texGen;
522		TextureGenerationSpec::TextureLevelSpec	level;
523
524		texGen.bindTarget		= GL_TEXTURE_2D_MULTISAMPLE;
525		texGen.queryTarget		= GL_TEXTURE_2D_MULTISAMPLE;
526		texGen.immutable		= true;
527		texGen.sampleCount		= 1;
528		texGen.fixedSamplePos	= false;
529		texGen.description		= std::string() + "GL_TEXTURE_2D_MULTISAMPLE, internal format " + glu::getPixelFormatName(renderableInternalFormats[internalFormatNdx]);
530
531		level.width				= 32;
532		level.height			= 32;
533		level.depth				= 0;
534		level.level				= 0;
535		level.internalFormat	= renderableInternalFormats[internalFormatNdx];
536		level.compressed		= false;
537
538		texGen.levels.push_back(level);
539		group.push_back(texGen);
540	}
541
542	// test all with texture2d
543	for (int internalFormatNdx = 0; internalFormatNdx < DE_LENGTH_OF_ARRAY(internalFormats); ++internalFormatNdx)
544	{
545		TextureGenerationSpec					texGen;
546		TextureGenerationSpec::TextureLevelSpec	level;
547
548		texGen.bindTarget		= GL_TEXTURE_2D;
549		texGen.queryTarget		= GL_TEXTURE_2D;
550		texGen.immutable		= true;
551		texGen.sampleCount		= 0;
552		texGen.description		= std::string() + "GL_TEXTURE_2D, internal format " + glu::getPixelFormatName(internalFormats[internalFormatNdx]);
553
554		level.width				= 32;
555		level.height			= 32;
556		level.depth				= 0;
557		level.level				= 0;
558		level.internalFormat	= internalFormats[internalFormatNdx];
559		level.compressed		= false;
560
561		texGen.levels.push_back(level);
562		group.push_back(texGen);
563	}
564
565	// test rgba8 with mip level 3
566	{
567		TextureGenerationSpec					texGen;
568		TextureGenerationSpec::TextureLevelSpec	level;
569
570		texGen.bindTarget		= GL_TEXTURE_2D;
571		texGen.queryTarget		= GL_TEXTURE_2D;
572		texGen.immutable		= false;
573		texGen.sampleCount		= 0;
574		texGen.description		= std::string() + "GL_TEXTURE_2D, internal format GL_RGBA8";
575
576		level.width				= 32;
577		level.height			= 32;
578		level.depth				= 0;
579		level.level				= 3;
580		level.internalFormat	= GL_RGBA8;
581		level.compressed		= false;
582
583		texGen.levels.push_back(level);
584		group.push_back(texGen);
585	}
586}
587
588static void generateCompressedTextureGenerationGroup (std::vector<TextureGenerationSpec>& group)
589{
590	// initial ms
591	{
592		TextureGenerationSpec texGen;
593		texGen.bindTarget	= GL_TEXTURE_2D_MULTISAMPLE;
594		texGen.queryTarget	= GL_TEXTURE_2D_MULTISAMPLE;
595		texGen.immutable	= true;
596		texGen.sampleCount	= 0;
597		texGen.description	= "GL_TEXTURE_2D_MULTISAMPLE, initial values";
598
599		group.push_back(texGen);
600	}
601
602	// initial non-ms
603	{
604		TextureGenerationSpec texGen;
605		texGen.bindTarget	= GL_TEXTURE_2D;
606		texGen.queryTarget	= GL_TEXTURE_2D;
607		texGen.immutable	= true;
608		texGen.sampleCount	= 0;
609		texGen.description	= "GL_TEXTURE_2D, initial values";
610
611		group.push_back(texGen);
612	}
613
614	// compressed
615	{
616		TextureGenerationSpec					texGen;
617		TextureGenerationSpec::TextureLevelSpec	level;
618
619		texGen.bindTarget		= GL_TEXTURE_2D;
620		texGen.queryTarget		= GL_TEXTURE_2D;
621		texGen.immutable		= false;
622		texGen.sampleCount		= 0;
623		texGen.description		= "GL_TEXTURE_2D, compressed";
624
625		level.width				= 32;
626		level.height			= 32;
627		level.depth				= 0;
628		level.level				= 0;
629		level.internalFormat	= GL_COMPRESSED_RGB8_ETC2;
630		level.compressed		= true;
631
632		texGen.levels.push_back(level);
633		group.push_back(texGen);
634	}
635}
636
637void applyTextureGenergationSpec (glu::CallLogWrapper& gl, const TextureGenerationSpec& spec)
638{
639	DE_ASSERT(!(spec.immutable && spec.levels.size() > 1));		// !< immutable textures have only one level
640
641	for (int levelNdx = 0; levelNdx < (int)spec.levels.size(); ++levelNdx)
642	{
643		const glu::TransferFormat transferFormat = (spec.levels[levelNdx].compressed) ? (glu::TransferFormat()) : (glu::getTransferFormat(glu::mapGLInternalFormat(spec.levels[levelNdx].internalFormat)));
644
645		if (spec.immutable && !spec.levels[levelNdx].compressed && spec.bindTarget == GL_TEXTURE_2D)
646			gl.glTexStorage2D(spec.bindTarget, 1, spec.levels[levelNdx].internalFormat, spec.levels[levelNdx].width, spec.levels[levelNdx].height);
647		else if (spec.immutable && !spec.levels[levelNdx].compressed && spec.bindTarget == GL_TEXTURE_3D)
648			gl.glTexStorage3D(spec.bindTarget, 1, spec.levels[levelNdx].internalFormat, spec.levels[levelNdx].width, spec.levels[levelNdx].height, spec.levels[levelNdx].depth);
649		else if (spec.immutable && !spec.levels[levelNdx].compressed && spec.bindTarget == GL_TEXTURE_2D_ARRAY)
650			gl.glTexStorage3D(spec.bindTarget, 1, spec.levels[levelNdx].internalFormat, spec.levels[levelNdx].width, spec.levels[levelNdx].height, spec.levels[levelNdx].depth);
651		else if (spec.immutable && !spec.levels[levelNdx].compressed && spec.bindTarget == GL_TEXTURE_CUBE_MAP)
652			gl.glTexStorage2D(spec.bindTarget, 1, spec.levels[levelNdx].internalFormat, spec.levels[levelNdx].width, spec.levels[levelNdx].height);
653		else if (spec.immutable && !spec.levels[levelNdx].compressed && spec.bindTarget == GL_TEXTURE_2D_MULTISAMPLE)
654			gl.glTexStorage2DMultisample(spec.bindTarget, spec.sampleCount, spec.levels[levelNdx].internalFormat, spec.levels[levelNdx].width, spec.levels[levelNdx].height, (spec.fixedSamplePos) ? (GL_TRUE) : (GL_FALSE));
655		else if (spec.immutable && !spec.levels[levelNdx].compressed && spec.bindTarget == GL_TEXTURE_2D_MULTISAMPLE_ARRAY)
656			gl.glTexStorage3DMultisample(spec.bindTarget, spec.sampleCount, spec.levels[levelNdx].internalFormat, spec.levels[levelNdx].width, spec.levels[levelNdx].height, spec.levels[levelNdx].depth, (spec.fixedSamplePos) ? (GL_TRUE) : (GL_FALSE));
657		else if (!spec.immutable && !spec.levels[levelNdx].compressed && spec.bindTarget == GL_TEXTURE_2D)
658			gl.glTexImage2D(spec.bindTarget, spec.levels[levelNdx].level, spec.levels[levelNdx].internalFormat, spec.levels[levelNdx].width, spec.levels[levelNdx].height, 0, transferFormat.format, transferFormat.dataType, DE_NULL);
659		else if (!spec.immutable && !spec.levels[levelNdx].compressed && spec.bindTarget == GL_TEXTURE_3D)
660			gl.glTexImage3D(spec.bindTarget, spec.levels[levelNdx].level, spec.levels[levelNdx].internalFormat, spec.levels[levelNdx].width, spec.levels[levelNdx].height, spec.levels[levelNdx].depth, 0, transferFormat.format, transferFormat.dataType, DE_NULL);
661		else if (!spec.immutable && !spec.levels[levelNdx].compressed && spec.bindTarget == GL_TEXTURE_2D_ARRAY)
662			gl.glTexImage3D(spec.bindTarget, spec.levels[levelNdx].level, spec.levels[levelNdx].internalFormat, spec.levels[levelNdx].width, spec.levels[levelNdx].height, spec.levels[levelNdx].depth, 0, transferFormat.format, transferFormat.dataType, DE_NULL);
663		else if (!spec.immutable && !spec.levels[levelNdx].compressed && spec.bindTarget == GL_TEXTURE_CUBE_MAP)
664			gl.glTexImage2D(spec.queryTarget, spec.levels[levelNdx].level, spec.levels[levelNdx].internalFormat, spec.levels[levelNdx].width, spec.levels[levelNdx].height, 0, transferFormat.format, transferFormat.dataType, DE_NULL);
665		else if (!spec.immutable && spec.levels[levelNdx].compressed && spec.bindTarget == GL_TEXTURE_2D)
666		{
667			DE_ASSERT(spec.levels[levelNdx].width == 32);
668			DE_ASSERT(spec.levels[levelNdx].height == 32);
669			DE_ASSERT(spec.levels[levelNdx].internalFormat == GL_COMPRESSED_RGB8_ETC2);
670
671			static const deUint8 buffer[64 * 8] = { 0 };
672			gl.glCompressedTexImage2D(spec.bindTarget, spec.levels[levelNdx].level, spec.levels[levelNdx].internalFormat, spec.levels[levelNdx].width, spec.levels[levelNdx].height, 0, sizeof(buffer), buffer);
673		}
674		else
675			DE_ASSERT(DE_FALSE);
676
677		GLU_EXPECT_NO_ERROR(gl.glGetError(), "set level");
678	}
679}
680
681class TextureLevelCase : public TestCase
682{
683public:
684										TextureLevelCase		(Context& ctx, const char* name, const char* desc, VerifierType type);
685										~TextureLevelCase		(void);
686
687	void								init					(void);
688	void								deinit					(void);
689	IterateResult						iterate					(void);
690
691protected:
692	void								getFormatSamples		(glw::GLenum target, std::vector<int>& samples);
693	bool								testConfig				(const TextureGenerationSpec& spec);
694	virtual bool						checkTextureState		(glu::CallLogWrapper& gl, const TextureGenerationSpec& spec) = 0;
695	virtual void						generateTestIterations	(std::vector<TextureGenerationSpec>& iterations) = 0;
696
697	const VerifierType					m_type;
698	const glw::GLenum					m_internalFormat;
699	glw::GLuint							m_texture;
700
701private:
702	int									m_iteration;
703	std::vector<TextureGenerationSpec>	m_iterations;
704	bool								m_allIterationsOk;
705	std::vector<int>					m_failedIterations;
706};
707
708TextureLevelCase::TextureLevelCase (Context& ctx, const char* name, const char* desc, VerifierType type)
709	: TestCase			(ctx, name, desc)
710	, m_type			(type)
711	, m_internalFormat	(GL_RGBA8)
712	, m_texture			(0)
713	, m_iteration		(0)
714	, m_allIterationsOk	(true)
715{
716}
717
718TextureLevelCase::~TextureLevelCase (void)
719{
720	deinit();
721}
722
723void TextureLevelCase::init (void)
724{
725	generateTestIterations(m_iterations);
726}
727
728void TextureLevelCase::deinit (void)
729{
730	if (m_texture)
731	{
732		m_context.getRenderContext().getFunctions().deleteTextures(1, &m_texture);
733		m_texture = 0;
734	}
735}
736
737void TextureLevelCase::getFormatSamples (glw::GLenum target, std::vector<int>& samples)
738{
739	const glw::Functions	gl			= m_context.getRenderContext().getFunctions();
740	int						sampleCount	= -1;
741
742	// fake values for unsupported queries to simplify code. The extension will be checked later for each config anyway (in testConfig())
743	if (target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY && !m_context.getContextInfo().isExtensionSupported("GL_OES_texture_storage_multisample_2d_array"))
744	{
745		samples.resize(1);
746		samples[0] = 0;
747		return;
748	}
749
750	gl.getInternalformativ(target, m_internalFormat, GL_NUM_SAMPLE_COUNTS, 1, &sampleCount);
751
752	if (sampleCount < 0)
753		throw tcu::TestError("internal format query failed");
754
755	samples.resize(sampleCount);
756
757	if (sampleCount > 0)
758	{
759		gl.getInternalformativ(target, m_internalFormat, GL_SAMPLES, sampleCount, &samples[0]);
760		GLU_EXPECT_NO_ERROR(gl.getError(), "get max samples");
761	}
762}
763
764TextureLevelCase::IterateResult TextureLevelCase::iterate (void)
765{
766	const bool result = testConfig(m_iterations[m_iteration]);
767
768	if (!result)
769	{
770		m_failedIterations.push_back(m_iteration);
771		m_allIterationsOk = false;
772	}
773
774	if (++m_iteration < (int)m_iterations.size())
775		return CONTINUE;
776
777	if (m_allIterationsOk)
778		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
779	else
780	{
781		tcu::MessageBuilder msg(&m_testCtx.getLog());
782
783		msg << "Following iteration(s) failed: ";
784		for (int ndx = 0; ndx < (int)m_failedIterations.size(); ++ndx)
785		{
786			if (ndx)
787				msg << ", ";
788			msg << (m_failedIterations[ndx] + 1);
789		}
790		msg << tcu::TestLog::EndMessage;
791
792		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "One or more iterations failed");
793	}
794	return STOP;
795}
796
797bool TextureLevelCase::testConfig (const TextureGenerationSpec& spec)
798{
799	const tcu::ScopedLogSection section(m_testCtx.getLog(), "Iteration", std::string() + "Iteration " + de::toString(m_iteration+1) + "/" + de::toString((int)m_iterations.size()) + " - " + spec.description);
800	glu::CallLogWrapper			gl		(m_context.getRenderContext().getFunctions(), m_testCtx.getLog());
801	bool						result;
802
803	// skip unsupported targets
804
805	if (spec.bindTarget == GL_TEXTURE_2D_MULTISAMPLE_ARRAY && !m_context.getContextInfo().isExtensionSupported("GL_OES_texture_storage_multisample_2d_array"))
806	{
807		m_testCtx.getLog() << tcu::TestLog::Message << "Target binding requires GL_OES_texture_storage_multisample_2d_array extension, skipping." << tcu::TestLog::EndMessage;
808		return true;
809	}
810
811	// test supported targets
812
813	gl.enableLogging(true);
814
815	gl.glGenTextures(1, &m_texture);
816	gl.glBindTexture(spec.bindTarget, m_texture);
817	GLU_EXPECT_NO_ERROR(gl.glGetError(), "gen tex");
818
819	// Set the state
820	applyTextureGenergationSpec(gl, spec);
821
822	// Verify the state
823	result = checkTextureState(gl, spec);
824
825	gl.glDeleteTextures(1, &m_texture);
826	m_texture = 0;
827
828	return result;
829}
830
831/*--------------------------------------------------------------------*//*!
832 * \brief Test all texture targets
833 *//*--------------------------------------------------------------------*/
834class TextureLevelCommonCase : public TextureLevelCase
835{
836public:
837					TextureLevelCommonCase	(Context& ctx, const char* name, const char* desc, VerifierType type);
838
839protected:
840	virtual void	generateTestIterations	(std::vector<TextureGenerationSpec>& iterations);
841};
842
843TextureLevelCommonCase::TextureLevelCommonCase (Context& ctx, const char* name, const char* desc, VerifierType type)
844	: TextureLevelCase(ctx, name, desc, type)
845{
846}
847
848void TextureLevelCommonCase::generateTestIterations (std::vector<TextureGenerationSpec>& iterations)
849{
850	std::vector<int> texture2DSamples;
851	std::vector<int> texture2DArraySamples;
852
853	getFormatSamples(GL_TEXTURE_2D_MULTISAMPLE, texture2DSamples);
854	getFormatSamples(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, texture2DArraySamples);
855
856	TCU_CHECK(!texture2DSamples.empty());
857	TCU_CHECK(!texture2DArraySamples.empty());
858
859	// gen iterations
860
861	generateColorTextureGenerationGroup(iterations, texture2DSamples[0], texture2DArraySamples[0], m_internalFormat);
862}
863
864/*--------------------------------------------------------------------*//*!
865 * \brief Test all multisample texture targets
866 *//*--------------------------------------------------------------------*/
867class TextureLevelMultisampleCase : public TextureLevelCase
868{
869public:
870					TextureLevelMultisampleCase	(Context& ctx, const char* name, const char* desc, VerifierType type);
871
872protected:
873	virtual void	generateTestIterations		(std::vector<TextureGenerationSpec>& iterations);
874};
875
876TextureLevelMultisampleCase::TextureLevelMultisampleCase (Context& ctx, const char* name, const char* desc, VerifierType type)
877	: TextureLevelCase(ctx, name, desc, type)
878{
879}
880
881void TextureLevelMultisampleCase::generateTestIterations (std::vector<TextureGenerationSpec>& iterations)
882{
883	std::vector<int> texture2DSamples;
884	std::vector<int> texture2DArraySamples;
885
886	getFormatSamples(GL_TEXTURE_2D_MULTISAMPLE, texture2DSamples);
887	getFormatSamples(GL_TEXTURE_2D_MULTISAMPLE_ARRAY, texture2DArraySamples);
888
889	TCU_CHECK(!texture2DSamples.empty());
890	TCU_CHECK(!texture2DArraySamples.empty());
891
892	// gen iterations
893
894	generateColorMultisampleTextureGenerationGroup(iterations, texture2DSamples[0], texture2DArraySamples[0], m_internalFormat);
895}
896
897class TextureLevelSampleCase : public TextureLevelMultisampleCase
898{
899public:
900	TextureLevelSampleCase (Context& ctx, const char* name, const char* desc, VerifierType type)
901		: TextureLevelMultisampleCase(ctx, name, desc, type)
902	{
903	}
904
905private:
906	bool checkTextureState (glu::CallLogWrapper& gl, const TextureGenerationSpec& spec)
907	{
908		const int queryLevel	= (spec.levels.empty()) ? (0) : (spec.levels[0].level);
909		const int refValue		= (spec.levels.empty()) ? (0) : (spec.sampleCount);
910
911		return verifyTextureLevelParameterGreaterOrEqual(gl, spec.queryTarget, queryLevel, GL_TEXTURE_SAMPLES, refValue, m_type);
912	}
913};
914
915class TextureLevelFixedSamplesCase : public TextureLevelMultisampleCase
916{
917public:
918	TextureLevelFixedSamplesCase (Context& ctx, const char* name, const char* desc, VerifierType type)
919		: TextureLevelMultisampleCase(ctx, name, desc, type)
920	{
921	}
922
923private:
924	bool checkTextureState (glu::CallLogWrapper& gl, const TextureGenerationSpec& spec)
925	{
926		const int queryLevel	= 0;
927		const int refValue		= (spec.levels.empty()) ? (1) : ((spec.fixedSamplePos) ? (1) : (0));
928
929		return verifyTextureLevelParameterEqual(gl, spec.queryTarget, queryLevel, GL_TEXTURE_FIXED_SAMPLE_LOCATIONS, refValue, m_type);
930	}
931};
932
933class TextureLevelWidthCase : public TextureLevelCommonCase
934{
935public:
936	TextureLevelWidthCase (Context& ctx, const char* name, const char* desc, VerifierType type)
937		: TextureLevelCommonCase(ctx, name, desc, type)
938	{
939	}
940
941private:
942	bool checkTextureState (glu::CallLogWrapper& gl, const TextureGenerationSpec& spec)
943	{
944		const int	initialValue	= 0;
945		bool		allOk			= true;
946
947		if (spec.levels.empty())
948		{
949			const int queryLevel	= 0;
950			const int refValue		= initialValue;
951
952			allOk &= verifyTextureLevelParameterEqual(gl, spec.queryTarget, queryLevel, GL_TEXTURE_WIDTH, refValue, m_type);
953		}
954		else
955		{
956			for (int levelNdx = 0; levelNdx < (int)spec.levels.size(); ++levelNdx)
957			{
958				const int queryLevel	= spec.levels[levelNdx].level;
959				const int refValue		= spec.levels[levelNdx].width;
960
961				allOk &= verifyTextureLevelParameterEqual(gl, spec.queryTarget, queryLevel, GL_TEXTURE_WIDTH, refValue, m_type);
962			}
963		}
964
965		return allOk;
966	}
967};
968
969class TextureLevelHeightCase : public TextureLevelCommonCase
970{
971public:
972	TextureLevelHeightCase (Context& ctx, const char* name, const char* desc, VerifierType type)
973		: TextureLevelCommonCase(ctx, name, desc, type)
974	{
975	}
976
977private:
978	bool checkTextureState (glu::CallLogWrapper& gl, const TextureGenerationSpec& spec)
979	{
980		const int	initialValue	= 0;
981		bool		allOk			= true;
982
983		if (spec.levels.empty())
984		{
985			const int queryLevel	= 0;
986			const int refValue		= initialValue;
987
988			allOk &= verifyTextureLevelParameterEqual(gl, spec.queryTarget, queryLevel, GL_TEXTURE_HEIGHT, refValue, m_type);
989		}
990		else
991		{
992			for (int levelNdx = 0; levelNdx < (int)spec.levels.size(); ++levelNdx)
993			{
994				const int queryLevel	= spec.levels[levelNdx].level;
995				const int refValue		= spec.levels[levelNdx].height;
996
997				allOk &= verifyTextureLevelParameterEqual(gl, spec.queryTarget, queryLevel, GL_TEXTURE_HEIGHT, refValue, m_type);
998			}
999		}
1000
1001		return allOk;
1002	}
1003};
1004
1005class TextureLevelDepthCase : public TextureLevelCommonCase
1006{
1007public:
1008	TextureLevelDepthCase (Context& ctx, const char* name, const char* desc, VerifierType type)
1009		: TextureLevelCommonCase(ctx, name, desc, type)
1010	{
1011	}
1012
1013private:
1014
1015	void generateTestIterations (std::vector<TextureGenerationSpec>& iterations)
1016	{
1017		std::vector<TextureGenerationSpec> allIterations;
1018		this->TextureLevelCommonCase::generateTestIterations(allIterations);
1019
1020		// test only cases with depth
1021		for (int ndx = 0; ndx < (int)allIterations.size(); ++ndx)
1022			if (textureTypeHasDepth(allIterations[ndx].bindTarget))
1023				iterations.push_back(allIterations[ndx]);
1024	}
1025
1026	bool checkTextureState (glu::CallLogWrapper& gl, const TextureGenerationSpec& spec)
1027	{
1028		const int	initialValue	= 0;
1029		bool		allOk			= true;
1030
1031		if (spec.levels.empty())
1032		{
1033			const int queryLevel	= 0;
1034			const int refValue		= initialValue;
1035
1036			allOk &= verifyTextureLevelParameterEqual(gl, spec.queryTarget, queryLevel, GL_TEXTURE_DEPTH, refValue, m_type);
1037		}
1038		else
1039		{
1040			for (int levelNdx = 0; levelNdx < (int)spec.levels.size(); ++levelNdx)
1041			{
1042				const int queryLevel	= spec.levels[levelNdx].level;
1043				const int refValue		= spec.levels[levelNdx].depth;
1044
1045				allOk &= verifyTextureLevelParameterEqual(gl, spec.queryTarget, queryLevel, GL_TEXTURE_DEPTH, refValue, m_type);
1046			}
1047		}
1048
1049		return allOk;
1050	}
1051};
1052
1053class TextureLevelInternalFormatCase : public TextureLevelCase
1054{
1055public:
1056	TextureLevelInternalFormatCase (Context& ctx, const char* name, const char* desc, VerifierType type)
1057		: TextureLevelCase(ctx, name, desc, type)
1058	{
1059	}
1060
1061private:
1062	void generateTestIterations (std::vector<TextureGenerationSpec>& iterations)
1063	{
1064		generateInternalFormatTextureGenerationGroup(iterations);
1065	}
1066
1067	bool checkTextureState (glu::CallLogWrapper& gl, const TextureGenerationSpec& spec)
1068	{
1069		bool allOk = true;
1070
1071		if (spec.levels.empty())
1072		{
1073			const int queryLevel		= 0;
1074			const int initialValues[2]	= { GL_RGBA, GL_R8 };
1075
1076			allOk &= verifyTextureLevelParameterInternalFormatAnyOf(gl, spec.queryTarget, queryLevel, GL_TEXTURE_INTERNAL_FORMAT, initialValues, DE_LENGTH_OF_ARRAY(initialValues), m_type);
1077		}
1078		else
1079		{
1080			for (int levelNdx = 0; levelNdx < (int)spec.levels.size(); ++levelNdx)
1081			{
1082				const int queryLevel	= spec.levels[levelNdx].level;
1083				const int refValue		= spec.levels[levelNdx].internalFormat;
1084
1085				allOk &= verifyTextureLevelParameterInternalFormatEqual(gl, spec.queryTarget, queryLevel, GL_TEXTURE_INTERNAL_FORMAT, refValue, m_type);
1086			}
1087		}
1088
1089		return allOk;
1090	}
1091};
1092
1093class TextureLevelSizeCase : public TextureLevelCase
1094{
1095public:
1096						TextureLevelSizeCase			(Context& ctx, const char* name, const char* desc, VerifierType type, glw::GLenum pname);
1097
1098private:
1099	void				generateTestIterations			(std::vector<TextureGenerationSpec>& iterations);
1100	bool				checkTextureState				(glu::CallLogWrapper& gl, const TextureGenerationSpec& spec);
1101	int					getMinimumComponentResolution	(glw::GLenum internalFormat);
1102
1103	const glw::GLenum	m_pname;
1104};
1105
1106TextureLevelSizeCase::TextureLevelSizeCase (Context& ctx, const char* name, const char* desc, VerifierType type, glw::GLenum pname)
1107	: TextureLevelCase	(ctx, name, desc, type)
1108	, m_pname			(pname)
1109{
1110}
1111
1112void TextureLevelSizeCase::generateTestIterations (std::vector<TextureGenerationSpec>& iterations)
1113{
1114	generateInternalFormatTextureGenerationGroup(iterations);
1115}
1116
1117bool TextureLevelSizeCase::checkTextureState (glu::CallLogWrapper& gl, const TextureGenerationSpec& spec)
1118{
1119	bool allOk = true;
1120
1121	if (spec.levels.empty())
1122	{
1123		allOk &= verifyTextureLevelParameterEqual(gl, spec.queryTarget, 0, m_pname, 0, m_type);
1124	}
1125	else
1126	{
1127		for (int levelNdx = 0; levelNdx < (int)spec.levels.size(); ++levelNdx)
1128		{
1129			const int queryLevel	= spec.levels[levelNdx].level;
1130			const int refValue		= getMinimumComponentResolution(spec.levels[levelNdx].internalFormat);
1131
1132			allOk &= verifyTextureLevelParameterGreaterOrEqual(gl, spec.queryTarget, queryLevel, m_pname, refValue, m_type);
1133		}
1134	}
1135
1136	return allOk;
1137}
1138
1139int TextureLevelSizeCase::getMinimumComponentResolution (glw::GLenum internalFormat)
1140{
1141	const tcu::TextureFormat	format			= glu::mapGLInternalFormat(internalFormat);
1142	const tcu::IVec4			channelBitDepth	= tcu::getTextureFormatBitDepth(format);
1143
1144	switch (m_pname)
1145	{
1146		case GL_TEXTURE_RED_SIZE:
1147			if (format.order == tcu::TextureFormat::R		||
1148				format.order == tcu::TextureFormat::RG		||
1149				format.order == tcu::TextureFormat::RGB		||
1150				format.order == tcu::TextureFormat::RGBA	||
1151				format.order == tcu::TextureFormat::BGRA	||
1152				format.order == tcu::TextureFormat::ARGB	||
1153				format.order == tcu::TextureFormat::sRGB	||
1154				format.order == tcu::TextureFormat::sRGBA)
1155				return channelBitDepth[0];
1156			else
1157				return 0;
1158
1159		case GL_TEXTURE_GREEN_SIZE:
1160			if (format.order == tcu::TextureFormat::RG		||
1161				format.order == tcu::TextureFormat::RGB		||
1162				format.order == tcu::TextureFormat::RGBA	||
1163				format.order == tcu::TextureFormat::BGRA	||
1164				format.order == tcu::TextureFormat::ARGB	||
1165				format.order == tcu::TextureFormat::sRGB	||
1166				format.order == tcu::TextureFormat::sRGBA)
1167				return channelBitDepth[1];
1168			else
1169				return 0;
1170
1171		case GL_TEXTURE_BLUE_SIZE:
1172			if (format.order == tcu::TextureFormat::RGB		||
1173				format.order == tcu::TextureFormat::RGBA	||
1174				format.order == tcu::TextureFormat::BGRA	||
1175				format.order == tcu::TextureFormat::ARGB	||
1176				format.order == tcu::TextureFormat::sRGB	||
1177				format.order == tcu::TextureFormat::sRGBA)
1178				return channelBitDepth[2];
1179			else
1180				return 0;
1181
1182		case GL_TEXTURE_ALPHA_SIZE:
1183			if (format.order == tcu::TextureFormat::RGBA	||
1184				format.order == tcu::TextureFormat::BGRA	||
1185				format.order == tcu::TextureFormat::ARGB	||
1186				format.order == tcu::TextureFormat::sRGBA)
1187				return channelBitDepth[3];
1188			else
1189				return 0;
1190
1191		case GL_TEXTURE_DEPTH_SIZE:
1192			if (format.order == tcu::TextureFormat::D	||
1193				format.order == tcu::TextureFormat::DS)
1194				return channelBitDepth[0];
1195			else
1196				return 0;
1197
1198		case GL_TEXTURE_STENCIL_SIZE:
1199			if (format.order == tcu::TextureFormat::DS)
1200				return channelBitDepth[3];
1201			else
1202				return 0;
1203
1204		case GL_TEXTURE_SHARED_SIZE:
1205			if (internalFormat == GL_RGB9_E5)
1206				return 5;
1207			else
1208				return 0;
1209		default:
1210			DE_ASSERT(DE_FALSE);
1211			return 0;
1212	}
1213}
1214
1215class TextureLevelTypeCase : public TextureLevelCase
1216{
1217public:
1218						TextureLevelTypeCase			(Context& ctx, const char* name, const char* desc, VerifierType type, glw::GLenum pname);
1219
1220private:
1221	void				generateTestIterations			(std::vector<TextureGenerationSpec>& iterations);
1222	bool				checkTextureState				(glu::CallLogWrapper& gl, const TextureGenerationSpec& spec);
1223	int					getComponentType				(glw::GLenum internalFormat);
1224
1225	const glw::GLenum	m_pname;
1226};
1227
1228TextureLevelTypeCase::TextureLevelTypeCase (Context& ctx, const char* name, const char* desc, VerifierType type, glw::GLenum pname)
1229	: TextureLevelCase	(ctx, name, desc, type)
1230	, m_pname			(pname)
1231{
1232}
1233
1234void TextureLevelTypeCase::generateTestIterations (std::vector<TextureGenerationSpec>& iterations)
1235{
1236	generateInternalFormatTextureGenerationGroup(iterations);
1237}
1238
1239bool TextureLevelTypeCase::checkTextureState (glu::CallLogWrapper& gl, const TextureGenerationSpec& spec)
1240{
1241	bool allOk = true;
1242
1243	if (spec.levels.empty())
1244	{
1245		allOk &= verifyTextureLevelParameterEqual(gl, spec.queryTarget, 0, m_pname, GL_NONE, m_type);
1246	}
1247	else
1248	{
1249		for (int levelNdx = 0; levelNdx < (int)spec.levels.size(); ++levelNdx)
1250		{
1251			const int queryLevel	= spec.levels[levelNdx].level;
1252			const int refValue		= getComponentType(spec.levels[levelNdx].internalFormat);
1253
1254			allOk &= verifyTextureLevelParameterEqual(gl, spec.queryTarget, queryLevel, m_pname, refValue, m_type);
1255		}
1256	}
1257
1258	return allOk;
1259}
1260
1261int TextureLevelTypeCase::getComponentType (glw::GLenum internalFormat)
1262{
1263	const tcu::TextureFormat		format			= glu::mapGLInternalFormat(internalFormat);
1264	const tcu::TextureChannelClass	channelClass	= tcu::getTextureChannelClass(format.type);
1265	glw::GLenum						channelType		= GL_NONE;
1266
1267	// depth-stencil special cases
1268	if (format.type == tcu::TextureFormat::UNSIGNED_INT_24_8)
1269	{
1270		if (m_pname == GL_TEXTURE_DEPTH_TYPE)
1271			return GL_UNSIGNED_NORMALIZED;
1272		else
1273			return GL_NONE;
1274	}
1275	else if (format.type == tcu::TextureFormat::FLOAT_UNSIGNED_INT_24_8_REV)
1276	{
1277		if (m_pname == GL_TEXTURE_DEPTH_TYPE)
1278			return GL_FLOAT;
1279		else
1280			return GL_NONE;
1281	}
1282	else
1283	{
1284		switch (channelClass)
1285		{
1286			case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:		channelType = GL_SIGNED_NORMALIZED;		break;
1287			case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:		channelType = GL_UNSIGNED_NORMALIZED;	break;
1288			case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:			channelType = GL_INT;					break;
1289			case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:			channelType = GL_UNSIGNED_INT;			break;
1290			case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:			channelType = GL_FLOAT;					break;
1291			default:
1292				DE_ASSERT(DE_FALSE);
1293		}
1294	}
1295
1296	switch (m_pname)
1297	{
1298		case GL_TEXTURE_RED_TYPE:
1299			if (format.order == tcu::TextureFormat::R		||
1300				format.order == tcu::TextureFormat::RG		||
1301				format.order == tcu::TextureFormat::RGB		||
1302				format.order == tcu::TextureFormat::RGBA	||
1303				format.order == tcu::TextureFormat::BGRA	||
1304				format.order == tcu::TextureFormat::ARGB	||
1305				format.order == tcu::TextureFormat::sRGB	||
1306				format.order == tcu::TextureFormat::sRGBA)
1307				return channelType;
1308			else
1309				return GL_NONE;
1310
1311		case GL_TEXTURE_GREEN_TYPE:
1312			if (format.order == tcu::TextureFormat::RG		||
1313				format.order == tcu::TextureFormat::RGB		||
1314				format.order == tcu::TextureFormat::RGBA	||
1315				format.order == tcu::TextureFormat::BGRA	||
1316				format.order == tcu::TextureFormat::ARGB	||
1317				format.order == tcu::TextureFormat::sRGB	||
1318				format.order == tcu::TextureFormat::sRGBA)
1319				return channelType;
1320			else
1321				return GL_NONE;
1322
1323		case GL_TEXTURE_BLUE_TYPE:
1324			if (format.order == tcu::TextureFormat::RGB		||
1325				format.order == tcu::TextureFormat::RGBA	||
1326				format.order == tcu::TextureFormat::BGRA	||
1327				format.order == tcu::TextureFormat::ARGB	||
1328				format.order == tcu::TextureFormat::sRGB	||
1329				format.order == tcu::TextureFormat::sRGBA)
1330				return channelType;
1331			else
1332				return GL_NONE;
1333
1334		case GL_TEXTURE_ALPHA_TYPE:
1335			if (format.order == tcu::TextureFormat::RGBA	||
1336				format.order == tcu::TextureFormat::BGRA	||
1337				format.order == tcu::TextureFormat::ARGB	||
1338				format.order == tcu::TextureFormat::sRGBA)
1339				return channelType;
1340			else
1341				return GL_NONE;
1342
1343		case GL_TEXTURE_DEPTH_TYPE:
1344			if (format.order == tcu::TextureFormat::D	||
1345				format.order == tcu::TextureFormat::DS)
1346				return channelType;
1347			else
1348				return GL_NONE;
1349
1350		default:
1351			DE_ASSERT(DE_FALSE);
1352			return 0;
1353	}
1354}
1355
1356class TextureLevelCompressedCase : public TextureLevelCase
1357{
1358public:
1359	TextureLevelCompressedCase (Context& ctx, const char* name, const char* desc, VerifierType type)
1360		: TextureLevelCase(ctx, name, desc, type)
1361	{
1362	}
1363
1364private:
1365	void generateTestIterations (std::vector<TextureGenerationSpec>& iterations)
1366	{
1367		generateCompressedTextureGenerationGroup(iterations);
1368	}
1369
1370	bool checkTextureState (glu::CallLogWrapper& gl, const TextureGenerationSpec& spec)
1371	{
1372		bool allOk = true;
1373
1374		if (spec.levels.empty())
1375		{
1376			allOk &= verifyTextureLevelParameterEqual(gl, spec.queryTarget, 0, GL_TEXTURE_COMPRESSED, 0, m_type);
1377		}
1378		else
1379		{
1380			for (int levelNdx = 0; levelNdx < (int)spec.levels.size(); ++levelNdx)
1381			{
1382				const int queryLevel	= spec.levels[levelNdx].level;
1383				const int refValue		= (spec.levels[levelNdx].compressed) ? (1) : (0);
1384
1385				allOk &= verifyTextureLevelParameterEqual(gl, spec.queryTarget, queryLevel, GL_TEXTURE_COMPRESSED, refValue, m_type);
1386			}
1387		}
1388
1389		return allOk;
1390	}
1391};
1392
1393} // anonymous
1394
1395TextureLevelStateQueryTests::TextureLevelStateQueryTests (Context& context)
1396	: TestCaseGroup(context, "texture_level", "GetTexLevelParameter tests")
1397{
1398}
1399
1400TextureLevelStateQueryTests::~TextureLevelStateQueryTests (void)
1401{
1402}
1403
1404void TextureLevelStateQueryTests::init (void)
1405{
1406	tcu::TestCaseGroup* const integerGroup = new tcu::TestCaseGroup(m_testCtx, "integer", "use GetTexLevelParameteriv");
1407	tcu::TestCaseGroup* const floatGroup = new tcu::TestCaseGroup(m_testCtx, "float", "use GetTexLevelParameterfv");
1408
1409	addChild(integerGroup);
1410	addChild(floatGroup);
1411
1412	for (int groupNdx = 0; groupNdx < 2; ++groupNdx)
1413	{
1414		tcu::TestCaseGroup* const	group		= (groupNdx == 0) ? (integerGroup) : (floatGroup);
1415		const VerifierType			verifier	= (groupNdx == 0) ? (VERIFIER_INT) : (VERIFIER_FLOAT);
1416
1417
1418		group->addChild(new TextureLevelSampleCase			(m_context, "texture_samples",					"Verify TEXTURE_SAMPLES",					verifier));
1419		group->addChild(new TextureLevelFixedSamplesCase	(m_context, "texture_fixed_sample_locations",	"Verify TEXTURE_FIXED_SAMPLE_LOCATIONS",	verifier));
1420		group->addChild(new TextureLevelWidthCase			(m_context, "texture_width",					"Verify TEXTURE_WIDTH",						verifier));
1421		group->addChild(new TextureLevelHeightCase			(m_context, "texture_height",					"Verify TEXTURE_HEIGHT",					verifier));
1422		group->addChild(new TextureLevelDepthCase			(m_context, "texture_depth",					"Verify TEXTURE_DEPTH",						verifier));
1423		group->addChild(new TextureLevelInternalFormatCase	(m_context, "texture_internal_format",			"Verify TEXTURE_INTERNAL_FORMAT",			verifier));
1424		group->addChild(new TextureLevelSizeCase			(m_context, "texture_red_size",					"Verify TEXTURE_RED_SIZE",					verifier,	GL_TEXTURE_RED_SIZE));
1425		group->addChild(new TextureLevelSizeCase			(m_context, "texture_green_size",				"Verify TEXTURE_GREEN_SIZE",				verifier,	GL_TEXTURE_GREEN_SIZE));
1426		group->addChild(new TextureLevelSizeCase			(m_context, "texture_blue_size",				"Verify TEXTURE_BLUE_SIZE",					verifier,	GL_TEXTURE_BLUE_SIZE));
1427		group->addChild(new TextureLevelSizeCase			(m_context, "texture_alpha_size",				"Verify TEXTURE_ALPHA_SIZE",				verifier,	GL_TEXTURE_ALPHA_SIZE));
1428		group->addChild(new TextureLevelSizeCase			(m_context, "texture_depth_size",				"Verify TEXTURE_DEPTH_SIZE",				verifier,	GL_TEXTURE_DEPTH_SIZE));
1429		group->addChild(new TextureLevelSizeCase			(m_context, "texture_stencil_size",				"Verify TEXTURE_STENCIL_SIZE",				verifier,	GL_TEXTURE_STENCIL_SIZE));
1430		group->addChild(new TextureLevelSizeCase			(m_context, "texture_shared_size",				"Verify TEXTURE_SHARED_SIZE",				verifier,	GL_TEXTURE_SHARED_SIZE));
1431		group->addChild(new TextureLevelTypeCase			(m_context, "texture_red_type",					"Verify TEXTURE_RED_TYPE",					verifier,	GL_TEXTURE_RED_TYPE));
1432		group->addChild(new TextureLevelTypeCase			(m_context, "texture_green_type",				"Verify TEXTURE_GREEN_TYPE",				verifier,	GL_TEXTURE_GREEN_TYPE));
1433		group->addChild(new TextureLevelTypeCase			(m_context, "texture_blue_type",				"Verify TEXTURE_BLUE_TYPE",					verifier,	GL_TEXTURE_BLUE_TYPE));
1434		group->addChild(new TextureLevelTypeCase			(m_context, "texture_alpha_type",				"Verify TEXTURE_ALPHA_TYPE",				verifier,	GL_TEXTURE_ALPHA_TYPE));
1435		group->addChild(new TextureLevelTypeCase			(m_context, "texture_depth_type",				"Verify TEXTURE_DEPTH_TYPE",				verifier,	GL_TEXTURE_DEPTH_TYPE));
1436		group->addChild(new TextureLevelCompressedCase		(m_context, "texture_compressed",				"Verify TEXTURE_COMPRESSED",				verifier));
1437	}
1438}
1439
1440} // Functional
1441} // gles31
1442} // deqp
1443