eglApi.cpp revision 7c0441ac271f4e00a2d63eb3048c037ebffa90b9
1/* 2 ** Copyright 2007, The Android Open Source Project 3 ** 4 ** Licensed under the Apache License, Version 2.0 (the "License"); 5 ** you may not use this file except in compliance with the License. 6 ** You may obtain a copy of the License at 7 ** 8 ** http://www.apache.org/licenses/LICENSE-2.0 9 ** 10 ** Unless required by applicable law or agreed to in writing, software 11 ** distributed under the License is distributed on an "AS IS" BASIS, 12 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 ** See the License for the specific language governing permissions and 14 ** limitations under the License. 15 */ 16 17#include <ctype.h> 18#include <stdlib.h> 19#include <string.h> 20 21#include <hardware/gralloc.h> 22#include <system/window.h> 23 24#include <EGL/egl.h> 25#include <EGL/eglext.h> 26#include <GLES/gl.h> 27#include <GLES/glext.h> 28 29#include <cutils/log.h> 30#include <cutils/atomic.h> 31#include <cutils/properties.h> 32#include <cutils/memory.h> 33 34#include <utils/KeyedVector.h> 35#include <utils/SortedVector.h> 36#include <utils/String8.h> 37 38#include "egl_impl.h" 39#include "egl_tls.h" 40#include "glestrace.h" 41#include "hooks.h" 42 43#include "egl_display.h" 44#include "egl_impl.h" 45#include "egl_object.h" 46#include "egl_tls.h" 47#include "egldefs.h" 48 49using namespace android; 50 51// ---------------------------------------------------------------------------- 52 53#define EGL_VERSION_HW_ANDROID 0x3143 54 55struct extention_map_t { 56 const char* name; 57 __eglMustCastToProperFunctionPointerType address; 58}; 59 60static const extention_map_t sExtentionMap[] = { 61 { "eglLockSurfaceKHR", 62 (__eglMustCastToProperFunctionPointerType)&eglLockSurfaceKHR }, 63 { "eglUnlockSurfaceKHR", 64 (__eglMustCastToProperFunctionPointerType)&eglUnlockSurfaceKHR }, 65 { "eglCreateImageKHR", 66 (__eglMustCastToProperFunctionPointerType)&eglCreateImageKHR }, 67 { "eglDestroyImageKHR", 68 (__eglMustCastToProperFunctionPointerType)&eglDestroyImageKHR }, 69 { "eglGetSystemTimeFrequencyNV", 70 (__eglMustCastToProperFunctionPointerType)&eglGetSystemTimeFrequencyNV }, 71 { "eglGetSystemTimeNV", 72 (__eglMustCastToProperFunctionPointerType)&eglGetSystemTimeNV }, 73}; 74 75// accesses protected by sExtensionMapMutex 76static DefaultKeyedVector<String8, __eglMustCastToProperFunctionPointerType> sGLExtentionMap; 77static int sGLExtentionSlot = 0; 78static pthread_mutex_t sExtensionMapMutex = PTHREAD_MUTEX_INITIALIZER; 79 80static void(*findProcAddress(const char* name, 81 const extention_map_t* map, size_t n))() { 82 for (uint32_t i=0 ; i<n ; i++) { 83 if (!strcmp(name, map[i].name)) { 84 return map[i].address; 85 } 86 } 87 return NULL; 88} 89 90// ---------------------------------------------------------------------------- 91 92namespace android { 93extern void setGLHooksThreadSpecific(gl_hooks_t const *value); 94extern EGLBoolean egl_init_drivers(); 95extern const __eglMustCastToProperFunctionPointerType gExtensionForwarders[MAX_NUMBER_OF_GL_EXTENSIONS]; 96extern int gEGLDebugLevel; 97extern gl_hooks_t gHooksTrace; 98} // namespace android; 99 100// ---------------------------------------------------------------------------- 101 102static inline void clearError() { egl_tls_t::clearError(); } 103static inline EGLContext getContext() { return egl_tls_t::getContext(); } 104 105// ---------------------------------------------------------------------------- 106 107EGLDisplay eglGetDisplay(EGLNativeDisplayType display) 108{ 109 clearError(); 110 111 uint32_t index = uint32_t(display); 112 if (index >= NUM_DISPLAYS) { 113 return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY); 114 } 115 116 if (egl_init_drivers() == EGL_FALSE) { 117 return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY); 118 } 119 120 EGLDisplay dpy = egl_display_t::getFromNativeDisplay(display); 121 return dpy; 122} 123 124// ---------------------------------------------------------------------------- 125// Initialization 126// ---------------------------------------------------------------------------- 127 128EGLBoolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor) 129{ 130 clearError(); 131 132 egl_display_t * const dp = get_display(dpy); 133 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE); 134 135 EGLBoolean res = dp->initialize(major, minor); 136 137 return res; 138} 139 140EGLBoolean eglTerminate(EGLDisplay dpy) 141{ 142 // NOTE: don't unload the drivers b/c some APIs can be called 143 // after eglTerminate() has been called. eglTerminate() only 144 // terminates an EGLDisplay, not a EGL itself. 145 146 clearError(); 147 148 egl_display_t* const dp = get_display(dpy); 149 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE); 150 151 EGLBoolean res = dp->terminate(); 152 153 return res; 154} 155 156// ---------------------------------------------------------------------------- 157// configuration 158// ---------------------------------------------------------------------------- 159 160EGLBoolean eglGetConfigs( EGLDisplay dpy, 161 EGLConfig *configs, 162 EGLint config_size, EGLint *num_config) 163{ 164 clearError(); 165 166 egl_display_t const * const dp = validate_display(dpy); 167 if (!dp) return EGL_FALSE; 168 169 if (num_config==0) { 170 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 171 } 172 173 EGLBoolean res = EGL_FALSE; 174 *num_config = 0; 175 176 egl_connection_t* const cnx = &gEGLImpl; 177 if (cnx->dso) { 178 res = cnx->egl.eglGetConfigs( 179 dp->disp.dpy, configs, config_size, num_config); 180 } 181 182 return res; 183} 184 185EGLBoolean eglChooseConfig( EGLDisplay dpy, const EGLint *attrib_list, 186 EGLConfig *configs, EGLint config_size, 187 EGLint *num_config) 188{ 189 clearError(); 190 191 egl_display_t const * const dp = validate_display(dpy); 192 if (!dp) return EGL_FALSE; 193 194 if (num_config==0) { 195 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 196 } 197 198 EGLBoolean res = EGL_FALSE; 199 *num_config = 0; 200 201 egl_connection_t* const cnx = &gEGLImpl; 202 if (cnx->dso) { 203 res = cnx->egl.eglChooseConfig( 204 dp->disp.dpy, attrib_list, configs, config_size, num_config); 205 } 206 return res; 207} 208 209EGLBoolean eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, 210 EGLint attribute, EGLint *value) 211{ 212 clearError(); 213 214 egl_display_t const* dp = 0; 215 egl_connection_t* cnx = validate_display_config(dpy, config, dp); 216 if (!cnx) return EGL_FALSE; 217 218 return cnx->egl.eglGetConfigAttrib( 219 dp->disp.dpy, config, attribute, value); 220} 221 222// ---------------------------------------------------------------------------- 223// surfaces 224// ---------------------------------------------------------------------------- 225 226EGLSurface eglCreateWindowSurface( EGLDisplay dpy, EGLConfig config, 227 NativeWindowType window, 228 const EGLint *attrib_list) 229{ 230 clearError(); 231 232 egl_display_t const* dp = 0; 233 egl_connection_t* cnx = validate_display_config(dpy, config, dp); 234 if (cnx) { 235 EGLDisplay iDpy = dp->disp.dpy; 236 EGLint format; 237 238 if (native_window_api_connect(window, NATIVE_WINDOW_API_EGL) != OK) { 239 ALOGE("EGLNativeWindowType %p already connected to another API", 240 window); 241 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE); 242 } 243 244 // set the native window's buffers format to match this config 245 if (cnx->egl.eglGetConfigAttrib(iDpy, 246 config, EGL_NATIVE_VISUAL_ID, &format)) { 247 if (format != 0) { 248 int err = native_window_set_buffers_format(window, format); 249 if (err != 0) { 250 ALOGE("error setting native window pixel format: %s (%d)", 251 strerror(-err), err); 252 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL); 253 return setError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE); 254 } 255 } 256 } 257 258 // the EGL spec requires that a new EGLSurface default to swap interval 259 // 1, so explicitly set that on the window here. 260 ANativeWindow* anw = reinterpret_cast<ANativeWindow*>(window); 261 anw->setSwapInterval(anw, 1); 262 263 EGLSurface surface = cnx->egl.eglCreateWindowSurface( 264 iDpy, config, window, attrib_list); 265 if (surface != EGL_NO_SURFACE) { 266 egl_surface_t* s = new egl_surface_t(dpy, config, window, surface, cnx); 267 return s; 268 } 269 270 // EGLSurface creation failed 271 native_window_set_buffers_format(window, 0); 272 native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL); 273 } 274 return EGL_NO_SURFACE; 275} 276 277EGLSurface eglCreatePixmapSurface( EGLDisplay dpy, EGLConfig config, 278 NativePixmapType pixmap, 279 const EGLint *attrib_list) 280{ 281 clearError(); 282 283 egl_display_t const* dp = 0; 284 egl_connection_t* cnx = validate_display_config(dpy, config, dp); 285 if (cnx) { 286 EGLSurface surface = cnx->egl.eglCreatePixmapSurface( 287 dp->disp.dpy, config, pixmap, attrib_list); 288 if (surface != EGL_NO_SURFACE) { 289 egl_surface_t* s = new egl_surface_t(dpy, config, NULL, surface, cnx); 290 return s; 291 } 292 } 293 return EGL_NO_SURFACE; 294} 295 296EGLSurface eglCreatePbufferSurface( EGLDisplay dpy, EGLConfig config, 297 const EGLint *attrib_list) 298{ 299 clearError(); 300 301 egl_display_t const* dp = 0; 302 egl_connection_t* cnx = validate_display_config(dpy, config, dp); 303 if (cnx) { 304 EGLSurface surface = cnx->egl.eglCreatePbufferSurface( 305 dp->disp.dpy, config, attrib_list); 306 if (surface != EGL_NO_SURFACE) { 307 egl_surface_t* s = new egl_surface_t(dpy, config, NULL, surface, cnx); 308 return s; 309 } 310 } 311 return EGL_NO_SURFACE; 312} 313 314EGLBoolean eglDestroySurface(EGLDisplay dpy, EGLSurface surface) 315{ 316 clearError(); 317 318 egl_display_t const * const dp = validate_display(dpy); 319 if (!dp) return EGL_FALSE; 320 321 SurfaceRef _s(dp, surface); 322 if (!_s.get()) 323 return setError(EGL_BAD_SURFACE, EGL_FALSE); 324 325 egl_surface_t * const s = get_surface(surface); 326 EGLBoolean result = s->cnx->egl.eglDestroySurface(dp->disp.dpy, s->surface); 327 if (result == EGL_TRUE) { 328 _s.terminate(); 329 } 330 return result; 331} 332 333EGLBoolean eglQuerySurface( EGLDisplay dpy, EGLSurface surface, 334 EGLint attribute, EGLint *value) 335{ 336 clearError(); 337 338 egl_display_t const * const dp = validate_display(dpy); 339 if (!dp) return EGL_FALSE; 340 341 SurfaceRef _s(dp, surface); 342 if (!_s.get()) 343 return setError(EGL_BAD_SURFACE, EGL_FALSE); 344 345 egl_surface_t const * const s = get_surface(surface); 346 return s->cnx->egl.eglQuerySurface( 347 dp->disp.dpy, s->surface, attribute, value); 348} 349 350void EGLAPI eglBeginFrame(EGLDisplay dpy, EGLSurface surface) { 351 clearError(); 352 353 egl_display_t const * const dp = validate_display(dpy); 354 if (!dp) { 355 return; 356 } 357 358 SurfaceRef _s(dp, surface); 359 if (!_s.get()) { 360 setError(EGL_BAD_SURFACE, EGL_FALSE); 361 return; 362 } 363 364 int64_t timestamp = systemTime(SYSTEM_TIME_MONOTONIC); 365 366 egl_surface_t const * const s = get_surface(surface); 367 native_window_set_buffers_timestamp(s->win.get(), timestamp); 368} 369 370// ---------------------------------------------------------------------------- 371// Contexts 372// ---------------------------------------------------------------------------- 373 374EGLContext eglCreateContext(EGLDisplay dpy, EGLConfig config, 375 EGLContext share_list, const EGLint *attrib_list) 376{ 377 clearError(); 378 379 egl_display_t const* dp = 0; 380 egl_connection_t* cnx = validate_display_config(dpy, config, dp); 381 if (cnx) { 382 if (share_list != EGL_NO_CONTEXT) { 383 egl_context_t* const c = get_context(share_list); 384 share_list = c->context; 385 } 386 EGLContext context = cnx->egl.eglCreateContext( 387 dp->disp.dpy, config, share_list, attrib_list); 388 if (context != EGL_NO_CONTEXT) { 389 // figure out if it's a GLESv1 or GLESv2 390 int version = 0; 391 if (attrib_list) { 392 while (*attrib_list != EGL_NONE) { 393 GLint attr = *attrib_list++; 394 GLint value = *attrib_list++; 395 if (attr == EGL_CONTEXT_CLIENT_VERSION) { 396 if (value == 1) { 397 version = egl_connection_t::GLESv1_INDEX; 398 } else if (value == 2) { 399 version = egl_connection_t::GLESv2_INDEX; 400 } 401 } 402 }; 403 } 404 egl_context_t* c = new egl_context_t(dpy, context, config, cnx, version); 405#if EGL_TRACE 406 if (gEGLDebugLevel > 0) 407 GLTrace_eglCreateContext(version, c); 408#endif 409 return c; 410 } 411 } 412 return EGL_NO_CONTEXT; 413} 414 415EGLBoolean eglDestroyContext(EGLDisplay dpy, EGLContext ctx) 416{ 417 clearError(); 418 419 egl_display_t const * const dp = validate_display(dpy); 420 if (!dp) 421 return EGL_FALSE; 422 423 ContextRef _c(dp, ctx); 424 if (!_c.get()) 425 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 426 427 egl_context_t * const c = get_context(ctx); 428 EGLBoolean result = c->cnx->egl.eglDestroyContext(dp->disp.dpy, c->context); 429 if (result == EGL_TRUE) { 430 _c.terminate(); 431 } 432 return result; 433} 434 435EGLBoolean eglMakeCurrent( EGLDisplay dpy, EGLSurface draw, 436 EGLSurface read, EGLContext ctx) 437{ 438 clearError(); 439 440 egl_display_t const * const dp = get_display(dpy); 441 if (!dp) return setError(EGL_BAD_DISPLAY, EGL_FALSE); 442 443 // If ctx is not EGL_NO_CONTEXT, read is not EGL_NO_SURFACE, or draw is not 444 // EGL_NO_SURFACE, then an EGL_NOT_INITIALIZED error is generated if dpy is 445 // a valid but uninitialized display. 446 if ( (ctx != EGL_NO_CONTEXT) || (read != EGL_NO_SURFACE) || 447 (draw != EGL_NO_SURFACE) ) { 448 if (!dp->isReady()) return setError(EGL_NOT_INITIALIZED, EGL_FALSE); 449 } 450 451 // get a reference to the object passed in 452 ContextRef _c(dp, ctx); 453 SurfaceRef _d(dp, draw); 454 SurfaceRef _r(dp, read); 455 456 // validate the context (if not EGL_NO_CONTEXT) 457 if ((ctx != EGL_NO_CONTEXT) && !_c.get()) { 458 // EGL_NO_CONTEXT is valid 459 return EGL_FALSE; 460 } 461 462 // these are the underlying implementation's object 463 EGLContext impl_ctx = EGL_NO_CONTEXT; 464 EGLSurface impl_draw = EGL_NO_SURFACE; 465 EGLSurface impl_read = EGL_NO_SURFACE; 466 467 // these are our objects structs passed in 468 egl_context_t * c = NULL; 469 egl_surface_t const * d = NULL; 470 egl_surface_t const * r = NULL; 471 472 // these are the current objects structs 473 egl_context_t * cur_c = get_context(getContext()); 474 475 if (ctx != EGL_NO_CONTEXT) { 476 c = get_context(ctx); 477 impl_ctx = c->context; 478 } else { 479 // no context given, use the implementation of the current context 480 if (cur_c == NULL) { 481 // no current context 482 if (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE) { 483 // calling eglMakeCurrent( ..., !=0, !=0, EGL_NO_CONTEXT); 484 return setError(EGL_BAD_MATCH, EGL_FALSE); 485 } 486 // not an error, there is just no current context. 487 return EGL_TRUE; 488 } 489 } 490 491 // retrieve the underlying implementation's draw EGLSurface 492 if (draw != EGL_NO_SURFACE) { 493 d = get_surface(draw); 494 impl_draw = d->surface; 495 } 496 497 // retrieve the underlying implementation's read EGLSurface 498 if (read != EGL_NO_SURFACE) { 499 r = get_surface(read); 500 impl_read = r->surface; 501 } 502 503 504 EGLBoolean result = const_cast<egl_display_t*>(dp)->makeCurrent(c, cur_c, 505 draw, read, ctx, 506 impl_draw, impl_read, impl_ctx); 507 508 if (result == EGL_TRUE) { 509 if (c) { 510 setGLHooksThreadSpecific(c->cnx->hooks[c->version]); 511 egl_tls_t::setContext(ctx); 512#if EGL_TRACE 513 if (gEGLDebugLevel > 0) 514 GLTrace_eglMakeCurrent(c->version, c->cnx->hooks[c->version], ctx); 515#endif 516 _c.acquire(); 517 _r.acquire(); 518 _d.acquire(); 519 } else { 520 setGLHooksThreadSpecific(&gHooksNoContext); 521 egl_tls_t::setContext(EGL_NO_CONTEXT); 522 } 523 } else { 524 // this will ALOGE the error 525 result = setError(c->cnx->egl.eglGetError(), EGL_FALSE); 526 } 527 return result; 528} 529 530 531EGLBoolean eglQueryContext( EGLDisplay dpy, EGLContext ctx, 532 EGLint attribute, EGLint *value) 533{ 534 clearError(); 535 536 egl_display_t const * const dp = validate_display(dpy); 537 if (!dp) return EGL_FALSE; 538 539 ContextRef _c(dp, ctx); 540 if (!_c.get()) return setError(EGL_BAD_CONTEXT, EGL_FALSE); 541 542 egl_context_t * const c = get_context(ctx); 543 return c->cnx->egl.eglQueryContext( 544 dp->disp.dpy, c->context, attribute, value); 545 546} 547 548EGLContext eglGetCurrentContext(void) 549{ 550 // could be called before eglInitialize(), but we wouldn't have a context 551 // then, and this function would correctly return EGL_NO_CONTEXT. 552 553 clearError(); 554 555 EGLContext ctx = getContext(); 556 return ctx; 557} 558 559EGLSurface eglGetCurrentSurface(EGLint readdraw) 560{ 561 // could be called before eglInitialize(), but we wouldn't have a context 562 // then, and this function would correctly return EGL_NO_SURFACE. 563 564 clearError(); 565 566 EGLContext ctx = getContext(); 567 if (ctx) { 568 egl_context_t const * const c = get_context(ctx); 569 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE); 570 switch (readdraw) { 571 case EGL_READ: return c->read; 572 case EGL_DRAW: return c->draw; 573 default: return setError(EGL_BAD_PARAMETER, EGL_NO_SURFACE); 574 } 575 } 576 return EGL_NO_SURFACE; 577} 578 579EGLDisplay eglGetCurrentDisplay(void) 580{ 581 // could be called before eglInitialize(), but we wouldn't have a context 582 // then, and this function would correctly return EGL_NO_DISPLAY. 583 584 clearError(); 585 586 EGLContext ctx = getContext(); 587 if (ctx) { 588 egl_context_t const * const c = get_context(ctx); 589 if (!c) return setError(EGL_BAD_CONTEXT, EGL_NO_SURFACE); 590 return c->dpy; 591 } 592 return EGL_NO_DISPLAY; 593} 594 595EGLBoolean eglWaitGL(void) 596{ 597 clearError(); 598 599 egl_connection_t* const cnx = &gEGLImpl; 600 if (!cnx->dso) 601 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 602 603 return cnx->egl.eglWaitGL(); 604} 605 606EGLBoolean eglWaitNative(EGLint engine) 607{ 608 clearError(); 609 610 egl_connection_t* const cnx = &gEGLImpl; 611 if (!cnx->dso) 612 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 613 614 return cnx->egl.eglWaitNative(engine); 615} 616 617EGLint eglGetError(void) 618{ 619 EGLint err = EGL_SUCCESS; 620 egl_connection_t* const cnx = &gEGLImpl; 621 if (cnx->dso) { 622 err = cnx->egl.eglGetError(); 623 } 624 if (err == EGL_SUCCESS) { 625 err = egl_tls_t::getError(); 626 } 627 return err; 628} 629 630__eglMustCastToProperFunctionPointerType eglGetProcAddress(const char *procname) 631{ 632 // eglGetProcAddress() could be the very first function called 633 // in which case we must make sure we've initialized ourselves, this 634 // happens the first time egl_get_display() is called. 635 636 clearError(); 637 638 if (egl_init_drivers() == EGL_FALSE) { 639 setError(EGL_BAD_PARAMETER, NULL); 640 return NULL; 641 } 642 643 // The EGL_ANDROID_blob_cache extension should not be exposed to 644 // applications. It is used internally by the Android EGL layer. 645 if (!strcmp(procname, "eglSetBlobCacheFuncsANDROID")) { 646 return NULL; 647 } 648 649 __eglMustCastToProperFunctionPointerType addr; 650 addr = findProcAddress(procname, sExtentionMap, NELEM(sExtentionMap)); 651 if (addr) return addr; 652 653 654 // this protects accesses to sGLExtentionMap and sGLExtentionSlot 655 pthread_mutex_lock(&sExtensionMapMutex); 656 657 /* 658 * Since eglGetProcAddress() is not associated to anything, it needs 659 * to return a function pointer that "works" regardless of what 660 * the current context is. 661 * 662 * For this reason, we return a "forwarder", a small stub that takes 663 * care of calling the function associated with the context 664 * currently bound. 665 * 666 * We first look for extensions we've already resolved, if we're seeing 667 * this extension for the first time, we go through all our 668 * implementations and call eglGetProcAddress() and record the 669 * result in the appropriate implementation hooks and return the 670 * address of the forwarder corresponding to that hook set. 671 * 672 */ 673 674 const String8 name(procname); 675 addr = sGLExtentionMap.valueFor(name); 676 const int slot = sGLExtentionSlot; 677 678 ALOGE_IF(slot >= MAX_NUMBER_OF_GL_EXTENSIONS, 679 "no more slots for eglGetProcAddress(\"%s\")", 680 procname); 681 682#if EGL_TRACE 683 gl_hooks_t *debugHooks = GLTrace_getGLHooks(); 684#endif 685 686 if (!addr && (slot < MAX_NUMBER_OF_GL_EXTENSIONS)) { 687 bool found = false; 688 689 egl_connection_t* const cnx = &gEGLImpl; 690 if (cnx->dso && cnx->egl.eglGetProcAddress) { 691 found = true; 692 // Extensions are independent of the bound context 693 cnx->hooks[egl_connection_t::GLESv1_INDEX]->ext.extensions[slot] = 694 cnx->hooks[egl_connection_t::GLESv2_INDEX]->ext.extensions[slot] = 695#if EGL_TRACE 696 debugHooks->ext.extensions[slot] = 697 gHooksTrace.ext.extensions[slot] = 698#endif 699 cnx->egl.eglGetProcAddress(procname); 700 } 701 702 if (found) { 703 addr = gExtensionForwarders[slot]; 704 sGLExtentionMap.add(name, addr); 705 sGLExtentionSlot++; 706 } 707 } 708 709 pthread_mutex_unlock(&sExtensionMapMutex); 710 return addr; 711} 712 713EGLBoolean eglSwapBuffers(EGLDisplay dpy, EGLSurface draw) 714{ 715 clearError(); 716 717 egl_display_t const * const dp = validate_display(dpy); 718 if (!dp) return EGL_FALSE; 719 720 SurfaceRef _s(dp, draw); 721 if (!_s.get()) 722 return setError(EGL_BAD_SURFACE, EGL_FALSE); 723 724#if EGL_TRACE 725 if (gEGLDebugLevel > 0) 726 GLTrace_eglSwapBuffers(dpy, draw); 727#endif 728 729 egl_surface_t const * const s = get_surface(draw); 730 return s->cnx->egl.eglSwapBuffers(dp->disp.dpy, s->surface); 731} 732 733EGLBoolean eglCopyBuffers( EGLDisplay dpy, EGLSurface surface, 734 NativePixmapType target) 735{ 736 clearError(); 737 738 egl_display_t const * const dp = validate_display(dpy); 739 if (!dp) return EGL_FALSE; 740 741 SurfaceRef _s(dp, surface); 742 if (!_s.get()) 743 return setError(EGL_BAD_SURFACE, EGL_FALSE); 744 745 egl_surface_t const * const s = get_surface(surface); 746 return s->cnx->egl.eglCopyBuffers(dp->disp.dpy, s->surface, target); 747} 748 749const char* eglQueryString(EGLDisplay dpy, EGLint name) 750{ 751 clearError(); 752 753 egl_display_t const * const dp = validate_display(dpy); 754 if (!dp) return (const char *) NULL; 755 756 switch (name) { 757 case EGL_VENDOR: 758 return dp->getVendorString(); 759 case EGL_VERSION: 760 return dp->getVersionString(); 761 case EGL_EXTENSIONS: 762 return dp->getExtensionString(); 763 case EGL_CLIENT_APIS: 764 return dp->getClientApiString(); 765 case EGL_VERSION_HW_ANDROID: 766 return dp->disp.queryString.version; 767 } 768 return setError(EGL_BAD_PARAMETER, (const char *)0); 769} 770 771 772// ---------------------------------------------------------------------------- 773// EGL 1.1 774// ---------------------------------------------------------------------------- 775 776EGLBoolean eglSurfaceAttrib( 777 EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value) 778{ 779 clearError(); 780 781 egl_display_t const * const dp = validate_display(dpy); 782 if (!dp) return EGL_FALSE; 783 784 SurfaceRef _s(dp, surface); 785 if (!_s.get()) 786 return setError(EGL_BAD_SURFACE, EGL_FALSE); 787 788 egl_surface_t const * const s = get_surface(surface); 789 if (s->cnx->egl.eglSurfaceAttrib) { 790 return s->cnx->egl.eglSurfaceAttrib( 791 dp->disp.dpy, s->surface, attribute, value); 792 } 793 return setError(EGL_BAD_SURFACE, EGL_FALSE); 794} 795 796EGLBoolean eglBindTexImage( 797 EGLDisplay dpy, EGLSurface surface, EGLint buffer) 798{ 799 clearError(); 800 801 egl_display_t const * const dp = validate_display(dpy); 802 if (!dp) return EGL_FALSE; 803 804 SurfaceRef _s(dp, surface); 805 if (!_s.get()) 806 return setError(EGL_BAD_SURFACE, EGL_FALSE); 807 808 egl_surface_t const * const s = get_surface(surface); 809 if (s->cnx->egl.eglBindTexImage) { 810 return s->cnx->egl.eglBindTexImage( 811 dp->disp.dpy, s->surface, buffer); 812 } 813 return setError(EGL_BAD_SURFACE, EGL_FALSE); 814} 815 816EGLBoolean eglReleaseTexImage( 817 EGLDisplay dpy, EGLSurface surface, EGLint buffer) 818{ 819 clearError(); 820 821 egl_display_t const * const dp = validate_display(dpy); 822 if (!dp) return EGL_FALSE; 823 824 SurfaceRef _s(dp, surface); 825 if (!_s.get()) 826 return setError(EGL_BAD_SURFACE, EGL_FALSE); 827 828 egl_surface_t const * const s = get_surface(surface); 829 if (s->cnx->egl.eglReleaseTexImage) { 830 return s->cnx->egl.eglReleaseTexImage( 831 dp->disp.dpy, s->surface, buffer); 832 } 833 return setError(EGL_BAD_SURFACE, EGL_FALSE); 834} 835 836EGLBoolean eglSwapInterval(EGLDisplay dpy, EGLint interval) 837{ 838 clearError(); 839 840 egl_display_t const * const dp = validate_display(dpy); 841 if (!dp) return EGL_FALSE; 842 843 EGLBoolean res = EGL_TRUE; 844 egl_connection_t* const cnx = &gEGLImpl; 845 if (cnx->dso && cnx->egl.eglSwapInterval) { 846 res = cnx->egl.eglSwapInterval(dp->disp.dpy, interval); 847 } 848 849 return res; 850} 851 852 853// ---------------------------------------------------------------------------- 854// EGL 1.2 855// ---------------------------------------------------------------------------- 856 857EGLBoolean eglWaitClient(void) 858{ 859 clearError(); 860 861 egl_connection_t* const cnx = &gEGLImpl; 862 if (!cnx->dso) 863 return setError(EGL_BAD_CONTEXT, EGL_FALSE); 864 865 EGLBoolean res; 866 if (cnx->egl.eglWaitClient) { 867 res = cnx->egl.eglWaitClient(); 868 } else { 869 res = cnx->egl.eglWaitGL(); 870 } 871 return res; 872} 873 874EGLBoolean eglBindAPI(EGLenum api) 875{ 876 clearError(); 877 878 if (egl_init_drivers() == EGL_FALSE) { 879 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 880 } 881 882 // bind this API on all EGLs 883 EGLBoolean res = EGL_TRUE; 884 egl_connection_t* const cnx = &gEGLImpl; 885 if (cnx->dso && cnx->egl.eglBindAPI) { 886 res = cnx->egl.eglBindAPI(api); 887 } 888 return res; 889} 890 891EGLenum eglQueryAPI(void) 892{ 893 clearError(); 894 895 if (egl_init_drivers() == EGL_FALSE) { 896 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 897 } 898 899 egl_connection_t* const cnx = &gEGLImpl; 900 if (cnx->dso && cnx->egl.eglQueryAPI) { 901 return cnx->egl.eglQueryAPI(); 902 } 903 904 // or, it can only be OpenGL ES 905 return EGL_OPENGL_ES_API; 906} 907 908EGLBoolean eglReleaseThread(void) 909{ 910 clearError(); 911 912 // If there is context bound to the thread, release it 913 egl_display_t::loseCurrent(get_context(getContext())); 914 915 egl_connection_t* const cnx = &gEGLImpl; 916 if (cnx->dso && cnx->egl.eglReleaseThread) { 917 cnx->egl.eglReleaseThread(); 918 } 919 920 egl_tls_t::clearTLS(); 921#if EGL_TRACE 922 if (gEGLDebugLevel > 0) 923 GLTrace_eglReleaseThread(); 924#endif 925 return EGL_TRUE; 926} 927 928EGLSurface eglCreatePbufferFromClientBuffer( 929 EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, 930 EGLConfig config, const EGLint *attrib_list) 931{ 932 clearError(); 933 934 egl_display_t const* dp = 0; 935 egl_connection_t* cnx = validate_display_config(dpy, config, dp); 936 if (!cnx) return EGL_FALSE; 937 if (cnx->egl.eglCreatePbufferFromClientBuffer) { 938 return cnx->egl.eglCreatePbufferFromClientBuffer( 939 dp->disp.dpy, buftype, buffer, config, attrib_list); 940 } 941 return setError(EGL_BAD_CONFIG, EGL_NO_SURFACE); 942} 943 944// ---------------------------------------------------------------------------- 945// EGL_EGLEXT_VERSION 3 946// ---------------------------------------------------------------------------- 947 948EGLBoolean eglLockSurfaceKHR(EGLDisplay dpy, EGLSurface surface, 949 const EGLint *attrib_list) 950{ 951 clearError(); 952 953 egl_display_t const * const dp = validate_display(dpy); 954 if (!dp) return EGL_FALSE; 955 956 SurfaceRef _s(dp, surface); 957 if (!_s.get()) 958 return setError(EGL_BAD_SURFACE, EGL_FALSE); 959 960 egl_surface_t const * const s = get_surface(surface); 961 if (s->cnx->egl.eglLockSurfaceKHR) { 962 return s->cnx->egl.eglLockSurfaceKHR( 963 dp->disp.dpy, s->surface, attrib_list); 964 } 965 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 966} 967 968EGLBoolean eglUnlockSurfaceKHR(EGLDisplay dpy, EGLSurface surface) 969{ 970 clearError(); 971 972 egl_display_t const * const dp = validate_display(dpy); 973 if (!dp) return EGL_FALSE; 974 975 SurfaceRef _s(dp, surface); 976 if (!_s.get()) 977 return setError(EGL_BAD_SURFACE, EGL_FALSE); 978 979 egl_surface_t const * const s = get_surface(surface); 980 if (s->cnx->egl.eglUnlockSurfaceKHR) { 981 return s->cnx->egl.eglUnlockSurfaceKHR(dp->disp.dpy, s->surface); 982 } 983 return setError(EGL_BAD_DISPLAY, EGL_FALSE); 984} 985 986EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, 987 EGLClientBuffer buffer, const EGLint *attrib_list) 988{ 989 clearError(); 990 991 egl_display_t const * const dp = validate_display(dpy); 992 if (!dp) return EGL_NO_IMAGE_KHR; 993 994 ContextRef _c(dp, ctx); 995 egl_context_t * const c = _c.get(); 996 997 EGLImageKHR result = EGL_NO_IMAGE_KHR; 998 egl_connection_t* const cnx = &gEGLImpl; 999 if (cnx->dso && cnx->egl.eglCreateImageKHR) { 1000 result = cnx->egl.eglCreateImageKHR( 1001 dp->disp.dpy, 1002 c ? c->context : EGL_NO_CONTEXT, 1003 target, buffer, attrib_list); 1004 } 1005 return result; 1006} 1007 1008EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR img) 1009{ 1010 clearError(); 1011 1012 egl_display_t const * const dp = validate_display(dpy); 1013 if (!dp) return EGL_FALSE; 1014 1015 egl_connection_t* const cnx = &gEGLImpl; 1016 if (cnx->dso && cnx->egl.eglDestroyImageKHR) { 1017 cnx->egl.eglDestroyImageKHR(dp->disp.dpy, img); 1018 } 1019 return EGL_TRUE; 1020} 1021 1022// ---------------------------------------------------------------------------- 1023// EGL_EGLEXT_VERSION 5 1024// ---------------------------------------------------------------------------- 1025 1026 1027EGLSyncKHR eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list) 1028{ 1029 clearError(); 1030 1031 egl_display_t const * const dp = validate_display(dpy); 1032 if (!dp) return EGL_NO_SYNC_KHR; 1033 1034 EGLSyncKHR result = EGL_NO_SYNC_KHR; 1035 egl_connection_t* const cnx = &gEGLImpl; 1036 if (cnx->dso && cnx->egl.eglCreateSyncKHR) { 1037 result = cnx->egl.eglCreateSyncKHR(dp->disp.dpy, type, attrib_list); 1038 } 1039 return result; 1040} 1041 1042EGLBoolean eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync) 1043{ 1044 clearError(); 1045 1046 egl_display_t const * const dp = validate_display(dpy); 1047 if (!dp) return EGL_FALSE; 1048 1049 EGLBoolean result = EGL_FALSE; 1050 egl_connection_t* const cnx = &gEGLImpl; 1051 if (cnx->dso && cnx->egl.eglDestroySyncKHR) { 1052 result = cnx->egl.eglDestroySyncKHR(dp->disp.dpy, sync); 1053 } 1054 return result; 1055} 1056 1057EGLint eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, 1058 EGLint flags, EGLTimeKHR timeout) 1059{ 1060 clearError(); 1061 1062 egl_display_t const * const dp = validate_display(dpy); 1063 if (!dp) return EGL_FALSE; 1064 1065 EGLBoolean result = EGL_FALSE; 1066 egl_connection_t* const cnx = &gEGLImpl; 1067 if (cnx->dso && cnx->egl.eglClientWaitSyncKHR) { 1068 result = cnx->egl.eglClientWaitSyncKHR( 1069 dp->disp.dpy, sync, flags, timeout); 1070 } 1071 return result; 1072} 1073 1074EGLBoolean eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync, 1075 EGLint attribute, EGLint *value) 1076{ 1077 clearError(); 1078 1079 egl_display_t const * const dp = validate_display(dpy); 1080 if (!dp) return EGL_FALSE; 1081 1082 EGLBoolean result = EGL_FALSE; 1083 egl_connection_t* const cnx = &gEGLImpl; 1084 if (cnx->dso && cnx->egl.eglGetSyncAttribKHR) { 1085 result = cnx->egl.eglGetSyncAttribKHR( 1086 dp->disp.dpy, sync, attribute, value); 1087 } 1088 return result; 1089} 1090 1091// ---------------------------------------------------------------------------- 1092// ANDROID extensions 1093// ---------------------------------------------------------------------------- 1094 1095/* ANDROID extensions entry-point go here */ 1096 1097// ---------------------------------------------------------------------------- 1098// NVIDIA extensions 1099// ---------------------------------------------------------------------------- 1100EGLuint64NV eglGetSystemTimeFrequencyNV() 1101{ 1102 clearError(); 1103 1104 if (egl_init_drivers() == EGL_FALSE) { 1105 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1106 } 1107 1108 EGLuint64NV ret = 0; 1109 egl_connection_t* const cnx = &gEGLImpl; 1110 1111 if (cnx->dso && cnx->egl.eglGetSystemTimeFrequencyNV) { 1112 return cnx->egl.eglGetSystemTimeFrequencyNV(); 1113 } 1114 1115 return setErrorQuiet(EGL_BAD_DISPLAY, 0); 1116} 1117 1118EGLuint64NV eglGetSystemTimeNV() 1119{ 1120 clearError(); 1121 1122 if (egl_init_drivers() == EGL_FALSE) { 1123 return setError(EGL_BAD_PARAMETER, EGL_FALSE); 1124 } 1125 1126 EGLuint64NV ret = 0; 1127 egl_connection_t* const cnx = &gEGLImpl; 1128 1129 if (cnx->dso && cnx->egl.eglGetSystemTimeNV) { 1130 return cnx->egl.eglGetSystemTimeNV(); 1131 } 1132 1133 return setErrorQuiet(EGL_BAD_DISPLAY, 0); 1134} 1135