Turn GskRenderNode into a derivable type

Language bindings—especially ones based on introspection—cannot deal
with custom type hiearchies. Luckily for us, GType has a derivable type
with low overhead: GTypeInstance.

By turning GskRenderNode into a GTypeInstance, and creating derived
types for each class of node, we can provide an introspectable API to
our non-C API consumers, with no functional change to the C API itself.
This commit is contained in:
Emmanuele Bassi 2020-04-07 23:33:54 +01:00
parent 5e095cd208
commit d701a89281
12 changed files with 1527 additions and 627 deletions

View File

@ -595,7 +595,7 @@ gsk_broadway_renderer_add_node (GskRenderer *renderer,
n = gsk_linear_gradient_node_get_n_color_stops (node);
add_uint32 (nodes, n);
for (i = 0; i < n; i++)
add_color_stop (nodes, &gsk_linear_gradient_node_peek_color_stops (node)[i]);
add_color_stop (nodes, &gsk_linear_gradient_node_peek_color_stops (node, NULL)[i]);
}
return;

View File

@ -25,7 +25,7 @@ node_sample_add (NodeSample *self,
g_assert (node_type <= N_NODE_TYPES);
if (self->nodes[node_type].class_name == NULL)
self->nodes[node_type].class_name = node->node_class->type_name;
self->nodes[node_type].class_name = g_type_name_from_instance ((GTypeInstance *) node);
self->nodes[node_type].count ++;
self->count ++;

View File

@ -150,7 +150,7 @@ print_render_node_tree (GskRenderNode *root, int level)
break;
default:
g_print ("%*s %s\n", level * INDENT, " ", root->node_class->type_name);
g_print ("%*s %s\n", level * INDENT, " ", g_type_name_from_instance ((GTypeInstance *) root));
}
#undef INDENT
@ -623,7 +623,9 @@ render_fallback_node (GskGLRenderer *self,
surface,
GL_NEAREST, GL_NEAREST);
gdk_gl_context_label_object_printf (self->gl_context, GL_TEXTURE, texture_id,
"Fallback %s %d", node->node_class->type_name, texture_id);
"Fallback %s %d",
g_type_name_from_instance ((GTypeInstance *) node),
texture_id);
cairo_surface_destroy (surface);
cairo_surface_destroy (rendered_surface);
@ -643,7 +645,7 @@ render_text_node (GskGLRenderer *self,
gboolean force_color)
{
const PangoFont *font = gsk_text_node_peek_font (node);
const PangoGlyphInfo *glyphs = gsk_text_node_peek_glyphs (node);
const PangoGlyphInfo *glyphs = gsk_text_node_peek_glyphs (node, NULL);
const float text_scale = ops_get_scale (builder);
const graphene_point_t *offset = gsk_text_node_get_offset (node);
const guint num_glyphs = gsk_text_node_get_num_glyphs (node);
@ -1106,7 +1108,7 @@ render_linear_gradient_node (GskGLRenderer *self,
RenderOpBuilder *builder)
{
const int n_color_stops = MIN (8, gsk_linear_gradient_node_get_n_color_stops (node));
const GskColorStop *stops = gsk_linear_gradient_node_peek_color_stops (node);
const GskColorStop *stops = gsk_linear_gradient_node_peek_color_stops (node, NULL);
const graphene_point_t *start = gsk_linear_gradient_node_peek_start (node);
const graphene_point_t *end = gsk_linear_gradient_node_peek_end (node);
OpLinearGradient *op;
@ -3159,9 +3161,13 @@ add_offscreen_ops (GskGLRenderer *self,
gsk_gl_driver_create_render_target (self->gl_driver, width, height, &texture_id, &render_target);
gdk_gl_context_label_object_printf (self->gl_context, GL_TEXTURE, texture_id,
"Offscreen<%s> %d", child_node->node_class->type_name, texture_id);
gdk_gl_context_label_object_printf (self->gl_context, GL_FRAMEBUFFER, render_target,
"Offscreen<%s> FB %d", child_node->node_class->type_name, render_target);
"Offscreen<%s> %d",
g_type_name_from_instance ((GTypeInstance *) child_node),
texture_id);
gdk_gl_context_label_object_printf (self->gl_context, GL_FRAMEBUFFER, render_target,
"Offscreen<%s> FB %d",
g_type_name_from_instance ((GTypeInstance *) child_node),
render_target);
graphene_matrix_init_ortho (&item_proj,
bounds->origin.x * scale,
@ -3209,10 +3215,11 @@ add_offscreen_ops (GskGLRenderer *self,
if (G_UNLIKELY (flags & DUMP_FRAMEBUFFER))
{
static int k;
ops_dump_framebuffer (builder, g_strdup_printf ("%s_%p_%d.png",
child_node->node_class->type_name,
child_node,
k ++),
ops_dump_framebuffer (builder,
g_strdup_printf ("%s_%p_%d.png",
g_type_name_from_instance ((GTypeInstance *) child_node),
child_node,
k ++),
width, height);
}
#endif
@ -3583,7 +3590,9 @@ gsk_gl_renderer_render_texture (GskRenderer *renderer,
gdk_gl_context_make_current (self->gl_context);
gdk_gl_context_push_debug_group_printf (self->gl_context,
"Render %s<%p> to texture", root->node_class->type_name, root);
"Render %s<%p> to texture",
g_type_name_from_instance ((GTypeInstance *) root),
root);
width = ceilf (viewport->size.width);
height = ceilf (viewport->size.height);
@ -3595,8 +3604,11 @@ gsk_gl_renderer_render_texture (GskRenderer *renderer,
glGenTextures (1, &texture_id);
glBindTexture (GL_TEXTURE_2D, texture_id);
gdk_gl_context_label_object_printf (self->gl_context, GL_TEXTURE, texture_id,
"Texture %s<%p> %d", root->node_class->type_name, root, texture_id);
gdk_gl_context_label_object_printf (self->gl_context, GL_TEXTURE, texture_id,
"Texture %s<%p> %d",
g_type_name_from_instance ((GTypeInstance *) root),
root,
texture_id);
if (gdk_gl_context_get_use_es (self->gl_context))
glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
@ -3605,8 +3617,11 @@ gsk_gl_renderer_render_texture (GskRenderer *renderer,
glGenFramebuffers (1, &fbo_id);
glBindFramebuffer (GL_FRAMEBUFFER, fbo_id);
gdk_gl_context_label_object_printf (self->gl_context, GL_FRAMEBUFFER, fbo_id,
"FB %s<%p> %d", root->node_class->type_name, root, fbo_id);
gdk_gl_context_label_object_printf (self->gl_context, GL_FRAMEBUFFER, fbo_id,
"FB %s<%p> %d",
g_type_name_from_instance ((GTypeInstance *) root),
root,
fbo_id);
glFramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture_id, 0);
g_assert_cmphex (glCheckFramebufferStatus (GL_FRAMEBUFFER), ==, GL_FRAMEBUFFER_COMPLETE);

View File

@ -46,9 +46,9 @@
* @GSK_TEXT_NODE: A node containing a glyph string
* @GSK_BLUR_NODE: A node that applies a blur
* @GSK_DEBUG_NODE: Debug information that does not affect the rendering
*
* The type of a node determines what the node is rendering.
**/
*/
typedef enum {
GSK_NOT_A_RENDER_NODE = 0,
GSK_CONTAINER_NODE,

View File

@ -50,47 +50,297 @@
#include <gobject/gvaluecollector.h>
G_DEFINE_QUARK (gsk-serialization-error-quark, gsk_serialization_error)
#define GSK_RENDER_NODE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GSK_TYPE_RENDER_NODE, GskRenderNodeClass))
/**
* GskRenderNode: (ref-func gsk_render_node_ref) (unref-func gsk_render_node_unref)
*
* The `GskRenderNode` structure contains only private data.
* A node in the render tree.
*/
G_DEFINE_BOXED_TYPE (GskRenderNode, gsk_render_node,
gsk_render_node_ref,
gsk_render_node_unref)
static void
value_render_node_init (GValue *value)
{
value->data[0].v_pointer = NULL;
}
static void
value_render_node_free_value (GValue *value)
{
if (value->data[0].v_pointer != NULL)
gsk_render_node_unref (value->data[0].v_pointer);
}
static void
value_render_node_copy_value (const GValue *src,
GValue *dst)
{
if (src->data[0].v_pointer != NULL)
dst->data[0].v_pointer = gsk_render_node_ref (src->data[0].v_pointer);
else
dst->data[0].v_pointer = NULL;
}
static gpointer
value_render_node_peek_pointer (const GValue *value)
{
return value->data[0].v_pointer;
}
G_DEFINE_QUARK (gsk-serialization-error-quark, gsk_serialization_error)
static char *
value_render_node_collect_value (GValue *value,
guint n_collect_values,
GTypeCValue *collect_values,
guint collect_flags)
{
GskRenderNode *node = collect_values[0].v_pointer;
if (node == NULL)
{
value->data[0].v_pointer = NULL;
return NULL;
}
if (node->parent_instance.g_class == NULL)
return g_strconcat ("invalid unclassed GskRenderNode pointer for "
"value type '",
G_VALUE_TYPE_NAME (value),
"'",
NULL);
value->data[0].v_pointer = gsk_render_node_ref (node);
return NULL;
}
static gchar *
value_render_node_lcopy_value (const GValue *value,
guint n_collect_values,
GTypeCValue *collect_values,
guint collect_flags)
{
GskRenderNode **node_p = collect_values[0].v_pointer;
if (node_p == NULL)
return g_strconcat ("value location for '",
G_VALUE_TYPE_NAME (value),
"' passed as NULL",
NULL);
if (value->data[0].v_pointer == NULL)
*node_p = NULL;
else if (collect_flags & G_VALUE_NOCOPY_CONTENTS)
*node_p = value->data[0].v_pointer;
else
*node_p = gsk_render_node_ref (value->data[0].v_pointer);
return NULL;
}
static void
gsk_render_node_finalize (GskRenderNode *self)
{
self->node_class->finalize (self);
g_type_free_instance ((GTypeInstance *) self);
}
g_free (self);
static void
gsk_render_node_real_draw (GskRenderNode *node,
cairo_t *cr)
{
}
static gboolean
gsk_render_node_real_can_diff (const GskRenderNode *node1,
const GskRenderNode *node2)
{
return FALSE;
}
static void
gsk_render_node_real_diff (GskRenderNode *node1,
GskRenderNode *node2,
cairo_region_t *region)
{
}
static void
gsk_render_node_class_init (GskRenderNodeClass *klass)
{
klass->node_type = GSK_NOT_A_RENDER_NODE;
klass->finalize = gsk_render_node_finalize;
klass->draw = gsk_render_node_real_draw;
klass->can_diff = gsk_render_node_real_can_diff;
klass->diff = gsk_render_node_real_diff;
}
static void
gsk_render_node_init (GskRenderNode *self)
{
g_atomic_ref_count_init (&self->ref_count);
}
GType
gsk_render_node_get_type (void)
{
static volatile gsize render_node_type__volatile;
if (g_once_init_enter (&render_node_type__volatile))
{
static const GTypeFundamentalInfo finfo = {
(G_TYPE_FLAG_CLASSED |
G_TYPE_FLAG_INSTANTIATABLE |
G_TYPE_FLAG_DERIVABLE |
G_TYPE_FLAG_DEEP_DERIVABLE),
};
static const GTypeValueTable value_table = {
value_render_node_init,
value_render_node_free_value,
value_render_node_copy_value,
value_render_node_peek_pointer,
"p",
value_render_node_collect_value,
"p",
value_render_node_lcopy_value,
};
const GTypeInfo node_info = {
/* Class */
sizeof (GskRenderNodeClass),
(GBaseInitFunc) NULL,
(GBaseFinalizeFunc) NULL,
(GClassInitFunc) gsk_render_node_class_init,
(GClassFinalizeFunc) NULL,
NULL,
/* Instance */
sizeof (GskRenderNode),
0,
(GInstanceInitFunc) gsk_render_node_init,
/* GValue */
&value_table,
};
GType render_node_type =
g_type_register_fundamental (g_type_fundamental_next (),
g_intern_static_string ("GskRenderNode"),
&node_info, &finfo,
G_TYPE_FLAG_ABSTRACT);
g_once_init_leave (&render_node_type__volatile, render_node_type);
}
return render_node_type__volatile;
}
typedef struct
{
GskRenderNodeType node_type;
void (* finalize) (GskRenderNode *node);
void (* draw) (GskRenderNode *node,
cairo_t *cr);
gboolean (* can_diff) (const GskRenderNode *node1,
const GskRenderNode *node2);
void (* diff) (GskRenderNode *node1,
GskRenderNode *node2,
cairo_region_t *region);
} RenderNodeClassData;
static void
gsk_render_node_generic_class_init (gpointer g_class,
gpointer class_data)
{
GskRenderNodeClass *node_class = g_class;
RenderNodeClassData *node_data = class_data;
/* Mandatory */
node_class->node_type = node_data->node_type;
/* Optional */
if (node_data->finalize != NULL)
node_class->finalize = node_data->finalize;
if (node_data->can_diff != NULL)
node_class->can_diff = node_data->can_diff;
/* Mandatory */
node_class->draw = node_data->draw;
node_class->diff = node_data->diff;
g_free (node_data);
}
static gboolean
gsk_render_node_can_diff_true (const GskRenderNode *node1,
const GskRenderNode *node2)
{
return TRUE;
}
/*< private >
* gsk_render_node_new:
* @node_class: class structure for this node
* gsk_render_node_type_register_static:
* @node_name: the name of the node
* @node_info: type information of the node
*
* Returns: (transfer full): the newly created #GskRenderNode
* Registers a new #GskRenderNode type for the given @node_name using
* the type information in @node_info.
*
* Returns: the newly registered GType
*/
GskRenderNode *
gsk_render_node_new (const GskRenderNodeClass *node_class, gsize extra_size)
GType
gsk_render_node_type_register_static (const char *node_name,
const GskRenderNodeTypeInfo *node_info)
{
GskRenderNode *self;
GTypeInfo info;
g_return_val_if_fail (node_class != NULL, NULL);
g_return_val_if_fail (node_class->node_type != GSK_NOT_A_RENDER_NODE, NULL);
info.class_size = sizeof (GskRenderNodeClass);
info.base_init = NULL;
info.base_finalize = NULL;
info.class_init = gsk_render_node_generic_class_init;
info.class_finalize = NULL;
self = g_malloc0 (node_class->struct_size + extra_size);
/* Avoid having a class_init() and a class struct for every GskRenderNode,
* by passing the various virtual functions and class data when initializing
* the base class
*/
info.class_data = g_new (RenderNodeClassData, 1);
((RenderNodeClassData *) info.class_data)->node_type = node_info->node_type;
((RenderNodeClassData *) info.class_data)->finalize = node_info->finalize;
((RenderNodeClassData *) info.class_data)->draw = node_info->draw;
((RenderNodeClassData *) info.class_data)->can_diff = node_info->can_diff != NULL
? node_info->can_diff
: gsk_render_node_can_diff_true;
((RenderNodeClassData *) info.class_data)->diff = node_info->diff != NULL
? node_info->diff
: gsk_render_node_diff_impossible;
self->node_class = node_class;
info.instance_size = node_info->instance_size;
info.n_preallocs = 0;
info.instance_init = (GInstanceInitFunc) node_info->instance_init;
info.value_table = NULL;
self->ref_count = 1;
return g_type_register_static (GSK_TYPE_RENDER_NODE, node_name, &info, 0);
}
return self;
/*< private >
* gsk_render_node_alloc:
* @node_type: the #GskRenderNodeType to instantiate
*
* Instantiates a new #GskRenderNode for the given @node_type.
*
* Returns: (transfer full) (type GskRenderNode): the newly created #GskRenderNode
*/
gpointer
gsk_render_node_alloc (GskRenderNodeType node_type)
{
g_return_val_if_fail (node_type > GSK_NOT_A_RENDER_NODE, NULL);
g_return_val_if_fail (node_type < GSK_RENDER_NODE_TYPE_N_TYPES, NULL);
g_assert (gsk_render_node_types[node_type] != G_TYPE_INVALID);
return g_type_create_instance (gsk_render_node_types[node_type]);
}
/**
@ -106,7 +356,7 @@ gsk_render_node_ref (GskRenderNode *node)
{
g_return_val_if_fail (GSK_IS_RENDER_NODE (node), NULL);
g_atomic_int_inc (&node->ref_count);
g_atomic_ref_count_inc (&node->ref_count);
return node;
}
@ -125,10 +375,11 @@ gsk_render_node_unref (GskRenderNode *node)
{
g_return_if_fail (GSK_IS_RENDER_NODE (node));
if (g_atomic_int_dec_and_test (&node->ref_count))
gsk_render_node_finalize (node);
if (g_atomic_ref_count_dec (&node->ref_count))
GSK_RENDER_NODE_GET_CLASS (node)->finalize (node);
}
/**
* gsk_render_node_get_node_type:
* @node: a #GskRenderNode
@ -142,14 +393,14 @@ gsk_render_node_get_node_type (GskRenderNode *node)
{
g_return_val_if_fail (GSK_IS_RENDER_NODE (node), GSK_NOT_A_RENDER_NODE);
return node->node_class->node_type;
return GSK_RENDER_NODE_GET_CLASS (node)->node_type;
}
G_GNUC_PURE static inline
GskRenderNodeType
_gsk_render_node_get_node_type (const GskRenderNode *node)
{
return node->node_class->node_type;
return GSK_RENDER_NODE_GET_CLASS (node)->node_type;
}
/**
@ -195,9 +446,10 @@ gsk_render_node_draw (GskRenderNode *node,
cairo_save (cr);
GSK_NOTE (CAIRO, g_message ("Rendering node %s[%p]",
node->node_class->type_name, node));
g_type_name_from_instance ((GTypeInstance *) node),
node));
node->node_class->draw (node, cr);
GSK_RENDER_NODE_GET_CLASS (node)->draw (node, cr);
#ifdef G_ENABLE_DEBUG
if (GSK_DEBUG_CHECK (GEOMETRY))
@ -216,7 +468,7 @@ gsk_render_node_draw (GskRenderNode *node,
if (cairo_status (cr))
{
g_warning ("drawing failure for render node %s: %s",
node->node_class->type_name,
g_type_name_from_instance ((GTypeInstance *) node),
cairo_status_to_string (cairo_status (cr)));
}
}
@ -245,7 +497,7 @@ gsk_render_node_can_diff (const GskRenderNode *node1,
if (_gsk_render_node_get_node_type (node1) != _gsk_render_node_get_node_type (node2))
return FALSE;
return node1->node_class->can_diff (node1, node2);
return GSK_RENDER_NODE_GET_CLASS (node1)->can_diff (node1, node2);
}
static void
@ -299,7 +551,7 @@ gsk_render_node_diff (GskRenderNode *node1,
if (_gsk_render_node_get_node_type (node1) != _gsk_render_node_get_node_type (node2))
return gsk_render_node_diff_impossible (node1, node2, region);
return node1->node_class->diff (node1, node2, region);
return GSK_RENDER_NODE_GET_CLASS (node1)->diff (node1, node2, region);
}
/**

View File

@ -99,6 +99,53 @@ GskRenderNode * gsk_render_node_deserialize (GBytes
GskParseErrorFunc error_func,
gpointer user_data);
#define GSK_TYPE_DEBUG_NODE (gsk_render_node_types[GSK_DEBUG_NODE])
#define GSK_TYPE_COLOR_NODE (gsk_render_node_types[GSK_COLOR_NODE])
#define GSK_TYPE_TEXTURE_NODE (gsk_render_node_types[GSK_TEXTURE_NODE])
#define GSK_TYPE_LINEAR_GRADIENT_NODE (gsk_render_node_types[GSK_LINEAR_GRADIENT_NODE])
#define GSK_TYPE_REPEATING_LINEAR_GRADIENT_NODE (gsk_render_node_types[GSK_REPEATING_LINEAR_GRADIENT_NODE])
#define GSK_TYPE_BORDER_NODE (gsk_render_node_types[GSK_BORDER_NODE])
#define GSK_TYPE_INSET_SHADOW_NODE (gsk_render_node_types[GSK_INSET_SHADOW_NODE])
#define GSK_TYPE_OUTSET_SHADOW_NODE (gsk_render_node_types[GSK_OUTSET_SHADOW_NODE])
#define GSK_TYPE_CAIRO_NODE (gsk_render_node_types[GSK_CAIRO_NODE])
#define GSK_TYPE_CONTAINER_NODE (gsk_render_node_types[GSK_CONTAINER_NODE])
#define GSK_TYPE_TRANSFORM_NODE (gsk_render_node_types[GSK_TRANSFORM_NODE])
#define GSK_TYPE_OPACITY_NODE (gsk_render_node_types[GSK_OPACITY_NODE])
#define GSK_TYPE_COLOR_MATRIX_NODE (gsk_render_node_types[GSK_COLOR_MATRIX_NODE])
#define GSK_TYPE_REPEAT_NODE (gsk_render_node_types[GSK_REPEAT_NODE])
#define GSK_TYPE_CLIP_NODE (gsk_render_node_types[GSK_CLIP_NODE])
#define GSK_TYPE_ROUNDED_CLIP_NODE (gsk_render_node_types[GSK_ROUNDED_CLIP_NODE])
#define GSK_TYPE_SHADOW_NODE (gsk_render_node_types[GSK_SHADOW_NODE])
#define GSK_TYPE_BLEND_NODE (gsk_render_node_types[GSK_BLEND_NODE])
#define GSK_TYPE_CROSS_FADE_NODE (gsk_render_node_types[GSK_CROSS_FADE_NODE])
#define GSK_TYPE_TEXT_NODE (gsk_render_node_types[GSK_TEXT_NODE])
#define GSK_TYPE_BLUR_NODE (gsk_render_node_types[GSK_BLUR_NODE])
/*< private >*/
GDK_EXTERN_VAR GType gsk_render_node_types[];
typedef struct _GskDebugNode GskDebugNode;
typedef struct _GskColorNode GskColorNode;
typedef struct _GskTextureNode GskTextureNode;
typedef struct _GskLinearGradientNode GskLinearGradientNode;
typedef struct _GskRepeatingLinearGradientNode GskRepeatingLinearGradientNode;
typedef struct _GskBorderNode GskBorderNode;
typedef struct _GskInsetShadowNode GskInsetShadowNode;
typedef struct _GskOutsetShadowNode GskOutsetShadowNode;
typedef struct _GskCairoNode GskCairoNode;
typedef struct _GskContainerNode GskContainerNode;
typedef struct _GskTransformNode GskTransformNode;
typedef struct _GskOpacityNode GskOpacityNode;
typedef struct _GskColorMatrixNode GskColorMatrixNode;
typedef struct _GskRepeatNode GskRepeatNode;
typedef struct _GskClipNode GskClipNode;
typedef struct _GskRoundedClipNode GskRoundedClipNode;
typedef struct _GskShadowNode GskShadowNode;
typedef struct _GskBlendNode GskBlendNode;
typedef struct _GskCrossFadeNode GskCrossFadeNode;
typedef struct _GskTextNode GskTextNode;
typedef struct _GskBlurNode GskBlurNode;
GDK_AVAILABLE_IN_ALL
GskRenderNode * gsk_debug_node_new (GskRenderNode *child,
char *message);
@ -132,7 +179,8 @@ const graphene_point_t * gsk_linear_gradient_node_peek_end (GskRenderNo
GDK_AVAILABLE_IN_ALL
gsize gsk_linear_gradient_node_get_n_color_stops (GskRenderNode *node);
GDK_AVAILABLE_IN_ALL
const GskColorStop * gsk_linear_gradient_node_peek_color_stops (GskRenderNode *node);
const GskColorStop * gsk_linear_gradient_node_peek_color_stops (GskRenderNode *node,
gsize *n_stops);
GDK_AVAILABLE_IN_ALL
GskRenderNode * gsk_repeating_linear_gradient_node_new (const graphene_rect_t *bounds,
@ -152,7 +200,6 @@ const float * gsk_border_node_peek_widths (GskRenderNode
GDK_AVAILABLE_IN_ALL
const GdkRGBA * gsk_border_node_peek_colors (GskRenderNode *node);
GDK_AVAILABLE_IN_ALL
GskRenderNode * gsk_inset_shadow_node_new (const GskRoundedRect *outline,
const GdkRGBA *color,
@ -254,7 +301,6 @@ GskRenderNode * gsk_clip_node_get_child (GskRenderNode
GDK_AVAILABLE_IN_ALL
const graphene_rect_t * gsk_clip_node_peek_clip (GskRenderNode *node);
GDK_AVAILABLE_IN_ALL
GskRenderNode * gsk_rounded_clip_node_new (GskRenderNode *child,
const GskRoundedRect *clip);
@ -308,7 +354,8 @@ gboolean gsk_text_node_has_color_glyphs (GskRenderNode
GDK_AVAILABLE_IN_ALL
guint gsk_text_node_get_num_glyphs (GskRenderNode *node);
GDK_AVAILABLE_IN_ALL
const PangoGlyphInfo *gsk_text_node_peek_glyphs (GskRenderNode *node);
const PangoGlyphInfo *gsk_text_node_peek_glyphs (GskRenderNode *node,
guint *n_glyphs);
GDK_AVAILABLE_IN_ALL
const GdkRGBA * gsk_text_node_peek_color (GskRenderNode *node);
GDK_AVAILABLE_IN_ALL

File diff suppressed because it is too large Load Diff

View File

@ -1973,9 +1973,9 @@ render_node_print (Printer *p,
case GSK_REPEATING_LINEAR_GRADIENT_NODE:
case GSK_LINEAR_GRADIENT_NODE:
{
const guint n_stops = gsk_linear_gradient_node_get_n_color_stops (node);
const GskColorStop *stops = gsk_linear_gradient_node_peek_color_stops (node);
int i;
const gsize n_stops = gsk_linear_gradient_node_get_n_color_stops (node);
const GskColorStop *stops = gsk_linear_gradient_node_peek_color_stops (node, NULL);
gsize i;
if (gsk_render_node_get_node_type (node) == GSK_REPEATING_LINEAR_GRADIENT_NODE)
start_node (p, "repeating-linear-gradient");
@ -2229,7 +2229,7 @@ render_node_print (Printer *p,
case GSK_TEXT_NODE:
{
const guint n_glyphs = gsk_text_node_get_num_glyphs (node);
const PangoGlyphInfo *glyphs = gsk_text_node_peek_glyphs (node);
const PangoGlyphInfo *glyphs = gsk_text_node_peek_glyphs (node, NULL);
const graphene_point_t *offset = gsk_text_node_get_offset (node);
const GdkRGBA *color = gsk_text_node_peek_color (node);
PangoFont *font = gsk_text_node_peek_font (node);
@ -2449,7 +2449,7 @@ render_node_print (Printer *p,
break;
default:
g_error ("Unhandled node: %s", node->node_class->type_name);
g_error ("Unhandled node: %s", g_type_name_from_instance ((GTypeInstance *) node));
break;
}
}

View File

@ -8,22 +8,30 @@ G_BEGIN_DECLS
typedef struct _GskRenderNodeClass GskRenderNodeClass;
#define GSK_IS_RENDER_NODE_TYPE(node,type) (GSK_IS_RENDER_NODE (node) && (node)->node_class->node_type == (type))
/* Keep this in sync with the GskRenderNodeType enumeration.
*
* We don't add an "n-types" value to avoid having to handle
* it in every single switch.
*/
#define GSK_RENDER_NODE_TYPE_N_TYPES (GSK_DEBUG_NODE + 1)
#define GSK_IS_RENDER_NODE_TYPE(node,type) \
(G_TYPE_INSTANCE_GET_CLASS ((node), GSK_TYPE_RENDER_NODE, GskRenderNodeClass)->node_type == (type))
struct _GskRenderNode
{
const GskRenderNodeClass *node_class;
GTypeInstance parent_instance;
volatile int ref_count;
gatomicrefcount ref_count;
graphene_rect_t bounds;
};
struct _GskRenderNodeClass
{
GTypeClass parent_class;
GskRenderNodeType node_type;
gsize struct_size;
const char *type_name;
void (* finalize) (GskRenderNode *node);
void (* draw) (GskRenderNode *node,
@ -35,18 +43,54 @@ struct _GskRenderNodeClass
cairo_region_t *region);
};
GskRenderNode * gsk_render_node_new (const GskRenderNodeClass *node_class,
gsize extra_size);
/*< private >
* GskRenderNodeTypeInfo:
* @node_type: the render node type in the #GskRenderNodeType enumeration
* @instance_size: the size of the render node instance
* @instance_init: (nullable): the instance initialization function
* @finalize: (nullable): the instance finalization function; must chain up to the
* implementation of the parent class
* @draw: the function called by gsk_render_node_draw()
* @can_diff: (nullable): the function called by gsk_render_node_can_diff(); if
* unset, gsk_render_node_can_diff_true() will be used
* @diff: (nullable): the function called by gsk_render_node_diff(); if unset,
* gsk_render_node_diff_impossible() will be used
*
* A struction that contains the type information for a #GskRenderNode subclass,
* to be used by gsk_render_node_type_register_static().
*/
typedef struct
{
GskRenderNodeType node_type;
gboolean gsk_render_node_can_diff (const GskRenderNode *node1,
const GskRenderNode *node2) G_GNUC_PURE;
void gsk_render_node_diff (GskRenderNode *node1,
GskRenderNode *node2,
cairo_region_t *region);
void gsk_render_node_diff_impossible (GskRenderNode *node1,
GskRenderNode *node2,
cairo_region_t *region);
gsize instance_size;
void (* instance_init) (GskRenderNode *node);
void (* finalize) (GskRenderNode *node);
void (* draw) (GskRenderNode *node,
cairo_t *cr);
gboolean (* can_diff) (const GskRenderNode *node1,
const GskRenderNode *node2);
void (* diff) (GskRenderNode *node1,
GskRenderNode *node2,
cairo_region_t *region);
} GskRenderNodeTypeInfo;
void gsk_render_node_init_types (void);
GType gsk_render_node_type_register_static (const char *node_name,
const GskRenderNodeTypeInfo *node_info);
gpointer gsk_render_node_alloc (GskRenderNodeType node_type);
gboolean gsk_render_node_can_diff (const GskRenderNode *node1,
const GskRenderNode *node2) G_GNUC_PURE;
void gsk_render_node_diff (GskRenderNode *node1,
GskRenderNode *node2,
cairo_region_t *region);
void gsk_render_node_diff_impossible (GskRenderNode *node1,
GskRenderNode *node2,
cairo_region_t *region);
G_END_DECLS

View File

@ -258,7 +258,7 @@ gsk_vulkan_render_pass_add_node (GskVulkanRenderPass *self,
return;
case GSK_SHADOW_NODE:
default:
FALLBACK ("Unsupported node '%s'", node->node_class->type_name);
FALLBACK ("Unsupported node '%s'", g_type_name_from_instance ((GTypeInstance *) node));
case GSK_REPEAT_NODE:
if (gsk_vulkan_clip_contains_rect (&constants->clip, &node->bounds))
@ -346,7 +346,7 @@ gsk_vulkan_render_pass_add_node (GskVulkanRenderPass *self,
case GSK_TEXT_NODE:
{
const PangoFont *font = gsk_text_node_peek_font (node);
const PangoGlyphInfo *glyphs = gsk_text_node_peek_glyphs (node);
const PangoGlyphInfo *glyphs = gsk_text_node_peek_glyphs (node, NULL);
guint num_glyphs = gsk_text_node_get_num_glyphs (node);
gboolean has_color_glyphs = gsk_text_node_has_color_glyphs (node);
int i;
@ -817,7 +817,7 @@ gsk_vulkan_render_pass_upload_fallback (GskVulkanRenderPass *self,
g_message ("Upload op=%s, node %s[%p], bounds %gx%g",
op->type == GSK_VULKAN_OP_FALLBACK_CLIP ? "fallback-clip" :
(op->type == GSK_VULKAN_OP_FALLBACK_ROUNDED_CLIP ? "fallback-rounded-clip" : "fallback"),
node->node_class->type_name, node,
g_type_name_from_instance ((GTypeInstance *) node), node,
ceil (node->bounds.size.width),
ceil (node->bounds.size.height)));
#ifdef G_ENABLE_DEBUG
@ -1195,7 +1195,7 @@ gsk_vulkan_render_pass_collect_vertex_data (GskVulkanRenderPass *self,
&op->text.node->bounds,
(PangoFont *)gsk_text_node_peek_font (op->text.node),
gsk_text_node_get_num_glyphs (op->text.node),
gsk_text_node_peek_glyphs (op->text.node),
gsk_text_node_peek_glyphs (op->text.node, NULL),
gsk_text_node_peek_color (op->text.node),
gsk_text_node_get_offset (op->text.node),
op->text.start_glyph,
@ -1214,7 +1214,7 @@ gsk_vulkan_render_pass_collect_vertex_data (GskVulkanRenderPass *self,
&op->text.node->bounds,
(PangoFont *)gsk_text_node_peek_font (op->text.node),
gsk_text_node_get_num_glyphs (op->text.node),
gsk_text_node_peek_glyphs (op->text.node),
gsk_text_node_peek_glyphs (op->text.node, NULL),
gsk_text_node_get_offset (op->text.node),
op->text.start_glyph,
op->text.num_glyphs,
@ -1244,7 +1244,7 @@ gsk_vulkan_render_pass_collect_vertex_data (GskVulkanRenderPass *self,
gsk_linear_gradient_node_peek_end (op->render.node),
gsk_render_node_get_node_type (op->render.node) == GSK_REPEATING_LINEAR_GRADIENT_NODE,
gsk_linear_gradient_node_get_n_color_stops (op->render.node),
gsk_linear_gradient_node_peek_color_stops (op->render.node));
gsk_linear_gradient_node_peek_color_stops (op->render.node, NULL));
n_bytes += op->render.vertex_count;
}
break;

View File

@ -95,6 +95,7 @@
#include "gdk/gdk.h"
#include "gdk/gdk-private.h"
#include "gsk/gskprivate.h"
#include "gsk/gskrendernodeprivate.h"
#include <locale.h>
@ -660,6 +661,7 @@ do_post_parse_initialization (void)
gtk_widget_set_default_direction (gtk_get_locale_direction ());
gsk_ensure_resources ();
gsk_render_node_init_types ();
_gtk_ensure_resources ();
gtk_initialized = TRUE;

View File

@ -601,7 +601,7 @@ populate_render_node_properties (GtkListStore *store,
const graphene_point_t *start = gsk_linear_gradient_node_peek_start (node);
const graphene_point_t *end = gsk_linear_gradient_node_peek_end (node);
const gsize n_stops = gsk_linear_gradient_node_get_n_color_stops (node);
const GskColorStop *stops = gsk_linear_gradient_node_peek_color_stops (node);
const GskColorStop *stops = gsk_linear_gradient_node_peek_color_stops (node, NULL);
int i;
GString *s;
GdkTexture *texture;
@ -633,7 +633,7 @@ populate_render_node_properties (GtkListStore *store,
case GSK_TEXT_NODE:
{
const PangoFont *font = gsk_text_node_peek_font (node);
const PangoGlyphInfo *glyphs = gsk_text_node_peek_glyphs (node);
const PangoGlyphInfo *glyphs = gsk_text_node_peek_glyphs (node, NULL);
const GdkRGBA *color = gsk_text_node_peek_color (node);
guint num_glyphs = gsk_text_node_get_num_glyphs (node);
const graphene_point_t *offset = gsk_text_node_get_offset (node);