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 retrieve 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 retrieve 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 retrieve 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", 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, "retrieved 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