[cogl/wip/neil/snippets: 13/21] snippet: Move the hook to be a property of the snippet



commit cd19e9f6c467ba67bf3a735608b6c2dadd2c17ef
Author: Neil Roberts <neil linux intel com>
Date:   Fri Nov 25 20:54:14 2011 +0000

    snippet: Move the hook to be a property of the snippet
    
    Instead of specifying the hook point when adding to the pipeline using
    a separate function for each hook, the hook is now a property of the
    snippet. The hook is set on construction and is then read-only.

 cogl/cogl-pipeline-fragend-glsl.c    |    4 +-
 cogl/cogl-pipeline-layer-state.c     |   27 ++++---
 cogl/cogl-pipeline-layer-state.h     |   44 +++-------
 cogl/cogl-pipeline-snippet-private.h |   15 +---
 cogl/cogl-pipeline-snippet.c         |    9 +--
 cogl/cogl-pipeline-state.c           |   34 ++------
 cogl/cogl-pipeline-state.h           |   67 ++-------------
 cogl/cogl-pipeline-vertend-glsl.c    |    2 +-
 cogl/cogl-snippet-private.h          |   16 ++++
 cogl/cogl-snippet.c                  |   13 +++-
 cogl/cogl-snippet.h                  |  151 +++++++++++++++++++++++++++++++++-
 tests/conform/test-snippets.c        |   62 +++++++++-----
 12 files changed, 270 insertions(+), 174 deletions(-)
