[mutter/wip/surface-content: 6/6] window-actor: Split into two subclasses of MetaSurfaceActor



commit 3144361f7d372253f36e2904280f69cbd200948b
Author: Jasper St. Pierre <jstpierre mecheye net>
Date:   Sat Feb 1 17:21:11 2014 -0500

    window-actor: Split into two subclasses of MetaSurfaceActor
    
    The rendering logic before was somewhat complex. We had three independent
    cases to take into account when doing rendering:
    
      * X11 compositor. In this case, we're a traditional X11 compositor,
        not a Wayland compositor. We use XCompositeNameWindowPixmap to get
        the backing pixmap for the window, and deal with the COMPOSITE
        extension messiness.
    
        In thi scase, meta_is_wayland_compositor() is FALSE.
    
      * Wayland clients. In this case, we're a Wayland compositor managing
        Wayland surfaces. The rendering for this is fairly straightforward,
        as Cogl handles most of the complexity with EGL and SHM buffers...
        Wayland clients give us the input and opaque regions through
        wl_surface.
    
        In this case, meta_is_wayland_compositor() is TRUE and
        priv->window->client_type == META_WINDOW_CLIENT_TYPE_WAYLAND.
    
      * XWayland clients. In this case, we're a Wayland compositor, like
        above, and XWayland hands us Wayland surfaces. XWayland handles
        the COMPOSITE extension messiness for us, and hands us a buffer
        like any other Wayland client. We have to fetch the input and
        opaque regions from the X11 window ourselves.
    
        In this case, meta_is_wayland_compositor() is TRUE and
        priv->window->client_type == META_WINDOW_CLIENT_TYPE_X11.
    
    We now split the rendering logic into two subclasses, which are:
    
      * MetaSurfaceActorX11, which handles the X11 compositor case, in that
        it uses XCompositeNameWindowPixmap to get the backing pixmap, and
        deal with all the COMPOSITE extension messiness.
    
      * MetaSurfaceActorWayland, which handles the Wayland compositor case
        for both native Wayland clients and XWayland clients. XWayland handles
        COMPOSITE for us, and handles pushing a surface over through the
        xf86-video-wayland DDX.
    
    Frame sync is still in MetaWindowActor, as it needs to work for both the
    X11 compositor and XWayland client cases. When Wayland's video display
    protocol lands, we can implement a "Wayland" backend for this, hopefully
    using our MetaWindow abstraction.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=720631

 src/Makefile.am                             |    4 +
 src/compositor/meta-surface-actor-wayland.c |  159 ++++++++
 src/compositor/meta-surface-actor-wayland.h |   65 +++
 src/compositor/meta-surface-actor-x11.c     |  551 ++++++++++++++++++++++++++
 src/compositor/meta-surface-actor-x11.h     |   69 ++++
 src/compositor/meta-surface-actor.c         |  124 +++----
 src/compositor/meta-surface-actor.h         |   45 ++-
 src/compositor/meta-window-actor.c          |  561 ++++-----------------------
 src/wayland/meta-wayland-surface.c          |   13 +-
 9 files changed, 1023 insertions(+), 568 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index 53f6f7a..42634b3 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -83,6 +83,10 @@ libmutter_wayland_la_SOURCES =                       \
        compositor/meta-shaped-texture-private.h        \
        compositor/meta-surface-actor.c         \
        compositor/meta-surface-actor.h         \
+       compositor/meta-surface-actor-x11.c     \
+       compositor/meta-surface-actor-x11.h     \
+       compositor/meta-surface-actor-wayland.c \
+       compositor/meta-surface-actor-wayland.h \
        compositor/meta-texture-rectangle.c     \
        compositor/meta-texture-rectangle.h     \
        compositor/meta-texture-tower.c         \
