egl_display.cpp revision 766010858ea7696d64f1b559413670bdd8627595
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 "egl_cache.h" 18#include "egl_display.h" 19#include "egl_object.h" 20#include "egl_tls.h" 21#include "egl_impl.h" 22#include "Loader.h" 23 24// ---------------------------------------------------------------------------- 25namespace android { 26// ---------------------------------------------------------------------------- 27 28extern void initEglTraceLevel(); 29extern void setGLHooksThreadSpecific(gl_hooks_t const *value); 30 31static int cmp_configs(const void* a, const void *b) { 32 const egl_config_t& c0 = *(egl_config_t const *)a; 33 const egl_config_t& c1 = *(egl_config_t const *)b; 34 return c0<c1 ? -1 : (c1<c0 ? 1 : 0); 35} 36 37// ---------------------------------------------------------------------------- 38 39egl_display_t egl_display_t::sDisplay[NUM_DISPLAYS]; 40 41egl_display_t::egl_display_t() : 42 magic('_dpy'), numTotalConfigs(0), configs(0), refs(0) { 43} 44 45egl_display_t::~egl_display_t() { 46 magic = 0; 47 egl_cache_t::get()->terminate(); 48} 49 50egl_display_t* egl_display_t::get(EGLDisplay dpy) { 51 uintptr_t index = uintptr_t(dpy)-1U; 52 return (index >= NUM_DISPLAYS) ? NULL : &sDisplay[index]; 53} 54 55void egl_display_t::addObject(egl_object_t* object) { 56 Mutex::Autolock _l(lock); 57 objects.add(object); 58} 59 60void egl_display_t::removeObject(egl_object_t* object) { 61 Mutex::Autolock _l(lock); 62 objects.remove(object); 63} 64 65bool egl_display_t::getObject(egl_object_t* object) { 66 Mutex::Autolock _l(lock); 67 if (objects.indexOf(object) >= 0) { 68 object->incRef(); 69 return true; 70 } 71 return false; 72} 73 74EGLDisplay egl_display_t::getFromNativeDisplay(EGLNativeDisplayType disp) { 75 if (uintptr_t(disp) >= NUM_DISPLAYS) 76 return NULL; 77 78 return sDisplay[uintptr_t(disp)].getDisplay(disp); 79} 80 81EGLDisplay egl_display_t::getDisplay(EGLNativeDisplayType display) { 82 83 Mutex::Autolock _l(lock); 84 85 // get our driver loader 86 Loader& loader(Loader::getInstance()); 87 88 for (int i = 0; i < IMPL_NUM_IMPLEMENTATIONS; i++) { 89 egl_connection_t* const cnx = &gEGLImpl[i]; 90 if (cnx->dso && disp[i].dpy == EGL_NO_DISPLAY) { 91 EGLDisplay dpy = cnx->egl.eglGetDisplay(display); 92 disp[i].dpy = dpy; 93 if (dpy == EGL_NO_DISPLAY) { 94 loader.close(cnx->dso); 95 cnx->dso = NULL; 96 } 97 } 98 } 99 100 return EGLDisplay(uintptr_t(display) + 1U); 101} 102 103EGLBoolean egl_display_t::initialize(EGLint *major, EGLint *minor) { 104 105 Mutex::Autolock _l(lock); 106 107 if (refs > 0) { 108 if (major != NULL) 109 *major = VERSION_MAJOR; 110 if (minor != NULL) 111 *minor = VERSION_MINOR; 112 refs++; 113 return EGL_TRUE; 114 } 115 116#if EGL_TRACE 117 118 // Called both at early_init time and at this time. (Early_init is pre-zygote, so 119 // the information from that call may be stale.) 120 initEglTraceLevel(); 121 122#endif 123 124 setGLHooksThreadSpecific(&gHooksNoContext); 125 126 // initialize each EGL and 127 // build our own extension string first, based on the extension we know 128 // and the extension supported by our client implementation 129 for (int i = 0; i < IMPL_NUM_IMPLEMENTATIONS; i++) { 130 egl_connection_t* const cnx = &gEGLImpl[i]; 131 cnx->major = -1; 132 cnx->minor = -1; 133 if (!cnx->dso) 134 continue; 135 136#if defined(ADRENO130) 137#warning "Adreno-130 eglInitialize() workaround" 138 /* 139 * The ADRENO 130 driver returns a different EGLDisplay each time 140 * eglGetDisplay() is called, but also makes the EGLDisplay invalid 141 * after eglTerminate() has been called, so that eglInitialize() 142 * cannot be called again. Therefore, we need to make sure to call 143 * eglGetDisplay() before calling eglInitialize(); 144 */ 145 if (i == IMPL_HARDWARE) { 146 disp[i].dpy = 147 cnx->egl.eglGetDisplay(EGL_DEFAULT_DISPLAY); 148 } 149#endif 150 151 EGLDisplay idpy = disp[i].dpy; 152 if (cnx->egl.eglInitialize(idpy, &cnx->major, &cnx->minor)) { 153 //LOGD("initialized %d dpy=%p, ver=%d.%d, cnx=%p", 154 // i, idpy, cnx->major, cnx->minor, cnx); 155 156 // display is now initialized 157 disp[i].state = egl_display_t::INITIALIZED; 158 159 // get the query-strings for this display for each implementation 160 disp[i].queryString.vendor = cnx->egl.eglQueryString(idpy, 161 EGL_VENDOR); 162 disp[i].queryString.version = cnx->egl.eglQueryString(idpy, 163 EGL_VERSION); 164 disp[i].queryString.extensions = cnx->egl.eglQueryString(idpy, 165 EGL_EXTENSIONS); 166 disp[i].queryString.clientApi = cnx->egl.eglQueryString(idpy, 167 EGL_CLIENT_APIS); 168 169 } else { 170 LOGW("%d: eglInitialize(%p) failed (%s)", i, idpy, 171 egl_tls_t::egl_strerror(cnx->egl.eglGetError())); 172 } 173 } 174 175 egl_cache_t::get()->initialize(this); 176 177 EGLBoolean res = EGL_FALSE; 178 for (int i = 0; i < IMPL_NUM_IMPLEMENTATIONS; i++) { 179 egl_connection_t* const cnx = &gEGLImpl[i]; 180 if (cnx->dso && cnx->major >= 0 && cnx->minor >= 0) { 181 EGLint n; 182 if (cnx->egl.eglGetConfigs(disp[i].dpy, 0, 0, &n)) { 183 disp[i].config = (EGLConfig*) malloc(sizeof(EGLConfig) * n); 184 if (disp[i].config) { 185 if (cnx->egl.eglGetConfigs(disp[i].dpy, disp[i].config, n, 186 &disp[i].numConfigs)) { 187 numTotalConfigs += n; 188 res = EGL_TRUE; 189 } 190 } 191 } 192 } 193 } 194 195 if (res == EGL_TRUE) { 196 configs = new egl_config_t[numTotalConfigs]; 197 for (int i = 0, k = 0; i < IMPL_NUM_IMPLEMENTATIONS; i++) { 198 egl_connection_t* const cnx = &gEGLImpl[i]; 199 if (cnx->dso && cnx->major >= 0 && cnx->minor >= 0) { 200 for (int j = 0; j < disp[i].numConfigs; j++) { 201 configs[k].impl = i; 202 configs[k].config = disp[i].config[j]; 203 configs[k].configId = k + 1; // CONFIG_ID start at 1 204 // store the implementation's CONFIG_ID 205 cnx->egl.eglGetConfigAttrib(disp[i].dpy, disp[i].config[j], 206 EGL_CONFIG_ID, &configs[k].implConfigId); 207 k++; 208 } 209 } 210 } 211 212 // sort our configurations so we can do binary-searches 213 qsort(configs, numTotalConfigs, sizeof(egl_config_t), cmp_configs); 214 215 refs++; 216 if (major != NULL) 217 *major = VERSION_MAJOR; 218 if (minor != NULL) 219 *minor = VERSION_MINOR; 220 return EGL_TRUE; 221 } 222 return setError(EGL_NOT_INITIALIZED, EGL_FALSE); 223} 224 225EGLBoolean egl_display_t::terminate() { 226 227 Mutex::Autolock _l(lock); 228 229 if (refs == 0) { 230 return setError(EGL_NOT_INITIALIZED, EGL_FALSE); 231 } 232 233 // this is specific to Android, display termination is ref-counted. 234 if (refs > 1) { 235 refs--; 236 return EGL_TRUE; 237 } 238 239 EGLBoolean res = EGL_FALSE; 240 for (int i = 0; i < IMPL_NUM_IMPLEMENTATIONS; i++) { 241 egl_connection_t* const cnx = &gEGLImpl[i]; 242 if (cnx->dso && disp[i].state == egl_display_t::INITIALIZED) { 243 if (cnx->egl.eglTerminate(disp[i].dpy) == EGL_FALSE) { 244 LOGW("%d: eglTerminate(%p) failed (%s)", i, disp[i].dpy, 245 egl_tls_t::egl_strerror(cnx->egl.eglGetError())); 246 } 247 // REVISIT: it's unclear what to do if eglTerminate() fails 248 free(disp[i].config); 249 250 disp[i].numConfigs = 0; 251 disp[i].config = 0; 252 disp[i].state = egl_display_t::TERMINATED; 253 254 res = EGL_TRUE; 255 } 256 } 257 258 // Mark all objects remaining in the list as terminated, unless 259 // there are no reference to them, it which case, we're free to 260 // delete them. 261 size_t count = objects.size(); 262 LOGW_IF(count, "eglTerminate() called w/ %d objects remaining", count); 263 for (size_t i=0 ; i<count ; i++) { 264 egl_object_t* o = objects.itemAt(i); 265 o->destroy(); 266 } 267 268 // this marks all object handles are "terminated" 269 objects.clear(); 270 271 refs--; 272 numTotalConfigs = 0; 273 delete[] configs; 274 return res; 275} 276 277 278// ---------------------------------------------------------------------------- 279}; // namespace android 280// ---------------------------------------------------------------------------- 281