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