[cogl/wip/neil/snippets: 21/26] snippet: Add a hook for the layer texture coordinate transformation



commit 84e5e968157998d757eade27342e23870bd01c13
Author: Neil Roberts <neil linux intel com>
Date:   Mon Nov 28 19:58:15 2011 +0000

    snippet: Add a hook for the layer texture coordinate transformation
    
    This adds a hook called COGL_SNIPPET_HOOK_TEXTURE_COORD_TRANSFORM.
    This can be used to alter the application of the layer user matrix to
    a texture coordinate or it can bypass it altogether.
    
    This is the first per-layer hook that affects the vertex shader state
    so the patch includes the boilerplate needed to get that to work.

 cogl/cogl-pipeline-layer-private.h       |    9 ++++-
 cogl/cogl-pipeline-layer-state-private.h |    9 ++++
 cogl/cogl-pipeline-layer-state.c         |   60 +++++++++++++++++++++++++++++-
 cogl/cogl-pipeline-layer.c               |   18 +++++++++
 cogl/cogl-pipeline-snippet-private.h     |    6 +++
 cogl/cogl-pipeline-snippet.c             |    2 +-
 cogl/cogl-pipeline-state.c               |   29 ++++++++++++++-
 cogl/cogl-pipeline-vertend-glsl.c        |   51 ++++++++++++++++++++++++-
 cogl/cogl-pipeline.c                     |    5 ++-
 cogl/cogl-snippet.h                      |   45 +++++++++++++++++++++-
 tests/conform/test-snippets.c            |   46 ++++++++++++++++++++++-
 11 files changed, 268 insertions(+), 12 deletions(-)
---
diff --git a/cogl/cogl-pipeline-layer-private.h b/cogl/cogl-pipeline-layer-private.h
index e428599..0bd7034 100644
--- a/cogl/cogl-pipeline-layer-private.h
+++ b/cogl/cogl-pipeline-layer-private.h
@@ -79,6 +79,7 @@ typedef enum
   COGL_PIPELINE_LAYER_STATE_COMBINE_CONSTANT_INDEX,
   COGL_PIPELINE_LAYER_STATE_USER_MATRIX_INDEX,
   COGL_PIPELINE_LAYER_STATE_POINT_SPRITE_COORDS_INDEX,
+  COGL_PIPELINE_LAYER_STATE_VERTEX_SNIPPETS_INDEX,
   COGL_PIPELINE_LAYER_STATE_FRAGMENT_SNIPPETS_INDEX,
 
   /* note: layers don't currently have any non-sparse state */
@@ -117,6 +118,8 @@ typedef enum
   COGL_PIPELINE_LAYER_STATE_POINT_SPRITE_COORDS =
     1L<<COGL_PIPELINE_LAYER_STATE_POINT_SPRITE_COORDS_INDEX,
 
+  COGL_PIPELINE_LAYER_STATE_VERTEX_SNIPPETS =
+    1L<<COGL_PIPELINE_LAYER_STATE_VERTEX_SNIPPETS_INDEX,
   COGL_PIPELINE_LAYER_STATE_FRAGMENT_SNIPPETS =
     1L<<COGL_PIPELINE_LAYER_STATE_FRAGMENT_SNIPPETS_INDEX,
 
@@ -139,15 +142,18 @@ typedef enum
    COGL_PIPELINE_LAYER_STATE_COMBINE_CONSTANT | \
    COGL_PIPELINE_LAYER_STATE_USER_MATRIX | \
    COGL_PIPELINE_LAYER_STATE_POINT_SPRITE_COORDS | \
+   COGL_PIPELINE_LAYER_STATE_VERTEX_SNIPPETS | \
    COGL_PIPELINE_LAYER_STATE_FRAGMENT_SNIPPETS)
 
 #define COGL_PIPELINE_LAYER_STATE_MULTI_PROPERTY \
   (COGL_PIPELINE_LAYER_STATE_FILTERS | \
    COGL_PIPELINE_LAYER_STATE_WRAP_MODES | \
    COGL_PIPELINE_LAYER_STATE_COMBINE | \
+   COGL_PIPELINE_LAYER_STATE_VERTEX_SNIPPETS | \
    COGL_PIPELINE_LAYER_STATE_FRAGMENT_SNIPPETS)
 
