Home | History | Annotate | Download | only in EGL
      1 /*
      2  ** Copyright 2007, The Android Open Source Project
      3  **
      4  ** Licensed under the Apache License, Version 2.0 (the "License");
      5  ** you may not use this file except in compliance with the License.
      6  ** You may obtain a copy of the License at
      7  **
      8  **     http://www.apache.org/licenses/LICENSE-2.0
      9  **
     10  ** Unless required by applicable law or agreed to in writing, software
     11  ** distributed under the License is distributed on an "AS IS" BASIS,
     12  ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  ** See the License for the specific language governing permissions and
     14  ** limitations under the License.
     15  */
     16 
     17 //#define LOG_NDEBUG 0
     18 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
     19 
     20 #include <EGL/Loader.h>
     21 
     22 #include <string>
     23 
     24 #include <dirent.h>
     25 #include <dlfcn.h>
     26 
     27 #include <android/dlext.h>
     28 #include <cutils/properties.h>
     29 #include <log/log.h>
     30 #include <utils/Timers.h>
     31 
     32 #ifndef __ANDROID_VNDK__
     33 #include <graphicsenv/GraphicsEnv.h>
     34 #endif
     35 #include <vndksupport/linker.h>
     36 
     37 #include "egl_platform_entries.h"
     38 #include "egl_trace.h"
     39 #include "egldefs.h"
     40 #include <EGL/eglext_angle.h>
     41 
     42 namespace android {
     43 
     44 /*
     45  * EGL userspace drivers must be provided either:
     46  * - as a single library:
     47  *      /vendor/lib/egl/libGLES.so
     48  *
     49  * - as separate libraries:
     50  *      /vendor/lib/egl/libEGL.so
     51  *      /vendor/lib/egl/libGLESv1_CM.so
     52  *      /vendor/lib/egl/libGLESv2.so
     53  *
     54  * The software renderer for the emulator must be provided as a single
     55  * library at:
     56  *
     57  *      /system/lib/egl/libGLES_android.so
     58  *
     59  *
     60  * For backward compatibility and to facilitate the transition to
     61  * this new naming scheme, the loader will additionally look for:
     62  *
     63  *      /{vendor|system}/lib/egl/lib{GLES | [EGL|GLESv1_CM|GLESv2]}_*.so
     64  *
     65  */
     66 
     67 Loader& Loader::getInstance() {
     68     static Loader loader;
     69     return loader;
     70 }
     71 
     72 static void* do_dlopen(const char* path, int mode) {
     73     ATRACE_CALL();
     74     return dlopen(path, mode);
     75 }
     76 
     77 static void* do_android_dlopen_ext(const char* path, int mode, const android_dlextinfo* info) {
     78     ATRACE_CALL();
     79     return android_dlopen_ext(path, mode, info);
     80 }
     81 
     82 static void* do_android_load_sphal_library(const char* path, int mode) {
     83     ATRACE_CALL();
     84     return android_load_sphal_library(path, mode);
     85 }
     86 
     87 static int do_android_unload_sphal_library(void* dso) {
     88     ATRACE_CALL();
     89     return android_unload_sphal_library(dso);
     90 }
     91 
     92 Loader::driver_t::driver_t(void* gles)
     93 {
     94     dso[0] = gles;
     95     for (size_t i=1 ; i<NELEM(dso) ; i++)
     96         dso[i] = nullptr;
     97 }
     98 
     99 Loader::driver_t::~driver_t()
    100 {
    101     for (size_t i=0 ; i<NELEM(dso) ; i++) {
    102         if (dso[i]) {
    103             dlclose(dso[i]);
    104             dso[i] = nullptr;
    105         }
    106     }
    107 }
    108 
    109 int Loader::driver_t::set(void* hnd, int32_t api)
    110 {
    111     switch (api) {
    112         case EGL:
    113             dso[0] = hnd;
    114             break;
    115         case GLESv1_CM:
    116             dso[1] = hnd;
    117             break;
    118         case GLESv2:
    119             dso[2] = hnd;
    120             break;
    121         default:
    122             return -EOVERFLOW;
    123     }
    124     return 0;
    125 }
    126 
    127 Loader::Loader()
    128     : getProcAddress(nullptr)
    129 {
    130 }
    131 
    132 Loader::~Loader() {
    133 }
    134 
    135 static void* load_wrapper(const char* path) {
    136     void* so = do_dlopen(path, RTLD_NOW | RTLD_LOCAL);
    137     ALOGE_IF(!so, "dlopen(\"%s\") failed: %s", path, dlerror());
    138     return so;
    139 }
    140 
    141 #ifndef EGL_WRAPPER_DIR
    142 #if defined(__LP64__)
    143 #define EGL_WRAPPER_DIR "/system/lib64"
    144 #else
    145 #define EGL_WRAPPER_DIR "/system/lib"
    146 #endif
    147 #endif
    148 
    149 static void setEmulatorGlesValue(void) {
    150     char prop[PROPERTY_VALUE_MAX];
    151     property_get("ro.kernel.qemu", prop, "0");
    152     if (atoi(prop) != 1) return;
    153 
    154     property_get("ro.kernel.qemu.gles",prop,"0");
    155     if (atoi(prop) == 1) {
    156         ALOGD("Emulator has host GPU support, qemu.gles is set to 1.");
    157         property_set("qemu.gles", "1");
    158         return;
    159     }
    160 
    161     // for now, checking the following
    162     // directory is good enough for emulator system images
    163     const char* vendor_lib_path =
    164 #if defined(__LP64__)
    165         "/vendor/lib64/egl";
    166 #else
    167         "/vendor/lib/egl";
    168 #endif
    169 
    170     const bool has_vendor_lib = (access(vendor_lib_path, R_OK) == 0);
    171     if (has_vendor_lib) {
    172         ALOGD("Emulator has vendor provided software renderer, qemu.gles is set to 2.");
    173         property_set("qemu.gles", "2");
    174     } else {
    175         ALOGD("Emulator without GPU support detected. "
    176               "Fallback to legacy software renderer, qemu.gles is set to 0.");
    177         property_set("qemu.gles", "0");
    178     }
    179 }
    180 
    181 static const char* DRIVER_SUFFIX_PROPERTY = "ro.hardware.egl";
    182 
    183 static const char* HAL_SUBNAME_KEY_PROPERTIES[2] = {
    184     DRIVER_SUFFIX_PROPERTY,
    185     "ro.board.platform",
    186 };
    187 
    188 static bool should_unload_system_driver(egl_connection_t* cnx) {
    189     // Return false if the system driver has been unloaded once.
    190     if (cnx->systemDriverUnloaded) {
    191         return false;
    192     }
    193 
    194     // Return true if Angle namespace is set.
    195     android_namespace_t* ns = android::GraphicsEnv::getInstance().getAngleNamespace();
    196     if (ns) {
    197         return true;
    198     }
    199 
    200 #ifndef __ANDROID_VNDK__
    201     // Return true if updated driver namespace is set.
    202     ns = android::GraphicsEnv::getInstance().getDriverNamespace();
    203     if (ns) {
    204         return true;
    205     }
    206 #endif
    207 
    208     return false;
    209 }
    210 
    211 static void uninit_api(char const* const* api, __eglMustCastToProperFunctionPointerType* curr) {
    212     while (*api) {
    213         *curr++ = nullptr;
    214         api++;
    215     }
    216 }
    217 
    218 void Loader::unload_system_driver(egl_connection_t* cnx) {
    219     ATRACE_CALL();
    220 
    221     uninit_api(gl_names,
    222                (__eglMustCastToProperFunctionPointerType*)&cnx
    223                        ->hooks[egl_connection_t::GLESv2_INDEX]
    224                        ->gl);
    225     uninit_api(gl_names,
    226                (__eglMustCastToProperFunctionPointerType*)&cnx
    227                        ->hooks[egl_connection_t::GLESv1_INDEX]
    228                        ->gl);
    229     uninit_api(egl_names, (__eglMustCastToProperFunctionPointerType*)&cnx->egl);
    230 
    231     if (cnx->dso) {
    232         ALOGD("Unload system gl driver.");
    233         driver_t* hnd = (driver_t*)cnx->dso;
    234         if (hnd->dso[2]) {
    235             do_android_unload_sphal_library(hnd->dso[2]);
    236         }
    237         if (hnd->dso[1]) {
    238             do_android_unload_sphal_library(hnd->dso[1]);
    239         }
    240         if (hnd->dso[0]) {
    241             do_android_unload_sphal_library(hnd->dso[0]);
    242         }
    243         cnx->dso = nullptr;
    244     }
    245 
    246     cnx->systemDriverUnloaded = true;
    247 }
    248 
    249 void* Loader::open(egl_connection_t* cnx)
    250 {
    251     ATRACE_CALL();
    252     const nsecs_t openTime = systemTime();
    253 
    254     if (should_unload_system_driver(cnx)) {
    255         unload_system_driver(cnx);
    256     }
    257 
    258     // If a driver has been loaded, return the driver directly.
    259     if (cnx->dso) {
    260         return cnx->dso;
    261     }
    262 
    263     setEmulatorGlesValue();
    264 
    265     // Check if we should use ANGLE early, so loading each driver doesn't require repeated queries.
    266     if (android::GraphicsEnv::getInstance().shouldUseAngle()) {
    267         cnx->shouldUseAngle = true;
    268     } else {
    269         cnx->shouldUseAngle = false;
    270     }
    271 
    272     // Firstly, try to load ANGLE driver.
    273     driver_t* hnd = attempt_to_load_angle(cnx);
    274     if (!hnd) {
    275         // Secondly, try to load from driver apk.
    276         hnd = attempt_to_load_updated_driver(cnx);
    277     }
    278 
    279     bool failToLoadFromDriverSuffixProperty = false;
    280     if (!hnd) {
    281         // Finally, try to load system driver, start by searching for the library name appended by
    282         // the system properties of the GLES userspace driver in both locations.
    283         // i.e.:
    284         //      libGLES_${prop}.so, or:
    285         //      libEGL_${prop}.so, libGLESv1_CM_${prop}.so, libGLESv2_${prop}.so
    286         char prop[PROPERTY_VALUE_MAX + 1];
    287         for (auto key : HAL_SUBNAME_KEY_PROPERTIES) {
    288             if (property_get(key, prop, nullptr) <= 0) {
    289                 continue;
    290             }
    291             hnd = attempt_to_load_system_driver(cnx, prop, true);
    292             if (hnd) {
    293                 break;
    294             } else if (strcmp(key, DRIVER_SUFFIX_PROPERTY) == 0) {
    295                 failToLoadFromDriverSuffixProperty = true;
    296             }
    297         }
    298     }
    299 
    300     if (!hnd) {
    301         // Can't find graphics driver by appending system properties, now search for the exact name
    302         // without any suffix of the GLES userspace driver in both locations.
    303         // i.e.:
    304         //      libGLES.so, or:
    305         //      libEGL.so, libGLESv1_CM.so, libGLESv2.so
    306         hnd = attempt_to_load_system_driver(cnx, nullptr, true);
    307     }
    308 
    309     if (!hnd && !failToLoadFromDriverSuffixProperty) {
    310         hnd = attempt_to_load_system_driver(cnx, nullptr, false);
    311     }
    312 
    313     if (!hnd) {
    314         android::GraphicsEnv::getInstance().setDriverLoaded(android::GraphicsEnv::Api::API_GL,
    315                                                             false, systemTime() - openTime);
    316     }
    317 
    318     LOG_ALWAYS_FATAL_IF(!hnd,
    319                         "couldn't find an OpenGL ES implementation, make sure you set %s or %s",
    320                         HAL_SUBNAME_KEY_PROPERTIES[0], HAL_SUBNAME_KEY_PROPERTIES[1]);
    321 
    322     if (!cnx->libEgl) {
    323         cnx->libEgl = load_wrapper(EGL_WRAPPER_DIR "/libEGL.so");
    324     }
    325     if (!cnx->libGles1) {
    326         cnx->libGles1 = load_wrapper(EGL_WRAPPER_DIR "/libGLESv1_CM.so");
    327     }
    328     if (!cnx->libGles2) {
    329         cnx->libGles2 = load_wrapper(EGL_WRAPPER_DIR "/libGLESv2.so");
    330     }
    331 
    332     if (!cnx->libEgl || !cnx->libGles2 || !cnx->libGles1) {
    333         android::GraphicsEnv::getInstance().setDriverLoaded(android::GraphicsEnv::Api::API_GL,
    334                                                             false, systemTime() - openTime);
    335     }
    336 
    337     LOG_ALWAYS_FATAL_IF(!cnx->libEgl,
    338             "couldn't load system EGL wrapper libraries");
    339 
    340     LOG_ALWAYS_FATAL_IF(!cnx->libGles2 || !cnx->libGles1,
    341             "couldn't load system OpenGL ES wrapper libraries");
    342 
    343     android::GraphicsEnv::getInstance().setDriverLoaded(android::GraphicsEnv::Api::API_GL, true,
    344                                                         systemTime() - openTime);
    345 
    346     return (void*)hnd;
    347 }
    348 
    349 void Loader::close(egl_connection_t* cnx)
    350 {
    351     driver_t* hnd = (driver_t*) cnx->dso;
    352     delete hnd;
    353     cnx->dso = nullptr;
    354 
    355     cnx->shouldUseAngle = false;
    356     cnx->angleDecided = false;
    357     cnx->useAngle = false;
    358 
    359     if (cnx->vendorEGL) {
    360         dlclose(cnx->vendorEGL);
    361         cnx->vendorEGL = nullptr;
    362     }
    363 }
    364 
    365 void Loader::init_api(void* dso,
    366         char const * const * api,
    367         char const * const * ref_api,
    368         __eglMustCastToProperFunctionPointerType* curr,
    369         getProcAddressType getProcAddress)
    370 {
    371     ATRACE_CALL();
    372 
    373     const ssize_t SIZE = 256;
    374     char scrap[SIZE];
    375     while (*api) {
    376         char const * name = *api;
    377         if (ref_api) {
    378             char const * ref_name = *ref_api;
    379             if (std::strcmp(name, ref_name) != 0) {
    380                 *curr++ = nullptr;
    381                 ref_api++;
    382                 continue;
    383             }
    384         }
    385 
    386         __eglMustCastToProperFunctionPointerType f =
    387             (__eglMustCastToProperFunctionPointerType)dlsym(dso, name);
    388         if (f == nullptr) {
    389             // couldn't find the entry-point, use eglGetProcAddress()
    390             f = getProcAddress(name);
    391         }
    392         if (f == nullptr) {
    393             // Try without the OES postfix
    394             ssize_t index = ssize_t(strlen(name)) - 3;
    395             if ((index>0 && (index<SIZE-1)) && (!strcmp(name+index, "OES"))) {
    396                 strncpy(scrap, name, index);
    397                 scrap[index] = 0;
    398                 f = (__eglMustCastToProperFunctionPointerType)dlsym(dso, scrap);
    399                 //ALOGD_IF(f, "found <%s> instead", scrap);
    400             }
    401         }
    402         if (f == nullptr) {
    403             // Try with the OES postfix
    404             ssize_t index = ssize_t(strlen(name)) - 3;
    405             if (index>0 && strcmp(name+index, "OES")) {
    406                 snprintf(scrap, SIZE, "%sOES", name);
    407                 f = (__eglMustCastToProperFunctionPointerType)dlsym(dso, scrap);
    408                 //ALOGD_IF(f, "found <%s> instead", scrap);
    409             }
    410         }
    411         if (f == nullptr) {
    412             //ALOGD("%s", name);
    413             f = (__eglMustCastToProperFunctionPointerType)gl_unimplemented;
    414 
    415             /*
    416              * GL_EXT_debug_label is special, we always report it as
    417              * supported, it's handled by GLES_trace. If GLES_trace is not
    418              * enabled, then these are no-ops.
    419              */
    420             if (!strcmp(name, "glInsertEventMarkerEXT")) {
    421                 f = (__eglMustCastToProperFunctionPointerType)gl_noop;
    422             } else if (!strcmp(name, "glPushGroupMarkerEXT")) {
    423                 f = (__eglMustCastToProperFunctionPointerType)gl_noop;
    424             } else if (!strcmp(name, "glPopGroupMarkerEXT")) {
    425                 f = (__eglMustCastToProperFunctionPointerType)gl_noop;
    426             }
    427         }
    428         *curr++ = f;
    429         api++;
    430         if (ref_api) ref_api++;
    431     }
    432 }
    433 
    434 static void* load_system_driver(const char* kind, const char* suffix, const bool exact) {
    435     ATRACE_CALL();
    436     class MatchFile {
    437     public:
    438         static std::string find(const char* libraryName, const bool exact) {
    439             const char* const searchPaths[] = {
    440 #if defined(__LP64__)
    441                     "/vendor/lib64/egl",
    442                     "/system/lib64/egl"
    443 #else
    444                     "/vendor/lib/egl",
    445                     "/system/lib/egl"
    446 #endif
    447             };
    448 
    449             for (auto dir : searchPaths) {
    450                 std::string absolutePath;
    451                 if (find(absolutePath, libraryName, dir, exact)) {
    452                     return absolutePath;
    453                 }
    454             }
    455 
    456             // Driver not found. gah.
    457             return std::string();
    458         }
    459     private:
    460         static bool find(std::string& result,
    461                 const std::string& pattern, const char* const search, bool exact) {
    462             if (exact) {
    463                 std::string absolutePath = std::string(search) + "/" + pattern + ".so";
    464                 if (!access(absolutePath.c_str(), R_OK)) {
    465                     result = absolutePath;
    466                     return true;
    467                 }
    468                 return false;
    469             }
    470 
    471             DIR* d = opendir(search);
    472             if (d != nullptr) {
    473                 struct dirent* e;
    474                 while ((e = readdir(d)) != nullptr) {
    475                     if (e->d_type == DT_DIR) {
    476                         continue;
    477                     }
    478                     if (!strcmp(e->d_name, "libGLES_android.so")) {
    479                         // always skip the software renderer
    480                         continue;
    481                     }
    482                     if (strstr(e->d_name, pattern.c_str()) == e->d_name) {
    483                         if (!strcmp(e->d_name + strlen(e->d_name) - 3, ".so")) {
    484                             result = std::string(search) + "/" + e->d_name;
    485                             closedir(d);
    486                             return true;
    487                         }
    488                     }
    489                 }
    490                 closedir(d);
    491             }
    492             return false;
    493         }
    494     };
    495 
    496     std::string libraryName = std::string("lib") + kind;
    497     if (suffix) {
    498         libraryName += std::string("_") + suffix;
    499     } else if (!exact) {
    500         // Deprecated: we look for files that match
    501         //      libGLES_*.so, or:
    502         //      libEGL_*.so, libGLESv1_CM_*.so, libGLESv2_*.so
    503         libraryName += std::string("_");
    504     }
    505     std::string absolutePath = MatchFile::find(libraryName.c_str(), exact);
    506     if (absolutePath.empty()) {
    507         // this happens often, we don't want to log an error
    508         return nullptr;
    509     }
    510     const char* const driver_absolute_path = absolutePath.c_str();
    511 
    512     // Try to load drivers from the 'sphal' namespace, if it exist. Fall back to
    513     // the original routine when the namespace does not exist.
    514     // See /system/core/rootdir/etc/ld.config.txt for the configuration of the
    515     // sphal namespace.
    516     void* dso = do_android_load_sphal_library(driver_absolute_path,
    517                                               RTLD_NOW | RTLD_LOCAL);
    518     if (dso == nullptr) {
    519         const char* err = dlerror();
    520         ALOGE("load_driver(%s): %s", driver_absolute_path, err ? err : "unknown");
    521         return nullptr;
    522     }
    523 
    524     ALOGD("loaded %s", driver_absolute_path);
    525 
    526     return dso;
    527 }
    528 
    529 static void* load_angle_from_namespace(const char* kind, android_namespace_t* ns) {
    530     const android_dlextinfo dlextinfo = {
    531             .flags = ANDROID_DLEXT_USE_NAMESPACE,
    532             .library_namespace = ns,
    533     };
    534 
    535     std::string name = std::string("lib") + kind + "_angle.so";
    536 
    537     void* so = do_android_dlopen_ext(name.c_str(), RTLD_LOCAL | RTLD_NOW, &dlextinfo);
    538 
    539     if (so) {
    540         ALOGD("dlopen_ext from APK (%s) success at %p", name.c_str(), so);
    541         return so;
    542     } else {
    543         ALOGE("dlopen_ext(\"%s\") failed: %s", name.c_str(), dlerror());
    544     }
    545 
    546     return nullptr;
    547 }
    548 
    549 static void* load_angle(const char* kind, android_namespace_t* ns, egl_connection_t* cnx) {
    550     void* so = nullptr;
    551 
    552     if ((cnx->shouldUseAngle) || android::GraphicsEnv::getInstance().shouldUseAngle()) {
    553         so = load_angle_from_namespace(kind, ns);
    554         cnx->shouldUseAngle = true;
    555     } else {
    556         cnx->shouldUseAngle = false;
    557     }
    558 
    559     if (so) {
    560         ALOGV("Loaded ANGLE %s library for '%s' (instead of native)", kind,
    561             android::GraphicsEnv::getInstance().getAngleAppName().c_str());
    562         cnx->useAngle = true;
    563 
    564         char prop[PROPERTY_VALUE_MAX];
    565 
    566         property_get("debug.hwui.renderer", prop, "UNSET");
    567         ALOGV("Skia's renderer set to %s", prop);
    568 
    569         EGLint angleBackendDefault = EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE;
    570         property_get("debug.angle.backend", prop, "0");
    571         switch (atoi(prop)) {
    572             case 1:
    573                 ALOGV("%s: Requesting OpenGLES back-end", __FUNCTION__);
    574                 angleBackendDefault = EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE;
    575                 break;
    576             case 2:
    577                 ALOGV("%s: Requesting Vulkan back-end", __FUNCTION__);
    578                 angleBackendDefault = EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE;
    579                 break;
    580             default:
    581                 break;
    582         }
    583 
    584         cnx->angleBackend = angleBackendDefault;
    585         if (!cnx->vendorEGL && (cnx->angleBackend == EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE)) {
    586             // Find and load vendor libEGL for ANGLE's GL back-end to use.
    587             char prop[PROPERTY_VALUE_MAX + 1];
    588             for (auto key : HAL_SUBNAME_KEY_PROPERTIES) {
    589                 if (property_get(key, prop, nullptr) <= 0) {
    590                     continue;
    591                 }
    592                 void* dso = load_system_driver("EGL", prop, true);
    593                 if (dso) {
    594                     cnx->vendorEGL = dso;
    595                     break;
    596                 }
    597             }
    598             if (!cnx->vendorEGL) {
    599                 cnx->vendorEGL = load_system_driver("EGL", nullptr, true);
    600             }
    601         }
    602     } else {
    603         ALOGV("Loaded native %s library for '%s' (instead of ANGLE)", kind,
    604             android::GraphicsEnv::getInstance().getAngleAppName().c_str());
    605         cnx->useAngle = false;
    606     }
    607     cnx->angleDecided = true;
    608 
    609     return so;
    610 }
    611 
    612 static void* load_updated_driver(const char* kind, android_namespace_t* ns) {
    613     ATRACE_CALL();
    614     const android_dlextinfo dlextinfo = {
    615         .flags = ANDROID_DLEXT_USE_NAMESPACE,
    616         .library_namespace = ns,
    617     };
    618     void* so = nullptr;
    619     char prop[PROPERTY_VALUE_MAX + 1];
    620     for (auto key : HAL_SUBNAME_KEY_PROPERTIES) {
    621         if (property_get(key, prop, nullptr) <= 0) {
    622             continue;
    623         }
    624         std::string name = std::string("lib") + kind + "_" + prop + ".so";
    625         so = do_android_dlopen_ext(name.c_str(), RTLD_LOCAL | RTLD_NOW, &dlextinfo);
    626         if (so) {
    627             return so;
    628         }
    629     }
    630     return nullptr;
    631 }
    632 
    633 Loader::driver_t* Loader::attempt_to_load_angle(egl_connection_t* cnx) {
    634     ATRACE_CALL();
    635     android_namespace_t* ns = android::GraphicsEnv::getInstance().getAngleNamespace();
    636     if (!ns) {
    637         return nullptr;
    638     }
    639 
    640     android::GraphicsEnv::getInstance().setDriverToLoad(android::GraphicsEnv::Driver::ANGLE);
    641     driver_t* hnd = nullptr;
    642 
    643     // ANGLE doesn't ship with GLES library, and thus we skip GLES driver.
    644     void* dso = load_angle("EGL", ns, cnx);
    645     if (dso) {
    646         initialize_api(dso, cnx, EGL);
    647         hnd = new driver_t(dso);
    648 
    649         dso = load_angle("GLESv1_CM", ns, cnx);
    650         initialize_api(dso, cnx, GLESv1_CM);
    651         hnd->set(dso, GLESv1_CM);
    652 
    653         dso = load_angle("GLESv2", ns, cnx);
    654         initialize_api(dso, cnx, GLESv2);
    655         hnd->set(dso, GLESv2);
    656     }
    657     return hnd;
    658 }
    659 
    660 Loader::driver_t* Loader::attempt_to_load_updated_driver(egl_connection_t* cnx) {
    661     ATRACE_CALL();
    662 #ifndef __ANDROID_VNDK__
    663     android_namespace_t* ns = android::GraphicsEnv::getInstance().getDriverNamespace();
    664     if (!ns) {
    665         return nullptr;
    666     }
    667 
    668     ALOGD("Load updated gl driver.");
    669     android::GraphicsEnv::getInstance().setDriverToLoad(android::GraphicsEnv::Driver::GL_UPDATED);
    670     driver_t* hnd = nullptr;
    671     void* dso = load_updated_driver("GLES", ns);
    672     if (dso) {
    673         initialize_api(dso, cnx, EGL | GLESv1_CM | GLESv2);
    674         hnd = new driver_t(dso);
    675         return hnd;
    676     }
    677 
    678     dso = load_updated_driver("EGL", ns);
    679     if (dso) {
    680         initialize_api(dso, cnx, EGL);
    681         hnd = new driver_t(dso);
    682 
    683         dso = load_updated_driver("GLESv1_CM", ns);
    684         initialize_api(dso, cnx, GLESv1_CM);
    685         hnd->set(dso, GLESv1_CM);
    686 
    687         dso = load_updated_driver("GLESv2", ns);
    688         initialize_api(dso, cnx, GLESv2);
    689         hnd->set(dso, GLESv2);
    690     }
    691     return hnd;
    692 #else
    693     return nullptr;
    694 #endif
    695 }
    696 
    697 Loader::driver_t* Loader::attempt_to_load_system_driver(egl_connection_t* cnx, const char* suffix,
    698                                                         const bool exact) {
    699     ATRACE_CALL();
    700     android::GraphicsEnv::getInstance().setDriverToLoad(android::GraphicsEnv::Driver::GL);
    701     driver_t* hnd = nullptr;
    702     void* dso = load_system_driver("GLES", suffix, exact);
    703     if (dso) {
    704         initialize_api(dso, cnx, EGL | GLESv1_CM | GLESv2);
    705         hnd = new driver_t(dso);
    706         return hnd;
    707     }
    708     dso = load_system_driver("EGL", suffix, exact);
    709     if (dso) {
    710         initialize_api(dso, cnx, EGL);
    711         hnd = new driver_t(dso);
    712 
    713         dso = load_system_driver("GLESv1_CM", suffix, exact);
    714         initialize_api(dso, cnx, GLESv1_CM);
    715         hnd->set(dso, GLESv1_CM);
    716 
    717         dso = load_system_driver("GLESv2", suffix, exact);
    718         initialize_api(dso, cnx, GLESv2);
    719         hnd->set(dso, GLESv2);
    720     }
    721     return hnd;
    722 }
    723 
    724 void Loader::initialize_api(void* dso, egl_connection_t* cnx, uint32_t mask) {
    725     if (mask & EGL) {
    726         getProcAddress = (getProcAddressType)dlsym(dso, "eglGetProcAddress");
    727 
    728         ALOGE_IF(!getProcAddress,
    729                 "can't find eglGetProcAddress() in EGL driver library");
    730 
    731         egl_t* egl = &cnx->egl;
    732         __eglMustCastToProperFunctionPointerType* curr =
    733             (__eglMustCastToProperFunctionPointerType*)egl;
    734         char const * const * api = egl_names;
    735         while (*api) {
    736             char const * name = *api;
    737             __eglMustCastToProperFunctionPointerType f =
    738                 (__eglMustCastToProperFunctionPointerType)dlsym(dso, name);
    739             if (f == nullptr) {
    740                 // couldn't find the entry-point, use eglGetProcAddress()
    741                 f = getProcAddress(name);
    742                 if (f == nullptr) {
    743                     f = (__eglMustCastToProperFunctionPointerType)nullptr;
    744                 }
    745             }
    746             *curr++ = f;
    747             api++;
    748         }
    749     }
    750 
    751     if (mask & GLESv1_CM) {
    752         init_api(dso, gl_names_1, gl_names,
    753             (__eglMustCastToProperFunctionPointerType*)
    754                 &cnx->hooks[egl_connection_t::GLESv1_INDEX]->gl,
    755             getProcAddress);
    756     }
    757 
    758     if (mask & GLESv2) {
    759         init_api(dso, gl_names, nullptr,
    760             (__eglMustCastToProperFunctionPointerType*)
    761                 &cnx->hooks[egl_connection_t::GLESv2_INDEX]->gl,
    762             getProcAddress);
    763     }
    764 }
    765 
    766 } // namespace android
    767