#include <gst/gl/gstglshadervariables.h>
#include "gstglfiltershader.h"
+#if HAVE_GRAPHENE
+#include <graphene-gobject.h>
+#endif
enum
{
PROP_SHADER,
PROP_VERTEX,
PROP_FRAGMENT,
+ PROP_UNIFORMS,
PROP_UPDATE_SHADER,
PROP_LAST,
};
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
/* FIXME: add other stages */
+ g_object_class_install_property (gobject_class, PROP_UNIFORMS,
+ g_param_spec_boxed ("uniforms", "GLSL Uniforms",
+ "GLSL Uniforms", GST_TYPE_STRUCTURE,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
g_object_class_install_property (gobject_class, PROP_UPDATE_SHADER,
g_param_spec_boolean ("update-shader", "Update Shader",
"Emit the \'create-shader\' signal for the next frame",
static void
gst_gl_filtershader_finalize (GObject * object)
{
+ GstGLFilterShader *filtershader = GST_GL_FILTERSHADER (object);
+
+ if (filtershader->uniforms)
+ gst_structure_free (filtershader->uniforms);
+ filtershader->uniforms = NULL;
+
G_OBJECT_CLASS (gst_gl_filtershader_parent_class)->finalize (object);
}
filtershader->new_source = TRUE;
GST_OBJECT_UNLOCK (filtershader);
break;
+ case PROP_UNIFORMS:
+ GST_OBJECT_LOCK (filtershader);
+ if (filtershader->uniforms)
+ gst_structure_free (filtershader->uniforms);
+ filtershader->uniforms = g_value_dup_boxed (value);
+ filtershader->new_uniforms = TRUE;
+ GST_OBJECT_UNLOCK (filtershader);
+ break;
case PROP_UPDATE_SHADER:
GST_OBJECT_LOCK (filtershader);
filtershader->update_shader = g_value_get_boolean (value);
g_value_set_string (value, filtershader->fragment);
GST_OBJECT_UNLOCK (filtershader);
break;
+ case PROP_UNIFORMS:
+ GST_OBJECT_LOCK (filtershader);
+ g_value_set_boxed (value, filtershader->uniforms);
+ GST_OBJECT_UNLOCK (filtershader);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
return TRUE;
}
+static gboolean
+_set_uniform (GQuark field_id, const GValue * value, gpointer user_data)
+{
+ GstGLShader *shader = user_data;
+ const gchar *field_name = g_quark_to_string (field_id);
+
+ if (G_TYPE_CHECK_VALUE_TYPE ((value), G_TYPE_INT)) {
+ gst_gl_shader_set_uniform_1i (shader, field_name, g_value_get_int (value));
+ } else if (G_TYPE_CHECK_VALUE_TYPE ((value), G_TYPE_FLOAT)) {
+ gst_gl_shader_set_uniform_1f (shader, field_name,
+ g_value_get_float (value));
+#if HAVE_GRAPHENE
+ } else if (G_TYPE_CHECK_VALUE_TYPE ((value), GRAPHENE_TYPE_VEC2)) {
+ graphene_vec2_t *vec2 = g_value_get_boxed (value);
+ float x = graphene_vec2_get_x (vec2);
+ float y = graphene_vec2_get_y (vec2);
+ gst_gl_shader_set_uniform_2f (shader, field_name, x, y);
+ } else if (G_TYPE_CHECK_VALUE_TYPE ((value), GRAPHENE_TYPE_VEC3)) {
+ graphene_vec3_t *vec3 = g_value_get_boxed (value);
+ float x = graphene_vec3_get_x (vec3);
+ float y = graphene_vec3_get_y (vec3);
+ float z = graphene_vec3_get_z (vec3);
+ gst_gl_shader_set_uniform_3f (shader, field_name, x, y, z);
+ } else if (G_TYPE_CHECK_VALUE_TYPE ((value), GRAPHENE_TYPE_VEC4)) {
+ graphene_vec4_t *vec4 = g_value_get_boxed (value);
+ float x = graphene_vec4_get_x (vec4);
+ float y = graphene_vec4_get_y (vec4);
+ float z = graphene_vec4_get_z (vec4);
+ float w = graphene_vec4_get_w (vec4);
+ gst_gl_shader_set_uniform_4f (shader, field_name, x, y, z, w);
+ } else if (G_TYPE_CHECK_VALUE_TYPE ((value), GRAPHENE_TYPE_MATRIX)) {
+ graphene_matrix_t *matrix = g_value_get_boxed (value);
+ float matrix_f[16];
+ graphene_matrix_to_float (matrix, matrix_f);
+ gst_gl_shader_set_uniform_matrix_4fv (shader, field_name, 1, FALSE,
+ matrix_f);
+#endif
+ } else {
+ /* FIXME: Add support for unsigned ints, non 4x4 matrices, etc */
+ GST_FIXME ("Don't know how to set the \'%s\' paramater. Unknown type",
+ field_name);
+ return TRUE;
+ }
+
+ return TRUE;
+}
+
+static void
+_update_uniforms (GstGLFilterShader * filtershader)
+{
+ if (filtershader->new_uniforms && filtershader->uniforms) {
+ gst_gl_shader_use (filtershader->shader);
+
+ gst_structure_foreach (filtershader->uniforms,
+ (GstStructureForeachFunc) _set_uniform, filtershader->shader);
+ filtershader->new_uniforms = FALSE;
+ }
+}
+
static GstGLShader *
_maybe_recompile_shader (GstGLFilterShader * filtershader)
{
gst_object_unref (filtershader->shader);
filtershader->new_source = FALSE;
filtershader->shader = gst_object_ref (shader);
+ filtershader->new_uniforms = TRUE;
+ _update_uniforms (filtershader);
GST_OBJECT_UNLOCK (filtershader);
return shader;
}
if (filtershader->shader) {
shader = gst_object_ref (filtershader->shader);
+ _update_uniforms (filtershader);
GST_OBJECT_UNLOCK (filtershader);
return shader;
}
gst_object_unref (filtershader->shader);
filtershader->shader = gst_object_ref (shader);
filtershader->new_source = FALSE;
+ filtershader->new_uniforms = TRUE;
+ _update_uniforms (filtershader);
GST_OBJECT_UNLOCK (filtershader);
return shader;
} else if (filtershader->shader) {
+ _update_uniforms (filtershader);
shader = gst_object_ref (filtershader->shader);
GST_OBJECT_UNLOCK (filtershader);
return shader;