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