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 State Query tests.
22  *//*--------------------------------------------------------------------*/
23 
24 #include "es2fTextureStateQueryTests.hpp"
25 #include "es2fApiCase.hpp"
26 #include "glsStateQueryUtil.hpp"
27 #include "gluRenderContext.hpp"
28 #include "glwEnums.hpp"
29 #include "glwFunctions.hpp"
30 #include "deRandom.hpp"
31 #include "deMath.h"
32 
33 using namespace glw; // GLint and other GL types
34 using namespace deqp::gls;
35 using deqp::gls::StateQueryUtil::StateQueryMemoryWriteGuard;
36 
37 
38 namespace deqp
39 {
40 namespace gles2
41 {
42 namespace Functional
43 {
44 namespace TextureParamVerifiers
45 {
46 
47 // TexParamVerifier
48 
49 class TexParamVerifier : protected glu::CallLogWrapper
50 {
51 public:
52 						TexParamVerifier	(const glw::Functions& gl, tcu::TestLog& log, const char* testNamePostfix);
53 	virtual				~TexParamVerifier	(); // make GCC happy
54 
55 	const char*			getTestNamePostfix	(void) const;
56 
57 	virtual void		verifyInteger		(tcu::TestContext& testCtx, GLenum target, GLenum name, GLint reference)	= DE_NULL;
58 	virtual void		verifyFloat			(tcu::TestContext& testCtx, GLenum target, GLenum name, GLfloat reference)	= DE_NULL;
59 private:
60 	const char*	const	m_testNamePostfix;
61 };
62 
TexParamVerifier(const glw::Functions & gl,tcu::TestLog & log,const char * testNamePostfix)63 TexParamVerifier::TexParamVerifier (const glw::Functions& gl, tcu::TestLog& log, const char* testNamePostfix)
64 	: glu::CallLogWrapper	(gl, log)
65 	, m_testNamePostfix		(testNamePostfix)
66 {
67 	enableLogging(true);
68 }
~TexParamVerifier()69 TexParamVerifier::~TexParamVerifier ()
70 {
71 }
72 
getTestNamePostfix(void) const73 const char* TexParamVerifier::getTestNamePostfix (void) const
74 {
75 	return m_testNamePostfix;
76 }
77 
78 class GetTexParameterIVerifier : public TexParamVerifier
79 {
80 public:
81 			GetTexParameterIVerifier	(const glw::Functions& gl, tcu::TestLog& log);
82 
83 	void	verifyInteger				(tcu::TestContext& testCtx, GLenum target, GLenum name, GLint reference);
84 	void	verifyFloat					(tcu::TestContext& testCtx, GLenum target, GLenum name, GLfloat reference);
85 };
86 
GetTexParameterIVerifier(const glw::Functions & gl,tcu::TestLog & log)87 GetTexParameterIVerifier::GetTexParameterIVerifier (const glw::Functions& gl, tcu::TestLog& log)
88 	: TexParamVerifier(gl, log, "_gettexparameteri")
89 {
90 }
91 
verifyInteger(tcu::TestContext & testCtx,GLenum target,GLenum name,GLint reference)92 void GetTexParameterIVerifier::verifyInteger (tcu::TestContext& testCtx, GLenum target, GLenum name, GLint reference)
93 {
94 	using tcu::TestLog;
95 
96 	StateQueryMemoryWriteGuard<GLint> state;
97 	glGetTexParameteriv(target, name, &state);
98 
99 	if (!state.verifyValidity(testCtx))
100 		return;
101 
102 	if (state != reference)
103 	{
104 		testCtx.getLog() << TestLog::Message << "// ERROR: expected " << reference << "; got " << state << TestLog::EndMessage;
105 
106 		if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
107 			testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid texture param value");
108 	}
109 }
110 
verifyFloat(tcu::TestContext & testCtx,GLenum target,GLenum name,GLfloat reference)111 void GetTexParameterIVerifier::verifyFloat (tcu::TestContext& testCtx, GLenum target, GLenum name, GLfloat reference)
112 {
113 	using tcu::TestLog;
114 
115 	const GLint expectedGLStateMax = StateQueryUtil::roundGLfloatToNearestIntegerHalfUp<GLint>(reference);
116 	const GLint expectedGLStateMin = StateQueryUtil::roundGLfloatToNearestIntegerHalfDown<GLint>(reference);
117 
118 	StateQueryMemoryWriteGuard<GLint> state;
119 	glGetTexParameteriv(target, name, &state);
120 
121 	if (!state.verifyValidity(testCtx))
122 		return;
123 
124 	if (state < expectedGLStateMin || state > expectedGLStateMax)
125 	{
126 		testCtx.getLog() << TestLog::Message << "// ERROR: expected in range [" << expectedGLStateMin << ", " << expectedGLStateMax << "]; got " << state << TestLog::EndMessage;
127 
128 		if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
129 			testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid texture param value");
130 	}
131 }
132 
133 class GetTexParameterFVerifier : public TexParamVerifier
134 {
135 public:
136 			GetTexParameterFVerifier	(const glw::Functions& gl, tcu::TestLog& log);
137 
138 	void	verifyInteger				(tcu::TestContext& testCtx, GLenum target, GLenum name, GLint reference);
139 	void	verifyFloat					(tcu::TestContext& testCtx, GLenum target, GLenum name, GLfloat reference);
140 };
141 
GetTexParameterFVerifier(const glw::Functions & gl,tcu::TestLog & log)142 GetTexParameterFVerifier::GetTexParameterFVerifier (const glw::Functions& gl, tcu::TestLog& log)
143 	: TexParamVerifier(gl, log, "_gettexparameterf")
144 {
145 }
146 
verifyInteger(tcu::TestContext & testCtx,GLenum target,GLenum name,GLint reference)147 void GetTexParameterFVerifier::verifyInteger (tcu::TestContext& testCtx, GLenum target, GLenum name, GLint reference)
148 {
149 	DE_ASSERT(reference == GLint(GLfloat(reference))); // reference integer must have 1:1 mapping to float for this to work. Reference value is always such value in these tests
150 
151 	using tcu::TestLog;
152 
153 	const GLfloat referenceAsFloat = GLfloat(reference);
154 
155 	StateQueryMemoryWriteGuard<GLfloat> state;
156 	glGetTexParameterfv(target, name, &state);
157 
158 	if (!state.verifyValidity(testCtx))
159 		return;
160 
161 	if (state != referenceAsFloat)
162 	{
163 		testCtx.getLog() << TestLog::Message << "// ERROR: expected " << referenceAsFloat << "; got " << state << TestLog::EndMessage;
164 
165 		if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
166 			testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid float value");
167 	}
168 }
169 
verifyFloat(tcu::TestContext & testCtx,GLenum target,GLenum name,GLfloat reference)170 void GetTexParameterFVerifier::verifyFloat (tcu::TestContext& testCtx, GLenum target, GLenum name, GLfloat reference)
171 {
172 	using tcu::TestLog;
173 
174 	StateQueryMemoryWriteGuard<GLfloat> state;
175 	glGetTexParameterfv(target, name, &state);
176 
177 	if (!state.verifyValidity(testCtx))
178 		return;
179 
180 	if (state != reference)
181 	{
182 		testCtx.getLog() << TestLog::Message << "// ERROR: expected " << reference << "; got " << state << TestLog::EndMessage;
183 
184 		if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
185 			testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid float value");
186 	}
187 }
188 
189 } // TextureParamVerifiers
190 
191 namespace
192 {
193 
194 using namespace TextureParamVerifiers;
195 
196 // Tests
197 
198 class TextureCase : public ApiCase
199 {
200 public:
TextureCase(Context & context,TexParamVerifier * verifier,const char * name,const char * description,GLenum textureTarget)201 	TextureCase (Context& context, TexParamVerifier* verifier, const char* name, const char* description, GLenum textureTarget)
202 		: ApiCase			(context, name, description)
203 		, m_textureTarget	(textureTarget)
204 		, m_verifier		(verifier)
205 	{
206 	}
207 
208 	virtual void testTexture (void) = DE_NULL;
209 
test(void)210 	void test (void)
211 	{
212 		GLuint textureId = 0;
213 		glGenTextures(1, &textureId);
214 		glBindTexture(m_textureTarget, textureId);
215 		expectError(GL_NO_ERROR);
216 
217 		testTexture();
218 
219 		glDeleteTextures(1, &textureId);
220 		expectError(GL_NO_ERROR);
221 	}
222 
223 protected:
224 	GLenum				m_textureTarget;
225 	TexParamVerifier*	m_verifier;
226 };
227 
228 class TextureWrapCase : public TextureCase
229 {
230 public:
TextureWrapCase(Context & context,TexParamVerifier * verifier,const char * name,const char * description,GLenum textureTarget,GLenum valueName)231 	TextureWrapCase (Context& context, TexParamVerifier* verifier, const char* name, const char* description, GLenum textureTarget, GLenum valueName)
232 		: TextureCase	(context, verifier, name, description, textureTarget)
233 		, m_valueName	(valueName)
234 	{
235 	}
236 
testTexture(void)237 	void testTexture (void)
238 	{
239 		const GLenum wrapValues[] = {GL_CLAMP_TO_EDGE, GL_REPEAT, GL_MIRRORED_REPEAT};
240 
241 		m_verifier->verifyInteger(m_testCtx, m_textureTarget, m_valueName, GL_REPEAT);
242 		expectError(GL_NO_ERROR);
243 
244 		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(wrapValues); ++ndx)
245 		{
246 			glTexParameteri(m_textureTarget, m_valueName, wrapValues[ndx]);
247 			expectError(GL_NO_ERROR);
248 
249 			m_verifier->verifyInteger(m_testCtx, m_textureTarget, m_valueName, wrapValues[ndx]);
250 			expectError(GL_NO_ERROR);
251 		}
252 
253 		//check unit conversions with float
254 
255 		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(wrapValues); ++ndx)
256 		{
257 			glTexParameterf(m_textureTarget, m_valueName, (GLfloat)wrapValues[ndx]);
258 			expectError(GL_NO_ERROR);
259 
260 			m_verifier->verifyInteger(m_testCtx, m_textureTarget, m_valueName, wrapValues[ndx]);
261 			expectError(GL_NO_ERROR);
262 		}
263 	}
264 
265 private:
266 	GLenum	m_valueName;
267 };
268 
269 class TextureMagFilterCase : public TextureCase
270 {
271 public:
TextureMagFilterCase(Context & context,TexParamVerifier * verifier,const char * name,const char * description,GLenum textureTarget)272 	TextureMagFilterCase (Context& context, TexParamVerifier* verifier, const char* name, const char* description, GLenum textureTarget)
273 		: TextureCase(context, verifier, name, description, textureTarget)
274 	{
275 	}
276 
testTexture(void)277 	void testTexture (void)
278 	{
279 		const GLenum magValues[] = {GL_NEAREST, GL_LINEAR};
280 
281 		m_verifier->verifyInteger(m_testCtx, m_textureTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
282 		expectError(GL_NO_ERROR);
283 
284 		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(magValues); ++ndx)
285 		{
286 			glTexParameteri(m_textureTarget, GL_TEXTURE_MAG_FILTER, magValues[ndx]);
287 			expectError(GL_NO_ERROR);
288 
289 			m_verifier->verifyInteger(m_testCtx, m_textureTarget, GL_TEXTURE_MAG_FILTER, magValues[ndx]);
290 			expectError(GL_NO_ERROR);
291 		}
292 
293 		//check unit conversions with float
294 
295 		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(magValues); ++ndx)
296 		{
297 			glTexParameterf(m_textureTarget, GL_TEXTURE_MAG_FILTER, (GLfloat)magValues[ndx]);
298 			expectError(GL_NO_ERROR);
299 
300 			m_verifier->verifyInteger(m_testCtx, m_textureTarget, GL_TEXTURE_MAG_FILTER, magValues[ndx]);
301 			expectError(GL_NO_ERROR);
302 		}
303 	}
304 };
305 
306 class TextureMinFilterCase : public TextureCase
307 {
308 public:
TextureMinFilterCase(Context & context,TexParamVerifier * verifier,const char * name,const char * description,GLenum textureTarget)309 	TextureMinFilterCase (Context& context, TexParamVerifier* verifier, const char* name, const char* description, GLenum textureTarget)
310 		: TextureCase(context, verifier, name, description, textureTarget)
311 	{
312 	}
313 
testTexture(void)314 	void testTexture (void)
315 	{
316 		const GLenum minValues[] = {GL_NEAREST, GL_LINEAR, GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR, GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_LINEAR};
317 
318 		m_verifier->verifyInteger(m_testCtx, m_textureTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);
319 		expectError(GL_NO_ERROR);
320 
321 		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(minValues); ++ndx)
322 		{
323 			glTexParameteri(m_textureTarget, GL_TEXTURE_MIN_FILTER, minValues[ndx]);
324 			expectError(GL_NO_ERROR);
325 
326 			m_verifier->verifyInteger(m_testCtx, m_textureTarget, GL_TEXTURE_MIN_FILTER, minValues[ndx]);
327 			expectError(GL_NO_ERROR);
328 		}
329 
330 		//check unit conversions with float
331 
332 		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(minValues); ++ndx)
333 		{
334 			glTexParameterf(m_textureTarget, GL_TEXTURE_MIN_FILTER, (GLfloat)minValues[ndx]);
335 			expectError(GL_NO_ERROR);
336 
337 			m_verifier->verifyInteger(m_testCtx, m_textureTarget, GL_TEXTURE_MIN_FILTER, minValues[ndx]);
338 			expectError(GL_NO_ERROR);
339 		}
340 	}
341 };
342 
343 } // anonymous
344 
345 #define FOR_EACH_VERIFIER(VERIFIERS, CODE_BLOCK)												\
346 	for (int _verifierNdx = 0; _verifierNdx < DE_LENGTH_OF_ARRAY(VERIFIERS); _verifierNdx++)	\
347 	{																							\
348 		TexParamVerifier* verifier = VERIFIERS[_verifierNdx];									\
349 		CODE_BLOCK;																				\
350 	}
351 
TextureStateQueryTests(Context & context)352 TextureStateQueryTests::TextureStateQueryTests (Context& context)
353 	: TestCaseGroup		(context, "texture", "Texture State Query tests")
354 	, m_verifierInt		(DE_NULL)
355 	, m_verifierFloat	(DE_NULL)
356 {
357 }
358 
~TextureStateQueryTests(void)359 TextureStateQueryTests::~TextureStateQueryTests (void)
360 {
361 	deinit();
362 }
363 
init(void)364 void TextureStateQueryTests::init (void)
365 {
366 	using namespace TextureParamVerifiers;
367 
368 	DE_ASSERT(m_verifierInt == DE_NULL);
369 	DE_ASSERT(m_verifierFloat == DE_NULL);
370 
371 	m_verifierInt		= new GetTexParameterIVerifier(m_context.getRenderContext().getFunctions(), m_context.getTestContext().getLog());
372 	m_verifierFloat		= new GetTexParameterFVerifier(m_context.getRenderContext().getFunctions(), m_context.getTestContext().getLog());
373 
374 	TexParamVerifier* verifiers[] = {m_verifierInt, m_verifierFloat};
375 
376 	const struct
377 	{
378 		const char*	name;
379 		GLenum		textureTarget;
380 	} textureTargets[] =
381 	{
382 		{ "texture_2d",			GL_TEXTURE_2D},
383 		{ "texture_cube_map",	GL_TEXTURE_CUBE_MAP}
384 	};
385 
386 	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(textureTargets); ++ndx)
387 	{
388 		FOR_EACH_VERIFIER(verifiers, addChild(new TextureWrapCase		(m_context, verifier,	(std::string(textureTargets[ndx].name)	+ "_texture_wrap_s"			+ verifier->getTestNamePostfix()).c_str(), "TEXTURE_WRAP_S",		textureTargets[ndx].textureTarget, GL_TEXTURE_WRAP_S)));
389 		FOR_EACH_VERIFIER(verifiers, addChild(new TextureWrapCase		(m_context, verifier,	(std::string(textureTargets[ndx].name)	+ "_texture_wrap_t"			+ verifier->getTestNamePostfix()).c_str(), "TEXTURE_WRAP_T",		textureTargets[ndx].textureTarget, GL_TEXTURE_WRAP_T)));
390 
391 		FOR_EACH_VERIFIER(verifiers, addChild(new TextureMagFilterCase	(m_context, verifier,	(std::string(textureTargets[ndx].name)	+ "_texture_mag_filter"		+ verifier->getTestNamePostfix()).c_str(), "TEXTURE_MAG_FILTER",	textureTargets[ndx].textureTarget)));
392 		FOR_EACH_VERIFIER(verifiers, addChild(new TextureMinFilterCase	(m_context, verifier,	(std::string(textureTargets[ndx].name)	+ "_texture_min_filter"		+ verifier->getTestNamePostfix()).c_str(), "TEXTURE_MIN_FILTER",	textureTargets[ndx].textureTarget)));
393 	}
394 }
395 
deinit(void)396 void TextureStateQueryTests::deinit (void)
397 {
398 	if (m_verifierInt)
399 	{
400 		delete m_verifierInt;
401 		m_verifierInt = NULL;
402 	}
403 	if (m_verifierFloat)
404 	{
405 		delete m_verifierFloat;
406 		m_verifierFloat = NULL;
407 	}
408 
409 	this->TestCaseGroup::deinit();
410 }
411 
412 } // Functional
413 } // gles2
414 } // deqp
415