Loader.cpp revision 7773c435bc5da8217433e1b242d3a6712a17b5f7
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** Copyright 2007, The Android Open Source Project 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** Licensed under the Apache License, Version 2.0 (the "License"); 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** you may not use this file except in compliance with the License. 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** You may obtain a copy of the License at 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ** http://www.apache.org/licenses/LICENSE-2.0 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ** 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ** Unless required by applicable law or agreed to in writing, software 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** distributed under the License is distributed on an "AS IS" BASIS, 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** See the License for the specific language governing permissions and 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ** limitations under the License. 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <ctype.h> 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdlib.h> 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdio.h> 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <string.h> 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <errno.h> 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <dlfcn.h> 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <limits.h> 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <cutils/log.h> 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <cutils/properties.h> 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <EGL/egl.h> 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "egldefs.h" 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "glestrace.h" 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "hooks.h" 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "Loader.h" 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// ---------------------------------------------------------------------------- 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace android { 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// ---------------------------------------------------------------------------- 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * EGL drivers are called 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * /system/lib/egl/lib{[EGL|GLESv1_CM|GLESv2] | GLES}_$TAG.so 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ANDROID_SINGLETON_STATIC_INSTANCE( Loader ) 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* This function is called to check whether we run inside the emulator, 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * and if this is the case whether GLES GPU emulation is supported. 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Returned values are: 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * -1 -> not running inside the emulator 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 0 -> running inside the emulator, but GPU emulation not supported 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 1 -> running inside the emulator, GPU emulation is supported 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * through the "emulation" config. 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)checkGlesEmulationStatus(void) 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* We're going to check for the following kernel parameters: 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * qemu=1 -> tells us that we run inside the emulator 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * android.qemu.gles=<number> -> tells us the GLES GPU emulation status 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Note that we will return <number> if we find it. This let us support 67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) * more additionnal emulation modes in the future. 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) */ 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) char prop[PROPERTY_VALUE_MAX]; 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int result = -1; 713240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch 723240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch /* First, check for qemu=1 */ 733240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch property_get("ro.kernel.qemu",prop,"0"); 743240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch if (atoi(prop) != 1) 753240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch return -1; 76a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 773240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch /* We are in the emulator, get GPU status value */ 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) property_get("ro.kernel.qemu.gles",prop,"0"); 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return atoi(prop); 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ---------------------------------------------------------------------------- 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Loader::driver_t::driver_t(void* gles) 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dso[0] = gles; 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i=1 ; i<NELEM(dso) ; i++) 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dso[i] = 0; 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Loader::driver_t::~driver_t() 92{ 93 for (size_t i=0 ; i<NELEM(dso) ; i++) { 94 if (dso[i]) { 95 dlclose(dso[i]); 96 dso[i] = 0; 97 } 98 } 99} 100 101status_t Loader::driver_t::set(void* hnd, int32_t api) 102{ 103 switch (api) { 104 case EGL: 105 dso[0] = hnd; 106 break; 107 case GLESv1_CM: 108 dso[1] = hnd; 109 break; 110 case GLESv2: 111 dso[2] = hnd; 112 break; 113 default: 114 return BAD_INDEX; 115 } 116 return NO_ERROR; 117} 118 119// ---------------------------------------------------------------------------- 120 121Loader::Loader() 122{ 123 char line[256]; 124 char tag[256]; 125 126 /* Special case for GLES emulation */ 127 if (checkGlesEmulationStatus() == 0) { 128 ALOGD("Emulator without GPU support detected. " 129 "Fallback to software renderer."); 130 mDriverTag.setTo("android"); 131 return; 132 } 133 134 /* Otherwise, use egl.cfg */ 135 FILE* cfg = fopen("/system/lib/egl/egl.cfg", "r"); 136 if (cfg == NULL) { 137 // default config 138 ALOGD("egl.cfg not found, using default config"); 139 mDriverTag.setTo("android"); 140 } else { 141 while (fgets(line, 256, cfg)) { 142 int dpy, impl; 143 if (sscanf(line, "%u %u %s", &dpy, &impl, tag) == 3) { 144 //ALOGD(">>> %u %u %s", dpy, impl, tag); 145 // We only load the h/w accelerated implementation 146 if (tag != String8("android")) { 147 mDriverTag = tag; 148 } 149 } 150 } 151 fclose(cfg); 152 } 153} 154 155Loader::~Loader() 156{ 157 GLTrace_stop(); 158} 159 160void* Loader::open(egl_connection_t* cnx) 161{ 162 void* dso; 163 driver_t* hnd = 0; 164 165 char const* tag = mDriverTag.string(); 166 if (tag) { 167 dso = load_driver("GLES", tag, cnx, EGL | GLESv1_CM | GLESv2); 168 if (dso) { 169 hnd = new driver_t(dso); 170 } else { 171 // Always load EGL first 172 dso = load_driver("EGL", tag, cnx, EGL); 173 if (dso) { 174 hnd = new driver_t(dso); 175 // TODO: make this more automated 176 hnd->set( load_driver("GLESv1_CM", tag, cnx, GLESv1_CM), GLESv1_CM ); 177 hnd->set( load_driver("GLESv2", tag, cnx, GLESv2), GLESv2 ); 178 } 179 } 180 } 181 182 LOG_FATAL_IF(!index && !hnd, 183 "couldn't find the default OpenGL ES implementation " 184 "for default display"); 185 186 return (void*)hnd; 187} 188 189status_t Loader::close(void* driver) 190{ 191 driver_t* hnd = (driver_t*)driver; 192 delete hnd; 193 return NO_ERROR; 194} 195 196void Loader::init_api(void* dso, 197 char const * const * api, 198 __eglMustCastToProperFunctionPointerType* curr, 199 getProcAddressType getProcAddress) 200{ 201 const ssize_t SIZE = 256; 202 char scrap[SIZE]; 203 while (*api) { 204 char const * name = *api; 205 __eglMustCastToProperFunctionPointerType f = 206 (__eglMustCastToProperFunctionPointerType)dlsym(dso, name); 207 if (f == NULL) { 208 // couldn't find the entry-point, use eglGetProcAddress() 209 f = getProcAddress(name); 210 } 211 if (f == NULL) { 212 // Try without the OES postfix 213 ssize_t index = ssize_t(strlen(name)) - 3; 214 if ((index>0 && (index<SIZE-1)) && (!strcmp(name+index, "OES"))) { 215 strncpy(scrap, name, index); 216 scrap[index] = 0; 217 f = (__eglMustCastToProperFunctionPointerType)dlsym(dso, scrap); 218 //ALOGD_IF(f, "found <%s> instead", scrap); 219 } 220 } 221 if (f == NULL) { 222 // Try with the OES postfix 223 ssize_t index = ssize_t(strlen(name)) - 3; 224 if (index>0 && strcmp(name+index, "OES")) { 225 snprintf(scrap, SIZE, "%sOES", name); 226 f = (__eglMustCastToProperFunctionPointerType)dlsym(dso, scrap); 227 //ALOGD_IF(f, "found <%s> instead", scrap); 228 } 229 } 230 if (f == NULL) { 231 //ALOGD("%s", name); 232 f = (__eglMustCastToProperFunctionPointerType)gl_unimplemented; 233 234 /* 235 * GL_EXT_debug_label is special, we always report it as 236 * supported, it's handled by GLES_trace. If GLES_trace is not 237 * enabled, then these are no-ops. 238 */ 239 if (!strcmp(name, "glInsertEventMarkerEXT")) { 240 f = (__eglMustCastToProperFunctionPointerType)gl_noop; 241 } else if (!strcmp(name, "glPushGroupMarkerEXT")) { 242 f = (__eglMustCastToProperFunctionPointerType)gl_noop; 243 } else if (!strcmp(name, "glPopGroupMarkerEXT")) { 244 f = (__eglMustCastToProperFunctionPointerType)gl_noop; 245 } 246 } 247 *curr++ = f; 248 api++; 249 } 250} 251 252void *Loader::load_driver(const char* kind, const char *tag, 253 egl_connection_t* cnx, uint32_t mask) 254{ 255 char driver_absolute_path[PATH_MAX]; 256 const char* const search1 = "/vendor/lib/egl/lib%s_%s.so"; 257 const char* const search2 = "/system/lib/egl/lib%s_%s.so"; 258 259 snprintf(driver_absolute_path, PATH_MAX, search1, kind, tag); 260 if (access(driver_absolute_path, R_OK)) { 261 snprintf(driver_absolute_path, PATH_MAX, search2, kind, tag); 262 if (access(driver_absolute_path, R_OK)) { 263 // this happens often, we don't want to log an error 264 return 0; 265 } 266 } 267 268 void* dso = dlopen(driver_absolute_path, RTLD_NOW | RTLD_LOCAL); 269 if (dso == 0) { 270 const char* err = dlerror(); 271 ALOGE("load_driver(%s): %s", driver_absolute_path, err?err:"unknown"); 272 return 0; 273 } 274 275 ALOGD("loaded %s", driver_absolute_path); 276 277 if (mask & EGL) { 278 getProcAddress = (getProcAddressType)dlsym(dso, "eglGetProcAddress"); 279 280 ALOGE_IF(!getProcAddress, 281 "can't find eglGetProcAddress() in %s", driver_absolute_path); 282 283 egl_t* egl = &cnx->egl; 284 __eglMustCastToProperFunctionPointerType* curr = 285 (__eglMustCastToProperFunctionPointerType*)egl; 286 char const * const * api = egl_names; 287 while (*api) { 288 char const * name = *api; 289 __eglMustCastToProperFunctionPointerType f = 290 (__eglMustCastToProperFunctionPointerType)dlsym(dso, name); 291 if (f == NULL) { 292 // couldn't find the entry-point, use eglGetProcAddress() 293 f = getProcAddress(name); 294 if (f == NULL) { 295 f = (__eglMustCastToProperFunctionPointerType)0; 296 } 297 } 298 *curr++ = f; 299 api++; 300 } 301 } 302 303 if (mask & GLESv1_CM) { 304 init_api(dso, gl_names, 305 (__eglMustCastToProperFunctionPointerType*) 306 &cnx->hooks[egl_connection_t::GLESv1_INDEX]->gl, 307 getProcAddress); 308 } 309 310 if (mask & GLESv2) { 311 init_api(dso, gl_names, 312 (__eglMustCastToProperFunctionPointerType*) 313 &cnx->hooks[egl_connection_t::GLESv2_INDEX]->gl, 314 getProcAddress); 315 } 316 317 return dso; 318} 319 320// ---------------------------------------------------------------------------- 321}; // namespace android 322// ---------------------------------------------------------------------------- 323