OSDN Git Service

Turning on warnings as error in Visual Studio
[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.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
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         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
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 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
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
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
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
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
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
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
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
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
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
466 EGLenum QueryAPI(void)
467 {
468         TRACE("()");
469
470         EGLenum API = egl::getCurrentAPI();
471
472         return success(API);
473 }
474
475 EGLBoolean WaitClient(void)
476 {
477         TRACE("()");
478
479         UNIMPLEMENTED();   // FIXME
480
481         return success(EGL_FALSE);
482 }
483
484 EGLBoolean ReleaseThread(void)
485 {
486         TRACE("()");
487
488         detachThread();
489
490         return success(EGL_TRUE);
491 }
492
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
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
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
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
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
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
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
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
825 EGLContext GetCurrentContext(void)
826 {
827         TRACE("()");
828
829         EGLContext context = egl::getCurrentContext();
830
831         return success(context);
832 }
833
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
854 EGLDisplay GetCurrentDisplay(void)
855 {
856         TRACE("()");
857
858         return success(egl::getCurrentDisplay());
859 }
860
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
879 EGLBoolean WaitGL(void)
880 {
881         TRACE("()");
882
883         UNIMPLEMENTED();   // FIXME
884
885         return success(EGL_FALSE);
886 }
887
888 EGLBoolean WaitNative(EGLint engine)
889 {
890         TRACE("(EGLint engine = %d)", engine);
891
892         UNIMPLEMENTED();   // FIXME
893
894         return success(EGL_FALSE);
895 }
896
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
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
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                         Image *image = new AndroidNativeImage(nativeBuffer);
986                         EGLImageKHR eglImage = display->createSharedImage(image);
987
988                         return success(eglImage);
989                 }
990         #endif
991
992         GLuint name = reinterpret_cast<GLuint>(buffer);
993
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
1006         Image *image = context->createSharedImage(target, name, textureLevel);
1007
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
1018         EGLImageKHR eglImage = display->createSharedImage(image);
1019
1020         return success(eglImage);
1021 }
1022
1023 EGLBoolean 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
1034         if(!display->destroySharedImage(image))
1035         {
1036                 return error(EGL_BAD_PARAMETER, EGL_FALSE);
1037         }
1038
1039         return success(EGL_TRUE);
1040 }
1041
1042 EGLDisplay 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
1046         #if defined(__linux__) && !defined(__ANDROID__)
1047                 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                 }
1054
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
1077                 return success(PRIMARY_DISPLAY);   // We only support the default display
1078         #else
1079                 return error(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
1080         #endif
1081 }
1082
1083 EGLSurface 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
1088 EGLSurface 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
1093 EGLSyncKHR 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
1126 EGLBoolean 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
1148 EGLint 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
1176 EGLBoolean 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 }