diff --git a/cogl-texture.h b/cogl-texture.h
index 117a12b14..3ca0d8137 100644
--- a/cogl-texture.h
+++ b/cogl-texture.h
@@ -148,7 +148,7 @@ gboolean        cogl_is_texture               (CoglHandle          handle);
 /**
  * cogl_texture_get_width:
  * @handle: a #CoglHandle for a texture.
- * 
+ *
  * Query the width of a cogl texture.
  *
  * Returns: the width of the GPU side texture in pixels:
@@ -158,7 +158,7 @@ guint           cogl_texture_get_width        (CoglHandle          handle);
 /**
  * cogl_texture_get_height:
  * @handle: a #CoglHandle for a texture.
- * 
+ *
  * Query the height of a cogl texture.
  *
  * Returns: the height of the GPU side texture in pixels:
@@ -168,7 +168,7 @@ guint           cogl_texture_get_height       (CoglHandle          handle);
 /**
  * cogl_texture_get_format:
  * @handle: a #CoglHandle for a texture.
- * 
+ *
  * Query the #CoglPixelFormat of a cogl texture.
  *
  * Returns: the #CoglPixelFormat of the GPU side texture.
@@ -179,7 +179,7 @@ CoglPixelFormat cogl_texture_get_format       (CoglHandle          handle);
 /**
  * cogl_texture_get_rowstride:
  * @handle: a #CoglHandle for a texture.
- * 
+ *
  * Query the rowstride of a cogl texture.
  *
  * Returns: the offset in bytes between each consequetive row of pixels.
@@ -189,7 +189,7 @@ guint           cogl_texture_get_rowstride    (CoglHandle          handle);
 /**
  * cogl_texture_get_max_waste:
  * @handle: a #CoglHandle for a texture.
- * 
+ *
  * Query the maximum wasted (unused) pixels in one dimension of a GPU side
  * texture.
  *
@@ -200,7 +200,7 @@ gint            cogl_texture_get_max_waste    (CoglHandle          handle);
 /**
  * cogl_texture_get_min_filter:
  * @handle: a #CoglHandle for a texture.
- * 
+ *
  * Query the currently set downscaling filter for a cogl texture.
  *
  * Returns: the current downscaling filter for a cogl texture.
@@ -210,7 +210,7 @@ COGLenum        cogl_texture_get_min_filter   (CoglHandle          handle);
 /**
  * cogl_texture_get_mag_filter:
  * @handle: a #CoglHandle for a texture.
- * 
+ *
  * Query the currently set downscaling filter for a cogl texture.
  *
  * Returns: the current downscaling filter for a cogl texture.
@@ -220,7 +220,7 @@ COGLenum        cogl_texture_get_mag_filter   (CoglHandle          handle);
 /**
  * cogl_texture_is_sliced:
  * @handle: a #CoglHandle for a texture.
- * 
+ *
  * Query if a texture is sliced (stored as multiple GPU side tecture
  * objects).
  *
@@ -235,7 +235,7 @@ gboolean        cogl_texture_is_sliced        (CoglHandle          handle);
  * @out_gl_handle: pointer to return location for the textures GL handle, or
  * NULL.
  * @out_gl_target: pointer to return location for the GL target type, or NULL.
- * 
+ *
  * Query the GL handles for a GPU side texture through it's #CoglHandle,
  * if the texture is spliced the data for the first sub texture will be
  * queried.
@@ -255,7 +255,7 @@ gboolean        cogl_texture_get_gl_texture   (CoglHandle         handle,
  * specified.
  * @data: memory location to write contents of buffer, or %NULL if we're
  * only querying the data size through the return value.
- * 
+ *
  * Copy the pixel data from a cogl texture to system memory.
  *
  * Returns: the size of the texture data in bytes (or 0 if the texture
@@ -271,7 +271,7 @@ gint            cogl_texture_get_data         (CoglHandle          handle,
  * @handle: a #CoglHandle.
  * @min_filter: the filter used when scaling the texture down.
  * @mag_filter: the filter used when magnifying the texture.
- * 
+ *
  * Changes the decimation and interpolation filters used when the texture is
  * drawn at other scales than 100%.
  */
@@ -297,7 +297,7 @@ void            cogl_texture_set_filters      (CoglHandle          handle,
  * @data: the actual pixel data.
  *
  * Sets the pixels in a rectangular subregion of @handle from an in-memory
- * buffer containing pixel data. 
+ * buffer containing pixel data.
  *
  * Returns: %TRUE if the subregion upload was successful, otherwise %FALSE.
  */
@@ -385,6 +385,29 @@ void            cogl_texture_polygon          (CoglHandle          handle,
                                                CoglTextureVertex  *vertices,
                                                gboolean            use_color);
 
+/**
+ * cogl_texture_multiple_rectangles:
+ * @handle: a @CoglHandle.
+ * @verts: an array of vertices
+ * @n_rects: number of rectangles to draw
+ *
+ * Draws a series of rectangles in the same way that
+ * cogl_texture_rectangle() does. In some situations it can give a
+ * significant performance boost to use this function rather than
+ * calling cogl_texture_rectangle() separately for each rectangle.
+ *
+ * @verts should point to an array of #CoglFixed<!-- -->s with
+ * @n_rects * 8 elements. Each group of 8 values corresponds to the
+ * parameters x1, y1, x2, y2, tx1, ty1, tx2 and ty2 and have the same
+ * meaning as in cogl_texture_rectangle().
+ *
+ * Since: 1.0
+ */
+void            cogl_texture_multiple_rectangles
+                                              (CoglHandle          handle,
+                                               const CoglFixed    *verts,
+                                               guint               n_rects);
+
 G_END_DECLS
 
 #endif /* __COGL_TEXTURE_H__ */
diff --git a/doc/reference/cogl/cogl-sections.txt b/doc/reference/cogl/cogl-sections.txt
index 03247ff3c..dcd7c933f 100644
--- a/doc/reference/cogl/cogl-sections.txt
+++ b/doc/reference/cogl/cogl-sections.txt
@@ -120,6 +120,7 @@ cogl_texture_set_region
 cogl_texture_ref
 cogl_texture_unref
 cogl_texture_rectangle
+cogl_texture_multiple_rectangles
 cogl_texture_polygon
 </SECTION>
 
diff --git a/gl/cogl-context.c b/gl/cogl-context.c
index d75086fbc..e2421f4ff 100644
--- a/gl/cogl-context.c
+++ b/gl/cogl-context.c
@@ -41,27 +41,29 @@ cogl_create_context ()
 {
   if (_context != NULL)
     return FALSE;
-  
+
   /* Allocate context memory */
   _context = (CoglContext*) g_malloc (sizeof (CoglContext));
-  
+
   /* Init default values */
   _context->feature_flags = 0;
   _context->features_cached = FALSE;
-  
+
   _context->enable_flags = 0;
   _context->color_alpha = 255;
-  
+
   _context->path_nodes = g_array_new (FALSE, FALSE, sizeof (CoglPathNode));
   _context->last_path = 0;
-  
+
   _context->texture_handles = NULL;
-  _context->texture_vertices_size = 0;
-  _context->texture_vertices = NULL;
-  
+  _context->texture_vertices = g_array_new (FALSE, FALSE,
+                                            sizeof (CoglTextureGLVertex));
+  _context->texture_indices = g_array_new (FALSE, FALSE,
+                                           sizeof (GLushort));
+
   _context->fbo_handles = NULL;
   _context->draw_buffer = COGL_WINDOW_BUFFER;
-  
+
   _context->blend_src_factor = CGL_SRC_ALPHA;
   _context->blend_dst_factor = CGL_ONE_MINUS_SRC_ALPHA;
 
@@ -70,7 +72,7 @@ cogl_create_context ()
   _context->program_handles = NULL;
 
   _context->mesh_handles = NULL;
-  
+
   _context->pf_glGenRenderbuffersEXT = NULL;
   _context->pf_glBindRenderbufferEXT = NULL;
   _context->pf_glRenderbufferStorageEXT = NULL;
@@ -82,7 +84,7 @@ cogl_create_context ()
   _context->pf_glDeleteFramebuffersEXT = NULL;
   _context->pf_glBlitFramebufferEXT = NULL;
   _context->pf_glRenderbufferStorageMultisampleEXT = NULL;
-  
+
   _context->pf_glCreateProgramObjectARB = NULL;
   _context->pf_glCreateShaderObjectARB = NULL;
   _context->pf_glShaderSourceARB = NULL;
@@ -115,7 +117,7 @@ cogl_create_context ()
   _context->pf_glUniformMatrix4fvARB = NULL;
 
   _context->pf_glDrawRangeElements = NULL;
-  
+
   /* Init OpenGL state */
   GE( glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE) );
   GE( glColorMask (TRUE, TRUE, TRUE, FALSE) );
@@ -124,7 +126,7 @@ cogl_create_context ()
 
   /* Initialise the clip stack */
   _cogl_clip_stack_state_init ();
-  
+
   return TRUE;
 }
 
@@ -147,7 +149,12 @@ cogl_destroy_context ()
     g_array_free (_context->shader_handles, TRUE);
   if (_context->program_handles)
     g_array_free (_context->program_handles, TRUE);
-  
+
+  if (_context->texture_vertices)
+    g_array_free (_context->texture_vertices, TRUE);
+  if (_context->texture_indices)
+    g_array_free (_context->texture_indices, TRUE);
+
   g_free (_context);
 }
 
@@ -157,6 +164,6 @@ _cogl_context_get_default ()
   /* Create if doesn't exist yet */
   if (_context == NULL)
     cogl_create_context ();
-  
+
   return _context;
 }
diff --git a/gl/cogl-context.h b/gl/cogl-context.h
index 8a2fc877d..d49330763 100644
--- a/gl/cogl-context.h
+++ b/gl/cogl-context.h
@@ -41,7 +41,7 @@ typedef struct
   /* Features cache */
   CoglFeatureFlags  feature_flags;
   gboolean          features_cached;
-  
+
   /* Enable cache */
   gulong            enable_flags;
   guint8            color_alpha;
@@ -49,7 +49,7 @@ typedef struct
   COGLenum          blend_dst_factor;
 
   gboolean          enable_backface_culling;
-  
+
   /* Primitives */
   CoglFixedVec2     path_start;
   CoglFixedVec2     path_pen;
@@ -60,12 +60,18 @@ typedef struct
 
   /* Cache of inverse projection matrix */
   GLfloat           inverse_projection[16];
-  
+
   /* Textures */
   GArray	      *texture_handles;
-  CoglTextureGLVertex *texture_vertices;
-  gulong               texture_vertices_size;
-  
+  GArray              *texture_vertices;
+  GArray              *texture_indices;
+  /* The gl texture number that the above vertices apply to. This to
+     detect when a different slice is encountered so that the vertices
+     can be flushed */
+  GLuint               texture_current;
+  GLenum               texture_target;
+  GLenum               texture_wrap_mode;
+
   /* Framebuffer objects */
   GArray           *fbo_handles;
   CoglBufferTarget  draw_buffer;
@@ -78,10 +84,10 @@ typedef struct
 
   /* Clip stack */
   CoglClipStackState clip;
-  
+
   /* Mesh */
   GArray           *mesh_handles;
-  
+
   /* Relying on glext.h to define these */
   COGL_PFNGLGENRENDERBUFFERSEXTPROC                pf_glGenRenderbuffersEXT;
   COGL_PFNGLDELETERENDERBUFFERSEXTPROC             pf_glDeleteRenderbuffersEXT;
@@ -95,7 +101,7 @@ typedef struct
   COGL_PFNGLDELETEFRAMEBUFFERSEXTPROC              pf_glDeleteFramebuffersEXT;
   COGL_PFNGLBLITFRAMEBUFFEREXTPROC                 pf_glBlitFramebufferEXT;
   COGL_PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC  pf_glRenderbufferStorageMultisampleEXT;
-  
+
   COGL_PFNGLCREATEPROGRAMOBJECTARBPROC             pf_glCreateProgramObjectARB;
   COGL_PFNGLCREATESHADEROBJECTARBPROC              pf_glCreateShaderObjectARB;
   COGL_PFNGLSHADERSOURCEARBPROC                    pf_glShaderSourceARB;
@@ -151,6 +157,6 @@ _cogl_context_get_default ();
 CoglContext *ctxvar = _cogl_context_get_default (); \
 if (ctxvar == NULL) return retval;
 
-#define NO_RETVAL 
+#define NO_RETVAL
 
 #endif /* __COGL_CONTEXT_H */
diff --git a/gl/cogl-texture.c b/gl/cogl-texture.c
index 5a202ae6b..a27a8b253 100644
--- a/gl/cogl-texture.c
+++ b/gl/cogl-texture.c
@@ -76,7 +76,7 @@ _cogl_texture_bitmap_free (CoglTexture *tex)
 {
   if (tex->bitmap.data != NULL && tex->bitmap_owner)
     g_free (tex->bitmap.data);
-  
+
   tex->bitmap.data = NULL;
   tex->bitmap_owner = FALSE;
 }
