window-actor: Move all buffer management and damage correction here

We want ShapedTexture to be a dumb actor that knows how to
pick/paint fairly easily, without any "platform knowledge", so to say...
This commit is contained in:
Jasper St. Pierre 2013-11-04 22:13:33 -05:00
parent 735b736110
commit a02d734243
6 changed files with 59 additions and 216 deletions

View File

@ -28,17 +28,9 @@
#define __META_SHAPED_TEXTURE_PRIVATE_H__ #define __META_SHAPED_TEXTURE_PRIVATE_H__
#include <meta/meta-shaped-texture.h> #include <meta/meta-shaped-texture.h>
#include "meta-wayland-private.h"
ClutterActor *meta_shaped_texture_new_with_xwindow (Window xwindow); ClutterActor *meta_shaped_texture_new (void);
ClutterActor *meta_shaped_texture_new_with_wayland_surface (MetaWaylandSurface *surface); void meta_shaped_texture_set_texture (MetaShapedTexture *stex,
void meta_shaped_texture_set_wayland_surface (MetaShapedTexture *stex, CoglTexture *texture);
MetaWaylandSurface *surface);
MetaWaylandSurface *meta_shaped_texture_get_wayland_surface (MetaShapedTexture *stex);
void meta_shaped_texture_set_pixmap (MetaShapedTexture *stex,
Pixmap pixmap);
void meta_shaped_texture_attach_wayland_buffer (MetaShapedTexture *stex,
MetaWaylandBuffer *buffer);
#endif #endif

View File

