Blame SOURCES/Allow-setting-up-quad-buffer-stereo-output.patch

3e8236
From 55f30d3240ad636519e1fcc5a579b7d5cba0ed5f Mon Sep 17 00:00:00 2001
3e8236
From: "Owen W. Taylor" <otaylor@fishsoup.net>
3e8236
Date: Thu, 8 May 2014 18:52:09 -0400
3e8236
Subject: [PATCH] Allow setting up quad-buffer stereo output
3e8236
3e8236
Add clutter_x11_set_use_stereo_stage() that can be called
3e8236
before clutter_init() so that the CoglDisplay we create and all
3e8236
stages created from that CoglDisplay will be created with a
3e8236
stereo fbconfig.
3e8236
3e8236
This is done in clutter-x11 because of the similarity to the
3e8236
existing clutter_x11_set_use_argb_visual(), and because it's
3e8236
not clear without other examples whether the need to have
3e8236
stereo enabled from before clutter_init() is universal or
3e8236
somethign specific to GLX.
3e8236
3e8236
https://bugzilla.gnome.org/show_bug.cgi?id=732706
3e8236
---
3e8236
 clutter/x11/clutter-backend-x11.c | 170 +++++++++++++++++++++++++++++---------
3e8236
 clutter/x11/clutter-x11.h         |   3 +
3e8236
 2 files changed, 133 insertions(+), 40 deletions(-)
