Calling dl_can_open() to determine whether the API is supported is
confusing and somewhat incorrect.

Instead, determine the supported APIs based on the string provided by
eglQueryString(EGL_CLIENT_APIS) and cross that with the minimum EGL
requirement (for eglBindAPI) for each one.

Note: we're added a minimum requirement of EGL 1.2 as things will
explode badly with versions prior to it.

v2: Completely reword commit message, finish implementation.
v3: Keep get_apis() and get_extensions() separate. Use mask for the API.

Signed-off-by: Emil Velikov <emil.l.veli...@gmail.com>
---
 src/waffle/egl/wegl_config.c  | 43 +++++++++++---------------------
 src/waffle/egl/wegl_display.c | 58 ++++++++++++++++++++++++++++++++-----------
 src/waffle/egl/wegl_display.h |  6 +++++
 3 files changed, 63 insertions(+), 44 deletions(-)

diff --git a/src/waffle/egl/wegl_config.c b/src/waffle/egl/wegl_config.c
index 08e06fb..37fbe65 100644
--- a/src/waffle/egl/wegl_config.c
+++ b/src/waffle/egl/wegl_config.c
@@ -41,8 +41,6 @@ static bool
 check_context_attrs(struct wegl_display *dpy,
                     const struct wcore_config_attrs *attrs)
 {
-    struct wcore_platform *plat = dpy->wcore.platform;
-
     if (attrs->context_forward_compatible) {
         assert(attrs->context_api == WAFFLE_CONTEXT_OPENGL);
         assert(wcore_config_attrs_version_ge(attrs, 30));
@@ -76,6 +74,14 @@ check_context_attrs(struct wegl_display *dpy,
 
     switch (attrs->context_api) {
         case WAFFLE_CONTEXT_OPENGL:
+            if (!(dpy->api_mask & WEGL_OPENGL_API)) {
+                wcore_errorf(WAFFLE_ERROR_UNSUPPORTED_ON_PLATFORM,
+                             "EGL 1.4 and eglQueryString(EGL_CLIENT_APIS) "
+                             "advertising \"OpenGL\" are required in order to "
+                             "request an OpenGL context.");
+                return false;
+            }
+
             if (!wcore_config_attrs_version_eq(attrs, 10) && 
!dpy->KHR_create_context) {
                 wcore_errorf(WAFFLE_ERROR_UNSUPPORTED_ON_PLATFORM,
                              "KHR_EXT_create_context is required in order to "
@@ -96,46 +102,25 @@ check_context_attrs(struct wegl_display *dpy,
                 return false;
             }
 
-            if (!plat->vtbl->dl_can_open(plat, WAFFLE_DL_OPENGL)) {
-                wcore_errorf(WAFFLE_ERROR_UNSUPPORTED_ON_PLATFORM,
-                             "failed to open the OpenGL library");
-                return false;
-            }
-
             return true;
 
         case WAFFLE_CONTEXT_OPENGL_ES1:
-            if (!plat->vtbl->dl_can_open(plat, WAFFLE_DL_OPENGL_ES1)) {
-                wcore_errorf(WAFFLE_ERROR_UNSUPPORTED_ON_PLATFORM,
-                             "failed to open the OpenGL ES1 library");
-                return false;
-            }
-
-            return true;
-
         case WAFFLE_CONTEXT_OPENGL_ES2:
-            if (!plat->vtbl->dl_can_open(plat, WAFFLE_DL_OPENGL_ES2)) {
+        case WAFFLE_CONTEXT_OPENGL_ES3:
+            if (!(dpy->api_mask & WEGL_OPENGL_ES_API)) {
                 wcore_errorf(WAFFLE_ERROR_UNSUPPORTED_ON_PLATFORM,
-                             "failed to open the OpenGL ES2 library");
+                             "eglQueryString(EGL_CLIENT_APIS) does not"
+                             "advertise OpenGL_ES.");
                 return false;
             }
-
-            return true;
-
-        case WAFFLE_CONTEXT_OPENGL_ES3:
-            if (!dpy->KHR_create_context) {
+            if (attrs->context_api == WAFFLE_CONTEXT_OPENGL_ES3 &&
+                !dpy->KHR_create_context) {
                 wcore_errorf(WAFFLE_ERROR_UNSUPPORTED_ON_PLATFORM,
                              "EGL_KHR_create_context is required to request "
                              "an OpenGL ES3 context");
                 return false;
             }
 
-            if (!plat->vtbl->dl_can_open(plat, WAFFLE_DL_OPENGL_ES3)) {
-                wcore_errorf(WAFFLE_ERROR_UNSUPPORTED_ON_PLATFORM,
-                             "failed to open the OpenGL ES3 library");
-                return false;
-            }
-
             return true;
 
         default:
diff --git a/src/waffle/egl/wegl_display.c b/src/waffle/egl/wegl_display.c
index c7be0a5..d5f6deb 100644
--- a/src/waffle/egl/wegl_display.c
+++ b/src/waffle/egl/wegl_display.c
@@ -34,6 +34,41 @@
 #include "wegl_platform.h"
 
 static bool
+get_apis(struct wegl_display *dpy)
+{
+    struct wegl_platform *plat = wegl_platform(dpy->wcore.platform);
+    const char *apis = plat->eglQueryString(dpy->egl, EGL_CLIENT_APIS);
+
+    // Our minimum requirement - EGL 1.2 ...
+    if (dpy->major_version != 1 || dpy->minor_version < 2) {
+        wcore_errorf(WAFFLE_ERROR_UNSUPPORTED_ON_PLATFORM,
+                     "EGL 1.2 or later is required");
+        return false;
+    }
+
+    // ... plus working eglQueryString(EGL_CLIENT_APIS).
+    if (!apis) {
+        wegl_emit_error(plat, "eglQueryString(EGL_CLIENT_APIS)");
+        return false;
+    }
+
+    // waffle_is_extension_in_string() resets the error state. That's ok,
+    // however, because if we've reached this point then no error should be
+    // pending emission.
+    assert(wcore_error_get_code() == 0);
+
+    if (waffle_is_extension_in_string(apis, "OpenGL_ES"))
+        dpy->api_mask |= WEGL_OPENGL_ES_API;
+
+    // Check for "OpenGL" if we're running EGL 1.4 or later.
+    if (dpy->major_version == 1 && dpy->minor_version >= 4)
+        if (waffle_is_extension_in_string(apis, "OpenGL"))
+            dpy->api_mask |= WEGL_OPENGL_API;
+
+    return true;
+}
+
+static bool
 get_extensions(struct wegl_display *dpy)
 {
     struct wegl_platform *plat = wegl_platform(dpy->wcore.platform);
@@ -81,6 +116,10 @@ wegl_display_init(struct wegl_display *dpy,
         goto fail;
     }
 
+    ok = get_apis(dpy);
+    if (!ok)
+        goto fail;
+
     ok = get_extensions(dpy);
     if (!ok)
         goto fail;
@@ -112,30 +151,19 @@ wegl_display_supports_context_api(struct wcore_display 
*wc_dpy,
                                   int32_t waffle_context_api)
 {
     struct wegl_display *dpy = wegl_display(wc_dpy);
-    struct wcore_platform *wc_plat = dpy->wcore.platform;
-    int32_t waffle_dl;
 
     switch (waffle_context_api) {
         case WAFFLE_CONTEXT_OPENGL:
-            waffle_dl = WAFFLE_DL_OPENGL;
-            break;
+            return !!(dpy->api_mask & WEGL_OPENGL_API);
         case WAFFLE_CONTEXT_OPENGL_ES1:
-            waffle_dl = WAFFLE_DL_OPENGL_ES1;
-            break;
         case WAFFLE_CONTEXT_OPENGL_ES2:
-            waffle_dl = WAFFLE_DL_OPENGL_ES2;
-            break;
+            return !!(dpy->api_mask & WEGL_OPENGL_ES_API);
         case WAFFLE_CONTEXT_OPENGL_ES3:
-            if (!dpy->KHR_create_context)
-                return false;
-
-            waffle_dl = WAFFLE_DL_OPENGL_ES3;
-            break;
+            return !!(dpy->api_mask & WEGL_OPENGL_ES_API) &&
+                   dpy->KHR_create_context;
         default:
             wcore_error_internal("waffle_context_api has bad value %#x",
                                  waffle_context_api);
             return false;
     }
-
-    return wc_plat->vtbl->dl_can_open(wc_plat, waffle_dl);
 }
diff --git a/src/waffle/egl/wegl_display.h b/src/waffle/egl/wegl_display.h
index 0d03ec8..348399d 100644
--- a/src/waffle/egl/wegl_display.h
+++ b/src/waffle/egl/wegl_display.h
@@ -34,9 +34,15 @@
 
 struct wcore_display;
 
+enum wegl_supported_api {
+    WEGL_OPENGL_API = 1 << 0,
+    WEGL_OPENGL_ES_API = 1 << 1,
+};
+
 struct wegl_display {
     struct wcore_display wcore;
     EGLDisplay egl;
+    enum wegl_supported_api api_mask;
     bool EXT_create_context_robustness;
     bool KHR_create_context;
     EGLint major_version;
-- 
2.8.0


_______________________________________________
waffle mailing list
waffle@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/waffle

Reply via email to