diff --git a/ext/gl/gltestsrc.c b/ext/gl/gltestsrc.c index db280176ab..61a140f294 100644 --- a/ext/gl/gltestsrc.c +++ b/ext/gl/gltestsrc.c @@ -189,29 +189,78 @@ gst_gl_test_src_smpte (GstGLTestSrc * v, GstBuffer * buffer, int w, int h) } void -gst_gl_test_src_snow (GstGLTestSrc * v, GstBuffer * buffer, int w, int h) +gst_gl_test_src_shader (GstGLTestSrc * v, GstBuffer * buffer, int w, int h) { -#if GST_GL_HAVE_OPENGL - if (gst_gl_context_get_gl_api (v->context) & GST_GL_API_OPENGL) { - glClearColor (0.0, 0.0, 0.0, 1.0); - glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - glMatrixMode (GL_PROJECTION); - glLoadIdentity (); + GstGLFuncs *gl = v->context->gl_vtable; - glMatrixMode (GL_MODELVIEW); - glLoadIdentity (); +/* *INDENT-OFF* */ - /* FIXME snow requires a fragment shader. Please write. */ - glColor4f (0.5, 0.5, 0.5, 1.0); - glBegin (GL_QUADS); - glVertex3f (-1.0 + 2.0 * (0.0), -1.0 + 2.0 * 1, 0); - glVertex3f (-1.0 + 2.0 * (1.0), -1.0 + 2.0 * 1, 0); - glVertex3f (-1.0 + 2.0 * (1.0), -1.0 + 2.0 * (0.0), 0); - glVertex3f (-1.0 + 2.0 * (0.0), -1.0 + 2.0 * (0.0), 0); - glEnd (); + 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, + }; + + 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, + }; + + 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 = 0; + GLint attr_uv_loc = 0; + + if (gst_gl_context_get_gl_api (v->context)) { + + gst_gl_context_clear_shader (v->context); + gl->BindTexture (GL_TEXTURE_2D, 0); + gl->Disable (GL_TEXTURE_2D); + + 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); } -#endif } static void diff --git a/ext/gl/gltestsrc.h b/ext/gl/gltestsrc.h index f79ffeef51..102109e101 100644 --- a/ext/gl/gltestsrc.h +++ b/ext/gl/gltestsrc.h @@ -32,7 +32,7 @@ struct vts_color_struct { void gst_gl_test_src_smpte (GstGLTestSrc * v, GstBuffer *buffer, int w, int h); -void gst_gl_test_src_snow (GstGLTestSrc * v, +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); diff --git a/ext/gl/gstgltestsrc.c b/ext/gl/gstgltestsrc.c index b64ebe1558..fa55b0ae57 100644 --- a/ext/gl/gstgltestsrc.c +++ b/ext/gl/gstgltestsrc.c @@ -111,6 +111,8 @@ static gboolean gst_gl_test_src_decide_allocation (GstBaseSrc * basesrc, static void gst_gl_test_src_callback (gpointer stuff); +static gboolean gst_gl_test_src_init_shader (GstGLTestSrc * gltestsrc); + #define GST_TYPE_GL_TEST_SRC_PATTERN (gst_gl_test_src_pattern_get_type ()) static GType gst_gl_test_src_pattern_get_type (void) @@ -227,6 +229,27 @@ 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); \ + }"; + static void gst_gl_test_src_set_pattern (GstGLTestSrc * gltestsrc, gint pattern_type) { @@ -239,7 +262,9 @@ gst_gl_test_src_set_pattern (GstGLTestSrc * gltestsrc, gint pattern_type) gltestsrc->make_image = gst_gl_test_src_smpte; break; case GST_GL_TEST_SRC_SNOW: - gltestsrc->make_image = 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; @@ -446,6 +471,19 @@ gst_gl_test_src_is_seekable (GstBaseSrc * psrc) return TRUE; } +static gboolean +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); + } + return TRUE; +} + static GstFlowReturn gst_gl_test_src_fill (GstPushSrc * psrc, GstBuffer * buffer) { @@ -691,6 +729,8 @@ gst_gl_test_src_decide_allocation (GstBaseSrc * basesrc, GstQuery * query) else gst_query_add_allocation_pool (query, pool, size, min, max); + gst_gl_test_src_init_shader (src); + gst_object_unref (pool); return TRUE; diff --git a/ext/gl/gstgltestsrc.h b/ext/gl/gstgltestsrc.h index 48e4d8644c..708a062461 100644 --- a/ext/gl/gstgltestsrc.h +++ b/ext/gl/gstgltestsrc.h @@ -98,6 +98,8 @@ struct _GstGLTestSrc { GLuint fbo; GLuint depthbuffer; + GstGLShader *shader; + GstBuffer* buffer; GstBufferPool *pool; @@ -111,6 +113,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); };