From 5bd977dd3c9e6183ed6c5fce9af98b29e661685d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=BCllner?= Date: Tue, 17 Aug 2010 13:30:12 +0200 Subject: [PATCH] [transitions] Do not recreate FBOs on opacity changes Creating an FBO may be expensive, so we should avoid the operation if possible. When transitioning between theme nodes, the widget's opacity is used to paint to the offscreen textures which are blended together - this means that the textures have to be recreated each time the widget's opacity changes. It is much more effective to paint the textures at full opacity and respect the widget's paint opacity when blending the textures together. https://bugzilla.gnome.org/show_bug.cgi?id=627085 --- src/st/st-theme-node-transition.c | 35 +++++++++++++++---------------- 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/src/st/st-theme-node-transition.c b/src/st/st-theme-node-transition.c index 78be9667c..9dbb45c04 100644 --- a/src/st/st-theme-node-transition.c +++ b/src/st/st-theme-node-transition.c @@ -49,7 +49,6 @@ struct _StThemeNodeTransitionPrivate { ClutterActorBox last_allocation; ClutterActorBox offscreen_box; - guint8 last_opacity; gboolean needs_setup; }; @@ -200,8 +199,7 @@ calculate_offscreen_box (StThemeNodeTransition *transition, static gboolean setup_framebuffers (StThemeNodeTransition *transition, - const ClutterActorBox *allocation, - guint8 paint_opacity) + const ClutterActorBox *allocation) { StThemeNodeTransitionPrivate *priv = transition->priv; CoglColor clear_color = { 0, 0, 0, 0 }; @@ -243,11 +241,17 @@ setup_framebuffers (StThemeNodeTransition *transition, cogl_handle_unref (priv->material); priv->material = cogl_material_new (); + cogl_material_set_layer_combine (priv->material, 0, + "RGBA = REPLACE (TEXTURE)", + NULL); cogl_material_set_layer_combine (priv->material, 1, "RGBA = INTERPOLATE (PREVIOUS, " "TEXTURE, " "CONSTANT[A])", NULL); + cogl_material_set_layer_combine (priv->material, 2, + "RGBA = MODULATE (PREVIOUS, PRIMARY)", + NULL); cogl_material_set_layer (priv->material, 0, priv->new_texture); cogl_material_set_layer (priv->material, 1, priv->old_texture); @@ -257,9 +261,7 @@ setup_framebuffers (StThemeNodeTransition *transition, cogl_ortho (priv->offscreen_box.x1, priv->offscreen_box.x2, priv->offscreen_box.y2, priv->offscreen_box.y1, 0.0, 1.0); - st_theme_node_paint (priv->old_theme_node, - allocation, - paint_opacity); + st_theme_node_paint (priv->old_theme_node, allocation, 255); cogl_pop_framebuffer (); cogl_push_framebuffer (priv->new_offscreen); @@ -267,9 +269,7 @@ setup_framebuffers (StThemeNodeTransition *transition, cogl_ortho (priv->offscreen_box.x1, priv->offscreen_box.x2, priv->offscreen_box.y2, priv->offscreen_box.y1, 0.0, 1.0); - st_theme_node_paint (priv->new_theme_node, - allocation, - paint_opacity); + st_theme_node_paint (priv->new_theme_node, allocation, 255); cogl_pop_framebuffer (); return TRUE; @@ -291,26 +291,25 @@ st_theme_node_transition_paint (StThemeNodeTransition *transition, g_return_if_fail (ST_IS_THEME_NODE (priv->old_theme_node)); g_return_if_fail (ST_IS_THEME_NODE (priv->new_theme_node)); - if (!clutter_actor_box_equal (allocation, &priv->last_allocation) || - paint_opacity != priv->last_opacity) + if (!clutter_actor_box_equal (allocation, &priv->last_allocation)) priv->needs_setup = TRUE; if (priv->needs_setup) { priv->last_allocation = *allocation; - priv->last_opacity = paint_opacity; calculate_offscreen_box (transition, allocation); - priv->needs_setup = !setup_framebuffers (transition, - allocation, - paint_opacity); + priv->needs_setup = !setup_framebuffers (transition, allocation); } - cogl_color_set_from_4ub (&constant, 0, 0, 0, - clutter_alpha_get_alpha (priv->alpha) * paint_opacity); - + cogl_color_set_from_4f (&constant, 0., 0., 0., + clutter_alpha_get_alpha (priv->alpha)); cogl_material_set_layer_combine_constant (priv->material, 1, &constant); + cogl_material_set_color4ub (priv->material, + paint_opacity, paint_opacity, + paint_opacity, paint_opacity); + cogl_set_source (priv->material); cogl_rectangle_with_multitexture_coords (priv->offscreen_box.x1, priv->offscreen_box.y1,