Index: clutter/sogl-sdl/sogl-utils.c
===================================================================
--- clutter/sogl-sdl/sogl-utils.c	(revision 0)
+++ clutter/sogl-sdl/sogl-utils.c	(revision 0)
@@ -0,0 +1,82 @@
+
+#include <stdlib.h>
+#include "sogl-utils.h"
+
+SoglList *
+sogl_list_prepend (SoglList *list, void *data)
+{
+	SoglList *l = malloc (sizeof (SoglList));
+	l->data = data;
+	l->prev = NULL;
+	l->next = list;
+	if (list) {
+		while (list->prev) list = list->prev;
+		list->prev = l;
+	}
+	return l;
+}
+
+SoglList *
+sogl_list_append (SoglList *list, void *data)
+{
+	SoglList *orig = list;
+	SoglList *l = malloc (sizeof (SoglList));
+	l->data = data;
+	l->prev = list;
+	l->next = NULL;
+	if (list) {
+		while (list->next) list = list->next;
+		list->next = l;
+	}
+	return orig ? orig : l;
+}
+
+SoglList *
+sogl_list_insert_before (SoglList *list, void *data)
+{
+	SoglList *l = calloc (1, sizeof (SoglList));
+	l->data = data;
+	if (list) {
+		l->next = list;
+		if (list->prev) {
+			list->prev->next = l;
+			l->prev = list->prev;
+		} else
+			l->prev = NULL;
+		list->prev = l;
+	}
+	return l;
+}
+
+SoglList *
+sogl_list_remove (SoglList *list, SoglList *link)
+{
+	SoglList *ret = (list == link) ? list->next : list;
+	if (link->prev) link->prev->next = link->next;
+	if (link->next) link->next->prev = link->prev;
+	free (link);
+	return ret;
+}
+
+SoglList *
+sogl_list_find (SoglList *list, void *data,
+		int (*find_cb)(void *data, void *ldata))
+{
+	SoglList *l;
+	for (l = list; l; l = l->next) {
+		if (find_cb) {
+			if (find_cb (data, l->data) == 0) break;
+		} else if (l->data == data) break;
+	}
+	return l;
+}
+
+int
+sogl_list_length (SoglList *list)
+{
+	int i;
+	SoglList *l;
+	for (l = list, i = 0; l; l = l->next, i++);
+	return i;
+}
+
Index: clutter/sogl-sdl/sogl-texture.c
===================================================================
--- clutter/sogl-sdl/sogl-texture.c	(revision 0)
+++ clutter/sogl-sdl/sogl-texture.c	(revision 0)
@@ -0,0 +1,62 @@
+
+#include <stdlib.h>
+#include <string.h>
+#include "sogl-texture.h"
+
+SoglTexture *
+sogl_texture_new (unsigned int width, unsigned int height,
+		  const unsigned char *pixels)
+{
+	unsigned int i;
+	SoglTexture *tex;
+	
+	tex = malloc (sizeof (SoglTexture));
+	tex->width = width;
+	tex->height = height;
+	tex->pixels = malloc (sizeof (SoglColor) * width * height);
+	tex->row_lookup = malloc (sizeof (unsigned int) * height);
+
+	for (i = 0; i < height; i++)
+		tex->row_lookup[i] = i * width;
+
+	if (pixels) {
+		memcpy (tex->pixels, pixels,
+			width * height * sizeof (SoglColor));
+	}
+	
+	return tex;
+}
+
+SoglTexture *
+sogl_texture_new_subtex (unsigned int x, unsigned int y,
+			 unsigned int width, unsigned int height,
+			 SoglTexture *texture)
+{
+	unsigned int row;
+	SoglTexture *tex;
+	
+	tex = sogl_texture_new (width, height, NULL);
+	for (row = 0; row < height; row++) {
+		memcpy (tex->pixels + (row * width),
+			texture->pixels + x +
+			((y + row) * texture->width),
+			width * sizeof (SoglColor));
+	}
+	
+	return tex;
+}
+
+void
+sogl_texture_free (SoglTexture *texture)
+{
+	free (texture->pixels);
+	free (texture->row_lookup);
+	free (texture);
+}
+
+SoglColor *
+sogl_texture_get (SoglTexture *texture, int x, int y)
+{
+	return & texture->pixels[texture->row_lookup[y] + x];
+}
+
Index: clutter/sogl-sdl/clutter-stage-sdl.c
===================================================================
--- clutter/sogl-sdl/clutter-stage-sdl.c	(revision 0)
+++ clutter/sogl-sdl/clutter-stage-sdl.c	(revision 0)
@@ -0,0 +1,242 @@
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "clutter-stage-sdl.h"
+#include "clutter-sdl.h"
+
+#include "../clutter-main.h"
+#include "../clutter-feature.h"
+#include "../clutter-color.h"
+#include "../clutter-util.h"
+#include "../clutter-event.h"
+#include "../clutter-enum-types.h"
+#include "../clutter-private.h"
+#include "../clutter-debug.h"
+#include "../clutter-units.h"
+
+#include "cogl.h"
+#include "sogl.h"
+
+G_DEFINE_TYPE (ClutterStageSDL, clutter_stage_sdl, CLUTTER_TYPE_STAGE);
+
+SoglCanvas *canvas;
+SDL_Surface *screen, *buffer;
+
+static void
+clutter_stage_sdl_show (ClutterActor *actor)
+{
+  CLUTTER_ACTOR_SET_FLAGS (actor, CLUTTER_ACTOR_MAPPED);
+
+  CLUTTER_ACTOR_CLASS (clutter_stage_sdl_parent_class)->show (actor);
+}
+
+static void
+clutter_stage_sdl_hide (ClutterActor *actor)
+{
+  /* No way to easily unmap SDL window ? */
+  CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_MAPPED);
+
+  CLUTTER_ACTOR_CLASS (clutter_stage_sdl_parent_class)->hide (actor);
+}
+
+static void
+clutter_stage_sdl_unrealize (ClutterActor *actor)
+{
+  ;
+}
+
+static void
+clutter_stage_sdl_realize (ClutterActor *actor)
+{
+  ClutterStageSDL *stage_sdl = CLUTTER_STAGE_SDL (actor);
+
+  gboolean is_offscreen, is_fullscreen;
+  ClutterPerspective perspective;
+
+  CLUTTER_NOTE (BACKEND, "Realizing main stage");
+
+  g_object_get (actor, "offscreen", &is_offscreen, NULL);
+  g_object_get (actor, "fullscreen", &is_fullscreen, NULL);
+
+  if (G_LIKELY (!is_offscreen))
+    {
+      gint flags = SDL_HWSURFACE;
+
+      if (is_fullscreen) flags |= SDL_FULLSCREEN;
+
+      /*SDL_GL_SetAttribute(SDL_GL_ACCUM_RED_SIZE, 0);
+      SDL_GL_SetAttribute(SDL_GL_ACCUM_GREEN_SIZE, 0);
+      SDL_GL_SetAttribute(SDL_GL_ACCUM_BLUE_SIZE, 0);
+      SDL_GL_SetAttribute(SDL_GL_ACCUM_ALPHA_SIZE, 0);*/
+
+      if (!(screen = SDL_SetVideoMode(stage_sdl->win_width, 
+			   stage_sdl->win_height, 
+			   32, flags)))
+	{
+	  CLUTTER_NOTE (BACKEND, "SDL appears not to handle this mode - %s",
+			SDL_GetError());
+	  CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED);
+	  return;
+	}
+    }
+  else
+    {
+      /* FIXME */
+      g_warning("SDL Backend does not yet support offscreen rendering\n");
+      CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED);
+      return;
+    }
+
+  CLUTTER_SET_PRIVATE_FLAGS(actor, CLUTTER_ACTOR_SYNC_MATRICES);
+}
+
+static void
+clutter_stage_sdl_query_coords (ClutterActor    *self,
+                                   ClutterActorBox *box)
+{
+  ClutterStageSDL *stage_sdl = CLUTTER_STAGE_SDL (self);
+
+  box->x1 = box->y1 = 0;
+  box->x2 = box->x1 + CLUTTER_UNITS_FROM_INT (stage_sdl->win_width);
+  box->y2 = box->y1 + CLUTTER_UNITS_FROM_INT (stage_sdl->win_height);
+}
+
+static void
+clutter_stage_sdl_request_coords (ClutterActor    *self,
+				  ClutterActorBox *box)
+{
+  ClutterStageSDL *stage_sdl = CLUTTER_STAGE_SDL (self);
+  gint new_width, new_height;
+
+  /* FIXME: some how have X configure_notfiys call this ? */
+  new_width  = ABS (CLUTTER_UNITS_TO_INT (box->x2 - box->x1));
+  new_height = ABS (CLUTTER_UNITS_TO_INT (box->y2 - box->y1));
+
+  if (new_width != stage_sdl->win_width ||
+      new_height != stage_sdl->win_height)
+    {
+      if (!(screen = SDL_SetVideoMode(new_width, 
+			   new_height, 
+			   32, SDL_HWSURFACE)))
+	{
+	  box->x2 = box->x1 + stage_sdl->win_width;
+	  box->y2 = box->y1 + stage_sdl->win_height;
+
+	  /* Failed */
+	  return;
+	}
+
+      stage_sdl->win_width  = new_width;
+      stage_sdl->win_height = new_height;
+      sogl_canvas_resize (canvas, new_width, new_height);
+      SDL_FreeSurface (buffer);
+      buffer = SDL_CreateRGBSurfaceFrom (canvas->buffer->pixels,
+                                         canvas->buffer->width,
+                                         canvas->buffer->height, 32,
+                                         sizeof (SoglColor) *
+                                                 canvas->buffer->width,
+                                         0x000000FF, 0x0000FF00,
+                                         0x00FF0000, 0xFF000000);
+
+      CLUTTER_SET_PRIVATE_FLAGS(self, CLUTTER_ACTOR_SYNC_MATRICES);
+    }
+}
+
+static void
+clutter_stage_sdl_set_fullscreen (ClutterStage *stage,
+                                  gboolean      fullscreen)
+{
+  ClutterStageSDL *stage_sdl = CLUTTER_STAGE_SDL (stage);
+  int              flags = SDL_HWSURFACE;
+
+  if (fullscreen) flags |= SDL_FULLSCREEN;
+
+  screen = SDL_SetVideoMode(stage_sdl->win_width,
+		   stage_sdl->win_height,
+		   32, flags);
+}
+
+static void
+clutter_stage_sdl_set_cursor_visible (ClutterStage *stage,
+                                      gboolean      show_cursor)
+{
+  SDL_ShowCursor(show_cursor);
+}
+
+static void
+clutter_stage_sdl_set_offscreen (ClutterStage *stage,
+                                 gboolean      offscreen)
+{
+  g_warning ("Stage of type `%s' do not support ClutterStage::set_offscreen",
+             G_OBJECT_TYPE_NAME (stage));
+}
+
+static GdkPixbuf*
+clutter_stage_sdl_draw_to_pixbuf (ClutterStage *stage,
+                                  GdkPixbuf    *dest,
+                                  gint          x,
+                                  gint          y,
+                                  gint          width,
+                                  gint          height)
+{
+  g_warning ("Stage of type `%s' do not support ClutterStage::draw_to_pixbuf",
+             G_OBJECT_TYPE_NAME (stage));
+  return NULL;
+}
+
+static void
+clutter_stage_sdl_set_title (ClutterStage *stage,
+			     const gchar  *title)
+{
+  SDL_WM_SetCaption  (title, NULL);
+}
+
+static void
+clutter_stage_sdl_dispose (GObject *gobject)
+{
+  ClutterStageSDL *stage_sdl = CLUTTER_STAGE_SDL (gobject);
+
+  clutter_actor_unrealize (CLUTTER_ACTOR (stage_sdl));
+
+  G_OBJECT_CLASS (clutter_stage_sdl_parent_class)->dispose (gobject);
+}
+
+static void
+clutter_stage_sdl_class_init (ClutterStageSDLClass *klass)
+{
+  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+  ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
+  ClutterStageClass *stage_class = CLUTTER_STAGE_CLASS (klass);
+
+  gobject_class->dispose = clutter_stage_sdl_dispose;
+  
+  actor_class->show = clutter_stage_sdl_show;
+  actor_class->hide = clutter_stage_sdl_hide;
+  actor_class->realize = clutter_stage_sdl_realize;
+  actor_class->unrealize = clutter_stage_sdl_unrealize;
+  actor_class->request_coords = clutter_stage_sdl_request_coords;
+  actor_class->query_coords = clutter_stage_sdl_query_coords;
+  
+  stage_class->set_fullscreen = clutter_stage_sdl_set_fullscreen;
+  stage_class->set_cursor_visible = clutter_stage_sdl_set_cursor_visible;
+  stage_class->set_offscreen = clutter_stage_sdl_set_offscreen;
+  stage_class->draw_to_pixbuf = clutter_stage_sdl_draw_to_pixbuf;
+  stage_class->set_title = clutter_stage_sdl_set_title;
+}
+
+static void
+clutter_stage_sdl_init (ClutterStageSDL *stage)
+{
+  stage->win_width = 640;
+  stage->win_height = 480;
+  canvas = sogl_canvas_new (640, 480, 0);
+  buffer = SDL_CreateRGBSurfaceFrom (canvas->buffer->pixels,
+                                     canvas->buffer->width,
+                                     canvas->buffer->height, 32,
+                                     sizeof (SoglColor) *
+                                             canvas->buffer->width,
+                                     0x000000FF, 0x0000FF00,
+                                     0x00FF0000, 0xFF000000);
+}
+
Index: clutter/sogl-sdl/sogl-matrix.c
===================================================================
--- clutter/sogl-sdl/sogl-matrix.c	(revision 0)
+++ clutter/sogl-sdl/sogl-matrix.c	(revision 0)
@@ -0,0 +1,123 @@
+
+#include "sogl-matrix.h"
+
+void
+sogl_matrix_mult (float a[4*4], float b[4*4], float c[4*4])
+{
+#define midx(m,y,x) m[(y*4)+x]
+	int i, j, k;
+
+	for (i = 0; i < 4; i++) {
+		for (j = 0; j < 4; j++) {
+			midx(c,i,j) = 0;
+			for (k = 0; k < 4; k++) {
+				midx(c,i,j) += midx(a,i,k) * midx(b,k,j);
+			}
+		}
+	}
+#undef midx
+}
+
+void
+sogl_matrix_identity (float m[4*4])
+{
+	m[0] = 1;
+	m[1] = 0;
+	m[2] = 0;
+	m[3] = 0;
+
+	m[4] = 0;
+	m[5] = 1;
+	m[6] = 0;
+	m[7] = 0;
+
+	m[8] = 0;
+	m[9] = 0;
+	m[10] = 1;
+	m[11] = 0;
+	
+	m[12] = 0;
+	m[13] = 0;
+	m[14] = 0;
+	m[15] = 1;
+}
+
+void
+sogl_matrix_translate (SoglPoint *vector, float m[4*4])
+{
+	m[0] = 1;
+	m[1] = 0;
+	m[2] = 0;
+	m[3] = 0;
+
+	m[4] = 0;
+	m[5] = 1;
+	m[6] = 0;
+	m[7] = 0;
+
+	m[8] = 0;
+	m[9] = 0;
+	m[10] = 1;
+	m[11] = 0;
+	
+	m[12] = vector->x;
+	m[13] = vector->y;
+	m[14] = vector->z;
+	m[15] = 1;
+}
+
+void
+sogl_matrix_scale (SoglPoint *scale, float m[4*4])
+{
+	m[0] = scale->x;
+	m[1] = 0;
+	m[2] = 0;
+	m[3] = 0;
+
+	m[4] = 0;
+	m[5] = scale->y;
+	m[6] = 0;
+	m[7] = 0;
+
+	m[8] = 0;
+	m[9] = 0;
+	m[10] = scale->z;
+	m[11] = 0;
+	
+	m[12] = 0;
+	m[13] = 0;
+	m[14] = 0;
+	m[15] = 1;
+}
+
+void
+sogl_matrix_rotate (SoglPoint *axis, float angle, float m[4*4])
+{
+	float c, s;
+	SoglPoint naxis;
+	
+	sogl_point_normalise (axis, &naxis);
+	c = cos (angle);
+	s = sin (angle);
+	
+	m[0] = naxis.x * naxis.x * (1-c) + c;
+	m[1] = naxis.x * naxis.y * (1-c) - naxis.z * s;
+	m[2] = naxis.x * naxis.z * (1-c) + naxis.y * s;
+	m[3] = 0;
+	
+	m[4] = naxis.y * naxis.x * (1-c) + naxis.z * s;
+	m[5] = naxis.y * naxis.y * (1-c) + c;
+	m[6] = naxis.y * naxis.z * (1-c) - naxis.x * s;
+	m[7] = 0;
+	
+	m[8] = naxis.x * naxis.z * (1-c) - naxis.y * s;
+	m[9] = naxis.y * naxis.z * (1-c) - naxis.x * s;
+	m[10] = naxis.z * naxis.z * (1-c) + c;
+	m[11] = 0;
+	
+	m[12] = 0;
+	m[13] = 0;
+	m[14] = 0;
+	m[15] = 1;
+}
+
Index: clutter/sogl-sdl/sogl-texture.h
===================================================================
--- clutter/sogl-sdl/sogl-texture.h	(revision 0)
+++ clutter/sogl-sdl/sogl-texture.h	(revision 0)
@@ -0,0 +1,32 @@
+
+#ifndef SOGL_TEXTURE_H
+#define SOGL_TEXTURE_H
+
+typedef struct {
+	unsigned char r;
+	unsigned char g;
+	unsigned char b;
+	unsigned char a;
+} __attribute__((__packed__)) SoglColor;
+
+typedef struct {
+	SoglColor *pixels;
+	unsigned int *row_lookup;
+	unsigned int width;
+	unsigned int height;
+	unsigned int id;
+} SoglTexture;
+
+SoglTexture *sogl_texture_new (unsigned int width, unsigned int height,
+			       const unsigned char *pixels);
+
+SoglTexture *sogl_texture_new_subtex (unsigned int x1, unsigned int y1,
+				      unsigned int x2, unsigned int y2,
+				      SoglTexture *texture);
+
+void sogl_texture_free (SoglTexture *texture);
+
+SoglColor * sogl_texture_get (SoglTexture *texture, int x, int y);
+
+#endif /* SOGL_TEXTURE_H */
+
Index: clutter/sogl-sdl/clutter-sdl.h
===================================================================
--- clutter/sogl-sdl/clutter-sdl.h	(revision 0)
+++ clutter/sogl-sdl/clutter-sdl.h	(revision 0)
@@ -0,0 +1,39 @@
+/*
+ * Clutter.
+ *
+ * An OpenGL based 'interactive canvas' library.
+ *
+ * Authored By Matthew Allum  <mallum@openedhand.com>
+ *
+ * Copyright (C) 2006 OpenedHand
+ *
+ * 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, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __CLUTTER_SDL_H__
+#define __CLUTTER_SDL_H__
+
+#include <glib.h>
+#include <SDL.h>
+
+#include <clutter/clutter-stage.h>
+
+G_BEGIN_DECLS
+
+
+G_END_DECLS
+
+#endif /* __CLUTTER_SDL_H__ */
Index: clutter/sogl-sdl/sogl-utils.h
===================================================================
--- clutter/sogl-sdl/sogl-utils.h	(revision 0)
+++ clutter/sogl-sdl/sogl-utils.h	(revision 0)
@@ -0,0 +1,36 @@
+
+#ifndef SOGL_UTILS_H
+#define SOGL_UTILS_H
+
+#include <math.h>
+
+#ifndef MIN
+#  define MIN(a,b) (((a) < (b)) ? (a) : (b))
+#endif
+
+#ifndef ABS
+#  define ABS(a) (((a) < 0) ? (-(a)) : (a))
+#endif
+
+#ifndef DEG2RAD
+#  define DEG2RAD(x)	((x)*(M_PI/180))
+#endif
+
+typedef struct _SoglList SoglList;
+
+struct _SoglList {
+	SoglList *prev;
+	SoglList *next;
+	void *data;
+};
+
+SoglList *sogl_list_prepend (SoglList *list, void *data);
+SoglList *sogl_list_append (SoglList *list, void *data);
+SoglList *sogl_list_insert_before (SoglList *list, void *data);
+SoglList *sogl_list_remove (SoglList *list, SoglList *link);
+SoglList *sogl_list_find (SoglList *list, void *data,
+			  int (*find_cb)(void *data, void *ldata));
+int sogl_list_length (SoglList *list);
+
+#endif /* SOGL_UTILS_H */
+
Index: clutter/sogl-sdl/clutter-stage-sdl.h
===================================================================
--- clutter/sogl-sdl/clutter-stage-sdl.h	(revision 0)
+++ clutter/sogl-sdl/clutter-stage-sdl.h	(revision 0)
@@ -0,0 +1,32 @@
+#ifndef __CLUTTER_STAGE_SDL_H__
+#define __CLUTTER_STAGE_SDL_H__
+
+#include <glib-object.h>
+#include <clutter/clutter-stage.h>
+
+#define CLUTTER_TYPE_STAGE_SDL                  (clutter_stage_sdl_get_type ())
+#define CLUTTER_STAGE_SDL(obj)                  (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_STAGE_SDL, ClutterStageSDL))
+#define CLUTTER_IS_STAGE_SDL(obj)               (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_STAGE_SDL))
+#define CLUTTER_STAGE_SDL_CLASS(klass)          (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_STAGE_SDL, ClutterStageSDLClass))
+#define CLUTTER_IS_STAGE_SDL_CLASS(klass)       (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_STAGE_SDL))
+#define CLUTTER_STAGE_SDL_GET_CLASS(obj)        (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_STAGE_SDL, ClutterStageSDLClass))
+
+typedef struct _ClutterStageSDL         ClutterStageSDL;
+typedef struct _ClutterStageSDLClass    ClutterStageSDLClass;
+
+struct _ClutterStageSDL
+{
+  ClutterStage parent_instance;
+
+  gint         win_width;
+  gint         win_height;
+};
+
+struct _ClutterStageSDLClass
+{
+  ClutterStageClass parent_class;
+};
+
+GType clutter_stage_sdl_get_type (void) G_GNUC_CONST;
+
+#endif /* __CLUTTER_STAGE_SDL_H__ */
Index: clutter/sogl-sdl/sogl.h
===================================================================
--- clutter/sogl-sdl/sogl.h	(revision 0)
+++ clutter/sogl-sdl/sogl.h	(revision 0)
@@ -0,0 +1,12 @@
+
+#ifndef SOGL_H
+#define SOGL_H
+
+#include "sogl-canvas.h"
+#include "sogl-texture.h"
+#include "sogl-poly.h"
+#include "sogl-utils.h"
+#include "sogl-matrix.h"
+
+#endif /* SOGL_H */
+
Index: clutter/sogl-sdl/sogl-matrix.h
===================================================================
--- clutter/sogl-sdl/sogl-matrix.h	(revision 0)
+++ clutter/sogl-sdl/sogl-matrix.h	(revision 0)
@@ -0,0 +1,14 @@
+
+#ifndef SOGL_MATRIX_H
+#define SOGL_MATRIX_H
+
+#include "sogl-poly.h"
+
+void sogl_matrix_mult (float a[4*4], float b[4*4], float c[4*4]);
+void sogl_matrix_identity (float m[4*4]);
+void sogl_matrix_translate (SoglPoint *vector, float m[4*4]);
+void sogl_matrix_scale (SoglPoint *scale, float m[4*4]);
+void sogl_matrix_rotate (SoglPoint *axis, float angle, float m[4*4]);
+
+#endif /* SOGL_MATRIX_H */
+
Index: clutter/sogl-sdl/sogl-canvas.c
===================================================================
--- clutter/sogl-sdl/sogl-canvas.c	(revision 0)
+++ clutter/sogl-sdl/sogl-canvas.c	(revision 0)
@@ -0,0 +1,133 @@
+
+#include <stdlib.h>
+#include "sogl-canvas.h"
+#include "sogl-matrix.h"
+
+SoglCanvas *
+sogl_canvas_new (unsigned int width, unsigned int height, int page_flip)
+{
+	int i;
+	SoglCanvas *canvas;
+	
+	canvas = calloc (1, sizeof (SoglCanvas));
+	canvas->pages[0] = sogl_texture_new (width, height, NULL);
+	if (page_flip)
+		canvas->pages[1] = sogl_texture_new (width, height, NULL);
+	else
+		canvas->pages[1] = NULL;
+	canvas->buffer = canvas->pages[0];
+	canvas->sbuffer = malloc (sizeof (int *) * height);
+	for (i = 0; i < height; i++)
+		canvas->sbuffer[i] = calloc (2, sizeof (int));
+	canvas->color.a = 255;
+	sogl_canvas_clear (canvas);
+	canvas->color.r = 255;
+	canvas->color.g = 255;
+	canvas->color.b = 255;
+	
+	canvas->z_near = 1;
+	sogl_canvas_set_fov (canvas, DEG2RAD(65));
+	
+	/* Set identity matrix */
+	sogl_matrix_identity (canvas->m);
+	
+	return canvas;
+}
+
+void
+sogl_canvas_free (SoglCanvas *canvas)
+{
+	int i;
+	
+	while (canvas->textures) {
+		sogl_texture_free ((SoglTexture *)canvas->textures->data);
+		canvas->textures = sogl_list_remove (canvas->textures,
+			canvas->textures);
+	}
+	
+	for (i = 0; i < canvas->buffer->height; i++)
+		free (canvas->sbuffer[i]);
+	free (canvas->sbuffer);
+	
+	if (canvas->pages[0]) sogl_texture_free (canvas->pages[0]);
+	if (canvas->pages[1]) sogl_texture_free (canvas->pages[1]);
+
+	free (canvas);
+}
+
+void
+sogl_canvas_resize (SoglCanvas *canvas, unsigned int width, unsigned int height)
+{
+	int i, flip = 0;
+	
+	if (canvas->sbuffer) {
+		for (i = 0; i < canvas->buffer->height; i++)
+			free (canvas->sbuffer[i]);
+		free (canvas->sbuffer);
+	}
+
+	if (canvas->pages[0]) sogl_texture_free (canvas->pages[0]);
+	if (canvas->pages[1]) {
+		sogl_texture_free (canvas->pages[1]);
+		flip = 1;
+	}
+	
+	canvas->pages[0] = sogl_texture_new (width, height, NULL);
+	if (flip)
+		canvas->pages[1] = sogl_texture_new (width, height, NULL);
+	
+	canvas->buffer = canvas->pages[0];
+
+	canvas->sbuffer = malloc (sizeof (int *) * height);
+	for (i = 0; i < height; i++)
+		canvas->sbuffer[i] = calloc (2, sizeof (int));
+}
+
+void
+sogl_canvas_flip (SoglCanvas *canvas)
+{
+	if (canvas->buffer == canvas->pages[0])
+		canvas->buffer = canvas->pages[1];
+	else
+		canvas->buffer = canvas->pages[0];
+}
+
+void
+sogl_canvas_clear (SoglCanvas *canvas)
+{
+	unsigned int x, y;
+	
+	for (y = 0; y < canvas->buffer->height; y++) {
+		for (x = 0; x < canvas->buffer->width; x++) {
+			sogl_canvas_plot (canvas, x, y);
+		}
+	}
+}
+
+void
+sogl_canvas_plot (SoglCanvas *canvas, unsigned int x, unsigned int y)
+{
+	SoglColor *pixel = sogl_texture_get (canvas->buffer, x, y);
+	if ((x < 0) || (y < 0) || (x >= canvas->buffer->width) ||
+	    (y >= canvas->buffer->height)) return;
+	if (canvas->color.a < 255) {
+		float alpha = (float)canvas->color.a/255;
+		pixel->r = MIN ((int)(pixel->r + (canvas->color.r * alpha)),
+			255);
+		pixel->g = MIN ((int)(pixel->g + (canvas->color.g * alpha)),
+			255);
+		pixel->b = MIN ((int)(pixel->b + (canvas->color.b * alpha)),
+			255);
+		pixel->a = 255;
+	} else {
+		*pixel = canvas->color;
+	}
+}
+
+void
+sogl_canvas_set_fov (SoglCanvas *canvas, float fov)
+{
+	canvas->fov = fov;
+	canvas->fovMult = (canvas->buffer->width/2) / (float)tan (fov/2);
+}
+
Index: clutter/sogl-sdl/clutter-event-sdl.c
===================================================================
--- clutter/sogl-sdl/clutter-event-sdl.c	(revision 0)
+++ clutter/sogl-sdl/clutter-event-sdl.c	(revision 0)
@@ -0,0 +1,353 @@
+/* Clutter.
+ * An OpenGL based 'interactive canvas' library.
+ * Authored By Matthew Allum  <mallum@openedhand.com>
+ * Copyright (C) 2006-2007 OpenedHand
+ *
+ * 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, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "clutter-stage-sdl.h"
+#include "clutter-backend-sdl.h"
+#include "clutter-sdl.h"
+
+#include "../clutter-backend.h"
+#include "../clutter-event.h"
+#include "../clutter-private.h"
+#include "../clutter-debug.h"
+#include "../clutter-main.h"
+#include "../clutter-keysyms.h"
+
+#include <string.h>
+#include <glib.h>
+
+typedef struct _ClutterEventSource ClutterEventSource;
+
+struct _ClutterEventSource
+{
+  GSource source;
+
+  ClutterBackend *backend;
+};
+
+static gboolean clutter_event_prepare  (GSource     *source,
+                                        gint        *timeout);
+static gboolean clutter_event_check    (GSource     *source);
+static gboolean clutter_event_dispatch (GSource     *source,
+                                        GSourceFunc  callback,
+                                        gpointer     user_data);
+
+static GList *event_sources = NULL;
+
+static GSourceFuncs event_funcs = {
+  clutter_event_prepare,
+  clutter_event_check,
+  clutter_event_dispatch,
+  NULL
+};
+
+static GSource *
+clutter_event_source_new (ClutterBackend *backend)
+{
+  GSource *source = g_source_new (&event_funcs, sizeof (ClutterEventSource));
+  ClutterEventSource *event_source = (ClutterEventSource *) source;
+
+  event_source->backend = backend;
+
+  return source;
+}
+
+void
+_clutter_events_init (ClutterBackend *backend)
+{
+  GSource *source;
+  ClutterEventSource *event_source;
+  ClutterBackendSDL *backend_sdl = CLUTTER_BACKEND_SDL (backend);
+
+  source = backend_sdl->event_source = clutter_event_source_new (backend);
+  event_source = (ClutterEventSource *) source;
+  g_source_set_priority (source, CLUTTER_PRIORITY_EVENTS);
+
+  event_sources = g_list_prepend (event_sources, event_source);
+
+  g_source_set_can_recurse (source, TRUE);
+  g_source_attach (source, NULL);
+}
+
+void
+_clutter_events_uninit (ClutterBackend *backend)
+{
+  ClutterBackendSDL *backend_sdl = CLUTTER_BACKEND_SDL (backend);
+
+  if (backend_sdl->event_source)
+    {
+      CLUTTER_NOTE (EVENT, "Destroying the event source");
+
+      event_sources = g_list_remove (event_sources,
+                                     backend_sdl->event_source);
+
+      g_source_destroy (backend_sdl->event_source);
+      g_source_unref (backend_sdl->event_source);
+      backend_sdl->event_source = NULL;
+    }
+}
+
+static gboolean
+clutter_event_prepare (GSource *source,
+                       gint    *timeout)
+{
+  SDL_Event events;
+  int       num_events;
+  gboolean retval;
+
+  clutter_threads_enter ();
+
+  num_events = SDL_PeepEvents(&events, 1, SDL_PEEKEVENT, SDL_ALLEVENTS);
+
+  if (num_events == 1)
+    {
+      clutter_threads_leave ();
+
+      *timeout = 0;
+      return TRUE;
+    }
+
+  if (num_events == -1)
+    g_warning("Error polling SDL: %s", SDL_GetError());
+
+  *timeout = 50;
+
+  retval = clutter_events_pending ();
+
+  clutter_threads_leave ();
+
+  return retval;
+}
+
+static gboolean
+clutter_event_check (GSource *source)
+{
+  SDL_Event events;
+  int       num_events;
+  gboolean  retval;
+
+  clutter_threads_enter ();
+
+  /* Pump SDL */
+  SDL_PumpEvents();
+
+  num_events = SDL_PeepEvents(&events, 1, SDL_PEEKEVENT, SDL_ALLEVENTS);
+
+  if (num_events == -1)
+    g_warning("Error polling SDL: %s", SDL_GetError());
+
+  retval = (num_events == 1 || clutter_events_pending ());
+
+  clutter_threads_leave ();
+
+  return retval;
+}
+
+static void
+key_event_translate (ClutterEvent   *event,
+		     SDL_Event      *sdl_event)
+{
+  event->key.time = 0;
+
+  /* FIXME: This is just a quick hack to make SDL keys roughly work.
+   * Fixing it properly is left as a exercise to someone who enjoys
+   * battleing the SDL API.
+   *
+   * We probably need to use sdl_event->key.keysym.unicode to do lookups
+   * and I have no idea how to get shifted keysyms. It looks quite easy
+   * if you drop into xlib but that then avoids the whole point of using
+   * SDL in the first place (More portability than just GLX)
+  */
+
+  switch(sdl_event->key.keysym.sym)
+    {
+    case SDLK_UP:        event->key.keyval = CLUTTER_Up; break;
+    case SDLK_DOWN:      event->key.keyval = CLUTTER_Down; break;
+    case SDLK_LEFT:      event->key.keyval = CLUTTER_Left; break;
+    case SDLK_RIGHT:     event->key.keyval = CLUTTER_Right; break;
+    case SDLK_HOME:      event->key.keyval = CLUTTER_Home; break;
+    case SDLK_END:       event->key.keyval = CLUTTER_End; break;
+    case SDLK_PAGEUP:    event->key.keyval = CLUTTER_Page_Up; break;
+    case SDLK_PAGEDOWN:  event->key.keyval = CLUTTER_Page_Down; break;
+    case SDLK_BACKSPACE: event->key.keyval = CLUTTER_BackSpace; break;
+    case SDLK_DELETE:    event->key.keyval = CLUTTER_Delete; break;
+    default:
+      event->key.keyval = sdl_event->key.keysym.sym;
+  }
+
+  event->key.hardware_keycode = sdl_event->key.keysym.scancode;
+
+  if (sdl_event->key.keysym.mod & KMOD_CTRL)
+    event->key.modifier_state
+      = event->key.modifier_state & CLUTTER_CONTROL_MASK;
+
+  if (sdl_event->key.keysym.mod & KMOD_SHIFT)
+    event->key.modifier_state
+      = event->key.modifier_state & CLUTTER_SHIFT_MASK;
+}
+
+static gboolean
+event_translate (ClutterBackend *backend,
+		 ClutterEvent   *event,
+		 SDL_Event      *sdl_event)
+{
+  gboolean res;
+
+  res = TRUE;
+
+  switch (sdl_event->type)
+    {
+    case SDL_KEYDOWN:
+      event->type = CLUTTER_KEY_PRESS;
+      key_event_translate (event, sdl_event);
+      break;
+
+    case SDL_KEYUP:
+      event->type = CLUTTER_KEY_RELEASE;
+      key_event_translate (event, sdl_event);
+      break;
+
+    case SDL_MOUSEBUTTONDOWN:
+      switch (sdl_event->button.button)
+        {
+        case 4: /* up */
+        case 5: /* down */
+        case 6: /* left */
+        case 7: /* right */
+          event->scroll.type = event->type = CLUTTER_SCROLL;
+
+          if (sdl_event->button.button == 4)
+            event->scroll.direction = CLUTTER_SCROLL_UP;
+          else if (sdl_event->button.button == 5)
+            event->scroll.direction = CLUTTER_SCROLL_DOWN;
+          else if (sdl_event->button.button == 6)
+            event->scroll.direction = CLUTTER_SCROLL_LEFT;
+          else
+            event->scroll.direction = CLUTTER_SCROLL_RIGHT;
+
+          event->scroll.time = 0;
+          event->scroll.x = sdl_event->button.x;
+          event->scroll.y = sdl_event->button.y;
+          event->scroll.modifier_state = sdl_event->button.state;
+
+          break;
+        default:
+          event->button.type = event->type = CLUTTER_BUTTON_PRESS;
+          event->button.time = 0;
+          event->button.x = sdl_event->button.x;
+          event->button.y = sdl_event->button.y;
+          event->button.modifier_state = sdl_event->button.state;
+          event->button.button = sdl_event->button.button;
+          break;
+        }
+      break;
+
+    case SDL_MOUSEBUTTONUP:
+      /* scroll events don't have a corresponding release */
+      if (sdl_event->button.button == 4 ||
+          sdl_event->button.button == 5 ||
+          sdl_event->button.button == 6 ||
+          sdl_event->button.button == 7)
+        {
+          res = FALSE;
+          break;
+        }
+
+      event->button.type = event->type = CLUTTER_BUTTON_RELEASE;
+      event->button.time = 0;
+      event->button.x = sdl_event->button.x;
+      event->button.y = sdl_event->button.y;
+      event->button.modifier_state = sdl_event->button.state;
+      event->button.button = sdl_event->button.button;
+      break;
+
+    case SDL_MOUSEMOTION:
+      event->motion.type = event->type = CLUTTER_MOTION;
+      event->motion.time = 0;
+      event->motion.x = sdl_event->motion.x;
+      event->motion.y = sdl_event->motion.y;
+      event->motion.modifier_state = sdl_event->motion.state;;
+      break;
+
+    default:
+      res = FALSE;
+      break;
+    }
+
+  return res;
+}
+
+
+static gboolean
+clutter_event_dispatch (GSource     *source,
+                        GSourceFunc  callback,
+                        gpointer     user_data)
+{
+  SDL_Event            sdl_event;
+  ClutterEvent        *event = NULL;
+  ClutterBackend      *backend = ((ClutterEventSource *) source)->backend;
+  ClutterMainContext  *clutter_context;
+
+  clutter_threads_enter ();
+
+  clutter_context = clutter_context_get_default ();
+
+  while (SDL_PollEvent(&sdl_event))
+    {
+      /* FIXME: essentially translate events and push them onto the queue
+       *        below will then pop them out via _clutter_events_queue.
+       */
+      if (sdl_event.type == SDL_QUIT)
+	{
+	  SDL_Quit();
+	  exit(0);
+	}
+      else
+	{
+	  event = clutter_event_new (CLUTTER_NOTHING);
+
+	  if (event_translate (backend, event, &sdl_event))
+	    {
+	      /* push directly here to avoid copy of queue_put */
+	      g_queue_push_head (clutter_context->events_queue, event);
+	    }
+	  else
+	    {
+	      clutter_event_free (event);
+	    }
+	}
+    }
+
+  event = clutter_event_get ();
+
+  if (event)
+    {
+      clutter_do_event(event);
+      clutter_event_free (event);
+    }
+
+  clutter_threads_leave ();
+
+  return TRUE;
+}
Index: clutter/sogl-sdl/sogl-canvas.h
===================================================================
--- clutter/sogl-sdl/sogl-canvas.h	(revision 0)
+++ clutter/sogl-sdl/sogl-canvas.h	(revision 0)
@@ -0,0 +1,37 @@
+
+#ifndef SOGL_CANVAS_H
+#define SOGL_CANVAS_H
+
+typedef struct _SoglCanvas SoglCanvas;
+
+#include "sogl-utils.h"
+#include "sogl-texture.h"
+#include "sogl-poly.h"
+
+struct _SoglCanvas {
+	SoglTexture *buffer;
+	SoglTexture *pages[2];
+	int **sbuffer;
+	SoglList *textures;
+	
+	SoglColor color;
+	SoglTexture *texture;
+	
+	float m[4*4];
+	float fov;
+	float fovMult;
+	float z_near;
+};
+
+SoglCanvas * sogl_canvas_new (unsigned int width, unsigned int height,
+			      int page_flip);
+void sogl_canvas_free (SoglCanvas *canvas);
+void sogl_canvas_resize (SoglCanvas *canvas,
+			 unsigned int width, unsigned int height);
+void sogl_canvas_flip (SoglCanvas *canvas);
+void sogl_canvas_clear (SoglCanvas *canvas);
+void sogl_canvas_plot (SoglCanvas *canvas, unsigned int x, unsigned int y);
+void sogl_canvas_set_fov (SoglCanvas *canvas, float fov);
+
+#endif /* SOGL_CANVAS_H */
+
Index: clutter/sogl-sdl/sogl-poly.c
===================================================================
--- clutter/sogl-sdl/sogl-poly.c	(revision 0)
+++ clutter/sogl-sdl/sogl-poly.c	(revision 0)
@@ -0,0 +1,499 @@
+
+#include "sogl-poly.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+
+void
+sogl_point_mult_scalar (SoglPoint *point, SoglPoint *dest, float mult)
+{
+	dest->x = point->x * mult;
+	dest->y = point->y * mult;
+	dest->z = point->z * mult;
+}
+
+float
+sogl_point_dot (SoglPoint *a, SoglPoint *b)
+{
+	return (a->x * b->x) + (a->y * b->y) + (a->z * b->z);
+}
+
+void
+sogl_point_normalise (SoglPoint *p, SoglPoint *dest)
+{
+	float mag = sqrt ((p->x*p->x) + (p->y*p->y) + (p->z*p->z));
+	dest->x = p->x / mag;
+	dest->y = p->y / mag;
+	dest->z = p->z / mag;
+}
+
+void
+sogl_point_cross (SoglPoint *a, SoglPoint *b, SoglPoint *dest)
+{
+	dest->x = (a->y * b->z) - (a->z * b->y);
+	dest->y = -((a->x * b->z) - (a->z * b->x));
+	dest->z = (a->x * b->y) - (a->y * b->x);
+}
+
+void
+sogl_point_add (SoglPoint *point1, SoglPoint *point2, SoglPoint *dest)
+{
+	dest->x = point1->x + point2->x;
+	dest->y = point1->y + point2->y;
+	dest->z = point1->z + point2->z;
+}
+
+void
+sogl_point_sub (SoglPoint *point1, SoglPoint *point2, SoglPoint *dest)
+{
+	dest->x = point1->x - point2->x;
+	dest->y = point1->y - point2->y;
+	dest->z = point1->z - point2->z;
+}
+
+void
+sogl_point_project (SoglPoint *point, int *x, int *y, float fovMult)
+{
+	*x = fovMult * point->x / point->z;
+	*y = fovMult * point->y / point->z;
+}
+
+void
+sogl_point_transform (SoglPoint *point, SoglPoint *dest, float *m)
+{
+#define midx(m,y,x) m[(y*4)+x]
+	dest->x = (midx(m,0,0) * point->x) +
+		(midx(m,1,0) * point->y) +
+		(midx(m,2,0) * point->z) + midx(m,3,0);
+	dest->y = (midx(m,0,1) * point->x) +
+		(midx(m,1,1) * point->y) +
+		(midx(m,2,1) * point->z) + midx(m,3,1);
+	dest->z = (midx(m,0,2) * point->x) +
+		(midx(m,1,2) * point->y) +
+		(midx(m,2,2) * point->z) + midx(m,3,2);
+#undef midx
+}
+
+void
+sogl_poly_transform (SoglPoly *poly, SoglPoly *dest, float *m)
+{
+	unsigned int i;
+	SoglPoint point;
+	
+	/* Transform texture coordinates */
+	sogl_point_transform (&poly->p, &dest->p, m);
+
+	sogl_point_add (&poly->p, &poly->m, &point);
+	sogl_point_transform (&point, &dest->m, m);
+	sogl_point_sub (&dest->m, &dest->p, &dest->m);
+	
+	sogl_point_add (&poly->p, &poly->n, &point);
+	sogl_point_transform (&point, &dest->n, m);
+	sogl_point_sub (&dest->n, &dest->p, &dest->n);
+	
+	/* Transform points */
+	for (i = 0; i < poly->npoints; i++)
+		sogl_point_transform (&poly->points[i], &dest->points[i], m);
+	dest->npoints = poly->npoints;
+	dest->texture = poly->texture;
+}
+
+static void
+sogl_poly_z_clip (SoglPoly *poly, SoglPoly *dest, float zmin)
+{
+	SoglPoint *p1;
+	unsigned int i, j;
+	
+	/* TODO: Add clipping against a far plane */
+	
+	p1 = &poly->points[poly->npoints - 1];
+	for (i = 0, j = 0; i < poly->npoints; i++) {
+		SoglPoint *p2 = &poly->points[i];
+		if ((p1->z >= zmin) && (p2->z >= zmin)) {
+			/* Type 1 edge - entirely inside */
+			dest->points[j] = *p2;
+			j++;
+		} else if ((p1->z < zmin) && (p2->z < zmin)) {
+			/* Type 2 edge - entirely outside */
+		} else if ((p1->z >= zmin) && (p2->z < zmin)) {
+			/* Type 3 edge - leaving view volume */
+			float t = (zmin - p1->z) / (p2->z - p1->z);
+			dest->points[j].x = p1->x + (p2->x - p1->x) * t;
+			dest->points[j].y = p1->y + (p2->y - p1->y) * t;
+			dest->points[j].z = zmin;
+			j++;
+		} else if ((p1->z < zmin) && (p2->z >= zmin)) {
+			/* Type 4 edge - entering view volume */
+			float t = (zmin - p1->z) / (p2->z - p1->z);
+			dest->points[j].x = p1->x + (p2->x - p1->x) * t;
+			dest->points[j].y = p1->y + (p2->y - p1->y) * t;
+			dest->points[j].z = zmin;
+			j++;
+			dest->points[j] = *p2;
+			j++;
+		}
+		p1 = p2;
+	}
+	dest->npoints = j;
+	
+	dest->p = poly->p;
+	dest->m = poly->m;
+	dest->n = poly->n;
+	dest->texture = poly->texture;
+}
+
+static void
+sogl_poly2d_clip (int poly2d[SOGL_POINTS_SIZE][2],
+		  int dest[SOGL_POINTS_SIZE][2], int npoints,
+		  int *npointsd, int xmin, int ymin, int xmax, int ymax)
+{
+	int i, j;
+	int *p1;
+	int poly2di[SOGL_POINTS_SIZE][2];
+	
+	/* Clip against right edge */
+	p1 = poly2d[npoints-1];
+	for (i = 0, j = 0; i < npoints; i++) {
+		int *p2 = poly2d[i];
+		if ((p1[0] <= xmax) && (p2[0] <= xmax)) {
+			/* Edge inside */
+			poly2di[j][0] = p2[0];
+			poly2di[j][1] = p2[1];
+			j++;
+		} else if ((p1[0] > xmax) && (p2[0] > xmax)) {
+			/* Edge outside */
+		} else if ((p1[0] <= xmax) && (p2[0] > xmax)) {
+			/* Edge leaving */
+			int temp = p2[0] - p1[0];
+			if (temp != 0) {
+				float m = (float)(p2[1]-p1[1]) / (float)temp;
+				poly2di[j][1] = (int)(p1[1] + m * (xmax - p1[0]));
+			} else {
+				poly2di[j][1] = p1[1];
+			}
+			poly2di[j][0] = xmax;
+			j++;
+		} else if ((p1[0] > xmax) && (p2[0] <= xmax)) {
+			/* Edge entering */
+			int temp = p2[0]-p1[0];
+			if (temp != 0) {
+				float m = (float)(p2[1]-p1[1]) / (float)temp;
+				poly2di[j][1] = (int)(p1[1] + m * (xmax - p1[0]));
+			} else {
+				poly2di[j][1] = p1[1];
+			}
+			poly2di[j][0] = xmax;
+			j++;
+			poly2di[j][0] = p2[0];
+			poly2di[j][1] = p2[1];
+			j++;
+		}
+		p1 = p2;
+	}
+	*npointsd = j;
+	
+	if (*npointsd < 3) return;
+	
+	/* Clip against left edge */
+	p1 = poly2di[*npointsd-1];
+	for (i = 0, j = 0; i < *npointsd; i++) {
+		int *p2 = poly2di[i];
+		if ((p1[0] >= xmin) && (p2[0] >= xmin)) {
+			dest[j][0] = p2[0];
+			dest[j][1] = p2[1];
+			j++;
+		} else if ((p1[0] < xmin) && (p2[0] < xmin)) {
+		} else if ((p1[0] >= xmin) && (p2[0] < xmin)) {
+			int temp = p2[0]-p1[0];
+			if (temp != 0) {
+				float m = (float)(p2[1]-p1[1]) / (float)temp;
+				dest[j][1] = (int)(p1[1] + m * (xmin - p1[0]));
+			} else {
+				dest[j][1] = p1[1];
+			}
+			dest[j][0] = xmin;
+			j++;
+		} else if ((p1[0] < xmin) && (p2[0] >= xmin)) {
+			int temp = p2[0]-p1[0];
+			if (temp != 0) {
+				float m = (float)(p2[1]-p1[1]) / (float)temp;
+				dest[j][1] = (int)(p1[1] + m * (xmin - p1[0]));
+			} else {
+				dest[j][1] = p1[1];
+			}
+			dest[j][0] = xmin;
+			j++;
+			dest[j][0] = p2[0];
+			dest[j][1] = p2[1];
+			j++;
+		}
+		p1 = p2;
+	}
+	*npointsd = j;
+	
+	if (*npointsd < 3) return;
+
+	/* Clip against upper edge */
+	p1 = dest[*npointsd-1];
+	for (i = 0, j = 0; i < *npointsd; i++) {
+		int *p2 = dest[i];
+		if ((p1[1] >= ymin) && (p2[1] >= ymin)) {
+			poly2di[j][0] = p2[0];
+			poly2di[j][1] = p2[1];
+			j++;
+		} else if ((p1[1] < ymin) && (p2[1] < ymin)) {
+		} else if ((p1[1] >= ymin) && (p2[1] < ymin)) {
+			int temp = p2[0] - p1[0];
+			if (temp != 0) {
+				float m = (float)(p2[1]-p1[1]) / (float)temp;
+				poly2di[j][0] = (int)(p1[0] + (ymin - p1[1])/m);
+			} else {
+				poly2di[j][0] = p1[0];
+			}
+			poly2di[j][1] = ymin;
+			j++;
+		} else if ((p1[1] < ymin) && (p2[1] >= ymin)) {
+			int temp = p2[0] - p1[0];
+			if (temp != 0) {
+				float m = (float)(p2[1]-p1[1]) / (float)temp;
+				poly2di[j][0] = (int)(p1[0] + (ymin - p1[1])/m);
+			} else {
+				poly2di[j][0] = p1[0];
+			}
+			poly2di[j][1] = ymin;
+			j++;
+			poly2di[j][0] = p2[0];
+			poly2di[j][1] = p2[1];
+			j++;
+		}
+		p1 = p2;
+	}
+	*npointsd = j;
+	
+	if (*npointsd < 3) return;
+
+	/* Clip against lower edge */
+	p1 = poly2di[*npointsd-1];
+	for (i = 0, j = 0; i < *npointsd; i++) {
+		int *p2 = poly2di[i];
+		if ((p1[1] <= ymax) && (p2[1] <= ymax)) {
+			dest[j][0] = p2[0];
+			dest[j][1] = p2[1];
+			j++;
+		} else if ((p1[1] > ymax) && (p2[1] > ymax)) {
+		} else if ((p1[1] <= ymax) && (p2[1] > ymax)) {
+			int temp = p2[0] - p1[0];
+			if (temp != 0) {
+				float m = (float)(p2[1]-p1[1]) / (float)temp;
+				dest[j][0] = (int)(p1[0] + (ymax - p1[1])/m);
+			} else {
+				dest[j][0] = p1[0];
+			}
+			dest[j][1] = ymax;
+			j++;
+		} else if ((p1[1] > ymax) && (p2[1] <= ymax)) {
+			int temp = p2[0] - p1[0];
+			if (temp != 0) {
+				float m = (float)(p2[1]-p1[1]) / (float)temp;
+				dest[j][0] = (int)(p1[0] + (ymax - p1[1])/m);
+			} else {
+				dest[j][0] = p1[0];
+			}
+			dest[j][1] = ymax;
+			j++;
+			dest[j][0] = p2[0];
+			dest[j][1] = p2[1];
+			j++;
+		}
+		p1 = p2;
+	}
+	*npointsd = j;
+}
+
+static void
+sogl_poly_scanlines (int poly2d[SOGL_POINTS_SIZE][2], int npoints,
+		     SoglCanvas *canvas, int miny)
+{
+	int i;
+	int p1[2];
+	p1[0] = poly2d[npoints-1][0];
+	p1[1] = poly2d[npoints-1][1];
+	for (i = 0; i < npoints; i++) {
+		int steep;
+		int x, dx, dy, e, ystep, y;
+		int p2[2];
+		p2[0] = poly2d[i][0];
+		p2[1] = poly2d[i][1];
+		
+		/*printf ("Line from %d, %d to %d, %d\n", p1[0], p1[1], p2[0], p2[1]);*/
+
+		/* Bresenham line algorithm */
+		steep = (ABS (p2[1] - p1[1]) > ABS (p2[0] - p1[0])) ? 1 : 0;
+		if (steep) {
+			int temp = p1[0];
+			p1[0] = p1[1];
+			p1[1] = temp;
+			temp = p2[0];
+			p2[0] = p2[1];
+			p2[1] = temp;
+		}
+		
+		if (p1[0] > p2[0]) {
+			int temp = p1[0];
+			p1[0] = p2[0];
+			p2[0] = temp;
+			temp = p1[1];
+			p1[1] = p2[1];
+			p2[1] = temp;
+		}
+		
+		dx = p2[0] - p1[0];
+		dy = ABS (p2[1] - p1[1]);
+		e = 0;
+		ystep = (p1[1] < p2[1]) ? 1 : -1;
+		y = p1[1];
+		
+		for (x = p1[0]; x <= p2[0]; x++) {
+			int px, py;
+			if (steep) {
+				px = y;
+				py = x - miny;
+			} else {
+				px = x;
+				py = y - miny;
+			}
+			
+			if (px <= canvas->sbuffer[py][0])
+				canvas->sbuffer[py][0] = px;
+			if (px >= canvas->sbuffer[py][1])
+				canvas->sbuffer[py][1] = px;
+			
+			e += dy;
+			if ((e * 2) >= dx) {
+				y += ystep;
+				e -= dx;
+			}
+		}
+		
+		p1[0] = poly2d[i][0];
+		p1[1] = poly2d[i][1];
+	}
+}
+
+void
+sogl_poly_render (SoglPoly *poly, SoglCanvas *canvas)
+{
+	int i, miny, maxy;
+	SoglPoint a, b, c, s;
+	SoglPoly tpoly, cpoly;
+	int poly2d[SOGL_POINTS_SIZE][2];
+	int poly2dc[SOGL_POINTS_SIZE][2], npointsc;
+
+	/* Transform polygon and clip against the near z plane */	
+	sogl_poly_transform (poly, &tpoly, canvas->m);
+	/*for (i = 0; i < tpoly.npoints; i++) {
+		printf ("3d Point: %f, %f, %f\n", tpoly.points[i].x,
+			tpoly.points[i].y, tpoly.points[i].z);
+	}*/
+	sogl_poly_z_clip (&tpoly, &cpoly, canvas->z_near);
+	
+	/* Project polygon onto 2d space */
+	for (i = 0; i < cpoly.npoints; i++) {
+		sogl_point_project (&cpoly.points[i],
+			&poly2d[i][0], &poly2d[i][1], canvas->fovMult);
+		/*printf ("2d Point: %d, %d\n", poly2d[i][0], poly2d[i][1]);*/
+	}
+	
+	/* Clip into canvas */
+	sogl_poly2d_clip (poly2d, poly2dc, cpoly.npoints,
+		&npointsc, -(canvas->buffer->width/2),
+		-(canvas->buffer->height/2),
+		(canvas->buffer->width/2)-1,
+		(canvas->buffer->height/2)-1);
+	if (npointsc < 3) return;
+	
+	/* Get min/max y, clear scanline buffer and get scalines for poly */
+	miny = 0x7FFFFFFF;
+	maxy = -0x7FFFFFFF;
+	for (i = 0; i < npointsc; i++) {
+		if (poly2dc[i][1] < miny) miny = poly2dc[i][1];
+		if (poly2dc[i][1] > maxy) maxy = poly2dc[i][1];
+	}
+	
+	for (i = 0; i < (maxy - miny); i++) {
+		canvas->sbuffer[i][0] = 0x7FFFFFFF;
+		canvas->sbuffer[i][1] = -0x7FFFFFFF;
+	}
+	sogl_poly_scanlines (poly2dc, npointsc, canvas, miny);
+
+	if (!poly->texture) {
+		/* Draw block-shaded polygon */
+		for (i = 0; i < (maxy - miny); i++) {
+			int j;
+			for (j = canvas->sbuffer[i][0];
+			     j < canvas->sbuffer[i][1]; j++){
+				sogl_canvas_plot (canvas,
+					j + canvas->buffer->width/2,
+					i + miny + canvas->buffer->height/2);
+			}
+		}
+		return;
+	}
+	
+	/* Draw textured polygon */
+	sogl_point_cross (&cpoly.p, &cpoly.n, &a);
+	sogl_point_mult_scalar (&a, &a, poly->texture->width);
+	sogl_point_cross (&cpoly.m, &cpoly.p, &b);
+	sogl_point_mult_scalar (&b, &b, poly->texture->height);
+	sogl_point_cross (&cpoly.n, &cpoly.m, &c);
+
+	/*s.x = canvas->sbuffer[0][0];
+	s.y = miny;*/
+	s.z = canvas->fovMult;
+	for (i = 0; i < (maxy - miny); i++) {
+		int j;
+		float sa, sb, sc;
+		
+		s.x = canvas->sbuffer[i][0];
+		s.y = i + miny;
+		
+		sa = sogl_point_dot (&s, &a);
+		sb = sogl_point_dot (&s, &b);
+		sc = sogl_point_dot (&s, &c);
+		
+		for (j = canvas->sbuffer[i][0];
+		     j < canvas->sbuffer[i][1]; j++) {
+			float u = sa/sc;
+			float v = sb/sc;
+			
+			if (u < 0) u = 0;
+			else if (u >= poly->texture->width)
+				u = poly->texture->width - 1;
+			if (v < 0) v = 0;
+			else if (v >= poly->texture->height)
+				v = poly->texture->height - 1;
+			
+			sa += a.x;
+			sb += b.x;
+			sc += c.x;
+			
+			canvas->color = poly->texture->pixels[
+				(int)u + ((int)v * poly->texture->width)];
+			sogl_canvas_plot (canvas, j + canvas->buffer->width/2,
+				s.y + canvas->buffer->height/2);
+		}
+	}
+}
+
+SoglPoly *
+sogl_poly_new ()
+{
+	return (SoglPoly *)calloc (1, sizeof (SoglPoly));
+}
+
+void
+sogl_poly_free (SoglPoly *poly)
+{
+	free (poly);
+}
+
Index: clutter/sogl-sdl/clutter-backend-sdl.c
===================================================================
--- clutter/sogl-sdl/clutter-backend-sdl.c	(revision 0)
+++ clutter/sogl-sdl/clutter-backend-sdl.c	(revision 0)
@@ -0,0 +1,231 @@
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "clutter-backend-sdl.h"
+#include "clutter-stage-sdl.h"
+#include "../clutter-private.h"
+#include "../clutter-main.h"
+#include "../clutter-debug.h"
+
+#include "sogl.h"
+
+static ClutterBackendSDL *backend_singleton = NULL;
+
+extern SoglCanvas *canvas;
+extern SDL_Surface *screen, *buffer;
+
+G_DEFINE_TYPE (ClutterBackendSDL, clutter_backend_sdl, CLUTTER_TYPE_BACKEND);
+
+static gboolean
+clutter_backend_sdl_pre_parse (ClutterBackend  *backend,
+                               GError         **error)
+{
+  return TRUE;
+}
+
+static gboolean
+clutter_backend_sdl_post_parse (ClutterBackend  *backend,
+                                GError         **error)
+{
+  int                err;
+
+  if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE) < 0)
+    {
+      g_set_error (error, CLUTTER_INIT_ERROR,
+		   CLUTTER_INIT_ERROR_BACKEND,
+		   "Unable to Initialize SDL");
+      return FALSE;
+    }
+
+  err = 0;
+/*#if defined(WIN32)
+  err = SDL_GL_LoadLibrary("opengl32.dll");
+#elif defined(__linux__) || defined(__FreeBSD__)
+  err = SDL_GL_LoadLibrary("libGL.so");
+#else
+#error Your platform is not supported
+  err = 1;
+#endif*/
+  if (err != 0)
+    {
+      g_set_error (error, CLUTTER_INIT_ERROR,
+		   CLUTTER_INIT_ERROR_BACKEND,
+		   SDL_GetError());
+      return FALSE;
+    }
+
+  return TRUE;
+}
+
+static gboolean
+clutter_backend_sdl_init_stage (ClutterBackend  *backend,
+                                GError         **error)
+{
+  ClutterBackendSDL *backend_sdl = CLUTTER_BACKEND_SDL (backend);
+
+  if (!backend_sdl->stage)
+    {
+      ClutterStageSDL *stage_sdl;
+      ClutterActor    *stage;
+
+      stage = g_object_new (CLUTTER_TYPE_STAGE_SDL, NULL);
+
+      /* copy backend data into the stage */
+      stage_sdl = CLUTTER_STAGE_SDL (stage);
+
+      g_object_set_data (G_OBJECT (stage), "clutter-backend", backend);
+
+      backend_sdl->stage = g_object_ref_sink (stage);
+    }
+
+  clutter_actor_realize (backend_sdl->stage);
+
+  if (!CLUTTER_ACTOR_IS_REALIZED (backend_sdl->stage))
+    {
+      g_set_error (error, CLUTTER_INIT_ERROR,
+                   CLUTTER_INIT_ERROR_INTERNAL,
+                   "Unable to realize the main stage");
+      return FALSE;
+    }
+
+  return TRUE;
+}
+
+static void
+clutter_backend_sdl_init_events (ClutterBackend *backend)
+{
+  _clutter_events_init (backend);
+
+}
+
+static const GOptionEntry entries[] =
+{
+  { NULL }
+};
+
+
+static void
+clutter_backend_sdl_add_options (ClutterBackend *backend,
+                                 GOptionGroup   *group)
+{
+  g_option_group_add_entries (group, entries);
+}
+
+static ClutterActor *
+clutter_backend_sdl_get_stage (ClutterBackend *backend)
+{
+  ClutterBackendSDL *backend_sdl = CLUTTER_BACKEND_SDL (backend);
+
+  return backend_sdl->stage;
+}
+
+static void
+clutter_backend_sdl_redraw (ClutterBackend *backend)
+{
+  ClutterBackendSDL *backend_sdl = CLUTTER_BACKEND_SDL (backend);
+  ClutterStageSDL   *stage_sdl;
+
+  stage_sdl = CLUTTER_STAGE_SDL(backend_sdl->stage);
+
+  clutter_actor_paint (CLUTTER_ACTOR(stage_sdl));
+  
+  SDL_BlitSurface (buffer, NULL, screen, NULL);
+  SDL_Flip (screen);
+}
+
+static void
+clutter_backend_sdl_finalize (GObject *gobject)
+{
+  SDL_Quit();
+
+  if (backend_singleton)
+    backend_singleton = NULL;
+
+  G_OBJECT_CLASS (clutter_backend_sdl_parent_class)->finalize (gobject);
+}
+
+static void
+clutter_backend_sdl_dispose (GObject *gobject)
+{
+  ClutterBackendSDL *backend_sdl = CLUTTER_BACKEND_SDL (gobject);
+
+  _clutter_events_uninit (CLUTTER_BACKEND (backend_sdl));
+
+  if (backend_sdl->stage)
+    {
+      CLUTTER_UNSET_PRIVATE_FLAGS (backend_sdl->stage,
+                                   CLUTTER_ACTOR_IS_TOPLEVEL);
+      clutter_actor_destroy (backend_sdl->stage);
+      backend_sdl->stage = NULL;
+    }
+
+  G_OBJECT_CLASS (clutter_backend_sdl_parent_class)->dispose (gobject);
+}
+
+static GObject *
+clutter_backend_sdl_constructor (GType                  gtype,
+                                 guint                  n_params,
+                                 GObjectConstructParam *params)
+{
+  GObjectClass *parent_class;
+  GObject *retval;
+
+  if (!backend_singleton)
+    {
+      parent_class = G_OBJECT_CLASS (clutter_backend_sdl_parent_class);
+      retval = parent_class->constructor (gtype, n_params, params);
+
+      backend_singleton = CLUTTER_BACKEND_SDL (retval);
+
+      return retval;
+    }
+
+  g_warning ("Attempting to create a new backend object. This should "
+             "never happen, so we return the singleton instance.");
+  
+  return g_object_ref (backend_singleton);
+}
+
+static ClutterFeatureFlags
+clutter_backend_sdl_get_features (ClutterBackend *backend)
+{
+  return CLUTTER_FEATURE_STAGE_CURSOR;
+}
+
+static void
+clutter_backend_sdl_class_init (ClutterBackendSDLClass *klass)
+{
+  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+  ClutterBackendClass *backend_class = CLUTTER_BACKEND_CLASS (klass);
+
+  gobject_class->constructor = clutter_backend_sdl_constructor;
+  gobject_class->dispose = clutter_backend_sdl_dispose;
+  gobject_class->finalize = clutter_backend_sdl_finalize;
+
+  backend_class->pre_parse = clutter_backend_sdl_pre_parse;
+  backend_class->post_parse = clutter_backend_sdl_post_parse;
+  backend_class->init_stage = clutter_backend_sdl_init_stage;
+  backend_class->init_events = clutter_backend_sdl_init_events;
+  backend_class->get_stage = clutter_backend_sdl_get_stage;
+  backend_class->add_options = clutter_backend_sdl_add_options;
+  backend_class->redraw      = clutter_backend_sdl_redraw;
+  backend_class->get_features = clutter_backend_sdl_get_features;
+}
+
+static void
+clutter_backend_sdl_init (ClutterBackendSDL *backend_sdl)
+{
+  ClutterBackend *backend = CLUTTER_BACKEND (backend_sdl);
+
+  clutter_backend_set_resolution (backend, 96.0);
+  clutter_backend_set_double_click_time (backend, 250);
+  clutter_backend_set_double_click_distance (backend, 5);
+}
+
+GType
+_clutter_backend_impl_get_type (void)
+{
+  return clutter_backend_sdl_get_type ();
+}
+
Index: clutter/sogl-sdl/Makefile.am
===================================================================
--- clutter/sogl-sdl/Makefile.am	(revision 0)
+++ clutter/sogl-sdl/Makefile.am	(revision 0)
@@ -0,0 +1,35 @@
+libclutterincludedir = $(includedir)/clutter-@CLUTTER_API_VERSION@/clutter
+libclutterinclude_HEADERS = clutter-sdl.h
+
+INCLUDES = \
+	-DG_LOG_DOMAIN=\"ClutterSDL\" \
+	-I$(top_srcdir) \
+	-I$(top_srcdir)/clutter/cogl 	        \
+	-I$(top_srcdir)/clutter/cogl/@CLUTTER_COGL@ \
+	$(CLUTTER_CFLAGS) \
+	$(CLUTTER_DEBUG_CFLAGS) \
+	$(GCC_FLAGS)
+
+LDADD = $(CLUTTER_LIBS)
+
+noinst_LTLIBRARIES = libclutter-sogl-sdl.la
+
+libclutter_sogl_sdl_la_SOURCES = \
+	clutter-backend-sdl.h \
+	clutter-backend-sdl.c \
+	clutter-event-sdl.c \
+	clutter-stage-sdl.h \
+	clutter-stage-sdl.c \
+	clutter-sdl.h \
+	sogl.h \
+	sogl-canvas.h \
+	sogl-canvas.c \
+	sogl-matrix.h \
+	sogl-matrix.c \
+	sogl-poly.h \
+	sogl-poly.c \
+	sogl-texture.h \
+	sogl-texture.c \
+	sogl-utils.h \
+	sogl-utils.c
+
Index: clutter/sogl-sdl/sogl-poly.h
===================================================================
--- clutter/sogl-sdl/sogl-poly.h	(revision 0)
+++ clutter/sogl-sdl/sogl-poly.h	(revision 0)
@@ -0,0 +1,43 @@
+
+#ifndef SOGL_POLY_H
+#define SOGL_POLY_H
+
+#include "sogl-utils.h"
+#include "sogl-texture.h"
+#include "sogl-canvas.h"
+
+#define SOGL_MAX_POINTS 4
+#define SOGL_POINTS_SIZE 8
+
+typedef struct {
+	float x;
+	float y;
+	float z;
+} SoglPoint;
+
+typedef struct {
+	SoglPoint points[SOGL_POINTS_SIZE];
+	unsigned int npoints;
+	
+	SoglTexture *texture;
+	SoglPoint p;
+	SoglPoint m;
+	SoglPoint n;
+} SoglPoly;
+
+void sogl_point_normalise (SoglPoint *p, SoglPoint *dest);
+void sogl_point_mult_scalar (SoglPoint *point, SoglPoint *dest, float mult);
+float sogl_point_dot (SoglPoint *a, SoglPoint *b);
+void sogl_point_cross (SoglPoint *a, SoglPoint *b, SoglPoint *dest);
+void sogl_point_add (SoglPoint *point1, SoglPoint *point2, SoglPoint *dest);
+void sogl_point_sub (SoglPoint *point1, SoglPoint *point2, SoglPoint *dest);
+void sogl_point_project (SoglPoint *point, int *x, int *y, float fovMult);
+void sogl_point_transform (SoglPoint *point, SoglPoint *dest, float *m);
+
+SoglPoly * sogl_poly_new ();
+void sogl_poly_free (SoglPoly *poly);
+void sogl_poly_transform (SoglPoly *poly, SoglPoly *dest, float *m);
+void sogl_poly_render (SoglPoly *poly, SoglCanvas *canvas);
+
+#endif /* SOGL_POLY_H */
+
Index: clutter/sogl-sdl/clutter-backend-sdl.h
===================================================================
--- clutter/sogl-sdl/clutter-backend-sdl.h	(revision 0)
+++ clutter/sogl-sdl/clutter-backend-sdl.h	(revision 0)
@@ -0,0 +1,66 @@
+/* Clutter.
+ * An OpenGL based 'interactive canvas' library.
+ * Authored By Matthew Allum  <mallum@openedhand.com>
+ * Copyright (C) 2006-2007 OpenedHand
+ *
+ * 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, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __CLUTTER_BACKEND_SDL_H__
+#define __CLUTTER_BACKEND_SDL_H__
+
+#include <glib-object.h>
+#include <clutter/clutter-backend.h>
+#include <SDL.h>
+
+G_BEGIN_DECLS
+
+#define CLUTTER_TYPE_BACKEND_SDL                (clutter_backend_sdl_get_type ())
+#define CLUTTER_BACKEND_SDL(obj)                (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_BACKEND_SDL, ClutterBackendSDL))
+#define CLUTTER_IS_BACKEND_SDL(obj)             (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_BACKEND_SDL))
+#define CLUTTER_BACKEND_SDL_CLASS(klass)        (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_BACKEND_SDL, ClutterBackendSDLClass))
+#define CLUTTER_IS_BACKEND_SDL_CLASS(klass)     (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_BACKEND_SDL))
+#define CLUTTER_BACKEND_SDL_GET_CLASS(obj)      (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_BACKEND_SDL, ClutterBackendSDLClass))
+
+typedef struct _ClutterBackendSDL       ClutterBackendSDL;
+typedef struct _ClutterBackendSDLClass  ClutterBackendSDLClass;
+
+struct _ClutterBackendSDL
+{
+  ClutterBackend parent_instance;
+
+  /* main stage singleton */
+  ClutterActor *stage;
+
+  /* event source */
+  GSource *event_source;
+
+  /*< private >*/
+};
+
+struct _ClutterBackendSDLClass
+{
+  ClutterBackendClass parent_class;
+};
+
+GType clutter_backend_sdl_get_type (void) G_GNUC_CONST;
+
+void _clutter_events_init (ClutterBackend *backend);
+void _clutter_events_uninit (ClutterBackend *backend);
+
+G_END_DECLS
+
+#endif /* __CLUTTER_BACKEND_SDL_H__ */
Index: clutter/clutter-texture.c
===================================================================
--- clutter/clutter-texture.c	(revision 1682)
+++ clutter/clutter-texture.c	(working copy)
@@ -448,7 +448,7 @@
       if (!priv->tiles)
 	{
 	  priv->tiles = g_new (COGLuint, 1);
-	  glGenTextures (1, priv->tiles);
+	  cogl_textures_create (1, priv->tiles);
 	  create_textures = TRUE;
 	}
 
