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
33using namespace glw; // GLint and other GL types
34using namespace deqp::gls;
35using deqp::gls::StateQueryUtil::StateQueryMemoryWriteGuard;
36
37
38namespace deqp
39{
40namespace gles2
41{
42namespace Functional
43{
44namespace TextureParamVerifiers
45{
46
47// TexParamVerifier
48
49class TexParamVerifier : protected glu::CallLogWrapper
50{
51public:
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;
59private:
60	const char*	const	m_testNamePostfix;
61};
62
63TexParamVerifier::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}
69TexParamVerifier::~TexParamVerifier ()
70{
71}
72
73const char* TexParamVerifier::getTestNamePostfix (void) const
74{
75	return m_testNamePostfix;
76}
77
78class GetTexParameterIVerifier : public TexParamVerifier
79{
80public:
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
87GetTexParameterIVerifier::GetTexParameterIVerifier (const glw::Functions& gl, tcu::TestLog& log)
88	: TexParamVerifier(gl, log, "_gettexparameteri")
89{
90}
91
92void 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
111void 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
133class GetTexParameterFVerifier : public TexParamVerifier
134{
135public:
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
142GetTexParameterFVerifier::GetTexParameterFVerifier (const glw::Functions& gl, tcu::TestLog& log)
143	: TexParamVerifier(gl, log, "_gettexparameterf")
144{
145}
146
147void 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
170void 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
191namespace
192{
193
194using namespace TextureParamVerifiers;
195
196// Tests
197
198class TextureCase : public ApiCase
199{
200public:
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
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
223protected:
224	GLenum				m_textureTarget;
225	TexParamVerifier*	m_verifier;
226};
227
228class TextureWrapCase : public TextureCase
229{
230public:
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
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
265private:
266	GLenum	m_valueName;
267};
268
269class TextureMagFilterCase : public TextureCase
270{
271public:
272	TextureMagFilterCase (Context& context, TexParamVerifier* verifier, const char* name, const char* description, GLenum textureTarget)
273		: TextureCase(context, verifier, name, description, textureTarget)
274	{
275	}
276
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
306class TextureMinFilterCase : public TextureCase
307{
308public:
309	TextureMinFilterCase (Context& context, TexParamVerifier* verifier, const char* name, const char* description, GLenum textureTarget)
310		: TextureCase(context, verifier, name, description, textureTarget)
311	{
312	}
313
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
352TextureStateQueryTests::TextureStateQueryTests (Context& context)
353	: TestCaseGroup		(context, "texture", "Texture State Query tests")
354	, m_verifierInt		(DE_NULL)
355	, m_verifierFloat	(DE_NULL)
356{
357}
358
359TextureStateQueryTests::~TextureStateQueryTests (void)
360{
361	deinit();
362}
363
364void 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
396void 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