diff --git a/cogl/cogl-context.c b/cogl/cogl-context.c
index 7a56a9ada..1c306e16f 100644
--- a/cogl/cogl-context.c
+++ b/cogl/cogl-context.c
@@ -239,7 +239,7 @@ cogl_create_context (void)
                                 default_texture_data);
 
   cogl_push_source (_context->opaque_color_pipeline);
-  _cogl_pipeline_flush_gl_state (_context->opaque_color_pipeline, FALSE);
+  _cogl_pipeline_flush_gl_state (_context->opaque_color_pipeline, FALSE, 0);
   _cogl_enable (enable_flags);
   _cogl_flush_face_winding ();
 
diff --git a/cogl/cogl-path.c b/cogl/cogl-path.c
index 9e4eee71a..0577f417b 100644
--- a/cogl/cogl-path.c
+++ b/cogl/cogl-path.c
@@ -230,7 +230,7 @@ _cogl_path_stroke_nodes (void)
 
   cogl_push_source (source);
 
-  _cogl_pipeline_flush_gl_state (source, FALSE);
+  _cogl_pipeline_flush_gl_state (source, FALSE, 0);
 
   /* Disable all client texture coordinate arrays */
   _cogl_bitmask_clear_all (&ctx->temp_bitmask);
@@ -376,7 +376,7 @@ _cogl_add_path_to_stencil_buffer (CoglPath  *path,
   /* Just setup a simple pipeline that doesn't use texturing... */
   cogl_push_source (ctx->stencil_pipeline);
 
-  _cogl_pipeline_flush_gl_state (ctx->stencil_pipeline, FALSE);
+  _cogl_pipeline_flush_gl_state (ctx->stencil_pipeline, FALSE, 0);
 
   _cogl_enable (enable_flags);
 
diff --git a/cogl/cogl-pipeline-arbfp.c b/cogl/cogl-pipeline-arbfp.c
index dea031c98..97b5e3693 100644
--- a/cogl/cogl-pipeline-arbfp.c
+++ b/cogl/cogl-pipeline-arbfp.c
@@ -327,7 +327,8 @@ get_arbfp_program_state (CoglPipeline *pipeline)
 static gboolean
 _cogl_pipeline_backend_arbfp_start (CoglPipeline *pipeline,
                                     int n_layers,
-                                    unsigned long pipelines_difference)
+                                    unsigned long pipelines_difference,
+                                    int n_tex_coord_attribs)
 {
   CoglPipelineBackendARBfpPrivate *priv;
   CoglPipeline *authority;
diff --git a/cogl/cogl-pipeline-fixed.c b/cogl/cogl-pipeline-fixed.c
index 092e5cccd..11337b7bd 100644
--- a/cogl/cogl-pipeline-fixed.c
+++ b/cogl/cogl-pipeline-fixed.c
@@ -73,7 +73,8 @@ _cogl_pipeline_backend_fixed_get_max_texture_units (void)
 static gboolean
 _cogl_pipeline_backend_fixed_start (CoglPipeline *pipeline,
                                     int n_layers,
-                                    unsigned long pipelines_difference)
+                                    unsigned long pipelines_difference,
+                                    int n_tex_coord_attribs)
 {
   _cogl_use_program (0, COGL_PIPELINE_PROGRAM_TYPE_FIXED);
   return TRUE;
diff --git a/cogl/cogl-pipeline-glsl.c b/cogl/cogl-pipeline-glsl.c
index 3e322e2f3..c94e517bf 100644
--- a/cogl/cogl-pipeline-glsl.c
+++ b/cogl/cogl-pipeline-glsl.c
@@ -73,6 +73,17 @@ typedef struct _GlslProgramState
   unsigned int user_program_age;
   GLuint gl_program;
 
+#ifdef HAVE_COGL_GLES2
+  /* To allow writing shaders that are portable between GLES 2 and
+   * OpenGL Cogl prepends a number of boilerplate #defines and
+   * declarations to user shaders. One of those declarations is an
+   * array of texture coordinate varyings, but to know how to emit the
+   * declaration we need to know how many texture coordinate
+   * attributes are in use.  The boilerplate also needs to be changed
+   * if this increases. */
+  int n_tex_coord_attribs;
+#endif
+
   /* This is set to TRUE if the program has changed since we last
      flushed the uniforms */
   gboolean gl_program_changed;
@@ -252,7 +263,8 @@ link_program (GLint gl_program)
 static gboolean
 _cogl_pipeline_backend_glsl_start (CoglPipeline *pipeline,
                                    int n_layers,
-                                   unsigned long pipelines_difference)
+                                   unsigned long pipelines_difference,
+                                   int n_tex_coord_attribs)
 {
   CoglPipelineBackendGlslPrivate *priv;
   CoglPipeline *authority;
@@ -285,8 +297,17 @@ _cogl_pipeline_backend_glsl_start (CoglPipeline *pipeline,
   if (priv->glsl_program_state)
     {
       /* However if the program has changed since the last link then we do
-         need to relink */
-      if (priv->glsl_program_state->user_program_age == user_program->age)
+       * need to relink
+       *
+       * Also if the number of texture coordinate attributes in use has
+       * increased, then delete the program so we can prepend a new
+       * _cogl_tex_coord[] varying array declaration. */
+      if (priv->glsl_program_state->user_program_age == user_program->age
+#ifdef HAVE_COGL_GLES2
+          && priv->glsl_program_state->n_tex_coord_attribs >=
+             n_tex_coord_attribs
+#endif
+         )
         return TRUE;
 
       /* Destroy the existing program. We can't just dirty the whole
@@ -340,6 +361,18 @@ _cogl_pipeline_backend_glsl_start (CoglPipeline *pipeline,
 
   GE_RET( gl_program, glCreateProgram () );
 
+#ifdef HAVE_COGL_GLES2
+  /* Find the largest count of texture coordinate attributes
+   * associated with each of the shaders so we can ensure a consistent
+   * _cogl_tex_coord[] array declaration across all of the shaders.*/
+  for (l = user_program->attached_shaders; l; l = l->next)
+    {
+      CoglShader *shader = l->data;
+      n_tex_coord_attribs = MAX (shader->n_tex_coord_attribs,
+                                 n_tex_coord_attribs);
+    }
+#endif
+
   /* Add all of the shaders from the user program */
   for (l = user_program->attached_shaders; l; l = l->next)
     {
@@ -347,11 +380,16 @@ _cogl_pipeline_backend_glsl_start (CoglPipeline *pipeline,
 
       g_assert (shader->language == COGL_SHADER_LANGUAGE_GLSL);
 
+      _cogl_shader_compile_real (shader, n_tex_coord_attribs);
+
       GE( glAttachShader (gl_program, shader->gl_handle) );
     }
 
   priv->glsl_program_state->gl_program = gl_program;
   priv->glsl_program_state->user_program_age = user_program->age;
+#ifdef HAVE_COGL_GLES2
+  priv->glsl_program_state->n_tex_coord_attribs = n_tex_coord_attribs;
+#endif
 
   link_program (gl_program);
 
diff --git a/cogl/cogl-pipeline-opengl-private.h b/cogl/cogl-pipeline-opengl-private.h
index 21bf0c5e9..43917b12a 100644
--- a/cogl/cogl-pipeline-opengl-private.h
+++ b/cogl/cogl-pipeline-opengl-private.h
@@ -150,7 +150,8 @@ _cogl_gl_use_program_wrapper (CoglHandle program);
 
 void
 _cogl_pipeline_flush_gl_state (CoglPipeline *pipeline,
-                               gboolean skip_gl_state);
+                               gboolean skip_gl_state,
+                               int n_tex_coord_attribs);
 
 #endif /* __COGL_PIPELINE_OPENGL_PRIVATE_H */
 
diff --git a/cogl/cogl-pipeline-opengl.c b/cogl/cogl-pipeline-opengl.c
index 7c2d1d77b..9a69b38e7 100644
--- a/cogl/cogl-pipeline-opengl.c
+++ b/cogl/cogl-pipeline-opengl.c
@@ -1036,7 +1036,8 @@ backend_add_layer_cb (CoglPipelineLayer *layer,
  */
 void
 _cogl_pipeline_flush_gl_state (CoglPipeline *pipeline,
-                               gboolean skip_gl_color)
+                               gboolean skip_gl_color,
+                               int n_tex_coord_attribs)
 {
   unsigned long    pipelines_difference;
   int              n_layers;
@@ -1139,7 +1140,8 @@ _cogl_pipeline_flush_gl_state (CoglPipeline *pipeline,
        * scratch buffers here... */
       if (G_UNLIKELY (!backend->start (pipeline,
                                        n_layers,
-                                       pipelines_difference)))
+                                       pipelines_difference,
+                                       n_tex_coord_attribs)))
         continue;
 
       state.backend = backend;
diff --git a/cogl/cogl-pipeline-private.h b/cogl/cogl-pipeline-private.h
index 955c3d767..b14669706 100644
--- a/cogl/cogl-pipeline-private.h
+++ b/cogl/cogl-pipeline-private.h
@@ -552,7 +552,8 @@ typedef struct _CoglPipelineBackend
 
   gboolean (*start) (CoglPipeline *pipeline,
                      int n_layers,
-                     unsigned long pipelines_difference);
+                     unsigned long pipelines_difference,
+                     int n_tex_coord_attribs);
   gboolean (*add_layer) (CoglPipeline *pipeline,
                          CoglPipelineLayer *layer,
                          unsigned long layers_difference);
diff --git a/cogl/cogl-shader-boilerplate.h b/cogl/cogl-shader-boilerplate.h
new file mode 100644
index 000000000..1ed3519e2
--- /dev/null
+++ b/cogl/cogl-shader-boilerplate.h
@@ -0,0 +1,107 @@
+/*
+ * Cogl
+ *
+ * An object oriented GL/GLES Abstraction/Utility Layer
+ *
+ * Copyright (C) 2010 Intel Corporation.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ *
+ * Authors:
+ *   Robert Bragg <robert@linux.intel.com>
+ */
+
+#ifndef __COGL_SHADER_BOILERPLATE_H
+#define __COGL_SHADER_BOILERPLATE_H
+
+#include "cogl.h"
+
+
+#define _COGL_COMMON_SHADER_BOILERPLATE \
+  "#define COGL_VERSION 100\n" \
+  "\n"
+
+#ifndef HAVE_COGL_GLES2
+
+#define _COGL_VERTEX_SHADER_BOILERPLATE \
+  _COGL_COMMON_SHADER_BOILERPLATE \
+  "#define cogl_position_in gl_Vertex\n" \
+  "#define cogl_color_in gl_Color\n" \
+  "#define cogl_tex_coord_in  gl_MultiTexCoord0\n" \
+  "#define cogl_tex_coord0_in gl_MultiTexCoord0\n" \
+  "#define cogl_tex_coord1_in gl_MultiTexCoord1\n" \
+  "#define cogl_tex_coord2_in gl_MultiTexCoord2\n" \
+  "#define cogl_tex_coord3_in gl_MultiTexCoord3\n" \
+  "#define cogl_tex_coord4_in gl_MultiTexCoord4\n" \
+  "#define cogl_tex_coord5_in gl_MultiTexCoord5\n" \
+  "#define cogl_tex_coord6_in gl_MultiTexCoord6\n" \
+  "#define cogl_tex_coord7_in gl_MultiTexCoord7\n" \
+  "#define cogl_normal_in gl_Normal\n" \
+  "\n" \
+  "#define cogl_position_out gl_Position\n" \
+  "#define cogl_point_size_out gl_PointSize\n" \
+  "#define cogl_color_out gl_FrontColor\n" \
+  "#define cogl_tex_coord_out gl_TexCoord\n" \
+  "\n" \
+  "#define cogl_modelview_matrix gl_ModelViewMatrix\n" \
+  "#define cogl_modelview_projection_matrix gl_ModelViewProjectionMatrix\n" \
+  "#define cogl_projection_matrix gl_ProjectionMatrix\n" \
+  "#define cogl_texture_matrix gl_TextureMatrix\n" \
+
+#define _COGL_FRAGMENT_SHADER_BOILERPLATE \
+  _COGL_COMMON_SHADER_BOILERPLATE \
+  "#define cogl_color_in gl_Color\n" \
+  "#define cogl_tex_coord_in gl_TexCoord\n" \
+  "\n" \
+  "#define cogl_color_out gl_FragColor\n" \
+  "#define cogl_depth_out gl_FragDepth\n" \
+  "\n" \
+  "#define cogl_front_facing gl_FrontFacing\n"
+#if 0
+  /* GLSL 1.2 has a bottom left origin, though later versions
+   * allow use of an origin_upper_left keyword which would be
+   * more appropriate for Cogl. */
+  "#define coglFragCoord   gl_FragCoord\n"
+#endif
+
+#else /* HAVE_COGL_GLES2 */
+
+#define _COGL_VERTEX_SHADER_BOILERPLATE \
+  _COGL_COMMON_SHADER_BOILERPLATE \
+  "#define cogl_color_out _cogl_color\n" \
+  "#define cogl_point_coord_out _cogl_point_coord\n" \
+  "#define cogl_tex_coord_out _cogl_tex_coord\n"
+
+#define _COGL_FRAGMENT_SHADER_BOILERPLATE \
+  _COGL_COMMON_SHADER_BOILERPLATE \
+  "#if __VERSION__ == 100\n" \
+  "precision highp float;\n" \
+  "#endif\n" \
+  "\n" \
+  "varying vec4 _cogl_color;\n" \
+  "\n" \
+  "#define cogl_color_in _cogl_color\n" \
+  "#define cogl_tex_coord_in _cogl_tex_coord\n" \
+  "\n" \
+  "#define cogl_color_out gl_FragColor\n" \
+  "#define cogl_depth_out gl_FragDepth\n" \
+  "\n" \
+  "#define cogl_front_facing gl_FrontFacing\n"
+
+#endif /* HAVE_COGL_GLES2 */
+
+#endif /* __COGL_SHADER_BOILERPLATE_H */
+
diff --git a/cogl/cogl-shader-private.h b/cogl/cogl-shader-private.h
index 9ba448002..03269a570 100644
--- a/cogl/cogl-shader-private.h
+++ b/cogl/cogl-shader-private.h
@@ -40,12 +40,17 @@ struct _CoglShader
 {
   CoglHandleObject   _parent;
   GLuint             gl_handle;
+  int                n_tex_coord_attribs;
   CoglShaderType     type;
   CoglShaderLanguage language;
+  char              *source;
 };
 
 CoglShader *_cogl_shader_pointer_from_handle (CoglHandle handle);
 
+void
+_cogl_shader_compile_real (CoglHandle handle, int n_tex_coord_attribs);
+
 CoglShaderLanguage
 _cogl_program_get_language (CoglHandle handle);
 
diff --git a/cogl/cogl-shader.c b/cogl/cogl-shader.c
index 6391ea529..b58cbe686 100644
--- a/cogl/cogl-shader.c
+++ b/cogl/cogl-shader.c
@@ -27,6 +27,7 @@
 
 #include "cogl.h"
 #include "cogl-shader-private.h"
+#include "cogl-shader-boilerplate.h"
 #include "cogl-internal.h"
 #include "cogl-context.h"
 #include "cogl-handle.h"
@@ -100,11 +101,35 @@ cogl_create_shader (CoglShaderType type)
   shader = g_slice_new (CoglShader);
   shader->language = COGL_SHADER_LANGUAGE_GLSL;
   shader->gl_handle = 0;
+#ifdef HAVE_COGL_GLES2
+  shader->n_tex_coord_attribs = 0;
+#endif
   shader->type = type;
 
   return _cogl_shader_handle_new (shader);
 }
 
