Blame SOURCES/0008-Add-support-for-quad-buffer-stereo.patch

e3f29c
From 7940ea62307044c056c16f1534e3e8e94cc7a352 Mon Sep 17 00:00:00 2001
db633a
From: "Owen W. Taylor" <otaylor@fishsoup.net>
db633a
Date: Thu, 8 May 2014 18:44:15 -0400
e3f29c
Subject: [PATCH 7/8] Add support for quad-buffer stereo
db633a
db633a
Track the stereo status of windows using the new EXT_stereo_tree
db633a
GLX extension.
db633a
db633a
When stereo is enabled or disabled, a restart is triggered via
db633a
meta_restart() after a timeout, setting a _META_ENABLE_STEREO
db633a
property on the root window to indicate whether we should
db633a
turn on a stereo stage for clutter. The property avoids a loop,
db633a
since we need to enable stereo *before* initializing Clutter and GL,
db633a
but we need GL to figure out whether we have stereo windows.
db633a
db633a
Stereo windows are drawn to the stage using new functionality
db633a
in Cogl to setup a stereo context, select which buffer to draw
db633a
to, and draw either the left or right buffer of a stereo
db633a
texture_from_pixmap.
db633a
---
db633a
 src/Makefile.am                              |   2 +
db633a
 src/compositor/compositor-private.h          |   9 ++
db633a
 src/compositor/compositor.c                  | 128 ++++++++++++++++++++++
db633a
 src/compositor/meta-shaped-texture-private.h |   5 +-
db633a
 src/compositor/meta-shaped-texture.c         | 157 ++++++++++++++++++++-------
e3f29c
 src/compositor/meta-surface-actor-wayland.c  |  10 +-
db633a
 src/compositor/meta-surface-actor-x11.c      |  56 ++++++++--
db633a
 src/compositor/meta-surface-actor-x11.h      |   5 +
db633a
 src/compositor/meta-window-actor-private.h   |   5 +
db633a
 src/compositor/meta-window-actor.c           |  22 ++++
db633a
 src/core/main.c                              |   4 +
db633a
 src/core/stereo.c                            | 153 ++++++++++++++++++++++++++
db633a
 src/core/stereo.h                            |  28 +++++
e3f29c
 src/wayland/meta-wayland-surface.c           |   2 +-
e3f29c
 14 files changed, 535 insertions(+), 51 deletions(-)
db633a
 create mode 100644 src/core/stereo.c
db633a
 create mode 100644 src/core/stereo.h
db633a
db633a
diff --git a/src/Makefile.am b/src/Makefile.am
e3f29c
index 6aef50de8..8c680602c 100644
db633a
--- a/src/Makefile.am
db633a
+++ b/src/Makefile.am
e3f29c
@@ -281,6 +281,8 @@ libmutter_@LIBMUTTER_API_VERSION@_la_SOURCES =	\
db633a
 	core/stack.h				\
db633a
 	core/stack-tracker.c			\
db633a
 	core/stack-tracker.h			\
db633a
+	core/stereo.c				\
db633a
+	core/stereo.h				\
db633a
 	core/util.c				\
db633a
 	meta/util.h				\
db633a
 	core/util-private.h			\
db633a
diff --git a/src/compositor/compositor-private.h b/src/compositor/compositor-private.h
e3f29c
index ba58bf175..1c257b5ee 100644
db633a
--- a/src/compositor/compositor-private.h
db633a
+++ b/src/compositor/compositor-private.h
db633a
@@ -21,6 +21,10 @@ struct _MetaCompositor
db633a
   gint64          server_time_query_time;
db633a
   gint64          server_time_offset;
db633a
 
db633a
+  int             glx_opcode;
db633a
+  guint           stereo_tree_ext : 1;
db633a
+  guint           have_stereo_windows : 1;
db633a
+
db633a
   guint           server_time_is_monotonic_time : 1;
db633a
   guint           no_mipmaps  : 1;
db633a
 
e3f29c
@@ -61,6 +65,11 @@ void     meta_end_modal_for_plugin   (MetaCompositor   *compositor,
db633a
 gint64 meta_compositor_monotonic_time_to_server_time (MetaDisplay *display,
db633a
                                                       gint64       monotonic_time);
db633a
 
db633a
+gboolean meta_compositor_window_is_stereo     (MetaScreen *screen,
db633a
+                                               Window      xwindow);
db633a
+void     meta_compositor_select_stereo_notify (MetaScreen *screen,
db633a
+                                               Window      xwindow);
db633a
+
db633a
 void meta_compositor_flash_window (MetaCompositor *compositor,
db633a
                                    MetaWindow     *window);
db633a
 
db633a
diff --git a/src/compositor/compositor.c b/src/compositor/compositor.c
e3f29c
index 17e8a55dd..a1bf1a8f8 100644
db633a
--- a/src/compositor/compositor.c
db633a
+++ b/src/compositor/compositor.c
db633a
@@ -70,6 +70,8 @@
db633a
 #include "meta-window-group.h"
db633a
 #include "window-private.h" /* to check window->hidden */
db633a
 #include "display-private.h" /* for meta_display_lookup_x_window() and meta_display_cancel_touch() */
db633a
+#include "stack-tracker.h"
db633a
+#include "stereo.h"
db633a
 #include "util-private.h"
e3f29c
 #include "backends/meta-dnd-private.h"
db633a
 #include "frame.h"
e3f29c
@@ -482,6 +484,97 @@ redirect_windows (MetaScreen *screen)
db633a
     }
db633a
 }
db633a
 
