1 /*
2  * GStreamer
3  * Copyright (C) 2008 Filippo Argiolas <filippo.argiolas@gmail.com>
4  * Copyright (C) 2014 Julien Isorce <julien.isorce@collabora.co.uk>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public
17  * License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
19  * Boston, MA 02110-1301, USA.
20  */
21 
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25 
26 #include "gl.h"
27 #include "gstglshader.h"
28 #include "gstglsl_private.h"
29 
30 /**
31  * SECTION:gstglshader
32  * @title: GstGLShader
33  * @short_description: object representing an OpenGL shader program
34  * @see_also: #GstGLSLStage
35  */
36 
37 #ifndef GLhandleARB
38 #define GLhandleARB GLuint
39 #endif
40 
41 #define USING_OPENGL(context) (gst_gl_context_check_gl_version (context, GST_GL_API_OPENGL, 1, 0))
42 #define USING_OPENGL3(context) (gst_gl_context_check_gl_version (context, GST_GL_API_OPENGL3, 3, 1))
43 #define USING_GLES(context) (gst_gl_context_check_gl_version (context, GST_GL_API_GLES, 1, 0))
44 #define USING_GLES2(context) (gst_gl_context_check_gl_version (context, GST_GL_API_GLES2, 2, 0))
45 #define USING_GLES3(context) (gst_gl_context_check_gl_version (context, GST_GL_API_GLES2, 3, 0))
46 
47 typedef struct _GstGLShaderVTable
48 {
49   GLuint (GSTGLAPI * CreateProgram) (void);
50   void (GSTGLAPI * DeleteProgram) (GLuint program);
51   void (GSTGLAPI * UseProgram) (GLuint program);
52   void (GSTGLAPI * GetAttachedShaders) (GLuint program, GLsizei maxcount,
53       GLsizei * count, GLuint * shaders);
54 
55     GLuint (GSTGLAPI * CreateShader) (GLenum shaderType);
56   void (GSTGLAPI * DeleteShader) (GLuint shader);
57   void (GSTGLAPI * AttachShader) (GLuint program, GLuint shader);
58   void (GSTGLAPI * DetachShader) (GLuint program, GLuint shader);
59 
60   void (GSTGLAPI * GetShaderiv) (GLuint program, GLenum pname, GLint * params);
61   void (GSTGLAPI * GetProgramiv) (GLuint program, GLenum pname, GLint * params);
62   void (GSTGLAPI * GetShaderInfoLog) (GLuint shader, GLsizei maxLength,
63       GLsizei * length, char *log);
64   void (GSTGLAPI * GetProgramInfoLog) (GLuint shader, GLsizei maxLength,
65       GLsizei * length, char *log);
66 } GstGLShaderVTable;
67 
68 enum
69 {
70   PROP_0,
71   PROP_LINKED,
72 };
73 
74 struct _GstGLShaderPrivate
75 {
76   GLhandleARB program_handle;
77   GList *stages;
78 
79   gboolean linked;
80   GHashTable *uniform_locations;
81 
82   GstGLSLFuncs vtable;
83 };
84 
85 GST_DEBUG_CATEGORY_STATIC (gst_gl_shader_debug);
86 #define GST_CAT_DEFAULT gst_gl_shader_debug
87 
88 #define DEBUG_INIT \
89   GST_DEBUG_CATEGORY_INIT (gst_gl_shader_debug, "glshader", 0, "shader");
90 G_DEFINE_TYPE_WITH_CODE (GstGLShader, gst_gl_shader, GST_TYPE_OBJECT,
91     G_ADD_PRIVATE (GstGLShader) DEBUG_INIT);
92 
93 static void
_cleanup_shader(GstGLContext * context,GstGLShader * shader)94 _cleanup_shader (GstGLContext * context, GstGLShader * shader)
95 {
96   GstGLShaderPrivate *priv = shader->priv;
97 
98   GST_OBJECT_LOCK (shader);
99 
100   /* release shader objects */
101   gst_gl_shader_release_unlocked (shader);
102 
103   /* delete program */
104   if (priv->program_handle) {
105     GST_TRACE ("finalizing program shader %u", priv->program_handle);
106 
107     priv->vtable.DeleteProgram (priv->program_handle);
108   }
109 
110   GST_DEBUG ("shader deleted %u", priv->program_handle);
111 
112   GST_OBJECT_UNLOCK (shader);
113 }
114 
115 static void
gst_gl_shader_finalize(GObject * object)116 gst_gl_shader_finalize (GObject * object)
117 {
118   GstGLShader *shader;
119   GstGLShaderPrivate *priv;
120 
121   shader = GST_GL_SHADER (object);
122   priv = shader->priv;
123 
124   GST_TRACE_OBJECT (shader, "finalizing shader %u", priv->program_handle);
125 
126   gst_gl_context_thread_add (shader->context,
127       (GstGLContextThreadFunc) _cleanup_shader, shader);
128 
129   priv->program_handle = 0;
130   g_hash_table_destroy (priv->uniform_locations);
131 
132   if (shader->context) {
133     gst_object_unref (shader->context);
134     shader->context = NULL;
135   }
136 
137   G_OBJECT_CLASS (gst_gl_shader_parent_class)->finalize (object);
138 }
139 
140 static void
gst_gl_shader_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)141 gst_gl_shader_set_property (GObject * object,
142     guint prop_id, const GValue * value, GParamSpec * pspec)
143 {
144   switch (prop_id) {
145     default:
146       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
147       break;
148   }
149 }
150 
151 static void
gst_gl_shader_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)152 gst_gl_shader_get_property (GObject * object,
153     guint prop_id, GValue * value, GParamSpec * pspec)
154 {
155   GstGLShader *shader = GST_GL_SHADER (object);
156   GstGLShaderPrivate *priv = shader->priv;
157 
158   switch (prop_id) {
159     case PROP_LINKED:
160       g_value_set_boolean (value, priv->linked);
161       break;
162     default:
163       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
164       break;
165   }
166 }
167 
168 static void
gst_gl_shader_class_init(GstGLShaderClass * klass)169 gst_gl_shader_class_init (GstGLShaderClass * klass)
170 {
171   /* bind class methods .. */
172   GObjectClass *obj_class = G_OBJECT_CLASS (klass);
173 
174   obj_class->finalize = gst_gl_shader_finalize;
175   obj_class->set_property = gst_gl_shader_set_property;
176   obj_class->get_property = gst_gl_shader_get_property;
177 
178   /* .. and install properties */
179   g_object_class_install_property (obj_class,
180       PROP_LINKED,
181       g_param_spec_boolean ("linked",
182           "Linked",
183           "Shader link status", FALSE,
184           G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
185 }
186 
187 static void
gst_gl_shader_init(GstGLShader * self)188 gst_gl_shader_init (GstGLShader * self)
189 {
190   /* initialize sources and create program object */
191   GstGLShaderPrivate *priv;
192 
193   priv = self->priv = gst_gl_shader_get_instance_private (self);
194 
195   priv->linked = FALSE;
196   priv->uniform_locations =
197       g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
198 }
199 
200 static int
_get_uniform_location(GstGLShader * shader,const gchar * name)201 _get_uniform_location (GstGLShader * shader, const gchar * name)
202 {
203   GstGLShaderPrivate *priv = shader->priv;
204   int location;
205   gpointer value;
206 
207   g_return_val_if_fail (priv->linked, 0);
208 
209   if (!g_hash_table_lookup_extended (priv->uniform_locations, name, NULL,
210           &value)) {
211     const GstGLFuncs *gl = shader->context->gl_vtable;
212     location = gl->GetUniformLocation (priv->program_handle, name);
213     g_hash_table_insert (priv->uniform_locations, g_strdup (name),
214         GINT_TO_POINTER (location));
215   } else {
216     location = GPOINTER_TO_INT (value);
217   }
218 
219   GST_TRACE_OBJECT (shader, "Retrieved uniform \'%s\' location %i", name,
220       location);
221 
222   return location;
223 }
224 
225 static GstGLShader *
_new_with_stages_va_list(GstGLContext * context,GError ** error,va_list varargs)226 _new_with_stages_va_list (GstGLContext * context, GError ** error,
227     va_list varargs)
228 {
229   GstGLShader *shader;
230   GstGLSLStage *stage;
231   gboolean to_unref_and_out = FALSE;
232 
233   g_return_val_if_fail (GST_IS_GL_CONTEXT (context), NULL);
234 
235   shader = g_object_new (GST_TYPE_GL_SHADER, NULL);
236   gst_object_ref_sink (shader);
237   shader->context = gst_object_ref (context);
238 
239   while ((stage = va_arg (varargs, GstGLSLStage *))) {
240     if (to_unref_and_out) {
241       gst_object_unref (stage);
242       continue;
243     }
244 
245     if (!gst_glsl_stage_compile (stage, error)) {
246       gst_object_unref (stage);
247       to_unref_and_out = TRUE;
248       continue;
249     }
250     if (!gst_gl_shader_attach (shader, stage)) {
251       g_set_error (error, GST_GLSL_ERROR, GST_GLSL_ERROR_PROGRAM,
252           "Failed to attach stage to program");
253       to_unref_and_out = TRUE;
254       continue;
255     }
256   }
257 
258   if (to_unref_and_out) {
259     gst_object_unref (shader);
260     return NULL;
261   }
262 
263   return shader;
264 }
265 
266 /**
267  * gst_gl_shader_new_link_with_stages:
268  * @context: a #GstGLContext
269  * @error: a #GError
270  * @...: a NULL terminated list of #GstGLSLStage's
271  *
272  * Each stage will attempt to be compiled and attached to @shader.  Then
273  * the shader will be linked. On error, %NULL will be returned and @error will
274  * contain the details of the error.
275  *
276  * Note: must be called in the GL thread
277  *
278  * Returns: (transfer full): a new @shader with the specified stages.
279  *
280  * Since: 1.8
281  */
282 GstGLShader *
gst_gl_shader_new_link_with_stages(GstGLContext * context,GError ** error,...)283 gst_gl_shader_new_link_with_stages (GstGLContext * context, GError ** error,
284     ...)
285 {
286   GstGLShader *shader;
287   va_list varargs;
288 
289   va_start (varargs, error);
290   shader = _new_with_stages_va_list (context, error, varargs);
291   va_end (varargs);
292 
293   if (!shader)
294     return NULL;
295 
296   if (!gst_gl_shader_link (shader, error))
297     return NULL;
298 
299   return shader;
300 }
301 
302 /**
303  * gst_gl_shader_new_with_stages:
304  * @context: a #GstGLContext
305  * @error: a #GError
306  * @...: a NULL terminated list of #GstGLSLStage's
307  *
308  * Each stage will attempt to be compiled and attached to @shader.  On error,
309  * %NULL will be returned and @error will contain the details of the error.
310  *
311  * Note: must be called in the GL thread
312  *
313  * Returns: (transfer full): a new @shader with the specified stages.
314  *
315  * Since: 1.8
316  */
317 GstGLShader *
gst_gl_shader_new_with_stages(GstGLContext * context,GError ** error,...)318 gst_gl_shader_new_with_stages (GstGLContext * context, GError ** error, ...)
319 {
320   GstGLShader *shader;
321   va_list varargs;
322 
323   va_start (varargs, error);
324   shader = _new_with_stages_va_list (context, error, varargs);
325   va_end (varargs);
326 
327   return shader;
328 }
329 
330 /**
331  * gst_gl_shader_new:
332  * @context: a #GstGLContext
333  *
334  * Note: must be called in the GL thread
335  *
336  * Returns: (transfer full): a new empty @shader
337  */
338 GstGLShader *
gst_gl_shader_new(GstGLContext * context)339 gst_gl_shader_new (GstGLContext * context)
340 {
341   return gst_gl_shader_new_with_stages (context, NULL, NULL);
342 }
343 
344 /**
345  * gst_gl_shader_new_default:
346  * @context: a #GstGLContext
347  * @error: a #GError that is filled on failure
348  *
349  * Note: must be called in the GL thread
350  *
351  * Returns: (transfer full): a default @shader or %NULL on failure
352  *
353  * Since: 1.8
354  */
355 GstGLShader *
gst_gl_shader_new_default(GstGLContext * context,GError ** error)356 gst_gl_shader_new_default (GstGLContext * context, GError ** error)
357 {
358   return gst_gl_shader_new_link_with_stages (context, error,
359       gst_glsl_stage_new_default_vertex (context),
360       gst_glsl_stage_new_default_fragment (context), NULL);
361 }
362 
363 /**
364  * gst_gl_shader_is_linked:
365  * @shader: a #GstGLShader
366  *
367  * Note: must be called in the GL thread
368  *
369  * Returns: whether @shader has been successfully linked
370  *
371  * Since: 1.8
372  */
373 gboolean
gst_gl_shader_is_linked(GstGLShader * shader)374 gst_gl_shader_is_linked (GstGLShader * shader)
375 {
376   gboolean ret;
377 
378   g_return_val_if_fail (GST_IS_GL_SHADER (shader), FALSE);
379 
380   GST_OBJECT_LOCK (shader);
381   ret = shader->priv->linked;
382   GST_OBJECT_UNLOCK (shader);
383 
384   return ret;
385 }
386 
387 static gboolean
_ensure_program(GstGLShader * shader)388 _ensure_program (GstGLShader * shader)
389 {
390   if (shader->priv->program_handle)
391     return TRUE;
392 
393   shader->priv->program_handle = shader->priv->vtable.CreateProgram ();
394   return shader->priv->program_handle != 0;
395 }
396 
397 /**
398  * gst_gl_shader_get_program_handle:
399  * @shader: a #GstGLShader
400  *
401  * Returns: the GL program handle for this shader
402  *
403  * Since: 1.8
404  */
405 int
gst_gl_shader_get_program_handle(GstGLShader * shader)406 gst_gl_shader_get_program_handle (GstGLShader * shader)
407 {
408   int ret;
409 
410   g_return_val_if_fail (GST_IS_GL_SHADER (shader), 0);
411 
412   GST_OBJECT_LOCK (shader);
413   ret = (int) shader->priv->program_handle;
414   GST_OBJECT_UNLOCK (shader);
415 
416   return ret;
417 }
418 
419 /**
420  * gst_gl_shader_detach_unlocked:
421  * @shader: a #GstGLShader
422  * @stage: a #GstGLSLStage to attach
423  *
424  * Detaches @stage from @shader.  @stage must have been successfully attached
425  * to @shader with gst_gl_shader_attach() or gst_gl_shader_attach_unlocked().
426  *
427  * Note: must be called in the GL thread
428  *
429  * Since: 1.8
430  */
431 void
gst_gl_shader_detach_unlocked(GstGLShader * shader,GstGLSLStage * stage)432 gst_gl_shader_detach_unlocked (GstGLShader * shader, GstGLSLStage * stage)
433 {
434   guint stage_handle;
435   GList *elem;
436 
437   g_return_if_fail (GST_IS_GL_SHADER (shader));
438   g_return_if_fail (GST_IS_GLSL_STAGE (stage));
439 
440   if (!_gst_glsl_funcs_fill (&shader->priv->vtable, shader->context)) {
441     GST_WARNING_OBJECT (shader, "Failed to retreive required GLSL functions");
442     return;
443   }
444 
445   if (!shader->priv->program_handle)
446     return;
447 
448   elem = g_list_find (shader->priv->stages, stage);
449   if (!elem) {
450     GST_FIXME_OBJECT (shader, "Could not find stage %p in shader %p", stage,
451         shader);
452     return;
453   }
454 
455   stage_handle = gst_glsl_stage_get_handle (stage);
456   if (!stage_handle) {
457     GST_FIXME_OBJECT (shader, "Stage %p doesn't have a GL handle", stage);
458     return;
459   }
460 
461   if (shader->context->gl_vtable->IsProgram)
462     g_assert (shader->context->gl_vtable->IsProgram (shader->
463             priv->program_handle));
464   if (shader->context->gl_vtable->IsShader)
465     g_assert (shader->context->gl_vtable->IsShader (stage_handle));
466 
467   GST_LOG_OBJECT (shader, "detaching shader %i from program %i", stage_handle,
468       (int) shader->priv->program_handle);
469   shader->priv->vtable.DetachShader (shader->priv->program_handle,
470       stage_handle);
471 
472   shader->priv->stages = g_list_delete_link (shader->priv->stages, elem);
473   gst_object_unref (stage);
474 }
475 
476 /**
477  * gst_gl_shader_detach:
478  * @shader: a #GstGLShader
479  * @stage: a #GstGLSLStage to attach
480  *
481  * Detaches @stage from @shader.  @stage must have been successfully attached
482  * to @shader with gst_gl_shader_attach() or gst_gl_shader_attach_unlocked().
483  *
484  * Note: must be called in the GL thread
485  *
486  * Since: 1.8
487  */
488 void
gst_gl_shader_detach(GstGLShader * shader,GstGLSLStage * stage)489 gst_gl_shader_detach (GstGLShader * shader, GstGLSLStage * stage)
490 {
491   g_return_if_fail (GST_IS_GL_SHADER (shader));
492   g_return_if_fail (GST_IS_GLSL_STAGE (stage));
493 
494   GST_OBJECT_LOCK (shader);
495   gst_gl_shader_detach_unlocked (shader, stage);
496   GST_OBJECT_UNLOCK (shader);
497 }
498 
499 /**
500  * gst_gl_shader_attach_unlocked:
501  * @shader: a #GstGLShader
502  * @stage: (transfer floating): a #GstGLSLStage to attach
503  *
504  * Attaches @stage to @shader.  @stage must have been successfully compiled
505  * with gst_glsl_stage_compile().
506  *
507  * Note: must be called in the GL thread
508  *
509  * Returns: whether @stage could be attached to @shader
510  *
511  * Since: 1.8
512  */
513 gboolean
gst_gl_shader_attach_unlocked(GstGLShader * shader,GstGLSLStage * stage)514 gst_gl_shader_attach_unlocked (GstGLShader * shader, GstGLSLStage * stage)
515 {
516   guint stage_handle;
517 
518   g_return_val_if_fail (GST_IS_GL_SHADER (shader), FALSE);
519   g_return_val_if_fail (GST_IS_GLSL_STAGE (stage), FALSE);
520 
521   if (!_gst_glsl_funcs_fill (&shader->priv->vtable, shader->context)) {
522     GST_WARNING_OBJECT (shader, "Failed to retreive required GLSL functions");
523     gst_object_ref_sink (stage);
524     gst_object_unref (stage);
525     return FALSE;
526   }
527 
528   if (!_ensure_program (shader)) {
529     gst_object_ref_sink (stage);
530     gst_object_unref (stage);
531     return FALSE;
532   }
533 
534   /* already attached? */
535   if (g_list_find (shader->priv->stages, stage)) {
536     gst_object_ref_sink (stage);
537     gst_object_unref (stage);
538     return TRUE;
539   }
540 
541   stage_handle = gst_glsl_stage_get_handle (stage);
542   if (!stage_handle) {
543     gst_object_ref_sink (stage);
544     gst_object_unref (stage);
545     return FALSE;
546   }
547 
548   if (shader->context->gl_vtable->IsProgram)
549     g_assert (shader->context->gl_vtable->IsProgram (shader->
550             priv->program_handle));
551   if (shader->context->gl_vtable->IsShader)
552     g_assert (shader->context->gl_vtable->IsShader (stage_handle));
553 
554   shader->priv->stages =
555       g_list_prepend (shader->priv->stages, gst_object_ref_sink (stage));
556   GST_LOG_OBJECT (shader, "attaching shader %i to program %i", stage_handle,
557       (int) shader->priv->program_handle);
558   shader->priv->vtable.AttachShader (shader->priv->program_handle,
559       stage_handle);
560 
561   return TRUE;
562 }
563 
564 /**
565  * gst_gl_shader_attach:
566  * @shader: a #GstGLShader
567  * @stage: (transfer floating): a #GstGLSLStage to attach
568  *
569  * Attaches @stage to @shader.  @stage must have been successfully compiled
570  * with gst_glsl_stage_compile().
571  *
572  * Note: must be called in the GL thread
573  *
574  * Returns: whether @stage could be attached to @shader
575  *
576  * Since: 1.8
577  */
578 gboolean
gst_gl_shader_attach(GstGLShader * shader,GstGLSLStage * stage)579 gst_gl_shader_attach (GstGLShader * shader, GstGLSLStage * stage)
580 {
581   gboolean ret;
582 
583   g_return_val_if_fail (GST_IS_GL_SHADER (shader), FALSE);
584   g_return_val_if_fail (GST_IS_GLSL_STAGE (stage), FALSE);
585 
586   GST_OBJECT_LOCK (shader);
587   ret = gst_gl_shader_attach_unlocked (shader, stage);
588   GST_OBJECT_UNLOCK (shader);
589 
590   return ret;
591 }
592 
593 /**
594  * gst_gl_shader_compile_attach_stage:
595  * @shader: a #GstGLShader
596  * @stage: a #GstGLSLStage to attach
597  * @error: a #GError
598  *
599  * Compiles @stage and attaches it to @shader.
600  *
601  * Note: must be called in the GL thread
602  *
603  * Returns: whether @stage could be compiled and attached to @shader
604  *
605  * Since: 1.8
606  */
607 gboolean
gst_gl_shader_compile_attach_stage(GstGLShader * shader,GstGLSLStage * stage,GError ** error)608 gst_gl_shader_compile_attach_stage (GstGLShader * shader, GstGLSLStage * stage,
609     GError ** error)
610 {
611   g_return_val_if_fail (GST_IS_GLSL_STAGE (stage), FALSE);
612 
613   if (!gst_glsl_stage_compile (stage, error)) {
614     return FALSE;
615   }
616 
617   if (!gst_gl_shader_attach (shader, stage)) {
618     g_set_error (error, GST_GLSL_ERROR, GST_GLSL_ERROR_COMPILE,
619         "Failed to attach stage to shader");
620     return FALSE;
621   }
622 
623   return TRUE;
624 }
625 
626 /**
627  * gst_gl_shader_link:
628  * @shader: a #GstGLShader
629  * @error: a #GError
630  *
631  * Links the current list of #GstGLSLStage's in @shader.
632  *
633  * Note: must be called in the GL thread
634  *
635  * Returns: whether @shader could be linked together.
636  *
637  * Since: 1.8
638  */
639 gboolean
gst_gl_shader_link(GstGLShader * shader,GError ** error)640 gst_gl_shader_link (GstGLShader * shader, GError ** error)
641 {
642   GstGLShaderPrivate *priv;
643   const GstGLFuncs *gl;
644   gchar info_buffer[2048];
645   GLint status = GL_FALSE;
646   gint len = 0;
647   gboolean ret;
648   GList *elem;
649 
650   g_return_val_if_fail (GST_IS_GL_SHADER (shader), FALSE);
651 
652   GST_OBJECT_LOCK (shader);
653 
654   priv = shader->priv;
655   gl = shader->context->gl_vtable;
656 
657   if (priv->linked) {
658     GST_OBJECT_UNLOCK (shader);
659     return TRUE;
660   }
661 
662   if (!_gst_glsl_funcs_fill (&shader->priv->vtable, shader->context)) {
663     g_set_error (error, GST_GLSL_ERROR, GST_GLSL_ERROR_PROGRAM,
664         "Failed to retreive required GLSL functions");
665     GST_OBJECT_UNLOCK (shader);
666     return FALSE;
667   }
668 
669   if (!_ensure_program (shader)) {
670     g_set_error (error, GST_GLSL_ERROR, GST_GLSL_ERROR_PROGRAM,
671         "Failed to create GL program object");
672     GST_OBJECT_UNLOCK (shader);
673     return FALSE;
674   }
675 
676   GST_TRACE ("shader created %u", shader->priv->program_handle);
677 
678   for (elem = shader->priv->stages; elem; elem = elem->next) {
679     GstGLSLStage *stage = elem->data;
680 
681     if (!gst_glsl_stage_compile (stage, error)) {
682       GST_OBJECT_UNLOCK (shader);
683       return FALSE;
684     }
685 
686     if (!gst_gl_shader_attach_unlocked (shader, stage)) {
687       g_set_error (error, GST_GLSL_ERROR, GST_GLSL_ERROR_COMPILE,
688           "Failed to attach shader %" GST_PTR_FORMAT "to program %"
689           GST_PTR_FORMAT, stage, shader);
690       GST_OBJECT_UNLOCK (shader);
691       return FALSE;
692     }
693   }
694 
695   /* if nothing failed link shaders */
696   gl->LinkProgram (priv->program_handle);
697   status = GL_FALSE;
698   priv->vtable.GetProgramiv (priv->program_handle, GL_LINK_STATUS, &status);
699 
700   priv->vtable.GetProgramInfoLog (priv->program_handle,
701       sizeof (info_buffer) - 1, &len, info_buffer);
702   info_buffer[len] = '\0';
703 
704   if (status != GL_TRUE) {
705     GST_ERROR ("Shader linking failed:\n%s", info_buffer);
706 
707     g_set_error (error, GST_GLSL_ERROR, GST_GLSL_ERROR_LINK,
708         "Shader Linking failed:\n%s", info_buffer);
709     ret = priv->linked = FALSE;
710     GST_OBJECT_UNLOCK (shader);
711     return ret;
712   } else if (len > 1) {
713     GST_FIXME ("shader link log:\n%s\n", info_buffer);
714   }
715 
716   ret = priv->linked = TRUE;
717   GST_OBJECT_UNLOCK (shader);
718 
719   g_object_notify (G_OBJECT (shader), "linked");
720 
721   return ret;
722 }
723 
724 /**
725  * gst_gl_shader_release_unlocked:
726  * @shader: a #GstGLShader
727  *
728  * Releases the shader and stages.
729  *
730  * Note: must be called in the GL thread
731  *
732  * Since: 1.8
733  */
734 void
gst_gl_shader_release_unlocked(GstGLShader * shader)735 gst_gl_shader_release_unlocked (GstGLShader * shader)
736 {
737   GstGLShaderPrivate *priv;
738   GList *elem;
739 
740   g_return_if_fail (GST_IS_GL_SHADER (shader));
741 
742   priv = shader->priv;
743 
744   for (elem = shader->priv->stages; elem;) {
745     GstGLSLStage *stage = elem->data;
746     GList *next = elem->next;
747 
748     gst_gl_shader_detach_unlocked (shader, stage);
749     elem = next;
750   }
751 
752   g_list_free_full (shader->priv->stages, (GDestroyNotify) gst_object_unref);
753   shader->priv->stages = NULL;
754 
755   priv->linked = FALSE;
756   g_hash_table_remove_all (priv->uniform_locations);
757 
758   g_object_notify (G_OBJECT (shader), "linked");
759 }
760 
761 /**
762  * gst_gl_shader_release:
763  * @shader: a #GstGLShader
764  *
765  * Releases the shader and stages.
766  *
767  * Note: must be called in the GL thread
768  *
769  * Since: 1.8
770  */
771 void
gst_gl_shader_release(GstGLShader * shader)772 gst_gl_shader_release (GstGLShader * shader)
773 {
774   g_return_if_fail (GST_IS_GL_SHADER (shader));
775 
776   GST_OBJECT_LOCK (shader);
777   gst_gl_shader_release_unlocked (shader);
778   GST_OBJECT_UNLOCK (shader);
779 }
780 
781 /**
782  * gst_gl_shader_use:
783  * @shader: a #GstGLShader
784  *
785  * Mark's @shader as being used for the next GL draw command.
786  *
787  * Note: must be called in the GL thread and @shader must have been linked.
788  */
789 void
gst_gl_shader_use(GstGLShader * shader)790 gst_gl_shader_use (GstGLShader * shader)
791 {
792   GstGLShaderPrivate *priv;
793 
794   g_return_if_fail (GST_IS_GL_SHADER (shader));
795 
796   priv = shader->priv;
797 
798   g_return_if_fail (priv->program_handle);
799 
800   priv->vtable.UseProgram (priv->program_handle);
801 
802   return;
803 }
804 
805 /**
806  * gst_gl_context_clear_shader:
807  * @context: a #GstGLContext
808  *
809  * Clear's the currently set shader from the GL state machine.
810  *
811  * Note: must be called in the GL thread.
812  */
813 void
gst_gl_context_clear_shader(GstGLContext * context)814 gst_gl_context_clear_shader (GstGLContext * context)
815 {
816   GstGLFuncs *gl;
817 
818   g_return_if_fail (GST_IS_GL_CONTEXT (context));
819 
820   gl = context->gl_vtable;
821 
822   if (gl->CreateProgram)
823     gl->UseProgram (0);
824   else if (gl->CreateProgramObject)
825     gl->UseProgramObject (0);
826 }
827 
828 #define set_uniform_pre_check(shader, name)                                 \
829   GLint location = -1;                                                      \
830   g_return_if_fail (shader != NULL);                                        \
831   g_return_if_fail (shader->priv->program_handle != 0);                     \
832   location = _get_uniform_location (shader, name);
833 
834 #ifdef G_HAVE_ISO_VARARGS
835 
836 #define set_uniform_v(gl_suffix, c_type, debug_stride, debug_str, ...)      \
837 void \
838 G_PASTE(gst_gl_shader_set_uniform_,gl_suffix) (GstGLShader * shader,        \
839         const gchar * name, guint count, const c_type * value)              \
840 {                                                                           \
841   guint i;                                                                  \
842   set_uniform_pre_check(shader, name)                                       \
843   for (i = 0; i < count; i++) {                                             \
844     const c_type * item = &value[i * debug_stride];                         \
845     GST_TRACE_OBJECT (shader, "Setting uniform %s (%i) index %i to "        \
846         debug_str, name, location, i, __VA_ARGS__);                         \
847   }                                                                         \
848   shader->context->gl_vtable->G_PASTE(Uniform,gl_suffix) (location, count, value); \
849 }
850 
851 #define set_uniform_func_decl(gl_suffix, ...)                               \
852 void                                                                        \
853 G_PASTE(gst_gl_shader_set_uniform_,gl_suffix) (GstGLShader * shader,        \
854     const gchar * name, __VA_ARGS__)
855 
856 #define set_uniform_body(gl_suffix, debug_str, ...)                         \
857 {                                                                           \
858   set_uniform_pre_check(shader, name)                                       \
859   GST_TRACE_OBJECT (shader, "Setting uniform %s (%i) = " debug_str,         \
860       name, location, __VA_ARGS__);                                         \
861   shader->context->gl_vtable->G_PASTE(Uniform,gl_suffix) (location, __VA_ARGS__); \
862 }
863 
864 #else /* G_HAVE_ISO_VARARGS */
865 #if G_HAVE_GNUC_VARARGS
866 
867 #define set_uniform_v(gl_suffix, c_type, debug_stride, debug_str, args...)  \
868 void                                                                        \
869 G_PASTE(gst_gl_shader_set_uniform_,gl_suffix) (GstGLShader * shader,        \
870         const gchar * name, guint count, const c_type * value)              \
871 {                                                                           \
872   guint i;                                                                  \
873   set_uniform_pre_check(shader, name)                                       \
874   for (i = 0; i < count; i++) {                                             \
875     const c_type * item = &value[i * debug_stride];                         \
876     GST_TRACE_OBJECT (shader, "Setting uniform %s (%i) index %i to "        \
877         debug_str, name, location, i, ##args);                              \
878   }                                                                         \
879   shader->context->gl_vtable->G_PASTE(Uniform,gl_suffix) (location, count, value); \
880 }
881 
882 #define set_uniform_func_decl(gl_suffix, args...)                           \
883 void                                                                        \
884 G_PASTE(gst_gl_shader_set_uniform_,gl_suffix) (GstGLShader * shader,        \
885     const gchar * name, ##args)
886 
887 #define set_uniform_body(gl_suffix, debug_str, args...)                     \
888 {                                                                           \
889   set_uniform_pre_check(shader, name)                                       \
890   GST_TRACE_OBJECT (shader, "Setting uniform %s (%i) = " debug_str,         \
891       name, location, ##args);                                              \
892   shader->context->gl_vtable->G_PASTE(Uniform,gl_suffix) (location, ##args); \
893 }
894 
895 #else
896 
897 #error "No vararg support in C macros. What kind of C compiler is this?!"
898 
899 #endif /* G_HAVE_GNUC_VARARGS */
900 #endif /* G_HAVE_ISO_VARARGS */
901 
902 /* *INDENT-OFF* */
903 /**
904  * gst_gl_shader_set_uniform_1f:
905  * @shader: a #GstGLShader
906  * @name: name of the uniform
907  * @value: value to set
908  *
909  * Perform glUniform1f() for @name on @shader
910  */
911 set_uniform_func_decl(1f, float value)
912 set_uniform_body(1f, "%f", value);
913 
914 /**
915  * gst_gl_shader_set_uniform_1fv:
916  * @shader: a #GstGLShader
917  * @name: name of the uniform
918  * @count: number of values to set
919  * @value: (array length=count): values to set
920  *
921  * Perform glUniform1fv() for @name on @shader
922  */
923 set_uniform_v(1fv, float, 1, "%f", item[0]);
924 
925 /**
926  * gst_gl_shader_set_uniform_1i:
927  * @shader: a #GstGLShader
928  * @name: name of the uniform
929  * @value: value to set
930  *
931  * Perform glUniform1i() for @name on @shader
932  */
933 set_uniform_func_decl(1i, int value)
934 set_uniform_body(1i, "%i", value);
935 
936 /**
937  * gst_gl_shader_set_uniform_1iv:
938  * @shader: a #GstGLShader
939  * @name: name of the uniform
940  * @count: number of values to set
941  * @value: (array length=count): values to set
942  *
943  * Perform glUniform1iv() for @name on @shader
944  */
945 set_uniform_v(1iv, int, 1, "%i", item[0]);
946 
947 /**
948  * gst_gl_shader_set_uniform_2f:
949  * @shader: a #GstGLShader
950  * @name: name of the uniform
951  * @v0: first value to set
952  * @v1: second value to set
953  *
954  * Perform glUniform2f() for @name on @shader
955  */
956 set_uniform_func_decl(2f, float v0, float v1)
957 set_uniform_body(2f, "%f, %f", v0, v1);
958 
959 /**
960  * gst_gl_shader_set_uniform_2fv:
961  * @shader: a #GstGLShader
962  * @name: name of the uniform
963  * @count: number of values to set
964  * @value: (array length=count): values to set
965  *
966  * Perform glUniform2fv() for @name on @shader
967  */
968 set_uniform_v(2fv, float, 2, "%f, %f", item[0], item[1]);
969 
970 /**
971  * gst_gl_shader_set_uniform_2i:
972  * @shader: a #GstGLShader
973  * @name: name of the uniform
974  * @v0: first value to set
975  * @v1: second value to set
976  *
977  * Perform glUniform2i() for @name on @shader
978  */
979 set_uniform_func_decl(2i, int v0, int v1)
980 set_uniform_body(2i, "%i, %i", v0, v1);
981 
982 /**
983  * gst_gl_shader_set_uniform_2iv:
984  * @shader: a #GstGLShader
985  * @name: name of the uniform
986  * @count: number of values to set
987  * @value: (array length=count): values to set
988  *
989  * Perform glUniform2iv() for @name on @shader
990  */
991 set_uniform_v(2iv, int, 2, "%i, %i", item[0], item[1]);
992 
993 /**
994  * gst_gl_shader_set_uniform_3f:
995  * @shader: a #GstGLShader
996  * @name: name of the uniform
997  * @v0: first value to set
998  * @v1: second value to set
999  * @v2: third value to set
1000  *
1001  * Perform glUniform3f() for @name on @shader
1002  */
1003 set_uniform_func_decl(3f, float v0, float v1, float v2)
1004 set_uniform_body(3f, "%f, %f, %f", v0, v1, v2);
1005 
1006 /**
1007  * gst_gl_shader_set_uniform_3fv:
1008  * @shader: a #GstGLShader
1009  * @name: name of the uniform
1010  * @count: number of values to set
1011  * @value: (array length=count): values to set
1012  *
1013  * Perform glUniform3fv() for @name on @shader
1014  */
1015 set_uniform_v(3fv, float, 3, "%f, %f, %f", item[0], item[1], item[2]);
1016 
1017 /**
1018  * gst_gl_shader_set_uniform_3i:
1019  * @shader: a #GstGLShader
1020  * @name: name of the uniform
1021  * @v0: first value to set
1022  * @v1: second value to set
1023  * @v2: third value to set
1024  *
1025  * Perform glUniform3i() for @name on @shader
1026  */
1027 set_uniform_func_decl(3i, int v0, int v1, int v2)
1028 set_uniform_body(3i, "%i, %i, %i", v0, v1, v2);
1029 
1030 /**
1031  * gst_gl_shader_set_uniform_3iv:
1032  * @shader: a #GstGLShader
1033  * @name: name of the uniform
1034  * @count: number of values to set
1035  * @value: (array length=count): values to set
1036  *
1037  * Perform glUniform3iv() for @name on @shader
1038  */
1039 set_uniform_v(3iv, int, 3, "%i, %i, %i", item[0], item[1], item[2]);
1040 
1041 /**
1042  * gst_gl_shader_set_uniform_4f:
1043  * @shader: a #GstGLShader
1044  * @name: name of the uniform
1045  * @v0: first value to set
1046  * @v1: second value to set
1047  * @v2: third value to set
1048  * @v3: fourth value to set
1049  *
1050  * Perform glUniform4f() for @name on @shader
1051  */
1052 set_uniform_func_decl(4f, float v0, float v1, float v2, float v3)
1053 set_uniform_body(4f, "%f, %f, %f, %f", v0, v1, v2, v3);
1054 
1055 /**
1056  * gst_gl_shader_set_uniform_4fv:
1057  * @shader: a #GstGLShader
1058  * @name: name of the uniform
1059  * @count: number of values to set
1060  * @value: (array length=count): values to set
1061  *
1062  * Perform glUniform4fv() for @name on @shader
1063  */
1064 set_uniform_v(4fv, float, 4, "%f, %f, %f, %f", item[0], item[1], item[2], item[3]);
1065 
1066 /**
1067  * gst_gl_shader_set_uniform_4i:
1068  * @shader: a #GstGLShader
1069  * @name: name of the uniform
1070  * @v0: first value to set
1071  * @v1: second value to set
1072  * @v2: third value to set
1073  * @v3: fourth value to set
1074  *
1075  * Perform glUniform4i() for @name on @shader
1076  */
1077 set_uniform_func_decl(4i, int v0, int v1, int v2, int v3)
1078 set_uniform_body(4i, "%i, %i, %i, %i", v0, v1, v2, v3);
1079 
1080 /**
1081  * gst_gl_shader_set_uniform_4iv:
1082  * @shader: a #GstGLShader
1083  * @name: name of the uniform
1084  * @count: number of values to set
1085  * @value: (array length=count): values to set
1086  *
1087  * Perform glUniform4iv() for @name on @shader
1088  */
1089 set_uniform_v(4iv, int, 4, "%i, %i, %i, %i", item[0], item[1], item[2], item[3]);
1090 /* *INDENT-ON* */
1091 
1092 /**
1093  * gst_gl_shader_set_uniform_matrix_2fv:
1094  * @shader: a #GstGLShader
1095  * @name: name of the uniform
1096  * @count: number of 2x2 matrices to set
1097  * @transpose: transpose the matrix
1098  * @value: matrix to set
1099  *
1100  * Perform glUniformMatrix2fv() for @name on @shader
1101  */
1102 void
gst_gl_shader_set_uniform_matrix_2fv(GstGLShader * shader,const gchar * name,gint count,gboolean transpose,const gfloat * value)1103 gst_gl_shader_set_uniform_matrix_2fv (GstGLShader * shader, const gchar * name,
1104     gint count, gboolean transpose, const gfloat * value)
1105 {
1106   set_uniform_pre_check (shader, name);
1107   shader->context->gl_vtable->UniformMatrix2fv (location, count, transpose,
1108       value);
1109 }
1110 
1111 /**
1112  * gst_gl_shader_set_uniform_matrix_3fv:
1113  * @shader: a #GstGLShader
1114  * @name: name of the uniform
1115  * @count: number of 3x3 matrices to set
1116  * @transpose: transpose the matrix
1117  * @value: values to set
1118  *
1119  * Perform glUniformMatrix3fv() for @name on @shader
1120  */
1121 void
gst_gl_shader_set_uniform_matrix_3fv(GstGLShader * shader,const gchar * name,gint count,gboolean transpose,const gfloat * value)1122 gst_gl_shader_set_uniform_matrix_3fv (GstGLShader * shader, const gchar * name,
1123     gint count, gboolean transpose, const gfloat * value)
1124 {
1125   set_uniform_pre_check (shader, name);
1126   shader->context->gl_vtable->UniformMatrix3fv (location, count, transpose,
1127       value);
1128 }
1129 
1130 /**
1131  * gst_gl_shader_set_uniform_matrix_4fv:
1132  * @shader: a #GstGLShader
1133  * @name: name of the uniform
1134  * @count: number of 4x4 matrices to set
1135  * @transpose: transpose the matrix
1136  * @value: values to set
1137  *
1138  * Perform glUniformMatrix4fv() for @name on @shader
1139  */
1140 void
gst_gl_shader_set_uniform_matrix_4fv(GstGLShader * shader,const gchar * name,gint count,gboolean transpose,const gfloat * value)1141 gst_gl_shader_set_uniform_matrix_4fv (GstGLShader * shader, const gchar * name,
1142     gint count, gboolean transpose, const gfloat * value)
1143 {
1144   set_uniform_pre_check (shader, name);
1145   shader->context->gl_vtable->UniformMatrix4fv (location, count, transpose,
1146       value);
1147 }
1148 
1149 /**
1150  * gst_gl_shader_set_uniform_matrix_2x3fv:
1151  * @shader: a #GstGLShader
1152  * @name: name of the uniform
1153  * @count: number of 2x3 matrices to set
1154  * @transpose: transpose the matrix
1155  * @value: values to set
1156  *
1157  * Perform glUniformMatrix2x3fv() for @name on @shader
1158  */
1159 void
gst_gl_shader_set_uniform_matrix_2x3fv(GstGLShader * shader,const gchar * name,gint count,gboolean transpose,const gfloat * value)1160 gst_gl_shader_set_uniform_matrix_2x3fv (GstGLShader * shader,
1161     const gchar * name, gint count, gboolean transpose, const gfloat * value)
1162 {
1163   set_uniform_pre_check (shader, name);
1164   shader->context->gl_vtable->UniformMatrix2x3fv (location, count, transpose,
1165       value);
1166 }
1167 
1168 /**
1169  * gst_gl_shader_set_uniform_matrix_2x4fv:
1170  * @shader: a #GstGLShader
1171  * @name: name of the uniform
1172  * @count: number of 2x4 matrices to set
1173  * @transpose: transpose the matrix
1174  * @value: values to set
1175  *
1176  * Perform glUniformMatrix2x4fv() for @name on @shader
1177  */
1178 void
gst_gl_shader_set_uniform_matrix_2x4fv(GstGLShader * shader,const gchar * name,gint count,gboolean transpose,const gfloat * value)1179 gst_gl_shader_set_uniform_matrix_2x4fv (GstGLShader * shader,
1180     const gchar * name, gint count, gboolean transpose, const gfloat * value)
1181 {
1182   set_uniform_pre_check (shader, name);
1183   shader->context->gl_vtable->UniformMatrix2x4fv (location, count, transpose,
1184       value);
1185 }
1186 
1187 /**
1188  * gst_gl_shader_set_uniform_matrix_3x2fv:
1189  * @shader: a #GstGLShader
1190  * @name: name of the uniform
1191  * @count: number of 3x2 matrices to set
1192  * @transpose: transpose the matrix
1193  * @value: values to set
1194  *
1195  * Perform glUniformMatrix3x2fv() for @name on @shader
1196  */
1197 void
gst_gl_shader_set_uniform_matrix_3x2fv(GstGLShader * shader,const gchar * name,gint count,gboolean transpose,const gfloat * value)1198 gst_gl_shader_set_uniform_matrix_3x2fv (GstGLShader * shader,
1199     const gchar * name, gint count, gboolean transpose, const gfloat * value)
1200 {
1201   set_uniform_pre_check (shader, name);
1202   shader->context->gl_vtable->UniformMatrix3x2fv (location, count, transpose,
1203       value);
1204 }
1205 
1206 /**
1207  * gst_gl_shader_set_uniform_matrix_3x4fv:
1208  * @shader: a #GstGLShader
1209  * @name: name of the uniform
1210  * @count: number of 3x4 matrices to set
1211  * @transpose: transpose the matrix
1212  * @value: values to set
1213  *
1214  * Perform glUniformMatrix3x4fv() for @name on @shader
1215  */
1216 void
gst_gl_shader_set_uniform_matrix_3x4fv(GstGLShader * shader,const gchar * name,gint count,gboolean transpose,const gfloat * value)1217 gst_gl_shader_set_uniform_matrix_3x4fv (GstGLShader * shader,
1218     const gchar * name, gint count, gboolean transpose, const gfloat * value)
1219 {
1220   set_uniform_pre_check (shader, name);
1221   shader->context->gl_vtable->UniformMatrix3x4fv (location, count, transpose,
1222       value);
1223 }
1224 
1225 /**
1226  * gst_gl_shader_set_uniform_matrix_4x2fv:
1227  * @shader: a #GstGLShader
1228  * @name: name of the uniform
1229  * @count: number of 4x2 matrices to set
1230  * @transpose: transpose the matrix
1231  * @value: values to set
1232  *
1233  * Perform glUniformMatrix4x2fv() for @name on @shader
1234  */
1235 void
gst_gl_shader_set_uniform_matrix_4x2fv(GstGLShader * shader,const gchar * name,gint count,gboolean transpose,const gfloat * value)1236 gst_gl_shader_set_uniform_matrix_4x2fv (GstGLShader * shader,
1237     const gchar * name, gint count, gboolean transpose, const gfloat * value)
1238 {
1239   set_uniform_pre_check (shader, name);
1240   shader->context->gl_vtable->UniformMatrix4x2fv (location, count, transpose,
1241       value);
1242 }
1243 
1244 /**
1245  * gst_gl_shader_set_uniform_matrix_4x3fv:
1246  * @shader: a #GstGLShader
1247  * @name: name of the uniform
1248  * @count: number of 4x3 matrices to set
1249  * @transpose: transpose the matrix
1250  * @value: values to set
1251  *
1252  * Perform glUniformMatrix4x3fv() for @name on @shader
1253  */
1254 void
gst_gl_shader_set_uniform_matrix_4x3fv(GstGLShader * shader,const gchar * name,gint count,gboolean transpose,const gfloat * value)1255 gst_gl_shader_set_uniform_matrix_4x3fv (GstGLShader * shader,
1256     const gchar * name, gint count, gboolean transpose, const gfloat * value)
1257 {
1258   set_uniform_pre_check (shader, name);
1259   shader->context->gl_vtable->UniformMatrix4x3fv (location, count, transpose,
1260       value);
1261 }
1262 
1263 /**
1264  * gst_gl_shader_get_attribute_location:
1265  * @shader: a #GstGLShader
1266  * @name: name of the attribute
1267  *
1268  * Returns: the attribute index for @name in @shader or -1 on failure
1269  */
1270 GLint
gst_gl_shader_get_attribute_location(GstGLShader * shader,const gchar * name)1271 gst_gl_shader_get_attribute_location (GstGLShader * shader, const gchar * name)
1272 {
1273   gint ret;
1274 
1275   g_return_val_if_fail (shader != NULL, -1);
1276   g_return_val_if_fail (shader->priv->program_handle != 0, -1);
1277 
1278   ret =
1279       shader->context->gl_vtable->GetAttribLocation (shader->priv->
1280       program_handle, name);
1281 
1282   GST_TRACE_OBJECT (shader, "retreived program %i attribute \'%s\' location %i",
1283       (int) shader->priv->program_handle, name, ret);
1284 
1285   return ret;
1286 }
1287 
1288 /**
1289  * gst_gl_shader_bind_attribute_location:
1290  * @shader: a #GstGLShader
1291  * @index: attribute index to set
1292  * @name: name of the attribute
1293  *
1294  * Bind attribute @name to the specified location @index using
1295  * glBindAttributeLocation().
1296  */
1297 void
gst_gl_shader_bind_attribute_location(GstGLShader * shader,GLuint index,const gchar * name)1298 gst_gl_shader_bind_attribute_location (GstGLShader * shader, GLuint index,
1299     const gchar * name)
1300 {
1301   g_return_if_fail (shader != NULL);
1302   g_return_if_fail (shader->priv->program_handle != 0);
1303 
1304   GST_TRACE_OBJECT (shader, "binding program %i attribute \'%s\' location %i",
1305       (int) shader->priv->program_handle, name, index);
1306 
1307   shader->context->gl_vtable->BindAttribLocation (shader->priv->program_handle,
1308       index, name);
1309 }
1310 
1311 /**
1312  * gst_gl_shader_bind_frag_data_location:
1313  * @shader: a #GstGLShader
1314  * @index: attribute index to set
1315  * @name: name of the attribute
1316  *
1317  * Bind attribute @name to the specified location @index using
1318  * glBindFragDataLocation().
1319  */
1320 void
gst_gl_shader_bind_frag_data_location(GstGLShader * shader,guint index,const gchar * name)1321 gst_gl_shader_bind_frag_data_location (GstGLShader * shader,
1322     guint index, const gchar * name)
1323 {
1324   g_return_if_fail (shader != NULL);
1325   if (!_ensure_program (shader))
1326     g_return_if_fail (shader->priv->program_handle);
1327   g_return_if_fail (shader->context->gl_vtable->BindFragDataLocation);
1328 
1329   GST_TRACE_OBJECT (shader, "binding program %i frag data \'%s\' location %i",
1330       (int) shader->priv->program_handle, name, index);
1331 
1332   shader->context->gl_vtable->BindFragDataLocation (shader->priv->
1333       program_handle, index, name);
1334 }
1335