egl: Use SConscript for Windows build.
[mesa.git] / src / egl / main / eglapi.c
index 14cc5fa6137fad45b0206aac58f0c4a16f38b5c5..9912043e06c61eab3103586f0fd2768de173aea0 100644 (file)
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+
+#include "eglstring.h"
 #include "eglcontext.h"
 #include "egldisplay.h"
 #include "egltypedefs.h"
 #include "eglglobals.h"
+#include "eglcurrent.h"
 #include "egldriver.h"
 #include "eglsurface.h"
 #include "eglconfig.h"
 #include "eglscreen.h"
 #include "eglmode.h"
+#include "eglimage.h"
 
 
 /**
- * This is typically the first EGL function that an application calls.
- * We initialize our global vars and create a private _EGLDisplay object.
+ * Macros to help return an API entrypoint.
+ *
+ * These macros will unlock the display and record the error code.
  */
-EGLDisplay EGLAPIENTRY
-eglGetDisplay(NativeDisplayType nativeDisplay)
-{
-   _EGLDisplay *dpy;
-   dpy = _eglFindDisplay(nativeDisplay);
-   if (!dpy) {
-      dpy = _eglNewDisplay(nativeDisplay);
-      if (dpy)
-         _eglLinkDisplay(dpy);
-   }
-   return _eglGetDisplayHandle(dpy);
-}
+#define RETURN_EGL_ERROR(disp, err, ret)        \
+   do {                                         \
+      if (disp)                                 \
+         _eglUnlockDisplay(disp);               \
+      /* EGL error codes are non-zero */        \
+      if (err)                                  \
+         _eglError(err, __FUNCTION__);          \
+      return ret;                               \
+   } while (0)
 
+#define RETURN_EGL_SUCCESS(disp, ret) \
+   RETURN_EGL_ERROR(disp, EGL_SUCCESS, ret)
 
-/**
- * This is typically the second EGL function that an application calls.
- * Here we load/initialize the actual hardware driver.
- */
-EGLBoolean EGLAPIENTRY
-eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
-{
-   _EGLDisplay *disp = _eglLookupDisplay(dpy);
-   _EGLDriver *drv;
-   EGLint major_int, minor_int;
+/* record EGL_SUCCESS only when ret evaluates to true */
+#define RETURN_EGL_EVAL(disp, ret) \
+   RETURN_EGL_ERROR(disp, (ret) ? EGL_SUCCESS : 0, ret)
 
-   if (!disp)
-      return _eglError(EGL_BAD_DISPLAY, __FUNCTION__);
 
-   drv = disp->Driver;
-   if (!drv) {
-      drv = _eglOpenDriver(disp);
-      if (!drv)
-         return _eglError(EGL_NOT_INITIALIZED, __FUNCTION__);
+/*
+ * A bunch of macros and checks to simplify error checking.
+ */
 
-      /* Initialize the particular display now */
-      if (!drv->API.Initialize(drv, disp, &major_int, &minor_int)) {
-         _eglCloseDriver(drv, disp);
-         return _eglError(EGL_NOT_INITIALIZED, __FUNCTION__);
-      }
+#define _EGL_CHECK_DISPLAY(disp, ret, drv)         \
+   do {                                            \
+      drv = _eglCheckDisplay(disp, __FUNCTION__);  \
+      if (!drv)                                    \
+         RETURN_EGL_ERROR(disp, 0, ret);           \
+   } while (0)
 
-      disp->APImajor = major_int;
-      disp->APIminor = minor_int;
-      snprintf(disp->Version, sizeof(disp->Version),
-               "%d.%d (%s)", major_int, minor_int, drv->Name);
+#define _EGL_CHECK_OBJECT(disp, type, obj, ret, drv)      \
+   do {                                                   \
+      drv = _eglCheck ## type(disp, obj, __FUNCTION__);   \
+      if (!drv)                                           \
+         RETURN_EGL_ERROR(disp, 0, ret);                  \
+   } while (0)
 
-      /* limit to APIs supported by core */
-      disp->ClientAPIsMask &= _EGL_API_ALL_BITS;
+#define _EGL_CHECK_SURFACE(disp, surf, ret, drv) \
+   _EGL_CHECK_OBJECT(disp, Surface, surf, ret, drv)
 
-      disp->Driver = drv;
-   } else {
-      major_int = disp->APImajor;
-      minor_int = disp->APIminor;
-   }
+#define _EGL_CHECK_CONTEXT(disp, context, ret, drv) \
+   _EGL_CHECK_OBJECT(disp, Context, context, ret, drv)
 
-   /* Update applications version of major and minor if not NULL */
-   if ((major != NULL) && (minor != NULL)) {
-      *major = major_int;
-      *minor = minor_int;
-   }
+#define _EGL_CHECK_CONFIG(disp, conf, ret, drv) \
+   _EGL_CHECK_OBJECT(disp, Config, conf, ret, drv)
 
-   return EGL_TRUE;
-}
+#define _EGL_CHECK_SCREEN(disp, scrn, ret, drv) \
+   _EGL_CHECK_OBJECT(disp, Screen, scrn, ret, drv)
 
+#define _EGL_CHECK_MODE(disp, m, ret, drv) \
+   _EGL_CHECK_OBJECT(disp, Mode, m, ret, drv)
 
-EGLBoolean EGLAPIENTRY
-eglTerminate(EGLDisplay dpy)
-{
-   _EGLDisplay *disp = _eglLookupDisplay(dpy);
-   _EGLDriver *drv;
 
-   if (!disp)
-      return _eglError(EGL_BAD_DISPLAY, __FUNCTION__);
 
-   drv = disp->Driver;
-   if (drv) {
-      drv->API.Terminate(drv, disp);
-      _eglCloseDriver(drv, disp);
-      disp->Driver = NULL;
-   }
-
-   return EGL_TRUE;
-}
-
-
-/**
- * A bunch of check functions and declare macros to simply error checking.
- */
 static INLINE _EGLDriver *
 _eglCheckDisplay(_EGLDisplay *disp, const char *msg)
 {
@@ -165,7 +136,7 @@ _eglCheckDisplay(_EGLDisplay *disp, const char *msg)
       _eglError(EGL_BAD_DISPLAY, msg);
       return NULL;
    }
-   if (!disp->Driver) {
+   if (!disp->Initialized) {
       _eglError(EGL_NOT_INITIALIZED, msg);
       return NULL;
    }
@@ -215,38 +186,6 @@ _eglCheckConfig(_EGLDisplay *disp, _EGLConfig *conf, const char *msg)
 }
 
 
