1 #include "config.h"
2 
3 #include "gskvulkantextpipelineprivate.h"
4 
5 struct _GskVulkanTextPipeline
6 {
7   GObject parent_instance;
8 };
9 
10 typedef struct _GskVulkanTextInstance GskVulkanTextInstance;
11 
12 struct _GskVulkanTextInstance
13 {
14   float rect[4];
15   float tex_rect[4];
16   float color[4];
17 };
18 
G_DEFINE_TYPE(GskVulkanTextPipeline,gsk_vulkan_text_pipeline,GSK_TYPE_VULKAN_PIPELINE)19 G_DEFINE_TYPE (GskVulkanTextPipeline, gsk_vulkan_text_pipeline, GSK_TYPE_VULKAN_PIPELINE)
20 
21 static const VkPipelineVertexInputStateCreateInfo *
22 gsk_vulkan_text_pipeline_get_input_state_create_info (GskVulkanPipeline *self)
23 {
24   static const VkVertexInputBindingDescription vertexBindingDescriptions[] = {
25       {
26           .binding = 0,
27           .stride = sizeof (GskVulkanTextInstance),
28           .inputRate = VK_VERTEX_INPUT_RATE_INSTANCE
29       }
30   };
31   static const VkVertexInputAttributeDescription vertexInputAttributeDescription[] = {
32       {
33           .location = 0,
34           .binding = 0,
35           .format = VK_FORMAT_R32G32B32A32_SFLOAT,
36           .offset = G_STRUCT_OFFSET (GskVulkanTextInstance, rect),
37       },
38       {
39           .location = 1,
40           .binding = 0,
41           .format = VK_FORMAT_R32G32B32A32_SFLOAT,
42           .offset = G_STRUCT_OFFSET (GskVulkanTextInstance, tex_rect),
43       },
44       {
45           .location = 2,
46           .binding = 0,
47           .format = VK_FORMAT_R32G32B32A32_SFLOAT,
48           .offset = G_STRUCT_OFFSET (GskVulkanTextInstance, color),
49       }
50   };
51   static const VkPipelineVertexInputStateCreateInfo info = {
52       .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
53       .vertexBindingDescriptionCount = G_N_ELEMENTS (vertexBindingDescriptions),
54       .pVertexBindingDescriptions = vertexBindingDescriptions,
55       .vertexAttributeDescriptionCount = G_N_ELEMENTS (vertexInputAttributeDescription),
56       .pVertexAttributeDescriptions = vertexInputAttributeDescription
57   };
58 
59   return &info;
60 }
61 
62 static void
gsk_vulkan_text_pipeline_finalize(GObject * gobject)63 gsk_vulkan_text_pipeline_finalize (GObject *gobject)
64 {
65   //GskVulkanTextPipeline *self = GSK_VULKAN_TEXT_PIPELINE (gobject);
66 
67   G_OBJECT_CLASS (gsk_vulkan_text_pipeline_parent_class)->finalize (gobject);
68 }
69 
70 static void
gsk_vulkan_text_pipeline_class_init(GskVulkanTextPipelineClass * klass)71 gsk_vulkan_text_pipeline_class_init (GskVulkanTextPipelineClass *klass)
72 {
73   GskVulkanPipelineClass *pipeline_class = GSK_VULKAN_PIPELINE_CLASS (klass);
74 
75   G_OBJECT_CLASS (klass)->finalize = gsk_vulkan_text_pipeline_finalize;
76 
77   pipeline_class->get_input_state_create_info = gsk_vulkan_text_pipeline_get_input_state_create_info;
78 }
79 
80 static void
gsk_vulkan_text_pipeline_init(GskVulkanTextPipeline * self)81 gsk_vulkan_text_pipeline_init (GskVulkanTextPipeline *self)
82 {
83 }
84 
85 GskVulkanPipeline *
gsk_vulkan_text_pipeline_new(GdkVulkanContext * context,VkPipelineLayout layout,const char * shader_name,VkRenderPass render_pass)86 gsk_vulkan_text_pipeline_new (GdkVulkanContext        *context,
87                               VkPipelineLayout         layout,
88                               const char              *shader_name,
89                               VkRenderPass             render_pass)
90 {
91   return gsk_vulkan_pipeline_new_full (GSK_TYPE_VULKAN_TEXT_PIPELINE, context, layout, shader_name, render_pass,
92                                        VK_BLEND_FACTOR_SRC_ALPHA, VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA);
93 }
94 
95 gsize
gsk_vulkan_text_pipeline_count_vertex_data(GskVulkanTextPipeline * pipeline,int num_instances)96 gsk_vulkan_text_pipeline_count_vertex_data (GskVulkanTextPipeline *pipeline,
97                                             int                    num_instances)
98 {
99   return sizeof (GskVulkanTextInstance) * num_instances;
100 }
101 
102 void
gsk_vulkan_text_pipeline_collect_vertex_data(GskVulkanTextPipeline * pipeline,guchar * data,GskVulkanRenderer * renderer,const graphene_rect_t * rect,PangoFont * font,guint total_glyphs,const PangoGlyphInfo * glyphs,const GdkRGBA * color,const graphene_point_t * offset,guint start_glyph,guint num_glyphs,float scale)103 gsk_vulkan_text_pipeline_collect_vertex_data (GskVulkanTextPipeline  *pipeline,
104                                               guchar                 *data,
105                                               GskVulkanRenderer      *renderer,
106                                               const graphene_rect_t  *rect,
107                                               PangoFont              *font,
108                                               guint                   total_glyphs,
109                                               const PangoGlyphInfo   *glyphs,
110                                               const GdkRGBA          *color,
111                                               const graphene_point_t *offset,
112                                               guint                   start_glyph,
113                                               guint                   num_glyphs,
114                                               float                   scale)
115 {
116   GskVulkanTextInstance *instances = (GskVulkanTextInstance *) data;
117   int i;
118   int count = 0;
119   int x_position = 0;
120 
121   for (i = 0; i < start_glyph; i++)
122     x_position += glyphs[i].geometry.width;
123 
124   for (; i < total_glyphs && count < num_glyphs; i++)
125     {
126       const PangoGlyphInfo *gi = &glyphs[i];
127 
128       if (gi->glyph != PANGO_GLYPH_EMPTY)
129         {
130           double cx = (x_position + gi->geometry.x_offset) / PANGO_SCALE;
131           double cy = gi->geometry.y_offset / PANGO_SCALE;
132           GskVulkanTextInstance *instance = &instances[count];
133           GskVulkanCachedGlyph *glyph;
134 
135           glyph = gsk_vulkan_renderer_get_cached_glyph (renderer,
136                                                         font,
137                                                         gi->glyph,
138                                                         x_position + gi->geometry.x_offset,
139                                                         gi->geometry.y_offset,
140                                                         scale);
141 
142           instance->tex_rect[0] = glyph->tx;
143           instance->tex_rect[1] = glyph->ty;
144           instance->tex_rect[2] = glyph->tw;
145           instance->tex_rect[3] = glyph->th;
146 
147           instance->rect[0] = offset->x + cx + glyph->draw_x;
148           instance->rect[1] = offset->y + cy + glyph->draw_y;
149           instance->rect[2] = glyph->draw_width;
150           instance->rect[3] = glyph->draw_height;
151 
152           instance->color[0] = color->red;
153           instance->color[1] = color->green;
154           instance->color[2] = color->blue;
155           instance->color[3] = color->alpha;
156 
157           count++;
158         }
159       x_position += gi->geometry.width;
160     }
161 }
162 
163 gsize
gsk_vulkan_text_pipeline_draw(GskVulkanTextPipeline * pipeline,VkCommandBuffer command_buffer,gsize offset,gsize n_commands)164 gsk_vulkan_text_pipeline_draw (GskVulkanTextPipeline *pipeline,
165                                VkCommandBuffer        command_buffer,
166                                gsize                  offset,
167                                gsize                  n_commands)
168 {
169   vkCmdDraw (command_buffer,
170              6, n_commands,
171              0, offset);
172 
173   return n_commands;
174 }
175