Compare commits
20 Commits
flatten-li
...
wip/matthi
Author | SHA1 | Date | |
---|---|---|---|
|
5e87f96aaf | ||
|
ffd2e620ba | ||
|
aec50193b0 | ||
|
2f46bd772e | ||
|
797042e616 | ||
|
ab00930bca | ||
|
8b70b91a76 | ||
|
b47fe87d61 | ||
|
63a1dc16ae | ||
|
f1a36a93cb | ||
|
e1adca7301 | ||
|
0152a4b309 | ||
|
e4b5835185 | ||
|
a6a3186bd7 | ||
|
40de42cff9 | ||
|
36001547f5 | ||
|
a87b120a2d | ||
|
fca1a9244e | ||
|
ae574b168a | ||
|
344bad9788 |
@@ -15,3 +15,23 @@ gsk_ensure_resources (void)
|
|||||||
|
|
||||||
g_once (®ister_resources_once, register_resources, NULL);
|
g_once (®ister_resources_once, register_resources, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
pango_glyph_string_num_glyphs (PangoGlyphString *glyphs)
|
||||||
|
{
|
||||||
|
int i, count;
|
||||||
|
|
||||||
|
count = 0;
|
||||||
|
for (i = 0; i < glyphs->num_glyphs; i++)
|
||||||
|
{
|
||||||
|
PangoGlyphInfo *gi = &glyphs->glyphs[i];
|
||||||
|
if (gi->glyph != PANGO_GLYPH_EMPTY)
|
||||||
|
{
|
||||||
|
if (!(gi->glyph & PANGO_GLYPH_UNKNOWN_FLAG))
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -2,11 +2,14 @@
|
|||||||
#define __GSK_PRIVATE_H__
|
#define __GSK_PRIVATE_H__
|
||||||
|
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
|
#include <pango/pango.h>
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
void gsk_ensure_resources (void);
|
void gsk_ensure_resources (void);
|
||||||
|
|
||||||
|
int pango_glyph_string_num_glyphs (PangoGlyphString *glyphs);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* __GSK_PRIVATE_H__ */
|
#endif /* __GSK_PRIVATE_H__ */
|
||||||
|
@@ -178,10 +178,8 @@ GDK_AVAILABLE_IN_3_92
|
|||||||
GskRenderNode * gsk_text_node_new (PangoFont *font,
|
GskRenderNode * gsk_text_node_new (PangoFont *font,
|
||||||
PangoGlyphString *glyphs,
|
PangoGlyphString *glyphs,
|
||||||
const GdkRGBA *color,
|
const GdkRGBA *color,
|
||||||
int x_offset,
|
double x,
|
||||||
int y_offset,
|
double y);
|
||||||
double base_x,
|
|
||||||
double base_y);
|
|
||||||
|
|
||||||
GDK_AVAILABLE_IN_3_92
|
GDK_AVAILABLE_IN_3_92
|
||||||
GskRenderNode * gsk_blur_node_new (GskRenderNode *child,
|
GskRenderNode * gsk_blur_node_new (GskRenderNode *child,
|
||||||
|
@@ -26,8 +26,6 @@
|
|||||||
#include "gskroundedrectprivate.h"
|
#include "gskroundedrectprivate.h"
|
||||||
#include "gsktextureprivate.h"
|
#include "gsktextureprivate.h"
|
||||||
|
|
||||||
#include <cairo-ft.h>
|
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
check_variant_type (GVariant *variant,
|
check_variant_type (GVariant *variant,
|
||||||
const char *type_string,
|
const char *type_string,
|
||||||
@@ -3812,13 +3810,13 @@ struct _GskTextNode
|
|||||||
GskRenderNode render_node;
|
GskRenderNode render_node;
|
||||||
|
|
||||||
PangoFont *font;
|
PangoFont *font;
|
||||||
gboolean has_color;
|
|
||||||
PangoGlyphString *glyphs;
|
PangoGlyphString *glyphs;
|
||||||
|
|
||||||
GdkRGBA color;
|
GdkRGBA color;
|
||||||
int x_offset;
|
double x;
|
||||||
int y_offset;
|
double y;
|
||||||
double base_x;
|
double ink_rect_y;
|
||||||
double base_y;
|
double ink_rect_height;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -3830,20 +3828,6 @@ gsk_text_node_finalize (GskRenderNode *node)
|
|||||||
pango_glyph_string_free (self->glyphs);
|
pango_glyph_string_free (self->glyphs);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
|
||||||
_pango_cairo_font_install (PangoFont *font,
|
|
||||||
cairo_t *cr)
|
|
||||||
{
|
|
||||||
cairo_scaled_font_t *scaled_font = pango_cairo_font_get_scaled_font ((PangoCairoFont *)font);
|
|
||||||
|
|
||||||
if (G_UNLIKELY (scaled_font == NULL || cairo_scaled_font_status (scaled_font) != CAIRO_STATUS_SUCCESS))
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
cairo_set_scaled_font (cr, scaled_font);
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef STACK_BUFFER_SIZE
|
#ifndef STACK_BUFFER_SIZE
|
||||||
#define STACK_BUFFER_SIZE (512 * sizeof (int))
|
#define STACK_BUFFER_SIZE (512 * sizeof (int))
|
||||||
#endif
|
#endif
|
||||||
@@ -3857,16 +3841,19 @@ gsk_text_node_draw (GskRenderNode *node,
|
|||||||
GskTextNode *self = (GskTextNode *) node;
|
GskTextNode *self = (GskTextNode *) node;
|
||||||
int i, count;
|
int i, count;
|
||||||
int x_position = 0;
|
int x_position = 0;
|
||||||
|
cairo_scaled_font_t *scaled_font;
|
||||||
cairo_glyph_t *cairo_glyphs;
|
cairo_glyph_t *cairo_glyphs;
|
||||||
cairo_glyph_t stack_glyphs[STACK_ARRAY_LENGTH (cairo_glyph_t)];
|
cairo_glyph_t stack_glyphs[STACK_ARRAY_LENGTH (cairo_glyph_t)];
|
||||||
|
|
||||||
|
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_save (cr);
|
||||||
|
|
||||||
cairo_translate (cr, self->x_offset, self->y_offset);
|
cairo_translate (cr, self->x, self->y);
|
||||||
|
cairo_set_scaled_font (cr, scaled_font);
|
||||||
gdk_cairo_set_source_rgba (cr, &self->color);
|
gdk_cairo_set_source_rgba (cr, &self->color);
|
||||||
if (!_pango_cairo_font_install (self->font, cr))
|
|
||||||
goto done;
|
|
||||||
|
|
||||||
if (self->glyphs->num_glyphs > (int) G_N_ELEMENTS (stack_glyphs))
|
if (self->glyphs->num_glyphs > (int) G_N_ELEMENTS (stack_glyphs))
|
||||||
cairo_glyphs = g_new (cairo_glyph_t, self->glyphs->num_glyphs);
|
cairo_glyphs = g_new (cairo_glyph_t, self->glyphs->num_glyphs);
|
||||||
@@ -3880,8 +3867,8 @@ gsk_text_node_draw (GskRenderNode *node,
|
|||||||
|
|
||||||
if (gi->glyph != PANGO_GLYPH_EMPTY)
|
if (gi->glyph != PANGO_GLYPH_EMPTY)
|
||||||
{
|
{
|
||||||
double cx = self->base_x + (double)(x_position + gi->geometry.x_offset) / PANGO_SCALE;
|
double cx = (double)(x_position + gi->geometry.x_offset) / PANGO_SCALE;
|
||||||
double cy = gi->geometry.y_offset == 0 ? self->base_y : self->base_y + (double)(gi->geometry.y_offset) / PANGO_SCALE;
|
double cy = (double)(gi->geometry.y_offset) / PANGO_SCALE;
|
||||||
|
|
||||||
if (!(gi->glyph & PANGO_GLYPH_UNKNOWN_FLAG))
|
if (!(gi->glyph & PANGO_GLYPH_UNKNOWN_FLAG))
|
||||||
{
|
{
|
||||||
@@ -3899,107 +3886,22 @@ gsk_text_node_draw (GskRenderNode *node,
|
|||||||
if (cairo_glyphs != stack_glyphs)
|
if (cairo_glyphs != stack_glyphs)
|
||||||
g_free (cairo_glyphs);
|
g_free (cairo_glyphs);
|
||||||
|
|
||||||
done:
|
|
||||||
cairo_restore (cr);
|
cairo_restore (cr);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define GSK_TEXT_NODE_VARIANT_TYPE "(sddddiidda(uiiii))"
|
|
||||||
|
|
||||||
static GVariant *
|
static GVariant *
|
||||||
gsk_text_node_serialize (GskRenderNode *node)
|
gsk_text_node_serialize (GskRenderNode *node)
|
||||||
{
|
{
|
||||||
GskTextNode *self = (GskTextNode *) node;
|
g_assert_not_reached ();
|
||||||
GVariant *v;
|
return NULL;
|
||||||
GVariantBuilder builder;
|
|
||||||
int i;
|
|
||||||
PangoFontDescription *desc;
|
|
||||||
char *s;
|
|
||||||
|
|
||||||
desc = pango_font_describe (self->font);
|
|
||||||
s = pango_font_description_to_string (desc);
|
|
||||||
for (i = 0; i < self->glyphs->num_glyphs; i++)
|
|
||||||
{
|
|
||||||
PangoGlyphInfo *glyph = &self->glyphs->glyphs[i];
|
|
||||||
g_variant_builder_add (&builder, "(uiiii)",
|
|
||||||
glyph->glyph,
|
|
||||||
glyph->geometry.width,
|
|
||||||
glyph->geometry.x_offset,
|
|
||||||
glyph->geometry.y_offset,
|
|
||||||
glyph->attr.is_cluster_start);
|
|
||||||
}
|
|
||||||
|
|
||||||
g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(uiiii)"));
|
|
||||||
v = g_variant_new (GSK_TEXT_NODE_VARIANT_TYPE,
|
|
||||||
s,
|
|
||||||
self->color.red,
|
|
||||||
self->color.green,
|
|
||||||
self->color.blue,
|
|
||||||
self->color.alpha,
|
|
||||||
self->x_offset,
|
|
||||||
self->y_offset,
|
|
||||||
self->base_x,
|
|
||||||
self->base_y,
|
|
||||||
&builder);
|
|
||||||
|
|
||||||
g_free (s);
|
|
||||||
pango_font_description_free (desc);
|
|
||||||
|
|
||||||
return v;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static GskRenderNode *
|
static GskRenderNode *
|
||||||
gsk_text_node_deserialize (GVariant *variant,
|
gsk_text_node_deserialize (GVariant *variant,
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
PangoFont *font;
|
g_assert_not_reached ();
|
||||||
PangoGlyphString *glyphs;
|
return NULL;
|
||||||
GVariantIter iter;
|
|
||||||
GskRenderNode *result;
|
|
||||||
PangoGlyphInfo glyph;
|
|
||||||
PangoFontDescription *desc;
|
|
||||||
PangoFontMap *fontmap;
|
|
||||||
PangoContext *context;
|
|
||||||
int cluster_start;
|
|
||||||
char *s;
|
|
||||||
GdkRGBA color;
|
|
||||||
int x_offset, y_offset;
|
|
||||||
double base_x, base_y;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (!check_variant_type (variant, GSK_TEXT_NODE_VARIANT_TYPE, error))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
g_variant_get (variant, "(&sddddiidda(uiiii))",
|
|
||||||
&color.red, &color.green, &color.blue, &color.alpha,
|
|
||||||
&x_offset, &y_offset,
|
|
||||||
&base_x, &base_y,
|
|
||||||
&s, &iter);
|
|
||||||
|
|
||||||
desc = pango_font_description_from_string (s);
|
|
||||||
fontmap = pango_cairo_font_map_get_default ();
|
|
||||||
context = pango_font_map_create_context (fontmap);
|
|
||||||
font = pango_font_map_load_font (fontmap, context, desc);
|
|
||||||
|
|
||||||
glyphs = pango_glyph_string_new ();
|
|
||||||
pango_glyph_string_set_size (glyphs, g_variant_iter_n_children (&iter));
|
|
||||||
i = 0;
|
|
||||||
while (g_variant_iter_next (&iter, "(uiiii)", &glyph.glyph, &glyph.geometry.width, &glyph.geometry.x_offset, &glyph.geometry.y_offset, &cluster_start))
|
|
||||||
{
|
|
||||||
glyph.attr.is_cluster_start = cluster_start;
|
|
||||||
glyphs->glyphs[i] = glyph;
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
result = gsk_text_node_new (font, glyphs, &color, /* FIXME: Avoid copying glyphs */
|
|
||||||
x_offset, y_offset,
|
|
||||||
base_x, base_y);
|
|
||||||
|
|
||||||
pango_glyph_string_free (glyphs);
|
|
||||||
pango_font_description_free (desc);
|
|
||||||
g_object_unref (context);
|
|
||||||
g_object_unref (font);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const GskRenderNodeClass GSK_TEXT_NODE_CLASS = {
|
static const GskRenderNodeClass GSK_TEXT_NODE_CLASS = {
|
||||||
@@ -4012,31 +3914,12 @@ static const GskRenderNodeClass GSK_TEXT_NODE_CLASS = {
|
|||||||
gsk_text_node_deserialize
|
gsk_text_node_deserialize
|
||||||
};
|
};
|
||||||
|
|
||||||
static gboolean
|
|
||||||
font_has_color_glyphs (PangoFont *font)
|
|
||||||
{
|
|
||||||
cairo_scaled_font_t *scaled_font;
|
|
||||||
gboolean has_color = FALSE;
|
|
||||||
|
|
||||||
scaled_font = pango_cairo_font_get_scaled_font ((PangoCairoFont *)font);
|
|
||||||
if (cairo_scaled_font_get_type (scaled_font) == CAIRO_FONT_TYPE_FT)
|
|
||||||
{
|
|
||||||
FT_Face ft_face = cairo_ft_scaled_font_lock_face (scaled_font);
|
|
||||||
has_color = (FT_HAS_COLOR (ft_face) != 0);
|
|
||||||
cairo_ft_scaled_font_unlock_face (scaled_font);
|
|
||||||
}
|
|
||||||
|
|
||||||
return has_color;
|
|
||||||
}
|
|
||||||
|
|
||||||
GskRenderNode *
|
GskRenderNode *
|
||||||
gsk_text_node_new (PangoFont *font,
|
gsk_text_node_new (PangoFont *font,
|
||||||
PangoGlyphString *glyphs,
|
PangoGlyphString *glyphs,
|
||||||
const GdkRGBA *color,
|
const GdkRGBA *color,
|
||||||
int x_offset,
|
double x,
|
||||||
int y_offset,
|
double y)
|
||||||
double base_x,
|
|
||||||
double base_y)
|
|
||||||
{
|
{
|
||||||
GskTextNode *self;
|
GskTextNode *self;
|
||||||
PangoRectangle ink_rect;
|
PangoRectangle ink_rect;
|
||||||
@@ -4053,23 +3936,70 @@ gsk_text_node_new (PangoFont *font,
|
|||||||
self->font = g_object_ref (font);
|
self->font = g_object_ref (font);
|
||||||
self->glyphs = pango_glyph_string_copy (glyphs);
|
self->glyphs = pango_glyph_string_copy (glyphs);
|
||||||
self->color = *color;
|
self->color = *color;
|
||||||
self->x_offset = x_offset;
|
self->x = x;
|
||||||
self->y_offset = y_offset;
|
self->y = y;
|
||||||
self->base_x = base_x;
|
self->ink_rect_y = ink_rect.y;
|
||||||
self->base_y = base_y;
|
self->ink_rect_height = ink_rect.height;
|
||||||
|
|
||||||
self->has_color = font_has_color_glyphs (font);
|
|
||||||
|
|
||||||
|
|
||||||
graphene_rect_init (&self->render_node.bounds,
|
graphene_rect_init (&self->render_node.bounds,
|
||||||
x_offset + base_x + ink_rect.x,
|
x,
|
||||||
y_offset + base_y + ink_rect.y,
|
y + ink_rect.y,
|
||||||
ink_rect.width,
|
ink_rect.x + ink_rect.width,
|
||||||
ink_rect.height);
|
ink_rect.height);
|
||||||
|
|
||||||
return &self->render_node;
|
return &self->render_node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const GdkRGBA *
|
||||||
|
gsk_text_node_get_color (GskRenderNode *node)
|
||||||
|
{
|
||||||
|
GskTextNode *self = (GskTextNode *) node;
|
||||||
|
|
||||||
|
g_return_val_if_fail (GSK_IS_RENDER_NODE_TYPE (node, GSK_TEXT_NODE), NULL);
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
float
|
||||||
|
gsk_text_node_get_x (GskRenderNode *node)
|
||||||
|
{
|
||||||
|
GskTextNode *self = (GskTextNode *) node;
|
||||||
|
|
||||||
|
g_return_val_if_fail (GSK_IS_RENDER_NODE_TYPE (node, GSK_TEXT_NODE), 0.0);
|
||||||
|
|
||||||
|
return (float)self->x;
|
||||||
|
}
|
||||||
|
|
||||||
|
float
|
||||||
|
gsk_text_node_get_y (GskRenderNode *node)
|
||||||
|
{
|
||||||
|
GskTextNode *self = (GskTextNode *) node;
|
||||||
|
|
||||||
|
g_return_val_if_fail (GSK_IS_RENDER_NODE_TYPE (node, GSK_TEXT_NODE), 0.0);
|
||||||
|
|
||||||
|
return (float)self->y;
|
||||||
|
}
|
||||||
|
|
||||||
/*** GSK_BLUR_NODE ***/
|
/*** GSK_BLUR_NODE ***/
|
||||||
|
|
||||||
typedef struct _GskBlurNode GskBlurNode;
|
typedef struct _GskBlurNode GskBlurNode;
|
||||||
|
@@ -81,6 +81,12 @@ cairo_surface_t *gsk_cairo_node_get_surface (GskRenderNode *node);
|
|||||||
|
|
||||||
GskTexture *gsk_texture_node_get_texture (GskRenderNode *node);
|
GskTexture *gsk_texture_node_get_texture (GskRenderNode *node);
|
||||||
|
|
||||||
|
PangoFont *gsk_text_node_get_font (GskRenderNode *node);
|
||||||
|
PangoGlyphString *gsk_text_node_get_glyphs (GskRenderNode *node);
|
||||||
|
const GdkRGBA *gsk_text_node_get_color (GskRenderNode *node);
|
||||||
|
float gsk_text_node_get_x (GskRenderNode *node);
|
||||||
|
float gsk_text_node_get_y (GskRenderNode *node);
|
||||||
|
|
||||||
const GdkRGBA *gsk_color_node_peek_color (GskRenderNode *node);
|
const GdkRGBA *gsk_color_node_peek_color (GskRenderNode *node);
|
||||||
|
|
||||||
const graphene_rect_t * gsk_clip_node_peek_clip (GskRenderNode *node);
|
const graphene_rect_t * gsk_clip_node_peek_clip (GskRenderNode *node);
|
||||||
|
156
gsk/gskvulkancolortextpipeline.c
Normal file
156
gsk/gskvulkancolortextpipeline.c
Normal file
@@ -0,0 +1,156 @@
|
|||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "gskvulkancolortextpipelineprivate.h"
|
||||||
|
|
||||||
|
struct _GskVulkanColorTextPipeline
|
||||||
|
{
|
||||||
|
GObject parent_instance;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct _GskVulkanColorTextInstance GskVulkanColorTextInstance;
|
||||||
|
|
||||||
|
struct _GskVulkanColorTextInstance
|
||||||
|
{
|
||||||
|
float rect[4];
|
||||||
|
float tex_rect[4];
|
||||||
|
};
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (GskVulkanColorTextPipeline, gsk_vulkan_color_text_pipeline, GSK_TYPE_VULKAN_PIPELINE)
|
||||||
|
|
||||||
|
static const VkPipelineVertexInputStateCreateInfo *
|
||||||
|
gsk_vulkan_color_text_pipeline_get_input_state_create_info (GskVulkanPipeline *self)
|
||||||
|
{
|
||||||
|
static const VkVertexInputBindingDescription vertexBindingDescriptions[] = {
|
||||||
|
{
|
||||||
|
.binding = 0,
|
||||||
|
.stride = sizeof (GskVulkanColorTextInstance),
|
||||||
|
.inputRate = VK_VERTEX_INPUT_RATE_INSTANCE
|
||||||
|
}
|
||||||
|
};
|
||||||
|
static const VkVertexInputAttributeDescription vertexInputAttributeDescription[] = {
|
||||||
|
{
|
||||||
|
.location = 0,
|
||||||
|
.binding = 0,
|
||||||
|
.format = VK_FORMAT_R32G32B32A32_SFLOAT,
|
||||||
|
.offset = G_STRUCT_OFFSET (GskVulkanColorTextInstance, rect),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.location = 1,
|
||||||
|
.binding = 0,
|
||||||
|
.format = VK_FORMAT_R32G32B32A32_SFLOAT,
|
||||||
|
.offset = G_STRUCT_OFFSET (GskVulkanColorTextInstance, tex_rect),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
static const VkPipelineVertexInputStateCreateInfo info = {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
|
||||||
|
.vertexBindingDescriptionCount = G_N_ELEMENTS (vertexBindingDescriptions),
|
||||||
|
.pVertexBindingDescriptions = vertexBindingDescriptions,
|
||||||
|
.vertexAttributeDescriptionCount = G_N_ELEMENTS (vertexInputAttributeDescription),
|
||||||
|
.pVertexAttributeDescriptions = vertexInputAttributeDescription
|
||||||
|
};
|
||||||
|
|
||||||
|
return &info;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gsk_vulkan_color_text_pipeline_finalize (GObject *gobject)
|
||||||
|
{
|
||||||
|
//GskVulkanColorTextPipeline *self = GSK_VULKAN_COLOR_TEXT_PIPELINE (gobject);
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (gsk_vulkan_color_text_pipeline_parent_class)->finalize (gobject);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gsk_vulkan_color_text_pipeline_class_init (GskVulkanColorTextPipelineClass *klass)
|
||||||
|
{
|
||||||
|
GskVulkanPipelineClass *pipeline_class = GSK_VULKAN_PIPELINE_CLASS (klass);
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (klass)->finalize = gsk_vulkan_color_text_pipeline_finalize;
|
||||||
|
|
||||||
|
pipeline_class->get_input_state_create_info = gsk_vulkan_color_text_pipeline_get_input_state_create_info;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gsk_vulkan_color_text_pipeline_init (GskVulkanColorTextPipeline *self)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
GskVulkanPipeline *
|
||||||
|
gsk_vulkan_color_text_pipeline_new (GskVulkanPipelineLayout *layout,
|
||||||
|
const char *shader_name,
|
||||||
|
VkRenderPass render_pass)
|
||||||
|
{
|
||||||
|
return gsk_vulkan_pipeline_new_full (GSK_TYPE_VULKAN_COLOR_TEXT_PIPELINE, layout, shader_name, render_pass,
|
||||||
|
VK_BLEND_FACTOR_SRC_ALPHA, VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA);
|
||||||
|
}
|
||||||
|
|
||||||
|
gsize
|
||||||
|
gsk_vulkan_color_text_pipeline_count_vertex_data (GskVulkanColorTextPipeline *pipeline,
|
||||||
|
int num_instances)
|
||||||
|
{
|
||||||
|
return sizeof (GskVulkanColorTextInstance) * num_instances;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gsk_vulkan_color_text_pipeline_collect_vertex_data (GskVulkanColorTextPipeline *pipeline,
|
||||||
|
guchar *data,
|
||||||
|
GskVulkanRenderer *renderer,
|
||||||
|
const graphene_rect_t *rect,
|
||||||
|
PangoFont *font,
|
||||||
|
PangoGlyphString *glyphs,
|
||||||
|
float x,
|
||||||
|
float y)
|
||||||
|
{
|
||||||
|
GskVulkanColorTextInstance *instances = (GskVulkanColorTextInstance *) data;
|
||||||
|
int i, count;
|
||||||
|
int x_position = 0;
|
||||||
|
float ink_rect_y;
|
||||||
|
float ink_rect_height;
|
||||||
|
|
||||||
|
/* XXX */
|
||||||
|
ink_rect_y = rect->origin.y - y;
|
||||||
|
ink_rect_height = rect->size.height;
|
||||||
|
|
||||||
|
count = 0;
|
||||||
|
for (i = 0; i < glyphs->num_glyphs; i++)
|
||||||
|
{
|
||||||
|
PangoGlyphInfo *gi = &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))
|
||||||
|
{
|
||||||
|
GskVulkanColorTextInstance *instance = &instances[count];
|
||||||
|
|
||||||
|
instance->rect[0] = x + cx;
|
||||||
|
instance->rect[1] = y + ink_rect_y + cy;
|
||||||
|
instance->rect[2] = (float)gi->geometry.width / PANGO_SCALE;
|
||||||
|
instance->rect[3] = ink_rect_height;
|
||||||
|
gsk_vulkan_renderer_get_glyph_coords (renderer, font, glyphs,
|
||||||
|
gi->glyph,
|
||||||
|
&instance->tex_rect[0],
|
||||||
|
&instance->tex_rect[1],
|
||||||
|
&instance->tex_rect[2],
|
||||||
|
&instance->tex_rect[3]);
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
x_position += gi->geometry.width;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gsize
|
||||||
|
gsk_vulkan_color_text_pipeline_draw (GskVulkanColorTextPipeline *pipeline,
|
||||||
|
VkCommandBuffer command_buffer,
|
||||||
|
gsize offset,
|
||||||
|
gsize n_commands)
|
||||||
|
{
|
||||||
|
vkCmdDraw (command_buffer,
|
||||||
|
6, n_commands,
|
||||||
|
0, offset);
|
||||||
|
|
||||||
|
return n_commands;
|
||||||
|
}
|
38
gsk/gskvulkancolortextpipelineprivate.h
Normal file
38
gsk/gskvulkancolortextpipelineprivate.h
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
#ifndef __GSK_VULKAN_COLOR_TEXT_PIPELINE_PRIVATE_H__
|
||||||
|
#define __GSK_VULKAN_COLOR_TEXT_PIPELINE_PRIVATE_H__
|
||||||
|
|
||||||
|
#include <graphene.h>
|
||||||
|
|
||||||
|
#include "gskvulkanpipelineprivate.h"
|
||||||
|
#include "gskvulkanrendererprivate.h"
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
typedef struct _GskVulkanColorTextPipelineLayout GskVulkanColorTextPipelineLayout;
|
||||||
|
|
||||||
|
#define GSK_TYPE_VULKAN_COLOR_TEXT_PIPELINE (gsk_vulkan_color_text_pipeline_get_type ())
|
||||||
|
|
||||||
|
G_DECLARE_FINAL_TYPE (GskVulkanColorTextPipeline, gsk_vulkan_color_text_pipeline, GSK, VULKAN_COLOR_TEXT_PIPELINE, GskVulkanPipeline)
|
||||||
|
|
||||||
|
GskVulkanPipeline * gsk_vulkan_color_text_pipeline_new (GskVulkanPipelineLayout *layout,
|
||||||
|
const char *shader_name,
|
||||||
|
VkRenderPass render_pass);
|
||||||
|
|
||||||
|
gsize gsk_vulkan_color_text_pipeline_count_vertex_data (GskVulkanColorTextPipeline *pipeline,
|
||||||
|
int num_instances);
|
||||||
|
void gsk_vulkan_color_text_pipeline_collect_vertex_data (GskVulkanColorTextPipeline *pipeline,
|
||||||
|
guchar *data,
|
||||||
|
GskVulkanRenderer *renderer,
|
||||||
|
const graphene_rect_t *rect,
|
||||||
|
PangoFont *font,
|
||||||
|
PangoGlyphString *glyphs,
|
||||||
|
float x,
|
||||||
|
float y);
|
||||||
|
gsize gsk_vulkan_color_text_pipeline_draw (GskVulkanColorTextPipeline *pipeline,
|
||||||
|
VkCommandBuffer command_buffer,
|
||||||
|
gsize offset,
|
||||||
|
gsize n_commands);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __GSK_VULKAN_COLOR_TEXT_PIPELINE_PRIVATE_H__ */
|
@@ -67,6 +67,19 @@ gsk_vulkan_pipeline_new (GType pipeline_type,
|
|||||||
GskVulkanPipelineLayout *layout,
|
GskVulkanPipelineLayout *layout,
|
||||||
const char *shader_name,
|
const char *shader_name,
|
||||||
VkRenderPass render_pass)
|
VkRenderPass render_pass)
|
||||||
|
{
|
||||||
|
return gsk_vulkan_pipeline_new_full (pipeline_type, layout, shader_name, render_pass,
|
||||||
|
VK_BLEND_FACTOR_ONE,
|
||||||
|
VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA);
|
||||||
|
}
|
||||||
|
|
||||||
|
GskVulkanPipeline *
|
||||||
|
gsk_vulkan_pipeline_new_full (GType pipeline_type,
|
||||||
|
GskVulkanPipelineLayout *layout,
|
||||||
|
const char *shader_name,
|
||||||
|
VkRenderPass render_pass,
|
||||||
|
VkBlendFactor srcBlendFactor,
|
||||||
|
VkBlendFactor dstBlendFactor)
|
||||||
{
|
{
|
||||||
GskVulkanPipelinePrivate *priv;
|
GskVulkanPipelinePrivate *priv;
|
||||||
GskVulkanPipeline *self;
|
GskVulkanPipeline *self;
|
||||||
@@ -134,11 +147,11 @@ gsk_vulkan_pipeline_new (GType pipeline_type,
|
|||||||
{
|
{
|
||||||
.blendEnable = VK_TRUE,
|
.blendEnable = VK_TRUE,
|
||||||
.colorBlendOp = VK_BLEND_OP_ADD,
|
.colorBlendOp = VK_BLEND_OP_ADD,
|
||||||
.srcColorBlendFactor = VK_BLEND_FACTOR_ONE,
|
.srcColorBlendFactor = srcBlendFactor,
|
||||||
.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
|
.dstColorBlendFactor = dstBlendFactor,
|
||||||
.alphaBlendOp = VK_BLEND_OP_ADD,
|
.alphaBlendOp = VK_BLEND_OP_ADD,
|
||||||
.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE,
|
.srcAlphaBlendFactor = srcBlendFactor,
|
||||||
.dstAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
|
.dstAlphaBlendFactor = dstBlendFactor,
|
||||||
.colorWriteMask = VK_COLOR_COMPONENT_A_BIT
|
.colorWriteMask = VK_COLOR_COMPONENT_A_BIT
|
||||||
| VK_COLOR_COMPONENT_R_BIT
|
| VK_COLOR_COMPONENT_R_BIT
|
||||||
| VK_COLOR_COMPONENT_G_BIT
|
| VK_COLOR_COMPONENT_G_BIT
|
||||||
|
@@ -48,6 +48,12 @@ GskVulkanPipeline * gsk_vulkan_pipeline_new (GType
|
|||||||
GskVulkanPipelineLayout *layout,
|
GskVulkanPipelineLayout *layout,
|
||||||
const char *shader_name,
|
const char *shader_name,
|
||||||
VkRenderPass render_pass);
|
VkRenderPass render_pass);
|
||||||
|
GskVulkanPipeline * gsk_vulkan_pipeline_new_full (GType pipeline_type,
|
||||||
|
GskVulkanPipelineLayout *layout,
|
||||||
|
const char *shader_name,
|
||||||
|
VkRenderPass render_pass,
|
||||||
|
VkBlendFactor srcBlendFactor,
|
||||||
|
VkBlendFactor dstBlendFactor);
|
||||||
|
|
||||||
VkPipeline gsk_vulkan_pipeline_get_pipeline (GskVulkanPipeline *self);
|
VkPipeline gsk_vulkan_pipeline_get_pipeline (GskVulkanPipeline *self);
|
||||||
|
|
||||||
|
@@ -15,8 +15,10 @@
|
|||||||
#include "gskvulkanborderpipelineprivate.h"
|
#include "gskvulkanborderpipelineprivate.h"
|
||||||
#include "gskvulkanboxshadowpipelineprivate.h"
|
#include "gskvulkanboxshadowpipelineprivate.h"
|
||||||
#include "gskvulkancolorpipelineprivate.h"
|
#include "gskvulkancolorpipelineprivate.h"
|
||||||
|
#include "gskvulkancolortextpipelineprivate.h"
|
||||||
#include "gskvulkaneffectpipelineprivate.h"
|
#include "gskvulkaneffectpipelineprivate.h"
|
||||||
#include "gskvulkanlineargradientpipelineprivate.h"
|
#include "gskvulkanlineargradientpipelineprivate.h"
|
||||||
|
#include "gskvulkantextpipelineprivate.h"
|
||||||
|
|
||||||
#define ORTHO_NEAR_PLANE -10000
|
#define ORTHO_NEAR_PLANE -10000
|
||||||
#define ORTHO_FAR_PLANE 10000
|
#define ORTHO_FAR_PLANE 10000
|
||||||
@@ -303,7 +305,7 @@ gsk_vulkan_render_collect_vertex_data (GskVulkanRender *self)
|
|||||||
|
|
||||||
for (l = self->render_passes; l; l = l->next)
|
for (l = self->render_passes; l; l = l->next)
|
||||||
{
|
{
|
||||||
offset += gsk_vulkan_render_pass_collect_vertex_data (l->data, data, offset, n_bytes - offset);
|
offset += gsk_vulkan_render_pass_collect_vertex_data (l->data, self, data, offset, n_bytes - offset);
|
||||||
g_assert (offset <= n_bytes);
|
g_assert (offset <= n_bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -344,6 +346,12 @@ gsk_vulkan_render_get_pipeline (GskVulkanRender *self,
|
|||||||
{ "blur", gsk_vulkan_blur_pipeline_new },
|
{ "blur", gsk_vulkan_blur_pipeline_new },
|
||||||
{ "blur-clip", gsk_vulkan_blur_pipeline_new },
|
{ "blur-clip", gsk_vulkan_blur_pipeline_new },
|
||||||
{ "blur-clip-rounded", gsk_vulkan_blur_pipeline_new },
|
{ "blur-clip-rounded", gsk_vulkan_blur_pipeline_new },
|
||||||
|
{ "mask", gsk_vulkan_text_pipeline_new },
|
||||||
|
{ "mask-clip", gsk_vulkan_text_pipeline_new },
|
||||||
|
{ "mask-clip-rounded", gsk_vulkan_text_pipeline_new },
|
||||||
|
{ "blend", gsk_vulkan_color_text_pipeline_new },
|
||||||
|
{ "blend-clip", gsk_vulkan_color_text_pipeline_new },
|
||||||
|
{ "blend-clip-rounded", gsk_vulkan_color_text_pipeline_new },
|
||||||
};
|
};
|
||||||
|
|
||||||
g_return_val_if_fail (type < GSK_VULKAN_N_PIPELINES, NULL);
|
g_return_val_if_fail (type < GSK_VULKAN_N_PIPELINES, NULL);
|
||||||
|
@@ -44,6 +44,8 @@ struct _GskVulkanRenderer
|
|||||||
|
|
||||||
GSList *textures;
|
GSList *textures;
|
||||||
|
|
||||||
|
GHashTable *glyph_cache;
|
||||||
|
|
||||||
#ifdef G_ENABLE_DEBUG
|
#ifdef G_ENABLE_DEBUG
|
||||||
ProfileTimers profile_timers;
|
ProfileTimers profile_timers;
|
||||||
#endif
|
#endif
|
||||||
@@ -343,3 +345,271 @@ gsk_vulkan_renderer_ref_texture_image (GskVulkanRenderer *self,
|
|||||||
|
|
||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef STACK_BUFFER_SIZE
|
||||||
|
#define STACK_BUFFER_SIZE (512 * sizeof (int))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define STACK_ARRAY_LENGTH(T) (STACK_BUFFER_SIZE / sizeof(T))
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
PangoGlyph glyph;
|
||||||
|
float x, y, width, height;
|
||||||
|
} GlyphCoords;
|
||||||
|
|
||||||
|
static void
|
||||||
|
render_text (cairo_t *cr,
|
||||||
|
PangoFont *font,
|
||||||
|
PangoGlyphString *glyphs,
|
||||||
|
GlyphCoords *coords,
|
||||||
|
int *num_coords,
|
||||||
|
float x,
|
||||||
|
float y,
|
||||||
|
float width,
|
||||||
|
float height)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
if (G_UNLIKELY (!scaled_font || cairo_scaled_font_status (scaled_font) != CAIRO_STATUS_SUCCESS))
|
||||||
|
return;
|
||||||
|
|
||||||
|
cairo_set_scaled_font (cr, scaled_font);
|
||||||
|
cairo_set_source_rgba (cr, 0, 0, 0, 1);
|
||||||
|
|
||||||
|
if (glyphs->num_glyphs > (int) G_N_ELEMENTS (stack_glyphs))
|
||||||
|
cairo_glyphs = g_new (cairo_glyph_t, glyphs->num_glyphs);
|
||||||
|
else
|
||||||
|
cairo_glyphs = stack_glyphs;
|
||||||
|
|
||||||
|
count = 0;
|
||||||
|
for (i = 0; i < glyphs->num_glyphs; i++)
|
||||||
|
{
|
||||||
|
PangoGlyphInfo *gi = &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;
|
||||||
|
|
||||||
|
if (!(gi->glyph & PANGO_GLYPH_UNKNOWN_FLAG))
|
||||||
|
{
|
||||||
|
cairo_glyphs[count].index = gi->glyph;
|
||||||
|
cairo_glyphs[count].x = cx;
|
||||||
|
cairo_glyphs[count].y = cy;
|
||||||
|
|
||||||
|
coords[count].glyph = gi->glyph;
|
||||||
|
coords[count].x = cx / width;
|
||||||
|
coords[count].y = 0.0;
|
||||||
|
coords[count].width = (float)gi->geometry.width / (PANGO_SCALE * width);
|
||||||
|
coords[count].height = 1.0; // FIXME get actual glyph height
|
||||||
|
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
x_position += gi->geometry.width;
|
||||||
|
}
|
||||||
|
|
||||||
|
*num_coords = count;
|
||||||
|
|
||||||
|
cairo_show_glyphs (cr, cairo_glyphs, count);
|
||||||
|
|
||||||
|
if (cairo_glyphs != stack_glyphs)
|
||||||
|
g_free (cairo_glyphs);
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
PangoFont *font;
|
||||||
|
PangoGlyphString *glyphs;
|
||||||
|
guint hash;
|
||||||
|
GlyphCoords *coords;
|
||||||
|
int num_coords;
|
||||||
|
} CacheItem;
|
||||||
|
|
||||||
|
static guint
|
||||||
|
item_hash (gconstpointer key)
|
||||||
|
{
|
||||||
|
const CacheItem *item = key;
|
||||||
|
PangoFontDescription *desc;
|
||||||
|
guint32 h = 5381;
|
||||||
|
char *p, *end;
|
||||||
|
|
||||||
|
if (item->hash != 0)
|
||||||
|
return item->hash;
|
||||||
|
|
||||||
|
end = ((char *)&item->glyphs->glyphs[item->glyphs->num_glyphs]);
|
||||||
|
for (p = (char *)item->glyphs->glyphs; p < end; p++)
|
||||||
|
h = (h << 5) + h + *p;
|
||||||
|
|
||||||
|
desc = pango_font_describe (item->font);
|
||||||
|
h ^= pango_font_description_hash (desc);
|
||||||
|
pango_font_description_free (desc);
|
||||||
|
|
||||||
|
if (h == 0)
|
||||||
|
h = 1;
|
||||||
|
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
item_equal (gconstpointer v1, gconstpointer v2)
|
||||||
|
{
|
||||||
|
const CacheItem *i1 = v1;
|
||||||
|
const CacheItem *i2 = v2;
|
||||||
|
int i;
|
||||||
|
PangoFontDescription *desc1, *desc2;
|
||||||
|
gboolean ret;
|
||||||
|
|
||||||
|
if (i1->glyphs->num_glyphs != i2->glyphs->num_glyphs)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
for (i = 0; i < i1->glyphs->num_glyphs; i++)
|
||||||
|
{
|
||||||
|
if (i1->glyphs->glyphs[i].glyph != i2->glyphs->glyphs[i].glyph)
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
desc1 = pango_font_describe (i1->font);
|
||||||
|
desc2 = pango_font_describe (i2->font);
|
||||||
|
ret = pango_font_description_equal (desc1, desc2);
|
||||||
|
pango_font_description_free (desc1);
|
||||||
|
pango_font_description_free (desc2);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
item_free (gpointer data)
|
||||||
|
{
|
||||||
|
CacheItem *item = data;
|
||||||
|
|
||||||
|
g_object_unref (item->font);
|
||||||
|
pango_glyph_string_free (item->glyphs);
|
||||||
|
g_free (item->coords);
|
||||||
|
g_free (item);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
ensure_cache (GskVulkanRenderer *renderer)
|
||||||
|
{
|
||||||
|
if (!renderer->glyph_cache)
|
||||||
|
renderer->glyph_cache = g_hash_table_new_full (item_hash, item_equal, NULL, item_free);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
find_cached_item (GskVulkanRenderer *renderer, PangoFont *font, PangoGlyphString *glyphs, GlyphCoords **coords)
|
||||||
|
{
|
||||||
|
CacheItem key;
|
||||||
|
CacheItem *value;
|
||||||
|
|
||||||
|
key.font = font;
|
||||||
|
key.glyphs = glyphs;
|
||||||
|
key.hash = 0;
|
||||||
|
key.coords = NULL;
|
||||||
|
key.num_coords = 0;
|
||||||
|
|
||||||
|
ensure_cache (renderer);
|
||||||
|
|
||||||
|
value = g_hash_table_lookup (renderer->glyph_cache, &key);
|
||||||
|
if (value)
|
||||||
|
{
|
||||||
|
*coords = value->coords;
|
||||||
|
return value->num_coords;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
cache_item (GskVulkanRenderer *renderer, PangoFont *font, PangoGlyphString *glyphs, GlyphCoords *coords, int num_coords)
|
||||||
|
{
|
||||||
|
CacheItem *item;
|
||||||
|
|
||||||
|
item = g_new (CacheItem, 1);
|
||||||
|
|
||||||
|
item->font = g_object_ref (font);
|
||||||
|
item->glyphs = pango_glyph_string_copy (glyphs);
|
||||||
|
item->hash = 0;
|
||||||
|
item->coords = coords;
|
||||||
|
item->num_coords = num_coords;
|
||||||
|
|
||||||
|
ensure_cache (renderer);
|
||||||
|
|
||||||
|
g_hash_table_add (renderer->glyph_cache, item);
|
||||||
|
}
|
||||||
|
|
||||||
|
GskVulkanImage *
|
||||||
|
gsk_vulkan_renderer_ref_glyph_image (GskVulkanRenderer *self,
|
||||||
|
GskVulkanUploader *uploader,
|
||||||
|
PangoFont *font,
|
||||||
|
PangoGlyphString *glyphs)
|
||||||
|
{
|
||||||
|
PangoRectangle ink_rect;
|
||||||
|
cairo_surface_t *surface;
|
||||||
|
cairo_t *cr;
|
||||||
|
GskVulkanImage *image;
|
||||||
|
GlyphCoords *coords;
|
||||||
|
int num_coords;
|
||||||
|
|
||||||
|
coords = g_new0 (GlyphCoords, glyphs->num_glyphs);
|
||||||
|
|
||||||
|
pango_glyph_string_extents (glyphs, font, &ink_rect, NULL);
|
||||||
|
pango_extents_to_pixels (&ink_rect, NULL);
|
||||||
|
|
||||||
|
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
|
||||||
|
ink_rect.x + ink_rect.width,
|
||||||
|
ink_rect.height);
|
||||||
|
|
||||||
|
cr = cairo_create (surface);
|
||||||
|
render_text (cr, font, glyphs, coords, &num_coords,
|
||||||
|
0, - ink_rect.y, ink_rect.x + ink_rect.width, ink_rect.height);
|
||||||
|
cairo_destroy (cr);
|
||||||
|
|
||||||
|
image = gsk_vulkan_image_new_from_data (uploader,
|
||||||
|
cairo_image_surface_get_data (surface),
|
||||||
|
cairo_image_surface_get_width (surface),
|
||||||
|
cairo_image_surface_get_height (surface),
|
||||||
|
cairo_image_surface_get_stride (surface));
|
||||||
|
cairo_surface_destroy (surface);
|
||||||
|
|
||||||
|
cache_item (self, font, glyphs, coords, num_coords);
|
||||||
|
|
||||||
|
return image;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gsk_vulkan_renderer_get_glyph_coords (GskVulkanRenderer *self,
|
||||||
|
PangoFont *font,
|
||||||
|
PangoGlyphString *glyphs,
|
||||||
|
PangoGlyph glyph,
|
||||||
|
float *x,
|
||||||
|
float *y,
|
||||||
|
float *width,
|
||||||
|
float *height)
|
||||||
|
{
|
||||||
|
GlyphCoords *coords;
|
||||||
|
int num_coords;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
*x = 0.0;
|
||||||
|
*y = 0.0;
|
||||||
|
*width = 1.0;
|
||||||
|
*height = 1.0;
|
||||||
|
|
||||||
|
num_coords = find_cached_item (self, font, glyphs, &coords);
|
||||||
|
for (i = 0; i < num_coords; i++)
|
||||||
|
{
|
||||||
|
if (coords[i].glyph == glyph)
|
||||||
|
{
|
||||||
|
*x = coords[i].x;
|
||||||
|
*y = coords[i].y;
|
||||||
|
*width = coords[i].width;
|
||||||
|
*height = coords[i].height;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -25,6 +25,23 @@ GskVulkanImage * gsk_vulkan_renderer_ref_texture_image (GskVulk
|
|||||||
GskTexture *texture,
|
GskTexture *texture,
|
||||||
GskVulkanUploader *uploader);
|
GskVulkanUploader *uploader);
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
float x, y, width, height;
|
||||||
|
} GskRectangle;
|
||||||
|
|
||||||
|
GskVulkanImage * gsk_vulkan_renderer_ref_glyph_image (GskVulkanRenderer *self,
|
||||||
|
GskVulkanUploader *uploader,
|
||||||
|
PangoFont *font,
|
||||||
|
PangoGlyphString *glyphs);
|
||||||
|
void gsk_vulkan_renderer_get_glyph_coords (GskVulkanRenderer *self,
|
||||||
|
PangoFont *font,
|
||||||
|
PangoGlyphString *glyphs,
|
||||||
|
PangoGlyph glyph,
|
||||||
|
float *x,
|
||||||
|
float *y,
|
||||||
|
float *width,
|
||||||
|
float *height);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* __GSK_VULKAN_RENDERER_PRIVATE_H__ */
|
#endif /* __GSK_VULKAN_RENDERER_PRIVATE_H__ */
|
||||||
|
@@ -12,11 +12,16 @@
|
|||||||
#include "gskvulkanboxshadowpipelineprivate.h"
|
#include "gskvulkanboxshadowpipelineprivate.h"
|
||||||
#include "gskvulkanclipprivate.h"
|
#include "gskvulkanclipprivate.h"
|
||||||
#include "gskvulkancolorpipelineprivate.h"
|
#include "gskvulkancolorpipelineprivate.h"
|
||||||
|
#include "gskvulkancolortextpipelineprivate.h"
|
||||||
#include "gskvulkaneffectpipelineprivate.h"
|
#include "gskvulkaneffectpipelineprivate.h"
|
||||||
#include "gskvulkanlineargradientpipelineprivate.h"
|
#include "gskvulkanlineargradientpipelineprivate.h"
|
||||||
|
#include "gskvulkantextpipelineprivate.h"
|
||||||
#include "gskvulkanimageprivate.h"
|
#include "gskvulkanimageprivate.h"
|
||||||
#include "gskvulkanpushconstantsprivate.h"
|
#include "gskvulkanpushconstantsprivate.h"
|
||||||
#include "gskvulkanrendererprivate.h"
|
#include "gskvulkanrendererprivate.h"
|
||||||
|
#include "gskprivate.h"
|
||||||
|
|
||||||
|
#include <cairo-ft.h>
|
||||||
|
|
||||||
typedef union _GskVulkanOp GskVulkanOp;
|
typedef union _GskVulkanOp GskVulkanOp;
|
||||||
typedef struct _GskVulkanOpRender GskVulkanOpRender;
|
typedef struct _GskVulkanOpRender GskVulkanOpRender;
|
||||||
@@ -29,6 +34,8 @@ typedef enum {
|
|||||||
GSK_VULKAN_OP_FALLBACK_ROUNDED_CLIP,
|
GSK_VULKAN_OP_FALLBACK_ROUNDED_CLIP,
|
||||||
GSK_VULKAN_OP_SURFACE,
|
GSK_VULKAN_OP_SURFACE,
|
||||||
GSK_VULKAN_OP_TEXTURE,
|
GSK_VULKAN_OP_TEXTURE,
|
||||||
|
GSK_VULKAN_OP_TEXT,
|
||||||
|
GSK_VULKAN_OP_COLOR_TEXT,
|
||||||
GSK_VULKAN_OP_COLOR,
|
GSK_VULKAN_OP_COLOR,
|
||||||
GSK_VULKAN_OP_LINEAR_GRADIENT,
|
GSK_VULKAN_OP_LINEAR_GRADIENT,
|
||||||
GSK_VULKAN_OP_OPACITY,
|
GSK_VULKAN_OP_OPACITY,
|
||||||
@@ -95,6 +102,23 @@ gsk_vulkan_render_pass_free (GskVulkanRenderPass *self)
|
|||||||
g_slice_free (GskVulkanRenderPass, self);
|
g_slice_free (GskVulkanRenderPass, self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
font_has_color_glyphs (PangoFont *font)
|
||||||
|
{
|
||||||
|
cairo_scaled_font_t *scaled_font;
|
||||||
|
gboolean has_color = FALSE;
|
||||||
|
|
||||||
|
scaled_font = pango_cairo_font_get_scaled_font ((PangoCairoFont *)font);
|
||||||
|
if (cairo_scaled_font_get_type (scaled_font) == CAIRO_FONT_TYPE_FT)
|
||||||
|
{
|
||||||
|
FT_Face ft_face = cairo_ft_scaled_font_lock_face (scaled_font);
|
||||||
|
has_color = (FT_HAS_COLOR (ft_face) != 0);
|
||||||
|
cairo_ft_scaled_font_unlock_face (scaled_font);
|
||||||
|
}
|
||||||
|
|
||||||
|
return has_color;
|
||||||
|
}
|
||||||
|
|
||||||
#define FALLBACK(...) G_STMT_START { \
|
#define FALLBACK(...) G_STMT_START { \
|
||||||
GSK_NOTE (FALLBACK, g_print (__VA_ARGS__)); \
|
GSK_NOTE (FALLBACK, g_print (__VA_ARGS__)); \
|
||||||
goto fallback; \
|
goto fallback; \
|
||||||
@@ -172,6 +196,35 @@ gsk_vulkan_render_pass_add_node (GskVulkanRenderPass *self,
|
|||||||
g_array_append_val (self->render_ops, op);
|
g_array_append_val (self->render_ops, op);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
case GSK_TEXT_NODE:
|
||||||
|
if (font_has_color_glyphs (gsk_text_node_get_font (node)))
|
||||||
|
{
|
||||||
|
if (gsk_vulkan_clip_contains_rect (&constants->clip, &node->bounds))
|
||||||
|
pipeline_type = GSK_VULKAN_PIPELINE_COLOR_TEXT;
|
||||||
|
else if (constants->clip.type == GSK_VULKAN_CLIP_RECT)
|
||||||
|
pipeline_type = GSK_VULKAN_PIPELINE_COLOR_TEXT_CLIP;
|
||||||
|
else if (constants->clip.type == GSK_VULKAN_CLIP_ROUNDED_CIRCULAR)
|
||||||
|
pipeline_type = GSK_VULKAN_PIPELINE_COLOR_TEXT_CLIP_ROUNDED;
|
||||||
|
else
|
||||||
|
FALLBACK ("Text nodes can't deal with clip type %u\n", constants->clip.type);
|
||||||
|
op.type = GSK_VULKAN_OP_COLOR_TEXT;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (gsk_vulkan_clip_contains_rect (&constants->clip, &node->bounds))
|
||||||
|
pipeline_type = GSK_VULKAN_PIPELINE_TEXT;
|
||||||
|
else if (constants->clip.type == GSK_VULKAN_CLIP_RECT)
|
||||||
|
pipeline_type = GSK_VULKAN_PIPELINE_TEXT_CLIP;
|
||||||
|
else if (constants->clip.type == GSK_VULKAN_CLIP_ROUNDED_CIRCULAR)
|
||||||
|
pipeline_type = GSK_VULKAN_PIPELINE_TEXT_CLIP_ROUNDED;
|
||||||
|
else
|
||||||
|
FALLBACK ("Text nodes can't deal with clip type %u\n", constants->clip.type);
|
||||||
|
op.type = GSK_VULKAN_OP_TEXT;
|
||||||
|
}
|
||||||
|
op.render.pipeline = gsk_vulkan_render_get_pipeline (render, pipeline_type);
|
||||||
|
g_array_append_val (self->render_ops, op);
|
||||||
|
return;
|
||||||
|
|
||||||
case GSK_TEXTURE_NODE:
|
case GSK_TEXTURE_NODE:
|
||||||
if (gsk_vulkan_clip_contains_rect (&constants->clip, &node->bounds))
|
if (gsk_vulkan_clip_contains_rect (&constants->clip, &node->bounds))
|
||||||
pipeline_type = GSK_VULKAN_PIPELINE_BLEND;
|
pipeline_type = GSK_VULKAN_PIPELINE_BLEND;
|
||||||
@@ -528,7 +581,9 @@ gsk_vulkan_render_pass_upload (GskVulkanRenderPass *self,
|
|||||||
|
|
||||||
case GSK_VULKAN_OP_SURFACE:
|
case GSK_VULKAN_OP_SURFACE:
|
||||||
{
|
{
|
||||||
cairo_surface_t *surface = gsk_cairo_node_get_surface (op->render.node);
|
cairo_surface_t *surface;
|
||||||
|
|
||||||
|
surface = gsk_cairo_node_get_surface (op->render.node);
|
||||||
op->render.source = gsk_vulkan_image_new_from_data (uploader,
|
op->render.source = gsk_vulkan_image_new_from_data (uploader,
|
||||||
cairo_image_surface_get_data (surface),
|
cairo_image_surface_get_data (surface),
|
||||||
cairo_image_surface_get_width (surface),
|
cairo_image_surface_get_width (surface),
|
||||||
@@ -538,6 +593,17 @@ gsk_vulkan_render_pass_upload (GskVulkanRenderPass *self,
|
|||||||
}
|
}
|
||||||
break;
|
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:
|
case GSK_VULKAN_OP_TEXTURE:
|
||||||
{
|
{
|
||||||
op->render.source = gsk_vulkan_renderer_ref_texture_image (GSK_VULKAN_RENDERER (gsk_vulkan_render_get_renderer (render)),
|
op->render.source = gsk_vulkan_renderer_ref_texture_image (GSK_VULKAN_RENDERER (gsk_vulkan_render_get_renderer (render)),
|
||||||
@@ -619,6 +685,18 @@ gsk_vulkan_render_pass_count_vertex_data (GskVulkanRenderPass *self)
|
|||||||
n_bytes += op->render.vertex_count;
|
n_bytes += op->render.vertex_count;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case GSK_VULKAN_OP_TEXT:
|
||||||
|
op->render.vertex_count = gsk_vulkan_text_pipeline_count_vertex_data (GSK_VULKAN_TEXT_PIPELINE (op->render.pipeline),
|
||||||
|
pango_glyph_string_num_glyphs (gsk_text_node_get_glyphs (op->render.node)));
|
||||||
|
n_bytes += op->render.vertex_count;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GSK_VULKAN_OP_COLOR_TEXT:
|
||||||
|
op->render.vertex_count = gsk_vulkan_color_text_pipeline_count_vertex_data (GSK_VULKAN_COLOR_TEXT_PIPELINE (op->render.pipeline),
|
||||||
|
pango_glyph_string_num_glyphs (gsk_text_node_get_glyphs (op->render.node)));
|
||||||
|
n_bytes += op->render.vertex_count;
|
||||||
|
break;
|
||||||
|
|
||||||
case GSK_VULKAN_OP_COLOR:
|
case GSK_VULKAN_OP_COLOR:
|
||||||
op->render.vertex_count = gsk_vulkan_color_pipeline_count_vertex_data (GSK_VULKAN_COLOR_PIPELINE (op->render.pipeline));
|
op->render.vertex_count = gsk_vulkan_color_pipeline_count_vertex_data (GSK_VULKAN_COLOR_PIPELINE (op->render.pipeline));
|
||||||
n_bytes += op->render.vertex_count;
|
n_bytes += op->render.vertex_count;
|
||||||
@@ -663,6 +741,7 @@ gsk_vulkan_render_pass_count_vertex_data (GskVulkanRenderPass *self)
|
|||||||
|
|
||||||
gsize
|
gsize
|
||||||
gsk_vulkan_render_pass_collect_vertex_data (GskVulkanRenderPass *self,
|
gsk_vulkan_render_pass_collect_vertex_data (GskVulkanRenderPass *self,
|
||||||
|
GskVulkanRender *render,
|
||||||
guchar *data,
|
guchar *data,
|
||||||
gsize offset,
|
gsize offset,
|
||||||
gsize total)
|
gsize total)
|
||||||
@@ -692,6 +771,37 @@ gsk_vulkan_render_pass_collect_vertex_data (GskVulkanRenderPass *self,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case GSK_VULKAN_OP_TEXT:
|
||||||
|
{
|
||||||
|
op->render.vertex_offset = offset + n_bytes;
|
||||||
|
gsk_vulkan_text_pipeline_collect_vertex_data (GSK_VULKAN_TEXT_PIPELINE (op->render.pipeline),
|
||||||
|
data + n_bytes + offset,
|
||||||
|
GSK_VULKAN_RENDERER (gsk_vulkan_render_get_renderer (render)),
|
||||||
|
&op->render.node->bounds,
|
||||||
|
gsk_text_node_get_font (op->render.node),
|
||||||
|
gsk_text_node_get_glyphs (op->render.node),
|
||||||
|
gsk_text_node_get_color (op->render.node),
|
||||||
|
gsk_text_node_get_x (op->render.node),
|
||||||
|
gsk_text_node_get_y (op->render.node));
|
||||||
|
n_bytes += op->render.vertex_count;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GSK_VULKAN_OP_COLOR_TEXT:
|
||||||
|
{
|
||||||
|
op->render.vertex_offset = offset + n_bytes;
|
||||||
|
gsk_vulkan_color_text_pipeline_collect_vertex_data (GSK_VULKAN_COLOR_TEXT_PIPELINE (op->render.pipeline),
|
||||||
|
data + n_bytes + offset,
|
||||||
|
GSK_VULKAN_RENDERER (gsk_vulkan_render_get_renderer (render)),
|
||||||
|
&op->render.node->bounds,
|
||||||
|
gsk_text_node_get_font (op->render.node),
|
||||||
|
gsk_text_node_get_glyphs (op->render.node),
|
||||||
|
gsk_text_node_get_x (op->render.node),
|
||||||
|
gsk_text_node_get_y (op->render.node));
|
||||||
|
n_bytes += op->render.vertex_count;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case GSK_VULKAN_OP_COLOR:
|
case GSK_VULKAN_OP_COLOR:
|
||||||
{
|
{
|
||||||
op->render.vertex_offset = offset + n_bytes;
|
op->render.vertex_offset = offset + n_bytes;
|
||||||
@@ -834,6 +944,8 @@ gsk_vulkan_render_pass_reserve_descriptor_sets (GskVulkanRenderPass *self,
|
|||||||
case GSK_VULKAN_OP_FALLBACK_CLIP:
|
case GSK_VULKAN_OP_FALLBACK_CLIP:
|
||||||
case GSK_VULKAN_OP_FALLBACK_ROUNDED_CLIP:
|
case GSK_VULKAN_OP_FALLBACK_ROUNDED_CLIP:
|
||||||
case GSK_VULKAN_OP_SURFACE:
|
case GSK_VULKAN_OP_SURFACE:
|
||||||
|
case GSK_VULKAN_OP_TEXT:
|
||||||
|
case GSK_VULKAN_OP_COLOR_TEXT:
|
||||||
case GSK_VULKAN_OP_TEXTURE:
|
case GSK_VULKAN_OP_TEXTURE:
|
||||||
case GSK_VULKAN_OP_OPACITY:
|
case GSK_VULKAN_OP_OPACITY:
|
||||||
case GSK_VULKAN_OP_BLUR:
|
case GSK_VULKAN_OP_BLUR:
|
||||||
@@ -910,6 +1022,72 @@ gsk_vulkan_render_pass_draw (GskVulkanRenderPass *self,
|
|||||||
current_draw_index, 1);
|
current_draw_index, 1);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case GSK_VULKAN_OP_TEXT:
|
||||||
|
if (current_pipeline != op->render.pipeline)
|
||||||
|
{
|
||||||
|
current_pipeline = op->render.pipeline;
|
||||||
|
vkCmdBindPipeline (command_buffer,
|
||||||
|
VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||||
|
gsk_vulkan_pipeline_get_pipeline (current_pipeline));
|
||||||
|
vkCmdBindVertexBuffers (command_buffer,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
(VkBuffer[1]) {
|
||||||
|
gsk_vulkan_buffer_get_buffer (vertex_buffer)
|
||||||
|
},
|
||||||
|
(VkDeviceSize[1]) { op->render.vertex_offset });
|
||||||
|
current_draw_index = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
vkCmdBindDescriptorSets (command_buffer,
|
||||||
|
VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||||
|
gsk_vulkan_pipeline_layout_get_pipeline_layout (layout),
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
(VkDescriptorSet[1]) {
|
||||||
|
gsk_vulkan_render_get_descriptor_set (render, op->render.descriptor_set_index)
|
||||||
|
},
|
||||||
|
0,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
current_draw_index += gsk_vulkan_text_pipeline_draw (GSK_VULKAN_TEXT_PIPELINE (current_pipeline),
|
||||||
|
command_buffer,
|
||||||
|
current_draw_index, pango_glyph_string_num_glyphs (gsk_text_node_get_glyphs (op->render.node)));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case GSK_VULKAN_OP_COLOR_TEXT:
|
||||||
|
if (current_pipeline != op->render.pipeline)
|
||||||
|
{
|
||||||
|
current_pipeline = op->render.pipeline;
|
||||||
|
vkCmdBindPipeline (command_buffer,
|
||||||
|
VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||||
|
gsk_vulkan_pipeline_get_pipeline (current_pipeline));
|
||||||
|
vkCmdBindVertexBuffers (command_buffer,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
(VkBuffer[1]) {
|
||||||
|
gsk_vulkan_buffer_get_buffer (vertex_buffer)
|
||||||
|
},
|
||||||
|
(VkDeviceSize[1]) { op->render.vertex_offset });
|
||||||
|
current_draw_index = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
vkCmdBindDescriptorSets (command_buffer,
|
||||||
|
VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||||
|
gsk_vulkan_pipeline_layout_get_pipeline_layout (layout),
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
(VkDescriptorSet[1]) {
|
||||||
|
gsk_vulkan_render_get_descriptor_set (render, op->render.descriptor_set_index)
|
||||||
|
},
|
||||||
|
0,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
current_draw_index += gsk_vulkan_color_text_pipeline_draw (GSK_VULKAN_COLOR_TEXT_PIPELINE (current_pipeline),
|
||||||
|
command_buffer,
|
||||||
|
current_draw_index, pango_glyph_string_num_glyphs (gsk_text_node_get_glyphs (op->render.node)));
|
||||||
|
break;
|
||||||
|
|
||||||
case GSK_VULKAN_OP_OPACITY:
|
case GSK_VULKAN_OP_OPACITY:
|
||||||
case GSK_VULKAN_OP_COLOR_MATRIX:
|
case GSK_VULKAN_OP_COLOR_MATRIX:
|
||||||
if (current_pipeline != op->render.pipeline)
|
if (current_pipeline != op->render.pipeline)
|
||||||
|
@@ -26,6 +26,7 @@ void gsk_vulkan_render_pass_upload (GskVulk
|
|||||||
|
|
||||||
gsize gsk_vulkan_render_pass_count_vertex_data (GskVulkanRenderPass *self);
|
gsize gsk_vulkan_render_pass_count_vertex_data (GskVulkanRenderPass *self);
|
||||||
gsize gsk_vulkan_render_pass_collect_vertex_data (GskVulkanRenderPass *self,
|
gsize gsk_vulkan_render_pass_collect_vertex_data (GskVulkanRenderPass *self,
|
||||||
|
GskVulkanRender *render,
|
||||||
guchar *data,
|
guchar *data,
|
||||||
gsize offset,
|
gsize offset,
|
||||||
gsize total);
|
gsize total);
|
||||||
|
@@ -34,6 +34,12 @@ typedef enum {
|
|||||||
GSK_VULKAN_PIPELINE_BLUR,
|
GSK_VULKAN_PIPELINE_BLUR,
|
||||||
GSK_VULKAN_PIPELINE_BLUR_CLIP,
|
GSK_VULKAN_PIPELINE_BLUR_CLIP,
|
||||||
GSK_VULKAN_PIPELINE_BLUR_CLIP_ROUNDED,
|
GSK_VULKAN_PIPELINE_BLUR_CLIP_ROUNDED,
|
||||||
|
GSK_VULKAN_PIPELINE_TEXT,
|
||||||
|
GSK_VULKAN_PIPELINE_TEXT_CLIP,
|
||||||
|
GSK_VULKAN_PIPELINE_TEXT_CLIP_ROUNDED,
|
||||||
|
GSK_VULKAN_PIPELINE_COLOR_TEXT,
|
||||||
|
GSK_VULKAN_PIPELINE_COLOR_TEXT_CLIP,
|
||||||
|
GSK_VULKAN_PIPELINE_COLOR_TEXT_CLIP_ROUNDED,
|
||||||
/* add more */
|
/* add more */
|
||||||
GSK_VULKAN_N_PIPELINES
|
GSK_VULKAN_N_PIPELINES
|
||||||
} GskVulkanPipelineType;
|
} GskVulkanPipelineType;
|
||||||
|
169
gsk/gskvulkantextpipeline.c
Normal file
169
gsk/gskvulkantextpipeline.c
Normal file
@@ -0,0 +1,169 @@
|
|||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include "gskvulkantextpipelineprivate.h"
|
||||||
|
|
||||||
|
struct _GskVulkanTextPipeline
|
||||||
|
{
|
||||||
|
GObject parent_instance;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct _GskVulkanTextInstance GskVulkanTextInstance;
|
||||||
|
|
||||||
|
struct _GskVulkanTextInstance
|
||||||
|
{
|
||||||
|
float rect[4];
|
||||||
|
float tex_rect[4];
|
||||||
|
float color[4];
|
||||||
|
};
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (GskVulkanTextPipeline, gsk_vulkan_text_pipeline, GSK_TYPE_VULKAN_PIPELINE)
|
||||||
|
|
||||||
|
static const VkPipelineVertexInputStateCreateInfo *
|
||||||
|
gsk_vulkan_text_pipeline_get_input_state_create_info (GskVulkanPipeline *self)
|
||||||
|
{
|
||||||
|
static const VkVertexInputBindingDescription vertexBindingDescriptions[] = {
|
||||||
|
{
|
||||||
|
.binding = 0,
|
||||||
|
.stride = sizeof (GskVulkanTextInstance),
|
||||||
|
.inputRate = VK_VERTEX_INPUT_RATE_INSTANCE
|
||||||
|
}
|
||||||
|
};
|
||||||
|
static const VkVertexInputAttributeDescription vertexInputAttributeDescription[] = {
|
||||||
|
{
|
||||||
|
.location = 0,
|
||||||
|
.binding = 0,
|
||||||
|
.format = VK_FORMAT_R32G32B32A32_SFLOAT,
|
||||||
|
.offset = G_STRUCT_OFFSET (GskVulkanTextInstance, rect),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.location = 1,
|
||||||
|
.binding = 0,
|
||||||
|
.format = VK_FORMAT_R32G32B32A32_SFLOAT,
|
||||||
|
.offset = G_STRUCT_OFFSET (GskVulkanTextInstance, tex_rect),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.location = 2,
|
||||||
|
.binding = 0,
|
||||||
|
.format = VK_FORMAT_R32G32B32A32_SFLOAT,
|
||||||
|
.offset = G_STRUCT_OFFSET (GskVulkanTextInstance, color),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
static const VkPipelineVertexInputStateCreateInfo info = {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
|
||||||
|
.vertexBindingDescriptionCount = G_N_ELEMENTS (vertexBindingDescriptions),
|
||||||
|
.pVertexBindingDescriptions = vertexBindingDescriptions,
|
||||||
|
.vertexAttributeDescriptionCount = G_N_ELEMENTS (vertexInputAttributeDescription),
|
||||||
|
.pVertexAttributeDescriptions = vertexInputAttributeDescription
|
||||||
|
};
|
||||||
|
|
||||||
|
return &info;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gsk_vulkan_text_pipeline_finalize (GObject *gobject)
|
||||||
|
{
|
||||||
|
//GskVulkanTextPipeline *self = GSK_VULKAN_TEXT_PIPELINE (gobject);
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (gsk_vulkan_text_pipeline_parent_class)->finalize (gobject);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gsk_vulkan_text_pipeline_class_init (GskVulkanTextPipelineClass *klass)
|
||||||
|
{
|
||||||
|
GskVulkanPipelineClass *pipeline_class = GSK_VULKAN_PIPELINE_CLASS (klass);
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (klass)->finalize = gsk_vulkan_text_pipeline_finalize;
|
||||||
|
|
||||||
|
pipeline_class->get_input_state_create_info = gsk_vulkan_text_pipeline_get_input_state_create_info;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gsk_vulkan_text_pipeline_init (GskVulkanTextPipeline *self)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
GskVulkanPipeline *
|
||||||
|
gsk_vulkan_text_pipeline_new (GskVulkanPipelineLayout *layout,
|
||||||
|
const char *shader_name,
|
||||||
|
VkRenderPass render_pass)
|
||||||
|
{
|
||||||
|
return gsk_vulkan_pipeline_new_full (GSK_TYPE_VULKAN_TEXT_PIPELINE, layout, shader_name, render_pass,
|
||||||
|
VK_BLEND_FACTOR_SRC_ALPHA, VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA);
|
||||||
|
}
|
||||||
|
|
||||||
|
gsize
|
||||||
|
gsk_vulkan_text_pipeline_count_vertex_data (GskVulkanTextPipeline *pipeline,
|
||||||
|
int num_instances)
|
||||||
|
{
|
||||||
|
return sizeof (GskVulkanTextInstance) * num_instances;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gsk_vulkan_text_pipeline_collect_vertex_data (GskVulkanTextPipeline *pipeline,
|
||||||
|
guchar *data,
|
||||||
|
GskVulkanRenderer *renderer,
|
||||||
|
const graphene_rect_t *rect,
|
||||||
|
PangoFont *font,
|
||||||
|
PangoGlyphString *glyphs,
|
||||||
|
const GdkRGBA *color,
|
||||||
|
float x,
|
||||||
|
float y)
|
||||||
|
{
|
||||||
|
GskVulkanTextInstance *instances = (GskVulkanTextInstance *) data;
|
||||||
|
int i, count;
|
||||||
|
int x_position = 0;
|
||||||
|
float ink_rect_y;
|
||||||
|
float ink_rect_height;
|
||||||
|
|
||||||
|
/* XXX */
|
||||||
|
ink_rect_y = rect->origin.y - y;
|
||||||
|
ink_rect_height = rect->size.height;
|
||||||
|
|
||||||
|
count = 0;
|
||||||
|
for (i = 0; i < glyphs->num_glyphs; i++)
|
||||||
|
{
|
||||||
|
PangoGlyphInfo *gi = &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))
|
||||||
|
{
|
||||||
|
GskVulkanTextInstance *instance = &instances[count];
|
||||||
|
|
||||||
|
instance->rect[0] = x + cx;
|
||||||
|
instance->rect[1] = y + ink_rect_y + cy;
|
||||||
|
instance->rect[2] = (float)gi->geometry.width / PANGO_SCALE;
|
||||||
|
instance->rect[3] = ink_rect_height;
|
||||||
|
gsk_vulkan_renderer_get_glyph_coords (renderer, font, glyphs,
|
||||||
|
gi->glyph,
|
||||||
|
&instance->tex_rect[0],
|
||||||
|
&instance->tex_rect[1],
|
||||||
|
&instance->tex_rect[2],
|
||||||
|
&instance->tex_rect[3]);
|
||||||
|
instance->color[0] = color->red;
|
||||||
|
instance->color[1] = color->green;
|
||||||
|
instance->color[2] = color->blue;
|
||||||
|
instance->color[3] = color->alpha;
|
||||||
|
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
x_position += gi->geometry.width;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gsize
|
||||||
|
gsk_vulkan_text_pipeline_draw (GskVulkanTextPipeline *pipeline,
|
||||||
|
VkCommandBuffer command_buffer,
|
||||||
|
gsize offset,
|
||||||
|
gsize n_commands)
|
||||||
|
{
|
||||||
|
vkCmdDraw (command_buffer,
|
||||||
|
6, n_commands,
|
||||||
|
0, offset);
|
||||||
|
|
||||||
|
return n_commands;
|
||||||
|
}
|
39
gsk/gskvulkantextpipelineprivate.h
Normal file
39
gsk/gskvulkantextpipelineprivate.h
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
#ifndef __GSK_VULKAN_TEXT_PIPELINE_PRIVATE_H__
|
||||||
|
#define __GSK_VULKAN_TEXT_PIPELINE_PRIVATE_H__
|
||||||
|
|
||||||
|
#include <graphene.h>
|
||||||
|
|
||||||
|
#include "gskvulkanpipelineprivate.h"
|
||||||
|
#include "gskvulkanrendererprivate.h"
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
typedef struct _GskVulkanTextPipelineLayout GskVulkanTextPipelineLayout;
|
||||||
|
|
||||||
|
#define GSK_TYPE_VULKAN_TEXT_PIPELINE (gsk_vulkan_text_pipeline_get_type ())
|
||||||
|
|
||||||
|
G_DECLARE_FINAL_TYPE (GskVulkanTextPipeline, gsk_vulkan_text_pipeline, GSK, VULKAN_TEXT_PIPELINE, GskVulkanPipeline)
|
||||||
|
|
||||||
|
GskVulkanPipeline * gsk_vulkan_text_pipeline_new (GskVulkanPipelineLayout * layout,
|
||||||
|
const char *shader_name,
|
||||||
|
VkRenderPass render_pass);
|
||||||
|
|
||||||
|
gsize gsk_vulkan_text_pipeline_count_vertex_data (GskVulkanTextPipeline *pipeline,
|
||||||
|
int num_instances);
|
||||||
|
void gsk_vulkan_text_pipeline_collect_vertex_data (GskVulkanTextPipeline *pipeline,
|
||||||
|
guchar *data,
|
||||||
|
GskVulkanRenderer *renderer,
|
||||||
|
const graphene_rect_t *rect,
|
||||||
|
PangoFont *font,
|
||||||
|
PangoGlyphString *glyphs,
|
||||||
|
const GdkRGBA *color,
|
||||||
|
float x,
|
||||||
|
float y);
|
||||||
|
gsize gsk_vulkan_text_pipeline_draw (GskVulkanTextPipeline *pipeline,
|
||||||
|
VkCommandBuffer command_buffer,
|
||||||
|
gsize offset,
|
||||||
|
gsize n_commands);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __GSK_VULKAN_TEXT_PIPELINE_PRIVATE_H__ */
|
@@ -61,10 +61,12 @@ if have_vulkan
|
|||||||
'gskvulkanbuffer.c',
|
'gskvulkanbuffer.c',
|
||||||
'gskvulkanclip.c',
|
'gskvulkanclip.c',
|
||||||
'gskvulkancolorpipeline.c',
|
'gskvulkancolorpipeline.c',
|
||||||
|
'gskvulkancolortextpipeline.c',
|
||||||
'gskvulkancommandpool.c',
|
'gskvulkancommandpool.c',
|
||||||
'gskvulkaneffectpipeline.c',
|
'gskvulkaneffectpipeline.c',
|
||||||
'gskvulkanlineargradientpipeline.c',
|
'gskvulkanlineargradientpipeline.c',
|
||||||
'gskvulkanimage.c',
|
'gskvulkanimage.c',
|
||||||
|
'gskvulkantextpipeline.c',
|
||||||
'gskvulkanmemory.c',
|
'gskvulkanmemory.c',
|
||||||
'gskvulkanpipeline.c',
|
'gskvulkanpipeline.c',
|
||||||
'gskvulkanpushconstants.c',
|
'gskvulkanpushconstants.c',
|
||||||
|
BIN
gsk/resources/vulkan/mask-clip-rounded.frag.spv
Normal file
BIN
gsk/resources/vulkan/mask-clip-rounded.frag.spv
Normal file
Binary file not shown.
BIN
gsk/resources/vulkan/mask-clip-rounded.vert.spv
Normal file
BIN
gsk/resources/vulkan/mask-clip-rounded.vert.spv
Normal file
Binary file not shown.
BIN
gsk/resources/vulkan/mask-clip.frag.spv
Normal file
BIN
gsk/resources/vulkan/mask-clip.frag.spv
Normal file
Binary file not shown.
BIN
gsk/resources/vulkan/mask-clip.vert.spv
Normal file
BIN
gsk/resources/vulkan/mask-clip.vert.spv
Normal file
Binary file not shown.
16
gsk/resources/vulkan/mask.frag
Normal file
16
gsk/resources/vulkan/mask.frag
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
#version 420 core
|
||||||
|
|
||||||
|
#include "clip.frag.glsl"
|
||||||
|
|
||||||
|
layout(location = 0) in vec2 inPos;
|
||||||
|
layout(location = 1) in vec2 inTexCoord;
|
||||||
|
layout(location = 2) in vec4 inColor;
|
||||||
|
|
||||||
|
layout(set = 0, binding = 0) uniform sampler2D inTexture;
|
||||||
|
|
||||||
|
layout(location = 0) out vec4 color;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
color = clip (inPos, vec4(inColor.rgb, texture(inTexture, inTexCoord).a));
|
||||||
|
}
|
BIN
gsk/resources/vulkan/mask.frag.spv
Normal file
BIN
gsk/resources/vulkan/mask.frag.spv
Normal file
Binary file not shown.
38
gsk/resources/vulkan/mask.vert
Normal file
38
gsk/resources/vulkan/mask.vert
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
#version 420 core
|
||||||
|
|
||||||
|
#include "clip.vert.glsl"
|
||||||
|
|
||||||
|
layout(location = 0) in vec4 inRect;
|
||||||
|
layout(location = 1) in vec4 inTexRect;
|
||||||
|
layout(location = 2) in vec4 inColor;
|
||||||
|
|
||||||
|
layout(location = 0) out vec2 outPos;
|
||||||
|
layout(location = 1) out vec2 outTexCoord;
|
||||||
|
layout(location = 2) out flat vec4 outColor;
|
||||||
|
|
||||||
|
out gl_PerVertex {
|
||||||
|
vec4 gl_Position;
|
||||||
|
};
|
||||||
|
|
||||||
|
vec2 offsets[6] = { vec2(0.0, 0.0),
|
||||||
|
vec2(1.0, 0.0),
|
||||||
|
vec2(0.0, 1.0),
|
||||||
|
vec2(0.0, 1.0),
|
||||||
|
vec2(1.0, 0.0),
|
||||||
|
vec2(1.0, 1.0) };
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
vec4 rect = clip (inRect);
|
||||||
|
vec2 pos = rect.xy + rect.zw * offsets[gl_VertexIndex];
|
||||||
|
gl_Position = push.mvp * vec4 (pos, 0.0, 1.0);
|
||||||
|
|
||||||
|
outPos = pos;
|
||||||
|
|
||||||
|
vec4 texrect = vec4((rect.xy - inRect.xy) / inRect.zw,
|
||||||
|
rect.zw / inRect.zw);
|
||||||
|
texrect = vec4(inTexRect.xy + inTexRect.zw * texrect.xy,
|
||||||
|
inTexRect.zw * texrect.zw);
|
||||||
|
outTexCoord = texrect.xy + texrect.zw * offsets[gl_VertexIndex];
|
||||||
|
|
||||||
|
outColor = inColor;
|
||||||
|
}
|
BIN
gsk/resources/vulkan/mask.vert.spv
Normal file
BIN
gsk/resources/vulkan/mask.vert.spv
Normal file
Binary file not shown.
@@ -14,6 +14,7 @@ gsk_private_vulkan_fragment_shaders = [
|
|||||||
'color-matrix.frag',
|
'color-matrix.frag',
|
||||||
'inset-shadow.frag',
|
'inset-shadow.frag',
|
||||||
'linear.frag',
|
'linear.frag',
|
||||||
|
'mask.frag',
|
||||||
'outset-shadow.frag',
|
'outset-shadow.frag',
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -25,6 +26,7 @@ gsk_private_vulkan_vertex_shaders = [
|
|||||||
'color-matrix.vert',
|
'color-matrix.vert',
|
||||||
'inset-shadow.vert',
|
'inset-shadow.vert',
|
||||||
'linear.vert',
|
'linear.vert',
|
||||||
|
'mask.vert',
|
||||||
'outset-shadow.vert',
|
'outset-shadow.vert',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@@ -112,8 +112,6 @@ gsk_pango_renderer_show_text_glyphs (PangoRenderer *renderer,
|
|||||||
int y)
|
int y)
|
||||||
{
|
{
|
||||||
GskPangoRenderer *crenderer = (GskPangoRenderer *) (renderer);
|
GskPangoRenderer *crenderer = (GskPangoRenderer *) (renderer);
|
||||||
double base_x = (double)x / PANGO_SCALE;
|
|
||||||
double base_y = (double)y / PANGO_SCALE;
|
|
||||||
int x_offset, y_offset;
|
int x_offset, y_offset;
|
||||||
GskRenderNode *node;
|
GskRenderNode *node;
|
||||||
GdkRGBA color;
|
GdkRGBA color;
|
||||||
@@ -121,7 +119,7 @@ gsk_pango_renderer_show_text_glyphs (PangoRenderer *renderer,
|
|||||||
gtk_snapshot_get_offset (crenderer->snapshot, &x_offset, &y_offset);
|
gtk_snapshot_get_offset (crenderer->snapshot, &x_offset, &y_offset);
|
||||||
get_color (crenderer, PANGO_RENDER_PART_FOREGROUND, &color);
|
get_color (crenderer, PANGO_RENDER_PART_FOREGROUND, &color);
|
||||||
|
|
||||||
node = gsk_text_node_new (font, glyphs, &color, x_offset, y_offset, base_x, base_y);
|
node = gsk_text_node_new (font, glyphs, &color, x_offset + (double)x/PANGO_SCALE, y_offset + (double)y/PANGO_SCALE);
|
||||||
if (node == NULL)
|
if (node == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -132,12 +130,8 @@ gsk_pango_renderer_show_text_glyphs (PangoRenderer *renderer,
|
|||||||
gsk_render_node_set_name (node, name);
|
gsk_render_node_set_name (node, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
gtk_snapshot_offset (crenderer->snapshot, base_x, base_y);
|
|
||||||
|
|
||||||
gtk_snapshot_append_node (crenderer->snapshot, node);
|
gtk_snapshot_append_node (crenderer->snapshot, node);
|
||||||
gsk_render_node_unref (node);
|
gsk_render_node_unref (node);
|
||||||
|
|
||||||
gtk_snapshot_offset (crenderer->snapshot, -base_x, -base_y);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
Reference in New Issue
Block a user