• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program Tester Core
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 utilities
22  *//*--------------------------------------------------------------------*/
23 
24 #include "egluUtil.hpp"
25 #include "egluDefs.hpp"
26 #include "egluNativeDisplay.hpp"
27 #include "tcuCommandLine.hpp"
28 #include "deSTLUtil.hpp"
29 
30 #include <algorithm>
31 #include <sstream>
32 
33 using std::string;
34 using std::vector;
35 
36 #if !defined(EGL_EXT_platform_base)
37 #	define EGL_EXT_platform_base 1
38 	typedef EGLDisplay (EGLAPIENTRYP PFNEGLGETPLATFORMDISPLAYEXTPROC) (EGLenum platform, void *native_display, const EGLint *attrib_list);
39 	typedef EGLSurface (EGLAPIENTRYP PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC) (EGLDisplay dpy, EGLConfig config, void *native_window, const EGLint *attrib_list);
40 	typedef EGLSurface (EGLAPIENTRYP PFNEGLCREATEPLATFORMPIXMAPSURFACEEXTPROC) (EGLDisplay dpy, EGLConfig config, void *native_pixmap, const EGLint *attrib_list);
41 #endif // EGL_EXT_platform_base
42 
43 namespace eglu
44 {
45 
getPlatformExtensions(void)46 vector<string> getPlatformExtensions (void)
47 {
48 	const char* const	extensionStr	= eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
49 	const EGLint		result			= eglGetError();
50 
51 	if (result == EGL_SUCCESS)
52 	{
53 		std::istringstream	stream			(extensionStr);
54 		string				currentExtension;
55 		vector<string>		extensions;
56 
57 		while (std::getline(stream, currentExtension, ' '))
58 			extensions.push_back(currentExtension);
59 
60 		return extensions;
61 	}
62 	else if (result != EGL_BAD_DISPLAY)
63 		throw Error(result, "eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS)", DE_NULL, __FILE__, __LINE__);
64 	else
65 		return vector<string>();
66 }
67 
getClientExtensions(EGLDisplay display)68 vector<string> getClientExtensions (EGLDisplay display)
69 {
70 	const char* const	extensionStr	= eglQueryString(display, EGL_EXTENSIONS);
71 	const EGLint		result			= eglGetError();
72 
73 	if (result == EGL_SUCCESS)
74 	{
75 		std::istringstream	stream			(extensionStr);
76 		string				currentExtension;
77 		vector<string>		extensions;
78 
79 		while (std::getline(stream, currentExtension, ' '))
80 			extensions.push_back(currentExtension);
81 
82 		return extensions;
83 	}
84 	else
85 		throw Error(result, "eglQueryString(display, EGL_EXTENSIONS)", DE_NULL, __FILE__, __LINE__);
86 }
87 
getConfigs(EGLDisplay display)88 vector<EGLConfig> getConfigs (EGLDisplay display)
89 {
90 	vector<EGLConfig>	configs;
91 	EGLint				configCount	= 0;
92 	EGLU_CHECK_CALL(eglGetConfigs(display, DE_NULL, 0, &configCount));
93 
94 	if (configCount > 0)
95 	{
96 		configs.resize(configCount);
97 		EGLU_CHECK_CALL(eglGetConfigs(display, &(configs[0]), (EGLint)configs.size(), &configCount));
98 	}
99 
100 	return configs;
101 }
102 
chooseConfig(EGLDisplay display,const AttribMap & attribs)103 vector<EGLConfig> chooseConfig (EGLDisplay display, const AttribMap& attribs)
104 {
105 	vector<EGLint> attribList;
106 
107 	for (AttribMap::const_iterator it = attribs.begin(); it != attribs.end(); ++it)
108 	{
109 		attribList.push_back(it->first);
110 		attribList.push_back(it->second);
111 	}
112 
113 	attribList.push_back(EGL_NONE);
114 
115 	{
116 		EGLint numConfigs = 0;
117 		EGLU_CHECK_CALL(eglChooseConfig(display, &attribList.front(), DE_NULL, 0, &numConfigs));
118 
119 		{
120 			vector<EGLConfig> configs(numConfigs);
121 
122 			if (numConfigs > 0)
123 				EGLU_CHECK_CALL(eglChooseConfig(display, &attribList.front(), &configs.front(), numConfigs, &numConfigs));
124 
125 			return configs;
126 		}
127 	}
128 }
129 
chooseSingleConfig(EGLDisplay display,const AttribMap & attribs)130 EGLConfig chooseSingleConfig (EGLDisplay display, const AttribMap& attribs)
131 {
132 	vector<EGLConfig> configs (chooseConfig(display, attribs));
133 	if (configs.empty())
134 		TCU_THROW(NotSupportedError, "No suitable EGL configuration found");
135 
136 	return configs.front();
137 }
138 
getConfigAttribInt(EGLDisplay display,EGLConfig config,EGLint attrib)139 EGLint getConfigAttribInt (EGLDisplay display, EGLConfig config, EGLint attrib)
140 {
141 	EGLint value = 0;
142 	EGLU_CHECK_CALL(eglGetConfigAttrib(display, config, attrib, &value));
143 	return value;
144 }
145 
querySurfaceInt(EGLDisplay display,EGLSurface surface,EGLint attrib)146 EGLint querySurfaceInt (EGLDisplay display, EGLSurface surface, EGLint attrib)
147 {
148 	EGLint value = 0;
149 	EGLU_CHECK_CALL(eglQuerySurface(display, surface, attrib, &value));
150 	return value;
151 }
152 
getSurfaceSize(EGLDisplay display,EGLSurface surface)153 tcu::IVec2 getSurfaceSize (EGLDisplay display, EGLSurface surface)
154 {
155 	const EGLint width	= querySurfaceInt(display, surface, EGL_WIDTH);
156 	const EGLint height	= querySurfaceInt(display, surface, EGL_HEIGHT);
157 	return tcu::IVec2(width, height);
158 }
159 
getSurfaceResolution(EGLDisplay display,EGLSurface surface)160 tcu::IVec2 getSurfaceResolution (EGLDisplay display, EGLSurface surface)
161 {
162 	const EGLint hRes	= querySurfaceInt(display, surface, EGL_HORIZONTAL_RESOLUTION);
163 	const EGLint vRes	= querySurfaceInt(display, surface, EGL_VERTICAL_RESOLUTION);
164 
165 	if (hRes == EGL_UNKNOWN || vRes == EGL_UNKNOWN)
166 		TCU_THROW(NotSupportedError, "Surface doesn't support pixel density queries");
167 	return tcu::IVec2(hRes, vRes);
168 }
169 
170 //! Get EGLdisplay using eglGetDisplay() or eglGetPlatformDisplayEXT()
getDisplay(NativeDisplay & nativeDisplay)171 EGLDisplay getDisplay (NativeDisplay& nativeDisplay)
172 {
173 	const bool	supportsLegacyGetDisplay		= (nativeDisplay.getCapabilities() & NativeDisplay::CAPABILITY_GET_DISPLAY_LEGACY) != 0;
174 	const bool	supportsPlatformGetDisplay		= (nativeDisplay.getCapabilities() & NativeDisplay::CAPABILITY_GET_DISPLAY_PLATFORM) != 0;
175 	bool		usePlatformExt					= false;
176 	EGLDisplay	display							= EGL_NO_DISPLAY;
177 
178 	TCU_CHECK_INTERNAL(supportsLegacyGetDisplay || supportsPlatformGetDisplay);
179 
180 	if (supportsPlatformGetDisplay)
181 	{
182 		const vector<string> platformExts = getPlatformExtensions();
183 		usePlatformExt = de::contains(platformExts.begin(), platformExts.end(), string("EGL_EXT_platform_base")) &&
184 						 de::contains(platformExts.begin(), platformExts.end(), string(nativeDisplay.getPlatformExtensionName()));
185 	}
186 
187 	if (usePlatformExt)
188 	{
189 		const PFNEGLGETPLATFORMDISPLAYEXTPROC	getPlatformDisplay	= (PFNEGLGETPLATFORMDISPLAYEXTPROC)eglGetProcAddress("eglGetPlatformDisplayEXT");
190 
191 		EGLU_CHECK_MSG("eglGetProcAddress()");
192 		TCU_CHECK(getPlatformDisplay);
193 
194 		display = getPlatformDisplay(nativeDisplay.getPlatformType(), nativeDisplay.getPlatformNative(), DE_NULL);
195 		EGLU_CHECK_MSG("eglGetPlatformDisplayEXT()");
196 		TCU_CHECK(display != EGL_NO_DISPLAY);
197 	}
198 	else if (supportsLegacyGetDisplay)
199 	{
200 		display = eglGetDisplay(nativeDisplay.getLegacyNative());
201 		EGLU_CHECK_MSG("eglGetDisplay()");
202 		TCU_CHECK(display != EGL_NO_DISPLAY);
203 	}
204 	else
205 		throw tcu::InternalError("No supported way to get EGL display", DE_NULL, __FILE__, __LINE__);
206 
207 	DE_ASSERT(display != EGL_NO_DISPLAY);
208 	return display;
209 }
210 
211 //! Create EGL window surface using eglCreateWindowSurface() or eglCreatePlatformWindowSurfaceEXT()
createWindowSurface(NativeDisplay & nativeDisplay,NativeWindow & window,EGLDisplay display,EGLConfig config,const EGLAttrib * attribList)212 EGLSurface createWindowSurface (NativeDisplay& nativeDisplay, NativeWindow& window, EGLDisplay display, EGLConfig config, const EGLAttrib* attribList)
213 {
214 	const bool	supportsLegacyCreate			= (window.getCapabilities() & NativeWindow::CAPABILITY_CREATE_SURFACE_LEGACY) != 0;
215 	const bool	supportsPlatformCreate			= (window.getCapabilities() & NativeWindow::CAPABILITY_CREATE_SURFACE_PLATFORM) != 0;
216 	bool		usePlatformExt					= false;
217 	EGLSurface	surface							= EGL_NO_SURFACE;
218 
219 	TCU_CHECK_INTERNAL(supportsLegacyCreate || supportsPlatformCreate);
220 
221 	if (supportsPlatformCreate)
222 	{
223 		const vector<string> platformExts = getPlatformExtensions();
224 		usePlatformExt = de::contains(platformExts.begin(), platformExts.end(), string("EGL_EXT_platform_base")) &&
225 						 de::contains(platformExts.begin(), platformExts.end(), string(nativeDisplay.getPlatformExtensionName()));
226 	}
227 
228 	// \todo [2014-03-13 pyry] EGL 1.5 core support
229 	if (usePlatformExt)
230 	{
231 		const PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC	createPlatformWindowSurface	= (PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC)eglGetProcAddress("eglCreatePlatformWindowSurfaceEXT");
232 		const vector<EGLint>							legacyAttribs				= toLegacyAttribList(attribList);
233 
234 		EGLU_CHECK_MSG("eglGetProcAddress()");
235 		TCU_CHECK(createPlatformWindowSurface);
236 
237 		surface = createPlatformWindowSurface(display, config, window.getPlatformNative(), &legacyAttribs[0]);
238 		EGLU_CHECK_MSG("eglCreatePlatformWindowSurfaceEXT()");
239 		TCU_CHECK(surface != EGL_NO_SURFACE);
240 	}
241 	else if (supportsLegacyCreate)
242 	{
243 		const vector<EGLint> legacyAttribs = toLegacyAttribList(attribList);
244 		surface = eglCreateWindowSurface(display, config, window.getLegacyNative(), &legacyAttribs[0]);
245 		EGLU_CHECK_MSG("eglCreateWindowSurface()");
246 		TCU_CHECK(surface != EGL_NO_SURFACE);
247 	}
248 	else
249 		throw tcu::InternalError("No supported way to create EGL window surface", DE_NULL, __FILE__, __LINE__);
250 
251 	DE_ASSERT(surface != EGL_NO_SURFACE);
252 	return surface;
253 }
254 
255 //! Create EGL pixmap surface using eglCreatePixmapSurface() or eglCreatePlatformPixmapSurfaceEXT()
createPixmapSurface(NativeDisplay & nativeDisplay,NativePixmap & pixmap,EGLDisplay display,EGLConfig config,const EGLAttrib * attribList)256 EGLSurface createPixmapSurface (NativeDisplay& nativeDisplay, NativePixmap& pixmap, EGLDisplay display, EGLConfig config, const EGLAttrib* attribList)
257 {
258 	const bool	supportsLegacyCreate			= (pixmap.getCapabilities() & NativePixmap::CAPABILITY_CREATE_SURFACE_LEGACY) != 0;
259 	const bool	supportsPlatformCreate			= (pixmap.getCapabilities() & NativePixmap::CAPABILITY_CREATE_SURFACE_PLATFORM) != 0;
260 	bool		usePlatformExt					= false;
261 	EGLSurface	surface							= EGL_NO_SURFACE;
262 
263 	TCU_CHECK_INTERNAL(supportsLegacyCreate || supportsPlatformCreate);
264 
265 	if (supportsPlatformCreate)
266 	{
267 		const vector<string> platformExts = getPlatformExtensions();
268 		usePlatformExt = de::contains(platformExts.begin(), platformExts.end(), string("EGL_EXT_platform_base")) &&
269 						 de::contains(platformExts.begin(), platformExts.end(), string(nativeDisplay.getPlatformExtensionName()));
270 	}
271 
272 	if (usePlatformExt)
273 	{
274 		const PFNEGLCREATEPLATFORMPIXMAPSURFACEEXTPROC	createPlatformPixmapSurface	= (PFNEGLCREATEPLATFORMPIXMAPSURFACEEXTPROC)eglGetProcAddress("eglCreatePlatformPixmapSurfaceEXT");
275 		const vector<EGLint>							legacyAttribs				= toLegacyAttribList(attribList);
276 
277 		EGLU_CHECK_MSG("eglGetProcAddress()");
278 		TCU_CHECK(createPlatformPixmapSurface);
279 
280 		surface = createPlatformPixmapSurface(display, config, pixmap.getPlatformNative(), &legacyAttribs[0]);
281 		EGLU_CHECK_MSG("eglCreatePlatformPixmapSurfaceEXT()");
282 		TCU_CHECK(surface != EGL_NO_SURFACE);
283 	}
284 	else if (supportsLegacyCreate)
285 	{
286 		const vector<EGLint> legacyAttribs = toLegacyAttribList(attribList);
287 		surface = eglCreatePixmapSurface(display, config, pixmap.getLegacyNative(), &legacyAttribs[0]);
288 		EGLU_CHECK_MSG("eglCreatePixmapSurface()");
289 		TCU_CHECK(surface != EGL_NO_SURFACE);
290 	}
291 	else
292 		throw tcu::InternalError("No supported way to create EGL pixmap surface", DE_NULL, __FILE__, __LINE__);
293 
294 	DE_ASSERT(surface != EGL_NO_SURFACE);
295 	return surface;
296 }
297 
getWindowVisibility(tcu::WindowVisibility visibility)298 static WindowParams::Visibility getWindowVisibility (tcu::WindowVisibility visibility)
299 {
300 	switch (visibility)
301 	{
302 		case tcu::WINDOWVISIBILITY_WINDOWED:	return WindowParams::VISIBILITY_VISIBLE;
303 		case tcu::WINDOWVISIBILITY_FULLSCREEN:	return WindowParams::VISIBILITY_FULLSCREEN;
304 		case tcu::WINDOWVISIBILITY_HIDDEN:		return WindowParams::VISIBILITY_HIDDEN;
305 
306 		default:
307 			DE_ASSERT(false);
308 			return WindowParams::VISIBILITY_DONT_CARE;
309 	}
310 }
311 
parseWindowVisibility(const tcu::CommandLine & commandLine)312 WindowParams::Visibility parseWindowVisibility (const tcu::CommandLine& commandLine)
313 {
314 	return getWindowVisibility(commandLine.getVisibility());
315 }
316 
toLegacyAttribList(const EGLAttrib * attribs)317 vector<EGLint> toLegacyAttribList (const EGLAttrib* attribs)
318 {
319 	const deUint64	attribMask		= 0xffffffffull;	//!< Max bits that can be used
320 	vector<EGLint>	legacyAttribs;
321 
322 	if (attribs)
323 	{
324 		for (const EGLAttrib* attrib = attribs; *attrib != EGL_NONE; attrib += 2)
325 		{
326 			if ((attrib[0] & ~attribMask) || (attrib[1] & ~attribMask))
327 				throw tcu::InternalError("Failed to translate EGLAttrib to EGLint", DE_NULL, __FILE__, __LINE__);
328 
329 			legacyAttribs.push_back((EGLint)attrib[0]);
330 			legacyAttribs.push_back((EGLint)attrib[1]);
331 		}
332 	}
333 
334 	legacyAttribs.push_back(EGL_NONE);
335 
336 	return legacyAttribs;
337 }
338 
339 } // eglu
340