OSDN Git Service

Revert "Revert "Modify EGL to disconnect the window when the surface gets destroyed.""
[android-x86/frameworks-native.git] / opengl / libs / EGL / eglApi.cpp
1 /*
2  ** Copyright 2007, The Android Open Source Project
3  **
4  ** Licensed under the Apache License, Version 2.0 (the "License");
5  ** you may not use this file except in compliance with the License.
6  ** You may obtain a copy of the License at
7  **
8  **     http://www.apache.org/licenses/LICENSE-2.0
9  **
10  ** Unless required by applicable law or agreed to in writing, software
11  ** distributed under the License is distributed on an "AS IS" BASIS,
12  ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  ** See the License for the specific language governing permissions and
14  ** limitations under the License.
15  */
16
17 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
18
19 #include <dlfcn.h>
20 #include <ctype.h>
21 #include <stdlib.h>
22 #include <string.h>
23
24 #include <hardware/gralloc.h>
25 #include <system/window.h>
26
27 #include <EGL/egl.h>
28 #include <EGL/eglext.h>
29
30 #include <cutils/log.h>
31 #include <cutils/atomic.h>
32 #include <cutils/compiler.h>
33 #include <cutils/properties.h>
34 #include <cutils/memory.h>
35
36 #include <utils/KeyedVector.h>
37 #include <utils/SortedVector.h>
38 #include <utils/String8.h>
39 #include <utils/Trace.h>
40
41 #include "../egl_impl.h"
42 #include "../glestrace.h"
43 #include "../hooks.h"
44
45 #include "egl_display.h"
46 #include "egl_object.h"
47 #include "egl_tls.h"
48 #include "egldefs.h"
49
50 using namespace android;
51
52 // This extension has not been ratified yet, so can't be shipped.
53 // Implementation is incomplete and untested.
54 #define ENABLE_EGL_KHR_GL_COLORSPACE 0
55
56 // ----------------------------------------------------------------------------
57
58 namespace android {
59
60 struct extention_map_t {
61     const char* name;
62     __eglMustCastToProperFunctionPointerType address;
63 };
64
65 /*
66  * This is the list of EGL extensions exposed to applications.
67  *
68  * Some of them (gBuiltinExtensionString) are implemented entirely in this EGL
69  * wrapper and are always available.
70  *
71  * The rest (gExtensionString) depend on support in the EGL driver, and are
72  * only available if the driver supports them. However, some of these must be
73  * supported because they are used by the Android system itself; these are
74  * listd as mandatory below and are required by the CDD. The system *assumes*
75  * the mandatory extensions are present and may not function properly if some
76  * are missing.
77  *
78  * NOTE: Both strings MUST have a single space as the last character.
79  */
80 extern char const * const gBuiltinExtensionString =
81         "EGL_KHR_get_all_proc_addresses "
82         "EGL_ANDROID_presentation_time "
83         "EGL_KHR_swap_buffers_with_damage "
84         ;
85 extern char const * const gExtensionString  =
86         "EGL_KHR_image "                        // mandatory
87         "EGL_KHR_image_base "                   // mandatory
88         "EGL_KHR_image_pixmap "
89         "EGL_KHR_lock_surface "
90 #if (ENABLE_EGL_KHR_GL_COLORSPACE != 0)
91         "EGL_KHR_gl_colorspace "
92 #endif
93         "EGL_KHR_gl_texture_2D_image "
94         "EGL_KHR_gl_texture_cubemap_image "
95         "EGL_KHR_gl_renderbuffer_image "
96         "EGL_KHR_reusable_sync "
97         "EGL_KHR_fence_sync "
98         "EGL_KHR_create_context "
99         "EGL_EXT_create_context_robustness "
100         "EGL_NV_system_time "
101         "EGL_ANDROID_image_native_buffer "      // mandatory
102         "EGL_KHR_wait_sync "                    // strongly recommended
103         "EGL_ANDROID_recordable "               // mandatory
104         "EGL_KHR_partial_update "               // strongly recommended
105         "EGL_EXT_buffer_age "                   // strongly recommended with partial_update
106         "EGL_KHR_create_context_no_error "
107         ;
108
109 // extensions not exposed to applications but used by the ANDROID system
110 //      "EGL_ANDROID_blob_cache "               // strongly recommended
111 //      "EGL_IMG_hibernate_process "            // optional
112 //      "EGL_ANDROID_native_fence_sync "        // strongly recommended
113 //      "EGL_ANDROID_framebuffer_target "       // mandatory for HWC 1.1
114 //      "EGL_ANDROID_image_crop "               // optional
115
116 /*
117  * EGL Extensions entry-points exposed to 3rd party applications
118  * (keep in sync with gExtensionString above)
119  *
120  */
121 static const extention_map_t sExtensionMap[] = {
122     // EGL_KHR_lock_surface
123     { "eglLockSurfaceKHR",
124             (__eglMustCastToProperFunctionPointerType)&eglLockSurfaceKHR },
125     { "eglUnlockSurfaceKHR",
126             (__eglMustCastToProperFunctionPointerType)&eglUnlockSurfaceKHR },
127
128     // EGL_KHR_image, EGL_KHR_image_base
129     { "eglCreateImageKHR",
130             (__eglMustCastToProperFunctionPointerType)&eglCreateImageKHR },
131     { "eglDestroyImageKHR",
132             (__eglMustCastToProperFunctionPointerType)&eglDestroyImageKHR },
133
134     // EGL_KHR_reusable_sync, EGL_KHR_fence_sync
135     { "eglCreateSyncKHR",
136             (__eglMustCastToProperFunctionPointerType)&eglCreateSyncKHR },
137     { "eglDestroySyncKHR",
138             (__eglMustCastToProperFunctionPointerType)&eglDestroySyncKHR },
139     { "eglClientWaitSyncKHR",
140             (__eglMustCastToProperFunctionPointerType)&eglClientWaitSyncKHR },
141     { "eglSignalSyncKHR",
142             (__eglMustCastToProperFunctionPointerType)&eglSignalSyncKHR },
143     { "eglGetSyncAttribKHR",
144             (__eglMustCastToProperFunctionPointerType)&eglGetSyncAttribKHR },
145
146     // EGL_NV_system_time
147     { "eglGetSystemTimeFrequencyNV",
148             (__eglMustCastToProperFunctionPointerType)&eglGetSystemTimeFrequencyNV },
149     { "eglGetSystemTimeNV",
150             (__eglMustCastToProperFunctionPointerType)&eglGetSystemTimeNV },
151
152     // EGL_KHR_wait_sync
153     { "eglWaitSyncKHR",
154             (__eglMustCastToProperFunctionPointerType)&eglWaitSyncKHR },
155
156     // EGL_ANDROID_presentation_time
157     { "eglPresentationTimeANDROID",
158             (__eglMustCastToProperFunctionPointerType)&eglPresentationTimeANDROID },
159
160     // EGL_KHR_swap_buffers_with_damage
161     { "eglSwapBuffersWithDamageKHR",
162             (__eglMustCastToProperFunctionPointerType)&eglSwapBuffersWithDamageKHR },
163
164     // EGL_KHR_partial_update
165     { "eglSetDamageRegionKHR",
166             (__eglMustCastToProperFunctionPointerType)&eglSetDamageRegionKHR },
167 };
168
169 /*
170  * These extensions entry-points should not be exposed to applications.
171  * They're used internally by the Android EGL layer.
172  */
173 #define FILTER_EXTENSIONS(procname) \
174         (!strcmp((procname), "eglSetBlobCacheFuncsANDROID") ||    \
175          !strcmp((procname), "eglHibernateProcessIMG")      ||    \
176          !strcmp((procname), "eglAwakenProcessIMG")         ||    \
177          !strcmp((procname), "eglDupNativeFenceFDANDROID"))
178
179
180
181 // accesses protected by sExtensionMapMutex
182 static DefaultKeyedVector<String8, __eglMustCastToProperFunctionPointerType> sGLExtentionMap;
183 static int sGLExtentionSlot = 0;
184 static pthread_mutex_t sExtensionMapMutex = PTHREAD_MUTEX_INITIALIZER;
185
186 static void(*findProcAddress(const char* name,
187         const extention_map_t* map, size_t n))() {
188     for (uint32_t i=0 ; i<n ; i++) {
189         if (!strcmp(name, map[i].name)) {
190             return map[i].address;
191         }
192     }
193     return NULL;
194 }
195
196 // ----------------------------------------------------------------------------
197
198 extern void setGLHooksThreadSpecific(gl_hooks_t const *value);
199 extern EGLBoolean egl_init_drivers();
200 extern const __eglMustCastToProperFunctionPointerType gExtensionForwarders[MAX_NUMBER_OF_GL_EXTENSIONS];
201 extern int getEGLDebugLevel();
202 extern void setEGLDebugLevel(int level);
203 extern gl_hooks_t gHooksTrace;
204
205 } // namespace android;
206
207
208 // ----------------------------------------------------------------------------
209
210 static inline void clearError() { egl_tls_t::clearError(); }
211 static inline EGLContext getContext() { return egl_tls_t::getContext(); }
212
213 // ----------------------------------------------------------------------------
214
215 EGLDisplay eglGetDisplay(EGLNativeDisplayType display)
216 {
217     clearError();
218
219     uintptr_t index = reinterpret_cast<uintptr_t>(display);
220     if (index >= NUM_DISPLAYS) {
221         return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
222     }
223
224     if (egl_init_drivers() == EGL_FALSE) {
225         return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
226     }
227
228     EGLDisplay dpy = egl_display_t::getFromNativeDisplay(display);
229     return dpy;
230 }
231
232 // ----------------------------------------------------------------------------
233 // Initialization
234 // ----------------------------------------------------------------------------
235
236 EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
237 {
238     clearError();
239
240     egl_display_ptr dp = get_display(dpy);
241     if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
242
243     EGLBoolean res = dp->initialize(major, minor);
244
245     return res;
246 }
247
248 EGLBoolean eglTerminate(EGLDisplay dpy)
249 {
250     // NOTE: don't unload the drivers b/c some APIs can be called
251     // after eglTerminate() has been called. eglTerminate() only
252     // terminates an EGLDisplay, not a EGL itself.
253
254     clearError();
255
256     egl_display_ptr dp = get_display(dpy);
257     if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
258
259     EGLBoolean res = dp->terminate();
260
261     return res;
262 }
263
264 // ----------------------------------------------------------------------------
265 // configuration
266 // ----------------------------------------------------------------------------
267
268 EGLBoolean eglGetConfigs(   EGLDisplay dpy,
269                             EGLConfig *configs,
270                             EGLint config_size, EGLint *num_config)
271 {
272     clearError();
273
274     const egl_display_ptr dp = validate_display(dpy);
275     if (!dp) return EGL_FALSE;
276
277     if (num_config==0) {
278         return setError(EGL_BAD_PARAMETER, EGL_FALSE);
279     }
280
281     EGLBoolean res = EGL_FALSE;
282     *num_config = 0;
283
284     egl_connection_t* const cnx = &gEGLImpl;
285     if (cnx->dso) {
286         res = cnx->egl.eglGetConfigs(
287                 dp->disp.dpy, configs, config_size, num_config);
288     }
289
290     return res;
291 }
292
293 EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list,
294                             EGLConfig *configs, EGLint config_size,
295                             EGLint *num_config)
296 {
297     clearError();
298
299     const egl_display_ptr dp = validate_display(dpy);
300     if (!dp) return EGL_FALSE;
301
302     if (num_config==0) {
303         return setError(EGL_BAD_PARAMETER, EGL_FALSE);
304     }
305
306     EGLBoolean res = EGL_FALSE;
307     *num_config = 0;
308
309     egl_connection_t* const cnx = &gEGLImpl;
310     if (cnx->dso) {
311         if (attrib_list) {
312             char value[PROPERTY_VALUE_MAX];
313             property_get("debug.egl.force_msaa", value, "false");
314
315             if (!strcmp(value, "true")) {
316                 size_t attribCount = 0;
317                 EGLint attrib = attrib_list[0];
318
319                 // Only enable MSAA if the context is OpenGL ES 2.0 and
320                 // if no caveat is requested
321                 const EGLint *attribRendererable = NULL;
322                 const EGLint *attribCaveat = NULL;
323
324                 // Count the number of attributes and look for
325                 // EGL_RENDERABLE_TYPE and EGL_CONFIG_CAVEAT
326                 while (attrib != EGL_NONE) {
327                     attrib = attrib_list[attribCount];
328                     switch (attrib) {
329                         case EGL_RENDERABLE_TYPE:
330                             attribRendererable = &attrib_list[attribCount];
331                             break;
332                         case EGL_CONFIG_CAVEAT:
333                             attribCaveat = &attrib_list[attribCount];
334                             break;
335                     }
336                     attribCount++;
337                 }
338
339                 if (attribRendererable && attribRendererable[1] == EGL_OPENGL_ES2_BIT &&
340                         (!attribCaveat || attribCaveat[1] != EGL_NONE)) {
341
342                     // Insert 2 extra attributes to force-enable MSAA 4x
343                     EGLint aaAttribs[attribCount + 4];
344                     aaAttribs[0] = EGL_SAMPLE_BUFFERS;
345                     aaAttribs[1] = 1;
346                     aaAttribs[2] = EGL_SAMPLES;
347                     aaAttribs[3] = 4;
348
349                     memcpy(&aaAttribs[4], attrib_list, attribCount * sizeof(EGLint));
350
351                     EGLint numConfigAA;
352                     EGLBoolean resAA = cnx->egl.eglChooseConfig(
353                             dp->disp.dpy, aaAttribs, configs, config_size, &numConfigAA);
354
355                     if (resAA == EGL_TRUE && numConfigAA > 0) {
356                         ALOGD("Enabling MSAA 4x");
357                         *num_config = numConfigAA;
358                         return resAA;
359                     }
360                 }
361             }
362         }
363
364         res = cnx->egl.eglChooseConfig(
365                 dp->disp.dpy, attrib_list, configs, config_size, num_config);
366     }
367     return res;
368 }
369
370 EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config,
371         EGLint attribute, EGLint *value)
372 {
373     clearError();
374
375     egl_connection_t* cnx = NULL;
376     const egl_display_ptr dp = validate_display_connection(dpy, cnx);
377     if (!dp) return EGL_FALSE;
378
379     return cnx->egl.eglGetConfigAttrib(
380             dp->disp.dpy, config, attribute, value);
381 }
382
383 // ----------------------------------------------------------------------------
384 // surfaces
385 // ----------------------------------------------------------------------------
386
387 // The EGL_KHR_gl_colorspace spec hasn't been ratified yet, so these haven't
388 // been added to the Khronos egl.h.
389 #define EGL_GL_COLORSPACE_KHR           EGL_VG_COLORSPACE
390 #define EGL_GL_COLORSPACE_SRGB_KHR      EGL_VG_COLORSPACE_sRGB
391 #define EGL_GL_COLORSPACE_LINEAR_KHR    EGL_VG_COLORSPACE_LINEAR
392
393 // Turn linear formats into corresponding sRGB formats when colorspace is
394 // EGL_GL_COLORSPACE_SRGB_KHR, or turn sRGB formats into corresponding linear
395 // formats when colorspace is EGL_GL_COLORSPACE_LINEAR_KHR. In any cases where
396 // the modification isn't possible, the original dataSpace is returned.
397 static android_dataspace modifyBufferDataspace( android_dataspace dataSpace,
398                                                 EGLint colorspace) {
399     if (colorspace == EGL_GL_COLORSPACE_LINEAR_KHR) {
400         return HAL_DATASPACE_SRGB_LINEAR;
401     } else if (colorspace == EGL_GL_COLORSPACE_SRGB_KHR) {
402         return HAL_DATASPACE_SRGB;
403     }
404     return dataSpace;
405 }
406
407 EGLSurface eglCreateWindowSurface(  EGLDisplay dpy, EGLConfig config,
408                                     NativeWindowType window,
409                                     const EGLint *attrib_list)
410 {
411     clearError();
412
413     egl_connection_t* cnx = NULL;
414     egl_display_ptr dp = validate_display_connection(dpy, cnx);
415     if (dp) {
416         EGLDisplay iDpy = dp->disp.dpy;
417
418         int result = native_window_api_connect(window, NATIVE_WINDOW_API_EGL);
419         if (result != OK) {
420             ALOGE("eglCreateWindowSurface: native_window_api_connect (win=%p) "
421                     "failed (%#x) (already connected to another API?)",
422                     window, result);
423             return setError(EGL_BAD_ALLOC, EGL_NO_SURFACE);
424         }
425
426         // Set the native window's buffers format to match what this config requests.
427         // Whether to use sRGB gamma is not part of the EGLconfig, but is part
428         // of our native format. So if sRGB gamma is requested, we have to
429         // modify the EGLconfig's format before setting the native window's
430         // format.
431
432         // by default, just pick RGBA_8888
433         EGLint format = HAL_PIXEL_FORMAT_RGBA_8888;
434         android_dataspace dataSpace = HAL_DATASPACE_UNKNOWN;
435
436         EGLint a = 0;
437         cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_ALPHA_SIZE, &a);
438         if (a > 0) {
439             // alpha-channel requested, there's really only one suitable format
440             format = HAL_PIXEL_FORMAT_RGBA_8888;
441         } else {
442             EGLint r, g, b;
443             r = g = b = 0;
444             cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_RED_SIZE,   &r);
445             cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_GREEN_SIZE, &g);
446             cnx->egl.eglGetConfigAttrib(iDpy, config, EGL_BLUE_SIZE,  &b);
447             EGLint colorDepth = r + g + b;
448             if (colorDepth <= 16) {
449                 format = HAL_PIXEL_FORMAT_RGB_565;
450             } else {
451                 format = HAL_PIXEL_FORMAT_RGBX_8888;
452             }
453         }
454
455         // now select a corresponding sRGB format if needed
456         if (attrib_list && dp->haveExtension("EGL_KHR_gl_colorspace")) {
457             for (const EGLint* attr = attrib_list; *attr != EGL_NONE; attr += 2) {
458                 if (*attr == EGL_GL_COLORSPACE_KHR) {
459                     if (ENABLE_EGL_KHR_GL_COLORSPACE) {
460                         dataSpace = modifyBufferDataspace(dataSpace, *(attr+1));
461                     } else {
462                         // Normally we'd pass through unhandled attributes to
463                         // the driver. But in case the driver implements this
464                         // extension but we're disabling it, we want to prevent
465                         // it getting through -- support will be broken without
466                         // our help.
467                         ALOGE("sRGB window surfaces not supported");
468                         return setError(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE);
469                     }
470                 }
471             }
472         }
473
474         if (format != 0) {
475             int err = native_window_set_buffers_format(window, format);
476             if (err != 0) {
477                 ALOGE("error setting native window pixel format: %s (%d)",
478                         strerror(-err), err);
479                 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
480                 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
481             }
482         }
483
484         if (dataSpace != 0) {
485             int err = native_window_set_buffers_data_space(window, dataSpace);
486             if (err != 0) {
487                 ALOGE("error setting native window pixel dataSpace: %s (%d)",
488                         strerror(-err), err);
489                 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
490                 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
491             }
492         }
493
494         // the EGL spec requires that a new EGLSurface default to swap interval
495         // 1, so explicitly set that on the window here.
496         ANativeWindow* anw = reinterpret_cast<ANativeWindow*>(window);
497         anw->setSwapInterval(anw, 1);
498
499         EGLSurface surface = cnx->egl.eglCreateWindowSurface(
500                 iDpy, config, window, attrib_list);
501         if (surface != EGL_NO_SURFACE) {
502             egl_surface_t* s = new egl_surface_t(dp.get(), config, window,
503                     surface, cnx);
504             return s;
505         }
506
507         // EGLSurface creation failed
508         native_window_set_buffers_format(window, 0);
509         native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
510     }
511     return EGL_NO_SURFACE;
512 }
513
514 EGLSurface eglCreatePixmapSurface(  EGLDisplay dpy, EGLConfig config,
515                                     NativePixmapType pixmap,
516                                     const EGLint *attrib_list)
517 {
518     clearError();
519
520     egl_connection_t* cnx = NULL;
521     egl_display_ptr dp = validate_display_connection(dpy, cnx);
522     if (dp) {
523         EGLSurface surface = cnx->egl.eglCreatePixmapSurface(
524                 dp->disp.dpy, config, pixmap, attrib_list);
525         if (surface != EGL_NO_SURFACE) {
526             egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL,
527                     surface, cnx);
528             return s;
529         }
530     }
531     return EGL_NO_SURFACE;
532 }
533
534 EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config,
535                                     const EGLint *attrib_list)
536 {
537     clearError();
538
539     egl_connection_t* cnx = NULL;
540     egl_display_ptr dp = validate_display_connection(dpy, cnx);
541     if (dp) {
542         EGLSurface surface = cnx->egl.eglCreatePbufferSurface(
543                 dp->disp.dpy, config, attrib_list);
544         if (surface != EGL_NO_SURFACE) {
545             egl_surface_t* s = new egl_surface_t(dp.get(), config, NULL,
546                     surface, cnx);
547             return s;
548         }
549     }
550     return EGL_NO_SURFACE;
551 }
552
553 EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
554 {
555     clearError();
556
557     const egl_display_ptr dp = validate_display(dpy);
558     if (!dp) return EGL_FALSE;
559
560     SurfaceRef _s(dp.get(), surface);
561     if (!_s.get())
562         return setError(EGL_BAD_SURFACE, EGL_FALSE);
563
564     egl_surface_t * const s = get_surface(surface);
565     ANativeWindow* window = s->win.get();
566     if (window) {
567         int result = native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
568         if (result != OK) {
569             ALOGE("eglDestroySurface: native_window_api_disconnect (win=%p) "
570                   "failed (%#x)",
571                   window, result);
572         }
573     }
574     EGLBoolean result = s->cnx->egl.eglDestroySurface(dp->disp.dpy, s->surface);
575     if (result == EGL_TRUE) {
576         _s.terminate();
577     }
578     return result;
579 }
580
581 EGLBoolean eglQuerySurface( EGLDisplay dpy, EGLSurface surface,
582                             EGLint attribute, EGLint *value)
583 {
584     clearError();
585
586     const egl_display_ptr dp = validate_display(dpy);
587     if (!dp) return EGL_FALSE;
588
589     SurfaceRef _s(dp.get(), surface);
590     if (!_s.get())
591         return setError(EGL_BAD_SURFACE, EGL_FALSE);
592
593     egl_surface_t const * const s = get_surface(surface);
594     return s->cnx->egl.eglQuerySurface(
595             dp->disp.dpy, s->surface, attribute, value);
596 }
597
598 void EGLAPI eglBeginFrame(EGLDisplay dpy, EGLSurface surface) {
599     ATRACE_CALL();
600     clearError();
601
602     const egl_display_ptr dp = validate_display(dpy);
603     if (!dp) {
604         return;
605     }
606
607     SurfaceRef _s(dp.get(), surface);
608     if (!_s.get()) {
609         setError(EGL_BAD_SURFACE, EGL_FALSE);
610         return;
611     }
612 }
613
614 // ----------------------------------------------------------------------------
615 // Contexts
616 // ----------------------------------------------------------------------------
617
618 EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config,
619                             EGLContext share_list, const EGLint *attrib_list)
620 {
621     clearError();
622
623     egl_connection_t* cnx = NULL;
624     const egl_display_ptr dp = validate_display_connection(dpy, cnx);
625     if (dp) {
626         if (share_list != EGL_NO_CONTEXT) {
627             if (!ContextRef(dp.get(), share_list).get()) {
628                 return setError(EGL_BAD_CONTEXT, EGL_NO_CONTEXT);
629             }
630             egl_context_t* const c = get_context(share_list);
631             share_list = c->context;
632         }
633         EGLContext context = cnx->egl.eglCreateContext(
634                 dp->disp.dpy, config, share_list, attrib_list);
635         if (context != EGL_NO_CONTEXT) {
636             // figure out if it's a GLESv1 or GLESv2
637             int version = 0;
638             if (attrib_list) {
639                 while (*attrib_list != EGL_NONE) {
640                     GLint attr = *attrib_list++;
641                     GLint value = *attrib_list++;
642                     if (attr == EGL_CONTEXT_CLIENT_VERSION) {
643                         if (value == 1) {
644                             version = egl_connection_t::GLESv1_INDEX;
645                         } else if (value == 2 || value == 3) {
646                             version = egl_connection_t::GLESv2_INDEX;
647                         }
648                     }
649                 };
650             }
651             egl_context_t* c = new egl_context_t(dpy, context, config, cnx,
652                     version);
653 #if EGL_TRACE
654             if (getEGLDebugLevel() > 0)
655                 GLTrace_eglCreateContext(version, c);
656 #endif
657             return c;
658         }
659     }
660     return EGL_NO_CONTEXT;
661 }
662
663 EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
664 {
665     clearError();
666
667     const egl_display_ptr dp = validate_display(dpy);
668     if (!dp)
669         return EGL_FALSE;
670
671     ContextRef _c(dp.get(), ctx);
672     if (!_c.get())
673         return setError(EGL_BAD_CONTEXT, EGL_FALSE);
674
675     egl_context_t * const c = get_context(ctx);
676     EGLBoolean result = c->cnx->egl.eglDestroyContext(dp->disp.dpy, c->context);
677     if (result == EGL_TRUE) {
678         _c.terminate();
679     }
680     return result;
681 }
682
683 EGLBoolean eglMakeCurrent(  EGLDisplay dpy, EGLSurface draw,
684                             EGLSurface read, EGLContext ctx)
685 {
686     clearError();
687
688     egl_display_ptr dp = validate_display(dpy);
689     if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE);
690
691     // If ctx is not EGL_NO_CONTEXT, read is not EGL_NO_SURFACE, or draw is not
692     // EGL_NO_SURFACE, then an EGL_NOT_INITIALIZED error is generated if dpy is
693     // a valid but uninitialized display.
694     if ( (ctx != EGL_NO_CONTEXT) || (read != EGL_NO_SURFACE) ||
695          (draw != EGL_NO_SURFACE) ) {
696         if (!dp->isReady()) return setError(EGL_NOT_INITIALIZED, EGL_FALSE);
697     }
698
699     // get a reference to the object passed in
700     ContextRef _c(dp.get(), ctx);
701     SurfaceRef _d(dp.get(), draw);
702     SurfaceRef _r(dp.get(), read);
703
704     // validate the context (if not EGL_NO_CONTEXT)
705     if ((ctx != EGL_NO_CONTEXT) && !_c.get()) {
706         // EGL_NO_CONTEXT is valid
707         return setError(EGL_BAD_CONTEXT, EGL_FALSE);
708     }
709
710     // these are the underlying implementation's object
711     EGLContext impl_ctx  = EGL_NO_CONTEXT;
712     EGLSurface impl_draw = EGL_NO_SURFACE;
713     EGLSurface impl_read = EGL_NO_SURFACE;
714
715     // these are our objects structs passed in
716     egl_context_t       * c = NULL;
717     egl_surface_t const * d = NULL;
718     egl_surface_t const * r = NULL;
719
720     // these are the current objects structs
721     egl_context_t * cur_c = get_context(getContext());
722
723     if (ctx != EGL_NO_CONTEXT) {
724         c = get_context(ctx);
725         impl_ctx = c->context;
726     } else {
727         // no context given, use the implementation of the current context
728         if (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE) {
729             // calling eglMakeCurrent( ..., !=0, !=0, EGL_NO_CONTEXT);
730             return setError(EGL_BAD_MATCH, EGL_FALSE);
731         }
732         if (cur_c == NULL) {
733             // no current context
734             // not an error, there is just no current context.
735             return EGL_TRUE;
736         }
737     }
738
739     // retrieve the underlying implementation's draw EGLSurface
740     if (draw != EGL_NO_SURFACE) {
741         if (!_d.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
742         d = get_surface(draw);
743         impl_draw = d->surface;
744     }
745
746     // retrieve the underlying implementation's read EGLSurface
747     if (read != EGL_NO_SURFACE) {
748         if (!_r.get()) return setError(EGL_BAD_SURFACE, EGL_FALSE);
749         r = get_surface(read);
750         impl_read = r->surface;
751     }
752
753
754     EGLBoolean result = dp->makeCurrent(c, cur_c,
755             draw, read, ctx,
756             impl_draw, impl_read, impl_ctx);
757
758     if (result == EGL_TRUE) {
759         if (c) {
760             setGLHooksThreadSpecific(c->cnx->hooks[c->version]);
761             egl_tls_t::setContext(ctx);
762 #if EGL_TRACE
763             if (getEGLDebugLevel() > 0)
764                 GLTrace_eglMakeCurrent(c->version, c->cnx->hooks[c->version], ctx);
765 #endif
766             _c.acquire();
767             _r.acquire();
768             _d.acquire();
769         } else {
770             setGLHooksThreadSpecific(&gHooksNoContext);
771             egl_tls_t::setContext(EGL_NO_CONTEXT);
772         }
773     } else {
774         // this will ALOGE the error
775         egl_connection_t* const cnx = &gEGLImpl;
776         result = setError(cnx->egl.eglGetError(), EGL_FALSE);
777     }
778     return result;
779 }
780
781
782 EGLBoolean eglQueryContext( EGLDisplay dpy, EGLContext ctx,
783                             EGLint attribute, EGLint *value)
784 {
785     clearError();
786
787     const egl_display_ptr dp = validate_display(dpy);
788     if (!dp) return EGL_FALSE;
789
790     ContextRef _c(dp.get(), ctx);
791     if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE);
792
793     egl_context_t * const c = get_context(ctx);
794     return c->cnx->egl.eglQueryContext(
795             dp->disp.dpy, c->context, attribute, value);
796
797 }
798
799 EGLContext eglGetCurrentContext(void)
800 {
801     // could be called before eglInitialize(), but we wouldn't have a context
802     // then, and this function would correctly return EGL_NO_CONTEXT.
803
804     clearError();
805
806     EGLContext ctx = getContext();
807     return ctx;
808 }
809
810 EGLSurface eglGetCurrentSurface(EGLint readdraw)
811 {
812     // could be called before eglInitialize(), but we wouldn't have a context
813     // then, and this function would correctly return EGL_NO_SURFACE.
814
815     clearError();
816
817     EGLContext ctx = getContext();
818     if (ctx) {
819         egl_context_t const * const c = get_context(ctx);
820         if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE);
821         switch (readdraw) {
822             case EGL_READ: return c->read;
823             case EGL_DRAW: return c->draw;
824             default: return setError(EGL_BAD_PARAMETER, EGL_NO_SURFACE);
825         }
826     }
827     return EGL_NO_SURFACE;
828 }
829
830 EGLDisplay eglGetCurrentDisplay(void)
831 {
832     // could be called before eglInitialize(), but we wouldn't have a context
833     // then, and this function would correctly return EGL_NO_DISPLAY.
834
835     clearError();
836
837     EGLContext ctx = getContext();
838     if (ctx) {
839         egl_context_t const * const c = get_context(ctx);
840         if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE);
841         return c->dpy;
842     }
843     return EGL_NO_DISPLAY;
844 }
845
846 EGLBoolean eglWaitGL(void)
847 {
848     clearError();
849
850     egl_connection_t* const cnx = &gEGLImpl;
851     if (!cnx->dso)
852         return setError(EGL_BAD_CONTEXT, EGL_FALSE);
853
854     return cnx->egl.eglWaitGL();
855 }
856
857 EGLBoolean eglWaitNative(EGLint engine)
858 {
859     clearError();
860
861     egl_connection_t* const cnx = &gEGLImpl;
862     if (!cnx->dso)
863         return setError(EGL_BAD_CONTEXT, EGL_FALSE);
864
865     return cnx->egl.eglWaitNative(engine);
866 }
867
868 EGLint eglGetError(void)
869 {
870     EGLint err = EGL_SUCCESS;
871     egl_connection_t* const cnx = &gEGLImpl;
872     if (cnx->dso) {
873         err = cnx->egl.eglGetError();
874     }
875     if (err == EGL_SUCCESS) {
876         err = egl_tls_t::getError();
877     }
878     return err;
879 }
880
881 static __eglMustCastToProperFunctionPointerType findBuiltinWrapper(
882         const char* procname) {
883     const egl_connection_t* cnx = &gEGLImpl;
884     void* proc = NULL;
885
886     proc = dlsym(cnx->libEgl, procname);
887     if (proc) return (__eglMustCastToProperFunctionPointerType)proc;
888
889     proc = dlsym(cnx->libGles2, procname);
890     if (proc) return (__eglMustCastToProperFunctionPointerType)proc;
891
892     proc = dlsym(cnx->libGles1, procname);
893     if (proc) return (__eglMustCastToProperFunctionPointerType)proc;
894
895     return NULL;
896 }
897
898 __eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname)
899 {
900     // eglGetProcAddress() could be the very first function called
901     // in which case we must make sure we've initialized ourselves, this
902     // happens the first time egl_get_display() is called.
903
904     clearError();
905
906     if (egl_init_drivers() == EGL_FALSE) {
907         setError(EGL_BAD_PARAMETER, NULL);
908         return  NULL;
909     }
910
911     if (FILTER_EXTENSIONS(procname)) {
912         return NULL;
913     }
914
915     __eglMustCastToProperFunctionPointerType addr;
916     addr = findProcAddress(procname, sExtensionMap, NELEM(sExtensionMap));
917     if (addr) return addr;
918
919     addr = findBuiltinWrapper(procname);
920     if (addr) return addr;
921
922     // this protects accesses to sGLExtentionMap and sGLExtentionSlot
923     pthread_mutex_lock(&sExtensionMapMutex);
924
925         /*
926          * Since eglGetProcAddress() is not associated to anything, it needs
927          * to return a function pointer that "works" regardless of what
928          * the current context is.
929          *
930          * For this reason, we return a "forwarder", a small stub that takes
931          * care of calling the function associated with the context
932          * currently bound.
933          *
934          * We first look for extensions we've already resolved, if we're seeing
935          * this extension for the first time, we go through all our
936          * implementations and call eglGetProcAddress() and record the
937          * result in the appropriate implementation hooks and return the
938          * address of the forwarder corresponding to that hook set.
939          *
940          */
941
942         const String8 name(procname);
943         addr = sGLExtentionMap.valueFor(name);
944         const int slot = sGLExtentionSlot;
945
946         ALOGE_IF(slot >= MAX_NUMBER_OF_GL_EXTENSIONS,
947                 "no more slots for eglGetProcAddress(\"%s\")",
948                 procname);
949
950 #if EGL_TRACE
951         gl_hooks_t *debugHooks = GLTrace_getGLHooks();
952 #endif
953
954         if (!addr && (slot < MAX_NUMBER_OF_GL_EXTENSIONS)) {
955             bool found = false;
956
957             egl_connection_t* const cnx = &gEGLImpl;
958             if (cnx->dso && cnx->egl.eglGetProcAddress) {
959                 // Extensions are independent of the bound context
960                 addr =
961                 cnx->hooks[egl_connection_t::GLESv1_INDEX]->ext.extensions[slot] =
962                 cnx->hooks[egl_connection_t::GLESv2_INDEX]->ext.extensions[slot] =
963 #if EGL_TRACE
964                 debugHooks->ext.extensions[slot] =
965                 gHooksTrace.ext.extensions[slot] =
966 #endif
967                         cnx->egl.eglGetProcAddress(procname);
968                 if (addr) found = true;
969             }
970
971             if (found) {
972                 addr = gExtensionForwarders[slot];
973                 sGLExtentionMap.add(name, addr);
974                 sGLExtentionSlot++;
975             }
976         }
977
978     pthread_mutex_unlock(&sExtensionMapMutex);
979     return addr;
980 }
981
982 class FrameCompletionThread : public Thread {
983 public:
984
985     static void queueSync(EGLSyncKHR sync) {
986         static sp<FrameCompletionThread> thread(new FrameCompletionThread);
987         static bool running = false;
988         if (!running) {
989             thread->run("GPUFrameCompletion");
990             running = true;
991         }
992         {
993             Mutex::Autolock lock(thread->mMutex);
994             ScopedTrace st(ATRACE_TAG, String8::format("kicked off frame %d",
995                     thread->mFramesQueued).string());
996             thread->mQueue.push_back(sync);
997             thread->mCondition.signal();
998             thread->mFramesQueued++;
999             ATRACE_INT("GPU Frames Outstanding", thread->mQueue.size());
1000         }
1001     }
1002
1003 private:
1004     FrameCompletionThread() : mFramesQueued(0), mFramesCompleted(0) {}
1005
1006     virtual bool threadLoop() {
1007         EGLSyncKHR sync;
1008         uint32_t frameNum;
1009         {
1010             Mutex::Autolock lock(mMutex);
1011             while (mQueue.isEmpty()) {
1012                 mCondition.wait(mMutex);
1013             }
1014             sync = mQueue[0];
1015             frameNum = mFramesCompleted;
1016         }
1017         EGLDisplay dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
1018         {
1019             ScopedTrace st(ATRACE_TAG, String8::format("waiting for frame %d",
1020                     frameNum).string());
1021             EGLint result = eglClientWaitSyncKHR(dpy, sync, 0, EGL_FOREVER_KHR);
1022             if (result == EGL_FALSE) {
1023                 ALOGE("FrameCompletion: error waiting for fence: %#x", eglGetError());
1024             } else if (result == EGL_TIMEOUT_EXPIRED_KHR) {
1025                 ALOGE("FrameCompletion: timeout waiting for fence");
1026             }
1027             eglDestroySyncKHR(dpy, sync);
1028         }
1029         {
1030             Mutex::Autolock lock(mMutex);
1031             mQueue.removeAt(0);
1032             mFramesCompleted++;
1033             ATRACE_INT("GPU Frames Outstanding", mQueue.size());
1034         }
1035         return true;
1036     }
1037
1038     uint32_t mFramesQueued;
1039     uint32_t mFramesCompleted;
1040     Vector<EGLSyncKHR> mQueue;
1041     Condition mCondition;
1042     Mutex mMutex;
1043 };
1044
1045 EGLBoolean eglSwapBuffersWithDamageKHR(EGLDisplay dpy, EGLSurface draw,
1046         EGLint *rects, EGLint n_rects)
1047 {
1048     ATRACE_CALL();
1049     clearError();
1050
1051     const egl_display_ptr dp = validate_display(dpy);
1052     if (!dp) return EGL_FALSE;
1053
1054     SurfaceRef _s(dp.get(), draw);
1055     if (!_s.get())
1056         return setError(EGL_BAD_SURFACE, EGL_FALSE);
1057
1058 #if EGL_TRACE
1059     gl_hooks_t const *trace_hooks = getGLTraceThreadSpecific();
1060     if (getEGLDebugLevel() > 0) {
1061         if (trace_hooks == NULL) {
1062             if (GLTrace_start() < 0) {
1063                 ALOGE("Disabling Tracer for OpenGL ES");
1064                 setEGLDebugLevel(0);
1065             } else {
1066                 // switch over to the trace version of hooks
1067                 EGLContext ctx = egl_tls_t::getContext();
1068                 egl_context_t * const c = get_context(ctx);
1069                 if (c) {
1070                     setGLHooksThreadSpecific(c->cnx->hooks[c->version]);
1071                     GLTrace_eglMakeCurrent(c->version, c->cnx->hooks[c->version], ctx);
1072                 }
1073             }
1074         }
1075
1076         GLTrace_eglSwapBuffers(dpy, draw);
1077     } else if (trace_hooks != NULL) {
1078         // tracing is now disabled, so switch back to the non trace version
1079         EGLContext ctx = egl_tls_t::getContext();
1080         egl_context_t * const c = get_context(ctx);
1081         if (c) setGLHooksThreadSpecific(c->cnx->hooks[c->version]);
1082         GLTrace_stop();
1083     }
1084 #endif
1085
1086     egl_surface_t const * const s = get_surface(draw);
1087
1088     if (CC_UNLIKELY(dp->traceGpuCompletion)) {
1089         EGLSyncKHR sync = eglCreateSyncKHR(dpy, EGL_SYNC_FENCE_KHR, NULL);
1090         if (sync != EGL_NO_SYNC_KHR) {
1091             FrameCompletionThread::queueSync(sync);
1092         }
1093     }
1094
1095     if (CC_UNLIKELY(dp->finishOnSwap)) {
1096         uint32_t pixel;
1097         egl_context_t * const c = get_context( egl_tls_t::getContext() );
1098         if (c) {
1099             // glReadPixels() ensures that the frame is complete
1100             s->cnx->hooks[c->version]->gl.glReadPixels(0,0,1,1,
1101                     GL_RGBA,GL_UNSIGNED_BYTE,&pixel);
1102         }
1103     }
1104
1105     if (n_rects == 0) {
1106         return s->cnx->egl.eglSwapBuffers(dp->disp.dpy, s->surface);
1107     }
1108
1109     Vector<android_native_rect_t> androidRects;
1110     for (int r = 0; r < n_rects; ++r) {
1111         int offset = r * 4;
1112         int x = rects[offset];
1113         int y = rects[offset + 1];
1114         int width = rects[offset + 2];
1115         int height = rects[offset + 3];
1116         android_native_rect_t androidRect;
1117         androidRect.left = x;
1118         androidRect.top = y + height;
1119         androidRect.right = x + width;
1120         androidRect.bottom = y;
1121         androidRects.push_back(androidRect);
1122     }
1123     native_window_set_surface_damage(s->win.get(), androidRects.array(),
1124             androidRects.size());
1125
1126     if (s->cnx->egl.eglSwapBuffersWithDamageKHR) {
1127         return s->cnx->egl.eglSwapBuffersWithDamageKHR(dp->disp.dpy, s->surface,
1128                 rects, n_rects);
1129     } else {
1130         return s->cnx->egl.eglSwapBuffers(dp->disp.dpy, s->surface);
1131     }
1132 }
1133
1134 EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface surface)
1135 {
1136     return eglSwapBuffersWithDamageKHR(dpy, surface, NULL, 0);
1137 }
1138
1139 EGLBoolean eglCopyBuffers(  EGLDisplay dpy, EGLSurface surface,
1140                             NativePixmapType target)
1141 {
1142     clearError();
1143
1144     const egl_display_ptr dp = validate_display(dpy);
1145     if (!dp) return EGL_FALSE;
1146
1147     SurfaceRef _s(dp.get(), surface);
1148     if (!_s.get())
1149         return setError(EGL_BAD_SURFACE, EGL_FALSE);
1150
1151     egl_surface_t const * const s = get_surface(surface);
1152     return s->cnx->egl.eglCopyBuffers(dp->disp.dpy, s->surface, target);
1153 }
1154
1155 const char* eglQueryString(EGLDisplay dpy, EGLint name)
1156 {
1157     clearError();
1158
1159     const egl_display_ptr dp = validate_display(dpy);
1160     if (!dp) return (const char *) NULL;
1161
1162     switch (name) {
1163         case EGL_VENDOR:
1164             return dp->getVendorString();
1165         case EGL_VERSION:
1166             return dp->getVersionString();
1167         case EGL_EXTENSIONS:
1168             return dp->getExtensionString();
1169         case EGL_CLIENT_APIS:
1170             return dp->getClientApiString();
1171     }
1172     return setError(EGL_BAD_PARAMETER, (const char *)0);
1173 }
1174
1175 EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name)
1176 {
1177     clearError();
1178
1179     const egl_display_ptr dp = validate_display(dpy);
1180     if (!dp) return (const char *) NULL;
1181
1182     switch (name) {
1183         case EGL_VENDOR:
1184             return dp->disp.queryString.vendor;
1185         case EGL_VERSION:
1186             return dp->disp.queryString.version;
1187         case EGL_EXTENSIONS:
1188             return dp->disp.queryString.extensions;
1189         case EGL_CLIENT_APIS:
1190             return dp->disp.queryString.clientApi;
1191     }
1192     return setError(EGL_BAD_PARAMETER, (const char *)0);
1193 }
1194
1195 // ----------------------------------------------------------------------------
1196 // EGL 1.1
1197 // ----------------------------------------------------------------------------
1198
1199 EGLBoolean eglSurfaceAttrib(
1200         EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
1201 {
1202     clearError();
1203
1204     const egl_display_ptr dp = validate_display(dpy);
1205     if (!dp) return EGL_FALSE;
1206
1207     SurfaceRef _s(dp.get(), surface);
1208     if (!_s.get())
1209         return setError(EGL_BAD_SURFACE, EGL_FALSE);
1210
1211     egl_surface_t const * const s = get_surface(surface);
1212     if (s->cnx->egl.eglSurfaceAttrib) {
1213         return s->cnx->egl.eglSurfaceAttrib(
1214                 dp->disp.dpy, s->surface, attribute, value);
1215     }
1216     return setError(EGL_BAD_SURFACE, EGL_FALSE);
1217 }
1218
1219 EGLBoolean eglBindTexImage(
1220         EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1221 {
1222     clearError();
1223
1224     const egl_display_ptr dp = validate_display(dpy);
1225     if (!dp) return EGL_FALSE;
1226
1227     SurfaceRef _s(dp.get(), surface);
1228     if (!_s.get())
1229         return setError(EGL_BAD_SURFACE, EGL_FALSE);
1230
1231     egl_surface_t const * const s = get_surface(surface);
1232     if (s->cnx->egl.eglBindTexImage) {
1233         return s->cnx->egl.eglBindTexImage(
1234                 dp->disp.dpy, s->surface, buffer);
1235     }
1236     return setError(EGL_BAD_SURFACE, EGL_FALSE);
1237 }
1238
1239 EGLBoolean eglReleaseTexImage(
1240         EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1241 {
1242     clearError();
1243
1244     const egl_display_ptr dp = validate_display(dpy);
1245     if (!dp) return EGL_FALSE;
1246
1247     SurfaceRef _s(dp.get(), surface);
1248     if (!_s.get())
1249         return setError(EGL_BAD_SURFACE, EGL_FALSE);
1250
1251     egl_surface_t const * const s = get_surface(surface);
1252     if (s->cnx->egl.eglReleaseTexImage) {
1253         return s->cnx->egl.eglReleaseTexImage(
1254                 dp->disp.dpy, s->surface, buffer);
1255     }
1256     return setError(EGL_BAD_SURFACE, EGL_FALSE);
1257 }
1258
1259 EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval)
1260 {
1261     clearError();
1262
1263     const egl_display_ptr dp = validate_display(dpy);
1264     if (!dp) return EGL_FALSE;
1265
1266     EGLBoolean res = EGL_TRUE;
1267     egl_connection_t* const cnx = &gEGLImpl;
1268     if (cnx->dso && cnx->egl.eglSwapInterval) {
1269         res = cnx->egl.eglSwapInterval(dp->disp.dpy, interval);
1270     }
1271
1272     return res;
1273 }
1274
1275
1276 // ----------------------------------------------------------------------------
1277 // EGL 1.2
1278 // ----------------------------------------------------------------------------
1279
1280 EGLBoolean eglWaitClient(void)
1281 {
1282     clearError();
1283
1284     egl_connection_t* const cnx = &gEGLImpl;
1285     if (!cnx->dso)
1286         return setError(EGL_BAD_CONTEXT, EGL_FALSE);
1287
1288     EGLBoolean res;
1289     if (cnx->egl.eglWaitClient) {
1290         res = cnx->egl.eglWaitClient();
1291     } else {
1292         res = cnx->egl.eglWaitGL();
1293     }
1294     return res;
1295 }
1296
1297 EGLBoolean eglBindAPI(EGLenum api)
1298 {
1299     clearError();
1300
1301     if (egl_init_drivers() == EGL_FALSE) {
1302         return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1303     }
1304
1305     // bind this API on all EGLs
1306     EGLBoolean res = EGL_TRUE;
1307     egl_connection_t* const cnx = &gEGLImpl;
1308     if (cnx->dso && cnx->egl.eglBindAPI) {
1309         res = cnx->egl.eglBindAPI(api);
1310     }
1311     return res;
1312 }
1313
1314 EGLenum eglQueryAPI(void)
1315 {
1316     clearError();
1317
1318     if (egl_init_drivers() == EGL_FALSE) {
1319         return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1320     }
1321
1322     egl_connection_t* const cnx = &gEGLImpl;
1323     if (cnx->dso && cnx->egl.eglQueryAPI) {
1324         return cnx->egl.eglQueryAPI();
1325     }
1326
1327     // or, it can only be OpenGL ES
1328     return EGL_OPENGL_ES_API;
1329 }
1330
1331 EGLBoolean eglReleaseThread(void)
1332 {
1333     clearError();
1334
1335 #if EGL_TRACE
1336     if (getEGLDebugLevel() > 0)
1337         GLTrace_eglReleaseThread();
1338 #endif
1339
1340     // If there is context bound to the thread, release it
1341     egl_display_t::loseCurrent(get_context(getContext()));
1342
1343     egl_connection_t* const cnx = &gEGLImpl;
1344     if (cnx->dso && cnx->egl.eglReleaseThread) {
1345         cnx->egl.eglReleaseThread();
1346     }
1347     egl_tls_t::clearTLS();
1348     return EGL_TRUE;
1349 }
1350
1351 EGLSurface eglCreatePbufferFromClientBuffer(
1352           EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer,
1353           EGLConfig config, const EGLint *attrib_list)
1354 {
1355     clearError();
1356
1357     egl_connection_t* cnx = NULL;
1358     const egl_display_ptr dp = validate_display_connection(dpy, cnx);
1359     if (!dp) return EGL_FALSE;
1360     if (cnx->egl.eglCreatePbufferFromClientBuffer) {
1361         return cnx->egl.eglCreatePbufferFromClientBuffer(
1362                 dp->disp.dpy, buftype, buffer, config, attrib_list);
1363     }
1364     return setError(EGL_BAD_CONFIG, EGL_NO_SURFACE);
1365 }
1366
1367 // ----------------------------------------------------------------------------
1368 // EGL_EGLEXT_VERSION 3
1369 // ----------------------------------------------------------------------------
1370
1371 EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface,
1372         const EGLint *attrib_list)
1373 {
1374     clearError();
1375
1376     const egl_display_ptr dp = validate_display(dpy);
1377     if (!dp) return EGL_FALSE;
1378
1379     SurfaceRef _s(dp.get(), surface);
1380     if (!_s.get())
1381         return setError(EGL_BAD_SURFACE, EGL_FALSE);
1382
1383     egl_surface_t const * const s = get_surface(surface);
1384     if (s->cnx->egl.eglLockSurfaceKHR) {
1385         return s->cnx->egl.eglLockSurfaceKHR(
1386                 dp->disp.dpy, s->surface, attrib_list);
1387     }
1388     return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1389 }
1390
1391 EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface)
1392 {
1393     clearError();
1394
1395     const egl_display_ptr dp = validate_display(dpy);
1396     if (!dp) return EGL_FALSE;
1397
1398     SurfaceRef _s(dp.get(), surface);
1399     if (!_s.get())
1400         return setError(EGL_BAD_SURFACE, EGL_FALSE);
1401
1402     egl_surface_t const * const s = get_surface(surface);
1403     if (s->cnx->egl.eglUnlockSurfaceKHR) {
1404         return s->cnx->egl.eglUnlockSurfaceKHR(dp->disp.dpy, s->surface);
1405     }
1406     return setError(EGL_BAD_DISPLAY, EGL_FALSE);
1407 }
1408
1409 EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target,
1410         EGLClientBuffer buffer, const EGLint *attrib_list)
1411 {
1412     clearError();
1413
1414     const egl_display_ptr dp = validate_display(dpy);
1415     if (!dp) return EGL_NO_IMAGE_KHR;
1416
1417     ContextRef _c(dp.get(), ctx);
1418     egl_context_t * const c = _c.get();
1419
1420     EGLImageKHR result = EGL_NO_IMAGE_KHR;
1421     egl_connection_t* const cnx = &gEGLImpl;
1422     if (cnx->dso && cnx->egl.eglCreateImageKHR) {
1423         result = cnx->egl.eglCreateImageKHR(
1424                 dp->disp.dpy,
1425                 c ? c->context : EGL_NO_CONTEXT,
1426                 target, buffer, attrib_list);
1427     }
1428     return result;
1429 }
1430
1431 EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img)
1432 {
1433     clearError();
1434
1435     const egl_display_ptr dp = validate_display(dpy);
1436     if (!dp) return EGL_FALSE;
1437
1438     EGLBoolean result = EGL_FALSE;
1439     egl_connection_t* const cnx = &gEGLImpl;
1440     if (cnx->dso && cnx->egl.eglDestroyImageKHR) {
1441         result = cnx->egl.eglDestroyImageKHR(dp->disp.dpy, img);
1442     }
1443     return result;
1444 }
1445
1446 // ----------------------------------------------------------------------------
1447 // EGL_EGLEXT_VERSION 5
1448 // ----------------------------------------------------------------------------
1449
1450
1451 EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list)
1452 {
1453     clearError();
1454
1455     const egl_display_ptr dp = validate_display(dpy);
1456     if (!dp) return EGL_NO_SYNC_KHR;
1457
1458     EGLSyncKHR result = EGL_NO_SYNC_KHR;
1459     egl_connection_t* const cnx = &gEGLImpl;
1460     if (cnx->dso && cnx->egl.eglCreateSyncKHR) {
1461         result = cnx->egl.eglCreateSyncKHR(dp->disp.dpy, type, attrib_list);
1462     }
1463     return result;
1464 }
1465
1466 EGLBoolean eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync)
1467 {
1468     clearError();
1469
1470     const egl_display_ptr dp = validate_display(dpy);
1471     if (!dp) return EGL_FALSE;
1472
1473     EGLBoolean result = EGL_FALSE;
1474     egl_connection_t* const cnx = &gEGLImpl;
1475     if (cnx->dso && cnx->egl.eglDestroySyncKHR) {
1476         result = cnx->egl.eglDestroySyncKHR(dp->disp.dpy, sync);
1477     }
1478     return result;
1479 }
1480
1481 EGLBoolean eglSignalSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode) {
1482     clearError();
1483
1484     const egl_display_ptr dp = validate_display(dpy);
1485     if (!dp) return EGL_FALSE;
1486
1487     EGLBoolean result = EGL_FALSE;
1488     egl_connection_t* const cnx = &gEGLImpl;
1489     if (cnx->dso && cnx->egl.eglSignalSyncKHR) {
1490         result = cnx->egl.eglSignalSyncKHR(
1491                 dp->disp.dpy, sync, mode);
1492     }
1493     return result;
1494 }
1495
1496 EGLint eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync,
1497         EGLint flags, EGLTimeKHR timeout)
1498 {
1499     clearError();
1500
1501     const egl_display_ptr dp = validate_display(dpy);
1502     if (!dp) return EGL_FALSE;
1503
1504     EGLBoolean result = EGL_FALSE;
1505     egl_connection_t* const cnx = &gEGLImpl;
1506     if (cnx->dso && cnx->egl.eglClientWaitSyncKHR) {
1507         result = cnx->egl.eglClientWaitSyncKHR(
1508                 dp->disp.dpy, sync, flags, timeout);
1509     }
1510     return result;
1511 }
1512
1513 EGLBoolean eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync,
1514         EGLint attribute, EGLint *value)
1515 {
1516     clearError();
1517
1518     const egl_display_ptr dp = validate_display(dpy);
1519     if (!dp) return EGL_FALSE;
1520
1521     EGLBoolean result = EGL_FALSE;
1522     egl_connection_t* const cnx = &gEGLImpl;
1523     if (cnx->dso && cnx->egl.eglGetSyncAttribKHR) {
1524         result = cnx->egl.eglGetSyncAttribKHR(
1525                 dp->disp.dpy, sync, attribute, value);
1526     }
1527     return result;
1528 }
1529
1530 // ----------------------------------------------------------------------------
1531 // EGL_EGLEXT_VERSION 15
1532 // ----------------------------------------------------------------------------
1533
1534 EGLint eglWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags) {
1535     clearError();
1536     const egl_display_ptr dp = validate_display(dpy);
1537     if (!dp) return EGL_FALSE;
1538     EGLint result = EGL_FALSE;
1539     egl_connection_t* const cnx = &gEGLImpl;
1540     if (cnx->dso && cnx->egl.eglWaitSyncKHR) {
1541         result = cnx->egl.eglWaitSyncKHR(dp->disp.dpy, sync, flags);
1542     }
1543     return result;
1544 }
1545
1546 // ----------------------------------------------------------------------------
1547 // ANDROID extensions
1548 // ----------------------------------------------------------------------------
1549
1550 EGLint eglDupNativeFenceFDANDROID(EGLDisplay dpy, EGLSyncKHR sync)
1551 {
1552     clearError();
1553
1554     const egl_display_ptr dp = validate_display(dpy);
1555     if (!dp) return EGL_NO_NATIVE_FENCE_FD_ANDROID;
1556
1557     EGLint result = EGL_NO_NATIVE_FENCE_FD_ANDROID;
1558     egl_connection_t* const cnx = &gEGLImpl;
1559     if (cnx->dso && cnx->egl.eglDupNativeFenceFDANDROID) {
1560         result = cnx->egl.eglDupNativeFenceFDANDROID(dp->disp.dpy, sync);
1561     }
1562     return result;
1563 }
1564
1565 EGLBoolean eglPresentationTimeANDROID(EGLDisplay dpy, EGLSurface surface,
1566         EGLnsecsANDROID time)
1567 {
1568     clearError();
1569
1570     const egl_display_ptr dp = validate_display(dpy);
1571     if (!dp) {
1572         return EGL_FALSE;
1573     }
1574
1575     SurfaceRef _s(dp.get(), surface);
1576     if (!_s.get()) {
1577         setError(EGL_BAD_SURFACE, EGL_FALSE);
1578         return EGL_FALSE;
1579     }
1580
1581     egl_surface_t const * const s = get_surface(surface);
1582     native_window_set_buffers_timestamp(s->win.get(), time);
1583
1584     return EGL_TRUE;
1585 }
1586
1587 // ----------------------------------------------------------------------------
1588 // NVIDIA extensions
1589 // ----------------------------------------------------------------------------
1590 EGLuint64NV eglGetSystemTimeFrequencyNV()
1591 {
1592     clearError();
1593
1594     if (egl_init_drivers() == EGL_FALSE) {
1595         return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1596     }
1597
1598     EGLuint64NV ret = 0;
1599     egl_connection_t* const cnx = &gEGLImpl;
1600
1601     if (cnx->dso && cnx->egl.eglGetSystemTimeFrequencyNV) {
1602         return cnx->egl.eglGetSystemTimeFrequencyNV();
1603     }
1604
1605     return setErrorQuiet(EGL_BAD_DISPLAY, 0);
1606 }
1607
1608 EGLuint64NV eglGetSystemTimeNV()
1609 {
1610     clearError();
1611
1612     if (egl_init_drivers() == EGL_FALSE) {
1613         return setError(EGL_BAD_PARAMETER, EGL_FALSE);
1614     }
1615
1616     EGLuint64NV ret = 0;
1617     egl_connection_t* const cnx = &gEGLImpl;
1618
1619     if (cnx->dso && cnx->egl.eglGetSystemTimeNV) {
1620         return cnx->egl.eglGetSystemTimeNV();
1621     }
1622
1623     return setErrorQuiet(EGL_BAD_DISPLAY, 0);
1624 }
1625
1626 // ----------------------------------------------------------------------------
1627 // Partial update extension
1628 // ----------------------------------------------------------------------------
1629 EGLBoolean eglSetDamageRegionKHR(EGLDisplay dpy, EGLSurface surface,
1630         EGLint *rects, EGLint n_rects)
1631 {
1632     clearError();
1633
1634     const egl_display_ptr dp = validate_display(dpy);
1635     if (!dp) {
1636         setError(EGL_BAD_DISPLAY, EGL_FALSE);
1637         return EGL_FALSE;
1638     }
1639
1640     SurfaceRef _s(dp.get(), surface);
1641     if (!_s.get()) {
1642         setError(EGL_BAD_SURFACE, EGL_FALSE);
1643         return EGL_FALSE;
1644     }
1645
1646     egl_surface_t const * const s = get_surface(surface);
1647     if (s->cnx->egl.eglSetDamageRegionKHR) {
1648         return s->cnx->egl.eglSetDamageRegionKHR(dp->disp.dpy, s->surface,
1649                 rects, n_rects);
1650     }
1651
1652     return EGL_FALSE;
1653 }