Compare commits

...

1 Commits

Author SHA1 Message Date
Alexander Larsson
8ecbd85acc gsk: Add GskRenderTree
A render tree owns all the nodes that are created during a frame,
and they are allocated with a custom allocator. All the resources
allocated for the tree are kept until destruction, and then
it is all released at the same time.

Allocation happes in chunks which makes both allocation and
freeing very efficient, and also quite cache efficient.

This somewhat changes the memory management of GskRenderNode. All
nodes created by the tree are owned by the tree, and normally you
don't need to ref them. If you want to keep them around you can still
ref them, but that actually refs the entire tree.
2017-01-11 16:39:39 +01:00
16 changed files with 420 additions and 373 deletions

View File

@@ -688,38 +688,38 @@ gsk_renderer_render_texture (GskRenderer *renderer,
/**
* gsk_renderer_render:
* @renderer: a #GskRenderer
* @root: a #GskRenderNode
* @root_node: a #GskRenderNode
* @context: The drawing context created via gsk_renderer_begin_draw_frame()
*
* Renders the scene graph, described by a tree of #GskRenderNode instances,
* using the given #GdkDrawingContext.
*
* The @renderer will acquire a reference on the #GskRenderNode tree while
* The @renderer will acquire a reference on the #GskRenderNode while
* the rendering is in progress.
*
* Since: 3.90
*/
void
gsk_renderer_render (GskRenderer *renderer,
GskRenderNode *root,
GskRenderNode *root_node,
GdkDrawingContext *context)
{
GskRendererPrivate *priv = gsk_renderer_get_instance_private (renderer);
g_return_if_fail (GSK_IS_RENDERER (renderer));
g_return_if_fail (priv->is_realized);
g_return_if_fail (GSK_IS_RENDER_NODE (root));
g_return_if_fail (GSK_IS_RENDER_NODE (root_node));
g_return_if_fail (priv->root_node == NULL);
g_return_if_fail (GDK_IS_DRAWING_CONTEXT (context));
g_return_if_fail (context == priv->drawing_context);
priv->root_node = gsk_render_node_ref (root);
priv->root_node = gsk_render_node_ref (root_node);
#ifdef G_ENABLE_DEBUG
gsk_profiler_reset (priv->profiler);
#endif
GSK_RENDERER_GET_CLASS (renderer)->render (renderer, root);
GSK_RENDERER_GET_CLASS (renderer)->render (renderer, root_node);
#ifdef G_ENABLE_DEBUG
if (GSK_DEBUG_CHECK (RENDERER))

View File

@@ -75,7 +75,7 @@ GdkDrawingContext * gsk_renderer_begin_draw_frame (GskRenderer
const cairo_region_t *region);
GDK_AVAILABLE_IN_3_90
void gsk_renderer_render (GskRenderer *renderer,
GskRenderNode *root,
GskRenderNode *root_node,
GdkDrawingContext *context);
GDK_AVAILABLE_IN_3_90
void gsk_renderer_end_draw_frame (GskRenderer *renderer,

View File

@@ -53,6 +53,113 @@
#include <gobject/gvaluecollector.h>
#define ALLOCATE_CHUNK_SIZE (16*1024 - 2*sizeof(gsize))
#define ALIGN(size, base) ((base) * (gsize) (((size) + (base) - 1) / (base)))
struct _GskRenderTree
{
GObject parent_instance;
guint8 *chunk;
gsize chunk_offset;
int chunk_count;
GPtrArray *destroy_list;
};
G_DEFINE_TYPE (GskRenderTree, gsk_render_tree, G_TYPE_OBJECT)
G_DEFINE_QUARK (gsk-serialization-error-quark, gsk_serialization_error)
static void
gsk_render_tree_finalize (GObject *gobject)
{
GskRenderTree *self = GSK_RENDER_TREE (gobject);
int i;
/* We free in reverse order, because the notify may touch
something allocated before it */
for (i = self->destroy_list->len - 2; i >= 0 ; i -= 2)
{
GDestroyNotify notify = g_ptr_array_index (self->destroy_list, i);
gpointer data = g_ptr_array_index (self->destroy_list, i + 1);
notify (data);
}
g_ptr_array_free (self->destroy_list, TRUE);
G_OBJECT_CLASS (gsk_render_tree_parent_class)->finalize (gobject);
}
static void
gsk_render_tree_class_init (GskRenderTreeClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
gobject_class->finalize = gsk_render_tree_finalize;
}
static void
gsk_render_tree_init (GskRenderTree *self)
{
self->destroy_list = g_ptr_array_new ();
}
void
gsk_render_tree_add_cleanup (GskRenderTree *self,
GDestroyNotify notify,
gpointer data)
{
g_ptr_array_add (self->destroy_list, notify);
g_ptr_array_add (self->destroy_list, data);
}
/* Note: Align-size must be a power of two */
gpointer
gsk_render_tree_allocate (GskRenderTree *self, gsize n_bytes, gsize align_size)
{
gpointer data = NULL;
if (n_bytes >= ALLOCATE_CHUNK_SIZE / 4)
{
data = g_malloc0 (n_bytes);
gsk_render_tree_add_cleanup (self, g_free, data);
}
else
{
self->chunk_offset = (self->chunk_offset + align_size - 1) & ~(align_size - 1);
if (self->chunk == NULL || (ALLOCATE_CHUNK_SIZE - self->chunk_offset) < n_bytes)
{
self->chunk = g_malloc (ALLOCATE_CHUNK_SIZE);
gsk_render_tree_add_cleanup (self, g_free, self->chunk);
self->chunk_offset = 0;
}
data = self->chunk + self->chunk_offset;
self->chunk_offset += n_bytes;
memset (data, 0, n_bytes);
}
return data;
}
GskRenderNode *
gsk_render_tree_ref_foreign (GskRenderTree *tree, GskRenderNode *node)
{
if (node->tree != tree)
gsk_render_tree_add_cleanup (tree, (GDestroyNotify)gsk_render_node_unref, gsk_render_node_ref (node));
return node;
}
GskRenderTree *
gsk_render_tree_new ()
{
return g_object_new (GSK_TYPE_RENDER_TREE,
NULL);
}
/**
* GskRenderNode: (ref-func gsk_render_node_ref) (unref-func gsk_render_node_unref)
*
@@ -65,42 +172,34 @@ G_DEFINE_BOXED_TYPE (GskRenderNode, gsk_render_node,
gsk_render_node_ref,
gsk_render_node_unref)
G_DEFINE_QUARK (gsk-serialization-error-quark, gsk_serialization_error)
static void
gsk_render_node_finalize (GskRenderNode *self)
{
self->node_class->finalize (self);
g_clear_pointer (&self->name, g_free);
g_free (self);
}
/*< private >
* gsk_render_node_new:
* gsk_render_tree_new_node:
* @node_class: class structure for this node
*
* Returns: (transfer full): the newly created #GskRenderNode
*/
GskRenderNode *
gsk_render_node_new (const GskRenderNodeClass *node_class, gsize extra_size)
gsk_render_tree_new_node (GskRenderTree *self, const GskRenderNodeClass *node_class, gsize extra_size)
{
GskRenderNode *self;
GskRenderNode *node;
g_return_val_if_fail (node_class != NULL, NULL);
g_return_val_if_fail (node_class->node_type != GSK_NOT_A_RENDER_NODE, NULL);
self = g_malloc0 (node_class->struct_size + extra_size);
node = gsk_render_tree_allocate (self, node_class->struct_size + extra_size, 2*sizeof(gsize));
self->node_class = node_class;
node->node_class = node_class;
node->tree = self;
node->min_filter = GSK_SCALING_FILTER_NEAREST;
node->mag_filter = GSK_SCALING_FILTER_NEAREST;
self->ref_count = 1;
return node;
}
self->min_filter = GSK_SCALING_FILTER_NEAREST;
self->mag_filter = GSK_SCALING_FILTER_NEAREST;
return self;
GskRenderTree *
gsk_render_node_get_tree (GskRenderNode *self)
{
return self->tree;
}
/**
@@ -108,6 +207,10 @@ gsk_render_node_new (const GskRenderNodeClass *node_class, gsize extra_size)
* @node: a #GskRenderNode
*
* Acquires a reference on the given #GskRenderNode.
* All nodes are owned by the tree they are part of, so normally you don't
* need to ref individual nodes.
*
* Note: This keeps the whole tree alive for the lifetime of the node.
*
* Returns: (transfer none): the #GskRenderNode with an additional reference
*
@@ -116,9 +219,12 @@ gsk_render_node_new (const GskRenderNodeClass *node_class, gsize extra_size)
GskRenderNode *
gsk_render_node_ref (GskRenderNode *node)
{
GskRenderTree *tree;
g_return_val_if_fail (GSK_IS_RENDER_NODE (node), NULL);
g_atomic_int_inc (&node->ref_count);
tree = gsk_render_node_get_tree (node);
g_object_ref (tree);
return node;
}
@@ -137,10 +243,12 @@ gsk_render_node_ref (GskRenderNode *node)
void
gsk_render_node_unref (GskRenderNode *node)
{
GskRenderTree *tree;
g_return_if_fail (GSK_IS_RENDER_NODE (node));
if (g_atomic_int_dec_and_test (&node->ref_count))
gsk_render_node_finalize (node);
tree = gsk_render_node_get_tree (node);
g_object_unref (tree);
}
/**
@@ -209,10 +317,16 @@ void
gsk_render_node_set_name (GskRenderNode *node,
const char *name)
{
GskRenderTree *tree;
char *new_name;
g_return_if_fail (GSK_IS_RENDER_NODE (node));
g_free (node->name);
node->name = g_strdup (name);
tree = gsk_render_node_get_tree (node);
new_name = gsk_render_tree_allocate (tree, strlen (name) + 1, 1);
strcpy (new_name, name);
node->name = new_name;
}
/**
@@ -391,6 +505,7 @@ gsk_render_node_deserialize (GBytes *bytes,
guint32 version, node_type;
GVariant *variant, *node_variant;
GskRenderNode *node = NULL;
GskRenderTree *tree;
variant = g_variant_new_from_bytes (G_VARIANT_TYPE ("(suuv)"), bytes, FALSE);
@@ -410,7 +525,10 @@ gsk_render_node_deserialize (GBytes *bytes,
goto out;
}
node = gsk_render_node_deserialize_node (node_type, node_variant, error);
tree = gsk_render_tree_new ();
node = gsk_render_node_deserialize_node (tree, node_type, node_variant, error);
gsk_render_node_ref (node);
g_object_unref (tree);
out:
g_free (id_string);

View File

@@ -28,12 +28,17 @@
G_BEGIN_DECLS
#define GSK_TYPE_RENDER_NODE (gsk_render_node_get_type ())
#define GSK_TYPE_RENDER_TREE (gsk_render_tree_get_type ())
GDK_AVAILABLE_IN_3_90
G_DECLARE_FINAL_TYPE (GskRenderTree, gsk_render_tree, GSK, RENDER_TREE, GObject)
#define GSK_TYPE_RENDER_NODE (gsk_render_node_get_type ())
#define GSK_IS_RENDER_NODE(obj) ((obj) != NULL)
#define GSK_SERIALIZATION_ERROR (gsk_serialization_error_quark ())
typedef struct _GskRenderTree GskRenderTree;
typedef struct _GskRenderNode GskRenderNode;
typedef struct _GskColorStop GskColorStop;
typedef struct _GskShadow GskShadow;
@@ -53,10 +58,11 @@ struct _GskShadow
};
GDK_AVAILABLE_IN_3_90
GType gsk_render_node_get_type (void) G_GNUC_CONST;
GQuark gsk_serialization_error_quark (void);
GskRenderTree * gsk_render_tree_new (void);
GDK_AVAILABLE_IN_3_90
GQuark gsk_serialization_error_quark (void);
GType gsk_render_node_get_type (void) G_GNUC_CONST;
GDK_AVAILABLE_IN_3_90
GskRenderNode * gsk_render_node_ref (GskRenderNode *node);
@@ -67,40 +73,47 @@ GDK_AVAILABLE_IN_3_90
GskRenderNodeType gsk_render_node_get_node_type (GskRenderNode *node);
GDK_AVAILABLE_IN_3_90
GskRenderNode * gsk_color_node_new (const GdkRGBA *rgba,
GskRenderNode * gsk_color_node_new (GskRenderTree *tree,
const GdkRGBA *rgba,
const graphene_rect_t *bounds);
GDK_AVAILABLE_IN_3_90
GskRenderNode * gsk_texture_node_new (GskTexture *texture,
GskRenderNode * gsk_texture_node_new (GskRenderTree *tree,
GskTexture *texture,
const graphene_rect_t *bounds);
GDK_AVAILABLE_IN_3_90
GskRenderNode * gsk_linear_gradient_node_new (const graphene_rect_t *bounds,
GskRenderNode * gsk_linear_gradient_node_new (GskRenderTree *tree,
const graphene_rect_t *bounds,
const graphene_point_t *start,
const graphene_point_t *end,
const GskColorStop *color_stops,
gsize n_color_stops);
GDK_AVAILABLE_IN_3_90
GskRenderNode * gsk_repeating_linear_gradient_node_new (const graphene_rect_t *bounds,
GskRenderNode * gsk_repeating_linear_gradient_node_new (GskRenderTree *tree,
const graphene_rect_t *bounds,
const graphene_point_t *start,
const graphene_point_t *end,
const GskColorStop *color_stops,
gsize n_color_stops);
GDK_AVAILABLE_IN_3_90
GskRenderNode * gsk_border_node_new (const GskRoundedRect *outline,
GskRenderNode * gsk_border_node_new (GskRenderTree *tree,
const GskRoundedRect *outline,
const float border_width[4],
const GdkRGBA border_color[4]);
GDK_AVAILABLE_IN_3_90
GskRenderNode * gsk_inset_shadow_node_new (const GskRoundedRect *outline,
GskRenderNode * gsk_inset_shadow_node_new (GskRenderTree *tree,
const GskRoundedRect *outline,
const GdkRGBA *color,
float dx,
float dy,
float spread,
float blur_radius);
GDK_AVAILABLE_IN_3_90
GskRenderNode * gsk_outset_shadow_node_new (const GskRoundedRect *outline,
GskRenderNode * gsk_outset_shadow_node_new (GskRenderTree *tree,
const GskRoundedRect *outline,
const GdkRGBA *color,
float dx,
float dy,
@@ -108,13 +121,15 @@ GskRenderNode * gsk_outset_shadow_node_new (const GskRounde
float blur_radius);
GDK_AVAILABLE_IN_3_90
GskRenderNode * gsk_cairo_node_new (const graphene_rect_t *bounds);
GskRenderNode * gsk_cairo_node_new (GskRenderTree *tree,
const graphene_rect_t *bounds);
GDK_AVAILABLE_IN_3_90
cairo_t * gsk_cairo_node_get_draw_context (GskRenderNode *node,
GskRenderer *renderer);
GDK_AVAILABLE_IN_3_90
GskRenderNode * gsk_container_node_new (GskRenderNode **children,
GskRenderNode * gsk_container_node_new (GskRenderTree *tree,
GskRenderNode **children,
guint n_children);
GDK_AVAILABLE_IN_3_90
guint gsk_container_node_get_n_children (GskRenderNode *node);
@@ -123,51 +138,60 @@ GskRenderNode * gsk_container_node_get_child (GskRenderNode
guint idx);
GDK_AVAILABLE_IN_3_90
GskRenderNode * gsk_transform_node_new (GskRenderNode *child,
GskRenderNode * gsk_transform_node_new (GskRenderTree *tree,
GskRenderNode *child,
const graphene_matrix_t *transform);
GDK_AVAILABLE_IN_3_90
GskRenderNode * gsk_transform_node_get_child (GskRenderNode *node);
GDK_AVAILABLE_IN_3_90
GskRenderNode * gsk_opacity_node_new (GskRenderNode *child,
GskRenderNode * gsk_opacity_node_new (GskRenderTree *tree,
GskRenderNode *child,
double opacity);
GDK_AVAILABLE_IN_3_90
GskRenderNode * gsk_opacity_node_get_child (GskRenderNode *node);
GDK_AVAILABLE_IN_3_90
GskRenderNode * gsk_color_matrix_node_new (GskRenderNode *child,
GskRenderNode * gsk_color_matrix_node_new (GskRenderTree *tree,
GskRenderNode *child,
const graphene_matrix_t *color_matrix,
const graphene_vec4_t *color_offset);
GDK_AVAILABLE_IN_3_90
GskRenderNode * gsk_repeat_node_new (const graphene_rect_t *bounds,
GskRenderNode * gsk_repeat_node_new (GskRenderTree *tree,
const graphene_rect_t *bounds,
GskRenderNode *child,
const graphene_rect_t *child_bounds);
GDK_AVAILABLE_IN_3_90
GskRenderNode * gsk_clip_node_new (GskRenderNode *child,
GskRenderNode * gsk_clip_node_new (GskRenderTree *tree,
GskRenderNode *child,
const graphene_rect_t *clip);
GDK_AVAILABLE_IN_3_90
GskRenderNode * gsk_clip_node_get_child (GskRenderNode *node);
GDK_AVAILABLE_IN_3_90
GskRenderNode * gsk_rounded_clip_node_new (GskRenderNode *child,
GskRenderNode * gsk_rounded_clip_node_new (GskRenderTree *tree,
GskRenderNode *child,
const GskRoundedRect *clip);
GDK_AVAILABLE_IN_3_90
GskRenderNode * gsk_rounded_clip_node_get_child (GskRenderNode *node);
GDK_AVAILABLE_IN_3_90
GskRenderNode * gsk_shadow_node_new (GskRenderNode *child,
GskRenderNode * gsk_shadow_node_new (GskRenderTree *tree,
GskRenderNode *child,
const GskShadow *shadows,
gsize n_shadows);
GDK_AVAILABLE_IN_3_90
GskRenderNode * gsk_blend_node_new (GskRenderNode *bottom,
GskRenderNode * gsk_blend_node_new (GskRenderTree *tree,
GskRenderNode *bottom,
GskRenderNode *top,
GskBlendMode blend_mode);
GDK_AVAILABLE_IN_3_90
GskRenderNode * gsk_cross_fade_node_new (GskRenderNode *start,
GskRenderNode * gsk_cross_fade_node_new (GskRenderTree *tree,
GskRenderNode *start,
GskRenderNode *end,
double progress);

File diff suppressed because it is too large Load Diff

View File

@@ -13,8 +13,7 @@ typedef struct _GskRenderNodeClass GskRenderNodeClass;
struct _GskRenderNode
{
const GskRenderNodeClass *node_class;
volatile int ref_count;
GskRenderTree *tree;
/* Use for debugging */
char *name;
@@ -31,19 +30,23 @@ struct _GskRenderNodeClass
GskRenderNodeType node_type;
gsize struct_size;
const char *type_name;
void (* finalize) (GskRenderNode *node);
void (* draw) (GskRenderNode *node,
cairo_t *cr);
GVariant * (* serialize) (GskRenderNode *node);
GskRenderNode * (* deserialize) (GVariant *variant,
GskRenderNode * (* deserialize) (GskRenderTree *tree,
GVariant *variant,
GError **error);
};
GskRenderNode *gsk_render_node_new (const GskRenderNodeClass *node_class, gsize extra_size);
GskRenderNode *gsk_render_tree_new_node (GskRenderTree *tree, const GskRenderNodeClass *node_class, gsize extra_size);
gpointer gsk_render_tree_allocate (GskRenderTree *self, gsize n_bytes, gsize align_size);
void gsk_render_tree_add_cleanup (GskRenderTree *tree, GDestroyNotify notify, gpointer data);
GskRenderNode *gsk_render_tree_ref_foreign (GskRenderTree *tree, GskRenderNode *node);
GVariant * gsk_render_node_serialize_node (GskRenderNode *node);
GskRenderNode * gsk_render_node_deserialize_node (GskRenderNodeType type, GVariant *variant, GError **error);
GskRenderNode * gsk_render_node_deserialize_node (GskRenderTree *tree, GskRenderNodeType type, GVariant *variant, GError **error);
GskRenderTree *gsk_render_node_get_tree (GskRenderNode *self);
double gsk_opacity_node_get_opacity (GskRenderNode *node);
GskRenderNode * gsk_color_matrix_node_get_child (GskRenderNode *node);
@@ -62,7 +65,7 @@ const GskRoundedRect * gsk_border_node_peek_outline (GskRenderNode *node);
float gsk_border_node_get_width (GskRenderNode *node, guint i);
const GdkRGBA * gsk_border_node_peek_color (GskRenderNode *node, guint i);
GskRenderNode *gsk_cairo_node_new_for_surface (const graphene_rect_t *bounds, cairo_surface_t *surface);
GskRenderNode *gsk_cairo_node_new_for_surface (GskRenderTree *tree, const graphene_rect_t *bounds, cairo_surface_t *surface);
cairo_surface_t *gsk_cairo_node_get_surface (GskRenderNode *node);
GskTexture *gsk_texture_node_get_texture (GskRenderNode *node);

View File

@@ -139,29 +139,23 @@ gtk_css_image_cross_fade_snapshot (GtkCssImage *image,
if (start_node && end_node)
{
GskRenderNode *node = gsk_cross_fade_node_new (start_node, end_node, cross_fade->progress);
GskRenderNode *node = gsk_cross_fade_node_new (gtk_snapshot_get_tree (snapshot), start_node, end_node, cross_fade->progress);
if (snapshot->record_names)
gsk_render_node_set_name (node, "CrossFade");
gtk_snapshot_append_node (snapshot, node);
gsk_render_node_unref (node);
gsk_render_node_unref (start_node);
gsk_render_node_unref (end_node);
}
else if (start_node)
{
gtk_snapshot_push_opacity (snapshot, 1.0 - cross_fade->progress, "CrossFadeStart");
gtk_snapshot_append_node (snapshot, start_node);
gtk_snapshot_pop_and_append (snapshot);
gsk_render_node_unref (start_node);
}
else if (end_node)
{
gtk_snapshot_push_opacity (snapshot, cross_fade->progress, "CrossFadeEnd");
gtk_snapshot_append_node (snapshot, end_node);
gtk_snapshot_pop_and_append (snapshot);
gsk_render_node_unref (end_node);
}
}
}

View File

@@ -238,6 +238,7 @@ gtk_css_image_linear_snapshot (GtkCssImage *image,
if (linear->repeating)
{
node = gsk_repeating_linear_gradient_node_new (
gtk_snapshot_get_tree (snapshot),
&GRAPHENE_RECT_INIT (off_x, off_y, width, height),
&GRAPHENE_POINT_INIT (off_x + width / 2 + x * (start - 0.5), off_y + height / 2 + y * (start - 0.5)),
&GRAPHENE_POINT_INIT (off_x + width / 2 + x * (end - 0.5), off_y + height / 2 + y * (end - 0.5)),
@@ -247,6 +248,7 @@ gtk_css_image_linear_snapshot (GtkCssImage *image,
else
{
node = gsk_linear_gradient_node_new (
gtk_snapshot_get_tree (snapshot),
&GRAPHENE_RECT_INIT (off_x, off_y, width, height),
&GRAPHENE_POINT_INIT (off_x + width / 2 + x * (start - 0.5), off_y + height / 2 + y * (start - 0.5)),
&GRAPHENE_POINT_INIT (off_x + width / 2 + x * (end - 0.5), off_y + height / 2 + y * (end - 0.5)),
@@ -262,8 +264,6 @@ gtk_css_image_linear_snapshot (GtkCssImage *image,
}
gtk_snapshot_append_node (snapshot, node);
gsk_render_node_unref (node);
}

View File

@@ -1051,7 +1051,8 @@ gtk_css_shadow_value_snapshot_outset (const GtkCssValue *shadow,
gsk_rounded_rect_init_copy (&outline, border_box);
gsk_rounded_rect_offset (&outline, off_x, off_y);
node = gsk_outset_shadow_node_new (&outline,
node = gsk_outset_shadow_node_new (gtk_snapshot_get_tree (snapshot),
&outline,
_gtk_css_rgba_value_get_rgba (shadow->color),
_gtk_css_number_value_get (shadow->hoffset, 0),
_gtk_css_number_value_get (shadow->voffset, 0),
@@ -1060,7 +1061,6 @@ gtk_css_shadow_value_snapshot_outset (const GtkCssValue *shadow,
if (snapshot->record_names)
gsk_render_node_set_name (node, "Outset Shadow");
gtk_snapshot_append_node (snapshot, node);
gsk_render_node_unref (node);
}
void
@@ -1082,7 +1082,8 @@ gtk_css_shadow_value_snapshot_inset (const GtkCssValue *shadow,
gsk_rounded_rect_init_copy (&outline, padding_box);
gsk_rounded_rect_offset (&outline, off_x, off_y);
node = gsk_inset_shadow_node_new (&outline,
node = gsk_inset_shadow_node_new (gtk_snapshot_get_tree (snapshot),
&outline,
_gtk_css_rgba_value_get_rgba (shadow->color),
_gtk_css_number_value_get (shadow->hoffset, 0),
_gtk_css_number_value_get (shadow->voffset, 0),
@@ -1091,6 +1092,5 @@ gtk_css_shadow_value_snapshot_inset (const GtkCssValue *shadow,
if (snapshot->record_names)
gsk_render_node_set_name (node, "Inset Shadow");
gtk_snapshot_append_node (snapshot, node);
gsk_render_node_unref (node);
}

View File

@@ -7024,6 +7024,8 @@ gtk_icon_view_create_drag_icon (GtkIconView *icon_view,
gsk_render_node_draw (node, cr);
cairo_destroy (cr);
gsk_render_node_unref (node);
return surface;
}
}

View File

@@ -676,20 +676,16 @@ gtk_css_style_snapshot_background (GtkCssStyle *style,
/* XXX: Is this necessary? Do we need a NULL node? */
if (top == NULL)
top = gsk_container_node_new (NULL, 0);
top = gsk_container_node_new (gtk_snapshot_get_tree (snapshot), NULL, 0);
if (bottom == NULL)
bottom = gsk_container_node_new (NULL, 0);
bottom = gsk_container_node_new (gtk_snapshot_get_tree (snapshot), NULL, 0);
blend = gsk_blend_node_new (bottom, top, blend_mode);
blend = gsk_blend_node_new (gtk_snapshot_get_tree (snapshot), bottom, top, blend_mode);
if (snapshot->record_names)
gsk_render_node_set_name (blend, "BackgroundBlend");
gtk_snapshot_push (snapshot, TRUE, "BackgroundBlendGroup");
gtk_snapshot_append_node (snapshot, blend);
gsk_render_node_unref (blend);
gsk_render_node_unref (top);
gsk_render_node_unref (bottom);
}
}

View File

@@ -437,11 +437,10 @@ snapshot_frame_fill (GtkSnapshot *snapshot,
gsk_rounded_rect_init_copy (&offset_outline, outline);
gsk_rounded_rect_offset (&offset_outline, off_x, off_y);
node = gsk_border_node_new (&offset_outline, border_width, colors);
node = gsk_border_node_new (snapshot->tree, &offset_outline, border_width, colors);
if (snapshot->record_names)
gsk_render_node_set_name (node, "Border");
gtk_snapshot_append_node (snapshot, node);
gsk_render_node_unref (node);
}
static void

View File

@@ -62,11 +62,11 @@ gtk_snapshot_collect_default (GtkSnapshotState *state,
}
else if (n_nodes == 1)
{
node = gsk_render_node_ref (nodes[0]);
node = nodes[0];
}
else
{
node = gsk_container_node_new (nodes, n_nodes);
node = gsk_container_node_new (state->tree, nodes, n_nodes);
if (name)
gsk_render_node_set_name (node, name);
}
@@ -77,6 +77,7 @@ gtk_snapshot_collect_default (GtkSnapshotState *state,
static GtkSnapshotState *
gtk_snapshot_state_new (GtkSnapshotState *parent,
char *name,
GskRenderTree *tree,
cairo_region_t *clip,
int translate_x,
int translate_y,
@@ -92,11 +93,12 @@ gtk_snapshot_state_new (GtkSnapshotState *parent,
else
{
state = g_slice_new0 (GtkSnapshotState);
state->nodes = g_ptr_array_new_with_free_func ((GDestroyNotify) gsk_render_node_unref);
state->nodes = g_ptr_array_new ();
state->parent = parent;
}
state->name = name;
state->tree = tree;
if (clip)
state->clip_region = cairo_region_reference (clip);
state->translate_x = translate_x;
@@ -137,6 +139,7 @@ gtk_snapshot_init (GtkSnapshot *snapshot,
snapshot->state = NULL;
snapshot->record_names = record_names;
snapshot->renderer = renderer;
snapshot->tree = gsk_render_tree_new ();
if (name && record_names)
{
@@ -151,6 +154,7 @@ gtk_snapshot_init (GtkSnapshot *snapshot,
snapshot->state = gtk_snapshot_state_new (NULL,
str,
snapshot->tree,
(cairo_region_t *) clip,
0, 0,
gtk_snapshot_collect_default);
@@ -160,7 +164,7 @@ GskRenderNode *
gtk_snapshot_finish (GtkSnapshot *snapshot)
{
GskRenderNode *result;
result = gtk_snapshot_pop (snapshot);
if (snapshot->state != NULL)
@@ -168,6 +172,9 @@ gtk_snapshot_finish (GtkSnapshot *snapshot)
g_warning ("Too many gtk_snapshot_push() calls.");
}
gsk_render_node_ref (result);
g_clear_object (&snapshot->tree);
return result;
}
@@ -208,6 +215,7 @@ gtk_snapshot_push (GtkSnapshot *snapshot,
{
snapshot->state = gtk_snapshot_state_new (snapshot->state,
str,
snapshot->state->tree,
snapshot->state->clip_region,
snapshot->state->translate_x,
snapshot->state->translate_y,
@@ -217,6 +225,7 @@ gtk_snapshot_push (GtkSnapshot *snapshot,
{
snapshot->state = gtk_snapshot_state_new (snapshot->state,
str,
snapshot->state->tree,
NULL,
0, 0,
gtk_snapshot_collect_default);
@@ -235,12 +244,10 @@ gtk_snapshot_collect_transform (GtkSnapshotState *state,
if (node == NULL)
return NULL;
transform_node = gsk_transform_node_new (node, &state->data.transform.transform);
transform_node = gsk_transform_node_new (state->tree, node, &state->data.transform.transform);
if (name)
gsk_render_node_set_name (transform_node, name);
gsk_render_node_unref (node);
return transform_node;
}
@@ -267,6 +274,7 @@ gtk_snapshot_push_transform (GtkSnapshot *snapshot,
state = gtk_snapshot_state_new (snapshot->state,
str,
snapshot->state->tree,
NULL,
0, 0,
gtk_snapshot_collect_transform);
@@ -295,12 +303,10 @@ gtk_snapshot_collect_opacity (GtkSnapshotState *state,
if (node == NULL)
return NULL;
opacity_node = gsk_opacity_node_new (node, state->data.opacity.opacity);
opacity_node = gsk_opacity_node_new (state->tree, node, state->data.opacity.opacity);
if (name)
gsk_render_node_set_name (opacity_node, name);
gsk_render_node_unref (node);
return opacity_node;
}
@@ -326,6 +332,7 @@ gtk_snapshot_push_opacity (GtkSnapshot *snapshot,
state = gtk_snapshot_state_new (snapshot->state,
str,
snapshot->state->tree,
snapshot->state->clip_region,
snapshot->state->translate_x,
snapshot->state->translate_y,
@@ -346,14 +353,12 @@ gtk_snapshot_collect_color_matrix (GtkSnapshotState *state,
if (node == NULL)
return NULL;
color_matrix_node = gsk_color_matrix_node_new (node,
color_matrix_node = gsk_color_matrix_node_new (state->tree, node,
&state->data.color_matrix.matrix,
&state->data.color_matrix.offset);
if (name)
gsk_render_node_set_name (color_matrix_node, name);
gsk_render_node_unref (node);
return color_matrix_node;
}
@@ -380,6 +385,7 @@ gtk_snapshot_push_color_matrix (GtkSnapshot *snapshot,
state = gtk_snapshot_state_new (snapshot->state,
str,
snapshot->state->tree,
snapshot->state->clip_region,
snapshot->state->translate_x,
snapshot->state->translate_y,
@@ -414,14 +420,12 @@ gtk_snapshot_collect_repeat (GtkSnapshotState *state,
if (node == NULL)
return NULL;
repeat_node = gsk_repeat_node_new (bounds,
repeat_node = gsk_repeat_node_new (state->tree, bounds,
node,
child_bounds->size.width > 0 ? child_bounds : NULL);
if (name)
gsk_render_node_set_name (repeat_node, name);
gsk_render_node_unref (node);
return repeat_node;
}
@@ -458,6 +462,7 @@ gtk_snapshot_push_repeat (GtkSnapshot *snapshot,
state = gtk_snapshot_state_new (snapshot->state,
str,
snapshot->state->tree,
clip,
snapshot->state->translate_x,
snapshot->state->translate_y,
@@ -484,12 +489,10 @@ gtk_snapshot_collect_clip (GtkSnapshotState *state,
if (node == NULL)
return NULL;
clip_node = gsk_clip_node_new (node, &state->data.clip.bounds);
clip_node = gsk_clip_node_new (state->tree, node, &state->data.clip.bounds);
if (name)
gsk_render_node_set_name (clip_node, name);
gsk_render_node_unref (node);
return clip_node;
}
@@ -530,6 +533,7 @@ gtk_snapshot_push_clip (GtkSnapshot *snapshot,
}
state = gtk_snapshot_state_new (snapshot->state,
str,
snapshot->state->tree,
clip,
snapshot->state->translate_x,
snapshot->state->translate_y,
@@ -554,12 +558,10 @@ gtk_snapshot_collect_rounded_clip (GtkSnapshotState *state,
if (node == NULL)
return NULL;
clip_node = gsk_rounded_clip_node_new (node, &state->data.rounded_clip.bounds);
clip_node = gsk_rounded_clip_node_new (state->tree, node, &state->data.rounded_clip.bounds);
if (name)
gsk_render_node_set_name (clip_node, name);
gsk_render_node_unref (node);
return clip_node;
}
@@ -602,6 +604,7 @@ gtk_snapshot_push_rounded_clip (GtkSnapshot *snapshot,
state = gtk_snapshot_state_new (snapshot->state,
str,
snapshot->state->tree,
clip,
snapshot->state->translate_x,
snapshot->state->translate_y,
@@ -626,11 +629,10 @@ gtk_snapshot_collect_shadow (GtkSnapshotState *state,
if (node == NULL)
return NULL;
shadow_node = gsk_shadow_node_new (node, state->data.shadow.shadows, state->data.shadow.n_shadows);
shadow_node = gsk_shadow_node_new (state->tree, node, state->data.shadow.shadows, state->data.shadow.n_shadows);
if (name)
gsk_render_node_set_name (shadow_node, name);
gsk_render_node_unref (node);
if (state->data.shadow.shadows != &state->data.shadow.a_shadow)
g_free (state->data.shadow.shadows);
@@ -661,6 +663,7 @@ gtk_snapshot_push_shadow (GtkSnapshot *snapshot,
state = gtk_snapshot_state_new (snapshot->state,
str,
snapshot->state->tree,
snapshot->state->clip_region,
snapshot->state->translate_x,
snapshot->state->translate_y,
@@ -736,10 +739,7 @@ gtk_snapshot_pop_and_append (GtkSnapshot *snapshot)
node = gtk_snapshot_pop (snapshot);
if (node)
{
gtk_snapshot_append_node (snapshot, node);
gsk_render_node_unref (node);
}
gtk_snapshot_append_node (snapshot, node);
}
/**
@@ -807,6 +807,12 @@ gtk_snapshot_get_offset (GtkSnapshot *snapshot,
*y = snapshot->state->translate_y;
}
GskRenderTree *
gtk_snapshot_get_tree (GtkSnapshot *snapshot)
{
return snapshot->tree;
}
/**
* gtk_snapshot_append_node:
* @snapshot: a #GtkSnapshot
@@ -826,7 +832,7 @@ gtk_snapshot_append_node (GtkSnapshot *snapshot,
if (snapshot->state)
{
g_ptr_array_add (snapshot->state->nodes, gsk_render_node_ref (node));
g_ptr_array_add (snapshot->state->nodes, node);
}
else
{
@@ -863,7 +869,7 @@ gtk_snapshot_append_cairo_node (GtkSnapshot *snapshot,
g_return_val_if_fail (bounds != NULL, NULL);
graphene_rect_offset_r (bounds, snapshot->state->translate_x, snapshot->state->translate_y, &real_bounds);
node = gsk_cairo_node_new (&real_bounds);
node = gsk_cairo_node_new (snapshot->tree, &real_bounds);
if (name && snapshot->record_names)
{
@@ -880,7 +886,6 @@ gtk_snapshot_append_cairo_node (GtkSnapshot *snapshot,
}
gtk_snapshot_append_node (snapshot, node);
gsk_render_node_unref (node);
cr = gsk_cairo_node_get_draw_context (node, snapshot->renderer);
@@ -915,7 +920,7 @@ gtk_snapshot_append_texture_node (GtkSnapshot *snapshot,
g_return_if_fail (bounds != NULL);
graphene_rect_offset_r (bounds, snapshot->state->translate_x, snapshot->state->translate_y, &real_bounds);
node = gsk_texture_node_new (texture, &real_bounds);
node = gsk_texture_node_new (snapshot->tree, texture, &real_bounds);
if (name && snapshot->record_names)
{
@@ -932,7 +937,6 @@ gtk_snapshot_append_texture_node (GtkSnapshot *snapshot,
}
gtk_snapshot_append_node (snapshot, node);
gsk_render_node_unref (node);
}
/**
@@ -963,7 +967,7 @@ gtk_snapshot_append_color_node (GtkSnapshot *snapshot,
g_return_if_fail (bounds != NULL);
graphene_rect_offset_r (bounds, snapshot->state->translate_x, snapshot->state->translate_y, &real_bounds);
node = gsk_color_node_new (color, &real_bounds);
node = gsk_color_node_new (snapshot->tree, color, &real_bounds);
if (name && snapshot->record_names)
{
@@ -980,7 +984,6 @@ gtk_snapshot_append_color_node (GtkSnapshot *snapshot,
}
gtk_snapshot_append_node (snapshot, node);
gsk_render_node_unref (node);
}
/**

View File

@@ -92,6 +92,8 @@ GDK_AVAILABLE_IN_3_90
void gtk_snapshot_get_offset (GtkSnapshot *snapshot,
int *x,
int *y);
GDK_AVAILABLE_IN_3_90
GskRenderTree *gtk_snapshot_get_tree (GtkSnapshot *snapshot);
GDK_AVAILABLE_IN_3_90
void gtk_snapshot_append_node (GtkSnapshot *snapshot,

View File

@@ -34,6 +34,7 @@ struct _GtkSnapshotState {
GtkSnapshotState *cached_state; /* A cleared state object we can (re)use */
char *name;
GskRenderTree *tree;
GPtrArray *nodes;
cairo_region_t *clip_region;
@@ -74,6 +75,7 @@ struct _GtkSnapshot {
GtkSnapshotState *state;
gboolean record_names;
GskRenderer *renderer;
GskRenderTree *tree;
};
void gtk_snapshot_init (GtkSnapshot *state,

View File

@@ -1933,12 +1933,11 @@ gtk_stack_snapshot_crossfade (GtkWidget *widget,
gtk_snapshot_push_transform (snapshot, &identity, "CrossFadeStart");
gtk_snapshot_append_node (snapshot, priv->last_visible_node);
start_node = gtk_snapshot_pop (snapshot);
node = gsk_cross_fade_node_new (start_node, end_node, progress);
gsk_render_node_unref (start_node);
node = gsk_cross_fade_node_new (gtk_snapshot_get_tree (snapshot), start_node, end_node, progress);
}
else
{
node = gsk_opacity_node_new (end_node, 1.0 - progress);
node = gsk_opacity_node_new (gtk_snapshot_get_tree (snapshot), end_node, 1.0 - progress);
}
if (snapshot->record_names)
@@ -1949,9 +1948,6 @@ gtk_stack_snapshot_crossfade (GtkWidget *widget,
}
gtk_snapshot_append_node (snapshot, node);
gsk_render_node_unref (node);
gsk_render_node_unref (end_node);
}
static void