gl/calayer: add resize callback based on the bounds rectangle

This commit is contained in:
Matthew Waters 2015-01-29 17:31:09 +11:00
parent 2ab0e1517f
commit 6d9dc9c81c
3 changed files with 136 additions and 142 deletions

View file

@ -35,14 +35,21 @@ G_BEGIN_DECLS
CGLContextObj gl_context; CGLContextObj gl_context;
@private @private
NSRect last_bounds;
gint expected_dims[4]; gint expected_dims[4];
GstGLWindowCB draw_cb; GstGLWindowCB draw_cb;
gpointer draw_data; gpointer draw_data;
GDestroyNotify draw_notify; GDestroyNotify draw_notify;
GstGLWindowResizeCB resize_cb;
gpointer resize_data;
GDestroyNotify resize_notify;
} }
- (void) setDrawCallback:(GstGLWindowCB)cb data:(gpointer)a notify:(GDestroyNotify)notify; - (void) setDrawCallback:(GstGLWindowCB)cb data:(gpointer)a notify:(GDestroyNotify)notify;
- (void) setResizeCallback:(GstGLWindowResizeCB)cb data:(gpointer)a notify:(GDestroyNotify)notify;
- (id) initWithGstGLContext: (GstGLContextCocoa *)context; - (id) initWithGstGLContext: (GstGLContextCocoa *)context;
- (void) resize: (NSRect)bounds;
@end @end
G_END_DECLS G_END_DECLS

View file

