eglapi.c revision 804488518296fbf20b06244bc0aa2e2793c61998
1/************************************************************************** 2 * 3 * Copyright 2008 VMware, Inc. 4 * Copyright 2009-2010 Chia-I Wu <olvaffe@gmail.com> 5 * Copyright 2010-2011 LunarG, Inc. 6 * All Rights Reserved. 7 * 8 * Permission is hereby granted, free of charge, to any person obtaining a 9 * copy of this software and associated documentation files (the 10 * "Software"), to deal in the Software without restriction, including 11 * without limitation the rights to use, copy, modify, merge, publish, 12 * distribute, sub license, and/or sell copies of the Software, and to 13 * permit persons to whom the Software is furnished to do so, subject to 14 * the following conditions: 15 * 16 * The above copyright notice and this permission notice (including the 17 * next paragraph) shall be included in all copies or substantial portions 18 * of the Software. 19 * 20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 23 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 25 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 26 * DEALINGS IN THE SOFTWARE. 27 * 28 **************************************************************************/ 29 30 31/** 32 * Public EGL API entrypoints 33 * 34 * Generally, we use the EGLDisplay parameter as a key to lookup the 35 * appropriate device driver handle, then jump though the driver's 36 * dispatch table to handle the function. 37 * 38 * That allows us the option of supporting multiple, simultaneous, 39 * heterogeneous hardware devices in the future. 40 * 41 * The EGLDisplay, EGLConfig, EGLContext and EGLSurface types are 42 * opaque handles. Internal objects are linked to a display to 43 * create the handles. 44 * 45 * For each public API entry point, the opaque handles are looked up 46 * before being dispatched to the drivers. When it fails to look up 47 * a handle, one of 48 * 49 * EGL_BAD_DISPLAY 50 * EGL_BAD_CONFIG 51 * EGL_BAD_CONTEXT 52 * EGL_BAD_SURFACE 53 * EGL_BAD_SCREEN_MESA 54 * EGL_BAD_MODE_MESA 55 * 56 * is generated and the driver function is not called. An 57 * uninitialized EGLDisplay has no driver associated with it. When 58 * such display is detected, 59 * 60 * EGL_NOT_INITIALIZED 61 * 62 * is generated. 63 * 64 * Some of the entry points use current display, context, or surface 65 * implicitly. For such entry points, the implicit objects are also 66 * checked before calling the driver function. Other than the 67 * errors listed above, 68 * 69 * EGL_BAD_CURRENT_SURFACE 70 * 71 * may also be generated. 72 * 73 * Notes on naming conventions: 74 * 75 * eglFooBar - public EGL function 76 * EGL_FOO_BAR - public EGL token 77 * EGLDatatype - public EGL datatype 78 * 79 * _eglFooBar - private EGL function 80 * _EGLDatatype - private EGL datatype, typedef'd struct 81 * _egl_struct - private EGL struct, non-typedef'd 82 * 83 */ 84 85 86#include <stdio.h> 87#include <stdlib.h> 88#include <string.h> 89#include "c99_compat.h" 90#include "c11/threads.h" 91#include "GL/mesa_glinterop.h" 92#include "eglcompiler.h" 93 94#include "eglglobals.h" 95#include "eglcontext.h" 96#include "egldisplay.h" 97#include "egltypedefs.h" 98#include "eglcurrent.h" 99#include "egldriver.h" 100#include "eglsurface.h" 101#include "eglconfig.h" 102#include "eglimage.h" 103#include "eglsync.h" 104 105 106/** 107 * Macros to help return an API entrypoint. 108 * 109 * These macros will unlock the display and record the error code. 110 */ 111#define RETURN_EGL_ERROR(disp, err, ret) \ 112 do { \ 113 if (disp) \ 114 _eglUnlockDisplay(disp); \ 115 /* EGL error codes are non-zero */ \ 116 if (err) \ 117 _eglError(err, __func__); \ 118 return ret; \ 119 } while (0) 120 121#define RETURN_EGL_SUCCESS(disp, ret) \ 122 RETURN_EGL_ERROR(disp, EGL_SUCCESS, ret) 123 124/* record EGL_SUCCESS only when ret evaluates to true */ 125#define RETURN_EGL_EVAL(disp, ret) \ 126 RETURN_EGL_ERROR(disp, (ret) ? EGL_SUCCESS : 0, ret) 127 128 129/* 130 * A bunch of macros and checks to simplify error checking. 131 */ 132 133#define _EGL_CHECK_DISPLAY(disp, ret, drv) \ 134 do { \ 135 drv = _eglCheckDisplay(disp, __func__); \ 136 if (!drv) \ 137 RETURN_EGL_ERROR(disp, 0, ret); \ 138 } while (0) 139 140#define _EGL_CHECK_OBJECT(disp, type, obj, ret, drv) \ 141 do { \ 142 drv = _eglCheck ## type(disp, obj, __func__); \ 143 if (!drv) \ 144 RETURN_EGL_ERROR(disp, 0, ret); \ 145 } while (0) 146 147#define _EGL_CHECK_SURFACE(disp, surf, ret, drv) \ 148 _EGL_CHECK_OBJECT(disp, Surface, surf, ret, drv) 149 150#define _EGL_CHECK_CONTEXT(disp, context, ret, drv) \ 151 _EGL_CHECK_OBJECT(disp, Context, context, ret, drv) 152 153#define _EGL_CHECK_CONFIG(disp, conf, ret, drv) \ 154 _EGL_CHECK_OBJECT(disp, Config, conf, ret, drv) 155 156#define _EGL_CHECK_SYNC(disp, s, ret, drv) \ 157 _EGL_CHECK_OBJECT(disp, Sync, s, ret, drv) 158 159 160static inline _EGLDriver * 161_eglCheckDisplay(_EGLDisplay *disp, const char *msg) 162{ 163 if (!disp) { 164 _eglError(EGL_BAD_DISPLAY, msg); 165 return NULL; 166 } 167 if (!disp->Initialized) { 168 _eglError(EGL_NOT_INITIALIZED, msg); 169 return NULL; 170 } 171 return disp->Driver; 172} 173 174 175static inline _EGLDriver * 176_eglCheckSurface(_EGLDisplay *disp, _EGLSurface *surf, const char *msg) 177{ 178 _EGLDriver *drv = _eglCheckDisplay(disp, msg); 179 if (!drv) 180 return NULL; 181 if (!surf) { 182 _eglError(EGL_BAD_SURFACE, msg); 183 return NULL; 184 } 185 return drv; 186} 187 188 189static inline _EGLDriver * 190_eglCheckContext(_EGLDisplay *disp, _EGLContext *context, const char *msg) 191{ 192 _EGLDriver *drv = _eglCheckDisplay(disp, msg); 193 if (!drv) 194 return NULL; 195 if (!context) { 196 _eglError(EGL_BAD_CONTEXT, msg); 197 return NULL; 198 } 199 return drv; 200} 201 202 203static inline _EGLDriver * 204_eglCheckConfig(_EGLDisplay *disp, _EGLConfig *conf, const char *msg) 205{ 206 _EGLDriver *drv = _eglCheckDisplay(disp, msg); 207 if (!drv) 208 return NULL; 209 if (!conf) { 210 _eglError(EGL_BAD_CONFIG, msg); 211 return NULL; 212 } 213 return drv; 214} 215 216 217static inline _EGLDriver * 218_eglCheckSync(_EGLDisplay *disp, _EGLSync *s, const char *msg) 219{ 220 _EGLDriver *drv = _eglCheckDisplay(disp, msg); 221 if (!drv) 222 return NULL; 223 if (!s) { 224 _eglError(EGL_BAD_PARAMETER, msg); 225 return NULL; 226 } 227 return drv; 228} 229 230 231/** 232 * Lookup and lock a display. 233 */ 234static inline _EGLDisplay * 235_eglLockDisplay(EGLDisplay display) 236{ 237 _EGLDisplay *dpy = _eglLookupDisplay(display); 238 if (dpy) 239 mtx_lock(&dpy->Mutex); 240 return dpy; 241} 242 243 244/** 245 * Unlock a display. 246 */ 247static inline void 248_eglUnlockDisplay(_EGLDisplay *dpy) 249{ 250 mtx_unlock(&dpy->Mutex); 251} 252 253static EGLBoolean 254_eglSetFuncName(const char *funcName, _EGLDisplay *disp, EGLenum objectType, _EGLResource *object) 255{ 256 _EGLThreadInfo *thr = _eglGetCurrentThread(); 257 if (!_eglIsCurrentThreadDummy()) { 258 thr->CurrentFuncName = funcName; 259 thr->CurrentObjectLabel = NULL; 260 261 if (objectType == EGL_OBJECT_THREAD_KHR) 262 thr->CurrentObjectLabel = thr->Label; 263 else if (objectType == EGL_OBJECT_DISPLAY_KHR && disp) 264 thr->CurrentObjectLabel = disp->Label; 265 else if (object) 266 thr->CurrentObjectLabel = object->Label; 267 268 return EGL_TRUE; 269 } 270 271 _eglDebugReportFull(EGL_BAD_ALLOC, funcName, funcName, 272 EGL_DEBUG_MSG_CRITICAL_KHR, NULL, NULL); 273 return EGL_FALSE; 274} 275 276#define _EGL_FUNC_START(disp, objectType, object, ret) \ 277 do { \ 278 if (!_eglSetFuncName(__func__, disp, objectType, (_EGLResource *) object)) { \ 279 if (disp) \ 280 _eglUnlockDisplay(disp); \ 281 return ret; \ 282 } \ 283 } while(0) 284 285/** 286 * Convert an attribute list from EGLint[] to EGLAttrib[]. 287 * 288 * Return an EGL error code. The output parameter out_attrib_list is modified 289 * only on success. 290 */ 291EGLint 292_eglConvertIntsToAttribs(const EGLint *int_list, EGLAttrib **out_attrib_list) 293{ 294 size_t len = 0; 295 EGLAttrib *attrib_list; 296 297 if (int_list) { 298 while (int_list[2*len] != EGL_NONE) 299 ++len; 300 } 301 302 if (len == 0) { 303 *out_attrib_list = NULL; 304 return EGL_SUCCESS; 305 } 306 307 if (2*len + 1 > SIZE_MAX / sizeof(EGLAttrib)) 308 return EGL_BAD_ALLOC; 309 310 attrib_list = malloc((2*len + 1) * sizeof(EGLAttrib)); 311 if (!attrib_list) 312 return EGL_BAD_ALLOC; 313 314 for (size_t i = 0; i < len; ++i) { 315 attrib_list[2*i + 0] = int_list[2*i + 0]; 316 attrib_list[2*i + 1] = int_list[2*i + 1]; 317 } 318 319 attrib_list[2*len] = EGL_NONE; 320 321 *out_attrib_list = attrib_list; 322 return EGL_SUCCESS; 323} 324 325 326static EGLint * 327_eglConvertAttribsToInt(const EGLAttrib *attr_list) 328{ 329 EGLint *int_attribs = NULL; 330 331 /* Convert attributes from EGLAttrib[] to EGLint[] */ 332 if (attr_list) { 333 int i, size = 0; 334 335 while (attr_list[size] != EGL_NONE) 336 size += 2; 337 338 size += 1; /* add space for EGL_NONE */ 339 340 int_attribs = calloc(size, sizeof(int_attribs[0])); 341 if (!int_attribs) 342 return NULL; 343 344 for (i = 0; i < size; i++) 345 int_attribs[i] = attr_list[i]; 346 } 347 return int_attribs; 348} 349 350 351/** 352 * This is typically the first EGL function that an application calls. 353 * It associates a private _EGLDisplay object to the native display. 354 */ 355EGLDisplay EGLAPIENTRY 356eglGetDisplay(EGLNativeDisplayType nativeDisplay) 357{ 358 _EGLPlatformType plat; 359 _EGLDisplay *dpy; 360 void *native_display_ptr; 361 362 _EGL_FUNC_START(NULL, EGL_OBJECT_THREAD_KHR, NULL, EGL_NO_DISPLAY); 363 364 STATIC_ASSERT(sizeof(void*) == sizeof(nativeDisplay)); 365 native_display_ptr = (void*) nativeDisplay; 366 367 plat = _eglGetNativePlatform(native_display_ptr); 368 dpy = _eglFindDisplay(plat, native_display_ptr); 369 return _eglGetDisplayHandle(dpy); 370} 371 372static EGLDisplay 373_eglGetPlatformDisplayCommon(EGLenum platform, void *native_display, 374 const EGLint *attrib_list) 375{ 376 _EGLDisplay *dpy; 377 378 switch (platform) { 379#ifdef HAVE_X11_PLATFORM 380 case EGL_PLATFORM_X11_EXT: 381 dpy = _eglGetX11Display((Display*) native_display, attrib_list); 382 break; 383#endif 384#ifdef HAVE_DRM_PLATFORM 385 case EGL_PLATFORM_GBM_MESA: 386 dpy = _eglGetGbmDisplay((struct gbm_device*) native_display, 387 attrib_list); 388 break; 389#endif 390#ifdef HAVE_WAYLAND_PLATFORM 391 case EGL_PLATFORM_WAYLAND_EXT: 392 dpy = _eglGetWaylandDisplay((struct wl_display*) native_display, 393 attrib_list); 394 break; 395#endif 396 default: 397 RETURN_EGL_ERROR(NULL, EGL_BAD_PARAMETER, NULL); 398 } 399 400 return _eglGetDisplayHandle(dpy); 401} 402 403static EGLDisplay EGLAPIENTRY 404eglGetPlatformDisplayEXT(EGLenum platform, void *native_display, 405 const EGLint *attrib_list) 406{ 407 _EGL_FUNC_START(NULL, EGL_OBJECT_THREAD_KHR, NULL, EGL_NO_DISPLAY); 408 return _eglGetPlatformDisplayCommon(platform, native_display, attrib_list); 409} 410 411EGLDisplay EGLAPIENTRY 412eglGetPlatformDisplay(EGLenum platform, void *native_display, 413 const EGLAttrib *attrib_list) 414{ 415 EGLDisplay display; 416 EGLint *int_attribs; 417 418 _EGL_FUNC_START(NULL, EGL_OBJECT_THREAD_KHR, NULL, EGL_NO_DISPLAY); 419 420 int_attribs = _eglConvertAttribsToInt(attrib_list); 421 if (attrib_list && !int_attribs) 422 RETURN_EGL_ERROR(NULL, EGL_BAD_ALLOC, NULL); 423 424 display = _eglGetPlatformDisplayCommon(platform, native_display, int_attribs); 425 free(int_attribs); 426 return display; 427} 428 429/** 430 * Copy the extension into the string and update the string pointer. 431 */ 432static EGLint 433_eglAppendExtension(char **str, const char *ext) 434{ 435 char *s = *str; 436 size_t len = strlen(ext); 437 438 if (s) { 439 memcpy(s, ext, len); 440 s[len++] = ' '; 441 s[len] = '\0'; 442 443 *str += len; 444 } 445 else { 446 len++; 447 } 448 449 return (EGLint) len; 450} 451 452/** 453 * Examine the individual extension enable/disable flags and recompute 454 * the driver's Extensions string. 455 */ 456static void 457_eglCreateExtensionsString(_EGLDisplay *dpy) 458{ 459#define _EGL_CHECK_EXTENSION(ext) \ 460 do { \ 461 if (dpy->Extensions.ext) { \ 462 _eglAppendExtension(&exts, "EGL_" #ext); \ 463 assert(exts <= dpy->ExtensionsString + _EGL_MAX_EXTENSIONS_LEN); \ 464 } \ 465 } while (0) 466 467 char *exts = dpy->ExtensionsString; 468 469 /* Please keep these sorted alphabetically. */ 470 _EGL_CHECK_EXTENSION(ANDROID_framebuffer_target); 471 _EGL_CHECK_EXTENSION(ANDROID_image_native_buffer); 472 _EGL_CHECK_EXTENSION(ANDROID_recordable); 473 474 _EGL_CHECK_EXTENSION(CHROMIUM_sync_control); 475 476 _EGL_CHECK_EXTENSION(EXT_buffer_age); 477 _EGL_CHECK_EXTENSION(EXT_create_context_robustness); 478 _EGL_CHECK_EXTENSION(EXT_image_dma_buf_import); 479 _EGL_CHECK_EXTENSION(EXT_swap_buffers_with_damage); 480 481 _EGL_CHECK_EXTENSION(KHR_cl_event2); 482 _EGL_CHECK_EXTENSION(KHR_create_context); 483 _EGL_CHECK_EXTENSION(KHR_fence_sync); 484 _EGL_CHECK_EXTENSION(KHR_get_all_proc_addresses); 485 _EGL_CHECK_EXTENSION(KHR_gl_colorspace); 486 _EGL_CHECK_EXTENSION(KHR_gl_renderbuffer_image); 487 _EGL_CHECK_EXTENSION(KHR_gl_texture_2D_image); 488 _EGL_CHECK_EXTENSION(KHR_gl_texture_3D_image); 489 _EGL_CHECK_EXTENSION(KHR_gl_texture_cubemap_image); 490 if (dpy->Extensions.KHR_image_base && dpy->Extensions.KHR_image_pixmap) 491 _eglAppendExtension(&exts, "EGL_KHR_image"); 492 _EGL_CHECK_EXTENSION(KHR_image_base); 493 _EGL_CHECK_EXTENSION(KHR_image_pixmap); 494 _EGL_CHECK_EXTENSION(KHR_no_config_context); 495 _EGL_CHECK_EXTENSION(KHR_reusable_sync); 496 _EGL_CHECK_EXTENSION(KHR_surfaceless_context); 497 _EGL_CHECK_EXTENSION(KHR_wait_sync); 498 499 if (dpy->Extensions.KHR_no_config_context) 500 _eglAppendExtension(&exts, "EGL_MESA_configless_context"); 501 _EGL_CHECK_EXTENSION(MESA_drm_image); 502 _EGL_CHECK_EXTENSION(MESA_image_dma_buf_export); 503 504 _EGL_CHECK_EXTENSION(NOK_swap_region); 505 _EGL_CHECK_EXTENSION(NOK_texture_from_pixmap); 506 507 _EGL_CHECK_EXTENSION(NV_post_sub_buffer); 508 509 _EGL_CHECK_EXTENSION(WL_bind_wayland_display); 510 _EGL_CHECK_EXTENSION(WL_create_wayland_buffer_from_image); 511 512#undef _EGL_CHECK_EXTENSION 513} 514 515static void 516_eglCreateAPIsString(_EGLDisplay *dpy) 517{ 518 if (dpy->ClientAPIs & EGL_OPENGL_BIT) 519 strcat(dpy->ClientAPIsString, "OpenGL "); 520 521 if (dpy->ClientAPIs & EGL_OPENGL_ES_BIT || 522 dpy->ClientAPIs & EGL_OPENGL_ES2_BIT || 523 dpy->ClientAPIs & EGL_OPENGL_ES3_BIT_KHR) { 524 strcat(dpy->ClientAPIsString, "OpenGL_ES "); 525 } 526 527 if (dpy->ClientAPIs & EGL_OPENVG_BIT) 528 strcat(dpy->ClientAPIsString, "OpenVG "); 529 530 assert(strlen(dpy->ClientAPIsString) < sizeof(dpy->ClientAPIsString)); 531} 532 533static void 534_eglComputeVersion(_EGLDisplay *disp) 535{ 536 disp->Version = 14; 537 538 if (disp->Extensions.KHR_fence_sync && 539 disp->Extensions.KHR_cl_event2 && 540 disp->Extensions.KHR_wait_sync && 541 disp->Extensions.KHR_image_base && 542 disp->Extensions.KHR_gl_texture_2D_image && 543 disp->Extensions.KHR_gl_texture_3D_image && 544 disp->Extensions.KHR_gl_texture_cubemap_image && 545 disp->Extensions.KHR_gl_renderbuffer_image && 546 disp->Extensions.KHR_create_context && 547 disp->Extensions.EXT_create_context_robustness && 548 disp->Extensions.KHR_get_all_proc_addresses && 549 disp->Extensions.KHR_gl_colorspace && 550 disp->Extensions.KHR_surfaceless_context) 551 disp->Version = 15; 552} 553 554/** 555 * This is typically the second EGL function that an application calls. 556 * Here we load/initialize the actual hardware driver. 557 */ 558EGLBoolean EGLAPIENTRY 559eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor) 560{ 561 _EGLDisplay *disp = _eglLockDisplay(dpy); 562 563 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE); 564 565 if (!disp) 566 RETURN_EGL_ERROR(NULL, EGL_BAD_DISPLAY, EGL_FALSE); 567 568 if (!disp->Initialized) { 569 if (!_eglMatchDriver(disp, EGL_FALSE)) 570 RETURN_EGL_ERROR(disp, EGL_NOT_INITIALIZED, EGL_FALSE); 571 572 /* limit to APIs supported by core */ 573 disp->ClientAPIs &= _EGL_API_ALL_BITS; 574 575 /* EGL_KHR_get_all_proc_addresses is a corner-case extension. The spec 576 * classifies it as an EGL display extension, though conceptually it's an 577 * EGL client extension. 578 * 579 * From the EGL_KHR_get_all_proc_addresses spec: 580 * 581 * The EGL implementation must expose the name 582 * EGL_KHR_client_get_all_proc_addresses if and only if it exposes 583 * EGL_KHR_get_all_proc_addresses and supports 584 * EGL_EXT_client_extensions. 585 * 586 * Mesa unconditionally exposes both client extensions mentioned above, 587 * so the spec requires that each EGLDisplay unconditionally expose 588 * EGL_KHR_get_all_proc_addresses also. 589 */ 590 disp->Extensions.KHR_get_all_proc_addresses = EGL_TRUE; 591 592 _eglComputeVersion(disp); 593 _eglCreateExtensionsString(disp); 594 _eglCreateAPIsString(disp); 595 snprintf(disp->VersionString, sizeof(disp->VersionString), 596 "%d.%d (%s)", disp->Version / 10, disp->Version % 10, 597 disp->Driver->Name); 598 } 599 600 /* Update applications version of major and minor if not NULL */ 601 if ((major != NULL) && (minor != NULL)) { 602 *major = disp->Version / 10; 603 *minor = disp->Version % 10; 604 } 605 606 RETURN_EGL_SUCCESS(disp, EGL_TRUE); 607} 608 609 610EGLBoolean EGLAPIENTRY 611eglTerminate(EGLDisplay dpy) 612{ 613 _EGLDisplay *disp = _eglLockDisplay(dpy); 614 615 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE); 616 617 if (!disp) 618 RETURN_EGL_ERROR(NULL, EGL_BAD_DISPLAY, EGL_FALSE); 619 620 if (disp->Initialized) { 621 _EGLDriver *drv = disp->Driver; 622 623 drv->API.Terminate(drv, disp); 624 /* do not reset disp->Driver */ 625 disp->ClientAPIsString[0] = 0; 626 disp->Initialized = EGL_FALSE; 627 } 628 629 RETURN_EGL_SUCCESS(disp, EGL_TRUE); 630} 631 632 633const char * EGLAPIENTRY 634eglQueryString(EGLDisplay dpy, EGLint name) 635{ 636 _EGLDisplay *disp; 637 _EGLDriver *drv; 638 639 if (dpy == EGL_NO_DISPLAY && name == EGL_EXTENSIONS) { 640 RETURN_EGL_SUCCESS(NULL, _eglGlobal.ClientExtensionString); 641 } 642 643 disp = _eglLockDisplay(dpy); 644 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, NULL); 645 _EGL_CHECK_DISPLAY(disp, NULL, drv); 646 647 switch (name) { 648 case EGL_VENDOR: 649 RETURN_EGL_SUCCESS(disp, _EGL_VENDOR_STRING); 650 case EGL_VERSION: 651 RETURN_EGL_SUCCESS(disp, disp->VersionString); 652 case EGL_EXTENSIONS: 653 RETURN_EGL_SUCCESS(disp, disp->ExtensionsString); 654 case EGL_CLIENT_APIS: 655 RETURN_EGL_SUCCESS(disp, disp->ClientAPIsString); 656 default: 657 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, NULL); 658 } 659} 660 661 662EGLBoolean EGLAPIENTRY 663eglGetConfigs(EGLDisplay dpy, EGLConfig *configs, 664 EGLint config_size, EGLint *num_config) 665{ 666 _EGLDisplay *disp = _eglLockDisplay(dpy); 667 _EGLDriver *drv; 668 EGLBoolean ret; 669 670 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE); 671 672 _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv); 673 ret = drv->API.GetConfigs(drv, disp, configs, config_size, num_config); 674 675 RETURN_EGL_EVAL(disp, ret); 676} 677 678 679EGLBoolean EGLAPIENTRY 680eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, 681 EGLint config_size, EGLint *num_config) 682{ 683 _EGLDisplay *disp = _eglLockDisplay(dpy); 684 _EGLDriver *drv; 685 EGLBoolean ret; 686 687 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE); 688 689 _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv); 690 ret = drv->API.ChooseConfig(drv, disp, attrib_list, configs, 691 config_size, num_config); 692 693 RETURN_EGL_EVAL(disp, ret); 694} 695 696 697EGLBoolean EGLAPIENTRY 698eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, 699 EGLint attribute, EGLint *value) 700{ 701 _EGLDisplay *disp = _eglLockDisplay(dpy); 702 _EGLConfig *conf = _eglLookupConfig(config, disp); 703 _EGLDriver *drv; 704 EGLBoolean ret; 705 706 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE); 707 708 _EGL_CHECK_CONFIG(disp, conf, EGL_FALSE, drv); 709 ret = drv->API.GetConfigAttrib(drv, disp, conf, attribute, value); 710 711 RETURN_EGL_EVAL(disp, ret); 712} 713 714 715EGLContext EGLAPIENTRY 716eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_list, 717 const EGLint *attrib_list) 718{ 719 _EGLDisplay *disp = _eglLockDisplay(dpy); 720 _EGLConfig *conf = _eglLookupConfig(config, disp); 721 _EGLContext *share = _eglLookupContext(share_list, disp); 722 _EGLDriver *drv; 723 _EGLContext *context; 724 EGLContext ret; 725 726 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_CONTEXT); 727 728 _EGL_CHECK_DISPLAY(disp, EGL_NO_CONTEXT, drv); 729 730 if (!config && !disp->Extensions.KHR_no_config_context) 731 RETURN_EGL_ERROR(disp, EGL_BAD_CONFIG, EGL_NO_CONTEXT); 732 733 if (!share && share_list != EGL_NO_CONTEXT) 734 RETURN_EGL_ERROR(disp, EGL_BAD_CONTEXT, EGL_NO_CONTEXT); 735 736 context = drv->API.CreateContext(drv, disp, conf, share, attrib_list); 737 ret = (context) ? _eglLinkContext(context) : EGL_NO_CONTEXT; 738 739 RETURN_EGL_EVAL(disp, ret); 740} 741 742 743EGLBoolean EGLAPIENTRY 744eglDestroyContext(EGLDisplay dpy, EGLContext ctx) 745{ 746 _EGLDisplay *disp = _eglLockDisplay(dpy); 747 _EGLContext *context = _eglLookupContext(ctx, disp); 748 _EGLDriver *drv; 749 EGLBoolean ret; 750 751 _EGL_FUNC_START(disp, EGL_OBJECT_CONTEXT_KHR, context, EGL_FALSE); 752 753 _EGL_CHECK_CONTEXT(disp, context, EGL_FALSE, drv); 754 _eglUnlinkContext(context); 755 ret = drv->API.DestroyContext(drv, disp, context); 756 757 RETURN_EGL_EVAL(disp, ret); 758} 759 760 761EGLBoolean EGLAPIENTRY 762eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, 763 EGLContext ctx) 764{ 765 _EGLDisplay *disp = _eglLockDisplay(dpy); 766 _EGLContext *context = _eglLookupContext(ctx, disp); 767 _EGLSurface *draw_surf = _eglLookupSurface(draw, disp); 768 _EGLSurface *read_surf = _eglLookupSurface(read, disp); 769 _EGLDriver *drv; 770 EGLBoolean ret; 771 772 _EGL_FUNC_START(disp, EGL_OBJECT_CONTEXT_KHR, context, EGL_FALSE); 773 774 if (!disp) 775 RETURN_EGL_ERROR(disp, EGL_BAD_DISPLAY, EGL_FALSE); 776 drv = disp->Driver; 777 778 /* display is allowed to be uninitialized under certain condition */ 779 if (!disp->Initialized) { 780 if (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE || 781 ctx != EGL_NO_CONTEXT) 782 RETURN_EGL_ERROR(disp, EGL_BAD_DISPLAY, EGL_FALSE); 783 } 784 if (!drv) 785 RETURN_EGL_SUCCESS(disp, EGL_TRUE); 786 787 if (!context && ctx != EGL_NO_CONTEXT) 788 RETURN_EGL_ERROR(disp, EGL_BAD_CONTEXT, EGL_FALSE); 789 if (!draw_surf || !read_surf) { 790 /* From the EGL 1.4 (20130211) spec: 791 * 792 * To release the current context without assigning a new one, set ctx 793 * to EGL_NO_CONTEXT and set draw and read to EGL_NO_SURFACE. 794 */ 795 if (!disp->Extensions.KHR_surfaceless_context && ctx != EGL_NO_CONTEXT) 796 RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE); 797 798 if ((!draw_surf && draw != EGL_NO_SURFACE) || 799 (!read_surf && read != EGL_NO_SURFACE)) 800 RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE); 801 if (draw_surf || read_surf) 802 RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_FALSE); 803 } 804 805 ret = drv->API.MakeCurrent(drv, disp, draw_surf, read_surf, context); 806 807 RETURN_EGL_EVAL(disp, ret); 808} 809 810 811EGLBoolean EGLAPIENTRY 812eglQueryContext(EGLDisplay dpy, EGLContext ctx, 813 EGLint attribute, EGLint *value) 814{ 815 _EGLDisplay *disp = _eglLockDisplay(dpy); 816 _EGLContext *context = _eglLookupContext(ctx, disp); 817 _EGLDriver *drv; 818 EGLBoolean ret; 819 820 _EGL_FUNC_START(disp, EGL_OBJECT_CONTEXT_KHR, context, EGL_FALSE); 821 822 _EGL_CHECK_CONTEXT(disp, context, EGL_FALSE, drv); 823 ret = drv->API.QueryContext(drv, disp, context, attribute, value); 824 825 RETURN_EGL_EVAL(disp, ret); 826} 827 828 829static EGLSurface 830_eglCreateWindowSurfaceCommon(_EGLDisplay *disp, EGLConfig config, 831 void *native_window, const EGLint *attrib_list) 832{ 833 _EGLConfig *conf = _eglLookupConfig(config, disp); 834 _EGLDriver *drv; 835 _EGLSurface *surf; 836 EGLSurface ret; 837 838 _EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE, drv); 839 840 if (native_window == NULL) 841 RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE); 842 843 surf = drv->API.CreateWindowSurface(drv, disp, conf, native_window, 844 attrib_list); 845 ret = (surf) ? _eglLinkSurface(surf) : EGL_NO_SURFACE; 846 847 RETURN_EGL_EVAL(disp, ret); 848} 849 850 851EGLSurface EGLAPIENTRY 852eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, 853 EGLNativeWindowType window, const EGLint *attrib_list) 854{ 855 _EGLDisplay *disp = _eglLockDisplay(dpy); 856 857 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE); 858 STATIC_ASSERT(sizeof(void*) == sizeof(window)); 859 return _eglCreateWindowSurfaceCommon(disp, config, (void*) window, 860 attrib_list); 861} 862 863static void * 864fixupNativeWindow(_EGLDisplay *disp, void *native_window) 865{ 866#ifdef HAVE_X11_PLATFORM 867 if (disp->Platform == _EGL_PLATFORM_X11 && native_window != NULL) { 868 /* The `native_window` parameter for the X11 platform differs between 869 * eglCreateWindowSurface() and eglCreatePlatformPixmapSurfaceEXT(). In 870 * eglCreateWindowSurface(), the type of `native_window` is an Xlib 871 * `Window`. In eglCreatePlatformWindowSurfaceEXT(), the type is 872 * `Window*`. Convert `Window*` to `Window` because that's what 873 * dri2_x11_create_window_surface() expects. 874 */ 875 return (void *)(* (Window*) native_window); 876 } 877#endif 878 return native_window; 879} 880 881static EGLSurface EGLAPIENTRY 882eglCreatePlatformWindowSurfaceEXT(EGLDisplay dpy, EGLConfig config, 883 void *native_window, 884 const EGLint *attrib_list) 885{ 886 _EGLDisplay *disp = _eglLockDisplay(dpy); 887 888 native_window = fixupNativeWindow(disp, native_window); 889 890 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE); 891 return _eglCreateWindowSurfaceCommon(disp, config, native_window, 892 attrib_list); 893} 894 895 896EGLSurface EGLAPIENTRY 897eglCreatePlatformWindowSurface(EGLDisplay dpy, EGLConfig config, 898 void *native_window, 899 const EGLAttrib *attrib_list) 900{ 901 _EGLDisplay *disp = _eglLockDisplay(dpy); 902 EGLSurface surface; 903 EGLint *int_attribs; 904 905 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE); 906 907 int_attribs = _eglConvertAttribsToInt(attrib_list); 908 if (attrib_list && !int_attribs) 909 RETURN_EGL_ERROR(disp, EGL_BAD_ALLOC, EGL_NO_SURFACE); 910 911 native_window = fixupNativeWindow(disp, native_window); 912 surface = _eglCreateWindowSurfaceCommon(disp, config, native_window, 913 int_attribs); 914 free(int_attribs); 915 return surface; 916} 917 918static void * 919fixupNativePixmap(_EGLDisplay *disp, void *native_pixmap) 920{ 921#ifdef HAVE_X11_PLATFORM 922 /* The `native_pixmap` parameter for the X11 platform differs between 923 * eglCreatePixmapSurface() and eglCreatePlatformPixmapSurfaceEXT(). In 924 * eglCreatePixmapSurface(), the type of `native_pixmap` is an Xlib 925 * `Pixmap`. In eglCreatePlatformPixmapSurfaceEXT(), the type is 926 * `Pixmap*`. Convert `Pixmap*` to `Pixmap` because that's what 927 * dri2_x11_create_pixmap_surface() expects. 928 */ 929 if (disp->Platform == _EGL_PLATFORM_X11 && native_pixmap != NULL) 930 return (void *)(* (Pixmap*) native_pixmap); 931#endif 932 return native_pixmap; 933} 934 935static EGLSurface 936_eglCreatePixmapSurfaceCommon(_EGLDisplay *disp, EGLConfig config, 937 void *native_pixmap, const EGLint *attrib_list) 938{ 939 _EGLConfig *conf = _eglLookupConfig(config, disp); 940 _EGLDriver *drv; 941 _EGLSurface *surf; 942 EGLSurface ret; 943 944 _EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE, drv); 945 surf = drv->API.CreatePixmapSurface(drv, disp, conf, native_pixmap, 946 attrib_list); 947 ret = (surf) ? _eglLinkSurface(surf) : EGL_NO_SURFACE; 948 949 RETURN_EGL_EVAL(disp, ret); 950} 951 952 953EGLSurface EGLAPIENTRY 954eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, 955 EGLNativePixmapType pixmap, const EGLint *attrib_list) 956{ 957 _EGLDisplay *disp = _eglLockDisplay(dpy); 958 959 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE); 960 STATIC_ASSERT(sizeof(void*) == sizeof(pixmap)); 961 return _eglCreatePixmapSurfaceCommon(disp, config, (void*) pixmap, 962 attrib_list); 963} 964 965static EGLSurface EGLAPIENTRY 966eglCreatePlatformPixmapSurfaceEXT(EGLDisplay dpy, EGLConfig config, 967 void *native_pixmap, 968 const EGLint *attrib_list) 969{ 970 _EGLDisplay *disp = _eglLockDisplay(dpy); 971 972 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE); 973 native_pixmap = fixupNativePixmap(disp, native_pixmap); 974 return _eglCreatePixmapSurfaceCommon(disp, config, native_pixmap, 975 attrib_list); 976} 977 978 979EGLSurface EGLAPIENTRY 980eglCreatePlatformPixmapSurface(EGLDisplay dpy, EGLConfig config, 981 void *native_pixmap, 982 const EGLAttrib *attrib_list) 983{ 984 _EGLDisplay *disp = _eglLockDisplay(dpy); 985 EGLSurface surface; 986 EGLint *int_attribs; 987 988 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE); 989 990 int_attribs = _eglConvertAttribsToInt(attrib_list); 991 if (attrib_list && !int_attribs) 992 RETURN_EGL_ERROR(disp, EGL_BAD_ALLOC, EGL_NO_SURFACE); 993 994 native_pixmap = fixupNativePixmap(disp, native_pixmap); 995 surface = _eglCreatePixmapSurfaceCommon(disp, config, native_pixmap, 996 int_attribs); 997 free(int_attribs); 998 return surface; 999} 1000 1001 1002EGLSurface EGLAPIENTRY 1003eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, 1004 const EGLint *attrib_list) 1005{ 1006 _EGLDisplay *disp = _eglLockDisplay(dpy); 1007 _EGLConfig *conf = _eglLookupConfig(config, disp); 1008 _EGLDriver *drv; 1009 _EGLSurface *surf; 1010 EGLSurface ret; 1011 1012 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE); 1013 _EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE, drv); 1014 1015 surf = drv->API.CreatePbufferSurface(drv, disp, conf, attrib_list); 1016 ret = (surf) ? _eglLinkSurface(surf) : EGL_NO_SURFACE; 1017 1018 RETURN_EGL_EVAL(disp, ret); 1019} 1020 1021 1022EGLBoolean EGLAPIENTRY 1023eglDestroySurface(EGLDisplay dpy, EGLSurface surface) 1024{ 1025 _EGLDisplay *disp = _eglLockDisplay(dpy); 1026 _EGLSurface *surf = _eglLookupSurface(surface, disp); 1027 _EGLDriver *drv; 1028 EGLBoolean ret; 1029 1030 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE); 1031 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv); 1032 _eglUnlinkSurface(surf); 1033 ret = drv->API.DestroySurface(drv, disp, surf); 1034 1035 RETURN_EGL_EVAL(disp, ret); 1036} 1037 1038EGLBoolean EGLAPIENTRY 1039eglQuerySurface(EGLDisplay dpy, EGLSurface surface, 1040 EGLint attribute, EGLint *value) 1041{ 1042 _EGLDisplay *disp = _eglLockDisplay(dpy); 1043 _EGLSurface *surf = _eglLookupSurface(surface, disp); 1044 _EGLDriver *drv; 1045 EGLBoolean ret; 1046 1047 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE); 1048 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv); 1049 ret = drv->API.QuerySurface(drv, disp, surf, attribute, value); 1050 1051 RETURN_EGL_EVAL(disp, ret); 1052} 1053 1054EGLBoolean EGLAPIENTRY 1055eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, 1056 EGLint attribute, EGLint value) 1057{ 1058 _EGLDisplay *disp = _eglLockDisplay(dpy); 1059 _EGLSurface *surf = _eglLookupSurface(surface, disp); 1060 _EGLDriver *drv; 1061 EGLBoolean ret; 1062 1063 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE); 1064 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv); 1065 ret = drv->API.SurfaceAttrib(drv, disp, surf, attribute, value); 1066 1067 RETURN_EGL_EVAL(disp, ret); 1068} 1069 1070 1071EGLBoolean EGLAPIENTRY 1072eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer) 1073{ 1074 _EGLDisplay *disp = _eglLockDisplay(dpy); 1075 _EGLSurface *surf = _eglLookupSurface(surface, disp); 1076 _EGLDriver *drv; 1077 EGLBoolean ret; 1078 1079 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE); 1080 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv); 1081 ret = drv->API.BindTexImage(drv, disp, surf, buffer); 1082 1083 RETURN_EGL_EVAL(disp, ret); 1084} 1085 1086 1087EGLBoolean EGLAPIENTRY 1088eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer) 1089{ 1090 _EGLDisplay *disp = _eglLockDisplay(dpy); 1091 _EGLSurface *surf = _eglLookupSurface(surface, disp); 1092 _EGLDriver *drv; 1093 EGLBoolean ret; 1094 1095 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE); 1096 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv); 1097 ret = drv->API.ReleaseTexImage(drv, disp, surf, buffer); 1098 1099 RETURN_EGL_EVAL(disp, ret); 1100} 1101 1102 1103EGLBoolean EGLAPIENTRY 1104eglSwapInterval(EGLDisplay dpy, EGLint interval) 1105{ 1106 _EGLDisplay *disp = _eglLockDisplay(dpy); 1107 _EGLContext *ctx = _eglGetCurrentContext(); 1108 _EGLSurface *surf = ctx ? ctx->DrawSurface : NULL; 1109 _EGLDriver *drv; 1110 EGLBoolean ret; 1111 1112 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE); 1113 _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv); 1114 1115 if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT || 1116 ctx->Resource.Display != disp) 1117 RETURN_EGL_ERROR(disp, EGL_BAD_CONTEXT, EGL_FALSE); 1118 1119 if (_eglGetSurfaceHandle(surf) == EGL_NO_SURFACE) 1120 RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE); 1121 1122 ret = drv->API.SwapInterval(drv, disp, surf, interval); 1123 1124 RETURN_EGL_EVAL(disp, ret); 1125} 1126 1127 1128EGLBoolean EGLAPIENTRY 1129eglSwapBuffers(EGLDisplay dpy, EGLSurface surface) 1130{ 1131 _EGLContext *ctx = _eglGetCurrentContext(); 1132 _EGLDisplay *disp = _eglLockDisplay(dpy); 1133 _EGLSurface *surf = _eglLookupSurface(surface, disp); 1134 _EGLDriver *drv; 1135 EGLBoolean ret; 1136 1137 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE); 1138 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv); 1139 1140 /* surface must be bound to current context in EGL 1.4 */ 1141 #ifndef _EGL_BUILT_IN_DRIVER_HAIKU 1142 if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT || 1143 surf != ctx->DrawSurface) 1144 RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE); 1145 #endif 1146 1147 ret = drv->API.SwapBuffers(drv, disp, surf); 1148 1149 RETURN_EGL_EVAL(disp, ret); 1150} 1151 1152 1153static EGLBoolean EGLAPIENTRY 1154eglSwapBuffersWithDamageEXT(EGLDisplay dpy, EGLSurface surface, 1155 EGLint *rects, EGLint n_rects) 1156{ 1157 _EGLContext *ctx = _eglGetCurrentContext(); 1158 _EGLDisplay *disp = _eglLockDisplay(dpy); 1159 _EGLSurface *surf = _eglLookupSurface(surface, disp); 1160 _EGLDriver *drv; 1161 EGLBoolean ret; 1162 1163 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE); 1164 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv); 1165 1166 /* surface must be bound to current context in EGL 1.4 */ 1167 if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT || 1168 surf != ctx->DrawSurface) 1169 RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE); 1170 1171 if ((n_rects > 0 && rects == NULL) || n_rects < 0) 1172 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE); 1173 1174 ret = drv->API.SwapBuffersWithDamageEXT(drv, disp, surf, rects, n_rects); 1175 1176 RETURN_EGL_EVAL(disp, ret); 1177} 1178 1179EGLBoolean EGLAPIENTRY 1180eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target) 1181{ 1182 _EGLDisplay *disp = _eglLockDisplay(dpy); 1183 _EGLSurface *surf = _eglLookupSurface(surface, disp); 1184 _EGLDriver *drv; 1185 EGLBoolean ret; 1186 void *native_pixmap_ptr; 1187 1188 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE); 1189 STATIC_ASSERT(sizeof(void*) == sizeof(target)); 1190 native_pixmap_ptr = (void*) target; 1191 1192 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv); 1193 if (disp->Platform != _eglGetNativePlatform(disp->PlatformDisplay)) 1194 RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_PIXMAP, EGL_FALSE); 1195 ret = drv->API.CopyBuffers(drv, disp, surf, native_pixmap_ptr); 1196 1197 RETURN_EGL_EVAL(disp, ret); 1198} 1199 1200 1201static EGLBoolean 1202_eglWaitClientCommon(void) 1203{ 1204 _EGLContext *ctx = _eglGetCurrentContext(); 1205 _EGLDisplay *disp; 1206 _EGLDriver *drv; 1207 EGLBoolean ret; 1208 1209 if (!ctx) 1210 RETURN_EGL_SUCCESS(NULL, EGL_TRUE); 1211 1212 disp = ctx->Resource.Display; 1213 mtx_lock(&disp->Mutex); 1214 1215 /* let bad current context imply bad current surface */ 1216 if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT || 1217 _eglGetSurfaceHandle(ctx->DrawSurface) == EGL_NO_SURFACE) 1218 RETURN_EGL_ERROR(disp, EGL_BAD_CURRENT_SURFACE, EGL_FALSE); 1219 1220 /* a valid current context implies an initialized current display */ 1221 assert(disp->Initialized); 1222 drv = disp->Driver; 1223 ret = drv->API.WaitClient(drv, disp, ctx); 1224 1225 RETURN_EGL_EVAL(disp, ret); 1226} 1227 1228EGLBoolean EGLAPIENTRY 1229eglWaitClient(void) 1230{ 1231 _EGL_FUNC_START(NULL, EGL_OBJECT_CONTEXT_KHR, _eglGetCurrentContext(), EGL_FALSE); 1232 return _eglWaitClientCommon(); 1233} 1234 1235EGLBoolean EGLAPIENTRY 1236eglWaitGL(void) 1237{ 1238 /* Since we only support OpenGL and GLES, eglWaitGL is equivalent to eglWaitClient. */ 1239 _EGL_FUNC_START(NULL, EGL_OBJECT_CONTEXT_KHR, _eglGetCurrentContext(), EGL_FALSE); 1240 return _eglWaitClientCommon(); 1241} 1242 1243 1244EGLBoolean EGLAPIENTRY 1245eglWaitNative(EGLint engine) 1246{ 1247 _EGLContext *ctx = _eglGetCurrentContext(); 1248 _EGLDisplay *disp; 1249 _EGLDriver *drv; 1250 EGLBoolean ret; 1251 1252 if (!ctx) 1253 RETURN_EGL_SUCCESS(NULL, EGL_TRUE); 1254 1255 _EGL_FUNC_START(NULL, EGL_OBJECT_THREAD_KHR, NULL, EGL_FALSE); 1256 1257 disp = ctx->Resource.Display; 1258 mtx_lock(&disp->Mutex); 1259 1260 /* let bad current context imply bad current surface */ 1261 if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT || 1262 _eglGetSurfaceHandle(ctx->DrawSurface) == EGL_NO_SURFACE) 1263 RETURN_EGL_ERROR(disp, EGL_BAD_CURRENT_SURFACE, EGL_FALSE); 1264 1265 /* a valid current context implies an initialized current display */ 1266 assert(disp->Initialized); 1267 drv = disp->Driver; 1268 ret = drv->API.WaitNative(drv, disp, engine); 1269 1270 RETURN_EGL_EVAL(disp, ret); 1271} 1272 1273 1274EGLDisplay EGLAPIENTRY 1275eglGetCurrentDisplay(void) 1276{ 1277 _EGLContext *ctx = _eglGetCurrentContext(); 1278 EGLDisplay ret; 1279 1280 ret = (ctx) ? _eglGetDisplayHandle(ctx->Resource.Display) : EGL_NO_DISPLAY; 1281 1282 RETURN_EGL_SUCCESS(NULL, ret); 1283} 1284 1285 1286EGLContext EGLAPIENTRY 1287eglGetCurrentContext(void) 1288{ 1289 _EGLContext *ctx = _eglGetCurrentContext(); 1290 EGLContext ret; 1291 1292 ret = _eglGetContextHandle(ctx); 1293 1294 RETURN_EGL_SUCCESS(NULL, ret); 1295} 1296 1297 1298EGLSurface EGLAPIENTRY 1299eglGetCurrentSurface(EGLint readdraw) 1300{ 1301 _EGLContext *ctx = _eglGetCurrentContext(); 1302 EGLint err = EGL_SUCCESS; 1303 _EGLSurface *surf; 1304 EGLSurface ret; 1305 1306 _EGL_FUNC_START(NULL, EGL_NONE, NULL, EGL_NO_SURFACE); 1307 1308 if (!ctx) 1309 RETURN_EGL_SUCCESS(NULL, EGL_NO_SURFACE); 1310 1311 switch (readdraw) { 1312 case EGL_DRAW: 1313 surf = ctx->DrawSurface; 1314 break; 1315 case EGL_READ: 1316 surf = ctx->ReadSurface; 1317 break; 1318 default: 1319 surf = NULL; 1320 err = EGL_BAD_PARAMETER; 1321 break; 1322 } 1323 1324 ret = _eglGetSurfaceHandle(surf); 1325 1326 RETURN_EGL_ERROR(NULL, err, ret); 1327} 1328 1329 1330EGLint EGLAPIENTRY 1331eglGetError(void) 1332{ 1333 _EGLThreadInfo *t = _eglGetCurrentThread(); 1334 EGLint e = t->LastError; 1335 if (!_eglIsCurrentThreadDummy()) 1336 t->LastError = EGL_SUCCESS; 1337 return e; 1338} 1339 1340 1341/** 1342 ** EGL 1.2 1343 **/ 1344 1345/** 1346 * Specify the client API to use for subsequent calls including: 1347 * eglCreateContext() 1348 * eglGetCurrentContext() 1349 * eglGetCurrentDisplay() 1350 * eglGetCurrentSurface() 1351 * eglMakeCurrent(when the ctx parameter is EGL NO CONTEXT) 1352 * eglWaitClient() 1353 * eglWaitNative() 1354 * See section 3.7 "Rendering Context" in the EGL specification for details. 1355 */ 1356EGLBoolean EGLAPIENTRY 1357eglBindAPI(EGLenum api) 1358{ 1359 _EGLThreadInfo *t; 1360 1361 _EGL_FUNC_START(NULL, EGL_OBJECT_THREAD_KHR, NULL, EGL_FALSE); 1362 1363 t = _eglGetCurrentThread(); 1364 if (_eglIsCurrentThreadDummy()) 1365 RETURN_EGL_ERROR(NULL, EGL_BAD_ALLOC, EGL_FALSE); 1366 1367 if (!_eglIsApiValid(api)) 1368 RETURN_EGL_ERROR(NULL, EGL_BAD_PARAMETER, EGL_FALSE); 1369 1370 t->CurrentAPI = api; 1371 1372 RETURN_EGL_SUCCESS(NULL, EGL_TRUE); 1373} 1374 1375 1376/** 1377 * Return the last value set with eglBindAPI(). 1378 */ 1379EGLenum EGLAPIENTRY 1380eglQueryAPI(void) 1381{ 1382 _EGLThreadInfo *t = _eglGetCurrentThread(); 1383 EGLenum ret; 1384 1385 /* returns one of EGL_OPENGL_API, EGL_OPENGL_ES_API or EGL_OPENVG_API */ 1386 ret = t->CurrentAPI; 1387 1388 RETURN_EGL_SUCCESS(NULL, ret); 1389} 1390 1391 1392EGLSurface EGLAPIENTRY 1393eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, 1394 EGLClientBuffer buffer, EGLConfig config, 1395 const EGLint *attrib_list) 1396{ 1397 _EGLDisplay *disp = _eglLockDisplay(dpy); 1398 _EGLConfig *conf = _eglLookupConfig(config, disp); 1399 _EGLDriver *drv; 1400 _EGLSurface *surf; 1401 EGLSurface ret; 1402 1403 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE); 1404 1405 _EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE, drv); 1406 1407 surf = drv->API.CreatePbufferFromClientBuffer(drv, disp, buftype, buffer, 1408 conf, attrib_list); 1409 ret = (surf) ? _eglLinkSurface(surf) : EGL_NO_SURFACE; 1410 1411 RETURN_EGL_EVAL(disp, ret); 1412} 1413 1414 1415EGLBoolean EGLAPIENTRY 1416eglReleaseThread(void) 1417{ 1418 /* unbind current contexts */ 1419 if (!_eglIsCurrentThreadDummy()) { 1420 _EGLThreadInfo *t = _eglGetCurrentThread(); 1421 _EGLContext *ctx = t->CurrentContext; 1422 1423 _EGL_FUNC_START(NULL, EGL_OBJECT_THREAD_KHR, NULL, EGL_FALSE); 1424 1425 if (ctx) { 1426 _EGLDisplay *disp = ctx->Resource.Display; 1427 _EGLDriver *drv; 1428 1429 mtx_lock(&disp->Mutex); 1430 drv = disp->Driver; 1431 (void) drv->API.MakeCurrent(drv, disp, NULL, NULL, NULL); 1432 mtx_unlock(&disp->Mutex); 1433 } 1434 } 1435 1436 _eglDestroyCurrentThread(); 1437 1438 RETURN_EGL_SUCCESS(NULL, EGL_TRUE); 1439} 1440 1441 1442static EGLImage 1443_eglCreateImageCommon(_EGLDisplay *disp, EGLContext ctx, EGLenum target, 1444 EGLClientBuffer buffer, const EGLint *attr_list) 1445{ 1446 _EGLContext *context = _eglLookupContext(ctx, disp); 1447 _EGLDriver *drv; 1448 _EGLImage *img; 1449 EGLImage ret; 1450 1451 _EGL_CHECK_DISPLAY(disp, EGL_NO_IMAGE_KHR, drv); 1452 if (!disp->Extensions.KHR_image_base) 1453 RETURN_EGL_EVAL(disp, EGL_NO_IMAGE_KHR); 1454 if (!context && ctx != EGL_NO_CONTEXT) 1455 RETURN_EGL_ERROR(disp, EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR); 1456 /* "If <target> is EGL_LINUX_DMA_BUF_EXT, <dpy> must be a valid display, 1457 * <ctx> must be EGL_NO_CONTEXT..." 1458 */ 1459 if (ctx != EGL_NO_CONTEXT && target == EGL_LINUX_DMA_BUF_EXT) 1460 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR); 1461 1462 img = drv->API.CreateImageKHR(drv, 1463 disp, context, target, buffer, attr_list); 1464 ret = (img) ? _eglLinkImage(img) : EGL_NO_IMAGE_KHR; 1465 1466 RETURN_EGL_EVAL(disp, ret); 1467} 1468 1469static EGLImage EGLAPIENTRY 1470eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, 1471 EGLClientBuffer buffer, const EGLint *attr_list) 1472{ 1473 _EGLDisplay *disp = _eglLockDisplay(dpy); 1474 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_IMAGE_KHR); 1475 return _eglCreateImageCommon(disp, ctx, target, buffer, attr_list); 1476} 1477 1478 1479EGLImage EGLAPIENTRY 1480eglCreateImage(EGLDisplay dpy, EGLContext ctx, EGLenum target, 1481 EGLClientBuffer buffer, const EGLAttrib *attr_list) 1482{ 1483 _EGLDisplay *disp = _eglLockDisplay(dpy); 1484 EGLImage image; 1485 EGLint *int_attribs; 1486 1487 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_IMAGE_KHR); 1488 1489 int_attribs = _eglConvertAttribsToInt(attr_list); 1490 if (attr_list && !int_attribs) 1491 RETURN_EGL_ERROR(disp, EGL_BAD_ALLOC, EGL_NO_IMAGE); 1492 1493 image = _eglCreateImageCommon(disp, ctx, target, buffer, int_attribs); 1494 free(int_attribs); 1495 return image; 1496} 1497 1498 1499EGLBoolean EGLAPIENTRY 1500eglDestroyImage(EGLDisplay dpy, EGLImage image) 1501{ 1502 _EGLDisplay *disp = _eglLockDisplay(dpy); 1503 _EGLImage *img = _eglLookupImage(image, disp); 1504 _EGLDriver *drv; 1505 EGLBoolean ret; 1506 1507 _EGL_FUNC_START(disp, EGL_OBJECT_IMAGE_KHR, img, EGL_FALSE); 1508 1509 _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv); 1510 if (!disp->Extensions.KHR_image_base) 1511 RETURN_EGL_EVAL(disp, EGL_FALSE); 1512 if (!img) 1513 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE); 1514 1515 _eglUnlinkImage(img); 1516 ret = drv->API.DestroyImageKHR(drv, disp, img); 1517 1518 RETURN_EGL_EVAL(disp, ret); 1519} 1520 1521 1522static EGLSync 1523_eglCreateSync(_EGLDisplay *disp, EGLenum type, const EGLAttrib *attrib_list, 1524 EGLBoolean orig_is_EGLAttrib, 1525 EGLenum invalid_type_error) 1526{ 1527 _EGLContext *ctx = _eglGetCurrentContext(); 1528 _EGLDriver *drv; 1529 _EGLSync *sync; 1530 EGLSync ret; 1531 1532 _EGL_CHECK_DISPLAY(disp, EGL_NO_SYNC_KHR, drv); 1533 1534 if (!disp->Extensions.KHR_cl_event2 && orig_is_EGLAttrib) { 1535 /* There exist two EGLAttrib variants of eglCreateSync*: 1536 * eglCreateSync64KHR which requires EGL_KHR_cl_event2, and eglCreateSync 1537 * which requires EGL 1.5. Here we use the presence of EGL_KHR_cl_event2 1538 * support as a proxy for EGL 1.5 support, even though that's not 1539 * entirely correct (though _eglComputeVersion does the same). 1540 * 1541 * The EGL spec provides no guidance on how to handle unsupported 1542 * functions. EGL_BAD_MATCH seems reasonable. 1543 */ 1544 RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_NO_SYNC_KHR); 1545 } 1546 1547 /* return an error if the client API doesn't support GL_OES_EGL_sync */ 1548 if (!ctx || ctx->Resource.Display != disp || 1549 ctx->ClientAPI != EGL_OPENGL_ES_API) 1550 RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_NO_SYNC_KHR); 1551 1552 switch (type) { 1553 case EGL_SYNC_FENCE_KHR: 1554 if (!disp->Extensions.KHR_fence_sync) 1555 RETURN_EGL_ERROR(disp, invalid_type_error, EGL_NO_SYNC_KHR); 1556 break; 1557 case EGL_SYNC_REUSABLE_KHR: 1558 if (!disp->Extensions.KHR_reusable_sync) 1559 RETURN_EGL_ERROR(disp, invalid_type_error, EGL_NO_SYNC_KHR); 1560 break; 1561 case EGL_SYNC_CL_EVENT_KHR: 1562 if (!disp->Extensions.KHR_cl_event2) 1563 RETURN_EGL_ERROR(disp, invalid_type_error, EGL_NO_SYNC_KHR); 1564 break; 1565 default: 1566 RETURN_EGL_ERROR(disp, invalid_type_error, EGL_NO_SYNC_KHR); 1567 } 1568 1569 sync = drv->API.CreateSyncKHR(drv, disp, type, attrib_list); 1570 ret = (sync) ? _eglLinkSync(sync) : EGL_NO_SYNC_KHR; 1571 1572 RETURN_EGL_EVAL(disp, ret); 1573} 1574 1575 1576static EGLSync EGLAPIENTRY 1577eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *int_list) 1578{ 1579 _EGLDisplay *disp = _eglLockDisplay(dpy); 1580 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE); 1581 1582 EGLSync sync; 1583 EGLAttrib *attrib_list; 1584 EGLint err; 1585 1586 if (sizeof(int_list[0]) == sizeof(attrib_list[0])) { 1587 attrib_list = (EGLAttrib *) int_list; 1588 } else { 1589 err = _eglConvertIntsToAttribs(int_list, &attrib_list); 1590 if (err != EGL_SUCCESS) 1591 RETURN_EGL_ERROR(disp, err, EGL_NO_SYNC); 1592 } 1593 1594 sync = _eglCreateSync(disp, type, attrib_list, EGL_FALSE, 1595 EGL_BAD_ATTRIBUTE); 1596 1597 if (sizeof(int_list[0]) != sizeof(attrib_list[0])) 1598 free(attrib_list); 1599 1600 /* Don't double-unlock the display. _eglCreateSync already unlocked it. */ 1601 return sync; 1602} 1603 1604 1605static EGLSync EGLAPIENTRY 1606eglCreateSync64KHR(EGLDisplay dpy, EGLenum type, const EGLAttrib *attrib_list) 1607{ 1608 _EGLDisplay *disp = _eglLockDisplay(dpy); 1609 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE); 1610 return _eglCreateSync(disp, type, attrib_list, EGL_TRUE, 1611 EGL_BAD_ATTRIBUTE); 1612} 1613 1614 1615EGLSync EGLAPIENTRY 1616eglCreateSync(EGLDisplay dpy, EGLenum type, const EGLAttrib *attrib_list) 1617{ 1618 _EGLDisplay *disp = _eglLockDisplay(dpy); 1619 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE); 1620 return _eglCreateSync(disp, type, attrib_list, EGL_TRUE, 1621 EGL_BAD_PARAMETER); 1622} 1623 1624 1625EGLBoolean EGLAPIENTRY 1626eglDestroySync(EGLDisplay dpy, EGLSync sync) 1627{ 1628 _EGLDisplay *disp = _eglLockDisplay(dpy); 1629 _EGLSync *s = _eglLookupSync(sync, disp); 1630 _EGLDriver *drv; 1631 EGLBoolean ret; 1632 1633 _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE); 1634 1635 _EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv); 1636 assert(disp->Extensions.KHR_reusable_sync || 1637 disp->Extensions.KHR_fence_sync); 1638 1639 _eglUnlinkSync(s); 1640 ret = drv->API.DestroySyncKHR(drv, disp, s); 1641 1642 RETURN_EGL_EVAL(disp, ret); 1643} 1644 1645 1646EGLint EGLAPIENTRY 1647eglClientWaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags, EGLTime timeout) 1648{ 1649 _EGLDisplay *disp = _eglLockDisplay(dpy); 1650 _EGLSync *s = _eglLookupSync(sync, disp); 1651 _EGLDriver *drv; 1652 EGLint ret; 1653 1654 _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE); 1655 1656 _EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv); 1657 assert(disp->Extensions.KHR_reusable_sync || 1658 disp->Extensions.KHR_fence_sync); 1659 1660 if (s->SyncStatus == EGL_SIGNALED_KHR) 1661 RETURN_EGL_EVAL(disp, EGL_CONDITION_SATISFIED_KHR); 1662 1663 /* if sync type is EGL_SYNC_REUSABLE_KHR, dpy should be 1664 * unlocked here to allow other threads also to be able to 1665 * go into waiting state. 1666 */ 1667 1668 if (s->Type == EGL_SYNC_REUSABLE_KHR) 1669 _eglUnlockDisplay(dpy); 1670 1671 ret = drv->API.ClientWaitSyncKHR(drv, disp, s, flags, timeout); 1672 1673 /* 1674 * 'disp' is already unlocked for reusable sync type, 1675 * so passing 'NULL' to bypass unlocking display. 1676 */ 1677 if (s->Type == EGL_SYNC_REUSABLE_KHR) 1678 RETURN_EGL_EVAL(NULL, ret); 1679 else 1680 RETURN_EGL_EVAL(disp, ret); 1681} 1682 1683 1684static EGLint 1685_eglWaitSyncCommon(_EGLDisplay *disp, _EGLSync *s, EGLint flags) 1686{ 1687 _EGLContext *ctx = _eglGetCurrentContext(); 1688 _EGLDriver *drv; 1689 EGLint ret; 1690 1691 _EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv); 1692 assert(disp->Extensions.KHR_wait_sync); 1693 1694 /* return an error if the client API doesn't support GL_OES_EGL_sync */ 1695 if (ctx == EGL_NO_CONTEXT || ctx->ClientAPI != EGL_OPENGL_ES_API) 1696 RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_FALSE); 1697 1698 /* the API doesn't allow any flags yet */ 1699 if (flags != 0) 1700 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE); 1701 1702 ret = drv->API.WaitSyncKHR(drv, disp, s); 1703 1704 RETURN_EGL_EVAL(disp, ret); 1705} 1706 1707static EGLint EGLAPIENTRY 1708eglWaitSyncKHR(EGLDisplay dpy, EGLSync sync, EGLint flags) 1709{ 1710 _EGLDisplay *disp = _eglLockDisplay(dpy); 1711 _EGLSync *s = _eglLookupSync(sync, disp); 1712 _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE); 1713 return _eglWaitSyncCommon(disp, s, flags); 1714} 1715 1716 1717EGLBoolean EGLAPIENTRY 1718eglWaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags) 1719{ 1720 /* The KHR version returns EGLint, while the core version returns 1721 * EGLBoolean. In both cases, the return values can only be EGL_FALSE and 1722 * EGL_TRUE. 1723 */ 1724 _EGLDisplay *disp = _eglLockDisplay(dpy); 1725 _EGLSync *s = _eglLookupSync(sync, disp); 1726 _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE); 1727 return _eglWaitSyncCommon(disp, s, flags); 1728} 1729 1730 1731static EGLBoolean EGLAPIENTRY 1732eglSignalSyncKHR(EGLDisplay dpy, EGLSync sync, EGLenum mode) 1733{ 1734 _EGLDisplay *disp = _eglLockDisplay(dpy); 1735 _EGLSync *s = _eglLookupSync(sync, disp); 1736 _EGLDriver *drv; 1737 EGLBoolean ret; 1738 1739 _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE); 1740 1741 _EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv); 1742 assert(disp->Extensions.KHR_reusable_sync); 1743 ret = drv->API.SignalSyncKHR(drv, disp, s, mode); 1744 1745 RETURN_EGL_EVAL(disp, ret); 1746} 1747 1748 1749static EGLBoolean 1750_eglGetSyncAttribCommon(_EGLDisplay *disp, _EGLSync *s, EGLint attribute, EGLAttrib *value) 1751{ 1752 _EGLDriver *drv; 1753 EGLBoolean ret; 1754 1755 _EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv); 1756 assert(disp->Extensions.KHR_reusable_sync || 1757 disp->Extensions.KHR_fence_sync); 1758 ret = drv->API.GetSyncAttrib(drv, disp, s, attribute, value); 1759 1760 RETURN_EGL_EVAL(disp, ret); 1761} 1762 1763EGLBoolean EGLAPIENTRY 1764eglGetSyncAttrib(EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLAttrib *value) 1765{ 1766 _EGLDisplay *disp = _eglLockDisplay(dpy); 1767 _EGLSync *s = _eglLookupSync(sync, disp); 1768 _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE); 1769 return _eglGetSyncAttribCommon(disp, s, attribute, value); 1770} 1771 1772 1773static EGLBoolean EGLAPIENTRY 1774eglGetSyncAttribKHR(EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLint *value) 1775{ 1776 _EGLDisplay *disp = _eglLockDisplay(dpy); 1777 _EGLSync *s = _eglLookupSync(sync, disp); 1778 EGLAttrib attrib; 1779 EGLBoolean result; 1780 1781 _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE); 1782 1783 if (!value) 1784 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE); 1785 1786 attrib = *value; 1787 result = _eglGetSyncAttribCommon(disp, s, attribute, &attrib); 1788 1789 /* The EGL_KHR_fence_sync spec says this about eglGetSyncAttribKHR: 1790 * 1791 * If any error occurs, <*value> is not modified. 1792 */ 1793 if (result == EGL_FALSE) 1794 return result; 1795 1796 *value = attrib; 1797 return result; 1798} 1799 1800 1801static EGLBoolean EGLAPIENTRY 1802eglSwapBuffersRegionNOK(EGLDisplay dpy, EGLSurface surface, 1803 EGLint numRects, const EGLint *rects) 1804{ 1805 _EGLContext *ctx = _eglGetCurrentContext(); 1806 _EGLDisplay *disp = _eglLockDisplay(dpy); 1807 _EGLSurface *surf = _eglLookupSurface(surface, disp); 1808 _EGLDriver *drv; 1809 EGLBoolean ret; 1810 1811 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE); 1812 1813 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv); 1814 1815 if (!disp->Extensions.NOK_swap_region) 1816 RETURN_EGL_EVAL(disp, EGL_FALSE); 1817 1818 /* surface must be bound to current context in EGL 1.4 */ 1819 if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT || 1820 surf != ctx->DrawSurface) 1821 RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE); 1822 1823 ret = drv->API.SwapBuffersRegionNOK(drv, disp, surf, numRects, rects); 1824 1825 RETURN_EGL_EVAL(disp, ret); 1826} 1827 1828 1829static EGLImage EGLAPIENTRY 1830eglCreateDRMImageMESA(EGLDisplay dpy, const EGLint *attr_list) 1831{ 1832 _EGLDisplay *disp = _eglLockDisplay(dpy); 1833 _EGLDriver *drv; 1834 _EGLImage *img; 1835 EGLImage ret; 1836 1837 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE); 1838 1839 _EGL_CHECK_DISPLAY(disp, EGL_NO_IMAGE_KHR, drv); 1840 if (!disp->Extensions.MESA_drm_image) 1841 RETURN_EGL_EVAL(disp, EGL_NO_IMAGE_KHR); 1842 1843 img = drv->API.CreateDRMImageMESA(drv, disp, attr_list); 1844 ret = (img) ? _eglLinkImage(img) : EGL_NO_IMAGE_KHR; 1845 1846 RETURN_EGL_EVAL(disp, ret); 1847} 1848 1849static EGLBoolean EGLAPIENTRY 1850eglExportDRMImageMESA(EGLDisplay dpy, EGLImage image, 1851 EGLint *name, EGLint *handle, EGLint *stride) 1852{ 1853 _EGLDisplay *disp = _eglLockDisplay(dpy); 1854 _EGLImage *img = _eglLookupImage(image, disp); 1855 _EGLDriver *drv; 1856 EGLBoolean ret; 1857 1858 _EGL_FUNC_START(disp, EGL_OBJECT_IMAGE_KHR, img, EGL_FALSE); 1859 1860 _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv); 1861 assert(disp->Extensions.MESA_drm_image); 1862 1863 if (!img) 1864 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE); 1865 1866 ret = drv->API.ExportDRMImageMESA(drv, disp, img, name, handle, stride); 1867 1868 RETURN_EGL_EVAL(disp, ret); 1869} 1870 1871 1872struct wl_display; 1873 1874static EGLBoolean EGLAPIENTRY 1875eglBindWaylandDisplayWL(EGLDisplay dpy, struct wl_display *display) 1876{ 1877 _EGLDisplay *disp = _eglLockDisplay(dpy); 1878 _EGLDriver *drv; 1879 EGLBoolean ret; 1880 1881 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE); 1882 1883 _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv); 1884 assert(disp->Extensions.WL_bind_wayland_display); 1885 1886 if (!display) 1887 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE); 1888 1889 ret = drv->API.BindWaylandDisplayWL(drv, disp, display); 1890 1891 RETURN_EGL_EVAL(disp, ret); 1892} 1893 1894static EGLBoolean EGLAPIENTRY 1895eglUnbindWaylandDisplayWL(EGLDisplay dpy, struct wl_display *display) 1896{ 1897 _EGLDisplay *disp = _eglLockDisplay(dpy); 1898 _EGLDriver *drv; 1899 EGLBoolean ret; 1900 1901 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE); 1902 1903 _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv); 1904 assert(disp->Extensions.WL_bind_wayland_display); 1905 1906 if (!display) 1907 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE); 1908 1909 ret = drv->API.UnbindWaylandDisplayWL(drv, disp, display); 1910 1911 RETURN_EGL_EVAL(disp, ret); 1912} 1913 1914static EGLBoolean EGLAPIENTRY 1915eglQueryWaylandBufferWL(EGLDisplay dpy, struct wl_resource *buffer, 1916 EGLint attribute, EGLint *value) 1917{ 1918 _EGLDisplay *disp = _eglLockDisplay(dpy); 1919 _EGLDriver *drv; 1920 EGLBoolean ret; 1921 1922 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE); 1923 1924 _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv); 1925 assert(disp->Extensions.WL_bind_wayland_display); 1926 1927 if (!buffer) 1928 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE); 1929 1930 ret = drv->API.QueryWaylandBufferWL(drv, disp, buffer, attribute, value); 1931 1932 RETURN_EGL_EVAL(disp, ret); 1933} 1934 1935 1936static struct wl_buffer * EGLAPIENTRY 1937eglCreateWaylandBufferFromImageWL(EGLDisplay dpy, EGLImage image) 1938{ 1939 _EGLDisplay *disp = _eglLockDisplay(dpy); 1940 _EGLImage *img; 1941 _EGLDriver *drv; 1942 struct wl_buffer *ret; 1943 1944 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE); 1945 1946 _EGL_CHECK_DISPLAY(disp, NULL, drv); 1947 assert(disp->Extensions.WL_create_wayland_buffer_from_image); 1948 1949 img = _eglLookupImage(image, disp); 1950 1951 if (!img) 1952 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, NULL); 1953 1954 ret = drv->API.CreateWaylandBufferFromImageWL(drv, disp, img); 1955 1956 RETURN_EGL_EVAL(disp, ret); 1957} 1958 1959static EGLBoolean EGLAPIENTRY 1960eglPostSubBufferNV(EGLDisplay dpy, EGLSurface surface, 1961 EGLint x, EGLint y, EGLint width, EGLint height) 1962{ 1963 _EGLDisplay *disp = _eglLockDisplay(dpy); 1964 _EGLSurface *surf = _eglLookupSurface(surface, disp); 1965 _EGLDriver *drv; 1966 EGLBoolean ret; 1967 1968 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE); 1969 1970 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv); 1971 1972 if (!disp->Extensions.NV_post_sub_buffer) 1973 RETURN_EGL_EVAL(disp, EGL_FALSE); 1974 1975 ret = drv->API.PostSubBufferNV(drv, disp, surf, x, y, width, height); 1976 1977 RETURN_EGL_EVAL(disp, ret); 1978} 1979 1980static EGLBoolean EGLAPIENTRY 1981eglGetSyncValuesCHROMIUM(EGLDisplay display, EGLSurface surface, 1982 EGLuint64KHR *ust, EGLuint64KHR *msc, 1983 EGLuint64KHR *sbc) 1984{ 1985 _EGLDisplay *disp = _eglLockDisplay(display); 1986 _EGLSurface *surf = _eglLookupSurface(surface, disp); 1987 _EGLDriver *drv; 1988 EGLBoolean ret; 1989 1990 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE); 1991 1992 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv); 1993 if (!disp->Extensions.CHROMIUM_sync_control) 1994 RETURN_EGL_EVAL(disp, EGL_FALSE); 1995 1996 if (!ust || !msc || !sbc) 1997 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE); 1998 1999 ret = drv->API.GetSyncValuesCHROMIUM(disp, surf, ust, msc, sbc); 2000 2001 RETURN_EGL_EVAL(disp, ret); 2002} 2003 2004static EGLBoolean EGLAPIENTRY 2005eglExportDMABUFImageQueryMESA(EGLDisplay dpy, EGLImage image, 2006 EGLint *fourcc, EGLint *nplanes, 2007 EGLuint64KHR *modifiers) 2008{ 2009 _EGLDisplay *disp = _eglLockDisplay(dpy); 2010 _EGLImage *img = _eglLookupImage(image, disp); 2011 _EGLDriver *drv; 2012 EGLBoolean ret; 2013 2014 _EGL_FUNC_START(disp, EGL_OBJECT_IMAGE_KHR, img, EGL_FALSE); 2015 2016 _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv); 2017 assert(disp->Extensions.MESA_image_dma_buf_export); 2018 2019 if (!img) 2020 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE); 2021 2022 ret = drv->API.ExportDMABUFImageQueryMESA(drv, disp, img, fourcc, nplanes, 2023 modifiers); 2024 2025 RETURN_EGL_EVAL(disp, ret); 2026} 2027 2028static EGLBoolean EGLAPIENTRY 2029eglExportDMABUFImageMESA(EGLDisplay dpy, EGLImage image, 2030 int *fds, EGLint *strides, EGLint *offsets) 2031{ 2032 _EGLDisplay *disp = _eglLockDisplay(dpy); 2033 _EGLImage *img = _eglLookupImage(image, disp); 2034 _EGLDriver *drv; 2035 EGLBoolean ret; 2036 2037 _EGL_FUNC_START(disp, EGL_OBJECT_IMAGE_KHR, img, EGL_FALSE); 2038 2039 _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv); 2040 assert(disp->Extensions.MESA_image_dma_buf_export); 2041 2042 if (!img) 2043 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE); 2044 2045 ret = drv->API.ExportDMABUFImageMESA(drv, disp, img, fds, strides, offsets); 2046 2047 RETURN_EGL_EVAL(disp, ret); 2048} 2049 2050static EGLint EGLAPIENTRY 2051eglLabelObjectKHR(EGLDisplay dpy, EGLenum objectType, EGLObjectKHR object, 2052 EGLLabelKHR label) 2053{ 2054 _EGLDisplay *disp = NULL; 2055 _EGLResourceType type; 2056 2057 _EGL_FUNC_START(NULL, EGL_NONE, NULL, EGL_BAD_ALLOC); 2058 2059 if (objectType == EGL_OBJECT_THREAD_KHR) { 2060 _EGLThreadInfo *t = _eglGetCurrentThread(); 2061 2062 if (!_eglIsCurrentThreadDummy()) { 2063 t->Label = label; 2064 return EGL_SUCCESS; 2065 } 2066 2067 RETURN_EGL_ERROR(NULL, EGL_BAD_ALLOC, EGL_BAD_ALLOC); 2068 } 2069 2070 disp = _eglLockDisplay(dpy); 2071 if (disp == NULL) 2072 RETURN_EGL_ERROR(disp, EGL_BAD_DISPLAY, EGL_BAD_DISPLAY); 2073 2074 if (objectType == EGL_OBJECT_DISPLAY_KHR) { 2075 if (dpy != (EGLDisplay) object) 2076 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_BAD_PARAMETER); 2077 2078 disp->Label = label; 2079 RETURN_EGL_EVAL(disp, EGL_SUCCESS); 2080 } 2081 2082 switch (objectType) { 2083 case EGL_OBJECT_CONTEXT_KHR: 2084 type = _EGL_RESOURCE_CONTEXT; 2085 break; 2086 case EGL_OBJECT_SURFACE_KHR: 2087 type = _EGL_RESOURCE_SURFACE; 2088 break; 2089 case EGL_OBJECT_IMAGE_KHR: 2090 type = _EGL_RESOURCE_IMAGE; 2091 break; 2092 case EGL_OBJECT_SYNC_KHR: 2093 type = _EGL_RESOURCE_SYNC; 2094 break; 2095 case EGL_OBJECT_STREAM_KHR: 2096 default: 2097 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_BAD_PARAMETER); 2098 } 2099 2100 if (_eglCheckResource(object, type, disp)) { 2101 _EGLResource *res = (_EGLResource *) object; 2102 2103 res->Label = label; 2104 RETURN_EGL_EVAL(disp, EGL_SUCCESS); 2105 } 2106 2107 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_BAD_PARAMETER); 2108} 2109 2110static EGLBoolean 2111validDebugMessageLevel(EGLAttrib level) 2112{ 2113 return (level >= EGL_DEBUG_MSG_CRITICAL_KHR && 2114 level <= EGL_DEBUG_MSG_INFO_KHR); 2115} 2116 2117static EGLint EGLAPIENTRY 2118eglDebugMessageControlKHR(EGLDEBUGPROCKHR callback, 2119 const EGLAttrib *attrib_list) 2120{ 2121 unsigned int newEnabled; 2122 2123 _EGL_FUNC_START(NULL, EGL_NONE, NULL, EGL_BAD_ALLOC); 2124 2125 mtx_lock(_eglGlobal.Mutex); 2126 2127 newEnabled = _eglGlobal.debugTypesEnabled; 2128 if (attrib_list != NULL) { 2129 int i; 2130 2131 for (i = 0; attrib_list[i] != EGL_NONE; i += 2) { 2132 if (validDebugMessageLevel(attrib_list[i])) { 2133 if (attrib_list[i + 1]) 2134 newEnabled |= DebugBitFromType(attrib_list[i]); 2135 else 2136 newEnabled &= ~DebugBitFromType(attrib_list[i]); 2137 continue; 2138 } 2139 2140 // On error, set the last error code, call the current 2141 // debug callback, and return the error code. 2142 mtx_unlock(_eglGlobal.Mutex); 2143 _eglReportError(EGL_BAD_ATTRIBUTE, NULL, 2144 "Invalid attribute 0x%04lx", (unsigned long) attrib_list[i]); 2145 return EGL_BAD_ATTRIBUTE; 2146 } 2147 } 2148 2149 if (callback != NULL) { 2150 _eglGlobal.debugCallback = callback; 2151 _eglGlobal.debugTypesEnabled = newEnabled; 2152 } else { 2153 _eglGlobal.debugCallback = NULL; 2154 _eglGlobal.debugTypesEnabled = _EGL_DEBUG_BIT_CRITICAL | _EGL_DEBUG_BIT_ERROR; 2155 } 2156 2157 mtx_unlock(_eglGlobal.Mutex); 2158 return EGL_SUCCESS; 2159} 2160 2161static EGLBoolean EGLAPIENTRY 2162eglQueryDebugKHR(EGLint attribute, EGLAttrib *value) 2163{ 2164 _EGL_FUNC_START(NULL, EGL_NONE, NULL, EGL_BAD_ALLOC); 2165 2166 mtx_lock(_eglGlobal.Mutex); 2167 2168 do { 2169 if (validDebugMessageLevel(attribute)) { 2170 if (_eglGlobal.debugTypesEnabled & DebugBitFromType(attribute)) 2171 *value = EGL_TRUE; 2172 else 2173 *value = EGL_FALSE; 2174 break; 2175 } 2176 2177 if (attribute == EGL_DEBUG_CALLBACK_KHR) { 2178 *value = (EGLAttrib) _eglGlobal.debugCallback; 2179 break; 2180 } 2181 2182 mtx_unlock(_eglGlobal.Mutex); 2183 _eglReportError(EGL_BAD_ATTRIBUTE, NULL, 2184 "Invalid attribute 0x%04lx", (unsigned long) attribute); 2185 return EGL_FALSE; 2186 } while (0); 2187 2188 mtx_unlock(_eglGlobal.Mutex); 2189 return EGL_TRUE; 2190} 2191 2192__eglMustCastToProperFunctionPointerType EGLAPIENTRY 2193eglGetProcAddress(const char *procname) 2194{ 2195 static const struct { 2196 const char *name; 2197 _EGLProc function; 2198 } egl_functions[] = { 2199 /* core functions queryable in the presence of 2200 * EGL_KHR_get_all_proc_addresses or EGL 1.5 2201 */ 2202 /* alphabetical order */ 2203 { "eglBindAPI", (_EGLProc) eglBindAPI }, 2204 { "eglBindTexImage", (_EGLProc) eglBindTexImage }, 2205 { "eglChooseConfig", (_EGLProc) eglChooseConfig }, 2206 { "eglCopyBuffers", (_EGLProc) eglCopyBuffers }, 2207 { "eglCreateContext", (_EGLProc) eglCreateContext }, 2208 { "eglCreatePbufferFromClientBuffer", (_EGLProc) eglCreatePbufferFromClientBuffer }, 2209 { "eglCreatePbufferSurface", (_EGLProc) eglCreatePbufferSurface }, 2210 { "eglCreatePixmapSurface", (_EGLProc) eglCreatePixmapSurface }, 2211 { "eglCreateWindowSurface", (_EGLProc) eglCreateWindowSurface }, 2212 { "eglDestroyContext", (_EGLProc) eglDestroyContext }, 2213 { "eglDestroySurface", (_EGLProc) eglDestroySurface }, 2214 { "eglGetConfigAttrib", (_EGLProc) eglGetConfigAttrib }, 2215 { "eglGetConfigs", (_EGLProc) eglGetConfigs }, 2216 { "eglGetCurrentContext", (_EGLProc) eglGetCurrentContext }, 2217 { "eglGetCurrentDisplay", (_EGLProc) eglGetCurrentDisplay }, 2218 { "eglGetCurrentSurface", (_EGLProc) eglGetCurrentSurface }, 2219 { "eglGetDisplay", (_EGLProc) eglGetDisplay }, 2220 { "eglGetError", (_EGLProc) eglGetError }, 2221 { "eglGetProcAddress", (_EGLProc) eglGetProcAddress }, 2222 { "eglInitialize", (_EGLProc) eglInitialize }, 2223 { "eglMakeCurrent", (_EGLProc) eglMakeCurrent }, 2224 { "eglQueryAPI", (_EGLProc) eglQueryAPI }, 2225 { "eglQueryContext", (_EGLProc) eglQueryContext }, 2226 { "eglQueryString", (_EGLProc) eglQueryString }, 2227 { "eglQuerySurface", (_EGLProc) eglQuerySurface }, 2228 { "eglReleaseTexImage", (_EGLProc) eglReleaseTexImage }, 2229 { "eglReleaseThread", (_EGLProc) eglReleaseThread }, 2230 { "eglSurfaceAttrib", (_EGLProc) eglSurfaceAttrib }, 2231 { "eglSwapBuffers", (_EGLProc) eglSwapBuffers }, 2232 { "eglSwapInterval", (_EGLProc) eglSwapInterval }, 2233 { "eglTerminate", (_EGLProc) eglTerminate }, 2234 { "eglWaitClient", (_EGLProc) eglWaitClient }, 2235 { "eglWaitGL", (_EGLProc) eglWaitGL }, 2236 { "eglWaitNative", (_EGLProc) eglWaitNative }, 2237 { "eglCreateSync", (_EGLProc) eglCreateSync }, 2238 { "eglDestroySync", (_EGLProc) eglDestroySync }, 2239 { "eglClientWaitSync", (_EGLProc) eglClientWaitSync }, 2240 { "eglGetSyncAttrib", (_EGLProc) eglGetSyncAttrib }, 2241 { "eglWaitSync", (_EGLProc) eglWaitSync }, 2242 { "eglCreateImage", (_EGLProc) eglCreateImage }, 2243 { "eglDestroyImage", (_EGLProc) eglDestroyImage }, 2244 { "eglGetPlatformDisplay", (_EGLProc) eglGetPlatformDisplay }, 2245 { "eglCreatePlatformWindowSurface", (_EGLProc) eglCreatePlatformWindowSurface }, 2246 { "eglCreatePlatformPixmapSurface", (_EGLProc) eglCreatePlatformPixmapSurface }, 2247 { "eglCreateImageKHR", (_EGLProc) eglCreateImageKHR }, 2248 { "eglDestroyImageKHR", (_EGLProc) eglDestroyImage }, 2249 { "eglCreateSyncKHR", (_EGLProc) eglCreateSyncKHR }, 2250 { "eglCreateSync64KHR", (_EGLProc) eglCreateSync64KHR }, 2251 { "eglDestroySyncKHR", (_EGLProc) eglDestroySync }, 2252 { "eglClientWaitSyncKHR", (_EGLProc) eglClientWaitSync }, 2253 { "eglWaitSyncKHR", (_EGLProc) eglWaitSyncKHR }, 2254 { "eglSignalSyncKHR", (_EGLProc) eglSignalSyncKHR }, 2255 { "eglGetSyncAttribKHR", (_EGLProc) eglGetSyncAttribKHR }, 2256 { "eglSwapBuffersRegionNOK", (_EGLProc) eglSwapBuffersRegionNOK }, 2257 { "eglCreateDRMImageMESA", (_EGLProc) eglCreateDRMImageMESA }, 2258 { "eglExportDRMImageMESA", (_EGLProc) eglExportDRMImageMESA }, 2259 { "eglBindWaylandDisplayWL", (_EGLProc) eglBindWaylandDisplayWL }, 2260 { "eglUnbindWaylandDisplayWL", (_EGLProc) eglUnbindWaylandDisplayWL }, 2261 { "eglQueryWaylandBufferWL", (_EGLProc) eglQueryWaylandBufferWL }, 2262 { "eglCreateWaylandBufferFromImageWL", (_EGLProc) eglCreateWaylandBufferFromImageWL }, 2263 { "eglPostSubBufferNV", (_EGLProc) eglPostSubBufferNV }, 2264 { "eglSwapBuffersWithDamageEXT", (_EGLProc) eglSwapBuffersWithDamageEXT }, 2265 { "eglGetPlatformDisplayEXT", (_EGLProc) eglGetPlatformDisplayEXT }, 2266 { "eglCreatePlatformWindowSurfaceEXT", (_EGLProc) eglCreatePlatformWindowSurfaceEXT }, 2267 { "eglCreatePlatformPixmapSurfaceEXT", (_EGLProc) eglCreatePlatformPixmapSurfaceEXT }, 2268 { "eglGetSyncValuesCHROMIUM", (_EGLProc) eglGetSyncValuesCHROMIUM }, 2269 { "eglExportDMABUFImageQueryMESA", (_EGLProc) eglExportDMABUFImageQueryMESA }, 2270 { "eglExportDMABUFImageMESA", (_EGLProc) eglExportDMABUFImageMESA }, 2271 { "eglLabelObjectKHR", (_EGLProc) eglLabelObjectKHR }, 2272 { "eglDebugMessageControlKHR", (_EGLProc) eglDebugMessageControlKHR }, 2273 { "eglQueryDebugKHR", (_EGLProc) eglQueryDebugKHR }, 2274 { NULL, NULL } 2275 }; 2276 EGLint i; 2277 _EGLProc ret; 2278 2279 if (!procname) 2280 RETURN_EGL_SUCCESS(NULL, NULL); 2281 2282 _EGL_FUNC_START(NULL, EGL_NONE, NULL, NULL); 2283 2284 ret = NULL; 2285 if (strncmp(procname, "egl", 3) == 0) { 2286 for (i = 0; egl_functions[i].name; i++) { 2287 if (strcmp(egl_functions[i].name, procname) == 0) { 2288 ret = egl_functions[i].function; 2289 break; 2290 } 2291 } 2292 } 2293 if (!ret) 2294 ret = _eglGetDriverProc(procname); 2295 2296 RETURN_EGL_SUCCESS(NULL, ret); 2297} 2298 2299static int 2300_eglLockDisplayInterop(EGLDisplay dpy, EGLContext context, 2301 _EGLDisplay **disp, _EGLDriver **drv, 2302 _EGLContext **ctx) 2303{ 2304 2305 *disp = _eglLockDisplay(dpy); 2306 if (!*disp || !(*disp)->Initialized || !(*disp)->Driver) { 2307 if (*disp) 2308 _eglUnlockDisplay(*disp); 2309 return MESA_GLINTEROP_INVALID_DISPLAY; 2310 } 2311 2312 *drv = (*disp)->Driver; 2313 2314 *ctx = _eglLookupContext(context, *disp); 2315 if (!*ctx || 2316 ((*ctx)->ClientAPI != EGL_OPENGL_API && 2317 (*ctx)->ClientAPI != EGL_OPENGL_ES_API)) { 2318 _eglUnlockDisplay(*disp); 2319 return MESA_GLINTEROP_INVALID_CONTEXT; 2320 } 2321 2322 return MESA_GLINTEROP_SUCCESS; 2323} 2324 2325int 2326MesaGLInteropEGLQueryDeviceInfo(EGLDisplay dpy, EGLContext context, 2327 struct mesa_glinterop_device_info *out) 2328{ 2329 _EGLDisplay *disp; 2330 _EGLDriver *drv; 2331 _EGLContext *ctx; 2332 int ret; 2333 2334 ret = _eglLockDisplayInterop(dpy, context, &disp, &drv, &ctx); 2335 if (ret != MESA_GLINTEROP_SUCCESS) 2336 return ret; 2337 2338 if (drv->API.GLInteropQueryDeviceInfo) 2339 ret = drv->API.GLInteropQueryDeviceInfo(disp, ctx, out); 2340 else 2341 ret = MESA_GLINTEROP_UNSUPPORTED; 2342 2343 _eglUnlockDisplay(disp); 2344 return ret; 2345} 2346 2347int 2348MesaGLInteropEGLExportObject(EGLDisplay dpy, EGLContext context, 2349 struct mesa_glinterop_export_in *in, 2350 struct mesa_glinterop_export_out *out) 2351{ 2352 _EGLDisplay *disp; 2353 _EGLDriver *drv; 2354 _EGLContext *ctx; 2355 int ret; 2356 2357 ret = _eglLockDisplayInterop(dpy, context, &disp, &drv, &ctx); 2358 if (ret != MESA_GLINTEROP_SUCCESS) 2359 return ret; 2360 2361 if (drv->API.GLInteropExportObject) 2362 ret = drv->API.GLInteropExportObject(disp, ctx, in, out); 2363 else 2364 ret = MESA_GLINTEROP_UNSUPPORTED; 2365 2366 _eglUnlockDisplay(disp); 2367 return ret; 2368} 2369