eglapi.c revision d5078b94323241a6482f54797756116b1c864327
1/** 2 * Public EGL API entrypoints 3 * 4 * Generally, we use the EGLDisplay parameter as a key to lookup the 5 * appropriate device driver handle, then jump though the driver's 6 * dispatch table to handle the function. 7 * 8 * That allows us the option of supporting multiple, simultaneous, 9 * heterogeneous hardware devices in the future. 10 * 11 * The EGLDisplay, EGLConfig, EGLContext and EGLSurface types are 12 * opaque handles implemented with 32-bit unsigned integers. 13 * It's up to the driver function or fallback function to look up the 14 * handle and get an object. 15 * By using opaque handles, we leave open the possibility of having 16 * indirect rendering in the future, like GLX. 17 * 18 * 19 * Notes on naming conventions: 20 * 21 * eglFooBar - public EGL function 22 * EGL_FOO_BAR - public EGL token 23 * EGLDatatype - public EGL datatype 24 * 25 * _eglFooBar - private EGL function 26 * _EGLDatatype - private EGL datatype, typedef'd struct 27 * _egl_struct - private EGL struct, non-typedef'd 28 * 29 */ 30 31 32 33#include <stdio.h> 34#include <stdlib.h> 35#include <string.h> 36#include "eglcontext.h" 37#include "egldisplay.h" 38#include "egltypedefs.h" 39#include "eglglobals.h" 40#include "egldriver.h" 41#include "eglsurface.h" 42 43 44 45/** 46 * This is typically the first EGL function that an application calls. 47 * We initialize our global vars and create a private _EGLDisplay object. 48 */ 49EGLDisplay EGLAPIENTRY 50eglGetDisplay(NativeDisplayType nativeDisplay) 51{ 52 _EGLDisplay *dpy; 53 _eglInitGlobals(); 54 dpy = _eglNewDisplay(nativeDisplay); 55 return _eglGetDisplayHandle(dpy); 56} 57 58 59/** 60 * This is typically the second EGL function that an application calls. 61 * Here we load/initialize the actual hardware driver. 62 */ 63EGLBoolean EGLAPIENTRY 64eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor) 65{ 66 if (dpy) { 67 EGLBoolean retVal; 68 _EGLDisplay *dpyPriv = _eglLookupDisplay(dpy); 69 if (!dpyPriv) { 70 return EGL_FALSE; 71 } 72 dpyPriv->Driver = _eglOpenDriver(dpyPriv, 73 dpyPriv->DriverName, 74 dpyPriv->DriverArgs); 75 if (!dpyPriv->Driver) { 76 return EGL_FALSE; 77 } 78 /* Initialize the particular driver now */ 79 retVal = dpyPriv->Driver->API.Initialize(dpyPriv->Driver, dpy, 80 major, minor); 81 82 dpyPriv->Driver->APImajor = *major; 83 dpyPriv->Driver->APIminor = *minor; 84 snprintf(dpyPriv->Driver->Version, sizeof(dpyPriv->Driver->Version), 85 "%d.%d (%s)", *major, *minor, dpyPriv->Driver->Name); 86 87 return retVal; 88 } 89 return EGL_FALSE; 90} 91 92 93EGLBoolean EGLAPIENTRY 94eglTerminate(EGLDisplay dpy) 95{ 96 _EGLDriver *drv = _eglLookupDriver(dpy); 97 if (drv) 98 return _eglCloseDriver(drv, dpy); 99 else 100 return EGL_FALSE; 101} 102 103 104const char * EGLAPIENTRY 105eglQueryString(EGLDisplay dpy, EGLint name) 106{ 107 _EGLDriver *drv = _eglLookupDriver(dpy); 108 if (drv) 109 return drv->API.QueryString(drv, dpy, name); 110 else 111 return NULL; 112} 113 114 115EGLBoolean EGLAPIENTRY 116eglGetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config) 117{ 118 _EGLDriver *drv = _eglLookupDriver(dpy); 119 /* XXX check drv for null in remaining functions */ 120 return drv->API.GetConfigs(drv, dpy, configs, config_size, num_config); 121} 122 123 124EGLBoolean EGLAPIENTRY 125eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config) 126{ 127 _EGLDriver *drv = _eglLookupDriver(dpy); 128 return drv->API.ChooseConfig(drv, dpy, attrib_list, configs, config_size, num_config); 129} 130 131 132EGLBoolean EGLAPIENTRY 133eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value) 134{ 135 _EGLDriver *drv = _eglLookupDriver(dpy); 136 return drv->API.GetConfigAttrib(drv, dpy, config, attribute, value); 137} 138 139 140EGLContext EGLAPIENTRY 141eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_list, const EGLint *attrib_list) 142{ 143 _EGLDriver *drv = _eglLookupDriver(dpy); 144 return drv->API.CreateContext(drv, dpy, config, share_list, attrib_list); 145} 146 147 148EGLBoolean EGLAPIENTRY 149eglDestroyContext(EGLDisplay dpy, EGLContext ctx) 150{ 151 _EGLDriver *drv = _eglLookupDriver(dpy); 152 return drv->API.DestroyContext(drv, dpy, ctx); 153} 154 155 156EGLBoolean EGLAPIENTRY 157eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx) 158{ 159 _EGLDriver *drv = _eglLookupDriver(dpy); 160 return drv->API.MakeCurrent(drv, dpy, draw, read, ctx); 161} 162 163 164EGLBoolean EGLAPIENTRY 165eglQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value) 166{ 167 _EGLDriver *drv = _eglLookupDriver(dpy); 168 return drv->API.QueryContext(drv, dpy, ctx, attribute, value); 169} 170 171 172EGLSurface EGLAPIENTRY 173eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, NativeWindowType window, const EGLint *attrib_list) 174{ 175 _EGLDriver *drv = _eglLookupDriver(dpy); 176 return drv->API.CreateWindowSurface(drv, dpy, config, window, attrib_list); 177} 178 179 180EGLSurface EGLAPIENTRY 181eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, NativePixmapType pixmap, const EGLint *attrib_list) 182{ 183 _EGLDriver *drv = _eglLookupDriver(dpy); 184 return drv->API.CreatePixmapSurface(drv, dpy, config, pixmap, attrib_list); 185} 186 187 188EGLSurface EGLAPIENTRY 189eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list) 190{ 191 _EGLDriver *drv = _eglLookupDriver(dpy); 192 return drv->API.CreatePbufferSurface(drv, dpy, config, attrib_list); 193} 194 195 196EGLBoolean EGLAPIENTRY 197eglDestroySurface(EGLDisplay dpy, EGLSurface surface) 198{ 199 _EGLDriver *drv = _eglLookupDriver(dpy); 200 return drv->API.DestroySurface(drv, dpy, surface); 201} 202 203 204EGLBoolean EGLAPIENTRY 205eglQuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value) 206{ 207 _EGLDriver *drv = _eglLookupDriver(dpy); 208 return drv->API.QuerySurface(drv, dpy, surface, attribute, value); 209} 210 211 212EGLBoolean EGLAPIENTRY 213eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value) 214{ 215 _EGLDriver *drv = _eglLookupDriver(dpy); 216 return drv->API.SurfaceAttrib(drv, dpy, surface, attribute, value); 217} 218 219 220EGLBoolean EGLAPIENTRY 221eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer) 222{ 223 _EGLDriver *drv = _eglLookupDriver(dpy); 224 return drv->API.BindTexImage(drv, dpy, surface, buffer); 225} 226 227 228EGLBoolean EGLAPIENTRY 229eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer) 230{ 231 _EGLDriver *drv = _eglLookupDriver(dpy); 232 return drv->API.ReleaseTexImage(drv, dpy, surface, buffer); 233} 234 235 236EGLBoolean EGLAPIENTRY 237eglSwapInterval(EGLDisplay dpy, EGLint interval) 238{ 239 _EGLDriver *drv = _eglLookupDriver(dpy); 240 return drv->API.SwapInterval(drv, dpy, interval); 241} 242 243 244EGLBoolean EGLAPIENTRY 245eglSwapBuffers(EGLDisplay dpy, EGLSurface draw) 246{ 247 _EGLDriver *drv = _eglLookupDriver(dpy); 248 return drv->API.SwapBuffers(drv, dpy, draw); 249} 250 251 252EGLBoolean EGLAPIENTRY 253eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, NativePixmapType target) 254{ 255 _EGLDriver *drv = _eglLookupDriver(dpy); 256 return drv->API.CopyBuffers(drv, dpy, surface, target); 257} 258 259 260EGLBoolean EGLAPIENTRY 261eglWaitGL(void) 262{ 263 EGLDisplay dpy = eglGetCurrentDisplay(); 264 if (dpy != EGL_NO_DISPLAY) { 265 _EGLDriver *drv = _eglLookupDriver(dpy); 266 return drv->API.WaitGL(drv, dpy); 267 } 268 else 269 return EGL_FALSE; 270} 271 272 273EGLBoolean EGLAPIENTRY 274eglWaitNative(EGLint engine) 275{ 276 EGLDisplay dpy = eglGetCurrentDisplay(); 277 if (dpy != EGL_NO_DISPLAY) { 278 _EGLDriver *drv = _eglLookupDriver(dpy); 279 return drv->API.WaitNative(drv, dpy, engine); 280 } 281 else 282 return EGL_FALSE; 283} 284 285 286EGLDisplay EGLAPIENTRY 287eglGetCurrentDisplay(void) 288{ 289 _EGLDisplay *dpy = _eglGetCurrentDisplay(); 290 return _eglGetDisplayHandle(dpy); 291} 292 293 294EGLContext EGLAPIENTRY 295eglGetCurrentContext(void) 296{ 297 _EGLContext *ctx = _eglGetCurrentContext(); 298 return _eglGetContextHandle(ctx); 299} 300 301 302EGLSurface EGLAPIENTRY 303eglGetCurrentSurface(EGLint readdraw) 304{ 305 _EGLSurface *s = _eglGetCurrentSurface(readdraw); 306 return _eglGetSurfaceHandle(s); 307} 308 309 310EGLint EGLAPIENTRY 311eglGetError(void) 312{ 313 _EGLThreadInfo *t = _eglGetCurrentThread(); 314 EGLint e = t->LastError; 315 t->LastError = EGL_SUCCESS; 316 return e; 317} 318 319 320void (* EGLAPIENTRY eglGetProcAddress(const char *procname))() 321{ 322 typedef void (*genericFunc)(); 323 struct name_function { 324 const char *name; 325 _EGLProc function; 326 }; 327 static struct name_function egl_functions[] = { 328 /* alphabetical order */ 329 { "eglBindTexImage", (_EGLProc) eglBindTexImage }, 330 { "eglChooseConfig", (_EGLProc) eglChooseConfig }, 331 { "eglCopyBuffers", (_EGLProc) eglCopyBuffers }, 332 { "eglCreateContext", (_EGLProc) eglCreateContext }, 333 { "eglCreatePbufferSurface", (_EGLProc) eglCreatePbufferSurface }, 334 { "eglCreatePixmapSurface", (_EGLProc) eglCreatePixmapSurface }, 335 { "eglCreateWindowSurface", (_EGLProc) eglCreateWindowSurface }, 336 { "eglDestroyContext", (_EGLProc) eglDestroyContext }, 337 { "eglDestroySurface", (_EGLProc) eglDestroySurface }, 338 { "eglGetConfigAttrib", (_EGLProc) eglGetConfigAttrib }, 339 { "eglGetConfigs", (_EGLProc) eglGetConfigs }, 340 { "eglGetCurrentContext", (_EGLProc) eglGetCurrentContext }, 341 { "eglGetCurrentDisplay", (_EGLProc) eglGetCurrentDisplay }, 342 { "eglGetCurrentSurface", (_EGLProc) eglGetCurrentSurface }, 343 { "eglGetDisplay", (_EGLProc) eglGetDisplay }, 344 { "eglGetError", (_EGLProc) eglGetError }, 345 { "eglGetProcAddress", (_EGLProc) eglGetProcAddress }, 346 { "eglInitialize", (_EGLProc) eglInitialize }, 347 { "eglMakeCurrent", (_EGLProc) eglMakeCurrent }, 348 { "eglQueryContext", (_EGLProc) eglQueryContext }, 349 { "eglQueryString", (_EGLProc) eglQueryString }, 350 { "eglQuerySurface", (_EGLProc) eglQuerySurface }, 351 { "eglReleaseTexImage", (_EGLProc) eglReleaseTexImage }, 352 { "eglSurfaceAttrib", (_EGLProc) eglSurfaceAttrib }, 353 { "eglSwapBuffers", (_EGLProc) eglSwapBuffers }, 354 { "eglSwapInterval", (_EGLProc) eglSwapInterval }, 355 { "eglTerminate", (_EGLProc) eglTerminate }, 356 { "eglWaitGL", (_EGLProc) eglWaitGL }, 357 { "eglWaitNative", (_EGLProc) eglWaitNative }, 358 /* Extensions */ 359#ifdef EGL_MESA_screen_surface 360 { "eglChooseModeMESA", (_EGLProc) eglChooseModeMESA }, 361 { "eglGetModesMESA", (_EGLProc) eglGetModesMESA }, 362 { "eglGetModeAttribMESA", (_EGLProc) eglGetModeAttribMESA }, 363 { "eglCopyContextMESA", (_EGLProc) eglCopyContextMESA }, 364 { "eglGetScreensMESA", (_EGLProc) eglGetScreensMESA }, 365 { "eglCreateScreenSurfaceMESA", (_EGLProc) eglCreateScreenSurfaceMESA }, 366 { "eglShowScreenSurfaceMESA", (_EGLProc) eglShowScreenSurfaceMESA }, 367 { "eglScreenPositionMESA", (_EGLProc) eglScreenPositionMESA }, 368 { "eglQueryScreenMESA", (_EGLProc) eglQueryScreenMESA }, 369 { "eglQueryScreenSurfaceMESA", (_EGLProc) eglQueryScreenSurfaceMESA }, 370 { "eglQueryScreenModeMESA", (_EGLProc) eglQueryScreenModeMESA }, 371 { "eglQueryModeStringMESA", (_EGLProc) eglQueryModeStringMESA }, 372#endif /* EGL_MESA_screen_surface */ 373#ifdef EGL_VERSION_1_2 374 { "eglBindAPI", (_EGLProc) eglBindAPI }, 375 { "eglCreatePbufferFromClientBuffer", (_EGLProc) eglCreatePbufferFromClientBuffer }, 376 { "eglQueryAPI", (_EGLProc) eglQueryAPI }, 377 { "eglReleaseThread", (_EGLProc) eglReleaseThread }, 378 { "eglWaitClient", (_EGLProc) eglWaitClient }, 379#endif /* EGL_VERSION_1_2 */ 380 { NULL, NULL } 381 }; 382 EGLint i; 383 for (i = 0; egl_functions[i].name; i++) { 384 if (strcmp(egl_functions[i].name, procname) == 0) { 385 return (genericFunc) egl_functions[i].function; 386 } 387 } 388#if 0 389 /* XXX enable this code someday */ 390 return (genericFunc) _glapi_get_proc_address(procname); 391#else 392 return NULL; 393#endif 394} 395 396 397/* 398 * EGL_MESA_screen extension 399 */ 400 401EGLBoolean EGLAPIENTRY 402eglChooseModeMESA(EGLDisplay dpy, EGLScreenMESA screen, 403 const EGLint *attrib_list, EGLModeMESA *modes, 404 EGLint modes_size, EGLint *num_modes) 405{ 406 _EGLDriver *drv = _eglLookupDriver(dpy); 407 if (drv) 408 return drv->API.ChooseModeMESA(drv, dpy, screen, attrib_list, modes, modes_size, num_modes); 409 else 410 return EGL_FALSE; 411} 412 413 414EGLBoolean EGLAPIENTRY 415eglGetModesMESA(EGLDisplay dpy, EGLScreenMESA screen, EGLModeMESA *modes, EGLint mode_size, EGLint *num_mode) 416{ 417 _EGLDriver *drv = _eglLookupDriver(dpy); 418 if (drv) 419 return drv->API.GetModesMESA(drv, dpy, screen, modes, mode_size, num_mode); 420 else 421 return EGL_FALSE; 422} 423 424 425EGLBoolean EGLAPIENTRY 426eglGetModeAttribMESA(EGLDisplay dpy, EGLModeMESA mode, EGLint attribute, EGLint *value) 427{ 428 _EGLDriver *drv = _eglLookupDriver(dpy); 429 if (drv) 430 return drv->API.GetModeAttribMESA(drv, dpy, mode, attribute, value); 431 else 432 return EGL_FALSE; 433} 434 435 436EGLBoolean EGLAPIENTRY 437eglCopyContextMESA(EGLDisplay dpy, EGLContext source, EGLContext dest, EGLint mask) 438{ 439 _EGLDriver *drv = _eglLookupDriver(dpy); 440 if (drv) 441 return drv->API.CopyContextMESA(drv, dpy, source, dest, mask); 442 else 443 return EGL_FALSE; 444} 445 446 447EGLBoolean 448eglGetScreensMESA(EGLDisplay dpy, EGLScreenMESA *screens, EGLint max_screens, EGLint *num_screens) 449{ 450 _EGLDriver *drv = _eglLookupDriver(dpy); 451 if (drv) 452 return drv->API.GetScreensMESA(drv, dpy, screens, max_screens, num_screens); 453 else 454 return EGL_FALSE; 455} 456 457 458EGLSurface 459eglCreateScreenSurfaceMESA(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list) 460{ 461 _EGLDriver *drv = _eglLookupDriver(dpy); 462 return drv->API.CreateScreenSurfaceMESA(drv, dpy, config, attrib_list); 463} 464 465 466EGLBoolean 467eglShowScreenSurfaceMESA(EGLDisplay dpy, EGLint screen, EGLSurface surface, EGLModeMESA mode) 468{ 469 _EGLDriver *drv = _eglLookupDriver(dpy); 470 return drv->API.ShowScreenSurfaceMESA(drv, dpy, screen, surface, mode); 471} 472 473 474EGLBoolean 475eglScreenPositionMESA(EGLDisplay dpy, EGLScreenMESA screen, EGLint x, EGLint y) 476{ 477 _EGLDriver *drv = _eglLookupDriver(dpy); 478 return drv->API.ScreenPositionMESA(drv, dpy, screen, x, y); 479} 480 481 482EGLBoolean 483eglQueryScreenMESA( EGLDisplay dpy, EGLScreenMESA screen, EGLint attribute, EGLint *value) 484{ 485 _EGLDriver *drv = _eglLookupDriver(dpy); 486 return drv->API.QueryScreenMESA(drv, dpy, screen, attribute, value); 487} 488 489 490EGLBoolean 491eglQueryScreenSurfaceMESA(EGLDisplay dpy, EGLScreenMESA screen, EGLSurface *surface) 492{ 493 _EGLDriver *drv = _eglLookupDriver(dpy); 494 return drv->API.QueryScreenSurfaceMESA(drv, dpy, screen, surface); 495} 496 497 498EGLBoolean 499eglQueryScreenModeMESA(EGLDisplay dpy, EGLScreenMESA screen, EGLModeMESA *mode) 500{ 501 _EGLDriver *drv = _eglLookupDriver(dpy); 502 return drv->API.QueryScreenModeMESA(drv, dpy, screen, mode); 503} 504 505 506const char * 507eglQueryModeStringMESA(EGLDisplay dpy, EGLModeMESA mode) 508{ 509 _EGLDriver *drv = _eglLookupDriver(dpy); 510 return drv->API.QueryModeStringMESA(drv, dpy, mode); 511} 512 513 514/** 515 ** EGL 1.2 516 **/ 517 518#ifdef EGL_VERSION_1_2 519 520 521/** 522 * Specify the client API to use for subsequent calls including: 523 * eglCreateContext() 524 * eglGetCurrentContext() 525 * eglGetCurrentDisplay() 526 * eglGetCurrentSurface() 527 * eglMakeCurrent(when the ctx parameter is EGL NO CONTEXT) 528 * eglWaitClient() 529 * eglWaitNative() 530 * See section 3.7 "Rendering Context" in the EGL specification for details. 531 */ 532EGLBoolean 533eglBindAPI(EGLenum api) 534{ 535 _EGLThreadInfo *t = _eglGetCurrentThread(); 536 537 switch (api) { 538#ifdef EGL_VERSION_1_4 539 case EGL_OPENGL_API: 540 if (_eglGlobal.ClientAPIsMask & EGL_OPENGL_BIT) { 541 t->CurrentAPI = api; 542 return EGL_TRUE; 543 } 544 _eglError(EGL_BAD_PARAMETER, "eglBindAPI"); 545 return EGL_FALSE; 546#endif 547 case EGL_OPENGL_ES_API: 548 if (_eglGlobal.ClientAPIsMask & (EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT)) { 549 t->CurrentAPI = api; 550 return EGL_TRUE; 551 } 552 _eglError(EGL_BAD_PARAMETER, "eglBindAPI"); 553 return EGL_FALSE; 554 case EGL_OPENVG_API: 555 if (_eglGlobal.ClientAPIsMask & EGL_OPENVG_BIT) { 556 t->CurrentAPI = api; 557 return EGL_TRUE; 558 } 559 _eglError(EGL_BAD_PARAMETER, "eglBindAPI"); 560 return EGL_FALSE; 561 default: 562 return EGL_FALSE; 563 } 564 return EGL_TRUE; 565} 566 567 568/** 569 * Return the last value set with eglBindAPI(). 570 */ 571EGLenum 572eglQueryAPI(void) 573{ 574 /* returns one of EGL_OPENGL_API, EGL_OPENGL_ES_API or EGL_OPENVG_API */ 575 _EGLThreadInfo *t = _eglGetCurrentThread(); 576 return t->CurrentAPI; 577} 578 579 580EGLSurface 581eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, 582 EGLClientBuffer buffer, EGLConfig config, 583 const EGLint *attrib_list) 584{ 585 _EGLDriver *drv = _eglLookupDriver(dpy); 586 return drv->API.CreatePbufferFromClientBuffer(drv, dpy, buftype, buffer, 587 config, attrib_list); 588} 589 590 591EGLBoolean 592eglReleaseThread(void) 593{ 594 _EGLThreadInfo *t = _eglGetCurrentThread(); 595 EGLDisplay dpy = eglGetCurrentDisplay(); 596 if (dpy) { 597 _EGLDriver *drv = _eglLookupDriver(dpy); 598 /* unbind context */ 599 (void) drv->API.MakeCurrent(drv, dpy, EGL_NO_SURFACE, 600 EGL_NO_SURFACE, EGL_NO_CONTEXT); 601 } 602 _eglDeleteThreadData(t); 603 return EGL_TRUE; 604} 605 606 607EGLBoolean 608eglWaitClient(void) 609{ 610 EGLDisplay dpy = eglGetCurrentDisplay(); 611 if (dpy != EGL_NO_DISPLAY) { 612 _EGLDriver *drv = _eglLookupDriver(dpy); 613 return drv->API.WaitClient(drv, dpy); 614 } 615 else 616 return EGL_FALSE; 617} 618 619#endif /* EGL_VERSION_1_2 */ 620