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