1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program EGL 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 Extension function pointer query tests.
22  *//*--------------------------------------------------------------------*/
23 
24 #include "teglGetProcAddressTests.hpp"
25 #include "teglTestCase.hpp"
26 #include "egluCallLogWrapper.hpp"
27 #include "egluStrUtil.hpp"
28 #include "egluUtil.hpp"
29 #include "eglwLibrary.hpp"
30 #include "eglwEnums.hpp"
31 #include "tcuTestLog.hpp"
32 #include "deSTLUtil.hpp"
33 #include "deStringUtil.hpp"
34 
35 namespace deqp
36 {
37 namespace egl
38 {
39 
40 namespace
41 {
42 
43 using tcu::TestLog;
44 using namespace eglw;
45 
46 // Function name strings generated from API headers
47 
48 #include "teglGetProcAddressTests.inl"
49 
50 struct FunctionNames
51 {
52 	int					numFunctions;
53 	const char* const*	functions;
54 
FunctionNamesdeqp::egl::__anon6f7298c30111::FunctionNames55 	FunctionNames (int numFunctions_, const char* const* functions_)
56 		: numFunctions	(numFunctions_)
57 		, functions		(functions_)
58 	{
59 	}
60 };
61 
getExtFunctionNames(const std::string & extName)62 FunctionNames getExtFunctionNames (const std::string& extName)
63 {
64 	for (int ndx = 0; ndx <= DE_LENGTH_OF_ARRAY(s_extensions); ndx++)
65 	{
66 		if (extName == s_extensions[ndx].name)
67 			return FunctionNames(s_extensions[ndx].numFunctions, s_extensions[ndx].functions);
68 	}
69 
70 	DE_ASSERT(false);
71 	return FunctionNames(0, DE_NULL);
72 }
73 
getCoreFunctionNames(EGLint apiBit)74 FunctionNames getCoreFunctionNames (EGLint apiBit)
75 {
76 	switch (apiBit)
77 	{
78 		case 0:							return FunctionNames(DE_LENGTH_OF_ARRAY(s_EGL14),	s_EGL14);
79 		case EGL_OPENGL_ES_BIT:			return FunctionNames(DE_LENGTH_OF_ARRAY(s_GLES10),	s_GLES10);
80 		case EGL_OPENGL_ES2_BIT:		return FunctionNames(DE_LENGTH_OF_ARRAY(s_GLES20),	s_GLES20);
81 		case EGL_OPENGL_ES3_BIT_KHR:	return FunctionNames(DE_LENGTH_OF_ARRAY(s_GLES30),	s_GLES30);
82 		default:
83 			DE_ASSERT(false);
84 	}
85 
86 	return FunctionNames(0, DE_NULL);
87 }
88 
89 } // anonymous
90 
91 // Base class for eglGetProcAddress() test cases
92 
93 class GetProcAddressCase : public TestCase, protected eglu::CallLogWrapper
94 {
95 public:
96 								GetProcAddressCase		(EglTestContext& eglTestCtx, const char* name, const char* description);
97 	virtual						~GetProcAddressCase		(void);
98 
99 	void						init					(void);
100 	void						deinit					(void);
101 	IterateResult				iterate					(void);
102 
103 	bool						isSupported				(const std::string& extName);
104 
105 	virtual void				executeTest				(void) = 0;
106 
107 protected:
108 	EGLDisplay					m_display;
109 
110 private:
111 	std::vector<std::string>	m_supported;
112 };
113 
GetProcAddressCase(EglTestContext & eglTestCtx,const char * name,const char * description)114 GetProcAddressCase::GetProcAddressCase (EglTestContext& eglTestCtx, const char* name, const char* description)
115 	: TestCase			(eglTestCtx, name, description)
116 	, CallLogWrapper	(eglTestCtx.getLibrary(), eglTestCtx.getTestContext().getLog())
117 	, m_display			(EGL_NO_DISPLAY)
118 {
119 }
120 
~GetProcAddressCase(void)121 GetProcAddressCase::~GetProcAddressCase (void)
122 {
123 }
124 
init(void)125 void GetProcAddressCase::init (void)
126 {
127 	try
128 	{
129 		m_supported = eglu::getClientExtensions(m_eglTestCtx.getLibrary());
130 	}
131 	catch (const eglu::Error& error)
132 	{
133 		// EGL_BAD_DISPLAY is generated if client extensions are not supported.
134 		if (error.getError() != EGL_BAD_DISPLAY)
135 			throw;
136 	}
137 
138 	DE_ASSERT(m_display == EGL_NO_DISPLAY);
139 
140 	m_display = eglu::getAndInitDisplay(m_eglTestCtx.getNativeDisplay());
141 
142 	{
143 		const std::vector<std::string> displayExtensios = eglu::getDisplayExtensions(m_eglTestCtx.getLibrary(), m_display);
144 		m_supported.insert(m_supported.end(), displayExtensios.begin(), displayExtensios.end());
145 	}
146 
147 	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
148 }
149 
deinit(void)150 void GetProcAddressCase::deinit (void)
151 {
152 	m_eglTestCtx.getLibrary().terminate(m_display);
153 	m_display = EGL_NO_DISPLAY;
154 }
155 
iterate(void)156 tcu::TestNode::IterateResult GetProcAddressCase::iterate (void)
157 {
158 	enableLogging(true);
159 
160 	executeTest();
161 
162 	enableLogging(false);
163 
164 	return STOP;
165 }
166 
isSupported(const std::string & extName)167 bool GetProcAddressCase::isSupported (const std::string& extName)
168 {
169 	return de::contains(m_supported.begin(), m_supported.end(), extName);
170 }
171 
172 // Test by extension
173 
174 class GetProcAddressExtensionCase : public GetProcAddressCase
175 {
176 public:
GetProcAddressExtensionCase(EglTestContext & eglTestCtx,const char * name,const char * description,const std::string & extName)177 	GetProcAddressExtensionCase (EglTestContext& eglTestCtx, const char* name, const char* description, const std::string& extName)
178 		: GetProcAddressCase	(eglTestCtx, name, description)
179 		, m_extName				(extName)
180 	{
181 	}
182 
~GetProcAddressExtensionCase(void)183 	virtual ~GetProcAddressExtensionCase (void)
184 	{
185 	}
186 
executeTest(void)187 	void executeTest (void)
188 	{
189 		TestLog&				log			= m_testCtx.getLog();
190 		bool					supported	= isSupported(m_extName);
191 		const FunctionNames		funcNames	= getExtFunctionNames(m_extName);
192 
193 		DE_ASSERT(funcNames.numFunctions > 0);
194 
195 		log << TestLog::Message << m_extName << ": " << (supported ? "supported" : "not supported") << TestLog::EndMessage;
196 		log << TestLog::Message << TestLog::EndMessage;
197 
198 		for (int funcNdx = 0; funcNdx < funcNames.numFunctions; funcNdx++)
199 		{
200 			const char*	funcName		= funcNames.functions[funcNdx];
201 			void		(*funcPtr)(void);
202 
203 			funcPtr = eglGetProcAddress(funcName);
204 			eglu::checkError(eglGetError(), "eglGetProcAddress()", __FILE__, __LINE__);
205 
206 			if (supported && funcPtr == 0)
207 			{
208 				log << TestLog::Message << "Fail, received null pointer for supported extension function: " << funcName << TestLog::EndMessage;
209 				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Unexpected null pointer");
210 			}
211 		}
212 	}
213 
214 private:
215 	std::string	m_extName;
216 };
217 
218 // Test core functions
219 
220 class GetProcAddressCoreFunctionsCase : public GetProcAddressCase
221 {
222 public:
GetProcAddressCoreFunctionsCase(EglTestContext & eglTestCtx,const char * name,const char * description,const EGLint apiBit)223 	GetProcAddressCoreFunctionsCase (EglTestContext& eglTestCtx, const char* name, const char* description, const EGLint apiBit)
224 		: GetProcAddressCase	(eglTestCtx, name, description)
225 		, m_apiBit				(apiBit)
226 	{
227 	}
228 
~GetProcAddressCoreFunctionsCase(void)229 	virtual ~GetProcAddressCoreFunctionsCase (void)
230 	{
231 	}
232 
executeTest(void)233 	void executeTest (void)
234 	{
235 		TestLog&				log					= m_testCtx.getLog();
236 		const bool				funcPtrSupported	= isSupported("EGL_KHR_get_all_proc_addresses");
237 		const bool				apiSupported		= (eglu::getRenderableAPIsMask(m_eglTestCtx.getLibrary(), m_display) & m_apiBit) == m_apiBit;
238 		const FunctionNames		funcNames			= getCoreFunctionNames(m_apiBit);
239 
240 		log << TestLog::Message << "EGL_KHR_get_all_proc_addresses: " << (funcPtrSupported ? "supported" : "not supported") << TestLog::EndMessage;
241 		log << TestLog::Message << TestLog::EndMessage;
242 
243 		if (!apiSupported)
244 		{
245 			log << TestLog::Message << eglu::getConfigAttribValueStr(EGL_RENDERABLE_TYPE, m_apiBit) << " not supported by any available configuration." << TestLog::EndMessage;
246 			log << TestLog::Message << TestLog::EndMessage;
247 		}
248 
249 		for (int funcNdx = 0; funcNdx < funcNames.numFunctions; funcNdx++)
250 		{
251 			const char*	funcName			= funcNames.functions[funcNdx];
252 			void		(*funcPtr)(void);
253 
254 			funcPtr = eglGetProcAddress(funcName);
255 			eglu::checkError(eglGetError(), "eglGetProcAddress()", __FILE__, __LINE__);
256 
257 			if (apiSupported && funcPtrSupported && (funcPtr == 0))
258 			{
259 				log << TestLog::Message << "Fail, received null pointer for supported function: " << funcName << TestLog::EndMessage;
260 				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Unexpected null pointer");
261 			}
262 			else if (!apiSupported && (funcPtr != 0))
263 			{
264 				log << TestLog::Message << "Warning, received non-null value for unsupported function: " << funcName << TestLog::EndMessage;
265 				m_testCtx.setTestResult(QP_TEST_RESULT_QUALITY_WARNING, "Non-null value for unsupported function");
266 			}
267 		}
268 	}
269 
270 private:
271 	const EGLint	m_apiBit;
272 };
273 
GetProcAddressTests(EglTestContext & eglTestCtx)274 GetProcAddressTests::GetProcAddressTests (EglTestContext& eglTestCtx)
275 	: TestCaseGroup(eglTestCtx, "get_proc_address", "eglGetProcAddress() tests")
276 {
277 }
278 
~GetProcAddressTests(void)279 GetProcAddressTests::~GetProcAddressTests (void)
280 {
281 }
282 
init(void)283 void GetProcAddressTests::init (void)
284 {
285 	// extensions
286 	{
287 		tcu::TestCaseGroup* extensionsGroup = new tcu::TestCaseGroup(m_testCtx, "extension", "Test EGL extensions");
288 		addChild(extensionsGroup);
289 
290 		for (int extNdx = 0; extNdx < DE_LENGTH_OF_ARRAY(s_extensions); extNdx++)
291 		{
292 			const std::string&		extName		= s_extensions[extNdx].name;
293 			std::string				testName	(extName);
294 
295 			for (size_t ndx = 0; ndx < extName.length(); ndx++)
296 				testName[ndx] = de::toLower(extName[ndx]);
297 
298 			extensionsGroup->addChild(new GetProcAddressExtensionCase(m_eglTestCtx, testName.c_str(), ("Test " + extName).c_str(), extName));
299 		}
300 	}
301 
302 	// core functions
303 	{
304 		tcu::TestCaseGroup* coreFuncGroup = new tcu::TestCaseGroup(m_testCtx, "core", "Test core functions");
305 		addChild(coreFuncGroup);
306 
307 		coreFuncGroup->addChild(new GetProcAddressCoreFunctionsCase	(m_eglTestCtx,	"egl",		"Test EGL core functions",			0));
308 		coreFuncGroup->addChild(new GetProcAddressCoreFunctionsCase	(m_eglTestCtx,	"gles",		"Test OpenGL ES core functions",	EGL_OPENGL_ES_BIT));
309 		coreFuncGroup->addChild(new GetProcAddressCoreFunctionsCase	(m_eglTestCtx,	"gles2",	"Test OpenGL ES 2 core functions",	EGL_OPENGL_ES2_BIT));
310 		coreFuncGroup->addChild(new GetProcAddressCoreFunctionsCase	(m_eglTestCtx,	"gles3",	"Test OpenGL ES 3 core functions",	EGL_OPENGL_ES3_BIT_KHR));
311 	}
312 }
313 
314 } // egl
315 } // deqp
316