[mutter/wip/surface-content: 8/8] surface content



commit 82a09644b1ef21b27779180cbee18fdb83935638
Author: Jasper St. Pierre <jstpierre mecheye net>
Date:   Fri Dec 6 13:45:11 2013 -0500

    surface content

 src/Makefile.am                               |    7 +
 src/compositor/meta-surface-actor.c           |   93 +---
 src/compositor/meta-surface-actor.h           |   14 +-
 src/compositor/meta-surface-content-private.h |   64 +++
 src/compositor/meta-surface-content-wayland.c |  180 +++++++
 src/compositor/meta-surface-content-wayland.h |   65 +++
 src/compositor/meta-surface-content-x11.c     |  518 +++++++++++++++++++
 src/compositor/meta-surface-content-x11.h     |   66 +++
 src/compositor/meta-surface-content.c         |   97 ++++
 src/compositor/meta-surface-content.h         |   61 +++
 src/compositor/meta-window-actor-private.h    |   10 -
 src/compositor/meta-window-actor.c            |  661 ++++---------------------
 src/wayland/meta-wayland-surface.c            |   16 +-
 src/wayland/meta-wayland-surface.h            |    1 +
 14 files changed, 1200 insertions(+), 653 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index b81c6ec..75d8f09 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -83,6 +83,13 @@ libmutter_wayland_la_SOURCES =                       \
        compositor/meta-shaped-texture-private.h        \
        compositor/meta-surface-actor.c         \
        compositor/meta-surface-actor.h         \
+       compositor/meta-surface-content.c       \
+       compositor/meta-surface-content.h       \
+       compositor/meta-surface-content-private.h       \
+       compositor/meta-surface-content-x11.c   \
+       compositor/meta-surface-content-x11.h   \
+       compositor/meta-surface-content-wayland.c       \
+       compositor/meta-surface-content-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.c b/src/compositor/meta-surface-actor.c
index efd49e1..fe0dc1b 100644
--- a/src/compositor/meta-surface-actor.c
+++ b/src/compositor/meta-surface-actor.c
@@ -10,20 +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"
 
+#include "meta-surface-content-private.h"
+
+/* Dummy "union" typedef */
+typedef struct _MetaSurfaceContent      MetaSurfaceContent;
+
 struct _MetaSurfaceActorPrivate
 {
   MetaShapedTexture *texture;
-  MetaWaylandBuffer *buffer;
+  MetaSurfaceContent *content;
 
   /* The region that is visible, used to optimize out redraws */
   cairo_region_t   *unobscured_region;
@@ -41,6 +45,7 @@ meta_surface_actor_dispose (GObject *object)
   MetaSurfaceActorPrivate *priv = self->priv;
 
   g_clear_pointer (&priv->unobscured_region, cairo_region_destroy);
+  g_clear_object (&priv->content);
 }
 
 static void
@@ -105,6 +110,24 @@ meta_surface_actor_init (MetaSurfaceActor *self)
   clutter_actor_add_child (CLUTTER_ACTOR (self), CLUTTER_ACTOR (priv->texture));
 }
 
+MetaSurfaceContent *
+meta_surface_actor_get_content (MetaSurfaceActor *self)
+{
+  MetaSurfaceActorPrivate *priv = self->priv;
+  return priv->content;
+}
+
+void
+meta_surface_actor_set_content (MetaSurfaceActor *self,
+                                MetaSurfaceContent *content)
+{
+  MetaSurfaceActorPrivate *priv = self->priv;
+  g_clear_object (&priv->content);
+
+  priv->content = g_object_ref_sink (content);
+  meta_surface_content_attach (priv->content, self);
+}
+
 cairo_surface_t *
 meta_surface_actor_get_image (MetaSurfaceActor      *self,
                               cairo_rectangle_int_t *clip)
@@ -118,30 +141,6 @@ 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)
-{
-  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);
-    }
-}
-
 static cairo_region_t *
 effective_unobscured_region (MetaSurfaceActor *self)
 {
@@ -151,20 +150,6 @@ effective_unobscured_region (MetaSurfaceActor *self)
 }
 
 gboolean
