egl: Update headers.
[mesa.git] / src / egl / main / eglapi.c
index 29617b7afff0b164eb1210a0438c6d1aa9590566..e57ce211b84fd78a0146d896a308d4eaf3d7fcd7 100644 (file)
@@ -9,12 +9,36 @@
  * heterogeneous hardware devices in the future.
  *
  * The EGLDisplay, EGLConfig, EGLContext and EGLSurface types are
- * opaque handles implemented with 32-bit unsigned integers.
- * It's up to the driver function or fallback function to look up the
- * handle and get an object.
- * By using opaque handles, we leave open the possibility of having
- * indirect rendering in the future, like GLX.
+ * opaque handles. Internal objects are linked to a display to
+ * create the handles.
  *
+ * For each public API entry point, the opaque handles are looked up
+ * before being dispatched to the drivers.  When it fails to look up
+ * a handle, one of
+ *
+ * EGL_BAD_DISPLAY
+ * EGL_BAD_CONFIG
+ * EGL_BAD_CONTEXT
+ * EGL_BAD_SURFACE
+ * EGL_BAD_SCREEN_MESA
+ * EGL_BAD_MODE_MESA
+ *
+ * is generated and the driver function is not called. An
+ * uninitialized EGLDisplay has no driver associated with it. When
+ * such display is detected,
+ *
+ * EGL_NOT_INITIALIZED
+ *
+ * is generated.
+ *
+ * Some of the entry points use current display, context, or surface
+ * implicitly.  For such entry points, the implicit objects are also
+ * checked before calling the driver function.  Other than the
+ * errors listed above,
+ *
+ * EGL_BAD_CURRENT_SURFACE
+ *
+ * may also be generated.
  *
  * Notes on naming conventions:
  *
@@ -77,6 +101,8 @@ eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
 
    drv = disp->Driver;
    if (!drv) {
+      _eglPreloadDrivers();
+
       drv = _eglOpenDriver(disp);
       if (!drv)
          return _eglError(EGL_NOT_INITIALIZED, __FUNCTION__);
@@ -92,8 +118,8 @@ eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
       snprintf(disp->Version, sizeof(disp->Version),
                "%d.%d (%s)", major_int, minor_int, drv->Name);
 
-      /* update the global notion of supported APIs */
-      _eglGlobal.ClientAPIsMask |= disp->ClientAPIsMask;
+      /* limit to APIs supported by core */
+      disp->ClientAPIsMask &= _EGL_API_ALL_BITS;
 
       disp->Driver = drv;
    } else {
@@ -496,15 +522,31 @@ eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
 EGLBoolean EGLAPIENTRY
 eglSwapInterval(EGLDisplay dpy, EGLint interval)
 {
+   _EGLContext *ctx = _eglGetCurrentContext();
+   _EGLSurface *surf;
    _EGL_DECLARE_DD(dpy);
-   return drv->API.SwapInterval(drv, disp, interval);
+
+   if (!ctx || !_eglIsContextLinked(ctx) || ctx->Resource.Display != disp)
+      return _eglError(EGL_BAD_CONTEXT, __FUNCTION__);
+
+   surf = ctx->DrawSurface;
+   if (!_eglIsSurfaceLinked(surf))
+      return _eglError(EGL_BAD_SURFACE, __FUNCTION__);
+
+   return drv->API.SwapInterval(drv, disp, surf, interval);
 }
 
 
 EGLBoolean EGLAPIENTRY
 eglSwapBuffers(EGLDisplay dpy, EGLSurface surface)
 {
+   _EGLContext *ctx = _eglGetCurrentContext();
    _EGL_DECLARE_DD_AND_SURFACE(dpy, surface);
+
+   /* 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 drv->API.SwapBuffers(drv, disp, surf);
 }
 
@@ -518,32 +560,66 @@ eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, NativePixmapType target)
 
 
 EGLBoolean EGLAPIENTRY
-eglWaitGL(void)
+eglWaitClient(void)
 {
-   _EGLDisplay *disp = _eglGetCurrentDisplay();
+   _EGLContext *ctx = _eglGetCurrentContext();
+   _EGLDisplay *disp;
    _EGLDriver *drv;
 
-   if (!disp)
+   if (!ctx)
       return EGL_TRUE;
+   /* let bad current context imply bad current surface */
+   if (!_eglIsContextLinked(ctx) || !_eglIsSurfaceLinked(ctx->DrawSurface))
+      return _eglError(EGL_BAD_CURRENT_SURFACE, __FUNCTION__);
 
-   /* a current display is always initialized */
+   /* a valid current context implies an initialized current display */
+   disp = ctx->Resource.Display;
    drv = disp->Driver;
+   assert(drv);
 
-   return drv->API.WaitGL(drv, disp);
+   return drv->API.WaitClient(drv, disp, ctx);
+}
+
+
+EGLBoolean EGLAPIENTRY
+eglWaitGL(void)
+{
+#ifdef EGL_VERSION_1_2
+   _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 _eglError(EGL_BAD_ALLOC, "eglWaitGL");
+
+   t->CurrentAPIIndex = es_index;
+   ret = eglWaitClient();
+   t->CurrentAPIIndex = api_index;
+   return ret;
+#else
+   return eglWaitClient();
+#endif
 }
 
 
 EGLBoolean EGLAPIENTRY
 eglWaitNative(EGLint engine)
 {
-   _EGLDisplay *disp = _eglGetCurrentDisplay();
+   _EGLContext *ctx = _eglGetCurrentContext();
+   _EGLDisplay *disp;
    _EGLDriver *drv;
 
-   if (!disp)
+   if (!ctx)
       return EGL_TRUE;
+   /* let bad current context imply bad current surface */
+   if (!_eglIsContextLinked(ctx) || !_eglIsSurfaceLinked(ctx->DrawSurface))
+      return _eglError(EGL_BAD_CURRENT_SURFACE, __FUNCTION__);
 
-   /* a current display is always initialized */
+   /* a valid current context implies an initialized current display */
+   disp = ctx->Resource.Display;
    drv = disp->Driver;
+   assert(drv);
 
    return drv->API.WaitNative(drv, disp, engine);
 }
@@ -568,8 +644,26 @@ eglGetCurrentContext(void)
 EGLSurface EGLAPIENTRY
 eglGetCurrentSurface(EGLint readdraw)
 {
-   _EGLSurface *s = _eglGetCurrentSurface(readdraw);
-   return _eglGetSurfaceHandle(s);
+   _EGLContext *ctx = _eglGetCurrentContext();
+   _EGLSurface *surf;
+
+   if (!ctx)
+      return EGL_NO_SURFACE;
+
+   switch (readdraw) {
+   case EGL_DRAW:
+      surf = ctx->DrawSurface;
+      break;
+   case EGL_READ:
+      surf = ctx->ReadSurface;
+      break;
+   default:
+      _eglError(EGL_BAD_PARAMETER, __FUNCTION__);
+      surf = NULL;
+      break;
+   }
+
+   return _eglGetSurfaceHandle(surf);
 }
 
 
@@ -584,45 +678,14 @@ eglGetError(void)
 }
 
 
