Exemple #1
0
/**
 * 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;
}
Exemple #2
0
/**
 * 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);
}
Exemple #4
0
/**
 * 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;
}
Exemple #5
0
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);
}
Exemple #6
0
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;
}