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