forked from AuroraMiddleware/gtk
cssnode: Split out the style cache
For now, the split out style cache doesn't cache anything. This is mostly to make sure that bisections of wrong caching behavior will bisect down to the commit that actually adds caching.
This commit is contained in:
parent
93f8fa7576
commit
5d562b6a2a
@ -416,6 +416,7 @@ gtk_private_h_sources = \
|
||||
gtkcssmatcherprivate.h \
|
||||
gtkcssnodeprivate.h \
|
||||
gtkcssnodedeclarationprivate.h \
|
||||
gtkcssnodestylecacheprivate.h \
|
||||
gtkcssnumbervalueprivate.h \
|
||||
gtkcsspalettevalueprivate.h \
|
||||
gtkcssparserprivate.h \
|
||||
@ -676,6 +677,7 @@ gtk_base_c_sources = \
|
||||
gtkcssmatcher.c \
|
||||
gtkcssnode.c \
|
||||
gtkcssnodedeclaration.c \
|
||||
gtkcssnodestylecache.c \
|
||||
gtkcssnumbervalue.c \
|
||||
gtkcsspalettevalue.c \
|
||||
gtkcssparser.c \
|
||||
|
123
gtk/gtkcssnode.c
123
gtk/gtkcssnode.c
@ -20,13 +20,13 @@
|
||||
#include "gtkcssnodeprivate.h"
|
||||
|
||||
#include "gtkcssanimatedstyleprivate.h"
|
||||
#include "gtkcsssectionprivate.h"
|
||||
#include "gtkcssstylepropertyprivate.h"
|
||||
#include "gtkdebug.h"
|
||||
#include "gtkintl.h"
|
||||
#include "gtkmarshalers.h"
|
||||
#include "gtksettingsprivate.h"
|
||||
#include "gtktypebuiltins.h"
|
||||
#include "gtkcssstylepropertyprivate.h"
|
||||
#include "gtkcsssectionprivate.h"
|
||||
|
||||
/*
|
||||
* CSS nodes are the backbone of the GtkStyleContext implementation and
|
||||
@ -116,8 +116,6 @@ struct _GtkCssNodeStyleChange {
|
||||
static guint cssnode_signals[LAST_SIGNAL] = { 0 };
|
||||
static GParamSpec *cssnode_properties[NUM_PROPERTIES];
|
||||
|
||||
static GQuark quark_global_cache;
|
||||
|
||||
static GtkStyleProviderPrivate *
|
||||
gtk_css_node_get_style_provider_or_null (GtkCssNode *cssnode)
|
||||
{
|
||||
@ -285,10 +283,6 @@ gtk_css_node_is_last_child (GtkCssNode *node)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#define UNPACK_DECLARATION(packed) ((GtkCssNodeDeclaration *) (GPOINTER_TO_SIZE (packed) & ~0x3))
|
||||
#define UNPACK_FLAGS(packed) (GPOINTER_TO_SIZE (packed) & 0x3)
|
||||
#define PACK(decl, first_child, last_child) GSIZE_TO_POINTER (GPOINTER_TO_SIZE (decl) | ((first_child) ? 0x2 : 0) | ((last_child) ? 0x1 : 0))
|
||||
|
||||
static gboolean
|
||||
may_use_global_parent_cache (GtkCssNode *node)
|
||||
{
|
||||
@ -308,109 +302,52 @@ may_use_global_parent_cache (GtkCssNode *node)
|
||||
|
||||
static GtkCssStyle *
|
||||
lookup_in_global_parent_cache (GtkCssNode *node,
|
||||
GtkCssStyle *parent,
|
||||
const GtkCssNodeDeclaration *decl)
|
||||
{
|
||||
GHashTable *cache;
|
||||
GtkCssStyle *style;
|
||||
GtkCssNode *parent;
|
||||
|
||||
parent = node->parent;
|
||||
|
||||
if (parent == NULL ||
|
||||
!may_use_global_parent_cache (node))
|
||||
return NULL;
|
||||
|
||||
cache = g_object_get_qdata (G_OBJECT (parent), quark_global_cache);
|
||||
if (cache == NULL)
|
||||
if (parent->cache == NULL)
|
||||
return NULL;
|
||||
|
||||
style = g_hash_table_lookup (cache,
|
||||
PACK (decl,
|
||||
gtk_css_node_is_first_child (node),
|
||||
gtk_css_node_is_last_child (node)));
|
||||
node->cache = gtk_css_node_style_cache_lookup (parent->cache,
|
||||
(GtkCssNodeDeclaration *) decl,
|
||||
gtk_css_node_is_first_child (node),
|
||||
gtk_css_node_is_last_child (node));
|
||||
if (node->cache == NULL)
|
||||
return NULL;
|
||||
|
||||
return style;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
may_be_stored_in_parent_cache (GtkCssStyle *style)
|
||||
{
|
||||
GtkCssChange change;
|
||||
|
||||
change = gtk_css_static_style_get_change (GTK_CSS_STATIC_STYLE (style));
|
||||
|
||||
/* The cache is shared between all children of the parent, so if a
|
||||
* style depends on a sibling it is not independant of the child.
|
||||
*/
|
||||
if (change & GTK_CSS_CHANGE_ANY_SIBLING)
|
||||
return FALSE;
|
||||
|
||||
/* Again, the cache is shared between all children of the parent.
|
||||
* If the position is relevant, no child has the same style.
|
||||
*/
|
||||
if (change & (GTK_CSS_CHANGE_NTH_CHILD | GTK_CSS_CHANGE_NTH_LAST_CHILD))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static guint
|
||||
gtk_global_parent_cache_hash (gconstpointer item)
|
||||
{
|
||||
return gtk_css_node_declaration_hash (UNPACK_DECLARATION (item)) << 2
|
||||
| UNPACK_FLAGS (item);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gtk_global_parent_cache_equal (gconstpointer item1,
|
||||
gconstpointer item2)
|
||||
{
|
||||
if (UNPACK_FLAGS (item1) != UNPACK_FLAGS (item2))
|
||||
return FALSE;
|
||||
|
||||
return gtk_css_node_declaration_equal (UNPACK_DECLARATION (item1),
|
||||
UNPACK_DECLARATION (item2));
|
||||
}
|
||||
|
||||
static void
|
||||
gtk_global_parent_cache_free (gpointer item)
|
||||
{
|
||||
gtk_css_node_declaration_unref (UNPACK_DECLARATION (item));
|
||||
return gtk_css_node_style_cache_get_style (node->cache);
|
||||
}
|
||||
|
||||
static void
|
||||
store_in_global_parent_cache (GtkCssNode *node,
|
||||
GtkCssStyle *parent,
|
||||
const GtkCssNodeDeclaration *decl,
|
||||
GtkCssStyle *style)
|
||||
{
|
||||
GHashTable *cache;
|
||||
GtkCssNode *parent;
|
||||
|
||||
g_assert (GTK_IS_CSS_STATIC_STYLE (style));
|
||||
|
||||
parent = node->parent;
|
||||
|
||||
if (parent == NULL ||
|
||||
!may_use_global_parent_cache (node))
|
||||
return;
|
||||
|
||||
if (!may_be_stored_in_parent_cache (style))
|
||||
return;
|
||||
if (parent->cache == NULL)
|
||||
parent->cache = gtk_css_node_style_cache_new (parent->style);
|
||||
|
||||
cache = g_object_get_qdata (G_OBJECT (parent), quark_global_cache);
|
||||
if (cache == NULL)
|
||||
{
|
||||
cache = g_hash_table_new_full (gtk_global_parent_cache_hash,
|
||||
gtk_global_parent_cache_equal,
|
||||
gtk_global_parent_cache_free,
|
||||
g_object_unref);
|
||||
g_object_set_qdata_full (G_OBJECT (parent),
|
||||
quark_global_cache,
|
||||
cache,
|
||||
(GDestroyNotify) g_hash_table_destroy);
|
||||
}
|
||||
|
||||
g_hash_table_insert (cache,
|
||||
PACK (gtk_css_node_declaration_ref ((GtkCssNodeDeclaration *) decl),
|
||||
gtk_css_node_is_first_child (node),
|
||||
gtk_css_node_is_last_child (node)),
|
||||
g_object_ref (style));
|
||||
node->cache = gtk_css_node_style_cache_insert (parent->cache,
|
||||
(GtkCssNodeDeclaration *) decl,
|
||||
gtk_css_node_is_first_child (node),
|
||||
gtk_css_node_is_last_child (node),
|
||||
style);
|
||||
}
|
||||
|
||||
static GtkCssStyle *
|
||||
@ -424,7 +361,7 @@ gtk_css_node_create_style (GtkCssNode *cssnode)
|
||||
decl = gtk_css_node_get_declaration (cssnode);
|
||||
parent = cssnode->parent ? cssnode->parent->style : NULL;
|
||||
|
||||
style = lookup_in_global_parent_cache (cssnode, parent, decl);
|
||||
style = lookup_in_global_parent_cache (cssnode, decl);
|
||||
if (style)
|
||||
return g_object_ref (style);
|
||||
|
||||
@ -437,7 +374,7 @@ gtk_css_node_create_style (GtkCssNode *cssnode)
|
||||
NULL,
|
||||
parent);
|
||||
|
||||
store_in_global_parent_cache (cssnode, parent, decl, style);
|
||||
store_in_global_parent_cache (cssnode, decl, style);
|
||||
|
||||
return style;
|
||||
}
|
||||
@ -625,8 +562,6 @@ gtk_css_node_class_init (GtkCssNodeClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
quark_global_cache = g_quark_from_static_string ("gtk-global-cache");
|
||||
|
||||
object_class->get_property = gtk_css_node_get_property;
|
||||
object_class->set_property = gtk_css_node_set_property;
|
||||
object_class->dispose = gtk_css_node_dispose;
|
||||
@ -1059,6 +994,8 @@ gtk_css_node_ensure_style (GtkCssNode *cssnode,
|
||||
if (cssnode->previous_sibling)
|
||||
gtk_css_node_ensure_style (cssnode->previous_sibling, current_time);
|
||||
|
||||
g_clear_pointer (&cssnode->cache, gtk_css_node_style_cache_unref);
|
||||
|
||||
new_style = GTK_CSS_NODE_GET_CLASS (cssnode)->update_style (cssnode,
|
||||
cssnode->pending_changes,
|
||||
current_time,
|
||||
@ -1066,12 +1003,6 @@ gtk_css_node_ensure_style (GtkCssNode *cssnode,
|
||||
|
||||
style_changed = gtk_css_node_set_style (cssnode, new_style);
|
||||
g_object_unref (new_style);
|
||||
|
||||
if (!style_changed && (cssnode->pending_changes & GTK_CSS_CHANGE_SOURCE))
|
||||
{
|
||||
/* clear the global cache if we reuse the same style after the CSS changed */
|
||||
g_object_set_qdata (G_OBJECT (cssnode->style), quark_global_cache, NULL);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -19,6 +19,7 @@
|
||||
#define __GTK_CSS_NODE_PRIVATE_H__
|
||||
|
||||
#include "gtkcssnodedeclarationprivate.h"
|
||||
#include "gtkcssnodestylecacheprivate.h"
|
||||
#include "gtkcssstylechangeprivate.h"
|
||||
#include "gtkbitmaskprivate.h"
|
||||
#include "gtkcsstypesprivate.h"
|
||||
@ -46,6 +47,7 @@ struct _GtkCssNode
|
||||
|
||||
GtkCssNodeDeclaration *decl;
|
||||
GtkCssStyle *style;
|
||||
GtkCssNodeStyleCache *cache; /* cache for children to look up styles */
|
||||
|
||||
GtkCssChange pending_changes; /* changes that accumulated since the style was last computed */
|
||||
|
||||
|
76
gtk/gtkcssnodestylecache.c
Normal file
76
gtk/gtkcssnodestylecache.c
Normal file
@ -0,0 +1,76 @@
|
||||
/* GTK - The GIMP Toolkit
|
||||
* Copyright (C) 2015 Benjamin Otte <otte@gnome.org>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gtkcssnodestylecacheprivate.h"
|
||||
|
||||
struct _GtkCssNodeStyleCache {
|
||||
guint ref_count;
|
||||
GtkCssStyle *style;
|
||||
GHashTable *children;
|
||||
};
|
||||
|
||||
GtkCssNodeStyleCache *
|
||||
gtk_css_node_style_cache_new (GtkCssStyle *style)
|
||||
{
|
||||
GtkCssNodeStyleCache *result;
|
||||
|
||||
result = g_slice_new0 (GtkCssNodeStyleCache);
|
||||
|
||||
result->ref_count = 1;
|
||||
result->style = g_object_ref (style);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
gtk_css_node_style_cache_unref (GtkCssNodeStyleCache *cache)
|
||||
{
|
||||
cache->ref_count--;
|
||||
|
||||
if (cache->ref_count > 0)
|
||||
return;
|
||||
|
||||
g_object_unref (cache->style);
|
||||
}
|
||||
|
||||
GtkCssStyle *
|
||||
gtk_css_node_style_cache_get_style (GtkCssNodeStyleCache *cache)
|
||||
{
|
||||
return cache->style;
|
||||
}
|
||||
|
||||
GtkCssNodeStyleCache *
|
||||
gtk_css_node_style_cache_insert (GtkCssNodeStyleCache *parent,
|
||||
GtkCssNodeDeclaration *decl,
|
||||
gboolean is_first,
|
||||
gboolean is_last,
|
||||
GtkCssStyle *style)
|
||||
{
|
||||
return gtk_css_node_style_cache_new (style);
|
||||
}
|
||||
|
||||
GtkCssNodeStyleCache *
|
||||
gtk_css_node_style_cache_lookup (GtkCssNodeStyleCache *parent,
|
||||
GtkCssNodeDeclaration *decl,
|
||||
gboolean is_first,
|
||||
gboolean is_last)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
44
gtk/gtkcssnodestylecacheprivate.h
Normal file
44
gtk/gtkcssnodestylecacheprivate.h
Normal file
@ -0,0 +1,44 @@
|
||||
/* GTK - The GIMP Toolkit
|
||||
* Copyright (C) 2016 Benjamin Otte <otte@gnome.org>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __GTK_CSS_NODE_STYLE_CACHE_PRIVATE_H__
|
||||
#define __GTK_CSS_NODE_STYLE_CACHE_PRIVATE_H__
|
||||
|
||||
#include "gtkcssstyleprivate.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct _GtkCssNodeStyleCache GtkCssNodeStyleCache;
|
||||
|
||||
GtkCssNodeStyleCache * gtk_css_node_style_cache_new (GtkCssStyle *style);
|
||||
void gtk_css_node_style_cache_unref (GtkCssNodeStyleCache *cache);
|
||||
|
||||
GtkCssStyle * gtk_css_node_style_cache_get_style (GtkCssNodeStyleCache *cache);
|
||||
|
||||
GtkCssNodeStyleCache * gtk_css_node_style_cache_insert (GtkCssNodeStyleCache *parent,
|
||||
GtkCssNodeDeclaration *decl,
|
||||
gboolean is_first,
|
||||
gboolean is_last,
|
||||
GtkCssStyle *style);
|
||||
GtkCssNodeStyleCache * gtk_css_node_style_cache_lookup (GtkCssNodeStyleCache *parent,
|
||||
GtkCssNodeDeclaration *decl,
|
||||
gboolean is_first,
|
||||
gboolean is_last);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GTK_CSS_NODE_STYLE_CACHE_PRIVATE_H__ */
|
Loading…
Reference in New Issue
Block a user