gl/window: add a dummy window class
authorMatthew Waters <ystreet00@gmail.com>
Mon, 17 Mar 2014 09:44:32 +0000 (10:44 +0100)
committerTim-Philipp Müller <tim@centricular.com>
Sat, 9 Dec 2017 19:31:34 +0000 (19:31 +0000)
Effective for the case where we have a platform that does not
require a native window.  We require a mainloop to run the GL
commands which is currently operated by GstGLWindow.

gst-libs/gst/gl/gstglwindow.c

index 966b370..3272d78 100644 (file)
@@ -86,6 +86,23 @@ struct _GstGLWindowPrivate
 
 static void gst_gl_window_finalize (GObject * object);
 
+typedef struct _GstGLDummyWindow
+{
+  GstGLWindow parent;
+
+  guintptr handle;
+
+  GMainContext *main_context;
+  GMainLoop *loop;
+} GstGLDummyWindow;
+
+typedef struct _GstGLDummyWindowCass
+{
+  GstGLWindowClass parent;
+} GstGLDummyWindowClass;
+
+GstGLDummyWindow *gst_gl_dummy_window_new (void);
+
 GQuark
 gst_gl_window_error_quark (void)
 {
@@ -163,10 +180,10 @@ gst_gl_window_new (GstGLDisplay * display)
 #endif
   if (!window) {
     /* subclass returned a NULL window */
-    GST_WARNING ("Could not create window. user specified %s",
-        user_choice ? user_choice : "(null)");
+    GST_WARNING ("Could not create window. user specified %s, creating dummy"
+        " window", user_choice ? user_choice : "(null)");
 
-    return NULL;
+    window = GST_GL_WINDOW (gst_gl_dummy_window_new ());
   }
 
   window->display = gst_object_ref (display);
@@ -536,3 +553,172 @@ gst_gl_window_get_context (GstGLWindow * window)
 
   return (GstGLContext *) g_weak_ref_get (&window->context_ref);
 }
+
+GType gst_gl_dummy_window_get_type (void);
+
+G_DEFINE_TYPE (GstGLDummyWindow, gst_gl_dummy_window, GST_GL_TYPE_WINDOW);
+
+static gboolean
+gst_gl_dummy_window_open (GstGLWindow * window, GError ** error)
+{
+  GstGLDummyWindow *dummy = (GstGLDummyWindow *) window;
+
+  dummy->main_context = g_main_context_new ();
+  dummy->loop = g_main_loop_new (dummy->main_context, FALSE);
+
+  return TRUE;
+}
+
+static void
+gst_gl_dummy_window_close (GstGLWindow * window)
+{
+  GstGLDummyWindow *dummy = (GstGLDummyWindow *) window;
+
+  g_main_loop_unref (dummy->loop);
+  g_main_context_unref (dummy->main_context);
+}
+
+static void
+gst_gl_dummy_window_quit (GstGLWindow * window)
+{
+  GstGLDummyWindow *dummy = (GstGLDummyWindow *) window;
+
+  g_main_loop_quit (dummy->loop);
+}
+
+static void
+gst_gl_dummy_window_run (GstGLWindow * window)
+{
+  GstGLDummyWindow *dummy = (GstGLDummyWindow *) window;
+
+  g_main_loop_run (dummy->loop);
+}
+
+typedef struct _GstGLMessage
+{
+  GstGLWindowCB callback;
+  gpointer data;
+  GDestroyNotify destroy;
+} GstGLMessage;
+
+static gboolean
+_run_message (GstGLMessage * message)
+{
+  if (message->callback)
+    message->callback (message->data);
+
+  if (message->destroy)
+    message->destroy (message->data);
+
+  g_slice_free (GstGLMessage, message);
+
+  return FALSE;
+}
+
+static void
+gst_gl_dummy_window_send_message_async (GstGLWindow * window,
+    GstGLWindowCB callback, gpointer data, GDestroyNotify destroy)
+{
+  GstGLDummyWindow *dummy;
+  GstGLMessage *message;
+
+  dummy = (GstGLDummyWindow *) window;
+  message = g_slice_new (GstGLMessage);
+
+  message->callback = callback;
+  message->data = data;
+  message->destroy = destroy;
+
+  g_main_context_invoke (dummy->main_context, (GSourceFunc) _run_message,
+      message);
+}
+
+static void
+gst_gl_dummy_window_set_window_handle (GstGLWindow * window, guintptr handle)
+{
+  GstGLDummyWindow *dummy = (GstGLDummyWindow *) window;
+
+  dummy->handle = handle;
+}
+
+static guintptr
+gst_gl_dummy_window_get_window_handle (GstGLWindow * window)
+{
+  GstGLDummyWindow *dummy = (GstGLDummyWindow *) window;
+
+  return (guintptr) dummy->handle;
+}
+
+struct draw
+{
+  GstGLDummyWindow *window;
+  guint width, height;
+};
+
+static void
+draw_cb (gpointer data)
+{
+  struct draw *draw_data = data;
+  GstGLDummyWindow *dummy = draw_data->window;
+  GstGLWindow *window = GST_GL_WINDOW (dummy);
+  GstGLContext *context = gst_gl_window_get_context (window);
+  GstGLContextClass *context_class = GST_GL_CONTEXT_GET_CLASS (context);
+
+  if (window->draw)
+    window->draw (window->draw_data);
+
+  context_class->swap_buffers (context);
+
+  gst_object_unref (context);
+}
+
+static void
+gst_gl_dummy_window_draw (GstGLWindow * window, guint width, guint height)
+{
+  struct draw draw_data;
+
+  draw_data.window = (GstGLDummyWindow *) window;
+  draw_data.width = width;
+  draw_data.height = height;
+
+  gst_gl_window_send_message (window, (GstGLWindowCB) draw_cb, &draw_data);
+}
+
+static guintptr
+gst_gl_dummy_window_get_display (GstGLWindow * window)
+{
+  return 0;
+}
+
+static void
+gst_gl_dummy_window_class_init (GstGLDummyWindowClass * klass)
+{
+  GstGLWindowClass *window_class = (GstGLWindowClass *) klass;
+
+  window_class->get_display =
+      GST_DEBUG_FUNCPTR (gst_gl_dummy_window_get_display);
+  window_class->get_window_handle =
+      GST_DEBUG_FUNCPTR (gst_gl_dummy_window_get_window_handle);
+  window_class->set_window_handle =
+      GST_DEBUG_FUNCPTR (gst_gl_dummy_window_set_window_handle);
+  window_class->draw_unlocked = GST_DEBUG_FUNCPTR (gst_gl_dummy_window_draw);
+  window_class->draw = GST_DEBUG_FUNCPTR (gst_gl_dummy_window_draw);
+  window_class->run = GST_DEBUG_FUNCPTR (gst_gl_dummy_window_run);
+  window_class->quit = GST_DEBUG_FUNCPTR (gst_gl_dummy_window_quit);
+  window_class->send_message_async =
+      GST_DEBUG_FUNCPTR (gst_gl_dummy_window_send_message_async);
+  window_class->open = GST_DEBUG_FUNCPTR (gst_gl_dummy_window_open);
+  window_class->close = GST_DEBUG_FUNCPTR (gst_gl_dummy_window_close);
+}
+
+static void
+gst_gl_dummy_window_init (GstGLDummyWindow * dummy)
+{
+  dummy->handle = 0;
+}
+
+GstGLDummyWindow *
+gst_gl_dummy_window_new (void)
+{
+  return g_object_new (gst_gl_dummy_window_get_type (), NULL);
+}