X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fegl%2Fmain%2Feglapi.c;h=b5c5e79c751b85a379e8b2171e2cd8ec1a1b5f92;hb=435ad514163d58596059256ae8f0bc518b99b4a1;hp=5694b5a4ca3ebdde490180210cab60c4234cf632;hpb=1534fc6d10509a443700a05923ab3f55eae1fd53;p=mesa.git diff --git a/src/egl/main/eglapi.c b/src/egl/main/eglapi.c index 5694b5a4ca3..b5c5e79c751 100644 --- a/src/egl/main/eglapi.c +++ b/src/egl/main/eglapi.c @@ -83,25 +83,33 @@ */ +#ifdef USE_LIBGLVND +#define EGLAPI +#undef PUBLIC +#define PUBLIC +#endif + #include #include #include #include "c99_compat.h" #include "c11/threads.h" -#include "GL/mesa_glinterop.h" -#include "eglcompiler.h" +#include "util/macros.h" +#include "egldefines.h" #include "eglglobals.h" #include "eglcontext.h" #include "egldisplay.h" #include "egltypedefs.h" #include "eglcurrent.h" +#include "egldevice.h" #include "egldriver.h" #include "eglsurface.h" #include "eglconfig.h" #include "eglimage.h" #include "eglsync.h" +#include "GL/mesa_glinterop.h" /** * Macros to help return an API entrypoint. @@ -163,7 +171,7 @@ struct _egl_entrypoint { }; -static inline _EGLDriver * +static inline const _EGLDriver * _eglCheckDisplay(_EGLDisplay *disp, const char *msg) { if (!disp) { @@ -178,10 +186,10 @@ _eglCheckDisplay(_EGLDisplay *disp, const char *msg) } -static inline _EGLDriver * +static inline const _EGLDriver * _eglCheckSurface(_EGLDisplay *disp, _EGLSurface *surf, const char *msg) { - _EGLDriver *drv = _eglCheckDisplay(disp, msg); + const _EGLDriver *drv = _eglCheckDisplay(disp, msg); if (!drv) return NULL; if (!surf) { @@ -192,10 +200,10 @@ _eglCheckSurface(_EGLDisplay *disp, _EGLSurface *surf, const char *msg) } -static inline _EGLDriver * +static inline const _EGLDriver * _eglCheckContext(_EGLDisplay *disp, _EGLContext *context, const char *msg) { - _EGLDriver *drv = _eglCheckDisplay(disp, msg); + const _EGLDriver *drv = _eglCheckDisplay(disp, msg); if (!drv) return NULL; if (!context) { @@ -206,10 +214,10 @@ _eglCheckContext(_EGLDisplay *disp, _EGLContext *context, const char *msg) } -static inline _EGLDriver * +static inline const _EGLDriver * _eglCheckConfig(_EGLDisplay *disp, _EGLConfig *conf, const char *msg) { - _EGLDriver *drv = _eglCheckDisplay(disp, msg); + const _EGLDriver *drv = _eglCheckDisplay(disp, msg); if (!drv) return NULL; if (!conf) { @@ -220,10 +228,10 @@ _eglCheckConfig(_EGLDisplay *disp, _EGLConfig *conf, const char *msg) } -static inline _EGLDriver * +static inline const _EGLDriver * _eglCheckSync(_EGLDisplay *disp, _EGLSync *s, const char *msg) { - _EGLDriver *drv = _eglCheckDisplay(disp, msg); + const _EGLDriver *drv = _eglCheckDisplay(disp, msg); if (!drv) return NULL; if (!s) { @@ -238,12 +246,12 @@ _eglCheckSync(_EGLDisplay *disp, _EGLSync *s, const char *msg) * Lookup and lock a display. */ static inline _EGLDisplay * -_eglLockDisplay(EGLDisplay display) +_eglLockDisplay(EGLDisplay dpy) { - _EGLDisplay *dpy = _eglLookupDisplay(display); - if (dpy) - mtx_lock(&dpy->Mutex); - return dpy; + _EGLDisplay *disp = _eglLookupDisplay(dpy); + if (disp) + mtx_lock(&disp->Mutex); + return disp; } @@ -251,9 +259,9 @@ _eglLockDisplay(EGLDisplay display) * Unlock a display. */ static inline void -_eglUnlockDisplay(_EGLDisplay *dpy) +_eglUnlockDisplay(_EGLDisplay *disp) { - mtx_unlock(&dpy->Mutex); + mtx_unlock(&disp->Mutex); } static EGLBoolean @@ -274,8 +282,7 @@ _eglSetFuncName(const char *funcName, _EGLDisplay *disp, EGLenum objectType, _EG return EGL_TRUE; } - _eglDebugReportFull(EGL_BAD_ALLOC, funcName, funcName, - EGL_DEBUG_MSG_CRITICAL_KHR, NULL, NULL); + _eglDebugReport(EGL_BAD_ALLOC, funcName, EGL_DEBUG_MSG_CRITICAL_KHR, NULL); return EGL_FALSE; } @@ -332,22 +339,16 @@ _eglConvertIntsToAttribs(const EGLint *int_list, EGLAttrib **out_attrib_list) static EGLint * _eglConvertAttribsToInt(const EGLAttrib *attr_list) { + size_t size = _eglNumAttribs(attr_list); EGLint *int_attribs = NULL; /* Convert attributes from EGLAttrib[] to EGLint[] */ - if (attr_list) { - int i, size = 0; - - while (attr_list[size] != EGL_NONE) - size += 2; - - size += 1; /* add space for EGL_NONE */ - + if (size) { int_attribs = calloc(size, sizeof(int_attribs[0])); if (!int_attribs) return NULL; - for (i = 0; i < size; i++) + for (size_t i = 0; i < size; i++) int_attribs[i] = attr_list[i]; } return int_attribs; @@ -362,7 +363,7 @@ EGLDisplay EGLAPIENTRY eglGetDisplay(EGLNativeDisplayType nativeDisplay) { _EGLPlatformType plat; - _EGLDisplay *dpy; + _EGLDisplay *disp; void *native_display_ptr; _EGL_FUNC_START(NULL, EGL_OBJECT_THREAD_KHR, NULL, EGL_NO_DISPLAY); @@ -371,70 +372,75 @@ eglGetDisplay(EGLNativeDisplayType nativeDisplay) native_display_ptr = (void*) nativeDisplay; plat = _eglGetNativePlatform(native_display_ptr); - dpy = _eglFindDisplay(plat, native_display_ptr); - return _eglGetDisplayHandle(dpy); + disp = _eglFindDisplay(plat, native_display_ptr, NULL); + return _eglGetDisplayHandle(disp); } static EGLDisplay _eglGetPlatformDisplayCommon(EGLenum platform, void *native_display, - const EGLint *attrib_list) + const EGLAttrib *attrib_list) { - _EGLDisplay *dpy; + _EGLDisplay *disp; switch (platform) { #ifdef HAVE_X11_PLATFORM case EGL_PLATFORM_X11_EXT: - dpy = _eglGetX11Display((Display*) native_display, attrib_list); + disp = _eglGetX11Display((Display*) native_display, attrib_list); break; #endif #ifdef HAVE_DRM_PLATFORM case EGL_PLATFORM_GBM_MESA: - dpy = _eglGetGbmDisplay((struct gbm_device*) native_display, + disp = _eglGetGbmDisplay((struct gbm_device*) native_display, attrib_list); break; #endif #ifdef HAVE_WAYLAND_PLATFORM case EGL_PLATFORM_WAYLAND_EXT: - dpy = _eglGetWaylandDisplay((struct wl_display*) native_display, + disp = _eglGetWaylandDisplay((struct wl_display*) native_display, attrib_list); break; #endif -#ifdef HAVE_SURFACELESS_PLATFORM case EGL_PLATFORM_SURFACELESS_MESA: - dpy = _eglGetSurfacelessDisplay(native_display, attrib_list); + disp = _eglGetSurfacelessDisplay(native_display, attrib_list); + break; +#ifdef HAVE_ANDROID_PLATFORM + case EGL_PLATFORM_ANDROID_KHR: + disp = _eglGetAndroidDisplay(native_display, attrib_list); break; #endif + case EGL_PLATFORM_DEVICE_EXT: + disp = _eglGetDeviceDisplay(native_display, attrib_list); + break; default: RETURN_EGL_ERROR(NULL, EGL_BAD_PARAMETER, NULL); } - return _eglGetDisplayHandle(dpy); + return _eglGetDisplayHandle(disp); } static EGLDisplay EGLAPIENTRY eglGetPlatformDisplayEXT(EGLenum platform, void *native_display, - const EGLint *attrib_list) + const EGLint *int_attribs) { + EGLAttrib *attrib_list; + EGLDisplay disp; + _EGL_FUNC_START(NULL, EGL_OBJECT_THREAD_KHR, NULL, EGL_NO_DISPLAY); - return _eglGetPlatformDisplayCommon(platform, native_display, attrib_list); + + if (_eglConvertIntsToAttribs(int_attribs, &attrib_list) != EGL_SUCCESS) + RETURN_EGL_ERROR(NULL, EGL_BAD_ALLOC, NULL); + + disp = _eglGetPlatformDisplayCommon(platform, native_display, attrib_list); + free(attrib_list); + return disp; } EGLDisplay EGLAPIENTRY eglGetPlatformDisplay(EGLenum platform, void *native_display, const EGLAttrib *attrib_list) { - EGLDisplay display; - EGLint *int_attribs; - _EGL_FUNC_START(NULL, EGL_OBJECT_THREAD_KHR, NULL, EGL_NO_DISPLAY); - - int_attribs = _eglConvertAttribsToInt(attrib_list); - if (attrib_list && !int_attribs) - RETURN_EGL_ERROR(NULL, EGL_BAD_ALLOC, NULL); - - display = _eglGetPlatformDisplayCommon(platform, native_display, int_attribs); - free(int_attribs); - return display; + return _eglGetPlatformDisplayCommon(platform, native_display, attrib_list); } /** @@ -465,19 +471,20 @@ _eglAppendExtension(char **str, const char *ext) * the driver's Extensions string. */ static void -_eglCreateExtensionsString(_EGLDisplay *dpy) +_eglCreateExtensionsString(_EGLDisplay *disp) { #define _EGL_CHECK_EXTENSION(ext) \ do { \ - if (dpy->Extensions.ext) { \ + if (disp->Extensions.ext) { \ _eglAppendExtension(&exts, "EGL_" #ext); \ - assert(exts <= dpy->ExtensionsString + _EGL_MAX_EXTENSIONS_LEN); \ + assert(exts <= disp->ExtensionsString + _EGL_MAX_EXTENSIONS_LEN); \ } \ } while (0) - char *exts = dpy->ExtensionsString; + char *exts = disp->ExtensionsString; /* Please keep these sorted alphabetically. */ + _EGL_CHECK_EXTENSION(ANDROID_blob_cache); _EGL_CHECK_EXTENSION(ANDROID_framebuffer_target); _EGL_CHECK_EXTENSION(ANDROID_image_native_buffer); _EGL_CHECK_EXTENSION(ANDROID_native_fence_sync); @@ -488,11 +495,18 @@ _eglCreateExtensionsString(_EGLDisplay *dpy) _EGL_CHECK_EXTENSION(EXT_buffer_age); _EGL_CHECK_EXTENSION(EXT_create_context_robustness); _EGL_CHECK_EXTENSION(EXT_image_dma_buf_import); + _EGL_CHECK_EXTENSION(EXT_image_dma_buf_import_modifiers); + _EGL_CHECK_EXTENSION(EXT_surface_CTA861_3_metadata); + _EGL_CHECK_EXTENSION(EXT_surface_SMPTE2086_metadata); _EGL_CHECK_EXTENSION(EXT_swap_buffers_with_damage); + _EGL_CHECK_EXTENSION(IMG_context_priority); + _EGL_CHECK_EXTENSION(KHR_cl_event2); _EGL_CHECK_EXTENSION(KHR_config_attribs); + _EGL_CHECK_EXTENSION(KHR_context_flush_control); _EGL_CHECK_EXTENSION(KHR_create_context); + _EGL_CHECK_EXTENSION(KHR_create_context_no_error); _EGL_CHECK_EXTENSION(KHR_fence_sync); _EGL_CHECK_EXTENSION(KHR_get_all_proc_addresses); _EGL_CHECK_EXTENSION(KHR_gl_colorspace); @@ -500,21 +514,26 @@ _eglCreateExtensionsString(_EGLDisplay *dpy) _EGL_CHECK_EXTENSION(KHR_gl_texture_2D_image); _EGL_CHECK_EXTENSION(KHR_gl_texture_3D_image); _EGL_CHECK_EXTENSION(KHR_gl_texture_cubemap_image); - if (dpy->Extensions.KHR_image_base && dpy->Extensions.KHR_image_pixmap) - _eglAppendExtension(&exts, "EGL_KHR_image"); + if (disp->Extensions.KHR_image_base && disp->Extensions.KHR_image_pixmap) + disp->Extensions.KHR_image = EGL_TRUE; + _EGL_CHECK_EXTENSION(KHR_image); _EGL_CHECK_EXTENSION(KHR_image_base); _EGL_CHECK_EXTENSION(KHR_image_pixmap); + _EGL_CHECK_EXTENSION(KHR_mutable_render_buffer); _EGL_CHECK_EXTENSION(KHR_no_config_context); + _EGL_CHECK_EXTENSION(KHR_partial_update); _EGL_CHECK_EXTENSION(KHR_reusable_sync); _EGL_CHECK_EXTENSION(KHR_surfaceless_context); - if (dpy->Extensions.EXT_swap_buffers_with_damage) + if (disp->Extensions.EXT_swap_buffers_with_damage) _eglAppendExtension(&exts, "EGL_KHR_swap_buffers_with_damage"); + _EGL_CHECK_EXTENSION(EXT_pixel_format_float); _EGL_CHECK_EXTENSION(KHR_wait_sync); - if (dpy->Extensions.KHR_no_config_context) + if (disp->Extensions.KHR_no_config_context) _eglAppendExtension(&exts, "EGL_MESA_configless_context"); _EGL_CHECK_EXTENSION(MESA_drm_image); _EGL_CHECK_EXTENSION(MESA_image_dma_buf_export); + _EGL_CHECK_EXTENSION(MESA_query_driver); _EGL_CHECK_EXTENSION(NOK_swap_region); _EGL_CHECK_EXTENSION(NOK_texture_from_pixmap); @@ -528,21 +547,32 @@ _eglCreateExtensionsString(_EGLDisplay *dpy) } static void -_eglCreateAPIsString(_EGLDisplay *dpy) -{ - if (dpy->ClientAPIs & EGL_OPENGL_BIT) - strcat(dpy->ClientAPIsString, "OpenGL "); +_eglCreateAPIsString(_EGLDisplay *disp) +{ +#define addstr(str) \ + { \ + const size_t old_len = strlen(disp->ClientAPIsString); \ + const size_t add_len = sizeof(str); \ + const size_t max_len = sizeof(disp->ClientAPIsString) - 1; \ + if (old_len + add_len <= max_len) \ + strcat(disp->ClientAPIsString, str " "); \ + else \ + assert(!"disp->ClientAPIsString is not large enough"); \ + } - if (dpy->ClientAPIs & EGL_OPENGL_ES_BIT || - dpy->ClientAPIs & EGL_OPENGL_ES2_BIT || - dpy->ClientAPIs & EGL_OPENGL_ES3_BIT_KHR) { - strcat(dpy->ClientAPIsString, "OpenGL_ES "); + if (disp->ClientAPIs & EGL_OPENGL_BIT) + addstr("OpenGL"); + + if (disp->ClientAPIs & EGL_OPENGL_ES_BIT || + disp->ClientAPIs & EGL_OPENGL_ES2_BIT || + disp->ClientAPIs & EGL_OPENGL_ES3_BIT_KHR) { + addstr("OpenGL_ES"); } - if (dpy->ClientAPIs & EGL_OPENVG_BIT) - strcat(dpy->ClientAPIsString, "OpenVG "); + if (disp->ClientAPIs & EGL_OPENVG_BIT) + addstr("OpenVG"); - assert(strlen(dpy->ClientAPIsString) < sizeof(dpy->ClientAPIsString)); +#undef addstr } static void @@ -564,6 +594,11 @@ _eglComputeVersion(_EGLDisplay *disp) disp->Extensions.KHR_gl_colorspace && disp->Extensions.KHR_surfaceless_context) disp->Version = 15; + + /* For Android P and below limit the EGL version to 1.4 */ +#if defined(ANDROID) && ANDROID_API_LEVEL <= 28 + disp->Version = 14; +#endif } /** @@ -581,7 +616,7 @@ eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor) RETURN_EGL_ERROR(NULL, EGL_BAD_DISPLAY, EGL_FALSE); if (!disp->Initialized) { - if (!_eglMatchDriver(disp, EGL_FALSE)) + if (!_eglInitializeDisplay(disp)) RETURN_EGL_ERROR(disp, EGL_NOT_INITIALIZED, EGL_FALSE); /* limit to APIs supported by core */ @@ -613,8 +648,7 @@ eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor) _eglCreateExtensionsString(disp); _eglCreateAPIsString(disp); snprintf(disp->VersionString, sizeof(disp->VersionString), - "%d.%d (%s)", disp->Version / 10, disp->Version % 10, - disp->Driver->Name); + "%d.%d", disp->Version / 10, disp->Version % 10); } /* Update applications version of major and minor if not NULL */ @@ -638,12 +672,14 @@ eglTerminate(EGLDisplay dpy) RETURN_EGL_ERROR(NULL, EGL_BAD_DISPLAY, EGL_FALSE); if (disp->Initialized) { - _EGLDriver *drv = disp->Driver; - - drv->API.Terminate(drv, disp); + disp->Driver->Terminate(disp); /* do not reset disp->Driver */ disp->ClientAPIsString[0] = 0; disp->Initialized = EGL_FALSE; + + /* Reset blob cache funcs on terminate. */ + disp->BlobCacheSet = NULL; + disp->BlobCacheGet = NULL; } RETURN_EGL_SUCCESS(disp, EGL_TRUE); @@ -654,11 +690,13 @@ const char * EGLAPIENTRY eglQueryString(EGLDisplay dpy, EGLint name) { _EGLDisplay *disp; - _EGLDriver *drv; + const _EGLDriver *drv; +#if !USE_LIBGLVND if (dpy == EGL_NO_DISPLAY && name == EGL_EXTENSIONS) { RETURN_EGL_SUCCESS(NULL, _eglGlobal.ClientExtensionString); } +#endif disp = _eglLockDisplay(dpy); _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, NULL); @@ -684,13 +722,17 @@ eglGetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config) { _EGLDisplay *disp = _eglLockDisplay(dpy); - _EGLDriver *drv; + const _EGLDriver *drv; EGLBoolean ret; _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE); _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv); - ret = drv->API.GetConfigs(drv, disp, configs, config_size, num_config); + + if (!num_config) + RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE); + + ret = _eglGetConfigs(drv, disp, configs, config_size, num_config); RETURN_EGL_EVAL(disp, ret); } @@ -701,14 +743,18 @@ eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config) { _EGLDisplay *disp = _eglLockDisplay(dpy); - _EGLDriver *drv; + const _EGLDriver *drv; EGLBoolean ret; _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE); _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv); - ret = drv->API.ChooseConfig(drv, disp, attrib_list, configs, - config_size, num_config); + + if (!num_config) + RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE); + + ret = _eglChooseConfig(drv, disp, attrib_list, configs, + config_size, num_config); RETURN_EGL_EVAL(disp, ret); } @@ -720,13 +766,14 @@ eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, { _EGLDisplay *disp = _eglLockDisplay(dpy); _EGLConfig *conf = _eglLookupConfig(config, disp); - _EGLDriver *drv; + const _EGLDriver *drv; EGLBoolean ret; _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE); _EGL_CHECK_CONFIG(disp, conf, EGL_FALSE, drv); - ret = drv->API.GetConfigAttrib(drv, disp, conf, attribute, value); + + ret = _eglGetConfigAttrib(drv, disp, conf, attribute, value); RETURN_EGL_EVAL(disp, ret); } @@ -739,7 +786,7 @@ eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_list, _EGLDisplay *disp = _eglLockDisplay(dpy); _EGLConfig *conf = _eglLookupConfig(config, disp); _EGLContext *share = _eglLookupContext(share_list, disp); - _EGLDriver *drv; + const _EGLDriver *drv; _EGLContext *context; EGLContext ret; @@ -755,7 +802,7 @@ eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_list, if (!share && share_list != EGL_NO_CONTEXT) RETURN_EGL_ERROR(disp, EGL_BAD_CONTEXT, EGL_NO_CONTEXT); - context = drv->API.CreateContext(drv, disp, conf, share, attrib_list); + context = drv->CreateContext(drv, disp, conf, share, attrib_list); ret = (context) ? _eglLinkContext(context) : EGL_NO_CONTEXT; RETURN_EGL_EVAL(disp, ret); @@ -767,14 +814,14 @@ eglDestroyContext(EGLDisplay dpy, EGLContext ctx) { _EGLDisplay *disp = _eglLockDisplay(dpy); _EGLContext *context = _eglLookupContext(ctx, disp); - _EGLDriver *drv; + const _EGLDriver *drv; EGLBoolean ret; _EGL_FUNC_START(disp, EGL_OBJECT_CONTEXT_KHR, context, EGL_FALSE); _EGL_CHECK_CONTEXT(disp, context, EGL_FALSE, drv); _eglUnlinkContext(context); - ret = drv->API.DestroyContext(drv, disp, context); + ret = drv->DestroyContext(drv, disp, context); RETURN_EGL_EVAL(disp, ret); } @@ -788,7 +835,7 @@ eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, _EGLContext *context = _eglLookupContext(ctx, disp); _EGLSurface *draw_surf = _eglLookupSurface(draw, disp); _EGLSurface *read_surf = _eglLookupSurface(read, disp); - _EGLDriver *drv; + const _EGLDriver *drv; EGLBoolean ret; _EGL_FUNC_START(disp, EGL_OBJECT_CONTEXT_KHR, context, EGL_FALSE); @@ -824,7 +871,15 @@ eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_FALSE); } - ret = drv->API.MakeCurrent(drv, disp, draw_surf, read_surf, context); + /* If a native window underlying either draw or read is no longer valid, + * an EGL_BAD_NATIVE_WINDOW error is generated. + */ + if (draw_surf && draw_surf->Lost) + RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_WINDOW, EGL_FALSE); + if (read_surf && read_surf->Lost) + RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_WINDOW, EGL_FALSE); + + ret = drv->MakeCurrent(drv, disp, draw_surf, read_surf, context); RETURN_EGL_EVAL(disp, ret); } @@ -836,24 +891,51 @@ eglQueryContext(EGLDisplay dpy, EGLContext ctx, { _EGLDisplay *disp = _eglLockDisplay(dpy); _EGLContext *context = _eglLookupContext(ctx, disp); - _EGLDriver *drv; + const _EGLDriver *drv; EGLBoolean ret; _EGL_FUNC_START(disp, EGL_OBJECT_CONTEXT_KHR, context, EGL_FALSE); _EGL_CHECK_CONTEXT(disp, context, EGL_FALSE, drv); - ret = drv->API.QueryContext(drv, disp, context, attribute, value); + + ret = _eglQueryContext(drv, disp, context, attribute, value); RETURN_EGL_EVAL(disp, ret); } +/* In EGL specs 1.4 and 1.5, at the end of sections 3.5.1 and 3.5.4, it says + * that if native_surface was already used to create a window or pixmap, we + * can't create a new one. This is what this function checks for. + */ +static bool +_eglNativeSurfaceAlreadyUsed(_EGLDisplay *disp, void *native_surface) +{ + _EGLResource *list; + + list = disp->ResourceLists[_EGL_RESOURCE_SURFACE]; + while (list) { + _EGLSurface *surf = (_EGLSurface *) list; + + list = list->Next; + + if (surf->Type == EGL_PBUFFER_BIT) + continue; + + if (surf->NativeSurface == native_surface) + return true; + } + + return false; +} + + static EGLSurface _eglCreateWindowSurfaceCommon(_EGLDisplay *disp, EGLConfig config, void *native_window, const EGLint *attrib_list) { _EGLConfig *conf = _eglLookupConfig(config, disp); - _EGLDriver *drv; + const _EGLDriver *drv; _EGLSurface *surf; EGLSurface ret; @@ -861,8 +943,8 @@ _eglCreateWindowSurfaceCommon(_EGLDisplay *disp, EGLConfig config, if (native_window == NULL) RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE); -#ifdef HAVE_SURFACELESS_PLATFORM - if (disp && disp->Platform == _EGL_PLATFORM_SURFACELESS) { + if (disp && (disp->Platform == _EGL_PLATFORM_SURFACELESS || + disp->Platform == _EGL_PLATFORM_DEVICE)) { /* From the EGL_MESA_platform_surfaceless spec (v1): * * eglCreatePlatformWindowSurface fails when called with a @@ -877,14 +959,16 @@ _eglCreateWindowSurfaceCommon(_EGLDisplay *disp, EGLConfig config, */ RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE); } -#endif _EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE, drv); if ((conf->SurfaceType & EGL_WINDOW_BIT) == 0) RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_NO_SURFACE); - surf = drv->API.CreateWindowSurface(drv, disp, conf, native_window, + if (_eglNativeSurfaceAlreadyUsed(disp, native_window)) + RETURN_EGL_ERROR(disp, EGL_BAD_ALLOC, EGL_NO_SURFACE); + + surf = drv->CreateWindowSurface(drv, disp, conf, native_window, attrib_list); ret = (surf) ? _eglLinkSurface(surf) : EGL_NO_SURFACE; @@ -908,7 +992,7 @@ static void * _fixupNativeWindow(_EGLDisplay *disp, void *native_window) { #ifdef HAVE_X11_PLATFORM - if (disp->Platform == _EGL_PLATFORM_X11 && native_window != NULL) { + if (disp && disp->Platform == _EGL_PLATFORM_X11 && native_window != NULL) { /* The `native_window` parameter for the X11 platform differs between * eglCreateWindowSurface() and eglCreatePlatformPixmapSurfaceEXT(). In * eglCreateWindowSurface(), the type of `native_window` is an Xlib @@ -963,14 +1047,14 @@ static void * _fixupNativePixmap(_EGLDisplay *disp, void *native_pixmap) { #ifdef HAVE_X11_PLATFORM - /* The `native_pixmap` parameter for the X11 platform differs between - * eglCreatePixmapSurface() and eglCreatePlatformPixmapSurfaceEXT(). In - * eglCreatePixmapSurface(), the type of `native_pixmap` is an Xlib - * `Pixmap`. In eglCreatePlatformPixmapSurfaceEXT(), the type is - * `Pixmap*`. Convert `Pixmap*` to `Pixmap` because that's what - * dri2_x11_create_pixmap_surface() expects. - */ - if (disp->Platform == _EGL_PLATFORM_X11 && native_pixmap != NULL) + /* The `native_pixmap` parameter for the X11 platform differs between + * eglCreatePixmapSurface() and eglCreatePlatformPixmapSurfaceEXT(). In + * eglCreatePixmapSurface(), the type of `native_pixmap` is an Xlib + * `Pixmap`. In eglCreatePlatformPixmapSurfaceEXT(), the type is + * `Pixmap*`. Convert `Pixmap*` to `Pixmap` because that's what + * dri2_x11_create_pixmap_surface() expects. + */ + if (disp && disp->Platform == _EGL_PLATFORM_X11 && native_pixmap != NULL) return (void *)(* (Pixmap*) native_pixmap); #endif return native_pixmap; @@ -981,12 +1065,12 @@ _eglCreatePixmapSurfaceCommon(_EGLDisplay *disp, EGLConfig config, void *native_pixmap, const EGLint *attrib_list) { _EGLConfig *conf = _eglLookupConfig(config, disp); - _EGLDriver *drv; + const _EGLDriver *drv; _EGLSurface *surf; EGLSurface ret; -#if HAVE_SURFACELESS_PLATFORM - if (disp && disp->Platform == _EGL_PLATFORM_SURFACELESS) { + if (disp && (disp->Platform == _EGL_PLATFORM_SURFACELESS || + disp->Platform == _EGL_PLATFORM_DEVICE)) { /* From the EGL_MESA_platform_surfaceless spec (v1): * * [Like eglCreatePlatformWindowSurface,] eglCreatePlatformPixmapSurface @@ -999,14 +1083,19 @@ _eglCreatePixmapSurfaceCommon(_EGLDisplay *disp, EGLConfig config, */ RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_PIXMAP, EGL_NO_SURFACE); } -#endif _EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE, drv); if ((conf->SurfaceType & EGL_PIXMAP_BIT) == 0) RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_NO_SURFACE); - surf = drv->API.CreatePixmapSurface(drv, disp, conf, native_pixmap, + if (native_pixmap == NULL) + RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_PIXMAP, EGL_NO_SURFACE); + + if (_eglNativeSurfaceAlreadyUsed(disp, native_pixmap)) + RETURN_EGL_ERROR(disp, EGL_BAD_ALLOC, EGL_NO_SURFACE); + + surf = drv->CreatePixmapSurface(drv, disp, conf, native_pixmap, attrib_list); ret = (surf) ? _eglLinkSurface(surf) : EGL_NO_SURFACE; @@ -1023,13 +1112,13 @@ eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE); STATIC_ASSERT(sizeof(void*) == sizeof(pixmap)); return _eglCreatePixmapSurfaceCommon(disp, config, (void*) pixmap, - attrib_list); + attrib_list); } static EGLSurface EGLAPIENTRY eglCreatePlatformPixmapSurfaceEXT(EGLDisplay dpy, EGLConfig config, - void *native_pixmap, - const EGLint *attrib_list) + void *native_pixmap, + const EGLint *attrib_list) { _EGLDisplay *disp = _eglLockDisplay(dpy); @@ -1069,7 +1158,7 @@ eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, { _EGLDisplay *disp = _eglLockDisplay(dpy); _EGLConfig *conf = _eglLookupConfig(config, disp); - _EGLDriver *drv; + const _EGLDriver *drv; _EGLSurface *surf; EGLSurface ret; @@ -1079,7 +1168,7 @@ eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, if ((conf->SurfaceType & EGL_PBUFFER_BIT) == 0) RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_NO_SURFACE); - surf = drv->API.CreatePbufferSurface(drv, disp, conf, attrib_list); + surf = drv->CreatePbufferSurface(drv, disp, conf, attrib_list); ret = (surf) ? _eglLinkSurface(surf) : EGL_NO_SURFACE; RETURN_EGL_EVAL(disp, ret); @@ -1091,13 +1180,13 @@ eglDestroySurface(EGLDisplay dpy, EGLSurface surface) { _EGLDisplay *disp = _eglLockDisplay(dpy); _EGLSurface *surf = _eglLookupSurface(surface, disp); - _EGLDriver *drv; + const _EGLDriver *drv; EGLBoolean ret; _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE); _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv); _eglUnlinkSurface(surf); - ret = drv->API.DestroySurface(drv, disp, surf); + ret = drv->DestroySurface(drv, disp, surf); RETURN_EGL_EVAL(disp, ret); } @@ -1108,12 +1197,16 @@ eglQuerySurface(EGLDisplay dpy, EGLSurface surface, { _EGLDisplay *disp = _eglLockDisplay(dpy); _EGLSurface *surf = _eglLookupSurface(surface, disp); - _EGLDriver *drv; + const _EGLDriver *drv; EGLBoolean ret; _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE); _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv); - ret = drv->API.QuerySurface(drv, disp, surf, attribute, value); + + if (drv->QuerySurface) + ret = drv->QuerySurface(drv, disp, surf, attribute, value); + else + ret = _eglQuerySurface(drv, disp, surf, attribute, value); RETURN_EGL_EVAL(disp, ret); } @@ -1124,12 +1217,13 @@ eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, { _EGLDisplay *disp = _eglLockDisplay(dpy); _EGLSurface *surf = _eglLookupSurface(surface, disp); - _EGLDriver *drv; + const _EGLDriver *drv; EGLBoolean ret; _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE); _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv); - ret = drv->API.SurfaceAttrib(drv, disp, surf, attribute, value); + + ret = _eglSurfaceAttrib(drv, disp, surf, attribute, value); RETURN_EGL_EVAL(disp, ret); } @@ -1140,12 +1234,12 @@ eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer) { _EGLDisplay *disp = _eglLockDisplay(dpy); _EGLSurface *surf = _eglLookupSurface(surface, disp); - _EGLDriver *drv; + const _EGLDriver *drv; EGLBoolean ret; _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE); _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv); - ret = drv->API.BindTexImage(drv, disp, surf, buffer); + ret = drv->BindTexImage(drv, disp, surf, buffer); RETURN_EGL_EVAL(disp, ret); } @@ -1156,12 +1250,12 @@ eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer) { _EGLDisplay *disp = _eglLockDisplay(dpy); _EGLSurface *surf = _eglLookupSurface(surface, disp); - _EGLDriver *drv; + const _EGLDriver *drv; EGLBoolean ret; _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE); _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv); - ret = drv->API.ReleaseTexImage(drv, disp, surf, buffer); + ret = drv->ReleaseTexImage(drv, disp, surf, buffer); RETURN_EGL_EVAL(disp, ret); } @@ -1173,7 +1267,7 @@ eglSwapInterval(EGLDisplay dpy, EGLint interval) _EGLDisplay *disp = _eglLockDisplay(dpy); _EGLContext *ctx = _eglGetCurrentContext(); _EGLSurface *surf = ctx ? ctx->DrawSurface : NULL; - _EGLDriver *drv; + const _EGLDriver *drv; EGLBoolean ret; _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE); @@ -1186,7 +1280,25 @@ eglSwapInterval(EGLDisplay dpy, EGLint interval) if (_eglGetSurfaceHandle(surf) == EGL_NO_SURFACE) RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE); - ret = drv->API.SwapInterval(drv, disp, surf, interval); + if (surf->Type != EGL_WINDOW_BIT) + RETURN_EGL_EVAL(disp, EGL_TRUE); + + interval = CLAMP(interval, + surf->Config->MinSwapInterval, + surf->Config->MaxSwapInterval); + + if (surf->SwapInterval != interval) { + if (drv->SwapInterval) + ret = drv->SwapInterval(drv, disp, surf, interval); + else + ret = _eglSwapInterval(drv, disp, surf, interval); + } + else { + ret = EGL_TRUE; + } + + if (ret) + surf->SwapInterval = interval; RETURN_EGL_EVAL(disp, ret); } @@ -1198,7 +1310,7 @@ eglSwapBuffers(EGLDisplay dpy, EGLSurface surface) _EGLContext *ctx = _eglGetCurrentContext(); _EGLDisplay *disp = _eglLockDisplay(dpy); _EGLSurface *surf = _eglLookupSurface(surface, disp); - _EGLDriver *drv; + const _EGLDriver *drv; EGLBoolean ret; _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE); @@ -1211,7 +1323,28 @@ eglSwapBuffers(EGLDisplay dpy, EGLSurface surface) RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE); #endif - ret = drv->API.SwapBuffers(drv, disp, surf); + if (surf->Type != EGL_WINDOW_BIT) + RETURN_EGL_EVAL(disp, EGL_TRUE); + + /* From the EGL 1.5 spec: + * + * If eglSwapBuffers is called and the native window associated with + * surface is no longer valid, an EGL_BAD_NATIVE_WINDOW error is + * generated. + */ + if (surf->Lost) + RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_WINDOW, EGL_FALSE); + + ret = drv->SwapBuffers(drv, disp, surf); + + /* EGL_KHR_partial_update + * Frame boundary successfully reached, + * reset damage region and reset BufferAgeRead + */ + if (ret) { + surf->SetDamageRegionCalled = EGL_FALSE; + surf->BufferAgeRead = EGL_FALSE; + } RETURN_EGL_EVAL(disp, ret); } @@ -1219,10 +1352,10 @@ eglSwapBuffers(EGLDisplay dpy, EGLSurface surface) static EGLBoolean _eglSwapBuffersWithDamageCommon(_EGLDisplay *disp, _EGLSurface *surf, - EGLint *rects, EGLint n_rects) + const EGLint *rects, EGLint n_rects) { _EGLContext *ctx = _eglGetCurrentContext(); - _EGLDriver *drv; + const _EGLDriver *drv; EGLBoolean ret; _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv); @@ -1232,17 +1365,29 @@ _eglSwapBuffersWithDamageCommon(_EGLDisplay *disp, _EGLSurface *surf, surf != ctx->DrawSurface) RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE); + if (surf->Type != EGL_WINDOW_BIT) + RETURN_EGL_EVAL(disp, EGL_TRUE); + if ((n_rects > 0 && rects == NULL) || n_rects < 0) RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE); - ret = drv->API.SwapBuffersWithDamageEXT(drv, disp, surf, rects, n_rects); + ret = drv->SwapBuffersWithDamageEXT(drv, disp, surf, rects, n_rects); + + /* EGL_KHR_partial_update + * Frame boundary successfully reached, + * reset damage region and reset BufferAgeRead + */ + if (ret) { + surf->SetDamageRegionCalled = EGL_FALSE; + surf->BufferAgeRead = EGL_FALSE; + } RETURN_EGL_EVAL(disp, ret); } static EGLBoolean EGLAPIENTRY eglSwapBuffersWithDamageEXT(EGLDisplay dpy, EGLSurface surface, - EGLint *rects, EGLint n_rects) + const EGLint *rects, EGLint n_rects) { _EGLDisplay *disp = _eglLockDisplay(dpy); _EGLSurface *surf = _eglLookupSurface(surface, disp); @@ -1252,7 +1397,7 @@ eglSwapBuffersWithDamageEXT(EGLDisplay dpy, EGLSurface surface, static EGLBoolean EGLAPIENTRY eglSwapBuffersWithDamageKHR(EGLDisplay dpy, EGLSurface surface, - EGLint *rects, EGLint n_rects) + const EGLint *rects, EGLint n_rects) { _EGLDisplay *disp = _eglLockDisplay(dpy); _EGLSurface *surf = _eglLookupSurface(surface, disp); @@ -1260,12 +1405,73 @@ eglSwapBuffersWithDamageKHR(EGLDisplay dpy, EGLSurface surface, return _eglSwapBuffersWithDamageCommon(disp, surf, rects, n_rects); } +/** + * Clamp the rectangles so that they lie within the surface. + */ + +static void +_eglSetDamageRegionKHRClampRects(_EGLDisplay* disp, _EGLSurface* surf, + EGLint *rects, EGLint n_rects) +{ + EGLint i; + EGLint surf_height = surf->Height; + EGLint surf_width = surf->Width; + + for (i = 0; i < (4 * n_rects); i += 4) { + EGLint x1, y1, x2, y2; + x1 = rects[i]; + y1 = rects[i + 1]; + x2 = rects[i + 2] + x1; + y2 = rects[i + 3] + y1; + + rects[i] = CLAMP(x1, 0, surf_width); + rects[i + 1] = CLAMP(y1, 0, surf_height); + rects[i + 2] = CLAMP(x2, 0, surf_width) - rects[i]; + rects[i + 3] = CLAMP(y2, 0, surf_height) - rects[i + 1]; + } +} + +static EGLBoolean EGLAPIENTRY +eglSetDamageRegionKHR(EGLDisplay dpy, EGLSurface surface, + EGLint *rects, EGLint n_rects) +{ + _EGLDisplay *disp = _eglLockDisplay(dpy); + _EGLSurface *surf = _eglLookupSurface(surface, disp); + _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE); + _EGLContext *ctx = _eglGetCurrentContext(); + const _EGLDriver *drv; + EGLBoolean ret; + _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv); + + if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT || + surf->Type != EGL_WINDOW_BIT || + ctx->DrawSurface != surf || + surf->SwapBehavior != EGL_BUFFER_DESTROYED) + RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_FALSE); + + /* If the damage region is already set or + * buffer age is not queried between + * frame boundaries, throw bad access error + */ + + if (surf->SetDamageRegionCalled || !surf->BufferAgeRead) + RETURN_EGL_ERROR(disp, EGL_BAD_ACCESS, EGL_FALSE); + + _eglSetDamageRegionKHRClampRects(disp, surf, rects, n_rects); + ret = drv->SetDamageRegion(drv, disp, surf, rects, n_rects); + + if (ret) + surf->SetDamageRegionCalled = EGL_TRUE; + + RETURN_EGL_EVAL(disp, ret); +} + EGLBoolean EGLAPIENTRY eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target) { _EGLDisplay *disp = _eglLockDisplay(dpy); _EGLSurface *surf = _eglLookupSurface(surface, disp); - _EGLDriver *drv; + const _EGLDriver *drv; EGLBoolean ret; void *native_pixmap_ptr; @@ -1274,9 +1480,7 @@ eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target) native_pixmap_ptr = (void*) target; _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv); - if (disp->Platform != _eglGetNativePlatform(disp->PlatformDisplay)) - RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_PIXMAP, EGL_FALSE); - ret = drv->API.CopyBuffers(drv, disp, surf, native_pixmap_ptr); + ret = drv->CopyBuffers(drv, disp, surf, native_pixmap_ptr); RETURN_EGL_EVAL(disp, ret); } @@ -1287,7 +1491,7 @@ _eglWaitClientCommon(void) { _EGLContext *ctx = _eglGetCurrentContext(); _EGLDisplay *disp; - _EGLDriver *drv; + const _EGLDriver *drv; EGLBoolean ret; if (!ctx) @@ -1304,7 +1508,7 @@ _eglWaitClientCommon(void) /* a valid current context implies an initialized current display */ assert(disp->Initialized); drv = disp->Driver; - ret = drv->API.WaitClient(drv, disp, ctx); + ret = drv->WaitClient(drv, disp, ctx); RETURN_EGL_EVAL(disp, ret); } @@ -1330,7 +1534,7 @@ eglWaitNative(EGLint engine) { _EGLContext *ctx = _eglGetCurrentContext(); _EGLDisplay *disp; - _EGLDriver *drv; + const _EGLDriver *drv; EGLBoolean ret; if (!ctx) @@ -1349,7 +1553,7 @@ eglWaitNative(EGLint engine) /* a valid current context implies an initialized current display */ assert(disp->Initialized); drv = disp->Driver; - ret = drv->API.WaitNative(drv, disp, engine); + ret = drv->WaitNative(drv, disp, engine); RETURN_EGL_EVAL(disp, ret); } @@ -1480,19 +1684,14 @@ eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, { _EGLDisplay *disp = _eglLockDisplay(dpy); _EGLConfig *conf = _eglLookupConfig(config, disp); - _EGLDriver *drv; - _EGLSurface *surf; - EGLSurface ret; + const _EGLDriver *drv; _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE); _EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE, drv); - surf = drv->API.CreatePbufferFromClientBuffer(drv, disp, buftype, buffer, - conf, attrib_list); - ret = (surf) ? _eglLinkSurface(surf) : EGL_NO_SURFACE; - - RETURN_EGL_EVAL(disp, ret); + /* OpenVG is not supported */ + RETURN_EGL_ERROR(disp, EGL_BAD_ALLOC, EGL_NO_SURFACE); } @@ -1508,11 +1707,11 @@ eglReleaseThread(void) if (ctx) { _EGLDisplay *disp = ctx->Resource.Display; - _EGLDriver *drv; + const _EGLDriver *drv; mtx_lock(&disp->Mutex); drv = disp->Driver; - (void) drv->API.MakeCurrent(drv, disp, NULL, NULL, NULL); + (void) drv->MakeCurrent(drv, disp, NULL, NULL, NULL); mtx_unlock(&disp->Mutex); } } @@ -1525,10 +1724,10 @@ eglReleaseThread(void) static EGLImage _eglCreateImageCommon(_EGLDisplay *disp, EGLContext ctx, EGLenum target, - EGLClientBuffer buffer, const EGLint *attr_list) + EGLClientBuffer buffer, const EGLint *attr_list) { _EGLContext *context = _eglLookupContext(ctx, disp); - _EGLDriver *drv; + const _EGLDriver *drv; _EGLImage *img; EGLImage ret; @@ -1543,8 +1742,8 @@ _eglCreateImageCommon(_EGLDisplay *disp, EGLContext ctx, EGLenum target, if (ctx != EGL_NO_CONTEXT && target == EGL_LINUX_DMA_BUF_EXT) RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR); - img = drv->API.CreateImageKHR(drv, - disp, context, target, buffer, attr_list); + img = drv->CreateImageKHR(drv, disp, context, target, + buffer, attr_list); ret = (img) ? _eglLinkImage(img) : EGL_NO_IMAGE_KHR; RETURN_EGL_EVAL(disp, ret); @@ -1583,7 +1782,7 @@ eglCreateImage(EGLDisplay dpy, EGLContext ctx, EGLenum target, static EGLBoolean _eglDestroyImageCommon(_EGLDisplay *disp, _EGLImage *img) { - _EGLDriver *drv; + const _EGLDriver *drv; EGLBoolean ret; _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv); @@ -1593,7 +1792,7 @@ _eglDestroyImageCommon(_EGLDisplay *disp, _EGLImage *img) RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE); _eglUnlinkImage(img); - ret = drv->API.DestroyImageKHR(drv, disp, img); + ret = drv->DestroyImageKHR(drv, disp, img); RETURN_EGL_EVAL(disp, ret); } @@ -1623,7 +1822,7 @@ _eglCreateSync(_EGLDisplay *disp, EGLenum type, const EGLAttrib *attrib_list, EGLenum invalid_type_error) { _EGLContext *ctx = _eglGetCurrentContext(); - _EGLDriver *drv; + const _EGLDriver *drv; _EGLSync *sync; EGLSync ret; @@ -1650,9 +1849,10 @@ _eglCreateSync(_EGLDisplay *disp, EGLenum type, const EGLAttrib *attrib_list, (type == EGL_SYNC_FENCE_KHR || type == EGL_SYNC_NATIVE_FENCE_ANDROID)) RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_NO_SYNC_KHR); - /* return an error if the client API doesn't support GL_OES_EGL_sync */ + /* return an error if the client API doesn't support GL_[OES|MESA]_EGL_sync. */ if (ctx && (ctx->Resource.Display != disp || - ctx->ClientAPI != EGL_OPENGL_ES_API)) + (ctx->ClientAPI != EGL_OPENGL_ES_API && + ctx->ClientAPI != EGL_OPENGL_API))) RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_NO_SYNC_KHR); switch (type) { @@ -1676,7 +1876,7 @@ _eglCreateSync(_EGLDisplay *disp, EGLenum type, const EGLAttrib *attrib_list, RETURN_EGL_ERROR(disp, invalid_type_error, EGL_NO_SYNC_KHR); } - sync = drv->API.CreateSyncKHR(drv, disp, type, attrib_list); + sync = drv->CreateSyncKHR(drv, disp, type, attrib_list); ret = (sync) ? _eglLinkSync(sync) : EGL_NO_SYNC_KHR; RETURN_EGL_EVAL(disp, ret); @@ -1735,7 +1935,7 @@ eglCreateSync(EGLDisplay dpy, EGLenum type, const EGLAttrib *attrib_list) static EGLBoolean _eglDestroySync(_EGLDisplay *disp, _EGLSync *s) { - _EGLDriver *drv; + const _EGLDriver *drv; EGLBoolean ret; _EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv); @@ -1744,7 +1944,7 @@ _eglDestroySync(_EGLDisplay *disp, _EGLSync *s) disp->Extensions.ANDROID_native_fence_sync); _eglUnlinkSync(s); - ret = drv->API.DestroySyncKHR(drv, disp, s); + ret = drv->DestroySyncKHR(drv, disp, s); RETURN_EGL_EVAL(disp, ret); } @@ -1772,7 +1972,7 @@ static EGLint _eglClientWaitSyncCommon(_EGLDisplay *disp, EGLDisplay dpy, _EGLSync *s, EGLint flags, EGLTime timeout) { - _EGLDriver *drv; + const _EGLDriver *drv; EGLint ret; _EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv); @@ -1791,7 +1991,7 @@ _eglClientWaitSyncCommon(_EGLDisplay *disp, EGLDisplay dpy, if (s->Type == EGL_SYNC_REUSABLE_KHR) _eglUnlockDisplay(dpy); - ret = drv->API.ClientWaitSyncKHR(drv, disp, s, flags, timeout); + ret = drv->ClientWaitSyncKHR(drv, disp, s, flags, timeout); /* * 'disp' is already unlocked for reusable sync type, @@ -1828,21 +2028,23 @@ static EGLint _eglWaitSyncCommon(_EGLDisplay *disp, _EGLSync *s, EGLint flags) { _EGLContext *ctx = _eglGetCurrentContext(); - _EGLDriver *drv; + const _EGLDriver *drv; EGLint ret; _EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv); assert(disp->Extensions.KHR_wait_sync); - /* return an error if the client API doesn't support GL_OES_EGL_sync */ - if (ctx == EGL_NO_CONTEXT || ctx->ClientAPI != EGL_OPENGL_ES_API) + /* return an error if the client API doesn't support GL_[OES|MESA]_EGL_sync. */ + if (ctx == EGL_NO_CONTEXT || + (ctx->ClientAPI != EGL_OPENGL_ES_API && + ctx->ClientAPI != EGL_OPENGL_API)) RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_FALSE); /* the API doesn't allow any flags yet */ if (flags != 0) RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE); - ret = drv->API.WaitSyncKHR(drv, disp, s); + ret = drv->WaitSyncKHR(drv, disp, s); RETURN_EGL_EVAL(disp, ret); } @@ -1876,14 +2078,14 @@ eglSignalSyncKHR(EGLDisplay dpy, EGLSync sync, EGLenum mode) { _EGLDisplay *disp = _eglLockDisplay(dpy); _EGLSync *s = _eglLookupSync(sync, disp); - _EGLDriver *drv; + const _EGLDriver *drv; EGLBoolean ret; _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE); _EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv); assert(disp->Extensions.KHR_reusable_sync); - ret = drv->API.SignalSyncKHR(drv, disp, s, mode); + ret = drv->SignalSyncKHR(drv, disp, s, mode); RETURN_EGL_EVAL(disp, ret); } @@ -1892,14 +2094,15 @@ eglSignalSyncKHR(EGLDisplay dpy, EGLSync sync, EGLenum mode) static EGLBoolean _eglGetSyncAttribCommon(_EGLDisplay *disp, _EGLSync *s, EGLint attribute, EGLAttrib *value) { - _EGLDriver *drv; + const _EGLDriver *drv; EGLBoolean ret; _EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv); assert(disp->Extensions.KHR_reusable_sync || disp->Extensions.KHR_fence_sync || disp->Extensions.ANDROID_native_fence_sync); - ret = drv->API.GetSyncAttrib(drv, disp, s, attribute, value); + + ret = _eglGetSyncAttrib(drv, disp, s, attribute, value); RETURN_EGL_EVAL(disp, ret); } @@ -1910,6 +2113,10 @@ eglGetSyncAttrib(EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLAttrib *valu _EGLDisplay *disp = _eglLockDisplay(dpy); _EGLSync *s = _eglLookupSync(sync, disp); _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE); + + if (!value) + RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE); + return _eglGetSyncAttribCommon(disp, s, attribute, value); } @@ -1946,7 +2153,7 @@ eglDupNativeFenceFDANDROID(EGLDisplay dpy, EGLSync sync) { _EGLDisplay *disp = _eglLockDisplay(dpy); _EGLSync *s = _eglLookupSync(sync, disp); - _EGLDriver *drv; + const _EGLDriver *drv; EGLBoolean ret; _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE); @@ -1960,19 +2167,19 @@ eglDupNativeFenceFDANDROID(EGLDisplay dpy, EGLSync sync) _EGL_CHECK_SYNC(disp, s, EGL_NO_NATIVE_FENCE_FD_ANDROID, drv); assert(disp->Extensions.ANDROID_native_fence_sync); - ret = drv->API.DupNativeFenceFDANDROID(drv, disp, s); + ret = drv->DupNativeFenceFDANDROID(drv, disp, s); RETURN_EGL_EVAL(disp, ret); } static EGLBoolean EGLAPIENTRY eglSwapBuffersRegionNOK(EGLDisplay dpy, EGLSurface surface, - EGLint numRects, const EGLint *rects) + EGLint numRects, const EGLint *rects) { _EGLContext *ctx = _eglGetCurrentContext(); _EGLDisplay *disp = _eglLockDisplay(dpy); _EGLSurface *surf = _eglLookupSurface(surface, disp); - _EGLDriver *drv; + const _EGLDriver *drv; EGLBoolean ret; _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE); @@ -1987,7 +2194,7 @@ eglSwapBuffersRegionNOK(EGLDisplay dpy, EGLSurface surface, surf != ctx->DrawSurface) RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE); - ret = drv->API.SwapBuffersRegionNOK(drv, disp, surf, numRects, rects); + ret = drv->SwapBuffersRegionNOK(drv, disp, surf, numRects, rects); RETURN_EGL_EVAL(disp, ret); } @@ -1997,7 +2204,7 @@ static EGLImage EGLAPIENTRY eglCreateDRMImageMESA(EGLDisplay dpy, const EGLint *attr_list) { _EGLDisplay *disp = _eglLockDisplay(dpy); - _EGLDriver *drv; + const _EGLDriver *drv; _EGLImage *img; EGLImage ret; @@ -2007,7 +2214,7 @@ eglCreateDRMImageMESA(EGLDisplay dpy, const EGLint *attr_list) if (!disp->Extensions.MESA_drm_image) RETURN_EGL_EVAL(disp, EGL_NO_IMAGE_KHR); - img = drv->API.CreateDRMImageMESA(drv, disp, attr_list); + img = drv->CreateDRMImageMESA(drv, disp, attr_list); ret = (img) ? _eglLinkImage(img) : EGL_NO_IMAGE_KHR; RETURN_EGL_EVAL(disp, ret); @@ -2015,11 +2222,11 @@ eglCreateDRMImageMESA(EGLDisplay dpy, const EGLint *attr_list) static EGLBoolean EGLAPIENTRY eglExportDRMImageMESA(EGLDisplay dpy, EGLImage image, - EGLint *name, EGLint *handle, EGLint *stride) + EGLint *name, EGLint *handle, EGLint *stride) { _EGLDisplay *disp = _eglLockDisplay(dpy); _EGLImage *img = _eglLookupImage(image, disp); - _EGLDriver *drv; + const _EGLDriver *drv; EGLBoolean ret; _EGL_FUNC_START(disp, EGL_OBJECT_IMAGE_KHR, img, EGL_FALSE); @@ -2030,7 +2237,7 @@ eglExportDRMImageMESA(EGLDisplay dpy, EGLImage image, if (!img) RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE); - ret = drv->API.ExportDRMImageMESA(drv, disp, img, name, handle, stride); + ret = drv->ExportDRMImageMESA(drv, disp, img, name, handle, stride); RETURN_EGL_EVAL(disp, ret); } @@ -2042,7 +2249,7 @@ static EGLBoolean EGLAPIENTRY eglBindWaylandDisplayWL(EGLDisplay dpy, struct wl_display *display) { _EGLDisplay *disp = _eglLockDisplay(dpy); - _EGLDriver *drv; + const _EGLDriver *drv; EGLBoolean ret; _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE); @@ -2053,7 +2260,7 @@ eglBindWaylandDisplayWL(EGLDisplay dpy, struct wl_display *display) if (!display) RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE); - ret = drv->API.BindWaylandDisplayWL(drv, disp, display); + ret = drv->BindWaylandDisplayWL(drv, disp, display); RETURN_EGL_EVAL(disp, ret); } @@ -2062,7 +2269,7 @@ static EGLBoolean EGLAPIENTRY eglUnbindWaylandDisplayWL(EGLDisplay dpy, struct wl_display *display) { _EGLDisplay *disp = _eglLockDisplay(dpy); - _EGLDriver *drv; + const _EGLDriver *drv; EGLBoolean ret; _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE); @@ -2073,7 +2280,7 @@ eglUnbindWaylandDisplayWL(EGLDisplay dpy, struct wl_display *display) if (!display) RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE); - ret = drv->API.UnbindWaylandDisplayWL(drv, disp, display); + ret = drv->UnbindWaylandDisplayWL(drv, disp, display); RETURN_EGL_EVAL(disp, ret); } @@ -2083,7 +2290,7 @@ eglQueryWaylandBufferWL(EGLDisplay dpy, struct wl_resource *buffer, EGLint attribute, EGLint *value) { _EGLDisplay *disp = _eglLockDisplay(dpy); - _EGLDriver *drv; + const _EGLDriver *drv; EGLBoolean ret; _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE); @@ -2094,7 +2301,7 @@ eglQueryWaylandBufferWL(EGLDisplay dpy, struct wl_resource *buffer, if (!buffer) RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE); - ret = drv->API.QueryWaylandBufferWL(drv, disp, buffer, attribute, value); + ret = drv->QueryWaylandBufferWL(drv, disp, buffer, attribute, value); RETURN_EGL_EVAL(disp, ret); } @@ -2105,20 +2312,21 @@ eglCreateWaylandBufferFromImageWL(EGLDisplay dpy, EGLImage image) { _EGLDisplay *disp = _eglLockDisplay(dpy); _EGLImage *img; - _EGLDriver *drv; + const _EGLDriver *drv; struct wl_buffer *ret; _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE); _EGL_CHECK_DISPLAY(disp, NULL, drv); - assert(disp->Extensions.WL_create_wayland_buffer_from_image); + if (!disp->Extensions.WL_create_wayland_buffer_from_image) + RETURN_EGL_EVAL(disp, NULL); img = _eglLookupImage(image, disp); if (!img) RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, NULL); - ret = drv->API.CreateWaylandBufferFromImageWL(drv, disp, img); + ret = drv->CreateWaylandBufferFromImageWL(drv, disp, img); RETURN_EGL_EVAL(disp, ret); } @@ -2129,7 +2337,7 @@ eglPostSubBufferNV(EGLDisplay dpy, EGLSurface surface, { _EGLDisplay *disp = _eglLockDisplay(dpy); _EGLSurface *surf = _eglLookupSurface(surface, disp); - _EGLDriver *drv; + const _EGLDriver *drv; EGLBoolean ret; _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE); @@ -2139,19 +2347,19 @@ eglPostSubBufferNV(EGLDisplay dpy, EGLSurface surface, if (!disp->Extensions.NV_post_sub_buffer) RETURN_EGL_EVAL(disp, EGL_FALSE); - ret = drv->API.PostSubBufferNV(drv, disp, surf, x, y, width, height); + ret = drv->PostSubBufferNV(drv, disp, surf, x, y, width, height); RETURN_EGL_EVAL(disp, ret); } static EGLBoolean EGLAPIENTRY -eglGetSyncValuesCHROMIUM(EGLDisplay display, EGLSurface surface, +eglGetSyncValuesCHROMIUM(EGLDisplay dpy, EGLSurface surface, EGLuint64KHR *ust, EGLuint64KHR *msc, EGLuint64KHR *sbc) { - _EGLDisplay *disp = _eglLockDisplay(display); + _EGLDisplay *disp = _eglLockDisplay(dpy); _EGLSurface *surf = _eglLookupSurface(surface, disp); - _EGLDriver *drv; + const _EGLDriver *drv; EGLBoolean ret; _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE); @@ -2163,7 +2371,7 @@ eglGetSyncValuesCHROMIUM(EGLDisplay display, EGLSurface surface, if (!ust || !msc || !sbc) RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE); - ret = drv->API.GetSyncValuesCHROMIUM(disp, surf, ust, msc, sbc); + ret = drv->GetSyncValuesCHROMIUM(disp, surf, ust, msc, sbc); RETURN_EGL_EVAL(disp, ret); } @@ -2175,7 +2383,7 @@ eglExportDMABUFImageQueryMESA(EGLDisplay dpy, EGLImage image, { _EGLDisplay *disp = _eglLockDisplay(dpy); _EGLImage *img = _eglLookupImage(image, disp); - _EGLDriver *drv; + const _EGLDriver *drv; EGLBoolean ret; _EGL_FUNC_START(disp, EGL_OBJECT_IMAGE_KHR, img, EGL_FALSE); @@ -2186,7 +2394,7 @@ eglExportDMABUFImageQueryMESA(EGLDisplay dpy, EGLImage image, if (!img) RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE); - ret = drv->API.ExportDMABUFImageQueryMESA(drv, disp, img, fourcc, nplanes, + ret = drv->ExportDMABUFImageQueryMESA(drv, disp, img, fourcc, nplanes, modifiers); RETURN_EGL_EVAL(disp, ret); @@ -2198,7 +2406,7 @@ eglExportDMABUFImageMESA(EGLDisplay dpy, EGLImage image, { _EGLDisplay *disp = _eglLockDisplay(dpy); _EGLImage *img = _eglLookupImage(image, disp); - _EGLDriver *drv; + const _EGLDriver *drv; EGLBoolean ret; _EGL_FUNC_START(disp, EGL_OBJECT_IMAGE_KHR, img, EGL_FALSE); @@ -2209,14 +2417,14 @@ eglExportDMABUFImageMESA(EGLDisplay dpy, EGLImage image, if (!img) RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE); - ret = drv->API.ExportDMABUFImageMESA(drv, disp, img, fds, strides, offsets); + ret = drv->ExportDMABUFImageMESA(drv, disp, img, fds, strides, offsets); RETURN_EGL_EVAL(disp, ret); } static EGLint EGLAPIENTRY eglLabelObjectKHR(EGLDisplay dpy, EGLenum objectType, EGLObjectKHR object, - EGLLabelKHR label) + EGLLabelKHR label) { _EGLDisplay *disp = NULL; _EGLResourceType type; @@ -2274,16 +2482,9 @@ eglLabelObjectKHR(EGLDisplay dpy, EGLenum objectType, EGLObjectKHR object, RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_BAD_PARAMETER); } -static EGLBoolean -_validDebugMessageLevel(EGLAttrib level) -{ - return (level >= EGL_DEBUG_MSG_CRITICAL_KHR && - level <= EGL_DEBUG_MSG_INFO_KHR); -} - static EGLint EGLAPIENTRY eglDebugMessageControlKHR(EGLDEBUGPROCKHR callback, - const EGLAttrib *attrib_list) + const EGLAttrib *attrib_list) { unsigned int newEnabled; @@ -2296,20 +2497,24 @@ eglDebugMessageControlKHR(EGLDEBUGPROCKHR callback, int i; for (i = 0; attrib_list[i] != EGL_NONE; i += 2) { - if (_validDebugMessageLevel(attrib_list[i])) { + switch (attrib_list[i]) { + case EGL_DEBUG_MSG_CRITICAL_KHR: + case EGL_DEBUG_MSG_ERROR_KHR: + case EGL_DEBUG_MSG_WARN_KHR: + case EGL_DEBUG_MSG_INFO_KHR: if (attrib_list[i + 1]) newEnabled |= DebugBitFromType(attrib_list[i]); else newEnabled &= ~DebugBitFromType(attrib_list[i]); - continue; + break; + default: + // On error, set the last error code, call the current + // debug callback, and return the error code. + mtx_unlock(_eglGlobal.Mutex); + _eglReportError(EGL_BAD_ATTRIBUTE, NULL, + "Invalid attribute 0x%04lx", (unsigned long) attrib_list[i]); + return EGL_BAD_ATTRIBUTE; } - - // On error, set the last error code, call the current - // debug callback, and return the error code. - mtx_unlock(_eglGlobal.Mutex); - _eglReportError(EGL_BAD_ATTRIBUTE, NULL, - "Invalid attribute 0x%04lx", (unsigned long) attrib_list[i]); - return EGL_BAD_ATTRIBUTE; } } @@ -2332,25 +2537,25 @@ eglQueryDebugKHR(EGLint attribute, EGLAttrib *value) mtx_lock(_eglGlobal.Mutex); - do { - if (_validDebugMessageLevel(attribute)) { - if (_eglGlobal.debugTypesEnabled & DebugBitFromType(attribute)) - *value = EGL_TRUE; - else - *value = EGL_FALSE; - break; - } - - if (attribute == EGL_DEBUG_CALLBACK_KHR) { - *value = (EGLAttrib) _eglGlobal.debugCallback; - break; - } - + switch (attribute) { + case EGL_DEBUG_MSG_CRITICAL_KHR: + case EGL_DEBUG_MSG_ERROR_KHR: + case EGL_DEBUG_MSG_WARN_KHR: + case EGL_DEBUG_MSG_INFO_KHR: + if (_eglGlobal.debugTypesEnabled & DebugBitFromType(attribute)) + *value = EGL_TRUE; + else + *value = EGL_FALSE; + break; + case EGL_DEBUG_CALLBACK_KHR: + *value = (EGLAttrib) _eglGlobal.debugCallback; + break; + default: mtx_unlock(_eglGlobal.Mutex); _eglReportError(EGL_BAD_ATTRIBUTE, NULL, - "Invalid attribute 0x%04lx", (unsigned long) attribute); + "Invalid attribute 0x%04lx", (unsigned long) attribute); return EGL_FALSE; - } while (0); + } mtx_unlock(_eglGlobal.Mutex); return EGL_TRUE; @@ -2364,6 +2569,182 @@ _eglFunctionCompare(const void *key, const void *elem) return strcmp(procname, entrypoint->name); } +static EGLBoolean EGLAPIENTRY +eglQueryDmaBufFormatsEXT(EGLDisplay dpy, EGLint max_formats, + EGLint *formats, EGLint *num_formats) +{ + _EGLDisplay *disp = _eglLockDisplay(dpy); + const _EGLDriver *drv; + EGLBoolean ret; + + _EGL_FUNC_START(NULL, EGL_NONE, NULL, EGL_FALSE); + + _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv); + + ret = drv->QueryDmaBufFormatsEXT(drv, disp, max_formats, formats, + num_formats); + + RETURN_EGL_EVAL(disp, ret); +} + +static EGLBoolean EGLAPIENTRY +eglQueryDmaBufModifiersEXT(EGLDisplay dpy, EGLint format, EGLint max_modifiers, + EGLuint64KHR *modifiers, EGLBoolean *external_only, + EGLint *num_modifiers) +{ + _EGLDisplay *disp = _eglLockDisplay(dpy); + const _EGLDriver *drv; + EGLBoolean ret; + + _EGL_FUNC_START(NULL, EGL_NONE, NULL, EGL_FALSE); + + _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv); + + ret = drv->QueryDmaBufModifiersEXT(drv, disp, format, max_modifiers, + modifiers, external_only, + num_modifiers); + + RETURN_EGL_EVAL(disp, ret); +} + +static void EGLAPIENTRY +eglSetBlobCacheFuncsANDROID(EGLDisplay *dpy, EGLSetBlobFuncANDROID set, + EGLGetBlobFuncANDROID get) +{ + /* This function does not return anything so we cannot + * utilize the helper macros _EGL_FUNC_START or _EGL_CHECK_DISPLAY. + */ + _EGLDisplay *disp = _eglLockDisplay(dpy); + if (!_eglSetFuncName(__func__, disp, EGL_OBJECT_DISPLAY_KHR, NULL)) { + if (disp) + _eglUnlockDisplay(disp); + return; + } + + const _EGLDriver *drv = _eglCheckDisplay(disp, __func__); + if (!drv) { + if (disp) + _eglUnlockDisplay(disp); + return; + } + + if (!set || !get) { + _eglError(EGL_BAD_PARAMETER, + "eglSetBlobCacheFuncsANDROID: NULL handler given"); + _eglUnlockDisplay(disp); + return; + } + + if (disp->BlobCacheSet) { + _eglError(EGL_BAD_PARAMETER, + "eglSetBlobCacheFuncsANDROID: functions already set"); + _eglUnlockDisplay(disp); + return; + } + + disp->BlobCacheSet = set; + disp->BlobCacheGet = get; + + drv->SetBlobCacheFuncsANDROID(drv, disp, set, get); + + _eglUnlockDisplay(disp); +} + +static EGLBoolean EGLAPIENTRY +eglQueryDeviceAttribEXT(EGLDeviceEXT device, + EGLint attribute, + EGLAttrib *value) +{ + _EGLDevice *dev = _eglLookupDevice(device); + EGLBoolean ret; + + _EGL_FUNC_START(NULL, EGL_NONE, NULL, EGL_FALSE); + if (!dev) + RETURN_EGL_ERROR(NULL, EGL_BAD_DEVICE_EXT, EGL_FALSE); + + ret = _eglQueryDeviceAttribEXT(dev, attribute, value); + RETURN_EGL_EVAL(NULL, ret); +} + +static const char * EGLAPIENTRY +eglQueryDeviceStringEXT(EGLDeviceEXT device, + EGLint name) +{ + _EGLDevice *dev = _eglLookupDevice(device); + + _EGL_FUNC_START(NULL, EGL_NONE, NULL, NULL); + if (!dev) + RETURN_EGL_ERROR(NULL, EGL_BAD_DEVICE_EXT, NULL); + + RETURN_EGL_EVAL(NULL, _eglQueryDeviceStringEXT(dev, name)); +} + +static EGLBoolean EGLAPIENTRY +eglQueryDevicesEXT(EGLint max_devices, + EGLDeviceEXT *devices, + EGLint *num_devices) +{ + EGLBoolean ret; + + _EGL_FUNC_START(NULL, EGL_NONE, NULL, EGL_FALSE); + ret = _eglQueryDevicesEXT(max_devices, (_EGLDevice **) devices, + num_devices); + RETURN_EGL_EVAL(NULL, ret); +} + +static EGLBoolean EGLAPIENTRY +eglQueryDisplayAttribEXT(EGLDisplay dpy, + EGLint attribute, + EGLAttrib *value) +{ + _EGLDisplay *disp = _eglLockDisplay(dpy); + const _EGLDriver *drv; + + _EGL_FUNC_START(NULL, EGL_NONE, NULL, EGL_FALSE); + _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv); + + switch (attribute) { + case EGL_DEVICE_EXT: + *value = (EGLAttrib) disp->Device; + break; + default: + RETURN_EGL_ERROR(disp, EGL_BAD_ATTRIBUTE, EGL_FALSE); + } + RETURN_EGL_SUCCESS(disp, EGL_TRUE); +} + +static char * EGLAPIENTRY +eglGetDisplayDriverConfig(EGLDisplay dpy) +{ + _EGLDisplay *disp = _eglLockDisplay(dpy); + const _EGLDriver *drv; + char *ret; + + _EGL_FUNC_START(disp, EGL_NONE, NULL, NULL); + _EGL_CHECK_DISPLAY(disp, NULL, drv); + + assert(disp->Extensions.MESA_query_driver); + + ret = drv->QueryDriverConfig(disp); + RETURN_EGL_EVAL(disp, ret); +} + +static const char * EGLAPIENTRY +eglGetDisplayDriverName(EGLDisplay dpy) +{ + _EGLDisplay *disp = _eglLockDisplay(dpy); + const _EGLDriver *drv; + const char *ret; + + _EGL_FUNC_START(disp, EGL_NONE, NULL, NULL); + _EGL_CHECK_DISPLAY(disp, NULL, drv); + + assert(disp->Extensions.MESA_query_driver); + + ret = drv->QueryDriverName(disp); + RETURN_EGL_EVAL(disp, ret); +} + __eglMustCastToProperFunctionPointerType EGLAPIENTRY eglGetProcAddress(const char *procname) { @@ -2397,7 +2778,7 @@ eglGetProcAddress(const char *procname) static int _eglLockDisplayInterop(EGLDisplay dpy, EGLContext context, - _EGLDisplay **disp, _EGLDriver **drv, + _EGLDisplay **disp, const _EGLDriver **drv, _EGLContext **ctx) { @@ -2426,7 +2807,7 @@ MesaGLInteropEGLQueryDeviceInfo(EGLDisplay dpy, EGLContext context, struct mesa_glinterop_device_info *out) { _EGLDisplay *disp; - _EGLDriver *drv; + const _EGLDriver *drv; _EGLContext *ctx; int ret; @@ -2434,8 +2815,8 @@ MesaGLInteropEGLQueryDeviceInfo(EGLDisplay dpy, EGLContext context, if (ret != MESA_GLINTEROP_SUCCESS) return ret; - if (drv->API.GLInteropQueryDeviceInfo) - ret = drv->API.GLInteropQueryDeviceInfo(disp, ctx, out); + if (drv->GLInteropQueryDeviceInfo) + ret = drv->GLInteropQueryDeviceInfo(disp, ctx, out); else ret = MESA_GLINTEROP_UNSUPPORTED; @@ -2449,7 +2830,7 @@ MesaGLInteropEGLExportObject(EGLDisplay dpy, EGLContext context, struct mesa_glinterop_export_out *out) { _EGLDisplay *disp; - _EGLDriver *drv; + const _EGLDriver *drv; _EGLContext *ctx; int ret; @@ -2457,8 +2838,8 @@ MesaGLInteropEGLExportObject(EGLDisplay dpy, EGLContext context, if (ret != MESA_GLINTEROP_SUCCESS) return ret; - if (drv->API.GLInteropExportObject) - ret = drv->API.GLInteropExportObject(disp, ctx, in, out); + if (drv->GLInteropExportObject) + ret = drv->GLInteropExportObject(disp, ctx, in, out); else ret = MESA_GLINTEROP_UNSUPPORTED;