[gnome-shell] st-widget: Cache two paint states



commit a2fcbb7e652fd2be95beacf180c01fe128e55cee
Author: Jasper St. Pierre <jstpierre mecheye net>
Date:   Thu Apr 4 23:06:29 2013 -0400

    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

 src/st/st-theme-node-drawing.c |    8 ++++++-
 src/st/st-theme-node.c         |   10 ++++----
 src/st/st-theme-node.h         |    2 +
 src/st/st-widget.c             |   45 ++++++++++++++++++++++++++++++++--------
 4 files changed, 50 insertions(+), 15 deletions(-)
---
diff --git a/src/st/st-theme-node-drawing.c b/src/st/st-theme-node-drawing.c
index b2f88c2..0f942f1 100644
--- a/src/st/st-theme-node-drawing.c
+++ b/src/st/st-theme-node-drawing.c
@@ -1965,7 +1965,10 @@ st_theme_node_paint (StThemeNode           *node,
     return;
 
   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;
    * 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;
 
+  state->node = NULL;
   state->box_shadow_material = COGL_INVALID_HANDLE;
   state->prerendered_texture = 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);
 
+  state->node = other->node;
+
   state->alloc_width = other->alloc_width;
   state->alloc_height = other->alloc_height;
 
diff --git a/src/st/st-theme-node.c b/src/st/st-theme-node.c
index 62980b1..a9a1fb5 100644
--- a/src/st/st-theme-node.c
+++ b/src/st/st-theme-node.c
@@ -3801,8 +3801,8 @@ st_theme_node_geometry_equal (StThemeNode *node,
 
 /**
  * st_theme_node_paint_equal:
- * @node: a #StThemeNode
- * @other: a different #StThemeNode
+ * @node: (allow-none): a #StThemeNode
+ * @other: (allow-none): a different #StThemeNode
  *
  * 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
@@ -3819,13 +3819,13 @@ st_theme_node_paint_equal (StThemeNode *node,
   StShadow *shadow, *other_shadow;
   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)
     return TRUE;
 
-  g_return_val_if_fail (ST_IS_THEME_NODE (other), FALSE);
-
   _st_theme_node_ensure_background (node);
   _st_theme_node_ensure_background (other);
 
diff --git a/src/st/st-theme-node.h b/src/st/st-theme-node.h
index 8f5da57..fc6caa1 100644
--- a/src/st/st-theme-node.h
+++ b/src/st/st-theme-node.h
@@ -97,6 +97,8 @@ typedef enum {
 typedef struct _StThemeNodePaintState StThemeNodePaintState;
 
 struct _StThemeNodePaintState {
+  StThemeNode *node;
+
   float alloc_width;
   float alloc_height;
 
diff --git a/src/st/st-widget.c b/src/st/st-widget.c
index 01c7b4c..c07dd7b 100644
--- a/src/st/st-widget.c
+++ b/src/st/st-widget.c
@@ -80,7 +80,8 @@ struct _StWidgetPrivate
   StWidget *prev_last_child;
   StWidget *prev_first_child;
 
-  StThemeNodePaintState paint_state;
+  StThemeNodePaintState paint_states[2];
+  int current_paint_state : 2;
 };
 
 /**
@@ -272,6 +273,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
 st_widget_texture_cache_changed (StTextureCache *cache,
                                  const char     *uri,
                                  gpointer        user_data)
@@ -304,8 +317,11 @@ st_widget_texture_cache_changed (StTextureCache *cache,
        * the paint state. We should probably implement a method to
        * the theme node to determine this, but for now, just wipe
        * 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)))
         clutter_actor_queue_redraw (CLUTTER_ACTOR (actor));
@@ -360,6 +376,7 @@ static void
 st_widget_finalize (GObject *gobject)
 {
   StWidgetPrivate *priv = ST_WIDGET (gobject)->priv;
+  int i;
 
   g_free (priv->style_class);
   g_free (priv->pseudo_class);
@@ -367,7 +384,8 @@ st_widget_finalize (GObject *gobject)
   g_free (priv->accessible_name);
   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);
 }
@@ -456,7 +474,7 @@ st_widget_paint_background (StWidget *widget)
                                     opacity);
   else
     st_theme_node_paint (theme_node,
-                         &widget->priv->paint_state,
+                         current_paint_state (widget),
                          &allocation,
                          opacity);
 }
@@ -1520,6 +1538,7 @@ static void
 st_widget_init (StWidget *actor)
 {
   StWidgetPrivate *priv;
+  int i;
 
   actor->priv = priv = ST_WIDGET_GET_PRIVATE (actor);
   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_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
 on_transition_completed (StThemeNodeTransition *transition,
                          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_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);
 
-  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 (),
                 "gtk-enable-animations", &animations_enabled,
@@ -1593,7 +1615,7 @@ st_widget_recompute_style (StWidget    *widget,
           widget->priv->transition_animation =
             st_theme_node_transition_new (old_theme_node,
                                           new_theme_node,
-                                          &widget->priv->paint_state,
+                                          current_paint_state (widget),
                                           transition_duration);
 
           g_signal_connect (widget->priv->transition_animation, "completed",
@@ -1610,7 +1632,12 @@ st_widget_recompute_style (StWidget    *widget,
     }
 
   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);
   widget->priv->is_style_dirty = FALSE;


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]