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