diff --git a/src/compositor/meta-surface-actor-wayland.c b/src/compositor/meta-surface-actor-wayland.c
new file mode 100644
index 0000000..7312795
--- /dev/null
+++ b/src/compositor/meta-surface-actor-wayland.c
@@ -0,0 +1,159 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+
+/*
+ * Copyright (C) 2013 Red Hat
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * Written by:
+ *     Jasper St. Pierre <jstpierre mecheye net>
+ */
+
+#include "config.h"
+
+#include "meta-surface-actor-wayland.h"
+
+#include <cogl/cogl-wayland-server.h>
+#include "meta-shaped-texture-private.h"
+
+struct _MetaSurfaceActorWaylandPrivate
+{
+  MetaWaylandSurface *surface;
+  MetaWaylandBuffer *buffer;
+};
+typedef struct _MetaSurfaceActorWaylandPrivate MetaSurfaceActorWaylandPrivate;
+
+G_DEFINE_TYPE_WITH_PRIVATE (MetaSurfaceActorWayland, meta_surface_actor_wayland, META_TYPE_SURFACE_ACTOR)
+
+static void
+meta_surface_actor_wayland_process_damage (MetaSurfaceActor *actor,
+                                           int x, int y, int width, int height)
+{
+  MetaSurfaceActorWayland *self = META_SURFACE_ACTOR_WAYLAND (actor);
+  MetaSurfaceActorWaylandPrivate *priv = meta_surface_actor_wayland_get_instance_private (self);
+
+  struct wl_resource *resource = priv->buffer->resource;
+  struct wl_shm_buffer *shm_buffer = wl_shm_buffer_get (resource);
+
+  if (shm_buffer)
+    {
+      CoglTexture2D *texture = COGL_TEXTURE_2D (priv->buffer->texture);
+      cogl_wayland_texture_set_region_from_shm_buffer (texture, x, y, width, height, shm_buffer, x, y, 0, 
NULL);
+    }
+
+  meta_surface_actor_redraw_area (META_SURFACE_ACTOR (self), x, y, width, height);
+}
+
+static void
+meta_surface_actor_wayland_pre_paint (MetaSurfaceActor *actor)
+{
+}
+
+static gboolean
+meta_surface_actor_wayland_is_argb32 (MetaSurfaceActor *actor)
+{
+  /* XXX -- look at the SHM buffer format. */
+  return TRUE;
+}
+
+static gboolean
+meta_surface_actor_wayland_is_visible (MetaSurfaceActor *actor)
+{
+  /* TODO: ensure that the buffer isn't NULL, implement
+   * wayland mapping semantics */
+  return TRUE;
+}
+
+static void
+meta_surface_actor_wayland_freeze (MetaSurfaceActor *actor)
+{
+}
+
+static void
+meta_surface_actor_wayland_thaw (MetaSurfaceActor *actor)
+{
+}
+
+static gboolean
+meta_surface_actor_wayland_is_frozen (MetaSurfaceActor *actor)
+{
+  return FALSE;
+}
+
+static gboolean
+meta_surface_actor_wayland_should_unredirect (MetaSurfaceActor *actor)
+{
+  return FALSE;
+}
+
+static void
+meta_surface_actor_wayland_set_unredirected (MetaSurfaceActor *actor,
+                                             gboolean          unredirected)
+{
+  /* Do nothing. In the future, we'll use KMS to set this
+   * up as a hardware overlay or something. */
+}
+
+static void
+meta_surface_actor_wayland_class_init (MetaSurfaceActorWaylandClass *klass)
+{
+  MetaSurfaceActorClass *surface_actor_class = META_SURFACE_ACTOR_CLASS (klass);
+
+  surface_actor_class->process_damage = meta_surface_actor_wayland_process_damage;
+  surface_actor_class->pre_paint = meta_surface_actor_wayland_pre_paint;
+  surface_actor_class->is_argb32 = meta_surface_actor_wayland_is_argb32;
+  surface_actor_class->is_visible = meta_surface_actor_wayland_is_visible;
+
+  surface_actor_class->freeze = meta_surface_actor_wayland_freeze;
+  surface_actor_class->thaw = meta_surface_actor_wayland_thaw;
+  surface_actor_class->is_frozen = meta_surface_actor_wayland_is_frozen;
+
+  surface_actor_class->should_unredirect = meta_surface_actor_wayland_should_unredirect;
+  surface_actor_class->set_unredirected = meta_surface_actor_wayland_set_unredirected;
+}
+
+static void
+meta_surface_actor_wayland_init (MetaSurfaceActorWayland *self)
+{
+}
+
+MetaSurfaceActor *
+meta_surface_actor_wayland_new (MetaWaylandSurface *surface)
+{
+  MetaSurfaceActorWayland *self = g_object_new (META_TYPE_SURFACE_ACTOR_WAYLAND, NULL);
+  MetaSurfaceActorWaylandPrivate *priv = meta_surface_actor_wayland_get_instance_private (self);
+
+  g_assert (meta_is_wayland_compositor ());
+
+  priv->surface = surface;
+
+  return META_SURFACE_ACTOR (self);
+}
+
+void
+meta_surface_actor_wayland_set_buffer (MetaSurfaceActorWayland *self,
+                                       MetaWaylandBuffer       *buffer)
+{
+  MetaSurfaceActorWaylandPrivate *priv = meta_surface_actor_wayland_get_instance_private (self);
+  MetaShapedTexture *stex = meta_surface_actor_get_texture (META_SURFACE_ACTOR (self));
+
+  priv->buffer = buffer;
+
+  if (buffer)
+    meta_shaped_texture_set_texture (stex, buffer->texture);
+  else
+    meta_shaped_texture_set_texture (stex, NULL);
+}
diff --git a/src/compositor/meta-surface-actor-wayland.h b/src/compositor/meta-surface-actor-wayland.h
new file mode 100644
index 0000000..2712f9d
--- /dev/null
+++ b/src/compositor/meta-surface-actor-wayland.h
@@ -0,0 +1,65 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+
+/*
+ * Copyright (C) 2013 Red Hat
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * Written by:
+ *     Jasper St. Pierre <jstpierre mecheye net>
+ */
+
+#ifndef __META_SURFACE_ACTOR_WAYLAND_H__
+#define __META_SURFACE_ACTOR_WAYLAND_H__
+
+#include <glib-object.h>
+
+#include "meta-surface-actor.h"
+
+#include "meta-wayland-private.h"
+
+G_BEGIN_DECLS
+
+#define META_TYPE_SURFACE_ACTOR_WAYLAND            (meta_surface_actor_wayland_get_type ())
+#define META_SURFACE_ACTOR_WAYLAND(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), 
META_TYPE_SURFACE_ACTOR_WAYLAND, MetaSurfaceActorWayland))
+#define META_SURFACE_ACTOR_WAYLAND_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass),  
META_TYPE_SURFACE_ACTOR_WAYLAND, MetaSurfaceActorWaylandClass))
+#define META_IS_SURFACE_ACTOR_WAYLAND(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), 
META_TYPE_SURFACE_ACTOR_WAYLAND))
+#define META_IS_SURFACE_ACTOR_WAYLAND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),  
META_TYPE_SURFACE_ACTOR_WAYLAND))
+#define META_SURFACE_ACTOR_WAYLAND_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj),  
META_TYPE_SURFACE_ACTOR_WAYLAND, MetaSurfaceActorWaylandClass))
+
+typedef struct _MetaSurfaceActorWayland      MetaSurfaceActorWayland;
+typedef struct _MetaSurfaceActorWaylandClass MetaSurfaceActorWaylandClass;
+
+struct _MetaSurfaceActorWayland
+{
+  MetaSurfaceActor parent;
+};
+
+struct _MetaSurfaceActorWaylandClass
+{
+  MetaSurfaceActorClass parent_class;
+};
+
+GType meta_surface_actor_wayland_get_type (void);
+
+MetaSurfaceActor * meta_surface_actor_wayland_new (MetaWaylandSurface *surface);
+
+void meta_surface_actor_wayland_set_buffer (MetaSurfaceActorWayland *self,
+                                              MetaWaylandBuffer         *buffer);
+
+G_END_DECLS
+
+#endif /* __META_SURFACE_ACTOR_WAYLAND_H__ */
diff --git a/src/compositor/meta-surface-actor-x11.c b/src/compositor/meta-surface-actor-x11.c
new file mode 100644
index 0000000..8f707d7
--- /dev/null
+++ b/src/compositor/meta-surface-actor-x11.c
@@ -0,0 +1,551 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+
+/*
+ * Copyright (C) 2013 Red Hat
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * Written by:
+ *     Owen Taylor <otaylor redhat com>
+ *     Jasper St. Pierre <jstpierre mecheye net>
+ */
+
+#include "config.h"
+
+#include "meta-surface-actor-x11.h"
+
+#include <X11/extensions/Xcomposite.h>
+#include <X11/extensions/Xrender.h>
+#include <cogl/cogl-texture-pixmap-x11.h>
+
+#include <meta/errors.h>
+#include "window-private.h"
+#include "meta-shaped-texture-private.h"
+#include "meta-cullable.h"
+
+struct _MetaSurfaceActorX11Private
+{
+  MetaWindow *window;
+
+  MetaDisplay *display;
+
+  CoglTexture *texture;
+  Pixmap pixmap;
+  Damage damage;
+
+  int last_width;
+  int last_height;
+
+  /* Freeze/thaw accounting */
+  guint freeze_count;
+
+  /* This is used to detect fullscreen windows that need to be unredirected */
+  guint full_damage_frames_count;
+  guint does_full_damage  : 1;
+
+  /* Other state... */
+  guint argb32 : 1;
+  guint received_damage : 1;
+  guint size_changed : 1;
+  guint needs_damage_all : 1;
+
+  guint unredirected   : 1;
+};
+typedef struct _MetaSurfaceActorX11Private MetaSurfaceActorX11Private;
+
+static void cullable_iface_init (MetaCullableInterface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (MetaSurfaceActorX11, meta_surface_actor_x11, META_TYPE_SURFACE_ACTOR,
+                         G_IMPLEMENT_INTERFACE (META_TYPE_CULLABLE, cullable_iface_init)
+                         G_ADD_PRIVATE (MetaSurfaceActorX11))
+
+static MetaCullableInterface *parent_cullable_iface;
+
+static void
+meta_surface_actor_x11_cull_out (MetaCullable   *cullable,
+                                 cairo_region_t *unobscured_region,
+                                 cairo_region_t *clip_region)
+{
+  MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (cullable);
+  MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
+
+  /* Don't do any culling for the unredirected window */
+  if (priv->unredirected)
+    return;
+
+  parent_cullable_iface->cull_out (cullable, unobscured_region, clip_region);
+}
+
+static void
+cullable_iface_init (MetaCullableInterface *iface)
+{
+  parent_cullable_iface = g_type_interface_peek_parent (iface);
+  iface->cull_out = meta_surface_actor_x11_cull_out;
+}
+
+static void
+free_damage (MetaSurfaceActorX11 *self)
+{
+  MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
+  MetaDisplay *display = priv->display;
+  Display *xdisplay = meta_display_get_xdisplay (display);
+
+  if (priv->damage == None)
+    return;
+
+  meta_error_trap_push (display);
+  XDamageDestroy (xdisplay, priv->damage);
+  priv->damage = None;
+  meta_error_trap_pop (display);
+}
+
+static void
+detach_pixmap (MetaSurfaceActorX11 *self)
+{
+  MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
+  MetaDisplay *display = priv->display;
+  Display *xdisplay = meta_display_get_xdisplay (display);
+  MetaShapedTexture *stex = meta_surface_actor_get_texture (META_SURFACE_ACTOR (self));
+
+  if (priv->pixmap == None)
+    return;
+
+  meta_error_trap_push (display);
+  XFreePixmap (xdisplay, priv->pixmap);
+  priv->pixmap = None;
+  meta_error_trap_pop (display);
+
+  meta_shaped_texture_set_texture (stex, NULL);
+
+  cogl_object_unref (priv->texture);
+  priv->texture = NULL;
+}
+
+static void
+set_pixmap (MetaSurfaceActorX11 *self,
+            Pixmap               pixmap)
+{
+  MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
+
+  CoglContext *ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
+  MetaShapedTexture *stex = meta_surface_actor_get_texture (META_SURFACE_ACTOR (self));
+  CoglTexture *texture;
+
+  g_assert (priv->pixmap == None);
+  priv->pixmap = pixmap;
+
+  texture = COGL_TEXTURE (cogl_texture_pixmap_x11_new (ctx, priv->pixmap, FALSE, NULL));
+
+  if (G_UNLIKELY (!cogl_texture_pixmap_x11_is_using_tfp_extension (COGL_TEXTURE_PIXMAP_X11 (texture))))
+    g_warning ("NOTE: Not using GLX TFP!\n");
+
+  priv->texture = texture;
+  meta_shaped_texture_set_texture (stex, texture);
+}
+
+static void
+update_pixmap (MetaSurfaceActorX11 *self)
+{
+  MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
+  MetaDisplay *display = priv->display;
+  Display *xdisplay = meta_display_get_xdisplay (display);
+
+  if (priv->size_changed)
+    {
+      detach_pixmap (self);
+      priv->size_changed = FALSE;
+    }
+
+  if (priv->pixmap == None)
+    {
+      Pixmap new_pixmap;
+      Window xwindow = meta_window_get_toplevel_xwindow (priv->window);
+
+      meta_error_trap_push (display);
+      new_pixmap = XCompositeNameWindowPixmap (xdisplay, xwindow);
+
+      if (meta_error_trap_pop_with_return (display) != Success)
+        {
+          /* Probably a BadMatch if the window isn't viewable; we could
+           * GrabServer/GetWindowAttributes/NameWindowPixmap/UngrabServer/Sync
+           * to avoid this, but there's no reason to take two round trips
+           * when one will do. (We need that Sync if we want to handle failures
+           * for any reason other than !viewable. That's unlikely, but maybe
+           * we'll BadAlloc or something.)
+           */
+          new_pixmap = None;
+        }
+
+      if (new_pixmap == None)
+        {
+          meta_verbose ("Unable to get named pixmap for %s\n",
+                        meta_window_get_description (priv->window));
+          return;
+        }
+
+      set_pixmap (self, new_pixmap);
+    }
+}
+
+static gboolean
+is_frozen (MetaSurfaceActorX11 *self)
+{
+  MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
+  return (priv->freeze_count > 0);
+}
+
+static gboolean
+is_visible (MetaSurfaceActorX11 *self)
+{
+  MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
+  return (priv->pixmap != None) && !priv->unredirected;
+}
+
+static void
+damage_area (MetaSurfaceActorX11 *self,
+             int x, int y, int width, int height)
+{
+  MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
+
+  if (!is_visible (self))
+    return;
+
+  cogl_texture_pixmap_x11_update_area (priv->texture, x, y, width, height);
+  meta_surface_actor_redraw_area (META_SURFACE_ACTOR (self), x, y, width, height);
+}
+
+static void
+damage_all (MetaSurfaceActorX11 *self)
+{
+  MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
+
+  if (!is_visible (self))
+    return;
+
+  damage_area (self, 0, 0, cogl_texture_get_width (priv->texture), cogl_texture_get_height (priv->texture));
+}
+
+static void
+meta_surface_actor_x11_process_damage (MetaSurfaceActor *actor,
+                                       int x, int y, int width, int height)
+{
+  MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (actor);
+  MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
+
+  priv->received_damage = TRUE;
+
+  if (!priv->unredirected && !priv->does_full_damage)
+    {
+      MetaRectangle window_rect;
+      meta_window_get_frame_rect (priv->window, &window_rect);
+
+      if (window_rect.x == x &&
+          window_rect.y == y &&
+          window_rect.width == width &&
+          window_rect.height == height)
+        priv->full_damage_frames_count++;
+      else
+        priv->full_damage_frames_count = 0;
+
+      if (priv->full_damage_frames_count >= 100)
+        priv->does_full_damage = TRUE;
+    }
+
+  if (is_frozen (self))
+    {
+      /* The window is frozen due to an effect in progress: we ignore damage
+       * here on the off chance that this will stop the corresponding
+       * texture_from_pixmap from being update.
+       *
+       * needs_damage_all tracks that some unknown damage happened while the
+       * window was frozen so that when the window becomes unfrozen we can
+       * issue a full window update to cover any lost damage.
+       *
+       * It should be noted that this is an unreliable mechanism since it's
+       * quite likely that drivers will aim to provide a zero-copy
+       * implementation of the texture_from_pixmap extension and in those cases
+       * any drawing done to the window is always immediately reflected in the
+       * texture regardless of damage event handling.
+       */
+      priv->needs_damage_all = TRUE;
+      return;
+    }
+
+  damage_area (self, x, y, width, height);
+}
+
+static void
+meta_surface_actor_x11_pre_paint (MetaSurfaceActor *actor)
+{
+  MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (actor);
+  MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
+  MetaDisplay *display = priv->display;
+  Display *xdisplay = meta_display_get_xdisplay (display);
+
+  if (is_frozen (self))
+    return;
+
+  if (priv->received_damage)
+    {
+      meta_error_trap_push (display);
+      XDamageSubtract (xdisplay, priv->damage, None, None);
+      meta_error_trap_pop (display);
+
+      /* We need to make sure that any X drawing that happens before the
+       * XDamageSubtract() above is visible to subsequent GL rendering;
+       * the only standardized way to do this is EXT_x11_sync_object,
+       * which isn't yet widely available. For now, we count on details
+       * of Xorg and the open source drivers, and hope for the best
+       * otherwise.
+       *
+       * Xorg and open source driver specifics:
+       *
+       * The X server makes sure to flush drawing to the kernel before
+       * sending out damage events, but since we use DamageReportBoundingBox
+       * there may be drawing between the last damage event and the
+       * XDamageSubtract() that needs to be flushed as well.
+       *
+       * Xorg always makes sure that drawing is flushed to the kernel
+       * before writing events or responses to the client, so any round trip
+       * request at this point is sufficient to flush the GLX buffers.
+       */
+      XSync (xdisplay, False);
+
+      priv->received_damage = FALSE;
+    }
+
+  update_pixmap (self);
+}
+
+static void
+meta_surface_actor_x11_freeze (MetaSurfaceActor *actor)
+{
+  MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (actor);
+  MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
+
+  priv->freeze_count ++;
+}
+
+static void
+meta_surface_actor_x11_thaw (MetaSurfaceActor *actor)
+{
+  MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (actor);
+  MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
+
+  if (priv->freeze_count == 0)
+    {
+      g_critical ("Error in freeze/thaw accounting.");
+      return;
+    }
+
+  priv->freeze_count --;
+
+  /* Since we ignore damage events while a window is frozen for certain effects
+   * we may need to issue an update_area() covering the whole pixmap if we
+   * don't know what real damage has happened. */
+  if (priv->needs_damage_all)
+    {
+      damage_all (self);
+      priv->needs_damage_all = FALSE;
+    }
+}
+
+static gboolean
+meta_surface_actor_x11_is_frozen (MetaSurfaceActor *actor)
+{
+  MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (actor);
+  return is_frozen (self);
+}
+
+static void
+update_is_argb32 (MetaSurfaceActorX11 *self)
+{
+  MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
+  MetaDisplay *display = priv->display;
+  Display *xdisplay = meta_display_get_xdisplay (display);
+
+  XRenderPictFormat *format;
+  format = XRenderFindVisualFormat (xdisplay, priv->window->xvisual);
+
+  priv->argb32 = (format && format->type == PictTypeDirect && format->direct.alphaMask);
+}
+
+static gboolean
+meta_surface_actor_x11_is_argb32 (MetaSurfaceActor *actor)
+{
+  MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (actor);
+  MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
+
+  return priv->argb32;
+}
+
+static gboolean
+meta_surface_actor_x11_is_visible (MetaSurfaceActor *actor)
+{
+  MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (actor);
+  return is_visible (self);
+}
+
+static gboolean
+meta_surface_actor_x11_should_unredirect (MetaSurfaceActor *actor)
+{
+  MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (actor);
+  MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
+
+  MetaWindow *window = priv->window;
+
+  if (meta_window_requested_dont_bypass_compositor (window))
+    return FALSE;
+
+  if (window->opacity != 0xFF)
+    return FALSE;
+
+  if (window->shape_region != NULL)
+    return FALSE;
+
+  if (priv->argb32 && !meta_window_requested_bypass_compositor (window))
+    return FALSE;
+
+  if (!meta_window_is_monitor_sized (window))
+    return FALSE;
+
+  if (meta_window_requested_bypass_compositor (window))
+    return TRUE;
+
+  if (meta_window_is_override_redirect (window))
+    return TRUE;
+
+  if (priv->does_full_damage)
+    return TRUE;
+
+  return FALSE;
+}
+
+static void
+sync_unredirected (MetaSurfaceActorX11 *self)
+{
+  MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
+  MetaDisplay *display = priv->display;
+  Display *xdisplay = meta_display_get_xdisplay (display);
+  Window xwindow = meta_window_get_toplevel_xwindow (priv->window);
+
+  meta_error_trap_push (display);
+
+  if (priv->unredirected)
+    {
+      detach_pixmap (self);
+      XCompositeUnredirectWindow (xdisplay, xwindow, CompositeRedirectManual);
+    }
+  else
+    {
+      XCompositeRedirectWindow (xdisplay, xwindow, CompositeRedirectManual);
+    }
+
+  meta_error_trap_pop (display);
+}
+
+static void
+meta_surface_actor_x11_set_unredirected (MetaSurfaceActor *actor,
+                                         gboolean          unredirected)
+{
+  MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (actor);
+  MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
+
+  if (priv->unredirected == unredirected)
+    return;
+
+  priv->unredirected = unredirected;
+  sync_unredirected (self);
+}
+
+static void
+meta_surface_actor_x11_dispose (GObject *object)
+{
+  MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (object);
+
+  detach_pixmap (self);
+  free_damage (self);
+
+  G_OBJECT_CLASS (meta_surface_actor_x11_parent_class)->dispose (object);
+}
+
+static void
+meta_surface_actor_x11_class_init (MetaSurfaceActorX11Class *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  MetaSurfaceActorClass *surface_actor_class = META_SURFACE_ACTOR_CLASS (klass);
+
+  object_class->dispose = meta_surface_actor_x11_dispose;
+
+  surface_actor_class->process_damage = meta_surface_actor_x11_process_damage;
+  surface_actor_class->pre_paint = meta_surface_actor_x11_pre_paint;
+  surface_actor_class->is_argb32 = meta_surface_actor_x11_is_argb32;
+  surface_actor_class->is_visible = meta_surface_actor_x11_is_visible;
+
+  surface_actor_class->freeze = meta_surface_actor_x11_freeze;
+  surface_actor_class->thaw = meta_surface_actor_x11_thaw;
+  surface_actor_class->is_frozen = meta_surface_actor_x11_is_frozen;
+
+  surface_actor_class->should_unredirect = meta_surface_actor_x11_should_unredirect;
+  surface_actor_class->set_unredirected = meta_surface_actor_x11_set_unredirected;
+}
+
+static void
+meta_surface_actor_x11_init (MetaSurfaceActorX11 *self)
+{
+  MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
+
+  priv->last_width = -1;
+  priv->last_height = -1;
+}
+
+MetaSurfaceActor *
+meta_surface_actor_x11_new (MetaWindow *window)
+{
+  MetaSurfaceActorX11 *self = g_object_new (META_TYPE_SURFACE_ACTOR_X11, NULL);
+  MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
+  MetaDisplay *display = meta_window_get_display (window);
+  Display *xdisplay = meta_display_get_xdisplay (display);
+  Window xwindow = meta_window_get_toplevel_xwindow (window);
+
+  g_assert (!meta_is_wayland_compositor ());
+
+  priv->window = window;
+  priv->display = display;
+
+  priv->damage = XDamageCreate (xdisplay, xwindow, XDamageReportBoundingBox);
+  update_is_argb32 (self);
+
+  priv->unredirected = FALSE;
+  sync_unredirected (self);
+
+  return META_SURFACE_ACTOR (self);
+}
+
+void
+meta_surface_actor_x11_set_size (MetaSurfaceActorX11 *self,
+                                 int width, int height)
+{
+  MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
+
+  if (priv->last_width == width &&
+      priv->last_height == height)
+    return;
+
+  priv->size_changed = TRUE;
+  priv->last_width = width;
+  priv->last_height = height;
+}
diff --git a/src/compositor/meta-surface-actor-x11.h b/src/compositor/meta-surface-actor-x11.h
new file mode 100644
index 0000000..0e692ee
--- /dev/null
+++ b/src/compositor/meta-surface-actor-x11.h
@@ -0,0 +1,69 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+
+/*
+ * Copyright (C) 2013 Red Hat
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * Written by:
+ *     Owen Taylor <otaylor redhat com>
+ *     Jasper St. Pierre <jstpierre mecheye net>
+ */
+
+#ifndef __META_SURFACE_ACTOR_X11_H__
+#define __META_SURFACE_ACTOR_X11_H__
+
+#include <glib-object.h>
+
+#include "meta-surface-actor.h"
+
+#include <X11/extensions/Xdamage.h>
+
+#include <meta/display.h>
+#include <meta/window.h>
+
+G_BEGIN_DECLS
+
+#define META_TYPE_SURFACE_ACTOR_X11            (meta_surface_actor_x11_get_type ())
+#define META_SURFACE_ACTOR_X11(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), 
META_TYPE_SURFACE_ACTOR_X11, MetaSurfaceActorX11))
+#define META_SURFACE_ACTOR_X11_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass),  
META_TYPE_SURFACE_ACTOR_X11, MetaSurfaceActorX11Class))
+#define META_IS_SURFACE_ACTOR_X11(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), 
META_TYPE_SURFACE_ACTOR_X11))
+#define META_IS_SURFACE_ACTOR_X11_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),  
META_TYPE_SURFACE_ACTOR_X11))
+#define META_SURFACE_ACTOR_X11_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj),  
META_TYPE_SURFACE_ACTOR_X11, MetaSurfaceActorX11Class))
+
+typedef struct _MetaSurfaceActorX11      MetaSurfaceActorX11;
+typedef struct _MetaSurfaceActorX11Class MetaSurfaceActorX11Class;
+
+struct _MetaSurfaceActorX11
+{
+  MetaSurfaceActor parent;
+};
+
+struct _MetaSurfaceActorX11Class
+{
+  MetaSurfaceActorClass parent_class;
+};
+
+GType meta_surface_actor_x11_get_type (void);
+
+MetaSurfaceActor * meta_surface_actor_x11_new (MetaWindow *window);
+
+void meta_surface_actor_x11_set_size (MetaSurfaceActorX11 *self,
+                                      int width, int height);
+
+G_END_DECLS
+
+#endif /* __META_SURFACE_ACTOR_X11_H__ */
diff --git a/src/compositor/meta-surface-actor.c b/src/compositor/meta-surface-actor.c
index 541094c..12ef9e3 100644
--- a/src/compositor/meta-surface-actor.c
+++ b/src/compositor/meta-surface-actor.c
@@ -10,26 +10,24 @@
  */
 
 #include <config.h>
