*/
+#ifdef USE_LIBGLVND
+#define EGLAPI
+#undef PUBLIC
+#define PUBLIC
+#endif
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "c11/threads.h"
#include "util/macros.h"
+#include "eglapi.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"
* 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;
}
* Unlock a display.
*/
static inline void
-_eglUnlockDisplay(_EGLDisplay *dpy)
+_eglUnlockDisplay(_EGLDisplay *disp)
{
- mtx_unlock(&dpy->Mutex);
+ mtx_unlock(&disp->Mutex);
}
static EGLBoolean
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;
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);
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 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;
#endif
+#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
const EGLint *int_attribs)
{
EGLAttrib *attrib_list;
- EGLDisplay display;
+ EGLDisplay disp;
_EGL_FUNC_START(NULL, EGL_OBJECT_THREAD_KHR, NULL, EGL_NO_DISPLAY);
if (_eglConvertIntsToAttribs(int_attribs, &attrib_list) != EGL_SUCCESS)
RETURN_EGL_ERROR(NULL, EGL_BAD_ALLOC, NULL);
- display = _eglGetPlatformDisplayCommon(platform, native_display, attrib_list);
+ disp = _eglGetPlatformDisplayCommon(platform, native_display, attrib_list);
free(attrib_list);
- return display;
+ return disp;
}
EGLDisplay EGLAPIENTRY
* 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(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)
- dpy->Extensions.KHR_image = EGL_TRUE;
+ 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_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);
}
static void
-_eglCreateAPIsString(_EGLDisplay *dpy)
+_eglCreateAPIsString(_EGLDisplay *disp)
{
#define addstr(str) \
{ \
- const size_t old_len = strlen(dpy->ClientAPIsString); \
+ const size_t old_len = strlen(disp->ClientAPIsString); \
const size_t add_len = sizeof(str); \
- const size_t max_len = sizeof(dpy->ClientAPIsString) - 1; \
+ const size_t max_len = sizeof(disp->ClientAPIsString) - 1; \
if (old_len + add_len <= max_len) \
- strcat(dpy->ClientAPIsString, str " "); \
+ strcat(disp->ClientAPIsString, str " "); \
else \
- assert(!"dpy->ClientAPIsString is not large enough"); \
+ assert(!"disp->ClientAPIsString is not large enough"); \
}
- if (dpy->ClientAPIs & EGL_OPENGL_BIT)
+ if (disp->ClientAPIs & EGL_OPENGL_BIT)
addstr("OpenGL");
- if (dpy->ClientAPIs & EGL_OPENGL_ES_BIT ||
- dpy->ClientAPIs & EGL_OPENGL_ES2_BIT ||
- dpy->ClientAPIs & EGL_OPENGL_ES3_BIT_KHR) {
+ 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)
+ if (disp->ClientAPIs & EGL_OPENVG_BIT)
addstr("OpenVG");
#undef addstr
_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 */
_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);
}
_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);
}
_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);
}
_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)
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 <display>
*/
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);
+ if (_eglNativeSurfaceAlreadyUsed(disp, native_window))
+ RETURN_EGL_ERROR(disp, EGL_BAD_ALLOC, EGL_NO_SURFACE);
+
surf = drv->API.CreateWindowSurface(drv, disp, conf, native_window,
attrib_list);
ret = (surf) ? _eglLinkSurface(surf) : EGL_NO_SURFACE;
_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
*/
RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_PIXMAP, EGL_NO_SURFACE);
}
-#endif
_EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE, drv);
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->API.CreatePixmapSurface(drv, disp, conf, native_pixmap,
attrib_list);
ret = (surf) ? _eglLinkSurface(surf) : EGL_NO_SURFACE;
_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->API.QuerySurface)
+ ret = drv->API.QuerySurface(drv, disp, surf, attribute, value);
+ else
+ ret = _eglQuerySurface(drv, disp, surf, attribute, value);
RETURN_EGL_EVAL(disp, 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);
}
surf->Config->MinSwapInterval,
surf->Config->MaxSwapInterval);
- if (surf->SwapInterval != interval)
- ret = drv->API.SwapInterval(drv, disp, surf, interval);
- else
+ if (surf->SwapInterval != interval) {
+ if (drv->API.SwapInterval)
+ ret = drv->API.SwapInterval(drv, disp, surf, interval);
+ else
+ ret = _eglSwapInterval(drv, disp, surf, interval);
+ }
+ else {
ret = EGL_TRUE;
+ }
if (ret)
surf->SwapInterval = interval;
RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE);
#endif
+ 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
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);
_EGLDisplay *disp = _eglLockDisplay(dpy);
_EGLConfig *conf = _eglLookupConfig(config, disp);
_EGLDriver *drv;
- _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,
- 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);
}
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);
}
}
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;
EGLBoolean ret;
_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);
+ _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);
+ _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->API.QueryDriverConfig(disp);
+ RETURN_EGL_EVAL(disp, ret);
+}
+
+static const char * EGLAPIENTRY
+eglGetDisplayDriverName(EGLDisplay dpy)
+{
+ _EGLDisplay *disp = _eglLockDisplay(dpy);
+ _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->API.QueryDriverName(disp);
+ RETURN_EGL_EVAL(disp, ret);
+}
+
__eglMustCastToProperFunctionPointerType EGLAPIENTRY
eglGetProcAddress(const char *procname)
{