[gtk+] stylecontext: Compute if things changed before invalidating



commit aaedc7b67fbe6d74fe75d2a4011777d794eeac60
Author: Benjamin Otte <otte redhat com>
Date:   Sat Apr 7 18:09:17 2012 +0200

    stylecontext: Compute if things changed before invalidating
    
    This is only a small performance boost by itself, but it's necessary
    for animations, so we need it.
    
    Benchmark numbers for my Glade benchmark for interested people:
            GTK 3.4.0    last commit  this commit
    Raleigh
      real  0m41.879s    0m10.176s    0m9.900s
      user  0m41.394s    0m9.895s     0m9.628s
      sys   0m0.111s     0m0.096s     0m0.102s
    
    Adwaita                                        (*)
      real  0m51.049s    0m13.432s    0m14.848s    0m12.253s
      user  0m50.487s    0m13.034s    0m13.218s    0m11.927s
      sys   0m0.117s     0m0.151s     0m0.147s     0m0.107s
    
    Ambiance (patched to not use private GTK APIs)
      real  0m52.167s    0m13.115s    0m13.117s    0m12.944s
      user  0m51.576s    0m12.739s    0m12.768s    0m12.651s
      sys   0m0.119s     0m0.137s     0m0.136s     0m0.118s
    
    (*) Adwaita and unico currently use custom properties, and
    _gtk_css_value_compare() for custom properties always returns FALSE,
    which makes this optimization never trigger. So I modified
    _gtk_css_value_compare() to return TRUE for these properties instead and
    reran the benchmark. Those are the numbers.

 gtk/gtkcsscomputedvalues.c        |   22 ++++++++++++++++++++++
 gtk/gtkcsscomputedvaluesprivate.h |    3 +++
 gtk/gtkstylecontext.c             |   23 +++++++++++++++++++++--
 3 files changed, 46 insertions(+), 2 deletions(-)
---
diff --git a/gtk/gtkcsscomputedvalues.c b/gtk/gtkcsscomputedvalues.c
index 608575e..ac2718f 100644
--- a/gtk/gtkcsscomputedvalues.c
+++ b/gtk/gtkcsscomputedvalues.c
@@ -227,3 +227,25 @@ _gtk_css_computed_values_get_section (GtkCssComputedValues *values,
   return g_ptr_array_index (values->sections, id);
 }
 
+GtkBitmask *
+_gtk_css_computed_values_get_difference (GtkCssComputedValues *values,
+                                         GtkCssComputedValues *other)
+{
+  GtkBitmask *result;
+  guint i, len;
+
+  len = MIN (values->values->len, other->values->len);
+  result = _gtk_bitmask_new ();
+  if (values->values->len != other->values->len)
+    result = _gtk_bitmask_invert_range (result, len, MAX (values->values->len, other->values->len));
+  
+  for (i = 0; i < len; i++)
+    {
+      if (!_gtk_css_value_equal (g_ptr_array_index (values->values, i),
+                                 g_ptr_array_index (other->values, i)))
+        result = _gtk_bitmask_set (result, i, TRUE);
+    }
+
+  return result;
+}
+
diff --git a/gtk/gtkcsscomputedvaluesprivate.h b/gtk/gtkcsscomputedvaluesprivate.h
index 81c9cf2..64234ef 100644
--- a/gtk/gtkcsscomputedvaluesprivate.h
+++ b/gtk/gtkcsscomputedvaluesprivate.h
@@ -22,6 +22,7 @@
 
 #include <glib-object.h>
 
+#include "gtk/gtkbitmaskprivate.h"
 #include "gtk/gtkcsssection.h"
 #include "gtk/gtkstylecontext.h"
 #include "gtk/gtkcssvalueprivate.h"
@@ -69,6 +70,8 @@ GtkCssValue *           _gtk_css_computed_values_get_value            (GtkCssCom
                                                                        guint                     id);
 GtkCssSection *         _gtk_css_computed_values_get_section          (GtkCssComputedValues     *values,
                                                                        guint                     id);
+GtkBitmask *            _gtk_css_computed_values_get_difference       (GtkCssComputedValues     *values,
+                                                                       GtkCssComputedValues     *other);
 
 
 G_END_DECLS
diff --git a/gtk/gtkstylecontext.c b/gtk/gtkstylecontext.c
index 103f235..b50f9d0 100644
--- a/gtk/gtkstylecontext.c
+++ b/gtk/gtkstylecontext.c
@@ -2830,12 +2830,31 @@ _gtk_style_context_validate (GtkStyleContext *context,
   if (priv->relevant_changes & change)
     {
       GtkStyleInfo *info = priv->info_stack->data;
+      GtkCssComputedValues *old, *new;
+
+      old = info->data ? g_object_ref (info->data->store) : NULL;
 
       if ((priv->relevant_changes & change) & ~GTK_STYLE_CONTEXT_CACHED_CHANGE)
         gtk_style_context_clear_cache (context);
+      else
+        info->data = NULL;
+
+      if (old)
+        {
+          GtkBitmask *bitmask;
+
+          new = style_data_lookup (context)->store;
+
+          bitmask = _gtk_css_computed_values_get_difference (new, old);
+          if (!_gtk_bitmask_is_empty (bitmask))
+            gtk_style_context_do_invalidate (context);
+
+          _gtk_bitmask_free (bitmask);
+          g_object_unref (old);
+        }
+      else
+        gtk_style_context_do_invalidate (context);
 
-      info->data = NULL;
-      gtk_style_context_do_invalidate (context);
     }
 
   change = _gtk_css_change_for_child (change);



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