[clutter/wip/cogl2: 3/5] clutter-shader-effect: Use CoglSnippets



commit 33375bc65f3ebae8c784076219e681a09b32fd74
Author: Neil Roberts <neil linux intel com>
Date:   Fri Apr 27 16:29:50 2012 +0100

    clutter-shader-effect: Use CoglSnippets
    
    Instead of using the legacy CoglProgram API, ClutterShaderEffect now
    creates a pipeline with a CoglSnippet. The source code from the
    application is written as if it was a complete shader source in the
    global scope rather than as a snippet so the code is now wrapped
    between a #define main .. and a #undef main so that it won't collide
    with the main function that Cogl generates. This wrapped source is
    then set as the declarations section on the snippet.
    
    Previously the effect would store the application's uniform values in
    a hash table and then flush them to the program whenever the effect is
    painted. This has been removed and now the values are directly stored
    on the pipeline which belongs to the effect. Each instance of the
    effect gets its own pipeline so there is no need to have the extra
    indirection of the hash table.
    
    The effect API has a public function to retrieve the CoglProgram. In
    order to avoid breaking this function the snippet is now copied into a
    CoglShader and CoglProgram on demand whenever they are requested.

 clutter/clutter-offscreen-effect.c |    7 +-
 clutter/clutter-shader-effect.c    |  510 ++++++++++++++++++------------------
 2 files changed, 264 insertions(+), 253 deletions(-)
