4 * An OpenGL based 'interactive canvas' library.
6 * Copyright (C) 2010 Intel Corporation.
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
22 * Emmanuele Bassi <ebassi@linux.intel.com>
26 * SECTION:clutter-shader-effect
27 * @short_description: Base class for shader effects
28 * @See_Also: #ClutterEffect, #ClutterOffscreenEffect
30 * #ClutterShaderEffect is a class that implements all the plumbing for
31 * creating #ClutterEffect<!-- -->s using GLSL shaders.
33 * #ClutterShaderEffect creates an offscreen buffer and then applies the
34 * GLSL shader (after checking whether the compilation and linking were
35 * successfull) to the buffer before painting it on screen.
37 * <refsect2 id="ClutterShaderEffect-implementing">
38 * <title>Implementing a ClutterShaderEffect</title>
39 * <para>Creating a sub-class of #ClutterShaderEffect requires the
40 * overriding of the <function>paint_target()</function> virtual
41 * function from the #ClutterOffscreenEffect class as well as the
42 * <function>get_static_shader_source()</function> virtual from the
43 * #ClutterShaderEffect class.</para>
44 * <para>The <function>get_static_shader_source()</function>
45 * function should return a copy of the shader source to use. This
46 * function is only called once per subclass of #ClutterShaderEffect
47 * regardless of how many instances of the effect are created. The
48 * source for the shader is typically stored in a static const
49 * string which is returned from this function via
51 * <para>The <function>paint_target()</function> should set the
52 * shader's uniforms if any. This is done by calling
53 * clutter_shader_effect_set_uniform_value() or
54 * clutter_shader_effect_set_uniform(). The sub-class should then
55 * chain up to the #ClutterShaderEffect implementation.</para>
56 * <example id="ClutterShaderEffect-example-uniforms">
57 * <title>Setting uniforms on a ClutterShaderEffect</title>
58 * <para>The example below shows a typical implementation of the
59 * <function>get_static_shader_source()</function> and
60 * <function>paint_target()</function> phases of a
61 * #ClutterShaderEffect sub-class.</para>
64 * my_effect_get_static_shader_source (ClutterShaderEffect *effect)
66 * return g_strdup (shader_source);
70 * my_effect_paint_target (ClutterOffscreenEffect *effect)
72 * MyEffect *self = MY_EFFECT (effect);
73 * ClutterShaderEffect *shader = CLUTTER_SHADER_EFFECT (effect);
74 * ClutterEffectClass *parent_class;
75 * gfloat component_r, component_g, component_b;
77 * /* the "tex" uniform is declared in the shader as:
79 * * uniform int tex;
81 * * and it is passed a constant value of 0
83 * clutter_shader_effect_set_uniform (shader, "tex", G_TYPE_INT, 1, 0);
85 * /* the "component" uniform is declared in the shader as:
87 * * uniform vec3 component;
89 * * and it's defined to contain the normalized components
90 * * of a #ClutterColor
92 * component_r = self->color.red / 255.0f;
93 * component_g = self->color.green / 255.0f;
94 * component_b = self->color.blue / 255.0f;
95 * clutter_shader_effect_set_uniform (shader, "component",
101 * /* chain up to the parent's implementation */
102 * parent_class = CLUTTER_OFFSCREEN_EFFECT_CLASS (my_effect_parent_class);
103 * return parent_class->paint_target (effect);
109 * #ClutterShaderEffect is available since Clutter 1.4
116 /* XXX: This file depends on the cogl_program_ api with has been
117 * removed for Cogl 2.0 so we undef COGL_ENABLE_EXPERIMENTAL_2_0_API
118 * for this file for now */
119 #undef COGL_ENABLE_EXPERIMENTAL_2_0_API
120 #include "cogl/cogl.h"
122 #include "clutter-shader-effect.h"
124 #include "clutter-debug.h"
125 #include "clutter-enum-types.h"
126 #include "clutter-feature.h"
127 #include "clutter-private.h"
128 #include "clutter-shader-types.h"
130 typedef struct _ShaderUniform
138 struct _ClutterShaderEffectPrivate
142 ClutterShaderType shader_type;
147 GHashTable *uniforms;
150 typedef struct _ClutterShaderEffectClassPrivate
152 /* These are the per-class pre-compiled shader and program which is
153 used when the class implements get_static_shader_source without
154 calling set_shader_source. They will be shared by all instances
158 } ClutterShaderEffectClassPrivate;
169 static GParamSpec *obj_props[PROP_LAST];
171 G_DEFINE_TYPE_WITH_CODE (ClutterShaderEffect,
172 clutter_shader_effect,
173 CLUTTER_TYPE_OFFSCREEN_EFFECT,
174 g_type_add_class_private (g_define_type_id,
175 sizeof (ClutterShaderEffectClassPrivate)))
178 clutter_shader_effect_clear (ClutterShaderEffect *self,
179 gboolean reset_uniforms)
181 ClutterShaderEffectPrivate *priv = self->priv;
183 if (priv->shader != COGL_INVALID_HANDLE)
185 cogl_handle_unref (priv->shader);
187 priv->shader = COGL_INVALID_HANDLE;
190 if (priv->program != COGL_INVALID_HANDLE)
192 cogl_handle_unref (priv->program);
194 priv->program = COGL_INVALID_HANDLE;
197 if (reset_uniforms && priv->uniforms != NULL)
199 g_hash_table_destroy (priv->uniforms);
200 priv->uniforms = NULL;
207 clutter_shader_effect_update_uniforms (ClutterShaderEffect *effect)
209 ClutterShaderEffectPrivate *priv = effect->priv;
214 if (priv->program == COGL_INVALID_HANDLE)
217 if (priv->uniforms == NULL)
221 g_hash_table_iter_init (&iter, priv->uniforms);
222 while (g_hash_table_iter_next (&iter, &key, &value))
224 ShaderUniform *uniform = value;
226 if (uniform->location == -1)
227 uniform->location = cogl_program_get_uniform_location (priv->program,
230 if (CLUTTER_VALUE_HOLDS_SHADER_FLOAT (&uniform->value))
232 const GLfloat *floats;
234 floats = clutter_value_get_shader_float (&uniform->value, &size);
235 cogl_program_set_uniform_float (priv->program, uniform->location,
239 else if (CLUTTER_VALUE_HOLDS_SHADER_INT (&uniform->value))
243 ints = clutter_value_get_shader_int (&uniform->value, &size);
244 cogl_program_set_uniform_int (priv->program, uniform->location,
248 else if (CLUTTER_VALUE_HOLDS_SHADER_MATRIX (&uniform->value))
250 const GLfloat *matrix;
252 matrix = clutter_value_get_shader_matrix (&uniform->value, &size);
253 cogl_program_set_uniform_matrix (priv->program, uniform->location,
258 else if (G_VALUE_HOLDS_FLOAT (&uniform->value))
260 const GLfloat float_val = g_value_get_float (&uniform->value);
262 cogl_program_set_uniform_float (priv->program, uniform->location,
266 else if (G_VALUE_HOLDS_DOUBLE (&uniform->value))
268 const GLfloat float_val =
269 (GLfloat) g_value_get_double (&uniform->value);
271 cogl_program_set_uniform_float (priv->program, uniform->location,
275 else if (G_VALUE_HOLDS_INT (&uniform->value))
277 const GLint int_val = g_value_get_int (&uniform->value);
279 cogl_program_set_uniform_int (priv->program, uniform->location,
284 g_warning ("Invalid uniform of type '%s' for name '%s'",
285 g_type_name (G_VALUE_TYPE (&uniform->value)),
291 clutter_shader_effect_set_actor (ClutterActorMeta *meta,
294 ClutterShaderEffect *self = CLUTTER_SHADER_EFFECT (meta);
295 ClutterShaderEffectPrivate *priv = self->priv;
296 ClutterActorMetaClass *parent;
298 if (!clutter_feature_available (CLUTTER_FEATURE_SHADERS_GLSL))
300 /* if we don't have support for GLSL shaders then we
301 * forcibly disable the ActorMeta
303 g_warning ("Unable to use the ShaderEffect: the graphics hardware "
304 "or the current GL driver does not implement support "
305 "for the GLSL shading language.");
306 clutter_actor_meta_set_enabled (meta, FALSE);
310 parent = CLUTTER_ACTOR_META_CLASS (clutter_shader_effect_parent_class);
311 parent->set_actor (meta, actor);
313 /* we keep a back pointer here */
314 priv->actor = clutter_actor_meta_get_actor (meta);
315 if (priv->actor == NULL)
318 CLUTTER_NOTE (SHADER, "Preparing shader effect of type '%s'",
319 G_OBJECT_TYPE_NAME (meta));
323 clutter_shader_effect_create_shader (ClutterShaderEffect *self)
325 ClutterShaderEffectPrivate *priv = self->priv;
327 switch (priv->shader_type)
329 case CLUTTER_FRAGMENT_SHADER:
330 return cogl_create_shader (COGL_SHADER_TYPE_FRAGMENT);
333 case CLUTTER_VERTEX_SHADER:
334 return cogl_create_shader (COGL_SHADER_TYPE_VERTEX);
338 g_assert_not_reached ();
343 clutter_shader_effect_try_static_source (ClutterShaderEffect *self)
345 ClutterShaderEffectPrivate *priv = self->priv;
346 ClutterShaderEffectClass *shader_effect_class =
347 CLUTTER_SHADER_EFFECT_GET_CLASS (self);
349 if (shader_effect_class->get_static_shader_source != NULL)
351 ClutterShaderEffectClassPrivate *class_priv;
354 G_TYPE_CLASS_GET_PRIVATE (shader_effect_class,
355 CLUTTER_TYPE_SHADER_EFFECT,
356 ClutterShaderEffectClassPrivate);
358 if (class_priv->shader == COGL_INVALID_HANDLE)
362 class_priv->shader = clutter_shader_effect_create_shader (self);
364 source = shader_effect_class->get_static_shader_source (self);
366 cogl_shader_source (class_priv->shader, source);
370 CLUTTER_NOTE (SHADER, "Compiling shader effect");
372 cogl_shader_compile (class_priv->shader);
374 if (cogl_shader_is_compiled (class_priv->shader))
376 class_priv->program = cogl_create_program ();
378 cogl_program_attach_shader (class_priv->program,
381 cogl_program_link (class_priv->program);
385 gchar *log_buf = cogl_shader_get_info_log (class_priv->shader);
387 g_warning (G_STRLOC ": Unable to compile the GLSL shader: %s", log_buf);
392 priv->shader = cogl_handle_ref (class_priv->shader);
394 if (class_priv->program != COGL_INVALID_HANDLE)
395 priv->program = cogl_handle_ref (class_priv->program);
400 clutter_shader_effect_paint_target (ClutterOffscreenEffect *effect)
402 ClutterShaderEffect *self = CLUTTER_SHADER_EFFECT (effect);
403 ClutterShaderEffectPrivate *priv = self->priv;
404 ClutterOffscreenEffectClass *parent;
407 /* If the source hasn't been set then we'll try to get it from the
408 static source instead */
409 if (priv->shader == COGL_INVALID_HANDLE)
410 clutter_shader_effect_try_static_source (self);
412 /* we haven't been prepared or we don't have support for
413 * GLSL shaders in Clutter
415 if (priv->program == COGL_INVALID_HANDLE)
418 CLUTTER_NOTE (SHADER, "Applying the shader effect of type '%s'",
419 G_OBJECT_TYPE_NAME (effect));
421 clutter_shader_effect_update_uniforms (CLUTTER_SHADER_EFFECT (effect));
423 /* associate the program to the offscreen target material */
424 material = clutter_offscreen_effect_get_target (effect);
425 cogl_pipeline_set_user_program (material, priv->program);
428 /* paint the offscreen buffer */
429 parent = CLUTTER_OFFSCREEN_EFFECT_CLASS (clutter_shader_effect_parent_class);
430 parent->paint_target (effect);
435 clutter_shader_effect_set_property (GObject *gobject,
440 ClutterShaderEffectPrivate *priv = CLUTTER_SHADER_EFFECT (gobject)->priv;
444 case PROP_SHADER_TYPE:
445 priv->shader_type = g_value_get_enum (value);
449 G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
455 clutter_shader_effect_finalize (GObject *gobject)
457 ClutterShaderEffect *effect = CLUTTER_SHADER_EFFECT (gobject);
459 clutter_shader_effect_clear (effect, TRUE);
461 G_OBJECT_CLASS (clutter_shader_effect_parent_class)->finalize (gobject);
465 clutter_shader_effect_class_init (ClutterShaderEffectClass *klass)
467 ClutterActorMetaClass *meta_class = CLUTTER_ACTOR_META_CLASS (klass);
468 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
469 ClutterOffscreenEffectClass *offscreen_class;
471 offscreen_class = CLUTTER_OFFSCREEN_EFFECT_CLASS (klass);
473 g_type_class_add_private (klass, sizeof (ClutterShaderEffectPrivate));
476 * ClutterShaderEffect:shader-type:
478 * The type of shader that is used by the effect. This property
479 * should be set by the constructor of #ClutterShaderEffect
484 obj_props[PROP_SHADER_TYPE] =
485 g_param_spec_enum ("shader-type",
487 P_("The type of shader used"),
488 CLUTTER_TYPE_SHADER_TYPE,
489 CLUTTER_FRAGMENT_SHADER,
490 CLUTTER_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY);
492 gobject_class->set_property = clutter_shader_effect_set_property;
493 gobject_class->finalize = clutter_shader_effect_finalize;
494 g_object_class_install_properties (gobject_class,
498 meta_class->set_actor = clutter_shader_effect_set_actor;
500 offscreen_class->paint_target = clutter_shader_effect_paint_target;
504 clutter_shader_effect_init (ClutterShaderEffect *effect)
506 effect->priv = G_TYPE_INSTANCE_GET_PRIVATE (effect,
507 CLUTTER_TYPE_SHADER_EFFECT,
508 ClutterShaderEffectPrivate);
512 * clutter_shader_effect_new:
513 * @shader_type: the type of the shader, either %CLUTTER_FRAGMENT_SHADER,
514 * or %CLUTTER_VERTEX_SHADER
516 * Creates a new #ClutterShaderEffect, to be applied to an actor using
517 * clutter_actor_add_effect().
519 * The effect will be empty until clutter_shader_effect_set_shader_source()
522 * Return value: (transfer full): the newly created #ClutterShaderEffect.
523 * Use g_object_unref() when done.
528 clutter_shader_effect_new (ClutterShaderType shader_type)
530 return g_object_new (CLUTTER_TYPE_SHADER_EFFECT,
531 "shader-type", shader_type,
536 * clutter_shader_effect_get_shader:
537 * @effect: a #ClutterShaderEffect
539 * Retrieves a pointer to the shader's handle
541 * Return value: (transfer none): a pointer to the shader's handle,
542 * or %COGL_INVALID_HANDLE
547 clutter_shader_effect_get_shader (ClutterShaderEffect *effect)
549 g_return_val_if_fail (CLUTTER_IS_SHADER_EFFECT (effect),
550 COGL_INVALID_HANDLE);
552 return effect->priv->shader;
556 * clutter_shader_effect_get_program:
557 * @effect: a #ClutterShaderEffect
559 * Retrieves a pointer to the program's handle
561 * Return value: (transfer none): a pointer to the program's handle,
562 * or %COGL_INVALID_HANDLE
567 clutter_shader_effect_get_program (ClutterShaderEffect *effect)
569 g_return_val_if_fail (CLUTTER_IS_SHADER_EFFECT (effect),
570 COGL_INVALID_HANDLE);
572 return effect->priv->program;
576 shader_uniform_free (gpointer data)
580 ShaderUniform *uniform = data;
582 g_value_unset (&uniform->value);
583 g_free (uniform->name);
585 g_slice_free (ShaderUniform, uniform);
589 static ShaderUniform *
590 shader_uniform_new (const gchar *name,
593 ShaderUniform *retval;
595 retval = g_slice_new0 (ShaderUniform);
596 retval->name = g_strdup (name);
597 retval->type = G_VALUE_TYPE (value);
598 retval->location = -1;
600 g_value_init (&retval->value, retval->type);
601 g_value_copy (value, &retval->value);
607 shader_uniform_update (ShaderUniform *uniform,
610 g_value_unset (&uniform->value);
612 g_value_init (&uniform->value, G_VALUE_TYPE (value));
613 g_value_copy (value, &uniform->value);
617 clutter_shader_effect_add_uniform (ClutterShaderEffect *effect,
621 ClutterShaderEffectPrivate *priv = effect->priv;
622 ShaderUniform *uniform;
624 if (priv->uniforms == NULL)
626 priv->uniforms = g_hash_table_new_full (g_str_hash, g_str_equal,
628 shader_uniform_free);
631 uniform = g_hash_table_lookup (priv->uniforms, name);
634 uniform = shader_uniform_new (name, value);
635 g_hash_table_insert (priv->uniforms, uniform->name, uniform);
638 shader_uniform_update (uniform, value);
640 if (priv->actor != NULL && !CLUTTER_ACTOR_IN_PAINT (priv->actor))
641 clutter_effect_queue_repaint (CLUTTER_EFFECT (effect));
645 * clutter_shader_effect_set_uniform_value:
646 * @effect: a #ClutterShaderEffect
647 * @name: the name of the uniform to set
648 * @value: a #GValue with the value of the uniform to set
650 * Sets @value as the payload for the uniform @name inside the shader
653 * The #GType of the @value must be one of: %G_TYPE_INT, for a single
654 * integer value; %G_TYPE_FLOAT, for a single floating point value;
655 * %CLUTTER_TYPE_SHADER_INT, for an array of integer values;
656 * %CLUTTER_TYPE_SHADER_FLOAT, for an array of floating point values;
657 * and %CLUTTER_TYPE_SHADER_MATRIX, for a matrix of floating point
658 * values. It also accepts %G_TYPE_DOUBLE for compatibility with other
664 clutter_shader_effect_set_uniform_value (ClutterShaderEffect *effect,
668 g_return_if_fail (CLUTTER_IS_SHADER_EFFECT (effect));
669 g_return_if_fail (name != NULL);
670 g_return_if_fail (value != NULL);
672 clutter_shader_effect_add_uniform (effect, name, value);
676 clutter_shader_effect_set_uniform_valist (ClutterShaderEffect *effect,
682 GValue value = G_VALUE_INIT;
684 if (value_type == CLUTTER_TYPE_SHADER_INT)
686 gint *int_values = va_arg (*args, gint*);
688 g_value_init (&value, CLUTTER_TYPE_SHADER_INT);
689 clutter_value_set_shader_int (&value, n_values, int_values);
694 if (value_type == CLUTTER_TYPE_SHADER_FLOAT)
696 gfloat *float_values = va_arg (*args, gfloat*);
698 g_value_init (&value, CLUTTER_TYPE_SHADER_FLOAT);
699 clutter_value_set_shader_float (&value, n_values, float_values);
704 if (value_type == CLUTTER_TYPE_SHADER_MATRIX)
706 gfloat *float_values = va_arg (*args, gfloat*);
708 g_value_init (&value, CLUTTER_TYPE_SHADER_MATRIX);
709 clutter_value_set_shader_matrix (&value, n_values, float_values);
714 if (value_type == G_TYPE_INT)
716 g_return_if_fail (n_values <= 4);
718 /* if we only have one value we can go through the fast path
719 * of using G_TYPE_INT, otherwise we create a vector of integers
720 * from the passed values
724 gint int_val = va_arg (*args, gint);
726 g_value_init (&value, G_TYPE_INT);
727 g_value_set_int (&value, int_val);
731 gint *int_values = g_new (gint, n_values);
734 for (i = 0; i < n_values; i++)
735 int_values[i] = va_arg (*args, gint);
737 g_value_init (&value, CLUTTER_TYPE_SHADER_INT);
738 clutter_value_set_shader_int (&value, n_values, int_values);
746 if (value_type == G_TYPE_FLOAT)
748 g_return_if_fail (n_values <= 4);
750 /* if we only have one value we can go through the fast path
751 * of using G_TYPE_FLOAT, otherwise we create a vector of floats
752 * from the passed values
756 gfloat float_val = (gfloat) va_arg (*args, gdouble);
758 g_value_init (&value, G_TYPE_FLOAT);
759 g_value_set_float (&value, float_val);
763 gfloat *float_values = g_new (gfloat, n_values);
766 for (i = 0; i < n_values; i++)
767 float_values[i] = (gfloat) va_arg (*args, double);
769 g_value_init (&value, CLUTTER_TYPE_SHADER_FLOAT);
770 clutter_value_set_shader_float (&value, n_values, float_values);
772 g_free (float_values);
778 g_warning ("Unrecognized type '%s' (values: %d) for uniform name '%s'",
779 g_type_name (value_type),
785 clutter_shader_effect_add_uniform (effect, name, &value);
786 g_value_unset (&value);
790 * clutter_shader_effect_set_uniform:
791 * @effect: a #ClutterShaderEffect
792 * @name: the name of the uniform to set
793 * @gtype: the type of the uniform to set
794 * @n_values: the number of values
795 * @...: a list of values
797 * Sets a list of values as the payload for the uniform @name inside
800 * The @gtype must be one of: %G_TYPE_INT, for 1 or more integer values;
801 * %G_TYPE_FLOAT, for 1 or more floating point values;
802 * %CLUTTER_TYPE_SHADER_INT, for a pointer to an array of integer values;
803 * %CLUTTER_TYPE_SHADER_FLOAT, for a pointer to an array of floating point
804 * values; and %CLUTTER_TYPE_SHADER_MATRIX, for a pointer to an array of
805 * floating point values mapping a matrix
807 * The number of values interepreted is defined by the @n_value
808 * argument, and by the @gtype argument. For instance, a uniform named
809 * "sampler0" and containing a single integer value is set using:
812 * clutter_shader_effect_set_uniform (effect, "sampler0",
817 * While a uniform named "components" and containing a 3-elements vector
818 * of floating point values (a "vec3") can be set using:
821 * gfloat component_r, component_g, component_b;
823 * clutter_shader_effect_set_uniform (effect, "components",
830 * or can be set using:
833 * gfloat component_vec[3];
835 * clutter_shader_effect_set_uniform (effect, "components",
836 * CLUTTER_TYPE_SHADER_FLOAT, 3,
840 * Finally, a uniform named "map" and containing a matrix can be set using:
843 * clutter_shader_effect_set_uniform (effect, "map",
844 * CLUTTER_TYPE_SHADER_MATRIX, 1,
845 * cogl_matrix_get_array (&matrix));
851 clutter_shader_effect_set_uniform (ClutterShaderEffect *effect,
859 g_return_if_fail (CLUTTER_IS_SHADER_EFFECT (effect));
860 g_return_if_fail (name != NULL);
861 g_return_if_fail (gtype != G_TYPE_INVALID);
862 g_return_if_fail (n_values > 0);
864 va_start (args, n_values);
865 clutter_shader_effect_set_uniform_valist (effect, name,
873 * clutter_shader_effect_set_shader_source:
874 * @effect: a #ClutterShaderEffect
875 * @source: the source of a GLSL shader
877 * Sets the source of the GLSL shader used by @effect
879 * This function should only be called by implementations of
880 * the #ClutterShaderEffect class, and not by application code.
882 * This function can only be called once; subsequent calls will
885 * Return value: %TRUE if the source was set
890 clutter_shader_effect_set_shader_source (ClutterShaderEffect *effect,
893 ClutterShaderEffectPrivate *priv;
895 g_return_val_if_fail (CLUTTER_IS_SHADER_EFFECT (effect), FALSE);
896 g_return_val_if_fail (source != NULL && *source != '\0', FALSE);
900 if (priv->shader != COGL_INVALID_HANDLE)
903 priv->shader = clutter_shader_effect_create_shader (effect);
905 cogl_shader_source (priv->shader, source);
907 CLUTTER_NOTE (SHADER, "Compiling shader effect");
909 cogl_shader_compile (priv->shader);
911 if (cogl_shader_is_compiled (priv->shader))
913 priv->program = cogl_create_program ();
915 cogl_program_attach_shader (priv->program, priv->shader);
917 cogl_program_link (priv->program);
921 gchar *log_buf = cogl_shader_get_info_log (priv->shader);
923 g_warning (G_STRLOC ": Unable to compile the GLSL shader: %s", log_buf);