3e8236
3e8236
diff --git a/clutter/x11/clutter-backend-x11.c b/clutter/x11/clutter-backend-x11.c
3e8236
index b7cfcc4..bba21e7 100644
3e8236
--- a/clutter/x11/clutter-backend-x11.c
3e8236
+++ b/clutter/x11/clutter-backend-x11.c
3e8236
@@ -96,6 +96,7 @@ static const gchar *atom_names[] = {
3e8236
 static gboolean _no_xevent_retrieval = FALSE;
3e8236
 static gboolean clutter_enable_xinput = TRUE;
3e8236
 static gboolean clutter_enable_argb = FALSE;
3e8236
+static gboolean clutter_enable_stereo = FALSE;
3e8236
 static Display  *_foreign_dpy = NULL;
3e8236
 
3e8236
 /* options */
3e8236
@@ -706,6 +707,59 @@ clutter_backend_x11_get_renderer (ClutterBackend  *backend,
3e8236
   return renderer;
3e8236
 }
3e8236
 
3e8236
+static gboolean
3e8236
+check_onscreen_template (CoglRenderer         *renderer,
3e8236
+                         CoglSwapChain        *swap_chain,
3e8236
+                         CoglOnscreenTemplate *onscreen_template,
3e8236
+                         CoglBool              enable_argb,
3e8236
+                         CoglBool              enable_stereo,
3e8236
+                         GError              **error)
3e8236
+{
3e8236
+  GError *internal_error = NULL;
3e8236
+
3e8236
+  cogl_swap_chain_set_has_alpha (swap_chain, enable_argb);
3e8236
+  cogl_onscreen_template_set_stereo_enabled (onscreen_template,
3e8236
+					     clutter_enable_stereo);
3e8236
+
3e8236
+  /* cogl_renderer_check_onscreen_template() is actually just a
3e8236
+   * shorthand for creating a CoglDisplay, and calling
3e8236
+   * cogl_display_setup() on it, then throwing the display away. If we
3e8236
+   * could just return that display, then it would be more efficient
3e8236
+   * not to use cogl_renderer_check_onscreen_template(). However, the
3e8236
+   * backend API requires that we return an CoglDisplay that has not
3e8236
+   * yet been setup, so one way or the other we'll have to discard the
3e8236
+   * first display and make a new fresh one.
3e8236
+   */
3e8236
+  if (cogl_renderer_check_onscreen_template (renderer, onscreen_template, &internal_error))
3e8236
+    {
3e8236
+      clutter_enable_argb = enable_argb;
3e8236
+      clutter_enable_stereo = enable_stereo;
3e8236
+
3e8236
+      return TRUE;
3e8236
+    }
3e8236
+  else
3e8236
+    {
3e8236
+      if (enable_argb || enable_stereo) /* More possibilities to try */
3e8236
+        CLUTTER_NOTE (BACKEND,
3e8236
+                      "Creation of a CoglDisplay with alpha=%s, stereo=%s failed: %s",
3e8236
+                      enable_argb ? "enabled" : "disabled",
3e8236
+                      enable_stereo ? "enabled" : "disabled",
3e8236
+                      internal_error != NULL
3e8236
+                        ?  internal_error->message
3e8236
+                        : "Unknown reason");
3e8236
+      else
3e8236
+        g_set_error_literal (error, CLUTTER_INIT_ERROR,
3e8236
+                             CLUTTER_INIT_ERROR_BACKEND,
3e8236
+                             internal_error != NULL
3e8236
+                               ? internal_error->message
3e8236
+                               : "Creation of a CoglDisplay failed");
3e8236
+
3e8236
+      g_clear_error (&internal_error);
3e8236
+
3e8236
+      return FALSE;
3e8236
+    }
3e8236
+}
3e8236
+
3e8236
 static CoglDisplay *
3e8236
 clutter_backend_x11_get_display (ClutterBackend  *backend,
3e8236
                                  CoglRenderer    *renderer,
3e8236
@@ -713,56 +767,38 @@ clutter_backend_x11_get_display (ClutterBackend  *backend,
3e8236
                                  GError         **error)
3e8236
 {
3e8236
   CoglOnscreenTemplate *onscreen_template;
3e8236
-  GError *internal_error = NULL;
3e8236
-  CoglDisplay *display;
3e8236
-  gboolean res;
3e8236
-
3e8236
-  CLUTTER_NOTE (BACKEND, "Alpha on Cogl swap chain: %s",
3e8236
-                clutter_enable_argb ? "enabled" : "disabled");
3e8236
+  CoglDisplay *display = NULL;
3e8236
+  gboolean res = FALSE;
3e8236
 
3e8236
-  cogl_swap_chain_set_has_alpha (swap_chain, clutter_enable_argb);
3e8236
+  CLUTTER_NOTE (BACKEND, "Creating CoglDisplay, alpha=%s, stereo=%s",
3e8236
+                clutter_enable_argb ? "enabled" : "disabled",
3e8236
+                clutter_enable_stereo ? "enabled" : "disabled");
3e8236
 
3e8236
   onscreen_template = cogl_onscreen_template_new (swap_chain);
3e8236
 
3e8236
-  res = cogl_renderer_check_onscreen_template (renderer,
3e8236
-                                               onscreen_template,
3e8236
-                                               &internal_error);
3e8236
-  if (!res && clutter_enable_argb)
3e8236
-    {
3e8236
-      CLUTTER_NOTE (BACKEND,
3e8236
-                    "Creation of a context with a ARGB visual failed: %s",
3e8236
-                    internal_error != NULL ? internal_error->message
3e8236
-                                           : "Unknown reason");
3e8236
+  /* It's possible that the current renderer doesn't support transparency
3e8236
+   * or doesn't support stereo, so we try the different combinations.
3e8236
+   */
3e8236
+  if (clutter_enable_argb && clutter_enable_stereo)
3e8236
+    res = check_onscreen_template (renderer, swap_chain, onscreen_template,
3e8236
+                                  TRUE, TRUE, error);
3e8236
 
3e8236
-      g_clear_error (&internal_error);
3e8236
+  /* Prioritize stereo over alpha */
3e8236
+  if (!res && clutter_enable_stereo)
3e8236
+    res = check_onscreen_template (renderer, swap_chain, onscreen_template,
3e8236
+                                  FALSE, TRUE, error);
3e8236
 
3e8236
-      /* It's possible that the current renderer doesn't support transparency
3e8236
-       * in a swap_chain so lets see if we can fallback to not having any
3e8236
-       * transparency...
3e8236
-       *
3e8236
-       * XXX: It might be nice to have a CoglRenderer feature we could
3e8236
-       * explicitly check for ahead of time.
3e8236
-       */
3e8236
-      clutter_enable_argb = FALSE;
3e8236
-      cogl_swap_chain_set_has_alpha (swap_chain, FALSE);
3e8236
-      res = cogl_renderer_check_onscreen_template (renderer,
3e8236
-                                                   onscreen_template,
3e8236
-                                                   &internal_error);
3e8236
-    }
3e8236
+  if (!res && clutter_enable_argb)
3e8236
+    res = check_onscreen_template (renderer, swap_chain, onscreen_template,
3e8236
+                                  TRUE, FALSE, error);
3e8236
 
3e8236
   if (!res)
3e8236
-    {
3e8236
-      g_set_error_literal (error, CLUTTER_INIT_ERROR,
3e8236
-                           CLUTTER_INIT_ERROR_BACKEND,
3e8236
-                           internal_error->message);
3e8236
+    res = check_onscreen_template (renderer, swap_chain, onscreen_template,
3e8236
+                                  FALSE, FALSE, error);
3e8236
 
3e8236
-      g_error_free (internal_error);
3e8236
-      cogl_object_unref (onscreen_template);
3e8236
+  if (res)
3e8236
+    display = cogl_display_new (renderer, onscreen_template);
3e8236
 
3e8236
-      return NULL;
3e8236
-    }
3e8236
-
3e8236
-  display = cogl_display_new (renderer, onscreen_template);
3e8236
   cogl_object_unref (onscreen_template);
3e8236
 
3e8236
   return display;
3e8236
@@ -1309,6 +1345,60 @@ clutter_x11_get_use_argb_visual (void)
3e8236
   return clutter_enable_argb;
3e8236
 }
3e8236
 
3e8236
+/**
3e8236
+ * clutter_x11_set_use_stereo_stage:
3e8236
+ * @use_stereo: %TRUE if the stereo stages should be used if possible.
3e8236
+ *
3e8236
+ * Sets whether the backend object for Clutter stages, will,
3e8236
+ * if possible, be created with the ability to support stereo drawing
3e8236
+ * (drawing separate images for the left and right eyes).
3e8236
+ *
3e8236
+ * This function must be called before clutter_init() is called.
3e8236
+ * During paint callbacks, cogl_framebuffer_is_stereo() can be called
3e8236
+ * on the framebuffer retrieved by cogl_get_draw_framebuffer() to
3e8236
+ * determine if stereo support was successfully enabled, and
3e8236
+ * cogl_framebuffer_set_stereo_mode() to determine which buffers
3e8236
+ * will be drawn to.
3e8236
+ *
3e8236
+ * Note that this function *does not* cause the stage to be drawn
3e8236
+ * multiple times with different perspective transformations and thus
3e8236
+ * appear in 3D, it simply enables individual ClutterActors to paint
3e8236
+ * different images for the left and and right eye.
3e8236
+ *
3e8236
+ * Since: 1.20
3e8236
+ */
3e8236
+void
3e8236
+clutter_x11_set_use_stereo_stage (gboolean use_stereo)
3e8236
+{
3e8236
+  if (_clutter_context_is_initialized ())
3e8236
+    {
3e8236
+      g_warning ("%s() can only be used before calling clutter_init()",
3e8236
+                 G_STRFUNC);
3e8236
+      return;
3e8236
+    }
3e8236
+
3e8236
+  CLUTTER_NOTE (BACKEND, "STEREO stages are %s",
3e8236
+                use_stereo ? "enabled" : "disabled");
3e8236
+
3e8236
+  clutter_enable_stereo = use_stereo;
3e8236
+}
3e8236
+
3e8236
+/**
3e8236
+ * clutter_x11_get_use_stereo_stage:
3e8236
+ *
3e8236
+ * Retrieves whether the Clutter X11 backend will create stereo
3e8236
+ * stages if possible.
3e8236
+ *
3e8236
+ * Return value: %TRUE if stereo stages are used if possible
3e8236
+ *
3e8236
+ * Since: 1.20
3e8236
+ */
3e8236
+gboolean
3e8236
+clutter_x11_get_use_stereo_stage (void)
3e8236
+{
3e8236
+  return clutter_enable_stereo;
3e8236
+}
3e8236
+
3e8236
 XVisualInfo *
3e8236
 _clutter_backend_x11_get_visual_info (ClutterBackendX11 *backend_x11)
3e8236
 {
3e8236
diff --git a/clutter/x11/clutter-x11.h b/clutter/x11/clutter-x11.h
3e8236
index 6913280..efcd37e 100644
3e8236
--- a/clutter/x11/clutter-x11.h
3e8236
+++ b/clutter/x11/clutter-x11.h
3e8236
@@ -137,6 +137,9 @@ gboolean clutter_x11_has_composite_extension (void);
3e8236
 void     clutter_x11_set_use_argb_visual (gboolean use_argb);
3e8236
 gboolean clutter_x11_get_use_argb_visual (void);
3e8236
 
3e8236
+void     clutter_x11_set_use_stereo_stage (gboolean use_stereo);
3e8236
+gboolean clutter_x11_get_use_stereo_stage (void);
3e8236
+
3e8236
 Time clutter_x11_get_current_event_time (void);
3e8236
 
3e8236
 gint clutter_x11_event_get_key_group (const ClutterEvent *event);
3e8236
-- 
3e8236
1.9.3
3e8236