@@ -87,7 +87,7 @@ _cogl_texture_bitmap_swap (CoglTexture     *tex,
 {
   if (tex->bitmap.data != NULL && tex->bitmap_owner)
     g_free (tex->bitmap.data);
-  
+
   tex->bitmap = *new_bitmap;
   tex->bitmap_owner = TRUE;
 }
@@ -99,11 +99,11 @@ _cogl_span_iter_update (CoglSpanIter *iter)
   iter->span = &g_array_index (iter->array,
 			       CoglTexSliceSpan,
 			       iter->index);
-  
+
   /* Offset next position by span size */
   iter->next_pos = iter->pos +
     COGL_FIXED_FROM_INT (iter->span->size - iter->span->waste);
-  
+
   /* Check if span intersects the area to cover */
   if (iter->next_pos <= iter->cover_start ||
       iter->pos >= iter->cover_end)
@@ -112,15 +112,15 @@ _cogl_span_iter_update (CoglSpanIter *iter)
       iter->intersects = FALSE;
       return;
     }
-  
+
   iter->intersects = TRUE;
-  
+
   /* Clip start position to coverage area */
   if (iter->pos < iter->cover_start)
     iter->intersect_start = iter->cover_start;
   else
     iter->intersect_start = iter->pos;
-  
+
   /* Clip end position to coverage area */
   if (iter->next_pos > iter->cover_end)
     iter->intersect_end = iter->cover_end;
@@ -143,7 +143,7 @@ _cogl_span_iter_begin (CoglSpanIter  *iter,
   iter->cover_start = cover_start;
   iter->cover_end = cover_end;
   iter->pos = iter->origin;
-  
+
   /* Update intersection */
   _cogl_span_iter_update (iter);
 }
@@ -153,10 +153,10 @@ _cogl_span_iter_next (CoglSpanIter *iter)
 {
   /* Move current position */
   iter->pos = iter->next_pos;
-  
+
   /* Pick next slice (wrap when last reached) */
   iter->index = (iter->index + 1) % iter->array->len;
-  
+
   /* Update intersection */
   _cogl_span_iter_update (iter);
 }
