surface content

This commit is contained in:
Jasper St. Pierre 2013-12-09 16:01:07 -05:00
parent 7ea537fad7
commit e6391c2896
9 changed files with 1029 additions and 577 deletions

View File

@ -83,6 +83,10 @@ libmutter_wayland_la_SOURCES = \
compositor/meta-shaped-texture-private.h \ compositor/meta-shaped-texture-private.h \
compositor/meta-surface-actor.c \ compositor/meta-surface-actor.c \
compositor/meta-surface-actor.h \ 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.c \
compositor/meta-texture-rectangle.h \ compositor/meta-texture-rectangle.h \
compositor/meta-texture-tower.c \ compositor/meta-texture-tower.c \

View File

@ -0,0 +1,159 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2013 Red Hat
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Written by:
* Jasper St. Pierre <jstpierre@mecheye.net>
*/
#include "config.h"
#include "meta-surface-actor-wayland.h"
#include <cogl/cogl-wayland-server.h>
#include "meta-shaped-texture-private.h"
struct _MetaSurfaceActorWaylandPrivate
{
MetaWaylandSurface *surface;
MetaWaylandBuffer *buffer;
};
typedef struct _MetaSurfaceActorWaylandPrivate MetaSurfaceActorWaylandPrivate;
G_DEFINE_TYPE_WITH_PRIVATE (MetaSurfaceActorWayland, meta_surface_actor_wayland, META_TYPE_SURFACE_ACTOR)
static void
meta_surface_actor_wayland_process_damage (MetaSurfaceActor *actor,
int x, int y, int width, int height)
{
MetaSurfaceActorWayland *self = META_SURFACE_ACTOR_WAYLAND (actor);
MetaSurfaceActorWaylandPrivate *priv = meta_surface_actor_wayland_get_instance_private (self);
struct wl_resource *resource = priv->buffer->resource;
struct wl_shm_buffer *shm_buffer = wl_shm_buffer_get (resource);
if (shm_buffer)
{
CoglTexture2D *texture = COGL_TEXTURE_2D (priv->buffer->texture);
cogl_wayland_texture_set_region_from_shm_buffer (texture, x, y, width, height, shm_buffer, x, y, 0, NULL);
}
meta_surface_actor_redraw_area (META_SURFACE_ACTOR (self), x, y, width, height);
}
static void
meta_surface_actor_wayland_pre_paint (MetaSurfaceActor *actor)
{
}
static gboolean
meta_surface_actor_wayland_is_argb32 (MetaSurfaceActor *actor)
{
/* TODO: look at the SHM buffer pixel format */
return TRUE;
}
static gboolean
meta_surface_actor_wayland_is_visible (MetaSurfaceActor *actor)
{
/* TODO: ensure that the buffer isn't NULL, implement
* wayland mapping semantics */
return TRUE;
}
static void
meta_surface_actor_wayland_freeze (MetaSurfaceActor *actor)
{
}
static void
meta_surface_actor_wayland_thaw (MetaSurfaceActor *actor)
{
}
static gboolean
meta_surface_actor_wayland_is_frozen (MetaSurfaceActor *actor)
{
return FALSE;
}
static gboolean
meta_surface_actor_wayland_should_unredirect (MetaSurfaceActor *actor)
{
return FALSE;
}
static void
meta_surface_actor_wayland_set_unredirected (MetaSurfaceActor *actor,
gboolean unredirected)
{
/* Do nothing. In the future, we'll use KMS to set this
* up as a hardware overlay or something. */
}
static void
meta_surface_actor_wayland_class_init (MetaSurfaceActorWaylandClass *klass)
{
MetaSurfaceActorClass *surface_actor_class = META_SURFACE_ACTOR_CLASS (klass);
surface_actor_class->process_damage = meta_surface_actor_wayland_process_damage;
surface_actor_class->pre_paint = meta_surface_actor_wayland_pre_paint;
surface_actor_class->is_argb32 = meta_surface_actor_wayland_is_argb32;
surface_actor_class->is_visible = meta_surface_actor_wayland_is_visible;
surface_actor_class->freeze = meta_surface_actor_wayland_freeze;
surface_actor_class->thaw = meta_surface_actor_wayland_thaw;
surface_actor_class->is_frozen = meta_surface_actor_wayland_is_frozen;
surface_actor_class->should_unredirect = meta_surface_actor_wayland_should_unredirect;
surface_actor_class->set_unredirected = meta_surface_actor_wayland_set_unredirected;
}
static void
meta_surface_actor_wayland_init (MetaSurfaceActorWayland *self)
{
}
MetaSurfaceActor *
meta_surface_actor_wayland_new (MetaWaylandSurface *surface)
{
MetaSurfaceActorWayland *self = g_object_new (META_TYPE_SURFACE_ACTOR_WAYLAND, NULL);
MetaSurfaceActorWaylandPrivate *priv = meta_surface_actor_wayland_get_instance_private (self);
g_assert (meta_is_wayland_compositor ());
priv->surface = surface;
return META_SURFACE_ACTOR (self);
}
void
meta_surface_actor_wayland_set_buffer (MetaSurfaceActorWayland *self,
MetaWaylandBuffer *buffer)
{
MetaSurfaceActorWaylandPrivate *priv = meta_surface_actor_wayland_get_instance_private (self);
MetaShapedTexture *stex = meta_surface_actor_get_texture (META_SURFACE_ACTOR (self));
priv->buffer = buffer;
if (buffer)
meta_shaped_texture_set_texture (stex, buffer->texture);
else
meta_shaped_texture_set_texture (stex, NULL);
}

View File

@ -0,0 +1,65 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2013 Red Hat
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Written by:
* Jasper St. Pierre <jstpierre@mecheye.net>
*/
#ifndef __META_SURFACE_ACTOR_WAYLAND_H__
#define __META_SURFACE_ACTOR_WAYLAND_H__
#include <glib-object.h>
#include "meta-surface-actor.h"
#include "meta-wayland-private.h"
G_BEGIN_DECLS
#define META_TYPE_SURFACE_ACTOR_WAYLAND (meta_surface_actor_wayland_get_type ())
#define META_SURFACE_ACTOR_WAYLAND(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_SURFACE_ACTOR_WAYLAND, MetaSurfaceActorWayland))
#define META_SURFACE_ACTOR_WAYLAND_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_SURFACE_ACTOR_WAYLAND, MetaSurfaceActorWaylandClass))
#define META_IS_SURFACE_ACTOR_WAYLAND(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_SURFACE_ACTOR_WAYLAND))
#define META_IS_SURFACE_ACTOR_WAYLAND_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_SURFACE_ACTOR_WAYLAND))
#define META_SURFACE_ACTOR_WAYLAND_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_SURFACE_ACTOR_WAYLAND, MetaSurfaceActorWaylandClass))
typedef struct _MetaSurfaceActorWayland MetaSurfaceActorWayland;
typedef struct _MetaSurfaceActorWaylandClass MetaSurfaceActorWaylandClass;
struct _MetaSurfaceActorWayland
{
MetaSurfaceActor parent;
};
struct _MetaSurfaceActorWaylandClass
{
MetaSurfaceActorClass parent_class;
};
GType meta_surface_actor_wayland_get_type (void);
MetaSurfaceActor * meta_surface_actor_wayland_new (MetaWaylandSurface *surface);
void meta_surface_actor_wayland_set_buffer (MetaSurfaceActorWayland *self,
MetaWaylandBuffer *buffer);
G_END_DECLS
#endif /* __META_SURFACE_ACTOR_WAYLAND_H__ */

