#include "config.h"
#endif
-/* non-GST-specific stuff */
-
#include "gltestsrc.h"
-#include <string.h>
-#include <stdlib.h>
#include <math.h>
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
+struct vts_color_struct
+{
+ gfloat R, G, B;
+};
+
enum
{
COLOR_WHITE = 0,
static const struct vts_color_struct vts_colors[] = {
/* 100% white */
- {255, 128, 128, 255, 255, 255, 255},
+ {1.0f, 1.0f, 1.0f},
/* yellow */
- {226, 0, 155, 255, 255, 0, 255},
+ {1.0f, 1.0f, 0.0f},
/* cyan */
- {179, 170, 0, 0, 255, 255, 255},
+ {0.0f, 1.0f, 1.0f},
/* green */
- {150, 46, 21, 0, 255, 0, 255},
+ {0.0f, 1.0f, 0.0f},
/* magenta */
- {105, 212, 235, 255, 0, 255, 255},
+ {1.0f, 0.0f, 1.0f},
/* red */
- {76, 85, 255, 255, 0, 0, 255},
+ {1.0f, 0.0f, 0.0f},
/* blue */
- {29, 255, 107, 0, 0, 255, 255},
+ {0.0f, 0.0f, 1.0f},
/* black */
- {16, 128, 128, 0, 0, 0, 255},
+ {0.0f, 0.0f, 0.0f},
/* -I */
- {16, 198, 21, 0, 0, 128, 255},
+ {0.0, 0.0f, 0.5f},
/* +Q */
- {16, 235, 198, 0, 128, 255, 255},
+ {0.0f, 0.5, 1.0f},
/* superblack */
- {0, 128, 128, 0, 0, 0, 255},
- /* 5% grey */
- {32, 128, 128, 32, 32, 32, 255},
+ {0.0f, 0.0f, 0.0f},
+ /* 7.421875% grey */
+ {19. / 256.0f, 19. / 256.0f, 19. / 256.0},
};
-static void
-gst_gl_test_src_unicolor (GstGLTestSrc * v, GstBuffer * buffer, int w,
- int h, const struct vts_color_struct *color);
+/* *INDENT-OFF* */
+static const GLfloat positions[] = {
+ -1.0, 1.0, 0.0, 1.0,
+ 1.0, 1.0, 0.0, 1.0,
+ 1.0, -1.0, 0.0, 1.0,
+ -1.0, -1.0, 0.0, 1.0,
+};
-void
-gst_gl_test_src_smpte (GstGLTestSrc * v, GstBuffer * buffer, int w, int h)
+static const GLushort indices_quad[] = { 0, 1, 2, 0, 2, 3 };
+/* *INDENT-ON* */
+
+struct SrcSMPTE
+{
+ struct BaseSrcImpl base;
+};
+
+static gpointer
+_src_smpte_new (GstGLTestSrc * test)
+{
+ struct SrcSMPTE *src = g_new0 (struct SrcSMPTE, 1);
+
+ src->base.src = test;
+
+ return src;
+}
+
+static gboolean
+_src_smpte_init (gpointer impl, GstGLContext * context, GstVideoInfo * v_info)
+{
+ struct SrcSMPTE *src = impl;
+
+ src->base.context = context;
+
+ return TRUE;
+}
+
+static gboolean
+_src_smpte_fill_bound_fbo (gpointer impl)
{
#if GST_GL_HAVE_OPENGL
+ struct SrcSMPTE *src = impl;
int i;
- if (gst_gl_context_get_gl_api (v->context) & GST_GL_API_OPENGL) {
+ if (gst_gl_context_get_gl_api (src->base.context) & GST_GL_API_OPENGL) {
glClearColor (0.0, 0.0, 0.0, 1.0);
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity ();
for (i = 0; i < 7; i++) {
- glColor4f (vts_colors[i].R * (1 / 255.0f), vts_colors[i].G * (1 / 255.0f),
- vts_colors[i].B * (1 / 255.0f), 1.0f);
+ glColor4f (vts_colors[i].R, vts_colors[i].G, vts_colors[i].B, 1.0f);
glBegin (GL_QUADS);
glVertex3f (-1.0f + i * (2.0f / 7.0f), -1.0f + 2.0 * (2.0f / 3.0f), 0);
glVertex3f (-1.0f + (i + 1.0f) * (2.0f / 7.0f),
k = 6 - i;
}
- glColor4f (vts_colors[k].R * (1 / 255.0f), vts_colors[k].G * (1 / 255.0f),
- vts_colors[k].B * (1 / 255.0f), 1.0f);
+ glColor4f (vts_colors[k].R, vts_colors[k].G, vts_colors[k].B, 1.0f);
glBegin (GL_QUADS);
glVertex3f (-1.0f + i * (2.0f / 7.0f), -1.0f + 2.0f * (3.0f / 4.0f), 0);
glVertex3f (-1.0f + (i + 1) * (2.0f / 7.0f), -1.0f + 2.0f * (3.0f / 4.0f),
k = 9;
}
- glColor4f (vts_colors[k].R * (1 / 255.0f), vts_colors[k].G * (1 / 255.0f),
- vts_colors[k].B * (1 / 255.0f), 1.0f);
+ glColor4f (vts_colors[k].R, vts_colors[k].G, vts_colors[k].B, 1.0f);
glBegin (GL_QUADS);
glVertex3f (-1.0f + i * (2.0f / 6.0f), -1.0f + 2.0f * 1, 0);
glVertex3f (-1.0f + (i + 1) * (2.0f / 6.0f), -1.0f + 2.0f * 1, 0);
k = COLOR_DARK_GREY;
}
- glColor4f (vts_colors[k].R * (1 / 255.0f), vts_colors[k].G * (1 / 255.0f),
- vts_colors[k].B * (1 / 255.0f), 1.0f);
+ glColor4f (vts_colors[k].R, vts_colors[k].G, vts_colors[k].B, 1.0f);
glBegin (GL_QUADS);
glVertex3f (-1.0f + 2.0f * (0.5f + i * (1.0f / 12.0f)), -1.0 + 2.0f * 1,
0);
glEnd ();
}
#endif
+
+ return TRUE;
}
-/* *INDENT-OFF* */
+static void
+_src_smpte_free (gpointer impl)
+{
+ g_free (impl);
+}
-static const GLfloat positions[] = {
- -1.0, 1.0, 0.0, 1.0,
- 1.0, 1.0, 0.0, 1.0,
- 1.0, -1.0, 0.0, 1.0,
- -1.0, -1.0, 0.0, 1.0,
- };
-static const GLfloat identitiy_matrix[] = {
- 1.0, 0.0, 0.0, 0.0,
- 0.0, 1.0, 0.0, 0.0,
- 0.0, 0.0, 1.0, 0.0,
- 0.0, 0.0, 0.0, 1.0,
- };
-/* *INDENT-ON* */
+static const struct SrcFuncs src_smpte = {
+ GST_GL_TEST_SRC_SMPTE,
+ _src_smpte_new,
+ _src_smpte_init,
+ _src_smpte_fill_bound_fbo,
+ _src_smpte_free,
+};
-void
-gst_gl_test_src_shader (GstGLTestSrc * v, GstBuffer * buffer, int w, int h)
+struct SrcUniColor
{
+ struct BaseSrcImpl base;
- GstGLFuncs *gl = v->context->gl_vtable;
+ struct vts_color_struct color;
+};
-/* *INDENT-OFF* */
- const GLfloat uvs[] = {
- 0.0, 1.0,
- 1.0, 1.0,
- 1.0, 0.0,
- 0.0, 0.0,
- };
-/* *INDENT-ON* */
+static gpointer
+_src_uni_color_new (GstGLTestSrc * test)
+{
+ struct SrcUniColor *src = g_new0 (struct SrcUniColor, 1);
- GLushort indices[] = { 0, 1, 2, 3, 0 };
+ src->base.src = test;
- GLint attr_position_loc = -1;
- GLint attr_uv_loc = -1;
+ return src;
+}
- if (gst_gl_context_get_gl_api (v->context)) {
+static gboolean
+_src_uni_color_init (gpointer impl, GstGLContext * context,
+ GstVideoInfo * v_info)
+{
+ struct SrcUniColor *src = impl;
- gst_gl_context_clear_shader (v->context);
- gl->BindTexture (GL_TEXTURE_2D, 0);
+ src->base.context = context;
+ src->base.v_info = *v_info;
- gst_gl_shader_use (v->shader);
+ return TRUE;
+}
- attr_position_loc =
- gst_gl_shader_get_attribute_location (v->shader, "position");
+static gboolean
+_src_uni_color_fill_bound_fbo (gpointer impl)
+{
+ struct SrcUniColor *src = impl;
+ const GstGLFuncs *gl = src->base.context->gl_vtable;
- attr_uv_loc = gst_gl_shader_get_attribute_location (v->shader, "uv");
+ gl->ClearColor (src->color.R, src->color.G, src->color.B, 1.0f);
+ gl->Clear (GL_COLOR_BUFFER_BIT);
- /* Load the vertex position */
- gl->VertexAttribPointer (attr_position_loc, 4, GL_FLOAT,
- GL_FALSE, 0, positions);
- /* Load the texture coordinate */
- gl->VertexAttribPointer (attr_uv_loc, 2, GL_FLOAT, GL_FALSE, 0, uvs);
+ return TRUE;
+}
+
+static void
+_src_uni_color_free (gpointer impl)
+{
+ g_free (impl);
+}
- gl->EnableVertexAttribArray (attr_position_loc);
- gl->EnableVertexAttribArray (attr_uv_loc);
+#define SRC_UNICOLOR(name, cap_name) \
+static gpointer \
+G_PASTE(G_PASTE(_src_unicolor_,name),_new) (GstGLTestSrc * test) \
+{ \
+ struct SrcUniColor *src = _src_uni_color_new (test); \
+ src->color = vts_colors[G_PASTE(COLOR_,cap_name)]; \
+ return src; \
+} \
+static const struct SrcFuncs G_PASTE (src_,name) = { \
+ G_PASTE(GST_GL_TEST_SRC_,cap_name), \
+ G_PASTE(G_PASTE(_src_unicolor_,name),_new), \
+ _src_uni_color_init, \
+ _src_uni_color_fill_bound_fbo, \
+ _src_uni_color_free, \
+}
- gst_gl_shader_set_uniform_matrix_4fv (v->shader, "mvp",
- 1, GL_FALSE, identitiy_matrix);
+SRC_UNICOLOR (white, WHITE);
+SRC_UNICOLOR (black, BLACK);
+SRC_UNICOLOR (red, RED);
+SRC_UNICOLOR (green, GREEN);
+SRC_UNICOLOR (blue, BLUE);
- gst_gl_shader_set_uniform_1f (v->shader, "time",
- (gfloat) v->running_time / GST_SECOND);
+static gpointer
+_src_blink_new (GstGLTestSrc * test)
+{
+ struct SrcUniColor *src = _src_uni_color_new (test);
- gst_gl_shader_set_uniform_1f (v->shader, "aspect_ratio",
- (gfloat) w / (gfloat) h);
+ src->color = vts_colors[COLOR_WHITE];
- gl->DrawElements (GL_TRIANGLE_STRIP, 5, GL_UNSIGNED_SHORT, indices);
+ return src;
+}
- gl->DisableVertexAttribArray (attr_position_loc);
- gl->DisableVertexAttribArray (attr_uv_loc);
+static gboolean
+_src_blink_fill_bound_fbo (gpointer impl)
+{
+ struct SrcUniColor *src = impl;
- gst_gl_context_clear_shader (v->context);
+ if (src->color.R > 0.5) {
+ src->color = vts_colors[COLOR_BLACK];
+ } else {
+ src->color = vts_colors[COLOR_WHITE];
}
+
+ return _src_uni_color_fill_bound_fbo (impl);
}
-static void
-gst_gl_test_src_unicolor (GstGLTestSrc * v, GstBuffer * buffer, int w,
- int h, const struct vts_color_struct *color)
+static const struct SrcFuncs src_blink = {
+ GST_GL_TEST_SRC_BLINK,
+ _src_blink_new,
+ _src_uni_color_init,
+ _src_blink_fill_bound_fbo,
+ _src_uni_color_free,
+};
+
+struct SrcShader
{
-#if GST_GL_HAVE_OPENGL
- if (gst_gl_context_get_gl_api (v->context) & GST_GL_API_OPENGL) {
- glClearColor (color->R * (1 / 255.0f), color->G * (1 / 255.0f),
- color->B * (1 / 255.0f), 1.0f);
- glClear (GL_COLOR_BUFFER_BIT);
+ struct BaseSrcImpl base;
+
+ GstGLShader *shader;
+
+ gint attr_position;
+ gint attr_texcoord;
+ /* x, y, z, w */
+ const gfloat *vertices;
+ guint n_vertices;
+ const gushort *indices;
+ guint n_indices;
+};
+
+static gboolean
+_src_shader_fill_bound_fbo (gpointer impl)
+{
+ struct SrcShader *src = impl;
+ const GstGLFuncs *gl;
+
+ g_return_val_if_fail (src->base.context, FALSE);
+ g_return_val_if_fail (src->shader, FALSE);
+ gl = src->base.context->gl_vtable;
+
+ gst_gl_shader_use (src->shader);
+
+ if (src->attr_position != -1) {
+ gl->VertexAttribPointer (src->attr_position, 4, GL_FLOAT, GL_FALSE, 0,
+ src->vertices);
+ gl->EnableVertexAttribArray (src->attr_position);
}
-#endif
+ gl->DrawElements (GL_TRIANGLES, src->n_indices, GL_UNSIGNED_SHORT,
+ src->indices);
+
+ if (src->attr_position != -1)
+ gl->DisableVertexAttribArray (src->attr_position);
+ gst_gl_context_clear_shader (src->base.context);
+
+ return TRUE;
}
-void
-gst_gl_test_src_black (GstGLTestSrc * v, GstBuffer * buffer, int w, int h)
+/* *INDENT-OFF* */
+static const gchar *checkers_vertex_src = "attribute vec4 position;\n"
+ "void main()\n"
+ "{\n"
+ " gl_Position = position;\n"
+ "}";
+
+static const gchar *checkers_fragment_src =
+ "#ifdef GL_ES\n"
+ "precision mediump float;\n"
+ "#endif\n"
+ "uniform float checker_width;\n"
+ "void main()\n"
+ "{\n"
+ " vec2 xy_index= floor((gl_FragCoord.xy-vec2(0.5,0.5))/checker_width);\n"
+ " vec2 xy_mod=mod(xy_index,vec2(2.0,2.0));\n"
+ " float result=mod(xy_mod.x+xy_mod.y,2.0);\n"
+ " gl_FragColor.r=step(result,0.5);\n"
+ " gl_FragColor.g=1.0-gl_FragColor.r;\n"
+ " gl_FragColor.ba=vec2(0,1);\n"
+ "}";
+/* *INDENT-ON* */
+
+struct SrcCheckers
{
- gst_gl_test_src_unicolor (v, buffer, w, h, vts_colors + COLOR_BLACK);
-}
+ struct SrcShader base;
-void
-gst_gl_test_src_white (GstGLTestSrc * v, GstBuffer * buffer, int w, int h)
+ guint checker_width;
+};
+
+static gboolean
+_src_checkers_init (gpointer impl, GstGLContext * context,
+ GstVideoInfo * v_info)
{
- gst_gl_test_src_unicolor (v, buffer, w, h, vts_colors + COLOR_WHITE);
+ struct SrcCheckers *src = impl;
+ GError *error = NULL;
+
+ src->base.base.context = context;
+
+ if (src->base.shader)
+ gst_object_unref (src->base.shader);
+ src->base.shader = gst_gl_shader_new_link_with_stages (context, &error,
+ gst_glsl_stage_new_with_string (context, GL_VERTEX_SHADER,
+ GST_GLSL_VERSION_NONE,
+ GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY,
+ checkers_vertex_src),
+ gst_glsl_stage_new_with_string (context, GL_FRAGMENT_SHADER,
+ GST_GLSL_VERSION_NONE,
+ GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY,
+ checkers_fragment_src), NULL);
+ if (!src->base.shader) {
+ GST_ERROR_OBJECT (src->base.base.src, "%s", error->message);
+ return FALSE;
+ }
+
+ src->base.attr_position =
+ gst_gl_shader_get_attribute_location (src->base.shader, "position");
+ if (src->base.attr_position == -1) {
+ GST_ERROR_OBJECT (src->base.base.src, "No position attribute");
+ return FALSE;
+ }
+ src->base.vertices = positions;
+ src->base.n_vertices = 4;
+ src->base.indices = indices_quad;
+ src->base.n_indices = 6;
+
+ gst_gl_shader_use (src->base.shader);
+ gst_gl_shader_set_uniform_1f (src->base.shader, "checker_width",
+ src->checker_width);
+ gst_gl_context_clear_shader (src->base.base.context);
+
+ return TRUE;
}
-void
-gst_gl_test_src_red (GstGLTestSrc * v, GstBuffer * buffer, int w, int h)
+static void
+_src_checkers_free (gpointer impl)
{
- gst_gl_test_src_unicolor (v, buffer, w, h, vts_colors + COLOR_RED);
+ struct SrcCheckers *src = impl;
+
+ if (!src)
+ return;
+
+ if (src->base.shader)
+ gst_object_unref (src->base.shader);
+ src->base.shader = NULL;
+
+ g_free (impl);
}
-void
-gst_gl_test_src_green (GstGLTestSrc * v, GstBuffer * buffer, int w, int h)
+static gpointer
+_src_checkers_new (GstGLTestSrc * test)
{
- gst_gl_test_src_unicolor (v, buffer, w, h, vts_colors + COLOR_GREEN);
+ struct SrcCheckers *src = g_new0 (struct SrcCheckers, 1);
+
+ src->base.base.src = test;
+
+ return src;
}
-void
-gst_gl_test_src_blue (GstGLTestSrc * v, GstBuffer * buffer, int w, int h)
+#define SRC_CHECKERS(spacing) \
+static gpointer \
+G_PASTE(G_PASTE(_src_checkers,spacing),_new) (GstGLTestSrc * test) \
+{ \
+ struct SrcCheckers *src = _src_checkers_new (test); \
+ src->checker_width = spacing; \
+ return src; \
+} \
+static const struct SrcFuncs G_PASTE(src_checkers,spacing) = { \
+ G_PASTE(GST_GL_TEST_SRC_CHECKERS,spacing), \
+ G_PASTE(G_PASTE(_src_checkers,spacing),_new), \
+ _src_checkers_init, \
+ _src_shader_fill_bound_fbo, \
+ _src_checkers_free, \
+}
+
+SRC_CHECKERS (1);
+SRC_CHECKERS (2);
+SRC_CHECKERS (4);
+SRC_CHECKERS (8);
+
+/* *INDENT-OFF* */
+static const gchar *snow_vertex_src =
+ "attribute vec4 position;\n"
+ "varying vec2 out_uv;\n"
+ "void main()\n"
+ "{\n"
+ " gl_Position = position;\n"
+ " out_uv = position.xy;\n"
+ "}";
+
+static const gchar *snow_fragment_src =
+ "#ifdef GL_ES\n"
+ "precision mediump float;\n"
+ "#endif\n"
+ "uniform float time;\n"
+ "varying vec2 out_uv;\n"
+ "\n"
+ "float rand(vec2 co){\n"
+ " return fract(sin(dot(co.xy, vec2(12.9898,78.233))) * 43758.5453);\n"
+ "}\n"
+ "void main()\n"
+ "{\n"
+ " gl_FragColor = vec4(rand(time * out_uv));\n"
+ "}";
+/* *INDENT-ON* */
+
+static gboolean
+_src_snow_init (gpointer impl, GstGLContext * context, GstVideoInfo * v_info)
{
- gst_gl_test_src_unicolor (v, buffer, w, h, vts_colors + COLOR_BLUE);
+ struct SrcShader *src = impl;
+ GError *error = NULL;
+
+ src->base.context = context;
+
+ if (src->shader)
+ gst_object_unref (src->shader);
+ src->shader = gst_gl_shader_new_link_with_stages (context, &error,
+ gst_glsl_stage_new_with_string (context, GL_VERTEX_SHADER,
+ GST_GLSL_VERSION_NONE,
+ GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY,
+ snow_vertex_src),
+ gst_glsl_stage_new_with_string (context, GL_FRAGMENT_SHADER,
+ GST_GLSL_VERSION_NONE,
+ GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY,
+ snow_fragment_src), NULL);
+ if (!src->shader) {
+ GST_ERROR_OBJECT (src->base.src, "%s", error->message);
+ return FALSE;
+ }
+
+ src->attr_position =
+ gst_gl_shader_get_attribute_location (src->shader, "position");
+ if (src->attr_position == -1) {
+ GST_ERROR_OBJECT (src->base.src, "No position attribute");
+ return FALSE;
+ }
+ src->vertices = positions;
+ src->n_vertices = 4;
+ src->indices = indices_quad;
+ src->n_indices = 6;
+
+ return TRUE;
}
-static void
-gst_gl_test_src_checkers (GstGLTestSrc * v, gint checker_width)
+static gboolean
+_src_snow_fill_bound_fbo (gpointer impl)
{
+ struct SrcShader *src = impl;
- GstGLFuncs *gl = v->context->gl_vtable;
+ g_return_val_if_fail (src->base.context, FALSE);
+ g_return_val_if_fail (src->shader, FALSE);
- GLushort indices[] = { 0, 1, 2, 3, 0 };
+ gst_gl_shader_use (src->shader);
+ gst_gl_shader_set_uniform_1f (src->shader, "time",
+ (gfloat) src->base.src->running_time / GST_SECOND);
- GLint attr_position_loc = -1;
+ return _src_shader_fill_bound_fbo (impl);
+}
- if (gst_gl_context_get_gl_api (v->context)) {
+static void
+_src_snow_free (gpointer impl)
+{
+ struct SrcShader *src = impl;
- gst_gl_context_clear_shader (v->context);
- gl->BindTexture (GL_TEXTURE_2D, 0);
+ if (!src)
+ return;
- gst_gl_shader_use (v->shader);
+ if (src->shader)
+ gst_object_unref (src->shader);
+ src->shader = NULL;
- attr_position_loc =
- gst_gl_shader_get_attribute_location (v->shader, "position");
+ g_free (impl);
+}
- /* Load the vertex position */
- gl->VertexAttribPointer (attr_position_loc, 4, GL_FLOAT,
- GL_FALSE, 0, positions);
+static gpointer
+_src_snow_new (GstGLTestSrc * test)
+{
+ struct SrcShader *src = g_new0 (struct SrcShader, 1);
- gl->EnableVertexAttribArray (attr_position_loc);
+ src->base.src = test;
- gst_gl_shader_set_uniform_matrix_4fv (v->shader, "mvp",
- 1, GL_FALSE, identitiy_matrix);
+ return src;
+}
- gst_gl_shader_set_uniform_1f (v->shader, "checker_width", checker_width);
+static const struct SrcFuncs src_snow = {
+ GST_GL_TEST_SRC_SNOW,
+ _src_snow_new,
+ _src_snow_init,
+ _src_snow_fill_bound_fbo,
+ _src_snow_free,
+};
- gl->DrawElements (GL_TRIANGLE_STRIP, 5, GL_UNSIGNED_SHORT, indices);
+/* *INDENT-OFF* */
+static const gchar *mandelbrot_vertex_src = "attribute vec4 position;\n"
+ "uniform float aspect_ratio;\n"
+ "varying vec2 fractal_position;\n"
+ "void main()\n"
+ "{\n"
+ " gl_Position = position;\n"
+ " fractal_position = vec2(position.y * 0.5 - 0.3, aspect_ratio * position.x * 0.5);\n"
+ " fractal_position *= 2.5;\n"
+ "}";
+
+static const gchar *mandelbrot_fragment_src =
+ "#ifdef GL_ES\n"
+ "precision mediump float;\n"
+ "#endif\n"
+ "uniform float time;\n"
+ "varying vec2 fractal_position;\n"
+ "const vec4 K = vec4(1.0, 0.66, 0.33, 3.0);\n"
+ "vec4 hsv_to_rgb(float hue, float saturation, float value) {\n"
+ " vec4 p = abs(fract(vec4(hue) + K) * 6.0 - K.wwww);\n"
+ " return value * mix(K.xxxx, clamp(p - K.xxxx, 0.0, 1.0), saturation);\n"
+ "}\n"
+ "vec4 i_to_rgb(int i) {\n"
+ " float hue = float(i) / 100.0 + sin(time);\n"
+ " return hsv_to_rgb(hue, 0.5, 0.8);\n"
+ "}\n"
+ "vec2 pow_2_complex(vec2 c) {\n"
+ " return vec2(c.x*c.x - c.y*c.y, 2.0 * c.x * c.y);\n"
+ "}\n"
+ "vec2 mandelbrot(vec2 c, vec2 c0) {\n"
+ " return pow_2_complex(c) + c0;\n"
+ "}\n"
+ "vec4 iterate_pixel(vec2 position) {\n"
+ " vec2 c = vec2(0);\n"
+ " for (int i=0; i < 100; i++) {\n"
+ " if (c.x*c.x + c.y*c.y > 2.0*2.0)\n"
+ " return i_to_rgb(i);\n"
+ " c = mandelbrot(c, position);\n"
+ " }\n"
+ " return vec4(0, 0, 0, 1);\n"
+ "}\n"
+ "void main() {\n"
+ " gl_FragColor = iterate_pixel(fractal_position);\n"
+ "}";
+/* *INDENT-ON* */
- gl->DisableVertexAttribArray (attr_position_loc);
+static gboolean
+_src_mandelbrot_init (gpointer impl, GstGLContext * context,
+ GstVideoInfo * v_info)
+{
+ struct SrcShader *src = impl;
+ GError *error = NULL;
+
+ src->base.context = context;
+
+ if (src->shader)
+ gst_object_unref (src->shader);
+ src->shader = gst_gl_shader_new_link_with_stages (context, &error,
+ gst_glsl_stage_new_with_string (context, GL_VERTEX_SHADER,
+ GST_GLSL_VERSION_NONE,
+ GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY,
+ mandelbrot_vertex_src),
+ gst_glsl_stage_new_with_string (context, GL_FRAGMENT_SHADER,
+ GST_GLSL_VERSION_NONE,
+ GST_GLSL_PROFILE_ES | GST_GLSL_PROFILE_COMPATIBILITY,
+ mandelbrot_fragment_src), NULL);
+ if (!src->shader) {
+ GST_ERROR_OBJECT (src->base.src, "%s", error->message);
+ return FALSE;
+ }
- gst_gl_context_clear_shader (v->context);
+ src->attr_position =
+ gst_gl_shader_get_attribute_location (src->shader, "position");
+ if (src->attr_position == -1) {
+ GST_ERROR_OBJECT (src->base.src, "No position attribute");
+ return FALSE;
}
+ src->vertices = positions;
+ src->n_vertices = 4;
+ src->indices = indices_quad;
+ src->n_indices = 6;
+
+ gst_gl_shader_use (src->shader);
+ gst_gl_shader_set_uniform_1f (src->shader, "aspect_ratio",
+ (gfloat) GST_VIDEO_INFO_WIDTH (v_info) /
+ (gfloat) GST_VIDEO_INFO_HEIGHT (v_info));
+ gst_gl_context_clear_shader (src->base.context);
+
+ return TRUE;
}
-
-void
-gst_gl_test_src_checkers1 (GstGLTestSrc * v, GstBuffer * buffer, int w, int h)
+static gboolean
+_src_mandelbrot_fill_bound_fbo (gpointer impl)
{
- gst_gl_test_src_checkers (v, 1);
-}
+ struct SrcShader *src = impl;
+ g_return_val_if_fail (src->base.context, FALSE);
+ g_return_val_if_fail (src->shader, FALSE);
-void
-gst_gl_test_src_checkers2 (GstGLTestSrc * v, GstBuffer * buffer, int w, int h)
-{
- gst_gl_test_src_checkers (v, 2);
+ gst_gl_shader_use (src->shader);
+ gst_gl_shader_set_uniform_1f (src->shader, "time",
+ (gfloat) src->base.src->running_time / GST_SECOND);
+
+ return _src_shader_fill_bound_fbo (impl);
}
-void
-gst_gl_test_src_checkers4 (GstGLTestSrc * v, GstBuffer * buffer, int w, int h)
+static void
+_src_mandelbrot_free (gpointer impl)
{
- gst_gl_test_src_checkers (v, 4);
+ struct SrcShader *src = impl;
+
+ if (!src)
+ return;
+ if (src->shader)
+ gst_object_unref (src->shader);
+ src->shader = NULL;
+
+ g_free (impl);
}
-void
-gst_gl_test_src_checkers8 (GstGLTestSrc * v, GstBuffer * buffer, int w, int h)
+static gpointer
+_src_mandelbrot_new (GstGLTestSrc * test)
{
- gst_gl_test_src_checkers (v, 8);
+ struct SrcShader *src = g_new0 (struct SrcShader, 1);
+
+ src->base.src = test;
+
+ return src;
}
+static const struct SrcFuncs src_mandelbrot = {
+ GST_GL_TEST_SRC_MANDELBROT,
+ _src_mandelbrot_new,
+ _src_mandelbrot_init,
+ _src_mandelbrot_fill_bound_fbo,
+ _src_mandelbrot_free,
+};
+
+#if 0
void
gst_gl_test_src_circular (GstGLTestSrc * v, GstBuffer * buffer, int w, int h)
{
}
#endif
}
+#endif
+static const struct SrcFuncs *src_impls[] = {
+ &src_smpte,
+ &src_snow,
+ &src_black,
+ &src_white,
+ &src_red,
+ &src_green,
+ &src_blue,
+ &src_checkers1,
+ &src_checkers2,
+ &src_checkers4,
+ &src_checkers8,
+ &src_blink,
+ &src_mandelbrot,
+};
+
+const struct SrcFuncs *
+gst_gl_test_src_get_src_funcs_for_pattern (GstGLTestSrcPattern pattern)
+{
+ gint i;
+
+ for (i = 0; i < G_N_ELEMENTS (src_impls); i++) {
+ if (src_impls[i]->pattern == pattern)
+ return src_impls[i];
+ }
+
+ return NULL;
+}
return caps;
}
-const gchar *snow_vertex_src = "attribute vec4 position; \
- attribute vec2 uv; \
- uniform mat4 mvp; \
- varying vec2 out_uv; \
- void main() \
- { \
- gl_Position = mvp * position; \
- out_uv = uv; \
- }";
-
-const gchar *snow_fragment_src = "uniform float time; \
- varying vec2 out_uv; \
- \
- float rand(vec2 co){ \
- return fract(sin(dot(co.xy, vec2(12.9898,78.233))) * 43758.5453); \
- } \
- void main() \
- { \
- gl_FragColor = rand(time * out_uv) * vec4(1); \
- }";
-
-const gchar *mandelbrot_vertex_src = "attribute vec4 position; \
- attribute vec2 uv; \
- uniform mat4 mvp; \
- uniform float aspect_ratio; \
- varying vec2 fractal_position; \
- \
- void main() \
- { \
- gl_Position = mvp * position; \
- fractal_position = vec2(uv.y - 0.8, aspect_ratio * (uv.x - 0.5)); \
- fractal_position *= 2.5; \
- }";
-
-const gchar *mandelbrot_fragment_src = "uniform float time; \
- varying vec2 fractal_position; \
- \
- const vec4 K = vec4(1.0, 0.66, 0.33, 3.0); \
- \
- vec4 hsv_to_rgb(float hue, float saturation, float value) { \
- vec4 p = abs(fract(vec4(hue) + K) * 6.0 - K.wwww); \
- return value * mix(K.xxxx, clamp(p - K.xxxx, 0.0, 1.0), saturation); \
- } \
- \
- vec4 i_to_rgb(int i) { \
- float hue = float(i) / 100.0 + sin(time); \
- return hsv_to_rgb(hue, 0.5, 0.8); \
- } \
- \
- vec2 pow_2_complex(vec2 c) { \
- return vec2(c.x*c.x - c.y*c.y, 2.0 * c.x * c.y); \
- } \
- \
- vec2 mandelbrot(vec2 c, vec2 c0) { \
- return pow_2_complex(c) + c0; \
- } \
- \
- vec4 iterate_pixel(vec2 position) { \
- vec2 c = vec2(0); \
- for (int i=0; i < 100; i++) { \
- if (c.x*c.x + c.y*c.y > 2.0*2.0) \
- return i_to_rgb(i); \
- c = mandelbrot(c, position); \
- } \
- return vec4(0, 0, 0, 1); \
- } \
- \
- void main() { \
- gl_FragColor = iterate_pixel(fractal_position); \
- }";
-
-
-const gchar *checkers_vertex_src = "attribute vec4 position; \
- uniform mat4 mvp; \
- void main() \
- { \
- gl_Position = mvp * position; \
- }";
-
-const gchar *checkers_fragment_src = "uniform float checker_width; \
- void main() \
- { \
- vec2 xy_index= floor((gl_FragCoord.xy-vec2(0.5,0.5))/checker_width); \
- vec2 xy_mod=mod(xy_index,vec2(2.0,2.0)); \
- float result=mod(xy_mod.x+xy_mod.y,2.0); \
- gl_FragColor.r=step(result,0.5); \
- gl_FragColor.g=1.0-gl_FragColor.r; \
- gl_FragColor.ba=vec2(0,1); \
- }";
-
-
static void
gst_gl_test_src_set_pattern (GstGLTestSrc * gltestsrc, gint pattern_type)
{
- gltestsrc->pattern_type = pattern_type;
-
- GST_DEBUG_OBJECT (gltestsrc, "setting pattern to %d", pattern_type);
-
- switch (pattern_type) {
- case GST_GL_TEST_SRC_SMPTE:
- gltestsrc->make_image = gst_gl_test_src_smpte;
- break;
- case GST_GL_TEST_SRC_SNOW:
- gltestsrc->vertex_src = snow_vertex_src;
- gltestsrc->fragment_src = snow_fragment_src;
- gltestsrc->make_image = gst_gl_test_src_shader;
- break;
- case GST_GL_TEST_SRC_BLACK:
- gltestsrc->make_image = gst_gl_test_src_black;
- break;
- case GST_GL_TEST_SRC_WHITE:
- gltestsrc->make_image = gst_gl_test_src_white;
- break;
- case GST_GL_TEST_SRC_RED:
- gltestsrc->make_image = gst_gl_test_src_red;
- break;
- case GST_GL_TEST_SRC_GREEN:
- gltestsrc->make_image = gst_gl_test_src_green;
- break;
- case GST_GL_TEST_SRC_BLUE:
- gltestsrc->make_image = gst_gl_test_src_blue;
- break;
- case GST_GL_TEST_SRC_CHECKERS1:
- gltestsrc->vertex_src = checkers_vertex_src;
- gltestsrc->fragment_src = checkers_fragment_src;
- gltestsrc->make_image = gst_gl_test_src_checkers1;
- break;
- case GST_GL_TEST_SRC_CHECKERS2:
- gltestsrc->vertex_src = checkers_vertex_src;
- gltestsrc->fragment_src = checkers_fragment_src;
- gltestsrc->make_image = gst_gl_test_src_checkers2;
- break;
- case GST_GL_TEST_SRC_CHECKERS4:
- gltestsrc->vertex_src = checkers_vertex_src;
- gltestsrc->fragment_src = checkers_fragment_src;
- gltestsrc->make_image = gst_gl_test_src_checkers4;
- break;
- case GST_GL_TEST_SRC_CHECKERS8:
- gltestsrc->vertex_src = checkers_vertex_src;
- gltestsrc->fragment_src = checkers_fragment_src;
- gltestsrc->make_image = gst_gl_test_src_checkers8;
- break;
- case GST_GL_TEST_SRC_CIRCULAR:
- gltestsrc->make_image = gst_gl_test_src_circular;
- break;
- case GST_GL_TEST_SRC_BLINK:
- gltestsrc->make_image = gst_gl_test_src_black;
- break;
- case GST_GL_TEST_SRC_MANDELBROT:
- gltestsrc->vertex_src = mandelbrot_vertex_src;
- gltestsrc->fragment_src = mandelbrot_fragment_src;
- gltestsrc->make_image = gst_gl_test_src_shader;
- break;
- default:
- g_assert_not_reached ();
- }
+ gltestsrc->set_pattern = pattern_type;
}
static void
switch (prop_id) {
case PROP_PATTERN:
- g_value_set_enum (value, src->pattern_type);
+ g_value_set_enum (value, src->set_pattern);
break;
case PROP_TIMESTAMP_OFFSET:
g_value_set_int64 (value, src->timestamp_offset);
{
if (gst_gl_context_get_gl_api (gltestsrc->context)) {
/* blocking call, wait until the opengl thread has compiled the shader */
- if (gltestsrc->vertex_src == NULL)
- return FALSE;
- return gst_gl_context_gen_shader (gltestsrc->context, gltestsrc->vertex_src,
- gltestsrc->fragment_src, &gltestsrc->shader);
+// if (gltestsrc->vertex_src == NULL)
+// return FALSE;
+// return gst_gl_context_gen_shader (gltestsrc->context, gltestsrc->vertex_src,
+// gltestsrc->fragment_src, &gltestsrc->shader);
}
return TRUE;
}
&& src->n_frames == 1))
goto eos;
- if (src->pattern_type == GST_GL_TEST_SRC_BLINK) {
- if (src->n_frames & 0x1)
- src->make_image = gst_gl_test_src_white;
- else
- src->make_image = gst_gl_test_src_black;
- }
-
if (!gst_video_frame_map (&out_frame, &src->out_info, buffer,
GST_MAP_WRITE | GST_MAP_GL)) {
return GST_FLOW_NOT_NEGOTIATED;
out_tex = *(guint *) out_frame.data[0];
- gst_buffer_replace (&src->buffer, buffer);
-
if (!gst_gl_context_use_fbo_v2 (src->context, width, height, src->fbo,
src->depthbuffer, out_tex, gst_gl_test_src_callback,
(gpointer) src)) {
- goto not_negotiated;
+ gst_video_frame_unmap (&out_frame);
+ goto gl_error;
}
-
gst_video_frame_unmap (&out_frame);
+ if (!src->gl_result)
+ goto gl_error;
sync_meta = gst_buffer_get_gl_sync_meta (buffer);
if (sync_meta)
return GST_FLOW_OK;
+gl_error:
+ {
+ GST_ELEMENT_ERROR (src, RESOURCE, NOT_FOUND, (_("failed to draw pattern")),
+ (_("A GL error occured")));
+ return GST_FLOW_NOT_NEGOTIATED;
+ }
not_negotiated:
{
GST_ELEMENT_ERROR (src, CORE, NEGOTIATION, (NULL),
gst_gl_test_src_callback (gpointer stuff)
{
GstGLTestSrc *src = GST_GL_TEST_SRC (stuff);
+ const struct SrcFuncs *funcs;
+
+ funcs = src->src_funcs;
+
+ if (!funcs || src->set_pattern != src->active_pattern) {
+ if (src->src_impl)
+ funcs->free (src->src_impl);
+ src->src_funcs = funcs =
+ gst_gl_test_src_get_src_funcs_for_pattern (src->set_pattern);
+ if (funcs == NULL) {
+ GST_ERROR_OBJECT (src, "Could not find an implementation of the "
+ "requested pattern");
+ src->gl_result = FALSE;
+ return;
+ }
+ src->src_impl = funcs->new (src);
+ if (!(src->gl_result =
+ funcs->init (src->src_impl, src->context, &src->out_info))) {
+ GST_ERROR_OBJECT (src, "Failed to initialize pattern");
+ return;
+ }
+ src->active_pattern = src->set_pattern;
+ }
- src->make_image (src, src->buffer, GST_VIDEO_INFO_WIDTH (&src->out_info),
- GST_VIDEO_INFO_HEIGHT (&src->out_info));
-
- gst_buffer_unref (src->buffer);
- src->buffer = NULL;
+ src->gl_result = funcs->fill_bound_fbo (src->src_impl);
+ if (!src->gl_result)
+ GST_ERROR_OBJECT (src, "Failed to render the pattern");
}
static GstStateChangeReturn