vulkan: Add an UploadGlyphOp
authorBenjamin Otte <otte@redhat.com>
Fri, 14 Jul 2023 18:55:45 +0000 (20:55 +0200)
committerBenjamin Otte <otte@redhat.com>
Sun, 16 Jul 2023 11:16:43 +0000 (13:16 +0200)
Now all the uploads have their own op.

gsk/vulkan/gskvulkanglyphcache.c
gsk/vulkan/gskvulkanglyphcacheprivate.h
gsk/vulkan/gskvulkanrender.c
gsk/vulkan/gskvulkanrenderer.c
gsk/vulkan/gskvulkanrendererprivate.h
gsk/vulkan/gskvulkanrenderpass.c
gsk/vulkan/gskvulkanuploadop.c
gsk/vulkan/gskvulkanuploadopprivate.h

index 1b5b916f119c608399acff5d4d46e3d3be108d77..a86d197e0656534861d71bbc585176fdf11b70a3 100644 (file)
@@ -3,6 +3,8 @@
 #include "gskvulkanglyphcacheprivate.h"
 
 #include "gskvulkanimageprivate.h"
+#include "gskvulkanuploadopprivate.h"
+
 #include "gskdebugprivate.h"
 #include "gskprivate.h"
 #include "gskrendererprivate.h"
@@ -29,7 +31,6 @@ typedef struct {
   int width, height;
   int x, y, y0;
   int num_glyphs;
-  GList *dirty_glyphs;
   guint old_pixels;
 } Atlas;
 
@@ -56,7 +57,6 @@ static gboolean glyph_cache_equal      (gconstpointer v1,
                                         gconstpointer v2);
 static void     glyph_cache_key_free   (gpointer      v);
 static void     glyph_cache_value_free (gpointer      v);
-static void     dirty_glyph_free       (gpointer      v);
 
 static Atlas *
 create_atlas (GskVulkanGlyphCache *cache)
@@ -71,7 +71,6 @@ create_atlas (GskVulkanGlyphCache *cache)
   atlas->x = 0;
   atlas->image = NULL;
   atlas->num_glyphs = 0;
-  atlas->dirty_glyphs = NULL;
 
   atlas->image = gsk_vulkan_image_new_for_atlas (cache->vulkan, atlas->width, atlas->height);
 
@@ -84,7 +83,6 @@ free_atlas (gpointer v)
   Atlas *atlas = v;
 
   g_clear_object (&atlas->image);
-  g_list_free_full (atlas->dirty_glyphs, dirty_glyph_free);
   g_free (atlas);
 }
 
@@ -159,30 +157,14 @@ glyph_cache_value_free (gpointer v)
   g_free (v);
 }
 
