1// 2// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. 3// Use of this source code is governed by a BSD-style license that can be 4// found in the LICENSE file. 5// 6 7// libEGL.cpp: Implements the exported EGL functions. 8 9#include <exception> 10 11#include "common/debug.h" 12#include "common/version.h" 13#include "libGLESv2/Context.h" 14#include "libGLESv2/Texture.h" 15#include "libGLESv2/main.h" 16#include "libGLESv2/renderer/SwapChain.h" 17 18#include "libEGL/main.h" 19#include "libEGL/Display.h" 20#include "libEGL/Surface.h" 21 22bool validateDisplay(egl::Display *display) 23{ 24 if (display == EGL_NO_DISPLAY) 25 { 26 return egl::error(EGL_BAD_DISPLAY, false); 27 } 28 29 if (!display->isInitialized()) 30 { 31 return egl::error(EGL_NOT_INITIALIZED, false); 32 } 33 34 return true; 35} 36 37bool validateConfig(egl::Display *display, EGLConfig config) 38{ 39 if (!validateDisplay(display)) 40 { 41 return false; 42 } 43 44 if (!display->isValidConfig(config)) 45 { 46 return egl::error(EGL_BAD_CONFIG, false); 47 } 48 49 return true; 50} 51 52bool validateContext(egl::Display *display, gl::Context *context) 53{ 54 if (!validateDisplay(display)) 55 { 56 return false; 57 } 58 59 if (!display->isValidContext(context)) 60 { 61 return egl::error(EGL_BAD_CONTEXT, false); 62 } 63 64 return true; 65} 66 67bool validateSurface(egl::Display *display, egl::Surface *surface) 68{ 69 if (!validateDisplay(display)) 70 { 71 return false; 72 } 73 74 if (!display->isValidSurface(surface)) 75 { 76 return egl::error(EGL_BAD_SURFACE, false); 77 } 78 79 return true; 80} 81 82extern "C" 83{ 84EGLint __stdcall eglGetError(void) 85{ 86 EVENT("()"); 87 88 EGLint error = egl::getCurrentError(); 89 90 if (error != EGL_SUCCESS) 91 { 92 egl::setCurrentError(EGL_SUCCESS); 93 } 94 95 return error; 96} 97 98EGLDisplay __stdcall eglGetDisplay(EGLNativeDisplayType display_id) 99{ 100 EVENT("(EGLNativeDisplayType display_id = 0x%0.8p)", display_id); 101 102 return egl::Display::getDisplay(display_id, EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE); 103} 104 105EGLDisplay __stdcall eglGetPlatformDisplayEXT(EGLenum platform, void *native_display, const EGLint *attrib_list) 106{ 107 EVENT("(EGLenum platform = %d, void* native_display = 0x%0.8p, const EGLint* attrib_list = 0x%0.8p)", 108 platform, native_display, attrib_list); 109 110 switch (platform) 111 { 112 case EGL_PLATFORM_ANGLE_ANGLE: 113 break; 114 115 default: 116 return egl::error(EGL_BAD_CONFIG, EGL_NO_DISPLAY); 117 } 118 119 EGLNativeDisplayType displayId = static_cast<EGLNativeDisplayType>(native_display); 120 121 // Validate the display device context 122 if (WindowFromDC(displayId) == NULL) 123 { 124 return egl::success(EGL_NO_DISPLAY); 125 } 126 127 EGLint requestedDisplayType = EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE; 128 if (attrib_list) 129 { 130 for (const EGLint *curAttrib = attrib_list; curAttrib[0] != EGL_NONE; curAttrib += 2) 131 { 132 switch (curAttrib[0]) 133 { 134 case EGL_PLATFORM_ANGLE_TYPE_ANGLE: 135 requestedDisplayType = curAttrib[1]; 136 break; 137 138 default: 139 break; 140 } 141 } 142 } 143 144 switch (requestedDisplayType) 145 { 146 case EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE: 147 break; 148 149 case EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE: 150 case EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE: 151 case EGL_PLATFORM_ANGLE_TYPE_D3D11_WARP_ANGLE: 152 if (!egl::Display::supportsPlatformD3D()) 153 { 154 return egl::success(EGL_NO_DISPLAY); 155 } 156 break; 157 158 case EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE: 159 case EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE: 160 if (!egl::Display::supportsPlatformOpenGL()) 161 { 162 return egl::success(EGL_NO_DISPLAY); 163 } 164 break; 165 166 default: 167 return egl::success(EGL_NO_DISPLAY); 168 } 169 170 return egl::Display::getDisplay(displayId, requestedDisplayType); 171} 172 173EGLBoolean __stdcall eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor) 174{ 175 EVENT("(EGLDisplay dpy = 0x%0.8p, EGLint *major = 0x%0.8p, EGLint *minor = 0x%0.8p)", 176 dpy, major, minor); 177 178 if (dpy == EGL_NO_DISPLAY) 179 { 180 return egl::error(EGL_BAD_DISPLAY, EGL_FALSE); 181 } 182 183 egl::Display *display = static_cast<egl::Display*>(dpy); 184 185 if (!display->initialize()) 186 { 187 return egl::error(EGL_NOT_INITIALIZED, EGL_FALSE); 188 } 189 190 if (major) *major = 1; 191 if (minor) *minor = 4; 192 193 return egl::success(EGL_TRUE); 194} 195 196EGLBoolean __stdcall eglTerminate(EGLDisplay dpy) 197{ 198 EVENT("(EGLDisplay dpy = 0x%0.8p)", dpy); 199 200 if (dpy == EGL_NO_DISPLAY) 201 { 202 return egl::error(EGL_BAD_DISPLAY, EGL_FALSE); 203 } 204 205 egl::Display *display = static_cast<egl::Display*>(dpy); 206 207 display->terminate(); 208 209 return egl::success(EGL_TRUE); 210} 211 212const char *__stdcall eglQueryString(EGLDisplay dpy, EGLint name) 213{ 214 EVENT("(EGLDisplay dpy = 0x%0.8p, EGLint name = %d)", dpy, name); 215 216 egl::Display *display = static_cast<egl::Display*>(dpy); 217 if (!(display == EGL_NO_DISPLAY && name == EGL_EXTENSIONS) && !validateDisplay(display)) 218 { 219 return NULL; 220 } 221 222 switch (name) 223 { 224 case EGL_CLIENT_APIS: 225 return egl::success("OpenGL_ES"); 226 case EGL_EXTENSIONS: 227 return egl::success(egl::Display::getExtensionString(display)); 228 case EGL_VENDOR: 229 return egl::success(display->getVendorString()); 230 case EGL_VERSION: 231 return egl::success("1.4 (ANGLE " ANGLE_VERSION_STRING ")"); 232 default: 233 return egl::error(EGL_BAD_PARAMETER, (const char*)NULL); 234 } 235} 236 237EGLBoolean __stdcall eglGetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config) 238{ 239 EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig *configs = 0x%0.8p, " 240 "EGLint config_size = %d, EGLint *num_config = 0x%0.8p)", 241 dpy, configs, config_size, num_config); 242 243 egl::Display *display = static_cast<egl::Display*>(dpy); 244 245 if (!validateDisplay(display)) 246 { 247 return EGL_FALSE; 248 } 249 250 if (!num_config) 251 { 252 return egl::error(EGL_BAD_PARAMETER, EGL_FALSE); 253 } 254 255 const EGLint attribList[] = {EGL_NONE}; 256 257 if (!display->getConfigs(configs, attribList, config_size, num_config)) 258 { 259 return egl::error(EGL_BAD_ATTRIBUTE, EGL_FALSE); 260 } 261 262 return egl::success(EGL_TRUE); 263} 264 265EGLBoolean __stdcall eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config) 266{ 267 EVENT("(EGLDisplay dpy = 0x%0.8p, const EGLint *attrib_list = 0x%0.8p, " 268 "EGLConfig *configs = 0x%0.8p, EGLint config_size = %d, EGLint *num_config = 0x%0.8p)", 269 dpy, attrib_list, configs, config_size, num_config); 270 271 egl::Display *display = static_cast<egl::Display*>(dpy); 272 273 if (!validateDisplay(display)) 274 { 275 return EGL_FALSE; 276 } 277 278 if (!num_config) 279 { 280 return egl::error(EGL_BAD_PARAMETER, EGL_FALSE); 281 } 282 283 const EGLint attribList[] = {EGL_NONE}; 284 285 if (!attrib_list) 286 { 287 attrib_list = attribList; 288 } 289 290 display->getConfigs(configs, attrib_list, config_size, num_config); 291 292 return egl::success(EGL_TRUE); 293} 294 295EGLBoolean __stdcall eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value) 296{ 297 EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, EGLint attribute = %d, EGLint *value = 0x%0.8p)", 298 dpy, config, attribute, value); 299 300 egl::Display *display = static_cast<egl::Display*>(dpy); 301 302 if (!validateConfig(display, config)) 303 { 304 return EGL_FALSE; 305 } 306 307 if (!display->getConfigAttrib(config, attribute, value)) 308 { 309 return egl::error(EGL_BAD_ATTRIBUTE, EGL_FALSE); 310 } 311 312 return egl::success(EGL_TRUE); 313} 314 315EGLSurface __stdcall eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list) 316{ 317 EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, EGLNativeWindowType win = 0x%0.8p, " 318 "const EGLint *attrib_list = 0x%0.8p)", dpy, config, win, attrib_list); 319 320 egl::Display *display = static_cast<egl::Display*>(dpy); 321 322 if (!validateConfig(display, config)) 323 { 324 return EGL_NO_SURFACE; 325 } 326 327 HWND window = (HWND)win; 328 329 if (!IsWindow(window)) 330 { 331 return egl::error(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE); 332 } 333 334 return display->createWindowSurface(window, config, attrib_list); 335} 336 337EGLSurface __stdcall eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list) 338{ 339 EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, const EGLint *attrib_list = 0x%0.8p)", 340 dpy, config, attrib_list); 341 342 egl::Display *display = static_cast<egl::Display*>(dpy); 343 344 if (!validateConfig(display, config)) 345 { 346 return EGL_NO_SURFACE; 347 } 348 349 return display->createOffscreenSurface(config, NULL, attrib_list); 350} 351 352EGLSurface __stdcall eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list) 353{ 354 EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, EGLNativePixmapType pixmap = 0x%0.8p, " 355 "const EGLint *attrib_list = 0x%0.8p)", dpy, config, pixmap, attrib_list); 356 357 egl::Display *display = static_cast<egl::Display*>(dpy); 358 359 if (!validateConfig(display, config)) 360 { 361 return EGL_NO_SURFACE; 362 } 363 364 UNIMPLEMENTED(); // FIXME 365 366 return egl::success(EGL_NO_SURFACE); 367} 368 369EGLBoolean __stdcall eglDestroySurface(EGLDisplay dpy, EGLSurface surface) 370{ 371 EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p)", dpy, surface); 372 373 egl::Display *display = static_cast<egl::Display*>(dpy); 374 egl::Surface *eglSurface = static_cast<egl::Surface*>(surface); 375 376 if (!validateSurface(display, eglSurface)) 377 { 378 return EGL_FALSE; 379 } 380 381 if (surface == EGL_NO_SURFACE) 382 { 383 return egl::error(EGL_BAD_SURFACE, EGL_FALSE); 384 } 385 386 display->destroySurface((egl::Surface*)surface); 387 388 return egl::success(EGL_TRUE); 389} 390 391EGLBoolean __stdcall eglQuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value) 392{ 393 EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint attribute = %d, EGLint *value = 0x%0.8p)", 394 dpy, surface, attribute, value); 395 396 egl::Display *display = static_cast<egl::Display*>(dpy); 397 egl::Surface *eglSurface = (egl::Surface*)surface; 398 399 if (!validateSurface(display, eglSurface)) 400 { 401 return EGL_FALSE; 402 } 403 404 if (surface == EGL_NO_SURFACE) 405 { 406 return egl::error(EGL_BAD_SURFACE, EGL_FALSE); 407 } 408 409 switch (attribute) 410 { 411 case EGL_VG_ALPHA_FORMAT: 412 UNIMPLEMENTED(); // FIXME 413 break; 414 case EGL_VG_COLORSPACE: 415 UNIMPLEMENTED(); // FIXME 416 break; 417 case EGL_CONFIG_ID: 418 *value = eglSurface->getConfigID(); 419 break; 420 case EGL_HEIGHT: 421 *value = eglSurface->getHeight(); 422 break; 423 case EGL_HORIZONTAL_RESOLUTION: 424 UNIMPLEMENTED(); // FIXME 425 break; 426 case EGL_LARGEST_PBUFFER: 427 UNIMPLEMENTED(); // FIXME 428 break; 429 case EGL_MIPMAP_TEXTURE: 430 UNIMPLEMENTED(); // FIXME 431 break; 432 case EGL_MIPMAP_LEVEL: 433 UNIMPLEMENTED(); // FIXME 434 break; 435 case EGL_MULTISAMPLE_RESOLVE: 436 UNIMPLEMENTED(); // FIXME 437 break; 438 case EGL_PIXEL_ASPECT_RATIO: 439 *value = eglSurface->getPixelAspectRatio(); 440 break; 441 case EGL_RENDER_BUFFER: 442 *value = eglSurface->getRenderBuffer(); 443 break; 444 case EGL_SWAP_BEHAVIOR: 445 *value = eglSurface->getSwapBehavior(); 446 break; 447 case EGL_TEXTURE_FORMAT: 448 *value = eglSurface->getTextureFormat(); 449 break; 450 case EGL_TEXTURE_TARGET: 451 *value = eglSurface->getTextureTarget(); 452 break; 453 case EGL_VERTICAL_RESOLUTION: 454 UNIMPLEMENTED(); // FIXME 455 break; 456 case EGL_WIDTH: 457 *value = eglSurface->getWidth(); 458 break; 459 case EGL_POST_SUB_BUFFER_SUPPORTED_NV: 460 *value = eglSurface->isPostSubBufferSupported(); 461 break; 462 case EGL_FIXED_SIZE_ANGLE: 463 *value = eglSurface->isFixedSize(); 464 break; 465 default: 466 return egl::error(EGL_BAD_ATTRIBUTE, EGL_FALSE); 467 } 468 469 return egl::success(EGL_TRUE); 470} 471 472EGLBoolean __stdcall eglQuerySurfacePointerANGLE(EGLDisplay dpy, EGLSurface surface, EGLint attribute, void **value) 473{ 474 TRACE("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint attribute = %d, void **value = 0x%0.8p)", 475 dpy, surface, attribute, value); 476 477 egl::Display *display = static_cast<egl::Display*>(dpy); 478 egl::Surface *eglSurface = (egl::Surface*)surface; 479 480 if (!validateSurface(display, eglSurface)) 481 { 482 return EGL_FALSE; 483 } 484 485 if (surface == EGL_NO_SURFACE) 486 { 487 return egl::error(EGL_BAD_SURFACE, EGL_FALSE); 488 } 489 490 switch (attribute) 491 { 492 case EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE: 493 { 494 rx::SwapChain *swapchain = eglSurface->getSwapChain(); 495 *value = (void*) (swapchain ? swapchain->getShareHandle() : NULL); 496 } 497 break; 498 default: 499 return egl::error(EGL_BAD_ATTRIBUTE, EGL_FALSE); 500 } 501 502 return egl::success(EGL_TRUE); 503} 504 505EGLBoolean __stdcall eglBindAPI(EGLenum api) 506{ 507 EVENT("(EGLenum api = 0x%X)", api); 508 509 switch (api) 510 { 511 case EGL_OPENGL_API: 512 case EGL_OPENVG_API: 513 return egl::error(EGL_BAD_PARAMETER, EGL_FALSE); // Not supported by this implementation 514 case EGL_OPENGL_ES_API: 515 break; 516 default: 517 return egl::error(EGL_BAD_PARAMETER, EGL_FALSE); 518 } 519 520 egl::setCurrentAPI(api); 521 522 return egl::success(EGL_TRUE); 523} 524 525EGLenum __stdcall eglQueryAPI(void) 526{ 527 EVENT("()"); 528 529 EGLenum API = egl::getCurrentAPI(); 530 531 return egl::success(API); 532} 533 534EGLBoolean __stdcall eglWaitClient(void) 535{ 536 EVENT("()"); 537 538 UNIMPLEMENTED(); // FIXME 539 540 return egl::success(0); 541} 542 543EGLBoolean __stdcall eglReleaseThread(void) 544{ 545 EVENT("()"); 546 547 eglMakeCurrent(EGL_NO_DISPLAY, EGL_NO_CONTEXT, EGL_NO_SURFACE, EGL_NO_SURFACE); 548 549 return egl::success(EGL_TRUE); 550} 551 552EGLSurface __stdcall eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list) 553{ 554 EVENT("(EGLDisplay dpy = 0x%0.8p, EGLenum buftype = 0x%X, EGLClientBuffer buffer = 0x%0.8p, " 555 "EGLConfig config = 0x%0.8p, const EGLint *attrib_list = 0x%0.8p)", 556 dpy, buftype, buffer, config, attrib_list); 557 558 egl::Display *display = static_cast<egl::Display*>(dpy); 559 560 if (!validateConfig(display, config)) 561 { 562 return EGL_NO_SURFACE; 563 } 564 565 if (buftype != EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE || !buffer) 566 { 567 return egl::error(EGL_BAD_PARAMETER, EGL_NO_SURFACE); 568 } 569 570 return display->createOffscreenSurface(config, (HANDLE)buffer, attrib_list); 571} 572 573EGLBoolean __stdcall eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value) 574{ 575 EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint attribute = %d, EGLint value = %d)", 576 dpy, surface, attribute, value); 577 578 egl::Display *display = static_cast<egl::Display*>(dpy); 579 egl::Surface *eglSurface = static_cast<egl::Surface*>(surface); 580 581 if (!validateSurface(display, eglSurface)) 582 { 583 return EGL_FALSE; 584 } 585 586 UNIMPLEMENTED(); // FIXME 587 588 return egl::success(EGL_TRUE); 589} 590 591EGLBoolean __stdcall eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer) 592{ 593 EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint buffer = %d)", dpy, surface, buffer); 594 595 egl::Display *display = static_cast<egl::Display*>(dpy); 596 egl::Surface *eglSurface = static_cast<egl::Surface*>(surface); 597 598 if (!validateSurface(display, eglSurface)) 599 { 600 return EGL_FALSE; 601 } 602 603 if (buffer != EGL_BACK_BUFFER) 604 { 605 return egl::error(EGL_BAD_PARAMETER, EGL_FALSE); 606 } 607 608 if (surface == EGL_NO_SURFACE || eglSurface->getWindowHandle()) 609 { 610 return egl::error(EGL_BAD_SURFACE, EGL_FALSE); 611 } 612 613 if (eglSurface->getBoundTexture()) 614 { 615 return egl::error(EGL_BAD_ACCESS, EGL_FALSE); 616 } 617 618 if (eglSurface->getTextureFormat() == EGL_NO_TEXTURE) 619 { 620 return egl::error(EGL_BAD_MATCH, EGL_FALSE); 621 } 622 623 if (!glBindTexImage(eglSurface)) 624 { 625 return egl::error(EGL_BAD_MATCH, EGL_FALSE); 626 } 627 628 return egl::success(EGL_TRUE); 629} 630 631EGLBoolean __stdcall eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer) 632{ 633 EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint buffer = %d)", dpy, surface, buffer); 634 635 egl::Display *display = static_cast<egl::Display*>(dpy); 636 egl::Surface *eglSurface = static_cast<egl::Surface*>(surface); 637 638 if (!validateSurface(display, eglSurface)) 639 { 640 return EGL_FALSE; 641 } 642 643 if (buffer != EGL_BACK_BUFFER) 644 { 645 return egl::error(EGL_BAD_PARAMETER, EGL_FALSE); 646 } 647 648 if (surface == EGL_NO_SURFACE || eglSurface->getWindowHandle()) 649 { 650 return egl::error(EGL_BAD_SURFACE, EGL_FALSE); 651 } 652 653 if (eglSurface->getTextureFormat() == EGL_NO_TEXTURE) 654 { 655 return egl::error(EGL_BAD_MATCH, EGL_FALSE); 656 } 657 658 gl::Texture2D *texture = eglSurface->getBoundTexture(); 659 660 if (texture) 661 { 662 texture->releaseTexImage(); 663 } 664 665 return egl::success(EGL_TRUE); 666} 667 668EGLBoolean __stdcall eglSwapInterval(EGLDisplay dpy, EGLint interval) 669{ 670 EVENT("(EGLDisplay dpy = 0x%0.8p, EGLint interval = %d)", dpy, interval); 671 672 egl::Display *display = static_cast<egl::Display*>(dpy); 673 674 if (!validateDisplay(display)) 675 { 676 return EGL_FALSE; 677 } 678 679 egl::Surface *draw_surface = static_cast<egl::Surface*>(egl::getCurrentDrawSurface()); 680 681 if (draw_surface == NULL) 682 { 683 return egl::error(EGL_BAD_SURFACE, EGL_FALSE); 684 } 685 686 draw_surface->setSwapInterval(interval); 687 688 return egl::success(EGL_TRUE); 689} 690 691EGLContext __stdcall eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list) 692{ 693 EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, EGLContext share_context = 0x%0.8p, " 694 "const EGLint *attrib_list = 0x%0.8p)", dpy, config, share_context, attrib_list); 695 696 // Get the requested client version (default is 1) and check it is 2 or 3. 697 EGLint client_version = 1; 698 bool reset_notification = false; 699 bool robust_access = false; 700 701 if (attrib_list) 702 { 703 for (const EGLint* attribute = attrib_list; attribute[0] != EGL_NONE; attribute += 2) 704 { 705 switch (attribute[0]) 706 { 707 case EGL_CONTEXT_CLIENT_VERSION: 708 client_version = attribute[1]; 709 break; 710 case EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT: 711 if (attribute[1] == EGL_TRUE) 712 { 713 return egl::error(EGL_BAD_CONFIG, EGL_NO_CONTEXT); // Unimplemented 714 // robust_access = true; 715 } 716 else if (attribute[1] != EGL_FALSE) 717 return egl::error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT); 718 break; 719 case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT: 720 if (attribute[1] == EGL_LOSE_CONTEXT_ON_RESET_EXT) 721 reset_notification = true; 722 else if (attribute[1] != EGL_NO_RESET_NOTIFICATION_EXT) 723 return egl::error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT); 724 break; 725 default: 726 return egl::error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT); 727 } 728 } 729 } 730 731 if (client_version != 2 && client_version != 3) 732 { 733 return egl::error(EGL_BAD_CONFIG, EGL_NO_CONTEXT); 734 } 735 736 egl::Display *display = static_cast<egl::Display*>(dpy); 737 738 if (share_context) 739 { 740 gl::Context* sharedGLContext = static_cast<gl::Context*>(share_context); 741 742 if (sharedGLContext->isResetNotificationEnabled() != reset_notification) 743 { 744 return egl::error(EGL_BAD_MATCH, EGL_NO_CONTEXT); 745 } 746 747 if (sharedGLContext->getClientVersion() != client_version) 748 { 749 return egl::error(EGL_BAD_CONTEXT, EGL_NO_CONTEXT); 750 } 751 752 // Can not share contexts between displays 753 if (sharedGLContext->getRenderer() != display->getRenderer()) 754 { 755 return egl::error(EGL_BAD_MATCH, EGL_NO_CONTEXT); 756 } 757 } 758 759 if (!validateConfig(display, config)) 760 { 761 return EGL_NO_CONTEXT; 762 } 763 764 return display->createContext(config, client_version, static_cast<gl::Context*>(share_context), reset_notification, robust_access); 765} 766 767EGLBoolean __stdcall eglDestroyContext(EGLDisplay dpy, EGLContext ctx) 768{ 769 EVENT("(EGLDisplay dpy = 0x%0.8p, EGLContext ctx = 0x%0.8p)", dpy, ctx); 770 771 egl::Display *display = static_cast<egl::Display*>(dpy); 772 gl::Context *context = static_cast<gl::Context*>(ctx); 773 774 if (!validateContext(display, context)) 775 { 776 return EGL_FALSE; 777 } 778 779 if (ctx == EGL_NO_CONTEXT) 780 { 781 return egl::error(EGL_BAD_CONTEXT, EGL_FALSE); 782 } 783 784 display->destroyContext(context); 785 786 return egl::success(EGL_TRUE); 787} 788 789EGLBoolean __stdcall eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx) 790{ 791 EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface draw = 0x%0.8p, EGLSurface read = 0x%0.8p, EGLContext ctx = 0x%0.8p)", 792 dpy, draw, read, ctx); 793 794 egl::Display *display = static_cast<egl::Display*>(dpy); 795 gl::Context *context = static_cast<gl::Context*>(ctx); 796 797 bool noContext = (ctx == EGL_NO_CONTEXT); 798 bool noSurface = (draw == EGL_NO_SURFACE || read == EGL_NO_SURFACE); 799 if (noContext != noSurface) 800 { 801 return egl::error(EGL_BAD_MATCH, EGL_FALSE); 802 } 803 804 if (ctx != EGL_NO_CONTEXT && !validateContext(display, context)) 805 { 806 return EGL_FALSE; 807 } 808 809 if (dpy != EGL_NO_DISPLAY && display->isInitialized()) 810 { 811 rx::Renderer *renderer = display->getRenderer(); 812 if (renderer->testDeviceLost(true)) 813 { 814 return EGL_FALSE; 815 } 816 817 if (renderer->isDeviceLost()) 818 { 819 return egl::error(EGL_CONTEXT_LOST, EGL_FALSE); 820 } 821 } 822 823 if ((draw != EGL_NO_SURFACE && !validateSurface(display, static_cast<egl::Surface*>(draw))) || 824 (read != EGL_NO_SURFACE && !validateSurface(display, static_cast<egl::Surface*>(read)))) 825 { 826 return EGL_FALSE; 827 } 828 829 if (draw != read) 830 { 831 UNIMPLEMENTED(); // FIXME 832 } 833 834 egl::setCurrentDisplay(dpy); 835 egl::setCurrentDrawSurface(draw); 836 egl::setCurrentReadSurface(read); 837 838 glMakeCurrent(context, display, static_cast<egl::Surface*>(draw)); 839 840 return egl::success(EGL_TRUE); 841} 842 843EGLContext __stdcall eglGetCurrentContext(void) 844{ 845 EVENT("()"); 846 847 EGLContext context = glGetCurrentContext(); 848 849 return egl::success(context); 850} 851 852EGLSurface __stdcall eglGetCurrentSurface(EGLint readdraw) 853{ 854 EVENT("(EGLint readdraw = %d)", readdraw); 855 856 if (readdraw == EGL_READ) 857 { 858 EGLSurface read = egl::getCurrentReadSurface(); 859 return egl::success(read); 860 } 861 else if (readdraw == EGL_DRAW) 862 { 863 EGLSurface draw = egl::getCurrentDrawSurface(); 864 return egl::success(draw); 865 } 866 else 867 { 868 return egl::error(EGL_BAD_PARAMETER, EGL_NO_SURFACE); 869 } 870} 871 872EGLDisplay __stdcall eglGetCurrentDisplay(void) 873{ 874 EVENT("()"); 875 876 EGLDisplay dpy = egl::getCurrentDisplay(); 877 878 return egl::success(dpy); 879} 880 881EGLBoolean __stdcall eglQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value) 882{ 883 EVENT("(EGLDisplay dpy = 0x%0.8p, EGLContext ctx = 0x%0.8p, EGLint attribute = %d, EGLint *value = 0x%0.8p)", 884 dpy, ctx, attribute, value); 885 886 egl::Display *display = static_cast<egl::Display*>(dpy); 887 gl::Context *context = static_cast<gl::Context*>(ctx); 888 889 if (!validateContext(display, context)) 890 { 891 return EGL_FALSE; 892 } 893 894 UNIMPLEMENTED(); // FIXME 895 896 return egl::success(0); 897} 898 899EGLBoolean __stdcall eglWaitGL(void) 900{ 901 EVENT("()"); 902 903 UNIMPLEMENTED(); // FIXME 904 905 return egl::success(0); 906} 907 908EGLBoolean __stdcall eglWaitNative(EGLint engine) 909{ 910 EVENT("(EGLint engine = %d)", engine); 911 912 UNIMPLEMENTED(); // FIXME 913 914 return egl::success(0); 915} 916 917EGLBoolean __stdcall eglSwapBuffers(EGLDisplay dpy, EGLSurface surface) 918{ 919 EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p)", dpy, surface); 920 921 egl::Display *display = static_cast<egl::Display*>(dpy); 922 egl::Surface *eglSurface = (egl::Surface*)surface; 923 924 if (!validateSurface(display, eglSurface)) 925 { 926 return EGL_FALSE; 927 } 928 929 if (display->getRenderer()->isDeviceLost()) 930 { 931 return egl::error(EGL_CONTEXT_LOST, EGL_FALSE); 932 } 933 934 if (surface == EGL_NO_SURFACE) 935 { 936 return egl::error(EGL_BAD_SURFACE, EGL_FALSE); 937 } 938 939 if (eglSurface->swap()) 940 { 941 return egl::success(EGL_TRUE); 942 } 943 944 return EGL_FALSE; 945} 946 947EGLBoolean __stdcall eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target) 948{ 949 EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLNativePixmapType target = 0x%0.8p)", dpy, surface, target); 950 951 egl::Display *display = static_cast<egl::Display*>(dpy); 952 egl::Surface *eglSurface = static_cast<egl::Surface*>(surface); 953 954 if (!validateSurface(display, eglSurface)) 955 { 956 return EGL_FALSE; 957 } 958 959 if (display->getRenderer()->isDeviceLost()) 960 { 961 return egl::error(EGL_CONTEXT_LOST, EGL_FALSE); 962 } 963 964 UNIMPLEMENTED(); // FIXME 965 966 return egl::success(0); 967} 968 969EGLBoolean __stdcall eglPostSubBufferNV(EGLDisplay dpy, EGLSurface surface, EGLint x, EGLint y, EGLint width, EGLint height) 970{ 971 EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint x = %d, EGLint y = %d, EGLint width = %d, EGLint height = %d)", dpy, surface, x, y, width, height); 972 973 if (x < 0 || y < 0 || width < 0 || height < 0) 974 { 975 return egl::error(EGL_BAD_PARAMETER, EGL_FALSE); 976 } 977 978 egl::Display *display = static_cast<egl::Display*>(dpy); 979 egl::Surface *eglSurface = static_cast<egl::Surface*>(surface); 980 981 if (!validateSurface(display, eglSurface)) 982 { 983 return EGL_FALSE; 984 } 985 986 if (display->getRenderer()->isDeviceLost()) 987 { 988 return egl::error(EGL_CONTEXT_LOST, EGL_FALSE); 989 } 990 991 if (surface == EGL_NO_SURFACE) 992 { 993 return egl::error(EGL_BAD_SURFACE, EGL_FALSE); 994 } 995 996 if (eglSurface->postSubBuffer(x, y, width, height)) 997 { 998 return egl::success(EGL_TRUE); 999 } 1000 1001 return EGL_FALSE; 1002} 1003 1004__eglMustCastToProperFunctionPointerType __stdcall eglGetProcAddress(const char *procname) 1005{ 1006 EVENT("(const char *procname = \"%s\")", procname); 1007 1008 struct Extension 1009 { 1010 const char *name; 1011 __eglMustCastToProperFunctionPointerType address; 1012 }; 1013 1014 static const Extension eglExtensions[] = 1015 { 1016 { "eglQuerySurfacePointerANGLE", (__eglMustCastToProperFunctionPointerType)eglQuerySurfacePointerANGLE }, 1017 { "eglPostSubBufferNV", (__eglMustCastToProperFunctionPointerType)eglPostSubBufferNV }, 1018 { "eglGetPlatformDisplayEXT", (__eglMustCastToProperFunctionPointerType)eglGetPlatformDisplayEXT }, 1019 { "", NULL }, 1020 }; 1021 1022 for (unsigned int ext = 0; ext < ArraySize(eglExtensions); ext++) 1023 { 1024 if (strcmp(procname, eglExtensions[ext].name) == 0) 1025 { 1026 return (__eglMustCastToProperFunctionPointerType)eglExtensions[ext].address; 1027 } 1028 } 1029 1030 return glGetProcAddress(procname); 1031} 1032} 1033