-#define _EGL_DECLARE_DD(dpy)                                   \
-   _EGLDisplay *disp = _eglLookupDisplay(dpy);                 \
-   _EGLDriver *drv;                                            \
-   do {                                                        \
-      drv = _eglCheckDisplay(disp, __FUNCTION__);              \
-      if (!drv)                                                \
-         return EGL_FALSE;                                     \
-   } while (0)
-
-
-#define _EGL_DECLARE_DD_AND_SURFACE(dpy, surface)              \
-   _EGLDisplay *disp = _eglLookupDisplay(dpy);                 \
-   _EGLSurface *surf = _eglLookupSurface((surface), disp);     \
-   _EGLDriver *drv;                                            \
-   do {                                                        \
-      drv = _eglCheckSurface(disp, surf, __FUNCTION__);        \
-      if (!drv)                                                \
-         return EGL_FALSE;                                     \
-   } while (0)
-
-
-#define _EGL_DECLARE_DD_AND_CONTEXT(dpy, ctx)                  \
-   _EGLDisplay *disp = _eglLookupDisplay(dpy);                 \
-   _EGLContext *context = _eglLookupContext((ctx), disp);      \
-   _EGLDriver *drv;                                            \
-   do {                                                        \
-      drv = _eglCheckContext(disp, context, __FUNCTION__);     \
-      if (!drv)                                                \
-         return EGL_FALSE;                                     \
-   } while (0)
-
-
 #ifdef EGL_MESA_screen_surface
 
 
@@ -278,36 +217,129 @@ _eglCheckMode(_EGLDisplay *disp, _EGLMode *m, const char *msg)
 }
 
 
-#define _EGL_DECLARE_DD_AND_SCREEN(dpy, screen)                \
-   _EGLDisplay *disp = _eglLookupDisplay(dpy);                 \
-   _EGLScreen *scrn = _eglLookupScreen((screen), disp);        \
-   _EGLDriver *drv;                                            \
-   do {                                                        \
-      drv = _eglCheckScreen(disp, scrn, __FUNCTION__);         \
-      if (!drv)                                                \
-         return EGL_FALSE;                                     \
-   } while (0)
+#endif /* EGL_MESA_screen_surface */
 
 
-#define _EGL_DECLARE_DD_AND_MODE(dpy, mode)                    \
-   _EGLDisplay *disp = _eglLookupDisplay(dpy);                 \
-   _EGLMode *m = _eglLookupMode((mode), disp);                 \
-   _EGLDriver *drv;                                            \
-   do {                                                        \
-      drv = _eglCheckMode(disp, m, __FUNCTION__);              \
-      if (!drv)                                                \
-         return EGL_FALSE;                                     \
-   } while (0)
+/**
+ * Lookup and lock a display.
+ */
+static INLINE _EGLDisplay *
+_eglLockDisplay(EGLDisplay display)
+{
+   _EGLDisplay *dpy = _eglLookupDisplay(display);
+   if (dpy)
+      _eglLockMutex(&dpy->Mutex);
+   return dpy;
+}
 
 
-#endif /* EGL_MESA_screen_surface */
+/**
+ * Unlock a display.
+ */
+static INLINE void
+_eglUnlockDisplay(_EGLDisplay *dpy)
+{
+   _eglUnlockMutex(&dpy->Mutex);
+}
+
+
+/**
+ * This is typically the first EGL function that an application calls.
+ * It associates a private _EGLDisplay object to the native display.
+ */
+EGLDisplay EGLAPIENTRY
+eglGetDisplay(EGLNativeDisplayType nativeDisplay)
+{
+   _EGLDisplay *dpy = _eglFindDisplay(nativeDisplay);
+   return _eglGetDisplayHandle(dpy);
+}
+
+
+/**
+ * This is typically the second EGL function that an application calls.
+ * Here we load/initialize the actual hardware driver.
+ */
+EGLBoolean EGLAPIENTRY
+eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
+{
+   _EGLDisplay *disp = _eglLockDisplay(dpy);
+   EGLint major_int = 0, minor_int = 0;
+
+   if (!disp)
+      RETURN_EGL_ERROR(NULL, EGL_BAD_DISPLAY, EGL_FALSE);
+
+   if (!disp->Initialized) {
+      _EGLDriver *drv = disp->Driver;
+
+      if (!drv) {
+         _eglPreloadDrivers();
+         drv = _eglMatchDriver(disp);
+        /* Initialize the particular display now */
+        if (drv && !drv->API.Initialize(drv, disp, &major_int, &minor_int))
+           RETURN_EGL_ERROR(disp, EGL_NOT_INITIALIZED, EGL_FALSE);
+      }
+      if (!drv)
+        /* Load and initialize the first default driver that works */
+        drv = _eglLoadDefaultDriver(disp, &major_int, &minor_int);
+      if (!drv)
+        RETURN_EGL_ERROR(disp, EGL_NOT_INITIALIZED, EGL_FALSE);
+
+      disp->APImajor = major_int;
+      disp->APIminor = minor_int;
+      _eglsnprintf(disp->Version, sizeof(disp->Version),
+               "%d.%d (%s)", major_int, minor_int, drv->Name);
+
+      /* limit to APIs supported by core */
+      disp->ClientAPIsMask &= _EGL_API_ALL_BITS;
+
+      disp->Driver = drv;
+      disp->Initialized = EGL_TRUE;
+   } else {
+      major_int = disp->APImajor;
+      minor_int = disp->APIminor;
+   }
+
+   /* Update applications version of major and minor if not NULL */
+   if ((major != NULL) && (minor != NULL)) {
+      *major = major_int;
+      *minor = minor_int;
+   }
+
+   RETURN_EGL_SUCCESS(disp, EGL_TRUE);
+}
+
+
+EGLBoolean EGLAPIENTRY
+eglTerminate(EGLDisplay dpy)
+{
+   _EGLDisplay *disp = _eglLockDisplay(dpy);
+
+   if (!disp)
+      RETURN_EGL_ERROR(NULL, EGL_BAD_DISPLAY, EGL_FALSE);
+
+   if (disp->Initialized) {
+      _EGLDriver *drv = disp->Driver;
+
+      drv->API.Terminate(drv, disp);
+      /* do not reset disp->Driver */
+      disp->Initialized = EGL_FALSE;
+   }
+
+   RETURN_EGL_SUCCESS(disp, EGL_TRUE);
+}
 
 
 const char * EGLAPIENTRY
 eglQueryString(EGLDisplay dpy, EGLint name)
 {
-   _EGL_DECLARE_DD(dpy);
-   return drv->API.QueryString(drv, disp, name);
+   _EGLDisplay *disp = _eglLockDisplay(dpy);
+   _EGLDriver *drv;
+   const char *ret;
+
+   _EGL_CHECK_DISPLAY(disp, NULL, drv);
+   ret = drv->API.QueryString(drv, disp, name);
+
+   RETURN_EGL_EVAL(disp, ret);
 }
 
 
@@ -315,8 +347,14 @@ EGLBoolean EGLAPIENTRY
 eglGetConfigs(EGLDisplay dpy, EGLConfig *configs,
               EGLint config_size, EGLint *num_config)
 {
-   _EGL_DECLARE_DD(dpy);
-   return drv->API.GetConfigs(drv, disp, configs, config_size, num_config);
+   _EGLDisplay *disp = _eglLockDisplay(dpy);
+   _EGLDriver *drv;
+   EGLBoolean ret;
+
+   _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
+   ret = drv->API.GetConfigs(drv, disp, configs, config_size, num_config);
+
+   RETURN_EGL_EVAL(disp, ret);
 }
 
 
