summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEmmanuele Bassi <ebassi@gnome.org>2016-07-05 17:41:01 +0100
committerEmmanuele Bassi <ebassi@gnome.org>2016-07-05 17:41:01 +0100
commitc4bf786e42360735cb947bf76333df781c8670e7 (patch)
treee04617076165f134e7f007ffe34e41e77b220454
parent4470d7d26949c96599a998b86ba92f07022524d4 (diff)
downloadgtk+-wip/ebassi/gsk-render-node-pool.tar.gz
gsk: Use GskRenderer to create render nodeswip/ebassi/gsk-render-node-pool
Instead of letting users create their own GskRenderNode instances we should cache render nodes inside GskRenderer. As rendering may end up resulting in thousands or more render nodes per frame, the memory pressure on the slice allocator may end up degrading our performance. By having render nodes cached and handed out from a pool we can recycle instances at every frame.
-rw-r--r--gsk/gskrenderer.c50
-rw-r--r--gsk/gskrenderer.h3
-rw-r--r--gsk/gskrendernode.c39
-rw-r--r--gsk/gskrendernode.h2
-rw-r--r--gsk/gskrendernodeprivate.h4
-rw-r--r--gtk/gtkwidget.c4
6 files changed, 95 insertions, 7 deletions
diff --git a/gsk/gskrenderer.c b/gsk/gskrenderer.c
index f9a9fedccb..f5ea2d9092 100644
--- a/gsk/gskrenderer.c
+++ b/gsk/gskrenderer.c
@@ -72,6 +72,9 @@ typedef struct
int scale_factor;
+ GPtrArray *render_nodes;
+ int last_render_node;
+
gboolean is_realized : 1;
gboolean auto_clear : 1;
gboolean use_alpha : 1;
@@ -867,6 +870,11 @@ gsk_renderer_realize (GskRenderer *renderer)
return TRUE;
priv->is_realized = GSK_RENDERER_GET_CLASS (renderer)->realize (renderer);
+ if (priv->is_realized)
+ {
+ priv->render_nodes = g_ptr_array_new_with_free_func ((GDestroyNotify) gsk_render_node_unref);
+ priv->last_render_node = 0;
+ }
return priv->is_realized;
}
@@ -891,6 +899,9 @@ gsk_renderer_unrealize (GskRenderer *renderer)
GSK_RENDERER_GET_CLASS (renderer)->unrealize (renderer);
+ g_clear_pointer (&priv->render_nodes, g_ptr_array_unref);
+ priv->last_render_node = 0;
+
priv->is_realized = FALSE;
}
@@ -930,6 +941,7 @@ gsk_renderer_render (GskRenderer *renderer,
g_clear_object (&priv->drawing_context);
g_clear_pointer (&priv->root_node, gsk_render_node_unref);
+ priv->last_render_node = 0;
}
/**
@@ -1081,3 +1093,41 @@ gsk_renderer_get_for_display (GdkDisplay *display)
return g_object_new (renderer_type, "display", display, NULL);
}
+
+/**
+ * gsk_renderer_create_render_node:
+ * @renderer: a #GskRenderer
+ *
+ * Creates a new #GskRenderNode.
+ *
+ * Returns: (transfer full): the newly created #GskRenderNode
+ *
+ * Since: 3.22
+ */
+GskRenderNode *
+gsk_renderer_create_render_node (GskRenderer *renderer)
+{
+ GskRendererPrivate *priv = gsk_renderer_get_instance_private (renderer);
+ GskRenderNode *res;
+
+ g_return_val_if_fail (GSK_IS_RENDERER (renderer), NULL);
+
+ if (priv->last_render_node < priv->render_nodes->len)
+ {
+ int idx = priv->last_render_node;
+
+ priv->last_render_node += 1;
+
+ res = g_ptr_array_index (priv->render_nodes, idx);
+ gsk_render_node_clear (res);
+ }
+ else
+ {
+ res = gsk_render_node_new ();
+ g_ptr_array_add (priv->render_nodes, res);
+
+ priv->last_render_node = priv->render_nodes->len - 1;
+ }
+
+ return gsk_render_node_ref (res);
+}
diff --git a/gsk/gskrenderer.h b/gsk/gskrenderer.h
index ec1d3aacc2..b8cf446f9e 100644
--- a/gsk/gskrenderer.h
+++ b/gsk/gskrenderer.h
@@ -101,6 +101,9 @@ void gsk_renderer_render (GskRenderer
GskRenderNode *root,
GdkDrawingContext *context);
+GDK_AVAILABLE_IN_3_22
+GskRenderNode * gsk_renderer_create_render_node (GskRenderer *renderer);
+
G_END_DECLS
#endif /* __GSK_RENDERER_H__ */
diff --git a/gsk/gskrendernode.c b/gsk/gskrendernode.c
index 9fe76d64f7..04f2bbdc66 100644
--- a/gsk/gskrendernode.c
+++ b/gsk/gskrendernode.c
@@ -144,10 +144,15 @@ gsk_render_node_finalize (GskRenderNode *self)
{
GskRenderNodeIter iter;
+ /* We need to drop the reference on each child
+ * before clearing the node
+ */
gsk_render_node_iter_init (&iter, self);
while (gsk_render_node_iter_next (&iter, NULL))
gsk_render_node_iter_remove (&iter);
+ gsk_render_node_clear (self);
+
g_type_free_instance ((GTypeInstance *) self);
}
@@ -231,14 +236,12 @@ gsk_render_node_get_type (void)
return gsk_render_node_type__volatile;
}
-/**
+/*< private >
* gsk_render_node_new:
*
* Creates a new #GskRenderNode, to be used with #GskRenderer.
*
* Returns: (transfer full): the newly created #GskRenderNode
- *
- * Since: 3.22
*/
GskRenderNode *
gsk_render_node_new (void)
@@ -246,6 +249,36 @@ gsk_render_node_new (void)
return (GskRenderNode *) g_type_create_instance (GSK_TYPE_RENDER_NODE);
}
+void
+gsk_render_node_clear (GskRenderNode *self)
+{
+ graphene_rect_init_from_rect (&self->bounds, graphene_rect_zero ());
+
+ graphene_matrix_init_identity (&self->transform);
+ graphene_matrix_init_identity (&self->child_transform);
+
+ self->opacity = 1.0;
+
+ self->is_mutable = TRUE;
+ self->opaque = FALSE;
+ self->hidden = FALSE;
+ self->needs_world_matrix_update = TRUE;
+
+ self->parent = NULL;
+ self->first_child = NULL;
+ self->last_child = NULL;
+ self->prev_sibling = NULL;
+ self->next_sibling = NULL;
+ self->n_children = 0;
+
+ self->age = 0;
+
+ g_free (self->name);
+ self->name = NULL;
+
+ g_clear_pointer (&self->surface, cairo_surface_destroy);
+}
+
/**
* gsk_render_node_ref:
* @node: a #GskRenderNode
diff --git a/gsk/gskrendernode.h b/gsk/gskrendernode.h
index a4709ff453..8cbd243497 100644
--- a/gsk/gskrendernode.h
+++ b/gsk/gskrendernode.h
@@ -39,8 +39,6 @@ GDK_AVAILABLE_IN_3_22
GType gsk_render_node_get_type (void) G_GNUC_CONST;
GDK_AVAILABLE_IN_3_22
-GskRenderNode * gsk_render_node_new (void);
-GDK_AVAILABLE_IN_3_22
GskRenderNode * gsk_render_node_ref (GskRenderNode *node);
GDK_AVAILABLE_IN_3_22
void gsk_render_node_unref (GskRenderNode *node);
diff --git a/gsk/gskrendernodeprivate.h b/gsk/gskrendernodeprivate.h
index 9893f962c1..e1b796416f 100644
--- a/gsk/gskrendernodeprivate.h
+++ b/gsk/gskrendernodeprivate.h
@@ -86,6 +86,10 @@ void gsk_render_node_update_world_matrix (GskRenderNode *node,
void gsk_render_node_get_world_matrix (GskRenderNode *node,
graphene_matrix_t *mv);
+GskRenderNode *gsk_render_node_new (void);
+
+void gsk_render_node_clear (GskRenderNode *node);
+
int gsk_render_node_get_size (GskRenderNode *root);
G_END_DECLS
diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c
index 90e0f2616e..fd3c728718 100644
--- a/gtk/gtkwidget.c
+++ b/gtk/gtkwidget.c
@@ -17479,7 +17479,7 @@ gtk_widget_get_render_node (GtkWidget *widget,
GskRenderNode *tmp;
cairo_t *cr;
- tmp = gsk_render_node_new ();
+ tmp = gsk_renderer_create_render_node (renderer);
gsk_render_node_set_bounds (tmp, &bounds);
gsk_render_node_set_transform (tmp, &m);
cr = gsk_render_node_get_draw_context (tmp);
@@ -17501,7 +17501,7 @@ gtk_widget_get_render_node (GtkWidget *widget,
gboolean result;
cairo_t *cr;
- tmp = gsk_render_node_new ();
+ tmp = gsk_renderer_create_render_node (renderer);
gsk_render_node_set_bounds (tmp, &bounds);
gsk_render_node_set_transform (tmp, &m);
cr = gsk_render_node_get_draw_context (tmp);