gl: add some GLSL utility functions

Specifically parsing/setting GLSL versions and the shader related
function table.
This commit is contained in:
Matthew Waters 2015-08-20 15:11:06 +10:00 committed by Tim-Philipp Müller
parent 01e1046dbc
commit 332543f3cf
5 changed files with 1012 additions and 0 deletions

View file

@ -18,6 +18,7 @@ libgstgl_@GST_API_VERSION@_la_SOURCES = \
gstglfilter.c \
gstglbasefilter.c \
gstglshader.c \
gstglsl.c \
gstglshadervariables.c \
gstglcolorconvert.c \
gstgldownload.c \
@ -31,6 +32,7 @@ libgstgl_@GST_API_VERSION@_la_SOURCES = \
gstglsyncmeta.c \
gstglviewconvert.c \
gstgloverlaycompositor.c \
gstglsl_private.h \
utils/opengl_versions.h
libgstgl_@GST_API_VERSION@includedir = $(includedir)/gstreamer-@GST_API_VERSION@/gst/gl
@ -46,6 +48,7 @@ libgstgl_@GST_API_VERSION@include_HEADERS = \
gstglbasefilter.h \
gstglshadervariables.h \
gstglshader.h \
gstglsl.h \
gstglcolorconvert.h \
gstgldownload.h \
gstgluploadmeta.h \

543
gst-libs/gst/gl/gstglsl.c Normal file
View file

