glviewconvert: Port more things to GLES/GL 3 compatibility
authorSebastian Dröge <sebastian@centricular.com>
Tue, 19 Apr 2016 16:43:03 +0000 (19:43 +0300)
committerSebastian Dröge <sebastian@centricular.com>
Wed, 27 Apr 2016 08:47:20 +0000 (11:47 +0300)
And move the shader mangling code into a single place instead of having a copy
in glcolorconvert and glviewconvert.

https://bugzilla.gnome.org/show_bug.cgi?id=765266

gst-libs/gst/gl/gstglcolorconvert.c
gst-libs/gst/gl/gstglsl.c
gst-libs/gst/gl/gstglsl_private.h
gst-libs/gst/gl/gstglviewconvert.c

index ae3d7fe8d9ab9e998373f2d2491fc8848ae7c434..ba717fadfef8b8e3f8b8cc9207f2732620c6965e 100644 (file)
@@ -27,6 +27,7 @@
 
 #include "gl.h"
 #include "gstglcolorconvert.h"
+#include "gstglsl_private.h"
 
 /**
  * SECTION:gstglcolorconvert
@@ -1710,209 +1711,6 @@ _unbind_buffer (GstGLColorConvert * convert)
   gl->DisableVertexAttribArray (convert->priv->attr_texture);
 }
 
-static gchar *
-_mangle_texture_access (const gchar * str, GstGLTextureTarget from,
-    GstGLTextureTarget to, GstGLAPI gl_api, guint gl_major, guint gl_minor)
-{
-  const gchar *from_str = NULL, *to_str = NULL;
-  gchar *ret, *tmp;
-  gchar *regex_find;
-  GRegex *regex;
-
-  if (from == GST_GL_TEXTURE_TARGET_2D)
-    from_str = "texture2D";
-  if (from == GST_GL_TEXTURE_TARGET_RECTANGLE)
-    from_str = "texture2DRect";
-  if (from == GST_GL_TEXTURE_TARGET_EXTERNAL_OES)
-    from_str = "texture2D";
-
-  if ((gl_api & GST_GL_API_OPENGL3) || (gl_api & GST_GL_API_GLES2
-          && gl_major >= 3)) {
-    to_str = "texture";
-  } else {
-    if (to == GST_GL_TEXTURE_TARGET_2D)
-      to_str = "texture2D";
-    if (to == GST_GL_TEXTURE_TARGET_RECTANGLE)
-      to_str = "texture2DRect";
-    if (to == GST_GL_TEXTURE_TARGET_EXTERNAL_OES)
-      to_str = "texture2D";
-  }
-
-  /* followed by any amount of whitespace then a bracket */
-  regex_find = g_strdup_printf ("%s(?=\\s*\\()", from_str);
-  regex = g_regex_new (regex_find, 0, 0, NULL);
-  tmp = g_regex_replace_literal (regex, str, -1, 0, to_str, 0, NULL);
-  g_free (regex_find);
-  g_regex_unref (regex);
-
-  if (tmp) {
-    ret = tmp;
-  } else {
-    GST_FIXME ("Couldn't mangle texture access successfully from %s to %s",
-        from_str, to_str);
-    ret = g_strdup (str);
-  }
-
-  return ret;
-}
-
-static gchar *
-_mangle_sampler_type (const gchar * str, GstGLTextureTarget from,
-    GstGLTextureTarget to)
-{
-  const gchar *from_str = NULL, *to_str = NULL;
-  gchar *ret, *tmp;
-  gchar *regex_find;
-  GRegex *regex;
-
-  if (from == GST_GL_TEXTURE_TARGET_2D)
-    from_str = "sampler2D";
-  if (from == GST_GL_TEXTURE_TARGET_RECTANGLE)
-    from_str = "sampler2DRect";
-  if (from == GST_GL_TEXTURE_TARGET_EXTERNAL_OES)
-    from_str = "samplerExternalOES";
-
-  if (to == GST_GL_TEXTURE_TARGET_2D)
-    to_str = "sampler2D";
-  if (to == GST_GL_TEXTURE_TARGET_RECTANGLE)
-    to_str = "sampler2DRect";
-  if (to == GST_GL_TEXTURE_TARGET_EXTERNAL_OES)
-    to_str = "samplerExternalOES";
-
-  /* followed by some whitespace  */
-  regex_find = g_strdup_printf ("%s(?=\\s)", from_str);
-  regex = g_regex_new (regex_find, 0, 0, NULL);
-  tmp = g_regex_replace_literal (regex, str, -1, 0, to_str, 0, NULL);
-  g_free (regex_find);
-  g_regex_unref (regex);
-
-  if (tmp) {
-    ret = tmp;
-  } else {
-    GST_FIXME ("Couldn't mangle sampler type successfully from %s to %s",
-        from_str, to_str);
-    ret = g_strdup (str);
-  }
-
-  return ret;
-}
-
-static gchar *
-_mangle_varying_attribute (const gchar * str, guint shader_type,
-    GstGLAPI gl_api, guint gl_major, guint gl_minor)
-{
-  if (shader_type == GL_VERTEX_SHADER) {
-    if ((gl_api & GST_GL_API_OPENGL3) || (gl_api & GST_GL_API_GLES2
-            && gl_major >= 3)) {
-      gchar *tmp, *tmp2;
-      GRegex *regex;
-
-      /* followed by some whitespace  */
-      regex = g_regex_new ("varying(?=\\s)", 0, 0, NULL);
-      tmp = g_regex_replace_literal (regex, str, -1, 0, "out", 0, NULL);
-      g_regex_unref (regex);
-
-      /* followed by some whitespace  */
-      regex = g_regex_new ("attribute(?=\\s)", 0, 0, NULL);
-      tmp2 = g_regex_replace_literal (regex, tmp, -1, 0, "in", 0, NULL);
-      g_regex_unref (regex);
-
-      g_free (tmp);
-      return tmp2;
-    }
-  } else if (shader_type == GL_FRAGMENT_SHADER) {
-    if ((gl_api & GST_GL_API_OPENGL3) || (gl_api & GST_GL_API_GLES2
-            && gl_major > 3)) {
-      gchar *tmp;
-      GRegex *regex;
-
-      /* followed by some whitespace  */
-      regex = g_regex_new ("varying(?=\\s)", 0, 0, NULL);
-      tmp = g_regex_replace_literal (regex, str, -1, 0, "in", 0, NULL);
-      g_regex_unref (regex);
-
-      return tmp;
-    }
-  }
-  return g_strdup (str);
-}
-
-static gchar *
-_mangle_frag_color_data (const gchar * str)
-{
-  GRegex *regex;
-  gchar *ret, *tmp;
-
-  regex = g_regex_new ("gl_FragColor", 0, 0, NULL);
-  ret = g_regex_replace_literal (regex, str, -1, 0, "fragColor", 0, NULL);
-  g_regex_unref (regex);
-
-  tmp = ret;
-  /* search and replace 'gl_FragData[NUM]' into fragColor_NUM */
-  regex = g_regex_new ("gl_FragData\\[(\\d+)\\]", 0, 0, NULL);
-  ret = g_regex_replace (regex, tmp, -1, 0, "fragColor_\\1", 0, NULL);
-  g_regex_unref (regex);
-  g_free (tmp);
-
-  return ret;
-}
-
-static void
-_mangle_version_profile_from_gl_api (GstGLAPI gl_api, gint gl_major,
-    gint gl_minor, GstGLSLVersion * version, GstGLSLProfile * profile)
-{
-  *version = GST_GLSL_VERSION_NONE;
-  *profile = GST_GLSL_PROFILE_NONE;
-
-  if (gl_api & GST_GL_API_OPENGL3) {
-    if (gl_major > 3 || gl_minor >= 3) {
-      *version = GST_GLSL_VERSION_330;
-      *profile = GST_GLSL_PROFILE_CORE;
-    } else {
-      *version = GST_GLSL_VERSION_150;
-      *profile = GST_GLSL_PROFILE_NONE;
-    }
-  } else if (gl_api & GST_GL_API_GLES2) {
-    if (gl_major >= 3) {
-      *version = GST_GLSL_VERSION_300;
-      *profile = GST_GLSL_PROFILE_ES;
-    } else if (gl_major >= 2) {
-      *version = GST_GLSL_VERSION_100;
-      *profile = GST_GLSL_PROFILE_ES;
-    }
-  } else if (gl_api & GST_GL_API_OPENGL) {
-    *version = GST_GLSL_VERSION_110;
-    *profile = GST_GLSL_PROFILE_COMPATIBILITY;
-  }
-}
-
-static gchar *
-_mangle_shader (const gchar * str, guint shader_type, GstGLTextureTarget from,
-    GstGLTextureTarget to, GstGLAPI gl_api, gint gl_major, gint gl_minor,
-    GstGLSLVersion * version, GstGLSLProfile * profile)
-{
-  gchar *tmp, *tmp2;
-
-  _mangle_version_profile_from_gl_api (gl_api, gl_major, gl_minor, version,
-      profile);
-  tmp = _mangle_texture_access (str, from, to, gl_api, gl_major, gl_minor);
-  tmp2 = _mangle_sampler_type (tmp, from, to);
-  g_free (tmp);
-  tmp =
-      _mangle_varying_attribute (tmp2, shader_type, gl_api, gl_major, gl_minor);
-  g_free (tmp2);
-  if (shader_type == GL_FRAGMENT_SHADER) {
-    if ((*profile == GST_GLSL_PROFILE_ES && *version >= GST_GLSL_VERSION_300)
-        || (*profile == GST_GLSL_PROFILE_CORE
-            && *version >= GST_GLSL_VERSION_150)) {
-      tmp2 = _mangle_frag_color_data (tmp);
-      g_free (tmp);
-      tmp = tmp2;
-    }
-  }
-  return tmp;
-}
-
 static GstGLShader *
 _create_shader (GstGLColorConvert * convert)
 {
@@ -1935,9 +1733,9 @@ _create_shader (GstGLColorConvert * convert)
   ret = gst_gl_shader_new (convert->context);
 
   tmp =
-      _mangle_shader (text_vertex_shader, GL_VERTEX_SHADER, info->templ->target,
-      convert->priv->from_texture_target, gl_api, gl_major, gl_minor, &version,
-      &profile);
+      _gst_glsl_mangle_shader (text_vertex_shader, GL_VERTEX_SHADER,
+      info->templ->target, convert->priv->from_texture_target, gl_api, gl_major,
+      gl_minor, &version, &profile);
 
   tmp1 = gst_glsl_version_profile_to_string (version, profile);
   version_str = g_strdup_printf ("#version %s\n", tmp1);
@@ -2043,7 +1841,7 @@ _create_shader (GstGLColorConvert * convert)
   }
   g_string_append (str, "\n}");
   tmp = g_string_free (str, FALSE);