db633a
+#define GLX_STEREO_TREE_EXT        0x20F5
db633a
+#define GLX_STEREO_NOTIFY_MASK_EXT 0x00000001
db633a
+#define GLX_STEREO_NOTIFY_EXT      0x00000000
db633a
+
db633a
+typedef struct {
db633a
+  int type;
db633a
+  unsigned long serial;
db633a
+  Bool send_event;
db633a
+  Display *display;
db633a
+  int extension;
db633a
+  int evtype;
db633a
+  Drawable window;
db633a
+  Bool stereo_tree;
db633a
+} StereoNotifyEvent;
db633a
+
db633a
+static gboolean
db633a
+screen_has_stereo_tree_ext (MetaScreen *screen)
db633a
+{
db633a
+  MetaDisplay *display = meta_screen_get_display (screen);
db633a
+  Display     *xdisplay = meta_display_get_xdisplay (display);
db633a
+  const char  *extensions_string;
db633a
+
db633a
+  static const char * (*query_extensions_string) (Display *display,
db633a
+                                                  int      screen);
db633a
+
db633a
+  if (query_extensions_string == NULL)
db633a
+    query_extensions_string =
db633a
+      (const char * (*) (Display *, int))
db633a
+      cogl_get_proc_address ("glXQueryExtensionsString");
db633a
+
db633a
+  extensions_string = query_extensions_string (xdisplay,
db633a
+                                               meta_screen_get_screen_number (screen));
db633a
+
e3f29c
+  return extensions_string && strstr (extensions_string, "EXT_stereo_tree") != 0;
db633a
+}
db633a
+
db633a
+#include <GL/gl.h>
db633a
+
db633a
+gboolean
db633a
+meta_compositor_window_is_stereo (MetaScreen *screen,
db633a
+                                  Window      xwindow)
db633a
+{
db633a
+  MetaCompositor *compositor = get_compositor_for_screen (screen);
db633a
+  MetaDisplay    *display = meta_screen_get_display (screen);
db633a
+  Display        *xdisplay = meta_display_get_xdisplay (display);
db633a
+
db633a
+  static int (*query_drawable) (Display      *dpy,
db633a
+                                Drawable      draw,
db633a
+                                int           attribute,
db633a
+                                unsigned int *value);
db633a
+
db633a
+  if (compositor->stereo_tree_ext)
db633a
+    {
db633a
+      unsigned int stereo_tree = 0;
db633a
+
db633a
+      if (query_drawable == NULL)
db633a
+        query_drawable =
db633a
+          (int (*) (Display *, Drawable, int, unsigned int *))
db633a
+          cogl_get_proc_address ("glXQueryDrawable");
db633a
+
db633a
+      query_drawable (xdisplay, xwindow, GLX_STEREO_TREE_EXT, &stereo_tree);
db633a
+
db633a
+      return stereo_tree != 0;
db633a
+    }
db633a
+  else
db633a
+    return FALSE;
db633a
+}
db633a
+
db633a
+void
db633a
+meta_compositor_select_stereo_notify (MetaScreen *screen,
db633a
+                                      Window      xwindow)
db633a
+{
db633a
+  MetaCompositor *compositor = get_compositor_for_screen (screen);
db633a
+  MetaDisplay    *display = meta_screen_get_display (screen);
db633a
+  Display        *xdisplay = meta_display_get_xdisplay (display);
db633a
+
db633a
+  static void (*select_event) (Display      *dpy,
db633a
+                               Drawable      draw,
db633a
+                               unsigned long event_mask);
db633a
+
db633a
+  if (compositor->stereo_tree_ext)
db633a
+    {
db633a
+      if (select_event == NULL)
db633a
+        select_event =
db633a
+          (void (*) (Display *, Drawable, unsigned long))
db633a
+          cogl_get_proc_address ("glXSelectEvent");
db633a
+
db633a
+      select_event (xdisplay, xwindow, GLX_STEREO_NOTIFY_MASK_EXT);
db633a
+    }
db633a
+}
db633a
+
db633a
 void
db633a
 meta_compositor_manage (MetaCompositor *compositor)
db633a
 {
e3f29c
@@ -490,6 +583,8 @@ meta_compositor_manage (MetaCompositor *compositor)
db633a
   MetaScreen *screen = display->screen;
db633a
   MetaBackend *backend = meta_get_backend ();
db633a
 
db633a
+  compositor->stereo_tree_ext = screen_has_stereo_tree_ext (screen);
db633a
+
db633a
   meta_screen_set_cm_selection (display->screen);
db633a
 
db633a
   compositor->stage = meta_backend_get_stage (backend);
e3f29c
@@ -757,6 +852,23 @@ meta_compositor_process_event (MetaCompositor *compositor,
db633a
       if (window)
db633a
         process_damage (compositor, (XDamageNotifyEvent *) event, window);
db633a
     }
db633a
+  else if (!meta_is_wayland_compositor () &&
db633a
+           event->type == GenericEvent &&
db633a
+           event->xcookie.extension == compositor->glx_opcode)
db633a
+    {
db633a
+      if (event->xcookie.evtype == GLX_STEREO_NOTIFY_EXT)
db633a
+        {
db633a
+          StereoNotifyEvent *stereo_event = (StereoNotifyEvent *)(event->xcookie.data);
db633a
+          window = meta_display_lookup_x_window (compositor->display, stereo_event->window);
db633a
+
db633a
+          if (window != NULL)
db633a
+            {
db633a
+              MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
db633a
+              meta_window_actor_stereo_notify (window_actor, stereo_event->stereo_tree);
db633a
+              meta_stack_tracker_queue_sync_stack (window->screen->stack_tracker);
db633a
+            }
db633a
+        }
db633a
+    }
db633a
 
db633a
   if (compositor->have_x11_sync_object)
db633a
     meta_sync_ring_handle_event (event);
e3f29c
@@ -957,6 +1069,7 @@ meta_compositor_sync_stack (MetaCompositor  *compositor,
db633a
 			    GList	    *stack)
db633a
 {
db633a
   GList *old_stack;
db633a
+  int stereo_window_count = 0;
db633a
 
db633a
   /* This is painful because hidden windows that we are in the process
db633a
    * of animating out of existence. They'll be at the bottom of the
e3f29c
@@ -1032,6 +1145,8 @@ meta_compositor_sync_stack (MetaCompositor  *compositor,
db633a
        * near the front of the other.)
db633a
        */
db633a
       compositor->windows = g_list_prepend (compositor->windows, actor);
db633a
+      if (meta_window_actor_is_stereo (actor))
db633a
+        stereo_window_count++;
db633a
 
db633a
       stack = g_list_remove (stack, window);
db633a
       old_stack = g_list_remove (old_stack, actor);
e3f29c
@@ -1039,6 +1154,8 @@ meta_compositor_sync_stack (MetaCompositor  *compositor,
db633a
 
db633a
   sync_actor_stacking (compositor);
e3f29c
 
db633a
+  meta_stereo_set_have_stereo_windows (stereo_window_count > 0);
e3f29c
+
e3f29c
   compositor->top_window_actor = get_top_visible_window_actor (compositor);
db633a
 }
db633a
 
e3f29c
@@ -1237,6 +1354,17 @@ meta_compositor_new (MetaDisplay *display)
db633a
                                            meta_post_paint_func,
db633a
                                            compositor,
db633a
                                            NULL);
db633a
+  if (!meta_is_wayland_compositor ())
db633a
+    {
db633a
+      Display *xdisplay = meta_display_get_xdisplay (display);
db633a
+      int glx_major_opcode, glx_first_event, glx_first_error;
db633a
+
db633a
+      if (XQueryExtension (xdisplay,
db633a
+                           "GLX",
db633a
+                           &glx_major_opcode, &glx_first_event, &glx_first_error))
db633a
+        compositor->glx_opcode = glx_major_opcode;
db633a
+    }
db633a
+
db633a
   return compositor;
db633a
 }
