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

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