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 "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
31#ifndef __ANDROID_VNDK__
32#include <graphicsenv/GraphicsEnv.h>
33#endif
34#include <vndksupport/linker.h>
35
36#include "egl_trace.h"
37#include "egldefs.h"
38
39extern "C" {
40  android_namespace_t* android_get_exported_namespace(const char*);
41}
42
43// ----------------------------------------------------------------------------
44namespace android {
45// ----------------------------------------------------------------------------
46
47
48/*
49 * EGL userspace drivers must be provided either:
50 * - as a single library:
51 *      /vendor/lib/egl/libGLES.so
52 *
53 * - as separate libraries:
54 *      /vendor/lib/egl/libEGL.so
55 *      /vendor/lib/egl/libGLESv1_CM.so
56 *      /vendor/lib/egl/libGLESv2.so
57 *
58 * The software renderer for the emulator must be provided as a single
59 * library at:
60 *
61 *      /system/lib/egl/libGLES_android.so
62 *
63 *
64 * For backward compatibility and to facilitate the transition to
65 * this new naming scheme, the loader will additionally look for:
66 *
67 *      /{vendor|system}/lib/egl/lib{GLES | [EGL|GLESv1_CM|GLESv2]}_*.so
68 *
69 */
70
71Loader& Loader::getInstance() {
72    static Loader loader;
73    return loader;
74}
75
76/* This function is called to check whether we run inside the emulator,
77 * and if this is the case whether GLES GPU emulation is supported.
78 *
79 * Returned values are:
80 *  -1   -> not running inside the emulator
81 *   0   -> running inside the emulator, but GPU emulation not supported
82 *   1   -> running inside the emulator, GPU emulation is supported
83 *          through the "emulation" host-side OpenGL ES implementation.
84 *   2   -> running inside the emulator, GPU emulation is supported
85 *          through a guest-side vendor driver's OpenGL ES implementation.
86 */
87static int
88checkGlesEmulationStatus(void)
89{
90    /* We're going to check for the following kernel parameters:
91     *
92     *    qemu=1                      -> tells us that we run inside the emulator
93     *    android.qemu.gles=<number>  -> tells us the GLES GPU emulation status
94     *
95     * Note that we will return <number> if we find it. This let us support
96     * more additionnal emulation modes in the future.
97     */
98    char  prop[PROPERTY_VALUE_MAX];
99    int   result = -1;
100
101    /* First, check for qemu=1 */
102    property_get("ro.kernel.qemu",prop,"0");
103    if (atoi(prop) != 1)
104        return -1;
105
106    /* We are in the emulator, get GPU status value */
107    property_get("qemu.gles",prop,"0");
108    return atoi(prop);
109}
110
111static void* do_dlopen(const char* path, int mode) {
112    ATRACE_CALL();
113    return dlopen(path, mode);
114}
115
116static void* do_android_dlopen_ext(const char* path, int mode, const android_dlextinfo* info) {
117    ATRACE_CALL();
118    return android_dlopen_ext(path, mode, info);
119}
120
121static void* do_android_load_sphal_library(const char* path, int mode) {
122    ATRACE_CALL();
123    return android_load_sphal_library(path, mode);
124}
125
126// ----------------------------------------------------------------------------
127
128Loader::driver_t::driver_t(void* gles)
129{
130    dso[0] = gles;
131    for (size_t i=1 ; i<NELEM(dso) ; i++)
132        dso[i] = 0;
133}
134
135Loader::driver_t::~driver_t()
136{
137    for (size_t i=0 ; i<NELEM(dso) ; i++) {
138        if (dso[i]) {
139            dlclose(dso[i]);
140            dso[i] = 0;
141        }
142    }
143}
144
145int Loader::driver_t::set(void* hnd, int32_t api)
146{
147    switch (api) {
148        case EGL:
149            dso[0] = hnd;
150            break;
151        case GLESv1_CM:
152            dso[1] = hnd;
153            break;
154        case GLESv2:
155            dso[2] = hnd;
156            break;
157        default:
158            return -EOVERFLOW;
159    }
160    return 0;
161}
162
163// ----------------------------------------------------------------------------
164
165Loader::Loader()
166    : getProcAddress(NULL)
167{
168}
169
170Loader::~Loader() {
171}
172
173static void* load_wrapper(const char* path) {
174    void* so = do_dlopen(path, RTLD_NOW | RTLD_LOCAL);
175    ALOGE_IF(!so, "dlopen(\"%s\") failed: %s", path, dlerror());
176    return so;
177}
178
179#ifndef EGL_WRAPPER_DIR
180#if defined(__LP64__)
181#define EGL_WRAPPER_DIR "/system/lib64"
182#else
183#define EGL_WRAPPER_DIR "/system/lib"
184#endif
185#endif
186
187static void setEmulatorGlesValue(void) {
188    char prop[PROPERTY_VALUE_MAX];
189    property_get("ro.kernel.qemu", prop, "0");
190    if (atoi(prop) != 1) return;
191
192    property_get("ro.kernel.qemu.gles",prop,"0");
193    if (atoi(prop) == 1) {
194        ALOGD("Emulator has host GPU support, qemu.gles is set to 1.");
195        property_set("qemu.gles", "1");
196        return;
197    }
198
199    // for now, checking the following
200    // directory is good enough for emulator system images
201    const char* vendor_lib_path =
202#if defined(__LP64__)
203        "/vendor/lib64/egl";
204#else
205        "/vendor/lib/egl";
206#endif
207
208    const bool has_vendor_lib = (access(vendor_lib_path, R_OK) == 0);
209    if (has_vendor_lib) {
210        ALOGD("Emulator has vendor provided software renderer, qemu.gles is set to 2.");
211        property_set("qemu.gles", "2");
212    } else {
213        ALOGD("Emulator without GPU support detected. "
214              "Fallback to legacy software renderer, qemu.gles is set to 0.");
215        property_set("qemu.gles", "0");
216    }
217}
218
219void* Loader::open(egl_connection_t* cnx)
220{
221    ATRACE_CALL();
222
223    void* dso;
224    driver_t* hnd = 0;
225
226    setEmulatorGlesValue();
227
228    dso = load_driver("GLES", cnx, EGL | GLESv1_CM | GLESv2);
229    if (dso) {
230        hnd = new driver_t(dso);
231    } else {
232        // Always load EGL first
233        dso = load_driver("EGL", cnx, EGL);
234        if (dso) {
235            hnd = new driver_t(dso);
236            hnd->set( load_driver("GLESv1_CM", cnx, GLESv1_CM), GLESv1_CM );
237            hnd->set( load_driver("GLESv2",    cnx, GLESv2),    GLESv2 );
238        }
239    }
240
241    LOG_ALWAYS_FATAL_IF(!hnd, "couldn't find an OpenGL ES implementation");
242
243    cnx->libEgl   = load_wrapper(EGL_WRAPPER_DIR "/libEGL.so");
244    cnx->libGles2 = load_wrapper(EGL_WRAPPER_DIR "/libGLESv2.so");
245    cnx->libGles1 = load_wrapper(EGL_WRAPPER_DIR "/libGLESv1_CM.so");
246
247    LOG_ALWAYS_FATAL_IF(!cnx->libEgl,
248            "couldn't load system EGL wrapper libraries");
249
250    LOG_ALWAYS_FATAL_IF(!cnx->libGles2 || !cnx->libGles1,
251            "couldn't load system OpenGL ES wrapper libraries");
252
253    return (void*)hnd;
254}
255
256void Loader::close(void* driver)
257{
258    driver_t* hnd = (driver_t*)driver;
259    delete hnd;
260}
261
262void Loader::init_api(void* dso,
263        char const * const * api,
264        __eglMustCastToProperFunctionPointerType* curr,
265        getProcAddressType getProcAddress)
266{
267    ATRACE_CALL();
268
269    const ssize_t SIZE = 256;
270    char scrap[SIZE];
271    while (*api) {
272        char const * name = *api;
273        __eglMustCastToProperFunctionPointerType f =
274            (__eglMustCastToProperFunctionPointerType)dlsym(dso, name);
275        if (f == NULL) {
276            // couldn't find the entry-point, use eglGetProcAddress()
277            f = getProcAddress(name);
278        }
279        if (f == NULL) {
280            // Try without the OES postfix
281            ssize_t index = ssize_t(strlen(name)) - 3;
282            if ((index>0 && (index<SIZE-1)) && (!strcmp(name+index, "OES"))) {
283                strncpy(scrap, name, index);
284                scrap[index] = 0;
285                f = (__eglMustCastToProperFunctionPointerType)dlsym(dso, scrap);
286                //ALOGD_IF(f, "found <%s> instead", scrap);
287            }
288        }
289        if (f == NULL) {
290            // Try with the OES postfix
291            ssize_t index = ssize_t(strlen(name)) - 3;
292            if (index>0 && strcmp(name+index, "OES")) {
293                snprintf(scrap, SIZE, "%sOES", name);
294                f = (__eglMustCastToProperFunctionPointerType)dlsym(dso, scrap);
295                //ALOGD_IF(f, "found <%s> instead", scrap);
296            }
297        }
298        if (f == NULL) {
299            //ALOGD("%s", name);
300            f = (__eglMustCastToProperFunctionPointerType)gl_unimplemented;
301
302            /*
303             * GL_EXT_debug_label is special, we always report it as
304             * supported, it's handled by GLES_trace. If GLES_trace is not
305             * enabled, then these are no-ops.
306             */
307            if (!strcmp(name, "glInsertEventMarkerEXT")) {
308                f = (__eglMustCastToProperFunctionPointerType)gl_noop;
309            } else if (!strcmp(name, "glPushGroupMarkerEXT")) {
310                f = (__eglMustCastToProperFunctionPointerType)gl_noop;
311            } else if (!strcmp(name, "glPopGroupMarkerEXT")) {
312                f = (__eglMustCastToProperFunctionPointerType)gl_noop;
313            }
314        }
315        *curr++ = f;
316        api++;
317    }
318}
319
320static void* load_system_driver(const char* kind) {
321    ATRACE_CALL();
322    class MatchFile {
323    public:
324        static std::string find(const char* kind) {
325            std::string result;
326            int emulationStatus = checkGlesEmulationStatus();
327            switch (emulationStatus) {
328                case 0:
329#if defined(__LP64__)
330                    result = "/vendor/lib64/egl/libGLES_android.so";
331#else
332                    result = "/vendor/lib/egl/libGLES_android.so";
333#endif
334                    return result;
335                case 1:
336                    // Use host-side OpenGL through the "emulation" library
337#if defined(__LP64__)
338                    result = std::string("/vendor/lib64/egl/lib") + kind + "_emulation.so";
339#else
340                    result = std::string("/vendor/lib/egl/lib") + kind + "_emulation.so";
341#endif
342                    return result;
343                case 2:
344                    // Use guest side swiftshader library
345#if defined(__LP64__)
346                    result = std::string("/vendor/lib64/egl/lib") + kind + "_swiftshader.so";
347#else
348                    result = std::string("/vendor/lib/egl/lib") + kind + "_swiftshader.so";
349#endif
350                    return result;
351                default:
352                    // Not in emulator, or use other guest-side implementation
353                    break;
354            }
355
356            std::string pattern = std::string("lib") + kind;
357            const char* const searchPaths[] = {
358#if defined(__LP64__)
359                    "/vendor/lib64/egl",
360                    "/system/lib64/egl"
361#else
362                    "/vendor/lib/egl",
363                    "/system/lib/egl"
364#endif
365            };
366
367            // first, we search for the exact name of the GLES userspace
368            // driver in both locations.
369            // i.e.:
370            //      libGLES.so, or:
371            //      libEGL.so, libGLESv1_CM.so, libGLESv2.so
372
373            for (size_t i=0 ; i<NELEM(searchPaths) ; i++) {
374                if (find(result, pattern, searchPaths[i], true)) {
375                    return result;
376                }
377            }
378
379            // for compatibility with the old "egl.cfg" naming convention
380            // we look for files that match:
381            //      libGLES_*.so, or:
382            //      libEGL_*.so, libGLESv1_CM_*.so, libGLESv2_*.so
383
384            pattern.append("_");
385            for (size_t i=0 ; i<NELEM(searchPaths) ; i++) {
386                if (find(result, pattern, searchPaths[i], false)) {
387                    return result;
388                }
389            }
390
391            // we didn't find the driver. gah.
392            result.clear();
393            return result;
394        }
395
396    private:
397        static bool find(std::string& result,
398                const std::string& pattern, const char* const search, bool exact) {
399            if (exact) {
400                std::string absolutePath = std::string(search) + "/" + pattern + ".so";
401                if (!access(absolutePath.c_str(), R_OK)) {
402                    result = absolutePath;
403                    return true;
404                }
405                return false;
406            }
407
408            DIR* d = opendir(search);
409            if (d != NULL) {
410                struct dirent* e;
411                while ((e = readdir(d)) != NULL) {
412                    if (e->d_type == DT_DIR) {
413                        continue;
414                    }
415                    if (!strcmp(e->d_name, "libGLES_android.so")) {
416                        // always skip the software renderer
417                        continue;
418                    }
419                    if (strstr(e->d_name, pattern.c_str()) == e->d_name) {
420                        if (!strcmp(e->d_name + strlen(e->d_name) - 3, ".so")) {
421                            result = std::string(search) + "/" + e->d_name;
422                            closedir(d);
423                            return true;
424                        }
425                    }
426                }
427                closedir(d);
428            }
429            return false;
430        }
431    };
432
433
434    std::string absolutePath = MatchFile::find(kind);
435    if (absolutePath.empty()) {
436        // this happens often, we don't want to log an error
437        return 0;
438    }
439    const char* const driver_absolute_path = absolutePath.c_str();
440
441    // Try to load drivers from the 'sphal' namespace, if it exist. Fall back to
442    // the original routine when the namespace does not exist.
443    // See /system/core/rootdir/etc/ld.config.txt for the configuration of the
444    // sphal namespace.
445    void* dso = do_android_load_sphal_library(driver_absolute_path,
446                                              RTLD_NOW | RTLD_LOCAL);
447    if (dso == 0) {
448        const char* err = dlerror();
449        ALOGE("load_driver(%s): %s", driver_absolute_path, err ? err : "unknown");
450        return 0;
451    }
452
453    ALOGD("loaded %s", driver_absolute_path);
454
455    return dso;
456}
457
458static const char* HAL_SUBNAME_KEY_PROPERTIES[2] = {
459    "ro.hardware.egl",
460    "ro.board.platform",
461};
462
463static void* load_updated_driver(const char* kind, android_namespace_t* ns) {
464    ATRACE_CALL();
465    const android_dlextinfo dlextinfo = {
466        .flags = ANDROID_DLEXT_USE_NAMESPACE,
467        .library_namespace = ns,
468    };
469    void* so = nullptr;
470    char prop[PROPERTY_VALUE_MAX + 1];
471    for (auto key : HAL_SUBNAME_KEY_PROPERTIES) {
472        if (property_get(key, prop, nullptr) > 0) {
473            std::string name = std::string("lib") + kind + "_" + prop + ".so";
474            so = do_android_dlopen_ext(name.c_str(), RTLD_LOCAL | RTLD_NOW, &dlextinfo);
475            if (so) {
476                return so;
477            }
478        }
479    }
480    return nullptr;
481}
482
483void *Loader::load_driver(const char* kind,
484        egl_connection_t* cnx, uint32_t mask)
485{
486    ATRACE_CALL();
487
488    void* dso = nullptr;
489#ifndef __ANDROID_VNDK__
490    android_namespace_t* ns = android_getDriverNamespace();
491    if (ns) {
492        dso = load_updated_driver(kind, ns);
493    }
494#endif
495    if (!dso) {
496        dso = load_system_driver(kind);
497        if (!dso)
498            return NULL;
499    }
500
501    if (mask & EGL) {
502        getProcAddress = (getProcAddressType)dlsym(dso, "eglGetProcAddress");
503
504        ALOGE_IF(!getProcAddress,
505                "can't find eglGetProcAddress() in EGL driver library");
506
507        egl_t* egl = &cnx->egl;
508        __eglMustCastToProperFunctionPointerType* curr =
509            (__eglMustCastToProperFunctionPointerType*)egl;
510        char const * const * api = egl_names;
511        while (*api) {
512            char const * name = *api;
513            __eglMustCastToProperFunctionPointerType f =
514                (__eglMustCastToProperFunctionPointerType)dlsym(dso, name);
515            if (f == NULL) {
516                // couldn't find the entry-point, use eglGetProcAddress()
517                f = getProcAddress(name);
518                if (f == NULL) {
519                    f = (__eglMustCastToProperFunctionPointerType)0;
520                }
521            }
522            *curr++ = f;
523            api++;
524        }
525    }
526
527    if (mask & GLESv1_CM) {
528        init_api(dso, gl_names,
529            (__eglMustCastToProperFunctionPointerType*)
530                &cnx->hooks[egl_connection_t::GLESv1_INDEX]->gl,
531            getProcAddress);
532    }
533
534    if (mask & GLESv2) {
535      init_api(dso, gl_names,
536            (__eglMustCastToProperFunctionPointerType*)
537                &cnx->hooks[egl_connection_t::GLESv2_INDEX]->gl,
538            getProcAddress);
539    }
540
541    return dso;
542}
543
544// ----------------------------------------------------------------------------
545}; // namespace android
546// ----------------------------------------------------------------------------
547