egl: add and enable EGL_KHR_config_attribs
[mesa.git] / src / egl / main / eglcontext.c
index 70277ab9db60e4c5f9b9afbcbfd8a9ec291883e3..60625f64705c67d90c00964ac26f4bfd45ef5542 100644 (file)
@@ -101,11 +101,42 @@ _eglParseContextAttribList(_EGLContext *ctx, _EGLDisplay *dpy,
 
       switch (attr) {
       case EGL_CONTEXT_CLIENT_VERSION:
+         /* The EGL 1.4 spec says:
+          *
+          *     "attribute EGL_CONTEXT_CLIENT_VERSION is only valid when the
+          *      current rendering API is EGL_OPENGL_ES_API"
+          *
+          * The EGL_KHR_create_context spec says:
+          *
+          *     "EGL_CONTEXT_MAJOR_VERSION_KHR           0x3098
+          *      (this token is an alias for EGL_CONTEXT_CLIENT_VERSION)"
+          *
+          *     "The values for attributes EGL_CONTEXT_MAJOR_VERSION_KHR and
+          *      EGL_CONTEXT_MINOR_VERSION_KHR specify the requested client API
+          *      version. They are only meaningful for OpenGL and OpenGL ES
+          *      contexts, and specifying them for other types of contexts will
+          *      generate an error."
+          */
+         if ((api != EGL_OPENGL_ES_API &&
+             (!dpy->Extensions.KHR_create_context || api != EGL_OPENGL_API))) {
+               err = EGL_BAD_ATTRIBUTE;
+               break;
+         }
+
          ctx->ClientMajorVersion = val;
          break;
 
       case EGL_CONTEXT_MINOR_VERSION_KHR:
-         if (!dpy->Extensions.KHR_create_context) {
+         /* The EGL_KHR_create_context spec says:
+          *
+          *     "The values for attributes EGL_CONTEXT_MAJOR_VERSION_KHR and
+          *      EGL_CONTEXT_MINOR_VERSION_KHR specify the requested client API
+          *      version. They are only meaningful for OpenGL and OpenGL ES
+          *      contexts, and specifying them for other types of contexts will
+          *      generate an error."
+          */
+         if (!dpy->Extensions.KHR_create_context ||
+             (api != EGL_OPENGL_ES_API && api != EGL_OPENGL_API)) {
             err = EGL_BAD_ATTRIBUTE;
             break;
          }
@@ -121,17 +152,56 @@ _eglParseContextAttribList(_EGLContext *ctx, _EGLDisplay *dpy,
 
          /* The EGL_KHR_create_context spec says:
           *
-          *     "Flags are only defined for OpenGL context creation, and
-          *     specifying a flags value other than zero for other types of
-          *     contexts, including OpenGL ES contexts, will generate an
-          *     error."
+          *     "If the EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR flag bit is set in
+          *     EGL_CONTEXT_FLAGS_KHR, then a <debug context> will be created.
+          *     [...]
+          *     In some cases a debug context may be identical to a non-debug
+          *     context. This bit is supported for OpenGL and OpenGL ES
+          *     contexts."
           */
-         if (api != EGL_OPENGL_API && val != 0) {
+         if ((val & EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR) &&
+             (api != EGL_OPENGL_API && api != EGL_OPENGL_ES_API)) {
             err = EGL_BAD_ATTRIBUTE;
             break;
          }
 
-         ctx->Flags = val;
+         /* The EGL_KHR_create_context spec says:
+          *
+          *     "If the EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR flag bit
+          *     is set in EGL_CONTEXT_FLAGS_KHR, then a <forward-compatible>
+          *     context will be created. Forward-compatible contexts are
+          *     defined only for OpenGL versions 3.0 and later. They must not
+          *     support functionality marked as <deprecated> by that version of
+          *     the API, while a non-forward-compatible context must support
+          *     all functionality in that version, deprecated or not. This bit
+          *     is supported for OpenGL contexts, and requesting a
+          *     forward-compatible context for OpenGL versions less than 3.0
+          *     will generate an error."
+          */
+         if ((val & EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR) &&
+             (api != EGL_OPENGL_API || ctx->ClientMajorVersion < 3)) {
+            err = EGL_BAD_ATTRIBUTE;
+            break;
+         }
+
+         /* The EGL_KHR_create_context_spec says:
+          *
+          *     "If the EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR bit is set in
+          *     EGL_CONTEXT_FLAGS_KHR, then a context supporting <robust buffer
+          *     access> will be created. Robust buffer access is defined in the
+          *     GL_ARB_robustness extension specification, and the resulting
+          *     context must also support either the GL_ARB_robustness
+          *     extension, or a version of OpenGL incorporating equivalent
+          *     functionality. This bit is supported for OpenGL contexts.
+          */
+         if ((val & EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR) &&
+             (api != EGL_OPENGL_API ||
+              !dpy->Extensions.EXT_create_context_robustness)) {
+            err = EGL_BAD_ATTRIBUTE;
+            break;
+         }
+
+         ctx->Flags |= val;
          break;
 
       case EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR:
@@ -194,7 +264,38 @@ _eglParseContextAttribList(_EGLContext *ctx, _EGLDisplay *dpy,
             break;
          }
 
-         ctx->Flags = EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR;
+         if (val == EGL_TRUE)
+            ctx->Flags |= EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR;
+         break;
+
+      case EGL_CONTEXT_OPENGL_ROBUST_ACCESS:
+         if (dpy->Version < 15) {
+            err = EGL_BAD_ATTRIBUTE;
+            break;
+         }
+
+         if (val == EGL_TRUE)
+            ctx->Flags |= EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR;
+         break;
+
+      case EGL_CONTEXT_OPENGL_DEBUG:
+         if (dpy->Version < 15) {
+            err = EGL_BAD_ATTRIBUTE;
+            break;
+         }
+
+         if (val == EGL_TRUE)
+            ctx->Flags |= EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR;
+         break;
+
+      case EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE:
+         if (dpy->Version < 15) {
+            err = EGL_BAD_ATTRIBUTE;
+            break;
+         }
+
+         if (val == EGL_TRUE)
+            ctx->Flags |= EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR;
          break;
 
       default:
@@ -322,11 +423,14 @@ _eglParseContextAttribList(_EGLContext *ctx, _EGLDisplay *dpy,
          break;
 
       case 3:
-      default:
          /* Don't put additional version checks here.  We don't know that
           * there won't be versions > 3.0.
           */
          break;
+
+      default:
+         err = EGL_BAD_MATCH;
+         break;
       }
    }
 
@@ -353,6 +457,16 @@ _eglParseContextAttribList(_EGLContext *ctx, _EGLDisplay *dpy,
 /**
  * Initialize the given _EGLContext object to defaults and/or the values
  * in the attrib_list.
+ *
+ * According to EGL 1.5 Section 3.7:
+ *
+ *     "EGL_OPENGL_API and EGL_OPENGL_ES_API are interchangeable for all
+ *     purposes except eglCreateContext."
+ *
+ * And since we only support GL and GLES, this is the only place where the
+ * bound API matters at all. We look up the current API from the current
+ * thread, and stash that in the context we're initializing. Our caller is
+ * responsible for determining whether that's an API it supports.
  */
 EGLBoolean
 _eglInitContext(_EGLContext *ctx, _EGLDisplay *dpy, _EGLConfig *conf,
@@ -424,9 +538,14 @@ _eglQueryContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *c,
 
    switch (attribute) {
    case EGL_CONFIG_ID:
-      if (!c->Config)
-         return _eglError(EGL_BAD_ATTRIBUTE, "eglQueryContext");
-      *value = c->Config->ConfigID;
+      /*
+       * From EGL_KHR_no_config_context:
+       *
+       *    "Querying EGL_CONFIG_ID returns the ID of the EGLConfig with
+       *     respect to which the context was created, or zero if created
+       *     without respect to an EGLConfig."
+       */
+      *value = c->Config ? c->Config->ConfigID : 0;
       break;
    case EGL_CONTEXT_CLIENT_VERSION:
       *value = c->ClientMajorVersion;
@@ -453,20 +572,16 @@ _eglQueryContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *c,
 static _EGLContext *
 _eglBindContextToThread(_EGLContext *ctx, _EGLThreadInfo *t)
 {
-   EGLint apiIndex;
    _EGLContext *oldCtx;
 
-   apiIndex = (ctx) ?
-      _eglConvertApiToIndex(ctx->ClientAPI) : t->CurrentAPIIndex;
-
-   oldCtx = t->CurrentContexts[apiIndex];
+   oldCtx = t->CurrentContext;
    if (ctx != oldCtx) {
       if (oldCtx)
          oldCtx->Binding = NULL;
       if (ctx)
          ctx->Binding = t;
 
-      t->CurrentContexts[apiIndex] = ctx;
+      t->CurrentContext = ctx;
    }
 
    return oldCtx;
@@ -481,7 +596,6 @@ _eglCheckMakeCurrent(_EGLContext *ctx, _EGLSurface *draw, _EGLSurface *read)
 {
    _EGLThreadInfo *t = _eglGetCurrentThread();
    _EGLDisplay *dpy;
-   EGLint conflict_api;
 
    if (_eglIsCurrentThreadDummy())
       return _eglError(EGL_BAD_ALLOC, "eglMakeCurrent");
@@ -513,13 +627,11 @@ _eglCheckMakeCurrent(_EGLContext *ctx, _EGLSurface *draw, _EGLSurface *read)
    if (ctx->Binding && ctx->Binding != t)
       return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");
    if (draw && draw->CurrentContext && draw->CurrentContext != ctx) {
-      if (draw->CurrentContext->Binding != t ||
-          draw->CurrentContext->ClientAPI != ctx->ClientAPI)
+      if (draw->CurrentContext->Binding != t)
          return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");
    }
    if (read && read->CurrentContext && read->CurrentContext != ctx) {
-      if (read->CurrentContext->Binding != t ||
-          read->CurrentContext->ClientAPI != ctx->ClientAPI)
+      if (read->CurrentContext->Binding != t)
          return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");
    }
 
@@ -530,9 +642,9 @@ _eglCheckMakeCurrent(_EGLContext *ctx, _EGLSurface *draw, _EGLSurface *read)
           (read && read->Config != ctx->Config))
          return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
    } else {
-      /* Otherwise we must be using the EGL_MESA_configless_context
+      /* Otherwise we must be using the EGL_KHR_no_config_context
        * extension */
-      assert(dpy->Extensions.MESA_configless_context);
+      assert(dpy->Extensions.KHR_no_config_context);
 
       /* The extension doesn't permit binding draw and read buffers with
        * differing contexts */
@@ -540,22 +652,6 @@ _eglCheckMakeCurrent(_EGLContext *ctx, _EGLSurface *draw, _EGLSurface *read)
          return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
    }
 
-   switch (ctx->ClientAPI) {
-   /* OpenGL and OpenGL ES are conflicting */
-   case EGL_OPENGL_ES_API:
-      conflict_api = EGL_OPENGL_API;
-      break;
-   case EGL_OPENGL_API:
-      conflict_api = EGL_OPENGL_ES_API;
-      break;
-   default:
-      conflict_api = -1;
-      break;
-   }
-
-   if (conflict_api >= 0 && _eglGetAPIContext(conflict_api))
-      return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");
-
    return EGL_TRUE;
 }