[gtk] gl renderer: Save some matrix multiplications



commit d15df65a9d78a7cfd40bbdbde604582a4032b5e9
Author: Timm Bäder <mail baedert org>
Date:   Sat Oct 6 09:23:26 2018 +0200

    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.

 gsk/gl/gskglrenderer.c         |  7 +++---
 gsk/gl/gskglrenderops.c        | 56 ++++++++++++++++++++++++++++++++++++++++++
 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);
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]