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