-#define COGL_PIPELINE_LAYER_STATE_AFFECTS_VERTEX_CODEGEN 0
+#define COGL_PIPELINE_LAYER_STATE_AFFECTS_VERTEX_CODEGEN \
+  COGL_PIPELINE_LAYER_STATE_VERTEX_SNIPPETS
 
 typedef enum
 {
@@ -200,6 +206,7 @@ typedef struct
 
   gboolean point_sprite_coords;
 
+  CoglPipelineSnippetList vertex_snippets;
   CoglPipelineSnippetList fragment_snippets;
 } CoglPipelineLayerBigState;
 
diff --git a/cogl/cogl-pipeline-layer-state-private.h b/cogl/cogl-pipeline-layer-state-private.h
index a283178..52bbe0e 100644
--- a/cogl/cogl-pipeline-layer-state-private.h
+++ b/cogl/cogl-pipeline-layer-state-private.h
@@ -79,6 +79,10 @@ _cogl_pipeline_layer_point_sprite_coords_equal (CoglPipelineLayer *authority0,
                                                 CoglPipelineLayer *authority1);
 
 gboolean
+_cogl_pipeline_layer_vertex_snippets_equal (CoglPipelineLayer *authority0,
+                                            CoglPipelineLayer *authority1);
+
+gboolean
 _cogl_pipeline_layer_fragment_snippets_equal (CoglPipelineLayer *authority0,
                                               CoglPipelineLayer *authority1);
 
@@ -128,6 +132,11 @@ _cogl_pipeline_layer_hash_point_sprite_state (CoglPipelineLayer *authority,
                                               CoglPipelineHashState *state);
 
 void
+_cogl_pipeline_layer_hash_vertex_snippets_state (CoglPipelineLayer *authority,
+                                                 CoglPipelineLayer **authorities,
+                                                 CoglPipelineHashState *state);
+
+void
 _cogl_pipeline_layer_hash_fragment_snippets_state (CoglPipelineLayer *authority,
                                                    CoglPipelineLayer **authorities,
                                                    CoglPipelineHashState *state);
diff --git a/cogl/cogl-pipeline-layer-state.c b/cogl/cogl-pipeline-layer-state.c
index 1523d36..e12efb8 100644
--- a/cogl/cogl-pipeline-layer-state.c
+++ b/cogl/cogl-pipeline-layer-state.c
@@ -776,6 +776,42 @@ cogl_pipeline_get_layer_point_sprite_coords_enabled (CoglPipeline *pipeline,
 }
 
 static void
+_cogl_pipeline_layer_add_vertex_snippet (CoglPipeline *pipeline,
+                                         int layer_index,
+                                         CoglSnippet *snippet)
+{
+  CoglPipelineLayerState change = COGL_PIPELINE_LAYER_STATE_VERTEX_SNIPPETS;
+  CoglPipelineLayer *layer, *authority;
+
+  /* Note: this will ensure that the layer exists, creating one if it
+   * doesn't already.
+   *
+   * Note: If the layer already existed it's possibly owned by another
+   * pipeline. If the layer is created then it will be owned by
+   * pipeline. */
+  layer = _cogl_pipeline_get_layer (pipeline, layer_index);
+
+  /* Now find the ancestor of the layer that is the authority for the
+   * state we want to change */
+  authority = _cogl_pipeline_layer_get_authority (layer, change);
+
+  layer = _cogl_pipeline_layer_pre_change_notify (pipeline, layer, change);
+
+  _cogl_pipeline_snippet_list_add (&layer->big_state->vertex_snippets,
+                                   snippet);
+
+  /* If we weren't previously the authority on this state then we need
+   * to extended our differences mask and so it's possible that some
+   * of our ancestry will now become redundant, so we aim to reparent
+   * ourselves if that's true... */
+  if (layer != authority)
+    {
+      layer->differences |= change;
+      _cogl_pipeline_layer_prune_redundant_ancestry (layer);
+    }
+}
+
+static void
 _cogl_pipeline_layer_add_fragment_snippet (CoglPipeline *pipeline,
                                            int layer_index,
                                            CoglSnippet *snippet)
