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:
parent
748b696c05
commit
993814255f
|
@ -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) {
|
||||||
|
|
|
@ -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,
|
||||||
|
|
Loading…
Reference in New Issue