Compare commits
20 Commits
add-mutter
...
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);
|
||||
}
|
||||
|
||||
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__
|
||||
|
||||
#include <glib.h>
|
||||
#include <pango/pango.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
void gsk_ensure_resources (void);
|
||||
|
||||
int pango_glyph_string_num_glyphs (PangoGlyphString *glyphs);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GSK_PRIVATE_H__ */
|
||||
|
@@ -178,10 +178,8 @@ GDK_AVAILABLE_IN_3_92
|
||||
GskRenderNode * gsk_text_node_new (PangoFont *font,
|
||||
PangoGlyphString *glyphs,
|
||||
const GdkRGBA *color,
|
||||
int x_offset,
|
||||
int y_offset,
|
||||
double base_x,
|
||||
double base_y);
|
||||
double x,
|
||||
double y);
|
||||
|
||||
GDK_AVAILABLE_IN_3_92
|
||||
GskRenderNode * gsk_blur_node_new (GskRenderNode *child,
|
||||
|
@@ -26,8 +26,6 @@
|
||||
#include "gskroundedrectprivate.h"
|
||||
#include "gsktextureprivate.h"
|
||||
|
||||
#include <cairo-ft.h>
|
||||
|
||||
static gboolean
|
||||
check_variant_type (GVariant *variant,
|
||||
const char *type_string,
|
||||
@@ -3812,13 +3810,13 @@ struct _GskTextNode
|
||||
GskRenderNode render_node;
|
||||
|
||||
PangoFont *font;
|
||||
gboolean has_color;
|
||||
PangoGlyphString *glyphs;
|
||||
|
||||
GdkRGBA color;
|
||||
int x_offset;
|
||||
int y_offset;
|
||||
double base_x;
|
||||
double base_y;
|
||||
double x;
|
||||
double y;
|
||||
double ink_rect_y;
|
||||
double ink_rect_height;
|
||||
};
|
||||
|
||||
static void
|
||||
@@ -3830,20 +3828,6 @@ gsk_text_node_finalize (GskRenderNode *node)
|
||||
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
|
||||
#define STACK_BUFFER_SIZE (512 * sizeof (int))
|
||||
#endif
|
||||
@@ -3857,16 +3841,19 @@ gsk_text_node_draw (GskRenderNode *node,
|
||||
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 *)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_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);
|
||||
if (!_pango_cairo_font_install (self->font, cr))
|
||||
goto done;
|
||||
|
||||
if (self->glyphs->num_glyphs > (int) G_N_ELEMENTS (stack_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)
|
||||
{
|
||||
double cx = self->base_x + (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 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))
|
||||
{
|
||||
@@ -3899,107 +3886,22 @@ gsk_text_node_draw (GskRenderNode *node,
|
||||
if (cairo_glyphs != stack_glyphs)
|
||||
g_free (cairo_glyphs);
|
||||
|
||||
done:
|
||||
cairo_restore (cr);
|
||||
}
|
||||
|
||||
#define GSK_TEXT_NODE_VARIANT_TYPE "(sddddiidda(uiiii))"
|
||||
|
||||
static GVariant *
|
||||
gsk_text_node_serialize (GskRenderNode *node)
|
||||
{
|
||||
GskTextNode *self = (GskTextNode *) node;
|
||||
GVariant *v;
|
||||
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;
|
||||
g_assert_not_reached ();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static GskRenderNode *
|
||||
gsk_text_node_deserialize (GVariant *variant,
|
||||
GError **error)
|
||||
{
|
||||
PangoFont *font;
|
||||
PangoGlyphString *glyphs;
|
||||
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;
|
||||
g_assert_not_reached ();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const GskRenderNodeClass GSK_TEXT_NODE_CLASS = {
|
||||
@@ -4012,31 +3914,12 @@ static const GskRenderNodeClass GSK_TEXT_NODE_CLASS = {
|
||||
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 *
|
||||
gsk_text_node_new (PangoFont *font,
|
||||
PangoGlyphString *glyphs,
|
||||
const GdkRGBA *color,
|
||||
int x_offset,
|
||||
int y_offset,
|
||||
double base_x,
|
||||
double base_y)
|
||||
double x,
|
||||
double y)
|
||||
{
|
||||
GskTextNode *self;
|
||||
PangoRectangle ink_rect;
|
||||
@@ -4053,23 +3936,70 @@ gsk_text_node_new (PangoFont *font,
|
||||
self->font = g_object_ref (font);
|
||||
self->glyphs = pango_glyph_string_copy (glyphs);
|
||||
self->color = *color;
|
||||
self->x_offset = x_offset;
|
||||
self->y_offset = y_offset;
|
||||
self->base_x = base_x;
|
||||
self->base_y = base_y;
|
||||
|
||||
self->has_color = font_has_color_glyphs (font);
|
||||
|
||||
self->x = x;
|
||||
self->y = y;
|
||||
self->ink_rect_y = ink_rect.y;
|
||||
self->ink_rect_height = ink_rect.height;
|
||||
|
||||
graphene_rect_init (&self->render_node.bounds,
|
||||
x_offset + base_x + ink_rect.x,
|
||||
y_offset + base_y + ink_rect.y,
|
||||
ink_rect.width,
|
||||
x,
|
||||
y + ink_rect.y,
|
||||
ink_rect.x + ink_rect.width,
|
||||
ink_rect.height);
|
||||
|
||||
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 ***/
|
||||
|
||||
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);
|
||||
|
||||
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 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,
|
||||
const char *shader_name,
|
||||
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;
|
||||
GskVulkanPipeline *self;
|
||||
@@ -134,11 +147,11 @@ gsk_vulkan_pipeline_new (GType pipeline_type,
|
||||
{
|
||||
.blendEnable = VK_TRUE,
|
||||
.colorBlendOp = VK_BLEND_OP_ADD,
|
||||
.srcColorBlendFactor = VK_BLEND_FACTOR_ONE,
|
||||
.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
|
||||
.srcColorBlendFactor = srcBlendFactor,
|
||||
.dstColorBlendFactor = dstBlendFactor,
|
||||
.alphaBlendOp = VK_BLEND_OP_ADD,
|
||||
.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE,
|
||||
.dstAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,
|
||||
.srcAlphaBlendFactor = srcBlendFactor,
|
||||
.dstAlphaBlendFactor = dstBlendFactor,
|
||||
.colorWriteMask = VK_COLOR_COMPONENT_A_BIT
|
||||
| VK_COLOR_COMPONENT_R_BIT
|
||||
| VK_COLOR_COMPONENT_G_BIT
|
||||
|
@@ -48,6 +48,12 @@ GskVulkanPipeline * gsk_vulkan_pipeline_new (GType
|
||||
GskVulkanPipelineLayout *layout,
|
||||
const char *shader_name,
|
||||
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);
|
||||
|
||||
|
@@ -15,8 +15,10 @@
|
||||
#include "gskvulkanborderpipelineprivate.h"
|
||||
#include "gskvulkanboxshadowpipelineprivate.h"
|
||||
#include "gskvulkancolorpipelineprivate.h"
|
||||
#include "gskvulkancolortextpipelineprivate.h"
|
||||
#include "gskvulkaneffectpipelineprivate.h"
|
||||
#include "gskvulkanlineargradientpipelineprivate.h"
|
||||
#include "gskvulkantextpipelineprivate.h"
|
||||
|
||||
#define ORTHO_NEAR_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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -344,6 +346,12 @@ gsk_vulkan_render_get_pipeline (GskVulkanRender *self,
|
||||
{ "blur", gsk_vulkan_blur_pipeline_new },
|
||||
{ "blur-clip", 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);
|
||||
|
@@ -44,6 +44,8 @@ struct _GskVulkanRenderer
|
||||
|
||||
GSList *textures;
|
||||
|
||||
GHashTable *glyph_cache;
|
||||
|
||||
#ifdef G_ENABLE_DEBUG
|
||||
ProfileTimers profile_timers;
|
||||
#endif
|
||||
@@ -343,3 +345,271 @@ gsk_vulkan_renderer_ref_texture_image (GskVulkanRenderer *self,
|
||||
|
||||
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,
|
||||
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
|
||||
|
||||
#endif /* __GSK_VULKAN_RENDERER_PRIVATE_H__ */
|
||||
|
@@ -12,11 +12,16 @@
|
||||
#include "gskvulkanboxshadowpipelineprivate.h"
|
||||
#include "gskvulkanclipprivate.h"
|
||||
#include "gskvulkancolorpipelineprivate.h"
|
||||
#include "gskvulkancolortextpipelineprivate.h"
|
||||
#include "gskvulkaneffectpipelineprivate.h"
|
||||
#include "gskvulkanlineargradientpipelineprivate.h"
|
||||
#include "gskvulkantextpipelineprivate.h"
|
||||
#include "gskvulkanimageprivate.h"
|
||||
#include "gskvulkanpushconstantsprivate.h"
|
||||
#include "gskvulkanrendererprivate.h"
|
||||
#include "gskprivate.h"
|
||||
|
||||
#include <cairo-ft.h>
|
||||
|
||||
typedef union _GskVulkanOp GskVulkanOp;
|
||||
typedef struct _GskVulkanOpRender GskVulkanOpRender;
|
||||
@@ -29,6 +34,8 @@ typedef enum {
|
||||
GSK_VULKAN_OP_FALLBACK_ROUNDED_CLIP,
|
||||
GSK_VULKAN_OP_SURFACE,
|
||||
GSK_VULKAN_OP_TEXTURE,
|
||||
GSK_VULKAN_OP_TEXT,
|
||||
GSK_VULKAN_OP_COLOR_TEXT,
|
||||
GSK_VULKAN_OP_COLOR,
|
||||
GSK_VULKAN_OP_LINEAR_GRADIENT,
|
||||
GSK_VULKAN_OP_OPACITY,
|
||||
@@ -95,6 +102,23 @@ gsk_vulkan_render_pass_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 { \
|
||||
GSK_NOTE (FALLBACK, g_print (__VA_ARGS__)); \
|
||||
goto fallback; \
|
||||
@@ -172,6 +196,35 @@ gsk_vulkan_render_pass_add_node (GskVulkanRenderPass *self,
|
||||
g_array_append_val (self->render_ops, op);
|
||||
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:
|
||||
if (gsk_vulkan_clip_contains_rect (&constants->clip, &node->bounds))
|
||||
pipeline_type = GSK_VULKAN_PIPELINE_BLEND;
|
||||
@@ -528,7 +581,9 @@ gsk_vulkan_render_pass_upload (GskVulkanRenderPass *self,
|
||||
|
||||
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,
|
||||
cairo_image_surface_get_data (surface),
|
||||
cairo_image_surface_get_width (surface),
|
||||
@@ -538,6 +593,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)),
|
||||
@@ -619,6 +685,18 @@ gsk_vulkan_render_pass_count_vertex_data (GskVulkanRenderPass *self)
|
||||
n_bytes += op->render.vertex_count;
|
||||
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:
|
||||
op->render.vertex_count = gsk_vulkan_color_pipeline_count_vertex_data (GSK_VULKAN_COLOR_PIPELINE (op->render.pipeline));
|
||||
n_bytes += op->render.vertex_count;
|
||||
@@ -663,6 +741,7 @@ gsk_vulkan_render_pass_count_vertex_data (GskVulkanRenderPass *self)
|
||||
|
||||
gsize
|
||||
gsk_vulkan_render_pass_collect_vertex_data (GskVulkanRenderPass *self,
|
||||
GskVulkanRender *render,
|
||||
guchar *data,
|
||||
gsize offset,
|
||||
gsize total)
|
||||
@@ -692,6 +771,37 @@ gsk_vulkan_render_pass_collect_vertex_data (GskVulkanRenderPass *self,
|
||||
}
|
||||
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:
|
||||
{
|
||||
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_ROUNDED_CLIP:
|
||||
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_OPACITY:
|
||||
case GSK_VULKAN_OP_BLUR:
|
||||
@@ -910,6 +1022,72 @@ gsk_vulkan_render_pass_draw (GskVulkanRenderPass *self,
|
||||
current_draw_index, 1);
|
||||
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_COLOR_MATRIX:
|
||||
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_collect_vertex_data (GskVulkanRenderPass *self,
|
||||
GskVulkanRender *render,
|
||||
guchar *data,
|
||||
gsize offset,
|
||||
gsize total);
|
||||
|
@@ -34,6 +34,12 @@ typedef enum {
|
||||
GSK_VULKAN_PIPELINE_BLUR,
|
||||
GSK_VULKAN_PIPELINE_BLUR_CLIP,
|
||||
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 */
|
||||
GSK_VULKAN_N_PIPELINES
|
||||
} 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',
|
||||
'gskvulkanclip.c',
|
||||
'gskvulkancolorpipeline.c',
|
||||
'gskvulkancolortextpipeline.c',
|
||||
'gskvulkancommandpool.c',
|
||||
'gskvulkaneffectpipeline.c',
|
||||
'gskvulkanlineargradientpipeline.c',
|
||||
'gskvulkanimage.c',
|
||||
'gskvulkantextpipeline.c',
|
||||
'gskvulkanmemory.c',
|
||||
'gskvulkanpipeline.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',
|
||||
'inset-shadow.frag',
|
||||
'linear.frag',
|
||||
'mask.frag',
|
||||
'outset-shadow.frag',
|
||||
]
|
||||
|
||||
@@ -25,6 +26,7 @@ gsk_private_vulkan_vertex_shaders = [
|
||||
'color-matrix.vert',
|
||||
'inset-shadow.vert',
|
||||
'linear.vert',
|
||||
'mask.vert',
|
||||
'outset-shadow.vert',
|
||||
]
|
||||
|
||||
|
@@ -112,8 +112,6 @@ gsk_pango_renderer_show_text_glyphs (PangoRenderer *renderer,
|
||||
int y)
|
||||
{
|
||||
GskPangoRenderer *crenderer = (GskPangoRenderer *) (renderer);
|
||||
double base_x = (double)x / PANGO_SCALE;
|
||||
double base_y = (double)y / PANGO_SCALE;
|
||||
int x_offset, y_offset;
|
||||
GskRenderNode *node;
|
||||
GdkRGBA color;
|
||||
@@ -121,7 +119,7 @@ gsk_pango_renderer_show_text_glyphs (PangoRenderer *renderer,
|
||||
gtk_snapshot_get_offset (crenderer->snapshot, &x_offset, &y_offset);
|
||||
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)
|
||||
return;
|
||||
|
||||
@@ -132,12 +130,8 @@ gsk_pango_renderer_show_text_glyphs (PangoRenderer *renderer,
|
||||
gsk_render_node_set_name (node, name);
|
||||
}
|
||||
|
||||
gtk_snapshot_offset (crenderer->snapshot, base_x, base_y);
|
||||
|
||||
gtk_snapshot_append_node (crenderer->snapshot, node);
|
||||
gsk_render_node_unref (node);
|
||||
|
||||
gtk_snapshot_offset (crenderer->snapshot, -base_x, -base_y);
|
||||
}
|
||||
|
||||
static void
|
||||
|
Reference in New Issue
Block a user