-  info->frag_prog = _mangle_shader (tmp, GL_FRAGMENT_SHADER,
+  info->frag_prog = _gst_glsl_mangle_shader (tmp, GL_FRAGMENT_SHADER,
       info->templ->target, convert->priv->from_texture_target, gl_api,
       gl_major, gl_minor, &version, &profile);
   g_free (tmp);
index 50745529056e5f655968a61ff8d259c00975d9a7..daf4e35260b5b2bcc5d76929ff1dec0d4fca5aff 100644 (file)
@@ -551,3 +551,208 @@ _gst_glsl_funcs_fill (GstGLSLFuncs * vtable, GstGLContext * context)
   vtable->initialized = TRUE;
   return TRUE;
 }
+
+
+static gchar *
+_mangle_texture_access (const gchar * str, GstGLTextureTarget from,
+    GstGLTextureTarget to, GstGLAPI gl_api, guint gl_major, guint gl_minor)
+{
+  const gchar *from_str = NULL, *to_str = NULL;
+  gchar *ret, *tmp;
+  gchar *regex_find;
+  GRegex *regex;
+
+  if (from == GST_GL_TEXTURE_TARGET_2D)
+    from_str = "texture2D";
+  if (from == GST_GL_TEXTURE_TARGET_RECTANGLE)
+    from_str = "texture2DRect";
+  if (from == GST_GL_TEXTURE_TARGET_EXTERNAL_OES)
+    from_str = "texture2D";
+
+  if ((gl_api & GST_GL_API_OPENGL3) || (gl_api & GST_GL_API_GLES2
+          && gl_major >= 3)) {
+    to_str = "texture";
+  } else {
+    if (to == GST_GL_TEXTURE_TARGET_2D)
+      to_str = "texture2D";
+    if (to == GST_GL_TEXTURE_TARGET_RECTANGLE)
+      to_str = "texture2DRect";
+    if (to == GST_GL_TEXTURE_TARGET_EXTERNAL_OES)
+      to_str = "texture2D";
+  }
+
+  /* followed by any amount of whitespace then a bracket */
+  regex_find = g_strdup_printf ("%s(?=\\s*\\()", from_str);
+  regex = g_regex_new (regex_find, 0, 0, NULL);
+  tmp = g_regex_replace_literal (regex, str, -1, 0, to_str, 0, NULL);
+  g_free (regex_find);
+  g_regex_unref (regex);
+
+  if (tmp) {
+    ret = tmp;
+  } else {
+    GST_FIXME ("Couldn't mangle texture access successfully from %s to %s",
+        from_str, to_str);
+    ret = g_strdup (str);
+  }
+
+  return ret;
+}
+
+static gchar *
+_mangle_sampler_type (const gchar * str, GstGLTextureTarget from,
+    GstGLTextureTarget to)
+{
+  const gchar *from_str = NULL, *to_str = NULL;
+  gchar *ret, *tmp;
+  gchar *regex_find;
+  GRegex *regex;
+
+  if (from == GST_GL_TEXTURE_TARGET_2D)
+    from_str = "sampler2D";
+  if (from == GST_GL_TEXTURE_TARGET_RECTANGLE)
+    from_str = "sampler2DRect";
+  if (from == GST_GL_TEXTURE_TARGET_EXTERNAL_OES)
+    from_str = "samplerExternalOES";
+
+  if (to == GST_GL_TEXTURE_TARGET_2D)
+    to_str = "sampler2D";
+  if (to == GST_GL_TEXTURE_TARGET_RECTANGLE)
+    to_str = "sampler2DRect";
+  if (to == GST_GL_TEXTURE_TARGET_EXTERNAL_OES)
+    to_str = "samplerExternalOES";
+
+  /* followed by some whitespace  */
+  regex_find = g_strdup_printf ("%s(?=\\s)", from_str);
+  regex = g_regex_new (regex_find, 0, 0, NULL);
+  tmp = g_regex_replace_literal (regex, str, -1, 0, to_str, 0, NULL);
+  g_free (regex_find);
+  g_regex_unref (regex);
+
+  if (tmp) {
+    ret = tmp;
+  } else {
+    GST_FIXME ("Couldn't mangle sampler type successfully from %s to %s",
+        from_str, to_str);
+    ret = g_strdup (str);
+  }
+
+  return ret;
+}
+
+static gchar *
+_mangle_varying_attribute (const gchar * str, guint shader_type,
+    GstGLAPI gl_api, guint gl_major, guint gl_minor)
+{
+  if (shader_type == GL_VERTEX_SHADER) {
+    if ((gl_api & GST_GL_API_OPENGL3) || (gl_api & GST_GL_API_GLES2
+            && gl_major >= 3)) {
+      gchar *tmp, *tmp2;
+      GRegex *regex;
+
+      /* followed by some whitespace  */
+      regex = g_regex_new ("varying(?=\\s)", 0, 0, NULL);
+      tmp = g_regex_replace_literal (regex, str, -1, 0, "out", 0, NULL);
+      g_regex_unref (regex);
+
+      /* followed by some whitespace  */
+      regex = g_regex_new ("attribute(?=\\s)", 0, 0, NULL);
+      tmp2 = g_regex_replace_literal (regex, tmp, -1, 0, "in", 0, NULL);
+      g_regex_unref (regex);
+
+      g_free (tmp);
+      return tmp2;
+    }
+  } else if (shader_type == GL_FRAGMENT_SHADER) {
+    if ((gl_api & GST_GL_API_OPENGL3) || (gl_api & GST_GL_API_GLES2
+            && gl_major > 3)) {
+      gchar *tmp;
+      GRegex *regex;
+
+      /* followed by some whitespace  */
+      regex = g_regex_new ("varying(?=\\s)", 0, 0, NULL);
+      tmp = g_regex_replace_literal (regex, str, -1, 0, "in", 0, NULL);
+      g_regex_unref (regex);
+
+      return tmp;
+    }
+  }
+  return g_strdup (str);
+}
+
+static gchar *
+_mangle_frag_color_data (const gchar * str)
+{
+  GRegex *regex;
+  gchar *ret, *tmp;
+
+  regex = g_regex_new ("gl_FragColor", 0, 0, NULL);
+  ret = g_regex_replace_literal (regex, str, -1, 0, "fragColor", 0, NULL);
+  g_regex_unref (regex);
+
+  tmp = ret;
+  /* search and replace 'gl_FragData[NUM]' into fragColor_NUM */
+  regex = g_regex_new ("gl_FragData\\[(\\d+)\\]", 0, 0, NULL);
+  ret = g_regex_replace (regex, tmp, -1, 0, "fragColor_\\1", 0, NULL);
+  g_regex_unref (regex);
+  g_free (tmp);
+
+  return ret;
+}
+
+static void
+_mangle_version_profile_from_gl_api (GstGLAPI gl_api, gint gl_major,
+    gint gl_minor, GstGLSLVersion * version, GstGLSLProfile * profile)
+{
+  *version = GST_GLSL_VERSION_NONE;
+  *profile = GST_GLSL_PROFILE_NONE;
+
+  if (gl_api & GST_GL_API_OPENGL3) {
+    if (gl_major > 3 || gl_minor >= 3) {
+      *version = GST_GLSL_VERSION_330;
+      *profile = GST_GLSL_PROFILE_CORE;
+    } else {
+      *version = GST_GLSL_VERSION_150;
+      *profile = GST_GLSL_PROFILE_NONE;
+    }
+  } else if (gl_api & GST_GL_API_GLES2) {
+    if (gl_major >= 3) {
+      *version = GST_GLSL_VERSION_300;
+      *profile = GST_GLSL_PROFILE_ES;
+    } else if (gl_major >= 2) {
+      *version = GST_GLSL_VERSION_100;
+      *profile = GST_GLSL_PROFILE_ES;
+    }
+  } else if (gl_api & GST_GL_API_OPENGL) {
+    *version = GST_GLSL_VERSION_110;
+    *profile = GST_GLSL_PROFILE_COMPATIBILITY;
+  }
+}
+
+gchar *
+_gst_glsl_mangle_shader (const gchar * str, guint shader_type,
+    GstGLTextureTarget from, GstGLTextureTarget to, GstGLAPI gl_api,
+    gint gl_major, gint gl_minor, GstGLSLVersion * version,
+    GstGLSLProfile * profile)
+{
+  gchar *tmp, *tmp2;
+
+  _mangle_version_profile_from_gl_api (gl_api, gl_major, gl_minor, version,
+      profile);
+  tmp = _mangle_texture_access (str, from, to, gl_api, gl_major, gl_minor);
+  tmp2 = _mangle_sampler_type (tmp, from, to);
+  g_free (tmp);
+  tmp =
+      _mangle_varying_attribute (tmp2, shader_type, gl_api, gl_major, gl_minor);
+  g_free (tmp2);
+  if (shader_type == GL_FRAGMENT_SHADER) {
+    if ((*profile == GST_GLSL_PROFILE_ES && *version >= GST_GLSL_VERSION_300)
+        || (*profile == GST_GLSL_PROFILE_CORE
+            && *version >= GST_GLSL_VERSION_150)) {
+      tmp2 = _mangle_frag_color_data (tmp);
+      g_free (tmp);
+      tmp = tmp2;
+    }
+  }
+  return tmp;
+}
index c1be677ae4348615f05092edb174d809b36ef4d3..49c6b382bdb0eafeb0f6b5d8501bd3895b389bf6 100644 (file)
@@ -58,6 +58,11 @@ typedef struct _GstGLSLFuncs
 G_GNUC_INTERNAL gboolean _gst_glsl_funcs_fill (GstGLSLFuncs * vtable, GstGLContext * context);
 G_GNUC_INTERNAL const gchar * _gst_glsl_shader_string_find_version (const gchar * str);
 
