gltestsrc: add a generic src framework

Any unsupported pattern (circular) results in an error
This commit is contained in:
Matthew Waters 2016-02-25 21:18:31 +11:00 committed by Tim-Philipp Müller
parent 5a68528419
commit 309005b12d
4 changed files with 680 additions and 418 deletions

View file

@ -21,18 +21,19 @@
#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,
@ -51,42 +52,75 @@ enum
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);
@ -97,8 +131,7 @@ gst_gl_test_src_smpte (GstGLTestSrc * v, GstBuffer * buffer, int w, int h)
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),
@ -117,8 +150,7 @@ gst_gl_test_src_smpte (GstGLTestSrc * v, GstBuffer * buffer, int w, int h)
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),
@ -140,8 +172,7 @@ gst_gl_test_src_smpte (GstGLTestSrc * v, GstBuffer * buffer, int w, int h)
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);
@ -162,8 +193,7 @@ gst_gl_test_src_smpte (GstGLTestSrc * v, GstBuffer * buffer, int w, int h)
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);
@ -185,193 +215,540 @@ gst_gl_test_src_smpte (GstGLTestSrc * v, GstBuffer * buffer, int w, int h)
glEnd ();
}
#endif
}
/* *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,
};
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* */
void
gst_gl_test_src_shader (GstGLTestSrc * v, GstBuffer * buffer, int w, int h)
{
GstGLFuncs *gl = v->context->gl_vtable;
/* *INDENT-OFF* */
const GLfloat uvs[] = {
0.0, 1.0,
1.0, 1.0,
1.0, 0.0,
0.0, 0.0,
};
/* *INDENT-ON* */
GLushort indices[] = { 0, 1, 2, 3, 0 };
GLint attr_position_loc = -1;
GLint attr_uv_loc = -1;
if (gst_gl_context_get_gl_api (v->context)) {
gst_gl_context_clear_shader (v->context);
gl->BindTexture (GL_TEXTURE_2D, 0);
gst_gl_shader_use (v->shader);
attr_position_loc =
gst_gl_shader_get_attribute_location (v->shader, "position");
attr_uv_loc = gst_gl_shader_get_attribute_location (v->shader, "uv");
/* 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);
gl->EnableVertexAttribArray (attr_position_loc);
gl->EnableVertexAttribArray (attr_uv_loc);
gst_gl_shader_set_uniform_matrix_4fv (v->shader, "mvp",
1, GL_FALSE, identitiy_matrix);
gst_gl_shader_set_uniform_1f (v->shader, "time",
(gfloat) v->running_time / GST_SECOND);
gst_gl_shader_set_uniform_1f (v->shader, "aspect_ratio",
(gfloat) w / (gfloat) h);
gl->DrawElements (GL_TRIANGLE_STRIP, 5, GL_UNSIGNED_SHORT, indices);
gl->DisableVertexAttribArray (attr_position_loc);
gl->DisableVertexAttribArray (attr_uv_loc);
gst_gl_context_clear_shader (v->context);
}
return TRUE;
}
static void
gst_gl_test_src_unicolor (GstGLTestSrc * v, GstBuffer * buffer, int w,
int h, const struct vts_color_struct *color)
_src_smpte_free (gpointer impl)
{
#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);
}
#endif
g_free (impl);
}
void
gst_gl_test_src_black (GstGLTestSrc * v, GstBuffer * buffer, int w, int h)
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,
};
struct SrcUniColor
{
gst_gl_test_src_unicolor (v, buffer, w, h, vts_colors + COLOR_BLACK);
struct BaseSrcImpl base;
struct vts_color_struct color;
};
static gpointer
_src_uni_color_new (GstGLTestSrc * test)
{
struct SrcUniColor *src = g_new0 (struct SrcUniColor, 1);
src->base.src = test;
return src;
}
void
gst_gl_test_src_white (GstGLTestSrc * v, GstBuffer * buffer, int w, int h)
static gboolean
_src_uni_color_init (gpointer impl, GstGLContext * context,
GstVideoInfo * v_info)
{
gst_gl_test_src_unicolor (v, buffer, w, h, vts_colors + COLOR_WHITE);
struct SrcUniColor *src = impl;
src->base.context = context;
src->base.v_info = *v_info;
return TRUE;
}
void
gst_gl_test_src_red (GstGLTestSrc * v, GstBuffer * buffer, int w, int h)
static gboolean
_src_uni_color_fill_bound_fbo (gpointer impl)
{
gst_gl_test_src_unicolor (v, buffer, w, h, vts_colors + COLOR_RED);
}
struct SrcUniColor *src = impl;
const GstGLFuncs *gl = src->base.context->gl_vtable;
void
gst_gl_test_src_green (GstGLTestSrc * v, GstBuffer * buffer, int w, int h)
{
gst_gl_test_src_unicolor (v, buffer, w, h, vts_colors + COLOR_GREEN);
}
gl->ClearColor (src->color.R, src->color.G, src->color.B, 1.0f);
gl->Clear (GL_COLOR_BUFFER_BIT);
void
gst_gl_test_src_blue (GstGLTestSrc * v, GstBuffer * buffer, int w, int h)
{
gst_gl_test_src_unicolor (v, buffer, w, h, vts_colors + COLOR_BLUE);
return TRUE;
}
static void
gst_gl_test_src_checkers (GstGLTestSrc * v, gint checker_width)
_src_uni_color_free (gpointer impl)
{
g_free (impl);
}
GstGLFuncs *gl = v->context->gl_vtable;
#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, \
}
GLushort indices[] = { 0, 1, 2, 3, 0 };
SRC_UNICOLOR (white, WHITE);
SRC_UNICOLOR (black, BLACK);
SRC_UNICOLOR (red, RED);
SRC_UNICOLOR (green, GREEN);
SRC_UNICOLOR (blue, BLUE);
GLint attr_position_loc = -1;
static gpointer
_src_blink_new (GstGLTestSrc * test)
{
struct SrcUniColor *src = _src_uni_color_new (test);
if (gst_gl_context_get_gl_api (v->context)) {
src->color = vts_colors[COLOR_WHITE];
gst_gl_context_clear_shader (v->context);
gl->BindTexture (GL_TEXTURE_2D, 0);
return src;
}
gst_gl_shader_use (v->shader);
static gboolean
_src_blink_fill_bound_fbo (gpointer impl)
{
struct SrcUniColor *src = impl;
attr_position_loc =
gst_gl_shader_get_attribute_location (v->shader, "position");
/* Load the vertex position */
gl->VertexAttribPointer (attr_position_loc, 4, GL_FLOAT,
GL_FALSE, 0, positions);
gl->EnableVertexAttribArray (attr_position_loc);
gst_gl_shader_set_uniform_matrix_4fv (v->shader, "mvp",
1, GL_FALSE, identitiy_matrix);
gst_gl_shader_set_uniform_1f (v->shader, "checker_width", checker_width);
gl->DrawElements (GL_TRIANGLE_STRIP, 5, GL_UNSIGNED_SHORT, indices);
gl->DisableVertexAttribArray (attr_position_loc);
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 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,
};
void
gst_gl_test_src_checkers1 (GstGLTestSrc * v, GstBuffer * buffer, int w, int h)
struct SrcShader
{
gst_gl_test_src_checkers (v, 1);
}
struct BaseSrcImpl base;
GstGLShader *shader;
void
gst_gl_test_src_checkers2 (GstGLTestSrc * v, GstBuffer * buffer, int w, int h)
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)
{
gst_gl_test_src_checkers (v, 2);
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);
}
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_checkers4 (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_checkers (v, 4);
struct SrcShader base;
}
guint checker_width;
};
void
gst_gl_test_src_checkers8 (GstGLTestSrc * v, GstBuffer * buffer, int w, int h)
static gboolean
_src_checkers_init (gpointer impl, GstGLContext * context,
GstVideoInfo * v_info)
{
gst_gl_test_src_checkers (v, 8);
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;
}
static void
_src_checkers_free (gpointer impl)
{
struct SrcCheckers *src = impl;
if (!src)
return;
if (src->base.shader)
gst_object_unref (src->base.shader);
src->base.shader = NULL;
g_free (impl);
}
static gpointer
_src_checkers_new (GstGLTestSrc * test)
{
struct SrcCheckers *src = g_new0 (struct SrcCheckers, 1);
src->base.base.src = test;
return src;
}
#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)
{
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 gboolean
_src_snow_fill_bound_fbo (gpointer impl)
{
struct SrcShader *src = impl;
g_return_val_if_fail (src->base.context, FALSE);
g_return_val_if_fail (src->shader, FALSE);
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);
}
static void
_src_snow_free (gpointer impl)
{
struct SrcShader *src = impl;
if (!src)
return;
if (src->shader)
gst_object_unref (src->shader);
src->shader = NULL;
g_free (impl);
}
static gpointer
_src_snow_new (GstGLTestSrc * test)
{
struct SrcShader *src = g_new0 (struct SrcShader, 1);
src->base.src = test;
return src;
}
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,
};
/* *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* */
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;
}
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;
}
static gboolean
_src_mandelbrot_fill_bound_fbo (gpointer impl)
{
struct SrcShader *src = impl;
g_return_val_if_fail (src->base.context, FALSE);
g_return_val_if_fail (src->shader, FALSE);
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);
}
static void
_src_mandelbrot_free (gpointer impl)
{
struct SrcShader *src = impl;
if (!src)
return;
if (src->shader)
gst_object_unref (src->shader);
src->shader = NULL;
g_free (impl);
}
static gpointer
_src_mandelbrot_new (GstGLTestSrc * test)
{
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)
{
@ -456,3 +833,32 @@ 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;
}