View File

@ -0,0 +1,551 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2013 Red Hat
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Written by:
* Owen Taylor <otaylor@redhat.com>
* Jasper St. Pierre <jstpierre@mecheye.net>
*/
#include "config.h"
#include "meta-surface-actor-x11.h"
#include <X11/extensions/Xcomposite.h>
#include <X11/extensions/Xrender.h>
#include <cogl/cogl-texture-pixmap-x11.h>
#include <meta/errors.h>
#include "window-private.h"
#include "meta-shaped-texture-private.h"
#include "meta-cullable.h"
struct _MetaSurfaceActorX11Private
{
MetaWindow *window;
MetaDisplay *display;
CoglTexture *texture;
Pixmap pixmap;
Damage damage;
int last_width;
int last_height;
/* Freeze/thaw accounting */
guint freeze_count;
/* This is used to detect fullscreen windows that need to be unredirected */
guint full_damage_frames_count;
guint does_full_damage : 1;
/* Other state... */
guint argb32 : 1;
guint received_damage : 1;
guint size_changed : 1;
guint needs_damage_all : 1;
guint unredirected : 1;
};
typedef struct _MetaSurfaceActorX11Private MetaSurfaceActorX11Private;
static void cullable_iface_init (MetaCullableInterface *iface);
G_DEFINE_TYPE_WITH_CODE (MetaSurfaceActorX11, meta_surface_actor_x11, META_TYPE_SURFACE_ACTOR,
G_IMPLEMENT_INTERFACE (META_TYPE_CULLABLE, cullable_iface_init)
G_ADD_PRIVATE (MetaSurfaceActorX11))
static MetaCullableInterface *parent_cullable_iface;
static void
meta_surface_actor_x11_cull_out (MetaCullable *cullable,
cairo_region_t *unobscured_region,
cairo_region_t *clip_region)
{
MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (cullable);
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
/* Don't do any culling for the unredirected window */
if (priv->unredirected)
return;
parent_cullable_iface->cull_out (cullable, unobscured_region, clip_region);
}
static void
cullable_iface_init (MetaCullableInterface *iface)
{
parent_cullable_iface = g_type_interface_peek_parent (iface);
iface->cull_out = meta_surface_actor_x11_cull_out;
}
static void
free_damage (MetaSurfaceActorX11 *self)
{
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
MetaDisplay *display = priv->display;
Display *xdisplay = meta_display_get_xdisplay (display);
if (priv->damage == None)
return;
meta_error_trap_push (display);
XDamageDestroy (xdisplay, priv->damage);
priv->damage = None;
meta_error_trap_pop (display);
}
static void
detach_pixmap (MetaSurfaceActorX11 *self)
{
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
MetaDisplay *display = priv->display;
Display *xdisplay = meta_display_get_xdisplay (display);
MetaShapedTexture *stex = meta_surface_actor_get_texture (META_SURFACE_ACTOR (self));
if (priv->pixmap == None)
return;
meta_error_trap_push (display);
XFreePixmap (xdisplay, priv->pixmap);
priv->pixmap = None;
meta_error_trap_pop (display);
meta_shaped_texture_set_texture (stex, NULL);
cogl_object_unref (priv->texture);
priv->texture = NULL;
}
static void
set_pixmap (MetaSurfaceActorX11 *self,
Pixmap pixmap)
{
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
CoglContext *ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
MetaShapedTexture *stex = meta_surface_actor_get_texture (META_SURFACE_ACTOR (self));
CoglTexture *texture;
g_assert (priv->pixmap == None);
priv->pixmap = pixmap;
texture = COGL_TEXTURE (cogl_texture_pixmap_x11_new (ctx, priv->pixmap, FALSE, NULL));
if (G_UNLIKELY (!cogl_texture_pixmap_x11_is_using_tfp_extension (COGL_TEXTURE_PIXMAP_X11 (texture))))
g_warning ("NOTE: Not using GLX TFP!\n");
priv->texture = texture;
meta_shaped_texture_set_texture (stex, texture);
}
static void
update_pixmap (MetaSurfaceActorX11 *self)
{
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
MetaDisplay *display = priv->display;
Display *xdisplay = meta_display_get_xdisplay (display);
if (priv->size_changed)
{
detach_pixmap (self);
priv->size_changed = FALSE;
}
if (priv->pixmap == None)
{
Pixmap new_pixmap;
Window xwindow = meta_window_get_toplevel_xwindow (priv->window);
meta_error_trap_push (display);
new_pixmap = XCompositeNameWindowPixmap (xdisplay, xwindow);
if (meta_error_trap_pop_with_return (display) != Success)
{
/* Probably a BadMatch if the window isn't viewable; we could
* GrabServer/GetWindowAttributes/NameWindowPixmap/UngrabServer/Sync
* to avoid this, but there's no reason to take two round trips
* when one will do. (We need that Sync if we want to handle failures
* for any reason other than !viewable. That's unlikely, but maybe
* we'll BadAlloc or something.)
*/
new_pixmap = None;
}
if (new_pixmap == None)
{
meta_verbose ("Unable to get named pixmap for %s\n",
meta_window_get_description (priv->window));
return;
}
set_pixmap (self, new_pixmap);
}
}
static gboolean
is_frozen (MetaSurfaceActorX11 *self)
{
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
return (priv->freeze_count > 0);
}
static gboolean
is_visible (MetaSurfaceActorX11 *self)
{
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
return (priv->pixmap != None) && !priv->unredirected;
}
static void
damage_area (MetaSurfaceActorX11 *self,
int x, int y, int width, int height)
{
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
if (!is_visible (self))
return;
cogl_texture_pixmap_x11_update_area (priv->texture, x, y, width, height);
meta_surface_actor_redraw_area (META_SURFACE_ACTOR (self), x, y, width, height);
}
static void
damage_all (MetaSurfaceActorX11 *self)
{
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
if (!is_visible (self))
return;
damage_area (self, 0, 0, cogl_texture_get_width (priv->texture), cogl_texture_get_height (priv->texture));
}
static void
meta_surface_actor_x11_process_damage (MetaSurfaceActor *actor,
int x, int y, int width, int height)
{
MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (actor);
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
priv->received_damage = TRUE;
if (!priv->unredirected && !priv->does_full_damage)
{
MetaRectangle window_rect;
meta_window_get_frame_rect (priv->window, &window_rect);
if (window_rect.x == x &&
window_rect.y == y &&
window_rect.width == width &&
window_rect.height == height)
priv->full_damage_frames_count++;
else
priv->full_damage_frames_count = 0;
if (priv->full_damage_frames_count >= 100)
priv->does_full_damage = TRUE;
}
if (is_frozen (self))
{
/* The window is frozen due to an effect in progress: we ignore damage
* here on the off chance that this will stop the corresponding
* texture_from_pixmap from being update.
*
* needs_damage_all tracks that some unknown damage happened while the
* window was frozen so that when the window becomes unfrozen we can
* issue a full window update to cover any lost damage.
*
* It should be noted that this is an unreliable mechanism since it's
* quite likely that drivers will aim to provide a zero-copy
* implementation of the texture_from_pixmap extension and in those cases
* any drawing done to the window is always immediately reflected in the
* texture regardless of damage event handling.
*/
priv->needs_damage_all = TRUE;
return;
}
damage_area (self, x, y, width, height);
}
static void
meta_surface_actor_x11_pre_paint (MetaSurfaceActor *actor)
{
MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (actor);
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
MetaDisplay *display = priv->display;
Display *xdisplay = meta_display_get_xdisplay (display);
if (is_frozen (self))
return;
if (priv->received_damage)
{
meta_error_trap_push (display);
XDamageSubtract (xdisplay, priv->damage, None, None);
meta_error_trap_pop (display);
/* We need to make sure that any X drawing that happens before the
* XDamageSubtract() above is visible to subsequent GL rendering;
* the only standardized way to do this is EXT_x11_sync_object,
* which isn't yet widely available. For now, we count on details
* of Xorg and the open source drivers, and hope for the best
* otherwise.
*
* Xorg and open source driver specifics:
*
* The X server makes sure to flush drawing to the kernel before
* sending out damage events, but since we use DamageReportBoundingBox
* there may be drawing between the last damage event and the
* XDamageSubtract() that needs to be flushed as well.
*
* Xorg always makes sure that drawing is flushed to the kernel
* before writing events or responses to the client, so any round trip
* request at this point is sufficient to flush the GLX buffers.
*/
XSync (xdisplay, False);
priv->received_damage = FALSE;
}
update_pixmap (self);
}
static void
meta_surface_actor_x11_freeze (MetaSurfaceActor *actor)
{
MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (actor);
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
priv->freeze_count ++;
}
static void
meta_surface_actor_x11_thaw (MetaSurfaceActor *actor)
{
MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (actor);
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
if (priv->freeze_count == 0)
{
g_critical ("Error in freeze/thaw accounting.");
return;
}
priv->freeze_count --;
/* Since we ignore damage events while a window is frozen for certain effects
* we may need to issue an update_area() covering the whole pixmap if we
* don't know what real damage has happened. */
if (priv->needs_damage_all)
{
damage_all (self);
priv->needs_damage_all = FALSE;
}
}
static gboolean
meta_surface_actor_x11_is_frozen (MetaSurfaceActor *actor)
{
MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (actor);
return is_frozen (self);
}
static void
update_is_argb32 (MetaSurfaceActorX11 *self)
{
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
MetaDisplay *display = priv->display;
Display *xdisplay = meta_display_get_xdisplay (display);
XRenderPictFormat *format;
format = XRenderFindVisualFormat (xdisplay, priv->window->xvisual);
priv->argb32 = (format && format->type == PictTypeDirect && format->direct.alphaMask);
}
static gboolean
meta_surface_actor_x11_is_argb32 (MetaSurfaceActor *actor)
{
MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (actor);
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
return priv->argb32;
}
static gboolean
meta_surface_actor_x11_is_visible (MetaSurfaceActor *actor)
{
MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (actor);
return is_visible (self);
}
static gboolean
meta_surface_actor_x11_should_unredirect (MetaSurfaceActor *actor)
{
MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (actor);
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
MetaWindow *window = priv->window;
if (meta_window_requested_dont_bypass_compositor (window))
return FALSE;
if (window->opacity != 0xFF)
return FALSE;
if (window->shape_region != NULL)
return FALSE;
if (priv->argb32 && !meta_window_requested_bypass_compositor (window))
return FALSE;
if (!meta_window_is_monitor_sized (window))
return FALSE;
if (meta_window_requested_bypass_compositor (window))
return TRUE;
if (meta_window_is_override_redirect (window))
return TRUE;
if (priv->does_full_damage)
return TRUE;
return FALSE;
}
static void
sync_unredirected (MetaSurfaceActorX11 *self)
{
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
MetaDisplay *display = priv->display;
Display *xdisplay = meta_display_get_xdisplay (display);
Window xwindow = meta_window_get_toplevel_xwindow (priv->window);
meta_error_trap_push (display);
if (priv->unredirected)
{
detach_pixmap (self);
XCompositeUnredirectWindow (xdisplay, xwindow, CompositeRedirectManual);
}
else
{
XCompositeRedirectWindow (xdisplay, xwindow, CompositeRedirectManual);
}
meta_error_trap_pop (display);
}
static void
meta_surface_actor_x11_set_unredirected (MetaSurfaceActor *actor,
gboolean unredirected)
{
MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (actor);
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
if (priv->unredirected == unredirected)
return;
priv->unredirected = unredirected;
sync_unredirected (self);
}
static void
meta_surface_actor_x11_dispose (GObject *object)
{
MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (object);
detach_pixmap (self);
free_damage (self);
G_OBJECT_CLASS (meta_surface_actor_x11_parent_class)->dispose (object);
}
static void
meta_surface_actor_x11_class_init (MetaSurfaceActorX11Class *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
MetaSurfaceActorClass *surface_actor_class = META_SURFACE_ACTOR_CLASS (klass);
object_class->dispose = meta_surface_actor_x11_dispose;
surface_actor_class->process_damage = meta_surface_actor_x11_process_damage;
surface_actor_class->pre_paint = meta_surface_actor_x11_pre_paint;
surface_actor_class->is_argb32 = meta_surface_actor_x11_is_argb32;
surface_actor_class->is_visible = meta_surface_actor_x11_is_visible;
surface_actor_class->freeze = meta_surface_actor_x11_freeze;
surface_actor_class->thaw = meta_surface_actor_x11_thaw;
surface_actor_class->is_frozen = meta_surface_actor_x11_is_frozen;
surface_actor_class->should_unredirect = meta_surface_actor_x11_should_unredirect;
surface_actor_class->set_unredirected = meta_surface_actor_x11_set_unredirected;
}
static void
meta_surface_actor_x11_init (MetaSurfaceActorX11 *self)
{
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
priv->last_width = -1;
priv->last_height = -1;
}
MetaSurfaceActor *
meta_surface_actor_x11_new (MetaWindow *window)
{
MetaSurfaceActorX11 *self = g_object_new (META_TYPE_SURFACE_ACTOR_X11, NULL);
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
MetaDisplay *display = meta_window_get_display (window);
Display *xdisplay = meta_display_get_xdisplay (display);
Window xwindow = meta_window_get_toplevel_xwindow (window);
g_assert (!meta_is_wayland_compositor ());
priv->window = window;
priv->display = display;
priv->damage = XDamageCreate (xdisplay, xwindow, XDamageReportBoundingBox);
update_is_argb32 (self);
priv->unredirected = FALSE;
sync_unredirected (self);
return META_SURFACE_ACTOR (self);
}
void
meta_surface_actor_x11_set_size (MetaSurfaceActorX11 *self,
int width, int height)
{
MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
if (priv->last_width == width &&
priv->last_height == height)
return;
priv->size_changed = TRUE;
priv->last_width = width;
priv->last_height = height;
}

