summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTimm Bäder <mail@baedert.org>2018-10-06 09:23:26 +0200
committerTimm Bäder <mail@baedert.org>2018-10-11 12:27:56 +0200
commitd15df65a9d78a7cfd40bbdbde604582a4032b5e9 (patch)
tree069c6d2b3a4367a0bc5c63c9635369cb1ad60393
parente0a1311e5b0c7f0456934c14902d0b622766bfc7 (diff)
downloadgtk+-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.c7
-rw-r--r--gsk/gl/gskglrenderops.c56
-rw-r--r--gsk/gl/gskglrenderopsprivate.h7
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);