mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-23 15:48:23 +00:00
gl/cocoa: Call UI related API from the application main thread
This commit is contained in:
parent
2173d34462
commit
66cb4166d3
2 changed files with 106 additions and 116 deletions
|
@ -85,7 +85,7 @@ gst_gl_window_cocoa_nsapp_iteration (gpointer data)
|
||||||
if ([NSThread isMainThread]) {
|
if ([NSThread isMainThread]) {
|
||||||
|
|
||||||
while ((event = ([NSApp nextEventMatchingMask:NSAnyEventMask
|
while ((event = ([NSApp nextEventMatchingMask:NSAnyEventMask
|
||||||
untilDate:[NSDate dateWithTimeIntervalSinceNow:0.5]
|
untilDate:[NSDate dateWithTimeIntervalSinceNow:0.05]
|
||||||
inMode:NSDefaultRunLoopMode dequeue:YES])) != nil) {
|
inMode:NSDefaultRunLoopMode dequeue:YES])) != nil) {
|
||||||
|
|
||||||
[NSApp sendEvent:event];
|
[NSApp sendEvent:event];
|
||||||
|
@ -135,7 +135,7 @@ gst_gl_context_cocoa_class_init (GstGLContextCocoaClass * klass)
|
||||||
|
|
||||||
if ([NSThread isMainThread]) {
|
if ([NSThread isMainThread]) {
|
||||||
/* In the main thread so just do the call now */
|
/* In the main thread so just do the call now */
|
||||||
|
|
||||||
/* The sharedApplication class method initializes
|
/* The sharedApplication class method initializes
|
||||||
* the display environment and connects your program
|
* the display environment and connects your program
|
||||||
* to the window server and the display server
|
* to the window server and the display server
|
||||||
|
@ -201,17 +201,11 @@ gst_gl_context_cocoa_create_context (GstGLContext *context, GstGLAPI gl_api,
|
||||||
GstGLContextCocoaPrivate *priv = context_cocoa->priv;
|
GstGLContextCocoaPrivate *priv = context_cocoa->priv;
|
||||||
GstGLWindow *window = gst_gl_context_get_window (context);
|
GstGLWindow *window = gst_gl_context_get_window (context);
|
||||||
GstGLWindowCocoa *window_cocoa = GST_GL_WINDOW_COCOA (window);
|
GstGLWindowCocoa *window_cocoa = GST_GL_WINDOW_COCOA (window);
|
||||||
GstGLNSView *glView = nil;
|
__block NSOpenGLContext *glContext = nil;
|
||||||
NSWindow *window_handle;
|
|
||||||
NSRect rect;
|
#ifndef GNUSTEP
|
||||||
NSAutoreleasePool *pool;
|
priv->source_id = g_timeout_add (200, gst_gl_window_cocoa_nsapp_iteration, NULL);
|
||||||
NSOpenGLPixelFormat *fmt = nil;
|
#endif
|
||||||
NSOpenGLContext *glContext = nil;
|
|
||||||
NSOpenGLPixelFormatAttribute attribs[] = {
|
|
||||||
NSOpenGLPFADoubleBuffer,
|
|
||||||
NSOpenGLPFAAccumSize, 32,
|
|
||||||
0
|
|
||||||
};
|
|
||||||
|
|
||||||
priv->gl_context = nil;
|
priv->gl_context = nil;
|
||||||
if (other_context)
|
if (other_context)
|
||||||
|
@ -219,52 +213,64 @@ gst_gl_context_cocoa_create_context (GstGLContext *context, GstGLAPI gl_api,
|
||||||
else
|
else
|
||||||
priv->external_gl_context = NULL;
|
priv->external_gl_context = NULL;
|
||||||
|
|
||||||
#ifdef GNUSTEP
|
dispatch_sync (dispatch_get_main_queue (), ^{
|
||||||
GSRegisterCurrentThread();
|
NSAutoreleasePool *pool;
|
||||||
#endif
|
NSOpenGLPixelFormat *fmt = nil;
|
||||||
|
GstGLNSView *glView = nil;
|
||||||
|
NSOpenGLPixelFormatAttribute attribs[] = {
|
||||||
|
NSOpenGLPFADoubleBuffer,
|
||||||
|
NSOpenGLPFAAccumSize, 32,
|
||||||
|
0
|
||||||
|
};
|
||||||
|
NSRect rect;
|
||||||
|
NSWindow *window_handle;
|
||||||
|
|
||||||
pool = [[NSAutoreleasePool alloc] init];
|
pool = [[NSAutoreleasePool alloc] init];
|
||||||
|
|
||||||
#ifdef GNUSTEP
|
#ifdef GNUSTEP
|
||||||
[NSApplication sharedApplication];
|
[NSApplication sharedApplication];
|
||||||
#endif
|
#endif
|
||||||
|
rect.origin.x = 0;
|
||||||
|
rect.origin.y = 0;
|
||||||
|
rect.size.width = 320;
|
||||||
|
rect.size.height = 240;
|
||||||
|
|
||||||
rect.origin.x = 0;
|
gst_gl_window_cocoa_create_window (window_cocoa, rect);
|
||||||
rect.origin.y = 0;
|
window_handle = (NSWindow *) gst_gl_window_get_window_handle (window);
|
||||||
rect.size.width = 320;
|
|
||||||
rect.size.height = 240;
|
|
||||||
|
|
||||||
gst_gl_window_cocoa_create_window (window_cocoa, rect);
|
fmt = [[NSOpenGLPixelFormat alloc] initWithAttributes:attribs];
|
||||||
window_handle = (NSWindow *) gst_gl_window_get_window_handle (window);
|
if (!fmt) {
|
||||||
|
gst_object_unref (window);
|
||||||
|
GST_WARNING ("cannot create NSOpenGLPixelFormat");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
glView = [GstGLNSView alloc];
|
glView = [[GstGLNSView alloc] initWithFrame:window_cocoa rect:rect];
|
||||||
|
|
||||||
fmt = [[NSOpenGLPixelFormat alloc] initWithAttributes:attribs];
|
[window_handle setContentView:glView];
|
||||||
|
|
||||||
if (!fmt) {
|
|
||||||
gst_object_unref (window);
|
|
||||||
GST_WARNING ("cannot create NSOpenGLPixelFormat");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
glView = [glView initWithFrame:window_cocoa rect:rect];
|
|
||||||
|
|
||||||
[window_handle setContentView:glView];
|
|
||||||
|
|
||||||
#ifndef GNUSTEP
|
#ifndef GNUSTEP
|
||||||
glContext = [[NSOpenGLContext alloc] initWithFormat:fmt
|
glContext = [[NSOpenGLContext alloc] initWithFormat:fmt
|
||||||
shareContext:context_cocoa->priv->external_gl_context];
|
shareContext:context_cocoa->priv->external_gl_context];
|
||||||
|
|
||||||
GST_DEBUG ("NSOpenGL context created: %"G_GUINTPTR_FORMAT, (guintptr) glContext);
|
GST_DEBUG ("NSOpenGL context created: %"G_GUINTPTR_FORMAT, (guintptr) glContext);
|
||||||
|
|
||||||
context_cocoa->priv->gl_context = glContext;
|
context_cocoa->priv->gl_context = glContext;
|
||||||
|
|
||||||
[glContext setView:glView];
|
[glContext setView:glView];
|
||||||
|
|
||||||
#else
|
#else
|
||||||
/* FIXME try to make context sharing work in GNUstep */
|
/* FIXME try to make context sharing work in GNUstep */
|
||||||
context_cocoa->priv->gl_context = glContext;
|
context_cocoa->priv->gl_context = glContext;
|
||||||
#endif
|
#endif
|
||||||
|
[pool release];
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!glContext) {
|
||||||
|
g_source_remove (priv->source_id);
|
||||||
|
priv->source_id = 0;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
/* OpenGL context is made current only one time threre.
|
/* OpenGL context is made current only one time threre.
|
||||||
* Indeed, all OpenGL calls are made in only one thread,
|
* Indeed, all OpenGL calls are made in only one thread,
|
||||||
|
@ -290,14 +296,7 @@ gst_gl_context_cocoa_create_context (GstGLContext *context, GstGLAPI gl_api,
|
||||||
}
|
}
|
||||||
NS_ENDHANDLER
|
NS_ENDHANDLER
|
||||||
|
|
||||||
GST_DEBUG ("opengl GstGLNSWindow initialized: %d x %d\n",
|
GST_DEBUG ("opengl GstGLNSWindow initialized");
|
||||||
(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);
|
gst_object_unref (window);
|
||||||
|
|
||||||
|
@ -307,6 +306,14 @@ gst_gl_context_cocoa_create_context (GstGLContext *context, GstGLAPI gl_api,
|
||||||
static void
|
static void
|
||||||
gst_gl_context_cocoa_destroy_context (GstGLContext *context)
|
gst_gl_context_cocoa_destroy_context (GstGLContext *context)
|
||||||
{
|
{
|
||||||
|
GstGLContextCocoa *context_cocoa = GST_GL_CONTEXT_COCOA (context);
|
||||||
|
GstGLContextCocoaPrivate *priv = context_cocoa->priv;
|
||||||
|
|
||||||
|
/* FIXME: Need to release context and other things? */
|
||||||
|
if (priv->source_id) {
|
||||||
|
g_source_remove (priv->source_id);
|
||||||
|
priv->source_id = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static guintptr
|
static guintptr
|
||||||
|
|
|
@ -123,20 +123,20 @@ gst_gl_window_cocoa_new (void)
|
||||||
return window;
|
return window;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Must be called from the main thread */
|
||||||
gboolean
|
gboolean
|
||||||
gst_gl_window_cocoa_create_window (GstGLWindowCocoa *window_cocoa, NSRect rect)
|
gst_gl_window_cocoa_create_window (GstGLWindowCocoa *window_cocoa, NSRect rect)
|
||||||
{
|
{
|
||||||
GstGLWindowCocoaPrivate *priv = window_cocoa->priv;
|
GstGLWindowCocoaPrivate *priv = window_cocoa->priv;
|
||||||
|
|
||||||
/* FIXME: This should probably be done in the application main thread */
|
|
||||||
priv->internal_win_id = [[GstGLNSWindow alloc] initWithContentRect:rect styleMask:
|
priv->internal_win_id = [[GstGLNSWindow alloc] initWithContentRect:rect styleMask:
|
||||||
(NSTitledWindowMask | NSClosableWindowMask |
|
(NSTitledWindowMask | NSClosableWindowMask |
|
||||||
NSResizableWindowMask | NSMiniaturizableWindowMask)
|
NSResizableWindowMask | NSMiniaturizableWindowMask)
|
||||||
backing: NSBackingStoreBuffered defer: NO screen: nil gstWin: window_cocoa];
|
backing: NSBackingStoreBuffered defer: NO screen: nil gstWin: window_cocoa];
|
||||||
|
|
||||||
GST_DEBUG ("NSWindow id: %"G_GUINTPTR_FORMAT, (guintptr) priv->internal_win_id);
|
GST_DEBUG ("NSWindow id: %"G_GUINTPTR_FORMAT, (guintptr) priv->internal_win_id);
|
||||||
|
|
||||||
[NSApp setDelegate: priv->internal_win_id];
|
[NSApp setDelegate: priv->internal_win_id];
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
@ -175,21 +175,6 @@ gst_gl_window_cocoa_get_window_handle (GstGLWindow *window)
|
||||||
return (guintptr) GST_GL_WINDOW_COCOA (window)->priv->internal_win_id;
|
return (guintptr) GST_GL_WINDOW_COCOA (window)->priv->internal_win_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
set_window_handle_cb (gpointer data)
|
|
||||||
{
|
|
||||||
GstGLWindowCocoa * window_cocoa = data;
|
|
||||||
NSView *view = [window_cocoa->priv->internal_win_id contentView];
|
|
||||||
|
|
||||||
/* FIXME: This should probably be in the application main thread! */
|
|
||||||
[window_cocoa->priv->internal_win_id orderOut:window_cocoa->priv->internal_win_id];
|
|
||||||
|
|
||||||
[window_cocoa->priv->external_view addSubview: view];
|
|
||||||
|
|
||||||
[view setFrame: [window_cocoa->priv->external_view bounds]];
|
|
||||||
[view setAutoresizingMask: NSViewWidthSizable|NSViewHeightSizable];
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_gl_window_cocoa_set_window_handle (GstGLWindow * window, guintptr handle)
|
gst_gl_window_cocoa_set_window_handle (GstGLWindow * window, guintptr handle)
|
||||||
{
|
{
|
||||||
|
@ -200,16 +185,6 @@ gst_gl_window_cocoa_set_window_handle (GstGLWindow * window, guintptr handle)
|
||||||
priv = window_cocoa->priv;
|
priv = window_cocoa->priv;
|
||||||
|
|
||||||
if (priv->internal_win_id) {
|
if (priv->internal_win_id) {
|
||||||
GstGLContextCocoa *context = (GstGLContextCocoa *) gst_gl_window_get_context (window);
|
|
||||||
|
|
||||||
if (context) {
|
|
||||||
if (context->priv->source_id) {
|
|
||||||
g_source_remove (context->priv->source_id);
|
|
||||||
context->priv->source_id = 0;
|
|
||||||
}
|
|
||||||
gst_object_unref (context);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (handle) {
|
if (handle) {
|
||||||
priv->external_view = (NSView *) handle;
|
priv->external_view = (NSView *) handle;
|
||||||
priv->visible = TRUE;
|
priv->visible = TRUE;
|
||||||
|
@ -220,7 +195,15 @@ gst_gl_window_cocoa_set_window_handle (GstGLWindow * window, guintptr handle)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
gst_gl_window_send_message (window, (GstGLWindowCB) set_window_handle_cb, window_cocoa);
|
dispatch_async (dispatch_get_main_queue (), ^{
|
||||||
|
NSView *view = [window_cocoa->priv->internal_win_id contentView];
|
||||||
|
[window_cocoa->priv->internal_win_id orderOut:window_cocoa->priv->internal_win_id];
|
||||||
|
|
||||||
|
[window_cocoa->priv->external_view addSubview: view];
|
||||||
|
|
||||||
|
[view setFrame: [window_cocoa->priv->external_view bounds]];
|
||||||
|
[view setAutoresizingMask: NSViewWidthSizable|NSViewHeightSizable];
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
/* no internal window yet so delay it to the next drawing */
|
/* no internal window yet so delay it to the next drawing */
|
||||||
priv->external_view = (NSView*) handle;
|
priv->external_view = (NSView*) handle;
|
||||||
|
@ -250,39 +233,38 @@ draw_cb (gpointer data)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!priv->external_view && !priv->visible) {
|
if (!priv->external_view && !priv->visible) {
|
||||||
gint x = 0;
|
dispatch_sync (dispatch_get_main_queue (), ^{
|
||||||
gint y = 0;
|
NSRect mainRect = [[NSScreen mainScreen] visibleFrame];
|
||||||
|
NSRect windowRect = [priv->internal_win_id frame];
|
||||||
|
gint x = 0;
|
||||||
|
gint y = 0;
|
||||||
|
|
||||||
/* FIXME: This should probably be done from the application main thread */
|
GST_DEBUG ("main screen rect: %d %d %d %d\n", (int) mainRect.origin.x,
|
||||||
|
(int) mainRect.origin.y, (int) mainRect.size.width,
|
||||||
|
(int) mainRect.size.height);
|
||||||
|
|
||||||
NSRect mainRect = [[NSScreen mainScreen] visibleFrame];
|
windowRect.origin.x += x;
|
||||||
NSRect windowRect = [priv->internal_win_id frame];
|
windowRect.origin.y += mainRect.size.height > y ? (mainRect.size.height - y) * 0.5 : y;
|
||||||
|
windowRect.size.width = draw_data->width;
|
||||||
|
windowRect.size.height = draw_data->height;
|
||||||
|
|
||||||
GST_DEBUG ("main screen rect: %d %d %d %d\n", (int) mainRect.origin.x,
|
GST_DEBUG ("window rect: %d %d %d %d\n", (int) windowRect.origin.x,
|
||||||
(int) mainRect.origin.y, (int) mainRect.size.width,
|
(int) windowRect.origin.y, (int) windowRect.size.width,
|
||||||
(int) mainRect.size.height);
|
(int) windowRect.size.height);
|
||||||
|
|
||||||
windowRect.origin.x += x;
|
x += 20;
|
||||||
windowRect.origin.y += mainRect.size.height > y ? (mainRect.size.height - y) * 0.5 : y;
|
y += 20;
|
||||||
windowRect.size.width = draw_data->width;
|
|
||||||
windowRect.size.height = draw_data->height;
|
|
||||||
|
|
||||||
GST_DEBUG ("window rect: %d %d %d %d\n", (int) windowRect.origin.x,
|
|
||||||
(int) windowRect.origin.y, (int) windowRect.size.width,
|
|
||||||
(int) windowRect.size.height);
|
|
||||||
|
|
||||||
x += 20;
|
|
||||||
y += 20;
|
|
||||||
|
|
||||||
#ifndef GNUSTEP
|
#ifndef GNUSTEP
|
||||||
[priv->internal_win_id setFrame:windowRect display:NO];
|
[priv->internal_win_id setFrame:windowRect display:NO];
|
||||||
GST_DEBUG ("make the window available\n");
|
GST_DEBUG ("make the window available\n");
|
||||||
[priv->internal_win_id makeMainWindow];
|
[priv->internal_win_id makeMainWindow];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
[priv->internal_win_id orderFrontRegardless];
|
[priv->internal_win_id orderFrontRegardless];
|
||||||
|
|
||||||
/*[priv->internal_win_id setViewsNeedDisplay:YES]; */
|
[priv->internal_win_id setViewsNeedDisplay:YES];
|
||||||
|
});
|
||||||
priv->visible = TRUE;
|
priv->visible = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -383,6 +365,7 @@ gst_gl_window_cocoa_send_message_async (GstGLWindow * window,
|
||||||
/* */
|
/* */
|
||||||
/* =============================================================*/
|
/* =============================================================*/
|
||||||
|
|
||||||
|
/* Must be called from the main thread */
|
||||||
@implementation GstGLNSWindow
|
@implementation GstGLNSWindow
|
||||||
|
|
||||||
- (id) initWithContentRect: (NSRect) contentRect
|
- (id) initWithContentRect: (NSRect) contentRect
|
||||||
|
@ -446,7 +429,6 @@ close_window_cb (gpointer data)
|
||||||
|
|
||||||
window = GST_GL_WINDOW (window_cocoa);
|
window = GST_GL_WINDOW (window_cocoa);
|
||||||
|
|
||||||
[window_cocoa->priv->internal_win_id setClosed];
|
|
||||||
if (window->close) {
|
if (window->close) {
|
||||||
window->close (window->close_data);
|
window->close (window->close_data);
|
||||||
}
|
}
|
||||||
|
@ -456,7 +438,8 @@ close_window_cb (gpointer data)
|
||||||
- (BOOL) windowShouldClose:(id)sender {
|
- (BOOL) windowShouldClose:(id)sender {
|
||||||
|
|
||||||
GST_DEBUG ("user clicked the close button\n");
|
GST_DEBUG ("user clicked the close button\n");
|
||||||
gst_gl_window_send_message (GST_GL_WINDOW (window_cocoa), (GstGLWindowCB) close_window_cb, window_cocoa);
|
[window_cocoa->priv->internal_win_id setClosed];
|
||||||
|
gst_gl_window_send_message_async (GST_GL_WINDOW (window_cocoa), (GstGLWindowCB) close_window_cb, gst_object_ref (window_cocoa), (GDestroyNotify) gst_object_unref);
|
||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -496,9 +479,9 @@ close_window_cb (gpointer data)
|
||||||
|
|
||||||
@implementation GstGLNSView
|
@implementation GstGLNSView
|
||||||
|
|
||||||
|
/* Must be called from the application main thread */
|
||||||
- (id)initWithFrame:(GstGLWindowCocoa *)window rect:(NSRect)contentRect {
|
- (id)initWithFrame:(GstGLWindowCocoa *)window rect:(NSRect)contentRect {
|
||||||
|
|
||||||
/* FIXME: This should probably be done from the application main thread */
|
|
||||||
self = [super initWithFrame: contentRect];
|
self = [super initWithFrame: contentRect];
|
||||||
|
|
||||||
window_cocoa = window;
|
window_cocoa = window;
|
||||||
|
@ -556,7 +539,7 @@ resize_cb (gpointer data)
|
||||||
NSRect bounds = [self bounds];
|
NSRect bounds = [self bounds];
|
||||||
NSRect visibleRect = [self visibleRect];
|
NSRect visibleRect = [self visibleRect];
|
||||||
NSSize frameSize = [self frame].size;
|
NSSize frameSize = [self frame].size;
|
||||||
struct resize resize_data;
|
struct resize *resize_data = g_new (struct resize, 1);
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (window, "Window resized: bounds %lf %lf %lf %lf, "
|
GST_DEBUG_OBJECT (window, "Window resized: bounds %lf %lf %lf %lf, "
|
||||||
"visibleRect %lf %lf %lf %lf, frame size %lf %lf",
|
"visibleRect %lf %lf %lf %lf, frame size %lf %lf",
|
||||||
|
@ -566,12 +549,12 @@ resize_cb (gpointer data)
|
||||||
visibleRect.size.width, visibleRect.size.height,
|
visibleRect.size.width, visibleRect.size.height,
|
||||||
frameSize.width, frameSize.height);
|
frameSize.width, frameSize.height);
|
||||||
|
|
||||||
resize_data.window = window_cocoa;
|
resize_data->window = window_cocoa;
|
||||||
resize_data.bounds = bounds;
|
resize_data->bounds = bounds;
|
||||||
resize_data.visibleRect = visibleRect;
|
resize_data->visibleRect = visibleRect;
|
||||||
resize_data.frameSize = frameSize;
|
resize_data->frameSize = frameSize;
|
||||||
|
|
||||||
gst_gl_window_send_message (GST_GL_WINDOW (window_cocoa), (GstGLWindowCB) resize_cb, &resize_data);
|
gst_gl_window_send_message_async (GST_GL_WINDOW (window_cocoa), (GstGLWindowCB) resize_cb, resize_data, (GDestroyNotify) g_free);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue