3 * Copyright (C) 2015 Lubosz Sarnecki <lubosz.sarnecki@collabora.co.uk>
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.
22 * SECTION:gstgloverlaycompositor
23 * @title: GstGLOverlayCompositor
24 * @short_description: Composite multiple overlays using OpenGL
25 * @see_also: #GstGLMemory, #GstGLContext
34 #include "gstgloverlaycompositor.h"
36 #include <gst/gl/gl.h>
37 #include <gst/gl/gstglfuncs.h>
39 GST_DEBUG_CATEGORY_STATIC (gst_gl_overlay_compositor_debug);
40 #define GST_CAT_DEFAULT gst_gl_overlay_compositor_debug
42 /*****************************************************************************
43 * GstGLCompositionOverlay object is internally used by GstGLOverlayCompositor
44 *****************************************************************************/
46 #define GST_TYPE_GL_COMPOSITION_OVERLAY (gst_gl_composition_overlay_get_type())
47 #define GST_GL_COMPOSITION_OVERLAY(obj) \
48 (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_GL_COMPOSITION_OVERLAY,\
49 GstGLCompositionOverlay))
51 typedef struct _GstGLCompositionOverlay GstGLCompositionOverlay;
52 typedef struct _GstGLCompositionOverlayClass GstGLCompositionOverlayClass;
54 static GType gst_gl_composition_overlay_get_type (void);
57 const gchar *fragment_shader =
58 "varying vec2 v_texcoord;\n"
59 "uniform sampler2D tex;\n"
62 " vec4 t = texture2D(tex, v_texcoord);\n"
63 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
64 " gl_FragColor = t.bgra;\n"
66 " gl_FragColor = t.gbar;\n"
71 struct _GstGLCompositionOverlay
74 GstGLContext *context;
78 GLuint position_buffer;
79 GLuint texcoord_buffer;
80 GLint position_attrib;
81 GLint texcoord_attrib;
83 GLfloat positions[16];
86 GstGLMemory *gl_memory;
87 GstVideoOverlayRectangle *rectangle;
92 struct _GstGLCompositionOverlayClass
94 GstObjectClass object_class;
97 G_DEFINE_TYPE (GstGLCompositionOverlay, gst_gl_composition_overlay,
101 gst_gl_composition_overlay_init_vertex_buffer (GstGLContext * context,
102 gpointer overlay_pointer)
104 const GstGLFuncs *gl = context->gl_vtable;
105 GstGLCompositionOverlay *overlay =
106 (GstGLCompositionOverlay *) overlay_pointer;
109 static const GLfloat texcoords[] = {
116 static const GLushort indices[] = {
121 if (gl->GenVertexArrays) {
122 gl->GenVertexArrays (1, &overlay->vao);
123 gl->BindVertexArray (overlay->vao);
126 gl->GenBuffers (1, &overlay->position_buffer);
127 gl->BindBuffer (GL_ARRAY_BUFFER, overlay->position_buffer);
128 gl->BufferData (GL_ARRAY_BUFFER, 4 * 4 * sizeof (GLfloat), overlay->positions,
131 /* Load the vertex position */
132 gl->VertexAttribPointer (overlay->position_attrib, 4, GL_FLOAT, GL_FALSE,
133 4 * sizeof (GLfloat), NULL);
135 gl->GenBuffers (1, &overlay->texcoord_buffer);
136 gl->BindBuffer (GL_ARRAY_BUFFER, overlay->texcoord_buffer);
137 gl->BufferData (GL_ARRAY_BUFFER, 4 * 2 * sizeof (GLfloat), texcoords,
140 /* Load the texture coordinate */
141 gl->VertexAttribPointer (overlay->texcoord_attrib, 2, GL_FLOAT, GL_FALSE,
142 2 * sizeof (GLfloat), NULL);
144 gl->GenBuffers (1, &overlay->index_buffer);
145 gl->BindBuffer (GL_ELEMENT_ARRAY_BUFFER, overlay->index_buffer);
146 gl->BufferData (GL_ELEMENT_ARRAY_BUFFER, sizeof (indices), indices,
149 gl->EnableVertexAttribArray (overlay->position_attrib);
150 gl->EnableVertexAttribArray (overlay->texcoord_attrib);
152 if (gl->GenVertexArrays) {
153 gl->BindVertexArray (0);
156 gl->BindBuffer (GL_ELEMENT_ARRAY_BUFFER, 0);
157 gl->BindBuffer (GL_ARRAY_BUFFER, 0);
161 gst_gl_composition_overlay_free_vertex_buffer (GstGLContext * context,
162 gpointer overlay_pointer)
164 const GstGLFuncs *gl = context->gl_vtable;
165 GstGLCompositionOverlay *overlay =
166 (GstGLCompositionOverlay *) overlay_pointer;
168 gl->DeleteVertexArrays (1, &overlay->vao);
172 if (overlay->position_buffer) {
173 gl->DeleteBuffers (1, &overlay->position_buffer);
174 overlay->position_buffer = 0;
177 if (overlay->texcoord_buffer) {
178 gl->DeleteBuffers (1, &overlay->texcoord_buffer);
179 overlay->texcoord_buffer = 0;
182 if (overlay->index_buffer) {
183 gl->DeleteBuffers (1, &overlay->index_buffer);
184 overlay->index_buffer = 0;
189 gst_gl_composition_overlay_bind_vertex_buffer (GstGLCompositionOverlay *
192 const GstGLFuncs *gl = overlay->context->gl_vtable;
193 gl->BindBuffer (GL_ARRAY_BUFFER, overlay->position_buffer);
194 gl->VertexAttribPointer (overlay->position_attrib, 4, GL_FLOAT, GL_FALSE,
195 4 * sizeof (GLfloat), NULL);
197 gl->BindBuffer (GL_ARRAY_BUFFER, overlay->texcoord_buffer);
198 gl->VertexAttribPointer (overlay->texcoord_attrib, 2, GL_FLOAT, GL_FALSE,
199 2 * sizeof (GLfloat), NULL);
201 gl->BindBuffer (GL_ELEMENT_ARRAY_BUFFER, overlay->index_buffer);
203 gl->EnableVertexAttribArray (overlay->position_attrib);
204 gl->EnableVertexAttribArray (overlay->texcoord_attrib);
208 gst_gl_composition_overlay_finalize (GObject * object)
210 GstGLCompositionOverlay *overlay;
212 overlay = GST_GL_COMPOSITION_OVERLAY (object);
214 if (overlay->gl_memory)
215 gst_memory_unref ((GstMemory *) overlay->gl_memory);
217 if (overlay->context) {
218 gst_gl_context_thread_add (overlay->context,
219 gst_gl_composition_overlay_free_vertex_buffer, overlay);
220 gst_object_unref (overlay->context);
223 G_OBJECT_CLASS (gst_gl_composition_overlay_parent_class)->finalize (object);
228 gst_gl_composition_overlay_class_init (GstGLCompositionOverlayClass * klass)
230 G_OBJECT_CLASS (klass)->finalize = gst_gl_composition_overlay_finalize;
234 gst_gl_composition_overlay_init (GstGLCompositionOverlay * overlay)
239 gst_gl_composition_overlay_add_transformation (GstGLCompositionOverlay *
240 overlay, GstBuffer * video_buffer)
243 guint comp_width, comp_height;
248 float rel_x, rel_y, rel_w, rel_h;
250 meta = gst_buffer_get_video_meta (video_buffer);
252 GST_WARNING_OBJECT (overlay, "buffer doesn't contain video meta");
256 gst_video_overlay_rectangle_get_render_rectangle (overlay->rectangle,
257 &comp_x, &comp_y, &comp_width, &comp_height);
260 height = meta->height;
262 /* calculate relative position */
263 rel_x = (float) comp_x / (float) width;
264 rel_y = (float) comp_y / (float) height;
266 rel_w = (float) comp_width / (float) width;
267 rel_h = (float) comp_height / (float) height;
269 /* transform from [0,1] to [-1,1], invert y axis */
270 rel_x = rel_x * 2.0 - 1.0;
271 rel_y = (1.0 - rel_y) * 2.0 - 1.0;
276 yswap = overlay->yinvert ? -1. : 1.;
278 /* initialize position array */
279 overlay->positions[0] = rel_x + rel_w;
280 overlay->positions[1] = rel_y * yswap;
281 overlay->positions[2] = 0.0;
282 overlay->positions[3] = 1.0;
283 overlay->positions[4] = rel_x;
284 overlay->positions[5] = rel_y * yswap;
285 overlay->positions[6] = 0.0;
286 overlay->positions[7] = 1.0;
287 overlay->positions[8] = rel_x;
288 overlay->positions[9] = (rel_y - rel_h) * yswap;
289 overlay->positions[10] = 0.0;
290 overlay->positions[11] = 1.0;
291 overlay->positions[12] = rel_x + rel_w;
292 overlay->positions[13] = (rel_y - rel_h) * yswap;
293 overlay->positions[14] = 0.0;
294 overlay->positions[15] = 1.0;
296 gst_gl_context_thread_add (overlay->context,
297 gst_gl_composition_overlay_free_vertex_buffer, overlay);
299 gst_gl_context_thread_add (overlay->context,
300 gst_gl_composition_overlay_init_vertex_buffer, overlay);
303 ("overlay position: (%d,%d) size: %dx%d video size: %dx%d",
304 comp_x, comp_y, comp_width, comp_height, meta->width, meta->height);
307 /* helper object API functions */
309 static GstGLCompositionOverlay *
310 gst_gl_composition_overlay_new (GstGLContext * context,
311 GstVideoOverlayRectangle * rectangle,
312 GLint position_attrib, GLint texcoord_attrib)
314 GstGLCompositionOverlay *overlay =
315 g_object_new (GST_TYPE_GL_COMPOSITION_OVERLAY, NULL);
317 overlay->gl_memory = NULL;
318 overlay->texture_id = -1;
319 overlay->rectangle = rectangle;
320 overlay->context = gst_object_ref (context);
322 overlay->position_attrib = position_attrib;
323 overlay->texcoord_attrib = texcoord_attrib;
325 GST_DEBUG_OBJECT (overlay, "Created new GstGLCompositionOverlay");
331 _video_frame_unmap_and_free (gpointer user_data)
333 GstVideoFrame *frame = user_data;
335 gst_video_frame_unmap (frame);
336 g_slice_free (GstVideoFrame, frame);
340 gst_gl_composition_overlay_upload (GstGLCompositionOverlay * overlay,
343 GstGLMemory *comp_gl_memory = NULL;
344 GstBuffer *comp_buffer = NULL;
345 GstBuffer *overlay_buffer = NULL;
348 GstVideoFrame *comp_frame;
349 GstVideoFrame gl_frame;
350 GstVideoOverlayFormatFlags flags;
351 GstVideoOverlayFormatFlags alpha_flags;
353 flags = gst_video_overlay_rectangle_get_flags (overlay->rectangle);
355 if (flags & GST_VIDEO_OVERLAY_FORMAT_FLAG_PREMULTIPLIED_ALPHA) {
356 alpha_flags = GST_VIDEO_OVERLAY_FORMAT_FLAG_PREMULTIPLIED_ALPHA;
357 } else if (!overlay->context->gl_vtable->BlendFuncSeparate) {
358 GST_FIXME_OBJECT (overlay, "No separate blend mode function, "
359 "cannot perform correct blending of unmultipled alpha in OpenGL. "
360 "Software converting");
361 alpha_flags = GST_VIDEO_OVERLAY_FORMAT_FLAG_PREMULTIPLIED_ALPHA;
367 gst_video_overlay_rectangle_get_pixels_unscaled_argb (overlay->rectangle,
370 comp_frame = g_slice_new (GstVideoFrame);
372 vmeta = gst_buffer_get_video_meta (comp_buffer);
373 gst_video_info_set_format (&vinfo, vmeta->format, vmeta->width,
375 vinfo.stride[0] = vmeta->stride[0];
377 if (gst_video_frame_map (comp_frame, &vinfo, comp_buffer, GST_MAP_READ)) {
378 GstGLVideoAllocationParams *params;
379 GstGLBaseMemoryAllocator *mem_allocator;
380 GstAllocator *allocator;
383 GST_ALLOCATOR (gst_gl_memory_allocator_get_default (overlay->context));
384 mem_allocator = GST_GL_BASE_MEMORY_ALLOCATOR (allocator);
386 gst_gl_composition_overlay_add_transformation (overlay, buf);
388 params = gst_gl_video_allocation_params_new_wrapped_data (overlay->context,
389 NULL, &comp_frame->info, 0, NULL, GST_GL_TEXTURE_TARGET_2D,
390 GST_GL_RGBA, comp_frame->data[0], comp_frame,
391 _video_frame_unmap_and_free);
394 (GstGLMemory *) gst_gl_base_memory_alloc (mem_allocator,
395 (GstGLAllocationParams *) params);
397 gst_gl_allocation_params_free ((GstGLAllocationParams *) params);
398 gst_object_unref (allocator);
400 overlay_buffer = gst_buffer_new ();
401 gst_buffer_append_memory (overlay_buffer, (GstMemory *) comp_gl_memory);
403 if (!gst_video_frame_map (&gl_frame, &comp_frame->info, overlay_buffer,
404 GST_MAP_READ | GST_MAP_GL)) {
405 gst_buffer_unref (overlay_buffer);
406 _video_frame_unmap_and_free (comp_frame);
407 GST_WARNING_OBJECT (overlay, "Cannot upload overlay texture");
411 gst_memory_ref ((GstMemory *) comp_gl_memory);
412 overlay->gl_memory = comp_gl_memory;
413 overlay->texture_id = comp_gl_memory->tex_id;
415 gst_buffer_unref (overlay_buffer);
416 gst_video_frame_unmap (&gl_frame);
418 GST_DEBUG ("uploaded overlay texture %d", overlay->texture_id);
420 g_slice_free (GstVideoFrame, comp_frame);
425 gst_gl_composition_overlay_draw (GstGLCompositionOverlay * overlay,
426 GstGLShader * shader)
428 const GstGLFuncs *gl = overlay->context->gl_vtable;
429 if (gl->GenVertexArrays)
430 gl->BindVertexArray (overlay->vao);
432 gst_gl_composition_overlay_bind_vertex_buffer (overlay);
434 if (overlay->texture_id != -1)
435 gl->BindTexture (GL_TEXTURE_2D, overlay->texture_id);
436 gl->DrawElements (GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, 0);
442 } GstGLOverlayCompositorPrivate;
450 /********************************************************************
451 * GstGLOverlayCompositor object, the public helper object to render
452 * GstVideoCompositionOverlayMeta
453 ********************************************************************/
456 GST_DEBUG_CATEGORY_INIT (gst_gl_overlay_compositor_debug, \
457 "gloverlaycompositor", 0, "overlaycompositor");
459 /* this matches what glimagesink does as this was publicized before being used
460 * in other elements that draw in different orientations */
461 #define DEFAULT_YINVERT FALSE
463 G_DEFINE_TYPE_WITH_CODE (GstGLOverlayCompositor, gst_gl_overlay_compositor,
464 GST_TYPE_OBJECT, G_ADD_PRIVATE (GstGLOverlayCompositor);
467 static void gst_gl_overlay_compositor_finalize (GObject * object);
468 static void gst_gl_overlay_compositor_set_property (GObject * object,
469 guint prop_id, const GValue * value, GParamSpec * pspec);
470 static void gst_gl_overlay_compositor_get_property (GObject * object,
471 guint prop_id, GValue * value, GParamSpec * pspec);
473 static gboolean _is_rectangle_in_overlays (GList * overlays,
474 GstVideoOverlayRectangle * rectangle);
475 static gboolean _is_overlay_in_rectangles (GstVideoOverlayComposition *
476 composition, GstGLCompositionOverlay * overlay);
479 gst_gl_overlay_compositor_class_init (GstGLOverlayCompositorClass * klass)
481 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
483 gobject_class->finalize = gst_gl_overlay_compositor_finalize;
484 gobject_class->set_property = gst_gl_overlay_compositor_set_property;
485 gobject_class->get_property = gst_gl_overlay_compositor_get_property;
487 g_object_class_install_property (gobject_class, PROP_YINVERT,
488 g_param_spec_boolean ("yinvert",
490 "Whether to invert the output across a horizintal axis",
491 DEFAULT_YINVERT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
495 gst_gl_overlay_compositor_init (GstGLOverlayCompositor * compositor)
497 GstGLOverlayCompositorPrivate *priv =
498 gst_gl_overlay_compositor_get_instance_private (compositor);
500 priv->yinvert = DEFAULT_YINVERT;
504 gst_gl_overlay_compositor_set_property (GObject * object, guint prop_id,
505 const GValue * value, GParamSpec * pspec)
507 GstGLOverlayCompositor *self = GST_GL_OVERLAY_COMPOSITOR (object);
508 GstGLOverlayCompositorPrivate *priv =
509 gst_gl_overlay_compositor_get_instance_private (self);
513 /* XXX: invalidiate all current rectangles on a change */
514 priv->yinvert = g_value_get_boolean (value);
517 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
523 gst_gl_overlay_compositor_get_property (GObject * object, guint prop_id,
524 GValue * value, GParamSpec * pspec)
526 GstGLOverlayCompositor *self = GST_GL_OVERLAY_COMPOSITOR (object);
527 GstGLOverlayCompositorPrivate *priv =
528 gst_gl_overlay_compositor_get_instance_private (self);
532 g_value_set_boolean (value, priv->yinvert);
535 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
541 gst_gl_overlay_compositor_init_gl (GstGLContext * context,
542 gpointer compositor_pointer)
544 GstGLOverlayCompositor *compositor =
545 (GstGLOverlayCompositor *) compositor_pointer;
546 GError *error = NULL;
547 const gchar *frag_strs[2];
550 gst_gl_shader_string_get_highest_precision (context,
551 GST_GLSL_VERSION_NONE,
552 GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY);
553 frag_strs[1] = fragment_shader;
555 if (!(compositor->shader =
556 gst_gl_shader_new_link_with_stages (context, &error,
557 gst_glsl_stage_new_default_vertex (context),
558 gst_glsl_stage_new_with_strings (context, GL_FRAGMENT_SHADER,
559 GST_GLSL_VERSION_NONE,
560 GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY, 2,
561 frag_strs), NULL))) {
562 GST_ERROR_OBJECT (compositor, "could not initialize shader: %s",
567 compositor->position_attrib =
568 gst_gl_shader_get_attribute_location (compositor->shader, "a_position");
569 compositor->texcoord_attrib =
570 gst_gl_shader_get_attribute_location (compositor->shader, "a_texcoord");
573 GstGLOverlayCompositor *
574 gst_gl_overlay_compositor_new (GstGLContext * context)
576 GstGLOverlayCompositor *compositor =
577 g_object_new (GST_TYPE_GL_OVERLAY_COMPOSITOR, NULL);
579 gst_object_ref_sink (compositor);
581 compositor->context = gst_object_ref (context);
583 gst_gl_context_thread_add (compositor->context,
584 gst_gl_overlay_compositor_init_gl, compositor);
586 GST_DEBUG_OBJECT (compositor, "Created new GstGLOverlayCompositor");
592 gst_gl_overlay_compositor_finalize (GObject * object)
594 GstGLOverlayCompositor *compositor;
596 compositor = GST_GL_OVERLAY_COMPOSITOR (object);
598 gst_gl_overlay_compositor_free_overlays (compositor);
600 if (compositor->context)
601 gst_object_unref (compositor->context);
603 if (compositor->shader) {
604 gst_object_unref (compositor->shader);
605 compositor->shader = NULL;
608 G_OBJECT_CLASS (gst_gl_overlay_compositor_parent_class)->finalize (object);
612 _is_rectangle_in_overlays (GList * overlays,
613 GstVideoOverlayRectangle * rectangle)
617 for (l = overlays; l != NULL; l = l->next) {
618 GstGLCompositionOverlay *overlay = (GstGLCompositionOverlay *) l->data;
619 if (overlay->rectangle == rectangle)
626 _is_overlay_in_rectangles (GstVideoOverlayComposition * composition,
627 GstGLCompositionOverlay * overlay)
631 for (i = 0; i < gst_video_overlay_composition_n_rectangles (composition); i++) {
632 GstVideoOverlayRectangle *rectangle =
633 gst_video_overlay_composition_get_rectangle (composition, i);
634 if (overlay->rectangle == rectangle)
641 gst_gl_overlay_compositor_free_overlays (GstGLOverlayCompositor * compositor)
643 GList *l = compositor->overlays;
645 GList *next = l->next;
646 GstGLCompositionOverlay *overlay = (GstGLCompositionOverlay *) l->data;
647 compositor->overlays = g_list_delete_link (compositor->overlays, l);
648 gst_object_unref (overlay);
651 g_list_free (compositor->overlays);
652 compositor->overlays = NULL;
656 gst_gl_overlay_compositor_upload_overlays (GstGLOverlayCompositor * compositor,
659 GstVideoOverlayCompositionMeta *composition_meta;
660 GstGLOverlayCompositorPrivate *priv =
661 gst_gl_overlay_compositor_get_instance_private (compositor);
663 composition_meta = gst_buffer_get_video_overlay_composition_meta (buf);
664 if (composition_meta) {
665 GstVideoOverlayComposition *composition = NULL;
666 guint num_overlays, i;
667 GList *l = compositor->overlays;
669 GST_DEBUG ("GstVideoOverlayCompositionMeta found.");
671 composition = composition_meta->overlay;
672 num_overlays = gst_video_overlay_composition_n_rectangles (composition);
674 /* add new overlays to list */
675 for (i = 0; i < num_overlays; i++) {
676 GstVideoOverlayRectangle *rectangle =
677 gst_video_overlay_composition_get_rectangle (composition, i);
679 if (!_is_rectangle_in_overlays (compositor->overlays, rectangle)) {
680 GstGLCompositionOverlay *overlay =
681 gst_gl_composition_overlay_new (compositor->context, rectangle,
682 compositor->position_attrib, compositor->texcoord_attrib);
683 gst_object_ref_sink (overlay);
684 overlay->yinvert = priv->yinvert;
686 gst_gl_composition_overlay_upload (overlay, buf);
688 compositor->overlays = g_list_append (compositor->overlays, overlay);
692 /* remove old overlays from list */
694 GList *next = l->next;
695 GstGLCompositionOverlay *overlay = (GstGLCompositionOverlay *) l->data;
696 if (!_is_overlay_in_rectangles (composition, overlay)) {
697 compositor->overlays = g_list_delete_link (compositor->overlays, l);
698 gst_object_unref (overlay);
703 gst_gl_overlay_compositor_free_overlays (compositor);
708 gst_gl_overlay_compositor_draw_overlays (GstGLOverlayCompositor * compositor)
710 const GstGLFuncs *gl = compositor->context->gl_vtable;
711 if (compositor->overlays != NULL) {
714 gl->Enable (GL_BLEND);
716 gst_gl_shader_use (compositor->shader);
717 gl->ActiveTexture (GL_TEXTURE0);
718 gst_gl_shader_set_uniform_1i (compositor->shader, "tex", 0);
720 for (l = compositor->overlays; l != NULL; l = l->next) {
721 GstGLCompositionOverlay *overlay = (GstGLCompositionOverlay *) l->data;
722 GstVideoOverlayFormatFlags flags;
724 flags = gst_video_overlay_rectangle_get_flags (overlay->rectangle);
726 if (flags & GST_VIDEO_OVERLAY_FORMAT_FLAG_PREMULTIPLIED_ALPHA
727 || !gl->BlendFuncSeparate) {
728 gl->BlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
730 gl->BlendFuncSeparate (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE,
731 GL_ONE_MINUS_SRC_ALPHA);
733 gst_gl_composition_overlay_draw (overlay, compositor->shader);
736 gl->BindTexture (GL_TEXTURE_2D, 0);
737 gl->Disable (GL_BLEND);
742 gst_gl_overlay_compositor_add_caps (GstCaps * caps)
744 GstCaps *composition_caps;
747 composition_caps = gst_caps_copy (caps);
749 for (i = 0; i < gst_caps_get_size (composition_caps); i++) {
750 GstCapsFeatures *f = gst_caps_get_features (composition_caps, i);
751 if (!gst_caps_features_is_any (f))
752 gst_caps_features_add (f,
753 GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION);
756 caps = gst_caps_merge (composition_caps, caps);