---
diff --git a/clutter/clutter-offscreen-effect.c b/clutter/clutter-offscreen-effect.c
index ee98e48..1159405 100644
--- a/clutter/clutter-offscreen-effect.c
+++ b/clutter/clutter-offscreen-effect.c
@@ -344,15 +344,18 @@ clutter_offscreen_effect_real_paint_target (ClutterOffscreenEffect *effect)
 {
   ClutterOffscreenEffectPrivate *priv = effect->priv;
   guint8 paint_opacity;
+  CoglPipeline *target;
+
+  target = COGL_PIPELINE (clutter_offscreen_effect_get_target (effect));
 
   paint_opacity = clutter_actor_get_paint_opacity (priv->actor);
 
-  cogl_pipeline_set_color4ub (priv->target,
+  cogl_pipeline_set_color4ub (target,
                               paint_opacity,
                               paint_opacity,
                               paint_opacity,
                               paint_opacity);
-  cogl_set_source (priv->target);
+  cogl_set_source (target);
 
   /* At this point we are in stage coordinates translated so if
    * we draw our texture using a textured quad the size of the paint
diff --git a/clutter/clutter-shader-effect.c b/clutter/clutter-shader-effect.c
index fbc10ca..747a250 100644
--- a/clutter/clutter-shader-effect.c
+++ b/clutter/clutter-shader-effect.c
@@ -20,6 +20,7 @@
  *
  * Author:
  *   Emmanuele Bassi <ebassi linux intel com>
+ *   Neil Roberts <neil linux intel com>
  */
 
 /**
@@ -113,6 +114,7 @@
 #include "config.h"
 #endif
 
+#define CLUTTER_ENABLE_EXPERIMENTAL_API
 /* XXX: This file depends on the cogl_program_ api with has been
  * removed for Cogl 2.0 so we undef COGL_ENABLE_EXPERIMENTAL_2_0_API
  * for this file for now */
@@ -127,34 +129,43 @@
 #include "clutter-private.h"
 #include "clutter-shader-types.h"
 
-typedef struct _ShaderUniform
-{
-  gchar *name;
-  GType type;
-  GValue value;
-  int location;
-} ShaderUniform;
-
 struct _ClutterShaderEffectPrivate
 {
   ClutterActor *actor;
 
   ClutterShaderType shader_type;
 
-  CoglHandle program;
+  /* The pipeline to use to render the texture. This will be created
+   * either when get_target is first called, when the shader source is
+   * set or when a uniform is first set. If it is created when a
+   * uniform is set then it won't get a snippet attached until
+   * something sets the source */
+  CoglPipeline *pipeline;
+  /* The snippet that was attached to the pipeline. This will be NULL
+   * if no snippet has been attached to the pipeline yet. This will
+   * happen if a uniform is set before setting the source */
+  CoglSnippet *snippet;
+
+  /* A CoglShader containing the same source as the snippet. This is
+   * created on demand only if clutter_shader_effect_get_program is
+   * called. */
   CoglHandle shader;
-
-  GHashTable *uniforms;
+  /* A CoglProgram containing the above shader. This is also only
+   * created on demand */
+  CoglHandle program;
 };
 
 typedef struct _ClutterShaderEffectClassPrivate
 {
-  /* These are the per-class pre-compiled shader and program which is
+  /* This is a per-class base pipeline with the snippet attached so
+     that Cogl can attach the pre-compiled program to it. This is only
      used when the class implements get_static_shader_source without
-     calling set_shader_source. They will be shared by all instances
-     of this class */
-  CoglHandle program;
-  CoglHandle shader;
+     calling set_shader_source. It will be shared by all instances of
+     this class */
+  CoglPipeline *base_pipeline;
+  /* When base_pipeline is not NULL, this will be a reference to the
+   * shader snippet that was used to create the pipeline */
+  CoglSnippet *base_snippet;
 } ClutterShaderEffectClassPrivate;
 
 enum
@@ -174,119 +185,6 @@ G_DEFINE_TYPE_WITH_CODE (ClutterShaderEffect,
                          g_type_add_class_private (g_define_type_id,
                                                    sizeof (ClutterShaderEffectClassPrivate)))
 
-static inline void
-clutter_shader_effect_clear (ClutterShaderEffect *self,
-                             gboolean             reset_uniforms)
-{
-  ClutterShaderEffectPrivate *priv = self->priv;
-
-  if (priv->shader != COGL_INVALID_HANDLE)
-    {
-      cogl_handle_unref (priv->shader);
-
-      priv->shader = COGL_INVALID_HANDLE;
-    }
-
-  if (priv->program != COGL_INVALID_HANDLE)
-    {
-      cogl_handle_unref (priv->program);
-
-      priv->program = COGL_INVALID_HANDLE;
-    }
-
-  if (reset_uniforms && priv->uniforms != NULL)
-    {
-      g_hash_table_destroy (priv->uniforms);
-      priv->uniforms = NULL;
-    }
-
-  priv->actor = NULL;
-}
-
-static void
-clutter_shader_effect_update_uniforms (ClutterShaderEffect *effect)
-{
-  ClutterShaderEffectPrivate *priv = effect->priv;
-  GHashTableIter iter;
-  gpointer key, value;
-  gsize size;
-
-  if (priv->program == COGL_INVALID_HANDLE)
-    return;
-
-  if (priv->uniforms == NULL)
-    return;
-
-  key = value = NULL;
-  g_hash_table_iter_init (&iter, priv->uniforms);
-  while (g_hash_table_iter_next (&iter, &key, &value))
-    {
-      ShaderUniform *uniform = value;
-
-      if (uniform->location == -1)
-        uniform->location = cogl_program_get_uniform_location (priv->program,
-                                                               uniform->name);
-
-      if (CLUTTER_VALUE_HOLDS_SHADER_FLOAT (&uniform->value))
-        {
-          const float *floats;
-
-          floats = clutter_value_get_shader_float (&uniform->value, &size);
-          cogl_program_set_uniform_float (priv->program, uniform->location,
-                                          size, 1,
-                                          floats);
-        }
-      else if (CLUTTER_VALUE_HOLDS_SHADER_INT (&uniform->value))
-        {
-          const int *ints;
-
-          ints = clutter_value_get_shader_int (&uniform->value, &size);
-          cogl_program_set_uniform_int (priv->program, uniform->location,
-                                        size, 1,
-                                        ints);
-        }
-      else if (CLUTTER_VALUE_HOLDS_SHADER_MATRIX (&uniform->value))
-        {
-          const float *matrix;
-
-          matrix = clutter_value_get_shader_matrix (&uniform->value, &size);
-          cogl_program_set_uniform_matrix (priv->program, uniform->location,
-                                           size, 1,
-                                           FALSE,
-                                           matrix);
-        }
-      else if (G_VALUE_HOLDS_FLOAT (&uniform->value))
-        {
-          const float float_val = g_value_get_float (&uniform->value);
-
-          cogl_program_set_uniform_float (priv->program, uniform->location,
-                                          1, 1,
-                                          &float_val);
-        }
-      else if (G_VALUE_HOLDS_DOUBLE (&uniform->value))
-        {
-          const float float_val =
-            (float) g_value_get_double (&uniform->value);
-
-          cogl_program_set_uniform_float (priv->program, uniform->location,
-                                          1, 1,
-                                          &float_val);
-        }
-      else if (G_VALUE_HOLDS_INT (&uniform->value))
-        {
-          const int int_val = g_value_get_int (&uniform->value);
-
-          cogl_program_set_uniform_int (priv->program, uniform->location,
-                                        1, 1,
-                                        &int_val);
-        }
-      else
-        g_warning ("Invalid uniform of type '%s' for name '%s'",
-                   g_type_name (G_VALUE_TYPE (&uniform->value)),
-                   uniform->name);
-    }
-}
-
 static void
 clutter_shader_effect_set_actor (ClutterActorMeta *meta,
                                  ClutterActor     *actor)
@@ -319,24 +217,44 @@ clutter_shader_effect_set_actor (ClutterActorMeta *meta,
                 G_OBJECT_TYPE_NAME (meta));
 }
 
-static CoglHandle
-clutter_shader_effect_create_shader (ClutterShaderEffect *self)
+static CoglSnippet *
+clutter_shader_effect_create_snippet (ClutterShaderEffect *self,
+                                      const char *source)
 {
   ClutterShaderEffectPrivate *priv = self->priv;
+  CoglSnippet *snippet;
+  char *wrapped_source;
 
   switch (priv->shader_type)
     {
     case CLUTTER_FRAGMENT_SHADER:
-      return cogl_create_shader (COGL_SHADER_TYPE_FRAGMENT);
+      snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_FRAGMENT,
+                                  NULL /* declarations */,
+                                  NULL /* post */);
       break;
 
     case CLUTTER_VERTEX_SHADER:
-      return cogl_create_shader (COGL_SHADER_TYPE_VERTEX);
+      snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_VERTEX,
+                                  NULL /* declarations */,
+                                  NULL /* post */);
       break;
 
     default:
       g_assert_not_reached ();
     }
