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.h"
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(__linux__)
29 #include "Main/libX11.hpp"
30 #endif
31
32 #include <string.h>
33
34 using namespace egl;
35
validateDisplay(egl::Display * display)36 static bool validateDisplay(egl::Display *display)
37 {
38 if(display == EGL_NO_DISPLAY)
39 {
40 return error(EGL_BAD_DISPLAY, false);
41 }
42
43 if(!display->isInitialized())
44 {
45 return error(EGL_NOT_INITIALIZED, false);
46 }
47
48 return true;
49 }
50
validateConfig(egl::Display * display,EGLConfig config)51 static bool validateConfig(egl::Display *display, EGLConfig config)
52 {
53 if(!validateDisplay(display))
54 {
55 return false;
56 }
57
58 if(!display->isValidConfig(config))
59 {
60 return error(EGL_BAD_CONFIG, false);
61 }
62
63 return true;
64 }
65
validateContext(egl::Display * display,egl::Context * context)66 static bool validateContext(egl::Display *display, egl::Context *context)
67 {
68 if(!validateDisplay(display))
69 {
70 return false;
71 }
72
73 if(!display->isValidContext(context))
74 {
75 return error(EGL_BAD_CONTEXT, false);
76 }
77
78 return true;
79 }
80
validateSurface(egl::Display * display,egl::Surface * surface)81 static bool validateSurface(egl::Display *display, egl::Surface *surface)
82 {
83 if(!validateDisplay(display))
84 {
85 return false;
86 }
87
88 if(!display->isValidSurface(surface))
89 {
90 return error(EGL_BAD_SURFACE, false);
91 }
92
93 return true;
94 }
95
96 namespace egl
97 {
GetError(void)98 EGLint GetError(void)
99 {
100 TRACE("()");
101
102 EGLint error = egl::getCurrentError();
103
104 if(error != EGL_SUCCESS)
105 {
106 egl::setCurrentError(EGL_SUCCESS);
107 }
108
109 return error;
110 }
111
GetDisplay(EGLNativeDisplayType display_id)112 EGLDisplay GetDisplay(EGLNativeDisplayType display_id)
113 {
114 TRACE("(EGLNativeDisplayType display_id = %p)", display_id);
115
116 if(display_id != EGL_DEFAULT_DISPLAY)
117 {
118 // FIXME: Check if display_id is the default display
119 }
120
121 #if defined(__linux__) && !defined(__ANDROID__)
122 if(!libX11)
123 {
124 return success(HEADLESS_DISPLAY);
125 }
126 #endif
127
128 return success(PRIMARY_DISPLAY); // We only support the default display
129 }
130
Initialize(EGLDisplay dpy,EGLint * major,EGLint * minor)131 EGLBoolean Initialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
132 {
133 TRACE("(EGLDisplay dpy = %p, EGLint *major = %p, EGLint *minor = %p)",
134 dpy, major, minor);
135
136 if(dpy == EGL_NO_DISPLAY)
137 {
138 return error(EGL_BAD_DISPLAY, EGL_FALSE);
139 }
140
141 egl::Display *display = egl::Display::get(dpy);
142
143 if(!display->initialize())
144 {
145 return error(EGL_NOT_INITIALIZED, EGL_FALSE);
146 }
147
148 if(major) *major = 1;
149 if(minor) *minor = 4;
150
151 return success(EGL_TRUE);
152 }
153
Terminate(EGLDisplay dpy)154 EGLBoolean Terminate(EGLDisplay dpy)
155 {
156 TRACE("(EGLDisplay dpy = %p)", dpy);
157
158 if(dpy == EGL_NO_DISPLAY)
159 {
160 return error(EGL_BAD_DISPLAY, EGL_FALSE);
161 }
162
163 egl::Display *display = egl::Display::get(dpy);
164
165 display->terminate();
166
167 return success(EGL_TRUE);
168 }
169
QueryString(EGLDisplay dpy,EGLint name)170 const char *QueryString(EGLDisplay dpy, EGLint name)
171 {
172 TRACE("(EGLDisplay dpy = %p, EGLint name = %d)", dpy, name);
173
174 #if defined(__linux__) && !defined(__ANDROID__)
175 if(dpy == EGL_NO_DISPLAY && name == EGL_EXTENSIONS)
176 {
177 return success("EGL_KHR_platform_gbm "
178 "EGL_KHR_platform_x11 "
179 "EGL_EXT_client_extensions "
180 "EGL_EXT_platform_base");
181 }
182 #endif
183
184 egl::Display *display = egl::Display::get(dpy);
185
186 if(!validateDisplay(display))
187 {
188 return nullptr;
189 }
190
191 switch(name)
192 {
193 case EGL_CLIENT_APIS:
194 return success("OpenGL_ES");
195 case EGL_EXTENSIONS:
196 return success("EGL_KHR_create_context "
197 "EGL_KHR_gl_texture_2D_image "
198 "EGL_KHR_gl_texture_cubemap_image "
199 "EGL_KHR_gl_renderbuffer_image "
200 "EGL_KHR_fence_sync "
201 "EGL_KHR_image_base "
202 "EGL_ANDROID_framebuffer_target "
203 "EGL_ANDROID_recordable");
204 case EGL_VENDOR:
205 return success("Google Inc.");
206 case EGL_VERSION:
207 return success("1.4 SwiftShader " VERSION_STRING);
208 }
209
210 return error(EGL_BAD_PARAMETER, (const char*)nullptr);
211 }
212
GetConfigs(EGLDisplay dpy,EGLConfig * configs,EGLint config_size,EGLint * num_config)213 EGLBoolean GetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config)
214 {
215 TRACE("(EGLDisplay dpy = %p, EGLConfig *configs = %p, "
216 "EGLint config_size = %d, EGLint *num_config = %p)",
217 dpy, configs, config_size, num_config);
218
219 egl::Display *display = egl::Display::get(dpy);
220
221 if(!validateDisplay(display))
222 {
223 return EGL_FALSE;
224 }
225
226 if(!num_config)
227 {
228 return error(EGL_BAD_PARAMETER, EGL_FALSE);
229 }
230
231 const EGLint attribList[] = {EGL_NONE};
232
233 if(!display->getConfigs(configs, attribList, config_size, num_config))
234 {
235 return error(EGL_BAD_ATTRIBUTE, EGL_FALSE);
236 }
237
238 return success(EGL_TRUE);
239 }
240
ChooseConfig(EGLDisplay dpy,const EGLint * attrib_list,EGLConfig * configs,EGLint config_size,EGLint * num_config)241 EGLBoolean ChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config)
242 {
243 TRACE("(EGLDisplay dpy = %p, const EGLint *attrib_list = %p, "
244 "EGLConfig *configs = %p, EGLint config_size = %d, EGLint *num_config = %p)",
245 dpy, attrib_list, configs, config_size, num_config);
246
247 egl::Display *display = egl::Display::get(dpy);
248
249 if(!validateDisplay(display))
250 {
251 return EGL_FALSE;
252 }
253
254 if(!num_config)
255 {
256 return error(EGL_BAD_PARAMETER, EGL_FALSE);
257 }
258
259 const EGLint attribList[] = {EGL_NONE};
260
261 if(!attrib_list)
262 {
263 attrib_list = attribList;
264 }
265
266 if(!display->getConfigs(configs, attrib_list, config_size, num_config))
267 {
268 return error(EGL_BAD_ATTRIBUTE, EGL_FALSE);
269 }
270
271 return success(EGL_TRUE);
272 }
273
GetConfigAttrib(EGLDisplay dpy,EGLConfig config,EGLint attribute,EGLint * value)274 EGLBoolean GetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value)
275 {
276 TRACE("(EGLDisplay dpy = %p, EGLConfig config = %p, EGLint attribute = %d, EGLint *value = %p)",
277 dpy, config, attribute, value);
278
279 egl::Display *display = egl::Display::get(dpy);
280
281 if(!validateConfig(display, config))
282 {
283 return EGL_FALSE;
284 }
285
286 if(!display->getConfigAttrib(config, attribute, value))
287 {
288 return error(EGL_BAD_ATTRIBUTE, EGL_FALSE);
289 }
290
291 return success(EGL_TRUE);
292 }
293
CreateWindowSurface(EGLDisplay dpy,EGLConfig config,EGLNativeWindowType window,const EGLint * attrib_list)294 EGLSurface CreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType window, const EGLint *attrib_list)
295 {
296 TRACE("(EGLDisplay dpy = %p, EGLConfig config = %p, EGLNativeWindowType win = %p, "
297 "const EGLint *attrib_list = %p)", dpy, config, window, attrib_list);
298
299 egl::Display *display = egl::Display::get(dpy);
300
301 if(!validateConfig(display, config))
302 {
303 return EGL_NO_SURFACE;
304 }
305
306 if(!display->isValidWindow(window))
307 {
308 return error(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
309 }
310
311 return display->createWindowSurface(window, config, attrib_list);
312 }
313
CreatePbufferSurface(EGLDisplay dpy,EGLConfig config,const EGLint * attrib_list)314 EGLSurface CreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list)
315 {
316 TRACE("(EGLDisplay dpy = %p, EGLConfig config = %p, const EGLint *attrib_list = %p)",
317 dpy, config, attrib_list);
318
319 egl::Display *display = egl::Display::get(dpy);
320
321 if(!validateConfig(display, config))
322 {
323 return EGL_NO_SURFACE;
324 }
325
326 return display->createPBufferSurface(config, attrib_list);
327 }
328
CreatePixmapSurface(EGLDisplay dpy,EGLConfig config,EGLNativePixmapType pixmap,const EGLint * attrib_list)329 EGLSurface CreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list)
330 {
331 TRACE("(EGLDisplay dpy = %p, EGLConfig config = %p, EGLNativePixmapType pixmap = %p, "
332 "const EGLint *attrib_list = %p)", dpy, config, pixmap, attrib_list);
333
334 egl::Display *display = egl::Display::get(dpy);
335
336 if(!validateConfig(display, config))
337 {
338 return EGL_NO_SURFACE;
339 }
340
341 UNIMPLEMENTED(); // FIXME
342
343 return success(EGL_NO_SURFACE);
344 }
345
DestroySurface(EGLDisplay dpy,EGLSurface surface)346 EGLBoolean DestroySurface(EGLDisplay dpy, EGLSurface surface)
347 {
348 TRACE("(EGLDisplay dpy = %p, EGLSurface surface = %p)", dpy, surface);
349
350 egl::Display *display = egl::Display::get(dpy);
351 egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);
352
353 if(!validateSurface(display, eglSurface))
354 {
355 return EGL_FALSE;
356 }
357
358 if(surface == EGL_NO_SURFACE)
359 {
360 return error(EGL_BAD_SURFACE, EGL_FALSE);
361 }
362
363 display->destroySurface((egl::Surface*)surface);
364
365 return success(EGL_TRUE);
366 }
367
QuerySurface(EGLDisplay dpy,EGLSurface surface,EGLint attribute,EGLint * value)368 EGLBoolean QuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value)
369 {
370 TRACE("(EGLDisplay dpy = %p, EGLSurface surface = %p, EGLint attribute = %d, EGLint *value = %p)",
371 dpy, surface, attribute, value);
372
373 egl::Display *display = egl::Display::get(dpy);
374 egl::Surface *eglSurface = (egl::Surface*)surface;
375
376 if(!validateSurface(display, eglSurface))
377 {
378 return EGL_FALSE;
379 }
380
381 if(surface == EGL_NO_SURFACE)
382 {
383 return error(EGL_BAD_SURFACE, EGL_FALSE);
384 }
385
386 switch(attribute)
387 {
388 case EGL_VG_ALPHA_FORMAT:
389 UNIMPLEMENTED(); // FIXME
390 break;
391 case EGL_VG_COLORSPACE:
392 UNIMPLEMENTED(); // FIXME
393 break;
394 case EGL_CONFIG_ID:
395 *value = eglSurface->getConfigID();
396 break;
397 case EGL_HEIGHT:
398 *value = eglSurface->getHeight();
399 break;
400 case EGL_HORIZONTAL_RESOLUTION:
401 UNIMPLEMENTED(); // FIXME
402 break;
403 case EGL_LARGEST_PBUFFER:
404 if(eglSurface->isPBufferSurface()) // For a window or pixmap surface, the contents of *value are not modified.
405 {
406 *value = eglSurface->getLargestPBuffer();
407 }
408 break;
409 case EGL_MIPMAP_TEXTURE:
410 UNIMPLEMENTED(); // FIXME
411 break;
412 case EGL_MIPMAP_LEVEL:
413 UNIMPLEMENTED(); // FIXME
414 break;
415 case EGL_MULTISAMPLE_RESOLVE:
416 UNIMPLEMENTED(); // FIXME
417 break;
418 case EGL_PIXEL_ASPECT_RATIO:
419 *value = eglSurface->getPixelAspectRatio();
420 break;
421 case EGL_RENDER_BUFFER:
422 *value = eglSurface->getRenderBuffer();
423 break;
424 case EGL_SWAP_BEHAVIOR:
425 *value = eglSurface->getSwapBehavior();
426 break;
427 case EGL_TEXTURE_FORMAT:
428 *value = eglSurface->getTextureFormat();
429 break;
430 case EGL_TEXTURE_TARGET:
431 *value = eglSurface->getTextureTarget();
432 break;
433 case EGL_VERTICAL_RESOLUTION:
434 UNIMPLEMENTED(); // FIXME
435 break;
436 case EGL_WIDTH:
437 *value = eglSurface->getWidth();
438 break;
439 default:
440 return error(EGL_BAD_ATTRIBUTE, EGL_FALSE);
441 }
442
443 return success(EGL_TRUE);
444 }
445
BindAPI(EGLenum api)446 EGLBoolean BindAPI(EGLenum api)
447 {
448 TRACE("(EGLenum api = 0x%X)", api);
449
450 switch(api)
451 {
452 case EGL_OPENGL_API:
453 case EGL_OPENVG_API:
454 return error(EGL_BAD_PARAMETER, EGL_FALSE); // Not supported by this implementation
455 case EGL_OPENGL_ES_API:
456 break;
457 default:
458 return error(EGL_BAD_PARAMETER, EGL_FALSE);
459 }
460
461 egl::setCurrentAPI(api);
462
463 return success(EGL_TRUE);
464 }
465
QueryAPI(void)466 EGLenum QueryAPI(void)
467 {
468 TRACE("()");
469
470 EGLenum API = egl::getCurrentAPI();
471
472 return success(API);
473 }
474
WaitClient(void)475 EGLBoolean WaitClient(void)
476 {
477 TRACE("()");
478
479 UNIMPLEMENTED(); // FIXME
480
481 return success(EGL_FALSE);
482 }
483
ReleaseThread(void)484 EGLBoolean ReleaseThread(void)
485 {
486 TRACE("()");
487
488 eglMakeCurrent(EGL_NO_DISPLAY, EGL_NO_CONTEXT, EGL_NO_SURFACE, EGL_NO_SURFACE);
489
490 return success(EGL_TRUE);
491 }
492
CreatePbufferFromClientBuffer(EGLDisplay dpy,EGLenum buftype,EGLClientBuffer buffer,EGLConfig config,const EGLint * attrib_list)493 EGLSurface CreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list)
494 {
495 TRACE("(EGLDisplay dpy = %p, EGLenum buftype = 0x%X, EGLClientBuffer buffer = %p, "
496 "EGLConfig config = %p, const EGLint *attrib_list = %p)",
497 dpy, buftype, buffer, config, attrib_list);
498
499 UNIMPLEMENTED();
500
501 return error(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
502 }
503
SurfaceAttrib(EGLDisplay dpy,EGLSurface surface,EGLint attribute,EGLint value)504 EGLBoolean SurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
505 {
506 TRACE("(EGLDisplay dpy = %p, EGLSurface surface = %p, EGLint attribute = %d, EGLint value = %d)",
507 dpy, surface, attribute, value);
508
509 egl::Display *display = egl::Display::get(dpy);
510 egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);
511
512 if(!validateSurface(display, eglSurface))
513 {
514 return EGL_FALSE;
515 }
516
517 switch(attribute)
518 {
519 case EGL_SWAP_BEHAVIOR:
520 if(value == EGL_BUFFER_PRESERVED)
521 {
522 if(!(eglSurface->getSurfaceType() & EGL_SWAP_BEHAVIOR_PRESERVED_BIT))
523 {
524 return error(EGL_BAD_MATCH, EGL_FALSE);
525 }
526 }
527 else if(value != EGL_BUFFER_DESTROYED)
528 {
529 return error(EGL_BAD_PARAMETER, EGL_FALSE);
530 }
531 eglSurface->setSwapBehavior(value);
532 break;
533 default:
534 UNIMPLEMENTED(); // FIXME
535 }
536
537 return success(EGL_TRUE);
538 }
539
BindTexImage(EGLDisplay dpy,EGLSurface surface,EGLint buffer)540 EGLBoolean BindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
541 {
542 TRACE("(EGLDisplay dpy = %p, EGLSurface surface = %p, EGLint buffer = %d)", dpy, surface, buffer);
543
544 egl::Display *display = egl::Display::get(dpy);
545 egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);
546
547 if(!validateSurface(display, eglSurface))
548 {
549 return EGL_FALSE;
550 }
551
552 if(buffer != EGL_BACK_BUFFER)
553 {
554 return error(EGL_BAD_PARAMETER, EGL_FALSE);
555 }
556
557 if(surface == EGL_NO_SURFACE || eglSurface->isWindowSurface())
558 {
559 return error(EGL_BAD_SURFACE, EGL_FALSE);
560 }
561
562 if(eglSurface->getBoundTexture())
563 {
564 return error(EGL_BAD_ACCESS, EGL_FALSE);
565 }
566
567 if(eglSurface->getTextureFormat() == EGL_NO_TEXTURE)
568 {
569 return error(EGL_BAD_MATCH, EGL_FALSE);
570 }
571
572 egl::Context *context = egl::getCurrentContext();
573
574 if(context)
575 {
576 context->bindTexImage(eglSurface);
577 }
578
579 return success(EGL_TRUE);
580 }
581
ReleaseTexImage(EGLDisplay dpy,EGLSurface surface,EGLint buffer)582 EGLBoolean ReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
583 {
584 TRACE("(EGLDisplay dpy = %p, EGLSurface surface = %p, EGLint buffer = %d)", dpy, surface, buffer);
585
586 egl::Display *display = egl::Display::get(dpy);
587 egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);
588
589 if(!validateSurface(display, eglSurface))
590 {
591 return EGL_FALSE;
592 }
593
594 if(buffer != EGL_BACK_BUFFER)
595 {
596 return error(EGL_BAD_PARAMETER, EGL_FALSE);
597 }
598
599 if(surface == EGL_NO_SURFACE || eglSurface->isWindowSurface())
600 {
601 return error(EGL_BAD_SURFACE, EGL_FALSE);
602 }
603
604 if(eglSurface->getTextureFormat() == EGL_NO_TEXTURE)
605 {
606 return error(EGL_BAD_MATCH, EGL_FALSE);
607 }
608
609 egl::Texture *texture = eglSurface->getBoundTexture();
610
611 if(texture)
612 {
613 texture->releaseTexImage();
614 }
615
616 return success(EGL_TRUE);
617 }
618
SwapInterval(EGLDisplay dpy,EGLint interval)619 EGLBoolean SwapInterval(EGLDisplay dpy, EGLint interval)
620 {
621 TRACE("(EGLDisplay dpy = %p, EGLint interval = %d)", dpy, interval);
622
623 egl::Display *display = egl::Display::get(dpy);
624 egl::Context *context = egl::getCurrentContext();
625
626 if(!validateContext(display, context))
627 {
628 return EGL_FALSE;
629 }
630
631 egl::Surface *draw_surface = static_cast<egl::Surface*>(egl::getCurrentDrawSurface());
632
633 if(!draw_surface)
634 {
635 return error(EGL_BAD_SURFACE, EGL_FALSE);
636 }
637
638 draw_surface->setSwapInterval(interval);
639
640 return success(EGL_TRUE);
641 }
642
CreateContext(EGLDisplay dpy,EGLConfig config,EGLContext share_context,const EGLint * attrib_list)643 EGLContext CreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list)
644 {
645 TRACE("(EGLDisplay dpy = %p, EGLConfig config = %p, EGLContext share_context = %p, "
646 "const EGLint *attrib_list = %p)", dpy, config, share_context, attrib_list);
647
648 EGLint majorVersion = 1;
649 EGLint minorVersion = 0;
650
651 if(attrib_list)
652 {
653 for(const EGLint* attribute = attrib_list; attribute[0] != EGL_NONE; attribute += 2)
654 {
655 switch(attribute[0])
656 {
657 case EGL_CONTEXT_MAJOR_VERSION_KHR: // This token is an alias for EGL_CONTEXT_CLIENT_VERSION
658 majorVersion = attribute[1];
659 break;
660 case EGL_CONTEXT_MINOR_VERSION_KHR:
661 minorVersion = attribute[1];
662 break;
663 case EGL_CONTEXT_FLAGS_KHR:
664 switch(attribute[1])
665 {
666 case EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR:
667 // According to the EGL_KHR_create_context spec:
668 // "Khronos is still defining the expected and required features of debug contexts, so
669 // implementations are currently free to implement "debug contexts" with little or no debug
670 // functionality. However, OpenGL and OpenGL ES implementations supporting the GL_KHR_debug
671 // extension should enable it when this bit is set."
672 break;
673 case EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR:
674 case EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR:
675 // These bits are for OpenGL contexts only, not OpenGL ES contexts
676 return error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
677 default:
678 return error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
679 }
680 break;
681 case EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR:
682 switch(attribute[1])
683 {
684 case EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR:
685 case EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR:
686 // These bits are for OpenGL contexts only, not OpenGL ES contexts
687 return error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
688 default:
689 return error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
690 }
691 break;
692 case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR:
693 switch(attribute[1])
694 {
695 case EGL_NO_RESET_NOTIFICATION_KHR:
696 case EGL_LOSE_CONTEXT_ON_RESET_KHR:
697 // These bits are for OpenGL contexts only, not OpenGL ES contexts
698 return error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
699 default:
700 return error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
701 }
702 break;
703 default:
704 return error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
705 }
706 }
707 }
708
709 switch(majorVersion)
710 {
711 case 1:
712 if(minorVersion != 0 && minorVersion != 1)
713 {
714 // 1.X: Only OpenGL ES 1.0 and 1.1 contexts are supported
715 return error(EGL_BAD_MATCH, EGL_NO_CONTEXT);
716 }
717 break;
718 case 2:
719 case 3:
720 if(minorVersion != 0)
721 {
722 // 2.X and 3.X: Only OpenGL ES 2.0 and 3.0 contexts are currently supported
723 return error(EGL_BAD_MATCH, EGL_NO_CONTEXT);
724 }
725 break;
726 default:
727 return error(EGL_BAD_MATCH, EGL_NO_CONTEXT);
728 }
729
730 egl::Display *display = egl::Display::get(dpy);
731 egl::Context *shareContext = static_cast<egl::Context*>(share_context);
732
733 if(!validateConfig(display, config))
734 {
735 return EGL_NO_CONTEXT;
736 }
737
738 if(shareContext && shareContext->getClientVersion() != majorVersion)
739 {
740 return error(EGL_BAD_CONTEXT, EGL_NO_CONTEXT);
741 }
742
743 return display->createContext(config, shareContext, majorVersion);
744 }
745
DestroyContext(EGLDisplay dpy,EGLContext ctx)746 EGLBoolean DestroyContext(EGLDisplay dpy, EGLContext ctx)
747 {
748 TRACE("(EGLDisplay dpy = %p, EGLContext ctx = %p)", dpy, ctx);
749
750 egl::Display *display = egl::Display::get(dpy);
751 egl::Context *context = static_cast<egl::Context*>(ctx);
752
753 if(!validateContext(display, context))
754 {
755 return EGL_FALSE;
756 }
757
758 if(ctx == EGL_NO_CONTEXT)
759 {
760 return error(EGL_BAD_CONTEXT, EGL_FALSE);
761 }
762
763 display->destroyContext(context);
764
765 return success(EGL_TRUE);
766 }
767
MakeCurrent(EGLDisplay dpy,EGLSurface draw,EGLSurface read,EGLContext ctx)768 EGLBoolean MakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx)
769 {
770 TRACE("(EGLDisplay dpy = %p, EGLSurface draw = %p, EGLSurface read = %p, EGLContext ctx = %p)",
771 dpy, draw, read, ctx);
772
773 egl::Display *display = egl::Display::get(dpy);
774 egl::Context *context = static_cast<egl::Context*>(ctx);
775 egl::Surface *drawSurface = static_cast<egl::Surface*>(draw);
776 egl::Surface *readSurface = static_cast<egl::Surface*>(read);
777
778 if(ctx != EGL_NO_CONTEXT || draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE)
779 {
780 if(!validateDisplay(display))
781 {
782 return EGL_FALSE;
783 }
784 }
785
786 if(ctx == EGL_NO_CONTEXT && (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE))
787 {
788 return error(EGL_BAD_MATCH, EGL_FALSE);
789 }
790
791 if(ctx != EGL_NO_CONTEXT && !validateContext(display, context))
792 {
793 return EGL_FALSE;
794 }
795
796 if((draw != EGL_NO_SURFACE && !validateSurface(display, drawSurface)) ||
797 (read != EGL_NO_SURFACE && !validateSurface(display, readSurface)))
798 {
799 return EGL_FALSE;
800 }
801
802 if((draw != EGL_NO_SURFACE) ^ (read != EGL_NO_SURFACE))
803 {
804 return error(EGL_BAD_MATCH, EGL_FALSE);
805 }
806
807 if(draw != read)
808 {
809 UNIMPLEMENTED(); // FIXME
810 }
811
812 egl::setCurrentDisplay(dpy);
813 egl::setCurrentDrawSurface(drawSurface);
814 egl::setCurrentReadSurface(readSurface);
815 egl::setCurrentContext(context);
816
817 if(context)
818 {
819 context->makeCurrent(drawSurface);
820 }
821
822 return success(EGL_TRUE);
823 }
824
GetCurrentContext(void)825 EGLContext GetCurrentContext(void)
826 {
827 TRACE("()");
828
829 EGLContext context = egl::getCurrentContext();
830
831 return success(context);
832 }
833
GetCurrentSurface(EGLint readdraw)834 EGLSurface GetCurrentSurface(EGLint readdraw)
835 {
836 TRACE("(EGLint readdraw = %d)", readdraw);
837
838 if(readdraw == EGL_READ)
839 {
840 EGLSurface read = egl::getCurrentReadSurface();
841 return success(read);
842 }
843 else if(readdraw == EGL_DRAW)
844 {
845 EGLSurface draw = egl::getCurrentDrawSurface();
846 return success(draw);
847 }
848 else
849 {
850 return error(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
851 }
852 }
853
GetCurrentDisplay(void)854 EGLDisplay GetCurrentDisplay(void)
855 {
856 TRACE("()");
857
858 return success(egl::getCurrentDisplay());
859 }
860
QueryContext(EGLDisplay dpy,EGLContext ctx,EGLint attribute,EGLint * value)861 EGLBoolean QueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value)
862 {
863 TRACE("(EGLDisplay dpy = %p, EGLContext ctx = %p, EGLint attribute = %d, EGLint *value = %p)",
864 dpy, ctx, attribute, value);
865
866 egl::Display *display = egl::Display::get(dpy);
867 egl::Context *context = static_cast<egl::Context*>(ctx);
868
869 if(!validateContext(display, context))
870 {
871 return EGL_FALSE;
872 }
873
874 UNIMPLEMENTED(); // FIXME
875
876 return success(0);
877 }
878
WaitGL(void)879 EGLBoolean WaitGL(void)
880 {
881 TRACE("()");
882
883 UNIMPLEMENTED(); // FIXME
884
885 return success(EGL_FALSE);
886 }
887
WaitNative(EGLint engine)888 EGLBoolean WaitNative(EGLint engine)
889 {
890 TRACE("(EGLint engine = %d)", engine);
891
892 UNIMPLEMENTED(); // FIXME
893
894 return success(EGL_FALSE);
895 }
896
SwapBuffers(EGLDisplay dpy,EGLSurface surface)897 EGLBoolean SwapBuffers(EGLDisplay dpy, EGLSurface surface)
898 {
899 TRACE("(EGLDisplay dpy = %p, EGLSurface surface = %p)", dpy, surface);
900
901 egl::Display *display = egl::Display::get(dpy);
902 egl::Surface *eglSurface = (egl::Surface*)surface;
903
904 if(!validateSurface(display, eglSurface))
905 {
906 return EGL_FALSE;
907 }
908
909 if(surface == EGL_NO_SURFACE)
910 {
911 return error(EGL_BAD_SURFACE, EGL_FALSE);
912 }
913
914 eglSurface->swap();
915
916 return success(EGL_TRUE);
917 }
918
CopyBuffers(EGLDisplay dpy,EGLSurface surface,EGLNativePixmapType target)919 EGLBoolean CopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target)
920 {
921 TRACE("(EGLDisplay dpy = %p, EGLSurface surface = %p, EGLNativePixmapType target = %p)", dpy, surface, target);
922
923 egl::Display *display = egl::Display::get(dpy);
924 egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);
925
926 if(!validateSurface(display, eglSurface))
927 {
928 return EGL_FALSE;
929 }
930
931 UNIMPLEMENTED(); // FIXME
932
933 return success(EGL_FALSE);
934 }
935
CreateImageKHR(EGLDisplay dpy,EGLContext ctx,EGLenum target,EGLClientBuffer buffer,const EGLint * attrib_list)936 EGLImageKHR CreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list)
937 {
938 TRACE("(EGLDisplay dpy = %p, EGLContext ctx = %p, EGLenum target = 0x%X, buffer = %p, const EGLint attrib_list = %p)", dpy, ctx, target, buffer, attrib_list);
939
940 egl::Display *display = egl::Display::get(dpy);
941 egl::Context *context = static_cast<egl::Context*>(ctx);
942
943 if(!validateDisplay(display))
944 {
945 return error(EGL_BAD_DISPLAY, EGL_NO_IMAGE_KHR);
946 }
947
948 if(context != EGL_NO_CONTEXT && !display->isValidContext(context))
949 {
950 return error(EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR);
951 }
952
953 EGLenum imagePreserved = EGL_FALSE;
954 GLuint textureLevel = 0;
955 if(attrib_list)
956 {
957 for(const EGLint *attribute = attrib_list; attribute[0] != EGL_NONE; attribute += 2)
958 {
959 if(attribute[0] == EGL_IMAGE_PRESERVED_KHR)
960 {
961 imagePreserved = attribute[1];
962 }
963 else if(attribute[0] == EGL_GL_TEXTURE_LEVEL_KHR)
964 {
965 textureLevel = attribute[1];
966 }
967 else
968 {
969 return error(EGL_BAD_ATTRIBUTE, EGL_NO_IMAGE_KHR);
970 }
971 }
972 }
973
974 #if defined(__ANDROID__)
975 if(target == EGL_NATIVE_BUFFER_ANDROID)
976 {
977 ANativeWindowBuffer *nativeBuffer = reinterpret_cast<ANativeWindowBuffer*>(buffer);
978
979 if(!nativeBuffer || GLPixelFormatFromAndroid(nativeBuffer->format) == GL_NONE)
980 {
981 ALOGW("%s badness unsupported HAL format=%x", __FUNCTION__, nativeBuffer ? nativeBuffer->format : 0);
982 return error(EGL_BAD_ATTRIBUTE, EGL_NO_IMAGE_KHR);
983 }
984
985 return success(new AndroidNativeImage(nativeBuffer));
986 }
987 #endif
988
989 GLuint name = reinterpret_cast<intptr_t>(buffer);
990
991 if(name == 0)
992 {
993 return error(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
994 }
995
996 EGLenum validationResult = context->validateSharedImage(target, name, textureLevel);
997
998 if(validationResult != EGL_SUCCESS)
999 {
1000 return error(validationResult, EGL_NO_IMAGE_KHR);
1001 }
1002
1003 egl::Image *image = context->createSharedImage(target, name, textureLevel);
1004
1005 if(!image)
1006 {
1007 return error(EGL_BAD_MATCH, EGL_NO_IMAGE_KHR);
1008 }
1009
1010 if(image->getDepth() > 1)
1011 {
1012 return error(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
1013 }
1014
1015 return success((EGLImageKHR)image);
1016 }
1017
DestroyImageKHR(EGLDisplay dpy,EGLImageKHR image)1018 EGLBoolean DestroyImageKHR(EGLDisplay dpy, EGLImageKHR image)
1019 {
1020 TRACE("(EGLDisplay dpy = %p, EGLImageKHR image = %p)", dpy, image);
1021
1022 egl::Display *display = egl::Display::get(dpy);
1023
1024 if(!validateDisplay(display))
1025 {
1026 return error(EGL_BAD_DISPLAY, EGL_FALSE);
1027 }
1028
1029 if(!image)
1030 {
1031 return error(EGL_BAD_PARAMETER, EGL_FALSE);
1032 }
1033
1034 egl::Image *glImage = static_cast<egl::Image*>(image);
1035 glImage->destroyShared();
1036
1037 return success(EGL_TRUE);
1038 }
1039
GetPlatformDisplayEXT(EGLenum platform,void * native_display,const EGLint * attrib_list)1040 EGLDisplay GetPlatformDisplayEXT(EGLenum platform, void *native_display, const EGLint *attrib_list)
1041 {
1042 TRACE("(EGLenum platform = 0x%X, void *native_display = %p, const EGLint *attrib_list = %p)", platform, native_display, attrib_list);
1043
1044 switch(platform)
1045 {
1046 #if defined(__linux__) && !defined(__ANDROID__)
1047 case EGL_PLATFORM_X11_EXT: break;
1048 case EGL_PLATFORM_GBM_KHR: break;
1049 #endif
1050 default:
1051 return error(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
1052 }
1053
1054 #if defined(__linux__) && !defined(__ANDROID__)
1055 if(platform == EGL_PLATFORM_X11_EXT)
1056 {
1057 if(!libX11)
1058 {
1059 return error(EGL_BAD_ATTRIBUTE, EGL_NO_DISPLAY);
1060 }
1061
1062 if(native_display != (void*)EGL_DEFAULT_DISPLAY || attrib_list != NULL)
1063 {
1064 return error(EGL_BAD_ATTRIBUTE, EGL_NO_DISPLAY); // Unimplemented
1065 }
1066 }
1067 else if(platform == EGL_PLATFORM_GBM_KHR)
1068 {
1069 if(native_display != (void*)EGL_DEFAULT_DISPLAY || attrib_list != NULL)
1070 {
1071 return error(EGL_BAD_ATTRIBUTE, EGL_NO_DISPLAY); // Unimplemented
1072 }
1073
1074 return success(HEADLESS_DISPLAY);
1075 }
1076 #endif
1077
1078 return success(PRIMARY_DISPLAY); // We only support the default display
1079 }
1080
CreatePlatformWindowSurfaceEXT(EGLDisplay dpy,EGLConfig config,void * native_window,const EGLint * attrib_list)1081 EGLSurface CreatePlatformWindowSurfaceEXT(EGLDisplay dpy, EGLConfig config, void *native_window, const EGLint *attrib_list)
1082 {
1083 return CreateWindowSurface(dpy, config, (EGLNativeWindowType)native_window, attrib_list);
1084 }
1085
CreatePlatformPixmapSurfaceEXT(EGLDisplay dpy,EGLConfig config,void * native_pixmap,const EGLint * attrib_list)1086 EGLSurface CreatePlatformPixmapSurfaceEXT(EGLDisplay dpy, EGLConfig config, void *native_pixmap, const EGLint *attrib_list)
1087 {
1088 return CreatePixmapSurface(dpy, config, (EGLNativePixmapType)native_pixmap, attrib_list);
1089 }
1090
CreateSyncKHR(EGLDisplay dpy,EGLenum type,const EGLint * attrib_list)1091 EGLSyncKHR CreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list)
1092 {
1093 TRACE("(EGLDisplay dpy = %p, EGLunum type = %x, EGLint *attrib_list=%p)", dpy, type, attrib_list);
1094
1095 egl::Display *display = egl::Display::get(dpy);
1096
1097 if(!validateDisplay(display))
1098 {
1099 return error(EGL_BAD_DISPLAY, EGL_NO_SYNC_KHR);
1100 }
1101
1102 if(type != EGL_SYNC_FENCE_KHR)
1103 {
1104 return error(EGL_BAD_ATTRIBUTE, EGL_NO_SYNC_KHR);
1105 }
1106
1107 if(attrib_list && attrib_list[0] != EGL_NONE)
1108 {
1109 return error(EGL_BAD_ATTRIBUTE, EGL_NO_SYNC_KHR);
1110 }
1111
1112 egl::Context *context = egl::getCurrentContext();
1113
1114 if(!validateContext(display, context))
1115 {
1116 return error(EGL_BAD_MATCH, EGL_NO_SYNC_KHR);
1117 }
1118
1119 EGLSyncKHR sync = display->createSync(context);
1120
1121 return success(sync);
1122 }
1123
DestroySyncKHR(EGLDisplay dpy,EGLSyncKHR sync)1124 EGLBoolean DestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync)
1125 {
1126 TRACE("(EGLDisplay dpy = %p, EGLSyncKHR sync = %p)", dpy, sync);
1127
1128 egl::Display *display = egl::Display::get(dpy);
1129 FenceSync *eglSync = static_cast<FenceSync*>(sync);
1130
1131 if(!validateDisplay(display))
1132 {
1133 return error(EGL_BAD_DISPLAY, EGL_FALSE);
1134 }
1135
1136 if(!display->isValidSync(eglSync))
1137 {
1138 return error(EGL_BAD_PARAMETER, EGL_FALSE);
1139 }
1140
1141 display->destroySync(eglSync);
1142
1143 return success(EGL_TRUE);
1144 }
1145
ClientWaitSyncKHR(EGLDisplay dpy,EGLSyncKHR sync,EGLint flags,EGLTimeKHR timeout)1146 EGLint ClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout)
1147 {
1148 TRACE("(EGLDisplay dpy = %p, EGLSyncKHR sync = %p, EGLint flags = %x, EGLTimeKHR value = %llx)", dpy, sync, flags, timeout);
1149
1150 egl::Display *display = egl::Display::get(dpy);
1151 FenceSync *eglSync = static_cast<FenceSync*>(sync);
1152
1153 if(!validateDisplay(display))
1154 {
1155 return error(EGL_BAD_DISPLAY, EGL_FALSE);
1156 }
1157
1158 if(!display->isValidSync(eglSync))
1159 {
1160 return error(EGL_BAD_PARAMETER, EGL_FALSE);
1161 }
1162
1163 (void)flags;
1164 (void)timeout;
1165
1166 if(!eglSync->isSignaled())
1167 {
1168 eglSync->wait();
1169 }
1170
1171 return success(EGL_CONDITION_SATISFIED_KHR);
1172 }
1173
GetSyncAttribKHR(EGLDisplay dpy,EGLSyncKHR sync,EGLint attribute,EGLint * value)1174 EGLBoolean GetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value)
1175 {
1176 TRACE("(EGLDisplay dpy = %p, EGLSyncKHR sync = %p, EGLint attribute = %x, EGLint *value = %p)", dpy, sync, attribute, value);
1177
1178 egl::Display *display = egl::Display::get(dpy);
1179 FenceSync *eglSync = static_cast<FenceSync*>(sync);
1180
1181 if(!validateDisplay(display))
1182 {
1183 return error(EGL_BAD_DISPLAY, EGL_FALSE);
1184 }
1185
1186 if(!display->isValidSync(eglSync))
1187 {
1188 return error(EGL_BAD_PARAMETER, EGL_FALSE);
1189 }
1190
1191 switch(attribute)
1192 {
1193 case EGL_SYNC_TYPE_KHR:
1194 *value = EGL_SYNC_FENCE_KHR;
1195 return success(EGL_TRUE);
1196 case EGL_SYNC_STATUS_KHR:
1197 eglSync->wait(); // TODO: Don't block. Just poll based on sw::Query.
1198 *value = eglSync->isSignaled() ? EGL_SIGNALED_KHR : EGL_UNSIGNALED_KHR;
1199 return success(EGL_TRUE);
1200 case EGL_SYNC_CONDITION_KHR:
1201 *value = EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR;
1202 return success(EGL_TRUE);
1203 default:
1204 return error(EGL_BAD_ATTRIBUTE, EGL_FALSE);
1205 }
1206 }
1207
GetProcAddress(const char * procname)1208 __eglMustCastToProperFunctionPointerType GetProcAddress(const char *procname)
1209 {
1210 TRACE("(const char *procname = \"%s\")", procname);
1211
1212 struct Extension
1213 {
1214 const char *name;
1215 __eglMustCastToProperFunctionPointerType address;
1216 };
1217
1218 static const Extension eglExtensions[] =
1219 {
1220 #define EXTENSION(name) {#name, (__eglMustCastToProperFunctionPointerType)name}
1221
1222 EXTENSION(eglCreateImageKHR),
1223 EXTENSION(eglDestroyImageKHR),
1224 EXTENSION(eglGetPlatformDisplayEXT),
1225 EXTENSION(eglCreatePlatformWindowSurfaceEXT),
1226 EXTENSION(eglCreatePlatformPixmapSurfaceEXT),
1227 EXTENSION(eglCreateSyncKHR),
1228 EXTENSION(eglDestroySyncKHR),
1229 EXTENSION(eglClientWaitSyncKHR),
1230 EXTENSION(eglGetSyncAttribKHR),
1231
1232 #undef EXTENSION
1233 };
1234
1235 for(unsigned int ext = 0; ext < sizeof(eglExtensions) / sizeof(Extension); ext++)
1236 {
1237 if(strcmp(procname, eglExtensions[ext].name) == 0)
1238 {
1239 return success((__eglMustCastToProperFunctionPointerType)eglExtensions[ext].address);
1240 }
1241 }
1242
1243 if(libGLESv2)
1244 {
1245 __eglMustCastToProperFunctionPointerType proc = libGLESv2->es2GetProcAddress(procname);
1246 if(proc) return success(proc);
1247 }
1248
1249 if(libGLES_CM)
1250 {
1251 __eglMustCastToProperFunctionPointerType proc = libGLES_CM->es1GetProcAddress(procname);
1252 if(proc) return success(proc);
1253 }
1254
1255 return success((__eglMustCastToProperFunctionPointerType)NULL);
1256 }
1257 }
1258