[cogl] Add fragment and vertex snippet hooks for global declarations



commit ebb82d5b0bc30487b7101dc66b769160b40f92ca
Author: Neil Roberts <neil linux intel com>
Date:   Tue Feb 26 17:52:20 2013 +0000

    Add fragment and vertex snippet hooks for global declarations
    
    This adds hook points to add global function and variable declarations
    to either the fragment or vertex shader. The declarations can then be
    used by subsequent snippets. Only the ‘declarations’ string of the
    snippet is used and the code is directly put in the global scope near
    the top of the shader.
    
    The reason this is necessary rather than just adding a normal snippet
    with the declarations is that for the other hooks Cogl assumes that
    the snippets are independent of each other. That means if a snippet
    has a replace string then it will assume that it doesn't even need to
    generate the code for earlier hooks which means the global
    declarations would be lost.
    
    Reviewed-by: Robert Bragg <robert linux intel com>

 cogl/cogl-pipeline-snippet-private.h        |    7 ++-
 cogl/cogl-pipeline-snippet.c                |   19 ++++-
 cogl/cogl-snippet.h                         |   34 ++++++++-
 cogl/driver/gl/cogl-pipeline-fragend-glsl.c |   19 ++++-
 cogl/driver/gl/cogl-pipeline-vertend-glsl.c |   19 ++++-
 tests/conform/test-snippets.c               |  114 ++++++++++++++++++++++++++-
 6 files changed, 204 insertions(+), 8 deletions(-)
---
diff --git a/cogl/cogl-pipeline-snippet-private.h b/cogl/cogl-pipeline-snippet-private.h
index b10b6ca..02dee35 100644
--- a/cogl/cogl-pipeline-snippet-private.h
+++ b/cogl/cogl-pipeline-snippet-private.h
@@ -3,7 +3,7 @@
  *
  * An object oriented GL/GLES Abstraction/Utility Layer
  *
- * Copyright (C) 2011 Intel Corporation.
+ * Copyright (C) 2011, 2013 Intel Corporation.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -90,6 +90,11 @@ void
 _cogl_pipeline_snippet_generate_code (const CoglPipelineSnippetData *data);
 
 void
+_cogl_pipeline_snippet_generate_declarations (GString *declarations_buf,
+                                              CoglSnippetHook hook,
+                                              CoglPipelineSnippetList *list);
+
+void
 _cogl_pipeline_snippet_list_free (CoglPipelineSnippetList *list);
 
 void
diff --git a/cogl/cogl-pipeline-snippet.c b/cogl/cogl-pipeline-snippet.c
index 2d5e4c2..0e0f620 100644
--- a/cogl/cogl-pipeline-snippet.c
+++ b/cogl/cogl-pipeline-snippet.c
@@ -3,7 +3,7 @@
  *
  * An object oriented GL/GLES Abstraction/Utility Layer
  *
- * Copyright (C) 2011 Intel Corporation.
+ * Copyright (C) 2011, 2013 Intel Corporation.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -183,6 +183,23 @@ _cogl_pipeline_snippet_generate_code (const CoglPipelineSnippetData *data)
       }
 }
 
