From 9cbb652b66d09f8849f96bc3f66101bae200eae3 Mon Sep 17 00:00:00 2001 From: Matthew Waters Date: Thu, 15 Aug 2013 17:09:04 +1000 Subject: [PATCH] [794/906] context: add subclasses for the different platforms (egl, glx, wgl, etc) - most code taken from the Window subclasses - tested combinations: xEGL, GLX, Wayland+EGL, Cocoa (under GNUStep), WGL (Wine) --- gst-libs/gst/gl/cocoa/Makefile.am | 7 +- gst-libs/gst/gl/cocoa/gstgl_cocoa_private.h | 78 ++++ gst-libs/gst/gl/cocoa/gstglcontext_cocoa.h | 67 +++ gst-libs/gst/gl/cocoa/gstglcontext_cocoa.m | 218 ++++++++++ gst-libs/gst/gl/cocoa/gstglwindow_cocoa.m | 236 ++--------- gst-libs/gst/gl/gstglcontext.c | 94 +++-- gst-libs/gst/gl/gstglcontext.h | 5 +- gst-libs/gst/gl/gstglegl.c | 220 +++++++--- gst-libs/gst/gl/gstglegl.h | 29 +- gst-libs/gst/gl/gstglwindow.c | 79 ++-- gst-libs/gst/gl/gstglwindow.h | 11 +- .../gst/gl/wayland/gstglwindow_wayland_egl.c | 133 ++---- .../gst/gl/wayland/gstglwindow_wayland_egl.h | 2 - gst-libs/gst/gl/win32/Makefile.am | 12 +- gst-libs/gst/gl/win32/gstglcontext_wgl.c | 245 +++++++++++ gst-libs/gst/gl/win32/gstglcontext_wgl.h | 62 +++ gst-libs/gst/gl/win32/gstglwindow_win32.c | 238 +++-------- gst-libs/gst/gl/win32/gstglwindow_win32.h | 2 + gst-libs/gst/gl/win32/gstglwindow_win32_wgl.c | 229 ---------- gst-libs/gst/gl/win32/gstglwindow_win32_wgl.h | 62 --- gst-libs/gst/gl/x11/Makefile.am | 13 +- gst-libs/gst/gl/x11/gstglcontext_glx.c | 396 ++++++++++++++++++ gst-libs/gst/gl/x11/gstglcontext_glx.h | 66 +++ gst-libs/gst/gl/x11/gstglwindow_x11.c | 173 ++++---- gst-libs/gst/gl/x11/gstglwindow_x11.h | 2 + gst-libs/gst/gl/x11/gstglwindow_x11_egl.c | 203 --------- gst-libs/gst/gl/x11/gstglwindow_x11_egl.h | 64 --- gst-libs/gst/gl/x11/gstglwindow_x11_glx.c | 366 ---------------- gst-libs/gst/gl/x11/gstglwindow_x11_glx.h | 66 --- 29 files changed, 1657 insertions(+), 1721 deletions(-) create mode 100644 gst-libs/gst/gl/cocoa/gstgl_cocoa_private.h create mode 100644 gst-libs/gst/gl/cocoa/gstglcontext_cocoa.h create mode 100644 gst-libs/gst/gl/cocoa/gstglcontext_cocoa.m create mode 100644 gst-libs/gst/gl/win32/gstglcontext_wgl.c create mode 100644 gst-libs/gst/gl/win32/gstglcontext_wgl.h delete mode 100644 gst-libs/gst/gl/win32/gstglwindow_win32_wgl.c delete mode 100644 gst-libs/gst/gl/win32/gstglwindow_win32_wgl.h create mode 100644 gst-libs/gst/gl/x11/gstglcontext_glx.c create mode 100644 gst-libs/gst/gl/x11/gstglcontext_glx.h delete mode 100644 gst-libs/gst/gl/x11/gstglwindow_x11_egl.c delete mode 100644 gst-libs/gst/gl/x11/gstglwindow_x11_egl.h delete mode 100644 gst-libs/gst/gl/x11/gstglwindow_x11_glx.c delete mode 100644 gst-libs/gst/gl/x11/gstglwindow_x11_glx.h diff --git a/gst-libs/gst/gl/cocoa/Makefile.am b/gst-libs/gst/gl/cocoa/Makefile.am index 4f21d66de4..9899f243ad 100644 --- a/gst-libs/gst/gl/cocoa/Makefile.am +++ b/gst-libs/gst/gl/cocoa/Makefile.am @@ -3,10 +3,13 @@ noinst_LTLIBRARIES = libgstgl-cocoa.la libgstgl_cocoa_la_SOURCES = \ - gstglwindow_cocoa.m + gstglwindow_cocoa.m \ + gstglcontext_cocoa.m noinst_HEADERS = \ - gstglwindow_cocoa.h + gstglwindow_cocoa.h \ + gstglcontext_cocoa.h \ + gstgl_cocoa_private.h libgstgl_cocoa_la_CFLAGS = \ -I$(top_srcdir)/gst-libs \ diff --git a/gst-libs/gst/gl/cocoa/gstgl_cocoa_private.h b/gst-libs/gst/gl/cocoa/gstgl_cocoa_private.h new file mode 100644 index 0000000000..07b2b14857 --- /dev/null +++ b/gst-libs/gst/gl/cocoa/gstgl_cocoa_private.h @@ -0,0 +1,78 @@ +/* + * GStreamer + * Copyright (C) 2012 Matthew Waters + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __GST_GL_COCOA_PRIVATE_H__ +#define __GST_GL_COCOA_PRIVATE_H__ + +#include + +#include + +#include "gstglwindow_cocoa.h" +#include "gstglcontext_cocoa.h" + +G_BEGIN_DECLS + +@interface AppThreadPerformer : NSObject { + GstGLWindowCocoa *m_cocoa; + GstGLWindowCB m_callback; + GstGLWindowResizeCB m_callback2; + gpointer m_data; + gint m_width; + gint m_height; +} +- (id) init: (GstGLWindowCocoa *)window; +- (id) initWithCallback:(GstGLWindowCocoa *)window callback:(GstGLWindowCB)callback userData:(gpointer) data; +- (id) initWithSize: (GstGLWindowCocoa *)window callback:(GstGLWindowResizeCB)callback userData:(gpointer)data toSize:(NSSize)size; +- (id) initWithAll: (GstGLWindowCocoa *)window callback:(GstGLWindowCB)callback userData:(gpointer) data; +- (void) updateWindow; +- (void) sendToApp; +- (void) setWindow; +- (void) stopApp; +- (void) closeWindow; +@end + +struct _GstGLContextCocoaPrivate +{ + NSOpenGLContext *gl_context; + NSOpenGLContext *external_gl_context; + NSRect rect; +}; + + +/* =============================================================*/ +/* */ +/* GstGLNSOpenGLView declaration */ +/* */ +/* =============================================================*/ + +@interface GstGLNSOpenGLView: NSOpenGLView { + GstGLWindowCocoa *m_cocoa; + gint m_resizeCount; +} +- (id) initWithFrame:(GstGLWindowCocoa *)window rect:(NSRect)contentRect + pixelFormat:(NSOpenGLPixelFormat *)fmt; +@end + +gboolean gst_gl_window_cocoa_create_window (GstGLWindowCocoa *window_cocoa); + +G_END_DECLS + +#endif /* __GST_GL_COCOA_PRIVATE_H__ */ diff --git a/gst-libs/gst/gl/cocoa/gstglcontext_cocoa.h b/gst-libs/gst/gl/cocoa/gstglcontext_cocoa.h new file mode 100644 index 0000000000..d7f0e044c1 --- /dev/null +++ b/gst-libs/gst/gl/cocoa/gstglcontext_cocoa.h @@ -0,0 +1,67 @@ +/* + * GStreamer + * Copyright (C) 2012 Matthew Waters + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __GST_GL_CONTEXT_COCOA_H__ +#define __GST_GL_CONTEXT_COCOA_H__ + +#include + +#include + +G_BEGIN_DECLS + +#define GST_GL_TYPE_CONTEXT_COCOA (gst_gl_context_cocoa_get_type()) +#define GST_GL_CONTEXT_COCOA(o) (G_TYPE_CHECK_INSTANCE_CAST((o), GST_GL_TYPE_CONTEXT_COCOA, GstGLContextCocoa)) +#define GST_GL_CONTEXT_COCOA_CLASS(k) (G_TYPE_CHECK_CLASS((k), GST_GL_TYPE_CONTEXT_COCOA, GstGLContextCocoaClass)) +#define GST_GL_IS_CONTEXT_COCOA(o) (G_TYPE_CHECK_INSTANCE_TYPE((o), GST_GL_TYPE_CONTEXT_COCOA)) +#define GST_GL_IS_CONTEXT_COCOA_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE((k), GST_GL_TYPE_CONTEXT_COCOA)) +#define GST_GL_CONTEXT_COCOA_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS((o), GST_GL_TYPE_CONTEXT_COCOA, GstGLContextCocoaClass)) + +typedef struct _GstGLContextCocoa GstGLContextCocoa; +typedef struct _GstGLContextCocoaPrivate GstGLContextCocoaPrivate; +typedef struct _GstGLContextCocoaClass GstGLContextCocoaClass; + +struct _GstGLContextCocoa { + /*< private >*/ + GstGLContext parent; + + /*< private >*/ + GstGLContextCocoaPrivate *priv; + + gpointer _reserved[GST_PADDING]; +}; + +struct _GstGLContextCocoaClass { + /*< private >*/ + GstGLContextClass parent_class; + + /*< private >*/ + gpointer _reserved[GST_PADDING_LARGE]; + + GstGLContextCocoaPrivate *priv; +}; + +GType gst_gl_context_cocoa_get_type (void); + +GstGLContextCocoa * gst_gl_context_cocoa_new (void); + +G_END_DECLS + +#endif /* __GST_GL_CONTEXT_COCOA_H__ */ diff --git a/gst-libs/gst/gl/cocoa/gstglcontext_cocoa.m b/gst-libs/gst/gl/cocoa/gstglcontext_cocoa.m new file mode 100644 index 0000000000..510b09e827 --- /dev/null +++ b/gst-libs/gst/gl/cocoa/gstglcontext_cocoa.m @@ -0,0 +1,218 @@ +/* + * GStreamer + * Copyright (C) 2012 Matthew Waters + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include "gstglcontext_cocoa.h" +#include "gstgl_cocoa_private.h" + +static gboolean gst_gl_context_cocoa_create_context (GstGLContext *context, GstGLAPI gl_api, + guintptr external_opengl_context, GError **error); +static guintptr gst_gl_context_cocoa_get_gl_context (GstGLContext * window); +static gboolean gst_gl_context_cocoa_activate (GstGLContext * context, gboolean activate); +static GstGLAPI gst_gl_context_cocoa_get_gl_api (GstGLContext * context); + +#define GST_GL_CONTEXT_COCOA_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE((o), GST_GL_TYPE_CONTEXT_COCOA, GstGLContextCocoaPrivate)) + +G_DEFINE_TYPE (GstGLContextCocoa, gst_gl_context_cocoa, GST_GL_TYPE_CONTEXT); + +static void +gst_gl_context_cocoa_class_init (GstGLContextCocoaClass * klass) +{ + GstGLContextClass *context_class; + +#ifndef GNUSTEP + NSAutoreleasePool* pool = nil; +#endif + + context_class = (GstGLContextClass *) klass; + + g_type_class_add_private (klass, sizeof (GstGLContextCocoaPrivate)); + + context_class->create_context = + GST_DEBUG_FUNCPTR (gst_gl_context_cocoa_create_context); + context_class->get_gl_context = + GST_DEBUG_FUNCPTR (gst_gl_context_cocoa_get_gl_context); + context_class->activate = GST_DEBUG_FUNCPTR (gst_gl_context_cocoa_activate); + context_class->get_gl_api = + GST_DEBUG_FUNCPTR (gst_gl_context_cocoa_get_gl_api); + +#ifndef GNUSTEP + pool = [[NSAutoreleasePool alloc] init]; + [NSApplication sharedApplication]; + + [pool release]; +#endif +} + +static void +gst_gl_context_cocoa_init (GstGLContextCocoa * context) +{ + context->priv = GST_GL_CONTEXT_COCOA_GET_PRIVATE (context); +} + +/* Must be called in the gl thread */ +GstGLContextCocoa * +gst_gl_context_cocoa_new (void) +{ + GstGLContextCocoa *context = g_object_new (GST_GL_TYPE_CONTEXT_COCOA, NULL); + + return context; +} + +static gboolean +gst_gl_context_cocoa_create_context (GstGLContext *context, GstGLAPI gl_api, + guintptr external_gl_context, GError **error) +{ + GstGLContextCocoa *context_cocoa = GST_GL_CONTEXT_COCOA (context); + GstGLContextCocoaPrivate *priv = context_cocoa->priv; + GstGLWindow *window = gst_gl_context_get_window (context); + GstGLWindowCocoa *window_cocoa = GST_GL_WINDOW_COCOA (window); + GstGLNSOpenGLView *glView = nil; + NSWindow *window_handle; + NSRect rect; + NSAutoreleasePool *pool; + NSOpenGLPixelFormat *fmt = nil; + NSOpenGLContext *glContext = nil; + NSOpenGLPixelFormatAttribute attribs[] = { + NSOpenGLPFADoubleBuffer, + NSOpenGLPFAAccumSize, 32, + 0 + }; + + priv->gl_context = nil; + priv->external_gl_context = (NSOpenGLContext *) external_gl_context; + + GSRegisterCurrentThread(); + + pool = [[NSAutoreleasePool alloc] init]; + +#ifdef GNUSTEP + [NSApplication sharedApplication]; +#endif + + rect.origin.x = 0; + rect.origin.y = 0; + rect.size.width = 320; + rect.size.height = 240; + + priv->rect = rect; + + gst_gl_window_cocoa_create_window (window_cocoa); + window_handle = (NSWindow *) gst_gl_window_get_window_handle (window); + + glView = [GstGLNSOpenGLView alloc]; + + fmt = [[NSOpenGLPixelFormat alloc] initWithAttributes:attribs]; + + if (!fmt) { + gst_object_unref (window); + GST_WARNING ("cannot create NSOpenGLPixelFormat"); + return FALSE; + } + + glView = [glView initWithFrame:window_cocoa rect:rect pixelFormat:fmt]; + + [window_handle setContentView:glView]; + +#ifndef GNUSTEP + glContext = [[NSOpenGLContext alloc] initWithFormat:fmt + shareContext:context_cocoa->priv->external_gl_context]; + + GST_DEBUG ("NSOpenGL context created: %lud\n", (guintptr) glContext); + + context_cocoa->priv->gl_context = glContext; + + [glView setOpenGLContext:glContext]; +#else + context_cocoa->priv->gl_context = [glView openGLContext]; +#endif + + /* OpenGL context is made current only one time threre. + * Indeed, all OpenGL calls are made in only one thread, + * the Application thread */ + [glContext makeCurrentContext]; + + [glContext update]; + + /* Back and front buffers are swapped only during the vertical retrace of the monitor. + * Discarded if you configured your driver to Never-use-V-Sync. + */ + NS_DURING { + if (glContext) { +#ifdef GNUSTEP + const long swapInterval = 1; +#else + const GLint swapInterval = 1; +#endif + [[glView openGLContext] setValues:&swapInterval forParameter:NSOpenGLCPSwapInterval]; + } + } NS_HANDLER { + GST_DEBUG ("your back-end does not implement NSOpenglContext::setValues\n"); + } + NS_ENDHANDLER + + GST_DEBUG ("opengl GstGLNSWindow initialized: %d x %d\n", + (gint) rect.size.width, (gint) rect.size.height); + + [pool release]; + +#ifndef GNUSTEP + priv->source_id = g_timeout_add_seconds (1, gst_gl_window_cocoa_nsapp_iteration, NULL); +#endif + + gst_object_unref (window); + + return TRUE; +} + +static guintptr +gst_gl_context_cocoa_get_gl_context (GstGLContext * context) +{ + return (guintptr) GST_GL_CONTEXT_COCOA (context)->priv->gl_context; +} + +static gboolean +gst_gl_context_cocoa_activate (GstGLContext * context, gboolean activate) +{ + GstGLContextCocoa *context_cocoa; + + context_cocoa = GST_GL_CONTEXT_COCOA (context); + + if (activate) + [context_cocoa->priv->gl_context makeCurrentContext]; +#if 0 + else + /* FIXME */ + [context_cocoa->priv->gl_context clearCurrentContext]; +#endif + return TRUE; +} + +static GstGLAPI +gst_gl_context_cocoa_get_gl_api (GstGLContext * context) +{ + return GST_GL_API_OPENGL; +} diff --git a/gst-libs/gst/gl/cocoa/gstglwindow_cocoa.m b/gst-libs/gst/gl/cocoa/gstglwindow_cocoa.m index 09ce64e058..038df34031 100644 --- a/gst-libs/gst/gl/cocoa/gstglwindow_cocoa.m +++ b/gst-libs/gst/gl/cocoa/gstglwindow_cocoa.m @@ -24,7 +24,7 @@ #include -#include "gstglwindow_cocoa.h" +#include "gstgl_cocoa_private.h" /* =============================================================*/ /* */ @@ -47,47 +47,6 @@ - (BOOL) canBecomeKeyWindow; @end -/* =============================================================*/ -/* */ -/* GstGLNSOpenGLView declaration */ -/* */ -/* =============================================================*/ - -@interface GstGLNSOpenGLView: NSOpenGLView { - GstGLWindowCocoa *m_cocoa; - gint m_resizeCount; -} -- (id) initWithFrame:(GstGLWindowCocoa *)window rect:(NSRect)contentRect - pixelFormat:(NSOpenGLPixelFormat *)fmt; -@end - - -/* =============================================================*/ -/* */ -/* AppThreadPerformer declaration */ -/* */ -/* =============================================================*/ - -/* Perform actions in the Application thread */ -@interface AppThreadPerformer : NSObject { - GstGLWindowCocoa *m_cocoa; - GstGLWindowCB m_callback; - GstGLWindowResizeCB m_callback2; - gpointer m_data; - gint m_width; - gint m_height; -} -- (id) init: (GstGLWindowCocoa *)window; -- (id) initWithCallback:(GstGLWindowCocoa *)window callback:(GstGLWindowCB)callback userData:(gpointer) data; -- (id) initWithSize: (GstGLWindowCocoa *)window callback:(GstGLWindowResizeCB)callback userData:(gpointer)data toSize:(NSSize)size; -- (id) initWithAll: (GstGLWindowCocoa *)window callback:(GstGLWindowCB)callback userData:(gpointer) data; -- (void) updateWindow; -- (void) sendToApp; -- (void) setWindow; -- (void) stopApp; -- (void) closeWindow; -@end - /* =============================================================*/ /* */ /* GstGLWindow */ @@ -110,26 +69,18 @@ GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT); #define gst_gl_window_cocoa_parent_class parent_class G_DEFINE_TYPE_WITH_CODE (GstGLWindowCocoa, gst_gl_window_cocoa, GST_GL_TYPE_WINDOW, DEBUG_INIT); -gboolean gst_gl_window_cocoa_create_context (GstGLWindow *window, GstGLAPI gl_api, - guintptr external_opengl_context, GError **error); -guintptr gst_gl_window_cocoa_get_gl_context (GstGLWindow * window); -gboolean gst_gl_window_cocoa_activate (GstGLWindow * window, gboolean activate); -void gst_gl_window_cocoa_set_window_handle (GstGLWindow * window, +static guintptr gst_gl_window_cocoa_get_window_handle (GstGLWindow * window); +static void gst_gl_window_cocoa_set_window_handle (GstGLWindow * window, guintptr handle); -void gst_gl_window_cocoa_draw_unlocked (GstGLWindow * window, guint width, - guint height); -void gst_gl_window_cocoa_draw (GstGLWindow * window, guint width, guint height); -void gst_gl_window_cocoa_run (GstGLWindow * window); -void gst_gl_window_cocoa_quit (GstGLWindow * window); -void gst_gl_window_cocoa_send_message (GstGLWindow * window, +static void gst_gl_window_cocoa_draw (GstGLWindow * window, guint width, guint height); +static void gst_gl_window_cocoa_run (GstGLWindow * window); +static void gst_gl_window_cocoa_quit (GstGLWindow * window); +static void gst_gl_window_cocoa_send_message (GstGLWindow * window, GstGLWindowCB callback, gpointer data); -GstGLAPI gst_gl_window_cocoa_get_gl_api (GstGLWindow * window); struct _GstGLWindowCocoaPrivate { GstGLNSWindow *internal_win_id; - NSOpenGLContext *gl_context; - NSOpenGLContext *external_gl_context; gboolean visible; NSWindow *parent; NSThread *thread; @@ -148,9 +99,10 @@ gst_gl_window_cocoa_nsapp_iteration (gpointer data) while ((event = ([NSApp nextEventMatchingMask:NSAnyEventMask untilDate:[NSDate dateWithTimeIntervalSinceNow:0.5] - inMode:NSDefaultRunLoopMode dequeue:YES])) != nil) + inMode:NSDefaultRunLoopMode dequeue:YES])) != nil) { [NSApp sendEvent:event]; + } } [pool release]; @@ -171,11 +123,8 @@ gst_gl_window_cocoa_class_init (GstGLWindowCocoaClass * klass) g_type_class_add_private (klass, sizeof (GstGLWindowCocoaPrivate)); - window_class->create_context = - GST_DEBUG_FUNCPTR (gst_gl_window_cocoa_create_context); - window_class->get_gl_context = - GST_DEBUG_FUNCPTR (gst_gl_window_cocoa_get_gl_context); - window_class->activate = GST_DEBUG_FUNCPTR (gst_gl_window_cocoa_activate); + window_class->get_window_handle = + GST_DEBUG_FUNCPTR (gst_gl_window_cocoa_get_window_handle); window_class->set_window_handle = GST_DEBUG_FUNCPTR (gst_gl_window_cocoa_set_window_handle); window_class->draw_unlocked = GST_DEBUG_FUNCPTR (gst_gl_window_cocoa_draw); @@ -184,8 +133,6 @@ gst_gl_window_cocoa_class_init (GstGLWindowCocoaClass * klass) window_class->quit = GST_DEBUG_FUNCPTR (gst_gl_window_cocoa_quit); window_class->send_message = GST_DEBUG_FUNCPTR (gst_gl_window_cocoa_send_message); - window_class->get_gl_api = - GST_DEBUG_FUNCPTR (gst_gl_window_cocoa_get_gl_api); #ifndef GNUSTEP pool = [[NSAutoreleasePool alloc] init]; @@ -213,33 +160,13 @@ gst_gl_window_cocoa_new (void) } gboolean -gst_gl_window_cocoa_create_context (GstGLWindow *window, GstGLAPI gl_api, - guintptr external_gl_context, GError **error) +gst_gl_window_cocoa_create_window (GstGLWindowCocoa *window_cocoa) { - GstGLWindowCocoa *window_cocoa = GST_GL_WINDOW_COCOA (window); + GstGLWindow *window = GST_GL_WINDOW (window_cocoa); + GstGLContext *context = gst_gl_window_get_context (window); + GstGLContextCocoa *context_cocoa = GST_GL_CONTEXT_COCOA (context); GstGLWindowCocoaPrivate *priv = window_cocoa->priv; - NSRect rect; - NSAutoreleasePool *pool; - - priv->internal_win_id = nil; - priv->gl_context = nil; - priv->external_gl_context = (NSOpenGLContext *) external_gl_context; - priv->visible = FALSE; - priv->thread = nil; - priv->running = TRUE; - - GSRegisterCurrentThread(); - - pool = [[NSAutoreleasePool alloc] init]; - -#ifdef GNUSTEP - [NSApplication sharedApplication]; -#endif - - rect.origin.x = 0; - rect.origin.y = 0; - rect.size.width = 320; - rect.size.height = 240; + NSRect rect = context_cocoa->priv->rect; priv->internal_win_id =[[GstGLNSWindow alloc] initWithContentRect:rect styleMask: (NSTitledWindowMask | NSClosableWindowMask | @@ -247,46 +174,23 @@ gst_gl_window_cocoa_create_context (GstGLWindow *window, GstGLAPI gl_api, backing: NSBackingStoreBuffered defer: NO screen: nil gstWin: window_cocoa]; GST_DEBUG ("NSWindow id: %lud\n", (guintptr) priv->internal_win_id); - + priv->thread = [NSThread currentThread]; [NSApp setDelegate: priv->internal_win_id]; - [pool release]; - -#ifndef GNUSTEP - priv->source_id = g_timeout_add_seconds (1, gst_gl_window_cocoa_nsapp_iteration, NULL); -#endif + gst_object_unref (context); return TRUE; } -guintptr -gst_gl_window_cocoa_get_gl_context (GstGLWindow * window) +static guintptr +gst_gl_window_cocoa_get_window_handle (GstGLWindow *window) { - return (guintptr) GST_GL_WINDOW_COCOA (window)->priv->gl_context; + return (guintptr) GST_GL_WINDOW_COCOA (window)->priv->internal_win_id; } -gboolean -gst_gl_window_cocoa_activate (GstGLWindow * window, gboolean activate) -{ - GstGLWindowCocoa *window_cocoa; - GstGLWindowCocoaPrivate *priv; - - window_cocoa = GST_GL_WINDOW_COCOA (window); - priv = window_cocoa->priv; - - if (activate) - [priv->gl_context makeCurrentContext]; -#if 0 - else - /* FIXME */ - [priv->gl_context clearCurrentContext]; -#endif - return TRUE; -} - -void +static void gst_gl_window_cocoa_set_window_handle (GstGLWindow * window, guintptr handle) { GstGLWindowCocoa *window_cocoa; @@ -316,7 +220,7 @@ gst_gl_window_cocoa_set_window_handle (GstGLWindow * window, guintptr handle) } /* Thread safe */ -void +static void gst_gl_window_cocoa_draw (GstGLWindow * window, guint width, guint height) { GstGLWindowCocoa *window_cocoa; @@ -373,7 +277,7 @@ gst_gl_window_cocoa_draw (GstGLWindow * window, guint width, guint height) GST_DEBUG ("failed to register current thread, cannot draw\n"); } -void +static void gst_gl_window_cocoa_run (GstGLWindow * window) { GstGLWindowCocoa *window_cocoa; @@ -389,6 +293,7 @@ gst_gl_window_cocoa_run (GstGLWindow * window) GST_DEBUG ("begin loop\n"); if (priv->internal_win_id != nil) { + priv->running = TRUE; #ifndef GNUSTEP while (priv->running) [run_loop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]; @@ -406,7 +311,7 @@ gst_gl_window_cocoa_run (GstGLWindow * window) } /* Thread safe */ -void +static void gst_gl_window_cocoa_quit (GstGLWindow * window) { GstGLWindowCocoa *window_cocoa; @@ -419,8 +324,10 @@ gst_gl_window_cocoa_quit (GstGLWindow * window) if (GSRegisterCurrentThread() || 1) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - AppThreadPerformer* app_thread_performer = [[AppThreadPerformer alloc] initWithAll:window_cocoa callback:NULL userData:NULL]; - [app_thread_performer performSelector:@selector(stopApp) onThread:priv->thread withObject:nil waitUntilDone:YES]; + AppThreadPerformer* app_thread_performer = [[AppThreadPerformer alloc] + initWithAll:window_cocoa callback:NULL userData:NULL]; + [app_thread_performer performSelector:@selector(stopApp) + onThread:priv->thread withObject:nil waitUntilDone:YES]; [pool release]; @@ -432,7 +339,7 @@ gst_gl_window_cocoa_quit (GstGLWindow * window) } /* Thread safe */ -void +static void gst_gl_window_cocoa_send_message (GstGLWindow * window, GstGLWindowCB callback, gpointer data) { @@ -461,12 +368,6 @@ gst_gl_window_cocoa_send_message (GstGLWindow * window, GstGLWindowCB callback, } } -GstGLAPI -gst_gl_window_cocoa_get_gl_api (GstGLWindow * window) -{ - return GST_GL_API_OPENGL; -} - /* =============================================================*/ /* */ /* GstGLNSWindow implementation */ @@ -481,15 +382,6 @@ gst_gl_window_cocoa_get_gl_api (GstGLWindow * window) defer: (BOOL) flag screen: (NSScreen *) aScreen gstWin: (GstGLWindowCocoa *) cocoa { - GstGLNSOpenGLView *glView = nil; - NSOpenGLPixelFormat *fmt = nil; - NSOpenGLContext *glContext = nil; - NSOpenGLPixelFormatAttribute attribs[] = { - NSOpenGLPFADoubleBuffer, - NSOpenGLPFAAccumSize, 32, - 0 - }; - m_isClosed = NO; m_cocoa = cocoa; @@ -501,66 +393,12 @@ gst_gl_window_cocoa_get_gl_api (GstGLWindow * window) GST_DEBUG ("initializing GstGLNSWindow\n"); - glView = [GstGLNSOpenGLView alloc]; - - fmt = [[NSOpenGLPixelFormat alloc] initWithAttributes:attribs]; - - if (!fmt) { - GST_WARNING ("cannot create NSOpenGLPixelFormat"); - return nil; - } - - glView = [glView initWithFrame:m_cocoa rect:contentRect pixelFormat:fmt]; - - [self setContentView:glView]; - -#ifndef GNUSTEP - glContext = [[NSOpenGLContext alloc] initWithFormat:fmt - shareContext:m_cocoa->priv->external_gl_context]; - - GST_DEBUG ("NSOpenGL context created: %lud\n", (guintptr) glContext); - - m_cocoa->priv->gl_context = glContext; - - [glView setOpenGLContext:glContext]; -#else - glContext = [glView openGLContext]; -#endif - - /* OpenGL context is made current only one time threre. - * Indeed, all OpenGL calls are made in only one thread, - * the Application thread */ - [glContext makeCurrentContext]; - - [glContext update]; - - /* Back and front buffers are swapped only during the vertical retrace of the monitor. - * Discarded if you configured your driver to Never-use-V-Sync. - */ - NS_DURING { - if (glContext) { -#ifdef GNUSTEP - const long swapInterval = 1; -#else - const GLint swapInterval = 1; -#endif - [[glView openGLContext] setValues:&swapInterval forParameter:NSOpenGLCPSwapInterval]; - } - } NS_HANDLER { - GST_DEBUG ("your back-end does not implement NSOpenglContext::setValues\n"); - } - NS_ENDHANDLER - - GST_DEBUG ("opengl GstGLNSWindow initialized: %d x %d\n", - (gint) contentRect.size.width, (gint) contentRect.size.height); - [self setTitle:@"OpenGL renderer"]; [self setBackgroundColor:[NSColor clearColor]]; [self orderOut:m_cocoa->priv->internal_win_id]; - if (m_cocoa->priv->parent) { NSWindow *window = m_cocoa->priv->parent; [window setContentView: [m_cocoa->priv->internal_win_id contentView]]; @@ -639,17 +477,17 @@ gst_gl_window_cocoa_get_gl_api (GstGLWindow * window) @implementation GstGLNSOpenGLView - (id)initWithFrame:(GstGLWindowCocoa *)window rect:(NSRect)contentRect pixelFormat:(NSOpenGLPixelFormat *)fmt { - + self = [super initWithFrame: contentRect pixelFormat: fmt]; - + m_cocoa = window; m_resizeCount = 0; - + #ifndef GNUSTEP [self setWantsLayer:NO]; #endif - - return self; + + return self; } - (void)reshape { @@ -660,7 +498,7 @@ gst_gl_window_cocoa_get_gl_api (GstGLWindow * window) if (m_resizeCount % 5 == 0) { m_resizeCount = 0; if (window->resize) { - + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; NSRect bounds = [self bounds]; AppThreadPerformer* app_thread_performer = [[AppThreadPerformer alloc] diff --git a/gst-libs/gst/gl/gstglcontext.c b/gst-libs/gst/gl/gstglcontext.c index 7bd8754bcb..c8e233d109 100644 --- a/gst-libs/gst/gl/gstglcontext.c +++ b/gst-libs/gst/gl/gstglcontext.c @@ -27,6 +27,19 @@ #include "gl.h" #include "gstglcontext.h" +#if GST_GL_HAVE_PLATFORM_GLX +#include "x11/gstglcontext_glx.h" +#endif +#if GST_GL_HAVE_PLATFORM_EGL +#include "gstglegl.h" +#endif +#if GST_GL_HAVE_PLATFORM_COCOA +#include "cocoa/gstglcontext_cocoa.h" +#endif +#if GST_GL_HAVE_PLATFORM_WGL +#include "win32/gstglcontext_wgl.h" +#endif + #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) @@ -37,7 +50,7 @@ GST_DEBUG_CATEGORY (GST_CAT_DEFAULT); #define gst_gl_context_parent_class parent_class -G_DEFINE_TYPE (GstGLContext, gst_gl_context, G_TYPE_OBJECT); +G_DEFINE_ABSTRACT_TYPE (GstGLContext, gst_gl_context, G_TYPE_OBJECT); #define GST_GL_CONTEXT_GET_PRIVATE(o) \ (G_TYPE_INSTANCE_GET_PRIVATE((o), GST_GL_TYPE_CONTEXT, GstGLContextPrivate)) @@ -121,7 +134,6 @@ gst_gl_context_new (GstGLDisplay * display) user_choice = g_getenv ("GST_GL_PLATFORM"); GST_INFO ("creating a context, user choice:%s", user_choice); -#if 0 #if GST_GL_HAVE_PLATFORM_EGL if (!context && (!user_choice || g_strstr_len (user_choice, 7, "egl"))) context = GST_GL_CONTEXT (gst_gl_context_egl_new ()); @@ -130,15 +142,17 @@ gst_gl_context_new (GstGLDisplay * display) if (!context && (!user_choice || g_strstr_len (user_choice, 3, "glx"))) context = GST_GL_CONTEXT (gst_gl_context_glx_new ()); #endif -#if GST_GL_HAVE_PLATFORM_WIN32 - if (!context && (!user_choice || g_strstr_len (user_choice, 5, "win32"))) - context = GST_GL_CONTEXT (gst_gl_context_win32_new ()); -#endif #if GST_GL_HAVE_PLATFORM_COCOA if (!context && (!user_choice || g_strstr_len (user_choice, 5, "cocoa"))) { context = GST_GL_CONTEXT (gst_gl_context_cocoa_new ()); } #endif +#if GST_GL_HAVE_PLATFORM_WGL + if (!context && (!user_choice || g_strstr_len (user_choice, 3, "wgl"))) { + context = GST_GL_CONTEXT (gst_gl_context_wgl_new ()); + } +#endif + if (!context) { /* subclass returned a NULL context */ GST_WARNING ("Could not create context. user specified %s", @@ -146,9 +160,6 @@ gst_gl_context_new (GstGLDisplay * display) return NULL; } -#endif - - context = g_object_new (GST_GL_TYPE_CONTEXT, NULL); context->priv->display = display; @@ -164,9 +175,13 @@ gst_gl_context_finalize (GObject * object) gst_gl_window_set_draw_callback (context->window, NULL, NULL, NULL); if (context->priv->alive) { + g_mutex_lock (&context->priv->render_lock); GST_INFO ("send quit gl window loop"); gst_gl_window_quit (context->window); - g_cond_wait (&context->priv->destroy_cond, &context->priv->render_lock); + while (context->priv->alive) { + g_cond_wait (&context->priv->destroy_cond, &context->priv->render_lock); + } + g_mutex_unlock (&context->priv->render_lock); } gst_gl_window_set_close_callback (context->window, NULL, NULL, NULL); @@ -189,18 +204,17 @@ gst_gl_context_finalize (GObject * object) G_OBJECT_CLASS (gst_gl_context_parent_class)->finalize (object); } -/* FIXME move the relevant window vfuncs into GstGLContext */ gboolean gst_gl_context_activate (GstGLContext * context, gboolean activate) { - GstGLWindowClass *window_class; + GstGLContextClass *context_class; gboolean result; g_return_val_if_fail (GST_GL_IS_CONTEXT (context), FALSE); - window_class = GST_GL_WINDOW_GET_CLASS (context->window); - g_return_val_if_fail (window_class->activate != NULL, FALSE); + context_class = GST_GL_CONTEXT_GET_CLASS (context); + g_return_val_if_fail (context_class->activate != NULL, FALSE); - result = window_class->activate (context->window, activate); + result = context_class->activate (context, activate); return result; } @@ -208,26 +222,26 @@ gst_gl_context_activate (GstGLContext * context, gboolean activate) GstGLAPI gst_gl_context_get_gl_api (GstGLContext * context) { - GstGLWindowClass *window_class; + GstGLContextClass *context_class; g_return_val_if_fail (GST_GL_IS_CONTEXT (context), GST_GL_API_NONE); - window_class = GST_GL_WINDOW_GET_CLASS (context->window); - g_return_val_if_fail (window_class->get_gl_api != NULL, GST_GL_API_NONE); + context_class = GST_GL_CONTEXT_GET_CLASS (context); + g_return_val_if_fail (context_class->get_gl_api != NULL, GST_GL_API_NONE); - return window_class->get_gl_api (context->window); + return context_class->get_gl_api (context); } gpointer gst_gl_context_get_proc_address (GstGLContext * context, const gchar * name) { gpointer ret; - GstGLWindowClass *window_class; + GstGLContextClass *context_class; g_return_val_if_fail (GST_GL_IS_CONTEXT (context), NULL); - window_class = GST_GL_WINDOW_GET_CLASS (context->window); - g_return_val_if_fail (window_class->get_proc_address != NULL, NULL); + context_class = GST_GL_CONTEXT_GET_CLASS (context); + g_return_val_if_fail (context_class->get_proc_address != NULL, NULL); - ret = window_class->get_proc_address (context->window, name); + ret = context_class->get_proc_address (context, name); return ret; } @@ -288,21 +302,13 @@ gst_gl_context_create (GstGLContext * context, guintptr external_gl_context, GError ** error) { gboolean alive = FALSE; - GstGLWindowClass *window_class; g_return_val_if_fail (GST_GL_IS_CONTEXT (context), FALSE); - window_class = GST_GL_WINDOW_GET_CLASS (context->window); - g_return_val_if_fail (window_class->create_context != NULL, FALSE); _ensure_window (context); g_mutex_lock (&context->priv->render_lock); - if (window_class->open) { - if (!(alive = window_class->open (context->window, error))) - goto out; - } - if (!context->priv->created) { context->priv->external_gl_context = external_gl_context; context->priv->error = error; @@ -321,7 +327,6 @@ gst_gl_context_create (GstGLContext * context, g_mutex_unlock (&context->priv->render_lock); -out: return alive; } @@ -475,6 +480,7 @@ _parse_gl_api (const gchar * apis_s) static gpointer gst_gl_context_create_thread (GstGLContext * context) { + GstGLContextClass *context_class; GstGLWindowClass *window_class; GstGLDisplay *display; GstGLFuncs *gl; @@ -488,9 +494,12 @@ gst_gl_context_create_thread (GstGLContext * context) GError **error; guintptr external_gl_context; + g_mutex_lock (&context->priv->render_lock); + error = context->priv->error; external_gl_context = context->priv->external_gl_context; + context_class = GST_GL_CONTEXT_GET_CLASS (context); window_class = GST_GL_WINDOW_GET_CLASS (context->window); if (window_class->open) { @@ -518,17 +527,34 @@ gst_gl_context_create_thread (GstGLContext * context) goto failure; } + if (context_class->choose_format && + !context_class->choose_format (context, error)) { + g_assert (error == NULL || *error != NULL); + g_free (compiled_api_s); + g_free (user_api_string); + goto failure; + } + GST_INFO ("Attempting to create opengl context. user chosen api(s) (%s), " "compiled api support (%s)", user_api_string, compiled_api_s); - if (!window_class->create_context (context->window, compiled_api & user_api, + if (!context_class->create_context (context, compiled_api & user_api, external_gl_context, error)) { g_assert (error == NULL || *error != NULL); g_free (compiled_api_s); g_free (user_api_string); goto failure; } - GST_INFO ("context created context"); + GST_INFO ("created context"); + + if (!context_class->activate (context, TRUE)) { + g_set_error (error, GST_GL_CONTEXT_ERROR, + GST_GL_CONTEXT_ERROR_RESOURCE_UNAVAILABLE, + "Failed to activate the GL Context"); + g_free (compiled_api_s); + g_free (user_api_string); + goto failure; + } display->gl_api = gst_gl_context_get_gl_api (context); g_assert (display->gl_api != GST_GL_API_NONE diff --git a/gst-libs/gst/gl/gstglcontext.h b/gst-libs/gst/gl/gstglcontext.h index 10c30a7011..68d6f0522f 100644 --- a/gst-libs/gst/gl/gstglcontext.h +++ b/gst-libs/gst/gl/gstglcontext.h @@ -36,7 +36,7 @@ G_BEGIN_DECLS GType gst_gl_context_get_type (void); #define GST_GL_CONTEXT_ERROR (gst_gl_context_error_quark ()) -GQuark gst_gl_window_error_quark (void); +GQuark gst_gl_context_error_quark (void); typedef enum { @@ -69,8 +69,11 @@ struct _GstGLContextClass { GstGLAPI (*get_gl_api) (GstGLContext *context); gpointer (*get_proc_address) (GstGLContext *context, const gchar *name); gboolean (*activate) (GstGLContext *context, gboolean activate); + gboolean (*choose_format) (GstGLContext *context, GError **error); gboolean (*create_context) (GstGLContext *context, GstGLAPI gl_api, guintptr external_gl_context, GError ** error); + void (*destroy_context) (GstGLContext *context); + void (*swap_buffers) (GstGLContext *context); /*< private >*/ gpointer _reserved[GST_PADDING]; diff --git a/gst-libs/gst/gl/gstglegl.c b/gst-libs/gst/gl/gstglegl.c index 9d183ae368..cb2cf1cbc5 100644 --- a/gst-libs/gst/gl/gstglegl.c +++ b/gst-libs/gst/gl/gstglegl.c @@ -22,11 +22,70 @@ #include "config.h" #endif -#include "gl.h" #include "gstglegl.h" +#include + +#if GST_GL_HAVE_WINDOW_X11 +#include "x11/gstglwindow_x11.h" +#endif +#if GST_GL_HAVE_WINDOW_WIN32 +#include "win32/gstglwindow_win32.h" +#endif + +static gboolean gst_gl_context_egl_create_context (GstGLContext * context, + GstGLAPI gl_api, guintptr external_gl_context, GError ** error); +static void gst_gl_context_egl_destroy_context (GstGLContext * context); +static gboolean gst_gl_context_egl_choose_format (GstGLContext * context, + GError ** error); + +static gboolean gst_gl_context_egl_activate (GstGLContext * context, + gboolean activate); +static void gst_gl_context_egl_swap_buffers (GstGLContext * context); +static guintptr gst_gl_context_egl_get_gl_context (GstGLContext * context); +static GstGLAPI gst_gl_context_egl_get_gl_api (GstGLContext * context); +static gpointer gst_gl_context_egl_get_proc_address (GstGLContext * context, + const gchar * name); + +G_DEFINE_TYPE (GstGLContextEGL, gst_gl_context_egl, GST_GL_TYPE_CONTEXT); + +static void +gst_gl_context_egl_class_init (GstGLContextEGLClass * klass) +{ + GstGLContextClass *context_class = (GstGLContextClass *) klass; + + context_class->get_gl_context = + GST_DEBUG_FUNCPTR (gst_gl_context_egl_get_gl_context); + context_class->activate = GST_DEBUG_FUNCPTR (gst_gl_context_egl_activate); + context_class->create_context = + GST_DEBUG_FUNCPTR (gst_gl_context_egl_create_context); + context_class->destroy_context = + GST_DEBUG_FUNCPTR (gst_gl_context_egl_destroy_context); + context_class->choose_format = + GST_DEBUG_FUNCPTR (gst_gl_context_egl_choose_format); + context_class->swap_buffers = + GST_DEBUG_FUNCPTR (gst_gl_context_egl_swap_buffers); + + context_class->get_gl_api = GST_DEBUG_FUNCPTR (gst_gl_context_egl_get_gl_api); + context_class->get_proc_address = + GST_DEBUG_FUNCPTR (gst_gl_context_egl_get_proc_address); +} + +static void +gst_gl_context_egl_init (GstGLContextEGL * context) +{ +} + +/* Must be called in the gl thread */ +GstGLContextEGL * +gst_gl_context_egl_new (void) +{ + GstGLContextEGL *window = g_object_new (GST_GL_TYPE_CONTEXT_EGL, NULL); + + return window; +} static const gchar * -gst_gl_egl_get_error_string (void) +gst_gl_context_egl_get_error_string (void) { EGLint nErr = eglGetError (); @@ -65,7 +124,33 @@ gst_gl_egl_get_error_string (void) } static gboolean -gst_gl_egl_choose_config (GstGLEGL * egl, GError ** error) +gst_gl_context_egl_choose_format (GstGLContext * context, GError ** error) +{ +#if GST_GL_HAVE_WINDOW_X11 + if (GST_GL_IS_WINDOW_X11 (context->window)) { + GstGLWindow *window = gst_gl_context_get_window (context); + GstGLWindowX11 *window_x11 = GST_GL_WINDOW_X11 (window); + gint ret; + + window_x11->visual_info = g_new0 (XVisualInfo, 1); + ret = XMatchVisualInfo (window_x11->device, window_x11->screen_num, + window_x11->depth, TrueColor, window_x11->visual_info); + + gst_object_unref (window); + + if (ret == 0) { + g_set_error (error, GST_GL_WINDOW_ERROR, GST_GL_WINDOW_ERROR_WRONG_CONFIG, + "Failed to match XVisualInfo"); + return FALSE; + } + } +#endif + + return TRUE; +} + +static gboolean +gst_gl_context_egl_choose_config (GstGLContextEGL * egl, GError ** error) { EGLint numConfigs; gint i = 0; @@ -87,9 +172,9 @@ gst_gl_egl_choose_config (GstGLEGL * egl, GError ** error) GST_INFO ("config set: %ld, %ld", (gulong) egl->egl_config, (gulong) numConfigs); } else { - g_set_error (error, GST_GL_WINDOW_ERROR, GST_GL_WINDOW_ERROR_WRONG_CONFIG, + g_set_error (error, GST_GL_CONTEXT_ERROR, GST_GL_CONTEXT_ERROR_WRONG_CONFIG, "Failed to set window configuration: %s", - gst_gl_egl_get_error_string ()); + gst_gl_context_egl_get_error_string ()); goto failure; } @@ -99,11 +184,13 @@ failure: return FALSE; } -GstGLEGL * -gst_gl_egl_create_context (EGLDisplay display, EGLNativeWindowType window, +static gboolean +gst_gl_context_egl_create_context (GstGLContext * context, GstGLAPI gl_api, guintptr external_gl_context, GError ** error) { - GstGLEGL *egl; + GstGLContextEGL *egl; + GstGLWindow *window = NULL; + EGLNativeWindowType window_handle; gint i = 0; EGLint context_attrib[3]; EGLint majorVersion; @@ -111,23 +198,25 @@ gst_gl_egl_create_context (EGLDisplay display, EGLNativeWindowType window, const gchar *egl_exts; gboolean need_surface = TRUE; - egl = g_slice_new0 (GstGLEGL); + egl = GST_GL_CONTEXT_EGL (context); + window = gst_gl_context_get_window (context); if ((gl_api & GST_GL_API_OPENGL) == GST_GL_API_NONE && (gl_api & GST_GL_API_GLES2) == GST_GL_API_NONE) { - g_set_error (error, GST_GL_WINDOW_ERROR, GST_GL_WINDOW_ERROR_WRONG_API, + g_set_error (error, GST_GL_CONTEXT_ERROR, GST_GL_CONTEXT_ERROR_WRONG_API, "xEGL supports opengl or gles2"); goto failure; } - egl->egl_display = display; + egl->egl_display = + eglGetDisplay ((EGLNativeDisplayType) gst_gl_window_get_display (window)); if (eglInitialize (egl->egl_display, &majorVersion, &minorVersion)) { GST_INFO ("egl initialized, version: %d.%d", majorVersion, minorVersion); } else { - g_set_error (error, GST_GL_WINDOW_ERROR, - GST_GL_WINDOW_ERROR_RESOURCE_UNAVAILABLE, - "Failed to initialize egl: %s", gst_gl_egl_get_error_string ()); + g_set_error (error, GST_GL_CONTEXT_ERROR, + GST_GL_CONTEXT_ERROR_RESOURCE_UNAVAILABLE, + "Failed to initialize egl: %s", gst_gl_context_egl_get_error_string ()); goto failure; } @@ -135,7 +224,7 @@ gst_gl_egl_create_context (EGLDisplay display, EGLNativeWindowType window, /* egl + opengl only available with EGL 1.4+ */ if (majorVersion == 1 && minorVersion <= 3) { if ((gl_api & ~GST_GL_API_OPENGL) == GST_GL_API_NONE) { - g_set_error (error, GST_GL_WINDOW_ERROR, GST_GL_WINDOW_ERROR_OLD_LIBS, + g_set_error (error, GST_GL_CONTEXT_ERROR, GST_GL_CONTEXT_ERROR_OLD_LIBS, "EGL version (%i.%i) too old for OpenGL support, (needed at least 1.4)", majorVersion, minorVersion); goto failure; @@ -146,8 +235,8 @@ gst_gl_egl_create_context (EGLDisplay display, EGLNativeWindowType window, if (gl_api & GST_GL_API_GLES2) { goto try_gles2; } else { - g_set_error (error, GST_GL_WINDOW_ERROR, - GST_GL_WINDOW_ERROR_WRONG_CONFIG, + g_set_error (error, GST_GL_CONTEXT_ERROR, + GST_GL_CONTEXT_ERROR_WRONG_CONFIG, "Failed to choose a suitable OpenGL API"); goto failure; } @@ -155,8 +244,9 @@ gst_gl_egl_create_context (EGLDisplay display, EGLNativeWindowType window, } if (!eglBindAPI (EGL_OPENGL_API)) { - g_set_error (error, GST_GL_WINDOW_ERROR, GST_GL_WINDOW_ERROR_FAILED, - "Failed to bind OpenGL|ES API: %s", gst_gl_egl_get_error_string ()); + g_set_error (error, GST_GL_CONTEXT_ERROR, GST_GL_CONTEXT_ERROR_FAILED, + "Failed to bind OpenGL|ES API: %s", + gst_gl_context_egl_get_error_string ()); goto failure; } @@ -164,15 +254,16 @@ gst_gl_egl_create_context (EGLDisplay display, EGLNativeWindowType window, } else if (gl_api & GST_GL_API_GLES2) { try_gles2: if (!eglBindAPI (EGL_OPENGL_ES_API)) { - g_set_error (error, GST_GL_WINDOW_ERROR, GST_GL_WINDOW_ERROR_FAILED, - "Failed to bind OpenGL|ES API: %s", gst_gl_egl_get_error_string ()); + g_set_error (error, GST_GL_CONTEXT_ERROR, GST_GL_CONTEXT_ERROR_FAILED, + "Failed to bind OpenGL|ES API: %s", + gst_gl_context_egl_get_error_string ()); goto failure; } egl->gl_api = GST_GL_API_GLES2; } - if (!gst_gl_egl_choose_config (egl, error)) { + if (!gst_gl_context_egl_choose_config (egl, error)) { g_assert (error == NULL || *error != NULL); goto failure; } @@ -192,18 +283,33 @@ gst_gl_egl_create_context (EGLDisplay display, EGLNativeWindowType window, if (egl->egl_context != EGL_NO_CONTEXT) { GST_INFO ("gl context created: %ld", (gulong) egl->egl_context); } else { - g_set_error (error, GST_GL_WINDOW_ERROR, GST_GL_WINDOW_ERROR_CREATE_CONTEXT, + g_set_error (error, GST_GL_CONTEXT_ERROR, + GST_GL_CONTEXT_ERROR_CREATE_CONTEXT, "Failed to create a OpenGL context: %s", - gst_gl_egl_get_error_string ()); + gst_gl_context_egl_get_error_string ()); goto failure; } egl_exts = eglQueryString (egl->egl_display, EGL_EXTENSIONS); - if (window) { + /* FIXME do we want a window vfunc ? */ +#if GST_GL_HAVE_WINDOW_X11 + if (GST_GL_IS_WINDOW_X11 (context->window)) { + gst_gl_window_x11_create_window ((GstGLWindowX11 *) context->window); + } +#endif +#if GST_GL_HAVE_WINDOW_WIN32 + if (GST_GL_IS_WINDOW_WIN32 (context->window)) { + gst_gl_window_win32_create_window ((GstGLWindowWin32 *) context->window); + } +#endif + + window_handle = gst_gl_window_get_window_handle (window); + + if (window_handle) { egl->egl_surface = - eglCreateWindowSurface (egl->egl_display, egl->egl_config, window, - NULL); + eglCreateWindowSurface (egl->egl_display, egl->egl_config, + window_handle, NULL); } else if (!gst_gl_check_extension ("EGL_KHR_surfaceless_context", egl_exts)) { EGLint surface_attrib[7]; gint j = 0; @@ -230,27 +336,32 @@ gst_gl_egl_create_context (EGLDisplay display, EGLNativeWindowType window, if (egl->egl_surface != EGL_NO_SURFACE) { GST_INFO ("surface created"); } else { - g_set_error (error, GST_GL_WINDOW_ERROR, GST_GL_WINDOW_ERROR_FAILED, + g_set_error (error, GST_GL_CONTEXT_ERROR, GST_GL_CONTEXT_ERROR_FAILED, "Failed to create window surface: %s", - gst_gl_egl_get_error_string ()); + gst_gl_context_egl_get_error_string ()); goto failure; } } - gst_gl_egl_activate (egl, TRUE); + gst_object_unref (window); - return egl; + return TRUE; failure: - gst_gl_egl_destroy_context (egl); + if (window) + gst_object_unref (window); - return NULL; + return FALSE; } -void -gst_gl_egl_destroy_context (GstGLEGL * egl) +static void +gst_gl_context_egl_destroy_context (GstGLContext * context) { - gst_gl_egl_activate (egl, FALSE); + GstGLContextEGL *egl; + + egl = GST_GL_CONTEXT_EGL (context); + + gst_gl_context_egl_activate (context, FALSE); if (egl->egl_surface) eglDestroySurface (egl->egl_surface, egl->egl_display); @@ -262,15 +373,16 @@ gst_gl_egl_destroy_context (GstGLEGL * egl) eglTerminate (egl->egl_display); eglReleaseThread (); } - - g_slice_free (GstGLEGL, egl); } -gboolean -gst_gl_egl_activate (GstGLEGL * egl, gboolean activate) +static gboolean +gst_gl_context_egl_activate (GstGLContext * context, gboolean activate) { + GstGLContextEGL *egl; gboolean result; + egl = GST_GL_CONTEXT_EGL (context); + if (activate) result = eglMakeCurrent (egl->egl_display, egl->egl_surface, egl->egl_surface, egl->egl_context); @@ -281,26 +393,30 @@ gst_gl_egl_activate (GstGLEGL * egl, gboolean activate) return result; } -guintptr -gst_gl_egl_get_gl_context (GstGLEGL * egl) +static guintptr +gst_gl_context_egl_get_gl_context (GstGLContext * context) { - return (guintptr) egl->egl_context; + return (guintptr) GST_GL_CONTEXT_EGL (context)->egl_context; } -void -gst_gl_egl_swap_buffers (GstGLEGL * egl) +static void +gst_gl_context_egl_swap_buffers (GstGLContext * context) { + GstGLContextEGL *egl; + + egl = GST_GL_CONTEXT_EGL (context); + eglSwapBuffers (egl->egl_display, egl->egl_surface); } -GstGLAPI -gst_gl_egl_get_gl_api (GstGLEGL * egl) +static GstGLAPI +gst_gl_context_egl_get_gl_api (GstGLContext * context) { - return egl->gl_api; + return GST_GL_CONTEXT_EGL (context)->gl_api; } -gpointer -gst_gl_egl_get_proc_address (GstGLEGL * egl, const gchar * name) +static gpointer +gst_gl_context_egl_get_proc_address (GstGLContext * context, const gchar * name) { gpointer result; @@ -309,7 +425,9 @@ gst_gl_egl_get_proc_address (GstGLEGL * egl, const gchar * name) return NULL; #endif - result = eglGetProcAddress (name); + if (!(result = eglGetProcAddress (name))) { + result = gst_gl_context_default_get_proc_address (context, name); + } return result; } diff --git a/gst-libs/gst/gl/gstglegl.h b/gst-libs/gst/gl/gstglegl.h index 4e5c3a5274..fcd2fe18ca 100644 --- a/gst-libs/gst/gl/gstglegl.h +++ b/gst-libs/gst/gl/gstglegl.h @@ -25,12 +25,23 @@ #include #include +#include G_BEGIN_DECLS -typedef struct _GstGLEGL GstGLEGL; +typedef struct _GstGLContextEGL GstGLContextEGL; +typedef struct _GstGLContextEGLClass GstGLContextEGLClass; + +#define GST_GL_TYPE_CONTEXT_EGL (gst_gl_context_egl_get_type()) +#define GST_GL_CONTEXT_EGL(o) (G_TYPE_CHECK_INSTANCE_CAST((o), GST_GL_TYPE_CONTEXT_EGL, GstGLContextEGL)) +#define GST_GL_CONTEXT_EGL_CLASS(k) (G_TYPE_CHECK_CLASS((k), GST_GL_TYPE_CONTEXT_EGL, GstGLContextEGLClass)) +#define GST_GL_IS_CONTEXT_EGL(o) (G_TYPE_CHECK_INSTANCE_TYPE((o), GST_GL_TYPE_CONTEXT_EGL)) +#define GST_GL_IS_CONTEXT_EGL_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE((k), GST_GL_TYPE_CONTEXT_EGL)) +#define GST_GL_CONTEXT_EGL_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS((o), GST_GL_TYPE_CONTEXT_EGL, GstGLContextEGLClass)) + +struct _GstGLContextEGL { + GstGLContext context; -struct _GstGLEGL { EGLContext egl_context; EGLDisplay egl_display; EGLSurface egl_surface; @@ -39,16 +50,12 @@ struct _GstGLEGL { GstGLAPI gl_api; }; -GstGLEGL * gst_gl_egl_create_context (EGLDisplay display, EGLNativeWindowType window, GstGLAPI gl_api, guintptr external_gl_context, GError ** error); -void gst_gl_egl_destroy_context (GstGLEGL *egl); +struct _GstGLContextEGLClass { + GstGLContextClass parent; +}; -gboolean gst_gl_egl_activate (GstGLEGL *egl, gboolean activate); -void gst_gl_egl_swap_buffers (GstGLEGL *egl); - -guintptr gst_gl_egl_get_gl_context (GstGLEGL *egl); -GstGLAPI gst_gl_egl_get_gl_api (GstGLEGL *egl); - -gpointer gst_gl_egl_get_proc_address (GstGLEGL *egl, const gchar * name); +GType gst_gl_context_egl_get_type (void); +GstGLContextEGL * gst_gl_context_egl_new (void); G_END_DECLS diff --git a/gst-libs/gst/gl/gstglwindow.c b/gst-libs/gst/gl/gstglwindow.c index 8349c434e4..41d859ea16 100644 --- a/gst-libs/gst/gl/gstglwindow.c +++ b/gst-libs/gst/gl/gstglwindow.c @@ -28,6 +28,8 @@ #include "gl.h" #include "gstglwindow.h" +/* FIXME make this work with windowless contexts */ + #if GST_GL_HAVE_WINDOW_X11 #include "x11/gstglwindow_x11.h" #endif @@ -170,40 +172,6 @@ gst_gl_window_finalize (GObject * object) G_OBJECT_CLASS (gst_gl_window_parent_class)->finalize (object); } -guintptr -gst_gl_window_get_gl_context (GstGLWindow * window) -{ - GstGLWindowClass *window_class; - guintptr result; - - g_return_val_if_fail (GST_GL_IS_WINDOW (window), 0); - window_class = GST_GL_WINDOW_GET_CLASS (window); - g_return_val_if_fail (window_class->get_gl_context != NULL, 0); - - GST_GL_WINDOW_LOCK (window); - result = window_class->get_gl_context (window); - GST_GL_WINDOW_UNLOCK (window); - - return result; -} - -gboolean -gst_gl_window_activate (GstGLWindow * window, gboolean activate) -{ - GstGLWindowClass *window_class; - gboolean result; - - g_return_val_if_fail (GST_GL_IS_WINDOW (window), FALSE); - window_class = GST_GL_WINDOW_GET_CLASS (window); - g_return_val_if_fail (window_class->activate != NULL, FALSE); - - GST_GL_WINDOW_LOCK (window); - result = window_class->activate (window, activate); - GST_GL_WINDOW_UNLOCK (window); - - return result; -} - void gst_gl_window_set_window_handle (GstGLWindow * window, guintptr handle) { @@ -369,41 +337,48 @@ gst_gl_window_set_close_callback (GstGLWindow * window, GstGLWindowCB callback, GST_GL_WINDOW_UNLOCK (window); } -GstGLAPI -gst_gl_window_get_gl_api (GstGLWindow * window) +gboolean +gst_gl_window_is_running (GstGLWindow * window) { - GstGLWindowClass *window_class; - - g_return_val_if_fail (GST_GL_IS_WINDOW (window), GST_GL_API_NONE); - window_class = GST_GL_WINDOW_GET_CLASS (window); - g_return_val_if_fail (window_class->get_gl_api != NULL, GST_GL_API_NONE); - - return window_class->get_gl_api (window); + return window->priv->alive; } -gpointer -gst_gl_window_get_proc_address (GstGLWindow * window, const gchar * name) +guintptr +gst_gl_window_get_display (GstGLWindow * window) { - gpointer ret; + guintptr ret; GstGLWindowClass *window_class; - g_return_val_if_fail (GST_GL_IS_WINDOW (window), NULL); + g_return_val_if_fail (GST_GL_IS_WINDOW (window), 0); window_class = GST_GL_WINDOW_GET_CLASS (window); - g_return_val_if_fail (window_class->get_proc_address != NULL, NULL); + g_return_val_if_fail (window_class->get_display != NULL, 0); GST_GL_WINDOW_LOCK (window); - ret = window_class->get_proc_address (window, name); + ret = window_class->get_display (window); GST_GL_WINDOW_UNLOCK (window); return ret; } -gboolean -gst_gl_window_is_running (GstGLWindow * window) +guintptr +gst_gl_window_get_window_handle (GstGLWindow * window) { - return window->priv->alive; + guintptr ret; + GstGLWindowClass *window_class; + + g_return_val_if_fail (GST_GL_IS_WINDOW (window), 0); + window_class = GST_GL_WINDOW_GET_CLASS (window); + g_return_val_if_fail (window_class->get_window_handle != NULL, 0); + + GST_GL_WINDOW_LOCK (window); + + ret = window_class->get_window_handle (window); + + GST_GL_WINDOW_UNLOCK (window); + + return ret; } GstGLContext * diff --git a/gst-libs/gst/gl/gstglwindow.h b/gst-libs/gst/gl/gstglwindow.h index f7aae8c5c6..946e551331 100644 --- a/gst-libs/gst/gl/gstglwindow.h +++ b/gst-libs/gst/gl/gstglwindow.h @@ -99,14 +99,9 @@ struct _GstGLWindowClass { /*< private >*/ GObjectClass parent_class; - guintptr (*get_gl_context) (GstGLWindow *window); - GstGLAPI (*get_gl_api) (GstGLWindow *window); - gpointer (*get_proc_address) (GstGLWindow *window, const gchar *name); - gboolean (*activate) (GstGLWindow *window, gboolean activate); + guintptr (*get_display) (GstGLWindow *window); void (*set_window_handle) (GstGLWindow *window, guintptr id); - gboolean (*create_context) (GstGLWindow *window, GstGLAPI gl_api, - guintptr external_gl_context, GError ** error); - gboolean (*share_context) (GstGLWindow *window, guintptr external_gl_context); + guintptr (*get_window_handle) (GstGLWindow *window); void (*draw_unlocked) (GstGLWindow *window, guint width, guint height); void (*draw) (GstGLWindow *window, guint width, guint height); void (*run) (GstGLWindow *window); @@ -132,7 +127,6 @@ void gst_gl_window_set_resize_callback (GstGLWindow *window, GstGLWindowRes void gst_gl_window_set_close_callback (GstGLWindow *window, GstGLWindowCB callback, gpointer data, GDestroyNotify destroy_notify); void gst_gl_window_set_need_lock (GstGLWindow *window, gboolean need_lock); -guintptr gst_gl_window_get_gl_context (GstGLWindow *window); void gst_gl_window_set_window_handle (GstGLWindow *window, guintptr handle); guintptr gst_gl_window_get_window_handle (GstGLWindow *window); void gst_gl_window_draw_unlocked (GstGLWindow *window, guint width, guint height); @@ -140,6 +134,7 @@ void gst_gl_window_draw (GstGLWindow *window, guint width, g void gst_gl_window_run (GstGLWindow *window); void gst_gl_window_quit (GstGLWindow *window); void gst_gl_window_send_message (GstGLWindow *window, GstGLWindowCB callback, gpointer data); +guintptr gst_gl_window_get_display (GstGLWindow *window); GstGLContext * gst_gl_window_get_context (GstGLWindow *window); diff --git a/gst-libs/gst/gl/wayland/gstglwindow_wayland_egl.c b/gst-libs/gst/gl/wayland/gstglwindow_wayland_egl.c index 16215d5137..32f82f6814 100644 --- a/gst-libs/gst/gl/wayland/gstglwindow_wayland_egl.c +++ b/gst-libs/gst/gl/wayland/gstglwindow_wayland_egl.c @@ -40,9 +40,8 @@ const gchar *WlEGLErrorString (); G_DEFINE_TYPE (GstGLWindowWaylandEGL, gst_gl_window_wayland_egl, GST_GL_TYPE_WINDOW); -static guintptr gst_gl_window_wayland_egl_get_gl_context (GstGLWindow * window); -static gboolean gst_gl_window_wayland_egl_activate (GstGLWindow * window, - gboolean activate); +static guintptr gst_gl_window_wayland_egl_get_window_handle (GstGLWindow * + window); static void gst_gl_window_wayland_egl_set_window_handle (GstGLWindow * window, guintptr handle); static void gst_gl_window_wayland_egl_draw (GstGLWindow * window, guint width, @@ -51,14 +50,10 @@ static void gst_gl_window_wayland_egl_run (GstGLWindow * window); static void gst_gl_window_wayland_egl_quit (GstGLWindow * window); static void gst_gl_window_wayland_egl_send_message (GstGLWindow * window, GstGLWindowCB callback, gpointer data); -static void gst_gl_window_wayland_egl_destroy_context (GstGLWindowWaylandEGL * - window_egl); -static gboolean gst_gl_window_wayland_egl_create_context (GstGLWindow - * window, GstGLAPI gl_api, guintptr external_gl_context, GError ** error); -static GstGLAPI gst_gl_window_wayland_egl_get_gl_api (GstGLWindow * window); -static gpointer gst_gl_window_wayland_egl_get_proc_address (GstGLWindow * - window, const gchar * name); static void gst_gl_window_wayland_egl_close (GstGLWindow * window); +static gboolean gst_gl_window_wayland_egl_open (GstGLWindow * window, + GError ** error); +static guintptr gst_gl_window_wayland_egl_get_display (GstGLWindow * window); static void pointer_handle_enter (void *data, struct wl_pointer *pointer, uint32_t serial, @@ -254,12 +249,8 @@ gst_gl_window_wayland_egl_class_init (GstGLWindowWaylandEGLClass * klass) { GstGLWindowClass *window_class = (GstGLWindowClass *) klass; - window_class->create_context = - GST_DEBUG_FUNCPTR (gst_gl_window_wayland_egl_create_context); - window_class->get_gl_context = - GST_DEBUG_FUNCPTR (gst_gl_window_wayland_egl_get_gl_context); - window_class->activate = - GST_DEBUG_FUNCPTR (gst_gl_window_wayland_egl_activate); + window_class->get_window_handle = + GST_DEBUG_FUNCPTR (gst_gl_window_wayland_egl_get_window_handle); window_class->set_window_handle = GST_DEBUG_FUNCPTR (gst_gl_window_wayland_egl_set_window_handle); window_class->draw_unlocked = @@ -269,11 +260,10 @@ gst_gl_window_wayland_egl_class_init (GstGLWindowWaylandEGLClass * klass) window_class->quit = GST_DEBUG_FUNCPTR (gst_gl_window_wayland_egl_quit); window_class->send_message = GST_DEBUG_FUNCPTR (gst_gl_window_wayland_egl_send_message); - window_class->get_gl_api = - GST_DEBUG_FUNCPTR (gst_gl_window_wayland_egl_get_gl_api); - window_class->get_proc_address = - GST_DEBUG_FUNCPTR (gst_gl_window_wayland_egl_get_proc_address); window_class->close = GST_DEBUG_FUNCPTR (gst_gl_window_wayland_egl_close); + window_class->open = GST_DEBUG_FUNCPTR (gst_gl_window_wayland_egl_open); + window_class->get_display = + GST_DEBUG_FUNCPTR (gst_gl_window_wayland_egl_get_display); } static void @@ -303,7 +293,7 @@ gst_gl_window_wayland_egl_close (GstGLWindow * window) window_egl = GST_GL_WINDOW_WAYLAND_EGL (window); - gst_gl_window_wayland_egl_destroy_context (window_egl); + destroy_surface (window_egl); if (window_egl->display.cursor_surface) wl_surface_destroy (window_egl->display.cursor_surface); @@ -324,8 +314,10 @@ gst_gl_window_wayland_egl_close (GstGLWindow * window) } static gboolean -_setup_wayland (GstGLWindowWaylandEGL * window_egl, GError ** error) +gst_gl_window_wayland_egl_open (GstGLWindow * window, GError ** error) { + GstGLWindowWaylandEGL *window_egl = GST_GL_WINDOW_WAYLAND_EGL (window); + window_egl->display.display = wl_display_connect (NULL); if (!window_egl->display.display) { g_set_error (error, GST_GL_WINDOW_ERROR, @@ -359,78 +351,6 @@ error: return FALSE; } -gboolean -gst_gl_window_wayland_egl_create_context (GstGLWindow * window, - GstGLAPI gl_api, guintptr external_gl_context, GError ** error) -{ - GstGLWindowWaylandEGL *window_egl = GST_GL_WINDOW_WAYLAND_EGL (window); - if (!_setup_wayland (window_egl, error)) - return FALSE; - - window_egl->egl = - gst_gl_egl_create_context (eglGetDisplay ((EGLNativeDisplayType) - window_egl->display.display), window_egl->window.native, gl_api, - external_gl_context, error); - if (!window_egl->egl) - goto failure; - - return TRUE; - -failure: - return FALSE; -} - -static void -gst_gl_window_wayland_egl_destroy_context (GstGLWindowWaylandEGL * window_egl) -{ - gst_gl_egl_activate (window_egl->egl, FALSE); - - destroy_surface (window_egl); - /* - gst_gl_egl_destroy_surface (window_egl->egl); - */ - gst_gl_egl_destroy_context (window_egl->egl); - window_egl->egl = NULL; -} - -static gboolean -gst_gl_window_wayland_egl_activate (GstGLWindow * window, gboolean activate) -{ - GstGLWindowWaylandEGL *window_egl; - - window_egl = GST_GL_WINDOW_WAYLAND_EGL (window); - - return gst_gl_egl_activate (window_egl->egl, activate); -} - -static guintptr -gst_gl_window_wayland_egl_get_gl_context (GstGLWindow * window) -{ - GstGLWindowWaylandEGL *window_egl; - - window_egl = GST_GL_WINDOW_WAYLAND_EGL (window); - - return gst_gl_egl_get_gl_context (window_egl->egl); -} - -static GstGLAPI -gst_gl_window_wayland_egl_get_gl_api (GstGLWindow * window) -{ - GstGLWindowWaylandEGL *window_egl; - - window_egl = GST_GL_WINDOW_WAYLAND_EGL (window); - - return gst_gl_egl_get_gl_api (window_egl->egl); -} - -static void -gst_gl_window_wayland_egl_swap_buffers (GstGLWindow * window) -{ - GstGLWindowWaylandEGL *window_egl = GST_GL_WINDOW_WAYLAND_EGL (window); - - gst_gl_egl_swap_buffers (window_egl->egl); -} - static void gst_gl_window_wayland_egl_run (GstGLWindow * window) { @@ -506,6 +426,12 @@ gst_gl_window_wayland_egl_send_message (GstGLWindow * window, g_mutex_unlock (&message.lock); } +static guintptr +gst_gl_window_wayland_egl_get_window_handle (GstGLWindow * window) +{ + return (guintptr) GST_GL_WINDOW_WAYLAND_EGL (window)->window.native; +} + static void gst_gl_window_wayland_egl_set_window_handle (GstGLWindow * window, guintptr handle) @@ -544,6 +470,8 @@ draw_cb (gpointer data) struct draw *draw_data = data; GstGLWindowWaylandEGL *window_egl = draw_data->window; GstGLWindow *window = GST_GL_WINDOW (window_egl); + GstGLContext *context = gst_gl_window_get_context (window); + GstGLContextClass *context_class = GST_GL_CONTEXT_GET_CLASS (context); if (window_egl->window.window_width != draw_data->width || window_egl->window.window_height != draw_data->height) { @@ -556,7 +484,9 @@ draw_cb (gpointer data) if (window->draw) window->draw (window->draw_data); - gst_gl_window_wayland_egl_swap_buffers (window); + context_class->swap_buffers (context); + + gst_object_unref (context); } static void @@ -571,19 +501,12 @@ gst_gl_window_wayland_egl_draw (GstGLWindow * window, guint width, guint height) gst_gl_window_send_message (window, (GstGLWindowCB) draw_cb, &draw_data); } -static gpointer -gst_gl_window_wayland_egl_get_proc_address (GstGLWindow * window, - const gchar * name) +static guintptr +gst_gl_window_wayland_egl_get_display (GstGLWindow * window) { - GstGLContext *context = NULL; GstGLWindowWaylandEGL *window_egl; - gpointer result; window_egl = GST_GL_WINDOW_WAYLAND_EGL (window); - if (!(result = gst_gl_egl_get_proc_address (window_egl->egl, name))) { - result = gst_gl_context_default_get_proc_address (context, name); - } - - return result; + return (guintptr) window_egl->display.display; } diff --git a/gst-libs/gst/gl/wayland/gstglwindow_wayland_egl.h b/gst-libs/gst/gl/wayland/gstglwindow_wayland_egl.h index e826e44763..32389e7106 100644 --- a/gst-libs/gst/gl/wayland/gstglwindow_wayland_egl.h +++ b/gst-libs/gst/gl/wayland/gstglwindow_wayland_egl.h @@ -74,8 +74,6 @@ struct window { struct _GstGLWindowWaylandEGL { /*< private >*/ GstGLWindow parent; - - GstGLEGL *egl; struct display display; struct window window; diff --git a/gst-libs/gst/gl/win32/Makefile.am b/gst-libs/gst/gl/win32/Makefile.am index 62768670d6..6ec6599451 100644 --- a/gst-libs/gst/gl/win32/Makefile.am +++ b/gst-libs/gst/gl/win32/Makefile.am @@ -9,13 +9,13 @@ noinst_HEADERS = \ gstglwindow_win32.h if USE_WGL -libgstgl_win32_la_SOURCES += gstglwindow_win32_wgl.c -noinst_HEADERS += gstglwindow_win32_wgl.h -endif -if USE_EGL -libgstgl_win32_la_SOURCES += gstglwindow_win32_egl.c -noinst_HEADERS += gstglwindow_win32_egl.h +libgstgl_win32_la_SOURCES += gstglcontext_wgl.c +noinst_HEADERS += gstglcontext_wgl.h endif +#if USE_EGL +#libgstgl_win32_la_SOURCES += gstglwindow_win32_egl.c +#noinst_HEADERS += gstglwindow_win32_egl.h +#endif libgstgl_win32_la_CFLAGS = \ -I$(top_srcdir)/gst-libs \ diff --git a/gst-libs/gst/gl/win32/gstglcontext_wgl.c b/gst-libs/gst/gl/win32/gstglcontext_wgl.c new file mode 100644 index 0000000000..826ab44b59 --- /dev/null +++ b/gst-libs/gst/gl/win32/gstglcontext_wgl.c @@ -0,0 +1,245 @@ +/* + * GStreamer + * Copyright (C) 2008 Julien Isorce + * Copyright (C) 2012 Matthew Waters + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include "../gstgl_fwd.h" +#include + +#include "gstglcontext_wgl.h" + +#define gst_gl_context_wgl_parent_class parent_class +G_DEFINE_TYPE (GstGLContextWGL, gst_gl_context_wgl, GST_GL_TYPE_CONTEXT); + +static guintptr gst_gl_context_wgl_get_gl_context (GstGLContext * context); +static void gst_gl_context_wgl_swap_buffers (GstGLContext * context); +static gboolean gst_gl_context_wgl_choose_format (GstGLContext * context, + GError ** error); +static gboolean gst_gl_context_wgl_activate (GstGLContext * context, + gboolean activate); +static gboolean gst_gl_context_wgl_create_context (GstGLContext * context, + GstGLAPI gl_api, guintptr external_gl_context, GError ** error); +static void gst_gl_context_wgl_destroy_context (GstGLContext * context); +GstGLAPI gst_gl_context_wgl_get_gl_api (GstGLContext * context); +static gpointer gst_gl_context_wgl_get_proc_address (GstGLContext * context, + const gchar * name); + +static void +gst_gl_context_wgl_class_init (GstGLContextWGLClass * klass) +{ + GstGLContextClass *context_class = (GstGLContextClass *) klass; + + context_class->get_gl_context = + GST_DEBUG_FUNCPTR (gst_gl_context_wgl_get_gl_context); + context_class->choose_format = + GST_DEBUG_FUNCPTR (gst_gl_context_wgl_choose_format); + context_class->activate = GST_DEBUG_FUNCPTR (gst_gl_context_wgl_activate); + context_class->create_context = + GST_DEBUG_FUNCPTR (gst_gl_context_wgl_create_context); + context_class->destroy_context = + GST_DEBUG_FUNCPTR (gst_gl_context_wgl_destroy_context); + context_class->swap_buffers = + GST_DEBUG_FUNCPTR (gst_gl_context_wgl_swap_buffers); + + context_class->get_proc_address = + GST_DEBUG_FUNCPTR (gst_gl_context_wgl_get_proc_address); + context_class->get_gl_api = GST_DEBUG_FUNCPTR (gst_gl_context_wgl_get_gl_api); +} + +static void +gst_gl_context_wgl_init (GstGLContextWGL * context_wgl) +{ +} + +/* Must be called in the gl thread */ +GstGLContextWGL * +gst_gl_context_wgl_new (void) +{ + GstGLContextWGL *context = g_object_new (GST_GL_TYPE_CONTEXT_WGL, NULL); + + return context; +} + +static gboolean +gst_gl_context_wgl_create_context (GstGLContext * context, + GstGLAPI gl_api, guintptr external_gl_context, GError ** error) +{ + GstGLWindow *window; + GstGLContextWGL *context_wgl; + HDC device; + + context_wgl = GST_GL_CONTEXT_WGL (context); + window = gst_gl_context_get_window (context); + device = (HDC) gst_gl_window_get_display (window); + + context_wgl->wgl_context = wglCreateContext (device); + if (context_wgl->wgl_context) + GST_DEBUG ("gl context created: %" G_GUINTPTR_FORMAT, + (guintptr) context_wgl->wgl_context); + else { + g_set_error (error, GST_GL_WINDOW_ERROR, GST_GL_WINDOW_ERROR_CREATE_CONTEXT, + "failed to create glcontext:%lu", GetLastError ()); + goto failure; + } + g_assert (context_wgl->wgl_context); + + GST_LOG ("gl context id: %" G_GUINTPTR_FORMAT, + (guintptr) context_wgl->wgl_context); + + gst_object_unref (window); + + return TRUE; + +failure: + gst_object_unref (window); + + return FALSE; +} + +static void +gst_gl_context_wgl_destroy_context (GstGLContext * context) +{ + GstGLContextWGL *context_wgl; + + context_wgl = GST_GL_CONTEXT_WGL (context); + + if (context_wgl->wgl_context) + wglDeleteContext (context_wgl->wgl_context); + context_wgl->wgl_context = NULL; +} + +static gboolean +gst_gl_context_wgl_choose_format (GstGLContext * context, GError ** error) +{ + GstGLWindow *window; + PIXELFORMATDESCRIPTOR pfd; + gint pixelformat = 0; + gboolean res = FALSE; + HDC device; + + window = gst_gl_context_get_window (context); + gst_gl_window_win32_create_window (GST_GL_WINDOW_WIN32 (window), error); + device = (HDC) gst_gl_window_get_display (window); + gst_object_unref (window); + + pfd.nSize = sizeof (PIXELFORMATDESCRIPTOR); + pfd.nVersion = 1; + pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER; + pfd.iPixelType = PFD_TYPE_RGBA; + pfd.cColorBits = 24; + pfd.cRedBits = 8; + pfd.cRedShift = 0; + pfd.cGreenBits = 8; + pfd.cGreenShift = 0; + pfd.cBlueBits = 8; + pfd.cBlueShift = 0; + pfd.cAlphaBits = 0; + pfd.cAlphaShift = 0; + pfd.cAccumBits = 0; + pfd.cAccumRedBits = 0; + pfd.cAccumGreenBits = 0; + pfd.cAccumBlueBits = 0; + pfd.cAccumAlphaBits = 0; + pfd.cDepthBits = 24; + pfd.cStencilBits = 8; + pfd.cAuxBuffers = 0; + pfd.iLayerType = PFD_MAIN_PLANE; + pfd.bReserved = 0; + pfd.dwLayerMask = 0; + pfd.dwVisibleMask = 0; + pfd.dwDamageMask = 0; + + pfd.cColorBits = (BYTE) GetDeviceCaps (device, BITSPIXEL); + + pixelformat = ChoosePixelFormat (device, &pfd); + + if (!pixelformat) { + g_set_error (error, GST_GL_CONTEXT_ERROR, GST_GL_CONTEXT_ERROR_FAILED, + "Failed to choose a pixel format"); + return FALSE; + } + + res = SetPixelFormat (device, pixelformat, &pfd); + + return res; +} + +static void +gst_gl_context_wgl_swap_buffers (GstGLContext * context) +{ + GstGLWindow *window = gst_gl_context_get_window (context); + HDC device = (HDC) gst_gl_window_get_display (window); + + SwapBuffers (device); + + gst_object_unref (window); +} + +static guintptr +gst_gl_context_wgl_get_gl_context (GstGLContext * context) +{ + return (guintptr) GST_GL_CONTEXT_WGL (context)->wgl_context; +} + +static gboolean +gst_gl_context_wgl_activate (GstGLContext * context, gboolean activate) +{ + GstGLWindow *window; + GstGLContextWGL *context_wgl; + HDC device; + gboolean result; + + window = gst_gl_context_get_window (context); + context_wgl = GST_GL_CONTEXT_WGL (context); + device = (HDC) gst_gl_window_get_display (window); + + if (activate) { + result = wglMakeCurrent (device, context_wgl->wgl_context); + } else { + result = wglMakeCurrent (NULL, NULL); + } + + gst_object_unref (window); + + return result; +} + +GstGLAPI +gst_gl_context_wgl_get_gl_api (GstGLContext * context) +{ + return GST_GL_API_OPENGL; +} + +static gpointer +gst_gl_context_wgl_get_proc_address (GstGLContext * context, const gchar * name) +{ + gpointer result; + + if (!(result = wglGetProcAddress ((LPCSTR) name))) { + result = gst_gl_context_default_get_proc_address (context, name); + } + + return result; +} diff --git a/gst-libs/gst/gl/win32/gstglcontext_wgl.h b/gst-libs/gst/gl/win32/gstglcontext_wgl.h new file mode 100644 index 0000000000..b996dc7cbc --- /dev/null +++ b/gst-libs/gst/gl/win32/gstglcontext_wgl.h @@ -0,0 +1,62 @@ +/* + * GStreamer + * Copyright (C) 2012 Matthew Waters + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __GST_GL_CONTEXT_WGL_H__ +#define __GST_GL_CONTEXT_WGL_H__ + +#include "gstglwindow_win32.h" + +G_BEGIN_DECLS + +#define GST_GL_TYPE_CONTEXT_WGL (gst_gl_context_wgl_get_type()) +#define GST_GL_CONTEXT_WGL(o) (G_TYPE_CHECK_INSTANCE_CAST((o), GST_GL_TYPE_CONTEXT_WGL, GstGLContextWGL)) +#define GST_GL_CONTEXT_WGL_CLASS(k) (G_TYPE_CHECK_CLASS((k), GST_GL_TYPE_CONTEXT_WGL, GstGLContextWGLClass)) +#define GST_GL_IS_CONTEXT_WGL(o) (G_TYPE_CHECK_INSTANCE_TYPE((o), GST_GL_TYPE_CONTEXT_WGL)) +#define GST_GL_IS_CONTEXT_WGL_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE((k), GST_GL_TYPE_CONTEXT_WGL)) +#define GST_GL_CONTEXT_WGL_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS((o), GST_GL_TYPE_CONTEXT_WGL, GstGLContextWGLClass)) + +typedef struct _GstGLContextWGL GstGLContextWGL; +typedef struct _GstGLContextWGLClass GstGLContextWGLClass; + +struct _GstGLContextWGL { + /*< private >*/ + GstGLContext parent; + + HGLRC wgl_context; + HGLRC external_gl_context; + + gpointer _reserved[GST_PADDING]; +}; + +struct _GstGLContextWGLClass { + /*< private >*/ + GstGLContextClass parent_class; + + /*< private >*/ + gpointer _reserved[GST_PADDING]; +}; + +GType gst_gl_context_wgl_get_type (void); + +GstGLContextWGL * gst_gl_context_wgl_new (void); + +G_END_DECLS + +#endif /* __GST_GL_CONTEXT_WGL_H__ */ diff --git a/gst-libs/gst/gl/win32/gstglwindow_win32.c b/gst-libs/gst/gl/win32/gstglwindow_win32.c index 724cd64d67..94c32fe7b8 100644 --- a/gst-libs/gst/gl/win32/gstglwindow_win32.c +++ b/gst-libs/gst/gl/win32/gstglwindow_win32.c @@ -25,17 +25,9 @@ #include "gstglwindow_win32.h" -#if GST_GL_HAVE_PLATFORM_WGL -#include "gstglwindow_win32_wgl.h" -#endif -#if GST_GL_HAVE_PLATFORM_EGL -#include "gstglwindow_win32_egl.h" -#endif - #define WM_GST_GL_WINDOW_CUSTOM (WM_APP+1) #define WM_GST_GL_WINDOW_QUIT (WM_APP+2) -void gst_gl_window_set_pixel_format (GstGLWindowWin32 * window); LRESULT CALLBACK window_proc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); LRESULT FAR PASCAL sub_class_proc (HWND hWnd, UINT uMsg, WPARAM wParam, @@ -51,11 +43,7 @@ enum struct _GstGLWindowWin32Private { - GstGLAPI gl_api; - guintptr external_gl_context; - GError **error; - gboolean activate; - gboolean activate_result; + gint dummy; }; #define GST_CAT_DEFAULT gst_gl_window_win32_debug @@ -67,20 +55,14 @@ GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT); G_DEFINE_TYPE_WITH_CODE (GstGLWindowWin32, gst_gl_window_win32, GST_GL_TYPE_WINDOW, DEBUG_INIT); -HHOOK hHook; - -gboolean gst_gl_window_win32_create_context (GstGLWindow * window, - GstGLAPI gl_api, guintptr external_gl_context, GError ** error); -guintptr gst_gl_window_win32_get_gl_context (GstGLWindow * window); -gboolean gst_gl_window_win32_activate (GstGLWindow * window, gboolean activate); -void gst_gl_window_win32_set_window_handle (GstGLWindow * window, +static void gst_gl_window_win32_set_window_handle (GstGLWindow * window, guintptr handle); -void gst_gl_window_win32_draw_unlocked (GstGLWindow * window, guint width, +static guintptr gst_gl_window_win32_get_display (GstGLWindow * window); +static void gst_gl_window_win32_draw (GstGLWindow * window, guint width, guint height); -void gst_gl_window_win32_draw (GstGLWindow * window, guint width, guint height); -void gst_gl_window_win32_run (GstGLWindow * window); -void gst_gl_window_win32_quit (GstGLWindow * window); -void gst_gl_window_win32_send_message (GstGLWindow * window, +static void gst_gl_window_win32_run (GstGLWindow * window); +static void gst_gl_window_win32_quit (GstGLWindow * window); +static void gst_gl_window_win32_send_message (GstGLWindow * window, GstGLWindowCB callback, gpointer data); static void @@ -90,11 +72,6 @@ gst_gl_window_win32_class_init (GstGLWindowWin32Class * klass) g_type_class_add_private (klass, sizeof (GstGLWindowWin32Private)); - window_class->create_context = - GST_DEBUG_FUNCPTR (gst_gl_window_win32_create_context); - window_class->get_gl_context = - GST_DEBUG_FUNCPTR (gst_gl_window_win32_get_gl_context); - window_class->activate = GST_DEBUG_FUNCPTR (gst_gl_window_win32_activate); window_class->set_window_handle = GST_DEBUG_FUNCPTR (gst_gl_window_win32_set_window_handle); window_class->draw_unlocked = GST_DEBUG_FUNCPTR (gst_gl_window_win32_draw); @@ -103,6 +80,8 @@ gst_gl_window_win32_class_init (GstGLWindowWin32Class * klass) window_class->quit = GST_DEBUG_FUNCPTR (gst_gl_window_win32_quit); window_class->send_message = GST_DEBUG_FUNCPTR (gst_gl_window_win32_send_message); + window_class->get_display = + GST_DEBUG_FUNCPTR (gst_gl_window_win32_get_display); } static void @@ -117,33 +96,16 @@ gst_gl_window_win32_init (GstGLWindowWin32 * window) GstGLWindowWin32 * gst_gl_window_win32_new (void) { - GstGLWindowWin32 *window = NULL; - const gchar *user_choice; - - user_choice = g_getenv ("GST_GL_PLATFORM"); - -#if GST_GL_HAVE_PLATFORM_WGL - if (!window && (!user_choice || g_strstr_len (user_choice, 3, "wgl"))) - window = GST_GL_WINDOW_WIN32 (gst_gl_window_win32_wgl_new ()); -#endif -#if GST_GL_HAVE_PLATFORM_EGL - if (!window && (!user_choice || g_strstr_len (user_choice, 3, "egl"))) - window = GST_GL_WINDOW_WIN32 (gst_gl_window_win32_egl_new ()); -#endif - if (!window) { - GST_WARNING ("Failed to create win32 window, user_choice:%s", - user_choice ? user_choice : "NULL"); - return NULL; - } + GstGLWindowWin32 *window = g_object_new (GST_GL_TYPE_WINDOW_WIN32, NULL); return window; } gboolean -gst_gl_window_win32_create_context (GstGLWindow * window, GstGLAPI gl_api, - guintptr external_gl_context, GError ** error) +gst_gl_window_win32_create_window (GstGLWindowWin32 * window_win32, + GError ** error) { - GstGLWindowWin32 *window_win32 = GST_GL_WINDOW_WIN32 (window); +// GstGLWindowWin32 *window_win32 = GST_GL_WINDOW_WIN32 (window); WNDCLASSEX wc; ATOM atom = 0; HINSTANCE hinstance = GetModuleHandle (NULL); @@ -177,7 +139,9 @@ gst_gl_window_win32_create_context (GstGLWindow * window, GstGLAPI gl_api, atom = RegisterClassEx (&wc); if (atom == 0) { - GST_WARNING ("Failed to register window class %lud\n", GetLastError ()); + g_set_error (error, GST_GL_CONTEXT_ERROR, GST_GL_CONTEXT_ERROR_FAILED, + "Failed to register window class 0x%x\n", + (unsigned int) GetLastError ()); goto failure; } } @@ -187,10 +151,6 @@ gst_gl_window_win32_create_context (GstGLWindow * window, GstGLAPI gl_api, window_win32->is_closed = FALSE; window_win32->visible = FALSE; - window_win32->priv->gl_api = gl_api; - window_win32->priv->external_gl_context = external_gl_context; - window_win32->priv->error = error; - window_win32->internal_win_id = CreateWindowEx (0, "GSTGL", "OpenGL renderer", @@ -198,16 +158,18 @@ gst_gl_window_win32_create_context (GstGLWindow * window, GstGLAPI gl_api, x, y, 0, 0, (HWND) NULL, (HMENU) NULL, hinstance, window_win32); if (!window_win32->internal_win_id) { - GST_DEBUG ("failed to create gl window\n"); + g_set_error (error, GST_GL_CONTEXT_ERROR, GST_GL_CONTEXT_ERROR_FAILED, + "failed to create gl window"); goto failure; } - GST_DEBUG ("gl window created: %" G_GUINTPTR_FORMAT "\n", + GST_DEBUG ("gl window created: %" G_GUINTPTR_FORMAT, (guintptr) window_win32->internal_win_id); //device is set in the window_proc if (!window_win32->device) { - GST_DEBUG ("failed to create device\n"); + g_set_error (error, GST_GL_CONTEXT_ERROR, GST_GL_CONTEXT_ERROR_FAILED, + "failed to create device"); goto failure; } @@ -220,47 +182,17 @@ failure: return FALSE; } -guintptr -gst_gl_window_win32_get_gl_context (GstGLWindow * window) +static guintptr +gst_gl_window_win32_get_display (GstGLWindow * window) { - GstGLWindowWin32Class *window_class; + GstGLWindowWin32 *window_win32; - window_class = GST_GL_WINDOW_WIN32_GET_CLASS (window); + window_win32 = GST_GL_WINDOW_WIN32 (window); - return window_class->get_gl_context (GST_GL_WINDOW_WIN32 (window)); + return (guintptr) window_win32->device; } static void -callback_activate (GstGLWindow * window) -{ - GstGLWindowWin32Class *window_class; - GstGLWindowWin32Private *priv; - GstGLWindowWin32 *window_win32; - - window_win32 = GST_GL_WINDOW_WIN32 (window); - window_class = GST_GL_WINDOW_WIN32_GET_CLASS (window_win32); - priv = window_win32->priv; - - priv->activate_result = window_class->activate (window_win32, priv->activate); -} - -gboolean -gst_gl_window_win32_activate (GstGLWindow * window, gboolean activate) -{ - GstGLWindowWin32 *window_win32; - GstGLWindowWin32Private *priv; - - window_win32 = GST_GL_WINDOW_WIN32 (window); - priv = window_win32->priv; - priv->activate = activate; - - gst_gl_window_win32_send_message (window, - GST_GL_WINDOW_CB (callback_activate), window_win32); - - return priv->activate_result; -} - -void gst_gl_window_win32_set_window_handle (GstGLWindow * window, guintptr id) { GstGLWindowWin32 *window_win32; @@ -284,7 +216,7 @@ gst_gl_window_win32_set_window_handle (GstGLWindow * window, guintptr id) if (parent_id) { WNDPROC parent_proc = GetProp (parent_id, "gl_window_parent_proc"); - GST_DEBUG ("release parent %" G_GUINTPTR_FORMAT "\n", (guintptr) parent_id); + GST_DEBUG ("release parent %" G_GUINTPTR_FORMAT, (guintptr) parent_id); g_return_if_fail (parent_proc); @@ -299,7 +231,7 @@ gst_gl_window_win32_set_window_handle (GstGLWindow * window, guintptr id) (WNDPROC) GetWindowLongPtr ((HWND) id, GWLP_WNDPROC); RECT rect; - GST_DEBUG ("set parent %" G_GUINTPTR_FORMAT "\n", id); + GST_DEBUG ("set parent %" G_GUINTPTR_FORMAT, id); SetProp ((HWND) id, "gl_window_id", window_win32->internal_win_id); SetProp ((HWND) id, "gl_window_parent_proc", (WNDPROC) window_parent_proc); @@ -326,7 +258,7 @@ gst_gl_window_win32_set_window_handle (GstGLWindow * window, guintptr id) } /* Thread safe */ -void +static void gst_gl_window_win32_draw (GstGLWindow * window, guint width, guint height) { GstGLWindowWin32 *window_win32 = GST_GL_WINDOW_WIN32 (window); @@ -355,20 +287,21 @@ gst_gl_window_win32_draw (GstGLWindow * window, guint width, guint height) RDW_NOERASE | RDW_INTERNALPAINT | RDW_INVALIDATE); } -void +static void gst_gl_window_win32_run (GstGLWindow * window) { gint bRet; MSG msg; - GST_INFO ("begin message loop\n"); + GST_INFO ("begin message loop"); while (TRUE) { bRet = GetMessage (&msg, NULL, 0, 0); if (bRet == 0) break; else if (bRet == -1) { - GST_WARNING ("Failed to get message %lud\n", GetLastError ()); + GST_WARNING ("Failed to get message 0x%x", + (unsigned int) GetLastError ()); break; } else { GST_TRACE ("handle message"); @@ -377,11 +310,11 @@ gst_gl_window_win32_run (GstGLWindow * window) } } - GST_INFO ("end message loop\n"); + GST_INFO ("end message loop"); } /* Thread safe */ -void +static void gst_gl_window_win32_quit (GstGLWindow * window) { GstGLWindowWin32 *window_win32; @@ -398,7 +331,7 @@ gst_gl_window_win32_quit (GstGLWindow * window) } /* Thread safe */ -void +static void gst_gl_window_win32_send_message (GstGLWindow * window, GstGLWindowCB callback, gpointer data) { @@ -420,73 +353,33 @@ LRESULT CALLBACK window_proc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { GstGLWindowWin32 *window_win32; - GstGLWindowWin32Class *window_class; - GstGLWindowWin32Private *priv; - if (uMsg == WM_CREATE) { window_win32 = GST_GL_WINDOW_WIN32 (((LPCREATESTRUCT) lParam)->lpCreateParams); - window_class = GST_GL_WINDOW_WIN32_GET_CLASS (window_win32); - GST_DEBUG ("WM_CREATE\n"); + GST_TRACE ("WM_CREATE"); - { - priv = window_win32->priv; - window_win32->device = GetDC (hWnd); - - window_class->choose_format (window_win32); - - window_class->create_context (window_win32, priv->gl_api, - priv->external_gl_context, priv->error); - -/* priv->gl_context = wglCreateContext (priv->device); - if (priv->gl_context) - GST_DEBUG ("gl context created: %" G_GUINTPTR_FORMAT "\n", - (guintptr) priv->gl_context); - else - GST_DEBUG ("failed to create glcontext %" G_GUINTPTR_FORMAT ", %lud\n", - (guintptr) hWnd, GetLastError ()); - g_assert (priv->gl_context);*/ - ReleaseDC (hWnd, window_win32->device); - - window_class->activate (window_win32, TRUE); - -/* if (!wglMakeCurrent (priv->device, priv->gl_context)) - GST_DEBUG ("failed to make opengl context current %" G_GUINTPTR_FORMAT - ", %lud\n", (guintptr) hWnd, GetLastError ()); -*/ - if (priv->external_gl_context) - window_class->share_context (window_win32, priv->external_gl_context); -/* - if (priv->external_gl_context) { - if (!wglShareLists (priv->external_gl_context, priv->gl_context)) - GST_DEBUG ("failed to share opengl context %" G_GUINTPTR_FORMAT - " with %" G_GUINTPTR_FORMAT "\n", (guintptr) priv->gl_context, - (guintptr) priv->external_gl_context); - else - GST_DEBUG ("share opengl context succeed %" G_GUINTPTR_FORMAT "\n", - (guintptr) priv->external_gl_context); - }*/ - } + window_win32->device = GetDC (hWnd); + /* Do this, otherwise we hang on exit. We can still use it (due to the + * CS_OWNDC flag in the WindowClass) after we have Released. + */ + ReleaseDC (hWnd, window_win32->device); SetProp (hWnd, "gl_window", window_win32); - return 0; } else if (GetProp (hWnd, "gl_window")) { GstGLWindow *window; + GstGLContext *context; + GstGLContextClass *context_class; window_win32 = GST_GL_WINDOW_WIN32 (GetProp (hWnd, "gl_window")); - window_class = GST_GL_WINDOW_WIN32_GET_CLASS (window_win32); window = GST_GL_WINDOW (window_win32); - priv = window_win32->priv; + context = gst_gl_window_get_context (window); + context_class = GST_GL_CONTEXT_GET_CLASS (context); g_assert (window_win32->internal_win_id == hWnd); -/* g_assert (!wglGetCurrentContext () - || priv->gl_context == wglGetCurrentContext ()); -*/ switch (uMsg) { - case WM_SIZE: { if (window->resize) { @@ -495,36 +388,32 @@ window_proc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) } break; } - case WM_PAINT: { if (window->draw) { PAINTSTRUCT ps; BeginPaint (hWnd, &ps); window->draw (window->draw_data); - window_class->swap_buffers (window_win32); -// SwapBuffers (priv->device); + context_class->swap_buffers (context); EndPaint (hWnd, &ps); } break; } - case WM_CLOSE: { ShowWindowAsync (window_win32->internal_win_id, SW_HIDE); - GST_DEBUG ("WM_CLOSE\n"); + GST_TRACE ("WM_CLOSE"); if (window->close) window->close (window->close_data); break; } - case WM_GST_GL_WINDOW_QUIT: { HWND parent_id = 0; - GST_DEBUG ("WM_GST_GL_WINDOW_QUIT\n"); + GST_TRACE ("WM_GST_GL_WINDOW_QUIT"); parent_id = window_win32->parent_win_id; if (parent_id) { @@ -541,38 +430,22 @@ window_proc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) window_win32->is_closed = TRUE; RemoveProp (hWnd, "gl_window"); - window_class->activate (window_win32, FALSE); - - window_class->destroy_context (window_win32); - -/* if (!wglMakeCurrent (NULL, NULL)) - GST_DEBUG ("failed to make current %" G_GUINTPTR_FORMAT ", %lud\n", - (guintptr) hWnd, GetLastError ()); - - if (priv->gl_context) { - if (!wglDeleteContext (priv->gl_context)) - GST_DEBUG ("failed to destroy context %" G_GUINTPTR_FORMAT ", %lud\n", - (guintptr) priv->gl_context, GetLastError ()); - } -*/ if (window_win32->internal_win_id) { if (!DestroyWindow (window_win32->internal_win_id)) - GST_DEBUG ("failed to destroy window %" G_GUINTPTR_FORMAT - ", %lud\n", (guintptr) hWnd, GetLastError ()); + GST_WARNING ("failed to destroy window %" G_GUINTPTR_FORMAT + ", 0x%x", (guintptr) hWnd, (unsigned int) GetLastError ()); } PostQuitMessage (0); break; } - case WM_CAPTURECHANGED: { - GST_DEBUG ("WM_CAPTURECHANGED\n"); + GST_DEBUG ("WM_CAPTURECHANGED"); if (window->draw) window->draw (window->draw_data); break; } - case WM_GST_GL_WINDOW_CUSTOM: { if (!window_win32->is_closed) { @@ -581,10 +454,8 @@ window_proc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) } break; } - case WM_ERASEBKGND: return TRUE; - default: { /* transmit messages to the parrent (ex: mouse/keyboard input) */ @@ -595,9 +466,12 @@ window_proc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) } } + gst_object_unref (context); + return 0; - } else + } else { return DefWindowProc (hWnd, uMsg, wParam, lParam); + } } LRESULT FAR PASCAL diff --git a/gst-libs/gst/gl/win32/gstglwindow_win32.h b/gst-libs/gst/gl/win32/gstglwindow_win32.h index 67ea16f1d9..c4416e1974 100644 --- a/gst-libs/gst/gl/win32/gstglwindow_win32.h +++ b/gst-libs/gst/gl/win32/gstglwindow_win32.h @@ -77,6 +77,8 @@ GType gst_gl_window_win32_get_type (void); GstGLWindowWin32 * gst_gl_window_win32_new (void); +gboolean gst_gl_window_win32_create_window (GstGLWindowWin32 * window_win32, GError ** error); + G_END_DECLS #endif /* __GST_GL_WINDOW_WIN32_H__ */ diff --git a/gst-libs/gst/gl/win32/gstglwindow_win32_wgl.c b/gst-libs/gst/gl/win32/gstglwindow_win32_wgl.c deleted file mode 100644 index 063596710e..0000000000 --- a/gst-libs/gst/gl/win32/gstglwindow_win32_wgl.c +++ /dev/null @@ -1,229 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2008 Julien Isorce - * Copyright (C) 2012 Matthew Waters - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#define GLIB_DISABLE_DEPRECATION_WARNINGS - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include - -#include "../gstgl_fwd.h" -#include - -#include "gstglwindow_win32_wgl.h" - -#define GST_CAT_DEFAULT gst_gl_window_debug - -#define gst_gl_window_win32_wgl_parent_class parent_class -G_DEFINE_TYPE (GstGLWindowWin32WGL, gst_gl_window_win32_wgl, - GST_GL_TYPE_WINDOW_WIN32); - -static guintptr gst_gl_window_win32_wgl_get_gl_context (GstGLWindowWin32 * - window_win32); -static void gst_gl_window_win32_wgl_swap_buffers (GstGLWindowWin32 * - window_win32); -static gboolean gst_gl_window_win32_wgl_choose_format (GstGLWindowWin32 * - window_win32); -static gboolean gst_gl_window_win32_wgl_activate (GstGLWindowWin32 * - window_win32, gboolean activate); -static gboolean gst_gl_window_win32_wgl_create_context (GstGLWindowWin32 * - window_win32, GstGLAPI gl_api, guintptr external_gl_context, - GError ** error); -static void gst_gl_window_win32_wgl_destroy_context (GstGLWindowWin32 * - window_win32); -GstGLAPI gst_gl_window_win32_wgl_get_gl_api (GstGLWindow * window); -static gpointer gst_gl_window_win32_wgl_get_proc_address (GstGLWindow * window, - const gchar * name); - -static void -gst_gl_window_win32_wgl_class_init (GstGLWindowWin32WGLClass * klass) -{ - GstGLWindowClass *window_class = (GstGLWindowClass *) klass; - GstGLWindowWin32Class *window_win32_class = (GstGLWindowWin32Class *) klass; - - window_win32_class->get_gl_context = - GST_DEBUG_FUNCPTR (gst_gl_window_win32_wgl_get_gl_context); - window_win32_class->choose_format = - GST_DEBUG_FUNCPTR (gst_gl_window_win32_wgl_choose_format); - window_win32_class->activate = - GST_DEBUG_FUNCPTR (gst_gl_window_win32_wgl_activate); - window_win32_class->create_context = - GST_DEBUG_FUNCPTR (gst_gl_window_win32_wgl_create_context); - window_win32_class->destroy_context = - GST_DEBUG_FUNCPTR (gst_gl_window_win32_wgl_destroy_context); - window_win32_class->swap_buffers = - GST_DEBUG_FUNCPTR (gst_gl_window_win32_wgl_swap_buffers); - - window_class->get_proc_address = - GST_DEBUG_FUNCPTR (gst_gl_window_win32_wgl_get_proc_address); - window_class->get_gl_api = - GST_DEBUG_FUNCPTR (gst_gl_window_win32_wgl_get_gl_api); -} - -static void -gst_gl_window_win32_wgl_init (GstGLWindowWin32WGL * window) -{ -} - -/* Must be called in the gl thread */ -GstGLWindowWin32WGL * -gst_gl_window_win32_wgl_new (void) -{ - GstGLWindowWin32WGL *window = - g_object_new (GST_GL_TYPE_WINDOW_WIN32_WGL, NULL); - - return window; -} - -static gboolean -gst_gl_window_win32_wgl_create_context (GstGLWindowWin32 * window_win32, - GstGLAPI gl_api, guintptr external_gl_context, GError ** error) -{ - GstGLWindowWin32WGL *window_wgl; - - window_wgl = GST_GL_WINDOW_WIN32_WGL (window_win32); - - window_wgl->wgl_context = wglCreateContext (window_win32->device); - if (window_wgl->wgl_context) - GST_DEBUG ("gl context created: %" G_GUINTPTR_FORMAT, - (guintptr) window_wgl->wgl_context); - else { - g_set_error (error, GST_GL_WINDOW_ERROR, GST_GL_WINDOW_ERROR_CREATE_CONTEXT, - "failed to create glcontext:%lu", GetLastError ()); - goto failure; - } - g_assert (window_wgl->wgl_context); - - GST_LOG ("gl context id: %" G_GUINTPTR_FORMAT, - (guintptr) window_wgl->wgl_context); - - return TRUE; - -failure: - return FALSE; -} - -static void -gst_gl_window_win32_wgl_destroy_context (GstGLWindowWin32 * window_win32) -{ - GstGLWindowWin32WGL *window_wgl; - - window_wgl = GST_GL_WINDOW_WIN32_WGL (window_win32); - - if (window_wgl->wgl_context) - wglDeleteContext (window_wgl->wgl_context); - window_wgl->wgl_context = NULL; -} - -static gboolean -gst_gl_window_win32_wgl_choose_format (GstGLWindowWin32 * window_win32) -{ - PIXELFORMATDESCRIPTOR pfd; - gint pixelformat = 0; - gboolean res = FALSE; - - pfd.nSize = sizeof (PIXELFORMATDESCRIPTOR); - pfd.nVersion = 1; - pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER; - pfd.iPixelType = PFD_TYPE_RGBA; - pfd.cColorBits = 24; - pfd.cRedBits = 8; - pfd.cRedShift = 0; - pfd.cGreenBits = 8; - pfd.cGreenShift = 0; - pfd.cBlueBits = 8; - pfd.cBlueShift = 0; - pfd.cAlphaBits = 0; - pfd.cAlphaShift = 0; - pfd.cAccumBits = 0; - pfd.cAccumRedBits = 0; - pfd.cAccumGreenBits = 0; - pfd.cAccumBlueBits = 0; - pfd.cAccumAlphaBits = 0; - pfd.cDepthBits = 24; - pfd.cStencilBits = 8; - pfd.cAuxBuffers = 0; - pfd.iLayerType = PFD_MAIN_PLANE; - pfd.bReserved = 0; - pfd.dwLayerMask = 0; - pfd.dwVisibleMask = 0; - pfd.dwDamageMask = 0; - - pfd.cColorBits = (BYTE) GetDeviceCaps (window_win32->device, BITSPIXEL); - - pixelformat = ChoosePixelFormat (window_win32->device, &pfd); - - g_return_val_if_fail (pixelformat, FALSE); - - res = SetPixelFormat (window_win32->device, pixelformat, &pfd); - - return res; -} - -static void -gst_gl_window_win32_wgl_swap_buffers (GstGLWindowWin32 * window_win32) -{ - SwapBuffers (window_win32->device); -} - -static guintptr -gst_gl_window_win32_wgl_get_gl_context (GstGLWindowWin32 * window_win32) -{ - return (guintptr) GST_GL_WINDOW_WIN32_WGL (window_win32)->wgl_context; -} - -static gboolean -gst_gl_window_win32_wgl_activate (GstGLWindowWin32 * window_win32, - gboolean activate) -{ - gboolean result; - - if (activate) { - result = wglMakeCurrent (window_win32->device, - GST_GL_WINDOW_WIN32_WGL (window_win32)->wgl_context); - } else { - result = wglMakeCurrent (NULL, NULL); - } - - return result; -} - -GstGLAPI -gst_gl_window_win32_wgl_get_gl_api (GstGLWindow * window) -{ - return GST_GL_API_OPENGL; -} - -static gpointer -gst_gl_window_win32_wgl_get_proc_address (GstGLWindow * window, - const gchar * name) -{ - GstGLContext *context; - gpointer result; - - if (!(result = wglGetProcAddress ((LPCSTR) name))) { - result = gst_gl_context_default_get_proc_address (context, name); - } - - return result; -} diff --git a/gst-libs/gst/gl/win32/gstglwindow_win32_wgl.h b/gst-libs/gst/gl/win32/gstglwindow_win32_wgl.h deleted file mode 100644 index ac1a108824..0000000000 --- a/gst-libs/gst/gl/win32/gstglwindow_win32_wgl.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2012 Matthew Waters - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#ifndef __GST_GL_WINDOW_WIN32_WGL_H__ -#define __GST_GL_WINDOW_WIN32_WGL_H__ - -#include "gstglwindow_win32.h" - -G_BEGIN_DECLS - -#define GST_GL_TYPE_WINDOW_WIN32_WGL (gst_gl_window_win32_wgl_get_type()) -#define GST_GL_WINDOW_WIN32_WGL(o) (G_TYPE_CHECK_INSTANCE_CAST((o), GST_GL_TYPE_WINDOW_WIN32_WGL, GstGLWindowWin32WGL)) -#define GST_GL_WINDOW_WIN32_WGL_CLASS(k) (G_TYPE_CHECK_CLASS((k), GST_GL_TYPE_WINDOW_WIN32_WGL, GstGLWindowWin32WGLClass)) -#define GST_GL_IS_WINDOW_WIN32_WGL(o) (G_TYPE_CHECK_INSTANCE_TYPE((o), GST_GL_TYPE_WINDOW_WIN32_WGL)) -#define GST_GL_IS_WINDOW_WIN32_WGL_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE((k), GST_GL_TYPE_WINDOW_WIN32_WGL)) -#define GST_GL_WINDOW_WIN32_WGL_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS((o), GST_GL_TYPE_WINDOW_WIN32_WGL, GstGLWindowWin32WGLClass)) - -typedef struct _GstGLWindowWin32WGL GstGLWindowWin32WGL; -typedef struct _GstGLWindowWin32WGLClass GstGLWindowWin32WGLClass; - -struct _GstGLWindowWin32WGL { - /*< private >*/ - GstGLWindowWin32 parent; - - HGLRC wgl_context; - HGLRC external_gl_context; - - gpointer _reserved[GST_PADDING]; -}; - -struct _GstGLWindowWin32WGLClass { - /*< private >*/ - GstGLWindowWin32Class parent_class; - - /*< private >*/ - gpointer _reserved[GST_PADDING]; -}; - -GType gst_gl_window_win32_wgl_get_type (void); - -GstGLWindowWin32WGL * gst_gl_window_win32_wgl_new (void); - -G_END_DECLS - -#endif /* __GST_GL_WINDOW_X11_H__ */ diff --git a/gst-libs/gst/gl/x11/Makefile.am b/gst-libs/gst/gl/x11/Makefile.am index 0dbcb4482e..e5db6d0528 100644 --- a/gst-libs/gst/gl/x11/Makefile.am +++ b/gst-libs/gst/gl/x11/Makefile.am @@ -11,14 +11,15 @@ noinst_HEADERS = \ x11_event_source.h if USE_GLX -libgstgl_x11_la_SOURCES += gstglwindow_x11_glx.c -noinst_HEADERS += gstglwindow_x11_glx.h -endif -if USE_EGL -libgstgl_x11_la_SOURCES += gstglwindow_x11_egl.c -noinst_HEADERS += gstglwindow_x11_egl.h +libgstgl_x11_la_SOURCES += gstglcontext_glx.c +noinst_HEADERS += gstglcontext_glx.h endif +#if USE_EGL +#libgstgl_x11_la_SOURCES += gstglwindow_x11_egl.c +#noinst_HEADERS += gstglwindow_x11_egl.h +#endif + libgstgl_x11_la_CFLAGS = \ -I$(top_srcdir)/gst-libs \ $(GL_CFLAGS) \ diff --git a/gst-libs/gst/gl/x11/gstglcontext_glx.c b/gst-libs/gst/gl/x11/gstglcontext_glx.c new file mode 100644 index 0000000000..86c9d8a380 --- /dev/null +++ b/gst-libs/gst/gl/x11/gstglcontext_glx.c @@ -0,0 +1,396 @@ +/* + * GStreamer + * Copyright (C) 2008 Julien Isorce + * Copyright (C) 2012 Matthew Waters + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#define GLIB_DISABLE_DEPRECATION_WARNINGS + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include "../gstgl_fwd.h" +#include + +#include +#include "gstglcontext_glx.h" + +#define GST_CAT_DEFAULT gst_gl_window_debug + +#define gst_gl_context_glx_parent_class parent_class +G_DEFINE_TYPE (GstGLContextGLX, gst_gl_context_glx, GST_GL_TYPE_CONTEXT); + +#define GST_GL_CONTEXT_GLX_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE((o), GST_GL_TYPE_CONTEXT_GLX, GstGLContextGLXPrivate)) + +static guintptr gst_gl_context_glx_get_gl_context (GstGLContext * context); +static void gst_gl_context_glx_swap_buffers (GstGLContext * context); +static gboolean gst_gl_context_glx_activate (GstGLContext * context, + gboolean activate); +static gboolean gst_gl_context_glx_create_context (GstGLContext * + context, GstGLAPI gl_api, guintptr external_gl_context, GError ** error); +static void gst_gl_context_glx_destroy_context (GstGLContext * context); +static gboolean gst_gl_context_glx_choose_format (GstGLContext * + context, GError ** error); +GstGLAPI gst_gl_context_glx_get_gl_api (GstGLContext * context); +static gpointer gst_gl_context_glx_get_proc_address (GstGLContext * context, + const gchar * name); + +struct _GstGLContextGLXPrivate +{ + int glx_major; + int glx_minor; + + GstGLAPI context_api; + + GLXFBConfig *fbconfigs; + GLXContext (*glXCreateContextAttribsARB) (Display *, GLXFBConfig, + GLXContext, Bool, const int *); +}; + +static void +gst_gl_context_glx_class_init (GstGLContextGLXClass * klass) +{ + GstGLContextClass *context_class = (GstGLContextClass *) klass; + + g_type_class_add_private (klass, sizeof (GstGLContextGLXPrivate)); + + context_class->get_gl_context = + GST_DEBUG_FUNCPTR (gst_gl_context_glx_get_gl_context); + context_class->activate = GST_DEBUG_FUNCPTR (gst_gl_context_glx_activate); + context_class->create_context = + GST_DEBUG_FUNCPTR (gst_gl_context_glx_create_context); + context_class->destroy_context = + GST_DEBUG_FUNCPTR (gst_gl_context_glx_destroy_context); + context_class->choose_format = + GST_DEBUG_FUNCPTR (gst_gl_context_glx_choose_format); + context_class->swap_buffers = + GST_DEBUG_FUNCPTR (gst_gl_context_glx_swap_buffers); + + context_class->get_gl_api = GST_DEBUG_FUNCPTR (gst_gl_context_glx_get_gl_api); + context_class->get_proc_address = + GST_DEBUG_FUNCPTR (gst_gl_context_glx_get_proc_address); +} + +static void +gst_gl_context_glx_init (GstGLContextGLX * context) +{ + context->priv = GST_GL_CONTEXT_GLX_GET_PRIVATE (context); +} + +GstGLContextGLX * +gst_gl_context_glx_new (void) +{ + GstGLContextGLX *window = g_object_new (GST_GL_TYPE_CONTEXT_GLX, NULL); + + return window; +} + +static inline void +_describe_fbconfig (Display * display, GLXFBConfig config) +{ + int val; + + glXGetFBConfigAttrib (display, config, GLX_FBCONFIG_ID, &val); + GST_DEBUG ("ID: %d", val); + glXGetFBConfigAttrib (display, config, GLX_DOUBLEBUFFER, &val); + GST_DEBUG ("double buffering: %d", val); + glXGetFBConfigAttrib (display, config, GLX_RED_SIZE, &val); + GST_DEBUG ("red: %d", val); + glXGetFBConfigAttrib (display, config, GLX_GREEN_SIZE, &val); + GST_DEBUG ("green: %d", val); + glXGetFBConfigAttrib (display, config, GLX_BLUE_SIZE, &val); + GST_DEBUG ("blue: %d", val); + glXGetFBConfigAttrib (display, config, GLX_ALPHA_SIZE, &val); + GST_DEBUG ("alpha: %d", val); + glXGetFBConfigAttrib (display, config, GLX_DEPTH_SIZE, &val); + GST_DEBUG ("depth: %d", val); + glXGetFBConfigAttrib (display, config, GLX_STENCIL_SIZE, &val); + GST_DEBUG ("stencil: %d", val); +} + +static gboolean +gst_gl_context_glx_create_context (GstGLContext * context, + GstGLAPI gl_api, guintptr external_gl_context, GError ** error) +{ + GstGLContextGLX *context_glx; + GstGLWindow *window; + GstGLWindowX11 *window_x11; + gboolean create_context; + const char *glx_exts; + int x_error; + Display *device; + + context_glx = GST_GL_CONTEXT_GLX (context); + window = gst_gl_context_get_window (context); + window_x11 = GST_GL_WINDOW_X11 (window); + device = (Display *) gst_gl_window_get_display (window); + + glx_exts = glXQueryExtensionsString (device, DefaultScreen (device)); + + create_context = gst_gl_check_extension ("GLX_ARB_create_context", glx_exts); + context_glx->priv->glXCreateContextAttribsARB = + (gpointer) glXGetProcAddressARB ((const GLubyte *) + "glXCreateContextAttribsARB"); + + if (create_context && context_glx->priv->glXCreateContextAttribsARB) { + int context_attribs_3[] = { + GLX_CONTEXT_MAJOR_VERSION_ARB, 3, + GLX_CONTEXT_MINOR_VERSION_ARB, 0, + //GLX_CONTEXT_FLAGS_ARB , GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB, + None + }; + + int context_attribs_pre_3[] = { + GLX_CONTEXT_MAJOR_VERSION_ARB, 1, + GLX_CONTEXT_MINOR_VERSION_ARB, 4, + None + }; + + gst_gl_window_x11_trap_x_errors (); + context_glx->glx_context = + context_glx->priv->glXCreateContextAttribsARB (device, + context_glx->priv->fbconfigs[0], (GLXContext) external_gl_context, True, + context_attribs_3); + + x_error = gst_gl_window_x11_untrap_x_errors (); + context_glx->priv->context_api = GST_GL_API_OPENGL3 | GST_GL_API_OPENGL; + + if (!context_glx->glx_context || x_error != 0) { + GST_DEBUG ("Failed to create an Opengl 3 context. trying a legacy one"); + + gst_gl_window_x11_trap_x_errors (); + context_glx->glx_context = + context_glx->priv->glXCreateContextAttribsARB (device, + context_glx->priv->fbconfigs[0], (GLXContext) external_gl_context, + True, context_attribs_pre_3); + + x_error = gst_gl_window_x11_untrap_x_errors (); + + if (x_error != 0) + context_glx->glx_context = NULL; + context_glx->priv->context_api = GST_GL_API_OPENGL; + } + + } else { + context_glx->glx_context = + glXCreateContext (device, window_x11->visual_info, + (GLXContext) external_gl_context, TRUE); + context_glx->priv->context_api = GST_GL_API_OPENGL; + } + + if (context_glx->priv->fbconfigs) + XFree (context_glx->priv->fbconfigs); + + if (!context_glx->glx_context) { + g_set_error (error, GST_GL_WINDOW_ERROR, GST_GL_WINDOW_ERROR_CREATE_CONTEXT, + "Failed to create opengl context"); + goto failure; + } + + GST_LOG ("gl context id: %ld", (gulong) context_glx->glx_context); + + gst_object_unref (window); + + return TRUE; + +failure: + if (window) + gst_object_unref (window); + + return FALSE; +} + +static void +gst_gl_context_glx_destroy_context (GstGLContext * context) +{ + GstGLWindow *window; + GstGLContextGLX *context_glx; + Display *device; + + context_glx = GST_GL_CONTEXT_GLX (context); + window = gst_gl_context_get_window (context); + device = (Display *) gst_gl_window_get_display (window); + + glXDestroyContext (device, context_glx->glx_context); + + context_glx->glx_context = 0; + + gst_object_unref (window); +} + +static gboolean +gst_gl_context_glx_choose_format (GstGLContext * context, GError ** error) +{ + GstGLContextGLX *context_glx; + GstGLWindow *window; + GstGLWindowX11 *window_x11; + gint error_base; + gint event_base; + Display *device; + + context_glx = GST_GL_CONTEXT_GLX (context); + window = gst_gl_context_get_window (context); + window_x11 = GST_GL_WINDOW_X11 (window); + device = (Display *) gst_gl_window_get_display (window); + + if (!glXQueryExtension (device, &error_base, &event_base)) { + g_set_error (error, GST_GL_WINDOW_ERROR, + GST_GL_WINDOW_ERROR_RESOURCE_UNAVAILABLE, "No GLX extension"); + goto failure; + } + + if (!glXQueryVersion (device, &context_glx->priv->glx_major, + &context_glx->priv->glx_minor)) { + g_set_error (error, GST_GL_WINDOW_ERROR, GST_GL_WINDOW_ERROR_CREATE_CONTEXT, + "Failed to query GLX version (glXQueryVersion failed)"); + goto failure; + } + + GST_INFO ("GLX Version: %d.%d", context_glx->priv->glx_major, + context_glx->priv->glx_minor); + + /* legacy case */ + if (context_glx->priv->glx_major < 1 || (context_glx->priv->glx_major == 1 + && context_glx->priv->glx_minor < 3)) { + gint attribs[] = { + GLX_RGBA, + GLX_RED_SIZE, 1, + GLX_GREEN_SIZE, 1, + GLX_BLUE_SIZE, 1, + GLX_DEPTH_SIZE, 16, + GLX_DOUBLEBUFFER, + None + }; + + window_x11->visual_info = glXChooseVisual (device, + window_x11->screen_num, attribs); + + if (!window_x11->visual_info) { + g_set_error (error, GST_GL_WINDOW_ERROR, GST_GL_WINDOW_ERROR_WRONG_CONFIG, + "Bad attributes in glXChooseVisual"); + goto failure; + } + } else { + gint attribs[] = { + GLX_RENDER_TYPE, GLX_RGBA_BIT, + GLX_RED_SIZE, 1, + GLX_GREEN_SIZE, 1, + GLX_BLUE_SIZE, 1, + GLX_DEPTH_SIZE, 16, + GLX_DOUBLEBUFFER, True, + None + }; + int fbcount; + + context_glx->priv->fbconfigs = glXChooseFBConfig (device, + DefaultScreen (device), attribs, &fbcount); + + if (!context_glx->priv->fbconfigs) { + g_set_error (error, GST_GL_WINDOW_ERROR, GST_GL_WINDOW_ERROR_WRONG_CONFIG, + "Could not find any FBConfig's to use (check attributes?)"); + goto failure; + } + + _describe_fbconfig (device, context_glx->priv->fbconfigs[0]); + + window_x11->visual_info = glXGetVisualFromFBConfig (device, + context_glx->priv->fbconfigs[0]); + + if (!window_x11->visual_info) { + g_set_error (error, GST_GL_WINDOW_ERROR, GST_GL_WINDOW_ERROR_WRONG_CONFIG, + "Bad attributes in FBConfig"); + goto failure; + } + } + + gst_gl_window_x11_create_window ((GstGLWindowX11 *) window); + + gst_object_unref (window); + + return TRUE; + +failure: + if (window) + gst_object_unref (window); + + return FALSE; +} + +static void +gst_gl_context_glx_swap_buffers (GstGLContext * context) +{ + GstGLWindow *window = gst_gl_context_get_window (context); + Display *device = (Display *) gst_gl_window_get_display (window); + Window window_handle = (Window) gst_gl_window_get_window_handle (window); + + glXSwapBuffers (device, window_handle); + + gst_object_unref (window); +} + +static guintptr +gst_gl_context_glx_get_gl_context (GstGLContext * context) +{ + return (guintptr) GST_GL_CONTEXT_GLX (context)->glx_context; +} + +static gboolean +gst_gl_context_glx_activate (GstGLContext * context, gboolean activate) +{ + GstGLWindow *window = gst_gl_context_get_window (context); + Display *device = (Display *) gst_gl_window_get_display (window); + Window window_handle = (Window) gst_gl_window_get_window_handle (window); + gboolean result; + + if (activate) { + result = glXMakeCurrent (device, window_handle, + GST_GL_CONTEXT_GLX (context)->glx_context); + } else { + result = glXMakeCurrent (device, None, NULL); + } + + gst_object_unref (window); + + return result; +} + +GstGLAPI +gst_gl_context_glx_get_gl_api (GstGLContext * context) +{ + GstGLContextGLX *context_glx; + + context_glx = GST_GL_CONTEXT_GLX (context); + + return context_glx->priv->context_api; +} + +static gpointer +gst_gl_context_glx_get_proc_address (GstGLContext * context, const gchar * name) +{ + gpointer result; + + if (!(result = glXGetProcAddressARB ((const GLubyte *) name))) { + result = gst_gl_context_default_get_proc_address (context, name); + } + + return result; +} diff --git a/gst-libs/gst/gl/x11/gstglcontext_glx.h b/gst-libs/gst/gl/x11/gstglcontext_glx.h new file mode 100644 index 0000000000..eca8d7f5d6 --- /dev/null +++ b/gst-libs/gst/gl/x11/gstglcontext_glx.h @@ -0,0 +1,66 @@ +/* + * GStreamer + * Copyright (C) 2012 Matthew Waters + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __GST_GL_CONTEXT_GLX_H__ +#define __GST_GL_CONTEXT_GLX_H__ + +#include "gstglwindow_x11.h" + +#include + +G_BEGIN_DECLS + +#define GST_GL_TYPE_CONTEXT_GLX (gst_gl_context_glx_get_type()) +#define GST_GL_CONTEXT_GLX(o) (G_TYPE_CHECK_INSTANCE_CAST((o), GST_GL_TYPE_CONTEXT_GLX, GstGLContextGLX)) +#define GST_GL_CONTEXT_GLX_CLASS(k) (G_TYPE_CHECK_CLASS((k), GST_GL_TYPE_CONTEXT_GLX, GstGLContextGLXClass)) +#define GST_GL_IS_CONTEXT_GLX(o) (G_TYPE_CHECK_INSTANCE_TYPE((o), GST_GL_TYPE_CONTEXT_GLX)) +#define GST_GL_IS_CONTEXT_GLX_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE((k), GST_GL_TYPE_CONTEXT_GLX)) +#define GST_GL_CONTEXT_GLX_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS((o), GST_GL_TYPE_CONTEXT_GLX, GstGLContextGLX_Class)) + +typedef struct _GstGLContextGLX GstGLContextGLX; +typedef struct _GstGLContextGLXClass GstGLContextGLXClass; +typedef struct _GstGLContextGLXPrivate GstGLContextGLXPrivate; + +struct _GstGLContextGLX { + /*< private >*/ + GstGLContext parent; + + GLXContext glx_context; + + GstGLContextGLXPrivate *priv; + + gpointer _reserved[GST_PADDING]; +}; + +struct _GstGLContextGLXClass { + /*< private >*/ + GstGLContextClass parent_class; + + /*< private >*/ + gpointer _reserved[GST_PADDING]; +}; + +GType gst_gl_context_glx_get_type (void); + +GstGLContextGLX * gst_gl_context_glx_new (void); + +G_END_DECLS + +#endif /* __GST_GL_CONTEXT_H__ */ diff --git a/gst-libs/gst/gl/x11/gstglwindow_x11.c b/gst-libs/gst/gl/x11/gstglwindow_x11.c index cf5d241a4d..7af3211d51 100644 --- a/gst-libs/gst/gl/x11/gstglwindow_x11.c +++ b/gst-libs/gst/gl/x11/gstglwindow_x11.c @@ -31,20 +31,13 @@ #include "x11_event_source.h" #include "gstglwindow_x11.h" -#if GST_GL_HAVE_PLATFORM_GLX -# include "gstglwindow_x11_glx.h" -#endif -#if GST_GL_HAVE_PLATFORM_EGL -# include "gstglwindow_x11_egl.h" -#endif - #define GST_GL_WINDOW_X11_GET_PRIVATE(o) \ (G_TYPE_INSTANCE_GET_PRIVATE((o), GST_GL_TYPE_WINDOW_X11, GstGLWindowX11Private)) #define GST_CAT_DEFAULT gst_gl_window_debug #define gst_gl_window_x11_parent_class parent_class -G_DEFINE_ABSTRACT_TYPE (GstGLWindowX11, gst_gl_window_x11, GST_GL_TYPE_WINDOW); +G_DEFINE_TYPE (GstGLWindowX11, gst_gl_window_x11, GST_GL_TYPE_WINDOW); /* X error trap */ static int TrappedErrorCode = 0; @@ -62,10 +55,12 @@ struct _GstGLWindowX11Private gboolean activate_result; }; +guintptr gst_gl_window_x11_get_display (GstGLWindow * window); guintptr gst_gl_window_x11_get_gl_context (GstGLWindow * window); gboolean gst_gl_window_x11_activate (GstGLWindow * window, gboolean activate); void gst_gl_window_x11_set_window_handle (GstGLWindow * window, guintptr handle); +guintptr gst_gl_window_x11_get_window_handle (GstGLWindow * window); void gst_gl_window_x11_draw_unlocked (GstGLWindow * window, guint width, guint height); void gst_gl_window_x11_draw (GstGLWindow * window, guint width, guint height); @@ -78,8 +73,6 @@ gboolean gst_gl_window_x11_create_context (GstGLWindow * window, gboolean gst_gl_window_x11_open (GstGLWindow * window, GError ** error); void gst_gl_window_x11_close (GstGLWindow * window); -static gboolean gst_gl_window_x11_create_window (GstGLWindowX11 * window_x11); - static void gst_gl_window_x11_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) @@ -150,13 +143,11 @@ gst_gl_window_x11_class_init (GstGLWindowX11Class * klass) g_param_spec_string ("display", "Display", "X Display name", NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - window_class->create_context = - GST_DEBUG_FUNCPTR (gst_gl_window_x11_create_context); - window_class->get_gl_context = - GST_DEBUG_FUNCPTR (gst_gl_window_x11_get_gl_context); - window_class->activate = GST_DEBUG_FUNCPTR (gst_gl_window_x11_activate); + window_class->get_display = GST_DEBUG_FUNCPTR (gst_gl_window_x11_get_display); window_class->set_window_handle = GST_DEBUG_FUNCPTR (gst_gl_window_x11_set_window_handle); + window_class->get_window_handle = + GST_DEBUG_FUNCPTR (gst_gl_window_x11_get_window_handle); window_class->draw_unlocked = GST_DEBUG_FUNCPTR (gst_gl_window_x11_draw_unlocked); window_class->draw = GST_DEBUG_FUNCPTR (gst_gl_window_x11_draw); @@ -181,26 +172,10 @@ GstGLWindowX11 * gst_gl_window_x11_new (void) { GstGLWindowX11 *window = NULL; - const gchar *user_choice; - user_choice = g_getenv ("GST_GL_PLATFORM"); + window = g_object_new (GST_GL_TYPE_WINDOW_X11, NULL); - GST_INFO ("Attempting to create x11 window, user platform choice:%s", - user_choice ? user_choice : "(null)"); - -#if GST_GL_HAVE_PLATFORM_GLX - if (!window && (!user_choice || g_strstr_len (user_choice, 3, "glx") != NULL)) - window = GST_GL_WINDOW_X11 (gst_gl_window_x11_glx_new ()); -#endif /* GST_GL_HAVE_PLATFORM_GLX */ -#ifdef GST_GL_HAVE_PLATFORM_EGL - if (!window && (!user_choice || g_strstr_len (user_choice, 3, "egl") != NULL)) - window = GST_GL_WINDOW_X11 (gst_gl_window_x11_egl_new ()); -#endif /* GST_GL_HAVE_PLATFORM_EGL */ - if (!window) { - GST_WARNING ("Failed to create x11 window, user_choice:%s", - user_choice ? user_choice : "NULL"); - return NULL; - } + gst_gl_window_set_need_lock (GST_GL_WINDOW (window), FALSE); return window; } @@ -228,27 +203,6 @@ gst_gl_window_x11_open (GstGLWindow * window, GError ** error) GST_LOG ("gl display sender: %ld", (gulong) window_x11->disp_send); - return TRUE; - -failure: - return FALSE; -} - -gboolean -gst_gl_window_x11_create_context (GstGLWindow * window, - GstGLAPI gl_api, guintptr external_gl_context, GError ** error) -{ - GstGLWindowX11 *window_x11 = GST_GL_WINDOW_X11 (window); - GstGLWindowX11Class *window_class = GST_GL_WINDOW_X11_GET_CLASS (window_x11); - - setlocale (LC_NUMERIC, "C"); - - gst_gl_window_set_need_lock (GST_GL_WINDOW (window_x11), FALSE); - - window_x11->running = TRUE; - window_x11->visible = FALSE; - window_x11->allow_extra_expose_events = TRUE; - g_assert (window_x11->device); window_x11->screen = DefaultScreenOfDisplay (window_x11->device); @@ -273,6 +227,28 @@ gst_gl_window_x11_create_context (GstGLWindow * window, g_source_attach (window_x11->x11_source, window_x11->main_context); + window_x11->allow_extra_expose_events = TRUE; + + return TRUE; + +failure: + return FALSE; +} + +gboolean +gst_gl_window_x11_create_context (GstGLWindow * window, + GstGLAPI gl_api, guintptr external_gl_context, GError ** error) +{ + GstGLWindowX11 *window_x11 = GST_GL_WINDOW_X11 (window); + GstGLWindowX11Class *window_class = GST_GL_WINDOW_X11_GET_CLASS (window_x11); + + setlocale (LC_NUMERIC, "C"); + + gst_gl_window_set_need_lock (GST_GL_WINDOW (window_x11), FALSE); + + window_x11->running = TRUE; + window_x11->visible = FALSE; + if (!window_class->choose_format (window_x11, error)) { goto failure; } @@ -296,7 +272,7 @@ failure: return FALSE; } -static gboolean +gboolean gst_gl_window_x11_create_window (GstGLWindowX11 * window_x11) { XSetWindowAttributes win_attr; @@ -373,9 +349,7 @@ void gst_gl_window_x11_close (GstGLWindow * window) { GstGLWindowX11 *window_x11 = GST_GL_WINDOW_X11 (window); - GstGLWindowX11Class *window_class = GST_GL_WINDOW_X11_GET_CLASS (window_x11); XEvent event; - Bool ret = TRUE; GST_GL_WINDOW_LOCK (window_x11); @@ -383,11 +357,6 @@ gst_gl_window_x11_close (GstGLWindow * window) if (window_x11->internal_win_id) XUnmapWindow (window_x11->device, window_x11->internal_win_id); - ret = window_class->activate (window_x11, FALSE); - if (!ret) - GST_DEBUG ("failed to release opengl context"); - window_class->destroy_context (window_x11); - XFree (window_x11->visual_info); if (window_x11->internal_win_id) { @@ -482,7 +451,7 @@ gst_gl_window_x11_set_window_handle (GstGLWindow * window, guintptr id) window_x11->parent_win = (Window) id; - if (window_x11->running) { + if (g_main_loop_is_running (window_x11->loop)) { GST_LOG ("set parent window id: %lud", id); g_mutex_lock (&window_x11->disp_send_lock); @@ -499,6 +468,16 @@ gst_gl_window_x11_set_window_handle (GstGLWindow * window, guintptr id) } } +guintptr +gst_gl_window_x11_get_window_handle (GstGLWindow * window) +{ + GstGLWindowX11 *window_x11; + + window_x11 = GST_GL_WINDOW_X11 (window); + + return window_x11->internal_win_id; +} + /* Called in the gl thread */ void gst_gl_window_x11_draw_unlocked (GstGLWindow * window, guint width, @@ -508,7 +487,8 @@ gst_gl_window_x11_draw_unlocked (GstGLWindow * window, guint width, window_x11 = GST_GL_WINDOW_X11 (window); - if (window_x11->running && window_x11->allow_extra_expose_events) { + if (g_main_loop_is_running (window_x11->loop) + && window_x11->allow_extra_expose_events) { XEvent event; XWindowAttributes attr; @@ -539,7 +519,7 @@ gst_gl_window_x11_draw (GstGLWindow * window, guint width, guint height) window_x11 = GST_GL_WINDOW_X11 (window); - if (window_x11->running) { + if (g_main_loop_is_running (window_x11->loop)) { XEvent event; XWindowAttributes attr; @@ -634,26 +614,63 @@ gst_gl_window_x11_run (GstGLWindow * window) g_main_loop_run (window_x11->loop); } +inline gchar * +event_type_to_string (guint type) +{ + switch (type) { + case CreateNotify: + return "CreateNotify"; + case ConfigureNotify: + return "ConfigureNotify"; + case DestroyNotify: + return "DestroyNotify"; + case MapNotify: + return "MapNotify"; + case UnmapNotify: + return "UnmapNotify"; + case Expose: + return "Expose"; + case VisibilityNotify: + return "VisibilityNotify"; + case PropertyNotify: + return "PropertyNotify"; + case SelectionClear: + return "SelectionClear"; + case SelectionNotify: + return "SelectionNotify"; + case SelectionRequest: + return "SelectionRequest"; + case ClientMessage: + return "ClientMessage"; + default: + return "unknown"; + } +} + gboolean gst_gl_window_x11_handle_event (GstGLWindowX11 * window_x11) { + GstGLContext *context; + GstGLContextClass *context_class; GstGLWindow *window; - GstGLWindowX11Class *window_class; gboolean ret = TRUE; window = GST_GL_WINDOW (window_x11); - window_class = GST_GL_WINDOW_X11_GET_CLASS (window_x11); + context = gst_gl_window_get_context (window); + context_class = GST_GL_CONTEXT_GET_CLASS (context); - if (window_x11->running && XPending (window_x11->device)) { + if (g_main_loop_is_running (window_x11->loop) + && XPending (window_x11->device)) { XEvent event; /* XSendEvent (which are called in other threads) are done from another display structure */ XNextEvent (window_x11->device, &event); - // use in generic/cube and other related uses window_x11->allow_extra_expose_events = XPending (window_x11->device) <= 2; + GST_LOG ("got event %s", event_type_to_string (event.type)); + switch (event.type) { case ClientMessage: { @@ -690,7 +707,7 @@ gst_gl_window_x11_handle_event (GstGLWindowX11 * window_x11) case Expose: if (window->draw) { window->draw (window->draw_data); - window_class->swap_buffers (window_x11); + context_class->swap_buffers (context); } break; @@ -719,12 +736,14 @@ gst_gl_window_x11_handle_event (GstGLWindowX11 * window_x11) } default: - GST_DEBUG ("unknown XEvent type: %ud", event.type); + GST_DEBUG ("unknown XEvent type: %u", event.type); break; } // switch } // while running + gst_object_unref (context); + return ret; } @@ -752,7 +771,7 @@ gst_gl_window_x11_send_message (GstGLWindow * window, GstGLWindowCB callback, window_x11 = GST_GL_WINDOW_X11 (window); - if (window_x11->running) { + if (g_main_loop_is_running (window_x11->loop)) { GstGLMessage message; message.window = window; @@ -807,3 +826,13 @@ gst_gl_window_x11_untrap_x_errors (void) return TrappedErrorCode; } + +guintptr +gst_gl_window_x11_get_display (GstGLWindow * window) +{ + GstGLWindowX11 *window_x11; + + window_x11 = GST_GL_WINDOW_X11 (window); + + return (guintptr) window_x11->device; +} diff --git a/gst-libs/gst/gl/x11/gstglwindow_x11.h b/gst-libs/gst/gl/x11/gstglwindow_x11.h index 9e5f04a4f7..97347e0959 100644 --- a/gst-libs/gst/gl/x11/gstglwindow_x11.h +++ b/gst-libs/gst/gl/x11/gstglwindow_x11.h @@ -103,6 +103,8 @@ GstGLWindowX11 * gst_gl_window_x11_new (void); void gst_gl_window_x11_trap_x_errors (void); gint gst_gl_window_x11_untrap_x_errors (void); +gboolean gst_gl_window_x11_create_window (GstGLWindowX11 * window_x11); + G_END_DECLS #endif /* __GST_GL_WINDOW_X11_H__ */ diff --git a/gst-libs/gst/gl/x11/gstglwindow_x11_egl.c b/gst-libs/gst/gl/x11/gstglwindow_x11_egl.c deleted file mode 100644 index 45413fba8a..0000000000 --- a/gst-libs/gst/gl/x11/gstglwindow_x11_egl.c +++ /dev/null @@ -1,203 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2008 Julien Isorce - * Copyright (C) 2012 Matthew Waters - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#define GLIB_DISABLE_DEPRECATION_WARNINGS - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "../gstgl_fwd.h" -#include - -#include "gstglwindow_x11_egl.h" - -const gchar *X11EGLErrorString (); - -#define GST_CAT_DEFAULT gst_gl_window_debug - -#define gst_gl_window_x11_egl_parent_class parent_class -G_DEFINE_TYPE (GstGLWindowX11EGL, gst_gl_window_x11_egl, - GST_GL_TYPE_WINDOW_X11); - -static guintptr gst_gl_window_x11_egl_get_gl_context (GstGLWindowX11 * - window_x11); -static void gst_gl_window_x11_egl_swap_buffers (GstGLWindowX11 * window_x11); -static gboolean gst_gl_window_x11_egl_activate (GstGLWindowX11 * window_x11, - gboolean activate); -static gboolean gst_gl_window_x11_egl_create_context (GstGLWindowX11 * - window_x11, GstGLAPI gl_api, guintptr external_gl_context, GError ** error); -static void gst_gl_window_x11_egl_destroy_context (GstGLWindowX11 * window_x11); -static gboolean gst_gl_window_x11_egl_choose_format (GstGLWindowX11 * - window_x11, GError ** error); -GstGLAPI gst_gl_window_x11_egl_get_gl_api (GstGLWindow * window); -static gpointer gst_gl_window_x11_egl_get_proc_address (GstGLWindow * window, - const gchar * name); - -static void -gst_gl_window_x11_egl_class_init (GstGLWindowX11EGLClass * klass) -{ - GstGLWindowClass *window_class = (GstGLWindowClass *) klass; - GstGLWindowX11Class *window_x11_class = (GstGLWindowX11Class *) klass; - - window_x11_class->get_gl_context = - GST_DEBUG_FUNCPTR (gst_gl_window_x11_egl_get_gl_context); - window_x11_class->activate = - GST_DEBUG_FUNCPTR (gst_gl_window_x11_egl_activate); - window_x11_class->create_context = - GST_DEBUG_FUNCPTR (gst_gl_window_x11_egl_create_context); - window_x11_class->destroy_context = - GST_DEBUG_FUNCPTR (gst_gl_window_x11_egl_destroy_context); - window_x11_class->choose_format = - GST_DEBUG_FUNCPTR (gst_gl_window_x11_egl_choose_format); - window_x11_class->swap_buffers = - GST_DEBUG_FUNCPTR (gst_gl_window_x11_egl_swap_buffers); - - window_class->get_gl_api = - GST_DEBUG_FUNCPTR (gst_gl_window_x11_egl_get_gl_api); - window_class->get_proc_address = - GST_DEBUG_FUNCPTR (gst_gl_window_x11_egl_get_proc_address); -} - -static void -gst_gl_window_x11_egl_init (GstGLWindowX11EGL * window) -{ -} - -/* Must be called in the gl thread */ -GstGLWindowX11EGL * -gst_gl_window_x11_egl_new (void) -{ - GstGLWindowX11EGL *window = g_object_new (GST_GL_TYPE_WINDOW_X11_EGL, NULL); - - return window; -} - -static gboolean -gst_gl_window_x11_egl_choose_format (GstGLWindowX11 * window_x11, - GError ** error) -{ - gint ret; - - window_x11->visual_info = g_new0 (XVisualInfo, 1); - ret = XMatchVisualInfo (window_x11->device, window_x11->screen_num, - window_x11->depth, TrueColor, window_x11->visual_info); - - if (ret == 0) { - g_set_error (error, GST_GL_WINDOW_ERROR, GST_GL_WINDOW_ERROR_WRONG_CONFIG, - "Failed to match XVisualInfo"); - return FALSE; - } - - return TRUE; -} - -static gboolean -gst_gl_window_x11_egl_create_context (GstGLWindowX11 * window_x11, - GstGLAPI gl_api, guintptr external_gl_context, GError ** error) -{ - GstGLWindowX11EGL *window_egl; - - if ((gl_api & GST_GL_API_OPENGL) == GST_GL_API_NONE && - (gl_api & GST_GL_API_GLES2) == GST_GL_API_NONE) { - g_set_error (error, GST_GL_WINDOW_ERROR, GST_GL_WINDOW_ERROR_WRONG_API, - "xEGL supports opengl or gles2"); - goto failure; - } - - window_egl = GST_GL_WINDOW_X11_EGL (window_x11); - - window_egl->egl = - gst_gl_egl_create_context (eglGetDisplay ((EGLNativeDisplayType) - window_x11->device), - (EGLNativeWindowType) window_x11->internal_win_id, gl_api, - external_gl_context, error); - if (!window_egl->egl) - goto failure; - - return TRUE; - -failure: - return FALSE; -} - -static void -gst_gl_window_x11_egl_destroy_context (GstGLWindowX11 * window_x11) -{ - GstGLWindowX11EGL *window_egl; - - window_egl = GST_GL_WINDOW_X11_EGL (window_x11); - - gst_gl_egl_destroy_context (window_egl->egl); - window_egl->egl = NULL; -} - -static gboolean -gst_gl_window_x11_egl_activate (GstGLWindowX11 * window_x11, gboolean activate) -{ - GstGLWindowX11EGL *window_egl; - - window_egl = GST_GL_WINDOW_X11_EGL (window_x11); - - return gst_gl_egl_activate (window_egl->egl, activate); -} - -static guintptr -gst_gl_window_x11_egl_get_gl_context (GstGLWindowX11 * window_x11) -{ - GstGLWindowX11EGL *window_egl; - - window_egl = GST_GL_WINDOW_X11_EGL (window_x11); - - return gst_gl_egl_get_gl_context (window_egl->egl); -} - -static void -gst_gl_window_x11_egl_swap_buffers (GstGLWindowX11 * window_x11) -{ - GstGLWindowX11EGL *window_egl = GST_GL_WINDOW_X11_EGL (window_x11); - - gst_gl_egl_swap_buffers (window_egl->egl); -} - -GstGLAPI -gst_gl_window_x11_egl_get_gl_api (GstGLWindow * window) -{ - GstGLWindowX11EGL *window_egl = GST_GL_WINDOW_X11_EGL (window); - - return window_egl->egl ? gst_gl_egl_get_gl_api (window_egl-> - egl) : GST_GL_API_GLES2 | GST_GL_API_OPENGL; -} - -static gpointer -gst_gl_window_x11_egl_get_proc_address (GstGLWindow * window, - const gchar * name) -{ - GstGLContext *context = NULL; - GstGLWindowX11EGL *window_egl = GST_GL_WINDOW_X11_EGL (window); - gpointer result; - - if (!(result = gst_gl_egl_get_proc_address (window_egl->egl, name))) { - result = gst_gl_context_default_get_proc_address (context, name); - } - - return result; -} diff --git a/gst-libs/gst/gl/x11/gstglwindow_x11_egl.h b/gst-libs/gst/gl/x11/gstglwindow_x11_egl.h deleted file mode 100644 index ddd4a28506..0000000000 --- a/gst-libs/gst/gl/x11/gstglwindow_x11_egl.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2012 Matthew Waters - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#ifndef __GST_GL_WINDOW_X11_EGL_H__ -#define __GST_GL_WINDOW_X11_EGL_H__ - -#include "gstglwindow_x11.h" -#include "../gstglegl.h" - -#include - -G_BEGIN_DECLS - -#define GST_GL_TYPE_WINDOW_X11_EGL (gst_gl_window_x11_egl_get_type()) -#define GST_GL_WINDOW_X11_EGL(o) (G_TYPE_CHECK_INSTANCE_CAST((o), GST_GL_TYPE_WINDOW_X11_EGL, GstGLWindowX11EGL)) -#define GST_GL_WINDOW_X11_EGL_CLASS(k) (G_TYPE_CHECK_CLASS((k), GST_GL_TYPE_WINDOW_X11_EGL, GstGLWindowX11EGLClass)) -#define GST_GL_IS_WINDOW_X11_EGL(o) (G_TYPE_CHECK_INSTANCE_TYPE((o), GST_GL_TYPE_WINDOW_X11_EGL)) -#define GST_GL_IS_WINDOW_X11_EGL_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE((k), GST_GL_TYPE_WINDOW_X11_EGL)) -#define GST_GL_WINDOW_X11_EGL_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS((o), GST_GL_TYPE_WINDOW_X11_EGL, GstGLWindowX11EGL_Class)) - -typedef struct _GstGLWindowX11EGL GstGLWindowX11EGL; -typedef struct _GstGLWindowX11EGLClass GstGLWindowX11EGLClass; - -struct _GstGLWindowX11EGL { - /*< private >*/ - GstGLWindowX11 parent; - - GstGLEGL *egl; - - gpointer _reserved[GST_PADDING]; -}; - -struct _GstGLWindowX11EGLClass { - /*< private >*/ - GstGLWindowX11Class parent_class; - - /*< private >*/ - gpointer _reserved[GST_PADDING]; -}; - -GType gst_gl_window_x11_egl_get_type (void); - -GstGLWindowX11EGL * gst_gl_window_x11_egl_new (void); - -G_END_DECLS - -#endif /* __GST_GL_WINDOW_X11_H__ */ diff --git a/gst-libs/gst/gl/x11/gstglwindow_x11_glx.c b/gst-libs/gst/gl/x11/gstglwindow_x11_glx.c deleted file mode 100644 index 932502945d..0000000000 --- a/gst-libs/gst/gl/x11/gstglwindow_x11_glx.c +++ /dev/null @@ -1,366 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2008 Julien Isorce - * Copyright (C) 2012 Matthew Waters - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#define GLIB_DISABLE_DEPRECATION_WARNINGS - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include - -#include "../gstgl_fwd.h" -#include - -#include -#include "gstglwindow_x11_glx.h" - -#define GST_CAT_DEFAULT gst_gl_window_debug - -#define gst_gl_window_x11_glx_parent_class parent_class -G_DEFINE_TYPE (GstGLWindowX11GLX, gst_gl_window_x11_glx, - GST_GL_TYPE_WINDOW_X11); - -#define GST_GL_WINDOW_X11_GLX_GET_PRIVATE(o) \ - (G_TYPE_INSTANCE_GET_PRIVATE((o), GST_GL_TYPE_WINDOW_X11_GLX, GstGLWindowX11GLXPrivate)) - -static guintptr gst_gl_window_x11_glx_get_gl_context (GstGLWindowX11 * - window_x11); -static void gst_gl_window_x11_glx_swap_buffers (GstGLWindowX11 * window_x11); -static gboolean gst_gl_window_x11_glx_activate (GstGLWindowX11 * window_x11, - gboolean activate); -static gboolean gst_gl_window_x11_glx_create_context (GstGLWindowX11 * - window_x11, GstGLAPI gl_api, guintptr external_gl_context, GError ** error); -static void gst_gl_window_x11_glx_destroy_context (GstGLWindowX11 * window_x11); -static gboolean gst_gl_window_x11_glx_choose_format (GstGLWindowX11 * - window_x11, GError ** error); -GstGLAPI gst_gl_window_x11_glx_get_gl_api (GstGLWindow * window); -static gpointer gst_gl_window_x11_glx_get_proc_address (GstGLWindow * window, - const gchar * name); - -struct _GstGLWindowX11GLXPrivate -{ - int glx_major; - int glx_minor; - - GstGLAPI context_api; - - GLXFBConfig *fbconfigs; - GLXContext (*glXCreateContextAttribsARB) (Display *, GLXFBConfig, - GLXContext, Bool, const int *); -}; - -static void -gst_gl_window_x11_glx_class_init (GstGLWindowX11GLXClass * klass) -{ - GstGLWindowClass *window_class = (GstGLWindowClass *) klass; - GstGLWindowX11Class *window_x11_class = (GstGLWindowX11Class *) klass; - - g_type_class_add_private (klass, sizeof (GstGLWindowX11GLXPrivate)); - - window_x11_class->get_gl_context = - GST_DEBUG_FUNCPTR (gst_gl_window_x11_glx_get_gl_context); - window_x11_class->activate = - GST_DEBUG_FUNCPTR (gst_gl_window_x11_glx_activate); - window_x11_class->create_context = - GST_DEBUG_FUNCPTR (gst_gl_window_x11_glx_create_context); - window_x11_class->destroy_context = - GST_DEBUG_FUNCPTR (gst_gl_window_x11_glx_destroy_context); - window_x11_class->choose_format = - GST_DEBUG_FUNCPTR (gst_gl_window_x11_glx_choose_format); - window_x11_class->swap_buffers = - GST_DEBUG_FUNCPTR (gst_gl_window_x11_glx_swap_buffers); - - window_class->get_gl_api = - GST_DEBUG_FUNCPTR (gst_gl_window_x11_glx_get_gl_api); - window_class->get_proc_address = - GST_DEBUG_FUNCPTR (gst_gl_window_x11_glx_get_proc_address); -} - -static void -gst_gl_window_x11_glx_init (GstGLWindowX11GLX * window) -{ - window->priv = GST_GL_WINDOW_X11_GLX_GET_PRIVATE (window); -} - -/* Must be called in the gl thread */ -GstGLWindowX11GLX * -gst_gl_window_x11_glx_new (void) -{ - GstGLWindowX11GLX *window = g_object_new (GST_GL_TYPE_WINDOW_X11_GLX, NULL); - - return window; -} - -static inline void -_describe_fbconfig (Display * display, GLXFBConfig config) -{ - int val; - - glXGetFBConfigAttrib (display, config, GLX_FBCONFIG_ID, &val); - GST_DEBUG ("ID: %d", val); - glXGetFBConfigAttrib (display, config, GLX_DOUBLEBUFFER, &val); - GST_DEBUG ("double buffering: %d", val); - glXGetFBConfigAttrib (display, config, GLX_RED_SIZE, &val); - GST_DEBUG ("red: %d", val); - glXGetFBConfigAttrib (display, config, GLX_GREEN_SIZE, &val); - GST_DEBUG ("green: %d", val); - glXGetFBConfigAttrib (display, config, GLX_BLUE_SIZE, &val); - GST_DEBUG ("blue: %d", val); - glXGetFBConfigAttrib (display, config, GLX_ALPHA_SIZE, &val); - GST_DEBUG ("alpha: %d", val); - glXGetFBConfigAttrib (display, config, GLX_DEPTH_SIZE, &val); - GST_DEBUG ("depth: %d", val); - glXGetFBConfigAttrib (display, config, GLX_STENCIL_SIZE, &val); - GST_DEBUG ("stencil: %d", val); -} - -static gboolean -gst_gl_window_x11_glx_create_context (GstGLWindowX11 * window_x11, - GstGLAPI gl_api, guintptr external_gl_context, GError ** error) -{ - GstGLWindowX11GLX *window_glx; - gboolean create_context; - const char *glx_exts; - int x_error; - - window_glx = GST_GL_WINDOW_X11_GLX (window_x11); - - glx_exts = - glXQueryExtensionsString (window_x11->device, - DefaultScreen (window_x11->device)); - - create_context = gst_gl_check_extension ("GLX_ARB_create_context", glx_exts); - window_glx->priv->glXCreateContextAttribsARB = - (gpointer) glXGetProcAddressARB ((const GLubyte *) - "glXCreateContextAttribsARB"); - - if (create_context && window_glx->priv->glXCreateContextAttribsARB) { - int context_attribs_3[] = { - GLX_CONTEXT_MAJOR_VERSION_ARB, 3, - GLX_CONTEXT_MINOR_VERSION_ARB, 0, - //GLX_CONTEXT_FLAGS_ARB , GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB, - None - }; - - int context_attribs_pre_3[] = { - GLX_CONTEXT_MAJOR_VERSION_ARB, 1, - GLX_CONTEXT_MINOR_VERSION_ARB, 4, - None - }; - - gst_gl_window_x11_trap_x_errors (); - window_glx->glx_context = - window_glx->priv->glXCreateContextAttribsARB (window_x11->device, - window_glx->priv->fbconfigs[0], (GLXContext) external_gl_context, True, - context_attribs_3); - - x_error = gst_gl_window_x11_untrap_x_errors (); - window_glx->priv->context_api = GST_GL_API_OPENGL3 | GST_GL_API_OPENGL; - - if (!window_glx->glx_context || x_error != 0) { - GST_DEBUG ("Failed to create an Opengl 3 context. trying a legacy one"); - - gst_gl_window_x11_trap_x_errors (); - window_glx->glx_context = - window_glx->priv->glXCreateContextAttribsARB (window_x11->device, - window_glx->priv->fbconfigs[0], (GLXContext) external_gl_context, - True, context_attribs_pre_3); - - x_error = gst_gl_window_x11_untrap_x_errors (); - - if (x_error != 0) - window_glx->glx_context = NULL; - window_glx->priv->context_api = GST_GL_API_OPENGL; - } - - } else { - window_glx->glx_context = - glXCreateContext (window_x11->device, window_x11->visual_info, - (GLXContext) external_gl_context, TRUE); - window_glx->priv->context_api = GST_GL_API_OPENGL; - } - - if (window_glx->priv->fbconfigs) - XFree (window_glx->priv->fbconfigs); - - if (!window_glx->glx_context) { - g_set_error (error, GST_GL_WINDOW_ERROR, GST_GL_WINDOW_ERROR_CREATE_CONTEXT, - "Failed to create opengl context"); - goto failure; - } - - GST_LOG ("gl context id: %ld", (gulong) window_glx->glx_context); - - return TRUE; - -failure: - return FALSE; -} - -static void -gst_gl_window_x11_glx_destroy_context (GstGLWindowX11 * window_x11) -{ - GstGLWindowX11GLX *window_glx; - - window_glx = GST_GL_WINDOW_X11_GLX (window_x11); - - glXDestroyContext (window_x11->device, window_glx->glx_context); - - window_glx->glx_context = 0; -} - -static gboolean -gst_gl_window_x11_glx_choose_format (GstGLWindowX11 * window_x11, - GError ** error) -{ - GstGLWindowX11GLX *window_glx; - gint error_base; - gint event_base; - - window_glx = GST_GL_WINDOW_X11_GLX (window_x11); - - if (!glXQueryExtension (window_x11->device, &error_base, &event_base)) { - g_set_error (error, GST_GL_WINDOW_ERROR, - GST_GL_WINDOW_ERROR_RESOURCE_UNAVAILABLE, "No GLX extension"); - goto failure; - } - - if (!glXQueryVersion (window_x11->device, &window_glx->priv->glx_major, - &window_glx->priv->glx_minor)) { - g_set_error (error, GST_GL_WINDOW_ERROR, GST_GL_WINDOW_ERROR_CREATE_CONTEXT, - "Failed to query GLX version (glXQueryVersion failed)"); - goto failure; - } - - GST_INFO ("GLX Version: %d.%d", window_glx->priv->glx_major, - window_glx->priv->glx_minor); - - /* legacy case */ - if (window_glx->priv->glx_major < 1 || (window_glx->priv->glx_major == 1 - && window_glx->priv->glx_minor < 3)) { - gint attribs[] = { - GLX_RGBA, - GLX_RED_SIZE, 1, - GLX_GREEN_SIZE, 1, - GLX_BLUE_SIZE, 1, - GLX_DEPTH_SIZE, 16, - GLX_DOUBLEBUFFER, - None - }; - - window_x11->visual_info = glXChooseVisual (window_x11->device, - window_x11->screen_num, attribs); - - if (!window_x11->visual_info) { - g_set_error (error, GST_GL_WINDOW_ERROR, GST_GL_WINDOW_ERROR_WRONG_CONFIG, - "Bad attributes in glXChooseVisual"); - goto failure; - } - } else { - gint attribs[] = { - GLX_RENDER_TYPE, GLX_RGBA_BIT, - GLX_RED_SIZE, 1, - GLX_GREEN_SIZE, 1, - GLX_BLUE_SIZE, 1, - GLX_DEPTH_SIZE, 16, - GLX_DOUBLEBUFFER, True, - None - }; - int fbcount; - - window_glx->priv->fbconfigs = glXChooseFBConfig (window_x11->device, - DefaultScreen (window_x11->device), attribs, &fbcount); - - if (!window_glx->priv->fbconfigs) { - g_set_error (error, GST_GL_WINDOW_ERROR, GST_GL_WINDOW_ERROR_WRONG_CONFIG, - "Could not find any FBConfig's to use (check attributes?)"); - goto failure; - } - - _describe_fbconfig (window_x11->device, window_glx->priv->fbconfigs[0]); - - window_x11->visual_info = glXGetVisualFromFBConfig (window_x11->device, - window_glx->priv->fbconfigs[0]); - - if (!window_x11->visual_info) { - g_set_error (error, GST_GL_WINDOW_ERROR, GST_GL_WINDOW_ERROR_WRONG_CONFIG, - "Bad attributes in FBConfig"); - goto failure; - } - } - - return TRUE; - -failure: - return FALSE; -} - -static void -gst_gl_window_x11_glx_swap_buffers (GstGLWindowX11 * window_x11) -{ - glXSwapBuffers (window_x11->device, window_x11->internal_win_id); -} - -static guintptr -gst_gl_window_x11_glx_get_gl_context (GstGLWindowX11 * window_x11) -{ - return (guintptr) GST_GL_WINDOW_X11_GLX (window_x11)->glx_context; -} - -static gboolean -gst_gl_window_x11_glx_activate (GstGLWindowX11 * window_x11, gboolean activate) -{ - gboolean result; - - if (activate) { - result = glXMakeCurrent (window_x11->device, window_x11->internal_win_id, - GST_GL_WINDOW_X11_GLX (window_x11)->glx_context); - } else { - result = glXMakeCurrent (window_x11->device, None, NULL); - } - - return result; -} - -GstGLAPI -gst_gl_window_x11_glx_get_gl_api (GstGLWindow * window) -{ - GstGLWindowX11GLX *window_glx; - - window_glx = GST_GL_WINDOW_X11_GLX (window); - - return window_glx->priv->context_api; -} - -static gpointer -gst_gl_window_x11_glx_get_proc_address (GstGLWindow * window, - const gchar * name) -{ - GstGLContext *context = NULL; - gpointer result; - - if (!(result = glXGetProcAddressARB ((const GLubyte *) name))) { - result = gst_gl_context_default_get_proc_address (context, name); - } - - return result; -} diff --git a/gst-libs/gst/gl/x11/gstglwindow_x11_glx.h b/gst-libs/gst/gl/x11/gstglwindow_x11_glx.h deleted file mode 100644 index 4930054a25..0000000000 --- a/gst-libs/gst/gl/x11/gstglwindow_x11_glx.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2012 Matthew Waters - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#ifndef __GST_GL_WINDOW_X11_GLX_H__ -#define __GST_GL_WINDOW_X11_GLX_H__ - -#include "gstglwindow_x11.h" - -#include - -G_BEGIN_DECLS - -#define GST_GL_TYPE_WINDOW_X11_GLX (gst_gl_window_x11_glx_get_type()) -#define GST_GL_WINDOW_X11_GLX(o) (G_TYPE_CHECK_INSTANCE_CAST((o), GST_GL_TYPE_WINDOW_X11_GLX, GstGLWindowX11GLX)) -#define GST_GL_WINDOW_X11_GLX_CLASS(k) (G_TYPE_CHECK_CLASS((k), GST_GL_TYPE_WINDOW_X11_GLX, GstGLWindowX11GLXClass)) -#define GST_GL_IS_WINDOW_X11_GLX(o) (G_TYPE_CHECK_INSTANCE_TYPE((o), GST_GL_TYPE_WINDOW_X11_GLX)) -#define GST_GL_IS_WINDOW_X11_GLX_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE((k), GST_GL_TYPE_WINDOW_X11_GLX)) -#define GST_GL_WINDOW_X11_GLX_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS((o), GST_GL_TYPE_WINDOW_X11_GLX, GstGLWindowX11GLX_Class)) - -typedef struct _GstGLWindowX11GLX GstGLWindowX11GLX; -typedef struct _GstGLWindowX11GLXClass GstGLWindowX11GLXClass; -typedef struct _GstGLWindowX11GLXPrivate GstGLWindowX11GLXPrivate; - -struct _GstGLWindowX11GLX { - /*< private >*/ - GstGLWindowX11 parent; - - GLXContext glx_context; - - GstGLWindowX11GLXPrivate *priv; - - gpointer _reserved[GST_PADDING]; -}; - -struct _GstGLWindowX11GLXClass { - /*< private >*/ - GstGLWindowX11Class parent_class; - - /*< private >*/ - gpointer _reserved[GST_PADDING]; -}; - -GType gst_gl_window_x11_glx_get_type (void); - -GstGLWindowX11GLX * gst_gl_window_x11_glx_new (void); - -G_END_DECLS - -#endif /* __GST_GL_WINDOW_X11_H__ */