/** * gsk_renderer_render: * @renderer: a #GskRenderer * @root: a #GskRenderNode * @region: (nullable): the #cairo_region_t that must be redrawn or %NULL * for the whole window * * Renders the scene graph, described by a tree of #GskRenderNode instances, * ensuring that the given @region gets redrawn. * * Renderers must ensure that changes of the contents given by the @root * node as well as the area given by @region are redrawn. They are however * free to not redraw any pixel outside of @region if they can guarantee that * it didn't change. * * The @renderer will acquire a reference on the #GskRenderNode tree while * the rendering is in progress. */ void gsk_renderer_render (GskRenderer *renderer, GskRenderNode *root, const cairo_region_t *region) { GskRendererPrivate *priv = gsk_renderer_get_instance_private (renderer); cairo_region_t *clip; 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 (priv->root_node == NULL); if (region == NULL || priv->prev_node == NULL || GSK_RENDERER_DEBUG_CHECK (renderer, FULL_REDRAW)) { clip = cairo_region_create_rectangle (&(GdkRectangle) { 0, 0, gdk_surface_get_width (priv->surface), gdk_surface_get_height (priv->surface) }); } else { clip = cairo_region_copy (region); gsk_render_node_diff (priv->prev_node, root, clip); if (cairo_region_is_empty (clip)) { cairo_region_destroy (clip); return; } } priv->root_node = gsk_render_node_ref (root); GSK_RENDERER_GET_CLASS (renderer)->render (renderer, root, clip); #ifdef G_ENABLE_DEBUG if (GSK_RENDERER_DEBUG_CHECK (renderer, RENDERER)) { GString *buf = g_string_new ("*** Frame stats ***\n\n"); gsk_profiler_append_counters (priv->profiler, buf); g_string_append_c (buf, '\n'); gsk_profiler_append_timers (priv->profiler, buf); g_string_append_c (buf, '\n'); g_print ("%s\n***\n\n", buf->str); g_string_free (buf, TRUE); } #endif g_clear_pointer (&priv->prev_node, gsk_render_node_unref); cairo_region_destroy (clip); priv->prev_node = priv->root_node; priv->root_node = NULL; }
/** * gtk_snapshot_append_node: * @snapshot: a #GtkSnapshot * @node: a #GskRenderNode * * Appends @node to the current render node of @snapshot, * without changing the current node. If @snapshot does * not have a current node yet, @node will become the * initial node. */ void gtk_snapshot_append_node (GtkSnapshot *snapshot, GskRenderNode *node) { g_return_if_fail (snapshot != NULL); g_return_if_fail (GSK_IS_RENDER_NODE (node)); if (snapshot->state) { g_ptr_array_add (snapshot->state->nodes, gsk_render_node_ref (node)); } else { g_critical ("Tried appending a node to an already finished snapshot."); } }
GdkPaintable * gtk_render_node_paintable_new (GskRenderNode *node, const graphene_rect_t *bounds) { GtkRenderNodePaintable *self; g_return_val_if_fail (GSK_IS_RENDER_NODE (node), NULL); g_return_val_if_fail (bounds != NULL, NULL); self = g_object_new (GTK_TYPE_RENDER_NODE_PAINTABLE, NULL); self->node = gsk_render_node_ref (node); self->bounds = *bounds; return GDK_PAINTABLE (self); }
/** * gsk_renderer_render_texture: * @renderer: a realized #GdkRenderer * @root: a #GskRenderNode * @viewport: (allow-none): the section to draw or %NULL to use @root's bounds * * Renders the scene graph, described by a tree of #GskRenderNode instances, * to a #GdkTexture. * * The @renderer will acquire a reference on the #GskRenderNode tree while * the rendering is in progress. * * If you want to apply any transformations to @root, you should put it into a * transform node and pass that node instead. * * Returns: (transfer full): a #GdkTexture with the rendered contents of @root. */ GdkTexture * gsk_renderer_render_texture (GskRenderer *renderer, GskRenderNode *root, const graphene_rect_t *viewport) { GskRendererPrivate *priv = gsk_renderer_get_instance_private (renderer); graphene_rect_t real_viewport; GdkTexture *texture; g_return_val_if_fail (GSK_IS_RENDERER (renderer), NULL); g_return_val_if_fail (priv->is_realized, NULL); g_return_val_if_fail (GSK_IS_RENDER_NODE (root), NULL); g_return_val_if_fail (priv->root_node == NULL, NULL); priv->root_node = gsk_render_node_ref (root); if (viewport == NULL) { gsk_render_node_get_bounds (root, &real_viewport); viewport = &real_viewport; } texture = GSK_RENDERER_GET_CLASS (renderer)->render_texture (renderer, root, viewport); #ifdef G_ENABLE_DEBUG if (GSK_RENDERER_DEBUG_CHECK (renderer, RENDERER)) { GString *buf = g_string_new ("*** Texture stats ***\n\n"); gsk_profiler_append_counters (priv->profiler, buf); g_string_append_c (buf, '\n'); gsk_profiler_append_timers (priv->profiler, buf); g_string_append_c (buf, '\n'); g_print ("%s\n***\n\n", buf->str); g_string_free (buf, TRUE); } #endif g_clear_pointer (&priv->root_node, gsk_render_node_unref); return texture; }
GtkInspectorRecording * gtk_inspector_render_recording_new (gint64 timestamp, GskProfiler *profiler, const GdkRectangle *area, const cairo_region_t *clip_region, GskRenderNode *node) { GtkInspectorRenderRecording *recording; recording = g_object_new (GTK_TYPE_INSPECTOR_RENDER_RECORDING, "timestamp", timestamp, NULL); collect_profiler_info (recording, profiler); recording->area = *area; recording->clip_region = cairo_region_copy (clip_region); recording->node = gsk_render_node_ref (node); return GTK_INSPECTOR_RECORDING (recording); }
static GskRenderNode * gtk_snapshot_collect_default (GskRenderNode **nodes, guint n_nodes, const char *name, gpointer unused) { GskRenderNode *node; if (n_nodes == 0) { node = NULL; } else if (n_nodes == 1) { node = gsk_render_node_ref (nodes[0]); } else { node = gsk_container_node_new (nodes, n_nodes); gsk_render_node_set_name (node, name); } return node; }