-meta_surface_actor_damage_all (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),
-                                          effective_unobscured_region (self));
-}
-
-gboolean
 meta_surface_actor_damage_area (MetaSurfaceActor *self,
                                 int               x,
                                 int               y,
@@ -173,7 +158,6 @@ meta_surface_actor_damage_area (MetaSurfaceActor *self,
 {
   MetaSurfaceActorPrivate *priv = self->priv;
 
-  update_area (self, x, y, width, height);
   return meta_shaped_texture_update_area (priv->texture,
                                           x, y, width, height,
                                           effective_unobscured_region (self));
@@ -187,27 +171,6 @@ meta_surface_actor_is_obscured (MetaSurfaceActor *self)
 }
 
 void
-meta_surface_actor_attach_wayland_buffer (MetaSurfaceActor *self,
-                                          MetaWaylandBuffer *buffer)
-{
-  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);
-}
-
-void
-meta_surface_actor_set_texture (MetaSurfaceActor *self,
-                                CoglTexture      *texture)
-{
-  MetaSurfaceActorPrivate *priv = self->priv;
-  meta_shaped_texture_set_texture (priv->texture, texture);
-}
-
-void
 meta_surface_actor_set_input_region (MetaSurfaceActor *self,
                                      cairo_region_t   *region)
 {
diff --git a/src/compositor/meta-surface-actor.h b/src/compositor/meta-surface-actor.h
index 0f5fd8f..4d814b7 100644
--- a/src/compositor/meta-surface-actor.h
+++ b/src/compositor/meta-surface-actor.h
@@ -6,7 +6,7 @@
 #include <config.h>
 
 #include <meta/meta-shaped-texture.h>
-#include "meta-wayland-types.h"
+#include "meta-surface-content.h"
 
 G_BEGIN_DECLS
 
@@ -21,6 +21,9 @@ typedef struct _MetaSurfaceActor        MetaSurfaceActor;
 typedef struct _MetaSurfaceActorClass   MetaSurfaceActorClass;
 typedef struct _MetaSurfaceActorPrivate MetaSurfaceActorPrivate;
 
+/* Dummy typedef */
+typedef struct _MetaSurfaceContent MetaSurfaceContent;
+
 struct _MetaSurfaceActorClass
 {
   /*< private >*/
@@ -38,12 +41,15 @@ GType meta_surface_actor_get_type (void);
 
 MetaSurfaceActor *meta_surface_actor_new (void);
 
+void meta_surface_actor_set_content (MetaSurfaceActor   *actor,
+                                     MetaSurfaceContent *content);
+MetaSurfaceContent *meta_surface_actor_get_content (MetaSurfaceActor *actor);
+
 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,
@@ -52,10 +58,6 @@ gboolean meta_surface_actor_damage_area (MetaSurfaceActor *self,
 
 gboolean meta_surface_actor_is_obscured (MetaSurfaceActor *self);
 
-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,
diff --git a/src/compositor/meta-surface-content-private.h b/src/compositor/meta-surface-content-private.h
new file mode 100644
index 0000000..0f77ea8
--- /dev/null
+++ b/src/compositor/meta-surface-content-private.h
@@ -0,0 +1,64 @@
+
+/* -*- 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_CONTENT_PRIVATE_H__
+#define __META_SURFACE_CONTENT_PRIVATE_H__
+
+#include <glib-object.h>
+
+#include "meta-surface-content.h"
+
+G_BEGIN_DECLS
+
+#define META_SURFACE_CONTENT_GET_IFACE(obj)   (G_TYPE_INSTANCE_GET_INTERFACE ((obj),  
META_TYPE_SURFACE_CONTENT, MetaSurfaceContentInterface))
+typedef struct _MetaSurfaceContentInterface MetaSurfaceContentInterface;
+
+struct _MetaSurfaceContentInterface
+{
+  GTypeInterface g_iface;
+
+  void     (* attach)            (MetaSurfaceContent *content,
+                                  MetaSurfaceActor   *actor);
+  void     (* process_damage)    (MetaSurfaceContent *content,
+                                  int x, int y, int width, int height);
+  void     (* pre_paint)         (MetaSurfaceContent *content);
+
+  gboolean (* is_argb32)         (MetaSurfaceContent *content);
+  gboolean (* is_visible)        (MetaSurfaceContent *content);
+
+  void     (* freeze)            (MetaSurfaceContent *content);
+  void     (* thaw)              (MetaSurfaceContent *content);
+  gboolean (* is_frozen)         (MetaSurfaceContent *content);
+
+  gboolean (* should_unredirect) (MetaSurfaceContent *content);
+  void     (* set_unredirected)  (MetaSurfaceContent *content,
+                                  gboolean            unredirected);
+};
+
+void meta_surface_content_attach (MetaSurfaceContent *content,
+                                  MetaSurfaceActor *actor);
+
+#endif /* __META_SURFACE_CONTENT_PRIVATE_H__ */
diff --git a/src/compositor/meta-surface-content-wayland.c b/src/compositor/meta-surface-content-wayland.c
new file mode 100644
index 0000000..c18027f
--- /dev/null
+++ b/src/compositor/meta-surface-content-wayland.c
@@ -0,0 +1,180 @@
+/* -*- 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-content-wayland.h"
+#include "meta-surface-content-private.h"
+
+#include <cogl/cogl-wayland-server.h>
+#include "meta-shaped-texture-private.h"
+
+struct _MetaSurfaceContentWaylandPrivate
+{
+  MetaSurfaceActor *surface_actor;
+
+  MetaWaylandSurface *surface;
+  MetaWaylandBuffer *buffer;
+};
+typedef struct _MetaSurfaceContentWaylandPrivate MetaSurfaceContentWaylandPrivate;
+
+static void surface_content_iface_init (MetaSurfaceContentInterface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (MetaSurfaceContentWayland, meta_surface_content_wayland, G_TYPE_INITIALLY_UNOWNED,
+                         G_IMPLEMENT_INTERFACE (META_TYPE_SURFACE_CONTENT, surface_content_iface_init)
+                         G_ADD_PRIVATE (MetaSurfaceContentWayland))
+
+static void
+meta_surface_content_wayland_attach (MetaSurfaceContent *content,
+                                     MetaSurfaceActor   *actor)
+{
+  MetaSurfaceContentWayland *self = META_SURFACE_CONTENT_WAYLAND (content);
+  MetaSurfaceContentWaylandPrivate *priv = meta_surface_content_wayland_get_instance_private (self);
+
+  g_clear_pointer (&priv->surface_actor, g_object_unref);
+  priv->surface_actor = g_object_ref_sink (actor);
+}
+
+static void
+meta_surface_content_wayland_process_damage (MetaSurfaceContent *content,
+                                             int x, int y, int width, int height)
+{
+  MetaSurfaceContentWayland *self = META_SURFACE_CONTENT_WAYLAND (content);
+  MetaSurfaceContentWaylandPrivate *priv = meta_surface_content_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);
+    }
+}
+
+static void
+meta_surface_content_wayland_pre_paint (MetaSurfaceContent *content)
+{
+}
+
+static gboolean
+meta_surface_content_wayland_is_argb32 (MetaSurfaceContent *content)
+{
+  /* TODO: look at the SHM buffer pixel format */
+  return TRUE;
+}
+
+static gboolean
+meta_surface_content_wayland_is_visible (MetaSurfaceContent *content)
+{
+  /* TODO: ensure that the buffer isn't NULL, implement
+   * wayland mapping semantics */
+  return TRUE;
+}
+
+static void
+meta_surface_content_wayland_freeze (MetaSurfaceContent *content)
+{
+}
+
+static void
+meta_surface_content_wayland_thaw (MetaSurfaceContent *content)
+{
+}
+
+static gboolean
+meta_surface_content_wayland_is_frozen (MetaSurfaceContent *content)
+{
+  return FALSE;
+}
+
+static gboolean
+meta_surface_content_wayland_should_unredirect (MetaSurfaceContent *content)
+{
+  return FALSE;
+}
+
+static void
+meta_surface_content_wayland_set_unredirected (MetaSurfaceContent *content,
+                                               gboolean            unredirected)
+{
+  /* Do nothing. In the future, we'll use KMS to set this
+   * up as a hardware overlay or something. */
+}
+
+static void
+surface_content_iface_init (MetaSurfaceContentInterface *iface)
+{
+  iface->attach = meta_surface_content_wayland_attach;
+  iface->process_damage = meta_surface_content_wayland_process_damage;
+  iface->pre_paint = meta_surface_content_wayland_pre_paint;
+
+  iface->is_argb32 = meta_surface_content_wayland_is_argb32;
+  iface->is_visible = meta_surface_content_wayland_is_visible;
+
+  iface->freeze = meta_surface_content_wayland_freeze;
+  iface->thaw = meta_surface_content_wayland_thaw;
+  iface->is_frozen = meta_surface_content_wayland_is_frozen;
+
+  iface->should_unredirect = meta_surface_content_wayland_should_unredirect;
+  iface->set_unredirected = meta_surface_content_wayland_set_unredirected;
+}
+
+static void
+meta_surface_content_wayland_class_init (MetaSurfaceContentWaylandClass *klass)
+{
+}
+
+static void
+meta_surface_content_wayland_init (MetaSurfaceContentWayland *self)
+{
+}
+
+MetaSurfaceContent *
+meta_surface_content_wayland_new (MetaWaylandSurface *surface)
+{
+  MetaSurfaceContentWayland *self = g_object_new (META_TYPE_SURFACE_CONTENT_WAYLAND, NULL);
+  MetaSurfaceContentWaylandPrivate *priv = meta_surface_content_wayland_get_instance_private (self);
+
+  g_assert (meta_is_wayland_compositor ());
+
+  priv->surface = surface;
+
+  return META_SURFACE_CONTENT (self);
+}
+
+void
+meta_surface_content_wayland_set_buffer (MetaSurfaceContentWayland *self,
+                                         MetaWaylandBuffer         *buffer)
+{
+  MetaSurfaceContentWaylandPrivate *priv = meta_surface_content_wayland_get_instance_private (self);
+  MetaShapedTexture *stex = meta_surface_actor_get_texture (priv->surface_actor);
+
+  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-content-wayland.h b/src/compositor/meta-surface-content-wayland.h
new file mode 100644
index 0000000..541b521
--- /dev/null
+++ b/src/compositor/meta-surface-content-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_CONTENT_WAYLAND_H__
+#define __META_SURFACE_CONTENT_WAYLAND_H__
+
+#include <glib-object.h>
+
+#include "meta-surface-content.h"
+
+#include "meta-wayland-private.h"
+
+G_BEGIN_DECLS
+
+#define META_TYPE_SURFACE_CONTENT_WAYLAND            (meta_surface_content_wayland_get_type ())
+#define META_SURFACE_CONTENT_WAYLAND(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), 
META_TYPE_SURFACE_CONTENT_WAYLAND, MetaSurfaceContentWayland))
+#define META_SURFACE_CONTENT_WAYLAND_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass),  
META_TYPE_SURFACE_CONTENT_WAYLAND, MetaSurfaceContentWaylandClass))
+#define META_IS_SURFACE_CONTENT_WAYLAND(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), 
META_TYPE_SURFACE_CONTENT_WAYLAND))
+#define META_IS_SURFACE_CONTENT_WAYLAND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),  
META_TYPE_SURFACE_CONTENT_WAYLAND))
+#define META_SURFACE_CONTENT_WAYLAND_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj),  
META_TYPE_SURFACE_CONTENT_WAYLAND, MetaSurfaceContentWaylandClass))
+
+typedef struct _MetaSurfaceContentWayland      MetaSurfaceContentWayland;
+typedef struct _MetaSurfaceContentWaylandClass MetaSurfaceContentWaylandClass;
+
+struct _MetaSurfaceContentWayland
+{
+  GObject parent;
+};
+
+struct _MetaSurfaceContentWaylandClass
+{
+  GObjectClass parent_class;
+};
+
+GType meta_surface_content_wayland_get_type (void);
+
+MetaSurfaceContent * meta_surface_content_wayland_new (MetaWaylandSurface *surface);
+
+void meta_surface_content_wayland_set_buffer (MetaSurfaceContentWayland *self,
+                                              MetaWaylandBuffer         *buffer);
+
+G_END_DECLS
+
+#endif /* __META_SURFACE_CONTENT_WAYLAND_H__ */
diff --git a/src/compositor/meta-surface-content-x11.c b/src/compositor/meta-surface-content-x11.c
new file mode 100644
index 0000000..00f2b1e
--- /dev/null
+++ b/src/compositor/meta-surface-content-x11.c
@@ -0,0 +1,518 @@
+/* -*- 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-content-x11.h"
+#include "meta-surface-content-private.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"
+
+struct _MetaSurfaceContentX11Private
+{
+  MetaSurfaceActor *surface_actor;
+
+  MetaWindow *window;
+
+  CoglTexture *texture;
+  Pixmap pixmap;
+  Damage damage;
+
+  /* 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 mapped       : 1;
+  guint received_damage : 1;
+  guint needs_pixmap : 1;
+  guint size_changed : 1;
+  guint needs_damage_all : 1;
+
+  guint unredirected   : 1;
+};
+typedef struct _MetaSurfaceContentX11Private MetaSurfaceContentX11Private;
+
+static void surface_content_iface_init (MetaSurfaceContentInterface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (MetaSurfaceContentX11, meta_surface_content_x11, G_TYPE_INITIALLY_UNOWNED,
+                         G_IMPLEMENT_INTERFACE (META_TYPE_SURFACE_CONTENT, surface_content_iface_init)
+                         G_ADD_PRIVATE (MetaSurfaceContentX11))
+
+static void
+free_damage (MetaSurfaceContentX11 *self)
+{
+  MetaSurfaceContentX11Private *priv = meta_surface_content_x11_get_instance_private (self);
+
+  MetaDisplay *display = meta_window_get_display (priv->window);
+  Display *xdisplay = meta_display_get_xdisplay (display);
+
+  g_assert (priv->damage != None);
+
+  meta_error_trap_push (display);
+  XDamageDestroy (xdisplay, priv->damage);
+  priv->damage = None;
+  meta_error_trap_pop (display);
+}
+
+static void
+detach_pixmap (MetaSurfaceContentX11 *self)
+{
+  MetaSurfaceContentX11Private *priv = meta_surface_content_x11_get_instance_private (self);
+
+  MetaDisplay *display = meta_window_get_display (priv->window);
+  Display *xdisplay = meta_display_get_xdisplay (display);
+  MetaShapedTexture *stex = meta_surface_actor_get_texture (priv->surface_actor);
+
+  g_assert (priv->pixmap != None);
+
+  XFreePixmap (xdisplay, priv->pixmap);
+  priv->pixmap = None;
+
+  meta_shaped_texture_set_texture (stex, NULL);
+
+  cogl_object_unref (priv->texture);
+  priv->texture = NULL;
+}
+
+static void
+set_pixmap (MetaSurfaceContentX11 *self,
+            Pixmap                 pixmap)
+{
+  MetaSurfaceContentX11Private *priv = meta_surface_content_x11_get_instance_private (self);
+
+  CoglContext *ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
+  MetaShapedTexture *stex = meta_surface_actor_get_texture (priv->surface_actor);
+  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 (MetaSurfaceContentX11 *self)
+{
+  MetaSurfaceContentX11Private *priv = meta_surface_content_x11_get_instance_private (self);
+
+  MetaDisplay *display = meta_window_get_display (priv->window);
+  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_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 (MetaSurfaceContentX11 *self)
+{
+  MetaSurfaceContentX11Private *priv = meta_surface_content_x11_get_instance_private (self);
+  return (priv->freeze_count > 0);
+}
+
+static gboolean
+is_visible (MetaSurfaceContentX11 *self)
+{
+  MetaSurfaceContentX11Private *priv = meta_surface_content_x11_get_instance_private (self);
+
+  return priv->mapped && !priv->needs_pixmap && !priv->unredirected;
+}
+
+static void
+meta_surface_content_x11_attach (MetaSurfaceContent *content,
+                                 MetaSurfaceActor   *actor)
+{
+  MetaSurfaceContentX11 *self = META_SURFACE_CONTENT_X11 (content);
+  MetaSurfaceContentX11Private *priv = meta_surface_content_x11_get_instance_private (self);
+
+  g_clear_pointer (&priv->surface_actor, g_object_unref);
+  priv->surface_actor = g_object_ref_sink (actor);
+}
+
+static void
+damage_area (MetaSurfaceContentX11 *self,
+             int x, int y, int width, int height)
+{
+  MetaSurfaceContentX11Private *priv = meta_surface_content_x11_get_instance_private (self);
+  cogl_texture_pixmap_x11_update_area (priv->texture, x, y, width, height);
+  meta_surface_actor_damage_area (priv->surface_actor, x, y, width, height);
+}
+
+static void
+damage_all (MetaSurfaceContentX11 *self)
+{
+  MetaSurfaceContentX11Private *priv = meta_surface_content_x11_get_instance_private (self);
+  CoglTexture *texture = priv->texture;
+
+  damage_area (self, 0, 0, cogl_texture_get_width (texture), cogl_texture_get_height (texture));
+}
+
+static void
+meta_surface_content_x11_process_damage (MetaSurfaceContent *content,
+                                         int x, int y, int width, int height)
+{
+  MetaSurfaceContentX11 *self = META_SURFACE_CONTENT_X11 (content);
+  MetaSurfaceContentX11Private *priv = meta_surface_content_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;
+    }
+
+  if (!is_visible (self))
+    return;
+
+  damage_area (self, x, y, width, height);
+}
+
+static void
+meta_surface_content_x11_pre_paint (MetaSurfaceContent *content)
+{
+  MetaSurfaceContentX11 *self = META_SURFACE_CONTENT_X11 (content);
+  MetaSurfaceContentX11Private *priv = meta_surface_content_x11_get_instance_private (self);
+
+  MetaDisplay *display = meta_window_get_display (priv->window);
+  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_content_x11_freeze (MetaSurfaceContent *content)
+{
+  MetaSurfaceContentX11 *self = META_SURFACE_CONTENT_X11 (content);
+  MetaSurfaceContentX11Private *priv = meta_surface_content_x11_get_instance_private (self);
+
+  priv->freeze_count ++;
+}
+
+static void
+meta_surface_content_x11_thaw (MetaSurfaceContent *content)
+{
+  MetaSurfaceContentX11 *self = META_SURFACE_CONTENT_X11 (content);
+  MetaSurfaceContentX11Private *priv = meta_surface_content_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);
+}
+
+static gboolean
+meta_surface_content_x11_is_frozen (MetaSurfaceContent *content)
+{
+  MetaSurfaceContentX11 *self = META_SURFACE_CONTENT_X11 (content);
+  return is_frozen (self);
+}
+
+static void
+update_is_argb32 (MetaSurfaceContentX11 *self)
+{
+  MetaSurfaceContentX11Private *priv = meta_surface_content_x11_get_instance_private (self);
+
+  MetaDisplay *display = meta_window_get_display (priv->window);
+  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_content_x11_is_argb32 (MetaSurfaceContent *content)
+{
+  MetaSurfaceContentX11 *self = META_SURFACE_CONTENT_X11 (content);
+  MetaSurfaceContentX11Private *priv = meta_surface_content_x11_get_instance_private (self);
+
+  return priv->argb32;
+}
+
+static gboolean
+meta_surface_content_x11_is_visible (MetaSurfaceContent *content)
+{
+  MetaSurfaceContentX11 *self = META_SURFACE_CONTENT_X11 (content);
+  return is_visible (self);
+}
+
+static gboolean
+meta_surface_content_x11_should_unredirect (MetaSurfaceContent *content)
+{
+  MetaSurfaceContentX11 *self = META_SURFACE_CONTENT_X11 (content);
+  MetaSurfaceContentX11Private *priv = meta_surface_content_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 (MetaSurfaceContentX11 *self)
+{
+  MetaSurfaceContentX11Private *priv = meta_surface_content_x11_get_instance_private (self);
+
+  MetaDisplay *display = meta_window_get_display (priv->window);
+  Display *xdisplay = meta_display_get_xdisplay (display);
+  Window xwindow = meta_window_get_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_content_x11_set_unredirected (MetaSurfaceContent *content,
+                                           gboolean            unredirected)
+{
+  MetaSurfaceContentX11 *self = META_SURFACE_CONTENT_X11 (content);
+  MetaSurfaceContentX11Private *priv = meta_surface_content_x11_get_instance_private (self);
+
+  if (priv->unredirected == unredirected)
+    return;
+
+  priv->unredirected = unredirected;
+  sync_unredirected (self);
+}
+
+static void
+surface_content_iface_init (MetaSurfaceContentInterface *iface)
+{
+  iface->attach = meta_surface_content_x11_attach;
+  iface->process_damage = meta_surface_content_x11_process_damage;
+  iface->pre_paint = meta_surface_content_x11_pre_paint;
+
+  iface->is_argb32 = meta_surface_content_x11_is_argb32;
+  iface->is_visible = meta_surface_content_x11_is_visible;
+
+  iface->freeze = meta_surface_content_x11_freeze;
+  iface->thaw = meta_surface_content_x11_thaw;
+  iface->is_frozen = meta_surface_content_x11_is_frozen;
+
+  iface->should_unredirect = meta_surface_content_x11_should_unredirect;
+  iface->set_unredirected = meta_surface_content_x11_set_unredirected;
+}
+
+static void
+meta_surface_content_x11_dispose (GObject *object)
+{
+  MetaSurfaceContentX11 *self = META_SURFACE_CONTENT_X11 (object);
+
+  detach_pixmap (self);
+  free_damage (self);
+}
+
+static void
+meta_surface_content_x11_class_init (MetaSurfaceContentX11Class *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->dispose = meta_surface_content_x11_dispose;
+}
+
+static void
+meta_surface_content_x11_init (MetaSurfaceContentX11 *self)
+{
+}
+
+MetaSurfaceContent *
+meta_surface_content_x11_new (MetaWindow *window)
+{
+  MetaSurfaceContentX11 *self = g_object_new (META_TYPE_SURFACE_CONTENT_X11, NULL);
+  MetaSurfaceContentX11Private *priv = meta_surface_content_x11_get_instance_private (self);
+
+  MetaDisplay *display = meta_window_get_display (window);
+  Display *xdisplay = meta_display_get_xdisplay (display);
+  Window xwindow = meta_window_get_xwindow (window);
+
+  g_assert (!meta_is_wayland_compositor ());
+
+  priv->window = window;
+
+  priv->damage = XDamageCreate (xdisplay, xwindow, XDamageReportBoundingBox);
+  update_is_argb32 (self);
+
+  priv->unredirected = FALSE;
+  sync_unredirected (self);
+
+  return META_SURFACE_CONTENT (self);
+}
diff --git a/src/compositor/meta-surface-content-x11.h b/src/compositor/meta-surface-content-x11.h
new file mode 100644
index 0000000..c51bd87
--- /dev/null
+++ b/src/compositor/meta-surface-content-x11.h
@@ -0,0 +1,66 @@
+/* -*- 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_CONTENT_X11_H__
+#define __META_SURFACE_CONTENT_X11_H__
+
+#include <glib-object.h>
+
+#include "meta-surface-content.h"
+
+#include <X11/extensions/Xdamage.h>
+
+#include <meta/display.h>
+#include <meta/window.h>
+
+G_BEGIN_DECLS
+
+#define META_TYPE_SURFACE_CONTENT_X11            (meta_surface_content_x11_get_type ())
+#define META_SURFACE_CONTENT_X11(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), 
META_TYPE_SURFACE_CONTENT_X11, MetaSurfaceContentX11))
+#define META_SURFACE_CONTENT_X11_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass),  
META_TYPE_SURFACE_CONTENT_X11, MetaSurfaceContentX11Class))
+#define META_IS_SURFACE_CONTENT_X11(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), 
META_TYPE_SURFACE_CONTENT_X11))
+#define META_IS_SURFACE_CONTENT_X11_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),  
META_TYPE_SURFACE_CONTENT_X11))
+#define META_SURFACE_CONTENT_X11_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj),  
META_TYPE_SURFACE_CONTENT_X11, MetaSurfaceContentX11Class))
+
+typedef struct _MetaSurfaceContentX11      MetaSurfaceContentX11;
+typedef struct _MetaSurfaceContentX11Class MetaSurfaceContentX11Class;
+
+struct _MetaSurfaceContentX11
+{
+  GObject parent;
+};
+
+struct _MetaSurfaceContentX11Class
+{
+  GObjectClass parent_class;
+};
+
+GType meta_surface_content_x11_get_type (void);
+
+MetaSurfaceContent * meta_surface_content_x11_new (MetaWindow *window);
+
+G_END_DECLS
+
+#endif /* __META_SURFACE_CONTENT_X11_H__ */
diff --git a/src/compositor/meta-surface-content.c b/src/compositor/meta-surface-content.c
new file mode 100644
index 0000000..0d3b77f
--- /dev/null
+++ b/src/compositor/meta-surface-content.c
@@ -0,0 +1,97 @@
+/* -*- 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-content-private.h"
+
+G_DEFINE_INTERFACE (MetaSurfaceContent, meta_surface_content, G_TYPE_OBJECT);
+
+static void
+meta_surface_content_default_init (MetaSurfaceContentInterface *iface)
+{
+}
+
+void
+meta_surface_content_attach (MetaSurfaceContent *content,
+                             MetaSurfaceActor   *actor)
+{
+  META_SURFACE_CONTENT_GET_IFACE (content)->attach (content, actor);
+}
+
+void
+meta_surface_content_process_damage (MetaSurfaceContent *content,
+                                     int x, int y, int width, int height)
+{
+  META_SURFACE_CONTENT_GET_IFACE (content)->process_damage (content, x, y, width, height);
+}
+
+void
+meta_surface_content_pre_paint (MetaSurfaceContent *content)
+{
+  META_SURFACE_CONTENT_GET_IFACE (content)->pre_paint (content);
+}
+
+gboolean
+meta_surface_content_is_argb32 (MetaSurfaceContent *content)
+{
+  return META_SURFACE_CONTENT_GET_IFACE (content)->is_argb32 (content);
+}
+
+gboolean
+meta_surface_content_is_visible (MetaSurfaceContent *content)
+{
+  return META_SURFACE_CONTENT_GET_IFACE (content)->is_visible (content);
+}
+
+void
+meta_surface_content_freeze (MetaSurfaceContent *content)
+{
+  META_SURFACE_CONTENT_GET_IFACE (content)->freeze (content);
+}
+
+void
+meta_surface_content_thaw (MetaSurfaceContent *content)
+{
+  META_SURFACE_CONTENT_GET_IFACE (content)->thaw (content);
+}
+
+gboolean
+meta_surface_content_is_frozen (MetaSurfaceContent *content)
+{
+  return META_SURFACE_CONTENT_GET_IFACE (content)->is_frozen (content);
+}
+
+gboolean
+meta_surface_content_should_unredirect (MetaSurfaceContent *content)
+{
+  return META_SURFACE_CONTENT_GET_IFACE (content)->should_unredirect (content);
+}
+
+void
+meta_surface_content_set_unredirected (MetaSurfaceContent *content,
+                                       gboolean            unredirected)
+{
+  META_SURFACE_CONTENT_GET_IFACE (content)->set_unredirected (content, unredirected);
+}
diff --git a/src/compositor/meta-surface-content.h b/src/compositor/meta-surface-content.h
new file mode 100644
index 0000000..aeed385
--- /dev/null
+++ b/src/compositor/meta-surface-content.h
@@ -0,0 +1,61 @@
+/* -*- 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_CONTENT_H__
+#define __META_SURFACE_CONTENT_H__
+
+#include <glib-object.h>
+
+#include "meta-surface-actor.h"
+
+G_BEGIN_DECLS
+
+#define META_TYPE_SURFACE_CONTENT             (meta_surface_content_get_type ())
+#define META_SURFACE_CONTENT(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_SURFACE_CONTENT, 
MetaSurfaceContent))
+#define META_IS_SURFACE_CONTENT(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_SURFACE_CONTENT))
+
+/* Dummy typedef */
+typedef struct _MetaSurfaceContent MetaSurfaceContent;
+
+GType meta_surface_content_get_type (void);
+
+void meta_surface_content_process_damage (MetaSurfaceContent *content,
+                                          int x, int y, int width, int height);
+void meta_surface_content_pre_paint (MetaSurfaceContent *content);
+
+gboolean meta_surface_content_is_argb32 (MetaSurfaceContent *content);
+gboolean meta_surface_content_is_visible (MetaSurfaceContent *content);
+
+void meta_surface_content_freeze (MetaSurfaceContent *content);
+void meta_surface_content_thaw (MetaSurfaceContent *content);
+gboolean meta_surface_content_is_frozen (MetaSurfaceContent *content);
+
+gboolean meta_surface_content_should_unredirect (MetaSurfaceContent *content);
+void meta_surface_content_set_unredirected (MetaSurfaceContent *content,
+                                            gboolean            unredirected);
+
+G_END_DECLS
+
+#endif /* __META_SURFACE_CONTENT_H__ */
diff --git a/src/compositor/meta-window-actor-private.h b/src/compositor/meta-window-actor-private.h
index e3d239d..4373026 100644
--- a/src/compositor/meta-window-actor-private.h
+++ b/src/compositor/meta-window-actor-private.h
@@ -28,9 +28,6 @@ void meta_window_actor_unmaximize (MetaWindowActor *self,
                                    MetaRectangle   *old_rect,
                                    MetaRectangle   *new_rect);
 
