#include <string.h>
#include "c99_compat.h"
#include "c11/threads.h"
-#include "eglcompiler.h"
+#include "util/macros.h"
#include "eglglobals.h"
#include "eglcontext.h"
#include "eglconfig.h"
#include "eglimage.h"
#include "eglsync.h"
-#include "eglstring.h"
+#include "GL/mesa_glinterop.h"
/**
* Macros to help return an API entrypoint.
_EGL_CHECK_OBJECT(disp, Sync, s, ret, drv)
+struct _egl_entrypoint {
+ const char *name;
+ _EGLProc function;
+};
+
+
static inline _EGLDriver *
_eglCheckDisplay(_EGLDisplay *disp, const char *msg)
{
mtx_unlock(&dpy->Mutex);
}
+static EGLBoolean
+_eglSetFuncName(const char *funcName, _EGLDisplay *disp, EGLenum objectType, _EGLResource *object)
+{
+ _EGLThreadInfo *thr = _eglGetCurrentThread();
+ if (!_eglIsCurrentThreadDummy()) {
+ thr->CurrentFuncName = funcName;
+ thr->CurrentObjectLabel = NULL;
+
+ if (objectType == EGL_OBJECT_THREAD_KHR)
+ thr->CurrentObjectLabel = thr->Label;
+ else if (objectType == EGL_OBJECT_DISPLAY_KHR && disp)
+ thr->CurrentObjectLabel = disp->Label;
+ else if (object)
+ thr->CurrentObjectLabel = object->Label;
+
+ return EGL_TRUE;
+ }
+
+ _eglDebugReport(EGL_BAD_ALLOC, funcName, EGL_DEBUG_MSG_CRITICAL_KHR, NULL);
+ return EGL_FALSE;
+}
+
+#define _EGL_FUNC_START(disp, objectType, object, ret) \
+ do { \
+ if (!_eglSetFuncName(__func__, disp, objectType, (_EGLResource *) object)) { \
+ if (disp) \
+ _eglUnlockDisplay(disp); \
+ return ret; \
+ } \
+ } while(0)
+
+/**
+ * Convert an attribute list from EGLint[] to EGLAttrib[].
+ *
+ * Return an EGL error code. The output parameter out_attrib_list is modified
+ * only on success.
+ */
+static EGLint
+_eglConvertIntsToAttribs(const EGLint *int_list, EGLAttrib **out_attrib_list)
+{
+ size_t len = 0;
+ EGLAttrib *attrib_list;
+
+ if (int_list) {
+ while (int_list[2*len] != EGL_NONE)
+ ++len;
+ }
+
+ if (len == 0) {
+ *out_attrib_list = NULL;
+ return EGL_SUCCESS;
+ }
+
+ if (2*len + 1 > SIZE_MAX / sizeof(EGLAttrib))
+ return EGL_BAD_ALLOC;
+
+ attrib_list = malloc((2*len + 1) * sizeof(EGLAttrib));
+ if (!attrib_list)
+ return EGL_BAD_ALLOC;
+
+ for (size_t i = 0; i < len; ++i) {
+ attrib_list[2*i + 0] = int_list[2*i + 0];
+ attrib_list[2*i + 1] = int_list[2*i + 1];
+ }
+
+ attrib_list[2*len] = EGL_NONE;
+
+ *out_attrib_list = attrib_list;
+ return EGL_SUCCESS;
+}
+
static EGLint *
_eglConvertAttribsToInt(const EGLAttrib *attr_list)
_EGLDisplay *dpy;
void *native_display_ptr;
+ _EGL_FUNC_START(NULL, EGL_OBJECT_THREAD_KHR, NULL, EGL_NO_DISPLAY);
+
STATIC_ASSERT(sizeof(void*) == sizeof(nativeDisplay));
native_display_ptr = (void*) nativeDisplay;
return _eglGetDisplayHandle(dpy);
}
-static EGLDisplay EGLAPIENTRY
-eglGetPlatformDisplayEXT(EGLenum platform, void *native_display,
- const EGLint *attrib_list)
+static EGLDisplay
+_eglGetPlatformDisplayCommon(EGLenum platform, void *native_display,
+ const EGLint *attrib_list)
{
_EGLDisplay *dpy;
dpy = _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);
+ break;
#endif
default:
RETURN_EGL_ERROR(NULL, EGL_BAD_PARAMETER, NULL);
return _eglGetDisplayHandle(dpy);
}
+static EGLDisplay EGLAPIENTRY
+eglGetPlatformDisplayEXT(EGLenum platform, void *native_display,
+ const EGLint *attrib_list)
+{
+ _EGL_FUNC_START(NULL, EGL_OBJECT_THREAD_KHR, NULL, EGL_NO_DISPLAY);
+ return _eglGetPlatformDisplayCommon(platform, native_display, attrib_list);
+}
+
EGLDisplay EGLAPIENTRY
eglGetPlatformDisplay(EGLenum platform, void *native_display,
const EGLAttrib *attrib_list)
{
EGLDisplay display;
- EGLint *int_attribs = _eglConvertAttribsToInt(attrib_list);
+ 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 = eglGetPlatformDisplayEXT(platform, native_display, int_attribs);
+ display = _eglGetPlatformDisplayCommon(platform, native_display, int_attribs);
free(int_attribs);
return display;
}
char *exts = dpy->ExtensionsString;
- _EGL_CHECK_EXTENSION(MESA_drm_display);
- _EGL_CHECK_EXTENSION(MESA_drm_image);
- _EGL_CHECK_EXTENSION(MESA_configless_context);
+ /* Please keep these sorted alphabetically. */
+ _EGL_CHECK_EXTENSION(ANDROID_framebuffer_target);
+ _EGL_CHECK_EXTENSION(ANDROID_image_native_buffer);
+ _EGL_CHECK_EXTENSION(ANDROID_native_fence_sync);
+ _EGL_CHECK_EXTENSION(ANDROID_recordable);
- _EGL_CHECK_EXTENSION(WL_bind_wayland_display);
- _EGL_CHECK_EXTENSION(WL_create_wayland_buffer_from_image);
+ _EGL_CHECK_EXTENSION(CHROMIUM_sync_control);
- _EGL_CHECK_EXTENSION(KHR_image_base);
- _EGL_CHECK_EXTENSION(KHR_image_pixmap);
- if (dpy->Extensions.KHR_image_base && dpy->Extensions.KHR_image_pixmap)
- _eglAppendExtension(&exts, "EGL_KHR_image");
+ _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_swap_buffers_with_damage);
- _EGL_CHECK_EXTENSION(KHR_vg_parent_image);
+ _EGL_CHECK_EXTENSION(KHR_cl_event2);
+ _EGL_CHECK_EXTENSION(KHR_config_attribs);
+ _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);
+ _EGL_CHECK_EXTENSION(KHR_gl_renderbuffer_image);
_EGL_CHECK_EXTENSION(KHR_gl_texture_2D_image);
- _EGL_CHECK_EXTENSION(KHR_gl_texture_cubemap_image);
_EGL_CHECK_EXTENSION(KHR_gl_texture_3D_image);
- _EGL_CHECK_EXTENSION(KHR_gl_renderbuffer_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");
+ _EGL_CHECK_EXTENSION(KHR_image_base);
+ _EGL_CHECK_EXTENSION(KHR_image_pixmap);
+ _EGL_CHECK_EXTENSION(KHR_no_config_context);
+ _EGL_CHECK_EXTENSION(KHR_partial_update);
_EGL_CHECK_EXTENSION(KHR_reusable_sync);
- _EGL_CHECK_EXTENSION(KHR_fence_sync);
+ _EGL_CHECK_EXTENSION(KHR_surfaceless_context);
+ if (dpy->Extensions.EXT_swap_buffers_with_damage)
+ _eglAppendExtension(&exts, "EGL_KHR_swap_buffers_with_damage");
_EGL_CHECK_EXTENSION(KHR_wait_sync);
- _EGL_CHECK_EXTENSION(KHR_cl_event2);
- _EGL_CHECK_EXTENSION(KHR_surfaceless_context);
- _EGL_CHECK_EXTENSION(KHR_create_context);
+ if (dpy->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(NOK_swap_region);
_EGL_CHECK_EXTENSION(NOK_texture_from_pixmap);
- _EGL_CHECK_EXTENSION(ANDROID_image_native_buffer);
-
- _EGL_CHECK_EXTENSION(CHROMIUM_sync_control);
-
- _EGL_CHECK_EXTENSION(EXT_create_context_robustness);
- _EGL_CHECK_EXTENSION(EXT_buffer_age);
- _EGL_CHECK_EXTENSION(EXT_swap_buffers_with_damage);
- _EGL_CHECK_EXTENSION(EXT_image_dma_buf_import);
-
_EGL_CHECK_EXTENSION(NV_post_sub_buffer);
- _EGL_CHECK_EXTENSION(MESA_image_dma_buf_export);
+ _EGL_CHECK_EXTENSION(WL_bind_wayland_display);
+ _EGL_CHECK_EXTENSION(WL_create_wayland_buffer_from_image);
+
#undef _EGL_CHECK_EXTENSION
}
if (dpy->ClientAPIs & EGL_OPENGL_BIT)
strcat(dpy->ClientAPIsString, "OpenGL ");
- if (dpy->ClientAPIs & EGL_OPENGL_ES_BIT)
+ 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 (dpy->ClientAPIs & EGL_OPENGL_ES2_BIT)
- strcat(dpy->ClientAPIsString, "OpenGL_ES2 ");
-
- if (dpy->ClientAPIs & EGL_OPENGL_ES3_BIT_KHR)
- strcat(dpy->ClientAPIsString, "OpenGL_ES3 ");
+ }
if (dpy->ClientAPIs & EGL_OPENVG_BIT)
strcat(dpy->ClientAPIsString, "OpenVG ");
_eglComputeVersion(_EGLDisplay *disp)
{
disp->Version = 14;
+
+ if (disp->Extensions.KHR_fence_sync &&
+ disp->Extensions.KHR_cl_event2 &&
+ disp->Extensions.KHR_wait_sync &&
+ disp->Extensions.KHR_image_base &&
+ disp->Extensions.KHR_gl_texture_2D_image &&
+ disp->Extensions.KHR_gl_texture_3D_image &&
+ disp->Extensions.KHR_gl_texture_cubemap_image &&
+ disp->Extensions.KHR_gl_renderbuffer_image &&
+ disp->Extensions.KHR_create_context &&
+ disp->Extensions.EXT_create_context_robustness &&
+ disp->Extensions.KHR_get_all_proc_addresses &&
+ disp->Extensions.KHR_gl_colorspace &&
+ disp->Extensions.KHR_surfaceless_context)
+ disp->Version = 15;
}
/**
{
_EGLDisplay *disp = _eglLockDisplay(dpy);
+ _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE);
+
if (!disp)
RETURN_EGL_ERROR(NULL, EGL_BAD_DISPLAY, EGL_FALSE);
if (!disp->Initialized) {
- if (!_eglMatchDriver(disp, EGL_FALSE))
+ if (!_eglMatchDriver(disp))
RETURN_EGL_ERROR(disp, EGL_NOT_INITIALIZED, EGL_FALSE);
/* limit to APIs supported by core */
*/
disp->Extensions.KHR_get_all_proc_addresses = EGL_TRUE;
+ /* Extensions is used to provide EGL 1.3 functionality for 1.2 aware
+ * programs. It is driver agnostic and handled in the main EGL code.
+ */
+ disp->Extensions.KHR_config_attribs = EGL_TRUE;
+
_eglComputeVersion(disp);
_eglCreateExtensionsString(disp);
_eglCreateAPIsString(disp);
- _eglsnprintf(disp->VersionString, sizeof(disp->VersionString),
- "%d.%d (%s)", disp->Version / 10, disp->Version % 10,
- disp->Driver->Name);
+ snprintf(disp->VersionString, sizeof(disp->VersionString),
+ "%d.%d", disp->Version / 10, disp->Version % 10);
}
/* Update applications version of major and minor if not NULL */
{
_EGLDisplay *disp = _eglLockDisplay(dpy);
+ _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE);
+
if (!disp)
RETURN_EGL_ERROR(NULL, EGL_BAD_DISPLAY, EGL_FALSE);
_EGLDriver *drv;
if (dpy == EGL_NO_DISPLAY && name == EGL_EXTENSIONS) {
- RETURN_EGL_SUCCESS(NULL, _eglGlobal.ClientExtensionString);
+ const char *ret = _eglGetClientExtensionString();
+ if (ret != NULL)
+ RETURN_EGL_SUCCESS(NULL, ret);
+ else
+ RETURN_EGL_ERROR(NULL, EGL_BAD_ALLOC, NULL);
}
disp = _eglLockDisplay(dpy);
+ _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, NULL);
_EGL_CHECK_DISPLAY(disp, NULL, drv);
switch (name) {
_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);
_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);
+ config_size, num_config);
RETURN_EGL_EVAL(disp, ret);
}
_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);
_EGLContext *context;
EGLContext ret;
+ _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_CONTEXT);
+
_EGL_CHECK_DISPLAY(disp, EGL_NO_CONTEXT, drv);
- if (!config && !disp->Extensions.MESA_configless_context)
+ if (config != EGL_NO_CONFIG_KHR)
+ _EGL_CHECK_CONFIG(disp, conf, EGL_NO_CONTEXT, drv);
+ else if (!disp->Extensions.KHR_no_config_context)
RETURN_EGL_ERROR(disp, EGL_BAD_CONFIG, EGL_NO_CONTEXT);
if (!share && share_list != EGL_NO_CONTEXT)
_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);
_EGLDriver *drv;
EGLBoolean ret;
+ _EGL_FUNC_START(disp, EGL_OBJECT_CONTEXT_KHR, context, EGL_FALSE);
+
if (!disp)
RETURN_EGL_ERROR(disp, EGL_BAD_DISPLAY, EGL_FALSE);
drv = disp->Driver;
RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_FALSE);
}
+ /* 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->API.MakeCurrent(drv, disp, draw_surf, read_surf, context);
RETURN_EGL_EVAL(disp, ret);
_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);
_EGLSurface *surf;
EGLSurface ret;
- _EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE, drv);
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) {
+ /* From the EGL_MESA_platform_surfaceless spec (v1):
+ *
+ * eglCreatePlatformWindowSurface fails when called with a <display>
+ * that belongs to the surfaceless platform. It returns
+ * EGL_NO_SURFACE and generates EGL_BAD_NATIVE_WINDOW. The
+ * justification for this unconditional failure is that the
+ * surfaceless platform has no native windows, and therefore the
+ * <native_window> parameter is always invalid.
+ *
+ * This check must occur before checking the EGLConfig, which emits
+ * EGL_BAD_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,
attrib_list);
ret = (surf) ? _eglLinkSurface(surf) : EGL_NO_SURFACE;
EGLNativeWindowType window, const EGLint *attrib_list)
{
_EGLDisplay *disp = _eglLockDisplay(dpy);
+
+ _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE);
STATIC_ASSERT(sizeof(void*) == sizeof(window));
return _eglCreateWindowSurfaceCommon(disp, config, (void*) window,
attrib_list);
}
-
-static EGLSurface EGLAPIENTRY
-eglCreatePlatformWindowSurfaceEXT(EGLDisplay dpy, EGLConfig config,
- void *native_window,
- const EGLint *attrib_list)
+static void *
+_fixupNativeWindow(_EGLDisplay *disp, void *native_window)
{
- _EGLDisplay *disp = _eglLockDisplay(dpy);
-
#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
* `Window*`. Convert `Window*` to `Window` because that's what
* dri2_x11_create_window_surface() expects.
*/
- native_window = (void*) (* (Window*) native_window);
+ return (void *)(* (Window*) native_window);
}
#endif
+ return native_window;
+}
+
+static EGLSurface EGLAPIENTRY
+eglCreatePlatformWindowSurfaceEXT(EGLDisplay dpy, EGLConfig config,
+ void *native_window,
+ const EGLint *attrib_list)
+{
+ _EGLDisplay *disp = _eglLockDisplay(dpy);
+ native_window = _fixupNativeWindow(disp, native_window);
+
+ _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE);
return _eglCreateWindowSurfaceCommon(disp, config, native_window,
attrib_list);
}
void *native_window,
const EGLAttrib *attrib_list)
{
+ _EGLDisplay *disp = _eglLockDisplay(dpy);
EGLSurface surface;
- EGLint *int_attribs = _eglConvertAttribsToInt(attrib_list);
+ EGLint *int_attribs;
+ _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE);
+
+ int_attribs = _eglConvertAttribsToInt(attrib_list);
if (attrib_list && !int_attribs)
- RETURN_EGL_ERROR(NULL, EGL_BAD_ALLOC, EGL_NO_SURFACE);
+ RETURN_EGL_ERROR(disp, EGL_BAD_ALLOC, EGL_NO_SURFACE);
- surface = eglCreatePlatformWindowSurfaceEXT(dpy, config, native_window,
- int_attribs);
+ native_window = _fixupNativeWindow(disp, native_window);
+ surface = _eglCreateWindowSurfaceCommon(disp, config, native_window,
+ int_attribs);
free(int_attribs);
return surface;
}
+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 && disp->Platform == _EGL_PLATFORM_X11 && native_pixmap != NULL)
+ return (void *)(* (Pixmap*) native_pixmap);
+#endif
+ return native_pixmap;
+}
static EGLSurface
_eglCreatePixmapSurfaceCommon(_EGLDisplay *disp, EGLConfig config,
_EGLSurface *surf;
EGLSurface ret;
+#if HAVE_SURFACELESS_PLATFORM
+ if (disp && disp->Platform == _EGL_PLATFORM_SURFACELESS) {
+ /* From the EGL_MESA_platform_surfaceless spec (v1):
+ *
+ * [Like eglCreatePlatformWindowSurface,] eglCreatePlatformPixmapSurface
+ * also fails when called with a <display> that belongs to the
+ * surfaceless platform. It returns EGL_NO_SURFACE and generates
+ * EGL_BAD_NATIVE_PIXMAP.
+ *
+ * This check must occur before checking the EGLConfig, which emits
+ * EGL_BAD_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);
+
+ if (native_pixmap == NULL)
+ RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_PIXMAP, EGL_NO_SURFACE);
+
surf = drv->API.CreatePixmapSurface(drv, disp, conf, native_pixmap,
attrib_list);
ret = (surf) ? _eglLinkSurface(surf) : EGL_NO_SURFACE;
EGLNativePixmapType pixmap, const EGLint *attrib_list)
{
_EGLDisplay *disp = _eglLockDisplay(dpy);
+
+ _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);
-#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) {
- native_pixmap = (void*) (* (Pixmap*) native_pixmap);
- }
-#endif
-
+ _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE);
+ native_pixmap = _fixupNativePixmap(disp, native_pixmap);
return _eglCreatePixmapSurfaceCommon(disp, config, native_pixmap,
attrib_list);
}
void *native_pixmap,
const EGLAttrib *attrib_list)
{
+ _EGLDisplay *disp = _eglLockDisplay(dpy);
EGLSurface surface;
- EGLint *int_attribs = _eglConvertAttribsToInt(attrib_list);
+ EGLint *int_attribs;
+ _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE);
+
+ int_attribs = _eglConvertAttribsToInt(attrib_list);
if (attrib_list && !int_attribs)
- RETURN_EGL_ERROR(NULL, EGL_BAD_ALLOC, EGL_NO_SURFACE);
+ RETURN_EGL_ERROR(disp, EGL_BAD_ALLOC, EGL_NO_SURFACE);
- surface = eglCreatePlatformPixmapSurfaceEXT(dpy, config, native_pixmap,
- int_attribs);
+ native_pixmap = _fixupNativePixmap(disp, native_pixmap);
+ surface = _eglCreatePixmapSurfaceCommon(disp, config, native_pixmap,
+ int_attribs);
free(int_attribs);
return surface;
}
_EGLSurface *surf;
EGLSurface ret;
+ _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE);
_EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE, drv);
+ 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);
ret = (surf) ? _eglLinkSurface(surf) : EGL_NO_SURFACE;
_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);
_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);
_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);
_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);
_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);
{
_EGLDisplay *disp = _eglLockDisplay(dpy);
_EGLContext *ctx = _eglGetCurrentContext();
- _EGLSurface *surf;
+ _EGLSurface *surf = ctx ? ctx->DrawSurface : NULL;
_EGLDriver *drv;
EGLBoolean ret;
+ _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
_EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT ||
ctx->Resource.Display != disp)
RETURN_EGL_ERROR(disp, EGL_BAD_CONTEXT, EGL_FALSE);
- surf = ctx->DrawSurface;
if (_eglGetSurfaceHandle(surf) == EGL_NO_SURFACE)
RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE);
- ret = drv->API.SwapInterval(drv, disp, surf, interval);
+ interval = CLAMP(interval,
+ surf->Config->MinSwapInterval,
+ surf->Config->MaxSwapInterval);
+
+ if (surf->SwapInterval != interval)
+ ret = drv->API.SwapInterval(drv, disp, surf, interval);
+ else
+ ret = EGL_TRUE;
+
+ if (ret)
+ surf->SwapInterval = interval;
RETURN_EGL_EVAL(disp, ret);
}
_EGLDriver *drv;
EGLBoolean ret;
+ _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
_EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
/* surface must be bound to current context in EGL 1.4 */
RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE);
#endif
+ /* 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->API.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);
}
-#ifdef EGL_EXT_swap_buffers_with_damage
-
-static EGLBoolean EGLAPIENTRY
-eglSwapBuffersWithDamageEXT(EGLDisplay dpy, EGLSurface surface,
- EGLint *rects, EGLint n_rects)
+static EGLBoolean
+_eglSwapBuffersWithDamageCommon(_EGLDisplay *disp, _EGLSurface *surf,
+ EGLint *rects, EGLint n_rects)
{
_EGLContext *ctx = _eglGetCurrentContext();
- _EGLDisplay *disp = _eglLockDisplay(dpy);
- _EGLSurface *surf = _eglLookupSurface(surface, disp);
_EGLDriver *drv;
EGLBoolean ret;
ret = drv->API.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);
}
-#endif /* EGL_EXT_swap_buffers_with_damage */
+static EGLBoolean EGLAPIENTRY
+eglSwapBuffersWithDamageEXT(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);
+ return _eglSwapBuffersWithDamageCommon(disp, surf, rects, n_rects);
+}
+
+static EGLBoolean EGLAPIENTRY
+eglSwapBuffersWithDamageKHR(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);
+ return _eglSwapBuffersWithDamageCommon(disp, surf, rects, n_rects);
+}
+
+/**
+ * If the width of the passed rect is greater than the surface's
+ * width then it is clamped to the width of the surface. Same with
+ * height.
+ */
+
+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 x, y, rect_width, rect_height;
+ x = rects[i];
+ y = rects[i + 1];
+ rect_width = rects[i + 2];
+ rect_height = rects[i + 3];
+
+ if (rect_width > surf_width - x)
+ rects[i + 2] = surf_width - x;
+
+ if (rect_height > surf_height - y)
+ rects[i + 3] = surf_height - y;
+ }
+}
+
+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();
+ _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->API.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)
EGLBoolean ret;
void *native_pixmap_ptr;
+ _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
STATIC_ASSERT(sizeof(void*) == sizeof(target));
native_pixmap_ptr = (void*) target;
}
-EGLBoolean EGLAPIENTRY
-eglWaitClient(void)
+static EGLBoolean
+_eglWaitClientCommon(void)
{
_EGLContext *ctx = _eglGetCurrentContext();
_EGLDisplay *disp;
RETURN_EGL_EVAL(disp, ret);
}
+EGLBoolean EGLAPIENTRY
+eglWaitClient(void)
+{
+ _EGL_FUNC_START(NULL, EGL_OBJECT_CONTEXT_KHR, _eglGetCurrentContext(), EGL_FALSE);
+ return _eglWaitClientCommon();
+}
EGLBoolean EGLAPIENTRY
eglWaitGL(void)
{
- _EGLThreadInfo *t = _eglGetCurrentThread();
- EGLint api_index = t->CurrentAPIIndex;
- EGLint es_index = _eglConvertApiToIndex(EGL_OPENGL_ES_API);
- EGLBoolean ret;
-
- if (api_index != es_index && _eglIsCurrentThreadDummy())
- RETURN_EGL_ERROR(NULL, EGL_BAD_ALLOC, EGL_FALSE);
-
- t->CurrentAPIIndex = es_index;
- ret = eglWaitClient();
- t->CurrentAPIIndex = api_index;
- return ret;
+ /* Since we only support OpenGL and GLES, eglWaitGL is equivalent to eglWaitClient. */
+ _EGL_FUNC_START(NULL, EGL_OBJECT_CONTEXT_KHR, _eglGetCurrentContext(), EGL_FALSE);
+ return _eglWaitClientCommon();
}
if (!ctx)
RETURN_EGL_SUCCESS(NULL, EGL_TRUE);
+ _EGL_FUNC_START(NULL, EGL_OBJECT_THREAD_KHR, NULL, EGL_FALSE);
+
disp = ctx->Resource.Display;
mtx_lock(&disp->Mutex);
_EGLSurface *surf;
EGLSurface ret;
+ _EGL_FUNC_START(NULL, EGL_NONE, NULL, EGL_NO_SURFACE);
+
if (!ctx)
RETURN_EGL_SUCCESS(NULL, EGL_NO_SURFACE);
}
-#ifdef EGL_MESA_drm_display
-
-static EGLDisplay EGLAPIENTRY
-eglGetDRMDisplayMESA(int fd)
-{
- _EGLDisplay *dpy = _eglFindDisplay(_EGL_PLATFORM_DRM, (void *) (intptr_t) fd);
- return _eglGetDisplayHandle(dpy);
-}
-
-#endif /* EGL_MESA_drm_display */
-
/**
** EGL 1.2
**/
EGLBoolean EGLAPIENTRY
eglBindAPI(EGLenum api)
{
- _EGLThreadInfo *t = _eglGetCurrentThread();
+ _EGLThreadInfo *t;
+
+ _EGL_FUNC_START(NULL, EGL_OBJECT_THREAD_KHR, NULL, EGL_FALSE);
+ t = _eglGetCurrentThread();
if (_eglIsCurrentThreadDummy())
RETURN_EGL_ERROR(NULL, EGL_BAD_ALLOC, EGL_FALSE);
if (!_eglIsApiValid(api))
RETURN_EGL_ERROR(NULL, EGL_BAD_PARAMETER, EGL_FALSE);
- t->CurrentAPIIndex = _eglConvertApiToIndex(api);
+ t->CurrentAPI = api;
RETURN_EGL_SUCCESS(NULL, EGL_TRUE);
}
EGLenum ret;
/* returns one of EGL_OPENGL_API, EGL_OPENGL_ES_API or EGL_OPENVG_API */
- ret = _eglConvertApiFromIndex(t->CurrentAPIIndex);
+ ret = t->CurrentAPI;
RETURN_EGL_SUCCESS(NULL, ret);
}
_EGLSurface *surf;
EGLSurface ret;
+ _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,
/* unbind current contexts */
if (!_eglIsCurrentThreadDummy()) {
_EGLThreadInfo *t = _eglGetCurrentThread();
- EGLint api_index = t->CurrentAPIIndex;
- EGLint i;
+ _EGLContext *ctx = t->CurrentContext;
- for (i = 0; i < _EGL_API_NUM_APIS; i++) {
- _EGLContext *ctx = t->CurrentContexts[i];
- if (ctx) {
- _EGLDisplay *disp = ctx->Resource.Display;
- _EGLDriver *drv;
+ _EGL_FUNC_START(NULL, EGL_OBJECT_THREAD_KHR, NULL, EGL_FALSE);
- t->CurrentAPIIndex = i;
+ if (ctx) {
+ _EGLDisplay *disp = ctx->Resource.Display;
+ _EGLDriver *drv;
- mtx_lock(&disp->Mutex);
- drv = disp->Driver;
- (void) drv->API.MakeCurrent(drv, disp, NULL, NULL, NULL);
- mtx_unlock(&disp->Mutex);
- }
+ mtx_lock(&disp->Mutex);
+ drv = disp->Driver;
+ (void) drv->API.MakeCurrent(drv, disp, NULL, NULL, NULL);
+ mtx_unlock(&disp->Mutex);
}
-
- t->CurrentAPIIndex = api_index;
}
_eglDestroyCurrentThread();
}
-static EGLImage EGLAPIENTRY
-eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target,
- EGLClientBuffer buffer, const EGLint *attr_list)
+static EGLImage
+_eglCreateImageCommon(_EGLDisplay *disp, EGLContext ctx, EGLenum target,
+ EGLClientBuffer buffer, const EGLint *attr_list)
{
- _EGLDisplay *disp = _eglLockDisplay(dpy);
_EGLContext *context = _eglLookupContext(ctx, disp);
_EGLDriver *drv;
_EGLImage *img;
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->API.CreateImageKHR(drv, disp, context, target,
+ buffer, attr_list);
ret = (img) ? _eglLinkImage(img) : EGL_NO_IMAGE_KHR;
RETURN_EGL_EVAL(disp, ret);
}
+static EGLImage EGLAPIENTRY
+eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target,
+ EGLClientBuffer buffer, const EGLint *attr_list)
+{
+ _EGLDisplay *disp = _eglLockDisplay(dpy);
+ _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_IMAGE_KHR);
+ return _eglCreateImageCommon(disp, ctx, target, buffer, attr_list);
+}
+
EGLImage EGLAPIENTRY
eglCreateImage(EGLDisplay dpy, EGLContext ctx, EGLenum target,
EGLClientBuffer buffer, const EGLAttrib *attr_list)
{
+ _EGLDisplay *disp = _eglLockDisplay(dpy);
EGLImage image;
- EGLint *int_attribs = _eglConvertAttribsToInt(attr_list);
+ EGLint *int_attribs;
+ _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_IMAGE_KHR);
+
+ int_attribs = _eglConvertAttribsToInt(attr_list);
if (attr_list && !int_attribs)
- RETURN_EGL_ERROR(NULL, EGL_BAD_ALLOC, EGL_NO_IMAGE);
+ RETURN_EGL_ERROR(disp, EGL_BAD_ALLOC, EGL_NO_IMAGE);
- image = eglCreateImageKHR(dpy, ctx, target, buffer, int_attribs);
+ image = _eglCreateImageCommon(disp, ctx, target, buffer, int_attribs);
free(int_attribs);
return image;
}
-EGLBoolean EGLAPIENTRY
-eglDestroyImage(EGLDisplay dpy, EGLImage image)
+static EGLBoolean
+_eglDestroyImageCommon(_EGLDisplay *disp, _EGLImage *img)
{
- _EGLDisplay *disp = _eglLockDisplay(dpy);
- _EGLImage *img = _eglLookupImage(image, disp);
_EGLDriver *drv;
EGLBoolean ret;
RETURN_EGL_EVAL(disp, ret);
}
+EGLBoolean EGLAPIENTRY
+eglDestroyImage(EGLDisplay dpy, EGLImage image)
+{
+ _EGLDisplay *disp = _eglLockDisplay(dpy);
+ _EGLImage *img = _eglLookupImage(image, disp);
+ _EGL_FUNC_START(disp, EGL_OBJECT_IMAGE_KHR, img, EGL_FALSE);
+ return _eglDestroyImageCommon(disp, img);
+}
+
+static EGLBoolean EGLAPIENTRY
+eglDestroyImageKHR(EGLDisplay dpy, EGLImage image)
+{
+ _EGLDisplay *disp = _eglLockDisplay(dpy);
+ _EGLImage *img = _eglLookupImage(image, disp);
+ _EGL_FUNC_START(disp, EGL_OBJECT_IMAGE_KHR, img, EGL_FALSE);
+ return _eglDestroyImageCommon(disp, img);
+}
+
static EGLSync
-_eglCreateSync(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list,
- const EGLAttrib *attrib_list64, EGLBoolean is64,
+_eglCreateSync(_EGLDisplay *disp, EGLenum type, const EGLAttrib *attrib_list,
+ EGLBoolean orig_is_EGLAttrib,
EGLenum invalid_type_error)
{
- _EGLDisplay *disp = _eglLockDisplay(dpy);
_EGLContext *ctx = _eglGetCurrentContext();
_EGLDriver *drv;
_EGLSync *sync;
_EGL_CHECK_DISPLAY(disp, EGL_NO_SYNC_KHR, drv);
- if (!disp->Extensions.KHR_cl_event2 && is64)
- RETURN_EGL_EVAL(disp, EGL_NO_SYNC_KHR);
+ if (!disp->Extensions.KHR_cl_event2 && orig_is_EGLAttrib) {
+ /* There exist two EGLAttrib variants of eglCreateSync*:
+ * eglCreateSync64KHR which requires EGL_KHR_cl_event2, and eglCreateSync
+ * which requires EGL 1.5. Here we use the presence of EGL_KHR_cl_event2
+ * support as a proxy for EGL 1.5 support, even though that's not
+ * entirely correct (though _eglComputeVersion does the same).
+ *
+ * The EGL spec provides no guidance on how to handle unsupported
+ * functions. EGL_BAD_MATCH seems reasonable.
+ */
+ RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_NO_SYNC_KHR);
+ }
+
+ /* If type is EGL_SYNC_FENCE and no context is current for the bound API
+ * (i.e., eglGetCurrentContext returns EGL_NO_CONTEXT ), an EGL_BAD_MATCH
+ * error is generated.
+ */
+ if (!ctx &&
+ (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 */
- if (!ctx || ctx->Resource.Display != dpy ||
- ctx->ClientAPI != EGL_OPENGL_ES_API)
+ if (ctx && (ctx->Resource.Display != disp ||
+ ctx->ClientAPI != EGL_OPENGL_ES_API))
RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_NO_SYNC_KHR);
switch (type) {
if (!disp->Extensions.KHR_cl_event2)
RETURN_EGL_ERROR(disp, invalid_type_error, EGL_NO_SYNC_KHR);
break;
+ case EGL_SYNC_NATIVE_FENCE_ANDROID:
+ if (!disp->Extensions.ANDROID_native_fence_sync)
+ RETURN_EGL_ERROR(disp, invalid_type_error, EGL_NO_SYNC_KHR);
+ break;
default:
RETURN_EGL_ERROR(disp, invalid_type_error, EGL_NO_SYNC_KHR);
}
- sync = drv->API.CreateSyncKHR(drv, disp, type, attrib_list, attrib_list64);
+ sync = drv->API.CreateSyncKHR(drv, disp, type, attrib_list);
ret = (sync) ? _eglLinkSync(sync) : EGL_NO_SYNC_KHR;
RETURN_EGL_EVAL(disp, ret);
static EGLSync EGLAPIENTRY
-eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list)
+eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *int_list)
{
- return _eglCreateSync(dpy, type, attrib_list, NULL, EGL_FALSE,
+ _EGLDisplay *disp = _eglLockDisplay(dpy);
+ _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE);
+
+ EGLSync sync;
+ EGLAttrib *attrib_list;
+ EGLint err;
+
+ if (sizeof(int_list[0]) == sizeof(attrib_list[0])) {
+ attrib_list = (EGLAttrib *) int_list;
+ } else {
+ err = _eglConvertIntsToAttribs(int_list, &attrib_list);
+ if (err != EGL_SUCCESS)
+ RETURN_EGL_ERROR(disp, err, EGL_NO_SYNC);
+ }
+
+ sync = _eglCreateSync(disp, type, attrib_list, EGL_FALSE,
EGL_BAD_ATTRIBUTE);
+
+ if (sizeof(int_list[0]) != sizeof(attrib_list[0]))
+ free(attrib_list);
+
+ /* Don't double-unlock the display. _eglCreateSync already unlocked it. */
+ return sync;
}
static EGLSync EGLAPIENTRY
eglCreateSync64KHR(EGLDisplay dpy, EGLenum type, const EGLAttrib *attrib_list)
{
- return _eglCreateSync(dpy, type, NULL, attrib_list, EGL_TRUE,
+ _EGLDisplay *disp = _eglLockDisplay(dpy);
+ _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE);
+ return _eglCreateSync(disp, type, attrib_list, EGL_TRUE,
EGL_BAD_ATTRIBUTE);
}
EGLSync EGLAPIENTRY
eglCreateSync(EGLDisplay dpy, EGLenum type, const EGLAttrib *attrib_list)
{
- return _eglCreateSync(dpy, type, NULL, attrib_list, EGL_TRUE,
+ _EGLDisplay *disp = _eglLockDisplay(dpy);
+ _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE);
+ return _eglCreateSync(disp, type, attrib_list, EGL_TRUE,
EGL_BAD_PARAMETER);
}
-EGLBoolean EGLAPIENTRY
-eglDestroySync(EGLDisplay dpy, EGLSync sync)
+static EGLBoolean
+_eglDestroySync(_EGLDisplay *disp, _EGLSync *s)
{
- _EGLDisplay *disp = _eglLockDisplay(dpy);
- _EGLSync *s = _eglLookupSync(sync, disp);
_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.KHR_fence_sync ||
+ disp->Extensions.ANDROID_native_fence_sync);
_eglUnlinkSync(s);
ret = drv->API.DestroySyncKHR(drv, disp, s);
RETURN_EGL_EVAL(disp, ret);
}
+EGLBoolean EGLAPIENTRY
+eglDestroySync(EGLDisplay dpy, EGLSync sync)
+{
+ _EGLDisplay *disp = _eglLockDisplay(dpy);
+ _EGLSync *s = _eglLookupSync(sync, disp);
+ _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE);
+ return _eglDestroySync(disp, s);
+}
-EGLint EGLAPIENTRY
-eglClientWaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags, EGLTime timeout)
+static EGLBoolean EGLAPIENTRY
+eglDestroySyncKHR(EGLDisplay dpy, EGLSync sync)
{
_EGLDisplay *disp = _eglLockDisplay(dpy);
_EGLSync *s = _eglLookupSync(sync, disp);
+ _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE);
+ return _eglDestroySync(disp, s);
+}
+
+
+static EGLint
+_eglClientWaitSyncCommon(_EGLDisplay *disp, EGLDisplay dpy,
+ _EGLSync *s, EGLint flags, EGLTime timeout)
+{
_EGLDriver *drv;
EGLint ret;
_EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv);
assert(disp->Extensions.KHR_reusable_sync ||
- disp->Extensions.KHR_fence_sync);
+ disp->Extensions.KHR_fence_sync ||
+ disp->Extensions.ANDROID_native_fence_sync);
if (s->SyncStatus == EGL_SIGNALED_KHR)
RETURN_EGL_EVAL(disp, EGL_CONDITION_SATISFIED_KHR);
+ /* if sync type is EGL_SYNC_REUSABLE_KHR, dpy should be
+ * unlocked here to allow other threads also to be able to
+ * go into waiting state.
+ */
+
+ if (s->Type == EGL_SYNC_REUSABLE_KHR)
+ _eglUnlockDisplay(dpy);
+
ret = drv->API.ClientWaitSyncKHR(drv, disp, s, flags, timeout);
- RETURN_EGL_EVAL(disp, ret);
+ /*
+ * 'disp' is already unlocked for reusable sync type,
+ * so passing 'NULL' to bypass unlocking display.
+ */
+ if (s->Type == EGL_SYNC_REUSABLE_KHR)
+ RETURN_EGL_EVAL(NULL, ret);
+ else
+ RETURN_EGL_EVAL(disp, ret);
}
+EGLint EGLAPIENTRY
+eglClientWaitSync(EGLDisplay dpy, EGLSync sync,
+ EGLint flags, EGLTime timeout)
+{
+ _EGLDisplay *disp = _eglLockDisplay(dpy);
+ _EGLSync *s = _eglLookupSync(sync, disp);
+ _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE);
+ return _eglClientWaitSyncCommon(disp, dpy, s, flags, timeout);
+}
static EGLint EGLAPIENTRY
-eglWaitSyncKHR(EGLDisplay dpy, EGLSync sync, EGLint flags)
+eglClientWaitSyncKHR(EGLDisplay dpy, EGLSync sync,
+ EGLint flags, EGLTime timeout)
{
_EGLDisplay *disp = _eglLockDisplay(dpy);
_EGLSync *s = _eglLookupSync(sync, disp);
+ _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE);
+ return _eglClientWaitSyncCommon(disp, dpy, s, flags, timeout);
+}
+
+
+static EGLint
+_eglWaitSyncCommon(_EGLDisplay *disp, _EGLSync *s, EGLint flags)
+{
_EGLContext *ctx = _eglGetCurrentContext();
_EGLDriver *drv;
EGLint ret;
RETURN_EGL_EVAL(disp, ret);
}
+static EGLint EGLAPIENTRY
+eglWaitSyncKHR(EGLDisplay dpy, EGLSync sync, EGLint flags)
+{
+ _EGLDisplay *disp = _eglLockDisplay(dpy);
+ _EGLSync *s = _eglLookupSync(sync, disp);
+ _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE);
+ return _eglWaitSyncCommon(disp, s, flags);
+}
+
EGLBoolean EGLAPIENTRY
eglWaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags)
* EGLBoolean. In both cases, the return values can only be EGL_FALSE and
* EGL_TRUE.
*/
- return eglWaitSyncKHR(dpy, sync, flags);
+ _EGLDisplay *disp = _eglLockDisplay(dpy);
+ _EGLSync *s = _eglLookupSync(sync, disp);
+ _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE);
+ return _eglWaitSyncCommon(disp, s, flags);
}
_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);
}
-EGLBoolean EGLAPIENTRY
-eglGetSyncAttrib(EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLAttrib *value)
+static EGLBoolean
+_eglGetSyncAttribCommon(_EGLDisplay *disp, _EGLSync *s, EGLint attribute, EGLAttrib *value)
{
- _EGLDisplay *disp = _eglLockDisplay(dpy);
- _EGLSync *s = _eglLookupSync(sync, disp);
_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.KHR_fence_sync ||
+ disp->Extensions.ANDROID_native_fence_sync);
ret = drv->API.GetSyncAttrib(drv, disp, s, attribute, value);
RETURN_EGL_EVAL(disp, ret);
}
+EGLBoolean EGLAPIENTRY
+eglGetSyncAttrib(EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLAttrib *value)
+{
+ _EGLDisplay *disp = _eglLockDisplay(dpy);
+ _EGLSync *s = _eglLookupSync(sync, disp);
+ _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE);
+ return _eglGetSyncAttribCommon(disp, s, attribute, value);
+}
+
static EGLBoolean EGLAPIENTRY
eglGetSyncAttribKHR(EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLint *value)
{
- EGLAttrib attrib = *value;
- EGLBoolean result = eglGetSyncAttrib(dpy, sync, attribute, &attrib);
+ _EGLDisplay *disp = _eglLockDisplay(dpy);
+ _EGLSync *s = _eglLookupSync(sync, disp);
+ EGLAttrib attrib;
+ EGLBoolean result;
+
+ _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE);
+
+ if (!value)
+ RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
+
+ attrib = *value;
+ result = _eglGetSyncAttribCommon(disp, s, attribute, &attrib);
/* The EGL_KHR_fence_sync spec says this about eglGetSyncAttribKHR:
*
return result;
}
+static EGLint EGLAPIENTRY
+eglDupNativeFenceFDANDROID(EGLDisplay dpy, EGLSync sync)
+{
+ _EGLDisplay *disp = _eglLockDisplay(dpy);
+ _EGLSync *s = _eglLookupSync(sync, disp);
+ _EGLDriver *drv;
+ EGLBoolean ret;
-#ifdef EGL_NOK_swap_region
+ _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE);
+
+ /* the spec doesn't seem to specify what happens if the fence
+ * type is not EGL_SYNC_NATIVE_FENCE_ANDROID, but this seems
+ * sensible:
+ */
+ if (!(s && (s->Type == EGL_SYNC_NATIVE_FENCE_ANDROID)))
+ RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_NO_NATIVE_FENCE_FD_ANDROID);
+
+ _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);
+
+ 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);
_EGLDriver *drv;
EGLBoolean ret;
+ _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
+
_EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
if (!disp->Extensions.NOK_swap_region)
RETURN_EGL_EVAL(disp, ret);
}
-#endif /* EGL_NOK_swap_region */
-
-
-#ifdef EGL_MESA_drm_image
static EGLImage EGLAPIENTRY
eglCreateDRMImageMESA(EGLDisplay dpy, const EGLint *attr_list)
_EGLImage *img;
EGLImage ret;
+ _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE);
+
_EGL_CHECK_DISPLAY(disp, EGL_NO_IMAGE_KHR, drv);
if (!disp->Extensions.MESA_drm_image)
RETURN_EGL_EVAL(disp, EGL_NO_IMAGE_KHR);
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;
EGLBoolean ret;
+ _EGL_FUNC_START(disp, EGL_OBJECT_IMAGE_KHR, img, EGL_FALSE);
+
_EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
assert(disp->Extensions.MESA_drm_image);
RETURN_EGL_EVAL(disp, ret);
}
-#endif
-#ifdef EGL_WL_bind_wayland_display
struct wl_display;
static EGLBoolean EGLAPIENTRY
_EGLDriver *drv;
EGLBoolean ret;
+ _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE);
+
_EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
assert(disp->Extensions.WL_bind_wayland_display);
_EGLDriver *drv;
EGLBoolean ret;
+ _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE);
+
_EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
assert(disp->Extensions.WL_bind_wayland_display);
_EGLDriver *drv;
EGLBoolean ret;
+ _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE);
+
_EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
assert(disp->Extensions.WL_bind_wayland_display);
RETURN_EGL_EVAL(disp, ret);
}
-#endif
-#ifdef EGL_WL_create_wayland_buffer_from_image
+
static struct wl_buffer * EGLAPIENTRY
eglCreateWaylandBufferFromImageWL(EGLDisplay dpy, EGLImage image)
{
_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);
RETURN_EGL_EVAL(disp, ret);
}
-#endif
static EGLBoolean EGLAPIENTRY
eglPostSubBufferNV(EGLDisplay dpy, EGLSurface surface,
_EGLDriver *drv;
EGLBoolean ret;
+ _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
+
_EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
if (!disp->Extensions.NV_post_sub_buffer)
_EGLDriver *drv;
EGLBoolean ret;
+ _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
+
_EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
if (!disp->Extensions.CHROMIUM_sync_control)
RETURN_EGL_EVAL(disp, EGL_FALSE);
RETURN_EGL_EVAL(disp, ret);
}
-#ifdef EGL_MESA_image_dma_buf_export
static EGLBoolean EGLAPIENTRY
eglExportDMABUFImageQueryMESA(EGLDisplay dpy, EGLImage image,
EGLint *fourcc, EGLint *nplanes,
_EGLDriver *drv;
EGLBoolean ret;
+ _EGL_FUNC_START(disp, EGL_OBJECT_IMAGE_KHR, img, EGL_FALSE);
+
_EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
assert(disp->Extensions.MESA_image_dma_buf_export);
_EGLDriver *drv;
EGLBoolean ret;
+ _EGL_FUNC_START(disp, EGL_OBJECT_IMAGE_KHR, img, EGL_FALSE);
+
_EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
assert(disp->Extensions.MESA_image_dma_buf_export);
RETURN_EGL_EVAL(disp, ret);
}
-#endif
+
+static EGLint EGLAPIENTRY
+eglLabelObjectKHR(EGLDisplay dpy, EGLenum objectType, EGLObjectKHR object,
+ EGLLabelKHR label)
+{
+ _EGLDisplay *disp = NULL;
+ _EGLResourceType type;
+
+ _EGL_FUNC_START(NULL, EGL_NONE, NULL, EGL_BAD_ALLOC);
+
+ if (objectType == EGL_OBJECT_THREAD_KHR) {
+ _EGLThreadInfo *t = _eglGetCurrentThread();
+
+ if (!_eglIsCurrentThreadDummy()) {
+ t->Label = label;
+ return EGL_SUCCESS;
+ }
+
+ RETURN_EGL_ERROR(NULL, EGL_BAD_ALLOC, EGL_BAD_ALLOC);
+ }
+
+ disp = _eglLockDisplay(dpy);
+ if (disp == NULL)
+ RETURN_EGL_ERROR(disp, EGL_BAD_DISPLAY, EGL_BAD_DISPLAY);
+
+ if (objectType == EGL_OBJECT_DISPLAY_KHR) {
+ if (dpy != (EGLDisplay) object)
+ RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_BAD_PARAMETER);
+
+ disp->Label = label;
+ RETURN_EGL_EVAL(disp, EGL_SUCCESS);
+ }
+
+ switch (objectType) {
+ case EGL_OBJECT_CONTEXT_KHR:
+ type = _EGL_RESOURCE_CONTEXT;
+ break;
+ case EGL_OBJECT_SURFACE_KHR:
+ type = _EGL_RESOURCE_SURFACE;
+ break;
+ case EGL_OBJECT_IMAGE_KHR:
+ type = _EGL_RESOURCE_IMAGE;
+ break;
+ case EGL_OBJECT_SYNC_KHR:
+ type = _EGL_RESOURCE_SYNC;
+ break;
+ case EGL_OBJECT_STREAM_KHR:
+ default:
+ RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_BAD_PARAMETER);
+ }
+
+ if (_eglCheckResource(object, type, disp)) {
+ _EGLResource *res = (_EGLResource *) object;
+
+ res->Label = label;
+ RETURN_EGL_EVAL(disp, EGL_SUCCESS);
+ }
+
+ RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_BAD_PARAMETER);
+}
+
+static EGLint EGLAPIENTRY
+eglDebugMessageControlKHR(EGLDEBUGPROCKHR callback,
+ const EGLAttrib *attrib_list)
+{
+ unsigned int newEnabled;
+
+ _EGL_FUNC_START(NULL, EGL_NONE, NULL, EGL_BAD_ALLOC);
+
+ mtx_lock(_eglGlobal.Mutex);
+
+ newEnabled = _eglGlobal.debugTypesEnabled;
+ if (attrib_list != NULL) {
+ int i;
+
+ for (i = 0; attrib_list[i] != EGL_NONE; i += 2) {
+ 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]);
+ 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;
+ }
+ }
+ }
+
+ if (callback != NULL) {
+ _eglGlobal.debugCallback = callback;
+ _eglGlobal.debugTypesEnabled = newEnabled;
+ } else {
+ _eglGlobal.debugCallback = NULL;
+ _eglGlobal.debugTypesEnabled = _EGL_DEBUG_BIT_CRITICAL | _EGL_DEBUG_BIT_ERROR;
+ }
+
+ mtx_unlock(_eglGlobal.Mutex);
+ return EGL_SUCCESS;
+}
+
+static EGLBoolean EGLAPIENTRY
+eglQueryDebugKHR(EGLint attribute, EGLAttrib *value)
+{
+ _EGL_FUNC_START(NULL, EGL_NONE, NULL, EGL_BAD_ALLOC);
+
+ mtx_lock(_eglGlobal.Mutex);
+
+ 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);
+ return EGL_FALSE;
+ }
+
+ mtx_unlock(_eglGlobal.Mutex);
+ return EGL_TRUE;
+}
+
+static int
+_eglFunctionCompare(const void *key, const void *elem)
+{
+ const char *procname = key;
+ const struct _egl_entrypoint *entrypoint = elem;
+ return strcmp(procname, entrypoint->name);
+}
+
+static EGLBoolean EGLAPIENTRY
+eglQueryDmaBufFormatsEXT(EGLDisplay dpy, EGLint max_formats,
+ EGLint *formats, EGLint *num_formats)
+{
+ _EGLDisplay *disp = _eglLockDisplay(dpy);
+ _EGLDriver *drv;
+ EGLBoolean ret;
+
+ _EGL_FUNC_START(NULL, EGL_NONE, NULL, EGL_FALSE);
+
+ _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
+
+ ret = drv->API.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);
+ _EGLDriver *drv;
+ EGLBoolean ret;
+
+ _EGL_FUNC_START(NULL, EGL_NONE, NULL, EGL_FALSE);
+
+ _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
+
+ ret = drv->API.QueryDmaBufModifiersEXT(drv, disp, format, max_modifiers,
+ modifiers, external_only,
+ num_modifiers);
+
+ RETURN_EGL_EVAL(disp, ret);
+}
__eglMustCastToProperFunctionPointerType EGLAPIENTRY
eglGetProcAddress(const char *procname)
{
- static const struct {
- const char *name;
- _EGLProc function;
- } egl_functions[] = {
- /* core functions queryable in the presence of
- * EGL_KHR_get_all_proc_addresses or EGL 1.5
- */
- /* alphabetical order */
- { "eglBindAPI", (_EGLProc) eglBindAPI },
- { "eglBindTexImage", (_EGLProc) eglBindTexImage },
- { "eglChooseConfig", (_EGLProc) eglChooseConfig },
- { "eglCopyBuffers", (_EGLProc) eglCopyBuffers },
- { "eglCreateContext", (_EGLProc) eglCreateContext },
- { "eglCreatePbufferFromClientBuffer", (_EGLProc) eglCreatePbufferFromClientBuffer },
- { "eglCreatePbufferSurface", (_EGLProc) eglCreatePbufferSurface },
- { "eglCreatePixmapSurface", (_EGLProc) eglCreatePixmapSurface },
- { "eglCreateWindowSurface", (_EGLProc) eglCreateWindowSurface },
- { "eglDestroyContext", (_EGLProc) eglDestroyContext },
- { "eglDestroySurface", (_EGLProc) eglDestroySurface },
- { "eglGetConfigAttrib", (_EGLProc) eglGetConfigAttrib },
- { "eglGetConfigs", (_EGLProc) eglGetConfigs },
- { "eglGetCurrentContext", (_EGLProc) eglGetCurrentContext },
- { "eglGetCurrentDisplay", (_EGLProc) eglGetCurrentDisplay },
- { "eglGetCurrentSurface", (_EGLProc) eglGetCurrentSurface },
- { "eglGetDisplay", (_EGLProc) eglGetDisplay },
- { "eglGetError", (_EGLProc) eglGetError },
- { "eglGetProcAddress", (_EGLProc) eglGetProcAddress },
- { "eglInitialize", (_EGLProc) eglInitialize },
- { "eglMakeCurrent", (_EGLProc) eglMakeCurrent },
- { "eglQueryAPI", (_EGLProc) eglQueryAPI },
- { "eglQueryContext", (_EGLProc) eglQueryContext },
- { "eglQueryString", (_EGLProc) eglQueryString },
- { "eglQuerySurface", (_EGLProc) eglQuerySurface },
- { "eglReleaseTexImage", (_EGLProc) eglReleaseTexImage },
- { "eglReleaseThread", (_EGLProc) eglReleaseThread },
- { "eglSurfaceAttrib", (_EGLProc) eglSurfaceAttrib },
- { "eglSwapBuffers", (_EGLProc) eglSwapBuffers },
- { "eglSwapInterval", (_EGLProc) eglSwapInterval },
- { "eglTerminate", (_EGLProc) eglTerminate },
- { "eglWaitClient", (_EGLProc) eglWaitClient },
- { "eglWaitGL", (_EGLProc) eglWaitGL },
- { "eglWaitNative", (_EGLProc) eglWaitNative },
- { "eglCreateSync", (_EGLProc) eglCreateSync },
- { "eglDestroySync", (_EGLProc) eglDestroySync },
- { "eglClientWaitSync", (_EGLProc) eglClientWaitSync },
- { "eglGetSyncAttrib", (_EGLProc) eglGetSyncAttrib },
- { "eglWaitSync", (_EGLProc) eglWaitSync },
- { "eglCreateImage", (_EGLProc) eglCreateImage },
- { "eglDestroyImage", (_EGLProc) eglDestroyImage },
- { "eglGetPlatformDisplay", (_EGLProc) eglGetPlatformDisplay },
- { "eglCreatePlatformWindowSurface", (_EGLProc) eglCreatePlatformWindowSurface },
- { "eglCreatePlatformPixmapSurface", (_EGLProc) eglCreatePlatformPixmapSurface },
-#ifdef EGL_MESA_drm_display
- { "eglGetDRMDisplayMESA", (_EGLProc) eglGetDRMDisplayMESA },
-#endif
- { "eglCreateImageKHR", (_EGLProc) eglCreateImageKHR },
- { "eglDestroyImageKHR", (_EGLProc) eglDestroyImage },
- { "eglCreateSyncKHR", (_EGLProc) eglCreateSyncKHR },
- { "eglCreateSync64KHR", (_EGLProc) eglCreateSync64KHR },
- { "eglDestroySyncKHR", (_EGLProc) eglDestroySync },
- { "eglClientWaitSyncKHR", (_EGLProc) eglClientWaitSync },
- { "eglWaitSyncKHR", (_EGLProc) eglWaitSyncKHR },
- { "eglSignalSyncKHR", (_EGLProc) eglSignalSyncKHR },
- { "eglGetSyncAttribKHR", (_EGLProc) eglGetSyncAttribKHR },
-#ifdef EGL_NOK_swap_region
- { "eglSwapBuffersRegionNOK", (_EGLProc) eglSwapBuffersRegionNOK },
-#endif
-#ifdef EGL_MESA_drm_image
- { "eglCreateDRMImageMESA", (_EGLProc) eglCreateDRMImageMESA },
- { "eglExportDRMImageMESA", (_EGLProc) eglExportDRMImageMESA },
-#endif
-#ifdef EGL_WL_bind_wayland_display
- { "eglBindWaylandDisplayWL", (_EGLProc) eglBindWaylandDisplayWL },
- { "eglUnbindWaylandDisplayWL", (_EGLProc) eglUnbindWaylandDisplayWL },
- { "eglQueryWaylandBufferWL", (_EGLProc) eglQueryWaylandBufferWL },
-#endif
-#ifdef EGL_WL_create_wayland_buffer_from_image
- { "eglCreateWaylandBufferFromImageWL", (_EGLProc) eglCreateWaylandBufferFromImageWL },
-#endif
- { "eglPostSubBufferNV", (_EGLProc) eglPostSubBufferNV },
-#ifdef EGL_EXT_swap_buffers_with_damage
- { "eglSwapBuffersWithDamageEXT", (_EGLProc) eglSwapBuffersWithDamageEXT },
-#endif
- { "eglGetPlatformDisplayEXT", (_EGLProc) eglGetPlatformDisplayEXT },
- { "eglCreatePlatformWindowSurfaceEXT", (_EGLProc) eglCreatePlatformWindowSurfaceEXT },
- { "eglCreatePlatformPixmapSurfaceEXT", (_EGLProc) eglCreatePlatformPixmapSurfaceEXT },
- { "eglGetSyncValuesCHROMIUM", (_EGLProc) eglGetSyncValuesCHROMIUM },
-#ifdef EGL_MESA_image_dma_buf_export
- { "eglExportDMABUFImageQueryMESA", (_EGLProc) eglExportDMABUFImageQueryMESA },
- { "eglExportDMABUFImageMESA", (_EGLProc) eglExportDMABUFImageMESA },
-#endif
- { NULL, NULL }
+ static const struct _egl_entrypoint egl_functions[] = {
+#define EGL_ENTRYPOINT(f) { .name = #f, .function = (_EGLProc) f },
+#include "eglentrypoint.h"
+#undef EGL_ENTRYPOINT
};
- EGLint i;
- _EGLProc ret;
+ _EGLProc ret = NULL;
if (!procname)
RETURN_EGL_SUCCESS(NULL, NULL);
- ret = NULL;
+ _EGL_FUNC_START(NULL, EGL_NONE, NULL, NULL);
+
if (strncmp(procname, "egl", 3) == 0) {
- for (i = 0; egl_functions[i].name; i++) {
- if (strcmp(egl_functions[i].name, procname) == 0) {
- ret = egl_functions[i].function;
- break;
- }
- }
+ const struct _egl_entrypoint *entrypoint =
+ bsearch(procname,
+ egl_functions, ARRAY_SIZE(egl_functions),
+ sizeof(egl_functions[0]),
+ _eglFunctionCompare);
+ if (entrypoint)
+ ret = entrypoint->function;
}
+
if (!ret)
ret = _eglGetDriverProc(procname);
RETURN_EGL_SUCCESS(NULL, ret);
}
+
+static int
+_eglLockDisplayInterop(EGLDisplay dpy, EGLContext context,
+ _EGLDisplay **disp, _EGLDriver **drv,
+ _EGLContext **ctx)
+{
+
+ *disp = _eglLockDisplay(dpy);
+ if (!*disp || !(*disp)->Initialized || !(*disp)->Driver) {
+ if (*disp)
+ _eglUnlockDisplay(*disp);
+ return MESA_GLINTEROP_INVALID_DISPLAY;
+ }
+
+ *drv = (*disp)->Driver;
+
+ *ctx = _eglLookupContext(context, *disp);
+ if (!*ctx ||
+ ((*ctx)->ClientAPI != EGL_OPENGL_API &&
+ (*ctx)->ClientAPI != EGL_OPENGL_ES_API)) {
+ _eglUnlockDisplay(*disp);
+ return MESA_GLINTEROP_INVALID_CONTEXT;
+ }
+
+ return MESA_GLINTEROP_SUCCESS;
+}
+
+PUBLIC int
+MesaGLInteropEGLQueryDeviceInfo(EGLDisplay dpy, EGLContext context,
+ struct mesa_glinterop_device_info *out)
+{
+ _EGLDisplay *disp;
+ _EGLDriver *drv;
+ _EGLContext *ctx;
+ int ret;
+
+ ret = _eglLockDisplayInterop(dpy, context, &disp, &drv, &ctx);
+ if (ret != MESA_GLINTEROP_SUCCESS)
+ return ret;
+
+ if (drv->API.GLInteropQueryDeviceInfo)
+ ret = drv->API.GLInteropQueryDeviceInfo(disp, ctx, out);
+ else
+ ret = MESA_GLINTEROP_UNSUPPORTED;
+
+ _eglUnlockDisplay(disp);
+ return ret;
+}
+
+PUBLIC int
+MesaGLInteropEGLExportObject(EGLDisplay dpy, EGLContext context,
+ struct mesa_glinterop_export_in *in,
+ struct mesa_glinterop_export_out *out)
+{
+ _EGLDisplay *disp;
+ _EGLDriver *drv;
+ _EGLContext *ctx;
+ int ret;
+
+ ret = _eglLockDisplayInterop(dpy, context, &disp, &drv, &ctx);
+ if (ret != MESA_GLINTEROP_SUCCESS)
+ return ret;
+
+ if (drv->API.GLInteropExportObject)
+ ret = drv->API.GLInteropExportObject(disp, ctx, in, out);
+ else
+ ret = MESA_GLINTEROP_UNSUPPORTED;
+
+ _eglUnlockDisplay(disp);
+ return ret;
+}