diff options
author | Daniel Stone <daniel@fooishbar.org> | 2012-08-17 14:37:11 +0100 |
---|---|---|
committer | Robert Bragg <robert@linux.intel.com> | 2012-09-17 23:06:21 +0100 |
commit | a491789637c0a718551661f3c753fe77b3c30a09 (patch) | |
tree | eb3908e3938266d9e7a36258a987a6e1d10c4de0 /cogl | |
parent | 50ba5fa130134a09b4be5ec503681539315c7af3 (diff) | |
download | cogl-a491789637c0a718551661f3c753fe77b3c30a09.tar.gz |
cogl-gles2-context: Append wrapper shader to user shaders
The SGX GLSL compiler refuses to accept shaders of the form:
void foo();
void bar() {
foo();
}
where foo is undefined at glShaderSource() time, left for definition at
link time. To work around this, simply append the wrapper shader to
user shaders, rather than building a separate shader that's always
linked with user shaders.
Signed-off-by: Daniel Stone <daniel@fooishbar.org>
Reviewed-by: Robert Bragg <robert@linux.intel.com>
(cherry picked from commit 96f02c445f763ace088be71dc32b3374b2cdbab2)
Diffstat (limited to 'cogl')
-rw-r--r-- | cogl/cogl-gles2-context-private.h | 4 | ||||
-rw-r--r-- | cogl/cogl-gles2-context.c | 71 |
2 files changed, 25 insertions, 50 deletions
diff --git a/cogl/cogl-gles2-context-private.h b/cogl/cogl-gles2-context-private.h index f9485481..5afb296f 100644 --- a/cogl/cogl-gles2-context-private.h +++ b/cogl/cogl-gles2-context-private.h @@ -162,10 +162,6 @@ struct _CoglGLES2Context * current */ CoglGLES2ProgramData *current_program; - /* A shader to provide a wrapper 'main' function. A single shader is - * used for all programs */ - GLuint wrapper_shader; - /* Whether the currently bound framebuffer needs flipping. This is * used to check for changes so that we can dirty the following * state flags */ diff --git a/cogl/cogl-gles2-context.c b/cogl/cogl-gles2-context.c index 47f99b7c..7e22150b 100644 --- a/cogl/cogl-gles2-context.c +++ b/cogl/cogl-gles2-context.c @@ -64,11 +64,12 @@ static CoglUserDataKey offscreen_wrapper_key; * a separate shader so that we can add some extra code to flip the * rendering when rendering to an offscreen buffer */ static const char -main_wrapper_function[] = +main_wrapper_prelude[] = "uniform vec4 " MAIN_WRAPPER_FLIP_UNIFORM ";\n" - "\n" - "void\n" - MAIN_WRAPPER_REPLACEMENT_NAME " ();\n" + "\n"; + +static const char +main_wrapper_function[] = "\n" "void\n" "main ()\n" @@ -732,8 +733,6 @@ gl_create_program_wrapper (void) g_hash_table_insert (gles2_ctx->program_map, GINT_TO_POINTER (id), data); - - gles2_ctx->context->glAttachShader (id, gles2_ctx->wrapper_shader); } return id; @@ -829,28 +828,40 @@ gl_shader_source_wrapper (GLuint shader, shader_data->type == GL_VERTEX_SHADER) { char **string_copy = g_alloca (count * sizeof (char *)); + GLint *length_copy = g_alloca (count * sizeof (GLint)); int i; - /* Replace any occurences of the symbol 'main' with a different - * symbol so that we can provide our own wrapper main - * function */ - + /* 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. */ 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); - string_copy[i] = 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'; } gles2_ctx->context->glShaderSource (shader, count, (const char *const *) string_copy, - length); + length_copy); for (i = 0; i < count; i++) g_free (string_copy[i]); @@ -957,8 +968,7 @@ gl_get_attached_shaders_wrapper (GLuint program, tmp_buf); for (i = 0, count_out = 0; i < count; i++) - if (tmp_buf[i] != gles2_ctx->wrapper_shader) - obj[count_out++] = tmp_buf[i]; + obj[count_out++] = tmp_buf[i]; if (count_ret) *count_ret = count_out; @@ -1477,8 +1487,6 @@ _cogl_gles2_context_free (CoglGLES2Context *gles2_context) const CoglWinsysVtable *winsys; GList *objects, *l; - ctx->glDeleteShader (gles2_context->wrapper_shader); - if (gles2_context->current_program) program_data_unref (gles2_context->current_program); @@ -1555,33 +1563,6 @@ free_texture_object_data (CoglGLES2TextureObjectData *data) g_slice_free (CoglGLES2TextureObjectData, data); } -static GLuint -create_wrapper_shader (CoglContext *ctx) -{ - const char *strings = main_wrapper_function; - GLint length = sizeof (main_wrapper_function) - 1; - GLint status; - GLuint shader; - - shader = ctx->glCreateShader (GL_VERTEX_SHADER); - ctx->glShaderSource (shader, 1, &strings, &length); - ctx->glCompileShader (shader); - ctx->glGetShaderiv (shader, GL_COMPILE_STATUS, &status); - - if (!status) - { - char buf[512]; - - ctx->glGetShaderInfoLog (shader, - sizeof (buf), - NULL, /* length */ - buf); - g_warning ("Compiling wrapper shader failed:\n%s", buf); - } - - return shader; -} - CoglGLES2Context * cogl_gles2_context_new (CoglContext *ctx, GError **error) { @@ -1635,8 +1616,6 @@ cogl_gles2_context_new (CoglContext *ctx, GError **error) #undef COGL_EXT_FUNCTION #undef COGL_EXT_END - gles2_ctx->wrapper_shader = create_wrapper_shader (ctx); - gles2_ctx->vtable->glBindFramebuffer = gl_bind_framebuffer_wrapper; gles2_ctx->vtable->glReadPixels = gl_read_pixels_wrapper; gles2_ctx->vtable->glCopyTexImage2D = gl_copy_tex_image_2d_wrapper; |