-void meta_window_actor_process_x11_damage (MetaWindowActor    *self,
-                                           XDamageNotifyEvent *event);
-
 void meta_window_actor_pre_paint      (MetaWindowActor    *self);
 void meta_window_actor_post_paint     (MetaWindowActor    *self);
 void meta_window_actor_frame_complete (MetaWindowActor    *self,
@@ -38,11 +35,6 @@ void meta_window_actor_frame_complete (MetaWindowActor    *self,
                                        gint64              presentation_time);
 
 void meta_window_actor_invalidate_shadow (MetaWindowActor *self);
-
-void meta_window_actor_set_redirected (MetaWindowActor *self, gboolean state);
-
-gboolean meta_window_actor_should_unredirect (MetaWindowActor *self);
-
 void meta_window_actor_get_shape_bounds (MetaWindowActor       *self,
                                           cairo_rectangle_int_t *bounds);
 
@@ -52,8 +44,6 @@ void     meta_window_actor_sync_actor_geometry (MetaWindowActor *self,
 void     meta_window_actor_sync_visibility     (MetaWindowActor *self);
 void     meta_window_actor_update_shape        (MetaWindowActor *self);
 void     meta_window_actor_update_opacity      (MetaWindowActor *self);
-void     meta_window_actor_mapped              (MetaWindowActor *self);
-void     meta_window_actor_unmapped            (MetaWindowActor *self);
 void     meta_window_actor_set_updates_frozen  (MetaWindowActor *self,
                                                 gboolean         updates_frozen);
 void     meta_window_actor_queue_frame_drawn   (MetaWindowActor *self,
diff --git a/src/compositor/meta-window-actor.c b/src/compositor/meta-window-actor.c
index df28bcc..ddccd16 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() */
@@ -36,6 +32,8 @@
 #include "meta-wayland-private.h"
 #include "monitor-private.h"
 #include "meta-cullable.h"
+#include "meta-surface-content.h"
+#include "meta-surface-content-x11.h"
 
 enum {
   POSITION_CHANGED,
@@ -53,6 +51,7 @@ struct _MetaWindowActorPrivate
   MetaScreen       *screen;
 
   MetaSurfaceActor *surface;
+  MetaSurfaceContent *surface_content;
 
   guint             surface_allocation_changed_id;
 
@@ -75,19 +74,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
@@ -102,12 +95,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                    mapped                 : 1;
-  guint                    argb32                 : 1;
   guint                    disposed               : 1;
   guint             redecorating           : 1;
 
@@ -124,24 +112,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;
@@ -180,7 +151,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);
@@ -308,9 +278,6 @@ window_decorated_notify (MetaWindow *mw,
   MetaWindowActor        *self     = META_WINDOW_ACTOR (data);
   MetaWindowActorPrivate *priv     = self->priv;
   MetaFrame              *frame    = meta_window_get_frame (mw);
-  MetaScreen             *screen   = priv->screen;
-  MetaDisplay            *display  = meta_screen_get_display (screen);
-  Display                *xdisplay = meta_display_get_xdisplay (display);
   Window                  new_xwindow;
 
   /*
@@ -324,23 +291,6 @@ window_decorated_notify (MetaWindow *mw,
   else
     new_xwindow = meta_window_get_xwindow (mw);
 
-  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;
-        }
-    }
-
   priv->xwindow = new_xwindow;
 
   /*
@@ -369,43 +319,82 @@ surface_allocation_changed_notify (ClutterActor           *actor,
   g_signal_emit (self, signals[SIZE_CHANGED], 0);
 }
 
+static gboolean
+is_argb32 (MetaWindowActor *self)
+{
+  MetaWindowActorPrivate *priv = self->priv;
+  return meta_surface_content_is_argb32 (priv->surface_content);
+}
+
+static gboolean
+is_transparent (MetaWindowActor *self)
+{
+  MetaWindowActorPrivate *priv = self->priv;
+  MetaWindow *window = priv->window;
+
+  return is_argb32 (self) || (window->opacity != 0xFF);
+}
+
+static gboolean
+is_frozen (MetaWindowActor *self)
+{
+  MetaWindowActorPrivate *priv = self->priv;
+  return meta_surface_content_is_frozen (priv->surface_content);
+}
+
 static void
-meta_window_actor_constructed (GObject *object)
+meta_window_actor_freeze (MetaWindowActor *self)
 {
-  MetaWindowActor        *self     = META_WINDOW_ACTOR (object);
-  MetaWindowActorPrivate *priv     = self->priv;
-  MetaScreen             *screen   = priv->screen;
-  MetaDisplay            *display  = meta_screen_get_display (screen);
-  Window                  xwindow  = priv->xwindow;
-  MetaWindow             *window   = priv->window;
-  Display                *xdisplay = meta_display_get_xdisplay (display);
+  MetaWindowActorPrivate *priv = self->priv;
+  meta_surface_content_freeze (priv->surface_content);
+}
 
-  if (!meta_is_wayland_compositor ())
-    priv->damage = XDamageCreate (xdisplay, xwindow,
-                                  XDamageReportBoundingBox);
+static void
+meta_window_actor_thaw (MetaWindowActor *self)
+{
+  MetaWindowActorPrivate *priv = self->priv;
 
-  if (window->client_type == META_WINDOW_CLIENT_TYPE_X11)
-    {
-      XRenderPictFormat      *format;
+  meta_surface_content_thaw (priv->surface_content);
 
-      format = XRenderFindVisualFormat (xdisplay, window->xvisual);
+  if (meta_surface_content_is_frozen (priv->surface_content))
+    return;
 
-      if (format && format->type == PictTypeDirect && format->direct.alphaMask)
-        priv->argb32 = TRUE;
-    }
-  else
-    {
-      /* XXX: parse shm formats to determine argb32 */
-      priv->argb32 = TRUE;
-    }
+  /* 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);
+}
+
+static MetaSurfaceActor *
+create_surface_actor_for_x11 (MetaWindow *window)
+{
+  MetaSurfaceActor *surface;
+  MetaSurfaceContent *content;
+
+  g_assert (!meta_is_wayland_compositor ());
+
+  surface = meta_surface_actor_new ();
+  content = meta_surface_content_x11_new (window);
+  meta_surface_actor_set_content (surface, content);
+
+  return surface;
+}
+
+static void
+meta_window_actor_constructed (GObject *object)
+{
+  MetaWindowActor        *self     = META_WINDOW_ACTOR (object);
+  MetaWindowActorPrivate *priv     = self->priv;
+  MetaWindow             *window   = priv->window;
 
   if (!priv->surface)
     {
       if (window->surface)
         priv->surface = window->surface->surface_actor;
       else
-        priv->surface = meta_surface_actor_new ();
-      g_object_ref_sink (priv->surface);
+        priv->surface = create_surface_actor_for_x11 (window);
 
       clutter_actor_add_child (CLUTTER_ACTOR (self), CLUTTER_ACTOR (priv->surface));
 
@@ -416,6 +405,8 @@ meta_window_actor_constructed (GObject *object)
                           self);
       meta_window_actor_update_shape (self);
 
+      priv->surface_content = meta_surface_actor_get_content (priv->surface);
+
       g_signal_connect_object (window, "notify::decorated",
                                G_CALLBACK (window_decorated_notify), self, 0);
       g_signal_connect_object (window, "notify::appears-focused",
@@ -443,8 +434,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)
@@ -455,9 +444,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);
@@ -472,18 +458,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);
@@ -666,15 +640,6 @@ meta_window_actor_get_shadow_bounds (MetaWindowActor       *self,
                           bounds);
 }
 
-static gboolean
-is_transparent (MetaWindowActor *self)
-{
-  MetaWindowActorPrivate *priv = self->priv;
-  MetaWindow *window = priv->window;
-
-  return priv->argb32 || (window->opacity != 0xFF);
-}
-
 /* If we have an ARGB32 window that we decorate with a frame, it's
  * probably something like a translucent terminal - something where
  * the alpha channel represents transparency rather than a shape.  We
@@ -983,13 +948,7 @@ meta_window_actor_showing_on_its_workspace (MetaWindowActor *self)
   return meta_window_showing_on_its_workspace (self->priv->window);
 }
 
-static void
-meta_window_actor_freeze (MetaWindowActor *self)
-{
-  if (!meta_is_wayland_compositor ())
-    self->priv->freeze_count++;
-}
-
+#if 0
 static gboolean
 send_frame_messages_timeout (gpointer data)
 {
@@ -1043,56 +1002,7 @@ 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->mapped || 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);
-    }
-}
+#endif
 
 void
 meta_window_actor_queue_frame_drawn (MetaWindowActor *self,
@@ -1113,6 +1023,7 @@ meta_window_actor_queue_frame_drawn (MetaWindowActor *self,
       clutter_stage_skip_sync_delay (CLUTTER_STAGE (stage));
     }
 
+#if 0
   if (!priv->repaint_scheduled)
     {
       gboolean is_obscured = meta_surface_actor_is_obscured (priv->surface);
@@ -1129,13 +1040,14 @@ meta_window_actor_queue_frame_drawn (MetaWindowActor *self,
         {
           queue_send_frame_messages_timeout (self);
         }
-      else if (priv->mapped && (!meta_is_wayland_compositor () || !priv->needs_pixmap))
+      else if (meta_surface_content_is_visible (priv->surface_content))
         {
           const cairo_rectangle_int_t clip = { 0, 0, 1, 1 };
           clutter_actor_queue_redraw_with_clip (CLUTTER_ACTOR (priv->surface), &clip);
           priv->repaint_scheduled = TRUE;
         }
     }
+#endif
 }
 
 gboolean
@@ -1149,36 +1061,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 (!priv->mapped)
-    return;
-
-  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)
@@ -1258,15 +1140,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 (!meta_window_is_mapped (priv->window))
-        meta_window_actor_detach_x11_pixmap (self);
-
-      if (priv->needs_pixmap)
-        clutter_actor_queue_redraw (CLUTTER_ACTOR (priv->surface));
-    }
 }
 
 void
@@ -1341,97 +1214,6 @@ 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;
-}
-
-void
-meta_window_actor_set_redirected (MetaWindowActor *self, gboolean state)
-{
-  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_actor_get_x_window (self);
-
-  if (state)
-    {
-      meta_error_trap_push (display);
-      XCompositeRedirectWindow (xdisplay, xwin, CompositeRedirectManual);
-      meta_error_trap_pop (display);
-      meta_window_actor_detach_x11_pixmap (self);
-      self->priv->unredirected = FALSE;
-    }
-  else
-    {
-      meta_error_trap_push (display);
-      XCompositeUnredirectWindow (xdisplay, xwin, CompositeRedirectManual);
-      meta_error_trap_pop (display);
-      self->priv->unredirected = TRUE;
-    }
-}
-
 void
 meta_window_actor_destroy (MetaWindowActor *self)
 {
@@ -1483,20 +1265,6 @@ 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;
-        }
-    }
-
   /* Normally we want freezing a window to also freeze its position; this allows
    * windows to atomically move and resize together, either under app control,
    * or because the user is resizing from the left/top. But on initial placement
@@ -1507,15 +1275,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;
 
@@ -1705,19 +1464,10 @@ meta_window_actor_new (MetaWindow *window)
                        NULL);
 
   priv = self->priv;
-  priv->mapped = meta_window_toplevel_is_mapped (priv->window);
+  meta_window_actor_set_updates_frozen (self, meta_window_updates_are_frozen (priv->window));
 
   if (!meta_is_wayland_compositor ())
     {
-      priv->last_width = -1;
-      priv->last_height = -1;
-
-      if (priv->mapped)
-        meta_window_actor_queue_create_x11_pixmap (self);
-
-      meta_window_actor_set_updates_frozen (self,
-                                            meta_window_updates_are_frozen (priv->window));
-
       /* 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.
        */
@@ -1749,38 +1499,6 @@ meta_window_actor_new (MetaWindow *window)
   return self;
 }
 
-void
-meta_window_actor_mapped (MetaWindowActor *self)
-{
-  MetaWindowActorPrivate *priv = self->priv;
-
-  g_return_if_fail (!priv->mapped);
-
-  priv->mapped = TRUE;
-
-  if (!meta_is_wayland_compositor ())
-    meta_window_actor_queue_create_x11_pixmap (self);
-}
-
-void
-meta_window_actor_unmapped (MetaWindowActor *self)
-{
-  MetaWindowActorPrivate *priv = self->priv;
-
-  g_return_if_fail (priv->mapped);
-
-  priv->mapped = FALSE;
-
-  if (meta_window_actor_effect_in_progress (self))
-    return;
-
-  if (!meta_is_wayland_compositor ())
-    {
-      meta_window_actor_detach_x11_pixmap (self);
-      priv->needs_pixmap = FALSE;
-    }
-}
-
 #if 0
 /* Print out a region; useful for debugging */
 static void
@@ -1892,88 +1610,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  = priv->xwindow;
-
-  if (!priv->needs_pixmap)
-    return;
-
-  if (!priv->mapped)
-    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);
-
-      /* ::size-changed is supposed to refer to meta_window_get_frame_rect().
-       * Emitting it here works pretty much OK because a new value of the
-       * *input* rect (which is the outer rect with the addition of invisible
-       * borders) forces a new pixmap and we get here. In the rare case where
-       * a change to the window size was exactly balanced by a change to the
-       * invisible borders, we would miss emitting the signal. We would also
-       * emit spurious signals when we get a new pixmap without a new size,
-       * but that should be mostly harmless.
-       */
-      g_signal_emit (self, signals[SIZE_CHANGED], 0);
-    }
-
-  priv->needs_pixmap = FALSE;
-
- out:
-  meta_error_trap_pop (display);
-}
-
 static void
 check_needs_shadow (MetaWindowActor *self)
 {
@@ -1984,9 +1620,6 @@ check_needs_shadow (MetaWindowActor *self)
   gboolean should_have_shadow;
   gboolean appears_focused;
 
-  if (!priv->mapped)
-    return;
-
   /* Calling meta_window_actor_has_shadow() here at every pre-paint is cheap
    * and avoids the need to explicitly handle window type changes, which
    * we would do if tried to keep track of when we might be adding or removing
@@ -2040,70 +1673,6 @@ check_needs_shadow (MetaWindowActor *self)
 }
 
 void
-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->mapped || 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;
-
-}
-
-void
 meta_window_actor_sync_visibility (MetaWindowActor *self)
 {
   MetaWindowActorPrivate *priv = self->priv;
@@ -2322,8 +1891,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;
 
@@ -2343,7 +1913,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);
@@ -2359,9 +1929,6 @@ check_needs_reshape (MetaWindowActor *self)
   MetaFrameBorders borders;
   cairo_rectangle_int_t client_area;
 
-  if (!priv->mapped)
-    return;
-
   if (!priv->needs_reshape)
     return;
 
@@ -2403,9 +1970,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))
     {
@@ -2414,45 +1978,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_content_pre_paint (priv->surface_content);
 
-      check_needs_x11_pixmap (self);
-    }
+  if (!meta_surface_content_is_visible (priv->surface_content))
+    return;
 
   check_needs_reshape (self);
   check_needs_shadow (self);
@@ -2641,20 +2170,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 0f90839..bf45bfc 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"
@@ -59,6 +59,9 @@
 #include "meta-weston-launch.h"
 #include "monitor-private.h"
 
+#include "meta-surface-actor.h"
+#include "meta-surface-content-wayland.h"
+
 static void
 surface_process_damage (MetaWaylandSurface *surface,
                         cairo_region_t *region)
@@ -69,8 +72,9 @@ 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_content_process_damage (surface->surface_content,
+                                           rect.x, rect.y, rect.width, rect.height);
     }
 }
 
@@ -261,7 +265,7 @@ actor_surface_commit (MetaWaylandSurface *surface)
     {
       ensure_buffer_texture (buffer);
       meta_wayland_buffer_reference (&surface->buffer_ref, buffer);
-      meta_surface_actor_attach_wayland_buffer (surface_actor, buffer);
+      meta_surface_content_wayland_set_buffer (META_SURFACE_CONTENT_WAYLAND (surface->surface_content), 
buffer);
       changed = TRUE;
     }
 
@@ -413,6 +417,7 @@ meta_wayland_surface_free (MetaWaylandSurface *surface)
   meta_wayland_compositor_repick (compositor);
 
   g_object_unref (surface->surface_actor);
+  g_object_unref (surface->surface_content);
 
   if (surface->resource)
     wl_resource_set_user_data (surface->resource, NULL);
@@ -503,6 +508,9 @@ meta_wayland_surface_create (MetaWaylandCompositor *compositor,
   wl_list_init (&surface->pending.frame_callback_list);
 
   surface->surface_actor = g_object_ref_sink (meta_surface_actor_new ());
+  surface->surface_content = g_object_ref_sink (meta_surface_content_wayland_new (surface));
+  meta_surface_actor_set_content (surface->surface_actor, surface->surface_content);
+
   return surface;
 }
 
diff --git a/src/wayland/meta-wayland-surface.h b/src/wayland/meta-wayland-surface.h
index 9533731..923d192 100644
--- a/src/wayland/meta-wayland-surface.h
+++ b/src/wayland/meta-wayland-surface.h
@@ -79,6 +79,7 @@ struct _MetaWaylandSurface
   MetaWaylandCompositor *compositor;
   MetaWaylandBufferReference buffer_ref;
   MetaSurfaceActor *surface_actor;
+  MetaSurfaceContent *surface_content;
   MetaWindow *window;
   MetaWaylandSurfaceExtension xdg_surface;
   MetaWaylandSurfaceExtension xdg_popup;


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