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 <string.h>
26
27 #include "gstglbasememory.h"
28
29 #include "gstglcontext.h"
30 #include "gstglcontext_private.h"
31 #include "gstglquery.h"
32
33 /**
34 * SECTION:gstglbasememory
35 * @title: GstGLBaseMemory
36 * @short_description: memory subclass for GL buffers
37 * @see_also: #GstMemory, #GstAllocator
38 *
39 * GstGLBaseMemory is a #GstMemory subclass providing the basis of support
40 * for the mapping of GL buffers.
41 *
42 * Data is uploaded or downloaded from the GPU as is necessary.
43 */
44
45 #define USING_OPENGL(context) (gst_gl_context_check_gl_version (context, GST_GL_API_OPENGL, 1, 0))
46 #define USING_OPENGL3(context) (gst_gl_context_check_gl_version (context, GST_GL_API_OPENGL3, 3, 1))
47 #define USING_GLES(context) (gst_gl_context_check_gl_version (context, GST_GL_API_GLES, 1, 0))
48 #define USING_GLES2(context) (gst_gl_context_check_gl_version (context, GST_GL_API_GLES2, 2, 0))
49 #define USING_GLES3(context) (gst_gl_context_check_gl_version (context, GST_GL_API_GLES2, 3, 0))
50
51 GST_DEBUG_CATEGORY_STATIC (GST_CAT_GL_BASE_MEMORY);
52 #define GST_CAT_DEFUALT GST_CAT_GL_BASE_MEMORY
53
54 GST_DEFINE_MINI_OBJECT_TYPE (GstGLBaseMemory, gst_gl_base_memory);
55
56 /**
57 * gst_gl_base_memory_error_quark:
58 *
59 * Returns: the quark used for #GstGLBaseMemory in #GError's
60 */
61 GQuark
gst_gl_base_memory_error_quark(void)62 gst_gl_base_memory_error_quark (void)
63 {
64 return g_quark_from_static_string ("gst-gl-base-memory-error-quark");
65 }
66
67 static gboolean
_default_create(GstGLBaseMemory * mem,GError ** error)68 _default_create (GstGLBaseMemory * mem, GError ** error)
69 {
70 g_set_error (error, GST_GL_BASE_MEMORY_ERROR, GST_GL_BASE_MEMORY_ERROR_FAILED,
71 "subclass should define create() vfunc");
72
73 g_critical ("subclass should override "
74 "GstGLBaseMemoryAllocatorClass::create() function");
75
76 return FALSE;
77 }
78
79 struct create_data
80 {
81 GstGLBaseMemory *mem;
82 gboolean result;
83 };
84
85 static void
_mem_create_gl(GstGLContext * context,struct create_data * transfer)86 _mem_create_gl (GstGLContext * context, struct create_data *transfer)
87 {
88 GstGLBaseMemoryAllocatorClass *alloc_class;
89 GError *error = NULL;
90
91 GST_CAT_TRACE (GST_CAT_GL_BASE_MEMORY, "Create memory %p", transfer->mem);
92
93 alloc_class =
94 GST_GL_BASE_MEMORY_ALLOCATOR_GET_CLASS (transfer->mem->mem.allocator);
95
96 g_return_if_fail (alloc_class->create != NULL);
97
98 /* Don't do expensive queries when debugging is disabled */
99 transfer->mem->query = NULL;
100 if (_gst_gl_context_debug_is_enabled (context))
101 transfer->mem->query =
102 gst_gl_query_new (context, GST_GL_QUERY_TIME_ELAPSED);
103
104 if ((transfer->result = alloc_class->create (transfer->mem, &error)))
105 return;
106
107 g_assert (error != NULL);
108
109 GST_CAT_ERROR (GST_CAT_GL_BASE_MEMORY, "Failed to create GL buffer: %s",
110 error->message);
111 g_clear_error (&error);
112 }
113
114 /**
115 * gst_gl_base_memory_init:
116 * @mem: the #GstGLBaseMemory to initialize
117 * @allocator: the #GstAllocator to initialize with
118 * @parent: (allow-none): the parent #GstMemory to initialize with
119 * @context: the #GstGLContext to initialize with
120 * @params: (allow-none): the @GstAllocationParams to initialize with
121 * @size: the number of bytes to be allocated
122 * @user_data: (allow-none): user data to call @notify with
123 * @notify: (allow-none): a #GDestroyNotify
124 *
125 * Initializes @mem with the required parameters
126 *
127 * Since: 1.8
128 */
129 void
gst_gl_base_memory_init(GstGLBaseMemory * mem,GstAllocator * allocator,GstMemory * parent,GstGLContext * context,const GstAllocationParams * params,gsize size,gpointer user_data,GDestroyNotify notify)130 gst_gl_base_memory_init (GstGLBaseMemory * mem, GstAllocator * allocator,
131 GstMemory * parent, GstGLContext * context,
132 const GstAllocationParams * params, gsize size, gpointer user_data,
133 GDestroyNotify notify)
134 {
135 gsize align = gst_memory_alignment, offset = 0, maxsize;
136 GstMemoryFlags flags = 0;
137 struct create_data data;
138
139 /* A note on sizes.
140 * gl_mem->alloc_size: the size to allocate when we control the allocation.
141 * Size of the unaligned allocation.
142 * mem->maxsize: the size that is used by GstMemory for mapping, to map the
143 * entire memory. The size of the aligned allocation
144 * mem->size: represents the size of the valid data. Can be reduced with
145 * gst_memory_resize()
146 *
147 * It holds that:
148 * mem->size + mem->offset <= mem->maxsize
149 * and
150 * mem->maxsize + alignment offset <= gl_mem->alloc_size
151 *
152 * We need to add the alignment mask to the allocated size in order to have
153 * the freedom to align the gl_mem->data pointer correctly which may be offset
154 * by at most align bytes in the alloc_data pointer.
155 *
156 * maxsize is not suitable for this as it is used by GstMemory as the size
157 * to map with.
158 */
159 mem->alloc_size = maxsize = size;
160 if (params) {
161 flags = params->flags;
162 align |= params->align;
163 offset = params->prefix;
164 maxsize += params->prefix + params->padding;
165
166 /* deals with any alignment */
167 mem->alloc_size = maxsize + align;
168 }
169
170 gst_memory_init (GST_MEMORY_CAST (mem), flags, allocator, parent, maxsize,
171 align, offset, size);
172
173 mem->context = gst_object_ref (context);
174 mem->notify = notify;
175 mem->user_data = user_data;
176
177 g_mutex_init (&mem->lock);
178
179 data.mem = mem;
180
181 gst_gl_context_thread_add (context,
182 (GstGLContextThreadFunc) _mem_create_gl, &data);
183 if (!data.result) {
184 GST_CAT_ERROR (GST_CAT_GL_BASE_MEMORY,
185 "Could not create GL buffer with context:%p", context);
186 }
187
188 GST_CAT_DEBUG (GST_CAT_GL_BASE_MEMORY, "new GL buffer memory:%p size:%"
189 G_GSIZE_FORMAT, mem, maxsize);
190 }
191
192 static gpointer
_align_data(gpointer data,gsize align)193 _align_data (gpointer data, gsize align)
194 {
195 guint8 *ret = data;
196 gsize aoffset;
197
198 /* do alignment, data must have enough padding at the end to move at most
199 * align bytes */
200 if ((aoffset = ((guintptr) ret & align))) {
201 aoffset = (align + 1) - aoffset;
202 ret += aoffset;
203 }
204
205 return ret;
206 }
207
208 /* subclass usage only */
209 /**
210 * gst_gl_base_memory_alloc_data:
211 * @gl_mem: a #GstGLBaseMemory
212 *
213 * Note: only intended for subclass usage to allocate the system memory buffer
214 * on demand. If there is already a non-NULL data pointer in @gl_mem->data,
215 * then this function imply returns TRUE.
216 *
217 * Returns: whether the system memory could be allocated
218 */
219 gboolean
gst_gl_base_memory_alloc_data(GstGLBaseMemory * gl_mem)220 gst_gl_base_memory_alloc_data (GstGLBaseMemory * gl_mem)
221 {
222 GstMemory *mem = (GstMemory *) gl_mem;
223
224 if (gl_mem->data)
225 return TRUE;
226
227 GST_CAT_LOG (GST_CAT_GL_BASE_MEMORY, "%p attempting allocation of data "
228 "pointer of size %" G_GSIZE_FORMAT, gl_mem, gl_mem->alloc_size);
229 gl_mem->alloc_data = g_try_malloc (gl_mem->alloc_size);
230
231 if (gl_mem->alloc_data == NULL)
232 return FALSE;
233
234 gl_mem->data = _align_data (gl_mem->alloc_data, mem->align);
235
236 GST_CAT_DEBUG (GST_CAT_GL_BASE_MEMORY, "%p allocated data pointer alloc %p, "
237 "data %p", gl_mem, gl_mem->alloc_data, gl_mem->data);
238
239 return TRUE;
240 }
241
242 struct map_data
243 {
244 GstGLBaseMemory *mem;
245 GstMapInfo *info;
246 gsize size;
247 gpointer data;
248 };
249
250 static void
_map_data_gl(GstGLContext * context,struct map_data * transfer)251 _map_data_gl (GstGLContext * context, struct map_data *transfer)
252 {
253 GstGLBaseMemoryAllocatorClass *alloc_class;
254 GstGLBaseMemory *mem = transfer->mem;
255 GstMapInfo *info = transfer->info;
256 guint prev_map_flags;
257 guint prev_gl_map_count;
258
259 alloc_class =
260 GST_GL_BASE_MEMORY_ALLOCATOR_GET_CLASS (transfer->mem->mem.allocator);
261
262 g_return_if_fail (alloc_class->map != NULL);
263
264 g_mutex_lock (&mem->lock);
265
266 prev_map_flags = mem->map_flags;
267 prev_gl_map_count = mem->gl_map_count;
268
269 GST_CAT_LOG (GST_CAT_GL_BASE_MEMORY, "mapping mem %p flags %04x", mem,
270 info->flags);
271
272 /* FIXME: validate map flags based on the memory domain */
273 if (mem->map_count++ == 0)
274 mem->map_flags = info->flags;
275 else {
276 /* assert that the flags are a subset of the first map flags */
277 g_assert ((((GST_MAP_GL - 1) & info->flags) & mem->map_flags) != 0);
278 GST_CAT_LOG (GST_CAT_GL_BASE_MEMORY, "multiple map no %d flags %04x "
279 "all flags %04x", mem->map_count, info->flags, mem->map_flags);
280 }
281
282 if ((info->flags & GST_MAP_GL) != (mem->map_flags & GST_MAP_GL))
283 mem->map_flags |= GST_MAP_GL;
284
285 if (info->flags & GST_MAP_GL)
286 mem->gl_map_count++;
287
288 transfer->data = alloc_class->map (transfer->mem, transfer->info,
289 transfer->size);
290
291 if (transfer->data) {
292 if (info->flags & GST_MAP_GL) {
293 if (info->flags & GST_MAP_WRITE)
294 GST_MINI_OBJECT_FLAG_SET (mem,
295 GST_GL_BASE_MEMORY_TRANSFER_NEED_DOWNLOAD);
296 GST_MEMORY_FLAG_UNSET (mem, GST_GL_BASE_MEMORY_TRANSFER_NEED_UPLOAD);
297 } else {
298 if (info->flags & GST_MAP_WRITE)
299 GST_MINI_OBJECT_FLAG_SET (mem, GST_GL_BASE_MEMORY_TRANSFER_NEED_UPLOAD);
300 GST_MEMORY_FLAG_UNSET (mem, GST_GL_BASE_MEMORY_TRANSFER_NEED_DOWNLOAD);
301 }
302 } else {
303 /* undo state tracking on error */
304 mem->map_flags = prev_map_flags;
305 mem->gl_map_count = prev_gl_map_count;
306 mem->map_count--;
307 }
308
309 g_mutex_unlock (&mem->lock);
310 }
311
312 static gpointer
_mem_map_full(GstGLBaseMemory * mem,GstMapInfo * info,gsize size)313 _mem_map_full (GstGLBaseMemory * mem, GstMapInfo * info, gsize size)
314 {
315 struct map_data transfer;
316
317 transfer.mem = mem;
318 transfer.info = info;
319 transfer.size = size;
320 transfer.data = NULL;
321
322 gst_gl_context_thread_add (mem->context,
323 (GstGLContextThreadFunc) _map_data_gl, &transfer);
324
325 return transfer.data;
326 }
327
328 struct unmap_data
329 {
330 GstGLBaseMemory *mem;
331 GstMapInfo *info;
332 };
333
334 static void
_unmap_data_gl(GstGLContext * context,struct unmap_data * transfer)335 _unmap_data_gl (GstGLContext * context, struct unmap_data *transfer)
336 {
337 GstGLBaseMemoryAllocatorClass *alloc_class;
338 GstGLBaseMemory *mem = transfer->mem;
339 GstMapInfo *info = transfer->info;
340
341 alloc_class =
342 GST_GL_BASE_MEMORY_ALLOCATOR_GET_CLASS (transfer->mem->mem.allocator);
343
344 g_return_if_fail (alloc_class->unmap != NULL);
345
346 g_mutex_lock (&mem->lock);
347
348 GST_CAT_LOG (GST_CAT_GL_BASE_MEMORY, "unmapping mem %p flags %04x", mem,
349 info->flags);
350
351 alloc_class->unmap (transfer->mem, transfer->info);
352
353 if (info->flags & GST_MAP_GL && --mem->gl_map_count)
354 /* unset the gl flag */
355 mem->map_flags &= ~GST_MAP_GL;
356
357 if (--mem->map_count <= 0) {
358 mem->map_flags = 0;
359 }
360
361 if (info->flags & GST_MAP_GL) {
362 if (info->flags & GST_MAP_WRITE)
363 GST_MINI_OBJECT_FLAG_SET (mem, GST_GL_BASE_MEMORY_TRANSFER_NEED_DOWNLOAD);
364 } else {
365 if (info->flags & GST_MAP_WRITE)
366 GST_MINI_OBJECT_FLAG_SET (mem, GST_GL_BASE_MEMORY_TRANSFER_NEED_UPLOAD);
367 }
368
369 g_mutex_unlock (&mem->lock);
370 }
371
372 static void
_mem_unmap_full(GstGLBaseMemory * mem,GstMapInfo * info)373 _mem_unmap_full (GstGLBaseMemory * mem, GstMapInfo * info)
374 {
375 struct unmap_data transfer;
376
377 transfer.mem = mem;
378 transfer.info = info;
379
380 gst_gl_context_thread_add (mem->context,
381 (GstGLContextThreadFunc) _unmap_data_gl, &transfer);
382 }
383
384 static GstGLBaseMemory *
_default_copy(GstGLBaseMemory * src,gssize offset,gssize size)385 _default_copy (GstGLBaseMemory * src, gssize offset, gssize size)
386 {
387 return NULL;
388 }
389
390 struct copy_params
391 {
392 GstGLBaseMemory *src;
393 GstGLBaseMemory *dest;
394 gssize offset;
395 gssize size;
396 gboolean result;
397 };
398
399 static void
_mem_copy_gl(GstGLContext * context,struct copy_params * transfer)400 _mem_copy_gl (GstGLContext * context, struct copy_params *transfer)
401 {
402 GstGLBaseMemoryAllocatorClass *alloc_class;
403
404 alloc_class =
405 GST_GL_BASE_MEMORY_ALLOCATOR_GET_CLASS (transfer->src->mem.allocator);
406
407 g_return_if_fail (alloc_class->copy != NULL);
408
409 transfer->dest =
410 alloc_class->copy (transfer->src, transfer->offset, transfer->size);
411 }
412
413 static GstMemory *
_mem_copy(GstGLBaseMemory * src,gssize offset,gssize size)414 _mem_copy (GstGLBaseMemory * src, gssize offset, gssize size)
415 {
416 struct copy_params transfer;
417
418 transfer.dest = NULL;
419 transfer.src = src;
420 transfer.offset = offset;
421 transfer.size = size;
422 if (size == -1 || size > 0)
423 gst_gl_context_thread_add (src->context,
424 (GstGLContextThreadFunc) _mem_copy_gl, &transfer);
425
426 return (GstMemory *) transfer.dest;
427 }
428
429 static GstMemory *
_mem_share(GstGLBaseMemory * mem,gssize offset,gssize size)430 _mem_share (GstGLBaseMemory * mem, gssize offset, gssize size)
431 {
432 return NULL;
433 }
434
435 static gboolean
_mem_is_span(GstGLBaseMemory * mem1,GstGLBaseMemory * mem2,gsize * offset)436 _mem_is_span (GstGLBaseMemory * mem1, GstGLBaseMemory * mem2, gsize * offset)
437 {
438 return FALSE;
439 }
440
441 static GstMemory *
_mem_alloc(GstAllocator * allocator,gsize size,GstAllocationParams * params)442 _mem_alloc (GstAllocator * allocator, gsize size, GstAllocationParams * params)
443 {
444 g_critical ("Subclass should override GstAllocatorClass::alloc() function");
445
446 return NULL;
447 }
448
449 static void
_default_destroy(GstGLBaseMemory * mem)450 _default_destroy (GstGLBaseMemory * mem)
451 {
452 }
453
454 static void
_destroy_gl_objects(GstGLContext * context,GstGLBaseMemory * mem)455 _destroy_gl_objects (GstGLContext * context, GstGLBaseMemory * mem)
456 {
457 GstGLBaseMemoryAllocatorClass *alloc_class;
458
459 alloc_class = GST_GL_BASE_MEMORY_ALLOCATOR_GET_CLASS (mem->mem.allocator);
460
461 g_return_if_fail (alloc_class->destroy != NULL);
462
463 alloc_class->destroy (mem);
464
465 if (mem->query)
466 gst_gl_query_free (mem->query);
467 }
468
469 static void
_mem_free(GstAllocator * allocator,GstMemory * memory)470 _mem_free (GstAllocator * allocator, GstMemory * memory)
471 {
472 GstGLBaseMemory *mem = (GstGLBaseMemory *) memory;
473
474 GST_CAT_TRACE (GST_CAT_GL_BASE_MEMORY, "freeing buffer memory:%p", mem);
475
476 gst_gl_context_thread_add (mem->context,
477 (GstGLContextThreadFunc) _destroy_gl_objects, mem);
478
479 g_mutex_clear (&mem->lock);
480
481 if (mem->alloc_data) {
482 g_free (mem->alloc_data);
483 mem->alloc_data = NULL;
484 }
485 mem->data = NULL;
486
487 if (mem->notify)
488 mem->notify (mem->user_data);
489
490 gst_object_unref (mem->context);
491
492 g_free (memory);
493 }
494
495 /**
496 * gst_gl_base_memory_init_once:
497 *
498 * Initializes the GL Base Memory allocator. It is safe to call this function
499 * multiple times. This must be called before any other GstGLBaseMemory operation.
500 *
501 * Since: 1.8
502 */
503 void
gst_gl_base_memory_init_once(void)504 gst_gl_base_memory_init_once (void)
505 {
506 static gsize _init = 0;
507
508 if (g_once_init_enter (&_init)) {
509 GST_DEBUG_CATEGORY_INIT (GST_CAT_GL_BASE_MEMORY, "glbasememory", 0,
510 "OpenGL BaseMemory");
511
512 g_once_init_leave (&_init, 1);
513 }
514 }
515
516 G_DEFINE_ABSTRACT_TYPE (GstGLBaseMemoryAllocator, gst_gl_base_memory_allocator,
517 GST_TYPE_ALLOCATOR);
518
519 static void
gst_gl_base_memory_allocator_class_init(GstGLBaseMemoryAllocatorClass * klass)520 gst_gl_base_memory_allocator_class_init (GstGLBaseMemoryAllocatorClass * klass)
521 {
522 GstAllocatorClass *allocator_class = (GstAllocatorClass *) klass;
523
524 allocator_class->alloc = _mem_alloc;
525 allocator_class->free = _mem_free;
526
527 klass->create = _default_create;
528 klass->copy = _default_copy;
529 klass->destroy = _default_destroy;
530 }
531
532 static void
gst_gl_base_memory_allocator_init(GstGLBaseMemoryAllocator * allocator)533 gst_gl_base_memory_allocator_init (GstGLBaseMemoryAllocator * allocator)
534 {
535 GstAllocator *alloc = GST_ALLOCATOR_CAST (allocator);
536
537 /* Keep the fallback copy function around, we will need it when copying with
538 * at an offset or smaller size */
539 allocator->fallback_mem_copy = alloc->mem_copy;
540
541 alloc->mem_map_full = (GstMemoryMapFullFunction) _mem_map_full;
542 alloc->mem_unmap_full = (GstMemoryUnmapFullFunction) _mem_unmap_full;
543 alloc->mem_copy = (GstMemoryCopyFunction) _mem_copy;
544 alloc->mem_share = (GstMemoryShareFunction) _mem_share;
545 alloc->mem_is_span = (GstMemoryIsSpanFunction) _mem_is_span;
546 }
547
548 /**
549 * gst_is_gl_base_memory:
550 * @mem:a #GstMemory
551 *
552 * Returns: whether the memory at @mem is a #GstGLBaseMemory
553 *
554 * Since: 1.8
555 */
556 gboolean
gst_is_gl_base_memory(GstMemory * mem)557 gst_is_gl_base_memory (GstMemory * mem)
558 {
559 return mem != NULL && mem->allocator != NULL &&
560 g_type_is_a (G_OBJECT_TYPE (mem->allocator),
561 GST_TYPE_GL_BASE_MEMORY_ALLOCATOR);
562 }
563
564 /**
565 * gst_gl_base_memory_memcpy:
566 * @src: the source #GstGLBaseMemory
567 * @dest: the destination #GstGLBaseMemory
568 * @offset: the offset to start at
569 * @size: the number of bytes to copy
570 *
571 * Returns: whether the copy succeeded.
572 *
573 * Since: 1.8
574 */
575 gboolean
gst_gl_base_memory_memcpy(GstGLBaseMemory * src,GstGLBaseMemory * dest,gssize offset,gssize size)576 gst_gl_base_memory_memcpy (GstGLBaseMemory * src, GstGLBaseMemory * dest,
577 gssize offset, gssize size)
578 {
579 GstMapInfo sinfo, dinfo;
580
581 if (!gst_gl_base_memory_alloc_data (GST_GL_BASE_MEMORY_CAST (dest)))
582 return FALSE;
583
584 if (!gst_memory_map ((GstMemory *) src, &sinfo, GST_MAP_READ)) {
585 GST_CAT_WARNING (GST_CAT_GL_BASE_MEMORY,
586 "could not read map source memory %p", src);
587 return FALSE;
588 }
589
590 if (!gst_memory_map ((GstMemory *) dest, &dinfo, GST_MAP_WRITE)) {
591 GST_CAT_WARNING (GST_CAT_GL_BASE_MEMORY,
592 "could not write map dest memory %p", dest);
593 gst_memory_unmap ((GstMemory *) src, &sinfo);
594 return FALSE;
595 }
596
597 if (size == -1)
598 size = sinfo.size > offset ? sinfo.size - offset : 0;
599
600 GST_CAT_DEBUG (GST_CAT_GL_BASE_MEMORY,
601 "memcpy %" G_GSSIZE_FORMAT " memory %p -> %p", size, src, dest);
602 memcpy (dinfo.data, sinfo.data + offset, size);
603 gst_memory_unmap ((GstMemory *) dest, &dinfo);
604 gst_memory_unmap ((GstMemory *) src, &sinfo);
605
606 return TRUE;
607 }
608
609 /**
610 * gst_gl_allocation_params_init: (skip)
611 * @params: the #GstGLAllocationParams to initialize
612 * @struct_size: the struct size of the implementation
613 * @alloc_flags: some alloc flags
614 * @copy: a copy function
615 * @free: a free function
616 * @context: (transfer none): a #GstGLContext
617 * @alloc_size: the number of bytes to allocate.
618 * @alloc_params: (transfer none) (allow-none): a #GstAllocationParams to apply
619 * @wrapped_data: (transfer none) (allow-none): a sysmem data pointer to initialize the allocation with
620 * @gl_handle: (transfer none): a GL handle to initialize the allocation with
621 * @user_data: (transfer none) (allow-none): user data to call @notify with
622 * @notify: (allow-none): a #GDestroyNotify
623 *
624 * @notify will be called once for each allocated memory using these @params
625 * when freeing the memory.
626 *
627 * Returns: whether the parameters could be initialized
628 *
629 * Since: 1.8
630 */
631 gboolean
gst_gl_allocation_params_init(GstGLAllocationParams * params,gsize struct_size,guint alloc_flags,GstGLAllocationParamsCopyFunc copy,GstGLAllocationParamsFreeFunc free,GstGLContext * context,gsize alloc_size,const GstAllocationParams * alloc_params,gpointer wrapped_data,gpointer gl_handle,gpointer user_data,GDestroyNotify notify)632 gst_gl_allocation_params_init (GstGLAllocationParams * params,
633 gsize struct_size, guint alloc_flags, GstGLAllocationParamsCopyFunc copy,
634 GstGLAllocationParamsFreeFunc free, GstGLContext * context,
635 gsize alloc_size, const GstAllocationParams * alloc_params,
636 gpointer wrapped_data, gpointer gl_handle, gpointer user_data,
637 GDestroyNotify notify)
638 {
639 memset (params, 0, sizeof (*params));
640
641 g_return_val_if_fail (struct_size > 0, FALSE);
642 g_return_val_if_fail (copy != NULL, FALSE);
643 g_return_val_if_fail (free != NULL, FALSE);
644 g_return_val_if_fail (GST_IS_GL_CONTEXT (context), FALSE);
645
646 params->struct_size = struct_size;
647 params->alloc_size = alloc_size;
648 params->copy = copy;
649 params->free = free;
650 params->alloc_flags = alloc_flags;
651 params->context = gst_object_ref (context);
652 if (alloc_params)
653 params->alloc_params = gst_allocation_params_copy (alloc_params);
654 params->notify = notify;
655 params->user_data = user_data;
656 params->wrapped_data = wrapped_data;
657 params->gl_handle = gl_handle;
658
659 return TRUE;
660 }
661
662 /**
663 * gst_gl_allocation_params_copy:
664 * @src: the #GstGLAllocationParams to initialize
665 *
666 * Returns: (transfer full): a copy of the #GstGLAllocationParams specified by
667 * @src or %NULL on failure
668 *
669 * Since: 1.8
670 */
671 GstGLAllocationParams *
gst_gl_allocation_params_copy(GstGLAllocationParams * src)672 gst_gl_allocation_params_copy (GstGLAllocationParams * src)
673 {
674 GstGLAllocationParams *dest;
675
676 g_return_val_if_fail (src != NULL, NULL);
677
678 dest = g_malloc0 (src->struct_size);
679
680 if (src->copy)
681 src->copy (src, dest);
682
683 return dest;
684 }
685
686 /**
687 * gst_gl_allocation_params_free:
688 * @params: the #GstGLAllocationParams to initialize
689 *
690 * Frees the #GstGLAllocationParams and all associated data.
691 *
692 * Since: 1.8
693 */
694 void
gst_gl_allocation_params_free(GstGLAllocationParams * params)695 gst_gl_allocation_params_free (GstGLAllocationParams * params)
696 {
697 if (params->free)
698 params->free (params);
699
700 g_free (params);
701 }
702
703 /**
704 * gst_gl_allocation_params_free_data:
705 * @params: the source #GstGLAllocationParams
706 *
707 * Frees the dynamically allocated data in @params. Direct subclasses
708 * should call this function in their own overridden free function.
709 *
710 * Since: 1.8
711 */
712 void
gst_gl_allocation_params_free_data(GstGLAllocationParams * params)713 gst_gl_allocation_params_free_data (GstGLAllocationParams * params)
714 {
715 if (params->context)
716 gst_object_unref (params->context);
717 if (params->alloc_params)
718 gst_allocation_params_free (params->alloc_params);
719 }
720
721 /**
722 * gst_gl_allocation_params_copy_data:
723 * @src: the source #GstGLAllocationParams
724 * @dest: the destination #GstGLAllocationParams
725 *
726 * Copies the dynamically allocated data from @src to @dest. Direct subclasses
727 * should call this function in their own overridden copy function.
728 *
729 * Since: 1.8
730 */
731 void
gst_gl_allocation_params_copy_data(GstGLAllocationParams * src,GstGLAllocationParams * dest)732 gst_gl_allocation_params_copy_data (GstGLAllocationParams * src,
733 GstGLAllocationParams * dest)
734 {
735 gst_gl_allocation_params_init (dest, src->struct_size, src->alloc_flags,
736 src->copy, src->free, src->context, src->alloc_size, NULL,
737 src->wrapped_data, src->gl_handle, src->user_data, src->notify);
738
739 if (src->alloc_params)
740 dest->alloc_params = gst_allocation_params_copy (src->alloc_params);
741 }
742
743 G_DEFINE_BOXED_TYPE (GstGLAllocationParams, gst_gl_allocation_params,
744 (GBoxedCopyFunc) gst_gl_allocation_params_copy,
745 (GBoxedFreeFunc) gst_gl_allocation_params_free);
746
747 /**
748 * gst_gl_base_memory_alloc:
749 * @allocator: a #GstGLBaseMemoryAllocator
750 * @params: the #GstGLAllocationParams to allocate the memory with
751 *
752 * Returns: a new #GstGLBaseMemory from @allocator with the requested @params.
753 *
754 * Since: 1.8
755 */
756 GstGLBaseMemory *
gst_gl_base_memory_alloc(GstGLBaseMemoryAllocator * allocator,GstGLAllocationParams * params)757 gst_gl_base_memory_alloc (GstGLBaseMemoryAllocator * allocator,
758 GstGLAllocationParams * params)
759 {
760 GstGLBaseMemoryAllocatorClass *alloc_class;
761
762 g_return_val_if_fail (GST_IS_GL_BASE_MEMORY_ALLOCATOR (allocator), NULL);
763
764 alloc_class = GST_GL_BASE_MEMORY_ALLOCATOR_GET_CLASS (allocator);
765
766 g_return_val_if_fail (alloc_class != NULL, NULL);
767 g_return_val_if_fail (alloc_class->alloc != NULL, NULL);
768
769 return alloc_class->alloc (allocator, params);
770 }
771