---
diff --git a/cogl/cogl-pipeline-fragend-glsl.c b/cogl/cogl-pipeline-fragend-glsl.c
index 1a34135..d23541b 100644
--- a/cogl/cogl-pipeline-fragend-glsl.c
+++ b/cogl/cogl-pipeline-fragend-glsl.c
@@ -481,7 +481,7 @@ ensure_texture_lookup_generated (CoglPipelineShaderState *shader_state,
   /* Wrap the texture lookup in any snippets that have been hooked */
   memset (&snippet_data, 0, sizeof (snippet_data));
   snippet_data.snippets = get_layer_fragment_snippets (layer);
-  snippet_data.hook = COGL_PIPELINE_SNIPPET_HOOK_TEXTURE_LOOKUP;
+  snippet_data.hook = COGL_SNIPPET_HOOK_TEXTURE_LOOKUP;
   snippet_data.chain_function = g_strdup_printf ("cogl_real_texture_lookup%i",
                                                  unit_index);
   snippet_data.final_name = g_strdup_printf ("cogl_texture_lookup%i",
@@ -977,7 +977,7 @@ _cogl_pipeline_fragend_glsl_end (CoglPipeline *pipeline,
       /* Add all of the hooks for fragment processing */
       memset (&snippet_data, 0, sizeof (snippet_data));
       snippet_data.snippets = get_fragment_snippets (pipeline);
-      snippet_data.hook = COGL_PIPELINE_SNIPPET_HOOK_FRAGMENT;
+      snippet_data.hook = COGL_SNIPPET_HOOK_FRAGMENT;
       snippet_data.chain_function = "cogl_generated_source";
       snippet_data.final_name = "main";
       snippet_data.function_prefix = "cogl_fragment_hook";
diff --git a/cogl/cogl-pipeline-layer-state.c b/cogl/cogl-pipeline-layer-state.c
index 8df86fc..1523d36 100644
--- a/cogl/cogl-pipeline-layer-state.c
+++ b/cogl/cogl-pipeline-layer-state.c
@@ -34,6 +34,7 @@
 #include "cogl-blend-string.h"
 #include "cogl-util.h"
 #include "cogl-matrix.h"
+#include "cogl-snippet-private.h"
 
 #include "string.h"
 #if 0
@@ -777,14 +778,11 @@ cogl_pipeline_get_layer_point_sprite_coords_enabled (CoglPipeline *pipeline,
 static void
 _cogl_pipeline_layer_add_fragment_snippet (CoglPipeline *pipeline,
                                            int layer_index,
-                                           CoglPipelineSnippetHook hook,
                                            CoglSnippet *snippet)
 {
   CoglPipelineLayerState change = COGL_PIPELINE_LAYER_STATE_FRAGMENT_SNIPPETS;
   CoglPipelineLayer *layer, *authority;
 
-  _COGL_RETURN_IF_FAIL (cogl_is_pipeline (pipeline));
-
   /* Note: this will ensure that the layer exists, creating one if it
    * doesn't already.
    *
@@ -800,7 +798,6 @@ _cogl_pipeline_layer_add_fragment_snippet (CoglPipeline *pipeline,
   layer = _cogl_pipeline_layer_pre_change_notify (pipeline, layer, change);
 
   _cogl_pipeline_snippet_list_add (&layer->big_state->fragment_snippets,
-                                   hook,
                                    snippet);
 
   /* If we weren't previously the authority on this state then we need
@@ -815,15 +812,21 @@ _cogl_pipeline_layer_add_fragment_snippet (CoglPipeline *pipeline,
 }
 
 void
-cogl_pipeline_add_texture_lookup_hook (CoglPipeline *pipeline,
-                                       int layer_index,
-                                       CoglSnippet *snippet)
+cogl_pipeline_add_layer_snippet (CoglPipeline *pipeline,
+                                 int layer_index,
+                                 CoglSnippet *snippet)
 {
-  CoglPipelineSnippetHook hook = COGL_PIPELINE_SNIPPET_HOOK_TEXTURE_LOOKUP;
-  _cogl_pipeline_layer_add_fragment_snippet (pipeline,
-                                             layer_index,
-                                             hook,
-                                             snippet);
+  _COGL_RETURN_IF_FAIL (cogl_is_pipeline (pipeline));
+  _COGL_RETURN_IF_FAIL (cogl_is_snippet (snippet));
+  _COGL_RETURN_IF_FAIL (snippet->hook >= COGL_SNIPPET_FIRST_LAYER_HOOK);
+
+  if (snippet->hook < COGL_SNIPPET_FIRST_LAYER_FRAGMENT_HOOK)
+    /* TODO */
+    g_assert_not_reached ();
+  else
+    _cogl_pipeline_layer_add_fragment_snippet (pipeline,
+                                               layer_index,
+                                               snippet);
 }
 
 gboolean
diff --git a/cogl/cogl-pipeline-layer-state.h b/cogl/cogl-pipeline-layer-state.h
index c44f1d9..a4ad16b 100644
--- a/cogl/cogl-pipeline-layer-state.h
+++ b/cogl/cogl-pipeline-layer-state.h
@@ -497,46 +497,26 @@ cogl_pipeline_set_layer_wrap_mode (CoglPipeline        *pipeline,
                                    int                  layer_index,
                                    CoglPipelineWrapMode mode);
 
+#define cogl_pipeline_add_layer_snippet cogl_pipeline_add_layer_snippet_EXP
 /**
- * cogl_pipeline_add_texture_lookup_hook:
+ * cogl_pipeline_add_layer_snippet:
  * @pipeline: A #CoglPipeline
- * @layer: The layer whose texutre lookup should be hooked
- * @snippet: The #CoglSnippet to add to the texture lookup for @layer
+ * @layer: The layer to hook the snippet to
+ * @snippet: A #CoglSnippet
  *
- * Adds a shader snippet that will hook on to the texture lookup part
- * of a given layer. This gives a chance for the application to modify
- * the coordinates that will be used for the texture lookup or to
- * alter the returned texel.
- *
- * Within the snippet code for this hook there are two extra variables
- * available. âcogl_tex_coordâ is a vec4 which contains the texture
- * coordinates that will be used for the texture lookup this can be
- * modified. âcogl_texelâ will contain the result of the texture
- * lookup. This can be modified.
- *
- * The âdeclarationsâ string in @snippet will be inserted in the main
- * scope of the shader. Use this to declare any uniforms, attributes
- * or functions that the snippet requires.
- *
- * The âpreâ string in @snippet will be inserted at the top of the
- * main() function before any fragment processing is done. This is a
- * good place to modify the cogl_tex_coord variable.
- *
- * If a âreplaceâ string is given then this will be used instead of a
- * the default texture lookup. The snippet would typically use its own
- * sampler in this case.
- *
- * The âpostâ string in @snippet will be inserted after texture lookup
- * has been preformed. Here the snippet can modify the cogl_texel
- * variable to alter the returned texel.
+ * Adds a shader snippet that will hook on to the given layer of the
+ * pipeline. The exact part of the pipeline that the snippet wraps
+ * around depends on the hook that is given to
+ * cogl_snippet_new(). Note that some hooks can't be used with a layer
+ * and need to be added with cogl_pipeline_add_snippet() instead.
  *
  * Since: 1.10
  * Stability: Unstable
  */
 void
-cogl_pipeline_add_texture_lookup_hook (CoglPipeline *pipeline,
-                                       int layer_index,
-                                       CoglSnippet *snippet);
+cogl_pipeline_add_layer_snippet (CoglPipeline *pipeline,
+                                 int layer,
+                                 CoglSnippet *snippet);
 
 #endif /* COGL_ENABLE_EXPERIMENTAL_API */
 
diff --git a/cogl/cogl-pipeline-snippet-private.h b/cogl/cogl-pipeline-snippet-private.h
index 0df4972..24ff610 100644
--- a/cogl/cogl-pipeline-snippet-private.h
+++ b/cogl/cogl-pipeline-snippet-private.h
@@ -31,15 +31,6 @@
 #include "cogl-snippet.h"
 #include "cogl-queue.h"
 
-/* Enumeration of all the hook points that a snippet can be attached
-   to within a pipeline. */
-typedef enum
-{
-  COGL_PIPELINE_SNIPPET_HOOK_VERTEX,
-  COGL_PIPELINE_SNIPPET_HOOK_FRAGMENT,
-  COGL_PIPELINE_SNIPPET_HOOK_TEXTURE_LOOKUP
-} CoglPipelineSnippetHook;
-
 typedef struct _CoglPipelineSnippet CoglPipelineSnippet;
 
 COGL_LIST_HEAD (CoglPipelineSnippetList, CoglPipelineSnippet);
@@ -48,9 +39,6 @@ struct _CoglPipelineSnippet
 {
   COGL_LIST_ENTRY (CoglPipelineSnippet) list_node;
 
-  /* Hook where this snippet is attached */
-  CoglPipelineSnippetHook hook;
-
   CoglSnippet *snippet;
 };
 
@@ -60,7 +48,7 @@ typedef struct
   CoglPipelineSnippetList *snippets;
 
   /* Only snippets at this hook point will be used */
-  CoglPipelineSnippetHook hook;
+  CoglSnippetHook hook;
 
   /* The final function to chain on to after all of the snippets code
      has been run */
@@ -98,7 +86,6 @@ _cogl_pipeline_snippet_list_free (CoglPipelineSnippetList *list);
 
 void
 _cogl_pipeline_snippet_list_add (CoglPipelineSnippetList *list,
-                                 CoglPipelineSnippetHook hook,
                                  CoglSnippet *snippet);
 
 void
diff --git a/cogl/cogl-pipeline-snippet.c b/cogl/cogl-pipeline-snippet.c
index bb57abd..794e163 100644
--- a/cogl/cogl-pipeline-snippet.c
+++ b/cogl/cogl-pipeline-snippet.c
@@ -44,7 +44,7 @@ _cogl_pipeline_snippet_generate_code (const CoglPipelineSnippetData *data)
   int snippet_num = 0;
 
   COGL_LIST_FOREACH (snippet, data->snippets, list_node)
-    if (snippet->hook == data->hook)
+    if (snippet->snippet->hook == data->hook)
       {
         const char *source;
 
@@ -179,12 +179,10 @@ _cogl_pipeline_snippet_list_free (CoglPipelineSnippetList *list)
 
 void
 _cogl_pipeline_snippet_list_add (CoglPipelineSnippetList *list,
-                                 CoglPipelineSnippetHook hook,
                                  CoglSnippet *snippet)
 {
   CoglPipelineSnippet *pipeline_snippet = g_slice_new (CoglPipelineSnippet);
 
-  pipeline_snippet->hook = hook;
   pipeline_snippet->snippet = cogl_object_ref (snippet);
 
   _cogl_snippet_make_immutable (pipeline_snippet->snippet);
@@ -236,9 +234,6 @@ _cogl_pipeline_snippet_list_hash (CoglPipelineSnippetList *list,
   COGL_LIST_FOREACH (l, list, list_node)
     {
       *hash = _cogl_util_one_at_a_time_hash (*hash,
-                                             &l->hook,
-                                             sizeof (CoglPipelineSnippetHook));
-      *hash = _cogl_util_one_at_a_time_hash (*hash,
                                              &l->snippet,
                                              sizeof (CoglSnippet *));
     }
@@ -253,7 +248,7 @@ _cogl_pipeline_snippet_list_equal (CoglPipelineSnippetList *list0,
   for (l0 = COGL_LIST_FIRST (list0), l1 = COGL_LIST_FIRST (list1);
        l0 && l1;
        l0 = COGL_LIST_NEXT (l0, list_node), l1 = COGL_LIST_NEXT (l1, list_node))
-    if (l0->hook != l1->hook || l0->snippet != l1->snippet)
+    if (l0->snippet != l1->snippet)
       return FALSE;
 
   return l0 == NULL && l1 == NULL;
diff --git a/cogl/cogl-pipeline-state.c b/cogl/cogl-pipeline-state.c
index 3477820..44384ed 100644
--- a/cogl/cogl-pipeline-state.c
+++ b/cogl/cogl-pipeline-state.c
@@ -1571,14 +1571,10 @@ cogl_pipeline_set_uniform_matrix (CoglPipeline *pipeline,
 
 static void
 _cogl_pipeline_add_vertex_snippet (CoglPipeline *pipeline,
-                                   CoglPipelineSnippetHook hook,
                                    CoglSnippet *snippet)
 {
   CoglPipelineState state = COGL_PIPELINE_STATE_VERTEX_SNIPPETS;
 
-  g_return_if_fail (cogl_is_pipeline (pipeline));
-  g_return_if_fail (cogl_is_snippet (snippet));
-
   /* - Flush journal primitives referencing the current state.
    * - Make sure the pipeline has no dependants so it may be modified.
    * - If the pipeline isn't currently an authority for the state being
@@ -1587,29 +1583,15 @@ _cogl_pipeline_add_vertex_snippet (CoglPipeline *pipeline,
   _cogl_pipeline_pre_change_notify (pipeline, state, NULL, FALSE);
 
   _cogl_pipeline_snippet_list_add (&pipeline->big_state->vertex_snippets,
-                                   hook,
                                    snippet);
 }
 
-void
-cogl_pipeline_add_vertex_hook (CoglPipeline *pipeline,
-                               CoglSnippet *snippet)
-{
-  _cogl_pipeline_add_vertex_snippet (pipeline,
-                                     COGL_PIPELINE_SNIPPET_HOOK_VERTEX,
-                                     snippet);
-}
-
 static void
 _cogl_pipeline_add_fragment_snippet (CoglPipeline *pipeline,
-                                     CoglPipelineSnippetHook hook,
                                      CoglSnippet *snippet)
 {
   CoglPipelineState state = COGL_PIPELINE_STATE_FRAGMENT_SNIPPETS;
 
-  g_return_if_fail (cogl_is_pipeline (pipeline));
-  g_return_if_fail (cogl_is_snippet (snippet));
-
   /* - Flush journal primitives referencing the current state.
    * - Make sure the pipeline has no dependants so it may be modified.
    * - If the pipeline isn't currently an authority for the state being
@@ -1618,17 +1600,21 @@ _cogl_pipeline_add_fragment_snippet (CoglPipeline *pipeline,
   _cogl_pipeline_pre_change_notify (pipeline, state, NULL, FALSE);
 
   _cogl_pipeline_snippet_list_add (&pipeline->big_state->fragment_snippets,
-                                   hook,
                                    snippet);
 }
 
 void
-cogl_pipeline_add_fragment_hook (CoglPipeline *pipeline,
-                                 CoglSnippet *snippet)
+cogl_pipeline_add_snippet (CoglPipeline *pipeline,
+                           CoglSnippet *snippet)
 {
-  _cogl_pipeline_add_fragment_snippet (pipeline,
-                                       COGL_PIPELINE_SNIPPET_HOOK_FRAGMENT,
-                                       snippet);
+  g_return_if_fail (cogl_is_pipeline (pipeline));
+  g_return_if_fail (cogl_is_snippet (snippet));
+  g_return_if_fail (snippet->hook < COGL_SNIPPET_FIRST_LAYER_HOOK);
+
+  if (snippet->hook < COGL_SNIPPET_FIRST_PIPELINE_FRAGMENT_HOOK)
+    _cogl_pipeline_add_vertex_snippet (pipeline, snippet);
+  else
+    _cogl_pipeline_add_fragment_snippet (pipeline, snippet);
 }
 
 gboolean
diff --git a/cogl/cogl-pipeline-state.h b/cogl/cogl-pipeline-state.h
index 4781a9e..b3500bf 100644
--- a/cogl/cogl-pipeline-state.h
+++ b/cogl/cogl-pipeline-state.h
@@ -937,73 +937,24 @@ cogl_pipeline_set_uniform_matrix (CoglPipeline *pipeline,
                                   gboolean transpose,
                                   const float *value);
 
+#define cogl_pipeline_add_snippet cogl_pipeline_add_snippet_EXP
 /**
- * cogl_pipeline_add_vertex_hook:
+ * cogl_pipeline_add_snippet:
  * @pipeline: A #CoglPipeline
  * @snippet: The #CoglSnippet to add to the vertex processing hook
  *
- * Adds a shader snippet that will hook on to the vertex processing
- * stage of @pipeline. This gives a chance for the application to
- * modify the vertex attributes generated by the shader. Typically the
- * snippet will modify cogl_color_out or cogl_position_out builtins.
- *
- * The âdeclarationsâ string in @snippet will be inserted in the main
- * scope of the shader. Use this to declare any uniforms, attributes
- * or functions that the snippet requires.
- *
- * The âpreâ string in @snippet will be inserted at the top of the
- * main() function before any vertex processing is done.
- *
- * The âreplaceâ string in @snippet will be used instead of the
- * generated vertex processing if it is present. This can be used if
- * the application wants to provide a complete vertex shader and
- * doesn't need the generated output from Cogl.
- *
- * The âpostâ string in @snippet will be inserted after all of the
- * standard vertex processing is done. This can be used to modify the
- * outputs.
- *
- * Since: 1.10
- * Stability: Unstable
- */
-void
-cogl_pipeline_add_vertex_hook (CoglPipeline *pipeline,
-                               CoglSnippet *snippet);
-
-/**
- * cogl_pipeline_add_fragment_hook:
- * @pipeline: A #CoglPipeline
- * @snippet: The #CoglSnippet to add to the fragment processing hook
- *
- * Adds a shader snippet that will hook on to the fragment processing
- * stage of @pipeline. This gives a chance for the application to
- * modify the fragment color generated by the shader. Typically the
- * snippet will modify cogl_color_out.
- *
- * The âdeclarationsâ string in @snippet will be inserted in the main
- * scope of the shader. Use this to declare any uniforms, attributes
- * or functions that the snippet requires.
- *
- * The âpreâ string in @snippet will be inserted at the top of the
- * main() function before any fragment processing is done.
- *
- * The âreplaceâ string in @snippet will be used instead of the
- * generated fragment processing if it is present. This can be used if
- * the application wants to provide a complete fragment shader and
- * doesn't need the generated output from Cogl.
- *
- * The âpostâ string in @snippet will be inserted after all of the
- * standard fragment processing is done. At this point the generated
- * value for the rest of the pipeline state will already be in
- * cogl_color_out so the application can modify the result by altering
- * this variable.
+ * Adds a shader snippet that to @pipeline. The snippet will wrap
+ * around or replace some part of the pipeline as defined by the hook
+ * point in @snippet. Note that some hook points are specific to a
+ * layer and must be added with cogl_pipeline_add_layer_snippet()
+ * instead.
  *
  * Since: 1.10
  * Stability: Unstable
  */
 void
-cogl_pipeline_add_fragment_hook (CoglPipeline *pipeline,
-                                 CoglSnippet *snippet);
+cogl_pipeline_add_snippet (CoglPipeline *pipeline,
+                           CoglSnippet *snippet);
 
 #endif /* COGL_ENABLE_EXPERIMENTAL_API */
 
diff --git a/cogl/cogl-pipeline-vertend-glsl.c b/cogl/cogl-pipeline-vertend-glsl.c
index 64b4737..a6f04ca 100644
--- a/cogl/cogl-pipeline-vertend-glsl.c
+++ b/cogl/cogl-pipeline-vertend-glsl.c
@@ -381,7 +381,7 @@ _cogl_pipeline_vertend_glsl_end (CoglPipeline *pipeline,
       /* Add all of the hooks for vertex processing */
       memset (&snippet_data, 0, sizeof (snippet_data));
       snippet_data.snippets = get_vertex_snippets (pipeline);
-      snippet_data.hook = COGL_PIPELINE_SNIPPET_HOOK_VERTEX;
+      snippet_data.hook = COGL_SNIPPET_HOOK_VERTEX;
       snippet_data.chain_function = "cogl_generated_source";
       snippet_data.final_name = "main";
       snippet_data.function_prefix = "cogl_vertex_hook";
diff --git a/cogl/cogl-snippet-private.h b/cogl/cogl-snippet-private.h
index bcc6abe..519738b 100644
--- a/cogl/cogl-snippet-private.h
+++ b/cogl/cogl-snippet-private.h
@@ -33,10 +33,26 @@
 #include "cogl-snippet.h"
 #include "cogl-object-private.h"
 
+/* These values are also used in the enum for CoglSnippetHook. They
+   are copied here because we don't really want these names to be part
+   of the public API */
+#define COGL_SNIPPET_HOOK_BAND_SIZE 2048
+#define COGL_SNIPPET_FIRST_PIPELINE_HOOK 0
+#define COGL_SNIPPET_FIRST_PIPELINE_VERTEX_HOOK \
+  COGL_SNIPPET_FIRST_PIPELINE_HOOK
+#define COGL_SNIPPET_FIRST_PIPELINE_FRAGMENT_HOOK \
+  (COGL_SNIPPET_FIRST_PIPELINE_VERTEX_HOOK + COGL_SNIPPET_HOOK_BAND_SIZE)
+#define COGL_SNIPPET_FIRST_LAYER_HOOK (COGL_SNIPPET_HOOK_BAND_SIZE * 2)
+#define COGL_SNIPPET_FIRST_LAYER_VERTEX_HOOK COGL_SNIPPET_FIRST_LAYER_HOOK
+#define COGL_SNIPPET_FIRST_LAYER_FRAGMENT_HOOK \
+  (COGL_SNIPPET_FIRST_LAYER_VERTEX_HOOK + COGL_SNIPPET_HOOK_BAND_SIZE)
+
 struct _CoglSnippet
 {
   CoglObject _parent;
 
+  CoglSnippetHook hook;
+
   /* This is set to TRUE the first time the snippet is attached to the
      pipeline. After that any attempts to modify the snippet will be
      ignored. */
diff --git a/cogl/cogl-snippet.c b/cogl/cogl-snippet.c
index d3a066f..0af6473 100644
--- a/cogl/cogl-snippet.c
+++ b/cogl/cogl-snippet.c
@@ -38,19 +38,30 @@ _cogl_snippet_free (CoglSnippet *snippet);
 COGL_OBJECT_DEFINE (Snippet, snippet);
 
 CoglSnippet *
-cogl_snippet_new (const char *declarations,
+cogl_snippet_new (CoglSnippetHook hook,
+                  const char *declarations,
                   const char *post)
 {
   CoglSnippet *snippet = g_slice_new0 (CoglSnippet);
 
   _cogl_snippet_object_new (snippet);
 
+  snippet->hook = hook;
+
   cogl_snippet_set_declarations (snippet, declarations);
   cogl_snippet_set_post (snippet, post);
 
   return snippet;
 }
 
+CoglSnippetHook
+cogl_snippet_get_hook (CoglSnippet *snippet)
+{
+  _COGL_RETURN_VAL_IF_FAIL (cogl_is_snippet (snippet), 0);
+
+  return snippet->hook;
+}
+
 static gboolean
 _cogl_snippet_modify (CoglSnippet *snippet)
 {
diff --git a/cogl/cogl-snippet.h b/cogl/cogl-snippet.h
index 260aed9..d966f17 100644
--- a/cogl/cogl-snippet.h
+++ b/cogl/cogl-snippet.h
@@ -46,9 +46,146 @@ typedef struct _CoglSnippet CoglSnippet;
 
 #define COGL_SNIPPET(OBJECT) ((CoglSnippet *)OBJECT)
 
+/* Enumeration of all the hook points that a snippet can be attached
+   to within a pipeline. */
+/**
+ * CoglSnippetHook:
+ * @COGL_SNIPPET_HOOK_VERTEX: A hook for the entire vertex processing
+ *   stage of the pipeline.
+ * @COGL_SNIPPET_HOOK_FRAGMENT: A hook for the entire fragment
+ *   processing stage of the pipeline.
+ * @COGL_SNIPPET_HOOK_TEXTURE_LOOKUP: A hook for the texture lookup
+ *   stage of a given layer in a pipeline.
+ *
+ * #CoglSnippetHook is used to specify a location within a
+ * #CoglPipeline where the code of the snippet should be used when it
+ * is attached to a pipeline.
+ *
+ * <glosslist>
+ *  <glossentry>
+ *   <glossterm>%COGL_SNIPPET_HOOK_VERTEX</glossterm>
+ *   <glossdef>
+ * <para>
+ * Adds a shader snippet that will hook on to the vertex processing
+ * stage of the pipeline. This gives a chance for the application to
+ * modify the vertex attributes generated by the shader. Typically the
+ * snippet will modify cogl_color_out or cogl_position_out builtins.
+ * </para>
+ * <para>
+ * The âdeclarationsâ string in @snippet will be inserted in the main
+ * scope of the shader. Use this to declare any uniforms, attributes
+ * or functions that the snippet requires.
+ * </para>
+ * <para>
+ * The âpreâ string in @snippet will be inserted at the top of the
+ * main() function before any vertex processing is done.
+ * </para>
+ * <para>
+ * The âreplaceâ string in @snippet will be used instead of the
+ * generated vertex processing if it is present. This can be used if
+ * the application wants to provide a complete vertex shader and
+ * doesn't need the generated output from Cogl.
+ * </para>
+ * <para>
+ * The âpostâ string in @snippet will be inserted after all of the
+ * standard vertex processing is done. This can be used to modify the
+ * outputs.
+ * </para>
+ *   </glossdef>
+ *  </glossentry>
+ *  <glossentry>
+ *   <glossterm>%COGL_SNIPPET_HOOK_FRAGMENT</glossterm>
+ *   <glossdef>
+ * <para>
+ * Adds a shader snippet that will hook on to the fragment processing
+ * stage of the pipeline. This gives a chance for the application to
+ * modify the fragment color generated by the shader. Typically the
+ * snippet will modify cogl_color_out.
+ * </para>
+ * <para>
+ * The âdeclarationsâ string in @snippet will be inserted in the main
+ * scope of the shader. Use this to declare any uniforms, attributes
+ * or functions that the snippet requires.
+ * </para>
+ * <para>
+ * The âpreâ string in @snippet will be inserted at the top of the
+ * main() function before any fragment processing is done.
+ * </para>
+ * <para>
+ * The âreplaceâ string in @snippet will be used instead of the
+ * generated fragment processing if it is present. This can be used if
+ * the application wants to provide a complete fragment shader and
+ * doesn't need the generated output from Cogl.
+ * </para>
+ * <para>
+ * The âpostâ string in @snippet will be inserted after all of the
+ * standard fragment processing is done. At this point the generated
+ * value for the rest of the pipeline state will already be in
+ * cogl_color_out so the application can modify the result by altering
+ * this variable.
+ * </para>
+ *   </glossdef>
+ *  </glossentry>
+ *  <glossentry>
+ *   <glossterm>%COGL_SNIPPET_HOOK_TEXTURE_LOOKUP</glossterm>
+ * Adds a shader snippet that will hook on to the texture lookup part
+ * of a given layer. This gives a chance for the application to modify
+ * the coordinates that will be used for the texture lookup or to
+ * alter the returned texel.
+ * </para>
+ * <para>
+ * Within the snippet code for this hook there are two extra variables
+ * available. âcogl_tex_coordâ is a vec4 which contains the texture
+ * coordinates that will be used for the texture lookup this can be
+ * modified. âcogl_texelâ will contain the result of the texture
+ * lookup. This can be modified.
+ * </para>
+ * <para>
+ * The âdeclarationsâ string in @snippet will be inserted in the main
+ * scope of the shader. Use this to declare any uniforms, attributes
+ * or functions that the snippet requires.
+ * </para>
+ * <para>
+ * The âpreâ string in @snippet will be inserted at the top of the
+ * main() function before any fragment processing is done. This is a
+ * good place to modify the cogl_tex_coord variable.
+ * </para>
+ * <para>
+ * If a âreplaceâ string is given then this will be used instead of a
+ * the default texture lookup. The snippet would typically use its own
+ * sampler in this case.
+ * </para>
+ * <para>
+ * The âpostâ string in @snippet will be inserted after texture lookup
+ * has been preformed. Here the snippet can modify the cogl_texel
+ * variable to alter the returned texel.
+ * </para>
+ *  </glossentry>
+ * </glosslist>
+ *
+ * Since: 1.10
+ * Stability: Unstable
+ */
+typedef enum {
+  /* Per pipeline vertex hooks */
+  COGL_SNIPPET_HOOK_VERTEX = 0,
+
+  /* Per pipeline fragment hooks */
+  COGL_SNIPPET_HOOK_FRAGMENT = 2048,
+
+  /* Per layer vertex hooks */
+  /* TODO */
+  /* ... = 4096 */
+
+  /* Per layer fragment hooks */
+  COGL_SNIPPET_HOOK_TEXTURE_LOOKUP = 6144
+} CoglSnippetHook;
+
 #define cogl_snippet_new cogl_snippet_new_EXP
 /**
  * cogl_snippet_new:
+ * @hook: The point in the pipeline that this snippet will wrap around
+ *   or replace.
  * @declarations: The source code for the declarations for this
  *   snippet or %NULL. See cogl_snippet_set_declarations().
  * @post: The source code to run after the hook point where this
@@ -62,9 +199,21 @@ typedef struct _CoglSnippet CoglSnippet;
  * Stability: Unstable
  */
 CoglSnippet *
-cogl_snippet_new (const char *declarations,
+cogl_snippet_new (CoglSnippetHook hook,
+                  const char *declarations,
                   const char *post);
 
+#define cogl_snippet_get_hook cogl_snipet_get_hook_EXP
+/**
+ * cogl_snippet_get_hook:
+ * @snippet: A #CoglSnippet
+ *
+ * Return value: the hook that was set when cogl_snippet_new() was
+ * called.
+ */
+CoglSnippetHook
+cogl_snippet_get_hook (CoglSnippet *snippet);
+
 #define cogl_is_snippet cogl_is_snippet_EXP
 /**
  * cogl_is_snippet:
diff --git a/tests/conform/test-snippets.c b/tests/conform/test-snippets.c
index 2d96a99..b53aeca 100644
--- a/tests/conform/test-snippets.c
+++ b/tests/conform/test-snippets.c
@@ -57,8 +57,10 @@ paint (TestState *state)
 
   cogl_pipeline_set_color4ub (pipeline, 255, 0, 0, 255);
 
-  snippet = cogl_snippet_new (NULL, "cogl_color_out.g += 1.0;");
-  cogl_pipeline_add_fragment_hook (pipeline, snippet);
+  snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_FRAGMENT,
+                              NULL, /* declarations */
+                              "cogl_color_out.g += 1.0;");
+  cogl_pipeline_add_snippet (pipeline, snippet);
   cogl_object_unref (snippet);
 
   cogl_push_source (pipeline);
@@ -72,8 +74,10 @@ paint (TestState *state)
 
   cogl_pipeline_set_color4ub (pipeline, 255, 0, 0, 255);
 
-  snippet = cogl_snippet_new (NULL, "cogl_color_out.b += 1.0;");
-  cogl_pipeline_add_vertex_hook (pipeline, snippet);
+  snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_VERTEX,
+                              NULL,
+                              "cogl_color_out.b += 1.0;");
+  cogl_pipeline_add_snippet (pipeline, snippet);
   cogl_object_unref (snippet);
 
   cogl_push_source (pipeline);
@@ -82,8 +86,8 @@ paint (TestState *state)
 
   cogl_object_unref (pipeline);
 
-  /* Single snippet used with in both the vertex and fragment hooks
-     with a uniform */
+  /* Snippets sharing a uniform across the vertex and fragment
+     hooks */
   pipeline = cogl_pipeline_new ();
 
   location = cogl_pipeline_get_uniform_location (pipeline, "a_value");
@@ -91,10 +95,15 @@ paint (TestState *state)
 
   cogl_pipeline_set_color4ub (pipeline, 255, 0, 0, 255);
 
-  snippet = cogl_snippet_new ("uniform float a_value;",
+  snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_VERTEX,
+                              "uniform float a_value;",
                               "cogl_color_out.b += a_value;");
-  cogl_pipeline_add_fragment_hook (pipeline, snippet);
-  cogl_pipeline_add_vertex_hook (pipeline, snippet);
+  cogl_pipeline_add_snippet (pipeline, snippet);
+  cogl_object_unref (snippet);
+  snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_FRAGMENT,
+                              "uniform float a_value;",
+                              "cogl_color_out.b += a_value;");
+  cogl_pipeline_add_snippet (pipeline, snippet);
   cogl_object_unref (snippet);
 
   cogl_push_source (pipeline);
@@ -121,8 +130,10 @@ paint (TestState *state)
       location = cogl_pipeline_get_uniform_location (pipeline, uniform_name);
       cogl_pipeline_set_uniform_1f (pipeline, location, (i + 1) * 0.1f);
 
-      snippet = cogl_snippet_new (declarations, code);
-      cogl_pipeline_add_fragment_hook (pipeline, snippet);
+      snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_FRAGMENT,
+                                  declarations,
+                                  code);
+      cogl_pipeline_add_snippet (pipeline, snippet);
       cogl_object_unref (snippet);
 
       g_free (code);
@@ -142,10 +153,11 @@ paint (TestState *state)
 
   cogl_pipeline_set_color4ub (pipeline, 255, 255, 255, 255);
 
-  snippet = cogl_snippet_new (NULL, "cogl_color_out = redvec;");
+  snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_FRAGMENT,
+                              NULL, /* declarations */
+                              "cogl_color_out = redvec;");
   cogl_snippet_set_pre (snippet, "vec4 redvec = vec4 (1.0, 0.0, 0.0, 1.0);");
-  cogl_pipeline_add_vertex_hook (pipeline, snippet);
-  cogl_pipeline_add_fragment_hook (pipeline, snippet);
+  cogl_pipeline_add_snippet (pipeline, snippet);
   cogl_object_unref (snippet);
 
   cogl_push_source (pipeline);
@@ -159,21 +171,22 @@ paint (TestState *state)
      the conformance test but at least it should be possible to see by
      setting COGL_DEBUG=show-source to check whether this shader gets
      generated twice */
-  snippet = cogl_snippet_new ("/* This comment should only be seen ONCE\n"
+  snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_FRAGMENT,
+                              "/* This comment should only be seen ONCE\n"
                               "   when COGL_DEBUG=show-source is TRUE\n"
                               "   even though it is used in two different\n"
                               "   unrelated pipelines */",
                               "cogl_color_out = vec4 (0.0, 1.0, 0.0, 1.0);\n");
 
   pipeline = cogl_pipeline_new ();
-  cogl_pipeline_add_fragment_hook (pipeline, snippet);
+  cogl_pipeline_add_snippet (pipeline, snippet);
   cogl_push_source (pipeline);
   cogl_rectangle (50, 0, 60, 10);
   cogl_pop_source ();
   cogl_object_unref (pipeline);
 
   pipeline = cogl_pipeline_new ();
-  cogl_pipeline_add_fragment_hook (pipeline, snippet);
+  cogl_pipeline_add_snippet (pipeline, snippet);
   cogl_push_source (pipeline);
   cogl_rectangle (60, 0, 70, 10);
   cogl_pop_source ();
@@ -182,7 +195,7 @@ paint (TestState *state)
   cogl_object_unref (snippet);
 
   /* Check the replace string */
-  snippet = cogl_snippet_new (NULL, NULL);
+  snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_FRAGMENT, NULL, NULL);
   cogl_snippet_set_pre (snippet,
                         "cogl_color_out = vec4 (0.0, 0.5, 0.0, 1.0);");
   /* Remove the generated output. If the replace string isn't working
@@ -193,7 +206,7 @@ paint (TestState *state)
                          "cogl_color_out += vec4 (0.5, 0.0, 0.0, 1.0);");
 
   pipeline = cogl_pipeline_new ();
-  cogl_pipeline_add_fragment_hook (pipeline, snippet);
+  cogl_pipeline_add_snippet (pipeline, snippet);
   cogl_push_source (pipeline);
   cogl_rectangle (70, 0, 80, 10);
   cogl_pop_source ();
@@ -202,14 +215,15 @@ paint (TestState *state)
   cogl_object_unref (snippet);
 
   /* Check the texture lookup hook */
-  snippet = cogl_snippet_new (NULL,
+  snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_TEXTURE_LOOKUP,
+                              NULL,
                               "cogl_texel.b += 1.0;");
   /* Flip the texture coordinates around the y axis so that it will
      get the green texel */
   cogl_snippet_set_pre (snippet, "cogl_tex_coord.x = 1.0 - cogl_tex_coord.x;");
 
   pipeline = create_texture_pipeline ();
-  cogl_pipeline_add_texture_lookup_hook (pipeline, 0, snippet);
+  cogl_pipeline_add_layer_snippet (pipeline, 0, snippet);
   cogl_push_source (pipeline);
   cogl_rectangle_with_texture_coords (80, 0, 90, 10,
                                       0, 0, 0, 0);
@@ -219,7 +233,7 @@ paint (TestState *state)
   cogl_object_unref (snippet);
 
   /* Sanity check modifying the snippet */
-  snippet = cogl_snippet_new ("foo", "bar");
+  snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_FRAGMENT, "foo", "bar");
   g_assert_cmpstr (cogl_snippet_get_declarations (snippet), ==, "foo");
   g_assert_cmpstr (cogl_snippet_get_post (snippet), ==, "bar");
   g_assert_cmpstr (cogl_snippet_get_replace (snippet), ==, NULL);
@@ -248,6 +262,10 @@ paint (TestState *state)
   g_assert_cmpstr (cogl_snippet_get_post (snippet), ==, "ba");
   g_assert_cmpstr (cogl_snippet_get_replace (snippet), ==, "baba");
   g_assert_cmpstr (cogl_snippet_get_pre (snippet), ==, "fuba");
+
+  g_assert_cmpint (cogl_snippet_get_hook (snippet),
+                   ==,
+                   COGL_SNIPPET_HOOK_FRAGMENT);
 }
 
 static void



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