Home | History | Annotate | Download | only in EGL
      1 /*
      2  ** Copyright 2018, 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 #include "egl_layers.h"
     18 
     19 #include <EGL/egl.h>
     20 #include <android-base/file.h>
     21 #include <android-base/strings.h>
     22 #include <android/dlext.h>
     23 #include <cutils/properties.h>
     24 #include <dlfcn.h>
     25 #include <graphicsenv/GraphicsEnv.h>
     26 #include <log/log.h>
     27 #include <nativebridge/native_bridge.h>
     28 #include <nativeloader/native_loader.h>
     29 #include <sys/prctl.h>
     30 
     31 namespace android {
     32 
     33 // GLES Layers
     34 //
     35 // - Layer discovery -
     36 // 1. Check for debug layer list from GraphicsEnv
     37 // 2. If none enabled, check system properties
     38 //
     39 // - Layer initializing -
     40 // - AndroidGLESLayer_Initialize (provided by layer, called by loader)
     41 // - AndroidGLESLayer_GetProcAddress (provided by layer, called by loader)
     42 // - getNextLayerProcAddress (provided by loader, called by layer)
     43 //
     44 // 1. Walk through defs for egl and each gl version
     45 // 2. Call GetLayerProcAddress passing the name and the target hook entry point
     46 //   - This tells the layer the next point in the chain it should call
     47 // 3. Replace the hook with the layer's entry point
     48 //    - All entryoints will be present, anything unsupported by the driver will
     49 //      have gl_unimplemented
     50 //
     51 // - Extension layering -
     52 //  Not all functions are known to Android, so libEGL handles extensions.
     53 //  They are looked up by applications using eglGetProcAddress
     54 //  Layers can look them up with getNextLayerProcAddress
     55 
     56 const int kFuncCount = sizeof(platform_impl_t) / sizeof(char*) + sizeof(egl_t) / sizeof(char*) +
     57         sizeof(gl_hooks_t) / sizeof(char*);
     58 
     59 typedef struct FunctionTable {
     60     EGLFuncPointer x[kFuncCount];
     61     EGLFuncPointer& operator[](int i) { return x[i]; }
     62 } FunctionTable;
     63 
     64 // TODO: Move these to class
     65 std::unordered_map<std::string, int> func_indices;
     66 // func_indices.reserve(kFuncCount);
     67 
     68 std::unordered_map<int, std::string> func_names;
     69 // func_names.reserve(kFuncCount);
     70 
     71 std::vector<FunctionTable> layer_functions;
     72 
     73 const void* getNextLayerProcAddress(void* layer_id, const char* name) {
     74     // Use layer_id to find funcs for layer below current
     75     // This is the same key provided in AndroidGLESLayer_Initialize
     76     auto next_layer_funcs = reinterpret_cast<FunctionTable*>(layer_id);
     77     EGLFuncPointer val;
     78 
     79     ALOGV("getNextLayerProcAddress servicing %s", name);
     80 
     81     if (func_indices.find(name) == func_indices.end()) {
     82         // No entry for this function - it is an extension
     83         // call down the GPA chain directly to the impl
     84         ALOGV("getNextLayerProcAddress - name(%s) no func_indices entry found", name);
     85 
     86         // Look up which GPA we should use
     87         int gpaIndex = func_indices["eglGetProcAddress"];
     88         ALOGV("getNextLayerProcAddress - name(%s) gpaIndex(%i) <- using GPA from this index", name, gpaIndex);
     89         EGLFuncPointer gpaNext = (*next_layer_funcs)[gpaIndex];
     90         ALOGV("getNextLayerProcAddress - name(%s) gpaIndex(%i) gpaNext(%llu) <- using GPA at this address", name, gpaIndex, (unsigned long long)gpaNext);
     91 
     92 
     93         // Call it for the requested function
     94         typedef void* (*PFNEGLGETPROCADDRESSPROC)(const char*);
     95         PFNEGLGETPROCADDRESSPROC next = reinterpret_cast<PFNEGLGETPROCADDRESSPROC>(gpaNext);
     96 
     97         val = reinterpret_cast<EGLFuncPointer>(next(name));
     98         ALOGV("getNextLayerProcAddress - name(%s) gpaIndex(%i) gpaNext(%llu) Got back (%llu) from GPA", name, gpaIndex, (unsigned long long)gpaNext, (unsigned long long)val);
     99 
    100         // We should store it now, but to do that, we need to move func_idx to the class so we can
    101         // increment it separately
    102         // TODO: Move func_idx to class and store the result of GPA
    103         return reinterpret_cast<void*>(val);
    104     }
    105 
    106     int index = func_indices[name];
    107     val = (*next_layer_funcs)[index];
    108     ALOGV("getNextLayerProcAddress - name(%s) index(%i) entry(%llu) - Got a hit, returning known entry", name, index, (unsigned long long)val);
    109     return reinterpret_cast<void*>(val);
    110 }
    111 
    112 void SetupFuncMaps(FunctionTable& functions, char const* const* entries, EGLFuncPointer* curr,
    113                    int& func_idx) {
    114     while (*entries) {
    115         const char* name = *entries;
    116 
    117         // Some names overlap, only fill with initial entry
    118         // This does mean that some indices will not be used
    119         if (func_indices.find(name) == func_indices.end()) {
    120             ALOGV("SetupFuncMaps - name(%s), func_idx(%i), No entry for func_indices, assigning now", name, func_idx);
    121             func_names[func_idx] = name;
    122             func_indices[name] = func_idx;
    123         } else {
    124             ALOGV("SetupFuncMaps - name(%s), func_idx(%i), Found entry for func_indices", name, func_idx);
    125         }
    126 
    127         // Populate layer_functions once with initial value
    128         // These values will arrive in priority order, starting with platform entries
    129         if (functions[func_idx] == nullptr) {
    130             ALOGV("SetupFuncMaps - name(%s), func_idx(%i), No entry for functions, assigning (%llu)", name, func_idx, (unsigned long long) *curr);
    131             functions[func_idx] = *curr;
    132         } else {
    133             ALOGV("SetupFuncMaps - name(%s), func_idx(%i), Found entry for functions (%llu)", name, func_idx, (unsigned long long) functions[func_idx]);
    134         }
    135 
    136         entries++;
    137         curr++;
    138         func_idx++;
    139     }
    140 }
    141 
    142 LayerLoader& LayerLoader::getInstance() {
    143     // This function is mutex protected in egl_init_drivers_locked and eglGetProcAddressImpl
    144     static LayerLoader layer_loader;
    145 
    146     if (!layer_loader.layers_loaded_) layer_loader.LoadLayers();
    147 
    148     return layer_loader;
    149 }
    150 
    151 const char kSystemLayerLibraryDir[] = "/data/local/debug/gles";
    152 
    153 std::string LayerLoader::GetDebugLayers() {
    154     // Layers can be specified at the Java level in GraphicsEnvironemnt
    155     // gpu_debug_layers_gles = layer1:layer2:layerN
    156     std::string debug_layers = android::GraphicsEnv::getInstance().getDebugLayersGLES();
    157 
    158     if (debug_layers.empty()) {
    159         // Only check system properties if Java settings are empty
    160         char prop[PROPERTY_VALUE_MAX];
    161         property_get("debug.gles.layers", prop, "");
    162         debug_layers = prop;
    163     }
    164 
    165     return debug_layers;
    166 }
    167 
    168 EGLFuncPointer LayerLoader::ApplyLayer(layer_setup_func layer_setup, const char* name,
    169                                        EGLFuncPointer next) {
    170     // Walk through our list of LayerSetup functions (they will already be in reverse order) to
    171     // build up a call chain from the driver
    172 
    173     EGLFuncPointer layer_entry = next;
    174 
    175     layer_entry = layer_setup(name, layer_entry);
    176 
    177     if (next != layer_entry) {
    178         ALOGV("We succeeded, replacing hook (%llu) with layer entry (%llu), for %s",
    179               (unsigned long long)next, (unsigned long long)layer_entry, name);
    180     }
    181 
    182     return layer_entry;
    183 }
    184 
    185 EGLFuncPointer LayerLoader::ApplyLayers(const char* name, EGLFuncPointer next) {
    186     if (!layers_loaded_ || layer_setup_.empty()) return next;
    187 
    188     ALOGV("ApplyLayers called for %s with next (%llu), current_layer_ (%i)", name,
    189           (unsigned long long)next, current_layer_);
    190 
    191     EGLFuncPointer val = next;
    192 
    193     // Only ApplyLayers for layers that have been setup, not all layers yet
    194     for (unsigned i = 0; i < current_layer_; i++) {
    195         ALOGV("ApplyLayers: Calling ApplyLayer with i = %i for %s with next (%llu)", i, name,
    196               (unsigned long long)next);
    197         val = ApplyLayer(layer_setup_[i], name, val);
    198     }
    199 
    200     ALOGV("ApplyLayers returning %llu for %s", (unsigned long long)val, name);
    201 
    202     return val;
    203 }
    204 
    205 void LayerLoader::LayerPlatformEntries(layer_setup_func layer_setup, EGLFuncPointer* curr,
    206                                        char const* const* entries) {
    207     while (*entries) {
    208         char const* name = *entries;
    209 
    210         EGLFuncPointer prev = *curr;
    211 
    212         // Pass the existing entry point into the layer, replace the call with return value
    213         *curr = ApplyLayer(layer_setup, name, *curr);
    214 
    215         if (prev != *curr) {
    216             ALOGV("LayerPlatformEntries: Replaced (%llu) with platform entry (%llu), for %s",
    217                   (unsigned long long)prev, (unsigned long long)*curr, name);
    218         } else {
    219             ALOGV("LayerPlatformEntries: No change(%llu) for %s, which means layer did not "
    220                   "intercept",
    221                   (unsigned long long)prev, name);
    222         }
    223 
    224         curr++;
    225         entries++;
    226     }
    227 }
    228 
    229 void LayerLoader::LayerDriverEntries(layer_setup_func layer_setup, EGLFuncPointer* curr,
    230                                      char const* const* entries) {
    231     while (*entries) {
    232         char const* name = *entries;
    233         EGLFuncPointer prev = *curr;
    234 
    235         // Only apply layers to driver entries if not handled by the platform
    236         if (FindPlatformImplAddr(name) == nullptr) {
    237             // Pass the existing entry point into the layer, replace the call with return value
    238             *curr = ApplyLayer(layer_setup, name, *prev);
    239 
    240             if (prev != *curr) {
    241                 ALOGV("LayerDriverEntries: Replaced (%llu) with platform entry (%llu), for %s",
    242                       (unsigned long long)prev, (unsigned long long)*curr, name);
    243             }
    244 
    245         } else {
    246             ALOGV("LayerDriverEntries: Skipped (%llu) for %s", (unsigned long long)prev, name);
    247         }
    248 
    249         curr++;
    250         entries++;
    251     }
    252 }
    253 
    254 bool LayerLoader::Initialized() {
    255     return initialized_;
    256 }
    257 
    258 void LayerLoader::InitLayers(egl_connection_t* cnx) {
    259     if (!layers_loaded_) return;
    260 
    261     if (initialized_) return;
    262 
    263     if (layer_setup_.empty()) {
    264         initialized_ = true;
    265         return;
    266     }
    267 
    268     // Include the driver in layer_functions
    269     layer_functions.resize(layer_setup_.size() + 1);
    270 
    271     // Walk through the initial lists and create layer_functions[0]
    272     int func_idx = 0;
    273     char const* const* entries;
    274     EGLFuncPointer* curr;
    275 
    276     entries = platform_names;
    277     curr = reinterpret_cast<EGLFuncPointer*>(&cnx->platform);
    278     SetupFuncMaps(layer_functions[0], entries, curr, func_idx);
    279     ALOGV("InitLayers: func_idx after platform_names: %i", func_idx);
    280 
    281     entries = egl_names;
    282     curr = reinterpret_cast<EGLFuncPointer*>(&cnx->egl);
    283     SetupFuncMaps(layer_functions[0], entries, curr, func_idx);
    284     ALOGV("InitLayers: func_idx after egl_names: %i", func_idx);
    285 
    286     entries = gl_names;
    287     curr = reinterpret_cast<EGLFuncPointer*>(&cnx->hooks[egl_connection_t::GLESv2_INDEX]->gl);
    288     SetupFuncMaps(layer_functions[0], entries, curr, func_idx);
    289     ALOGV("InitLayers: func_idx after gl_names: %i", func_idx);
    290 
    291     // Walk through each layer's entry points per API, starting just above the driver
    292     for (current_layer_ = 0; current_layer_ < layer_setup_.size(); current_layer_++) {
    293         // Init the layer with a key that points to layer just below it
    294         layer_init_[current_layer_](reinterpret_cast<void*>(&layer_functions[current_layer_]),
    295                                     reinterpret_cast<PFNEGLGETNEXTLAYERPROCADDRESSPROC>(
    296                                             getNextLayerProcAddress));
    297 
    298         // Check functions implemented by the platform
    299         func_idx = 0;
    300         entries = platform_names;
    301         curr = reinterpret_cast<EGLFuncPointer*>(&cnx->platform);
    302         LayerPlatformEntries(layer_setup_[current_layer_], curr, entries);
    303 
    304         // Populate next function table after layers have been applied
    305         SetupFuncMaps(layer_functions[current_layer_ + 1], entries, curr, func_idx);
    306 
    307         // EGL
    308         entries = egl_names;
    309         curr = reinterpret_cast<EGLFuncPointer*>(&cnx->egl);
    310         LayerDriverEntries(layer_setup_[current_layer_], curr, entries);
    311 
    312         // Populate next function table after layers have been applied
    313         SetupFuncMaps(layer_functions[current_layer_ + 1], entries, curr, func_idx);
    314 
    315         // GLES 2+
    316         // NOTE: We route calls to GLESv2 hooks, not GLESv1, so layering does not support GLES 1.x
    317         // If it were added in the future, a different layer initialization model would be needed,
    318         // that defers loading GLES entrypoints until after eglMakeCurrent, so two phase
    319         // initialization.
    320         entries = gl_names;
    321         curr = reinterpret_cast<EGLFuncPointer*>(&cnx->hooks[egl_connection_t::GLESv2_INDEX]->gl);
    322         LayerDriverEntries(layer_setup_[current_layer_], curr, entries);
    323 
    324         // Populate next function table after layers have been applied
    325         SetupFuncMaps(layer_functions[current_layer_ + 1], entries, curr, func_idx);
    326     }
    327 
    328     // We only want to apply layers once
    329     initialized_ = true;
    330 }
    331 
    332 void LayerLoader::LoadLayers() {
    333     std::string debug_layers = GetDebugLayers();
    334 
    335     // If no layers are specified, we're done
    336     if (debug_layers.empty()) return;
    337 
    338     // Only enable the system search path for non-user builds
    339     std::string system_path;
    340     if (property_get_bool("ro.debuggable", false) && prctl(PR_GET_DUMPABLE, 0, 0, 0, 0)) {
    341         system_path = kSystemLayerLibraryDir;
    342     }
    343 
    344     ALOGI("Debug layer list: %s", debug_layers.c_str());
    345     std::vector<std::string> layers = android::base::Split(debug_layers, ":");
    346 
    347     // Load the layers in reverse order so we start with the driver's entrypoint and work our way up
    348     for (int32_t i = layers.size() - 1; i >= 0; i--) {
    349         // Check each layer path for the layer
    350         std::vector<std::string> paths =
    351                 android::base::Split(android::GraphicsEnv::getInstance().getLayerPaths().c_str(),
    352                                      ":");
    353 
    354         if (!system_path.empty()) {
    355             // Prepend the system paths so they override other layers
    356             auto it = paths.begin();
    357             paths.insert(it, system_path);
    358         }
    359 
    360         bool layer_found = false;
    361         for (uint32_t j = 0; j < paths.size() && !layer_found; j++) {
    362             std::string layer;
    363 
    364             ALOGI("Searching %s for GLES layers", paths[j].c_str());
    365 
    366             // Realpath will return null for non-existent files
    367             android::base::Realpath(paths[j] + "/" + layers[i], &layer);
    368 
    369             if (!layer.empty()) {
    370                 layer_found = true;
    371                 ALOGI("GLES layer found: %s", layer.c_str());
    372 
    373                 // Load the layer
    374                 //
    375                 // TODO: This code is common with Vulkan loader, refactor
    376                 //
    377                 // Libraries in the system layer library dir can't be loaded into
    378                 // the application namespace. That causes compatibility problems, since
    379                 // any symbol dependencies will be resolved by system libraries. They
    380                 // can't safely use libc++_shared, for example. Which is one reason
    381                 // (among several) we only allow them in non-user builds.
    382                 void* handle = nullptr;
    383                 auto app_namespace = android::GraphicsEnv::getInstance().getAppNamespace();
    384                 if (app_namespace && !android::base::StartsWith(layer, kSystemLayerLibraryDir)) {
    385                     bool native_bridge = false;
    386                     char* error_message = nullptr;
    387                     handle = OpenNativeLibraryInNamespace(
    388                         app_namespace, layer.c_str(), &native_bridge, &error_message);
    389                     if (!handle) {
    390                         ALOGE("Failed to load layer %s with error: %s", layer.c_str(),
    391                               error_message);
    392                         android::NativeLoaderFreeErrorMessage(error_message);
    393                         return;
    394                     }
    395 
    396                 } else {
    397                     handle = dlopen(layer.c_str(), RTLD_NOW | RTLD_LOCAL);
    398                 }
    399 
    400                 if (handle) {
    401                     ALOGV("Loaded layer handle (%llu) for layer %s", (unsigned long long)handle,
    402                           layers[i].c_str());
    403                 } else {
    404                     // If the layer is found but can't be loaded, try setenforce 0
    405                     const char* dlsym_error = dlerror();
    406                     ALOGE("Failed to load layer %s with error: %s", layer.c_str(), dlsym_error);
    407                     return;
    408                 }
    409 
    410                 // Find the layer's Initialize function
    411                 std::string init_func = "AndroidGLESLayer_Initialize";
    412                 ALOGV("Looking for entrypoint %s", init_func.c_str());
    413 
    414                 layer_init_func LayerInit =
    415                         reinterpret_cast<layer_init_func>(dlsym(handle, init_func.c_str()));
    416                 if (LayerInit) {
    417                     ALOGV("Found %s for layer %s", init_func.c_str(), layer.c_str());
    418                     layer_init_.push_back(LayerInit);
    419                 } else {
    420                     ALOGE("Failed to dlsym %s for layer %s", init_func.c_str(), layer.c_str());
    421                     return;
    422                 }
    423 
    424                 // Find the layer's setup function
    425                 std::string setup_func = "AndroidGLESLayer_GetProcAddress";
    426                 ALOGV("Looking for entrypoint %s", setup_func.c_str());
    427 
    428                 layer_setup_func LayerSetup =
    429                         reinterpret_cast<layer_setup_func>(dlsym(handle, setup_func.c_str()));
    430                 if (LayerSetup) {
    431                     ALOGV("Found %s for layer %s", setup_func.c_str(), layer.c_str());
    432                     layer_setup_.push_back(LayerSetup);
    433                 } else {
    434                     ALOGE("Failed to dlsym %s for layer %s", setup_func.c_str(), layer.c_str());
    435                     return;
    436                 }
    437             }
    438         }
    439     }
    440     // Track this so we only attempt to load these once
    441     layers_loaded_ = true;
    442 }
    443 
    444 } // namespace android
    445