From 4581ce5f156a0292ade2c458eec65297b267efcb Mon Sep 17 00:00:00 2001 From: Neil Roberts Date: Fri, 25 Nov 2011 22:02:53 +0000 Subject: [PATCH] fragend-glsl: Don't generate the default texture lookup if replaced Previously the function containing the default texture lookup is always generated regardless of whether there is a snippet with a replace string which would cause it not be used. Now this snippets are all scanned to check for replace strings before generating the texture lookup. Reviewed-by: Robert Bragg --- cogl/cogl-pipeline-fragend-glsl.c | 132 +++++++++++++++++------------- tests/conform/test-snippets.c | 15 ++++ 2 files changed, 90 insertions(+), 57 deletions(-) diff --git a/cogl/cogl-pipeline-fragend-glsl.c b/cogl/cogl-pipeline-fragend-glsl.c index 15bea5939..b7500ebe1 100644 --- a/cogl/cogl-pipeline-fragend-glsl.c +++ b/cogl/cogl-pipeline-fragend-glsl.c @@ -37,6 +37,7 @@ #include "cogl-pipeline-layer-private.h" #include "cogl-shader-private.h" #include "cogl-blend-string.h" +#include "cogl-snippet-private.h" #ifdef COGL_PIPELINE_FRAGEND_GLSL @@ -200,6 +201,19 @@ get_layer_fragment_snippets (CoglPipelineLayer *layer) return &layer->big_state->fragment_snippets; } +static gboolean +has_replace_hook (CoglPipelineLayer *layer, + CoglSnippetHook hook) +{ + CoglPipelineSnippet *snippet; + + COGL_LIST_FOREACH (snippet, get_layer_fragment_snippets (layer), list_node) + if (snippet->snippet->hook == hook && snippet->snippet->replace) + return TRUE; + + return FALSE; +} + static gboolean _cogl_pipeline_fragend_glsl_start (CoglPipeline *pipeline, int n_layers, @@ -374,9 +388,7 @@ ensure_texture_lookup_generated (CoglPipelineShaderState *shader_state, CoglPipeline *pipeline, CoglPipelineLayer *layer) { - CoglHandle texture; int unit_index = _cogl_pipeline_layer_get_unit_index (layer); - const char *target_string, *tex_coord_swizzle; CoglPipelineSnippetData snippet_data; _COGL_GET_CONTEXT (ctx, NO_RETVAL); @@ -415,73 +427,79 @@ ensure_texture_lookup_generated (CoglPipelineShaderState *shader_state, g_string_append (shader_state->source, ");\n"); - texture = _cogl_pipeline_layer_get_texture (layer); - - if (texture == NULL) + /* There's no need to generate the real texture lookup if it's going + to be replaced */ + if (!has_replace_hook (layer, COGL_SNIPPET_HOOK_TEXTURE_LOOKUP)) { - target_string = "2D"; - tex_coord_swizzle = "st"; - } - else - { - GLenum gl_target; + CoglHandle texture = _cogl_pipeline_layer_get_texture (layer); + const char *target_string, *tex_coord_swizzle; - cogl_texture_get_gl_texture (texture, NULL, &gl_target); - switch (gl_target) + if (texture == NULL) { -#ifdef HAVE_COGL_GL - case GL_TEXTURE_1D: - target_string = "1D"; - tex_coord_swizzle = "s"; - break; -#endif - - case GL_TEXTURE_2D: target_string = "2D"; tex_coord_swizzle = "st"; - break; + } + else + { + GLenum gl_target; -#ifdef GL_ARB_texture_rectangle - case GL_TEXTURE_RECTANGLE_ARB: - target_string = "2DRect"; - tex_coord_swizzle = "st"; - break; + cogl_texture_get_gl_texture (texture, NULL, &gl_target); + switch (gl_target) + { +#ifdef HAVE_COGL_GL + case GL_TEXTURE_1D: + target_string = "1D"; + tex_coord_swizzle = "s"; + break; #endif - case GL_TEXTURE_3D: - target_string = "3D"; - tex_coord_swizzle = "stp"; - break; + case GL_TEXTURE_2D: + target_string = "2D"; + tex_coord_swizzle = "st"; + break; - default: - g_assert_not_reached (); +#ifdef GL_ARB_texture_rectangle + case GL_TEXTURE_RECTANGLE_ARB: + target_string = "2DRect"; + tex_coord_swizzle = "st"; + break; +#endif + + case GL_TEXTURE_3D: + target_string = "3D"; + tex_coord_swizzle = "stp"; + break; + + default: + g_assert_not_reached (); + } } + + /* Create a sampler uniform */ + if (G_LIKELY (!COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_TEXTURING))) + g_string_append_printf (shader_state->header, + "uniform sampler%s _cogl_sampler_%i;\n", + target_string, + unit_index); + + g_string_append_printf (shader_state->header, + "vec4\n" + "cogl_real_texture_lookup%i (vec4 coords)\n" + "{\n" + " return ", + unit_index); + + if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_TEXTURING))) + g_string_append (shader_state->header, + "vec4 (1.0, 1.0, 1.0, 1.0);\n"); + else + g_string_append_printf (shader_state->header, + "texture%s (_cogl_sampler_%i, coords.%s);\n", + target_string, unit_index, tex_coord_swizzle); + + g_string_append (shader_state->header, "}\n"); } - /* Create a sampler uniform */ - if (G_LIKELY (!COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_TEXTURING))) - g_string_append_printf (shader_state->header, - "uniform sampler%s _cogl_sampler_%i;\n", - target_string, - unit_index); - - g_string_append_printf (shader_state->header, - "vec4\n" - "cogl_real_texture_lookup%i (vec4 coords)\n" - "{\n" - " return ", - unit_index); - - if (G_UNLIKELY (COGL_DEBUG_ENABLED (COGL_DEBUG_DISABLE_TEXTURING))) - g_string_append (shader_state->header, - "vec4 (1.0, 1.0, 1.0, 1.0);\n"); - else - g_string_append_printf (shader_state->header, - "texture%s (_cogl_sampler_%i, coords.%s);\n", - target_string, unit_index, tex_coord_swizzle); - - g_string_append (shader_state->header, "}\n"); - /* Wrap the texture lookup in any snippets that have been hooked */ memset (&snippet_data, 0, sizeof (snippet_data)); snippet_data.snippets = get_layer_fragment_snippets (layer); diff --git a/tests/conform/test-snippets.c b/tests/conform/test-snippets.c index 1722cb4e9..bb0cf3449 100644 --- a/tests/conform/test-snippets.c +++ b/tests/conform/test-snippets.c @@ -232,6 +232,20 @@ paint (TestState *state) cogl_object_unref (snippet); + /* Check replacing the texture lookup hook */ + snippet = cogl_snippet_new (COGL_SNIPPET_HOOK_TEXTURE_LOOKUP, NULL, NULL); + cogl_snippet_set_replace (snippet, "cogl_texel = vec4 (0.0, 0.0, 1.0, 0.0);"); + + pipeline = create_texture_pipeline (); + cogl_pipeline_add_layer_snippet (pipeline, 0, snippet); + cogl_push_source (pipeline); + cogl_rectangle_with_texture_coords (90, 0, 100, 10, + 0, 0, 0, 0); + cogl_pop_source (); + cogl_object_unref (pipeline); + + cogl_object_unref (snippet); + /* Test replacing a previous snippet */ pipeline = create_texture_pipeline (); @@ -302,6 +316,7 @@ validate_result (void) test_utils_check_pixel (65, 5, 0x00ff00ff); test_utils_check_pixel (75, 5, 0x808000ff); test_utils_check_pixel (85, 5, 0x00ffffff); + test_utils_check_pixel (95, 5, 0x0000ffff); test_utils_check_pixel (105, 5, 0xff0000ff); }