[gtk/wip/alexl/broadway7: 78/87] broadway: Optimize color matrix + texture nodes to pre-colorized texture



commit f932d35c9507a15ad89cbf2680531ed0c11a9b77
Author: Alexander Larsson <alexl redhat com>
Date:   Thu Mar 28 23:31:36 2019 +0100

    broadway: Optimize color matrix + texture nodes to pre-colorized texture

 gsk/gskbroadwayrenderer.c | 160 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 160 insertions(+)
---
diff --git a/gsk/gskbroadwayrenderer.c b/gsk/gskbroadwayrenderer.c
index e8cf1fe347..dd30633aed 100644
--- a/gsk/gskbroadwayrenderer.c
+++ b/gsk/gskbroadwayrenderer.c
@@ -326,6 +326,145 @@ add_new_node (GskRenderer *renderer,
   return TRUE;
 }
 
+typedef struct ColorizedTexture {
+  GdkTexture *texture;
+  graphene_matrix_t color_matrix;
+  graphene_vec4_t color_offset;
+} ColorizedTexture;
+
+static void
+colorized_texture_free (ColorizedTexture *colorized)
+{
+  g_object_unref (colorized->texture);
+  g_free (colorized);
+}
+
+static ColorizedTexture *
+colorized_texture_new (GdkTexture *texture,
+                       const graphene_matrix_t *color_matrix,
+                       const graphene_vec4_t *color_offset)
+{
+  ColorizedTexture *colorized = g_new0 (ColorizedTexture, 1);
+  colorized->texture = g_object_ref (texture);
+  colorized->color_matrix = *color_matrix;
+  colorized->color_offset = *color_offset;
+  return colorized;
+}
+
+static void
+colorized_texture_free_list (GList *list)
+{
+  g_list_free_full (list, (GDestroyNotify)colorized_texture_free);
+}
+
+
+static gboolean
+matrix_equal (const graphene_matrix_t *a,
+              const graphene_matrix_t *b)
+{
+  for (int i = 0; i < 4; i ++)
+    {
+      graphene_vec4_t ra, rb;
+      graphene_matrix_get_row (a, i, &ra);
+      graphene_matrix_get_row (b, i, &rb);
+      if (!graphene_vec4_equal (&ra, &rb))
+        return FALSE;
+    }
+  return TRUE;
+}
+
+static GdkTexture *
+get_colorized_texture (GdkTexture *texture,
+                       const graphene_matrix_t *color_matrix,
+                       const graphene_vec4_t *color_offset)
+{
+  cairo_surface_t *surface = gdk_texture_download_surface (texture);
+  cairo_surface_t *image_surface;
+  graphene_vec4_t pixel;
+  guint32* pixel_data;
+  guchar *data;
+  gsize x, y, width, height, stride;
+  float alpha;
+  GdkTexture *colorized_texture;
+  GList *colorized_list, *l;
+  ColorizedTexture *colorized;
+
+  colorized_list = g_object_get_data (G_OBJECT (texture), "broadway-colorized");
+
+  for (l = colorized_list; l != NULL; l = l->next)
+    {
+      colorized = l->data;
+
+      if (graphene_vec4_equal (&colorized->color_offset, color_offset) &&
+          matrix_equal (&colorized->color_matrix, color_matrix))
+        return g_object_ref (colorized->texture);
+    }
+
+  image_surface = cairo_surface_map_to_image (surface, NULL);
+  data = cairo_image_surface_get_data (image_surface);
+  width = cairo_image_surface_get_width (image_surface);
+  height = cairo_image_surface_get_height (image_surface);
+  stride = cairo_image_surface_get_stride (image_surface);
+
+  for (y = 0; y < height; y++)
+    {
+      pixel_data = (guint32 *) data;
+      for (x = 0; x < width; x++)
+        {
+          alpha = ((pixel_data[x] >> 24) & 0xFF) / 255.0;
+
+          if (alpha == 0)
+            {
+              graphene_vec4_init (&pixel, 0.0, 0.0, 0.0, 0.0);
+            }
+          else
+            {
+              graphene_vec4_init (&pixel,
+                                  ((pixel_data[x] >> 16) & 0xFF) / (255.0 * alpha),
+                                  ((pixel_data[x] >>  8) & 0xFF) / (255.0 * alpha),
+                                  ( pixel_data[x]        & 0xFF) / (255.0 * alpha),
+                                  alpha);
+              graphene_matrix_transform_vec4 (color_matrix, &pixel, &pixel);
+            }
+
+          graphene_vec4_add (&pixel, color_offset, &pixel);
+
+          alpha = graphene_vec4_get_w (&pixel);
+          if (alpha > 0.0)
+            {
+              alpha = MIN (alpha, 1.0);
+              pixel_data[x] = (((guint32) (alpha * 255)) << 24) |
+                              (((guint32) (CLAMP (graphene_vec4_get_x (&pixel), 0, 1) * alpha * 255)) << 16) 
|
+                              (((guint32) (CLAMP (graphene_vec4_get_y (&pixel), 0, 1) * alpha * 255)) <<  8) 
|
+                               ((guint32) (CLAMP (graphene_vec4_get_z (&pixel), 0, 1) * alpha * 255));
+            }
+          else
+            {
+              pixel_data[x] = 0;
+            }
+        }
+      data += stride;
+    }
+
+  cairo_surface_mark_dirty (image_surface);
+  cairo_surface_unmap_image (surface, image_surface);
+
+  colorized_texture = gdk_texture_new_for_surface (surface);
+
+  colorized = colorized_texture_new (colorized_texture, color_matrix, color_offset);
+  if (colorized_list)
+    colorized_list = g_list_append (colorized_list, colorized);
+  else
+    {
+      colorized_list = g_list_append (NULL, colorized);
+      g_object_set_data_full (G_OBJECT (texture), "broadway-colorized",
+                              colorized_list, (GDestroyNotify)colorized_texture_free_list);
+    }
+
+  return colorized_texture;
+}
+
+
 /* Note: This tracks the offset so that we can convert
    the absolute coordinates of the GskRenderNodes to
    parent-relative which is what the dom uses, and
@@ -571,6 +710,27 @@ gsk_broadway_renderer_add_node (GskRenderer *renderer,
       return;
 
     case GSK_COLOR_MATRIX_NODE:
+      {
+        GskRenderNode *child = gsk_color_matrix_node_get_child (node);
+        if (gsk_render_node_get_node_type (child) == GSK_TEXTURE_NODE)
+          {
+            const graphene_matrix_t *color_matrix = gsk_color_matrix_node_peek_color_matrix (node);
+            const graphene_vec4_t *color_offset = gsk_color_matrix_node_peek_color_offset (node);
+            GdkTexture *texture = gsk_texture_node_get_texture (child);
+            GdkTexture *colorized_texture = get_colorized_texture (texture, color_matrix, color_offset);
+            if (add_new_node (renderer, node, BROADWAY_NODE_TEXTURE))
+              {
+                guint32 texture_id = gdk_broadway_display_ensure_texture (display, colorized_texture);
+                add_rect (nodes, &child->bounds, offset_x, offset_y);
+                add_uint32 (nodes, texture_id);
+              }
+
+            return;
+          }
+      }
+      break;
+
+
     case GSK_TEXT_NODE:
     case GSK_REPEATING_LINEAR_GRADIENT_NODE:
     case GSK_REPEAT_NODE:


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