View File

@ -0,0 +1,69 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2013 Red Hat
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Written by:
* Owen Taylor <otaylor@redhat.com>
* Jasper St. Pierre <jstpierre@mecheye.net>
*/
#ifndef __META_SURFACE_ACTOR_X11_H__
#define __META_SURFACE_ACTOR_X11_H__
#include <glib-object.h>
#include "meta-surface-actor.h"
#include <X11/extensions/Xdamage.h>
#include <meta/display.h>
#include <meta/window.h>
G_BEGIN_DECLS
#define META_TYPE_SURFACE_ACTOR_X11 (meta_surface_actor_x11_get_type ())
#define META_SURFACE_ACTOR_X11(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_SURFACE_ACTOR_X11, MetaSurfaceActorX11))
#define META_SURFACE_ACTOR_X11_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_SURFACE_ACTOR_X11, MetaSurfaceActorX11Class))
#define META_IS_SURFACE_ACTOR_X11(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_SURFACE_ACTOR_X11))
#define META_IS_SURFACE_ACTOR_X11_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_SURFACE_ACTOR_X11))
#define META_SURFACE_ACTOR_X11_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_SURFACE_ACTOR_X11, MetaSurfaceActorX11Class))
typedef struct _MetaSurfaceActorX11 MetaSurfaceActorX11;
typedef struct _MetaSurfaceActorX11Class MetaSurfaceActorX11Class;
struct _MetaSurfaceActorX11
{
MetaSurfaceActor parent;
};
struct _MetaSurfaceActorX11Class
{
MetaSurfaceActorClass parent_class;
};
GType meta_surface_actor_x11_get_type (void);
MetaSurfaceActor * meta_surface_actor_x11_new (MetaWindow *window);
void meta_surface_actor_x11_set_size (MetaSurfaceActorX11 *self,
int width, int height);
G_END_DECLS
#endif /* __META_SURFACE_ACTOR_X11_H__ */

