diff options
author | Timm Bäder <mail@baedert.org> | 2018-10-06 09:23:26 +0200 |
---|---|---|
committer | Timm Bäder <mail@baedert.org> | 2018-10-11 12:27:56 +0200 |
commit | d15df65a9d78a7cfd40bbdbde604582a4032b5e9 (patch) | |
tree | 069c6d2b3a4367a0bc5c63c9635369cb1ad60393 | |
parent | e0a1311e5b0c7f0456934c14902d0b622766bfc7 (diff) | |
download | gtk+-d15df65a9d78a7cfd40bbdbde604582a4032b5e9.tar.gz |
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.
-rw-r--r-- | gsk/gl/gskglrenderer.c | 7 | ||||
-rw-r--r-- | gsk/gl/gskglrenderops.c | 56 | ||||
-rw-r--r-- | gsk/gl/gskglrenderopsprivate.h | 7 |
3 files changed, 66 insertions, 4 deletions
diff --git a/gsk/gl/gskglrenderer.c b/gsk/gl/gskglrenderer.c index ceaf499d00..5ba5840a53 100644 --- a/gsk/gl/gskglrenderer.c +++ b/gsk/gl/gskglrenderer.c @@ -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)) diff --git a/gsk/gl/gskglrenderops.c b/gsk/gl/gskglrenderops.c index 21223ee157..eba7c8fb47 100644 --- a/gsk/gl/gskglrenderops.c +++ b/gsk/gl/gskglrenderops.c @@ -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; } diff --git a/gsk/gl/gskglrenderopsprivate.h b/gsk/gl/gskglrenderopsprivate.h index 917c3fc8de..c77de348b4 100644 --- a/gsk/gl/gskglrenderopsprivate.h +++ b/gsk/gl/gskglrenderopsprivate.h @@ -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); |