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 
33 using namespace glw; // GLint and other
34 using deqp::gls::StateQueryUtil::StateQueryMemoryWriteGuard;
35 
36 namespace deqp
37 {
38 namespace gles3
39 {
40 namespace Functional
41 {
42 namespace Integer64StateQueryVerifiers
43 {
44 
45 // StateVerifier
46 
47 class StateVerifier : protected glu::CallLogWrapper
48 {
49 public:
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 
57 private:
58 	const char*	const	m_testNamePostfix;
59 };
60 
StateVerifier(const glw::Functions & gl,tcu::TestLog & log,const char * testNamePostfix)61 StateVerifier::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 
~StateVerifier()68 StateVerifier::~StateVerifier ()
69 {
70 }
71 
getTestNamePostfix(void) const72 const char* StateVerifier::getTestNamePostfix (void) const
73 {
74 	return m_testNamePostfix;
75 }
76 
77 // GetBooleanVerifier
78 
79 class GetBooleanVerifier : public StateVerifier
80 {
81 public:
82 			GetBooleanVerifier				(const glw::Functions& gl, tcu::TestLog& log);
83 	void	verifyUnsignedInteger64GreaterOrEqual	(tcu::TestContext& testCtx, GLenum name, GLuint64 reference);
84 };
85 
GetBooleanVerifier(const glw::Functions & gl,tcu::TestLog & log)86 GetBooleanVerifier::GetBooleanVerifier (const glw::Functions& gl, tcu::TestLog& log)
87 	: StateVerifier(gl, log, "_getboolean")
88 {
89 }
90 
verifyUnsignedInteger64GreaterOrEqual(tcu::TestContext & testCtx,GLenum name,GLuint64 reference)91 void 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 
123 class GetIntegerVerifier : public StateVerifier
124 {
125 public:
126 			GetIntegerVerifier				(const glw::Functions& gl, tcu::TestLog& log);
127 	void	verifyUnsignedInteger64GreaterOrEqual	(tcu::TestContext& testCtx, GLenum name, GLuint64 reference);
128 };
129 
GetIntegerVerifier(const glw::Functions & gl,tcu::TestLog & log)130 GetIntegerVerifier::GetIntegerVerifier (const glw::Functions& gl, tcu::TestLog& log)
131 	: StateVerifier(gl, log, "_getinteger")
132 {
133 }
134 
verifyUnsignedInteger64GreaterOrEqual(tcu::TestContext & testCtx,GLenum name,GLuint64 reference)135 void 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 
159 class GetFloatVerifier : public StateVerifier
160 {
161 public:
162 			GetFloatVerifier					(const glw::Functions& gl, tcu::TestLog& log);
163 	void	verifyUnsignedInteger64GreaterOrEqual	(tcu::TestContext& testCtx, GLenum name, GLuint64 reference);
164 };
165 
GetFloatVerifier(const glw::Functions & gl,tcu::TestLog & log)166 GetFloatVerifier::GetFloatVerifier (const glw::Functions& gl, tcu::TestLog& log)
167 	: StateVerifier(gl, log, "_getfloat")
168 {
169 }
170 
verifyUnsignedInteger64GreaterOrEqual(tcu::TestContext & testCtx,GLenum name,GLuint64 reference)171 void 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 
191 namespace
192 {
193 
194 using namespace Integer64StateQueryVerifiers;
195 
196 class ConstantMinimumValue64TestCase : public ApiCase
197 {
198 public:
ConstantMinimumValue64TestCase(Context & context,StateVerifier * verifier,const char * name,const char * description,GLenum targetName,GLuint64 minValue)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 
test(void)207 	void test (void)
208 	{
209 		m_verifier->verifyUnsignedInteger64GreaterOrEqual(m_testCtx, m_targetName, m_minValue);
210 		expectError(GL_NO_ERROR);
211 	}
212 
213 private:
214 	GLenum			m_targetName;
215 	GLuint64		m_minValue;
216 	StateVerifier*	m_verifier;
217 };
218 
219 class MaxCombinedStageUniformComponentsCase : public ApiCase
220 {
221 public:
MaxCombinedStageUniformComponentsCase(Context & context,StateVerifier * verifier,const char * name,const char * description,GLenum targetName,GLenum targetMaxUniformBlocksName,GLenum targetMaxUniformComponentsName)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 
test(void)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 
250 private:
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 
Integer64StateQueryTests(Context & context)266 Integer64StateQueryTests::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 
~Integer64StateQueryTests(void)274 Integer64StateQueryTests::~Integer64StateQueryTests (void)
275 {
276 	deinit();
277 }
278 
init(void)279 void 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 
deinit(void)312 void 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