@@ -519,7 +519,7 @@
   if (priv->tiles == NULL)
     {
       priv->tiles = g_new (COGLuint, priv->n_x_tiles * priv->n_y_tiles);
-      glGenTextures (priv->n_x_tiles * priv->n_y_tiles, priv->tiles);
+      cogl_textures_create (priv->n_x_tiles * priv->n_y_tiles, priv->tiles);
       create_textures = TRUE;
     }
 
@@ -1453,7 +1453,7 @@
   if (!priv->tiles)
     {
       priv->tiles = g_new (COGLuint, 1);
-      glGenTextures (1, priv->tiles);
+      cogl_textures_create (1, priv->tiles);
     }
 
   cogl_texture_bind (priv->target_type, priv->tiles[0]);
Index: clutter/clutter-clone-texture.c
===================================================================
--- clutter/clutter-clone-texture.c	(revision 1682)
+++ clutter/clutter-clone-texture.c	(working copy)
@@ -176,7 +176,7 @@
   ClutterCloneTexturePrivate  *priv;
   ClutterActor                *parent_texture;
   gint                         x_1, y_1, x_2, y_2;
-  GLenum                       target_type;
+  COGLenum                       target_type;
   ClutterColor                 col = { 0xff, 0xff, 0xff, 0xff };
 
   priv = CLUTTER_CLONE_TEXTURE (self)->priv;
