121558daf691dbcdff4a41e659fd013273db4d0b7Jesse Hall/*
2518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian ** Copyright 2007, The Android Open Source Project
3518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian **
421558daf691dbcdff4a41e659fd013273db4d0b7Jesse Hall ** Licensed under the Apache License, Version 2.0 (the "License");
521558daf691dbcdff4a41e659fd013273db4d0b7Jesse Hall ** you may not use this file except in compliance with the License.
621558daf691dbcdff4a41e659fd013273db4d0b7Jesse Hall ** You may obtain a copy of the License at
7518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian **
821558daf691dbcdff4a41e659fd013273db4d0b7Jesse Hall **     http://www.apache.org/licenses/LICENSE-2.0
9518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian **
1021558daf691dbcdff4a41e659fd013273db4d0b7Jesse Hall ** Unless required by applicable law or agreed to in writing, software
1121558daf691dbcdff4a41e659fd013273db4d0b7Jesse Hall ** distributed under the License is distributed on an "AS IS" BASIS,
1221558daf691dbcdff4a41e659fd013273db4d0b7Jesse Hall ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1321558daf691dbcdff4a41e659fd013273db4d0b7Jesse Hall ** See the License for the specific language governing permissions and
14518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian ** limitations under the License.
15518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian */
16518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
17b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall#define __STDC_LIMIT_MACROS 1
18b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall
194b9511c16195a646242eff833b0af212933b6ecaMathias Agopian#include <string.h>
204b9511c16195a646242eff833b0af212933b6ecaMathias Agopian
2139c24a20bbc697630d2b92c251b70c04d6f9d00cMathias Agopian#include "../egl_impl.h"
2239c24a20bbc697630d2b92c251b70c04d6f9d00cMathias Agopian
23aca51c06f38155f1435fbc6944d7fc0a9bf1e4e9Jamie Gennis#include "egl_cache.h"
24518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian#include "egl_display.h"
25518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian#include "egl_object.h"
26518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian#include "egl_tls.h"
27518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian#include "Loader.h"
287db993a98b9239bd4e384cc4aa128262fe3cf52cMathias Agopian#include <cutils/properties.h>
29518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
30518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian// ----------------------------------------------------------------------------
31518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopiannamespace android {
32518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian// ----------------------------------------------------------------------------
33518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
344b9511c16195a646242eff833b0af212933b6ecaMathias Agopianstatic char const * const sVendorString     = "Android";
354b9511c16195a646242eff833b0af212933b6ecaMathias Agopianstatic char const * const sVersionString    = "1.4 Android META-EGL";
36cc2b1560e87369676a2d13f17bd1ff4021a91819Mathias Agopianstatic char const * const sClientApiString  = "OpenGL_ES";
374b9511c16195a646242eff833b0af212933b6ecaMathias Agopian
3821558daf691dbcdff4a41e659fd013273db4d0b7Jesse Hallextern char const * const gBuiltinExtensionString;
39e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopianextern char const * const gExtensionString;
404b9511c16195a646242eff833b0af212933b6ecaMathias Agopian
41518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopianextern void initEglTraceLevel();
42b13c78f8520ef5a96effdee977bbacb881236c66Siva Velusamyextern void initEglDebugLevel();
43518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopianextern void setGLHooksThreadSpecific(gl_hooks_t const *value);
44518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
45518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian// ----------------------------------------------------------------------------
46518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
47c2e41222bf02a6579763974f82d65875cfa43481Jesse Hallstatic bool findExtension(const char* exts, const char* name, size_t nameLen) {
48c2e41222bf02a6579763974f82d65875cfa43481Jesse Hall    if (exts) {
49c2e41222bf02a6579763974f82d65875cfa43481Jesse Hall        const char* match = strstr(exts, name);
50c2e41222bf02a6579763974f82d65875cfa43481Jesse Hall        if (match && (match[nameLen] == '\0' || match[nameLen] == ' ')) {
51c2e41222bf02a6579763974f82d65875cfa43481Jesse Hall            return true;
52c2e41222bf02a6579763974f82d65875cfa43481Jesse Hall        }
53c2e41222bf02a6579763974f82d65875cfa43481Jesse Hall    }
54c2e41222bf02a6579763974f82d65875cfa43481Jesse Hall    return false;
55c2e41222bf02a6579763974f82d65875cfa43481Jesse Hall}
56c2e41222bf02a6579763974f82d65875cfa43481Jesse Hall
57518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopianegl_display_t egl_display_t::sDisplay[NUM_DISPLAYS];
58518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
59518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopianegl_display_t::egl_display_t() :
60a0fef1c8bb22443402fb3aeda7ce70f7d5775b0aJesse Hall    magic('_dpy'), finishOnSwap(false), traceGpuCompletion(false), refs(0) {
61518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian}
62518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
63518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopianegl_display_t::~egl_display_t() {
64518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    magic = 0;
65766010858ea7696d64f1b559413670bdd8627595Jamie Gennis    egl_cache_t::get()->terminate();
66518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian}
67518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
68518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopianegl_display_t* egl_display_t::get(EGLDisplay dpy) {
69518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    uintptr_t index = uintptr_t(dpy)-1U;
70518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    return (index >= NUM_DISPLAYS) ? NULL : &sDisplay[index];
71518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian}
72518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
73518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopianvoid egl_display_t::addObject(egl_object_t* object) {
74518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    Mutex::Autolock _l(lock);
75518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    objects.add(object);
76518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian}
77518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
785b287a6ea8dfac7ab3e03ae1e98f9e2214cbae09Mathias Agopianvoid egl_display_t::removeObject(egl_object_t* object) {
79518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    Mutex::Autolock _l(lock);
805b287a6ea8dfac7ab3e03ae1e98f9e2214cbae09Mathias Agopian    objects.remove(object);
81518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian}
82518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
83f0480de37492597a5c5cf1e6f8346f1467e3a552Mathias Agopianbool egl_display_t::getObject(egl_object_t* object) const {
84518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    Mutex::Autolock _l(lock);
855b287a6ea8dfac7ab3e03ae1e98f9e2214cbae09Mathias Agopian    if (objects.indexOf(object) >= 0) {
86f0480de37492597a5c5cf1e6f8346f1467e3a552Mathias Agopian        if (object->getDisplay() == this) {
87f0480de37492597a5c5cf1e6f8346f1467e3a552Mathias Agopian            object->incRef();
88f0480de37492597a5c5cf1e6f8346f1467e3a552Mathias Agopian            return true;
89f0480de37492597a5c5cf1e6f8346f1467e3a552Mathias Agopian        }
90518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    }
91518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    return false;
92518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian}
93518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
94518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias AgopianEGLDisplay egl_display_t::getFromNativeDisplay(EGLNativeDisplayType disp) {
95518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    if (uintptr_t(disp) >= NUM_DISPLAYS)
96518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        return NULL;
97518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
98518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    return sDisplay[uintptr_t(disp)].getDisplay(disp);
99518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian}
100518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
101518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias AgopianEGLDisplay egl_display_t::getDisplay(EGLNativeDisplayType display) {
102518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
103518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    Mutex::Autolock _l(lock);
104518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
105518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    // get our driver loader
106518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    Loader& loader(Loader::getInstance());
107518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
108ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian    egl_connection_t* const cnx = &gEGLImpl;
109ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian    if (cnx->dso && disp.dpy == EGL_NO_DISPLAY) {
110ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian        EGLDisplay dpy = cnx->egl.eglGetDisplay(display);
111ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian        disp.dpy = dpy;
112ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian        if (dpy == EGL_NO_DISPLAY) {
113ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian            loader.close(cnx->dso);
114ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian            cnx->dso = NULL;
115518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        }
116518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    }
117518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
118518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    return EGLDisplay(uintptr_t(display) + 1U);
119518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian}
120518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
121518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias AgopianEGLBoolean egl_display_t::initialize(EGLint *major, EGLint *minor) {
122518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
123518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    Mutex::Autolock _l(lock);
124518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
125518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    if (refs > 0) {
126518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        if (major != NULL)
127518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian            *major = VERSION_MAJOR;
128518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        if (minor != NULL)
129518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian            *minor = VERSION_MINOR;
130518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        refs++;
131518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        return EGL_TRUE;
132518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    }
133518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
134518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian#if EGL_TRACE
135518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
136518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    // Called both at early_init time and at this time. (Early_init is pre-zygote, so
137518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    // the information from that call may be stale.)
138518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    initEglTraceLevel();
139b13c78f8520ef5a96effdee977bbacb881236c66Siva Velusamy    initEglDebugLevel();
140518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
141518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian#endif
142518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
143518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    setGLHooksThreadSpecific(&gHooksNoContext);
144518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
145518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    // initialize each EGL and
146518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    // build our own extension string first, based on the extension we know
147518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    // and the extension supported by our client implementation
148ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian
149ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian    egl_connection_t* const cnx = &gEGLImpl;
150ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian    cnx->major = -1;
151ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian    cnx->minor = -1;
152ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian    if (cnx->dso) {
153ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian        EGLDisplay idpy = disp.dpy;
154518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        if (cnx->egl.eglInitialize(idpy, &cnx->major, &cnx->minor)) {
155ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian            //ALOGD("initialized dpy=%p, ver=%d.%d, cnx=%p",
156ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian            //        idpy, cnx->major, cnx->minor, cnx);
157518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
158518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian            // display is now initialized
159ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian            disp.state = egl_display_t::INITIALIZED;
160518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
161518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian            // get the query-strings for this display for each implementation
162ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian            disp.queryString.vendor = cnx->egl.eglQueryString(idpy,
163518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                    EGL_VENDOR);
164ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian            disp.queryString.version = cnx->egl.eglQueryString(idpy,
165518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                    EGL_VERSION);
166ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian            disp.queryString.extensions = cnx->egl.eglQueryString(idpy,
167518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                    EGL_EXTENSIONS);
168ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian            disp.queryString.clientApi = cnx->egl.eglQueryString(idpy,
169518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                    EGL_CLIENT_APIS);
170518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
171518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        } else {
172ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian            ALOGW("eglInitialize(%p) failed (%s)", idpy,
173518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian                    egl_tls_t::egl_strerror(cnx->egl.eglGetError()));
174518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        }
175518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    }
176518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
1774b9511c16195a646242eff833b0af212933b6ecaMathias Agopian    // the query strings are per-display
1784b9511c16195a646242eff833b0af212933b6ecaMathias Agopian    mVendorString.setTo(sVendorString);
1794b9511c16195a646242eff833b0af212933b6ecaMathias Agopian    mVersionString.setTo(sVersionString);
1804b9511c16195a646242eff833b0af212933b6ecaMathias Agopian    mClientApiString.setTo(sClientApiString);
1814b9511c16195a646242eff833b0af212933b6ecaMathias Agopian
18221558daf691dbcdff4a41e659fd013273db4d0b7Jesse Hall    mExtensionString.setTo(gBuiltinExtensionString);
183e9b3dfb7d5cc233747407381a51a081c335dc076Mathias Agopian    char const* start = gExtensionString;
1844b9511c16195a646242eff833b0af212933b6ecaMathias Agopian    char const* end;
1854b9511c16195a646242eff833b0af212933b6ecaMathias Agopian    do {
1864b9511c16195a646242eff833b0af212933b6ecaMathias Agopian        // find the space separating this extension for the next one
1874b9511c16195a646242eff833b0af212933b6ecaMathias Agopian        end = strchr(start, ' ');
1884b9511c16195a646242eff833b0af212933b6ecaMathias Agopian        if (end) {
1894b9511c16195a646242eff833b0af212933b6ecaMathias Agopian            // length of the extension string
1904b9511c16195a646242eff833b0af212933b6ecaMathias Agopian            const size_t len = end - start;
191f3ae82d8134e7f5a2f0432ef809569bfa418883bMathias Agopian            if (len) {
192f3ae82d8134e7f5a2f0432ef809569bfa418883bMathias Agopian                // NOTE: we could avoid the copy if we had strnstr.
193f3ae82d8134e7f5a2f0432ef809569bfa418883bMathias Agopian                const String8 ext(start, len);
194c2e41222bf02a6579763974f82d65875cfa43481Jesse Hall                if (findExtension(disp.queryString.extensions, ext.string(),
195c2e41222bf02a6579763974f82d65875cfa43481Jesse Hall                        len)) {
196c2e41222bf02a6579763974f82d65875cfa43481Jesse Hall                    mExtensionString.append(start, len+1);
1974b9511c16195a646242eff833b0af212933b6ecaMathias Agopian                }
1984b9511c16195a646242eff833b0af212933b6ecaMathias Agopian            }
1994b9511c16195a646242eff833b0af212933b6ecaMathias Agopian            // process the next extension string, and skip the space.
2004b9511c16195a646242eff833b0af212933b6ecaMathias Agopian            start = end + 1;
2014b9511c16195a646242eff833b0af212933b6ecaMathias Agopian        }
2024b9511c16195a646242eff833b0af212933b6ecaMathias Agopian    } while (end);
2034b9511c16195a646242eff833b0af212933b6ecaMathias Agopian
204aca51c06f38155f1435fbc6944d7fc0a9bf1e4e9Jamie Gennis    egl_cache_t::get()->initialize(this);
205aca51c06f38155f1435fbc6944d7fc0a9bf1e4e9Jamie Gennis
2067db993a98b9239bd4e384cc4aa128262fe3cf52cMathias Agopian    char value[PROPERTY_VALUE_MAX];
2077db993a98b9239bd4e384cc4aa128262fe3cf52cMathias Agopian    property_get("debug.egl.finish", value, "0");
2087db993a98b9239bd4e384cc4aa128262fe3cf52cMathias Agopian    if (atoi(value)) {
2097db993a98b9239bd4e384cc4aa128262fe3cf52cMathias Agopian        finishOnSwap = true;
2107db993a98b9239bd4e384cc4aa128262fe3cf52cMathias Agopian    }
2117db993a98b9239bd4e384cc4aa128262fe3cf52cMathias Agopian
21228ef8d7911dbfd1bf8256fb43acba894d87fc07aJamie Gennis    property_get("debug.egl.traceGpuCompletion", value, "0");
21328ef8d7911dbfd1bf8256fb43acba894d87fc07aJamie Gennis    if (atoi(value)) {
21428ef8d7911dbfd1bf8256fb43acba894d87fc07aJamie Gennis        traceGpuCompletion = true;
21528ef8d7911dbfd1bf8256fb43acba894d87fc07aJamie Gennis    }
21628ef8d7911dbfd1bf8256fb43acba894d87fc07aJamie Gennis
2177773c435bc5da8217433e1b242d3a6712a17b5f7Mathias Agopian    refs++;
2187773c435bc5da8217433e1b242d3a6712a17b5f7Mathias Agopian    if (major != NULL)
2197773c435bc5da8217433e1b242d3a6712a17b5f7Mathias Agopian        *major = VERSION_MAJOR;
2207773c435bc5da8217433e1b242d3a6712a17b5f7Mathias Agopian    if (minor != NULL)
2217773c435bc5da8217433e1b242d3a6712a17b5f7Mathias Agopian        *minor = VERSION_MINOR;
222a0fef1c8bb22443402fb3aeda7ce70f7d5775b0aJesse Hall
223a0fef1c8bb22443402fb3aeda7ce70f7d5775b0aJesse Hall    mHibernation.setDisplayValid(true);
224a0fef1c8bb22443402fb3aeda7ce70f7d5775b0aJesse Hall
2257773c435bc5da8217433e1b242d3a6712a17b5f7Mathias Agopian    return EGL_TRUE;
226518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian}
227518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
228518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias AgopianEGLBoolean egl_display_t::terminate() {
229518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
230518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    Mutex::Autolock _l(lock);
231518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
232518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    if (refs == 0) {
233fe98127eaaf82686ba750001e2b771abece44e97Mathias Agopian        /*
234fe98127eaaf82686ba750001e2b771abece44e97Mathias Agopian         * From the EGL spec (3.2):
235fe98127eaaf82686ba750001e2b771abece44e97Mathias Agopian         * "Termination of a display that has already been terminated,
236fe98127eaaf82686ba750001e2b771abece44e97Mathias Agopian         *  (...), is allowed, but the only effect of such a call is
237fe98127eaaf82686ba750001e2b771abece44e97Mathias Agopian         *  to return EGL_TRUE (...)
238fe98127eaaf82686ba750001e2b771abece44e97Mathias Agopian         */
239fe98127eaaf82686ba750001e2b771abece44e97Mathias Agopian        return EGL_TRUE;
240518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    }
241518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
242518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    // this is specific to Android, display termination is ref-counted.
243518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    if (refs > 1) {
244518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        refs--;
245518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian        return EGL_TRUE;
246518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    }
247518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
248518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    EGLBoolean res = EGL_FALSE;
249ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian    egl_connection_t* const cnx = &gEGLImpl;
250ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian    if (cnx->dso && disp.state == egl_display_t::INITIALIZED) {
251ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian        if (cnx->egl.eglTerminate(disp.dpy) == EGL_FALSE) {
252ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian            ALOGW("eglTerminate(%p) failed (%s)", disp.dpy,
253ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian                    egl_tls_t::egl_strerror(cnx->egl.eglGetError()));
254ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian        }
255ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian        // REVISIT: it's unclear what to do if eglTerminate() fails
256ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian        disp.state = egl_display_t::TERMINATED;
257ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian        res = EGL_TRUE;
258518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    }
259518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
260a0fef1c8bb22443402fb3aeda7ce70f7d5775b0aJesse Hall    mHibernation.setDisplayValid(false);
261a0fef1c8bb22443402fb3aeda7ce70f7d5775b0aJesse Hall
262a08cf6e3a4ee045608bc8991a779dedb4f281a3fJamie Gennis    // Reset the extension string since it will be regenerated if we get
263a08cf6e3a4ee045608bc8991a779dedb4f281a3fJamie Gennis    // reinitialized.
264a08cf6e3a4ee045608bc8991a779dedb4f281a3fJamie Gennis    mExtensionString.setTo("");
265a08cf6e3a4ee045608bc8991a779dedb4f281a3fJamie Gennis
2665b287a6ea8dfac7ab3e03ae1e98f9e2214cbae09Mathias Agopian    // Mark all objects remaining in the list as terminated, unless
2675b287a6ea8dfac7ab3e03ae1e98f9e2214cbae09Mathias Agopian    // there are no reference to them, it which case, we're free to
2685b287a6ea8dfac7ab3e03ae1e98f9e2214cbae09Mathias Agopian    // delete them.
2695b287a6ea8dfac7ab3e03ae1e98f9e2214cbae09Mathias Agopian    size_t count = objects.size();
27032397c1cd3327905173b36baa6fd1c579bc328ffSteve Block    ALOGW_IF(count, "eglTerminate() called w/ %d objects remaining", count);
2715b287a6ea8dfac7ab3e03ae1e98f9e2214cbae09Mathias Agopian    for (size_t i=0 ; i<count ; i++) {
2725b287a6ea8dfac7ab3e03ae1e98f9e2214cbae09Mathias Agopian        egl_object_t* o = objects.itemAt(i);
2735b287a6ea8dfac7ab3e03ae1e98f9e2214cbae09Mathias Agopian        o->destroy();
2745b287a6ea8dfac7ab3e03ae1e98f9e2214cbae09Mathias Agopian    }
2755b287a6ea8dfac7ab3e03ae1e98f9e2214cbae09Mathias Agopian
2765b287a6ea8dfac7ab3e03ae1e98f9e2214cbae09Mathias Agopian    // this marks all object handles are "terminated"
2775b287a6ea8dfac7ab3e03ae1e98f9e2214cbae09Mathias Agopian    objects.clear();
278518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
279518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    refs--;
280518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian    return res;
281518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian}
282518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
283fb87e54a9af8bc5063ca4deebe81d90126992480Mathias Agopianvoid egl_display_t::loseCurrent(egl_context_t * cur_c)
284fb87e54a9af8bc5063ca4deebe81d90126992480Mathias Agopian{
285fb87e54a9af8bc5063ca4deebe81d90126992480Mathias Agopian    if (cur_c) {
286a4b2c041828d1074dca3b999407e7dd85568c5aaMathias Agopian        egl_display_t* display = cur_c->getDisplay();
287a4b2c041828d1074dca3b999407e7dd85568c5aaMathias Agopian        if (display) {
288a4b2c041828d1074dca3b999407e7dd85568c5aaMathias Agopian            display->loseCurrentImpl(cur_c);
289a4b2c041828d1074dca3b999407e7dd85568c5aaMathias Agopian        }
290a4b2c041828d1074dca3b999407e7dd85568c5aaMathias Agopian    }
291a4b2c041828d1074dca3b999407e7dd85568c5aaMathias Agopian}
292fb87e54a9af8bc5063ca4deebe81d90126992480Mathias Agopian
293a4b2c041828d1074dca3b999407e7dd85568c5aaMathias Agopianvoid egl_display_t::loseCurrentImpl(egl_context_t * cur_c)
294a4b2c041828d1074dca3b999407e7dd85568c5aaMathias Agopian{
295a4b2c041828d1074dca3b999407e7dd85568c5aaMathias Agopian    // by construction, these are either 0 or valid (possibly terminated)
296a4b2c041828d1074dca3b999407e7dd85568c5aaMathias Agopian    // it should be impossible for these to be invalid
297a4b2c041828d1074dca3b999407e7dd85568c5aaMathias Agopian    ContextRef _cur_c(cur_c);
298a4b2c041828d1074dca3b999407e7dd85568c5aaMathias Agopian    SurfaceRef _cur_r(cur_c ? get_surface(cur_c->read) : NULL);
299a4b2c041828d1074dca3b999407e7dd85568c5aaMathias Agopian    SurfaceRef _cur_d(cur_c ? get_surface(cur_c->draw) : NULL);
300a4b2c041828d1074dca3b999407e7dd85568c5aaMathias Agopian
301a4b2c041828d1074dca3b999407e7dd85568c5aaMathias Agopian    { // scope for the lock
302a4b2c041828d1074dca3b999407e7dd85568c5aaMathias Agopian        Mutex::Autolock _l(lock);
303fb87e54a9af8bc5063ca4deebe81d90126992480Mathias Agopian        cur_c->onLooseCurrent();
304fb87e54a9af8bc5063ca4deebe81d90126992480Mathias Agopian
305fb87e54a9af8bc5063ca4deebe81d90126992480Mathias Agopian    }
306a4b2c041828d1074dca3b999407e7dd85568c5aaMathias Agopian
307a4b2c041828d1074dca3b999407e7dd85568c5aaMathias Agopian    // This cannot be called with the lock held because it might end-up
308a4b2c041828d1074dca3b999407e7dd85568c5aaMathias Agopian    // calling back into EGL (in particular when a surface is destroyed
309a4b2c041828d1074dca3b999407e7dd85568c5aaMathias Agopian    // it calls ANativeWindow::disconnect
310a4b2c041828d1074dca3b999407e7dd85568c5aaMathias Agopian    _cur_c.release();
311a4b2c041828d1074dca3b999407e7dd85568c5aaMathias Agopian    _cur_r.release();
312a4b2c041828d1074dca3b999407e7dd85568c5aaMathias Agopian    _cur_d.release();
313fb87e54a9af8bc5063ca4deebe81d90126992480Mathias Agopian}
314fb87e54a9af8bc5063ca4deebe81d90126992480Mathias Agopian
315fb87e54a9af8bc5063ca4deebe81d90126992480Mathias AgopianEGLBoolean egl_display_t::makeCurrent(egl_context_t* c, egl_context_t* cur_c,
316fb87e54a9af8bc5063ca4deebe81d90126992480Mathias Agopian        EGLSurface draw, EGLSurface read, EGLContext ctx,
317fb87e54a9af8bc5063ca4deebe81d90126992480Mathias Agopian        EGLSurface impl_draw, EGLSurface impl_read, EGLContext impl_ctx)
318fb87e54a9af8bc5063ca4deebe81d90126992480Mathias Agopian{
319fb87e54a9af8bc5063ca4deebe81d90126992480Mathias Agopian    EGLBoolean result;
320a4b2c041828d1074dca3b999407e7dd85568c5aaMathias Agopian
321a4b2c041828d1074dca3b999407e7dd85568c5aaMathias Agopian    // by construction, these are either 0 or valid (possibly terminated)
322a4b2c041828d1074dca3b999407e7dd85568c5aaMathias Agopian    // it should be impossible for these to be invalid
323a4b2c041828d1074dca3b999407e7dd85568c5aaMathias Agopian    ContextRef _cur_c(cur_c);
324a4b2c041828d1074dca3b999407e7dd85568c5aaMathias Agopian    SurfaceRef _cur_r(cur_c ? get_surface(cur_c->read) : NULL);
325a4b2c041828d1074dca3b999407e7dd85568c5aaMathias Agopian    SurfaceRef _cur_d(cur_c ? get_surface(cur_c->draw) : NULL);
326a4b2c041828d1074dca3b999407e7dd85568c5aaMathias Agopian
327a4b2c041828d1074dca3b999407e7dd85568c5aaMathias Agopian    { // scope for the lock
328a4b2c041828d1074dca3b999407e7dd85568c5aaMathias Agopian        Mutex::Autolock _l(lock);
329fb87e54a9af8bc5063ca4deebe81d90126992480Mathias Agopian        if (c) {
330a4b2c041828d1074dca3b999407e7dd85568c5aaMathias Agopian            result = c->cnx->egl.eglMakeCurrent(
331ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian                    disp.dpy, impl_draw, impl_read, impl_ctx);
332a4b2c041828d1074dca3b999407e7dd85568c5aaMathias Agopian            if (result == EGL_TRUE) {
333a4b2c041828d1074dca3b999407e7dd85568c5aaMathias Agopian                c->onMakeCurrent(draw, read);
334258385978c517a47626161b1e644c48bcee28de1Jesse Hall                if (!cur_c) {
335a0fef1c8bb22443402fb3aeda7ce70f7d5775b0aJesse Hall                    mHibernation.incWakeCount(HibernationMachine::STRONG);
336258385978c517a47626161b1e644c48bcee28de1Jesse Hall                }
337a4b2c041828d1074dca3b999407e7dd85568c5aaMathias Agopian            }
338a4b2c041828d1074dca3b999407e7dd85568c5aaMathias Agopian        } else {
339a4b2c041828d1074dca3b999407e7dd85568c5aaMathias Agopian            result = cur_c->cnx->egl.eglMakeCurrent(
340ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopian                    disp.dpy, impl_draw, impl_read, impl_ctx);
341a4b2c041828d1074dca3b999407e7dd85568c5aaMathias Agopian            if (result == EGL_TRUE) {
342a4b2c041828d1074dca3b999407e7dd85568c5aaMathias Agopian                cur_c->onLooseCurrent();
343a0fef1c8bb22443402fb3aeda7ce70f7d5775b0aJesse Hall                mHibernation.decWakeCount(HibernationMachine::STRONG);
344a4b2c041828d1074dca3b999407e7dd85568c5aaMathias Agopian            }
345fb87e54a9af8bc5063ca4deebe81d90126992480Mathias Agopian        }
346fb87e54a9af8bc5063ca4deebe81d90126992480Mathias Agopian    }
347a4b2c041828d1074dca3b999407e7dd85568c5aaMathias Agopian
348a4b2c041828d1074dca3b999407e7dd85568c5aaMathias Agopian    if (result == EGL_TRUE) {
349a4b2c041828d1074dca3b999407e7dd85568c5aaMathias Agopian        // This cannot be called with the lock held because it might end-up
350a4b2c041828d1074dca3b999407e7dd85568c5aaMathias Agopian        // calling back into EGL (in particular when a surface is destroyed
351a4b2c041828d1074dca3b999407e7dd85568c5aaMathias Agopian        // it calls ANativeWindow::disconnect
352a4b2c041828d1074dca3b999407e7dd85568c5aaMathias Agopian        _cur_c.release();
353a4b2c041828d1074dca3b999407e7dd85568c5aaMathias Agopian        _cur_r.release();
354a4b2c041828d1074dca3b999407e7dd85568c5aaMathias Agopian        _cur_d.release();
355a4b2c041828d1074dca3b999407e7dd85568c5aaMathias Agopian    }
356a4b2c041828d1074dca3b999407e7dd85568c5aaMathias Agopian
357fb87e54a9af8bc5063ca4deebe81d90126992480Mathias Agopian    return result;
358fb87e54a9af8bc5063ca4deebe81d90126992480Mathias Agopian}
359518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian
360c2e41222bf02a6579763974f82d65875cfa43481Jesse Hallbool egl_display_t::haveExtension(const char* name, size_t nameLen) const {
361c2e41222bf02a6579763974f82d65875cfa43481Jesse Hall    if (!nameLen) {
362c2e41222bf02a6579763974f82d65875cfa43481Jesse Hall        nameLen = strlen(name);
363c2e41222bf02a6579763974f82d65875cfa43481Jesse Hall    }
364c2e41222bf02a6579763974f82d65875cfa43481Jesse Hall    return findExtension(mExtensionString.string(), name, nameLen);
365c2e41222bf02a6579763974f82d65875cfa43481Jesse Hall}
366c2e41222bf02a6579763974f82d65875cfa43481Jesse Hall
367a0fef1c8bb22443402fb3aeda7ce70f7d5775b0aJesse Hall// ----------------------------------------------------------------------------
368a0fef1c8bb22443402fb3aeda7ce70f7d5775b0aJesse Hall
369a0fef1c8bb22443402fb3aeda7ce70f7d5775b0aJesse Hallbool egl_display_t::HibernationMachine::incWakeCount(WakeRefStrength strength) {
370a0fef1c8bb22443402fb3aeda7ce70f7d5775b0aJesse Hall    Mutex::Autolock _l(mLock);
371b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall    ALOGE_IF(mWakeCount < 0 || mWakeCount == INT32_MAX,
372b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall             "Invalid WakeCount (%d) on enter\n", mWakeCount);
373a0fef1c8bb22443402fb3aeda7ce70f7d5775b0aJesse Hall
374b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall    mWakeCount++;
375a0fef1c8bb22443402fb3aeda7ce70f7d5775b0aJesse Hall    if (strength == STRONG)
376a0fef1c8bb22443402fb3aeda7ce70f7d5775b0aJesse Hall        mAttemptHibernation = false;
377a0fef1c8bb22443402fb3aeda7ce70f7d5775b0aJesse Hall
378258385978c517a47626161b1e644c48bcee28de1Jesse Hall    if (CC_UNLIKELY(mHibernating)) {
379258385978c517a47626161b1e644c48bcee28de1Jesse Hall        ALOGV("Awakening\n");
380258385978c517a47626161b1e644c48bcee28de1Jesse Hall        egl_connection_t* const cnx = &gEGLImpl;
381a0fef1c8bb22443402fb3aeda7ce70f7d5775b0aJesse Hall
382a0fef1c8bb22443402fb3aeda7ce70f7d5775b0aJesse Hall        // These conditions should be guaranteed before entering hibernation;
383a0fef1c8bb22443402fb3aeda7ce70f7d5775b0aJesse Hall        // we don't want to get into a state where we can't wake up.
384a0fef1c8bb22443402fb3aeda7ce70f7d5775b0aJesse Hall        ALOGD_IF(!mDpyValid || !cnx->egl.eglAwakenProcessIMG,
385a0fef1c8bb22443402fb3aeda7ce70f7d5775b0aJesse Hall                 "Invalid hibernation state, unable to awaken\n");
386a0fef1c8bb22443402fb3aeda7ce70f7d5775b0aJesse Hall
387258385978c517a47626161b1e644c48bcee28de1Jesse Hall        if (!cnx->egl.eglAwakenProcessIMG()) {
388258385978c517a47626161b1e644c48bcee28de1Jesse Hall            ALOGE("Failed to awaken EGL implementation\n");
389258385978c517a47626161b1e644c48bcee28de1Jesse Hall            return false;
390258385978c517a47626161b1e644c48bcee28de1Jesse Hall        }
391258385978c517a47626161b1e644c48bcee28de1Jesse Hall        mHibernating = false;
392258385978c517a47626161b1e644c48bcee28de1Jesse Hall    }
393b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall    return true;
394b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall}
395b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall
396a0fef1c8bb22443402fb3aeda7ce70f7d5775b0aJesse Hallvoid egl_display_t::HibernationMachine::decWakeCount(WakeRefStrength strength) {
397a0fef1c8bb22443402fb3aeda7ce70f7d5775b0aJesse Hall    Mutex::Autolock _l(mLock);
398b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall    ALOGE_IF(mWakeCount <= 0, "Invalid WakeCount (%d) on leave\n", mWakeCount);
399a0fef1c8bb22443402fb3aeda7ce70f7d5775b0aJesse Hall
400a0fef1c8bb22443402fb3aeda7ce70f7d5775b0aJesse Hall    mWakeCount--;
401a0fef1c8bb22443402fb3aeda7ce70f7d5775b0aJesse Hall    if (strength == STRONG)
402a0fef1c8bb22443402fb3aeda7ce70f7d5775b0aJesse Hall        mAttemptHibernation = true;
403a0fef1c8bb22443402fb3aeda7ce70f7d5775b0aJesse Hall
404a0fef1c8bb22443402fb3aeda7ce70f7d5775b0aJesse Hall    if (mWakeCount == 0 && CC_UNLIKELY(mAttemptHibernation)) {
405258385978c517a47626161b1e644c48bcee28de1Jesse Hall        egl_connection_t* const cnx = &gEGLImpl;
406258385978c517a47626161b1e644c48bcee28de1Jesse Hall        mAttemptHibernation = false;
407201f3b2da572eb27b9d4b3131e6d8c3c92a13de8Jesse Hall        if (mAllowHibernation && mDpyValid &&
408a0fef1c8bb22443402fb3aeda7ce70f7d5775b0aJesse Hall                cnx->egl.eglHibernateProcessIMG &&
409a0fef1c8bb22443402fb3aeda7ce70f7d5775b0aJesse Hall                cnx->egl.eglAwakenProcessIMG) {
410258385978c517a47626161b1e644c48bcee28de1Jesse Hall            ALOGV("Hibernating\n");
411258385978c517a47626161b1e644c48bcee28de1Jesse Hall            if (!cnx->egl.eglHibernateProcessIMG()) {
412258385978c517a47626161b1e644c48bcee28de1Jesse Hall                ALOGE("Failed to hibernate EGL implementation\n");
413258385978c517a47626161b1e644c48bcee28de1Jesse Hall                return;
414258385978c517a47626161b1e644c48bcee28de1Jesse Hall            }
415258385978c517a47626161b1e644c48bcee28de1Jesse Hall            mHibernating = true;
416258385978c517a47626161b1e644c48bcee28de1Jesse Hall        }
417258385978c517a47626161b1e644c48bcee28de1Jesse Hall    }
418258385978c517a47626161b1e644c48bcee28de1Jesse Hall}
419258385978c517a47626161b1e644c48bcee28de1Jesse Hall
420a0fef1c8bb22443402fb3aeda7ce70f7d5775b0aJesse Hallvoid egl_display_t::HibernationMachine::setDisplayValid(bool valid) {
421a0fef1c8bb22443402fb3aeda7ce70f7d5775b0aJesse Hall    Mutex::Autolock _l(mLock);
422a0fef1c8bb22443402fb3aeda7ce70f7d5775b0aJesse Hall    mDpyValid = valid;
423b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall}
424b29e5e8c2682ae145e8c56d9afb061f8da7f854cJesse Hall
425518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian// ----------------------------------------------------------------------------
426518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian}; // namespace android
427518ec112f468eb67bf681b3eec896d7bfb4ff98dMathias Agopian// ----------------------------------------------------------------------------
428