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