diff --git a/src/Makefile.am b/src/Makefile.am index ae8f7c130..dcf94e53b 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -80,6 +80,10 @@ libmutter_wayland_la_SOURCES = \ compositor/meta-shaped-texture-private.h \ compositor/meta-surface-actor.c \ compositor/meta-surface-actor.h \ + compositor/meta-surface-actor-x11.c \ + compositor/meta-surface-actor-x11.h \ + compositor/meta-surface-actor-wayland.c \ + compositor/meta-surface-actor-wayland.h \ compositor/meta-texture-rectangle.c \ compositor/meta-texture-rectangle.h \ compositor/meta-texture-tower.c \ diff --git a/src/compositor/meta-surface-actor-wayland.c b/src/compositor/meta-surface-actor-wayland.c new file mode 100644 index 000000000..9fe1e8220 --- /dev/null +++ b/src/compositor/meta-surface-actor-wayland.c @@ -0,0 +1,153 @@ +/* -*- 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 + */ + +#include "config.h" + +#include "meta-surface-actor-wayland.h" + +#include +#include "meta-shaped-texture-private.h" + +struct _MetaSurfaceActorWaylandPrivate +{ + MetaWaylandSurface *surface; + MetaWaylandBuffer *buffer; +}; +typedef struct _MetaSurfaceActorWaylandPrivate MetaSurfaceActorWaylandPrivate; + +G_DEFINE_TYPE_WITH_PRIVATE (MetaSurfaceActorWayland, meta_surface_actor_wayland, META_TYPE_SURFACE_ACTOR) + +static void +meta_surface_actor_wayland_process_damage (MetaSurfaceActor *actor, + int x, int y, int width, int height) +{ + MetaSurfaceActorWayland *self = META_SURFACE_ACTOR_WAYLAND (actor); + MetaSurfaceActorWaylandPrivate *priv = meta_surface_actor_wayland_get_instance_private (self); + + struct wl_resource *resource = priv->buffer->resource; + struct wl_shm_buffer *shm_buffer = wl_shm_buffer_get (resource); + + if (shm_buffer) + { + CoglTexture2D *texture = COGL_TEXTURE_2D (priv->buffer->texture); + cogl_wayland_texture_set_region_from_shm_buffer (texture, x, y, width, height, shm_buffer, x, y, 0, NULL); + } + + meta_surface_actor_update_area (META_SURFACE_ACTOR (self), x, y, width, height); +} + +static void +meta_surface_actor_wayland_pre_paint (MetaSurfaceActor *actor) +{ +} + +static gboolean +meta_surface_actor_wayland_is_argb32 (MetaSurfaceActor *actor) +{ + /* XXX -- look at the SHM buffer format. */ + return TRUE; +} + +static gboolean +meta_surface_actor_wayland_is_visible (MetaSurfaceActor *actor) +{ + /* TODO: ensure that the buffer isn't NULL, implement + * wayland mapping semantics */ + return TRUE; +} + +static gboolean +meta_surface_actor_wayland_should_unredirect (MetaSurfaceActor *actor) +{ + return FALSE; +} + +static void +meta_surface_actor_wayland_set_unredirected (MetaSurfaceActor *actor, + gboolean unredirected) +{ + /* Do nothing. In the future, we'll use KMS to set this + * up as a hardware overlay or something. */ +} + +static gboolean +meta_surface_actor_wayland_is_unredirected (MetaSurfaceActor *actor) +{ + return FALSE; +} + +static void +meta_surface_actor_wayland_class_init (MetaSurfaceActorWaylandClass *klass) +{ + MetaSurfaceActorClass *surface_actor_class = META_SURFACE_ACTOR_CLASS (klass); + + surface_actor_class->process_damage = meta_surface_actor_wayland_process_damage; + surface_actor_class->pre_paint = meta_surface_actor_wayland_pre_paint; + surface_actor_class->is_argb32 = meta_surface_actor_wayland_is_argb32; + surface_actor_class->is_visible = meta_surface_actor_wayland_is_visible; + + surface_actor_class->should_unredirect = meta_surface_actor_wayland_should_unredirect; + surface_actor_class->set_unredirected = meta_surface_actor_wayland_set_unredirected; + surface_actor_class->is_unredirected = meta_surface_actor_wayland_is_unredirected; +} + +static void +meta_surface_actor_wayland_init (MetaSurfaceActorWayland *self) +{ +} + +MetaSurfaceActor * +meta_surface_actor_wayland_new (MetaWaylandSurface *surface) +{ + MetaSurfaceActorWayland *self = g_object_new (META_TYPE_SURFACE_ACTOR_WAYLAND, NULL); + MetaSurfaceActorWaylandPrivate *priv = meta_surface_actor_wayland_get_instance_private (self); + + g_assert (meta_is_wayland_compositor ()); + + priv->surface = surface; + + return META_SURFACE_ACTOR (self); +} + +void +meta_surface_actor_wayland_set_buffer (MetaSurfaceActorWayland *self, + MetaWaylandBuffer *buffer) +{ + MetaSurfaceActorWaylandPrivate *priv = meta_surface_actor_wayland_get_instance_private (self); + MetaShapedTexture *stex = meta_surface_actor_get_texture (META_SURFACE_ACTOR (self)); + + priv->buffer = buffer; + + if (buffer) + meta_shaped_texture_set_texture (stex, buffer->texture); + else + meta_shaped_texture_set_texture (stex, NULL); +} + +MetaWaylandSurface * +meta_surface_actor_wayland_get_surface (MetaSurfaceActorWayland *self) +{ + MetaSurfaceActorWaylandPrivate *priv = meta_surface_actor_wayland_get_instance_private (self); + return priv->surface; +} diff --git a/src/compositor/meta-surface-actor-wayland.h b/src/compositor/meta-surface-actor-wayland.h new file mode 100644 index 000000000..89c6b300f --- /dev/null +++ b/src/compositor/meta-surface-actor-wayland.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: + * Jasper St. Pierre + */ + +#ifndef __META_SURFACE_ACTOR_WAYLAND_H__ +#define __META_SURFACE_ACTOR_WAYLAND_H__ + +#include + +#include "meta-surface-actor.h" + +#include "meta-wayland-private.h" + +G_BEGIN_DECLS + +#define META_TYPE_SURFACE_ACTOR_WAYLAND (meta_surface_actor_wayland_get_type ()) +#define META_SURFACE_ACTOR_WAYLAND(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_SURFACE_ACTOR_WAYLAND, MetaSurfaceActorWayland)) +#define META_SURFACE_ACTOR_WAYLAND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_SURFACE_ACTOR_WAYLAND, MetaSurfaceActorWaylandClass)) +#define META_IS_SURFACE_ACTOR_WAYLAND(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_SURFACE_ACTOR_WAYLAND)) +#define META_IS_SURFACE_ACTOR_WAYLAND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_SURFACE_ACTOR_WAYLAND)) +#define META_SURFACE_ACTOR_WAYLAND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_SURFACE_ACTOR_WAYLAND, MetaSurfaceActorWaylandClass)) + +typedef struct _MetaSurfaceActorWayland MetaSurfaceActorWayland; +typedef struct _MetaSurfaceActorWaylandClass MetaSurfaceActorWaylandClass; + +struct _MetaSurfaceActorWayland +{ + MetaSurfaceActor parent; +}; + +struct _MetaSurfaceActorWaylandClass +{ + MetaSurfaceActorClass parent_class; +}; + +GType meta_surface_actor_wayland_get_type (void); + +MetaSurfaceActor * meta_surface_actor_wayland_new (MetaWaylandSurface *surface); +MetaWaylandSurface * meta_surface_actor_wayland_get_surface (MetaSurfaceActorWayland *self); + +void meta_surface_actor_wayland_set_buffer (MetaSurfaceActorWayland *self, + MetaWaylandBuffer *buffer); + +G_END_DECLS + +#endif /* __META_SURFACE_ACTOR_WAYLAND_H__ */ diff --git a/src/compositor/meta-surface-actor-x11.c b/src/compositor/meta-surface-actor-x11.c new file mode 100644 index 000000000..3eea2c31b --- /dev/null +++ b/src/compositor/meta-surface-actor-x11.c @@ -0,0 +1,453 @@ +/* -*- 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 + * Jasper St. Pierre + */ + +#include "config.h" + +#include "meta-surface-actor-x11.h" + +#include +#include +#include + +#include +#include "window-private.h" +#include "meta-shaped-texture-private.h" +#include "meta-cullable.h" + +struct _MetaSurfaceActorX11Private +{ + MetaWindow *window; + + MetaDisplay *display; + + CoglTexture *texture; + Pixmap pixmap; + Damage damage; + + int last_width; + int last_height; + + /* This is used to detect fullscreen windows that need to be unredirected */ + guint full_damage_frames_count; + guint does_full_damage : 1; + + /* Other state... */ + guint argb32 : 1; + guint received_damage : 1; + guint size_changed : 1; + + guint unredirected : 1; +}; +typedef struct _MetaSurfaceActorX11Private MetaSurfaceActorX11Private; + +G_DEFINE_TYPE_WITH_PRIVATE (MetaSurfaceActorX11, meta_surface_actor_x11, META_TYPE_SURFACE_ACTOR) + +static void +free_damage (MetaSurfaceActorX11 *self) +{ + MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self); + MetaDisplay *display = priv->display; + Display *xdisplay = meta_display_get_xdisplay (display); + + if (priv->damage == None) + return; + + meta_error_trap_push (display); + XDamageDestroy (xdisplay, priv->damage); + priv->damage = None; + meta_error_trap_pop (display); +} + +static void +detach_pixmap (MetaSurfaceActorX11 *self) +{ + MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self); + MetaDisplay *display = priv->display; + Display *xdisplay = meta_display_get_xdisplay (display); + MetaShapedTexture *stex = meta_surface_actor_get_texture (META_SURFACE_ACTOR (self)); + + if (priv->pixmap == None) + return; + + /* 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_shaped_texture_set_texture (stex, NULL); + cogl_flush (); + + meta_error_trap_push (display); + XFreePixmap (xdisplay, priv->pixmap); + priv->pixmap = None; + meta_error_trap_pop (display); + + cogl_object_unref (priv->texture); + priv->texture = NULL; +} + +static void +set_pixmap (MetaSurfaceActorX11 *self, + Pixmap pixmap) +{ + MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self); + + CoglContext *ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ()); + MetaShapedTexture *stex = meta_surface_actor_get_texture (META_SURFACE_ACTOR (self)); + CoglTexture *texture; + + g_assert (priv->pixmap == None); + priv->pixmap = pixmap; + + texture = COGL_TEXTURE (cogl_texture_pixmap_x11_new (ctx, priv->pixmap, FALSE, NULL)); + + if (G_UNLIKELY (!cogl_texture_pixmap_x11_is_using_tfp_extension (COGL_TEXTURE_PIXMAP_X11 (texture)))) + g_warning ("NOTE: Not using GLX TFP!\n"); + + priv->texture = texture; + meta_shaped_texture_set_texture (stex, texture); +} + +static void +update_pixmap (MetaSurfaceActorX11 *self) +{ + MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self); + MetaDisplay *display = priv->display; + Display *xdisplay = meta_display_get_xdisplay (display); + + if (priv->size_changed) + { + detach_pixmap (self); + priv->size_changed = FALSE; + } + + if (priv->pixmap == None) + { + Pixmap new_pixmap; + Window xwindow = meta_window_get_toplevel_xwindow (priv->window); + + meta_error_trap_push (display); + new_pixmap = XCompositeNameWindowPixmap (xdisplay, xwindow); + + if (meta_error_trap_pop_with_return (display) != Success) + { + /* Probably a BadMatch if the window isn't viewable; we could + * GrabServer/GetWindowAttributes/NameWindowPixmap/UngrabServer/Sync + * to avoid this, but there's no reason to take two round trips + * when one will do. (We need that Sync if we want to handle failures + * for any reason other than !viewable. That's unlikely, but maybe + * we'll BadAlloc or something.) + */ + new_pixmap = None; + } + + if (new_pixmap == None) + { + meta_verbose ("Unable to get named pixmap for %s\n", + meta_window_get_description (priv->window)); + return; + } + + set_pixmap (self, new_pixmap); + } +} + +static gboolean +is_visible (MetaSurfaceActorX11 *self) +{ + MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self); + return (priv->pixmap != None) && !priv->unredirected; +} + +static void +damage_area (MetaSurfaceActorX11 *self, + int x, int y, int width, int height) +{ + MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self); + + if (!is_visible (self)) + return; + + cogl_texture_pixmap_x11_update_area (priv->texture, x, y, width, height); + meta_surface_actor_update_area (META_SURFACE_ACTOR (self), x, y, width, height); +} + +static void +meta_surface_actor_x11_process_damage (MetaSurfaceActor *actor, + int x, int y, int width, int height) +{ + MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (actor); + MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self); + + priv->received_damage = TRUE; + + if (meta_window_is_fullscreen (priv->window) && !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; + } + + /* Drop damage event for unredirected windows */ + if (priv->unredirected) + return; + + damage_area (self, x, y, width, height); +} + +static void +meta_surface_actor_x11_pre_paint (MetaSurfaceActor *actor) +{ + MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (actor); + MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self); + MetaDisplay *display = priv->display; + Display *xdisplay = meta_display_get_xdisplay (display); + + if (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 +update_is_argb32 (MetaSurfaceActorX11 *self) +{ + MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self); + MetaDisplay *display = priv->display; + Display *xdisplay = meta_display_get_xdisplay (display); + + XRenderPictFormat *format; + format = XRenderFindVisualFormat (xdisplay, priv->window->xvisual); + + priv->argb32 = (format && format->type == PictTypeDirect && format->direct.alphaMask); +} + +static gboolean +meta_surface_actor_x11_is_argb32 (MetaSurfaceActor *actor) +{ + MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (actor); + MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self); + + return priv->argb32; +} + +static gboolean +meta_surface_actor_x11_is_visible (MetaSurfaceActor *actor) +{ + MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (actor); + return is_visible (self); +} + +static gboolean +meta_surface_actor_x11_should_unredirect (MetaSurfaceActor *actor) +{ + MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (actor); + MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self); + + MetaWindow *window = priv->window; + + if (meta_window_requested_dont_bypass_compositor (window)) + return FALSE; + + if (window->opacity != 0xFF) + return FALSE; + + if (window->shape_region != NULL) + return FALSE; + + if (priv->argb32 && !meta_window_requested_bypass_compositor (window)) + return FALSE; + + if (!meta_window_is_monitor_sized (window)) + return FALSE; + + if (meta_window_requested_bypass_compositor (window)) + return TRUE; + + if (meta_window_is_override_redirect (window)) + return TRUE; + + if (priv->does_full_damage) + return TRUE; + + return FALSE; +} + +static void +sync_unredirected (MetaSurfaceActorX11 *self) +{ + MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self); + MetaDisplay *display = priv->display; + Display *xdisplay = meta_display_get_xdisplay (display); + Window xwindow = meta_window_get_toplevel_xwindow (priv->window); + + meta_error_trap_push (display); + + if (priv->unredirected) + { + detach_pixmap (self); + XCompositeUnredirectWindow (xdisplay, xwindow, CompositeRedirectManual); + } + else + { + XCompositeRedirectWindow (xdisplay, xwindow, CompositeRedirectManual); + } + + meta_error_trap_pop (display); +} + +static void +meta_surface_actor_x11_set_unredirected (MetaSurfaceActor *actor, + gboolean unredirected) +{ + MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (actor); + MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self); + + if (priv->unredirected == unredirected) + return; + + priv->unredirected = unredirected; + sync_unredirected (self); +} + +static gboolean +meta_surface_actor_x11_is_unredirected (MetaSurfaceActor *actor) +{ + MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (actor); + MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self); + + return priv->unredirected; +} + +static void +meta_surface_actor_x11_dispose (GObject *object) +{ + MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (object); + + detach_pixmap (self); + free_damage (self); + + G_OBJECT_CLASS (meta_surface_actor_x11_parent_class)->dispose (object); +} + +static void +meta_surface_actor_x11_class_init (MetaSurfaceActorX11Class *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + MetaSurfaceActorClass *surface_actor_class = META_SURFACE_ACTOR_CLASS (klass); + + object_class->dispose = meta_surface_actor_x11_dispose; + + surface_actor_class->process_damage = meta_surface_actor_x11_process_damage; + surface_actor_class->pre_paint = meta_surface_actor_x11_pre_paint; + surface_actor_class->is_argb32 = meta_surface_actor_x11_is_argb32; + surface_actor_class->is_visible = meta_surface_actor_x11_is_visible; + + surface_actor_class->should_unredirect = meta_surface_actor_x11_should_unredirect; + surface_actor_class->set_unredirected = meta_surface_actor_x11_set_unredirected; + surface_actor_class->is_unredirected = meta_surface_actor_x11_is_unredirected; +} + +static void +meta_surface_actor_x11_init (MetaSurfaceActorX11 *self) +{ + MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self); + + priv->last_width = -1; + priv->last_height = -1; +} + +MetaSurfaceActor * +meta_surface_actor_x11_new (MetaWindow *window) +{ + MetaSurfaceActorX11 *self = g_object_new (META_TYPE_SURFACE_ACTOR_X11, NULL); + MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self); + MetaDisplay *display = meta_window_get_display (window); + Display *xdisplay = meta_display_get_xdisplay (display); + Window xwindow = meta_window_get_toplevel_xwindow (window); + + g_assert (!meta_is_wayland_compositor ()); + + priv->window = window; + priv->display = display; + + priv->damage = XDamageCreate (xdisplay, xwindow, XDamageReportBoundingBox); + update_is_argb32 (self); + + priv->unredirected = FALSE; + sync_unredirected (self); + + return META_SURFACE_ACTOR (self); +} + +void +meta_surface_actor_x11_set_size (MetaSurfaceActorX11 *self, + int width, int height) +{ + MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self); + + if (priv->last_width == width && + priv->last_height == height) + return; + + priv->size_changed = TRUE; + priv->last_width = width; + priv->last_height = height; +} diff --git a/src/compositor/meta-surface-actor-x11.h b/src/compositor/meta-surface-actor-x11.h new file mode 100644 index 000000000..0e692ee0f --- /dev/null +++ b/src/compositor/meta-surface-actor-x11.h @@ -0,0 +1,69 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ + +/* + * Copyright (C) 2013 Red Hat + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + * + * Written by: + * Owen Taylor + * Jasper St. Pierre + */ + +#ifndef __META_SURFACE_ACTOR_X11_H__ +#define __META_SURFACE_ACTOR_X11_H__ + +#include + +#include "meta-surface-actor.h" + +#include + +#include +#include + +G_BEGIN_DECLS + +#define META_TYPE_SURFACE_ACTOR_X11 (meta_surface_actor_x11_get_type ()) +#define META_SURFACE_ACTOR_X11(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_SURFACE_ACTOR_X11, MetaSurfaceActorX11)) +#define META_SURFACE_ACTOR_X11_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_SURFACE_ACTOR_X11, MetaSurfaceActorX11Class)) +#define META_IS_SURFACE_ACTOR_X11(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_SURFACE_ACTOR_X11)) +#define META_IS_SURFACE_ACTOR_X11_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_SURFACE_ACTOR_X11)) +#define META_SURFACE_ACTOR_X11_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_SURFACE_ACTOR_X11, MetaSurfaceActorX11Class)) + +typedef struct _MetaSurfaceActorX11 MetaSurfaceActorX11; +typedef struct _MetaSurfaceActorX11Class MetaSurfaceActorX11Class; + +struct _MetaSurfaceActorX11 +{ + MetaSurfaceActor parent; +}; + +struct _MetaSurfaceActorX11Class +{ + MetaSurfaceActorClass parent_class; +}; + +GType meta_surface_actor_x11_get_type (void); + +MetaSurfaceActor * meta_surface_actor_x11_new (MetaWindow *window); + +void meta_surface_actor_x11_set_size (MetaSurfaceActorX11 *self, + int width, int height); + +G_END_DECLS + +#endif /* __META_SURFACE_ACTOR_X11_H__ */ diff --git a/src/compositor/meta-surface-actor.c b/src/compositor/meta-surface-actor.c index 5afa4d70f..734629a79 100644 --- a/src/compositor/meta-surface-actor.c +++ b/src/compositor/meta-surface-actor.c @@ -10,30 +10,30 @@ */ #include -#include -#include -#include -#include + #include "meta-surface-actor.h" + +#include +#include #include "meta-wayland-private.h" #include "meta-cullable.h" - #include "meta-shaped-texture-private.h" struct _MetaSurfaceActorPrivate { - MetaWaylandSurface *surface; - MetaShapedTexture *texture; - MetaWaylandBuffer *buffer; cairo_region_t *input_region; + + /* Freeze/thaw accounting */ + guint freeze_count; + guint needs_damage_all : 1; }; static void cullable_iface_init (MetaCullableInterface *iface); -G_DEFINE_TYPE_WITH_CODE (MetaSurfaceActor, meta_surface_actor, CLUTTER_TYPE_ACTOR, - G_IMPLEMENT_INTERFACE (META_TYPE_CULLABLE, cullable_iface_init)); +G_DEFINE_ABSTRACT_TYPE_WITH_CODE (MetaSurfaceActor, meta_surface_actor, CLUTTER_TYPE_ACTOR, + G_IMPLEMENT_INTERFACE (META_TYPE_CULLABLE, cullable_iface_init)); gboolean meta_surface_actor_get_unobscured_bounds (MetaSurfaceActor *self, @@ -164,50 +164,11 @@ 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); - } -} - gboolean -meta_surface_actor_damage_all (MetaSurfaceActor *self) +meta_surface_actor_update_area (MetaSurfaceActor *self, + int x, int y, int width, int height) { 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)); -} - -gboolean -meta_surface_actor_damage_area (MetaSurfaceActor *self, - int x, - int y, - int width, - int height) -{ - MetaSurfaceActorPrivate *priv = self->priv; - - update_area (self, x, y, width, height); return meta_shaped_texture_update_area (priv->texture, x, y, width, height); } @@ -218,27 +179,6 @@ meta_surface_actor_is_obscured (MetaSurfaceActor *self) return meta_shaped_texture_is_obscured (priv->texture); } -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) @@ -262,20 +202,114 @@ meta_surface_actor_set_opaque_region (MetaSurfaceActor *self, meta_shaped_texture_set_opaque_region (priv->texture, region); } -MetaWaylandSurface * -meta_surface_actor_get_surface (MetaSurfaceActor *self) +static gboolean +is_frozen (MetaSurfaceActor *self) { MetaSurfaceActorPrivate *priv = self->priv; - return priv->surface; + return (priv->freeze_count > 0); } -MetaSurfaceActor * -meta_surface_actor_new (MetaWaylandSurface *surface) +void +meta_surface_actor_process_damage (MetaSurfaceActor *self, + int x, int y, int width, int height) { - MetaSurfaceActor *self = g_object_new (META_TYPE_SURFACE_ACTOR, NULL); MetaSurfaceActorPrivate *priv = self->priv; - priv->surface = surface; + 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; + } - return self; + META_SURFACE_ACTOR_GET_CLASS (self)->process_damage (self, x, y, width, height); +} + +void +meta_surface_actor_pre_paint (MetaSurfaceActor *self) +{ + META_SURFACE_ACTOR_GET_CLASS (self)->pre_paint (self); +} + +gboolean +meta_surface_actor_is_argb32 (MetaSurfaceActor *self) +{ + return META_SURFACE_ACTOR_GET_CLASS (self)->is_argb32 (self); +} + +gboolean +meta_surface_actor_is_visible (MetaSurfaceActor *self) +{ + return META_SURFACE_ACTOR_GET_CLASS (self)->is_visible (self); +} + +void +meta_surface_actor_freeze (MetaSurfaceActor *self) +{ + MetaSurfaceActorPrivate *priv = self->priv; + + priv->freeze_count ++; +} + +void +meta_surface_actor_thaw (MetaSurfaceActor *self) +{ + MetaSurfaceActorPrivate *priv = self->priv; + + 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) + { + meta_surface_actor_process_damage (self, 0, 0, + clutter_actor_get_width (CLUTTER_ACTOR (priv->texture)), + clutter_actor_get_height (CLUTTER_ACTOR (priv->texture))); + priv->needs_damage_all = FALSE; + } +} + +gboolean +meta_surface_actor_is_frozen (MetaSurfaceActor *self) +{ + return is_frozen (self); +} + +gboolean +meta_surface_actor_should_unredirect (MetaSurfaceActor *self) +{ + return META_SURFACE_ACTOR_GET_CLASS (self)->should_unredirect (self); +} + +void +meta_surface_actor_set_unredirected (MetaSurfaceActor *self, + gboolean unredirected) +{ + META_SURFACE_ACTOR_GET_CLASS (self)->set_unredirected (self, unredirected); +} + +gboolean +meta_surface_actor_is_unredirected (MetaSurfaceActor *self) +{ + return META_SURFACE_ACTOR_GET_CLASS (self)->is_unredirected (self); } diff --git a/src/compositor/meta-surface-actor.h b/src/compositor/meta-surface-actor.h index e42deb42f..c3182a626 100644 --- a/src/compositor/meta-surface-actor.h +++ b/src/compositor/meta-surface-actor.h @@ -6,7 +6,6 @@ #include #include -#include "meta-wayland-types.h" G_BEGIN_DECLS @@ -25,6 +24,17 @@ struct _MetaSurfaceActorClass { /*< private >*/ ClutterActorClass parent_class; + + void (* process_damage) (MetaSurfaceActor *actor, + int x, int y, int width, int height); + void (* pre_paint) (MetaSurfaceActor *actor); + gboolean (* is_argb32) (MetaSurfaceActor *actor); + gboolean (* is_visible) (MetaSurfaceActor *actor); + + gboolean (* should_unredirect) (MetaSurfaceActor *actor); + void (* set_unredirected) (MetaSurfaceActor *actor, + gboolean unredirected); + gboolean (* is_unredirected) (MetaSurfaceActor *actor); }; struct _MetaSurfaceActor @@ -36,34 +46,37 @@ struct _MetaSurfaceActor GType meta_surface_actor_get_type (void); -MetaSurfaceActor *meta_surface_actor_new (MetaWaylandSurface *surface); - cairo_surface_t *meta_surface_actor_get_image (MetaSurfaceActor *self, cairo_rectangle_int_t *clip); MetaShapedTexture *meta_surface_actor_get_texture (MetaSurfaceActor *self); -gboolean meta_surface_actor_damage_all (MetaSurfaceActor *self); -gboolean meta_surface_actor_damage_area (MetaSurfaceActor *self, - int x, - int y, - int width, - int height); - gboolean meta_surface_actor_is_obscured (MetaSurfaceActor *self); gboolean meta_surface_actor_get_unobscured_bounds (MetaSurfaceActor *self, cairo_rectangle_int_t *unobscured_bounds); -void meta_surface_actor_set_texture (MetaSurfaceActor *self, - CoglTexture *texture); -void meta_surface_actor_attach_wayland_buffer (MetaSurfaceActor *self, - MetaWaylandBuffer *buffer); void meta_surface_actor_set_input_region (MetaSurfaceActor *self, cairo_region_t *region); void meta_surface_actor_set_opaque_region (MetaSurfaceActor *self, cairo_region_t *region); -MetaWaylandSurface *meta_surface_actor_get_surface (MetaSurfaceActor *surface); +gboolean meta_surface_actor_update_area (MetaSurfaceActor *actor, + int x, int y, int width, int height); + +void meta_surface_actor_process_damage (MetaSurfaceActor *actor, + int x, int y, int width, int height); +void meta_surface_actor_pre_paint (MetaSurfaceActor *actor); +gboolean meta_surface_actor_is_argb32 (MetaSurfaceActor *actor); +gboolean meta_surface_actor_is_visible (MetaSurfaceActor *actor); + +void meta_surface_actor_freeze (MetaSurfaceActor *actor); +void meta_surface_actor_thaw (MetaSurfaceActor *actor); +gboolean meta_surface_actor_is_frozen (MetaSurfaceActor *actor); + +gboolean meta_surface_actor_should_unredirect (MetaSurfaceActor *actor); +void meta_surface_actor_set_unredirected (MetaSurfaceActor *actor, + gboolean unredirected); +gboolean meta_surface_actor_is_unredirected (MetaSurfaceActor *actor); G_END_DECLS diff --git a/src/compositor/meta-window-actor.c b/src/compositor/meta-window-actor.c index 1ffc51251..ba6f3f14f 100644 --- a/src/compositor/meta-window-actor.c +++ b/src/compositor/meta-window-actor.c @@ -10,10 +10,6 @@ #include -#include -#include -#include - #include #include #include /* for gdk_rectangle_union() */ @@ -30,13 +26,15 @@ #include "meta-shaped-texture-private.h" #include "meta-shadow-factory-private.h" #include "meta-window-actor-private.h" -#include "meta-surface-actor.h" #include "meta-texture-rectangle.h" #include "region-utils.h" #include "meta-wayland-private.h" #include "monitor-private.h" #include "meta-cullable.h" +#include "meta-surface-actor.h" +#include "meta-surface-actor-x11.h" + struct _MetaWindowActorPrivate { MetaWindow *window; @@ -63,19 +61,13 @@ struct _MetaWindowActorPrivate /* The region we should clip to when painting the shadow */ cairo_region_t *shadow_clip; - guint send_frame_messages_timer; - gint64 frame_drawn_time; - /* Extracted size-invariant shape used for shadows */ MetaWindowShape *shadow_shape; - - gint last_width; - gint last_height; - - gint freeze_count; - char * shadow_class; + guint send_frame_messages_timer; + gint64 frame_drawn_time; + /* * These need to be counters rather than flags, since more plugins * can implement same effect; the practicality of stacking effects @@ -90,11 +82,7 @@ struct _MetaWindowActorPrivate /* List of FrameData for recent frames */ GList *frames; - Pixmap back_pixmap; /* Not used in wayland compositor mode */ - Damage damage; /* Not used in wayland compositor mode */ - guint visible : 1; - guint argb32 : 1; guint disposed : 1; guint redecorating : 1; @@ -111,22 +99,7 @@ struct _MetaWindowActorPrivate guint no_shadow : 1; - - /* - * None of these are used in wayland compositor mode... - */ - - guint needs_damage_all : 1; - guint received_x11_damage : 1; - - guint 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; @@ -163,7 +136,6 @@ static gboolean meta_window_actor_get_paint_volume (ClutterActor *actor, ClutterPaintVolume *volume); -static void meta_window_actor_detach_x11_pixmap (MetaWindowActor *self); static gboolean meta_window_actor_has_shadow (MetaWindowActor *self); static void meta_window_actor_handle_updates (MetaWindowActor *self); @@ -254,9 +226,6 @@ window_decorated_notify (MetaWindow *mw, { MetaWindowActor *self = META_WINDOW_ACTOR (data); MetaWindowActorPrivate *priv = self->priv; - MetaScreen *screen = priv->screen; - MetaDisplay *display = meta_screen_get_display (screen); - Display *xdisplay = meta_display_get_xdisplay (display); /* * Basically, we have to reconstruct the the internals of this object @@ -264,23 +233,6 @@ window_decorated_notify (MetaWindow *mw, */ priv->redecorating = TRUE; - if (!meta_is_wayland_compositor ()) - { - meta_window_actor_detach_x11_pixmap (self); - - /* - * First of all, clean up any resources we are currently using and will - * be replacing. - */ - if (priv->damage != None) - { - meta_error_trap_push (display); - XDamageDestroy (xdisplay, priv->damage); - meta_error_trap_pop (display); - priv->damage = None; - } - } - /* * Recreate the contents. */ @@ -305,13 +257,52 @@ surface_allocation_changed_notify (ClutterActor *actor, meta_window_actor_update_shape (self); } +static gboolean +is_argb32 (MetaWindowActor *self) +{ + MetaWindowActorPrivate *priv = self->priv; + return meta_surface_actor_is_argb32 (priv->surface); +} + static gboolean is_non_opaque (MetaWindowActor *self) { MetaWindowActorPrivate *priv = self->priv; MetaWindow *window = priv->window; - return priv->argb32 || (window->opacity != 0xFF); + return is_argb32 (self) || (window->opacity != 0xFF); +} + +static gboolean +is_frozen (MetaWindowActor *self) +{ + MetaWindowActorPrivate *priv = self->priv; + return meta_surface_actor_is_frozen (priv->surface); +} + +static void +meta_window_actor_freeze (MetaWindowActor *self) +{ + MetaWindowActorPrivate *priv = self->priv; + meta_surface_actor_freeze (priv->surface); +} + +static void +meta_window_actor_thaw (MetaWindowActor *self) +{ + MetaWindowActorPrivate *priv = self->priv; + + meta_surface_actor_thaw (priv->surface); + + if (is_frozen (self)) + 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); } static void @@ -320,38 +311,15 @@ meta_window_actor_constructed (GObject *object) MetaWindowActor *self = META_WINDOW_ACTOR (object); MetaWindowActorPrivate *priv = self->priv; MetaWindow *window = priv->window; - Window xwindow = meta_window_get_toplevel_xwindow (window); - MetaScreen *screen = meta_window_get_screen (window); - MetaDisplay *display = meta_screen_get_display (screen); - Display *xdisplay = meta_display_get_xdisplay (display); - priv->screen = screen; - - if (!meta_is_wayland_compositor ()) - priv->damage = XDamageCreate (xdisplay, xwindow, - XDamageReportBoundingBox); - - if (window->client_type == META_WINDOW_CLIENT_TYPE_X11) - { - XRenderPictFormat *format; - - format = XRenderFindVisualFormat (xdisplay, window->xvisual); - - if (format && format->type == PictTypeDirect && format->direct.alphaMask) - priv->argb32 = TRUE; - } - else - { - /* XXX: parse shm formats to determine argb32 */ - priv->argb32 = TRUE; - } + priv->screen = window->screen; if (!priv->surface) { if (window->surface) priv->surface = window->surface->surface_actor; else - priv->surface = meta_surface_actor_new (NULL); + priv->surface = meta_surface_actor_x11_new (window); g_object_ref_sink (priv->surface); clutter_actor_add_child (CLUTTER_ACTOR (self), CLUTTER_ACTOR (priv->surface)); @@ -374,8 +342,6 @@ meta_window_actor_dispose (GObject *object) MetaWindowActor *self = META_WINDOW_ACTOR (object); MetaWindowActorPrivate *priv = self->priv; MetaScreen *screen; - MetaDisplay *display; - Display *xdisplay; MetaCompScreen *info; if (priv->disposed) @@ -386,9 +352,6 @@ meta_window_actor_dispose (GObject *object) screen = priv->screen; info = meta_screen_get_compositor_data (screen); - if (!meta_is_wayland_compositor ()) - meta_window_actor_detach_x11_pixmap (self); - if (priv->send_frame_messages_timer != 0) { g_source_remove (priv->send_frame_messages_timer); @@ -403,18 +366,6 @@ meta_window_actor_dispose (GObject *object) g_clear_pointer (&priv->unfocused_shadow, meta_shadow_unref); g_clear_pointer (&priv->shadow_shape, meta_window_shape_unref); - if (!meta_is_wayland_compositor () && priv->damage != None) - { - display = meta_screen_get_display (screen); - xdisplay = meta_display_get_xdisplay (display); - - meta_error_trap_push (display); - XDamageDestroy (xdisplay, priv->damage); - meta_error_trap_pop (display); - - priv->damage = None; - } - info->windows = g_list_remove (info->windows, (gconstpointer) self); g_clear_object (&priv->window); @@ -825,13 +776,6 @@ meta_window_actor_is_destroyed (MetaWindowActor *self) return self->priv->disposed; } -static void -meta_window_actor_freeze (MetaWindowActor *self) -{ - if (!meta_is_wayland_compositor ()) - self->priv->freeze_count++; -} - static gboolean send_frame_messages_timeout (gpointer data) { @@ -886,55 +830,6 @@ queue_send_frame_messages_timeout (MetaWindowActor *self) priv->send_frame_messages_timer = g_timeout_add_full (META_PRIORITY_REDRAW, offset, send_frame_messages_timeout, self, NULL); } -static void -meta_window_actor_damage_all (MetaWindowActor *self) -{ - MetaWindowActorPrivate *priv = self->priv; - gboolean redraw_queued; - - if (!priv->needs_damage_all) - return; - - if (priv->back_pixmap == None) - return; - - redraw_queued = meta_surface_actor_damage_all (priv->surface); - priv->repaint_scheduled = priv->repaint_scheduled || redraw_queued; - priv->needs_damage_all = FALSE; -} - -static void -meta_window_actor_thaw (MetaWindowActor *self) -{ - if (!meta_is_wayland_compositor ()) - { - self->priv->freeze_count--; - - if (G_UNLIKELY (self->priv->freeze_count < 0)) - { - g_warning ("Error in freeze/thaw accounting."); - self->priv->freeze_count = 0; - return; - } - - if (self->priv->freeze_count) - return; - - /* We sometimes ignore moves and resizes on frozen windows */ - meta_window_actor_sync_actor_geometry (self, FALSE); - - /* We do this now since we might be going right back into the - * frozen state */ - meta_window_actor_handle_updates (self); - - /* Since we ignore damage events while a window is frozen for certain effects - * we may need to issue an update_area() covering the whole pixmap if we - * don't know what real damage has happened. */ - if (self->priv->needs_damage_all) - meta_window_actor_damage_all (self); - } -} - void meta_window_actor_queue_frame_drawn (MetaWindowActor *self, gboolean no_delay_frame) @@ -989,12 +884,6 @@ meta_window_actor_effect_in_progress (MetaWindowActor *self) self->priv->destroy_in_progress); } -static gboolean -is_frozen (MetaWindowActor *self) -{ - return self->priv->freeze_count ? TRUE : FALSE; -} - static gboolean is_freeze_thaw_effect (gulong event) { @@ -1075,12 +964,6 @@ meta_window_actor_after_effects (MetaWindowActor *self) meta_window_actor_sync_visibility (self); meta_window_actor_sync_actor_geometry (self, FALSE); - - if (!meta_is_wayland_compositor ()) - { - if (priv->back_pixmap == None) - clutter_actor_queue_redraw (CLUTTER_ACTOR (priv->surface)); - } } void @@ -1155,93 +1038,19 @@ meta_window_actor_effect_completed (MetaWindowActor *self, meta_window_actor_after_effects (self); } -/* Called to drop our reference to a window backing pixmap that we - * previously obtained with XCompositeNameWindowPixmap. We do this - * when the window is unmapped or when we want to update to a new - * pixmap for a new size. - */ -static void -meta_window_actor_detach_x11_pixmap (MetaWindowActor *self) -{ - MetaWindowActorPrivate *priv = self->priv; - MetaScreen *screen = priv->screen; - MetaDisplay *display = meta_screen_get_display (screen); - Display *xdisplay = meta_display_get_xdisplay (display); - - if (!priv->back_pixmap) - return; - - /* Get rid of all references to the pixmap before freeing it; it's unclear whether - * you are supposed to be able to free a GLXPixmap after freeing the underlying - * pixmap, but it certainly doesn't work with current DRI/Mesa - */ - meta_surface_actor_set_texture (priv->surface, NULL); - cogl_flush(); - - XFreePixmap (xdisplay, priv->back_pixmap); - priv->back_pixmap = None; -} - gboolean meta_window_actor_should_unredirect (MetaWindowActor *self) { - MetaWindow *metaWindow = meta_window_actor_get_meta_window (self); MetaWindowActorPrivate *priv = self->priv; - - if (meta_is_wayland_compositor ()) - return FALSE; - - if (meta_window_requested_dont_bypass_compositor (metaWindow)) - return FALSE; - - if (metaWindow->opacity != 0xFF) - return FALSE; - - if (metaWindow->shape_region != NULL) - return FALSE; - - if (priv->argb32 && !meta_window_requested_bypass_compositor (metaWindow)) - return FALSE; - - if (!meta_window_is_monitor_sized (metaWindow)) - return FALSE; - - if (meta_window_requested_bypass_compositor (metaWindow)) - return TRUE; - - if (meta_window_is_override_redirect (metaWindow)) - return TRUE; - - if (priv->does_full_damage) - return TRUE; - - return FALSE; + return meta_surface_actor_should_unredirect (priv->surface); } void meta_window_actor_set_unredirected (MetaWindowActor *self, gboolean unredirected) { - MetaWindow *metaWindow = meta_window_actor_get_meta_window (self); - MetaDisplay *display = meta_window_get_display (metaWindow); - - Display *xdisplay = meta_display_get_xdisplay (display); - Window xwin = meta_window_get_toplevel_xwindow (metaWindow); - - meta_error_trap_push (display); - - if (unredirected) - { - XCompositeUnredirectWindow (xdisplay, xwin, CompositeRedirectManual); - } - else - { - XCompositeRedirectWindow (xdisplay, xwin, CompositeRedirectManual); - meta_window_actor_detach_x11_pixmap (self); - } - - self->priv->unredirected = unredirected; - meta_error_trap_pop (display); + MetaWindowActorPrivate *priv = self->priv; + meta_surface_actor_set_unredirected (priv->surface, unredirected); } void @@ -1301,19 +1110,11 @@ meta_window_actor_sync_actor_geometry (MetaWindowActor *self, meta_window_get_input_rect (priv->window, &window_rect); - /* When running as a display server we catch size changes when new - buffers are attached */ - if (!meta_is_wayland_compositor ()) - { - if (priv->last_width != window_rect.width || - priv->last_height != window_rect.height) - { - priv->x11_size_changed = TRUE; - - priv->last_width = window_rect.width; - priv->last_height = window_rect.height; - } - } + /* When running as a Wayland compositor we catch size changes when new + * buffers are attached */ + if (META_IS_SURFACE_ACTOR_X11 (priv->surface)) + meta_surface_actor_x11_set_size (META_SURFACE_ACTOR_X11 (priv->surface), + window_rect.width, window_rect.height); /* Normally we want freezing a window to also freeze its position; this allows * windows to atomically move and resize together, either under app control, @@ -1325,15 +1126,6 @@ meta_window_actor_sync_actor_geometry (MetaWindowActor *self, if (is_frozen (self) && !did_placement) return; - if (!meta_is_wayland_compositor ()) - { - if (priv->x11_size_changed) - { - meta_window_actor_detach_x11_pixmap (self); - meta_window_actor_update_shape (self); - } - } - if (meta_window_actor_effect_in_progress (self)) return; @@ -1500,20 +1292,13 @@ meta_window_actor_new (MetaWindow *window) priv = self->priv; - if (!meta_is_wayland_compositor ()) - { - priv->last_width = -1; - priv->last_height = -1; + meta_window_actor_set_updates_frozen (self, meta_window_updates_are_frozen (priv->window)); - meta_window_actor_set_updates_frozen (self, - meta_window_updates_are_frozen (priv->window)); - - /* If a window doesn't start off with updates frozen, we should - * we should send a _NET_WM_FRAME_DRAWN immediately after the first drawn. - */ - if (priv->window->extended_sync_request_counter && !priv->updates_frozen) - meta_window_actor_queue_frame_drawn (self, FALSE); - } + /* 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. + */ + if (priv->window->extended_sync_request_counter && !priv->updates_frozen) + meta_window_actor_queue_frame_drawn (self, FALSE); meta_window_actor_sync_actor_geometry (self, priv->window->placed); @@ -1622,13 +1407,6 @@ meta_window_actor_cull_out (MetaCullable *cullable, cairo_region_t *clip_region) { MetaWindowActor *self = META_WINDOW_ACTOR (cullable); - MetaWindowActorPrivate *priv = self->priv; - - meta_cullable_cull_out_children (cullable, unobscured_region, clip_region); - - /* Don't do any culling for the unredirected window */ - if (priv->unredirected) - return; meta_window_actor_set_clip_region_beneath (self, clip_region); } @@ -1651,64 +1429,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; - MetaDisplay *display = meta_screen_get_display (priv->screen); - Display *xdisplay = meta_display_get_xdisplay (display); - Window xwindow = meta_window_get_toplevel_xwindow (priv->window); - - /* This can happen while we're frozen. */ - 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); - } - - out: - meta_error_trap_pop (display); -} - static void check_needs_shadow (MetaWindowActor *self) { @@ -1776,61 +1496,12 @@ 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->back_pixmap == None) - 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; + meta_surface_actor_process_damage (priv->surface, + event->area.x, + event->area.y, + event->area.width, + event->area.height); } void @@ -2058,8 +1729,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; @@ -2079,7 +1751,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); @@ -2136,9 +1808,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)) { @@ -2147,45 +1816,13 @@ 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 (meta_surface_actor_is_unredirected (priv->surface)) + return; - if (priv->received_x11_damage) - { - meta_error_trap_push (display); - XDamageSubtract (xdisplay, priv->damage, None, None); - meta_error_trap_pop (display); + meta_surface_actor_pre_paint (priv->surface); - /* 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; - } - - check_needs_x11_pixmap (self); - } + if (!meta_surface_actor_is_visible (priv->surface)) + return; check_needs_reshape (self); check_needs_shadow (self); @@ -2374,20 +2011,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; + + updates_frozen = updates_frozen != FALSE; + + if (priv->updates_frozen != updates_frozen) { - MetaWindowActorPrivate *priv = self->priv; - - 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); - } + priv->updates_frozen = updates_frozen; + if (updates_frozen) + meta_window_actor_freeze (self); + else + meta_window_actor_thaw (self); } } diff --git a/src/core/display.c b/src/core/display.c index 907f1a597..d3a03bd77 100644 --- a/src/core/display.c +++ b/src/core/display.c @@ -73,6 +73,7 @@ #include #include "meta-xwayland-private.h" +#include "meta-surface-actor-wayland.h" #define GRAB_OP_IS_WINDOW_SWITCH(g) \ (g == META_GRAB_OP_KEYBOARD_TABBING_NORMAL || \ @@ -1682,9 +1683,9 @@ get_window_for_event (MetaDisplay *display, return display->grab_window; source = clutter_event_get_source (event); - if (META_IS_SURFACE_ACTOR (source)) + if (META_IS_SURFACE_ACTOR_WAYLAND (source)) { - MetaWaylandSurface *surface = meta_surface_actor_get_surface (META_SURFACE_ACTOR (source)); + MetaWaylandSurface *surface = meta_surface_actor_wayland_get_surface (META_SURFACE_ACTOR_WAYLAND (source)); g_assert (surface != NULL); return surface->window; } diff --git a/src/wayland/meta-wayland-seat.c b/src/wayland/meta-wayland-seat.c index df8e7814f..d73072925 100644 --- a/src/wayland/meta-wayland-seat.c +++ b/src/wayland/meta-wayland-seat.c @@ -38,6 +38,7 @@ #include "meta-shaped-texture-private.h" #include "meta-wayland-stage.h" #include "meta-cursor-tracker-private.h" +#include "meta-surface-actor-wayland.h" #define DEFAULT_AXIS_STEP_DISTANCE wl_fixed_from_int (10) @@ -420,8 +421,8 @@ meta_wayland_seat_repick (MetaWaylandSeat *seat, else seat->current_stage = NULL; - if (META_IS_SURFACE_ACTOR (actor)) - surface = meta_surface_actor_get_surface (META_SURFACE_ACTOR (actor)); + if (META_IS_SURFACE_ACTOR_WAYLAND (actor)) + surface = meta_surface_actor_wayland_get_surface (META_SURFACE_ACTOR_WAYLAND (actor)); pointer->current = surface; if (surface != pointer->focus_surface) diff --git a/src/wayland/meta-wayland-surface.c b/src/wayland/meta-wayland-surface.c index 7d9257367..0783316fe 100644 --- a/src/wayland/meta-wayland-surface.c +++ b/src/wayland/meta-wayland-surface.c @@ -44,11 +44,11 @@ #include "meta-wayland-private.h" #include "meta-xwayland-private.h" #include "meta-wayland-stage.h" -#include "meta-surface-actor.h" #include "meta-wayland-seat.h" #include "meta-wayland-keyboard.h" #include "meta-wayland-pointer.h" #include "meta-wayland-data-device.h" + #include "meta-cursor-tracker-private.h" #include "display-private.h" #include "window-private.h" @@ -58,6 +58,9 @@ #include "meta-idle-monitor-private.h" #include "monitor-private.h" +#include "meta-surface-actor.h" +#include "meta-surface-actor-wayland.h" + typedef enum { META_WAYLAND_SUBSURFACE_PLACEMENT_ABOVE, @@ -114,8 +117,8 @@ surface_process_damage (MetaWaylandSurface *surface, { cairo_rectangle_int_t rect; cairo_region_get_rectangle (region, i, &rect); - meta_surface_actor_damage_area (surface->surface_actor, - rect.x, rect.y, rect.width, rect.height); + meta_surface_actor_process_damage (surface->surface_actor, + rect.x, rect.y, rect.width, rect.height); } } @@ -295,7 +298,7 @@ actor_surface_commit (MetaWaylandSurface *surface, if (buffer_changed) { ensure_buffer_texture (buffer); - meta_surface_actor_attach_wayland_buffer (surface_actor, buffer); + meta_surface_actor_wayland_set_buffer (META_SURFACE_ACTOR_WAYLAND (surface->surface_actor), buffer); } surface_process_damage (surface, pending->damage); @@ -645,7 +648,7 @@ meta_wayland_surface_create (MetaWaylandCompositor *compositor, wl_resource_set_implementation (surface->resource, &meta_wayland_surface_interface, surface, wl_surface_destructor); surface->buffer_destroy_listener.notify = surface_handle_buffer_destroy; - surface->surface_actor = g_object_ref_sink (meta_surface_actor_new (surface)); + surface->surface_actor = g_object_ref_sink (meta_surface_actor_wayland_new (surface)); clutter_actor_set_reactive (CLUTTER_ACTOR (surface->surface_actor), TRUE); double_buffered_state_init (&surface->pending);