View File

@ -10,20 +10,18 @@
*/ */
#include <config.h> #include <config.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-surface-actor.h"
#include <clutter/clutter.h>
#include <meta/meta-shaped-texture.h>
#include "meta-wayland-private.h" #include "meta-wayland-private.h"
#include "meta-cullable.h" #include "meta-cullable.h"
#include "meta-shaped-texture-private.h" #include "meta-shaped-texture-private.h"
struct _MetaSurfaceActorPrivate struct _MetaSurfaceActorPrivate
{ {
MetaShapedTexture *texture; MetaShapedTexture *texture;
MetaWaylandBuffer *buffer;
/* The region that is visible, used to optimize out redraws */ /* The region that is visible, used to optimize out redraws */
cairo_region_t *unobscured_region; cairo_region_t *unobscured_region;
@ -31,8 +29,8 @@ struct _MetaSurfaceActorPrivate
static void cullable_iface_init (MetaCullableInterface *iface); static void cullable_iface_init (MetaCullableInterface *iface);
G_DEFINE_TYPE_WITH_CODE (MetaSurfaceActor, meta_surface_actor, CLUTTER_TYPE_ACTOR, G_DEFINE_ABSTRACT_TYPE_WITH_CODE (MetaSurfaceActor, meta_surface_actor, CLUTTER_TYPE_ACTOR,
G_IMPLEMENT_INTERFACE (META_TYPE_CULLABLE, cullable_iface_init)); G_IMPLEMENT_INTERFACE (META_TYPE_CULLABLE, cullable_iface_init));
static gboolean static gboolean
meta_surface_actor_get_paint_volume (ClutterActor *actor, meta_surface_actor_get_paint_volume (ClutterActor *actor,
@ -160,30 +158,6 @@ meta_surface_actor_get_texture (MetaSurfaceActor *self)
return self->priv->texture; 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 * static cairo_region_t *
effective_unobscured_region (MetaSurfaceActor *self) effective_unobscured_region (MetaSurfaceActor *self)
{ {
@ -193,29 +167,11 @@ effective_unobscured_region (MetaSurfaceActor *self)
} }
gboolean gboolean
meta_surface_actor_damage_all (MetaSurfaceActor *self) meta_surface_actor_redraw_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),
effective_unobscured_region (self));
}
gboolean
meta_surface_actor_damage_area (MetaSurfaceActor *self,
int x,
int y,
int width,
int height)
{ {
MetaSurfaceActorPrivate *priv = self->priv; MetaSurfaceActorPrivate *priv = self->priv;
update_area (self, x, y, width, height);
return meta_shaped_texture_update_area (priv->texture, return meta_shaped_texture_update_area (priv->texture,
x, y, width, height, x, y, width, height,
effective_unobscured_region (self)); effective_unobscured_region (self));
@ -232,27 +188,6 @@ meta_surface_actor_is_obscured (MetaSurfaceActor *self)
return FALSE; return FALSE;
} }
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 void
meta_surface_actor_set_input_region (MetaSurfaceActor *self, meta_surface_actor_set_input_region (MetaSurfaceActor *self,
cairo_region_t *region) cairo_region_t *region)
@ -269,8 +204,58 @@ meta_surface_actor_set_opaque_region (MetaSurfaceActor *self,
meta_shaped_texture_set_opaque_region (priv->texture, region); meta_shaped_texture_set_opaque_region (priv->texture, region);
} }
MetaSurfaceActor * void
meta_surface_actor_new (void) meta_surface_actor_process_damage (MetaSurfaceActor *actor,
int x, int y, int width, int height)
{ {
return g_object_new (META_TYPE_SURFACE_ACTOR, NULL); META_SURFACE_ACTOR_GET_CLASS (actor)->process_damage (actor, x, y, width, height);
}
void
meta_surface_actor_pre_paint (MetaSurfaceActor *actor)
{
META_SURFACE_ACTOR_GET_CLASS (actor)->pre_paint (actor);
}
gboolean
meta_surface_actor_is_argb32 (MetaSurfaceActor *actor)
{
return META_SURFACE_ACTOR_GET_CLASS (actor)->is_argb32 (actor);
}
gboolean
meta_surface_actor_is_visible (MetaSurfaceActor *actor)
{
return META_SURFACE_ACTOR_GET_CLASS (actor)->is_visible (actor);
}
void
meta_surface_actor_freeze (MetaSurfaceActor *actor)
{
META_SURFACE_ACTOR_GET_CLASS (actor)->freeze (actor);
}
void
meta_surface_actor_thaw (MetaSurfaceActor *actor)
{
META_SURFACE_ACTOR_GET_CLASS (actor)->thaw (actor);
}
gboolean
meta_surface_actor_is_frozen (MetaSurfaceActor *actor)
{
return META_SURFACE_ACTOR_GET_CLASS (actor)->is_frozen (actor);
}
gboolean
meta_surface_actor_should_unredirect (MetaSurfaceActor *actor)
{
return META_SURFACE_ACTOR_GET_CLASS (actor)->should_unredirect (actor);
}
void
meta_surface_actor_set_unredirected (MetaSurfaceActor *actor,
gboolean unredirected)
{
META_SURFACE_ACTOR_GET_CLASS (actor)->set_unredirected (actor, unredirected);
} }

