[Cogl] [PATCH] cogl-gles2-context: Append wrapper shader to user shaders

Daniel Stone daniel at fooishbar.org
Fri Aug 17 06:13:45 PDT 2012


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 at fooishbar.org>
---
 cogl/cogl-gles2-context-private.h |    4 ---
 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 f948548..5afb296 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 3585705..d78e027 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);
+
+          memcpy (&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);
 
@@ -1557,33 +1565,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)
 {
@@ -1639,8 +1620,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;
-- 
1.7.10.4



More information about the Cogl mailing list