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 <neil@linux.intel.com>

(cherry picked from commit d2904d518718e3fbf4441abe2c2bcfd63edfd64b)
This commit is contained in:
Robert Bragg 2012-08-28 13:56:43 +01:00
parent a491789637
commit 5f3768f086

View File

@ -60,9 +60,9 @@ static CoglUserDataKey offscreen_wrapper_key;
* whether we are rendering to an offscreen buffer or not */ * whether we are rendering to an offscreen buffer or not */
#define MAIN_WRAPPER_FLIP_UNIFORM "_cogl_flip_vector" #define MAIN_WRAPPER_FLIP_UNIFORM "_cogl_flip_vector"
/* This wrapper function around 'main' is appended to every program in /* This wrapper function around 'main' is appended to every vertex shader
* a separate shader so that we can add some extra code to flip the * so that we can add some extra code to flip the rendering when
* rendering when rendering to an offscreen buffer */ * rendering to an offscreen buffer */
static const char static const char
main_wrapper_prelude[] = main_wrapper_prelude[] =
"uniform vec4 " MAIN_WRAPPER_FLIP_UNIFORM ";\n" "uniform vec4 " MAIN_WRAPPER_FLIP_UNIFORM ";\n"
@ -827,43 +827,48 @@ gl_shader_source_wrapper (GLuint shader,
GINT_TO_POINTER (shader))) && GINT_TO_POINTER (shader))) &&
shader_data->type == GL_VERTEX_SHADER) shader_data->type == GL_VERTEX_SHADER)
{ {
char **string_copy = g_alloca (count * sizeof (char *)); char **string_copy = g_alloca ((count + 2) * sizeof (char *));
GLint *length_copy = g_alloca (count * sizeof (GLint)); int *length_copy = g_alloca ((count +2) * sizeof (int));
int i; int i;
/* First, copy the shader into a new string; then, replace all string_copy[0] = main_wrapper_prelude;
* instances of the symbol 'main' with our replacement symbol length_copy[0] = -1;
* so we can provide our own wrapper main function; then append
* that wrapper function. */ /* 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++) for (i = 0; i < count; i++)
{ {
int string_length = length ? length[i] : strlen (string[i]); int string_length;
int prelude_length = strlen (main_wrapper_prelude);
int wrapper_length = strlen (main_wrapper_function); 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], replace_token (string_copy[i],
"main", "main",
MAIN_WRAPPER_REPLACEMENT_NAME, MAIN_WRAPPER_REPLACEMENT_NAME,
string_length); string_length);
memmove (&string_copy[i][prelude_length], string_copy[i], length_copy[i + 1] = string_length;
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';
} }
string_copy[count + 1] = main_wrapper_function;
length_copy[count + 1] = -1;
gles2_ctx->context->glShaderSource (shader, gles2_ctx->context->glShaderSource (shader,
count, count + 2,
(const char *const *) string_copy, (const char *const *) string_copy,
length_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]); g_free (string_copy[i]);
} }
else else