change how the userspace GLES drivers are named

for single library:
  /vendor/lib/egl/GLES.so

for multiple libraries:
  /vendor/lib/egl/EGL.so
  /vendor/lib/egl/GLESv1_CM.so
  /vendor/lib/egl/GLESv2.so

EGL_BOARD_CONFIG as well as egl.cfg are not needed anymore.

To facilitate the transition, the loader will also look
for the older naming scheme.

Bug: 8631636
Change-Id: Id4b113468df29bae72b323f76598229914e1c7a1
This commit is contained in:
Mathias Agopian 2013-04-23 20:52:29 +02:00
parent 748b696c05
commit 993814255f
2 changed files with 126 additions and 62 deletions

View File

@ -21,6 +21,7 @@
#include <errno.h> #include <errno.h>
#include <dlfcn.h> #include <dlfcn.h>
#include <limits.h> #include <limits.h>
#include <dirent.h>
#include <cutils/log.h> #include <cutils/log.h>
#include <cutils/properties.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() Loader::Loader()
{ : getProcAddress(NULL) {
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 (String8("android") != tag) {
mDriverTag = tag;
}
}
}
fclose(cfg);
}
} }
Loader::~Loader() Loader::~Loader() {
{
GLTrace_stop(); GLTrace_stop();
} }
@ -180,26 +166,20 @@ void* Loader::open(egl_connection_t* cnx)
void* dso; void* dso;
driver_t* hnd = 0; driver_t* hnd = 0;
char const* tag = mDriverTag.string(); dso = load_driver("GLES", cnx, EGL | GLESv1_CM | GLESv2);
if (tag) { if (dso) {
dso = load_driver("GLES", tag, cnx, EGL | GLESv1_CM | GLESv2); hnd = new driver_t(dso);
} else {
// Always load EGL first
dso = load_driver("EGL", cnx, EGL);
if (dso) { if (dso) {
hnd = new driver_t(dso); hnd = new driver_t(dso);
} else { hnd->set( load_driver("GLESv1_CM", cnx, GLESv1_CM), GLESv1_CM );
// Always load EGL first hnd->set( load_driver("GLESv2", cnx, GLESv2), GLESv2 );
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 );
}
} }
} }
LOG_FATAL_IF(!index && !hnd, LOG_ALWAYS_FATAL_IF(!hnd, "couldn't find an OpenGL ES implementation");
"couldn't find the default OpenGL ES implementation "
"for default display");
return (void*)hnd; 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) egl_connection_t* cnx, uint32_t mask)
{ {
char driver_absolute_path[PATH_MAX]; class MatchFile {
const char* const search1 = "/vendor/lib/egl/lib%s_%s.so"; public:
const char* const search2 = "/system/lib/egl/lib%s_%s.so"; 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"
};
snprintf(driver_absolute_path, PATH_MAX, search1, kind, tag); // first, we search for the exact name of the GLES userspace
if (access(driver_absolute_path, R_OK)) { // driver in both locations.
snprintf(driver_absolute_path, PATH_MAX, search2, kind, tag); // i.e.:
if (access(driver_absolute_path, R_OK)) { // libGLES.so, or:
// this happens often, we don't want to log an error // libEGL.so, libGLESv1_CM.so, libGLESv2.so
return 0;
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); void* dso = dlopen(driver_absolute_path, RTLD_NOW | RTLD_LOCAL);
if (dso == 0) { if (dso == 0) {

View File

@ -52,7 +52,6 @@ class Loader : public Singleton<Loader>
void* dso[3]; void* dso[3];
}; };
String8 mDriverTag;
getProcAddressType getProcAddress; getProcAddressType getProcAddress;
public: public:
@ -63,7 +62,7 @@ public:
private: private:
Loader(); 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)) static __attribute__((noinline))
void init_api(void* dso, void init_api(void* dso,