@@ -324,9 +362,15 @@ EGLBoolean EGLAPIENTRY
 eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs,
                 EGLint config_size, EGLint *num_config)
 {
-   _EGL_DECLARE_DD(dpy);
-   return drv->API.ChooseConfig(drv, disp, attrib_list, configs,
+   _EGLDisplay *disp = _eglLockDisplay(dpy);
+   _EGLDriver *drv;
+   EGLBoolean ret;
+
+   _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
+   ret = drv->API.ChooseConfig(drv, disp, attrib_list, configs,
                                 config_size, num_config);
+
+   RETURN_EGL_EVAL(disp, ret);
 }
 
 
@@ -334,15 +378,15 @@ EGLBoolean EGLAPIENTRY
 eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config,
                    EGLint attribute, EGLint *value)
 {
-   _EGLDisplay *disp = _eglLookupDisplay(dpy);
+   _EGLDisplay *disp = _eglLockDisplay(dpy);
    _EGLConfig *conf = _eglLookupConfig(config, disp);
    _EGLDriver *drv;
+   EGLBoolean ret;
 
-   drv = _eglCheckConfig(disp, conf, __FUNCTION__);
-   if (!drv)
-      return EGL_FALSE;
+   _EGL_CHECK_CONFIG(disp, conf, EGL_FALSE, drv);
+   ret = drv->API.GetConfigAttrib(drv, disp, conf, attribute, value);
 
-   return drv->API.GetConfigAttrib(drv, disp, conf, attribute, value);
+   RETURN_EGL_EVAL(disp, ret);
 }
 
 
@@ -350,34 +394,37 @@ EGLContext EGLAPIENTRY
 eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_list,
                  const EGLint *attrib_list)
 {
-   _EGLDisplay *disp = _eglLookupDisplay(dpy);
+   _EGLDisplay *disp = _eglLockDisplay(dpy);
    _EGLConfig *conf = _eglLookupConfig(config, disp);
    _EGLContext *share = _eglLookupContext(share_list, disp);
    _EGLDriver *drv;
    _EGLContext *context;
+   EGLContext ret;
 
-   drv = _eglCheckConfig(disp, conf, __FUNCTION__);
-   if (!drv)
-      return EGL_NO_CONTEXT;
-   if (!share && share_list != EGL_NO_CONTEXT) {
-      _eglError(EGL_BAD_CONTEXT, __FUNCTION__);
-      return EGL_NO_CONTEXT;
-   }
+   _EGL_CHECK_CONFIG(disp, conf, EGL_NO_CONTEXT, drv);
+   if (!share && share_list != EGL_NO_CONTEXT)
+      RETURN_EGL_ERROR(disp, EGL_BAD_CONTEXT, EGL_NO_CONTEXT);
 
    context = drv->API.CreateContext(drv, disp, conf, share, attrib_list);
-   if (context)
-      return _eglLinkContext(context, disp);
-   else
-      return EGL_NO_CONTEXT;
+   ret = (context) ? _eglLinkContext(context, disp) : EGL_NO_CONTEXT;
+
+   RETURN_EGL_EVAL(disp, ret);
 }
 
 
 EGLBoolean EGLAPIENTRY
 eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
 {
-   _EGL_DECLARE_DD_AND_CONTEXT(dpy, ctx);
+   _EGLDisplay *disp = _eglLockDisplay(dpy);
+   _EGLContext *context = _eglLookupContext(ctx, disp);
+   _EGLDriver *drv;
+   EGLBoolean ret;
+
+   _EGL_CHECK_CONTEXT(disp, context, EGL_FALSE, drv);
    _eglUnlinkContext(context);
-   return drv->API.DestroyContext(drv, disp, context);
+   ret = drv->API.DestroyContext(drv, disp, context);
+
+   RETURN_EGL_EVAL(disp, ret);
 }
 
 
@@ -385,22 +432,35 @@ EGLBoolean EGLAPIENTRY
 eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read,
                EGLContext ctx)
 {
-   _EGLDisplay *disp = _eglLookupDisplay(dpy);
+   _EGLDisplay *disp = _eglLockDisplay(dpy);
    _EGLContext *context = _eglLookupContext(ctx, disp);
    _EGLSurface *draw_surf = _eglLookupSurface(draw, disp);
    _EGLSurface *read_surf = _eglLookupSurface(read, disp);
    _EGLDriver *drv;
+   EGLBoolean ret;
+
+   if (!disp)
+      RETURN_EGL_ERROR(disp, EGL_BAD_DISPLAY, EGL_FALSE);
+   drv = disp->Driver;
 
-   drv = _eglCheckDisplay(disp, __FUNCTION__);
+   /* display is allowed to be uninitialized under certain condition */
+   if (!disp->Initialized) {
+      if (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE ||
+          ctx != EGL_NO_CONTEXT)
+         RETURN_EGL_ERROR(disp, EGL_BAD_DISPLAY, EGL_FALSE);
+   }
    if (!drv)
-      return EGL_FALSE;
+      RETURN_EGL_SUCCESS(disp, EGL_TRUE);
+
    if (!context && ctx != EGL_NO_CONTEXT)
-      return _eglError(EGL_BAD_CONTEXT, __FUNCTION__);
+      RETURN_EGL_ERROR(disp, EGL_BAD_CONTEXT, EGL_FALSE);
    if ((!draw_surf && draw != EGL_NO_SURFACE) ||
        (!read_surf && read != EGL_NO_SURFACE))
-      return _eglError(EGL_BAD_SURFACE, __FUNCTION__);
+      RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE);
+
+   ret = drv->API.MakeCurrent(drv, disp, draw_surf, read_surf, context);
 
-   return drv->API.MakeCurrent(drv, disp, draw_surf, read_surf, context);
+   RETURN_EGL_EVAL(disp, ret);
 }
 
 
@@ -408,50 +468,53 @@ EGLBoolean EGLAPIENTRY
 eglQueryContext(EGLDisplay dpy, EGLContext ctx,
                 EGLint attribute, EGLint *value)
 {
-   _EGL_DECLARE_DD_AND_CONTEXT(dpy, ctx);
-   return drv->API.QueryContext(drv, disp, context, attribute, value);
+   _EGLDisplay *disp = _eglLockDisplay(dpy);
+   _EGLContext *context = _eglLookupContext(ctx, disp);
+   _EGLDriver *drv;
+   EGLBoolean ret;
+
+   _EGL_CHECK_CONTEXT(disp, context, EGL_FALSE, drv);
+   ret = drv->API.QueryContext(drv, disp, context, attribute, value);
+
+   RETURN_EGL_EVAL(disp, ret);
 }
 
 
 EGLSurface EGLAPIENTRY
 eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config,