+
+#include "meta-surface-actor.h"
+
 #include <clutter/clutter.h>
-#include <cogl/cogl-wayland-server.h>
-#include <cogl/cogl-texture-pixmap-x11.h>
 #include <meta/meta-shaped-texture.h>
-#include "meta-surface-actor.h"
 #include "meta-wayland-private.h"
 #include "meta-cullable.h"
-
 #include "meta-shaped-texture-private.h"
 
 struct _MetaSurfaceActorPrivate
 {
   MetaShapedTexture *texture;
-  MetaWaylandBuffer *buffer;
 };
 
 static void cullable_iface_init (MetaCullableInterface *iface);
 
-G_DEFINE_TYPE_WITH_CODE (MetaSurfaceActor, meta_surface_actor, CLUTTER_TYPE_ACTOR,
-                         G_IMPLEMENT_INTERFACE (META_TYPE_CULLABLE, cullable_iface_init));
+G_DEFINE_ABSTRACT_TYPE_WITH_CODE (MetaSurfaceActor, meta_surface_actor, CLUTTER_TYPE_ACTOR,
+                                  G_IMPLEMENT_INTERFACE (META_TYPE_CULLABLE, cullable_iface_init));
 
 gboolean
 meta_surface_actor_get_unobscured_bounds (MetaSurfaceActor      *self,
@@ -92,99 +90,89 @@ meta_surface_actor_get_texture (MetaSurfaceActor *self)
   return self->priv->texture;
 }
 
