[gtk] gl renderer: Use stack to keep track of modelview matrix



commit ef751bc809dbaabf8c08efb2e38171e3181371d8
Author: Timm Bäder <mail baedert org>
Date:   Mon Nov 26 17:52:35 2018 +0100

    gl renderer: Use stack to keep track of modelview matrix
    
    So we can avoid calculating metadata for matrices all the time.

 gsk/gl/gskglrenderer.c         |  38 ++++++------
 gsk/gl/gskglrenderops.c        | 128 ++++++++++++++++++++++++++++++++---------
 gsk/gl/gskglrenderopsprivate.h |  29 ++++++++--
 3 files changed, 140 insertions(+), 55 deletions(-)
---
diff --git a/gsk/gl/gskglrenderer.c b/gsk/gl/gskglrenderer.c
index 5ba5840a53..f8074a4531 100644
--- a/gsk/gl/gskglrenderer.c
+++ b/gsk/gl/gskglrenderer.c
@@ -301,7 +301,7 @@ rounded_rect_to_floats (GskGLRenderer        *self,
   int i;
   graphene_rect_t transformed_bounds;
 
-  graphene_matrix_transform_bounds (&builder->current_modelview, &rect->bounds, &transformed_bounds);
+  graphene_matrix_transform_bounds (builder->current_modelview, &rect->bounds, &transformed_bounds);
 
   outline[0] = transformed_bounds.origin.x;
   outline[1] = transformed_bounds.origin.y;
@@ -578,7 +578,7 @@ render_border_node (GskGLRenderer   *self,
 
     /* Prepare outline */
     outline = *rounded_outline;
-    graphene_matrix_transform_bounds (&builder->current_modelview,
+    graphene_matrix_transform_bounds (builder->current_modelview,
                                       &outline.bounds, &outline.bounds);
     for (i = 0; i < 4; i ++)
       {
@@ -711,17 +711,15 @@ render_offset_node (GskGLRenderer   *self,
 
     default:
       {
-        graphene_matrix_t prev_mv;
         graphene_matrix_t transform, transformed_mv;
 
         graphene_matrix_init_translate (&transform,
                                         &GRAPHENE_POINT3D_INIT(dx, dy, 1.0));
-        graphene_matrix_multiply (&transform, &builder->current_modelview, &transformed_mv);
-        prev_mv = ops_set_modelview (builder, &transformed_mv);
+        graphene_matrix_multiply (&transform, builder->current_modelview, &transformed_mv);
 
+        ops_push_modelview (builder, &transformed_mv);
         gsk_gl_renderer_add_render_ops (self, child, builder);
-
-        ops_set_modelview (builder, &prev_mv);
+        ops_pop_modelview (builder);
       }
     }
 }
@@ -732,16 +730,14 @@ render_transform_node (GskGLRenderer   *self,
                        RenderOpBuilder *builder)
 {
   GskRenderNode *child = gsk_transform_node_get_child (node);
-  graphene_matrix_t prev_mv;
   graphene_matrix_t transform, transformed_mv;
 
   graphene_matrix_init_from_matrix (&transform, gsk_transform_node_peek_transform (node));
-  graphene_matrix_multiply (&transform, &builder->current_modelview, &transformed_mv);
-  prev_mv = ops_set_modelview (builder, &transformed_mv);
+  graphene_matrix_multiply (&transform, builder->current_modelview, &transformed_mv);
 
+  ops_push_modelview (builder, &transformed_mv);
   gsk_gl_renderer_add_render_ops (self, child, builder);
-
-  ops_set_modelview (builder, &prev_mv);
+  ops_pop_modelview (builder);
 }
 
 static inline void
@@ -805,7 +801,7 @@ render_clip_node (GskGLRenderer   *self,
   GskRoundedRect child_clip;
 
   transformed_clip = *gsk_clip_node_peek_clip (node);
-  graphene_matrix_transform_bounds (&builder->current_modelview, &transformed_clip, &transformed_clip);
+  graphene_matrix_transform_bounds (builder->current_modelview, &transformed_clip, &transformed_clip);
 
   graphene_rect_intersection (&transformed_clip,
                               &builder->current_clip.bounds,
@@ -835,7 +831,7 @@ render_rounded_clip_node (GskGLRenderer       *self,
   int i;
 
   transformed_clip = child_clip;
-  graphene_matrix_transform_bounds (&builder->current_modelview, &child_clip.bounds, 
&transformed_clip.bounds);
+  graphene_matrix_transform_bounds (builder->current_modelview, &child_clip.bounds, 
&transformed_clip.bounds);
 
   if (graphene_rect_contains_rect (&builder->current_clip.bounds,
                                    &transformed_clip.bounds))
@@ -1071,7 +1067,6 @@ render_outset_shadow_node (GskGLRenderer       *self,
   RenderOp op;
   graphene_matrix_t identity;
   graphene_matrix_t prev_projection;
-  graphene_matrix_t prev_modelview;
   graphene_rect_t prev_viewport;
   graphene_matrix_t item_proj;
   int blurred_texture_id;
@@ -1124,7 +1119,7 @@ render_outset_shadow_node (GskGLRenderer       *self,
       op.op = OP_CLEAR;
       ops_add (builder, &op);
       prev_projection = ops_set_projection (builder, &item_proj);
-      prev_modelview = ops_set_modelview (builder, &identity);
+      ops_push_modelview (builder, &identity);
       prev_viewport = ops_set_viewport (builder, &GRAPHENE_RECT_INIT (0, 0, texture_width, texture_height));
 
       /* Draw outline */
@@ -1175,7 +1170,7 @@ render_outset_shadow_node (GskGLRenderer       *self,
 
       ops_set_clip (builder, &prev_clip);
       ops_set_viewport (builder, &prev_viewport);
-      ops_set_modelview (builder, &prev_modelview);
+      ops_pop_modelview (builder);
       ops_set_projection (builder, &prev_projection);
       ops_set_render_target (builder, prev_render_target);
 
@@ -2273,7 +2268,6 @@ add_offscreen_ops (GskGLRenderer   *self,
   RenderOp op;
   graphene_matrix_t identity;
   graphene_matrix_t prev_projection;
-  graphene_matrix_t prev_modelview;
   graphene_rect_t prev_viewport;
   graphene_matrix_t item_proj;
   GskRoundedRect prev_clip;
@@ -2313,7 +2307,7 @@ add_offscreen_ops (GskGLRenderer   *self,
   op.op = OP_CLEAR;
   ops_add (builder, &op);
   prev_projection = ops_set_projection (builder, &item_proj);
-  prev_modelview = ops_set_modelview (builder, &identity);
+  ops_push_modelview (builder, &identity);
   prev_viewport = ops_set_viewport (builder, &GRAPHENE_RECT_INIT (min_x * scale,
                                                                   min_y * scale,
                                                                   width, height));
@@ -2329,7 +2323,7 @@ add_offscreen_ops (GskGLRenderer   *self,
     ops_set_clip (builder, &prev_clip);
 
   ops_set_viewport (builder, &prev_viewport);
-  ops_set_modelview (builder, &prev_modelview);
+  ops_pop_modelview (builder);
   ops_set_projection (builder, &prev_projection);
   ops_set_render_target (builder, prev_render_target);
 
@@ -2547,11 +2541,11 @@ gsk_gl_renderer_do_render (GskRenderer           *renderer,
   memset (&render_op_builder, 0, sizeof (render_op_builder));
   render_op_builder.renderer = self;
   render_op_builder.current_projection = projection;
-  render_op_builder.current_modelview = modelview;
   render_op_builder.current_viewport = *viewport;
   render_op_builder.current_opacity = 1.0f;
   render_op_builder.render_ops = self->render_ops;
   gsk_rounded_rect_init_from_rect (&render_op_builder.current_clip, viewport, 0.0f);
+  ops_push_modelview (&render_op_builder, &modelview);
 
   if (fbo_id != 0)
     ops_set_render_target (&render_op_builder, fbo_id);
@@ -2560,6 +2554,8 @@ gsk_gl_renderer_do_render (GskRenderer           *renderer,
 
   /* We correctly reset the state everywhere */
   g_assert_cmpint (render_op_builder.current_render_target, ==, fbo_id);
+  ops_pop_modelview (&render_op_builder);
+  ops_finish (&render_op_builder);
 
   /*g_message ("Ops: %u", self->render_ops->len);*/
 
diff --git a/gsk/gl/gskglrenderops.c b/gsk/gl/gskglrenderops.c
index f89022b133..f0ef2f633e 100644
--- a/gsk/gl/gskglrenderops.c
+++ b/gsk/gl/gskglrenderops.c
@@ -1,5 +1,13 @@
 #include "gskglrenderopsprivate.h"
 
+void
+ops_finish (RenderOpBuilder *builder)
+{
+  if (builder->mv_stack)
+    g_array_free (builder->mv_stack, TRUE);
+}
+
+
 static inline void
 rgba_to_float (const GdkRGBA *c,
                float         *f)
@@ -13,24 +21,14 @@ rgba_to_float (const GdkRGBA *c,
 float
 ops_get_scale (const RenderOpBuilder *builder)
 {
-  const graphene_matrix_t *mv = &builder->current_modelview;
-  graphene_vec3_t col1;
-  graphene_vec3_t col2;
+  const MatrixStackEntry *head;
 
-  /* TODO: We should probably split this up into two values... */
-
-  graphene_vec3_init (&col1,
-                      graphene_matrix_get_value (mv, 0, 0),
-                      graphene_matrix_get_value (mv, 1, 0),
-                      graphene_matrix_get_value (mv, 2, 0));
+  g_assert (builder->mv_stack != NULL);
+  g_assert (builder->mv_stack->len >= 1);
 
-  graphene_vec3_init (&col2,
-                      graphene_matrix_get_value (mv, 0, 1),
-                      graphene_matrix_get_value (mv, 1, 1),
-                      graphene_matrix_get_value (mv, 2, 1));
+  head = &g_array_index (builder->mv_stack, MatrixStackEntry, builder->mv_stack->len - 1);
 
-  return MAX (graphene_vec3_length (&col1),
-              graphene_vec3_length (&col2));
+  return head->metadata.scale;
 }
 
 static inline gboolean
@@ -64,23 +62,59 @@ matrix_is_only_translation (const graphene_matrix_t *mat)
   return TRUE;
 }
 
+static void
+extract_matrix_metadata (const graphene_matrix_t *m,
+                         OpsMatrixMetadata       *md)
+{
+  graphene_vec3_t col1;
+  graphene_vec3_t col2;
+
+  /* Is this matrix JUST a translation? */
+  md->is_only_translation = matrix_is_only_translation (m);
+
+  /* TODO: We should probably split this up into two values... */
+
+  /* Scale */
+  graphene_vec3_init (&col1,
+                      graphene_matrix_get_value (m, 0, 0),
+                      graphene_matrix_get_value (m, 1, 0),
+                      graphene_matrix_get_value (m, 2, 0));
+
+  graphene_vec3_init (&col2,
+                      graphene_matrix_get_value (m, 0, 1),
+                      graphene_matrix_get_value (m, 1, 1),
+                      graphene_matrix_get_value (m, 2, 1));
+
+  md->scale = MAX (graphene_vec3_length (&col1),
+                   graphene_vec3_length (&col2));
+
+}
+
+
 void
 ops_transform_bounds_modelview (const RenderOpBuilder *builder,
                                 const graphene_rect_t *src,
                                 graphene_rect_t       *dst)
 {
-  if (builder->modelview_is_translation)
+  const MatrixStackEntry *head;
+
+  g_assert (builder->mv_stack != NULL);
+  g_assert (builder->mv_stack->len >= 1);
+
+  head = &g_array_index (builder->mv_stack, MatrixStackEntry, builder->mv_stack->len - 1);
+
+  if (head->metadata.is_only_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);
+      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,
+      graphene_matrix_transform_bounds (builder->current_modelview,
                                         src,
                                         dst);
     }
@@ -118,12 +152,12 @@ ops_set_program (RenderOpBuilder *builder,
     }
 
   if (memcmp (&empty_matrix, &builder->program_state[program->index].modelview, sizeof (graphene_matrix_t)) 
== 0 ||
-      memcmp (&builder->current_modelview, &builder->program_state[program->index].modelview, sizeof 
(graphene_matrix_t)) != 0)
+      memcmp (builder->current_modelview, &builder->program_state[program->index].modelview, sizeof 
(graphene_matrix_t)) != 0)
     {
       op.op = OP_CHANGE_MODELVIEW;
-      op.modelview = builder->current_modelview;
+      op.modelview = *builder->current_modelview;
       g_array_append_val (builder->render_ops, op);
-      builder->program_state[program->index].modelview = builder->current_modelview;
+      builder->program_state[program->index].modelview = *builder->current_modelview;
     }
 
   if (memcmp (&empty_rect, &builder->program_state[program->index].viewport, sizeof (graphene_rect_t)) == 0 
||
@@ -187,17 +221,16 @@ ops_set_clip (RenderOpBuilder      *builder,
   return prev_clip;
 }
 
-graphene_matrix_t
+static void
 ops_set_modelview (RenderOpBuilder         *builder,
                    const graphene_matrix_t *modelview)
 {
   RenderOp op;
-  graphene_matrix_t prev_mv;
 
   if (builder->current_program &&
       memcmp (&builder->program_state[builder->current_program->index].modelview, modelview,
               sizeof (graphene_matrix_t)) == 0)
-    return *modelview;
+    return;
 
   if (builder->render_ops->len > 0)
     {
@@ -222,12 +255,51 @@ ops_set_modelview (RenderOpBuilder         *builder,
 
   if (builder->current_program != NULL)
     builder->program_state[builder->current_program->index].modelview = *modelview;
+}
 
-  prev_mv = builder->current_modelview;
-  builder->current_modelview = *modelview;
-  builder->modelview_is_translation = matrix_is_only_translation (modelview);
+void
+ops_push_modelview (RenderOpBuilder         *builder,
+                    const graphene_matrix_t *mv)
+{
+  MatrixStackEntry *entry;
 
-  return prev_mv;
+  if (G_UNLIKELY (builder->mv_stack == NULL))
+      builder->mv_stack = g_array_new (FALSE, TRUE, sizeof (MatrixStackEntry));
+
+  g_assert (builder->mv_stack != NULL);
+
+  g_array_set_size (builder->mv_stack, builder->mv_stack->len + 1);
+  entry = &g_array_index (builder->mv_stack, MatrixStackEntry, builder->mv_stack->len - 1);
+
+  entry->matrix = *mv;
+  extract_matrix_metadata (mv, &entry->metadata);
+
+  builder->current_modelview = &entry->matrix;
+  ops_set_modelview (builder, mv);
+}
+
+void
+ops_pop_modelview (RenderOpBuilder *builder)
+{
+  const graphene_matrix_t *m;
+  const MatrixStackEntry *head;
+
+  g_assert (builder->mv_stack);
+  g_assert (builder->mv_stack->len >= 1);
+
+  builder->mv_stack->len --;
+  head = &g_array_index (builder->mv_stack, MatrixStackEntry, builder->mv_stack->len - 1);
+  m = &head->matrix;
+
+  if (builder->mv_stack->len >= 1)
+    {
+      builder->current_modelview = m;
+      ops_set_modelview (builder, m);
+    }
+  else
+    {
+      builder->current_modelview = NULL;
+    }
 }
 
 graphene_matrix_t
diff --git a/gsk/gl/gskglrenderopsprivate.h b/gsk/gl/gskglrenderopsprivate.h
index c77de348b4..18a4734257 100644
--- a/gsk/gl/gskglrenderopsprivate.h
+++ b/gsk/gl/gskglrenderopsprivate.h
@@ -12,6 +12,20 @@
 #define GL_N_VERTICES 6
 #define GL_N_PROGRAMS 12
 
+
+
+typedef struct
+{
+  guint is_only_translation : 1;
+  float scale;
+} OpsMatrixMetadata;
+
+typedef struct
+{
+  graphene_matrix_t matrix;
+  OpsMatrixMetadata metadata;
+} MatrixStackEntry;
+
 enum {
   OP_NONE,
   OP_CHANGE_OPACITY         =  1,
@@ -222,9 +236,6 @@ typedef struct
   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;
@@ -234,10 +245,19 @@ typedef struct
 
   GArray *render_ops;
   GskGLRenderer *renderer;
+
+  /* Stack of modelview matrices */
+  GArray *mv_stack;
+  /* Pointer into mv_stack */
+  const graphene_matrix_t *current_modelview;
 } RenderOpBuilder;
 
 
 
+void              ops_finish             (RenderOpBuilder         *builder);
+void              ops_push_modelview     (RenderOpBuilder         *builder,
+                                          const graphene_matrix_t *mv);
+void              ops_pop_modelview      (RenderOpBuilder         *builder);
 float             ops_get_scale          (const RenderOpBuilder   *builder);
 
 void              ops_set_program        (RenderOpBuilder         *builder,
@@ -246,9 +266,6 @@ void              ops_set_program        (RenderOpBuilder         *builder,
 GskRoundedRect    ops_set_clip           (RenderOpBuilder         *builder,
                                           const GskRoundedRect    *clip);
 
-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);


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