-                       NativeWindowType window, const EGLint *attrib_list)
+                       EGLNativeWindowType window, const EGLint *attrib_list)
 {
-   _EGLDisplay *disp = _eglLookupDisplay(dpy);
+   _EGLDisplay *disp = _eglLockDisplay(dpy);
    _EGLConfig *conf = _eglLookupConfig(config, disp);
    _EGLDriver *drv;
    _EGLSurface *surf;
+   EGLSurface ret;
 
-   drv = _eglCheckConfig(disp, conf, __FUNCTION__);
-   if (!drv)
-      return EGL_NO_SURFACE;
+   _EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE, drv);
 
    surf = drv->API.CreateWindowSurface(drv, disp, conf, window, attrib_list);
-   if (surf)
-      return _eglLinkSurface(surf, disp);
-   else
-      return EGL_NO_SURFACE;
+   ret = (surf) ? _eglLinkSurface(surf, disp) : EGL_NO_SURFACE;
+
+   RETURN_EGL_EVAL(disp, ret);
 }
 
 
 EGLSurface EGLAPIENTRY
 eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config,
-                       NativePixmapType pixmap, const EGLint *attrib_list)
+                       EGLNativePixmapType pixmap, const EGLint *attrib_list)
 {
-   _EGLDisplay *disp = _eglLookupDisplay(dpy);
+   _EGLDisplay *disp = _eglLockDisplay(dpy);
    _EGLConfig *conf = _eglLookupConfig(config, disp);
    _EGLDriver *drv;
    _EGLSurface *surf;
+   EGLSurface ret;
 
-   drv = _eglCheckConfig(disp, conf, __FUNCTION__);
-   if (!drv)
-      return EGL_NO_SURFACE;
+   _EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE, drv);
 
    surf = drv->API.CreatePixmapSurface(drv, disp, conf, pixmap, attrib_list);
-   if (surf)
-      return _eglLinkSurface(surf, disp);
-   else
-      return EGL_NO_SURFACE;
+   ret = (surf) ? _eglLinkSurface(surf, disp) : EGL_NO_SURFACE;
+
+   RETURN_EGL_EVAL(disp, ret);
 }
 
 
@@ -459,79 +522,118 @@ EGLSurface EGLAPIENTRY
 eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config,
                         const EGLint *attrib_list)
 {
-   _EGLDisplay *disp = _eglLookupDisplay(dpy);
+   _EGLDisplay *disp = _eglLockDisplay(dpy);
    _EGLConfig *conf = _eglLookupConfig(config, disp);
    _EGLDriver *drv;
    _EGLSurface *surf;
+   EGLSurface ret;
 
-   drv = _eglCheckConfig(disp, conf, __FUNCTION__);
-   if (!drv)
-      return EGL_NO_SURFACE;
+   _EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE, drv);
 
    surf = drv->API.CreatePbufferSurface(drv, disp, conf, attrib_list);
-   if (surf)
-      return _eglLinkSurface(surf, disp);
-   else
-      return EGL_NO_SURFACE;
+   ret = (surf) ? _eglLinkSurface(surf, disp) : EGL_NO_SURFACE;
+
+   RETURN_EGL_EVAL(disp, ret);
 }
 
 
 EGLBoolean EGLAPIENTRY
 eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
 {
-   _EGL_DECLARE_DD_AND_SURFACE(dpy, surface);
+   _EGLDisplay *disp = _eglLockDisplay(dpy);
+   _EGLSurface *surf = _eglLookupSurface(surface, disp);
+   _EGLDriver *drv;
+   EGLBoolean ret;
+
+   _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
    _eglUnlinkSurface(surf);
-   return drv->API.DestroySurface(drv, disp, surf);
+   ret = drv->API.DestroySurface(drv, disp, surf);
+
+   RETURN_EGL_EVAL(disp, ret);
 }
 
 EGLBoolean EGLAPIENTRY
 eglQuerySurface(EGLDisplay dpy, EGLSurface surface,
                 EGLint attribute, EGLint *value)
 {
-   _EGL_DECLARE_DD_AND_SURFACE(dpy, surface);
-   return drv->API.QuerySurface(drv, disp, surf, attribute, value);
+   _EGLDisplay *disp = _eglLockDisplay(dpy);
+   _EGLSurface *surf = _eglLookupSurface(surface, disp);
+   _EGLDriver *drv;
+   EGLBoolean ret;
+
+   _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
+   ret = drv->API.QuerySurface(drv, disp, surf, attribute, value);
+
+   RETURN_EGL_EVAL(disp, ret);
 }
 
 EGLBoolean EGLAPIENTRY
 eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface,
                  EGLint attribute, EGLint value)
 {
-   _EGL_DECLARE_DD_AND_SURFACE(dpy, surface);
-   return drv->API.SurfaceAttrib(drv, disp, surf, attribute, value);
+   _EGLDisplay *disp = _eglLockDisplay(dpy);
+   _EGLSurface *surf = _eglLookupSurface(surface, disp);
+   _EGLDriver *drv;
+   EGLBoolean ret;
+
+   _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
+   ret = drv->API.SurfaceAttrib(drv, disp, surf, attribute, value);
+
+   RETURN_EGL_EVAL(disp, ret);
 }
 
 
 EGLBoolean EGLAPIENTRY
 eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
 {
-   _EGL_DECLARE_DD_AND_SURFACE(dpy, surface);
-   return drv->API.BindTexImage(drv, disp, surf, buffer);
+   _EGLDisplay *disp = _eglLockDisplay(dpy);
+   _EGLSurface *surf = _eglLookupSurface(surface, disp);
+   _EGLDriver *drv;
+   EGLBoolean ret;
+
+   _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
+   ret = drv->API.BindTexImage(drv, disp, surf, buffer);
+
+   RETURN_EGL_EVAL(disp, ret);
 }
 
 
 EGLBoolean EGLAPIENTRY
 eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
 {
-   _EGL_DECLARE_DD_AND_SURFACE(dpy, surface);
-   return drv->API.ReleaseTexImage(drv, disp, surf, buffer);
+   _EGLDisplay *disp = _eglLockDisplay(dpy);
+   _EGLSurface *surf = _eglLookupSurface(surface, disp);
+   _EGLDriver *drv;
+   EGLBoolean ret;
+
+   _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
+   ret = drv->API.ReleaseTexImage(drv, disp, surf, buffer);
+
+   RETURN_EGL_EVAL(disp, ret);
 }
 
 
 EGLBoolean EGLAPIENTRY
 eglSwapInterval(EGLDisplay dpy, EGLint interval)
 {
+   _EGLDisplay *disp = _eglLockDisplay(dpy);
    _EGLContext *ctx = _eglGetCurrentContext();
    _EGLSurface *surf;
-   _EGL_DECLARE_DD(dpy);
+   _EGLDriver *drv;
+   EGLBoolean ret;
+
+   _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
 
-   if (!ctx || !_eglIsContextLinked(ctx) || ctx->Display != disp)
-      return _eglError(EGL_BAD_CONTEXT, __FUNCTION__);
+   if (!ctx || !_eglIsContextLinked(ctx) || ctx->Resource.Display != disp)
+      RETURN_EGL_ERROR(disp, EGL_BAD_CONTEXT, EGL_FALSE);
 
    surf = ctx->DrawSurface;
    if (!_eglIsSurfaceLinked(surf))
-      return _eglError(EGL_BAD_SURFACE, __FUNCTION__);
+      RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE);
 
