mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 20:21:24 +00:00
gl/calayer: add resize callback based on the bounds rectangle
This commit is contained in:
parent
2ab0e1517f
commit
6d9dc9c81c
3 changed files with 136 additions and 142 deletions
|
@ -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
|
||||||
|
|
|
@ -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];
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue