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