View file

@ -22,37 +22,60 @@
#include <glib.h>
typedef struct _GstGLTestSrc GstGLTestSrc;
/**
* GstGLTestSrcPattern:
* @GST_GL_TEST_SRC_SMPTE: A standard SMPTE test pattern
* @GST_GL_TEST_SRC_SNOW: Random noise
* @GST_GL_TEST_SRC_BLACK: A black image
* @GST_GL_TEST_SRC_WHITE: A white image
* @GST_GL_TEST_SRC_RED: A red image
* @GST_GL_TEST_SRC_GREEN: A green image
* @GST_GL_TEST_SRC_BLUE: A blue image
* @GST_GL_TEST_SRC_CHECKERS1: Checkers pattern (1px)
* @GST_GL_TEST_SRC_CHECKERS2: Checkers pattern (2px)
* @GST_GL_TEST_SRC_CHECKERS4: Checkers pattern (4px)
* @GST_GL_TEST_SRC_CHECKERS8: Checkers pattern (8px)
* @GST_GL_TEST_SRC_CIRCULAR: Circular pattern
* @GST_GL_TEST_SRC_BLINK: Alternate between black and white
*
* The test pattern to produce.
*/
typedef enum {
GST_GL_TEST_SRC_SMPTE,
GST_GL_TEST_SRC_SNOW,
GST_GL_TEST_SRC_BLACK,
GST_GL_TEST_SRC_WHITE,
GST_GL_TEST_SRC_RED,
GST_GL_TEST_SRC_GREEN,
GST_GL_TEST_SRC_BLUE,
GST_GL_TEST_SRC_CHECKERS1,
GST_GL_TEST_SRC_CHECKERS2,
GST_GL_TEST_SRC_CHECKERS4,
GST_GL_TEST_SRC_CHECKERS8,
GST_GL_TEST_SRC_CIRCULAR,
GST_GL_TEST_SRC_BLINK,
GST_GL_TEST_SRC_MANDELBROT
} GstGLTestSrcPattern;
#include "gstgltestsrc.h"
struct vts_color_struct {
guint8 Y, U, V;
guint8 R, G, B;
guint8 A;
struct BaseSrcImpl {
GstGLTestSrc *src;
GstGLContext *context;
GstVideoInfo v_info;
};
void gst_gl_test_src_smpte (GstGLTestSrc * v,
GstBuffer *buffer, int w, int h);
void gst_gl_test_src_shader (GstGLTestSrc * v,
GstBuffer *buffer, int w, int h);
void gst_gl_test_src_black (GstGLTestSrc * v,
GstBuffer *buffer, int w, int h);
void gst_gl_test_src_white (GstGLTestSrc * v,
GstBuffer *buffer, int w, int h);
void gst_gl_test_src_red (GstGLTestSrc * v,
GstBuffer *buffer, int w, int h);
void gst_gl_test_src_green (GstGLTestSrc * v,
GstBuffer *buffer, int w, int h);
void gst_gl_test_src_blue (GstGLTestSrc * v,
GstBuffer *buffer, int w, int h);
void gst_gl_test_src_checkers1 (GstGLTestSrc * v,
GstBuffer *buffer, int w, int h);
void gst_gl_test_src_checkers2 (GstGLTestSrc * v,
GstBuffer *buffer, int w, int h);
void gst_gl_test_src_checkers4 (GstGLTestSrc * v,
GstBuffer *buffer, int w, int h);
void gst_gl_test_src_checkers8 (GstGLTestSrc * v,
GstBuffer *buffer, int w, int h);
void gst_gl_test_src_circular (GstGLTestSrc * v,
GstBuffer *buffer, int w, int h);
struct SrcFuncs
{
GstGLTestSrcPattern pattern;
gpointer (*new) (GstGLTestSrc * src);
gboolean (*init) (gpointer impl, GstGLContext * context, GstVideoInfo * v_info);
gboolean (*fill_bound_fbo) (gpointer impl);
void (*free) (gpointer impl);
};
const struct SrcFuncs * gst_gl_test_src_get_src_funcs_for_pattern (GstGLTestSrcPattern pattern);
#endif

View file

@ -228,162 +228,10 @@ gst_gl_test_src_fixate (GstBaseSrc * bsrc, GstCaps * caps)
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
@ -415,7 +263,7 @@ gst_gl_test_src_get_property (GObject * object, guint prop_id,
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);
@ -598,10 +446,10 @@ gst_gl_test_src_init_shader (GstGLTestSrc * gltestsrc)
{
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;
}
@ -627,13 +475,6 @@ gst_gl_test_src_fill (GstPushSrc * psrc, GstBuffer * buffer)
&& 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;
@ -641,15 +482,15 @@ gst_gl_test_src_fill (GstPushSrc * psrc, GstBuffer * buffer)
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)
@ -673,6 +514,12 @@ gst_gl_test_src_fill (GstPushSrc * psrc, GstBuffer * buffer)
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),
@ -888,12 +735,33 @@ static void
gst_gl_test_src_callback (gpointer stuff)
{
GstGLTestSrc *src = GST_GL_TEST_SRC (stuff);
const struct SrcFuncs *funcs;
src->make_image (src, src->buffer, GST_VIDEO_INFO_WIDTH (&src->out_info),
GST_VIDEO_INFO_HEIGHT (&src->out_info));
funcs = src->src_funcs;
gst_buffer_unref (src->buffer);
src->buffer = NULL;
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->gl_result = funcs->fill_bound_fbo (src->src_impl);
if (!src->gl_result)
GST_ERROR_OBJECT (src, "Failed to render the pattern");
}
static GstStateChangeReturn

