1 #include "config.h"
2 
3 #include "gskvulkanlineargradientpipelineprivate.h"
4 
5 struct _GskVulkanLinearGradientPipeline
6 {
7   GObject parent_instance;
8 };
9 
10 typedef struct _GskVulkanLinearGradientInstance GskVulkanLinearGradientInstance;
11 
12 struct _GskVulkanLinearGradientInstance
13 {
14   float rect[4];
15   float start[2];
16   float end[2];
17   gint32 repeating;
18   gint32 stop_count;
19   float offsets[GSK_VULKAN_LINEAR_GRADIENT_PIPELINE_MAX_COLOR_STOPS];
20   float colors[GSK_VULKAN_LINEAR_GRADIENT_PIPELINE_MAX_COLOR_STOPS][4];
21 };
22 
G_DEFINE_TYPE(GskVulkanLinearGradientPipeline,gsk_vulkan_linear_gradient_pipeline,GSK_TYPE_VULKAN_PIPELINE)23 G_DEFINE_TYPE (GskVulkanLinearGradientPipeline, gsk_vulkan_linear_gradient_pipeline, GSK_TYPE_VULKAN_PIPELINE)
24 
25 static const VkPipelineVertexInputStateCreateInfo *
26 gsk_vulkan_linear_gradient_pipeline_get_input_state_create_info (GskVulkanPipeline *self)
27 {
28   static const VkVertexInputBindingDescription vertexBindingDescriptions[] = {
29       {
30           .binding = 0,
31           .stride = sizeof (GskVulkanLinearGradientInstance),
32           .inputRate = VK_VERTEX_INPUT_RATE_INSTANCE
33       }
34   };
35   static const VkVertexInputAttributeDescription vertexInputAttributeDescription[] = {
36       {
37           .location = 0,
38           .binding = 0,
39           .format = VK_FORMAT_R32G32B32A32_SFLOAT,
40           .offset = 0,
41       },
42       {
43           .location = 1,
44           .binding = 0,
45           .format = VK_FORMAT_R32G32_SFLOAT,
46           .offset = G_STRUCT_OFFSET (GskVulkanLinearGradientInstance, start),
47       },
48       {
49           .location = 2,
50           .binding = 0,
51           .format = VK_FORMAT_R32G32_SFLOAT,
52           .offset = G_STRUCT_OFFSET (GskVulkanLinearGradientInstance, end),
53       },
54       {
55           .location = 3,
56           .binding = 0,
57           .format = VK_FORMAT_R32_SINT,
58           .offset = G_STRUCT_OFFSET (GskVulkanLinearGradientInstance, repeating),
59       },
60       {
61           .location = 4,
62           .binding = 0,
63           .format = VK_FORMAT_R32_SINT,
64           .offset = G_STRUCT_OFFSET (GskVulkanLinearGradientInstance, stop_count),
65       },
66       {
67           .location = 5,
68           .binding = 0,
69           .format = VK_FORMAT_R32G32B32A32_SFLOAT,
70           .offset = G_STRUCT_OFFSET (GskVulkanLinearGradientInstance, offsets),
71       },
72       {
73           .location = 6,
74           .binding = 0,
75           .format = VK_FORMAT_R32G32B32A32_SFLOAT,
76           .offset = G_STRUCT_OFFSET (GskVulkanLinearGradientInstance, offsets) + sizeof (float) * 4,
77       },
78       {
79           .location = 7,
80           .binding = 0,
81           .format = VK_FORMAT_R32G32B32A32_SFLOAT,
82           .offset = G_STRUCT_OFFSET (GskVulkanLinearGradientInstance, colors[0]),
83       },
84       {
85           .location = 8,
86           .binding = 0,
87           .format = VK_FORMAT_R32G32B32A32_SFLOAT,
88           .offset = G_STRUCT_OFFSET (GskVulkanLinearGradientInstance, colors[1]),
89       },
90       {
91           .location = 9,
92           .binding = 0,
93           .format = VK_FORMAT_R32G32B32A32_SFLOAT,
94           .offset = G_STRUCT_OFFSET (GskVulkanLinearGradientInstance, colors[2]),
95       },
96       {
97           .location = 10,
98           .binding = 0,
99           .format = VK_FORMAT_R32G32B32A32_SFLOAT,
100           .offset = G_STRUCT_OFFSET (GskVulkanLinearGradientInstance, colors[3]),
101       },
102       {
103           .location = 11,
104           .binding = 0,
105           .format = VK_FORMAT_R32G32B32A32_SFLOAT,
106           .offset = G_STRUCT_OFFSET (GskVulkanLinearGradientInstance, colors[4]),
107       },
108       {
109           .location = 12,
110           .binding = 0,
111           .format = VK_FORMAT_R32G32B32A32_SFLOAT,
112           .offset = G_STRUCT_OFFSET (GskVulkanLinearGradientInstance, colors[5]),
113       },
114       {
115           .location = 13,
116           .binding = 0,
117           .format = VK_FORMAT_R32G32B32A32_SFLOAT,
118           .offset = G_STRUCT_OFFSET (GskVulkanLinearGradientInstance, colors[6]),
119       },
120       {
121           .location = 14,
122           .binding = 0,
123           .format = VK_FORMAT_R32G32B32A32_SFLOAT,
124           .offset = G_STRUCT_OFFSET (GskVulkanLinearGradientInstance, colors[7]),
125       }
126   };
127   static const VkPipelineVertexInputStateCreateInfo info = {
128       .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
129       .vertexBindingDescriptionCount = G_N_ELEMENTS (vertexBindingDescriptions),
130       .pVertexBindingDescriptions = vertexBindingDescriptions,
131       .vertexAttributeDescriptionCount = G_N_ELEMENTS (vertexInputAttributeDescription),
132       .pVertexAttributeDescriptions = vertexInputAttributeDescription
133   };
134 
135   return &info;
136 }
137 
138 static void
gsk_vulkan_linear_gradient_pipeline_finalize(GObject * gobject)139 gsk_vulkan_linear_gradient_pipeline_finalize (GObject *gobject)
140 {
141   //GskVulkanLinearGradientPipeline *self = GSK_VULKAN_LINEAR_GRADIENT_PIPELINE (gobject);
142 
143   G_OBJECT_CLASS (gsk_vulkan_linear_gradient_pipeline_parent_class)->finalize (gobject);
144 }
145 
146 static void
gsk_vulkan_linear_gradient_pipeline_class_init(GskVulkanLinearGradientPipelineClass * klass)147 gsk_vulkan_linear_gradient_pipeline_class_init (GskVulkanLinearGradientPipelineClass *klass)
148 {
149   GskVulkanPipelineClass *pipeline_class = GSK_VULKAN_PIPELINE_CLASS (klass);
150 
151   G_OBJECT_CLASS (klass)->finalize = gsk_vulkan_linear_gradient_pipeline_finalize;
152 
153   pipeline_class->get_input_state_create_info = gsk_vulkan_linear_gradient_pipeline_get_input_state_create_info;
154 }
155 
156 static void
gsk_vulkan_linear_gradient_pipeline_init(GskVulkanLinearGradientPipeline * self)157 gsk_vulkan_linear_gradient_pipeline_init (GskVulkanLinearGradientPipeline *self)
158 {
159 }
160 
161 GskVulkanPipeline *
gsk_vulkan_linear_gradient_pipeline_new(GdkVulkanContext * context,VkPipelineLayout layout,const char * shader_name,VkRenderPass render_pass)162 gsk_vulkan_linear_gradient_pipeline_new (GdkVulkanContext        *context,
163                                          VkPipelineLayout         layout,
164                                          const char              *shader_name,
165                                          VkRenderPass             render_pass)
166 {
167   return gsk_vulkan_pipeline_new (GSK_TYPE_VULKAN_LINEAR_GRADIENT_PIPELINE, context, layout, shader_name, render_pass);
168 }
169 
170 gsize
gsk_vulkan_linear_gradient_pipeline_count_vertex_data(GskVulkanLinearGradientPipeline * pipeline)171 gsk_vulkan_linear_gradient_pipeline_count_vertex_data (GskVulkanLinearGradientPipeline *pipeline)
172 {
173   return sizeof (GskVulkanLinearGradientInstance);
174 }
175 
176 void
gsk_vulkan_linear_gradient_pipeline_collect_vertex_data(GskVulkanLinearGradientPipeline * pipeline,guchar * data,const graphene_rect_t * rect,const graphene_point_t * start,const graphene_point_t * end,gboolean repeating,gsize n_stops,const GskColorStop * stops)177 gsk_vulkan_linear_gradient_pipeline_collect_vertex_data (GskVulkanLinearGradientPipeline *pipeline,
178                                                          guchar                    *data,
179                                                          const graphene_rect_t     *rect,
180                                                          const graphene_point_t    *start,
181                                                          const graphene_point_t    *end,
182                                                          gboolean                   repeating,
183                                                          gsize                      n_stops,
184                                                          const GskColorStop        *stops)
185 {
186   GskVulkanLinearGradientInstance *instance = (GskVulkanLinearGradientInstance *) data;
187   gsize i;
188 
189   if (n_stops > GSK_VULKAN_LINEAR_GRADIENT_PIPELINE_MAX_COLOR_STOPS)
190     {
191       g_warning ("Only %u color stops supported.", GSK_VULKAN_LINEAR_GRADIENT_PIPELINE_MAX_COLOR_STOPS);
192       n_stops = GSK_VULKAN_LINEAR_GRADIENT_PIPELINE_MAX_COLOR_STOPS;
193     }
194   instance->rect[0] = rect->origin.x;
195   instance->rect[1] = rect->origin.y;
196   instance->rect[2] = rect->size.width;
197   instance->rect[3] = rect->size.height;
198   instance->start[0] = start->x;
199   instance->start[1] = start->y;
200   instance->end[0] = end->x;
201   instance->end[1] = end->y;
202   instance->repeating = repeating;
203   instance->stop_count = n_stops;
204   for (i = 0; i < n_stops; i++)
205     {
206       instance->offsets[i] = stops[i].offset;
207       instance->colors[i][0] = stops[i].color.red;
208       instance->colors[i][1] = stops[i].color.green;
209       instance->colors[i][2] = stops[i].color.blue;
210       instance->colors[i][3] = stops[i].color.alpha;
211     }
212 }
213 
214 gsize
gsk_vulkan_linear_gradient_pipeline_draw(GskVulkanLinearGradientPipeline * pipeline,VkCommandBuffer command_buffer,gsize offset,gsize n_commands)215 gsk_vulkan_linear_gradient_pipeline_draw (GskVulkanLinearGradientPipeline *pipeline,
216                                    VkCommandBuffer            command_buffer,
217                                    gsize                      offset,
218                                    gsize                      n_commands)
219 {
220   vkCmdDraw (command_buffer,
221              6, n_commands,
222              0, offset);
223 
224   return n_commands;
225 }
226