View File

@ -6,7 +6,6 @@
#include <config.h> #include <config.h>
#include <meta/meta-shaped-texture.h> #include <meta/meta-shaped-texture.h>
#include "meta-wayland-types.h"
G_BEGIN_DECLS G_BEGIN_DECLS
@ -25,6 +24,20 @@ struct _MetaSurfaceActorClass
{ {
/*< private >*/ /*< private >*/
ClutterActorClass parent_class; ClutterActorClass parent_class;
void (* process_damage) (MetaSurfaceActor *actor,
int x, int y, int width, int height);
void (* pre_paint) (MetaSurfaceActor *actor);
gboolean (* is_argb32) (MetaSurfaceActor *actor);
gboolean (* is_visible) (MetaSurfaceActor *actor);
void (* freeze) (MetaSurfaceActor *actor);
void (* thaw) (MetaSurfaceActor *actor);
gboolean (* is_frozen) (MetaSurfaceActor *actor);
gboolean (* should_unredirect) (MetaSurfaceActor *actor);
void (* set_unredirected) (MetaSurfaceActor *actor,
gboolean unredirected);
}; };
struct _MetaSurfaceActor struct _MetaSurfaceActor
@ -36,31 +49,35 @@ struct _MetaSurfaceActor
GType meta_surface_actor_get_type (void); GType meta_surface_actor_get_type (void);
MetaSurfaceActor *meta_surface_actor_new (void);
cairo_surface_t *meta_surface_actor_get_image (MetaSurfaceActor *self, cairo_surface_t *meta_surface_actor_get_image (MetaSurfaceActor *self,
cairo_rectangle_int_t *clip); cairo_rectangle_int_t *clip);
MetaShapedTexture *meta_surface_actor_get_texture (MetaSurfaceActor *self); 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_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, void meta_surface_actor_set_input_region (MetaSurfaceActor *self,
cairo_region_t *region); cairo_region_t *region);
void meta_surface_actor_set_opaque_region (MetaSurfaceActor *self, void meta_surface_actor_set_opaque_region (MetaSurfaceActor *self,
cairo_region_t *region); cairo_region_t *region);
gboolean meta_surface_actor_redraw_area (MetaSurfaceActor *actor,
int x, int y, int width, int height);
void meta_surface_actor_process_damage (MetaSurfaceActor *actor,
int x, int y, int width, int height);
void meta_surface_actor_pre_paint (MetaSurfaceActor *actor);
gboolean meta_surface_actor_is_argb32 (MetaSurfaceActor *actor);
gboolean meta_surface_actor_is_visible (MetaSurfaceActor *actor);
void meta_surface_actor_freeze (MetaSurfaceActor *actor);
void meta_surface_actor_thaw (MetaSurfaceActor *actor);
gboolean meta_surface_actor_is_frozen (MetaSurfaceActor *actor);
gboolean meta_surface_actor_should_unredirect (MetaSurfaceActor *actor);
void meta_surface_actor_set_unredirected (MetaSurfaceActor *actor,
gboolean unredirected);
G_END_DECLS G_END_DECLS
#endif /* META_SURFACE_ACTOR_PRIVATE_H */ #endif /* META_SURFACE_ACTOR_PRIVATE_H */

View File

