OSDN Git Service

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