Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1966cf62 authored by Jesse Hall's avatar Jesse Hall
Browse files

EGL: Load updated EGL/GLES drivers

Because the driver namespace is stored in libgui, and libgui depends
on libEGL, this required a hack for libEGL to access the namespace.
See the comment added in GraphicsEnv.h for details; the summary is
that the libgui->libEGL dependency should go away, and then libEGL can
depend on libgui directly.

For system drivers, the loader would happily load anything named
lib{GLES,EGL,GLESv2,GLESv1_CM}_*.so in /vendor/lib[64]/egl, for
backward-compatibility with the old and no-longer-supported egl.cfg
system. However, it preferred unsuffixed names. That's not actually a
good idea, since the DT_SONAME would clash with the system libraries.
For updated drivers, we only look for suffixes from the
ro.hardware.egl and ro.board.platform system properties, similar to
the Vulkan and HAL library search. A future change (tied to a future
release) will do the same for system drivers.

Bug: 33531483
Test: Launch GLES apps w/ and w/o updated driver package
Change-Id: Ibfbb275629b0c6cf9c51314aea1361e81ff72d4b
parent b2401203
Loading
Loading
Loading
Loading
+13 −0
Original line number Diff line number Diff line
@@ -43,4 +43,17 @@ private:

} // namespace android

/* FIXME
 * Export an un-mangled function that just does
 *     return android::GraphicsEnv::getInstance().getDriverNamespace();
 * This allows libEGL to get the function pointer via dlsym, since it can't
 * directly link against libgui. In a future release, we'll fix this so that
 * libgui does not depend on graphics API libraries, and libEGL can link
 * against it. The current dependencies from libgui -> libEGL are:
 *  - the GLConsumer class, which should be moved to its own library
 *  - the EGLsyncKHR synchronization in BufferQueue, which is deprecated and
 *    will be removed soon.
 */
extern "C" android_namespace_t* android_getDriverNamespace();

#endif // ANDROID_GUI_GRAPHICS_ENV_H
+4 −0
Original line number Diff line number Diff line
@@ -75,3 +75,7 @@ android_namespace_t* GraphicsEnv::getDriverNamespace() {
}

} // namespace android

extern "C" android_namespace_t* android_getDriverNamespace() {
    return android::GraphicsEnv::getInstance().getDriverNamespace();
}
+67 −5
Original line number Diff line number Diff line
@@ -14,6 +14,9 @@
 ** limitations under the License.
 */

//#define LOG_NDEBUG 0

#include <array>
#include <ctype.h>
#include <dirent.h>
#include <dlfcn.h>
@@ -23,6 +26,7 @@
#include <stdlib.h>
#include <string.h>

#include <android/dlext.h>
#include <cutils/properties.h>
#include <log/log.h>

@@ -154,10 +158,26 @@ status_t Loader::driver_t::set(void* hnd, int32_t api)
// ----------------------------------------------------------------------------

Loader::Loader()
    : getProcAddress(NULL) {
    : getProcAddress(NULL),
      mLibGui(nullptr),
      mGetDriverNamespace(nullptr)
{
    // FIXME: See note in GraphicsEnv.h about android_getDriverNamespace().
    // libgui should already be loaded in any process that uses libEGL, but
    // if for some reason it isn't, then we're not going to get a driver
    // namespace anyway, so don't force it to be loaded.
    mLibGui = dlopen("libgui.so", RTLD_NOLOAD | RTLD_LOCAL | RTLD_LAZY);
    if (!mLibGui) {
        ALOGD("failed to load libgui: %s", dlerror());
        return;
    }
    mGetDriverNamespace = reinterpret_cast<decltype(mGetDriverNamespace)>(
            dlsym(mLibGui, "android_getDriverNamespace"));
}

Loader::~Loader() {
    if (mLibGui)
        dlclose(mLibGui);
}

static void* load_wrapper(const char* path) {
@@ -304,9 +324,7 @@ void Loader::init_api(void* dso,
    }
}

void *Loader::load_driver(const char* kind,
        egl_connection_t* cnx, uint32_t mask)
{
static void* load_system_driver(const char* kind) {
    class MatchFile {
    public:
        static String8 find(const char* kind) {
@@ -431,11 +449,55 @@ void *Loader::load_driver(const char* kind,

    ALOGD("loaded %s", driver_absolute_path);

    return dso;
}

static const std::array<const char*, 2> HAL_SUBNAME_KEY_PROPERTIES = {{
    "ro.hardware.egl",
    "ro.board.platform",
}};

static void* load_updated_driver(const char* kind, android_namespace_t* ns) {
    const android_dlextinfo dlextinfo = {
        .flags = ANDROID_DLEXT_USE_NAMESPACE,
        .library_namespace = ns,
    };
    void* so = nullptr;
    char prop[PROPERTY_VALUE_MAX + 1];
    for (auto key : HAL_SUBNAME_KEY_PROPERTIES) {
        if (property_get(key, prop, nullptr) > 0) {
            String8 name;
            name.appendFormat("lib%s_%s.so", kind, prop);
            so = android_dlopen_ext(name.string(), RTLD_LOCAL | RTLD_NOW,
                    &dlextinfo);
            if (so)
                return so;
        }
    }
    return nullptr;
}

void *Loader::load_driver(const char* kind,
        egl_connection_t* cnx, uint32_t mask)
{
    void* dso = nullptr;
    if (mGetDriverNamespace) {
        android_namespace_t* ns = mGetDriverNamespace();
        if (ns) {
            dso = load_updated_driver(kind, ns);
        }
    }
    if (!dso) {
        dso = load_system_driver(kind);
        if (!dso)
            return NULL;
    }

    if (mask & EGL) {
        getProcAddress = (getProcAddressType)dlsym(dso, "eglGetProcAddress");

        ALOGE_IF(!getProcAddress,
                "can't find eglGetProcAddress() in %s", driver_absolute_path);
                "can't find eglGetProcAddress() in EGL driver library");

        egl_t* egl = &cnx->egl;
        __eglMustCastToProperFunctionPointerType* curr =
+6 −1
Original line number Diff line number Diff line
@@ -25,6 +25,8 @@
#include <utils/Singleton.h>
#include <utils/String8.h>

#include <gui/GraphicsEnv.h>

#include <EGL/egl.h>

// ----------------------------------------------------------------------------
@@ -54,6 +56,9 @@ class Loader : public Singleton<Loader>
    
    getProcAddressType getProcAddress;

    void* mLibGui;
    decltype(android_getDriverNamespace)* mGetDriverNamespace;

public:
    ~Loader();