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