diff --git a/gst-libs/gst/gl/gstglshadervariables.c b/gst-libs/gst/gl/gstglshadervariables.c
new file mode 100644
index 0000000..432615c
--- /dev/null
+++ b/gst-libs/gst/gl/gstglshadervariables.c
@@ -0,0 +1,1398 @@
+/*
+ * GStreamer
+ * Copyright (C) 2009 Luc Deschenaux <luc.deschenaux@freesurf.ch>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library 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.
+ */
+
+#include "gstglshadervariables.h"
+
+#define trimleft(s,chars) while(s[0] && strchr(chars,s[0])) ++s;
+#define trimright(s,chars) { \
+	char *end; \
+	end=s+strlen(s)-1; \
+	while(end>=s && strchr(chars,end[0])) (end--)[0]=0; \
+}
+
+char *parsename (char **varname, int *arraysize, char **saveptr);
+char *parsevalue (char *value, char *_saveptr,
+    struct gst_gl_shadervariable_desc *ret);
+char *vec_parsevalue (int n, char *value, char *_saveptr,
+    struct gst_gl_shadervariable_desc *ret);
+char *bvec_parsevalue (int n, char *value, char *_saveptr,
+    struct gst_gl_shadervariable_desc *ret);
+char *ivec_parsevalue (int n, char *value, char *_saveptr,
+    struct gst_gl_shadervariable_desc *ret);
+char *uvec_parsevalue (int n, char *value, char *_saveptr,
+    struct gst_gl_shadervariable_desc *ret);
+char *mat_parsevalue (int n, int m, char *value, char *_saveptr,
+    struct gst_gl_shadervariable_desc *ret);
+
+/*
+	Function:
+		gst_gl_shadervariables_parse
+
+	Description:
+		Parse uniform variables declarations and set their values in
+		the specified shader.
+
+	Arguments:
+
+		GstGLShader *shader:
+			Shader in which variables are to be set.
+
+		char *variables:
+			The text to be parsed.
+
+		int (*_setvariable)():	
+			Defaults to gst_gl_shadervariable_set().
+			You can specify here a user function for managing the
+			parsed variable description.
+
+	return values:
+		 0: 	No error.
+		-1:	Error.
+	
+*/
+
+int
+gst_gl_shadervariables_parse (GstGLShader * shader, char *variables,
+    int (*_setvariable) (GstGLShader * shader,
+        struct gst_gl_shadervariable_desc * v))
+{
+  char *p = 0;
+  char *p0;
+  char *e;
+  char e1 = 0;
+  char *t = 0;
+  char *varname;
+  char *vartype;
+  char *varvalue;
+  int arraysize = 0;
+  char *saveptr = variables;
+  int line = 1;
+  char *lim;
+  int i;
+  int len;
+  struct gst_gl_shadervariable_desc ret;
+
+  if (!_setvariable) {
+    _setvariable = gst_gl_shadervariable_set;
+  }
+
+  if (!variables)
+    return 0;
+
+  p0 = variables;
+  trimright (p0, " \t\n");
+  lim = variables + strlen (variables);
+  e = strchr (p0, ';');
+  while (p0 < lim) {
+
+    if (!e) {
+      if (p0[0])
+        goto parse_error;
+      break;
+    }
+
+    e1 = e[1];
+    e[1] = 0;
+    p = g_strdup (p0);
+    e[1] = e1;
+
+    trimright (p, " \t");
+    trimleft (p, " \t\n");
+
+    t = strtok_r (p, " \t", &saveptr);
+    if (!t)
+      goto parse_error;
+    trimleft (t, " \t");
+    trimright (t, " \t\n");
+
+    if (t[0]) {
+
+      if (!strcmp (t, "const")) {
+        t = strtok_r (0, " \t", &saveptr);
+        if (!t)
+          goto parse_error;
+        trimleft (t, " \t");
+        if (!t[0])
+          goto parse_error;
+      }
+      // parse data type
+      for (i = 0; i < _datatypecount; ++i) {
+        if (!strcmp (t, gst_gl_shadervariable_datatype[i])) {
+          ret.type = (gst_gl_shadervariable_datatypeindex) i;
+          break;
+        }
+      }
+      if (i == _datatypecount)
+        goto parse_error;
+
+      vartype = g_strdup (t);
+      GST_INFO ("vartype : '%s'\n", vartype);
+
+      trimleft (saveptr, " \t");
+      t = saveptr;
+      if (*saveptr == '=')
+        goto parse_error;
+
+      // parse variable name and array size
+      t = parsename (&varname, &arraysize, &saveptr);
+      if (t)
+        goto parse_error;
+
+      trimright (varname, " \t");
+      GST_INFO ("varname : '%s'\n", varname);
+      GST_INFO ("arraysize : %d\n", arraysize);
+
+      // check type cast after assignement operator
+      t = strtok_r (0, "(", &saveptr);
+      if (!t)
+        goto parse_error;
+      trimleft (t, " \t");
+      trimright (t, " \t");
+
+      if (arraysize) {
+        char *s = g_malloc (strlen (vartype) + 32);
+        sprintf (s, "%s[%d]", vartype, arraysize);
+        if (strcmp (t, s))
+          goto parse_error;
+      } else {
+        if (strcmp (t, vartype))
+          goto parse_error;
+      }
+
+      // extract variable value
+      t = strtok_r (0, ";", &saveptr);
+      if (!t)
+        goto parse_error;
+      trimleft (t, " \t");
+      trimright (t, " \t");
+
+      if (!t[0])
+        goto parse_error;
+      if (*(saveptr - 2) != ')')
+        goto parse_error;
+      *(saveptr - 2) = 0;
+      if (!t[0])
+        goto parse_error;
+
+      varvalue = g_strdup (t);
+      GST_INFO ("value: %s\n\n", varvalue);
+
+      t = saveptr;
+      if (t[0])
+        goto parse_error;
+
+      // parse variable value
+      len = strlen (varvalue);
+      ret.name = varname;
+      ret.arraysize = arraysize;
+      t = parsevalue (varvalue, saveptr, &ret);
+      if (t) {
+        t -= len;
+        goto parse_error;
+      }
+      // set variable value
+      _setvariable (shader, &ret);
+
+      fflush (0);
+    }
+    // Tell me why we cannot free(p) whithout segfault.
+    //g_free(p);
+    p0 = e + 1;
+    ++line;
+    e = strchr (p0, ';');
+  }
+
+  return 0;
+
+parse_error:
+  if (!t) {
+    t = saveptr;
+  }
+  if (!e) {
+    t = p = p0;
+  } else {
+    e[1] = 0;
+    trimleft (p0, " \t\n");
+    GST_ERROR ("\n%s", p0);
+    e[1] = e1;
+    for (i = 0; i < t - p; ++i)
+      fprintf (stderr, " ");
+    fprintf (stderr, "^\n");
+  }
+  GST_ERROR ("parse error on line %d, position %d (%s)", line, t - p, t);
+  return -1;
+}
+
+/*
+	Function:
+		parsename
+
+	Description:
+		Parse text between the data type and the assignement operator
+		(ie: variable name and array size).
+
+	Arguments:
+
+		char **varname:
+			Text to parse.
+
+		int *arraysize:
+			Pointer to array size. Set to 0 if no array.
+
+		char **saveptr:
+			Address of char *saveptr for strtok_r()
+
+	return values:
+		 0: 	No error.
+		!0:	Pointer to parse error.
+	
+*/
+
+char *
+parsename (char **varname, int *arraysize, char **saveptr)
+{
+  char *t;
+  char *i;
+  int j;
+
+  *arraysize = 0;
+  t = strtok_r (0, "=", saveptr);
+  if (!t)
+    return *saveptr;
+
+  trimleft (t, " \t");
+  trimright (t, " \t");
+
+  i = strchr (t, '[');
+  if (!i) {                     // not an array
+    if (!t[0])
+      return t;
+    for (j = 0; j < strlen (t); ++j) {
+      if (!strchr (VALID_VARNAME_CHARS, t[j]))
+        return t + j;
+    }
+    *varname = g_strdup (t);
+  } else {                      // is an array
+
+    char *i2;
+    char *c;
+
+    i2 = strchr (i + 1, ']');
+    if (!i2)
+      return i + 1;
+    *i = 0;
+
+    if (!t[0])
+      return t;
+    for (j = 0; j < strlen (t); ++j) {
+      if (!strchr (VALID_VARNAME_CHARS, t[j]))
+        return t;
+    }
+
+    *varname = g_strdup (t);
+    *i = '[';
+
+    for (c = i + 1; c < i2; ++c)
+      if (*c < '0' || *c > '9')
+        return c;
+
+    *i2 = 0;
+    *arraysize = atoi (i + 1);
+    *i2 = ']';
+
+    if (!*arraysize)
+      return i + 1;
+  }
+
+  return 0;
+}
+
+/*
+	Function:
+		gst_gl_shadervariable_set
+
+	Description:
+		Set variable value in the specified shader
+
+	Arguments:
+
+		GstGlShader *shader:
+			The shader where to set the variable.
+
+		struct gst_gl_shadervariable_desc *ret:
+			The variable description.
+
+	return values:
+		 0: 	No error.
+		!0:	Variable type unknown/incorrect.
+	
+*/
+
+int
+gst_gl_shadervariable_set (GstGLShader * shader,
+    struct gst_gl_shadervariable_desc *ret)
+{
+
+  switch (ret->type) {
+    case _bool:
+      if (ret->arraysize) {
+        gst_gl_shader_set_uniform_1iv (shader, ret->name, ret->count,
+            (int *) ret->value);
+      } else {
+        gst_gl_shader_set_uniform_1i (shader, ret->name,
+            ((int *) ret->value)[0]);
+      }
+      break;
+    case _int:
+      if (ret->arraysize) {
+        gst_gl_shader_set_uniform_1iv (shader, ret->name, ret->count,
+            (int *) ret->value);
+      } else {
+        gst_gl_shader_set_uniform_1i (shader, ret->name,
+            ((int *) ret->value)[0]);
+      }
+      break;
+
+    case _uint:
+      if (ret->arraysize) {
+        gst_gl_shader_set_uniform_1iv (shader, ret->name, ret->count,
+            (int *) ret->value);
+      } else {
+        gst_gl_shader_set_uniform_1i (shader, ret->name,
+            ((unsigned int *) ret->value)[0]);
+      }
+      break;
+
+    case _float:
+      if (ret->arraysize) {
+        gst_gl_shader_set_uniform_1fv (shader, ret->name, ret->count,
+            (float *) ret->value);
+      } else {
+        gst_gl_shader_set_uniform_1f (shader, ret->name,
+            ((float *) ret->value)[0]);
+      }
+      break;
+
+    case _vec2:
+      if (ret->arraysize) {
+        gst_gl_shader_set_uniform_2fv (shader, ret->name, ret->count,
+            (float *) ret->value);
+      } else {
+        gst_gl_shader_set_uniform_2f (shader, ret->name,
+            ((float *) ret->value)[0], ((float *) ret->value)[1]);
+      }
+      break;
+
+    case _bvec2:
+    case _ivec2:
+    case _uvec2:
+      if (ret->arraysize) {
+        gst_gl_shader_set_uniform_2iv (shader, ret->name, ret->count,
+            (int *) ret->value);
+      } else {
+        gst_gl_shader_set_uniform_2i (shader, ret->name,
+            ((int *) ret->value)[0], ((int *) ret->value)[1]);
+      }
+      break;
+
+    case _vec3:
+      if (ret->arraysize) {
+        gst_gl_shader_set_uniform_3fv (shader, ret->name, ret->count,
+            (float *) ret->value);
+      } else {
+        gst_gl_shader_set_uniform_3f (shader, ret->name,
+            ((float *) ret->value)[0], ((float *) ret->value)[1],
+            ((float *) ret->value)[2]);
+      }
+      break;
+
+    case _bvec3:
+    case _ivec3:
+    case _uvec3:
+      if (ret->arraysize) {
+        gst_gl_shader_set_uniform_3iv (shader, ret->name, ret->count,
+            (int *) ret->value);
+      } else {
+        gst_gl_shader_set_uniform_3i (shader, ret->name,
+            ((int *) ret->value)[0], ((int *) ret->value)[1],
+            ((int *) ret->value)[2]);
+      }
+      break;
+
+    case _vec4:
+      if (ret->arraysize) {
+        gst_gl_shader_set_uniform_4fv (shader, ret->name, ret->count,
+            (float *) ret->value);
+      } else {
+        gst_gl_shader_set_uniform_4f (shader, ret->name,
+            ((float *) ret->value)[0], ((float *) ret->value)[1],
+            ((float *) ret->value)[2], ((float *) ret->value)[3]);
+      }
+      break;
+
+    case _bvec4:
+    case _ivec4:
+    case _uvec4:
+      if (ret->arraysize) {
+        gst_gl_shader_set_uniform_4iv (shader, ret->name, ret->count,
+            (int *) ret->value);
+      } else {
+        gst_gl_shader_set_uniform_4i (shader, ret->name,
+            ((int *) ret->value)[0], ((int *) ret->value)[1],
+            ((int *) ret->value)[2], ((int *) ret->value)[3]);
+      }
+      break;
+
+    case _mat2:
+    case _mat2x2:
+      gst_gl_shader_set_uniform_matrix_2fv (shader, ret->name, ret->count, 0,
+          (float *) ret->value);
+      break;
+
+    case _mat2x3:
+      gst_gl_shader_set_uniform_matrix_2x3fv (shader, ret->name, ret->count, 0,
+          (float *) ret->value);
+      break;
+
+    case _mat3x2:
+      gst_gl_shader_set_uniform_matrix_3x2fv (shader, ret->name, ret->count, 0,
+          (float *) ret->value);
+      break;
+
+    case _mat2x4:
+      gst_gl_shader_set_uniform_matrix_2x4fv (shader, ret->name, ret->count, 0,
+          (float *) ret->value);
+      break;
+
+    case _mat4x2:
+      gst_gl_shader_set_uniform_matrix_4x2fv (shader, ret->name, ret->count, 0,
+          (float *) ret->value);
+      break;
+
+    case _mat3:
+    case _mat3x3:
+      gst_gl_shader_set_uniform_matrix_3fv (shader, ret->name, ret->count, 0,
+          (float *) ret->value);
+      break;
+
+    case _mat3x4:
+      gst_gl_shader_set_uniform_matrix_3x4fv (shader, ret->name, ret->count, 0,
+          (float *) ret->value);
+      break;
+
+    case _mat4x3:
+      gst_gl_shader_set_uniform_matrix_4x3fv (shader, ret->name, ret->count, 0,
+          (float *) ret->value);
+      break;
+
+    case _mat4:
+    case _mat4x4:
+      gst_gl_shader_set_uniform_matrix_4fv (shader, ret->name, ret->count, 0,
+          (float *) ret->value);
+      break;
+
+    default:
+      return -1;
+  }
+  return 0;
+}
+
+/*
+	Function:
+		parsevalue
+
+	Description:
+		Parse text coming after the assignement operator for scalar
+		variables or call the appropriate subroutine to parse vector
+		variables.
+
+	Arguments:
+
+		char *value:
+			Text to be parsed.
+
+		char *_saveptr:
+			Index of end of value.
+
+		struct gst_gl_shadervariable_desc *ret:
+			The variable description to be completed
+			At input time it contains the data type index (type),
+			variable name (name) and array size (arraysize).
+
+	return values:
+		 0: 	No error.
+		!0:	Pointer to parse error.
+	
+*/
+
+char *
+parsevalue (char *value, char *_saveptr, struct gst_gl_shadervariable_desc *ret)
+{
+
+  int i, j;
+  char *t;
+  char *saveptr = value;
+
+  switch (ret->type) {
+    case _bool:
+      ret->count = (ret->arraysize) ? ret->arraysize : 1;
+      if (ret->count == 1) {    // no array
+        if (strcmp (value, "true") && strcmp (value, "false"))
+          return _saveptr;
+        ret->value = (void *) g_malloc (sizeof (int));
+        ((int *) ret->value)[0] = strcmp (value, "false");
+
+      } else {                  // array
+        ret->value = g_malloc (sizeof (int *) * ret->count);
+        t = strtok_r (value, ",", &saveptr);
+        for (i = 0; i < ret->count; ++i) {
+          if (!t)
+            return _saveptr + (saveptr - value);
+          trimleft (t, " \t");
+          trimright (t, " \t");
+          if (strcmp (t, "true") && strcmp (t, "false"))
+            return _saveptr + (saveptr - t);
+          ((int *) ret->value)[i] = strcmp (t, "false");
+          t = strtok_r (0, ",", &saveptr);
+        }
+      }
+      break;
+    case _int:
+      ret->count = (ret->arraysize) ? ret->arraysize : 1;
+      if (ret->count == 1) {
+        for (j = 0; j < strlen (value); ++j) {
+          if (!strchr ("-0123456789", value[j]))
+            return _saveptr + j;
+        }
+        ret->value = (void *) g_malloc (sizeof (int));
+        *((int *) ret->value) = atoi (value);
+
+      } else {
+        ret->value = g_malloc (sizeof (int) * ret->count);
+        t = strtok_r (value, ",", &saveptr);
+
+        for (i = 0; i < ret->count; ++i) {
+
+          if (!t)
+            return _saveptr + (saveptr - value);
+
+          trimleft (t, " \t");
+          trimright (t, " \t");
+          if (!t[0])
+            return _saveptr + (saveptr - t);
+
+          for (j = 0; j < strlen (value); ++j) {
+            if (!strchr ("-0123456789", value[j]))
+              return _saveptr + (saveptr - t) + j;
+          }
+
+          ((int *) ret->value)[i] = atoi (t);
+          t = strtok_r (0, ",", &saveptr);
+        }
+      }
+      break;
+
+    case _uint:
+      ret->count = (ret->arraysize) ? ret->arraysize : 1;
+      if (ret->count == 1) {
+        for (j = 0; j < strlen (value); ++j) {
+          if (!strchr ("0123456789", value[j]))
+            return _saveptr + j;
+        }
+        ret->value = (void *) g_malloc (sizeof (unsigned int));
+        *((unsigned int *) ret->value) = atoi (value);
+
+      } else {
+        ret->value = g_malloc (sizeof (unsigned int) * ret->count);
+        t = strtok_r (value, ",", &saveptr);
+
+        for (i = 0; i < ret->count; ++i) {
+
+          if (!t)
+            return _saveptr + (saveptr - value);
+
+          trimleft (t, " \t");
+          trimright (t, " \t");
+          if (!t[0])
+            return _saveptr + (saveptr - t);
+
+          for (j = 0; j < strlen (value); ++j) {
+            if (!strchr ("0123456789", value[j]))
+              return _saveptr + (saveptr - t) + j;
+          }
+
+          ((unsigned int *) ret->value)[i] = atoi (t);
+          t = strtok_r (0, ",", &saveptr);
+        }
+      }
+      break;
+
+    case _float:
+      ret->count = (ret->arraysize) ? ret->arraysize : 1;
+      if (ret->count == 1) {
+        for (j = 0; j < strlen (value); ++j) {
+          if (!strchr ("0123456789.-", value[j]))
+            return _saveptr + j;
+        }
+        ret->value = (void *) g_malloc (sizeof (float));
+        *((float *) ret->value) = (float) atof (value);
+
+      } else {
+        ret->value = g_malloc (sizeof (float) * ret->count);
+        t = strtok_r (value, ",", &saveptr);
+
+        for (i = 0; i < ret->count; ++i) {
+
+          if (!t)
+            return _saveptr + (saveptr - value);
+
+          trimleft (t, " \t");
+          trimright (t, " \t");
+          if (!t[0])
+            return _saveptr + (saveptr - t);
+
+          for (j = 0; j < strlen (value); ++j) {
+            if (!strchr ("0123456789.-", value[j]))
+              return _saveptr + (saveptr - t) + j;
+          }
+
+          ((float *) ret->value)[i] = (float) atof (t);
+          t = strtok_r (0, ",", &saveptr);
+        }
+      }
+      break;
+
+    case _vec2:
+      return vec_parsevalue (2, value, _saveptr, ret);
+      break;
+
+    case _bvec2:
+      return bvec_parsevalue (2, value, _saveptr, ret);
+      break;
+
+    case _ivec2:
+      return ivec_parsevalue (2, value, _saveptr, ret);
+      break;
+
+    case _uvec2:
+      return uvec_parsevalue (2, value, _saveptr, ret);
+      break;
+
+    case _vec3:
+      return vec_parsevalue (3, value, _saveptr, ret);
+      break;
+
+    case _bvec3:
+      return bvec_parsevalue (3, value, _saveptr, ret);
+      break;
+
+    case _ivec3:
+      return uvec_parsevalue (3, value, _saveptr, ret);
+      break;
+
+    case _uvec3:
+      return uvec_parsevalue (3, value, _saveptr, ret);
+      break;
+
+    case _vec4:
+      return vec_parsevalue (4, value, _saveptr, ret);
+      break;
+
+    case _bvec4:
+      return bvec_parsevalue (4, value, _saveptr, ret);
+      break;
+
+    case _ivec4:
+      return ivec_parsevalue (4, value, _saveptr, ret);
+      break;
+
+    case _uvec4:
+      return uvec_parsevalue (4, value, _saveptr, ret);
+      break;
+
+    case _mat2:
+    case _mat2x2:
+      return mat_parsevalue (2, 2, value, _saveptr, ret);
+      break;
+
+    case _mat2x3:
+      return mat_parsevalue (2, 3, value, _saveptr, ret);
+      break;
+
+    case _mat3x2:
+      return mat_parsevalue (3, 2, value, _saveptr, ret);
+      break;
+
+    case _mat2x4:
+      return mat_parsevalue (2, 4, value, _saveptr, ret);
+      break;
+
+    case _mat4x2:
+      return mat_parsevalue (4, 2, value, _saveptr, ret);
+      break;
+
+    case _mat3:
+    case _mat3x3:
+      return mat_parsevalue (3, 3, value, _saveptr, ret);
+      break;
+
+    case _mat3x4:
+      return mat_parsevalue (3, 4, value, _saveptr, ret);
+      break;
+
+    case _mat4x3:
+      return mat_parsevalue (4, 3, value, _saveptr, ret);
+      break;
+
+    case _mat4:
+    case _mat4x4:
+      return mat_parsevalue (4, 4, value, _saveptr, ret);
+      break;
+
+    default:
+      break;
+  }
+  return 0;
+}
+
+/*
+	Function:
+		vec_parsevalue
+
+	Description:
+		Parse text coming after the assignement operator for vec
+		type variables.
+
+	Arguments:
+
+		int n;
+			Vector dimension.
+
+		char *value:
+			Text to be parsed.
+
+		char *_saveptr:
+			Index of end of value.
+
+		struct gst_gl_shadervariable_desc *ret:
+			The variable description to be completed
+			At input time it contains the data type index (type),
+			variable name (name) and array size (arraysize).
+
+	return values:
+		 0: 	No error.
+		!0:	Pointer to parse error.
+	
+*/
+
+char *
+vec_parsevalue (int n, char *value, char *_saveptr,
+    struct gst_gl_shadervariable_desc *ret)
+{
+
+  int i;
+  int j;
+  int k;
+  char *saveptr = value;
+  char *saveptr2;
+  char *t;
+  char *u;
+
+  ret->count = (ret->arraysize) ? ret->arraysize * n : n;
+  ret->value = g_malloc (sizeof (float) * ret->count);
+
+  if (!ret->arraysize) {
+    t = strtok_r (value, ",", &saveptr);
+
+    for (i = 0; i < ret->count; ++i) {
+
+      if (!t)
+        return _saveptr + (saveptr - value);
+
+      trimleft (t, " \t");
+      trimright (t, " \t");
+      if (!t[0])
+        return _saveptr + (saveptr - t);
+
+      for (j = 0; j < strlen (value); ++j) {
+        if (!strchr ("0123456789.-", value[j]))
+          return _saveptr + (saveptr - t) + j;
+      }
+
+      ((float *) ret->value)[i] = (float) atof (t);
+      t = strtok_r (0, ",", &saveptr);
+    }
+
+  } else {
+
+    saveptr2 = value;
+    u = strtok_r (value, ")", &saveptr2);
+
+    for (k = 0; k < ret->arraysize; ++k) {
+
+      if (!u)
+        return _saveptr + (saveptr2 - value);
+
+      trimleft (u, " \t");
+      trimright (u, " \t");
+
+      if (k) {
+        if (u[0] != ',')
+          return _saveptr + (u - value);
+        ++u;
+        trimleft (u, " \t");
+      }
+
+      if (strncmp (u, gst_gl_shadervariable_datatype[ret->type],
+              strlen (gst_gl_shadervariable_datatype[ret->type])))
+        return _saveptr + (u - value);
+
+      u += strlen (gst_gl_shadervariable_datatype[ret->type]);
+      trimleft (u, " \t");
+      if (u[0] != '(')
+        return _saveptr + (u - value);
+      ++u;
+
+      t = strtok_r (u, ",", &saveptr);
+      if (!t)
+        return _saveptr + (u - value);
+
+      for (i = 0; i < n; ++i) {
+
+        trimleft (t, " \t");
+        trimright (t, " \t");
+        if (!t[0])
+          return _saveptr + (t - value);
+
+        for (j = 0; j < strlen (t); ++j) {
+          if (!strchr ("0123456789.-", t[j]))
+            return _saveptr + (t - value) + j;
+        }
+
+        ((float *) ret->value)[k * n + i] = (float) atof (t);
+        t = strtok_r (0, ",", &saveptr);
+        if (i < (n - 1) && !t)
+          return _saveptr + (saveptr - value);
+
+      }
+      u = strtok_r (0, ")", &saveptr2);
+    }
+  }
+  return 0;
+}
+
+/*
+	Function:
+		bvec_parsevalue
+
+	Description:
+		Parse text coming after the assignement operator for bvec
+		type variables.
+
+	Arguments:
+
+		int n;
+			Vector dimension.
+
+		char *value:
+			Text to be parsed.
+
+		char *_saveptr:
+			Index of end of value.
+
+		struct gst_gl_shadervariable_desc *ret:
+			The variable description to be completed
+			At input time it contains the data type index (type),
+			variable name (name) and array size (arraysize).
+
+	return values:
+		 0: 	No error.
+		!0:	Pointer to parse error.
+	
+*/
+
+char *
+bvec_parsevalue (int n, char *value, char *_saveptr,
+    struct gst_gl_shadervariable_desc *ret)
+{
+
+  int i;
+  int k;
+  char *saveptr = value;
+  char *saveptr2;
+  char *t;
+  char *u;
+
+  ret->count = (ret->arraysize) ? ret->arraysize * n : n;
+  ret->value = g_malloc (sizeof (char **) * ret->count);
+
+  if (!ret->arraysize) {
+    t = strtok_r (value, ",", &saveptr);
+
+    for (i = 0; i < ret->count; ++i) {
+
+      if (!t)
+        return _saveptr + (saveptr - value);
+
+      trimleft (t, " \t");
+      trimright (t, " \t");
+      if (!t[0])
+        return _saveptr + (saveptr - t);
+
+      if (strcmp ("true", value) || strcmp ("false", value))
+        return _saveptr + (saveptr - t);
+
+      ((int *) ret->value)[i] = strcmp (t, "false");
+      t = strtok_r (0, ",", &saveptr);
+    }
+
+  } else {
+
+    saveptr2 = value;
+    u = strtok_r (value, ")", &saveptr2);
+
+    for (k = 0; k < ret->arraysize; ++k) {
+
+      if (!u)
+        return _saveptr + (saveptr2 - value);
+
+      trimleft (u, " \t");
+      trimright (u, " \t");
+
+      if (k) {
+        if (u[0] != ',')
+          return _saveptr + (u - value);
+        ++u;
+        trimleft (u, " \t");
+      }
+
+      if (strncmp (u, gst_gl_shadervariable_datatype[ret->type],
+              strlen (gst_gl_shadervariable_datatype[ret->type])))
+        return _saveptr + (u - value);
+
+      u += strlen (gst_gl_shadervariable_datatype[ret->type]);
+      trimleft (u, " \t");
+      if (u[0] != '(')
+        return _saveptr + (u - value);
+      ++u;
+
+      t = strtok_r (u, ",", &saveptr);
+      if (!t)
+        return _saveptr + (u - value);
+
+      for (i = 0; i < n; ++i) {
+
+        trimleft (t, " \t");
+        trimright (t, " \t");
+        if (!t[0])
+          return _saveptr + (t - value);
+
+        if (strcmp ("true", t) || strcmp ("false", t))
+          return _saveptr + (saveptr - t);
+
+        ((int *) ret->value)[k * n + i] = strcmp (t, "false");
+        t = strtok_r (0, ",", &saveptr);
+        if (i < (n - 1) && !t)
+          return _saveptr + (saveptr - value);
+
+      }
+      u = strtok_r (0, ")", &saveptr2);
+    }
+  }
+  return 0;
+}
+
+/*
+	Function:
+		ivec_parsevalue
+
+	Description:
+		Parse text coming after the assignement operator for ivec
+		type variables.
+
+	Arguments:
+
+		int n;
+			Vector dimension.
+
+		char *value:
+			Text to be parsed.
+
+		char *_saveptr:
+			Index of end of value.
+
+		struct gst_gl_shadervariable_desc *ret:
+			The variable description to be completed
+			At input time it contains the data type index (type),
+			variable name (name) and array size (arraysize).
+
+	return values:
+		 0: 	No error.
+		!0:	Pointer to parse error.
+	
+*/
+
+char *
+ivec_parsevalue (int n, char *value, char *_saveptr,
+    struct gst_gl_shadervariable_desc *ret)
+{
+
+  int i;
+  int j;
+  int k;
+  char *saveptr = value;
+  char *saveptr2;
+  char *t;
+  char *u;
+
+  ret->count = (ret->arraysize) ? ret->arraysize * n : n;
+  ret->value = g_malloc (sizeof (int) * ret->count);
+
+  if (!ret->arraysize) {
+    t = strtok_r (value, ",", &saveptr);
+
+    for (i = 0; i < ret->count; ++i) {
+
+      if (!t)
+        return _saveptr + (saveptr - value);
+
+      trimleft (t, " \t");
+      trimright (t, " \t");
+      if (!t[0])
+        return _saveptr + (saveptr - t);
+
+      for (j = 0; j < strlen (value); ++j) {
+        if (!strchr ("0123456789-", value[j]))
+          return _saveptr + (saveptr - t) + j;
+      }
+
+      ((int *) ret->value)[i] = atoi (t);
+      t = strtok_r (0, ",", &saveptr);
+    }
+
+  } else {
+
+    saveptr2 = value;
+    u = strtok_r (value, ")", &saveptr2);
+
+    for (k = 0; k < ret->arraysize; ++k) {
+
+      if (!u)
+        return _saveptr + (saveptr2 - value);
+
+      trimleft (u, " \t");
+      trimright (u, " \t");
+
+      if (k) {
+        if (u[0] != ',')
+          return _saveptr + (u - value);
+        ++u;
+        trimleft (u, " \t");
+      }
+
+      if (strncmp (u, gst_gl_shadervariable_datatype[ret->type],
+              strlen (gst_gl_shadervariable_datatype[ret->type])))
+        return _saveptr + (u - value);
+
+      u += strlen (gst_gl_shadervariable_datatype[ret->type]);
+      trimleft (u, " \t");
+      if (u[0] != '(')
+        return _saveptr + (u - value);
+      ++u;
+
+      t = strtok_r (u, ",", &saveptr);
+      if (!t)
+        return _saveptr + (u - value);
+
+      for (i = 0; i < n; ++i) {
+
+        trimleft (t, " \t");
+        trimright (t, " \t");
+        if (!t[0])
+          return _saveptr + (t - value);
+
+        for (j = 0; j < strlen (t); ++j) {
+          if (!strchr ("0123456789-", t[j]))
+            return _saveptr + (t - value) + j;
+        }
+
+        ((int *) ret->value)[k * n + i] = atoi (t);
+        t = strtok_r (0, ",", &saveptr);
+        if (i < (n - 1) && !t)
+          return _saveptr + (saveptr - value);
+
+      }
+      u = strtok_r (0, ")", &saveptr2);
+    }
+  }
+  return 0;
+}
+
+/*
+	Function:
+		uvec_parsevalue
+
+	Description:
+		Parse text coming after the assignement operator for uvec
+		type variables.
+
+	Arguments:
+
+		int n;
+			Vector dimension.
+
+		char *value:
+			Text to be parsed.
+
+		char *_saveptr:
+			Index of end of value.
+
+		struct gst_gl_shadervariable_desc *ret:
+			The variable description to be completed
+			At input time it contains the data type index (type),
+			variable name (name) and array size (arraysize).
+
+	return values:
+		 0: 	No error.
+		!0:	Pointer to parse error.
+	
+*/
+
+char *
+uvec_parsevalue (int n, char *value, char *_saveptr,
+    struct gst_gl_shadervariable_desc *ret)
+{
+
+  int i;
+  int j;
+  int k;
+  char *saveptr = value;
+  char *saveptr2;
+  char *t;
+  char *u;
+
+  ret->count = (ret->arraysize) ? ret->arraysize * n : n;
+  ret->value = g_malloc (sizeof (unsigned int) * ret->count);
+
+  if (!ret->arraysize) {
+    t = strtok_r (value, ",", &saveptr);
+
+    for (i = 0; i < ret->count; ++i) {
+
+      if (!t)
+        return _saveptr + (saveptr - value);
+
+      trimleft (t, " \t");
+      trimright (t, " \t");
+      if (!t[0])
+        return _saveptr + (saveptr - t);
+
+      for (j = 0; j < strlen (value); ++j) {
+        if (!strchr ("0123456789", value[j]))
+          return _saveptr + (saveptr - t) + j;
+      }
+
+      ((unsigned int *) ret->value)[i] = atoi (t);
+      t = strtok_r (0, ",", &saveptr);
+    }
+
+  } else {
+
+    saveptr2 = value;
+    u = strtok_r (value, ")", &saveptr2);
+
+    for (k = 0; k < ret->arraysize; ++k) {
+
+      if (!u)
+        return _saveptr + (saveptr2 - value);
+
+      trimleft (u, " \t");
+      trimright (u, " \t");
+
+      if (k) {
+        if (u[0] != ',')
+          return _saveptr + (u - value);
+        ++u;
+        trimleft (u, " \t");
+      }
+
+      if (strncmp (u, gst_gl_shadervariable_datatype[ret->type],
+              strlen (gst_gl_shadervariable_datatype[ret->type])))
+        return _saveptr + (u - value);
+
+      u += strlen (gst_gl_shadervariable_datatype[ret->type]);
+      trimleft (u, " \t");
+      if (u[0] != '(')
+        return _saveptr + (u - value);
+      ++u;
+
+      t = strtok_r (u, ",", &saveptr);
+      if (!t)
+        return _saveptr + (u - value);
+
+      for (i = 0; i < n; ++i) {
+
+        trimleft (t, " \t");
+        trimright (t, " \t");
+        if (!t[0])
+          return _saveptr + (t - value);
+
+        for (j = 0; j < strlen (t); ++j) {
+          if (!strchr ("0123456789", t[j]))
+            return _saveptr + (t - value) + j;
+        }
+
+        ((unsigned int *) ret->value)[k * n + i] = atoi (t);
+        t = strtok_r (0, ",", &saveptr);
+        if (i < (n - 1) && !t)
+          return _saveptr + (saveptr - value);
+
+      }
+      u = strtok_r (0, ")", &saveptr2);
+    }
+  }
+  return 0;
+}
+
+/*
+	Function:
+		mat_parsevalue
+
+	Description:
+		Parse text coming after the assignement operator for matrix
+		type variables.
+
+	Arguments:
+
+		int n,m;
+			Matrix dimensions.
+
+		char *value:
+			Text to be parsed.
+
+		char *_saveptr:
+			Index of end of value.
+
+		struct gst_gl_shadervariable_desc *ret:
+			The variable description to be completed
+			At input time it contains the data type index (type),
+			variable name (name) and array size (arraysize).
+
+	return values:
+		 0: 	No error.
+		!0:	Pointer to parse error.
+	
+*/
+
+char *
+mat_parsevalue (int n, int m, char *value, char *_saveptr,
+    struct gst_gl_shadervariable_desc *ret)
+{
+
+  int i;
+  int j;
+  int k;
+  char *saveptr = value;
+  char *saveptr2;
+  char *t;
+  char *u;
+
+  ret->count = (ret->arraysize) ? ret->arraysize * n * m : n * m;
+  ret->value = g_malloc (sizeof (float) * ret->count);
+
+  if (!ret->arraysize) {
+    t = strtok_r (value, ",", &saveptr);
+
+    for (i = 0; i < ret->count; ++i) {
+
+      if (!t)
+        return _saveptr + (saveptr - value);
+
+      trimleft (t, " \t");
+      trimright (t, " \t");
+      if (!t[0])
+        return _saveptr + (saveptr - t);
+
+      for (j = 0; j < strlen (value); ++j) {
+        if (!strchr ("0123456789.-", value[j]))
+          return _saveptr + (saveptr - t) + j;
+      }
+
+      ((float *) ret->value)[i] = (float) atof (t);
+      t = strtok_r (0, ",", &saveptr);
+    }
+
+  } else {
+
+    saveptr2 = value;
+    u = strtok_r (value, ")", &saveptr2);
+
+    for (k = 0; k < ret->arraysize; ++k) {
+
+      if (!u)
+        return _saveptr + (saveptr2 - value);
+
+      trimleft (u, " \t");
+      trimright (u, " \t");
+
+      if (k) {
+        if (u[0] != ',')
+          return _saveptr + (u - value);
+        ++u;
+        trimleft (u, " \t");
+      }
+
+      if (strncmp (u, gst_gl_shadervariable_datatype[ret->type],
+              strlen (gst_gl_shadervariable_datatype[ret->type])))
+        return _saveptr + (u - value);
+
+      u += strlen (gst_gl_shadervariable_datatype[ret->type]);
+      trimleft (u, " \t");
+      if (u[0] != '(')
+        return _saveptr + (u - value);
+      ++u;
+
+      t = strtok_r (u, ",", &saveptr);
+      if (!t)
+        return _saveptr + (u - value);
+
+      for (i = 0; i < n * m; ++i) {
+
+        trimleft (t, " \t");
+        trimright (t, " \t");
+        if (!t[0])
+          return _saveptr + (t - value);
+
+        for (j = 0; j < strlen (t); ++j) {
+          if (!strchr ("0123456789.-", t[j]))
+            return _saveptr + (t - value) + j;
+        }
+
+        ((float *) ret->value)[k * n * m + i] = (float) atof (t);
+        t = strtok_r (0, ",", &saveptr);
+        if (i < (n * m - 1) && !t)
+          return _saveptr + (saveptr - value);
+
+      }
+      u = strtok_r (0, ")", &saveptr2);
+    }
+  }
+  return 0;
+}
diff --git a/gst-libs/gst/gl/gstglshadervariables.h b/gst-libs/gst/gl/gstglshadervariables.h
new file mode 100644
index 0000000..9168fb3
--- /dev/null
+++ b/gst-libs/gst/gl/gstglshadervariables.h
@@ -0,0 +1,107 @@
+/*
+ * GStreamer
+ * Copyright (C) 2009 Luc Deschenaux <luc.deschenaux@freesurf.ch>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library 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 GST_GLSHADER_VARIABLES
+#define GST_GLSHADER_VARIABLES
+
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <gstglshader.h>
+
+#define VALID_VARNAME_CHARS "abcdefghijklmnopqurstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"
+
+char *gst_gl_shadervariable_datatype[]={
+	"bool",
+	"int",
+	"uint",
+	"float",
+	"vec2",
+	"vec3",
+	"vec4",
+	"bvec2",
+	"bvec3",
+	"bvec4",
+	"ivec2",
+	"ivec3",
+	"ivec4",
+	"uvec2",
+	"uvec3",
+	"uvec4",
+	"mat2",
+	"mat3",
+	"mat4",
+	"mat2x2",
+	"mat2x3",
+	"mat2x4",
+	"mat3x2",
+	"mat3x3",
+	"mat3x4",
+	"mat4x2",
+	"mat4x3",
+	"mat4x4",
+	0
+};
+
+typedef enum {
+	_bool,
+	_int,
+	_uint,
+	_float,
+	_vec2,
+	_vec3,
+	_vec4,
+	_bvec2,
+	_bvec3,
+	_bvec4,
+	_ivec2,
+	_ivec3,
+	_ivec4,
+	_uvec2,
+	_uvec3,
+	_uvec4,
+	_mat2,
+	_mat3,
+	_mat4,
+	_mat2x2,
+	_mat2x3,
+	_mat2x4,
+	_mat3x2,
+	_mat3x3,
+	_mat3x4,
+	_mat4x2,
+	_mat4x3,
+	_mat4x4,
+	_datatypecount
+} gst_gl_shadervariable_datatypeindex;
+
+typedef struct gst_gl_shadervariable_desc {
+	gst_gl_shadervariable_datatypeindex type;
+	char	*name;
+	int	arraysize;
+	int	count;
+	void	*value;
+
+} gst_gl_shadervariable_desc;
+
+int gst_gl_shadervariables_parse(GstGLShader *shader,char *variables,int (*_setvariable)(GstGLShader *shader,struct gst_gl_shadervariable_desc *v));
+int gst_gl_shadervariable_set(GstGLShader *shader,struct gst_gl_shadervariable_desc *ret);
+
+#endif
diff --git a/gst/gl/gstglfiltershader.c b/gst/gl/gstglfiltershader.c
new file mode 100644
index 0000000..4285d4e
--- /dev/null
+++ b/gst/gl/gstglfiltershader.c
@@ -0,0 +1,434 @@
+/*
+ * glshader gstreamer plugin
+ * Copyrithg (C) 2008 Filippo Argiolas <filippo.argiolas@gmail.com>
+ * Copyright (C) 2009 Luc Deschenaux <luc.deschenaux@freesurf.ch>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library 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.
+ */
+
+/**
+ * SECTION:element-glshader
+ *
+ * Filter loading OpenGL fragment shader from file
+ *
+ * <refsect2>
+ * <title>Examples</title>
+ * |[
+ * gst-launch videotestsrc ! glupload ! glshader location=myshader.fs ! glimagesink
+ * ]|
+ * FBO (Frame Buffer Object) and GLSL (OpenGL Shading Language) are required.
+ * </refsect2>
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <string.h>
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gst/gst.h>
+#include <gst/controller/gstcontroller.h>
+#include "gstglfiltershader.h"
+#include <gstglshadervariables.h>
+
+/* horizontal filter */
+static gchar *hfilter_fragment_source;
+static gchar *hfilter_fragment_variables[2];
+
+enum {
+	PROP_0,
+	PROP_LOCATION,
+	PROP_PRESET,
+	PROP_VARIABLES
+};
+
+#define GST_CAT_DEFAULT gst_gl_filtershader_debug
+GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
+
+static const GstElementDetails element_details =
+GST_ELEMENT_DETAILS ("OpenGL fragment shader filter",
+    "Filter/Effect",
+    "Filter loading OpenGL fragment shader from file",
+    "<luc.deschenaux@freesurf.ch>, Filippo Argiolas <filippo.argiolas@gmail.com>");
+
+#define DEBUG_INIT(bla)							\
+  GST_DEBUG_CATEGORY_INIT (gst_gl_filtershader_debug, "glshader", 0, "glshader element");
+
+GST_BOILERPLATE_FULL (GstGLFilterShader, gst_gl_filtershader, GstGLFilter,
+    GST_TYPE_GL_FILTER, DEBUG_INIT);
+
+static void gst_gl_filtershader_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec);
+static void gst_gl_filtershader_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec);
+static void gst_gl_filter_filtershader_reset (GstGLFilter * filter);
+static void gst_gl_filtershader_draw_texture (GstGLFilterShader * filtershader,
+    GLuint tex);
+
+static void gst_gl_filtershader_load_shader (char *filename,char **storage);
+static void gst_gl_filtershader_load_variables (char *filename,char **storage);
+static void gst_gl_filtershader_init_shader (GstGLFilter * filter);
+static gboolean gst_gl_filtershader_filter (GstGLFilter * filter,
+    GstGLBuffer * inbuf, GstGLBuffer * outbuf);
+static void gst_gl_filtershader_hcallback (gint width, gint height, guint texture,
+    gpointer stuff);
+
+
+static void
+gst_gl_filtershader_init_resources (GstGLFilter * filter)
+{
+  glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8,
+      filter->width, filter->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+  glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+  glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+  glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S,
+      GL_CLAMP_TO_EDGE);
+  glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T,
+      GL_CLAMP_TO_EDGE);
+}
+
+static void
+gst_gl_filtershader_reset_resources (GstGLFilter * filter)
+{
+  //GstGLFilterShader *filtershader = GST_GL_FILTERSHADER (filter);
+}
+
+static void
+gst_gl_filtershader_base_init (gpointer klass)
+{
+  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+
+  gst_element_class_set_details (element_class, &element_details);
+  /* initialize library */
+  gst_controller_init (NULL, NULL);
+
+}
+
+static void
+gst_gl_filtershader_class_init (GstGLFilterShaderClass * klass)
+{
+  GObjectClass *gobject_class;
+
+  gobject_class = (GObjectClass *) klass;
+  gobject_class->set_property = gst_gl_filtershader_set_property;
+  gobject_class->get_property = gst_gl_filtershader_get_property;
+
+  g_object_class_install_property (gobject_class, PROP_LOCATION,
+      g_param_spec_string ("location", "File Location",
+          "Location of the GLSL file to load", NULL,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  g_object_class_install_property (gobject_class, PROP_PRESET,
+      g_param_spec_string ("preset", "Preset File Location",
+          "Location of the shader uniform variables preset file", NULL,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  g_object_class_install_property (gobject_class, PROP_VARIABLES,
+      g_param_spec_string ("vars", "Uniform variables",
+          "Set the shader uniform variables", NULL,
+          G_PARAM_WRITABLE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
+
+  GST_GL_FILTER_CLASS (klass)->filter = gst_gl_filtershader_filter;
+  GST_GL_FILTER_CLASS (klass)->display_init_cb =
+      gst_gl_filtershader_init_resources;
+  GST_GL_FILTER_CLASS (klass)->display_reset_cb =
+      gst_gl_filtershader_reset_resources;
+  GST_GL_FILTER_CLASS (klass)->onInitFBO = gst_gl_filtershader_init_shader;
+  GST_GL_FILTER_CLASS (klass)->onReset = gst_gl_filter_filtershader_reset;
+}
+
+static void
+gst_gl_filtershader_init (GstGLFilterShader * filtershader,
+    GstGLFilterShaderClass * klass)
+{
+  filtershader->shader0 = NULL;
+}
+
+static void
+gst_gl_filter_filtershader_reset (GstGLFilter * filter)
+{
+  GstGLFilterShader *filtershader = GST_GL_FILTERSHADER (filter);
+
+  //blocking call, wait the opengl thread has destroyed the shader
+  gst_gl_display_del_shader (filter->display, filtershader->shader0);
+
+}
+
+static void
+gst_gl_filtershader_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec)
+{
+  GstGLFilterShader *filtershader = GST_GL_FILTERSHADER (object);
+
+  switch (prop_id) {
+
+    case PROP_LOCATION:
+
+      if (filtershader->filename) {
+	      g_free(filtershader->filename);
+      }
+      if (filtershader->compiled) { 
+	      //gst_gl_display_del_shader (filtershader->filter.display, filtershader->shader0);
+	      gst_gl_filter_filtershader_reset (&filtershader->filter);
+	      filtershader->shader0=0;
+      }
+      filtershader->filename=g_strdup(g_value_get_string (value));
+      filtershader->compiled=0;
+      filtershader->texSet=0;
+
+      break;
+
+    case PROP_PRESET:
+
+      if (filtershader->presetfile) {
+	      g_free(filtershader->presetfile);
+      }
+
+      filtershader->presetfile=g_strdup(g_value_get_string (value));
+
+      if (hfilter_fragment_variables[0]) {
+	      g_free(hfilter_fragment_variables[0]);
+	      hfilter_fragment_variables[0]=0;
+      }
+
+      if (!filtershader->presetfile[0]) {
+	      g_free(filtershader->presetfile);
+	      filtershader->presetfile=0;
+      }
+
+      break;
+
+    case PROP_VARIABLES:
+
+      if (hfilter_fragment_variables[1]) {
+	      g_free(hfilter_fragment_variables[1]);
+      }
+
+      hfilter_fragment_variables[1]=g_strdup(g_value_get_string (value));
+
+      if (!hfilter_fragment_variables[1][0]) {
+	      g_free(hfilter_fragment_variables[1]);
+	      hfilter_fragment_variables[1]=0;
+      }
+
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static void
+gst_gl_filtershader_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec)
+{
+   GstGLFilterShader *filtershader = GST_GL_FILTERSHADER (object); 
+
+  switch (prop_id) {
+    case PROP_LOCATION:
+      g_value_set_string(value, filtershader->filename);
+      break;
+
+    case PROP_PRESET:
+      g_value_set_string(value, filtershader->presetfile);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static int
+gst_gl_filtershader_load_file (char *filename,char **storage)
+{
+
+  size_t count;
+  ssize_t bytes;
+  int f;
+
+  // read the filter from file
+  GST_INFO ("loading file: %s", filename);
+  f=open(filename,O_RDONLY);
+  if (f<0) {
+	GST_ERROR ("could not open file: %s", filename);
+	return -1;
+  }
+
+  if (*storage) {
+	g_free(*storage);
+	*storage=0;
+  }
+
+  count=lseek(f,0,SEEK_END);
+  *storage=g_malloc(count+1);
+  if (!*storage) {
+	GST_ERROR ("g_malloc failed: %u", count);
+	return -1;
+  }
+
+  lseek(f,0,SEEK_SET);
+  bytes=read(f,(void*)*storage,count);
+  if (bytes<0 || bytes!=count) {
+	GST_ERROR ("read failed: %u/%u", bytes,count);
+	return -1;
+  }
+  ((char*)*storage)[count]=0;
+
+  close(f);
+  GST_INFO ("read: %u", bytes);
+  return 0;
+}
+
+static void
+gst_gl_filtershader_load_shader (char *filename,char **storage) {
+	if (gst_gl_filtershader_load_file(filename,storage)) {
+		exit(1);
+	}
+}
+
+static void
+gst_gl_filtershader_load_variables (char *filename,char **storage) {
+
+	if (storage[0]) {
+		g_free(storage[0]);
+		storage[0]=0;
+	}
+
+	if (!filename) return;
+
+	if (gst_gl_filtershader_load_file(filename,storage)) {
+		exit(1);
+	}
+}
+
+static void
+gst_gl_filtershader_variables_parse(GstGLShader *shader,gchar *variables)
+{
+	gst_gl_shadervariables_parse(shader,variables,0);
+}
+
+
+static void
+gst_gl_filtershader_init_shader (GstGLFilter * filter)
+{
+
+  GstGLFilterShader *filtershader = GST_GL_FILTERSHADER (filter);
+
+  gst_gl_filtershader_load_shader(filtershader->filename,&hfilter_fragment_source);
+
+  //blocking call, wait the opengl thread has compiled the shader
+  gst_gl_display_gen_shader (filter->display, 0, hfilter_fragment_source,
+      &filtershader->shader0);
+
+  if (!filtershader->shader0) {
+	  GST_ERROR("Fragment Shader compilation failed.");
+	  exit(1);
+  }
+
+  filtershader->compiled=1;
+
+  gst_gl_filtershader_load_variables(filtershader->presetfile,&hfilter_fragment_variables[0]);
+
+}
+
+static void
+gst_gl_filtershader_draw_texture (GstGLFilterShader * filtershader, GLuint tex)
+{
+  GstGLFilter *filter = GST_GL_FILTER (filtershader);
+
+  glActiveTexture (GL_TEXTURE0);
+  glEnable (GL_TEXTURE_RECTANGLE_ARB);
+  glBindTexture (GL_TEXTURE_RECTANGLE_ARB, tex);
+
+  glBegin (GL_QUADS);
+
+  glTexCoord2f (0.0, 0.0);
+  glVertex2f (-1.0, -1.0);
+  glTexCoord2f ((gfloat) filter->width, 0.0);
+  glVertex2f (1.0, -1.0);
+  glTexCoord2f ((gfloat) filter->width, (gfloat) filter->height);
+  glVertex2f (1.0, 1.0);
+  glTexCoord2f (0.0, (gfloat) filter->height);
+  glVertex2f (-1.0, 1.0);
+
+  glEnd ();
+}
+
+static gboolean
+gst_gl_filtershader_filter (GstGLFilter * filter, GstGLBuffer * inbuf,
+    GstGLBuffer * outbuf)
+{
+  GstClockTime timestamp;
+ 
+  GstGLFilterShader *filtershader = GST_GL_FILTERSHADER (filter);
+
+  if (!filtershader->compiled) {
+	  gst_gl_filtershader_init_shader(filter);
+  }
+
+  gst_gl_filter_render_to_target (filter, inbuf->texture,  ///
+      outbuf->texture, gst_gl_filtershader_hcallback, filtershader); ///
+
+  timestamp=GST_BUFFER_TIMESTAMP (outbuf);
+  if (GST_CLOCK_TIME_IS_VALID (timestamp))
+      gst_object_sync_values (G_OBJECT (filter), timestamp);
+
+  return TRUE;
+}
+
+static void
+gst_gl_filtershader_hcallback (gint width, gint height, guint texture,
+    gpointer stuff)
+{
+  GstGLFilterShader *filtershader = GST_GL_FILTERSHADER (stuff);
+
+  glMatrixMode (GL_PROJECTION);
+  glLoadIdentity ();
+
+  gst_gl_shader_use (filtershader->shader0);
+
+
+  glActiveTexture (GL_TEXTURE1);
+  glEnable (GL_TEXTURE_RECTANGLE_ARB);
+  glBindTexture (GL_TEXTURE_RECTANGLE_ARB, texture);
+  glDisable (GL_TEXTURE_RECTANGLE_ARB);
+
+  if (!filtershader->texSet) {
+	  gst_gl_shader_set_uniform_1i (filtershader->shader0, "tex", 1);
+	  filtershader->texSet=1;
+  }
+
+  if (hfilter_fragment_variables[0]) {
+	  gst_gl_filtershader_variables_parse(filtershader->shader0,hfilter_fragment_variables[0]);
+	  g_free(hfilter_fragment_variables[0]);
+	  hfilter_fragment_variables[0]=0;
+  }
+  if (hfilter_fragment_variables[1]) {
+	  gst_gl_filtershader_variables_parse(filtershader->shader0,hfilter_fragment_variables[1]);
+	  g_free(hfilter_fragment_variables[1]);
+	  hfilter_fragment_variables[1]=0;
+  }
+
+  gst_gl_filtershader_draw_texture (filtershader, texture);
+
+}
diff --git a/gst/gl/gstglfiltershader.h b/gst/gl/gstglfiltershader.h
new file mode 100644
index 0000000..eb37b66
--- /dev/null
+++ b/gst/gl/gstglfiltershader.h
@@ -0,0 +1,56 @@
+/*
+ * glshader gstreamer plugin
+ * Copyright (C) 2008 Filippo Argiolas <filippo.argiolas@gmail.com>
+ * Copyright (C) 2009 Luc Deschenaux <luc.deschenaux@freesurf.ch>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library 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 _GST_GL_FILTERSHADER_H_
+#define _GST_GL_FILTERSHADER_H_
+
+#include <gstglfilter.h>
+
+#define GST_TYPE_GL_FILTERSHADER            (gst_gl_filtershader_get_type())
+#define GST_GL_FILTERSHADER(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_GL_FILTERSHADER,GstGLFilterShader))
+#define GST_IS_GL_FILTERSHADER(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_GL_FILTERSHADER))
+#define GST_GL_FILTERSHADER_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass) ,GST_TYPE_GL_FILTERSHADER,GstGLFilterShaderClass))
+#define GST_IS_GL_FILTERSHADER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass) ,GST_TYPE_GL_FILTERSHADER))
+#define GST_GL_FILTERSHADER_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj) ,GST_TYPE_GL_FILTERSHADER,GstGLFilterShaderClass))
+
+typedef struct _GstGLFilterShader GstGLFilterShader;
+typedef struct _GstGLFilterShaderClass GstGLFilterShaderClass;
+
+struct _GstGLFilterShader
+{
+  GstGLFilter filter;
+  GstGLShader *shader0;
+  int compiled;
+  gchar	*filename;
+  gchar	*presetfile;
+  int texSet;
+
+};
+
+struct _GstGLFilterShaderClass
+{
+  GstGLFilterClass filter_class;
+};
+
+GType gst_gl_glfiltershader_get_type (void);
+
+#endif /* _GST_GL_FILTERSHADER_H_ */
+