@@ -175,10 +175,10 @@ prep_for_gl_pixels_upload (gint	       pixels_rowstride,
 			   gint	       pixels_bpp)
 {
   GE( glPixelStorei (GL_UNPACK_ROW_LENGTH, pixels_rowstride / pixels_bpp) );
-  
+
   GE( glPixelStorei (GL_UNPACK_SKIP_PIXELS, pixels_src_x) );
   GE( glPixelStorei (GL_UNPACK_SKIP_ROWS, pixels_src_y) );
-  
+
   if (!(pixels_rowstride & 0x7))
     GE( glPixelStorei (GL_UNPACK_ALIGNMENT, 8) );
   else if (!(pixels_rowstride & 0x3))
@@ -240,7 +240,7 @@ _cogl_texture_upload_to_gl (CoglTexture *tex)
   gint               bpp;
   gint               x,y;
   guchar            *waste_buf;
-  
+
   bpp = _cogl_get_format_bpp (tex->bitmap.format);
 
   waste_buf = _cogl_texture_allocate_waste_buffer (tex);
@@ -249,22 +249,22 @@ _cogl_texture_upload_to_gl (CoglTexture *tex)
   for (y = 0; y < tex->slice_y_spans->len; ++y)
     {
       y_span = &g_array_index (tex->slice_y_spans, CoglTexSliceSpan, y);
-	
+
       /* Iterate horizontal slices */
       for (x = 0; x < tex->slice_x_spans->len; ++x)
 	{
 	  x_span = &g_array_index (tex->slice_x_spans, CoglTexSliceSpan, x);
-	  
+
 	  /* Pick the gl texture object handle */
 	  gl_handle = g_array_index (tex->slice_gl_handles, GLuint,
 				     y * tex->slice_x_spans->len + x);
-	  
+
 	  /* Setup gl alignment to match rowstride and top-left corner */
 	  prep_for_gl_pixels_upload (tex->bitmap.rowstride,
 				     x_span->start,
 				     y_span->start,
 				     bpp);
-	  
+
 	  /* Upload new image data */
 	  GE( glBindTexture (tex->gl_target, gl_handle) );
 
@@ -364,27 +364,27 @@ _cogl_texture_download_from_gl (CoglTexture *tex,
   gint               bpp;
   gint               x,y;
   CoglBitmap         slice_bmp;
-  
+
   bpp = _cogl_get_format_bpp (target_bmp->format);
-  
+
   /* Iterate vertical slices */
   for (y = 0; y < tex->slice_y_spans->len; ++y)
     {
       y_span = &g_array_index (tex->slice_y_spans, CoglTexSliceSpan, y);
-      
+
       /* Iterate horizontal slices */
       for (x = 0; x < tex->slice_x_spans->len; ++x)
 	{
 	  /*if (x != 0 || y != 1) continue;*/
 	  x_span = &g_array_index (tex->slice_x_spans, CoglTexSliceSpan, x);
-	  
+
 	  /* Pick the gl texture object handle */
 	  gl_handle = g_array_index (tex->slice_gl_handles, GLuint,
 				     y * tex->slice_x_spans->len + x);
-	  
+
 	  /* If there's any waste we need to copy manually
              (no glGetTexSubImage) */
-	  
+
 	  if (y_span->waste != 0 || x_span->waste != 0)
 	    {
 	      /* Setup temp bitmap for slice subregion */
@@ -394,19 +394,19 @@ _cogl_texture_download_from_gl (CoglTexture *tex,
 	      slice_bmp.rowstride = bpp * slice_bmp.width;
 	      slice_bmp.data = (guchar*) g_malloc (slice_bmp.rowstride *
 						   slice_bmp.height);
-	      
+
 	      /* Setup gl alignment to 0,0 top-left corner */
 	      prep_for_gl_pixels_download (slice_bmp.rowstride);
-	      
+
 	      /* Download slice image data into temp bmp */
 	      GE( glBindTexture (tex->gl_target, gl_handle) );
-	      
+
 	      GE (glGetTexImage (tex->gl_target,
 				 0, /* level */
 				 target_gl_format,
 				 target_gl_type,
 				 slice_bmp.data) );
-	      
+
 	      /* Copy portion of slice from temp to target bmp */
 	      _cogl_bitmap_copy_subregion (&slice_bmp,
 					   target_bmp,
@@ -425,10 +425,10 @@ _cogl_texture_download_from_gl (CoglTexture *tex,
 			    + y_span->start * target_bmp->rowstride;
 
 	      prep_for_gl_pixels_download (target_bmp->rowstride);
-	      
+
 	      /* Download slice image data */
 	      GE( glBindTexture (tex->gl_target, gl_handle) );
-	      
+
 	      GE( glGetTexImage (tex->gl_target,
 				 0, /* level */
 				 target_gl_format,
@@ -437,7 +437,7 @@ _cogl_texture_download_from_gl (CoglTexture *tex,
 	    }
 	}
     }
-  
+
   return TRUE;
 }
 
@@ -463,7 +463,7 @@ _cogl_texture_upload_subregion_to_gl (CoglTexture *tex,
   gint              inter_w = 0, inter_h = 0;
   gint              local_x = 0, local_y = 0;
   guchar           *waste_buf;
-  
+
   bpp = _cogl_get_format_bpp (source_bmp->format);
 
   waste_buf = _cogl_texture_allocate_waste_buffer (tex);
@@ -473,9 +473,9 @@ _cogl_texture_upload_subregion_to_gl (CoglTexture *tex,
        _cogl_span_iter_begin (&y_iter, tex->slice_y_spans,
 			      0, COGL_FIXED_FROM_INT (dst_y),
 			      COGL_FIXED_FROM_INT (dst_y + height));
-       
+
        !_cogl_span_iter_end (&y_iter);
-       
+
        _cogl_span_iter_next (&y_iter),
        source_y += inter_h )
     {
@@ -494,9 +494,9 @@ _cogl_texture_upload_subregion_to_gl (CoglTexture *tex,
 	   _cogl_span_iter_begin (&x_iter, tex->slice_x_spans,
 				  0, COGL_FIXED_FROM_INT (dst_x),
 				  COGL_FIXED_FROM_INT (dst_x + width));
-	   
+
 	   !_cogl_span_iter_end (&x_iter);
-	   
+
 	   _cogl_span_iter_next (&x_iter),
 	   source_x += inter_w )
         {
@@ -515,27 +515,27 @@ _cogl_texture_upload_subregion_to_gl (CoglTexture *tex,
 			               x_iter.intersect_start);
 	  inter_h = COGL_FIXED_TO_INT (y_iter.intersect_end -
 				       y_iter.intersect_start);
-	  
+
 	  /* Localize intersection top-left corner to slice*/
 	  local_x = COGL_FIXED_TO_INT (x_iter.intersect_start -
 				       x_iter.pos);
 	  local_y = COGL_FIXED_TO_INT (y_iter.intersect_start -
 				       y_iter.pos);
-	  
+
 	  /* Pick slice GL handle */
 	  gl_handle = g_array_index (tex->slice_gl_handles, GLuint,
 				     y_iter.index * tex->slice_x_spans->len +
 				     x_iter.index);
-	  
+
 	  /* Setup gl alignment to match rowstride and top-left corner */
 	  prep_for_gl_pixels_upload (source_bmp->rowstride,
 				     source_x,
 				     source_y,
 				     bpp);
-	  
+
 	  /* Upload new image data */
 	  GE( glBindTexture (tex->gl_target, gl_handle) );
-	  
+
 	  GE( glTexSubImage2D (tex->gl_target, 0,
 			       local_x, local_y,
 			       inter_w, inter_h,
@@ -657,12 +657,12 @@ _cogl_rect_slices_for_size (gint     size_to_fill,
 {
   gint             n_spans = 0;
   CoglTexSliceSpan span;
-  
+
   /* Init first slice span */
   span.start = 0;
   span.size = max_span_size;
   span.waste = 0;
-  
+
   /* Repeat until whole area covered */
   while (size_to_fill >= span.size)
     {
@@ -672,7 +672,7 @@ _cogl_rect_slices_for_size (gint     size_to_fill,
       size_to_fill -= span.size;
       n_spans++;
     }
-  
+
   /* Add one last smaller slice span */
   if (size_to_fill > 0)
     {
@@ -680,7 +680,7 @@ _cogl_rect_slices_for_size (gint     size_to_fill,
       if (out_spans) g_array_append_val (out_spans, span);
       n_spans++;
     }
-  
+
   return n_spans;
 }
 
@@ -692,15 +692,15 @@ _cogl_pot_slices_for_size (gint     size_to_fill,
 {
   gint             n_spans = 0;
   CoglTexSliceSpan span;
-  
+
   /* Init first slice span */
   span.start = 0;
   span.size = max_span_size;
   span.waste = 0;
-  
+
   /* Fix invalid max_waste */
   if (max_waste < 0) max_waste = 0;
-  
+
   while (TRUE)
     {
       /* Is the whole area covered? */
@@ -729,7 +729,7 @@ _cogl_pot_slices_for_size (gint     size_to_fill,
 	    }
 	}
     }
-  
+
   /* Can't get here */
   return 0;
 }
@@ -744,7 +744,7 @@ _cogl_texture_size_supported (GLenum gl_target,
   if (gl_target ==  GL_TEXTURE_2D)
     {
       /* Proxy texture allows for a quick check for supported size */
-      
+
       GLint new_width = 0;
 
       GE( glTexImage2D (GL_PROXY_TEXTURE_2D, 0, GL_RGBA,
@@ -788,7 +788,7 @@ _cogl_texture_set_wrap_mode_parameter (CoglTexture *tex,
 
 static gboolean
 _cogl_texture_slices_create (CoglTexture *tex)
-{  
+{
   gint              bpp;
   gint              max_width;
   gint              max_height;
@@ -800,11 +800,11 @@ _cogl_texture_slices_create (CoglTexture *tex)
   CoglTexSliceSpan *x_span;
   CoglTexSliceSpan *y_span;
   const GLfloat     transparent_color[4] = { 0x00, 0x00, 0x00, 0x00 };
-  
+
   gint   (*slices_for_size) (gint, gint, gint, GArray*);
-  
+
   bpp = _cogl_get_format_bpp (tex->bitmap.format);
-  
+
   /* Initialize size of largest slice according to supported features */
   if (cogl_features_available (COGL_FEATURE_TEXTURE_NPOT))
     {
@@ -820,12 +820,12 @@ _cogl_texture_slices_create (CoglTexture *tex)
       tex->gl_target = GL_TEXTURE_2D;
       slices_for_size = _cogl_pot_slices_for_size;
     }
-  
+
   /* Negative number means no slicing forced by the user */
   if (tex->max_waste <= -1)
     {
       CoglTexSliceSpan span;
-      
+
       /* Check if size supported else bail out */
       if (!_cogl_texture_size_supported (tex->gl_target,
 					tex->gl_format,
@@ -835,25 +835,25 @@ _cogl_texture_slices_create (CoglTexture *tex)
 	{
 	  return FALSE;
 	}
-      
+
       n_x_slices = 1;
       n_y_slices = 1;
-      
-      /* Init span arrays */      
+
+      /* Init span arrays */
       tex->slice_x_spans = g_array_sized_new (FALSE, FALSE,
 					      sizeof (CoglTexSliceSpan),
 					      1);
-      
+
       tex->slice_y_spans = g_array_sized_new (FALSE, FALSE,
 					      sizeof (CoglTexSliceSpan),
 					      1);
-      
+
       /* Add a single span for width and height */
       span.start = 0;
       span.size = max_width;
       span.waste = max_width - tex->bitmap.width;
       g_array_append_val (tex->slice_x_spans, span);
-      
+
       span.size = max_height;
       span.waste = max_height - tex->bitmap.height;
       g_array_append_val (tex->slice_y_spans, span);
@@ -872,46 +872,46 @@ _cogl_texture_slices_create (CoglTexture *tex)
 	    max_width /= 2;
 	  else
 	    max_height /= 2;
-	  
+
 	  if (max_width == 0 || max_height == 0)
 	    return FALSE;
 	}
-      
+
       /* Determine the slices required to cover the bitmap area */
       n_x_slices = slices_for_size (tex->bitmap.width,
 				    max_width, tex->max_waste,
 				    NULL);
-      
+
       n_y_slices = slices_for_size (tex->bitmap.height,
 				    max_height, tex->max_waste,
 				    NULL);
-  
+
       /* Init span arrays with reserved size */
       tex->slice_x_spans = g_array_sized_new (FALSE, FALSE,
 					      sizeof (CoglTexSliceSpan),
 					      n_x_slices);
-      
+
       tex->slice_y_spans = g_array_sized_new (FALSE, FALSE,
 					      sizeof (CoglTexSliceSpan),
 					      n_y_slices);
-      
+
       /* Fill span arrays with info */
       slices_for_size (tex->bitmap.width,
 		       max_width, tex->max_waste,
 		       tex->slice_x_spans);
-      
+
       slices_for_size (tex->bitmap.height,
 		       max_height, tex->max_waste,
 		       tex->slice_y_spans);
     }
-  
+
   /* Init and resize GL handle array */
   n_slices = n_x_slices * n_y_slices;
-  
+
   tex->slice_gl_handles = g_array_sized_new (FALSE, FALSE,
 					     sizeof (GLuint),
 					     n_slices);
-  
+
   g_array_set_size (tex->slice_gl_handles, n_slices);
 
   /* Wrap mode not yet set */
@@ -921,19 +921,19 @@ _cogl_texture_slices_create (CoglTexture *tex)
    * (some implementations might supported faster
    *  re-binding between textures inside a set) */
   gl_handles = (GLuint*) tex->slice_gl_handles->data;
-  
+
   GE( glGenTextures (n_slices, gl_handles) );
-  
-  
+
+
   /* Init each GL texture object */
   for (y = 0; y < n_y_slices; ++y)
     {
       y_span = &g_array_index (tex->slice_y_spans, CoglTexSliceSpan, y);
-      
+
       for (x = 0; x < n_x_slices; ++x)
 	{
 	  x_span = &g_array_index (tex->slice_x_spans, CoglTexSliceSpan, x);
-	  
+
 #if COGL_DEBUG
 	  printf ("CREATE SLICE (%d,%d)\n", x,y);
 	  printf ("size: (%d x %d)\n",
@@ -964,19 +964,19 @@ _cogl_texture_slices_create (CoglTexture *tex)
 			    tex->gl_format, tex->gl_type, 0) );
 	}
     }
-  
+
   return TRUE;
 }
 
 static void
 _cogl_texture_slices_free (CoglTexture *tex)
-{ 
+{
   if (tex->slice_x_spans != NULL)
     g_array_free (tex->slice_x_spans, TRUE);
-  
+
   if (tex->slice_y_spans != NULL)
     g_array_free (tex->slice_y_spans, TRUE);
-  
+
   if (tex->slice_gl_handles != NULL)
     {
       if (tex->is_foreign == FALSE)
@@ -984,7 +984,7 @@ _cogl_texture_slices_free (CoglTexture *tex)
 	  GE( glDeleteTextures (tex->slice_gl_handles->len,
 				(GLuint*) tex->slice_gl_handles->data) );
 	}
-      
+
       g_array_free (tex->slice_gl_handles, TRUE);
     }
 }
@@ -998,34 +998,34 @@ _cogl_pixel_format_from_gl_internal (GLenum            gl_int_format,
      is re-matched against cogl when getting or setting
      texture image data.
   */
-  
+
   switch (gl_int_format)
     {
     case GL_ALPHA: case GL_ALPHA4: case GL_ALPHA8:
     case GL_ALPHA12: case GL_ALPHA16:
-      
+
       *out_format = COGL_PIXEL_FORMAT_A_8;
       return TRUE;
-      
+
     case GL_LUMINANCE: case GL_LUMINANCE4: case GL_LUMINANCE8:
     case GL_LUMINANCE12: case GL_LUMINANCE16:
-      
+
       *out_format = COGL_PIXEL_FORMAT_G_8;
       return TRUE;
-      
+
     case GL_RGB: case GL_RGB4: case GL_RGB5: case GL_RGB8:
     case GL_RGB10: case GL_RGB12: case GL_RGB16: case GL_R3_G3_B2:
-      
+
       *out_format = COGL_PIXEL_FORMAT_RGB_888;
       return TRUE;
-      
+
     case GL_RGBA: case GL_RGBA2: case GL_RGBA4: case GL_RGB5_A1:
     case GL_RGBA8: case GL_RGB10_A2: case GL_RGBA12: case GL_RGBA16:
-      
+
       *out_format = COGL_PIXEL_FORMAT_RGBA_8888;
       return TRUE;
     }
-  
+
   return FALSE;
 }
 
@@ -1039,17 +1039,17 @@ _cogl_pixel_format_to_gl (CoglPixelFormat  format,
   GLenum          glintformat = 0;
   GLenum          glformat = 0;
   GLenum          gltype = 0;
-  
+
   /* No premultiplied formats accepted  by GL
    * (FIXME: latest hardware?) */
-  
+
   if (format & COGL_PREMULT_BIT)
     format = (format & COGL_UNPREMULT_MASK);
-  
+
   /* Everything else accepted
    * (FIXME: check YUV support) */
   required_format = format;
-  
+
   /* Find GL equivalents */
   switch (format)
     {
@@ -1063,7 +1063,7 @@ _cogl_pixel_format_to_gl (CoglPixelFormat  format,
       glformat = GL_LUMINANCE;
       gltype = GL_UNSIGNED_BYTE;
       break;
-      
+
     case COGL_PIXEL_FORMAT_RGB_888:
       glintformat = GL_RGB;
       glformat = GL_RGB;
@@ -1084,7 +1084,7 @@ _cogl_pixel_format_to_gl (CoglPixelFormat  format,
       glformat = GL_BGRA;
       gltype = GL_UNSIGNED_BYTE;
       break;
-      
+
       /* The following two types of channel ordering
        * have no GL equivalent unless defined using
        * system word byte ordering */
@@ -1097,7 +1097,7 @@ _cogl_pixel_format_to_gl (CoglPixelFormat  format,
       gltype = GL_UNSIGNED_INT_8_8_8_8_REV;
 #endif
       break;
-      
+
     case COGL_PIXEL_FORMAT_ABGR_8888:
       glintformat = GL_RGBA;
       glformat = GL_RGBA;
@@ -1107,7 +1107,7 @@ _cogl_pixel_format_to_gl (CoglPixelFormat  format,
       gltype = GL_UNSIGNED_INT_8_8_8_8_REV;
 #endif
       break;
-      
+
       /* The following three types of channel ordering
        * are always defined using system word byte
        * ordering (even according to GLES spec) */
@@ -1126,19 +1126,19 @@ _cogl_pixel_format_to_gl (CoglPixelFormat  format,
       glformat = GL_RGBA;
       gltype = GL_UNSIGNED_SHORT_5_5_5_1;
       break;
-      
+
       /* FIXME: check extensions for YUV support */
     default:
       break;
     }
-  
+
   if (out_glintformat != NULL)
     *out_glintformat = glintformat;
   if (out_glformat != NULL)
     *out_glformat = glformat;
   if (out_gltype != NULL)
     *out_gltype = gltype;
-  
+
   return required_format;
 }
 
@@ -1149,7 +1149,7 @@ _cogl_texture_bitmap_prepare (CoglTexture     *tex,
   CoglBitmap        new_bitmap;
   CoglPixelFormat   new_data_format;
   gboolean          success;
-  
+
   /* Was there any internal conversion requested? */
   if (internal_format == COGL_PIXEL_FORMAT_ANY)
     internal_format = tex->bitmap.format;
@@ -1159,21 +1159,21 @@ _cogl_texture_bitmap_prepare (CoglTexture     *tex,
 					      &tex->gl_intformat,
 					      &tex->gl_format,
 					      &tex->gl_type);
-  
+
   /* Convert to internal format */
   if (new_data_format != tex->bitmap.format)
     {
       success = _cogl_bitmap_convert_and_premult (&tex->bitmap,
 						  &new_bitmap,
 						  new_data_format);
-      
+
       if (!success)
 	return FALSE;
-      
+
       /* Update texture with new data */
       _cogl_texture_bitmap_swap (tex, &new_bitmap);
     }
-  
+
   return TRUE;
 }
 
@@ -1197,15 +1197,15 @@ cogl_texture_new_with_size (guint           width,
   CoglTexture *tex;
   gint         bpp;
   gint         rowstride;
-  
+
   /* Since no data, we need some internal format */
   if (internal_format == COGL_PIXEL_FORMAT_ANY)
     return COGL_INVALID_HANDLE;
-  
+
   /* Rowstride from width */
   bpp = _cogl_get_format_bpp (internal_format);
   rowstride = width * bpp;
-  
+
   /* Init texture with empty bitmap */
   tex = (CoglTexture*) g_malloc (sizeof (CoglTexture));
 
@@ -1214,36 +1214,36 @@ cogl_texture_new_with_size (guint           width,
 
   tex->is_foreign = FALSE;
   tex->auto_mipmap = auto_mipmap;
-  
+
   tex->bitmap.width = width;
   tex->bitmap.height = height;
   tex->bitmap.format = internal_format;
   tex->bitmap.rowstride = rowstride;
   tex->bitmap.data = NULL;
   tex->bitmap_owner = FALSE;
-  
+
   tex->slice_x_spans = NULL;
   tex->slice_y_spans = NULL;
   tex->slice_gl_handles = NULL;
-  
+
   tex->max_waste = max_waste;
   tex->min_filter = CGL_NEAREST;
   tex->mag_filter = CGL_NEAREST;
-  
+
   /* Find closest GL format match */
   tex->bitmap.format =
     _cogl_pixel_format_to_gl (internal_format,
 			      &tex->gl_intformat,
 			      &tex->gl_format,
 			      &tex->gl_type);
-  
+
   /* Create slices for the given format and size */
   if (!_cogl_texture_slices_create (tex))
     {
       _cogl_texture_free (tex);
       return COGL_INVALID_HANDLE;
     }
-  
+
   return _cogl_texture_handle_new (tex);
 }
 
@@ -1259,20 +1259,20 @@ cogl_texture_new_from_data (guint              width,
 {
   CoglTexture *tex;
   gint         bpp;
-  
+
   if (format == COGL_PIXEL_FORMAT_ANY)
     return COGL_INVALID_HANDLE;
-  
+
   if (data == NULL)
     return COGL_INVALID_HANDLE;
-  
+
   /* Rowstride from width if not given */
   bpp = _cogl_get_format_bpp (format);
   if (rowstride == 0) rowstride = width * bpp;
-  
+
   /* Create new texture and fill with given data */
   tex = (CoglTexture*) g_malloc (sizeof (CoglTexture));
-  
+
   tex->ref_count = 1;
   COGL_HANDLE_DEBUG_NEW (texture, tex);
 
@@ -1285,40 +1285,40 @@ cogl_texture_new_from_data (guint              width,
   tex->bitmap.format = format;
   tex->bitmap.rowstride = rowstride;
   tex->bitmap_owner = FALSE;
-  
+
   tex->slice_x_spans = NULL;
   tex->slice_y_spans = NULL;
   tex->slice_gl_handles = NULL;
-  
+
   tex->max_waste = max_waste;
   tex->min_filter = CGL_NEAREST;
   tex->mag_filter = CGL_NEAREST;
-  
+
   /* FIXME: If upload fails we should set some kind of
    * error flag but still return texture handle (this
    * is to keep the behavior equal to _new_from_file;
    * see below) */
-  
+
   if (!_cogl_texture_bitmap_prepare (tex, internal_format))
     {
       _cogl_texture_free (tex);
       return COGL_INVALID_HANDLE;
     }
-  
+
   if (!_cogl_texture_slices_create (tex))
     {
       _cogl_texture_free (tex);
       return COGL_INVALID_HANDLE;
     }
-  
+
   if (!_cogl_texture_upload_to_gl (tex))
     {
       _cogl_texture_free (tex);
       return COGL_INVALID_HANDLE;
     }
-  
+
   _cogl_texture_bitmap_free (tex);
-  
+
   return _cogl_texture_handle_new (tex);
 }
 
@@ -1331,7 +1331,7 @@ cogl_texture_new_from_file (const gchar     *filename,
 {
   CoglBitmap   bmp;
   CoglTexture *tex;
-  
+
   g_return_val_if_fail (error == NULL || *error == NULL, COGL_INVALID_HANDLE);
 
   /* Try loading with imaging backend */
@@ -1346,27 +1346,27 @@ cogl_texture_new_from_file (const gchar     *filename,
 	  *error = NULL;
 	}
     }
-  
+
   /* Create new texture and fill with loaded data */
   tex = (CoglTexture*) g_malloc ( sizeof (CoglTexture));
-  
+
   tex->ref_count = 1;
   COGL_HANDLE_DEBUG_NEW (texture, tex);
-  
+
   tex->is_foreign = FALSE;
   tex->auto_mipmap = auto_mipmap;
 
   tex->bitmap = bmp;
   tex->bitmap_owner = TRUE;
-  
+
   tex->slice_x_spans = NULL;
   tex->slice_y_spans = NULL;
   tex->slice_gl_handles = NULL;
-  
+
   tex->max_waste = max_waste;
   tex->min_filter = CGL_NEAREST;
   tex->mag_filter = CGL_NEAREST;
-  
+
   /* FIXME: If upload fails we should set some kind of
    * error flag but still return texture handle if the
    * user decides to destroy another texture and upload
@@ -1374,27 +1374,27 @@ cogl_texture_new_from_file (const gchar     *filename,
    * in that case). As a rule then, everytime a valid
    * CoglHandle is returned, it should also be destroyed
    * with cogl_texture_unref at some point! */
-  
+
   if (!_cogl_texture_bitmap_prepare (tex, internal_format))
     {
       _cogl_texture_free (tex);
       return COGL_INVALID_HANDLE;
     }
-  
+
   if (!_cogl_texture_slices_create (tex))
     {
       _cogl_texture_free (tex);
       return COGL_INVALID_HANDLE;
     }
-  
+
   if (!_cogl_texture_upload_to_gl (tex))
     {
       _cogl_texture_free (tex);
       return COGL_INVALID_HANDLE;
     }
-  
+
   _cogl_texture_bitmap_free (tex);
-  
+
   return _cogl_texture_handle_new (tex);
 }
 
@@ -1413,7 +1413,7 @@ cogl_texture_new_from_foreign (GLuint           gl_handle,
      robustness and for completeness in case one day GLES gains
      support for them.
   */
-  
+
   GLenum           gl_error = 0;
   GLboolean        gl_istexture;
   GLint            gl_compressed = GL_FALSE;
@@ -1448,23 +1448,23 @@ cogl_texture_new_from_foreign (GLuint           gl_handle,
   glBindTexture (gl_target, gl_handle);
   if (glGetError () != GL_NO_ERROR)
     return COGL_INVALID_HANDLE;
-  
+
   /* Obtain texture parameters
      (only level 0 we are interested in) */
-  
+
   GE( glGetTexLevelParameteriv (gl_target, 0,
 				GL_TEXTURE_COMPRESSED,
 				&gl_compressed) );
-  
+
   GE( glGetTexLevelParameteriv (gl_target, 0,
 				GL_TEXTURE_INTERNAL_FORMAT,
 				&gl_int_format) );
-  
+
 
   GE( glGetTexLevelParameteriv (gl_target, 0,
 				GL_TEXTURE_WIDTH,
 				&gl_width) );
-  
+
   GE( glGetTexLevelParameteriv (gl_target, 0,
 				GL_TEXTURE_HEIGHT,
 				&gl_height) );
@@ -1472,57 +1472,57 @@ cogl_texture_new_from_foreign (GLuint           gl_handle,
   GE( glGetTexParameteriv (gl_target,
 			   GL_TEXTURE_MIN_FILTER,
 			   &gl_min_filter) );
-  
+
   GE( glGetTexParameteriv (gl_target,
 			   GL_TEXTURE_MAG_FILTER,
 			   &gl_mag_filter) );
-  
+
   GE( glGetTexParameteriv (gl_target,
                            GL_GENERATE_MIPMAP,
                            &gl_gen_mipmap) );
-  
+
   /* Validate width and height */
   if (gl_width <= 0 || gl_height <= 0)
     return COGL_INVALID_HANDLE;
-  
+
   /* Validate pot waste */
   if (x_pot_waste < 0 || x_pot_waste >= gl_width ||
       y_pot_waste < 0 || y_pot_waste >= gl_height)
     return COGL_INVALID_HANDLE;
-  
+
   /* Compressed texture images not supported */
   if (gl_compressed == GL_TRUE)
     return COGL_INVALID_HANDLE;
-  
+
   /* Try and match to a cogl format */
   if (!_cogl_pixel_format_from_gl_internal (gl_int_format,
 					    &format))
     {
       return COGL_INVALID_HANDLE;
     }
-  
+
   /* Create new texture */
   tex = (CoglTexture*) g_malloc ( sizeof (CoglTexture));
-  
+
   tex->ref_count = 1;
   COGL_HANDLE_DEBUG_NEW (texture, tex);
-  
+
   /* Setup bitmap info */
   tex->is_foreign = TRUE;
   tex->auto_mipmap = (gl_gen_mipmap == GL_TRUE) ? TRUE : FALSE;
-  
+
   bpp = _cogl_get_format_bpp (format);
   tex->bitmap.format = format;
   tex->bitmap.width = gl_width - x_pot_waste;
   tex->bitmap.height = gl_height - y_pot_waste;
   tex->bitmap.rowstride = tex->bitmap.width * bpp;
   tex->bitmap_owner = FALSE;
-  
+
   tex->gl_target = gl_target;
   tex->gl_intformat = gl_int_format;
   tex->gl_format = gl_int_format;
   tex->gl_type = GL_UNSIGNED_BYTE;
-  
+
   tex->min_filter = gl_min_filter;
   tex->mag_filter = gl_mag_filter;
   tex->max_waste = 0;
@@ -1534,26 +1534,26 @@ cogl_texture_new_from_foreign (GLuint           gl_handle,
   tex->slice_x_spans =
     g_array_sized_new (FALSE, FALSE,
 		       sizeof (CoglTexSliceSpan), 1);
-  
+
   tex->slice_y_spans =
     g_array_sized_new (FALSE, FALSE,
 		       sizeof (CoglTexSliceSpan), 1);
-  
+
   tex->slice_gl_handles =
     g_array_sized_new (FALSE, FALSE,
 		       sizeof (GLuint), 1);
-  
+
   /* Store info for a single slice */
   x_span.start = 0;
   x_span.size = gl_width;
   x_span.waste = x_pot_waste;
   g_array_append_val (tex->slice_x_spans, x_span);
-  
+
   y_span.start = 0;
   y_span.size = gl_height;
   y_span.waste = y_pot_waste;
   g_array_append_val (tex->slice_y_spans, y_span);
-  
+
   g_array_append_val (tex->slice_gl_handles, gl_handle);
 
   return _cogl_texture_handle_new (tex);
@@ -1563,12 +1563,12 @@ guint
 cogl_texture_get_width (CoglHandle handle)
 {
   CoglTexture *tex;
-  
+
   if (!cogl_is_texture (handle))
     return 0;
-  
+
   tex = _cogl_texture_pointer_from_handle (handle);
-  
+
   return tex->bitmap.width;
 }
 
@@ -1576,12 +1576,12 @@ guint
 cogl_texture_get_height (CoglHandle handle)
 {
   CoglTexture *tex;
-  
+
   if (!cogl_is_texture (handle))
     return 0;
-  
+
   tex = _cogl_texture_pointer_from_handle (handle);
-  
+
   return tex->bitmap.height;
 }
 
@@ -1589,12 +1589,12 @@ CoglPixelFormat
 cogl_texture_get_format (CoglHandle handle)
 {
   CoglTexture *tex;
-  
+
   if (!cogl_is_texture (handle))
     return COGL_PIXEL_FORMAT_ANY;
-  
+
   tex = _cogl_texture_pointer_from_handle (handle);
-  
+
   return tex->bitmap.format;
 }
 
@@ -1602,12 +1602,12 @@ guint
 cogl_texture_get_rowstride (CoglHandle handle)
 {
   CoglTexture *tex;
-  
+
   if (!cogl_is_texture (handle))
     return 0;
-  
+
   tex = _cogl_texture_pointer_from_handle (handle);
-  
+
   return tex->bitmap.rowstride;
 }
 
@@ -1615,12 +1615,12 @@ gint
 cogl_texture_get_max_waste (CoglHandle handle)
 {
   CoglTexture *tex;
-  
+
   if (!cogl_is_texture (handle))
     return 0;
-  
+
   tex = _cogl_texture_pointer_from_handle (handle);
-  
+
   return tex->max_waste;
 }
 
@@ -1628,18 +1628,18 @@ gboolean
 cogl_texture_is_sliced (CoglHandle handle)
 {
   CoglTexture *tex;
-  
+
   if (!cogl_is_texture (handle))
     return FALSE;
-  
+
   tex = _cogl_texture_pointer_from_handle (handle);
-  
+
   if (tex->slice_gl_handles == NULL)
     return FALSE;
-  
+
   if (tex->slice_gl_handles->len <= 1)
     return FALSE;
-  
+
   return TRUE;
 }
 
@@ -1649,24 +1649,24 @@ cogl_texture_get_gl_texture (CoglHandle handle,
 			     GLenum *out_gl_target)
 {
   CoglTexture *tex;
-  
+
   if (!cogl_is_texture (handle))
     return FALSE;
-  
+
   tex = _cogl_texture_pointer_from_handle (handle);
-  
+
   if (tex->slice_gl_handles == NULL)
     return FALSE;
-  
+
   if (tex->slice_gl_handles->len < 1)
     return FALSE;
-  
+
   if (out_gl_handle != NULL)
     *out_gl_handle = g_array_index (tex->slice_gl_handles, GLuint, 0);
-  
+
   if (out_gl_target != NULL)
     *out_gl_target = tex->gl_target;
-  
+
   return TRUE;
 }
 
@@ -1674,12 +1674,12 @@ COGLenum
 cogl_texture_get_min_filter (CoglHandle handle)
 {
   CoglTexture *tex;
-  
+
   if (!cogl_is_texture (handle))
     return 0;
-  
+
   tex = _cogl_texture_pointer_from_handle (handle);
-  
+
   return tex->min_filter;
 }
 
@@ -1687,12 +1687,12 @@ COGLenum
 cogl_texture_get_mag_filter (CoglHandle handle)
 {
   CoglTexture *tex;
-  
+
   if (!cogl_is_texture (handle))
     return 0;
-  
+
   tex = _cogl_texture_pointer_from_handle (handle);
-  
+
   return tex->mag_filter;
 }
 
@@ -1704,20 +1704,20 @@ cogl_texture_set_filters (CoglHandle handle,
   CoglTexture *tex;
   GLuint       gl_handle;
   int          i;
-  
+
   if (!cogl_is_texture (handle))
     return;
-  
+
   tex = _cogl_texture_pointer_from_handle (handle);
-  
+
   /* Store new values */
   tex->min_filter = min_filter;
   tex->mag_filter = mag_filter;
-  
+
   /* Make sure slices were created */
   if (tex->slice_gl_handles == NULL)
     return;
-  
+
   /* Apply new filters to every slice */
   for (i=0; i<tex->slice_gl_handles->len; ++i)
     {
@@ -1753,37 +1753,37 @@ cogl_texture_set_region (CoglHandle       handle,
   GLenum           closest_gl_format;
   GLenum           closest_gl_type;
   gboolean         success;
-  
+
   /* Check if valid texture handle */
   if (!cogl_is_texture (handle))
     return FALSE;
-  
+
   tex = _cogl_texture_pointer_from_handle (handle);
-  
+
   /* Check for valid format */
   if (format == COGL_PIXEL_FORMAT_ANY)
     return FALSE;
-  
+
   /* Shortcut out early if the image is empty */
   if (width == 0 || height == 0)
     return TRUE;
-   
+
   /* Init source bitmap */
   source_bmp.width = width;
   source_bmp.height = height;
   source_bmp.format = format;
   source_bmp.data = (guchar*)data;
-  
+
   /* Rowstride from width if none specified */
   bpp = _cogl_get_format_bpp (format);
   source_bmp.rowstride = (rowstride == 0) ? width * bpp : rowstride;
-  
+
   /* Find closest format to internal that's supported by GL */
   closest_format = _cogl_pixel_format_to_gl (tex->bitmap.format,
 					     NULL, /* don't need */
 					     &closest_gl_format,
 					     &closest_gl_type);
-  
+
   /* If no direct match, convert */
   if (closest_format != format)
     {
@@ -1791,13 +1791,13 @@ cogl_texture_set_region (CoglHandle       handle,
       success = _cogl_bitmap_convert_and_premult (&source_bmp,
 						  &temp_bmp,
 						  closest_format);
-      
+
       /* Swap bitmaps if succeeded */
       if (!success) return FALSE;
       source_bmp = temp_bmp;
       source_bmp_owner = TRUE;
     }
-  
+
   /* Send data to GL */
   _cogl_texture_upload_subregion_to_gl (tex,
 					src_x, src_y,
@@ -1806,11 +1806,11 @@ cogl_texture_set_region (CoglHandle       handle,
 					&source_bmp,
 					closest_gl_format,
 					closest_gl_type);
-  
+
   /* Free data if owner */
   if (source_bmp_owner)
     g_free (source_bmp.data);
-  
+
   return TRUE;
 }
 
@@ -1833,33 +1833,33 @@ cogl_texture_get_data (CoglHandle       handle,
   guchar           *src;
   guchar           *dst;
   gint              y;
-  
+
   /* Check if valid texture handle */
   if (!cogl_is_texture (handle))
     return 0;
-  
+
   tex = _cogl_texture_pointer_from_handle (handle);
-  
+
   /* Default to internal format if none specified */
   if (format == COGL_PIXEL_FORMAT_ANY)
     format = tex->bitmap.format;
-  
+
   /* Rowstride from texture width if none specified */
   bpp = _cogl_get_format_bpp (format);
   if (rowstride == 0) rowstride = tex->bitmap.width * bpp;
-  
+
   /* Return byte size if only that requested */
   byte_size =  tex->bitmap.height * rowstride;
   if (data == NULL) return byte_size;
-  
+
   /* Find closest format that's supported by GL */
   closest_format = _cogl_pixel_format_to_gl (format,
 					     NULL, /* don't need */
 					     &closest_gl_format,
 					     &closest_gl_type);
-  
+
   closest_bpp = _cogl_get_format_bpp (closest_format);
-  
+
   /* Is the requested format supported? */
   if (closest_format == format)
     {
@@ -1878,12 +1878,12 @@ cogl_texture_get_data (CoglHandle       handle,
       target_bmp.data = (guchar*) g_malloc (target_bmp.height
 					    * target_bmp.rowstride);
     }
-  
+
   /* Retrieve data from slices */
   _cogl_texture_download_from_gl (tex, &target_bmp,
 				  closest_gl_format,
 				  closest_gl_type);
-  
+
   /* Was intermediate used? */
   if (closest_format != format)
     {
@@ -1891,11 +1891,11 @@ cogl_texture_get_data (CoglHandle       handle,
       success = _cogl_bitmap_convert_and_premult (&target_bmp,
 						  &new_bmp,
 						  format);
-      
+
       /* Free intermediate data and return if failed */
       g_free (target_bmp.data);
       if (!success) return 0;
-      
+
       /* Copy to user buffer */
       for (y = 0; y < new_bmp.height; ++y)
 	{
@@ -1903,14 +1903,103 @@ cogl_texture_get_data (CoglHandle       handle,
 	  dst = data + y * rowstride;
 	  memcpy (dst, src, new_bmp.width);
 	}
-      
+
       /* Free converted data */
       g_free (new_bmp.data);
     }
-  
+
   return byte_size;
 }
 
+static void
+_cogl_texture_flush_vertices (void)
+{
+  _COGL_GET_CONTEXT (ctx, NO_RETVAL);
+
+  if (ctx->texture_vertices->len > 0)
+    {
+      int needed_indices;
+      CoglTextureGLVertex *p
+        = (CoglTextureGLVertex *) ctx->texture_vertices->data;
+
+      /* The indices are always the same sequence regardless of the
+         vertices so we only need to change it if there are more
+         vertices than ever before */
+      needed_indices = ctx->texture_vertices->len / 4 * 6;
+      if (needed_indices > ctx->texture_indices->len)
+        {
+          int old_len = ctx->texture_indices->len;
+          int vert_num = old_len / 6 * 4;
+          int i;
+          GLushort *q;
+
+          /* Add two triangles for each quad to the list of
+             indices. That makes six new indices but two of the
+             vertices in the triangles are shared. */
+          g_array_set_size (ctx->texture_indices, needed_indices);
+          q = &g_array_index (ctx->texture_indices, GLushort, old_len);
+
+          for (i = old_len;
+               i < ctx->texture_indices->len;
+               i += 6, vert_num += 4)
+            {
+              *(q++) = vert_num + 0;
+              *(q++) = vert_num + 1;
+              *(q++) = vert_num + 3;
+
+              *(q++) = vert_num + 1;
+              *(q++) = vert_num + 2;
+              *(q++) = vert_num + 3;
+            }
+        }
+
+      GE( glVertexPointer (2, GL_FLOAT,
+                           sizeof (CoglTextureGLVertex), p->v ) );
+      GE( glTexCoordPointer (2, GL_FLOAT,
+                             sizeof (CoglTextureGLVertex), p->t ) );
+
+      GE( glBindTexture (ctx->texture_target, ctx->texture_current) );
+      GE( ctx->pf_glDrawRangeElements (GL_TRIANGLES,
+                                       0, ctx->texture_vertices->len - 1,
+                                       needed_indices,
+                                       GL_UNSIGNED_SHORT,
+                                       ctx->texture_indices->data) );
+
+      g_array_set_size (ctx->texture_vertices, 0);
+    }
+}
+
+static void
+_cogl_texture_add_quad_vertices (GLfloat x1, GLfloat y1,
+                                 GLfloat x2, GLfloat y2,
+                                 GLfloat tx1, GLfloat ty1,
+                                 GLfloat tx2, GLfloat ty2)
+{
+  CoglTextureGLVertex *p;
+  GLushort first_vert;
+
+  _COGL_GET_CONTEXT (ctx, NO_RETVAL);
+
+  /* Add the four vertices of the quad to the list of queued
+     vertices */
+  first_vert = ctx->texture_vertices->len;
+  g_array_set_size (ctx->texture_vertices, first_vert + 4);
+  p = &g_array_index (ctx->texture_vertices, CoglTextureGLVertex, first_vert);
+
+  p->v[0] = x1;  p->v[1] = y1;
+  p->t[0] = tx1; p->t[1] = ty1;
+  p++;
+  p->v[0] = x1;  p->v[1] = y2;
+  p->t[0] = tx1; p->t[1] = ty2;
+  p++;
+  p->v[0] = x2;  p->v[1] = y2;
+  p->t[0] = tx2; p->t[1] = ty2;
+  p++;
+  p->v[0] = x2;  p->v[1] = y1;
+  p->t[0] = tx2; p->t[1] = ty1;
+  p++;
+}
+
 static void
 _cogl_texture_quad_sw (CoglTexture *tex,
 		       CoglFixed x1,
@@ -1931,38 +2020,21 @@ _cogl_texture_quad_sw (CoglTexture *tex,
   CoglFixed       slice_tx2 ,  slice_ty2;
   CoglFixed       slice_qx1 ,  slice_qy1;
   CoglFixed       slice_qx2 ,  slice_qy2;
-  GLfloat         tex_coords[8];
-  GLfloat         quad_coords[8];
   GLuint          gl_handle;
-  gulong          enable_flags = (COGL_ENABLE_VERTEX_ARRAY
-                                  | COGL_ENABLE_TEXCOORD_ARRAY);
-  
+
   _COGL_GET_CONTEXT (ctx, NO_RETVAL);
 
 #if COGL_DEBUG
   printf("=== Drawing Tex Quad (Software Tiling Mode) ===\n");
 #endif
 
-  /* Prepare GL state */
-  if (tex->gl_target == CGL_TEXTURE_RECTANGLE_ARB)
-    enable_flags |= COGL_ENABLE_TEXTURE_RECT;
-  else
-    enable_flags |= COGL_ENABLE_TEXTURE_2D;
-
-  if (ctx->color_alpha < 255
-      || tex->bitmap.format & COGL_A_BIT)
-    {
-      enable_flags |= COGL_ENABLE_BLEND;
-    }
-
-  if (ctx->enable_backface_culling)
-    enable_flags |= COGL_ENABLE_BACKFACE_CULLING;
-
-  cogl_enable (enable_flags);
-
   /* We can't use hardware repeat so we need to set clamp to edge
      otherwise it might pull in edge pixels from the other side */
+  if (ctx->texture_vertices->len > 0
+      && ctx->texture_wrap_mode != GL_CLAMP_TO_EDGE)
+    _cogl_texture_flush_vertices ();
   _cogl_texture_set_wrap_mode_parameter (tex, GL_CLAMP_TO_EDGE);
+  ctx->texture_wrap_mode = GL_CLAMP_TO_EDGE;
 
   /* If the texture coordinates are backwards then swap both the
      geometry and texture coordinates so that the texture will be
@@ -1986,21 +2058,18 @@ _cogl_texture_quad_sw (CoglTexture *tex,
       ty1 = ty2;
       ty2 = temp;
     }
-  
-  GE( glTexCoordPointer (2, GL_FLOAT, 0, tex_coords) );
-  GE( glVertexPointer   (2, GL_FLOAT, 0, quad_coords) );
-  
+
   /* Scale ratio from texture to quad widths */
   tw = COGL_FIXED_FROM_INT (tex->bitmap.width);
   th = COGL_FIXED_FROM_INT (tex->bitmap.height);
-  
+
   tqx = COGL_FIXED_DIV (x2 - x1, COGL_FIXED_MUL (tw, (tx2 - tx1)));
   tqy = COGL_FIXED_DIV (y2 - y1, COGL_FIXED_MUL (th, (ty2 - ty1)));
 
   /* Integral texture coordinate for first tile */
   first_tx = COGL_FIXED_FROM_INT (COGL_FIXED_FLOOR (tx1));
   first_ty = COGL_FIXED_FROM_INT (COGL_FIXED_FLOOR (ty1));
-  
+
   /* Denormalize texture coordinates */
   first_tx = COGL_FIXED_MUL (first_tx, tw);
   first_ty = COGL_FIXED_MUL (first_ty, th);
@@ -2012,21 +2081,21 @@ _cogl_texture_quad_sw (CoglTexture *tex,
   /* Quad coordinate of the first tile */
   first_qx = x1 - COGL_FIXED_MUL (tx1 - first_tx, tqx);
   first_qy = y1 - COGL_FIXED_MUL (ty1 - first_ty, tqy);
-  
-  
+
+
   /* Iterate until whole quad height covered */
   for (_cogl_span_iter_begin (&iter_y, tex->slice_y_spans,
 			      first_ty, ty1, ty2) ;
        !_cogl_span_iter_end  (&iter_y) ;
        _cogl_span_iter_next  (&iter_y) )
-    { 
+    {
       /* Discard slices out of quad early */
       if (!iter_y.intersects) continue;
-      
+
       /* Span-quad intersection in quad coordinates */
       slice_qy1 = first_qy +
 	COGL_FIXED_MUL (iter_y.intersect_start - first_ty, tqy);
-      
+
       slice_qy2 = first_qy +
 	COGL_FIXED_MUL (iter_y.intersect_end - first_ty, tqy);
 
@@ -2050,14 +2119,14 @@ _cogl_texture_quad_sw (CoglTexture *tex,
         {
 	  /* Discard slices out of quad early */
 	  if (!iter_x.intersects) continue;
-	  
+
 	  /* Span-quad intersection in quad coordinates */
 	  slice_qx1 = first_qx +
 	    COGL_FIXED_MUL (iter_x.intersect_start - first_tx, tqx);
-	  
+
 	  slice_qx2 = first_qx +
 	    COGL_FIXED_MUL (iter_x.intersect_end - first_tx, tqx);
-	  
+
 	  /* Localize slice texture coordinates */
 	  slice_tx1 = iter_x.intersect_start - iter_x.pos;
 	  slice_tx2 = iter_x.intersect_end - iter_x.pos;
@@ -2081,30 +2150,28 @@ _cogl_texture_quad_sw (CoglTexture *tex,
 	  printf("tx2: %f\n", COGL_FIXED_TO_FLOAT (slice_tx2));
 	  printf("ty2: %f\n", COGL_FIXED_TO_FLOAT (slice_ty2));
 #endif
-	  
+
 	  /* Pick and bind opengl texture object */
 	  gl_handle = g_array_index (tex->slice_gl_handles, GLuint,
 				     iter_y.index * iter_x.array->len +
 				     iter_x.index);
-	  
-	  GE( glBindTexture (tex->gl_target, gl_handle) );
 
-#define CFX_F COGL_FIXED_TO_FLOAT
-	  
-	  /* Draw textured quad */
-          tex_coords[0] = CFX_F(slice_tx1); tex_coords[1] = CFX_F(slice_ty2);
-          tex_coords[2] = CFX_F(slice_tx2); tex_coords[3] = CFX_F(slice_ty2);
-          tex_coords[4] = CFX_F(slice_tx1); tex_coords[5] = CFX_F(slice_ty1);
-          tex_coords[6] = CFX_F(slice_tx2); tex_coords[7] = CFX_F(slice_ty1);
+          /* If we're using a different texture from the one already queued
+             then flush the vertices */
+          if (ctx->texture_vertices->len > 0
+              && gl_handle != ctx->texture_current)
+            _cogl_texture_flush_vertices ();
+          ctx->texture_target = tex->gl_target;
+          ctx->texture_current = gl_handle;
 
-          quad_coords[0] = CFX_F(slice_qx1); quad_coords[1] = CFX_F(slice_qy2);
-          quad_coords[2] = CFX_F(slice_qx2); quad_coords[3] = CFX_F(slice_qy2);
-          quad_coords[4] = CFX_F(slice_qx1); quad_coords[5] = CFX_F(slice_qy1);
-          quad_coords[6] = CFX_F(slice_qx2); quad_coords[7] = CFX_F(slice_qy1);
-
-	  GE (glDrawArrays (GL_TRIANGLE_STRIP, 0, 4) );
-
-#undef CFX_F
+          _cogl_texture_add_quad_vertices (COGL_FIXED_TO_FLOAT (slice_qx1),
+                                           COGL_FIXED_TO_FLOAT (slice_qy1),
+                                           COGL_FIXED_TO_FLOAT (slice_qx2),
+                                           COGL_FIXED_TO_FLOAT (slice_qy2),
+                                           COGL_FIXED_TO_FLOAT (slice_tx1),
+                                           COGL_FIXED_TO_FLOAT (slice_ty1),
+                                           COGL_FIXED_TO_FLOAT (slice_tx2),
+                                           COGL_FIXED_TO_FLOAT (slice_ty2));
 	}
     }
 }
@@ -2120,37 +2187,16 @@ _cogl_texture_quad_hw (CoglTexture *tex,
 		       CoglFixed tx2,
 		       CoglFixed ty2)
 {
-  GLfloat           tex_coords[8];
-  GLfloat           quad_coords[8];
   GLuint            gl_handle;
   CoglTexSliceSpan *x_span;
   CoglTexSliceSpan *y_span;
-  gulong            enable_flags = (COGL_ENABLE_VERTEX_ARRAY
-                                   | COGL_ENABLE_TEXCOORD_ARRAY);
+  GLenum            wrap_mode;
 
 #if COGL_DEBUG
   printf("=== Drawing Tex Quad (Hardware Tiling Mode) ===\n");
 #endif
-  
+
   _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-  
-  /* Prepare GL state */
-  if (tex->gl_target == CGL_TEXTURE_RECTANGLE_ARB)
-    enable_flags |= COGL_ENABLE_TEXTURE_RECT;
-  else
-    enable_flags |= COGL_ENABLE_TEXTURE_2D;
-
-  if (ctx->color_alpha < 255
-      || tex->bitmap.format & COGL_A_BIT)
-    {
-      enable_flags |= COGL_ENABLE_BLEND;
-    }
-  
-  if (ctx->enable_backface_culling)
-    enable_flags |= COGL_ENABLE_BACKFACE_CULLING;
-
-  cogl_enable (enable_flags);
-
 
   /* If the texture coords are all in the range [0,1] then we want to
      clamp the coords to the edge otherwise it can pull in edge pixels
@@ -2159,17 +2205,25 @@ _cogl_texture_quad_hw (CoglTexture *tex,
       && tx2 >= 0 && tx2 <= COGL_FIXED_1
       && ty1 >= 0 && ty1 <= COGL_FIXED_1
       && ty2 >= 0 && ty2 <= COGL_FIXED_1)
-    _cogl_texture_set_wrap_mode_parameter (tex, GL_CLAMP_TO_EDGE);
+    wrap_mode = GL_CLAMP_TO_EDGE;
   else
-    _cogl_texture_set_wrap_mode_parameter (tex, GL_REPEAT);
+    wrap_mode = GL_REPEAT;
 
-  GE( glTexCoordPointer (2, GL_FLOAT, 0, tex_coords) );
-  GE( glVertexPointer   (2, GL_FLOAT, 0, quad_coords) );
-  
   /* Pick and bind opengl texture object */
   gl_handle = g_array_index (tex->slice_gl_handles, GLuint, 0);
-  GE( glBindTexture (tex->gl_target, gl_handle) );
-  
+
+  /* If we're using a different texture from the one already queued
+     then flush the vertices */
+  if (ctx->texture_vertices->len > 0
+      && (gl_handle != ctx->texture_current
+          || ctx->texture_wrap_mode != wrap_mode))
+    _cogl_texture_flush_vertices ();
+  ctx->texture_target = tex->gl_target;
+  ctx->texture_current = gl_handle;
+  ctx->texture_wrap_mode = wrap_mode;
+
+  _cogl_texture_set_wrap_mode_parameter (tex, wrap_mode);
+
   /* Don't include the waste in the texture coordinates */
   x_span = &g_array_index (tex->slice_x_spans, CoglTexSliceSpan, 0);
   y_span = &g_array_index (tex->slice_y_spans, CoglTexSliceSpan, 0);
@@ -2189,22 +2243,84 @@ _cogl_texture_quad_hw (CoglTexture *tex,
       ty2 *= y_span->size;
     }
 
-#define CFX_F(x) COGL_FIXED_TO_FLOAT(x)
+  _cogl_texture_add_quad_vertices (COGL_FIXED_TO_FLOAT (x1),
+                                   COGL_FIXED_TO_FLOAT (y1),
+                                   COGL_FIXED_TO_FLOAT (x2),
+                                   COGL_FIXED_TO_FLOAT (y2),
+                                   COGL_FIXED_TO_FLOAT (tx1),
+                                   COGL_FIXED_TO_FLOAT (ty1),
+                                   COGL_FIXED_TO_FLOAT (tx2),
+                                   COGL_FIXED_TO_FLOAT (ty2));
+}
 
-  /* Draw textured quad */
-  tex_coords[0] = CFX_F(tx1); tex_coords[1] = CFX_F(ty2);
-  tex_coords[2] = CFX_F(tx2); tex_coords[3] = CFX_F(ty2);
-  tex_coords[4] = CFX_F(tx1); tex_coords[5] = CFX_F(ty1);
-  tex_coords[6] = CFX_F(tx2); tex_coords[7] = CFX_F(ty1);
+void
+cogl_texture_multiple_rectangles (CoglHandle       handle,
+                                  const CoglFixed *verts,
+                                  guint            n_rects)
+{
+  CoglTexture    *tex;
+  gulong          enable_flags = (COGL_ENABLE_VERTEX_ARRAY
+                                  | COGL_ENABLE_TEXCOORD_ARRAY);
 
-  quad_coords[0] = CFX_F(x1); quad_coords[1] = CFX_F(y2);
-  quad_coords[2] = CFX_F(x2); quad_coords[3] = CFX_F(y2);
-  quad_coords[4] = CFX_F(x1); quad_coords[5] = CFX_F(y1);
-  quad_coords[6] = CFX_F(x2); quad_coords[7] = CFX_F(y1);
+  _COGL_GET_CONTEXT (ctx, NO_RETVAL);
 
-  GE (glDrawArrays (GL_TRIANGLE_STRIP, 0, 4) );
+  /* Check if valid texture */
+  if (!cogl_is_texture (handle))
+    return;
 
-#undef CFX_F
+  cogl_clip_ensure ();
+
+  tex = _cogl_texture_pointer_from_handle (handle);
+
+  /* Make sure we got stuff to draw */
+  if (tex->slice_gl_handles == NULL)
+    return;
+
+  if (tex->slice_gl_handles->len == 0)
+    return;
+
+  /* Prepare GL state */
+  if (tex->gl_target == CGL_TEXTURE_RECTANGLE_ARB)
+    enable_flags |= COGL_ENABLE_TEXTURE_RECT;
+  else
+    enable_flags |= COGL_ENABLE_TEXTURE_2D;
+
+  if (ctx->color_alpha < 255
+      || tex->bitmap.format & COGL_A_BIT)
+    enable_flags |= COGL_ENABLE_BLEND;
+
+  if (ctx->enable_backface_culling)
+    enable_flags |= COGL_ENABLE_BACKFACE_CULLING;
+
+  cogl_enable (enable_flags);
+
+  g_array_set_size (ctx->texture_vertices, 0);
+
+  while (n_rects-- > 0)
+    {
+      if (verts[4] != verts[6] && verts[5] != verts[7])
+        {
+          /* If there is only one GL texture and either the texture is
+             NPOT (no waste) or all of the coordinates are in the
+             range [0,1] then we can use hardware tiling */
+          if (tex->slice_gl_handles->len == 1
+              && ((cogl_features_available (COGL_FEATURE_TEXTURE_NPOT)
+                   && tex->gl_target == GL_TEXTURE_2D)
+                  || (verts[4] >= 0 && verts[4] <= COGL_FIXED_1
+                      && verts[6] >= 0 && verts[6] <= COGL_FIXED_1
+                      && verts[5] >= 0 && verts[5] <= COGL_FIXED_1
+                      && verts[7] >= 0 && verts[7] <= COGL_FIXED_1)))
+            _cogl_texture_quad_hw (tex, verts[0],verts[1], verts[2],verts[3],
+                                   verts[4],verts[5], verts[6],verts[7]);
+          else
+            _cogl_texture_quad_sw (tex, verts[0],verts[1], verts[2],verts[3],
+                                   verts[4],verts[5], verts[6],verts[7]);
+        }
+
+      verts += 8;
+    }
+
+  _cogl_texture_flush_vertices ();
 }
 
 void
@@ -2218,39 +2334,18 @@ cogl_texture_rectangle (CoglHandle   handle,
 			CoglFixed tx2,
 			CoglFixed ty2)
 {
-  CoglTexture       *tex;
-  
-  /* Check if valid texture */
-  if (!cogl_is_texture (handle))
-    return;
-  
-  cogl_clip_ensure ();
+  CoglFixed verts[8];
 
-  tex = _cogl_texture_pointer_from_handle (handle);
-  
-  /* Make sure we got stuff to draw */
-  if (tex->slice_gl_handles == NULL)
-    return;
-  
-  if (tex->slice_gl_handles->len == 0)
-    return;
-  
-  if (tx1 == tx2 || ty1 == ty2)
-    return;
+  verts[0] = x1;
+  verts[1] = y1;
+  verts[2] = x2;
+  verts[3] = y2;
+  verts[4] = tx1;
+  verts[5] = ty1;
+  verts[6] = tx2;
+  verts[7] = ty2;
 
-  /* If there is only one GL texture and either the texture is NPOT
-     (no waste) or all of the coordinates are in the range [0,1] then
-     we can use hardware tiling */
-  if (tex->slice_gl_handles->len == 1
-      && ((cogl_features_available (COGL_FEATURE_TEXTURE_NPOT)
-           && tex->gl_target == GL_TEXTURE_2D)
-          || (tx1 >= 0 && tx1 <= COGL_FIXED_1
-              && tx2 >= 0 && tx2 <= COGL_FIXED_1
-              && ty1 >= 0 && ty1 <= COGL_FIXED_1
-              && ty2 >= 0 && ty2 <= COGL_FIXED_1)))
-    _cogl_texture_quad_hw (tex, x1,y1, x2,y2, tx1,ty1, tx2,ty2);
-  else
-    _cogl_texture_quad_sw (tex, x1,y1, x2,y2, tx1,ty1, tx2,ty2);
+  cogl_texture_multiple_rectangles (handle, verts, 1);
 }
 
 void
@@ -2299,23 +2394,9 @@ cogl_texture_polygon (CoglHandle         handle,
   /* Make sure there is enough space in the global texture vertex
      array. This is used so we can render the polygon with a single
      call to OpenGL but still support any number of vertices */
-  if (ctx->texture_vertices_size < n_vertices)
-    {
-      guint nsize = ctx->texture_vertices_size;
-      
-      if (nsize == 0)
-	nsize = 1;
-      do
-	nsize *= 2;
-      while (nsize < n_vertices);
-      
-      ctx->texture_vertices_size = nsize;
+  g_array_set_size (ctx->texture_vertices, n_vertices);
+  p = (CoglTextureGLVertex *) ctx->texture_vertices->data;
 
-      ctx->texture_vertices = g_realloc (ctx->texture_vertices,
-					 nsize
-					 * sizeof (CoglTextureGLVertex));
-    }
-  
   /* Prepare GL state */
   enable_flags = (COGL_ENABLE_VERTEX_ARRAY
 		  | COGL_ENABLE_TEXCOORD_ARRAY
@@ -2332,14 +2413,12 @@ cogl_texture_polygon (CoglHandle         handle,
   if (use_color)
     {
       enable_flags |= COGL_ENABLE_COLOR_ARRAY;
-      GE( glColorPointer (4, GL_UNSIGNED_BYTE, sizeof (CoglTextureGLVertex),
-			  ctx->texture_vertices[0].c) );
+      GE( glColorPointer (4, GL_UNSIGNED_BYTE,
+                          sizeof (CoglTextureGLVertex), p->c) );
     }
 
-  GE( glVertexPointer (3, GL_FLOAT, sizeof (CoglTextureGLVertex),
-		       ctx->texture_vertices[0].v) );
-  GE( glTexCoordPointer (2, GL_FLOAT, sizeof (CoglTextureGLVertex),
-			 ctx->texture_vertices[0].t) );
+  GE( glVertexPointer (3, GL_FLOAT, sizeof (CoglTextureGLVertex), p->v ) );
+  GE( glTexCoordPointer (2, GL_FLOAT, sizeof (CoglTextureGLVertex), p->t ) );
 
   cogl_enable (enable_flags);
 
@@ -2362,9 +2441,11 @@ cogl_texture_polygon (CoglHandle         handle,
 
 	  gl_handle = g_array_index (tex->slice_gl_handles, GLuint, tex_num++);
 
+          p = (CoglTextureGLVertex *) ctx->texture_vertices->data;
+
 	  /* Convert the vertices into an array of GLfloats ready to pass to
 	     OpenGL */
-	  for (i = 0, p = ctx->texture_vertices; i < n_vertices; i++, p++)
+	  for (i = 0; i < n_vertices; i++, p++)
 	    {
               CoglFixed tx, ty;
 
diff --git a/gles/cogl-context.c b/gles/cogl-context.c
index c7c768dec..b09568de4 100644
--- a/gles/cogl-context.c
+++ b/gles/cogl-context.c
@@ -59,9 +59,11 @@ cogl_create_context ()
   _context->last_path = 0;
 
   _context->texture_handles = NULL;
-  _context->texture_vertices_size = 0;
-  _context->texture_vertices = NULL;
-  
+  _context->texture_vertices = g_array_new (FALSE, FALSE,
+                                            sizeof (CoglTextureGLVertex));
+  _context->texture_indices = g_array_new (FALSE, FALSE,
+                                           sizeof (GLushort));
+
   _context->fbo_handles = NULL;
   _context->program_handles = NULL;
   _context->shader_handles = NULL;
@@ -104,8 +106,10 @@ cogl_destroy_context ()
 #endif
 
   if (_context->texture_vertices)
-    g_free (_context->texture_vertices);
-  
+    g_array_free (_context->texture_vertices, TRUE);
+  if (_context->texture_indices)
+    g_array_free (_context->texture_indices, TRUE);
+
   if (_context->texture_handles)
     g_array_free (_context->texture_handles, TRUE);
   if (_context->fbo_handles)
diff --git a/gles/cogl-context.h b/gles/cogl-context.h
index b62903efc..5d835712a 100644
--- a/gles/cogl-context.h
+++ b/gles/cogl-context.h
@@ -65,9 +65,14 @@ typedef struct
 
   /* Textures */
   GArray              *texture_handles;
-  CoglTextureGLVertex *texture_vertices;
-  gulong               texture_vertices_size;
-  
+  GArray              *texture_vertices;
+  GArray              *texture_indices;
+  /* The gl texture number that the above vertices apply to. This to
+     detect when a different slice is encountered so that the vertices
+     can be flushed */
+  GLuint               texture_current;
+  GLenum               texture_target;
+
   /* Framebuffer objects */
   GArray              *fbo_handles;
   CoglBufferTarget     draw_buffer;
diff --git a/gles/cogl-texture.c b/gles/cogl-texture.c
index 5a75eb389..915e82b23 100644
--- a/gles/cogl-texture.c
+++ b/gles/cogl-texture.c
@@ -2047,6 +2047,94 @@ cogl_texture_get_data (CoglHandle       handle,
   return byte_size;
 }
 
+static void
+_cogl_texture_flush_vertices (void)
+{
+  _COGL_GET_CONTEXT (ctx, NO_RETVAL);
+
+  if (ctx->texture_vertices->len > 0)
+    {
+      int needed_indices;
+      CoglTextureGLVertex *p
+        = (CoglTextureGLVertex *) ctx->texture_vertices->data;
+
+      /* The indices are always the same sequence regardless of the
+         vertices so we only need to change it if there are more
+         vertices than ever before */
+      needed_indices = ctx->texture_vertices->len / 4 * 6;
+      if (needed_indices > ctx->texture_indices->len)
+        {
+          int old_len = ctx->texture_indices->len;
+          int vert_num = old_len / 6 * 4;
+          int i;
+          GLushort *q;
+
+          /* Add two triangles for each quad to the list of
+             indices. That makes six new indices but two of the
+             vertices in the triangles are shared. */
+          g_array_set_size (ctx->texture_indices, needed_indices);
+          q = &g_array_index (ctx->texture_indices, GLushort, old_len);
+
+          for (i = old_len;
+               i < ctx->texture_indices->len;
+               i += 6, vert_num += 4)
+            {
+              *(q++) = vert_num + 0;
+              *(q++) = vert_num + 1;
+              *(q++) = vert_num + 3;
+
+              *(q++) = vert_num + 1;
+              *(q++) = vert_num + 2;
+              *(q++) = vert_num + 3;
+            }
+        }
+
+      GE( glVertexPointer (2, GL_FLOAT,
+                           sizeof (CoglTextureGLVertex), p->v ) );
+      GE( glTexCoordPointer (2, GL_FLOAT,
+                             sizeof (CoglTextureGLVertex), p->t ) );
+
+      GE( glBindTexture (ctx->texture_target, ctx->texture_current) );
+      GE( glDrawElements (GL_TRIANGLES,
+                          needed_indices,
+                          GL_UNSIGNED_SHORT,
+                          ctx->texture_indices->data) );
+
+      g_array_set_size (ctx->texture_vertices, 0);
+    }
+}
+
+static void
+_cogl_texture_add_quad_vertices (GLfloat x1, GLfloat y1,
+                                 GLfloat x2, GLfloat y2,
+                                 GLfloat tx1, GLfloat ty1,
+                                 GLfloat tx2, GLfloat ty2)
+{
+  CoglTextureGLVertex *p;
+  GLushort first_vert;
+
+  _COGL_GET_CONTEXT (ctx, NO_RETVAL);
+
+  /* Add the four vertices of the quad to the list of queued
+     vertices */
+  first_vert = ctx->texture_vertices->len;
+  g_array_set_size (ctx->texture_vertices, first_vert + 4);
+  p = &g_array_index (ctx->texture_vertices, CoglTextureGLVertex, first_vert);
+
+  p->v[0] = x1;  p->v[1] = y1;
+  p->t[0] = tx1; p->t[1] = ty1;
+  p++;
+  p->v[0] = x1;  p->v[1] = y2;
+  p->t[0] = tx1; p->t[1] = ty2;
+  p++;
+  p->v[0] = x2;  p->v[1] = y2;
+  p->t[0] = tx2; p->t[1] = ty2;
+  p++;
+  p->v[0] = x2;  p->v[1] = y1;
+  p->t[0] = tx2; p->t[1] = ty1;
+  p++;
+}
+
 static void
 _cogl_texture_quad_sw (CoglTexture *tex,
 		       CoglFixed x1,
@@ -2067,31 +2155,13 @@ _cogl_texture_quad_sw (CoglTexture *tex,
   CoglFixed       slice_tx2 ,  slice_ty2;
   CoglFixed       slice_qx1 ,  slice_qy1;
   CoglFixed       slice_qx2 ,  slice_qy2;
-  GLfloat         tex_coords[8];
-  GLfloat         quad_coords[8];
   GLuint          gl_handle;
-  gulong          enable_flags = (COGL_ENABLE_TEXTURE_2D
-                                  | COGL_ENABLE_VERTEX_ARRAY
-                                  | COGL_ENABLE_TEXCOORD_ARRAY);
-  
+
   _COGL_GET_CONTEXT (ctx, NO_RETVAL);
 
 #if COGL_DEBUG
   printf("=== Drawing Tex Quad (Software Tiling Mode) ===\n");
 #endif
-  
-  
-  /* Prepare GL state */
-  if (ctx->color_alpha < 255
-      || tex->bitmap.format & COGL_A_BIT)
-    {
-      enable_flags |= COGL_ENABLE_BLEND;
-    }
-
-  if (ctx->enable_backface_culling)
-    enable_flags |= COGL_ENABLE_BACKFACE_CULLING;
-
-  cogl_enable (enable_flags);
 
   /* If the texture coordinates are backwards then swap both the
      geometry and texture coordinates so that the texture will be
@@ -2115,10 +2185,7 @@ _cogl_texture_quad_sw (CoglTexture *tex,
       ty1 = ty2;
       ty2 = temp;
     }
-  
-  GE( glTexCoordPointer (2, GL_FLOAT, 0, tex_coords) );
-  GE( glVertexPointer   (2, GL_FLOAT, 0, quad_coords) );
-  
+
   /* Scale ratio from texture to quad widths */
   tw = COGL_FIXED_FROM_INT (tex->bitmap.width);
   th = COGL_FIXED_FROM_INT (tex->bitmap.height);
@@ -2158,17 +2225,16 @@ _cogl_texture_quad_sw (CoglTexture *tex,
       
       slice_qy2 = first_qy +
 	COGL_FIXED_MUL (iter_y.intersect_end - first_ty, tqy);
-      
+
       /* Localize slice texture coordinates */
       slice_ty1 = iter_y.intersect_start - iter_y.pos;
       slice_ty2 = iter_y.intersect_end - iter_y.pos;
-      
+
       /* Normalize texture coordinates to current slice
          (rectangle texture targets take denormalized) */
       slice_ty1 /= iter_y.span->size;
       slice_ty2 /= iter_y.span->size;
-      
-      
+
       /* Iterate until whole quad width covered */
       for (_cogl_span_iter_begin (&iter_x, tex->slice_x_spans,
 				  first_tx, tx1, tx2) ;
@@ -2188,12 +2254,12 @@ _cogl_texture_quad_sw (CoglTexture *tex,
 	  /* Localize slice texture coordinates */
 	  slice_tx1 = iter_x.intersect_start - iter_x.pos;
 	  slice_tx2 = iter_x.intersect_end - iter_x.pos;
-	  
+
 	  /* Normalize texture coordinates to current slice
              (rectangle texture targets take denormalized) */
           slice_tx1 /= iter_x.span->size;
           slice_tx2 /= iter_x.span->size;
-	  
+
 #if COGL_DEBUG
 	  printf("~~~~~ slice (%d,%d)\n", iter_x.index, iter_y.index);
 	  printf("qx1: %f\n", COGL_FIXED_TO_FLOAT (slice_qx1));
@@ -2210,26 +2276,23 @@ _cogl_texture_quad_sw (CoglTexture *tex,
 	  gl_handle = g_array_index (tex->slice_gl_handles, GLuint,
 				     iter_y.index * iter_x.array->len +
 				     iter_x.index);
-	  
-	  GE( cogl_gles2_wrapper_bind_texture (tex->gl_target, gl_handle,
-					       tex->gl_intformat) );
 
-#define CFX_F COGL_FIXED_TO_FLOAT
-	  
-	  /* Draw textured quad */
-          tex_coords[0] = CFX_F(slice_tx1); tex_coords[1] = CFX_F(slice_ty2);
-          tex_coords[2] = CFX_F(slice_tx2); tex_coords[3] = CFX_F(slice_ty2);
-          tex_coords[4] = CFX_F(slice_tx1); tex_coords[5] = CFX_F(slice_ty1);
-          tex_coords[6] = CFX_F(slice_tx2); tex_coords[7] = CFX_F(slice_ty1);
+          /* If we're using a different texture from the one already queued
+             then flush the vertices */
+          if (ctx->texture_vertices->len > 0
+              && gl_handle != ctx->texture_current)
+            _cogl_texture_flush_vertices ();
+          ctx->texture_target = tex->gl_target;
+          ctx->texture_current = gl_handle;
 
-          quad_coords[0] = CFX_F(slice_qx1); quad_coords[1] = CFX_F(slice_qy2);
-          quad_coords[2] = CFX_F(slice_qx2); quad_coords[3] = CFX_F(slice_qy2);
-          quad_coords[4] = CFX_F(slice_qx1); quad_coords[5] = CFX_F(slice_qy1);
-          quad_coords[6] = CFX_F(slice_qx2); quad_coords[7] = CFX_F(slice_qy1);
-
-	  GE (glDrawArrays (GL_TRIANGLE_STRIP, 0, 4) );
-
-#undef CFX_F
+          _cogl_texture_add_quad_vertices (COGL_FIXED_TO_FLOAT (slice_qx1),
+                                           COGL_FIXED_TO_FLOAT (slice_qy1),
+                                           COGL_FIXED_TO_FLOAT (slice_qx2),
+                                           COGL_FIXED_TO_FLOAT (slice_qy2),
+                                           COGL_FIXED_TO_FLOAT (slice_tx1),
+                                           COGL_FIXED_TO_FLOAT (slice_ty1),
+                                           COGL_FIXED_TO_FLOAT (slice_tx2),
+                                           COGL_FIXED_TO_FLOAT (slice_ty2));
 	}
     }
 }
@@ -2245,41 +2308,27 @@ _cogl_texture_quad_hw (CoglTexture *tex,
 		       CoglFixed tx2,
 		       CoglFixed ty2)
 {
-  GLfloat           tex_coords[8];
-  GLfloat           quad_coords[8];
   GLuint            gl_handle;
   CoglTexSliceSpan *x_span;
   CoglTexSliceSpan *y_span;
-  gulong            enable_flags = (COGL_ENABLE_TEXTURE_2D
-                                   | COGL_ENABLE_VERTEX_ARRAY
-                                   | COGL_ENABLE_TEXCOORD_ARRAY);
 
 #if COGL_DEBUG
   printf("=== Drawing Tex Quad (Hardware Tiling Mode) ===\n");
 #endif
-  
-  _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-  
-  /* Prepare GL state */
-  if (ctx->color_alpha < 255
-      || tex->bitmap.format & COGL_A_BIT)
-    {
-      enable_flags |= COGL_ENABLE_BLEND;
-    }
-  
-  if (ctx->enable_backface_culling)
-    enable_flags |= COGL_ENABLE_BACKFACE_CULLING;
 
-  cogl_enable (enable_flags);
-  
-  GE( glTexCoordPointer (2, GL_FLOAT, 0, tex_coords) );
-  GE( glVertexPointer   (2, GL_FLOAT, 0, quad_coords) );
-  
+  _COGL_GET_CONTEXT (ctx, NO_RETVAL);
+
   /* Pick and bind opengl texture object */
   gl_handle = g_array_index (tex->slice_gl_handles, GLuint, 0);
-  GE( cogl_gles2_wrapper_bind_texture (tex->gl_target, gl_handle,
-				       tex->gl_intformat) );
-  
+
+  /* If we're using a different texture from the one already queued
+     then flush the vertices */
+  if (ctx->texture_vertices->len > 0
+      && gl_handle != ctx->texture_current)
+    _cogl_texture_flush_vertices ();
+  ctx->texture_target = tex->gl_target;
+  ctx->texture_current = gl_handle;
+
   /* Don't include the waste in the texture coordinates */
   x_span = &g_array_index (tex->slice_x_spans, CoglTexSliceSpan, 0);
   y_span = &g_array_index (tex->slice_y_spans, CoglTexSliceSpan, 0);
@@ -2290,22 +2339,80 @@ _cogl_texture_quad_hw (CoglTexture *tex,
   ty1 = ty1 * (y_span->size - y_span->waste) / y_span->size;
   ty2 = ty2 * (y_span->size - y_span->waste) / y_span->size;
 
-#define CFX_F(x) COGL_FIXED_TO_FLOAT(x)
+  _cogl_texture_add_quad_vertices (COGL_FIXED_TO_FLOAT (x1),
+                                   COGL_FIXED_TO_FLOAT (y1),
+                                   COGL_FIXED_TO_FLOAT (x2),
+                                   COGL_FIXED_TO_FLOAT (y2),
+                                   COGL_FIXED_TO_FLOAT (tx1),
+                                   COGL_FIXED_TO_FLOAT (ty1),
+                                   COGL_FIXED_TO_FLOAT (tx2),
+                                   COGL_FIXED_TO_FLOAT (ty2));
+}
+
+void
+cogl_texture_multiple_rectangles (CoglHandle       handle,
+                                  const CoglFixed *verts,
+                                  guint            n_rects)
+{
+  CoglTexture    *tex;
+  gulong          enable_flags = (COGL_ENABLE_VERTEX_ARRAY
+                                  | COGL_ENABLE_TEXCOORD_ARRAY
+                                  | COGL_ENABLE_TEXTURE_2D);
+
+  _COGL_GET_CONTEXT (ctx, NO_RETVAL);
+
+  /* Check if valid texture */
+  if (!cogl_is_texture (handle))
+    return;
   
-  /* Draw textured quad */
-  tex_coords[0] = CFX_F(tx1); tex_coords[1] = CFX_F(ty2);
-  tex_coords[2] = CFX_F(tx2); tex_coords[3] = CFX_F(ty2);
-  tex_coords[4] = CFX_F(tx1); tex_coords[5] = CFX_F(ty1);
-  tex_coords[6] = CFX_F(tx2); tex_coords[7] = CFX_F(ty1);
+  cogl_clip_ensure ();
 
-  quad_coords[0] = CFX_F(x1); quad_coords[1] = CFX_F(y2);
-  quad_coords[2] = CFX_F(x2); quad_coords[3] = CFX_F(y2);
-  quad_coords[4] = CFX_F(x1); quad_coords[5] = CFX_F(y1);
-  quad_coords[6] = CFX_F(x2); quad_coords[7] = CFX_F(y1);
+  tex = _cogl_texture_pointer_from_handle (handle);
+  
+  /* Make sure we got stuff to draw */
+  if (tex->slice_gl_handles == NULL)
+    return;
+  
+  if (tex->slice_gl_handles->len == 0)
+    return;
 
-  GE (glDrawArrays (GL_TRIANGLE_STRIP, 0, 4) );
+  /* Prepare GL state */
+  if (ctx->color_alpha < 255
+      || tex->bitmap.format & COGL_A_BIT)
+    enable_flags |= COGL_ENABLE_BLEND;
 
-#undef CFX_F
+  if (ctx->enable_backface_culling)
+    enable_flags |= COGL_ENABLE_BACKFACE_CULLING;
+
+  cogl_enable (enable_flags);
+
+  g_array_set_size (ctx->texture_vertices, 0);
+
+  while (n_rects-- > 0)
+    {
+      if (verts[4] != verts[6] && verts[5] != verts[7])
+        {
+          /* If there is only one GL texture and either the texture is
+             NPOT (no waste) or all of the coordinates are in the
+             range [0,1] then we can use hardware tiling */
+          if (tex->slice_gl_handles->len == 1
+              && ((cogl_features_available (COGL_FEATURE_TEXTURE_NPOT)
+                   && tex->gl_target == GL_TEXTURE_2D)
+                  || (verts[4] >= 0 && verts[4] <= COGL_FIXED_1
+                      && verts[6] >= 0 && verts[6] <= COGL_FIXED_1
+                      && verts[5] >= 0 && verts[5] <= COGL_FIXED_1
+                      && verts[7] >= 0 && verts[7] <= COGL_FIXED_1)))
+            _cogl_texture_quad_hw (tex, verts[0],verts[1], verts[2],verts[3],
+                                   verts[4],verts[5], verts[6],verts[7]);
+          else
+            _cogl_texture_quad_sw (tex, verts[0],verts[1], verts[2],verts[3],
+                                   verts[4],verts[5], verts[6],verts[7]);
+        }
+
+      verts += 8;
+    }
+
+  _cogl_texture_flush_vertices ();
 }
 
 void
@@ -2319,47 +2426,18 @@ cogl_texture_rectangle (CoglHandle   handle,
 			CoglFixed tx2,
 			CoglFixed ty2)
 {
-  CoglTexture       *tex;
-  
-  /* Check if valid texture */
-  if (!cogl_is_texture (handle))
-    return;
+  CoglFixed verts[8];
 
-  cogl_clip_ensure ();
-  
-  tex = _cogl_texture_pointer_from_handle (handle);
-  
-  /* Make sure we got stuff to draw */
-  if (tex->slice_gl_handles == NULL)
-    return;
-  
-  if (tex->slice_gl_handles->len == 0)
-    return;
-  
-  if (tx1 == tx2 || ty1 == ty2)
-    return;
-  
-  /* Pick tiling mode according to hw support */
-  if (cogl_features_available (COGL_FEATURE_TEXTURE_NPOT)
-      && tex->slice_gl_handles->len == 1)
-    {
-      _cogl_texture_quad_hw (tex, x1,y1, x2,y2, tx1,ty1, tx2,ty2);
-    }
-  else
-    {
-      if (tex->slice_gl_handles->len == 1
-          && tx1 >= -COGL_FIXED_1
-          && tx2 <= COGL_FIXED_1
-          && ty1 >= -COGL_FIXED_1
-          && ty2 <= COGL_FIXED_1)
-	{
-	  _cogl_texture_quad_hw (tex, x1,y1, x2,y2, tx1,ty1, tx2,ty2);
-	}
-      else
-	{
-	  _cogl_texture_quad_sw (tex, x1,y1, x2,y2, tx1,ty1, tx2,ty2);
-	}
-    }
+  verts[0] = x1;
+  verts[1] = y1;
+  verts[2] = x2;
+  verts[3] = y2;
+  verts[4] = tx1;
+  verts[5] = ty1;
+  verts[6] = tx2;
+  verts[7] = ty2;
+
+  cogl_texture_multiple_rectangles (handle, verts, 1);
 }
 
 void
@@ -2405,23 +2483,9 @@ cogl_texture_polygon (CoglHandle         handle,
   /* Make sure there is enough space in the global texture vertex
      array. This is used so we can render the polygon with a single
      call to OpenGL but still support any number of vertices */
-  if (ctx->texture_vertices_size < n_vertices)
-    {
-      guint nsize = ctx->texture_vertices_size;
-      
-      if (nsize == 0)
-	nsize = 1;
-      do
-	nsize *= 2;
-      while (nsize < n_vertices);
-      
-      ctx->texture_vertices_size = nsize;
+  g_array_set_size (ctx->texture_vertices, n_vertices);
+  p = (CoglTextureGLVertex *) ctx->texture_vertices->data;
 
-      ctx->texture_vertices = g_realloc (ctx->texture_vertices,
-					 nsize
-					 * sizeof (CoglTextureGLVertex));
-    }
-  
   /* Prepare GL state */
   enable_flags = (COGL_ENABLE_TEXTURE_2D
 		  | COGL_ENABLE_VERTEX_ARRAY
@@ -2447,14 +2511,12 @@ cogl_texture_polygon (CoglHandle         handle,
   if (use_color)
     {
       enable_flags |= COGL_ENABLE_COLOR_ARRAY;
-      GE( glColorPointer (4, GL_UNSIGNED_BYTE, sizeof (CoglTextureGLVertex),
-			  ctx->texture_vertices[0].c) );
-    }
+      GE( glColorPointer (4, GL_UNSIGNED_BYTE,
+                          sizeof (CoglTextureGLVertex), p->c) );
+     }
 
-  GE( glVertexPointer (3, GL_FLOAT, sizeof (CoglTextureGLVertex),
-		       ctx->texture_vertices[0].v) );
-  GE( glTexCoordPointer (2, GL_FLOAT, sizeof (CoglTextureGLVertex),
-			 ctx->texture_vertices[0].t) );
+  GE( glVertexPointer (3, GL_FLOAT, sizeof (CoglTextureGLVertex), p->v ) );
+  GE( glTexCoordPointer (2, GL_FLOAT, sizeof (CoglTextureGLVertex), p->t ) );
 
   cogl_enable (enable_flags);
   
@@ -2464,7 +2526,7 @@ cogl_texture_polygon (CoglHandle         handle,
 
   /* Convert the vertices into an array of GLfloats ready to pass to
      OpenGL */
-  for (i = 0, p = ctx->texture_vertices; i < n_vertices; i++, p++)
+  for (i = 0; i < n_vertices; i++, p++)
     {
 #define CFX_F COGL_FIXED_TO_FLOAT