-   return drv->API.SwapInterval(drv, disp, surf, interval);
+   ret = drv->API.SwapInterval(drv, disp, surf, interval);
+
+   RETURN_EGL_EVAL(disp, ret);
 }
 
 
@@ -539,21 +641,35 @@ EGLBoolean EGLAPIENTRY
 eglSwapBuffers(EGLDisplay dpy, EGLSurface surface)
 {
    _EGLContext *ctx = _eglGetCurrentContext();
-   _EGL_DECLARE_DD_AND_SURFACE(dpy, surface);
+   _EGLDisplay *disp = _eglLockDisplay(dpy);
+   _EGLSurface *surf = _eglLookupSurface(surface, disp);
+   _EGLDriver *drv;
+   EGLBoolean ret;
+
+   _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
 
    /* surface must be bound to current context in EGL 1.4 */
    if (!ctx || !_eglIsContextLinked(ctx) || surf != ctx->DrawSurface)
-      return _eglError(EGL_BAD_SURFACE, __FUNCTION__);
+      RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE);
 
-   return drv->API.SwapBuffers(drv, disp, surf);
+   ret = drv->API.SwapBuffers(drv, disp, surf);
+
+   RETURN_EGL_EVAL(disp, ret);
 }
 
 
 EGLBoolean EGLAPIENTRY
-eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, NativePixmapType target)
+eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target)
 {
-   _EGL_DECLARE_DD_AND_SURFACE(dpy, surface);
-   return drv->API.CopyBuffers(drv, disp, surf, target);
+   _EGLDisplay *disp = _eglLockDisplay(dpy);
+   _EGLSurface *surf = _eglLookupSurface(surface, disp);
+   _EGLDriver *drv;
+   EGLBoolean ret;
+
+   _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
+   ret = drv->API.CopyBuffers(drv, disp, surf, target);
+
+   RETURN_EGL_EVAL(disp, ret);
 }
 
 
@@ -563,19 +679,24 @@ eglWaitClient(void)
    _EGLContext *ctx = _eglGetCurrentContext();
    _EGLDisplay *disp;
    _EGLDriver *drv;
+   EGLBoolean ret;
 
    if (!ctx)
-      return EGL_TRUE;
+      RETURN_EGL_SUCCESS(NULL, EGL_TRUE);
+
+   disp = ctx->Resource.Display;
+   _eglLockMutex(&disp->Mutex);
+
    /* let bad current context imply bad current surface */
    if (!_eglIsContextLinked(ctx) || !_eglIsSurfaceLinked(ctx->DrawSurface))
-      return _eglError(EGL_BAD_CURRENT_SURFACE, __FUNCTION__);
+      RETURN_EGL_ERROR(disp, EGL_BAD_CURRENT_SURFACE, EGL_FALSE);
 
    /* a valid current context implies an initialized current display */
-   disp = ctx->Display;
+   assert(disp->Initialized);
    drv = disp->Driver;
-   assert(drv);
+   ret = drv->API.WaitClient(drv, disp, ctx);
 
-   return drv->API.WaitClient(drv, disp, ctx);
+   RETURN_EGL_EVAL(disp, ret);
 }
 
 
@@ -589,7 +710,7 @@ eglWaitGL(void)
    EGLBoolean ret;
 
    if (api_index != es_index && _eglIsCurrentThreadDummy())
-      return _eglError(EGL_BAD_ALLOC, "eglWaitGL");
+      RETURN_EGL_ERROR(NULL, EGL_BAD_ALLOC, EGL_FALSE);
 
    t->CurrentAPIIndex = es_index;
    ret = eglWaitClient();
@@ -607,27 +728,36 @@ eglWaitNative(EGLint engine)
    _EGLContext *ctx = _eglGetCurrentContext();
    _EGLDisplay *disp;
    _EGLDriver *drv;
+   EGLBoolean ret;
 
    if (!ctx)
-      return EGL_TRUE;
+      RETURN_EGL_SUCCESS(NULL, EGL_TRUE);
+
+   disp = ctx->Resource.Display;
+   _eglLockMutex(&disp->Mutex);
+
    /* let bad current context imply bad current surface */
    if (!_eglIsContextLinked(ctx) || !_eglIsSurfaceLinked(ctx->DrawSurface))
-      return _eglError(EGL_BAD_CURRENT_SURFACE, __FUNCTION__);
+      RETURN_EGL_ERROR(disp, EGL_BAD_CURRENT_SURFACE, EGL_FALSE);
 
    /* a valid current context implies an initialized current display */
-   disp = ctx->Display;
+   assert(disp->Initialized);
    drv = disp->Driver;
-   assert(drv);
+   ret = drv->API.WaitNative(drv, disp, engine);
 
-   return drv->API.WaitNative(drv, disp, engine);
+   RETURN_EGL_EVAL(disp, ret);
 }
 
 
 EGLDisplay EGLAPIENTRY
 eglGetCurrentDisplay(void)
 {
-   _EGLDisplay *dpy = _eglGetCurrentDisplay();
-   return _eglGetDisplayHandle(dpy);
+   _EGLContext *ctx = _eglGetCurrentContext();
+   EGLDisplay ret;
+
+   ret = (ctx) ? _eglGetDisplayHandle(ctx->Resource.Display) : EGL_NO_DISPLAY;
+
+   RETURN_EGL_SUCCESS(NULL, ret);
 }
 
 
@@ -635,7 +765,11 @@ EGLContext EGLAPIENTRY
 eglGetCurrentContext(void)
 {
    _EGLContext *ctx = _eglGetCurrentContext();
-   return _eglGetContextHandle(ctx);
+   EGLContext ret;
+
+   ret = _eglGetContextHandle(ctx);
+
+   RETURN_EGL_SUCCESS(NULL, ret);
 }
 
 
@@ -643,10 +777,12 @@ EGLSurface EGLAPIENTRY
 eglGetCurrentSurface(EGLint readdraw)
 {
    _EGLContext *ctx = _eglGetCurrentContext();
+   EGLint err = EGL_SUCCESS;
    _EGLSurface *surf;
+   EGLSurface ret;
 
    if (!ctx)
-      return EGL_NO_SURFACE;
+      RETURN_EGL_SUCCESS(NULL, EGL_NO_SURFACE);
 
    switch (readdraw) {
    case EGL_DRAW:
@@ -656,12 +792,14 @@ eglGetCurrentSurface(EGLint readdraw)
       surf = ctx->ReadSurface;
       break;
    default:
-      _eglError(EGL_BAD_PARAMETER, __FUNCTION__);
       surf = NULL;
+      err = EGL_BAD_PARAMETER;
       break;
    }
 
-   return _eglGetSurfaceHandle(surf);
+   ret = _eglGetSurfaceHandle(surf);
+
+   RETURN_EGL_ERROR(NULL, err, ret);
 }
 
 
