gl/cocoa: Switch to a plain NSView subclass instead of NSOpenGLView

We don't and can't use NSOpenGLView as it's supposed to be used and
it gets into our way by being to clever in various situations.
This commit is contained in:
Sebastian Dröge 2014-09-26 13:05:27 +03:00 committed by Tim-Philipp Müller
parent ef00d85f16
commit 02b3e26854
3 changed files with 76 additions and 53 deletions

View file

@ -34,25 +34,23 @@ struct _GstGLContextCocoaPrivate
{ {
NSOpenGLContext *gl_context; NSOpenGLContext *gl_context;
NSOpenGLContext *external_gl_context; NSOpenGLContext *external_gl_context;
NSRect rect;
gint source_id; gint source_id;
}; };
/* =============================================================*/ /* =============================================================*/
/* */ /* */
/* GstGLNSOpenGLView declaration */ /* GstGLNSView declaration */
/* */ /* */
/* =============================================================*/ /* =============================================================*/
@interface GstGLNSOpenGLView: NSOpenGLView { @interface GstGLNSView: NSView {
GstGLWindowCocoa *m_cocoa; GstGLWindowCocoa *window_cocoa;
} }
- (id) initWithFrame:(GstGLWindowCocoa *)window rect:(NSRect)contentRect - (id) initWithFrame:(GstGLWindowCocoa *)window rect:(NSRect)contentRect;
pixelFormat:(NSOpenGLPixelFormat *)fmt;
@end @end
gboolean gst_gl_window_cocoa_create_window (GstGLWindowCocoa *window_cocoa); gboolean gst_gl_window_cocoa_create_window (GstGLWindowCocoa *window_cocoa, NSRect rect);
G_END_DECLS G_END_DECLS

View file

