1 /*
2 * GStreamer
3 * Copyright (C) 2015 Matthew Waters <matthew@centricular.com>
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19 */
20
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25 #include "vkimagememory.h"
26
27 /**
28 * SECTION:vkimagememory
29 * @title: GstVkImageMemory
30 * @short_description: memory subclass for Vulkan image memory
31 * @see_also: #GstMemory, #GstAllocator
32 *
33 * GstVulkanImageMemory is a #GstMemory subclass providing support for the
34 * mapping of Vulkan device memory.
35 */
36
37 #define GST_CAT_DEFUALT GST_CAT_VULKAN_IMAGE_MEMORY
38 GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFUALT);
39
40 static GstAllocator *_vulkan_image_memory_allocator;
41
42 VkFormat
gst_vulkan_format_from_video_format(GstVideoFormat v_format,guint plane)43 gst_vulkan_format_from_video_format (GstVideoFormat v_format, guint plane)
44 {
45 guint n_plane_components;
46
47 switch (v_format) {
48 case GST_VIDEO_FORMAT_RGBx:
49 case GST_VIDEO_FORMAT_BGRx:
50 case GST_VIDEO_FORMAT_xRGB:
51 case GST_VIDEO_FORMAT_xBGR:
52 case GST_VIDEO_FORMAT_RGBA:
53 case GST_VIDEO_FORMAT_BGRA:
54 case GST_VIDEO_FORMAT_ARGB:
55 case GST_VIDEO_FORMAT_ABGR:
56 case GST_VIDEO_FORMAT_AYUV:
57 n_plane_components = 4;
58 break;
59 case GST_VIDEO_FORMAT_RGB:
60 case GST_VIDEO_FORMAT_BGR:
61 n_plane_components = 3;
62 break;
63 case GST_VIDEO_FORMAT_RGB16:
64 case GST_VIDEO_FORMAT_BGR16:
65 return VK_FORMAT_R5G6B5_UNORM_PACK16;
66 case GST_VIDEO_FORMAT_GRAY16_BE:
67 case GST_VIDEO_FORMAT_GRAY16_LE:
68 case GST_VIDEO_FORMAT_YUY2:
69 case GST_VIDEO_FORMAT_UYVY:
70 n_plane_components = 2;
71 break;
72 case GST_VIDEO_FORMAT_NV12:
73 case GST_VIDEO_FORMAT_NV21:
74 n_plane_components = plane == 0 ? 1 : 2;
75 break;
76 case GST_VIDEO_FORMAT_GRAY8:
77 case GST_VIDEO_FORMAT_Y444:
78 case GST_VIDEO_FORMAT_Y42B:
79 case GST_VIDEO_FORMAT_Y41B:
80 case GST_VIDEO_FORMAT_I420:
81 case GST_VIDEO_FORMAT_YV12:
82 n_plane_components = 1;
83 break;
84 default:
85 n_plane_components = 4;
86 g_assert_not_reached ();
87 break;
88 }
89
90 switch (n_plane_components) {
91 case 4:
92 return VK_FORMAT_R8G8B8A8_UNORM;
93 case 3:
94 return VK_FORMAT_R8G8B8_UNORM;
95 case 2:
96 return VK_FORMAT_R8G8_UNORM;
97 case 1:
98 return VK_FORMAT_R8_UNORM;
99 default:
100 g_assert_not_reached ();
101 return VK_FORMAT_R8G8B8A8_UNORM;
102 }
103 }
104
105 static void
_view_create_info(VkImage image,VkFormat format,VkImageViewCreateInfo * info)106 _view_create_info (VkImage image, VkFormat format, VkImageViewCreateInfo * info)
107 {
108 info->sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
109 info->pNext = NULL;
110 info->image = image;
111 info->format = format;
112 info->viewType = VK_IMAGE_VIEW_TYPE_2D;
113 info->flags = 0;
114
115 GST_VK_COMPONENT_MAPPING (info->components, VK_COMPONENT_SWIZZLE_R,
116 VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A);
117 GST_VK_IMAGE_SUBRESOURCE_RANGE (info->subresourceRange,
118 VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1);
119 }
120
121 static gboolean
_create_info_from_args(VkImageCreateInfo * info,VkFormat format,gsize width,gsize height,VkImageTiling tiling,VkImageUsageFlags usage)122 _create_info_from_args (VkImageCreateInfo * info, VkFormat format, gsize width,
123 gsize height, VkImageTiling tiling, VkImageUsageFlags usage)
124 {
125 /* FIXME: validate these */
126
127 info->sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
128 info->pNext = NULL;
129 info->flags = 0;
130 info->imageType = VK_IMAGE_TYPE_2D;
131 info->format = format;
132 GST_VK_EXTENT3D (info->extent, width, height, 1);
133 info->mipLevels = 1;
134 info->arrayLayers = 1;
135 info->samples = VK_SAMPLE_COUNT_1_BIT;
136 info->tiling = tiling;
137 info->usage = usage;
138 info->sharingMode = VK_SHARING_MODE_EXCLUSIVE;
139 info->queueFamilyIndexCount = 0;
140 info->pQueueFamilyIndices = NULL;
141 info->initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
142
143 return TRUE;
144 }
145
146 static void
_vk_image_mem_init(GstVulkanImageMemory * mem,GstAllocator * allocator,GstMemory * parent,GstVulkanDevice * device,VkImageUsageFlags usage,GstAllocationParams * params,gsize size,gpointer user_data,GDestroyNotify notify)147 _vk_image_mem_init (GstVulkanImageMemory * mem, GstAllocator * allocator,
148 GstMemory * parent, GstVulkanDevice * device, VkImageUsageFlags usage,
149 GstAllocationParams * params, gsize size, gpointer user_data,
150 GDestroyNotify notify)
151 {
152 gsize align = gst_memory_alignment, offset = 0, maxsize = size;
153 GstMemoryFlags flags = 0;
154
155 if (params) {
156 flags = params->flags;
157 align |= params->align;
158 offset = params->prefix;
159 maxsize += params->prefix + params->padding + align;
160 }
161
162 gst_memory_init (GST_MEMORY_CAST (mem), flags, allocator, parent, maxsize,
163 align, offset, size);
164
165 mem->device = gst_object_ref (device);
166 mem->image_layout = VK_IMAGE_LAYOUT_UNDEFINED;
167 mem->usage = usage;
168 mem->wrapped = FALSE;
169 mem->notify = notify;
170 mem->user_data = user_data;
171
172 g_mutex_init (&mem->lock);
173
174 GST_CAT_DEBUG (GST_CAT_VULKAN_IMAGE_MEMORY,
175 "new Vulkan Image memory:%p size:%" G_GSIZE_FORMAT, mem, maxsize);
176 }
177
178 static GstVulkanImageMemory *
_vk_image_mem_new_alloc(GstAllocator * allocator,GstMemory * parent,GstVulkanDevice * device,VkFormat format,gsize width,gsize height,VkImageTiling tiling,VkImageUsageFlags usage,VkMemoryPropertyFlags mem_prop_flags,gpointer user_data,GDestroyNotify notify)179 _vk_image_mem_new_alloc (GstAllocator * allocator, GstMemory * parent,
180 GstVulkanDevice * device, VkFormat format, gsize width, gsize height,
181 VkImageTiling tiling, VkImageUsageFlags usage,
182 VkMemoryPropertyFlags mem_prop_flags, gpointer user_data,
183 GDestroyNotify notify)
184 {
185 GstVulkanImageMemory *mem = NULL;
186 GstAllocationParams params = { 0, };
187 VkImageViewCreateInfo view_info;
188 VkImageCreateInfo image_info;
189 VkPhysicalDevice gpu;
190 GError *error = NULL;
191 guint32 type_idx;
192 VkImage image;
193 VkResult err;
194
195 gpu = gst_vulkan_device_get_physical_device (device);
196 if (!_create_info_from_args (&image_info, format, width, height, tiling,
197 usage)) {
198 GST_CAT_ERROR (GST_CAT_VULKAN_IMAGE_MEMORY, "Incorrect image parameters");
199 goto error;
200 }
201
202 err = vkCreateImage (device->device, &image_info, NULL, &image);
203 if (gst_vulkan_error_to_g_error (err, &error, "vkCreateImage") < 0)
204 goto vk_error;
205
206 mem = g_new0 (GstVulkanImageMemory, 1);
207 _vk_image_mem_init (mem, allocator, parent, device, usage, ¶ms,
208 mem->requirements.size, user_data, notify);
209 mem->create_info = image_info;
210 mem->image = image;
211
212 vkGetImageMemoryRequirements (device->device, image, &mem->requirements);
213 err = vkGetPhysicalDeviceImageFormatProperties (gpu, format, VK_IMAGE_TYPE_2D,
214 tiling, usage, 0, &mem->format_properties);
215 if (gst_vulkan_error_to_g_error (err, &error,
216 "vkGetPhysicalDeviceImageFormatProperties") < 0)
217 goto vk_error;
218
219 if (!gst_vulkan_memory_find_memory_type_index_with_type_properties (device,
220 mem->requirements.memoryTypeBits, mem_prop_flags, &type_idx))
221 goto error;
222
223 /* XXX: assumes alignment is a power of 2 */
224 params.align = mem->requirements.alignment - 1;
225 mem->vk_mem = (GstVulkanMemory *) gst_vulkan_memory_alloc (device, type_idx,
226 ¶ms, mem->requirements.size, mem_prop_flags);
227 if (!mem->vk_mem)
228 goto error;
229
230 err = vkBindImageMemory (device->device, image, mem->vk_mem->mem_ptr, 0);
231 if (gst_vulkan_error_to_g_error (err, &error, "vkBindImageMemory") < 0)
232 goto vk_error;
233
234 if (usage & (VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT |
235 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT)) {
236 _view_create_info (mem->image, format, &view_info);
237 err = vkCreateImageView (device->device, &view_info, NULL, &mem->view);
238 if (gst_vulkan_error_to_g_error (err, &error, "vkCreateImageView") < 0)
239 goto vk_error;
240 }
241
242 return mem;
243
244 vk_error:
245 {
246 GST_CAT_ERROR (GST_CAT_VULKAN_IMAGE_MEMORY,
247 "Failed to allocate image memory %s", error->message);
248 g_clear_error (&error);
249 goto error;
250 }
251
252 error:
253 {
254 if (mem)
255 gst_memory_unref ((GstMemory *) mem);
256 return NULL;
257 }
258 }
259
260 static GstVulkanImageMemory *
_vk_image_mem_new_wrapped(GstAllocator * allocator,GstMemory * parent,GstVulkanDevice * device,VkImage image,VkFormat format,gsize width,gsize height,VkImageTiling tiling,VkImageUsageFlags usage,gpointer user_data,GDestroyNotify notify)261 _vk_image_mem_new_wrapped (GstAllocator * allocator, GstMemory * parent,
262 GstVulkanDevice * device, VkImage image, VkFormat format, gsize width,
263 gsize height, VkImageTiling tiling, VkImageUsageFlags usage,
264 gpointer user_data, GDestroyNotify notify)
265 {
266 GstVulkanImageMemory *mem = g_new0 (GstVulkanImageMemory, 1);
267 GstAllocationParams params = { 0, };
268 VkImageViewCreateInfo view_info;
269 VkPhysicalDevice gpu;
270 GError *error = NULL;
271 VkResult err;
272
273 gpu = gst_vulkan_device_get_physical_device (device);
274 mem->image = image;
275
276 vkGetImageMemoryRequirements (device->device, mem->image, &mem->requirements);
277
278 /* XXX: assumes alignment is a power of 2 */
279 params.align = mem->requirements.alignment - 1;
280 params.flags = GST_MEMORY_FLAG_NOT_MAPPABLE;
281 _vk_image_mem_init (mem, allocator, parent, device, usage, ¶ms,
282 mem->requirements.size, user_data, notify);
283 mem->wrapped = TRUE;
284
285 if (!_create_info_from_args (&mem->create_info, format, width, height, tiling,
286 usage)) {
287 GST_CAT_ERROR (GST_CAT_VULKAN_IMAGE_MEMORY, "Incorrect image parameters");
288 goto error;
289 }
290
291 err = vkGetPhysicalDeviceImageFormatProperties (gpu, format, VK_IMAGE_TYPE_2D,
292 tiling, usage, 0, &mem->format_properties);
293 if (gst_vulkan_error_to_g_error (err, &error,
294 "vkGetPhysicalDeviceImageFormatProperties") < 0)
295 goto vk_error;
296
297 /* XXX: we don't actually if the image has a vkDeviceMemory bound so
298 * this may fail */
299 if (usage & (VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT |
300 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT)) {
301 _view_create_info (mem->image, format, &view_info);
302 err = vkCreateImageView (device->device, &view_info, NULL, &mem->view);
303 if (gst_vulkan_error_to_g_error (err, &error, "vkCreateImageView") < 0)
304 goto vk_error;
305 }
306
307 return mem;
308
309 vk_error:
310 {
311 GST_CAT_ERROR (GST_CAT_VULKAN_IMAGE_MEMORY,
312 "Failed to allocate image memory %s", error->message);
313 g_clear_error (&error);
314 goto error;
315 }
316
317 error:
318 {
319 gst_memory_unref ((GstMemory *) mem);
320 return NULL;
321 }
322 }
323
324 static gpointer
_vk_image_mem_map_full(GstVulkanImageMemory * mem,GstMapInfo * info,gsize size)325 _vk_image_mem_map_full (GstVulkanImageMemory * mem, GstMapInfo * info,
326 gsize size)
327 {
328 GstMapInfo *vk_map_info;
329
330 /* FIXME: possible layout transformation needed */
331 g_mutex_lock (&mem->lock);
332
333 if (!mem->vk_mem) {
334 g_mutex_unlock (&mem->lock);
335 return NULL;
336 }
337
338 vk_map_info = g_new0 (GstMapInfo, 1);
339 info->user_data[0] = vk_map_info;
340 if (!gst_memory_map ((GstMemory *) mem->vk_mem, vk_map_info, info->flags)) {
341 g_free (vk_map_info);
342 g_mutex_unlock (&mem->lock);
343 return NULL;
344 }
345 g_mutex_unlock (&mem->lock);
346
347 return vk_map_info->data;
348 }
349
350 static void
_vk_image_mem_unmap_full(GstVulkanImageMemory * mem,GstMapInfo * info)351 _vk_image_mem_unmap_full (GstVulkanImageMemory * mem, GstMapInfo * info)
352 {
353 g_mutex_lock (&mem->lock);
354 gst_memory_unmap ((GstMemory *) mem->vk_mem, info->user_data[0]);
355 g_mutex_unlock (&mem->lock);
356
357 g_free (info->user_data[0]);
358 }
359
360 static GstMemory *
_vk_image_mem_copy(GstVulkanImageMemory * src,gssize offset,gssize size)361 _vk_image_mem_copy (GstVulkanImageMemory * src, gssize offset, gssize size)
362 {
363 return NULL;
364 }
365
366 static GstMemory *
_vk_image_mem_share(GstVulkanImageMemory * mem,gssize offset,gssize size)367 _vk_image_mem_share (GstVulkanImageMemory * mem, gssize offset, gssize size)
368 {
369 return NULL;
370 }
371
372 static gboolean
_vk_image_mem_is_span(GstVulkanImageMemory * mem1,GstVulkanImageMemory * mem2,gsize * offset)373 _vk_image_mem_is_span (GstVulkanImageMemory * mem1, GstVulkanImageMemory * mem2,
374 gsize * offset)
375 {
376 return FALSE;
377 }
378
379 static GstMemory *
_vk_image_mem_alloc(GstAllocator * allocator,gsize size,GstAllocationParams * params)380 _vk_image_mem_alloc (GstAllocator * allocator, gsize size,
381 GstAllocationParams * params)
382 {
383 g_critical ("Subclass should override GstAllocatorClass::alloc() function");
384
385 return NULL;
386 }
387
388 static void
_vk_image_mem_free(GstAllocator * allocator,GstMemory * memory)389 _vk_image_mem_free (GstAllocator * allocator, GstMemory * memory)
390 {
391 GstVulkanImageMemory *mem = (GstVulkanImageMemory *) memory;
392
393 GST_CAT_TRACE (GST_CAT_VULKAN_IMAGE_MEMORY, "freeing image memory:%p "
394 "id:%" G_GUINT64_FORMAT, mem, (guint64) mem->image);
395
396 if (mem->image && !mem->wrapped)
397 vkDestroyImage (mem->device->device, mem->image, NULL);
398
399 if (mem->view)
400 vkDestroyImageView (mem->device->device, mem->view, NULL);
401
402 if (mem->vk_mem)
403 gst_memory_unref ((GstMemory *) mem->vk_mem);
404
405 if (mem->notify)
406 mem->notify (mem->user_data);
407
408 gst_object_unref (mem->device);
409
410 g_free (mem);
411 }
412
413 static VkAccessFlags
_access_flags_from_layout(VkImageLayout image_layout)414 _access_flags_from_layout (VkImageLayout image_layout)
415 {
416 if (image_layout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL)
417 return VK_ACCESS_TRANSFER_WRITE_BIT;
418
419 if (image_layout == VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL)
420 return VK_ACCESS_TRANSFER_READ_BIT;
421
422 if (image_layout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL)
423 return VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
424
425 if (image_layout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL)
426 return VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
427
428 if (image_layout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)
429 return VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_INPUT_ATTACHMENT_READ_BIT;
430
431 return 0;
432 }
433
434 gboolean
gst_vulkan_image_memory_set_layout(GstVulkanImageMemory * vk_mem,VkImageLayout image_layout,VkImageMemoryBarrier * barrier)435 gst_vulkan_image_memory_set_layout (GstVulkanImageMemory * vk_mem,
436 VkImageLayout image_layout, VkImageMemoryBarrier * barrier)
437 {
438 /* validate vk_mem->usage with image_layout */
439
440 barrier->sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
441 barrier->pNext = NULL;
442 barrier->dstAccessMask = _access_flags_from_layout (image_layout);
443 barrier->srcAccessMask = _access_flags_from_layout (vk_mem->image_layout);
444 barrier->oldLayout = vk_mem->image_layout;
445 barrier->newLayout = image_layout;
446 barrier->srcQueueFamilyIndex = 0;
447 barrier->dstQueueFamilyIndex = 0;
448 barrier->image = vk_mem->image;
449 GST_VK_IMAGE_SUBRESOURCE_RANGE (barrier->subresourceRange,
450 VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1);
451
452 /* FIXME: what if the barrier is never submitted or is submitted out of order? */
453 vk_mem->image_layout = image_layout;
454
455 return TRUE;
456 }
457
458 /**
459 * gst_vulkan_image_memory_alloc:
460 *
461 * Allocated a new #GstVulkanImageMemory.
462 *
463 * Returns: a #GstMemory object backed by a vulkan device memory
464 */
465 GstMemory *
gst_vulkan_image_memory_alloc(GstVulkanDevice * device,VkFormat format,gsize width,gsize height,VkImageTiling tiling,VkImageUsageFlags usage,VkMemoryPropertyFlags mem_prop_flags)466 gst_vulkan_image_memory_alloc (GstVulkanDevice * device, VkFormat format,
467 gsize width, gsize height, VkImageTiling tiling, VkImageUsageFlags usage,
468 VkMemoryPropertyFlags mem_prop_flags)
469 {
470 GstVulkanImageMemory *mem;
471
472 mem = _vk_image_mem_new_alloc (_vulkan_image_memory_allocator, NULL, device,
473 format, width, height, tiling, usage, mem_prop_flags, NULL, NULL);
474
475 return (GstMemory *) mem;
476 }
477
478 GstMemory *
gst_vulkan_image_memory_wrapped(GstVulkanDevice * device,VkImage image,VkFormat format,gsize width,gsize height,VkImageTiling tiling,VkImageUsageFlags usage,gpointer user_data,GDestroyNotify notify)479 gst_vulkan_image_memory_wrapped (GstVulkanDevice * device, VkImage image,
480 VkFormat format, gsize width, gsize height, VkImageTiling tiling,
481 VkImageUsageFlags usage, gpointer user_data, GDestroyNotify notify)
482 {
483 GstVulkanImageMemory *mem;
484
485 mem = _vk_image_mem_new_wrapped (_vulkan_image_memory_allocator, NULL, device,
486 image, format, width, height, tiling, usage, user_data, notify);
487
488 return (GstMemory *) mem;
489 }
490
491 guint32
gst_vulkan_image_memory_get_width(GstVulkanImageMemory * image)492 gst_vulkan_image_memory_get_width (GstVulkanImageMemory * image)
493 {
494 g_return_val_if_fail (gst_is_vulkan_image_memory (GST_MEMORY_CAST (image)),
495 0);
496
497 return image->create_info.extent.width;
498 }
499
500 guint32
gst_vulkan_image_memory_get_height(GstVulkanImageMemory * image)501 gst_vulkan_image_memory_get_height (GstVulkanImageMemory * image)
502 {
503 g_return_val_if_fail (gst_is_vulkan_image_memory (GST_MEMORY_CAST (image)),
504 0);
505
506 return image->create_info.extent.height;
507 }
508
509 G_DEFINE_TYPE (GstVulkanImageMemoryAllocator, gst_vulkan_image_memory_allocator,
510 GST_TYPE_ALLOCATOR);
511
512 static void
gst_vulkan_image_memory_allocator_class_init(GstVulkanImageMemoryAllocatorClass * klass)513 gst_vulkan_image_memory_allocator_class_init (GstVulkanImageMemoryAllocatorClass
514 * klass)
515 {
516 GstAllocatorClass *allocator_class = (GstAllocatorClass *) klass;
517
518 allocator_class->alloc = _vk_image_mem_alloc;
519 allocator_class->free = _vk_image_mem_free;
520 }
521
522 static void
gst_vulkan_image_memory_allocator_init(GstVulkanImageMemoryAllocator * allocator)523 gst_vulkan_image_memory_allocator_init (GstVulkanImageMemoryAllocator *
524 allocator)
525 {
526 GstAllocator *alloc = GST_ALLOCATOR_CAST (allocator);
527
528 alloc->mem_type = GST_VULKAN_IMAGE_MEMORY_ALLOCATOR_NAME;
529 alloc->mem_map_full = (GstMemoryMapFullFunction) _vk_image_mem_map_full;
530 alloc->mem_unmap_full = (GstMemoryUnmapFullFunction) _vk_image_mem_unmap_full;
531 alloc->mem_copy = (GstMemoryCopyFunction) _vk_image_mem_copy;
532 alloc->mem_share = (GstMemoryShareFunction) _vk_image_mem_share;
533 alloc->mem_is_span = (GstMemoryIsSpanFunction) _vk_image_mem_is_span;
534 }
535
536 /**
537 * gst_vulkan_image_memory_init_once:
538 *
539 * Initializes the Vulkan memory allocator. It is safe to call this function
540 * multiple times. This must be called before any other #GstVulkanImageMemory operation.
541 */
542 void
gst_vulkan_image_memory_init_once(void)543 gst_vulkan_image_memory_init_once (void)
544 {
545 static volatile gsize _init = 0;
546
547 if (g_once_init_enter (&_init)) {
548 GST_DEBUG_CATEGORY_INIT (GST_CAT_VULKAN_IMAGE_MEMORY, "vulkanimagememory",
549 0, "Vulkan Image Memory");
550
551 _vulkan_image_memory_allocator =
552 g_object_new (gst_vulkan_image_memory_allocator_get_type (), NULL);
553 gst_object_ref_sink (_vulkan_image_memory_allocator);
554
555 gst_allocator_register (GST_VULKAN_IMAGE_MEMORY_ALLOCATOR_NAME,
556 gst_object_ref (_vulkan_image_memory_allocator));
557 g_once_init_leave (&_init, 1);
558 }
559 }
560
561 /**
562 * gst_is_vulkan_image_memory:
563 * @mem:a #GstMemory
564 *
565 * Returns: whether the memory at @mem is a #GstVulkanImageMemory
566 */
567 gboolean
gst_is_vulkan_image_memory(GstMemory * mem)568 gst_is_vulkan_image_memory (GstMemory * mem)
569 {
570 return mem != NULL && mem->allocator != NULL &&
571 g_type_is_a (G_OBJECT_TYPE (mem->allocator),
572 GST_TYPE_VULKAN_IMAGE_MEMORY_ALLOCATOR);
573 }
574