diff --git a/src/compositor/meta-shaped-texture-private.h b/src/compositor/meta-shaped-texture-private.h index 284f43e36..44816a14d 100644 --- a/src/compositor/meta-shaped-texture-private.h +++ b/src/compositor/meta-shaped-texture-private.h @@ -27,6 +27,7 @@ #ifndef __META_SHAPED_TEXTURE_PRIVATE_H__ #define __META_SHAPED_TEXTURE_PRIVATE_H__ +#include "backends/meta-monitor-manager-private.h" #include "meta/meta-shaped-texture.h" ClutterActor *meta_shaped_texture_new (void); @@ -41,5 +42,7 @@ void meta_shaped_texture_set_fallback_size (MetaShapedTexture *stex, int fallback_height); gboolean meta_shaped_texture_is_obscured (MetaShapedTexture *self); cairo_region_t * meta_shaped_texture_get_opaque_region (MetaShapedTexture *stex); +void meta_shaped_texture_set_transform (MetaShapedTexture *stex, + MetaMonitorTransform transform); #endif diff --git a/src/compositor/meta-shaped-texture.c b/src/compositor/meta-shaped-texture.c index 919e7a9b5..3a7710301 100644 --- a/src/compositor/meta-shaped-texture.c +++ b/src/compositor/meta-shaped-texture.c @@ -103,8 +103,12 @@ struct _MetaShapedTexturePrivate cairo_region_t *clip_region; cairo_region_t *unobscured_region; + gboolean size_invalid; + MetaMonitorTransform transform; + int tex_width, tex_height; int fallback_width, fallback_height; + int dst_width, dst_height; gint64 prev_invalidation, last_invalidation; guint fast_updates; @@ -139,6 +143,14 @@ meta_shaped_texture_class_init (MetaShapedTextureClass *klass) G_TYPE_NONE, 0); } +static void +invalidate_size (MetaShapedTexture *stex) +{ + MetaShapedTexturePrivate *priv = stex->priv; + + priv->size_invalid = TRUE; +} + static void meta_shaped_texture_init (MetaShapedTexture *self) { @@ -152,6 +164,68 @@ meta_shaped_texture_init (MetaShapedTexture *self) priv->mask_texture = NULL; priv->create_mipmaps = TRUE; priv->is_y_inverted = TRUE; + priv->transform = META_MONITOR_TRANSFORM_NORMAL; + + g_signal_connect (self, + "notify::scale-x", + G_CALLBACK (invalidate_size), + self); +} + +static void +update_size (MetaShapedTexture *stex) +{ + MetaShapedTexturePrivate *priv = stex->priv; + int dst_width; + int dst_height; + + if (meta_monitor_transform_is_rotated (priv->transform)) + { + if (priv->texture) + { + dst_width = priv->tex_height; + dst_height = priv->tex_width; + } + else + { + dst_width = priv->fallback_height; + dst_height = priv->fallback_width; + } + } + else + { + if (priv->texture) + { + dst_width = priv->tex_width; + dst_height = priv->tex_height; + } + else + { + dst_width = priv->fallback_width; + dst_height = priv->fallback_height; + } + } + + priv->size_invalid = FALSE; + + if (priv->dst_width != dst_width || + priv->dst_height != dst_height) + { + priv->dst_width = dst_width; + priv->dst_height = dst_height; + meta_shaped_texture_set_mask_texture (stex, NULL); + clutter_actor_queue_relayout (CLUTTER_ACTOR (stex)); + g_signal_emit (stex, signals[SIZE_CHANGED], 0); + } +} + +static void +ensure_size_valid (MetaShapedTexture *stex) +{ + MetaShapedTexturePrivate *priv = stex->priv; + + if (priv->size_invalid) + update_size (stex); } static void @@ -165,16 +239,9 @@ set_unobscured_region (MetaShapedTexture *self, { int width, height; - if (priv->texture) - { - width = priv->tex_width; - height = priv->tex_height; - } - else - { - width = priv->fallback_width; - height = priv->fallback_height; - } + ensure_size_valid (self); + width = priv->dst_width; + height = priv->dst_height; cairo_rectangle_int_t bounds = { 0, 0, width, height }; priv->unobscured_region = cairo_region_copy (unobscured_region); @@ -262,6 +329,45 @@ get_base_pipeline (MetaShapedTexture *stex, cogl_pipeline_set_layer_matrix (pipeline, 0, &matrix); } + if (priv->transform != META_MONITOR_TRANSFORM_NORMAL) + { + CoglMatrix matrix; + CoglEuler euler; + + cogl_matrix_init_translation (&matrix, 0.5, 0.5, 0.0); + switch (priv->transform) + { + case META_MONITOR_TRANSFORM_90: + cogl_euler_init (&euler, 0.0, 0.0, 90.0); + break; + case META_MONITOR_TRANSFORM_180: + cogl_euler_init (&euler, 0.0, 0.0, 180.0); + break; + case META_MONITOR_TRANSFORM_270: + cogl_euler_init (&euler, 0.0, 0.0, 270.0); + break; + case META_MONITOR_TRANSFORM_FLIPPED: + cogl_euler_init (&euler, 180.0, 0.0, 0.0); + break; + case META_MONITOR_TRANSFORM_FLIPPED_90: + cogl_euler_init (&euler, 0.0, 180.0, 90.0); + break; + case META_MONITOR_TRANSFORM_FLIPPED_180: + cogl_euler_init (&euler, 180.0, 0.0, 180.0); + break; + case META_MONITOR_TRANSFORM_FLIPPED_270: + cogl_euler_init (&euler, 0.0, 180.0, 270.0); + break; + case META_MONITOR_TRANSFORM_NORMAL: + g_assert_not_reached (); + } + cogl_matrix_rotate_euler (&matrix, &euler); + cogl_matrix_translate (&matrix, -0.5, -0.5, 0.0); + + cogl_pipeline_set_layer_matrix (pipeline, 0, &matrix); + cogl_pipeline_set_layer_matrix (pipeline, 1, &matrix); + } + if (priv->snippet) cogl_pipeline_add_layer_snippet (pipeline, 0, priv->snippet); @@ -382,9 +488,7 @@ set_cogl_texture (MetaShapedTexture *stex, { priv->tex_width = width; priv->tex_height = height; - meta_shaped_texture_set_mask_texture (stex, NULL); - clutter_actor_queue_relayout (CLUTTER_ACTOR (stex)); - g_signal_emit (stex, signals[SIZE_CHANGED], 0); + update_size (stex); } /* NB: We don't queue a redraw of the actor here because we don't @@ -417,7 +521,7 @@ meta_shaped_texture_paint (ClutterActor *actor) MetaShapedTexture *stex = (MetaShapedTexture *) actor; MetaShapedTexturePrivate *priv = stex->priv; double tex_scale; - int tex_width, tex_height; + int dst_width, dst_height; cairo_rectangle_int_t tex_rect; guchar opacity; gboolean use_opaque_region; @@ -482,13 +586,14 @@ meta_shaped_texture_paint (ClutterActor *actor) } clutter_actor_get_scale (actor, &tex_scale, NULL); - tex_width = priv->tex_width; - tex_height = priv->tex_height; + ensure_size_valid (stex); + dst_width = priv->dst_width; + dst_height = priv->dst_height; - if (tex_width == 0 || tex_height == 0) /* no contents yet */ + if (dst_width == 0 || dst_height == 0) /* no contents yet */ return; - tex_rect = (cairo_rectangle_int_t) { 0, 0, tex_width, tex_height }; + tex_rect = (cairo_rectangle_int_t) { 0, 0, dst_width, dst_height }; /* Use nearest-pixel interpolation if the texture is unscaled. This * improves performance, especially with software rendering. @@ -496,7 +601,7 @@ meta_shaped_texture_paint (ClutterActor *actor) filter = COGL_PIPELINE_FILTER_LINEAR; - if (meta_actor_painting_untransformed (tex_width, tex_height, NULL, NULL)) + if (meta_actor_painting_untransformed (dst_width, dst_height, NULL, NULL)) filter = COGL_PIPELINE_FILTER_NEAREST; ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ()); @@ -670,18 +775,15 @@ meta_shaped_texture_get_preferred_width (ClutterActor *self, gfloat *min_width_p, gfloat *natural_width_p) { - MetaShapedTexturePrivate *priv = META_SHAPED_TEXTURE (self)->priv; - int width; + MetaShapedTexture *stex = META_SHAPED_TEXTURE (self); + MetaShapedTexturePrivate *priv = stex->priv; - if (priv->texture) - width = priv->tex_width; - else - width = priv->fallback_width; + ensure_size_valid (stex); if (min_width_p) - *min_width_p = width; + *min_width_p = priv->dst_width; if (natural_width_p) - *natural_width_p = width; + *natural_width_p = priv->dst_width; } static void @@ -690,18 +792,15 @@ meta_shaped_texture_get_preferred_height (ClutterActor *self, gfloat *min_height_p, gfloat *natural_height_p) { - MetaShapedTexturePrivate *priv = META_SHAPED_TEXTURE (self)->priv; - int height; + MetaShapedTexture *stex = META_SHAPED_TEXTURE (self); + MetaShapedTexturePrivate *priv = stex->priv; - if (priv->texture) - height = priv->tex_height; - else - height = priv->fallback_height; + ensure_size_valid (stex); if (min_height_p) - *min_height_p = height; + *min_height_p = priv->dst_height; if (natural_height_p) - *natural_height_p = height; + *natural_height_p = priv->dst_height; } static cairo_region_t * @@ -958,6 +1057,21 @@ meta_shaped_texture_get_opaque_region (MetaShapedTexture *stex) return priv->opaque_region; } +void +meta_shaped_texture_set_transform (MetaShapedTexture *stex, + MetaMonitorTransform transform) +{ + MetaShapedTexturePrivate *priv = stex->priv; + + if (priv->transform == transform) + return; + + priv->transform = transform; + + meta_shaped_texture_reset_pipelines (stex); + invalidate_size (stex); +} + /** * meta_shaped_texture_get_image: * @stex: A #MetaShapedTexture @@ -1057,14 +1171,16 @@ meta_shaped_texture_get_image (MetaShapedTexture *stex, } void -meta_shaped_texture_set_fallback_size (MetaShapedTexture *self, +meta_shaped_texture_set_fallback_size (MetaShapedTexture *stex, int fallback_width, int fallback_height) { - MetaShapedTexturePrivate *priv = self->priv; + MetaShapedTexturePrivate *priv = stex->priv; priv->fallback_width = fallback_width; priv->fallback_height = fallback_height; + + invalidate_size (stex); } static void diff --git a/src/compositor/meta-surface-actor.c b/src/compositor/meta-surface-actor.c index 256215373..823c1ac12 100644 --- a/src/compositor/meta-surface-actor.c +++ b/src/compositor/meta-surface-actor.c @@ -385,3 +385,12 @@ meta_surface_actor_get_window (MetaSurfaceActor *self) { return META_SURFACE_ACTOR_GET_CLASS (self)->get_window (self); } + +void +meta_surface_actor_set_transform (MetaSurfaceActor *self, + MetaMonitorTransform transform) +{ + MetaSurfaceActorPrivate *priv = self->priv; + + meta_shaped_texture_set_transform (priv->texture, transform); +} diff --git a/src/compositor/meta-surface-actor.h b/src/compositor/meta-surface-actor.h index 6a2740023..102b67083 100644 --- a/src/compositor/meta-surface-actor.h +++ b/src/compositor/meta-surface-actor.h @@ -5,6 +5,7 @@ #include "config.h" +#include "backends/meta-backend-types.h" #include "meta/meta-shaped-texture.h" #include "meta/window.h" @@ -76,6 +77,8 @@ void meta_surface_actor_set_unredirected (MetaSurfaceActor *actor, gboolean unredirected); gboolean meta_surface_actor_is_unredirected (MetaSurfaceActor *actor); +void meta_surface_actor_set_transform (MetaSurfaceActor *self, + MetaMonitorTransform transform); G_END_DECLS #endif /* META_SURFACE_ACTOR_PRIVATE_H */