1 // Copyright 2016 The SwiftShader Authors. All Rights Reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // libEGL.cpp: Implements the exported EGL functions. 16 17 #include "main.h" 18 #include "Display.h" 19 #include "Surface.hpp" 20 #include "Texture.hpp" 21 #include "Context.hpp" 22 #include "common/Image.hpp" 23 #include "common/debug.h" 24 #include "Common/Version.h" 25 26 #if defined(__ANDROID__) 27 #include <system/window.h> 28 #elif defined(__linux__) 29 #include "Main/libX11.hpp" 30 #endif 31 32 #include <algorithm> 33 #include <string.h> 34 35 using namespace egl; 36 37 static bool validateDisplay(egl::Display *display) 38 { 39 if(display == EGL_NO_DISPLAY) 40 { 41 return error(EGL_BAD_DISPLAY, false); 42 } 43 44 if(!display->isInitialized()) 45 { 46 return error(EGL_NOT_INITIALIZED, false); 47 } 48 49 return true; 50 } 51 52 static bool validateConfig(egl::Display *display, EGLConfig config) 53 { 54 if(!validateDisplay(display)) 55 { 56 return false; 57 } 58 59 if(!display->isValidConfig(config)) 60 { 61 return error(EGL_BAD_CONFIG, false); 62 } 63 64 return true; 65 } 66 67 static bool validateContext(egl::Display *display, egl::Context *context) 68 { 69 if(!validateDisplay(display)) 70 { 71 return false; 72 } 73 74 if(!display->isValidContext(context)) 75 { 76 return error(EGL_BAD_CONTEXT, false); 77 } 78 79 return true; 80 } 81 82 static bool validateSurface(egl::Display *display, egl::Surface *surface) 83 { 84 if(!validateDisplay(display)) 85 { 86 return false; 87 } 88 89 if(!display->isValidSurface(surface)) 90 { 91 return error(EGL_BAD_SURFACE, false); 92 } 93 94 return true; 95 } 96 97 namespace egl 98 { 99 EGLint GetError(void) 100 { 101 TRACE("()"); 102 103 EGLint error = egl::getCurrentError(); 104 105 if(error != EGL_SUCCESS) 106 { 107 egl::setCurrentError(EGL_SUCCESS); 108 } 109 110 return error; 111 } 112 113 EGLDisplay GetDisplay(EGLNativeDisplayType display_id) 114 { 115 TRACE("(EGLNativeDisplayType display_id = %p)", display_id); 116 117 if(display_id != EGL_DEFAULT_DISPLAY) 118 { 119 // FIXME: Check if display_id is the default display 120 } 121 122 #if defined(__linux__) && !defined(__ANDROID__) 123 if(!libX11) 124 { 125 return success(HEADLESS_DISPLAY); 126 } 127 #endif 128 129 return success(PRIMARY_DISPLAY); // We only support the default display 130 } 131 132 EGLBoolean Initialize(EGLDisplay dpy, EGLint *major, EGLint *minor) 133 { 134 TRACE("(EGLDisplay dpy = %p, EGLint *major = %p, EGLint *minor = %p)", 135 dpy, major, minor); 136 137 egl::Display *display = egl::Display::get(dpy); 138 139 if(!display) 140 { 141 return error(EGL_BAD_DISPLAY, EGL_FALSE); 142 } 143 144 if(!display->initialize()) 145 { 146 return error(EGL_NOT_INITIALIZED, EGL_FALSE); 147 } 148 149 if(major) *major = 1; 150 if(minor) *minor = 4; 151 152 return success(EGL_TRUE); 153 } 154 155 EGLBoolean Terminate(EGLDisplay dpy) 156 { 157 TRACE("(EGLDisplay dpy = %p)", dpy); 158 159 if(dpy == EGL_NO_DISPLAY) 160 { 161 return error(EGL_BAD_DISPLAY, EGL_FALSE); 162 } 163 164 egl::Display *display = egl::Display::get(dpy); 165 166 display->terminate(); 167 168 return success(EGL_TRUE); 169 } 170 171 const char *QueryString(EGLDisplay dpy, EGLint name) 172 { 173 TRACE("(EGLDisplay dpy = %p, EGLint name = %d)", dpy, name); 174 175 if(dpy == EGL_NO_DISPLAY && name == EGL_EXTENSIONS) 176 { 177 return success( 178 "EGL_KHR_client_get_all_proc_addresses " 179 #if defined(__linux__) && !defined(__ANDROID__) 180 "EGL_KHR_platform_gbm " 181 "EGL_KHR_platform_x11 " 182 #endif 183 "EGL_EXT_client_extensions " 184 "EGL_EXT_platform_base"); 185 } 186 187 egl::Display *display = egl::Display::get(dpy); 188 189 if(!validateDisplay(display)) 190 { 191 return nullptr; 192 } 193 194 switch(name) 195 { 196 case EGL_CLIENT_APIS: 197 return success("OpenGL_ES"); 198 case EGL_EXTENSIONS: 199 return success("EGL_KHR_create_context " 200 "EGL_KHR_get_all_proc_addresses " 201 "EGL_KHR_gl_texture_2D_image " 202 "EGL_KHR_gl_texture_cubemap_image " 203 "EGL_KHR_gl_renderbuffer_image " 204 "EGL_KHR_fence_sync " 205 "EGL_KHR_image_base " 206 "EGL_KHR_surfaceless_context " 207 "EGL_ANGLE_iosurface_client_buffer " 208 "EGL_ANDROID_framebuffer_target " 209 "EGL_ANDROID_recordable"); 210 case EGL_VENDOR: 211 return success("Google Inc."); 212 case EGL_VERSION: 213 return success("1.4 SwiftShader " VERSION_STRING); 214 } 215 216 return error(EGL_BAD_PARAMETER, (const char*)nullptr); 217 } 218 219 EGLBoolean GetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config) 220 { 221 TRACE("(EGLDisplay dpy = %p, EGLConfig *configs = %p, " 222 "EGLint config_size = %d, EGLint *num_config = %p)", 223 dpy, configs, config_size, num_config); 224 225 egl::Display *display = egl::Display::get(dpy); 226 227 if(!validateDisplay(display)) 228 { 229 return EGL_FALSE; 230 } 231 232 if(!num_config) 233 { 234 return error(EGL_BAD_PARAMETER, EGL_FALSE); 235 } 236 237 const EGLint attribList[] = {EGL_NONE}; 238 239 if(!display->getConfigs(configs, attribList, config_size, num_config)) 240 { 241 return error(EGL_BAD_ATTRIBUTE, EGL_FALSE); 242 } 243 244 return success(EGL_TRUE); 245 } 246 247 EGLBoolean ChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config) 248 { 249 TRACE("(EGLDisplay dpy = %p, const EGLint *attrib_list = %p, " 250 "EGLConfig *configs = %p, EGLint config_size = %d, EGLint *num_config = %p)", 251 dpy, attrib_list, configs, config_size, num_config); 252 253 egl::Display *display = egl::Display::get(dpy); 254 255 if(!validateDisplay(display)) 256 { 257 return EGL_FALSE; 258 } 259 260 if(!num_config) 261 { 262 return error(EGL_BAD_PARAMETER, EGL_FALSE); 263 } 264 265 const EGLint attribList[] = {EGL_NONE}; 266 267 if(!attrib_list) 268 { 269 attrib_list = attribList; 270 } 271 272 if(!display->getConfigs(configs, attrib_list, config_size, num_config)) 273 { 274 return error(EGL_BAD_ATTRIBUTE, EGL_FALSE); 275 } 276 277 return success(EGL_TRUE); 278 } 279 280 EGLBoolean GetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value) 281 { 282 TRACE("(EGLDisplay dpy = %p, EGLConfig config = %p, EGLint attribute = %d, EGLint *value = %p)", 283 dpy, config, attribute, value); 284 285 egl::Display *display = egl::Display::get(dpy); 286 287 if(!validateConfig(display, config)) 288 { 289 return EGL_FALSE; 290 } 291 292 if(!display->getConfigAttrib(config, attribute, value)) 293 { 294 return error(EGL_BAD_ATTRIBUTE, EGL_FALSE); 295 } 296 297 return success(EGL_TRUE); 298 } 299 300 EGLSurface CreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType window, const EGLint *attrib_list) 301 { 302 TRACE("(EGLDisplay dpy = %p, EGLConfig config = %p, EGLNativeWindowType win = %p, " 303 "const EGLint *attrib_list = %p)", dpy, config, window, attrib_list); 304 305 egl::Display *display = egl::Display::get(dpy); 306 307 if(!validateConfig(display, config)) 308 { 309 return EGL_NO_SURFACE; 310 } 311 312 if(!display->isValidWindow(window)) 313 { 314 return error(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE); 315 } 316 317 return display->createWindowSurface(window, config, attrib_list); 318 } 319 320 EGLSurface CreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list) 321 { 322 TRACE("(EGLDisplay dpy = %p, EGLConfig config = %p, const EGLint *attrib_list = %p)", 323 dpy, config, attrib_list); 324 325 egl::Display *display = egl::Display::get(dpy); 326 327 if(!validateConfig(display, config)) 328 { 329 return EGL_NO_SURFACE; 330 } 331 332 return display->createPBufferSurface(config, attrib_list); 333 } 334 335 EGLSurface CreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list) 336 { 337 TRACE("(EGLDisplay dpy = %p, EGLConfig config = %p, EGLNativePixmapType pixmap = %p, " 338 "const EGLint *attrib_list = %p)", dpy, config, pixmap, attrib_list); 339 340 egl::Display *display = egl::Display::get(dpy); 341 342 if(!validateConfig(display, config)) 343 { 344 return EGL_NO_SURFACE; 345 } 346 347 UNIMPLEMENTED(); // FIXME 348 349 return success(EGL_NO_SURFACE); 350 } 351 352 EGLBoolean DestroySurface(EGLDisplay dpy, EGLSurface surface) 353 { 354 TRACE("(EGLDisplay dpy = %p, EGLSurface surface = %p)", dpy, surface); 355 356 egl::Display *display = egl::Display::get(dpy); 357 egl::Surface *eglSurface = static_cast<egl::Surface*>(surface); 358 359 if(!validateSurface(display, eglSurface)) 360 { 361 return EGL_FALSE; 362 } 363 364 if(surface == EGL_NO_SURFACE) 365 { 366 return error(EGL_BAD_SURFACE, EGL_FALSE); 367 } 368 369 display->destroySurface((egl::Surface*)surface); 370 371 return success(EGL_TRUE); 372 } 373 374 EGLBoolean QuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value) 375 { 376 TRACE("(EGLDisplay dpy = %p, EGLSurface surface = %p, EGLint attribute = %d, EGLint *value = %p)", 377 dpy, surface, attribute, value); 378 379 egl::Display *display = egl::Display::get(dpy); 380 egl::Surface *eglSurface = (egl::Surface*)surface; 381 382 if(!validateSurface(display, eglSurface)) 383 { 384 return EGL_FALSE; 385 } 386 387 if(surface == EGL_NO_SURFACE) 388 { 389 return error(EGL_BAD_SURFACE, EGL_FALSE); 390 } 391 392 switch(attribute) 393 { 394 case EGL_VG_ALPHA_FORMAT: 395 UNIMPLEMENTED(); // FIXME 396 break; 397 case EGL_VG_COLORSPACE: 398 UNIMPLEMENTED(); // FIXME 399 break; 400 case EGL_CONFIG_ID: 401 *value = eglSurface->getConfigID(); 402 break; 403 case EGL_HEIGHT: 404 *value = eglSurface->getHeight(); 405 break; 406 case EGL_HORIZONTAL_RESOLUTION: 407 UNIMPLEMENTED(); // FIXME 408 break; 409 case EGL_LARGEST_PBUFFER: 410 if(eglSurface->isPBufferSurface()) // For a window or pixmap surface, the contents of *value are not modified. 411 { 412 *value = eglSurface->getLargestPBuffer(); 413 } 414 break; 415 case EGL_MIPMAP_TEXTURE: 416 UNIMPLEMENTED(); // FIXME 417 break; 418 case EGL_MIPMAP_LEVEL: 419 UNIMPLEMENTED(); // FIXME 420 break; 421 case EGL_MULTISAMPLE_RESOLVE: 422 UNIMPLEMENTED(); // FIXME 423 break; 424 case EGL_PIXEL_ASPECT_RATIO: 425 *value = eglSurface->getPixelAspectRatio(); 426 break; 427 case EGL_RENDER_BUFFER: 428 *value = eglSurface->getRenderBuffer(); 429 break; 430 case EGL_SWAP_BEHAVIOR: 431 *value = eglSurface->getSwapBehavior(); 432 break; 433 case EGL_TEXTURE_FORMAT: 434 *value = eglSurface->getTextureFormat(); 435 break; 436 case EGL_TEXTURE_TARGET: 437 *value = eglSurface->getTextureTarget(); 438 break; 439 case EGL_VERTICAL_RESOLUTION: 440 UNIMPLEMENTED(); // FIXME 441 break; 442 case EGL_WIDTH: 443 *value = eglSurface->getWidth(); 444 break; 445 default: 446 return error(EGL_BAD_ATTRIBUTE, EGL_FALSE); 447 } 448 449 return success(EGL_TRUE); 450 } 451 452 EGLBoolean BindAPI(EGLenum api) 453 { 454 TRACE("(EGLenum api = 0x%X)", api); 455 456 switch(api) 457 { 458 case EGL_OPENGL_API: 459 case EGL_OPENVG_API: 460 return error(EGL_BAD_PARAMETER, EGL_FALSE); // Not supported by this implementation 461 case EGL_OPENGL_ES_API: 462 break; 463 default: 464 return error(EGL_BAD_PARAMETER, EGL_FALSE); 465 } 466 467 egl::setCurrentAPI(api); 468 469 return success(EGL_TRUE); 470 } 471 472 EGLenum QueryAPI(void) 473 { 474 TRACE("()"); 475 476 EGLenum API = egl::getCurrentAPI(); 477 478 return success(API); 479 } 480 481 EGLBoolean WaitClient(void) 482 { 483 TRACE("()"); 484 485 // eglWaitClient is ignored if there is no current EGL rendering context for the current rendering API. 486 egl::Context *context = egl::getCurrentContext(); 487 488 if(context) 489 { 490 context->finish(); 491 } 492 493 return success(EGL_TRUE); 494 } 495 496 EGLBoolean ReleaseThread(void) 497 { 498 TRACE("()"); 499 500 detachThread(); 501 502 return EGL_TRUE; // success() is not called here because it would re-allocate thread-local storage. 503 } 504 505 EGLSurface CreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list) 506 { 507 TRACE("(EGLDisplay dpy = %p, EGLenum buftype = 0x%X, EGLClientBuffer buffer = %p, " 508 "EGLConfig config = %p, const EGLint *attrib_list = %p)", 509 dpy, buftype, buffer, config, attrib_list); 510 511 switch(buftype) 512 { 513 case EGL_IOSURFACE_ANGLE: 514 { 515 egl::Display *display = egl::Display::get(dpy); 516 517 if(!validateConfig(display, config)) 518 { 519 return EGL_NO_SURFACE; 520 } 521 522 return display->createPBufferSurface(config, attrib_list, buffer); 523 } 524 case EGL_OPENVG_IMAGE: 525 UNIMPLEMENTED(); 526 return error(EGL_BAD_PARAMETER, EGL_NO_SURFACE); 527 default: 528 return error(EGL_BAD_PARAMETER, EGL_NO_SURFACE); 529 }; 530 } 531 532 EGLBoolean SurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value) 533 { 534 TRACE("(EGLDisplay dpy = %p, EGLSurface surface = %p, EGLint attribute = %d, EGLint value = %d)", 535 dpy, surface, attribute, value); 536 537 egl::Display *display = egl::Display::get(dpy); 538 egl::Surface *eglSurface = static_cast<egl::Surface*>(surface); 539 540 if(!validateSurface(display, eglSurface)) 541 { 542 return EGL_FALSE; 543 } 544 545 switch(attribute) 546 { 547 case EGL_SWAP_BEHAVIOR: 548 if(value == EGL_BUFFER_PRESERVED) 549 { 550 if(!(eglSurface->getSurfaceType() & EGL_SWAP_BEHAVIOR_PRESERVED_BIT)) 551 { 552 return error(EGL_BAD_MATCH, EGL_FALSE); 553 } 554 } 555 else if(value != EGL_BUFFER_DESTROYED) 556 { 557 return error(EGL_BAD_PARAMETER, EGL_FALSE); 558 } 559 eglSurface->setSwapBehavior(value); 560 break; 561 default: 562 UNIMPLEMENTED(); // FIXME 563 } 564 565 return success(EGL_TRUE); 566 } 567 568 EGLBoolean BindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer) 569 { 570 TRACE("(EGLDisplay dpy = %p, EGLSurface surface = %p, EGLint buffer = %d)", dpy, surface, buffer); 571 572 egl::Display *display = egl::Display::get(dpy); 573 egl::Surface *eglSurface = static_cast<egl::Surface*>(surface); 574 575 if(!validateSurface(display, eglSurface)) 576 { 577 return EGL_FALSE; 578 } 579 580 if(buffer != EGL_BACK_BUFFER) 581 { 582 return error(EGL_BAD_PARAMETER, EGL_FALSE); 583 } 584 585 if(surface == EGL_NO_SURFACE || eglSurface->isWindowSurface()) 586 { 587 return error(EGL_BAD_SURFACE, EGL_FALSE); 588 } 589 590 if(eglSurface->getBoundTexture()) 591 { 592 return error(EGL_BAD_ACCESS, EGL_FALSE); 593 } 594 595 if(eglSurface->getTextureFormat() == EGL_NO_TEXTURE) 596 { 597 return error(EGL_BAD_MATCH, EGL_FALSE); 598 } 599 600 egl::Context *context = egl::getCurrentContext(); 601 602 if(context) 603 { 604 context->bindTexImage(eglSurface); 605 } 606 607 return success(EGL_TRUE); 608 } 609 610 EGLBoolean ReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer) 611 { 612 TRACE("(EGLDisplay dpy = %p, EGLSurface surface = %p, EGLint buffer = %d)", dpy, surface, buffer); 613 614 egl::Display *display = egl::Display::get(dpy); 615 egl::Surface *eglSurface = static_cast<egl::Surface*>(surface); 616 617 if(!validateSurface(display, eglSurface)) 618 { 619 return EGL_FALSE; 620 } 621 622 if(buffer != EGL_BACK_BUFFER) 623 { 624 return error(EGL_BAD_PARAMETER, EGL_FALSE); 625 } 626 627 if(surface == EGL_NO_SURFACE || eglSurface->isWindowSurface()) 628 { 629 return error(EGL_BAD_SURFACE, EGL_FALSE); 630 } 631 632 if(eglSurface->getTextureFormat() == EGL_NO_TEXTURE) 633 { 634 return error(EGL_BAD_MATCH, EGL_FALSE); 635 } 636 637 egl::Texture *texture = eglSurface->getBoundTexture(); 638 639 if(texture) 640 { 641 texture->releaseTexImage(); 642 } 643 644 return success(EGL_TRUE); 645 } 646 647 EGLBoolean SwapInterval(EGLDisplay dpy, EGLint interval) 648 { 649 TRACE("(EGLDisplay dpy = %p, EGLint interval = %d)", dpy, interval); 650 651 egl::Display *display = egl::Display::get(dpy); 652 egl::Context *context = egl::getCurrentContext(); 653 654 if(!validateContext(display, context)) 655 { 656 return EGL_FALSE; 657 } 658 659 egl::Surface *draw_surface = static_cast<egl::Surface*>(egl::getCurrentDrawSurface()); 660 661 if(!draw_surface) 662 { 663 return error(EGL_BAD_SURFACE, EGL_FALSE); 664 } 665 666 draw_surface->setSwapInterval(interval); 667 668 return success(EGL_TRUE); 669 } 670 671 EGLContext CreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list) 672 { 673 TRACE("(EGLDisplay dpy = %p, EGLConfig config = %p, EGLContext share_context = %p, " 674 "const EGLint *attrib_list = %p)", dpy, config, share_context, attrib_list); 675 676 EGLint majorVersion = 1; 677 EGLint minorVersion = 0; 678 679 if(attrib_list) 680 { 681 for(const EGLint* attribute = attrib_list; attribute[0] != EGL_NONE; attribute += 2) 682 { 683 switch(attribute[0]) 684 { 685 case EGL_CONTEXT_MAJOR_VERSION_KHR: // This token is an alias for EGL_CONTEXT_CLIENT_VERSION 686 majorVersion = attribute[1]; 687 break; 688 case EGL_CONTEXT_MINOR_VERSION_KHR: 689 minorVersion = attribute[1]; 690 break; 691 case EGL_CONTEXT_FLAGS_KHR: 692 switch(attribute[1]) 693 { 694 case EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR: 695 // According to the EGL_KHR_create_context spec: 696 // "Khronos is still defining the expected and required features of debug contexts, so 697 // implementations are currently free to implement "debug contexts" with little or no debug 698 // functionality. However, OpenGL and OpenGL ES implementations supporting the GL_KHR_debug 699 // extension should enable it when this bit is set." 700 break; 701 case EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR: 702 case EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR: 703 // These bits are for OpenGL contexts only, not OpenGL ES contexts 704 return error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT); 705 default: 706 return error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT); 707 } 708 break; 709 case EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR: 710 switch(attribute[1]) 711 { 712 case EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR: 713 case EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR: 714 // These bits are for OpenGL contexts only, not OpenGL ES contexts 715 return error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT); 716 default: 717 return error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT); 718 } 719 break; 720 case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR: 721 switch(attribute[1]) 722 { 723 case EGL_NO_RESET_NOTIFICATION_KHR: 724 case EGL_LOSE_CONTEXT_ON_RESET_KHR: 725 // These bits are for OpenGL contexts only, not OpenGL ES contexts 726 return error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT); 727 default: 728 return error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT); 729 } 730 break; 731 default: 732 return error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT); 733 } 734 } 735 } 736 737 switch(majorVersion) 738 { 739 case 1: 740 if(minorVersion != 0 && minorVersion != 1) 741 { 742 // 1.X: Only OpenGL ES 1.0 and 1.1 contexts are supported 743 return error(EGL_BAD_MATCH, EGL_NO_CONTEXT); 744 } 745 break; 746 case 2: 747 case 3: 748 if(minorVersion != 0) 749 { 750 // 2.X and 3.X: Only OpenGL ES 2.0 and 3.0 contexts are currently supported 751 return error(EGL_BAD_MATCH, EGL_NO_CONTEXT); 752 } 753 break; 754 default: 755 return error(EGL_BAD_MATCH, EGL_NO_CONTEXT); 756 } 757 758 egl::Display *display = egl::Display::get(dpy); 759 egl::Context *shareContext = static_cast<egl::Context*>(share_context); 760 761 if(!validateConfig(display, config)) 762 { 763 return EGL_NO_CONTEXT; 764 } 765 766 if(shareContext && shareContext->getClientVersion() != majorVersion) 767 { 768 return error(EGL_BAD_CONTEXT, EGL_NO_CONTEXT); 769 } 770 771 return display->createContext(config, shareContext, majorVersion); 772 } 773 774 EGLBoolean DestroyContext(EGLDisplay dpy, EGLContext ctx) 775 { 776 TRACE("(EGLDisplay dpy = %p, EGLContext ctx = %p)", dpy, ctx); 777 778 egl::Display *display = egl::Display::get(dpy); 779 egl::Context *context = static_cast<egl::Context*>(ctx); 780 781 if(!validateContext(display, context)) 782 { 783 return EGL_FALSE; 784 } 785 786 if(ctx == EGL_NO_CONTEXT) 787 { 788 return error(EGL_BAD_CONTEXT, EGL_FALSE); 789 } 790 791 display->destroyContext(context); 792 793 return success(EGL_TRUE); 794 } 795 796 EGLBoolean MakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx) 797 { 798 TRACE("(EGLDisplay dpy = %p, EGLSurface draw = %p, EGLSurface read = %p, EGLContext ctx = %p)", 799 dpy, draw, read, ctx); 800 801 egl::Display *display = egl::Display::get(dpy); 802 egl::Context *context = static_cast<egl::Context*>(ctx); 803 egl::Surface *drawSurface = static_cast<egl::Surface*>(draw); 804 egl::Surface *readSurface = static_cast<egl::Surface*>(read); 805 806 if(ctx != EGL_NO_CONTEXT || draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE) 807 { 808 if(!validateDisplay(display)) 809 { 810 return EGL_FALSE; 811 } 812 } 813 814 if(ctx == EGL_NO_CONTEXT && (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE)) 815 { 816 return error(EGL_BAD_MATCH, EGL_FALSE); 817 } 818 819 if(ctx != EGL_NO_CONTEXT && !validateContext(display, context)) 820 { 821 return EGL_FALSE; 822 } 823 824 if((draw != EGL_NO_SURFACE && !validateSurface(display, drawSurface)) || 825 (read != EGL_NO_SURFACE && !validateSurface(display, readSurface))) 826 { 827 return EGL_FALSE; 828 } 829 830 if((draw != EGL_NO_SURFACE && drawSurface->hasClientBuffer()) || 831 (read != EGL_NO_SURFACE && readSurface->hasClientBuffer())) 832 { 833 // Make current is not supported on IOSurface pbuffers. 834 return error(EGL_BAD_SURFACE, EGL_FALSE); 835 } 836 837 if((draw != EGL_NO_SURFACE) ^ (read != EGL_NO_SURFACE)) 838 { 839 return error(EGL_BAD_MATCH, EGL_FALSE); 840 } 841 842 if(draw != read) 843 { 844 UNIMPLEMENTED(); // FIXME 845 } 846 847 egl::setCurrentDrawSurface(drawSurface); 848 egl::setCurrentReadSurface(readSurface); 849 egl::setCurrentContext(context); 850 851 if(context) 852 { 853 context->makeCurrent(drawSurface); 854 } 855 856 return success(EGL_TRUE); 857 } 858 859 EGLContext GetCurrentContext(void) 860 { 861 TRACE("()"); 862 863 EGLContext context = egl::getCurrentContext(); 864 865 return success(context); 866 } 867 868 EGLSurface GetCurrentSurface(EGLint readdraw) 869 { 870 TRACE("(EGLint readdraw = %d)", readdraw); 871 872 if(readdraw == EGL_READ) 873 { 874 EGLSurface read = egl::getCurrentReadSurface(); 875 return success(read); 876 } 877 else if(readdraw == EGL_DRAW) 878 { 879 EGLSurface draw = egl::getCurrentDrawSurface(); 880 return success(draw); 881 } 882 else 883 { 884 return error(EGL_BAD_PARAMETER, EGL_NO_SURFACE); 885 } 886 } 887 888 EGLDisplay GetCurrentDisplay(void) 889 { 890 TRACE("()"); 891 892 egl::Context *context = egl::getCurrentContext(); 893 894 if(!context) 895 { 896 return success(EGL_NO_DISPLAY); 897 } 898 899 egl::Display *display = context->getDisplay(); 900 901 if(!display) 902 { 903 return error(EGL_BAD_ACCESS, EGL_NO_DISPLAY); 904 } 905 906 return success(display->getEGLDisplay()); 907 } 908 909 EGLBoolean QueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value) 910 { 911 TRACE("(EGLDisplay dpy = %p, EGLContext ctx = %p, EGLint attribute = %d, EGLint *value = %p)", 912 dpy, ctx, attribute, value); 913 914 egl::Display *display = egl::Display::get(dpy); 915 egl::Context *context = static_cast<egl::Context*>(ctx); 916 917 if(!validateContext(display, context)) 918 { 919 return EGL_FALSE; 920 } 921 922 switch(attribute) 923 { 924 case EGL_CONFIG_ID: 925 *value = context->getConfigID(); 926 break; 927 case EGL_CONTEXT_CLIENT_TYPE: 928 *value = egl::getCurrentAPI(); 929 break; 930 case EGL_CONTEXT_CLIENT_VERSION: 931 *value = context->getClientVersion(); 932 break; 933 case EGL_RENDER_BUFFER: 934 *value = EGL_BACK_BUFFER; 935 break; 936 default: 937 return error(EGL_BAD_ATTRIBUTE, EGL_FALSE); 938 } 939 940 return success(EGL_TRUE); 941 } 942 943 EGLBoolean WaitGL(void) 944 { 945 TRACE("()"); 946 947 // glWaitGL is ignored if there is no current EGL rendering context for OpenGL ES. 948 egl::Context *context = egl::getCurrentContext(); 949 950 if(context) 951 { 952 context->finish(); 953 } 954 955 return success(EGL_TRUE); 956 } 957 958 EGLBoolean WaitNative(EGLint engine) 959 { 960 TRACE("(EGLint engine = %d)", engine); 961 962 if(engine != EGL_CORE_NATIVE_ENGINE) 963 { 964 return error(EGL_BAD_PARAMETER, EGL_FALSE); 965 } 966 967 // eglWaitNative is ignored if there is no current EGL rendering context. 968 egl::Context *context = egl::getCurrentContext(); 969 970 if(context) 971 { 972 #if defined(__linux__) && !defined(__ANDROID__) 973 egl::Display *display = context->getDisplay(); 974 975 if(!display) 976 { 977 return error(EGL_BAD_DISPLAY, EGL_FALSE); 978 } 979 980 libX11->XSync((::Display*)display->getNativeDisplay(), False); 981 #else 982 UNIMPLEMENTED(); 983 #endif 984 } 985 986 return success(EGL_TRUE); 987 } 988 989 EGLBoolean SwapBuffers(EGLDisplay dpy, EGLSurface surface) 990 { 991 TRACE("(EGLDisplay dpy = %p, EGLSurface surface = %p)", dpy, surface); 992 993 egl::Display *display = egl::Display::get(dpy); 994 egl::Surface *eglSurface = (egl::Surface*)surface; 995 996 if(!validateSurface(display, eglSurface)) 997 { 998 return EGL_FALSE; 999 } 1000 1001 if(surface == EGL_NO_SURFACE) 1002 { 1003 return error(EGL_BAD_SURFACE, EGL_FALSE); 1004 } 1005 1006 eglSurface->swap(); 1007 1008 return success(EGL_TRUE); 1009 } 1010 1011 EGLBoolean CopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target) 1012 { 1013 TRACE("(EGLDisplay dpy = %p, EGLSurface surface = %p, EGLNativePixmapType target = %p)", dpy, surface, target); 1014 1015 egl::Display *display = egl::Display::get(dpy); 1016 egl::Surface *eglSurface = static_cast<egl::Surface*>(surface); 1017 1018 if(!validateSurface(display, eglSurface)) 1019 { 1020 return EGL_FALSE; 1021 } 1022 1023 UNIMPLEMENTED(); // FIXME 1024 1025 return success(EGL_FALSE); 1026 } 1027 1028 EGLImageKHR CreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list) 1029 { 1030 TRACE("(EGLDisplay dpy = %p, EGLContext ctx = %p, EGLenum target = 0x%X, buffer = %p, const EGLint attrib_list = %p)", dpy, ctx, target, buffer, attrib_list); 1031 1032 egl::Display *display = egl::Display::get(dpy); 1033 egl::Context *context = static_cast<egl::Context*>(ctx); 1034 1035 if(!validateDisplay(display)) 1036 { 1037 return error(EGL_BAD_DISPLAY, EGL_NO_IMAGE_KHR); 1038 } 1039 1040 if(context != EGL_NO_CONTEXT && !display->isValidContext(context)) 1041 { 1042 return error(EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR); 1043 } 1044 1045 EGLenum imagePreserved = EGL_FALSE; 1046 GLuint textureLevel = 0; 1047 if(attrib_list) 1048 { 1049 for(const EGLint *attribute = attrib_list; attribute[0] != EGL_NONE; attribute += 2) 1050 { 1051 if(attribute[0] == EGL_IMAGE_PRESERVED_KHR) 1052 { 1053 imagePreserved = attribute[1]; 1054 } 1055 else if(attribute[0] == EGL_GL_TEXTURE_LEVEL_KHR) 1056 { 1057 textureLevel = attribute[1]; 1058 } 1059 else 1060 { 1061 return error(EGL_BAD_ATTRIBUTE, EGL_NO_IMAGE_KHR); 1062 } 1063 } 1064 } 1065 1066 #if defined(__ANDROID__) 1067 if(target == EGL_NATIVE_BUFFER_ANDROID) 1068 { 1069 ANativeWindowBuffer *nativeBuffer = reinterpret_cast<ANativeWindowBuffer*>(buffer); 1070 1071 if(!nativeBuffer || GLPixelFormatFromAndroid(nativeBuffer->format) == GL_NONE) 1072 { 1073 ALOGW("%s badness unsupported HAL format=%x", __FUNCTION__, nativeBuffer ? nativeBuffer->format : 0); 1074 return error(EGL_BAD_ATTRIBUTE, EGL_NO_IMAGE_KHR); 1075 } 1076 1077 Image *image = new AndroidNativeImage(nativeBuffer); 1078 EGLImageKHR eglImage = display->createSharedImage(image); 1079 1080 return success(eglImage); 1081 } 1082 #endif 1083 1084 GLuint name = static_cast<GLuint>(reinterpret_cast<uintptr_t>(buffer)); 1085 1086 if(name == 0) 1087 { 1088 return error(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR); 1089 } 1090 1091 EGLenum validationResult = context->validateSharedImage(target, name, textureLevel); 1092 1093 if(validationResult != EGL_SUCCESS) 1094 { 1095 return error(validationResult, EGL_NO_IMAGE_KHR); 1096 } 1097 1098 Image *image = context->createSharedImage(target, name, textureLevel); 1099 1100 if(!image) 1101 { 1102 return error(EGL_BAD_MATCH, EGL_NO_IMAGE_KHR); 1103 } 1104 1105 if(image->getDepth() > 1) 1106 { 1107 return error(EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR); 1108 } 1109 1110 EGLImageKHR eglImage = display->createSharedImage(image); 1111 1112 return success(eglImage); 1113 } 1114 1115 EGLBoolean DestroyImageKHR(EGLDisplay dpy, EGLImageKHR image) 1116 { 1117 TRACE("(EGLDisplay dpy = %p, EGLImageKHR image = %p)", dpy, image); 1118 1119 egl::Display *display = egl::Display::get(dpy); 1120 1121 if(!validateDisplay(display)) 1122 { 1123 return error(EGL_BAD_DISPLAY, EGL_FALSE); 1124 } 1125 1126 if(!display->destroySharedImage(image)) 1127 { 1128 return error(EGL_BAD_PARAMETER, EGL_FALSE); 1129 } 1130 1131 return success(EGL_TRUE); 1132 } 1133 1134 EGLDisplay GetPlatformDisplayEXT(EGLenum platform, void *native_display, const EGLint *attrib_list) 1135 { 1136 TRACE("(EGLenum platform = 0x%X, void *native_display = %p, const EGLint *attrib_list = %p)", platform, native_display, attrib_list); 1137 1138 #if defined(__linux__) && !defined(__ANDROID__) 1139 switch(platform) 1140 { 1141 case EGL_PLATFORM_X11_EXT: break; 1142 case EGL_PLATFORM_GBM_KHR: break; 1143 default: 1144 return error(EGL_BAD_PARAMETER, EGL_NO_DISPLAY); 1145 } 1146 1147 if(platform == EGL_PLATFORM_X11_EXT) 1148 { 1149 if(!libX11) 1150 { 1151 return error(EGL_BAD_ATTRIBUTE, EGL_NO_DISPLAY); 1152 } 1153 1154 if(native_display != (void*)EGL_DEFAULT_DISPLAY || attrib_list != NULL) 1155 { 1156 return error(EGL_BAD_ATTRIBUTE, EGL_NO_DISPLAY); // Unimplemented 1157 } 1158 } 1159 else if(platform == EGL_PLATFORM_GBM_KHR) 1160 { 1161 if(native_display != (void*)EGL_DEFAULT_DISPLAY || attrib_list != NULL) 1162 { 1163 return error(EGL_BAD_ATTRIBUTE, EGL_NO_DISPLAY); // Unimplemented 1164 } 1165 1166 return success(HEADLESS_DISPLAY); 1167 } 1168 1169 return success(PRIMARY_DISPLAY); // We only support the default display 1170 #else 1171 return error(EGL_BAD_PARAMETER, EGL_NO_DISPLAY); 1172 #endif 1173 } 1174 1175 EGLSurface CreatePlatformWindowSurfaceEXT(EGLDisplay dpy, EGLConfig config, void *native_window, const EGLint *attrib_list) 1176 { 1177 return CreateWindowSurface(dpy, config, (EGLNativeWindowType)native_window, attrib_list); 1178 } 1179 1180 EGLSurface CreatePlatformPixmapSurfaceEXT(EGLDisplay dpy, EGLConfig config, void *native_pixmap, const EGLint *attrib_list) 1181 { 1182 return CreatePixmapSurface(dpy, config, (EGLNativePixmapType)native_pixmap, attrib_list); 1183 } 1184 1185 EGLSyncKHR CreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list) 1186 { 1187 TRACE("(EGLDisplay dpy = %p, EGLunum type = %x, EGLint *attrib_list=%p)", dpy, type, attrib_list); 1188 1189 egl::Display *display = egl::Display::get(dpy); 1190 1191 if(!validateDisplay(display)) 1192 { 1193 return error(EGL_BAD_DISPLAY, EGL_NO_SYNC_KHR); 1194 } 1195 1196 if(type != EGL_SYNC_FENCE_KHR) 1197 { 1198 return error(EGL_BAD_ATTRIBUTE, EGL_NO_SYNC_KHR); 1199 } 1200 1201 if(attrib_list && attrib_list[0] != EGL_NONE) 1202 { 1203 return error(EGL_BAD_ATTRIBUTE, EGL_NO_SYNC_KHR); 1204 } 1205 1206 egl::Context *context = egl::getCurrentContext(); 1207 1208 if(!validateContext(display, context)) 1209 { 1210 return error(EGL_BAD_MATCH, EGL_NO_SYNC_KHR); 1211 } 1212 1213 EGLSyncKHR sync = display->createSync(context); 1214 1215 return success(sync); 1216 } 1217 1218 EGLBoolean DestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync) 1219 { 1220 TRACE("(EGLDisplay dpy = %p, EGLSyncKHR sync = %p)", dpy, sync); 1221 1222 egl::Display *display = egl::Display::get(dpy); 1223 FenceSync *eglSync = static_cast<FenceSync*>(sync); 1224 1225 if(!validateDisplay(display)) 1226 { 1227 return error(EGL_BAD_DISPLAY, EGL_FALSE); 1228 } 1229 1230 if(!display->isValidSync(eglSync)) 1231 { 1232 return error(EGL_BAD_PARAMETER, EGL_FALSE); 1233 } 1234 1235 display->destroySync(eglSync); 1236 1237 return success(EGL_TRUE); 1238 } 1239 1240 EGLint ClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout) 1241 { 1242 TRACE("(EGLDisplay dpy = %p, EGLSyncKHR sync = %p, EGLint flags = %x, EGLTimeKHR value = %llx)", dpy, sync, flags, timeout); 1243 1244 egl::Display *display = egl::Display::get(dpy); 1245 FenceSync *eglSync = static_cast<FenceSync*>(sync); 1246 1247 if(!validateDisplay(display)) 1248 { 1249 return error(EGL_BAD_DISPLAY, EGL_FALSE); 1250 } 1251 1252 if(!display->isValidSync(eglSync)) 1253 { 1254 return error(EGL_BAD_PARAMETER, EGL_FALSE); 1255 } 1256 1257 (void)flags; 1258 (void)timeout; 1259 1260 if(!eglSync->isSignaled()) 1261 { 1262 eglSync->wait(); 1263 } 1264 1265 return success(EGL_CONDITION_SATISFIED_KHR); 1266 } 1267 1268 EGLBoolean GetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value) 1269 { 1270 TRACE("(EGLDisplay dpy = %p, EGLSyncKHR sync = %p, EGLint attribute = %x, EGLint *value = %p)", dpy, sync, attribute, value); 1271 1272 egl::Display *display = egl::Display::get(dpy); 1273 FenceSync *eglSync = static_cast<FenceSync*>(sync); 1274 1275 if(!validateDisplay(display)) 1276 { 1277 return error(EGL_BAD_DISPLAY, EGL_FALSE); 1278 } 1279 1280 if(!display->isValidSync(eglSync)) 1281 { 1282 return error(EGL_BAD_PARAMETER, EGL_FALSE); 1283 } 1284 1285 switch(attribute) 1286 { 1287 case EGL_SYNC_TYPE_KHR: 1288 *value = EGL_SYNC_FENCE_KHR; 1289 return success(EGL_TRUE); 1290 case EGL_SYNC_STATUS_KHR: 1291 eglSync->wait(); // TODO: Don't block. Just poll based on sw::Query. 1292 *value = eglSync->isSignaled() ? EGL_SIGNALED_KHR : EGL_UNSIGNALED_KHR; 1293 return success(EGL_TRUE); 1294 case EGL_SYNC_CONDITION_KHR: 1295 *value = EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR; 1296 return success(EGL_TRUE); 1297 default: 1298 return error(EGL_BAD_ATTRIBUTE, EGL_FALSE); 1299 } 1300 } 1301 1302 __eglMustCastToProperFunctionPointerType GetProcAddress(const char *procname) 1303 { 1304 TRACE("(const char *procname = \"%s\")", procname); 1305 1306 struct Function 1307 { 1308 const char *name; 1309 __eglMustCastToProperFunctionPointerType address; 1310 }; 1311 1312 struct CompareFunctor 1313 { 1314 bool operator()(const Function &a, const Function &b) const 1315 { 1316 return strcmp(a.name, b.name) < 0; 1317 } 1318 }; 1319 1320 // This array must be kept sorted with respect to strcmp(), so that binary search works correctly. 1321 // The Unix command "LC_COLLATE=C sort" will generate the correct order. 1322 static const Function eglFunctions[] = 1323 { 1324 #define FUNCTION(name) {#name, (__eglMustCastToProperFunctionPointerType)name} 1325 1326 FUNCTION(eglBindAPI), 1327 FUNCTION(eglBindTexImage), 1328 FUNCTION(eglChooseConfig), 1329 FUNCTION(eglClientWaitSyncKHR), 1330 FUNCTION(eglCopyBuffers), 1331 FUNCTION(eglCreateContext), 1332 FUNCTION(eglCreateImageKHR), 1333 FUNCTION(eglCreatePbufferFromClientBuffer), 1334 FUNCTION(eglCreatePbufferSurface), 1335 FUNCTION(eglCreatePixmapSurface), 1336 FUNCTION(eglCreatePlatformPixmapSurfaceEXT), 1337 FUNCTION(eglCreatePlatformWindowSurfaceEXT), 1338 FUNCTION(eglCreateSyncKHR), 1339 FUNCTION(eglCreateWindowSurface), 1340 FUNCTION(eglDestroyContext), 1341 FUNCTION(eglDestroyImageKHR), 1342 FUNCTION(eglDestroySurface), 1343 FUNCTION(eglDestroySyncKHR), 1344 FUNCTION(eglGetConfigAttrib), 1345 FUNCTION(eglGetConfigs), 1346 FUNCTION(eglGetCurrentContext), 1347 FUNCTION(eglGetCurrentDisplay), 1348 FUNCTION(eglGetCurrentSurface), 1349 FUNCTION(eglGetDisplay), 1350 FUNCTION(eglGetError), 1351 FUNCTION(eglGetPlatformDisplayEXT), 1352 FUNCTION(eglGetProcAddress), 1353 FUNCTION(eglGetSyncAttribKHR), 1354 FUNCTION(eglInitialize), 1355 FUNCTION(eglMakeCurrent), 1356 FUNCTION(eglQueryAPI), 1357 FUNCTION(eglQueryContext), 1358 FUNCTION(eglQueryString), 1359 FUNCTION(eglQuerySurface), 1360 FUNCTION(eglReleaseTexImage), 1361 FUNCTION(eglReleaseThread), 1362 FUNCTION(eglSurfaceAttrib), 1363 FUNCTION(eglSwapBuffers), 1364 FUNCTION(eglSwapInterval), 1365 FUNCTION(eglTerminate), 1366 FUNCTION(eglWaitClient), 1367 FUNCTION(eglWaitGL), 1368 FUNCTION(eglWaitNative), 1369 1370 #undef FUNCTION 1371 }; 1372 1373 static const size_t numFunctions = sizeof eglFunctions / sizeof(Function); 1374 static const Function *const eglFunctionsEnd = eglFunctions + numFunctions; 1375 1376 Function needle; 1377 needle.name = procname; 1378 1379 if(procname && strncmp("egl", procname, 3) == 0) 1380 { 1381 const Function *result = std::lower_bound(eglFunctions, eglFunctionsEnd, needle, CompareFunctor()); 1382 if (result != eglFunctionsEnd && strcmp(procname, result->name) == 0) 1383 { 1384 return success((__eglMustCastToProperFunctionPointerType)result->address); 1385 } 1386 } 1387 1388 if(libGLESv2) 1389 { 1390 __eglMustCastToProperFunctionPointerType proc = libGLESv2->es2GetProcAddress(procname); 1391 if(proc) return success(proc); 1392 } 1393 1394 if(libGLES_CM) 1395 { 1396 __eglMustCastToProperFunctionPointerType proc = libGLES_CM->es1GetProcAddress(procname); 1397 if(proc) return success(proc); 1398 } 1399 1400 return success((__eglMustCastToProperFunctionPointerType)NULL); 1401 } 1402 } 1403