[mutter/wip/surface-content: 8/8] surface content
- From: Jasper St. Pierre <jstpierre src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [mutter/wip/surface-content: 8/8] surface content
- Date: Fri, 6 Dec 2013 20:23:22 +0000 (UTC)
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]