+
+  /* The snippet can't define a 'main' function so we need to redefine
+   * the application's main function to something else */
+  wrapped_source = g_strconcat ("#define main clutter_shader_effect_main\n",
+                                source,
+                                "\n#undef main\n",
+                                NULL);
+  cogl_snippet_set_declarations (snippet, wrapped_source);
+  g_free (wrapped_source);
+
+  cogl_snippet_set_replace (snippet, "clutter_shader_effect_main ();\n");
+
+  return snippet;
 }
 
 static void
@@ -355,80 +273,70 @@ clutter_shader_effect_try_static_source (ClutterShaderEffect *self)
                                   CLUTTER_TYPE_SHADER_EFFECT,
                                   ClutterShaderEffectClassPrivate);
 
-      if (class_priv->shader == COGL_INVALID_HANDLE)
+      if (class_priv->base_pipeline == NULL)
         {
+          ClutterBackend *backend = clutter_get_default_backend ();
+          CoglContext *cogl_context =
+            clutter_backend_get_cogl_context (backend);
           gchar *source;
 
-          class_priv->shader = clutter_shader_effect_create_shader (self);
-
           source = shader_effect_class->get_static_shader_source (self);
 
-          cogl_shader_source (class_priv->shader, source);
+          class_priv->base_snippet =
+            clutter_shader_effect_create_snippet (self, source);
 
           g_free (source);
 
-          CLUTTER_NOTE (SHADER, "Compiling shader effect");
-
-          cogl_shader_compile (class_priv->shader);
-
-          if (cogl_shader_is_compiled (class_priv->shader))
-            {
-              class_priv->program = cogl_create_program ();
-
-              cogl_program_attach_shader (class_priv->program,
-                                          class_priv->shader);
+          class_priv->base_pipeline = cogl_pipeline_new (cogl_context);
 
-              cogl_program_link (class_priv->program);
-            }
-          else
-            {
-              gchar *log_buf = cogl_shader_get_info_log (class_priv->shader);
+          cogl_pipeline_add_snippet (class_priv->base_pipeline,
+                                     class_priv->base_snippet);
 
-              g_warning (G_STRLOC ": Unable to compile the GLSL shader: %s", log_buf);
-              g_free (log_buf);
-            }
+          cogl_pipeline_set_layer_null_texture (class_priv->base_pipeline,
+                                                0, /* layer_index */
+                                                COGL_TEXTURE_TYPE_2D);
         }
 
