Compare commits

...

4 Commits

Author SHA1 Message Date
Alexander Larsson
b8c33e8153 GskRenderNode: Use C99 flexible arrays to avoid extra allocation
Instead of a separate allocation for any arrays in the render node
we allocate these as part of the render node itself, using C99
flexible arrays.

This leads to less allocations, which is nice, but the major reason
for this is that it allows us to change the allocation scheme further
in the future. For instance, we want to do stack-like allocation so
that all the render-nodes for an entire frame are allocated in one
(or a few) chunks.
2016-12-21 12:20:56 +01:00
Alexander Larsson
ad5d7be194 gsk: Add bounds member to RenderNode
Instead of constantly recalculating this (especially recursively for
parents!) we do it only on construction, because everything is
immutable anyway. Also, most nodes had a bounds already and can
use the new parent member instead.

We also do direct access to the node bounds rather than calling
gsk_render_node_get_bounds in various places, which means
we do less copying.
2016-12-21 11:55:15 +01:00
Alexander Larsson
38d49b04a3 gsk: Drop gsk_render_node_make_immutable, nodes are always immutable 2016-12-21 11:00:18 +01:00
Alexander Larsson
45bbb3b447 gsk docs: gsk_render_node_iter_get_type doesn't exist anymore 2016-12-21 10:59:35 +01:00
7 changed files with 120 additions and 444 deletions

View File

@@ -1,3 +1,2 @@
gsk_render_node_get_type
gsk_render_node_iter_get_type
gsk_renderer_get_type

View File

