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