glsStateQueryUtil.hpp revision 3c827367444ee418f129b2c238299f49d3264554
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 "deMath.h"
27#include "tcuDefs.hpp"
28#include "tcuTestLog.hpp"
29
30namespace deqp
31{
32namespace gls
33{
34namespace StateQueryUtil
35{
36
37/*--------------------------------------------------------------------*//*!
38 * \brief Rounds given float to the nearest integer (half up).
39 *
40 * Returns the nearest integer for a float argument. In the case that there
41 * are two nearest integers at the equal distance (aka. the argument is of
42 * form x.5), the integer with the higher value is chosen. (x.5 rounds to x+1)
43 *//*--------------------------------------------------------------------*/
44template <typename T>
45T roundGLfloatToNearestIntegerHalfUp (float val)
46{
47	return (T)(deFloatFloor(val + 0.5f));
48}
49
50/*--------------------------------------------------------------------*//*!
51 * \brief Rounds given float to the nearest integer (half down).
52 *
53 * Returns the nearest integer for a float argument. In the case that there
54 * are two nearest integers at the equal distance (aka. the argument is of
55 * form x.5), the integer with the higher value is chosen. (x.5 rounds to x)
56 *//*--------------------------------------------------------------------*/
57template <typename T>
58T roundGLfloatToNearestIntegerHalfDown (float val)
59{
60	return (T)(deFloatCeil(val - 0.5f));
61}
62
63template <typename T>
64class StateQueryMemoryWriteGuard
65{
66public:
67					StateQueryMemoryWriteGuard	(void);
68
69					operator T&					(void);
70	T*				operator &					(void);
71
72	bool			isUndefined					(void) const;
73	bool			isMemoryContaminated		(void) const;
74	bool			verifyValidity				(tcu::TestContext& testCtx) const;
75
76	const T&		get							(void) const { return m_value; }
77
78private:
79	enum
80	{
81		GUARD_VALUE = 0xDEDEADCD
82	};
83	enum
84	{
85		WRITE_GUARD_VALUE = 0xDE
86	};
87
88	deInt32			m_preguard;
89	union
90	{
91		T			m_value;
92		deUint8		m_isWrittenToGuard[sizeof(T)];
93	};
94	deInt32			m_postguard; // \note guards are not const qualified since the GL implementation might modify them
95};
96
97template <typename T>
98StateQueryMemoryWriteGuard<T>::StateQueryMemoryWriteGuard (void)
99	: m_preguard	((deInt32)(GUARD_VALUE))
100	, m_postguard	((deInt32)(GUARD_VALUE))
101{
102	for (size_t i = 0; i < DE_LENGTH_OF_ARRAY(m_isWrittenToGuard); ++i)
103		m_isWrittenToGuard[i] = (deUint8)WRITE_GUARD_VALUE;
104}
105
106template <typename T>
107StateQueryMemoryWriteGuard<T>::operator T& (void)
108{
109	return m_value;
110}
111
112template <typename T>
113T* StateQueryMemoryWriteGuard<T>::operator & (void)
114{
115	return &m_value;
116}
117
118template <typename T>
119bool StateQueryMemoryWriteGuard<T>::isUndefined () const
120{
121	for (size_t i = 0; i < DE_LENGTH_OF_ARRAY(m_isWrittenToGuard); ++i)
122		if (m_isWrittenToGuard[i] != (deUint8)WRITE_GUARD_VALUE)
123			return false;
124	return true;
125}
126
127template <typename T>
128bool StateQueryMemoryWriteGuard<T>::isMemoryContaminated () const
129{
130	return (m_preguard != (deInt32)(GUARD_VALUE)) || (m_postguard != (deInt32)(GUARD_VALUE));
131}
132
133template <typename T>
134bool StateQueryMemoryWriteGuard<T>::verifyValidity (tcu::TestContext& testCtx) const
135{
136	using tcu::TestLog;
137
138	if (m_preguard != (deInt32)(GUARD_VALUE))
139	{
140		testCtx.getLog() << TestLog::Message << "// ERROR: Pre-guard value was modified " << TestLog::EndMessage;
141		if (testCtx.getTestResult() == QP_TEST_RESULT_PASS ||
142			testCtx.getTestResult() == QP_TEST_RESULT_LAST)
143			testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Get* did an illegal memory write");
144
145		return false;
146	}
147	else if (m_postguard != (deInt32)(GUARD_VALUE))
148	{
149		testCtx.getLog() << TestLog::Message << "// ERROR: Post-guard value was modified " << TestLog::EndMessage;
150		if (testCtx.getTestResult() == QP_TEST_RESULT_PASS ||
151			testCtx.getTestResult() == QP_TEST_RESULT_LAST)
152			testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Get* did an illegal memory write");
153
154		return false;
155	}
156	else if (isUndefined())
157	{
158		testCtx.getLog() << TestLog::Message << "// ERROR: Get* did not return a value" << TestLog::EndMessage;
159		if (testCtx.getTestResult() == QP_TEST_RESULT_PASS ||
160			testCtx.getTestResult() == QP_TEST_RESULT_LAST)
161			testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Get* did not return a value");
162
163		return false;
164	}
165
166	return true;
167}
168
169template<typename T>
170std::ostream& operator<< (std::ostream& str, const StateQueryMemoryWriteGuard<T>& guard)
171{
172	return str << guard.get();
173}
174
175} // StateQueryUtil
176} // gls
177} // deqp
178
179#endif // _GLSSTATEQUERYUTIL_HPP
180