@@ -676,7 +814,8 @@ eglGetError(void)
 }
 
 
-void (* EGLAPIENTRY eglGetProcAddress(const char *procname))()
+__eglMustCastToProperFunctionPointerType EGLAPIENTRY
+eglGetProcAddress(const char *procname)
 {
    static const struct {
       const char *name;
@@ -697,31 +836,44 @@ void (* EGLAPIENTRY eglGetProcAddress(const char *procname))()
       { "eglQueryScreenModeMESA", (_EGLProc) eglQueryScreenModeMESA },
       { "eglQueryModeStringMESA", (_EGLProc) eglQueryModeStringMESA },
 #endif /* EGL_MESA_screen_surface */
+#ifdef EGL_KHR_image_base
+      { "eglCreateImageKHR", (_EGLProc) eglCreateImageKHR },
+      { "eglDestroyImageKHR", (_EGLProc) eglDestroyImageKHR },
+#endif /* EGL_KHR_image_base */
+#ifdef EGL_NOK_swap_region
+      { "eglSwapBuffersRegionNOK", (_EGLProc) eglSwapBuffersRegionNOK },
+#endif
       { NULL, NULL }
    };
    EGLint i;
+   _EGLProc ret;
 
    if (!procname)
-      return NULL;
+      RETURN_EGL_SUCCESS(NULL, NULL);
+
+   ret = NULL;
    if (strncmp(procname, "egl", 3) == 0) {
       for (i = 0; egl_functions[i].name; i++) {
-         if (strcmp(egl_functions[i].name, procname) == 0)
-            return egl_functions[i].function;
+         if (strcmp(egl_functions[i].name, procname) == 0) {
+            ret = egl_functions[i].function;
+            break;
+         }
       }
    }
+   if (ret)
+      RETURN_EGL_SUCCESS(NULL, ret);
 
-   /* preload a driver if there isn't one */
-   if (!_eglGlobal.NumDrivers)
-      _eglPreloadDriver(NULL);
+   _eglPreloadDrivers();
 
    /* now loop over drivers to query their procs */
    for (i = 0; i < _eglGlobal.NumDrivers; i++) {
-      _EGLProc p = _eglGlobal.Drivers[i]->API.GetProcAddress(procname);
-      if (p)
-         return p;
+      _EGLDriver *drv = _eglGlobal.Drivers[i];
+      ret = drv->API.GetProcAddress(drv, procname);
+      if (ret)
+         break;
    }
 
-   return NULL;
+   RETURN_EGL_SUCCESS(NULL, ret);
 }
 
 
@@ -737,9 +889,16 @@ eglChooseModeMESA(EGLDisplay dpy, EGLScreenMESA screen,
                   const EGLint *attrib_list, EGLModeMESA *modes,
                   EGLint modes_size, EGLint *num_modes)
 {
-   _EGL_DECLARE_DD_AND_SCREEN(dpy, screen);
-   return drv->API.ChooseModeMESA(drv, disp, scrn, attrib_list,
-                                  modes, modes_size, num_modes);
+   _EGLDisplay *disp = _eglLockDisplay(dpy);
+   _EGLScreen *scrn = _eglLookupScreen(screen, disp);
+   _EGLDriver *drv;
+   EGLBoolean ret;
+
+   _EGL_CHECK_SCREEN(disp, scrn, EGL_FALSE, drv);
+   ret = drv->API.ChooseModeMESA(drv, disp, scrn, attrib_list,
+         modes, modes_size, num_modes);
+
+   RETURN_EGL_EVAL(disp, ret);
 }
 
 
@@ -747,8 +906,15 @@ EGLBoolean EGLAPIENTRY
 eglGetModesMESA(EGLDisplay dpy, EGLScreenMESA screen, EGLModeMESA *modes,
                 EGLint mode_size, EGLint *num_mode)
 {
-   _EGL_DECLARE_DD_AND_SCREEN(dpy, screen);
-   return drv->API.GetModesMESA(drv, disp, scrn, modes, mode_size, num_mode);
+   _EGLDisplay *disp = _eglLockDisplay(dpy);
+   _EGLScreen *scrn = _eglLookupScreen(screen, disp);
+   _EGLDriver *drv;
+   EGLBoolean ret;
+
+   _EGL_CHECK_SCREEN(disp, scrn, EGL_FALSE, drv);
+   ret = drv->API.GetModesMESA(drv, disp, scrn, modes, mode_size, num_mode);
+
+   RETURN_EGL_EVAL(disp, ret);
 }
 
 
@@ -756,8 +922,15 @@ EGLBoolean EGLAPIENTRY
 eglGetModeAttribMESA(EGLDisplay dpy, EGLModeMESA mode,
                      EGLint attribute, EGLint *value)
 {
-   _EGL_DECLARE_DD_AND_MODE(dpy, mode);
-   return drv->API.GetModeAttribMESA(drv, disp, m, attribute, value);
+   _EGLDisplay *disp = _eglLockDisplay(dpy);
+   _EGLMode *m = _eglLookupMode(mode, disp);
+   _EGLDriver *drv;
+   EGLBoolean ret;
+
+   _EGL_CHECK_MODE(disp, m, EGL_FALSE, drv);
+   ret = drv->API.GetModeAttribMESA(drv, disp, m, attribute, value);
+
+   RETURN_EGL_EVAL(disp, ret);
 }
 
 
@@ -765,20 +938,20 @@ EGLBoolean EGLAPIENTRY
 eglCopyContextMESA(EGLDisplay dpy, EGLContext source, EGLContext dest,
                    EGLint mask)
 {
-   _EGLDisplay *disp = _eglLookupDisplay(dpy);
+   _EGLDisplay *disp = _eglLockDisplay(dpy);
    _EGLContext *source_context = _eglLookupContext(source, disp);
    _EGLContext *dest_context = _eglLookupContext(dest, disp);
    _EGLDriver *drv;
+   EGLBoolean ret;
 
-   drv = _eglCheckContext(disp, source_context, __FUNCTION__);
-   if (!drv || !dest_context) {
-      if (drv)
-         _eglError(EGL_BAD_CONTEXT, __FUNCTION__);
-      return EGL_FALSE;
-   }
+   _EGL_CHECK_CONTEXT(disp, source_context, EGL_FALSE, drv);
+   if (!dest_context)
+      RETURN_EGL_ERROR(disp, EGL_BAD_CONTEXT, EGL_FALSE);
+
+   ret = drv->API.CopyContextMESA(drv, disp,
+         source_context, dest_context, mask);
 
-   return drv->API.CopyContextMESA(drv, disp, source_context, dest_context,
-                                   mask);
+   RETURN_EGL_EVAL(disp, ret);
 }
 
 
@@ -786,9 +959,14 @@ EGLBoolean
 eglGetScreensMESA(EGLDisplay dpy, EGLScreenMESA *screens,
                   EGLint max_screens, EGLint *num_screens)
 {
-   _EGL_DECLARE_DD(dpy);
-   return drv->API.GetScreensMESA(drv, disp, screens,
-                                  max_screens, num_screens);
+   _EGLDisplay *disp = _eglLockDisplay(dpy);
+   _EGLDriver *drv;
+   EGLBoolean ret;
+
+   _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
+   ret = drv->API.GetScreensMESA(drv, disp, screens, max_screens, num_screens);
+
+   RETURN_EGL_EVAL(disp, ret);
 }
 
 
