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 <android-base/properties.h>
23 #include <android/dlext.h>
24 #include <cutils/properties.h>
25 #include <dirent.h>
26 #include <dlfcn.h>
27 #include <graphicsenv/GraphicsEnv.h>
28 #include <log/log.h>
29 #include <utils/Timers.h>
30 #include <vndksupport/linker.h>
31 
32 #include <string>
33 
34 #include "EGL/eglext_angle.h"
35 #include "egl_platform_entries.h"
36 #include "egl_trace.h"
37 #include "egldefs.h"
38 
39 namespace android {
40 
41 /*
42  * EGL userspace drivers must be provided either:
43  * - as a single library:
44  *      /vendor/${LIB}/egl/libGLES.so
45  *
46  * - as separate libraries:
47  *      /vendor/${LIB}/egl/libEGL.so
48  *      /vendor/${LIB}/egl/libGLESv1_CM.so
49  *      /vendor/${LIB}/egl/libGLESv2.so
50  *
51  * For backward compatibility and to facilitate the transition to
52  * this new naming scheme, the loader will additionally look for:
53  *
54  *      /vendor/${LIB}/egl/lib{GLES | [EGL|GLESv1_CM|GLESv2]}_${SUFFIX}.so
55  *
56  */
57 
58 #ifndef SYSTEM_LIB_PATH
59 #if defined(__LP64__)
60 #define SYSTEM_LIB_PATH "/system/lib64"
61 #else
62 #define SYSTEM_LIB_PATH "/system/lib"
63 #endif
64 #endif
65 
66 static const char* PERSIST_DRIVER_SUFFIX_PROPERTY = "persist.graphics.egl";
67 static const char* RO_DRIVER_SUFFIX_PROPERTY = "ro.hardware.egl";
68 static const char* RO_BOARD_PLATFORM_PROPERTY = "ro.board.platform";
69 static const char* ANGLE_SUFFIX_VALUE = "angle";
70 
71 static const char* HAL_SUBNAME_KEY_PROPERTIES[3] = {
72         PERSIST_DRIVER_SUFFIX_PROPERTY,
73         RO_DRIVER_SUFFIX_PROPERTY,
74         RO_BOARD_PLATFORM_PROPERTY,
75 };
76 
77 static const char* const VENDOR_LIB_EGL_DIR =
78 #if defined(__LP64__)
79         "/vendor/lib64/egl";
80 #else
81         "/vendor/lib/egl";
82 #endif
83 
84 static const char* const SYSTEM_LIB_DIR =
85 #if defined(__LP64__)
86         "/system/lib64";
87 #else
88         "/system/lib";
89 #endif
90 
do_dlopen(const char * path,int mode)91 static void* do_dlopen(const char* path, int mode) {
92     ATRACE_CALL();
93     return dlopen(path, mode);
94 }
95 
do_android_dlopen_ext(const char * path,int mode,const android_dlextinfo * info)96 static void* do_android_dlopen_ext(const char* path, int mode, const android_dlextinfo* info) {
97     ATRACE_CALL();
98     return android_dlopen_ext(path, mode, info);
99 }
100 
do_android_load_sphal_library(const char * path,int mode)101 static void* do_android_load_sphal_library(const char* path, int mode) {
102     ATRACE_CALL();
103     return android_load_sphal_library(path, mode);
104 }
105 
do_android_unload_sphal_library(void * dso)106 static int do_android_unload_sphal_library(void* dso) {
107     ATRACE_CALL();
108     return android_unload_sphal_library(dso);
109 }
110 
load_wrapper(const char * path)111 static void* load_wrapper(const char* path) {
112     void* so = do_dlopen(path, RTLD_NOW | RTLD_LOCAL);
113     ALOGE_IF(!so, "dlopen(\"%s\") failed: %s", path, dlerror());
114     return so;
115 }
116 
getInstance()117 Loader& Loader::getInstance() {
118     static Loader loader;
119     return loader;
120 }
121 
driver_t(void * gles)122 Loader::driver_t::driver_t(void* gles)
123 {
124     dso[0] = gles;
125     for (size_t i=1 ; i<NELEM(dso) ; i++)
126         dso[i] = nullptr;
127 }
128 
~driver_t()129 Loader::driver_t::~driver_t()
130 {
131     for (size_t i=0 ; i<NELEM(dso) ; i++) {
132         if (dso[i]) {
133             dlclose(dso[i]);
134             dso[i] = nullptr;
135         }
136     }
137 }
138 
set(void * hnd,int32_t api)139 int Loader::driver_t::set(void* hnd, int32_t api)
140 {
141     switch (api) {
142         case EGL:
143             dso[0] = hnd;
144             break;
145         case GLESv1_CM:
146             dso[1] = hnd;
147             break;
148         case GLESv2:
149             dso[2] = hnd;
150             break;
151         default:
152             return -EOVERFLOW;
153     }
154     return 0;
155 }
156 
Loader()157 Loader::Loader()
158     : getProcAddress(nullptr)
159 {
160 }
161 
~Loader()162 Loader::~Loader() {
163 }
164 
165 // Check whether the loaded system drivers should be unloaded in order to
166 // load ANGLE or the updatable graphics drivers.
167 // If ANGLE namespace is set, it means the application is identified to run on top of ANGLE.
168 // If updatable graphics driver namespace is set, it means the application is identified to
169 // run on top of updatable graphics drivers.
should_unload_system_driver(egl_connection_t * cnx)170 static bool should_unload_system_driver(egl_connection_t* cnx) {
171     // Return false if the system driver has been unloaded once.
172     if (cnx->systemDriverUnloaded) {
173         return false;
174     }
175 
176     // Return true if ANGLE namespace is set.
177     android_namespace_t* ns = android::GraphicsEnv::getInstance().getAngleNamespace();
178     if (ns) {
179         // Unless the default GLES driver is ANGLE and the process should use system ANGLE, since
180         // the intended GLES driver is already loaded.
181         // This should be updated in a later patch that cleans up namespaces
182         if (!(cnx->angleLoaded && android::GraphicsEnv::getInstance().shouldUseSystemAngle())) {
183             return true;
184         }
185     }
186 
187     // Return true if app requests to use ANGLE, but ANGLE is not loaded.
188     // Difference with the case above is on devices that don't have an ANGLE apk installed,
189     // ANGLE namespace is not set. In that case if ANGLE in system partition is not loaded,
190     // we should unload the system driver first, and then load ANGLE from system partition.
191     if (!cnx->angleLoaded && android::GraphicsEnv::getInstance().shouldUseAngle()) {
192         return true;
193     }
194 
195     // Return true if native GLES drivers should be used and ANGLE is already loaded.
196     if (android::GraphicsEnv::getInstance().shouldUseNativeDriver() && cnx->angleLoaded) {
197         return true;
198     }
199 
200     // Return true if updated driver namespace is set.
201     ns = android::GraphicsEnv::getInstance().getDriverNamespace();
202     if (ns) {
203         return true;
204     }
205 
206     return false;
207 }
208 
uninit_api(char const * const * api,__eglMustCastToProperFunctionPointerType * curr)209 static void uninit_api(char const* const* api, __eglMustCastToProperFunctionPointerType* curr) {
210     while (*api) {
211         *curr++ = nullptr;
212         api++;
213     }
214 }
215 
unload_system_driver(egl_connection_t * cnx)216 void Loader::unload_system_driver(egl_connection_t* cnx) {
217     ATRACE_CALL();
218 
219     uninit_api(gl_names,
220                (__eglMustCastToProperFunctionPointerType*)&cnx
221                        ->hooks[egl_connection_t::GLESv2_INDEX]
222                        ->gl);
223     uninit_api(gl_names,
224                (__eglMustCastToProperFunctionPointerType*)&cnx
225                        ->hooks[egl_connection_t::GLESv1_INDEX]
226                        ->gl);
227     uninit_api(egl_names, (__eglMustCastToProperFunctionPointerType*)&cnx->egl);
228 
229     if (cnx->dso) {
230         ALOGD("Unload system gl driver.");
231         driver_t* hnd = (driver_t*)cnx->dso;
232         if (hnd->dso[2]) {
233             do_android_unload_sphal_library(hnd->dso[2]);
234         }
235         if (hnd->dso[1]) {
236             do_android_unload_sphal_library(hnd->dso[1]);
237         }
238         if (hnd->dso[0]) {
239             do_android_unload_sphal_library(hnd->dso[0]);
240         }
241         cnx->dso = nullptr;
242         cnx->angleLoaded = false;
243     }
244 
245     cnx->systemDriverUnloaded = true;
246 }
247 
open(egl_connection_t * cnx)248 void* Loader::open(egl_connection_t* cnx) {
249     ATRACE_CALL();
250     const nsecs_t openTime = systemTime();
251 
252     if (cnx->dso && should_unload_system_driver(cnx)) {
253         unload_system_driver(cnx);
254     }
255 
256     // If a driver has been loaded, return the driver directly.
257     if (cnx->dso) {
258         return cnx->dso;
259     }
260 
261     driver_t* hnd = nullptr;
262     // Firstly, try to load ANGLE driver, if ANGLE should be loaded and fail, abort.
263     if (android::GraphicsEnv::getInstance().shouldUseAngle()) {
264         hnd = attempt_to_load_angle(cnx);
265         LOG_ALWAYS_FATAL_IF(!hnd, "Failed to load ANGLE.");
266     }
267 
268     if (!hnd) {
269         // Secondly, try to load from driver apk.
270         hnd = attempt_to_load_updated_driver(cnx);
271 
272         // If updated driver apk is set but fail to load, abort here.
273         LOG_ALWAYS_FATAL_IF(android::GraphicsEnv::getInstance().getDriverNamespace(),
274                             "couldn't find an OpenGL ES implementation from %s",
275                             android::GraphicsEnv::getInstance().getDriverPath().c_str());
276     }
277 
278     // Attempt to load native GLES drivers specified by ro.hardware.egl if native is selected.
279     // If native is selected but fail to load, abort.
280     if (!hnd && android::GraphicsEnv::getInstance().shouldUseNativeDriver()) {
281         auto driverSuffix = base::GetProperty(RO_DRIVER_SUFFIX_PROPERTY, "");
282         LOG_ALWAYS_FATAL_IF(driverSuffix.empty(),
283                             "Native GLES driver is selected but not specified in %s",
284                             RO_DRIVER_SUFFIX_PROPERTY);
285         hnd = attempt_to_load_system_driver(cnx, driverSuffix.c_str(), true);
286         LOG_ALWAYS_FATAL_IF(!hnd, "Native GLES driver is selected but failed to load. %s=%s",
287                             RO_DRIVER_SUFFIX_PROPERTY, driverSuffix.c_str());
288     }
289 
290     // Finally, try to load default driver.
291     bool failToLoadFromDriverSuffixProperty = false;
292     if (!hnd) {
293         // Start by searching for the library name appended by the system
294         // properties of the GLES userspace driver in both locations.
295         // i.e.:
296         //      libGLES_${prop}.so, or:
297         //      libEGL_${prop}.so, libGLESv1_CM_${prop}.so, libGLESv2_${prop}.so
298         for (auto key : HAL_SUBNAME_KEY_PROPERTIES) {
299             auto prop = base::GetProperty(key, "");
300             if (prop.empty()) {
301                 continue;
302             }
303             hnd = attempt_to_load_system_driver(cnx, prop.c_str(), true);
304             if (!hnd) {
305                 ALOGD("Failed to load drivers from property %s with value %s", key, prop.c_str());
306                 failToLoadFromDriverSuffixProperty = true;
307             }
308 
309             // Abort regardless of whether subsequent properties are set, the value must be set
310             // correctly with the first property that has a value.
311             break;
312         }
313     }
314 
315     if (!hnd) {
316         // Can't find graphics driver by appending the value from system properties, now search for
317         // the exact name without any suffix of the GLES userspace driver in both locations.
318         // i.e.:
319         //      libGLES.so, or:
320         //      libEGL.so, libGLESv1_CM.so, libGLESv2.so
321         hnd = attempt_to_load_system_driver(cnx, nullptr, true);
322     }
323 
324     if (!hnd && !failToLoadFromDriverSuffixProperty &&
325         property_get_int32("ro.vendor.api_level", 0) < __ANDROID_API_U__) {
326         // Still can't find the graphics drivers with the exact name. This time try to use wildcard
327         // matching if the device is launched before Android 14.
328         hnd = attempt_to_load_system_driver(cnx, nullptr, false);
329     }
330 
331     if (!hnd) {
332         android::GraphicsEnv::getInstance().setDriverLoaded(android::GpuStatsInfo::Api::API_GL,
333                                                             false, systemTime() - openTime);
334     } else {
335         // init_angle_backend will check if loaded driver is ANGLE or not,
336         // will set cnx->angleLoaded appropriately.
337         // Do this here so that we use ANGLE path when driver is ANGLE (e.g. loaded as native),
338         // not just loading ANGLE as option.
339         attempt_to_init_angle_backend(hnd->dso[2], cnx);
340     }
341 
342     LOG_ALWAYS_FATAL_IF(!hnd,
343                         "couldn't find an OpenGL ES implementation, make sure one of %s, %s and %s "
344                         "is set",
345                         HAL_SUBNAME_KEY_PROPERTIES[0], HAL_SUBNAME_KEY_PROPERTIES[1],
346                         HAL_SUBNAME_KEY_PROPERTIES[2]);
347 
348     if (!cnx->libEgl) {
349         cnx->libEgl = load_wrapper(SYSTEM_LIB_PATH "/libEGL.so");
350     }
351     if (!cnx->libGles1) {
352         cnx->libGles1 = load_wrapper(SYSTEM_LIB_PATH "/libGLESv1_CM.so");
353     }
354     if (!cnx->libGles2) {
355         cnx->libGles2 = load_wrapper(SYSTEM_LIB_PATH "/libGLESv2.so");
356     }
357 
358     if (!cnx->libEgl || !cnx->libGles2 || !cnx->libGles1) {
359         android::GraphicsEnv::getInstance().setDriverLoaded(android::GpuStatsInfo::Api::API_GL,
360                                                             false, systemTime() - openTime);
361     }
362 
363     LOG_ALWAYS_FATAL_IF(!cnx->libEgl,
364             "couldn't load system EGL wrapper libraries");
365 
366     LOG_ALWAYS_FATAL_IF(!cnx->libGles2 || !cnx->libGles1,
367                         "couldn't load system OpenGL ES wrapper libraries");
368 
369     android::GraphicsEnv::getInstance().setDriverLoaded(android::GpuStatsInfo::Api::API_GL, true,
370                                                         systemTime() - openTime);
371 
372     return (void*)hnd;
373 }
374 
close(egl_connection_t * cnx)375 void Loader::close(egl_connection_t* cnx)
376 {
377     driver_t* hnd = (driver_t*) cnx->dso;
378     delete hnd;
379     cnx->dso = nullptr;
380 
381     cnx->angleLoaded = false;
382 }
383 
init_api(void * dso,char const * const * api,char const * const * ref_api,__eglMustCastToProperFunctionPointerType * curr,getProcAddressType getProcAddress)384 void Loader::init_api(void* dso,
385         char const * const * api,
386         char const * const * ref_api,
387         __eglMustCastToProperFunctionPointerType* curr,
388         getProcAddressType getProcAddress)
389 {
390     ATRACE_CALL();
391 
392     const ssize_t SIZE = 256;
393     char scrap[SIZE];
394     while (*api) {
395         char const * name = *api;
396         if (ref_api) {
397             char const * ref_name = *ref_api;
398             if (std::strcmp(name, ref_name) != 0) {
399                 *curr++ = nullptr;
400                 ref_api++;
401                 continue;
402             }
403         }
404 
405         __eglMustCastToProperFunctionPointerType f =
406             (__eglMustCastToProperFunctionPointerType)dlsym(dso, name);
407         if (f == nullptr) {
408             // couldn't find the entry-point, use eglGetProcAddress()
409             f = getProcAddress(name);
410         }
411         if (f == nullptr) {
412             // Try without the OES postfix
413             ssize_t index = ssize_t(strlen(name)) - 3;
414             if ((index>0 && (index<SIZE-1)) && (!strcmp(name+index, "OES"))) {
415                 strncpy(scrap, name, index);
416                 scrap[index] = 0;
417                 f = (__eglMustCastToProperFunctionPointerType)dlsym(dso, scrap);
418                 //ALOGD_IF(f, "found <%s> instead", scrap);
419             }
420         }
421         if (f == nullptr) {
422             // Try with the OES postfix
423             ssize_t index = ssize_t(strlen(name)) - 3;
424             if (index>0 && strcmp(name+index, "OES")) {
425                 snprintf(scrap, SIZE, "%sOES", name);
426                 f = (__eglMustCastToProperFunctionPointerType)dlsym(dso, scrap);
427                 //ALOGD_IF(f, "found <%s> instead", scrap);
428             }
429         }
430         if (f == nullptr) {
431             //ALOGD("%s", name);
432             f = (__eglMustCastToProperFunctionPointerType)gl_unimplemented;
433 
434             /*
435              * GL_EXT_debug_marker is special, we always report it as
436              * supported, it's handled by GLES_trace. If GLES_trace is not
437              * enabled, then these are no-ops.
438              */
439             if (!strcmp(name, "glInsertEventMarkerEXT")) {
440                 f = (__eglMustCastToProperFunctionPointerType)gl_noop;
441             } else if (!strcmp(name, "glPushGroupMarkerEXT")) {
442                 f = (__eglMustCastToProperFunctionPointerType)gl_noop;
443             } else if (!strcmp(name, "glPopGroupMarkerEXT")) {
444                 f = (__eglMustCastToProperFunctionPointerType)gl_noop;
445             }
446         }
447         *curr++ = f;
448         api++;
449         if (ref_api) ref_api++;
450     }
451 }
452 
findLibrary(const std::string libraryName,const std::string searchPath,const bool exact)453 static std::string findLibrary(const std::string libraryName, const std::string searchPath,
454                                const bool exact) {
455     if (exact) {
456         std::string absolutePath = searchPath + "/" + libraryName + ".so";
457         if (!access(absolutePath.c_str(), R_OK)) {
458             return absolutePath;
459         }
460         return std::string();
461     }
462 
463     DIR* d = opendir(searchPath.c_str());
464     if (d != nullptr) {
465         struct dirent* e;
466         while ((e = readdir(d)) != nullptr) {
467             if (e->d_type == DT_DIR) {
468                 continue;
469             }
470             if (!strcmp(e->d_name, "libGLES_android.so")) {
471                 // always skip the software renderer
472                 continue;
473             }
474             if (strstr(e->d_name, libraryName.c_str()) == e->d_name) {
475                 if (!strcmp(e->d_name + strlen(e->d_name) - 3, ".so")) {
476                     std::string result = searchPath + "/" + e->d_name;
477                     closedir(d);
478                     return result;
479                 }
480             }
481         }
482         closedir(d);
483     }
484     // Driver not found. gah.
485     return std::string();
486 }
487 
load_system_driver(const char * kind,const char * suffix,const bool exact)488 static void* load_system_driver(const char* kind, const char* suffix, const bool exact) {
489     ATRACE_CALL();
490 
491     std::string libraryName = std::string("lib") + kind;
492     if (suffix) {
493         libraryName += std::string("_") + suffix;
494     } else if (!exact) {
495         // Deprecated for devices launching in Android 14
496         // Look for files that match
497         //      libGLES_*.so, or,
498         //      libEGL_*.so, libGLESv1_CM_*.so, libGLESv2_*.so
499         libraryName += std::string("_");
500     }
501 
502     void* dso = nullptr;
503 
504     const bool isSuffixAngle = suffix != nullptr && strcmp(suffix, ANGLE_SUFFIX_VALUE) == 0;
505     const std::string absolutePath =
506             findLibrary(libraryName, isSuffixAngle ? SYSTEM_LIB_PATH : VENDOR_LIB_EGL_DIR, exact);
507     if (absolutePath.empty()) {
508         // this happens often, we don't want to log an error
509         return nullptr;
510     }
511     const char* const driverAbsolutePath = absolutePath.c_str();
512 
513     // Currently the default driver is unlikely to be ANGLE on most devices,
514     // hence put this first. Only use sphal namespace when system ANGLE binaries
515     // are not the default drivers.
516     if (!isSuffixAngle) {
517         // Try to load drivers from the 'sphal' namespace, if it exist. Fall back to
518         // the original routine when the namespace does not exist.
519         // See /system/linkerconfig/contents/namespace for the configuration of the
520         // sphal namespace.
521         dso = do_android_load_sphal_library(driverAbsolutePath, RTLD_NOW | RTLD_LOCAL);
522     } else {
523         // Try to load drivers from the default namespace.
524         // See /system/linkerconfig/contents/namespace for the configuration of the
525         // default namespace.
526         dso = do_dlopen(driverAbsolutePath, RTLD_NOW | RTLD_LOCAL);
527     }
528 
529     if (dso == nullptr) {
530         const char* err = dlerror();
531         ALOGE("load_driver(%s): %s", driverAbsolutePath, err ? err : "unknown");
532         return nullptr;
533     }
534 
535     ALOGV("loaded %s", driverAbsolutePath);
536 
537     return dso;
538 }
539 
load_angle(const char * kind,android_namespace_t * ns)540 static void* load_angle(const char* kind, android_namespace_t* ns) {
541     std::string name = std::string("lib") + kind + "_angle.so";
542     void* so = nullptr;
543 
544     if (android::GraphicsEnv::getInstance().shouldUseSystemAngle()) {
545         so = do_dlopen(name.c_str(), RTLD_NOW | RTLD_LOCAL);
546     } else {
547         const android_dlextinfo dlextinfo = {
548                 .flags = ANDROID_DLEXT_USE_NAMESPACE,
549                 .library_namespace = ns,
550         };
551         so = do_android_dlopen_ext(name.c_str(), RTLD_LOCAL | RTLD_NOW, &dlextinfo);
552     }
553 
554     if (so) {
555         return so;
556     } else {
557         ALOGE("dlopen_ext(\"%s\") failed: %s", name.c_str(), dlerror());
558     }
559 
560     return nullptr;
561 }
562 
load_updated_driver(const char * kind,android_namespace_t * ns)563 static void* load_updated_driver(const char* kind, android_namespace_t* ns) {
564     ATRACE_CALL();
565     const android_dlextinfo dlextinfo = {
566         .flags = ANDROID_DLEXT_USE_NAMESPACE,
567         .library_namespace = ns,
568     };
569     void* so = nullptr;
570     for (auto key : HAL_SUBNAME_KEY_PROPERTIES) {
571         auto prop = base::GetProperty(key, "");
572         if (prop.empty()) {
573             continue;
574         }
575         std::string name = std::string("lib") + kind + "_" + prop + ".so";
576         so = do_android_dlopen_ext(name.c_str(), RTLD_LOCAL | RTLD_NOW, &dlextinfo);
577         if (so) {
578             return so;
579         }
580         ALOGE("Could not load %s from updatable gfx driver namespace: %s.", name.c_str(),
581               dlerror());
582     }
583     return nullptr;
584 }
585 
attempt_to_load_angle(egl_connection_t * cnx)586 Loader::driver_t* Loader::attempt_to_load_angle(egl_connection_t* cnx) {
587     ATRACE_CALL();
588 
589     android_namespace_t* ns = android::GraphicsEnv::getInstance().getAngleNamespace();
590     // ANGLE namespace is used for loading ANGLE from apk, and hence if namespace is not
591     // constructed, it means ANGLE apk is not set to be the OpenGL ES driver.
592     // Hence skip if ANGLE apk and system ANGLE are not set to be the OpenGL ES driver.
593     if (!ns && !android::GraphicsEnv::getInstance().shouldUseSystemAngle()) {
594         return nullptr;
595     }
596 
597     // use ANGLE APK driver
598     android::GraphicsEnv::getInstance().setDriverToLoad(android::GpuStatsInfo::Driver::ANGLE);
599     driver_t* hnd = nullptr;
600 
601     // ANGLE doesn't ship with GLES library, and thus we skip GLES driver.
602     void* dso = load_angle("EGL", ns);
603     if (dso) {
604         initialize_api(dso, cnx, EGL);
605         hnd = new driver_t(dso);
606 
607         dso = load_angle("GLESv1_CM", ns);
608         initialize_api(dso, cnx, GLESv1_CM);
609         hnd->set(dso, GLESv1_CM);
610 
611         dso = load_angle("GLESv2", ns);
612         initialize_api(dso, cnx, GLESv2);
613         hnd->set(dso, GLESv2);
614     }
615     return hnd;
616 }
617 
attempt_to_init_angle_backend(void * dso,egl_connection_t * cnx)618 void Loader::attempt_to_init_angle_backend(void* dso, egl_connection_t* cnx) {
619     cnx->angleGetDisplayPlatformFunc = dlsym(dso, "ANGLEGetDisplayPlatform");
620     cnx->angleResetDisplayPlatformFunc = dlsym(dso, "ANGLEResetDisplayPlatform");
621 
622     if (cnx->angleGetDisplayPlatformFunc) {
623         ALOGV("ANGLE GLES library loaded");
624         cnx->angleLoaded = true;
625         android::GraphicsEnv::getInstance().setDriverToLoad(android::GpuStatsInfo::Driver::ANGLE);
626     } else {
627         ALOGV("Native GLES library loaded");
628         cnx->angleLoaded = false;
629     }
630 }
631 
attempt_to_load_updated_driver(egl_connection_t * cnx)632 Loader::driver_t* Loader::attempt_to_load_updated_driver(egl_connection_t* cnx) {
633     ATRACE_CALL();
634 
635     android_namespace_t* ns = android::GraphicsEnv::getInstance().getDriverNamespace();
636     if (!ns) {
637         return nullptr;
638     }
639 
640     ALOGD("Load updated gl driver.");
641     android::GraphicsEnv::getInstance().setDriverToLoad(android::GpuStatsInfo::Driver::GL_UPDATED);
642     driver_t* hnd = nullptr;
643     void* dso = load_updated_driver("GLES", ns);
644     if (dso) {
645         initialize_api(dso, cnx, EGL | GLESv1_CM | GLESv2);
646         hnd = new driver_t(dso);
647         return hnd;
648     }
649 
650     dso = load_updated_driver("EGL", ns);
651     if (dso) {
652         initialize_api(dso, cnx, EGL);
653         hnd = new driver_t(dso);
654 
655         dso = load_updated_driver("GLESv1_CM", ns);
656         initialize_api(dso, cnx, GLESv1_CM);
657         hnd->set(dso, GLESv1_CM);
658 
659         dso = load_updated_driver("GLESv2", ns);
660         initialize_api(dso, cnx, GLESv2);
661         hnd->set(dso, GLESv2);
662     }
663     return hnd;
664 }
665 
attempt_to_load_system_driver(egl_connection_t * cnx,const char * suffix,const bool exact)666 Loader::driver_t* Loader::attempt_to_load_system_driver(egl_connection_t* cnx, const char* suffix,
667                                                         const bool exact) {
668     ATRACE_CALL();
669     if (suffix && strcmp(suffix, "angle") == 0) {
670         // use system ANGLE driver
671         android::GraphicsEnv::getInstance().setDriverToLoad(android::GpuStatsInfo::Driver::ANGLE);
672     } else {
673         android::GraphicsEnv::getInstance().setDriverToLoad(android::GpuStatsInfo::Driver::GL);
674     }
675 
676     driver_t* hnd = nullptr;
677     void* dso = load_system_driver("GLES", suffix, exact);
678     if (dso) {
679         initialize_api(dso, cnx, EGL | GLESv1_CM | GLESv2);
680         hnd = new driver_t(dso);
681         return hnd;
682     }
683     dso = load_system_driver("EGL", suffix, exact);
684     if (dso) {
685         initialize_api(dso, cnx, EGL);
686         hnd = new driver_t(dso);
687 
688         dso = load_system_driver("GLESv1_CM", suffix, exact);
689         initialize_api(dso, cnx, GLESv1_CM);
690         hnd->set(dso, GLESv1_CM);
691 
692         dso = load_system_driver("GLESv2", suffix, exact);
693         initialize_api(dso, cnx, GLESv2);
694         hnd->set(dso, GLESv2);
695     }
696     return hnd;
697 }
698 
initialize_api(void * dso,egl_connection_t * cnx,uint32_t mask)699 void Loader::initialize_api(void* dso, egl_connection_t* cnx, uint32_t mask) {
700     if (mask & EGL) {
701         getProcAddress = (getProcAddressType)dlsym(dso, "eglGetProcAddress");
702 
703         ALOGE_IF(!getProcAddress,
704                 "can't find eglGetProcAddress() in EGL driver library");
705 
706         egl_t* egl = &cnx->egl;
707         __eglMustCastToProperFunctionPointerType* curr =
708             (__eglMustCastToProperFunctionPointerType*)egl;
709         char const * const * api = egl_names;
710         while (*api) {
711             char const * name = *api;
712             __eglMustCastToProperFunctionPointerType f =
713                 (__eglMustCastToProperFunctionPointerType)dlsym(dso, name);
714             if (f == nullptr) {
715                 // couldn't find the entry-point, use eglGetProcAddress()
716                 f = getProcAddress(name);
717                 if (f == nullptr) {
718                     f = (__eglMustCastToProperFunctionPointerType)nullptr;
719                 }
720             }
721             *curr++ = f;
722             api++;
723         }
724     }
725 
726     if (mask & GLESv1_CM) {
727         init_api(dso, gl_names_1, gl_names,
728             (__eglMustCastToProperFunctionPointerType*)
729                 &cnx->hooks[egl_connection_t::GLESv1_INDEX]->gl,
730             getProcAddress);
731     }
732 
733     if (mask & GLESv2) {
734         init_api(dso, gl_names, nullptr,
735             (__eglMustCastToProperFunctionPointerType*)
736                 &cnx->hooks[egl_connection_t::GLESv2_INDEX]->gl,
737             getProcAddress);
738     }
739 }
740 
741 } // namespace android
742