+void
+_cogl_pipeline_snippet_generate_declarations (GString *declarations_buf,
+                                              CoglSnippetHook hook,
+                                              CoglPipelineSnippetList *snippets)
+{
+  CoglPipelineSnippet *snippet;
+
+  COGL_LIST_FOREACH (snippet, snippets, list_node)
+    if (snippet->snippet->hook == hook)
+      {
+        const char *source;
+
+        if ((source = cogl_snippet_get_declarations (snippet->snippet)))
+          g_string_append (declarations_buf, source);
+      }
+}
+
 static void
 _cogl_pipeline_snippet_free (CoglPipelineSnippet *pipeline_snippet)
 {
diff --git a/cogl/cogl-snippet.h b/cogl/cogl-snippet.h
index fcf9af2..d6de2a4 100644
--- a/cogl/cogl-snippet.h
+++ b/cogl/cogl-snippet.h
@@ -3,7 +3,7 @@
  *
  * An object oriented GL/GLES Abstraction/Utility Layer
  *
- * Copyright (C) 2011 Intel Corporation.
+ * Copyright (C) 2011, 2013 Intel Corporation.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -302,6 +302,12 @@ typedef struct _CoglSnippet CoglSnippet;
    to within a pipeline. */
 /**
  * CoglSnippetHook:
+ * @COGL_SNIPPET_HOOK_VERTEX_GLOBALS: A hook for declaring global data
+ *   that can be shared with all other snippets that are on a vertex
+ *   hook.
+ * @COGL_SNIPPET_HOOK_FRAGMENT_GLOBALS: A hook for declaring global
+ *   data wthat can be shared with all other snippets that are on a
+ *   fragment hook.
  * @COGL_SNIPPET_HOOK_VERTEX: A hook for the entire vertex processing
  *   stage of the pipeline.
  * @COGL_SNIPPET_HOOK_VERTEX_TRANSFORM: A hook for the vertex transformation.
@@ -320,6 +326,30 @@ typedef struct _CoglSnippet CoglSnippet;
  *
  * <glosslist>
  *  <glossentry>
+ *   <glossterm>%COGL_SNIPPET_HOOK_VERTEX_GLOBALS</glossterm>
+ *   <glossdef>
+ * <para>
+ * Adds a shader snippet at the beginning of the global section of the
+ * shader for the vertex processing. Any declarations here can be
+ * shared with all other snippets that are attached to a vertex hook.
+ * Only the ‘declarations’ string is used and the other strings are
+ * ignored.
+ * </para>
+ *   </glossdef>
+ *  </glossentry>
+ *  <glossentry>
+ *   <glossterm>%COGL_SNIPPET_HOOK_FRAGMENT_GLOBALS</glossterm>
+ *   <glossdef>
+ * <para>
+ * Adds a shader snippet at the beginning of the global section of the
+ * shader for the fragment processing. Any declarations here can be
+ * shared with all other snippets that are attached to a fragment
+ * hook. Only the ‘declarations’ string is used and the other strings
+ * are ignored.
+ * </para>
+ *   </glossdef>
+ *  </glossentry>
+ *  <glossentry>
  *   <glossterm>%COGL_SNIPPET_HOOK_VERTEX</glossterm>
  *   <glossdef>
  * <para>
@@ -539,9 +569,11 @@ typedef enum {
   /* Per pipeline vertex hooks */
   COGL_SNIPPET_HOOK_VERTEX = 0,
   COGL_SNIPPET_HOOK_VERTEX_TRANSFORM,
+  COGL_SNIPPET_HOOK_VERTEX_GLOBALS,
 
   /* Per pipeline fragment hooks */
   COGL_SNIPPET_HOOK_FRAGMENT = 2048,
+  COGL_SNIPPET_HOOK_FRAGMENT_GLOBALS,
 
   /* Per layer vertex hooks */
   COGL_SNIPPET_HOOK_TEXTURE_COORD_TRANSFORM = 4096,
diff --git a/cogl/driver/gl/cogl-pipeline-fragend-glsl.c b/cogl/driver/gl/cogl-pipeline-fragend-glsl.c
index 6ea64c6..85bc8d3 100644
--- a/cogl/driver/gl/cogl-pipeline-fragend-glsl.c
+++ b/cogl/driver/gl/cogl-pipeline-fragend-glsl.c
@@ -3,7 +3,7 @@
  *
  * An object oriented GL/GLES Abstraction/Utility Layer
  *
- * Copyright (C) 2008,2009,2010 Intel Corporation.
+ * Copyright (C) 2008,2009,2010,2013 Intel Corporation.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -205,6 +205,21 @@ has_replace_hook (CoglPipelineLayer *layer,
 }
 
 static void
+add_global_declarations (CoglPipeline *pipeline,
+                         CoglPipelineShaderState *shader_state)
+{
+  CoglSnippetHook hook = COGL_SNIPPET_HOOK_FRAGMENT_GLOBALS;
+  CoglPipelineSnippetList *snippets = get_fragment_snippets (pipeline);
+
+  /* Add the global data hooks. All of the code in these snippets is
+   * always added and only the declarations data is used */
+
+  _cogl_pipeline_snippet_generate_declarations (shader_state->header,
+                                                hook,
+                                                snippets);
+}
+
+static void
 _cogl_pipeline_fragend_glsl_start (CoglPipeline *pipeline,
                                    int n_layers,
                                    unsigned long pipelines_difference)
@@ -296,6 +311,8 @@ _cogl_pipeline_fragend_glsl_start (CoglPipeline *pipeline,
   shader_state->source = ctx->codegen_source_buffer;
   COGL_LIST_INIT (&shader_state->layers);
 
+  add_global_declarations (pipeline, shader_state);
+
   g_string_append (shader_state->source,
                    "void\n"
                    "cogl_generated_source ()\n"
diff --git a/cogl/driver/gl/cogl-pipeline-vertend-glsl.c b/cogl/driver/gl/cogl-pipeline-vertend-glsl.c
index a298145..3a2b155 100644
--- a/cogl/driver/gl/cogl-pipeline-vertend-glsl.c
+++ b/cogl/driver/gl/cogl-pipeline-vertend-glsl.c
@@ -3,7 +3,7 @@
  *
  * An object oriented GL/GLES Abstraction/Utility Layer
  *
- * Copyright (C) 2010 Intel Corporation.
+ * Copyright (C) 2010,2013 Intel Corporation.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -140,6 +140,21 @@ get_layer_vertex_snippets (CoglPipelineLayer *layer)
 }
 
 static void
+add_global_declarations (CoglPipeline *pipeline,
+                         CoglPipelineShaderState *shader_state)
+{
+  CoglSnippetHook hook = COGL_SNIPPET_HOOK_VERTEX_GLOBALS;
+  CoglPipelineSnippetList *snippets = get_vertex_snippets (pipeline);
+
+  /* Add the global data hooks. All of the code in these snippets is
+   * always added and only the declarations data is used */
+
+  _cogl_pipeline_snippet_generate_declarations (shader_state->header,
+                                                hook,
+                                                snippets);
+}
+
+static void
 _cogl_pipeline_vertend_glsl_start (CoglPipeline *pipeline,
                                    int n_layers,
                                    unsigned long pipelines_difference)
@@ -218,6 +233,8 @@ _cogl_pipeline_vertend_glsl_start (CoglPipeline *pipeline,
   shader_state->header = ctx->codegen_header_buffer;
   shader_state->source = ctx->codegen_source_buffer;
 
+  add_global_declarations (pipeline, shader_state);
+
   g_string_append (shader_state->source,
                    "void\n"
                    "cogl_generated_source ()\n"
diff --git a/tests/conform/test-snippets.c b/tests/conform/test-snippets.c
index df85042..07a99a1 100644
--- a/tests/conform/test-snippets.c
+++ b/tests/conform/test-snippets.c
@@ -6,7 +6,7 @@
 
 typedef struct _TestState
 {
-  int padding;
+  int fb_width, fb_height;
 } TestState;
 
 typedef void (* SnippetTestFunc) (TestState *state);
@@ -525,6 +525,109 @@ test_vertex_transform_hook (TestState *state)
 }
 
 static void
+test_global_vertex_hook (TestState *state)
+{
+  CoglPipeline *pipeline;
+  CoglSnippet *snippet;
+
+  pipeline = cogl_pipeline_new (test_ctx);
+
+  /* Creates a function in the global declarations hook which is used
+   * by a subsequent snippet. The subsequent snippets replace any
+   * previous snippets but this shouldn't prevent the global
+   * declarations from being generated */
+
+  snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_VERTEX_GLOBALS,
+                              /* declarations */
+                              "float\n"
+                              "multiply_by_two (float number)\n"
+                              "{\n"
+                              "  return number * 2.0;\n"
+                              "}\n",
+                              /* post */
+                              "This string shouldn't be used so "
+                              "we can safely put garbage in here.");
+  cogl_snippet_set_pre (snippet,
+                        "This string shouldn't be used so "
+                        "we can safely put garbage in here.");
+  cogl_snippet_set_replace (snippet,
+                            "This string shouldn't be used so "
+                            "we can safely put garbage in here.");
+  cogl_pipeline_add_snippet (pipeline, snippet);
+  cogl_object_unref (snippet);
+
+  snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_VERTEX,
+                              NULL, /* declarations */
+                              NULL /* replace */);
+  cogl_snippet_set_replace (snippet,
+                            "cogl_color_out.r = multiply_by_two (0.5);\n"
+                            "cogl_color_out.gba = vec3 (0.0, 0.0, 1.0);\n"
+                            "cogl_position_out = cogl_position_in;\n");
+  cogl_pipeline_add_snippet (pipeline, snippet);
+  cogl_object_unref (snippet);
+
+  cogl_framebuffer_draw_rectangle (test_fb,
+                                   pipeline,
+                                   -1, 1,
+                                   10.0f * 2.0f / state->fb_width - 1.0f,
+                                   10.0f * 2.0f / state->fb_height - 1.0f);
+
+  cogl_object_unref (pipeline);
+
+  test_utils_check_pixel (test_fb, 5, 5, 0xff0000ff);
+}
+
+static void
+test_global_fragment_hook (TestState *state)
+{
+  CoglPipeline *pipeline;
+  CoglSnippet *snippet;
+
+  pipeline = cogl_pipeline_new (test_ctx);
+
+  /* Creates a function in the global declarations hook which is used
+   * by a subsequent snippet. The subsequent snippets replace any
+   * previous snippets but this shouldn't prevent the global
+   * declarations from being generated */
+
+  snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_FRAGMENT_GLOBALS,
+                              /* declarations */
+                              "float\n"
+                              "multiply_by_four (float number)\n"
+                              "{\n"
+                              "  return number * 4.0;\n"
+                              "}\n",
+                              /* post */
+                              "This string shouldn't be used so "
+                              "we can safely put garbage in here.");
+  cogl_snippet_set_pre (snippet,
+                        "This string shouldn't be used so "
+                        "we can safely put garbage in here.");
+  cogl_snippet_set_replace (snippet,
+                            "This string shouldn't be used so "
+                            "we can safely put garbage in here.");
+  cogl_pipeline_add_snippet (pipeline, snippet);
+  cogl_object_unref (snippet);
+
+  snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_FRAGMENT,
+                              NULL, /* declarations */
+                              NULL /* replace */);
+  cogl_snippet_set_replace (snippet,
+                            "cogl_color_out.r = multiply_by_four (0.25);\n"
+                            "cogl_color_out.gba = vec3 (0.0, 0.0, 1.0);\n");
+  cogl_pipeline_add_snippet (pipeline, snippet);
+  cogl_object_unref (snippet);
+
+  cogl_framebuffer_draw_rectangle (test_fb,
+                                   pipeline,
+                                   0, 0, 10, 10);
+
+  cogl_object_unref (pipeline);
+
+  test_utils_check_pixel (test_fb, 5, 5, 0xff0000ff);
+}
+
+static void
 test_snippet_order (TestState *state)
 {
   CoglPipeline *pipeline;
@@ -660,6 +763,8 @@ tests[] =
     test_modify_vertex_layer,
     test_replace_vertex_layer,
     test_vertex_transform_hook,
+    test_global_fragment_hook,
+    test_global_vertex_hook,
     test_snippet_order,
     test_naming_texture_units,
     test_snippet_properties
@@ -685,10 +790,13 @@ test_snippets (void)
 {
   TestState state;
 
+  state.fb_width = cogl_framebuffer_get_width (test_fb);
+  state.fb_height = cogl_framebuffer_get_height (test_fb);
+
   cogl_framebuffer_orthographic (test_fb,
                                  0, 0,
-                                 cogl_framebuffer_get_width (test_fb),
-                                 cogl_framebuffer_get_height (test_fb),
+                                 state.fb_width,
+                                 state.fb_height,
                                  -1,
                                  100);
 


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