@@ -796,20 +974,18 @@ EGLSurface
 eglCreateScreenSurfaceMESA(EGLDisplay dpy, EGLConfig config,
                            const EGLint *attrib_list)
 {
-   _EGLDisplay *disp = _eglLookupDisplay(dpy);
+   _EGLDisplay *disp = _eglLockDisplay(dpy);
    _EGLConfig *conf = _eglLookupConfig(config, disp);
    _EGLDriver *drv;
    _EGLSurface *surf;
+   EGLSurface ret;
 
-   drv = _eglCheckConfig(disp, conf, __FUNCTION__);
-   if (!drv)
-      return EGL_NO_SURFACE;
+   _EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE, drv);
 
    surf = drv->API.CreateScreenSurfaceMESA(drv, disp, conf, attrib_list);
-   if (surf)
-      return _eglLinkSurface(surf, disp);
-   else
-      return EGL_NO_SURFACE;
+   ret = (surf) ? _eglLinkSurface(surf, disp) : EGL_NO_SURFACE;
+
+   RETURN_EGL_EVAL(disp, ret);
 }
 
 
@@ -817,29 +993,37 @@ EGLBoolean
 eglShowScreenSurfaceMESA(EGLDisplay dpy, EGLint screen,
                          EGLSurface surface, EGLModeMESA mode)
 {
-   _EGLDisplay *disp = _eglLookupDisplay(dpy);
+   _EGLDisplay *disp = _eglLockDisplay(dpy);
    _EGLScreen *scrn = _eglLookupScreen((EGLScreenMESA) screen, disp);
    _EGLSurface *surf = _eglLookupSurface(surface, disp);
    _EGLMode *m = _eglLookupMode(mode, disp);
    _EGLDriver *drv;
+   EGLBoolean ret;
 
-   drv = _eglCheckScreen(disp, scrn, __FUNCTION__);
-   if (!drv)
-      return EGL_FALSE;
+   _EGL_CHECK_SCREEN(disp, scrn, EGL_FALSE, drv);
    if (!surf && surface != EGL_NO_SURFACE)
-      return _eglError(EGL_BAD_SURFACE, __FUNCTION__);
+      RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE);
    if (!m && mode != EGL_NO_MODE_MESA)
-      return _eglError(EGL_BAD_MODE_MESA, __FUNCTION__);
+      RETURN_EGL_ERROR(disp, EGL_BAD_MODE_MESA, EGL_FALSE);
 
-   return drv->API.ShowScreenSurfaceMESA(drv, disp, scrn, surf, m);
+   ret = drv->API.ShowScreenSurfaceMESA(drv, disp, scrn, surf, m);
+
+   RETURN_EGL_EVAL(disp, ret);
 }
 
 
 EGLBoolean
 eglScreenPositionMESA(EGLDisplay dpy, EGLScreenMESA screen, EGLint x, EGLint y)
 {
-   _EGL_DECLARE_DD_AND_SCREEN(dpy, screen);
-   return drv->API.ScreenPositionMESA(drv, disp, scrn, x, y);
+   _EGLDisplay *disp = _eglLockDisplay(dpy);
+   _EGLScreen *scrn = _eglLookupScreen(screen, disp);
+   _EGLDriver *drv;
+   EGLBoolean ret;
+
+   _EGL_CHECK_SCREEN(disp, scrn, EGL_FALSE, drv);
+   ret = drv->API.ScreenPositionMESA(drv, disp, scrn, x, y);
+
+   RETURN_EGL_EVAL(disp, ret);
 }
 
 
@@ -847,8 +1031,15 @@ EGLBoolean
 eglQueryScreenMESA(EGLDisplay dpy, EGLScreenMESA screen,
                    EGLint attribute, EGLint *value)
 {
-   _EGL_DECLARE_DD_AND_SCREEN(dpy, screen);
-   return drv->API.QueryScreenMESA(drv, disp, scrn, attribute, value);
+   _EGLDisplay *disp = _eglLockDisplay(dpy);
+   _EGLScreen *scrn = _eglLookupScreen(screen, disp);
+   _EGLDriver *drv;
+   EGLBoolean ret;
+
+   _EGL_CHECK_SCREEN(disp, scrn, EGL_FALSE, drv);
+   ret = drv->API.QueryScreenMESA(drv, disp, scrn, attribute, value);
+
+   RETURN_EGL_EVAL(disp, ret);
 }
 
 
@@ -856,49 +1047,51 @@ EGLBoolean
 eglQueryScreenSurfaceMESA(EGLDisplay dpy, EGLScreenMESA screen,
                           EGLSurface *surface)
 {
-   _EGLDisplay *disp = _eglLookupDisplay(dpy);
+   _EGLDisplay *disp = _eglLockDisplay(dpy);
    _EGLScreen *scrn = _eglLookupScreen((EGLScreenMESA) screen, disp);
    _EGLDriver *drv;
    _EGLSurface *surf;
+   EGLBoolean ret;
 
-   drv = _eglCheckScreen(disp, scrn, __FUNCTION__);
-   if (!drv)
-      return EGL_FALSE;
-
-   if (drv->API.QueryScreenSurfaceMESA(drv, disp, scrn, &surf) != EGL_TRUE)
-      surf = NULL;
-   if (surface)
+   _EGL_CHECK_SCREEN(disp, scrn, EGL_FALSE, drv);
+   ret = drv->API.QueryScreenSurfaceMESA(drv, disp, scrn, &surf);
+   if (ret && surface)
       *surface = _eglGetSurfaceHandle(surf);
-   return (surf != NULL);
+
+   RETURN_EGL_EVAL(disp, ret);
 }
 
 
 EGLBoolean
 eglQueryScreenModeMESA(EGLDisplay dpy, EGLScreenMESA screen, EGLModeMESA *mode)
 {
-   _EGLDisplay *disp = _eglLookupDisplay(dpy);
+   _EGLDisplay *disp = _eglLockDisplay(dpy);
    _EGLScreen *scrn = _eglLookupScreen((EGLScreenMESA) screen, disp);
    _EGLDriver *drv;
    _EGLMode *m;
+   EGLBoolean ret;
 
-   drv = _eglCheckScreen(disp, scrn, __FUNCTION__);
-   if (!drv)
-      return EGL_FALSE;
-
-   if (drv->API.QueryScreenModeMESA(drv, disp, scrn, &m) != EGL_TRUE)
-      m = NULL;
-   if (mode)
+   _EGL_CHECK_SCREEN(disp, scrn, EGL_FALSE, drv);
+   ret = drv->API.QueryScreenModeMESA(drv, disp, scrn, &m);
+   if (ret && mode)
       *mode = m->Handle;
 
-   return (m != NULL);
+   RETURN_EGL_EVAL(disp, ret);
 }
 
 
 const char *
 eglQueryModeStringMESA(EGLDisplay dpy, EGLModeMESA mode)
 {
-   _EGL_DECLARE_DD_AND_MODE(dpy, mode);
-   return drv->API.QueryModeStringMESA(drv, disp, m);
+   _EGLDisplay *disp = _eglLockDisplay(dpy);
+   _EGLMode *m = _eglLookupMode(mode, disp);
+   _EGLDriver *drv;
+   const char *ret;
+
+   _EGL_CHECK_MODE(disp, m, NULL, drv);
+   ret = drv->API.QueryModeStringMESA(drv, disp, m);
+
+   RETURN_EGL_EVAL(disp, ret);
 }
 
 
