summaryrefslogtreecommitdiff
path: root/gst-libs/gst/gl/gstglshader.c
diff options
context:
space:
mode:
authorMatthew Waters <matthew@centricular.com>2015-05-12 22:04:26 +1000
committerMatthew Waters <matthew@centricular.com>2015-05-14 14:58:07 +1000
commite1b077d6aff3e431cc94bae22629070aa7047fdb (patch)
tree26ced13490de2e068ddd916ecc46e58dfc591ec5 /gst-libs/gst/gl/gstglshader.c
parent3d0bc93edca205419e8c50fff0ebefefbbfa1864 (diff)
downloadgstreamer-plugins-bad-e1b077d6aff3e431cc94bae22629070aa7047fdb.tar.gz
glshader: attempt to detect the gles2 inside opengl3 case
This is necessary to use gles2 shaders in a GL 3 core context on OS X which fails without a proper #version being set on the shaders.
Diffstat (limited to 'gst-libs/gst/gl/gstglshader.c')
-rw-r--r--gst-libs/gst/gl/gstglshader.c107
1 files changed, 103 insertions, 4 deletions
diff --git a/gst-libs/gst/gl/gstglshader.c b/gst-libs/gst/gl/gstglshader.c
index 8b06d6eb4..016e47517 100644
--- a/gst-libs/gst/gl/gstglshader.c
+++ b/gst-libs/gst/gl/gstglshader.c
@@ -26,6 +26,11 @@
#include "gl.h"
#include "gstglshader.h"
+/* FIXME: separate into separate shader stage objects that can be added/removed
+ * independently of the shader program */
+
+static const gchar *es2_version_header = "#version 100\n";
+
/* *INDENT-OFF* */
static const gchar *simple_vertex_shader_str_gles2 =
"attribute vec4 a_position;\n"
@@ -107,6 +112,8 @@ struct _GstGLShaderPrivate
gboolean compiled;
gboolean active;
+ GstGLAPI gl_api;
+
GstGLShaderVTable vtable;
};
@@ -324,6 +331,9 @@ gst_gl_shader_init (GstGLShader * self)
priv->compiled = FALSE;
priv->active = FALSE; /* unused at the moment */
+
+ /* FIXME: add API to get/set this for each shader */
+ priv->gl_api = GST_GL_API_ANY;
}
static gboolean
@@ -395,6 +405,80 @@ gst_gl_shader_is_compiled (GstGLShader * shader)
return shader->priv->compiled;
}
+static gboolean
+_shader_string_has_version (const gchar * str)
+{
+ gboolean sl_comment = FALSE;
+ gboolean ml_comment = FALSE;
+ gboolean has_version = FALSE;
+ gint i = 0;
+
+ /* search for #version to allow for preceeding comments as allowed by the
+ * GLSL specification */
+ while (str && str[i] != '\0' && i < 1024) {
+ if (sl_comment) {
+ if (str[i] != '\n')
+ sl_comment = FALSE;
+ i++;
+ continue;
+ }
+
+ if (ml_comment) {
+ if (g_strstr_len (&str[i], 2, "*/")) {
+ ml_comment = FALSE;
+ i += 2;
+ } else {
+ i++;
+ }
+ continue;
+ }
+
+ if (g_strstr_len (&str[i], 2, "//")) {
+ sl_comment = TRUE;
+ i += 2;
+ continue;
+ }
+
+ if (g_strstr_len (&str[i], 2, "/*")) {
+ ml_comment = TRUE;
+ i += 2;
+ continue;
+ }
+
+ if (g_strstr_len (&str[i], 1, "#")) {
+ if (g_strstr_len (&str[i], 8, "#version"))
+ has_version = TRUE;
+ break;
+ }
+
+ i++;
+ }
+
+ return has_version;
+}
+
+static void
+_maybe_prepend_version (GstGLShader * shader, const gchar * shader_str,
+ gint * n_vertex_sources, const gchar *** vertex_sources)
+{
+ gint n = 1;
+
+ /* FIXME: this all an educated guess */
+ if (gst_gl_context_check_gl_version (shader->context, GST_GL_API_OPENGL3, 3,
+ 0)
+ && (shader->priv->gl_api & GST_GL_API_GLES2) != 0
+ && !_shader_string_has_version (shader_str))
+ n = 2;
+
+ *vertex_sources = g_malloc0 (n * sizeof (gchar *));
+
+ if (n > 1)
+ *vertex_sources[0] = es2_version_header;
+
+ (*vertex_sources)[n - 1] = shader_str;
+ *n_vertex_sources = n;
+}
+
gboolean
gst_gl_shader_compile (GstGLShader * shader, GError ** error)
{
@@ -423,10 +507,18 @@ gst_gl_shader_compile (GstGLShader * shader, GError ** error)
g_return_val_if_fail (priv->program_handle, FALSE);
if (priv->vertex_src) {
+ gint n_vertex_sources;
+ const gchar **vertex_sources;
+
+ _maybe_prepend_version (shader, priv->vertex_src, &n_vertex_sources,
+ &vertex_sources);
+
/* create vertex object */
- const gchar *vertex_source = priv->vertex_src;
priv->vertex_handle = priv->vtable.CreateShader (GL_VERTEX_SHADER);
- gl->ShaderSource (priv->vertex_handle, 1, &vertex_source, NULL);
+ gl->ShaderSource (priv->vertex_handle, n_vertex_sources, vertex_sources,
+ NULL);
+ g_free (vertex_sources);
+
/* compile */
gl->CompileShader (priv->vertex_handle);
/* check everything is ok */
@@ -455,10 +547,17 @@ gst_gl_shader_compile (GstGLShader * shader, GError ** error)
}
if (priv->fragment_src) {
+ gint n_fragment_sources;
+ const gchar **fragment_sources;
+
+ _maybe_prepend_version (shader, priv->fragment_src, &n_fragment_sources,
+ &fragment_sources);
+
/* create fragment object */
- const gchar *fragment_source = priv->fragment_src;
priv->fragment_handle = priv->vtable.CreateShader (GL_FRAGMENT_SHADER);
- gl->ShaderSource (priv->fragment_handle, 1, &fragment_source, NULL);
+ gl->ShaderSource (priv->fragment_handle, n_fragment_sources,
+ fragment_sources, NULL);
+ g_free (fragment_sources);
/* compile */
gl->CompileShader (priv->fragment_handle);
/* check everything is ok */