-      priv->shader = cogl_handle_ref (class_priv->shader);
+      /* There might already be a pipeline if some uniforms were set
+       * on the effect first. In that case we'll create a new pipeline
+       * and share just the snippet. This should still end up using
+       * the same GL program as other instances because Cogl will be
+       * able to recognise that the same snippet is used */
+      if (priv->pipeline)
+        cogl_pipeline_add_snippet (priv->pipeline,
+                                   class_priv->base_snippet);
+      else
+        priv->pipeline = cogl_pipeline_copy (class_priv->base_pipeline);
 
-      if (class_priv->program != COGL_INVALID_HANDLE)
-        priv->program = cogl_handle_ref (class_priv->program);
+      priv->snippet = cogl_object_ref (class_priv->base_snippet);
     }
 }
 
-static void
-clutter_shader_effect_paint_target (ClutterOffscreenEffect *effect)
+static CoglMaterial *
+clutter_shader_effect_get_target (ClutterOffscreenEffect *effect)
 {
   ClutterShaderEffect *self = CLUTTER_SHADER_EFFECT (effect);
   ClutterShaderEffectPrivate *priv = self->priv;
-  ClutterOffscreenEffectClass *parent;
-  CoglHandle material;
 
-  /* If the source hasn't been set then we'll try to get it from the
-     static source instead */
-  if (priv->shader == COGL_INVALID_HANDLE)
+  /* If the source hasn't been set yet then we'll try to get it from
+     the static source instead */
+  if (priv->snippet == NULL)
     clutter_shader_effect_try_static_source (self);
 
-  /* we haven't been prepared or we don't have support for
-   * GLSL shaders in Clutter
-   */
-  if (priv->program == COGL_INVALID_HANDLE)
-    goto out;
-
-  CLUTTER_NOTE (SHADER, "Applying the shader effect of type '%s'",
-                G_OBJECT_TYPE_NAME (effect));
-
-  clutter_shader_effect_update_uniforms (CLUTTER_SHADER_EFFECT (effect));
-
-  /* associate the program to the offscreen target material */
-  material = clutter_offscreen_effect_get_target (effect);
-  cogl_pipeline_set_user_program (material, priv->program);
-
-out:
-  /* paint the offscreen buffer */
-  parent = CLUTTER_OFFSCREEN_EFFECT_CLASS (clutter_shader_effect_parent_class);
-  parent->paint_target (effect);
+  if (priv->snippet == NULL)
+    {
+      ClutterOffscreenEffectClass *parent;
+      parent =
+        CLUTTER_OFFSCREEN_EFFECT_CLASS (clutter_shader_effect_parent_class);
+      return parent->get_target (effect);
+    }
+  else
+    {
+      CoglTexture *texture = clutter_offscreen_effect_get_texture (effect);
+      cogl_pipeline_set_layer_texture (priv->pipeline, 0, texture);
 
+      return (CoglMaterial *) priv->pipeline;
+    }
 }
 
 static void
@@ -455,8 +363,35 @@ static void
 clutter_shader_effect_finalize (GObject *gobject)
 {
   ClutterShaderEffect *effect = CLUTTER_SHADER_EFFECT (gobject);
+  ClutterShaderEffectPrivate *priv = effect->priv;
+
+  if (priv->pipeline != NULL)
+    {
+      cogl_object_unref (priv->pipeline);
+
+      priv->pipeline = NULL;
+    }
+
+  if (priv->snippet != NULL)
+    {
+      cogl_object_unref (priv->snippet);
+
+      priv->snippet = NULL;
+    }
+
+  if (priv->shader != COGL_INVALID_HANDLE)
+    {
+      cogl_handle_unref (priv->shader);
+
+      priv->shader = COGL_INVALID_HANDLE;
+    }
+
+  if (priv->program != COGL_INVALID_HANDLE)
+    {
+      cogl_handle_unref (priv->program);
 
-  clutter_shader_effect_clear (effect, TRUE);
+      priv->program = COGL_INVALID_HANDLE;
+    }
 
   G_OBJECT_CLASS (clutter_shader_effect_parent_class)->finalize (gobject);
 }
@@ -497,7 +432,7 @@ clutter_shader_effect_class_init (ClutterShaderEffectClass *klass)
 
   meta_class->set_actor = clutter_shader_effect_set_actor;
 
-  offscreen_class->paint_target = clutter_shader_effect_paint_target;
+  offscreen_class->get_target = clutter_shader_effect_get_target;
 }
 
 static void
