1 // Copyright 2016 The SwiftShader Authors. All Rights Reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //    http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 // libEGL.cpp: Implements the exported EGL functions.
16 
17 #include "main.h"
18 #include "Display.h"
19 #include "Surface.hpp"
20 #include "Texture.hpp"
21 #include "Context.hpp"
22 #include "common/Image.hpp"
23 #include "common/debug.h"
24 #include "Common/Version.h"
25 
26 #if defined(__ANDROID__) && !defined(ANDROID_NDK_BUILD)
27 #include <vndk/window.h>
28 #elif defined(USE_X11)
29 #include "Main/libX11.hpp"
30 #endif
31 
32 #include <algorithm>
33 #include <vector>
34 #include <string.h>
35 
36 namespace egl
37 {
38 namespace
39 {
getDisplayLock(egl::Display * display)40 sw::RecursiveLock *getDisplayLock(egl::Display *display) {
41 	if (!display) return nullptr;
42 	return display->getLock();
43 }
44 
validateDisplay(egl::Display * display)45 bool validateDisplay(egl::Display *display)
46 {
47 	if(display == EGL_NO_DISPLAY)
48 	{
49 		return error(EGL_BAD_DISPLAY, false);
50 	}
51 
52 	if(!display->isInitialized())
53 	{
54 		return error(EGL_NOT_INITIALIZED, false);
55 	}
56 
57 	return true;
58 }
59 
validateConfig(egl::Display * display,EGLConfig config)60 bool validateConfig(egl::Display *display, EGLConfig config)
61 {
62 	if(!validateDisplay(display))
63 	{
64 		return false;
65 	}
66 
67 	if(!display->isValidConfig(config))
68 	{
69 		return error(EGL_BAD_CONFIG, false);
70 	}
71 
72 	return true;
73 }
74 
validateContext(egl::Display * display,egl::Context * context)75 bool validateContext(egl::Display *display, egl::Context *context)
76 {
77 	if(!validateDisplay(display))
78 	{
79 		return false;
80 	}
81 
82 	if(!display->isValidContext(context))
83 	{
84 		return error(EGL_BAD_CONTEXT, false);
85 	}
86 
87 	return true;
88 }
89 
validateSurface(egl::Display * display,egl::Surface * surface)90 bool validateSurface(egl::Display *display, egl::Surface *surface)
91 {
92 	if(!validateDisplay(display))
93 	{
94 		return false;
95 	}
96 
97 	if(!display->isValidSurface(surface))
98 	{
99 		return error(EGL_BAD_SURFACE, false);
100 	}
101 
102 	return true;
103 }
104 
105 // Class to facilitate conversion from EGLint to EGLAttrib lists.
106 class EGLAttribs
107 {
108 public:
EGLAttribs(const EGLint * attrib_list)109 	explicit EGLAttribs(const EGLint *attrib_list)
110 	{
111 		if(attrib_list)
112 		{
113 			while(*attrib_list != EGL_NONE)
114 			{
115 				attrib.push_back(static_cast<EGLAttrib>(*attrib_list));
116 				attrib_list++;
117 			}
118 		}
119 
120 		attrib.push_back(EGL_NONE);
121 	}
122 
operator &() const123 	const EGLAttrib *operator&() const
124 	{
125 		return &attrib[0];
126 	}
127 
128 private:
129 	std::vector<EGLAttrib> attrib;
130 };
131 }
132 
GetError(void)133 EGLint EGLAPIENTRY GetError(void)
134 {
135 	TRACE("()");
136 
137 	EGLint error = egl::getCurrentError();
138 
139 	if(error != EGL_SUCCESS)
140 	{
141 		egl::setCurrentError(EGL_SUCCESS);
142 	}
143 
144 	return error;
145 }
146 
GetDisplay(EGLNativeDisplayType display_id)147 EGLDisplay EGLAPIENTRY GetDisplay(EGLNativeDisplayType display_id)
148 {
149 	TRACE("(EGLNativeDisplayType display_id = %p)", display_id);
150 
151 	if(display_id != EGL_DEFAULT_DISPLAY)
152 	{
153 		// FIXME: Check if display_id is the default display
154 	}
155 
156     #if (defined(__linux__) || defined(__FreeBSD) || defined(__DragonFly__)) && !defined(__ANDROID__)
157 		#if defined(USE_X11)
158 		if(!libX11)
159 		#endif  // Non X11 linux is headless only
160 		{
161 			return success(HEADLESS_DISPLAY);
162 		}
163 	#endif
164 
165 	return success(PRIMARY_DISPLAY);   // We only support the default display
166 }
167 
Initialize(EGLDisplay dpy,EGLint * major,EGLint * minor)168 EGLBoolean EGLAPIENTRY Initialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
169 {
170 	TRACE("(EGLDisplay dpy = %p, EGLint *major = %p, EGLint *minor = %p)",
171 		  dpy, major, minor);
172 
173 	egl::Display *display = egl::Display::get(dpy);
174 
175 	RecursiveLockGuard lock(egl::getDisplayLock(display));
176 
177 	if(!display)
178 	{
179 		return error(EGL_BAD_DISPLAY, EGL_FALSE);
180 	}
181 
182 	if(!display->initialize())
183 	{
184 		return error(EGL_NOT_INITIALIZED, EGL_FALSE);
185 	}
186 
187 	if(major) *major = 1;
188 	if(minor) *minor = 4;
189 
190 	return success(EGL_TRUE);
191 }
192 
Terminate(EGLDisplay dpy)193 EGLBoolean EGLAPIENTRY Terminate(EGLDisplay dpy)
194 {
195 	TRACE("(EGLDisplay dpy = %p)", dpy);
196 
197 	if(dpy == EGL_NO_DISPLAY)
198 	{
199 		return error(EGL_BAD_DISPLAY, EGL_FALSE);
200 	}
201 
202 	egl::Display *display = egl::Display::get(dpy);
203 
204 	RecursiveLockGuard lock(egl::getDisplayLock(display));
205 
206 	display->terminate();
207 
208 	return success(EGL_TRUE);
209 }
210 
QueryString(EGLDisplay dpy,EGLint name)211 const char *EGLAPIENTRY QueryString(EGLDisplay dpy, EGLint name)
212 {
213 	TRACE("(EGLDisplay dpy = %p, EGLint name = %d)", dpy, name);
214 
215 	if(dpy == EGL_NO_DISPLAY && name == EGL_EXTENSIONS)
216 	{
217 		return success(
218 			"EGL_KHR_client_get_all_proc_addresses "
219 #if (defined(__linux__) || defined(__FreeBSD__) || defined(__DragonFly__)) && !defined(__ANDROID__)
220 			"EGL_KHR_platform_gbm "
221 #endif
222 #if defined(USE_X11)
223 			"EGL_KHR_platform_x11 "
224 #endif
225 			"EGL_EXT_client_extensions "
226 			"EGL_EXT_platform_base");
227 	}
228 
229 	egl::Display *display = egl::Display::get(dpy);
230 
231 	RecursiveLockGuard lock(egl::getDisplayLock(display));
232 
233 	if(!validateDisplay(display))
234 	{
235 		return nullptr;
236 	}
237 
238 	switch(name)
239 	{
240 	case EGL_CLIENT_APIS:
241 		return success("OpenGL_ES");
242 	case EGL_EXTENSIONS:
243 		return success("EGL_KHR_create_context "
244 		               "EGL_KHR_get_all_proc_addresses "
245 		               "EGL_KHR_gl_texture_2D_image "
246 		               "EGL_KHR_gl_texture_cubemap_image "
247 		               "EGL_KHR_gl_renderbuffer_image "
248 		               "EGL_KHR_fence_sync "
249 		               "EGL_KHR_image_base "
250 		               "EGL_KHR_surfaceless_context "
251 		               "EGL_ANGLE_iosurface_client_buffer "
252 		               "EGL_ANDROID_framebuffer_target "
253 		               "EGL_ANDROID_recordable");
254 	case EGL_VENDOR:
255 		return success("Google Inc.");
256 	case EGL_VERSION:
257 		return success("1.4 SwiftShader " VERSION_STRING);
258 	}
259 
260 	return error(EGL_BAD_PARAMETER, (const char*)nullptr);
261 }
262 
GetConfigs(EGLDisplay dpy,EGLConfig * configs,EGLint config_size,EGLint * num_config)263 EGLBoolean EGLAPIENTRY GetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config)
264 {
265 	TRACE("(EGLDisplay dpy = %p, EGLConfig *configs = %p, "
266 	      "EGLint config_size = %d, EGLint *num_config = %p)",
267 	      dpy, configs, config_size, num_config);
268 
269 	egl::Display *display = egl::Display::get(dpy);
270 
271 	RecursiveLockGuard lock(egl::getDisplayLock(display));
272 
273 	if(!validateDisplay(display))
274 	{
275 		return EGL_FALSE;
276 	}
277 
278 	if(!num_config)
279 	{
280 		return error(EGL_BAD_PARAMETER, EGL_FALSE);
281 	}
282 
283 	const EGLint attribList[] = {EGL_NONE};
284 
285 	if(!display->getConfigs(configs, attribList, config_size, num_config))
286 	{
287 		return error(EGL_BAD_ATTRIBUTE, EGL_FALSE);
288 	}
289 
290 	return success(EGL_TRUE);
291 }
292 
ChooseConfig(EGLDisplay dpy,const EGLint * attrib_list,EGLConfig * configs,EGLint config_size,EGLint * num_config)293 EGLBoolean EGLAPIENTRY ChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config)
294 {
295 	TRACE("(EGLDisplay dpy = %p, const EGLint *attrib_list = %p, "
296 	      "EGLConfig *configs = %p, EGLint config_size = %d, EGLint *num_config = %p)",
297 	      dpy, attrib_list, configs, config_size, num_config);
298 
299 	egl::Display *display = egl::Display::get(dpy);
300 
301 	RecursiveLockGuard lock(egl::getDisplayLock(display));
302 
303 	if(!validateDisplay(display))
304 	{
305 		return EGL_FALSE;
306 	}
307 
308 	if(!num_config)
309 	{
310 		return error(EGL_BAD_PARAMETER, EGL_FALSE);
311 	}
312 
313 	const EGLint attribList[] = {EGL_NONE};
314 
315 	if(!attrib_list)
316 	{
317 		attrib_list = attribList;
318 	}
319 
320 	if(!display->getConfigs(configs, attrib_list, config_size, num_config))
321 	{
322 		return error(EGL_BAD_ATTRIBUTE, EGL_FALSE);
323 	}
324 
325 	return success(EGL_TRUE);
326 }
327 
GetConfigAttrib(EGLDisplay dpy,EGLConfig config,EGLint attribute,EGLint * value)328 EGLBoolean EGLAPIENTRY GetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value)
329 {
330 	TRACE("(EGLDisplay dpy = %p, EGLConfig config = %p, EGLint attribute = %d, EGLint *value = %p)",
331 	      dpy, config, attribute, value);
332 
333 	egl::Display *display = egl::Display::get(dpy);
334 
335 	RecursiveLockGuard lock(egl::getDisplayLock(display));
336 
337 	if(!validateConfig(display, config))
338 	{
339 		return EGL_FALSE;
340 	}
341 
342 	if(!display->getConfigAttrib(config, attribute, value))
343 	{
344 		return error(EGL_BAD_ATTRIBUTE, EGL_FALSE);
345 	}
346 
347 	return success(EGL_TRUE);
348 }
349 
CreatePlatformWindowSurface(EGLDisplay dpy,EGLConfig config,void * native_window,const EGLAttrib * attrib_list)350 EGLSurface EGLAPIENTRY CreatePlatformWindowSurface(EGLDisplay dpy, EGLConfig config, void *native_window, const EGLAttrib *attrib_list)
351 {
352 	TRACE("(EGLDisplay dpy = %p, EGLConfig config = %p, void *native_window = %p, "
353 	      "const EGLint *attrib_list = %p)", dpy, config, native_window, attrib_list);
354 
355 	egl::Display *display = egl::Display::get(dpy);
356 
357 	RecursiveLockGuard lock(egl::getDisplayLock(display));
358 
359 	if(!validateConfig(display, config))
360 	{
361 		return EGL_NO_SURFACE;
362 	}
363 
364 	#if defined(USE_X11)
365 		native_window = (void *)(*(::Window*)native_window);
366 	#endif
367 
368 	if(!display->isValidWindow((EGLNativeWindowType)native_window))
369 	{
370 		return error(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
371 	}
372 
373 	return display->createWindowSurface((EGLNativeWindowType)native_window, config, attrib_list);
374 }
375 
CreatePlatformWindowSurfaceEXT(EGLDisplay dpy,EGLConfig config,void * native_window,const EGLint * attrib_list)376 EGLSurface EGLAPIENTRY CreatePlatformWindowSurfaceEXT(EGLDisplay dpy, EGLConfig config, void *native_window, const EGLint *attrib_list)
377 {
378 	TRACE("(EGLDisplay dpy = %p, EGLConfig config = %p, void *native_window = %p, "
379 	      "const EGLint *attrib_list = %p)", dpy, config, native_window, attrib_list);
380 
381 	EGLAttribs attribs(attrib_list);
382 	return CreatePlatformWindowSurface(dpy, config, native_window, &attribs);
383 }
384 
CreateWindowSurface(EGLDisplay dpy,EGLConfig config,EGLNativeWindowType window,const EGLint * attrib_list)385 EGLSurface EGLAPIENTRY CreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType window, const EGLint *attrib_list)
386 {
387 	TRACE("(EGLDisplay dpy = %p, EGLConfig config = %p, EGLNativeWindowType window = %p, "
388 	      "const EGLint *attrib_list = %p)", dpy, config, window, attrib_list);
389 
390 	EGLAttribs attribs(attrib_list);
391 
392 	#if defined(USE_X11)
393 		return CreatePlatformWindowSurface(dpy, config, (void*)&window, &attribs);
394 	#else
395 		return CreatePlatformWindowSurface(dpy, config, (void*)window, &attribs);
396 	#endif
397 }
398 
CreatePbufferSurface(EGLDisplay dpy,EGLConfig config,const EGLint * attrib_list)399 EGLSurface EGLAPIENTRY CreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list)
400 {
401 	TRACE("(EGLDisplay dpy = %p, EGLConfig config = %p, const EGLint *attrib_list = %p)",
402 	      dpy, config, attrib_list);
403 
404 	egl::Display *display = egl::Display::get(dpy);
405 
406 	RecursiveLockGuard lock(egl::getDisplayLock(display));
407 
408 	if(!validateConfig(display, config))
409 	{
410 		return EGL_NO_SURFACE;
411 	}
412 
413 	return display->createPBufferSurface(config, attrib_list);
414 }
415 
CreatePlatformPixmapSurface(EGLDisplay dpy,EGLConfig config,void * native_pixmap,const EGLAttrib * attrib_list)416 EGLSurface EGLAPIENTRY CreatePlatformPixmapSurface(EGLDisplay dpy, EGLConfig config, void *native_pixmap, const EGLAttrib *attrib_list)
417 {
418 	TRACE("(EGLDisplay dpy = %p, EGLConfig config = %p, void *native_pixmap = %p, "
419 	      "const EGLint *attrib_list = %p)", dpy, config, native_pixmap, attrib_list);
420 
421 	egl::Display *display = egl::Display::get(dpy);
422 
423 	RecursiveLockGuard lock(egl::getDisplayLock(display));
424 
425 	if(!validateConfig(display, config))
426 	{
427 		return EGL_NO_SURFACE;
428 	}
429 
430 	UNIMPLEMENTED();   // FIXME
431 
432 	return success(EGL_NO_SURFACE);
433 }
434 
CreatePlatformPixmapSurfaceEXT(EGLDisplay dpy,EGLConfig config,void * native_pixmap,const EGLint * attrib_list)435 EGLSurface EGLAPIENTRY CreatePlatformPixmapSurfaceEXT(EGLDisplay dpy, EGLConfig config, void *native_pixmap, const EGLint *attrib_list)
436 {
437 	TRACE("(EGLDisplay dpy = %p, EGLConfig config = %p, void *native_pixmap = %p, "
438 	      "const EGLint *attrib_list = %p)", dpy, config, native_pixmap, attrib_list);
439 
440 	EGLAttribs attribs(attrib_list);
441 	return CreatePlatformPixmapSurface(dpy, config, native_pixmap, &attribs);
442 }
443 
CreatePixmapSurface(EGLDisplay dpy,EGLConfig config,EGLNativePixmapType pixmap,const EGLint * attrib_list)444 EGLSurface EGLAPIENTRY CreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list)
445 {
446 	TRACE("(EGLDisplay dpy = %p, EGLConfig config = %p, EGLNativePixmapType pixmap = %p, "
447 	      "const EGLint *attrib_list = %p)", dpy, config, pixmap, attrib_list);
448 
449 	EGLAttribs attribs(attrib_list);
450 	return CreatePlatformPixmapSurface(dpy, config, (void*)pixmap, &attribs);
451 }
452 
DestroySurface(EGLDisplay dpy,EGLSurface surface)453 EGLBoolean EGLAPIENTRY DestroySurface(EGLDisplay dpy, EGLSurface surface)
454 {
455 	TRACE("(EGLDisplay dpy = %p, EGLSurface surface = %p)", dpy, surface);
456 
457 	egl::Display *display = egl::Display::get(dpy);
458 	egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);
459 
460 	RecursiveLockGuard lock(egl::getDisplayLock(display));
461 
462 	if(!validateSurface(display, eglSurface))
463 	{
464 		return EGL_FALSE;
465 	}
466 
467 	if(surface == EGL_NO_SURFACE)
468 	{
469 		return error(EGL_BAD_SURFACE, EGL_FALSE);
470 	}
471 
472 	display->destroySurface((egl::Surface*)surface);
473 
474 	return success(EGL_TRUE);
475 }
476 
QuerySurface(EGLDisplay dpy,EGLSurface surface,EGLint attribute,EGLint * value)477 EGLBoolean EGLAPIENTRY QuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value)
478 {
479 	TRACE("(EGLDisplay dpy = %p, EGLSurface surface = %p, EGLint attribute = %d, EGLint *value = %p)",
480 	      dpy, surface, attribute, value);
481 
482 	egl::Display *display = egl::Display::get(dpy);
483 	egl::Surface *eglSurface = (egl::Surface*)surface;
484 
485 	RecursiveLockGuard lock(egl::getDisplayLock(display));
486 
487 	if(!validateSurface(display, eglSurface))
488 	{
489 		return EGL_FALSE;
490 	}
491 
492 	if(surface == EGL_NO_SURFACE)
493 	{
494 		return error(EGL_BAD_SURFACE, EGL_FALSE);
495 	}
496 
497 	switch(attribute)
498 	{
499 	case EGL_VG_ALPHA_FORMAT:
500 		*value = EGL_VG_ALPHA_FORMAT_NONPRE;   // Default
501 		break;
502 	case EGL_VG_COLORSPACE:
503 		*value = EGL_VG_COLORSPACE_sRGB;   // Default
504 		break;
505 	case EGL_CONFIG_ID:
506 		*value = eglSurface->getConfigID();
507 		break;
508 	case EGL_HEIGHT:
509 		*value = eglSurface->getHeight();
510 		break;
511 	case EGL_HORIZONTAL_RESOLUTION:
512 		*value = EGL_UNKNOWN;
513 		break;
514 	case EGL_LARGEST_PBUFFER:
515 		if(eglSurface->isPBufferSurface())   // For a window or pixmap surface, the contents of *value are not modified.
516 		{
517 			*value = eglSurface->getLargestPBuffer();
518 		}
519 		break;
520 	case EGL_MIPMAP_TEXTURE:
521 		if(eglSurface->isPBufferSurface())   // For a window or pixmap surface, the contents of *value are not modified.
522 		{
523 			*value = EGL_FALSE;   // UNIMPLEMENTED
524 		}
525 		break;
526 	case EGL_MIPMAP_LEVEL:
527 		if(eglSurface->isPBufferSurface())   // For a window or pixmap surface, the contents of *value are not modified.
528 		{
529 			*value = eglSurface->getMipmapLevel();
530 		}
531 		break;
532 	case EGL_MULTISAMPLE_RESOLVE:
533 		*value = eglSurface->getMultisampleResolve();
534 		break;
535 	case EGL_PIXEL_ASPECT_RATIO:
536 		*value = eglSurface->getPixelAspectRatio();
537 		break;
538 	case EGL_RENDER_BUFFER:
539 		*value = eglSurface->getRenderBuffer();
540 		break;
541 	case EGL_SWAP_BEHAVIOR:
542 		*value = eglSurface->getSwapBehavior();
543 		break;
544 	case EGL_TEXTURE_FORMAT:
545 		if(eglSurface->isPBufferSurface())   // For a window or pixmap surface, the contents of *value are not modified.
546 		{
547 			*value = eglSurface->getTextureFormat();
548 		}
549 		break;
550 	case EGL_TEXTURE_TARGET:
551 		if(eglSurface->isPBufferSurface())   // For a window or pixmap surface, the contents of *value are not modified.
552 		{
553 			*value = eglSurface->getTextureTarget();
554 		}
555 		break;
556 	case EGL_VERTICAL_RESOLUTION:
557 		*value = EGL_UNKNOWN;
558 		break;
559 	case EGL_WIDTH:
560 		*value = eglSurface->getWidth();
561 		break;
562 	default:
563 		return error(EGL_BAD_ATTRIBUTE, EGL_FALSE);
564 	}
565 
566 	return success(EGL_TRUE);
567 }
568 
BindAPI(EGLenum api)569 EGLBoolean EGLAPIENTRY BindAPI(EGLenum api)
570 {
571 	TRACE("(EGLenum api = 0x%X)", api);
572 
573 	switch(api)
574 	{
575 	case EGL_OPENGL_API:
576 	case EGL_OPENVG_API:
577 		return error(EGL_BAD_PARAMETER, EGL_FALSE);   // Not supported by this implementation
578 	case EGL_OPENGL_ES_API:
579 		break;
580 	default:
581 		return error(EGL_BAD_PARAMETER, EGL_FALSE);
582 	}
583 
584 	egl::setCurrentAPI(api);
585 
586 	return success(EGL_TRUE);
587 }
588 
QueryAPI(void)589 EGLenum EGLAPIENTRY QueryAPI(void)
590 {
591 	TRACE("()");
592 
593 	EGLenum API = egl::getCurrentAPI();
594 
595 	return success(API);
596 }
597 
WaitClient(void)598 EGLBoolean EGLAPIENTRY WaitClient(void)
599 {
600 	TRACE("()");
601 
602 	// eglWaitClient is ignored if there is no current EGL rendering context for the current rendering API.
603 	egl::Context *context = egl::getCurrentContext();
604 
605 	if(context)
606 	{
607 		context->finish();
608 	}
609 
610 	return success(EGL_TRUE);
611 }
612 
ReleaseThread(void)613 EGLBoolean EGLAPIENTRY ReleaseThread(void)
614 {
615 	TRACE("()");
616 
617 	detachThread();
618 
619 	return EGL_TRUE;   // success() is not called here because it would re-allocate thread-local storage.
620 }
621 
CreatePbufferFromClientBuffer(EGLDisplay dpy,EGLenum buftype,EGLClientBuffer buffer,EGLConfig config,const EGLint * attrib_list)622 EGLSurface EGLAPIENTRY CreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list)
623 {
624 	TRACE("(EGLDisplay dpy = %p, EGLenum buftype = 0x%X, EGLClientBuffer buffer = %p, "
625 	      "EGLConfig config = %p, const EGLint *attrib_list = %p)",
626 	      dpy, buftype, buffer, config, attrib_list);
627 
628 	switch(buftype)
629 	{
630 	case EGL_IOSURFACE_ANGLE:
631 	{
632 		egl::Display *display = egl::Display::get(dpy);
633 
634 		RecursiveLockGuard lock(egl::getDisplayLock(display));
635 
636 		if(!validateConfig(display, config))
637 		{
638 			return EGL_NO_SURFACE;
639 		}
640 
641 		return display->createPBufferSurface(config, attrib_list, buffer);
642 	}
643 	case EGL_OPENVG_IMAGE:
644 		UNIMPLEMENTED();
645 		return error(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
646 	default:
647 		return error(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
648 	};
649 }
650 
SurfaceAttrib(EGLDisplay dpy,EGLSurface surface,EGLint attribute,EGLint value)651 EGLBoolean EGLAPIENTRY SurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
652 {
653 	TRACE("(EGLDisplay dpy = %p, EGLSurface surface = %p, EGLint attribute = %d, EGLint value = %d)",
654 	      dpy, surface, attribute, value);
655 
656 	egl::Display *display = egl::Display::get(dpy);
657 	egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);
658 
659 	RecursiveLockGuard lock(egl::getDisplayLock(display));
660 
661 	if(!validateSurface(display, eglSurface))
662 	{
663 		return EGL_FALSE;
664 	}
665 
666 	switch(attribute)
667 	{
668 	case EGL_MIPMAP_LEVEL:
669 		eglSurface->setMipmapLevel(value);
670 		break;
671 	case EGL_MULTISAMPLE_RESOLVE:
672 		switch(value)
673 		{
674 		case EGL_MULTISAMPLE_RESOLVE_DEFAULT:
675 			break;
676 		case EGL_MULTISAMPLE_RESOLVE_BOX:
677 			if(!(eglSurface->getSurfaceType() & EGL_MULTISAMPLE_RESOLVE_BOX_BIT))
678 			{
679 				return error(EGL_BAD_MATCH, EGL_FALSE);
680 			}
681 			break;
682 		default:
683 			return error(EGL_BAD_PARAMETER, EGL_FALSE);
684 		}
685 		eglSurface->setMultisampleResolve(value);
686 		break;
687 	case EGL_SWAP_BEHAVIOR:
688 		switch(value)
689 		{
690 		case EGL_BUFFER_DESTROYED:
691 			break;
692 		case EGL_BUFFER_PRESERVED:
693 			if(!(eglSurface->getSurfaceType() & EGL_SWAP_BEHAVIOR_PRESERVED_BIT))
694 			{
695 				return error(EGL_BAD_MATCH, EGL_FALSE);
696 			}
697 			break;
698 		default:
699 			return error(EGL_BAD_PARAMETER, EGL_FALSE);
700 		}
701 		eglSurface->setSwapBehavior(value);
702 		break;
703 	default:
704 		return error(EGL_BAD_PARAMETER, EGL_FALSE);
705 	}
706 
707 	return success(EGL_TRUE);
708 }
709 
BindTexImage(EGLDisplay dpy,EGLSurface surface,EGLint buffer)710 EGLBoolean EGLAPIENTRY BindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
711 {
712 	TRACE("(EGLDisplay dpy = %p, EGLSurface surface = %p, EGLint buffer = %d)", dpy, surface, buffer);
713 
714 	egl::Display *display = egl::Display::get(dpy);
715 	egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);
716 
717 	RecursiveLockGuard lock(egl::getDisplayLock(display));
718 
719 	if(!validateSurface(display, eglSurface))
720 	{
721 		return EGL_FALSE;
722 	}
723 
724 	if(buffer != EGL_BACK_BUFFER)
725 	{
726 		return error(EGL_BAD_PARAMETER, EGL_FALSE);
727 	}
728 
729 	if(surface == EGL_NO_SURFACE || eglSurface->isWindowSurface())
730 	{
731 		return error(EGL_BAD_SURFACE, EGL_FALSE);
732 	}
733 
734 	if(eglSurface->getBoundTexture())
735 	{
736 		return error(EGL_BAD_ACCESS, EGL_FALSE);
737 	}
738 
739 	if(eglSurface->getTextureFormat() == EGL_NO_TEXTURE)
740 	{
741 		return error(EGL_BAD_MATCH, EGL_FALSE);
742 	}
743 
744 	egl::Context *context = egl::getCurrentContext();
745 
746 	if(context)
747 	{
748 		context->bindTexImage(eglSurface);
749 	}
750 
751 	return success(EGL_TRUE);
752 }
753 
ReleaseTexImage(EGLDisplay dpy,EGLSurface surface,EGLint buffer)754 EGLBoolean EGLAPIENTRY ReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
755 {
756 	TRACE("(EGLDisplay dpy = %p, EGLSurface surface = %p, EGLint buffer = %d)", dpy, surface, buffer);
757 
758 	egl::Display *display = egl::Display::get(dpy);
759 	egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);
760 
761 	RecursiveLockGuard lock(egl::getDisplayLock(display));
762 
763 	if(!validateSurface(display, eglSurface))
764 	{
765 		return EGL_FALSE;
766 	}
767 
768 	if(buffer != EGL_BACK_BUFFER)
769 	{
770 		return error(EGL_BAD_PARAMETER, EGL_FALSE);
771 	}
772 
773 	if(surface == EGL_NO_SURFACE || eglSurface->isWindowSurface())
774 	{
775 		return error(EGL_BAD_SURFACE, EGL_FALSE);
776 	}
777 
778 	if(eglSurface->getTextureFormat() == EGL_NO_TEXTURE)
779 	{
780 		return error(EGL_BAD_MATCH, EGL_FALSE);
781 	}
782 
783 	egl::Texture *texture = eglSurface->getBoundTexture();
784 
785 	if(texture)
786 	{
787 		texture->releaseTexImage();
788 	}
789 
790 	return success(EGL_TRUE);
791 }
792 
SwapInterval(EGLDisplay dpy,EGLint interval)793 EGLBoolean EGLAPIENTRY SwapInterval(EGLDisplay dpy, EGLint interval)
794 {
795 	TRACE("(EGLDisplay dpy = %p, EGLint interval = %d)", dpy, interval);
796 
797 	egl::Display *display = egl::Display::get(dpy);
798 	egl::Context *context = egl::getCurrentContext();
799 
800 	RecursiveLockGuard lock(egl::getDisplayLock(display));
801 
802 	if(!validateContext(display, context))
803 	{
804 		return EGL_FALSE;
805 	}
806 
807 	egl::Surface *draw_surface = static_cast<egl::Surface*>(egl::getCurrentDrawSurface());
808 
809 	if(!draw_surface)
810 	{
811 		return error(EGL_BAD_SURFACE, EGL_FALSE);
812 	}
813 
814 	draw_surface->setSwapInterval(interval);
815 
816 	return success(EGL_TRUE);
817 }
818 
CreateContext(EGLDisplay dpy,EGLConfig config,EGLContext share_context,const EGLint * attrib_list)819 EGLContext EGLAPIENTRY CreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list)
820 {
821 	TRACE("(EGLDisplay dpy = %p, EGLConfig config = %p, EGLContext share_context = %p, "
822 	      "const EGLint *attrib_list = %p)", dpy, config, share_context, attrib_list);
823 
824 	EGLint majorVersion = 1;
825 	EGLint minorVersion = 0;
826 
827 	if(attrib_list)
828 	{
829 		for(const EGLint* attribute = attrib_list; attribute[0] != EGL_NONE; attribute += 2)
830 		{
831 			switch(attribute[0])
832 			{
833 			case EGL_CONTEXT_MAJOR_VERSION_KHR:   // This token is an alias for EGL_CONTEXT_CLIENT_VERSION
834 				majorVersion = attribute[1];
835 				break;
836 			case EGL_CONTEXT_MINOR_VERSION_KHR:
837 				minorVersion = attribute[1];
838 				break;
839 			case EGL_CONTEXT_FLAGS_KHR:
840 				switch(attribute[1])
841 				{
842 				case EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR:
843 					// According to the EGL_KHR_create_context spec:
844 					// "Khronos is still defining the expected and required features of debug contexts, so
845 					//  implementations are currently free to implement "debug contexts" with little or no debug
846 					//  functionality. However, OpenGL and OpenGL ES implementations supporting the GL_KHR_debug
847 					//  extension should enable it when this bit is set."
848 					break;
849 				case EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR:
850 				case EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR:
851 					// These bits are for OpenGL contexts only, not OpenGL ES contexts
852 					return error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
853 				default:
854 					return error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
855 				}
856 				break;
857 			case EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR:
858 				switch(attribute[1])
859 				{
860 				case EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR:
861 				case EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR:
862 					// These bits are for OpenGL contexts only, not OpenGL ES contexts
863 					return error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
864 				default:
865 					return error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
866 				}
867 				break;
868 			case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR:
869 				switch(attribute[1])
870 				{
871 				case EGL_NO_RESET_NOTIFICATION_KHR:
872 				case EGL_LOSE_CONTEXT_ON_RESET_KHR:
873 					// These bits are for OpenGL contexts only, not OpenGL ES contexts
874 					return error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
875 				default:
876 					return error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
877 				}
878 				break;
879 			default:
880 				return error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
881 			}
882 		}
883 	}
884 
885 	switch(majorVersion)
886 	{
887 	case 1:
888 		if(minorVersion != 0 && minorVersion != 1)
889 		{
890 			// 1.X: Only OpenGL ES 1.0 and 1.1 contexts are supported
891 			return error(EGL_BAD_MATCH, EGL_NO_CONTEXT);
892 		}
893 		break;
894 	case 2:
895 	case 3:
896 		if(minorVersion != 0)
897 		{
898 			// 2.X and 3.X: Only OpenGL ES 2.0 and 3.0 contexts are currently supported
899 			return error(EGL_BAD_MATCH, EGL_NO_CONTEXT);
900 		}
901 		break;
902 	default:
903 		return error(EGL_BAD_MATCH, EGL_NO_CONTEXT);
904 	}
905 
906 	egl::Display *display = egl::Display::get(dpy);
907 	egl::Context *shareContext = static_cast<egl::Context*>(share_context);
908 
909 	RecursiveLockGuard lock(egl::getDisplayLock(display));
910 
911 	if(!validateConfig(display, config))
912 	{
913 		return EGL_NO_CONTEXT;
914 	}
915 
916 	// Allow sharing between different context versions >= 2.0, but isolate 1.x
917 	// contexts from 2.0+. Strict matching between context versions >= 2.0 is
918 	// confusing for apps to navigate because of version promotion.
919 	if(shareContext && ((shareContext->getClientVersion() >= 2) ^ (majorVersion >= 2)))
920 	{
921 		return error(EGL_BAD_CONTEXT, EGL_NO_CONTEXT);
922 	}
923 
924 	return display->createContext(config, shareContext, majorVersion);
925 }
926 
DestroyContext(EGLDisplay dpy,EGLContext ctx)927 EGLBoolean EGLAPIENTRY DestroyContext(EGLDisplay dpy, EGLContext ctx)
928 {
929 	TRACE("(EGLDisplay dpy = %p, EGLContext ctx = %p)", dpy, ctx);
930 
931 	egl::Display *display = egl::Display::get(dpy);
932 	egl::Context *context = static_cast<egl::Context*>(ctx);
933 
934 	RecursiveLockGuard lock(egl::getDisplayLock(display));
935 
936 	if(!validateContext(display, context))
937 	{
938 		return EGL_FALSE;
939 	}
940 
941 	if(ctx == EGL_NO_CONTEXT)
942 	{
943 		return error(EGL_BAD_CONTEXT, EGL_FALSE);
944 	}
945 
946 	display->destroyContext(context);
947 
948 	return success(EGL_TRUE);
949 }
950 
MakeCurrent(EGLDisplay dpy,EGLSurface draw,EGLSurface read,EGLContext ctx)951 EGLBoolean EGLAPIENTRY MakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx)
952 {
953 	TRACE("(EGLDisplay dpy = %p, EGLSurface draw = %p, EGLSurface read = %p, EGLContext ctx = %p)",
954 	      dpy, draw, read, ctx);
955 
956 	egl::Display *display = egl::Display::get(dpy);
957 	egl::Context *context = static_cast<egl::Context*>(ctx);
958 	egl::Surface *drawSurface = static_cast<egl::Surface*>(draw);
959 	egl::Surface *readSurface = static_cast<egl::Surface*>(read);
960 
961 	RecursiveLockGuard lock(egl::getDisplayLock(display));
962 
963 	if(ctx != EGL_NO_CONTEXT || draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE)
964 	{
965 		if(!validateDisplay(display))
966 		{
967 			return EGL_FALSE;
968 		}
969 	}
970 
971 	if(ctx == EGL_NO_CONTEXT && (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE))
972 	{
973 		return error(EGL_BAD_MATCH, EGL_FALSE);
974 	}
975 
976 	if(ctx != EGL_NO_CONTEXT && !validateContext(display, context))
977 	{
978 		return EGL_FALSE;
979 	}
980 
981 	if((draw != EGL_NO_SURFACE && !validateSurface(display, drawSurface)) ||
982 	   (read != EGL_NO_SURFACE && !validateSurface(display, readSurface)))
983 	{
984 		return EGL_FALSE;
985 	}
986 
987 	if((draw != EGL_NO_SURFACE) ^ (read != EGL_NO_SURFACE))
988 	{
989 		return error(EGL_BAD_MATCH, EGL_FALSE);
990 	}
991 
992 	if(draw != read)
993 	{
994 		UNIMPLEMENTED();   // FIXME
995 	}
996 
997 	egl::setCurrentDrawSurface(drawSurface);
998 	egl::setCurrentReadSurface(readSurface);
999 	egl::setCurrentContext(context);
1000 
1001 	if(context)
1002 	{
1003 		context->makeCurrent(drawSurface);
1004 	}
1005 
1006 	return success(EGL_TRUE);
1007 }
1008 
GetCurrentContext(void)1009 EGLContext EGLAPIENTRY GetCurrentContext(void)
1010 {
1011 	TRACE("()");
1012 
1013 	EGLContext context = egl::getCurrentContext();
1014 
1015 	return success(context);
1016 }
1017 
GetCurrentSurface(EGLint readdraw)1018 EGLSurface EGLAPIENTRY GetCurrentSurface(EGLint readdraw)
1019 {
1020 	TRACE("(EGLint readdraw = %d)", readdraw);
1021 
1022 	if(readdraw == EGL_READ)
1023 	{
1024 		EGLSurface read = egl::getCurrentReadSurface();
1025 		return success(read);
1026 	}
1027 	else if(readdraw == EGL_DRAW)
1028 	{
1029 		EGLSurface draw = egl::getCurrentDrawSurface();
1030 		return success(draw);
1031 	}
1032 	else
1033 	{
1034 		return error(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
1035 	}
1036 }
1037 
GetCurrentDisplay(void)1038 EGLDisplay EGLAPIENTRY GetCurrentDisplay(void)
1039 {
1040 	TRACE("()");
1041 
1042 	egl::Context *context = egl::getCurrentContext();
1043 
1044 	if(!context)
1045 	{
1046 		return success(EGL_NO_DISPLAY);
1047 	}
1048 
1049 	egl::Display *display = context->getDisplay();
1050 
1051 	if(!display)
1052 	{
1053 		return error(EGL_BAD_ACCESS, EGL_NO_DISPLAY);
1054 	}
1055 
1056 	return success(display->getEGLDisplay());
1057 }
1058 
QueryContext(EGLDisplay dpy,EGLContext ctx,EGLint attribute,EGLint * value)1059 EGLBoolean EGLAPIENTRY QueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value)
1060 {
1061 	TRACE("(EGLDisplay dpy = %p, EGLContext ctx = %p, EGLint attribute = %d, EGLint *value = %p)",
1062 	      dpy, ctx, attribute, value);
1063 
1064 	egl::Display *display = egl::Display::get(dpy);
1065 	egl::Context *context = static_cast<egl::Context*>(ctx);
1066 
1067 	RecursiveLockGuard lock(egl::getDisplayLock(display));
1068 
1069 	if(!validateContext(display, context))
1070 	{
1071 		return EGL_FALSE;
1072 	}
1073 
1074 	switch(attribute)
1075 	{
1076 	case EGL_CONFIG_ID:
1077 		*value = context->getConfigID();
1078 		break;
1079 	case EGL_CONTEXT_CLIENT_TYPE:
1080 		*value = egl::getCurrentAPI();
1081 		break;
1082 	case EGL_CONTEXT_CLIENT_VERSION:
1083 		*value = context->getClientVersion();
1084 		break;
1085 	case EGL_RENDER_BUFFER:
1086 		*value = EGL_BACK_BUFFER;
1087 		break;
1088 	default:
1089 		return error(EGL_BAD_ATTRIBUTE, EGL_FALSE);
1090 	}
1091 
1092 	return success(EGL_TRUE);
1093 }
1094 
WaitGL(void)1095 EGLBoolean EGLAPIENTRY WaitGL(void)
1096 {
1097 	TRACE("()");
1098 
1099 	// glWaitGL is ignored if there is no current EGL rendering context for OpenGL ES.
1100 	egl::Context *context = egl::getCurrentContext();
1101 
1102 	if(context)
1103 	{
1104 		context->finish();
1105 	}
1106 
1107 	return success(EGL_TRUE);
1108 }
1109 
WaitNative(EGLint engine)1110 EGLBoolean EGLAPIENTRY WaitNative(EGLint engine)
1111 {
1112 	TRACE("(EGLint engine = %d)", engine);
1113 
1114 	if(engine != EGL_CORE_NATIVE_ENGINE)
1115 	{
1116 		return error(EGL_BAD_PARAMETER, EGL_FALSE);
1117 	}
1118 
1119 	// eglWaitNative is ignored if there is no current EGL rendering context.
1120 	egl::Context *context = egl::getCurrentContext();
1121 
1122 	if(context)
1123 	{
1124 		#if defined(USE_X11)
1125 			egl::Display *display = context->getDisplay();
1126 
1127 			if(!display)
1128 			{
1129 				return error(EGL_BAD_DISPLAY, EGL_FALSE);
1130 			}
1131 
1132 			libX11->XSync((::Display*)display->getNativeDisplay(), False);
1133 		#else
1134 			UNIMPLEMENTED();
1135 		#endif
1136 	}
1137 
1138 	return success(EGL_TRUE);
1139 }
1140 
SwapBuffers(EGLDisplay dpy,EGLSurface surface)1141 EGLBoolean EGLAPIENTRY SwapBuffers(EGLDisplay dpy, EGLSurface surface)
1142 {
1143 	TRACE("(EGLDisplay dpy = %p, EGLSurface surface = %p)", dpy, surface);
1144 
1145 	egl::Display *display = egl::Display::get(dpy);
1146 	egl::Surface *eglSurface = (egl::Surface*)surface;
1147 
1148 	{
1149 		RecursiveLockGuard lock(egl::getDisplayLock(display));
1150 
1151 		if(!validateSurface(display, eglSurface))
1152 		{
1153 			return EGL_FALSE;
1154 		}
1155 	}
1156 
1157 	if(surface == EGL_NO_SURFACE)
1158 	{
1159 		return error(EGL_BAD_SURFACE, EGL_FALSE);
1160 	}
1161 
1162 	eglSurface->swap();
1163 
1164 	return success(EGL_TRUE);
1165 }
1166 
CopyBuffers(EGLDisplay dpy,EGLSurface surface,EGLNativePixmapType target)1167 EGLBoolean EGLAPIENTRY CopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target)
1168 {
1169 	TRACE("(EGLDisplay dpy = %p, EGLSurface surface = %p, EGLNativePixmapType target = %p)", dpy, surface, target);
1170 
1171 	egl::Display *display = egl::Display::get(dpy);
1172 	egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);
1173 
1174 	RecursiveLockGuard lock(egl::getDisplayLock(display));
1175 
1176 	if(!validateSurface(display, eglSurface))
1177 	{
1178 		return EGL_FALSE;
1179 	}
1180 
1181 	UNIMPLEMENTED();   // FIXME
1182 
1183 	return success(EGL_FALSE);
1184 }
1185 
CreateImage(EGLDisplay dpy,EGLContext ctx,EGLenum target,EGLClientBuffer buffer,const EGLAttrib * attrib_list)1186 EGLImage EGLAPIENTRY CreateImage(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLAttrib *attrib_list)
1187 {
1188 	TRACE("(EGLDisplay dpy = %p, EGLContext ctx = %p, EGLenum target = 0x%X, buffer = %p, const EGLAttrib *attrib_list = %p)", dpy, ctx, target, buffer, attrib_list);
1189 
1190 	egl::Display *display = egl::Display::get(dpy);
1191 	egl::Context *context = static_cast<egl::Context*>(ctx);
1192 
1193 	RecursiveLockGuard lock(egl::getDisplayLock(display));
1194 
1195 	if(!validateDisplay(display))
1196 	{
1197 		return error(EGL_BAD_DISPLAY, EGL_NO_IMAGE_KHR);
1198 	}
1199 
1200 	if(context != EGL_NO_CONTEXT && !display->isValidContext(context))
1201 	{
1202 		return error(EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR);
1203 	}
1204 
1205 	EGLenum imagePreserved = EGL_FALSE;
1206 	(void)imagePreserved; // currently unused
1207 
1208 	GLuint textureLevel = 0;
1209 	if(attrib_list)
1210 	{
1211 		for(const EGLAttrib *attribute = attrib_list; attribute[0] != EGL_NONE; attribute += 2)
1212 		{
1213 			if(attribute[0] == EGL_IMAGE_PRESERVED_KHR)
1214 			{
1215 				imagePreserved = static_cast<EGLenum>(attribute[1]);
1216 			}
1217 			else if(attribute[0] == EGL_GL_TEXTURE_LEVEL_KHR)
1218 			{
1219 				textureLevel = static_cast<GLuint>(attribute[1]);
1220 			}
1221 			else
1222 			{
1223 				return error(EGL_BAD_ATTRIBUTE, EGL_NO_IMAGE_KHR);
1224 			}
1225 		}
1226 	}
1227 
1228 	#if defined(__ANDROID__) && !defined(ANDROID_NDK_BUILD)
1229 		if(target == EGL_NATIVE_BUFFER_ANDROID)
1230 		{
1231 			ANativeWindowBuffer *nativeBuffer = reinterpret_cast<ANativeWindowBuffer*>(buffer);
1232 
1233 			if(!nativeBuffer || GLPixelFormatFromAndroid(nativeBuffer->format) == GL_NONE)
1234 			{
1235 				ERR("%s badness unsupported HAL format=%x", __FUNCTION__, nativeBuffer ? nativeBuffer->format : 0);
1236 				return error(EGL_BAD_ATTRIBUTE, EGL_NO_IMAGE_KHR);
1237 			}
1238 
1239 			Image *image = new AndroidNativeImage(nativeBuffer);
1240 			EGLImageKHR eglImage = display->createSharedImage(image);
1241 
1242 			return success(eglImage);
1243 		}
1244 	#endif
1245 
1246 	GLuint name = static_cast<GLuint>(reinterpret_cast<uintptr_t>(buffer));
1247 
1248 	if(name == 0)
1249 	{
1250 		return error(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
1251 	}
1252 
1253 	EGLenum validationResult = context->validateSharedImage(target, name, textureLevel);
1254 
1255 	if(validationResult != EGL_SUCCESS)
1256 	{
1257 		return error(validationResult, EGL_NO_IMAGE_KHR);
1258 	}
1259 
1260 	Image *image = context->createSharedImage(target, name, textureLevel);
1261 
1262 	if(!image)
1263 	{
1264 		return error(EGL_BAD_MATCH, EGL_NO_IMAGE_KHR);
1265 	}
1266 
1267 	if(image->getDepth() > 1)
1268 	{
1269 		return error(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
1270 	}
1271 
1272 	EGLImage eglImage = display->createSharedImage(image);
1273 
1274 	return success(eglImage);
1275 }
1276 
CreateImageKHR(EGLDisplay dpy,EGLContext ctx,EGLenum target,EGLClientBuffer buffer,const EGLint * attrib_list)1277 EGLImageKHR EGLAPIENTRY CreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list)
1278 {
1279 	TRACE("(EGLDisplay dpy = %p, EGLContext ctx = %p, EGLenum target = 0x%X, buffer = %p, const EGLint attrib_list = %p)", dpy, ctx, target, buffer, attrib_list);
1280 
1281 	EGLAttribs attribs(attrib_list);
1282 	return CreateImage(dpy, ctx, target, buffer, &attribs);
1283 }
1284 
DestroyImageKHR(EGLDisplay dpy,EGLImageKHR image)1285 EGLBoolean EGLAPIENTRY DestroyImageKHR(EGLDisplay dpy, EGLImageKHR image)
1286 {
1287 	TRACE("(EGLDisplay dpy = %p, EGLImageKHR image = %p)", dpy, image);
1288 
1289 	egl::Display *display = egl::Display::get(dpy);
1290 
1291 	RecursiveLockGuard lock(egl::getDisplayLock(display));
1292 
1293 	if(!validateDisplay(display))
1294 	{
1295 		return error(EGL_BAD_DISPLAY, EGL_FALSE);
1296 	}
1297 
1298 	if(!display->destroySharedImage(image))
1299 	{
1300 		return error(EGL_BAD_PARAMETER, EGL_FALSE);
1301 	}
1302 
1303 	return success(EGL_TRUE);
1304 }
1305 
GetPlatformDisplay(EGLenum platform,void * native_display,const EGLAttrib * attrib_list)1306 EGLDisplay EGLAPIENTRY GetPlatformDisplay(EGLenum platform, void *native_display, const EGLAttrib *attrib_list)
1307 {
1308 	TRACE("(EGLenum platform = 0x%X, void *native_display = %p, const EGLAttrib *attrib_list = %p)", platform, native_display, attrib_list);
1309 
1310 #if (defined(__linux__) || defined(__FreeBSD__) || defined(__DragonFly__)) && !defined(__ANDROID__)
1311 		switch(platform)
1312 		{
1313 		#if defined(USE_X11)
1314 		case EGL_PLATFORM_X11_EXT: break;
1315 		#endif
1316 		case EGL_PLATFORM_GBM_KHR: break;
1317 		default:
1318 			return error(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
1319 		}
1320 
1321 		if(platform == EGL_PLATFORM_GBM_KHR)
1322 		{
1323 			if(native_display != (void*)EGL_DEFAULT_DISPLAY)
1324 			{
1325 				return error(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);   // Unimplemented
1326 			}
1327 
1328 			if(attrib_list && attrib_list[0] != EGL_NONE)
1329 			{
1330 				return error(EGL_BAD_ATTRIBUTE, EGL_NO_DISPLAY);   // Unimplemented
1331 			}
1332 
1333 			return success(HEADLESS_DISPLAY);
1334 		}
1335 		#if defined(USE_X11)
1336 		else if(platform == EGL_PLATFORM_X11_EXT)
1337 		{
1338 			if(!libX11)
1339 			{
1340 				return error(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
1341 			}
1342 
1343 			if(native_display != (void*)EGL_DEFAULT_DISPLAY)
1344 			{
1345 				return error(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);   // Unimplemented
1346 			}
1347 
1348 			if(attrib_list && attrib_list[0] != EGL_NONE)
1349 			{
1350 				return error(EGL_BAD_ATTRIBUTE, EGL_NO_DISPLAY);   // Unimplemented
1351 			}
1352 		}
1353 		#endif
1354 
1355 		return success(PRIMARY_DISPLAY);   // We only support the default display
1356 	#else
1357 		return error(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
1358 	#endif
1359 }
1360 
GetPlatformDisplayEXT(EGLenum platform,void * native_display,const EGLint * attrib_list)1361 EGLDisplay EGLAPIENTRY GetPlatformDisplayEXT(EGLenum platform, void *native_display, const EGLint *attrib_list)
1362 {
1363 	TRACE("(EGLenum platform = 0x%X, void *native_display = %p, const EGLint *attrib_list = %p)", platform, native_display, attrib_list);
1364 
1365 	EGLAttribs attribs(attrib_list);
1366 	return GetPlatformDisplay(platform, native_display, &attribs);
1367 }
1368 
CreateSync(EGLDisplay dpy,EGLenum type,const EGLAttrib * attrib_list)1369 EGLSync EGLAPIENTRY CreateSync(EGLDisplay dpy, EGLenum type, const EGLAttrib *attrib_list)
1370 {
1371 	TRACE("(EGLDisplay dpy = %p, EGLunum type = %x, EGLAttrib *attrib_list=%p)", dpy, type, attrib_list);
1372 
1373 	egl::Display *display = egl::Display::get(dpy);
1374 
1375 	RecursiveLockGuard lock(egl::getDisplayLock(display));
1376 
1377 	if(!validateDisplay(display))
1378 	{
1379 		return error(EGL_BAD_DISPLAY, EGL_NO_SYNC_KHR);
1380 	}
1381 
1382 	if(type != EGL_SYNC_FENCE_KHR)
1383 	{
1384 		return error(EGL_BAD_ATTRIBUTE, EGL_NO_SYNC_KHR);
1385 	}
1386 
1387 	if(attrib_list && attrib_list[0] != EGL_NONE)
1388 	{
1389 		return error(EGL_BAD_ATTRIBUTE, EGL_NO_SYNC_KHR);
1390 	}
1391 
1392 	egl::Context *context = egl::getCurrentContext();
1393 
1394 	if(!validateContext(display, context))
1395 	{
1396 		return error(EGL_BAD_MATCH, EGL_NO_SYNC_KHR);
1397 	}
1398 
1399 	EGLSyncKHR sync = display->createSync(context);
1400 
1401 	return success(sync);
1402 }
1403 
CreateSyncKHR(EGLDisplay dpy,EGLenum type,const EGLint * attrib_list)1404 EGLSyncKHR EGLAPIENTRY CreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list)
1405 {
1406 	TRACE("(EGLDisplay dpy = %p, EGLunum type = %x, EGLint *attrib_list=%p)", dpy, type, attrib_list);
1407 
1408 	EGLAttribs attribs(attrib_list);
1409 	return CreateSync(dpy, type, &attribs);
1410 }
1411 
DestroySyncKHR(EGLDisplay dpy,EGLSyncKHR sync)1412 EGLBoolean EGLAPIENTRY DestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync)
1413 {
1414 	TRACE("(EGLDisplay dpy = %p, EGLSyncKHR sync = %p)", dpy, sync);
1415 
1416 	egl::Display *display = egl::Display::get(dpy);
1417 	FenceSync *eglSync = static_cast<FenceSync*>(sync);
1418 
1419 	RecursiveLockGuard lock(egl::getDisplayLock(display));
1420 
1421 	if(!validateDisplay(display))
1422 	{
1423 		return error(EGL_BAD_DISPLAY, EGL_FALSE);
1424 	}
1425 
1426 	if(!display->isValidSync(eglSync))
1427 	{
1428 		return error(EGL_BAD_PARAMETER, EGL_FALSE);
1429 	}
1430 
1431 	display->destroySync(eglSync);
1432 
1433 	return success(EGL_TRUE);
1434 }
1435 
ClientWaitSyncKHR(EGLDisplay dpy,EGLSyncKHR sync,EGLint flags,EGLTimeKHR timeout)1436 EGLint EGLAPIENTRY ClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout)
1437 {
1438 	TRACE("(EGLDisplay dpy = %p, EGLSyncKHR sync = %p, EGLint flags = %x, EGLTimeKHR value = %llx)", dpy, sync, flags, timeout);
1439 
1440 	egl::Display *display = egl::Display::get(dpy);
1441 	FenceSync *eglSync = static_cast<FenceSync*>(sync);
1442 
1443 	RecursiveLockGuard lock(egl::getDisplayLock(display));
1444 
1445 	if(!validateDisplay(display))
1446 	{
1447 		return error(EGL_BAD_DISPLAY, EGL_FALSE);
1448 	}
1449 
1450 	if(!display->isValidSync(eglSync))
1451 	{
1452 		return error(EGL_BAD_PARAMETER, EGL_FALSE);
1453 	}
1454 
1455 	(void)flags;
1456 	(void)timeout;
1457 
1458 	if(!eglSync->isSignaled())
1459 	{
1460 		eglSync->wait();
1461 	}
1462 
1463 	return success(EGL_CONDITION_SATISFIED_KHR);
1464 }
1465 
GetSyncAttrib(EGLDisplay dpy,EGLSyncKHR sync,EGLint attribute,EGLAttrib * value)1466 EGLBoolean EGLAPIENTRY GetSyncAttrib(EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLAttrib *value)
1467 {
1468 	TRACE("(EGLDisplay dpy = %p, EGLSyncKHR sync = %p, EGLint attribute = %x, EGLAttrib *value = %p)", dpy, sync, attribute, value);
1469 
1470 	egl::Display *display = egl::Display::get(dpy);
1471 	FenceSync *eglSync = static_cast<FenceSync*>(sync);
1472 
1473 	RecursiveLockGuard lock(egl::getDisplayLock(display));
1474 
1475 	if(!validateDisplay(display))
1476 	{
1477 		return error(EGL_BAD_DISPLAY, EGL_FALSE);
1478 	}
1479 
1480 	if(!display->isValidSync(eglSync))
1481 	{
1482 		return error(EGL_BAD_PARAMETER, EGL_FALSE);
1483 	}
1484 
1485 	if(!value)
1486 	{
1487 		return error(EGL_BAD_PARAMETER, EGL_FALSE);
1488 	}
1489 
1490 	switch(attribute)
1491 	{
1492 	case EGL_SYNC_TYPE_KHR:
1493 		*value = EGL_SYNC_FENCE_KHR;
1494 		return success(EGL_TRUE);
1495 	case EGL_SYNC_STATUS_KHR:
1496 		eglSync->wait();   // TODO: Don't block. Just poll based on sw::Query.
1497 		*value = eglSync->isSignaled() ? EGL_SIGNALED_KHR : EGL_UNSIGNALED_KHR;
1498 		return success(EGL_TRUE);
1499 	case EGL_SYNC_CONDITION_KHR:
1500 		*value = EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR;
1501 		return success(EGL_TRUE);
1502 	default:
1503 		return error(EGL_BAD_ATTRIBUTE, EGL_FALSE);
1504 	}
1505 }
1506 
GetSyncAttribKHR(EGLDisplay dpy,EGLSyncKHR sync,EGLint attribute,EGLint * value)1507 EGLBoolean EGLAPIENTRY GetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value)
1508 {
1509 	EGLAttrib attrib_value;
1510 	EGLBoolean result = GetSyncAttrib(dpy, sync, attribute, &attrib_value);
1511 	*value = static_cast<EGLint>(attrib_value);
1512 	return result;
1513 }
1514 
GetProcAddress(const char * procname)1515 __eglMustCastToProperFunctionPointerType EGLAPIENTRY GetProcAddress(const char *procname)
1516 {
1517 	TRACE("(const char *procname = \"%s\")", procname);
1518 
1519 	struct Function
1520 	{
1521 		const char *name;
1522 		__eglMustCastToProperFunctionPointerType address;
1523 	};
1524 
1525 	struct CompareFunctor
1526 	{
1527 		bool operator()(const Function &a, const Function &b) const
1528 		{
1529 			return strcmp(a.name, b.name) < 0;
1530 		}
1531 	};
1532 
1533 	// This array must be kept sorted with respect to strcmp(), so that binary search works correctly.
1534 	// The Unix command "LC_COLLATE=C sort" will generate the correct order.
1535 	static const Function eglFunctions[] =
1536 	{
1537 		#define FUNCTION(name) {#name, (__eglMustCastToProperFunctionPointerType)name}
1538 
1539 		FUNCTION(eglBindAPI),
1540 		FUNCTION(eglBindTexImage),
1541 		FUNCTION(eglChooseConfig),
1542 		FUNCTION(eglClientWaitSync),
1543 		FUNCTION(eglClientWaitSyncKHR),
1544 		FUNCTION(eglCopyBuffers),
1545 		FUNCTION(eglCreateContext),
1546 		FUNCTION(eglCreateImage),
1547 		FUNCTION(eglCreateImageKHR),
1548 		FUNCTION(eglCreatePbufferFromClientBuffer),
1549 		FUNCTION(eglCreatePbufferSurface),
1550 		FUNCTION(eglCreatePixmapSurface),
1551 		FUNCTION(eglCreatePlatformPixmapSurface),
1552 		FUNCTION(eglCreatePlatformPixmapSurfaceEXT),
1553 		FUNCTION(eglCreatePlatformWindowSurface),
1554 		FUNCTION(eglCreatePlatformWindowSurfaceEXT),
1555 		FUNCTION(eglCreateSync),
1556 		FUNCTION(eglCreateSyncKHR),
1557 		FUNCTION(eglCreateWindowSurface),
1558 		FUNCTION(eglDestroyContext),
1559 		FUNCTION(eglDestroyImage),
1560 		FUNCTION(eglDestroyImageKHR),
1561 		FUNCTION(eglDestroySurface),
1562 		FUNCTION(eglDestroySync),
1563 		FUNCTION(eglDestroySyncKHR),
1564 		FUNCTION(eglGetConfigAttrib),
1565 		FUNCTION(eglGetConfigs),
1566 		FUNCTION(eglGetCurrentContext),
1567 		FUNCTION(eglGetCurrentDisplay),
1568 		FUNCTION(eglGetCurrentSurface),
1569 		FUNCTION(eglGetDisplay),
1570 		FUNCTION(eglGetError),
1571 		FUNCTION(eglGetPlatformDisplay),
1572 		FUNCTION(eglGetPlatformDisplayEXT),
1573 		FUNCTION(eglGetProcAddress),
1574 		FUNCTION(eglGetSyncAttrib),
1575 		FUNCTION(eglGetSyncAttribKHR),
1576 		FUNCTION(eglInitialize),
1577 		FUNCTION(eglMakeCurrent),
1578 		FUNCTION(eglQueryAPI),
1579 		FUNCTION(eglQueryContext),
1580 		FUNCTION(eglQueryString),
1581 		FUNCTION(eglQuerySurface),
1582 		FUNCTION(eglReleaseTexImage),
1583 		FUNCTION(eglReleaseThread),
1584 		FUNCTION(eglSurfaceAttrib),
1585 		FUNCTION(eglSwapBuffers),
1586 		FUNCTION(eglSwapInterval),
1587 		FUNCTION(eglTerminate),
1588 		FUNCTION(eglWaitClient),
1589 		FUNCTION(eglWaitGL),
1590 		FUNCTION(eglWaitNative),
1591 		FUNCTION(eglWaitSync),
1592 		FUNCTION(eglWaitSyncKHR),
1593 
1594 		#undef FUNCTION
1595 	};
1596 
1597 	static const size_t numFunctions = sizeof eglFunctions / sizeof(Function);
1598 	static const Function *const eglFunctionsEnd = eglFunctions + numFunctions;
1599 
1600 	Function needle;
1601 	needle.name = procname;
1602 
1603 	if(procname && strncmp("egl", procname, 3) == 0)
1604 	{
1605 		const Function *result = std::lower_bound(eglFunctions, eglFunctionsEnd, needle, CompareFunctor());
1606 		if (result != eglFunctionsEnd && strcmp(procname, result->name) == 0)
1607 		{
1608 			return success((__eglMustCastToProperFunctionPointerType)result->address);
1609 		}
1610 	}
1611 
1612 	if(libGLESv2)
1613 	{
1614 		__eglMustCastToProperFunctionPointerType proc = libGLESv2->es2GetProcAddress(procname);
1615 		if(proc) return success(proc);
1616 	}
1617 
1618 	if(libGLES_CM)
1619 	{
1620 		__eglMustCastToProperFunctionPointerType proc =  libGLES_CM->es1GetProcAddress(procname);
1621 		if(proc) return success(proc);
1622 	}
1623 
1624 	return success((__eglMustCastToProperFunctionPointerType)NULL);
1625 }
1626 }
1627