From e1370ee209ddf4b864c7275f0d67d8ab64d59029 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Wed, 19 Dec 2018 12:52:58 +0100 Subject: [PATCH] shaped-texture: Put actual texture painting in helper This is so that it can be reused later by meta_shaped_texture_get_image() for drawing via an offscreen framebuffer. https://gitlab.gnome.org/GNOME/mutter/merge_requests/362 --- src/compositor/meta-shaped-texture.c | 139 +++++++++++++++------------ 1 file changed, 77 insertions(+), 62 deletions(-) diff --git a/src/compositor/meta-shaped-texture.c b/src/compositor/meta-shaped-texture.c index 051421fe8..d2788bd12 100644 --- a/src/compositor/meta-shaped-texture.c +++ b/src/compositor/meta-shaped-texture.c @@ -490,9 +490,11 @@ texture_is_idle_and_not_mipmapped (gpointer user_data) } static void -meta_shaped_texture_paint (ClutterActor *actor) +do_paint (MetaShapedTexture *stex, + CoglFramebuffer *fb, + CoglTexture *paint_tex, + cairo_region_t *clip_region) { - MetaShapedTexture *stex = (MetaShapedTexture *) actor; double tex_scale; int dst_width, dst_height; cairo_rectangle_int_t tex_rect; @@ -502,63 +504,10 @@ meta_shaped_texture_paint (ClutterActor *actor) cairo_region_t *opaque_tex_region; cairo_region_t *blended_tex_region; CoglContext *ctx; - CoglFramebuffer *fb; - CoglTexture *paint_tex = NULL; ClutterActorBox alloc; CoglPipelineFilter filter; - gint64 now = g_get_monotonic_time (); - if (stex->clip_region && cairo_region_is_empty (stex->clip_region)) - 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 - * used together with SGIS_generate_mipmap, however this is very - * rarely supported. Also, even when it is supported there - * are distinct performance implications from: - * - * - Updating mipmaps that we don't need - * - Having to reallocate pixmaps on the server into larger buffers - * - * So, we just unconditionally use our mipmap emulation code. If we - * wanted to use SGIS_generate_mipmap, we'd have to query COGL to - * see if it was supported (no API currently), and then if and only - * if that was the case, set the clutter texture quality to HIGH. - * Setting the texture quality to high without SGIS_generate_mipmap - * support for TFP textures will result in fallbacks to XGetImage. - */ - if (stex->create_mipmaps && stex->last_invalidation) - { - gint64 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 == NULL) - { - paint_tex = COGL_TEXTURE (stex->texture); - - if (paint_tex == NULL) - return; - - 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); - } - } - - clutter_actor_get_scale (actor, &tex_scale, NULL); + clutter_actor_get_scale (CLUTTER_ACTOR (stex), &tex_scale, NULL); ensure_size_valid (stex); dst_width = stex->dst_width; @@ -568,8 +517,6 @@ meta_shaped_texture_paint (ClutterActor *actor) tex_rect = (cairo_rectangle_int_t) { 0, 0, dst_width, dst_height }; - fb = cogl_get_draw_framebuffer (); - /* Use nearest-pixel interpolation if the texture is unscaled. This * improves performance, especially with software rendering. */ @@ -583,8 +530,8 @@ meta_shaped_texture_paint (ClutterActor *actor) ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ()); - opacity = clutter_actor_get_paint_opacity (actor); - clutter_actor_get_allocation_box (actor, &alloc); + opacity = clutter_actor_get_paint_opacity (CLUTTER_ACTOR (stex)); + clutter_actor_get_allocation_box (CLUTTER_ACTOR (stex), &alloc); if (stex->opaque_region && opacity == 255) { @@ -600,10 +547,10 @@ meta_shaped_texture_paint (ClutterActor *actor) use_opaque_region = FALSE; } - if (stex->clip_region) + if (clip_region) { clip_tex_region = - meta_region_scale_double (stex->clip_region, + meta_region_scale_double (clip_region, 1.0 / tex_scale, META_ROUNDING_STRATEGY_GROW); } @@ -745,6 +692,74 @@ meta_shaped_texture_paint (ClutterActor *actor) g_clear_pointer (&blended_tex_region, cairo_region_destroy); } +static void +meta_shaped_texture_paint (ClutterActor *actor) +{ + MetaShapedTexture *stex = META_SHAPED_TEXTURE (actor); + CoglTexture *paint_tex; + CoglFramebuffer *fb; + + if (!stex->texture) + return; + + if (stex->clip_region && cairo_region_is_empty (stex->clip_region)) + 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 + * used together with SGIS_generate_mipmap, however this is very + * rarely supported. Also, even when it is supported there + * are distinct performance implications from: + * + * - Updating mipmaps that we don't need + * - Having to reallocate pixmaps on the server into larger buffers + * + * So, we just unconditionally use our mipmap emulation code. If we + * wanted to use SGIS_generate_mipmap, we'd have to query COGL to + * see if it was supported (no API currently), and then if and only + * if that was the case, set the clutter texture quality to HIGH. + * Setting the texture quality to high without SGIS_generate_mipmap + * support for TFP textures will result in fallbacks to XGetImage. + */ + if (stex->create_mipmaps) + { + 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); + } + 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; + + fb = cogl_get_draw_framebuffer (); + do_paint (META_SHAPED_TEXTURE (actor), fb, paint_tex, stex->clip_region); +} + static void meta_shaped_texture_get_preferred_width (ClutterActor *self, gfloat for_height,