3 * Copyright (C) 2012 Matthew Waters <ystreet00@gmail.com>
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.
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.
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.
27 #include <gst/video/video.h>
29 #include "gstglmemory.h"
30 #include "gstglutils.h"
34 * @short_description: memory subclass for GL textures
35 * @see_also: #GstMemory, #GstAllocator, #GstGLBufferPool
37 * GstGLMemory is a #GstMemory subclass providing support for the mapping of
40 * #GstGLMemory is created through gst_gl_memory_alloc() or system memory can
41 * be wrapped through gst_gl_memory_wrapped().
43 * Data is uploaded or downloaded from the GPU as is necessary.
46 #define USING_OPENGL(context) (gst_gl_context_check_gl_version (context, GST_GL_API_OPENGL, 1, 0))
47 #define USING_OPENGL3(context) (gst_gl_context_check_gl_version (context, GST_GL_API_OPENGL3, 3, 1))
48 #define USING_GLES(context) (gst_gl_context_check_gl_version (context, GST_GL_API_GLES, 1, 0))
49 #define USING_GLES2(context) (gst_gl_context_check_gl_version (context, GST_GL_API_GLES2, 2, 0))
50 #define USING_GLES3(context) (gst_gl_context_check_gl_version (context, GST_GL_API_GLES2, 3, 0))
52 #define GL_MEM_WIDTH(gl_mem) _get_plane_width (&gl_mem->info, gl_mem->plane)
53 #define GL_MEM_HEIGHT(gl_mem) _get_plane_height (&gl_mem->info, gl_mem->plane)
54 #define GL_MEM_STRIDE(gl_mem) GST_VIDEO_INFO_PLANE_STRIDE (&gl_mem->info, gl_mem->plane)
56 #define CONTEXT_SUPPORTS_PBO_UPLOAD(context) \
57 (gst_gl_context_check_gl_version (context, \
58 GST_GL_API_OPENGL | GST_GL_API_OPENGL3, 2, 1) \
59 || gst_gl_context_check_gl_version (context, GST_GL_API_GLES2, 3, 0))
60 #define CONTEXT_SUPPORTS_PBO_DOWNLOAD(context) \
61 (gst_gl_context_check_gl_version (context, \
62 GST_GL_API_OPENGL | GST_GL_API_OPENGL3 | GST_GL_API_GLES2, 3, 0))
64 GST_DEBUG_CATEGORY_STATIC (GST_CAT_GL_MEMORY);
65 #define GST_CAT_DEFUALT GST_CAT_GL_MEMORY
67 static GstAllocator *_gl_allocator;
69 /* compatability definitions... */
82 #ifndef GL_PIXEL_PACK_BUFFER
83 #define GL_PIXEL_PACK_BUFFER 0x88EB
85 #ifndef GL_PIXEL_UNPACK_BUFFER
86 #define GL_PIXEL_UNPACK_BUFFER 0x88EC
88 #ifndef GL_STREAM_READ
89 #define GL_STREAM_READ 0x88E1
91 #ifndef GL_STREAM_DRAW
92 #define GL_STREAM_DRAW 0x88E0
94 #ifndef GL_STREAM_COPY
95 #define GL_STREAM_COPY 0x88E2
97 #ifndef GL_UNPACK_ROW_LENGTH
98 #define GL_UNPACK_ROW_LENGTH 0x0CF2
100 #ifndef GL_MAP_READ_BIT
101 #define GL_MAP_READ_BIT 0x0001
103 #ifndef GL_MAP_WRITE_BIT
104 #define GL_MAP_WRITE_BIT 0x0002
111 GstVideoGLTextureType out_format;
112 guint out_width, out_height;
120 } GstGLMemoryCopyParams;
123 _gl_format_n_components (guint format)
126 case GST_VIDEO_GL_TEXTURE_TYPE_RGBA:
129 case GST_VIDEO_GL_TEXTURE_TYPE_RGB:
130 case GST_VIDEO_GL_TEXTURE_TYPE_RGB16:
133 case GST_VIDEO_GL_TEXTURE_TYPE_LUMINANCE_ALPHA:
134 case GST_VIDEO_GL_TEXTURE_TYPE_RG:
135 case GL_LUMINANCE_ALPHA:
138 case GST_VIDEO_GL_TEXTURE_TYPE_LUMINANCE:
139 case GST_VIDEO_GL_TEXTURE_TYPE_R:
149 _gl_type_n_components (guint type)
152 case GL_UNSIGNED_BYTE:
154 case GL_UNSIGNED_SHORT_5_6_5:
157 g_assert_not_reached ();
163 _gl_type_n_bytes (guint type)
166 case GL_UNSIGNED_BYTE:
168 case GL_UNSIGNED_SHORT_5_6_5:
171 g_assert_not_reached ();
177 _gl_format_type_n_bytes (guint format, guint type)
179 return _gl_format_n_components (format) / _gl_type_n_components (type) *
180 _gl_type_n_bytes (type);
184 _gst_gl_format_from_gl_texture_type (GstVideoGLTextureType tex_format)
186 switch (tex_format) {
187 case GST_VIDEO_GL_TEXTURE_TYPE_LUMINANCE_ALPHA:
188 return GL_LUMINANCE_ALPHA;
189 case GST_VIDEO_GL_TEXTURE_TYPE_LUMINANCE:
191 case GST_VIDEO_GL_TEXTURE_TYPE_RGBA:
193 case GST_VIDEO_GL_TEXTURE_TYPE_RGB:
194 case GST_VIDEO_GL_TEXTURE_TYPE_RGB16:
196 case GST_VIDEO_GL_TEXTURE_TYPE_RG:
198 case GST_VIDEO_GL_TEXTURE_TYPE_R:
201 return GST_VIDEO_GL_TEXTURE_TYPE_RGBA;
206 _gl_texture_type_n_bytes (GstVideoGLTextureType tex_format)
210 format = _gst_gl_format_from_gl_texture_type (tex_format);
211 type = GL_UNSIGNED_BYTE;
212 if (tex_format == GST_VIDEO_GL_TEXTURE_TYPE_RGB16)
213 type = GL_UNSIGNED_SHORT_5_6_5;
215 return _gl_format_type_n_bytes (format, type);
218 GstVideoGLTextureType
219 gst_gl_texture_type_from_format (GstGLContext * context,
220 GstVideoFormat v_format, guint plane)
222 #if GST_GL_HAVE_PLATFORM_EAGL
223 gboolean texture_rg = FALSE;
225 gboolean texture_rg =
226 gst_gl_context_check_feature (context, "GL_EXT_texture_rg")
227 || gst_gl_context_check_feature (context, "GL_ARB_texture_rg");
229 guint n_plane_components;
232 case GST_VIDEO_FORMAT_RGBx:
233 case GST_VIDEO_FORMAT_BGRx:
234 case GST_VIDEO_FORMAT_xRGB:
235 case GST_VIDEO_FORMAT_xBGR:
236 case GST_VIDEO_FORMAT_RGBA:
237 case GST_VIDEO_FORMAT_BGRA:
238 case GST_VIDEO_FORMAT_ARGB:
239 case GST_VIDEO_FORMAT_ABGR:
240 case GST_VIDEO_FORMAT_AYUV:
241 n_plane_components = 4;
243 case GST_VIDEO_FORMAT_RGB:
244 case GST_VIDEO_FORMAT_BGR:
245 n_plane_components = 3;
247 case GST_VIDEO_FORMAT_RGB16:
248 case GST_VIDEO_FORMAT_BGR16:
249 return GST_VIDEO_GL_TEXTURE_TYPE_RGB16;
250 case GST_VIDEO_FORMAT_GRAY16_BE:
251 case GST_VIDEO_FORMAT_GRAY16_LE:
252 case GST_VIDEO_FORMAT_YUY2:
253 case GST_VIDEO_FORMAT_UYVY:
254 n_plane_components = 2;
256 case GST_VIDEO_FORMAT_NV12:
257 case GST_VIDEO_FORMAT_NV21:
258 n_plane_components = plane == 0 ? 1 : 2;
260 case GST_VIDEO_FORMAT_GRAY8:
261 case GST_VIDEO_FORMAT_Y444:
262 case GST_VIDEO_FORMAT_Y42B:
263 case GST_VIDEO_FORMAT_Y41B:
264 case GST_VIDEO_FORMAT_I420:
265 case GST_VIDEO_FORMAT_YV12:
266 n_plane_components = 1;
269 n_plane_components = 4;
270 g_assert_not_reached ();
274 switch (n_plane_components) {
276 return GST_VIDEO_GL_TEXTURE_TYPE_RGBA;
279 return GST_VIDEO_GL_TEXTURE_TYPE_RGB;
282 return texture_rg ? GST_VIDEO_GL_TEXTURE_TYPE_RG :
283 GST_VIDEO_GL_TEXTURE_TYPE_LUMINANCE_ALPHA;
286 return texture_rg ? GST_VIDEO_GL_TEXTURE_TYPE_R :
287 GST_VIDEO_GL_TEXTURE_TYPE_LUMINANCE;
290 g_assert_not_reached ();
294 return GST_VIDEO_GL_TEXTURE_TYPE_RGBA;
298 _sized_gl_format_from_gl_format_type (GLenum format, GLenum type)
303 case GL_UNSIGNED_BYTE:
310 case GL_UNSIGNED_BYTE:
313 case GL_UNSIGNED_SHORT_5_6_5:
320 case GL_UNSIGNED_BYTE:
327 case GL_UNSIGNED_BYTE:
335 case GL_LUMINANCE_ALPHA:
336 return GL_LUMINANCE_ALPHA;
345 g_assert_not_reached ();
350 _get_plane_width (GstVideoInfo * info, guint plane)
352 if (GST_VIDEO_INFO_IS_YUV (info))
353 /* For now component width and plane width are the same and the
354 * plane-component mapping matches
356 return GST_VIDEO_INFO_COMP_WIDTH (info, plane);
358 return GST_VIDEO_INFO_WIDTH (info);
362 _get_plane_height (GstVideoInfo * info, guint plane)
364 if (GST_VIDEO_INFO_IS_YUV (info))
365 /* For now component width and plane width are the same and the
366 * plane-component mapping matches
368 return GST_VIDEO_INFO_COMP_HEIGHT (info, plane);
370 return GST_VIDEO_INFO_HEIGHT (info);
373 typedef struct _GenTexture
383 _generate_texture (GstGLContext * context, GenTexture * data)
385 const GstGLFuncs *gl = context->gl_vtable;
386 GLenum internal_format;
388 GST_CAT_TRACE (GST_CAT_GL_MEMORY,
389 "Generating texture format:%u type:%u dimensions:%ux%u", data->gl_format,
390 data->gl_type, data->width, data->height);
393 _sized_gl_format_from_gl_format_type (data->gl_format, data->gl_type);
395 gl->GenTextures (1, &data->result);
396 gl->BindTexture (data->gl_target, data->result);
397 gl->TexImage2D (data->gl_target, 0, internal_format, data->width,
398 data->height, 0, data->gl_format, data->gl_type, NULL);
400 gl->TexParameteri (data->gl_target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
401 gl->TexParameteri (data->gl_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
402 gl->TexParameteri (data->gl_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
403 gl->TexParameteri (data->gl_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
405 GST_CAT_LOG (GST_CAT_GL_MEMORY, "generated texture id:%d", data->result);
408 /* find the difference between the start of the plane and where the video
409 * data starts in the plane */
411 _find_plane_frame_start (GstGLMemory * gl_mem)
416 /* find the start of the plane data including padding */
418 for (i = 0; i < gl_mem->plane; i++) {
420 gst_gl_get_plane_data_size (&gl_mem->info, &gl_mem->valign, i);
423 /* offset between the plane data start and where the video frame starts */
424 return (GST_VIDEO_INFO_PLANE_OFFSET (&gl_mem->info,
425 gl_mem->plane)) - plane_start;
429 _upload_memory (GstGLContext * context, GstGLMemory * gl_mem)
431 const GstGLFuncs *gl;
432 GLenum gl_format, gl_type, gl_target;
436 if (!GST_GL_MEMORY_FLAG_IS_SET (gl_mem, GST_GL_MEMORY_FLAG_NEED_UPLOAD)) {
440 gl = context->gl_vtable;
442 gl_type = GL_UNSIGNED_BYTE;
443 if (gl_mem->tex_type == GST_VIDEO_GL_TEXTURE_TYPE_RGB16)
444 gl_type = GL_UNSIGNED_SHORT_5_6_5;
446 gl_format = _gst_gl_format_from_gl_texture_type (gl_mem->tex_type);
447 gl_target = gl_mem->tex_target;
449 if (USING_OPENGL (context) || USING_GLES3 (context)
450 || USING_OPENGL3 (context)) {
451 gl->PixelStorei (GL_UNPACK_ROW_LENGTH, gl_mem->unpack_length);
452 } else if (USING_GLES2 (context)) {
453 gl->PixelStorei (GL_UNPACK_ALIGNMENT, gl_mem->unpack_length);
456 GST_CAT_LOG (GST_CAT_GL_MEMORY, "upload for texture id:%u, with pbo %u %ux%u",
457 gl_mem->tex_id, gl_mem->transfer_pbo, gl_mem->tex_width,
458 GL_MEM_HEIGHT (gl_mem));
460 /* find the start of the plane data including padding */
461 plane_start = _find_plane_frame_start (gl_mem);
463 if (gl_mem->transfer_pbo && CONTEXT_SUPPORTS_PBO_UPLOAD (context)) {
464 gl->BindBuffer (GL_PIXEL_UNPACK_BUFFER, gl_mem->transfer_pbo);
465 data = (void *) plane_start;
467 data = (gpointer) ((gintptr) plane_start + (gintptr) gl_mem->data);
470 gl->BindTexture (gl_target, gl_mem->tex_id);
471 gl->TexSubImage2D (gl_target, 0, 0, 0, gl_mem->tex_width,
472 GL_MEM_HEIGHT (gl_mem), gl_format, gl_type, data);
474 if (gl_mem->transfer_pbo && CONTEXT_SUPPORTS_PBO_UPLOAD (context))
475 gl->BindBuffer (GL_PIXEL_UNPACK_BUFFER, 0);
477 /* Reset to default values */
478 if (USING_OPENGL (context) || USING_GLES3 (context)) {
479 gl->PixelStorei (GL_UNPACK_ROW_LENGTH, 0);
480 } else if (USING_GLES2 (context)) {
481 gl->PixelStorei (GL_UNPACK_ALIGNMENT, 4);
484 gl->BindTexture (gl_target, 0);
486 GST_GL_MEMORY_FLAG_UNSET (gl_mem, GST_GL_MEMORY_FLAG_NEED_UPLOAD);
490 _transfer_upload (GstGLContext * context, GstGLMemory * gl_mem)
492 const GstGLFuncs *gl;
495 if (!CONTEXT_SUPPORTS_PBO_UPLOAD (context))
499 gl = context->gl_vtable;
501 if (!gl_mem->transfer_pbo)
502 gl->GenBuffers (1, &gl_mem->transfer_pbo);
504 GST_CAT_DEBUG (GST_CAT_GL_MEMORY, "uploading texture %u using pbo %u",
505 gl_mem->tex_id, gl_mem->transfer_pbo);
507 size = ((GstMemory *) gl_mem)->maxsize;
509 if (USING_OPENGL (context) || USING_GLES3 (context)
510 || USING_OPENGL3 (context)) {
511 gl->PixelStorei (GL_UNPACK_ROW_LENGTH, gl_mem->unpack_length);
512 } else if (USING_GLES2 (context)) {
513 gl->PixelStorei (GL_UNPACK_ALIGNMENT, gl_mem->unpack_length);
516 gl->BindBuffer (GL_PIXEL_UNPACK_BUFFER, gl_mem->transfer_pbo);
517 gl->BufferData (GL_PIXEL_UNPACK_BUFFER, size, gl_mem->data, GL_STREAM_DRAW);
518 gl->BindBuffer (GL_PIXEL_UNPACK_BUFFER, 0);
520 /* Reset to default values */
521 if (USING_OPENGL (context) || USING_GLES3 (context)) {
522 gl->PixelStorei (GL_UNPACK_ROW_LENGTH, 0);
523 } else if (USING_GLES2 (context)) {
524 gl->PixelStorei (GL_UNPACK_ALIGNMENT, 4);
529 _calculate_unpack_length (GstGLMemory * gl_mem)
533 gl_mem->tex_scaling[0] = 1.0f;
534 gl_mem->tex_scaling[1] = 1.0f;
535 gl_mem->unpack_length = 1;
536 gl_mem->tex_width = GL_MEM_WIDTH (gl_mem);
538 n_gl_bytes = _gl_texture_type_n_bytes (gl_mem->tex_type);
539 if (n_gl_bytes == 0) {
540 GST_CAT_ERROR (GST_CAT_GL_MEMORY, "Unsupported texture type %d",
545 if (USING_OPENGL (gl_mem->context) || USING_GLES3 (gl_mem->context)
546 || USING_OPENGL3 (gl_mem->context)) {
547 gl_mem->unpack_length = GL_MEM_STRIDE (gl_mem) / n_gl_bytes;
548 } else if (USING_GLES2 (gl_mem->context)) {
551 while (j >= n_gl_bytes) {
552 /* GST_ROUND_UP_j(GL_MEM_WIDTH (gl_mem) * n_gl_bytes) */
554 ((GL_MEM_WIDTH (gl_mem) * n_gl_bytes) + j - 1) & ~(j - 1);
556 if (round_up_j == GL_MEM_STRIDE (gl_mem)) {
557 GST_CAT_LOG (GST_CAT_GL_MEMORY, "Found alignment of %u based on width "
558 "(with plane width:%u, plane stride:%u and pixel stride:%u. "
559 "RU%u(%u*%u) = %u)", j, GL_MEM_WIDTH (gl_mem),
560 GL_MEM_STRIDE (gl_mem), n_gl_bytes, j, GL_MEM_WIDTH (gl_mem),
561 n_gl_bytes, round_up_j);
563 gl_mem->unpack_length = j;
569 if (j < n_gl_bytes) {
570 /* Failed to find a suitable alignment, try based on plane_stride and
571 * scale in the shader. Useful for alignments that are greater than 8.
575 while (j >= n_gl_bytes) {
576 /* GST_ROUND_UP_j((GL_MEM_STRIDE (gl_mem)) */
577 guint round_up_j = ((GL_MEM_STRIDE (gl_mem)) + j - 1) & ~(j - 1);
579 if (round_up_j == (GL_MEM_STRIDE (gl_mem))) {
580 GST_CAT_LOG (GST_CAT_GL_MEMORY, "Found alignment of %u based on "
581 "stride (with plane stride:%u and pixel stride:%u. "
582 "RU%u(%u) = %u)", j, GL_MEM_STRIDE (gl_mem), n_gl_bytes, j,
583 GL_MEM_STRIDE (gl_mem), round_up_j);
585 gl_mem->unpack_length = j;
586 gl_mem->tex_scaling[0] =
587 (gfloat) (GL_MEM_WIDTH (gl_mem) * n_gl_bytes) /
588 (gfloat) GL_MEM_STRIDE (gl_mem);
589 gl_mem->tex_width = GL_MEM_STRIDE (gl_mem) / n_gl_bytes;
595 if (j < n_gl_bytes) {
597 (GST_CAT_GL_MEMORY, "Failed to find matching alignment. Image may "
598 "look corrupted. plane width:%u, plane stride:%u and pixel "
599 "stride:%u", GL_MEM_WIDTH (gl_mem), GL_MEM_STRIDE (gl_mem),
607 _transfer_download (GstGLContext * context, GstGLMemory * gl_mem)
609 const GstGLFuncs *gl;
615 if (!CONTEXT_SUPPORTS_PBO_DOWNLOAD (context)
616 || gl_mem->tex_type == GST_VIDEO_GL_TEXTURE_TYPE_LUMINANCE
617 || gl_mem->tex_type == GST_VIDEO_GL_TEXTURE_TYPE_LUMINANCE_ALPHA)
621 gl = context->gl_vtable;
623 if (!gl_mem->transfer_pbo)
624 gl->GenBuffers (1, &gl_mem->transfer_pbo);
626 GST_CAT_DEBUG (GST_CAT_GL_MEMORY, "downloading texture %u using pbo %u",
627 gl_mem->tex_id, gl_mem->transfer_pbo);
629 size = ((GstMemory *) gl_mem)->maxsize;
630 plane_start = _find_plane_frame_start (gl_mem);
631 format = _gst_gl_format_from_gl_texture_type (gl_mem->tex_type);
632 type = GL_UNSIGNED_BYTE;
633 if (gl_mem->tex_type == GST_VIDEO_GL_TEXTURE_TYPE_RGB16)
634 type = GL_UNSIGNED_SHORT_5_6_5;
636 gl->BindBuffer (GL_PIXEL_PACK_BUFFER, gl_mem->transfer_pbo);
637 gl->BufferData (GL_PIXEL_PACK_BUFFER, size, NULL, GL_STREAM_READ);
639 /* FIXME: try and avoid creating and destroying fbo's every download... */
640 /* create a framebuffer object */
641 gl->GenFramebuffers (1, &fboId);
642 gl->BindFramebuffer (GL_FRAMEBUFFER, fboId);
644 gl->FramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
645 GL_TEXTURE_2D, gl_mem->tex_id, 0);
647 if (!gst_gl_context_check_framebuffer_status (context)) {
648 GST_CAT_ERROR (GST_CAT_GL_MEMORY, "failed to download texture");
652 gl->ReadPixels (0, 0, gl_mem->tex_width, GL_MEM_HEIGHT (gl_mem), format,
653 type, (void *) plane_start);
656 gl->BindFramebuffer (GL_FRAMEBUFFER, 0);
657 gl->DeleteFramebuffers (1, &fboId);
659 gl->BindBuffer (GL_PIXEL_PACK_BUFFER, 0);
663 _download_memory (GstGLContext * context, GstGLMemory * gl_mem)
665 const GstGLFuncs *gl;
669 gl = context->gl_vtable;
670 format = _gst_gl_format_from_gl_texture_type (gl_mem->tex_type);
671 type = GL_UNSIGNED_BYTE;
672 if (gl_mem->tex_type == GST_VIDEO_GL_TEXTURE_TYPE_RGB16)
673 type = GL_UNSIGNED_SHORT_5_6_5;
675 if (!gl->GenFramebuffers) {
676 gst_gl_context_set_error (context, "Cannot download GL texture "
677 "without support for Framebuffers");
681 if (gst_gl_context_get_gl_api (context) & GST_GL_API_GLES2
682 && (gl_mem->tex_type == GST_VIDEO_GL_TEXTURE_TYPE_LUMINANCE
683 || gl_mem->tex_type == GST_VIDEO_GL_TEXTURE_TYPE_LUMINANCE_ALPHA)) {
684 gst_gl_context_set_error (context, "Cannot download GL luminance/"
685 "luminance alpha textures");
689 GST_CAT_LOG (GST_CAT_GL_MEMORY, "downloading memory %p, tex %u into %p",
690 gl_mem, gl_mem->tex_id, gl_mem->data);
692 if (gl_mem->tex_type == GST_VIDEO_GL_TEXTURE_TYPE_LUMINANCE
693 || gl_mem->tex_type == GST_VIDEO_GL_TEXTURE_TYPE_LUMINANCE_ALPHA) {
694 gl->BindTexture (gl_mem->tex_target, gl_mem->tex_id);
695 gl->GetTexImage (gl_mem->tex_target, 0, format, type, gl_mem->data);
696 gl->BindTexture (gl_mem->tex_target, 0);
697 } else if (gl_mem->transfer_pbo && CONTEXT_SUPPORTS_PBO_DOWNLOAD (context)) {
698 gsize size = ((GstMemory *) gl_mem)->maxsize;
699 gpointer map_data = NULL;
701 gl->BindBuffer (GL_PIXEL_PACK_BUFFER, gl_mem->transfer_pbo);
703 gl->MapBufferRange (GL_PIXEL_PACK_BUFFER, 0, size, GL_MAP_READ_BIT);
705 GST_CAT_WARNING (GST_CAT_GL_MEMORY, "error mapping buffer for download");
706 gl->BindBuffer (GL_PIXEL_PACK_BUFFER, 0);
710 /* FIXME: COPY! use glMapBuffer + glSync everywhere to remove this */
711 memcpy (gl_mem->data, map_data, size);
713 gl->UnmapBuffer (GL_PIXEL_PACK_BUFFER);
714 gl->BindBuffer (GL_PIXEL_PACK_BUFFER, 0);
717 /* FIXME: try and avoid creating and destroying fbo's every download... */
718 /* create a framebuffer object */
719 gl->GenFramebuffers (1, &fboId);
720 gl->BindFramebuffer (GL_FRAMEBUFFER, fboId);
722 gl->FramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
723 gl_mem->tex_target, gl_mem->tex_id, 0);
725 if (!gst_gl_context_check_framebuffer_status (context))
728 gl->ReadPixels (0, 0, gl_mem->tex_width, GL_MEM_HEIGHT (gl_mem), format,
731 gl->BindFramebuffer (GL_FRAMEBUFFER, 0);
734 gl->DeleteFramebuffers (1, &fboId);
742 _gl_mem_init (GstGLMemory * mem, GstAllocator * allocator, GstMemory * parent,
743 GstGLContext * context, GstVideoInfo * info, GstVideoAlignment * valign,
744 guint plane, gpointer user_data, GDestroyNotify notify)
748 g_return_if_fail (plane < GST_VIDEO_INFO_N_PLANES (info));
752 mem->valign = *valign;
754 gst_video_alignment_reset (&mem->valign);
756 maxsize = gst_gl_get_plane_data_size (info, valign, plane);
758 gst_memory_init (GST_MEMORY_CAST (mem), GST_MEMORY_FLAG_NO_SHARE,
759 allocator, parent, maxsize, 0, 0, maxsize);
761 mem->context = gst_object_ref (context);
763 gst_gl_texture_type_from_format (context, GST_VIDEO_INFO_FORMAT (info),
765 /* we always operate on 2D textures unless we're dealing with wrapped textures */
766 mem->tex_target = GL_TEXTURE_2D;
768 mem->notify = notify;
769 mem->user_data = user_data;
770 mem->data_wrapped = FALSE;
771 mem->texture_wrapped = FALSE;
773 g_mutex_init (&mem->lock);
775 _calculate_unpack_length (mem);
777 GST_CAT_DEBUG (GST_CAT_GL_MEMORY, "new GL texture memory:%p format:%u "
778 "dimensions:%ux%u stride:%u size:%" G_GSIZE_FORMAT, mem, mem->tex_type,
779 mem->tex_width, GL_MEM_HEIGHT (mem), GL_MEM_STRIDE (mem), maxsize);
783 _gl_mem_new (GstAllocator * allocator, GstMemory * parent,
784 GstGLContext * context, GstVideoInfo * info, GstVideoAlignment * valign,
785 guint plane, gpointer user_data, GDestroyNotify notify)
788 GenTexture data = { 0, };
789 mem = g_slice_new0 (GstGLMemory);
790 _gl_mem_init (mem, allocator, parent, context, info, valign, plane,
793 data.width = mem->tex_width;
794 data.height = GL_MEM_HEIGHT (mem);
795 data.gl_format = _gst_gl_format_from_gl_texture_type (mem->tex_type);
796 data.gl_type = GL_UNSIGNED_BYTE;
797 data.gl_target = mem->tex_target;
798 if (mem->tex_type == GST_VIDEO_GL_TEXTURE_TYPE_RGB16)
799 data.gl_type = GL_UNSIGNED_SHORT_5_6_5;
801 gst_gl_context_thread_add (context,
802 (GstGLContextThreadFunc) _generate_texture, &data);
804 GST_CAT_WARNING (GST_CAT_GL_MEMORY,
805 "Could not create GL texture with context:%p", context);
808 GST_CAT_TRACE (GST_CAT_GL_MEMORY, "created texture %u", data.result);
810 mem->tex_id = data.result;
811 mem->tex_target = data.gl_target;
817 _gl_mem_map (GstGLMemory * gl_mem, gsize maxsize, GstMapFlags flags)
821 g_return_val_if_fail (maxsize == gl_mem->mem.maxsize, NULL);
823 g_mutex_lock (&gl_mem->lock);
825 if ((flags & GST_MAP_GL) == GST_MAP_GL) {
826 if ((flags & GST_MAP_READ) == GST_MAP_READ) {
827 GST_CAT_TRACE (GST_CAT_GL_MEMORY, "mapping GL texture:%u for reading",
829 if (GST_GL_MEMORY_FLAG_IS_SET (gl_mem, GST_GL_MEMORY_FLAG_NEED_UPLOAD)) {
830 gst_gl_context_thread_add (gl_mem->context,
831 (GstGLContextThreadFunc) _upload_memory, gl_mem);
832 GST_GL_MEMORY_FLAG_UNSET (gl_mem, GST_GL_MEMORY_FLAG_NEED_UPLOAD);
836 if ((flags & GST_MAP_WRITE) == GST_MAP_WRITE) {
837 GST_CAT_TRACE (GST_CAT_GL_MEMORY, "mapping GL texture:%u for writing",
839 GST_GL_MEMORY_FLAG_SET (gl_mem, GST_GL_MEMORY_FLAG_NEED_DOWNLOAD);
840 GST_GL_MEMORY_FLAG_UNSET (gl_mem, GST_GL_MEMORY_FLAG_NEED_UPLOAD);
843 data = &gl_mem->tex_id;
844 } else { /* not GL */
845 if ((flags & GST_MAP_READ) == GST_MAP_READ) {
846 GST_CAT_TRACE (GST_CAT_GL_MEMORY,
847 "mapping GL texture:%u for reading from system memory",
849 if (GST_GL_MEMORY_FLAG_IS_SET (gl_mem, GST_GL_MEMORY_FLAG_NEED_DOWNLOAD)) {
850 gst_gl_context_thread_add (gl_mem->context,
851 (GstGLContextThreadFunc) _download_memory, gl_mem);
852 GST_GL_MEMORY_FLAG_UNSET (gl_mem, GST_GL_MEMORY_FLAG_NEED_DOWNLOAD);
856 if ((flags & GST_MAP_WRITE) == GST_MAP_WRITE) {
857 GST_CAT_TRACE (GST_CAT_GL_MEMORY,
858 "mapping GL texture:%u for writing to system memory", gl_mem->tex_id);
859 GST_GL_MEMORY_FLAG_SET (gl_mem, GST_GL_MEMORY_FLAG_NEED_UPLOAD);
860 GST_GL_MEMORY_FLAG_UNSET (gl_mem, GST_GL_MEMORY_FLAG_NEED_DOWNLOAD);
866 gl_mem->map_flags = flags;
868 g_mutex_unlock (&gl_mem->lock);
874 gst_gl_memory_download_transfer (GstGLMemory * gl_mem)
876 g_mutex_lock (&gl_mem->lock);
878 gst_gl_context_thread_add (gl_mem->context,
879 (GstGLContextThreadFunc) _transfer_download, gl_mem);
881 g_mutex_unlock (&gl_mem->lock);
885 _gl_mem_unmap (GstGLMemory * gl_mem)
887 g_mutex_lock (&gl_mem->lock);
889 if (gl_mem->map_flags & GST_MAP_WRITE) {
890 if (!(gl_mem->map_flags & GST_MAP_GL))
891 gst_gl_context_thread_add (gl_mem->context,
892 (GstGLContextThreadFunc) _transfer_upload, gl_mem);
895 gl_mem->map_flags = 0;
897 g_mutex_unlock (&gl_mem->lock);
901 _gl_mem_copy_thread (GstGLContext * context, gpointer data)
903 const GstGLFuncs *gl;
904 GstGLMemoryCopyParams *copy_params;
907 GLuint out_tex_target;
909 gsize out_width, out_height, out_stride;
910 GLuint out_gl_format, out_gl_type;
911 GLuint in_gl_format, in_gl_type;
912 gsize in_size, out_size;
914 copy_params = (GstGLMemoryCopyParams *) data;
915 src = copy_params->src;
916 tex_id = copy_params->tex_id;
917 out_tex_target = copy_params->tex_target;
918 out_width = copy_params->out_width;
919 out_height = copy_params->out_height;
920 out_stride = copy_params->out_stride;
922 gl = src->context->gl_vtable;
923 out_gl_format = _gst_gl_format_from_gl_texture_type (copy_params->out_format);
924 out_gl_type = GL_UNSIGNED_BYTE;
925 if (copy_params->out_format == GST_VIDEO_GL_TEXTURE_TYPE_RGB16)
926 out_gl_type = GL_UNSIGNED_SHORT_5_6_5;
927 in_gl_format = _gst_gl_format_from_gl_texture_type (src->tex_type);
928 in_gl_type = GL_UNSIGNED_BYTE;
929 if (src->tex_type == GST_VIDEO_GL_TEXTURE_TYPE_RGB16)
930 in_gl_type = GL_UNSIGNED_SHORT_5_6_5;
932 if (!gl->GenFramebuffers) {
933 gst_gl_context_set_error (src->context,
934 "Context, EXT_framebuffer_object not supported");
938 in_size = GL_MEM_HEIGHT (src) * GL_MEM_STRIDE (src);
939 out_size = out_height * out_stride;
941 if (copy_params->respecify) {
942 if (in_size != out_size) {
943 GST_ERROR ("Cannot copy between textures with backing data of different"
944 "sizes. input %" G_GSIZE_FORMAT " output %" G_GSIZE_FORMAT, in_size,
951 GenTexture data = { 0, };
952 data.width = copy_params->out_width;
953 data.height = copy_params->out_height;
954 data.gl_target = out_tex_target;
955 data.gl_format = out_gl_format;
956 data.gl_type = GL_UNSIGNED_BYTE;
957 if (copy_params->out_format == GST_VIDEO_GL_TEXTURE_TYPE_RGB16)
958 data.gl_type = GL_UNSIGNED_SHORT_5_6_5;
960 _generate_texture (context, &data);
961 tex_id = data.result;
965 GST_CAT_WARNING (GST_CAT_GL_MEMORY,
966 "Could not create GL texture with context:%p", src->context);
969 GST_CAT_LOG (GST_CAT_GL_MEMORY, "copying memory %p, tex %u into texture %i",
970 src, src->tex_id, tex_id);
972 /* FIXME: try and avoid creating and destroying fbo's every copy... */
973 /* create a framebuffer object */
974 gl->GenFramebuffers (1, &fboId);
975 gl->BindFramebuffer (GL_FRAMEBUFFER, fboId);
977 gl->FramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
978 src->tex_target, src->tex_id, 0);
980 // if (!gst_gl_context_check_framebuffer_status (src->context))
983 gl->BindTexture (out_tex_target, tex_id);
984 if (copy_params->respecify) {
985 if (!gl->GenBuffers) {
986 gst_gl_context_set_error (context, "Cannot reinterpret texture contents "
987 "without buffer objects");
988 gl->BindTexture (out_tex_target, 0);
992 if (gst_gl_context_get_gl_api (context) & GST_GL_API_GLES2
993 && (in_gl_format != GL_RGBA || in_gl_type != GL_UNSIGNED_BYTE)) {
994 gst_gl_context_set_error (context, "Cannot copy non RGBA/UNSIGNED_BYTE "
995 "textures on GLES2");
996 gl->BindTexture (out_tex_target, 0);
1001 gl->GenBuffers (1, &src->pbo);
1003 GST_TRACE ("copying texture data with size of %u*%u*%u",
1004 _gl_format_type_n_bytes (in_gl_format, in_gl_type), src->tex_width,
1005 GL_MEM_HEIGHT (src));
1008 gl->BindBuffer (GL_PIXEL_PACK_BUFFER, src->pbo);
1009 gl->BufferData (GL_PIXEL_PACK_BUFFER, in_size, NULL, GL_STREAM_COPY);
1010 gl->ReadPixels (0, 0, src->tex_width, GL_MEM_HEIGHT (src), in_gl_format,
1012 gl->BindBuffer (GL_PIXEL_PACK_BUFFER, 0);
1014 gl->BindBuffer (GL_PIXEL_UNPACK_BUFFER, src->pbo);
1015 gl->TexSubImage2D (out_tex_target, 0, 0, 0, out_width, out_height,
1016 out_gl_format, out_gl_type, 0);
1018 gl->BindBuffer (GL_PIXEL_UNPACK_BUFFER, 0);
1019 } else { /* different sizes */
1020 gl->CopyTexImage2D (out_tex_target, 0, out_gl_format, 0, 0, out_width,
1024 gl->BindTexture (out_tex_target, 0);
1025 gl->BindFramebuffer (GL_FRAMEBUFFER, 0);
1027 gl->DeleteFramebuffers (1, &fboId);
1029 copy_params->tex_id = tex_id;
1030 copy_params->result = TRUE;
1037 gl->DeleteFramebuffers (1, &fboId);
1039 copy_params->tex_id = 0;
1040 copy_params->result = FALSE;
1046 copy_params->result = FALSE;
1052 _gl_mem_copy (GstGLMemory * src, gssize offset, gssize size)
1056 g_mutex_lock (&((GstGLMemory *) src)->lock);
1058 if (GST_GL_MEMORY_FLAG_IS_SET (src, GST_GL_MEMORY_FLAG_NEED_UPLOAD)) {
1059 dest = _gl_mem_new (src->mem.allocator, NULL, src->context, &src->info,
1060 &src->valign, src->plane, NULL, NULL);
1061 dest->data = g_try_malloc (src->mem.maxsize);
1062 if (dest->data == NULL) {
1063 GST_CAT_WARNING (GST_CAT_GL_MEMORY, "Could not copy GL Memory");
1064 gst_memory_unref ((GstMemory *) dest);
1067 memcpy (dest->data, src->data, src->mem.maxsize);
1068 GST_GL_MEMORY_FLAG_SET (dest, GST_GL_MEMORY_FLAG_NEED_UPLOAD);
1070 GstGLMemoryCopyParams copy_params;
1072 copy_params.src = src;
1073 copy_params.tex_id = 0;
1074 copy_params.out_format = src->tex_type;
1075 copy_params.out_width = src->tex_width;
1076 copy_params.out_height = GL_MEM_HEIGHT (src);
1077 copy_params.out_stride = GL_MEM_STRIDE (src);
1078 copy_params.respecify = FALSE;
1080 gst_gl_context_thread_add (src->context, _gl_mem_copy_thread, ©_params);
1082 dest = g_slice_new0 (GstGLMemory);
1083 _gl_mem_init (dest, src->mem.allocator, NULL, src->context, &src->info,
1084 &src->valign, src->plane, NULL, NULL);
1086 if (!copy_params.result) {
1087 GST_CAT_WARNING (GST_CAT_GL_MEMORY, "Could not copy GL Memory");
1088 gst_memory_unref ((GstMemory *) dest);
1092 dest->tex_id = copy_params.tex_id;
1093 dest->data = g_try_malloc (src->mem.maxsize);
1094 if (dest->data == NULL) {
1095 GST_CAT_WARNING (GST_CAT_GL_MEMORY, "Could not copy GL Memory");
1096 gst_memory_unref ((GstMemory *) dest);
1099 GST_GL_MEMORY_FLAG_SET (dest, GST_GL_MEMORY_FLAG_NEED_DOWNLOAD);
1102 g_mutex_unlock (&((GstGLMemory *) src)->lock);
1104 return (GstMemory *) dest;
1108 _gl_mem_share (GstGLMemory * mem, gssize offset, gssize size)
1114 _gl_mem_is_span (GstGLMemory * mem1, GstGLMemory * mem2, gsize * offset)
1120 _gl_mem_alloc (GstAllocator * allocator, gsize size,
1121 GstAllocationParams * params)
1123 g_warning ("use gst_gl_memory_alloc () to allocate from this "
1124 "GstGLMemory allocator");
1130 _destroy_gl_objects (GstGLContext * context, GstGLMemory * gl_mem)
1132 const GstGLFuncs *gl = context->gl_vtable;
1134 if (gl_mem->tex_id && !gl_mem->texture_wrapped)
1135 gl->DeleteTextures (1, &gl_mem->tex_id);
1138 gl->DeleteBuffers (1, &gl_mem->pbo);
1142 _gl_mem_free (GstAllocator * allocator, GstMemory * mem)
1144 GstGLMemory *gl_mem = (GstGLMemory *) mem;
1146 GST_CAT_TRACE (GST_CAT_GL_MEMORY, "freeing texture %u", gl_mem->tex_id);
1148 gst_gl_context_thread_add (gl_mem->context,
1149 (GstGLContextThreadFunc) _destroy_gl_objects, gl_mem);
1152 gl_mem->notify (gl_mem->user_data);
1154 if (gl_mem->data && !gl_mem->data_wrapped) {
1155 g_free (gl_mem->data);
1156 gl_mem->data = NULL;
1159 g_mutex_clear (&gl_mem->lock);
1161 gst_object_unref (gl_mem->context);
1162 g_slice_free (GstGLMemory, gl_mem);
1166 * gst_gl_memory_copy_into_texture:
1167 * @gl_mem:a #GstGLMemory
1168 * @tex_id:OpenGL texture id
1169 * @tex_type: a #GstVideoGLTextureType
1170 * @width: width of @tex_id
1171 * @height: height of @tex_id
1172 * @stride: stride of the backing texture data
1173 * @respecify: whether to copy the data or copy per texel
1175 * Copies @gl_mem into the texture specfified by @tex_id. The format of @tex_id
1176 * is specified by @tex_type, @width and @height.
1178 * If @respecify is %TRUE, then the copy is performed in terms of the texture
1179 * data. This is useful for splitting RGBA textures into RG or R textures or
1180 * vice versa. The requirement for this to succeed is that the backing texture
1181 * data must be the same size, i.e. say a RGBA8 texture is converted into a RG8
1182 * texture, then the RG texture must have twice as many pixels available for
1183 * output as the RGBA texture.
1185 * Otherwise, if @respecify is %FALSE, then the copy is performed per texel
1186 * using glCopyTexImage. See the OpenGL specification for details on the
1187 * mappings between texture formats.
1189 * Returns: Whether the copy suceeded
1192 gst_gl_memory_copy_into_texture (GstGLMemory * gl_mem, guint tex_id,
1193 GstVideoGLTextureType tex_type, gint width, gint height, gint stride,
1196 GstGLMemoryCopyParams copy_params;
1198 copy_params.src = gl_mem;
1199 copy_params.tex_id = tex_id;
1200 copy_params.out_format = tex_type;
1201 copy_params.out_width = width;
1202 copy_params.out_height = height;
1203 copy_params.out_stride = stride;
1204 copy_params.respecify = respecify;
1206 gst_gl_context_thread_add (gl_mem->context, _gl_mem_copy_thread,
1209 return copy_params.result;
1213 * gst_gl_memory_wrapped_texture:
1214 * @context: a #GstGLContext
1215 * @texture_id: the GL texture handle
1216 * @texture_target: the GL texture target
1217 * @info: the #GstVideoInfo of the memory
1218 * @plane: The plane this memory will represent
1219 * @user_data: user data
1220 * @notify: Destroy callback for the user data
1222 * Wraps a texture handle into a #GstGLMemory.
1224 * Returns: a newly allocated #GstGLMemory
1227 gst_gl_memory_wrapped_texture (GstGLContext * context,
1228 guint texture_id, guint texture_target,
1229 GstVideoInfo * info, guint plane, GstVideoAlignment * valign,
1230 gpointer user_data, GDestroyNotify notify)
1234 mem = g_slice_new0 (GstGLMemory);
1235 _gl_mem_init (mem, _gl_allocator, NULL, context, info, valign, plane, NULL,
1238 mem->tex_id = texture_id;
1239 mem->tex_target = texture_target;
1240 mem->texture_wrapped = TRUE;
1241 mem->data = g_try_malloc (mem->mem.maxsize);
1242 if (mem->data == NULL) {
1243 gst_memory_unref ((GstMemory *) mem);
1247 GST_GL_MEMORY_FLAG_SET (mem, GST_GL_MEMORY_FLAG_NEED_DOWNLOAD);
1253 * gst_gl_memory_alloc:
1254 * @context:a #GstGLContext
1255 * @info: the #GstVideoInfo of the memory
1256 * @plane: the plane this memory will represent
1257 * @valign: the #GstVideoAlignment applied to @info
1259 * Allocated a new #GstGlMemory.
1261 * Returns: a #GstMemory object with a GL texture specified by @vinfo
1265 gst_gl_memory_alloc (GstGLContext * context, GstVideoInfo * info,
1266 guint plane, GstVideoAlignment * valign)
1270 mem = _gl_mem_new (_gl_allocator, NULL, context, info, valign, plane, NULL,
1273 mem->data = g_try_malloc (mem->mem.maxsize);
1274 if (mem->data == NULL) {
1275 gst_memory_unref ((GstMemory *) mem);
1279 return (GstMemory *) mem;
1283 * gst_gl_memory_wrapped:
1284 * @context:a #GstGLContext
1285 * @info: the #GstVideoInfo of the memory and data
1286 * @plane: the plane this memory will represent
1287 * @valign: the #GstVideoAlignment applied to @info
1288 * @data: the data to wrap
1289 * @user_data: data called with for @notify
1290 * @notify: function called with @user_data when @data needs to be freed
1292 * Wrapped @data into a #GstGLMemory. This version will account for padding
1293 * added to the allocation and expressed through @valign.
1295 * Returns: a #GstGLMemory object with a GL texture specified by @v_info
1296 * from @context and contents specified by @data
1299 gst_gl_memory_wrapped (GstGLContext * context, GstVideoInfo * info,
1300 guint plane, GstVideoAlignment * valign, gpointer data, gpointer user_data,
1301 GDestroyNotify notify)
1305 mem = _gl_mem_new (_gl_allocator, NULL, context, info, valign, plane,
1309 mem->data_wrapped = TRUE;
1311 GST_GL_MEMORY_FLAG_SET (mem, GST_GL_MEMORY_FLAG_NEED_UPLOAD);
1317 gst_gl_memory_get_texture_width (GstGLMemory * gl_mem)
1319 g_return_val_if_fail (gst_is_gl_memory ((GstMemory *) gl_mem), 0);
1321 return gl_mem->tex_width;
1325 gst_gl_memory_get_texture_height (GstGLMemory * gl_mem)
1327 g_return_val_if_fail (gst_is_gl_memory ((GstMemory *) gl_mem), 0);
1329 return _get_plane_height (&gl_mem->info, gl_mem->plane);
1332 G_DEFINE_TYPE (GstGLAllocator, gst_gl_allocator, GST_TYPE_ALLOCATOR);
1335 gst_gl_allocator_class_init (GstGLAllocatorClass * klass)
1337 GstAllocatorClass *allocator_class;
1339 allocator_class = (GstAllocatorClass *) klass;
1341 allocator_class->alloc = _gl_mem_alloc;
1342 allocator_class->free = _gl_mem_free;
1346 gst_gl_allocator_init (GstGLAllocator * allocator)
1348 GstAllocator *alloc = GST_ALLOCATOR_CAST (allocator);
1350 alloc->mem_type = GST_GL_MEMORY_ALLOCATOR;
1351 alloc->mem_map = (GstMemoryMapFunction) _gl_mem_map;
1352 alloc->mem_unmap = (GstMemoryUnmapFunction) _gl_mem_unmap;
1353 alloc->mem_copy = (GstMemoryCopyFunction) _gl_mem_copy;
1354 alloc->mem_share = (GstMemoryShareFunction) _gl_mem_share;
1355 alloc->mem_is_span = (GstMemoryIsSpanFunction) _gl_mem_is_span;
1359 * gst_gl_memory_init:
1361 * Initializes the GL Memory allocator. It is safe to call this function
1362 * multiple times. This must be called before any other GstGLMemory operation.
1365 gst_gl_memory_init (void)
1367 static volatile gsize _init = 0;
1369 if (g_once_init_enter (&_init)) {
1370 GST_DEBUG_CATEGORY_INIT (GST_CAT_GL_MEMORY, "glmemory", 0, "OpenGL Memory");
1372 _gl_allocator = g_object_new (gst_gl_allocator_get_type (), NULL);
1374 gst_allocator_register (GST_GL_MEMORY_ALLOCATOR,
1375 gst_object_ref (_gl_allocator));
1376 g_once_init_leave (&_init, 1);
1384 * Returns: whether the memory at @mem is a #GstGLMemory
1387 gst_is_gl_memory (GstMemory * mem)
1389 return mem != NULL && mem->allocator == _gl_allocator;
1393 * gst_gl_memory_setup_buffer:
1394 * @context: a #GstGLContext
1395 * @info: a #GstVideoInfo
1396 * @valign: the #GstVideoAlignment applied to @info
1397 * @buffer: a #GstBuffer
1399 * Adds the required #GstGLMemory<!-- -->s with the correct configuration to
1400 * @buffer based on @info. This version handles padding through @valign.
1402 * Returns: whether the memory's were sucessfully added.
1405 gst_gl_memory_setup_buffer (GstGLContext * context, GstVideoInfo * info,
1406 GstVideoAlignment * valign, GstBuffer * buffer)
1408 GstGLMemory *gl_mem[GST_VIDEO_MAX_PLANES] = { NULL, };
1411 n_mem = GST_VIDEO_INFO_N_PLANES (info);
1413 for (i = 0; i < n_mem; i++) {
1414 gl_mem[i] = (GstGLMemory *) gst_gl_memory_alloc (context, info, i, valign);
1415 if (gl_mem[i] == NULL)
1418 gst_buffer_append_memory (buffer, (GstMemory *) gl_mem[i]);
1421 gst_buffer_add_video_meta_full (buffer, 0,
1422 GST_VIDEO_INFO_FORMAT (info), GST_VIDEO_INFO_WIDTH (info),
1423 GST_VIDEO_INFO_HEIGHT (info), n_mem, info->offset, info->stride);
1429 * gst_gl_memory_setup_wrapped:
1430 * @context: a #GstGLContext
1431 * @info: a #GstVideoInfo
1432 * @valign: a #GstVideoInfo
1433 * @data: a list of per plane data pointers
1434 * @textures: (transfer out): a list of #GstGLMemory
1436 * Wraps per plane data pointer in @data into the corresponding entry in
1437 * @textures based on @info and padding from @valign.
1439 * Returns: whether the memory's were sucessfully created.
1442 gst_gl_memory_setup_wrapped (GstGLContext * context, GstVideoInfo * info,
1443 GstVideoAlignment * valign, gpointer data[GST_VIDEO_MAX_PLANES],
1444 GstGLMemory * textures[GST_VIDEO_MAX_PLANES])
1448 for (i = 0; i < GST_VIDEO_INFO_N_PLANES (info); i++) {
1449 textures[i] = (GstGLMemory *) gst_gl_memory_wrapped (context, info, i,
1450 valign, data[i], NULL, NULL);