[gtk+/wip/matthiasc/text-node] Use vulkan images for text
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+/wip/matthiasc/text-node] Use vulkan images for text
- Date: Sun, 10 Sep 2017 14:06:08 +0000 (UTC)
commit 8b70b91a7607e50abec0217b33a913276c61a148
Author: Matthias Clasen <mclasen redhat com>
Date: Sun Sep 10 09:57:42 2017 -0400
Use vulkan images for text
We are still using a single texture for each
glyph string.
Along the way, we drop the surface from the text node
and return gsk_text_node_draw to the way it was initially,
directly drawing on the provided cairo_t.
gsk/gskrendernodeimpl.c | 122 +++++++++++++---------------------------
gsk/gskrendernodeprivate.h | 3 +-
gsk/gskvulkanrenderer.c | 12 +++-
gsk/gskvulkanrendererprivate.h | 4 +-
gsk/gskvulkanrenderpass.c | 24 ++++----
5 files changed, 62 insertions(+), 103 deletions(-)
---
diff --git a/gsk/gskrendernodeimpl.c b/gsk/gskrendernodeimpl.c
index fecc133..5ea2a13 100644
--- a/gsk/gskrendernodeimpl.c
+++ b/gsk/gskrendernodeimpl.c
@@ -3811,8 +3811,8 @@ struct _GskTextNode
{
GskRenderNode render_node;
+ PangoFont *font;
PangoGlyphString *glyphs;
- cairo_surface_t *surface;
GdkRGBA color;
gboolean has_color;
@@ -3827,8 +3827,8 @@ gsk_text_node_finalize (GskRenderNode *node)
{
GskTextNode *self = (GskTextNode *) node;
+ g_object_unref (self->font);
pango_glyph_string_free (self->glyphs);
- cairo_surface_destroy (self->surface);
}
#ifndef STACK_BUFFER_SIZE
@@ -3838,39 +3838,40 @@ gsk_text_node_finalize (GskRenderNode *node)
#define STACK_ARRAY_LENGTH(T) (STACK_BUFFER_SIZE / sizeof(T))
static void
-render_text (cairo_t *cr,
- PangoGlyphString *glyphs,
- PangoFont *font,
- double x,
- double y)
+gsk_text_node_draw (GskRenderNode *node,
+ cairo_t *cr)
{
+ GskTextNode *self = (GskTextNode *) node;
int i, count;
int x_position = 0;
cairo_scaled_font_t *scaled_font;
cairo_glyph_t *cairo_glyphs;
cairo_glyph_t stack_glyphs[STACK_ARRAY_LENGTH (cairo_glyph_t)];
- scaled_font = pango_cairo_font_get_scaled_font ((PangoCairoFont *)font);
+ scaled_font = pango_cairo_font_get_scaled_font ((PangoCairoFont *)self->font);
if (G_UNLIKELY (!scaled_font || cairo_scaled_font_status (scaled_font) != CAIRO_STATUS_SUCCESS))
return;
+ cairo_save (cr);
+
+ cairo_translate (cr, self->x, self->y);
cairo_set_scaled_font (cr, scaled_font);
- cairo_set_source_rgba (cr, 0, 0, 0, 1);
+ gdk_cairo_set_source_rgba (cr, &self->color);
- if (glyphs->num_glyphs > (int) G_N_ELEMENTS (stack_glyphs))
- cairo_glyphs = g_new (cairo_glyph_t, glyphs->num_glyphs);
+ if (self->glyphs->num_glyphs > (int) G_N_ELEMENTS (stack_glyphs))
+ cairo_glyphs = g_new (cairo_glyph_t, self->glyphs->num_glyphs);
else
cairo_glyphs = stack_glyphs;
count = 0;
- for (i = 0; i < glyphs->num_glyphs; i++)
+ for (i = 0; i < self->glyphs->num_glyphs; i++)
{
- PangoGlyphInfo *gi = &glyphs->glyphs[i];
+ PangoGlyphInfo *gi = &self->glyphs->glyphs[i];
if (gi->glyph != PANGO_GLYPH_EMPTY)
{
- double cx = x + (double)(x_position + gi->geometry.x_offset) / PANGO_SCALE;
- double cy = y + (double)(gi->geometry.y_offset) / PANGO_SCALE;
+ double cx = (double)(x_position + gi->geometry.x_offset) / PANGO_SCALE;
+ double cy = (double)(gi->geometry.y_offset) / PANGO_SCALE;
if (!(gi->glyph & PANGO_GLYPH_UNKNOWN_FLAG))
{
@@ -3887,6 +3888,8 @@ render_text (cairo_t *cr,
if (cairo_glyphs != stack_glyphs)
g_free (cairo_glyphs);
+
+ cairo_restore (cr);
}
/*
@@ -3897,56 +3900,6 @@ render_text (cairo_t *cr,
* - switch to using a font atlas instead of per-call cached surfaces
*/
-static void
-gsk_text_node_draw (GskRenderNode *node,
- cairo_t *cr)
-{
- GskTextNode *self = (GskTextNode *) node;
- int i;
- int x_position = 0;
-
- cairo_save (cr);
-
- cairo_translate (cr, self->x, self->y);
-
- gdk_cairo_set_source_rgba (cr, &self->color);
-
- for (i = 0; i < self->glyphs->num_glyphs; i++)
- {
- PangoGlyphInfo *gi = &self->glyphs->glyphs[i];
-
- if (gi->glyph != PANGO_GLYPH_EMPTY)
- {
- double cx = (double)(x_position + gi->geometry.x_offset) / PANGO_SCALE;
- double cy = (double)(gi->geometry.y_offset) / PANGO_SCALE;
-
- if (!(gi->glyph & PANGO_GLYPH_UNKNOWN_FLAG))
- {
- cairo_rectangle (cr, cx,
- cy + self->ink_rect_y,
- gi->geometry.width / PANGO_SCALE,
- self->ink_rect_height);
- cairo_clip (cr);
-
- cairo_move_to (cr, cx, cy + self->ink_rect_y);
- if (self->has_color)
- {
- cairo_set_source_surface (cr, self->surface, 0, self->ink_rect_y);
- cairo_paint (cr);
- }
- else
- {
- cairo_mask_surface (cr, self->surface, 0, self->ink_rect_y);
- }
- cairo_reset_clip (cr);
- }
- }
- x_position += gi->geometry.width;
- }
-
- cairo_restore (cr);
-}
-
static GVariant *
gsk_text_node_serialize (GskRenderNode *node)
{
@@ -3998,7 +3951,6 @@ gsk_text_node_new (PangoFont *font,
{
GskTextNode *self;
PangoRectangle ink_rect;
- cairo_t *cr;
pango_glyph_string_extents (glyphs, font, &ink_rect, NULL);
pango_extents_to_pixels (&ink_rect, NULL);
@@ -4009,6 +3961,7 @@ gsk_text_node_new (PangoFont *font,
self = (GskTextNode *) gsk_render_node_new (&GSK_TEXT_NODE_CLASS, 0);
+ self->font = g_object_ref (font);
self->glyphs = pango_glyph_string_copy (glyphs);
self->color = *color;
self->x = x;
@@ -4023,26 +3976,9 @@ gsk_text_node_new (PangoFont *font,
ink_rect.x + ink_rect.width,
ink_rect.height);
- self->surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
- ink_rect.x + ink_rect.width,
- ink_rect.height);
- cr = cairo_create (self->surface);
- render_text (cr, glyphs, font, 0, - ink_rect.y);
- cairo_destroy (cr);
-
return &self->render_node;
}
-cairo_surface_t *
-gsk_text_node_get_surface (GskRenderNode *node)
-{
- GskTextNode *self = (GskTextNode *) node;
-
- g_return_val_if_fail (GSK_IS_RENDER_NODE_TYPE (node, GSK_TEXT_NODE), NULL);
-
- return self->surface;
-}
-
gboolean
gsk_text_node_get_has_color (GskRenderNode *node)
{
@@ -4063,6 +3999,26 @@ gsk_text_node_get_color (GskRenderNode *node)
return &self->color;
}
+PangoFont *
+gsk_text_node_get_font (GskRenderNode *node)
+{
+ GskTextNode *self = (GskTextNode *) node;
+
+ g_return_val_if_fail (GSK_IS_RENDER_NODE_TYPE (node, GSK_TEXT_NODE), NULL);
+
+ return self->font;
+}
+
+PangoGlyphString *
+gsk_text_node_get_glyphs (GskRenderNode *node)
+{
+ GskTextNode *self = (GskTextNode *) node;
+
+ g_return_val_if_fail (GSK_IS_RENDER_NODE_TYPE (node, GSK_TEXT_NODE), NULL);
+
+ return self->glyphs;
+}
+
/*** GSK_BLUR_NODE ***/
typedef struct _GskBlurNode GskBlurNode;
diff --git a/gsk/gskrendernodeprivate.h b/gsk/gskrendernodeprivate.h
index f2fd507..008bdea 100644
--- a/gsk/gskrendernodeprivate.h
+++ b/gsk/gskrendernodeprivate.h
@@ -81,7 +81,8 @@ cairo_surface_t *gsk_cairo_node_get_surface (GskRenderNode *node);
GskTexture *gsk_texture_node_get_texture (GskRenderNode *node);
-cairo_surface_t *gsk_text_node_get_surface (GskRenderNode *node);
+PangoFont *gsk_text_node_get_font (GskRenderNode *node);
+PangoGlyphString *gsk_text_node_get_glyphs (GskRenderNode *node);
gboolean gsk_text_node_get_has_color (GskRenderNode *node);
const GdkRGBA *gsk_text_node_get_color (GskRenderNode *node);
diff --git a/gsk/gskvulkanrenderer.c b/gsk/gskvulkanrenderer.c
index f70935f..57262e6 100644
--- a/gsk/gskvulkanrenderer.c
+++ b/gsk/gskvulkanrenderer.c
@@ -418,14 +418,16 @@ GskVulkanImage *
gsk_vulkan_renderer_ref_glyph_image (GskVulkanRenderer *self,
GskVulkanUploader *uploader,
PangoFont *font,
- PangoGlyphString *glyphs,
- GskRectangle *glyph_rects,
- int *num_glyphs)
+ PangoGlyphString *glyphs)
{
PangoRectangle ink_rect;
cairo_surface_t *surface;
cairo_t *cr;
GskVulkanImage *image;
+ GskRectangle *glyph_rects;
+ int num_glyphs;
+
+ glyph_rects = g_new (GskRectangle, glyphs->num_glyphs);
pango_glyph_string_extents (glyphs, font, &ink_rect, NULL);
pango_extents_to_pixels (&ink_rect, NULL);
@@ -435,7 +437,7 @@ gsk_vulkan_renderer_ref_glyph_image (GskVulkanRenderer *self,
ink_rect.height);
cr = cairo_create (surface);
- render_text (cr, font, glyphs, glyph_rects, num_glyphs,
+ render_text (cr, font, glyphs, glyph_rects, &num_glyphs,
0, - ink_rect.y, ink_rect.x + ink_rect.width, ink_rect.height);
cairo_destroy (cr);
@@ -446,5 +448,7 @@ gsk_vulkan_renderer_ref_glyph_image (GskVulkanRenderer *self,
cairo_image_surface_get_stride (surface));
cairo_surface_destroy (surface);
+ g_free (glyph_rects); // FIXME: keep this around per-image
+
return image;
}
diff --git a/gsk/gskvulkanrendererprivate.h b/gsk/gskvulkanrendererprivate.h
index 6d06bc1..06fb1fb 100644
--- a/gsk/gskvulkanrendererprivate.h
+++ b/gsk/gskvulkanrendererprivate.h
@@ -32,9 +32,7 @@ typedef struct {
GskVulkanImage * gsk_vulkan_renderer_ref_glyph_image (GskVulkanRenderer *self,
GskVulkanUploader *uploader,
PangoFont *font,
- PangoGlyphString *glyphs,
- GskRectangle *glyph_rects,
- int *num_glyphs);
+ PangoGlyphString *glyphs);
G_END_DECLS
diff --git a/gsk/gskvulkanrenderpass.c b/gsk/gskvulkanrenderpass.c
index cb56fce..70e1f06 100644
--- a/gsk/gskvulkanrenderpass.c
+++ b/gsk/gskvulkanrenderpass.c
@@ -177,8 +177,6 @@ gsk_vulkan_render_pass_add_node (GskVulkanRenderPass *self,
return;
case GSK_TEXT_NODE:
- if (gsk_text_node_get_surface (node) == NULL)
- return;
if (gsk_text_node_get_has_color (node))
{
if (gsk_vulkan_clip_contains_rect (&constants->clip, &node->bounds))
@@ -448,10 +446,6 @@ gsk_vulkan_render_pass_get_node_as_texture (GskVulkanRenderPass *self,
surface = cairo_surface_reference (gsk_cairo_node_get_surface (node));
goto got_surface;
- case GSK_TEXT_NODE:
- surface = cairo_surface_reference (gsk_text_node_get_surface (node));
- goto got_surface;
-
default:
break;
}
@@ -566,15 +560,10 @@ gsk_vulkan_render_pass_upload (GskVulkanRenderPass *self,
break;
case GSK_VULKAN_OP_SURFACE:
- case GSK_VULKAN_OP_TEXT:
- case GSK_VULKAN_OP_COLOR_TEXT:
{
cairo_surface_t *surface;
- if (gsk_render_node_get_node_type (op->render.node) == GSK_CAIRO_NODE)
- surface = gsk_cairo_node_get_surface (op->render.node);
- else
- surface = gsk_text_node_get_surface (op->render.node);
+ surface = gsk_cairo_node_get_surface (op->render.node);
op->render.source = gsk_vulkan_image_new_from_data (uploader,
cairo_image_surface_get_data (surface),
cairo_image_surface_get_width (surface),
@@ -584,6 +573,17 @@ gsk_vulkan_render_pass_upload (GskVulkanRenderPass *self,
}
break;
+ case GSK_VULKAN_OP_TEXT:
+ case GSK_VULKAN_OP_COLOR_TEXT:
+ {
+ op->render.source = gsk_vulkan_renderer_ref_glyph_image (GSK_VULKAN_RENDERER
(gsk_vulkan_render_get_renderer (render)),
+ uploader,
+ gsk_text_node_get_font
(op->render.node),
+ gsk_text_node_get_glyphs
(op->render.node));
+ gsk_vulkan_render_add_cleanup_image (render, op->render.source);
+ }
+ break;
+
case GSK_VULKAN_OP_TEXTURE:
{
op->render.source = gsk_vulkan_renderer_ref_texture_image (GSK_VULKAN_RENDERER
(gsk_vulkan_render_get_renderer (render)),
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]