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 <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 (String8("android") != tag) {
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";
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"
};
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;
// 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) {

View File

@ -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,