gl renderer: Save some matrix multiplications

We do this for every single node, which is a little costly, especially
since the common case for the modelview matrix these days is a simple
translation. So, check whether the new modelview matrix is only a
translation matrix and if so, don't do a full matrix multiplication per
node.
This commit is contained in:
Timm Bäder
2018-10-06 09:23:26 +02:00
parent e0a1311e5b
commit d15df65a9d
3 changed files with 66 additions and 4 deletions

View File

@@ -2140,10 +2140,9 @@ gsk_gl_renderer_add_render_ops (GskGLRenderer *self,
{
graphene_rect_t transformed_node_bounds;
graphene_matrix_transform_bounds (&builder->current_modelview,
&node->bounds,
&transformed_node_bounds);
graphene_rect_offset (&transformed_node_bounds, builder->dx, builder->dy);
ops_transform_bounds_modelview (builder,
&node->bounds,
&transformed_node_bounds);
if (!graphene_rect_intersection (&builder->current_clip.bounds,
&transformed_node_bounds, NULL))

View File

@@ -19,6 +19,61 @@ ops_get_scale (const RenderOpBuilder *builder)
graphene_matrix_get_y_scale (mv));
}
static inline gboolean
matrix_is_only_translation (const graphene_matrix_t *mat)
{
graphene_vec4_t row1;
graphene_vec4_t row2;
graphene_vec4_t row3;
graphene_vec4_t row;
graphene_vec4_init (&row1, 1, 0, 0, 0);
graphene_vec4_init (&row2, 0, 1, 0, 0);
graphene_vec4_init (&row3, 0, 0, 1, 0);
graphene_matrix_get_row (mat, 0, &row);
if (!graphene_vec4_equal (&row1, &row))
return FALSE;
graphene_matrix_get_row (mat, 1, &row);
if (!graphene_vec4_equal (&row2, &row))
return FALSE;
graphene_matrix_get_row (mat, 2, &row);
if (!graphene_vec4_equal (&row3, &row))
return FALSE;
graphene_matrix_get_row (mat, 3, &row);
if (graphene_vec4_get_w (&row) != 1)
return FALSE;
return TRUE;
}
void
ops_transform_bounds_modelview (const RenderOpBuilder *builder,
const graphene_rect_t *src,
graphene_rect_t *dst)
{
if (builder->modelview_is_translation)
{
graphene_vec4_t row4;
/* TODO: We could do the get_row here only once, when setting the new modelview matrix. */
graphene_matrix_get_row (&builder->current_modelview, 3, &row4);
*dst = *src;
graphene_rect_offset (dst, graphene_vec4_get_x (&row4), graphene_vec4_get_y (&row4));
}
else
{
graphene_matrix_transform_bounds (&builder->current_modelview,
src,
dst);
}
graphene_rect_offset (dst, builder->dx, builder->dy);
}
void
ops_set_program (RenderOpBuilder *builder,
const Program *program)
@@ -156,6 +211,7 @@ ops_set_modelview (RenderOpBuilder *builder,
prev_mv = builder->current_modelview;
builder->current_modelview = *modelview;
builder->modelview_is_translation = matrix_is_only_translation (modelview);
return prev_mv;
}

View File

@@ -221,7 +221,10 @@ typedef struct
int current_render_target;
int current_texture;
GskRoundedRect current_clip;
graphene_matrix_t current_modelview;
guint modelview_is_translation : 1;
graphene_matrix_t current_projection;
graphene_rect_t current_viewport;
float current_opacity;
@@ -246,6 +249,10 @@ GskRoundedRect ops_set_clip (RenderOpBuilder *builder,
graphene_matrix_t ops_set_modelview (RenderOpBuilder *builder,
const graphene_matrix_t *modelview);
void ops_transform_bounds_modelview (const RenderOpBuilder *builder,
const graphene_rect_t *src,
graphene_rect_t *dst);
graphene_matrix_t ops_set_projection (RenderOpBuilder *builder,
const graphene_matrix_t *projection);