@ -0,0 +1,543 @@
/*
* GStreamer
* Copyright (C) 2015 Matthew Waters <matthew@centricular.com>
*
* 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., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <gst/gl/gl.h>
#include "gstglsl.h"
#include "gstglsl_private.h"
GQuark
gst_glsl_error_quark (void)
{
return g_quark_from_static_string ("gst-glsl-error");
}
struct glsl_version_string
{
GstGLSLVersion version;
const gchar *name;
};
static const struct glsl_version_string glsl_versions[] = {
/* keep in sync with definition in the header */
{GST_GLSL_VERSION_100, "100"},
{GST_GLSL_VERSION_110, "110"},
{GST_GLSL_VERSION_120, "120"},
{GST_GLSL_VERSION_130, "130"},
{GST_GLSL_VERSION_140, "140"},
{GST_GLSL_VERSION_150, "150"},
{GST_GLSL_VERSION_300, "300"},
{GST_GLSL_VERSION_310, "310"},
{GST_GLSL_VERSION_320, "320"},
{GST_GLSL_VERSION_330, "330"},
{GST_GLSL_VERSION_400, "400"},
{GST_GLSL_VERSION_410, "410"},
{GST_GLSL_VERSION_420, "420"},
{GST_GLSL_VERSION_430, "430"},
{GST_GLSL_VERSION_440, "440"},
{GST_GLSL_VERSION_450, "450"},
};
struct glsl_profile_string
{
GstGLSLProfile profile;
const gchar *name;
};
static const struct glsl_profile_string glsl_profiles[] = {
/* keep in sync with definition in the header */
{GST_GLSL_PROFILE_ES, "es"},
{GST_GLSL_PROFILE_CORE, "core"},
{GST_GLSL_PROFILE_COMPATIBILITY, "compatibility"},
};
const gchar *
gst_glsl_version_to_string (GstGLSLVersion version)
{
int i;
if (version == GST_GLSL_VERSION_NONE)
return NULL;
for (i = 0; i < G_N_ELEMENTS (glsl_versions); i++) {
if (version == glsl_versions[i].version)
return glsl_versions[i].name;
}
return NULL;
}
GstGLSLVersion
gst_glsl_version_from_string (const gchar * string)
{
gchar *str;
int i;
if (string == NULL)
return 0;
str = g_strdup (string);
str = g_strstrip (str);
for (i = 0; i < G_N_ELEMENTS (glsl_versions); i++) {
if (g_strcmp0 (str, glsl_versions[i].name) == 0) {
g_free (str);
return glsl_versions[i].version;
}
}
g_free (str);
return 0;
}
const gchar *
gst_glsl_profile_to_string (GstGLSLProfile profile)
{
int i;
if (profile == GST_GLSL_PROFILE_NONE)
return NULL;
/* multiple profiles are not allowed */
if ((profile & (profile - 1)) != 0)
return NULL;
for (i = 0; i < G_N_ELEMENTS (glsl_profiles); i++) {
if (profile == glsl_profiles[i].profile)
return glsl_profiles[i].name;
}
return NULL;
}
GstGLSLProfile
gst_glsl_profile_from_string (const gchar * string)
{
gchar *str;
int i;
if (string == NULL)
return GST_GLSL_PROFILE_NONE;
str = g_strdup (string);
str = g_strstrip (str);
for (i = 0; i < G_N_ELEMENTS (glsl_profiles); i++) {
if (g_strcmp0 (str, glsl_profiles[i].name) == 0) {
g_free (str);
return glsl_profiles[i].profile;
}
}
g_free (str);
return GST_GLSL_PROFILE_NONE;
}
static gboolean
_is_valid_version_profile (GstGLSLVersion version, GstGLSLProfile profile)
{
if (version == GST_GLSL_VERSION_NONE)
return TRUE;
/* versions that may not need an explicit profile */
if (version <= GST_GLSL_VERSION_150 && profile == GST_GLSL_PROFILE_NONE)
return TRUE;
/* ES versions require an ES profile */
if (version == GST_GLSL_VERSION_100 || version == GST_GLSL_VERSION_300
|| version == GST_GLSL_VERSION_310 || version == GST_GLSL_VERSION_320)
return profile == GST_GLSL_PROFILE_ES;
/* required profile and no ES profile for normal GL contexts */
if (version >= GST_GLSL_VERSION_330)
return profile == GST_GLSL_PROFILE_NONE || profile == GST_GLSL_PROFILE_CORE
|| profile == GST_GLSL_PROFILE_COMPATIBILITY;
if (version <= GST_GLSL_VERSION_150)
return profile == GST_GLSL_PROFILE_NONE
|| profile == GST_GLSL_PROFILE_COMPATIBILITY;
return FALSE;
}
gchar *
gst_glsl_version_profile_to_string (GstGLSLVersion version,
GstGLSLProfile profile)
{
const gchar *version_s, *profile_s;
if (!_is_valid_version_profile (version, profile))
return NULL;
version_s = gst_glsl_version_to_string (version);
/* no profiles in GL/ES <= 150 */
if (version <= GST_GLSL_VERSION_150)
profile_s = NULL;
else
profile_s = gst_glsl_profile_to_string (profile);
if (!version_s)
return NULL;
if (profile_s)
return g_strdup_printf ("%s %s", version_s, profile_s);
return g_strdup (version_s);
}
static void
_fixup_version_profile (GstGLSLVersion * version, GstGLSLProfile * profile)
{
if (*version == GST_GLSL_VERSION_100 || *version == GST_GLSL_VERSION_300
|| *version == GST_GLSL_VERSION_310 || *version == GST_GLSL_VERSION_320)
*profile = GST_GLSL_PROFILE_ES;
else if (*version <= GST_GLSL_VERSION_150)
*profile = GST_GLSL_PROFILE_COMPATIBILITY;
else if (*profile == GST_GLSL_PROFILE_NONE
&& *version >= GST_GLSL_VERSION_330)
*profile = GST_GLSL_PROFILE_CORE;
}
/* @str points to the start of "#version", "# version" or "#\tversion", etc */
static const gchar *
_check_valid_version_preprocessor_string (const gchar * str)
{
gint i = 0;
if (!str || !str[i])
return NULL;
/* there can be whitespace between the '#' and 'version' */
do {
i++;
if (str[i] == '\0' || str[i] == '\n' || str[i] == '\r')
return NULL;
} while (g_ascii_isspace (str[i]));
if (g_strstr_len (&str[i], 7, "version"))
return &str[i + 7];
return NULL;
}
gboolean
gst_glsl_version_profile_from_string (const gchar * string,
GstGLSLVersion * version_ret, GstGLSLProfile * profile_ret)
{
gchar *str, *version_s, *profile_s;
GstGLSLVersion version;
GstGLSLProfile profile;
gint i;
if (!string)
goto error;
str = g_strdup (string);
version_s = g_strstrip (str);
/* skip possible #version prefix */
if (str[0] == '#') {
if (!(version_s =
(gchar *) _check_valid_version_preprocessor_string (version_s)))
goto error;
}
version_s = g_strstrip (version_s);
i = 0;
while (version_s && version_s[i] != '\0' && g_ascii_isdigit (version_s[i]))
i++;
/* wrong version length */
if (i != 3) {
g_free (str);
goto error;
}
version_s[i] = '\0';
i++;
profile_s = &version_s[i];
profile_s = g_strstrip (profile_s);
profile = gst_glsl_profile_from_string (profile_s);
version = gst_glsl_version_from_string (version_s);
g_free (str);
/* check whether the parsed data is valid */
if (!version)
goto error;
if (!_is_valid_version_profile (version, profile))
goto error;
/* got a profile when none was expected */
if (version <= GST_GLSL_VERSION_150 && profile != GST_GLSL_PROFILE_NONE)
goto error;
_fixup_version_profile (&version, &profile);
if (profile_ret)
*profile_ret = profile;
if (version_ret)
*version_ret = version;
return TRUE;
error:
{
if (profile_ret)
*profile_ret = GST_GLSL_PROFILE_NONE;
if (version_ret)
*version_ret = GST_GLSL_VERSION_NONE;
return FALSE;
}
}
/* returns the pointer in @str to the #version declaration */
const gchar *
_gst_glsl_shader_string_find_version (const gchar * str)
{
gboolean sl_comment = FALSE;
gboolean ml_comment = FALSE;
gboolean newline = TRUE;
gint i = 0;
/* search for #version while allowing for preceeding comments/whitespace as
* permitted by the GLSL specification */
while (str && str[i] != '\0' && i < 1024) {
if (str[i] == '\n' || str[i] == '\r') {
newline = TRUE;
sl_comment = FALSE;
i++;
continue;
}
if (g_ascii_isspace (str[i]))
goto next;
if (sl_comment)
goto next;
if (ml_comment) {
if (g_strstr_len (&str[i], 2, "*/")) {
ml_comment = FALSE;
i++;
}
goto next;
}
if (g_strstr_len (&str[i], 2, "//")) {
sl_comment = TRUE;
i++;
goto next;
}
if (g_strstr_len (&str[i], 2, "/*")) {
ml_comment = TRUE;
i++;
goto next;
}
if (str[i] == '#') {
if (newline && _check_valid_version_preprocessor_string (&str[i]))
return &str[i];
break;
}
next:
newline = FALSE;
i++;
}
return NULL;
}
gboolean
gst_glsl_string_get_version_profile (const gchar * s, GstGLSLVersion * version,
GstGLSLProfile * profile)
{
const gchar *version_profile_s;
version_profile_s = _gst_glsl_shader_string_find_version (s);
if (!version_profile_s)
goto error;
if (!gst_glsl_version_profile_from_string (version_profile_s, version,
profile))
goto error;
return TRUE;
error:
{
if (version)
*version = GST_GLSL_VERSION_NONE;
if (profile)
*profile = GST_GLSL_PROFILE_NONE;
return FALSE;
}
}
GstGLSLVersion
gst_gl_version_to_glsl_version (GstGLAPI gl_api, gint maj, gint min)
{
g_return_val_if_fail (gl_api != GST_GL_API_NONE, 0);
if (gl_api & GST_GL_API_GLES2) {
if (maj == 2 && min == 0)
return 100;
if (maj == 3 && min >= 0 && min <= 2)
return maj * 100 + min * 10;
return 0;
}
/* versions match for >= 3.3 */
if (gl_api & (GST_GL_API_OPENGL3 | GST_GL_API_OPENGL)) {
if (maj > 3 || (maj == 3 && min >= 3))
return maj * 100 + min * 10;
if (maj == 3 && min == 2)
return 150;
if (maj == 3 && min == 1)
return 140;
if (maj == 3 && min == 0)
return 130;
if (maj == 2 && min == 1)
return 120;
if (maj == 2 && min == 0)
return 110;
return 0;
}
return 0;
}
gboolean
gst_gl_context_supports_glsl_profile_version (GstGLContext * context,
GstGLSLVersion version, GstGLSLProfile profile)
{
g_return_val_if_fail (GST_GL_IS_CONTEXT (context), FALSE);
if (!_is_valid_version_profile (version, profile))
return FALSE;
if (profile != GST_GLSL_PROFILE_NONE) {
if (gst_gl_context_check_gl_version (context, GST_GL_API_GLES2, 2, 0)) {
if ((profile & GST_GLSL_PROFILE_ES) == 0)
return FALSE;
} else if ((gst_gl_context_get_gl_api (context) & GST_GL_API_OPENGL) != 0) {
if ((profile & GST_GLSL_PROFILE_COMPATIBILITY) == 0)
return FALSE;
} else if ((gst_gl_context_get_gl_api (context) & GST_GL_API_OPENGL3) != 0) {
/* GL_ARB_es2_compatibility is requried for GL3 contexts */
if ((profile & (GST_GLSL_PROFILE_CORE | GST_GLSL_PROFILE_ES)) == 0)
return FALSE;
} else {
g_assert_not_reached ();
}
}
if (version != GST_GLSL_VERSION_NONE) {
GstGLAPI gl_api;
gint maj, min, glsl_version;
if (gst_gl_context_check_gl_version (context, GST_GL_API_GLES2, 3, 1)) {
if (version > GST_GLSL_VERSION_310)
return FALSE;
} else if (gst_gl_context_check_gl_version (context, GST_GL_API_GLES2, 3,
0)) {
if (version > GST_GLSL_VERSION_300)
return FALSE;
} else if (gst_gl_context_check_gl_version (context, GST_GL_API_GLES2, 2,
0)) {
if (version > GST_GLSL_VERSION_100)
return FALSE;
}
gl_api = gst_gl_context_get_gl_api (context);
gst_gl_context_get_gl_version (context, &maj, &min);
glsl_version = gst_gl_version_to_glsl_version (gl_api, maj, min);
if (glsl_version > version)
return FALSE;
if (gst_gl_context_check_gl_version (context, GST_GL_API_OPENGL3, 1, 0))
/* GL_ARB_es2_compatibility is requried for GL3 contexts */
if (version < GST_GLSL_VERSION_150 && version != GST_GLSL_VERSION_100)
return FALSE;
if (gst_gl_context_check_gl_version (context, GST_GL_API_OPENGL, 1, 0)
&& version < GST_GLSL_VERSION_110)
return FALSE;
}
return TRUE;
}
gboolean
_gst_glsl_funcs_fill (GstGLSLFuncs * vtable, GstGLContext * context)
{
GstGLFuncs *gl = context->gl_vtable;
if (vtable->initialized)
return TRUE;
if (gl->CreateProgram) {
vtable->CreateProgram = gl->CreateProgram;
vtable->DeleteProgram = gl->DeleteProgram;
vtable->UseProgram = gl->UseProgram;
vtable->CreateShader = gl->CreateShader;
vtable->DeleteShader = gl->DeleteShader;
vtable->AttachShader = gl->AttachShader;
vtable->DetachShader = gl->DetachShader;
vtable->GetAttachedShaders = gl->GetAttachedShaders;
vtable->GetShaderInfoLog = gl->GetShaderInfoLog;
vtable->GetShaderiv = gl->GetShaderiv;
vtable->GetProgramInfoLog = gl->GetProgramInfoLog;
vtable->GetProgramiv = gl->GetProgramiv;
} else if (gl->CreateProgramObject) {
vtable->CreateProgram = gl->CreateProgramObject;
vtable->DeleteProgram = gl->DeleteObject;
vtable->UseProgram = gl->UseProgramObject;
vtable->CreateShader = gl->CreateShaderObject;
vtable->DeleteShader = gl->DeleteObject;
vtable->AttachShader = gl->AttachObject;
vtable->DetachShader = gl->DetachObject;
vtable->GetAttachedShaders = gl->GetAttachedObjects;
vtable->GetShaderInfoLog = gl->GetInfoLog;
vtable->GetShaderiv = gl->GetObjectParameteriv;
vtable->GetProgramInfoLog = gl->GetInfoLog;
vtable->GetProgramiv = gl->GetObjectParameteriv;
} else {
vtable->initialized = FALSE;
return FALSE;
}
vtable->initialized = TRUE;
return TRUE;
}