+G_GNUC_INTERNAL gchar *
+_gst_glsl_mangle_shader (const gchar * str, guint shader_type, GstGLTextureTarget from,
+    GstGLTextureTarget to, GstGLAPI gl_api, gint gl_major, gint gl_minor,
+    GstGLSLVersion * version, GstGLSLProfile * profile);
+
 G_END_DECLS
 
 #endif /* __GST_GLSL_PRIVATE_H__ */
index ec335e1e62f5dd5206cb125adeb2b716df18baee..be940aab60122f4e62ef23c2e0a6b4e7c8da9efd 100644 (file)
@@ -31,6 +31,7 @@
 #endif
 
 #include "gstglviewconvert.h"
+#include "gstglsl_private.h"
 #include <gst/video/gstvideoaffinetransformationmeta.h>
 
 #define USING_OPENGL(context) (gst_gl_context_check_gl_version (context, GST_GL_API_OPENGL, 1, 0))
@@ -159,7 +160,6 @@ static const gchar *fragment_header =
   "#ifdef GL_ES\n"
   "precision mediump float;\n"
   "#endif\n"
-  "varying vec2 v_texcoord;\n"
   "uniform sampler2D tex_l;\n"
   "uniform sampler2D tex_r;\n"
   "uniform float width;\n"
