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 EGL Test Case
22 *//*--------------------------------------------------------------------*/
23
24 #include "teglTestCase.hpp"
25
26 #include "tcuPlatform.hpp"
27
28 #include "egluUtil.hpp"
29 #include "egluGLFunctionLoader.hpp"
30 #include "egluPlatform.hpp"
31
32 #include "gluRenderContext.hpp"
33 #include "glwInitFunctions.hpp"
34
35 #include <set>
36
37 using std::vector;
38 using std::set;
39
40 namespace deqp
41 {
42 namespace egl
43 {
44
45 namespace
46 {
47
split(std::vector<std::string> & dst,const std::string & src)48 void split (std::vector<std::string>& dst, const std::string& src)
49 {
50 size_t start = 0;
51 size_t end = std::string::npos;
52
53 while ((end = src.find(' ', start)) != std::string::npos)
54 {
55 dst.push_back(src.substr(start, end-start));
56 start = end+1;
57 }
58
59 if (start < end)
60 dst.push_back(src.substr(start, end-start));
61 }
62
parseAPI(const std::string & api)63 EGLint parseAPI (const std::string& api)
64 {
65 if (api == "OpenGL")
66 return EGL_OPENGL_API;
67 else if (api == "OpenGL_ES")
68 return EGL_OPENGL_ES_API;
69 else if (api == "OpenVG")
70 return EGL_OPENVG_API;
71 else
72 {
73 tcu::print("Warning: Unknown API '%s'", api.c_str());
74 return 0;
75 }
76 }
77
78 } // anonymous
79
EglTestContext(tcu::TestContext & testCtx,const eglu::NativeDisplayFactory & displayFactory,const eglu::NativeWindowFactory * windowFactory,const eglu::NativePixmapFactory * pixmapFactory)80 EglTestContext::EglTestContext (tcu::TestContext& testCtx, const eglu::NativeDisplayFactory& displayFactory, const eglu::NativeWindowFactory* windowFactory, const eglu::NativePixmapFactory* pixmapFactory)
81 : m_testCtx (testCtx)
82 , m_displayFactory (displayFactory)
83 , m_windowFactory (windowFactory)
84 , m_pixmapFactory (pixmapFactory)
85 , m_defaultNativeDisplay (DE_NULL)
86 , m_defaultEGLDisplay (DE_NULL)
87 {
88 // Temporarily allocate default display for storing config list
89 try
90 {
91 EGLDisplay eglDisplay = EGL_NO_DISPLAY;
92 EGLint majorVersion;
93 EGLint minorVersion;
94
95 m_defaultNativeDisplay = m_displayFactory.createDisplay();
96
97 eglDisplay = eglu::getDisplay(*m_defaultNativeDisplay);
98 TCU_CHECK_EGL_CALL(eglInitialize(eglDisplay, &majorVersion, &minorVersion));
99
100 m_defaultEGLDisplay = new tcu::egl::Display(eglDisplay, majorVersion, minorVersion);
101
102 // Create config list
103 {
104 vector<EGLConfig> configs;
105 set<EGLint> idSet; // For checking for duplicate config IDs
106
107 m_defaultEGLDisplay->getConfigs(configs);
108
109 m_configs.resize(configs.size());
110 for (int ndx = 0; ndx < (int)configs.size(); ndx++)
111 {
112 m_defaultEGLDisplay->describeConfig(configs[ndx], m_configs[ndx]);
113
114 EGLint id = m_configs[ndx].configId;
115 if (idSet.find(id) != idSet.end())
116 tcu::print("Warning: Duplicate config ID %d\n", id);
117 idSet.insert(id);
118 }
119 }
120
121 // Query supported APIs
122 {
123 const char* clientAPIs = eglQueryString(eglDisplay, EGL_CLIENT_APIS);
124 std::vector<std::string> apis;
125 TCU_CHECK(clientAPIs);
126
127 split(apis, clientAPIs);
128 for (std::vector<std::string>::const_iterator apiIter = apis.begin(); apiIter != apis.end(); apiIter++)
129 {
130 EGLint parsedAPI = parseAPI(*apiIter);
131 if (parsedAPI != 0)
132 m_supportedAPIs.insert(parsedAPI);
133 }
134 }
135
136 delete m_defaultEGLDisplay;
137 m_defaultEGLDisplay = DE_NULL;
138 delete m_defaultNativeDisplay;
139 m_defaultNativeDisplay = DE_NULL;
140 }
141 catch (...)
142 {
143 delete m_defaultEGLDisplay;
144 m_defaultEGLDisplay = DE_NULL;
145 delete m_defaultNativeDisplay;
146 m_defaultNativeDisplay = DE_NULL;
147 throw;
148 }
149 }
150
~EglTestContext(void)151 EglTestContext::~EglTestContext (void)
152 {
153 for (GLLibraryMap::iterator iter = m_glLibraries.begin(); iter != m_glLibraries.end(); ++iter)
154 delete iter->second;
155
156 delete m_defaultEGLDisplay;
157 delete m_defaultNativeDisplay;
158 }
159
createDefaultDisplay(void)160 void EglTestContext::createDefaultDisplay (void)
161 {
162 EGLDisplay eglDisplay = EGL_NO_DISPLAY;
163 EGLint majorVersion;
164 EGLint minorVersion;
165
166 DE_ASSERT(!m_defaultEGLDisplay);
167 DE_ASSERT(!m_defaultNativeDisplay);
168
169 try
170 {
171 m_defaultNativeDisplay = m_displayFactory.createDisplay();
172
173 eglDisplay = eglu::getDisplay(*m_defaultNativeDisplay);
174 TCU_CHECK_EGL_CALL(eglInitialize(eglDisplay, &majorVersion, &minorVersion));
175
176 m_defaultEGLDisplay = new tcu::egl::Display(eglDisplay, majorVersion, minorVersion);
177 }
178 catch (const std::exception&)
179 {
180 delete m_defaultEGLDisplay;
181 m_defaultEGLDisplay = DE_NULL;
182 delete m_defaultNativeDisplay;
183 m_defaultNativeDisplay = DE_NULL;
184 throw;
185 }
186 }
187
getNativeWindowFactory(void) const188 const eglu::NativeWindowFactory& EglTestContext::getNativeWindowFactory (void) const
189 {
190 if (m_windowFactory)
191 return *m_windowFactory;
192 else
193 throw tcu::NotSupportedError("No default native window factory available", "", __FILE__, __LINE__);
194 }
195
getNativePixmapFactory(void) const196 const eglu::NativePixmapFactory& EglTestContext::getNativePixmapFactory (void) const
197 {
198 if (m_pixmapFactory)
199 return *m_pixmapFactory;
200 else
201 throw tcu::NotSupportedError("No default native pixmap factory available", "", __FILE__, __LINE__);
202 }
203
destroyDefaultDisplay(void)204 void EglTestContext::destroyDefaultDisplay (void)
205 {
206 DE_ASSERT(m_defaultEGLDisplay);
207 DE_ASSERT(m_defaultNativeDisplay);
208
209 delete m_defaultEGLDisplay;
210 m_defaultEGLDisplay = DE_NULL;
211
212 delete m_defaultNativeDisplay;
213 m_defaultNativeDisplay = DE_NULL;
214 }
215
createNativeWindow(EGLDisplay display,EGLConfig config,const EGLAttrib * attribList,int width,int height,eglu::WindowParams::Visibility visibility)216 eglu::NativeWindow* EglTestContext::createNativeWindow (EGLDisplay display, EGLConfig config, const EGLAttrib* attribList, int width, int height, eglu::WindowParams::Visibility visibility)
217 {
218 if (!m_windowFactory)
219 throw tcu::NotSupportedError("Windows not supported", "", __FILE__, __LINE__);
220
221 return m_windowFactory->createWindow(m_defaultNativeDisplay, display, config, attribList, eglu::WindowParams(width, height, visibility));
222 }
223
createNativePixmap(EGLDisplay display,EGLConfig config,const EGLAttrib * attribList,int width,int height)224 eglu::NativePixmap* EglTestContext::createNativePixmap (EGLDisplay display, EGLConfig config, const EGLAttrib* attribList, int width, int height)
225 {
226 if (!m_pixmapFactory)
227 throw tcu::NotSupportedError("Pixmaps not supported", "", __FILE__, __LINE__);
228
229 return m_pixmapFactory->createPixmap(m_defaultNativeDisplay, display, config, attribList, width, height);
230 }
231
232 // \todo [2014-10-06 pyry] Quite hacky, expose ApiType internals?
makeKey(glu::ApiType apiType)233 static deUint32 makeKey (glu::ApiType apiType)
234 {
235 return (apiType.getMajorVersion() << 8) | (apiType.getMinorVersion() << 4) | apiType.getProfile();
236 }
237
getGLLibrary(glu::ApiType apiType) const238 const tcu::FunctionLibrary* EglTestContext::getGLLibrary (glu::ApiType apiType) const
239 {
240 tcu::FunctionLibrary* library = DE_NULL;
241 const deUint32 key = makeKey(apiType);
242 GLLibraryMap::iterator iter = m_glLibraries.find(key);
243
244 if (iter == m_glLibraries.end())
245 {
246 library = m_testCtx.getPlatform().getEGLPlatform().createDefaultGLFunctionLibrary(apiType, m_testCtx.getCommandLine());
247 m_glLibraries.insert(std::make_pair(key, library));
248 }
249 else
250 library = iter->second;
251
252 return library;
253 }
254
getGLFunction(glu::ApiType apiType,const char * name) const255 deFunctionPtr EglTestContext::getGLFunction (glu::ApiType apiType, const char* name) const
256 {
257 // \todo [2014-03-11 pyry] This requires fall-back to eglGetProcAddress(), right?
258 const tcu::FunctionLibrary* const library = getGLLibrary(apiType);
259 return library->getFunction(name);
260 }
261
getGLFunctions(glw::Functions & gl,glu::ApiType apiType) const262 void EglTestContext::getGLFunctions (glw::Functions& gl, glu::ApiType apiType) const
263 {
264 const tcu::FunctionLibrary* const library = getGLLibrary(apiType);
265 const eglu::GLFunctionLoader loader (library);
266
267 // \note There may not be current context, so we can't use initFunctions().
268 glu::initCoreFunctions(&gl, &loader, apiType);
269 }
270
TestCaseGroup(EglTestContext & eglTestCtx,const char * name,const char * description)271 TestCaseGroup::TestCaseGroup (EglTestContext& eglTestCtx, const char* name, const char* description)
272 : tcu::TestCaseGroup (eglTestCtx.getTestContext(), name, description)
273 , m_eglTestCtx (eglTestCtx)
274 {
275 }
276
~TestCaseGroup(void)277 TestCaseGroup::~TestCaseGroup (void)
278 {
279 }
280
TestCase(EglTestContext & eglTestCtx,const char * name,const char * description)281 TestCase::TestCase (EglTestContext& eglTestCtx, const char* name, const char* description)
282 : tcu::TestCase (eglTestCtx.getTestContext(), name, description)
283 , m_eglTestCtx (eglTestCtx)
284 {
285 }
286
TestCase(EglTestContext & eglTestCtx,tcu::TestNodeType type,const char * name,const char * description)287 TestCase::TestCase (EglTestContext& eglTestCtx, tcu::TestNodeType type, const char* name, const char* description)
288 : tcu::TestCase (eglTestCtx.getTestContext(), type, name, description)
289 , m_eglTestCtx (eglTestCtx)
290 {
291 }
292
~TestCase(void)293 TestCase::~TestCase (void)
294 {
295 }
296
297 } // egl
298 } // deqp
299