@ -35,12 +35,9 @@
#include "meta-texture-tower.h" #include "meta-texture-tower.h"
#include "meta-shaped-texture-private.h" #include "meta-shaped-texture-private.h"
#include "meta-wayland-private.h"
#include <cogl/cogl-wayland-server.h>
#include <clutter/clutter.h> #include <clutter/clutter.h>
#include <cogl/cogl.h> #include <cogl/cogl.h>
#include <cogl/cogl-texture-pixmap-x11.h>
#include <gdk/gdk.h> /* for gdk_rectangle_intersect() */ #include <gdk/gdk.h> /* for gdk_rectangle_intersect() */
static void meta_shaped_texture_dispose (GObject *object); static void meta_shaped_texture_dispose (GObject *object);
@ -61,15 +58,7 @@ static void meta_shaped_texture_get_preferred_height (ClutterActor *self,
static gboolean meta_shaped_texture_get_paint_volume (ClutterActor *self, ClutterPaintVolume *volume); static gboolean meta_shaped_texture_get_paint_volume (ClutterActor *self, ClutterPaintVolume *volume);
typedef enum _MetaShapedTextureType G_DEFINE_TYPE (MetaShapedTexture, meta_shaped_texture, CLUTTER_TYPE_ACTOR);
{
META_SHAPED_TEXTURE_TYPE_X11_PIXMAP,
META_SHAPED_TEXTURE_TYPE_WAYLAND_SURFACE,
} MetaShapedTextureType;
G_DEFINE_TYPE (MetaShapedTexture, meta_shaped_texture,
CLUTTER_TYPE_ACTOR);
#define META_SHAPED_TEXTURE_GET_PRIVATE(obj) \ #define META_SHAPED_TEXTURE_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), META_TYPE_SHAPED_TEXTURE, \ (G_TYPE_INSTANCE_GET_PRIVATE ((obj), META_TYPE_SHAPED_TEXTURE, \
@ -79,18 +68,7 @@ struct _MetaShapedTexturePrivate
{ {
MetaTextureTower *paint_tower; MetaTextureTower *paint_tower;
MetaShapedTextureType type;
union {
struct {
Pixmap pixmap;
} x11;
struct {
MetaWaylandSurface *surface;
} wayland;
};
CoglTexture *texture; CoglTexture *texture;
CoglTexture *mask_texture; CoglTexture *mask_texture;
cairo_region_t *clip_region; cairo_region_t *clip_region;
@ -128,9 +106,7 @@ meta_shaped_texture_init (MetaShapedTexture *self)
priv->paint_tower = meta_texture_tower_new (); priv->paint_tower = meta_texture_tower_new ();
priv->type = META_SHAPED_TEXTURE_TYPE_X11_PIXMAP;
priv->texture = NULL; priv->texture = NULL;
priv->mask_texture = NULL; priv->mask_texture = NULL;
priv->create_mipmaps = TRUE; priv->create_mipmaps = TRUE;
} }
@ -220,10 +196,8 @@ paint_clipped_rectangle (CoglFramebuffer *fb,
cogl_framebuffer_draw_multitextured_rectangle (fb, pipeline, cogl_framebuffer_draw_multitextured_rectangle (fb, pipeline,
x1, y1, x2, y2, x1, y1, x2, y2,
&coords[0], 8); &coords[0], 8);
} }
static void static void
set_cogl_texture (MetaShapedTexture *stex, set_cogl_texture (MetaShapedTexture *stex,
CoglTexture *cogl_tex) CoglTexture *cogl_tex)
@ -571,48 +545,6 @@ meta_shaped_texture_get_paint_volume (ClutterActor *self,
return clutter_paint_volume_set_from_allocation (volume, self); return clutter_paint_volume_set_from_allocation (volume, self);
} }
ClutterActor *
meta_shaped_texture_new_with_wayland_surface (MetaWaylandSurface *surface)
{
ClutterActor *actor = g_object_new (META_TYPE_SHAPED_TEXTURE, NULL);
MetaShapedTexturePrivate *priv = META_SHAPED_TEXTURE (actor)->priv;
/* XXX: it could probably be better to have a "type" construct-only
* property or create wayland/x11 subclasses */
priv->type = META_SHAPED_TEXTURE_TYPE_WAYLAND_SURFACE;
meta_shaped_texture_set_wayland_surface (META_SHAPED_TEXTURE (actor),
surface);
return actor;
}
void
meta_shaped_texture_set_wayland_surface (MetaShapedTexture *stex,
MetaWaylandSurface *surface)
{
MetaShapedTexturePrivate *priv = stex->priv;
priv->wayland.surface = surface;
if (surface && surface->buffer_ref.buffer)
meta_shaped_texture_attach_wayland_buffer (stex,
surface->buffer_ref.buffer);
}
MetaWaylandSurface *
meta_shaped_texture_get_wayland_surface (MetaShapedTexture *stex)
{
MetaShapedTexturePrivate *priv = stex->priv;
return priv->wayland.surface;
}
ClutterActor *
meta_shaped_texture_new_with_xwindow (Window xwindow)
{
return g_object_new (META_TYPE_SHAPED_TEXTURE, NULL);
}
void void
meta_shaped_texture_set_create_mipmaps (MetaShapedTexture *stex, meta_shaped_texture_set_create_mipmaps (MetaShapedTexture *stex,
gboolean create_mipmaps) gboolean create_mipmaps)
@ -655,35 +587,6 @@ meta_shaped_texture_set_mask_texture (MetaShapedTexture *stex,
clutter_actor_queue_redraw (CLUTTER_ACTOR (stex)); clutter_actor_queue_redraw (CLUTTER_ACTOR (stex));
} }
static void
wayland_surface_update_area (MetaShapedTexture *stex,
int x,
int y,
int width,
int height)
{
MetaShapedTexturePrivate *priv;
MetaWaylandBuffer *buffer;
priv = stex->priv;
g_return_if_fail (priv->type == META_SHAPED_TEXTURE_TYPE_WAYLAND_SURFACE);
g_return_if_fail (priv->texture != NULL);
buffer = priv->wayland.surface->buffer_ref.buffer;
if (buffer)
{
struct wl_resource *resource = buffer->resource;
struct wl_shm_buffer *shm_buffer = wl_shm_buffer_get (resource);
if (shm_buffer)
cogl_wayland_texture_2d_update_area (COGL_TEXTURE_2D (priv->texture),
shm_buffer,
x, y, width, height);
}
}
static gboolean static gboolean
get_clip (MetaShapedTexture *stex, get_clip (MetaShapedTexture *stex,
int x, int x,
@ -765,17 +668,6 @@ meta_shaped_texture_update_area (MetaShapedTexture *stex,
if (priv->texture == NULL) if (priv->texture == NULL)
return FALSE; return FALSE;
switch (priv->type)
{
case META_SHAPED_TEXTURE_TYPE_X11_PIXMAP:
cogl_texture_pixmap_x11_update_area (COGL_TEXTURE_PIXMAP_X11 (priv->texture),
x, y, width, height);
break;
case META_SHAPED_TEXTURE_TYPE_WAYLAND_SURFACE:
wayland_surface_update_area (stex, x, y, width, height);
break;
}
meta_texture_tower_update_area (priv->paint_tower, x, y, width, height); meta_texture_tower_update_area (priv->paint_tower, x, y, width, height);
has_clip = get_clip (stex, x, y, width, height, &clip); has_clip = get_clip (stex, x, y, width, height, &clip);
@ -815,58 +707,17 @@ meta_shaped_texture_update_area (MetaShapedTexture *stex,
} }
/** /**
* meta_shaped_texture_set_pixmap: * meta_shaped_texture_set_texture:
* @stex: The #MetaShapedTexture * @stex: The #MetaShapedTexture
* @pixmap: The pixmap you want the stex to assume * @pixmap: The #CoglTexture to display
*/ */
void void
meta_shaped_texture_set_pixmap (MetaShapedTexture *stex, meta_shaped_texture_set_texture (MetaShapedTexture *stex,
Pixmap pixmap) CoglTexture *texture)
{ {
MetaShapedTexturePrivate *priv;
g_return_if_fail (META_IS_SHAPED_TEXTURE (stex)); g_return_if_fail (META_IS_SHAPED_TEXTURE (stex));
priv = stex->priv; set_cogl_texture (stex, texture);
if (priv->x11.pixmap == pixmap)
return;
priv->x11.pixmap = pixmap;
if (pixmap != None)
{
CoglContext *ctx =
clutter_backend_get_cogl_context (clutter_get_default_backend ());
CoglTexture *texture =
COGL_TEXTURE (cogl_texture_pixmap_x11_new (ctx, pixmap, FALSE, NULL));
set_cogl_texture (stex, texture);
}
else
set_cogl_texture (stex, NULL);
}
void
meta_shaped_texture_attach_wayland_buffer (MetaShapedTexture *stex,
MetaWaylandBuffer *buffer)
{
MetaShapedTexturePrivate *priv;
g_return_if_fail (META_IS_SHAPED_TEXTURE (stex));
priv = stex->priv;
/* TODO: we should change this api to be something like
* meta_shaped_texture_notify_buffer_attach() since we now maintain
* a reference to the MetaWaylandSurface where we can access the
* buffer without it being explicitly passed as an argument.
*/
g_return_if_fail (priv->wayland.surface->buffer_ref.buffer == buffer);
if (buffer)
set_cogl_texture (stex, buffer->texture);
else
set_cogl_texture (stex, NULL);
} }
/** /**
@ -1077,3 +928,9 @@ meta_shaped_texture_get_image (MetaShapedTexture *stex,
return surface; return surface;
} }
ClutterActor *
meta_shaped_texture_new (void)
{
return g_object_new (META_TYPE_SHAPED_TEXTURE, NULL);
}

View File

@ -35,8 +35,6 @@ void meta_window_actor_process_wayland_damage (MetaWindowActor *self,
int y, int y,
int width, int width,
int height); int height);
void meta_window_actor_set_wayland_surface (MetaWindowActor *self,
MetaWaylandSurface *surface);
void meta_window_actor_attach_wayland_buffer (MetaWindowActor *self, void meta_window_actor_attach_wayland_buffer (MetaWindowActor *self,
MetaWaylandBuffer *buffer); MetaWaylandBuffer *buffer);

View File

@ -16,6 +16,7 @@
#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 <cogl/cogl-wayland-server.h>
#include <gdk/gdk.h> /* for gdk_rectangle_union() */ #include <gdk/gdk.h> /* for gdk_rectangle_union() */
#include <string.h> #include <string.h>
@ -52,6 +53,8 @@ struct _MetaWindowActorPrivate
ClutterActor *actor; ClutterActor *actor;
MetaWaylandBuffer *buffer;
/* MetaShadowFactory only caches shadows that are actually in use; /* MetaShadowFactory only caches shadows that are actually in use;
* to avoid unnecessary recomputation we do two things: 1) we store * to avoid unnecessary recomputation we do two things: 1) we store
* both a focused and unfocused shadow for the window. If the window * both a focused and unfocused shadow for the window. If the window
@ -391,10 +394,7 @@ meta_window_actor_constructed (GObject *object)
if (!priv->actor) if (!priv->actor)
{ {
if (meta_is_wayland_compositor ()) priv->actor = meta_shaped_texture_new ();
priv->actor = meta_shaped_texture_new_with_wayland_surface (window->surface);
else
priv->actor = meta_shaped_texture_new_with_xwindow (xwindow);
clutter_actor_add_child (CLUTTER_ACTOR (self), priv->actor); clutter_actor_add_child (CLUTTER_ACTOR (self), priv->actor);
clutter_actor_set_reactive (CLUTTER_ACTOR (self), TRUE); clutter_actor_set_reactive (CLUTTER_ACTOR (self), TRUE);
@ -1014,6 +1014,35 @@ 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
wayland_surface_update_area (MetaWindowActor *self,
int x, int y, int width, int height)
{
MetaWindowActorPrivate *priv = self->priv;
struct wl_resource *resource = priv->buffer->resource;
struct wl_shm_buffer *shm_buffer = wl_shm_buffer_get (resource);
if (shm_buffer)
cogl_wayland_texture_2d_update_area (COGL_TEXTURE_2D (priv->buffer->texture),
shm_buffer, x, y, width, height);
}
static void
update_area (MetaWindowActor *self,
int x, int y, int width, int height)
{
MetaWindowActorPrivate *priv = self->priv;
CoglTexture *texture;
texture = meta_shaped_texture_get_texture (META_SHAPED_TEXTURE (priv->actor));
if (meta_is_wayland_compositor ())
wayland_surface_update_area (self, x, y, width, height);
else
cogl_texture_pixmap_x11_update_area (COGL_TEXTURE_PIXMAP_X11 (texture),
x, y, width, height);
}
static void static void
meta_window_actor_damage_all (MetaWindowActor *self) meta_window_actor_damage_all (MetaWindowActor *self)
{ {
@ -1029,6 +1058,7 @@ meta_window_actor_damage_all (MetaWindowActor *self)
if (!priv->mapped || priv->needs_pixmap) if (!priv->mapped || priv->needs_pixmap)
return; return;
update_area (self, 0, 0, cogl_texture_get_width (texture), cogl_texture_get_height (texture));
redraw_queued = meta_shaped_texture_update_area (META_SHAPED_TEXTURE (priv->actor), redraw_queued = meta_shaped_texture_update_area (META_SHAPED_TEXTURE (priv->actor),
0, 0, 0, 0,
cogl_texture_get_width (texture), cogl_texture_get_width (texture),
@ -1350,8 +1380,7 @@ meta_window_actor_detach_x11_pixmap (MetaWindowActor *self)
* you are supposed to be able to free a GLXPixmap after freeing the underlying * 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 * pixmap, but it certainly doesn't work with current DRI/Mesa
*/ */
meta_shaped_texture_set_pixmap (META_SHAPED_TEXTURE (priv->actor), meta_shaped_texture_set_texture (META_SHAPED_TEXTURE (priv->actor), NULL);
None);
cogl_flush(); cogl_flush();
XFreePixmap (xdisplay, priv->back_pixmap); XFreePixmap (xdisplay, priv->back_pixmap);
@ -1429,9 +1458,6 @@ meta_window_actor_destroy (MetaWindowActor *self)
priv = self->priv; priv = self->priv;
if (meta_is_wayland_compositor ())
meta_shaped_texture_set_wayland_surface (META_SHAPED_TEXTURE (priv->actor), NULL);
window = priv->window; window = priv->window;
window_type = meta_window_get_window_type (window); window_type = meta_window_get_window_type (window);
meta_window_set_compositor_private (window, NULL); meta_window_set_compositor_private (window, NULL);
@ -1975,6 +2001,7 @@ check_needs_x11_pixmap (MetaWindowActor *self)
if (priv->back_pixmap == None) if (priv->back_pixmap == None)
{ {
CoglContext *ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
CoglTexture *texture; CoglTexture *texture;
meta_error_trap_push (display); meta_error_trap_push (display);
@ -2003,19 +2030,12 @@ check_needs_x11_pixmap (MetaWindowActor *self)
meta_shaped_texture_set_create_mipmaps (META_SHAPED_TEXTURE (priv->actor), meta_shaped_texture_set_create_mipmaps (META_SHAPED_TEXTURE (priv->actor),
FALSE); FALSE);
meta_shaped_texture_set_pixmap (META_SHAPED_TEXTURE (priv->actor), texture = COGL_TEXTURE (cogl_texture_pixmap_x11_new (ctx, priv->back_pixmap, FALSE, NULL));
priv->back_pixmap);
texture = meta_shaped_texture_get_texture (META_SHAPED_TEXTURE (priv->actor));
/*
* This only works *after* actually setting the pixmap, so we have to
* do it here.
* See: http://bugzilla.clutter-project.org/show_bug.cgi?id=2236
*/
if (G_UNLIKELY (!cogl_texture_pixmap_x11_is_using_tfp_extension (COGL_TEXTURE_PIXMAP_X11 (texture)))) if (G_UNLIKELY (!cogl_texture_pixmap_x11_is_using_tfp_extension (COGL_TEXTURE_PIXMAP_X11 (texture))))
g_warning ("NOTE: Not using GLX TFP!\n"); g_warning ("NOTE: Not using GLX TFP!\n");
meta_shaped_texture_set_texture (META_SHAPED_TEXTURE (priv->actor), texture);
/* ::size-changed is supposed to refer to meta_window_get_outer_rect(). /* ::size-changed is supposed to refer to meta_window_get_outer_rect().
* Emitting it here works pretty much OK because a new value of the * Emitting it here works pretty much OK because a new value of the
* *input* rect (which is the outer rect with the addition of invisible * *input* rect (which is the outer rect with the addition of invisible
@ -2153,6 +2173,7 @@ meta_window_actor_process_x11_damage (MetaWindowActor *self,
if (!priv->mapped || priv->needs_pixmap) if (!priv->mapped || priv->needs_pixmap)
return; return;
update_area (self, event->area.x, event->area.y, event->area.width, event->area.height);
redraw_queued = meta_shaped_texture_update_area (META_SHAPED_TEXTURE (priv->actor), redraw_queued = meta_shaped_texture_update_area (META_SHAPED_TEXTURE (priv->actor),
event->area.x, event->area.x,
event->area.y, event->area.y,
@ -2178,11 +2199,11 @@ meta_window_actor_process_wayland_damage (MetaWindowActor *self,
if (!priv->mapped) if (!priv->mapped)
return; return;
update_area (self, x, y, width, height);
redraw_queued = meta_shaped_texture_update_area (META_SHAPED_TEXTURE (priv->actor), redraw_queued = meta_shaped_texture_update_area (META_SHAPED_TEXTURE (priv->actor),
x, y, width, height, x, y, width, height,
clutter_actor_has_mapped_clones (priv->actor) ? clutter_actor_has_mapped_clones (priv->actor) ?
NULL : priv->unobscured_region); NULL : priv->unobscured_region);
priv->repaint_scheduled = priv->repaint_scheduled || redraw_queued; priv->repaint_scheduled = priv->repaint_scheduled || redraw_queued;
} }
@ -2509,31 +2530,17 @@ maybe_emit_size_changed (MetaWindowActor *self,
} }
} }
void
meta_window_actor_set_wayland_surface (MetaWindowActor *self,
MetaWaylandSurface *surface)
{
MetaWindowActorPrivate *priv = self->priv;
meta_shaped_texture_set_wayland_surface (META_SHAPED_TEXTURE (priv->actor),
surface);
if (surface && surface->buffer_ref.buffer)
maybe_emit_size_changed (self, surface->buffer_ref.buffer);
}
void void
meta_window_actor_attach_wayland_buffer (MetaWindowActor *self, meta_window_actor_attach_wayland_buffer (MetaWindowActor *self,
MetaWaylandBuffer *buffer) MetaWaylandBuffer *buffer)
{ {
MetaWindowActorPrivate *priv = self->priv; MetaWindowActorPrivate *priv = self->priv;
MetaShapedTexture *stex = META_SHAPED_TEXTURE (priv->actor); MetaShapedTexture *stex = META_SHAPED_TEXTURE (priv->actor);
CoglTexture *prev_tex = meta_shaped_texture_get_texture (stex);
meta_shaped_texture_attach_wayland_buffer (stex, buffer); priv->buffer = buffer;
if (!prev_tex)
meta_window_actor_sync_actor_geometry (self, FALSE);
meta_shaped_texture_set_texture (stex, buffer->texture);
meta_window_actor_sync_actor_geometry (self, FALSE);
maybe_emit_size_changed (self, buffer); maybe_emit_size_changed (self, buffer);
} }

View File

@ -439,12 +439,6 @@ meta_wayland_seat_repick (MetaWaylandSeat *seat,
surface = window->surface; surface = window->surface;
} }
else if (META_IS_SHAPED_TEXTURE (actor))
{
MetaShapedTexture *shaped_texture = META_SHAPED_TEXTURE (actor);
surface = meta_shaped_texture_get_wayland_surface (shaped_texture);
}
pointer->current = surface; pointer->current = surface;
if (surface != pointer->focus) if (surface != pointer->focus)

View File

@ -48,11 +48,6 @@ xserver_set_window_id (struct wl_client *client,
window = meta_display_lookup_x_window (display, xid); window = meta_display_lookup_x_window (display, xid);
if (window) if (window)
{ {
MetaWindowActor *window_actor =
META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
meta_window_actor_set_wayland_surface (window_actor, surface);
surface->window = window; surface->window = window;
window->surface = surface; window->surface = surface;