1/*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL ES 2.0 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 format tests.
22 *
23 * Constants:
24 *  + nearest-neighbor filtering
25 *  + no mipmaps
26 *  + full texture coordinate range (but not outside) tested
27 *  + accessed from fragment shader
28 *  + texture unit 0
29 *  + named texture object
30 *
31 * Variables:
32 *  + texture format
33 *  + texture type: 2D or cubemap
34 *//*--------------------------------------------------------------------*/
35
36#include "es2fTextureFormatTests.hpp"
37#include "glsTextureTestUtil.hpp"
38#include "gluTexture.hpp"
39#include "gluStrUtil.hpp"
40#include "gluTextureUtil.hpp"
41#include "gluPixelTransfer.hpp"
42#include "tcuSurfaceAccess.hpp"
43#include "tcuTestLog.hpp"
44#include "tcuTextureUtil.hpp"
45
46#include "deStringUtil.hpp"
47
48#include "glwEnums.hpp"
49#include "glwFunctions.hpp"
50
51namespace deqp
52{
53namespace gles2
54{
55namespace Functional
56{
57
58using tcu::TestLog;
59using std::vector;
60using std::string;
61using tcu::Sampler;
62using namespace glu;
63using namespace gls::TextureTestUtil;
64using namespace glu::TextureTestUtil;
65
66// Texture2DFormatCase
67
68class Texture2DFormatCase : public tcu::TestCase
69{
70public:
71							Texture2DFormatCase		(tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const char* name, const char* description, deUint32 format, deUint32 dataType, int width, int height);
72							~Texture2DFormatCase	(void);
73
74	void					init					(void);
75	void					deinit					(void);
76	IterateResult			iterate					(void);
77
78private:
79							Texture2DFormatCase		(const Texture2DFormatCase& other);
80	Texture2DFormatCase&	operator=				(const Texture2DFormatCase& other);
81
82	glu::RenderContext&		m_renderCtx;
83
84	const deUint32			m_format;
85	const deUint32			m_dataType;
86	const int				m_width;
87	const int				m_height;
88
89	glu::Texture2D*			m_texture;
90	TextureRenderer			m_renderer;
91};
92
93Texture2DFormatCase::Texture2DFormatCase (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const char* name, const char* description, deUint32 format, deUint32 dataType, int width, int height)
94	: TestCase		(testCtx, name, description)
95	, m_renderCtx	(renderCtx)
96	, m_format		(format)
97	, m_dataType	(dataType)
98	, m_width		(width)
99	, m_height		(height)
100	, m_texture		(DE_NULL)
101	, m_renderer	(renderCtx, testCtx.getLog(), glu::GLSL_VERSION_100_ES, glu::PRECISION_MEDIUMP)
102{
103}
104
105Texture2DFormatCase::~Texture2DFormatCase (void)
106{
107	deinit();
108}
109
110void Texture2DFormatCase::init (void)
111{
112	TestLog&				log		= m_testCtx.getLog();
113	tcu::TextureFormat		fmt		= glu::mapGLTransferFormat(m_format, m_dataType);
114	tcu::TextureFormatInfo	spec	= tcu::getTextureFormatInfo(fmt);
115	std::ostringstream		fmtName;
116
117	fmtName << getTextureFormatStr(m_format) << ", " << getTypeStr(m_dataType);
118
119	log << TestLog::Message << "2D texture, " << fmtName.str() << ", " << m_width << "x" << m_height
120							<< ",\n  fill with " << formatGradient(&spec.valueMin, &spec.valueMax) << " gradient"
121		<< TestLog::EndMessage;
122
123	m_texture = new Texture2D(m_renderCtx, m_format, m_dataType, m_width, m_height);
124
125	// Fill level 0.
126	m_texture->getRefTexture().allocLevel(0);
127	tcu::fillWithComponentGradients(m_texture->getRefTexture().getLevel(0), spec.valueMin, spec.valueMax);
128}
129
130void Texture2DFormatCase::deinit (void)
131{
132	delete m_texture;
133	m_texture = DE_NULL;
134
135	m_renderer.clear();
136}
137
138Texture2DFormatCase::IterateResult Texture2DFormatCase::iterate (void)
139{
140	TestLog&				log					= m_testCtx.getLog();
141	const glw::Functions&	gl					= m_renderCtx.getFunctions();
142	RandomViewport			viewport			(m_renderCtx.getRenderTarget(), m_width, m_height, deStringHash(getName()));
143	tcu::Surface			renderedFrame		(viewport.width, viewport.height);
144	tcu::Surface			referenceFrame		(viewport.width, viewport.height);
145	tcu::RGBA				threshold			= m_renderCtx.getRenderTarget().getPixelFormat().getColorThreshold() + tcu::RGBA(1,1,1,1);
146	vector<float>			texCoord;
147	ReferenceParams			renderParams		(TEXTURETYPE_2D);
148	tcu::TextureFormatInfo	spec				= tcu::getTextureFormatInfo(m_texture->getRefTexture().getFormat());
149	const deUint32			wrapS				= GL_CLAMP_TO_EDGE;
150	const deUint32			wrapT				= GL_CLAMP_TO_EDGE;
151	const deUint32			minFilter			= GL_NEAREST;
152	const deUint32			magFilter			= GL_NEAREST;
153
154	renderParams.flags			|= RenderParams::LOG_ALL;
155	renderParams.samplerType	= getSamplerType(m_texture->getRefTexture().getFormat());
156	renderParams.sampler		= Sampler(Sampler::CLAMP_TO_EDGE, Sampler::CLAMP_TO_EDGE, Sampler::CLAMP_TO_EDGE, Sampler::NEAREST, Sampler::NEAREST);
157	renderParams.colorScale		= spec.lookupScale;
158	renderParams.colorBias		= spec.lookupBias;
159
160	computeQuadTexCoord2D(texCoord, tcu::Vec2(0.0f, 0.0f), tcu::Vec2(1.0f, 1.0f));
161
162	log << TestLog::Message << "Texture parameters:"
163							<< "\n  WRAP_S = " << getTextureParameterValueStr(GL_TEXTURE_WRAP_S, wrapS)
164							<< "\n  WRAP_T = " << getTextureParameterValueStr(GL_TEXTURE_WRAP_T, wrapT)
165							<< "\n  MIN_FILTER = " << getTextureParameterValueStr(GL_TEXTURE_MIN_FILTER, minFilter)
166							<< "\n  MAG_FILTER = " << getTextureParameterValueStr(GL_TEXTURE_MAG_FILTER, magFilter)
167		<< TestLog::EndMessage;
168
169	// Setup base viewport.
170	gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height);
171
172	// Upload texture data to GL.
173	m_texture->upload();
174
175	// Bind to unit 0.
176	gl.activeTexture(GL_TEXTURE0);
177	gl.bindTexture(GL_TEXTURE_2D, m_texture->getGLTexture());
178
179	// Setup nearest neighbor filtering and clamp-to-edge.
180	gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapS);
181	gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapT);
182	gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter);
183	gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter);
184
185	GLU_EXPECT_NO_ERROR(gl.getError(), "Set texturing state");
186
187	// Draw.
188	m_renderer.renderQuad(0, &texCoord[0], renderParams);
189	glu::readPixels(m_renderCtx, viewport.x, viewport.y, renderedFrame.getAccess());
190	GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels()");
191
192	// Compute reference.
193	sampleTexture(tcu::SurfaceAccess(referenceFrame, m_renderCtx.getRenderTarget().getPixelFormat()), m_texture->getRefTexture(), &texCoord[0], renderParams);
194
195	// Compare and log.
196	bool isOk = compareImages(log, referenceFrame, renderedFrame, threshold);
197
198	m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS	: QP_TEST_RESULT_FAIL,
199							isOk ? "Pass"				: "Image comparison failed");
200
201	return STOP;
202}
203
204// TextureCubeFormatCase
205
206class TextureCubeFormatCase : public tcu::TestCase
207{
208public:
209							TextureCubeFormatCase	(tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const char* name, const char* description, deUint32 format, deUint32 dataType, int width, int height);
210							~TextureCubeFormatCase	(void);
211
212	void					init					(void);
213	void					deinit					(void);
214	IterateResult			iterate					(void);
215
216private:
217							TextureCubeFormatCase	(const TextureCubeFormatCase& other);
218	TextureCubeFormatCase&	operator=				(const TextureCubeFormatCase& other);
219
220	bool					testFace				(tcu::CubeFace face);
221
222	glu::RenderContext&		m_renderCtx;
223
224	const deUint32			m_format;
225	const deUint32			m_dataType;
226	const int				m_width;
227	const int				m_height;
228
229	glu::TextureCube*		m_texture;
230	TextureRenderer			m_renderer;
231
232	int						m_curFace;
233	bool					m_isOk;
234};
235
236
237TextureCubeFormatCase::TextureCubeFormatCase (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const char* name, const char* description, deUint32 format, deUint32 dataType, int width, int height)
238	: TestCase		(testCtx, name, description)
239	, m_renderCtx	(renderCtx)
240	, m_format		(format)
241	, m_dataType	(dataType)
242	, m_width		(width)
243	, m_height		(height)
244	, m_texture		(DE_NULL)
245	, m_renderer	(renderCtx, testCtx.getLog(), glu::GLSL_VERSION_100_ES, glu::PRECISION_MEDIUMP)
246	, m_curFace		(0)
247	, m_isOk		(false)
248{
249}
250
251TextureCubeFormatCase::~TextureCubeFormatCase (void)
252{
253	deinit();
254}
255
256void TextureCubeFormatCase::init (void)
257{
258	TestLog&				log		= m_testCtx.getLog();
259	tcu::TextureFormat		fmt		= glu::mapGLTransferFormat(m_format, m_dataType);
260	tcu::TextureFormatInfo	spec	= tcu::getTextureFormatInfo(fmt);
261	std::ostringstream		fmtName;
262
263	if (m_dataType)
264		fmtName << getTextureFormatStr(m_format) << ", " << getTypeStr(m_dataType);
265	else
266		fmtName << getTextureFormatStr(m_format);
267
268	log << TestLog::Message << "Cube map texture, " << fmtName.str() << ", " << m_width << "x" << m_height
269							<< ",\n  fill with " << formatGradient(&spec.valueMin, &spec.valueMax) << " gradient"
270		<< TestLog::EndMessage;
271
272	DE_ASSERT(m_width == m_height);
273	m_texture = m_dataType != GL_NONE
274			  ? new TextureCube(m_renderCtx, m_format, m_dataType, m_width)	// Implicit internal format.
275		      : new TextureCube(m_renderCtx, m_format, m_width);				// Explicit internal format.
276
277	// Fill level 0.
278	for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
279	{
280		tcu::Vec4 gMin, gMax;
281
282		switch (face)
283		{
284			case 0: gMin = spec.valueMin.swizzle(0, 1, 2, 3); gMax = spec.valueMax.swizzle(0, 1, 2, 3); break;
285			case 1: gMin = spec.valueMin.swizzle(2, 1, 0, 3); gMax = spec.valueMax.swizzle(2, 1, 0, 3); break;
286			case 2: gMin = spec.valueMin.swizzle(1, 2, 0, 3); gMax = spec.valueMax.swizzle(1, 2, 0, 3); break;
287			case 3: gMin = spec.valueMax.swizzle(0, 1, 2, 3); gMax = spec.valueMin.swizzle(0, 1, 2, 3); break;
288			case 4: gMin = spec.valueMax.swizzle(2, 1, 0, 3); gMax = spec.valueMin.swizzle(2, 1, 0, 3); break;
289			case 5: gMin = spec.valueMax.swizzle(1, 2, 0, 3); gMax = spec.valueMin.swizzle(1, 2, 0, 3); break;
290			default:
291				DE_ASSERT(false);
292		}
293
294		m_texture->getRefTexture().allocLevel((tcu::CubeFace)face, 0);
295		tcu::fillWithComponentGradients(m_texture->getRefTexture().getLevelFace(0, (tcu::CubeFace)face), gMin, gMax);
296	}
297
298	// Upload texture data to GL.
299	m_texture->upload();
300
301	// Initialize iteration state.
302	m_curFace	= 0;
303	m_isOk		= true;
304}
305
306void TextureCubeFormatCase::deinit (void)
307{
308	delete m_texture;
309	m_texture = DE_NULL;
310
311	m_renderer.clear();
312}
313
314bool TextureCubeFormatCase::testFace (tcu::CubeFace face)
315{
316	const glw::Functions&	gl					= m_renderCtx.getFunctions();
317	TestLog&				log					= m_testCtx.getLog();
318	RandomViewport			viewport			(m_renderCtx.getRenderTarget(), m_width, m_height, deStringHash(getName())+(deUint32)face);
319	tcu::Surface			renderedFrame		(viewport.width, viewport.height);
320	tcu::Surface			referenceFrame		(viewport.width, viewport.height);
321	tcu::RGBA				threshold			= m_renderCtx.getRenderTarget().getPixelFormat().getColorThreshold() + tcu::RGBA(1,1,1,1);
322	vector<float>			texCoord;
323	ReferenceParams			renderParams		(TEXTURETYPE_CUBE);
324	tcu::TextureFormatInfo	spec				= tcu::getTextureFormatInfo(m_texture->getRefTexture().getFormat());
325
326	renderParams.samplerType				= getSamplerType(m_texture->getRefTexture().getFormat());
327	renderParams.sampler					= Sampler(Sampler::CLAMP_TO_EDGE, Sampler::CLAMP_TO_EDGE, Sampler::CLAMP_TO_EDGE, Sampler::NEAREST, Sampler::NEAREST);
328	renderParams.sampler.seamlessCubeMap	= false;
329	renderParams.colorScale					= spec.lookupScale;
330	renderParams.colorBias					= spec.lookupBias;
331
332	// Log render info on first face.
333	if (face == tcu::CUBEFACE_NEGATIVE_X)
334		renderParams.flags |= RenderParams::LOG_ALL;
335
336	computeQuadTexCoordCube(texCoord, face);
337
338	// \todo [2011-10-28 pyry] Image set name / section?
339	log << TestLog::Message << face << TestLog::EndMessage;
340
341	// Setup base viewport.
342	gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height);
343
344	// Bind to unit 0.
345	gl.activeTexture(GL_TEXTURE0);
346	gl.bindTexture(GL_TEXTURE_CUBE_MAP, m_texture->getGLTexture());
347
348	// Setup nearest neighbor filtering and clamp-to-edge.
349	gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
350	gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
351	gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
352	gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
353
354	GLU_EXPECT_NO_ERROR(gl.getError(), "Set texturing state");
355
356	m_renderer.renderQuad(0, &texCoord[0], renderParams);
357	glu::readPixels(m_renderCtx, viewport.x, viewport.y, renderedFrame.getAccess());
358	GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels()");
359
360	// Compute reference.
361	sampleTexture(tcu::SurfaceAccess(referenceFrame, m_renderCtx.getRenderTarget().getPixelFormat()), m_texture->getRefTexture(), &texCoord[0], renderParams);
362
363	// Compare and log.
364	return compareImages(log, referenceFrame, renderedFrame, threshold);
365}
366
367TextureCubeFormatCase::IterateResult TextureCubeFormatCase::iterate (void)
368{
369	// Execute test for all faces.
370	if (!testFace((tcu::CubeFace)m_curFace))
371		m_isOk = false;
372
373	m_curFace += 1;
374
375	if (m_curFace == tcu::CUBEFACE_LAST)
376	{
377		m_testCtx.setTestResult(m_isOk ? QP_TEST_RESULT_PASS	: QP_TEST_RESULT_FAIL,
378								m_isOk ? "Pass"					: "Image comparison failed");
379		return STOP;
380	}
381	else
382		return CONTINUE;
383}
384
385TextureFormatTests::TextureFormatTests (Context& context)
386	: TestCaseGroup(context, "format", "Texture Format Tests")
387{
388}
389
390TextureFormatTests::~TextureFormatTests (void)
391{
392}
393
394// Compressed2DFormatCase
395
396class Compressed2DFormatCase : public tcu::TestCase
397{
398public:
399								Compressed2DFormatCase		(tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const glu::ContextInfo& renderCtxInfo, const char* name, const char* description, const std::vector<std::string>& filenames);
400								~Compressed2DFormatCase		(void);
401
402	void						init						(void);
403	void						deinit						(void);
404	IterateResult				iterate						(void);
405
406private:
407								Compressed2DFormatCase		(const Compressed2DFormatCase& other);
408	Compressed2DFormatCase&		operator=					(const Compressed2DFormatCase& other);
409
410	glu::RenderContext&			m_renderCtx;
411	const glu::ContextInfo&		m_renderCtxInfo;
412
413	std::vector<std::string>	m_filenames;
414
415	glu::Texture2D*				m_texture;
416	TextureRenderer				m_renderer;
417};
418
419Compressed2DFormatCase::Compressed2DFormatCase (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const glu::ContextInfo& renderCtxInfo, const char* name, const char* description, const std::vector<std::string>& filenames)
420	: TestCase			(testCtx, name, description)
421	, m_renderCtx		(renderCtx)
422	, m_renderCtxInfo	(renderCtxInfo)
423	, m_filenames		(filenames)
424	, m_texture			(DE_NULL)
425	, m_renderer		(renderCtx, testCtx.getLog(), glu::GLSL_VERSION_100_ES, glu::PRECISION_MEDIUMP)
426{
427}
428
429Compressed2DFormatCase::~Compressed2DFormatCase (void)
430{
431	deinit();
432}
433
434void Compressed2DFormatCase::init (void)
435{
436	// Create texture.
437	m_texture = Texture2D::create(m_renderCtx, m_renderCtxInfo, m_testCtx.getArchive(), (int)m_filenames.size(), m_filenames);
438}
439
440void Compressed2DFormatCase::deinit (void)
441{
442	delete m_texture;
443	m_texture = DE_NULL;
444
445	m_renderer.clear();
446}
447
448Compressed2DFormatCase::IterateResult Compressed2DFormatCase::iterate (void)
449{
450	const glw::Functions&	gl					= m_renderCtx.getFunctions();
451	TestLog&				log					= m_testCtx.getLog();
452	RandomViewport			viewport			(m_renderCtx.getRenderTarget(), m_texture->getRefTexture().getWidth(), m_texture->getRefTexture().getHeight(), deStringHash(getName()));
453	tcu::Surface			renderedFrame		(viewport.width, viewport.height);
454	tcu::Surface			referenceFrame		(viewport.width, viewport.height);
455	tcu::RGBA				threshold			= m_renderCtx.getRenderTarget().getPixelFormat().getColorThreshold() + tcu::RGBA(1,1,1,1);
456	vector<float>			texCoord;
457
458	computeQuadTexCoord2D(texCoord, tcu::Vec2(0.0f, 0.0f), tcu::Vec2(1.0f, 1.0f));
459
460	// Setup base viewport.
461	gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height);
462
463	// Bind to unit 0.
464	gl.activeTexture(GL_TEXTURE0);
465	gl.bindTexture(GL_TEXTURE_2D, m_texture->getGLTexture());
466
467	// Setup nearest neighbor filtering and clamp-to-edge.
468	gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,		GL_CLAMP_TO_EDGE);
469	gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,		GL_CLAMP_TO_EDGE);
470	gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,	GL_NEAREST);
471	gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,	GL_NEAREST);
472
473	GLU_EXPECT_NO_ERROR(gl.getError(), "Set texturing state");
474
475	// Draw.
476	m_renderer.renderQuad(0, &texCoord[0], TEXTURETYPE_2D);
477	glu::readPixels(m_renderCtx, viewport.x, viewport.y, renderedFrame.getAccess());
478	GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels()");
479
480	// Compute reference.
481	ReferenceParams refParams(TEXTURETYPE_2D);
482	refParams.sampler = Sampler(Sampler::CLAMP_TO_EDGE, Sampler::CLAMP_TO_EDGE, Sampler::CLAMP_TO_EDGE, Sampler::NEAREST, Sampler::NEAREST);
483	sampleTexture(tcu::SurfaceAccess(referenceFrame, m_renderCtx.getRenderTarget().getPixelFormat()), m_texture->getRefTexture(), &texCoord[0], refParams);
484
485	// Compare and log.
486	bool isOk = compareImages(log, referenceFrame, renderedFrame, threshold);
487
488	m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS	: QP_TEST_RESULT_FAIL,
489							isOk ? "Pass"				: "Image comparison failed");
490
491	return STOP;
492}
493
494// CompressedCubeFormatCase
495
496class CompressedCubeFormatCase : public tcu::TestCase
497{
498public:
499								CompressedCubeFormatCase	(tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const glu::ContextInfo& renderCtxInfo, const char* name, const char* description, const std::vector<std::string>& filenames);
500								~CompressedCubeFormatCase	(void);
501
502	void						init						(void);
503	void						deinit						(void);
504	IterateResult				iterate						(void);
505
506private:
507								CompressedCubeFormatCase	(const CompressedCubeFormatCase& other);
508	CompressedCubeFormatCase&	operator=					(const CompressedCubeFormatCase& other);
509
510	bool						testFace					(tcu::CubeFace face);
511
512	glu::RenderContext&			m_renderCtx;
513	const glu::ContextInfo&		m_renderCtxInfo;
514
515	std::vector<std::string>	m_filenames;
516
517	glu::TextureCube*			m_texture;
518	TextureRenderer				m_renderer;
519
520	int							m_curFace;
521	bool						m_isOk;
522};
523
524CompressedCubeFormatCase::CompressedCubeFormatCase (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const glu::ContextInfo& renderCtxInfo, const char* name, const char* description, const std::vector<std::string>& filenames)
525	: TestCase			(testCtx, name, description)
526	, m_renderCtx		(renderCtx)
527	, m_renderCtxInfo	(renderCtxInfo)
528	, m_filenames		(filenames)
529	, m_texture			(DE_NULL)
530	, m_renderer		(renderCtx, testCtx.getLog(), glu::GLSL_VERSION_100_ES, glu::PRECISION_MEDIUMP)
531	, m_curFace			(0)
532	, m_isOk			(false)
533{
534}
535
536CompressedCubeFormatCase::~CompressedCubeFormatCase (void)
537{
538	deinit();
539}
540
541void CompressedCubeFormatCase::init (void)
542{
543	// Create texture.
544	DE_ASSERT(m_filenames.size() % 6 == 0);
545	m_texture = TextureCube::create(m_renderCtx, m_renderCtxInfo, m_testCtx.getArchive(), (int)m_filenames.size()/6, m_filenames);
546
547	m_curFace	= 0;
548	m_isOk		= true;
549}
550
551void CompressedCubeFormatCase::deinit (void)
552{
553	delete m_texture;
554	m_texture = DE_NULL;
555
556	m_renderer.clear();
557}
558
559bool CompressedCubeFormatCase::testFace (tcu::CubeFace face)
560{
561	const glw::Functions&	gl					= m_renderCtx.getFunctions();
562	TestLog&				log					= m_testCtx.getLog();
563	RandomViewport			viewport			(m_renderCtx.getRenderTarget(), m_texture->getRefTexture().getSize(), m_texture->getRefTexture().getSize(), deStringHash(getName())+(deUint32)face);
564	tcu::Surface			renderedFrame		(viewport.width, viewport.height);
565	tcu::Surface			referenceFrame		(viewport.width, viewport.height);
566	Sampler					sampler				(Sampler::CLAMP_TO_EDGE, Sampler::CLAMP_TO_EDGE, Sampler::CLAMP_TO_EDGE, Sampler::NEAREST, Sampler::NEAREST);
567	tcu::RGBA				threshold			= m_renderCtx.getRenderTarget().getPixelFormat().getColorThreshold() + tcu::RGBA(1,1,1,1);
568	vector<float>			texCoord;
569
570	computeQuadTexCoordCube(texCoord, face);
571
572	// \todo [2011-10-28 pyry] Image set name / section?
573	log << TestLog::Message << face << TestLog::EndMessage;
574
575	// Setup base viewport.
576	gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height);
577
578	// Bind to unit 0.
579	gl.activeTexture(GL_TEXTURE0);
580	gl.bindTexture(GL_TEXTURE_CUBE_MAP, m_texture->getGLTexture());
581
582	// Setup nearest neighbor filtering and clamp-to-edge.
583	gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
584	gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
585	gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
586	gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
587
588	GLU_EXPECT_NO_ERROR(gl.getError(), "Set texturing state");
589
590	m_renderer.renderQuad(0, &texCoord[0], TEXTURETYPE_CUBE);
591	glu::readPixels(m_renderCtx, viewport.x, viewport.y, renderedFrame.getAccess());
592	GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels()");
593
594	// Compute reference.
595	sampleTexture(tcu::SurfaceAccess(referenceFrame, m_renderCtx.getRenderTarget().getPixelFormat()), m_texture->getRefTexture(), &texCoord[0], ReferenceParams(TEXTURETYPE_CUBE, sampler));
596
597	// Compare and log.
598	return compareImages(log, referenceFrame, renderedFrame, threshold);
599}
600
601CompressedCubeFormatCase::IterateResult CompressedCubeFormatCase::iterate (void)
602{
603	// Execute test for all faces.
604	if (!testFace((tcu::CubeFace)m_curFace))
605		m_isOk = false;
606
607	m_curFace += 1;
608
609	if (m_curFace == tcu::CUBEFACE_LAST)
610	{
611		m_testCtx.setTestResult(m_isOk ? QP_TEST_RESULT_PASS	: QP_TEST_RESULT_FAIL,
612								m_isOk ? "Pass"					: "Image comparison failed");
613		return STOP;
614	}
615	else
616		return CONTINUE;
617}
618
619vector<string> toStringVector (const char* const* str, int numStr)
620{
621	vector<string> v;
622	v.resize(numStr);
623	for (int i = 0; i < numStr; i++)
624		v[i] = str[i];
625	return v;
626}
627
628void TextureFormatTests::init (void)
629{
630	struct
631	{
632		const char*	name;
633		deUint32		format;
634		deUint32		dataType;
635	} texFormats[] =
636	{
637		{ "a8",			GL_ALPHA,			GL_UNSIGNED_BYTE },
638		{ "l8",			GL_LUMINANCE,		GL_UNSIGNED_BYTE },
639		{ "la88",		GL_LUMINANCE_ALPHA,	GL_UNSIGNED_BYTE },
640		{ "rgb565",		GL_RGB,				GL_UNSIGNED_SHORT_5_6_5 },
641		{ "rgb888",		GL_RGB,				GL_UNSIGNED_BYTE },
642		{ "rgba4444",	GL_RGBA,			GL_UNSIGNED_SHORT_4_4_4_4 },
643		{ "rgba5551",	GL_RGBA,			GL_UNSIGNED_SHORT_5_5_5_1 },
644		{ "rgba8888",	GL_RGBA,			GL_UNSIGNED_BYTE }
645	};
646
647	for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(texFormats); formatNdx++)
648	{
649		deUint32	format			= texFormats[formatNdx].format;
650		deUint32	dataType		= texFormats[formatNdx].dataType;
651		string	nameBase		= texFormats[formatNdx].name;
652		string	descriptionBase	= string(glu::getTextureFormatName(format)) + ", " + glu::getTypeName(dataType);
653
654		addChild(new Texture2DFormatCase	(m_testCtx, m_context.getRenderContext(),	(nameBase + "_2d_pot").c_str(),		(descriptionBase + ", GL_TEXTURE_2D").c_str(),			format, dataType, 128, 128));
655		addChild(new Texture2DFormatCase	(m_testCtx, m_context.getRenderContext(),	(nameBase + "_2d_npot").c_str(),	(descriptionBase + ", GL_TEXTURE_2D").c_str(),			format, dataType,  63, 112));
656		addChild(new TextureCubeFormatCase	(m_testCtx, m_context.getRenderContext(),	(nameBase + "_cube_pot").c_str(),	(descriptionBase + ", GL_TEXTURE_CUBE_MAP").c_str(),	format, dataType,  64,  64));
657		addChild(new TextureCubeFormatCase	(m_testCtx, m_context.getRenderContext(),	(nameBase + "_cube_npot").c_str(),	(descriptionBase + ", GL_TEXTURE_CUBE_MAP").c_str(),	format, dataType,  57,  57));
658	}
659
660	// ETC-1 compressed formats.
661	{
662		static const char* filenames[] =
663		{
664			"data/etc1/photo_helsinki_mip_0.pkm",
665			"data/etc1/photo_helsinki_mip_1.pkm",
666			"data/etc1/photo_helsinki_mip_2.pkm",
667			"data/etc1/photo_helsinki_mip_3.pkm",
668			"data/etc1/photo_helsinki_mip_4.pkm",
669			"data/etc1/photo_helsinki_mip_5.pkm",
670			"data/etc1/photo_helsinki_mip_6.pkm",
671			"data/etc1/photo_helsinki_mip_7.pkm"
672		};
673		addChild(new Compressed2DFormatCase(m_testCtx, m_context.getRenderContext(), m_context.getContextInfo(), "etc1_2d_pot", "GL_ETC1_RGB8_OES, GL_TEXTURE_2D", toStringVector(filenames, DE_LENGTH_OF_ARRAY(filenames))));
674	}
675
676	{
677		vector<string> filenames;
678		filenames.push_back("data/etc1/photo_helsinki_113x89.pkm");
679		addChild(new Compressed2DFormatCase(m_testCtx, m_context.getRenderContext(), m_context.getContextInfo(), "etc1_2d_npot", "GL_ETC1_RGB8_OES, GL_TEXTURE_2D", filenames));
680	}
681
682	{
683		static const char* faceExt[] = { "neg_x", "pos_x", "neg_y", "pos_y", "neg_z", "pos_z" };
684
685		const int		potNumLevels	= 7;
686		vector<string>	potFilenames;
687		for (int level = 0; level < potNumLevels; level++)
688			for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
689				potFilenames.push_back(string("data/etc1/skybox_") + faceExt[face] + "_mip_" + de::toString(level) + ".pkm");
690
691		addChild(new CompressedCubeFormatCase(m_testCtx, m_context.getRenderContext(), m_context.getContextInfo(), "etc1_cube_pot", "GL_ETC1_RGB8_OES, GL_TEXTURE_CUBE_MAP", potFilenames));
692
693		vector<string> npotFilenames;
694		for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
695			npotFilenames.push_back(string("data/etc1/skybox_61x61_") + faceExt[face] + ".pkm");
696
697		addChild(new CompressedCubeFormatCase(m_testCtx, m_context.getRenderContext(), m_context.getContextInfo(), "etc1_cube_npot", "GL_ETC_RGB8_OES, GL_TEXTURE_CUBE_MAP", npotFilenames));
698	}
699}
700
701} // Functional
702} // gles2
703} // deqp
704