@@ -821,8 +857,9 @@ cogl_pipeline_add_layer_snippet (CoglPipeline *pipeline,
   _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 ();
+    _cogl_pipeline_layer_add_vertex_snippet (pipeline,
+                                             layer_index,
+                                             snippet);
   else
     _cogl_pipeline_layer_add_fragment_snippet (pipeline,
                                                layer_index,
@@ -967,6 +1004,16 @@ _cogl_pipeline_layer_point_sprite_coords_equal (CoglPipelineLayer *authority0,
 }
 
 gboolean
+_cogl_pipeline_layer_vertex_snippets_equal (CoglPipelineLayer *authority0,
+                                            CoglPipelineLayer *authority1)
+{
+  return _cogl_pipeline_snippet_list_equal (&authority0->big_state->
+                                            vertex_snippets,
+                                            &authority1->big_state->
+                                            vertex_snippets);
+}
+
+gboolean
 _cogl_pipeline_layer_fragment_snippets_equal (CoglPipelineLayer *authority0,
                                               CoglPipelineLayer *authority1)
 {
@@ -1730,6 +1777,15 @@ _cogl_pipeline_layer_hash_point_sprite_state (CoglPipelineLayer *authority,
 }
 
 void
+_cogl_pipeline_layer_hash_vertex_snippets_state (CoglPipelineLayer *authority,
+                                                 CoglPipelineLayer **authorities,
+                                                 CoglPipelineHashState *state)
+{
+  _cogl_pipeline_snippet_list_hash (&authority->big_state->vertex_snippets,
+                                    &state->hash);
+}
+
+void
 _cogl_pipeline_layer_hash_fragment_snippets_state (CoglPipelineLayer *authority,
                                                    CoglPipelineLayer **authorities,
                                                    CoglPipelineHashState *state)
diff --git a/cogl/cogl-pipeline-layer.c b/cogl/cogl-pipeline-layer.c
index 76d17e7..d2d799d 100644
--- a/cogl/cogl-pipeline-layer.c
+++ b/cogl/cogl-pipeline-layer.c
@@ -115,6 +115,10 @@ _cogl_pipeline_layer_has_alpha (CoglPipelineLayer *layer)
 
   /* All bets are off if the layer contains any snippets */
   snippets_authority = _cogl_pipeline_layer_get_authority
+    (layer, COGL_PIPELINE_LAYER_STATE_VERTEX_SNIPPETS);
+  if (!COGL_LIST_EMPTY (&snippets_authority->big_state->vertex_snippets))
+    return TRUE;
+  snippets_authority = _cogl_pipeline_layer_get_authority
     (layer, COGL_PIPELINE_LAYER_STATE_FRAGMENT_SNIPPETS);
   if (!COGL_LIST_EMPTY (&snippets_authority->big_state->fragment_snippets))
     return TRUE;
@@ -211,6 +215,11 @@ _cogl_pipeline_layer_init_multi_property_sparse_state (
           }
         break;
       }
+    case COGL_PIPELINE_LAYER_STATE_VERTEX_SNIPPETS:
+      _cogl_pipeline_snippet_list_copy (&layer->big_state->vertex_snippets,
+                                        &authority->big_state->
+                                        vertex_snippets);
+      break;
     case COGL_PIPELINE_LAYER_STATE_FRAGMENT_SNIPPETS:
       _cogl_pipeline_snippet_list_copy (&layer->big_state->fragment_snippets,
                                         &authority->big_state->
@@ -591,6 +600,12 @@ _cogl_pipeline_layer_equal (CoglPipelineLayer *layer0,
                           _cogl_pipeline_layer_point_sprite_coords_equal))
     return FALSE;
 
+  if (layers_difference & COGL_PIPELINE_LAYER_STATE_VERTEX_SNIPPETS &&
+      !layer_state_equal (COGL_PIPELINE_LAYER_STATE_VERTEX_SNIPPETS_INDEX,
+                          authorities0, authorities1,
+                          _cogl_pipeline_layer_vertex_snippets_equal))
+    return FALSE;
+
   if (layers_difference & COGL_PIPELINE_LAYER_STATE_FRAGMENT_SNIPPETS &&
       !layer_state_equal (COGL_PIPELINE_LAYER_STATE_FRAGMENT_SNIPPETS_INDEX,
                           authorities0, authorities1,
@@ -609,6 +624,9 @@ _cogl_pipeline_layer_free (CoglPipelineLayer *layer)
       layer->texture != NULL)
     cogl_object_unref (layer->texture);
 
+  if (layer->differences & COGL_PIPELINE_LAYER_STATE_VERTEX_SNIPPETS)
+    _cogl_pipeline_snippet_list_free (&layer->big_state->vertex_snippets);
+
   if (layer->differences & COGL_PIPELINE_LAYER_STATE_FRAGMENT_SNIPPETS)
     _cogl_pipeline_snippet_list_free (&layer->big_state->fragment_snippets);
 
diff --git a/cogl/cogl-pipeline-snippet-private.h b/cogl/cogl-pipeline-snippet-private.h
index 24ff610..823193e 100644
--- a/cogl/cogl-pipeline-snippet-private.h
+++ b/cogl/cogl-pipeline-snippet-private.h
@@ -68,6 +68,12 @@ typedef struct
      NULL */
   const char *return_variable;
 
+  /* If this is TRUE then it won't allocate a separate variable for
+     the return value. Instead it is expected that the snippet will
+     modify one of the argument variables directly and that will be
+     returned */
+  gboolean return_variable_is_argument;
+
   /* The argument names or NULL if there are none */
   const char *arguments;
 
diff --git a/cogl/cogl-pipeline-snippet.c b/cogl/cogl-pipeline-snippet.c
index 33bf223..2e37741 100644
--- a/cogl/cogl-pipeline-snippet.c
+++ b/cogl/cogl-pipeline-snippet.c
@@ -131,7 +131,7 @@ _cogl_pipeline_snippet_generate_code (const CoglPipelineSnippetData *data)
                          ")\n"
                          "{\n");
 
-        if (data->return_type)
+        if (data->return_type && !data->return_variable_is_argument)
           g_string_append_printf (data->source_buf,
                                   "  %s %s;\n"
                                   "\n",
diff --git a/cogl/cogl-pipeline-state.c b/cogl/cogl-pipeline-state.c
index 44384ed..3e010f2 100644
--- a/cogl/cogl-pipeline-state.c
+++ b/cogl/cogl-pipeline-state.c
@@ -1627,10 +1627,37 @@ _cogl_pipeline_has_non_layer_vertex_snippets (CoglPipeline *pipeline)
   return !COGL_LIST_EMPTY (&authority->big_state->vertex_snippets);
 }
 
+static gboolean
+check_layer_has_vertex_snippet (CoglPipelineLayer *layer,
+                                void *user_data)
+{
+  unsigned long state = COGL_PIPELINE_LAYER_STATE_VERTEX_SNIPPETS;
+  CoglPipelineLayer *authority =
+    _cogl_pipeline_layer_get_authority (layer, state);
+  gboolean *found_vertex_snippet = user_data;
+
+  if (!COGL_LIST_EMPTY (&authority->big_state->vertex_snippets))
+    {
+      *found_vertex_snippet = TRUE;
+      return FALSE;
+    }
+
+  return TRUE;
+}
+
 gboolean
 _cogl_pipeline_has_vertex_snippets (CoglPipeline *pipeline)
 {
-  return _cogl_pipeline_has_non_layer_vertex_snippets (pipeline);
+  gboolean found_vertex_snippet = FALSE;
+
+  if (_cogl_pipeline_has_non_layer_vertex_snippets (pipeline))
+    return TRUE;
+
+  _cogl_pipeline_foreach_layer_internal (pipeline,
+                                         check_layer_has_vertex_snippet,
+                                         &found_vertex_snippet);
+
+  return found_vertex_snippet;
 }
 
 gboolean
diff --git a/cogl/cogl-pipeline-vertend-glsl.c b/cogl/cogl-pipeline-vertend-glsl.c
index a6f04ca..da0958c 100644
--- a/cogl/cogl-pipeline-vertend-glsl.c
+++ b/cogl/cogl-pipeline-vertend-glsl.c
@@ -140,6 +140,15 @@ get_vertex_snippets (CoglPipeline *pipeline)
   return &pipeline->big_state->vertex_snippets;
 }
 
+static CoglPipelineSnippetList *
+get_layer_vertex_snippets (CoglPipelineLayer *layer)
+{
+  unsigned long state = COGL_PIPELINE_LAYER_STATE_VERTEX_SNIPPETS;
+  layer = _cogl_pipeline_layer_get_authority (layer, state);
+
+  return &layer->big_state->vertex_snippets;
+}
+
 static gboolean
 _cogl_pipeline_vertend_glsl_start (CoglPipeline *pipeline,
                                    int n_layers,
@@ -293,6 +302,7 @@ _cogl_pipeline_vertend_glsl_add_layer (CoglPipeline *pipeline,
                                        unsigned long layers_difference)
 {
   CoglPipelineShaderState *shader_state;
+  CoglPipelineSnippetData snippet_data;
   int unit_index;
 
   _COGL_GET_CONTEXT (ctx, FALSE);
@@ -338,10 +348,47 @@ _cogl_pipeline_vertend_glsl_add_layer (CoglPipeline *pipeline,
    * avoid setting them if not
    */
 
+  g_string_append_printf (shader_state->header,
+                          "vec4\n"
+                          "cogl_real_transform_layer%i (mat4 matrix, "
+                          "vec4 tex_coord)\n"
+                          "{\n"
+                          "  return matrix * tex_coord;\n"
+                          "}\n",
+                          unit_index);
+
+  /* Wrap the layer code in any snippets that have been hooked */
+  memset (&snippet_data, 0, sizeof (snippet_data));
+  snippet_data.snippets = get_layer_vertex_snippets (layer);
+  snippet_data.hook = COGL_SNIPPET_HOOK_TEXTURE_COORD_TRANSFORM;
+  snippet_data.chain_function = g_strdup_printf ("cogl_real_transform_layer%i",
+                                                 unit_index);
+  snippet_data.final_name = g_strdup_printf ("cogl_transform_layer%i",
+                                             unit_index);
+  snippet_data.function_prefix = g_strdup_printf ("cogl_transform_layer%i",
+                                                  unit_index);
+  snippet_data.return_type = "vec4";
+  snippet_data.return_variable = "cogl_tex_coord";
+  snippet_data.return_variable_is_argument = TRUE;
+  snippet_data.arguments = "cogl_matrix, cogl_tex_coord";
+  snippet_data.argument_declarations = "mat4 cogl_matrix, vec4 cogl_tex_coord";
+  snippet_data.source_buf = shader_state->header;
+
+  _cogl_pipeline_snippet_generate_code (&snippet_data);
+
+  g_free ((char *) snippet_data.chain_function);
+  g_free ((char *) snippet_data.final_name);
+  g_free ((char *) snippet_data.function_prefix);
+
   g_string_append_printf (shader_state->source,
                           "  cogl_tex_coord_out[%i] = "
-                          "cogl_texture_matrix[%i] * cogl_tex_coord%i_in;\n",
-                          unit_index, unit_index, unit_index);
+                          "cogl_transform_layer%i (cogl_texture_matrix[%i],\n"
+                          "                           "
+                          "                        cogl_tex_coord%i_in);\n",
+                          unit_index,
+                          unit_index,
+                          unit_index,
+                          unit_index);
 
   return TRUE;
 }
diff --git a/cogl/cogl-pipeline.c b/cogl/cogl-pipeline.c
index 026c9c6..7277782 100644
--- a/cogl/cogl-pipeline.c
+++ b/cogl/cogl-pipeline.c
@@ -2614,12 +2614,15 @@ _cogl_pipeline_init_layer_state_hash_functions (void)
   _index = COGL_PIPELINE_LAYER_STATE_POINT_SPRITE_COORDS_INDEX;
   layer_state_hash_functions[_index] =
     _cogl_pipeline_layer_hash_point_sprite_state;
+  _index = COGL_PIPELINE_LAYER_STATE_VERTEX_SNIPPETS_INDEX;
+  layer_state_hash_functions[_index] =
+    _cogl_pipeline_layer_hash_point_sprite_state;
   _index = COGL_PIPELINE_LAYER_STATE_FRAGMENT_SNIPPETS_INDEX;
   layer_state_hash_functions[_index] =
     _cogl_pipeline_layer_hash_fragment_snippets_state;
 
   /* So we get a big error if we forget to update this code! */
-  g_assert (COGL_PIPELINE_LAYER_STATE_SPARSE_COUNT == 10);
+  g_assert (COGL_PIPELINE_LAYER_STATE_SPARSE_COUNT == 11);
 }
 
 static gboolean
diff --git a/cogl/cogl-snippet.h b/cogl/cogl-snippet.h
index 799ab80..c30c5cf 100644
--- a/cogl/cogl-snippet.h
+++ b/cogl/cogl-snippet.h
@@ -54,6 +54,8 @@ typedef struct _CoglSnippet CoglSnippet;
  *   stage of the pipeline.
  * @COGL_SNIPPET_HOOK_FRAGMENT: A hook for the entire fragment
  *   processing stage of the pipeline.
+ * @COGL_SNIPPET_HOOK_TEXTURE_COORD_TRANSFORM: A hook for applying the
+ *   layer matrix to a texture coordinate for a layer.
  * @COGL_SNIPPET_HOOK_LAYER_FRAGMENT: A hook for the fragment
  *   processing of a particular layer.
  * @COGL_SNIPPET_HOOK_TEXTURE_LOOKUP: A hook for the texture lookup
@@ -129,6 +131,46 @@ typedef struct _CoglSnippet CoglSnippet;
  *   </glossdef>
  *  </glossentry>
  *  <glossentry>
+ *   <glossterm>%COGL_SNIPPET_HOOK_TEXTURE_COORD_TRANSFORM</glossterm>
+ * Adds a shader snippet that will hook on to the texture coordinate
+ * transformation of a particular layer. This can be used to replace
+ * the processing for a layer or to modify the results.
+ * </para>
+ * <para>
+ * Within the snippet code for this hook there are two extra
+ * variables. The first is a mat4 called cogl_matrix which represents
+ * the user matrix for this layer. The second is called cogl_tex_coord
+ * and represents the incoming and outgoing texture coordinate. On
+ * entry to the hook, cogl_tex_coord contains the value of the
+ * corresponding texture coordinate attribute for this layer. The hook
+ * is expected to modify this variable. The output will be passed as a
+ * varying to the fragment processing stage. The default code will
+ * just multiply cogl_matrix by cogl_tex_coord and store the result in
+ * cogl_tex_coord.
+ * </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 just before the
+ * fragment processing for this layer. At this point cogl_tex_coord
+ * still contains the value of the texture coordinate attribute.
+ * </para>
+ * <para>
+ * If a âreplaceâ string is given then this will be used instead of
+ * the default fragment processing for this layer. The snippet can
+ * modify cogl_tex_coord or leave it as is to apply no transformation.
+ * </para>
+ * <para>
+ * The âpostâ string in @snippet will be inserted just after the
+ * transformation. At this point cogl_tex_coord will contain the
+ * results of the transformation but it can be further modified by the
+ * snippet.
+ * </para>
+ *  </glossentry>
+ *  <glossentry>
  *   <glossterm>%COGL_SNIPPET_HOOK_LAYER_FRAGMENT</glossterm>
  * Adds a shader snippet that will hook on to the fragment processing
  * of a particular layer. This can be used to replace the processing
@@ -209,8 +251,7 @@ typedef enum {
   COGL_SNIPPET_HOOK_FRAGMENT = 2048,
 
   /* Per layer vertex hooks */
-  /* TODO */
-  /* ... = 4096 */
+  COGL_SNIPPET_HOOK_TEXTURE_COORD_TRANSFORM = 4096,
 
   /* Per layer fragment hooks */
   COGL_SNIPPET_HOOK_LAYER_FRAGMENT = 6144,
diff --git a/tests/conform/test-snippets.c b/tests/conform/test-snippets.c
index 5533f2e..148d3f0 100644
--- a/tests/conform/test-snippets.c
+++ b/tests/conform/test-snippets.c
@@ -45,6 +45,7 @@ paint (TestState *state)
 {
   CoglPipeline *pipeline;
   CoglSnippet *snippet;
+  CoglMatrix matrix;
   CoglColor color;
   int location;
   int i;
@@ -268,7 +269,7 @@ paint (TestState *state)
   cogl_pop_source ();
   cogl_object_unref (pipeline);
 
-  /* Test replacing the layer code */
+  /* Test replacing the fragment layer code */
   pipeline = create_texture_pipeline ();
 
   snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_LAYER_FRAGMENT, NULL, NULL);
@@ -291,7 +292,7 @@ paint (TestState *state)
   cogl_pop_source ();
   cogl_object_unref (pipeline);
 
-  /* Test modifying the layer code */
+  /* Test modifying the fragment layer code */
   pipeline = cogl_pipeline_new ();
 
   cogl_pipeline_set_uniform_1f (pipeline,
@@ -311,6 +312,45 @@ paint (TestState *state)
   cogl_pop_source ();
   cogl_object_unref (pipeline);
 
+  /* Test modifying the vertex layer code */
+  pipeline = create_texture_pipeline ();
+
+  cogl_matrix_init_identity (&matrix);
+  cogl_matrix_translate (&matrix, 0.0f, 1.0f, 0.0f);
+  cogl_pipeline_set_layer_matrix (pipeline, 0, &matrix);
+
+  snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_TEXTURE_COORD_TRANSFORM,
+                              NULL,
+                              "cogl_tex_coord.x = 1.0;");
+  cogl_pipeline_add_layer_snippet (pipeline, 0, snippet);
+  cogl_object_unref (snippet);
+
+  cogl_push_source (pipeline);
+  cogl_rectangle_with_texture_coords (130, 0, 140, 10,
+                                      0, 0, 0, 0);
+  cogl_pop_source ();
+  cogl_object_unref (pipeline);
+
+  /* Test replacing the vertex layer code */
+  pipeline = create_texture_pipeline ();
+
+  cogl_matrix_init_identity (&matrix);
+  cogl_matrix_translate (&matrix, 0.0f, 1.0f, 0.0f);
+  cogl_pipeline_set_layer_matrix (pipeline, 0, &matrix);
+
+  snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_TEXTURE_COORD_TRANSFORM,
+                              NULL,
+                              NULL);
+  cogl_snippet_set_replace (snippet, "cogl_tex_coord.x = 1.0;\n");
+  cogl_pipeline_add_layer_snippet (pipeline, 0, snippet);
+  cogl_object_unref (snippet);
+
+  cogl_push_source (pipeline);
+  cogl_rectangle_with_texture_coords (140, 0, 150, 10,
+                                      0, 0, 0, 0);
+  cogl_pop_source ();
+  cogl_object_unref (pipeline);
+
   /* Sanity check modifying the snippet */
   snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_FRAGMENT, "foo", "bar");
   g_assert_cmpstr (cogl_snippet_get_declarations (snippet), ==, "foo");
@@ -363,6 +403,8 @@ validate_result (void)
   test_utils_check_pixel (105, 5, 0xff0000ff);
   test_utils_check_pixel (115, 5, 0xff00ffff);
   test_utils_check_pixel (125, 5, 0xff80ffff);
+  test_utils_check_pixel (135, 5, 0xffff00ff);
+  test_utils_check_pixel (145, 5, 0x00ff00ff);
 }
 
 void



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