@@ -546,10 +481,64 @@ clutter_shader_effect_new (ClutterShaderType shader_type)
 CoglHandle
 clutter_shader_effect_get_shader (ClutterShaderEffect *effect)
 {
+  ClutterShaderEffectPrivate *priv;
+  char *source;
+
   g_return_val_if_fail (CLUTTER_IS_SHADER_EFFECT (effect),
                         COGL_INVALID_HANDLE);
 
-  return effect->priv->shader;
+  priv = effect->priv;
+
+  if (priv->shader != COGL_INVALID_HANDLE)
+    return priv->shader;
+
+  if (priv->snippet == NULL)
+    /* Source not set yet */
+    return COGL_INVALID_HANDLE;
+
+  switch (priv->shader_type)
+    {
+    case CLUTTER_FRAGMENT_SHADER:
+      priv->shader = cogl_create_shader (COGL_SHADER_TYPE_FRAGMENT);
+      break;
+
+    case CLUTTER_VERTEX_SHADER:
+      priv->shader = cogl_create_shader (COGL_SHADER_TYPE_VERTEX);
+      break;
+
+    default:
+      g_assert_not_reached ();
+    }
+
+  /* The source in the snippet is wrapped to replace the main
+   * function. To convert it back to a full shader source we need to
+   * add some extra code to call the wrapped main function */
+  source = g_strconcat (cogl_snippet_get_declarations (priv->snippet),
+                        "\n"
+                        "void\n"
+                        "main ()\n"
+                        "{\n"
+                        "  clutter_shader_effect_main ();\n"
+                        "}\n",
+                        NULL);
+
+  cogl_shader_source (priv->shader, source);
+
+  g_free (source);
+
+  cogl_shader_compile (priv->shader);
+
+  if (!cogl_shader_is_compiled (priv->shader))
+    {
+      gchar *log_buf = cogl_shader_get_info_log (priv->shader);
+      g_warning (G_STRLOC ": Unable to compile the GLSL shader: %s", log_buf);
+      g_free (log_buf);
+
+      cogl_handle_unref (priv->shader);
+      priv->shader = NULL;
+    }
+
+  return priv->shader;
 }
 
 /**
@@ -566,51 +555,41 @@ clutter_shader_effect_get_shader (ClutterShaderEffect *effect)
 CoglHandle
 clutter_shader_effect_get_program (ClutterShaderEffect *effect)
 {
+  ClutterShaderEffectPrivate *priv;
+  CoglHandle shader;
+
   g_return_val_if_fail (CLUTTER_IS_SHADER_EFFECT (effect),
                         COGL_INVALID_HANDLE);
 
-  return effect->priv->program;
-}
-
-static void
-shader_uniform_free (gpointer data)
-{
-  if (data != NULL)
-    {
-      ShaderUniform *uniform = data;
-
-      g_value_unset (&uniform->value);
-      g_free (uniform->name);
+  priv = effect->priv;
 
-      g_slice_free (ShaderUniform, uniform);
-    }
-}
+  if (priv->program != COGL_INVALID_HANDLE)
+    return priv->program;
 
-static ShaderUniform *
-shader_uniform_new (const gchar  *name,
-                    const GValue *value)
-{
-  ShaderUniform *retval;
+  shader = clutter_shader_effect_get_shader (effect);
 
-  retval = g_slice_new0 (ShaderUniform);
-  retval->name = g_strdup (name);
-  retval->type = G_VALUE_TYPE (value);
-  retval->location = -1;
+  if (shader == COGL_INVALID_HANDLE)
+    return COGL_INVALID_HANDLE;
 
-  g_value_init (&retval->value, retval->type);
-  g_value_copy (value, &retval->value);
+  priv->program = cogl_create_program ();
+  cogl_program_attach_shader (priv->program, shader);
+  cogl_program_link (priv->program);
 
-  return retval;
+  return priv->program;
 }
 
 static void
-shader_uniform_update (ShaderUniform *uniform,
-                       const GValue  *value)
+clutter_shader_effect_ensure_pipeline (ClutterShaderEffect *effect)
 {
-  g_value_unset (&uniform->value);
+  ClutterShaderEffectPrivate *priv = effect->priv;
+
+  if (priv->pipeline == NULL)
+    {
+      CoglContext *context =
+        clutter_backend_get_cogl_context (clutter_get_default_backend ());
 
-  g_value_init (&uniform->value, G_VALUE_TYPE (value));
-  g_value_copy (value, &uniform->value);
+      priv->pipeline = cogl_pipeline_new (context);
+    }
 }
 
 static inline void
@@ -619,23 +598,70 @@ clutter_shader_effect_add_uniform (ClutterShaderEffect *effect,
                                    const GValue        *value)
 {
   ClutterShaderEffectPrivate *priv = effect->priv;
-  ShaderUniform *uniform;
+  int uniform_location;
+  gsize size;
 
-  if (priv->uniforms == NULL)
+  clutter_shader_effect_ensure_pipeline (effect);
+
+  uniform_location = cogl_pipeline_get_uniform_location (priv->pipeline, name);
+
+  if (CLUTTER_VALUE_HOLDS_SHADER_FLOAT (value))
     {
-      priv->uniforms = g_hash_table_new_full (g_str_hash, g_str_equal,
-                                              NULL,
-                                              shader_uniform_free);
+      const float *floats;
+
+      floats = clutter_value_get_shader_float (value, &size);
+      cogl_pipeline_set_uniform_float (priv->pipeline, uniform_location,
+                                       size, 1,
+                                       floats);
     }
+  else if (CLUTTER_VALUE_HOLDS_SHADER_INT (value))
+    {
+      const int *ints;
 
-  uniform = g_hash_table_lookup (priv->uniforms, name);
-  if (uniform == NULL)
+      ints = clutter_value_get_shader_int (value, &size);
+      cogl_pipeline_set_uniform_int (priv->pipeline, uniform_location,
+                                     size, 1,
+                                     ints);
+    }
+  else if (CLUTTER_VALUE_HOLDS_SHADER_MATRIX (value))
     {
-      uniform = shader_uniform_new (name, value);
-      g_hash_table_insert (priv->uniforms, uniform->name, uniform);
+      const float *matrix;
+
+      matrix = clutter_value_get_shader_matrix (value, &size);
+      cogl_pipeline_set_uniform_matrix (priv->pipeline, uniform_location,
+                                        size, 1,
+                                        FALSE,
+                                        matrix);
+    }
+  else if (G_VALUE_HOLDS_FLOAT (value))
+    {
+      const float float_val = g_value_get_float (value);
+
+      cogl_pipeline_set_uniform_float (priv->pipeline, uniform_location,
+                                       1, 1,
+                                       &float_val);
+    }
+  else if (G_VALUE_HOLDS_DOUBLE (value))
+    {
+      const float float_val =
+        (float) g_value_get_double (value);
+
+      cogl_pipeline_set_uniform_float (priv->pipeline, uniform_location,
+                                       1, 1,
+                                       &float_val);
+    }
+  else if (G_VALUE_HOLDS_INT (value))
+    {
+      const int int_val = g_value_get_int (value);
+
+      cogl_pipeline_set_uniform_int (priv->pipeline, uniform_location,
+                                     1, 1,
+                                     &int_val);
     }
   else
-    shader_uniform_update (uniform, value);
+    g_warning ("Invalid uniform of type '%s' for name '%s'",
+               g_type_name (G_VALUE_TYPE (value)),
+               name);
 
   if (priv->actor != NULL && !CLUTTER_ACTOR_IN_PAINT (priv->actor))
     clutter_effect_queue_repaint (CLUTTER_EFFECT (effect));
@@ -897,32 +923,14 @@ clutter_shader_effect_set_shader_source (ClutterShaderEffect *effect,
 
   priv = effect->priv;
 
-  if (priv->shader != COGL_INVALID_HANDLE)
+  if (priv->snippet != NULL)
     return TRUE;
 
-  priv->shader = clutter_shader_effect_create_shader (effect);
-
-  cogl_shader_source (priv->shader, source);
-
-  CLUTTER_NOTE (SHADER, "Compiling shader effect");
+  clutter_shader_effect_ensure_pipeline (effect);
 
-  cogl_shader_compile (priv->shader);
+  priv->snippet = clutter_shader_effect_create_snippet (effect, source);
 
-  if (cogl_shader_is_compiled (priv->shader))
-    {
-      priv->program = cogl_create_program ();
-
-      cogl_program_attach_shader (priv->program, priv->shader);
-
-      cogl_program_link (priv->program);
-    }
-  else
-    {
-      gchar *log_buf = cogl_shader_get_info_log (priv->shader);
-
-      g_warning (G_STRLOC ": Unable to compile the GLSL shader: %s", log_buf);
-      g_free (log_buf);
-    }
+  cogl_pipeline_add_snippet (priv->pipeline, priv->snippet);
 
   return TRUE;
 }



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]