@ -10,10 +10,6 @@
#include <math.h> #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 <clutter/x11/clutter-x11.h>
#include <cogl/cogl-texture-pixmap-x11.h> #include <cogl/cogl-texture-pixmap-x11.h>
#include <gdk/gdk.h> /* for gdk_rectangle_union() */ #include <gdk/gdk.h> /* for gdk_rectangle_union() */
@ -30,13 +26,15 @@
#include "meta-shaped-texture-private.h" #include "meta-shaped-texture-private.h"
#include "meta-shadow-factory-private.h" #include "meta-shadow-factory-private.h"
#include "meta-window-actor-private.h" #include "meta-window-actor-private.h"
#include "meta-surface-actor.h"
#include "meta-texture-rectangle.h" #include "meta-texture-rectangle.h"
#include "region-utils.h" #include "region-utils.h"
#include "meta-wayland-private.h" #include "meta-wayland-private.h"
#include "monitor-private.h" #include "monitor-private.h"
#include "meta-cullable.h" #include "meta-cullable.h"
#include "meta-surface-actor.h"
#include "meta-surface-actor-x11.h"
struct _MetaWindowActorPrivate struct _MetaWindowActorPrivate
{ {
MetaWindow *window; MetaWindow *window;
@ -63,19 +61,13 @@ struct _MetaWindowActorPrivate
/* The region we should clip to when painting the shadow */ /* The region we should clip to when painting the shadow */
cairo_region_t *shadow_clip; cairo_region_t *shadow_clip;
guint send_frame_messages_timer;
gint64 frame_drawn_time;
/* Extracted size-invariant shape used for shadows */ /* Extracted size-invariant shape used for shadows */
MetaWindowShape *shadow_shape; MetaWindowShape *shadow_shape;
gint last_width;
gint last_height;
gint freeze_count;
char * shadow_class; char * shadow_class;
guint send_frame_messages_timer;
gint64 frame_drawn_time;
/* /*
* These need to be counters rather than flags, since more plugins * These need to be counters rather than flags, since more plugins
* can implement same effect; the practicality of stacking effects * can implement same effect; the practicality of stacking effects
@ -90,11 +82,7 @@ struct _MetaWindowActorPrivate
/* List of FrameData for recent frames */ /* List of FrameData for recent frames */
GList *frames; GList *frames;
Pixmap back_pixmap; /* Not used in wayland compositor mode */
Damage damage; /* Not used in wayland compositor mode */
guint visible : 1; guint visible : 1;
guint argb32 : 1;
guint disposed : 1; guint disposed : 1;
guint redecorating : 1; guint redecorating : 1;
@ -111,24 +99,7 @@ struct _MetaWindowActorPrivate
guint no_shadow : 1; 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 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; typedef struct _FrameData FrameData;
@ -165,7 +136,6 @@ static gboolean meta_window_actor_get_paint_volume (ClutterActor *actor,
ClutterPaintVolume *volume); ClutterPaintVolume *volume);
static void meta_window_actor_detach_x11_pixmap (MetaWindowActor *self);
static gboolean meta_window_actor_has_shadow (MetaWindowActor *self); static gboolean meta_window_actor_has_shadow (MetaWindowActor *self);
static void meta_window_actor_handle_updates (MetaWindowActor *self); static void meta_window_actor_handle_updates (MetaWindowActor *self);
@ -256,9 +226,6 @@ window_decorated_notify (MetaWindow *mw,
{ {
MetaWindowActor *self = META_WINDOW_ACTOR (data); MetaWindowActor *self = META_WINDOW_ACTOR (data);
MetaWindowActorPrivate *priv = self->priv; 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 * Basically, we have to reconstruct the the internals of this object
@ -266,23 +233,6 @@ window_decorated_notify (MetaWindow *mw,
*/ */
priv->redecorating = TRUE; 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. * Recreate the contents.
*/ */
@ -307,13 +257,52 @@ surface_allocation_changed_notify (ClutterActor *actor,
meta_window_actor_update_shape (self); 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 static gboolean
is_non_opaque (MetaWindowActor *self) is_non_opaque (MetaWindowActor *self)
{ {
MetaWindowActorPrivate *priv = self->priv; MetaWindowActorPrivate *priv = self->priv;
MetaWindow *window = priv->window; 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 (meta_surface_actor_is_frozen (priv->surface))
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 static void
@ -322,38 +311,15 @@ meta_window_actor_constructed (GObject *object)
MetaWindowActor *self = META_WINDOW_ACTOR (object); MetaWindowActor *self = META_WINDOW_ACTOR (object);
MetaWindowActorPrivate *priv = self->priv; MetaWindowActorPrivate *priv = self->priv;
MetaWindow *window = priv->window; 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; priv->screen = window->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;
}
if (!priv->surface) if (!priv->surface)
{ {
if (window->surface) if (window->surface)
priv->surface = window->surface->surface_actor; priv->surface = window->surface->surface_actor;
else else
priv->surface = meta_surface_actor_new (); priv->surface = meta_surface_actor_x11_new (window);
g_object_ref_sink (priv->surface); g_object_ref_sink (priv->surface);
clutter_actor_add_child (CLUTTER_ACTOR (self), CLUTTER_ACTOR (priv->surface)); clutter_actor_add_child (CLUTTER_ACTOR (self), CLUTTER_ACTOR (priv->surface));
@ -376,8 +342,6 @@ meta_window_actor_dispose (GObject *object)
MetaWindowActor *self = META_WINDOW_ACTOR (object); MetaWindowActor *self = META_WINDOW_ACTOR (object);
MetaWindowActorPrivate *priv = self->priv; MetaWindowActorPrivate *priv = self->priv;
MetaScreen *screen; MetaScreen *screen;
MetaDisplay *display;
Display *xdisplay;
MetaCompScreen *info; MetaCompScreen *info;
if (priv->disposed) if (priv->disposed)
@ -388,9 +352,6 @@ meta_window_actor_dispose (GObject *object)
screen = priv->screen; screen = priv->screen;
info = meta_screen_get_compositor_data (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) if (priv->send_frame_messages_timer != 0)
{ {
g_source_remove (priv->send_frame_messages_timer); g_source_remove (priv->send_frame_messages_timer);
@ -405,18 +366,6 @@ meta_window_actor_dispose (GObject *object)
g_clear_pointer (&priv->unfocused_shadow, meta_shadow_unref); g_clear_pointer (&priv->unfocused_shadow, meta_shadow_unref);
g_clear_pointer (&priv->shadow_shape, meta_window_shape_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); info->windows = g_list_remove (info->windows, (gconstpointer) self);
g_clear_object (&priv->window); g_clear_object (&priv->window);
@ -834,13 +783,6 @@ meta_window_actor_is_destroyed (MetaWindowActor *self)
return self->priv->disposed; return self->priv->disposed;
} }
static void
meta_window_actor_freeze (MetaWindowActor *self)
{
if (!meta_is_wayland_compositor ())
self->priv->freeze_count++;
}
static gboolean static gboolean
send_frame_messages_timeout (gpointer data) send_frame_messages_timeout (gpointer data)
{ {
@ -895,56 +837,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); priv->send_frame_messages_timer = g_timeout_add_full (META_PRIORITY_REDRAW, offset, send_frame_messages_timeout, self, NULL);
} }
static void
meta_window_actor_damage_all (MetaWindowActor *self)
{
MetaWindowActorPrivate *priv = self->priv;
gboolean redraw_queued;
if (!priv->needs_damage_all)
return;
if (priv->needs_pixmap)
return;
redraw_queued = meta_surface_actor_damage_all (priv->surface);
priv->repaint_scheduled = priv->repaint_scheduled || redraw_queued;
priv->needs_damage_all = FALSE;
}
static void
meta_window_actor_thaw (MetaWindowActor *self)
{
if (!meta_is_wayland_compositor ())
{
self->priv->freeze_count--;
if (G_UNLIKELY (self->priv->freeze_count < 0))
{
g_warning ("Error in freeze/thaw accounting.");
self->priv->freeze_count = 0;
return;
}
if (self->priv->freeze_count)
return;
/* We sometimes ignore moves and resizes on frozen windows */
meta_window_actor_sync_actor_geometry (self, FALSE);
/* We do this now since we might be going right back into the
* frozen state */
meta_window_actor_handle_updates (self);
/* Since we ignore damage events while a window is frozen for certain effects
* we may need to issue an update_area() covering the whole pixmap if we
* don't know what real damage has happened. */
if (self->priv->needs_damage_all)
meta_window_actor_damage_all (self);
}
}
void void
meta_window_actor_queue_frame_drawn (MetaWindowActor *self, meta_window_actor_queue_frame_drawn (MetaWindowActor *self,
gboolean no_delay_frame) gboolean no_delay_frame)
@ -999,33 +891,6 @@ meta_window_actor_effect_in_progress (MetaWindowActor *self)
self->priv->destroy_in_progress); self->priv->destroy_in_progress);
} }
static gboolean
is_frozen (MetaWindowActor *self)
{
return self->priv->freeze_count ? TRUE : FALSE;
}
static void
meta_window_actor_queue_create_x11_pixmap (MetaWindowActor *self)
{
MetaWindowActorPrivate *priv = self->priv;
priv->needs_pixmap = TRUE;
if (is_frozen (self))
return;
/* This will cause the compositor paint function to be run
* if the actor is visible or a clone of the actor is visible.
* if the actor isn't visible in any way, then we don't
* need to repair the window anyways, and can wait until
* the stage is redrawn for some other reason
*
* The compositor paint function repairs all windows.
*/
clutter_actor_queue_redraw (CLUTTER_ACTOR (priv->surface));
}
static gboolean static gboolean
is_freeze_thaw_effect (gulong event) is_freeze_thaw_effect (gulong event)
{ {
@ -1106,12 +971,6 @@ meta_window_actor_after_effects (MetaWindowActor *self)
meta_window_actor_sync_visibility (self); meta_window_actor_sync_visibility (self);
meta_window_actor_sync_actor_geometry (self, FALSE); meta_window_actor_sync_actor_geometry (self, FALSE);
if (!meta_is_wayland_compositor ())
{
if (priv->needs_pixmap)
clutter_actor_queue_redraw (CLUTTER_ACTOR (priv->surface));
}
} }
void void
@ -1186,95 +1045,19 @@ meta_window_actor_effect_completed (MetaWindowActor *self,
meta_window_actor_after_effects (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 gboolean
meta_window_actor_should_unredirect (MetaWindowActor *self) meta_window_actor_should_unredirect (MetaWindowActor *self)
{ {
MetaWindow *metaWindow = meta_window_actor_get_meta_window (self);
MetaWindowActorPrivate *priv = self->priv; MetaWindowActorPrivate *priv = self->priv;
return meta_surface_actor_should_unredirect (priv->surface);
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 void
meta_window_actor_set_unredirected (MetaWindowActor *self, meta_window_actor_set_unredirected (MetaWindowActor *self,
gboolean unredirected) gboolean unredirected)
{ {
MetaWindow *metaWindow = meta_window_actor_get_meta_window (self); MetaWindowActorPrivate *priv = self->priv;
MetaDisplay *display = meta_window_get_display (metaWindow); meta_surface_actor_set_unredirected (priv->surface, unredirected);
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);
} }
void void
@ -1328,19 +1111,11 @@ meta_window_actor_sync_actor_geometry (MetaWindowActor *self,
meta_window_get_input_rect (priv->window, &window_rect); meta_window_get_input_rect (priv->window, &window_rect);
/* When running as a display server we catch size changes when new /* When running as a Wayland compositor we catch size changes when new
buffers are attached */ * buffers are attached */
if (!meta_is_wayland_compositor ()) if (META_IS_SURFACE_ACTOR_X11 (priv->surface))
{ meta_surface_actor_x11_set_size (META_SURFACE_ACTOR_X11 (priv->surface),
if (priv->last_width != window_rect.width || window_rect.width, window_rect.height);
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 /* Normally we want freezing a window to also freeze its position; this allows
* windows to atomically move and resize together, either under app control, * windows to atomically move and resize together, either under app control,
@ -1352,15 +1127,6 @@ meta_window_actor_sync_actor_geometry (MetaWindowActor *self,
if (is_frozen (self) && !did_placement) if (is_frozen (self) && !did_placement)
return; 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)) if (meta_window_actor_effect_in_progress (self))
return; return;
@ -1528,14 +1294,10 @@ meta_window_actor_new (MetaWindow *window)
priv = self->priv; priv = self->priv;
if (!meta_is_wayland_compositor ()) meta_window_actor_set_updates_frozen (self, meta_window_updates_are_frozen (priv->window));
if (META_IS_SURFACE_ACTOR_X11 (priv->surface))
{ {
priv->last_width = -1;
priv->last_height = -1;
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 /* 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. * we should send a _NET_WM_FRAME_DRAWN immediately after the first drawn.
*/ */
@ -1646,11 +1408,6 @@ meta_window_actor_cull_out (MetaCullable *cullable,
cairo_region_t *clip_region) cairo_region_t *clip_region)
{ {
MetaWindowActor *self = META_WINDOW_ACTOR (cullable); MetaWindowActor *self = META_WINDOW_ACTOR (cullable);
MetaWindowActorPrivate *priv = self->priv;
/* Don't do any culling for the unredirected window */
if (priv->unredirected)
return;
meta_cullable_cull_out_children (cullable, unobscured_region, clip_region); meta_cullable_cull_out_children (cullable, unobscured_region, clip_region);
meta_window_actor_set_clip_region_beneath (self, clip_region); meta_window_actor_set_clip_region_beneath (self, clip_region);
@ -1674,74 +1431,6 @@ cullable_iface_init (MetaCullableInterface *iface)
iface->reset_culling = meta_window_actor_reset_culling; iface->reset_culling = meta_window_actor_reset_culling;
} }
/* When running as a wayland compositor we don't make requests for
* replacement pixmaps when resizing windows, we will instead be
* asked to attach replacement buffers by the clients. */
static void
check_needs_x11_pixmap (MetaWindowActor *self)
{
MetaWindowActorPrivate *priv = self->priv;
MetaScreen *screen = priv->screen;
MetaDisplay *display = meta_screen_get_display (screen);
Display *xdisplay = meta_display_get_xdisplay (display);
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
Window xwindow = meta_window_get_toplevel_xwindow (priv->window);
if (!priv->needs_pixmap)
return;
if (xwindow == meta_screen_get_xroot (screen) ||
xwindow == clutter_x11_get_stage_window (CLUTTER_STAGE (info->stage)))
return;
if (priv->x11_size_changed)
{
meta_window_actor_detach_x11_pixmap (self);
priv->x11_size_changed = FALSE;
}
meta_error_trap_push (display);
if (priv->back_pixmap == None)
{
CoglContext *ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
CoglTexture *texture;
meta_error_trap_push (display);
priv->back_pixmap = XCompositeNameWindowPixmap (xdisplay, xwindow);
if (meta_error_trap_pop_with_return (display) != Success)
{
/* Probably a BadMatch if the window isn't viewable; we could
* GrabServer/GetWindowAttributes/NameWindowPixmap/UngrabServer/Sync
* to avoid this, but there's no reason to take two round trips
* when one will do. (We need that Sync if we want to handle failures
* for any reason other than !viewable. That's unlikely, but maybe
* we'll BadAlloc or something.)
*/
priv->back_pixmap = None;
}
if (priv->back_pixmap == None)
{
meta_verbose ("Unable to get named pixmap for %p\n", self);
goto out;
}
texture = COGL_TEXTURE (cogl_texture_pixmap_x11_new (ctx, priv->back_pixmap, FALSE, NULL));
if (G_UNLIKELY (!cogl_texture_pixmap_x11_is_using_tfp_extension (COGL_TEXTURE_PIXMAP_X11 (texture))))
g_warning ("NOTE: Not using GLX TFP!\n");
meta_surface_actor_set_texture (META_SURFACE_ACTOR (priv->surface), texture);
}
priv->needs_pixmap = FALSE;
out:
meta_error_trap_pop (display);
}
static void static void
check_needs_shadow (MetaWindowActor *self) check_needs_shadow (MetaWindowActor *self)
{ {
@ -1809,63 +1498,14 @@ meta_window_actor_process_x11_damage (MetaWindowActor *self,
XDamageNotifyEvent *event) XDamageNotifyEvent *event)
{ {
MetaWindowActorPrivate *priv = self->priv; MetaWindowActorPrivate *priv = self->priv;
MetaCompScreen *info = meta_screen_get_compositor_data (priv->screen);
gboolean redraw_queued;
priv->received_x11_damage = TRUE; g_assert (!meta_is_wayland_compositor ());
if (meta_window_is_fullscreen (priv->window) && g_list_last (info->windows)->data == self && !priv->unredirected)
{
MetaRectangle window_rect;
meta_window_get_frame_rect (priv->window, &window_rect);
if (window_rect.x == event->area.x &&
window_rect.y == event->area.y &&
window_rect.width == event->area.width &&
window_rect.height == event->area.height)
priv->full_damage_frames_count++;
else
priv->full_damage_frames_count = 0;
if (priv->full_damage_frames_count >= 100)
priv->does_full_damage = TRUE;
}
/* Drop damage event for unredirected windows */
if (priv->unredirected)
return;
if (is_frozen (self))
{
/* The window is frozen due to an effect in progress: we ignore damage
* here on the off chance that this will stop the corresponding
* texture_from_pixmap from being update.
*
* needs_damage_all tracks that some unknown damage happened while the
* window was frozen so that when the window becomes unfrozen we can
* issue a full window update to cover any lost damage.
*
* It should be noted that this is an unreliable mechanism since it's
* quite likely that drivers will aim to provide a zero-copy
* implementation of the texture_from_pixmap extension and in those cases
* any drawing done to the window is always immediately reflected in the
* texture regardless of damage event handling.
*/
priv->needs_damage_all = TRUE;
return;
}
if (priv->needs_pixmap)
return;
redraw_queued = meta_surface_actor_damage_area (priv->surface,
event->area.x,
event->area.y,
event->area.width,
event->area.height);
priv->repaint_scheduled = priv->repaint_scheduled || redraw_queued;
meta_surface_actor_process_damage (priv->surface,
event->area.x,
event->area.y,
event->area.width,
event->area.height);
} }
void void
@ -2093,8 +1733,9 @@ meta_window_actor_update_opaque_region (MetaWindowActor *self)
{ {
MetaWindowActorPrivate *priv = self->priv; MetaWindowActorPrivate *priv = self->priv;
cairo_region_t *opaque_region; 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; MetaFrameBorders borders;
@ -2114,7 +1755,7 @@ meta_window_actor_update_opaque_region (MetaWindowActor *self)
cairo_region_translate (opaque_region, borders.total.left, borders.total.top); cairo_region_translate (opaque_region, borders.total.left, borders.total.top);
cairo_region_intersect (opaque_region, priv->shape_region); cairo_region_intersect (opaque_region, priv->shape_region);
} }
else if (priv->argb32) else if (argb32)
opaque_region = NULL; opaque_region = NULL;
else else
opaque_region = cairo_region_reference (priv->shape_region); opaque_region = cairo_region_reference (priv->shape_region);
@ -2171,9 +1812,6 @@ static void
meta_window_actor_handle_updates (MetaWindowActor *self) meta_window_actor_handle_updates (MetaWindowActor *self)
{ {
MetaWindowActorPrivate *priv = self->priv; 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)) if (is_frozen (self))
{ {
@ -2182,45 +1820,10 @@ meta_window_actor_handle_updates (MetaWindowActor *self)
return; return;
} }
if (!meta_is_wayland_compositor ()) meta_surface_actor_pre_paint (priv->surface);
{
if (priv->unredirected)
{
/* Nothing to do here until/if the window gets redirected again */
return;
}
if (priv->received_x11_damage) if (!meta_surface_actor_is_visible (priv->surface))
{ return;
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;
}
check_needs_x11_pixmap (self);
}
check_needs_reshape (self); check_needs_reshape (self);
check_needs_shadow (self); check_needs_shadow (self);
@ -2409,20 +2012,16 @@ void
meta_window_actor_set_updates_frozen (MetaWindowActor *self, meta_window_actor_set_updates_frozen (MetaWindowActor *self,
gboolean updates_frozen) gboolean updates_frozen)
{ {
/* On wayland we shouldn't need to ever freeze updates... */ MetaWindowActorPrivate *priv = self->priv;
if (!meta_is_wayland_compositor ())
updates_frozen = updates_frozen != FALSE;
if (priv->updates_frozen != updates_frozen)
{ {
MetaWindowActorPrivate *priv = self->priv; priv->updates_frozen = updates_frozen;
if (updates_frozen)
updates_frozen = updates_frozen != FALSE; meta_window_actor_freeze (self);
else
if (priv->updates_frozen != updates_frozen) meta_window_actor_thaw (self);
{
priv->updates_frozen = updates_frozen;
if (updates_frozen)
meta_window_actor_freeze (self);
else
meta_window_actor_thaw (self);
}
} }
} }

View File

@ -44,11 +44,11 @@
#include "meta-wayland-private.h" #include "meta-wayland-private.h"
#include "meta-xwayland-private.h" #include "meta-xwayland-private.h"
#include "meta-wayland-stage.h" #include "meta-wayland-stage.h"
#include "meta-surface-actor.h"
#include "meta-wayland-seat.h" #include "meta-wayland-seat.h"
#include "meta-wayland-keyboard.h" #include "meta-wayland-keyboard.h"
#include "meta-wayland-pointer.h" #include "meta-wayland-pointer.h"
#include "meta-wayland-data-device.h" #include "meta-wayland-data-device.h"
#include "meta-cursor-tracker-private.h" #include "meta-cursor-tracker-private.h"
#include "display-private.h" #include "display-private.h"
#include "window-private.h" #include "window-private.h"
@ -58,6 +58,9 @@
#include "meta-idle-monitor-private.h" #include "meta-idle-monitor-private.h"
#include "monitor-private.h" #include "monitor-private.h"
#include "meta-surface-actor.h"
#include "meta-surface-actor-wayland.h"
static void static void
surface_process_damage (MetaWaylandSurface *surface, surface_process_damage (MetaWaylandSurface *surface,
cairo_region_t *region) cairo_region_t *region)
@ -68,8 +71,8 @@ surface_process_damage (MetaWaylandSurface *surface,
{ {
cairo_rectangle_int_t rect; cairo_rectangle_int_t rect;
cairo_region_get_rectangle (region, i, &rect); cairo_region_get_rectangle (region, i, &rect);
meta_surface_actor_damage_area (surface->surface_actor, meta_surface_actor_process_damage (surface->surface_actor,
rect.x, rect.y, rect.width, rect.height); rect.x, rect.y, rect.width, rect.height);
} }
} }
@ -260,7 +263,7 @@ actor_surface_commit (MetaWaylandSurface *surface)
{ {
ensure_buffer_texture (buffer); ensure_buffer_texture (buffer);
meta_wayland_buffer_reference (&surface->buffer_ref, buffer); meta_wayland_buffer_reference (&surface->buffer_ref, buffer);
meta_surface_actor_attach_wayland_buffer (surface_actor, buffer); meta_surface_actor_wayland_set_buffer (META_SURFACE_ACTOR_WAYLAND (surface->surface_actor), buffer);
changed = TRUE; changed = TRUE;
} }
@ -501,7 +504,7 @@ meta_wayland_surface_create (MetaWaylandCompositor *compositor,
surface_handle_pending_buffer_destroy; surface_handle_pending_buffer_destroy;
wl_list_init (&surface->pending.frame_callback_list); wl_list_init (&surface->pending.frame_callback_list);
surface->surface_actor = g_object_ref_sink (meta_surface_actor_new ()); surface->surface_actor = g_object_ref_sink (meta_surface_actor_wayland_new (surface));
return surface; return surface;
} }