@@ -1453,205 +1453,11 @@ _init_view_convert_fbo (GstGLViewConvert * viewconvert)
   return ret;
 }
 
-static gchar *
-_mangle_texture_access (const gchar * str, GstGLTextureTarget from,
-    GstGLTextureTarget to)
-{
-  const gchar *from_str = NULL, *to_str = NULL;
-  gchar *ret, *tmp;
-  gchar *regex_find;
-  GRegex *regex;
-
-  if (from == GST_GL_TEXTURE_TARGET_2D)
-    from_str = "texture2D";
-  if (from == GST_GL_TEXTURE_TARGET_RECTANGLE)
-    from_str = "texture2DRect";
-  if (from == GST_GL_TEXTURE_TARGET_EXTERNAL_OES)
-    from_str = "texture2D";
-
-  if (to == GST_GL_TEXTURE_TARGET_2D)
-    to_str = "texture2D";
-  if (to == GST_GL_TEXTURE_TARGET_RECTANGLE)
-    to_str = "texture2DRect";
-  if (to == GST_GL_TEXTURE_TARGET_EXTERNAL_OES)
-    to_str = "texture2D";
-
-  /* followed by any amount of whitespace then a bracket */
-  regex_find = g_strdup_printf ("%s(?=\\s*\\()", from_str);
-  regex = g_regex_new (regex_find, 0, 0, NULL);
-  tmp = g_regex_replace_literal (regex, str, -1, 0, to_str, 0, NULL);
-  g_free (regex_find);
-  g_regex_unref (regex);
-
-  if (tmp) {
-    ret = tmp;
-  } else {
-    GST_FIXME ("Couldn't mangle texture access successfully from %s to %s",
-        from_str, to_str);
-    ret = g_strdup (str);
-  }
-
-  return ret;
-}
-
-static gchar *
-_mangle_sampler_type (const gchar * str, GstGLTextureTarget from,
-    GstGLTextureTarget to)
-{
-  const gchar *from_str = NULL, *to_str = NULL;
-  gchar *ret, *tmp;
-  gchar *regex_find;
-  GRegex *regex;
-
-  if (from == GST_GL_TEXTURE_TARGET_2D)
-    from_str = "sampler2D";
-  if (from == GST_GL_TEXTURE_TARGET_RECTANGLE)
-    from_str = "sampler2DRect";
-  if (from == GST_GL_TEXTURE_TARGET_EXTERNAL_OES)
-    from_str = "samplerExternalOES";
-
-  if (to == GST_GL_TEXTURE_TARGET_2D)
-    to_str = "sampler2D";
-  if (to == GST_GL_TEXTURE_TARGET_RECTANGLE)
-    to_str = "sampler2DRect";
-  if (to == GST_GL_TEXTURE_TARGET_EXTERNAL_OES)
-    to_str = "samplerExternalOES";
-
-  /* followed by some whitespace  */
-  regex_find = g_strdup_printf ("%s(?=\\s)", from_str);
-  regex = g_regex_new (regex_find, 0, 0, NULL);
-  tmp = g_regex_replace_literal (regex, str, -1, 0, to_str, 0, NULL);
-  g_free (regex_find);
-  g_regex_unref (regex);
-
-  if (tmp) {
-    ret = tmp;
-  } else {
-    GST_FIXME ("Couldn't mangle sampler type successfully from %s to %s",
-        from_str, to_str);
-    ret = g_strdup (str);
-  }
-
-  return ret;
-}
-
-static gchar *
-_mangle_varying_attribute (const gchar * str, guint shader_type,
-    GstGLSLVersion version, GstGLSLProfile profile)
-{
-  if (shader_type == GL_VERTEX_SHADER) {
-    if (profile == GST_GLSL_PROFILE_CORE || (profile == GST_GLSL_PROFILE_ES
-            && version >= GST_GLSL_VERSION_300)) {
-      gchar *tmp, *tmp2;
-      GRegex *regex;
-
-      /* followed by some whitespace  */
-      regex = g_regex_new ("varying(?=\\s)", 0, 0, NULL);
-      tmp = g_regex_replace_literal (regex, str, -1, 0, "out", 0, NULL);
-      g_regex_unref (regex);
-
-      /* followed by some whitespace  */
-      regex = g_regex_new ("attribute(?=\\s)", 0, 0, NULL);
-      tmp2 = g_regex_replace_literal (regex, tmp, -1, 0, "in", 0, NULL);
-      g_regex_unref (regex);
-
-      g_free (tmp);
-      return tmp2;
-    }
-  } else if (shader_type == GL_FRAGMENT_SHADER) {
-    if (profile == GST_GLSL_PROFILE_CORE || (profile == GST_GLSL_PROFILE_ES
-            && version >= GST_GLSL_VERSION_300)) {
-      gchar *tmp;
-      GRegex *regex;
-
-      /* followed by some whitespace  */
-      regex = g_regex_new ("varying(?=\\s)", 0, 0, NULL);
-      tmp = g_regex_replace_literal (regex, str, -1, 0, "in", 0, NULL);
-      g_regex_unref (regex);
-
-      return tmp;
-    }
-  }
-  return g_strdup (str);
-}
-
-static gchar *
-_mangle_frag_color_data (const gchar * str)
-{
-  GRegex *regex;
-  gchar *ret, *tmp;
-
-  regex = g_regex_new ("gl_FragColor", 0, 0, NULL);
-  ret = g_regex_replace_literal (regex, str, -1, 0, "fragColor", 0, NULL);
-  g_regex_unref (regex);
-
-  tmp = ret;
-  /* search and replace 'gl_FragData[NUM]' into fragColor_NUM */
-  regex = g_regex_new ("gl_FragData\\[(\\d+)\\]", 0, 0, NULL);
-  ret = g_regex_replace (regex, tmp, -1, 0, "fragColor_\\1", 0, NULL);
-  g_regex_unref (regex);
-  g_free (tmp);
-
-  return ret;
-}
-
-static void
-_mangle_version_profile_from_gl_api (GstGLAPI gl_api, gint gl_major,
-    gint gl_minor, GstGLSLVersion * version, GstGLSLProfile * profile)
-{
-  *version = GST_GLSL_VERSION_NONE;
-  *profile = GST_GLSL_PROFILE_NONE;
-
-  if (gl_api & GST_GL_API_OPENGL3) {
-    if (gl_major > 3 || gl_minor >= 3) {
-      *version = GST_GLSL_VERSION_330;
-      *profile = GST_GLSL_PROFILE_CORE;
-    } else {
-      *version = GST_GLSL_VERSION_150;
-      *profile = GST_GLSL_PROFILE_NONE;
-    }
-  } else if (gl_api & GST_GL_API_GLES2) {
-    if (gl_major >= 3) {
-      *version = GST_GLSL_VERSION_300;
-      *profile = GST_GLSL_PROFILE_ES;
-    } else if (gl_major >= 2) {
-      *version = GST_GLSL_VERSION_100;
-      *profile = GST_GLSL_PROFILE_ES;
-    }
-  } else if (gl_api & GST_GL_API_OPENGL) {
-    *version = GST_GLSL_VERSION_110;
-    *profile = GST_GLSL_PROFILE_COMPATIBILITY;
-  }
-}
-
-static gchar *
-_mangle_shader (const gchar * str, guint shader_type, GstGLTextureTarget from,
-    GstGLTextureTarget to, GstGLSLVersion version, GstGLSLProfile profile)
-{
-  gchar *tmp, *tmp2;
-
-  tmp2 = _mangle_sampler_type (str, from, to);
-  tmp = _mangle_texture_access (tmp2, from, to);
-  g_free (tmp2);
-  tmp2 = _mangle_varying_attribute (tmp, shader_type, version, profile);
-  g_free (tmp);
-  if (shader_type == GL_FRAGMENT_SHADER) {
-    if ((profile == GST_GLSL_PROFILE_ES && version >= GST_GLSL_VERSION_300)
-        || (profile == GST_GLSL_PROFILE_CORE
-            && version >= GST_GLSL_VERSION_150)) {
-      tmp = _mangle_frag_color_data (tmp2);
-      g_free (tmp2);
-      tmp2 = tmp;
-    }
-  }
-
-  return tmp2;
-}
-
 /* free after use */
 static gchar *
 _get_shader_string (GstGLViewConvert * viewconvert, GstGLShader * shader,
     GstVideoMultiviewMode in_mode, GstVideoMultiviewMode out_mode,
+    GstGLAPI gl_api, gint gl_major, gint gl_minor,
     GstGLSLVersion version, GstGLSLProfile profile)
 {
   const gchar *input_str, *output_str;
@@ -1747,14 +1553,29 @@ _get_shader_string (GstGLViewConvert * viewconvert, GstGLShader * shader,
     }
   }
 
