gltestsrc: implement snow pattern with GLSL.
authorLubosz Sarnecki <lubosz@gmail.com>
Thu, 21 Aug 2014 00:13:58 +0000 (02:13 +0200)
committerTim-Philipp Müller <tim@centricular.com>
Sat, 9 Dec 2017 19:31:46 +0000 (19:31 +0000)
https://bugzilla.gnome.org/show_bug.cgi?id=735131

ext/gl/gltestsrc.c
ext/gl/gltestsrc.h
ext/gl/gstgltestsrc.c
ext/gl/gstgltestsrc.h

index db28017..61a140f 100644 (file)
@@ -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
index f79ffee..102109e 100644 (file)
@@ -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);
index b64ebe1..fa55b0a 100644 (file)
@@ -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;
index 48e4d86..708a062 100644 (file)
@@ -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);
 };