More work on text nodes

This commit takes several steps towards rendering text
like we want to.

The creation of the cairo surface and texture is moved
to the backend (in GskVulkanRenderer). We add a mask
shader that is used in the next text pipeline to use
the texture as a mask, like cairo_mask_surface does.
There is a separate color text pipeline that uses the
already existing blend shaders to use the texture as
a source, like cairo_paint does.

The text node api is simplified to have just a single
offset, which determines the left end of the text baseline,
like all our other text drawing APIs.
This commit is contained in:
Matthias Clasen 2017-09-01 16:58:42 -04:00
parent edc73e78b8
commit b0e8d8483d
28 changed files with 954 additions and 91 deletions

View File

@ -15,3 +15,23 @@ gsk_ensure_resources (void)
g_once (&register_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;
}

View File

@ -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__ */

View File

@ -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,

View File

@ -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,11 @@ 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;
};
static void
@ -3830,20 +3826,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 +3839,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 +3865,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,11 +3884,10 @@ 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))"
#define GSK_TEXT_NODE_VARIANT_TYPE "(sdddddda(uiiii))"
static GVariant *
gsk_text_node_serialize (GskRenderNode *node)
@ -3935,10 +3919,8 @@ gsk_text_node_serialize (GskRenderNode *node)
self->color.green,
self->color.blue,
self->color.alpha,
self->x_offset,
self->y_offset,
self->base_x,
self->base_y,
self->x,
self->y,
&builder);
g_free (s);
@ -3962,18 +3944,15 @@ gsk_text_node_deserialize (GVariant *variant,
int cluster_start;
char *s;
GdkRGBA color;
int x_offset, y_offset;
double base_x, base_y;
double x, 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);
&s, &color.red, &color.green, &color.blue, &color.alpha,
&x, &y, &iter);
desc = pango_font_description_from_string (s);
fontmap = pango_cairo_font_map_get_default ();
@ -3983,16 +3962,17 @@ gsk_text_node_deserialize (GVariant *variant,
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))
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);
result = gsk_text_node_new (font, glyphs, &color, x, y); /* FIXME: Avoid copying glyphs */
pango_glyph_string_free (glyphs);
pango_font_description_free (desc);
@ -4012,31 +3992,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 +4014,68 @@ 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;
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;

View File

@ -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);

View File

@ -0,0 +1,161 @@
#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;
GskGlyphCoords *coords;
/* XXX */
ink_rect_y = rect->origin.y - y;
ink_rect_height = rect->size.height;
coords = g_new (GskGlyphCoords, glyphs->num_glyphs);
gsk_vulkan_renderer_get_glyph_coords (renderer, font, glyphs, coords);
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;
instance->tex_rect[0] = coords[i].x;
instance->tex_rect[1] = coords[i].y;
instance->tex_rect[2] = coords[i].width;
instance->tex_rect[3] = coords[i].height;
count++;
}
}
x_position += gi->geometry.width;
}
g_free (coords);
}
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;
}

View 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__ */

View File

@ -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

View File

@ -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);

View File

@ -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);

View File

@ -44,6 +44,8 @@ struct _GskVulkanRenderer
GSList *textures;
GHashTable *glyph_cache;
#ifdef G_ENABLE_DEBUG
ProfileTimers profile_timers;
#endif
@ -343,3 +345,142 @@ 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))
static void
render_text (cairo_t *cr,
PangoFont *font,
PangoGlyphString *glyphs,
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;
count++;
}
}
x_position += gi->geometry.width;
}
cairo_show_glyphs (cr, cairo_glyphs, count);
if (cairo_glyphs != stack_glyphs)
g_free (cairo_glyphs);
}
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;
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, 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);
return image;
}
static void
place_text (PangoFont *font,
PangoGlyphString *glyphs,
GskGlyphCoords *coords,
float x,
float y,
float width,
float height)
{
int i;
int x_position = 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;
if (!(gi->glyph & PANGO_GLYPH_UNKNOWN_FLAG))
{
coords[i].glyph = gi->glyph;
coords[i].x = cx / width;
coords[i].y = 0.0;
coords[i].width = (float)gi->geometry.width / (PANGO_SCALE * width);
coords[i].height = 1.0; // FIXME get actual glyph height
}
}
x_position += gi->geometry.width;
}
}
void
gsk_vulkan_renderer_get_glyph_coords (GskVulkanRenderer *self,
PangoFont *font,
PangoGlyphString *glyphs,
GskGlyphCoords *coords)
{
PangoRectangle ink_rect;
pango_glyph_string_extents (glyphs, font, &ink_rect, NULL);
pango_extents_to_pixels (&ink_rect, NULL);
place_text (font, glyphs, coords, 0, - ink_rect.y, ink_rect.x + ink_rect.width, ink_rect.height);
}

View File

@ -25,6 +25,20 @@ GskVulkanImage * gsk_vulkan_renderer_ref_texture_image (GskVulk
GskTexture *texture,
GskVulkanUploader *uploader);
typedef struct {
PangoGlyph glyph;
float x, y, width, height;
} GskGlyphCoords;
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,
GskGlyphCoords *coords);
G_END_DECLS
#endif /* __GSK_VULKAN_RENDERER_PRIVATE_H__ */

View File

@ -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)

View File

@ -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);

View File

@ -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;

173
gsk/gskvulkantextpipeline.c Normal file
View File

@ -0,0 +1,173 @@
#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;
GskGlyphCoords *coords;
/* XXX */
ink_rect_y = rect->origin.y - y;
ink_rect_height = rect->size.height;
coords = g_new (GskGlyphCoords, glyphs->num_glyphs);
gsk_vulkan_renderer_get_glyph_coords (renderer, font, glyphs, coords);
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;
instance->tex_rect[0] = coords[i].x;
instance->tex_rect[1] = coords[i].y;
instance->tex_rect[2] = coords[i].width;
instance->tex_rect[3] = coords[i].height;
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;
}
g_free (coords);
}
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;
}

View 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__ */

View File

@ -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',

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View 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));
}

Binary file not shown.

View 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;
}

Binary file not shown.

View File

@ -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',
]

View File

@ -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