-static void
-update_area (MetaSurfaceActor *self,
-             int x, int y, int width, int height)
+gboolean
+meta_surface_actor_redraw_area (MetaSurfaceActor *self,
+                                int x, int y, int width, int height)
 {
   MetaSurfaceActorPrivate *priv = self->priv;
-
-  if (meta_is_wayland_compositor ())
-    {
-      struct wl_resource *resource = priv->buffer->resource;
-      struct wl_shm_buffer *shm_buffer = wl_shm_buffer_get (resource);
-
-      if (shm_buffer)
-        {
-          CoglTexture2D *texture = COGL_TEXTURE_2D (priv->buffer->texture);
-          cogl_wayland_texture_set_region_from_shm_buffer (texture, x, y, width, height, shm_buffer, x, y, 
0, NULL);
-        }
-    }
-  else
-    {
-      CoglTexturePixmapX11 *texture = COGL_TEXTURE_PIXMAP_X11 (meta_shaped_texture_get_texture 
(priv->texture));
-      cogl_texture_pixmap_x11_update_area (texture, x, y, width, height);
-    }
+  return meta_shaped_texture_update_area (priv->texture, x, y, width, height);
 }
 
 gboolean
-meta_surface_actor_damage_all (MetaSurfaceActor *self)
+meta_surface_actor_is_obscured (MetaSurfaceActor *self)
 {
   MetaSurfaceActorPrivate *priv = self->priv;
-  CoglTexture *texture = meta_shaped_texture_get_texture (priv->texture);
-
-  update_area (self, 0, 0, cogl_texture_get_width (texture), cogl_texture_get_height (texture));
-  return meta_shaped_texture_update_area (priv->texture, 0, 0, cogl_texture_get_width (texture), 
cogl_texture_get_height (texture));
+  return meta_shaped_texture_is_obscured (priv->texture);
 }
 
-gboolean
-meta_surface_actor_damage_area (MetaSurfaceActor *self,
-                                int               x,
-                                int               y,
-                                int               width,
-                                int               height)
+void
+meta_surface_actor_set_input_region (MetaSurfaceActor *self,
+                                     cairo_region_t   *region)
 {
   MetaSurfaceActorPrivate *priv = self->priv;
-
-  update_area (self, x, y, width, height);
-  return meta_shaped_texture_update_area (priv->texture, x, y, width, height);
+  meta_shaped_texture_set_input_shape_region (priv->texture, region);
 }
 
-gboolean
-meta_surface_actor_is_obscured (MetaSurfaceActor *self)
+void
+meta_surface_actor_set_opaque_region (MetaSurfaceActor *self,
+                                      cairo_region_t   *region)
 {
   MetaSurfaceActorPrivate *priv = self->priv;
-  return meta_shaped_texture_is_obscured (priv->texture);
+  meta_shaped_texture_set_opaque_region (priv->texture, region);
 }
 
 void
-meta_surface_actor_attach_wayland_buffer (MetaSurfaceActor *self,
-                                          MetaWaylandBuffer *buffer)
+meta_surface_actor_process_damage (MetaSurfaceActor *actor,
+                                   int x, int y, int width, int height)
 {
-  MetaSurfaceActorPrivate *priv = self->priv;
-  priv->buffer = buffer;
-
-  if (buffer)
-    meta_shaped_texture_set_texture (priv->texture, buffer->texture);
-  else
-    meta_shaped_texture_set_texture (priv->texture, NULL);
+  META_SURFACE_ACTOR_GET_CLASS (actor)->process_damage (actor, x, y, width, height);
 }
 
 void
-meta_surface_actor_set_texture (MetaSurfaceActor *self,
-                                CoglTexture      *texture)
+meta_surface_actor_pre_paint (MetaSurfaceActor *actor)
 {
-  MetaSurfaceActorPrivate *priv = self->priv;
-  meta_shaped_texture_set_texture (priv->texture, texture);
+  META_SURFACE_ACTOR_GET_CLASS (actor)->pre_paint (actor);
+}
+
+gboolean
+meta_surface_actor_is_argb32 (MetaSurfaceActor *actor)
+{
+  return META_SURFACE_ACTOR_GET_CLASS (actor)->is_argb32 (actor);
+}
+
+gboolean
+meta_surface_actor_is_visible (MetaSurfaceActor *actor)
+{
+  return META_SURFACE_ACTOR_GET_CLASS (actor)->is_visible (actor);
 }
 
 void
