194cdba97ce1de140623d84c14fb15f12f7da89ddJesse Hall/*
2de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian ** Copyright 2007, The Android Open Source Project
3de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian **
494cdba97ce1de140623d84c14fb15f12f7da89ddJesse Hall ** Licensed under the Apache License, Version 2.0 (the "License");
594cdba97ce1de140623d84c14fb15f12f7da89ddJesse Hall ** you may not use this file except in compliance with the License.
694cdba97ce1de140623d84c14fb15f12f7da89ddJesse Hall ** You may obtain a copy of the License at
7de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian **
894cdba97ce1de140623d84c14fb15f12f7da89ddJesse Hall **     http://www.apache.org/licenses/LICENSE-2.0
9de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian **
1094cdba97ce1de140623d84c14fb15f12f7da89ddJesse Hall ** Unless required by applicable law or agreed to in writing, software
1194cdba97ce1de140623d84c14fb15f12f7da89ddJesse Hall ** distributed under the License is distributed on an "AS IS" BASIS,
1294cdba97ce1de140623d84c14fb15f12f7da89ddJesse Hall ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1394cdba97ce1de140623d84c14fb15f12f7da89ddJesse Hall ** See the License for the specific language governing permissions and
14de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian ** limitations under the License.
15de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian */
16de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian
17a91f64cbe1bc057a466a865446767ffd48133a8fJesse Hall//#define LOG_NDEBUG 0
18bb5a921fef0445f1ffa4fe0781cd1b8108ad79ceJesse Hall#define ATRACE_TAG ATRACE_TAG_GRAPHICS
19a91f64cbe1bc057a466a865446767ffd48133a8fJesse Hall
20a91f64cbe1bc057a466a865446767ffd48133a8fJesse Hall#include <array>
21de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian#include <ctype.h>
22de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian#include <stdlib.h>
23de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian#include <stdio.h>
24de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian#include <string.h>
25de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian#include <errno.h>
26de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian#include <dlfcn.h>
27de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian#include <limits.h>
28993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian#include <dirent.h>
29de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian
30a91f64cbe1bc057a466a865446767ffd48133a8fJesse Hall#include <android/dlext.h>
31de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian#include <cutils/log.h>
3280b30c24ffc0f67b87d7a6b29f616d1c521d40aeDavid 'Digit' Turner#include <cutils/properties.h>
33bb5a921fef0445f1ffa4fe0781cd1b8108ad79ceJesse Hall#include <utils/Trace.h>
34de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian
35de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian#include <EGL/egl.h>
36de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian
371cadb25da1ed875bdd078270e642966724a0c39aMathias Agopian#include "egldefs.h"
38de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian#include "Loader.h"
39de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian
40de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian// ----------------------------------------------------------------------------
41de58697644a52a614ad9498aa087e95d4a223673Mathias Agopiannamespace android {
42de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian// ----------------------------------------------------------------------------
43de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian
44de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian
45de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian/*
46993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian * EGL userspace drivers must be provided either:
47993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian * - as a single library:
48993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian *      /vendor/lib/egl/libGLES.so
49993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian *
50993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian * - as separate libraries:
51993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian *      /vendor/lib/egl/libEGL.so
52993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian *      /vendor/lib/egl/libGLESv1_CM.so
53993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian *      /vendor/lib/egl/libGLESv2.so
54993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian *
55993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian * The software renderer for the emulator must be provided as a single
56993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian * library at:
57993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian *
58993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian *      /system/lib/egl/libGLES_android.so
59993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian *
60993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian *
61993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian * For backward compatibility and to facilitate the transition to
62993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian * this new naming scheme, the loader will additionally look for:
6394cdba97ce1de140623d84c14fb15f12f7da89ddJesse Hall *
64993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian *      /{vendor|system}/lib/egl/lib{GLES | [EGL|GLESv1_CM|GLESv2]}_*.so
6594cdba97ce1de140623d84c14fb15f12f7da89ddJesse Hall *
66de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian */
67de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian
68de58697644a52a614ad9498aa087e95d4a223673Mathias AgopianANDROID_SINGLETON_STATIC_INSTANCE( Loader )
69de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian
7080b30c24ffc0f67b87d7a6b29f616d1c521d40aeDavid 'Digit' Turner/* This function is called to check whether we run inside the emulator,
7180b30c24ffc0f67b87d7a6b29f616d1c521d40aeDavid 'Digit' Turner * and if this is the case whether GLES GPU emulation is supported.
7280b30c24ffc0f67b87d7a6b29f616d1c521d40aeDavid 'Digit' Turner *
7380b30c24ffc0f67b87d7a6b29f616d1c521d40aeDavid 'Digit' Turner * Returned values are:
7480b30c24ffc0f67b87d7a6b29f616d1c521d40aeDavid 'Digit' Turner *  -1   -> not running inside the emulator
7580b30c24ffc0f67b87d7a6b29f616d1c521d40aeDavid 'Digit' Turner *   0   -> running inside the emulator, but GPU emulation not supported
7680b30c24ffc0f67b87d7a6b29f616d1c521d40aeDavid 'Digit' Turner *   1   -> running inside the emulator, GPU emulation is supported
77776951f9db5744c94167d463584e9ee42c849712Nicolas Capens *          through the "emulation" host-side OpenGL ES implementation.
78776951f9db5744c94167d463584e9ee42c849712Nicolas Capens *   2   -> running inside the emulator, GPU emulation is supported
79776951f9db5744c94167d463584e9ee42c849712Nicolas Capens *          through a guest-side vendor driver's OpenGL ES implementation.
8080b30c24ffc0f67b87d7a6b29f616d1c521d40aeDavid 'Digit' Turner */
8180b30c24ffc0f67b87d7a6b29f616d1c521d40aeDavid 'Digit' Turnerstatic int
8280b30c24ffc0f67b87d7a6b29f616d1c521d40aeDavid 'Digit' TurnercheckGlesEmulationStatus(void)
8380b30c24ffc0f67b87d7a6b29f616d1c521d40aeDavid 'Digit' Turner{
8480b30c24ffc0f67b87d7a6b29f616d1c521d40aeDavid 'Digit' Turner    /* We're going to check for the following kernel parameters:
8580b30c24ffc0f67b87d7a6b29f616d1c521d40aeDavid 'Digit' Turner     *
8680b30c24ffc0f67b87d7a6b29f616d1c521d40aeDavid 'Digit' Turner     *    qemu=1                      -> tells us that we run inside the emulator
8780b30c24ffc0f67b87d7a6b29f616d1c521d40aeDavid 'Digit' Turner     *    android.qemu.gles=<number>  -> tells us the GLES GPU emulation status
8880b30c24ffc0f67b87d7a6b29f616d1c521d40aeDavid 'Digit' Turner     *
8980b30c24ffc0f67b87d7a6b29f616d1c521d40aeDavid 'Digit' Turner     * Note that we will return <number> if we find it. This let us support
9080b30c24ffc0f67b87d7a6b29f616d1c521d40aeDavid 'Digit' Turner     * more additionnal emulation modes in the future.
9180b30c24ffc0f67b87d7a6b29f616d1c521d40aeDavid 'Digit' Turner     */
9280b30c24ffc0f67b87d7a6b29f616d1c521d40aeDavid 'Digit' Turner    char  prop[PROPERTY_VALUE_MAX];
9380b30c24ffc0f67b87d7a6b29f616d1c521d40aeDavid 'Digit' Turner    int   result = -1;
9480b30c24ffc0f67b87d7a6b29f616d1c521d40aeDavid 'Digit' Turner
9580b30c24ffc0f67b87d7a6b29f616d1c521d40aeDavid 'Digit' Turner    /* First, check for qemu=1 */
9680b30c24ffc0f67b87d7a6b29f616d1c521d40aeDavid 'Digit' Turner    property_get("ro.kernel.qemu",prop,"0");
9780b30c24ffc0f67b87d7a6b29f616d1c521d40aeDavid 'Digit' Turner    if (atoi(prop) != 1)
9880b30c24ffc0f67b87d7a6b29f616d1c521d40aeDavid 'Digit' Turner        return -1;
9980b30c24ffc0f67b87d7a6b29f616d1c521d40aeDavid 'Digit' Turner
10080b30c24ffc0f67b87d7a6b29f616d1c521d40aeDavid 'Digit' Turner    /* We are in the emulator, get GPU status value */
10169e5b1ab80018817b1d4ffbbdb5695ff70168c95bohu    property_get("qemu.gles",prop,"0");
10280b30c24ffc0f67b87d7a6b29f616d1c521d40aeDavid 'Digit' Turner    return atoi(prop);
10380b30c24ffc0f67b87d7a6b29f616d1c521d40aeDavid 'Digit' Turner}
10480b30c24ffc0f67b87d7a6b29f616d1c521d40aeDavid 'Digit' Turner
105de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian// ----------------------------------------------------------------------------
106de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian
107d75f84d6410da934d1b1760fdc0d05d4ba1e8f35Mathias Agopianstatic char const * getProcessCmdline() {
108d75f84d6410da934d1b1760fdc0d05d4ba1e8f35Mathias Agopian    long pid = getpid();
109d75f84d6410da934d1b1760fdc0d05d4ba1e8f35Mathias Agopian    char procPath[128];
110d75f84d6410da934d1b1760fdc0d05d4ba1e8f35Mathias Agopian    snprintf(procPath, 128, "/proc/%ld/cmdline", pid);
111d75f84d6410da934d1b1760fdc0d05d4ba1e8f35Mathias Agopian    FILE * file = fopen(procPath, "r");
112d75f84d6410da934d1b1760fdc0d05d4ba1e8f35Mathias Agopian    if (file) {
113d75f84d6410da934d1b1760fdc0d05d4ba1e8f35Mathias Agopian        static char cmdline[256];
114d75f84d6410da934d1b1760fdc0d05d4ba1e8f35Mathias Agopian        char *str = fgets(cmdline, sizeof(cmdline) - 1, file);
115d75f84d6410da934d1b1760fdc0d05d4ba1e8f35Mathias Agopian        fclose(file);
116d75f84d6410da934d1b1760fdc0d05d4ba1e8f35Mathias Agopian        if (str) {
117d75f84d6410da934d1b1760fdc0d05d4ba1e8f35Mathias Agopian            return cmdline;
118d75f84d6410da934d1b1760fdc0d05d4ba1e8f35Mathias Agopian        }
119d75f84d6410da934d1b1760fdc0d05d4ba1e8f35Mathias Agopian    }
120d75f84d6410da934d1b1760fdc0d05d4ba1e8f35Mathias Agopian    return NULL;
121d75f84d6410da934d1b1760fdc0d05d4ba1e8f35Mathias Agopian}
122d75f84d6410da934d1b1760fdc0d05d4ba1e8f35Mathias Agopian
123bb5a921fef0445f1ffa4fe0781cd1b8108ad79ceJesse Hallstatic void* do_dlopen(const char* path, int mode) {
124bb5a921fef0445f1ffa4fe0781cd1b8108ad79ceJesse Hall    ATRACE_CALL();
125bb5a921fef0445f1ffa4fe0781cd1b8108ad79ceJesse Hall    return dlopen(path, mode);
126bb5a921fef0445f1ffa4fe0781cd1b8108ad79ceJesse Hall}
127bb5a921fef0445f1ffa4fe0781cd1b8108ad79ceJesse Hall
128d75f84d6410da934d1b1760fdc0d05d4ba1e8f35Mathias Agopian// ----------------------------------------------------------------------------
129d75f84d6410da934d1b1760fdc0d05d4ba1e8f35Mathias Agopian
13094cdba97ce1de140623d84c14fb15f12f7da89ddJesse HallLoader::driver_t::driver_t(void* gles)
131de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian{
132de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian    dso[0] = gles;
133de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian    for (size_t i=1 ; i<NELEM(dso) ; i++)
134de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian        dso[i] = 0;
135de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian}
136de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian
13794cdba97ce1de140623d84c14fb15f12f7da89ddJesse HallLoader::driver_t::~driver_t()
138de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian{
139de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian    for (size_t i=0 ; i<NELEM(dso) ; i++) {
140de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian        if (dso[i]) {
141de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian            dlclose(dso[i]);
142de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian            dso[i] = 0;
143de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian        }
144de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian    }
145de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian}
146de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian
147de58697644a52a614ad9498aa087e95d4a223673Mathias Agopianstatus_t Loader::driver_t::set(void* hnd, int32_t api)
148de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian{
149de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian    switch (api) {
150de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian        case EGL:
151de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian            dso[0] = hnd;
152de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian            break;
153de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian        case GLESv1_CM:
154de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian            dso[1] = hnd;
155de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian            break;
156de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian        case GLESv2:
157de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian            dso[2] = hnd;
158de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian            break;
159de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian        default:
160de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian            return BAD_INDEX;
161de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian    }
162de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian    return NO_ERROR;
163de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian}
164de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian
165de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian// ----------------------------------------------------------------------------
166de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian
167de58697644a52a614ad9498aa087e95d4a223673Mathias AgopianLoader::Loader()
168a91f64cbe1bc057a466a865446767ffd48133a8fJesse Hall    : getProcAddress(NULL),
169a91f64cbe1bc057a466a865446767ffd48133a8fJesse Hall      mLibGui(nullptr),
170a91f64cbe1bc057a466a865446767ffd48133a8fJesse Hall      mGetDriverNamespace(nullptr)
171a91f64cbe1bc057a466a865446767ffd48133a8fJesse Hall{
172a91f64cbe1bc057a466a865446767ffd48133a8fJesse Hall    // FIXME: See note in GraphicsEnv.h about android_getDriverNamespace().
173a91f64cbe1bc057a466a865446767ffd48133a8fJesse Hall    // libgui should already be loaded in any process that uses libEGL, but
174a91f64cbe1bc057a466a865446767ffd48133a8fJesse Hall    // if for some reason it isn't, then we're not going to get a driver
175a91f64cbe1bc057a466a865446767ffd48133a8fJesse Hall    // namespace anyway, so don't force it to be loaded.
176a91f64cbe1bc057a466a865446767ffd48133a8fJesse Hall    mLibGui = dlopen("libgui.so", RTLD_NOLOAD | RTLD_LOCAL | RTLD_LAZY);
177a91f64cbe1bc057a466a865446767ffd48133a8fJesse Hall    if (!mLibGui) {
178a91f64cbe1bc057a466a865446767ffd48133a8fJesse Hall        ALOGD("failed to load libgui: %s", dlerror());
179a91f64cbe1bc057a466a865446767ffd48133a8fJesse Hall        return;
180a91f64cbe1bc057a466a865446767ffd48133a8fJesse Hall    }
181a91f64cbe1bc057a466a865446767ffd48133a8fJesse Hall    mGetDriverNamespace = reinterpret_cast<decltype(mGetDriverNamespace)>(
182a91f64cbe1bc057a466a865446767ffd48133a8fJesse Hall            dlsym(mLibGui, "android_getDriverNamespace"));
183de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian}
184de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian
185993814255fc248454368ed9fe34b4703a05eaf99Mathias AgopianLoader::~Loader() {
186a91f64cbe1bc057a466a865446767ffd48133a8fJesse Hall    if (mLibGui)
187a91f64cbe1bc057a466a865446767ffd48133a8fJesse Hall        dlclose(mLibGui);
188de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian}
189de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian
190c07b52060acd627c8510c1a9151e0753fce76330Jesse Hallstatic void* load_wrapper(const char* path) {
191bb5a921fef0445f1ffa4fe0781cd1b8108ad79ceJesse Hall    void* so = do_dlopen(path, RTLD_NOW | RTLD_LOCAL);
192c07b52060acd627c8510c1a9151e0753fce76330Jesse Hall    ALOGE_IF(!so, "dlopen(\"%s\") failed: %s", path, dlerror());
193c07b52060acd627c8510c1a9151e0753fce76330Jesse Hall    return so;
194c07b52060acd627c8510c1a9151e0753fce76330Jesse Hall}
195c07b52060acd627c8510c1a9151e0753fce76330Jesse Hall
196c2466e6f005e9cbeea7764e9d8864fa6bca17633Evgenii Stepanov#ifndef EGL_WRAPPER_DIR
197c2466e6f005e9cbeea7764e9d8864fa6bca17633Evgenii Stepanov#if defined(__LP64__)
198c2466e6f005e9cbeea7764e9d8864fa6bca17633Evgenii Stepanov#define EGL_WRAPPER_DIR "/system/lib64"
199c2466e6f005e9cbeea7764e9d8864fa6bca17633Evgenii Stepanov#else
200c2466e6f005e9cbeea7764e9d8864fa6bca17633Evgenii Stepanov#define EGL_WRAPPER_DIR "/system/lib"
201c2466e6f005e9cbeea7764e9d8864fa6bca17633Evgenii Stepanov#endif
202c2466e6f005e9cbeea7764e9d8864fa6bca17633Evgenii Stepanov#endif
203c2466e6f005e9cbeea7764e9d8864fa6bca17633Evgenii Stepanov
20469e5b1ab80018817b1d4ffbbdb5695ff70168c95bohustatic void setEmulatorGlesValue(void) {
20569e5b1ab80018817b1d4ffbbdb5695ff70168c95bohu    char prop[PROPERTY_VALUE_MAX];
20669e5b1ab80018817b1d4ffbbdb5695ff70168c95bohu    property_get("ro.kernel.qemu", prop, "0");
20769e5b1ab80018817b1d4ffbbdb5695ff70168c95bohu    if (atoi(prop) != 1) return;
20869e5b1ab80018817b1d4ffbbdb5695ff70168c95bohu
20969e5b1ab80018817b1d4ffbbdb5695ff70168c95bohu    property_get("ro.kernel.qemu.gles",prop,"0");
21069e5b1ab80018817b1d4ffbbdb5695ff70168c95bohu    if (atoi(prop) == 1) {
21169e5b1ab80018817b1d4ffbbdb5695ff70168c95bohu        ALOGD("Emulator has host GPU support, qemu.gles is set to 1.");
21269e5b1ab80018817b1d4ffbbdb5695ff70168c95bohu        property_set("qemu.gles", "1");
21369e5b1ab80018817b1d4ffbbdb5695ff70168c95bohu        return;
21469e5b1ab80018817b1d4ffbbdb5695ff70168c95bohu    }
21569e5b1ab80018817b1d4ffbbdb5695ff70168c95bohu
21669e5b1ab80018817b1d4ffbbdb5695ff70168c95bohu    // for now, checking the following
21769e5b1ab80018817b1d4ffbbdb5695ff70168c95bohu    // directory is good enough for emulator system images
21869e5b1ab80018817b1d4ffbbdb5695ff70168c95bohu    const char* vendor_lib_path =
21969e5b1ab80018817b1d4ffbbdb5695ff70168c95bohu#if defined(__LP64__)
22069e5b1ab80018817b1d4ffbbdb5695ff70168c95bohu        "/vendor/lib64/egl";
22169e5b1ab80018817b1d4ffbbdb5695ff70168c95bohu#else
22269e5b1ab80018817b1d4ffbbdb5695ff70168c95bohu        "/vendor/lib/egl";
22369e5b1ab80018817b1d4ffbbdb5695ff70168c95bohu#endif
22469e5b1ab80018817b1d4ffbbdb5695ff70168c95bohu
22569e5b1ab80018817b1d4ffbbdb5695ff70168c95bohu    const bool has_vendor_lib = (access(vendor_lib_path, R_OK) == 0);
22669e5b1ab80018817b1d4ffbbdb5695ff70168c95bohu    if (has_vendor_lib) {
22769e5b1ab80018817b1d4ffbbdb5695ff70168c95bohu        ALOGD("Emulator has vendor provided software renderer, qemu.gles is set to 2.");
22869e5b1ab80018817b1d4ffbbdb5695ff70168c95bohu        property_set("qemu.gles", "2");
22969e5b1ab80018817b1d4ffbbdb5695ff70168c95bohu    } else {
23069e5b1ab80018817b1d4ffbbdb5695ff70168c95bohu        ALOGD("Emulator without GPU support detected. "
23169e5b1ab80018817b1d4ffbbdb5695ff70168c95bohu              "Fallback to legacy software renderer, qemu.gles is set to 0.");
23269e5b1ab80018817b1d4ffbbdb5695ff70168c95bohu        property_set("qemu.gles", "0");
23369e5b1ab80018817b1d4ffbbdb5695ff70168c95bohu    }
23469e5b1ab80018817b1d4ffbbdb5695ff70168c95bohu}
23569e5b1ab80018817b1d4ffbbdb5695ff70168c95bohu
236ada798b7ca7cabc255aa159964b64975e7fdb2dfMathias Agopianvoid* Loader::open(egl_connection_t* cnx)
237de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian{
238bb5a921fef0445f1ffa4fe0781cd1b8108ad79ceJesse Hall    ATRACE_CALL();
239bb5a921fef0445f1ffa4fe0781cd1b8108ad79ceJesse Hall
240de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian    void* dso;
241de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian    driver_t* hnd = 0;
24294cdba97ce1de140623d84c14fb15f12f7da89ddJesse Hall
24369e5b1ab80018817b1d4ffbbdb5695ff70168c95bohu    setEmulatorGlesValue();
24469e5b1ab80018817b1d4ffbbdb5695ff70168c95bohu
245993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian    dso = load_driver("GLES", cnx, EGL | GLESv1_CM | GLESv2);
246993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian    if (dso) {
247993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian        hnd = new driver_t(dso);
248993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian    } else {
249993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian        // Always load EGL first
250993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian        dso = load_driver("EGL", cnx, EGL);
251de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian        if (dso) {
252de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian            hnd = new driver_t(dso);
253993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian            hnd->set( load_driver("GLESv1_CM", cnx, GLESv1_CM), GLESv1_CM );
254993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian            hnd->set( load_driver("GLESv2",    cnx, GLESv2),    GLESv2 );
255de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian        }
256de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian    }
257de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian
258993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian    LOG_ALWAYS_FATAL_IF(!hnd, "couldn't find an OpenGL ES implementation");
259c07b52060acd627c8510c1a9151e0753fce76330Jesse Hall
260c2466e6f005e9cbeea7764e9d8864fa6bca17633Evgenii Stepanov    cnx->libEgl   = load_wrapper(EGL_WRAPPER_DIR "/libEGL.so");
261c2466e6f005e9cbeea7764e9d8864fa6bca17633Evgenii Stepanov    cnx->libGles2 = load_wrapper(EGL_WRAPPER_DIR "/libGLESv2.so");
262c2466e6f005e9cbeea7764e9d8864fa6bca17633Evgenii Stepanov    cnx->libGles1 = load_wrapper(EGL_WRAPPER_DIR "/libGLESv1_CM.so");
263c2466e6f005e9cbeea7764e9d8864fa6bca17633Evgenii Stepanov
264c0ec5e2333b6350480851b8b48f000c78ea3f88aMichael Chock    LOG_ALWAYS_FATAL_IF(!cnx->libEgl,
265c0ec5e2333b6350480851b8b48f000c78ea3f88aMichael Chock            "couldn't load system EGL wrapper libraries");
266c0ec5e2333b6350480851b8b48f000c78ea3f88aMichael Chock
267c07b52060acd627c8510c1a9151e0753fce76330Jesse Hall    LOG_ALWAYS_FATAL_IF(!cnx->libGles2 || !cnx->libGles1,
268c07b52060acd627c8510c1a9151e0753fce76330Jesse Hall            "couldn't load system OpenGL ES wrapper libraries");
269c07b52060acd627c8510c1a9151e0753fce76330Jesse Hall
270de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian    return (void*)hnd;
271de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian}
272de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian
273de58697644a52a614ad9498aa087e95d4a223673Mathias Agopianstatus_t Loader::close(void* driver)
274de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian{
275de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian    driver_t* hnd = (driver_t*)driver;
276de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian    delete hnd;
277de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian    return NO_ERROR;
278de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian}
279de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian
28094cdba97ce1de140623d84c14fb15f12f7da89ddJesse Hallvoid Loader::init_api(void* dso,
28194cdba97ce1de140623d84c14fb15f12f7da89ddJesse Hall        char const * const * api,
28294cdba97ce1de140623d84c14fb15f12f7da89ddJesse Hall        __eglMustCastToProperFunctionPointerType* curr,
28394cdba97ce1de140623d84c14fb15f12f7da89ddJesse Hall        getProcAddressType getProcAddress)
284de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian{
285bb5a921fef0445f1ffa4fe0781cd1b8108ad79ceJesse Hall    ATRACE_CALL();
286bb5a921fef0445f1ffa4fe0781cd1b8108ad79ceJesse Hall
2877773c435bc5da8217433e1b242d3a6712a17b5f7Mathias Agopian    const ssize_t SIZE = 256;
2880ad71a97c6061e3b12d2308bd43e02dfeeb63db4Mathias Agopian    char scrap[SIZE];
289de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian    while (*api) {
290de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian        char const * name = *api;
29194cdba97ce1de140623d84c14fb15f12f7da89ddJesse Hall        __eglMustCastToProperFunctionPointerType f =
292de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian            (__eglMustCastToProperFunctionPointerType)dlsym(dso, name);
293de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian        if (f == NULL) {
294de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian            // couldn't find the entry-point, use eglGetProcAddress()
295de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian            f = getProcAddress(name);
296de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian        }
297de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian        if (f == NULL) {
298de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian            // Try without the OES postfix
299de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian            ssize_t index = ssize_t(strlen(name)) - 3;
3000ad71a97c6061e3b12d2308bd43e02dfeeb63db4Mathias Agopian            if ((index>0 && (index<SIZE-1)) && (!strcmp(name+index, "OES"))) {
301de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian                strncpy(scrap, name, index);
302de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian                scrap[index] = 0;
303de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian                f = (__eglMustCastToProperFunctionPointerType)dlsym(dso, scrap);
3049d4536835248525f32f1504a3d28d5bbfa0a2910Steve Block                //ALOGD_IF(f, "found <%s> instead", scrap);
305de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian            }
306de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian        }
307de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian        if (f == NULL) {
308de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian            // Try with the OES postfix
3090ad71a97c6061e3b12d2308bd43e02dfeeb63db4Mathias Agopian            ssize_t index = ssize_t(strlen(name)) - 3;
3100ad71a97c6061e3b12d2308bd43e02dfeeb63db4Mathias Agopian            if (index>0 && strcmp(name+index, "OES")) {
3110ad71a97c6061e3b12d2308bd43e02dfeeb63db4Mathias Agopian                snprintf(scrap, SIZE, "%sOES", name);
312de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian                f = (__eglMustCastToProperFunctionPointerType)dlsym(dso, scrap);
3139d4536835248525f32f1504a3d28d5bbfa0a2910Steve Block                //ALOGD_IF(f, "found <%s> instead", scrap);
314de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian            }
315de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian        }
316de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian        if (f == NULL) {
3179d4536835248525f32f1504a3d28d5bbfa0a2910Steve Block            //ALOGD("%s", name);
318de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian            f = (__eglMustCastToProperFunctionPointerType)gl_unimplemented;
31948d438d05f14c2f4bd83ae89f520368cd49122dfMathias Agopian
32048d438d05f14c2f4bd83ae89f520368cd49122dfMathias Agopian            /*
32148d438d05f14c2f4bd83ae89f520368cd49122dfMathias Agopian             * GL_EXT_debug_label is special, we always report it as
32248d438d05f14c2f4bd83ae89f520368cd49122dfMathias Agopian             * supported, it's handled by GLES_trace. If GLES_trace is not
32348d438d05f14c2f4bd83ae89f520368cd49122dfMathias Agopian             * enabled, then these are no-ops.
32448d438d05f14c2f4bd83ae89f520368cd49122dfMathias Agopian             */
32548d438d05f14c2f4bd83ae89f520368cd49122dfMathias Agopian            if (!strcmp(name, "glInsertEventMarkerEXT")) {
32648d438d05f14c2f4bd83ae89f520368cd49122dfMathias Agopian                f = (__eglMustCastToProperFunctionPointerType)gl_noop;
32748d438d05f14c2f4bd83ae89f520368cd49122dfMathias Agopian            } else if (!strcmp(name, "glPushGroupMarkerEXT")) {
32848d438d05f14c2f4bd83ae89f520368cd49122dfMathias Agopian                f = (__eglMustCastToProperFunctionPointerType)gl_noop;
32948d438d05f14c2f4bd83ae89f520368cd49122dfMathias Agopian            } else if (!strcmp(name, "glPopGroupMarkerEXT")) {
33048d438d05f14c2f4bd83ae89f520368cd49122dfMathias Agopian                f = (__eglMustCastToProperFunctionPointerType)gl_noop;
33148d438d05f14c2f4bd83ae89f520368cd49122dfMathias Agopian            }
332de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian        }
333de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian        *curr++ = f;
334de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian        api++;
335de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian    }
336de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian}
337de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian
338a91f64cbe1bc057a466a865446767ffd48133a8fJesse Hallstatic void* load_system_driver(const char* kind) {
339bb5a921fef0445f1ffa4fe0781cd1b8108ad79ceJesse Hall    ATRACE_CALL();
340993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian    class MatchFile {
341993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian    public:
342993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian        static String8 find(const char* kind) {
343993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian            String8 result;
344776951f9db5744c94167d463584e9ee42c849712Nicolas Capens            int emulationStatus = checkGlesEmulationStatus();
345776951f9db5744c94167d463584e9ee42c849712Nicolas Capens            switch (emulationStatus) {
346776951f9db5744c94167d463584e9ee42c849712Nicolas Capens                case 0:
347776951f9db5744c94167d463584e9ee42c849712Nicolas Capens#if defined(__LP64__)
348776951f9db5744c94167d463584e9ee42c849712Nicolas Capens                    result.setTo("/system/lib64/egl/libGLES_android.so");
349776951f9db5744c94167d463584e9ee42c849712Nicolas Capens#else
350776951f9db5744c94167d463584e9ee42c849712Nicolas Capens                    result.setTo("/system/lib/egl/libGLES_android.so");
351776951f9db5744c94167d463584e9ee42c849712Nicolas Capens#endif
352776951f9db5744c94167d463584e9ee42c849712Nicolas Capens                    return result;
353776951f9db5744c94167d463584e9ee42c849712Nicolas Capens                case 1:
354776951f9db5744c94167d463584e9ee42c849712Nicolas Capens                    // Use host-side OpenGL through the "emulation" library
355776951f9db5744c94167d463584e9ee42c849712Nicolas Capens#if defined(__LP64__)
356776951f9db5744c94167d463584e9ee42c849712Nicolas Capens                    result.appendFormat("/system/lib64/egl/lib%s_emulation.so", kind);
357776951f9db5744c94167d463584e9ee42c849712Nicolas Capens#else
358776951f9db5744c94167d463584e9ee42c849712Nicolas Capens                    result.appendFormat("/system/lib/egl/lib%s_emulation.so", kind);
359776951f9db5744c94167d463584e9ee42c849712Nicolas Capens#endif
360776951f9db5744c94167d463584e9ee42c849712Nicolas Capens                    return result;
361776951f9db5744c94167d463584e9ee42c849712Nicolas Capens                default:
362776951f9db5744c94167d463584e9ee42c849712Nicolas Capens                    // Not in emulator, or use other guest-side implementation
363776951f9db5744c94167d463584e9ee42c849712Nicolas Capens                    break;
364776951f9db5744c94167d463584e9ee42c849712Nicolas Capens            }
365776951f9db5744c94167d463584e9ee42c849712Nicolas Capens
366993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian            String8 pattern;
367993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian            pattern.appendFormat("lib%s", kind);
368993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian            const char* const searchPaths[] = {
3698edb8f5f2d016e4e31530ad7a0c44a4a7a853f64Dan Willemsen#if defined(__LP64__)
3708edb8f5f2d016e4e31530ad7a0c44a4a7a853f64Dan Willemsen                    "/vendor/lib64/egl",
3718edb8f5f2d016e4e31530ad7a0c44a4a7a853f64Dan Willemsen                    "/system/lib64/egl"
3728edb8f5f2d016e4e31530ad7a0c44a4a7a853f64Dan Willemsen#else
373993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian                    "/vendor/lib/egl",
374993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian                    "/system/lib/egl"
3758edb8f5f2d016e4e31530ad7a0c44a4a7a853f64Dan Willemsen#endif
376993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian            };
377993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian
378993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian            // first, we search for the exact name of the GLES userspace
379993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian            // driver in both locations.
380993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian            // i.e.:
381993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian            //      libGLES.so, or:
382993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian            //      libEGL.so, libGLESv1_CM.so, libGLESv2.so
383993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian
384993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian            for (size_t i=0 ; i<NELEM(searchPaths) ; i++) {
385993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian                if (find(result, pattern, searchPaths[i], true)) {
386993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian                    return result;
387993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian                }
388993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian            }
389993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian
390993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian            // for compatibility with the old "egl.cfg" naming convention
391993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian            // we look for files that match:
392993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian            //      libGLES_*.so, or:
393993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian            //      libEGL_*.so, libGLESv1_CM_*.so, libGLESv2_*.so
394993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian
395993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian            pattern.append("_");
396993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian            for (size_t i=0 ; i<NELEM(searchPaths) ; i++) {
397993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian                if (find(result, pattern, searchPaths[i], false)) {
398993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian                    return result;
399993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian                }
400993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian            }
401993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian
402993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian            // we didn't find the driver. gah.
403993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian            result.clear();
404993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian            return result;
405993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian        }
406993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian
407993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian    private:
408993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian        static bool find(String8& result,
409993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian                const String8& pattern, const char* const search, bool exact) {
410993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian            if (exact) {
411993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian                String8 absolutePath;
412993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian                absolutePath.appendFormat("%s/%s.so", search, pattern.string());
413993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian                if (!access(absolutePath.string(), R_OK)) {
414993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian                    result = absolutePath;
415993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian                    return true;
416993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian                }
417993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian                return false;
418993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian            }
419993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian
420993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian            DIR* d = opendir(search);
421993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian            if (d != NULL) {
422993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian                struct dirent cur;
423993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian                struct dirent* e;
424993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian                while (readdir_r(d, &cur, &e) == 0 && e) {
425993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian                    if (e->d_type == DT_DIR) {
426993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian                        continue;
427993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian                    }
428993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian                    if (!strcmp(e->d_name, "libGLES_android.so")) {
429993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian                        // always skip the software renderer
430993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian                        continue;
431993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian                    }
432993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian                    if (strstr(e->d_name, pattern.string()) == e->d_name) {
433993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian                        if (!strcmp(e->d_name + strlen(e->d_name) - 3, ".so")) {
434993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian                            result.clear();
435993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian                            result.appendFormat("%s/%s", search, e->d_name);
436993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian                            closedir(d);
437993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian                            return true;
438993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian                        }
439993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian                    }
440993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian                }
441993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian                closedir(d);
442993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian            }
443993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian            return false;
4442b9e4f6a2490864ead44e88a68da78be5cb3da22Brian Swetland        }
445993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian    };
446993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian
447993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian
448993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian    String8 absolutePath = MatchFile::find(kind);
449993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian    if (absolutePath.isEmpty()) {
450993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian        // this happens often, we don't want to log an error
451993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian        return 0;
4528c17384a5edd027376926b857af1fb170dbe9b43Mathias Agopian    }
453993814255fc248454368ed9fe34b4703a05eaf99Mathias Agopian    const char* const driver_absolute_path = absolutePath.string();
4548c17384a5edd027376926b857af1fb170dbe9b43Mathias Agopian
455bb5a921fef0445f1ffa4fe0781cd1b8108ad79ceJesse Hall    void* dso = do_dlopen(driver_absolute_path, RTLD_NOW | RTLD_LOCAL);
4568c17384a5edd027376926b857af1fb170dbe9b43Mathias Agopian    if (dso == 0) {
4578c17384a5edd027376926b857af1fb170dbe9b43Mathias Agopian        const char* err = dlerror();
458e6f43ddce78d6846af12550ff9193c5c6fe5844bSteve Block        ALOGE("load_driver(%s): %s", driver_absolute_path, err?err:"unknown");
4598c17384a5edd027376926b857af1fb170dbe9b43Mathias Agopian        return 0;
4608c17384a5edd027376926b857af1fb170dbe9b43Mathias Agopian    }
461de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian
4629d4536835248525f32f1504a3d28d5bbfa0a2910Steve Block    ALOGD("loaded %s", driver_absolute_path);
463baca89c06a40c6c19ae2294fb4263d893126320cMathias Agopian
464a91f64cbe1bc057a466a865446767ffd48133a8fJesse Hall    return dso;
465a91f64cbe1bc057a466a865446767ffd48133a8fJesse Hall}
466a91f64cbe1bc057a466a865446767ffd48133a8fJesse Hall
467bb5a921fef0445f1ffa4fe0781cd1b8108ad79ceJesse Hallstatic void* do_android_dlopen_ext(const char* path, int mode, const android_dlextinfo* info) {
468bb5a921fef0445f1ffa4fe0781cd1b8108ad79ceJesse Hall    ATRACE_CALL();
469bb5a921fef0445f1ffa4fe0781cd1b8108ad79ceJesse Hall    return android_dlopen_ext(path, mode, info);
470bb5a921fef0445f1ffa4fe0781cd1b8108ad79ceJesse Hall}
471bb5a921fef0445f1ffa4fe0781cd1b8108ad79ceJesse Hall
472a91f64cbe1bc057a466a865446767ffd48133a8fJesse Hallstatic const std::array<const char*, 2> HAL_SUBNAME_KEY_PROPERTIES = {{
473a91f64cbe1bc057a466a865446767ffd48133a8fJesse Hall    "ro.hardware.egl",
474a91f64cbe1bc057a466a865446767ffd48133a8fJesse Hall    "ro.board.platform",
475a91f64cbe1bc057a466a865446767ffd48133a8fJesse Hall}};
476a91f64cbe1bc057a466a865446767ffd48133a8fJesse Hall
477a91f64cbe1bc057a466a865446767ffd48133a8fJesse Hallstatic void* load_updated_driver(const char* kind, android_namespace_t* ns) {
478bb5a921fef0445f1ffa4fe0781cd1b8108ad79ceJesse Hall    ATRACE_CALL();
479a91f64cbe1bc057a466a865446767ffd48133a8fJesse Hall    const android_dlextinfo dlextinfo = {
480a91f64cbe1bc057a466a865446767ffd48133a8fJesse Hall        .flags = ANDROID_DLEXT_USE_NAMESPACE,
481a91f64cbe1bc057a466a865446767ffd48133a8fJesse Hall        .library_namespace = ns,
482a91f64cbe1bc057a466a865446767ffd48133a8fJesse Hall    };
483a91f64cbe1bc057a466a865446767ffd48133a8fJesse Hall    void* so = nullptr;
484a91f64cbe1bc057a466a865446767ffd48133a8fJesse Hall    char prop[PROPERTY_VALUE_MAX + 1];
485a91f64cbe1bc057a466a865446767ffd48133a8fJesse Hall    for (auto key : HAL_SUBNAME_KEY_PROPERTIES) {
486a91f64cbe1bc057a466a865446767ffd48133a8fJesse Hall        if (property_get(key, prop, nullptr) > 0) {
487a91f64cbe1bc057a466a865446767ffd48133a8fJesse Hall            String8 name;
488a91f64cbe1bc057a466a865446767ffd48133a8fJesse Hall            name.appendFormat("lib%s_%s.so", kind, prop);
489bb5a921fef0445f1ffa4fe0781cd1b8108ad79ceJesse Hall            so = do_android_dlopen_ext(name.string(), RTLD_LOCAL | RTLD_NOW,
490a91f64cbe1bc057a466a865446767ffd48133a8fJesse Hall                    &dlextinfo);
491a91f64cbe1bc057a466a865446767ffd48133a8fJesse Hall            if (so)
492a91f64cbe1bc057a466a865446767ffd48133a8fJesse Hall                return so;
493a91f64cbe1bc057a466a865446767ffd48133a8fJesse Hall        }
494a91f64cbe1bc057a466a865446767ffd48133a8fJesse Hall    }
495a91f64cbe1bc057a466a865446767ffd48133a8fJesse Hall    return nullptr;
496a91f64cbe1bc057a466a865446767ffd48133a8fJesse Hall}
497a91f64cbe1bc057a466a865446767ffd48133a8fJesse Hall
498a91f64cbe1bc057a466a865446767ffd48133a8fJesse Hallvoid *Loader::load_driver(const char* kind,
499a91f64cbe1bc057a466a865446767ffd48133a8fJesse Hall        egl_connection_t* cnx, uint32_t mask)
500a91f64cbe1bc057a466a865446767ffd48133a8fJesse Hall{
501bb5a921fef0445f1ffa4fe0781cd1b8108ad79ceJesse Hall    ATRACE_CALL();
502bb5a921fef0445f1ffa4fe0781cd1b8108ad79ceJesse Hall
503a91f64cbe1bc057a466a865446767ffd48133a8fJesse Hall    void* dso = nullptr;
504a91f64cbe1bc057a466a865446767ffd48133a8fJesse Hall    if (mGetDriverNamespace) {
505a91f64cbe1bc057a466a865446767ffd48133a8fJesse Hall        android_namespace_t* ns = mGetDriverNamespace();
506a91f64cbe1bc057a466a865446767ffd48133a8fJesse Hall        if (ns) {
507a91f64cbe1bc057a466a865446767ffd48133a8fJesse Hall            dso = load_updated_driver(kind, ns);
508a91f64cbe1bc057a466a865446767ffd48133a8fJesse Hall        }
509a91f64cbe1bc057a466a865446767ffd48133a8fJesse Hall    }
510a91f64cbe1bc057a466a865446767ffd48133a8fJesse Hall    if (!dso) {
511a91f64cbe1bc057a466a865446767ffd48133a8fJesse Hall        dso = load_system_driver(kind);
512a91f64cbe1bc057a466a865446767ffd48133a8fJesse Hall        if (!dso)
513a91f64cbe1bc057a466a865446767ffd48133a8fJesse Hall            return NULL;
514a91f64cbe1bc057a466a865446767ffd48133a8fJesse Hall    }
515a91f64cbe1bc057a466a865446767ffd48133a8fJesse Hall
516de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian    if (mask & EGL) {
517de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian        getProcAddress = (getProcAddressType)dlsym(dso, "eglGetProcAddress");
518de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian
51994cdba97ce1de140623d84c14fb15f12f7da89ddJesse Hall        ALOGE_IF(!getProcAddress,
520a91f64cbe1bc057a466a865446767ffd48133a8fJesse Hall                "can't find eglGetProcAddress() in EGL driver library");
521de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian
522618fa10949c42eb83fa5fe105fe542bcff833ddaMathias Agopian        egl_t* egl = &cnx->egl;
523de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian        __eglMustCastToProperFunctionPointerType* curr =
524de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian            (__eglMustCastToProperFunctionPointerType*)egl;
525de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian        char const * const * api = egl_names;
526de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian        while (*api) {
527de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian            char const * name = *api;
52894cdba97ce1de140623d84c14fb15f12f7da89ddJesse Hall            __eglMustCastToProperFunctionPointerType f =
529de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian                (__eglMustCastToProperFunctionPointerType)dlsym(dso, name);
530de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian            if (f == NULL) {
531de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian                // couldn't find the entry-point, use eglGetProcAddress()
532de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian                f = getProcAddress(name);
533de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian                if (f == NULL) {
534de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian                    f = (__eglMustCastToProperFunctionPointerType)0;
535de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian                }
536de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian            }
537de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian            *curr++ = f;
538de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian            api++;
539de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian        }
540de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian    }
54194cdba97ce1de140623d84c14fb15f12f7da89ddJesse Hall
542de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian    if (mask & GLESv1_CM) {
543618fa10949c42eb83fa5fe105fe542bcff833ddaMathias Agopian        init_api(dso, gl_names,
544618fa10949c42eb83fa5fe105fe542bcff833ddaMathias Agopian            (__eglMustCastToProperFunctionPointerType*)
5457773c435bc5da8217433e1b242d3a6712a17b5f7Mathias Agopian                &cnx->hooks[egl_connection_t::GLESv1_INDEX]->gl,
546618fa10949c42eb83fa5fe105fe542bcff833ddaMathias Agopian            getProcAddress);
547de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian    }
548de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian
549de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian    if (mask & GLESv2) {
550618fa10949c42eb83fa5fe105fe542bcff833ddaMathias Agopian      init_api(dso, gl_names,
551618fa10949c42eb83fa5fe105fe542bcff833ddaMathias Agopian            (__eglMustCastToProperFunctionPointerType*)
5527773c435bc5da8217433e1b242d3a6712a17b5f7Mathias Agopian                &cnx->hooks[egl_connection_t::GLESv2_INDEX]->gl,
553de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian            getProcAddress);
554de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian    }
55594cdba97ce1de140623d84c14fb15f12f7da89ddJesse Hall
556de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian    return dso;
557de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian}
558de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian
559de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian// ----------------------------------------------------------------------------
560de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian}; // namespace android
561de58697644a52a614ad9498aa087e95d4a223673Mathias Agopian// ----------------------------------------------------------------------------
562