]> Pileus Git - ~andy/gtk/commitdiff
stylecontext: Compute if things changed before invalidating
authorBenjamin Otte <otte@redhat.com>
Sat, 7 Apr 2012 16:09:17 +0000 (18:09 +0200)
committerBenjamin Otte <otte@redhat.com>
Tue, 17 Apr 2012 06:59:21 +0000 (08:59 +0200)
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
gtk/gtkcsscomputedvaluesprivate.h
gtk/gtkstylecontext.c

index 608575e38caac9c351019cda65b9165cc85edd10..ac2718f44a544e8bc21b97a92832ed20411e29da 100644 (file)
@@ -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;
+}
+
index 81c9cf25191b64c0c26641fae34182cf93fd492a..64234ef3714c6d0bd76d6a5536107527783bd48d 100644 (file)
@@ -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
index 103f235df4bc37a4b2ea27af0789c3df58683986..b50f9d06023e9e3b43491b2d8fe33f92f4be5894 100644 (file)
@@ -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);