@ -97,7 +97,8 @@
CGLReleaseContext (glContext); CGLReleaseContext (glContext);
} }
- (void)setDrawCallback:(GstGLWindowCB)cb data:(gpointer)data notify:(GDestroyNotify)notify { - (void)setDrawCallback:(GstGLWindowCB)cb data:(gpointer)data
notify:(GDestroyNotify)notify {
g_return_if_fail (cb); g_return_if_fail (cb);
if (self->draw_notify) if (self->draw_notify)
@ -108,12 +109,14 @@
self->draw_notify = notify; self->draw_notify = notify;
} }
- (void)resize:(NSRect)bounds { - (void)setResizeCallback:(GstGLWindowResizeCB)cb data:(gpointer)data
const GstGLFuncs *gl = ((GstGLContext *)self->gst_gl_context)->gl_vtable; notify:(GDestroyNotify)notify {
if (self->resize_notify)
self->resize_notify (self->resize_notify);
GST_LOG ("resizing"); self->resize_cb = cb;
self->resize_data = data;
gl->GetIntegerv (GL_VIEWPORT, self->expected_dims); self->resize_notify = notify;
} }
- (void)drawInCGLContext:(CGLContextObj)glContext - (void)drawInCGLContext:(CGLContextObj)glContext
@ -121,6 +124,7 @@
forLayerTime:(CFTimeInterval)interval forLayerTime:(CFTimeInterval)interval
displayTime:(const CVTimeStamp *)timeStamp { displayTime:(const CVTimeStamp *)timeStamp {
const GstGLFuncs *gl = ((GstGLContext *)self->gst_gl_context)->gl_vtable; const GstGLFuncs *gl = ((GstGLContext *)self->gst_gl_context)->gl_vtable;
GstVideoRectangle src, dst, result;
gint ca_viewport[4]; gint ca_viewport[4];
GST_LOG ("CAOpenGLLayer drawing with cgl context %p", glContext); GST_LOG ("CAOpenGLLayer drawing with cgl context %p", glContext);
@ -130,7 +134,23 @@
* the CA viewport set up on entry to this function */ * the CA viewport set up on entry to this function */
gl->GetIntegerv (GL_VIEWPORT, ca_viewport); gl->GetIntegerv (GL_VIEWPORT, ca_viewport);
GstVideoRectangle src, dst, result; if (self->last_bounds.size.width != self.bounds.size.width
|| self->last_bounds.size.height != self.bounds.size.height) {
if (self->resize_cb) {
self->resize_cb (self->resize_data, self.bounds.size.width,
self.bounds.size.height);
gl->GetIntegerv (GL_VIEWPORT, self->expected_dims);
} else {
/* default to whatever ca gives us */
self->expected_dims[0] = ca_viewport[0];
self->expected_dims[1] = ca_viewport[1];
self->expected_dims[2] = ca_viewport[2];
self->expected_dims[3] = ca_viewport[3];
}
self->last_bounds = self.bounds;
}
src.x = self->expected_dims[0]; src.x = self->expected_dims[0];
src.y = self->expected_dims[1]; src.y = self->expected_dims[1];

View file

@ -220,60 +220,6 @@ gst_gl_window_cocoa_set_window_handle (GstGLWindow * window, guintptr handle)
} }
} }
void
gst_gl_window_cocoa_draw_thread (GstGLWindowCocoa *window_cocoa)
{
GstGLWindowCocoaPrivate *priv = window_cocoa->priv;
/* useful when set_window_handle is called before
* the internal NSWindow */
if (priv->external_view && !priv->visible) {
gst_gl_window_cocoa_set_window_handle (GST_GL_WINDOW (window_cocoa), (guintptr) priv->external_view);
priv->visible = TRUE;
}
if (!priv->external_view && !priv->visible) {
NSRect mainRect = [[NSScreen mainScreen] visibleFrame];
NSRect windowRect = [priv->internal_win_id frame];
gint x = 0;
gint y = 0;
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);
windowRect.origin.x += x;
windowRect.origin.y += mainRect.size.height > y ? (mainRect.size.height - y) * 0.5 : y;
windowRect.size.width = window_cocoa->priv->preferred_width;
windowRect.size.height = window_cocoa->priv->preferred_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;
[priv->internal_win_id setFrame:windowRect display:NO];
GST_DEBUG ("make the window available\n");
[priv->internal_win_id makeMainWindow];
[priv->internal_win_id orderFrontRegardless];
[priv->internal_win_id setViewsNeedDisplay:YES];
priv->visible = TRUE;
}
if (g_main_loop_is_running (priv->loop)) {
if (![priv->internal_win_id isClosed]) {
GstGLWindow *window = GST_GL_WINDOW (window_cocoa);
/* draw opengl scene in the back buffer */
if (window->draw)
window->draw (window->draw_data);
}
}
}
static void static void
gst_gl_window_cocoa_draw (GstGLWindow * window) gst_gl_window_cocoa_draw (GstGLWindow * window)
@ -362,6 +308,103 @@ gst_gl_window_cocoa_send_message_async (GstGLWindow * window,
(GSourceFunc) _run_message, message); (GSourceFunc) _run_message, message);
} }
static void
gst_gl_cocoa_draw_cb (GstGLWindowCocoa *window_cocoa)
{
GstGLWindowCocoaPrivate *priv = window_cocoa->priv;
/* useful when set_window_handle is called before
* the internal NSWindow */
if (priv->external_view && !priv->visible) {
gst_gl_window_cocoa_set_window_handle (GST_GL_WINDOW (window_cocoa), (guintptr) priv->external_view);
priv->visible = TRUE;
}
if (!priv->external_view && !priv->visible) {
NSRect mainRect = [[NSScreen mainScreen] visibleFrame];
NSRect windowRect = [priv->internal_win_id frame];
gint x = 0;
gint y = 0;
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);
windowRect.origin.x += x;
windowRect.origin.y += mainRect.size.height > y ? (mainRect.size.height - y) * 0.5 : y;
windowRect.size.width = window_cocoa->priv->preferred_width;
windowRect.size.height = window_cocoa->priv->preferred_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;
[priv->internal_win_id setFrame:windowRect display:NO];
GST_DEBUG ("make the window available\n");
[priv->internal_win_id makeMainWindow];
[priv->internal_win_id orderFrontRegardless];
[priv->internal_win_id setViewsNeedDisplay:YES];
priv->visible = TRUE;
}
if (g_main_loop_is_running (priv->loop)) {
if (![priv->internal_win_id isClosed]) {
GstGLWindow *window = GST_GL_WINDOW (window_cocoa);
/* draw opengl scene in the back buffer */
if (window->draw)
window->draw (window->draw_data);
}
}
}
static void
gst_gl_cocoa_resize_cb (GstGLNSView * view, guint width, guint height)
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
GstGLWindowCocoa *window_cocoa = view->window_cocoa;
GstGLWindow *window = GST_GL_WINDOW (window_cocoa);
GstGLContext *context = gst_gl_window_get_context (window);
if (g_main_loop_is_running (window_cocoa->priv->loop) && ![window_cocoa->priv->internal_win_id isClosed]) {
const GstGLFuncs *gl;
NSRect bounds = [view bounds];
NSRect visibleRect = [view visibleRect];
gint viewport_dim[4];
gl = context->gl_vtable;
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
bounds = [view convertRectToBacking:bounds];
visibleRect = [view convertRectToBacking:visibleRect];
#endif
GST_DEBUG_OBJECT (window, "Window resized: bounds %lf %lf %lf %lf "
"visibleRect %lf %lf %lf %lf",
bounds.origin.x, bounds.origin.y,
bounds.size.width, bounds.size.height,
visibleRect.origin.x, visibleRect.origin.y,
visibleRect.size.width, visibleRect.size.height);
if (window->resize) {
window->resize (window->resize_data, width, height);
gl->GetIntegerv (GL_VIEWPORT, viewport_dim);
}
gl->Viewport (viewport_dim[0] - visibleRect.origin.x,
viewport_dim[1] - visibleRect.origin.y,
viewport_dim[2], viewport_dim[3]);
}
gst_object_unref (context);
[pool release];
}
/* =============================================================*/ /* =============================================================*/
/* */ /* */
/* GstGLNSWindow implementation */ /* GstGLNSWindow implementation */
@ -450,7 +493,6 @@ close_window_cb (gpointer data)
@end @end
/* =============================================================*/ /* =============================================================*/
/* */ /* */
/* GstGLNSView implementation */ /* GstGLNSView implementation */
@ -474,64 +516,24 @@ close_window_cb (gpointer data)
[self setLayer:layerContent]; [self setLayer:layerContent];
[self setWantsLayer:YES]; [self setWantsLayer:YES];
self->layer = (GstGLCAOpenGLLayer *)layerContent; self->layer = (GstGLCAOpenGLLayer *)layerContent;
[self->layer setDrawCallback:(GstGLWindowCB)gst_gl_window_cocoa_draw_thread data:window notify:NULL]; [self->layer setDrawCallback:(GstGLWindowCB)gst_gl_cocoa_draw_cb
data:window notify:NULL];
[self->layer setResizeCallback:(GstGLWindowResizeCB)gst_gl_cocoa_resize_cb
data:self notify:NULL];
[self setLayerContentsRedrawPolicy:NSViewLayerContentsRedrawOnSetNeedsDisplay]; [self setLayerContentsRedrawPolicy:NSViewLayerContentsRedrawOnSetNeedsDisplay];
/* Get notified about changes */
[self setPostsFrameChangedNotifications:YES];
[[NSNotificationCenter defaultCenter] addObserver: self selector:@selector(reshape:) name: NSViewFrameDidChangeNotification object: self];
[self setWantsBestResolutionOpenGLSurface:YES]; [self setWantsBestResolutionOpenGLSurface:YES];
return self; return self;
} }
- (void) dealloc { - (void) dealloc {
[[NSNotificationCenter defaultCenter] removeObserver: self];
[self->layer release]; [self->layer release];
[super dealloc]; [super dealloc];
} }
struct resize
{
GstGLWindowCocoa * window;
NSRect bounds, visibleRect;
};
static void
resize_cb (gpointer data)
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
struct resize *resize_data = data;
GstGLWindowCocoa *window_cocoa = resize_data->window;
GstGLWindow *window = GST_GL_WINDOW (window_cocoa);
GstGLContext *context = gst_gl_window_get_context (window);
if (g_main_loop_is_running (window_cocoa->priv->loop) && ![window_cocoa->priv->internal_win_id isClosed]) {
const GstGLFuncs *gl;
GstGLCAOpenGLLayer *gl_layer;
gl = context->gl_vtable;
if (window->resize) {
window->resize (window->resize_data, resize_data->bounds.size.width, resize_data->bounds.size.height);
gl->GetIntegerv (GL_VIEWPORT, window_cocoa->priv->viewport_dim);
}
gl->Viewport (window_cocoa->priv->viewport_dim[0] - resize_data->visibleRect.origin.x,
window_cocoa->priv->viewport_dim[1] - resize_data->visibleRect.origin.y,
window_cocoa->priv->viewport_dim[2], window_cocoa->priv->viewport_dim[3]);
gl_layer = ((GstGLNSView *)[window_cocoa->priv->internal_win_id contentView])->layer;
[gl_layer resize:resize_data->bounds];
gst_gl_window_draw (window);
}
gst_object_unref (context);
[pool release];
}
- (void)renewGState { - (void)renewGState {
/* Don't update the screen until we redraw, this /* Don't update the screen until we redraw, this
* prevents flickering during scrolling, clipping, * prevents flickering during scrolling, clipping,
@ -542,41 +544,6 @@ resize_cb (gpointer data)
[super renewGState]; [super renewGState];
} }
- (void)reshape: (NSNotification*)notification {
GstGLWindow *window;
window = GST_GL_WINDOW (window_cocoa);
if (window->resize) {
NSRect bounds = [self bounds];
NSRect visibleRect = [self visibleRect];
struct resize *resize_data = g_new (struct resize, 1);
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
bounds = [self convertRectToBacking:bounds];
visibleRect = [self convertRectToBacking:visibleRect];
#endif
GST_DEBUG_OBJECT (window, "Window resized: bounds %lf %lf %lf %lf "
"visibleRect %lf %lf %lf %lf",
bounds.origin.x, bounds.origin.y,
bounds.size.width, bounds.size.height,
visibleRect.origin.x, visibleRect.origin.y,
visibleRect.size.width, visibleRect.size.height);
resize_data->window = window_cocoa;
resize_data->bounds = bounds;
resize_data->visibleRect = visibleRect;
gst_gl_window_send_message_async (GST_GL_WINDOW (window_cocoa),
(GstGLWindowCB) resize_cb, resize_data, (GDestroyNotify) g_free);
}
}
- (void)drawRect: (NSRect)dirtyRect {
[self reshape:nil];
}
- (BOOL) isOpaque { - (BOOL) isOpaque {
return YES; return YES;
} }