snippet: Add a 'replace' string

If present, the 'replace' string will be used instead of whatever code
would normally be invoked for that hook point. It will also replace
any previous snippets.

Reviewed-by: Robert Bragg <robert@linux.intel.com>
This commit is contained in:
Neil Roberts 2011-11-25 14:36:31 +00:00 committed by Robert Bragg
parent 0fdd5690c6
commit 717e96b304
7 changed files with 110 additions and 4 deletions

View File

@ -957,8 +957,11 @@ _cogl_pipeline_fragend_glsl_end (CoglPipeline *pipeline,
if ((source = cogl_snippet_get_pre (snippet->snippet))) if ((source = cogl_snippet_get_pre (snippet->snippet)))
g_string_append (shader_state->source, source); g_string_append (shader_state->source, source);
/* Chain on to the next function */ /* Chain on to the next function, or bypass it if there is
if (snippet_num > 0) a replace string */
if ((source = cogl_snippet_get_replace (snippet->snippet)))
g_string_append (shader_state->source, source);
else if (snippet_num > 0)
g_string_append_printf (shader_state->source, g_string_append_printf (shader_state->source,
" cogl_snippet%i ();\n", " cogl_snippet%i ();\n",
snippet_num - 1); snippet_num - 1);

View File

@ -954,6 +954,11 @@ cogl_pipeline_set_uniform_matrix (CoglPipeline *pipeline,
* The pre string in @snippet will be inserted at the top of the * The pre string in @snippet will be inserted at the top of the
* main() function before any vertex processing is done. * 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 * The post string in @snippet will be inserted after all of the
* standard vertex processing is done. This can be used to modify the * standard vertex processing is done. This can be used to modify the
* outputs. * outputs.
@ -982,6 +987,11 @@ cogl_pipeline_add_vertex_hook (CoglPipeline *pipeline,
* The pre string in @snippet will be inserted at the top of the * The pre string in @snippet will be inserted at the top of the
* main() function before any fragment processing is done. * 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 * The post string in @snippet will be inserted after all of the
* standard fragment processing is done. At this point the generated * standard fragment processing is done. At this point the generated
* value for the rest of the pipeline state will already be in * value for the rest of the pipeline state will already be in

View File

@ -397,8 +397,11 @@ _cogl_pipeline_vertend_glsl_end (CoglPipeline *pipeline,
if ((source = cogl_snippet_get_pre (snippet->snippet))) if ((source = cogl_snippet_get_pre (snippet->snippet)))
g_string_append (shader_state->source, source); g_string_append (shader_state->source, source);
/* Chain on to the next function */ /* Chain on to the next function, or bypass it if there is
if (snippet_num > 0) a replace string */
if ((source = cogl_snippet_get_replace (snippet->snippet)))
g_string_append (shader_state->source, source);
else if (snippet_num > 0)
g_string_append_printf (shader_state->source, g_string_append_printf (shader_state->source,
" cogl_snippet%i ();\n", " cogl_snippet%i ();\n",
snippet_num - 1); snippet_num - 1);

View File

@ -44,6 +44,7 @@ struct _CoglSnippet
char *declarations; char *declarations;
char *pre; char *pre;
char *replace;
char *post; char *post;
}; };

View File

@ -108,6 +108,27 @@ cogl_snippet_get_pre (CoglSnippet *snippet)
return snippet->pre; return snippet->pre;
} }
void
cogl_snippet_set_replace (CoglSnippet *snippet,
const char *replace)
{
_COGL_RETURN_IF_FAIL (cogl_is_snippet (snippet));
if (!_cogl_snippet_modify (snippet))
return;
g_free (snippet->replace);
snippet->replace = replace ? g_strdup (replace) : NULL;
}
const char *
cogl_snippet_get_replace (CoglSnippet *snippet)
{
_COGL_RETURN_VAL_IF_FAIL (cogl_is_snippet (snippet), NULL);
return snippet->replace;
}
void void
cogl_snippet_set_post (CoglSnippet *snippet, cogl_snippet_set_post (CoglSnippet *snippet,
const char *post) const char *post)
@ -140,6 +161,7 @@ _cogl_snippet_free (CoglSnippet *snippet)
{ {
g_free (snippet->declarations); g_free (snippet->declarations);
g_free (snippet->pre); g_free (snippet->pre);
g_free (snippet->replace);
g_free (snippet->post); g_free (snippet->post);
g_slice_free (CoglSnippet, snippet); g_slice_free (CoglSnippet, snippet);
} }

View File