@@ -929,13 +1122,14 @@ eglBindAPI(EGLenum api)
    _EGLThreadInfo *t = _eglGetCurrentThread();
 
    if (_eglIsCurrentThreadDummy())
-      return _eglError(EGL_BAD_ALLOC, "eglBindAPI");
+      RETURN_EGL_ERROR(NULL, EGL_BAD_ALLOC, EGL_FALSE);
 
    if (!_eglIsApiValid(api))
-      return _eglError(EGL_BAD_PARAMETER, "eglBindAPI");
+      RETURN_EGL_ERROR(NULL, EGL_BAD_PARAMETER, EGL_FALSE);
 
    t->CurrentAPIIndex = _eglConvertApiToIndex(api);
-   return EGL_TRUE;
+
+   RETURN_EGL_SUCCESS(NULL, EGL_TRUE);
 }
 
 
@@ -945,9 +1139,13 @@ eglBindAPI(EGLenum api)
 EGLenum
 eglQueryAPI(void)
 {
-   /* returns one of EGL_OPENGL_API, EGL_OPENGL_ES_API or EGL_OPENVG_API */
    _EGLThreadInfo *t = _eglGetCurrentThread();
-   return _eglConvertApiFromIndex(t->CurrentAPIIndex);
+   EGLenum ret;
+
+   /* returns one of EGL_OPENGL_API, EGL_OPENGL_ES_API or EGL_OPENVG_API */
+   ret = _eglConvertApiFromIndex(t->CurrentAPIIndex);
+
+   RETURN_EGL_SUCCESS(NULL, ret);
 }
 
 
@@ -956,40 +1154,129 @@ eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype,
                                  EGLClientBuffer buffer, EGLConfig config,
                                  const EGLint *attrib_list)
 {
-   _EGLDisplay *disp = _eglLookupDisplay(dpy);
+   _EGLDisplay *disp = _eglLockDisplay(dpy);
    _EGLConfig *conf = _eglLookupConfig(config, disp);
    _EGLDriver *drv;
    _EGLSurface *surf;
+   EGLSurface ret;
 
-   drv = _eglCheckConfig(disp, conf, __FUNCTION__);
-   if (!drv)
-      return EGL_NO_SURFACE;
+   _EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE, drv);
 
    surf = drv->API.CreatePbufferFromClientBuffer(drv, disp, buftype, buffer,
                                                  conf, attrib_list);
-   if (surf)
-      return _eglLinkSurface(surf, disp);
-   else
-      return EGL_NO_SURFACE;
+   ret = (surf) ? _eglLinkSurface(surf, disp) : EGL_NO_SURFACE;
+
+   RETURN_EGL_EVAL(disp, ret);
 }
 
 
 EGLBoolean
 eglReleaseThread(void)
 {
-   /* unbind current context */
+   /* unbind current contexts */
    if (!_eglIsCurrentThreadDummy()) {
-      _EGLDisplay *disp = _eglGetCurrentDisplay();
-      _EGLDriver *drv;
-      if (disp) {
-         drv = disp->Driver;
-         (void) drv->API.MakeCurrent(drv, disp, NULL, NULL, NULL);
+      _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;
+
+            _eglLockMutex(&disp->Mutex);
+            drv = disp->Driver;
+            (void) drv->API.MakeCurrent(drv, disp, NULL, NULL, NULL);
+            _eglUnlockMutex(&disp->Mutex);
+         }
       }
+
+      t->CurrentAPIIndex = api_index;
    }
 
    _eglDestroyCurrentThread();
-   return EGL_TRUE;
+
+   RETURN_EGL_SUCCESS(NULL, EGL_TRUE);
 }
 
 
 #endif /* EGL_VERSION_1_2 */
+
+
+#ifdef EGL_KHR_image_base
+
+
+EGLImageKHR
+eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target,
+                  EGLClientBuffer buffer, const EGLint *attr_list)
+{
+   _EGLDisplay *disp = _eglLockDisplay(dpy);
+   _EGLContext *context = _eglLookupContext(ctx, disp);
+   _EGLDriver *drv;
+   _EGLImage *img;
+   EGLImageKHR ret;
+
+   _EGL_CHECK_DISPLAY(disp, EGL_NO_IMAGE_KHR, drv);
+   if (!context && ctx != EGL_NO_CONTEXT)
+      RETURN_EGL_ERROR(disp, EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR);
+
+   img = drv->API.CreateImageKHR(drv,
+         disp, context, target, buffer, attr_list);
+   ret = (img) ? _eglLinkImage(img, disp) : EGL_NO_IMAGE_KHR;
+
+   RETURN_EGL_EVAL(disp, ret);
+}
+
+
+EGLBoolean
+eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR image)
+{
+   _EGLDisplay *disp = _eglLockDisplay(dpy);
+   _EGLImage *img = _eglLookupImage(image, disp);
+   _EGLDriver *drv;
+   EGLBoolean ret;
+
+   _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
+   if (!img)
+      RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
+
+   _eglUnlinkImage(img);
+   ret = drv->API.DestroyImageKHR(drv, disp, img);
+
+   RETURN_EGL_EVAL(disp, ret);
+}
+
+
+#endif /* EGL_KHR_image_base */
+
+
+#ifdef EGL_NOK_swap_region
+
+EGLBoolean
+eglSwapBuffersRegionNOK(EGLDisplay dpy, EGLSurface surface,
+                       EGLint numRects, const EGLint *rects)
+{
+   _EGLContext *ctx = _eglGetCurrentContext();
+   _EGLDisplay *disp = _eglLockDisplay(dpy);
+   _EGLSurface *surf = _eglLookupSurface(surface, disp);
+   _EGLDriver *drv;
+   EGLBoolean ret;
+
+   _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
+
+   /* surface must be bound to current context in EGL 1.4 */
+   if (!ctx || !_eglIsContextLinked(ctx) || surf != ctx->DrawSurface)
+      RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE);
+
+   if (drv->API.SwapBuffersRegionNOK)
+      ret = drv->API.SwapBuffersRegionNOK(drv, disp, surf, numRects, rects);
+   else
+      ret = drv->API.SwapBuffers(drv, disp, surf);
+
+   RETURN_EGL_EVAL(disp, ret);
+}
+
+#endif /* EGL_NOK_swap_region */