#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include "c99_compat.h"
+#include "c11/threads.h"
+#include "eglcompiler.h"
#include "eglglobals.h"
#include "eglcontext.h"
#include "eglmode.h"
#include "eglimage.h"
#include "eglsync.h"
+#include "eglstring.h"
/**
_eglUnlockDisplay(disp); \
/* EGL error codes are non-zero */ \
if (err) \
- _eglError(err, __FUNCTION__); \
+ _eglError(err, __func__); \
return ret; \
} while (0)
#define _EGL_CHECK_DISPLAY(disp, ret, drv) \
do { \
- drv = _eglCheckDisplay(disp, __FUNCTION__); \
+ drv = _eglCheckDisplay(disp, __func__); \
if (!drv) \
RETURN_EGL_ERROR(disp, 0, ret); \
} while (0)
#define _EGL_CHECK_OBJECT(disp, type, obj, ret, drv) \
do { \
- drv = _eglCheck ## type(disp, obj, __FUNCTION__); \
+ drv = _eglCheck ## type(disp, obj, __func__); \
if (!drv) \
RETURN_EGL_ERROR(disp, 0, ret); \
} while (0)
_EGL_CHECK_OBJECT(disp, Sync, s, ret, drv)
-static INLINE _EGLDriver *
+static inline _EGLDriver *
_eglCheckDisplay(_EGLDisplay *disp, const char *msg)
{
if (!disp) {
}
-static INLINE _EGLDriver *
+static inline _EGLDriver *
_eglCheckSurface(_EGLDisplay *disp, _EGLSurface *surf, const char *msg)
{
_EGLDriver *drv = _eglCheckDisplay(disp, msg);
}
-static INLINE _EGLDriver *
+static inline _EGLDriver *
_eglCheckContext(_EGLDisplay *disp, _EGLContext *context, const char *msg)
{
_EGLDriver *drv = _eglCheckDisplay(disp, msg);
}
-static INLINE _EGLDriver *
+static inline _EGLDriver *
_eglCheckConfig(_EGLDisplay *disp, _EGLConfig *conf, const char *msg)
{
_EGLDriver *drv = _eglCheckDisplay(disp, msg);
}
-static INLINE _EGLDriver *
+static inline _EGLDriver *
_eglCheckSync(_EGLDisplay *disp, _EGLSync *s, const char *msg)
{
_EGLDriver *drv = _eglCheckDisplay(disp, msg);
#ifdef EGL_MESA_screen_surface
-static INLINE _EGLDriver *
+static inline _EGLDriver *
_eglCheckScreen(_EGLDisplay *disp, _EGLScreen *scrn, const char *msg)
{
_EGLDriver *drv = _eglCheckDisplay(disp, msg);
}
-static INLINE _EGLDriver *
+static inline _EGLDriver *
_eglCheckMode(_EGLDisplay *disp, _EGLMode *m, const char *msg)
{
_EGLDriver *drv = _eglCheckDisplay(disp, msg);
/**
* Lookup and lock a display.
*/
-static INLINE _EGLDisplay *
+static inline _EGLDisplay *
_eglLockDisplay(EGLDisplay display)
{
_EGLDisplay *dpy = _eglLookupDisplay(display);
if (dpy)
- _eglLockMutex(&dpy->Mutex);
+ mtx_lock(&dpy->Mutex);
return dpy;
}
/**
* Unlock a display.
*/
-static INLINE void
+static inline void
_eglUnlockDisplay(_EGLDisplay *dpy)
{
- _eglUnlockMutex(&dpy->Mutex);
+ mtx_unlock(&dpy->Mutex);
}
return _eglGetDisplayHandle(dpy);
}
+/**
+ * Copy the extension into the string and update the string pointer.
+ */
+static EGLint
+_eglAppendExtension(char **str, const char *ext)
+{
+ char *s = *str;
+ size_t len = strlen(ext);
+
+ if (s) {
+ memcpy(s, ext, len);
+ s[len++] = ' ';
+ s[len] = '\0';
+
+ *str += len;
+ }
+ else {
+ len++;
+ }
+
+ return (EGLint) len;
+}
+
+/**
+ * Examine the individual extension enable/disable flags and recompute
+ * the driver's Extensions string.
+ */
+static void
+_eglCreateExtensionsString(_EGLDisplay *dpy)
+{
+#define _EGL_CHECK_EXTENSION(ext) \
+ do { \
+ if (dpy->Extensions.ext) { \
+ _eglAppendExtension(&exts, "EGL_" #ext); \
+ assert(exts <= dpy->ExtensionsString + _EGL_MAX_EXTENSIONS_LEN); \
+ } \
+ } while (0)
+
+ char *exts = dpy->ExtensionsString;
+
+ _EGL_CHECK_EXTENSION(MESA_screen_surface);
+ _EGL_CHECK_EXTENSION(MESA_copy_context);
+ _EGL_CHECK_EXTENSION(MESA_drm_display);
+ _EGL_CHECK_EXTENSION(MESA_drm_image);
+ _EGL_CHECK_EXTENSION(MESA_configless_context);
+
+ _EGL_CHECK_EXTENSION(WL_bind_wayland_display);
+ _EGL_CHECK_EXTENSION(WL_create_wayland_buffer_from_image);
+
+ _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(KHR_vg_parent_image);
+ _EGL_CHECK_EXTENSION(KHR_get_all_proc_addresses);
+ _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_reusable_sync);
+ _EGL_CHECK_EXTENSION(KHR_fence_sync);
+ _EGL_CHECK_EXTENSION(KHR_wait_sync);
+ _EGL_CHECK_EXTENSION(KHR_cl_event2);
+
+ _EGL_CHECK_EXTENSION(KHR_surfaceless_context);
+ _EGL_CHECK_EXTENSION(KHR_create_context);
+
+ _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);
+#undef _EGL_CHECK_EXTENSION
+}
+
+static void
+_eglCreateAPIsString(_EGLDisplay *dpy)
+{
+ if (dpy->ClientAPIs & EGL_OPENGL_BIT)
+ strcat(dpy->ClientAPIsString, "OpenGL ");
+
+ if (dpy->ClientAPIs & EGL_OPENGL_ES_BIT)
+ 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 ");
+
+ assert(strlen(dpy->ClientAPIsString) < sizeof(dpy->ClientAPIsString));
+}
+
+
/**
* This is typically the second EGL function that an application calls.
* Here we load/initialize the actual hardware driver.
/* limit to APIs supported by core */
disp->ClientAPIs &= _EGL_API_ALL_BITS;
+
+ /* EGL_KHR_get_all_proc_addresses is a corner-case extension. The spec
+ * classifies it as an EGL display extension, though conceptually it's an
+ * EGL client extension.
+ *
+ * From the EGL_KHR_get_all_proc_addresses spec:
+ *
+ * The EGL implementation must expose the name
+ * EGL_KHR_client_get_all_proc_addresses if and only if it exposes
+ * EGL_KHR_get_all_proc_addresses and supports
+ * EGL_EXT_client_extensions.
+ *
+ * Mesa unconditionally exposes both client extensions mentioned above,
+ * so the spec requires that each EGLDisplay unconditionally expose
+ * EGL_KHR_get_all_proc_addresses also.
+ */
+ disp->Extensions.KHR_get_all_proc_addresses = EGL_TRUE;
+
+ _eglCreateExtensionsString(disp);
+ _eglCreateAPIsString(disp);
+ _eglsnprintf(disp->VersionString, sizeof(disp->VersionString),
+ "%d.%d (%s)", disp->VersionMajor, disp->VersionMinor,
+ disp->Driver->Name);
}
/* Update applications version of major and minor if not NULL */
drv->API.Terminate(drv, disp);
/* do not reset disp->Driver */
+ disp->ClientAPIsString[0] = 0;
disp->Initialized = EGL_FALSE;
}
{
_EGLDisplay *disp;
_EGLDriver *drv;
- const char *ret;
if (dpy == EGL_NO_DISPLAY && name == EGL_EXTENSIONS) {
RETURN_EGL_SUCCESS(NULL, _eglGlobal.ClientExtensionString);
disp = _eglLockDisplay(dpy);
_EGL_CHECK_DISPLAY(disp, NULL, drv);
- ret = drv->API.QueryString(drv, disp, name);
- RETURN_EGL_EVAL(disp, ret);
+ switch (name) {
+ case EGL_VENDOR:
+ RETURN_EGL_SUCCESS(disp, _EGL_VENDOR_STRING);
+ case EGL_VERSION:
+ RETURN_EGL_SUCCESS(disp, disp->VersionString);
+ case EGL_EXTENSIONS:
+ RETURN_EGL_SUCCESS(disp, disp->ExtensionsString);
+ case EGL_CLIENT_APIS:
+ RETURN_EGL_SUCCESS(disp, disp->ClientAPIsString);
+ default:
+ RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, NULL);
+ }
}
_EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
/* surface must be bound to current context in EGL 1.4 */
+ #ifndef _EGL_BUILT_IN_DRIVER_HAIKU
if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT ||
surf != ctx->DrawSurface)
RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE);
+ #endif
ret = drv->API.SwapBuffers(drv, disp, surf);
RETURN_EGL_SUCCESS(NULL, EGL_TRUE);
disp = ctx->Resource.Display;
- _eglLockMutex(&disp->Mutex);
+ mtx_lock(&disp->Mutex);
/* let bad current context imply bad current surface */
if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT ||
RETURN_EGL_SUCCESS(NULL, EGL_TRUE);
disp = ctx->Resource.Display;
- _eglLockMutex(&disp->Mutex);
+ mtx_lock(&disp->Mutex);
/* let bad current context imply bad current surface */
if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT ||
{ "eglCreateImageKHR", (_EGLProc) eglCreateImageKHR },
{ "eglDestroyImageKHR", (_EGLProc) eglDestroyImageKHR },
{ "eglCreateSyncKHR", (_EGLProc) eglCreateSyncKHR },
+ { "eglCreateSync64KHR", (_EGLProc) eglCreateSync64KHR },
{ "eglDestroySyncKHR", (_EGLProc) eglDestroySyncKHR },
{ "eglClientWaitSyncKHR", (_EGLProc) eglClientWaitSyncKHR },
+ { "eglWaitSyncKHR", (_EGLProc) eglWaitSyncKHR },
{ "eglSignalSyncKHR", (_EGLProc) eglSignalSyncKHR },
{ "eglGetSyncAttribKHR", (_EGLProc) eglGetSyncAttribKHR },
#ifdef EGL_NOK_swap_region
{ "eglCreatePlatformWindowSurfaceEXT", (_EGLProc) eglCreatePlatformWindowSurfaceEXT },
{ "eglCreatePlatformPixmapSurfaceEXT", (_EGLProc) eglCreatePlatformPixmapSurfaceEXT },
{ "eglGetSyncValuesCHROMIUM", (_EGLProc) eglGetSyncValuesCHROMIUM },
+#ifdef EGL_MESA_dma_buf_image_export
+ { "eglExportDMABUFImageQueryMESA", (_EGLProc) eglExportDMABUFImageQueryMESA },
+ { "eglExportDMABUFImageMESA", (_EGLProc) eglExportDMABUFImageMESA },
+#endif
{ NULL, NULL }
};
EGLint i;
t->CurrentAPIIndex = i;
- _eglLockMutex(&disp->Mutex);
+ mtx_lock(&disp->Mutex);
drv = disp->Driver;
(void) drv->API.MakeCurrent(drv, disp, NULL, NULL, NULL);
- _eglUnlockMutex(&disp->Mutex);
+ mtx_unlock(&disp->Mutex);
}
}
}
-EGLSyncKHR EGLAPIENTRY
-eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list)
+static EGLSyncKHR
+_eglCreateSync(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list,
+ const EGLAttribKHR *attrib_list64, EGLBoolean is64)
{
_EGLDisplay *disp = _eglLockDisplay(dpy);
+ _EGLContext *ctx = _eglGetCurrentContext();
_EGLDriver *drv;
_EGLSync *sync;
EGLSyncKHR ret;
_EGL_CHECK_DISPLAY(disp, EGL_NO_SYNC_KHR, drv);
- if (!disp->Extensions.KHR_reusable_sync)
+
+ if (!disp->Extensions.KHR_cl_event2 && is64)
RETURN_EGL_EVAL(disp, EGL_NO_SYNC_KHR);
- sync = drv->API.CreateSyncKHR(drv, disp, type, attrib_list);
+ /* 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)
+ RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_NO_SYNC_KHR);
+
+ switch (type) {
+ case EGL_SYNC_FENCE_KHR:
+ if (!disp->Extensions.KHR_fence_sync)
+ RETURN_EGL_ERROR(disp, EGL_BAD_ATTRIBUTE, EGL_NO_SYNC_KHR);
+ break;
+ case EGL_SYNC_REUSABLE_KHR:
+ if (!disp->Extensions.KHR_reusable_sync)
+ RETURN_EGL_ERROR(disp, EGL_BAD_ATTRIBUTE, EGL_NO_SYNC_KHR);
+ break;
+ case EGL_SYNC_CL_EVENT_KHR:
+ if (!disp->Extensions.KHR_cl_event2)
+ RETURN_EGL_ERROR(disp, EGL_BAD_ATTRIBUTE, EGL_NO_SYNC_KHR);
+ break;
+ default:
+ RETURN_EGL_ERROR(disp, EGL_BAD_ATTRIBUTE, EGL_NO_SYNC_KHR);
+ }
+
+ sync = drv->API.CreateSyncKHR(drv, disp, type, attrib_list, attrib_list64);
ret = (sync) ? _eglLinkSync(sync) : EGL_NO_SYNC_KHR;
RETURN_EGL_EVAL(disp, ret);
}
+EGLSyncKHR EGLAPIENTRY
+eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list)
+{
+ return _eglCreateSync(dpy, type, attrib_list, NULL, EGL_FALSE);
+}
+
+
+EGLSyncKHR EGLAPIENTRY
+eglCreateSync64KHR(EGLDisplay dpy, EGLenum type, const EGLAttribKHR *attrib_list)
+{
+ return _eglCreateSync(dpy, type, NULL, attrib_list, EGL_TRUE);
+}
+
+
EGLBoolean EGLAPIENTRY
eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync)
{
EGLBoolean ret;
_EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv);
- assert(disp->Extensions.KHR_reusable_sync);
+ assert(disp->Extensions.KHR_reusable_sync ||
+ disp->Extensions.KHR_fence_sync);
_eglUnlinkSync(s);
ret = drv->API.DestroySyncKHR(drv, disp, s);
EGLint ret;
_EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv);
- assert(disp->Extensions.KHR_reusable_sync);
+ assert(disp->Extensions.KHR_reusable_sync ||
+ disp->Extensions.KHR_fence_sync);
+
+ if (s->SyncStatus == EGL_SIGNALED_KHR)
+ RETURN_EGL_EVAL(disp, EGL_CONDITION_SATISFIED_KHR);
+
ret = drv->API.ClientWaitSyncKHR(drv, disp, s, flags, timeout);
RETURN_EGL_EVAL(disp, ret);
}
+EGLint EGLAPIENTRY
+eglWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags)
+{
+ _EGLDisplay *disp = _eglLockDisplay(dpy);
+ _EGLSync *s = _eglLookupSync(sync, disp);
+ _EGLContext *ctx = _eglGetCurrentContext();
+ _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_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);
+
+ RETURN_EGL_EVAL(disp, ret);
+}
+
+
EGLBoolean EGLAPIENTRY
eglSignalSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode)
{
EGLBoolean ret;
_EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv);
- assert(disp->Extensions.KHR_reusable_sync);
+ assert(disp->Extensions.KHR_reusable_sync ||
+ disp->Extensions.KHR_fence_sync);
ret = drv->API.GetSyncAttribKHR(drv, disp, s, attribute, value);
RETURN_EGL_EVAL(disp, ret);
RETURN_EGL_EVAL(disp, ret);
}
+
+#ifdef EGL_MESA_image_dma_buf_export
+EGLBoolean EGLAPIENTRY
+eglExportDMABUFImageQueryMESA(EGLDisplay dpy, EGLImageKHR image,
+ EGLint *fourcc, EGLint *nplanes,
+ EGLuint64KHR *modifiers)
+{
+ _EGLDisplay *disp = _eglLockDisplay(dpy);
+ _EGLImage *img = _eglLookupImage(image, disp);
+ _EGLDriver *drv;
+ EGLBoolean ret;
+
+ _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
+ assert(disp->Extensions.MESA_image_dma_buf_export);
+
+ if (!img)
+ RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
+
+ ret = drv->API.ExportDMABUFImageQueryMESA(drv, disp, img, fourcc, nplanes,
+ modifiers);
+
+ RETURN_EGL_EVAL(disp, ret);
+}
+
+EGLBoolean EGLAPIENTRY
+eglExportDMABUFImageMESA(EGLDisplay dpy, EGLImageKHR image,
+ int *fds, EGLint *strides, EGLint *offsets)
+{
+ _EGLDisplay *disp = _eglLockDisplay(dpy);
+ _EGLImage *img = _eglLookupImage(image, disp);
+ _EGLDriver *drv;
+ EGLBoolean ret;
+
+ _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
+ assert(disp->Extensions.MESA_image_dma_buf_export);
+
+ if (!img)
+ RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
+
+ ret = drv->API.ExportDMABUFImageMESA(drv, disp, img, fds, strides, offsets);
+
+ RETURN_EGL_EVAL(disp, ret);
+}
+#endif