mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 20:21:24 +00:00
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.
This commit is contained in:
parent
2b4ce9435d
commit
675f789871
1 changed files with 103 additions and 4 deletions
|
@ -26,6 +26,11 @@
|
||||||
#include "gl.h"
|
#include "gl.h"
|
||||||
#include "gstglshader.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* */
|
/* *INDENT-OFF* */
|
||||||
static const gchar *simple_vertex_shader_str_gles2 =
|
static const gchar *simple_vertex_shader_str_gles2 =
|
||||||
"attribute vec4 a_position;\n"
|
"attribute vec4 a_position;\n"
|
||||||
|
@ -107,6 +112,8 @@ struct _GstGLShaderPrivate
|
||||||
gboolean compiled;
|
gboolean compiled;
|
||||||
gboolean active;
|
gboolean active;
|
||||||
|
|
||||||
|
GstGLAPI gl_api;
|
||||||
|
|
||||||
GstGLShaderVTable vtable;
|
GstGLShaderVTable vtable;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -324,6 +331,9 @@ gst_gl_shader_init (GstGLShader * self)
|
||||||
|
|
||||||
priv->compiled = FALSE;
|
priv->compiled = FALSE;
|
||||||
priv->active = FALSE; /* unused at the moment */
|
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
|
static gboolean
|
||||||
|
@ -395,6 +405,80 @@ gst_gl_shader_is_compiled (GstGLShader * shader)
|
||||||
return shader->priv->compiled;
|
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
|
gboolean
|
||||||
gst_gl_shader_compile (GstGLShader * shader, GError ** error)
|
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);
|
g_return_val_if_fail (priv->program_handle, FALSE);
|
||||||
|
|
||||||
if (priv->vertex_src) {
|
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 */
|
/* create vertex object */
|
||||||
const gchar *vertex_source = priv->vertex_src;
|
|
||||||
priv->vertex_handle = priv->vtable.CreateShader (GL_VERTEX_SHADER);
|
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 */
|
/* compile */
|
||||||
gl->CompileShader (priv->vertex_handle);
|
gl->CompileShader (priv->vertex_handle);
|
||||||
/* check everything is ok */
|
/* check everything is ok */
|
||||||
|
@ -455,10 +547,17 @@ gst_gl_shader_compile (GstGLShader * shader, GError ** error)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (priv->fragment_src) {
|
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 */
|
/* create fragment object */
|
||||||
const gchar *fragment_source = priv->fragment_src;
|
|
||||||
priv->fragment_handle = priv->vtable.CreateShader (GL_FRAGMENT_SHADER);
|
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 */
|
/* compile */
|
||||||
gl->CompileShader (priv->fragment_handle);
|
gl->CompileShader (priv->fragment_handle);
|
||||||
/* check everything is ok */
|
/* check everything is ok */
|
||||||
|
|
Loading…
Reference in a new issue