• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program OpenGL ES 3.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 size tests.
22  *//*--------------------------------------------------------------------*/
23 
24 #include "es3fTextureSizeTests.hpp"
25 #include "glsTextureTestUtil.hpp"
26 #include "gluTexture.hpp"
27 #include "gluStrUtil.hpp"
28 #include "gluTextureUtil.hpp"
29 #include "gluPixelTransfer.hpp"
30 #include "tcuTestLog.hpp"
31 #include "tcuTextureUtil.hpp"
32 
33 #include "glwEnums.hpp"
34 #include "glwFunctions.hpp"
35 
36 namespace deqp
37 {
38 namespace gles3
39 {
40 namespace Functional
41 {
42 
43 using tcu::TestLog;
44 using std::vector;
45 using std::string;
46 using tcu::Sampler;
47 using namespace glu;
48 using namespace gls::TextureTestUtil;
49 using namespace glu::TextureTestUtil;
50 
51 
52 class Texture2DSizeCase : public tcu::TestCase
53 {
54 public:
55 							Texture2DSizeCase		(tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const char* name, const char* description, deUint32 format, deUint32 dataType, int width, int height, bool mipmaps);
56 							~Texture2DSizeCase		(void);
57 
58 	void					init					(void);
59 	void					deinit					(void);
60 	IterateResult			iterate					(void);
61 
62 private:
63 							Texture2DSizeCase		(const Texture2DSizeCase& other);
64 	Texture2DSizeCase&		operator=				(const Texture2DSizeCase& other);
65 
66 	glu::RenderContext&		m_renderCtx;
67 
68 	deUint32				m_format;
69 	deUint32				m_dataType;
70 	int						m_width;
71 	int						m_height;
72 	bool					m_useMipmaps;
73 
74 	glu::Texture2D*			m_texture;
75 	TextureRenderer			m_renderer;
76 };
77 
Texture2DSizeCase(tcu::TestContext & testCtx,glu::RenderContext & renderCtx,const char * name,const char * description,deUint32 format,deUint32 dataType,int width,int height,bool mipmaps)78 Texture2DSizeCase::Texture2DSizeCase (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const char* name, const char* description, deUint32 format, deUint32 dataType, int width, int height, bool mipmaps)
79 	: TestCase		(testCtx, name, description)
80 	, m_renderCtx	(renderCtx)
81 	, m_format		(format)
82 	, m_dataType	(dataType)
83 	, m_width		(width)
84 	, m_height		(height)
85 	, m_useMipmaps	(mipmaps)
86 	, m_texture		(DE_NULL)
87 	, m_renderer	(renderCtx, testCtx.getLog(), glu::GLSL_VERSION_300_ES, glu::PRECISION_MEDIUMP)
88 {
89 }
90 
~Texture2DSizeCase(void)91 Texture2DSizeCase::~Texture2DSizeCase (void)
92 {
93 	Texture2DSizeCase::deinit();
94 }
95 
init(void)96 void Texture2DSizeCase::init (void)
97 {
98 	DE_ASSERT(!m_texture);
99 	m_texture = new Texture2D(m_renderCtx, m_format, m_dataType, m_width, m_height);
100 
101 	int numLevels = m_useMipmaps ? deLog2Floor32(de::max(m_width, m_height))+1 : 1;
102 
103 	// Fill levels.
104 	for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
105 	{
106 		m_texture->getRefTexture().allocLevel(levelNdx);
107 		tcu::fillWithComponentGradients(m_texture->getRefTexture().getLevel(levelNdx), tcu::Vec4(-1.0f, -1.0f, -1.0f, 2.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f));
108 	}
109 }
110 
deinit(void)111 void Texture2DSizeCase::deinit (void)
112 {
113 	delete m_texture;
114 	m_texture = DE_NULL;
115 
116 	m_renderer.clear();
117 }
118 
iterate(void)119 Texture2DSizeCase::IterateResult Texture2DSizeCase::iterate (void)
120 {
121 	const glw::Functions&	gl				= m_renderCtx.getFunctions();
122 	TestLog&				log				= m_testCtx.getLog();
123 	RandomViewport			viewport		(m_renderCtx.getRenderTarget(), 128, 128, deStringHash(getName()));
124 	tcu::Surface			renderedFrame	(viewport.width, viewport.height);
125 	tcu::Surface			referenceFrame	(viewport.width, viewport.height);
126 	const tcu::IVec4		texBits			= tcu::getTextureFormatBitDepth(glu::mapGLTransferFormat(m_format, m_dataType));
127 	const tcu::PixelFormat&	rtFmt			= m_renderCtx.getRenderTarget().getPixelFormat();
128 	const tcu::PixelFormat	thresholdFormat(de::min(texBits[0], rtFmt.redBits), de::min(texBits[1], rtFmt.greenBits), de::min(texBits[2], rtFmt.blueBits), de::min(texBits[3], rtFmt.alphaBits));
129 	tcu::RGBA				threshold		= thresholdFormat.getColorThreshold() + tcu::RGBA(7,7,7,7);
130 	deUint32				wrapS			= GL_CLAMP_TO_EDGE;
131 	deUint32				wrapT			= GL_CLAMP_TO_EDGE;
132 	// Do not minify with GL_NEAREST. A large POT texture with a small POT render target will produce
133 	// indeterminate results.
134 	deUint32				minFilter		= m_useMipmaps ? GL_NEAREST_MIPMAP_NEAREST : GL_LINEAR;
135 	deUint32				magFilter		= GL_NEAREST;
136 	vector<float>			texCoord;
137 
138 	computeQuadTexCoord2D(texCoord, tcu::Vec2(0.0f, 0.0f), tcu::Vec2(1.0f, 1.0f));
139 
140 	// Setup base viewport.
141 	gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height);
142 
143 	// Upload texture data to GL.
144 	m_texture->upload();
145 
146 	// Bind to unit 0.
147 	gl.activeTexture(GL_TEXTURE0);
148 	gl.bindTexture(GL_TEXTURE_2D, m_texture->getGLTexture());
149 
150 	gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,		wrapS);
151 	gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,		wrapT);
152 	gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,	minFilter);
153 	gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,	magFilter);
154 	GLU_EXPECT_NO_ERROR(gl.getError(), "Set texturing state");
155 
156 	// Draw.
157 	m_renderer.renderQuad(0, &texCoord[0], TEXTURETYPE_2D);
158 	glu::readPixels(m_renderCtx, viewport.x, viewport.y, renderedFrame.getAccess());
159 
160 	// Compute reference.
161 	sampleTexture(tcu::SurfaceAccess(referenceFrame, m_renderCtx.getRenderTarget().getPixelFormat()), m_texture->getRefTexture(), &texCoord[0], ReferenceParams(TEXTURETYPE_2D, mapGLSampler(wrapS, wrapT, minFilter, magFilter)));
162 
163 	// Compare and log.
164 	bool isOk = compareImages(log, referenceFrame, renderedFrame, threshold);
165 
166 	m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS	: QP_TEST_RESULT_FAIL,
167 							isOk ? "Pass"				: "Image comparison failed");
168 
169 	return STOP;
170 }
171 
172 class TextureCubeSizeCase : public tcu::TestCase
173 {
174 public:
175 							TextureCubeSizeCase		(tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const char* name, const char* description, deUint32 format, deUint32 dataType, int width, int height, bool mipmaps);
176 							~TextureCubeSizeCase	(void);
177 
178 	void					init					(void);
179 	void					deinit					(void);
180 	IterateResult			iterate					(void);
181 
182 private:
183 							TextureCubeSizeCase		(const TextureCubeSizeCase& other);
184 	TextureCubeSizeCase&	operator=				(const TextureCubeSizeCase& other);
185 
186 	bool					testFace				(tcu::CubeFace face);
187 
188 	glu::RenderContext&		m_renderCtx;
189 
190 	deUint32				m_format;
191 	deUint32				m_dataType;
192 	int						m_width;
193 	int						m_height;
194 	bool					m_useMipmaps;
195 
196 	glu::TextureCube*		m_texture;
197 	TextureRenderer			m_renderer;
198 
199 	int						m_curFace;
200 	bool					m_isOk;
201 };
202 
TextureCubeSizeCase(tcu::TestContext & testCtx,glu::RenderContext & renderCtx,const char * name,const char * description,deUint32 format,deUint32 dataType,int width,int height,bool mipmaps)203 TextureCubeSizeCase::TextureCubeSizeCase (tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const char* name, const char* description, deUint32 format, deUint32 dataType, int width, int height, bool mipmaps)
204 	: TestCase		(testCtx, name, description)
205 	, m_renderCtx	(renderCtx)
206 	, m_format		(format)
207 	, m_dataType	(dataType)
208 	, m_width		(width)
209 	, m_height		(height)
210 	, m_useMipmaps	(mipmaps)
211 	, m_texture		(DE_NULL)
212 	, m_renderer	(renderCtx, testCtx.getLog(), glu::GLSL_VERSION_300_ES, glu::PRECISION_MEDIUMP)
213 	, m_curFace		(0)
214 	, m_isOk		(false)
215 {
216 }
217 
~TextureCubeSizeCase(void)218 TextureCubeSizeCase::~TextureCubeSizeCase (void)
219 {
220 	TextureCubeSizeCase::deinit();
221 }
222 
init(void)223 void TextureCubeSizeCase::init (void)
224 {
225 	DE_ASSERT(!m_texture);
226 	DE_ASSERT(m_width == m_height);
227 	m_texture = new TextureCube(m_renderCtx, m_format, m_dataType, m_width);
228 
229 	static const tcu::Vec4 gradients[tcu::CUBEFACE_LAST][2] =
230 	{
231 		{ tcu::Vec4(-1.0f, -1.0f, -1.0f, 2.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f) }, // negative x
232 		{ tcu::Vec4( 0.0f, -1.0f, -1.0f, 2.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f) }, // positive x
233 		{ tcu::Vec4(-1.0f,  0.0f, -1.0f, 2.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f) }, // negative y
234 		{ tcu::Vec4(-1.0f, -1.0f,  0.0f, 2.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f) }, // positive y
235 		{ tcu::Vec4(-1.0f, -1.0f, -1.0f, 0.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f) }, // negative z
236 		{ tcu::Vec4( 0.0f,  0.0f,  0.0f, 2.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f) }  // positive z
237 	};
238 
239 	int numLevels = m_useMipmaps ? deLog2Floor32(de::max(m_width, m_height))+1 : 1;
240 
241 	// Fill levels.
242 	for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
243 	{
244 		for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
245 		{
246 			m_texture->getRefTexture().allocLevel((tcu::CubeFace)face, levelNdx);
247 			fillWithComponentGradients(m_texture->getRefTexture().getLevelFace(levelNdx, (tcu::CubeFace)face), gradients[face][0], gradients[face][1]);
248 		}
249 	}
250 
251 	// Upload texture data to GL.
252 	m_texture->upload();
253 
254 	// Initialize iteration state.
255 	m_curFace	= 0;
256 	m_isOk		= true;
257 }
258 
deinit(void)259 void TextureCubeSizeCase::deinit (void)
260 {
261 	delete m_texture;
262 	m_texture = DE_NULL;
263 
264 	m_renderer.clear();
265 }
266 
testFace(tcu::CubeFace face)267 bool TextureCubeSizeCase::testFace (tcu::CubeFace face)
268 {
269 	const glw::Functions&	gl				= m_renderCtx.getFunctions();
270 	TestLog&				log				= m_testCtx.getLog();
271 	RandomViewport			viewport		(m_renderCtx.getRenderTarget(), 128, 128, deStringHash(getName())+(deUint32)face);
272 	tcu::Surface			renderedFrame	(viewport.width, viewport.height);
273 	tcu::Surface			referenceFrame	(viewport.width, viewport.height);
274 	const tcu::IVec4		texBits			= tcu::getTextureFormatBitDepth(glu::mapGLTransferFormat(m_format, m_dataType));
275 	const tcu::PixelFormat&	rtFmt			= m_renderCtx.getRenderTarget().getPixelFormat();
276 	const tcu::PixelFormat	thresholdFormat(de::min(texBits[0], rtFmt.redBits), de::min(texBits[1], rtFmt.greenBits), de::min(texBits[2], rtFmt.blueBits), de::min(texBits[3], rtFmt.alphaBits));
277 	tcu::RGBA				threshold		= thresholdFormat.getColorThreshold() + tcu::RGBA(7,7,7,7);
278 	deUint32				wrapS			= GL_CLAMP_TO_EDGE;
279 	deUint32				wrapT			= GL_CLAMP_TO_EDGE;
280 	// Do not minify with GL_NEAREST. A large POT texture with a small POT render target will produce
281 	// indeterminate results.
282 	deUint32				minFilter		= m_useMipmaps ? GL_NEAREST_MIPMAP_NEAREST : GL_LINEAR;
283 	deUint32				magFilter		= GL_NEAREST;
284 	vector<float>			texCoord;
285 
286 	computeQuadTexCoordCube(texCoord, face);
287 
288 	// \todo [2011-10-28 pyry] Image set name / section?
289 	log << TestLog::Message << face << TestLog::EndMessage;
290 
291 	// Setup base viewport.
292 	gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height);
293 
294 	// Bind to unit 0.
295 	gl.activeTexture(GL_TEXTURE0);
296 	gl.bindTexture(GL_TEXTURE_CUBE_MAP, m_texture->getGLTexture());
297 
298 	gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, wrapS);
299 	gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, wrapT);
300 	gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, minFilter);
301 	gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, magFilter);
302 	GLU_EXPECT_NO_ERROR(gl.getError(), "Set texturing state");
303 
304 	m_renderer.renderQuad(0, &texCoord[0], TEXTURETYPE_CUBE);
305 	glu::readPixels(m_renderCtx, viewport.x, viewport.y, renderedFrame.getAccess());
306 
307 	// Compute reference.
308 	Sampler sampler = mapGLSampler(wrapS, wrapT, minFilter, magFilter);
309 	sampler.seamlessCubeMap = true;
310 	sampleTexture(tcu::SurfaceAccess(referenceFrame, m_renderCtx.getRenderTarget().getPixelFormat()), m_texture->getRefTexture(), &texCoord[0], ReferenceParams(TEXTURETYPE_CUBE, sampler));
311 
312 	// Compare and log.
313 	return compareImages(log, referenceFrame, renderedFrame, threshold);
314 }
315 
iterate(void)316 TextureCubeSizeCase::IterateResult TextureCubeSizeCase::iterate (void)
317 {
318 	// Execute test for all faces.
319 	if (!testFace((tcu::CubeFace)m_curFace))
320 		m_isOk = false;
321 
322 	m_curFace += 1;
323 
324 	if (m_curFace == tcu::CUBEFACE_LAST)
325 	{
326 		m_testCtx.setTestResult(m_isOk ? QP_TEST_RESULT_PASS	: QP_TEST_RESULT_FAIL,
327 								m_isOk ? "Pass"					: "Image comparison failed");
328 		return STOP;
329 	}
330 	else
331 		return CONTINUE;
332 }
333 
TextureSizeTests(Context & context)334 TextureSizeTests::TextureSizeTests (Context& context)
335 	: TestCaseGroup(context, "size", "Texture Size Tests")
336 {
337 }
338 
~TextureSizeTests(void)339 TextureSizeTests::~TextureSizeTests (void)
340 {
341 }
342 
init(void)343 void TextureSizeTests::init (void)
344 {
345 	struct
346 	{
347 		int	width;
348 		int	height;
349 	} sizes2D[] =
350 	{
351 		{   64,   64 }, // Spec-mandated minimum.
352 		{   65,   63 },
353 		{  512,  512 },
354 		{ 1024, 1024 },
355 		{ 2048, 2048 }
356 	};
357 
358 	struct
359 	{
360 		int	width;
361 		int	height;
362 	} sizesCube[] =
363 	{
364 		{  15,  15 },
365 		{  16,  16 }, // Spec-mandated minimum
366 		{  64,  64 },
367 		{ 128, 128 },
368 		{ 256, 256 },
369 		{ 512, 512 }
370 	};
371 
372 	struct
373 	{
374 		const char*	name;
375 		deUint32	format;
376 		deUint32	dataType;
377 	} formats[] =
378 	{
379 		{ "l8",			GL_LUMINANCE,		GL_UNSIGNED_BYTE },
380 		{ "rgba4444",	GL_RGBA,			GL_UNSIGNED_SHORT_4_4_4_4 },
381 		{ "rgb888",		GL_RGB,				GL_UNSIGNED_BYTE },
382 		{ "rgba8888",	GL_RGBA,			GL_UNSIGNED_BYTE }
383 	};
384 
385 	// 2D cases.
386 	tcu::TestCaseGroup* group2D = new tcu::TestCaseGroup(m_testCtx, "2d", "2D Texture Size Tests");
387 	addChild(group2D);
388 	for (int sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(sizes2D); sizeNdx++)
389 	{
390 		int		width	= sizes2D[sizeNdx].width;
391 		int		height	= sizes2D[sizeNdx].height;
392 		bool	isPOT	= deIsPowerOfTwo32(width) && deIsPowerOfTwo32(height);
393 
394 		for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); formatNdx++)
395 		{
396 			for (int mipmap = 0; mipmap < (isPOT ? 2 : 1); mipmap++)
397 			{
398 				std::ostringstream name;
399 				name << width << "x" << height << "_" << formats[formatNdx].name << (mipmap ? "_mipmap" : "");
400 
401 				group2D->addChild(new Texture2DSizeCase(m_testCtx, m_context.getRenderContext(), name.str().c_str(), "",
402 														formats[formatNdx].format, formats[formatNdx].dataType,
403 														width, height, mipmap != 0));
404 			}
405 		}
406 	}
407 
408 	// Cubemap cases.
409 	tcu::TestCaseGroup* groupCube = new tcu::TestCaseGroup(m_testCtx, "cube", "Cubemap Texture Size Tests");
410 	addChild(groupCube);
411 	for (int sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(sizesCube); sizeNdx++)
412 	{
413 		int		width	= sizesCube[sizeNdx].width;
414 		int		height	= sizesCube[sizeNdx].height;
415 		bool	isPOT	= deIsPowerOfTwo32(width) && deIsPowerOfTwo32(height);
416 
417 		for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); formatNdx++)
418 		{
419 			for (int mipmap = 0; mipmap < (isPOT ? 2 : 1); mipmap++)
420 			{
421 				std::ostringstream name;
422 				name << width << "x" << height << "_" << formats[formatNdx].name << (mipmap ? "_mipmap" : "");
423 
424 				groupCube->addChild(new TextureCubeSizeCase(m_testCtx, m_context.getRenderContext(), name.str().c_str(), "",
425 															formats[formatNdx].format, formats[formatNdx].dataType,
426 															width, height, mipmap != 0));
427 			}
428 		}
429 	}
430 }
431 
432 } // Functional
433 } // gles3
434 } // deqp
435