[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
This commit is contained in:
Florian Müllner 2010-08-17 13:30:12 +02:00
parent c3cb0be011
commit 5bd977dd3c

View File

@ -49,7 +49,6 @@ struct _StThemeNodeTransitionPrivate {
ClutterActorBox last_allocation; ClutterActorBox last_allocation;
ClutterActorBox offscreen_box; ClutterActorBox offscreen_box;
guint8 last_opacity;
gboolean needs_setup; gboolean needs_setup;
}; };
@ -200,8 +199,7 @@ calculate_offscreen_box (StThemeNodeTransition *transition,
static gboolean static gboolean
setup_framebuffers (StThemeNodeTransition *transition, setup_framebuffers (StThemeNodeTransition *transition,
const ClutterActorBox *allocation, const ClutterActorBox *allocation)
guint8 paint_opacity)
{ {
StThemeNodeTransitionPrivate *priv = transition->priv; StThemeNodeTransitionPrivate *priv = transition->priv;
CoglColor clear_color = { 0, 0, 0, 0 }; CoglColor clear_color = { 0, 0, 0, 0 };
@ -243,11 +241,17 @@ setup_framebuffers (StThemeNodeTransition *transition,
cogl_handle_unref (priv->material); cogl_handle_unref (priv->material);
priv->material = cogl_material_new (); 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, cogl_material_set_layer_combine (priv->material, 1,
"RGBA = INTERPOLATE (PREVIOUS, " "RGBA = INTERPOLATE (PREVIOUS, "
"TEXTURE, " "TEXTURE, "
"CONSTANT[A])", "CONSTANT[A])",
NULL); 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, 0, priv->new_texture);
cogl_material_set_layer (priv->material, 1, priv->old_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, cogl_ortho (priv->offscreen_box.x1, priv->offscreen_box.x2,
priv->offscreen_box.y2, priv->offscreen_box.y1, priv->offscreen_box.y2, priv->offscreen_box.y1,
0.0, 1.0); 0.0, 1.0);
st_theme_node_paint (priv->old_theme_node, st_theme_node_paint (priv->old_theme_node, allocation, 255);
allocation,
paint_opacity);
cogl_pop_framebuffer (); cogl_pop_framebuffer ();
cogl_push_framebuffer (priv->new_offscreen); cogl_push_framebuffer (priv->new_offscreen);
@ -267,9 +269,7 @@ setup_framebuffers (StThemeNodeTransition *transition,
cogl_ortho (priv->offscreen_box.x1, priv->offscreen_box.x2, cogl_ortho (priv->offscreen_box.x1, priv->offscreen_box.x2,
priv->offscreen_box.y2, priv->offscreen_box.y1, priv->offscreen_box.y2, priv->offscreen_box.y1,
0.0, 1.0); 0.0, 1.0);
st_theme_node_paint (priv->new_theme_node, st_theme_node_paint (priv->new_theme_node, allocation, 255);
allocation,
paint_opacity);
cogl_pop_framebuffer (); cogl_pop_framebuffer ();
return TRUE; 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->old_theme_node));
g_return_if_fail (ST_IS_THEME_NODE (priv->new_theme_node)); g_return_if_fail (ST_IS_THEME_NODE (priv->new_theme_node));
if (!clutter_actor_box_equal (allocation, &priv->last_allocation) || if (!clutter_actor_box_equal (allocation, &priv->last_allocation))
paint_opacity != priv->last_opacity)
priv->needs_setup = TRUE; priv->needs_setup = TRUE;
if (priv->needs_setup) if (priv->needs_setup)
{ {
priv->last_allocation = *allocation; priv->last_allocation = *allocation;
priv->last_opacity = paint_opacity;
calculate_offscreen_box (transition, allocation); calculate_offscreen_box (transition, allocation);
priv->needs_setup = !setup_framebuffers (transition, priv->needs_setup = !setup_framebuffers (transition, allocation);
allocation,
paint_opacity);
} }
cogl_color_set_from_4ub (&constant, 0, 0, 0, cogl_color_set_from_4f (&constant, 0., 0., 0.,
clutter_alpha_get_alpha (priv->alpha) * paint_opacity); clutter_alpha_get_alpha (priv->alpha));
cogl_material_set_layer_combine_constant (priv->material, 1, &constant); 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_set_source (priv->material);
cogl_rectangle_with_multitexture_coords (priv->offscreen_box.x1, cogl_rectangle_with_multitexture_coords (priv->offscreen_box.x1,
priv->offscreen_box.y1, priv->offscreen_box.y1,