gl/window: add a dummy window class

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.
This commit is contained in:
Matthew Waters 2014-03-17 10:44:32 +01:00
parent aaa7cfc9fc
commit b67af0e314

View file

@ -86,6 +86,23 @@ struct _GstGLWindowPrivate
static void gst_gl_window_finalize (GObject * object); 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 GQuark
gst_gl_window_error_quark (void) gst_gl_window_error_quark (void)
{ {
@ -163,10 +180,10 @@ gst_gl_window_new (GstGLDisplay * display)
#endif #endif
if (!window) { if (!window) {
/* subclass returned a NULL window */ /* subclass returned a NULL window */
GST_WARNING ("Could not create window. user specified %s", GST_WARNING ("Could not create window. user specified %s, creating dummy"
user_choice ? user_choice : "(null)"); " window", user_choice ? user_choice : "(null)");
return NULL; window = GST_GL_WINDOW (gst_gl_dummy_window_new ());
} }
window->display = gst_object_ref (display); 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); 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);
}