1 /* 2 * Copyright (C) 2011 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 #include "eglDisplay.h" 17 #include "HostConnection.h" 18 #include <dlfcn.h> 19 20 #include <string> 21 22 static const int systemEGLVersionMajor = 1; 23 static const int systemEGLVersionMinor = 4; 24 static const char systemEGLVendor[] = "Google Android emulator"; 25 26 // list of extensions supported by this EGL implementation 27 // NOTE that each extension name should be suffixed with space 28 static const char systemStaticEGLExtensions[] = 29 "EGL_ANDROID_image_native_buffer " 30 "EGL_KHR_fence_sync " 31 "EGL_KHR_image_base " 32 "EGL_KHR_gl_texture_2d_image "; 33 34 // extensions to add dynamically depending on host-side support 35 static const char kDynamicEGLExtNativeSync[] = "EGL_ANDROID_native_fence_sync "; 36 static const char kDynamicEGLExtWaitSync[] = "EGL_KHR_wait_sync "; 37 38 static void *s_gles_lib = NULL; 39 static void *s_gles2_lib = NULL; 40 41 // The following function will be called when we (libEGL) 42 // gets unloaded 43 // At this point we want to unload the gles libraries we 44 // might have loaded during initialization 45 static void __attribute__ ((destructor)) do_on_unload(void) 46 { 47 if (s_gles_lib) { 48 dlclose(s_gles_lib); 49 } 50 51 if (s_gles2_lib) { 52 dlclose(s_gles2_lib); 53 } 54 } 55 56 eglDisplay::eglDisplay() : 57 m_initialized(false), 58 m_major(0), 59 m_minor(0), 60 m_hostRendererVersion(0), 61 m_numConfigs(0), 62 m_numConfigAttribs(0), 63 m_attribs(DefaultKeyedVector<EGLint, EGLint>(ATTRIBUTE_NONE)), 64 m_configs(NULL), 65 m_gles_iface(NULL), 66 m_gles2_iface(NULL), 67 m_versionString(NULL), 68 m_vendorString(NULL), 69 m_extensionString(NULL) 70 { 71 pthread_mutex_init(&m_lock, NULL); 72 pthread_mutex_init(&m_ctxLock, NULL); 73 pthread_mutex_init(&m_surfaceLock, NULL); 74 } 75 76 eglDisplay::~eglDisplay() 77 { 78 terminate(); 79 pthread_mutex_destroy(&m_lock); 80 pthread_mutex_destroy(&m_ctxLock); 81 pthread_mutex_destroy(&m_surfaceLock); 82 } 83 84 #if PLATFORM_SDK_VERSION >= 26 85 #define PARTITION "/vendor" 86 #else 87 #define PARTITION "/system" 88 #endif 89 90 bool eglDisplay::initialize(EGLClient_eglInterface *eglIface) 91 { 92 pthread_mutex_lock(&m_lock); 93 if (!m_initialized) { 94 95 // 96 // load GLES client API 97 // 98 #if __LP64__ 99 m_gles_iface = loadGLESClientAPI(PARTITION "/lib64/egl/libGLESv1_CM_emulation.so", 100 eglIface, 101 &s_gles_lib); 102 #else 103 m_gles_iface = loadGLESClientAPI(PARTITION "/lib/egl/libGLESv1_CM_emulation.so", 104 eglIface, 105 &s_gles_lib); 106 #endif 107 if (!m_gles_iface) { 108 pthread_mutex_unlock(&m_lock); 109 ALOGE("Failed to load gles1 iface"); 110 return false; 111 } 112 113 #ifdef WITH_GLES2 114 #if __LP64__ 115 m_gles2_iface = loadGLESClientAPI(PARTITION "/lib64/egl/libGLESv2_emulation.so", 116 eglIface, 117 &s_gles2_lib); 118 #else 119 m_gles2_iface = loadGLESClientAPI(PARTITION "/lib/egl/libGLESv2_emulation.so", 120 eglIface, 121 &s_gles2_lib); 122 #endif 123 // Note that if loading gles2 failed, we can still run with no 124 // GLES2 support, having GLES2 is not mandatory. 125 #endif 126 127 // 128 // establish connection with the host 129 // 130 HostConnection *hcon = HostConnection::get(); 131 if (!hcon) { 132 pthread_mutex_unlock(&m_lock); 133 ALOGE("Failed to establish connection with the host\n"); 134 return false; 135 } 136 hcon->setGrallocOnly(false); 137 138 // 139 // get renderControl encoder instance 140 // 141 renderControl_encoder_context_t *rcEnc = hcon->rcEncoder(); 142 if (!rcEnc) { 143 pthread_mutex_unlock(&m_lock); 144 ALOGE("Failed to get renderControl encoder instance"); 145 return false; 146 } 147 148 // 149 // Query host reneder and EGL version 150 // 151 m_hostRendererVersion = rcEnc->rcGetRendererVersion(rcEnc); 152 EGLint status = rcEnc->rcGetEGLVersion(rcEnc, &m_major, &m_minor); 153 if (status != EGL_TRUE) { 154 // host EGL initialization failed !! 155 pthread_mutex_unlock(&m_lock); 156 return false; 157 } 158 159 // 160 // Take minimum version beween what we support and what the host support 161 // 162 if (m_major > systemEGLVersionMajor) { 163 m_major = systemEGLVersionMajor; 164 m_minor = systemEGLVersionMinor; 165 } 166 else if (m_major == systemEGLVersionMajor && 167 m_minor > systemEGLVersionMinor) { 168 m_minor = systemEGLVersionMinor; 169 } 170 171 // 172 // Query the host for the set of configs 173 // 174 m_numConfigs = rcEnc->rcGetNumConfigs(rcEnc, (uint32_t*)&m_numConfigAttribs); 175 if (m_numConfigs <= 0 || m_numConfigAttribs <= 0) { 176 // just sanity check - should never happen 177 pthread_mutex_unlock(&m_lock); 178 return false; 179 } 180 181 uint32_t nInts = m_numConfigAttribs * (m_numConfigs + 1); 182 EGLint tmp_buf[nInts]; 183 m_configs = new EGLint[nInts-m_numConfigAttribs]; 184 if (!m_configs) { 185 pthread_mutex_unlock(&m_lock); 186 return false; 187 } 188 189 //EGLint n = rcEnc->rcGetConfigs(rcEnc, nInts*sizeof(EGLint), m_configs); 190 EGLint n = rcEnc->rcGetConfigs(rcEnc, nInts*sizeof(EGLint), (GLuint*)tmp_buf); 191 if (n != m_numConfigs) { 192 pthread_mutex_unlock(&m_lock); 193 return false; 194 } 195 196 //Fill the attributes vector. 197 //The first m_numConfigAttribs values of tmp_buf are the actual attributes enums. 198 for (int i=0; i<m_numConfigAttribs; i++) { 199 m_attribs.add(tmp_buf[i], i); 200 } 201 202 //Copy the actual configs data to m_configs 203 memcpy(m_configs, tmp_buf + m_numConfigAttribs, m_numConfigs*m_numConfigAttribs*sizeof(EGLint)); 204 205 m_initialized = true; 206 } 207 pthread_mutex_unlock(&m_lock); 208 209 processConfigs(); 210 211 return true; 212 } 213 214 void eglDisplay::processConfigs() 215 { 216 for (intptr_t i=0; i<m_numConfigs; i++) { 217 EGLConfig config = (EGLConfig)i; 218 //Setup the EGL_NATIVE_VISUAL_ID attribute 219 PixelFormat format; 220 if (getConfigNativePixelFormat(config, &format)) { 221 setConfigAttrib(config, EGL_NATIVE_VISUAL_ID, format); 222 } 223 } 224 } 225 226 void eglDisplay::terminate() 227 { 228 pthread_mutex_lock(&m_lock); 229 if (m_initialized) { 230 // Cannot use the for loop in the following code because 231 // eglDestroyContext may erase elements. 232 EGLContextSet::iterator ctxIte = m_contexts.begin(); 233 while (ctxIte != m_contexts.end()) { 234 EGLContextSet::iterator ctxToDelete = ctxIte; 235 ctxIte ++; 236 eglDestroyContext(static_cast<EGLDisplay>(this), *ctxToDelete); 237 } 238 EGLSurfaceSet::iterator surfaceIte = m_surfaces.begin(); 239 while (surfaceIte != m_surfaces.end()) { 240 EGLSurfaceSet::iterator surfaceToDelete = surfaceIte; 241 surfaceIte ++; 242 eglDestroySurface(static_cast<EGLDisplay>(this), *surfaceToDelete); 243 } 244 m_initialized = false; 245 delete [] m_configs; 246 m_configs = NULL; 247 248 if (m_versionString) { 249 free(m_versionString); 250 m_versionString = NULL; 251 } 252 if (m_vendorString) { 253 free(m_vendorString); 254 m_vendorString = NULL; 255 } 256 if (m_extensionString) { 257 free(m_extensionString); 258 m_extensionString = NULL; 259 } 260 } 261 pthread_mutex_unlock(&m_lock); 262 } 263 264 EGLClient_glesInterface *eglDisplay::loadGLESClientAPI(const char *libName, 265 EGLClient_eglInterface *eglIface, 266 void **libHandle) 267 { 268 void *lib = dlopen(libName, RTLD_NOW); 269 if (!lib) { 270 ALOGE("Failed to dlopen %s", libName); 271 return NULL; 272 } 273 274 init_emul_gles_t init_gles_func = (init_emul_gles_t)dlsym(lib,"init_emul_gles"); 275 if (!init_gles_func) { 276 ALOGE("Failed to find init_emul_gles"); 277 dlclose((void*)lib); 278 return NULL; 279 } 280 281 *libHandle = lib; 282 return (*init_gles_func)(eglIface); 283 } 284 285 static char *queryHostEGLString(EGLint name) 286 { 287 HostConnection *hcon = HostConnection::get(); 288 if (hcon) { 289 renderControl_encoder_context_t *rcEnc = hcon->rcEncoder(); 290 if (rcEnc) { 291 int n = rcEnc->rcQueryEGLString(rcEnc, name, NULL, 0); 292 if (n < 0) { 293 // allocate space for the string. 294 char *str = (char *)malloc(-n); 295 n = rcEnc->rcQueryEGLString(rcEnc, name, str, -n); 296 if (n > 0) { 297 return str; 298 } 299 300 free(str); 301 } 302 } 303 } 304 305 return NULL; 306 } 307 308 static bool findExtInList(const char* token, int tokenlen, const char* list) 309 { 310 const char* p = list; 311 while (*p != '\0') { 312 const char* q = strchr(p, ' '); 313 if (q == NULL) { 314 /* should not happen, list must be space-terminated */ 315 break; 316 } 317 if (tokenlen == (q - p) && !memcmp(token, p, tokenlen)) { 318 return true; /* found it */ 319 } 320 p = q+1; 321 } 322 return false; /* not found */ 323 } 324 325 static char *buildExtensionString() 326 { 327 //Query host extension string 328 char *hostExt = queryHostEGLString(EGL_EXTENSIONS); 329 if (!hostExt || (hostExt[1] == '\0')) { 330 // no extensions on host - only static extension list supported 331 return strdup(systemStaticEGLExtensions); 332 } 333 334 int n = strlen(hostExt); 335 if (n > 0) { 336 char *initialEGLExts; 337 char *finalEGLExts; 338 339 HostConnection *hcon = HostConnection::get(); 340 // If we got here, we must have succeeded in queryHostEGLString 341 // and we thus should have a valid connection 342 assert(hcon); 343 344 asprintf(&initialEGLExts,"%s%s", systemStaticEGLExtensions, hostExt); 345 346 std::string dynamicEGLExtensions; 347 348 if (hcon->rcEncoder()->hasNativeSync() && 349 !strstr(initialEGLExts, kDynamicEGLExtNativeSync)) { 350 dynamicEGLExtensions += kDynamicEGLExtNativeSync; 351 352 if (hcon->rcEncoder()->hasNativeSyncV3()) { 353 dynamicEGLExtensions += kDynamicEGLExtWaitSync; 354 } 355 } 356 357 asprintf(&finalEGLExts, "%s%s", initialEGLExts, dynamicEGLExtensions.c_str()); 358 359 free((char*)hostExt); 360 return finalEGLExts; 361 } 362 else { 363 free((char*)hostExt); 364 return strdup(systemStaticEGLExtensions); 365 } 366 } 367 368 const char *eglDisplay::queryString(EGLint name) 369 { 370 if (name == EGL_CLIENT_APIS) { 371 return "OpenGL_ES"; 372 } 373 else if (name == EGL_VERSION) { 374 pthread_mutex_lock(&m_lock); 375 if (m_versionString) { 376 pthread_mutex_unlock(&m_lock); 377 return m_versionString; 378 } 379 380 // build version string 381 asprintf(&m_versionString, "%d.%d", m_major, m_minor); 382 pthread_mutex_unlock(&m_lock); 383 384 return m_versionString; 385 } 386 else if (name == EGL_VENDOR) { 387 pthread_mutex_lock(&m_lock); 388 if (m_vendorString) { 389 pthread_mutex_unlock(&m_lock); 390 return m_vendorString; 391 } 392 393 // build vendor string 394 const char *hostVendor = queryHostEGLString(EGL_VENDOR); 395 396 if (hostVendor) { 397 asprintf(&m_vendorString, "%s Host: %s", 398 systemEGLVendor, hostVendor); 399 free((char*)hostVendor); 400 } 401 else { 402 m_vendorString = (char *)systemEGLVendor; 403 } 404 pthread_mutex_unlock(&m_lock); 405 406 return m_vendorString; 407 } 408 else if (name == EGL_EXTENSIONS) { 409 pthread_mutex_lock(&m_lock); 410 if (m_extensionString) { 411 pthread_mutex_unlock(&m_lock); 412 return m_extensionString; 413 } 414 415 // build extension string 416 m_extensionString = buildExtensionString(); 417 pthread_mutex_unlock(&m_lock); 418 419 return m_extensionString; 420 } 421 else { 422 ALOGE("[%s] Unknown name %d\n", __FUNCTION__, name); 423 return NULL; 424 } 425 } 426 427 /* To get the value of attribute <a> of config <c> use the following formula: 428 * value = *(m_configs + (int)c*m_numConfigAttribs + a); 429 */ 430 EGLBoolean eglDisplay::getAttribValue(EGLConfig config, EGLint attribIdx, EGLint * value) 431 { 432 if (attribIdx == ATTRIBUTE_NONE) 433 { 434 ALOGE("[%s] Bad attribute idx\n", __FUNCTION__); 435 return EGL_FALSE; 436 } 437 *value = *(m_configs + (intptr_t)config*m_numConfigAttribs + attribIdx); 438 return EGL_TRUE; 439 } 440 441 #define EGL_COLOR_COMPONENT_TYPE_EXT 0x3339 442 #define EGL_COLOR_COMPONENT_TYPE_FIXED_EXT 0x333A 443 444 EGLBoolean eglDisplay::getConfigAttrib(EGLConfig config, EGLint attrib, EGLint * value) 445 { 446 if (attrib == EGL_FRAMEBUFFER_TARGET_ANDROID) { 447 *value = EGL_TRUE; 448 return EGL_TRUE; 449 } 450 if (attrib == EGL_COVERAGE_SAMPLES_NV || 451 attrib == EGL_COVERAGE_BUFFERS_NV) { 452 *value = 0; 453 return EGL_TRUE; 454 } 455 if (attrib == EGL_DEPTH_ENCODING_NV) { 456 *value = EGL_DEPTH_ENCODING_NONE_NV; 457 return EGL_TRUE; 458 } 459 if (attrib == EGL_COLOR_COMPONENT_TYPE_EXT) { 460 *value = EGL_COLOR_COMPONENT_TYPE_FIXED_EXT; 461 return EGL_TRUE; 462 } 463 //Though it seems that valueFor() is thread-safe, we don't take chanses 464 pthread_mutex_lock(&m_lock); 465 EGLBoolean ret = getAttribValue(config, m_attribs.valueFor(attrib), value); 466 pthread_mutex_unlock(&m_lock); 467 return ret; 468 } 469 470 void eglDisplay::dumpConfig(EGLConfig config) 471 { 472 EGLint value = 0; 473 DBG("^^^^^^^^^^ dumpConfig %d ^^^^^^^^^^^^^^^^^^", (int)config); 474 for (int i=0; i<m_numConfigAttribs; i++) { 475 getAttribValue(config, i, &value); 476 DBG("{%d}[%d] %d\n", (int)config, i, value); 477 } 478 } 479 480 /* To set the value of attribute <a> of config <c> use the following formula: 481 * *(m_configs + (int)c*m_numConfigAttribs + a) = value; 482 */ 483 EGLBoolean eglDisplay::setAttribValue(EGLConfig config, EGLint attribIdx, EGLint value) 484 { 485 if (attribIdx == ATTRIBUTE_NONE) 486 { 487 ALOGE("[%s] Bad attribute idx\n", __FUNCTION__); 488 return EGL_FALSE; 489 } 490 *(m_configs + (intptr_t)config*m_numConfigAttribs + attribIdx) = value; 491 return EGL_TRUE; 492 } 493 494 EGLBoolean eglDisplay::setConfigAttrib(EGLConfig config, EGLint attrib, EGLint value) 495 { 496 //Though it seems that valueFor() is thread-safe, we don't take chanses 497 pthread_mutex_lock(&m_lock); 498 EGLBoolean ret = setAttribValue(config, m_attribs.valueFor(attrib), value); 499 pthread_mutex_unlock(&m_lock); 500 return ret; 501 } 502 503 504 EGLBoolean eglDisplay::getConfigNativePixelFormat(EGLConfig config, PixelFormat * format) 505 { 506 EGLint redSize, blueSize, greenSize, alphaSize; 507 508 if ( !(getAttribValue(config, m_attribs.valueFor(EGL_RED_SIZE), &redSize) && 509 getAttribValue(config, m_attribs.valueFor(EGL_BLUE_SIZE), &blueSize) && 510 getAttribValue(config, m_attribs.valueFor(EGL_GREEN_SIZE), &greenSize) && 511 getAttribValue(config, m_attribs.valueFor(EGL_ALPHA_SIZE), &alphaSize)) ) 512 { 513 ALOGE("Couldn't find value for one of the pixel format attributes"); 514 return EGL_FALSE; 515 } 516 517 //calculate the GL internal format 518 if ((redSize==8)&&(greenSize==8)&&(blueSize==8)&&(alphaSize==8)) *format = PIXEL_FORMAT_RGBA_8888; //XXX: BGR? 519 else if ((redSize==8)&&(greenSize==8)&&(blueSize==8)&&(alphaSize==0)) *format = PIXEL_FORMAT_RGBX_8888; //XXX or PIXEL_FORMAT_RGB_888 520 else if ((redSize==5)&&(greenSize==6)&&(blueSize==5)&&(alphaSize==0)) *format = PIXEL_FORMAT_RGB_565; 521 else if ((redSize==5)&&(greenSize==5)&&(blueSize==5)&&(alphaSize==1)) *format = PIXEL_FORMAT_RGBA_5551; 522 else if ((redSize==4)&&(greenSize==4)&&(blueSize==4)&&(alphaSize==4)) *format = PIXEL_FORMAT_RGBA_4444; 523 else { 524 return EGL_FALSE; 525 } 526 return EGL_TRUE; 527 } 528 EGLBoolean eglDisplay::getConfigGLPixelFormat(EGLConfig config, GLenum * format) 529 { 530 EGLint redSize, blueSize, greenSize, alphaSize; 531 532 if ( !(getAttribValue(config, m_attribs.valueFor(EGL_RED_SIZE), &redSize) && 533 getAttribValue(config, m_attribs.valueFor(EGL_BLUE_SIZE), &blueSize) && 534 getAttribValue(config, m_attribs.valueFor(EGL_GREEN_SIZE), &greenSize) && 535 getAttribValue(config, m_attribs.valueFor(EGL_ALPHA_SIZE), &alphaSize)) ) 536 { 537 ALOGE("Couldn't find value for one of the pixel format attributes"); 538 return EGL_FALSE; 539 } 540 541 //calculate the GL internal format 542 if ((redSize == greenSize) && (redSize == blueSize) && 543 ((redSize == 8) || (redSize == 16) || (redSize == 32))) 544 { 545 if (alphaSize == 0) *format = GL_RGB; 546 else *format = GL_RGBA; 547 } 548 else if ((redSize==5)&&(greenSize==6)&&(blueSize==5)&&(alphaSize==0)) *format = GL_RGB565_OES; 549 else if ((redSize==5)&&(greenSize==5)&&(blueSize==5)&&(alphaSize==1)) *format = GL_RGB5_A1_OES; 550 else if ((redSize==4)&&(greenSize==4)&&(blueSize==4)&&(alphaSize==4)) *format = GL_RGBA4_OES; 551 else return EGL_FALSE; 552 553 return EGL_TRUE; 554 } 555 556 void eglDisplay::onCreateContext(EGLContext ctx) { 557 pthread_mutex_lock(&m_ctxLock); 558 m_contexts.insert(ctx); 559 pthread_mutex_unlock(&m_ctxLock); 560 } 561 562 void eglDisplay::onCreateSurface(EGLSurface surface) { 563 pthread_mutex_lock(&m_surfaceLock); 564 m_surfaces.insert(surface); 565 pthread_mutex_unlock(&m_surfaceLock); 566 } 567 568 void eglDisplay::onDestroyContext(EGLContext ctx) { 569 pthread_mutex_lock(&m_ctxLock); 570 m_contexts.erase(ctx); 571 pthread_mutex_unlock(&m_ctxLock); 572 } 573 574 void eglDisplay::onDestroySurface(EGLSurface surface) { 575 pthread_mutex_lock(&m_surfaceLock); 576 m_surfaces.erase(surface); 577 pthread_mutex_unlock(&m_surfaceLock); 578 } 579 580 bool eglDisplay::isContext(EGLContext ctx) { 581 pthread_mutex_lock(&m_ctxLock); 582 bool res = m_contexts.find(ctx) != m_contexts.end(); 583 pthread_mutex_unlock(&m_ctxLock); 584 return res; 585 } 586 587 bool eglDisplay::isSurface(EGLSurface surface) { 588 pthread_mutex_lock(&m_surfaceLock); 589 bool res = m_surfaces.find(surface) != m_surfaces.end(); 590 pthread_mutex_unlock(&m_surfaceLock); 591 return res; 592 } 593