-  g_string_append (str, "\nvoid main() {\nvec4 l, r;\n");
+  {
+    const gchar *varying = NULL;
+
+    if ((profile == GST_GLSL_PROFILE_ES && version >= GST_GLSL_VERSION_300)
+        || (profile == GST_GLSL_PROFILE_CORE
+            && version >= GST_GLSL_VERSION_150)) {
+      varying = "in";
+    } else {
+      varying = "varying";
+    }
+    g_string_append_printf (str,
+        "\n%s vec2 v_texcoord;\nvoid main() {\nvec4 l, r;\n", varying);
+  }
+
   g_string_append (str, input_str);
   g_string_append (str, output_str);
   g_string_append (str, "\n}");
   tmp = g_string_free (str, FALSE);
 
-  tmp2 = _mangle_shader (tmp, GL_FRAGMENT_SHADER, GST_GL_TEXTURE_TARGET_2D,
-      viewconvert->from_texture_target, version, profile);
+  tmp2 =
+      _gst_glsl_mangle_shader (tmp, GL_FRAGMENT_SHADER,
+      GST_GL_TEXTURE_TARGET_2D, viewconvert->from_texture_target, gl_api,
+      gl_major, gl_minor, &version, &profile);
 
   return tmp2;
 }
@@ -1912,23 +1733,24 @@ _init_view_convert (GstGLViewConvert * viewconvert)
     GstGLAPI gl_api;
     gint gl_major, gl_minor;
     GstGLSLStage *vert, *frag;
