blob: 4a1998fcb5f6c734c5024aaebfff7cb0576c1e6a [file] [log] [blame]
Nicolas Capens0bac2852016-05-07 06:09:58 -04001// 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"
Alexis Hetu2f48bcb2016-12-05 12:43:27 -050019#include "EGLSurface.h"
Nicolas Capens0bac2852016-05-07 06:09:58 -040020#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
34using namespace egl;
35
36static 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
51static 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
66static 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
81static 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
96namespace egl
97{
98EGLint 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
112EGLDisplay 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
131EGLBoolean 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
154EGLBoolean 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
170const 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:
Alexis Hetub75bb022016-05-18 11:43:43 -0400196 return success("EGL_KHR_create_context "
197 "EGL_KHR_gl_texture_2D_image "
Nicolas Capens0bac2852016-05-07 06:09:58 -0400198 "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
213EGLBoolean 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
241EGLBoolean 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
274EGLBoolean 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
294EGLSurface 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
314EGLSurface 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
329EGLSurface 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
346EGLBoolean 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
368EGLBoolean 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
446EGLBoolean 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
466EGLenum QueryAPI(void)
467{
468 TRACE("()");
469
470 EGLenum API = egl::getCurrentAPI();
471
472 return success(API);
473}
474
475EGLBoolean WaitClient(void)
476{
477 TRACE("()");
478
479 UNIMPLEMENTED(); // FIXME
480
481 return success(EGL_FALSE);
482}
483
484EGLBoolean ReleaseThread(void)
485{
486 TRACE("()");
487
Nicolas Capenscc5c7d92016-06-13 14:35:11 -0400488 detachThread();
Nicolas Capens0bac2852016-05-07 06:09:58 -0400489
490 return success(EGL_TRUE);
491}
492
493EGLSurface 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
504EGLBoolean 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
540EGLBoolean 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
582EGLBoolean 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
619EGLBoolean 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
643EGLContext 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
Alexis Hetub75bb022016-05-18 11:43:43 -0400648 EGLint majorVersion = 1;
649 EGLint minorVersion = 0;
650
Nicolas Capens0bac2852016-05-07 06:09:58 -0400651 if(attrib_list)
652 {
653 for(const EGLint* attribute = attrib_list; attribute[0] != EGL_NONE; attribute += 2)
654 {
Alexis Hetub75bb022016-05-18 11:43:43 -0400655 switch(attribute[0])
Nicolas Capens0bac2852016-05-07 06:09:58 -0400656 {
Alexis Hetub75bb022016-05-18 11:43:43 -0400657 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:
Nicolas Capens0bac2852016-05-07 06:09:58 -0400704 return error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
705 }
706 }
707 }
708
Alexis Hetub75bb022016-05-18 11:43:43 -0400709 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
Nicolas Capens0bac2852016-05-07 06:09:58 -0400730 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
Alexis Hetub75bb022016-05-18 11:43:43 -0400738 if(shareContext && shareContext->getClientVersion() != majorVersion)
Nicolas Capens0bac2852016-05-07 06:09:58 -0400739 {
740 return error(EGL_BAD_CONTEXT, EGL_NO_CONTEXT);
741 }
742
Alexis Hetub75bb022016-05-18 11:43:43 -0400743 return display->createContext(config, shareContext, majorVersion);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400744}
745
746EGLBoolean 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
768EGLBoolean 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
825EGLContext GetCurrentContext(void)
826{
827 TRACE("()");
828
829 EGLContext context = egl::getCurrentContext();
830
831 return success(context);
832}
833
834EGLSurface 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
854EGLDisplay GetCurrentDisplay(void)
855{
856 TRACE("()");
857
858 return success(egl::getCurrentDisplay());
859}
860
861EGLBoolean 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
879EGLBoolean WaitGL(void)
880{
881 TRACE("()");
882
883 UNIMPLEMENTED(); // FIXME
884
885 return success(EGL_FALSE);
886}
887
888EGLBoolean WaitNative(EGLint engine)
889{
890 TRACE("(EGLint engine = %d)", engine);
891
892 UNIMPLEMENTED(); // FIXME
893
894 return success(EGL_FALSE);
895}
896
897EGLBoolean 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
919EGLBoolean 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
936EGLImageKHR 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
Nicolas Capens58df2f62016-06-07 14:48:56 -0400985 Image *image = new AndroidNativeImage(nativeBuffer);
986 EGLImageKHR eglImage = display->createSharedImage(image);
987
988 return success(eglImage);
Nicolas Capens0bac2852016-05-07 06:09:58 -0400989 }
990 #endif
991
Nicolas Capens3a795c62016-06-30 10:38:12 -0400992 GLuint name = static_cast<GLuint>(reinterpret_cast<uintptr_t>(buffer));
Nicolas Capens0bac2852016-05-07 06:09:58 -0400993
994 if(name == 0)
995 {
996 return error(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
997 }
998
999 EGLenum validationResult = context->validateSharedImage(target, name, textureLevel);
1000
1001 if(validationResult != EGL_SUCCESS)
1002 {
1003 return error(validationResult, EGL_NO_IMAGE_KHR);
1004 }
1005
Nicolas Capens58df2f62016-06-07 14:48:56 -04001006 Image *image = context->createSharedImage(target, name, textureLevel);
Nicolas Capens0bac2852016-05-07 06:09:58 -04001007
1008 if(!image)
1009 {
1010 return error(EGL_BAD_MATCH, EGL_NO_IMAGE_KHR);
1011 }
1012
1013 if(image->getDepth() > 1)
1014 {
1015 return error(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
1016 }
1017
Nicolas Capens58df2f62016-06-07 14:48:56 -04001018 EGLImageKHR eglImage = display->createSharedImage(image);
1019
1020 return success(eglImage);
Nicolas Capens0bac2852016-05-07 06:09:58 -04001021}
1022
1023EGLBoolean DestroyImageKHR(EGLDisplay dpy, EGLImageKHR image)
1024{
1025 TRACE("(EGLDisplay dpy = %p, EGLImageKHR image = %p)", dpy, image);
1026
1027 egl::Display *display = egl::Display::get(dpy);
1028
1029 if(!validateDisplay(display))
1030 {
1031 return error(EGL_BAD_DISPLAY, EGL_FALSE);
1032 }
1033
Nicolas Capens58df2f62016-06-07 14:48:56 -04001034 if(!display->destroySharedImage(image))
Nicolas Capens0bac2852016-05-07 06:09:58 -04001035 {
1036 return error(EGL_BAD_PARAMETER, EGL_FALSE);
1037 }
1038
Nicolas Capens0bac2852016-05-07 06:09:58 -04001039 return success(EGL_TRUE);
1040}
1041
1042EGLDisplay GetPlatformDisplayEXT(EGLenum platform, void *native_display, const EGLint *attrib_list)
1043{
1044 TRACE("(EGLenum platform = 0x%X, void *native_display = %p, const EGLint *attrib_list = %p)", platform, native_display, attrib_list);
1045
Nicolas Capens0bac2852016-05-07 06:09:58 -04001046 #if defined(__linux__) && !defined(__ANDROID__)
Alexis Hetu1d672442016-06-23 11:24:00 -04001047 switch(platform)
1048 {
1049 case EGL_PLATFORM_X11_EXT: break;
1050 case EGL_PLATFORM_GBM_KHR: break;
1051 default:
1052 return error(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
1053 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04001054
Nicolas Capens0bac2852016-05-07 06:09:58 -04001055 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 }
Nicolas Capens0bac2852016-05-07 06:09:58 -04001076
Alexis Hetu1d672442016-06-23 11:24:00 -04001077 return success(PRIMARY_DISPLAY); // We only support the default display
1078 #else
1079 return error(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
1080 #endif
Nicolas Capens0bac2852016-05-07 06:09:58 -04001081}
1082
1083EGLSurface CreatePlatformWindowSurfaceEXT(EGLDisplay dpy, EGLConfig config, void *native_window, const EGLint *attrib_list)
1084{
1085 return CreateWindowSurface(dpy, config, (EGLNativeWindowType)native_window, attrib_list);
1086}
1087
1088EGLSurface CreatePlatformPixmapSurfaceEXT(EGLDisplay dpy, EGLConfig config, void *native_pixmap, const EGLint *attrib_list)
1089{
1090 return CreatePixmapSurface(dpy, config, (EGLNativePixmapType)native_pixmap, attrib_list);
1091}
1092
1093EGLSyncKHR CreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list)
1094{
1095 TRACE("(EGLDisplay dpy = %p, EGLunum type = %x, EGLint *attrib_list=%p)", dpy, type, attrib_list);
1096
1097 egl::Display *display = egl::Display::get(dpy);
1098
1099 if(!validateDisplay(display))
1100 {
1101 return error(EGL_BAD_DISPLAY, EGL_NO_SYNC_KHR);
1102 }
1103
1104 if(type != EGL_SYNC_FENCE_KHR)
1105 {
1106 return error(EGL_BAD_ATTRIBUTE, EGL_NO_SYNC_KHR);
1107 }
1108
1109 if(attrib_list && attrib_list[0] != EGL_NONE)
1110 {
1111 return error(EGL_BAD_ATTRIBUTE, EGL_NO_SYNC_KHR);
1112 }
1113
1114 egl::Context *context = egl::getCurrentContext();
1115
1116 if(!validateContext(display, context))
1117 {
1118 return error(EGL_BAD_MATCH, EGL_NO_SYNC_KHR);
1119 }
1120
1121 EGLSyncKHR sync = display->createSync(context);
1122
1123 return success(sync);
1124}
1125
1126EGLBoolean DestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync)
1127{
1128 TRACE("(EGLDisplay dpy = %p, EGLSyncKHR sync = %p)", dpy, sync);
1129
1130 egl::Display *display = egl::Display::get(dpy);
1131 FenceSync *eglSync = static_cast<FenceSync*>(sync);
1132
1133 if(!validateDisplay(display))
1134 {
1135 return error(EGL_BAD_DISPLAY, EGL_FALSE);
1136 }
1137
1138 if(!display->isValidSync(eglSync))
1139 {
1140 return error(EGL_BAD_PARAMETER, EGL_FALSE);
1141 }
1142
1143 display->destroySync(eglSync);
1144
1145 return success(EGL_TRUE);
1146}
1147
1148EGLint ClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout)
1149{
1150 TRACE("(EGLDisplay dpy = %p, EGLSyncKHR sync = %p, EGLint flags = %x, EGLTimeKHR value = %llx)", dpy, sync, flags, timeout);
1151
1152 egl::Display *display = egl::Display::get(dpy);
1153 FenceSync *eglSync = static_cast<FenceSync*>(sync);
1154
1155 if(!validateDisplay(display))
1156 {
1157 return error(EGL_BAD_DISPLAY, EGL_FALSE);
1158 }
1159
1160 if(!display->isValidSync(eglSync))
1161 {
1162 return error(EGL_BAD_PARAMETER, EGL_FALSE);
1163 }
1164
1165 (void)flags;
1166 (void)timeout;
1167
1168 if(!eglSync->isSignaled())
1169 {
1170 eglSync->wait();
1171 }
1172
1173 return success(EGL_CONDITION_SATISFIED_KHR);
1174}
1175
1176EGLBoolean GetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value)
1177{
1178 TRACE("(EGLDisplay dpy = %p, EGLSyncKHR sync = %p, EGLint attribute = %x, EGLint *value = %p)", dpy, sync, attribute, value);
1179
1180 egl::Display *display = egl::Display::get(dpy);
1181 FenceSync *eglSync = static_cast<FenceSync*>(sync);
1182
1183 if(!validateDisplay(display))
1184 {
1185 return error(EGL_BAD_DISPLAY, EGL_FALSE);
1186 }
1187
1188 if(!display->isValidSync(eglSync))
1189 {
1190 return error(EGL_BAD_PARAMETER, EGL_FALSE);
1191 }
1192
1193 switch(attribute)
1194 {
1195 case EGL_SYNC_TYPE_KHR:
1196 *value = EGL_SYNC_FENCE_KHR;
1197 return success(EGL_TRUE);
1198 case EGL_SYNC_STATUS_KHR:
1199 eglSync->wait(); // TODO: Don't block. Just poll based on sw::Query.
1200 *value = eglSync->isSignaled() ? EGL_SIGNALED_KHR : EGL_UNSIGNALED_KHR;
1201 return success(EGL_TRUE);
1202 case EGL_SYNC_CONDITION_KHR:
1203 *value = EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR;
1204 return success(EGL_TRUE);
1205 default:
1206 return error(EGL_BAD_ATTRIBUTE, EGL_FALSE);
1207 }
1208}
1209
1210__eglMustCastToProperFunctionPointerType GetProcAddress(const char *procname)
1211{
1212 TRACE("(const char *procname = \"%s\")", procname);
1213
1214 struct Extension
1215 {
1216 const char *name;
1217 __eglMustCastToProperFunctionPointerType address;
1218 };
1219
1220 static const Extension eglExtensions[] =
1221 {
1222 #define EXTENSION(name) {#name, (__eglMustCastToProperFunctionPointerType)name}
1223
1224 EXTENSION(eglCreateImageKHR),
1225 EXTENSION(eglDestroyImageKHR),
1226 EXTENSION(eglGetPlatformDisplayEXT),
1227 EXTENSION(eglCreatePlatformWindowSurfaceEXT),
1228 EXTENSION(eglCreatePlatformPixmapSurfaceEXT),
1229 EXTENSION(eglCreateSyncKHR),
1230 EXTENSION(eglDestroySyncKHR),
1231 EXTENSION(eglClientWaitSyncKHR),
1232 EXTENSION(eglGetSyncAttribKHR),
1233
1234 #undef EXTENSION
1235 };
1236
1237 for(unsigned int ext = 0; ext < sizeof(eglExtensions) / sizeof(Extension); ext++)
1238 {
1239 if(strcmp(procname, eglExtensions[ext].name) == 0)
1240 {
1241 return success((__eglMustCastToProperFunctionPointerType)eglExtensions[ext].address);
1242 }
1243 }
1244
1245 if(libGLESv2)
1246 {
1247 __eglMustCastToProperFunctionPointerType proc = libGLESv2->es2GetProcAddress(procname);
1248 if(proc) return success(proc);
1249 }
1250
1251 if(libGLES_CM)
1252 {
1253 __eglMustCastToProperFunctionPointerType proc = libGLES_CM->es1GetProcAddress(procname);
1254 if(proc) return success(proc);
1255 }
1256
1257 return success((__eglMustCastToProperFunctionPointerType)NULL);
1258}
1259}