-void (* EGLAPIENTRY eglGetProcAddress(const char *procname))()
+__eglMustCastToProperFunctionPointerType EGLAPIENTRY
+eglGetProcAddress(const char *procname)
 {
-   typedef void (*genericFunc)();
-   struct name_function {
+   static const struct {
       const char *name;
       _EGLProc function;
-   };
-   static struct name_function egl_functions[] = {
-      /* alphabetical order */
-      { "eglBindTexImage", (_EGLProc) eglBindTexImage },
-      { "eglChooseConfig", (_EGLProc) eglChooseConfig },
-      { "eglCopyBuffers", (_EGLProc) eglCopyBuffers },
-      { "eglCreateContext", (_EGLProc) eglCreateContext },
-      { "eglCreatePbufferSurface", (_EGLProc) eglCreatePbufferSurface },
-      { "eglCreatePixmapSurface", (_EGLProc) eglCreatePixmapSurface },
-      { "eglCreateWindowSurface", (_EGLProc) eglCreateWindowSurface },
-      { "eglDestroyContext", (_EGLProc) eglDestroyContext },
-      { "eglDestroySurface", (_EGLProc) eglDestroySurface },
-      { "eglGetConfigAttrib", (_EGLProc) eglGetConfigAttrib },
-      { "eglGetConfigs", (_EGLProc) eglGetConfigs },
-      { "eglGetCurrentContext", (_EGLProc) eglGetCurrentContext },
-      { "eglGetCurrentDisplay", (_EGLProc) eglGetCurrentDisplay },
-      { "eglGetCurrentSurface", (_EGLProc) eglGetCurrentSurface },
-      { "eglGetDisplay", (_EGLProc) eglGetDisplay },
-      { "eglGetError", (_EGLProc) eglGetError },
-      { "eglGetProcAddress", (_EGLProc) eglGetProcAddress },
-      { "eglInitialize", (_EGLProc) eglInitialize },
-      { "eglMakeCurrent", (_EGLProc) eglMakeCurrent },
-      { "eglQueryContext", (_EGLProc) eglQueryContext },
-      { "eglQueryString", (_EGLProc) eglQueryString },
-      { "eglQuerySurface", (_EGLProc) eglQuerySurface },
-      { "eglReleaseTexImage", (_EGLProc) eglReleaseTexImage },
-      { "eglSurfaceAttrib", (_EGLProc) eglSurfaceAttrib },
-      { "eglSwapBuffers", (_EGLProc) eglSwapBuffers },
-      { "eglSwapInterval", (_EGLProc) eglSwapInterval },
-      { "eglTerminate", (_EGLProc) eglTerminate },
-      { "eglWaitGL", (_EGLProc) eglWaitGL },
-      { "eglWaitNative", (_EGLProc) eglWaitNative },
-      /* Extensions */
+   } egl_functions[] = {
+      /* extensions only */
 #ifdef EGL_MESA_screen_surface
       { "eglChooseModeMESA", (_EGLProc) eglChooseModeMESA },
       { "eglGetModesMESA", (_EGLProc) eglGetModesMESA },
@@ -637,25 +700,25 @@ void (* EGLAPIENTRY eglGetProcAddress(const char *procname))()
       { "eglQueryScreenModeMESA", (_EGLProc) eglQueryScreenModeMESA },
       { "eglQueryModeStringMESA", (_EGLProc) eglQueryModeStringMESA },
 #endif /* EGL_MESA_screen_surface */
-#ifdef EGL_VERSION_1_2
-      { "eglBindAPI", (_EGLProc) eglBindAPI },
-      { "eglCreatePbufferFromClientBuffer", (_EGLProc) eglCreatePbufferFromClientBuffer },
-      { "eglQueryAPI", (_EGLProc) eglQueryAPI },
-      { "eglReleaseThread", (_EGLProc) eglReleaseThread },
-      { "eglWaitClient", (_EGLProc) eglWaitClient },
-#endif /* EGL_VERSION_1_2 */
       { NULL, NULL }
    };
    EGLint i;
-   for (i = 0; egl_functions[i].name; i++) {
-      if (strcmp(egl_functions[i].name, procname) == 0) {
-         return (genericFunc) egl_functions[i].function;
+
+   if (!procname)
+      return 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;
       }
    }
 
+   _eglPreloadDrivers();
+
    /* now loop over drivers to query their procs */
    for (i = 0; i < _eglGlobal.NumDrivers; i++) {
-      _EGLProc p = _eglGlobal.Drivers[i]->API.GetProcAddress(procname);
+      _EGLDriver *drv = _eglGlobal.Drivers[i];
+      _EGLProc p = drv->API.GetProcAddress(drv, procname);
       if (p)
          return p;
    }
@@ -664,6 +727,9 @@ void (* EGLAPIENTRY eglGetProcAddress(const char *procname))()
 }
 
 
+#ifdef EGL_MESA_screen_surface
+
+
 /*
  * EGL_MESA_screen extension
  */
@@ -838,6 +904,9 @@ eglQueryModeStringMESA(EGLDisplay dpy, EGLModeMESA mode)
 }
 
 