-    gchar *tmp, *version_str;
+    gchar *tmp, *tmp1, *version_str;
     const gchar *strings[2];
     GError *error = NULL;
 
     gl_api = gst_gl_context_get_gl_api (viewconvert->context);
     gst_gl_context_get_gl_version (viewconvert->context, &gl_major, &gl_minor);
-    _mangle_version_profile_from_gl_api (gl_api, gl_major, gl_minor, &version,
-        &profile);
 
-    tmp = gst_glsl_version_profile_to_string (version, profile);
-    version_str = g_strdup_printf ("#version %s\n", tmp);
-    g_free (tmp);
+    tmp =
+        _gst_glsl_mangle_shader
+        (gst_gl_shader_string_vertex_mat4_texture_transform, GL_VERTEX_SHADER,
+        GST_GL_TEXTURE_TARGET_2D, viewconvert->from_texture_target, gl_api,
+        gl_major, gl_minor, &version, &profile);
+
+    tmp1 = gst_glsl_version_profile_to_string (version, profile);
+    version_str = g_strdup_printf ("#version %s\n", tmp1);
+    g_free (tmp1);
     strings[0] = version_str;
 
-    tmp = _mangle_shader (gst_gl_shader_string_vertex_mat4_texture_transform,
-        GL_VERTEX_SHADER, GST_GL_TEXTURE_TARGET_2D,
-        viewconvert->from_texture_target, version, profile);
     strings[1] = tmp;
     vert =
         gst_glsl_stage_new_with_strings (viewconvert->context,
@@ -1945,7 +1767,7 @@ _init_view_convert (GstGLViewConvert * viewconvert)
     }
 
     fragment_source_str = _get_shader_string (viewconvert, viewconvert->shader,
-        in_mode, out_mode, version, profile);
+        in_mode, out_mode, gl_api, gl_major, gl_minor, version, profile);
     strings[1] = fragment_source_str;
 
     frag =