View file

@ -28,6 +28,8 @@
#include <gst/gl/gl.h>
#include "gltestsrc.h"
G_BEGIN_DECLS
#define GST_TYPE_GL_TEST_SRC \
@ -41,41 +43,6 @@ G_BEGIN_DECLS
#define GST_IS_GL_TEST_SRC_CLASS(klass) \
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_GL_TEST_SRC))
/**
* GstGLTestSrcPattern:
* @GST_GL_TEST_SRC_SMPTE: A standard SMPTE test pattern
* @GST_GL_TEST_SRC_SNOW: Random noise
* @GST_GL_TEST_SRC_BLACK: A black image
* @GST_GL_TEST_SRC_WHITE: A white image
* @GST_GL_TEST_SRC_RED: A red image
* @GST_GL_TEST_SRC_GREEN: A green image
* @GST_GL_TEST_SRC_BLUE: A blue image
* @GST_GL_TEST_SRC_CHECKERS1: Checkers pattern (1px)
* @GST_GL_TEST_SRC_CHECKERS2: Checkers pattern (2px)
* @GST_GL_TEST_SRC_CHECKERS4: Checkers pattern (4px)
* @GST_GL_TEST_SRC_CHECKERS8: Checkers pattern (8px)
* @GST_GL_TEST_SRC_CIRCULAR: Circular pattern
* @GST_GL_TEST_SRC_BLINK: Alternate between black and white
*
* The test pattern to produce.
*/
typedef enum {
GST_GL_TEST_SRC_SMPTE,
GST_GL_TEST_SRC_SNOW,
GST_GL_TEST_SRC_BLACK,
GST_GL_TEST_SRC_WHITE,
GST_GL_TEST_SRC_RED,
GST_GL_TEST_SRC_GREEN,
GST_GL_TEST_SRC_BLUE,
GST_GL_TEST_SRC_CHECKERS1,
GST_GL_TEST_SRC_CHECKERS2,
GST_GL_TEST_SRC_CHECKERS4,
GST_GL_TEST_SRC_CHECKERS8,
GST_GL_TEST_SRC_CIRCULAR,
GST_GL_TEST_SRC_BLINK,
GST_GL_TEST_SRC_MANDELBROT
} GstGLTestSrcPattern;
typedef struct _GstGLTestSrc GstGLTestSrc;
typedef struct _GstGLTestSrcClass GstGLTestSrcClass;
@ -90,10 +57,10 @@ struct _GstGLTestSrc {
/*< private >*/
/* type of output */
GstGLTestSrcPattern pattern_type;
GstGLTestSrcPattern set_pattern;
GstGLTestSrcPattern active_pattern;
/* video state */
char *format_name;
GstVideoInfo out_info;
GLuint fbo;
@ -101,7 +68,6 @@ struct _GstGLTestSrc {
GstGLShader *shader;
GstBuffer* buffer;
GstBufferPool *pool;
GstGLDisplay *display;
@ -111,10 +77,9 @@ struct _GstGLTestSrc {
gint64 n_frames; /* total frames sent */
gboolean negotiated;
const gchar *vertex_src;
const gchar *fragment_src;
void (*make_image) (GstGLTestSrc* v, GstBuffer* buffer, gint w, gint h);
gboolean gl_result;
const struct SrcFuncs *src_funcs;
gpointer src_impl;
GstCaps *out_caps;
};