@@ -604,7 +604,6 @@ gsk_gl_renderer_add_render_item (GskGLRenderer *self,
RenderItem *parent)
{
graphene_rect_t viewport;
graphene_rect_t bounds;
RenderItem item;
RenderItem *ritem = NULL;
int program_id;
@@ -618,24 +617,22 @@ gsk_gl_renderer_add_render_item (GskGLRenderer *self,
if (scale_factor < 1)
scale_factor = 1;
gsk_render_node_get_bounds (node, &bounds);
item.node = node;
item.name = node->name != NULL ? node->name : "unnamed";
/* The texture size */
item.size.width = bounds.size.width * scale_factor;
item.size.height = bounds.size.height * scale_factor;
item.size.width = node->bounds.size.width * scale_factor;
item.size.height = node->bounds.size.height * scale_factor;
/* Each render item is an axis-aligned bounding box that we
* transform using the given transformation matrix
*/
item.min.x = bounds.origin.x;
item.min.y = bounds.origin.y;
item.min.x = node->bounds.origin.x;
item.min.y = node->bounds.origin.y;
item.min.z = 0.f;
item.max.x = item.min.x + bounds.size.width;
item.max.y = item.min.y + bounds.size.height;
item.max.x = item.min.x + node->bounds.size.width;
item.max.y = item.min.y + node->bounds.size.height;
item.max.z = 0.f;
/* The location of the item, in normalized world coordinates */
@@ -763,17 +760,14 @@ gsk_gl_renderer_add_render_item (GskGLRenderer *self,
default:
{
graphene_rect_t bounds;
cairo_surface_t *surface;
cairo_t *cr;
gsk_render_node_get_bounds (node, &bounds);
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
ceil (bounds.size.width),
ceil (bounds.size.height));
ceil (node->bounds.size.width),
ceil (node->bounds.size.height));
cr = cairo_create (surface);
cairo_translate (cr, -bounds.origin.x, -bounds.origin.y);
cairo_translate (cr, -node->bounds.origin.x, -node->bounds.origin.y);
gsk_render_node_draw (node, cr);

View File

@@ -616,7 +616,7 @@ gsk_renderer_unrealize (GskRenderer *renderer)
* using the given #GdkDrawingContext.
*
* The @renderer will acquire a reference on the #GskRenderNode tree while
* the rendering is in progress, and will make the tree immutable.
* the rendering is in progress.
*
* Since: 3.90
*/
@@ -635,7 +635,6 @@ gsk_renderer_render (GskRenderer *renderer,
g_return_if_fail (context == priv->drawing_context);
priv->root_node = gsk_render_node_ref (root);
gsk_render_node_make_immutable (priv->root_node);
#ifdef G_ENABLE_DEBUG
gsk_profiler_reset (priv->profiler);

View File

@@ -35,8 +35,8 @@
*
* Render nodes are meant to be transient; once they have been associated
* to a #GskRenderer it's safe to release any reference you have on them.
* Once a #GskRenderNode has been rendered, it is marked as immutable, and
* cannot be modified.
* All #GskRenderNodes are immutable, you can only specify their properties
* during construction.
*/
#include "config.h"
@@ -68,13 +68,11 @@ G_DEFINE_BOXED_TYPE (GskRenderNode, gsk_render_node,
static void
gsk_render_node_finalize (GskRenderNode *self)
{
self->is_mutable = TRUE;
self->node_class->finalize (self);
g_clear_pointer (&self->name, g_free);
g_slice_free1 (self->node_class->struct_size, self);
g_free (self);
}
/*< private >
@@ -84,14 +82,14 @@ gsk_render_node_finalize (GskRenderNode *self)
* Returns: (transfer full): the newly created #GskRenderNode
*/
GskRenderNode *
gsk_render_node_new (const GskRenderNodeClass *node_class)
gsk_render_node_new (const GskRenderNodeClass *node_class, gsize extra_size)
{
GskRenderNode *self;
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_slice_alloc0 (node_class->struct_size);
self = g_malloc0 (node_class->struct_size + extra_size);
self->node_class = node_class;
@@ -100,8 +98,6 @@ gsk_render_node_new (const GskRenderNodeClass *node_class)
self->min_filter = GSK_SCALING_FILTER_NEAREST;
self->mag_filter = GSK_SCALING_FILTER_NEAREST;
self->is_mutable = TRUE;
return self;
}
@@ -180,7 +176,7 @@ gsk_render_node_get_bounds (GskRenderNode *node,
g_return_if_fail (GSK_IS_RENDER_NODE (node));
g_return_if_fail (bounds != NULL);
node->node_class->get_bounds (node, bounds);
graphene_rect_init_from_rect (bounds, &node->bounds);
}
void
@@ -237,23 +233,6 @@ gsk_render_node_get_name (GskRenderNode *node)
return node->name;
}
/*< private >
* gsk_render_node_make_immutable:
* @node: a #GskRenderNode
*
* Marks @node, and all its children, as immutable.
*/
void
gsk_render_node_make_immutable (GskRenderNode *node)
{
if (!node->is_mutable)
return;
node->node_class->make_immutable (node);
node->is_mutable = FALSE;
}
/**
* gsk_render_node_draw:
* @node: a #GskRenderNode
@@ -279,14 +258,11 @@ gsk_render_node_draw (GskRenderNode *node,
if (!GSK_RENDER_MODE_CHECK (GEOMETRY))
{
graphene_rect_t frame;
gsk_render_node_get_bounds (node, &frame);
GSK_NOTE (CAIRO, g_print ("CLIP = { .x = %g, .y = %g, .width = %g, .height = %g }\n",
frame.origin.x, frame.origin.y,
frame.size.width, frame.size.height));
node->bounds.origin.x, node->bounds.origin.y,
node->bounds.size.width, node->bounds.size.height));
cairo_rectangle (cr, frame.origin.x, frame.origin.y, frame.size.width, frame.size.height);
cairo_rectangle (cr, node->bounds.origin.x, node->bounds.origin.y, node->bounds.size.width, node->bounds.size.height);
cairo_clip (cr);
}
@@ -298,12 +274,9 @@ gsk_render_node_draw (GskRenderNode *node,
if (GSK_RENDER_MODE_CHECK (GEOMETRY))
{
graphene_rect_t frame;
gsk_render_node_get_bounds (node, &frame);
cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
cairo_rectangle (cr, frame.origin.x - 1, frame.origin.y - 1, frame.size.width + 2, frame.size.height + 2);
cairo_rectangle (cr, node->bounds.origin.x - 1, node->bounds.origin.y - 1,
node->bounds.size.width + 2, node->bounds.size.height + 2);
cairo_set_line_width (cr, 2);
cairo_set_source_rgba (cr, 0, 0, 0, 0.5);
cairo_stroke (cr);

File diff suppressed because it is too large Load Diff

View File

@@ -23,8 +23,7 @@ struct _GskRenderNode
GskScalingFilter min_filter;
GskScalingFilter mag_filter;
/* Bit fields; leave at the end */
gboolean is_mutable : 1;
graphene_rect_t bounds;
};
struct _GskRenderNodeClass
@@ -33,16 +32,11 @@ struct _GskRenderNodeClass
gsize struct_size;
const char *type_name;
void (* finalize) (GskRenderNode *node);
void (* make_immutable) (GskRenderNode *node);
void (* draw) (GskRenderNode *node,
cairo_t *cr);
void (* get_bounds) (GskRenderNode *node,
graphene_rect_t *bounds);
};
GskRenderNode *gsk_render_node_new (const GskRenderNodeClass *node_class);
void gsk_render_node_make_immutable (GskRenderNode *node);
GskRenderNode *gsk_render_node_new (const GskRenderNodeClass *node_class, gsize extra_size);
void gsk_render_node_get_bounds (GskRenderNode *node,
graphene_rect_t *frame);

View File

@@ -171,20 +171,20 @@ gsk_vulkan_render_pass_upload_fallback (GskVulkanRenderPass *self,
GskVulkanRender *render,
GskVulkanUploader *uploader)
{
graphene_rect_t bounds;
GskRenderNode *node;
cairo_surface_t *surface;
cairo_t *cr;
gsk_render_node_get_bounds (op->node, &bounds);
node = op->node;
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
ceil (bounds.size.width),
ceil (bounds.size.height));
ceil (node->bounds.size.width),
ceil (node->bounds.size.height));
cr = cairo_create (surface);
cairo_translate (cr, -bounds.origin.x, -bounds.origin.y);
cairo_translate (cr, -node->bounds.origin.x, -node->bounds.origin.y);
gsk_render_node_draw (node, cr);
gsk_render_node_draw (op->node, cr);
cairo_destroy (cr);
op->source = gsk_vulkan_image_new_from_data (uploader,
@@ -303,26 +303,20 @@ gsk_vulkan_render_pass_collect_vertex_data (GskVulkanRenderPass *self,
case GSK_VULKAN_OP_SURFACE:
case GSK_VULKAN_OP_TEXTURE:
{
graphene_rect_t bounds;
gsk_render_node_get_bounds (op->render.node, &bounds);
op->render.vertex_offset = offset + n_bytes;
gsk_vulkan_blend_pipeline_collect_vertex_data (GSK_VULKAN_BLEND_PIPELINE (op->render.pipeline),
data + n_bytes + offset,
&bounds);
&op->render.node.bounds);
n_bytes += op->render.vertex_count;
}
break;
case GSK_VULKAN_OP_COLOR:
{
graphene_rect_t bounds;
gsk_render_node_get_bounds (op->render.node, &bounds);
op->render.vertex_offset = offset + n_bytes;
gsk_vulkan_color_pipeline_collect_vertex_data (GSK_VULKAN_COLOR_PIPELINE (op->render.pipeline),
data + n_bytes + offset,
&bounds,
&op->render.node.bounds,
gsk_color_node_peek_color (op->render.node));
n_bytes += op->render.vertex_count;
}