1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program Tester Core
3 * ----------------------------------------
5 * Copyright 2014 The Android Open Source Project
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
21 * \brief EGL utilities
22 *//*--------------------------------------------------------------------*/
24 #include "egluUtil.hpp"
25 #include "egluDefs.hpp"
26 #include "egluNativeDisplay.hpp"
27 #include "egluConfigFilter.hpp"
28 #include "eglwLibrary.hpp"
29 #include "eglwEnums.hpp"
30 #include "tcuCommandLine.hpp"
31 #include "deSTLUtil.hpp"
32 #include "deStringUtil.hpp"
33 #include "glwEnums.hpp"
46 vector<EGLint> attribMapToList (const AttribMap& attribs)
48 vector<EGLint> attribList;
50 for (AttribMap::const_iterator it = attribs.begin(); it != attribs.end(); ++it)
52 attribList.push_back(it->first);
53 attribList.push_back(it->second);
56 attribList.push_back(EGL_NONE);
61 Version getVersion (const Library& egl, EGLDisplay display)
65 // eglInitialize on already initialized displays just returns the version.
66 EGLU_CHECK_CALL(egl, initialize(display, &major, &minor));
68 return Version(major, minor);
71 vector<string> getExtensions (const Library& egl, EGLDisplay display)
73 const char* const extensionStr = egl.queryString(display, EGL_EXTENSIONS);
75 EGLU_CHECK_MSG(egl, "Querying extensions failed");
77 return de::splitString(extensionStr, ' ');
80 bool hasExtension (const Library& egl, EGLDisplay display, const string& str)
82 const vector<string> extensions = getExtensions(egl, display);
83 return de::contains(extensions.begin(), extensions.end(), str);
86 vector<string> getPlatformExtensions (const Library& egl)
88 return getExtensions(egl, EGL_NO_DISPLAY);
91 vector<string> getClientExtensions (const Library& egl, EGLDisplay display)
93 DE_ASSERT(display != EGL_NO_DISPLAY);
95 return getExtensions(egl, display);
98 vector<EGLConfig> getConfigs (const Library& egl, EGLDisplay display)
100 vector<EGLConfig> configs;
101 EGLint configCount = 0;
102 EGLU_CHECK_CALL(egl, getConfigs(display, DE_NULL, 0, &configCount));
106 configs.resize(configCount);
107 EGLU_CHECK_CALL(egl, getConfigs(display, &(configs[0]), (EGLint)configs.size(), &configCount));
113 vector<EGLConfig> chooseConfigs (const Library& egl, EGLDisplay display, const EGLint* attribList)
115 EGLint numConfigs = 0;
117 EGLU_CHECK_CALL(egl, chooseConfig(display, attribList, DE_NULL, 0, &numConfigs));
120 vector<EGLConfig> configs(numConfigs);
123 EGLU_CHECK_CALL(egl, chooseConfig(display, attribList, &configs.front(), numConfigs, &numConfigs));
129 vector<EGLConfig> chooseConfigs (const Library& egl, EGLDisplay display, const FilterList& filters)
131 const vector<EGLConfig> allConfigs (getConfigs(egl, display));
132 vector<EGLConfig> matchingConfigs;
134 for (vector<EGLConfig>::const_iterator cfg = allConfigs.begin(); cfg != allConfigs.end(); ++cfg)
136 if (filters.match(egl, display, *cfg))
137 matchingConfigs.push_back(*cfg);
140 return matchingConfigs;
143 EGLConfig chooseSingleConfig (const Library& egl, EGLDisplay display, const FilterList& filters)
145 const vector<EGLConfig> allConfigs (getConfigs(egl, display));
147 for (vector<EGLConfig>::const_iterator cfg = allConfigs.begin(); cfg != allConfigs.end(); ++cfg)
149 if (filters.match(egl, display, *cfg))
153 TCU_THROW(NotSupportedError, "No matching EGL config found");
156 EGLConfig chooseSingleConfig (const Library& egl, EGLDisplay display, const EGLint* attribList)
158 const vector<EGLConfig> configs (chooseConfigs(egl, display, attribList));
160 TCU_THROW(NotSupportedError, "No matching EGL config found");
162 return configs.front();
165 vector<EGLConfig> chooseConfigs (const Library& egl, EGLDisplay display, const AttribMap& attribs)
167 const vector<EGLint> attribList = attribMapToList(attribs);
168 return chooseConfigs(egl, display, &attribList.front());
171 EGLConfig chooseSingleConfig (const Library& egl, EGLDisplay display, const AttribMap& attribs)
173 const vector<EGLint> attribList = attribMapToList(attribs);
174 return chooseSingleConfig(egl, display, &attribList.front());
177 EGLConfig chooseConfigByID (const Library& egl, EGLDisplay display, EGLint id)
181 attribs[EGL_CONFIG_ID] = id;
182 attribs[EGL_TRANSPARENT_TYPE] = EGL_DONT_CARE;
183 attribs[EGL_COLOR_BUFFER_TYPE] = EGL_DONT_CARE;
184 attribs[EGL_RENDERABLE_TYPE] = EGL_DONT_CARE;
185 attribs[EGL_SURFACE_TYPE] = EGL_DONT_CARE;
187 return chooseSingleConfig(egl, display, attribs);
190 EGLint getConfigAttribInt (const Library& egl, EGLDisplay display, EGLConfig config, EGLint attrib)
193 EGLU_CHECK_CALL(egl, getConfigAttrib(display, config, attrib, &value));
197 EGLint getConfigID (const Library& egl, EGLDisplay display, EGLConfig config)
199 return getConfigAttribInt(egl, display, config, EGL_CONFIG_ID);
202 EGLint querySurfaceInt (const Library& egl, EGLDisplay display, EGLSurface surface, EGLint attrib)
205 EGLU_CHECK_CALL(egl, querySurface(display, surface, attrib, &value));
209 tcu::IVec2 getSurfaceSize (const Library& egl, EGLDisplay display, EGLSurface surface)
211 const EGLint width = querySurfaceInt(egl, display, surface, EGL_WIDTH);
212 const EGLint height = querySurfaceInt(egl, display, surface, EGL_HEIGHT);
213 return tcu::IVec2(width, height);
216 tcu::IVec2 getSurfaceResolution (const Library& egl, EGLDisplay display, EGLSurface surface)
218 const EGLint hRes = querySurfaceInt(egl, display, surface, EGL_HORIZONTAL_RESOLUTION);
219 const EGLint vRes = querySurfaceInt(egl, display, surface, EGL_VERTICAL_RESOLUTION);
221 if (hRes == EGL_UNKNOWN || vRes == EGL_UNKNOWN)
222 TCU_THROW(NotSupportedError, "Surface doesn't support pixel density queries");
223 return tcu::IVec2(hRes, vRes);
226 //! Get EGLdisplay using eglGetDisplay() or eglGetPlatformDisplayEXT()
227 EGLDisplay getDisplay (NativeDisplay& nativeDisplay)
229 const Library& egl = nativeDisplay.getLibrary();
230 const bool supportsLegacyGetDisplay = (nativeDisplay.getCapabilities() & NativeDisplay::CAPABILITY_GET_DISPLAY_LEGACY) != 0;
231 const bool supportsPlatformGetDisplay = (nativeDisplay.getCapabilities() & NativeDisplay::CAPABILITY_GET_DISPLAY_PLATFORM) != 0;
232 bool usePlatformExt = false;
233 EGLDisplay display = EGL_NO_DISPLAY;
235 TCU_CHECK_INTERNAL(supportsLegacyGetDisplay || supportsPlatformGetDisplay);
237 if (supportsPlatformGetDisplay)
239 const vector<string> platformExts = getPlatformExtensions(egl);
240 usePlatformExt = de::contains(platformExts.begin(), platformExts.end(), string("EGL_EXT_platform_base")) &&
241 de::contains(platformExts.begin(), platformExts.end(), string(nativeDisplay.getPlatformExtensionName()));
246 const vector<EGLint> legacyAttribs = toLegacyAttribList(nativeDisplay.getPlatformAttributes());
248 display = egl.getPlatformDisplayEXT(nativeDisplay.getPlatformType(), nativeDisplay.getPlatformNative(), &legacyAttribs[0]);
249 EGLU_CHECK_MSG(egl, "eglGetPlatformDisplayEXT()");
250 TCU_CHECK(display != EGL_NO_DISPLAY);
252 else if (supportsLegacyGetDisplay)
254 display = egl.getDisplay(nativeDisplay.getLegacyNative());
255 EGLU_CHECK_MSG(egl, "eglGetDisplay()");
256 TCU_CHECK(display != EGL_NO_DISPLAY);
259 throw tcu::InternalError("No supported way to get EGL display", DE_NULL, __FILE__, __LINE__);
261 DE_ASSERT(display != EGL_NO_DISPLAY);
265 EGLDisplay getAndInitDisplay (NativeDisplay& nativeDisplay, Version* version)
267 const Library& egl = nativeDisplay.getLibrary();
268 EGLDisplay display = getDisplay(nativeDisplay);
271 EGLU_CHECK_CALL(egl, initialize(display, &major, &minor));
274 *version = Version(major, minor);
279 //! Create EGL window surface using eglCreateWindowSurface() or eglCreatePlatformWindowSurfaceEXT()
280 EGLSurface createWindowSurface (NativeDisplay& nativeDisplay, NativeWindow& window, EGLDisplay display, EGLConfig config, const EGLAttrib* attribList)
282 const Library& egl = nativeDisplay.getLibrary();
283 const bool supportsLegacyCreate = (window.getCapabilities() & NativeWindow::CAPABILITY_CREATE_SURFACE_LEGACY) != 0;
284 const bool supportsPlatformCreate = (window.getCapabilities() & NativeWindow::CAPABILITY_CREATE_SURFACE_PLATFORM) != 0;
285 bool usePlatformExt = false;
286 EGLSurface surface = EGL_NO_SURFACE;
288 TCU_CHECK_INTERNAL(supportsLegacyCreate || supportsPlatformCreate);
290 if (supportsPlatformCreate)
292 const vector<string> platformExts = getPlatformExtensions(egl);
293 usePlatformExt = de::contains(platformExts.begin(), platformExts.end(), string("EGL_EXT_platform_base")) &&
294 de::contains(platformExts.begin(), platformExts.end(), string(nativeDisplay.getPlatformExtensionName()));
297 // \todo [2014-03-13 pyry] EGL 1.5 core support
300 const vector<EGLint> legacyAttribs = toLegacyAttribList(attribList);
302 surface = egl.createPlatformWindowSurfaceEXT(display, config, window.getPlatformNative(), &legacyAttribs[0]);
303 EGLU_CHECK_MSG(egl, "eglCreatePlatformWindowSurfaceEXT()");
304 TCU_CHECK(surface != EGL_NO_SURFACE);
306 else if (supportsLegacyCreate)
308 const vector<EGLint> legacyAttribs = toLegacyAttribList(attribList);
309 surface = egl.createWindowSurface(display, config, window.getLegacyNative(), &legacyAttribs[0]);
310 EGLU_CHECK_MSG(egl, "eglCreateWindowSurface()");
311 TCU_CHECK(surface != EGL_NO_SURFACE);
314 throw tcu::InternalError("No supported way to create EGL window surface", DE_NULL, __FILE__, __LINE__);
316 DE_ASSERT(surface != EGL_NO_SURFACE);
320 //! Create EGL pixmap surface using eglCreatePixmapSurface() or eglCreatePlatformPixmapSurfaceEXT()
321 EGLSurface createPixmapSurface (NativeDisplay& nativeDisplay, NativePixmap& pixmap, EGLDisplay display, EGLConfig config, const EGLAttrib* attribList)
323 const Library& egl = nativeDisplay.getLibrary();
324 const bool supportsLegacyCreate = (pixmap.getCapabilities() & NativePixmap::CAPABILITY_CREATE_SURFACE_LEGACY) != 0;
325 const bool supportsPlatformCreate = (pixmap.getCapabilities() & NativePixmap::CAPABILITY_CREATE_SURFACE_PLATFORM) != 0;
326 bool usePlatformExt = false;
327 EGLSurface surface = EGL_NO_SURFACE;
329 TCU_CHECK_INTERNAL(supportsLegacyCreate || supportsPlatformCreate);
331 if (supportsPlatformCreate)
333 const vector<string> platformExts = getPlatformExtensions(egl);
334 usePlatformExt = de::contains(platformExts.begin(), platformExts.end(), string("EGL_EXT_platform_base")) &&
335 de::contains(platformExts.begin(), platformExts.end(), string(nativeDisplay.getPlatformExtensionName()));
340 const vector<EGLint> legacyAttribs = toLegacyAttribList(attribList);
342 surface = egl.createPlatformPixmapSurfaceEXT(display, config, pixmap.getPlatformNative(), &legacyAttribs[0]);
343 EGLU_CHECK_MSG(egl, "eglCreatePlatformPixmapSurfaceEXT()");
344 TCU_CHECK(surface != EGL_NO_SURFACE);
346 else if (supportsLegacyCreate)
348 const vector<EGLint> legacyAttribs = toLegacyAttribList(attribList);
349 surface = egl.createPixmapSurface(display, config, pixmap.getLegacyNative(), &legacyAttribs[0]);
350 EGLU_CHECK_MSG(egl, "eglCreatePixmapSurface()");
351 TCU_CHECK(surface != EGL_NO_SURFACE);
354 throw tcu::InternalError("No supported way to create EGL pixmap surface", DE_NULL, __FILE__, __LINE__);
356 DE_ASSERT(surface != EGL_NO_SURFACE);
360 static WindowParams::Visibility getWindowVisibility (tcu::WindowVisibility visibility)
364 case tcu::WINDOWVISIBILITY_WINDOWED: return WindowParams::VISIBILITY_VISIBLE;
365 case tcu::WINDOWVISIBILITY_FULLSCREEN: return WindowParams::VISIBILITY_FULLSCREEN;
366 case tcu::WINDOWVISIBILITY_HIDDEN: return WindowParams::VISIBILITY_HIDDEN;
370 return WindowParams::VISIBILITY_DONT_CARE;
374 WindowParams::Visibility parseWindowVisibility (const tcu::CommandLine& commandLine)
376 return getWindowVisibility(commandLine.getVisibility());
379 EGLenum parseClientAPI (const std::string& api)
382 return EGL_OPENGL_API;
383 else if (api == "OpenGL_ES")
384 return EGL_OPENGL_ES_API;
385 else if (api == "OpenVG")
386 return EGL_OPENVG_API;
388 throw tcu::InternalError("Unknown EGL client API '" + api + "'");
391 vector<EGLenum> parseClientAPIs (const std::string& apiList)
393 const vector<string> apiStrs = de::splitString(apiList, ' ');
394 vector<EGLenum> apis;
396 for (vector<string>::const_iterator api = apiStrs.begin(); api != apiStrs.end(); ++api)
397 apis.push_back(parseClientAPI(*api));
402 vector<EGLenum> getClientAPIs (const eglw::Library& egl, eglw::EGLDisplay display)
404 return parseClientAPIs(egl.queryString(display, EGL_CLIENT_APIS));
407 EGLint getRenderableAPIsMask (const eglw::Library& egl, eglw::EGLDisplay display)
409 const vector<EGLConfig> configs = getConfigs(egl, display);
412 for (vector<EGLConfig>::const_iterator i = configs.begin(); i != configs.end(); ++i)
413 allAPIs |= getConfigAttribInt(egl, display, *i, EGL_RENDERABLE_TYPE);
418 vector<EGLint> toLegacyAttribList (const EGLAttrib* attribs)
420 const deUint64 attribMask = 0xffffffffull; //!< Max bits that can be used
421 vector<EGLint> legacyAttribs;
425 for (const EGLAttrib* attrib = attribs; *attrib != EGL_NONE; attrib += 2)
427 if ((attrib[0] & ~attribMask) || (attrib[1] & ~attribMask))
428 throw tcu::InternalError("Failed to translate EGLAttrib to EGLint", DE_NULL, __FILE__, __LINE__);
430 legacyAttribs.push_back((EGLint)attrib[0]);
431 legacyAttribs.push_back((EGLint)attrib[1]);
435 legacyAttribs.push_back(EGL_NONE);
437 return legacyAttribs;
440 template<typename Factory>
441 static const Factory& selectFactory (const tcu::FactoryRegistry<Factory>& registry, const char* objectTypeName, const char* cmdLineArg)
445 const Factory* factory = registry.getFactoryByName(cmdLineArg);
451 tcu::print("ERROR: Unknown or unsupported EGL %s type '%s'", objectTypeName, cmdLineArg);
452 tcu::print("Available EGL %s types:\n", objectTypeName);
453 for (size_t ndx = 0; ndx < registry.getFactoryCount(); ndx++)
454 tcu::print(" %s: %s\n", registry.getFactoryByIndex(ndx)->getName(), registry.getFactoryByIndex(ndx)->getDescription());
456 TCU_THROW(NotSupportedError, (string("Unsupported or unknown EGL ") + objectTypeName + " type '" + cmdLineArg + "'").c_str());
459 else if (!registry.empty())
460 return *registry.getDefaultFactory();
462 TCU_THROW(NotSupportedError, (string("No factory supporting EGL '") + objectTypeName + "' type").c_str());
465 const NativeDisplayFactory& selectNativeDisplayFactory (const NativeDisplayFactoryRegistry& registry, const tcu::CommandLine& cmdLine)
467 return selectFactory(registry, "display", cmdLine.getEGLDisplayType());
470 const NativeWindowFactory& selectNativeWindowFactory (const NativeDisplayFactory& factory, const tcu::CommandLine& cmdLine)
472 return selectFactory(factory.getNativeWindowRegistry(), "window", cmdLine.getEGLWindowType());
475 const NativePixmapFactory& selectNativePixmapFactory (const NativeDisplayFactory& factory, const tcu::CommandLine& cmdLine)
477 return selectFactory(factory.getNativePixmapRegistry(), "pixmap", cmdLine.getEGLPixmapType());