
/* THIS IS ALL PSEUDO CODE */

/* the sink wraps the gl context that comes with the external API (clutter, etc ...)
 * and proposes it to the upstream gstgl element.
 * The gstgl element creates a new context when calling decide_allocation
 * and do sharing with the external gl context.
 * So that the textures that come from the gstgl element will be usable in
 * the external API.
 * Then if the external API directly uses GL API there is nothing special to do more.
 *
 * But for clutter we will need to call cogl_texture_new_from_foreign to wrap the
 * textures that come from the upstream gstgl element.
 * https://developer.gnome.org/cogl/stable/cogl-Textures.html#cogl-texture-new-from-foreign
 * For cairo we will have to call cairo_gl_surface_create_for_texture
 * http://cgit.freedesktop.org/cairo/tree/src/cairo-gl-surface.c#n658
 *
 * With webkit the mecanism will be a bit different, we will have to copy
 * the texture when calling the GstVideoGLTextureUpload callback:
 * http://trac.webkit.org/browser/trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.cpp#L334
 *
 * Also the following draft my be added into a new gstreamer interface GstGLBridge
 */

GstGLDisplay *sink->display = NULL;
GstGLContext *sink->context = NULL;

gboolean external_sink_wrap_gl_callback (gpointer data)
{
  GstExternalVideoSink *sink = data;

  EGLContext eglcontext = eglGetCurrentContext ();
  if (eglcontext == EGL_NO_CONTEXT) {
    g_cond_signal (cond);
    g_mutex_unlock (mutex);
    return FALSE;
  }

  EGLDisplay egldisplay = eglGetCurrentDisplay ();
  if (egldisplay == EGL_NO_DISPLAY) {
    g_cond_signal (cond);
    g_mutex_unlock (mutex);
    return FALSE;
  }

  sink->display = gst_gl_display_new (egldisplay);
  sink->context = gst_gl_context_new (eglcontext, sink->display);

  g_cond_signal (cond);
  g_mutex_unlock (mutex);
  return FALSE;
}

external_sink_propose_allocation (GstBaseSink * sink, GstQuery* query)
{
  /* call our callback in the thread where webkit gl context lives
   * here is an example for GLib API:
   * for webkit it's the default main context (g_main_context_default)
   * but if this is not the case for other external sinks we can use:
   * g_timeout_source_new / g_source_set_funcs / g_source_attach
   */
  g_mutex_lock(mutex);
  g_timeout_add_full (G_PRIORITY_DEFAULT, (interval) 0, external_sink_wrap_gl_callback, gst_object_ref (sink), gst_object_unref);
  g_cond_wait(cond, mutex);

  /* @"share": TRUE means that the upstream element has to create a new gl context
   * and share with the external context
   * It will be valid because when doing the sharing the new context has not
   * yet created any texture and it's also valid if the external context
   * has already created some textures */
  s = gst_structure_new ("GstVideoGLTextureUploadMeta", "gst.gl.GstGLContext", GST_GL_TYPE_CONTEXT, sink->context, "share", G_TYPE_BOOLEAN, TRUE, NULL);
  gst_query_add_allocation_meta (query, GST_VIDEO_GL_TEXTURE_UPLOAD_META_API_TYPE, s);
}

/* maybe the display needs to be retrieved sooner (= call external_sink_wrap_gl_callback sooner).
 * For example when going to ready state. Because the following query may be called
 * earlier then when calling propose_allocation */
external_sink_query (GstQuery * query)
{
  switch (GST_QUERY_TYPE (query)) {
    case GST_QUERY_CONTEXT:
      return gst_gl_handle_context_query (sink, query, &sink->display);
      break;
  }
}
