snippet: Add a hook for the vertex transform

This adds a hook to wrap or replace the vertex transform stage.

Reviewed-by: Robert Bragg <robert@linux.intel.com>
This commit is contained in:
Neil Roberts 2011-11-28 22:06:53 +00:00 committed by Robert Bragg
parent 68b3643b25
commit 7590fc3ec3
3 changed files with 90 additions and 2 deletions

View File

@ -418,13 +418,30 @@ _cogl_pipeline_vertend_glsl_end (CoglPipeline *pipeline,
0 /* no application private data */); 0 /* no application private data */);
COGL_COUNTER_INC (_cogl_uprof_context, vertend_glsl_compile_counter); COGL_COUNTER_INC (_cogl_uprof_context, vertend_glsl_compile_counter);
g_string_append (shader_state->source, g_string_append (shader_state->header,
"void\n"
"cogl_real_vertex_transform ()\n"
"{\n"
" cogl_position_out = " " cogl_position_out = "
"cogl_modelview_projection_matrix * " "cogl_modelview_projection_matrix * "
"cogl_position_in;\n" "cogl_position_in;\n"
"}\n");
g_string_append (shader_state->source,
" cogl_vertex_transform ();\n"
" cogl_color_out = cogl_color_in;\n" " cogl_color_out = cogl_color_in;\n"
"}\n"); "}\n");
/* Add hooks for the vertex transform part */
memset (&snippet_data, 0, sizeof (snippet_data));
snippet_data.snippets = get_vertex_snippets (pipeline);
snippet_data.hook = COGL_SNIPPET_HOOK_VERTEX_TRANSFORM;
snippet_data.chain_function = "cogl_real_vertex_transform";
snippet_data.final_name = "cogl_vertex_transform";
snippet_data.function_prefix = "cogl_vertex_transform";
snippet_data.source_buf = shader_state->header;
_cogl_pipeline_snippet_generate_code (&snippet_data);
/* Add all of the hooks for vertex processing */ /* Add all of the hooks for vertex processing */
memset (&snippet_data, 0, sizeof (snippet_data)); memset (&snippet_data, 0, sizeof (snippet_data));
snippet_data.snippets = get_vertex_snippets (pipeline); snippet_data.snippets = get_vertex_snippets (pipeline);

View File

@ -52,6 +52,7 @@ typedef struct _CoglSnippet CoglSnippet;
* CoglSnippetHook: * CoglSnippetHook:
* @COGL_SNIPPET_HOOK_VERTEX: A hook for the entire vertex processing * @COGL_SNIPPET_HOOK_VERTEX: A hook for the entire vertex processing
* stage of the pipeline. * stage of the pipeline.
* @COGL_SNIPPET_HOOK_VERTEX_TRANSFORM: A hook for the vertex transformation.
* @COGL_SNIPPET_HOOK_FRAGMENT: A hook for the entire fragment * @COGL_SNIPPET_HOOK_FRAGMENT: A hook for the entire fragment
* processing stage of the pipeline. * processing stage of the pipeline.
* @COGL_SNIPPET_HOOK_TEXTURE_COORD_TRANSFORM: A hook for applying the * @COGL_SNIPPET_HOOK_TEXTURE_COORD_TRANSFORM: A hook for applying the
@ -98,6 +99,37 @@ typedef struct _CoglSnippet CoglSnippet;
* </glossdef> * </glossdef>
* </glossentry> * </glossentry>
* <glossentry> * <glossentry>
* <glossterm>%COGL_SNIPPET_HOOK_VERTEX_TRANSFORM</glossterm>
* <glossdef>
* <para>
* Adds a shader snippet that will hook on to the vertex transform stage.
* Typically the snippet will use the cogl_modelview_matrix,
* cogl_projection_matrix and cogl_modelview_projection_matrix matrices and the
* cogl_position_in attribute. The hook must write to cogl_position_out.
* The default processing for this hook will multiply cogl_position_in by
* the combined modelview-projection matrix and store it on cogl_position_out.
* </para>
* <para>
* The declarations string in @snippet will be inserted in the
* global 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 the vertex transform is done.
* </para>
* <para>
* The replace string in @snippet will be used instead of the
* generated vertex transform if it is present.
* </para>
* <para>
* The post string in @snippet will be inserted after all of the
* standard vertex transformation is done. This can be used to modify the
* cogl_position_out in addition to the default processing.
* </para>
* </glossdef>
* </glossentry>
* <glossentry>
* <glossterm>%COGL_SNIPPET_HOOK_FRAGMENT</glossterm> * <glossterm>%COGL_SNIPPET_HOOK_FRAGMENT</glossterm>
* <glossdef> * <glossdef>
* <para> * <para>
@ -246,6 +278,7 @@ typedef struct _CoglSnippet CoglSnippet;
typedef enum { typedef enum {
/* Per pipeline vertex hooks */ /* Per pipeline vertex hooks */
COGL_SNIPPET_HOOK_VERTEX = 0, COGL_SNIPPET_HOOK_VERTEX = 0,
COGL_SNIPPET_HOOK_VERTEX_TRANSFORM,
/* Per pipeline fragment hooks */ /* Per pipeline fragment hooks */
COGL_SNIPPET_HOOK_FRAGMENT = 2048, COGL_SNIPPET_HOOK_FRAGMENT = 2048,

View File

@ -45,11 +45,13 @@ paint (TestState *state)
{ {
CoglPipeline *pipeline; CoglPipeline *pipeline;
CoglSnippet *snippet; CoglSnippet *snippet;
CoglMatrix matrix; CoglMatrix matrix, identity_matrix;
CoglColor color; CoglColor color;
int location; int location;
int i; int i;
cogl_matrix_init_identity (&identity_matrix);
cogl_color_init_from_4ub (&color, 0, 0, 0, 255); cogl_color_init_from_4ub (&color, 0, 0, 0, 255);
cogl_clear (&color, COGL_BUFFER_BIT_COLOR); cogl_clear (&color, COGL_BUFFER_BIT_COLOR);
@ -351,6 +353,41 @@ paint (TestState *state)
cogl_pop_source (); cogl_pop_source ();
cogl_object_unref (pipeline); cogl_object_unref (pipeline);
/* Test the vertex transform hook */
pipeline = cogl_pipeline_new ();
cogl_pipeline_set_color4ub (pipeline, 255, 0, 255, 255);
snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_VERTEX_TRANSFORM,
"uniform mat4 pmat;",
NULL);
cogl_snippet_set_replace (snippet, "cogl_position_out = "
"pmat * cogl_position_in;");
cogl_pipeline_add_snippet (pipeline, snippet);
cogl_object_unref (snippet);
/* Copy the current projection matrix to a uniform */
cogl_get_projection_matrix (&matrix);
location = cogl_pipeline_get_uniform_location (pipeline, "pmat");
cogl_pipeline_set_uniform_matrix (pipeline,
location,
4, /* dimensions */
1, /* count */
FALSE, /* don't transpose */
cogl_matrix_get_array (&matrix));
/* Replace the real projection matrix with the identity. This should
mess up the drawing unless the snippet replacement is working */
cogl_set_projection_matrix (&identity_matrix);
cogl_push_source (pipeline);
cogl_rectangle (150, 0, 160, 10);
cogl_pop_source ();
cogl_object_unref (pipeline);
/* Restore the projection matrix */
cogl_set_projection_matrix (&matrix);
/* Sanity check modifying the snippet */ /* Sanity check modifying the snippet */
snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_FRAGMENT, "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_declarations (snippet), ==, "foo");
@ -405,6 +442,7 @@ validate_result (void)
test_utils_check_pixel (125, 5, 0xff80ffff); test_utils_check_pixel (125, 5, 0xff80ffff);
test_utils_check_pixel (135, 5, 0xffff00ff); test_utils_check_pixel (135, 5, 0xffff00ff);
test_utils_check_pixel (145, 5, 0x00ff00ff); test_utils_check_pixel (145, 5, 0x00ff00ff);
test_utils_check_pixel (155, 5, 0xff00ffff);
} }
void void