#include <string.h>
#include "c99_compat.h"
#include "c11/threads.h"
-#include "GL/mesa_glinterop.h"
#include "util/macros.h"
#include "eglglobals.h"
#include "eglimage.h"
#include "eglsync.h"
+#include "GL/mesa_glinterop.h"
/**
* Macros to help return an API entrypoint.
return EGL_TRUE;
}
- _eglDebugReportFull(EGL_BAD_ALLOC, funcName, funcName,
- EGL_DEBUG_MSG_CRITICAL_KHR, NULL, NULL);
+ _eglDebugReport(EGL_BAD_ALLOC, funcName, EGL_DEBUG_MSG_CRITICAL_KHR, NULL);
return EGL_FALSE;
}
static EGLDisplay
_eglGetPlatformDisplayCommon(EGLenum platform, void *native_display,
- const EGLint *attrib_list)
+ const EGLint *attrib_list)
{
_EGLDisplay *dpy;
_EGL_CHECK_EXTENSION(EXT_buffer_age);
_EGL_CHECK_EXTENSION(EXT_create_context_robustness);
_EGL_CHECK_EXTENSION(EXT_image_dma_buf_import);
+ _EGL_CHECK_EXTENSION(EXT_image_dma_buf_import_modifiers);
_EGL_CHECK_EXTENSION(EXT_swap_buffers_with_damage);
_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_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_surfaceless_context);
if (dpy->Extensions.EXT_swap_buffers_with_damage)
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 */
_eglCreateExtensionsString(disp);
_eglCreateAPIsString(disp);
snprintf(disp->VersionString, sizeof(disp->VersionString),
- "%d.%d (%s)", disp->Version / 10, disp->Version % 10,
- disp->Driver->Name);
+ "%d.%d (%s)", disp->Version / 10, disp->Version % 10,
+ disp->Driver->Name);
}
/* Update applications version of major and minor if not NULL */
_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);
}
_fixupNativeWindow(_EGLDisplay *disp, void *native_window)
{
#ifdef HAVE_X11_PLATFORM
- if (disp->Platform == _EGL_PLATFORM_X11 && native_window != NULL) {
+ if (disp && disp->Platform == _EGL_PLATFORM_X11 && native_window != NULL) {
/* The `native_window` parameter for the X11 platform differs between
* eglCreateWindowSurface() and eglCreatePlatformPixmapSurfaceEXT(). In
* eglCreateWindowSurface(), the type of `native_window` is an Xlib
_fixupNativePixmap(_EGLDisplay *disp, void *native_pixmap)
{
#ifdef HAVE_X11_PLATFORM
- /* The `native_pixmap` parameter for the X11 platform differs between
- * eglCreatePixmapSurface() and eglCreatePlatformPixmapSurfaceEXT(). In
- * eglCreatePixmapSurface(), the type of `native_pixmap` is an Xlib
- * `Pixmap`. In eglCreatePlatformPixmapSurfaceEXT(), the type is
- * `Pixmap*`. Convert `Pixmap*` to `Pixmap` because that's what
- * dri2_x11_create_pixmap_surface() expects.
- */
- if (disp->Platform == _EGL_PLATFORM_X11 && native_pixmap != NULL)
+ /* The `native_pixmap` parameter for the X11 platform differs between
+ * eglCreatePixmapSurface() and eglCreatePlatformPixmapSurfaceEXT(). In
+ * eglCreatePixmapSurface(), the type of `native_pixmap` is an Xlib
+ * `Pixmap`. In eglCreatePlatformPixmapSurfaceEXT(), the type is
+ * `Pixmap*`. Convert `Pixmap*` to `Pixmap` because that's what
+ * dri2_x11_create_pixmap_surface() expects.
+ */
+ if (disp && disp->Platform == _EGL_PLATFORM_X11 && native_pixmap != NULL)
return (void *)(* (Pixmap*) native_pixmap);
#endif
return native_pixmap;
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;
_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);
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);
}
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);
}
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);
}
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)
{
static EGLImage
_eglCreateImageCommon(_EGLDisplay *disp, EGLContext ctx, EGLenum target,
- EGLClientBuffer buffer, const EGLint *attr_list)
+ EGLClientBuffer buffer, const EGLint *attr_list)
{
_EGLContext *context = _eglLookupContext(ctx, disp);
_EGLDriver *drv;
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);
/* return an error if the client API doesn't support GL_OES_EGL_sync */
if (ctx && (ctx->Resource.Display != disp ||
- ctx->ClientAPI != EGL_OPENGL_ES_API))
+ ctx->ClientAPI != EGL_OPENGL_ES_API))
RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_NO_SYNC_KHR);
switch (type) {
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);
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);
static EGLint EGLAPIENTRY
eglLabelObjectKHR(EGLDisplay dpy, EGLenum objectType, EGLObjectKHR object,
- EGLLabelKHR label)
+ EGLLabelKHR label)
{
_EGLDisplay *disp = NULL;
_EGLResourceType type;
RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_BAD_PARAMETER);
}
-static EGLBoolean
-_validDebugMessageLevel(EGLAttrib level)
-{
- return (level >= EGL_DEBUG_MSG_CRITICAL_KHR &&
- level <= EGL_DEBUG_MSG_INFO_KHR);
-}
-
static EGLint EGLAPIENTRY
eglDebugMessageControlKHR(EGLDEBUGPROCKHR callback,
- const EGLAttrib *attrib_list)
+ const EGLAttrib *attrib_list)
{
unsigned int newEnabled;
int i;
for (i = 0; attrib_list[i] != EGL_NONE; i += 2) {
- if (_validDebugMessageLevel(attrib_list[i])) {
+ switch (attrib_list[i]) {
+ case EGL_DEBUG_MSG_CRITICAL_KHR:
+ case EGL_DEBUG_MSG_ERROR_KHR:
+ case EGL_DEBUG_MSG_WARN_KHR:
+ case EGL_DEBUG_MSG_INFO_KHR:
if (attrib_list[i + 1])
newEnabled |= DebugBitFromType(attrib_list[i]);
else
newEnabled &= ~DebugBitFromType(attrib_list[i]);
- continue;
+ break;
+ default:
+ // On error, set the last error code, call the current
+ // debug callback, and return the error code.
+ mtx_unlock(_eglGlobal.Mutex);
+ _eglReportError(EGL_BAD_ATTRIBUTE, NULL,
+ "Invalid attribute 0x%04lx", (unsigned long) attrib_list[i]);
+ return EGL_BAD_ATTRIBUTE;
}
-
- // On error, set the last error code, call the current
- // debug callback, and return the error code.
- mtx_unlock(_eglGlobal.Mutex);
- _eglReportError(EGL_BAD_ATTRIBUTE, NULL,
- "Invalid attribute 0x%04lx", (unsigned long) attrib_list[i]);
- return EGL_BAD_ATTRIBUTE;
}
}
mtx_lock(_eglGlobal.Mutex);
- do {
- if (_validDebugMessageLevel(attribute)) {
- if (_eglGlobal.debugTypesEnabled & DebugBitFromType(attribute))
- *value = EGL_TRUE;
- else
- *value = EGL_FALSE;
- break;
- }
-
- if (attribute == EGL_DEBUG_CALLBACK_KHR) {
- *value = (EGLAttrib) _eglGlobal.debugCallback;
- break;
- }
-
+ switch (attribute) {
+ case EGL_DEBUG_MSG_CRITICAL_KHR:
+ case EGL_DEBUG_MSG_ERROR_KHR:
+ case EGL_DEBUG_MSG_WARN_KHR:
+ case EGL_DEBUG_MSG_INFO_KHR:
+ if (_eglGlobal.debugTypesEnabled & DebugBitFromType(attribute))
+ *value = EGL_TRUE;
+ else
+ *value = EGL_FALSE;
+ break;
+ case EGL_DEBUG_CALLBACK_KHR:
+ *value = (EGLAttrib) _eglGlobal.debugCallback;
+ break;
+ default:
mtx_unlock(_eglGlobal.Mutex);
_eglReportError(EGL_BAD_ATTRIBUTE, NULL,
- "Invalid attribute 0x%04lx", (unsigned long) attribute);
+ "Invalid attribute 0x%04lx", (unsigned long) attribute);
return EGL_FALSE;
- } while (0);
+ }
mtx_unlock(_eglGlobal.Mutex);
return EGL_TRUE;