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 <system/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(__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(__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(!display->isValidWindow((EGLNativeWindowType)native_window))
365 	{
366 		return error(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
367 	}
368 
369 	return display->createWindowSurface((EGLNativeWindowType)native_window, config, attrib_list);
370 }
371 
CreatePlatformWindowSurfaceEXT(EGLDisplay dpy,EGLConfig config,void * native_window,const EGLint * attrib_list)372 EGLSurface EGLAPIENTRY CreatePlatformWindowSurfaceEXT(EGLDisplay dpy, EGLConfig config, void *native_window, const EGLint *attrib_list)
373 {
374 	TRACE("(EGLDisplay dpy = %p, EGLConfig config = %p, void *native_window = %p, "
375 	      "const EGLint *attrib_list = %p)", dpy, config, native_window, attrib_list);
376 
377 	EGLAttribs attribs(attrib_list);
378 	return CreatePlatformWindowSurface(dpy, config, native_window, &attribs);
379 }
380 
CreateWindowSurface(EGLDisplay dpy,EGLConfig config,EGLNativeWindowType window,const EGLint * attrib_list)381 EGLSurface EGLAPIENTRY CreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType window, const EGLint *attrib_list)
382 {
383 	TRACE("(EGLDisplay dpy = %p, EGLConfig config = %p, EGLNativeWindowType window = %p, "
384 	      "const EGLint *attrib_list = %p)", dpy, config, window, attrib_list);
385 
386 	EGLAttribs attribs(attrib_list);
387 	return CreatePlatformWindowSurface(dpy, config, (void*)window, &attribs);
388 }
389 
CreatePbufferSurface(EGLDisplay dpy,EGLConfig config,const EGLint * attrib_list)390 EGLSurface EGLAPIENTRY CreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list)
391 {
392 	TRACE("(EGLDisplay dpy = %p, EGLConfig config = %p, const EGLint *attrib_list = %p)",
393 	      dpy, config, attrib_list);
394 
395 	egl::Display *display = egl::Display::get(dpy);
396 
397 	RecursiveLockGuard lock(egl::getDisplayLock(display));
398 
399 	if(!validateConfig(display, config))
400 	{
401 		return EGL_NO_SURFACE;
402 	}
403 
404 	return display->createPBufferSurface(config, attrib_list);
405 }
406 
CreatePlatformPixmapSurface(EGLDisplay dpy,EGLConfig config,void * native_pixmap,const EGLAttrib * attrib_list)407 EGLSurface EGLAPIENTRY CreatePlatformPixmapSurface(EGLDisplay dpy, EGLConfig config, void *native_pixmap, const EGLAttrib *attrib_list)
408 {
409 	TRACE("(EGLDisplay dpy = %p, EGLConfig config = %p, void *native_pixmap = %p, "
410 	      "const EGLint *attrib_list = %p)", dpy, config, native_pixmap, attrib_list);
411 
412 	egl::Display *display = egl::Display::get(dpy);
413 
414 	RecursiveLockGuard lock(egl::getDisplayLock(display));
415 
416 	if(!validateConfig(display, config))
417 	{
418 		return EGL_NO_SURFACE;
419 	}
420 
421 	UNIMPLEMENTED();   // FIXME
422 
423 	return success(EGL_NO_SURFACE);
424 }
425 
CreatePlatformPixmapSurfaceEXT(EGLDisplay dpy,EGLConfig config,void * native_pixmap,const EGLint * attrib_list)426 EGLSurface EGLAPIENTRY CreatePlatformPixmapSurfaceEXT(EGLDisplay dpy, EGLConfig config, void *native_pixmap, const EGLint *attrib_list)
427 {
428 	TRACE("(EGLDisplay dpy = %p, EGLConfig config = %p, void *native_pixmap = %p, "
429 	      "const EGLint *attrib_list = %p)", dpy, config, native_pixmap, attrib_list);
430 
431 	EGLAttribs attribs(attrib_list);
432 	return CreatePlatformPixmapSurface(dpy, config, native_pixmap, &attribs);
433 }
434 
CreatePixmapSurface(EGLDisplay dpy,EGLConfig config,EGLNativePixmapType pixmap,const EGLint * attrib_list)435 EGLSurface EGLAPIENTRY CreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list)
436 {
437 	TRACE("(EGLDisplay dpy = %p, EGLConfig config = %p, EGLNativePixmapType pixmap = %p, "
438 	      "const EGLint *attrib_list = %p)", dpy, config, pixmap, attrib_list);
439 
440 	EGLAttribs attribs(attrib_list);
441 	return CreatePlatformPixmapSurface(dpy, config, (void*)pixmap, &attribs);
442 }
443 
DestroySurface(EGLDisplay dpy,EGLSurface surface)444 EGLBoolean EGLAPIENTRY DestroySurface(EGLDisplay dpy, EGLSurface surface)
445 {
446 	TRACE("(EGLDisplay dpy = %p, EGLSurface surface = %p)", dpy, surface);
447 
448 	egl::Display *display = egl::Display::get(dpy);
449 	egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);
450 
451 	RecursiveLockGuard lock(egl::getDisplayLock(display));
452 
453 	if(!validateSurface(display, eglSurface))
454 	{
455 		return EGL_FALSE;
456 	}
457 
458 	if(surface == EGL_NO_SURFACE)
459 	{
460 		return error(EGL_BAD_SURFACE, EGL_FALSE);
461 	}
462 
463 	display->destroySurface((egl::Surface*)surface);
464 
465 	return success(EGL_TRUE);
466 }
467 
QuerySurface(EGLDisplay dpy,EGLSurface surface,EGLint attribute,EGLint * value)468 EGLBoolean EGLAPIENTRY QuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value)
469 {
470 	TRACE("(EGLDisplay dpy = %p, EGLSurface surface = %p, EGLint attribute = %d, EGLint *value = %p)",
471 	      dpy, surface, attribute, value);
472 
473 	egl::Display *display = egl::Display::get(dpy);
474 	egl::Surface *eglSurface = (egl::Surface*)surface;
475 
476 	RecursiveLockGuard lock(egl::getDisplayLock(display));
477 
478 	if(!validateSurface(display, eglSurface))
479 	{
480 		return EGL_FALSE;
481 	}
482 
483 	if(surface == EGL_NO_SURFACE)
484 	{
485 		return error(EGL_BAD_SURFACE, EGL_FALSE);
486 	}
487 
488 	switch(attribute)
489 	{
490 	case EGL_VG_ALPHA_FORMAT:
491 		*value = EGL_VG_ALPHA_FORMAT_NONPRE;   // Default
492 		break;
493 	case EGL_VG_COLORSPACE:
494 		*value = EGL_VG_COLORSPACE_sRGB;   // Default
495 		break;
496 	case EGL_CONFIG_ID:
497 		*value = eglSurface->getConfigID();
498 		break;
499 	case EGL_HEIGHT:
500 		*value = eglSurface->getHeight();
501 		break;
502 	case EGL_HORIZONTAL_RESOLUTION:
503 		*value = EGL_UNKNOWN;
504 		break;
505 	case EGL_LARGEST_PBUFFER:
506 		if(eglSurface->isPBufferSurface())   // For a window or pixmap surface, the contents of *value are not modified.
507 		{
508 			*value = eglSurface->getLargestPBuffer();
509 		}
510 		break;
511 	case EGL_MIPMAP_TEXTURE:
512 		if(eglSurface->isPBufferSurface())   // For a window or pixmap surface, the contents of *value are not modified.
513 		{
514 			*value = EGL_FALSE;   // UNIMPLEMENTED
515 		}
516 		break;
517 	case EGL_MIPMAP_LEVEL:
518 		if(eglSurface->isPBufferSurface())   // For a window or pixmap surface, the contents of *value are not modified.
519 		{
520 			*value = eglSurface->getMipmapLevel();
521 		}
522 		break;
523 	case EGL_MULTISAMPLE_RESOLVE:
524 		*value = eglSurface->getMultisampleResolve();
525 		break;
526 	case EGL_PIXEL_ASPECT_RATIO:
527 		*value = eglSurface->getPixelAspectRatio();
528 		break;
529 	case EGL_RENDER_BUFFER:
530 		*value = eglSurface->getRenderBuffer();
531 		break;
532 	case EGL_SWAP_BEHAVIOR:
533 		*value = eglSurface->getSwapBehavior();
534 		break;
535 	case EGL_TEXTURE_FORMAT:
536 		if(eglSurface->isPBufferSurface())   // For a window or pixmap surface, the contents of *value are not modified.
537 		{
538 			*value = eglSurface->getTextureFormat();
539 		}
540 		break;
541 	case EGL_TEXTURE_TARGET:
542 		if(eglSurface->isPBufferSurface())   // For a window or pixmap surface, the contents of *value are not modified.
543 		{
544 			*value = eglSurface->getTextureTarget();
545 		}
546 		break;
547 	case EGL_VERTICAL_RESOLUTION:
548 		*value = EGL_UNKNOWN;
549 		break;
550 	case EGL_WIDTH:
551 		*value = eglSurface->getWidth();
552 		break;
553 	default:
554 		return error(EGL_BAD_ATTRIBUTE, EGL_FALSE);
555 	}
556 
557 	return success(EGL_TRUE);
558 }
559 
BindAPI(EGLenum api)560 EGLBoolean EGLAPIENTRY BindAPI(EGLenum api)
561 {
562 	TRACE("(EGLenum api = 0x%X)", api);
563 
564 	switch(api)
565 	{
566 	case EGL_OPENGL_API:
567 	case EGL_OPENVG_API:
568 		return error(EGL_BAD_PARAMETER, EGL_FALSE);   // Not supported by this implementation
569 	case EGL_OPENGL_ES_API:
570 		break;
571 	default:
572 		return error(EGL_BAD_PARAMETER, EGL_FALSE);
573 	}
574 
575 	egl::setCurrentAPI(api);
576 
577 	return success(EGL_TRUE);
578 }
579 
QueryAPI(void)580 EGLenum EGLAPIENTRY QueryAPI(void)
581 {
582 	TRACE("()");
583 
584 	EGLenum API = egl::getCurrentAPI();
585 
586 	return success(API);
587 }
588 
WaitClient(void)589 EGLBoolean EGLAPIENTRY WaitClient(void)
590 {
591 	TRACE("()");
592 
593 	// eglWaitClient is ignored if there is no current EGL rendering context for the current rendering API.
594 	egl::Context *context = egl::getCurrentContext();
595 
596 	if(context)
597 	{
598 		context->finish();
599 	}
600 
601 	return success(EGL_TRUE);
602 }
603 
ReleaseThread(void)604 EGLBoolean EGLAPIENTRY ReleaseThread(void)
605 {
606 	TRACE("()");
607 
608 	detachThread();
609 
610 	return EGL_TRUE;   // success() is not called here because it would re-allocate thread-local storage.
611 }
612 
CreatePbufferFromClientBuffer(EGLDisplay dpy,EGLenum buftype,EGLClientBuffer buffer,EGLConfig config,const EGLint * attrib_list)613 EGLSurface EGLAPIENTRY CreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list)
614 {
615 	TRACE("(EGLDisplay dpy = %p, EGLenum buftype = 0x%X, EGLClientBuffer buffer = %p, "
616 	      "EGLConfig config = %p, const EGLint *attrib_list = %p)",
617 	      dpy, buftype, buffer, config, attrib_list);
618 
619 	switch(buftype)
620 	{
621 	case EGL_IOSURFACE_ANGLE:
622 	{
623 		egl::Display *display = egl::Display::get(dpy);
624 
625 		RecursiveLockGuard lock(egl::getDisplayLock(display));
626 
627 		if(!validateConfig(display, config))
628 		{
629 			return EGL_NO_SURFACE;
630 		}
631 
632 		return display->createPBufferSurface(config, attrib_list, buffer);
633 	}
634 	case EGL_OPENVG_IMAGE:
635 		UNIMPLEMENTED();
636 		return error(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
637 	default:
638 		return error(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
639 	};
640 }
641 
SurfaceAttrib(EGLDisplay dpy,EGLSurface surface,EGLint attribute,EGLint value)642 EGLBoolean EGLAPIENTRY SurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
643 {
644 	TRACE("(EGLDisplay dpy = %p, EGLSurface surface = %p, EGLint attribute = %d, EGLint value = %d)",
645 	      dpy, surface, attribute, value);
646 
647 	egl::Display *display = egl::Display::get(dpy);
648 	egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);
649 
650 	RecursiveLockGuard lock(egl::getDisplayLock(display));
651 
652 	if(!validateSurface(display, eglSurface))
653 	{
654 		return EGL_FALSE;
655 	}
656 
657 	switch(attribute)
658 	{
659 	case EGL_MIPMAP_LEVEL:
660 		eglSurface->setMipmapLevel(value);
661 		break;
662 	case EGL_MULTISAMPLE_RESOLVE:
663 		switch(value)
664 		{
665 		case EGL_MULTISAMPLE_RESOLVE_DEFAULT:
666 			break;
667 		case EGL_MULTISAMPLE_RESOLVE_BOX:
668 			if(!(eglSurface->getSurfaceType() & EGL_MULTISAMPLE_RESOLVE_BOX_BIT))
669 			{
670 				return error(EGL_BAD_MATCH, EGL_FALSE);
671 			}
672 			break;
673 		default:
674 			return error(EGL_BAD_PARAMETER, EGL_FALSE);
675 		}
676 		eglSurface->setMultisampleResolve(value);
677 		break;
678 	case EGL_SWAP_BEHAVIOR:
679 		switch(value)
680 		{
681 		case EGL_BUFFER_DESTROYED:
682 			break;
683 		case EGL_BUFFER_PRESERVED:
684 			if(!(eglSurface->getSurfaceType() & EGL_SWAP_BEHAVIOR_PRESERVED_BIT))
685 			{
686 				return error(EGL_BAD_MATCH, EGL_FALSE);
687 			}
688 			break;
689 		default:
690 			return error(EGL_BAD_PARAMETER, EGL_FALSE);
691 		}
692 		eglSurface->setSwapBehavior(value);
693 		break;
694 	default:
695 		return error(EGL_BAD_PARAMETER, EGL_FALSE);
696 	}
697 
698 	return success(EGL_TRUE);
699 }
700 
BindTexImage(EGLDisplay dpy,EGLSurface surface,EGLint buffer)701 EGLBoolean EGLAPIENTRY BindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
702 {
703 	TRACE("(EGLDisplay dpy = %p, EGLSurface surface = %p, EGLint buffer = %d)", dpy, surface, buffer);
704 
705 	egl::Display *display = egl::Display::get(dpy);
706 	egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);
707 
708 	RecursiveLockGuard lock(egl::getDisplayLock(display));
709 
710 	if(!validateSurface(display, eglSurface))
711 	{
712 		return EGL_FALSE;
713 	}
714 
715 	if(buffer != EGL_BACK_BUFFER)
716 	{
717 		return error(EGL_BAD_PARAMETER, EGL_FALSE);
718 	}
719 
720 	if(surface == EGL_NO_SURFACE || eglSurface->isWindowSurface())
721 	{
722 		return error(EGL_BAD_SURFACE, EGL_FALSE);
723 	}
724 
725 	if(eglSurface->getBoundTexture())
726 	{
727 		return error(EGL_BAD_ACCESS, EGL_FALSE);
728 	}
729 
730 	if(eglSurface->getTextureFormat() == EGL_NO_TEXTURE)
731 	{
732 		return error(EGL_BAD_MATCH, EGL_FALSE);
733 	}
734 
735 	egl::Context *context = egl::getCurrentContext();
736 
737 	if(context)
738 	{
739 		context->bindTexImage(eglSurface);
740 	}
741 
742 	return success(EGL_TRUE);
743 }
744 
ReleaseTexImage(EGLDisplay dpy,EGLSurface surface,EGLint buffer)745 EGLBoolean EGLAPIENTRY ReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
746 {
747 	TRACE("(EGLDisplay dpy = %p, EGLSurface surface = %p, EGLint buffer = %d)", dpy, surface, buffer);
748 
749 	egl::Display *display = egl::Display::get(dpy);
750 	egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);
751 
752 	RecursiveLockGuard lock(egl::getDisplayLock(display));
753 
754 	if(!validateSurface(display, eglSurface))
755 	{
756 		return EGL_FALSE;
757 	}
758 
759 	if(buffer != EGL_BACK_BUFFER)
760 	{
761 		return error(EGL_BAD_PARAMETER, EGL_FALSE);
762 	}
763 
764 	if(surface == EGL_NO_SURFACE || eglSurface->isWindowSurface())
765 	{
766 		return error(EGL_BAD_SURFACE, EGL_FALSE);
767 	}
768 
769 	if(eglSurface->getTextureFormat() == EGL_NO_TEXTURE)
770 	{
771 		return error(EGL_BAD_MATCH, EGL_FALSE);
772 	}
773 
774 	egl::Texture *texture = eglSurface->getBoundTexture();
775 
776 	if(texture)
777 	{
778 		texture->releaseTexImage();
779 	}
780 
781 	return success(EGL_TRUE);
782 }
783 
SwapInterval(EGLDisplay dpy,EGLint interval)784 EGLBoolean EGLAPIENTRY SwapInterval(EGLDisplay dpy, EGLint interval)
785 {
786 	TRACE("(EGLDisplay dpy = %p, EGLint interval = %d)", dpy, interval);
787 
788 	egl::Display *display = egl::Display::get(dpy);
789 	egl::Context *context = egl::getCurrentContext();
790 
791 	RecursiveLockGuard lock(egl::getDisplayLock(display));
792 
793 	if(!validateContext(display, context))
794 	{
795 		return EGL_FALSE;
796 	}
797 
798 	egl::Surface *draw_surface = static_cast<egl::Surface*>(egl::getCurrentDrawSurface());
799 
800 	if(!draw_surface)
801 	{
802 		return error(EGL_BAD_SURFACE, EGL_FALSE);
803 	}
804 
805 	draw_surface->setSwapInterval(interval);
806 
807 	return success(EGL_TRUE);
808 }
809 
CreateContext(EGLDisplay dpy,EGLConfig config,EGLContext share_context,const EGLint * attrib_list)810 EGLContext EGLAPIENTRY CreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list)
811 {
812 	TRACE("(EGLDisplay dpy = %p, EGLConfig config = %p, EGLContext share_context = %p, "
813 	      "const EGLint *attrib_list = %p)", dpy, config, share_context, attrib_list);
814 
815 	EGLint majorVersion = 1;
816 	EGLint minorVersion = 0;
817 
818 	if(attrib_list)
819 	{
820 		for(const EGLint* attribute = attrib_list; attribute[0] != EGL_NONE; attribute += 2)
821 		{
822 			switch(attribute[0])
823 			{
824 			case EGL_CONTEXT_MAJOR_VERSION_KHR:   // This token is an alias for EGL_CONTEXT_CLIENT_VERSION
825 				majorVersion = attribute[1];
826 				break;
827 			case EGL_CONTEXT_MINOR_VERSION_KHR:
828 				minorVersion = attribute[1];
829 				break;
830 			case EGL_CONTEXT_FLAGS_KHR:
831 				switch(attribute[1])
832 				{
833 				case EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR:
834 					// According to the EGL_KHR_create_context spec:
835 					// "Khronos is still defining the expected and required features of debug contexts, so
836 					//  implementations are currently free to implement "debug contexts" with little or no debug
837 					//  functionality. However, OpenGL and OpenGL ES implementations supporting the GL_KHR_debug
838 					//  extension should enable it when this bit is set."
839 					break;
840 				case EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR:
841 				case EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR:
842 					// These bits are for OpenGL contexts only, not OpenGL ES contexts
843 					return error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
844 				default:
845 					return error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
846 				}
847 				break;
848 			case EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR:
849 				switch(attribute[1])
850 				{
851 				case EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR:
852 				case EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR:
853 					// These bits are for OpenGL contexts only, not OpenGL ES contexts
854 					return error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
855 				default:
856 					return error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
857 				}
858 				break;
859 			case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR:
860 				switch(attribute[1])
861 				{
862 				case EGL_NO_RESET_NOTIFICATION_KHR:
863 				case EGL_LOSE_CONTEXT_ON_RESET_KHR:
864 					// These bits are for OpenGL contexts only, not OpenGL ES contexts
865 					return error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
866 				default:
867 					return error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
868 				}
869 				break;
870 			default:
871 				return error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
872 			}
873 		}
874 	}
875 
876 	switch(majorVersion)
877 	{
878 	case 1:
879 		if(minorVersion != 0 && minorVersion != 1)
880 		{
881 			// 1.X: Only OpenGL ES 1.0 and 1.1 contexts are supported
882 			return error(EGL_BAD_MATCH, EGL_NO_CONTEXT);
883 		}
884 		break;
885 	case 2:
886 	case 3:
887 		if(minorVersion != 0)
888 		{
889 			// 2.X and 3.X: Only OpenGL ES 2.0 and 3.0 contexts are currently supported
890 			return error(EGL_BAD_MATCH, EGL_NO_CONTEXT);
891 		}
892 		break;
893 	default:
894 		return error(EGL_BAD_MATCH, EGL_NO_CONTEXT);
895 	}
896 
897 	egl::Display *display = egl::Display::get(dpy);
898 	egl::Context *shareContext = static_cast<egl::Context*>(share_context);
899 
900 	RecursiveLockGuard lock(egl::getDisplayLock(display));
901 
902 	if(!validateConfig(display, config))
903 	{
904 		return EGL_NO_CONTEXT;
905 	}
906 
907 	// Allow sharing between different context versions >= 2.0, but isolate 1.x
908 	// contexts from 2.0+. Strict matching between context versions >= 2.0 is
909 	// confusing for apps to navigate because of version promotion.
910 	if(shareContext && ((shareContext->getClientVersion() >= 2) ^ (majorVersion >= 2)))
911 	{
912 		return error(EGL_BAD_CONTEXT, EGL_NO_CONTEXT);
913 	}
914 
915 	return display->createContext(config, shareContext, majorVersion);
916 }
917 
DestroyContext(EGLDisplay dpy,EGLContext ctx)918 EGLBoolean EGLAPIENTRY DestroyContext(EGLDisplay dpy, EGLContext ctx)
919 {
920 	TRACE("(EGLDisplay dpy = %p, EGLContext ctx = %p)", dpy, ctx);
921 
922 	egl::Display *display = egl::Display::get(dpy);
923 	egl::Context *context = static_cast<egl::Context*>(ctx);
924 
925 	RecursiveLockGuard lock(egl::getDisplayLock(display));
926 
927 	if(!validateContext(display, context))
928 	{
929 		return EGL_FALSE;
930 	}
931 
932 	if(ctx == EGL_NO_CONTEXT)
933 	{
934 		return error(EGL_BAD_CONTEXT, EGL_FALSE);
935 	}
936 
937 	display->destroyContext(context);
938 
939 	return success(EGL_TRUE);
940 }
941 
MakeCurrent(EGLDisplay dpy,EGLSurface draw,EGLSurface read,EGLContext ctx)942 EGLBoolean EGLAPIENTRY MakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx)
943 {
944 	TRACE("(EGLDisplay dpy = %p, EGLSurface draw = %p, EGLSurface read = %p, EGLContext ctx = %p)",
945 	      dpy, draw, read, ctx);
946 
947 	egl::Display *display = egl::Display::get(dpy);
948 	egl::Context *context = static_cast<egl::Context*>(ctx);
949 	egl::Surface *drawSurface = static_cast<egl::Surface*>(draw);
950 	egl::Surface *readSurface = static_cast<egl::Surface*>(read);
951 
952 	RecursiveLockGuard lock(egl::getDisplayLock(display));
953 
954 	if(ctx != EGL_NO_CONTEXT || draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE)
955 	{
956 		if(!validateDisplay(display))
957 		{
958 			return EGL_FALSE;
959 		}
960 	}
961 
962 	if(ctx == EGL_NO_CONTEXT && (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE))
963 	{
964 		return error(EGL_BAD_MATCH, EGL_FALSE);
965 	}
966 
967 	if(ctx != EGL_NO_CONTEXT && !validateContext(display, context))
968 	{
969 		return EGL_FALSE;
970 	}
971 
972 	if((draw != EGL_NO_SURFACE && !validateSurface(display, drawSurface)) ||
973 	   (read != EGL_NO_SURFACE && !validateSurface(display, readSurface)))
974 	{
975 		return EGL_FALSE;
976 	}
977 
978 	if((draw != EGL_NO_SURFACE) ^ (read != EGL_NO_SURFACE))
979 	{
980 		return error(EGL_BAD_MATCH, EGL_FALSE);
981 	}
982 
983 	if(draw != read)
984 	{
985 		UNIMPLEMENTED();   // FIXME
986 	}
987 
988 	egl::setCurrentDrawSurface(drawSurface);
989 	egl::setCurrentReadSurface(readSurface);
990 	egl::setCurrentContext(context);
991 
992 	if(context)
993 	{
994 		context->makeCurrent(drawSurface);
995 	}
996 
997 	return success(EGL_TRUE);
998 }
999 
GetCurrentContext(void)1000 EGLContext EGLAPIENTRY GetCurrentContext(void)
1001 {
1002 	TRACE("()");
1003 
1004 	EGLContext context = egl::getCurrentContext();
1005 
1006 	return success(context);
1007 }
1008 
GetCurrentSurface(EGLint readdraw)1009 EGLSurface EGLAPIENTRY GetCurrentSurface(EGLint readdraw)
1010 {
1011 	TRACE("(EGLint readdraw = %d)", readdraw);
1012 
1013 	if(readdraw == EGL_READ)
1014 	{
1015 		EGLSurface read = egl::getCurrentReadSurface();
1016 		return success(read);
1017 	}
1018 	else if(readdraw == EGL_DRAW)
1019 	{
1020 		EGLSurface draw = egl::getCurrentDrawSurface();
1021 		return success(draw);
1022 	}
1023 	else
1024 	{
1025 		return error(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
1026 	}
1027 }
1028 
GetCurrentDisplay(void)1029 EGLDisplay EGLAPIENTRY GetCurrentDisplay(void)
1030 {
1031 	TRACE("()");
1032 
1033 	egl::Context *context = egl::getCurrentContext();
1034 
1035 	if(!context)
1036 	{
1037 		return success(EGL_NO_DISPLAY);
1038 	}
1039 
1040 	egl::Display *display = context->getDisplay();
1041 
1042 	if(!display)
1043 	{
1044 		return error(EGL_BAD_ACCESS, EGL_NO_DISPLAY);
1045 	}
1046 
1047 	return success(display->getEGLDisplay());
1048 }
1049 
QueryContext(EGLDisplay dpy,EGLContext ctx,EGLint attribute,EGLint * value)1050 EGLBoolean EGLAPIENTRY QueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value)
1051 {
1052 	TRACE("(EGLDisplay dpy = %p, EGLContext ctx = %p, EGLint attribute = %d, EGLint *value = %p)",
1053 	      dpy, ctx, attribute, value);
1054 
1055 	egl::Display *display = egl::Display::get(dpy);
1056 	egl::Context *context = static_cast<egl::Context*>(ctx);
1057 
1058 	RecursiveLockGuard lock(egl::getDisplayLock(display));
1059 
1060 	if(!validateContext(display, context))
1061 	{
1062 		return EGL_FALSE;
1063 	}
1064 
1065 	switch(attribute)
1066 	{
1067 	case EGL_CONFIG_ID:
1068 		*value = context->getConfigID();
1069 		break;
1070 	case EGL_CONTEXT_CLIENT_TYPE:
1071 		*value = egl::getCurrentAPI();
1072 		break;
1073 	case EGL_CONTEXT_CLIENT_VERSION:
1074 		*value = context->getClientVersion();
1075 		break;
1076 	case EGL_RENDER_BUFFER:
1077 		*value = EGL_BACK_BUFFER;
1078 		break;
1079 	default:
1080 		return error(EGL_BAD_ATTRIBUTE, EGL_FALSE);
1081 	}
1082 
1083 	return success(EGL_TRUE);
1084 }
1085 
WaitGL(void)1086 EGLBoolean EGLAPIENTRY WaitGL(void)
1087 {
1088 	TRACE("()");
1089 
1090 	// glWaitGL is ignored if there is no current EGL rendering context for OpenGL ES.
1091 	egl::Context *context = egl::getCurrentContext();
1092 
1093 	if(context)
1094 	{
1095 		context->finish();
1096 	}
1097 
1098 	return success(EGL_TRUE);
1099 }
1100 
WaitNative(EGLint engine)1101 EGLBoolean EGLAPIENTRY WaitNative(EGLint engine)
1102 {
1103 	TRACE("(EGLint engine = %d)", engine);
1104 
1105 	if(engine != EGL_CORE_NATIVE_ENGINE)
1106 	{
1107 		return error(EGL_BAD_PARAMETER, EGL_FALSE);
1108 	}
1109 
1110 	// eglWaitNative is ignored if there is no current EGL rendering context.
1111 	egl::Context *context = egl::getCurrentContext();
1112 
1113 	if(context)
1114 	{
1115 		#if defined(USE_X11)
1116 			egl::Display *display = context->getDisplay();
1117 
1118 			if(!display)
1119 			{
1120 				return error(EGL_BAD_DISPLAY, EGL_FALSE);
1121 			}
1122 
1123 			libX11->XSync((::Display*)display->getNativeDisplay(), False);
1124 		#else
1125 			UNIMPLEMENTED();
1126 		#endif
1127 	}
1128 
1129 	return success(EGL_TRUE);
1130 }
1131 
SwapBuffers(EGLDisplay dpy,EGLSurface surface)1132 EGLBoolean EGLAPIENTRY SwapBuffers(EGLDisplay dpy, EGLSurface surface)
1133 {
1134 	TRACE("(EGLDisplay dpy = %p, EGLSurface surface = %p)", dpy, surface);
1135 
1136 	egl::Display *display = egl::Display::get(dpy);
1137 	egl::Surface *eglSurface = (egl::Surface*)surface;
1138 
1139 	{
1140 		RecursiveLockGuard lock(egl::getDisplayLock(display));
1141 
1142 		if(!validateSurface(display, eglSurface))
1143 		{
1144 			return EGL_FALSE;
1145 		}
1146 	}
1147 
1148 	if(surface == EGL_NO_SURFACE)
1149 	{
1150 		return error(EGL_BAD_SURFACE, EGL_FALSE);
1151 	}
1152 
1153 	eglSurface->swap();
1154 
1155 	return success(EGL_TRUE);
1156 }
1157 
CopyBuffers(EGLDisplay dpy,EGLSurface surface,EGLNativePixmapType target)1158 EGLBoolean EGLAPIENTRY CopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target)
1159 {
1160 	TRACE("(EGLDisplay dpy = %p, EGLSurface surface = %p, EGLNativePixmapType target = %p)", dpy, surface, target);
1161 
1162 	egl::Display *display = egl::Display::get(dpy);
1163 	egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);
1164 
1165 	RecursiveLockGuard lock(egl::getDisplayLock(display));
1166 
1167 	if(!validateSurface(display, eglSurface))
1168 	{
1169 		return EGL_FALSE;
1170 	}
1171 
1172 	UNIMPLEMENTED();   // FIXME
1173 
1174 	return success(EGL_FALSE);
1175 }
1176 
CreateImage(EGLDisplay dpy,EGLContext ctx,EGLenum target,EGLClientBuffer buffer,const EGLAttrib * attrib_list)1177 EGLImage EGLAPIENTRY CreateImage(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLAttrib *attrib_list)
1178 {
1179 	TRACE("(EGLDisplay dpy = %p, EGLContext ctx = %p, EGLenum target = 0x%X, buffer = %p, const EGLAttrib *attrib_list = %p)", dpy, ctx, target, buffer, attrib_list);
1180 
1181 	egl::Display *display = egl::Display::get(dpy);
1182 	egl::Context *context = static_cast<egl::Context*>(ctx);
1183 
1184 	RecursiveLockGuard lock(egl::getDisplayLock(display));
1185 
1186 	if(!validateDisplay(display))
1187 	{
1188 		return error(EGL_BAD_DISPLAY, EGL_NO_IMAGE_KHR);
1189 	}
1190 
1191 	if(context != EGL_NO_CONTEXT && !display->isValidContext(context))
1192 	{
1193 		return error(EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR);
1194 	}
1195 
1196 	EGLenum imagePreserved = EGL_FALSE;
1197 	(void)imagePreserved; // currently unused
1198 
1199 	GLuint textureLevel = 0;
1200 	if(attrib_list)
1201 	{
1202 		for(const EGLAttrib *attribute = attrib_list; attribute[0] != EGL_NONE; attribute += 2)
1203 		{
1204 			if(attribute[0] == EGL_IMAGE_PRESERVED_KHR)
1205 			{
1206 				imagePreserved = static_cast<EGLenum>(attribute[1]);
1207 			}
1208 			else if(attribute[0] == EGL_GL_TEXTURE_LEVEL_KHR)
1209 			{
1210 				textureLevel = static_cast<GLuint>(attribute[1]);
1211 			}
1212 			else
1213 			{
1214 				return error(EGL_BAD_ATTRIBUTE, EGL_NO_IMAGE_KHR);
1215 			}
1216 		}
1217 	}
1218 
1219 	#if defined(__ANDROID__) && !defined(ANDROID_NDK_BUILD)
1220 		if(target == EGL_NATIVE_BUFFER_ANDROID)
1221 		{
1222 			ANativeWindowBuffer *nativeBuffer = reinterpret_cast<ANativeWindowBuffer*>(buffer);
1223 
1224 			if(!nativeBuffer || GLPixelFormatFromAndroid(nativeBuffer->format) == GL_NONE)
1225 			{
1226 				ERR("%s badness unsupported HAL format=%x", __FUNCTION__, nativeBuffer ? nativeBuffer->format : 0);
1227 				return error(EGL_BAD_ATTRIBUTE, EGL_NO_IMAGE_KHR);
1228 			}
1229 
1230 			Image *image = new AndroidNativeImage(nativeBuffer);
1231 			EGLImageKHR eglImage = display->createSharedImage(image);
1232 
1233 			return success(eglImage);
1234 		}
1235 	#endif
1236 
1237 	GLuint name = static_cast<GLuint>(reinterpret_cast<uintptr_t>(buffer));
1238 
1239 	if(name == 0)
1240 	{
1241 		return error(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
1242 	}
1243 
1244 	EGLenum validationResult = context->validateSharedImage(target, name, textureLevel);
1245 
1246 	if(validationResult != EGL_SUCCESS)
1247 	{
1248 		return error(validationResult, EGL_NO_IMAGE_KHR);
1249 	}
1250 
1251 	Image *image = context->createSharedImage(target, name, textureLevel);
1252 
1253 	if(!image)
1254 	{
1255 		return error(EGL_BAD_MATCH, EGL_NO_IMAGE_KHR);
1256 	}
1257 
1258 	if(image->getDepth() > 1)
1259 	{
1260 		return error(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
1261 	}
1262 
1263 	EGLImage eglImage = display->createSharedImage(image);
1264 
1265 	return success(eglImage);
1266 }
1267 
CreateImageKHR(EGLDisplay dpy,EGLContext ctx,EGLenum target,EGLClientBuffer buffer,const EGLint * attrib_list)1268 EGLImageKHR EGLAPIENTRY CreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list)
1269 {
1270 	TRACE("(EGLDisplay dpy = %p, EGLContext ctx = %p, EGLenum target = 0x%X, buffer = %p, const EGLint attrib_list = %p)", dpy, ctx, target, buffer, attrib_list);
1271 
1272 	EGLAttribs attribs(attrib_list);
1273 	return CreateImage(dpy, ctx, target, buffer, &attribs);
1274 }
1275 
DestroyImageKHR(EGLDisplay dpy,EGLImageKHR image)1276 EGLBoolean EGLAPIENTRY DestroyImageKHR(EGLDisplay dpy, EGLImageKHR image)
1277 {
1278 	TRACE("(EGLDisplay dpy = %p, EGLImageKHR image = %p)", dpy, image);
1279 
1280 	egl::Display *display = egl::Display::get(dpy);
1281 
1282 	RecursiveLockGuard lock(egl::getDisplayLock(display));
1283 
1284 	if(!validateDisplay(display))
1285 	{
1286 		return error(EGL_BAD_DISPLAY, EGL_FALSE);
1287 	}
1288 
1289 	if(!display->destroySharedImage(image))
1290 	{
1291 		return error(EGL_BAD_PARAMETER, EGL_FALSE);
1292 	}
1293 
1294 	return success(EGL_TRUE);
1295 }
1296 
GetPlatformDisplay(EGLenum platform,void * native_display,const EGLAttrib * attrib_list)1297 EGLDisplay EGLAPIENTRY GetPlatformDisplay(EGLenum platform, void *native_display, const EGLAttrib *attrib_list)
1298 {
1299 	TRACE("(EGLenum platform = 0x%X, void *native_display = %p, const EGLAttrib *attrib_list = %p)", platform, native_display, attrib_list);
1300 
1301 	#if defined(__linux__) && !defined(__ANDROID__)
1302 		switch(platform)
1303 		{
1304 		#if defined(USE_X11)
1305 		case EGL_PLATFORM_X11_EXT: break;
1306 		#endif
1307 		case EGL_PLATFORM_GBM_KHR: break;
1308 		default:
1309 			return error(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
1310 		}
1311 
1312 		if(platform == EGL_PLATFORM_GBM_KHR)
1313 		{
1314 			if(native_display != (void*)EGL_DEFAULT_DISPLAY)
1315 			{
1316 				return error(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);   // Unimplemented
1317 			}
1318 
1319 			if(attrib_list && attrib_list[0] != EGL_NONE)
1320 			{
1321 				return error(EGL_BAD_ATTRIBUTE, EGL_NO_DISPLAY);   // Unimplemented
1322 			}
1323 
1324 			return success(HEADLESS_DISPLAY);
1325 		}
1326 		#if defined(USE_X11)
1327 		else if(platform == EGL_PLATFORM_X11_EXT)
1328 		{
1329 			if(!libX11)
1330 			{
1331 				return error(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
1332 			}
1333 
1334 			if(native_display != (void*)EGL_DEFAULT_DISPLAY)
1335 			{
1336 				return error(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);   // Unimplemented
1337 			}
1338 
1339 			if(attrib_list && attrib_list[0] != EGL_NONE)
1340 			{
1341 				return error(EGL_BAD_ATTRIBUTE, EGL_NO_DISPLAY);   // Unimplemented
1342 			}
1343 		}
1344 		#endif
1345 
1346 		return success(PRIMARY_DISPLAY);   // We only support the default display
1347 	#else
1348 		return error(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
1349 	#endif
1350 }
1351 
GetPlatformDisplayEXT(EGLenum platform,void * native_display,const EGLint * attrib_list)1352 EGLDisplay EGLAPIENTRY GetPlatformDisplayEXT(EGLenum platform, void *native_display, const EGLint *attrib_list)
1353 {
1354 	TRACE("(EGLenum platform = 0x%X, void *native_display = %p, const EGLint *attrib_list = %p)", platform, native_display, attrib_list);
1355 
1356 	EGLAttribs attribs(attrib_list);
1357 	return GetPlatformDisplay(platform, native_display, &attribs);
1358 }
1359 
CreateSync(EGLDisplay dpy,EGLenum type,const EGLAttrib * attrib_list)1360 EGLSync EGLAPIENTRY CreateSync(EGLDisplay dpy, EGLenum type, const EGLAttrib *attrib_list)
1361 {
1362 	TRACE("(EGLDisplay dpy = %p, EGLunum type = %x, EGLAttrib *attrib_list=%p)", dpy, type, attrib_list);
1363 
1364 	egl::Display *display = egl::Display::get(dpy);
1365 
1366 	RecursiveLockGuard lock(egl::getDisplayLock(display));
1367 
1368 	if(!validateDisplay(display))
1369 	{
1370 		return error(EGL_BAD_DISPLAY, EGL_NO_SYNC_KHR);
1371 	}
1372 
1373 	if(type != EGL_SYNC_FENCE_KHR)
1374 	{
1375 		return error(EGL_BAD_ATTRIBUTE, EGL_NO_SYNC_KHR);
1376 	}
1377 
1378 	if(attrib_list && attrib_list[0] != EGL_NONE)
1379 	{
1380 		return error(EGL_BAD_ATTRIBUTE, EGL_NO_SYNC_KHR);
1381 	}
1382 
1383 	egl::Context *context = egl::getCurrentContext();
1384 
1385 	if(!validateContext(display, context))
1386 	{
1387 		return error(EGL_BAD_MATCH, EGL_NO_SYNC_KHR);
1388 	}
1389 
1390 	EGLSyncKHR sync = display->createSync(context);
1391 
1392 	return success(sync);
1393 }
1394 
CreateSyncKHR(EGLDisplay dpy,EGLenum type,const EGLint * attrib_list)1395 EGLSyncKHR EGLAPIENTRY CreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list)
1396 {
1397 	TRACE("(EGLDisplay dpy = %p, EGLunum type = %x, EGLint *attrib_list=%p)", dpy, type, attrib_list);
1398 
1399 	EGLAttribs attribs(attrib_list);
1400 	return CreateSync(dpy, type, &attribs);
1401 }
1402 
DestroySyncKHR(EGLDisplay dpy,EGLSyncKHR sync)1403 EGLBoolean EGLAPIENTRY DestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync)
1404 {
1405 	TRACE("(EGLDisplay dpy = %p, EGLSyncKHR sync = %p)", dpy, sync);
1406 
1407 	egl::Display *display = egl::Display::get(dpy);
1408 	FenceSync *eglSync = static_cast<FenceSync*>(sync);
1409 
1410 	RecursiveLockGuard lock(egl::getDisplayLock(display));
1411 
1412 	if(!validateDisplay(display))
1413 	{
1414 		return error(EGL_BAD_DISPLAY, EGL_FALSE);
1415 	}
1416 
1417 	if(!display->isValidSync(eglSync))
1418 	{
1419 		return error(EGL_BAD_PARAMETER, EGL_FALSE);
1420 	}
1421 
1422 	display->destroySync(eglSync);
1423 
1424 	return success(EGL_TRUE);
1425 }
1426 
ClientWaitSyncKHR(EGLDisplay dpy,EGLSyncKHR sync,EGLint flags,EGLTimeKHR timeout)1427 EGLint EGLAPIENTRY ClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout)
1428 {
1429 	TRACE("(EGLDisplay dpy = %p, EGLSyncKHR sync = %p, EGLint flags = %x, EGLTimeKHR value = %llx)", dpy, sync, flags, timeout);
1430 
1431 	egl::Display *display = egl::Display::get(dpy);
1432 	FenceSync *eglSync = static_cast<FenceSync*>(sync);
1433 
1434 	RecursiveLockGuard lock(egl::getDisplayLock(display));
1435 
1436 	if(!validateDisplay(display))
1437 	{
1438 		return error(EGL_BAD_DISPLAY, EGL_FALSE);
1439 	}
1440 
1441 	if(!display->isValidSync(eglSync))
1442 	{
1443 		return error(EGL_BAD_PARAMETER, EGL_FALSE);
1444 	}
1445 
1446 	(void)flags;
1447 	(void)timeout;
1448 
1449 	if(!eglSync->isSignaled())
1450 	{
1451 		eglSync->wait();
1452 	}
1453 
1454 	return success(EGL_CONDITION_SATISFIED_KHR);
1455 }
1456 
GetSyncAttrib(EGLDisplay dpy,EGLSyncKHR sync,EGLint attribute,EGLAttrib * value)1457 EGLBoolean EGLAPIENTRY GetSyncAttrib(EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLAttrib *value)
1458 {
1459 	TRACE("(EGLDisplay dpy = %p, EGLSyncKHR sync = %p, EGLint attribute = %x, EGLAttrib *value = %p)", dpy, sync, attribute, value);
1460 
1461 	egl::Display *display = egl::Display::get(dpy);
1462 	FenceSync *eglSync = static_cast<FenceSync*>(sync);
1463 
1464 	RecursiveLockGuard lock(egl::getDisplayLock(display));
1465 
1466 	if(!validateDisplay(display))
1467 	{
1468 		return error(EGL_BAD_DISPLAY, EGL_FALSE);
1469 	}
1470 
1471 	if(!display->isValidSync(eglSync))
1472 	{
1473 		return error(EGL_BAD_PARAMETER, EGL_FALSE);
1474 	}
1475 
1476 	if(!value)
1477 	{
1478 		return error(EGL_BAD_PARAMETER, EGL_FALSE);
1479 	}
1480 
1481 	switch(attribute)
1482 	{
1483 	case EGL_SYNC_TYPE_KHR:
1484 		*value = EGL_SYNC_FENCE_KHR;
1485 		return success(EGL_TRUE);
1486 	case EGL_SYNC_STATUS_KHR:
1487 		eglSync->wait();   // TODO: Don't block. Just poll based on sw::Query.
1488 		*value = eglSync->isSignaled() ? EGL_SIGNALED_KHR : EGL_UNSIGNALED_KHR;
1489 		return success(EGL_TRUE);
1490 	case EGL_SYNC_CONDITION_KHR:
1491 		*value = EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR;
1492 		return success(EGL_TRUE);
1493 	default:
1494 		return error(EGL_BAD_ATTRIBUTE, EGL_FALSE);
1495 	}
1496 }
1497 
GetSyncAttribKHR(EGLDisplay dpy,EGLSyncKHR sync,EGLint attribute,EGLint * value)1498 EGLBoolean EGLAPIENTRY GetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value)
1499 {
1500 	EGLAttrib attrib_value;
1501 	EGLBoolean result = GetSyncAttrib(dpy, sync, attribute, &attrib_value);
1502 	*value = static_cast<EGLint>(attrib_value);
1503 	return result;
1504 }
1505 
GetProcAddress(const char * procname)1506 __eglMustCastToProperFunctionPointerType EGLAPIENTRY GetProcAddress(const char *procname)
1507 {
1508 	TRACE("(const char *procname = \"%s\")", procname);
1509 
1510 	struct Function
1511 	{
1512 		const char *name;
1513 		__eglMustCastToProperFunctionPointerType address;
1514 	};
1515 
1516 	struct CompareFunctor
1517 	{
1518 		bool operator()(const Function &a, const Function &b) const
1519 		{
1520 			return strcmp(a.name, b.name) < 0;
1521 		}
1522 	};
1523 
1524 	// This array must be kept sorted with respect to strcmp(), so that binary search works correctly.
1525 	// The Unix command "LC_COLLATE=C sort" will generate the correct order.
1526 	static const Function eglFunctions[] =
1527 	{
1528 		#define FUNCTION(name) {#name, (__eglMustCastToProperFunctionPointerType)name}
1529 
1530 		FUNCTION(eglBindAPI),
1531 		FUNCTION(eglBindTexImage),
1532 		FUNCTION(eglChooseConfig),
1533 		FUNCTION(eglClientWaitSync),
1534 		FUNCTION(eglClientWaitSyncKHR),
1535 		FUNCTION(eglCopyBuffers),
1536 		FUNCTION(eglCreateContext),
1537 		FUNCTION(eglCreateImage),
1538 		FUNCTION(eglCreateImageKHR),
1539 		FUNCTION(eglCreatePbufferFromClientBuffer),
1540 		FUNCTION(eglCreatePbufferSurface),
1541 		FUNCTION(eglCreatePixmapSurface),
1542 		FUNCTION(eglCreatePlatformPixmapSurface),
1543 		FUNCTION(eglCreatePlatformPixmapSurfaceEXT),
1544 		FUNCTION(eglCreatePlatformWindowSurface),
1545 		FUNCTION(eglCreatePlatformWindowSurfaceEXT),
1546 		FUNCTION(eglCreateSync),
1547 		FUNCTION(eglCreateSyncKHR),
1548 		FUNCTION(eglCreateWindowSurface),
1549 		FUNCTION(eglDestroyContext),
1550 		FUNCTION(eglDestroyImage),
1551 		FUNCTION(eglDestroyImageKHR),
1552 		FUNCTION(eglDestroySurface),
1553 		FUNCTION(eglDestroySync),
1554 		FUNCTION(eglDestroySyncKHR),
1555 		FUNCTION(eglGetConfigAttrib),
1556 		FUNCTION(eglGetConfigs),
1557 		FUNCTION(eglGetCurrentContext),
1558 		FUNCTION(eglGetCurrentDisplay),
1559 		FUNCTION(eglGetCurrentSurface),
1560 		FUNCTION(eglGetDisplay),
1561 		FUNCTION(eglGetError),
1562 		FUNCTION(eglGetPlatformDisplay),
1563 		FUNCTION(eglGetPlatformDisplayEXT),
1564 		FUNCTION(eglGetProcAddress),
1565 		FUNCTION(eglGetSyncAttrib),
1566 		FUNCTION(eglGetSyncAttribKHR),
1567 		FUNCTION(eglInitialize),
1568 		FUNCTION(eglMakeCurrent),
1569 		FUNCTION(eglQueryAPI),
1570 		FUNCTION(eglQueryContext),
1571 		FUNCTION(eglQueryString),
1572 		FUNCTION(eglQuerySurface),
1573 		FUNCTION(eglReleaseTexImage),
1574 		FUNCTION(eglReleaseThread),
1575 		FUNCTION(eglSurfaceAttrib),
1576 		FUNCTION(eglSwapBuffers),
1577 		FUNCTION(eglSwapInterval),
1578 		FUNCTION(eglTerminate),
1579 		FUNCTION(eglWaitClient),
1580 		FUNCTION(eglWaitGL),
1581 		FUNCTION(eglWaitNative),
1582 		FUNCTION(eglWaitSync),
1583 		FUNCTION(eglWaitSyncKHR),
1584 
1585 		#undef FUNCTION
1586 	};
1587 
1588 	static const size_t numFunctions = sizeof eglFunctions / sizeof(Function);
1589 	static const Function *const eglFunctionsEnd = eglFunctions + numFunctions;
1590 
1591 	Function needle;
1592 	needle.name = procname;
1593 
1594 	if(procname && strncmp("egl", procname, 3) == 0)
1595 	{
1596 		const Function *result = std::lower_bound(eglFunctions, eglFunctionsEnd, needle, CompareFunctor());
1597 		if (result != eglFunctionsEnd && strcmp(procname, result->name) == 0)
1598 		{
1599 			return success((__eglMustCastToProperFunctionPointerType)result->address);
1600 		}
1601 	}
1602 
1603 	if(libGLESv2)
1604 	{
1605 		__eglMustCastToProperFunctionPointerType proc = libGLESv2->es2GetProcAddress(procname);
1606 		if(proc) return success(proc);
1607 	}
1608 
1609 	if(libGLES_CM)
1610 	{
1611 		__eglMustCastToProperFunctionPointerType proc =  libGLES_CM->es1GetProcAddress(procname);
1612 		if(proc) return success(proc);
1613 	}
1614 
1615 	return success((__eglMustCastToProperFunctionPointerType)NULL);
1616 }
1617 }
1618