@ -201,7 +201,7 @@ 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);
GstGLNSOpenGLView *glView = nil; GstGLNSView *glView = nil;
NSWindow *window_handle; NSWindow *window_handle;
NSRect rect; NSRect rect;
NSAutoreleasePool *pool; NSAutoreleasePool *pool;
@ -234,12 +234,10 @@ gst_gl_context_cocoa_create_context (GstGLContext *context, GstGLAPI gl_api,
rect.size.width = 320; rect.size.width = 320;
rect.size.height = 240; rect.size.height = 240;
priv->rect = rect; gst_gl_window_cocoa_create_window (window_cocoa, rect);
gst_gl_window_cocoa_create_window (window_cocoa);
window_handle = (NSWindow *) gst_gl_window_get_window_handle (window); window_handle = (NSWindow *) gst_gl_window_get_window_handle (window);
glView = [GstGLNSOpenGLView alloc]; glView = [GstGLNSView alloc];
fmt = [[NSOpenGLPixelFormat alloc] initWithAttributes:attribs]; fmt = [[NSOpenGLPixelFormat alloc] initWithAttributes:attribs];
@ -249,7 +247,7 @@ gst_gl_context_cocoa_create_context (GstGLContext *context, GstGLAPI gl_api,
return FALSE; return FALSE;
} }
glView = [glView initWithFrame:window_cocoa rect:rect pixelFormat:fmt]; glView = [glView initWithFrame:window_cocoa rect:rect];
[window_handle setContentView:glView]; [window_handle setContentView:glView];
@ -263,11 +261,9 @@ gst_gl_context_cocoa_create_context (GstGLContext *context, GstGLAPI gl_api,
[glContext setView:glView]; [glContext setView:glView];
[glView setOpenGLContext:glContext];
#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 = [glView openGLContext]; context_cocoa->priv->gl_context = glContext;
#endif #endif
/* OpenGL context is made current only one time threre. /* OpenGL context is made current only one time threre.
@ -287,7 +283,7 @@ gst_gl_context_cocoa_create_context (GstGLContext *context, GstGLAPI gl_api,
#else #else
const GLint swapInterval = 1; const GLint swapInterval = 1;
#endif #endif
[[glView openGLContext] setValues:&swapInterval forParameter:NSOpenGLCPSwapInterval]; [glContext setValues:&swapInterval forParameter:NSOpenGLCPSwapInterval];
} }
} NS_HANDLER { } NS_HANDLER {
GST_DEBUG ("your back-end does not implement NSOpenglContext::setValues\n"); GST_DEBUG ("your back-end does not implement NSOpenglContext::setValues\n");

View file

@ -1,6 +1,7 @@
/* /*
* GStreamer * GStreamer
* Copyright (C) 2008 Julien Isorce <julien.isorce@gmail.com> * Copyright (C) 2008 Julien Isorce <julien.isorce@gmail.com>
* Copyright (C) 2014 Sebastian Dröge <sebastian@centricular.com>
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it un der the terms of the GNU Library General Public * modify it un der the terms of the GNU Library General Public
@ -34,7 +35,7 @@
@interface GstGLNSWindow: NSWindow { @interface GstGLNSWindow: NSWindow {
BOOL m_isClosed; BOOL m_isClosed;
GstGLWindowCocoa *m_cocoa; GstGLWindowCocoa *window_cocoa;
} }
- (id)initWithContentRect:(NSRect)contentRect - (id)initWithContentRect:(NSRect)contentRect
styleMask: (unsigned int) styleMask styleMask: (unsigned int) styleMask
@ -123,17 +124,12 @@ gst_gl_window_cocoa_new (void)
} }
gboolean gboolean
gst_gl_window_cocoa_create_window (GstGLWindowCocoa *window_cocoa) gst_gl_window_cocoa_create_window (GstGLWindowCocoa *window_cocoa, NSRect rect)
{ {
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; GstGLWindowCocoaPrivate *priv = window_cocoa->priv;
NSRect rect = context_cocoa->priv->rect;
/* FIXME: This should probably be done in the application main thread */ /* FIXME: This should probably be done in the application main thread */
priv->internal_win_id = [GstGLNSWindow alloc]; priv->internal_win_id = [[GstGLNSWindow alloc] initWithContentRect:rect styleMask:
[priv->internal_win_id 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];
@ -142,8 +138,6 @@ gst_gl_window_cocoa_create_window (GstGLWindowCocoa *window_cocoa)
[NSApp setDelegate: priv->internal_win_id]; [NSApp setDelegate: priv->internal_win_id];
gst_object_unref (context);
return TRUE; return TRUE;
} }
@ -256,8 +250,8 @@ draw_cb (gpointer data)
} }
if (!priv->external_view && !priv->visible) { if (!priv->external_view && !priv->visible) {
static gint x = 0; gint x = 0;
static gint y = 0; gint y = 0;
/* FIXME: This should probably be done from the application main thread */ /* FIXME: This should probably be done from the application main thread */
@ -294,11 +288,16 @@ draw_cb (gpointer data)
if (g_main_loop_is_running (priv->loop)) { if (g_main_loop_is_running (priv->loop)) {
if (![priv->internal_win_id isClosed]) { if (![priv->internal_win_id isClosed]) {
GstGLContext *context = gst_gl_window_get_context (GST_GL_WINDOW (window_cocoa));
NSOpenGLContext * glContext = (NSOpenGLContext *) gst_gl_context_get_gl_context (context);
/* draw opengl scene in the back buffer */ /* draw opengl scene in the back buffer */
GST_GL_WINDOW (window_cocoa)->draw (GST_GL_WINDOW (window_cocoa)->draw_data); GST_GL_WINDOW (window_cocoa)->draw (GST_GL_WINDOW (window_cocoa)->draw_data);
/* Copy the back buffer to the front buffer */ /* Copy the back buffer to the front buffer */
[[[priv->internal_win_id contentView] openGLContext] flushBuffer]; [glContext flushBuffer];
gst_object_unref (context);
} }
} }
} }
@ -393,7 +392,7 @@ gst_gl_window_cocoa_send_message_async (GstGLWindow * window,
gstWin: (GstGLWindowCocoa *) cocoa { gstWin: (GstGLWindowCocoa *) cocoa {
m_isClosed = NO; m_isClosed = NO;
m_cocoa = cocoa; window_cocoa = cocoa;
self = [super initWithContentRect: contentRect self = [super initWithContentRect: contentRect
styleMask: styleMask backing: bufferingType styleMask: styleMask backing: bufferingType
@ -407,14 +406,14 @@ gst_gl_window_cocoa_send_message_async (GstGLWindow * window,
[self setBackgroundColor:[NSColor clearColor]]; [self setBackgroundColor:[NSColor clearColor]];
[self orderOut:m_cocoa->priv->internal_win_id]; [self orderOut:window_cocoa->priv->internal_win_id];
if (m_cocoa->priv->external_view) { if (window_cocoa->priv->external_view) {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSView *view = [m_cocoa->priv->internal_win_id contentView]; NSView *view = [window_cocoa->priv->internal_win_id contentView];
[m_cocoa->priv->external_view addSubview: view]; [window_cocoa->priv->external_view addSubview: view];
[view setFrame: [m_cocoa->priv->external_view bounds]]; [view setFrame: [window_cocoa->priv->external_view bounds]];
[view setAutoresizingMask: NSViewWidthSizable|NSViewHeightSizable]; [view setAutoresizingMask: NSViewWidthSizable|NSViewHeightSizable];
[pool release]; [pool release];
@ -457,7 +456,7 @@ 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 (m_cocoa), (GstGLWindowCB) close_window_cb, m_cocoa); gst_gl_window_send_message (GST_GL_WINDOW (window_cocoa), (GstGLWindowCB) close_window_cb, window_cocoa);
return YES; return YES;
} }
@ -491,29 +490,39 @@ close_window_cb (gpointer data)
/* =============================================================*/ /* =============================================================*/
/* */ /* */
/* GstGLNSOpenGLView implementation */ /* GstGLNSView implementation */
/* */ /* */
/* =============================================================*/ /* =============================================================*/
@implementation GstGLNSOpenGLView @implementation GstGLNSView
- (id)initWithFrame:(GstGLWindowCocoa *)window rect:(NSRect)contentRect pixelFormat:(NSOpenGLPixelFormat *)fmt { - (id)initWithFrame:(GstGLWindowCocoa *)window rect:(NSRect)contentRect {
self = [super initWithFrame: contentRect pixelFormat: fmt]; /* FIXME: This should probably be done from the application main thread */
self = [super initWithFrame: contentRect];
m_cocoa = window; window_cocoa = window;
#ifndef GNUSTEP #ifndef GNUSTEP
[self setWantsLayer:NO]; [self setWantsLayer:NO];
#endif #endif
/* Get notified about changes */
[[NSNotificationCenter defaultCenter] addObserver: self selector:@selector(reshape) name: NSViewFrameDidChangeNotification object: self];
return self; return self;
} }
- (void) dealloc {
[[NSNotificationCenter defaultCenter] removeObserver: self];
[super dealloc];
}
struct resize struct resize
{ {
GstGLWindowCocoa * window; GstGLWindowCocoa * window;
gint width, height; NSRect bounds, visibleRect;
NSSize frameSize;
}; };
static void static void
@ -522,36 +531,56 @@ resize_cb (gpointer data)
struct resize *resize_data = data; struct resize *resize_data = data;
GstGLWindowCocoa *window_cocoa = resize_data->window; GstGLWindowCocoa *window_cocoa = resize_data->window;
GstGLWindow *window = GST_GL_WINDOW (window_cocoa); GstGLWindow *window = GST_GL_WINDOW (window_cocoa);
GstGLContext *context = gst_gl_window_get_context (window);
NSOpenGLContext * glContext = (NSOpenGLContext *) gst_gl_context_get_gl_context (context);
if (g_main_loop_is_running (window_cocoa->priv->loop) && ![window_cocoa->priv->internal_win_id isClosed]) { if (g_main_loop_is_running (window_cocoa->priv->loop) && ![window_cocoa->priv->internal_win_id isClosed]) {
/* FIXME: Need to adjust viewport for clipping here */
if (window->resize) { if (window->resize) {
window->resize (window->resize_data, resize_data->width, resize_data->height); window->resize (window->resize_data, resize_data->bounds.size.width, resize_data->bounds.size.height);
} }
[[[window_cocoa->priv->internal_win_id contentView] openGLContext] update]; [glContext update];
GST_GL_WINDOW (window_cocoa)->draw (GST_GL_WINDOW (window_cocoa)->draw_data); GST_GL_WINDOW (window_cocoa)->draw (GST_GL_WINDOW (window_cocoa)->draw_data);
[[[window_cocoa->priv->internal_win_id contentView] openGLContext] flushBuffer]; [glContext flushBuffer];
} }
gst_object_unref (context);
} }
- (void)reshape { - (void)reshape {
GstGLWindow *window; GstGLWindow *window;
window = GST_GL_WINDOW (m_cocoa); window = GST_GL_WINDOW (window_cocoa);
if (window->resize) { if (window->resize) {
NSRect bounds = [self bounds]; NSRect bounds = [self bounds];
NSRect visibleRect = [self visibleRect];
NSSize frameSize = [self frame].size;
struct resize resize_data; struct resize resize_data;
resize_data.window = m_cocoa; GST_DEBUG_OBJECT (window, "Window resized: bounds %lf %lf %lf %lf, "
resize_data.width = bounds.size.width; "visibleRect %lf %lf %lf %lf, frame size %lf %lf",
resize_data.height = bounds.size.height; bounds.origin.x, bounds.origin.y,
bounds.size.width, bounds.size.height,
visibleRect.origin.x, visibleRect.origin.y,
visibleRect.size.width, visibleRect.size.height,
frameSize.width, frameSize.height);
gst_gl_window_send_message (GST_GL_WINDOW (m_cocoa), (GstGLWindowCB) resize_cb, &resize_data); resize_data.window = window_cocoa;
resize_data.bounds = bounds;
resize_data.visibleRect = visibleRect;
resize_data.frameSize = frameSize;
gst_gl_window_send_message (GST_GL_WINDOW (window_cocoa), (GstGLWindowCB) resize_cb, &resize_data);
} }
} }
- (void) update { - (BOOL) isOpaque {
return YES;
}
- (BOOL) isFlipped {
return YES;
} }
@end @end