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