From 5f3768f08673424473338b3d64b6978a77bb5954 Mon Sep 17 00:00:00 2001 From: Robert Bragg Date: Tue, 28 Aug 2012 13:56:43 +0100 Subject: [PATCH] gles2-context: only insert prelude + wrapper into strv once In our wrapper for glShaderSource we special case when a vertex shader is being specified so we can sneak in a wrapper for the main function to potentially flip all rendering upside down for better integration with Cogl. Previously we were appending the wrapper to all the sub-strings passed via the vector of strings to glShaderSource but we now grow the vector instead and insert the prelude and wrapper strings into the beginning and end of the vector respectively so we should only have one copy for a single shader. Reviewed-by: Neil Roberts (cherry picked from commit d2904d518718e3fbf4441abe2c2bcfd63edfd64b) --- cogl/cogl-gles2-context.c | 53 +++++++++++++++++++++------------------ 1 file changed, 29 insertions(+), 24 deletions(-) diff --git a/cogl/cogl-gles2-context.c b/cogl/cogl-gles2-context.c index 7e22150b2..012b3624a 100644 --- a/cogl/cogl-gles2-context.c +++ b/cogl/cogl-gles2-context.c @@ -60,9 +60,9 @@ static CoglUserDataKey offscreen_wrapper_key; * whether we are rendering to an offscreen buffer or not */ #define MAIN_WRAPPER_FLIP_UNIFORM "_cogl_flip_vector" -/* This wrapper function around 'main' is appended to every program in - * a separate shader so that we can add some extra code to flip the - * rendering when rendering to an offscreen buffer */ +/* This wrapper function around 'main' is appended to every vertex shader + * so that we can add some extra code to flip the rendering when + * rendering to an offscreen buffer */ static const char main_wrapper_prelude[] = "uniform vec4 " MAIN_WRAPPER_FLIP_UNIFORM ";\n" @@ -827,43 +827,48 @@ gl_shader_source_wrapper (GLuint shader, GINT_TO_POINTER (shader))) && shader_data->type == GL_VERTEX_SHADER) { - char **string_copy = g_alloca (count * sizeof (char *)); - GLint *length_copy = g_alloca (count * sizeof (GLint)); + char **string_copy = g_alloca ((count + 2) * sizeof (char *)); + int *length_copy = g_alloca ((count +2) * sizeof (int)); int i; - /* First, copy the shader into a new string; then, replace all - * instances of the symbol 'main' with our replacement symbol - * so we can provide our own wrapper main function; then append - * that wrapper function. */ + string_copy[0] = main_wrapper_prelude; + length_copy[0] = -1; + + /* Replace any occurences of the symbol 'main' with a different + * symbol so that we can provide our own wrapper main + * function */ + for (i = 0; i < count; i++) { - int string_length = length ? length[i] : strlen (string[i]); - int prelude_length = strlen (main_wrapper_prelude); - int wrapper_length = strlen (main_wrapper_function); + int string_length; + + if (length == NULL || length[i] < 0) + string_length = strlen (string[i]); + else + string_length = length[i]; + + string_copy[i + 1] = g_memdup (string[i], string_length); - length_copy[i] = string_length + prelude_length + wrapper_length; - string_copy[i] = g_malloc (length_copy[i] + 1); - memcpy (string_copy[i], string[i], string_length); - string_copy[i][string_length] = '\0'; replace_token (string_copy[i], "main", MAIN_WRAPPER_REPLACEMENT_NAME, string_length); - memmove (&string_copy[i][prelude_length], string_copy[i], - string_length); - memcpy (string_copy[i], main_wrapper_prelude, prelude_length); - memcpy (&string_copy[i][prelude_length + string_length], - main_wrapper_function, wrapper_length); - string_copy[i][length_copy[i]] = '\0'; + length_copy[i + 1] = string_length; } + string_copy[count + 1] = main_wrapper_function; + length_copy[count + 1] = -1; + gles2_ctx->context->glShaderSource (shader, - count, + count + 2, (const char *const *) string_copy, length_copy); - for (i = 0; i < count; i++) + /* Note: we don't need to free the first and last entries in + * string_copy[] which are our prelude and wrapper strings + * respectively... */ + for (i = 1; i < count; i++) g_free (string_copy[i]); } else