db633a
 
db633a
diff --git a/src/compositor/meta-shaped-texture-private.h b/src/compositor/meta-shaped-texture-private.h
e3f29c
index 5b3f283c2..189a95312 100644
db633a
--- a/src/compositor/meta-shaped-texture-private.h
db633a
+++ b/src/compositor/meta-shaped-texture-private.h
db633a
@@ -30,8 +30,9 @@
db633a
 #include <meta/meta-shaped-texture.h>
db633a
 
db633a
 ClutterActor *meta_shaped_texture_new (void);
db633a
-void meta_shaped_texture_set_texture (MetaShapedTexture *stex,
db633a
-                                      CoglTexture       *texture);
db633a
+void meta_shaped_texture_set_textures (MetaShapedTexture *stex,
db633a
+                                       CoglTexture       *texture,
db633a
+                                       CoglTexture       *texture_right);
e3f29c
 void meta_shaped_texture_set_is_y_inverted (MetaShapedTexture *stex,
e3f29c
                                             gboolean           is_y_inverted);
e3f29c
 void meta_shaped_texture_set_snippet (MetaShapedTexture *stex,
db633a
diff --git a/src/compositor/meta-shaped-texture.c b/src/compositor/meta-shaped-texture.c
e3f29c
index 98346c6ae..b89de03a3 100644
db633a
--- a/src/compositor/meta-shaped-texture.c
db633a
+++ b/src/compositor/meta-shaped-texture.c
db633a
@@ -74,8 +74,10 @@ static guint signals[LAST_SIGNAL];
db633a
 struct _MetaShapedTexturePrivate
db633a
 {
db633a
   MetaTextureTower *paint_tower;
db633a
+  MetaTextureTower *paint_tower_right;
db633a
 
db633a
   CoglTexture *texture;
db633a
+  CoglTexture *texture_right;
db633a
   CoglTexture *mask_texture;
e3f29c
   CoglSnippet *snippet;
db633a
 
e3f29c
@@ -129,8 +131,10 @@ meta_shaped_texture_init (MetaShapedTexture *self)
db633a
   priv = self->priv = META_SHAPED_TEXTURE_GET_PRIVATE (self);
db633a
 
db633a
   priv->paint_tower = meta_texture_tower_new ();
db633a
+  priv->paint_tower_right = NULL; /* demand create */
db633a
 
db633a
   priv->texture = NULL;
db633a
+  priv->texture_right = NULL;
db633a
   priv->mask_texture = NULL;
db633a
   priv->create_mipmaps = TRUE;
e3f29c
   priv->is_y_inverted = TRUE;
e3f29c
@@ -191,11 +195,11 @@ meta_shaped_texture_dispose (GObject *object)
db633a
   MetaShapedTexture *self = (MetaShapedTexture *) object;
db633a
   MetaShapedTexturePrivate *priv = self->priv;
db633a
 
db633a
-  if (priv->paint_tower)
db633a
-    meta_texture_tower_free (priv->paint_tower);
db633a
-  priv->paint_tower = NULL;
db633a
+  g_clear_pointer (&priv->paint_tower, meta_texture_tower_free);
db633a
+  g_clear_pointer (&priv->paint_tower_right, meta_texture_tower_free);
db633a
 
db633a
   g_clear_pointer (&priv->texture, cogl_object_unref);
db633a
+  g_clear_pointer (&priv->texture_right, cogl_object_unref);
db633a
   g_clear_pointer (&priv->opaque_region, cairo_region_destroy);
db633a
 
db633a
   meta_shaped_texture_set_mask_texture (self, NULL);
e3f29c
@@ -326,8 +330,9 @@ paint_clipped_rectangle (CoglFramebuffer       *fb,
db633a
 }
db633a
 
db633a
 static void
db633a
-set_cogl_texture (MetaShapedTexture *stex,
db633a
-                  CoglTexture       *cogl_tex)
db633a
+set_cogl_textures (MetaShapedTexture *stex,
db633a
+                   CoglTexture       *cogl_tex,
db633a
+                   CoglTexture       *cogl_tex_right)
db633a
 {
db633a
   MetaShapedTexturePrivate *priv;
db633a
   guint width, height;
e3f29c
@@ -338,8 +343,11 @@ set_cogl_texture (MetaShapedTexture *stex,
db633a
 
db633a
   if (priv->texture)
db633a
     cogl_object_unref (priv->texture);
db633a
+  if (priv->texture_right)
db633a
+    cogl_object_unref (priv->texture_right);
db633a
 
db633a
   priv->texture = cogl_tex;
db633a
+  priv->texture_right = cogl_tex_right;
db633a
 
db633a
   if (cogl_tex != NULL)
db633a
     {
e3f29c
@@ -353,6 +361,9 @@ set_cogl_texture (MetaShapedTexture *stex,
db633a
       height = 0;
db633a
     }
db633a
 
db633a
+  if (cogl_tex_right != NULL)
db633a
+    cogl_object_ref (cogl_tex_right);
db633a
+
db633a
   if (priv->tex_width != width ||
db633a
       priv->tex_height != height)
db633a
     {
e3f29c
@@ -368,52 +379,41 @@ set_cogl_texture (MetaShapedTexture *stex,
db633a
    * previous buffer. We only queue a redraw in response to surface
db633a
    * damage. */
db633a
 
db633a
+  if (cogl_tex_right != NULL)
db633a
+    {
db633a
+      if (priv->paint_tower_right == NULL)
db633a
+        priv->paint_tower_right = meta_texture_tower_new ();
db633a
+    }
db633a
+  else
db633a
+    {
db633a
+      g_clear_pointer (&priv->paint_tower_right, meta_texture_tower_free);
db633a
+    }
db633a
+
db633a
   if (priv->create_mipmaps)
db633a
-    meta_texture_tower_set_base_texture (priv->paint_tower, cogl_tex);
db633a
+    {
db633a
+      meta_texture_tower_set_base_texture (priv->paint_tower, cogl_tex);
db633a
+
db633a
+      if (priv->paint_tower_right)
db633a
+        meta_texture_tower_set_base_texture (priv->paint_tower_right, cogl_tex_right);
db633a
+    }
db633a
 }
db633a
 
db633a
 static void
db633a
-meta_shaped_texture_paint (ClutterActor *actor)
db633a
+paint_texture (MetaShapedTexture *stex,
db633a
+               CoglTexture       *paint_tex)
db633a
 {
db633a
-  MetaShapedTexture *stex = (MetaShapedTexture *) actor;
db633a
+  ClutterActor *actor = CLUTTER_ACTOR (stex);
db633a
   MetaShapedTexturePrivate *priv = stex->priv;
db633a
   guint tex_width, tex_height;
db633a
   guchar opacity;
db633a
   CoglContext *ctx;
db633a
   CoglFramebuffer *fb;
db633a
-  CoglTexture *paint_tex;
db633a
   ClutterActorBox alloc;
db633a
   CoglPipelineFilter filter;
db633a
 
db633a
   if (priv->clip_region && cairo_region_is_empty (priv->clip_region))
db633a
     return;
db633a
 
db633a
-  if (!CLUTTER_ACTOR_IS_REALIZED (CLUTTER_ACTOR (stex)))
db633a
-    clutter_actor_realize (CLUTTER_ACTOR (stex));
db633a
-
db633a
-  /* The GL EXT_texture_from_pixmap extension does allow for it to be
db633a
-   * used together with SGIS_generate_mipmap, however this is very
db633a
-   * rarely supported. Also, even when it is supported there
db633a
-   * are distinct performance implications from:
db633a
-   *
db633a
-   *  - Updating mipmaps that we don't need
db633a
-   *  - Having to reallocate pixmaps on the server into larger buffers
db633a
-   *
db633a
-   * So, we just unconditionally use our mipmap emulation code. If we
db633a
-   * wanted to use SGIS_generate_mipmap, we'd have to  query COGL to
db633a
-   * see if it was supported (no API currently), and then if and only
db633a
-   * if that was the case, set the clutter texture quality to HIGH.
db633a
-   * Setting the texture quality to high without SGIS_generate_mipmap
db633a
-   * support for TFP textures will result in fallbacks to XGetImage.
db633a
-   */
db633a
-  if (priv->create_mipmaps)
db633a
-    paint_tex = meta_texture_tower_get_paint_texture (priv->paint_tower);
db633a
-  else
db633a
-    paint_tex = COGL_TEXTURE (priv->texture);
db633a
-
db633a
-  if (paint_tex == NULL)
db633a
-    return;
db633a
-
db633a
   tex_width = priv->tex_width;
db633a
   tex_height = priv->tex_height;
db633a
 
e3f29c
@@ -574,6 +574,76 @@ meta_shaped_texture_paint (ClutterActor *actor)
db633a
 }
db633a
 
db633a
 static void
db633a
+meta_shaped_texture_paint (ClutterActor *actor)
db633a
+{
db633a
+  MetaShapedTexture *stex = (MetaShapedTexture *) actor;
db633a
+  MetaShapedTexturePrivate *priv = stex->priv;
db633a
+  CoglFramebuffer *fb;
db633a
+  gboolean stereo;
db633a
+  CoglTexture *paint_tex;
db633a
+  CoglTexture *paint_tex_right;
db633a
+
db633a
+  if (priv->clip_region && cairo_region_is_empty (priv->clip_region))
db633a
+    return;
db633a
+
db633a
+  if (!CLUTTER_ACTOR_IS_REALIZED (CLUTTER_ACTOR (stex)))
db633a
+    clutter_actor_realize (CLUTTER_ACTOR (stex));
db633a
+
db633a
+  /* The GL EXT_texture_from_pixmap extension does allow for it to be
db633a
+   * used together with SGIS_generate_mipmap, however this is very
db633a
+   * rarely supported. Also, even when it is supported there
db633a
+   * are distinct performance implications from:
db633a
+   *
db633a
+   *  - Updating mipmaps that we don't need
db633a
+   *  - Having to reallocate pixmaps on the server into larger buffers
db633a
+   *
db633a
+   * So, we just unconditionally use our mipmap emulation code. If we
db633a
+   * wanted to use SGIS_generate_mipmap, we'd have to  query COGL to
db633a
+   * see if it was supported (no API currently), and then if and only
db633a
+   * if that was the case, set the clutter texture quality to HIGH.
db633a
+   * Setting the texture quality to high without SGIS_generate_mipmap
db633a
+   * support for TFP textures will result in fallbacks to XGetImage.
db633a
+   */
db633a
+  if (priv->create_mipmaps)
db633a
+    paint_tex = meta_texture_tower_get_paint_texture (priv->paint_tower);
db633a
+  else
db633a
+    paint_tex = COGL_TEXTURE (priv->texture);
db633a
+
db633a
+  if (paint_tex == NULL)
db633a
+    return;
db633a
+
db633a
+  fb = cogl_get_draw_framebuffer ();
db633a
+
db633a
+  stereo = priv->texture_right && cogl_framebuffer_get_is_stereo (fb);
db633a
+
db633a
+  if (stereo)
db633a
+    {
db633a
+      if (priv->create_mipmaps)
db633a
+	paint_tex_right = meta_texture_tower_get_paint_texture (priv->paint_tower_right);
db633a
+      else
db633a
+	paint_tex_right = COGL_TEXTURE (priv->texture_right);
db633a
+    }
db633a
+  else
db633a
+    paint_tex_right = NULL;
db633a
+
db633a
+  if (paint_tex != NULL)
db633a
+    {
db633a
+      if (stereo)
db633a
+	cogl_framebuffer_set_stereo_mode (fb, COGL_STEREO_LEFT);
db633a
+      paint_texture (stex, paint_tex);
db633a
+      if (stereo)
db633a
+	cogl_framebuffer_set_stereo_mode (fb, COGL_STEREO_BOTH);
db633a
+    }
db633a
+
db633a
+  if (paint_tex_right != NULL)
db633a
+    {
db633a
+      cogl_framebuffer_set_stereo_mode (fb, COGL_STEREO_RIGHT);
db633a
+      paint_texture (stex, paint_tex_right);
db633a
+      cogl_framebuffer_set_stereo_mode (fb, COGL_STEREO_BOTH);
db633a
+    }
db633a
+}
db633a
+
db633a
+static void
db633a
 meta_shaped_texture_get_preferred_width (ClutterActor *self,
db633a
                                          gfloat        for_height,
db633a
                                          gfloat       *min_width_p,
e3f29c
@@ -692,6 +762,12 @@ meta_shaped_texture_set_create_mipmaps (MetaShapedTexture *stex,
db633a
       priv->create_mipmaps = create_mipmaps;
db633a
       base_texture = create_mipmaps ? priv->texture : NULL;
db633a
       meta_texture_tower_set_base_texture (priv->paint_tower, base_texture);
db633a
+
db633a
+      if (priv->paint_tower_right)
db633a
+        {
db633a
+          base_texture = create_mipmaps ? priv->texture_right : NULL;
db633a
+          meta_texture_tower_set_base_texture (priv->paint_tower_right, base_texture);
db633a
+        }
db633a
     }
db633a
 }
db633a
 
e3f29c
@@ -757,6 +833,8 @@ meta_shaped_texture_update_area (MetaShapedTexture *stex,
db633a
     return FALSE;
db633a
 
db633a
   meta_texture_tower_update_area (priv->paint_tower, x, y, width, height);
db633a
+  if (priv->paint_tower_right)
db633a
+    meta_texture_tower_update_area (priv->paint_tower_right, x, y, width, height);
db633a
 
db633a
   unobscured_region = effective_unobscured_region (stex);
db633a
   if (unobscured_region)
e3f29c
@@ -789,17 +867,18 @@ meta_shaped_texture_update_area (MetaShapedTexture *stex,
db633a
 }
db633a
 
db633a
 /**
db633a
- * meta_shaped_texture_set_texture:
db633a
+ * meta_shaped_texture_set_textures:
db633a
  * @stex: The #MetaShapedTexture
db633a
  * @pixmap: The #CoglTexture to display
db633a
  */
db633a
 void
db633a
-meta_shaped_texture_set_texture (MetaShapedTexture *stex,
db633a
-                                 CoglTexture       *texture)
db633a
+meta_shaped_texture_set_textures (MetaShapedTexture *stex,
db633a
+                                  CoglTexture       *texture,
db633a
+                                  CoglTexture       *texture_right)
db633a
 {
db633a
   g_return_if_fail (META_IS_SHAPED_TEXTURE (stex));
db633a
 
db633a
-  set_cogl_texture (stex, texture);
db633a
+  set_cogl_textures (stex, texture, texture_right);
db633a
 }
db633a
 
db633a
 /**
db633a
diff --git a/src/compositor/meta-surface-actor-wayland.c b/src/compositor/meta-surface-actor-wayland.c
e3f29c
index 551322573..6ca68eb64 100644
db633a
--- a/src/compositor/meta-surface-actor-wayland.c
db633a
+++ b/src/compositor/meta-surface-actor-wayland.c
e3f29c
@@ -403,7 +403,7 @@ meta_surface_actor_wayland_dispose (GObject *object)
e3f29c
   MetaShapedTexture *stex =
e3f29c
     meta_surface_actor_get_texture (META_SURFACE_ACTOR (self));
e3f29c
 
e3f29c
-  meta_shaped_texture_set_texture (stex, NULL);
e3f29c
+  meta_shaped_texture_set_textures (stex, NULL, NULL);
e3f29c
   if (priv->surface)
e3f29c
     {
e3f29c
       g_object_remove_weak_pointer (G_OBJECT (priv->surface),
e3f29c
@@ -462,6 +462,14 @@ meta_surface_actor_wayland_new (MetaWaylandSurface *surface)
e3f29c
   return META_SURFACE_ACTOR (self);
db633a
 }
db633a
 
e3f29c
+void
e3f29c
+meta_surface_actor_wayland_set_texture (MetaSurfaceActorWayland *self,
e3f29c
+                                        CoglTexture *texture)
e3f29c
+{
e3f29c
+  MetaShapedTexture *stex = meta_surface_actor_get_texture (META_SURFACE_ACTOR (self));
e3f29c
+  meta_shaped_texture_set_textures (stex, texture, NULL);
e3f29c
+}
e3f29c
+
db633a
 MetaWaylandSurface *
e3f29c
 meta_surface_actor_wayland_get_surface (MetaSurfaceActorWayland *self)
e3f29c
 {
db633a
diff --git a/src/compositor/meta-surface-actor-x11.c b/src/compositor/meta-surface-actor-x11.c
e3f29c
index d32aeb68a..52db3808e 100644
db633a
--- a/src/compositor/meta-surface-actor-x11.c
db633a
+++ b/src/compositor/meta-surface-actor-x11.c
db633a
@@ -31,6 +31,7 @@
db633a
 #include <cogl/winsys/cogl-texture-pixmap-x11.h>
db633a
 
db633a
 #include <meta/errors.h>
db633a
+#include "compositor-private.h"
db633a
 #include "window-private.h"
db633a
 #include "meta-shaped-texture-private.h"
db633a
 #include "meta-cullable.h"
db633a
@@ -43,6 +44,7 @@ struct _MetaSurfaceActorX11Private
db633a
   MetaDisplay *display;
db633a
 
db633a
   CoglTexture *texture;
db633a
+  CoglTexture *texture_right;
db633a
   Pixmap pixmap;
db633a
   Damage damage;
db633a
 
db633a
@@ -58,6 +60,8 @@ struct _MetaSurfaceActorX11Private
db633a
   guint size_changed : 1;
db633a
 
db633a
   guint unredirected   : 1;
db633a
+
db633a
+  guint stereo : 1;
db633a
 };
db633a
 typedef struct _MetaSurfaceActorX11Private MetaSurfaceActorX11Private;
db633a
 
db633a
@@ -94,7 +98,7 @@ detach_pixmap (MetaSurfaceActorX11 *self)
db633a
    * you are supposed to be able to free a GLXPixmap after freeing the underlying
db633a
    * pixmap, but it certainly doesn't work with current DRI/Mesa
db633a
    */
db633a
-  meta_shaped_texture_set_texture (stex, NULL);
db633a
+  meta_shaped_texture_set_textures (stex, NULL, NULL);
db633a
   cogl_flush ();
db633a
 
db633a
   meta_error_trap_push (display);
db633a
@@ -103,6 +107,7 @@ detach_pixmap (MetaSurfaceActorX11 *self)
db633a
   meta_error_trap_pop (display);
db633a
 
db633a
   g_clear_pointer (&priv->texture, cogl_object_unref);
db633a
+  g_clear_pointer (&priv->texture_right, cogl_object_unref);
db633a
 }
db633a
 
db633a
 static void
db633a
@@ -114,23 +119,35 @@ set_pixmap (MetaSurfaceActorX11 *self,
db633a
   CoglContext *ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
db633a
   MetaShapedTexture *stex = meta_surface_actor_get_texture (META_SURFACE_ACTOR (self));
db633a
   CoglError *error = NULL;
db633a
-  CoglTexture *texture;
db633a
+  CoglTexturePixmapX11 *texture;
db633a
+  CoglTexturePixmapX11 *texture_right;
db633a
 
db633a
   g_assert (priv->pixmap == None);
db633a
   priv->pixmap = pixmap;
db633a
 
db633a
-  texture = COGL_TEXTURE (cogl_texture_pixmap_x11_new (ctx, priv->pixmap, FALSE, &error));
db633a
+  if (priv->stereo)
db633a
+    texture = cogl_texture_pixmap_x11_new_left (ctx, pixmap, FALSE, &error);
db633a
+  else
db633a
+    texture = cogl_texture_pixmap_x11_new (ctx, pixmap, FALSE, &error);
db633a
+
db633a
+  if (priv->stereo)
db633a
+    texture_right = cogl_texture_pixmap_x11_new_right (texture);
db633a
+  else
db633a
+    texture_right = NULL;
db633a
 
db633a
   if (error != NULL)
db633a
     {
db633a
       g_warning ("Failed to allocate stex texture: %s", error->message);
db633a
       cogl_error_free (error);
db633a
     }
db633a
-  else if (G_UNLIKELY (!cogl_texture_pixmap_x11_is_using_tfp_extension (COGL_TEXTURE_PIXMAP_X11 (texture))))
db633a
+  else if (G_UNLIKELY (!cogl_texture_pixmap_x11_is_using_tfp_extension (texture)))
db633a
     g_warning ("NOTE: Not using GLX TFP!\n");
db633a
 
db633a
-  priv->texture = texture;
db633a
-  meta_shaped_texture_set_texture (stex, texture);
db633a
+  priv->texture = COGL_TEXTURE (texture);
db633a
+  if (priv->stereo)
db633a
+    priv->texture_right = COGL_TEXTURE (texture_right);
db633a
+
db633a
+  meta_shaped_texture_set_textures (stex, COGL_TEXTURE (texture), COGL_TEXTURE (texture_right));
db633a
 }
db633a
 
db633a
 static void
db633a
@@ -433,8 +450,8 @@ reset_texture (MetaSurfaceActorX11 *self)
db633a
   /* Setting the texture to NULL will cause all the FBO's cached by the
db633a
    * shaped texture's MetaTextureTower to be discarded and recreated.
db633a
    */
db633a
-  meta_shaped_texture_set_texture (stex, NULL);
db633a
-  meta_shaped_texture_set_texture (stex, priv->texture);
db633a
+  meta_shaped_texture_set_textures (stex, NULL, NULL);
db633a
+  meta_shaped_texture_set_textures (stex, priv->texture, priv->texture_right);
db633a
 }
db633a
 
db633a
 MetaSurfaceActor *
db633a
@@ -443,12 +460,17 @@ meta_surface_actor_x11_new (MetaWindow *window)
db633a
   MetaSurfaceActorX11 *self = g_object_new (META_TYPE_SURFACE_ACTOR_X11, NULL);
db633a
   MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
db633a
   MetaDisplay *display = meta_window_get_display (window);
db633a
+  Window xwindow;
db633a
 
db633a
   g_assert (!meta_is_wayland_compositor ());
db633a
 
db633a
   priv->window = window;
db633a
   priv->display = display;
db633a
 
db633a
+  xwindow = meta_window_x11_get_toplevel_xwindow (window);
db633a
+  priv->stereo = meta_compositor_window_is_stereo (display->screen, xwindow);
db633a
+  meta_compositor_select_stereo_notify (display->screen, xwindow);
db633a
+
db633a
   g_signal_connect_object (priv->display, "gl-video-memory-purged",
db633a
                            G_CALLBACK (reset_texture), self, G_CONNECT_SWAPPED);
db633a
 
db633a
@@ -479,3 +501,21 @@ meta_surface_actor_x11_set_size (MetaSurfaceActorX11 *self,
db633a
   priv->last_height = height;
db633a
   meta_shaped_texture_set_fallback_size (stex, width, height);
db633a
 }
db633a
+
db633a
+void
db633a
+meta_surface_actor_x11_stereo_notify (MetaSurfaceActorX11 *self,
db633a
+                                      gboolean             stereo_tree)
db633a
+{
db633a
+  MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
db633a
+
db633a
+  priv->stereo = stereo_tree != FALSE;
db633a
+  detach_pixmap (self);
db633a
+}
db633a
+
db633a
+gboolean
db633a
+meta_surface_actor_x11_is_stereo (MetaSurfaceActorX11 *self)
db633a
+{
db633a
+  MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
db633a
+
db633a
+  return priv->stereo;
db633a
+}
db633a
diff --git a/src/compositor/meta-surface-actor-x11.h b/src/compositor/meta-surface-actor-x11.h
e3f29c
index 0e692ee0f..4b2ecccb1 100644
db633a
--- a/src/compositor/meta-surface-actor-x11.h
db633a
+++ b/src/compositor/meta-surface-actor-x11.h
db633a
@@ -64,6 +64,11 @@ MetaSurfaceActor * meta_surface_actor_x11_new (MetaWindow *window);
db633a
 void meta_surface_actor_x11_set_size (MetaSurfaceActorX11 *self,
db633a
                                       int width, int height);
db633a
 
db633a
+void meta_surface_actor_x11_stereo_notify (MetaSurfaceActorX11 *self,
db633a
+                                           gboolean             stereo_tree);
db633a
+
db633a
+gboolean meta_surface_actor_x11_is_stereo (MetaSurfaceActorX11 *self);
db633a
+
db633a
 G_END_DECLS
db633a
 
db633a
 #endif /* __META_SURFACE_ACTOR_X11_H__ */
db633a
diff --git a/src/compositor/meta-window-actor-private.h b/src/compositor/meta-window-actor-private.h
e3f29c
index 72dcd1451..035d756b2 100644
db633a
--- a/src/compositor/meta-window-actor-private.h
db633a
+++ b/src/compositor/meta-window-actor-private.h
db633a
@@ -59,4 +59,9 @@ void meta_window_actor_effect_completed (MetaWindowActor  *actor,
db633a
 MetaSurfaceActor *meta_window_actor_get_surface (MetaWindowActor *self);
db633a
 void meta_window_actor_update_surface (MetaWindowActor *self);
db633a
 
db633a
+void meta_window_actor_stereo_notify (MetaWindowActor *actor,
db633a
+                                      gboolean         stereo_tree);
db633a
+
db633a
+gboolean meta_window_actor_is_stereo (MetaWindowActor *actor);
db633a
+
db633a
 #endif /* META_WINDOW_ACTOR_PRIVATE_H */
db633a
diff --git a/src/compositor/meta-window-actor.c b/src/compositor/meta-window-actor.c
e3f29c
index 1184cd422..773e6d09d 100644
db633a
--- a/src/compositor/meta-window-actor.c
db633a
+++ b/src/compositor/meta-window-actor.c
e3f29c
@@ -2150,3 +2150,25 @@ meta_window_actor_sync_updates_frozen (MetaWindowActor *self)
db633a
 
db633a
   meta_window_actor_set_updates_frozen (self, meta_window_updates_are_frozen (window));
db633a
 }
db633a
+
db633a
+void
db633a
+meta_window_actor_stereo_notify (MetaWindowActor *self,
db633a
+                                 gboolean         stereo_tree)
db633a
+{
db633a
+  MetaWindowActorPrivate *priv = self->priv;
db633a
+
db633a
+  if (META_IS_SURFACE_ACTOR_X11 (priv->surface))
db633a
+    meta_surface_actor_x11_stereo_notify (META_SURFACE_ACTOR_X11 (priv->surface),
db633a
+                                          stereo_tree);
db633a
+}
db633a
+
db633a
+gboolean
db633a
+meta_window_actor_is_stereo (MetaWindowActor *self)
db633a
+{
db633a
+  MetaWindowActorPrivate *priv = self->priv;
db633a
+
db633a
+  if (META_IS_SURFACE_ACTOR_X11 (priv->surface))
db633a
+    return meta_surface_actor_x11_is_stereo (META_SURFACE_ACTOR_X11 (priv->surface));
db633a
+  else
db633a
+    return FALSE;
db633a
+}
db633a
diff --git a/src/core/main.c b/src/core/main.c
e3f29c
index dc1f1c4f6..2c1160711 100644
db633a
--- a/src/core/main.c
db633a
+++ b/src/core/main.c
db633a
@@ -47,6 +47,7 @@
db633a
 #include <meta/main.h>
db633a
 #include "util-private.h"
db633a
 #include "display-private.h"
db633a
+#include "stereo.h"
db633a
 #include <meta/errors.h>
db633a
 #include "ui.h"
db633a
 #include <meta/prefs.h>
e3f29c
@@ -566,6 +567,9 @@ meta_init (void)
db633a
 
e3f29c
   meta_init_backend (backend_gtype);
db633a
 
db633a
+  if (!meta_is_wayland_compositor ())
db633a
+    meta_stereo_init ();
db633a
+
db633a
   meta_clutter_init ();
db633a
 
db633a
 #ifdef HAVE_WAYLAND
db633a
diff --git a/src/core/stereo.c b/src/core/stereo.c
db633a
new file mode 100644
e3f29c
index 000000000..5a232b67c
db633a
--- /dev/null
db633a
+++ b/src/core/stereo.c
db633a
@@ -0,0 +1,153 @@
db633a
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
db633a
+
db633a
+/*
db633a
+ * Copyright (C) 2014 Red Hat, Inc.
db633a
+ *
db633a
+ * This program is free software; you can redistribute it and/or
db633a
+ * modify it under the terms of the GNU General Public License as
db633a
+ * published by the Free Software Foundation; either version 2 of the
db633a
+ * License, or (at your option) any later version.
db633a
+ *
db633a
+ * This program is distributed in the hope that it will be useful, but
db633a
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
db633a
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
db633a
+ * General Public License for more details.
db633a
+ *
db633a
+ * You should have received a copy of the GNU General Public License
db633a
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
db633a
+ */
db633a
+
db633a
+/*
db633a
+ * SECTION:stereo
db633a
+ * @short_description: Keep track of whether we are a stereo compositor
db633a
+ *
db633a
+ * With GLX, we need to use a different GL context for stereo and
db633a
+ * non-stereo support. Support for multiple GL contexts is unfinished
db633a
+ * in Cogl and entirely lacking in Clutter, so it's by far easier
db633a
+ * to just restart Mutter when we detect a stereo window.
db633a
+ *
db633a
+ * A property _MUTTER_ENABLE_STEREO is maintained on the root window
db633a
+ * to know whether we should initialize clutter for stereo or not.
db633a
+ * When the presence or absence of stereo windows mismatches the
db633a
+ * stereo-enabled state for a sufficiently long period of time,
db633a
+ * we restart Mutter.
db633a
+ */
db633a
+
db633a
+#include <config.h>
db633a
+
db633a
+#include <clutter/x11/clutter-x11.h>
db633a
+#include <gio/gunixinputstream.h>
db633a
+#include <X11/Xatom.h>
db633a
+
db633a
+#include <meta/main.h>
db633a
+#include "ui.h"
db633a
+#include <meta/util.h>
db633a
+#include "display-private.h"
db633a
+#include "stereo.h"
db633a
+#include "util-private.h"
db633a
+
db633a
+static guint stereo_switch_id = 0;
db633a
+static gboolean stereo_enabled = FALSE;
db633a
+/* -1 so the first time meta_stereo_set_have_stereo_windows() is called
db633a
+ * we avoid the short-circuit and set up a timeout to restart
db633a
+ * if necessary */
db633a
+static gboolean stereo_have_windows = (gboolean)-1;
db633a
+static gboolean stereo_restart = FALSE;
db633a
+
db633a
+#define STEREO_ENABLE_WAIT 1000
db633a
+#define STEREO_DISABLE_WAIT 5000
db633a
+
db633a
+void
db633a
+meta_stereo_init (void)
db633a
+{
db633a
+  Display *xdisplay;
db633a
+  Window root;
db633a
+  Atom atom_enable_stereo;
db633a
+  Atom type;
db633a
+  int format;
db633a
+  unsigned long n_items, bytes_after;
db633a
+  guchar *data;
db633a
+
db633a
+  xdisplay = XOpenDisplay (NULL);
db633a
+  if (xdisplay == NULL)
db633a
+    meta_fatal ("Unable to open X display %s\n", XDisplayName (NULL));
db633a
+
db633a
+  root = DefaultRootWindow (xdisplay);
db633a
+  atom_enable_stereo = XInternAtom (xdisplay, "_MUTTER_ENABLE_STEREO", False);
db633a
+
db633a
+  XGetWindowProperty (xdisplay, root, atom_enable_stereo,
db633a
+                      0, 1, False, XA_INTEGER,
db633a
+                      &type, &format, &n_items, &bytes_after, &data);
db633a
+  if (type == XA_INTEGER)
db633a
+    {
db633a
+      if (format == 32 && n_items == 1 && bytes_after == 0)
db633a
+        {
db633a
+          stereo_enabled = *(long *)data;
db633a
+        }
db633a
+      else
db633a
+        {
db633a
+          meta_warning ("Bad value for _MUTTER_ENABLE_STEREO property\n");
db633a
+        }
db633a
+
db633a
+      XFree (data);
db633a
+    }
db633a
+  else if (type != None)
db633a
+    {
db633a
+      meta_warning ("Bad type for _MUTTER_ENABLE_STEREO property\n");
db633a
+    }
db633a
+
db633a
+  meta_verbose ("On startup, _MUTTER_ENABLE_STEREO=%s",
db633a
+                stereo_enabled ? "yes" : "no");
db633a
+  clutter_x11_set_use_stereo_stage (stereo_enabled);
db633a
+  XCloseDisplay (xdisplay);
db633a
+}
db633a
+
db633a
+static gboolean
db633a
+meta_stereo_switch (gpointer data)
db633a
+{
db633a
+  stereo_switch_id = 0;
db633a
+  stereo_restart = TRUE;
db633a
+
db633a
+  meta_restart (stereo_have_windows ?
db633a
+                _("Enabling stereo...") :
db633a
+                _("Disabling stereo..."));
db633a
+
db633a
+  return FALSE;
db633a
+}
db633a
+
db633a
+void
db633a
+meta_stereo_set_have_stereo_windows (gboolean have_windows)
db633a
+{
db633a
+  have_windows = have_windows != FALSE;
db633a
+
db633a
+  if (!stereo_restart && have_windows != stereo_have_windows)
db633a
+    {
db633a
+      MetaDisplay *display = meta_get_display ();
db633a
+      Display *xdisplay = meta_display_get_xdisplay (display);
db633a
+      Window root = DefaultRootWindow (xdisplay);
db633a
+      Atom atom_enable_stereo = XInternAtom (xdisplay, "_MUTTER_ENABLE_STEREO", False);
db633a
+      long value;
db633a
+
db633a
+      stereo_have_windows = have_windows;
db633a
+
db633a
+      if (stereo_have_windows)
db633a
+        meta_verbose ("Detected stereo windows\n");
db633a
+      else
db633a
+        meta_verbose ("No stereo windows detected\n");
db633a
+
db633a
+      value = stereo_have_windows;
db633a
+      XChangeProperty (xdisplay, root,
db633a
+                       atom_enable_stereo, XA_INTEGER, 32,
db633a
+                       PropModeReplace, (guchar *)&value, 1);
db633a
+
db633a
+      if (stereo_switch_id != 0)
db633a
+        {
db633a
+          g_source_remove (stereo_switch_id);
db633a
+          stereo_switch_id = 0;
db633a
+        }
db633a
+
db633a
+      if (stereo_have_windows != stereo_enabled)
db633a
+        stereo_switch_id = g_timeout_add (stereo_have_windows ? STEREO_ENABLE_WAIT : STEREO_DISABLE_WAIT,
db633a
+                                          meta_stereo_switch, NULL);
db633a
+    }
db633a
+}
db633a
diff --git a/src/core/stereo.h b/src/core/stereo.h
db633a
new file mode 100644
e3f29c
index 000000000..ccd1d702a
db633a
--- /dev/null
db633a
+++ b/src/core/stereo.h
db633a
@@ -0,0 +1,28 @@
db633a
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
db633a
+
db633a
+/*
db633a
+ * Copyright (C) 2014 Red Hat, Inc.
db633a
+ *
db633a
+ * This program is free software; you can redistribute it and/or
db633a
+ * modify it under the terms of the GNU General Public License as
db633a
+ * published by the Free Software Foundation; either version 2 of the
db633a
+ * License, or (at your option) any later version.
db633a
+ *
db633a
+ * This program is distributed in the hope that it will be useful, but
db633a
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
db633a
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
db633a
+ * General Public License for more details.
db633a
+ *
db633a
+ * You should have received a copy of the GNU General Public License
db633a
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
db633a
+ */
db633a
+
db633a
+#ifndef META_STEREO_H
db633a
+#define META_STEREO_H
db633a
+
db633a
+void     meta_stereo_init                    (void);
db633a
+void     meta_stereo_set_have_stereo_windows (gboolean have_windows);
db633a
+gboolean meta_stereo_is_restart              (void);
db633a
+void     meta_stereo_finish_restart          (void);
db633a
+
db633a
+#endif
e3f29c
diff --git a/src/wayland/meta-wayland-surface.c b/src/wayland/meta-wayland-surface.c
e3f29c
index 6f9df37da..d353ae5d0 100644
e3f29c
--- a/src/wayland/meta-wayland-surface.c
e3f29c
+++ b/src/wayland/meta-wayland-surface.c
e3f29c
@@ -789,7 +789,7 @@ apply_pending_state (MetaWaylandSurface      *surface,
e3f29c
               snippet = meta_wayland_buffer_create_snippet (pending->buffer);
e3f29c
               is_y_inverted = meta_wayland_buffer_is_y_inverted (pending->buffer);
e3f29c
 
e3f29c
-              meta_shaped_texture_set_texture (stex, texture);
e3f29c
+              meta_shaped_texture_set_textures (stex, texture, NULL);
e3f29c
               meta_shaped_texture_set_snippet (stex, snippet);
e3f29c
               meta_shaped_texture_set_is_y_inverted (stex, is_y_inverted);
e3f29c
               g_clear_pointer (&snippet, cogl_object_unref);
db633a
-- 
e3f29c
2.14.2
db633a