3 * Copyright (C) 2013 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.
29 #include "gstglutils.h"
31 #if GST_GL_HAVE_WINDOW_X11
32 #include <gst/gl/x11/gstgldisplay_x11.h>
35 #ifndef GL_FRAMEBUFFER_UNDEFINED
36 #define GL_FRAMEBUFFER_UNDEFINED 0x8219
38 #ifndef GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT
39 #define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6
41 #ifndef GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT
42 #define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7
44 #ifndef GL_FRAMEBUFFER_UNSUPPORTED
45 #define GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD
47 #ifndef GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS
48 #define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS 0x8CD9
51 #define USING_OPENGL(context) (gst_gl_context_check_gl_version (context, GST_GL_API_OPENGL, 1, 0))
52 #define USING_OPENGL3(context) (gst_gl_context_check_gl_version (context, GST_GL_API_OPENGL3, 3, 1))
53 #define USING_GLES(context) (gst_gl_context_check_gl_version (context, GST_GL_API_GLES, 1, 0))
54 #define USING_GLES2(context) (gst_gl_context_check_gl_version (context, GST_GL_API_GLES2, 2, 0))
55 #define USING_GLES3(context) (gst_gl_context_check_gl_version (context, GST_GL_API_GLES2, 3, 0))
57 static gchar *error_message;
59 /* called in the gl thread */
61 gst_gl_context_check_framebuffer_status (GstGLContext * context)
64 status = context->gl_vtable->CheckFramebufferStatus (GL_FRAMEBUFFER);
67 case GL_FRAMEBUFFER_COMPLETE:
71 case GL_FRAMEBUFFER_UNSUPPORTED:
72 GST_ERROR ("GL_FRAMEBUFFER_UNSUPPORTED");
75 case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
76 GST_ERROR ("GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT");
79 case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
80 GST_ERROR ("GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT");
82 case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS:
83 GST_ERROR ("GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS");
85 #if GST_GL_HAVE_OPENGL
86 case GL_FRAMEBUFFER_UNDEFINED:
87 GST_ERROR ("GL_FRAMEBUFFER_UNDEFINED");
91 GST_ERROR ("General FBO error");
97 typedef struct _GenTexture
100 GstVideoFormat format;
105 _gen_texture (GstGLContext * context, GenTexture * data)
107 const GstGLFuncs *gl = context->gl_vtable;
109 GST_TRACE ("Generating texture format:%u dimensions:%ux%u", data->format,
110 data->width, data->height);
112 gl->GenTextures (1, &data->result);
113 gl->BindTexture (GL_TEXTURE_2D, data->result);
115 if (data->width > 0 && data->height > 0)
116 gl->TexImage2D (GL_TEXTURE_2D, 0, GL_RGBA8, data->width,
117 data->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
119 gl->TexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
120 gl->TexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
121 gl->TexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
122 gl->TexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
124 GST_LOG ("generated texture id:%d", data->result);
128 gst_gl_context_gen_texture (GstGLContext * context, GLuint * pTexture,
129 GstVideoFormat v_format, GLint width, GLint height)
131 GenTexture data = { width, height, v_format, 0 };
133 gst_gl_context_thread_add (context, (GstGLContextThreadFunc) _gen_texture,
136 *pTexture = data.result;
140 _del_texture (GstGLContext * context, guint * texture)
142 context->gl_vtable->DeleteTextures (1, texture);
146 gst_gl_context_del_texture (GstGLContext * context, GLuint * pTexture)
148 gst_gl_context_thread_add (context, (GstGLContextThreadFunc) _del_texture,
152 typedef struct _GenTextureFull
154 const GstVideoInfo *info;
160 _gen_texture_full (GstGLContext * context, GenTextureFull * data)
162 const GstGLFuncs *gl = context->gl_vtable;
163 GLint glinternalformat = 0;
167 gl->GenTextures (1, &data->result);
168 gl->BindTexture (GL_TEXTURE_2D, data->result);
170 switch (GST_VIDEO_INFO_FORMAT (data->info)) {
171 case GST_VIDEO_FORMAT_RGB:
172 case GST_VIDEO_FORMAT_BGR:
174 glinternalformat = GL_RGB8;
176 gltype = GL_UNSIGNED_BYTE;
179 case GST_VIDEO_FORMAT_RGB16:
181 glinternalformat = GL_RGB16;
183 gltype = GL_UNSIGNED_SHORT_5_6_5;
186 case GST_VIDEO_FORMAT_RGBA:
187 case GST_VIDEO_FORMAT_BGRA:
188 case GST_VIDEO_FORMAT_ARGB:
189 case GST_VIDEO_FORMAT_ABGR:
190 case GST_VIDEO_FORMAT_RGBx:
191 case GST_VIDEO_FORMAT_BGRx:
192 case GST_VIDEO_FORMAT_xRGB:
193 case GST_VIDEO_FORMAT_xBGR:
194 case GST_VIDEO_FORMAT_AYUV:
196 glinternalformat = GL_RGBA8;
198 gltype = GL_UNSIGNED_BYTE;
201 case GST_VIDEO_FORMAT_NV12:
202 case GST_VIDEO_FORMAT_NV21:
204 glinternalformat = GL_LUMINANCE;
205 glformat = data->comp == 0 ? GL_LUMINANCE : GL_LUMINANCE_ALPHA;
206 gltype = GL_UNSIGNED_BYTE;
209 case GST_VIDEO_FORMAT_I420:
210 case GST_VIDEO_FORMAT_YV12:
211 case GST_VIDEO_FORMAT_Y444:
212 case GST_VIDEO_FORMAT_Y42B:
213 case GST_VIDEO_FORMAT_Y41B:
215 glformat = GL_LUMINANCE;
216 gltype = GL_UNSIGNED_BYTE;
220 GST_WARNING ("unsupported %s",
221 gst_video_format_to_string (GST_VIDEO_INFO_FORMAT (data->info)));
225 gl->TexImage2D (GL_TEXTURE_2D, 0, glinternalformat,
226 GST_VIDEO_INFO_COMP_WIDTH (data->info, data->comp),
227 GST_VIDEO_INFO_COMP_HEIGHT (data->info, data->comp), 0, glformat, gltype,
230 gl->TexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
231 gl->TexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
232 gl->TexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
233 gl->TexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
237 gst_gl_generate_texture_full (GstGLContext * context, const GstVideoInfo * info,
238 const guint comp, gint stride[], gsize offset[], gsize size[],
241 GenTextureFull data = { info, comp, 0 };
243 switch (GST_VIDEO_INFO_FORMAT (info)) {
244 case GST_VIDEO_FORMAT_RGB:
245 case GST_VIDEO_FORMAT_BGR:
247 stride[0] = GST_ROUND_UP_4 (GST_VIDEO_INFO_WIDTH (info) * 3);
249 size[0] = stride[0] * GST_VIDEO_INFO_HEIGHT (info);
252 case GST_VIDEO_FORMAT_RGB16:
254 stride[0] = GST_ROUND_UP_4 (GST_VIDEO_INFO_WIDTH (info) * 2);
256 size[0] = stride[0] * GST_VIDEO_INFO_HEIGHT (info);
259 case GST_VIDEO_FORMAT_RGBA:
260 case GST_VIDEO_FORMAT_BGRA:
261 case GST_VIDEO_FORMAT_ARGB:
262 case GST_VIDEO_FORMAT_ABGR:
263 case GST_VIDEO_FORMAT_RGBx:
264 case GST_VIDEO_FORMAT_BGRx:
265 case GST_VIDEO_FORMAT_xRGB:
266 case GST_VIDEO_FORMAT_xBGR:
267 case GST_VIDEO_FORMAT_AYUV:
269 stride[0] = GST_ROUND_UP_4 (GST_VIDEO_INFO_WIDTH (info) * 4);
271 size[0] = stride[0] * GST_VIDEO_INFO_HEIGHT (info);
274 case GST_VIDEO_FORMAT_NV12:
275 case GST_VIDEO_FORMAT_NV21:
277 size[comp] = stride[comp] * GST_VIDEO_INFO_COMP_HEIGHT (info, comp);
279 stride[0] = GST_ROUND_UP_4 (GST_VIDEO_INFO_COMP_WIDTH (info, 1));
282 stride[1] = GST_ROUND_UP_4 (GST_VIDEO_INFO_COMP_WIDTH (info, 1) * 2);
287 case GST_VIDEO_FORMAT_I420:
288 case GST_VIDEO_FORMAT_YV12:
289 case GST_VIDEO_FORMAT_Y444:
290 case GST_VIDEO_FORMAT_Y42B:
291 case GST_VIDEO_FORMAT_Y41B:
293 stride[comp] = GST_ROUND_UP_4 (GST_VIDEO_INFO_COMP_WIDTH (info, comp));;
294 size[comp] = stride[comp] * GST_VIDEO_INFO_COMP_HEIGHT (info, comp);
300 offset[2] = offset[1] + size[1];
304 GST_WARNING ("unsupported %s",
305 gst_video_format_to_string (GST_VIDEO_INFO_FORMAT (info)));
309 gst_gl_context_thread_add (context,
310 (GstGLContextThreadFunc) _gen_texture_full, &data);
312 *pTexture = data.result;
315 typedef struct _GenFBO
317 GstGLFramebuffer *frame;
323 _gen_fbo (GstGLContext * context, GenFBO * data)
325 gst_gl_framebuffer_generate (data->frame, data->width, data->height,
326 data->fbo, data->depth);
330 gst_gl_context_gen_fbo (GstGLContext * context, gint width, gint height,
331 GLuint * fbo, GLuint * depthbuffer)
333 GstGLFramebuffer *frame = gst_gl_framebuffer_new (context);
335 GenFBO data = { frame, width, height, fbo, depthbuffer };
337 gst_gl_context_thread_add (context, (GstGLContextThreadFunc) _gen_fbo, &data);
339 gst_object_unref (frame);
344 typedef struct _UseFBO2
346 GstGLFramebuffer *frame;
347 gint texture_fbo_width;
348 gint texture_fbo_height;
357 _use_fbo_v2 (GstGLContext * context, UseFBO2 * data)
359 gst_gl_framebuffer_use_v2 (data->frame, data->texture_fbo_width,
360 data->texture_fbo_height, data->fbo, data->depth_buffer,
361 data->texture_fbo, data->cb, data->stuff);
365 gst_gl_context_use_fbo_v2 (GstGLContext * context, gint texture_fbo_width,
366 gint texture_fbo_height, GLuint fbo, GLuint depth_buffer,
367 GLuint texture_fbo, GLCB_V2 cb, gpointer stuff)
369 GstGLFramebuffer *frame = gst_gl_framebuffer_new (context);
372 { frame, texture_fbo_width, texture_fbo_height, fbo, depth_buffer,
373 texture_fbo, cb, stuff
376 gst_gl_context_thread_add (context, (GstGLContextThreadFunc) _use_fbo_v2,
379 gst_object_unref (frame);
384 typedef struct _DelFBO
386 GstGLFramebuffer *frame;
391 /* Called in the gl thread */
393 _del_fbo (GstGLContext * context, DelFBO * data)
395 gst_gl_framebuffer_delete (data->frame, data->fbo, data->depth);
398 /* Called by gltestsrc and glfilter */
400 gst_gl_context_del_fbo (GstGLContext * context, GLuint fbo, GLuint depth_buffer)
402 GstGLFramebuffer *frame = gst_gl_framebuffer_new (context);
404 DelFBO data = { frame, fbo, depth_buffer };
406 gst_gl_context_thread_add (context, (GstGLContextThreadFunc) _del_fbo, &data);
408 gst_object_unref (frame);
412 _compile_shader (GstGLContext * context, GstGLShader ** shader)
414 GError *error = NULL;
416 gst_gl_shader_compile (*shader, &error);
418 gst_gl_context_set_error (context, "%s", error->message);
419 g_error_free (error);
421 gst_gl_context_clear_shader (context);
422 gst_object_unref (*shader);
427 /* Called by glfilter */
429 gst_gl_context_gen_shader (GstGLContext * context, const gchar * vert_src,
430 const gchar * frag_src, GstGLShader ** shader)
432 g_return_val_if_fail (frag_src != NULL || vert_src != NULL, FALSE);
433 g_return_val_if_fail (shader != NULL, FALSE);
435 *shader = gst_gl_shader_new (context);
438 gst_gl_shader_set_fragment_source (*shader, frag_src);
440 gst_gl_shader_set_vertex_source (*shader, vert_src);
442 gst_gl_context_thread_add (context, (GstGLContextThreadFunc) _compile_shader,
445 return *shader != NULL;
449 gst_gl_context_set_error (GstGLContext * context, const char *format, ...)
454 g_free (error_message);
456 va_start (args, format);
457 error_message = g_strdup_vprintf (format, args);
460 GST_WARNING ("%s", error_message);
464 gst_gl_context_get_error (void)
466 return error_message;
469 /* Called by glfilter */
471 gst_gl_context_del_shader (GstGLContext * context, GstGLShader * shader)
473 gst_object_unref (shader);
477 gst_gl_display_found (GstElement * element, GstGLDisplay * display)
480 GST_LOG_OBJECT (element, "already have a display (%p)", display);
487 GST_DEBUG_CATEGORY_STATIC (GST_CAT_CONTEXT);
490 context_pad_query (const GValue * item, GValue * value, gpointer user_data)
492 GstPad *pad = g_value_get_object (item);
493 GstQuery *query = user_data;
496 res = gst_pad_peer_query (pad, query);
499 g_value_set_boolean (value, TRUE);
503 GST_CAT_INFO_OBJECT (GST_CAT_CONTEXT, pad, "context pad peer query failed");
508 run_context_query (GstElement * element, GstQuery * query,
509 GstPadDirection direction)
512 GstIteratorFoldFunction func = context_pad_query;
515 g_value_init (&res, G_TYPE_BOOLEAN);
516 g_value_set_boolean (&res, FALSE);
519 if (direction == GST_PAD_SRC)
520 it = gst_element_iterate_src_pads (element);
522 it = gst_element_iterate_sink_pads (element);
524 while (gst_iterator_fold (it, func, &res, query) == GST_ITERATOR_RESYNC)
525 gst_iterator_resync (it);
527 gst_iterator_free (it);
529 return g_value_get_boolean (&res);
533 _gst_context_query (GstElement * element,
534 gpointer ptr, const gchar * display_type)
539 /* 2a) Query downstream with GST_QUERY_CONTEXT for the context and
540 * check if downstream already has a context of the specific type
541 * 2b) Query upstream as above.
543 query = gst_query_new_context (display_type);
544 if (run_context_query (element, query, GST_PAD_SRC)) {
545 gst_query_parse_context (query, &ctxt);
546 GST_CAT_INFO_OBJECT (GST_CAT_CONTEXT, element,
547 "found context (%p) in downstream query", ctxt);
548 } else if (run_context_query (element, query, GST_PAD_SINK)) {
549 gst_query_parse_context (query, &ctxt);
550 GST_CAT_INFO_OBJECT (GST_CAT_CONTEXT, element,
551 "found context (%p) in upstream query", ctxt);
553 /* 3) Post a GST_MESSAGE_NEED_CONTEXT message on the bus with
554 * the required context type and afterwards check if a
555 * usable context was set now as in 1). The message could
556 * be handled by the parent bins of the element and the
561 GST_CAT_INFO_OBJECT (GST_CAT_CONTEXT, element,
562 "posting need context message");
563 msg = gst_message_new_need_context (GST_OBJECT_CAST (element),
565 gst_element_post_message (element, msg);
569 * Whomever responds to the need-context message performs a
570 * GstElement::set_context() with the required context in which the element
571 * is required to update the display_ptr or call gst_gl_handle_set_context().
578 gst_gl_display_context_query (GstElement * element, GstGLDisplay ** display_ptr)
583 #ifndef GST_DISABLE_GST_DEBUG
584 if (!GST_CAT_CONTEXT)
585 GST_DEBUG_CATEGORY_GET (GST_CAT_CONTEXT, "GST_CONTEXT");
589 _gst_context_query (element, display_ptr, GST_GL_DISPLAY_CONTEXT_TYPE);
590 gst_query_parse_context (query, &ctxt);
591 if (ctxt && gst_context_has_context_type (ctxt, GST_GL_DISPLAY_CONTEXT_TYPE))
592 gst_context_get_gl_display (ctxt, display_ptr);
597 #if GST_GL_HAVE_WINDOW_X11
598 gst_query_unref (query);
599 query = _gst_context_query (element, display_ptr, "gst.x11.display.handle");
600 gst_query_parse_context (query, &ctxt);
601 if (ctxt && gst_context_has_context_type (ctxt, "gst.x11.display.handle")) {
602 const GstStructure *s;
605 s = gst_context_get_structure (ctxt);
606 if (gst_structure_get (s, "display", G_TYPE_POINTER, &display, NULL)
609 (GstGLDisplay *) gst_gl_display_x11_new_with_display (display);
618 gst_query_unref (query);
622 gst_gl_context_query (GstElement * element, GstGLContext ** context_ptr)
627 #ifndef GST_DISABLE_GST_DEBUG
628 if (!GST_CAT_CONTEXT)
629 GST_DEBUG_CATEGORY_GET (GST_CAT_CONTEXT, "GST_CONTEXT");
632 query = _gst_context_query (element, context_ptr, "gst.gl.app_context");
633 gst_query_parse_context (query, &ctxt);
634 if (ctxt && gst_context_has_context_type (ctxt, "gst.gl.app_context")) {
635 const GstStructure *s = gst_context_get_structure (ctxt);
636 gst_structure_get (s, "context", GST_GL_TYPE_CONTEXT, context_ptr, NULL);
639 gst_query_unref (query);
642 /* 4) Create a context by itself and post a GST_MESSAGE_HAVE_CONTEXT
646 gst_gl_display_context_propagate (GstElement * element, GstGLDisplay * display)
652 GST_ERROR_OBJECT (element, "Could not get GL display connection");
656 context = gst_context_new (GST_GL_DISPLAY_CONTEXT_TYPE, TRUE);
657 gst_context_set_gl_display (context, display);
659 GST_CAT_INFO_OBJECT (GST_CAT_CONTEXT, element,
660 "posting have context (%p) message with display (%p)", context, display);
661 msg = gst_message_new_have_context (GST_OBJECT_CAST (element), context);
662 gst_element_post_message (GST_ELEMENT_CAST (element), msg);
666 gst_gl_ensure_element_data (gpointer element, GstGLDisplay ** display_ptr,
667 GstGLContext ** context_ptr)
669 GstGLDisplay *display;
671 g_return_val_if_fail (element != NULL, FALSE);
672 g_return_val_if_fail (display_ptr != NULL, FALSE);
673 g_return_val_if_fail (context_ptr != NULL, FALSE);
675 /* 1) Check if the element already has a context of the specific
678 display = *display_ptr;
679 if (gst_gl_display_found (element, display))
682 gst_gl_display_context_query (element, display_ptr);
684 /* Neighbour found and it updated the display */
685 if (gst_gl_display_found (element, *display_ptr))
688 /* If no neighboor, or application not interested, use system default */
689 display = gst_gl_display_new ();
691 *display_ptr = display;
693 gst_gl_display_context_propagate (element, display);
699 gst_gl_context_query (element, context_ptr);
702 return *display_ptr != NULL;
706 gst_gl_handle_set_context (GstElement * element, GstContext * context,
707 GstGLDisplay ** display, GstGLContext ** other_context)
709 GstGLDisplay *display_replacement = NULL;
710 GstGLContext *context_replacement = NULL;
711 const gchar *context_type;
713 g_return_val_if_fail (display != NULL, FALSE);
714 g_return_val_if_fail (other_context != NULL, FALSE);
719 context_type = gst_context_get_context_type (context);
721 if (g_strcmp0 (context_type, GST_GL_DISPLAY_CONTEXT_TYPE) == 0) {
722 if (!gst_context_get_gl_display (context, &display_replacement)) {
723 GST_WARNING_OBJECT (element, "Failed to get display from context");
727 #if GST_GL_HAVE_WINDOW_X11
728 else if (g_strcmp0 (context_type, "gst.x11.display.handle") == 0) {
729 const GstStructure *s;
732 s = gst_context_get_structure (context);
733 if (gst_structure_get (s, "display", G_TYPE_POINTER, &display, NULL))
734 display_replacement =
735 (GstGLDisplay *) gst_gl_display_x11_new_with_display (display);
738 else if (g_strcmp0 (context_type, "gst.gl.app_context") == 0) {
739 const GstStructure *s = gst_context_get_structure (context);
740 GstGLDisplay *context_display;
741 GstGLDisplay *element_display;
743 if (gst_structure_get (s, "context", GST_GL_TYPE_CONTEXT,
744 &context_replacement, NULL)) {
745 context_display = gst_gl_context_get_display (context_replacement);
746 element_display = display_replacement ? display_replacement : *display;
748 && (gst_gl_display_get_handle_type (element_display) &
749 gst_gl_display_get_handle_type (context_display)) == 0) {
750 GST_ELEMENT_WARNING (element, LIBRARY, SETTINGS, ("%s",
751 "Cannot set a GL context with a different display type"), ("%s",
752 "Cannot set a GL context with a different display type"));
753 gst_object_unref (context_replacement);
754 context_replacement = NULL;
756 gst_object_unref (context_display);
760 if (display_replacement) {
761 GstGLDisplay *old = *display;
762 *display = display_replacement;
765 gst_object_unref (old);
768 if (context_replacement) {
769 GstGLContext *old = *other_context;
770 *other_context = context_replacement;
773 gst_object_unref (old);
780 gst_gl_handle_context_query (GstElement * element, GstQuery * query,
781 GstGLDisplay ** display, GstGLContext ** other_context)
783 gboolean res = FALSE;
784 const gchar *context_type;
785 GstContext *context, *old_context;
787 g_return_val_if_fail (element != NULL, FALSE);
788 g_return_val_if_fail (query != NULL, FALSE);
789 g_return_val_if_fail (display != NULL, FALSE);
790 g_return_val_if_fail (other_context != NULL, FALSE);
792 gst_query_parse_context_type (query, &context_type);
794 if (g_strcmp0 (context_type, GST_GL_DISPLAY_CONTEXT_TYPE) == 0) {
796 gst_query_parse_context (query, &old_context);
799 context = gst_context_copy (old_context);
801 context = gst_context_new (GST_GL_DISPLAY_CONTEXT_TYPE, TRUE);
803 gst_context_set_gl_display (context, *display);
804 gst_query_set_context (query, context);
805 gst_context_unref (context);
807 res = *display != NULL;
809 #if GST_GL_HAVE_WINDOW_X11
810 else if (g_strcmp0 (context_type, "gst.x11.display.handle") == 0) {
812 Display *x11_display = NULL;
814 gst_query_parse_context (query, &old_context);
817 context = gst_context_copy (old_context);
819 context = gst_context_new ("gst.x11.display.handle", TRUE);
822 && ((*display)->type & GST_GL_DISPLAY_TYPE_X11) ==
823 GST_GL_DISPLAY_TYPE_X11)
824 x11_display = (Display *) gst_gl_display_get_handle (*display);
826 s = gst_context_writable_structure (context);
827 gst_structure_set (s, "display", G_TYPE_POINTER, x11_display, NULL);
829 gst_query_set_context (query, context);
830 gst_context_unref (context);
832 res = x11_display != NULL;
835 else if (g_strcmp0 (context_type, "gst.gl.app_context") == 0) {
838 gst_query_parse_context (query, &old_context);
841 context = gst_context_copy (old_context);
843 context = gst_context_new ("gst.gl.app_context", TRUE);
845 s = gst_context_writable_structure (context);
846 gst_structure_set (s, "context", GST_GL_TYPE_CONTEXT, *other_context, NULL);
847 gst_query_set_context (query, context);
848 gst_context_unref (context);
850 res = *other_context != NULL;
857 gst_gl_get_plane_data_size (GstVideoInfo * info, GstVideoAlignment * align,
863 padded_height = info->height;
866 padded_height += align->padding_top + align->padding_bottom;
869 GST_VIDEO_FORMAT_INFO_SCALE_HEIGHT (info->finfo, plane, padded_height);
871 plane_size = GST_VIDEO_INFO_PLANE_STRIDE (info, plane) * padded_height;
877 gst_gl_caps_replace_all_caps_features (const GstCaps * caps,
878 const gchar * feature_name)
880 GstCaps *tmp = gst_caps_copy (caps);
881 guint n = gst_caps_get_size (tmp);
884 for (i = 0; i < n; i++) {
885 GstCapsFeatures *features = gst_caps_get_features (tmp, i);
887 guint n_f = gst_caps_features_get_size (features);
889 for (j = 0; j < n_f; j++) {
890 gst_caps_features_remove_id (features,
891 gst_caps_features_get_nth_id (features, j));
895 gst_caps_features_add (features, feature_name);