[Cogl] [PATCH 1/2] Add fragment and vertex snippet hooks for global declarations

Robert Bragg robert at sixbynine.org
Tue Feb 26 12:29:02 PST 2013


This looks good to land to me:

Reviewed-by: Robert Bragg <robert at linux.intel.com>

thanks,
- Robert

On Tue, Feb 26, 2013 at 7:56 PM, Neil Roberts <neil at linux.intel.com> wrote:
> 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.
> ---
>  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);
>
> --
> 1.7.11.3.g3c3efa5
>
> _______________________________________________
> Cogl mailing list
> Cogl at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/cogl


More information about the Cogl mailing list