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 "tcuResultCollector.hpp"
30#include "glwDefs.hpp"
31#include "deMath.h"
32
33namespace glu
34{
35class CallLogWrapper;
36} // glu
37
38namespace deqp
39{
40namespace gls
41{
42namespace StateQueryUtil
43{
44
45#define GLS_COLLECT_GL_ERROR(RES, ERR, MSG) \
46	do \
47	{ \
48		const deUint32 err = (ERR); \
49		if (err != GL_NO_ERROR) \
50			(RES).fail(std::string("Got Error ") + glu::getErrorStr(err).toString() + ": " + (MSG)); \
51	} \
52	while (deGetFalse())
53
54/*--------------------------------------------------------------------*//*!
55 * \brief Rounds given float to the nearest integer (half up).
56 *
57 * Returns the nearest integer for a float argument. In the case that there
58 * are two nearest integers at the equal distance (aka. the argument is of
59 * form x.5), the integer with the higher value is chosen. (x.5 rounds to x+1)
60 *//*--------------------------------------------------------------------*/
61template <typename T>
62T roundGLfloatToNearestIntegerHalfUp (float val)
63{
64	return (T)(deFloatFloor(val + 0.5f));
65}
66
67/*--------------------------------------------------------------------*//*!
68 * \brief Rounds given float to the nearest integer (half down).
69 *
70 * Returns the nearest integer for a float argument. In the case that there
71 * are two nearest integers at the equal distance (aka. the argument is of
72 * form x.5), the integer with the higher value is chosen. (x.5 rounds to x)
73 *//*--------------------------------------------------------------------*/
74template <typename T>
75T roundGLfloatToNearestIntegerHalfDown (float val)
76{
77	return (T)(deFloatCeil(val - 0.5f));
78}
79
80template <typename T>
81class StateQueryMemoryWriteGuard
82{
83public:
84					StateQueryMemoryWriteGuard	(void);
85
86					operator T&					(void);
87	T*				operator &					(void);
88
89	bool			isUndefined					(void) const;
90	bool			isMemoryContaminated		(void) const;
91	bool			isPreguardContaminated		(void) const;
92	bool			isPostguardContaminated		(void) const;
93	bool			verifyValidity				(tcu::TestContext& testCtx) const;
94	bool			verifyValidity				(tcu::ResultCollector& result) const;
95
96	const T&		get							(void) const { return m_value; }
97
98private:
99	enum
100	{
101		WRITE_GUARD_VALUE = 0xDE
102	};
103
104	T				m_preguard;
105	T				m_value;
106	T				m_postguard; // \note guards are not const qualified since the GL implementation might modify them
107};
108
109template <typename T>
110StateQueryMemoryWriteGuard<T>::StateQueryMemoryWriteGuard (void)
111{
112	DE_STATIC_ASSERT(sizeof(T) * 3 == sizeof(StateQueryMemoryWriteGuard<T>)); // tightly packed
113
114	deMemset(&m_preguard, WRITE_GUARD_VALUE, sizeof(m_preguard));
115	deMemset(&m_value, WRITE_GUARD_VALUE, sizeof(m_value));
116	deMemset(&m_postguard, WRITE_GUARD_VALUE, sizeof(m_postguard));
117}
118
119template <typename T>
120StateQueryMemoryWriteGuard<T>::operator T& (void)
121{
122	return m_value;
123}
124
125template <typename T>
126T* StateQueryMemoryWriteGuard<T>::operator & (void)
127{
128	return &m_value;
129}
130
131template <typename T>
132bool StateQueryMemoryWriteGuard<T>::isUndefined () const
133{
134	for (size_t i = 0; i < sizeof(T); ++i)
135		if (((deUint8*)&m_value)[i] != (deUint8)WRITE_GUARD_VALUE)
136			return false;
137	return true;
138}
139
140template <typename T>
141bool StateQueryMemoryWriteGuard<T>::isMemoryContaminated () const
142{
143	return isPreguardContaminated() || isPostguardContaminated();
144}
145
146template <typename T>
147bool StateQueryMemoryWriteGuard<T>::isPreguardContaminated (void) const
148{
149	for (size_t i = 0; i < sizeof(T); ++i)
150		if (((deUint8*)&m_preguard)[i] != (deUint8)WRITE_GUARD_VALUE)
151			return true;
152	return false;
153}
154
155template <typename T>
156bool StateQueryMemoryWriteGuard<T>::isPostguardContaminated (void) const
157{
158	for (size_t i = 0; i < sizeof(T); ++i)
159		if (((deUint8*)&m_postguard)[i] != (deUint8)WRITE_GUARD_VALUE)
160			return true;
161	return false;
162}
163
164template <typename T>
165bool StateQueryMemoryWriteGuard<T>::verifyValidity (tcu::TestContext& testCtx) const
166{
167	using tcu::TestLog;
168
169	if (isPreguardContaminated())
170	{
171		testCtx.getLog() << TestLog::Message << "// ERROR: Pre-guard value was modified " << TestLog::EndMessage;
172		if (testCtx.getTestResult() == QP_TEST_RESULT_PASS ||
173			testCtx.getTestResult() == QP_TEST_RESULT_LAST)
174			testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Get* did an illegal memory write");
175
176		return false;
177	}
178	else if (isPostguardContaminated())
179	{
180		testCtx.getLog() << TestLog::Message << "// ERROR: Post-guard value was modified " << TestLog::EndMessage;
181		if (testCtx.getTestResult() == QP_TEST_RESULT_PASS ||
182			testCtx.getTestResult() == QP_TEST_RESULT_LAST)
183			testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Get* did an illegal memory write");
184
185		return false;
186	}
187	else if (isUndefined())
188	{
189		testCtx.getLog() << TestLog::Message << "// ERROR: Get* did not return a value" << TestLog::EndMessage;
190		if (testCtx.getTestResult() == QP_TEST_RESULT_PASS ||
191			testCtx.getTestResult() == QP_TEST_RESULT_LAST)
192			testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Get* did not return a value");
193
194		return false;
195	}
196
197	return true;
198}
199
200template <typename T>
201bool StateQueryMemoryWriteGuard<T>::verifyValidity (tcu::ResultCollector& result) const
202{
203	using tcu::TestLog;
204
205	if (isPreguardContaminated())
206	{
207		result.fail("pre-guard value was modified");
208		return false;
209	}
210	else if (isPostguardContaminated())
211	{
212		result.fail("post-guard value was modified");
213		return false;
214	}
215	else if (isUndefined())
216	{
217		result.fail("Get* did not return a value");
218		return false;
219	}
220
221	return true;
222}
223
224template<typename T>
225std::ostream& operator<< (std::ostream& str, const StateQueryMemoryWriteGuard<T>& guard)
226{
227	return str << guard.get();
228}
229
230// Verifiers
231
232enum QueryType
233{
234	QUERY_BOOLEAN = 0,
235	QUERY_BOOLEAN_VEC4,
236	QUERY_ISENABLED,
237	QUERY_INTEGER,
238	QUERY_INTEGER64,
239	QUERY_FLOAT,
240
241	// indexed
242	QUERY_INDEXED_BOOLEAN,
243	QUERY_INDEXED_BOOLEAN_VEC4,
244	QUERY_INDEXED_ISENABLED,
245	QUERY_INDEXED_INTEGER,
246	QUERY_INDEXED_INTEGER_VEC4,
247	QUERY_INDEXED_INTEGER64,
248	QUERY_INDEXED_INTEGER64_VEC4,
249
250	// attributes
251	QUERY_ATTRIBUTE_INTEGER,
252	QUERY_ATTRIBUTE_FLOAT,
253	QUERY_ATTRIBUTE_PURE_INTEGER,
254	QUERY_ATTRIBUTE_PURE_UNSIGNED_INTEGER,
255
256	// fb
257	QUERY_FRAMEBUFFER_INTEGER,
258
259	// program
260	QUERY_PROGRAM_INTEGER,
261	QUERY_PROGRAM_INTEGER_VEC3,
262
263	// program pipeline
264	QUERY_PIPELINE_INTEGER,
265
266	// texture param
267	QUERY_TEXTURE_PARAM_INTEGER,
268	QUERY_TEXTURE_PARAM_FLOAT,
269	QUERY_TEXTURE_PARAM_PURE_INTEGER,
270	QUERY_TEXTURE_PARAM_PURE_UNSIGNED_INTEGER,
271	QUERY_TEXTURE_PARAM_INTEGER_VEC4,
272	QUERY_TEXTURE_PARAM_FLOAT_VEC4,
273	QUERY_TEXTURE_PARAM_PURE_INTEGER_VEC4,
274	QUERY_TEXTURE_PARAM_PURE_UNSIGNED_INTEGER_VEC4,
275
276	// texture level
277	QUERY_TEXTURE_LEVEL_INTEGER,
278	QUERY_TEXTURE_LEVEL_FLOAT,
279
280	// pointer
281	QUERY_POINTER,
282
283	// object states
284	QUERY_ISTEXTURE,
285
286	// query queries
287	QUERY_QUERY,
288
289	// sampler state
290	QUERY_SAMPLER_PARAM_INTEGER,
291	QUERY_SAMPLER_PARAM_FLOAT,
292	QUERY_SAMPLER_PARAM_PURE_INTEGER,
293	QUERY_SAMPLER_PARAM_PURE_UNSIGNED_INTEGER,
294	QUERY_SAMPLER_PARAM_INTEGER_VEC4,
295	QUERY_SAMPLER_PARAM_FLOAT_VEC4,
296	QUERY_SAMPLER_PARAM_PURE_INTEGER_VEC4,
297	QUERY_SAMPLER_PARAM_PURE_UNSIGNED_INTEGER_VEC4,
298
299	QUERY_LAST
300};
301
302enum DataType
303{
304	DATATYPE_BOOLEAN = 0,
305	DATATYPE_INTEGER,
306	DATATYPE_INTEGER64,
307	DATATYPE_FLOAT16,
308	DATATYPE_FLOAT,
309	DATATYPE_UNSIGNED_INTEGER,
310	DATATYPE_INTEGER_VEC3,
311	DATATYPE_FLOAT_VEC4,
312	DATATYPE_INTEGER_VEC4,
313	DATATYPE_INTEGER64_VEC4,
314	DATATYPE_UNSIGNED_INTEGER_VEC4,
315	DATATYPE_BOOLEAN_VEC4,
316	DATATYPE_POINTER,
317
318	DATATYPE_LAST
319};
320
321class QueriedState
322{
323public:
324	typedef glw::GLint		GLIntVec3[3];
325	typedef glw::GLint		GLIntVec4[4];
326	typedef glw::GLuint		GLUintVec4[4];
327	typedef glw::GLfloat	GLFloatVec4[4];
328	typedef bool			BooleanVec4[4];
329	typedef glw::GLint64	GLInt64Vec4[4];
330
331							QueriedState			(void);
332	explicit				QueriedState			(glw::GLint);
333	explicit				QueriedState			(glw::GLint64);
334	explicit				QueriedState			(bool);
335	explicit				QueriedState			(glw::GLfloat);
336	explicit				QueriedState			(glw::GLuint);
337	explicit				QueriedState			(const GLIntVec3&);
338	explicit				QueriedState			(void*);
339	explicit				QueriedState			(const GLIntVec4&);
340	explicit				QueriedState			(const GLUintVec4&);
341	explicit				QueriedState			(const GLFloatVec4&);
342	explicit				QueriedState			(const BooleanVec4&);
343	explicit				QueriedState			(const GLInt64Vec4&);
344
345	bool					isUndefined				(void) const;
346	DataType				getType					(void) const;
347
348	glw::GLint&				getIntAccess			(void);
349	glw::GLint64&			getInt64Access			(void);
350	bool&					getBoolAccess			(void);
351	glw::GLfloat&			getFloatAccess			(void);
352	glw::GLuint&			getUintAccess			(void);
353	GLIntVec3&				getIntVec3Access		(void);
354	void*&					getPtrAccess			(void);
355	GLIntVec4&				getIntVec4Access		(void);
356	GLUintVec4&				getUintVec4Access		(void);
357	GLFloatVec4&			getFloatVec4Access		(void);
358	BooleanVec4&			getBooleanVec4Access	(void);
359	GLInt64Vec4&			getInt64Vec4Access		(void);
360
361private:
362	DataType				m_type;
363	union
364	{
365		glw::GLint			vInt;
366		glw::GLint64		vInt64;
367		bool				vBool;
368		glw::GLfloat		vFloat;
369		glw::GLuint			vUint;
370		GLIntVec3			vIntVec3;
371		void*				vPtr;
372		GLIntVec4			vIntVec4;
373		GLUintVec4			vUintVec4;
374		GLFloatVec4			vFloatVec4;
375		BooleanVec4			vBooleanVec4;
376		GLInt64Vec4			vInt64Vec4;
377	} m_v;
378};
379
380// query functions
381
382void queryState									(tcu::ResultCollector& result, glu::CallLogWrapper& gl, QueryType type, glw::GLenum pname, QueriedState& state);
383void queryIndexedState							(tcu::ResultCollector& result, glu::CallLogWrapper& gl, QueryType type, glw::GLenum target, int index, QueriedState& state);
384void queryAttributeState						(tcu::ResultCollector& result, glu::CallLogWrapper& gl, QueryType type, glw::GLenum target, int index, QueriedState& state);
385void queryFramebufferState						(tcu::ResultCollector& result, glu::CallLogWrapper& gl, QueryType type, glw::GLenum target, glw::GLenum pname, QueriedState& state);
386void queryProgramState							(tcu::ResultCollector& result, glu::CallLogWrapper& gl, QueryType type, glw::GLuint program, glw::GLenum pname, QueriedState& state);
387void queryPipelineState							(tcu::ResultCollector& result, glu::CallLogWrapper& gl, QueryType type, glw::GLuint pipeline, glw::GLenum pname, QueriedState& state);
388void queryTextureParamState						(tcu::ResultCollector& result, glu::CallLogWrapper& gl, QueryType type, glw::GLenum target, glw::GLenum pname, QueriedState& state);
389void queryTextureLevelState						(tcu::ResultCollector& result, glu::CallLogWrapper& gl, QueryType type, glw::GLenum target, int level, glw::GLenum pname, QueriedState& state);
390void queryPointerState							(tcu::ResultCollector& result, glu::CallLogWrapper& gl, QueryType type, glw::GLenum pname, QueriedState& state);
391void queryObjectState							(tcu::ResultCollector& result, glu::CallLogWrapper& gl, QueryType type, glw::GLuint handle, QueriedState& state);
392void queryQueryState							(tcu::ResultCollector& result, glu::CallLogWrapper& gl, QueryType type, glw::GLenum target, glw::GLenum pname, QueriedState& state);
393void querySamplerState							(tcu::ResultCollector& result, glu::CallLogWrapper& gl, QueryType type, glw::GLuint sampler, glw::GLenum pname, QueriedState& state);
394
395// verification functions
396
397void verifyBoolean								(tcu::ResultCollector& result, QueriedState& state, bool expected);
398void verifyInteger								(tcu::ResultCollector& result, QueriedState& state, int expected);
399void verifyIntegerMin							(tcu::ResultCollector& result, QueriedState& state, int minValue);
400void verifyIntegerMax							(tcu::ResultCollector& result, QueriedState& state, int maxValue);
401void verifyIntegersEqual						(tcu::ResultCollector& result, QueriedState& stateA, QueriedState& stateB);
402void verifyFloat								(tcu::ResultCollector& result, QueriedState& state, float expected);
403void verifyFloatMin								(tcu::ResultCollector& result, QueriedState& state, float minValue);
404void verifyFloatMax								(tcu::ResultCollector& result, QueriedState& state, float maxValue);
405void verifyIntegerVec3							(tcu::ResultCollector& result, QueriedState& state, const tcu::IVec3& expected);
406void verifyIntegerVec4							(tcu::ResultCollector& result, QueriedState& state, const tcu::IVec4& expected);
407void verifyUnsignedIntegerVec4					(tcu::ResultCollector& result, QueriedState& state, const tcu::UVec4& expected);
408void verifyFloatVec4							(tcu::ResultCollector& result, QueriedState& state, const tcu::Vec4& expected);
409void verifyBooleanVec4							(tcu::ResultCollector& result, QueriedState& state, const tcu::BVec4& expected);
410void verifyPointer								(tcu::ResultCollector& result, QueriedState& state, const void* expected);
411void verifyNormalizedI32Vec4					(tcu::ResultCollector& result, QueriedState& state, const tcu::IVec4& expected);
412
413// Helper functions that both query and verify
414
415void verifyStateBoolean							(tcu::ResultCollector& result, glu::CallLogWrapper& gl, glw::GLenum target,		bool expected,			QueryType type);
416void verifyStateInteger							(tcu::ResultCollector& result, glu::CallLogWrapper& gl, glw::GLenum target,		int expected,			QueryType type);
417void verifyStateIntegerMin						(tcu::ResultCollector& result, glu::CallLogWrapper& gl, glw::GLenum target,		int minValue,			QueryType type);
418void verifyStateIntegerMax						(tcu::ResultCollector& result, glu::CallLogWrapper& gl, glw::GLenum target,		int maxValue,			QueryType type);
419void verifyStateIntegerEqualToOther				(tcu::ResultCollector& result, glu::CallLogWrapper& gl, glw::GLenum target,		glw::GLenum other,		QueryType type);
420void verifyStateFloat							(tcu::ResultCollector& result, glu::CallLogWrapper& gl, glw::GLenum target,		float reference,		QueryType type);
421void verifyStateFloatMin						(tcu::ResultCollector& result, glu::CallLogWrapper& gl, glw::GLenum target,		float minValue,			QueryType type);
422void verifyStateFloatMax						(tcu::ResultCollector& result, glu::CallLogWrapper& gl, glw::GLenum target,		float maxValue,			QueryType type);
423void verifyStatePointer							(tcu::ResultCollector& result, glu::CallLogWrapper& gl, glw::GLenum target,		const void* expected,	QueryType type);
424void verifyStateIndexedBoolean					(tcu::ResultCollector& result, glu::CallLogWrapper& gl, glw::GLenum target,		int index,				bool expected,				QueryType type);
425void verifyStateIndexedBooleanVec4				(tcu::ResultCollector& result, glu::CallLogWrapper& gl, glw::GLenum target,		int index,				const tcu::BVec4& expected,	QueryType type);
426void verifyStateIndexedInteger					(tcu::ResultCollector& result, glu::CallLogWrapper& gl, glw::GLenum target,		int index,				int expected,				QueryType type);
427void verifyStateIndexedIntegerMin				(tcu::ResultCollector& result, glu::CallLogWrapper& gl, glw::GLenum target,		int index,				int minValue,				QueryType type);
428void verifyStateAttributeInteger				(tcu::ResultCollector& result, glu::CallLogWrapper& gl, glw::GLenum target,		int index,				int expected,				QueryType type);
429void verifyStateFramebufferInteger				(tcu::ResultCollector& result, glu::CallLogWrapper& gl, glw::GLenum target,		glw::GLenum pname,		int expected,				QueryType type);
430void verifyStateFramebufferIntegerMin			(tcu::ResultCollector& result, glu::CallLogWrapper& gl, glw::GLenum target,		glw::GLenum pname,		int minValue,				QueryType type);
431void verifyStateProgramInteger					(tcu::ResultCollector& result, glu::CallLogWrapper& gl, glw::GLuint program,	glw::GLenum pname,		int expected,				QueryType type);
432void verifyStateProgramIntegerVec3				(tcu::ResultCollector& result, glu::CallLogWrapper& gl, glw::GLuint program,	glw::GLenum pname,		const tcu::IVec3& expected,	QueryType type);
433void verifyStatePipelineInteger					(tcu::ResultCollector& result, glu::CallLogWrapper& gl, glw::GLuint pipeline,	glw::GLenum pname,		int expected,				QueryType type);
434void verifyStateTextureParamInteger				(tcu::ResultCollector& result, glu::CallLogWrapper& gl, glw::GLenum target,		glw::GLenum pname,		int expected,				QueryType type);
435void verifyStateTextureParamFloat				(tcu::ResultCollector& result, glu::CallLogWrapper& gl, glw::GLenum target,		glw::GLenum pname,		float expected,				QueryType type);
436void verifyStateTextureParamFloatVec4			(tcu::ResultCollector& result, glu::CallLogWrapper& gl, glw::GLenum target,		glw::GLenum pname,		const tcu::Vec4& expected,	QueryType type);
437void verifyStateTextureParamNormalizedI32Vec4	(tcu::ResultCollector& result, glu::CallLogWrapper& gl, glw::GLenum target,		glw::GLenum pname,		const tcu::IVec4& expected,	QueryType type);
438void verifyStateTextureParamIntegerVec4			(tcu::ResultCollector& result, glu::CallLogWrapper& gl, glw::GLenum target,		glw::GLenum pname,		const tcu::IVec4& expected,	QueryType type);
439void verifyStateTextureParamUnsignedIntegerVec4	(tcu::ResultCollector& result, glu::CallLogWrapper& gl, glw::GLenum target,		glw::GLenum pname,		const tcu::UVec4& expected,	QueryType type);
440void verifyStateTextureLevelInteger				(tcu::ResultCollector& result, glu::CallLogWrapper& gl, glw::GLenum target,		int level,				glw::GLenum pname,			int expected,		QueryType type);
441void verifyStateObjectBoolean					(tcu::ResultCollector& result, glu::CallLogWrapper& gl, glw::GLuint handle,		bool expected,			QueryType type);
442void verifyStateQueryInteger					(tcu::ResultCollector& result, glu::CallLogWrapper& gl, glw::GLenum target,		glw::GLenum pname,		int expected,				QueryType type);
443void verifyStateSamplerParamInteger				(tcu::ResultCollector& result, glu::CallLogWrapper& gl, glw::GLuint sampler,	glw::GLenum pname,		int expected,				QueryType type);
444void verifyStateSamplerParamFloat				(tcu::ResultCollector& result, glu::CallLogWrapper& gl, glw::GLuint sampler,	glw::GLenum pname,		float expected,				QueryType type);
445void verifyStateSamplerParamFloatVec4			(tcu::ResultCollector& result, glu::CallLogWrapper& gl, glw::GLuint sampler,	glw::GLenum pname,		const tcu::Vec4& expected,	QueryType type);
446void verifyStateSamplerParamNormalizedI32Vec4	(tcu::ResultCollector& result, glu::CallLogWrapper& gl, glw::GLuint sampler,	glw::GLenum pname,		const tcu::IVec4& expected,	QueryType type);
447void verifyStateSamplerParamIntegerVec4			(tcu::ResultCollector& result, glu::CallLogWrapper& gl, glw::GLuint sampler,	glw::GLenum pname,		const tcu::IVec4& expected,	QueryType type);
448void verifyStateSamplerParamUnsignedIntegerVec4	(tcu::ResultCollector& result, glu::CallLogWrapper& gl, glw::GLuint sampler,	glw::GLenum pname,		const tcu::UVec4& expected,	QueryType type);
449
450} // StateQueryUtil
451} // gls
452} // deqp
453
454#endif // _GLSSTATEQUERYUTIL_HPP
455