opengl: defer GLESV1 library loading until context creation time
Test: boot and run GLESV1 test app
Bug: b/147019446
Change-Id: Ia3925a96c745d9bbb966b0e3bda9f0a1332e2a14
diff --git a/opengl/libs/EGL/Loader.cpp b/opengl/libs/EGL/Loader.cpp
index e143260..5f04f64 100644
--- a/opengl/libs/EGL/Loader.cpp
+++ b/opengl/libs/EGL/Loader.cpp
@@ -25,7 +25,6 @@
#include <dlfcn.h>
#include <android/dlext.h>
-#include <cutils/properties.h>
#include <log/log.h>
#include <utils/Timers.h>
@@ -206,6 +205,7 @@
}
cnx->systemDriverUnloaded = true;
+ cnx->loadedDriverType = egl_connection_t::GLES_NO_DRIVER;
}
void* Loader::open(egl_connection_t* cnx)
@@ -228,6 +228,7 @@
} else {
cnx->shouldUseAngle = false;
}
+ cnx->loadedDriverType = egl_connection_t::GLES_NO_DRIVER;
// Firstly, try to load ANGLE driver.
driver_t* hnd = attempt_to_load_angle(cnx);
@@ -237,22 +238,26 @@
}
bool failToLoadFromDriverSuffixProperty = false;
+ cnx->systemDriverUseExactName = true;
if (!hnd) {
// Finally, try to load system driver, start by searching for the library name appended by
// the system properties of the GLES userspace driver in both locations.
// i.e.:
// libGLES_${prop}.so, or:
// libEGL_${prop}.so, libGLESv1_CM_${prop}.so, libGLESv2_${prop}.so
- char prop[PROPERTY_VALUE_MAX + 1];
for (auto key : HAL_SUBNAME_KEY_PROPERTIES) {
- if (property_get(key, prop, nullptr) <= 0) {
+ if (property_get(key, cnx->systemDriverProperty, nullptr) <= 0) {
continue;
}
- hnd = attempt_to_load_system_driver(cnx, prop, true);
+ hnd = attempt_to_load_system_driver(cnx, cnx->systemDriverProperty,
+ cnx->systemDriverUseExactName);
if (hnd) {
+ cnx->systemDriverUseProperty = true;
break;
- } else if (strcmp(key, DRIVER_SUFFIX_PROPERTY) == 0) {
- failToLoadFromDriverSuffixProperty = true;
+ } else {
+ if (strcmp(key, DRIVER_SUFFIX_PROPERTY) == 0) {
+ failToLoadFromDriverSuffixProperty = true;
+ }
}
}
}
@@ -263,11 +268,12 @@
// i.e.:
// libGLES.so, or:
// libEGL.so, libGLESv1_CM.so, libGLESv2.so
- hnd = attempt_to_load_system_driver(cnx, nullptr, true);
+ hnd = attempt_to_load_system_driver(cnx, nullptr, cnx->systemDriverUseExactName);
}
if (!hnd && !failToLoadFromDriverSuffixProperty) {
- hnd = attempt_to_load_system_driver(cnx, nullptr, false);
+ cnx->systemDriverUseExactName = false;
+ hnd = attempt_to_load_system_driver(cnx, nullptr, cnx->systemDriverUseExactName);
}
if (!hnd) {
@@ -282,14 +288,11 @@
if (!cnx->libEgl) {
cnx->libEgl = load_wrapper(EGL_WRAPPER_DIR "/libEGL.so");
}
- if (!cnx->libGles1) {
- cnx->libGles1 = load_wrapper(EGL_WRAPPER_DIR "/libGLESv1_CM.so");
- }
if (!cnx->libGles2) {
cnx->libGles2 = load_wrapper(EGL_WRAPPER_DIR "/libGLESv2.so");
}
- if (!cnx->libEgl || !cnx->libGles2 || !cnx->libGles1) {
+ if (!cnx->libEgl || !cnx->libGles2) {
android::GraphicsEnv::getInstance().setDriverLoaded(android::GpuStatsInfo::Api::API_GL,
false, systemTime() - openTime);
}
@@ -297,8 +300,7 @@
LOG_ALWAYS_FATAL_IF(!cnx->libEgl,
"couldn't load system EGL wrapper libraries");
- LOG_ALWAYS_FATAL_IF(!cnx->libGles2 || !cnx->libGles1,
- "couldn't load system OpenGL ES wrapper libraries");
+ LOG_ALWAYS_FATAL_IF(!cnx->libGles2, "couldn't load system OpenGL ESv2+ wrapper libraries");
android::GraphicsEnv::getInstance().setDriverLoaded(android::GpuStatsInfo::Api::API_GL, true,
systemTime() - openTime);
@@ -314,7 +316,7 @@
cnx->shouldUseAngle = false;
cnx->angleDecided = false;
- cnx->useAngle = false;
+ cnx->loadedDriverType = egl_connection_t::GLES_NO_DRIVER;
if (cnx->vendorEGL) {
dlclose(cnx->vendorEGL);
@@ -519,7 +521,6 @@
if (so) {
ALOGV("Loaded ANGLE %s library for '%s' (instead of native)", kind,
android::GraphicsEnv::getInstance().getAngleAppName().c_str());
- cnx->useAngle = true;
char prop[PROPERTY_VALUE_MAX];
@@ -562,7 +563,6 @@
} else {
ALOGV("Loaded native %s library for '%s' (instead of ANGLE)", kind,
android::GraphicsEnv::getInstance().getAngleAppName().c_str());
- cnx->useAngle = false;
}
cnx->angleDecided = true;
@@ -592,6 +592,7 @@
Loader::driver_t* Loader::attempt_to_load_angle(egl_connection_t* cnx) {
ATRACE_CALL();
+ assert(cnx->loadedDriverType == egl_connection_t::GLES_NO_DRIVER);
android_namespace_t* ns = android::GraphicsEnv::getInstance().getAngleNamespace();
if (!ns) {
return nullptr;
@@ -606,19 +607,17 @@
initialize_api(dso, cnx, EGL);
hnd = new driver_t(dso);
- dso = load_angle("GLESv1_CM", ns, cnx);
- initialize_api(dso, cnx, GLESv1_CM);
- hnd->set(dso, GLESv1_CM);
-
dso = load_angle("GLESv2", ns, cnx);
initialize_api(dso, cnx, GLESv2);
hnd->set(dso, GLESv2);
+ cnx->loadedDriverType = egl_connection_t::GLES_ANGLE_STANDALONE_DRIVER;
}
return hnd;
}
Loader::driver_t* Loader::attempt_to_load_updated_driver(egl_connection_t* cnx) {
ATRACE_CALL();
+ assert(cnx->loadedDriverType == egl_connection_t::GLES_NO_DRIVER);
#ifndef __ANDROID_VNDK__
android_namespace_t* ns = android::GraphicsEnv::getInstance().getDriverNamespace();
if (!ns) {
@@ -630,8 +629,9 @@
driver_t* hnd = nullptr;
void* dso = load_updated_driver("GLES", ns);
if (dso) {
- initialize_api(dso, cnx, EGL | GLESv1_CM | GLESv2);
+ initialize_api(dso, cnx, EGL | GLESv2);
hnd = new driver_t(dso);
+ if (hnd) cnx->loadedDriverType = egl_connection_t::GLES_UPDATED_COMBO_DRIVER;
return hnd;
}
@@ -640,13 +640,10 @@
initialize_api(dso, cnx, EGL);
hnd = new driver_t(dso);
- dso = load_updated_driver("GLESv1_CM", ns);
- initialize_api(dso, cnx, GLESv1_CM);
- hnd->set(dso, GLESv1_CM);
-
dso = load_updated_driver("GLESv2", ns);
initialize_api(dso, cnx, GLESv2);
hnd->set(dso, GLESv2);
+ cnx->loadedDriverType = egl_connection_t::GLES_UPDATED_STANDALONE_DRIVER;
}
return hnd;
#else
@@ -657,30 +654,94 @@
Loader::driver_t* Loader::attempt_to_load_system_driver(egl_connection_t* cnx, const char* suffix,
const bool exact) {
ATRACE_CALL();
+ assert(cnx->loadedDriverType == egl_connection_t::GLES_NO_DRIVER);
android::GraphicsEnv::getInstance().setDriverToLoad(android::GpuStatsInfo::Driver::GL);
driver_t* hnd = nullptr;
void* dso = load_system_driver("GLES", suffix, exact);
if (dso) {
- initialize_api(dso, cnx, EGL | GLESv1_CM | GLESv2);
+ initialize_api(dso, cnx, EGL | GLESv2);
hnd = new driver_t(dso);
+ if (hnd) cnx->loadedDriverType = egl_connection_t::GLES_SYSTEM_COMBO_DRIVER;
return hnd;
}
+
dso = load_system_driver("EGL", suffix, exact);
if (dso) {
initialize_api(dso, cnx, EGL);
hnd = new driver_t(dso);
- dso = load_system_driver("GLESv1_CM", suffix, exact);
- initialize_api(dso, cnx, GLESv1_CM);
- hnd->set(dso, GLESv1_CM);
-
dso = load_system_driver("GLESv2", suffix, exact);
initialize_api(dso, cnx, GLESv2);
hnd->set(dso, GLESv2);
+ cnx->loadedDriverType = egl_connection_t::GLES_SYSTEM_STANDALONE_DRIVER;
}
return hnd;
}
+bool Loader::load_glesv1_driver(egl_connection_t* cnx) {
+ ATRACE_CALL();
+ void* dso = nullptr;
+
+ driver_t* hnd = (driver_t*)cnx->dso;
+ // EGL driver must have been loaded. if not, something went wrong.
+ if (!hnd || cnx->loadedDriverType == egl_connection_t::GLES_NO_DRIVER) {
+ return false;
+ }
+
+ if (cnx->libGles1) return EGL_TRUE;
+
+ // If there is a GLES driver, use that first
+ switch (cnx->loadedDriverType) {
+ case egl_connection_t::GLES_SYSTEM_COMBO_DRIVER:
+ case egl_connection_t::GLES_UPDATED_COMBO_DRIVER: {
+ dso = hnd->dso[0];
+ initialize_api(dso, cnx, GLESv1_CM);
+ break;
+ }
+ case egl_connection_t::GLES_ANGLE_STANDALONE_DRIVER: {
+ android_namespace_t* ns = android::GraphicsEnv::getInstance().getAngleNamespace();
+ dso = load_angle("GLESv1_CM", ns, cnx);
+ if (dso) {
+ initialize_api(dso, cnx, GLESv1_CM);
+ hnd->set(dso, GLESv1_CM);
+ }
+ break;
+ }
+ case egl_connection_t::GLES_UPDATED_STANDALONE_DRIVER: {
+ android_namespace_t* ns = android::GraphicsEnv::getInstance().getDriverNamespace();
+ void* dso = load_updated_driver("GLESv1_CM", ns);
+ if (dso) {
+ initialize_api(dso, cnx, GLESv1_CM);
+ hnd->set(dso, GLESv1_CM);
+ }
+ break;
+ }
+ case egl_connection_t::GLES_SYSTEM_STANDALONE_DRIVER: {
+ dso = load_system_driver("GLESv1_CM",
+ cnx->systemDriverUseProperty ? cnx->systemDriverProperty
+ : nullptr,
+ cnx->systemDriverUseExactName);
+ if (dso) {
+ initialize_api(dso, cnx, GLESv1_CM);
+ hnd->set(dso, GLESv1_CM);
+ }
+ break;
+ }
+ default: {
+ ALOGE("Bad loadedDriverType (%d)", cnx->loadedDriverType);
+ break;
+ }
+ }
+
+ if (!cnx->libGles1) {
+ cnx->libGles1 = load_wrapper(EGL_WRAPPER_DIR "/libGLESv1_CM.so");
+ }
+
+ LOG_ALWAYS_FATAL_IF(!cnx->libGles1, "couldn't load system OpenGL ES V1 wrapper libraries");
+
+ return dso ? true : false;
+}
+
void Loader::initialize_api(void* dso, egl_connection_t* cnx, uint32_t mask) {
if (mask & EGL) {
getProcAddress = (getProcAddressType)dlsym(dso, "eglGetProcAddress");
diff --git a/opengl/libs/EGL/Loader.h b/opengl/libs/EGL/Loader.h
index 6f31ab4..4199753 100644
--- a/opengl/libs/EGL/Loader.h
+++ b/opengl/libs/EGL/Loader.h
@@ -53,6 +53,8 @@
void* open(egl_connection_t* cnx);
void close(egl_connection_t* cnx);
+ bool load_glesv1_driver(egl_connection_t* cnx);
+
private:
Loader();
driver_t* attempt_to_load_angle(egl_connection_t* cnx);
diff --git a/opengl/libs/EGL/egl.cpp b/opengl/libs/EGL/egl.cpp
index 25b1009..768d3b5 100644
--- a/opengl/libs/EGL/egl.cpp
+++ b/opengl/libs/EGL/egl.cpp
@@ -202,6 +202,15 @@
return cnx->dso ? EGL_TRUE : EGL_FALSE;
}
+static EGLBoolean egl_init_glesv1_drivers_locked() {
+ // get our driver loader
+ Loader& loader(Loader::getInstance());
+
+ // dynamically load our GLESV1 implementation
+ egl_connection_t* cnx = &gEGLImpl;
+ return loader.load_glesv1_driver(cnx);
+}
+
static pthread_mutex_t sInitDriverMutex = PTHREAD_MUTEX_INITIALIZER;
EGLBoolean egl_init_drivers() {
@@ -212,6 +221,14 @@
return res;
}
+EGLBoolean egl_init_glesv1_drivers() {
+ EGLBoolean res;
+ pthread_mutex_lock(&sInitDriverMutex);
+ res = egl_init_glesv1_drivers_locked();
+ pthread_mutex_unlock(&sInitDriverMutex);
+ return res;
+}
+
static pthread_mutex_t sLogPrintMutex = PTHREAD_MUTEX_INITIALIZER;
static std::chrono::steady_clock::time_point sLogPrintTime;
static constexpr std::chrono::seconds DURATION(1);
diff --git a/opengl/libs/EGL/egl_display.cpp b/opengl/libs/EGL/egl_display.cpp
index 67d69b4..3b19b32 100644
--- a/opengl/libs/EGL/egl_display.cpp
+++ b/opengl/libs/EGL/egl_display.cpp
@@ -220,7 +220,7 @@
if (cnx->dso) {
EGLDisplay dpy = EGL_NO_DISPLAY;
- if (cnx->useAngle) {
+ if (cnx->loadedDriverType == egl_connection_t::GLES_ANGLE_STANDALONE_DRIVER) {
EGLint error;
dpy = getPlatformDisplayAngle(display, cnx, attrib_list, &error);
if (error != EGL_NONE) {
@@ -464,7 +464,7 @@
egl_connection_t* const cnx = &gEGLImpl;
if (cnx->dso && disp.state == egl_display_t::INITIALIZED) {
// If we're using ANGLE reset any custom DisplayPlatform
- if (cnx->useAngle) {
+ if (cnx->loadedDriverType == egl_connection_t::GLES_ANGLE_STANDALONE_DRIVER) {
angle::resetAnglePlatform(disp.dpy);
}
if (cnx->egl.eglTerminate(disp.dpy) == EGL_FALSE) {
diff --git a/opengl/libs/EGL/egl_platform_entries.cpp b/opengl/libs/EGL/egl_platform_entries.cpp
index 5162ba4..e2bc5c6 100644
--- a/opengl/libs/EGL/egl_platform_entries.cpp
+++ b/opengl/libs/EGL/egl_platform_entries.cpp
@@ -277,6 +277,7 @@
extern void setGLHooksThreadSpecific(gl_hooks_t const *value);
extern EGLBoolean egl_init_drivers();
+extern EGLBoolean egl_init_glesv1_drivers();
extern const __eglMustCastToProperFunctionPointerType gExtensionForwarders[MAX_NUMBER_OF_GL_EXTENSIONS];
extern gl_hooks_t gHooksTrace;
@@ -956,44 +957,42 @@
egl_context_t* const c = get_context(share_list);
share_list = c->context;
}
- // b/111083885 - If we are presenting EGL 1.4 interface to apps
- // error out on robust access attributes that are invalid
- // in EGL 1.4 as the driver may be fine with them but dEQP expects
- // tests to fail according to spec.
- if (attrib_list && (cnx->driverVersion < EGL_MAKE_VERSION(1, 5, 0))) {
- const EGLint* attrib_ptr = attrib_list;
- while (*attrib_ptr != EGL_NONE) {
- GLint attr = *attrib_ptr++;
- GLint value = *attrib_ptr++;
- if (attr == EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR) {
- // We are GL ES context with EGL 1.4, this is an invalid
- // attribute
+
+ // figure out if it's a GLESv1 or GLESv2
+ int gles_version_idx = egl_connection_t::GLESv1_INDEX;
+ if (attrib_list) {
+ const EGLint* ptr = attrib_list; // so that we don't modify attrib_list
+ while (*ptr != EGL_NONE) {
+ GLint attr = *ptr++;
+ GLint value = *ptr++;
+ if (attr == EGL_CONTEXT_CLIENT_VERSION) {
+ if (value == 1) {
+ gles_version_idx = egl_connection_t::GLESv1_INDEX;
+ } else if (value == 2 || value == 3) {
+ gles_version_idx = egl_connection_t::GLESv2_INDEX;
+ }
+ } else if (attr == EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR &&
+ cnx->driverVersion < EGL_MAKE_VERSION(1, 5, 0)) {
+ // b/111083885 - If we are presenting EGL 1.4 interface to apps
+ // error out on robust access attributes that are invalid
+ // in EGL 1.4 as the driver may be fine with them but dEQP expects
+ // tests to fail according to spec.
return setError(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT);
}
- };
+ }
}
+
+ // GLESV1 driver is lazily loaded and initialized
+ if (gles_version_idx == egl_connection_t::GLESv1_INDEX) {
+ android::GraphicsEnv::getInstance().setTargetStats(
+ android::GpuStatsInfo::Stats::GLES_1_IN_USE);
+ if (!egl_init_glesv1_drivers()) return EGL_NO_CONTEXT;
+ }
+
EGLContext context = cnx->egl.eglCreateContext(
dp->disp.dpy, config, share_list, attrib_list);
if (context != EGL_NO_CONTEXT) {
- // figure out if it's a GLESv1 or GLESv2
- int version = 0;
- if (attrib_list) {
- while (*attrib_list != EGL_NONE) {
- GLint attr = *attrib_list++;
- GLint value = *attrib_list++;
- if (attr == EGL_CONTEXT_CLIENT_VERSION) {
- if (value == 1) {
- version = egl_connection_t::GLESv1_INDEX;
- android::GraphicsEnv::getInstance().setTargetStats(
- android::GpuStatsInfo::Stats::GLES_1_IN_USE);
- } else if (value == 2 || value == 3) {
- version = egl_connection_t::GLESv2_INDEX;
- }
- }
- };
- }
- egl_context_t* c = new egl_context_t(dpy, context, config, cnx,
- version);
+ egl_context_t* c = new egl_context_t(dpy, context, config, cnx, gles_version_idx);
return c;
}
}
diff --git a/opengl/libs/EGL/egldefs.h b/opengl/libs/EGL/egldefs.h
index 7bb9b59..4e9d7d0 100644
--- a/opengl/libs/EGL/egldefs.h
+++ b/opengl/libs/EGL/egldefs.h
@@ -17,11 +17,12 @@
#ifndef ANDROID_EGLDEFS_H
#define ANDROID_EGLDEFS_H
+#include <cutils/properties.h>
+#include <log/log.h>
+
#include "../hooks.h"
#include "egl_platform_entries.h"
-#include <log/log.h>
-
#define VERSION_MAJOR 1
#define VERSION_MINOR 4
#define EGL_MAKE_VERSION(major, minor, patch) (((major) << 22) | ((minor) << 12) | (patch))
@@ -44,6 +45,15 @@
GLESv2_INDEX = 1
};
+ enum {
+ GLES_NO_DRIVER = 0, // no driver is loaded
+ GLES_SYSTEM_COMBO_DRIVER = 1, // GLES combo driver in system folder is loaded
+ GLES_SYSTEM_STANDALONE_DRIVER = 2, // standalone system drivers are loaded
+ GLES_ANGLE_STANDALONE_DRIVER = 3, // ANGLE (always standalone) drivers are loaded.
+ GLES_UPDATED_COMBO_DRIVER = 4, // GLES combo driver in updated driver folder is loaded
+ GLES_UPDATED_STANDALONE_DRIVER = 5, // standalone drivers in updated driver folder are loaded
+ };
+
inline egl_connection_t() : dso(nullptr),
libEgl(nullptr),
libGles1(nullptr),
@@ -83,9 +93,12 @@
bool systemDriverUnloaded;
bool shouldUseAngle; // Should we attempt to load ANGLE
bool angleDecided; // Have we tried to load ANGLE
- bool useAngle; // Was ANGLE successfully loaded
EGLint angleBackend;
+ int loadedDriverType;
void* vendorEGL;
+ bool systemDriverUseExactName;
+ bool systemDriverUseProperty;
+ char systemDriverProperty[PROPERTY_VALUE_MAX + 1];
};
// clang-format on