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 Integer64 State Query tests.
22 *//*--------------------------------------------------------------------*/
23
24#include "es3fInteger64StateQueryTests.hpp"
25#include "glsStateQueryUtil.hpp"
26#include "es3fApiCase.hpp"
27#include "gluRenderContext.hpp"
28#include "tcuRenderTarget.hpp"
29#include "glwEnums.hpp"
30
31#include <limits>
32
33using namespace glw; // GLint and other
34using deqp::gls::StateQueryUtil::StateQueryMemoryWriteGuard;
35
36namespace deqp
37{
38namespace gles3
39{
40namespace Functional
41{
42namespace Integer64StateQueryVerifiers
43{
44
45// StateVerifier
46
47class StateVerifier : protected glu::CallLogWrapper
48{
49public:
50						StateVerifier							(const glw::Functions& gl, tcu::TestLog& log, const char* testNamePostfix);
51	virtual				~StateVerifier							(); // make GCC happy
52
53	const char*			getTestNamePostfix						(void) const;
54
55	virtual void		verifyUnsignedInteger64GreaterOrEqual	(tcu::TestContext& testCtx, GLenum name, GLuint64 reference) = DE_NULL;
56
57private:
58	const char*	const	m_testNamePostfix;
59};
60
61StateVerifier::StateVerifier (const glw::Functions& gl, tcu::TestLog& log, const char* testNamePostfix)
62	: glu::CallLogWrapper	(gl, log)
63	, m_testNamePostfix		(testNamePostfix)
64{
65	enableLogging(true);
66}
67
68StateVerifier::~StateVerifier ()
69{
70}
71
72const char* StateVerifier::getTestNamePostfix (void) const
73{
74	return m_testNamePostfix;
75}
76
77// GetBooleanVerifier
78
79class GetBooleanVerifier : public StateVerifier
80{
81public:
82			GetBooleanVerifier				(const glw::Functions& gl, tcu::TestLog& log);
83	void	verifyUnsignedInteger64GreaterOrEqual	(tcu::TestContext& testCtx, GLenum name, GLuint64 reference);
84};
85
86GetBooleanVerifier::GetBooleanVerifier (const glw::Functions& gl, tcu::TestLog& log)
87	: StateVerifier(gl, log, "_getboolean")
88{
89}
90
91void GetBooleanVerifier::verifyUnsignedInteger64GreaterOrEqual (tcu::TestContext& testCtx, GLenum name, GLuint64 reference)
92{
93	using tcu::TestLog;
94
95	StateQueryMemoryWriteGuard<GLboolean> state;
96	glGetBooleanv(name, &state);
97
98	if (!state.verifyValidity(testCtx))
99		return;
100
101	if (state == GL_TRUE) // state is non-zero, could be greater than reference (correct)
102		return;
103
104	if (state == GL_FALSE) // state is zero
105	{
106		if (reference > 0) // and reference is greater than zero?
107		{
108			testCtx.getLog() << TestLog::Message << "// ERROR: expected GL_TRUE" << TestLog::EndMessage;
109			if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
110				testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid boolean value");
111		}
112	}
113	else
114	{
115		testCtx.getLog() << TestLog::Message << "// ERROR: expected GL_TRUE or GL_FALSE" << TestLog::EndMessage;
116		if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
117			testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid boolean value");
118	}
119}
120
121//GetIntegerVerifier
122
123class GetIntegerVerifier : public StateVerifier
124{
125public:
126			GetIntegerVerifier				(const glw::Functions& gl, tcu::TestLog& log);
127	void	verifyUnsignedInteger64GreaterOrEqual	(tcu::TestContext& testCtx, GLenum name, GLuint64 reference);
128};
129
130GetIntegerVerifier::GetIntegerVerifier (const glw::Functions& gl, tcu::TestLog& log)
131	: StateVerifier(gl, log, "_getinteger")
132{
133}
134
135void GetIntegerVerifier::verifyUnsignedInteger64GreaterOrEqual (tcu::TestContext& testCtx, GLenum name, GLuint64 reference)
136{
137	using tcu::TestLog;
138
139	StateQueryMemoryWriteGuard<GLint> state;
140	glGetIntegerv(name, &state);
141
142	if (!state.verifyValidity(testCtx))
143		return;
144
145	// check that the converted value would be in the correct range, otherwise checking wont tell us anything
146	if (reference > (GLuint64)std::numeric_limits<GLint>::max())
147		return;
148
149	if (GLuint(state) < reference)
150	{
151		testCtx.getLog() << TestLog::Message << "// ERROR: expected greater or equal to " << reference << "; got " << state << TestLog::EndMessage;
152		if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
153			testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid integer value");
154	}
155}
156
157//GetFloatVerifier
158
159class GetFloatVerifier : public StateVerifier
160{
161public:
162			GetFloatVerifier					(const glw::Functions& gl, tcu::TestLog& log);
163	void	verifyUnsignedInteger64GreaterOrEqual	(tcu::TestContext& testCtx, GLenum name, GLuint64 reference);
164};
165
166GetFloatVerifier::GetFloatVerifier (const glw::Functions& gl, tcu::TestLog& log)
167	: StateVerifier(gl, log, "_getfloat")
168{
169}
170
171void GetFloatVerifier::verifyUnsignedInteger64GreaterOrEqual (tcu::TestContext& testCtx, GLenum name, GLuint64 reference)
172{
173	using tcu::TestLog;
174
175	StateQueryMemoryWriteGuard<GLfloat> state;
176	glGetFloatv(name, &state);
177
178	if (!state.verifyValidity(testCtx))
179		return;
180
181	if (state < GLfloat(reference))
182	{
183		testCtx.getLog() << TestLog::Message << "// ERROR: expected greater or equal to " << GLfloat(reference) << "; got " << state << TestLog::EndMessage;
184		if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
185			testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid float value");
186	}
187}
188
189} // Integer64StateQueryVerifiers
190
191namespace
192{
193
194using namespace Integer64StateQueryVerifiers;
195
196class ConstantMinimumValue64TestCase : public ApiCase
197{
198public:
199	ConstantMinimumValue64TestCase (Context& context, StateVerifier* verifier, const char* name, const char* description, GLenum targetName, GLuint64 minValue)
200		: ApiCase		(context, name, description)
201		, m_targetName	(targetName)
202		, m_minValue	(minValue)
203		, m_verifier	(verifier)
204	{
205	}
206
207	void test (void)
208	{
209		m_verifier->verifyUnsignedInteger64GreaterOrEqual(m_testCtx, m_targetName, m_minValue);
210		expectError(GL_NO_ERROR);
211	}
212
213private:
214	GLenum			m_targetName;
215	GLuint64		m_minValue;
216	StateVerifier*	m_verifier;
217};
218
219class MaxCombinedStageUniformComponentsCase : public ApiCase
220{
221public:
222	MaxCombinedStageUniformComponentsCase (Context& context, StateVerifier* verifier, const char* name, const char* description, GLenum targetName, GLenum targetMaxUniformBlocksName, GLenum targetMaxUniformComponentsName)
223		: ApiCase							(context, name, description)
224		, m_targetName						(targetName)
225		, m_targetMaxUniformBlocksName		(targetMaxUniformBlocksName)
226		, m_targetMaxUniformComponentsName	(targetMaxUniformComponentsName)
227		, m_verifier						(verifier)
228	{
229	}
230
231	void test (void)
232	{
233		GLint uniformBlockSize = 0;
234		glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &uniformBlockSize);
235		expectError(GL_NO_ERROR);
236
237		GLint maxUniformBlocks = 0;
238		GLint maxUniformComponents = 0;
239		glGetIntegerv(m_targetMaxUniformBlocksName, &maxUniformBlocks);
240		glGetIntegerv(m_targetMaxUniformComponentsName, &maxUniformComponents);
241		expectError(GL_NO_ERROR);
242
243		// MAX_stage_UNIFORM_BLOCKS * MAX_UNIFORM_BLOCK_SIZE / 4 + MAX_stage_UNIFORM_COMPONENTS
244		const GLuint64 minCombinedUniformComponents = GLuint64(maxUniformBlocks) * uniformBlockSize / 4 + maxUniformComponents;
245
246		m_verifier->verifyUnsignedInteger64GreaterOrEqual(m_testCtx, m_targetName, minCombinedUniformComponents);
247		expectError(GL_NO_ERROR);
248	}
249
250private:
251	GLenum			m_targetName;
252	GLenum			m_targetMaxUniformBlocksName;
253	GLenum			m_targetMaxUniformComponentsName;
254	StateVerifier*	m_verifier;
255};
256
257#define FOR_EACH_VERIFIER(VERIFIERS, CODE_BLOCK)												\
258	for (int _verifierNdx = 0; _verifierNdx < DE_LENGTH_OF_ARRAY(VERIFIERS); _verifierNdx++)	\
259	{																							\
260		StateVerifier* verifier = VERIFIERS[_verifierNdx];										\
261		CODE_BLOCK;																				\
262	}
263
264} // anonymous
265
266Integer64StateQueryTests::Integer64StateQueryTests (Context& context)
267	: TestCaseGroup			(context, "integers64", "Integer (64) Values")
268	, m_verifierBoolean		(DE_NULL)
269	, m_verifierInteger		(DE_NULL)
270	, m_verifierFloat		(DE_NULL)
271{
272}
273
274Integer64StateQueryTests::~Integer64StateQueryTests (void)
275{
276	deinit();
277}
278
279void Integer64StateQueryTests::init (void)
280{
281	DE_ASSERT(m_verifierBoolean == DE_NULL);
282	DE_ASSERT(m_verifierInteger == DE_NULL);
283	DE_ASSERT(m_verifierFloat == DE_NULL);
284
285	m_verifierBoolean		= new GetBooleanVerifier		(m_context.getRenderContext().getFunctions(), m_context.getTestContext().getLog());
286	m_verifierInteger		= new GetIntegerVerifier		(m_context.getRenderContext().getFunctions(), m_context.getTestContext().getLog());
287	m_verifierFloat			= new GetFloatVerifier			(m_context.getRenderContext().getFunctions(), m_context.getTestContext().getLog());
288
289	const struct LimitedStateInteger64
290	{
291		const char*		name;
292		const char*		description;
293		GLenum			targetName;
294		GLuint64		minValue;
295	} implementationLimits[] =
296	{
297		{ "max_element_index",			"MAX_ELEMENT_INDEX",		GL_MAX_ELEMENT_INDEX,			0x00FFFFFF /*2^24-1*/	},
298		{ "max_server_wait_timeout",	"MAX_SERVER_WAIT_TIMEOUT",	GL_MAX_SERVER_WAIT_TIMEOUT,		0						},
299		{ "max_uniform_block_size",		"MAX_UNIFORM_BLOCK_SIZE",	GL_MAX_UNIFORM_BLOCK_SIZE,		16384					}
300	};
301
302	// \note do not check the values with integer64 verifier as that has already been checked in implementation_limits
303	StateVerifier* verifiers[] = {m_verifierBoolean, m_verifierInteger, m_verifierFloat};
304
305	for (int testNdx = 0; testNdx < DE_LENGTH_OF_ARRAY(implementationLimits); testNdx++)
306		FOR_EACH_VERIFIER(verifiers, addChild(new ConstantMinimumValue64TestCase(m_context, verifier, (std::string(implementationLimits[testNdx].name) + verifier->getTestNamePostfix()).c_str(), implementationLimits[testNdx].description, implementationLimits[testNdx].targetName, implementationLimits[testNdx].minValue)));
307
308	FOR_EACH_VERIFIER(verifiers, addChild(new MaxCombinedStageUniformComponentsCase (m_context, verifier,	(std::string("max_combined_vertex_uniform_components")		+ verifier->getTestNamePostfix()).c_str(),	"MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS",	GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS,		GL_MAX_VERTEX_UNIFORM_BLOCKS,		GL_MAX_VERTEX_UNIFORM_COMPONENTS)));
309	FOR_EACH_VERIFIER(verifiers, addChild(new MaxCombinedStageUniformComponentsCase (m_context, verifier,	(std::string("max_combined_fragment_uniform_components")	+ verifier->getTestNamePostfix()).c_str(),	"MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS",	GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS,	GL_MAX_FRAGMENT_UNIFORM_BLOCKS,		GL_MAX_FRAGMENT_UNIFORM_COMPONENTS)));
310}
311
312void Integer64StateQueryTests::deinit (void)
313{
314	if (m_verifierBoolean)
315	{
316		delete m_verifierBoolean;
317		m_verifierBoolean = DE_NULL;
318	}
319	if (m_verifierInteger)
320	{
321		delete m_verifierInteger;
322		m_verifierInteger = DE_NULL;
323	}
324	if (m_verifierFloat)
325	{
326		delete m_verifierFloat;
327		m_verifierFloat = DE_NULL;
328	}
329
330	this->TestCaseGroup::deinit();
331}
332
333} // Functional
334} // gles3
335} // deqp
336