Index: clutter/pango/pangoclutter-render.c
===================================================================
--- clutter/pango/pangoclutter-render.c	(revision 1682)
+++ clutter/pango/pangoclutter-render.c	(working copy)
@@ -373,7 +373,7 @@
 				 CGL_UNSIGNED_BYTE,
 				 bm.bitmap);
 
-      glTexParameteri (CGL_TEXTURE_2D, GL_GENERATE_MIPMAP, FALSE);
+      /*glTexParameteri (CGL_TEXTURE_2D, GL_GENERATE_MIPMAP, FALSE);*/
 
       renderer->curtex = g->tex.name;
     }
Index: clutter/cogl/sogl/cogl.c
===================================================================
--- clutter/cogl/sogl/cogl.c	(revision 0)
+++ clutter/cogl/sogl/cogl.c	(revision 0)
@@ -0,0 +1,557 @@
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+#include <math.h>
+#include "cogl.h"
+#include "sogl.h"
+
+extern SoglCanvas *canvas;
+static GList *stack = NULL, *stackp = NULL;
+static unsigned int texnum = 0;
+
+CoglFuncPtr
+cogl_get_proc_address (const gchar* name)
+{
+	return NULL;
+}
+
+gboolean 
+cogl_check_extension (const gchar *name, const gchar *ext)
+{
+	return FALSE;
+}
+
+void
+cogl_perspective (ClutterFixed fovy,
+		  ClutterFixed aspect,
+		  ClutterFixed zNear,
+		  ClutterFixed zFar)
+{
+	sogl_matrix_identity (canvas->m);
+	canvas->m[0] = aspect;
+	canvas->z_near = CLUTTER_FIXED_TO_FLOAT (zNear);
+/*	ClutterFixed xmax, ymax;
+	ClutterFixed fovy_rad_half = CLUTTER_FIXED_MUL (fovy, CFX_PI) / 360;
+
+	ymax = clutter_qmulx (zNear, CLUTTER_FIXED_DIV (
+		clutter_sinx (fovy_rad_half), clutter_cosx (fovy_rad_half)));
+	xmax = clutter_qmulx (ymax, aspect);
+
+	sogl_matrix_identity (canvas->m);
+	
+	canvas->m[0] = CLUTTER_FIXED_TO_FLOAT (CLUTTER_FIXED_DIV (zNear, xmax));
+	canvas->m[5] = CLUTTER_FIXED_TO_FLOAT (CLUTTER_FIXED_DIV (zNear, ymax));
+	canvas->m[10] = CLUTTER_FIXED_TO_FLOAT (
+		CLUTTER_FIXED_DIV ((zFar + zNear), (zFar - zNear)));
+
+	sogl_canvas_set_fov (canvas, fovy);
+	canvas->z_near = CLUTTER_FIXED_TO_FLOAT (zNear);*/
+}
+
+void
+cogl_setup_viewport (guint        width,
+		     guint        height,
+		     ClutterFixed fovy,
+		     ClutterFixed aspect,
+		     ClutterFixed z_near,
+		     ClutterFixed z_far)
+{
+	float m[4*4], mi[4*4];
+	SoglPoint vector;
+	
+	vector = (SoglPoint){ 1.f/width, 1.f/height, 1.f };
+	sogl_matrix_scale (&vector, m);
+	sogl_matrix_mult (canvas->m, m, mi);
+
+	vector = (SoglPoint){ -0.5, -0.5, 1 };
+	sogl_matrix_translate (&vector, m);
+	sogl_matrix_mult (mi, m, canvas->m);
+
+/*	float z_camera;
+	float m[4*4], mi[4*4];
+	SoglPoint vector;
+	
+	g_debug ("%s (%d, %d, %f, %f, %f, %f)", G_STRFUNC, width, height,
+		CLUTTER_FIXED_TO_FLOAT (fovy),
+		CLUTTER_FIXED_TO_FLOAT (aspect),
+		CLUTTER_FIXED_TO_FLOAT (z_near),
+		CLUTTER_FIXED_TO_FLOAT (z_far));
+	
+	cogl_perspective (fovy, aspect, z_near, z_far);
+	
+#define DEFAULT_Z_CAMERA 0.869f
+	z_camera = 
+	z_camera = DEFAULT_Z_CAMERA;
+
+	if (fovy != CFX_60) {
+		ClutterFixed fovy_rad = CFX_MUL (fovy, CFX_PI) / 180;
+
+		z_camera = CLUTTER_FIXED_TO_FLOAT (
+			CFX_DIV (clutter_sinx (fovy_rad),
+				clutter_cosx (fovy_rad)) >> 1);
+	}
+
+	vector = (SoglPoint){ -0.5f, -0.5f, z_camera };
+	sogl_matrix_translate (&vector, m);
+	sogl_matrix_mult (canvas->m, m, mi);
+	
+	vector = (SoglPoint){ 1.f / width, 1.f / height, 1.f / width };
+	sogl_matrix_scale (&vector, m);
+	sogl_matrix_mult (mi, m, canvas->m);
+
+	vector = (SoglPoint){ 0, -1.f * height, 0 };
+	sogl_matrix_translate (&vector, m);
+	sogl_matrix_mult (canvas->m, m, mi);
+	
+	memcpy (canvas->m, mi, 4 * 4 * sizeof (float));
+
+	g_debug ("Position: %f, %f, %f, Scale: %f, %f, %f",
+		canvas->m[12], canvas->m[13], canvas->m[14],
+		canvas->m[0], canvas->m[5], canvas->m[10]);*/
+
+/*  GE( glTranslatef (-0.5f, -0.5f, -z_camera) );
+  GE( glScalef ( 1.0f / width,
+ 	    -1.0f / height,
+		 1.0f / width) );
+  GE( glTranslatef (0.0f, -1.0 * height, 0.0f) );*/
+}
+
+void
+cogl_paint_init (const ClutterColor *color)
+{
+	SoglColor prev_color = canvas->color;
+	canvas->color = (SoglColor){
+		color->red, color->green, color->blue, color->alpha };
+	sogl_canvas_clear (canvas);
+	canvas->color = prev_color;
+}
+
+void
+cogl_push_matrix (void)
+{
+	if ((!stack) || (!stackp->next)) {
+		if (!stack) stack = g_list_prepend (NULL, NULL);
+		stack = g_list_append (stack, malloc (sizeof (float) * 4 * 4));
+		stackp = g_list_last (stack);
+	} else {
+		stackp = stackp->next;
+	}
+	
+	memcpy (stackp->data, canvas->m, sizeof (float) * 4 * 4);
+}
+
+void
+cogl_pop_matrix (void)
+{
+	if ((!stackp) || (!stackp->data)) return;
+	
+	memcpy (canvas->m, stackp->data, sizeof (float) * 4 * 4);
+	stackp = stackp->prev;
+}
+
+void
+cogl_scale (ClutterFixed x, ClutterFixed y)
+{
+	float m[4*4], mi[4*4];
+	SoglPoint vector;
+
+	vector = (SoglPoint){ CLUTTER_FIXED_TO_FLOAT (x),
+		CLUTTER_FIXED_TO_FLOAT (y), 1.f };
+	sogl_matrix_scale (&vector, m);
+	sogl_matrix_mult (m, canvas->m, mi);
+	
+	memcpy (canvas->m, mi, sizeof (float) * 4 * 4);
+}
+
+void
+cogl_translatex (ClutterFixed x, ClutterFixed y, ClutterFixed z)
+{
+	float m[4*4], mi[4*4];
+	SoglPoint vector;
+
+	vector = (SoglPoint){ CLUTTER_FIXED_TO_FLOAT (x),
+		CLUTTER_FIXED_TO_FLOAT (y), CLUTTER_FIXED_TO_FLOAT (z) };
+	sogl_matrix_translate (&vector, m);
+	sogl_matrix_mult (m, canvas->m, mi);
+	
+	memcpy (canvas->m, mi, sizeof (float) * 4 * 4);
+}
+
+void
+cogl_translate (gint x, gint y, gint z)
+{
+	float m[4*4], mi[4*4];
+	SoglPoint vector;
+
+	vector = (SoglPoint){ (float)x, (float)y, (float)z };
+	sogl_matrix_translate (&vector, m);
+	sogl_matrix_mult (m, canvas->m, mi);
+	
+	memcpy (canvas->m, mi, sizeof (float) * 4 * 4);
+}
+
+void
+cogl_rotatex (ClutterFixed angle, gint x, gint y, gint z)
+{
+	float m[4*4], mi[4*4];
+	SoglPoint vector;
+
+	vector = (SoglPoint){ CLUTTER_FIXED_TO_FLOAT (x),
+		CLUTTER_FIXED_TO_FLOAT (y), CLUTTER_FIXED_TO_FLOAT (z) };
+	sogl_matrix_rotate (&vector,
+		CLUTTER_FIXED_TO_FLOAT (angle)*(M_PI/180), m);
+	sogl_matrix_mult (m, canvas->m, mi);
+	
+	memcpy (canvas->m, mi, sizeof (float) * 4 * 4);
+}
+
+void
+cogl_rotate (gint angle, gint x, gint y, gint z)
+{
+	float m[4*4], mi[4*4];
+	SoglPoint vector;
+
+	vector = (SoglPoint){ (float)x, (float)y, (float)z };
+	sogl_matrix_rotate (&vector,
+		CLUTTER_FIXED_TO_FLOAT (angle)*(M_PI/180), m);
+	sogl_matrix_mult (m, canvas->m, mi);
+	
+	memcpy (canvas->m, mi, sizeof (float) * 4 * 4);
+}
+
+void
+cogl_color (const ClutterColor *color)
+{
+	canvas->color.r = color->red;
+	canvas->color.g = color->green;
+	canvas->color.b = color->blue;
+	canvas->color.a = color->alpha;
+}
+
+void
+cogl_clip_set (const ClutterGeometry *clip)
+{
+}
+
+void
+cogl_clip_unset (void)
+{
+}
+
+void
+cogl_enable (gulong flags)
+{
+}
+
+gboolean
+cogl_texture_can_size (COGLenum       target,
+		       COGLenum pixel_format,
+		       COGLenum pixel_type,
+		       int    width, 
+		       int    height)
+{
+	return TRUE;
+}
+
+void
+cogl_texture_quad (gint   x1,
+		   gint   x2, 
+		   gint   y1, 
+		   gint   y2,
+		   ClutterFixed tx1,
+		   ClutterFixed ty1,
+		   ClutterFixed tx2,
+		   ClutterFixed ty2)
+{
+	SoglPoly poly;
+
+	poly.points[0].x = x1;
+	poly.points[0].y = y1;
+	poly.points[0].z = 0;
+
+	poly.points[1].x = x2;
+	poly.points[1].y = y1;
+	poly.points[1].z = 0;
+
+	poly.points[2].x = x2;
+	poly.points[2].y = y2;
+	poly.points[2].z = 0;
+
+	poly.points[3].x = x1;
+	poly.points[3].y = y2;
+	poly.points[3].z = 0;
+
+	poly.texture = canvas->texture;
+	poly.p.x = x1;
+	poly.p.y = y1;
+	poly.p.z = 0;
+
+	poly.m.x = x2-x1;
+	poly.m.y = 0;
+	poly.m.z = 0;
+
+	poly.n.x = 0;
+	poly.n.y = y2-y1;
+	poly.n.z = 0;
+
+	poly.npoints = 4;
+	
+	sogl_poly_render (&poly, canvas);
+}
+
+void
+cogl_textures_create (guint num, COGLuint *textures)
+{
+	int i;
+	for (i = 0; i < num; i++, texnum++) {
+		SoglTexture *texture = sogl_texture_new (0, 0, NULL);
+		texture->id = texnum;
+		textures[i] = texnum;
+		canvas->textures = sogl_list_append (canvas->textures, texture);
+	}
+}
+
+static int
+find_cb (void *data, void *ldata)
+{
+	SoglTexture *texture = (SoglTexture *)ldata;
+	COGLuint *id = (COGLuint *)data;
+	
+	if (texture->id == *id) return 0;
+	else return -1;
+}
+
+void
+cogl_textures_destroy (guint num, const COGLuint *textures)
+{
+	int  i;
+	for (i = 0; i < num; i++) {
+		SoglList *link = sogl_list_find (canvas->textures,
+			(void *)&textures[i], find_cb);
+		if (!link) continue;
+		sogl_texture_free ((SoglTexture *)link->data);
+		canvas->textures = sogl_list_remove (canvas->textures, link);
+	}
+}
+
+void
+cogl_texture_bind (COGLenum target, COGLuint texture)
+{
+	SoglList *link = sogl_list_find (canvas->textures, &texture, find_cb);
+	if (!link) {
+		g_warning ("%s: Texture not found?", G_STRFUNC);
+		return;
+	}
+	canvas->texture = (SoglTexture *)link->data;
+}
+
+void
+cogl_texture_set_alignment (COGLenum target, 
+			    guint    alignment,
+			    guint    row_length)
+{
+}
+
+void
+cogl_texture_set_filters (COGLenum target, 
+			  COGLenum min_filter,
+			  COGLenum max_filter)
+{
+}
+
+void
+cogl_texture_set_wrap (COGLenum target, 
+		       COGLenum wrap_s,
+		       COGLenum wrap_t)
+{
+}
+
+void
+cogl_texture_image_2d (COGLenum      target,
+		       COGLint       internal_format,
+		       gint          width, 
+		       gint          height, 
+		       COGLenum      format,
+		       COGLenum      type,
+		       const guchar* pixels)
+{
+	unsigned int id;
+	SoglList *link;
+	SoglTexture *texture;
+	
+	if (!canvas->texture) {
+		g_warning ("%s: No texture bound", G_STRFUNC);
+		return;
+	}
+	
+	if (format != CGL_RGBA) {
+		g_warning ("%s: Unsupported texture (at the moment)",
+			G_STRFUNC);
+		return;
+	}
+	
+	id = canvas->texture->id;
+	link = sogl_list_find (canvas->textures, &id, find_cb);
+	if (!link) {
+		g_warning ("%s: Unable to find texture in list", G_STRFUNC);
+		return;
+	}
+	
+	sogl_texture_free ((SoglTexture *)link->data);
+	texture = sogl_texture_new (width, height, pixels);
+	texture->id = id;
+	link->data = texture;
+}
+
+void
+cogl_texture_sub_image_2d (COGLenum      target,
+			   gint          xoff,
+			   gint          yoff,
+			   gint          width, 
+			   gint          height,
+			   COGLenum      format,  
+			   COGLenum      type,
+			   const guchar* pixels)
+{
+	unsigned int id, texwidth, texheight;
+	SoglList *link;
+	SoglTexture *texture, *subtex;
+	
+	if (!canvas->texture) {
+		g_warning ("%s: No texture bound", G_STRFUNC);
+		return;
+	}
+
+	if (!pixels) {
+		g_warning ("%s: No pixel data", G_STRFUNC);
+	}
+	
+	if (format != CGL_RGBA) {
+		g_warning ("%s: Unsupported texture (at the moment)",
+			G_STRFUNC);
+		return;
+	}
+	
+	id = canvas->texture->id;
+	link = sogl_list_find (canvas->textures, &id, find_cb);
+	if (!link) {
+		g_warning ("%s: Unable to find texture in list", G_STRFUNC);
+		return;
+	}
+	
+	/* There's more duplication here than is necessary */
+	texwidth = ((SoglTexture *)link->data)->width;
+	texheight = ((SoglTexture *)link->data)->height;
+	
+	sogl_texture_free ((SoglTexture *)link->data);
+	
+	texture = sogl_texture_new (texwidth, texheight, pixels);
+	subtex = sogl_texture_new_subtex (xoff, yoff,
+		xoff + width, yoff + width, texture);
+	sogl_texture_free (texture);
+	subtex->id = id;
+	link->data = subtex;
+}
+
+void
+cogl_rectangle (gint x, gint y, guint width, guint height)
+{
+	SoglPoly poly;
+
+	poly.points[0].x = x;
+	poly.points[0].y = y;
+	poly.points[0].z = 0;
+
+	poly.points[1].x = x + width;
+	poly.points[1].y = y;
+	poly.points[1].z = 0;
+
+	poly.points[2].x = x + width;
+	poly.points[2].y = y + height;
+	poly.points[2].z = 0;
+
+	poly.points[3].x = x;
+	poly.points[3].y = y + height;
+	poly.points[3].z = 0;
+
+	poly.texture = NULL;
+	poly.npoints = 4;
+	
+	sogl_poly_render (&poly, canvas);
+}
+
+void
+cogl_trapezoid (gint y1,
+		gint x11,
+		gint x21,
+		gint y2,
+		gint x12,
+		gint x22)
+{
+	SoglPoly poly;
+
+	poly.points[0].x = x11;
+	poly.points[0].y = y1;
+	poly.points[0].z = 0;
+
+	poly.points[1].x = x21;
+	poly.points[1].y = y1;
+	poly.points[1].z = 0;
+
+	poly.points[2].x = x22;
+	poly.points[2].y = y2;
+	poly.points[2].z = 0;
+
+	poly.points[3].x = x12;
+	poly.points[3].y = y2;
+	poly.points[3].z = 0;
+
+	poly.texture = NULL;
+	poly.npoints = 4;
+	
+	sogl_poly_render (&poly, canvas);
+}
+
+void
+cogl_alpha_func (COGLenum     func, 
+		 ClutterFixed ref)
+{
+}
+
+ClutterFeatureFlags
+cogl_get_features ()
+{
+	return CLUTTER_FEATURE_TEXTURE_RECTANGLE;
+}
+
+void
+cogl_get_modelview_matrix (ClutterFixed m[16])
+{
+}
+
+void
+cogl_get_projection_matrix (ClutterFixed m[16])
+{
+}
+
+void
+cogl_get_viewport (ClutterFixed v[4])
+{
+}
+
+void
+cogl_get_bitmasks (gint *red, gint *green, gint *blue, gint *alpha)
+{
+}
+
+void
+cogl_fog_set (const ClutterColor *fog_color,
+              ClutterFixed        density,
+              ClutterFixed        z_near,
+              ClutterFixed        z_far)
+{
+}
+
Index: clutter/cogl/sogl/cogl-defines.h
===================================================================
--- clutter/cogl/sogl/cogl-defines.h	(revision 0)
+++ clutter/cogl/sogl/cogl-defines.h	(revision 0)
@@ -0,0 +1,460 @@
+/*
+ * Clutter COGL
+ *
+ * A basic GL/GLES Abstraction/Utility Layer
+ *
+ * Authored By Matthew Allum  <mallum@openedhand.com>
+ *
+ * Copyright (C) 2007 OpenedHand
+ *
+ * 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, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __COGL_DEFINES_H__
+#define __COGL_DEFINES_H__
+
+G_BEGIN_DECLS
+
+/* ClearBufferMask */
+#define CGL_DEPTH_BUFFER_BIT 0
+#define CGL_STENCIL_BUFFER_BIT 1
+#define CGL_COLOR_BUFFER_BIT 2
+
+/* Boolean */
+#define CGL_FALSE 0
+#define CGL_TRUE 1
+
+/* BeginMode */
+#define CGL_POINTS 0
+#define CGL_LINES 1
+#define CGL_LINE_LOOP 2
+#define CGL_LINE_STRIP 3
+#define CGL_TRIANGLES 4
+#define CGL_TRIANGLE_STRIP 5
+#define CGL_TRIANGLE_FAN 6
+
+/* AlphaFunction */
+#define CGL_NEVER 0
+#define CGL_LESS 1
+#define CGL_EQUAL 2
+#define CGL_LEQUAL 3
+#define CGL_GREATER 4
+#define CGL_NOTEQUAL 5
+#define CGL_GEQUAL 6
+#define CGL_ALWAYS 7
+
+/* BlendingFactorDest */
+#define CGL_ZERO 0
+#define CGL_ONE 1
+#define CGL_SRC_COLOR 2
+#define CGL_ONE_MINUS_SRC_COLOR 3
+#define CGL_SRC_ALPHA 4
+#define CGL_ONE_MINUS_SRC_ALPHA 5
+#define CGL_DST_ALPHA 6
+#define CGL_ONE_MINUS_DST_ALPHA 7
+
+/* BlendingFactorSrc */
+#define CGL_DST_COLOR 0
+#define CGL_ONE_MINUS_DST_COLOR 1
+#define CGL_SRC_ALPHA_SATURATE 2
+/* Missing; */
+/*      GL_ZERO */
+/*      GL_ONE */
+/*      GL_SRC_ALPHA */
+/*      GL_ONE_MINUS_SRC_ALPHA */
+/*      GL_DST_ALPHA */
+/*      GL_ONE_MINUS_DST_ALPHA */
+
+/* CullFaceMode */
+#define CGL_FRONT 0
+#define CGL_BACK 1
+#define CGL_FRONT_AND_BACK 2
+
+/* EnableCap */
+#define CGL_FOG 0
+#define CGL_LIGHTING 1
+#define CGL_CULL_FACE 2
+#define CGL_ALPHA_TEST 3
+#define CGL_BLEND 4
+#define CGL_COLOR_LOGIC_OP 5
+#define CGL_DITHER 6
+#define CGL_STENCIL_TEST 7
+#define CGL_DEPTH_TEST 8
+#define CGL_POINT_SMOOTH 9
+#define CGL_LINE_SMOOTH 10
+/*#define CGL_SCISSOR_TEST 11*/ /* Defined below */
+#define CGL_COLOR_MATERIAL 12
+#define CGL_NORMALIZE 13
+#define CGL_RESCALE_NORMAL 14
+/*#define CGL_POLYGON_OFFSET_FILL 15*/ /* Defined below */
+#define CGL_VERTEX_ARRAY 16
+#define CGL_NORMAL_ARRAY 17
+#define CGL_COLOR_ARRAY 18
+#define CGL_TEXTURE_COORD_ARRAY 19
+#define CGL_MULTISAMPLE 20
+#define CGL_SAMPLE_ALPHA_TO_COVERAGE 21
+#define CGL_SAMPLE_ALPHA_TO_ONE 22
+#define CGL_SAMPLE_COVERAGE 23
+
+/* Errors */
+#define CGL_NO_ERROR 0
+#define CGL_INVALID_ENUM 1
+#define CGL_INVALID_VALUE 2
+#define CGL_INVALID_OPERATION 3
+#define CGL_STACK_OVERFLOW 4
+#define CGL_STACK_UNDERFLOW 5
+#define CGL_OUT_OF_MEMORY 6
+
+/* Fog mode */
+#define CGL_EXP 0
+#define CGL_EXP2 1
+#define CGL_FOG_DENSITY 2
+
+/* FogParameter */
+#define CGL_FOG_START 0
+#define CGL_FOG_END 1
+#define CGL_FOG_MODE 2
+#define CGL_FOG_COLOR 3
+#define CGL_CW 4
+#define CGL_CCW 5
+
+/* GetPName */
+#define CGL_CURRENT_COLOR 0
+#define CGL_CURRENT_NORMAL 1
+#define CGL_CURRENT_TEXTURE_COORDS 2
+#define CGL_POINT_SIZE 3
+#define CGL_POINT_SIZE_MIN 4
+#define CGL_POINT_SIZE_MAX 5
+#define CGL_POINT_FADE_THRESHOLD_SIZE 6
+#define CGL_POINT_DISTANCE_ATTENUATION 7
+#define CGL_SMOOTH_POINT_SIZE_RANGE 8
+#define CGL_LINE_WIDTH 9
+#define CGL_SMOOTH_LINE_WIDTH_RANGE 10
+#define CGL_ALIASED_POINT_SIZE_RANGE 11
+#define CGL_ALIASED_LINE_WIDTH_RANGE 12
+#define CGL_CULL_FACE_MODE 13
+#define CGL_FRONT_FACE 14
+#define CGL_SHADE_MODEL 15
+#define CGL_DEPTH_RANGE 16
+#define CGL_DEPTH_WRITEMASK 17
+#define CGL_DEPTH_CLEAR_VALUE 18
+#define CGL_DEPTH_FUNC 19
+#define CGL_STENCIL_CLEAR_VALUE 20
+#define CGL_STENCIL_FUNC 21
+#define CGL_STENCIL_VALUE_MASK 22
+#define CGL_STENCIL_FAIL 23
+#define CGL_STENCIL_PASS_DEPTH_FAIL 24
+#define CGL_STENCIL_PASS_DEPTH_PASS 25
+#define CGL_STENCIL_REF 26
+#define CGL_STENCIL_WRITEMASK 27
+#define CGL_MATRIX_MODE 28
+#define CGL_VIEWPORT 29
+#define CGL_MODELVIEW_STACK_DEPTH 30
+#define CGL_PROJECTION_STACK_DEPTH 31
+#define CGL_TEXTURE_STACK_DEPTH 32
+#define CGL_MODELVIEW_MATRIX 33
+#define CGL_PROJECTION_MATRIX 34
+#define CGL_TEXTURE_MATRIX 35
+#define CGL_ALPHA_TEST_FUNC 36
+#define CGL_ALPHA_TEST_REF 37
+#define CGL_BLEND_DST 38
+#define CGL_BLEND_SRC 39
+#define CGL_LOGIC_OP_MODE 40
+#define CGL_SCISSOR_BOX 41
+#define CGL_SCISSOR_TEST 42
+#define CGL_COLOR_CLEAR_VALUE 43
+#define CGL_COLOR_WRITEMASK 44
+#define CGL_UNPACK_ALIGNMENT 45
+#define CGL_PACK_ALIGNMENT 46
+#define CGL_MAX_LIGHTS 47
+#define CGL_MAX_CLIP_PLANES 48
+#define CGL_MAX_TEXTURE_SIZE 49
+#define CGL_MAX_MODELVIEW_STACK_DEPTH 50
+#define CGL_MAX_PROJECTION_STACK_DEPTH 51
+#define CGL_MAX_TEXTURE_STACK_DEPTH 52
+#define CGL_MAX_VIEWPORT_DIMS 53
+#define CGL_MAX_ELEMENTS_VERTICES 54
+#define CGL_MAX_ELEMENTS_INDICES 55
+#define CGL_MAX_TEXTURE_UNITS 56
+#define CGL_SUBPIXEL_BITS 57
+#define CGL_RED_BITS 58
+#define CGL_GREEN_BITS 59
+#define CGL_BLUE_BITS 60
+#define CGL_ALPHA_BITS 61
+#define CGL_DEPTH_BITS 62
+#define CGL_STENCIL_BITS 63
+#define CGL_POLYGON_OFFSET_UNITS 64
+#define CGL_POLYGON_OFFSET_FILL 65
+#define CGL_POLYGON_OFFSET_FACTOR 66
+#define CGL_VERTEX_ARRAY_SIZE 67
+#define CGL_VERTEX_ARRAY_TYPE 68
+#define CGL_VERTEX_ARRAY_STRIDE 69
+#define CGL_NORMAL_ARRAY_TYPE 70
+#define CGL_NORMAL_ARRAY_STRIDE 71
+#define CGL_COLOR_ARRAY_SIZE 72
+#define CGL_COLOR_ARRAY_TYPE 73
+#define CGL_COLOR_ARRAY_STRIDE 74
+#define CGL_TEXTURE_COORD_ARRAY_SIZE 75
+#define CGL_TEXTURE_COORD_ARRAY_TYPE 76
+#define CGL_TEXTURE_COORD_ARRAY_STRIDE 77
+#define CGL_VERTEX_ARRAY_POINTER 78
+#define CGL_NORMAL_ARRAY_POINTER 79
+#define CGL_COLOR_ARRAY_POINTER 80
+#define CGL_TEXTURE_COORD_ARRAY_POINTER 81
+#define CGL_SAMPLE_BUFFERS 82
+#define CGL_SAMPLES 83
+#define CGL_SAMPLE_COVERAGE_VALUE 84
+#define CGL_SAMPLE_COVERAGE_INVERT 85
+
+/* GetTextureParameter - missing */
+/*      GL_TEXTURE_MAG_FILTER */
+/*      GL_TEXTURE_MIN_FILTER */
+/*      GL_TEXTURE_WRAP_S */
+/*      GL_TEXTURE_WRAP_T */
+
+
+#define CGL_IMPLEMENTATION_COLOR_READ_TYPE_OES 0
+#define CGL_IMPLEMENTATION_COLOR_READ_FORMAT_OES 1
+#define CGL_NUM_COMPRESSED_TEXTURE_FORMATS 2
+#define CGL_COMPRESSED_TEXTURE_FORMATS 3
+
+/* OES_matrix_get */
+#define CGL_MODELVIEW_MATRIX_FLOAT_AS_INT_BITS 0
+#define CGL_PROJECTION_MATRIX_FLOAT_AS_INT_BITS 1
+#define CGL_TEXTURE_MATRIX_FLOAT_AS_INT_BITS 2
+/* HintMode */
+#define CGL_DONT_CARE 0
+#define CGL_FASTEST 1
+#define CGL_NICEST 2
+
+/* HintTarget */
+#define CGL_PERSPECTIVE_CORRECTION_HINT 0
+#define CGL_POINT_SMOOTH_HINT 1
+#define CGL_LINE_SMOOTH_HINT 2
+#define CGL_POLYGON_SMOOTH_HINT 3
+#define CGL_FOG_HINT 4
+#define CGL_GENERATE_MIPMAP_HINT 5
+
+/* LightModelParameter */
+#define CGL_LIGHT_MODEL_AMBIENT 0
+#define CGL_LIGHT_MODEL_TWO_SIDE 1
+
+/* LightParameter */
+#define CGL_AMBIENT 0
+#define CGL_DIFFUSE 1
+#define CGL_SPECULAR 2
+#define CGL_POSITION 3
+#define CGL_SPOT_DIRECTION 4
+#define CGL_SPOT_EXPONENT 5
+#define CGL_SPOT_CUTOFF 6
+#define CGL_CONSTANT_ATTENUATION 7
+#define CGL_LINEAR_ATTENUATION 8
+#define CGL_QUADRATIC_ATTENUATION 9
+
+/* DataType */
+#define CGL_BYTE 0
+#define CGL_UNSIGNED_BYTE 1
+#define CGL_SHORT 2
+#define CGL_UNSIGNED_SHORT 3
+#define CGL_FLOAT 4
+#define CGL_FIXED 5
+
+/* LogicOp */
+#define CGL_CLEAR 0
+#define CGL_AND 1
+#define CGL_AND_REVERSE 2
+#define CGL_COPY 3
+#define CGL_AND_INVERTED 4
+#define CGL_NOOP 5
+#define CGL_XOR 6
+#define CGL_OR 7
+#define CGL_NOR 8
+#define CGL_EQUIV 9
+#define CGL_INVERT 10
+#define CGL_OR_REVERSE 11
+#define CGL_COPY_INVERTED 12
+#define CGL_OR_INVERTED 13
+#define CGL_NAND 14
+#define CGL_SET 15
+
+/* MaterialParameter */
+#define CGL_EMISSION 0
+#define CGL_SHININESS 1
+#define CGL_AMBIENT_AND_DIFFUSE 2
+
+/* MatrixMode */
+#define CGL_MODELVIEW 0
+#define CGL_PROJECTION 1
+#define CGL_TEXTURE 2
+
+/* PixelFormat */
+#define CGL_ALPHA 0
+#define CGL_RGB 1
+#define CGL_RGBA 2
+#define CGL_LUMINANCE 3
+#define CGL_LUMINANCE_ALPHA 4
+
+/* PixelStoreParameter */
+/* Defined above */
+/*#define CGL_UNPACK_ALIGNMENT 0
+#define CGL_PACK_ALIGNMENT 1*/
+
+/* PixelType */
+/*      GL_UNSIGNED_BYTE */
+#define CGL_UNSIGNED_SHORT_4_4_4_4 0
+#define CGL_UNSIGNED_SHORT_5_5_5_1 1
+#define CGL_UNSIGNED_SHORT_5_6_5   2
+
+/* ShadingModel */
+#define CGL_FLAT 0
+#define CGL_SMOOTH 1
+
+/* StencilFunction */
+/*      GL_NEVER */
+/*      GL_LESS */
+/*      GL_EQUAL */
+/*      GL_LEQUAL */
+/*      GL_GREATER */
+/*      GL_NOTEQUAL */
+/*      GL_GEQUAL */
+/*      GL_ALWAYS */
+
+/* StencilOp */
+#define CGL_KEEP 0
+#define CGL_REPLACE 1
+#define CGL_INCR 2
+#define CGL_DECR 3
+
+/* StringName */
+#define CGL_VENDOR 0
+#define CGL_RENDERER 1
+#define CGL_VERSION 2
+#define CGL_EXTENSIONS 3
+
+/* TextureEnvMode */
+#define CGL_MODULATE 0
+#define CGL_DECAL 1
+#define CGL_ADD 2
+/*      GL_BLEND */
+/*      GL_REPLACE */
+
+/* TextureEnvParameter */
+#define CGL_TEXTURE_ENV_MODE 0
+#define CGL_TEXTURE_ENV_COLOR 1
+
+/* TextureEnvTarget */
+#define CGL_TEXTURE_ENV 0
+
+/* TextureMagFilter */
+#define CGL_NEAREST 0
+#define CGL_LINEAR 1
+
+/* TextureMinFilter */
+/*      GL_NEAREST */
+/*      GL_LINEAR */
+#define CGL_NEAREST_MIPMAP_NEAREST 0
+#define CGL_LINEAR_MIPMAP_NEAREST 1
+#define CGL_NEAREST_MIPMAP_LINEAR 2
+#define CGL_LINEAR_MIPMAP_LINEAR 3
+
+/* TextureParameterName */
+#define CGL_TEXTURE_MAG_FILTER 0
+#define CGL_TEXTURE_MIN_FILTER 1
+#define CGL_TEXTURE_WRAP_S 0
+#define CGL_TEXTURE_WRAP_T 1
+#define CGL_GENERATE_MIPMAP 0
+
+#define CGL_ACTIVE_TEXTURE 0
+#define CGL_CLIENT_ACTIVE_TEXTURE 1
+
+/* TextureWrapMode */
+#define CGL_REPEAT 0
+#define CGL_CLAMP_TO_EDGE 1
+
+/* PixelInternalFormat */
+
+/* Buffer Objects */
+#define CGL_ARRAY_BUFFER 0
+#define CGL_ELEMENT_ARRAY_BUFFER 1
+#define CGL_ARRAY_BUFFER_BINDING 2
+#define CGL_ELEMENT_ARRAY_BUFFER_BINDING 3
+#define CGL_VERTEX_ARRAY_BUFFER_BINDING 4
+#define CGL_NORMAL_ARRAY_BUFFER_BINDING 5
+#define CGL_COLOR_ARRAY_BUFFER_BINDING 6
+#define CGL_TEXTURE_COORD_ARRAY_BUFFER_BINDING 7
+#define CGL_STATIC_DRAW 8
+#define CGL_DYNAMIC_DRAW 9
+#define CGL_WRITE_ONLY 10
+#define CGL_BUFFER_SIZE 11
+#define CGL_BUFFER_USAGE 12
+#define CGL_BUFFER_ACCESS 13
+#define CGL_SUBTRACT 14
+#define CGL_COMBINE 15
+#define CGL_COMBINE_RGB 16
+#define CGL_COMBINE_ALPHA 17
+#define CGL_RGB_SCALE 18
+#define CGL_ADD_SIGNED 19
+#define CGL_INTERPOLATE 20
+#define CGL_CONSTANT 21
+#define CGL_PRIMARY_COLOR 22
+#define CGL_PREVIOUS 23
+#define CGL_ALPHA_SCALE 24
+#define CGL_POINT_SPRITE_OES 25
+#define CGL_COORD_REPLACE_OES 26
+#define CGL_POINT_SIZE_ARRAY_OES 27
+#define CGL_POINT_SIZE_ARRAY_TYPE_OES 28
+#define CGL_POINT_SIZE_ARRAY_STRIDE_OES 29
+#define CGL_POINT_SIZE_ARRAY_POINTER_OES 30
+#define CGL_POINT_SIZE_ARRAY_BUFFER_BINDING_OES 31
+#define CGL_MAX_VERTEX_UNITS_OES 32
+#define CGL_MAX_PALETTE_MATRICES_OES 33
+#define CGL_MATRIX_PALETTE_OES 34
+#define CGL_MATRIX_INDEX_ARRAY_OES 35
+#define CGL_WEIGHT_ARRAY_OES 36
+#define CGL_MATRIX_INDEX_ARRAY_SIZE_OES 37
+#define CGL_MATRIX_INDEX_ARRAY_TYPE_OES 38
+#define CGL_MATRIX_INDEX_ARRAY_STRIDE_OES 39
+#define CGL_MATRIX_INDEX_ARRAY_POINTER_OES 40
+#define CGL_MATRIX_INDEX_ARRAY_BUFFER_BINDING_OES 41
+#define CGL_WEIGHT_ARRAY_SIZE_OES 42
+#define CGL_WEIGHT_ARRAY_TYPE_OES 43
+#define CGL_WEIGHT_ARRAY_STRIDE_OES 44
+#define CGL_WEIGHT_ARRAY_POINTER_OES 45
+#define CGL_WEIGHT_ARRAY_BUFFER_BINDING_OES 46
+#define CGL_TEXTURE_CROP_RECT_OES 47
+
+typedef int COGLenum;
+typedef int  COGLint;
+typedef unsigned int COGLuint;
+
+/* extras */
+
+#define CGL_TEXTURE_2D 0
+#define CGL_ARGB 1
+#define CGL_BGR 2
+#define CGL_BGRA 3
+
+/* Its unlikely we support this */
+#define CGL_TEXTURE_RECTANGLE_ARB 4
+
+/* YUV textures also unsupported */
+#define CGL_YCBCR_MESA 5
+#define CGL_UNSIGNED_SHORT_8_8_REV_MESA 6
+#define CGL_UNSIGNED_SHORT_8_8_MESA 7
+
+G_END_DECLS
+
+#endif
Index: clutter/cogl/sogl/Makefile.am
===================================================================
--- clutter/cogl/sogl/Makefile.am	(revision 0)
+++ clutter/cogl/sogl/Makefile.am	(revision 0)
@@ -0,0 +1,20 @@
+libclutterincludedir = $(includedir)/clutter-@CLUTTER_API_VERSION@/clutter
+libclutterinclude_HEADERS = $(top_srcdir)/clutter/cogl/cogl.h \
+                            $(top_srcdir)/clutter/cogl/sogl/cogl-defines.h
+
+INCLUDES = \
+	-I$(top_srcdir)              \
+	-I$(top_srcdir)/clutter/cogl \
+	-I$(top_srcdir)/clutter/$(clutterbackend) \
+	$(CLUTTER_CFLAGS)            \
+	$(CLUTTER_DEBUG_CFLAGS)      \
+	$(GCC_FLAGS)
+
+LDADD = $(CLUTTER_LIBS)
+
+noinst_LTLIBRARIES = libclutter-cogl.la
+
+libclutter_cogl_la_SOURCES =                         \
+	$(top_srcdir)/clutter/cogl/cogl.h            \
+        cogl-defines.h                               \
+	cogl.c
Index: clutter/cogl/Makefile.am
===================================================================
--- clutter/cogl/Makefile.am	(revision 1682)
+++ clutter/cogl/Makefile.am	(working copy)
@@ -2,4 +2,4 @@
 
 EXTRA_DIST=cogl.h
 
