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