mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-09-19 21:40:22 +00:00
vulkan: Add an UploadGlyphOp
Now all the uploads have their own op.
This commit is contained in:
parent
68b337d457
commit
93db1cc89e
@ -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, ®ions[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)
|
||||
{
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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:
|
||||
*
|
||||
|
@ -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);
|
||||
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user