forked from AuroraMiddleware/gtk
snapshot: Add gtk_snapshot_from_parent
Most of the time, the GtkSnapshot objects we create while snapshotting widgets don't end up containing all that many nodes or states in their respective node or state stack. This undermines the amortized allocation behavior of the G(Ptr)Array we use for the stacks. So instead, use the (until now unused) parent_snapshot GtkSnapshot* passed to gtk_widget_create_render_node and reuse its node and state stack. We do not avoid allocating a new GtkSnapshot object, but we do avoid allocating a ton of G(Ptr)Array objects and we also avoid realloc'ing their storage.
This commit is contained in:
parent
c1c764255f
commit
cf1526cca6
@ -162,6 +162,7 @@ gtk_snapshot_new (void)
|
||||
|
||||
snapshot = g_object_new (GTK_TYPE_SNAPSHOT, NULL);
|
||||
|
||||
snapshot->from_parent = FALSE;
|
||||
snapshot->state_stack = g_array_new (FALSE, TRUE, sizeof (GtkSnapshotState));
|
||||
g_array_set_clear_func (snapshot->state_stack, (GDestroyNotify)gtk_snapshot_state_clear);
|
||||
snapshot->nodes = g_ptr_array_new_with_free_func ((GDestroyNotify)gsk_render_node_unref);
|
||||
@ -173,6 +174,24 @@ gtk_snapshot_new (void)
|
||||
return snapshot;
|
||||
}
|
||||
|
||||
/* Private. Does the same as _new but does not allocate a NEW
|
||||
* state/node stack. */
|
||||
GtkSnapshot *
|
||||
gtk_snapshot_new_with_parent (GtkSnapshot *parent_snapshot)
|
||||
{
|
||||
GtkSnapshot *snapshot = g_object_new (GTK_TYPE_SNAPSHOT, NULL);
|
||||
|
||||
snapshot->state_stack = parent_snapshot->state_stack;
|
||||
snapshot->nodes = parent_snapshot->nodes;
|
||||
snapshot->from_parent = TRUE;
|
||||
|
||||
gtk_snapshot_push_state (snapshot,
|
||||
0, 0,
|
||||
gtk_snapshot_collect_default);
|
||||
|
||||
return snapshot;
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_snapshot_free_to_node: (skip)
|
||||
* @snapshot: (transfer full): a #GtkSnapshot
|
||||
@ -904,7 +923,8 @@ gtk_snapshot_pop_internal (GtkSnapshot *snapshot)
|
||||
guint state_index;
|
||||
GskRenderNode *node;
|
||||
|
||||
if (snapshot->state_stack->len == 0)
|
||||
if (snapshot->state_stack->len == 0 &&
|
||||
!snapshot->from_parent)
|
||||
{
|
||||
g_warning ("Too many gtk_snapshot_pop() calls.");
|
||||
return NULL;
|
||||
@ -950,17 +970,21 @@ gtk_snapshot_to_node (GtkSnapshot *snapshot)
|
||||
GskRenderNode *result;
|
||||
|
||||
/* We should have exactly our initial state */
|
||||
if (snapshot->state_stack->len > 1)
|
||||
if (snapshot->state_stack->len > 1 &&
|
||||
!snapshot->from_parent)
|
||||
{
|
||||
g_warning ("Too many gtk_snapshot_push() calls. %u states remaining.", snapshot->state_stack->len);
|
||||
}
|
||||
|
||||
|
||||
result = gtk_snapshot_pop_internal (snapshot);
|
||||
|
||||
g_array_free (snapshot->state_stack, TRUE);
|
||||
snapshot->state_stack = NULL;
|
||||
if (!snapshot->from_parent)
|
||||
{
|
||||
g_array_free (snapshot->state_stack, TRUE);
|
||||
g_ptr_array_free (snapshot->nodes, TRUE);
|
||||
}
|
||||
|
||||
g_ptr_array_free (snapshot->nodes, TRUE);
|
||||
snapshot->state_stack = NULL;
|
||||
snapshot->nodes = NULL;
|
||||
|
||||
return result;
|
||||
|
@ -90,6 +90,8 @@ struct _GdkSnapshot {
|
||||
|
||||
GArray *state_stack;
|
||||
GPtrArray *nodes;
|
||||
|
||||
guint from_parent : 1;
|
||||
};
|
||||
|
||||
struct _GtkSnapshotClass {
|
||||
@ -99,6 +101,8 @@ struct _GtkSnapshotClass {
|
||||
void gtk_snapshot_append_node_internal (GtkSnapshot *snapshot,
|
||||
GskRenderNode *node);
|
||||
|
||||
GtkSnapshot * gtk_snapshot_new_with_parent (GtkSnapshot *parent_snapshot);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GTK_SNAPSHOT_PRIVATE_H__ */
|
||||
|
@ -12961,7 +12961,7 @@ gtk_widget_create_render_node (GtkWidget *widget,
|
||||
if (opacity <= 0.0)
|
||||
return NULL;
|
||||
|
||||
snapshot = gtk_snapshot_new ();
|
||||
snapshot = gtk_snapshot_new_with_parent (parent_snapshot);
|
||||
|
||||
_gtk_widget_get_allocation (widget, &allocation);
|
||||
gtk_snapshot_push_debug (snapshot,
|
||||
|
Loading…
Reference in New Issue
Block a user