+#endif /* EGL_MESA_screen_surface */
+
+
 /**
  ** EGL 1.2
  **/
@@ -867,33 +936,7 @@ eglBindAPI(EGLenum api)
    if (!_eglIsApiValid(api))
       return _eglError(EGL_BAD_PARAMETER, "eglBindAPI");
 
-   switch (api) {
-#ifdef EGL_VERSION_1_4
-   case EGL_OPENGL_API:
-      if (_eglGlobal.ClientAPIsMask & EGL_OPENGL_BIT) {
-         t->CurrentAPIIndex = _eglConvertApiToIndex(api);
-         return EGL_TRUE;
-      }
-      _eglError(EGL_BAD_PARAMETER, "eglBindAPI");
-      return EGL_FALSE;
-#endif
-   case EGL_OPENGL_ES_API:
-      if (_eglGlobal.ClientAPIsMask & (EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT)) {
-         t->CurrentAPIIndex = _eglConvertApiToIndex(api);
-         return EGL_TRUE;
-      }
-      _eglError(EGL_BAD_PARAMETER, "eglBindAPI");
-      return EGL_FALSE;
-   case EGL_OPENVG_API:
-      if (_eglGlobal.ClientAPIsMask & EGL_OPENVG_BIT) {
-         t->CurrentAPIIndex = _eglConvertApiToIndex(api);
-         return EGL_TRUE;
-      }
-      _eglError(EGL_BAD_PARAMETER, "eglBindAPI");
-      return EGL_FALSE;
-   default:
-      return EGL_FALSE;
-   }
+   t->CurrentAPIIndex = _eglConvertApiToIndex(api);
    return EGL_TRUE;
 }
 
@@ -951,20 +994,4 @@ eglReleaseThread(void)
 }
 
 
-EGLBoolean
-eglWaitClient(void)
-{
-   _EGLDisplay *disp = _eglGetCurrentDisplay();
-   _EGLDriver *drv;
-
-   if (!disp)
-      return EGL_TRUE;
-
-   /* a current display is always initialized */
-   drv = disp->Driver;
-
-   return drv->API.WaitClient(drv, disp);
-}
-
-
 #endif /* EGL_VERSION_1_2 */