-typedef struct {
-  GlyphCacheKey *key;
-  GskVulkanCachedGlyph *value;
-  cairo_surface_t *surface;
-} DirtyGlyph;
-
-static void
-dirty_glyph_free (gpointer v)
-{
-  DirtyGlyph *glyph = v;
-
-  if (glyph->surface)
-    cairo_surface_destroy (glyph->surface);
-  g_free (glyph);
-}
-
 static void
 add_to_cache (GskVulkanGlyphCache  *cache,
+              GskVulkanRender      *render,
               GlyphCacheKey        *key,
               GskVulkanCachedGlyph *value)
 {
   Atlas *atlas;
   int i;
-  DirtyGlyph *dirty;
   int width = ceil (value->draw_width * key->scale / 1024.0);
   int height = ceil (value->draw_height * key->scale / 1024.0);
   int width_with_padding = width + 2 * PADDING;
@@ -228,16 +210,28 @@ add_to_cache (GskVulkanGlyphCache  *cache,
   value->tw = (float)width / atlas->width;
   value->th = (float)height / atlas->height;
 
-  dirty = g_new (DirtyGlyph, 1);
-  dirty->key = key;
-  dirty->value = value;
-  atlas->dirty_glyphs = g_list_prepend (atlas->dirty_glyphs, dirty);
-
   atlas->x = atlas->x + width_with_padding;
   atlas->y = MAX (atlas->y, atlas->y0 + height_with_padding);
 
   atlas->num_glyphs++;
 
+  gsk_vulkan_upload_glyph_op (render,
+                              atlas->image,
+                              &(cairo_rectangle_int_t) {
+                                  .x = value->atlas_x,
+                                  .y = value->atlas_y,
+                                  .width = width_with_padding,
+                                  .height = height_with_padding
+                              },
+                              key->font,
+                              &(PangoGlyphInfo) {
+                                  .glyph = key->glyph,
+                                  .geometry.width = value->draw_width * PANGO_SCALE,
+                                  .geometry.x_offset = (0.25 * key->xshift - value->draw_x) * PANGO_SCALE,
+                                  .geometry.y_offset = (0.25 * key->yshift - value->draw_y) * PANGO_SCALE
+                              },
+                              (float) key->scale / PANGO_SCALE);
+
 #ifdef G_ENABLE_DEBUG
   if (GSK_DEBUG_CHECK (GLYPH_CACHE))
     {
@@ -245,9 +239,9 @@ add_to_cache (GskVulkanGlyphCache  *cache,
       for (i = 0; i < cache->atlases->len; i++)
         {
           atlas = g_ptr_array_index (cache->atlases, i);
-          g_print ("\tAtlas %d (%dx%d): %d glyphs (%d dirty), %.2g%% old pixels, filled to %d, %d / %d\n",
+          g_print ("\tAtlas %d (%dx%d): %d glyphs, %.2g%% old pixels, filled to %d, %d / %d\n",
                    i, atlas->width, atlas->height,
-                   atlas->num_glyphs, g_list_length (atlas->dirty_glyphs),
+                   atlas->num_glyphs,
                    100.0 * (double)atlas->old_pixels / (double)(atlas->width * atlas->height),
                    atlas->x, atlas->y0, atlas->y);
         }
@@ -255,82 +249,6 @@ add_to_cache (GskVulkanGlyphCache  *cache,
 #endif
 }
 
-static void
-render_glyph (Atlas          *atlas,
-              DirtyGlyph     *glyph,
-              GskImageRegion *region)
-{
-  GlyphCacheKey *key = glyph->key;
-  GskVulkanCachedGlyph *value = glyph->value;
-  cairo_surface_t *surface;
-  cairo_t *cr;
-  PangoGlyphString glyphs;
-  PangoGlyphInfo gi;
-  int surface_height;
-  int surface_width;
-
-  surface_width = ceil (value->draw_width * key->scale / 1024.0) + 2 * PADDING;
-  surface_height = ceil (value->draw_height * key->scale / 1024.0) + 2 * PADDING;
-
-  surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, surface_width, surface_height);
-  cairo_surface_set_device_scale (surface, key->scale / 1024.0, key->scale / 1024.0);
-
-  cr = cairo_create (surface);
-
-  /* Make sure the entire surface is initialized to black */
-  cairo_set_source_rgba (cr, 0, 0, 0, 0);
-  cairo_rectangle (cr, 0.0, 0.0, surface_width, surface_width);
-  cairo_fill (cr);
-
-  /* Draw glyph */
-  cairo_set_source_rgba (cr, 1, 1, 1, 1);
-
-  gi.glyph = key->glyph;
-  gi.geometry.width = value->draw_width * 1024;
-  gi.geometry.x_offset = (0.25 * key->xshift - value->draw_x) * 1024;
-  gi.geometry.y_offset = (0.25 * key->yshift - value->draw_y) * 1024;
-
-  glyphs.num_glyphs = 1;
-  glyphs.glyphs = &gi;
-
-  pango_cairo_show_glyph_string (cr, key->font, &glyphs);
-
-  cairo_destroy (cr);
-
-  glyph->surface = surface;
-
-  region->data = cairo_image_surface_get_data (surface);
-  region->width = cairo_image_surface_get_width (surface);
-  region->height = cairo_image_surface_get_height (surface);
-  region->stride = cairo_image_surface_get_stride (surface);
-  region->x = value->atlas_x;
-  region->y = value->atlas_y;
-}
-
-static void
-upload_dirty_glyphs (GskVulkanGlyphCache *cache,
-                     Atlas               *atlas,
-                     GskVulkanUploader   *uploader)
-{
-  GList *l;
-  guint num_regions;
-  GskImageRegion *regions;
-  int i;
-
-  num_regions = g_list_length (atlas->dirty_glyphs);
-  regions = alloca (sizeof (GskImageRegion) * num_regions);
-
-  for (l = atlas->dirty_glyphs, i = 0; l; l = l->next, i++)
-    render_glyph (atlas, (DirtyGlyph *)l->data, &regions[i]);
-
-  GSK_DEBUG (GLYPH_CACHE, "uploading %d glyphs to cache", num_regions);
-
-  gsk_vulkan_image_upload_regions (atlas->image, uploader, num_regions, regions);
-
-  g_list_free_full (atlas->dirty_glyphs, dirty_glyph_free);
-  atlas->dirty_glyphs = NULL;
-}
-
 GskVulkanGlyphCache *
 gsk_vulkan_glyph_cache_new (GdkVulkanContext *vulkan)
 {
@@ -347,7 +265,7 @@ gsk_vulkan_glyph_cache_new (GdkVulkanContext *vulkan)
 
 GskVulkanCachedGlyph *
 gsk_vulkan_glyph_cache_lookup (GskVulkanGlyphCache *cache,
-                               gboolean             create,
+                               GskVulkanRender     *render,
                                PangoFont           *font,
                                PangoGlyph           glyph,
                                int                  x,
@@ -381,7 +299,7 @@ gsk_vulkan_glyph_cache_lookup (GskVulkanGlyphCache *cache,
         }
     }
 
-  if (create && value == NULL)
+  if (value == NULL)
     {
       GlyphCacheKey *key;
       PangoRectangle ink_rect;
@@ -410,7 +328,7 @@ gsk_vulkan_glyph_cache_lookup (GskVulkanGlyphCache *cache,
       key->scale = (guint)(scale * 1024);
 
       if (ink_rect.width > 0 && ink_rect.height > 0)
-        add_to_cache (cache, key, value);
+        add_to_cache (cache, render, key, value);
 
       g_hash_table_insert (cache->hash_table, key, value);
     }
@@ -418,22 +336,6 @@ gsk_vulkan_glyph_cache_lookup (GskVulkanGlyphCache *cache,
   return value;
 }
 
-void
-gsk_vulkan_glyph_cache_upload (GskVulkanGlyphCache *cache,
-                               GskVulkanUploader   *uploader)
-{
-  Atlas *atlas;
-  guint i;
-
-  for (i = 0; i < cache->atlases->len; i++)
-    {
-      atlas = g_ptr_array_index (cache->atlases, i);
-
-      if (atlas->dirty_glyphs)
-        upload_dirty_glyphs (cache, atlas, uploader);
-    }
-}
-
 void
 gsk_vulkan_glyph_cache_begin_frame (GskVulkanGlyphCache *cache)
 {
index 4d845a6295389ff5b7b44352c7ed6912345322bd..bd0977e6b135faa721847e55ace16bc636e7f7e3 100644 (file)
@@ -2,6 +2,7 @@
 
 #include <pango/pango.h>
 #include "gskvulkanimageprivate.h"
+#include "gskvulkanprivate.h"
 
 G_BEGIN_DECLS
 
@@ -32,11 +33,8 @@ typedef struct
 
 GskVulkanGlyphCache  *gsk_vulkan_glyph_cache_new            (GdkVulkanContext    *vulkan);
 
-void                  gsk_vulkan_glyph_cache_upload         (GskVulkanGlyphCache *cache,
-                                                             GskVulkanUploader   *uploader);
-
 GskVulkanCachedGlyph *gsk_vulkan_glyph_cache_lookup         (GskVulkanGlyphCache *cache,
-                                                             gboolean             create,
+                                                             GskVulkanRender     *render,
                                                              PangoFont           *font,
                                                              PangoGlyph           glyph,
                                                              int                  x,
index 6a9a1bac5039586e04813e353631e940286f1fd3..8b412b5470abbd32931763e05fbb2fddac77f436 100644 (file)
@@ -511,9 +511,6 @@ gsk_vulkan_render_upload (GskVulkanRender *self)
 {
   GskVulkanOp *op;
 
-  gsk_vulkan_glyph_cache_upload (gsk_vulkan_renderer_get_glyph_cache (GSK_VULKAN_RENDERER (self->renderer)),
-                                 self->uploader);
-
   for (op = self->first_op; op; op = op->next)
     {
       gsk_vulkan_op_upload (op, self->uploader);
index 6985e92a666bcf0f46891a3509efbe657685adb7..862e278a5dac32965f7581a94bc777de36060f41 100644 (file)
@@ -463,17 +463,6 @@ gsk_vulkan_renderer_get_glyph_cache (GskVulkanRenderer  *self)
   return self->glyph_cache;
 }
 
-GskVulkanCachedGlyph *
-gsk_vulkan_renderer_cache_glyph (GskVulkanRenderer *self,
-                                 PangoFont         *font,
-                                 PangoGlyph         glyph,
-                                 int                x,
-                                 int                y,
-                                 float              scale)
-{
-  return gsk_vulkan_glyph_cache_lookup (self->glyph_cache, TRUE, font, glyph, x, y, scale);
-}
-
 /**
  * gsk_vulkan_renderer_new:
  *
index 65809afabd8870f761dc18f6d6588d08ff1f0878..af4cbccf721758743b41213d80803fe836e3a72a 100644 (file)
@@ -12,13 +12,6 @@ void                    gsk_vulkan_renderer_add_texture_image           (GskVulk
                                                                          GdkTexture             *texture,
                                                                          GskVulkanImage         *image);
 
-GskVulkanCachedGlyph  *gsk_vulkan_renderer_cache_glyph      (GskVulkanRenderer *renderer,
-                                                             PangoFont         *font,
-                                                             PangoGlyph         glyph,
-                                                             int                x,
-                                                             int                y,
-                                                             float              scale);
-
 GskVulkanGlyphCache *   gsk_vulkan_renderer_get_glyph_cache             (GskVulkanRenderer      *self);
 
 
index 6f16a0a95058a0e353bec9ea2ca1b6247b9bdd01..1c951a604e3a6cc590f3966c88dbef5613f363bf 100644 (file)
@@ -1041,7 +1041,7 @@ gsk_vulkan_render_pass_add_text_node (GskVulkanRenderPass       *self,
                                       GskRenderNode             *node)
 {
   const PangoGlyphInfo *glyphs;
-  GskVulkanRenderer *renderer;
+  GskVulkanGlyphCache *cache;
   const graphene_point_t *node_offset;
   const PangoFont *font;
   guint num_glyphs;
@@ -1049,12 +1049,11 @@ gsk_vulkan_render_pass_add_text_node (GskVulkanRenderPass       *self,
   int i;
   float scale;
 
-  renderer = GSK_VULKAN_RENDERER (gsk_vulkan_render_get_renderer (render));
+  cache = gsk_vulkan_renderer_get_glyph_cache (GSK_VULKAN_RENDERER (gsk_vulkan_render_get_renderer (render)));
   num_glyphs = gsk_text_node_get_num_glyphs (node);
   glyphs = gsk_text_node_get_glyphs (node, NULL);
   font = gsk_text_node_get_font (node);
 
-
   scale = MAX (graphene_vec2_get_x (&state->scale), graphene_vec2_get_y (&state->scale));
   node_offset = gsk_text_node_get_offset (node);
 
@@ -1065,12 +1064,13 @@ gsk_vulkan_render_pass_add_text_node (GskVulkanRenderPass       *self,
       const PangoGlyphInfo *gi = &glyphs[i];
       graphene_rect_t glyph_bounds, glyph_tex_rect;
 
-      glyph = gsk_vulkan_renderer_cache_glyph (renderer,
-                                               (PangoFont *)font,
-                                               gi->glyph,
-                                               x_position + gi->geometry.x_offset,
-                                               gi->geometry.y_offset,
-                                               scale);
+      glyph = gsk_vulkan_glyph_cache_lookup (cache,
+                                             render,
+                                             (PangoFont *)font,
+                                             gi->glyph,
+                                             x_position + gi->geometry.x_offset,
+                                             gi->geometry.y_offset,
+                                             scale);
 
       glyph_bounds = GRAPHENE_RECT_INIT (glyph->draw_x + node_offset->x + (float) (x_position + gi->geometry.x_offset) / PANGO_SCALE,
                                          glyph->draw_y + node_offset->y + (float) (gi->geometry.y_offset) / PANGO_SCALE,
index 908a286a4bb26e6cd621ca08e72cb4c3e0556311..ef6b4ef95b55bad0bd333259d997e7b94eac735c 100644 (file)
@@ -408,3 +408,133 @@ gsk_vulkan_upload_cairo_op (GskVulkanRender       *render,
 
   return self->image;
 }
+
+typedef struct _GskVulkanUploadGlyphOp GskVulkanUploadGlyphOp;
+
+struct _GskVulkanUploadGlyphOp
+{
+  GskVulkanOp op;
+
+  GskVulkanImage *image;
+  cairo_rectangle_int_t area;
+  PangoFont *font;
+  PangoGlyphInfo glyph_info;
+  float scale;
+
+  GskVulkanBuffer *buffer;
+};
+
+static void
+gsk_vulkan_upload_glyph_op_finish (GskVulkanOp *op)
+{
+  GskVulkanUploadGlyphOp *self = (GskVulkanUploadGlyphOp *) op;
+
+  g_object_unref (self->image);
+  g_object_unref (self->font);
+
+  g_clear_pointer (&self->buffer, gsk_vulkan_buffer_free);
+}
+
+static void
+gsk_vulkan_upload_glyph_op_print (GskVulkanOp *op,
+                                  GString     *string,
+                                  guint        indent)
+{
+  GskVulkanUploadGlyphOp *self = (GskVulkanUploadGlyphOp *) op;
+
+  print_indent (string, indent);
+  g_string_append (string, "upload-glyph ");
+  print_int_rect (string, &self->area);
+  g_string_append_printf (string, "glyph %u @ %g ", self->glyph_info.glyph, self->scale);
+  print_newline (string);
+}
+
+static void
+gsk_vulkan_upload_glyph_op_draw (GskVulkanOp *op,
+                                 guchar      *data,
+                                 gsize        stride)
+{
+  GskVulkanUploadGlyphOp *self = (GskVulkanUploadGlyphOp *) op;
+  cairo_surface_t *surface;
+  cairo_t *cr;
+
+  surface = cairo_image_surface_create_for_data (data,
+                                                 CAIRO_FORMAT_ARGB32,
+                                                 self->area.width,
+                                                 self->area.height,
+                                                 stride);
+  cairo_surface_set_device_scale (surface, self->scale, self->scale);
+
+  cr = cairo_create (surface);
+
+  /* Make sure the entire surface is initialized to black */
+  cairo_set_source_rgba (cr, 0, 0, 0, 0);
+  cairo_rectangle (cr, 0.0, 0.0, self->area.width, self->area.height);
+  cairo_fill (cr);
+
+  /* Draw glyph */
+  cairo_set_source_rgba (cr, 1, 1, 1, 1);
+
+  pango_cairo_show_glyph_string (cr,
+                                 self->font,
+                                 &(PangoGlyphString) {
+                                   .num_glyphs = 1,
+                                   .glyphs = &self->glyph_info
+                                 });
+
+  cairo_destroy (cr);
+
+  cairo_surface_finish (surface);
+  cairo_surface_destroy (surface);
+}
+
+static GskVulkanOp *
+gsk_vulkan_upload_glyph_op_command (GskVulkanOp      *op,
+                                    GskVulkanRender  *render,
+                                    VkPipelineLayout  pipeline_layout,
+                                    VkCommandBuffer   command_buffer)
+{
+  GskVulkanUploadGlyphOp *self = (GskVulkanUploadGlyphOp *) op;
+
+  return gsk_vulkan_upload_op_command_with_area (op,
+                                                 render,
+                                                 pipeline_layout,
+                                                 command_buffer,
+                                                 self->image,
+                                                 &self->area,
+                                                 gsk_vulkan_upload_glyph_op_draw,
+                                                 &self->buffer);
+}
+
+static const GskVulkanOpClass GSK_VULKAN_UPLOAD_GLYPH_OP_CLASS = {
+  GSK_VULKAN_OP_SIZE (GskVulkanUploadGlyphOp),
+  GSK_VULKAN_STAGE_UPLOAD,
+  NULL,
+  NULL,
+  gsk_vulkan_upload_glyph_op_finish,
+  gsk_vulkan_upload_glyph_op_print,
+  gsk_vulkan_upload_op_upload,
+  gsk_vulkan_upload_op_count_vertex_data,
+  gsk_vulkan_upload_op_collect_vertex_data,
+  gsk_vulkan_upload_op_reserve_descriptor_sets,
+  gsk_vulkan_upload_glyph_op_command
+};
+
+void
+gsk_vulkan_upload_glyph_op (GskVulkanRender       *render,
+                            GskVulkanImage        *image,
+                            cairo_rectangle_int_t *area,
+                            PangoFont             *font,
+                            PangoGlyphInfo        *glyph_info,
+                            float                  scale)
+{
+  GskVulkanUploadGlyphOp *self;
+
+  self = (GskVulkanUploadGlyphOp *) gsk_vulkan_op_alloc (render, &GSK_VULKAN_UPLOAD_GLYPH_OP_CLASS);
+
+  self->image = g_object_ref (image);
+  self->area = *area;
+  self->font = g_object_ref (font);
+  self->glyph_info = *glyph_info;
+  self->scale = scale;
+}
index dbb1fcfb830242d7bc34bb464b7ff6f9c6441e0d..675337e0325c159abb02a3ea93814fe5ab29b131 100644 (file)
@@ -14,6 +14,12 @@ GskVulkanImage *        gsk_vulkan_upload_cairo_op                      (GskVulk
                                                                          const graphene_vec2_t          *scale,
                                                                          const graphene_rect_t          *viewport);
 
+void                    gsk_vulkan_upload_glyph_op                      (GskVulkanRender                *render,
+                                                                         GskVulkanImage                 *image,
+                                                                         cairo_rectangle_int_t          *area,
+                                                                         PangoFont                      *font,
+                                                                         PangoGlyphInfo                 *glyph_info,
+                                                                         float                           scale);
 
 G_END_DECLS