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 // ---------------------------------------------------------------------------- 27 namespace android { 28 // ---------------------------------------------------------------------------- 29 30 static char const * const sVendorString = "Android"; 31 static char const * const sVersionString = "1.4 Android META-EGL"; 32 static 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 // 44 static 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 60 extern void initEglTraceLevel(); 61 extern void setGLHooksThreadSpecific(gl_hooks_t const *value); 62 63 static 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 71 egl_display_t egl_display_t::sDisplay[NUM_DISPLAYS]; 72 73 egl_display_t::egl_display_t() : 74 magic('_dpy'), numTotalConfigs(0), configs(0), refs(0) { 75 } 76 77 egl_display_t::~egl_display_t() { 78 magic = 0; 79 egl_cache_t::get()->terminate(); 80 } 81 82 egl_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 87 void egl_display_t::addObject(egl_object_t* object) { 88 Mutex::Autolock _l(lock); 89 objects.add(object); 90 } 91 92 void egl_display_t::removeObject(egl_object_t* object) { 93 Mutex::Autolock _l(lock); 94 objects.remove(object); 95 } 96 97 bool 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 108 EGLDisplay 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 115 EGLDisplay 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 137 EGLBoolean 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 //LOGD("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 LOGW("%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 293 EGLBoolean 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 LOGW("%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 LOGW_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