From 268f1a30b239ec0262e2eaa33117a2aa14df19ff Mon Sep 17 00:00:00 2001 From: Luc Deschenaux Date: Thu, 17 Nov 2011 17:36:44 +0100 Subject: [PATCH] [471/906] glshader: add dynamic fragment shader filter Also add fragment shader parser Fix bug #600195 --- gst-libs/gst/gl/CMakeLists.txt | 3 + gst-libs/gst/gl/GNUmakefile.gnustep | 1 + gst-libs/gst/gl/Makefile.am | 4 +- gst-libs/gst/gl/gstgles2.h | 21 + gst-libs/gst/gl/gstglshader.c | 342 ++++++ gst-libs/gst/gl/gstglshader.h | 29 + gst-libs/gst/gl/gstglshadervariables.c | 1473 ++++++++++++++++++++++++ gst-libs/gst/gl/gstglshadervariables.h | 39 + gst/gl/CMakeLists.txt | 1 + gst/gl/GNUmakefile.gnustep | 1 + gst/gl/Makefile.am | 2 + gst/gl/gstglfiltershader.c | 405 +++++++ gst/gl/gstglfiltershader.h | 55 + gst/gl/gstopengl.c | 7 + 14 files changed, 2382 insertions(+), 1 deletion(-) create mode 100644 gst-libs/gst/gl/gstglshadervariables.c create mode 100644 gst-libs/gst/gl/gstglshadervariables.h create mode 100644 gst/gl/gstglfiltershader.c create mode 100644 gst/gl/gstglfiltershader.h diff --git a/gst-libs/gst/gl/CMakeLists.txt b/gst-libs/gst/gl/CMakeLists.txt index f09574191c..cbe95fe97e 100755 --- a/gst-libs/gst/gl/CMakeLists.txt +++ b/gst-libs/gst/gl/CMakeLists.txt @@ -24,6 +24,7 @@ add_library (gstgl STATIC gstglbuffer.c gstglfilter.c gstglmixer.c + gstglshadervariables.c gstglshader.c) target_link_libraries(gstgl @@ -47,6 +48,7 @@ else (WIN32) gstglbuffer.c gstglfilter.c gstglmixer.c + gstglshadervariables.c gstglshader.c) target_link_libraries(gstgl @@ -70,6 +72,7 @@ else (WIN32) gstglbuffer.c gstglfilter.c gstglmixer.c + gstglshadervariables.c gstglshader.c) target_link_libraries(gstgl diff --git a/gst-libs/gst/gl/GNUmakefile.gnustep b/gst-libs/gst/gl/GNUmakefile.gnustep index ad83adab3c..bb977f4368 100644 --- a/gst-libs/gst/gl/GNUmakefile.gnustep +++ b/gst-libs/gst/gl/GNUmakefile.gnustep @@ -7,6 +7,7 @@ gstlibsgstgl_C_FILES = \ gstglbuffer.c \ gstglfilter.c \ gstglmixer.c \ + gstglshadervariables.c \ gstglshader.c gstlibsgstgl_OBJC_FILES = gstglwindow_cocoa.m diff --git a/gst-libs/gst/gl/Makefile.am b/gst-libs/gst/gl/Makefile.am index 1fe393e09d..2ef7afcd4a 100644 --- a/gst-libs/gst/gl/Makefile.am +++ b/gst-libs/gst/gl/Makefile.am @@ -13,7 +13,8 @@ libgstgl_@GST_MAJORMINOR@_la_SOURCES = \ gstglbuffer.c \ gstglfilter.c \ gstglmixer.c \ - gstglshader.c + gstglshader.c \ + gstglshadervariables.c if GL_BACKEND_WIN32 libgstgl_@GST_MAJORMINOR@_la_SOURCES += gstglwindow_win32.c @@ -37,6 +38,7 @@ libgstgl_@GST_MAJORMINOR@include_HEADERS = \ gstglfilter.h \ gstglmixer.h \ gstglmixerpad.h \ + gstglshadervariables.h \ gstglshader.h libgstgl_@GST_MAJORMINOR@_la_LIBADD = \ diff --git a/gst-libs/gst/gl/gstgles2.h b/gst-libs/gst/gl/gstgles2.h index e48c9f4b1b..a9e53f7ce6 100644 --- a/gst-libs/gst/gl/gstgles2.h +++ b/gst-libs/gst/gl/gstgles2.h @@ -94,7 +94,28 @@ G_BEGIN_DECLS #define glUniform1fARB glUniform1f #define glUniform1fvARB glUniform1fv #define glUniform1iARB glUniform1i +#define glUniform1ivARB glUniform1iv +#define glUniform2fARB glUniform2f +#define glUniform2fvARB glUniform2fv +#define glUniform2iARB glUniform2i +#define glUniform2ivARB glUniform2iv +#define glUniform3fARB glUniform3f +#define glUniform3fvARB glUniform3fv +#define glUniform3iARB glUniform3i +#define glUniform3ivARB glUniform3iv +#define glUniform4fARB glUniform4f +#define glUniform4fvARB glUniform4fv +#define glUniform4iARB glUniform4i +#define glUniform4ivARB glUniform4iv +#define glUniformMatrix2fvARB glUniformMatrix2fv +#define glUniformMatrix3fvARB glUniformMatrix3fv #define glUniformMatrix4fvARB glUniformMatrix4fv +#define glUniformMatrix2x3fvARB glUniformMatrix2x3fv +#define glUniformMatrix2x4fvARB glUniformMatrix2x4fv +#define glUniformMatrix3x2fvARB glUniformMatrix3x2fv +#define glUniformMatrix3x3fvARB glUniformMatrix3x4fv +#define glUniformMatrix4x2fvARB glUniformMatrix4x2fv +#define glUniformMatrix4x3fvARB glUniformMatrix4x3fv #define glGetUniformLocationARB glGetUniformLocation #define glGetAttribLocationARB glGetAttribLocation #define glBindAttribLocationARB glBindAttribLocation diff --git a/gst-libs/gst/gl/gstglshader.c b/gst-libs/gst/gl/gstglshader.c index 45fb3e3d94..0ae7b30200 100644 --- a/gst-libs/gst/gl/gstglshader.c +++ b/gst-libs/gst/gl/gstglshader.c @@ -518,6 +518,314 @@ gst_gl_shader_set_uniform_1i (GstGLShader * shader, const gchar * name, glUniform1iARB (location, value); } +void +gst_gl_shader_set_uniform_1iv (GstGLShader * shader, const gchar * name, + guint count, gint * value) +{ + GstGLShaderPrivate *priv; + GLint location = -1; + + priv = shader->priv; + + g_return_if_fail (priv->program_handle != 0); + + location = glGetUniformLocationARB (priv->program_handle, name); + + glUniform1ivARB (location, count, value); +} + +void +gst_gl_shader_set_uniform_2f (GstGLShader * shader, const gchar * name, + gfloat value0, gfloat value1) +{ + GstGLShaderPrivate *priv; + GLint location = -1; + + priv = shader->priv; + + g_return_if_fail (priv->program_handle != 0); + + location = glGetUniformLocationARB (priv->program_handle, name); + + glUniform2fARB (location, value0, value1); +} + +void +gst_gl_shader_set_uniform_2fv (GstGLShader * shader, const gchar * name, + guint count, gfloat * value) +{ + GstGLShaderPrivate *priv; + GLint location = -1; + + priv = shader->priv; + + g_return_if_fail (priv->program_handle != 0); + + location = glGetUniformLocationARB (priv->program_handle, name); + + glUniform2fvARB (location, count, value); +} + +void +gst_gl_shader_set_uniform_2i (GstGLShader * shader, const gchar * name, + gint v0, gint v1) +{ + GstGLShaderPrivate *priv; + GLint location = -1; + + priv = shader->priv; + + g_return_if_fail (priv->program_handle != 0); + + location = glGetUniformLocationARB (priv->program_handle, name); + + glUniform2iARB (location, v0, v1); +} + +void +gst_gl_shader_set_uniform_2iv (GstGLShader * shader, const gchar * name, + guint count, gint * value) +{ + GstGLShaderPrivate *priv; + GLint location = -1; + + priv = shader->priv; + + g_return_if_fail (priv->program_handle != 0); + + location = glGetUniformLocationARB (priv->program_handle, name); + + glUniform2ivARB (location, count, value); +} + +void +gst_gl_shader_set_uniform_3f (GstGLShader * shader, const gchar * name, + gfloat v0, gfloat v1, gfloat v2) +{ + GstGLShaderPrivate *priv; + GLint location = -1; + + priv = shader->priv; + + g_return_if_fail (priv->program_handle != 0); + + location = glGetUniformLocationARB (priv->program_handle, name); + + glUniform3fARB (location, v0, v1, v2); +} + +void +gst_gl_shader_set_uniform_3fv (GstGLShader * shader, const gchar * name, + guint count, gfloat * value) +{ + GstGLShaderPrivate *priv; + GLint location = -1; + + priv = shader->priv; + + g_return_if_fail (priv->program_handle != 0); + + location = glGetUniformLocationARB (priv->program_handle, name); + + glUniform3fvARB (location, count, value); +} + +void +gst_gl_shader_set_uniform_3i (GstGLShader * shader, const gchar * name, + gint v0, gint v1, gint v2) +{ + GstGLShaderPrivate *priv; + GLint location = -1; + + priv = shader->priv; + + g_return_if_fail (priv->program_handle != 0); + + location = glGetUniformLocationARB (priv->program_handle, name); + + glUniform3iARB (location, v0, v1, v2); +} + +void +gst_gl_shader_set_uniform_3iv (GstGLShader * shader, const gchar * name, + guint count, gint * value) +{ + GstGLShaderPrivate *priv; + GLint location = -1; + + priv = shader->priv; + + g_return_if_fail (priv->program_handle != 0); + + location = glGetUniformLocationARB (priv->program_handle, name); + + glUniform3ivARB (location, count, value); +} + +void +gst_gl_shader_set_uniform_4f (GstGLShader * shader, const gchar * name, + gfloat v0, gfloat v1, gfloat v2, gfloat v3) +{ + GstGLShaderPrivate *priv; + GLint location = -1; + + priv = shader->priv; + + g_return_if_fail (priv->program_handle != 0); + + location = glGetUniformLocationARB (priv->program_handle, name); + + glUniform4fARB (location, v0, v1, v2, v3); +} + +void +gst_gl_shader_set_uniform_4fv (GstGLShader * shader, const gchar * name, + guint count, gfloat * value) +{ + GstGLShaderPrivate *priv; + GLint location = -1; + + priv = shader->priv; + + g_return_if_fail (priv->program_handle != 0); + + location = glGetUniformLocationARB (priv->program_handle, name); + + glUniform4fvARB (location, count, value); +} + +void +gst_gl_shader_set_uniform_4i (GstGLShader * shader, const gchar * name, + gint v0, gint v1, gint v2, gint v3) +{ + GstGLShaderPrivate *priv; + GLint location = -1; + + priv = shader->priv; + + g_return_if_fail (priv->program_handle != 0); + + location = glGetUniformLocationARB (priv->program_handle, name); + + glUniform4iARB (location, v0, v1, v2, v3); +} + +void +gst_gl_shader_set_uniform_4iv (GstGLShader * shader, const gchar * name, + guint count, gint * value) +{ + GstGLShaderPrivate *priv; + GLint location = -1; + + priv = shader->priv; + + g_return_if_fail (priv->program_handle != 0); + + location = glGetUniformLocationARB (priv->program_handle, name); + + glUniform4ivARB (location, count, value); +} + +void +gst_gl_shader_set_uniform_matrix_2fv (GstGLShader * shader, const gchar * name, + GLsizei count, GLboolean transpose, const GLfloat * value) +{ + GstGLShaderPrivate *priv; + GLint location = -1; + + priv = shader->priv; + + g_return_if_fail (priv->program_handle != 0); + + location = glGetUniformLocationARB (priv->program_handle, name); + + glUniformMatrix2fvARB (location, count, transpose, value); +} + +void +gst_gl_shader_set_uniform_matrix_2x3fv (GstGLShader * shader, + const gchar * name, GLsizei count, GLboolean transpose, + const GLfloat * value) +{ + GstGLShaderPrivate *priv; + GLint location = -1; + + priv = shader->priv; + + g_return_if_fail (priv->program_handle != 0); + + location = glGetUniformLocationARB (priv->program_handle, name); + + glUniformMatrix2x3fv (location, count, transpose, value); +} + +void +gst_gl_shader_set_uniform_matrix_2x4fv (GstGLShader * shader, + const gchar * name, GLsizei count, GLboolean transpose, + const GLfloat * value) +{ + GstGLShaderPrivate *priv; + GLint location = -1; + + priv = shader->priv; + + g_return_if_fail (priv->program_handle != 0); + + location = glGetUniformLocationARB (priv->program_handle, name); + + glUniformMatrix2x4fv (location, count, transpose, value); +} + +void +gst_gl_shader_set_uniform_matrix_3fv (GstGLShader * shader, const gchar * name, + GLsizei count, GLboolean transpose, const GLfloat * value) +{ + GstGLShaderPrivate *priv; + GLint location = -1; + + priv = shader->priv; + + g_return_if_fail (priv->program_handle != 0); + + location = glGetUniformLocationARB (priv->program_handle, name); + + glUniformMatrix3fvARB (location, count, transpose, value); +} + +void +gst_gl_shader_set_uniform_matrix_3x2fv (GstGLShader * shader, + const gchar * name, GLsizei count, GLboolean transpose, + const GLfloat * value) +{ + GstGLShaderPrivate *priv; + GLint location = -1; + + priv = shader->priv; + + g_return_if_fail (priv->program_handle != 0); + + location = glGetUniformLocationARB (priv->program_handle, name); + + glUniformMatrix3x2fv (location, count, transpose, value); +} + +void +gst_gl_shader_set_uniform_matrix_3x4fv (GstGLShader * shader, + const gchar * name, GLsizei count, GLboolean transpose, + const GLfloat * value) +{ + GstGLShaderPrivate *priv; + GLint location = -1; + + priv = shader->priv; + + g_return_if_fail (priv->program_handle != 0); + + location = glGetUniformLocationARB (priv->program_handle, name); + + glUniformMatrix3x4fv (location, count, transpose, value); +} + void gst_gl_shader_set_uniform_matrix_4fv (GstGLShader * shader, const gchar * name, GLsizei count, GLboolean transpose, const GLfloat * value) @@ -534,6 +842,40 @@ gst_gl_shader_set_uniform_matrix_4fv (GstGLShader * shader, const gchar * name, glUniformMatrix4fvARB (location, count, transpose, value); } +void +gst_gl_shader_set_uniform_matrix_4x2fv (GstGLShader * shader, + const gchar * name, GLsizei count, GLboolean transpose, + const GLfloat * value) +{ + GstGLShaderPrivate *priv; + GLint location = -1; + + priv = shader->priv; + + g_return_if_fail (priv->program_handle != 0); + + location = glGetUniformLocationARB (priv->program_handle, name); + + glUniformMatrix4x2fv (location, count, transpose, value); +} + +void +gst_gl_shader_set_uniform_matrix_4x3fv (GstGLShader * shader, + const gchar * name, GLsizei count, GLboolean transpose, + const GLfloat * value) +{ + GstGLShaderPrivate *priv; + GLint location = -1; + + priv = shader->priv; + + g_return_if_fail (priv->program_handle != 0); + + location = glGetUniformLocationARB (priv->program_handle, name); + + glUniformMatrix4x3fv (location, count, transpose, value); +} + GLint gst_gl_shader_get_attribute_location (GstGLShader * shader, const gchar * name) { diff --git a/gst-libs/gst/gl/gstglshader.h b/gst-libs/gst/gl/gstglshader.h index a63316b930..a200805c7f 100644 --- a/gst-libs/gst/gl/gstglshader.h +++ b/gst-libs/gst/gl/gstglshader.h @@ -93,10 +93,39 @@ void gst_gl_shader_release (GstGLShader *shader); void gst_gl_shader_use (GstGLShader *shader); void gst_gl_shader_set_uniform_1i (GstGLShader *shader, const gchar *name, gint value); +void gst_gl_shader_set_uniform_1iv (GstGLShader *shader, const gchar *name, guint count, gint * value); void gst_gl_shader_set_uniform_1f (GstGLShader *shader, const gchar *name, gfloat value); void gst_gl_shader_set_uniform_1fv (GstGLShader *shader, const gchar *name, guint count, gfloat * value); +void gst_gl_shader_set_uniform_2i (GstGLShader *shader, const gchar *name, gint v0, gint v1); +void gst_gl_shader_set_uniform_2iv (GstGLShader *shader, const gchar *name, guint count, gint * value); +void gst_gl_shader_set_uniform_2f (GstGLShader *shader, const gchar *name, gfloat v0, gfloat v1); +void gst_gl_shader_set_uniform_2fv (GstGLShader *shader, const gchar *name, guint count, gfloat * value); +void gst_gl_shader_set_uniform_3i (GstGLShader *shader, const gchar *name, gint v0, gint v1, gint v2); +void gst_gl_shader_set_uniform_3iv (GstGLShader *shader, const gchar *name, guint count, gint * value); +void gst_gl_shader_set_uniform_3f (GstGLShader *shader, const gchar *name, gfloat v0, gfloat v1, gfloat v2); +void gst_gl_shader_set_uniform_3fv (GstGLShader *shader, const gchar *name, guint count, gfloat * value); +void gst_gl_shader_set_uniform_4i (GstGLShader *shader, const gchar *name, gint v0, gint v1, gint v2, gint v3); +void gst_gl_shader_set_uniform_4iv (GstGLShader *shader, const gchar *name, guint count, gint * value); +void gst_gl_shader_set_uniform_4f (GstGLShader *shader, const gchar *name, gfloat v0, gfloat v1, gfloat v2, gfloat v3); +void gst_gl_shader_set_uniform_4fv (GstGLShader *shader, const gchar *name, guint count, gfloat * value); +void gst_gl_shader_set_uniform_matrix_2fv (GstGLShader * shader, const gchar * name, + GLsizei count, GLboolean transpose, const GLfloat* value); +void gst_gl_shader_set_uniform_matrix_2x3fv (GstGLShader * shader, const gchar * name, + GLsizei count, GLboolean transpose, const GLfloat* value); +void gst_gl_shader_set_uniform_matrix_2x4fv (GstGLShader * shader, const gchar * name, + GLsizei count, GLboolean transpose, const GLfloat* value); +void gst_gl_shader_set_uniform_matrix_3fv (GstGLShader * shader, const gchar * name, + GLsizei count, GLboolean transpose, const GLfloat* value); +void gst_gl_shader_set_uniform_matrix_3x2fv (GstGLShader * shader, const gchar * name, + GLsizei count, GLboolean transpose, const GLfloat* value); +void gst_gl_shader_set_uniform_matrix_3x4fv (GstGLShader * shader, const gchar * name, + GLsizei count, GLboolean transpose, const GLfloat* value); void gst_gl_shader_set_uniform_matrix_4fv (GstGLShader * shader, const gchar * name, GLsizei count, GLboolean transpose, const GLfloat* value); +void gst_gl_shader_set_uniform_matrix_4x2fv (GstGLShader * shader, const gchar * name, + GLsizei count, GLboolean transpose, const GLfloat* value); +void gst_gl_shader_set_uniform_matrix_4x3fv (GstGLShader * shader, const gchar * name, + GLsizei count, GLboolean transpose, const GLfloat* value); GLint gst_gl_shader_get_attribute_location (GstGLShader *shader, const gchar *name); void gst_gl_shader_bind_attribute_location (GstGLShader * shader, GLuint index, const gchar * name); diff --git a/gst-libs/gst/gl/gstglshadervariables.c b/gst-libs/gst/gl/gstglshadervariables.c new file mode 100644 index 0000000000..ad0644f66a --- /dev/null +++ b/gst-libs/gst/gl/gstglshadervariables.c @@ -0,0 +1,1473 @@ +/* + * GStreamer + * Copyright (C) 2009 Luc Deschenaux + * + * 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 *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; + +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 0000000000..01b6d8f6d0 --- /dev/null +++ b/gst-libs/gst/gl/gstglshadervariables.h @@ -0,0 +1,39 @@ +/* + * GStreamer + * Copyright (C) 2009 Luc Deschenaux + * + * 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 +#include +#include +#include + +#define VALID_VARNAME_CHARS "abcdefghijklmnopqurstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_" + +struct 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/CMakeLists.txt b/gst/gl/CMakeLists.txt index 24ebb2a9cd..9fbd0b9d00 100755 --- a/gst/gl/CMakeLists.txt +++ b/gst/gl/CMakeLists.txt @@ -34,6 +34,7 @@ add_library (gstopengl MODULE gstglfilterglass.c gstglfilterapp.c gstglfilterreflectedscreen.c + gstglfiltershader.c gstglcolorscale.c gltestsrc.c gstgltestsrc.c diff --git a/gst/gl/GNUmakefile.gnustep b/gst/gl/GNUmakefile.gnustep index 4f2ceb658e..37df1d4b10 100644 --- a/gst/gl/GNUmakefile.gnustep +++ b/gst/gl/GNUmakefile.gnustep @@ -14,6 +14,7 @@ gstgl_C_FILES += \ gstglfilterglass.c \ gstglfilterapp.c \ gstglfilterreflectedscreen.c \ + gstglfiltershader.c \ gstglcolorscale.c \ gltestsrc.c \ gstgltestsrc.c \ diff --git a/gst/gl/Makefile.am b/gst/gl/Makefile.am index 2bcf641ad4..fc433030b7 100644 --- a/gst/gl/Makefile.am +++ b/gst/gl/Makefile.am @@ -9,6 +9,8 @@ if GL_IS_OPENGL OPENGL_SOURCES = \ gstglbumper.c \ gstglbumper.h \ + gstglfiltershader.c \ + gstglfiltershader.h \ gstglfilterblur.c \ gstglfilterblur.h \ gstglfiltersobel.c \ diff --git a/gst/gl/gstglfiltershader.c b/gst/gl/gstglfiltershader.c new file mode 100644 index 0000000000..e3b8621e82 --- /dev/null +++ b/gst/gl/gstglfiltershader.c @@ -0,0 +1,405 @@ +/* + * glshader gstreamer plugin + * Copyrithg (C) 2008 Filippo Argiolas + * Copyright (C) 2009 Luc Deschenaux + * + * 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 + * + * + * Examples + * |[ + * gst-launch videotestsrc ! glupload ! glshader location=myshader.fs ! glimagesink + * ]| + * FBO (Frame Buffer Object) and GLSL (OpenGL Shading Language) are required. + * + */ + +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include "gstglfiltershader.h" +#include + +/* 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); + +#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_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_simple (element_class, + "OpenGL fragment shader filter", "Filter/Effect", + "Load GLSL fragment shader from file", ""); + /* 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 gboolean +gst_gl_filtershader_filter (GstGLFilter * filter, GstGLBuffer * inbuf, + GstGLBuffer * outbuf) +{ + 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); /// + + return TRUE; +} + +static void +gst_gl_filtershader_hcallback (gint width, gint height, guint texture, + gpointer stuff) +{ + GstGLFilter *filter = GST_GL_FILTER (stuff); + GstGLFilterShader *filtershader = GST_GL_FILTERSHADER (filter); + + 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); + + gst_gl_shader_set_uniform_1i (filtershader->shader0, "tex", 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_filter_draw_texture (filter, texture); + +} diff --git a/gst/gl/gstglfiltershader.h b/gst/gl/gstglfiltershader.h new file mode 100644 index 0000000000..266d3a7af2 --- /dev/null +++ b/gst/gl/gstglfiltershader.h @@ -0,0 +1,55 @@ +/* + * glshader gstreamer plugin + * Copyright (C) 2008 Filippo Argiolas + * Copyright (C) 2009 Luc Deschenaux + * + * 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 + +#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_ */ diff --git a/gst/gl/gstopengl.c b/gst/gl/gstopengl.c index ee8e546bda..cd66544eae 100644 --- a/gst/gl/gstopengl.c +++ b/gst/gl/gstopengl.c @@ -59,6 +59,7 @@ GType gst_gl_effects_get_type (void); #include "gstglfilterglass.h" #include "gstglfilterapp.h" #include "gstglfilterreflectedscreen.h" +#include "gstglfiltershader.h" #include "gstglcolorscale.h" #include "gstgldeinterlace.h" #include "gstglbumper.h" @@ -68,6 +69,7 @@ GType gst_gl_deinterlace_get_type (void); GType gst_gl_filter_app_get_type (void); GType gst_gl_filter_reflected_screen_get_type (void); GType gst_gl_filterblur_get_type (void); +GType gst_gl_filtershader_get_type (void); GType gst_gl_filtersobel_get_type (void); GType gst_gl_filter_laplacian_get_type (void); GType gst_gl_filter_glass_get_type (void); @@ -134,6 +136,11 @@ plugin_init (GstPlugin * plugin) return FALSE; } + if (!gst_element_register (plugin, "glshader", + GST_RANK_NONE, gst_gl_filtershader_get_type ())) { + return FALSE; + } + if (!gst_element_register (plugin, "glfiltersobel", GST_RANK_NONE, gst_gl_filtersobel_get_type ())) { return FALSE;