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 Float State Query tests.
22 *//*--------------------------------------------------------------------*/
23
24#include "es3fFloatStateQueryTests.hpp"
25#include "glsStateQueryUtil.hpp"
26#include "es3fApiCase.hpp"
27#include "gluRenderContext.hpp"
28#include "tcuRenderTarget.hpp"
29#include "tcuFormatUtil.hpp"
30#include "deRandom.hpp"
31#include "deMath.h"
32#include "glwEnums.hpp"
33
34#include <limits>
35
36using namespace glw; // GLint and other GL types
37using namespace deqp::gls;
38using deqp::gls::StateQueryUtil::StateQueryMemoryWriteGuard;
39
40namespace deqp
41{
42namespace gles3
43{
44namespace Functional
45{
46namespace FloatStateQueryVerifiers
47{
48namespace
49{
50
51const int FLOAT_EXPANSION_E		= 0x03FF; // 10 bits error allowed, requires 22 accurate bits
52const int FLOAT_EXPANSION_E_64	= 0x07FF;
53
54GLint64 expandGLFloatToInteger (GLfloat f)
55{
56	const GLuint64 referenceValue = (GLint64)(f * 2147483647.0);
57	return referenceValue;
58}
59
60GLint clampToGLint (GLint64 val)
61{
62	return (GLint)de::clamp<GLint64>(val, std::numeric_limits<GLint>::min(), std::numeric_limits<GLint>::max());
63}
64
65} // anonymous
66
67// StateVerifier
68
69class StateVerifier : protected glu::CallLogWrapper
70{
71public:
72						StateVerifier					(const glw::Functions& gl, tcu::TestLog& log, const char* testNamePostfix);
73	virtual				~StateVerifier					(); // make GCC happy
74
75	const char*			getTestNamePostfix				(void)																																													const;
76
77	virtual void		verifyFloat						(tcu::TestContext& testCtx, GLenum name, GLfloat reference)																																		= DE_NULL;
78
79	// "Expanded" == Float to int conversion converts from [-1.0 to 1.0] -> [MIN_INT MAX_INT]
80	virtual void		verifyFloatExpanded				(tcu::TestContext& testCtx, GLenum name, GLfloat reference)																																		= DE_NULL;
81	virtual void		verifyFloat2Expanded			(tcu::TestContext& testCtx, GLenum name, GLfloat reference0, GLfloat reference1)																												= DE_NULL;
82	virtual void		verifyFloat4Color				(tcu::TestContext& testCtx, GLenum name, GLfloat reference0, GLfloat reference1, GLfloat reference2, GLfloat reference3)																		= DE_NULL;
83
84	// verify that the given range is completely whitin the GL state range
85	virtual void		verifyFloatRange				(tcu::TestContext& testCtx, GLenum name, GLfloat min, GLfloat max)																																= DE_NULL;
86	virtual void		verifyFloatGreaterOrEqual		(tcu::TestContext& testCtx, GLenum name, GLfloat reference)																																		= DE_NULL;
87
88private:
89	const char*	const	m_testNamePostfix;
90};
91
92StateVerifier::StateVerifier (const glw::Functions& gl, tcu::TestLog& log, const char* testNamePostfix)
93	: glu::CallLogWrapper	(gl, log)
94	, m_testNamePostfix		(testNamePostfix)
95{
96	enableLogging(true);
97}
98
99StateVerifier::~StateVerifier ()
100{
101}
102
103const char* StateVerifier::getTestNamePostfix (void) const
104{
105	return m_testNamePostfix;
106}
107
108// GetBooleanVerifier
109
110class GetBooleanVerifier : public StateVerifier
111{
112public:
113			GetBooleanVerifier		(const glw::Functions& gl, tcu::TestLog& log);
114	void	verifyFloat						(tcu::TestContext& testCtx, GLenum name, GLfloat reference);
115	void	verifyFloatExpanded				(tcu::TestContext& testCtx, GLenum name, GLfloat reference);
116	void	verifyFloat2Expanded			(tcu::TestContext& testCtx, GLenum name, GLfloat reference0, GLfloat reference1);
117	void	verifyFloat4Color				(tcu::TestContext& testCtx, GLenum name, GLfloat reference0, GLfloat reference1, GLfloat reference2, GLfloat reference3);
118	void	verifyFloatRange				(tcu::TestContext& testCtx, GLenum name, GLfloat min, GLfloat max);
119	void	verifyFloatGreaterOrEqual		(tcu::TestContext& testCtx, GLenum name, GLfloat reference);
120};
121
122GetBooleanVerifier::GetBooleanVerifier (const glw::Functions& gl, tcu::TestLog& log)
123	: StateVerifier(gl, log, "_getboolean")
124{
125}
126
127void GetBooleanVerifier::verifyFloat (tcu::TestContext& testCtx, GLenum name, GLfloat reference)
128{
129	using tcu::TestLog;
130
131	StateQueryMemoryWriteGuard<GLboolean> state;
132	glGetBooleanv(name, &state);
133
134	if (!state.verifyValidity(testCtx))
135		return;
136
137	const GLboolean expectedGLState = reference != 0.0f ? GL_TRUE : GL_FALSE;
138
139	if (state != expectedGLState)
140	{
141		testCtx.getLog() << TestLog::Message << "// ERROR: expected " << (expectedGLState==GL_TRUE ? "GL_TRUE" : "GL_FALSE") << "; got " << (state == GL_TRUE ? "GL_TRUE" : (state == GL_FALSE ? "GL_FALSE" : "non-boolean")) << TestLog::EndMessage;
142		if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
143			testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid boolean value");
144	}
145}
146
147void GetBooleanVerifier::verifyFloatExpanded (tcu::TestContext& testCtx, GLenum name, GLfloat reference)
148{
149	DE_ASSERT(de::inRange(reference, -1.0f, 1.0f));
150	verifyFloat(testCtx, name, reference);
151}
152
153void GetBooleanVerifier::verifyFloat2Expanded (tcu::TestContext& testCtx, GLenum name, GLfloat reference0, GLfloat reference1)
154{
155	DE_ASSERT(de::inRange(reference0, -1.0f, 1.0f));
156	DE_ASSERT(de::inRange(reference1, -1.0f, 1.0f));
157
158	using tcu::TestLog;
159
160	StateQueryMemoryWriteGuard<GLboolean[2]> boolVector2;
161	glGetBooleanv(name, boolVector2);
162
163	if (!boolVector2.verifyValidity(testCtx))
164		return;
165
166	const GLboolean referenceAsGLBoolean[] =
167	{
168		reference0 != 0.0f ? GLboolean(GL_TRUE) : GLboolean(GL_FALSE),
169		reference1 != 0.0f ? GLboolean(GL_TRUE) : GLboolean(GL_FALSE),
170	};
171
172	if (boolVector2[0] != referenceAsGLBoolean[0] ||
173		boolVector2[1] != referenceAsGLBoolean[1])
174	{
175		testCtx.getLog() << TestLog::Message << "// ERROR: expected "
176			<< (boolVector2[0] ? "GL_TRUE" : "GL_FALSE") << " "
177			<< (boolVector2[1] ? "GL_TRUE" : "GL_FALSE") << " "
178			<< TestLog::EndMessage;
179
180		if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
181			testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid boolean value");
182	}
183}
184
185void GetBooleanVerifier::verifyFloat4Color (tcu::TestContext& testCtx, GLenum name, GLfloat reference0, GLfloat reference1, GLfloat reference2, GLfloat reference3)
186{
187	using tcu::TestLog;
188
189	StateQueryMemoryWriteGuard<GLboolean[4]> boolVector4;
190	glGetBooleanv(name, boolVector4);
191
192	if (!boolVector4.verifyValidity(testCtx))
193		return;
194
195	const GLboolean referenceAsGLBoolean[] =
196	{
197		reference0 != 0.0f ? GLboolean(GL_TRUE) : GLboolean(GL_FALSE),
198		reference1 != 0.0f ? GLboolean(GL_TRUE) : GLboolean(GL_FALSE),
199		reference2 != 0.0f ? GLboolean(GL_TRUE) : GLboolean(GL_FALSE),
200		reference3 != 0.0f ? GLboolean(GL_TRUE) : GLboolean(GL_FALSE),
201	};
202
203	if (boolVector4[0] != referenceAsGLBoolean[0] ||
204		boolVector4[1] != referenceAsGLBoolean[1] ||
205		boolVector4[2] != referenceAsGLBoolean[2] ||
206		boolVector4[3] != referenceAsGLBoolean[3])
207	{
208		testCtx.getLog() << TestLog::Message << "// ERROR: expected "
209			<< (referenceAsGLBoolean[0] ? "GL_TRUE" : "GL_FALSE") << " "
210			<< (referenceAsGLBoolean[1] ? "GL_TRUE" : "GL_FALSE") << " "
211			<< (referenceAsGLBoolean[2] ? "GL_TRUE" : "GL_FALSE") << " "
212			<< (referenceAsGLBoolean[3] ? "GL_TRUE" : "GL_FALSE") << TestLog::EndMessage;
213
214		if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
215			testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid boolean value");
216	}
217}
218
219void GetBooleanVerifier::verifyFloatRange (tcu::TestContext& testCtx, GLenum name, GLfloat min, GLfloat max)
220{
221	using tcu::TestLog;
222
223	StateQueryMemoryWriteGuard<GLboolean[2]> range;
224	glGetBooleanv(name, range);
225
226	if (!range.verifyValidity(testCtx))
227		return;
228
229	if (range[0] == GL_FALSE)
230	{
231		if (max < 0 || min < 0)
232		{
233			testCtx.getLog() << TestLog::Message << "// ERROR: range [" << min << ", " << max << "] is not in range [" << (range[0] == GL_TRUE ? "GL_TRUE" : (range[0] == GL_FALSE ? "GL_FALSE" : "non-boolean")) << ", " << (range[1] == GL_TRUE ? "GL_TRUE" : (range[1] == GL_FALSE ? "GL_FALSE" : "non-boolean")) << "]"  << TestLog::EndMessage;
234			if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
235				testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid boolean range");
236			return;
237		}
238	}
239	if (range[1] == GL_FALSE)
240	{
241		if (max > 0 || min > 0)
242		{
243			testCtx.getLog() << TestLog::Message << "// ERROR: range [" << min << ", " << max << "] is not in range [" << (range[0] == GL_TRUE ? "GL_TRUE" : (range[0] == GL_FALSE ? "GL_FALSE" : "non-boolean")) << ", " << (range[1] == GL_TRUE ? "GL_TRUE" : (range[1] == GL_FALSE ? "GL_FALSE" : "non-boolean")) << "]"  << TestLog::EndMessage;
244			if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
245				testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid boolean range");
246			return;
247		}
248	}
249}
250
251void GetBooleanVerifier::verifyFloatGreaterOrEqual (tcu::TestContext& testCtx, GLenum name, GLfloat reference)
252{
253	using tcu::TestLog;
254
255	StateQueryMemoryWriteGuard<GLboolean> state;
256	glGetBooleanv(name, &state);
257
258	if (!state.verifyValidity(testCtx))
259		return;
260
261	if (state == GL_TRUE) // state is non-zero, could be greater than reference (correct)
262		return;
263
264	if (state == GL_FALSE) // state is zero
265	{
266		if (reference > 0) // and reference is greater than zero?
267		{
268			testCtx.getLog() << TestLog::Message << "// ERROR: expected GL_TRUE" << TestLog::EndMessage;
269			if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
270				testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid boolean value");
271		}
272	}
273	else
274	{
275		testCtx.getLog() << TestLog::Message << "// ERROR: expected GL_TRUE or GL_FALSE" << TestLog::EndMessage;
276		if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
277			testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid boolean value");
278	}
279}
280
281//GetIntegerVerifier
282
283class GetIntegerVerifier : public StateVerifier
284{
285public:
286			GetIntegerVerifier		(const glw::Functions& gl, tcu::TestLog& log);
287	void	verifyFloat						(tcu::TestContext& testCtx, GLenum name, GLfloat reference);
288	void	verifyFloatExpanded				(tcu::TestContext& testCtx, GLenum name, GLfloat reference);
289	void	verifyFloat2Expanded			(tcu::TestContext& testCtx, GLenum name, GLfloat reference0, GLfloat reference1);
290	void	verifyFloat4Color				(tcu::TestContext& testCtx, GLenum name, GLfloat reference0, GLfloat reference1, GLfloat reference2, GLfloat reference3);
291	void	verifyFloatRange				(tcu::TestContext& testCtx, GLenum name, GLfloat min, GLfloat max);
292	void	verifyFloatGreaterOrEqual		(tcu::TestContext& testCtx, GLenum name, GLfloat reference);
293};
294
295GetIntegerVerifier::GetIntegerVerifier (const glw::Functions& gl, tcu::TestLog& log)
296	: StateVerifier(gl, log, "_getinteger")
297{
298}
299
300void GetIntegerVerifier::verifyFloat (tcu::TestContext& testCtx, GLenum name, GLfloat reference)
301{
302	using tcu::TestLog;
303
304	const GLint expectedGLStateMax = StateQueryUtil::roundGLfloatToNearestIntegerHalfUp<GLint>(reference);
305	const GLint expectedGLStateMin = StateQueryUtil::roundGLfloatToNearestIntegerHalfDown<GLint>(reference);
306
307	StateQueryMemoryWriteGuard<GLint> state;
308	glGetIntegerv(name, &state);
309
310	if (!state.verifyValidity(testCtx))
311		return;
312
313	if (state < expectedGLStateMin || state > expectedGLStateMax)
314	{
315		testCtx.getLog() << TestLog::Message << "// ERROR: expected rounding to the nearest integer, valid range [" << expectedGLStateMin << "," << expectedGLStateMax << "]; got " << state << TestLog::EndMessage;
316		if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
317			testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid integer value");
318	}
319}
320
321void GetIntegerVerifier::verifyFloatExpanded (tcu::TestContext& testCtx, GLenum name, GLfloat reference)
322{
323	DE_ASSERT(de::inRange(reference, -1.0f, 1.0f));
324
325	using tcu::TestLog;
326	using tcu::toHex;
327
328	StateQueryMemoryWriteGuard<GLint> state;
329	glGetIntegerv(name, &state);
330
331	if (!state.verifyValidity(testCtx))
332		return;
333
334	const GLint expectedGLStateMax = clampToGLint(expandGLFloatToInteger(reference) + FLOAT_EXPANSION_E);
335	const GLint expectedGLStateMin = clampToGLint(expandGLFloatToInteger(reference) - FLOAT_EXPANSION_E);
336
337	if (state < expectedGLStateMin || state > expectedGLStateMax)
338	{
339		testCtx.getLog() << TestLog::Message << "// ERROR: expected in range [" << toHex(expectedGLStateMin) << "," << toHex(expectedGLStateMax) << "]; got " << toHex((GLint)state) << TestLog::EndMessage;
340		if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
341			testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid integer value");
342	}
343}
344
345void GetIntegerVerifier::verifyFloat2Expanded (tcu::TestContext& testCtx, GLenum name, GLfloat reference0, GLfloat reference1)
346{
347	DE_ASSERT(de::inRange(reference0, -1.0f, 1.0f));
348	DE_ASSERT(de::inRange(reference1, -1.0f, 1.0f));
349
350	using tcu::TestLog;
351	using tcu::toHex;
352
353	StateQueryMemoryWriteGuard<GLint[2]> floatVector2;
354	glGetIntegerv(name, floatVector2);
355
356	if (!floatVector2.verifyValidity(testCtx))
357		return;
358
359	const GLint referenceAsGLintMin[] =
360	{
361		clampToGLint(expandGLFloatToInteger(reference0) - FLOAT_EXPANSION_E),
362		clampToGLint(expandGLFloatToInteger(reference1) - FLOAT_EXPANSION_E)
363	};
364	const GLint referenceAsGLintMax[] =
365	{
366		clampToGLint(expandGLFloatToInteger(reference0) + FLOAT_EXPANSION_E),
367		clampToGLint(expandGLFloatToInteger(reference1) + FLOAT_EXPANSION_E)
368	};
369
370	if (floatVector2[0] < referenceAsGLintMin[0] || floatVector2[0] > referenceAsGLintMax[0] ||
371		floatVector2[1] < referenceAsGLintMin[1] || floatVector2[1] > referenceAsGLintMax[1])
372	{
373		testCtx.getLog() << TestLog::Message
374			<< "// ERROR: expected in ranges "
375			<< "[" << toHex(referenceAsGLintMin[0]) << " " << toHex(referenceAsGLintMax[0]) << "], "
376			<< "[" << toHex(referenceAsGLintMin[1]) << " " << toHex(referenceAsGLintMax[1]) << "]"
377			<< "; got "
378			<< toHex(floatVector2[0]) << ", "
379			<< toHex(floatVector2[1]) << " "<< TestLog::EndMessage;
380
381		if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
382			testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid integer value");
383	}
384}
385
386void GetIntegerVerifier::verifyFloat4Color (tcu::TestContext& testCtx, GLenum name, GLfloat reference0, GLfloat reference1, GLfloat reference2, GLfloat reference3)
387{
388	using tcu::TestLog;
389	using tcu::toHex;
390
391	StateQueryMemoryWriteGuard<GLint[4]> floatVector4;
392	glGetIntegerv(name, floatVector4);
393
394	if (!floatVector4.verifyValidity(testCtx))
395		return;
396
397	const GLint referenceAsGLintMin[] =
398	{
399		clampToGLint(expandGLFloatToInteger(reference0) - FLOAT_EXPANSION_E),
400		clampToGLint(expandGLFloatToInteger(reference1) - FLOAT_EXPANSION_E),
401		clampToGLint(expandGLFloatToInteger(reference2) - FLOAT_EXPANSION_E),
402		clampToGLint(expandGLFloatToInteger(reference3) - FLOAT_EXPANSION_E)
403	};
404	const GLint referenceAsGLintMax[] =
405	{
406		clampToGLint(expandGLFloatToInteger(reference0) + FLOAT_EXPANSION_E),
407		clampToGLint(expandGLFloatToInteger(reference1) + FLOAT_EXPANSION_E),
408		clampToGLint(expandGLFloatToInteger(reference2) + FLOAT_EXPANSION_E),
409		clampToGLint(expandGLFloatToInteger(reference3) + FLOAT_EXPANSION_E)
410	};
411
412	if (floatVector4[0] < referenceAsGLintMin[0] || floatVector4[0] > referenceAsGLintMax[0] ||
413		floatVector4[1] < referenceAsGLintMin[1] || floatVector4[1] > referenceAsGLintMax[1] ||
414		floatVector4[2] < referenceAsGLintMin[2] || floatVector4[2] > referenceAsGLintMax[2] ||
415		floatVector4[3] < referenceAsGLintMin[3] || floatVector4[3] > referenceAsGLintMax[3])
416	{
417		testCtx.getLog() << TestLog::Message
418			<< "// ERROR: expected in ranges "
419			<< "[" << toHex(referenceAsGLintMin[0]) << " " << toHex(referenceAsGLintMax[0]) << "], "
420			<< "[" << toHex(referenceAsGLintMin[1]) << " " << toHex(referenceAsGLintMax[1]) << "], "
421			<< "[" << toHex(referenceAsGLintMin[2]) << " " << toHex(referenceAsGLintMax[2]) << "], "
422			<< "[" << toHex(referenceAsGLintMin[3]) << " " << toHex(referenceAsGLintMax[3]) << "]"
423			<< "; got "
424			<< toHex(floatVector4[0]) << ", "
425			<< toHex(floatVector4[1]) << ", "
426			<< toHex(floatVector4[2]) << ", "
427			<< toHex(floatVector4[3]) << " "<< TestLog::EndMessage;
428
429		if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
430			testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid integer value");
431	}
432}
433
434void GetIntegerVerifier::verifyFloatRange (tcu::TestContext& testCtx, GLenum name, GLfloat min, GLfloat max)
435{
436	using tcu::TestLog;
437
438	StateQueryMemoryWriteGuard<GLint[2]> range;
439	glGetIntegerv(name, range);
440
441	if (!range.verifyValidity(testCtx))
442		return;
443
444	const GLint testRangeAsGLint[] =
445	{
446		StateQueryUtil::roundGLfloatToNearestIntegerHalfUp<GLint>(min),
447		StateQueryUtil::roundGLfloatToNearestIntegerHalfDown<GLint>(max)
448	};
449
450	// check if test range outside of gl state range
451	if (testRangeAsGLint[0] < range[0] ||
452		testRangeAsGLint[1] > range[1])
453	{
454		testCtx.getLog() << TestLog::Message
455			<< "// ERROR: range ["
456			<< testRangeAsGLint[0] << ", "
457			<< testRangeAsGLint[1] << "]"
458			<< " is not in range ["
459			<< range[0] << ", "
460			<< range[1] << "]" << TestLog::EndMessage;
461
462		if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
463			testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid integer range");
464	}
465}
466
467void GetIntegerVerifier::verifyFloatGreaterOrEqual (tcu::TestContext& testCtx, GLenum name, GLfloat reference)
468{
469	using tcu::TestLog;
470
471	StateQueryMemoryWriteGuard<GLint> state;
472	glGetIntegerv(name, &state);
473
474	if (!state.verifyValidity(testCtx))
475		return;
476
477	const GLint referenceAsInt = StateQueryUtil::roundGLfloatToNearestIntegerHalfDown<GLint>(reference);
478
479	if (state < referenceAsInt)
480	{
481		testCtx.getLog() << TestLog::Message << "// ERROR: expected expected greater or equal to " << referenceAsInt << "; got " << state << TestLog::EndMessage;
482		if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
483			testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid integer value");
484	}
485}
486
487//GetInteger64Verifier
488
489class GetInteger64Verifier : public StateVerifier
490{
491public:
492			GetInteger64Verifier		(const glw::Functions& gl, tcu::TestLog& log);
493	void	verifyFloat						(tcu::TestContext& testCtx, GLenum name, GLfloat reference);
494	void	verifyFloatExpanded				(tcu::TestContext& testCtx, GLenum name, GLfloat reference);
495	void	verifyFloat2Expanded			(tcu::TestContext& testCtx, GLenum name, GLfloat reference0, GLfloat reference1);
496	void	verifyFloat4Color				(tcu::TestContext& testCtx, GLenum name, GLfloat reference0, GLfloat reference1, GLfloat reference2, GLfloat reference3);
497	void	verifyFloatRange				(tcu::TestContext& testCtx, GLenum name, GLfloat min, GLfloat max);
498	void	verifyFloatGreaterOrEqual		(tcu::TestContext& testCtx, GLenum name, GLfloat reference);
499};
500
501GetInteger64Verifier::GetInteger64Verifier (const glw::Functions& gl, tcu::TestLog& log)
502	: StateVerifier(gl, log, "_getinteger64")
503{
504}
505
506void GetInteger64Verifier::verifyFloat (tcu::TestContext& testCtx, GLenum name, GLfloat reference)
507{
508	using tcu::TestLog;
509
510	const GLint64 expectedGLStateMax = StateQueryUtil::roundGLfloatToNearestIntegerHalfUp<GLint64>(reference);
511	const GLint64 expectedGLStateMin = StateQueryUtil::roundGLfloatToNearestIntegerHalfDown<GLint64>(reference);
512
513	StateQueryMemoryWriteGuard<GLint64> state;
514	glGetInteger64v(name, &state);
515
516	if (!state.verifyValidity(testCtx))
517		return;
518
519	if (state < expectedGLStateMin || state > expectedGLStateMax)
520	{
521		testCtx.getLog() << TestLog::Message << "// ERROR: expected rounding to the nearest integer, valid range [" << expectedGLStateMin << "," << expectedGLStateMax << "]; got " << state << TestLog::EndMessage;
522		if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
523			testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid integer value");
524	}
525}
526
527void GetInteger64Verifier::verifyFloatExpanded (tcu::TestContext& testCtx, GLenum name, GLfloat reference)
528{
529	DE_ASSERT(de::inRange(reference, -1.0f, 1.0f));
530
531	using tcu::TestLog;
532	using tcu::toHex;
533
534	StateQueryMemoryWriteGuard<GLint64> state;
535	glGetInteger64v(name, &state);
536
537	if (!state.verifyValidity(testCtx))
538		return;
539
540	const GLint64 expectedGLStateMax = expandGLFloatToInteger(reference) + FLOAT_EXPANSION_E_64;
541	const GLint64 expectedGLStateMin = expandGLFloatToInteger(reference) - FLOAT_EXPANSION_E_64;
542
543	if (state < expectedGLStateMin || state > expectedGLStateMax)
544	{
545		testCtx.getLog() << TestLog::Message << "// ERROR: expected in range [" << toHex(expectedGLStateMin) << "," << toHex(expectedGLStateMax) << "]; got " << toHex((GLint64)state) << TestLog::EndMessage;
546		if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
547			testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid integer value");
548	}
549}
550
551void GetInteger64Verifier::verifyFloat2Expanded (tcu::TestContext& testCtx, GLenum name, GLfloat reference0, GLfloat reference1)
552{
553	DE_ASSERT(de::inRange(reference0, -1.0f, 1.0f));
554	DE_ASSERT(de::inRange(reference1, -1.0f, 1.0f));
555
556	using tcu::TestLog;
557	using tcu::toHex;
558
559	StateQueryMemoryWriteGuard<GLint64[2]> floatVector2;
560	glGetInteger64v(name, floatVector2);
561
562	if (!floatVector2.verifyValidity(testCtx))
563		return;
564
565	const GLint64 referenceAsGLintMin[] =
566	{
567		expandGLFloatToInteger(reference0) - FLOAT_EXPANSION_E_64,
568		expandGLFloatToInteger(reference1) - FLOAT_EXPANSION_E_64
569	};
570	const GLint64 referenceAsGLintMax[] =
571	{
572		expandGLFloatToInteger(reference0) + FLOAT_EXPANSION_E_64,
573		expandGLFloatToInteger(reference1) + FLOAT_EXPANSION_E_64
574	};
575
576	if (floatVector2[0] < referenceAsGLintMin[0] || floatVector2[0] > referenceAsGLintMax[0] ||
577		floatVector2[1] < referenceAsGLintMin[1] || floatVector2[1] > referenceAsGLintMax[1])
578	{
579		testCtx.getLog() << TestLog::Message
580			<< "// ERROR: expected in ranges "
581			<< "[" << toHex(referenceAsGLintMin[0]) << " " << toHex(referenceAsGLintMax[0]) << "], "
582			<< "[" << toHex(referenceAsGLintMin[1]) << " " << toHex(referenceAsGLintMax[1]) << "]"
583			<< "; got "
584			<< toHex(floatVector2[0]) << ", "
585			<< toHex(floatVector2[1]) << " "<< TestLog::EndMessage;
586
587		if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
588			testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid integer value");
589	}
590}
591
592void GetInteger64Verifier::verifyFloat4Color (tcu::TestContext& testCtx, GLenum name, GLfloat reference0, GLfloat reference1, GLfloat reference2, GLfloat reference3)
593{
594	using tcu::TestLog;
595	using tcu::toHex;
596
597	StateQueryMemoryWriteGuard<GLint64[4]> floatVector4;
598	glGetInteger64v(name, floatVector4);
599
600	if (!floatVector4.verifyValidity(testCtx))
601		return;
602
603	const GLint64 referenceAsGLintMin[] =
604	{
605		expandGLFloatToInteger(reference0) - FLOAT_EXPANSION_E_64,
606		expandGLFloatToInteger(reference1) - FLOAT_EXPANSION_E_64,
607		expandGLFloatToInteger(reference2) - FLOAT_EXPANSION_E_64,
608		expandGLFloatToInteger(reference3) - FLOAT_EXPANSION_E_64
609	};
610	const GLint64 referenceAsGLintMax[] =
611	{
612		expandGLFloatToInteger(reference0) + FLOAT_EXPANSION_E_64,
613		expandGLFloatToInteger(reference1) + FLOAT_EXPANSION_E_64,
614		expandGLFloatToInteger(reference2) + FLOAT_EXPANSION_E_64,
615		expandGLFloatToInteger(reference3) + FLOAT_EXPANSION_E_64
616	};
617
618	if (floatVector4[0] < referenceAsGLintMin[0] || floatVector4[0] > referenceAsGLintMax[0] ||
619		floatVector4[1] < referenceAsGLintMin[1] || floatVector4[1] > referenceAsGLintMax[1] ||
620		floatVector4[2] < referenceAsGLintMin[2] || floatVector4[2] > referenceAsGLintMax[2] ||
621		floatVector4[3] < referenceAsGLintMin[3] || floatVector4[3] > referenceAsGLintMax[3])
622	{
623		testCtx.getLog() << TestLog::Message
624			<< "// ERROR: expected in ranges "
625			<< "[" << toHex(referenceAsGLintMin[0]) << " " << toHex(referenceAsGLintMax[0]) << "], "
626			<< "[" << toHex(referenceAsGLintMin[1]) << " " << toHex(referenceAsGLintMax[1]) << "], "
627			<< "[" << toHex(referenceAsGLintMin[2]) << " " << toHex(referenceAsGLintMax[2]) << "], "
628			<< "[" << toHex(referenceAsGLintMin[3]) << " " << toHex(referenceAsGLintMax[3]) << "]"
629			<< "; got "
630			<< toHex(floatVector4[0]) << ", "
631			<< toHex(floatVector4[1]) << ", "
632			<< toHex(floatVector4[2]) << ", "
633			<< toHex(floatVector4[3]) << " "<< TestLog::EndMessage;
634
635		if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
636			testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid integer value");
637	}
638}
639
640void GetInteger64Verifier::verifyFloatRange (tcu::TestContext& testCtx, GLenum name, GLfloat min, GLfloat max)
641{
642	using tcu::TestLog;
643
644	StateQueryMemoryWriteGuard<GLint64[2]> range;
645	glGetInteger64v(name, range);
646
647	if (!range.verifyValidity(testCtx))
648		return;
649
650	const GLint64 testRangeAsGLint[] =
651	{
652		StateQueryUtil::roundGLfloatToNearestIntegerHalfUp<GLint64>(min),
653		StateQueryUtil::roundGLfloatToNearestIntegerHalfDown<GLint64>(max)
654	};
655
656	// check if test range outside of gl state range
657	if (testRangeAsGLint[0] < range[0] ||
658		testRangeAsGLint[1] > range[1])
659	{
660		testCtx.getLog() << TestLog::Message
661			<< "// ERROR: range ["
662			<< testRangeAsGLint[0] << ", "
663			<< testRangeAsGLint[1] << "]"
664			<< " is not in range ["
665			<< range[0] << ", "
666			<< range[1] << "]" << TestLog::EndMessage;
667
668		if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
669			testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid integer range");
670	}
671}
672
673void GetInteger64Verifier::verifyFloatGreaterOrEqual (tcu::TestContext& testCtx, GLenum name, GLfloat reference)
674{
675	using tcu::TestLog;
676
677	StateQueryMemoryWriteGuard<GLint64> state;
678	glGetInteger64v(name, &state);
679
680	if (!state.verifyValidity(testCtx))
681		return;
682
683	const GLint64 referenceAsInt = StateQueryUtil::roundGLfloatToNearestIntegerHalfDown<GLint64>(reference);
684
685	if (state < referenceAsInt)
686	{
687		testCtx.getLog() << TestLog::Message << "// ERROR: expected expected greater or equal to " << referenceAsInt << "; got " << state << TestLog::EndMessage;
688		if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
689			testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid integer value");
690	}
691}
692
693//GetFloatVerifier
694
695class GetFloatVerifier : public StateVerifier
696{
697public:
698			GetFloatVerifier			(const glw::Functions& gl, tcu::TestLog& log);
699	void	verifyFloat						(tcu::TestContext& testCtx, GLenum name, GLfloat reference);
700	void	verifyFloatExpanded				(tcu::TestContext& testCtx, GLenum name, GLfloat reference);
701	void	verifyFloat2Expanded			(tcu::TestContext& testCtx, GLenum name, GLfloat reference0, GLfloat reference1);
702	void	verifyFloat4Color				(tcu::TestContext& testCtx, GLenum name, GLfloat reference0, GLfloat reference1, GLfloat reference2, GLfloat reference3);
703	void	verifyFloatRange				(tcu::TestContext& testCtx, GLenum name, GLfloat min, GLfloat max);
704	void	verifyFloatGreaterOrEqual		(tcu::TestContext& testCtx, GLenum name, GLfloat reference);
705};
706
707GetFloatVerifier::GetFloatVerifier (const glw::Functions& gl, tcu::TestLog& log)
708	: StateVerifier(gl, log, "_getfloat")
709{
710}
711
712void GetFloatVerifier::verifyFloat (tcu::TestContext& testCtx, GLenum name, GLfloat reference)
713{
714	using tcu::TestLog;
715
716	StateQueryMemoryWriteGuard<GLfloat> state;
717	glGetFloatv(name, &state);
718
719	if (!state.verifyValidity(testCtx))
720		return;
721
722	if (state != reference)
723	{
724		testCtx.getLog() << TestLog::Message << "// ERROR: expected " << reference << "; got " << state << TestLog::EndMessage;
725		if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
726			testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid float value");
727	}
728}
729
730void GetFloatVerifier::verifyFloatExpanded (tcu::TestContext& testCtx, GLenum name, GLfloat reference)
731{
732	DE_ASSERT(de::inRange(reference, -1.0f, 1.0f));
733	verifyFloat(testCtx, name, reference);
734}
735
736void GetFloatVerifier::verifyFloat2Expanded (tcu::TestContext& testCtx, GLenum name, GLfloat reference0, GLfloat reference1)
737{
738	DE_ASSERT(de::inRange(reference0, -1.0f, 1.0f));
739	DE_ASSERT(de::inRange(reference1, -1.0f, 1.0f));
740
741	using tcu::TestLog;
742
743	StateQueryMemoryWriteGuard<GLfloat[2]> floatVector2;
744	glGetFloatv(name, floatVector2);
745
746	if (!floatVector2.verifyValidity(testCtx))
747		return;
748
749	if (floatVector2[0] != reference0 ||
750		floatVector2[1] != reference1)
751	{
752		testCtx.getLog() << TestLog::Message << "// ERROR: expected " << reference0 << ", " << reference1 << "; got " << floatVector2[0] << " " << floatVector2[1] << TestLog::EndMessage;
753
754		if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
755			testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid float value");
756	}
757}
758
759void GetFloatVerifier::verifyFloat4Color (tcu::TestContext& testCtx, GLenum name, GLfloat reference0, GLfloat reference1, GLfloat reference2, GLfloat reference3)
760{
761	using tcu::TestLog;
762
763	StateQueryMemoryWriteGuard<GLfloat[4]> floatVector4;
764	glGetFloatv(name, floatVector4);
765
766	if (!floatVector4.verifyValidity(testCtx))
767		return;
768
769	if (floatVector4[0] != reference0 ||
770		floatVector4[1] != reference1 ||
771		floatVector4[2] != reference2 ||
772		floatVector4[3] != reference3)
773	{
774		testCtx.getLog() << TestLog::Message
775			<< "// ERROR: expected "<< reference0 << ", " << reference1 << ", " << reference2 << ", " << reference3
776			<< "; got " << floatVector4[0] << ", " << floatVector4[1] << ", " << floatVector4[2] << ", " << floatVector4[3]
777			<< TestLog::EndMessage;
778
779		if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
780			testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid float value");
781	}
782}
783
784void GetFloatVerifier::verifyFloatRange (tcu::TestContext& testCtx, GLenum name, GLfloat min, GLfloat max)
785{
786	using tcu::TestLog;
787
788	StateQueryMemoryWriteGuard<GLfloat[2]> floatVector2;
789	glGetFloatv(name, floatVector2);
790
791	if (!floatVector2.verifyValidity(testCtx))
792		return;
793
794	if (floatVector2[0] > min ||
795		floatVector2[1] < max)
796	{
797		testCtx.getLog() << TestLog::Message << "// ERROR: expected in range [" << min << ", " << max << "]; got [" << floatVector2[0] << " " << floatVector2[1]  << "]" << TestLog::EndMessage;
798
799		if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
800			testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid float range");
801	}
802}
803
804void GetFloatVerifier::verifyFloatGreaterOrEqual (tcu::TestContext& testCtx, GLenum name, GLfloat reference)
805{
806	using tcu::TestLog;
807
808	StateQueryMemoryWriteGuard<GLfloat> state;
809	glGetFloatv(name, &state);
810
811	if (!state.verifyValidity(testCtx))
812		return;
813
814	if (state < reference)
815	{
816		testCtx.getLog() << TestLog::Message << "// ERROR: expected greater or equal to " << reference << "; got " << state << TestLog::EndMessage;
817		if (testCtx.getTestResult() == QP_TEST_RESULT_PASS)
818			testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got invalid float value");
819	}
820}
821
822
823} // FloatStateQueryVerifiers
824
825namespace
826{
827
828using namespace FloatStateQueryVerifiers;
829
830class DepthRangeCase : public ApiCase
831{
832public:
833	DepthRangeCase (Context& context, StateVerifier* verifier, const char* name, const char* description)
834		: ApiCase		(context, name, description)
835		, m_verifier	(verifier)
836	{
837	}
838
839	void test (void)
840	{
841		de::Random rnd(0xabcdef);
842
843		m_verifier->verifyFloat2Expanded(m_testCtx, GL_DEPTH_RANGE, 0.0f, 1.0f);
844		expectError(GL_NO_ERROR);
845
846		const struct FixedTest
847		{
848			float n, f;
849		} fixedTests[] =
850		{
851			{ 0.5f, 1.0f },
852			{ 0.0f, 0.5f },
853			{ 0.0f, 0.0f },
854			{ 1.0f, 1.0f }
855		};
856		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(fixedTests); ++ndx)
857		{
858			glDepthRangef(fixedTests[ndx].n, fixedTests[ndx].f);
859
860			m_verifier->verifyFloat2Expanded(m_testCtx, GL_DEPTH_RANGE, fixedTests[ndx].n, fixedTests[ndx].f);
861			expectError(GL_NO_ERROR);
862		}
863
864		const int numIterations = 120;
865		for (int i = 0; i < numIterations; ++i)
866		{
867			GLfloat n	= rnd.getFloat(0, 1);
868			GLfloat f	= rnd.getFloat(0, 1);
869
870			glDepthRangef(n, f);
871			m_verifier->verifyFloat2Expanded(m_testCtx, GL_DEPTH_RANGE, n, f);
872			expectError(GL_NO_ERROR);
873		}
874	}
875private:
876	StateVerifier*	m_verifier;
877};
878
879class LineWidthCase : public ApiCase
880{
881public:
882	LineWidthCase (Context& context, StateVerifier* verifier, const char* name, const char* description)
883		: ApiCase		(context, name, description)
884		, m_verifier	(verifier)
885	{
886	}
887
888	void test (void)
889	{
890		de::Random rnd(0xabcdef);
891
892		m_verifier->verifyFloat(m_testCtx, GL_LINE_WIDTH, 1.0f);
893		expectError(GL_NO_ERROR);
894
895		GLfloat range[2] = {1};
896		glGetFloatv(GL_ALIASED_LINE_WIDTH_RANGE, range);
897		expectError(GL_NO_ERROR);
898
899		const int numIterations = 120;
900		for (int i = 0; i < numIterations; ++i)
901		{
902			const GLfloat reference = rnd.getFloat(range[0], range[1]);
903
904			glLineWidth(reference);
905			m_verifier->verifyFloat(m_testCtx, GL_LINE_WIDTH, reference);
906			expectError(GL_NO_ERROR);
907		}
908	}
909private:
910	StateVerifier*	m_verifier;
911};
912
913class PolygonOffsetFactorCase : public ApiCase
914{
915public:
916	PolygonOffsetFactorCase (Context& context, StateVerifier* verifier, const char* name, const char* description)
917		: ApiCase		(context, name, description)
918		, m_verifier	(verifier)
919	{
920	}
921
922	void test (void)
923	{
924		de::Random rnd(0xabcdef);
925
926		m_verifier->verifyFloat(m_testCtx, GL_POLYGON_OFFSET_FACTOR, 0.0f);
927		expectError(GL_NO_ERROR);
928
929		const float fixedTests[] =
930		{
931			0.0f, 0.5f, -0.5f, 1.5f
932		};
933		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(fixedTests); ++ndx)
934		{
935			glPolygonOffset(fixedTests[ndx], 0);
936			m_verifier->verifyFloat(m_testCtx, GL_POLYGON_OFFSET_FACTOR, fixedTests[ndx]);
937			expectError(GL_NO_ERROR);
938		}
939
940		const int numIterations = 120;
941		for (int i = 0; i < numIterations; ++i)
942		{
943			const GLfloat reference = rnd.getFloat(-64000, 64000);
944
945			glPolygonOffset(reference, 0);
946			m_verifier->verifyFloat(m_testCtx, GL_POLYGON_OFFSET_FACTOR, reference);
947			expectError(GL_NO_ERROR);
948		}
949	}
950private:
951	StateVerifier*	m_verifier;
952};
953
954class PolygonOffsetUnitsCase : public ApiCase
955{
956public:
957	PolygonOffsetUnitsCase (Context& context, StateVerifier* verifier, const char* name, const char* description)
958		: ApiCase		(context, name, description)
959		, m_verifier	(verifier)
960	{
961	}
962
963	void test (void)
964	{
965		de::Random rnd(0xabcdef);
966
967		m_verifier->verifyFloat(m_testCtx, GL_POLYGON_OFFSET_UNITS, 0.0f);
968		expectError(GL_NO_ERROR);
969
970		const float fixedTests[] =
971		{
972			0.0f, 0.5f, -0.5f, 1.5f
973		};
974		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(fixedTests); ++ndx)
975		{
976			glPolygonOffset(0, fixedTests[ndx]);
977			m_verifier->verifyFloat(m_testCtx, GL_POLYGON_OFFSET_UNITS, fixedTests[ndx]);
978			expectError(GL_NO_ERROR);
979		}
980
981		const int numIterations = 120;
982		for (int i = 0; i < numIterations; ++i)
983		{
984			const GLfloat reference = rnd.getFloat(-64000, 64000);
985
986			glPolygonOffset(0, reference);
987			m_verifier->verifyFloat(m_testCtx, GL_POLYGON_OFFSET_UNITS, reference);
988			expectError(GL_NO_ERROR);
989		}
990	}
991private:
992	StateVerifier*	m_verifier;
993};
994
995class SampleCoverageCase : public ApiCase
996{
997public:
998	SampleCoverageCase (Context& context, StateVerifier* verifier, const char* name, const char* description)
999		: ApiCase		(context, name, description)
1000		, m_verifier	(verifier)
1001	{
1002	}
1003
1004	void test (void)
1005	{
1006		de::Random rnd(0xabcdef);
1007
1008		m_verifier->verifyFloat(m_testCtx, GL_SAMPLE_COVERAGE_VALUE, 1.0f);
1009		expectError(GL_NO_ERROR);
1010
1011		{
1012			const float fixedTests[] =
1013			{
1014				0.0f, 0.5f, 0.45f, 0.55f
1015			};
1016			for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(fixedTests); ++ndx)
1017			{
1018				glSampleCoverage(fixedTests[ndx], GL_FALSE);
1019				m_verifier->verifyFloat(m_testCtx, GL_SAMPLE_COVERAGE_VALUE, fixedTests[ndx]);
1020				expectError(GL_NO_ERROR);
1021			}
1022		}
1023
1024		{
1025			const float clampTests[] =
1026			{
1027				-1.0f, -1.5f, 1.45f, 3.55f
1028			};
1029			for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(clampTests); ++ndx)
1030			{
1031				glSampleCoverage(clampTests[ndx], GL_FALSE);
1032				m_verifier->verifyFloat(m_testCtx, GL_SAMPLE_COVERAGE_VALUE, de::clamp(clampTests[ndx], 0.0f, 1.0f));
1033				expectError(GL_NO_ERROR);
1034			}
1035		}
1036
1037		{
1038			const int numIterations = 120;
1039			for (int i = 0; i < numIterations; ++i)
1040			{
1041				GLfloat		reference	= rnd.getFloat(0, 1);
1042				GLboolean	invert		= rnd.getBool() ? GL_TRUE : GL_FALSE;
1043
1044				glSampleCoverage(reference, invert);
1045				m_verifier->verifyFloat(m_testCtx, GL_SAMPLE_COVERAGE_VALUE, reference);
1046				expectError(GL_NO_ERROR);
1047			}
1048		}
1049	}
1050private:
1051	StateVerifier*	m_verifier;
1052};
1053
1054class BlendColorCase : public ApiCase
1055{
1056public:
1057	BlendColorCase (Context& context, StateVerifier* verifier, const char* name, const char* description)
1058		: ApiCase		(context, name, description)
1059		, m_verifier	(verifier)
1060	{
1061	}
1062
1063	void test (void)
1064	{
1065		de::Random rnd(0xabcdef);
1066
1067		m_verifier->verifyFloat4Color(m_testCtx, GL_BLEND_COLOR, 0, 0, 0, 0);
1068		expectError(GL_NO_ERROR);
1069
1070		const struct FixedTest
1071		{
1072			float r, g, b, a;
1073		} fixedTests[] =
1074		{
1075			{ 0.5f, 1.0f, 0.5f, 1.0f },
1076			{ 0.0f, 0.5f, 0.0f, 0.5f },
1077			{ 0.0f, 0.0f, 0.0f, 0.0f },
1078			{ 1.0f, 1.0f, 1.0f, 1.0f },
1079		};
1080		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(fixedTests); ++ndx)
1081		{
1082			glBlendColor(fixedTests[ndx].r, fixedTests[ndx].g, fixedTests[ndx].b, fixedTests[ndx].a);
1083			m_verifier->verifyFloat4Color(m_testCtx, GL_BLEND_COLOR, fixedTests[ndx].r, fixedTests[ndx].g, fixedTests[ndx].b, fixedTests[ndx].a);
1084			expectError(GL_NO_ERROR);
1085		}
1086
1087		const int numIterations = 120;
1088		for (int i = 0; i < numIterations; ++i)
1089		{
1090			const GLfloat r = rnd.getFloat(0, 1);
1091			const GLfloat g = rnd.getFloat(0, 1);
1092			const GLfloat b = rnd.getFloat(0, 1);
1093			const GLfloat a = rnd.getFloat(0, 1);
1094
1095			glBlendColor(r, g, b, a);
1096			m_verifier->verifyFloat4Color(m_testCtx, GL_BLEND_COLOR, r, g, b, a);
1097			expectError(GL_NO_ERROR);
1098		}
1099	}
1100private:
1101	StateVerifier*	m_verifier;
1102};
1103
1104class ColorClearCase : public ApiCase
1105{
1106public:
1107	ColorClearCase (Context& context, StateVerifier* verifier, const char* name, const char* description)
1108		: ApiCase		(context, name, description)
1109		, m_verifier	(verifier)
1110	{
1111	}
1112
1113	void test (void)
1114	{
1115		de::Random rnd(0xabcdef);
1116
1117		// \note Initial color clear value check is temorarily removed. (until the framework does not alter it)
1118		//m_verifier->verifyFloat4Color(m_testCtx, GL_COLOR_CLEAR_VALUE, 0, 0, 0, 0);
1119		//expectError(GL_NO_ERROR);
1120
1121		const struct FixedTest
1122		{
1123			float r, g, b, a;
1124		} fixedTests[] =
1125		{
1126			{ 0.5f, 1.0f, 0.5f, 1.0f },
1127			{ 0.0f, 0.5f, 0.0f, 0.5f },
1128			{ 0.0f, 0.0f, 0.0f, 0.0f },
1129			{ 1.0f, 1.0f, 1.0f, 1.0f },
1130		};
1131		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(fixedTests); ++ndx)
1132		{
1133			glClearColor(fixedTests[ndx].r, fixedTests[ndx].g, fixedTests[ndx].b, fixedTests[ndx].a);
1134			m_verifier->verifyFloat4Color(m_testCtx, GL_COLOR_CLEAR_VALUE, fixedTests[ndx].r, fixedTests[ndx].g, fixedTests[ndx].b, fixedTests[ndx].a);
1135			expectError(GL_NO_ERROR);
1136		}
1137
1138		const int numIterations = 120;
1139		for (int i = 0; i < numIterations; ++i)
1140		{
1141			const GLfloat r = rnd.getFloat(0, 1);
1142			const GLfloat g = rnd.getFloat(0, 1);
1143			const GLfloat b = rnd.getFloat(0, 1);
1144			const GLfloat a = rnd.getFloat(0, 1);
1145
1146			glClearColor(r, g, b, a);
1147			m_verifier->verifyFloat4Color(m_testCtx, GL_COLOR_CLEAR_VALUE, r, g, b, a);
1148			expectError(GL_NO_ERROR);
1149		}
1150	}
1151private:
1152	StateVerifier*	m_verifier;
1153};
1154
1155class DepthClearCase : public ApiCase
1156{
1157public:
1158	DepthClearCase (Context& context, StateVerifier* verifier, const char* name, const char* description)
1159		: ApiCase		(context, name, description)
1160		, m_verifier	(verifier)
1161	{
1162	}
1163
1164	void test (void)
1165	{
1166		de::Random rnd(0xabcdef);
1167
1168		m_verifier->verifyFloatExpanded(m_testCtx, GL_DEPTH_CLEAR_VALUE, 1);
1169		expectError(GL_NO_ERROR);
1170
1171		const int numIterations = 120;
1172		for (int i = 0; i < numIterations; ++i)
1173		{
1174			const GLfloat ref = rnd.getFloat(0, 1);
1175
1176			glClearDepthf(ref);
1177			m_verifier->verifyFloatExpanded(m_testCtx, GL_DEPTH_CLEAR_VALUE, ref);
1178			expectError(GL_NO_ERROR);
1179		}
1180	}
1181private:
1182	StateVerifier*	m_verifier;
1183};
1184
1185class MaxTextureLODBiasCase : public ApiCase
1186{
1187public:
1188	MaxTextureLODBiasCase (Context& context, StateVerifier* verifier, const char* name, const char* description)
1189		: ApiCase		(context, name, description)
1190		, m_verifier	(verifier)
1191	{
1192	}
1193
1194	void test (void)
1195	{
1196		m_verifier->verifyFloatGreaterOrEqual(m_testCtx, GL_MAX_TEXTURE_LOD_BIAS, 2.0f);
1197		expectError(GL_NO_ERROR);
1198	}
1199private:
1200	StateVerifier*	m_verifier;
1201};
1202
1203class AliasedPointSizeRangeCase : public ApiCase
1204{
1205public:
1206	AliasedPointSizeRangeCase (Context& context, StateVerifier* verifier, const char* name, const char* description)
1207		: ApiCase		(context, name, description)
1208		, m_verifier	(verifier)
1209	{
1210	}
1211
1212	void test (void)
1213	{
1214		m_verifier->verifyFloatRange(m_testCtx, GL_ALIASED_POINT_SIZE_RANGE, 1, 1);
1215		expectError(GL_NO_ERROR);
1216	}
1217private:
1218	StateVerifier*	m_verifier;
1219};
1220
1221class AliasedLineWidthRangeCase : public ApiCase
1222{
1223public:
1224	AliasedLineWidthRangeCase (Context& context, StateVerifier* verifier, const char* name, const char* description)
1225		: ApiCase		(context, name, description)
1226		, m_verifier	(verifier)
1227	{
1228	}
1229
1230	void test (void)
1231	{
1232		m_verifier->verifyFloatRange(m_testCtx, GL_ALIASED_LINE_WIDTH_RANGE, 1, 1);
1233		expectError(GL_NO_ERROR);
1234	}
1235private:
1236	StateVerifier*	m_verifier;
1237};
1238
1239#define FOR_EACH_VERIFIER(VERIFIERS, CODE_BLOCK)												\
1240	for (int _verifierNdx = 0; _verifierNdx < DE_LENGTH_OF_ARRAY(VERIFIERS); _verifierNdx++)	\
1241	{																							\
1242		StateVerifier* verifier = (VERIFIERS)[_verifierNdx];									\
1243		CODE_BLOCK;																				\
1244	}
1245
1246} // anonymous
1247
1248FloatStateQueryTests::FloatStateQueryTests (Context& context)
1249	: TestCaseGroup			(context, "floats", "Float Values")
1250	, m_verifierBoolean		(DE_NULL)
1251	, m_verifierInteger		(DE_NULL)
1252	, m_verifierInteger64	(DE_NULL)
1253	, m_verifierFloat		(DE_NULL)
1254{
1255}
1256
1257FloatStateQueryTests::~FloatStateQueryTests (void)
1258{
1259	deinit();
1260}
1261
1262void FloatStateQueryTests::init (void)
1263{
1264	DE_ASSERT(m_verifierBoolean == DE_NULL);
1265	DE_ASSERT(m_verifierInteger == DE_NULL);
1266	DE_ASSERT(m_verifierInteger64 == DE_NULL);
1267	DE_ASSERT(m_verifierFloat == DE_NULL);
1268
1269	m_verifierBoolean		= new GetBooleanVerifier	(m_context.getRenderContext().getFunctions(), m_context.getTestContext().getLog());
1270	m_verifierInteger		= new GetIntegerVerifier	(m_context.getRenderContext().getFunctions(), m_context.getTestContext().getLog());
1271	m_verifierInteger64		= new GetInteger64Verifier	(m_context.getRenderContext().getFunctions(), m_context.getTestContext().getLog());
1272	m_verifierFloat			= new GetFloatVerifier		(m_context.getRenderContext().getFunctions(), m_context.getTestContext().getLog());
1273
1274	StateVerifier* verifiers[] = {m_verifierBoolean, m_verifierInteger, m_verifierInteger64, m_verifierFloat};
1275
1276	FOR_EACH_VERIFIER(verifiers, addChild(new DepthRangeCase				(m_context, verifier,	(std::string("depth_range")					+ verifier->getTestNamePostfix()).c_str(),	"DEPTH_RANGE")));
1277	FOR_EACH_VERIFIER(verifiers, addChild(new LineWidthCase					(m_context, verifier,	(std::string("line_width")					+ verifier->getTestNamePostfix()).c_str(),	"LINE_WIDTH")));
1278	FOR_EACH_VERIFIER(verifiers, addChild(new PolygonOffsetFactorCase		(m_context, verifier,	(std::string("polygon_offset_factor")		+ verifier->getTestNamePostfix()).c_str(),	"POLYGON_OFFSET_FACTOR")));
1279	FOR_EACH_VERIFIER(verifiers, addChild(new PolygonOffsetUnitsCase		(m_context, verifier,	(std::string("polygon_offset_units")		+ verifier->getTestNamePostfix()).c_str(),	"POLYGON_OFFSET_UNITS")));
1280	FOR_EACH_VERIFIER(verifiers, addChild(new SampleCoverageCase			(m_context, verifier,	(std::string("sample_coverage_value")		+ verifier->getTestNamePostfix()).c_str(),	"SAMPLE_COVERAGE_VALUE")));
1281	FOR_EACH_VERIFIER(verifiers, addChild(new BlendColorCase				(m_context, verifier,	(std::string("blend_color")					+ verifier->getTestNamePostfix()).c_str(),	"BLEND_COLOR")));
1282	FOR_EACH_VERIFIER(verifiers, addChild(new ColorClearCase				(m_context, verifier,	(std::string("color_clear_value")			+ verifier->getTestNamePostfix()).c_str(),	"COLOR_CLEAR_VALUE")));
1283	FOR_EACH_VERIFIER(verifiers, addChild(new DepthClearCase				(m_context, verifier,	(std::string("depth_clear_value")			+ verifier->getTestNamePostfix()).c_str(),	"DEPTH_CLEAR_VALUE")));
1284	FOR_EACH_VERIFIER(verifiers, addChild(new MaxTextureLODBiasCase			(m_context, verifier,	(std::string("max_texture_lod_bias")		+ verifier->getTestNamePostfix()).c_str(),	"MAX_TEXTURE_LOD_BIAS")));
1285	FOR_EACH_VERIFIER(verifiers, addChild(new AliasedPointSizeRangeCase		(m_context, verifier,	(std::string("aliased_point_size_range")	+ verifier->getTestNamePostfix()).c_str(),	"ALIASED_POINT_SIZE_RANGE")));
1286	FOR_EACH_VERIFIER(verifiers, addChild(new AliasedLineWidthRangeCase		(m_context, verifier,	(std::string("aliased_line_width_range")	+ verifier->getTestNamePostfix()).c_str(),	"ALIASED_LINE_WIDTH_RANGE")));
1287}
1288
1289void FloatStateQueryTests::deinit (void)
1290{
1291	if (m_verifierBoolean)
1292	{
1293		delete m_verifierBoolean;
1294		m_verifierBoolean = DE_NULL;
1295	}
1296	if (m_verifierInteger)
1297	{
1298		delete m_verifierInteger;
1299		m_verifierInteger = DE_NULL;
1300	}
1301	if (m_verifierInteger64)
1302	{
1303		delete m_verifierInteger64;
1304		m_verifierInteger64 = DE_NULL;
1305	}
1306	if (m_verifierFloat)
1307	{
1308		delete m_verifierFloat;
1309		m_verifierFloat = DE_NULL;
1310	}
1311
1312	this->TestCaseGroup::deinit();
1313}
1314
1315} // Functional
1316} // gles3
1317} // deqp
1318