1e5c31af7Sopenharmony_ci/*-------------------------------------------------------------------------
2e5c31af7Sopenharmony_ci * drawElements Quality Program OpenGL ES 2.0 Module
3e5c31af7Sopenharmony_ci * -------------------------------------------------
4e5c31af7Sopenharmony_ci *
5e5c31af7Sopenharmony_ci * Copyright 2014 The Android Open Source Project
6e5c31af7Sopenharmony_ci *
7e5c31af7Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
8e5c31af7Sopenharmony_ci * you may not use this file except in compliance with the License.
9e5c31af7Sopenharmony_ci * You may obtain a copy of the License at
10e5c31af7Sopenharmony_ci *
11e5c31af7Sopenharmony_ci *      http://www.apache.org/licenses/LICENSE-2.0
12e5c31af7Sopenharmony_ci *
13e5c31af7Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
14e5c31af7Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
15e5c31af7Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16e5c31af7Sopenharmony_ci * See the License for the specific language governing permissions and
17e5c31af7Sopenharmony_ci * limitations under the License.
18e5c31af7Sopenharmony_ci *
19e5c31af7Sopenharmony_ci *//*!
20e5c31af7Sopenharmony_ci * \file
21e5c31af7Sopenharmony_ci * \brief Mipmapping tests.
22e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
23e5c31af7Sopenharmony_ci
24e5c31af7Sopenharmony_ci#include "es2fTextureMipmapTests.hpp"
25e5c31af7Sopenharmony_ci#include "glsTextureTestUtil.hpp"
26e5c31af7Sopenharmony_ci#include "gluTexture.hpp"
27e5c31af7Sopenharmony_ci#include "gluStrUtil.hpp"
28e5c31af7Sopenharmony_ci#include "gluTextureUtil.hpp"
29e5c31af7Sopenharmony_ci#include "gluPixelTransfer.hpp"
30e5c31af7Sopenharmony_ci#include "tcuTestLog.hpp"
31e5c31af7Sopenharmony_ci#include "tcuTextureUtil.hpp"
32e5c31af7Sopenharmony_ci#include "tcuVector.hpp"
33e5c31af7Sopenharmony_ci#include "tcuMatrix.hpp"
34e5c31af7Sopenharmony_ci#include "tcuMatrixUtil.hpp"
35e5c31af7Sopenharmony_ci#include "tcuTexLookupVerifier.hpp"
36e5c31af7Sopenharmony_ci#include "tcuVectorUtil.hpp"
37e5c31af7Sopenharmony_ci#include "deStringUtil.hpp"
38e5c31af7Sopenharmony_ci#include "deRandom.hpp"
39e5c31af7Sopenharmony_ci#include "glwFunctions.hpp"
40e5c31af7Sopenharmony_ci#include "glwEnums.hpp"
41e5c31af7Sopenharmony_ci
42e5c31af7Sopenharmony_cinamespace deqp
43e5c31af7Sopenharmony_ci{
44e5c31af7Sopenharmony_cinamespace gles2
45e5c31af7Sopenharmony_ci{
46e5c31af7Sopenharmony_cinamespace Functional
47e5c31af7Sopenharmony_ci{
48e5c31af7Sopenharmony_ci
49e5c31af7Sopenharmony_ciusing tcu::TestLog;
50e5c31af7Sopenharmony_ciusing std::vector;
51e5c31af7Sopenharmony_ciusing std::string;
52e5c31af7Sopenharmony_ciusing tcu::Sampler;
53e5c31af7Sopenharmony_ciusing tcu::Vec2;
54e5c31af7Sopenharmony_ciusing tcu::Mat2;
55e5c31af7Sopenharmony_ciusing tcu::Vec4;
56e5c31af7Sopenharmony_ciusing tcu::IVec2;
57e5c31af7Sopenharmony_ciusing tcu::IVec4;
58e5c31af7Sopenharmony_ciusing namespace glu;
59e5c31af7Sopenharmony_ciusing namespace gls::TextureTestUtil;
60e5c31af7Sopenharmony_ciusing namespace glu::TextureTestUtil;
61e5c31af7Sopenharmony_ci
62e5c31af7Sopenharmony_cienum CoordType
63e5c31af7Sopenharmony_ci{
64e5c31af7Sopenharmony_ci	COORDTYPE_BASIC,		//!< texCoord = translateScale(position).
65e5c31af7Sopenharmony_ci	COORDTYPE_BASIC_BIAS,	//!< Like basic, but with bias values.
66e5c31af7Sopenharmony_ci	COORDTYPE_AFFINE,		//!< texCoord = translateScaleRotateShear(position).
67e5c31af7Sopenharmony_ci	COORDTYPE_PROJECTED,	//!< Projected coordinates, w != 1
68e5c31af7Sopenharmony_ci
69e5c31af7Sopenharmony_ci	COORDTYPE_LAST
70e5c31af7Sopenharmony_ci};
71e5c31af7Sopenharmony_ci
72e5c31af7Sopenharmony_ci// Texture2DMipmapCase
73e5c31af7Sopenharmony_ci
74e5c31af7Sopenharmony_ciclass Texture2DMipmapCase : public tcu::TestCase
75e5c31af7Sopenharmony_ci{
76e5c31af7Sopenharmony_cipublic:
77e5c31af7Sopenharmony_ci
78e5c31af7Sopenharmony_ci								Texture2DMipmapCase			(tcu::TestContext&			testCtx,
79e5c31af7Sopenharmony_ci															 glu::RenderContext&		renderCtx,
80e5c31af7Sopenharmony_ci															 const glu::ContextInfo&	renderCtxInfo,
81e5c31af7Sopenharmony_ci															 const char*				name,
82e5c31af7Sopenharmony_ci															 const char*				desc,
83e5c31af7Sopenharmony_ci															 CoordType					coordType,
84e5c31af7Sopenharmony_ci															 deUint32					minFilter,
85e5c31af7Sopenharmony_ci															 deUint32					wrapS,
86e5c31af7Sopenharmony_ci															 deUint32					wrapT,
87e5c31af7Sopenharmony_ci															 deUint32					format,
88e5c31af7Sopenharmony_ci															 deUint32					dataType,
89e5c31af7Sopenharmony_ci															 int						width,
90e5c31af7Sopenharmony_ci															 int						height);
91e5c31af7Sopenharmony_ci								~Texture2DMipmapCase		(void);
92e5c31af7Sopenharmony_ci
93e5c31af7Sopenharmony_ci	void						init						(void);
94e5c31af7Sopenharmony_ci	void						deinit						(void);
95e5c31af7Sopenharmony_ci	IterateResult				iterate						(void);
96e5c31af7Sopenharmony_ci
97e5c31af7Sopenharmony_ciprivate:
98e5c31af7Sopenharmony_ci								Texture2DMipmapCase			(const Texture2DMipmapCase& other);
99e5c31af7Sopenharmony_ci	Texture2DMipmapCase&		operator=					(const Texture2DMipmapCase& other);
100e5c31af7Sopenharmony_ci
101e5c31af7Sopenharmony_ci	glu::RenderContext&			m_renderCtx;
102e5c31af7Sopenharmony_ci	const glu::ContextInfo&		m_renderCtxInfo;
103e5c31af7Sopenharmony_ci
104e5c31af7Sopenharmony_ci	CoordType					m_coordType;
105e5c31af7Sopenharmony_ci	deUint32					m_minFilter;
106e5c31af7Sopenharmony_ci	deUint32					m_wrapS;
107e5c31af7Sopenharmony_ci	deUint32					m_wrapT;
108e5c31af7Sopenharmony_ci	deUint32					m_format;
109e5c31af7Sopenharmony_ci	deUint32					m_dataType;
110e5c31af7Sopenharmony_ci	int							m_width;
111e5c31af7Sopenharmony_ci	int							m_height;
112e5c31af7Sopenharmony_ci
113e5c31af7Sopenharmony_ci	glu::Texture2D*				m_texture;
114e5c31af7Sopenharmony_ci	TextureRenderer				m_renderer;
115e5c31af7Sopenharmony_ci};
116e5c31af7Sopenharmony_ci
117e5c31af7Sopenharmony_ciTexture2DMipmapCase::Texture2DMipmapCase (tcu::TestContext&			testCtx,
118e5c31af7Sopenharmony_ci										  glu::RenderContext&		renderCtx,
119e5c31af7Sopenharmony_ci										  const glu::ContextInfo&	renderCtxInfo,
120e5c31af7Sopenharmony_ci										  const char*				name,
121e5c31af7Sopenharmony_ci										  const char*				desc,
122e5c31af7Sopenharmony_ci										  CoordType					coordType,
123e5c31af7Sopenharmony_ci										  deUint32					minFilter,
124e5c31af7Sopenharmony_ci										  deUint32					wrapS,
125e5c31af7Sopenharmony_ci										  deUint32					wrapT,
126e5c31af7Sopenharmony_ci										  deUint32					format,
127e5c31af7Sopenharmony_ci										  deUint32					dataType,
128e5c31af7Sopenharmony_ci										  int						width,
129e5c31af7Sopenharmony_ci										  int						height)
130e5c31af7Sopenharmony_ci	: TestCase			(testCtx, name, desc)
131e5c31af7Sopenharmony_ci	, m_renderCtx		(renderCtx)
132e5c31af7Sopenharmony_ci	, m_renderCtxInfo	(renderCtxInfo)
133e5c31af7Sopenharmony_ci	, m_coordType		(coordType)
134e5c31af7Sopenharmony_ci	, m_minFilter		(minFilter)
135e5c31af7Sopenharmony_ci	, m_wrapS			(wrapS)
136e5c31af7Sopenharmony_ci	, m_wrapT			(wrapT)
137e5c31af7Sopenharmony_ci	, m_format			(format)
138e5c31af7Sopenharmony_ci	, m_dataType		(dataType)
139e5c31af7Sopenharmony_ci	, m_width			(width)
140e5c31af7Sopenharmony_ci	, m_height			(height)
141e5c31af7Sopenharmony_ci	, m_texture			(DE_NULL)
142e5c31af7Sopenharmony_ci	, m_renderer		(renderCtx, testCtx.getLog(), glu::GLSL_VERSION_100_ES,
143e5c31af7Sopenharmony_ci						 renderCtxInfo.isFragmentHighPrecisionSupported() ? glu::PRECISION_HIGHP // Use highp if available.
144e5c31af7Sopenharmony_ci																		  : glu::PRECISION_MEDIUMP)
145e5c31af7Sopenharmony_ci{
146e5c31af7Sopenharmony_ci}
147e5c31af7Sopenharmony_ci
148e5c31af7Sopenharmony_ciTexture2DMipmapCase::~Texture2DMipmapCase (void)
149e5c31af7Sopenharmony_ci{
150e5c31af7Sopenharmony_ci	deinit();
151e5c31af7Sopenharmony_ci}
152e5c31af7Sopenharmony_ci
153e5c31af7Sopenharmony_civoid Texture2DMipmapCase::init (void)
154e5c31af7Sopenharmony_ci{
155e5c31af7Sopenharmony_ci	if (!m_renderCtxInfo.isFragmentHighPrecisionSupported())
156e5c31af7Sopenharmony_ci		m_testCtx.getLog() << TestLog::Message << "Warning: High precision not supported in fragment shaders." << TestLog::EndMessage;
157e5c31af7Sopenharmony_ci
158e5c31af7Sopenharmony_ci	if (m_coordType == COORDTYPE_PROJECTED && m_renderCtx.getRenderTarget().getNumSamples() > 0)
159e5c31af7Sopenharmony_ci		throw tcu::NotSupportedError("Projected lookup validation not supported in multisample config");
160e5c31af7Sopenharmony_ci
161e5c31af7Sopenharmony_ci	m_texture = new Texture2D(m_renderCtx, m_format, m_dataType, m_width, m_height);
162e5c31af7Sopenharmony_ci
163e5c31af7Sopenharmony_ci	int numLevels = deLog2Floor32(de::max(m_width, m_height))+1;
164e5c31af7Sopenharmony_ci
165e5c31af7Sopenharmony_ci	// Fill texture with colored grid.
166e5c31af7Sopenharmony_ci	for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
167e5c31af7Sopenharmony_ci	{
168e5c31af7Sopenharmony_ci		deUint32	step		= 0xff / (numLevels-1);
169e5c31af7Sopenharmony_ci		deUint32	inc			= deClamp32(step*levelNdx, 0x00, 0xff);
170e5c31af7Sopenharmony_ci		deUint32	dec			= 0xff - inc;
171e5c31af7Sopenharmony_ci		deUint32	rgb			= (inc << 16) | (dec << 8) | 0xff;
172e5c31af7Sopenharmony_ci		deUint32	color		= 0xff000000 | rgb;
173e5c31af7Sopenharmony_ci
174e5c31af7Sopenharmony_ci		m_texture->getRefTexture().allocLevel(levelNdx);
175e5c31af7Sopenharmony_ci		tcu::clear(m_texture->getRefTexture().getLevel(levelNdx), tcu::RGBA(color).toVec());
176e5c31af7Sopenharmony_ci	}
177e5c31af7Sopenharmony_ci}
178e5c31af7Sopenharmony_ci
179e5c31af7Sopenharmony_civoid Texture2DMipmapCase::deinit (void)
180e5c31af7Sopenharmony_ci{
181e5c31af7Sopenharmony_ci	delete m_texture;
182e5c31af7Sopenharmony_ci	m_texture = DE_NULL;
183e5c31af7Sopenharmony_ci
184e5c31af7Sopenharmony_ci	m_renderer.clear();
185e5c31af7Sopenharmony_ci}
186e5c31af7Sopenharmony_ci
187e5c31af7Sopenharmony_cistatic void getBasicTexCoord2D (std::vector<float>& dst, int cellNdx)
188e5c31af7Sopenharmony_ci{
189e5c31af7Sopenharmony_ci	static const struct
190e5c31af7Sopenharmony_ci	{
191e5c31af7Sopenharmony_ci		Vec2 bottomLeft;
192e5c31af7Sopenharmony_ci		Vec2 topRight;
193e5c31af7Sopenharmony_ci	} s_basicCoords[] =
194e5c31af7Sopenharmony_ci	{
195e5c31af7Sopenharmony_ci		{ Vec2(-0.1f,  0.1f), Vec2( 0.8f,  1.0f) },
196e5c31af7Sopenharmony_ci		{ Vec2(-0.3f, -0.6f), Vec2( 0.7f,  0.4f) },
197e5c31af7Sopenharmony_ci		{ Vec2(-0.3f,  0.6f), Vec2( 0.7f, -0.9f) },
198e5c31af7Sopenharmony_ci		{ Vec2(-0.8f,  0.6f), Vec2( 0.7f, -0.9f) },
199e5c31af7Sopenharmony_ci
200e5c31af7Sopenharmony_ci		{ Vec2(-0.5f, -0.5f), Vec2( 1.5f,  1.5f) },
201e5c31af7Sopenharmony_ci		{ Vec2( 1.0f, -1.0f), Vec2(-1.3f,  1.0f) },
202e5c31af7Sopenharmony_ci		{ Vec2( 1.2f, -1.0f), Vec2(-1.3f,  1.6f) },
203e5c31af7Sopenharmony_ci		{ Vec2( 2.2f, -1.1f), Vec2(-1.3f,  0.8f) },
204e5c31af7Sopenharmony_ci
205e5c31af7Sopenharmony_ci		{ Vec2(-1.5f,  1.6f), Vec2( 1.7f, -1.4f) },
206e5c31af7Sopenharmony_ci		{ Vec2( 2.0f,  1.6f), Vec2( 2.3f, -1.4f) },
207e5c31af7Sopenharmony_ci		{ Vec2( 1.3f, -2.6f), Vec2(-2.7f,  2.9f) },
208e5c31af7Sopenharmony_ci		{ Vec2(-0.8f, -6.6f), Vec2( 6.0f, -0.9f) },
209e5c31af7Sopenharmony_ci
210e5c31af7Sopenharmony_ci		{ Vec2( -8.0f,   9.0f), Vec2(  8.3f,  -7.0f) },
211e5c31af7Sopenharmony_ci		{ Vec2(-16.0f,  10.0f), Vec2( 18.3f,  24.0f) },
212e5c31af7Sopenharmony_ci		{ Vec2( 30.2f,  55.0f), Vec2(-24.3f,  -1.6f) },
213e5c31af7Sopenharmony_ci		{ Vec2(-33.2f,  64.1f), Vec2( 32.1f, -64.1f) },
214e5c31af7Sopenharmony_ci	};
215e5c31af7Sopenharmony_ci
216e5c31af7Sopenharmony_ci	DE_ASSERT(de::inBounds(cellNdx, 0, DE_LENGTH_OF_ARRAY(s_basicCoords)));
217e5c31af7Sopenharmony_ci
218e5c31af7Sopenharmony_ci	const Vec2& bottomLeft	= s_basicCoords[cellNdx].bottomLeft;
219e5c31af7Sopenharmony_ci	const Vec2& topRight	= s_basicCoords[cellNdx].topRight;
220e5c31af7Sopenharmony_ci
221e5c31af7Sopenharmony_ci	computeQuadTexCoord2D(dst, bottomLeft, topRight);
222e5c31af7Sopenharmony_ci}
223e5c31af7Sopenharmony_ci
224e5c31af7Sopenharmony_cistatic void getAffineTexCoord2D (std::vector<float>& dst, int cellNdx)
225e5c31af7Sopenharmony_ci{
226e5c31af7Sopenharmony_ci	// Use basic coords as base.
227e5c31af7Sopenharmony_ci	getBasicTexCoord2D(dst, cellNdx);
228e5c31af7Sopenharmony_ci
229e5c31af7Sopenharmony_ci	// Rotate based on cell index.
230e5c31af7Sopenharmony_ci	float		angle		= 2.0f*DE_PI * ((float)cellNdx / 16.0f);
231e5c31af7Sopenharmony_ci	tcu::Mat2	rotMatrix	= tcu::rotationMatrix(angle);
232e5c31af7Sopenharmony_ci
233e5c31af7Sopenharmony_ci	// Second and third row are sheared.
234e5c31af7Sopenharmony_ci	float		shearX		= de::inRange(cellNdx, 4, 11) ? (float)(15-cellNdx) / 16.0f : 0.0f;
235e5c31af7Sopenharmony_ci	tcu::Mat2	shearMatrix	= tcu::shearMatrix(tcu::Vec2(shearX, 0.0f));
236e5c31af7Sopenharmony_ci
237e5c31af7Sopenharmony_ci	tcu::Mat2	transform	= rotMatrix * shearMatrix;
238e5c31af7Sopenharmony_ci	Vec2		p0			= transform * Vec2(dst[0], dst[1]);
239e5c31af7Sopenharmony_ci	Vec2		p1			= transform * Vec2(dst[2], dst[3]);
240e5c31af7Sopenharmony_ci	Vec2		p2			= transform * Vec2(dst[4], dst[5]);
241e5c31af7Sopenharmony_ci	Vec2		p3			= transform * Vec2(dst[6], dst[7]);
242e5c31af7Sopenharmony_ci
243e5c31af7Sopenharmony_ci	dst[0] = p0.x();	dst[1] = p0.y();
244e5c31af7Sopenharmony_ci	dst[2] = p1.x();	dst[3] = p1.y();
245e5c31af7Sopenharmony_ci	dst[4] = p2.x();	dst[5] = p2.y();
246e5c31af7Sopenharmony_ci	dst[6] = p3.x();	dst[7] = p3.y();
247e5c31af7Sopenharmony_ci}
248e5c31af7Sopenharmony_ci
249e5c31af7Sopenharmony_ciTexture2DMipmapCase::IterateResult Texture2DMipmapCase::iterate (void)
250e5c31af7Sopenharmony_ci{
251e5c31af7Sopenharmony_ci	const glw::Functions&		gl					= m_renderCtx.getFunctions();
252e5c31af7Sopenharmony_ci
253e5c31af7Sopenharmony_ci	const tcu::Texture2D&		refTexture			= m_texture->getRefTexture();
254e5c31af7Sopenharmony_ci
255e5c31af7Sopenharmony_ci	const deUint32				magFilter			= GL_NEAREST;
256e5c31af7Sopenharmony_ci	const int					texWidth			= refTexture.getWidth();
257e5c31af7Sopenharmony_ci	const int					texHeight			= refTexture.getHeight();
258e5c31af7Sopenharmony_ci	const int					defViewportWidth	= texWidth*4;
259e5c31af7Sopenharmony_ci	const int					defViewportHeight	= texHeight*4;
260e5c31af7Sopenharmony_ci
261e5c31af7Sopenharmony_ci	const RandomViewport		viewport			(m_renderCtx.getRenderTarget(), defViewportWidth, defViewportHeight, deStringHash(getName()));
262e5c31af7Sopenharmony_ci	ReferenceParams				sampleParams		(TEXTURETYPE_2D);
263e5c31af7Sopenharmony_ci	vector<float>				texCoord;
264e5c31af7Sopenharmony_ci
265e5c31af7Sopenharmony_ci	const bool					isProjected			= m_coordType == COORDTYPE_PROJECTED;
266e5c31af7Sopenharmony_ci	const bool					useLodBias			= m_coordType == COORDTYPE_BASIC_BIAS;
267e5c31af7Sopenharmony_ci
268e5c31af7Sopenharmony_ci	tcu::Surface				renderedFrame		(viewport.width, viewport.height);
269e5c31af7Sopenharmony_ci
270e5c31af7Sopenharmony_ci	// Viewport is divided into 4x4 grid.
271e5c31af7Sopenharmony_ci	int							gridWidth			= 4;
272e5c31af7Sopenharmony_ci	int							gridHeight			= 4;
273e5c31af7Sopenharmony_ci	int							cellWidth			= viewport.width / gridWidth;
274e5c31af7Sopenharmony_ci	int							cellHeight			= viewport.height / gridHeight;
275e5c31af7Sopenharmony_ci
276e5c31af7Sopenharmony_ci	// Bail out if rendertarget is too small.
277e5c31af7Sopenharmony_ci	if (viewport.width < defViewportWidth/2 || viewport.height < defViewportHeight/2)
278e5c31af7Sopenharmony_ci		throw tcu::NotSupportedError("Too small viewport", "", __FILE__, __LINE__);
279e5c31af7Sopenharmony_ci
280e5c31af7Sopenharmony_ci	// Sampling parameters.
281e5c31af7Sopenharmony_ci	sampleParams.sampler		= glu::mapGLSampler(m_wrapS, m_wrapT, m_minFilter, magFilter);
282e5c31af7Sopenharmony_ci	sampleParams.samplerType	= glu::TextureTestUtil::getSamplerType(m_texture->getRefTexture().getFormat());
283e5c31af7Sopenharmony_ci	sampleParams.flags			= (isProjected ? ReferenceParams::PROJECTED : 0) | (useLodBias ? ReferenceParams::USE_BIAS : 0);
284e5c31af7Sopenharmony_ci	sampleParams.lodMode		= LODMODE_EXACT; // Use ideal lod.
285e5c31af7Sopenharmony_ci
286e5c31af7Sopenharmony_ci	// Upload texture data.
287e5c31af7Sopenharmony_ci	m_texture->upload();
288e5c31af7Sopenharmony_ci
289e5c31af7Sopenharmony_ci	// Bind gradient texture and setup sampler parameters.
290e5c31af7Sopenharmony_ci	gl.bindTexture	(GL_TEXTURE_2D, m_texture->getGLTexture());
291e5c31af7Sopenharmony_ci	gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,		m_wrapS);
292e5c31af7Sopenharmony_ci	gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,		m_wrapT);
293e5c31af7Sopenharmony_ci	gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,	m_minFilter);
294e5c31af7Sopenharmony_ci	gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,	magFilter);
295e5c31af7Sopenharmony_ci
296e5c31af7Sopenharmony_ci	GLU_EXPECT_NO_ERROR(gl.getError(), "After texture setup");
297e5c31af7Sopenharmony_ci
298e5c31af7Sopenharmony_ci	// Bias values.
299e5c31af7Sopenharmony_ci	static const float s_bias[] = { 1.0f, -2.0f, 0.8f, -0.5f, 1.5f, 0.9f, 2.0f, 4.0f };
300e5c31af7Sopenharmony_ci
301e5c31af7Sopenharmony_ci	// Projection values.
302e5c31af7Sopenharmony_ci	static const Vec4 s_projections[] =
303e5c31af7Sopenharmony_ci	{
304e5c31af7Sopenharmony_ci		Vec4(1.2f, 1.0f, 0.7f, 1.0f),
305e5c31af7Sopenharmony_ci		Vec4(1.3f, 0.8f, 0.6f, 2.0f),
306e5c31af7Sopenharmony_ci		Vec4(0.8f, 1.0f, 1.7f, 0.6f),
307e5c31af7Sopenharmony_ci		Vec4(1.2f, 1.0f, 1.7f, 1.5f)
308e5c31af7Sopenharmony_ci	};
309e5c31af7Sopenharmony_ci
310e5c31af7Sopenharmony_ci	// Render cells.
311e5c31af7Sopenharmony_ci	for (int gridY = 0; gridY < gridHeight; gridY++)
312e5c31af7Sopenharmony_ci	{
313e5c31af7Sopenharmony_ci		for (int gridX = 0; gridX < gridWidth; gridX++)
314e5c31af7Sopenharmony_ci		{
315e5c31af7Sopenharmony_ci			const int		curX		= cellWidth*gridX;
316e5c31af7Sopenharmony_ci			const int		curY		= cellHeight*gridY;
317e5c31af7Sopenharmony_ci			const int		curW		= gridX+1 == gridWidth ? (viewport.width-curX) : cellWidth;
318e5c31af7Sopenharmony_ci			const int		curH		= gridY+1 == gridHeight ? (viewport.height-curY) : cellHeight;
319e5c31af7Sopenharmony_ci			const int		cellNdx		= gridY*gridWidth + gridX;
320e5c31af7Sopenharmony_ci
321e5c31af7Sopenharmony_ci			// Compute texcoord.
322e5c31af7Sopenharmony_ci			switch (m_coordType)
323e5c31af7Sopenharmony_ci			{
324e5c31af7Sopenharmony_ci				case COORDTYPE_BASIC_BIAS:	// Fall-through.
325e5c31af7Sopenharmony_ci				case COORDTYPE_PROJECTED:
326e5c31af7Sopenharmony_ci				case COORDTYPE_BASIC:		getBasicTexCoord2D	(texCoord, cellNdx);	break;
327e5c31af7Sopenharmony_ci				case COORDTYPE_AFFINE:		getAffineTexCoord2D	(texCoord, cellNdx);	break;
328e5c31af7Sopenharmony_ci				default:					DE_ASSERT(DE_FALSE);
329e5c31af7Sopenharmony_ci			}
330e5c31af7Sopenharmony_ci
331e5c31af7Sopenharmony_ci			if (isProjected)
332e5c31af7Sopenharmony_ci				sampleParams.w = s_projections[cellNdx % DE_LENGTH_OF_ARRAY(s_projections)];
333e5c31af7Sopenharmony_ci
334e5c31af7Sopenharmony_ci			if (useLodBias)
335e5c31af7Sopenharmony_ci				sampleParams.bias = s_bias[cellNdx % DE_LENGTH_OF_ARRAY(s_bias)];
336e5c31af7Sopenharmony_ci
337e5c31af7Sopenharmony_ci			// Render with GL.
338e5c31af7Sopenharmony_ci			gl.viewport(viewport.x+curX, viewport.y+curY, curW, curH);
339e5c31af7Sopenharmony_ci			m_renderer.renderQuad(0, &texCoord[0], sampleParams);
340e5c31af7Sopenharmony_ci		}
341e5c31af7Sopenharmony_ci	}
342e5c31af7Sopenharmony_ci
343e5c31af7Sopenharmony_ci	// Read result.
344e5c31af7Sopenharmony_ci	glu::readPixels(m_renderCtx, viewport.x, viewport.y, renderedFrame.getAccess());
345e5c31af7Sopenharmony_ci
346e5c31af7Sopenharmony_ci	// Compare and log.
347e5c31af7Sopenharmony_ci	{
348e5c31af7Sopenharmony_ci		const tcu::PixelFormat&	pixelFormat		= m_renderCtx.getRenderTarget().getPixelFormat();
349e5c31af7Sopenharmony_ci		const bool				isTrilinear		= m_minFilter == GL_NEAREST_MIPMAP_LINEAR || m_minFilter == GL_LINEAR_MIPMAP_LINEAR;
350e5c31af7Sopenharmony_ci		tcu::Surface			referenceFrame	(viewport.width, viewport.height);
351e5c31af7Sopenharmony_ci		tcu::Surface			errorMask		(viewport.width, viewport.height);
352e5c31af7Sopenharmony_ci		tcu::LookupPrecision	lookupPrec;
353e5c31af7Sopenharmony_ci		tcu::LodPrecision		lodPrec;
354e5c31af7Sopenharmony_ci		int						numFailedPixels	= 0;
355e5c31af7Sopenharmony_ci
356e5c31af7Sopenharmony_ci		lookupPrec.coordBits		= tcu::IVec3(20, 20, 0);
357e5c31af7Sopenharmony_ci		lookupPrec.uvwBits			= tcu::IVec3(16, 16, 0); // Doesn't really matter since pixels are unicolored.
358e5c31af7Sopenharmony_ci		lookupPrec.colorThreshold	= tcu::computeFixedPointThreshold(max(getBitsVec(pixelFormat) - (isTrilinear ? 2 : 1), tcu::IVec4(0)));
359e5c31af7Sopenharmony_ci		lookupPrec.colorMask		= getCompareMask(pixelFormat);
360e5c31af7Sopenharmony_ci		lodPrec.derivateBits		= 10;
361e5c31af7Sopenharmony_ci		lodPrec.lodBits				= isProjected ? 6 : 8;
362e5c31af7Sopenharmony_ci
363e5c31af7Sopenharmony_ci		for (int gridY = 0; gridY < gridHeight; gridY++)
364e5c31af7Sopenharmony_ci		{
365e5c31af7Sopenharmony_ci			for (int gridX = 0; gridX < gridWidth; gridX++)
366e5c31af7Sopenharmony_ci			{
367e5c31af7Sopenharmony_ci				const int		curX		= cellWidth*gridX;
368e5c31af7Sopenharmony_ci				const int		curY		= cellHeight*gridY;
369e5c31af7Sopenharmony_ci				const int		curW		= gridX+1 == gridWidth ? (viewport.width-curX) : cellWidth;
370e5c31af7Sopenharmony_ci				const int		curH		= gridY+1 == gridHeight ? (viewport.height-curY) : cellHeight;
371e5c31af7Sopenharmony_ci				const int		cellNdx		= gridY*gridWidth + gridX;
372e5c31af7Sopenharmony_ci
373e5c31af7Sopenharmony_ci				// Compute texcoord.
374e5c31af7Sopenharmony_ci				switch (m_coordType)
375e5c31af7Sopenharmony_ci				{
376e5c31af7Sopenharmony_ci					case COORDTYPE_BASIC_BIAS:	// Fall-through.
377e5c31af7Sopenharmony_ci					case COORDTYPE_PROJECTED:
378e5c31af7Sopenharmony_ci					case COORDTYPE_BASIC:		getBasicTexCoord2D	(texCoord, cellNdx);	break;
379e5c31af7Sopenharmony_ci					case COORDTYPE_AFFINE:		getAffineTexCoord2D	(texCoord, cellNdx);	break;
380e5c31af7Sopenharmony_ci					default:					DE_ASSERT(DE_FALSE);
381e5c31af7Sopenharmony_ci				}
382e5c31af7Sopenharmony_ci
383e5c31af7Sopenharmony_ci				if (isProjected)
384e5c31af7Sopenharmony_ci					sampleParams.w = s_projections[cellNdx % DE_LENGTH_OF_ARRAY(s_projections)];
385e5c31af7Sopenharmony_ci
386e5c31af7Sopenharmony_ci				if (useLodBias)
387e5c31af7Sopenharmony_ci					sampleParams.bias = s_bias[cellNdx % DE_LENGTH_OF_ARRAY(s_bias)];
388e5c31af7Sopenharmony_ci
389e5c31af7Sopenharmony_ci				// Render ideal result
390e5c31af7Sopenharmony_ci				sampleTexture(tcu::SurfaceAccess(referenceFrame, pixelFormat, curX, curY, curW, curH),
391e5c31af7Sopenharmony_ci							  refTexture, &texCoord[0], sampleParams);
392e5c31af7Sopenharmony_ci
393e5c31af7Sopenharmony_ci				// Compare this cell
394e5c31af7Sopenharmony_ci				numFailedPixels += computeTextureLookupDiff(tcu::getSubregion(renderedFrame.getAccess(), curX, curY, curW, curH),
395e5c31af7Sopenharmony_ci															tcu::getSubregion(referenceFrame.getAccess(), curX, curY, curW, curH),
396e5c31af7Sopenharmony_ci															tcu::getSubregion(errorMask.getAccess(), curX, curY, curW, curH),
397e5c31af7Sopenharmony_ci															m_texture->getRefTexture(), &texCoord[0], sampleParams,
398e5c31af7Sopenharmony_ci															lookupPrec, lodPrec, m_testCtx.getWatchDog());
399e5c31af7Sopenharmony_ci			}
400e5c31af7Sopenharmony_ci		}
401e5c31af7Sopenharmony_ci
402e5c31af7Sopenharmony_ci		if (numFailedPixels > 0)
403e5c31af7Sopenharmony_ci			m_testCtx.getLog() << TestLog::Message << "ERROR: Image verification failed, found " << numFailedPixels << " invalid pixels!" << TestLog::EndMessage;
404e5c31af7Sopenharmony_ci
405e5c31af7Sopenharmony_ci		m_testCtx.getLog() << TestLog::ImageSet("Result", "Verification result")
406e5c31af7Sopenharmony_ci							<< TestLog::Image("Rendered", "Rendered image", renderedFrame);
407e5c31af7Sopenharmony_ci
408e5c31af7Sopenharmony_ci		if (numFailedPixels > 0)
409e5c31af7Sopenharmony_ci		{
410e5c31af7Sopenharmony_ci			m_testCtx.getLog() << TestLog::Image("Reference", "Ideal reference", referenceFrame)
411e5c31af7Sopenharmony_ci								<< TestLog::Image("ErrorMask", "Error mask", errorMask);
412e5c31af7Sopenharmony_ci		}
413e5c31af7Sopenharmony_ci
414e5c31af7Sopenharmony_ci		m_testCtx.getLog() << TestLog::EndImageSet;
415e5c31af7Sopenharmony_ci
416e5c31af7Sopenharmony_ci		{
417e5c31af7Sopenharmony_ci			const bool isOk = numFailedPixels == 0;
418e5c31af7Sopenharmony_ci			m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS	: QP_TEST_RESULT_FAIL,
419e5c31af7Sopenharmony_ci									isOk ? "Pass"				: "Image verification failed");
420e5c31af7Sopenharmony_ci		}
421e5c31af7Sopenharmony_ci	}
422e5c31af7Sopenharmony_ci
423e5c31af7Sopenharmony_ci	return STOP;
424e5c31af7Sopenharmony_ci}
425e5c31af7Sopenharmony_ci
426e5c31af7Sopenharmony_ci// TextureCubeMipmapCase
427e5c31af7Sopenharmony_ci
428e5c31af7Sopenharmony_ciclass TextureCubeMipmapCase : public tcu::TestCase
429e5c31af7Sopenharmony_ci{
430e5c31af7Sopenharmony_cipublic:
431e5c31af7Sopenharmony_ci
432e5c31af7Sopenharmony_ci								TextureCubeMipmapCase		(tcu::TestContext&			testCtx,
433e5c31af7Sopenharmony_ci															 glu::RenderContext&		renderCtx,
434e5c31af7Sopenharmony_ci															 const glu::ContextInfo&	renderCtxInfo,
435e5c31af7Sopenharmony_ci															 const char*				name,
436e5c31af7Sopenharmony_ci															 const char*				desc,
437e5c31af7Sopenharmony_ci															 CoordType					coordType,
438e5c31af7Sopenharmony_ci															 deUint32					minFilter,
439e5c31af7Sopenharmony_ci															 deUint32					wrapS,
440e5c31af7Sopenharmony_ci															 deUint32					wrapT,
441e5c31af7Sopenharmony_ci															 deUint32					format,
442e5c31af7Sopenharmony_ci															 deUint32					dataType,
443e5c31af7Sopenharmony_ci															 int						size);
444e5c31af7Sopenharmony_ci								~TextureCubeMipmapCase		(void);
445e5c31af7Sopenharmony_ci
446e5c31af7Sopenharmony_ci	void						init						(void);
447e5c31af7Sopenharmony_ci	void						deinit						(void);
448e5c31af7Sopenharmony_ci	IterateResult				iterate						(void);
449e5c31af7Sopenharmony_ci
450e5c31af7Sopenharmony_ciprivate:
451e5c31af7Sopenharmony_ci								TextureCubeMipmapCase		(const TextureCubeMipmapCase& other);
452e5c31af7Sopenharmony_ci	TextureCubeMipmapCase&		operator=					(const TextureCubeMipmapCase& other);
453e5c31af7Sopenharmony_ci
454e5c31af7Sopenharmony_ci	glu::RenderContext&			m_renderCtx;
455e5c31af7Sopenharmony_ci	const glu::ContextInfo&		m_renderCtxInfo;
456e5c31af7Sopenharmony_ci
457e5c31af7Sopenharmony_ci	CoordType					m_coordType;
458e5c31af7Sopenharmony_ci	deUint32					m_minFilter;
459e5c31af7Sopenharmony_ci	deUint32					m_wrapS;
460e5c31af7Sopenharmony_ci	deUint32					m_wrapT;
461e5c31af7Sopenharmony_ci	deUint32					m_format;
462e5c31af7Sopenharmony_ci	deUint32					m_dataType;
463e5c31af7Sopenharmony_ci	int							m_size;
464e5c31af7Sopenharmony_ci
465e5c31af7Sopenharmony_ci	glu::TextureCube*			m_texture;
466e5c31af7Sopenharmony_ci	TextureRenderer				m_renderer;
467e5c31af7Sopenharmony_ci};
468e5c31af7Sopenharmony_ci
469e5c31af7Sopenharmony_ciTextureCubeMipmapCase::TextureCubeMipmapCase (tcu::TestContext&			testCtx,
470e5c31af7Sopenharmony_ci											  glu::RenderContext&		renderCtx,
471e5c31af7Sopenharmony_ci											  const glu::ContextInfo&	renderCtxInfo,
472e5c31af7Sopenharmony_ci											  const char*				name,
473e5c31af7Sopenharmony_ci											  const char*				desc,
474e5c31af7Sopenharmony_ci											  CoordType					coordType,
475e5c31af7Sopenharmony_ci											  deUint32					minFilter,
476e5c31af7Sopenharmony_ci											  deUint32					wrapS,
477e5c31af7Sopenharmony_ci											  deUint32					wrapT,
478e5c31af7Sopenharmony_ci											  deUint32					format,
479e5c31af7Sopenharmony_ci											  deUint32					dataType,
480e5c31af7Sopenharmony_ci											  int						size)
481e5c31af7Sopenharmony_ci	: TestCase			(testCtx, name, desc)
482e5c31af7Sopenharmony_ci	, m_renderCtx		(renderCtx)
483e5c31af7Sopenharmony_ci	, m_renderCtxInfo	(renderCtxInfo)
484e5c31af7Sopenharmony_ci	, m_coordType		(coordType)
485e5c31af7Sopenharmony_ci	, m_minFilter		(minFilter)
486e5c31af7Sopenharmony_ci	, m_wrapS			(wrapS)
487e5c31af7Sopenharmony_ci	, m_wrapT			(wrapT)
488e5c31af7Sopenharmony_ci	, m_format			(format)
489e5c31af7Sopenharmony_ci	, m_dataType		(dataType)
490e5c31af7Sopenharmony_ci	, m_size			(size)
491e5c31af7Sopenharmony_ci	, m_texture			(DE_NULL)
492e5c31af7Sopenharmony_ci	, m_renderer		(renderCtx, testCtx.getLog(), glu::GLSL_VERSION_100_ES,
493e5c31af7Sopenharmony_ci						 renderCtxInfo.isFragmentHighPrecisionSupported() ? glu::PRECISION_HIGHP // Use highp if available.
494e5c31af7Sopenharmony_ci																		  : glu::PRECISION_MEDIUMP)
495e5c31af7Sopenharmony_ci{
496e5c31af7Sopenharmony_ci}
497e5c31af7Sopenharmony_ci
498e5c31af7Sopenharmony_ciTextureCubeMipmapCase::~TextureCubeMipmapCase (void)
499e5c31af7Sopenharmony_ci{
500e5c31af7Sopenharmony_ci	deinit();
501e5c31af7Sopenharmony_ci}
502e5c31af7Sopenharmony_ci
503e5c31af7Sopenharmony_civoid TextureCubeMipmapCase::init (void)
504e5c31af7Sopenharmony_ci{
505e5c31af7Sopenharmony_ci	if (!m_renderCtxInfo.isFragmentHighPrecisionSupported())
506e5c31af7Sopenharmony_ci		m_testCtx.getLog() << TestLog::Message << "Warning: High precision not supported in fragment shaders." << TestLog::EndMessage;
507e5c31af7Sopenharmony_ci
508e5c31af7Sopenharmony_ci	if (m_coordType == COORDTYPE_PROJECTED && m_renderCtx.getRenderTarget().getNumSamples() > 0)
509e5c31af7Sopenharmony_ci		throw tcu::NotSupportedError("Projected lookup validation not supported in multisample config");
510e5c31af7Sopenharmony_ci
511e5c31af7Sopenharmony_ci	m_texture = new TextureCube(m_renderCtx, m_format, m_dataType, m_size);
512e5c31af7Sopenharmony_ci
513e5c31af7Sopenharmony_ci	int numLevels = deLog2Floor32(m_size)+1;
514e5c31af7Sopenharmony_ci
515e5c31af7Sopenharmony_ci	// Fill texture with colored grid.
516e5c31af7Sopenharmony_ci	for (int faceNdx = 0; faceNdx < tcu::CUBEFACE_LAST; faceNdx++)
517e5c31af7Sopenharmony_ci	{
518e5c31af7Sopenharmony_ci		for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
519e5c31af7Sopenharmony_ci		{
520e5c31af7Sopenharmony_ci			deUint32	step		= 0xff / (numLevels-1);
521e5c31af7Sopenharmony_ci			deUint32	inc			= deClamp32(step*levelNdx, 0x00, 0xff);
522e5c31af7Sopenharmony_ci			deUint32	dec			= 0xff - inc;
523e5c31af7Sopenharmony_ci			deUint32	rgb			= 0;
524e5c31af7Sopenharmony_ci
525e5c31af7Sopenharmony_ci			switch (faceNdx)
526e5c31af7Sopenharmony_ci			{
527e5c31af7Sopenharmony_ci				case 0: rgb = (inc << 16) | (dec << 8) | 255; break;
528e5c31af7Sopenharmony_ci				case 1: rgb = (255 << 16) | (inc << 8) | dec; break;
529e5c31af7Sopenharmony_ci				case 2: rgb = (dec << 16) | (255 << 8) | inc; break;
530e5c31af7Sopenharmony_ci				case 3: rgb = (dec << 16) | (inc << 8) | 255; break;
531e5c31af7Sopenharmony_ci				case 4: rgb = (255 << 16) | (dec << 8) | inc; break;
532e5c31af7Sopenharmony_ci				case 5: rgb = (inc << 16) | (255 << 8) | dec; break;
533e5c31af7Sopenharmony_ci			}
534e5c31af7Sopenharmony_ci
535e5c31af7Sopenharmony_ci			deUint32	color		= 0xff000000 | rgb;
536e5c31af7Sopenharmony_ci
537e5c31af7Sopenharmony_ci			m_texture->getRefTexture().allocLevel((tcu::CubeFace)faceNdx, levelNdx);
538e5c31af7Sopenharmony_ci			tcu::clear(m_texture->getRefTexture().getLevelFace(levelNdx, (tcu::CubeFace)faceNdx), tcu::RGBA(color).toVec());
539e5c31af7Sopenharmony_ci		}
540e5c31af7Sopenharmony_ci	}
541e5c31af7Sopenharmony_ci}
542e5c31af7Sopenharmony_ci
543e5c31af7Sopenharmony_civoid TextureCubeMipmapCase::deinit (void)
544e5c31af7Sopenharmony_ci{
545e5c31af7Sopenharmony_ci	delete m_texture;
546e5c31af7Sopenharmony_ci	m_texture = DE_NULL;
547e5c31af7Sopenharmony_ci
548e5c31af7Sopenharmony_ci	m_renderer.clear();
549e5c31af7Sopenharmony_ci}
550e5c31af7Sopenharmony_ci
551e5c31af7Sopenharmony_cistatic void randomPartition (vector<IVec4>& dst, de::Random& rnd, int x, int y, int width, int height)
552e5c31af7Sopenharmony_ci{
553e5c31af7Sopenharmony_ci	const int minWidth	= 8;
554e5c31af7Sopenharmony_ci	const int minHeight	= 8;
555e5c31af7Sopenharmony_ci
556e5c31af7Sopenharmony_ci	bool	partition		= rnd.getFloat() > 0.4f;
557e5c31af7Sopenharmony_ci	bool	partitionX		= partition && width > minWidth && rnd.getBool();
558e5c31af7Sopenharmony_ci	bool	partitionY		= partition && height > minHeight && !partitionX;
559e5c31af7Sopenharmony_ci
560e5c31af7Sopenharmony_ci	if (partitionX)
561e5c31af7Sopenharmony_ci	{
562e5c31af7Sopenharmony_ci		int split = width/2 + rnd.getInt(-width/4, +width/4);
563e5c31af7Sopenharmony_ci		randomPartition(dst, rnd, x, y, split, height);
564e5c31af7Sopenharmony_ci		randomPartition(dst, rnd, x+split, y, width-split, height);
565e5c31af7Sopenharmony_ci	}
566e5c31af7Sopenharmony_ci	else if (partitionY)
567e5c31af7Sopenharmony_ci	{
568e5c31af7Sopenharmony_ci		int split = height/2 + rnd.getInt(-height/4, +height/4);
569e5c31af7Sopenharmony_ci		randomPartition(dst, rnd, x, y, width, split);
570e5c31af7Sopenharmony_ci		randomPartition(dst, rnd, x, y+split, width, height-split);
571e5c31af7Sopenharmony_ci	}
572e5c31af7Sopenharmony_ci	else
573e5c31af7Sopenharmony_ci		dst.push_back(IVec4(x, y, width, height));
574e5c31af7Sopenharmony_ci}
575e5c31af7Sopenharmony_ci
576e5c31af7Sopenharmony_cistatic void computeGridLayout (vector<IVec4>& dst, int width, int height)
577e5c31af7Sopenharmony_ci{
578e5c31af7Sopenharmony_ci	de::Random rnd(7);
579e5c31af7Sopenharmony_ci	randomPartition(dst, rnd, 0, 0, width, height);
580e5c31af7Sopenharmony_ci}
581e5c31af7Sopenharmony_ci
582e5c31af7Sopenharmony_ciTextureCubeMipmapCase::IterateResult TextureCubeMipmapCase::iterate (void)
583e5c31af7Sopenharmony_ci{
584e5c31af7Sopenharmony_ci	const deUint32			magFilter			= GL_NEAREST;
585e5c31af7Sopenharmony_ci	const int				texWidth			= m_texture->getRefTexture().getSize();
586e5c31af7Sopenharmony_ci	const int				texHeight			= m_texture->getRefTexture().getSize();
587e5c31af7Sopenharmony_ci	const int				defViewportWidth	= texWidth*2;
588e5c31af7Sopenharmony_ci	const int				defViewportHeight	= texHeight*2;
589e5c31af7Sopenharmony_ci
590e5c31af7Sopenharmony_ci	const glw::Functions&	gl					= m_renderCtx.getFunctions();
591e5c31af7Sopenharmony_ci	const RandomViewport	viewport			(m_renderCtx.getRenderTarget(), defViewportWidth, defViewportHeight, deStringHash(getName()));
592e5c31af7Sopenharmony_ci
593e5c31af7Sopenharmony_ci	const bool				isProjected			= m_coordType == COORDTYPE_PROJECTED;
594e5c31af7Sopenharmony_ci	const bool				useLodBias			= m_coordType == COORDTYPE_BASIC_BIAS;
595e5c31af7Sopenharmony_ci
596e5c31af7Sopenharmony_ci	vector<float>			texCoord;
597e5c31af7Sopenharmony_ci	tcu::Surface			renderedFrame		(viewport.width, viewport.height);
598e5c31af7Sopenharmony_ci
599e5c31af7Sopenharmony_ci	// Bail out if rendertarget is too small.
600e5c31af7Sopenharmony_ci	if (viewport.width < defViewportWidth/2 || viewport.height < defViewportHeight/2)
601e5c31af7Sopenharmony_ci		throw tcu::NotSupportedError("Too small viewport", "", __FILE__, __LINE__);
602e5c31af7Sopenharmony_ci
603e5c31af7Sopenharmony_ci	bool isES3Compatible = m_renderCtxInfo.isES3Compatible();
604e5c31af7Sopenharmony_ci
605e5c31af7Sopenharmony_ci	// Upload texture data.
606e5c31af7Sopenharmony_ci	m_texture->upload();
607e5c31af7Sopenharmony_ci
608e5c31af7Sopenharmony_ci	// Bind gradient texture and setup sampler parameters.
609e5c31af7Sopenharmony_ci	gl.bindTexture	(GL_TEXTURE_CUBE_MAP, m_texture->getGLTexture());
610e5c31af7Sopenharmony_ci	gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S,		m_wrapS);
611e5c31af7Sopenharmony_ci	gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T,		m_wrapT);
612e5c31af7Sopenharmony_ci	gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER,	m_minFilter);
613e5c31af7Sopenharmony_ci	gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER,	magFilter);
614e5c31af7Sopenharmony_ci
615e5c31af7Sopenharmony_ci	GLU_EXPECT_NO_ERROR(gl.getError(), "After texture setup");
616e5c31af7Sopenharmony_ci
617e5c31af7Sopenharmony_ci	// Compute grid.
618e5c31af7Sopenharmony_ci	vector<IVec4> gridLayout;
619e5c31af7Sopenharmony_ci	computeGridLayout(gridLayout, viewport.width, viewport.height);
620e5c31af7Sopenharmony_ci
621e5c31af7Sopenharmony_ci	// Bias values.
622e5c31af7Sopenharmony_ci	static const float s_bias[] = { 1.0f, -2.0f, 0.8f, -0.5f, 1.5f, 0.9f, 2.0f, 4.0f };
623e5c31af7Sopenharmony_ci
624e5c31af7Sopenharmony_ci	// Projection values \note Less agressive than in 2D case due to smaller quads.
625e5c31af7Sopenharmony_ci	static const Vec4 s_projections[] =
626e5c31af7Sopenharmony_ci	{
627e5c31af7Sopenharmony_ci		Vec4(1.2f, 1.0f, 0.7f, 1.0f),
628e5c31af7Sopenharmony_ci		Vec4(1.3f, 0.8f, 0.6f, 1.1f),
629e5c31af7Sopenharmony_ci		Vec4(0.8f, 1.0f, 1.2f, 0.8f),
630e5c31af7Sopenharmony_ci		Vec4(1.2f, 1.0f, 1.3f, 0.9f)
631e5c31af7Sopenharmony_ci	};
632e5c31af7Sopenharmony_ci
633e5c31af7Sopenharmony_ci	// Render with GL
634e5c31af7Sopenharmony_ci	for (int cellNdx = 0; cellNdx < (int)gridLayout.size(); cellNdx++)
635e5c31af7Sopenharmony_ci	{
636e5c31af7Sopenharmony_ci		const int			curX		= gridLayout[cellNdx].x();
637e5c31af7Sopenharmony_ci		const int			curY		= gridLayout[cellNdx].y();
638e5c31af7Sopenharmony_ci		const int			curW		= gridLayout[cellNdx].z();
639e5c31af7Sopenharmony_ci		const int			curH		= gridLayout[cellNdx].w();
640e5c31af7Sopenharmony_ci		const tcu::CubeFace	cubeFace	= (tcu::CubeFace)(cellNdx % tcu::CUBEFACE_LAST);
641e5c31af7Sopenharmony_ci		RenderParams		params		(TEXTURETYPE_CUBE);
642e5c31af7Sopenharmony_ci
643e5c31af7Sopenharmony_ci		DE_ASSERT(m_coordType != COORDTYPE_AFFINE); // Not supported.
644e5c31af7Sopenharmony_ci		computeQuadTexCoordCube(texCoord, cubeFace);
645e5c31af7Sopenharmony_ci
646e5c31af7Sopenharmony_ci		if (isProjected)
647e5c31af7Sopenharmony_ci		{
648e5c31af7Sopenharmony_ci			params.flags	|= ReferenceParams::PROJECTED;
649e5c31af7Sopenharmony_ci			params.w		 = s_projections[cellNdx % DE_LENGTH_OF_ARRAY(s_projections)];
650e5c31af7Sopenharmony_ci		}
651e5c31af7Sopenharmony_ci
652e5c31af7Sopenharmony_ci		if (useLodBias)
653e5c31af7Sopenharmony_ci		{
654e5c31af7Sopenharmony_ci			params.flags	|= ReferenceParams::USE_BIAS;
655e5c31af7Sopenharmony_ci			params.bias		 = s_bias[cellNdx % DE_LENGTH_OF_ARRAY(s_bias)];
656e5c31af7Sopenharmony_ci		}
657e5c31af7Sopenharmony_ci
658e5c31af7Sopenharmony_ci		// Render with GL.
659e5c31af7Sopenharmony_ci		gl.viewport(viewport.x+curX, viewport.y+curY, curW, curH);
660e5c31af7Sopenharmony_ci		m_renderer.renderQuad(0, &texCoord[0], params);
661e5c31af7Sopenharmony_ci	}
662e5c31af7Sopenharmony_ci	GLU_EXPECT_NO_ERROR(gl.getError(), "Draw");
663e5c31af7Sopenharmony_ci
664e5c31af7Sopenharmony_ci	// Read result.
665e5c31af7Sopenharmony_ci	glu::readPixels(m_renderCtx, viewport.x, viewport.y, renderedFrame.getAccess());
666e5c31af7Sopenharmony_ci	GLU_EXPECT_NO_ERROR(gl.getError(), "Read pixels");
667e5c31af7Sopenharmony_ci
668e5c31af7Sopenharmony_ci	// Render reference and compare
669e5c31af7Sopenharmony_ci	{
670e5c31af7Sopenharmony_ci		tcu::Surface			referenceFrame		(viewport.width, viewport.height);
671e5c31af7Sopenharmony_ci		tcu::Surface			errorMask			(viewport.width, viewport.height);
672e5c31af7Sopenharmony_ci		int						numFailedPixels		= 0;
673e5c31af7Sopenharmony_ci		ReferenceParams			params				(TEXTURETYPE_CUBE);
674e5c31af7Sopenharmony_ci		tcu::LookupPrecision	lookupPrec;
675e5c31af7Sopenharmony_ci		tcu::LodPrecision		lodPrec;
676e5c31af7Sopenharmony_ci
677e5c31af7Sopenharmony_ci		// Params for rendering reference
678e5c31af7Sopenharmony_ci		params.sampler					= glu::mapGLSampler(m_wrapS, m_wrapT, m_minFilter, magFilter);
679e5c31af7Sopenharmony_ci		params.sampler.seamlessCubeMap	= isES3Compatible;
680e5c31af7Sopenharmony_ci		params.lodMode					= LODMODE_EXACT;
681e5c31af7Sopenharmony_ci
682e5c31af7Sopenharmony_ci		// Comparison parameters
683e5c31af7Sopenharmony_ci		lookupPrec.colorMask			= getCompareMask(m_renderCtx.getRenderTarget().getPixelFormat());
684e5c31af7Sopenharmony_ci		lookupPrec.colorThreshold		= tcu::computeFixedPointThreshold(max(getBitsVec(m_renderCtx.getRenderTarget().getPixelFormat())-2, IVec4(0)));
685e5c31af7Sopenharmony_ci		lookupPrec.coordBits			= isProjected ? tcu::IVec3(8) : tcu::IVec3(10);
686e5c31af7Sopenharmony_ci		lookupPrec.uvwBits				= tcu::IVec3(5,5,0);
687e5c31af7Sopenharmony_ci		lodPrec.derivateBits			= 10;
688e5c31af7Sopenharmony_ci		lodPrec.lodBits					= isES3Compatible ? 3 : 4;
689e5c31af7Sopenharmony_ci		lodPrec.lodBits					= isProjected ? lodPrec.lodBits : 6;
690e5c31af7Sopenharmony_ci
691e5c31af7Sopenharmony_ci		for (int cellNdx = 0; cellNdx < (int)gridLayout.size(); cellNdx++)
692e5c31af7Sopenharmony_ci		{
693e5c31af7Sopenharmony_ci			const int				curX		= gridLayout[cellNdx].x();
694e5c31af7Sopenharmony_ci			const int				curY		= gridLayout[cellNdx].y();
695e5c31af7Sopenharmony_ci			const int				curW		= gridLayout[cellNdx].z();
696e5c31af7Sopenharmony_ci			const int				curH		= gridLayout[cellNdx].w();
697e5c31af7Sopenharmony_ci			const tcu::CubeFace		cubeFace	= (tcu::CubeFace)(cellNdx % tcu::CUBEFACE_LAST);
698e5c31af7Sopenharmony_ci
699e5c31af7Sopenharmony_ci			DE_ASSERT(m_coordType != COORDTYPE_AFFINE); // Not supported.
700e5c31af7Sopenharmony_ci			computeQuadTexCoordCube(texCoord, cubeFace);
701e5c31af7Sopenharmony_ci
702e5c31af7Sopenharmony_ci			if (isProjected)
703e5c31af7Sopenharmony_ci			{
704e5c31af7Sopenharmony_ci				params.flags	|= ReferenceParams::PROJECTED;
705e5c31af7Sopenharmony_ci				params.w		 = s_projections[cellNdx % DE_LENGTH_OF_ARRAY(s_projections)];
706e5c31af7Sopenharmony_ci			}
707e5c31af7Sopenharmony_ci
708e5c31af7Sopenharmony_ci			if (useLodBias)
709e5c31af7Sopenharmony_ci			{
710e5c31af7Sopenharmony_ci				params.flags	|= ReferenceParams::USE_BIAS;
711e5c31af7Sopenharmony_ci				params.bias		 = s_bias[cellNdx % DE_LENGTH_OF_ARRAY(s_bias)];
712e5c31af7Sopenharmony_ci			}
713e5c31af7Sopenharmony_ci
714e5c31af7Sopenharmony_ci			// Render ideal reference.
715e5c31af7Sopenharmony_ci			{
716e5c31af7Sopenharmony_ci				tcu::SurfaceAccess idealDst(referenceFrame, m_renderCtx.getRenderTarget().getPixelFormat(), curX, curY, curW, curH);
717e5c31af7Sopenharmony_ci				sampleTexture(idealDst, m_texture->getRefTexture(), &texCoord[0], params);
718e5c31af7Sopenharmony_ci			}
719e5c31af7Sopenharmony_ci
720e5c31af7Sopenharmony_ci			// Compare this cell
721e5c31af7Sopenharmony_ci			numFailedPixels += computeTextureLookupDiff(tcu::getSubregion(renderedFrame.getAccess(), curX, curY, curW, curH),
722e5c31af7Sopenharmony_ci														tcu::getSubregion(referenceFrame.getAccess(), curX, curY, curW, curH),
723e5c31af7Sopenharmony_ci														tcu::getSubregion(errorMask.getAccess(), curX, curY, curW, curH),
724e5c31af7Sopenharmony_ci														m_texture->getRefTexture(), &texCoord[0], params,
725e5c31af7Sopenharmony_ci														lookupPrec, lodPrec, m_testCtx.getWatchDog());
726e5c31af7Sopenharmony_ci		}
727e5c31af7Sopenharmony_ci
728e5c31af7Sopenharmony_ci		if (numFailedPixels > 0)
729e5c31af7Sopenharmony_ci			m_testCtx.getLog() << TestLog::Message << "ERROR: Image verification failed, found " << numFailedPixels << " invalid pixels!" << TestLog::EndMessage;
730e5c31af7Sopenharmony_ci
731e5c31af7Sopenharmony_ci		m_testCtx.getLog() << TestLog::ImageSet("Result", "Verification result")
732e5c31af7Sopenharmony_ci						   << TestLog::Image("Rendered", "Rendered image", renderedFrame);
733e5c31af7Sopenharmony_ci
734e5c31af7Sopenharmony_ci		if (numFailedPixels > 0)
735e5c31af7Sopenharmony_ci		{
736e5c31af7Sopenharmony_ci			m_testCtx.getLog() << TestLog::Image("Reference", "Ideal reference", referenceFrame)
737e5c31af7Sopenharmony_ci							   << TestLog::Image("ErrorMask", "Error mask", errorMask);
738e5c31af7Sopenharmony_ci		}
739e5c31af7Sopenharmony_ci
740e5c31af7Sopenharmony_ci		m_testCtx.getLog() << TestLog::EndImageSet;
741e5c31af7Sopenharmony_ci
742e5c31af7Sopenharmony_ci		{
743e5c31af7Sopenharmony_ci			const bool isOk = numFailedPixels == 0;
744e5c31af7Sopenharmony_ci			m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS	: QP_TEST_RESULT_FAIL,
745e5c31af7Sopenharmony_ci									isOk ? "Pass"				: "Image verification failed");
746e5c31af7Sopenharmony_ci		}
747e5c31af7Sopenharmony_ci	}
748e5c31af7Sopenharmony_ci
749e5c31af7Sopenharmony_ci	return STOP;
750e5c31af7Sopenharmony_ci}
751e5c31af7Sopenharmony_ci
752e5c31af7Sopenharmony_ci// Texture2DGenMipmapCase
753e5c31af7Sopenharmony_ci
754e5c31af7Sopenharmony_ciclass Texture2DGenMipmapCase : public tcu::TestCase
755e5c31af7Sopenharmony_ci{
756e5c31af7Sopenharmony_cipublic:
757e5c31af7Sopenharmony_ci
758e5c31af7Sopenharmony_ci								Texture2DGenMipmapCase		(tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const char* name, const char* desc, deUint32 format, deUint32 dataType, deUint32 hint, int width, int height);
759e5c31af7Sopenharmony_ci								~Texture2DGenMipmapCase		(void);
760e5c31af7Sopenharmony_ci
761e5c31af7Sopenharmony_ci	void						init						(void);
762e5c31af7Sopenharmony_ci	void						deinit						(void);
763e5c31af7Sopenharmony_ci	IterateResult				iterate						(void);
764e5c31af7Sopenharmony_ci
765e5c31af7Sopenharmony_ciprivate:
766e5c31af7Sopenharmony_ci								Texture2DGenMipmapCase		(const Texture2DGenMipmapCase& other);
767e5c31af7Sopenharmony_ci	Texture2DGenMipmapCase&		operator=					(const Texture2DGenMipmapCase& other);
768e5c31af7Sopenharmony_ci
769e5c31af7Sopenharmony_ci	glu::RenderContext&			m_renderCtx;
770e5c31af7Sopenharmony_ci
771e5c31af7Sopenharmony_ci	deUint32					m_format;
772e5c31af7Sopenharmony_ci	deUint32					m_dataType;
773e5c31af7Sopenharmony_ci	deUint32					m_hint;
774e5c31af7Sopenharmony_ci	int							m_width;
775e5c31af7Sopenharmony_ci	int							m_height;
776e5c31af7Sopenharmony_ci
777e5c31af7Sopenharmony_ci	glu::Texture2D*				m_texture;
778e5c31af7Sopenharmony_ci	TextureRenderer				m_renderer;
779e5c31af7Sopenharmony_ci};
780e5c31af7Sopenharmony_ci
781e5c31af7Sopenharmony_ciTexture2DGenMipmapCase::Texture2DGenMipmapCase (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const char* name, const char* desc, deUint32 format, deUint32 dataType, deUint32 hint, int width, int height)
782e5c31af7Sopenharmony_ci	: TestCase			(testCtx, name, desc)
783e5c31af7Sopenharmony_ci	, m_renderCtx		(renderCtx)
784e5c31af7Sopenharmony_ci	, m_format			(format)
785e5c31af7Sopenharmony_ci	, m_dataType		(dataType)
786e5c31af7Sopenharmony_ci	, m_hint			(hint)
787e5c31af7Sopenharmony_ci	, m_width			(width)
788e5c31af7Sopenharmony_ci	, m_height			(height)
789e5c31af7Sopenharmony_ci	, m_texture			(DE_NULL)
790e5c31af7Sopenharmony_ci	, m_renderer		(renderCtx, testCtx.getLog(), glu::GLSL_VERSION_100_ES, glu::PRECISION_MEDIUMP)
791e5c31af7Sopenharmony_ci{
792e5c31af7Sopenharmony_ci}
793e5c31af7Sopenharmony_ci
794e5c31af7Sopenharmony_ciTexture2DGenMipmapCase::~Texture2DGenMipmapCase (void)
795e5c31af7Sopenharmony_ci{
796e5c31af7Sopenharmony_ci	deinit();
797e5c31af7Sopenharmony_ci}
798e5c31af7Sopenharmony_ci
799e5c31af7Sopenharmony_civoid Texture2DGenMipmapCase::init (void)
800e5c31af7Sopenharmony_ci{
801e5c31af7Sopenharmony_ci	DE_ASSERT(!m_texture);
802e5c31af7Sopenharmony_ci	m_texture = new Texture2D(m_renderCtx, m_format, m_dataType, m_width, m_height);
803e5c31af7Sopenharmony_ci}
804e5c31af7Sopenharmony_ci
805e5c31af7Sopenharmony_civoid Texture2DGenMipmapCase::deinit (void)
806e5c31af7Sopenharmony_ci{
807e5c31af7Sopenharmony_ci	delete m_texture;
808e5c31af7Sopenharmony_ci	m_texture = DE_NULL;
809e5c31af7Sopenharmony_ci
810e5c31af7Sopenharmony_ci	m_renderer.clear();
811e5c31af7Sopenharmony_ci}
812e5c31af7Sopenharmony_ci
813e5c31af7Sopenharmony_ciTexture2DGenMipmapCase::IterateResult Texture2DGenMipmapCase::iterate (void)
814e5c31af7Sopenharmony_ci{
815e5c31af7Sopenharmony_ci	const glw::Functions&	gl					= m_renderCtx.getFunctions();
816e5c31af7Sopenharmony_ci
817e5c31af7Sopenharmony_ci	const deUint32			minFilter			= GL_NEAREST_MIPMAP_NEAREST;
818e5c31af7Sopenharmony_ci	const deUint32			magFilter			= GL_NEAREST;
819e5c31af7Sopenharmony_ci	const deUint32			wrapS				= GL_CLAMP_TO_EDGE;
820e5c31af7Sopenharmony_ci	const deUint32			wrapT				= GL_CLAMP_TO_EDGE;
821e5c31af7Sopenharmony_ci
822e5c31af7Sopenharmony_ci	const int				numLevels			= deLog2Floor32(de::max(m_width, m_height))+1;
823e5c31af7Sopenharmony_ci
824e5c31af7Sopenharmony_ci	tcu::Texture2D			resultTexture		(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), m_texture->getRefTexture().getWidth(), m_texture->getRefTexture().getHeight(), isES2Context(m_renderCtx.getType()));
825e5c31af7Sopenharmony_ci
826e5c31af7Sopenharmony_ci	vector<float>			texCoord;
827e5c31af7Sopenharmony_ci
828e5c31af7Sopenharmony_ci	// Initialize texture level 0 with colored grid.
829e5c31af7Sopenharmony_ci	m_texture->getRefTexture().allocLevel(0);
830e5c31af7Sopenharmony_ci	tcu::fillWithGrid(m_texture->getRefTexture().getLevel(0), 8, tcu::Vec4(1.0f, 0.5f, 0.0f, 0.5f), tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f));
831e5c31af7Sopenharmony_ci
832e5c31af7Sopenharmony_ci	// Upload data and setup params.
833e5c31af7Sopenharmony_ci	m_texture->upload();
834e5c31af7Sopenharmony_ci
835e5c31af7Sopenharmony_ci	gl.bindTexture	(GL_TEXTURE_2D, m_texture->getGLTexture());
836e5c31af7Sopenharmony_ci	gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,		wrapS);
837e5c31af7Sopenharmony_ci	gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,		wrapT);
838e5c31af7Sopenharmony_ci	gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,	minFilter);
839e5c31af7Sopenharmony_ci	gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,	magFilter);
840e5c31af7Sopenharmony_ci	GLU_EXPECT_NO_ERROR(gl.getError(), "After texture setup");
841e5c31af7Sopenharmony_ci
842e5c31af7Sopenharmony_ci	// Generate mipmap.
843e5c31af7Sopenharmony_ci	gl.hint(GL_GENERATE_MIPMAP_HINT, m_hint);
844e5c31af7Sopenharmony_ci	gl.generateMipmap(GL_TEXTURE_2D);
845e5c31af7Sopenharmony_ci	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenerateMipmap()");
846e5c31af7Sopenharmony_ci
847e5c31af7Sopenharmony_ci	// Use (0, 0) -> (1, 1) texture coordinates.
848e5c31af7Sopenharmony_ci	computeQuadTexCoord2D(texCoord, Vec2(0.0f, 0.0f), Vec2(1.0f, 1.0f));
849e5c31af7Sopenharmony_ci
850e5c31af7Sopenharmony_ci	// Fetch resulting texture by rendering.
851e5c31af7Sopenharmony_ci	for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
852e5c31af7Sopenharmony_ci	{
853e5c31af7Sopenharmony_ci		const int				levelWidth		= de::max(1, m_width >> levelNdx);
854e5c31af7Sopenharmony_ci		const int				levelHeight		= de::max(1, m_height >> levelNdx);
855e5c31af7Sopenharmony_ci		const RandomViewport	viewport		(m_renderCtx.getRenderTarget(), levelWidth, levelHeight, deStringHash(getName()) + levelNdx);
856e5c31af7Sopenharmony_ci
857e5c31af7Sopenharmony_ci		gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height);
858e5c31af7Sopenharmony_ci		m_renderer.renderQuad(0, &texCoord[0], TEXTURETYPE_2D);
859e5c31af7Sopenharmony_ci
860e5c31af7Sopenharmony_ci		resultTexture.allocLevel(levelNdx);
861e5c31af7Sopenharmony_ci		glu::readPixels(m_renderCtx, viewport.x, viewport.y, resultTexture.getLevel(levelNdx));
862e5c31af7Sopenharmony_ci	}
863e5c31af7Sopenharmony_ci
864e5c31af7Sopenharmony_ci	// Compare results
865e5c31af7Sopenharmony_ci	{
866e5c31af7Sopenharmony_ci
867e5c31af7Sopenharmony_ci		const IVec4			framebufferBits		= max(getBitsVec(m_renderCtx.getRenderTarget().getPixelFormat())-2, IVec4(0));
868e5c31af7Sopenharmony_ci		const IVec4			formatBits			= tcu::getTextureFormatBitDepth(glu::mapGLTransferFormat(m_format, m_dataType));
869e5c31af7Sopenharmony_ci		const tcu::BVec4	formatMask			= greaterThan(formatBits, IVec4(0));
870e5c31af7Sopenharmony_ci		const IVec4			cmpBits				= select(min(framebufferBits, formatBits), framebufferBits, formatMask);
871e5c31af7Sopenharmony_ci		GenMipmapPrecision	comparePrec;
872e5c31af7Sopenharmony_ci
873e5c31af7Sopenharmony_ci		comparePrec.colorMask		= getCompareMask(m_renderCtx.getRenderTarget().getPixelFormat());
874e5c31af7Sopenharmony_ci		comparePrec.colorThreshold	= tcu::computeFixedPointThreshold(cmpBits);
875e5c31af7Sopenharmony_ci		comparePrec.filterBits		= tcu::IVec3(4, 4, 0);
876e5c31af7Sopenharmony_ci
877e5c31af7Sopenharmony_ci		const qpTestResult compareResult = compareGenMipmapResult(m_testCtx.getLog(), resultTexture, m_texture->getRefTexture(), comparePrec);
878e5c31af7Sopenharmony_ci
879e5c31af7Sopenharmony_ci		m_testCtx.setTestResult(compareResult, compareResult == QP_TEST_RESULT_PASS				? "Pass" :
880e5c31af7Sopenharmony_ci											   compareResult == QP_TEST_RESULT_QUALITY_WARNING	? "Low-quality method used"	:
881e5c31af7Sopenharmony_ci											   compareResult == QP_TEST_RESULT_FAIL				? "Image comparison failed"	: "");
882e5c31af7Sopenharmony_ci	}
883e5c31af7Sopenharmony_ci
884e5c31af7Sopenharmony_ci	return STOP;
885e5c31af7Sopenharmony_ci}
886e5c31af7Sopenharmony_ci
887e5c31af7Sopenharmony_ci// TextureCubeGenMipmapCase
888e5c31af7Sopenharmony_ci
889e5c31af7Sopenharmony_ciclass TextureCubeGenMipmapCase : public tcu::TestCase
890e5c31af7Sopenharmony_ci{
891e5c31af7Sopenharmony_cipublic:
892e5c31af7Sopenharmony_ci
893e5c31af7Sopenharmony_ci								TextureCubeGenMipmapCase		(tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const char* name, const char* desc, deUint32 format, deUint32 dataType, deUint32 hint, int size);
894e5c31af7Sopenharmony_ci								~TextureCubeGenMipmapCase		(void);
895e5c31af7Sopenharmony_ci
896e5c31af7Sopenharmony_ci	void						init							(void);
897e5c31af7Sopenharmony_ci	void						deinit							(void);
898e5c31af7Sopenharmony_ci	IterateResult				iterate							(void);
899e5c31af7Sopenharmony_ci
900e5c31af7Sopenharmony_ciprivate:
901e5c31af7Sopenharmony_ci								TextureCubeGenMipmapCase		(const TextureCubeGenMipmapCase& other);
902e5c31af7Sopenharmony_ci	TextureCubeGenMipmapCase&	operator=						(const TextureCubeGenMipmapCase& other);
903e5c31af7Sopenharmony_ci
904e5c31af7Sopenharmony_ci	glu::RenderContext&			m_renderCtx;
905e5c31af7Sopenharmony_ci
906e5c31af7Sopenharmony_ci	deUint32					m_format;
907e5c31af7Sopenharmony_ci	deUint32					m_dataType;
908e5c31af7Sopenharmony_ci	deUint32					m_hint;
909e5c31af7Sopenharmony_ci	int							m_size;
910e5c31af7Sopenharmony_ci
911e5c31af7Sopenharmony_ci	glu::TextureCube*			m_texture;
912e5c31af7Sopenharmony_ci	TextureRenderer				m_renderer;
913e5c31af7Sopenharmony_ci};
914e5c31af7Sopenharmony_ci
915e5c31af7Sopenharmony_ciTextureCubeGenMipmapCase::TextureCubeGenMipmapCase (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const char* name, const char* desc, deUint32 format, deUint32 dataType, deUint32 hint, int size)
916e5c31af7Sopenharmony_ci	: TestCase			(testCtx, name, desc)
917e5c31af7Sopenharmony_ci	, m_renderCtx		(renderCtx)
918e5c31af7Sopenharmony_ci	, m_format			(format)
919e5c31af7Sopenharmony_ci	, m_dataType		(dataType)
920e5c31af7Sopenharmony_ci	, m_hint			(hint)
921e5c31af7Sopenharmony_ci	, m_size			(size)
922e5c31af7Sopenharmony_ci	, m_texture			(DE_NULL)
923e5c31af7Sopenharmony_ci	, m_renderer		(renderCtx, testCtx.getLog(), glu::GLSL_VERSION_100_ES, glu::PRECISION_MEDIUMP)
924e5c31af7Sopenharmony_ci{
925e5c31af7Sopenharmony_ci}
926e5c31af7Sopenharmony_ci
927e5c31af7Sopenharmony_ciTextureCubeGenMipmapCase::~TextureCubeGenMipmapCase (void)
928e5c31af7Sopenharmony_ci{
929e5c31af7Sopenharmony_ci	deinit();
930e5c31af7Sopenharmony_ci}
931e5c31af7Sopenharmony_ci
932e5c31af7Sopenharmony_civoid TextureCubeGenMipmapCase::init (void)
933e5c31af7Sopenharmony_ci{
934e5c31af7Sopenharmony_ci	if (m_renderCtx.getRenderTarget().getWidth() < 3*m_size || m_renderCtx.getRenderTarget().getHeight() < 2*m_size)
935e5c31af7Sopenharmony_ci		throw tcu::NotSupportedError("Render target size must be at least (" + de::toString(3*m_size) + ", " + de::toString(2*m_size) + ")");
936e5c31af7Sopenharmony_ci
937e5c31af7Sopenharmony_ci	DE_ASSERT(!m_texture);
938e5c31af7Sopenharmony_ci	m_texture = new TextureCube(m_renderCtx, m_format, m_dataType, m_size);
939e5c31af7Sopenharmony_ci}
940e5c31af7Sopenharmony_ci
941e5c31af7Sopenharmony_civoid TextureCubeGenMipmapCase::deinit (void)
942e5c31af7Sopenharmony_ci{
943e5c31af7Sopenharmony_ci	delete m_texture;
944e5c31af7Sopenharmony_ci	m_texture = DE_NULL;
945e5c31af7Sopenharmony_ci
946e5c31af7Sopenharmony_ci	m_renderer.clear();
947e5c31af7Sopenharmony_ci}
948e5c31af7Sopenharmony_ci
949e5c31af7Sopenharmony_ciTextureCubeGenMipmapCase::IterateResult TextureCubeGenMipmapCase::iterate (void)
950e5c31af7Sopenharmony_ci{
951e5c31af7Sopenharmony_ci	const glw::Functions&	gl					= m_renderCtx.getFunctions();
952e5c31af7Sopenharmony_ci
953e5c31af7Sopenharmony_ci	const deUint32			minFilter			= GL_NEAREST_MIPMAP_NEAREST;
954e5c31af7Sopenharmony_ci	const deUint32			magFilter			= GL_NEAREST;
955e5c31af7Sopenharmony_ci	const deUint32			wrapS				= GL_CLAMP_TO_EDGE;
956e5c31af7Sopenharmony_ci	const deUint32			wrapT				= GL_CLAMP_TO_EDGE;
957e5c31af7Sopenharmony_ci
958e5c31af7Sopenharmony_ci	tcu::TextureCube		resultTexture		(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), m_size);
959e5c31af7Sopenharmony_ci
960e5c31af7Sopenharmony_ci	const int				numLevels			= deLog2Floor32(m_size)+1;
961e5c31af7Sopenharmony_ci	vector<float>			texCoord;
962e5c31af7Sopenharmony_ci
963e5c31af7Sopenharmony_ci	// Initialize texture level 0 with colored grid.
964e5c31af7Sopenharmony_ci	for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
965e5c31af7Sopenharmony_ci	{
966e5c31af7Sopenharmony_ci		Vec4 ca, cb; // Grid colors.
967e5c31af7Sopenharmony_ci
968e5c31af7Sopenharmony_ci		switch (face)
969e5c31af7Sopenharmony_ci		{
970e5c31af7Sopenharmony_ci			case 0: ca = Vec4(1.0f, 0.3f, 0.0f, 0.7f); cb = Vec4(0.0f, 0.0f, 1.0f, 1.0f); break;
971e5c31af7Sopenharmony_ci			case 1: ca = Vec4(0.0f, 1.0f, 0.5f, 0.5f); cb = Vec4(1.0f, 0.0f, 0.0f, 1.0f); break;
972e5c31af7Sopenharmony_ci			case 2: ca = Vec4(0.7f, 0.0f, 1.0f, 0.3f); cb = Vec4(0.0f, 1.0f, 0.0f, 1.0f); break;
973e5c31af7Sopenharmony_ci			case 3: ca = Vec4(0.0f, 0.3f, 1.0f, 1.0f); cb = Vec4(1.0f, 0.0f, 0.0f, 0.7f); break;
974e5c31af7Sopenharmony_ci			case 4: ca = Vec4(1.0f, 0.0f, 0.5f, 1.0f); cb = Vec4(0.0f, 1.0f, 0.0f, 0.5f); break;
975e5c31af7Sopenharmony_ci			case 5: ca = Vec4(0.7f, 1.0f, 0.0f, 1.0f); cb = Vec4(0.0f, 0.0f, 1.0f, 0.3f); break;
976e5c31af7Sopenharmony_ci		}
977e5c31af7Sopenharmony_ci
978e5c31af7Sopenharmony_ci		m_texture->getRefTexture().allocLevel((tcu::CubeFace)face, 0);
979e5c31af7Sopenharmony_ci		fillWithGrid(m_texture->getRefTexture().getLevelFace(0, (tcu::CubeFace)face), 8, ca, cb);
980e5c31af7Sopenharmony_ci	}
981e5c31af7Sopenharmony_ci
982e5c31af7Sopenharmony_ci	// Upload data and setup params.
983e5c31af7Sopenharmony_ci	m_texture->upload();
984e5c31af7Sopenharmony_ci
985e5c31af7Sopenharmony_ci	gl.bindTexture	(GL_TEXTURE_CUBE_MAP, m_texture->getGLTexture());
986e5c31af7Sopenharmony_ci	gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S,		wrapS);
987e5c31af7Sopenharmony_ci	gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T,		wrapT);
988e5c31af7Sopenharmony_ci	gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER,	minFilter);
989e5c31af7Sopenharmony_ci	gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER,	magFilter);
990e5c31af7Sopenharmony_ci	GLU_EXPECT_NO_ERROR(gl.getError(), "After texture setup");
991e5c31af7Sopenharmony_ci
992e5c31af7Sopenharmony_ci	// Generate mipmap.
993e5c31af7Sopenharmony_ci	gl.hint(GL_GENERATE_MIPMAP_HINT, m_hint);
994e5c31af7Sopenharmony_ci	gl.generateMipmap(GL_TEXTURE_CUBE_MAP);
995e5c31af7Sopenharmony_ci	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenerateMipmap()");
996e5c31af7Sopenharmony_ci
997e5c31af7Sopenharmony_ci	// Render all levels.
998e5c31af7Sopenharmony_ci	for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
999e5c31af7Sopenharmony_ci	{
1000e5c31af7Sopenharmony_ci		const int	levelWidth	= de::max(1, m_size >> levelNdx);
1001e5c31af7Sopenharmony_ci		const int	levelHeight	= de::max(1, m_size >> levelNdx);
1002e5c31af7Sopenharmony_ci
1003e5c31af7Sopenharmony_ci		for (int faceNdx = 0; faceNdx < tcu::CUBEFACE_LAST; faceNdx++)
1004e5c31af7Sopenharmony_ci		{
1005e5c31af7Sopenharmony_ci			const RandomViewport	viewport	(m_renderCtx.getRenderTarget(), levelWidth*3, levelHeight*2, deStringHash(getName()) ^ deInt32Hash(levelNdx + faceNdx));
1006e5c31af7Sopenharmony_ci			const tcu::CubeFace		face		= tcu::CubeFace(faceNdx);
1007e5c31af7Sopenharmony_ci
1008e5c31af7Sopenharmony_ci			computeQuadTexCoordCube(texCoord, face);
1009e5c31af7Sopenharmony_ci
1010e5c31af7Sopenharmony_ci			gl.viewport(viewport.x, viewport.y, levelWidth, levelHeight);
1011e5c31af7Sopenharmony_ci			m_renderer.renderQuad(0, &texCoord[0], TEXTURETYPE_CUBE);
1012e5c31af7Sopenharmony_ci
1013e5c31af7Sopenharmony_ci			resultTexture.allocLevel(face, levelNdx);
1014e5c31af7Sopenharmony_ci			glu::readPixels(m_renderCtx, viewport.x, viewport.y, resultTexture.getLevelFace(levelNdx, face));
1015e5c31af7Sopenharmony_ci		}
1016e5c31af7Sopenharmony_ci	}
1017e5c31af7Sopenharmony_ci
1018e5c31af7Sopenharmony_ci	// Compare results
1019e5c31af7Sopenharmony_ci	{
1020e5c31af7Sopenharmony_ci		const IVec4			framebufferBits		= max(getBitsVec(m_renderCtx.getRenderTarget().getPixelFormat())-2, IVec4(0));
1021e5c31af7Sopenharmony_ci		const IVec4			formatBits			= tcu::getTextureFormatBitDepth(glu::mapGLTransferFormat(m_format, m_dataType));
1022e5c31af7Sopenharmony_ci		const tcu::BVec4	formatMask			= greaterThan(formatBits, IVec4(0));
1023e5c31af7Sopenharmony_ci		const IVec4			cmpBits				= select(min(framebufferBits, formatBits), framebufferBits, formatMask);
1024e5c31af7Sopenharmony_ci		GenMipmapPrecision	comparePrec;
1025e5c31af7Sopenharmony_ci
1026e5c31af7Sopenharmony_ci		comparePrec.colorMask		= getCompareMask(m_renderCtx.getRenderTarget().getPixelFormat());
1027e5c31af7Sopenharmony_ci		comparePrec.colorThreshold	= tcu::computeFixedPointThreshold(cmpBits);
1028e5c31af7Sopenharmony_ci		comparePrec.filterBits		= tcu::IVec3(4, 4, 0);
1029e5c31af7Sopenharmony_ci
1030e5c31af7Sopenharmony_ci		const qpTestResult compareResult = compareGenMipmapResult(m_testCtx.getLog(), resultTexture, m_texture->getRefTexture(), comparePrec);
1031e5c31af7Sopenharmony_ci
1032e5c31af7Sopenharmony_ci		m_testCtx.setTestResult(compareResult, compareResult == QP_TEST_RESULT_PASS				? "Pass" :
1033e5c31af7Sopenharmony_ci											   compareResult == QP_TEST_RESULT_QUALITY_WARNING	? "Low-quality method used"	:
1034e5c31af7Sopenharmony_ci											   compareResult == QP_TEST_RESULT_FAIL				? "Image comparison failed"	: "");
1035e5c31af7Sopenharmony_ci	}
1036e5c31af7Sopenharmony_ci
1037e5c31af7Sopenharmony_ci	return STOP;
1038e5c31af7Sopenharmony_ci}
1039e5c31af7Sopenharmony_ci
1040e5c31af7Sopenharmony_ciTextureMipmapTests::TextureMipmapTests (Context& context)
1041e5c31af7Sopenharmony_ci	: TestCaseGroup(context, "mipmap", "Mipmapping tests")
1042e5c31af7Sopenharmony_ci{
1043e5c31af7Sopenharmony_ci}
1044e5c31af7Sopenharmony_ci
1045e5c31af7Sopenharmony_ciTextureMipmapTests::~TextureMipmapTests (void)
1046e5c31af7Sopenharmony_ci{
1047e5c31af7Sopenharmony_ci}
1048e5c31af7Sopenharmony_ci
1049e5c31af7Sopenharmony_civoid TextureMipmapTests::init (void)
1050e5c31af7Sopenharmony_ci{
1051e5c31af7Sopenharmony_ci	tcu::TestCaseGroup* group2D		= new tcu::TestCaseGroup(m_testCtx, "2d",	"2D Texture Mipmapping");
1052e5c31af7Sopenharmony_ci	tcu::TestCaseGroup*	groupCube	= new tcu::TestCaseGroup(m_testCtx, "cube",	"Cube Map Filtering");
1053e5c31af7Sopenharmony_ci	addChild(group2D);
1054e5c31af7Sopenharmony_ci	addChild(groupCube);
1055e5c31af7Sopenharmony_ci
1056e5c31af7Sopenharmony_ci	static const struct
1057e5c31af7Sopenharmony_ci	{
1058e5c31af7Sopenharmony_ci		const char*		name;
1059e5c31af7Sopenharmony_ci		deUint32		mode;
1060e5c31af7Sopenharmony_ci	} wrapModes[] =
1061e5c31af7Sopenharmony_ci	{
1062e5c31af7Sopenharmony_ci		{ "clamp",		GL_CLAMP_TO_EDGE },
1063e5c31af7Sopenharmony_ci		{ "repeat",		GL_REPEAT },
1064e5c31af7Sopenharmony_ci		{ "mirror",		GL_MIRRORED_REPEAT }
1065e5c31af7Sopenharmony_ci	};
1066e5c31af7Sopenharmony_ci
1067e5c31af7Sopenharmony_ci	static const struct
1068e5c31af7Sopenharmony_ci	{
1069e5c31af7Sopenharmony_ci		const char*		name;
1070e5c31af7Sopenharmony_ci		deUint32		mode;
1071e5c31af7Sopenharmony_ci	} minFilterModes[] =
1072e5c31af7Sopenharmony_ci	{
1073e5c31af7Sopenharmony_ci		{ "nearest_nearest",	GL_NEAREST_MIPMAP_NEAREST	},
1074e5c31af7Sopenharmony_ci		{ "linear_nearest",		GL_LINEAR_MIPMAP_NEAREST	},
1075e5c31af7Sopenharmony_ci		{ "nearest_linear",		GL_NEAREST_MIPMAP_LINEAR	},
1076e5c31af7Sopenharmony_ci		{ "linear_linear",		GL_LINEAR_MIPMAP_LINEAR		}
1077e5c31af7Sopenharmony_ci	};
1078e5c31af7Sopenharmony_ci
1079e5c31af7Sopenharmony_ci	static const struct
1080e5c31af7Sopenharmony_ci	{
1081e5c31af7Sopenharmony_ci		CoordType		type;
1082e5c31af7Sopenharmony_ci		const char*		name;
1083e5c31af7Sopenharmony_ci		const char*		desc;
1084e5c31af7Sopenharmony_ci	} coordTypes[] =
1085e5c31af7Sopenharmony_ci	{
1086e5c31af7Sopenharmony_ci		{ COORDTYPE_BASIC,		"basic",		"Mipmapping with translated and scaled coordinates" },
1087e5c31af7Sopenharmony_ci		{ COORDTYPE_AFFINE,		"affine",		"Mipmapping with affine coordinate transform"		},
1088e5c31af7Sopenharmony_ci		{ COORDTYPE_PROJECTED,	"projected",	"Mipmapping with perspective projection"			}
1089e5c31af7Sopenharmony_ci	};
1090e5c31af7Sopenharmony_ci
1091e5c31af7Sopenharmony_ci	static const struct
1092e5c31af7Sopenharmony_ci	{
1093e5c31af7Sopenharmony_ci		const char*		name;
1094e5c31af7Sopenharmony_ci		deUint32		format;
1095e5c31af7Sopenharmony_ci		deUint32		dataType;
1096e5c31af7Sopenharmony_ci	} formats[] =
1097e5c31af7Sopenharmony_ci	{
1098e5c31af7Sopenharmony_ci		{ "a8",			GL_ALPHA,			GL_UNSIGNED_BYTE },
1099e5c31af7Sopenharmony_ci		{ "l8",			GL_LUMINANCE,		GL_UNSIGNED_BYTE },
1100e5c31af7Sopenharmony_ci		{ "la88",		GL_LUMINANCE_ALPHA,	GL_UNSIGNED_BYTE },
1101e5c31af7Sopenharmony_ci		{ "rgb565",		GL_RGB,				GL_UNSIGNED_SHORT_5_6_5 },
1102e5c31af7Sopenharmony_ci		{ "rgb888",		GL_RGB,				GL_UNSIGNED_BYTE },
1103e5c31af7Sopenharmony_ci		{ "rgba4444",	GL_RGBA,			GL_UNSIGNED_SHORT_4_4_4_4 },
1104e5c31af7Sopenharmony_ci		{ "rgba5551",	GL_RGBA,			GL_UNSIGNED_SHORT_5_5_5_1 },
1105e5c31af7Sopenharmony_ci		{ "rgba8888",	GL_RGBA,			GL_UNSIGNED_BYTE }
1106e5c31af7Sopenharmony_ci	};
1107e5c31af7Sopenharmony_ci
1108e5c31af7Sopenharmony_ci	static const struct
1109e5c31af7Sopenharmony_ci	{
1110e5c31af7Sopenharmony_ci		const char*		name;
1111e5c31af7Sopenharmony_ci		deUint32		hint;
1112e5c31af7Sopenharmony_ci	} genHints[] =
1113e5c31af7Sopenharmony_ci	{
1114e5c31af7Sopenharmony_ci		{ "fastest",	GL_FASTEST },
1115e5c31af7Sopenharmony_ci		{ "nicest",		GL_NICEST }
1116e5c31af7Sopenharmony_ci	};
1117e5c31af7Sopenharmony_ci
1118e5c31af7Sopenharmony_ci	static const struct
1119e5c31af7Sopenharmony_ci	{
1120e5c31af7Sopenharmony_ci		const char*		name;
1121e5c31af7Sopenharmony_ci		int				width;
1122e5c31af7Sopenharmony_ci		int				height;
1123e5c31af7Sopenharmony_ci	} tex2DSizes[] =
1124e5c31af7Sopenharmony_ci	{
1125e5c31af7Sopenharmony_ci		{ DE_NULL,		64, 64 }, // Default.
1126e5c31af7Sopenharmony_ci		{ "non_square",	32, 64 }
1127e5c31af7Sopenharmony_ci	};
1128e5c31af7Sopenharmony_ci
1129e5c31af7Sopenharmony_ci	// 2D cases.
1130e5c31af7Sopenharmony_ci	for (int coordType = 0; coordType < DE_LENGTH_OF_ARRAY(coordTypes); coordType++)
1131e5c31af7Sopenharmony_ci	{
1132e5c31af7Sopenharmony_ci		tcu::TestCaseGroup* coordTypeGroup = new tcu::TestCaseGroup(m_testCtx, coordTypes[coordType].name, coordTypes[coordType].desc);
1133e5c31af7Sopenharmony_ci		group2D->addChild(coordTypeGroup);
1134e5c31af7Sopenharmony_ci
1135e5c31af7Sopenharmony_ci		for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
1136e5c31af7Sopenharmony_ci		{
1137e5c31af7Sopenharmony_ci			for (int wrapMode = 0; wrapMode < DE_LENGTH_OF_ARRAY(wrapModes); wrapMode++)
1138e5c31af7Sopenharmony_ci			{
1139e5c31af7Sopenharmony_ci				// Add non_square variants to basic cases only.
1140e5c31af7Sopenharmony_ci				int sizeEnd = coordTypes[coordType].type == COORDTYPE_BASIC ? DE_LENGTH_OF_ARRAY(tex2DSizes) : 1;
1141e5c31af7Sopenharmony_ci
1142e5c31af7Sopenharmony_ci				for (int size = 0; size < sizeEnd; size++)
1143e5c31af7Sopenharmony_ci				{
1144e5c31af7Sopenharmony_ci					std::ostringstream name;
1145e5c31af7Sopenharmony_ci					name << minFilterModes[minFilter].name
1146e5c31af7Sopenharmony_ci						 << "_" << wrapModes[wrapMode].name;
1147e5c31af7Sopenharmony_ci
1148e5c31af7Sopenharmony_ci					if (tex2DSizes[size].name)
1149e5c31af7Sopenharmony_ci						name << "_" << tex2DSizes[size].name;
1150e5c31af7Sopenharmony_ci
1151e5c31af7Sopenharmony_ci					coordTypeGroup->addChild(new Texture2DMipmapCase(m_testCtx, m_context.getRenderContext(), m_context.getContextInfo(),
1152e5c31af7Sopenharmony_ci																	 name.str().c_str(), "",
1153e5c31af7Sopenharmony_ci																	 coordTypes[coordType].type,
1154e5c31af7Sopenharmony_ci																	 minFilterModes[minFilter].mode,
1155e5c31af7Sopenharmony_ci																	 wrapModes[wrapMode].mode,
1156e5c31af7Sopenharmony_ci																	 wrapModes[wrapMode].mode,
1157e5c31af7Sopenharmony_ci																	 GL_RGBA, GL_UNSIGNED_BYTE,
1158e5c31af7Sopenharmony_ci																	 tex2DSizes[size].width, tex2DSizes[size].height));
1159e5c31af7Sopenharmony_ci				}
1160e5c31af7Sopenharmony_ci			}
1161e5c31af7Sopenharmony_ci		}
1162e5c31af7Sopenharmony_ci	}
1163e5c31af7Sopenharmony_ci
1164e5c31af7Sopenharmony_ci	// 2D bias variants.
1165e5c31af7Sopenharmony_ci	{
1166e5c31af7Sopenharmony_ci		tcu::TestCaseGroup* biasGroup = new tcu::TestCaseGroup(m_testCtx, "bias", "User-supplied bias value");
1167e5c31af7Sopenharmony_ci		group2D->addChild(biasGroup);
1168e5c31af7Sopenharmony_ci
1169e5c31af7Sopenharmony_ci		for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
1170e5c31af7Sopenharmony_ci			biasGroup->addChild(new Texture2DMipmapCase(m_testCtx, m_context.getRenderContext(), m_context.getContextInfo(),
1171e5c31af7Sopenharmony_ci														minFilterModes[minFilter].name, "",
1172e5c31af7Sopenharmony_ci														COORDTYPE_BASIC_BIAS,
1173e5c31af7Sopenharmony_ci														minFilterModes[minFilter].mode,
1174e5c31af7Sopenharmony_ci														GL_REPEAT, GL_REPEAT,
1175e5c31af7Sopenharmony_ci														GL_RGBA, GL_UNSIGNED_BYTE,
1176e5c31af7Sopenharmony_ci														tex2DSizes[0].width, tex2DSizes[0].height));
1177e5c31af7Sopenharmony_ci	}
1178e5c31af7Sopenharmony_ci
1179e5c31af7Sopenharmony_ci	// 2D mipmap generation variants.
1180e5c31af7Sopenharmony_ci	{
1181e5c31af7Sopenharmony_ci		tcu::TestCaseGroup* genMipmapGroup = new tcu::TestCaseGroup(m_testCtx, "generate", "Mipmap generation tests");
1182e5c31af7Sopenharmony_ci		group2D->addChild(genMipmapGroup);
1183e5c31af7Sopenharmony_ci
1184e5c31af7Sopenharmony_ci		for (int format = 0; format < DE_LENGTH_OF_ARRAY(formats); format++)
1185e5c31af7Sopenharmony_ci		{
1186e5c31af7Sopenharmony_ci			for (int size = 0; size < DE_LENGTH_OF_ARRAY(tex2DSizes); size++)
1187e5c31af7Sopenharmony_ci			{
1188e5c31af7Sopenharmony_ci				for (int hint = 0; hint < DE_LENGTH_OF_ARRAY(genHints); hint++)
1189e5c31af7Sopenharmony_ci				{
1190e5c31af7Sopenharmony_ci					std::ostringstream name;
1191e5c31af7Sopenharmony_ci					name << formats[format].name;
1192e5c31af7Sopenharmony_ci
1193e5c31af7Sopenharmony_ci					if (tex2DSizes[size].name)
1194e5c31af7Sopenharmony_ci						name << "_" << tex2DSizes[size].name;
1195e5c31af7Sopenharmony_ci
1196e5c31af7Sopenharmony_ci					name << "_" << genHints[hint].name;
1197e5c31af7Sopenharmony_ci
1198e5c31af7Sopenharmony_ci					genMipmapGroup->addChild(new Texture2DGenMipmapCase(m_testCtx, m_context.getRenderContext(), name.str().c_str(), "",
1199e5c31af7Sopenharmony_ci																		formats[format].format, formats[format].dataType, genHints[hint].hint,
1200e5c31af7Sopenharmony_ci																		tex2DSizes[size].width, tex2DSizes[size].height));
1201e5c31af7Sopenharmony_ci				}
1202e5c31af7Sopenharmony_ci			}
1203e5c31af7Sopenharmony_ci		}
1204e5c31af7Sopenharmony_ci	}
1205e5c31af7Sopenharmony_ci
1206e5c31af7Sopenharmony_ci	const int cubeMapSize = 64;
1207e5c31af7Sopenharmony_ci
1208e5c31af7Sopenharmony_ci	static const struct
1209e5c31af7Sopenharmony_ci	{
1210e5c31af7Sopenharmony_ci		CoordType		type;
1211e5c31af7Sopenharmony_ci		const char*		name;
1212e5c31af7Sopenharmony_ci		const char*		desc;
1213e5c31af7Sopenharmony_ci	} cubeCoordTypes[] =
1214e5c31af7Sopenharmony_ci	{
1215e5c31af7Sopenharmony_ci		{ COORDTYPE_BASIC,		"basic",		"Mipmapping with translated and scaled coordinates" },
1216e5c31af7Sopenharmony_ci		{ COORDTYPE_PROJECTED,	"projected",	"Mipmapping with perspective projection"			},
1217e5c31af7Sopenharmony_ci		{ COORDTYPE_BASIC_BIAS,	"bias",			"User-supplied bias value"							}
1218e5c31af7Sopenharmony_ci	};
1219e5c31af7Sopenharmony_ci
1220e5c31af7Sopenharmony_ci	// Cubemap cases.
1221e5c31af7Sopenharmony_ci	for (int coordType = 0; coordType < DE_LENGTH_OF_ARRAY(cubeCoordTypes); coordType++)
1222e5c31af7Sopenharmony_ci	{
1223e5c31af7Sopenharmony_ci		tcu::TestCaseGroup* coordTypeGroup = new tcu::TestCaseGroup(m_testCtx, cubeCoordTypes[coordType].name, cubeCoordTypes[coordType].desc);
1224e5c31af7Sopenharmony_ci		groupCube->addChild(coordTypeGroup);
1225e5c31af7Sopenharmony_ci
1226e5c31af7Sopenharmony_ci		for (int minFilter = 0; minFilter < DE_LENGTH_OF_ARRAY(minFilterModes); minFilter++)
1227e5c31af7Sopenharmony_ci		{
1228e5c31af7Sopenharmony_ci			coordTypeGroup->addChild(new TextureCubeMipmapCase(m_testCtx, m_context.getRenderContext(), m_context.getContextInfo(),
1229e5c31af7Sopenharmony_ci															   minFilterModes[minFilter].name, "",
1230e5c31af7Sopenharmony_ci															   cubeCoordTypes[coordType].type,
1231e5c31af7Sopenharmony_ci															   minFilterModes[minFilter].mode,
1232e5c31af7Sopenharmony_ci															   GL_CLAMP_TO_EDGE,
1233e5c31af7Sopenharmony_ci															   GL_CLAMP_TO_EDGE,
1234e5c31af7Sopenharmony_ci															   GL_RGBA, GL_UNSIGNED_BYTE, cubeMapSize));
1235e5c31af7Sopenharmony_ci		}
1236e5c31af7Sopenharmony_ci	}
1237e5c31af7Sopenharmony_ci
1238e5c31af7Sopenharmony_ci	// Cubemap mipmap generation variants.
1239e5c31af7Sopenharmony_ci	{
1240e5c31af7Sopenharmony_ci		tcu::TestCaseGroup* genMipmapGroup = new tcu::TestCaseGroup(m_testCtx, "generate", "Mipmap generation tests");
1241e5c31af7Sopenharmony_ci		groupCube->addChild(genMipmapGroup);
1242e5c31af7Sopenharmony_ci
1243e5c31af7Sopenharmony_ci		for (int format = 0; format < DE_LENGTH_OF_ARRAY(formats); format++)
1244e5c31af7Sopenharmony_ci		{
1245e5c31af7Sopenharmony_ci			for (int hint = 0; hint < DE_LENGTH_OF_ARRAY(genHints); hint++)
1246e5c31af7Sopenharmony_ci			{
1247e5c31af7Sopenharmony_ci				std::ostringstream name;
1248e5c31af7Sopenharmony_ci				name << formats[format].name
1249e5c31af7Sopenharmony_ci					 << "_" << genHints[hint].name;
1250e5c31af7Sopenharmony_ci
1251e5c31af7Sopenharmony_ci				genMipmapGroup->addChild(new TextureCubeGenMipmapCase(m_testCtx, m_context.getRenderContext(), name.str().c_str(), "", formats[format].format, formats[format].dataType, genHints[hint].hint, cubeMapSize));
1252e5c31af7Sopenharmony_ci			}
1253e5c31af7Sopenharmony_ci		}
1254e5c31af7Sopenharmony_ci	}
1255e5c31af7Sopenharmony_ci}
1256e5c31af7Sopenharmony_ci
1257e5c31af7Sopenharmony_ci} // Functional
1258e5c31af7Sopenharmony_ci} // gles2
1259e5c31af7Sopenharmony_ci} // deqp
1260