glsStateQueryUtil.hpp revision cb82ed72dcbbfd8a6d07736c3259605227bc984f
1#ifndef _GLSSTATEQUERYUTIL_HPP
2#define _GLSSTATEQUERYUTIL_HPP
3/*-------------------------------------------------------------------------
4 * drawElements Quality Program OpenGL (ES) Module
5 * -----------------------------------------------
6 *
7 * Copyright 2014 The Android Open Source Project
8 *
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
12 *
13 *      http://www.apache.org/licenses/LICENSE-2.0
14 *
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
20 *
21 *//*!
22 * \file
23 * \brief State Query test utils.
24 *//*--------------------------------------------------------------------*/
25
26#include "tcuDefs.hpp"
27#include "tcuTestLog.hpp"
28#include "tcuTestContext.hpp"
29#include "glwDefs.hpp"
30#include "deMath.h"
31
32namespace glu
33{
34class CallLogWrapper;
35} // glu
36
37namespace deqp
38{
39namespace gls
40{
41namespace StateQueryUtil
42{
43
44/*--------------------------------------------------------------------*//*!
45 * \brief Rounds given float to the nearest integer (half up).
46 *
47 * Returns the nearest integer for a float argument. In the case that there
48 * are two nearest integers at the equal distance (aka. the argument is of
49 * form x.5), the integer with the higher value is chosen. (x.5 rounds to x+1)
50 *//*--------------------------------------------------------------------*/
51template <typename T>
52T roundGLfloatToNearestIntegerHalfUp (float val)
53{
54	return (T)(deFloatFloor(val + 0.5f));
55}
56
57/*--------------------------------------------------------------------*//*!
58 * \brief Rounds given float to the nearest integer (half down).
59 *
60 * Returns the nearest integer for a float argument. In the case that there
61 * are two nearest integers at the equal distance (aka. the argument is of
62 * form x.5), the integer with the higher value is chosen. (x.5 rounds to x)
63 *//*--------------------------------------------------------------------*/
64template <typename T>
65T roundGLfloatToNearestIntegerHalfDown (float val)
66{
67	return (T)(deFloatCeil(val - 0.5f));
68}
69
70template <typename T>
71class StateQueryMemoryWriteGuard
72{
73public:
74					StateQueryMemoryWriteGuard	(void);
75
76					operator T&					(void);
77	T*				operator &					(void);
78
79	bool			isUndefined					(void) const;
80	bool			isMemoryContaminated		(void) const;
81	bool			isPreguardContaminated		(void) const;
82	bool			isPostguardContaminated		(void) const;
83	bool			verifyValidity				(tcu::TestContext& testCtx) const;
84	bool			verifyValidity				(tcu::ResultCollector& result) const;
85
86	const T&		get							(void) const { return m_value; }
87
88private:
89	enum
90	{
91		WRITE_GUARD_VALUE = 0xDE
92	};
93
94	T				m_preguard;
95	T				m_value;
96	T				m_postguard; // \note guards are not const qualified since the GL implementation might modify them
97};
98
99template <typename T>
100StateQueryMemoryWriteGuard<T>::StateQueryMemoryWriteGuard (void)
101{
102	DE_STATIC_ASSERT(sizeof(T) * 3 == sizeof(StateQueryMemoryWriteGuard<T>)); // tightly packed
103
104	for (size_t i = 0; i < sizeof(T); ++i)
105	{
106		((deUint8*)&m_preguard)[i]	= (deUint8)WRITE_GUARD_VALUE;
107		((deUint8*)&m_value)[i]		= (deUint8)WRITE_GUARD_VALUE;
108		((deUint8*)&m_postguard)[i]	= (deUint8)WRITE_GUARD_VALUE;
109	}
110}
111
112template <typename T>
113StateQueryMemoryWriteGuard<T>::operator T& (void)
114{
115	return m_value;
116}
117
118template <typename T>
119T* StateQueryMemoryWriteGuard<T>::operator & (void)
120{
121	return &m_value;
122}
123
124template <typename T>
125bool StateQueryMemoryWriteGuard<T>::isUndefined () const
126{
127	for (size_t i = 0; i < sizeof(T); ++i)
128		if (((deUint8*)&m_value)[i] != (deUint8)WRITE_GUARD_VALUE)
129			return false;
130	return true;
131}
132
133template <typename T>
134bool StateQueryMemoryWriteGuard<T>::isMemoryContaminated () const
135{
136	return isPreguardContaminated() || isPostguardContaminated();
137}
138
139template <typename T>
140bool StateQueryMemoryWriteGuard<T>::isPreguardContaminated (void) const
141{
142	for (size_t i = 0; i < sizeof(T); ++i)
143		if (((deUint8*)&m_preguard)[i] != (deUint8)WRITE_GUARD_VALUE)
144			return true;
145	return false;
146}
147
148template <typename T>
149bool StateQueryMemoryWriteGuard<T>::isPostguardContaminated (void) const
150{
151	for (size_t i = 0; i < sizeof(T); ++i)
152		if (((deUint8*)&m_postguard)[i] != (deUint8)WRITE_GUARD_VALUE)
153			return true;
154	return false;
155}
156
157template <typename T>
158bool StateQueryMemoryWriteGuard<T>::verifyValidity (tcu::TestContext& testCtx) const
159{
160	using tcu::TestLog;
161
162	if (isPreguardContaminated())
163	{
164		testCtx.getLog() << TestLog::Message << "// ERROR: Pre-guard value was modified " << TestLog::EndMessage;
165		if (testCtx.getTestResult() == QP_TEST_RESULT_PASS ||
166			testCtx.getTestResult() == QP_TEST_RESULT_LAST)
167			testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Get* did an illegal memory write");
168
169		return false;
170	}
171	else if (isPostguardContaminated())
172	{
173		testCtx.getLog() << TestLog::Message << "// ERROR: Post-guard value was modified " << TestLog::EndMessage;
174		if (testCtx.getTestResult() == QP_TEST_RESULT_PASS ||
175			testCtx.getTestResult() == QP_TEST_RESULT_LAST)
176			testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Get* did an illegal memory write");
177
178		return false;
179	}
180	else if (isUndefined())
181	{
182		testCtx.getLog() << TestLog::Message << "// ERROR: Get* did not return a value" << TestLog::EndMessage;
183		if (testCtx.getTestResult() == QP_TEST_RESULT_PASS ||
184			testCtx.getTestResult() == QP_TEST_RESULT_LAST)
185			testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Get* did not return a value");
186
187		return false;
188	}
189
190	return true;
191}
192
193template <typename T>
194bool StateQueryMemoryWriteGuard<T>::verifyValidity (tcu::ResultCollector& result) const
195{
196	using tcu::TestLog;
197
198	if (isPreguardContaminated())
199	{
200		result.fail("pre-guard value was modified");
201		return false;
202	}
203	else if (isPostguardContaminated())
204	{
205		result.fail("post-guard value was modified");
206		return false;
207	}
208	else if (isUndefined())
209	{
210		result.fail("Get* did not return a value");
211		return false;
212	}
213
214	return true;
215}
216
217template<typename T>
218std::ostream& operator<< (std::ostream& str, const StateQueryMemoryWriteGuard<T>& guard)
219{
220	return str << guard.get();
221}
222
223// Verifiers
224
225enum QueryType
226{
227	QUERY_BOOLEAN = 0,
228	QUERY_BOOLEAN_VEC4,
229	QUERY_ISENABLED,
230	QUERY_INTEGER,
231	QUERY_INTEGER64,
232	QUERY_FLOAT,
233
234	// indexed
235	QUERY_INDEXED_BOOLEAN,
236	QUERY_INDEXED_INTEGER,
237	QUERY_INDEXED_INTEGER64,
238
239	// attributes
240	QUERY_ATTRIBUTE_INTEGER,
241	QUERY_ATTRIBUTE_FLOAT,
242	QUERY_ATTRIBUTE_PURE_INTEGER,
243	QUERY_ATTRIBUTE_PURE_UNSIGNED_INTEGER,
244
245	// fb
246	QUERY_FRAMEBUFFER_INTEGER,
247
248	// program
249	QUERY_PROGRAM_INTEGER,
250	QUERY_PROGRAM_INTEGER_VEC3,
251
252	// program pipeline
253	QUERY_PIPELINE_INTEGER,
254
255	// texture param
256	QUERY_TEXTURE_PARAM_INTEGER,
257	QUERY_TEXTURE_PARAM_FLOAT,
258
259	// texture level
260	QUERY_TEXTURE_LEVEL_INTEGER,
261	QUERY_TEXTURE_LEVEL_FLOAT,
262
263	QUERY_LAST
264};
265
266enum DataType
267{
268	DATATYPE_BOOLEAN = 0,
269	DATATYPE_INTEGER,
270	DATATYPE_INTEGER64,
271	DATATYPE_FLOAT,
272	DATATYPE_UNSIGNED_INTEGER,
273	DATATYPE_INTEGER_VEC3,
274
275	DATATYPE_LAST
276};
277
278class QueriedState
279{
280public:
281	typedef glw::GLint GLIntVec3[3];
282
283							QueriedState		(void);
284	explicit				QueriedState		(glw::GLint);
285	explicit				QueriedState		(glw::GLint64);
286	explicit				QueriedState		(glw::GLboolean);
287	explicit				QueriedState		(glw::GLfloat);
288	explicit				QueriedState		(glw::GLuint);
289	explicit				QueriedState		(const GLIntVec3&);
290
291	bool					isUndefined			(void) const;
292	DataType				getType				(void) const;
293
294	glw::GLint&				getIntAccess		(void);
295	glw::GLint64&			getInt64Access		(void);
296	glw::GLboolean&			getBoolAccess		(void);
297	glw::GLfloat&			getFloatAccess		(void);
298	glw::GLuint&			getUintAccess		(void);
299	GLIntVec3&				getIntVec3Access	(void);
300
301private:
302	DataType				m_type;
303	union
304	{
305		glw::GLint			vInt;
306		glw::GLint64		vInt64;
307		glw::GLboolean		vBool;
308		glw::GLfloat		vFloat;
309		glw::GLuint			vUint;
310		GLIntVec3			vIntVec3;
311	} m_v;
312};
313
314// query functions
315
316void queryState							(tcu::ResultCollector& result, glu::CallLogWrapper& gl, QueryType type, glw::GLenum target, QueriedState& state);
317void queryIndexedState					(tcu::ResultCollector& result, glu::CallLogWrapper& gl, QueryType type, glw::GLenum target, int index, QueriedState& state);
318void queryAttributeState				(tcu::ResultCollector& result, glu::CallLogWrapper& gl, QueryType type, glw::GLenum target, int index, QueriedState& state);
319void queryFramebufferState				(tcu::ResultCollector& result, glu::CallLogWrapper& gl, QueryType type, glw::GLenum target, glw::GLenum pname, QueriedState& state);
320void queryProgramState					(tcu::ResultCollector& result, glu::CallLogWrapper& gl, QueryType type, glw::GLuint program, glw::GLenum pname, QueriedState& state);
321void queryPipelineState					(tcu::ResultCollector& result, glu::CallLogWrapper& gl, QueryType type, glw::GLuint pipeline, glw::GLenum pname, QueriedState& state);
322void queryTextureParamState				(tcu::ResultCollector& result, glu::CallLogWrapper& gl, QueryType type, glw::GLenum target, glw::GLenum pname, QueriedState& state);
323void queryTextureLevelState				(tcu::ResultCollector& result, glu::CallLogWrapper& gl, QueryType type, glw::GLenum target, int level, glw::GLenum pname, QueriedState& state);
324
325// verification functions
326
327void verifyBoolean						(tcu::ResultCollector& result, QueriedState& state, bool expected);
328void verifyInteger						(tcu::ResultCollector& result, QueriedState& state, int expected);
329void verifyIntegerMin					(tcu::ResultCollector& result, QueriedState& state, int minValue);
330void verifyIntegerMax					(tcu::ResultCollector& result, QueriedState& state, int maxValue);
331void verifyIntegersEqual				(tcu::ResultCollector& result, QueriedState& stateA, QueriedState& stateB);
332void verifyFloat						(tcu::ResultCollector& result, QueriedState& state, float expected);
333void verifyFloatMin						(tcu::ResultCollector& result, QueriedState& state, float minValue);
334void verifyFloatMax						(tcu::ResultCollector& result, QueriedState& state, float maxValue);
335void verifyIntegerVec3					(tcu::ResultCollector& result, QueriedState& state, const tcu::IVec3& expected);
336
337// Helper functions that both query and verify
338
339void verifyStateBoolean					(tcu::ResultCollector& result, glu::CallLogWrapper& gl, glw::GLenum target,		bool expected,		QueryType type);
340void verifyStateInteger					(tcu::ResultCollector& result, glu::CallLogWrapper& gl, glw::GLenum target,		int expected,		QueryType type);
341void verifyStateIntegerMin				(tcu::ResultCollector& result, glu::CallLogWrapper& gl, glw::GLenum target,		int minValue,		QueryType type);
342void verifyStateIntegerMax				(tcu::ResultCollector& result, glu::CallLogWrapper& gl, glw::GLenum target,		int maxValue,		QueryType type);
343void verifyStateIntegerEqualToOther		(tcu::ResultCollector& result, glu::CallLogWrapper& gl, glw::GLenum target,		glw::GLenum other,	QueryType type);
344void verifyStateFloat					(tcu::ResultCollector& result, glu::CallLogWrapper& gl, glw::GLenum target,		float reference,	QueryType type);
345void verifyStateFloatMin				(tcu::ResultCollector& result, glu::CallLogWrapper& gl, glw::GLenum target,		float minValue,		QueryType type);
346void verifyStateFloatMax				(tcu::ResultCollector& result, glu::CallLogWrapper& gl, glw::GLenum target,		float maxValue,		QueryType type);
347void verifyStateIndexedBoolean			(tcu::ResultCollector& result, glu::CallLogWrapper& gl, glw::GLenum target,		int index,			bool expected,				QueryType type);
348void verifyStateIndexedInteger			(tcu::ResultCollector& result, glu::CallLogWrapper& gl, glw::GLenum target,		int index,			int expected,				QueryType type);
349void verifyStateIndexedIntegerMin		(tcu::ResultCollector& result, glu::CallLogWrapper& gl, glw::GLenum target,		int index,			int minValue,				QueryType type);
350void verifyStateAttributeInteger		(tcu::ResultCollector& result, glu::CallLogWrapper& gl, glw::GLenum target,		int index,			int expected,				QueryType type);
351void verifyStateFramebufferInteger		(tcu::ResultCollector& result, glu::CallLogWrapper& gl, glw::GLenum target,		glw::GLenum pname,	int expected,				QueryType type);
352void verifyStateFramebufferIntegerMin	(tcu::ResultCollector& result, glu::CallLogWrapper& gl, glw::GLenum target,		glw::GLenum pname,	int minValue,				QueryType type);
353void verifyStateProgramInteger			(tcu::ResultCollector& result, glu::CallLogWrapper& gl, glw::GLuint program,	glw::GLenum pname,	int expected,				QueryType type);
354void verifyStateProgramIntegerVec3		(tcu::ResultCollector& result, glu::CallLogWrapper& gl, glw::GLuint program, 	glw::GLenum pname,	const tcu::IVec3& expected,	QueryType type);
355void verifyStatePipelineInteger			(tcu::ResultCollector& result, glu::CallLogWrapper& gl, glw::GLuint pipeline,	glw::GLenum pname,	int expected,				QueryType type);
356void verifyStateTextureParamInteger		(tcu::ResultCollector& result, glu::CallLogWrapper& gl, glw::GLenum target,		glw::GLenum pname,	int expected,				QueryType type);
357
358} // StateQueryUtil
359} // gls
360} // deqp
361
362#endif // _GLSSTATEQUERYUTIL_HPP
363