mirror of
https://github.com/brl/mutter.git
synced 2024-12-24 12:02:04 +00:00
shaped-texture: Implement ClutterContent
MetaWindowActor is the compositor-side representative of a MetaWindow. Specifically it represents the geometry of the window under Clutter scene graph. MetaWindowActors are backed by MetaSurfaceActors, that represent the windowing system's surfaces themselves. Naturally, these surfaces have textures with the pixel content of the clients associated with them. These textures are represented by MetaShapedTexture. MetaShapedTextures are currently implemented as ClutterActor subclasses that override the paint function to paint the textures it holds. Conceptually, however, Clutter has an abstraction layer for contents of actors: ClutterContent. Which MetaShapedTexture fits nicely, in fact. Make MetaShapedTexture a ClutterContent implementation. This forces a few changes in the stack: * MetaShapedTexture now handles buffer scale. * We now paint into ClutterPaintNode instead of the direct framebuffer. * Various pieces of Wayland code now use MetaSurfaceActor instead of MetaShapedTexture. * MetaSurfaceActorWayland doesn't override size negotiation vfuncs anymore https://gitlab.gnome.org/GNOME/mutter/merge_requests/409
This commit is contained in:
parent
e33d6b2908
commit
75cffd0ec4
@ -30,7 +30,7 @@
|
|||||||
#include "backends/meta-monitor-manager-private.h"
|
#include "backends/meta-monitor-manager-private.h"
|
||||||
#include "meta/meta-shaped-texture.h"
|
#include "meta/meta-shaped-texture.h"
|
||||||
|
|
||||||
ClutterActor *meta_shaped_texture_new (void);
|
MetaShapedTexture *meta_shaped_texture_new (void);
|
||||||
void meta_shaped_texture_set_texture (MetaShapedTexture *stex,
|
void meta_shaped_texture_set_texture (MetaShapedTexture *stex,
|
||||||
CoglTexture *texture);
|
CoglTexture *texture);
|
||||||
void meta_shaped_texture_set_is_y_inverted (MetaShapedTexture *stex,
|
void meta_shaped_texture_set_is_y_inverted (MetaShapedTexture *stex,
|
||||||
@ -51,5 +51,13 @@ void meta_shaped_texture_set_viewport_dst_size (MetaShapedTexture *stex,
|
|||||||
int dst_width,
|
int dst_width,
|
||||||
int dst_height);
|
int dst_height);
|
||||||
void meta_shaped_texture_reset_viewport_dst_size (MetaShapedTexture *stex);
|
void meta_shaped_texture_reset_viewport_dst_size (MetaShapedTexture *stex);
|
||||||
|
void meta_shaped_texture_cull_out (MetaShapedTexture *stex,
|
||||||
|
cairo_region_t *unobscured_region,
|
||||||
|
cairo_region_t *clip_region,
|
||||||
|
uint8_t opacity);
|
||||||
|
void meta_shaped_texture_reset_culling (MetaShapedTexture *stex);
|
||||||
|
void meta_shaped_texture_set_buffer_scale (MetaShapedTexture *stex,
|
||||||
|
int buffer_scale);
|
||||||
|
int meta_shaped_texture_get_buffer_scale (MetaShapedTexture *stex);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -58,21 +58,7 @@
|
|||||||
|
|
||||||
static void meta_shaped_texture_dispose (GObject *object);
|
static void meta_shaped_texture_dispose (GObject *object);
|
||||||
|
|
||||||
static void meta_shaped_texture_paint (ClutterActor *actor);
|
static void clutter_content_iface_init (ClutterContentInterface *iface);
|
||||||
|
|
||||||
static void meta_shaped_texture_get_preferred_width (ClutterActor *self,
|
|
||||||
gfloat for_height,
|
|
||||||
gfloat *min_width_p,
|
|
||||||
gfloat *natural_width_p);
|
|
||||||
|
|
||||||
static void meta_shaped_texture_get_preferred_height (ClutterActor *self,
|
|
||||||
gfloat for_width,
|
|
||||||
gfloat *min_height_p,
|
|
||||||
gfloat *natural_height_p);
|
|
||||||
|
|
||||||
static gboolean meta_shaped_texture_get_paint_volume (ClutterActor *self, ClutterPaintVolume *volume);
|
|
||||||
|
|
||||||
static void cullable_iface_init (MetaCullableInterface *iface);
|
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
@ -85,7 +71,7 @@ static guint signals[LAST_SIGNAL];
|
|||||||
|
|
||||||
struct _MetaShapedTexture
|
struct _MetaShapedTexture
|
||||||
{
|
{
|
||||||
ClutterActor parent;
|
GObject parent;
|
||||||
|
|
||||||
MetaTextureTower *paint_tower;
|
MetaTextureTower *paint_tower;
|
||||||
|
|
||||||
@ -123,25 +109,22 @@ struct _MetaShapedTexture
|
|||||||
guint remipmap_timeout_id;
|
guint remipmap_timeout_id;
|
||||||
gint64 earliest_remipmap;
|
gint64 earliest_remipmap;
|
||||||
|
|
||||||
|
int buffer_scale;
|
||||||
|
|
||||||
guint create_mipmaps : 1;
|
guint create_mipmaps : 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
G_DEFINE_TYPE_WITH_CODE (MetaShapedTexture, meta_shaped_texture, CLUTTER_TYPE_ACTOR,
|
G_DEFINE_TYPE_WITH_CODE (MetaShapedTexture, meta_shaped_texture, G_TYPE_OBJECT,
|
||||||
G_IMPLEMENT_INTERFACE (META_TYPE_CULLABLE, cullable_iface_init));
|
G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_CONTENT,
|
||||||
|
clutter_content_iface_init));
|
||||||
|
|
||||||
static void
|
static void
|
||||||
meta_shaped_texture_class_init (MetaShapedTextureClass *klass)
|
meta_shaped_texture_class_init (MetaShapedTextureClass *klass)
|
||||||
{
|
{
|
||||||
GObjectClass *gobject_class = (GObjectClass *) klass;
|
GObjectClass *gobject_class = (GObjectClass *) klass;
|
||||||
ClutterActorClass *actor_class = (ClutterActorClass *) klass;
|
|
||||||
|
|
||||||
gobject_class->dispose = meta_shaped_texture_dispose;
|
gobject_class->dispose = meta_shaped_texture_dispose;
|
||||||
|
|
||||||
actor_class->get_preferred_width = meta_shaped_texture_get_preferred_width;
|
|
||||||
actor_class->get_preferred_height = meta_shaped_texture_get_preferred_height;
|
|
||||||
actor_class->paint = meta_shaped_texture_paint;
|
|
||||||
actor_class->get_paint_volume = meta_shaped_texture_get_paint_volume;
|
|
||||||
|
|
||||||
signals[SIZE_CHANGED] = g_signal_new ("size-changed",
|
signals[SIZE_CHANGED] = g_signal_new ("size-changed",
|
||||||
G_TYPE_FROM_CLASS (gobject_class),
|
G_TYPE_FROM_CLASS (gobject_class),
|
||||||
G_SIGNAL_RUN_LAST,
|
G_SIGNAL_RUN_LAST,
|
||||||
@ -161,40 +144,30 @@ meta_shaped_texture_init (MetaShapedTexture *stex)
|
|||||||
{
|
{
|
||||||
stex->paint_tower = meta_texture_tower_new ();
|
stex->paint_tower = meta_texture_tower_new ();
|
||||||
|
|
||||||
|
stex->buffer_scale = 1;
|
||||||
stex->texture = NULL;
|
stex->texture = NULL;
|
||||||
stex->mask_texture = NULL;
|
stex->mask_texture = NULL;
|
||||||
stex->create_mipmaps = TRUE;
|
stex->create_mipmaps = TRUE;
|
||||||
stex->is_y_inverted = TRUE;
|
stex->is_y_inverted = TRUE;
|
||||||
stex->transform = META_MONITOR_TRANSFORM_NORMAL;
|
stex->transform = META_MONITOR_TRANSFORM_NORMAL;
|
||||||
|
|
||||||
g_signal_connect (stex,
|
|
||||||
"notify::scale-x",
|
|
||||||
G_CALLBACK (invalidate_size),
|
|
||||||
stex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
update_size (MetaShapedTexture *stex)
|
update_size (MetaShapedTexture *stex)
|
||||||
{
|
{
|
||||||
ClutterActor *actor = CLUTTER_ACTOR (stex);
|
int buffer_scale = stex->buffer_scale;
|
||||||
int dst_width;
|
int dst_width;
|
||||||
int dst_height;
|
int dst_height;
|
||||||
|
|
||||||
if (stex->has_viewport_dst_size)
|
if (stex->has_viewport_dst_size)
|
||||||
{
|
{
|
||||||
double tex_scale;
|
dst_width = stex->viewport_dst_width;
|
||||||
|
dst_height = stex->viewport_dst_height;
|
||||||
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)
|
else if (stex->has_viewport_src_rect)
|
||||||
{
|
{
|
||||||
double tex_scale;
|
dst_width = stex->viewport_src_rect.size.width;
|
||||||
|
dst_height = stex->viewport_src_rect.size.height;
|
||||||
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
|
else
|
||||||
{
|
{
|
||||||
@ -202,26 +175,26 @@ update_size (MetaShapedTexture *stex)
|
|||||||
{
|
{
|
||||||
if (stex->texture)
|
if (stex->texture)
|
||||||
{
|
{
|
||||||
dst_width = stex->tex_height;
|
dst_width = stex->tex_height / buffer_scale;
|
||||||
dst_height = stex->tex_width;
|
dst_height = stex->tex_width / buffer_scale;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
dst_width = stex->fallback_height;
|
dst_width = stex->fallback_height / buffer_scale;
|
||||||
dst_height = stex->fallback_width;
|
dst_height = stex->fallback_width / buffer_scale;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (stex->texture)
|
if (stex->texture)
|
||||||
{
|
{
|
||||||
dst_width = stex->tex_width;
|
dst_width = stex->tex_width / buffer_scale;
|
||||||
dst_height = stex->tex_height;
|
dst_height = stex->tex_height / buffer_scale;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
dst_width = stex->fallback_width;
|
dst_width = stex->fallback_width / buffer_scale;
|
||||||
dst_height = stex->fallback_height;
|
dst_height = stex->fallback_height / buffer_scale;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -234,7 +207,7 @@ update_size (MetaShapedTexture *stex)
|
|||||||
stex->dst_width = dst_width;
|
stex->dst_width = dst_width;
|
||||||
stex->dst_height = dst_height;
|
stex->dst_height = dst_height;
|
||||||
meta_shaped_texture_set_mask_texture (stex, NULL);
|
meta_shaped_texture_set_mask_texture (stex, NULL);
|
||||||
clutter_actor_queue_relayout (CLUTTER_ACTOR (stex));
|
clutter_content_invalidate_size (CLUTTER_CONTENT (stex));
|
||||||
g_signal_emit (stex, signals[SIZE_CHANGED], 0);
|
g_signal_emit (stex, signals[SIZE_CHANGED], 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -377,27 +350,25 @@ get_base_pipeline (MetaShapedTexture *stex,
|
|||||||
|
|
||||||
if (stex->has_viewport_src_rect)
|
if (stex->has_viewport_src_rect)
|
||||||
{
|
{
|
||||||
ClutterActor *actor = CLUTTER_ACTOR (stex);
|
float scaled_tex_width = stex->tex_width / (float) stex->buffer_scale;
|
||||||
double tex_scale;
|
float scaled_tex_height = stex->tex_height / (float) stex->buffer_scale;
|
||||||
|
|
||||||
clutter_actor_get_scale (actor, &tex_scale, NULL);
|
|
||||||
|
|
||||||
if (meta_monitor_transform_is_rotated (stex->transform))
|
if (meta_monitor_transform_is_rotated (stex->transform))
|
||||||
{
|
{
|
||||||
cogl_matrix_scale (&matrix,
|
cogl_matrix_scale (&matrix,
|
||||||
stex->viewport_src_rect.size.width /
|
stex->viewport_src_rect.size.width /
|
||||||
(stex->tex_height * tex_scale),
|
scaled_tex_height,
|
||||||
stex->viewport_src_rect.size.height /
|
stex->viewport_src_rect.size.height /
|
||||||
(stex->tex_width * tex_scale),
|
scaled_tex_width,
|
||||||
1);
|
1);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
cogl_matrix_scale (&matrix,
|
cogl_matrix_scale (&matrix,
|
||||||
stex->viewport_src_rect.size.width /
|
stex->viewport_src_rect.size.width /
|
||||||
(stex->tex_width * tex_scale),
|
scaled_tex_width,
|
||||||
stex->viewport_src_rect.size.height /
|
stex->viewport_src_rect.size.height /
|
||||||
(stex->tex_height * tex_scale),
|
scaled_tex_height,
|
||||||
1);
|
1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -469,21 +440,17 @@ get_unblended_pipeline (MetaShapedTexture *stex,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
paint_clipped_rectangle (MetaShapedTexture *stex,
|
paint_clipped_rectangle_node (MetaShapedTexture *stex,
|
||||||
CoglFramebuffer *fb,
|
ClutterPaintNode *root_node,
|
||||||
CoglPipeline *pipeline,
|
CoglPipeline *pipeline,
|
||||||
cairo_rectangle_int_t *rect,
|
cairo_rectangle_int_t *rect,
|
||||||
ClutterActorBox *alloc)
|
ClutterActorBox *alloc)
|
||||||
{
|
{
|
||||||
|
g_autoptr (ClutterPaintNode) node = NULL;
|
||||||
float coords[8];
|
float coords[8];
|
||||||
float x1, y1, x2, y2;
|
|
||||||
float alloc_width;
|
float alloc_width;
|
||||||
float alloc_height;
|
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_width = alloc->x2 - alloc->x1;
|
||||||
alloc_height = alloc->y2 - alloc->y1;
|
alloc_height = alloc->y2 - alloc->y1;
|
||||||
|
|
||||||
@ -497,9 +464,18 @@ paint_clipped_rectangle (MetaShapedTexture *stex,
|
|||||||
coords[6] = coords[2];
|
coords[6] = coords[2];
|
||||||
coords[7] = coords[3];
|
coords[7] = coords[3];
|
||||||
|
|
||||||
cogl_framebuffer_draw_multitextured_rectangle (fb, pipeline,
|
node = clutter_pipeline_node_new (pipeline);
|
||||||
x1, y1, x2, y2,
|
clutter_paint_node_set_name (node, "MetaShapedTexture (clipped)");
|
||||||
&coords[0], 8);
|
clutter_paint_node_add_child (root_node, node);
|
||||||
|
|
||||||
|
clutter_paint_node_add_multitexture_rectangle (node,
|
||||||
|
&(ClutterActorBox) {
|
||||||
|
.x1 = rect->x,
|
||||||
|
.x2 = rect->x + rect->width,
|
||||||
|
.y1 = rect->y,
|
||||||
|
.y2 = rect->y + rect->height,
|
||||||
|
},
|
||||||
|
coords, 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -542,6 +518,8 @@ set_cogl_texture (MetaShapedTexture *stex,
|
|||||||
|
|
||||||
if (stex->create_mipmaps)
|
if (stex->create_mipmaps)
|
||||||
meta_texture_tower_set_base_texture (stex->paint_tower, cogl_tex);
|
meta_texture_tower_set_base_texture (stex->paint_tower, cogl_tex);
|
||||||
|
|
||||||
|
clutter_content_invalidate (CLUTTER_CONTENT (stex));
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
@ -552,39 +530,47 @@ texture_is_idle_and_not_mipmapped (gpointer user_data)
|
|||||||
if ((g_get_monotonic_time () - stex->earliest_remipmap) < 0)
|
if ((g_get_monotonic_time () - stex->earliest_remipmap) < 0)
|
||||||
return G_SOURCE_CONTINUE;
|
return G_SOURCE_CONTINUE;
|
||||||
|
|
||||||
clutter_actor_queue_redraw (CLUTTER_ACTOR (stex));
|
clutter_content_invalidate (CLUTTER_CONTENT (stex));
|
||||||
stex->remipmap_timeout_id = 0;
|
stex->remipmap_timeout_id = 0;
|
||||||
|
|
||||||
return G_SOURCE_REMOVE;
|
return G_SOURCE_REMOVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static cairo_region_t *
|
||||||
do_paint (MetaShapedTexture *stex,
|
effective_unobscured_region (MetaShapedTexture *stex)
|
||||||
CoglFramebuffer *fb,
|
{
|
||||||
CoglTexture *paint_tex,
|
return stex->unobscured_region;
|
||||||
cairo_region_t *clip_region)
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
do_paint_content (MetaShapedTexture *stex,
|
||||||
|
ClutterPaintNode *root_node,
|
||||||
|
CoglTexture *paint_tex,
|
||||||
|
ClutterActorBox *alloc,
|
||||||
|
uint8_t opacity)
|
||||||
|
|
||||||
{
|
{
|
||||||
double tex_scale;
|
|
||||||
int dst_width, dst_height;
|
int dst_width, dst_height;
|
||||||
cairo_rectangle_int_t tex_rect;
|
cairo_rectangle_int_t content_rect;
|
||||||
guchar opacity;
|
|
||||||
gboolean use_opaque_region;
|
gboolean use_opaque_region;
|
||||||
cairo_region_t *clip_tex_region;
|
|
||||||
cairo_region_t *opaque_tex_region;
|
|
||||||
cairo_region_t *blended_tex_region;
|
cairo_region_t *blended_tex_region;
|
||||||
CoglContext *ctx;
|
CoglContext *ctx;
|
||||||
ClutterActorBox alloc;
|
|
||||||
CoglPipelineFilter filter;
|
CoglPipelineFilter filter;
|
||||||
|
|
||||||
clutter_actor_get_scale (CLUTTER_ACTOR (stex), &tex_scale, NULL);
|
|
||||||
ensure_size_valid (stex);
|
ensure_size_valid (stex);
|
||||||
dst_width = stex->dst_width;
|
|
||||||
|
|
||||||
|
dst_width = stex->dst_width;
|
||||||
dst_height = stex->dst_height;
|
dst_height = stex->dst_height;
|
||||||
|
|
||||||
if (dst_width == 0 || dst_height == 0) /* no contents yet */
|
if (dst_width == 0 || dst_height == 0) /* no contents yet */
|
||||||
return;
|
return;
|
||||||
|
|
||||||
tex_rect = (cairo_rectangle_int_t) { 0, 0, dst_width, dst_height };
|
content_rect = (cairo_rectangle_int_t) {
|
||||||
|
.x = 0,
|
||||||
|
.y = 0,
|
||||||
|
.width = dst_width,
|
||||||
|
.height = dst_height,
|
||||||
|
};
|
||||||
|
|
||||||
/* Use nearest-pixel interpolation if the texture is unscaled. This
|
/* Use nearest-pixel interpolation if the texture is unscaled. This
|
||||||
* improves performance, especially with software rendering.
|
* improves performance, especially with software rendering.
|
||||||
@ -592,55 +578,28 @@ do_paint (MetaShapedTexture *stex,
|
|||||||
|
|
||||||
filter = COGL_PIPELINE_FILTER_LINEAR;
|
filter = COGL_PIPELINE_FILTER_LINEAR;
|
||||||
|
|
||||||
if (meta_actor_painting_untransformed (fb,
|
if (meta_actor_painting_untransformed (clutter_paint_node_get_framebuffer (root_node),
|
||||||
dst_width, dst_height,
|
dst_width, dst_height,
|
||||||
NULL, NULL))
|
NULL, NULL))
|
||||||
filter = COGL_PIPELINE_FILTER_NEAREST;
|
filter = COGL_PIPELINE_FILTER_NEAREST;
|
||||||
|
|
||||||
ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
|
ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
|
||||||
|
|
||||||
opacity = clutter_actor_get_paint_opacity (CLUTTER_ACTOR (stex));
|
use_opaque_region = stex->opaque_region && opacity == 255;
|
||||||
clutter_actor_get_allocation_box (CLUTTER_ACTOR (stex), &alloc);
|
|
||||||
|
|
||||||
if (stex->opaque_region && opacity == 255)
|
|
||||||
{
|
|
||||||
opaque_tex_region =
|
|
||||||
meta_region_scale_double (stex->opaque_region,
|
|
||||||
1.0 / tex_scale,
|
|
||||||
META_ROUNDING_STRATEGY_SHRINK);
|
|
||||||
use_opaque_region = TRUE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
opaque_tex_region = NULL;
|
|
||||||
use_opaque_region = FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (clip_region)
|
|
||||||
{
|
|
||||||
clip_tex_region =
|
|
||||||
meta_region_scale_double (clip_region,
|
|
||||||
1.0 / tex_scale,
|
|
||||||
META_ROUNDING_STRATEGY_GROW);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
clip_tex_region = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (use_opaque_region)
|
if (use_opaque_region)
|
||||||
{
|
{
|
||||||
if (clip_tex_region)
|
if (stex->clip_region)
|
||||||
blended_tex_region = cairo_region_copy (clip_tex_region);
|
blended_tex_region = cairo_region_copy (stex->clip_region);
|
||||||
else
|
else
|
||||||
blended_tex_region = cairo_region_create_rectangle (&tex_rect);
|
blended_tex_region = cairo_region_create_rectangle (&content_rect);
|
||||||
|
|
||||||
cairo_region_subtract (blended_tex_region, opaque_tex_region);
|
cairo_region_subtract (blended_tex_region, stex->opaque_region);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (clip_tex_region)
|
if (stex->clip_region)
|
||||||
blended_tex_region = cairo_region_reference (clip_tex_region);
|
blended_tex_region = cairo_region_reference (stex->clip_region);
|
||||||
else
|
else
|
||||||
blended_tex_region = NULL;
|
blended_tex_region = NULL;
|
||||||
}
|
}
|
||||||
@ -664,23 +623,24 @@ do_paint (MetaShapedTexture *stex,
|
|||||||
/* First, paint the unblended parts, which are part of the opaque region. */
|
/* First, paint the unblended parts, which are part of the opaque region. */
|
||||||
if (use_opaque_region)
|
if (use_opaque_region)
|
||||||
{
|
{
|
||||||
CoglPipeline *opaque_pipeline;
|
|
||||||
cairo_region_t *region;
|
cairo_region_t *region;
|
||||||
int n_rects;
|
int n_rects;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (clip_tex_region)
|
if (stex->clip_region)
|
||||||
{
|
{
|
||||||
region = cairo_region_copy (clip_tex_region);
|
region = cairo_region_copy (stex->clip_region);
|
||||||
cairo_region_intersect (region, opaque_tex_region);
|
cairo_region_intersect (region, stex->opaque_region);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
region = cairo_region_reference (opaque_tex_region);
|
region = cairo_region_reference (stex->opaque_region);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!cairo_region_is_empty (region))
|
if (!cairo_region_is_empty (region))
|
||||||
{
|
{
|
||||||
|
CoglPipeline *opaque_pipeline;
|
||||||
|
|
||||||
opaque_pipeline = get_unblended_pipeline (stex, ctx);
|
opaque_pipeline = get_unblended_pipeline (stex, ctx);
|
||||||
cogl_pipeline_set_layer_texture (opaque_pipeline, 0, paint_tex);
|
cogl_pipeline_set_layer_texture (opaque_pipeline, 0, paint_tex);
|
||||||
cogl_pipeline_set_layer_filters (opaque_pipeline, 0, filter, filter);
|
cogl_pipeline_set_layer_filters (opaque_pipeline, 0, filter, filter);
|
||||||
@ -690,11 +650,9 @@ do_paint (MetaShapedTexture *stex,
|
|||||||
{
|
{
|
||||||
cairo_rectangle_int_t rect;
|
cairo_rectangle_int_t rect;
|
||||||
cairo_region_get_rectangle (region, i, &rect);
|
cairo_region_get_rectangle (region, i, &rect);
|
||||||
paint_clipped_rectangle (stex,
|
paint_clipped_rectangle_node (stex, root_node,
|
||||||
fb,
|
|
||||||
opaque_pipeline,
|
opaque_pipeline,
|
||||||
&rect,
|
&rect, alloc);
|
||||||
&alloc);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -744,47 +702,83 @@ do_paint (MetaShapedTexture *stex,
|
|||||||
cairo_rectangle_int_t rect;
|
cairo_rectangle_int_t rect;
|
||||||
cairo_region_get_rectangle (blended_tex_region, i, &rect);
|
cairo_region_get_rectangle (blended_tex_region, i, &rect);
|
||||||
|
|
||||||
if (!gdk_rectangle_intersect (&tex_rect, &rect, &rect))
|
if (!gdk_rectangle_intersect (&content_rect, &rect, &rect))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
paint_clipped_rectangle (stex,
|
paint_clipped_rectangle_node (stex, root_node,
|
||||||
fb,
|
|
||||||
blended_pipeline,
|
blended_pipeline,
|
||||||
&rect,
|
&rect, alloc);
|
||||||
&alloc);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
g_autoptr (ClutterPaintNode) node = NULL;
|
||||||
|
|
||||||
|
node = clutter_pipeline_node_new (blended_pipeline);
|
||||||
|
clutter_paint_node_set_name (node, "MetaShapedTexture (unclipped)");
|
||||||
|
clutter_paint_node_add_child (root_node, node);
|
||||||
|
|
||||||
/* 3) blended_tex_region is NULL. Do a full paint. */
|
/* 3) blended_tex_region is NULL. Do a full paint. */
|
||||||
cogl_framebuffer_draw_rectangle (fb, blended_pipeline,
|
clutter_paint_node_add_rectangle (node, alloc);
|
||||||
0, 0,
|
|
||||||
alloc.x2 - alloc.x1,
|
|
||||||
alloc.y2 - alloc.y1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
g_clear_pointer (&clip_tex_region, cairo_region_destroy);
|
|
||||||
g_clear_pointer (&opaque_tex_region, cairo_region_destroy);
|
|
||||||
g_clear_pointer (&blended_tex_region, cairo_region_destroy);
|
g_clear_pointer (&blended_tex_region, cairo_region_destroy);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static CoglTexture *
|
||||||
meta_shaped_texture_paint (ClutterActor *actor)
|
select_texture_for_paint (MetaShapedTexture *stex)
|
||||||
{
|
{
|
||||||
MetaShapedTexture *stex = META_SHAPED_TEXTURE (actor);
|
CoglTexture *texture = NULL;
|
||||||
CoglTexture *paint_tex;
|
int64_t now;
|
||||||
CoglFramebuffer *fb;
|
|
||||||
|
|
||||||
if (!stex->texture)
|
if (!stex->texture)
|
||||||
return;
|
return NULL;
|
||||||
|
|
||||||
|
now = g_get_monotonic_time ();
|
||||||
|
|
||||||
|
if (stex->create_mipmaps && stex->last_invalidation)
|
||||||
|
{
|
||||||
|
int64_t age = now - stex->last_invalidation;
|
||||||
|
|
||||||
|
if (age >= MIN_MIPMAP_AGE_USEC ||
|
||||||
|
stex->fast_updates < MIN_FAST_UPDATES_BEFORE_UNMIPMAP)
|
||||||
|
texture = meta_texture_tower_get_paint_texture (stex->paint_tower);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!texture)
|
||||||
|
{
|
||||||
|
texture = stex->texture;
|
||||||
|
|
||||||
|
if (stex->create_mipmaps)
|
||||||
|
{
|
||||||
|
/* Minus 1000 to ensure we don't fail the age test in timeout */
|
||||||
|
stex->earliest_remipmap = now + MIN_MIPMAP_AGE_USEC - 1000;
|
||||||
|
|
||||||
|
if (!stex->remipmap_timeout_id)
|
||||||
|
stex->remipmap_timeout_id =
|
||||||
|
g_timeout_add (MIN_MIPMAP_AGE_USEC / 1000,
|
||||||
|
texture_is_idle_and_not_mipmapped,
|
||||||
|
stex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return texture;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_shaped_texture_paint_content (ClutterContent *content,
|
||||||
|
ClutterActor *actor,
|
||||||
|
ClutterPaintNode *root_node)
|
||||||
|
{
|
||||||
|
MetaShapedTexture *stex = META_SHAPED_TEXTURE (content);
|
||||||
|
ClutterActorBox alloc;
|
||||||
|
CoglTexture *paint_tex = NULL;
|
||||||
|
uint8_t opacity;
|
||||||
|
|
||||||
if (stex->clip_region && cairo_region_is_empty (stex->clip_region))
|
if (stex->clip_region && cairo_region_is_empty (stex->clip_region))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!CLUTTER_ACTOR_IS_REALIZED (CLUTTER_ACTOR (stex)))
|
|
||||||
clutter_actor_realize (CLUTTER_ACTOR (stex));
|
|
||||||
|
|
||||||
/* The GL EXT_texture_from_pixmap extension does allow for it to be
|
/* The GL EXT_texture_from_pixmap extension does allow for it to be
|
||||||
* used together with SGIS_generate_mipmap, however this is very
|
* used together with SGIS_generate_mipmap, however this is very
|
||||||
* rarely supported. Also, even when it is supported there
|
* rarely supported. Also, even when it is supported there
|
||||||
@ -800,100 +794,39 @@ meta_shaped_texture_paint (ClutterActor *actor)
|
|||||||
* Setting the texture quality to high without SGIS_generate_mipmap
|
* Setting the texture quality to high without SGIS_generate_mipmap
|
||||||
* support for TFP textures will result in fallbacks to XGetImage.
|
* support for TFP textures will result in fallbacks to XGetImage.
|
||||||
*/
|
*/
|
||||||
if (stex->create_mipmaps)
|
paint_tex = select_texture_for_paint (stex);
|
||||||
{
|
|
||||||
int64_t now = g_get_monotonic_time ();
|
|
||||||
int64_t age = now - stex->last_invalidation;
|
|
||||||
|
|
||||||
if (age >= MIN_MIPMAP_AGE_USEC ||
|
|
||||||
stex->fast_updates < MIN_FAST_UPDATES_BEFORE_UNMIPMAP)
|
|
||||||
{
|
|
||||||
paint_tex = meta_texture_tower_get_paint_texture (stex->paint_tower);
|
|
||||||
if (!paint_tex)
|
if (!paint_tex)
|
||||||
paint_tex = stex->texture;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
paint_tex = stex->texture;
|
|
||||||
|
|
||||||
/* Minus 1000 to ensure we don't fail the age test in timeout */
|
|
||||||
stex->earliest_remipmap = now + MIN_MIPMAP_AGE_USEC - 1000;
|
|
||||||
|
|
||||||
if (!stex->remipmap_timeout_id)
|
|
||||||
stex->remipmap_timeout_id =
|
|
||||||
g_timeout_add (MIN_MIPMAP_AGE_USEC / 1000,
|
|
||||||
texture_is_idle_and_not_mipmapped,
|
|
||||||
stex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
paint_tex = COGL_TEXTURE (stex->texture);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cogl_texture_get_width (paint_tex) == 0 ||
|
|
||||||
cogl_texture_get_height (paint_tex) == 0)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
fb = cogl_get_draw_framebuffer ();
|
opacity = clutter_actor_get_paint_opacity (actor);
|
||||||
do_paint (META_SHAPED_TEXTURE (actor), fb, paint_tex, stex->clip_region);
|
clutter_actor_get_content_box (actor, &alloc);
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
do_paint_content (stex, root_node, paint_tex, &alloc, opacity);
|
||||||
meta_shaped_texture_get_preferred_width (ClutterActor *self,
|
|
||||||
gfloat for_height,
|
|
||||||
gfloat *min_width_p,
|
|
||||||
gfloat *natural_width_p)
|
|
||||||
{
|
|
||||||
MetaShapedTexture *stex = META_SHAPED_TEXTURE (self);
|
|
||||||
|
|
||||||
ensure_size_valid (stex);
|
|
||||||
|
|
||||||
if (min_width_p)
|
|
||||||
*min_width_p = stex->dst_width;
|
|
||||||
if (natural_width_p)
|
|
||||||
*natural_width_p = stex->dst_width;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
meta_shaped_texture_get_preferred_height (ClutterActor *self,
|
|
||||||
gfloat for_width,
|
|
||||||
gfloat *min_height_p,
|
|
||||||
gfloat *natural_height_p)
|
|
||||||
{
|
|
||||||
MetaShapedTexture *stex = META_SHAPED_TEXTURE (self);
|
|
||||||
|
|
||||||
ensure_size_valid (stex);
|
|
||||||
|
|
||||||
if (min_height_p)
|
|
||||||
*min_height_p = stex->dst_height;
|
|
||||||
if (natural_height_p)
|
|
||||||
*natural_height_p = stex->dst_height;
|
|
||||||
}
|
|
||||||
|
|
||||||
static cairo_region_t *
|
|
||||||
effective_unobscured_region (MetaShapedTexture *stex)
|
|
||||||
{
|
|
||||||
ClutterActor *actor;
|
|
||||||
|
|
||||||
/* Fail if we have any mapped clones. */
|
|
||||||
actor = CLUTTER_ACTOR (stex);
|
|
||||||
do
|
|
||||||
{
|
|
||||||
if (clutter_actor_has_mapped_clones (actor))
|
|
||||||
return NULL;
|
|
||||||
actor = clutter_actor_get_parent (actor);
|
|
||||||
}
|
|
||||||
while (actor != NULL);
|
|
||||||
|
|
||||||
return stex->unobscured_region;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
meta_shaped_texture_get_paint_volume (ClutterActor *actor,
|
meta_shaped_texture_get_preferred_size (ClutterContent *content,
|
||||||
ClutterPaintVolume *volume)
|
float *width,
|
||||||
|
float *height)
|
||||||
{
|
{
|
||||||
return clutter_paint_volume_set_from_allocation (volume, actor);
|
MetaShapedTexture *stex = META_SHAPED_TEXTURE (content);
|
||||||
|
|
||||||
|
ensure_size_valid (stex);
|
||||||
|
|
||||||
|
if (width)
|
||||||
|
*width = stex->dst_width;
|
||||||
|
|
||||||
|
if (height)
|
||||||
|
*height = stex->dst_height;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
clutter_content_iface_init (ClutterContentInterface *iface)
|
||||||
|
{
|
||||||
|
iface->paint_content = meta_shaped_texture_paint_content;
|
||||||
|
iface->get_preferred_size = meta_shaped_texture_get_preferred_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -927,7 +860,7 @@ meta_shaped_texture_set_mask_texture (MetaShapedTexture *stex,
|
|||||||
cogl_object_ref (stex->mask_texture);
|
cogl_object_ref (stex->mask_texture);
|
||||||
}
|
}
|
||||||
|
|
||||||
clutter_actor_queue_redraw (CLUTTER_ACTOR (stex));
|
clutter_content_invalidate (CLUTTER_CONTENT (stex));
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
@ -987,14 +920,11 @@ meta_shaped_texture_update_area (MetaShapedTexture *stex,
|
|||||||
{
|
{
|
||||||
ClutterRect viewport;
|
ClutterRect viewport;
|
||||||
ClutterRect inverted_viewport;
|
ClutterRect inverted_viewport;
|
||||||
double tex_scale;
|
|
||||||
float dst_width;
|
float dst_width;
|
||||||
float dst_height;
|
float dst_height;
|
||||||
int inverted_dst_width;
|
int inverted_dst_width;
|
||||||
int inverted_dst_height;
|
int inverted_dst_height;
|
||||||
|
|
||||||
clutter_actor_get_scale (CLUTTER_ACTOR (stex), &tex_scale, NULL);
|
|
||||||
|
|
||||||
if (stex->has_viewport_src_rect)
|
if (stex->has_viewport_src_rect)
|
||||||
{
|
{
|
||||||
viewport = stex->viewport_src_rect;
|
viewport = stex->viewport_src_rect;
|
||||||
@ -1004,8 +934,8 @@ meta_shaped_texture_update_area (MetaShapedTexture *stex,
|
|||||||
viewport = (ClutterRect) {
|
viewport = (ClutterRect) {
|
||||||
.origin.x = 0,
|
.origin.x = 0,
|
||||||
.origin.y = 0,
|
.origin.y = 0,
|
||||||
.size.width = stex->tex_width * tex_scale,
|
.size.width = stex->tex_width,
|
||||||
.size.height = stex->tex_height * tex_scale
|
.size.height = stex->tex_height,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1016,13 +946,13 @@ meta_shaped_texture_update_area (MetaShapedTexture *stex,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
dst_width = (float) stex->tex_width * tex_scale;
|
dst_width = (float) stex->tex_width;
|
||||||
dst_height = (float) stex->tex_height * tex_scale;
|
dst_height = (float) stex->tex_height;
|
||||||
}
|
}
|
||||||
|
|
||||||
inverted_viewport = (ClutterRect) {
|
inverted_viewport = (ClutterRect) {
|
||||||
.origin.x = -((viewport.origin.x * (dst_width / viewport.size.width)) / tex_scale),
|
.origin.x = -(viewport.origin.x * (dst_width / viewport.size.width)),
|
||||||
.origin.y = -((viewport.origin.y * (dst_height / viewport.size.height)) / tex_scale),
|
.origin.y = -(viewport.origin.y * (dst_height / viewport.size.height)),
|
||||||
.size.width = dst_width,
|
.size.width = dst_width,
|
||||||
.size.height = dst_height
|
.size.height = dst_height
|
||||||
};
|
};
|
||||||
@ -1037,10 +967,10 @@ meta_shaped_texture_update_area (MetaShapedTexture *stex,
|
|||||||
}
|
}
|
||||||
|
|
||||||
meta_texture_tower_update_area (stex->paint_tower,
|
meta_texture_tower_update_area (stex->paint_tower,
|
||||||
clip.x,
|
x,
|
||||||
clip.y,
|
y,
|
||||||
clip.width,
|
width,
|
||||||
clip.height);
|
height);
|
||||||
|
|
||||||
stex->prev_invalidation = stex->last_invalidation;
|
stex->prev_invalidation = stex->last_invalidation;
|
||||||
stex->last_invalidation = g_get_monotonic_time ();
|
stex->last_invalidation = g_get_monotonic_time ();
|
||||||
@ -1059,6 +989,8 @@ meta_shaped_texture_update_area (MetaShapedTexture *stex,
|
|||||||
unobscured_region = effective_unobscured_region (stex);
|
unobscured_region = effective_unobscured_region (stex);
|
||||||
if (unobscured_region)
|
if (unobscured_region)
|
||||||
{
|
{
|
||||||
|
cairo_rectangle_int_t extents;
|
||||||
|
cairo_region_t *scaled_unobscured_region;
|
||||||
cairo_region_t *intersection;
|
cairo_region_t *intersection;
|
||||||
|
|
||||||
if (cairo_region_is_empty (unobscured_region))
|
if (cairo_region_is_empty (unobscured_region))
|
||||||
@ -1071,7 +1003,7 @@ meta_shaped_texture_update_area (MetaShapedTexture *stex,
|
|||||||
{
|
{
|
||||||
cairo_rectangle_int_t damage_rect;
|
cairo_rectangle_int_t damage_rect;
|
||||||
cairo_region_get_extents (intersection, &damage_rect);
|
cairo_region_get_extents (intersection, &damage_rect);
|
||||||
clutter_actor_queue_redraw_with_clip (CLUTTER_ACTOR (stex), &damage_rect);
|
clutter_content_invalidate (CLUTTER_CONTENT (stex));
|
||||||
cairo_region_destroy (intersection);
|
cairo_region_destroy (intersection);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@ -1081,7 +1013,7 @@ meta_shaped_texture_update_area (MetaShapedTexture *stex,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
clutter_actor_queue_redraw_with_clip (CLUTTER_ACTOR (stex), &clip);
|
clutter_content_invalidate (CLUTTER_CONTENT (stex));
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1274,6 +1206,7 @@ static cairo_surface_t *
|
|||||||
get_image_via_offscreen (MetaShapedTexture *stex,
|
get_image_via_offscreen (MetaShapedTexture *stex,
|
||||||
cairo_rectangle_int_t *clip)
|
cairo_rectangle_int_t *clip)
|
||||||
{
|
{
|
||||||
|
g_autoptr (ClutterPaintNode) root_node = NULL;
|
||||||
ClutterBackend *clutter_backend = clutter_get_default_backend ();
|
ClutterBackend *clutter_backend = clutter_get_default_backend ();
|
||||||
CoglContext *cogl_context =
|
CoglContext *cogl_context =
|
||||||
clutter_backend_get_cogl_context (clutter_backend);
|
clutter_backend_get_cogl_context (clutter_backend);
|
||||||
@ -1283,7 +1216,7 @@ get_image_via_offscreen (MetaShapedTexture *stex,
|
|||||||
CoglFramebuffer *fb;
|
CoglFramebuffer *fb;
|
||||||
CoglMatrix projection_matrix;
|
CoglMatrix projection_matrix;
|
||||||
cairo_rectangle_int_t fallback_clip;
|
cairo_rectangle_int_t fallback_clip;
|
||||||
CoglColor clear_color;
|
ClutterColor clear_color;
|
||||||
cairo_surface_t *surface;
|
cairo_surface_t *surface;
|
||||||
|
|
||||||
if (!clip)
|
if (!clip)
|
||||||
@ -1329,12 +1262,20 @@ get_image_via_offscreen (MetaShapedTexture *stex,
|
|||||||
|
|
||||||
cogl_framebuffer_set_projection_matrix (fb, &projection_matrix);
|
cogl_framebuffer_set_projection_matrix (fb, &projection_matrix);
|
||||||
|
|
||||||
cogl_color_init_from_4ub (&clear_color, 0, 0, 0, 0);
|
clear_color = (ClutterColor) { 0, 0, 0, 0 };
|
||||||
cogl_framebuffer_clear (fb, COGL_BUFFER_BIT_COLOR, &clear_color);
|
|
||||||
|
|
||||||
do_paint (stex, fb, stex->texture, NULL);
|
root_node = clutter_root_node_new (fb, &clear_color, COGL_BUFFER_BIT_COLOR);
|
||||||
|
clutter_paint_node_set_name (root_node, "MetaShapedTexture.offscreen");
|
||||||
|
|
||||||
cogl_framebuffer_pop_matrix (fb);
|
do_paint_content (stex, root_node,
|
||||||
|
stex->texture,
|
||||||
|
&(ClutterActorBox) {
|
||||||
|
clip->x, clip->y,
|
||||||
|
clip->width, clip->height,
|
||||||
|
},
|
||||||
|
255);
|
||||||
|
|
||||||
|
clutter_paint_node_paint (root_node);
|
||||||
|
|
||||||
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
|
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
|
||||||
clip->width, clip->height);
|
clip->width, clip->height);
|
||||||
@ -1386,13 +1327,11 @@ meta_shaped_texture_get_image (MetaShapedTexture *stex,
|
|||||||
|
|
||||||
if (clip != NULL)
|
if (clip != NULL)
|
||||||
{
|
{
|
||||||
double tex_scale;
|
|
||||||
cairo_rectangle_int_t dst_rect;
|
cairo_rectangle_int_t dst_rect;
|
||||||
|
|
||||||
transformed_clip = alloca (sizeof (cairo_rectangle_int_t));
|
transformed_clip = alloca (sizeof (cairo_rectangle_int_t));
|
||||||
|
|
||||||
clutter_actor_get_scale (CLUTTER_ACTOR (stex), &tex_scale, NULL);
|
meta_rectangle_scale_double (clip, stex->buffer_scale,
|
||||||
meta_rectangle_scale_double (clip, 1.0 / tex_scale,
|
|
||||||
META_ROUNDING_STRATEGY_GROW,
|
META_ROUNDING_STRATEGY_GROW,
|
||||||
transformed_clip);
|
transformed_clip);
|
||||||
|
|
||||||
@ -1479,17 +1418,46 @@ meta_shaped_texture_set_fallback_size (MetaShapedTexture *stex,
|
|||||||
invalidate_size (stex);
|
invalidate_size (stex);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
MetaShapedTexture *
|
||||||
meta_shaped_texture_cull_out (MetaCullable *cullable,
|
meta_shaped_texture_new (void)
|
||||||
cairo_region_t *unobscured_region,
|
|
||||||
cairo_region_t *clip_region)
|
|
||||||
{
|
{
|
||||||
MetaShapedTexture *stex = META_SHAPED_TEXTURE (cullable);
|
return g_object_new (META_TYPE_SHAPED_TEXTURE, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_shaped_texture_set_buffer_scale (MetaShapedTexture *stex,
|
||||||
|
int buffer_scale)
|
||||||
|
{
|
||||||
|
g_return_if_fail (META_IS_SHAPED_TEXTURE (stex));
|
||||||
|
|
||||||
|
if (buffer_scale == stex->buffer_scale)
|
||||||
|
return;
|
||||||
|
|
||||||
|
stex->buffer_scale = buffer_scale;
|
||||||
|
|
||||||
|
invalidate_size (stex);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
meta_shaped_texture_get_buffer_scale (MetaShapedTexture *stex)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (META_IS_SHAPED_TEXTURE (stex), 1.0);
|
||||||
|
|
||||||
|
return stex->buffer_scale;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_shaped_texture_cull_out (MetaShapedTexture *stex,
|
||||||
|
cairo_region_t *unobscured_region,
|
||||||
|
cairo_region_t *clip_region,
|
||||||
|
uint8_t opacity)
|
||||||
|
{
|
||||||
|
g_return_if_fail (META_IS_SHAPED_TEXTURE (stex));
|
||||||
|
|
||||||
set_unobscured_region (stex, unobscured_region);
|
set_unobscured_region (stex, unobscured_region);
|
||||||
set_clip_region (stex, clip_region);
|
set_clip_region (stex, clip_region);
|
||||||
|
|
||||||
if (clutter_actor_get_paint_opacity (CLUTTER_ACTOR (stex)) == 0xff)
|
if (opacity == 0xff)
|
||||||
{
|
{
|
||||||
if (stex->opaque_region)
|
if (stex->opaque_region)
|
||||||
{
|
{
|
||||||
@ -1501,22 +1469,10 @@ meta_shaped_texture_cull_out (MetaCullable *cullable,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
void
|
||||||
meta_shaped_texture_reset_culling (MetaCullable *cullable)
|
meta_shaped_texture_reset_culling (MetaShapedTexture *stex)
|
||||||
{
|
{
|
||||||
MetaShapedTexture *self = META_SHAPED_TEXTURE (cullable);
|
g_return_if_fail (META_IS_SHAPED_TEXTURE (stex));
|
||||||
set_clip_region (self, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
set_clip_region (stex, NULL);
|
||||||
cullable_iface_init (MetaCullableInterface *iface)
|
|
||||||
{
|
|
||||||
iface->cull_out = meta_shaped_texture_cull_out;
|
|
||||||
iface->reset_culling = meta_shaped_texture_reset_culling;
|
|
||||||
}
|
|
||||||
|
|
||||||
ClutterActor *
|
|
||||||
meta_shaped_texture_new (void)
|
|
||||||
{
|
|
||||||
return g_object_new (META_TYPE_SHAPED_TEXTURE, NULL);
|
|
||||||
}
|
}
|
||||||
|
@ -110,54 +110,6 @@ meta_surface_actor_wayland_get_window (MetaSurfaceActor *actor)
|
|||||||
return surface->window;
|
return surface->window;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
meta_surface_actor_wayland_get_preferred_width (ClutterActor *actor,
|
|
||||||
gfloat for_height,
|
|
||||||
gfloat *min_width_p,
|
|
||||||
gfloat *natural_width_p)
|
|
||||||
{
|
|
||||||
MetaSurfaceActorWayland *self = META_SURFACE_ACTOR_WAYLAND (actor);
|
|
||||||
MetaShapedTexture *stex;
|
|
||||||
double scale;
|
|
||||||
|
|
||||||
stex = meta_surface_actor_get_texture (META_SURFACE_ACTOR (self));
|
|
||||||
clutter_actor_get_scale (CLUTTER_ACTOR (stex), &scale, NULL);
|
|
||||||
clutter_actor_get_preferred_width (CLUTTER_ACTOR (stex),
|
|
||||||
for_height,
|
|
||||||
min_width_p,
|
|
||||||
natural_width_p);
|
|
||||||
|
|
||||||
if (min_width_p)
|
|
||||||
*min_width_p *= scale;
|
|
||||||
|
|
||||||
if (natural_width_p)
|
|
||||||
*natural_width_p *= scale;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
meta_surface_actor_wayland_get_preferred_height (ClutterActor *actor,
|
|
||||||
gfloat for_width,
|
|
||||||
gfloat *min_height_p,
|
|
||||||
gfloat *natural_height_p)
|
|
||||||
{
|
|
||||||
MetaSurfaceActorWayland *self = META_SURFACE_ACTOR_WAYLAND (actor);
|
|
||||||
MetaShapedTexture *stex;
|
|
||||||
double scale;
|
|
||||||
|
|
||||||
stex = meta_surface_actor_get_texture (META_SURFACE_ACTOR (self));
|
|
||||||
clutter_actor_get_scale (CLUTTER_ACTOR (stex), NULL, &scale);
|
|
||||||
clutter_actor_get_preferred_height (CLUTTER_ACTOR (stex),
|
|
||||||
for_width,
|
|
||||||
min_height_p,
|
|
||||||
natural_height_p);
|
|
||||||
|
|
||||||
if (min_height_p)
|
|
||||||
*min_height_p *= scale;
|
|
||||||
|
|
||||||
if (natural_height_p)
|
|
||||||
*natural_height_p *= scale;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
meta_surface_actor_wayland_paint (ClutterActor *actor)
|
meta_surface_actor_wayland_paint (ClutterActor *actor)
|
||||||
{
|
{
|
||||||
@ -203,8 +155,6 @@ meta_surface_actor_wayland_class_init (MetaSurfaceActorWaylandClass *klass)
|
|||||||
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
|
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
|
||||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||||
|
|
||||||
actor_class->get_preferred_width = meta_surface_actor_wayland_get_preferred_width;
|
|
||||||
actor_class->get_preferred_height = meta_surface_actor_wayland_get_preferred_height;
|
|
||||||
actor_class->paint = meta_surface_actor_wayland_paint;
|
actor_class->paint = meta_surface_actor_wayland_paint;
|
||||||
|
|
||||||
surface_actor_class->process_damage = meta_surface_actor_wayland_process_damage;
|
surface_actor_class->process_damage = meta_surface_actor_wayland_process_damage;
|
||||||
|
@ -159,13 +159,22 @@ meta_surface_actor_cull_out (MetaCullable *cullable,
|
|||||||
cairo_region_t *unobscured_region,
|
cairo_region_t *unobscured_region,
|
||||||
cairo_region_t *clip_region)
|
cairo_region_t *clip_region)
|
||||||
{
|
{
|
||||||
meta_cullable_cull_out_children (cullable, unobscured_region, clip_region);
|
MetaSurfaceActor *surface_actor = META_SURFACE_ACTOR (cullable);
|
||||||
|
MetaSurfaceActorPrivate *priv =
|
||||||
|
meta_surface_actor_get_instance_private (surface_actor);
|
||||||
|
uint8_t opacity = clutter_actor_get_opacity (CLUTTER_ACTOR (cullable));
|
||||||
|
|
||||||
|
meta_shaped_texture_cull_out (priv->texture, unobscured_region, clip_region, opacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
meta_surface_actor_reset_culling (MetaCullable *cullable)
|
meta_surface_actor_reset_culling (MetaCullable *cullable)
|
||||||
{
|
{
|
||||||
meta_cullable_reset_culling_children (cullable);
|
MetaSurfaceActor *surface_actor = META_SURFACE_ACTOR (cullable);
|
||||||
|
MetaSurfaceActorPrivate *priv =
|
||||||
|
meta_surface_actor_get_instance_private (surface_actor);
|
||||||
|
|
||||||
|
meta_shaped_texture_reset_culling (priv->texture);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -189,10 +198,13 @@ meta_surface_actor_init (MetaSurfaceActor *self)
|
|||||||
MetaSurfaceActorPrivate *priv =
|
MetaSurfaceActorPrivate *priv =
|
||||||
meta_surface_actor_get_instance_private (self);
|
meta_surface_actor_get_instance_private (self);
|
||||||
|
|
||||||
priv->texture = META_SHAPED_TEXTURE (meta_shaped_texture_new ());
|
priv->texture = meta_shaped_texture_new ();
|
||||||
g_signal_connect_object (priv->texture, "size-changed",
|
g_signal_connect_object (priv->texture, "size-changed",
|
||||||
G_CALLBACK (texture_size_changed), self, 0);
|
G_CALLBACK (texture_size_changed), self, 0);
|
||||||
clutter_actor_add_child (CLUTTER_ACTOR (self), CLUTTER_ACTOR (priv->texture));
|
clutter_actor_set_content (CLUTTER_ACTOR (self),
|
||||||
|
CLUTTER_CONTENT (priv->texture));
|
||||||
|
clutter_actor_set_request_mode (CLUTTER_ACTOR (self),
|
||||||
|
CLUTTER_REQUEST_CONTENT_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
cairo_surface_t *
|
cairo_surface_t *
|
||||||
|
@ -833,14 +833,14 @@ meta_window_actor_get_meta_window (MetaWindowActor *self)
|
|||||||
*
|
*
|
||||||
* Return value: (transfer none): the #ClutterActor for the contents
|
* Return value: (transfer none): the #ClutterActor for the contents
|
||||||
*/
|
*/
|
||||||
ClutterActor *
|
MetaShapedTexture *
|
||||||
meta_window_actor_get_texture (MetaWindowActor *self)
|
meta_window_actor_get_texture (MetaWindowActor *self)
|
||||||
{
|
{
|
||||||
MetaWindowActorPrivate *priv =
|
MetaWindowActorPrivate *priv =
|
||||||
meta_window_actor_get_instance_private (self);
|
meta_window_actor_get_instance_private (self);
|
||||||
|
|
||||||
if (priv->surface)
|
if (priv->surface)
|
||||||
return CLUTTER_ACTOR (meta_surface_actor_get_texture (priv->surface));
|
return meta_surface_actor_get_texture (priv->surface);
|
||||||
else
|
else
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -1902,19 +1902,19 @@ meta_window_actor_get_frame_bounds (MetaScreenCastWindow *screen_cast_window,
|
|||||||
MetaShapedTexture *stex;
|
MetaShapedTexture *stex;
|
||||||
MetaRectangle buffer_rect;
|
MetaRectangle buffer_rect;
|
||||||
MetaRectangle frame_rect;
|
MetaRectangle frame_rect;
|
||||||
double scale_x, scale_y;
|
int buffer_scale;
|
||||||
|
|
||||||
stex = meta_surface_actor_get_texture (priv->surface);
|
stex = meta_surface_actor_get_texture (priv->surface);
|
||||||
clutter_actor_get_scale (CLUTTER_ACTOR (stex), &scale_x, &scale_y);
|
buffer_scale = meta_shaped_texture_get_buffer_scale (stex);
|
||||||
|
|
||||||
window = priv->window;
|
window = priv->window;
|
||||||
meta_window_get_buffer_rect (window, &buffer_rect);
|
meta_window_get_buffer_rect (window, &buffer_rect);
|
||||||
meta_window_get_frame_rect (window, &frame_rect);
|
meta_window_get_frame_rect (window, &frame_rect);
|
||||||
|
|
||||||
bounds->x = (int) floor ((frame_rect.x - buffer_rect.x) / scale_x);
|
bounds->x = (int) floor ((frame_rect.x - buffer_rect.x) / (float) buffer_scale);
|
||||||
bounds->y = (int) floor ((frame_rect.y - buffer_rect.y) / scale_y);
|
bounds->y = (int) floor ((frame_rect.y - buffer_rect.y) / (float) buffer_scale);
|
||||||
bounds->width = (int) ceil (frame_rect.width / scale_x);
|
bounds->width = (int) ceil (frame_rect.width / (float) buffer_scale);
|
||||||
bounds->height = (int) ceil (frame_rect.height / scale_y);
|
bounds->height = (int) ceil (frame_rect.height / (float) buffer_scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -1928,7 +1928,6 @@ meta_window_actor_transform_relative_position (MetaScreenCastWindow *screen_cast
|
|||||||
MetaWindowActor *window_actor = META_WINDOW_ACTOR (screen_cast_window);
|
MetaWindowActor *window_actor = META_WINDOW_ACTOR (screen_cast_window);
|
||||||
MetaWindowActorPrivate *priv =
|
MetaWindowActorPrivate *priv =
|
||||||
meta_window_actor_get_instance_private (window_actor);
|
meta_window_actor_get_instance_private (window_actor);
|
||||||
MetaShapedTexture *stex;
|
|
||||||
MetaRectangle bounds;
|
MetaRectangle bounds;
|
||||||
ClutterVertex v1 = { 0.f, }, v2 = { 0.f, };
|
ClutterVertex v1 = { 0.f, }, v2 = { 0.f, };
|
||||||
|
|
||||||
@ -1941,8 +1940,9 @@ meta_window_actor_transform_relative_position (MetaScreenCastWindow *screen_cast
|
|||||||
bounds.y,
|
bounds.y,
|
||||||
bounds.y + bounds.height);
|
bounds.y + bounds.height);
|
||||||
|
|
||||||
stex = meta_surface_actor_get_texture (priv->surface);
|
clutter_actor_apply_transform_to_point (CLUTTER_ACTOR (priv->surface),
|
||||||
clutter_actor_apply_transform_to_point (CLUTTER_ACTOR (stex), &v1, &v2);
|
&v1,
|
||||||
|
&v2);
|
||||||
|
|
||||||
*x_out = (double) v2.x;
|
*x_out = (double) v2.x;
|
||||||
*y_out = (double) v2.y;
|
*y_out = (double) v2.y;
|
||||||
@ -1969,22 +1969,19 @@ meta_window_actor_transform_cursor_position (MetaScreenCastWindow *screen_cast_w
|
|||||||
out_cursor_scale)
|
out_cursor_scale)
|
||||||
{
|
{
|
||||||
MetaShapedTexture *stex;
|
MetaShapedTexture *stex;
|
||||||
double actor_scale;
|
double texture_scale;
|
||||||
float cursor_texture_scale;
|
float cursor_texture_scale;
|
||||||
|
|
||||||
stex = meta_surface_actor_get_texture (priv->surface);
|
stex = meta_surface_actor_get_texture (priv->surface);
|
||||||
clutter_actor_get_scale (CLUTTER_ACTOR (stex), &actor_scale, NULL);
|
texture_scale = meta_shaped_texture_get_buffer_scale (stex);
|
||||||
cursor_texture_scale = meta_cursor_sprite_get_texture_scale (cursor_sprite);
|
cursor_texture_scale = meta_cursor_sprite_get_texture_scale (cursor_sprite);
|
||||||
|
|
||||||
*out_cursor_scale = actor_scale / cursor_texture_scale;
|
*out_cursor_scale = texture_scale / cursor_texture_scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (out_relative_cursor_position)
|
if (out_relative_cursor_position)
|
||||||
{
|
{
|
||||||
MetaShapedTexture *stex;
|
clutter_actor_transform_stage_point (CLUTTER_ACTOR (priv->surface),
|
||||||
|
|
||||||
stex = meta_surface_actor_get_texture (priv->surface);
|
|
||||||
clutter_actor_transform_stage_point (CLUTTER_ACTOR (stex),
|
|
||||||
cursor_position->x,
|
cursor_position->x,
|
||||||
cursor_position->y,
|
cursor_position->y,
|
||||||
&out_relative_cursor_position->x,
|
&out_relative_cursor_position->x,
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
|
|
||||||
#include "clutter/clutter.h"
|
#include "clutter/clutter.h"
|
||||||
#include "meta/compositor.h"
|
#include "meta/compositor.h"
|
||||||
|
#include "meta/meta-shaped-texture.h"
|
||||||
|
|
||||||
#define META_TYPE_WINDOW_ACTOR (meta_window_actor_get_type ())
|
#define META_TYPE_WINDOW_ACTOR (meta_window_actor_get_type ())
|
||||||
|
|
||||||
@ -38,7 +39,7 @@ META_EXPORT
|
|||||||
MetaWindow * meta_window_actor_get_meta_window (MetaWindowActor *self);
|
MetaWindow * meta_window_actor_get_meta_window (MetaWindowActor *self);
|
||||||
|
|
||||||
META_EXPORT
|
META_EXPORT
|
||||||
ClutterActor * meta_window_actor_get_texture (MetaWindowActor *self);
|
MetaShapedTexture *meta_window_actor_get_texture (MetaWindowActor *self);
|
||||||
|
|
||||||
META_EXPORT
|
META_EXPORT
|
||||||
void meta_window_actor_sync_visibility (MetaWindowActor *self);
|
void meta_window_actor_sync_visibility (MetaWindowActor *self);
|
||||||
|
@ -154,16 +154,13 @@ meta_wayland_actor_surface_real_sync_actor_state (MetaWaylandActorSurface *actor
|
|||||||
meta_wayland_surface_role_get_surface (surface_role);
|
meta_wayland_surface_role_get_surface (surface_role);
|
||||||
MetaSurfaceActor *surface_actor;
|
MetaSurfaceActor *surface_actor;
|
||||||
MetaShapedTexture *stex;
|
MetaShapedTexture *stex;
|
||||||
double actor_scale;
|
|
||||||
GList *l;
|
GList *l;
|
||||||
cairo_rectangle_int_t surface_rect;
|
cairo_rectangle_int_t surface_rect;
|
||||||
int geometry_scale;
|
int geometry_scale;
|
||||||
|
|
||||||
surface_actor = priv->actor;
|
surface_actor = priv->actor;
|
||||||
stex = meta_surface_actor_get_texture (surface_actor);
|
stex = meta_surface_actor_get_texture (surface_actor);
|
||||||
|
meta_shaped_texture_set_buffer_scale (stex, surface->scale);
|
||||||
actor_scale = meta_wayland_actor_surface_calculate_scale (actor_surface);
|
|
||||||
clutter_actor_set_scale (CLUTTER_ACTOR (stex), actor_scale, actor_scale);
|
|
||||||
|
|
||||||
/* Wayland surface coordinate space -> stage coordinate space */
|
/* Wayland surface coordinate space -> stage coordinate space */
|
||||||
geometry_scale = meta_wayland_actor_surface_get_geometry_scale (actor_surface);
|
geometry_scale = meta_wayland_actor_surface_get_geometry_scale (actor_surface);
|
||||||
|
@ -1197,7 +1197,7 @@ meta_wayland_data_device_start_drag (MetaWaylandDataDevice *data
|
|||||||
|
|
||||||
surface_actor = meta_wayland_surface_get_actor (surface);
|
surface_actor = meta_wayland_surface_get_actor (surface);
|
||||||
|
|
||||||
clutter_actor_transform_stage_point (CLUTTER_ACTOR (meta_surface_actor_get_texture (surface_actor)),
|
clutter_actor_transform_stage_point (CLUTTER_ACTOR (surface_actor),
|
||||||
seat->pointer->grab_x,
|
seat->pointer->grab_x,
|
||||||
seat->pointer->grab_y,
|
seat->pointer->grab_y,
|
||||||
&surface_pos.x, &surface_pos.y);
|
&surface_pos.x, &surface_pos.y);
|
||||||
|
@ -1581,7 +1581,7 @@ meta_wayland_surface_get_relative_coordinates (MetaWaylandSurface *surface,
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
ClutterActor *actor =
|
ClutterActor *actor =
|
||||||
CLUTTER_ACTOR (meta_surface_actor_get_texture (meta_wayland_surface_get_actor (surface)));
|
CLUTTER_ACTOR (meta_wayland_surface_get_actor (surface));
|
||||||
|
|
||||||
clutter_actor_transform_stage_point (actor, abs_x, abs_y, sx, sy);
|
clutter_actor_transform_stage_point (actor, abs_x, abs_y, sx, sy);
|
||||||
*sx /= surface->scale;
|
*sx /= surface->scale;
|
||||||
@ -1597,7 +1597,7 @@ meta_wayland_surface_get_absolute_coordinates (MetaWaylandSurface *surface,
|
|||||||
float *y)
|
float *y)
|
||||||
{
|
{
|
||||||
ClutterActor *actor =
|
ClutterActor *actor =
|
||||||
CLUTTER_ACTOR (meta_surface_actor_get_texture (meta_wayland_surface_get_actor (surface)));
|
CLUTTER_ACTOR (meta_wayland_surface_get_actor (surface));
|
||||||
ClutterVertex sv = {
|
ClutterVertex sv = {
|
||||||
.x = sx * surface->scale,
|
.x = sx * surface->scale,
|
||||||
.y = sy * surface->scale,
|
.y = sy * surface->scale,
|
||||||
|
@ -663,7 +663,7 @@ meta_wayland_tablet_tool_get_relative_coordinates (MetaWaylandTabletTool *tool,
|
|||||||
surface_actor = meta_wayland_surface_get_actor (surface);
|
surface_actor = meta_wayland_surface_get_actor (surface);
|
||||||
|
|
||||||
clutter_event_get_coords (event, &xf, &yf);
|
clutter_event_get_coords (event, &xf, &yf);
|
||||||
clutter_actor_transform_stage_point (CLUTTER_ACTOR (meta_surface_actor_get_texture (surface_actor)),
|
clutter_actor_transform_stage_point (CLUTTER_ACTOR (surface_actor),
|
||||||
xf, yf, &xf, &yf);
|
xf, yf, &xf, &yf);
|
||||||
|
|
||||||
*sx = wl_fixed_from_double (xf) / surface->scale;
|
*sx = wl_fixed_from_double (xf) / surface->scale;
|
||||||
|
Loading…
Reference in New Issue
Block a user