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