[mutter] shaped-texture: Add support for viewports
- From: Jonas Ådahl <jadahl src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [mutter] shaped-texture: Add support for viewports
- Date: Wed, 6 Feb 2019 12:37:07 +0000 (UTC)
commit edfe5cc3b7533a663dae6fee43938ae40b289387
Author: Robert Mader <robert mader posteo de>
Date: Fri Nov 30 15:34:00 2018 +0100
shaped-texture: Add support for viewports
This implements the viewporter protocol which offers a cropping and scaling
capabilities to wayland clients.
There are several use cases for this, for example video players and games,
both as a convenience function and as potential performance optimization when
paired with hardware overlays etc.
https://gitlab.gnome.org/GNOME/mutter/merge_requests/323
src/compositor/meta-shaped-texture-private.h | 7 +
src/compositor/meta-shaped-texture.c | 234 +++++++++++++++++++++++----
src/compositor/meta-surface-actor.c | 41 +++++
src/compositor/meta-surface-actor.h | 7 +
4 files changed, 262 insertions(+), 27 deletions(-)
---
diff --git a/src/compositor/meta-shaped-texture-private.h b/src/compositor/meta-shaped-texture-private.h
index 44816a14d..a86a2bff0 100644
--- a/src/compositor/meta-shaped-texture-private.h
+++ b/src/compositor/meta-shaped-texture-private.h
@@ -44,5 +44,12 @@ 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);
+void meta_shaped_texture_set_viewport_src_rect (MetaShapedTexture *stex,
+ ClutterRect *src_rect);
+void meta_shaped_texture_reset_viewport_src_rect (MetaShapedTexture *stex);
+void meta_shaped_texture_set_viewport_dst_size (MetaShapedTexture *stex,
+ int dst_width,
+ int dst_height);
+void meta_shaped_texture_reset_viewport_dst_size (MetaShapedTexture *stex);
#endif
diff --git a/src/compositor/meta-shaped-texture.c b/src/compositor/meta-shaped-texture.c
index 9f96d6718..b04ae89c2 100644
--- a/src/compositor/meta-shaped-texture.c
+++ b/src/compositor/meta-shaped-texture.c
@@ -32,6 +32,7 @@
#include "core/boxes-private.h"
#include <gdk/gdk.h>
+#include <math.h>
#include "cogl/cogl.h"
#include "compositor/clutter-utils.h"
@@ -106,6 +107,11 @@ struct _MetaShapedTexture
gboolean size_invalid;
MetaMonitorTransform transform;
+ gboolean has_viewport_src_rect;
+ ClutterRect viewport_src_rect;
+ gboolean has_viewport_dst_size;
+ int viewport_dst_width;
+ int viewport_dst_height;
int tex_width, tex_height;
int fallback_width, fallback_height;
@@ -169,33 +175,53 @@ meta_shaped_texture_init (MetaShapedTexture *stex)
static void
update_size (MetaShapedTexture *stex)
{
+ ClutterActor *actor = CLUTTER_ACTOR (stex);
int dst_width;
int dst_height;
- if (meta_monitor_transform_is_rotated (stex->transform))
+ if (stex->has_viewport_dst_size)
{
- if (stex->texture)
- {
- dst_width = stex->tex_height;
- dst_height = stex->tex_width;
- }
- else
- {
- dst_width = stex->fallback_height;
- dst_height = stex->fallback_width;
- }
+ double tex_scale;
+
+ clutter_actor_get_scale (actor, &tex_scale, NULL);
+ dst_width = ceil (stex->viewport_dst_width / tex_scale);
+ dst_height = ceil (stex->viewport_dst_height / tex_scale);
+ }
+ else if (stex->has_viewport_src_rect)
+ {
+ double tex_scale;
+
+ clutter_actor_get_scale (actor, &tex_scale, NULL);
+ dst_width = ceil (stex->viewport_src_rect.size.width / tex_scale);
+ dst_height = ceil (stex->viewport_src_rect.size.height / tex_scale);
}
else
{
- if (stex->texture)
+ if (meta_monitor_transform_is_rotated (stex->transform))
{
- dst_width = stex->tex_width;
- dst_height = stex->tex_height;
+ if (stex->texture)
+ {
+ dst_width = stex->tex_height;
+ dst_height = stex->tex_width;
+ }
+ else
+ {
+ dst_width = stex->fallback_height;
+ dst_height = stex->fallback_width;
+ }
}
else
{
- dst_width = stex->fallback_width;
- dst_height = stex->fallback_height;
+ if (stex->texture)
+ {
+ dst_width = stex->tex_width;
+ dst_height = stex->tex_height;
+ }
+ else
+ {
+ dst_width = stex->fallback_width;
+ dst_height = stex->fallback_height;
+ }
}
}
@@ -408,23 +434,66 @@ get_unblended_pipeline (MetaShapedTexture *stex,
}
static void
-paint_clipped_rectangle (CoglFramebuffer *fb,
+paint_clipped_rectangle (MetaShapedTexture *stex,
+ CoglFramebuffer *fb,
CoglPipeline *pipeline,
cairo_rectangle_int_t *rect,
ClutterActorBox *alloc)
{
float coords[8];
float x1, y1, x2, y2;
+ float alloc_width;
+ float alloc_height;
x1 = rect->x;
y1 = rect->y;
x2 = rect->x + rect->width;
y2 = rect->y + rect->height;
+ alloc_width = alloc->x2 - alloc->x1;
+ alloc_height = alloc->y2 - alloc->y1;
+
+ if (stex->has_viewport_src_rect)
+ {
+ double tex_scale;
+ float src_x;
+ float src_y;
+ float src_width;
+ float src_height;
+
+ clutter_actor_get_scale (CLUTTER_ACTOR (stex), &tex_scale, NULL);
+
+ src_x = stex->viewport_src_rect.origin.x / tex_scale;
+ src_y = stex->viewport_src_rect.origin.y / tex_scale;
+ src_width = stex->viewport_src_rect.size.width / tex_scale;
+ src_height = stex->viewport_src_rect.size.height / tex_scale;
- coords[0] = rect->x / (alloc->x2 - alloc->x1);
- coords[1] = rect->y / (alloc->y2 - alloc->y1);
- coords[2] = (rect->x + rect->width) / (alloc->x2 - alloc->x1);
- coords[3] = (rect->y + rect->height) / (alloc->y2 - alloc->y1);
+ coords[0] = rect->x * src_width / alloc_width + src_x;
+ coords[1] = rect->y * src_height / alloc_height + src_y;
+ coords[2] = rect->width * src_width / alloc_width + coords[0];
+ coords[3] = rect->height * src_height / alloc_height + coords[1];
+
+ if (meta_monitor_transform_is_rotated (stex->transform))
+ {
+ coords[0] /= stex->tex_height;
+ coords[1] /= stex->tex_width;
+ coords[2] /= stex->tex_height;
+ coords[3] /= stex->tex_width;
+ }
+ else
+ {
+ coords[0] /= stex->tex_width;
+ coords[1] /= stex->tex_height;
+ coords[2] /= stex->tex_width;
+ coords[3] /= stex->tex_height;
+ }
+ }
+ else
+ {
+ coords[0] = rect->x / alloc_width;
+ coords[1] = rect->y / alloc_height;
+ coords[2] = (rect->x + rect->width) / alloc_width;
+ coords[3] = (rect->y + rect->height) / alloc_height;
+ }
coords[4] = coords[0];
coords[5] = coords[1];
@@ -624,7 +693,11 @@ do_paint (MetaShapedTexture *stex,
{
cairo_rectangle_int_t rect;
cairo_region_get_rectangle (region, i, &rect);
- paint_clipped_rectangle (fb, opaque_pipeline, &rect, &alloc);
+ paint_clipped_rectangle (stex,
+ fb,
+ opaque_pipeline,
+ &rect,
+ &alloc);
}
}
@@ -677,16 +750,21 @@ do_paint (MetaShapedTexture *stex,
if (!gdk_rectangle_intersect (&tex_rect, &rect, &rect))
continue;
- paint_clipped_rectangle (fb, blended_pipeline, &rect, &alloc);
+ paint_clipped_rectangle (stex,
+ fb,
+ blended_pipeline,
+ &rect,
+ &alloc);
}
}
else
{
/* 3) blended_tex_region is NULL. Do a full paint. */
- cogl_framebuffer_draw_rectangle (fb, blended_pipeline,
- 0, 0,
- alloc.x2 - alloc.x1,
- alloc.y2 - alloc.y1);
+ paint_clipped_rectangle (stex,
+ fb,
+ blended_pipeline,
+ &tex_rect,
+ &alloc);
}
}
@@ -909,6 +987,59 @@ meta_shaped_texture_update_area (MetaShapedTexture *stex,
stex->dst_height,
&clip);
+ if (stex->has_viewport_src_rect || stex->has_viewport_dst_size)
+ {
+ ClutterRect viewport;
+ ClutterRect inverted_viewport;
+ double tex_scale;
+ float dst_width;
+ float dst_height;
+ int inverted_dst_width;
+ int inverted_dst_height;
+
+ clutter_actor_get_scale (CLUTTER_ACTOR (stex), &tex_scale, NULL);
+
+ if (stex->has_viewport_src_rect)
+ {
+ viewport = stex->viewport_src_rect;
+ }
+ else
+ {
+ viewport = (ClutterRect) {
+ .origin.x = 0,
+ .origin.y = 0,
+ .size.width = stex->tex_width * tex_scale,
+ .size.height = stex->tex_height * tex_scale
+ };
+ }
+
+ if (stex->has_viewport_dst_size)
+ {
+ dst_width = (float) stex->viewport_dst_width;
+ dst_height = (float) stex->viewport_dst_height;
+ }
+ else
+ {
+ dst_width = (float) stex->tex_width * tex_scale;
+ dst_height = (float) stex->tex_height * tex_scale;
+ }
+
+ inverted_viewport = (ClutterRect) {
+ .origin.x = -((viewport.origin.x * (dst_width / viewport.size.width)) / tex_scale),
+ .origin.y = -((viewport.origin.y * (dst_height / viewport.size.height)) / tex_scale),
+ .size.width = dst_width,
+ .size.height = dst_height
+ };
+ inverted_dst_width = ceilf (viewport.size.width);
+ inverted_dst_height = ceilf (viewport.size.height);
+
+ meta_rectangle_crop_and_scale (&clip,
+ &inverted_viewport,
+ inverted_dst_width,
+ inverted_dst_height,
+ &clip);
+ }
+
meta_texture_tower_update_area (stex->paint_tower,
clip.x,
clip.y,
@@ -1063,12 +1194,61 @@ meta_shaped_texture_set_transform (MetaShapedTexture *stex,
invalidate_size (stex);
}
+void
+meta_shaped_texture_set_viewport_src_rect (MetaShapedTexture *stex,
+ ClutterRect *src_rect)
+{
+ if (!stex->has_viewport_src_rect ||
+ stex->viewport_src_rect.origin.x != src_rect->origin.x ||
+ stex->viewport_src_rect.origin.y != src_rect->origin.y ||
+ stex->viewport_src_rect.size.width != src_rect->size.width ||
+ stex->viewport_src_rect.size.height != src_rect->size.height)
+ {
+ stex->has_viewport_src_rect = TRUE;
+ stex->viewport_src_rect = *src_rect;
+ invalidate_size (stex);
+ }
+}
+
+void
+meta_shaped_texture_reset_viewport_src_rect (MetaShapedTexture *stex)
+{
+ stex->has_viewport_src_rect = FALSE;
+ invalidate_size (stex);
+}
+
+void
+meta_shaped_texture_set_viewport_dst_size (MetaShapedTexture *stex,
+ int dst_width,
+ int dst_height)
+{
+ if (!stex->has_viewport_dst_size ||
+ stex->viewport_dst_width != dst_width ||
+ stex->viewport_dst_height != dst_height)
+ {
+ stex->has_viewport_dst_size = TRUE;
+ stex->viewport_dst_width = dst_width;
+ stex->viewport_dst_height = dst_height;
+ invalidate_size (stex);
+ }
+}
+
+void
+meta_shaped_texture_reset_viewport_dst_size (MetaShapedTexture *stex)
+{
+ stex->has_viewport_dst_size = FALSE;
+ invalidate_size (stex);
+}
+
static gboolean
should_get_via_offscreen (MetaShapedTexture *stex)
{
if (!cogl_texture_is_get_data_supported (stex->texture))
return TRUE;
+ if (stex->has_viewport_src_rect || stex->has_viewport_dst_size)
+ return TRUE;
+
switch (stex->transform)
{
case META_MONITOR_TRANSFORM_90:
diff --git a/src/compositor/meta-surface-actor.c b/src/compositor/meta-surface-actor.c
index 6edf7c22d..fb2776000 100644
--- a/src/compositor/meta-surface-actor.c
+++ b/src/compositor/meta-surface-actor.c
@@ -419,3 +419,44 @@ meta_surface_actor_set_transform (MetaSurfaceActor *self,
meta_shaped_texture_set_transform (priv->texture, transform);
}
+
+void
+meta_surface_actor_set_viewport_src_rect (MetaSurfaceActor *self,
+ ClutterRect *src_rect)
+{
+ MetaSurfaceActorPrivate *priv =
+ meta_surface_actor_get_instance_private (self);
+
+ meta_shaped_texture_set_viewport_src_rect (priv->texture, src_rect);
+}
+
+void
+meta_surface_actor_reset_viewport_src_rect (MetaSurfaceActor *self)
+{
+ MetaSurfaceActorPrivate *priv =
+ meta_surface_actor_get_instance_private (self);
+
+ meta_shaped_texture_reset_viewport_src_rect (priv->texture);
+}
+
+void
+meta_surface_actor_set_viewport_dst_size (MetaSurfaceActor *self,
+ int dst_width,
+ int dst_height)
+{
+ MetaSurfaceActorPrivate *priv =
+ meta_surface_actor_get_instance_private (self);
+
+ meta_shaped_texture_set_viewport_dst_size (priv->texture,
+ dst_width,
+ dst_height);
+}
+
+void
+meta_surface_actor_reset_viewport_dst_size (MetaSurfaceActor *self)
+{
+ MetaSurfaceActorPrivate *priv =
+ meta_surface_actor_get_instance_private (self);
+
+ meta_shaped_texture_reset_viewport_dst_size (priv->texture);
+}
diff --git a/src/compositor/meta-surface-actor.h b/src/compositor/meta-surface-actor.h
index bf60ac462..1cffcf99c 100644
--- a/src/compositor/meta-surface-actor.h
+++ b/src/compositor/meta-surface-actor.h
@@ -65,6 +65,13 @@ gboolean meta_surface_actor_is_unredirected (MetaSurfaceActor *actor);
void meta_surface_actor_set_transform (MetaSurfaceActor *self,
MetaMonitorTransform transform);
+void meta_surface_actor_set_viewport_src_rect (MetaSurfaceActor *self,
+ ClutterRect *src_rect);
+void meta_surface_actor_reset_viewport_src_rect (MetaSurfaceActor *self);
+void meta_surface_actor_set_viewport_dst_size (MetaSurfaceActor *self,
+ int dst_width,
+ int dst_height);
+void meta_surface_actor_reset_viewport_dst_size (MetaSurfaceActor *self);
G_END_DECLS
#endif /* META_SURFACE_ACTOR_PRIVATE_H */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]