summaryrefslogtreecommitdiffstats
path: root/opengl/libs/EGL
diff options
context:
space:
mode:
Diffstat (limited to 'opengl/libs/EGL')
-rw-r--r--opengl/libs/EGL/Loader.cpp187
-rw-r--r--opengl/libs/EGL/Loader.h3
-rw-r--r--opengl/libs/EGL/eglApi.cpp10
-rw-r--r--opengl/libs/EGL/egl_tls.cpp30
-rw-r--r--opengl/libs/EGL/egl_tls.h3
5 files changed, 151 insertions, 82 deletions
diff --git a/opengl/libs/EGL/Loader.cpp b/opengl/libs/EGL/Loader.cpp
index 00bfa5a..c02a85f 100644
--- a/opengl/libs/EGL/Loader.cpp
+++ b/opengl/libs/EGL/Loader.cpp
@@ -21,6 +21,7 @@
#include <errno.h>
#include <dlfcn.h>
#include <limits.h>
+#include <dirent.h>
#include <cutils/log.h>
#include <cutils/properties.h>
@@ -38,9 +39,25 @@ namespace android {
/*
- * EGL drivers are called
+ * EGL userspace drivers must be provided either:
+ * - as a single library:
+ * /vendor/lib/egl/libGLES.so
+ *
+ * - as separate libraries:
+ * /vendor/lib/egl/libEGL.so
+ * /vendor/lib/egl/libGLESv1_CM.so
+ * /vendor/lib/egl/libGLESv2.so
+ *
+ * The software renderer for the emulator must be provided as a single
+ * library at:
+ *
+ * /system/lib/egl/libGLES_android.so
+ *
+ *
+ * For backward compatibility and to facilitate the transition to
+ * this new naming scheme, the loader will additionally look for:
*
- * /system/lib/egl/lib{[EGL|GLESv1_CM|GLESv2] | GLES}_$TAG.so
+ * /{vendor|system}/lib/egl/lib{GLES | [EGL|GLESv1_CM|GLESv2]}_*.so
*
*/
@@ -137,41 +154,10 @@ status_t Loader::driver_t::set(void* hnd, int32_t api)
// ----------------------------------------------------------------------------
Loader::Loader()
-{
- char line[256];
- char tag[256];
-
- /* Special case for GLES emulation */
- if (checkGlesEmulationStatus() == 0) {
- ALOGD("Emulator without GPU support detected. "
- "Fallback to software renderer.");
- mDriverTag.setTo("android");
- return;
- }
-
- /* Otherwise, use egl.cfg */
- FILE* cfg = fopen("/system/lib/egl/egl.cfg", "r");
- if (cfg == NULL) {
- // default config
- ALOGD("egl.cfg not found, using default config");
- mDriverTag.setTo("android");
- } else {
- while (fgets(line, 256, cfg)) {
- int dpy, impl;
- if (sscanf(line, "%u %u %s", &dpy, &impl, tag) == 3) {
- //ALOGD(">>> %u %u %s", dpy, impl, tag);
- // We only load the h/w accelerated implementation
- if (tag != String8("android")) {
- mDriverTag = tag;
- }
- }
- }
- fclose(cfg);
- }
+ : getProcAddress(NULL) {
}
-Loader::~Loader()
-{
+Loader::~Loader() {
GLTrace_stop();
}
@@ -180,26 +166,20 @@ void* Loader::open(egl_connection_t* cnx)
void* dso;
driver_t* hnd = 0;
- char const* tag = mDriverTag.string();
- if (tag) {
- dso = load_driver("GLES", tag, cnx, EGL | GLESv1_CM | GLESv2);
+ dso = load_driver("GLES", cnx, EGL | GLESv1_CM | GLESv2);
+ if (dso) {
+ hnd = new driver_t(dso);
+ } else {
+ // Always load EGL first
+ dso = load_driver("EGL", cnx, EGL);
if (dso) {
hnd = new driver_t(dso);
- } else {
- // Always load EGL first
- dso = load_driver("EGL", tag, cnx, EGL);
- if (dso) {
- hnd = new driver_t(dso);
- // TODO: make this more automated
- hnd->set( load_driver("GLESv1_CM", tag, cnx, GLESv1_CM), GLESv1_CM );
- hnd->set( load_driver("GLESv2", tag, cnx, GLESv2), GLESv2 );
- }
+ hnd->set( load_driver("GLESv1_CM", cnx, GLESv1_CM), GLESv1_CM );
+ hnd->set( load_driver("GLESv2", cnx, GLESv2), GLESv2 );
}
}
- LOG_FATAL_IF(!index && !hnd,
- "couldn't find the default OpenGL ES implementation "
- "for default display");
+ LOG_ALWAYS_FATAL_IF(!hnd, "couldn't find an OpenGL ES implementation");
return (void*)hnd;
}
@@ -267,21 +247,106 @@ void Loader::init_api(void* dso,
}
}
-void *Loader::load_driver(const char* kind, const char *tag,
+void *Loader::load_driver(const char* kind,
egl_connection_t* cnx, uint32_t mask)
{
- char driver_absolute_path[PATH_MAX];
- const char* const search1 = "/vendor/lib/egl/lib%s_%s.so";
- const char* const search2 = "/system/lib/egl/lib%s_%s.so";
-
- snprintf(driver_absolute_path, PATH_MAX, search1, kind, tag);
- if (access(driver_absolute_path, R_OK)) {
- snprintf(driver_absolute_path, PATH_MAX, search2, kind, tag);
- if (access(driver_absolute_path, R_OK)) {
- // this happens often, we don't want to log an error
- return 0;
+ class MatchFile {
+ public:
+ static String8 find(const char* kind) {
+ String8 result;
+ String8 pattern;
+ pattern.appendFormat("lib%s", kind);
+ const char* const searchPaths[] = {
+ "/vendor/lib/egl",
+ "/system/lib/egl"
+ };
+
+ // first, we search for the exact name of the GLES userspace
+ // driver in both locations.
+ // i.e.:
+ // libGLES.so, or:
+ // libEGL.so, libGLESv1_CM.so, libGLESv2.so
+
+ for (size_t i=0 ; i<NELEM(searchPaths) ; i++) {
+ if (find(result, pattern, searchPaths[i], true)) {
+ return result;
+ }
+ }
+
+ // for compatibility with the old "egl.cfg" naming convention
+ // we look for files that match:
+ // libGLES_*.so, or:
+ // libEGL_*.so, libGLESv1_CM_*.so, libGLESv2_*.so
+
+ pattern.append("_");
+ for (size_t i=0 ; i<NELEM(searchPaths) ; i++) {
+ if (find(result, pattern, searchPaths[i], false)) {
+ return result;
+ }
+ }
+
+ // we didn't find the driver. gah.
+ result.clear();
+ return result;
}
+
+ private:
+ static bool find(String8& result,
+ const String8& pattern, const char* const search, bool exact) {
+
+ // in the emulator case, we just return the hardcoded name
+ // of the software renderer.
+ if (checkGlesEmulationStatus() == 0) {
+ ALOGD("Emulator without GPU support detected. "
+ "Fallback to software renderer.");
+ result.setTo("/system/lib/egl/libGLES_android.so");
+ return true;
+ }
+
+ if (exact) {
+ String8 absolutePath;
+ absolutePath.appendFormat("%s/%s.so", search, pattern.string());
+ if (!access(absolutePath.string(), R_OK)) {
+ result = absolutePath;
+ return true;
+ }
+ return false;
+ }
+
+ DIR* d = opendir(search);
+ if (d != NULL) {
+ struct dirent cur;
+ struct dirent* e;
+ while (readdir_r(d, &cur, &e) == 0 && e) {
+ if (e->d_type == DT_DIR) {
+ continue;
+ }
+ if (!strcmp(e->d_name, "libGLES_android.so")) {
+ // always skip the software renderer
+ continue;
+ }
+ if (strstr(e->d_name, pattern.string()) == e->d_name) {
+ if (!strcmp(e->d_name + strlen(e->d_name) - 3, ".so")) {
+ result.clear();
+ result.appendFormat("%s/%s", search, e->d_name);
+ closedir(d);
+ return true;
+ }
+ }
+ }
+ closedir(d);
+ }
+ return false;
+ }
+ };
+
+
+ String8 absolutePath = MatchFile::find(kind);
+ if (absolutePath.isEmpty()) {
+ // this happens often, we don't want to log an error
+ return 0;
}
+ const char* const driver_absolute_path = absolutePath.string();
void* dso = dlopen(driver_absolute_path, RTLD_NOW | RTLD_LOCAL);
if (dso == 0) {
diff --git a/opengl/libs/EGL/Loader.h b/opengl/libs/EGL/Loader.h
index 30773cb..8cefe32 100644
--- a/opengl/libs/EGL/Loader.h
+++ b/opengl/libs/EGL/Loader.h
@@ -52,7 +52,6 @@ class Loader : public Singleton<Loader>
void* dso[3];
};
- String8 mDriverTag;
getProcAddressType getProcAddress;
public:
@@ -63,7 +62,7 @@ public:
private:
Loader();
- void *load_driver(const char* kind, const char *tag, egl_connection_t* cnx, uint32_t mask);
+ void *load_driver(const char* kind, egl_connection_t* cnx, uint32_t mask);
static __attribute__((noinline))
void init_api(void* dso,
diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp
index 93eedff..2bc9851 100644
--- a/opengl/libs/EGL/eglApi.cpp
+++ b/opengl/libs/EGL/eglApi.cpp
@@ -1182,6 +1182,11 @@ EGLBoolean eglReleaseThread(void)
{
clearError();
+#if EGL_TRACE
+ if (getEGLDebugLevel() > 0)
+ GLTrace_eglReleaseThread();
+#endif
+
// If there is context bound to the thread, release it
egl_display_t::loseCurrent(get_context(getContext()));
@@ -1189,12 +1194,7 @@ EGLBoolean eglReleaseThread(void)
if (cnx->dso && cnx->egl.eglReleaseThread) {
cnx->egl.eglReleaseThread();
}
-
egl_tls_t::clearTLS();
-#if EGL_TRACE
- if (getEGLDebugLevel() > 0)
- GLTrace_eglReleaseThread();
-#endif
return EGL_TRUE;
}
diff --git a/opengl/libs/EGL/egl_tls.cpp b/opengl/libs/EGL/egl_tls.cpp
index 52312a2..f3739aa 100644
--- a/opengl/libs/EGL/egl_tls.cpp
+++ b/opengl/libs/EGL/egl_tls.cpp
@@ -29,8 +29,8 @@
namespace android {
-pthread_key_t egl_tls_t::sKey = -1;
-pthread_mutex_t egl_tls_t::sLockKey = PTHREAD_MUTEX_INITIALIZER;
+pthread_key_t egl_tls_t::sKey = TLS_KEY_NOT_INITIALIZED;
+pthread_once_t egl_tls_t::sOnceKey = PTHREAD_ONCE_INIT;
egl_tls_t::egl_tls_t()
: error(EGL_SUCCESS), ctx(0), logCallWithNoContext(EGL_TRUE) {
@@ -59,12 +59,12 @@ const char *egl_tls_t::egl_strerror(EGLint err) {
void egl_tls_t::validateTLSKey()
{
- if (sKey == -1) {
- pthread_mutex_lock(&sLockKey);
- if (sKey == -1)
- pthread_key_create(&sKey, NULL);
- pthread_mutex_unlock(&sLockKey);
- }
+ struct TlsKeyInitializer {
+ static void create() {
+ pthread_key_create(&sKey, (void (*)(void*))&eglReleaseThread);
+ }
+ };
+ pthread_once(&sOnceKey, TlsKeyInitializer::create);
}
void egl_tls_t::setErrorEtcImpl(
@@ -104,11 +104,11 @@ egl_tls_t* egl_tls_t::getTLS() {
}
void egl_tls_t::clearTLS() {
- if (sKey != -1) {
+ if (sKey != TLS_KEY_NOT_INITIALIZED) {
egl_tls_t* tls = (egl_tls_t*)pthread_getspecific(sKey);
if (tls) {
- delete tls;
pthread_setspecific(sKey, 0);
+ delete tls;
}
}
}
@@ -120,10 +120,13 @@ void egl_tls_t::clearError() {
}
EGLint egl_tls_t::getError() {
- if (sKey == -1)
+ if (sKey == TLS_KEY_NOT_INITIALIZED) {
return EGL_SUCCESS;
+ }
egl_tls_t* tls = (egl_tls_t*)pthread_getspecific(sKey);
- if (!tls) return EGL_SUCCESS;
+ if (!tls) {
+ return EGL_SUCCESS;
+ }
EGLint error = tls->error;
tls->error = EGL_SUCCESS;
return error;
@@ -135,8 +138,9 @@ void egl_tls_t::setContext(EGLContext ctx) {
}
EGLContext egl_tls_t::getContext() {
- if (sKey == -1)
+ if (sKey == TLS_KEY_NOT_INITIALIZED) {
return EGL_NO_CONTEXT;
+ }
egl_tls_t* tls = (egl_tls_t *)pthread_getspecific(sKey);
if (!tls) return EGL_NO_CONTEXT;
return tls->ctx;
diff --git a/opengl/libs/EGL/egl_tls.h b/opengl/libs/EGL/egl_tls.h
index 56c5dba..5af4f5b 100644
--- a/opengl/libs/EGL/egl_tls.h
+++ b/opengl/libs/EGL/egl_tls.h
@@ -30,8 +30,9 @@ namespace android {
class DbgContext;
class egl_tls_t {
+ enum { TLS_KEY_NOT_INITIALIZED = -1 };
static pthread_key_t sKey;
- static pthread_mutex_t sLockKey;
+ static pthread_once_t sOnceKey;
EGLint error;
EGLContext ctx;