@ -154,6 +154,42 @@ cogl_snippet_set_pre (CoglSnippet *snippet,
const char * const char *
cogl_snippet_get_pre (CoglSnippet *snippet); cogl_snippet_get_pre (CoglSnippet *snippet);
#define cogl_snippet_set_replace cogl_snippet_set_replace_EXP
/**
* cogl_snippet_set_replace:
* @snippet: A #CoglSnippet
* @replace: The new source string for the replace section of this snippet.
*
* Sets a source string that will be used instead of any generated
* source code or any previous snippets for this hook point. Please
* see the documentation of each hook point in #CoglPipeline for a
* description of how this string should be used.
*
* This function should only be called before the snippet is attached
* to its first pipeline. After that the snippet should be considered
* immutable.
*
* Since: 1.10
* Stability: Unstable
*/
void
cogl_snippet_set_replace (CoglSnippet *snippet,
const char *replace);
#define cogl_snippet_get_replace cogl_snippet_get_replace_EXP
/**
* cogl_snippet_get_replace:
* @snippet: A #CoglSnippet
*
* Return value: the source string that was set with
* cogl_snippet_set_replace() or %NULL if none was set.
*
* Since: 1.10
* Stability: Unstable
*/
const char *
cogl_snippet_get_replace (CoglSnippet *snippet);
#define cogl_snippet_set_post cogl_snippet_set_post_EXP #define cogl_snippet_set_post cogl_snippet_set_post_EXP
/** /**
* cogl_snippet_set_post: * cogl_snippet_set_post:

View File

@ -150,25 +150,55 @@ paint (TestState *state)
cogl_object_unref (snippet); cogl_object_unref (snippet);
/* Check the replace string */
snippet = cogl_snippet_new (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
then the code from the pre string would get overwritten with
white */
cogl_snippet_set_replace (snippet, "/* do nothing */");
cogl_snippet_set_post (snippet,
"cogl_color_out += vec4 (0.5, 0.0, 0.0, 1.0);");
pipeline = cogl_pipeline_new ();
cogl_pipeline_add_fragment_hook (pipeline, snippet);
cogl_push_source (pipeline);
cogl_rectangle (70, 0, 80, 10);
cogl_pop_source ();
cogl_object_unref (pipeline);
cogl_object_unref (snippet);
/* Sanity check modifying the snippet */ /* Sanity check modifying the snippet */
snippet = cogl_snippet_new ("foo", "bar"); snippet = cogl_snippet_new ("foo", "bar");
g_assert_cmpstr (cogl_snippet_get_declarations (snippet), ==, "foo"); g_assert_cmpstr (cogl_snippet_get_declarations (snippet), ==, "foo");
g_assert_cmpstr (cogl_snippet_get_post (snippet), ==, "bar"); g_assert_cmpstr (cogl_snippet_get_post (snippet), ==, "bar");
g_assert_cmpstr (cogl_snippet_get_replace (snippet), ==, NULL);
g_assert_cmpstr (cogl_snippet_get_pre (snippet), ==, NULL); g_assert_cmpstr (cogl_snippet_get_pre (snippet), ==, NULL);
cogl_snippet_set_declarations (snippet, "fu"); cogl_snippet_set_declarations (snippet, "fu");
g_assert_cmpstr (cogl_snippet_get_declarations (snippet), ==, "fu"); g_assert_cmpstr (cogl_snippet_get_declarations (snippet), ==, "fu");
g_assert_cmpstr (cogl_snippet_get_post (snippet), ==, "bar"); g_assert_cmpstr (cogl_snippet_get_post (snippet), ==, "bar");
g_assert_cmpstr (cogl_snippet_get_replace (snippet), ==, NULL);
g_assert_cmpstr (cogl_snippet_get_pre (snippet), ==, NULL); g_assert_cmpstr (cogl_snippet_get_pre (snippet), ==, NULL);
cogl_snippet_set_post (snippet, "ba"); cogl_snippet_set_post (snippet, "ba");
g_assert_cmpstr (cogl_snippet_get_declarations (snippet), ==, "fu"); g_assert_cmpstr (cogl_snippet_get_declarations (snippet), ==, "fu");
g_assert_cmpstr (cogl_snippet_get_post (snippet), ==, "ba"); g_assert_cmpstr (cogl_snippet_get_post (snippet), ==, "ba");
g_assert_cmpstr (cogl_snippet_get_replace (snippet), ==, NULL);
g_assert_cmpstr (cogl_snippet_get_pre (snippet), ==, NULL); g_assert_cmpstr (cogl_snippet_get_pre (snippet), ==, NULL);
cogl_snippet_set_pre (snippet, "fuba"); cogl_snippet_set_pre (snippet, "fuba");
g_assert_cmpstr (cogl_snippet_get_declarations (snippet), ==, "fu"); g_assert_cmpstr (cogl_snippet_get_declarations (snippet), ==, "fu");
g_assert_cmpstr (cogl_snippet_get_post (snippet), ==, "ba"); g_assert_cmpstr (cogl_snippet_get_post (snippet), ==, "ba");
g_assert_cmpstr (cogl_snippet_get_replace (snippet), ==, NULL);
g_assert_cmpstr (cogl_snippet_get_pre (snippet), ==, "fuba");
cogl_snippet_set_replace (snippet, "baba");
g_assert_cmpstr (cogl_snippet_get_declarations (snippet), ==, "fu");
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_cmpstr (cogl_snippet_get_pre (snippet), ==, "fuba");
} }
@ -182,6 +212,7 @@ validate_result (void)
test_utils_check_pixel (45, 5, 0xff0000ff); test_utils_check_pixel (45, 5, 0xff0000ff);
test_utils_check_pixel (55, 5, 0x00ff00ff); test_utils_check_pixel (55, 5, 0x00ff00ff);
test_utils_check_pixel (65, 5, 0x00ff00ff); test_utils_check_pixel (65, 5, 0x00ff00ff);
test_utils_check_pixel (75, 5, 0x808000ff);
} }
void void