96
gst-libs/gst/gl/gstglsl.h Normal file
View file

@ -0,0 +1,96 @@
/*
* GStreamer
* Copyright (C) 2015 Matthew Waters <matthew@centricular.com>
*
* 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., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef __GST_GLSL_H__
#define __GST_GLSL_H__
#include <gst/gl/gstgl_fwd.h>
G_BEGIN_DECLS
GQuark gst_glsl_error_quark (void);
#define GST_GLSL_ERROR (gst_glsl_error_quark ())
typedef enum {
GST_GLSL_ERROR_COMPILE,
GST_GLSL_ERROR_LINK,
GST_GLSL_ERROR_PROGRAM,
} GstGLSLError;
typedef enum
{
GST_GLSL_VERSION_NONE = 0,
GST_GLSL_VERSION_100 = 100, /* ES */
GST_GLSL_VERSION_110 = 110, /* GL */
GST_GLSL_VERSION_120 = 120, /* GL */
GST_GLSL_VERSION_130 = 130, /* GL */
GST_GLSL_VERSION_140 = 140, /* GL */
GST_GLSL_VERSION_150 = 150, /* GL */
GST_GLSL_VERSION_300 = 300, /* ES */
GST_GLSL_VERSION_310 = 310, /* ES */
GST_GLSL_VERSION_320 = 320, /* ES */
GST_GLSL_VERSION_330 = 330, /* GL */
GST_GLSL_VERSION_400 = 400, /* GL */
GST_GLSL_VERSION_410 = 410, /* GL */
GST_GLSL_VERSION_420 = 420, /* GL */
GST_GLSL_VERSION_430 = 430, /* GL */
GST_GLSL_VERSION_440 = 440, /* GL */
GST_GLSL_VERSION_450 = 450, /* GL */
GST_GLSL_VERSION_ANY = -1,
} GstGLSLVersion;
typedef enum
{
/* XXX: maybe make GstGLAPI instead */
GST_GLSL_PROFILE_NONE = 0,
GST_GLSL_PROFILE_ES = (1 << 0),
GST_GLSL_PROFILE_CORE = (1 << 1),
GST_GLSL_PROFILE_COMPATIBILITY = (1 << 2),
GST_GLSL_PROFILE_ANY = -1,
} GstGLSLProfile;
GstGLSLVersion gst_glsl_version_from_string (const gchar * string);
const gchar * gst_glsl_version_to_string (GstGLSLVersion version);
GstGLSLProfile gst_glsl_profile_from_string (const gchar * string);
const gchar * gst_glsl_profile_to_string (GstGLSLProfile profile);
gchar * gst_glsl_version_profile_to_string (GstGLSLVersion version,
GstGLSLProfile profile);
gboolean gst_glsl_version_profile_from_string (const gchar * string,
GstGLSLVersion * version,
GstGLSLProfile * profile);
gboolean gst_glsl_string_get_version_profile (const gchar *s,
GstGLSLVersion * version,
GstGLSLProfile * profile);
GstGLSLVersion gst_gl_version_to_glsl_version (GstGLAPI gl_api, gint maj, gint min);
gboolean gst_gl_context_supports_glsl_profile_version (GstGLContext * context,
GstGLSLVersion version,
GstGLSLProfile profile);
G_END_DECLS
#endif /* __GST_GLSL_H__ */

