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:
@@ -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))
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user