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