+static void
+delete_shader (CoglShader *shader)
+{
+  _COGL_GET_CONTEXT (ctx, NO_RETVAL);
+
+#ifdef HAVE_COGL_GL
+  if (shader->language == COGL_SHADER_LANGUAGE_ARBFP)
+    {
+      if (shader->gl_handle)
+        GE (glDeletePrograms (1, &shader->gl_handle));
+    }
+  else
+#endif
+    {
+      if (shader->gl_handle)
+        GE (glDeleteShader (shader->gl_handle));
+    }
+
+  shader->gl_handle = 0;
+}
+
 void
 cogl_shader_source (CoglHandle   handle,
                     const char  *source)
@@ -127,29 +152,55 @@ cogl_shader_source (CoglHandle   handle,
     language = COGL_SHADER_LANGUAGE_GLSL;
 
   /* Delete the old object if the language is changing... */
-  if (G_UNLIKELY (language != shader->language))
-    {
-#ifdef HAVE_COGL_GL
-      if (shader->language == COGL_SHADER_LANGUAGE_ARBFP)
-        {
-          if (shader->gl_handle)
-            GE (glDeletePrograms (1, &shader->gl_handle));
-        }
-      else
-#endif
-        {
-          if (shader->gl_handle)
-            GE (glDeleteShader (shader->gl_handle));
-        }
-    }
+  if (G_UNLIKELY (language != shader->language) &&
+      shader->gl_handle)
+    delete_shader (shader);
+
+  shader->source = g_strdup (source);
+
+  shader->language = language;
+}
+
+void
+cogl_shader_compile (CoglHandle handle)
+{
+  CoglShader *shader = handle;
+
+  if (!cogl_is_shader (handle))
+    return;
 
 #ifdef HAVE_COGL_GL
-  if (language == COGL_SHADER_LANGUAGE_ARBFP)
+  _cogl_shader_compile_real (shader, 0 /* ignored */);
+#endif
+
+  /* XXX: For GLES2 we don't actually compile anything until the
+   * shader gets used so we have an opportunity to add some
+   * boilerplate to the shader.
+   *
+   * At the end of the day this is obviously a badly designed API
+   * given that we are having to lie to the user. It was a mistake to
+   * so thinly wrap the OpenGL shader API and the current plan is to
+   * replace it with a pipeline snippets API. */
+}
+
+void
+_cogl_shader_compile_real (CoglHandle handle,
+                           int n_tex_coord_attribs)
+{
+  CoglShader *shader = handle;
+
+  _COGL_GET_CONTEXT (ctx, NO_RETVAL);
+
+#ifdef HAVE_COGL_GL
+  if (shader->language == COGL_SHADER_LANGUAGE_ARBFP)
     {
 #ifdef COGL_GL_DEBUG
       GLenum gl_error;
 #endif
 
+      if (shader->gl_handle)
+        return;
+
       GE (glGenPrograms (1, &shader->gl_handle));
 
       GE (glBindProgram (GL_FRAGMENT_PROGRAM_ARB, shader->gl_handle));
@@ -160,8 +211,8 @@ cogl_shader_source (CoglHandle   handle,
 #endif
       glProgramString (GL_FRAGMENT_PROGRAM_ARB,
                        GL_PROGRAM_FORMAT_ASCII_ARB,
-                       strlen (source),
-                       source);
+                       strlen (shader->source),
+                       shader->source);
 #ifdef COGL_GL_DEBUG
       gl_error = glGetError ();
       if (gl_error != GL_NO_ERROR)
@@ -169,7 +220,7 @@ cogl_shader_source (CoglHandle   handle,
           g_warning ("%s: GL error (%d): Failed to compile ARBfp:\n%s\n%s",
                      G_STRLOC,
                      gl_error,
-                     source,
+                     shader->source,
                      glGetString (GL_PROGRAM_ERROR_STRING_ARB));
         }
 #endif
@@ -177,44 +228,70 @@ cogl_shader_source (CoglHandle   handle,
   else
 #endif
     {
-      if (!shader->gl_handle)
+      char *sourcev[4];
+      int count = 0;
+      GLenum gl_type;
+
+      if (shader->gl_handle
+#ifdef HAVE_COGL_GLES2
+          && shader->n_tex_coord_attribs >= n_tex_coord_attribs
+#endif
+         )
+        return;
+
+      if (shader->gl_handle)
+        delete_shader (shader);
+
+      switch (shader->type)
         {
-          GLenum gl_type;
-
-          switch (shader->type)
-            {
-            case COGL_SHADER_TYPE_VERTEX:
-              gl_type = GL_VERTEX_SHADER;
-              break;
-            case COGL_SHADER_TYPE_FRAGMENT:
-              gl_type = GL_FRAGMENT_SHADER;
-              break;
-            default:
-              g_assert_not_reached ();
-              break;
-            }
-
-          shader->gl_handle = glCreateShader (gl_type);
+        case COGL_SHADER_TYPE_VERTEX:
+          gl_type = GL_VERTEX_SHADER;
+          break;
+        case COGL_SHADER_TYPE_FRAGMENT:
+          gl_type = GL_FRAGMENT_SHADER;
+          break;
+        default:
+          g_assert_not_reached ();
+          break;
         }
-      glShaderSource (shader->gl_handle, 1, &source, NULL);
+
+      shader->gl_handle = glCreateShader (gl_type);
+
+      sourcev[count++] = _COGL_COMMON_SHADER_BOILERPLATE;
+      if (shader->type == COGL_SHADER_TYPE_VERTEX)
+        sourcev[count++] = _COGL_VERTEX_SHADER_BOILERPLATE;
+      else
+        sourcev[count++] = _COGL_FRAGMENT_SHADER_BOILERPLATE;
+
+#ifdef HAVE_COGL_GLES2
+      if (n_tex_coord_attribs)
+        sourcev[count++] =
+          g_strdup_printf ("varying vec2 _cogl_tex_coord[%d];\n",
+                           n_tex_coord_attribs);
+      shader->n_tex_coord_attribs = n_tex_coord_attribs;
+#endif
+
+      sourcev[count++] = shader->source;
+
+      glShaderSource (shader->gl_handle, count, (const char **)sourcev, NULL);
+
+#ifdef HAVE_COGL_GLES2
+      if (count == 4)
+        g_free (sourcev[2]);
+#endif
+
+      GE (glCompileShader (shader->gl_handle));
+
+#ifdef COGL_GL_DEBUG
+      if (!cogl_shader_is_compiled (handle))
+        {
+          char *log = cogl_shader_get_info_log (handle);
+          g_warning ("Failed to compile GLSL program:\nsrc:\n%s\nerror:\n%s\n",
+                     shader->source,
+                     log);
+        }
+#endif
     }
-
-  shader->language = language;
-}
-
-void
-cogl_shader_compile (CoglHandle handle)
-{
-  CoglShader *shader;
-  _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
-  if (!cogl_is_shader (handle))
-    return;
-
-  shader = _cogl_shader_pointer_from_handle (handle);
-
-  if (shader->language == COGL_SHADER_LANGUAGE_GLSL)
-    GE (glCompileShader (shader->gl_handle));
 }
 
 char *
@@ -242,6 +319,21 @@ cogl_shader_get_info_log (CoglHandle handle)
     {
       char buffer[512];
       int len = 0;
+
+      /* We don't normally compile the shader when the user calls
+       * cogl_shader_compile() because we want to be able to add
+       * boilerplate code that depends on how it ends up finally being
+       * used.
+       *
+       * Here we force an early compile if the user is interested in
+       * log information to increase the chance that the log will be
+       * useful! We have to guess the number of texture coordinate
+       * attributes that may be used (normally less than 4) since that
+       * affects the boilerplate.
+       */
+      if (!shader->gl_handle)
+        _cogl_shader_compile_real (handle, 4);
+
       glGetShaderInfoLog (shader->gl_handle, 511, &len, buffer);
       buffer[len] = '\0';
       return g_strdup (buffer);
@@ -284,6 +376,24 @@ cogl_shader_is_compiled (CoglHandle handle)
   else
 #endif
     {
+      /* FIXME: We currently have an arbitrary limit of 4 texture
+       * coordinate attributes since our API means we have to add
+       * some boilerplate to the users GLSL program (for GLES2)
+       * before we actually know how many attributes are in use.
+       *
+       * 4 will probably be enough (or at least that limitation should
+       * be enough until we can replace this API with the pipeline
+       * snippets API) but if it isn't then the shader won't compile,
+       * through no fault of the user.
+       *
+       * To some extent this is just a symptom of bad API design; it
+       * was a mistake for Cogl to so thinly wrap the OpenGL shader
+       * API. Eventually we plan for this whole API will be deprecated
+       * by the pipeline snippets framework.
+       */
+      if (!shader->gl_handle)
+        _cogl_shader_compile_real (handle, 4);
+
       GE (glGetShaderiv (shader->gl_handle, GL_COMPILE_STATUS, &status));
       if (status == GL_TRUE)
         return TRUE;
diff --git a/cogl/cogl-vertex-attribute.c b/cogl/cogl-vertex-attribute.c
index 2b5682e57..199354b9c 100644
--- a/cogl/cogl-vertex-attribute.c
+++ b/cogl/cogl-vertex-attribute.c
@@ -435,6 +435,7 @@ enable_gl_state (CoglVertexAttribute **attributes,
   gboolean skip_gl_color = FALSE;
   CoglPipeline *source;
   CoglPipeline *copy = NULL;
+  int n_tex_coord_attribs = 0;
 
   _COGL_GET_CONTEXT (ctx, COGL_INVALID_HANDLE);
 
@@ -490,6 +491,7 @@ enable_gl_state (CoglVertexAttribute **attributes,
                                  base + attribute->offset));
           _cogl_bitmask_set (&ctx->temp_bitmask,
                              attribute->texture_unit, TRUE);
+          n_tex_coord_attribs++;
           break;
         case COGL_VERTEX_ATTRIBUTE_NAME_ID_POSITION_ARRAY:
           enable_flags |= COGL_ENABLE_VERTEX_ARRAY;
@@ -578,7 +580,7 @@ enable_gl_state (CoglVertexAttribute **attributes,
       _cogl_pipeline_apply_legacy_state (source);
     }
 
-  _cogl_pipeline_flush_gl_state (source, skip_gl_color);
+  _cogl_pipeline_flush_gl_state (source, skip_gl_color, n_tex_coord_attribs);
 
   if (ctx->enable_backface_culling)
     enable_flags |= COGL_ENABLE_BACKFACE_CULLING;
diff --git a/cogl/cogl-vertex-buffer.c b/cogl/cogl-vertex-buffer.c
index 192d4d561..47ac93a37 100644
--- a/cogl/cogl-vertex-buffer.c
+++ b/cogl/cogl-vertex-buffer.c
@@ -218,6 +218,79 @@ validate_gl_attribute (const char *gl_attribute,
   return type;
 }
 
+/* There are a number of standard OpenGL attributes that we deal with
+ * specially. These attributes are all namespaced with a "gl_" prefix
+ * so we should catch any typos instead of silently adding a custom
+ * attribute.
+ */
+static CoglVertexBufferAttribFlags
+validate_cogl_attribute (const char *cogl_attribute,
+		         guint8 n_components,
+		         guint8 *texture_unit)
+{
+  CoglVertexBufferAttribFlags type;
+  char *detail_seperator = NULL;
+  int name_len;
+
+  detail_seperator = strstr (cogl_attribute, "::");
+  if (detail_seperator)
+    name_len = detail_seperator - cogl_attribute;
+  else
+    name_len = strlen (cogl_attribute);
+
+  if (strncmp (cogl_attribute, "position_in", name_len) == 0)
+    {
+      if (G_UNLIKELY (n_components == 1))
+        g_critical ("glVertexPointer doesn't allow 1 component vertex "
+                    "positions so we currently only support "
+                    "\"cogl_position_in\" attributes where "
+                    "n_components == 2, 3 or 4");
+      type = COGL_VERTEX_BUFFER_ATTRIB_FLAG_VERTEX_ARRAY;
+    }
+  else if (strncmp (cogl_attribute, "color_in", name_len) == 0)
+    {
+      if (G_UNLIKELY (n_components != 3 && n_components != 4))
+        g_critical ("glColorPointer expects 3 or 4 component colors so we "
+                    "currently only support \"cogl_color_in\" attributes "
+                    "where n_components == 3 or 4");
+      type = COGL_VERTEX_BUFFER_ATTRIB_FLAG_COLOR_ARRAY;
+    }
+  else if (strncmp (cogl_attribute,
+		    "cogl_tex_coord",
+		    strlen ("cogl_tex_coord")) == 0)
+    {
+      unsigned int unit;
+
+      if (strcmp (cogl_attribute, "cogl_tex_coord_in") == 0)
+        unit = 0;
+      else if (sscanf (cogl_attribute, "cogl_tex_coord%u_in", &unit) != 1)
+	{
+	  g_warning ("texture coordinate attributes should either be "
+                     "referenced as \"cogl_tex_coord_in\" or with a"
+                     "texture unit number like \"cogl_tex_coord1_in\"");
+	  unit = 0;
+	}
+      /* FIXME: validate any '::' delimiter for this case */
+      *texture_unit = unit;
+      type = COGL_VERTEX_BUFFER_ATTRIB_FLAG_TEXTURE_COORD_ARRAY;
+    }
+  else if (strncmp (cogl_attribute, "normal_in", name_len) == 0)
+    {
+      if (G_UNLIKELY (n_components != 3))
+        g_critical ("glNormalPointer expects 3 component normals so we "
+                    "currently only support \"cogl_normal_in\" attributes "
+                    "where n_components == 3");
+      type = COGL_VERTEX_BUFFER_ATTRIB_FLAG_NORMAL_ARRAY;
+    }
+  else
+    {
+      g_warning ("Unknown cogl_* attribute name cogl_%s\n", cogl_attribute);
+      type = COGL_VERTEX_BUFFER_ATTRIB_FLAG_INVALID;
+    }
+
+  return type;
+}
+
 /* This validates that a custom attribute name is a valid GLSL variable name
  *
  * NB: attribute names may have a detail component delimited using '::' E.g.
@@ -402,8 +475,9 @@ cogl_vertex_buffer_add (CoglHandle         handle,
 
 	  attribute = submitted_attribute;
 
-	  /* since we will skip validate_gl_attribute in this case, we need
-	   * to pluck out the attribute type before overwriting the flags: */
+	  /* since we will skip validate_gl/cogl_attribute in this case, we
+           * need to pluck out the attribute type before overwriting the
+           * flags: */
 	  flags |=
             attribute->flags & COGL_VERTEX_BUFFER_ATTRIB_FLAG_TYPE_MASK;
 	  break;
@@ -424,6 +498,14 @@ cogl_vertex_buffer_add (CoglHandle         handle,
 	  if (flags & COGL_VERTEX_BUFFER_ATTRIB_FLAG_INVALID)
 	    return;
 	}
+      else if (strncmp (attribute_name, "cogl_", 5) == 0)
+	{
+	  flags |= validate_cogl_attribute (attribute_name + 5,
+					    n_components,
+					    &texture_unit);
+	  if (flags & COGL_VERTEX_BUFFER_ATTRIB_FLAG_INVALID)
+	    return;
+	}
       else
 	{
 	  flags |= COGL_VERTEX_BUFFER_ATTRIB_FLAG_CUSTOM_ARRAY;
diff --git a/cogl/cogl.c b/cogl/cogl.c
index e21b088b0..b1882ef80 100644
--- a/cogl/cogl.c
+++ b/cogl/cogl.c
@@ -745,6 +745,7 @@ void
 cogl_begin_gl (void)
 {
   unsigned long enable_flags = 0;
+  CoglPipeline *pipeline;
 
   _COGL_GET_CONTEXT (ctx, NO_RETVAL);
 
@@ -777,8 +778,21 @@ cogl_begin_gl (void)
    *
    * A user should instead call cogl_set_source_color4ub() before
    * cogl_begin_gl() to simplify the state flushed.
+   *
+   * XXX: note defining n_tex_coord_attribs using
+   * cogl_pipeline_get_n_layers is a hack, but the problem is that
+   * n_tex_coord_attribs is usually defined when drawing a primitive
+   * which isn't happening here.
+   *
+   * Maybe it would be more useful if this code did flush the
+   * opaque_color_pipeline and then call into cogl-pipeline-opengl.c to then
+   * restore all state for the material's backend back to default OpenGL
+   * values.
    */
-  _cogl_pipeline_flush_gl_state (cogl_get_source (), FALSE);
+  pipeline = cogl_get_source ();
+  _cogl_pipeline_flush_gl_state (pipeline,
+                                 FALSE,
+                                 cogl_pipeline_get_n_layers (pipeline));
 
   if (ctx->enable_backface_culling)
     enable_flags |= COGL_ENABLE_BACKFACE_CULLING;
diff --git a/cogl/driver/gles/cogl-fixed-fragment-shader.glsl b/cogl/driver/gles/cogl-fixed-fragment-shader.glsl
index 3f82deebb..1facee71f 100644
--- a/cogl/driver/gles/cogl-fixed-fragment-shader.glsl
+++ b/cogl/driver/gles/cogl-fixed-fragment-shader.glsl
@@ -7,8 +7,8 @@ precision highp float;
 /*** _cogl_fixed_fragment_shader_inputs ***/
 
 /* Inputs from the vertex shader */
-varying vec4       frag_color;
-varying float      fog_amount;
+varying vec4 _cogl_color;
+varying float _cogl_fog_amount;
 
 /*** _cogl_fixed_fragment_shader_texturing_options ***/
 
@@ -17,10 +17,10 @@ varying float      fog_amount;
 /*** _cogl_fixed_fragment_shader_fogging_options ***/
 
 /* Fogging options */
-uniform vec4       fog_color;
+uniform vec4 _cogl_fog_color;
 
 /* Alpha test options */
-uniform float      alpha_test_ref;
+uniform float _cogl_alpha_test_ref;
 
 /*** _cogl_fixed_fragment_shader_main_declare ***/
 
@@ -33,30 +33,32 @@ main (void)
   /*** _cogl_fixed_fragment_shader_fog ***/
 
   /* Mix the calculated color with the fog color */
-  gl_FragColor.rgb = mix (fog_color.rgb, gl_FragColor.rgb, fog_amount);
+  gl_FragColor.rgb = mix (_cogl_fog_color.rgb, gl_FragColor.rgb,
+                          _cogl_fog_amount);
 
   /* Alpha testing */
 
   /*** _cogl_fixed_fragment_shader_alpha_never ***/
   discard;
   /*** _cogl_fixed_fragment_shader_alpha_less ***/
-  if (gl_FragColor.a >= alpha_test_ref)
+  if (gl_FragColor.a >= _cogl_alpha_test_ref)
     discard;
   /*** _cogl_fixed_fragment_shader_alpha_equal ***/
-  if (gl_FragColor.a != alpha_test_ref)
+  if (gl_FragColor.a != _cogl_alpha_test_ref)
     discard;
   /*** _cogl_fixed_fragment_shader_alpha_lequal ***/
-  if (gl_FragColor.a > alpha_test_ref)
+  if (gl_FragColor.a > _cogl_alpha_test_ref)
     discard;
   /*** _cogl_fixed_fragment_shader_alpha_greater ***/
-  if (gl_FragColor.a <= alpha_test_ref)
+  if (gl_FragColor.a <= _cogl_alpha_test_ref)
     discard;
   /*** _cogl_fixed_fragment_shader_alpha_notequal ***/
-  if (gl_FragColor.a == alpha_test_ref)
+  if (gl_FragColor.a == _cogl_alpha_test_ref)
     discard;
   /*** _cogl_fixed_fragment_shader_alpha_gequal ***/
-  if (gl_FragColor.a < alpha_test_ref)
+  if (gl_FragColor.a < _cogl_alpha_test_ref)
     discard;
 
   /*** _cogl_fixed_fragment_shader_end ***/
 }
+
diff --git a/cogl/driver/gles/cogl-fixed-vertex-shader.glsl b/cogl/driver/gles/cogl-fixed-vertex-shader.glsl
index 0080477d3..f73f8b9a8 100644
--- a/cogl/driver/gles/cogl-fixed-vertex-shader.glsl
+++ b/cogl/driver/gles/cogl-fixed-vertex-shader.glsl
@@ -1,30 +1,30 @@
 /*** _cogl_fixed_vertex_shader_per_vertex_attribs ***/
 
 /* Per vertex attributes */
-attribute vec4     vertex_attrib;
-attribute vec4     color_attrib;
+attribute vec4 cogl_position_in;
+attribute vec4 cogl_color_in;
 
 /*** _cogl_fixed_vertex_shader_transform_matrices ***/
 
 /* Transformation matrices */
-uniform mat4       modelview_matrix;
-uniform mat4       mvp_matrix; /* combined modelview and projection matrix */
+uniform mat4 cogl_modelview_matrix;
+uniform mat4 cogl_modelview_projection_matrix; /* combined modelview and projection matrix */
 
 /*** _cogl_fixed_vertex_shader_output_variables ***/
 
 /* Outputs to the fragment shader */
-varying vec4       frag_color;
-varying float      fog_amount;
+varying vec4 _cogl_color;
+varying float _cogl_fog_amount;
 
 /*** _cogl_fixed_vertex_shader_fogging_options ***/
 
 /* Fogging options */
-uniform float      fog_density;
-uniform float      fog_start;
-uniform float      fog_end;
+uniform float _cogl_fog_density;
+uniform float _cogl_fog_start;
+uniform float _cogl_fog_end;
 
 /* Point options */
-uniform float      point_size;
+uniform float cogl_point_size_in;
 
 /*** _cogl_fixed_vertex_shader_main_start ***/
 
@@ -34,38 +34,40 @@ main (void)
   vec4 transformed_tex_coord;
 
   /* Calculate the transformed position */
-  gl_Position = mvp_matrix * vertex_attrib;
+  gl_Position = cogl_modelview_projection_matrix * cogl_position_in;
 
   /* Copy across the point size from the uniform */
-  gl_PointSize = point_size;
+  gl_PointSize = cogl_point_size_in;
 
   /* Calculate the transformed texture coordinate */
 
   /*** _cogl_fixed_vertex_shader_frag_color_start ***/
 
   /* Pass the interpolated vertex color on to the fragment shader */
-  frag_color = color_attrib;
+  _cogl_color = cogl_color_in;
 
   /*** _cogl_fixed_vertex_shader_fog_start ***/
 
   /* Estimate the distance from the eye using just the z-coordinate to
      use as the fog coord */
-  vec4 eye_coord = modelview_matrix * vertex_attrib;
+  vec4 eye_coord = cogl_modelview_matrix * cogl_position_in;
   float fog_coord = abs (eye_coord.z / eye_coord.w);
 
   /* Calculate the fog amount per-vertex and interpolate it for the
      fragment shader */
 
   /*** _cogl_fixed_vertex_shader_fog_exp ***/
-  fog_amount = exp (-fog_density * fog_coord);
+  _cogl_fog_amount = exp (-fog_density * fog_coord);
   /*** _cogl_fixed_vertex_shader_fog_exp2 ***/
-  fog_amount = exp (-fog_density * fog_coord
-		    * fog_density * fog_coord);
+  _cogl_fog_amount = exp (-_cogl_fog_density * fog_coord
+		    * _cogl_fog_density * fog_coord);
   /*** _cogl_fixed_vertex_shader_fog_linear ***/
-  fog_amount = (fog_end - fog_coord) / (fog_end - fog_start);
+  _cogl_fog_amount = (_cogl_fog_end - fog_coord) /
+                     (_cogl_fog_end - _cogl_fog_start);
 
   /*** _cogl_fixed_vertex_shader_fog_end ***/
-  fog_amount = clamp (fog_amount, 0.0, 1.0);
+  _cogl_fog_amount = clamp (_cogl_fog_amount, 0.0, 1.0);
 
   /*** _cogl_fixed_vertex_shader_end ***/
 }
+
diff --git a/cogl/driver/gles/cogl-gles2-wrapper.c b/cogl/driver/gles/cogl-gles2-wrapper.c
index 032872099..e557fd28e 100644
--- a/cogl/driver/gles/cogl-gles2-wrapper.c
+++ b/cogl/driver/gles/cogl-gles2-wrapper.c
@@ -318,7 +318,7 @@ cogl_gles2_get_vertex_shader (const CoglGles2WrapperSettings *settings)
   for (i = 0; i < COGL_GLES2_MAX_TEXTURE_UNITS; i++)
     if (COGL_GLES2_TEXTURE_UNIT_IS_ENABLED (settings->texture_units, i))
       g_string_append_printf (shader_source,
-			      "attribute vec4 multi_tex_coord_attrib%d;\n",
+			      "attribute vec4 cogl_tex_coord%d_in;\n",
 			      i);
 
   /* Find the biggest enabled texture unit index */
@@ -332,11 +332,11 @@ cogl_gles2_get_vertex_shader (const CoglGles2WrapperSettings *settings)
   if (n_texture_units > 0)
     {
       g_string_append_printf (shader_source,
-                              "uniform mat4	      texture_matrix[%d];\n",
+                              "uniform mat4 cogl_texture_matrix[%d];\n",
                               n_texture_units);
 
       g_string_append_printf (shader_source,
-                              "varying vec2       tex_coord[%d];",
+                              "varying vec2 _cogl_tex_coord[%d];",
                               n_texture_units);
     }
 
@@ -349,11 +349,11 @@ cogl_gles2_get_vertex_shader (const CoglGles2WrapperSettings *settings)
       {
         g_string_append_printf (shader_source,
                                 "transformed_tex_coord = "
-                                "texture_matrix[%d] "
-                                " * multi_tex_coord_attrib%d;\n",
+                                "cogl_texture_matrix[%d] "
+                                " * cogl_tex_coord%d_in;\n",
                                 i, i);
         g_string_append_printf (shader_source,
-                                "tex_coord[%d] = transformed_tex_coord.st "
+                                "_cogl_tex_coord[%d] = transformed_tex_coord.st "
                                 " / transformed_tex_coord.q;\n",
                                 i);
       }
@@ -410,19 +410,21 @@ cogl_gles2_add_texture_lookup (int unit,
   _COGL_GET_GLES2_WRAPPER (w, NO_RETVAL);
 
   if (w->settings.tex_env[unit].texture_target == GL_TEXTURE_3D_OES)
-    g_string_append_printf (shader_source, "texture3D (texture_unit[%d], ",
+    g_string_append_printf (shader_source,
+                            "texture3D (_cogl_texture_unit[%d], ",
                             unit);
   else
-    g_string_append_printf (shader_source, "texture2D (texture_unit[%d], ",
+    g_string_append_printf (shader_source,
+                            "texture2D (_cogl_texture_unit[%d], ",
                             unit);
 
   /* If point sprite coord generation is being used then divert to the
      built-in varying var for that instead of the texture
      coordinates */
   if (w->settings.tex_env[unit].point_sprite_coords)
-    g_string_append (shader_source, "gl_PointCoord");
+    g_string_append (shader_source, "_cogl_point_coord");
   else
-    g_string_append_printf (shader_source, "tex_coord[%d]", unit);
+    g_string_append_printf (shader_source, "_cogl_tex_coord[%d]", unit);
 
   g_string_append_printf (shader_source, ").%s", swizzle);
 }
@@ -458,7 +460,7 @@ cogl_gles2_add_arg (int unit,
       break;
 
     case GL_CONSTANT:
-      g_string_append_printf (shader_source, "combine_constant[%d].%s",
+      g_string_append_printf (shader_source, "_cogl_combine_constant[%d].%s",
                               unit, swizzle);
       break;
 
@@ -470,7 +472,7 @@ cogl_gles2_add_arg (int unit,
         }
       /* flow through */
     case GL_PRIMARY_COLOR:
-      g_string_append_printf (shader_source, "frag_color.%s", swizzle);
+      g_string_append_printf (shader_source, "_cogl_color.%s", swizzle);
       break;
 
     default:
@@ -635,13 +637,13 @@ cogl_gles2_get_fragment_shader (const CoglGles2WrapperSettings *settings)
   if (n_texture_units > 0)
     {
       g_string_append_printf (shader_source,
-                              "varying vec2       tex_coord[%d];\n",
+                              "varying vec2 _cogl_tex_coord[%d];\n",
                               n_texture_units);
 
       g_string_append (shader_source,
                        _cogl_fixed_fragment_shader_texturing_options);
       g_string_append_printf (shader_source,
-                              "uniform sampler2D  texture_unit[%d];\n",
+                              "uniform sampler2D _cogl_texture_unit[%d];\n",
                               n_texture_units);
     }
 
@@ -655,12 +657,12 @@ cogl_gles2_get_fragment_shader (const CoglGles2WrapperSettings *settings)
      apparent bug in the PowerVR drivers. Without it the alpha
      blending seems to stop working */
   g_string_append (shader_source,
-                   "vec4 frag_color_copy = frag_color;\n");
+                   "vec4 frag_color_copy = _cogl_color;\n");
 
   /* If there are no textures units enabled then we can just directly
      use the color from the vertex shader */
   if (n_texture_units == 0)
-    g_string_append (shader_source, "gl_FragColor = frag_color;\n");
+    g_string_append (shader_source, "gl_FragColor = _cogl_color;\n");
   else
     /* Otherwise we need to calculate the value based on the layer
        combine settings */
@@ -769,17 +771,17 @@ cogl_gles2_wrapper_get_locations (GLuint program,
   int i;
 
   uniforms->mvp_matrix_uniform
-    = glGetUniformLocation (program, "mvp_matrix");
+    = glGetUniformLocation (program, "cogl_modelview_projection_matrix");
   uniforms->modelview_matrix_uniform
-    = glGetUniformLocation (program, "modelview_matrix");
+    = glGetUniformLocation (program, "cogl_modelview_matrix");
 
   for (i = 0; i < COGL_GLES2_MAX_TEXTURE_UNITS; i++)
     if (COGL_GLES2_TEXTURE_UNIT_IS_ENABLED (settings->texture_units, i))
       {
-        char *matrix_var_name = g_strdup_printf ("texture_matrix[%d]", i);
-        char *sampler_var_name = g_strdup_printf ("texture_unit[%d]", i);
+        char *matrix_var_name = g_strdup_printf ("cogl_texture_matrix[%d]", i);
+        char *sampler_var_name = g_strdup_printf ("_cogl_texture_unit[%d]", i);
         char *tex_coord_var_name =
-          g_strdup_printf ("multi_tex_coord_attrib%d", i);
+          g_strdup_printf ("cogl_tex_coord%d_in", i);
 
         uniforms->texture_matrix_uniforms[i]
           = glGetUniformLocation (program, matrix_var_name);
@@ -800,30 +802,30 @@ cogl_gles2_wrapper_get_locations (GLuint program,
       }
 
   uniforms->fog_density_uniform
-    = glGetUniformLocation (program, "fog_density");
+    = glGetUniformLocation (program, "_cogl_fog_density");
   uniforms->fog_start_uniform
-    = glGetUniformLocation (program, "fog_start");
+    = glGetUniformLocation (program, "_cogl_fog_start");
   uniforms->fog_end_uniform
-    = glGetUniformLocation (program, "fog_end");
+    = glGetUniformLocation (program, "_cogl_fog_end");
   uniforms->fog_color_uniform
-    = glGetUniformLocation (program, "fog_color");
+    = glGetUniformLocation (program, "_cogl_fog_color");
 
   uniforms->alpha_test_ref_uniform
-    = glGetUniformLocation (program, "alpha_test_ref");
+    = glGetUniformLocation (program, "_cogl_alpha_test_ref");
 
   uniforms->point_size_uniform
-    = glGetUniformLocation (program, "point_size");
+    = glGetUniformLocation (program, "cogl_point_size_in");
 }
 
 static void
 cogl_gles2_wrapper_bind_attributes (GLuint program)
 {
   glBindAttribLocation (program, COGL_GLES2_WRAPPER_VERTEX_ATTRIB,
-			"vertex_attrib");
+			"cogl_position_in");
   glBindAttribLocation (program, COGL_GLES2_WRAPPER_COLOR_ATTRIB,
-			"color_attrib");
+			"cogl_color_in");
   glBindAttribLocation (program, COGL_GLES2_WRAPPER_NORMAL_ATTRIB,
-			"normal_attrib");
+			"cogl_normal_in");
 }
 
 static CoglGles2WrapperProgram *