#include <string.h>
#include "c99_compat.h"
#include "c11/threads.h"
+#include "GL/mesa_glinterop.h"
#include "eglcompiler.h"
#include "eglglobals.h"
#include "eglconfig.h"
#include "eglimage.h"
#include "eglsync.h"
-#include "eglstring.h"
/**
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_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_swap_buffers_with_damage);
- _EGL_CHECK_EXTENSION(KHR_vg_parent_image);
+ _EGL_CHECK_EXTENSION(KHR_cl_event2);
+ _EGL_CHECK_EXTENSION(KHR_create_context);
+ _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_reusable_sync);
- _EGL_CHECK_EXTENSION(KHR_fence_sync);
+ _EGL_CHECK_EXTENSION(KHR_surfaceless_context);
_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;
}
/**
_eglComputeVersion(disp);
_eglCreateExtensionsString(disp);
_eglCreateAPIsString(disp);
- _eglsnprintf(disp->VersionString, sizeof(disp->VersionString),
+ snprintf(disp->VersionString, sizeof(disp->VersionString),
"%d.%d (%s)", disp->Version / 10, disp->Version % 10,
disp->Driver->Name);
}
_EGL_CHECK_DISPLAY(disp, EGL_NO_CONTEXT, drv);
- if (!config && !disp->Extensions.MESA_configless_context)
+ if (!config && !disp->Extensions.KHR_no_config_context)
RETURN_EGL_ERROR(disp, EGL_BAD_CONFIG, EGL_NO_CONTEXT);
if (!share && share_list != EGL_NO_CONTEXT)
}
-#ifdef EGL_EXT_swap_buffers_with_damage
-
static EGLBoolean EGLAPIENTRY
eglSwapBuffersWithDamageEXT(EGLDisplay dpy, EGLSurface surface,
EGLint *rects, EGLint n_rects)
RETURN_EGL_EVAL(disp, ret);
}
-#endif /* EGL_EXT_swap_buffers_with_damage */
-
EGLBoolean EGLAPIENTRY
eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target)
{
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. */
+ return eglWaitClient();
}
}
-#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
**/
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);
}
/* unbind current contexts */
if (!_eglIsCurrentThreadDummy()) {
_EGLThreadInfo *t = _eglGetCurrentThread();
- EGLint api_index = t->CurrentAPIIndex;
- EGLint i;
-
- for (i = 0; i < _EGL_API_NUM_APIS; i++) {
- _EGLContext *ctx = t->CurrentContexts[i];
- if (ctx) {
- _EGLDisplay *disp = ctx->Resource.Display;
- _EGLDriver *drv;
- t->CurrentAPIIndex = i;
+ _EGLContext *ctx = t->CurrentContext;
+ 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();
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);
}
static EGLBoolean EGLAPIENTRY
eglGetSyncAttribKHR(EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLint *value)
{
- EGLAttrib attrib = *value;
- EGLBoolean result = eglGetSyncAttrib(dpy, sync, attribute, &attrib);
+ EGLAttrib attrib;
+ EGLBoolean result;
+
+ if (!value)
+ RETURN_EGL_ERROR(NULL, EGL_BAD_PARAMETER, EGL_FALSE);
+
+ attrib = *value;
+ result = eglGetSyncAttrib(dpy, sync, attribute, &attrib);
/* The EGL_KHR_fence_sync spec says this about eglGetSyncAttribKHR:
*
}
-#ifdef EGL_NOK_swap_region
-
static EGLBoolean EGLAPIENTRY
eglSwapBuffersRegionNOK(EGLDisplay dpy, EGLSurface surface,
EGLint numRects, const EGLint *rects)
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)
RETURN_EGL_EVAL(disp, ret);
}
-#endif
-#ifdef EGL_WL_bind_wayland_display
struct wl_display;
static EGLBoolean EGLAPIENTRY
RETURN_EGL_EVAL(disp, ret);
}
-#endif
-#ifdef EGL_WL_create_wayland_buffer_from_image
+
static struct wl_buffer * EGLAPIENTRY
eglCreateWaylandBufferFromImageWL(EGLDisplay dpy, EGLImage image)
{
RETURN_EGL_EVAL(disp, ret);
}
-#endif
static EGLBoolean EGLAPIENTRY
eglPostSubBufferNV(EGLDisplay dpy, EGLSurface surface,
RETURN_EGL_EVAL(disp, ret);
}
-#ifdef EGL_MESA_image_dma_buf_export
static EGLBoolean EGLAPIENTRY
eglExportDMABUFImageQueryMESA(EGLDisplay dpy, EGLImage image,
EGLint *fourcc, EGLint *nplanes,
RETURN_EGL_EVAL(disp, ret);
}
-#endif
__eglMustCastToProperFunctionPointerType EGLAPIENTRY
eglGetProcAddress(const char *procname)
{ "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 },
{ "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 }
};
EGLint i;
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;
+}
+
+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;
+}
+
+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;
+}