-meta_surface_actor_set_input_region (MetaSurfaceActor *self,
-                                     cairo_region_t   *region)
+meta_surface_actor_freeze (MetaSurfaceActor *actor)
 {
-  MetaSurfaceActorPrivate *priv = self->priv;
-  meta_shaped_texture_set_input_shape_region (priv->texture, region);
+  META_SURFACE_ACTOR_GET_CLASS (actor)->freeze (actor);
 }
 
 void
-meta_surface_actor_set_opaque_region (MetaSurfaceActor *self,
-                                      cairo_region_t   *region)
+meta_surface_actor_thaw (MetaSurfaceActor *actor)
 {
-  MetaSurfaceActorPrivate *priv = self->priv;
-  meta_shaped_texture_set_opaque_region (priv->texture, region);
+  META_SURFACE_ACTOR_GET_CLASS (actor)->thaw (actor);
 }
 
-MetaSurfaceActor *
-meta_surface_actor_new (void)
+gboolean
+meta_surface_actor_is_frozen (MetaSurfaceActor *actor)
+{
+  return META_SURFACE_ACTOR_GET_CLASS (actor)->is_frozen (actor);
+}
+
+gboolean
+meta_surface_actor_should_unredirect (MetaSurfaceActor *actor)
+{
+  return META_SURFACE_ACTOR_GET_CLASS (actor)->should_unredirect (actor);
+}
+
+void
+meta_surface_actor_set_unredirected (MetaSurfaceActor *actor,
+                                     gboolean          unredirected)
 {
-  return g_object_new (META_TYPE_SURFACE_ACTOR, NULL);
+  META_SURFACE_ACTOR_GET_CLASS (actor)->set_unredirected (actor, unredirected);
 }
diff --git a/src/compositor/meta-surface-actor.h b/src/compositor/meta-surface-actor.h
index fa7f0c3..26f9891 100644
--- a/src/compositor/meta-surface-actor.h
+++ b/src/compositor/meta-surface-actor.h
@@ -6,7 +6,6 @@
 #include <config.h>
 
 #include <meta/meta-shaped-texture.h>
-#include "meta-wayland-types.h"
 
 G_BEGIN_DECLS
 
@@ -25,6 +24,20 @@ struct _MetaSurfaceActorClass
 {
   /*< private >*/
   ClutterActorClass parent_class;
+
+  void     (* process_damage)    (MetaSurfaceActor *actor,
+                                  int x, int y, int width, int height);
+  void     (* pre_paint)         (MetaSurfaceActor *actor);
+  gboolean (* is_argb32)         (MetaSurfaceActor *actor);
+  gboolean (* is_visible)        (MetaSurfaceActor *actor);
+
+  void     (* freeze)            (MetaSurfaceActor *actor);
+  void     (* thaw)              (MetaSurfaceActor *actor);
+  gboolean (* is_frozen)         (MetaSurfaceActor *actor);
+
+  gboolean (* should_unredirect) (MetaSurfaceActor *actor);
+  void     (* set_unredirected)  (MetaSurfaceActor *actor,
+                                  gboolean          unredirected);
 };
 
 struct _MetaSurfaceActor
@@ -36,33 +49,37 @@ struct _MetaSurfaceActor
 
 GType meta_surface_actor_get_type (void);
 
-MetaSurfaceActor *meta_surface_actor_new (void);
-
 cairo_surface_t *meta_surface_actor_get_image (MetaSurfaceActor      *self,
                                                cairo_rectangle_int_t *clip);
 
 MetaShapedTexture *meta_surface_actor_get_texture (MetaSurfaceActor *self);
 
-gboolean meta_surface_actor_damage_all  (MetaSurfaceActor *self);
-gboolean meta_surface_actor_damage_area (MetaSurfaceActor *self,
-                                         int               x,
-                                         int               y,
-                                         int               width,
-                                         int               height);
-
 gboolean meta_surface_actor_is_obscured (MetaSurfaceActor *self);
 gboolean meta_surface_actor_get_unobscured_bounds (MetaSurfaceActor      *self,
                                                    cairo_rectangle_int_t *unobscured_bounds);
 
-void meta_surface_actor_set_texture (MetaSurfaceActor *self,
-                                     CoglTexture      *texture);
-void meta_surface_actor_attach_wayland_buffer (MetaSurfaceActor  *self,
-                                               MetaWaylandBuffer *buffer);
 void meta_surface_actor_set_input_region (MetaSurfaceActor *self,
                                           cairo_region_t   *region);
 void meta_surface_actor_set_opaque_region (MetaSurfaceActor *self,
                                            cairo_region_t   *region);
 
+gboolean meta_surface_actor_redraw_area (MetaSurfaceActor *actor,
+                                         int x, int y, int width, int height);
+
+void meta_surface_actor_process_damage (MetaSurfaceActor *actor,
+                                        int x, int y, int width, int height);
+void meta_surface_actor_pre_paint (MetaSurfaceActor *actor);
+gboolean meta_surface_actor_is_argb32 (MetaSurfaceActor *actor);
+gboolean meta_surface_actor_is_visible (MetaSurfaceActor *actor);
+
+void meta_surface_actor_freeze (MetaSurfaceActor *actor);
+void meta_surface_actor_thaw (MetaSurfaceActor *actor);
+gboolean meta_surface_actor_is_frozen (MetaSurfaceActor *actor);
+
+gboolean meta_surface_actor_should_unredirect (MetaSurfaceActor *actor);
+void meta_surface_actor_set_unredirected (MetaSurfaceActor *actor,
+                                          gboolean          unredirected);
+
 G_END_DECLS
 
 #endif /* META_SURFACE_ACTOR_PRIVATE_H */
diff --git a/src/compositor/meta-window-actor.c b/src/compositor/meta-window-actor.c
index 4fee87e..f264de3 100644
--- a/src/compositor/meta-window-actor.c
+++ b/src/compositor/meta-window-actor.c
@@ -10,10 +10,6 @@
 
 #include <math.h>
 
-#include <X11/extensions/Xcomposite.h>
-#include <X11/extensions/Xdamage.h>
-#include <X11/extensions/Xrender.h>
-
 #include <clutter/x11/clutter-x11.h>
 #include <cogl/cogl-texture-pixmap-x11.h>
 #include <gdk/gdk.h> /* for gdk_rectangle_union() */
@@ -30,13 +26,15 @@
 #include "meta-shaped-texture-private.h"
 #include "meta-shadow-factory-private.h"
 #include "meta-window-actor-private.h"
-#include "meta-surface-actor.h"
 #include "meta-texture-rectangle.h"
 #include "region-utils.h"
 #include "meta-wayland-private.h"
 #include "monitor-private.h"
 #include "meta-cullable.h"
 
+#include "meta-surface-actor.h"
+#include "meta-surface-actor-x11.h"
+
 struct _MetaWindowActorPrivate
 {
   MetaWindow       *window;
@@ -63,19 +61,13 @@ struct _MetaWindowActorPrivate
   /* The region we should clip to when painting the shadow */
   cairo_region_t   *shadow_clip;
 
-  guint              send_frame_messages_timer;
-  gint64             frame_drawn_time;
-
   /* Extracted size-invariant shape used for shadows */
   MetaWindowShape  *shadow_shape;
-
-  gint              last_width;
-  gint              last_height;
-
-  gint              freeze_count;
-
   char *            shadow_class;
 
+  guint              send_frame_messages_timer;
+  gint64             frame_drawn_time;
+
   /*
    * These need to be counters rather than flags, since more plugins
    * can implement same effect; the practicality of stacking effects
@@ -90,11 +82,7 @@ struct _MetaWindowActorPrivate
   /* List of FrameData for recent frames */
   GList            *frames;
 
-  Pixmap            back_pixmap; /* Not used in wayland compositor mode */
-  Damage            damage; /* Not used in wayland compositor mode */
-
   guint                    visible                : 1;
-  guint                    argb32                 : 1;
   guint                    disposed               : 1;
   guint             redecorating           : 1;
 
@@ -111,24 +99,7 @@ struct _MetaWindowActorPrivate
 
   guint             no_shadow              : 1;
 
-
-  /* 
-   * None of these are used in wayland compositor mode...
-   */
-
-  guint                    needs_damage_all       : 1;
-  guint                    received_x11_damage    : 1;
-
-  guint                    needs_pixmap           : 1;
-
-  guint                    x11_size_changed       : 1;
   guint             updates_frozen         : 1;
-
-  guint             unredirected           : 1;
-
-  /* This is used to detect fullscreen windows that need to be unredirected */
-  guint             full_damage_frames_count;
-  guint             does_full_damage  : 1;
 };
 
 typedef struct _FrameData FrameData;
@@ -165,7 +136,6 @@ static gboolean meta_window_actor_get_paint_volume (ClutterActor       *actor,
                                                     ClutterPaintVolume *volume);
 
 
-static void meta_window_actor_detach_x11_pixmap     (MetaWindowActor *self);
 static gboolean meta_window_actor_has_shadow (MetaWindowActor *self);
 
 static void meta_window_actor_handle_updates (MetaWindowActor *self);
