wayland: check for egl extensions explicitly
authornobled <nobled@dreamwidth.org>
Tue, 8 Feb 2011 15:45:39 +0000 (15:45 +0000)
committernobled <nobled@dreamwidth.org>
Tue, 8 Feb 2011 16:15:09 +0000 (16:15 +0000)
eglGetProcAddress() returns non-null function pointers
whether or not they're actually supported by the driver,
since it can be used before any driver gets loaded. So
we have to check if the extensions are advertised first,
which requires having an initialized display, so we split
the display creation code into its own function.

The exception to extension-checking is EGL_MESA_drm_display,
since by definition it's needed before any display is even
created.

clutter/wayland/clutter-backend-wayland.c

index 1763c13..c96a245 100644 (file)
@@ -182,11 +182,42 @@ display_handle_global (struct wl_display *display,
 }
 
 static gboolean
+try_get_display (ClutterBackendWayland *backend_wayland, GError **error)
+{
+  EGLDisplay edpy = EGL_NO_DISPLAY;
+  int drm_fd;
+
+  drm_fd = open (backend_wayland->device_name, O_RDWR);
+
+  backend_wayland->get_drm_display =
+    (PFNEGLGETDRMDISPLAYMESA) eglGetProcAddress ("eglGetDRMDisplayMESA");
+
+  if (backend_wayland->get_drm_display != NULL && drm_fd >= 0)
+     edpy = backend_wayland->get_drm_display (drm_fd);
+
+  if (edpy == EGL_NO_DISPLAY)
+      edpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+
+  if (edpy == EGL_NO_DISPLAY)
+    {
+      g_set_error (error, CLUTTER_INIT_ERROR,
+                  CLUTTER_INIT_ERROR_BACKEND,
+                  "Failed to open EGLDisplay");
+      return FALSE;
+    }
+
+  backend_wayland->edpy   = edpy;
+  backend_wayland->drm_fd = drm_fd;
+
+  return TRUE;
+}
+
+static gboolean
 try_enable_drm (ClutterBackendWayland *backend_wayland, GError **error)
 {
   drm_magic_t magic;
+  const gchar *exts, *glexts;
 
-  backend_wayland->drm_fd = open (backend_wayland->device_name, O_RDWR);
   if (backend_wayland->drm_fd < 0)
     {
       g_set_error (error, CLUTTER_INIT_ERROR,
@@ -195,21 +226,19 @@ try_enable_drm (ClutterBackendWayland *backend_wayland, GError **error)
       return FALSE;
     }
 
-  if (drmGetMagic (backend_wayland->drm_fd, &magic))
+  glexts = glGetString(GL_EXTENSIONS);
+  exts = eglQueryString (backend_wayland->edpy, EGL_EXTENSIONS);
+
+  if (!_cogl_check_extension ("EGL_KHR_image_base", exts) ||
+      !_cogl_check_extension ("EGL_MESA_drm_image", exts) ||
+      !_cogl_check_extension ("GL_OES_EGL_image", glexts))
     {
       g_set_error (error, CLUTTER_INIT_ERROR,
                   CLUTTER_INIT_ERROR_BACKEND,
-                  "Failed to get drm magic");
+                  "Missing EGL extensions");
       return FALSE;
     }
 
-  wl_drm_authenticate (backend_wayland->wayland_drm, magic);
-  wl_display_iterate (backend_wayland->wayland_display, WL_DISPLAY_WRITABLE);
-  while (!backend_wayland->authenticated)
-    wl_display_iterate (backend_wayland->wayland_display, WL_DISPLAY_READABLE);
-
-  backend_wayland->get_drm_display =
-    (PFNEGLGETDRMDISPLAYMESA) eglGetProcAddress ("eglGetDRMDisplayMESA");
   backend_wayland->create_drm_image =
     (PFNEGLCREATEDRMIMAGEMESA) eglGetProcAddress ("eglCreateDRMImageMESA");
   backend_wayland->destroy_image =
@@ -219,8 +248,7 @@ try_enable_drm (ClutterBackendWayland *backend_wayland, GError **error)
   backend_wayland->image_target_texture_2d =
     (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) eglGetProcAddress ("glEGLImageTargetTexture2DOES");
 
-  if (backend_wayland->get_drm_display == NULL ||
-      backend_wayland->create_drm_image == NULL ||
+  if (backend_wayland->create_drm_image == NULL ||
       backend_wayland->destroy_image == NULL ||
       backend_wayland->export_drm_image == NULL ||
       backend_wayland->image_target_texture_2d == NULL)
@@ -231,8 +259,18 @@ try_enable_drm (ClutterBackendWayland *backend_wayland, GError **error)
       return FALSE;
     }
 
-  backend_wayland->edpy =
-    backend_wayland->get_drm_display (backend_wayland->drm_fd);
+  if (drmGetMagic (backend_wayland->drm_fd, &magic))
+    {
+      g_set_error (error, CLUTTER_INIT_ERROR,
+                  CLUTTER_INIT_ERROR_BACKEND,
+                  "Failed to get drm magic");
+      return FALSE;
+    }
+
+  wl_drm_authenticate (backend_wayland->wayland_drm, magic);
+  wl_display_iterate (backend_wayland->wayland_display, WL_DISPLAY_WRITABLE);
+  while (!backend_wayland->authenticated)
+    wl_display_iterate (backend_wayland->wayland_display, WL_DISPLAY_READABLE);
 
   return TRUE;
 };
@@ -268,16 +306,8 @@ clutter_backend_wayland_post_parse (ClutterBackend  *backend,
   /* Process connection events. */
   wl_display_iterate (backend_wayland->wayland_display, WL_DISPLAY_READABLE);
 
-  backend_wayland->drm_enabled = try_enable_drm(backend_wayland, error);
-
-  if (!backend_wayland->drm_enabled) {
-    if (backend_wayland->wayland_shm == NULL)
-      return FALSE;
-
-    g_debug("Could not enable DRM buffers, falling back to SHM buffers");
-    g_clear_error(error);
-    backend_wayland->edpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
-  }
+  if (!try_get_display(backend_wayland, error))
+    return FALSE;
 
   status = eglInitialize (backend_wayland->edpy,
                          &backend_wayland->egl_version_major,
@@ -294,6 +324,16 @@ clutter_backend_wayland_post_parse (ClutterBackend  *backend,
                backend_wayland->egl_version_major,
                backend_wayland->egl_version_minor);
 
+  backend_wayland->drm_enabled = try_enable_drm(backend_wayland, error);
+
+  if (!backend_wayland->drm_enabled) {
+    if (backend_wayland->wayland_shm == NULL)
+      return FALSE;
+
+    g_debug("Could not enable DRM buffers, falling back to SHM buffers");
+    g_clear_error(error);
+  }
+
   return TRUE;
 }
 
@@ -612,6 +652,7 @@ _clutter_backend_wayland_class_init (ClutterBackendWaylandClass *klass)
 static void
 _clutter_backend_wayland_init (ClutterBackendWayland *backend_wayland)
 {
+  backend_wayland->edpy = EGL_NO_DISPLAY;
   backend_wayland->egl_context = EGL_NO_CONTEXT;
 
   backend_wayland->drm_fd = -1;