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