@@ -256,9 +226,6 @@ window_decorated_notify (MetaWindow *mw,
 {
   MetaWindowActor        *self     = META_WINDOW_ACTOR (data);
   MetaWindowActorPrivate *priv     = self->priv;
-  MetaScreen             *screen   = priv->screen;
-  MetaDisplay            *display  = meta_screen_get_display (screen);
-  Display                *xdisplay = meta_display_get_xdisplay (display);
 
   /*
    * Basically, we have to reconstruct the the internals of this object
@@ -266,23 +233,6 @@ window_decorated_notify (MetaWindow *mw,
    */
   priv->redecorating = TRUE;
 
-  if (!meta_is_wayland_compositor ())
-    {
-      meta_window_actor_detach_x11_pixmap (self);
-
-      /*
-       * First of all, clean up any resources we are currently using and will
-       * be replacing.
-       */
-      if (priv->damage != None)
-        {
-          meta_error_trap_push (display);
-          XDamageDestroy (xdisplay, priv->damage);
-          meta_error_trap_pop (display);
-          priv->damage = None;
-        }
-    }
-
   /*
    * Recreate the contents.
    */
@@ -308,52 +258,68 @@ surface_allocation_changed_notify (ClutterActor           *actor,
 }
 
 static gboolean
+is_argb32 (MetaWindowActor *self)
+{
+  MetaWindowActorPrivate *priv = self->priv;
+  return meta_surface_actor_is_argb32 (priv->surface);
+}
+
+static gboolean
 is_non_opaque (MetaWindowActor *self)
 {
   MetaWindowActorPrivate *priv = self->priv;
   MetaWindow *window = priv->window;
 
-  return priv->argb32 || (window->opacity != 0xFF);
+  return is_argb32 (self) || (window->opacity != 0xFF);
+}
+
+static gboolean
+is_frozen (MetaWindowActor *self)
+{
+  MetaWindowActorPrivate *priv = self->priv;
+  return meta_surface_actor_is_frozen (priv->surface);
 }
 
 static void
-meta_window_actor_constructed (GObject *object)
+meta_window_actor_freeze (MetaWindowActor *self)
 {
-  MetaWindowActor        *self     = META_WINDOW_ACTOR (object);
-  MetaWindowActorPrivate *priv     = self->priv;
-  MetaWindow             *window   = priv->window;
-  Window                  xwindow  = meta_window_get_toplevel_xwindow (window);
-  MetaScreen             *screen   = meta_window_get_screen (window);
-  MetaDisplay            *display  = meta_screen_get_display (screen);
-  Display                *xdisplay = meta_display_get_xdisplay (display);
+  MetaWindowActorPrivate *priv = self->priv;
+  meta_surface_actor_freeze (priv->surface);
+}
 
-  priv->screen = screen;
+static void
+meta_window_actor_thaw (MetaWindowActor *self)
+{
+  MetaWindowActorPrivate *priv = self->priv;
 
-  if (!meta_is_wayland_compositor ())
-    priv->damage = XDamageCreate (xdisplay, xwindow,
-                                  XDamageReportBoundingBox);
+  meta_surface_actor_thaw (priv->surface);
 
-  if (window->client_type == META_WINDOW_CLIENT_TYPE_X11)
-    {
-      XRenderPictFormat      *format;
+  if (meta_surface_actor_is_frozen (priv->surface))
+    return;
 
-      format = XRenderFindVisualFormat (xdisplay, window->xvisual);
+  /* We sometimes ignore moves and resizes on frozen windows */
+  meta_window_actor_sync_actor_geometry (self, FALSE);
 
-      if (format && format->type == PictTypeDirect && format->direct.alphaMask)
-        priv->argb32 = TRUE;
-    }
-  else
-    {
-      /* XXX: parse shm formats to determine argb32 */
-      priv->argb32 = TRUE;
-    }
+  /* We do this now since we might be going right back into the
+   * frozen state */
+  meta_window_actor_handle_updates (self);
+}
+
+static void
+meta_window_actor_constructed (GObject *object)
+{
+  MetaWindowActor        *self     = META_WINDOW_ACTOR (object);
+  MetaWindowActorPrivate *priv     = self->priv;
+  MetaWindow             *window   = priv->window;
+
+  priv->screen = window->screen;
 
   if (!priv->surface)
     {
       if (window->surface)
         priv->surface = window->surface->surface_actor;
       else
-        priv->surface = meta_surface_actor_new ();
+        priv->surface = meta_surface_actor_x11_new (window);
       g_object_ref_sink (priv->surface);
 
       clutter_actor_add_child (CLUTTER_ACTOR (self), CLUTTER_ACTOR (priv->surface));
@@ -376,8 +342,6 @@ meta_window_actor_dispose (GObject *object)
   MetaWindowActor        *self = META_WINDOW_ACTOR (object);
   MetaWindowActorPrivate *priv = self->priv;
   MetaScreen             *screen;
-  MetaDisplay            *display;
-  Display                *xdisplay;
   MetaCompScreen         *info;
 
   if (priv->disposed)
@@ -388,9 +352,6 @@ meta_window_actor_dispose (GObject *object)
   screen   = priv->screen;
   info     = meta_screen_get_compositor_data (screen);
 
-  if (!meta_is_wayland_compositor ())
-    meta_window_actor_detach_x11_pixmap (self);
-
   if (priv->send_frame_messages_timer != 0)
     {
       g_source_remove (priv->send_frame_messages_timer);
@@ -405,18 +366,6 @@ meta_window_actor_dispose (GObject *object)
   g_clear_pointer (&priv->unfocused_shadow, meta_shadow_unref);
   g_clear_pointer (&priv->shadow_shape, meta_window_shape_unref);
 
-  if (!meta_is_wayland_compositor () && priv->damage != None)
-    {
-      display  = meta_screen_get_display (screen);
-      xdisplay = meta_display_get_xdisplay (display);
-
-      meta_error_trap_push (display);
-      XDamageDestroy (xdisplay, priv->damage);
-      meta_error_trap_pop (display);
-
-      priv->damage = None;
-    }
-
   info->windows = g_list_remove (info->windows, (gconstpointer) self);
 
   g_clear_object (&priv->window);
@@ -827,13 +776,6 @@ meta_window_actor_is_destroyed (MetaWindowActor *self)
   return self->priv->disposed;
 }
 
-static void
-meta_window_actor_freeze (MetaWindowActor *self)
-{
-  if (!meta_is_wayland_compositor ())
-    self->priv->freeze_count++;
-}
-
 static gboolean
 send_frame_messages_timeout (gpointer data)
 {
@@ -888,56 +830,6 @@ queue_send_frame_messages_timeout (MetaWindowActor *self)
   priv->send_frame_messages_timer = g_timeout_add_full (META_PRIORITY_REDRAW, offset, 
send_frame_messages_timeout, self, NULL);
 }
 
-static void
-meta_window_actor_damage_all (MetaWindowActor *self)
-{
-  MetaWindowActorPrivate *priv = self->priv;
-  gboolean redraw_queued;
-
-  if (!priv->needs_damage_all)
-    return;
-
-  if (priv->needs_pixmap)
-    return;
-
-  redraw_queued = meta_surface_actor_damage_all (priv->surface);
-
-  priv->repaint_scheduled = priv->repaint_scheduled || redraw_queued;
-  priv->needs_damage_all = FALSE;
-}
-
-static void
-meta_window_actor_thaw (MetaWindowActor *self)
-{
-  if (!meta_is_wayland_compositor ())
-    {
-      self->priv->freeze_count--;
-
-      if (G_UNLIKELY (self->priv->freeze_count < 0))
-        {
-          g_warning ("Error in freeze/thaw accounting.");
-          self->priv->freeze_count = 0;
-          return;
-        }
-
-      if (self->priv->freeze_count)
-        return;
-
-      /* We sometimes ignore moves and resizes on frozen windows */
-      meta_window_actor_sync_actor_geometry (self, FALSE);
-
-      /* We do this now since we might be going right back into the
-       * frozen state */
-      meta_window_actor_handle_updates (self);
-
-      /* Since we ignore damage events while a window is frozen for certain effects
-       * we may need to issue an update_area() covering the whole pixmap if we
-       * don't know what real damage has happened. */
-      if (self->priv->needs_damage_all)
-        meta_window_actor_damage_all (self);
-    }
-}
-
 void
 meta_window_actor_queue_frame_drawn (MetaWindowActor *self,
                                      gboolean         no_delay_frame)
@@ -993,33 +885,6 @@ meta_window_actor_effect_in_progress (MetaWindowActor *self)
 }
 
 static gboolean
-is_frozen (MetaWindowActor *self)
-{
-  return self->priv->freeze_count ? TRUE : FALSE;
-}
-
-static void
-meta_window_actor_queue_create_x11_pixmap (MetaWindowActor *self)
-{
-  MetaWindowActorPrivate *priv = self->priv;
-
-  priv->needs_pixmap = TRUE;
-
-  if (is_frozen (self))
-    return;
-
-  /* This will cause the compositor paint function to be run
-   * if the actor is visible or a clone of the actor is visible.
-   * if the actor isn't visible in any way, then we don't
-   * need to repair the window anyways, and can wait until
-   * the stage is redrawn for some other reason
-   *
-   * The compositor paint function repairs all windows.
-   */
-  clutter_actor_queue_redraw (CLUTTER_ACTOR (priv->surface));
-}
-
-static gboolean
 is_freeze_thaw_effect (gulong event)
 {
   switch (event)
@@ -1099,12 +964,6 @@ meta_window_actor_after_effects (MetaWindowActor *self)
 
   meta_window_actor_sync_visibility (self);
   meta_window_actor_sync_actor_geometry (self, FALSE);
-
-  if (!meta_is_wayland_compositor ())
-    {
-      if (priv->needs_pixmap)
-        clutter_actor_queue_redraw (CLUTTER_ACTOR (priv->surface));
-    }
 }
 
 void
@@ -1179,95 +1038,19 @@ meta_window_actor_effect_completed (MetaWindowActor *self,
     meta_window_actor_after_effects (self);
 }
 
-/* Called to drop our reference to a window backing pixmap that we
- * previously obtained with XCompositeNameWindowPixmap. We do this
- * when the window is unmapped or when we want to update to a new
- * pixmap for a new size.
- */
-static void
-meta_window_actor_detach_x11_pixmap (MetaWindowActor *self)
-{
-  MetaWindowActorPrivate *priv     = self->priv;
-  MetaScreen            *screen   = priv->screen;
-  MetaDisplay           *display  = meta_screen_get_display (screen);
-  Display               *xdisplay = meta_display_get_xdisplay (display);
-
-  if (!priv->back_pixmap)
-    return;
-
-  /* Get rid of all references to the pixmap before freeing it; it's unclear whether
-   * you are supposed to be able to free a GLXPixmap after freeing the underlying
-   * pixmap, but it certainly doesn't work with current DRI/Mesa
-   */
-  meta_surface_actor_set_texture (priv->surface, NULL);
-  cogl_flush();
-
-  XFreePixmap (xdisplay, priv->back_pixmap);
-  priv->back_pixmap = None;
-
-  meta_window_actor_queue_create_x11_pixmap (self);
-}
-
 gboolean
 meta_window_actor_should_unredirect (MetaWindowActor *self)
 {
-  MetaWindow *metaWindow = meta_window_actor_get_meta_window (self);
   MetaWindowActorPrivate *priv = self->priv;
-
-  if (meta_is_wayland_compositor ())
-    return FALSE;
-
-  if (meta_window_requested_dont_bypass_compositor (metaWindow))
-    return FALSE;
-
-  if (metaWindow->opacity != 0xFF)
-    return FALSE;
-
-  if (metaWindow->shape_region != NULL)
-    return FALSE;
-
-  if (priv->argb32 && !meta_window_requested_bypass_compositor (metaWindow))
-    return FALSE;
-
-  if (!meta_window_is_monitor_sized (metaWindow))
-    return FALSE;
-
-  if (meta_window_requested_bypass_compositor (metaWindow))
-    return TRUE;
-
-  if (meta_window_is_override_redirect (metaWindow))
-    return TRUE;
-
-  if (priv->does_full_damage)
-    return TRUE;
-
-  return FALSE;
+  return meta_surface_actor_should_unredirect (priv->surface);
 }
 
 void
 meta_window_actor_set_unredirected (MetaWindowActor *self,
                                     gboolean         unredirected)
 {
-  MetaWindow *metaWindow = meta_window_actor_get_meta_window (self);
-  MetaDisplay *display = meta_window_get_display (metaWindow);
-
-  Display *xdisplay = meta_display_get_xdisplay (display);
-  Window  xwin = meta_window_get_toplevel_xwindow (metaWindow);
-
-  meta_error_trap_push (display);
-
-  if (unredirected)
-    {
-      XCompositeUnredirectWindow (xdisplay, xwin, CompositeRedirectManual);
-    }
-  else
-    {
-      XCompositeRedirectWindow (xdisplay, xwin, CompositeRedirectManual);
-      meta_window_actor_detach_x11_pixmap (self);
-    }
-
-  self->priv->unredirected = unredirected;
-  meta_error_trap_pop (display);
+  MetaWindowActorPrivate *priv = self->priv;
+  meta_surface_actor_set_unredirected (priv->surface, unredirected);
 }
 
 void
@@ -1327,19 +1110,11 @@ meta_window_actor_sync_actor_geometry (MetaWindowActor *self,
 
   meta_window_get_input_rect (priv->window, &window_rect);
 
-  /* When running as a display server we catch size changes when new
-     buffers are attached */
-  if (!meta_is_wayland_compositor ())
-    {
-      if (priv->last_width != window_rect.width ||
-          priv->last_height != window_rect.height)
-        {
-          priv->x11_size_changed = TRUE;
-
-          priv->last_width = window_rect.width;
-          priv->last_height = window_rect.height;
-        }
-    }
+  /* When running as a Wayland compositor we catch size changes when new
+   * buffers are attached */
+  if (META_IS_SURFACE_ACTOR_X11 (priv->surface))
+    meta_surface_actor_x11_set_size (META_SURFACE_ACTOR_X11 (priv->surface),
+                                     window_rect.width, window_rect.height);
 
   /* Normally we want freezing a window to also freeze its position; this allows
    * windows to atomically move and resize together, either under app control,
@@ -1351,15 +1126,6 @@ meta_window_actor_sync_actor_geometry (MetaWindowActor *self,
   if (is_frozen (self) && !did_placement)
     return;
 
-  if (!meta_is_wayland_compositor ())
-    {
-      if (priv->x11_size_changed)
-        {
-          meta_window_actor_queue_create_x11_pixmap (self);
-          meta_window_actor_update_shape (self);
-        }
-    }
-
   if (meta_window_actor_effect_in_progress (self))
     return;
 
@@ -1527,14 +1293,10 @@ meta_window_actor_new (MetaWindow *window)
 
   priv = self->priv;
 
-  if (!meta_is_wayland_compositor ())
-    {
-      priv->last_width = -1;
-      priv->last_height = -1;
-
-      meta_window_actor_set_updates_frozen (self,
-                                            meta_window_updates_are_frozen (priv->window));
+  meta_window_actor_set_updates_frozen (self, meta_window_updates_are_frozen (priv->window));
 
+  if (META_IS_SURFACE_ACTOR_X11 (priv->surface))
+    {
       /* If a window doesn't start off with updates frozen, we should
        * we should send a _NET_WM_FRAME_DRAWN immediately after the first drawn.
        */
@@ -1651,11 +1413,6 @@ meta_window_actor_cull_out (MetaCullable   *cullable,
                             cairo_region_t *clip_region)
 {
   MetaWindowActor *self = META_WINDOW_ACTOR (cullable);
-  MetaWindowActorPrivate *priv = self->priv;
-
-  /* Don't do any culling for the unredirected window */
-  if (priv->unredirected)
-    return;
 
   meta_cullable_cull_out_children (cullable, unobscured_region, clip_region);
   meta_window_actor_set_clip_region_beneath (self, clip_region);
@@ -1679,74 +1436,6 @@ cullable_iface_init (MetaCullableInterface *iface)
   iface->reset_culling = meta_window_actor_reset_culling;
 }
 
-/* When running as a wayland compositor we don't make requests for
- * replacement pixmaps when resizing windows, we will instead be
- * asked to attach replacement buffers by the clients. */
-static void
-check_needs_x11_pixmap (MetaWindowActor *self)
-{
-  MetaWindowActorPrivate *priv     = self->priv;
-  MetaScreen          *screen   = priv->screen;
-  MetaDisplay         *display  = meta_screen_get_display (screen);
-  Display             *xdisplay = meta_display_get_xdisplay (display);
-  MetaCompScreen      *info     = meta_screen_get_compositor_data (screen);
-  Window               xwindow  = meta_window_get_toplevel_xwindow (priv->window);
-
-  if (!priv->needs_pixmap)
-    return;
-
-  if (xwindow == meta_screen_get_xroot (screen) ||
-      xwindow == clutter_x11_get_stage_window (CLUTTER_STAGE (info->stage)))
-    return;
-
-  if (priv->x11_size_changed)
-    {
-      meta_window_actor_detach_x11_pixmap (self);
-      priv->x11_size_changed = FALSE;
-    }
-
-  meta_error_trap_push (display);
-
-  if (priv->back_pixmap == None)
-    {
-      CoglContext *ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
-      CoglTexture *texture;
-
-      meta_error_trap_push (display);
-
-      priv->back_pixmap = XCompositeNameWindowPixmap (xdisplay, xwindow);
-
-      if (meta_error_trap_pop_with_return (display) != Success)
-        {
-          /* Probably a BadMatch if the window isn't viewable; we could
-           * GrabServer/GetWindowAttributes/NameWindowPixmap/UngrabServer/Sync
-           * to avoid this, but there's no reason to take two round trips
-           * when one will do. (We need that Sync if we want to handle failures
-           * for any reason other than !viewable. That's unlikely, but maybe
-           * we'll BadAlloc or something.)
-           */
-          priv->back_pixmap = None;
-        }
-
-      if (priv->back_pixmap == None)
-        {
-          meta_verbose ("Unable to get named pixmap for %p\n", self);
-          goto out;
-        }
-
-      texture = COGL_TEXTURE (cogl_texture_pixmap_x11_new (ctx, priv->back_pixmap, FALSE, NULL));
-      if (G_UNLIKELY (!cogl_texture_pixmap_x11_is_using_tfp_extension (COGL_TEXTURE_PIXMAP_X11 (texture))))
-        g_warning ("NOTE: Not using GLX TFP!\n");
-
-      meta_surface_actor_set_texture (META_SURFACE_ACTOR (priv->surface), texture);
-    }
-
-  priv->needs_pixmap = FALSE;
-
- out:
-  meta_error_trap_pop (display);
-}
-
 static void
 check_needs_shadow (MetaWindowActor *self)
 {
@@ -1814,63 +1503,14 @@ meta_window_actor_process_x11_damage (MetaWindowActor    *self,
                                       XDamageNotifyEvent *event)
 {
   MetaWindowActorPrivate *priv = self->priv;
-  MetaCompScreen *info = meta_screen_get_compositor_data (priv->screen);
-  gboolean redraw_queued;
 
-  priv->received_x11_damage = TRUE;
-
-  if (meta_window_is_fullscreen (priv->window) && g_list_last (info->windows)->data == self && 
!priv->unredirected)
-    {
-      MetaRectangle window_rect;
-      meta_window_get_frame_rect (priv->window, &window_rect);
-
-      if (window_rect.x == event->area.x &&
-          window_rect.y == event->area.y &&
-          window_rect.width == event->area.width &&
-          window_rect.height == event->area.height)
-        priv->full_damage_frames_count++;
-      else
-        priv->full_damage_frames_count = 0;
-
-      if (priv->full_damage_frames_count >= 100)
-        priv->does_full_damage = TRUE;
-    }
-
-  /* Drop damage event for unredirected windows */
-  if (priv->unredirected)
-    return;
-
-  if (is_frozen (self))
-    {
-      /* The window is frozen due to an effect in progress: we ignore damage
-       * here on the off chance that this will stop the corresponding
-       * texture_from_pixmap from being update.
-       *
-       * needs_damage_all tracks that some unknown damage happened while the
-       * window was frozen so that when the window becomes unfrozen we can
-       * issue a full window update to cover any lost damage.
-       *
-       * It should be noted that this is an unreliable mechanism since it's
-       * quite likely that drivers will aim to provide a zero-copy
-       * implementation of the texture_from_pixmap extension and in those cases
-       * any drawing done to the window is always immediately reflected in the
-       * texture regardless of damage event handling.
-       */
-      priv->needs_damage_all = TRUE;
-      return;
-    }
-
-  if (priv->needs_pixmap)
-    return;
-
-  redraw_queued = meta_surface_actor_damage_area (priv->surface,
-                                                  event->area.x,
-                                                  event->area.y,
-                                                  event->area.width,
-                                                  event->area.height);
-
-  priv->repaint_scheduled = priv->repaint_scheduled  || redraw_queued;
+  g_assert (!meta_is_wayland_compositor ());
 
+  meta_surface_actor_process_damage (priv->surface,
+                                     event->area.x,
+                                     event->area.y,
+                                     event->area.width,
+                                     event->area.height);
 }
 
 void
@@ -2098,8 +1738,9 @@ meta_window_actor_update_opaque_region (MetaWindowActor *self)
 {
   MetaWindowActorPrivate *priv = self->priv;
   cairo_region_t *opaque_region;
+  gboolean argb32 = is_argb32 (self);
 
-  if (priv->argb32 && priv->window->opaque_region != NULL)
+  if (argb32 && priv->window->opaque_region != NULL)
     {
       MetaFrameBorders borders;
 
@@ -2119,7 +1760,7 @@ meta_window_actor_update_opaque_region (MetaWindowActor *self)
       cairo_region_translate (opaque_region, borders.total.left, borders.total.top);
       cairo_region_intersect (opaque_region, priv->shape_region);
     }
-  else if (priv->argb32)
+  else if (argb32)
     opaque_region = NULL;
   else
     opaque_region = cairo_region_reference (priv->shape_region);
@@ -2176,9 +1817,6 @@ static void
 meta_window_actor_handle_updates (MetaWindowActor *self)
 {
   MetaWindowActorPrivate *priv = self->priv;
-  MetaScreen          *screen   = priv->screen;
-  MetaDisplay         *display  = meta_screen_get_display (screen);
-  Display             *xdisplay = meta_display_get_xdisplay (display);
 
   if (is_frozen (self))
     {
@@ -2187,45 +1825,10 @@ meta_window_actor_handle_updates (MetaWindowActor *self)
       return;
     }
 
-  if (!meta_is_wayland_compositor ())
-    {
-      if (priv->unredirected)
-        {
-          /* Nothing to do here until/if the window gets redirected again */
-          return;
-        }
-
-      if (priv->received_x11_damage)
-        {
-          meta_error_trap_push (display);
-          XDamageSubtract (xdisplay, priv->damage, None, None);
-          meta_error_trap_pop (display);
-
-          /* We need to make sure that any X drawing that happens before the
-           * XDamageSubtract() above is visible to subsequent GL rendering;
-           * the only standardized way to do this is EXT_x11_sync_object,
-           * which isn't yet widely available. For now, we count on details
-           * of Xorg and the open source drivers, and hope for the best
-           * otherwise.
-           *
-           * Xorg and open source driver specifics:
-           *
-           * The X server makes sure to flush drawing to the kernel before
-           * sending out damage events, but since we use DamageReportBoundingBox
-           * there may be drawing between the last damage event and the
-           * XDamageSubtract() that needs to be flushed as well.
-           *
-           * Xorg always makes sure that drawing is flushed to the kernel
-           * before writing events or responses to the client, so any round trip
-           * request at this point is sufficient to flush the GLX buffers.
-           */
-          XSync (xdisplay, False);
-
-          priv->received_x11_damage = FALSE;
-        }
+  meta_surface_actor_pre_paint (priv->surface);
 
-      check_needs_x11_pixmap (self);
-    }
+  if (!meta_surface_actor_is_visible (priv->surface))
+    return;
 
   check_needs_reshape (self);
   check_needs_shadow (self);
@@ -2414,20 +2017,16 @@ void
 meta_window_actor_set_updates_frozen (MetaWindowActor *self,
                                       gboolean         updates_frozen)
 {
-  /* On wayland we shouldn't need to ever freeze updates... */
-  if (!meta_is_wayland_compositor ())
-    {
-      MetaWindowActorPrivate *priv = self->priv;
+  MetaWindowActorPrivate *priv = self->priv;
 
-      updates_frozen = updates_frozen != FALSE;
+  updates_frozen = updates_frozen != FALSE;
 
-      if (priv->updates_frozen != updates_frozen)
-        {
-          priv->updates_frozen = updates_frozen;
-          if (updates_frozen)
-            meta_window_actor_freeze (self);
-          else
-            meta_window_actor_thaw (self);
-        }
+  if (priv->updates_frozen != updates_frozen)
+    {
+      priv->updates_frozen = updates_frozen;
+      if (updates_frozen)
+        meta_window_actor_freeze (self);
+      else
+        meta_window_actor_thaw (self);
     }
 }
diff --git a/src/wayland/meta-wayland-surface.c b/src/wayland/meta-wayland-surface.c
index c24645e..73dae30 100644
--- a/src/wayland/meta-wayland-surface.c
+++ b/src/wayland/meta-wayland-surface.c
@@ -44,11 +44,11 @@
 #include "meta-wayland-private.h"
 #include "meta-xwayland-private.h"
 #include "meta-wayland-stage.h"
-#include "meta-surface-actor.h"
 #include "meta-wayland-seat.h"
 #include "meta-wayland-keyboard.h"
 #include "meta-wayland-pointer.h"
 #include "meta-wayland-data-device.h"
+
 #include "meta-cursor-tracker-private.h"
 #include "display-private.h"
 #include "window-private.h"
@@ -58,6 +58,9 @@
 #include "meta-idle-monitor-private.h"
 #include "monitor-private.h"
 
+#include "meta-surface-actor.h"
+#include "meta-surface-actor-wayland.h"
+
 typedef enum
 {
   META_WAYLAND_SUBSURFACE_PLACEMENT_ABOVE,
@@ -114,8 +117,8 @@ surface_process_damage (MetaWaylandSurface *surface,
     {
       cairo_rectangle_int_t rect;
       cairo_region_get_rectangle (region, i, &rect);
-      meta_surface_actor_damage_area (surface->surface_actor,
-                                      rect.x, rect.y, rect.width, rect.height);
+      meta_surface_actor_process_damage (surface->surface_actor,
+                                         rect.x, rect.y, rect.width, rect.height);
     }
 }
 
@@ -297,7 +300,7 @@ actor_surface_commit (MetaWaylandSurface             *surface,
   if (buffer_changed)
     {
       ensure_buffer_texture (buffer);
-      meta_surface_actor_attach_wayland_buffer (surface_actor, buffer);
+      meta_surface_actor_wayland_set_buffer (META_SURFACE_ACTOR_WAYLAND (surface->surface_actor), buffer);
     }
 
   surface_process_damage (surface, pending->damage);
@@ -636,7 +639,7 @@ meta_wayland_surface_create (MetaWaylandCompositor *compositor,
 
   surface->buffer_destroy_listener.notify = surface_handle_buffer_destroy;
 
-  surface->surface_actor = g_object_ref_sink (meta_surface_actor_new ());
+  surface->surface_actor = g_object_ref_sink (meta_surface_actor_wayland_new (surface));
   return surface;
 }
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]