[gtk] gl renderer: Stop determining the matrix category ourselves



commit 58c2bea959b447b36f37757fd6a1a2ae8ea675c8
Author: Timm Bäder <mail baedert org>
Date:   Sat Feb 23 07:50:51 2019 +0100

    gl renderer: Stop determining the matrix category ourselves
    
    Use the category we get from transform nodes and add ops_ API to supply
    one when we set a graphene_matrix_t directly.

 gsk/gl/gskglrenderer.c         | 119 +++++++++++------------
 gsk/gl/gskglrenderops.c        | 208 ++++++++++++++++++++++++++---------------
 gsk/gl/gskglrenderopsprivate.h |  14 ++-
 3 files changed, 195 insertions(+), 146 deletions(-)
---
diff --git a/gsk/gl/gskglrenderer.c b/gsk/gl/gskglrenderer.c
index 24f5452491..4128953430 100644
--- a/gsk/gl/gskglrenderer.c
+++ b/gsk/gl/gskglrenderer.c
@@ -249,6 +249,8 @@ node_supports_transform (GskRenderNode *node)
       case GSK_OPACITY_NODE:
       case GSK_COLOR_MATRIX_NODE:
       case GSK_TEXTURE_NODE:
+      case GSK_TRANSFORM_NODE:
+      case GSK_CROSS_FADE_NODE:
         return TRUE;
 
       default:
@@ -769,7 +771,6 @@ render_transform_node (GskGLRenderer   *self,
   const graphene_matrix_t *node_transform = gsk_transform_node_peek_transform (node);
   GskRenderNode *child = gsk_transform_node_get_child (node);
 
-
   switch (category)
     {
     case GSK_MATRIX_CATEGORY_IDENTITY:
@@ -789,23 +790,9 @@ render_transform_node (GskGLRenderer   *self,
 
     case GSK_MATRIX_CATEGORY_2D_AFFINE:
       {
-        const float scale = ops_get_scale (builder);
-        graphene_matrix_t transform, transformed_mv;
-        const float dx = builder->dx;
-        const float dy = builder->dy;
-
-        graphene_matrix_init_from_matrix (&transform, node_transform);
-        graphene_matrix_multiply (&transform, builder->current_modelview, &transformed_mv);
-        graphene_matrix_translate (&transformed_mv,
-                                   &(graphene_point3d_t) { builder->dx * scale, builder->dy * scale, 0});
-
-        builder->dx = 0;
-        builder->dy = 0;
-        ops_push_modelview (builder, &transformed_mv);
+        ops_push_modelview (builder, node_transform, category);
         gsk_gl_renderer_add_render_ops (self, child, builder);
         ops_pop_modelview (builder);
-        builder->dx = dx;
-        builder->dy = dy;
       }
     break;
 
@@ -814,8 +801,6 @@ render_transform_node (GskGLRenderer   *self,
     case GSK_MATRIX_CATEGORY_INVERTIBLE:
     default:
       {
-        const float scale = ops_get_scale (builder);
-        graphene_matrix_t transform, transformed_mv;
         const float min_x = child->bounds.origin.x;
         const float min_y = child->bounds.origin.y;
         const float max_x = min_x + child->bounds.size.width;
@@ -823,53 +808,56 @@ render_transform_node (GskGLRenderer   *self,
         int texture_id;
         gboolean is_offscreen;
 
-        graphene_matrix_init_from_matrix (&transform, node_transform);
-        graphene_matrix_multiply (&transform, builder->current_modelview, &transformed_mv);
-        graphene_matrix_translate (&transformed_mv,
-                                   &(graphene_point3d_t) { builder->dx * scale, builder->dy * scale, 0});
-
-        ops_push_modelview (builder, &transformed_mv);
-        /* For non-trivial transforms, we draw everything on a texture and then
-         * draw the texture transformed. */
-        /* TODO: We should compute a modelview containing only the "non-trivial"
-         *       part (e.g. the rotation) and use that. We want to keep the scale
-         *       for the texture.
-         */
-        add_offscreen_ops (self, builder,
-                           &child->bounds,
-                           child,
-                           &texture_id, &is_offscreen,
-                           RESET_CLIP | RESET_OPACITY);
-        ops_set_texture (builder, texture_id);
-        ops_set_program (builder, &self->blit_program);
-
-        if (is_offscreen)
-          {
-            const GskQuadVertex offscreen_vertex_data[GL_N_VERTICES] = {
-              { { min_x, min_y }, { 0, 1 }, },
-              { { min_x, max_y }, { 0, 0 }, },
-              { { max_x, min_y }, { 1, 1 }, },
-
-              { { max_x, max_y }, { 1, 0 }, },
-              { { min_x, max_y }, { 0, 0 }, },
-              { { max_x, min_y }, { 1, 1 }, },
-            };
+        ops_push_modelview (builder, node_transform, category);
 
-            ops_draw (builder, offscreen_vertex_data);
+        if (node_supports_transform (child))
+          {
+            gsk_gl_renderer_add_render_ops (self, child, builder);
           }
         else
           {
-            const GskQuadVertex onscreen_vertex_data[GL_N_VERTICES] = {
-              { { min_x, min_y }, { 0, 0 }, },
-              { { min_x, max_y }, { 0, 1 }, },
-              { { max_x, min_y }, { 1, 0 }, },
-
-              { { max_x, max_y }, { 1, 1 }, },
-              { { min_x, max_y }, { 0, 1 }, },
-              { { max_x, min_y }, { 1, 0 }, },
-            };
-
-            ops_draw (builder, onscreen_vertex_data);
+            /* For non-trivial transforms, we draw everything on a texture and then
+             * draw the texture transformed. */
+            /* TODO: We should compute a modelview containing only the "non-trivial"
+             *       part (e.g. the rotation) and use that. We want to keep the scale
+             *       for the texture.
+             */
+            add_offscreen_ops (self, builder,
+                               &child->bounds,
+                               child,
+                               &texture_id, &is_offscreen,
+                               RESET_CLIP | RESET_OPACITY);
+            ops_set_texture (builder, texture_id);
+            ops_set_program (builder, &self->blit_program);
+
+            if (is_offscreen)
+              {
+                const GskQuadVertex offscreen_vertex_data[GL_N_VERTICES] = {
+                  { { min_x, min_y }, { 0, 1 }, },
+                  { { min_x, max_y }, { 0, 0 }, },
+                  { { max_x, min_y }, { 1, 1 }, },
+
+                  { { max_x, max_y }, { 1, 0 }, },
+                  { { min_x, max_y }, { 0, 0 }, },
+                  { { max_x, min_y }, { 1, 1 }, },
+                };
+
+                ops_draw (builder, offscreen_vertex_data);
+              }
+            else
+              {
+                const GskQuadVertex onscreen_vertex_data[GL_N_VERTICES] = {
+                  { { min_x, min_y }, { 0, 0 }, },
+                  { { min_x, max_y }, { 0, 1 }, },
+                  { { max_x, min_y }, { 1, 0 }, },
+
+                  { { max_x, max_y }, { 1, 1 }, },
+                  { { min_x, max_y }, { 0, 1 }, },
+                  { { max_x, min_y }, { 1, 0 }, },
+                };
+
+                ops_draw (builder, onscreen_vertex_data);
+              }
           }
 
         ops_pop_modelview (builder);
@@ -1306,7 +1294,7 @@ render_outset_shadow_node (GskGLRenderer       *self,
       op.op = OP_CLEAR;
       ops_add (builder, &op);
       prev_projection = ops_set_projection (builder, &item_proj);
-      ops_push_modelview (builder, &identity);
+      ops_set_modelview (builder, &identity, GSK_MATRIX_CATEGORY_IDENTITY);
       prev_viewport = ops_set_viewport (builder, &GRAPHENE_RECT_INIT (0, 0, texture_width, texture_height));
 
       /* Draw outline */
@@ -2368,7 +2356,7 @@ gsk_gl_renderer_add_render_ops (GskGLRenderer   *self,
     break;
 
     case GSK_DEBUG_NODE:
-      gsk_gl_renderer_add_render_ops (self, 
+      gsk_gl_renderer_add_render_ops (self,
                                       gsk_debug_node_get_child (node),
                                       builder);
     break;
@@ -2523,7 +2511,7 @@ add_offscreen_ops (GskGLRenderer         *self,
   op.op = OP_CLEAR;
   ops_add (builder, &op);
   prev_projection = ops_set_projection (builder, &item_proj);
-  ops_push_modelview (builder, &identity);
+  ops_set_modelview (builder, &identity, GSK_MATRIX_CATEGORY_IDENTITY);
   prev_viewport = ops_set_viewport (builder,
                                     &GRAPHENE_RECT_INIT (bounds->origin.x * scale,
                                                          bounds->origin.y * scale,
@@ -2783,7 +2771,8 @@ gsk_gl_renderer_do_render (GskRenderer           *renderer,
   render_op_builder.current_viewport = *viewport;
   render_op_builder.current_opacity = 1.0f;
   render_op_builder.render_ops = self->render_ops;
-  ops_push_modelview (&render_op_builder, &modelview);
+  ops_set_modelview (&render_op_builder, &modelview,
+                     scale_factor == 1 ? GSK_MATRIX_CATEGORY_IDENTITY : GSK_MATRIX_CATEGORY_2D_AFFINE);
 
   /* Initial clip is self->render_region! */
   if (self->render_region != NULL)
diff --git a/gsk/gl/gskglrenderops.c b/gsk/gl/gskglrenderops.c
index 9fbc9ec405..ee5e19b479 100644
--- a/gsk/gl/gskglrenderops.c
+++ b/gsk/gl/gskglrenderops.c
@@ -63,63 +63,55 @@ static void
 extract_matrix_metadata (const graphene_matrix_t *m,
                          OpsMatrixMetadata       *md)
 {
-  graphene_vec3_t col1;
-  graphene_vec3_t col2;
-
-  /* Translate */
-  md->translate_x = graphene_matrix_get_value (m, 3, 0);
-  md->translate_y = graphene_matrix_get_value (m, 3, 1);
-
-  /* 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_x = graphene_vec3_length (&col1);
-  md->scale_y = graphene_vec3_length (&col2);
-
-  /* A simple matrix (in our case) is one that doesn't do anything but scale
-   * and/or translate.
-   *
-   * For orher matrices, we fall back to offscreen drawing.
-   */
-  md->simple = TRUE;
-  {
-    static const guchar check_zero[4][4] = {
-      { 0, 1, 0, 1 },        /* If any of the values marked as '1' here is non-zero, */
-      { 1, 0, 0, 1 },        /* We have to resort to offscreen drawing later on. */
-      { 1, 1, 0, 1 },
-      { 0, 0, 0, 0 },
-    };
-    int x, y;
-
-    for (x = 0; x < 4; x ++)
-      for (y = 0; y < 4; y ++)
-          if (check_zero[y][x] &&
-              graphene_matrix_get_value (m, y, x) != 0.0f)
-            {
-              md->simple = FALSE;
-              goto out;
-            }
-  }
-
-out:
-  md->only_translation = (md->simple && md->scale_x == 1 && md->scale_y == 1);
+  switch (md->category)
+    {
+    case GSK_MATRIX_CATEGORY_IDENTITY:
+      md->scale_x = 1;
+      md->scale_y = 1;
+    break;
+
+    case GSK_MATRIX_CATEGORY_2D_TRANSLATE:
+      md->translate_x = graphene_matrix_get_value (m, 3, 0);
+      md->translate_y = graphene_matrix_get_value (m, 3, 1);
+      md->scale_x = 1;
+      md->scale_y = 1;
+    break;
+
+    case GSK_MATRIX_CATEGORY_UNKNOWN:
+    case GSK_MATRIX_CATEGORY_ANY:
+    case GSK_MATRIX_CATEGORY_INVERTIBLE:
+    case GSK_MATRIX_CATEGORY_2D_AFFINE:
+      {
+        graphene_vec3_t col1;
+        graphene_vec3_t col2;
+
+        md->translate_x = graphene_matrix_get_value (m, 3, 0);
+        md->translate_y = graphene_matrix_get_value (m, 3, 1);
+
+        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_x = graphene_vec3_length (&col1);
+        md->scale_y = graphene_vec3_length (&col2);
+      }
+    break;
+    default:
+      {}
+    }
 }
 
-
 void
 ops_transform_bounds_modelview (const RenderOpBuilder *builder,
                                 const graphene_rect_t *src,
                                 graphene_rect_t       *dst)
 {
-  const float scale = ops_get_scale (builder);
   const MatrixStackEntry *head;
 
   g_assert (builder->mv_stack != NULL);
@@ -127,34 +119,32 @@ ops_transform_bounds_modelview (const RenderOpBuilder *builder,
 
   head = &g_array_index (builder->mv_stack, MatrixStackEntry, builder->mv_stack->len - 1);
 
-  if (head->metadata.only_translation)
+  switch (head->metadata.category)
     {
+    case GSK_MATRIX_CATEGORY_IDENTITY:
       *dst = *src;
-      graphene_rect_offset (dst,
-                            head->metadata.translate_x,
-                            head->metadata.translate_y);
-    }
-  else
-    {
+      break;
+
+    case GSK_MATRIX_CATEGORY_2D_TRANSLATE:
+      *dst = *src;
+      dst->origin.x += head->metadata.translate_x;
+      dst->origin.y += head->metadata.translate_y;
+      break;
+
+    /* TODO: Handle scale */
+    case GSK_MATRIX_CATEGORY_2D_AFFINE:
+    case GSK_MATRIX_CATEGORY_UNKNOWN:
+    case GSK_MATRIX_CATEGORY_ANY:
+    case GSK_MATRIX_CATEGORY_INVERTIBLE:
+    default:
       graphene_matrix_transform_bounds (builder->current_modelview,
                                         src,
                                         dst);
-    }
-
-  graphene_rect_offset (dst, builder->dx * scale, builder->dy * scale);
-}
 
-gboolean
-ops_modelview_is_simple (const RenderOpBuilder *builder)
-{
-  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);
+    }
 
-  return head->metadata.simple;
+  dst->origin.x += builder->dx * head->metadata.scale_x;
+  dst->origin.y += builder->dy * head->metadata.scale_y;
 }
 
 void
@@ -303,8 +293,8 @@ ops_has_clip (RenderOpBuilder *self)
 }
 
 static void
-ops_set_modelview (RenderOpBuilder         *builder,
-                   const graphene_matrix_t *modelview)
+ops_set_modelview_internal (RenderOpBuilder         *builder,
+                            const graphene_matrix_t *modelview)
 {
   RenderOp op;
 
@@ -338,9 +328,12 @@ ops_set_modelview (RenderOpBuilder         *builder,
     builder->current_program_state->modelview = *modelview;
 }
 
+/* This sets the modelview to the given one without looking at the
+ * one that's currently set */
 void
-ops_push_modelview (RenderOpBuilder         *builder,
-                    const graphene_matrix_t *mv)
+ops_set_modelview (RenderOpBuilder         *builder,
+                   const graphene_matrix_t *mv,
+                   GskMatrixCategory        mv_category)
 {
   MatrixStackEntry *entry;
 
@@ -353,10 +346,64 @@ ops_push_modelview (RenderOpBuilder         *builder,
   entry = &g_array_index (builder->mv_stack, MatrixStackEntry, builder->mv_stack->len - 1);
 
   entry->matrix = *mv;
+  entry->metadata.category = mv_category;
+
+  entry->metadata.dx_before = builder->dx;
+  entry->metadata.dy_before = builder->dy;
+  extract_matrix_metadata (mv, &entry->metadata);
+
+  builder->dx = 0;
+  builder->dy = 0;
+  builder->current_modelview = &entry->matrix;
+  ops_set_modelview_internal (builder, &entry->matrix);
+}
+
+/* This sets the given modelview to the one we get when multiplying
+ * the given modelview with the current one. */
+void
+ops_push_modelview (RenderOpBuilder         *builder,
+                    const graphene_matrix_t *mv,
+                    GskMatrixCategory        mv_category)
+{
+  float scale = ops_get_scale (builder);
+  MatrixStackEntry *entry;
+
+  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);
+
+  if (G_LIKELY (builder->mv_stack->len >= 2))
+    {
+      const MatrixStackEntry *cur;
+
+      cur = &g_array_index (builder->mv_stack, MatrixStackEntry, builder->mv_stack->len - 2);
+      /* Multiply given matrix with current modelview */
+
+      graphene_matrix_multiply (mv, &cur->matrix, &entry->matrix);
+      graphene_matrix_translate (&entry->matrix,
+                                 &(graphene_point3d_t) { builder->dx * scale, builder->dy * scale, 0});
+
+      entry->metadata.category = MIN (mv_category, cur->metadata.category);
+    }
+  else
+    {
+      entry->matrix = *mv;
+      entry->metadata.category = mv_category;
+    }
+
+  entry->metadata.dx_before = builder->dx;
+  entry->metadata.dy_before = builder->dy;
+
   extract_matrix_metadata (mv, &entry->metadata);
 
+  builder->dx = 0;
+  builder->dy = 0;
   builder->current_modelview = &entry->matrix;
-  ops_set_modelview (builder, mv);
+  ops_set_modelview_internal (builder, &entry->matrix);
 }
 
 void
@@ -368,6 +415,10 @@ ops_pop_modelview (RenderOpBuilder *builder)
   g_assert (builder->mv_stack);
   g_assert (builder->mv_stack->len >= 1);
 
+  head = &g_array_index (builder->mv_stack, MatrixStackEntry, builder->mv_stack->len - 1);
+  builder->dx = head->metadata.dx_before;
+  builder->dy = head->metadata.dy_before;
+
   builder->mv_stack->len --;
   head = &g_array_index (builder->mv_stack, MatrixStackEntry, builder->mv_stack->len - 1);
   m = &head->matrix;
@@ -375,7 +426,7 @@ ops_pop_modelview (RenderOpBuilder *builder)
   if (builder->mv_stack->len >= 1)
     {
       builder->current_modelview = m;
-      ops_set_modelview (builder, m);
+      ops_set_modelview_internal (builder, m);
     }
   else
     {
@@ -684,6 +735,9 @@ ops_draw (RenderOpBuilder     *builder,
   builder->buffer_size += sizeof (GskQuadVertex) * GL_N_VERTICES;
 }
 
+/* The offset is only valid for the current modelview.
+ * Setting a new modelview will add the offset to that matrix
+ * and reset the internal offset to 0. */
 void
 ops_offset (RenderOpBuilder *builder,
             float            x,
diff --git a/gsk/gl/gskglrenderopsprivate.h b/gsk/gl/gskglrenderopsprivate.h
index 67c50641e1..e80d688259 100644
--- a/gsk/gl/gskglrenderopsprivate.h
+++ b/gsk/gl/gskglrenderopsprivate.h
@@ -8,6 +8,7 @@
 #include "gskgldriverprivate.h"
 #include "gskroundedrectprivate.h"
 #include "gskglrendererprivate.h"
+#include "gskrendernodeprivate.h"
 
 #define GL_N_VERTICES 6
 #define GL_N_PROGRAMS 11
@@ -21,8 +22,10 @@ typedef struct
   float scale_x;
   float scale_y;
 
-  guint simple : 1;
-  guint only_translation : 1;
+  float dx_before;
+  float dy_before;
+
+  GskMatrixCategory category;
 } OpsMatrixMetadata;
 
 typedef struct
@@ -277,9 +280,12 @@ void              ops_dump_framebuffer   (RenderOpBuilder         *builder,
 
 void              ops_finish             (RenderOpBuilder         *builder);
 void              ops_push_modelview     (RenderOpBuilder         *builder,
-                                          const graphene_matrix_t *mv);
+                                          const graphene_matrix_t *mv,
+                                          GskMatrixCategory        mv_category);
+void              ops_set_modelview      (RenderOpBuilder         *builder,
+                                          const graphene_matrix_t *mv,
+                                          GskMatrixCategory        mv_category);
 void              ops_pop_modelview      (RenderOpBuilder         *builder);
-gboolean          ops_modelview_is_simple (const RenderOpBuilder  *builder);
 float             ops_get_scale          (const RenderOpBuilder   *builder);
 
 void              ops_set_program        (RenderOpBuilder         *builder,


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