diff --git a/gst-libs/gst/gl/gstgldisplay.c b/gst-libs/gst/gl/gstgldisplay.c index 66e9dd6f6d..569bc41a30 100644 --- a/gst-libs/gst/gl/gstgldisplay.c +++ b/gst-libs/gst/gl/gstgldisplay.c @@ -75,9 +75,6 @@ static void gst_gl_display_finalize (GObject * object); gpointer gst_gl_display_thread_create_context (GstGLDisplay * display); void gst_gl_display_thread_destroy_context (GstGLDisplay * display); void gst_gl_display_thread_run_generic (GstGLDisplay * display); -#if GST_GL_HAVE_GLES2 -void gst_gl_display_thread_init_redisplay (GstGLDisplay * display); -#endif void gst_gl_display_thread_gen_fbo (GstGLDisplay * display); void gst_gl_display_thread_use_fbo (GstGLDisplay * display); void gst_gl_display_thread_use_fbo_v2 (GstGLDisplay * display); @@ -88,9 +85,6 @@ void gst_gl_display_thread_del_shader (GstGLDisplay * display); /* private methods */ void gst_gl_display_lock (GstGLDisplay * display); void gst_gl_display_unlock (GstGLDisplay * display); -void gst_gl_display_on_resize (GstGLDisplay * display, gint width, gint height); -void gst_gl_display_on_draw (GstGLDisplay * display); -void gst_gl_display_on_close (GstGLDisplay * display); void gst_gl_display_del_texture_thread (GstGLDisplay * display, GLuint * pTexture); @@ -103,29 +97,6 @@ void _del_shader (GstGLDisplay * display); void _use_fbo (GstGLDisplay * display); void _use_fbo_v2 (GstGLDisplay * display); -#if GST_GL_HAVE_GLES2 -/* *INDENT-OFF* */ -static const gchar *redisplay_vertex_shader_str_gles2 = - "attribute vec4 a_position; \n" - "attribute vec2 a_texCoord; \n" - "varying vec2 v_texCoord; \n" - "void main() \n" - "{ \n" - " gl_Position = a_position; \n" - " v_texCoord = a_texCoord; \n" - "} \n"; - -static const gchar *redisplay_fragment_shader_str_gles2 = - "precision mediump float; \n" - "varying vec2 v_texCoord; \n" - "uniform sampler2D s_texture; \n" - "void main() \n" - "{ \n" - " gl_FragColor = texture2D( s_texture, v_texCoord );\n" - "} \n"; -/* *INDENT-ON* */ -#endif - struct _GstGLDisplayPrivate { /* conditions */ @@ -136,18 +107,6 @@ struct _GstGLDisplayPrivate GstGLDisplayThreadFunc generic_callback; gpointer data; - /* action redisplay */ - GLuint redisplay_texture; - GLuint redisplay_texture_width; - GLuint redisplay_texture_height; -#if GST_GL_HAVE_GLES2 - GstGLShader *redisplay_shader; - gchar *redisplay_vertex_shader_str_gles2; - gchar *redisplay_fragment_shader_str_gles2; - GLint redisplay_attr_position_loc; - GLint redisplay_attr_texture_loc; -#endif - /* action gen and del texture */ GLuint gen_texture; GLuint gen_texture_width; @@ -541,14 +500,6 @@ gst_gl_display_thread_create_context (GstGLDisplay * display) goto failure; } - /* setup callbacks */ - gst_gl_window_set_resize_callback (display->gl_window, - GST_GL_WINDOW_RESIZE_CB (gst_gl_display_on_resize), display); - gst_gl_window_set_draw_callback (display->gl_window, - GST_GL_WINDOW_CB (gst_gl_display_on_draw), display); - gst_gl_window_set_close_callback (display->gl_window, - GST_GL_WINDOW_CB (gst_gl_display_on_close), display); - g_cond_signal (&display->priv->cond_create_context); display->isAlive = TRUE; @@ -590,13 +541,6 @@ failure: void gst_gl_display_thread_destroy_context (GstGLDisplay * display) { -#if GST_GL_HAVE_GLES2 - if (display->priv->redisplay_shader) { - g_object_unref (G_OBJECT (display->priv->redisplay_shader)); - display->priv->redisplay_shader = NULL; - } -#endif - GST_INFO ("Context destroyed"); } @@ -610,36 +554,6 @@ gst_gl_display_thread_run_generic (GstGLDisplay * display) display->priv->generic_callback (display, display->priv->data); } -#if GST_GL_HAVE_GLES2 -/* Called in the gl thread */ -void -gst_gl_display_thread_init_redisplay (GstGLDisplay * display) -{ - GError *error = NULL; - display->priv->redisplay_shader = gst_gl_shader_new (display); - - gst_gl_shader_set_vertex_source (display->priv->redisplay_shader, - redisplay_vertex_shader_str_gles2); - gst_gl_shader_set_fragment_source (display->priv->redisplay_shader, - redisplay_fragment_shader_str_gles2); - - gst_gl_shader_compile (display->priv->redisplay_shader, &error); - if (error) { - gst_gl_display_set_error (display, "%s", error->message); - g_error_free (error); - error = NULL; - gst_gl_display_clear_shader (display); - } else { - display->priv->redisplay_attr_position_loc = - gst_gl_shader_get_attribute_location (display->priv->redisplay_shader, - "a_position"); - display->priv->redisplay_attr_texture_loc = - gst_gl_shader_get_attribute_location (display->priv->redisplay_shader, - "a_texCoord"); - } -} -#endif - void _gen_fbo (GstGLDisplay * display) { @@ -932,168 +846,6 @@ _del_shader (GstGLDisplay * display) //---------------------- BEGIN PRIVATE ----------------------- //------------------------------------------------------------ - -void -gst_gl_display_on_resize (GstGLDisplay * display, gint width, gint height) -{ - const GstGLFuncs *gl = display->gl_vtable; - - GST_TRACE ("GL Window resized to %ux%u", width, height); - - //check if a client reshape callback is registered - if (display->priv->clientReshapeCallback) - display->priv->clientReshapeCallback (width, height, - display->priv->client_data); - - //default reshape - else { - if (display->keep_aspect_ratio) { - GstVideoRectangle src, dst, result; - - src.x = 0; - src.y = 0; - src.w = display->priv->redisplay_texture_width; - src.h = display->priv->redisplay_texture_height; - - dst.x = 0; - dst.y = 0; - dst.w = width; - dst.h = height; - - gst_video_sink_center_rect (src, dst, &result, TRUE); - gl->Viewport (result.x, result.y, result.w, result.h); - } else { - gl->Viewport (0, 0, width, height); - } -#if GST_GL_HAVE_OPENGL - if (USING_OPENGL (display)) { - gl->MatrixMode (GL_PROJECTION); - gl->LoadIdentity (); - gluOrtho2D (0, width, 0, height); - gl->MatrixMode (GL_MODELVIEW); - } -#endif - } -} - - -void -gst_gl_display_on_draw (GstGLDisplay * display) -{ - const GstGLFuncs *gl = display->gl_vtable; - - /* check if texture is ready for being drawn */ - if (!display->priv->redisplay_texture) - return; - /* opengl scene */ - GST_TRACE ("drawing texture:%u", display->priv->redisplay_texture); - - /* make sure that the environnement is clean */ - gst_gl_display_clear_shader (display); - -#if GST_GL_HAVE_OPENGL - if (USING_OPENGL (display)) - gl->Disable (GL_TEXTURE_RECTANGLE_ARB); -#endif - - gl->BindTexture (GL_TEXTURE_RECTANGLE_ARB, 0); - - /* check if a client draw callback is registered */ - if (display->priv->clientDrawCallback) { - gboolean doRedisplay = - display->priv->clientDrawCallback (display->priv->redisplay_texture, - display->priv->redisplay_texture_width, - display->priv->redisplay_texture_height, - display->priv->client_data); - - if (doRedisplay && display->gl_window) - gst_gl_window_draw_unlocked (display->gl_window, - display->priv->redisplay_texture_width, - display->priv->redisplay_texture_height); - } - /* default opengl scene */ - else { -#if GST_GL_HAVE_OPENGL - if (USING_OPENGL (display)) { - gfloat verts[8] = { 1.0f, 1.0f, - -1.0f, 1.0f, - -1.0f, -1.0f, - 1.0f, -1.0f - }; - gint texcoords[8] = { display->priv->redisplay_texture_width, 0, - 0, 0, - 0, display->priv->redisplay_texture_height, - display->priv->redisplay_texture_width, - display->priv->redisplay_texture_height - }; - gl->Clear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - gl->MatrixMode (GL_PROJECTION); - gl->LoadIdentity (); - - gl->Enable (GL_TEXTURE_RECTANGLE_ARB); - gl->BindTexture (GL_TEXTURE_RECTANGLE_ARB, - display->priv->redisplay_texture); - - gl->EnableClientState (GL_VERTEX_ARRAY); - gl->EnableClientState (GL_TEXTURE_COORD_ARRAY); - gl->VertexPointer (2, GL_FLOAT, 0, &verts); - gl->TexCoordPointer (2, GL_INT, 0, &texcoords); - - gl->DrawArrays (GL_TRIANGLE_FAN, 0, 4); - - gl->DisableClientState (GL_VERTEX_ARRAY); - gl->DisableClientState (GL_TEXTURE_COORD_ARRAY); - - gl->Disable (GL_TEXTURE_RECTANGLE_ARB); - } -#endif -#if GST_GL_HAVE_GLES2 - if (USING_GLES2 (display)) { - const GLfloat vVertices[] = { 1.0f, 1.0f, 0.0f, - 1.0f, 0.0f, - -1.0f, 1.0f, 0.0f, - 0.0f, 0.0f, - -1.0f, -1.0f, 0.0f, - 0.0f, 1.0f, - 1.0f, -1.0f, 0.0f, - 1.0f, 1.0f - }; - - GLushort indices[] = { 0, 1, 2, 0, 2, 3 }; - - gl->Clear (GL_COLOR_BUFFER_BIT); - - gst_gl_shader_use (display->priv->redisplay_shader); - - /* Load the vertex position */ - gl->VertexAttribPointer (display->priv->redisplay_attr_position_loc, 3, - GL_FLOAT, GL_FALSE, 5 * sizeof (GLfloat), vVertices); - - /* Load the texture coordinate */ - gl->VertexAttribPointer (display->priv->redisplay_attr_texture_loc, 2, - GL_FLOAT, GL_FALSE, 5 * sizeof (GLfloat), &vVertices[3]); - - gl->EnableVertexAttribArray (display->priv->redisplay_attr_position_loc); - gl->EnableVertexAttribArray (display->priv->redisplay_attr_texture_loc); - - gl->ActiveTexture (GL_TEXTURE0); - gl->BindTexture (GL_TEXTURE_2D, display->priv->redisplay_texture); - gst_gl_shader_set_uniform_1i (display->priv->redisplay_shader, - "s_texture", 0); - - gl->DrawElements (GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices); - } -#endif - } /* end default opengl scene */ -} - -void -gst_gl_display_on_close (GstGLDisplay * display) -{ - gst_gl_display_set_error (display, "Output window was closed"); -} - void gst_gl_display_gen_texture_window_cb (GstGLDisplay * display) { @@ -1289,42 +1041,6 @@ gst_gl_display_create_context (GstGLDisplay * display, return isAlive; } - -/* Called by the glimagesink element */ -gboolean -gst_gl_display_redisplay (GstGLDisplay * display, GLuint texture, - gint gl_width, gint gl_height, gint window_width, gint window_height, - gboolean keep_aspect_ratio) -{ - gboolean isAlive; - - gst_gl_display_lock (display); - if (display->isAlive) { - -#if GST_GL_HAVE_GLES2 - if (USING_GLES2 (display)) { - if (!display->priv->redisplay_shader) { - gst_gl_window_send_message (display->gl_window, - GST_GL_WINDOW_CB (gst_gl_display_thread_init_redisplay), display); - } - } -#endif - - if (texture) { - display->priv->redisplay_texture = texture; - display->priv->redisplay_texture_width = gl_width; - display->priv->redisplay_texture_height = gl_height; - } - display->keep_aspect_ratio = keep_aspect_ratio; - if (display->gl_window) - gst_gl_window_draw (display->gl_window, window_width, window_height); - } - isAlive = display->isAlive; - gst_gl_display_unlock (display); - - return isAlive; -} - void gst_gl_display_thread_add (GstGLDisplay * display, GstGLDisplayThreadFunc func, gpointer data) @@ -1337,7 +1053,6 @@ gst_gl_display_thread_add (GstGLDisplay * display, gst_gl_display_unlock (display); } -/* Called by gst_gl_buffer_new */ void gst_gl_display_gen_texture (GstGLDisplay * display, GLuint * pTexture, GstVideoFormat v_format, GLint width, GLint height) @@ -1357,8 +1072,6 @@ gst_gl_display_gen_texture (GstGLDisplay * display, GLuint * pTexture, gst_gl_display_unlock (display); } - -/* Called by gst_gl_buffer_finalize */ void gst_gl_display_del_texture (GstGLDisplay * display, GLuint * pTexture) { @@ -1369,7 +1082,6 @@ gst_gl_display_del_texture (GstGLDisplay * display, GLuint * pTexture) gst_gl_display_unlock (display); } -/* Called by gltestsrc and glfilter */ gboolean gst_gl_display_gen_fbo (GstGLDisplay * display, gint width, gint height, GLuint * fbo, GLuint * depthbuffer) @@ -1516,44 +1228,6 @@ gst_gl_display_del_shader (GstGLDisplay * display, GstGLShader * shader) gst_gl_display_unlock (display); } - -/* Called by the glimagesink */ -void -gst_gl_display_set_window_id (GstGLDisplay * display, guintptr window_id) -{ - gst_gl_display_lock (display); - gst_gl_window_set_window_handle (display->gl_window, window_id); - gst_gl_display_unlock (display); -} - - -/* Called by the glimagesink */ -void -gst_gl_display_set_client_reshape_callback (GstGLDisplay * display, CRCB cb) -{ - gst_gl_display_lock (display); - display->priv->clientReshapeCallback = cb; - gst_gl_display_unlock (display); -} - - -/* Called by the glimagesink */ -void -gst_gl_display_set_client_draw_callback (GstGLDisplay * display, CDCB cb) -{ - gst_gl_display_lock (display); - display->priv->clientDrawCallback = cb; - gst_gl_display_unlock (display); -} - -void -gst_gl_display_set_client_data (GstGLDisplay * display, gpointer data) -{ - gst_gl_display_lock (display); - display->priv->client_data = data; - gst_gl_display_unlock (display); -} - gulong gst_gl_display_get_internal_gl_context (GstGLDisplay * display) { diff --git a/gst-libs/gst/gl/gstgldisplay.h b/gst-libs/gst/gl/gstgldisplay.h index 5cabac9534..a8e5794dfc 100644 --- a/gst-libs/gst/gl/gstgldisplay.h +++ b/gst-libs/gst/gl/gstgldisplay.h @@ -179,9 +179,6 @@ GstGLDisplay *gst_gl_display_new (void); gboolean gst_gl_display_create_context (GstGLDisplay * display, gulong external_gl_context); -gboolean gst_gl_display_redisplay (GstGLDisplay * display, GLuint texture, - gint gl_width, gint gl_height, gint window_width, gint window_height, - gboolean keep_aspect_ratio); void gst_gl_display_thread_add (GstGLDisplay * display, GstGLDisplayThreadFunc func, gpointer data); @@ -211,12 +208,6 @@ gboolean gst_gl_display_gen_shader (GstGLDisplay * display, const gchar * shader_fragment_source, GstGLShader ** shader); void gst_gl_display_del_shader (GstGLDisplay * display, GstGLShader * shader); -void gst_gl_display_set_window_id (GstGLDisplay * display, guintptr window_id); -void gst_gl_display_set_client_reshape_callback (GstGLDisplay * display, - CRCB cb); -void gst_gl_display_set_client_draw_callback (GstGLDisplay * display, CDCB cb); -void gst_gl_display_set_client_data (GstGLDisplay * display, gpointer data); - gulong gst_gl_display_get_internal_gl_context (GstGLDisplay * display); void gst_gl_display_activate_gl_context (GstGLDisplay * display, gboolean activate); diff --git a/gst/gl/gstglimagesink.c b/gst/gl/gstglimagesink.c index 8b95620ab3..dc81ff9c46 100644 --- a/gst/gl/gstglimagesink.c +++ b/gst/gl/gstglimagesink.c @@ -90,6 +90,23 @@ GST_DEBUG_CATEGORY (gst_debug_glimage_sink); #define GST_CAT_DEFAULT gst_debug_glimage_sink +#define USING_OPENGL(display) (display->gl_api & GST_GL_API_OPENGL) +#define USING_OPENGL3(display) (display->gl_api & GST_GL_API_OPENGL3) +#define USING_GLES(display) (display->gl_api & GST_GL_API_GLES) +#define USING_GLES2(display) (display->gl_api & GST_GL_API_GLES2) +#define USING_GLES3(display) (display->gl_api & GST_GL_API_GLES3) + +#if GST_GL_HAVE_GLES2 +static void gst_glimage_sink_thread_init_redisplay (GstGLDisplay * display); +#endif +static void gst_glimage_sink_on_close (GstGLImageSink * gl_sink); +static void gst_glimage_sink_on_resize (GstGLImageSink * gl_sink, gint width, + gint height); +static void gst_glimage_sink_on_draw (GstGLImageSink * gl_sink); +static gboolean gst_glimage_sink_redisplay (GstGLImageSink * gl_sink, + GLuint texture, gint gl_width, gint gl_height, gint window_width, + gint window_height, gboolean keep_aspect_ratio); + static void gst_glimage_sink_finalize (GObject * object); static void gst_glimage_sink_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * param_spec); @@ -115,6 +132,30 @@ static void gst_glimage_sink_set_window_handle (GstVideoOverlay * overlay, guintptr id); static void gst_glimage_sink_expose (GstVideoOverlay * overlay); + +#if GST_GL_HAVE_GLES2 +/* *INDENT-OFF* */ +static const gchar *redisplay_vertex_shader_str_gles2 = + "attribute vec4 a_position; \n" + "attribute vec2 a_texCoord; \n" + "varying vec2 v_texCoord; \n" + "void main() \n" + "{ \n" + " gl_Position = a_position; \n" + " v_texCoord = a_texCoord; \n" + "} \n"; + +static const gchar *redisplay_fragment_shader_str_gles2 = + "precision mediump float; \n" + "varying vec2 v_texCoord; \n" + "uniform sampler2D s_texture; \n" + "void main() \n" + "{ \n" + " gl_FragColor = texture2D( s_texture, v_texCoord );\n" + "} \n"; +/* *INDENT-ON* */ +#endif + static GstStaticPadTemplate gst_glimage_sink_template = GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, @@ -390,6 +431,14 @@ gst_glimage_sink_change_state (GstElement * element, GstStateChange transition) return GST_STATE_CHANGE_FAILURE; } + + /* setup callbacks */ + gst_gl_window_set_resize_callback (glimage_sink->display->gl_window, + GST_GL_WINDOW_RESIZE_CB (gst_glimage_sink_on_resize), glimage_sink); + gst_gl_window_set_draw_callback (glimage_sink->display->gl_window, + GST_GL_WINDOW_CB (gst_glimage_sink_on_draw), glimage_sink); + gst_gl_window_set_close_callback (glimage_sink->display->gl_window, + GST_GL_WINDOW_CB (gst_glimage_sink_on_close), glimage_sink); } break; case GST_STATE_CHANGE_PAUSED_TO_PLAYING: @@ -489,15 +538,6 @@ gst_glimage_sink_set_caps (GstBaseSink * bsink, GstCaps * caps) gst_gl_upload_init_format (glimage_sink->upload, GST_VIDEO_INFO_FORMAT (&vinfo), width, height, width, height); - gst_gl_display_set_client_reshape_callback (glimage_sink->display, - glimage_sink->clientReshapeCallback); - - gst_gl_display_set_client_draw_callback (glimage_sink->display, - glimage_sink->clientDrawCallback); - - gst_gl_display_set_client_data (glimage_sink->display, - glimage_sink->client_data); - par_n = GST_VIDEO_INFO_PAR_N (&vinfo); par_d = GST_VIDEO_INFO_PAR_D (&vinfo); @@ -588,7 +628,7 @@ gst_glimage_sink_render (GstBaseSink * bsink, GstBuffer * buf) if (glimage_sink->window_id != glimage_sink->new_window_id) { glimage_sink->window_id = glimage_sink->new_window_id; - gst_gl_display_set_window_id (glimage_sink->display, + gst_gl_window_set_window_handle (glimage_sink->display->gl_window, glimage_sink->window_id); } //the buffer is cleared when an other comes in @@ -605,7 +645,7 @@ gst_glimage_sink_render (GstBaseSink * bsink, GstBuffer * buf) GST_VIDEO_SINK_HEIGHT (glimage_sink)); //redisplay opengl scene - if (!gst_gl_display_redisplay (glimage_sink->display, + if (!gst_glimage_sink_redisplay (glimage_sink, tex_id, GST_VIDEO_INFO_WIDTH (&glimage_sink->info), GST_VIDEO_INFO_HEIGHT (&glimage_sink->info), GST_VIDEO_SINK_WIDTH (glimage_sink), @@ -657,16 +697,16 @@ gst_glimage_sink_expose (GstVideoOverlay * overlay) { GstGLImageSink *glimage_sink = GST_GLIMAGE_SINK (overlay); - //redisplay opengl scene + /* redisplay opengl scene */ if (glimage_sink->display && glimage_sink->window_id) { if (glimage_sink->window_id != glimage_sink->new_window_id) { glimage_sink->window_id = glimage_sink->new_window_id; - gst_gl_display_set_window_id (glimage_sink->display, + gst_gl_window_set_window_handle (glimage_sink->display->gl_window, glimage_sink->window_id); } - gst_gl_display_redisplay (glimage_sink->display, 0, 0, 0, 0, 0, + gst_glimage_sink_redisplay (glimage_sink, 0, 0, 0, 0, 0, glimage_sink->keep_aspect_ratio); } } @@ -749,3 +789,237 @@ config_failed: return FALSE; } } + +#if GST_GL_HAVE_GLES2 +/* Called in the gl thread */ +static void +gst_gl_display_thread_init_redisplay (GstGLImageSink * gl_sink) +{ + GError *error = NULL; + gl_sink->redisplay_shader = gst_gl_shader_new (gl_sink->display); + + gst_gl_shader_set_vertex_source (gl_sink->redisplay_shader, + redisplay_vertex_shader_str_gles2); + gst_gl_shader_set_fragment_source (gl_sink->redisplay_shader, + redisplay_fragment_shader_str_gles2); + + gst_gl_shader_compile (display->gl_sink->redisplay_shader, &error); + if (error) { + gst_gl_display_set_error (gl_sink->display, "%s", error->message); + g_error_free (error); + error = NULL; + gst_gl_display_clear_shader (gl_sink->display); + } else { + gl_sink->redisplay_attr_position_loc = + gst_gl_shader_get_attribute_location (display->priv->redisplay_shader, + "a_position"); + gl_sink->redisplay_attr_texture_loc = + gst_gl_shader_get_attribute_location (display->priv->redisplay_shader, + "a_texCoord"); + } +} +#endif + +static void +gst_glimage_sink_on_resize (GstGLImageSink * gl_sink, gint width, gint height) +{ + const GstGLFuncs *gl = gl_sink->display->gl_vtable; + + GST_TRACE ("GL Window resized to %ux%u", width, height); + + /* check if a client reshape callback is registered */ + if (gl_sink->clientReshapeCallback) + gl_sink->clientReshapeCallback (width, height, gl_sink->client_data); + + /* default reshape */ + else { + if (gl_sink->keep_aspect_ratio) { + GstVideoRectangle src, dst, result; + + src.x = 0; + src.y = 0; + src.w = gl_sink->redisplay_texture_width; + src.h = gl_sink->redisplay_texture_height; + + dst.x = 0; + dst.y = 0; + dst.w = width; + dst.h = height; + + gst_video_sink_center_rect (src, dst, &result, TRUE); + gl->Viewport (result.x, result.y, result.w, result.h); + } else { + gl->Viewport (0, 0, width, height); + } +#if GST_GL_HAVE_OPENGL + if (USING_OPENGL (gl_sink->display)) { + gl->MatrixMode (GL_PROJECTION); + gl->LoadIdentity (); + gluOrtho2D (0, width, 0, height); + gl->MatrixMode (GL_MODELVIEW); + } +#endif + } +} + + +static void +gst_glimage_sink_on_draw (GstGLImageSink * gl_sink) +{ + const GstGLFuncs *gl = gl_sink->display->gl_vtable; + + /* check if texture is ready for being drawn */ + if (!gl_sink->redisplay_texture) + return; + /* opengl scene */ + GST_TRACE ("redrawing texture:%u", gl_sink->redisplay_texture); + + /* make sure that the environnement is clean */ + gst_gl_display_clear_shader (gl_sink->display); + +#if GST_GL_HAVE_OPENGL + if (USING_OPENGL (gl_sink->display)) + gl->Disable (GL_TEXTURE_RECTANGLE_ARB); +#endif + + gl->BindTexture (GL_TEXTURE_RECTANGLE_ARB, 0); + + /* check if a client draw callback is registered */ + if (gl_sink->clientDrawCallback) { + gboolean doRedisplay = + gl_sink->clientDrawCallback (gl_sink->redisplay_texture, + gl_sink->redisplay_texture_width, + gl_sink->redisplay_texture_height, + gl_sink->client_data); + + if (doRedisplay && gl_sink->display->gl_window) + gst_gl_window_draw_unlocked (gl_sink->display->gl_window, + gl_sink->redisplay_texture_width, gl_sink->redisplay_texture_height); + } + /* default opengl scene */ + else { +#if GST_GL_HAVE_OPENGL + if (USING_OPENGL (gl_sink->display)) { + gfloat verts[8] = { 1.0f, 1.0f, + -1.0f, 1.0f, + -1.0f, -1.0f, + 1.0f, -1.0f + }; + gint texcoords[8] = { gl_sink->redisplay_texture_width, 0, + 0, 0, + 0, gl_sink->redisplay_texture_height, + gl_sink->redisplay_texture_width, + gl_sink->redisplay_texture_height + }; + gl->Clear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + gl->MatrixMode (GL_PROJECTION); + gl->LoadIdentity (); + + gl->Enable (GL_TEXTURE_RECTANGLE_ARB); + gl->BindTexture (GL_TEXTURE_RECTANGLE_ARB, gl_sink->redisplay_texture); + + gl->EnableClientState (GL_VERTEX_ARRAY); + gl->EnableClientState (GL_TEXTURE_COORD_ARRAY); + gl->VertexPointer (2, GL_FLOAT, 0, &verts); + gl->TexCoordPointer (2, GL_INT, 0, &texcoords); + + gl->DrawArrays (GL_TRIANGLE_FAN, 0, 4); + + gl->DisableClientState (GL_VERTEX_ARRAY); + gl->DisableClientState (GL_TEXTURE_COORD_ARRAY); + + gl->Disable (GL_TEXTURE_RECTANGLE_ARB); + } +#endif +#if GST_GL_HAVE_GLES2 + if (USING_GLES2 (display)) { + const GLfloat vVertices[] = { 1.0f, 1.0f, 0.0f, + 1.0f, 0.0f, + -1.0f, 1.0f, 0.0f, + 0.0f, 0.0f, + -1.0f, -1.0f, 0.0f, + 0.0f, 1.0f, + 1.0f, -1.0f, 0.0f, + 1.0f, 1.0f + }; + + GLushort indices[] = { 0, 1, 2, 0, 2, 3 }; + + gl->Clear (GL_COLOR_BUFFER_BIT); + + gst_gl_shader_use (gl_sink->redisplay_shader); + + /* Load the vertex position */ + gl->VertexAttribPointer (display->priv->redisplay_attr_position_loc, 3, + GL_FLOAT, GL_FALSE, 5 * sizeof (GLfloat), vVertices); + + /* Load the texture coordinate */ + gl->VertexAttribPointer (display->priv->redisplay_attr_texture_loc, 2, + GL_FLOAT, GL_FALSE, 5 * sizeof (GLfloat), &vVertices[3]); + + gl->EnableVertexAttribArray (display->priv->redisplay_attr_position_loc); + gl->EnableVertexAttribArray (display->priv->redisplay_attr_texture_loc); + + gl->ActiveTexture (GL_TEXTURE0); + gl->BindTexture (GL_TEXTURE_2D, display->priv->redisplay_texture); + gst_gl_shader_set_uniform_1i (display->priv->redisplay_shader, + "s_texture", 0); + + gl->DrawElements (GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices); + } +#endif + } /* end default opengl scene */ +} + +static void +gst_glimage_sink_on_close (GstGLImageSink * gl_sink) +{ + gst_gl_display_set_error (gl_sink->display, "Output window was closed"); +} + +static gboolean +gst_glimage_sink_redisplay (GstGLImageSink * gl_sink, GLuint texture, + gint gl_width, gint gl_height, gint window_width, gint window_height, + gboolean keep_aspect_ratio) +{ + gboolean isAlive; + + gst_gl_display_lock (gl_sink->display); + if (gl_sink->display->isAlive) { + +#if GST_GL_HAVE_GLES2 + if (USING_GLES2 (gl_sink->display)) { + if (!gl_sink->redisplay_shader) { + gst_gl_window_send_message (display->gl_window, + GST_GL_WINDOW_CB (gst_glimage_sink_thread_init_redisplay), display); + } + } +#endif + + if (texture) { + gl_sink->redisplay_texture = texture; + gl_sink->redisplay_texture_width = gl_width; + gl_sink->redisplay_texture_height = gl_height; + } + gl_sink->keep_aspect_ratio = keep_aspect_ratio; + if (gl_sink->display->gl_window) + gst_gl_window_draw (gl_sink->display->gl_window, window_width, + window_height); + } + isAlive = gl_sink->display->isAlive; + gst_gl_display_unlock (gl_sink->display); + + return isAlive; +} + +void +temp (GstGLImageSink * gl_sink) +{ +#if GST_GL_HAVE_GLES2 + if (gl_sink->redisplay_shader) { + g_object_unref (G_OBJECT (gl_sink->redisplay_shader)); + gl_sink->redisplay_shader = NULL; + } +#endif +} diff --git a/gst/gl/gstglimagesink.h b/gst/gl/gstglimagesink.h index 27a0f7724c..2a97bf6067 100644 --- a/gst/gl/gstglimagesink.h +++ b/gst/gl/gstglimagesink.h @@ -28,6 +28,7 @@ #include #include "gstglbufferpool.h" +#include G_BEGIN_DECLS @@ -73,6 +74,19 @@ struct _GstGLImageSink GValue *par; GstBufferPool *pool; + + /* action redisplay */ + GLuint redisplay_texture; + GLuint redisplay_texture_width; + GLuint redisplay_texture_height; +#if GST_GL_HAVE_GLES2 + GstGLShader *redisplay_shader; + gchar *redisplay_vertex_shader_str_gles2; + gchar *redisplay_fragment_shader_str_gles2; + GLint redisplay_attr_position_loc; + GLint redisplay_attr_texture_loc; +#endif + }; struct _GstGLImageSinkClass