View file

@ -0,0 +1,63 @@
/*
* GStreamer
* Copyright (C) 2015 Matthew Waters <matthew@centricular.com>
*
* 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., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef __GST_GLSL_PRIVATE_H__
#define __GST_GLSL_PRIVATE_H__
#include <gst/gl/gstgl_fwd.h>
G_BEGIN_DECLS
#ifndef GL_COMPILE_STATUS
#define GL_COMPILE_STATUS 0x8B81
#endif
#ifndef GLhandleARB
#define GLhandleARB GLuint
#endif
typedef struct _GstGLSLFuncs
{
gboolean initialized;
GLuint GSTGLAPI (*CreateProgram) (void);
void GSTGLAPI (*DeleteProgram) (GLuint program);
void GSTGLAPI (*UseProgram) (GLuint program);
void GSTGLAPI (*GetAttachedShaders) (GLuint program, GLsizei maxcount,
GLsizei * count, GLuint * shaders);
GLuint GSTGLAPI (*CreateShader) (GLenum shaderType);
void GSTGLAPI (*DeleteShader) (GLuint shader);
void GSTGLAPI (*AttachShader) (GLuint program, GLuint shader);
void GSTGLAPI (*DetachShader) (GLuint program, GLuint shader);
void GSTGLAPI (*GetShaderiv) (GLuint program, GLenum pname, GLint * params);
void GSTGLAPI (*GetProgramiv) (GLuint program, GLenum pname, GLint * params);
void GSTGLAPI (*GetShaderInfoLog) (GLuint shader, GLsizei maxLength,
GLsizei * length, char *log);
void GSTGLAPI (*GetProgramInfoLog) (GLuint shader, GLsizei maxLength,
GLsizei * length, char *log);
} GstGLSLFuncs;
gboolean _gst_glsl_funcs_fill (GstGLSLFuncs * vtable, GstGLContext * context);
const gchar * _gst_glsl_shader_string_find_version (const gchar * str);
G_END_DECLS
#endif /* __GST_GLSL_PRIVATE_H__ */

