cogl: Add pipeline hooks to user program pipelines
Instead of just adding the cogl header boilerplate, we'll redirect the main function with #define and #undef to cogl_main(). The real main calls the hooks-generated cogl_hooks() which chains up to the users main() which is now called cogl_main(). <boilerplate> #define main cogl_main <user shader> <hook functions> void cogl_hooks () { cogl_main (); <hook code> } #undef main void main () { cogl_hooks(); } This allows the user shader to continue using shaders which seem like they define the main function and output to the framebuffer but also gives the CoglPipeline a chance to add hooks. This in particular makes our ClutterColorState transform hooks work on user programs which are used by ClutterShaderEffects. Closes: https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/7804 Closes: https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/7805 Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/3662 Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/4037>
This commit is contained in:

committed by
Marge Bot

parent
62e5706ed5
commit
5e98ee5dbe
@ -699,24 +699,75 @@ _cogl_pipeline_progend_glsl_start (CoglPipeline *pipeline)
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static CoglPipelineSnippetList *
|
||||||
|
get_fragment_snippets (CoglPipeline *pipeline)
|
||||||
|
{
|
||||||
|
pipeline =
|
||||||
|
_cogl_pipeline_get_authority (pipeline,
|
||||||
|
COGL_PIPELINE_STATE_FRAGMENT_SNIPPETS);
|
||||||
|
|
||||||
|
return &pipeline->big_state->fragment_snippets;
|
||||||
|
}
|
||||||
|
|
||||||
|
static CoglPipelineSnippetList *
|
||||||
|
get_vertex_snippets (CoglPipeline *pipeline)
|
||||||
|
{
|
||||||
|
pipeline =
|
||||||
|
_cogl_pipeline_get_authority (pipeline,
|
||||||
|
COGL_PIPELINE_STATE_VERTEX_SNIPPETS);
|
||||||
|
|
||||||
|
return &pipeline->big_state->vertex_snippets;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
needs_recompile (CoglShader *shader,
|
||||||
|
CoglPipeline *pipeline,
|
||||||
|
CoglPipeline *prev)
|
||||||
|
{
|
||||||
|
/* XXX: currently the only things that will affect the
|
||||||
|
* boilerplate for user shaders, apart from driver features,
|
||||||
|
* are the pipeline layer-indices, texture-unit-indices and
|
||||||
|
* snippets
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (pipeline == prev)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (!_cogl_pipeline_layer_and_unit_numbers_equal (prev, pipeline))
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
switch (shader->type)
|
||||||
|
{
|
||||||
|
case COGL_SHADER_TYPE_VERTEX:
|
||||||
|
if (!_cogl_pipeline_vertex_snippets_state_equal (prev, pipeline))
|
||||||
|
return TRUE;
|
||||||
|
break;
|
||||||
|
case COGL_SHADER_TYPE_FRAGMENT:
|
||||||
|
if (!_cogl_pipeline_fragment_snippets_state_equal (prev, pipeline))
|
||||||
|
return TRUE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
g_assert_not_reached ();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_cogl_shader_compile_real (CoglShader *shader,
|
_cogl_shader_compile_real (CoglShader *shader,
|
||||||
CoglPipeline *pipeline)
|
CoglPipeline *pipeline)
|
||||||
{
|
{
|
||||||
|
g_autoptr(GString) hooks_source = NULL;
|
||||||
|
CoglPipelineSnippetData snippet_data;
|
||||||
|
const char *shader_sources[4];
|
||||||
GLenum gl_type;
|
GLenum gl_type;
|
||||||
GLint status;
|
GLint status;
|
||||||
CoglContext *ctx = pipeline->context;
|
CoglContext *ctx = pipeline->context;
|
||||||
|
|
||||||
if (shader->gl_handle)
|
if (shader->gl_handle)
|
||||||
{
|
{
|
||||||
CoglPipeline *prev = shader->compilation_pipeline;
|
if (!needs_recompile (shader, pipeline, shader->compilation_pipeline))
|
||||||
|
|
||||||
/* XXX: currently the only things that will affect the
|
|
||||||
* boilerplate for user shaders, apart from driver features,
|
|
||||||
* are the pipeline layer-indices and texture-unit-indices
|
|
||||||
*/
|
|
||||||
if (pipeline == prev ||
|
|
||||||
_cogl_pipeline_layer_and_unit_numbers_equal (prev, pipeline))
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
GE (ctx, glDeleteShader (shader->gl_handle));
|
GE (ctx, glDeleteShader (shader->gl_handle));
|
||||||
@ -729,28 +780,47 @@ _cogl_shader_compile_real (CoglShader *shader,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hooks_source = g_string_new ("");
|
||||||
|
memset (&snippet_data, 0, sizeof (snippet_data));
|
||||||
|
snippet_data.chain_function = "cogl_main";
|
||||||
|
snippet_data.final_name = "cogl_hooks";
|
||||||
|
snippet_data.source_buf = hooks_source;
|
||||||
|
|
||||||
switch (shader->type)
|
switch (shader->type)
|
||||||
{
|
{
|
||||||
case COGL_SHADER_TYPE_VERTEX:
|
case COGL_SHADER_TYPE_VERTEX:
|
||||||
gl_type = GL_VERTEX_SHADER;
|
gl_type = GL_VERTEX_SHADER;
|
||||||
|
snippet_data.snippets = get_vertex_snippets (pipeline);
|
||||||
|
snippet_data.hook = COGL_SNIPPET_HOOK_VERTEX;
|
||||||
|
snippet_data.function_prefix = "cogl_vertex_hook";
|
||||||
break;
|
break;
|
||||||
case COGL_SHADER_TYPE_FRAGMENT:
|
case COGL_SHADER_TYPE_FRAGMENT:
|
||||||
gl_type = GL_FRAGMENT_SHADER;
|
gl_type = GL_FRAGMENT_SHADER;
|
||||||
|
snippet_data.snippets = get_fragment_snippets (pipeline);
|
||||||
|
snippet_data.hook = COGL_SNIPPET_HOOK_FRAGMENT;
|
||||||
|
snippet_data.function_prefix = "cogl_fragment_hook";
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
g_assert_not_reached ();
|
g_assert_not_reached ();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_cogl_pipeline_snippet_generate_code (&snippet_data);
|
||||||
|
|
||||||
|
shader_sources[0] = "#define main cogl_main\n";
|
||||||
|
shader_sources[1] = shader->source;
|
||||||
|
shader_sources[2] = hooks_source->str;
|
||||||
|
shader_sources[3] = "#undef main\n"
|
||||||
|
"void main () { cogl_hooks(); }\n";
|
||||||
|
|
||||||
shader->gl_handle = ctx->glCreateShader (gl_type);
|
shader->gl_handle = ctx->glCreateShader (gl_type);
|
||||||
|
|
||||||
_cogl_glsl_shader_set_source_with_boilerplate (ctx,
|
_cogl_glsl_shader_set_source_with_boilerplate (ctx,
|
||||||
shader->gl_handle,
|
shader->gl_handle,
|
||||||
gl_type,
|
gl_type,
|
||||||
pipeline,
|
pipeline,
|
||||||
1,
|
G_N_ELEMENTS (shader_sources),
|
||||||
(const char **)
|
shader_sources,
|
||||||
&shader->source,
|
|
||||||
NULL);
|
NULL);
|
||||||
GE (ctx, glCompileShader (shader->gl_handle));
|
GE (ctx, glCompileShader (shader->gl_handle));
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user