-DIST_SUBDIRS = gl gles
+DIST_SUBDIRS = gl gles sogl
Index: clutter/clutter-main.c
===================================================================
--- clutter/clutter-main.c	(revision 1682)
+++ clutter/clutter-main.c	(working copy)
@@ -223,9 +223,10 @@
 		  gint            y,
 		  ClutterPickMode mode)
 {
+#if defined (HAVE_COGL_GL) || defined (HAVE_COGL_GLES)
   ClutterMainContext *context;
   guchar              pixel[4];
-  GLint               viewport[4];
+  COGLint               viewport[4];
   ClutterColor        white = { 0xff, 0xff, 0xff, 0xff };
   guint32             id;
   gint                r,g,b;
@@ -238,6 +239,7 @@
   /* Disable dithering (if any) when doing the painting in pick mode */
   glDisable (GL_DITHER);
 
+
   /* Render the entire scence in pick mode - just single colored silhouette's  
    * are drawn offscreen (as we never swap buffers)
   */
@@ -266,6 +268,9 @@
   id = pixel[2]>>(8-b) | pixel[1]<<b>>(8-g) | pixel[0]<<(g+b)>>(8-r);
 
   return clutter_get_actor_by_gid (id);
+#else
+  return NULL;
+#endif
 }
 
 /**
Index: clutter/Makefile.am
===================================================================
--- clutter/Makefile.am	(revision 1682)
+++ clutter/Makefile.am	(working copy)
@@ -2,7 +2,7 @@
 
 SUBDIRS = cogl pango json $(clutterbackend) $(backendextra)
 
-DIST_SUBDIRS = pango glx eglx eglnative cogl sdl json osx x11
+DIST_SUBDIRS = pango glx eglx eglnative cogl sdl sogl-sdl json osx x11
 
 target = $(clutterbackend)
 
Index: configure.ac
===================================================================
--- configure.ac	(revision 1682)
+++ configure.ac	(working copy)
@@ -91,7 +91,7 @@
 backendextralib=
 clutterbackend=glx
 AC_ARG_WITH([flavour],
-            AC_HELP_STRING([--with-flavour=@<:@glx/eglx/eglnative/sdl@:>@],
+            AC_HELP_STRING([--with-flavour=@<:@glx/eglx/eglnative/sdl/sogl-sdl@:>@],
                            [Select the Clutter backend]),
             clutterbackend=$with_flavour)
 
@@ -125,8 +125,24 @@
 
 case $clutterbackend in
 
-  sdl)
+  sogl-sdl)
+    CLUTTER_FLAVOUR="sogl-sdl"
+    AC_DEFINE([HAVE_CLUTTER_SOGL], 1, [Have the SOGL backend])
 
+    CLUTTER_COGL="sogl"
+    AC_DEFINE([HAVE_COGL_SOGL], 1, [Have SOGL for rendering])
+
+    AC_PATH_PROG(SDL_CONFIG, sdl-config)
+    if test "x$SDL_CONFIG" = "x"; then
+       AC_MSG_ERROR([[No sdl-config binary found in path and SDL flavour requested.]])
+    else
+       SDL_CFLAGS=`$SDL_CONFIG --cflags`
+       SDL_LIBS=`$SDL_CONFIG --libs`
+     fi
+    ;;
+
+ sdl)
+
     clutter_gl_header="GL/gl.h"
     CLUTTER_FLAVOUR="sdl"
     AC_DEFINE([HAVE_CLUTTER_SDL], 1, [Have the SDL backend])
@@ -381,10 +397,12 @@
         clutter/eglnative/Makefile
         clutter/osx/Makefile
         clutter/sdl/Makefile
+	clutter/sogl-sdl/Makefile
         clutter/cogl/Makefile
         clutter/cogl/gl/Makefile
         clutter/cogl/gl/cogl-defines.h
         clutter/cogl/gles/Makefile
+	clutter/cogl/sogl/Makefile
         clutter/json/Makefile
         clutter/pango/Makefile
         tests/Makefile