307
tests/check/libs/gstglsl.c Normal file
View file

@ -0,0 +1,307 @@
/* GStreamer
* Copyright (C) 2015 Matthew Waters <matthew@centricular.com>
*
* 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., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <gst/check/gstcheck.h>
#include <gst/gl/gstglsl.h>
#include <stdio.h>
static void
setup (void)
{
}
static void
teardown (void)
{
}
/* *INDENT-OFF* */
static const struct {GstGLSLVersion version; const gchar * name;} glsl_versions[] = {
{GST_GLSL_VERSION_100, "100"},
{GST_GLSL_VERSION_110, "110"},
{GST_GLSL_VERSION_120, "120"},
{GST_GLSL_VERSION_130, "130"},
{GST_GLSL_VERSION_140, "140"},
{GST_GLSL_VERSION_150, "150"},
{GST_GLSL_VERSION_300, "300"},
{GST_GLSL_VERSION_310, "310"},
{GST_GLSL_VERSION_320, "320"},
{GST_GLSL_VERSION_330, "330"},
{GST_GLSL_VERSION_400, "400"},
{GST_GLSL_VERSION_410, "410"},
{GST_GLSL_VERSION_420, "420"},
{GST_GLSL_VERSION_430, "430"},
{GST_GLSL_VERSION_440, "440"},
{GST_GLSL_VERSION_450, "450"},
};
static const struct {GstGLSLProfile profile; const gchar * name;} glsl_profiles[] = {
{GST_GLSL_PROFILE_ES, "es"},
{GST_GLSL_PROFILE_CORE, "core"},
{GST_GLSL_PROFILE_COMPATIBILITY, "compatibility"},
};
static const struct {GstGLSLVersion version; GstGLSLProfile profile; const gchar * name;} glsl_version_profiles[] = {
{GST_GLSL_VERSION_100, GST_GLSL_PROFILE_ES, "100"},
{GST_GLSL_VERSION_110, GST_GLSL_PROFILE_COMPATIBILITY, "110"},
{GST_GLSL_VERSION_120, GST_GLSL_PROFILE_COMPATIBILITY, "120"},
{GST_GLSL_VERSION_130, GST_GLSL_PROFILE_COMPATIBILITY, "130"},
{GST_GLSL_VERSION_140, GST_GLSL_PROFILE_COMPATIBILITY, "140"},
{GST_GLSL_VERSION_150, GST_GLSL_PROFILE_COMPATIBILITY, "150"},
{GST_GLSL_VERSION_300, GST_GLSL_PROFILE_ES, "300 es"},
{GST_GLSL_VERSION_310, GST_GLSL_PROFILE_ES, "310 es"},
{GST_GLSL_VERSION_320, GST_GLSL_PROFILE_ES, "320 es"},
{GST_GLSL_VERSION_330, GST_GLSL_PROFILE_CORE, "330 core"},
{GST_GLSL_VERSION_330, GST_GLSL_PROFILE_COMPATIBILITY, "330 compatibility"},
{GST_GLSL_VERSION_400, GST_GLSL_PROFILE_CORE, "400 core"},
{GST_GLSL_VERSION_400, GST_GLSL_PROFILE_COMPATIBILITY, "400 compatibility"},
{GST_GLSL_VERSION_410, GST_GLSL_PROFILE_CORE, "410 core"},
{GST_GLSL_VERSION_410, GST_GLSL_PROFILE_COMPATIBILITY, "410 compatibility"},
{GST_GLSL_VERSION_420, GST_GLSL_PROFILE_CORE, "420 core"},
{GST_GLSL_VERSION_420, GST_GLSL_PROFILE_COMPATIBILITY, "420 compatibility"},
{GST_GLSL_VERSION_430, GST_GLSL_PROFILE_CORE, "430 core"},
{GST_GLSL_VERSION_430, GST_GLSL_PROFILE_COMPATIBILITY, "430 compatibility"},
{GST_GLSL_VERSION_440, GST_GLSL_PROFILE_CORE, "440 core"},
{GST_GLSL_VERSION_440, GST_GLSL_PROFILE_COMPATIBILITY, "440 compatibility"},
{GST_GLSL_VERSION_450, GST_GLSL_PROFILE_CORE, "450 core"},
{GST_GLSL_VERSION_450, GST_GLSL_PROFILE_COMPATIBILITY, "450 compatibility"},
};
static const gchar * invalid_deserialize_glsl[] = {
"",
" \t\r\n",
"ael dja",
"es",
"core",
"compatibility",
"1000",
"100 es",
"100 core",
"100 compatibility",
"150 es",
"150 core",
"150 compatibility",
"300 core",
"300 compatibility",
"310 core",
"310 compatibility",
"320 core",
"320 compatibility",
"330 es",
};
static const struct {GstGLSLVersion version; GstGLSLProfile profile;} invalid_serialize_glsl[] = {
{GST_GLSL_VERSION_100, GST_GLSL_PROFILE_CORE},
{GST_GLSL_VERSION_100, GST_GLSL_PROFILE_COMPATIBILITY},
{GST_GLSL_VERSION_110, GST_GLSL_PROFILE_ES},
{GST_GLSL_VERSION_110, GST_GLSL_PROFILE_CORE},
{GST_GLSL_VERSION_120, GST_GLSL_PROFILE_ES},
{GST_GLSL_VERSION_120, GST_GLSL_PROFILE_CORE},
{GST_GLSL_VERSION_130, GST_GLSL_PROFILE_ES},
{GST_GLSL_VERSION_130, GST_GLSL_PROFILE_CORE},
{GST_GLSL_VERSION_140, GST_GLSL_PROFILE_ES},
{GST_GLSL_VERSION_140, GST_GLSL_PROFILE_CORE},
{GST_GLSL_VERSION_150, GST_GLSL_PROFILE_ES},
{GST_GLSL_VERSION_150, GST_GLSL_PROFILE_CORE},
{GST_GLSL_VERSION_300, GST_GLSL_PROFILE_NONE},
{GST_GLSL_VERSION_300, GST_GLSL_PROFILE_CORE},
{GST_GLSL_VERSION_300, GST_GLSL_PROFILE_COMPATIBILITY},
{GST_GLSL_VERSION_310, GST_GLSL_PROFILE_NONE},
{GST_GLSL_VERSION_310, GST_GLSL_PROFILE_CORE},
{GST_GLSL_VERSION_310, GST_GLSL_PROFILE_COMPATIBILITY},
{GST_GLSL_VERSION_320, GST_GLSL_PROFILE_NONE},
{GST_GLSL_VERSION_320, GST_GLSL_PROFILE_CORE},
{GST_GLSL_VERSION_320, GST_GLSL_PROFILE_COMPATIBILITY},
{GST_GLSL_VERSION_330, GST_GLSL_PROFILE_ES},
{GST_GLSL_VERSION_400, GST_GLSL_PROFILE_ES},
{GST_GLSL_VERSION_410, GST_GLSL_PROFILE_ES},
{GST_GLSL_VERSION_420, GST_GLSL_PROFILE_ES},
{GST_GLSL_VERSION_430, GST_GLSL_PROFILE_ES},
{GST_GLSL_VERSION_440, GST_GLSL_PROFILE_ES},
{GST_GLSL_VERSION_450, GST_GLSL_PROFILE_ES},
};
static const struct {const gchar *name; gboolean succeed; GstGLSLVersion version; GstGLSLProfile profile;} glsl_str_map[] = {
{"//#version 100\n", FALSE, GST_GLSL_VERSION_NONE, GST_GLSL_PROFILE_NONE},
{"/*\n#version 100*/\n", FALSE, GST_GLSL_VERSION_NONE, GST_GLSL_PROFILE_NONE},
{"/*\r#version 100*/", FALSE, GST_GLSL_VERSION_NONE, GST_GLSL_PROFILE_NONE},
{"#\rversion 100", FALSE, GST_GLSL_VERSION_NONE, GST_GLSL_PROFILE_NONE},
{"#\nversion 100", FALSE, GST_GLSL_VERSION_NONE, GST_GLSL_PROFILE_NONE},
{"\t#version 100", FALSE, GST_GLSL_VERSION_NONE, GST_GLSL_PROFILE_NONE},
{"//\r#version 100", TRUE, GST_GLSL_VERSION_100, GST_GLSL_PROFILE_ES},
{"//\n#version 100", TRUE, GST_GLSL_VERSION_100, GST_GLSL_PROFILE_ES},
{"# \tversion 100", TRUE, GST_GLSL_VERSION_100, GST_GLSL_PROFILE_ES},
{"\n#version 100", TRUE, GST_GLSL_VERSION_100, GST_GLSL_PROFILE_ES},
{"\r#version 100", TRUE, GST_GLSL_VERSION_100, GST_GLSL_PROFILE_ES},
};
/* *INDENT-ON* */
GST_START_TEST (test_serialization)
{
gint i;
/* versions */
for (i = 0; i < G_N_ELEMENTS (glsl_versions); i++) {
GstGLSLVersion version;
const gchar *version_s;
version_s = gst_glsl_version_to_string (glsl_versions[i].version);
fail_unless (g_strcmp0 (version_s, glsl_versions[i].name) == 0, "%s != %s",
version_s, glsl_versions[i].name);
version = gst_glsl_version_from_string (glsl_versions[i].name);
fail_unless (version == glsl_versions[i].version, "%s != %s",
gst_glsl_version_to_string (glsl_versions[i].version),
gst_glsl_version_to_string (version));
}
/* profiles */
for (i = 0; i < G_N_ELEMENTS (glsl_profiles); i++) {
GstGLSLProfile profile;
const gchar *profile_s;
profile_s = gst_glsl_profile_to_string (glsl_profiles[i].profile);
fail_unless (g_strcmp0 (profile_s, glsl_profiles[i].name) == 0, "%s != %s",
profile_s, glsl_profiles[i].name);
profile = gst_glsl_profile_from_string (glsl_profiles[i].name);
fail_unless (profile == glsl_profiles[i].profile, "%s != %s",
gst_glsl_profile_to_string (glsl_profiles[i].profile),
gst_glsl_profile_to_string (profile));
}
for (i = 0; i < G_N_ELEMENTS (glsl_version_profiles); i++) {
gchar *version_profile_s;
GstGLSLVersion version;
GstGLSLProfile profile;
version_profile_s =
gst_glsl_version_profile_to_string (glsl_version_profiles[i].version,
glsl_version_profiles[i].profile);
fail_unless (g_strcmp0 (version_profile_s,
glsl_version_profiles[i].name) == 0, "%s != %s", version_profile_s,
glsl_version_profiles[i].name);
fail_unless (gst_glsl_version_profile_from_string (glsl_version_profiles
[i].name, &version, &profile), "Failed to parse %s",
glsl_version_profiles[i].name);
fail_unless (profile == glsl_version_profiles[i].profile
&& version == glsl_version_profiles[i].version, "%s != %s %s",
glsl_version_profiles[i].name, gst_glsl_version_to_string (version),
gst_glsl_profile_to_string (profile));
}
/* failures */
for (i = 0; i < G_N_ELEMENTS (invalid_deserialize_glsl); i++) {
GstGLSLVersion version;
GstGLSLProfile profile;
fail_if (gst_glsl_version_profile_from_string (invalid_deserialize_glsl[i],
&version, &profile),
"successfully deserialized %s into %s %s (should have failed)",
invalid_deserialize_glsl[i], gst_glsl_version_to_string (version),
gst_glsl_profile_to_string (profile));
}
/* failures */
for (i = 0; i < G_N_ELEMENTS (invalid_serialize_glsl); i++) {
gchar *version_profile_s;
version_profile_s =
gst_glsl_version_profile_to_string (invalid_serialize_glsl[i].version,
invalid_serialize_glsl[i].profile);
fail_if (version_profile_s != NULL,
"successfully serialized %s from %s %s (should have failed)",
version_profile_s,
gst_glsl_version_to_string (invalid_serialize_glsl[i].version),
gst_glsl_profile_to_string (invalid_serialize_glsl[i].profile));
g_free (version_profile_s);
}
/* map strings to version/profile */
for (i = 0; i < G_N_ELEMENTS (glsl_str_map); i++) {
GstGLSLVersion version;
GstGLSLProfile profile;
fail_unless (glsl_str_map[i].succeed ==
gst_glsl_string_get_version_profile (glsl_str_map[i].name, &version,
&profile), "Incorrect result for parsing \'%s\': %s",
glsl_str_map[i].name, glsl_str_map[i].succeed ? "false" : "true");
if (glsl_str_map[i].succeed) {
fail_unless (version == glsl_str_map[i].version, "With %s: %s != %s",
glsl_str_map[i].name,
gst_glsl_version_to_string (glsl_str_map[i].version),
gst_glsl_version_to_string (version));
fail_unless (profile == glsl_str_map[i].profile, "With %s: %s != %s",
glsl_str_map[i].name,
gst_glsl_profile_to_string (glsl_str_map[i].profile),
gst_glsl_profile_to_string (profile));
}
}
/* special ones */
{
GstGLSLVersion version;
GstGLSLProfile profile;
gchar *version_profile_s;
version_profile_s =
gst_glsl_version_profile_to_string (GST_GLSL_VERSION_100,
GST_GLSL_PROFILE_ES);
fail_unless (g_strcmp0 (version_profile_s, "100") == 0, "%s != 100",
version_profile_s);
g_free (version_profile_s);
version_profile_s =
gst_glsl_version_profile_to_string (GST_GLSL_VERSION_100,
GST_GLSL_PROFILE_NONE);
fail_unless (g_strcmp0 (version_profile_s, "100") == 0, "%s != 100",
version_profile_s);
g_free (version_profile_s);
fail_unless (gst_glsl_version_profile_from_string ("100", &version,
&profile));
fail_unless (version == GST_GLSL_VERSION_100
&& profile == GST_GLSL_PROFILE_ES, "100 != %s %s",
gst_glsl_version_to_string (version),
gst_glsl_profile_to_string (profile));
}
}
GST_END_TEST;
static Suite *
gst_gl_upload_suite (void)
{
Suite *s = suite_create ("GstGLSL");
TCase *tc_chain = tcase_create ("glsl");
suite_add_tcase (s, tc_chain);
tcase_add_checked_fixture (tc_chain, setup, teardown);
tcase_add_test (tc_chain, test_serialization);
return s;
}
GST_CHECK_MAIN (gst_gl_upload);