egl_display.cpp revision 32397c1cd3327905173b36baa6fd1c579bc328ff
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#include <string.h>
18
19#include "egl_cache.h"
20#include "egl_display.h"
21#include "egl_object.h"
22#include "egl_tls.h"
23#include "egl_impl.h"
24#include "Loader.h"
25
26// ----------------------------------------------------------------------------
27namespace android {
28// ----------------------------------------------------------------------------
29
30static char const * const sVendorString     = "Android";
31static char const * const sVersionString    = "1.4 Android META-EGL";
32static char const * const sClientApiString  = "OpenGL ES";
33
34// this is the list of EGL extensions that are exposed to applications
35// some of them are mandatory because used by the ANDROID system.
36//
37// mandatory extensions are required per the CDD and not explicitly
38// checked during EGL initialization. the system *assumes* these extensions
39// are present. the system may not function properly if some mandatory
40// extensions are missing.
41//
42// NOTE: sExtensionString MUST be have a single space as the last character.
43//
44static char const * const sExtensionString  =
45        "EGL_KHR_image "                        // mandatory
46        "EGL_KHR_image_base "                   // mandatory
47        "EGL_KHR_image_pixmap "
48        "EGL_KHR_gl_texture_2D_image "
49        "EGL_KHR_gl_texture_cubemap_image "
50        "EGL_KHR_gl_renderbuffer_image "
51        "EGL_KHR_fence_sync "
52        "EGL_NV_system_time "
53        "EGL_ANDROID_image_native_buffer "      // mandatory
54        ;
55
56// extensions not exposed to applications but used by the ANDROID system
57//      "EGL_ANDROID_recordable "               // mandatory
58//      "EGL_ANDROID_blob_cache "               // strongly recommended
59
60extern void initEglTraceLevel();
61extern void setGLHooksThreadSpecific(gl_hooks_t const *value);
62
63static int cmp_configs(const void* a, const void *b) {
64    const egl_config_t& c0 = *(egl_config_t const *)a;
65    const egl_config_t& c1 = *(egl_config_t const *)b;
66    return c0<c1 ? -1 : (c1<c0 ? 1 : 0);
67}
68
69// ----------------------------------------------------------------------------
70
71egl_display_t egl_display_t::sDisplay[NUM_DISPLAYS];
72
73egl_display_t::egl_display_t() :
74    magic('_dpy'), numTotalConfigs(0), configs(0), refs(0) {
75}
76
77egl_display_t::~egl_display_t() {
78    magic = 0;
79    egl_cache_t::get()->terminate();
80}
81
82egl_display_t* egl_display_t::get(EGLDisplay dpy) {
83    uintptr_t index = uintptr_t(dpy)-1U;
84    return (index >= NUM_DISPLAYS) ? NULL : &sDisplay[index];
85}
86
87void egl_display_t::addObject(egl_object_t* object) {
88    Mutex::Autolock _l(lock);
89    objects.add(object);
90}
91
92void egl_display_t::removeObject(egl_object_t* object) {
93    Mutex::Autolock _l(lock);
94    objects.remove(object);
95}
96
97bool egl_display_t::getObject(egl_object_t* object) const {
98    Mutex::Autolock _l(lock);
99    if (objects.indexOf(object) >= 0) {
100        if (object->getDisplay() == this) {
101            object->incRef();
102            return true;
103        }
104    }
105    return false;
106}
107
108EGLDisplay egl_display_t::getFromNativeDisplay(EGLNativeDisplayType disp) {
109    if (uintptr_t(disp) >= NUM_DISPLAYS)
110        return NULL;
111
112    return sDisplay[uintptr_t(disp)].getDisplay(disp);
113}
114
115EGLDisplay egl_display_t::getDisplay(EGLNativeDisplayType display) {
116
117    Mutex::Autolock _l(lock);
118
119    // get our driver loader
120    Loader& loader(Loader::getInstance());
121
122    for (int i = 0; i < IMPL_NUM_IMPLEMENTATIONS; i++) {
123        egl_connection_t* const cnx = &gEGLImpl[i];
124        if (cnx->dso && disp[i].dpy == EGL_NO_DISPLAY) {
125            EGLDisplay dpy = cnx->egl.eglGetDisplay(display);
126            disp[i].dpy = dpy;
127            if (dpy == EGL_NO_DISPLAY) {
128                loader.close(cnx->dso);
129                cnx->dso = NULL;
130            }
131        }
132    }
133
134    return EGLDisplay(uintptr_t(display) + 1U);
135}
136
137EGLBoolean egl_display_t::initialize(EGLint *major, EGLint *minor) {
138
139    Mutex::Autolock _l(lock);
140
141    if (refs > 0) {
142        if (major != NULL)
143            *major = VERSION_MAJOR;
144        if (minor != NULL)
145            *minor = VERSION_MINOR;
146        refs++;
147        return EGL_TRUE;
148    }
149
150#if EGL_TRACE
151
152    // Called both at early_init time and at this time. (Early_init is pre-zygote, so
153    // the information from that call may be stale.)
154    initEglTraceLevel();
155
156#endif
157
158    setGLHooksThreadSpecific(&gHooksNoContext);
159
160    // initialize each EGL and
161    // build our own extension string first, based on the extension we know
162    // and the extension supported by our client implementation
163    for (int i = 0; i < IMPL_NUM_IMPLEMENTATIONS; i++) {
164        egl_connection_t* const cnx = &gEGLImpl[i];
165        cnx->major = -1;
166        cnx->minor = -1;
167        if (!cnx->dso)
168            continue;
169
170#if defined(ADRENO130)
171#warning "Adreno-130 eglInitialize() workaround"
172        /*
173         * The ADRENO 130 driver returns a different EGLDisplay each time
174         * eglGetDisplay() is called, but also makes the EGLDisplay invalid
175         * after eglTerminate() has been called, so that eglInitialize()
176         * cannot be called again. Therefore, we need to make sure to call
177         * eglGetDisplay() before calling eglInitialize();
178         */
179        if (i == IMPL_HARDWARE) {
180            disp[i].dpy =
181            cnx->egl.eglGetDisplay(EGL_DEFAULT_DISPLAY);
182        }
183#endif
184
185        EGLDisplay idpy = disp[i].dpy;
186        if (cnx->egl.eglInitialize(idpy, &cnx->major, &cnx->minor)) {
187            //ALOGD("initialized %d dpy=%p, ver=%d.%d, cnx=%p",
188            //        i, idpy, cnx->major, cnx->minor, cnx);
189
190            // display is now initialized
191            disp[i].state = egl_display_t::INITIALIZED;
192
193            // get the query-strings for this display for each implementation
194            disp[i].queryString.vendor = cnx->egl.eglQueryString(idpy,
195                    EGL_VENDOR);
196            disp[i].queryString.version = cnx->egl.eglQueryString(idpy,
197                    EGL_VERSION);
198            disp[i].queryString.extensions = cnx->egl.eglQueryString(idpy,
199                    EGL_EXTENSIONS);
200            disp[i].queryString.clientApi = cnx->egl.eglQueryString(idpy,
201                    EGL_CLIENT_APIS);
202
203        } else {
204            ALOGW("%d: eglInitialize(%p) failed (%s)", i, idpy,
205                    egl_tls_t::egl_strerror(cnx->egl.eglGetError()));
206        }
207    }
208
209    // the query strings are per-display
210    mVendorString.setTo(sVendorString);
211    mVersionString.setTo(sVersionString);
212    mClientApiString.setTo(sClientApiString);
213
214    // we only add extensions that exist in at least one implementation
215    char const* start = sExtensionString;
216    char const* end;
217    do {
218        // find the space separating this extension for the next one
219        end = strchr(start, ' ');
220        if (end) {
221            // length of the extension string
222            const size_t len = end - start;
223            if (len) {
224                // NOTE: we could avoid the copy if we had strnstr.
225                const String8 ext(start, len);
226                // now go through all implementations and look for this extension
227                for (int i = 0; i < IMPL_NUM_IMPLEMENTATIONS; i++) {
228                    if (disp[i].queryString.extensions) {
229                        // if we find it, add this extension string to our list
230                        // (and don't forget the space)
231                        const char* match = strstr(disp[i].queryString.extensions, ext.string());
232                        if (match && (match[len] == ' ' || match[len] == 0)) {
233                            mExtensionString.append(start, len+1);
234                        }
235                    }
236                }
237            }
238            // process the next extension string, and skip the space.
239            start = end + 1;
240        }
241    } while (end);
242
243    egl_cache_t::get()->initialize(this);
244
245    EGLBoolean res = EGL_FALSE;
246    for (int i = 0; i < IMPL_NUM_IMPLEMENTATIONS; i++) {
247        egl_connection_t* const cnx = &gEGLImpl[i];
248        if (cnx->dso && cnx->major >= 0 && cnx->minor >= 0) {
249            EGLint n;
250            if (cnx->egl.eglGetConfigs(disp[i].dpy, 0, 0, &n)) {
251                disp[i].config = (EGLConfig*) malloc(sizeof(EGLConfig) * n);
252                if (disp[i].config) {
253                    if (cnx->egl.eglGetConfigs(disp[i].dpy, disp[i].config, n,
254                            &disp[i].numConfigs)) {
255                        numTotalConfigs += n;
256                        res = EGL_TRUE;
257                    }
258                }
259            }
260        }
261    }
262
263    if (res == EGL_TRUE) {
264        configs = new egl_config_t[numTotalConfigs];
265        for (int i = 0, k = 0; i < IMPL_NUM_IMPLEMENTATIONS; i++) {
266            egl_connection_t* const cnx = &gEGLImpl[i];
267            if (cnx->dso && cnx->major >= 0 && cnx->minor >= 0) {
268                for (int j = 0; j < disp[i].numConfigs; j++) {
269                    configs[k].impl = i;
270                    configs[k].config = disp[i].config[j];
271                    configs[k].configId = k + 1; // CONFIG_ID start at 1
272                    // store the implementation's CONFIG_ID
273                    cnx->egl.eglGetConfigAttrib(disp[i].dpy, disp[i].config[j],
274                            EGL_CONFIG_ID, &configs[k].implConfigId);
275                    k++;
276                }
277            }
278        }
279
280        // sort our configurations so we can do binary-searches
281        qsort(configs, numTotalConfigs, sizeof(egl_config_t), cmp_configs);
282
283        refs++;
284        if (major != NULL)
285            *major = VERSION_MAJOR;
286        if (minor != NULL)
287            *minor = VERSION_MINOR;
288        return EGL_TRUE;
289    }
290    return setError(EGL_NOT_INITIALIZED, EGL_FALSE);
291}
292
293EGLBoolean egl_display_t::terminate() {
294
295    Mutex::Autolock _l(lock);
296
297    if (refs == 0) {
298        return setError(EGL_NOT_INITIALIZED, EGL_FALSE);
299    }
300
301    // this is specific to Android, display termination is ref-counted.
302    if (refs > 1) {
303        refs--;
304        return EGL_TRUE;
305    }
306
307    EGLBoolean res = EGL_FALSE;
308    for (int i = 0; i < IMPL_NUM_IMPLEMENTATIONS; i++) {
309        egl_connection_t* const cnx = &gEGLImpl[i];
310        if (cnx->dso && disp[i].state == egl_display_t::INITIALIZED) {
311            if (cnx->egl.eglTerminate(disp[i].dpy) == EGL_FALSE) {
312                ALOGW("%d: eglTerminate(%p) failed (%s)", i, disp[i].dpy,
313                        egl_tls_t::egl_strerror(cnx->egl.eglGetError()));
314            }
315            // REVISIT: it's unclear what to do if eglTerminate() fails
316            free(disp[i].config);
317
318            disp[i].numConfigs = 0;
319            disp[i].config = 0;
320            disp[i].state = egl_display_t::TERMINATED;
321
322            res = EGL_TRUE;
323        }
324    }
325
326    // Mark all objects remaining in the list as terminated, unless
327    // there are no reference to them, it which case, we're free to
328    // delete them.
329    size_t count = objects.size();
330    ALOGW_IF(count, "eglTerminate() called w/ %d objects remaining", count);
331    for (size_t i=0 ; i<count ; i++) {
332        egl_object_t* o = objects.itemAt(i);
333        o->destroy();
334    }
335
336    // this marks all object handles are "terminated"
337    objects.clear();
338
339    refs--;
340    numTotalConfigs = 0;
341    delete[] configs;
342    return res;
343}
344
345
346// ----------------------------------------------------------------------------
347}; // namespace android
348// ----------------------------------------------------------------------------
349