st-widget: Cache two paint states
In most cases, we'll transition between two states on hover / focus. Instead of recalculating and repainting our resources on state change, simply cache the last state when we transition. https://bugzilla.gnome.org/show_bug.cgi?id=697274
This commit is contained in:
parent
db14dc973a
commit
a2fcbb7e65
@ -1965,7 +1965,10 @@ st_theme_node_paint (StThemeNode *node,
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if (state->alloc_width != width || state->alloc_height != height)
|
if (state->alloc_width != width || state->alloc_height != height)
|
||||||
st_theme_node_render_resources (node, state, width, height);
|
{
|
||||||
|
state->node = node;
|
||||||
|
st_theme_node_render_resources (node, state, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
/* Rough notes about the relationship of borders and backgrounds in CSS3;
|
/* Rough notes about the relationship of borders and backgrounds in CSS3;
|
||||||
* see http://www.w3.org/TR/css3-background/ for more accurate details.
|
* see http://www.w3.org/TR/css3-background/ for more accurate details.
|
||||||
@ -2097,6 +2100,7 @@ st_theme_node_paint_state_init (StThemeNodePaintState *state)
|
|||||||
{
|
{
|
||||||
int corner_id;
|
int corner_id;
|
||||||
|
|
||||||
|
state->node = NULL;
|
||||||
state->box_shadow_material = COGL_INVALID_HANDLE;
|
state->box_shadow_material = COGL_INVALID_HANDLE;
|
||||||
state->prerendered_texture = COGL_INVALID_HANDLE;
|
state->prerendered_texture = COGL_INVALID_HANDLE;
|
||||||
state->prerendered_material = COGL_INVALID_HANDLE;
|
state->prerendered_material = COGL_INVALID_HANDLE;
|
||||||
@ -2116,6 +2120,8 @@ st_theme_node_paint_state_copy (StThemeNodePaintState *state,
|
|||||||
|
|
||||||
st_theme_node_paint_state_free (state);
|
st_theme_node_paint_state_free (state);
|
||||||
|
|
||||||
|
state->node = other->node;
|
||||||
|
|
||||||
state->alloc_width = other->alloc_width;
|
state->alloc_width = other->alloc_width;
|
||||||
state->alloc_height = other->alloc_height;
|
state->alloc_height = other->alloc_height;
|
||||||
|
|
||||||
|
@ -3801,8 +3801,8 @@ st_theme_node_geometry_equal (StThemeNode *node,
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* st_theme_node_paint_equal:
|
* st_theme_node_paint_equal:
|
||||||
* @node: a #StThemeNode
|
* @node: (allow-none): a #StThemeNode
|
||||||
* @other: a different #StThemeNode
|
* @other: (allow-none): a different #StThemeNode
|
||||||
*
|
*
|
||||||
* Check if st_theme_node_paint() will paint identically for @node as it does
|
* Check if st_theme_node_paint() will paint identically for @node as it does
|
||||||
* for @other. Note that in some cases this function may return %TRUE even
|
* for @other. Note that in some cases this function may return %TRUE even
|
||||||
@ -3819,13 +3819,13 @@ st_theme_node_paint_equal (StThemeNode *node,
|
|||||||
StShadow *shadow, *other_shadow;
|
StShadow *shadow, *other_shadow;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
g_return_val_if_fail (ST_IS_THEME_NODE (node), FALSE);
|
/* Make sure NULL != NULL */
|
||||||
|
if (node == NULL || other == NULL)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
if (node == other)
|
if (node == other)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
g_return_val_if_fail (ST_IS_THEME_NODE (other), FALSE);
|
|
||||||
|
|
||||||
_st_theme_node_ensure_background (node);
|
_st_theme_node_ensure_background (node);
|
||||||
_st_theme_node_ensure_background (other);
|
_st_theme_node_ensure_background (other);
|
||||||
|
|
||||||
|
@ -97,6 +97,8 @@ typedef enum {
|
|||||||
typedef struct _StThemeNodePaintState StThemeNodePaintState;
|
typedef struct _StThemeNodePaintState StThemeNodePaintState;
|
||||||
|
|
||||||
struct _StThemeNodePaintState {
|
struct _StThemeNodePaintState {
|
||||||
|
StThemeNode *node;
|
||||||
|
|
||||||
float alloc_width;
|
float alloc_width;
|
||||||
float alloc_height;
|
float alloc_height;
|
||||||
|
|
||||||
|
@ -80,7 +80,8 @@ struct _StWidgetPrivate
|
|||||||
StWidget *prev_last_child;
|
StWidget *prev_last_child;
|
||||||
StWidget *prev_first_child;
|
StWidget *prev_first_child;
|
||||||
|
|
||||||
StThemeNodePaintState paint_state;
|
StThemeNodePaintState paint_states[2];
|
||||||
|
int current_paint_state : 2;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -271,6 +272,18 @@ st_widget_remove_transition (StWidget *widget)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
next_paint_state (StWidget *widget)
|
||||||
|
{
|
||||||
|
widget->priv->current_paint_state = (widget->priv->current_paint_state + 1) % G_N_ELEMENTS (widget->priv->paint_states);
|
||||||
|
}
|
||||||
|
|
||||||
|
static StThemeNodePaintState *
|
||||||
|
current_paint_state (StWidget *widget)
|
||||||
|
{
|
||||||
|
return &widget->priv->paint_states[widget->priv->current_paint_state];
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
st_widget_texture_cache_changed (StTextureCache *cache,
|
st_widget_texture_cache_changed (StTextureCache *cache,
|
||||||
const char *uri,
|
const char *uri,
|
||||||
@ -304,8 +317,11 @@ st_widget_texture_cache_changed (StTextureCache *cache,
|
|||||||
* the paint state. We should probably implement a method to
|
* the paint state. We should probably implement a method to
|
||||||
* the theme node to determine this, but for now, just wipe
|
* the theme node to determine this, but for now, just wipe
|
||||||
* the entire paint state.
|
* the entire paint state.
|
||||||
|
*
|
||||||
|
* Use the existing state instead of a new one because it's
|
||||||
|
* assumed the rest of the state will stay the same.
|
||||||
*/
|
*/
|
||||||
st_theme_node_paint_state_invalidate (&actor->priv->paint_state);
|
st_theme_node_paint_state_invalidate (current_paint_state (actor));
|
||||||
|
|
||||||
if (CLUTTER_ACTOR_IS_MAPPED (CLUTTER_ACTOR (actor)))
|
if (CLUTTER_ACTOR_IS_MAPPED (CLUTTER_ACTOR (actor)))
|
||||||
clutter_actor_queue_redraw (CLUTTER_ACTOR (actor));
|
clutter_actor_queue_redraw (CLUTTER_ACTOR (actor));
|
||||||
@ -360,6 +376,7 @@ static void
|
|||||||
st_widget_finalize (GObject *gobject)
|
st_widget_finalize (GObject *gobject)
|
||||||
{
|
{
|
||||||
StWidgetPrivate *priv = ST_WIDGET (gobject)->priv;
|
StWidgetPrivate *priv = ST_WIDGET (gobject)->priv;
|
||||||
|
int i;
|
||||||
|
|
||||||
g_free (priv->style_class);
|
g_free (priv->style_class);
|
||||||
g_free (priv->pseudo_class);
|
g_free (priv->pseudo_class);
|
||||||
@ -367,7 +384,8 @@ st_widget_finalize (GObject *gobject)
|
|||||||
g_free (priv->accessible_name);
|
g_free (priv->accessible_name);
|
||||||
g_free (priv->inline_style);
|
g_free (priv->inline_style);
|
||||||
|
|
||||||
st_theme_node_paint_state_free (&priv->paint_state);
|
for (i = 0; i < G_N_ELEMENTS (priv->paint_states); i++)
|
||||||
|
st_theme_node_paint_state_init (&priv->paint_states[i]);
|
||||||
|
|
||||||
G_OBJECT_CLASS (st_widget_parent_class)->finalize (gobject);
|
G_OBJECT_CLASS (st_widget_parent_class)->finalize (gobject);
|
||||||
}
|
}
|
||||||
@ -456,7 +474,7 @@ st_widget_paint_background (StWidget *widget)
|
|||||||
opacity);
|
opacity);
|
||||||
else
|
else
|
||||||
st_theme_node_paint (theme_node,
|
st_theme_node_paint (theme_node,
|
||||||
&widget->priv->paint_state,
|
current_paint_state (widget),
|
||||||
&allocation,
|
&allocation,
|
||||||
opacity);
|
opacity);
|
||||||
}
|
}
|
||||||
@ -1520,6 +1538,7 @@ static void
|
|||||||
st_widget_init (StWidget *actor)
|
st_widget_init (StWidget *actor)
|
||||||
{
|
{
|
||||||
StWidgetPrivate *priv;
|
StWidgetPrivate *priv;
|
||||||
|
int i;
|
||||||
|
|
||||||
actor->priv = priv = ST_WIDGET_GET_PRIVATE (actor);
|
actor->priv = priv = ST_WIDGET_GET_PRIVATE (actor);
|
||||||
priv->is_stylable = TRUE;
|
priv->is_stylable = TRUE;
|
||||||
@ -1535,14 +1554,17 @@ st_widget_init (StWidget *actor)
|
|||||||
g_signal_connect (st_texture_cache_get_default (), "texture-file-changed",
|
g_signal_connect (st_texture_cache_get_default (), "texture-file-changed",
|
||||||
G_CALLBACK (st_widget_texture_cache_changed), actor);
|
G_CALLBACK (st_widget_texture_cache_changed), actor);
|
||||||
|
|
||||||
st_theme_node_paint_state_init (&priv->paint_state);
|
for (i = 0; i < G_N_ELEMENTS (priv->paint_states); i++)
|
||||||
|
st_theme_node_paint_state_init (&priv->paint_states[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
on_transition_completed (StThemeNodeTransition *transition,
|
on_transition_completed (StThemeNodeTransition *transition,
|
||||||
StWidget *widget)
|
StWidget *widget)
|
||||||
{
|
{
|
||||||
st_theme_node_paint_state_copy (&widget->priv->paint_state,
|
next_paint_state (widget);
|
||||||
|
|
||||||
|
st_theme_node_paint_state_copy (current_paint_state (widget),
|
||||||
st_theme_node_transition_get_new_paint_state (transition));
|
st_theme_node_transition_get_new_paint_state (transition));
|
||||||
|
|
||||||
st_widget_remove_transition (widget);
|
st_widget_remove_transition (widget);
|
||||||
@ -1569,7 +1591,7 @@ st_widget_recompute_style (StWidget *widget,
|
|||||||
|
|
||||||
transition_duration = st_theme_node_get_transition_duration (new_theme_node);
|
transition_duration = st_theme_node_get_transition_duration (new_theme_node);
|
||||||
|
|
||||||
paint_equal = old_theme_node && st_theme_node_paint_equal (old_theme_node, new_theme_node);
|
paint_equal = st_theme_node_paint_equal (old_theme_node, new_theme_node);
|
||||||
|
|
||||||
g_object_get (gtk_settings_get_default (),
|
g_object_get (gtk_settings_get_default (),
|
||||||
"gtk-enable-animations", &animations_enabled,
|
"gtk-enable-animations", &animations_enabled,
|
||||||
@ -1593,7 +1615,7 @@ st_widget_recompute_style (StWidget *widget,
|
|||||||
widget->priv->transition_animation =
|
widget->priv->transition_animation =
|
||||||
st_theme_node_transition_new (old_theme_node,
|
st_theme_node_transition_new (old_theme_node,
|
||||||
new_theme_node,
|
new_theme_node,
|
||||||
&widget->priv->paint_state,
|
current_paint_state (widget),
|
||||||
transition_duration);
|
transition_duration);
|
||||||
|
|
||||||
g_signal_connect (widget->priv->transition_animation, "completed",
|
g_signal_connect (widget->priv->transition_animation, "completed",
|
||||||
@ -1610,7 +1632,12 @@ st_widget_recompute_style (StWidget *widget,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!paint_equal)
|
if (!paint_equal)
|
||||||
st_theme_node_paint_state_invalidate (&widget->priv->paint_state);
|
{
|
||||||
|
next_paint_state (widget);
|
||||||
|
|
||||||
|
if (!st_theme_node_paint_equal (new_theme_node, current_paint_state (widget)->node))
|
||||||
|
st_theme_node_paint_state_invalidate (current_paint_state (widget));
|
||||||
|
}
|
||||||
|
|
||||||
g_signal_emit (widget, signals[STYLE_CHANGED], 0);
|
g_signal_emit (widget, signals[STYLE_CHANGED], 0);
|
||||||
widget->priv->is_style_dirty = FALSE;
|
widget->priv->is_style_dirty = FALSE;
|
||||||
|
Loading…
Reference in New Issue
Block a user