From 134f3e97bf482b75c0eccbe5ac943a2a1d5a4ad6 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Mon, 4 Mar 2013 14:23:06 +0100 Subject: OSX: run native event loop in a separate thread This commit is a followup on the previous one and uses a solution I like more since it totally decouples the Cocoa code from mpv's core and tries to emulate a generic Cocoa application's lifecycle as much as possible without fighting the framework. mpv's main is executed in a pthread while the main thread runs the native cocoa event loop. All of the thread safety is mainly accomplished with additional logic in cocoa_common as to not increase complexity on the crossplatform parts of the code. --- video/out/cocoa_common.h | 5 +- video/out/cocoa_common.m | 324 ++++++++++++++++++++++++++++++++--------------- video/out/gl_cocoa.c | 8 ++ video/out/gl_common.h | 7 + video/out/vo_opengl.c | 13 ++ 5 files changed, 253 insertions(+), 104 deletions(-) (limited to 'video') diff --git a/video/out/cocoa_common.h b/video/out/cocoa_common.h index 3450ebd547..823325ad15 100644 --- a/video/out/cocoa_common.h +++ b/video/out/cocoa_common.h @@ -24,7 +24,6 @@ struct vo_cocoa_state; -bool vo_cocoa_gui_running(void); void *vo_cocoa_glgetaddr(const char *s); int vo_cocoa_init(struct vo *vo); @@ -37,6 +36,7 @@ int vo_cocoa_config_window(struct vo *vo, uint32_t d_width, uint32_t d_height, uint32_t flags, int gl3profile); +void vo_cocoa_set_current_context(struct vo *vo, bool current); void vo_cocoa_swap_buffers(struct vo *vo); int vo_cocoa_check_events(struct vo *vo); void vo_cocoa_fullscreen(struct vo *vo); @@ -44,6 +44,9 @@ void vo_cocoa_ontop(struct vo *vo); void vo_cocoa_pause(struct vo *vo); void vo_cocoa_resume(struct vo *vo); +void vo_cocoa_register_resize_callback(struct vo *vo, + void (*cb)(struct vo *vo, int w, int h)); + // returns an int to conform to the gl extensions from other platforms int vo_cocoa_swap_interval(int enabled); diff --git a/video/out/cocoa_common.m b/video/out/cocoa_common.m index fba906c9b2..cc8f69bc1d 100644 --- a/video/out/cocoa_common.m +++ b/video/out/cocoa_common.m @@ -85,10 +85,7 @@ static bool RightAltPressed(NSEvent *event) CFSTR("PreventUserIdleDisplaySleep") #endif -@interface GLMPlayerWindow : NSWindow { - struct vo *_vo; -} -- (void)setVideoOutput:(struct vo *)vo; +@interface GLMPlayerWindow : NSWindow - (BOOL)canBecomeKeyWindow; - (BOOL)canBecomeMainWindow; - (void)fullscreen; @@ -97,11 +94,54 @@ static bool RightAltPressed(NSEvent *event) - (int)titleHeight; - (NSRect)clipFrame:(NSRect)frame withContentAspect:(NSSize) aspect; - (void)setContentSize:(NSSize)newSize keepCentered:(BOOL)keepCentered; +@property(nonatomic, assign) struct vo *videoOutput; @end @interface GLMPlayerOpenGLView : NSView @end +struct vo_cocoa_input_queue { + NSMutableArray *fifo; +}; + +static int vo_cocoa_input_queue_free(void *ptr) +{ + struct vo_cocoa_input_queue *iq = ptr; + [iq->fifo release]; + return 0; +} + +static struct vo_cocoa_input_queue *vo_cocoa_input_queue_init(void *talloc_ctx) +{ + struct vo_cocoa_input_queue *iq = talloc_ptrtype(talloc_ctx, iq); + *iq = (struct vo_cocoa_input_queue) { + .fifo = [[NSMutableArray alloc] init], + }; + talloc_set_destructor(iq, vo_cocoa_input_queue_free); + return iq; +} + +static void cocoa_async_put_key(struct vo_cocoa_input_queue *iq, int key) +{ + @synchronized (iq->fifo) { + [iq->fifo addObject:[NSNumber numberWithInt:key]]; + } +} + +static int cocoa_sync_get_key(struct vo_cocoa_input_queue *iq) +{ + int r = -1; + + @synchronized (iq->fifo) { + if ([iq->fifo count] > 0) { + r = [[iq->fifo objectAtIndex:0] intValue]; + [iq->fifo removeObjectAtIndex:0]; + } + } + + return r; +} + struct vo_cocoa_state { GLMPlayerWindow *window; NSOpenGLContext *glContext; @@ -123,25 +163,32 @@ struct vo_cocoa_state { NSInteger window_level; + struct aspect_data aspdat; + int display_cursor; int cursor_timer; int vo_cursor_autohide_delay; bool did_resize; + bool did_async_resize; bool out_fs_resize; IOPMAssertionID power_mgmt_assertion; CGFloat accumulated_scroll; -}; -static int _instances = 0; + NSRecursiveLock *lock; + void (*resize_redraw)(struct vo *vo, int w, int h); + + struct vo_cocoa_input_queue *input_queue; +}; static struct vo_cocoa_state *vo_cocoa_init_state(struct vo *vo) { struct vo_cocoa_state *s = talloc_ptrtype(vo, s); *s = (struct vo_cocoa_state){ .did_resize = NO, + .did_async_resize = NO, .current_video_size = {0,0}, .previous_video_size = {0,0}, .windowed_mask = NSTitledWindowMask|NSClosableWindowMask| @@ -153,8 +200,11 @@ static struct vo_cocoa_state *vo_cocoa_init_state(struct vo *vo) .vo_cursor_autohide_delay = vo->opts->cursor_autohide_delay, .power_mgmt_assertion = kIOPMNullAssertionID, .accumulated_scroll = 0, + .lock = [[NSRecursiveLock alloc] init], + .input_queue = vo_cocoa_input_queue_init(s), }; if (!vo->opts->border) s->windowed_mask = NSBorderlessWindowMask; + return s; } @@ -165,9 +215,16 @@ static bool supports_hidpi(NSView *view) [view respondsToSelector:hdpi_selector]; } -bool vo_cocoa_gui_running(void) +static NSRect to_pixels(struct vo *vo, NSRect frame) { - return _instances > 0; + struct vo_cocoa_state *s = vo->cocoa; + NSView *view = [s->window contentView]; + + if (supports_hidpi(view)) { + return [view convertRectToBacking: frame]; + } else { + return frame; + } } void *vo_cocoa_glgetaddr(const char *s) @@ -208,7 +265,6 @@ int vo_cocoa_init(struct vo *vo) { vo->cocoa = vo_cocoa_init_state(vo); vo->wakeup_period = 0.02; - _instances++; disable_power_management(vo); return 1; @@ -216,17 +272,17 @@ int vo_cocoa_init(struct vo *vo) void vo_cocoa_uninit(struct vo *vo) { - struct vo_cocoa_state *s = vo->cocoa; - CGDisplayShowCursor(kCGDirectMainDisplay); - enable_power_management(vo); - [NSApp setPresentationOptions:NSApplicationPresentationDefault]; - - [s->window release]; - s->window = nil; - [s->glContext release]; - s->glContext = nil; + dispatch_sync(dispatch_get_main_queue(), ^{ + struct vo_cocoa_state *s = vo->cocoa; + CGDisplayShowCursor(kCGDirectMainDisplay); + enable_power_management(vo); + [NSApp setPresentationOptions:NSApplicationPresentationDefault]; - _instances--; + [s->window release]; + s->window = nil; + [s->glContext release]; + s->glContext = nil; + }); } void vo_cocoa_pause(struct vo *vo) @@ -239,6 +295,13 @@ void vo_cocoa_resume(struct vo *vo) disable_power_management(vo); } +void vo_cocoa_register_resize_callback(struct vo *vo, + void (*cb)(struct vo *vo, int w, int h)) +{ + struct vo_cocoa_state *s = vo->cocoa; + s->resize_redraw = cb; +} + static int current_screen_has_dock_or_menubar(struct vo *vo) { struct vo_cocoa_state *s = vo->cocoa; @@ -296,23 +359,11 @@ void vo_cocoa_update_xinerama_info(struct vo *vo) vo->xinerama_y = s->screen_frame.origin.y; } -int vo_cocoa_change_attributes(struct vo *vo) -{ - return 0; -} - static void resize_window(struct vo *vo) { struct vo_cocoa_state *s = vo->cocoa; NSView *view = [s->window contentView]; - NSRect frame; - - if (supports_hidpi(view)) { - frame = [view convertRectToBacking: [view frame]]; - } else { - frame = [view frame]; - } - + NSRect frame = to_pixels(vo, [view frame]); vo->dwidth = frame.size.width; vo->dheight = frame.size.height; [s->glContext update]; @@ -402,8 +453,7 @@ static int create_window(struct vo *vo, uint32_t d_width, uint32_t d_height, [glView release]; [s->window setAcceptsMouseMovedEvents:YES]; [s->glContext setView:glView]; - [s->glContext makeCurrentContext]; - [s->window setVideoOutput:vo]; + s->window.videoOutput = vo; [s->window setDelegate:s->window]; [s->window makeMainWindow]; @@ -433,58 +483,103 @@ static void update_window(struct vo *vo) } } +static void resize_redraw(struct vo *vo, int width, int height) +{ + struct vo_cocoa_state *s = vo->cocoa; + if (s->resize_redraw) { + vo_cocoa_set_current_context(vo, true); + [s->glContext update]; + s->resize_redraw(vo, width, height); + [s->glContext flushBuffer]; + s->did_async_resize = YES; + vo_cocoa_set_current_context(vo, false); + } +} + int vo_cocoa_config_window(struct vo *vo, uint32_t d_width, uint32_t d_height, uint32_t flags, int gl3profile) { - struct vo_cocoa_state *s = vo->cocoa; - struct mp_vo_opts *opts = vo->opts; + __block int rv = 0; + dispatch_sync(dispatch_get_main_queue(), ^{ + struct vo_cocoa_state *s = vo->cocoa; + struct mp_vo_opts *opts = vo->opts; - if (vo->config_count > 0) { - NSPoint origin = [s->window frame].origin; - vo->dx = origin.x; - vo->dy = origin.y; - } + if (vo->config_count > 0) { + NSPoint origin = [s->window frame].origin; + vo->dx = origin.x; + vo->dy = origin.y; + } - update_state_sizes(s, d_width, d_height); + s->aspdat = vo->aspdat; + update_state_sizes(s, d_width, d_height); - if (!(s->window || s->glContext)) { - if (create_window(vo, d_width, d_height, flags, gl3profile) < 0) - return -1; - } else { - update_window(vo); - } + if (!(s->window || s->glContext)) { + if (create_window(vo, d_width, d_height, flags, gl3profile) < 0) + rv = -1; + } else { + update_window(vo); + } - [s->window setFrameOrigin:NSMakePoint(vo->dx, vo->dy)]; + [s->window setFrameOrigin:NSMakePoint(vo->dx, vo->dy)]; - if (flags & VOFLAG_HIDDEN) { - [s->window orderOut:nil]; - } else { - [s->window makeKeyAndOrderFront:nil]; - [NSApp activateIgnoringOtherApps:YES]; - } + if (flags & VOFLAG_HIDDEN) { + [s->window orderOut:nil]; + } else { + [s->window makeKeyAndOrderFront:nil]; + [NSApp activateIgnoringOtherApps:YES]; + } - if (flags & VOFLAG_FULLSCREEN && !vo->opts->fs) - vo_cocoa_fullscreen(vo); + if (flags & VOFLAG_FULLSCREEN && !vo->opts->fs) + vo_cocoa_fullscreen(vo); - vo_set_level(vo, opts->ontop); + vo_set_level(vo, opts->ontop); + + resize_window(vo); - resize_window(vo); + if (s->window_title) + [s->window_title release]; - if (s->window_title) - [s->window_title release]; + s->window_title = + [[NSString alloc] initWithUTF8String:vo_get_window_title(vo)]; + [s->window setTitle: s->window_title]; + }); - s->window_title = - [[NSString alloc] initWithUTF8String:vo_get_window_title(vo)]; - [s->window setTitle: s->window_title]; + [vo->cocoa->glContext makeCurrentContext]; - return 0; + return rv; +} + +static bool resize_callback_registered(struct vo *vo) +{ + struct vo_cocoa_state *s = vo->cocoa; + return s->resize_redraw; +} + +void vo_cocoa_set_current_context(struct vo *vo, bool current) +{ + struct vo_cocoa_state *s = vo->cocoa; + if (current) { + [s->lock lock]; + [s->glContext makeCurrentContext]; + } else { + [NSOpenGLContext clearCurrentContext]; + [s->lock unlock]; + } } void vo_cocoa_swap_buffers(struct vo *vo) { struct vo_cocoa_state *s = vo->cocoa; - [s->glContext flushBuffer]; + if (s->did_async_resize && resize_callback_registered(vo)) { + // when in live resize the GL view asynchronously updates itself from + // it's drawRect: implementation and calls flushBuffer. This means the + // backbuffer is probably in an inconsistent state, so we skip one + // flushBuffer call here on the playloop thread. + s->did_async_resize = NO; + } else { + [s->glContext flushBuffer]; + } } static void vo_cocoa_display_cursor(struct vo *vo, int requested_state) @@ -516,6 +611,9 @@ int vo_cocoa_check_events(struct vo *vo) s->cursor_timer = ms_time; } + int key = cocoa_sync_get_key(s->input_queue); + if (key >= 0) mplayer_put_key(vo->key_fifo, key); + if (s->did_resize) { s->did_resize = NO; resize_window(vo); @@ -527,9 +625,17 @@ int vo_cocoa_check_events(struct vo *vo) void vo_cocoa_fullscreen(struct vo *vo) { + // This is the secondary thread, unlock since we are going to invoke a + // method synchronously on the GUI thread using Cocoa. + vo_cocoa_set_current_context(vo, false); + struct vo_cocoa_state *s = vo->cocoa; - [s->window fullscreen]; - resize_window(vo); + [s->window performSelectorOnMainThread:@selector(fullscreen) + withObject:nil + waitUntilDone:YES]; + + // Now lock again! + vo_cocoa_set_current_context(vo, true); } int vo_cocoa_swap_interval(int enabled) @@ -567,34 +673,30 @@ int vo_cocoa_cgl_color_size(struct vo *vo) } @implementation GLMPlayerWindow -- (void)setVideoOutput:(struct vo *)vo -{ - _vo = vo; -} - +@synthesize videoOutput = _video_output; - (void)windowDidResize:(NSNotification *) notification { - if (_vo) { - struct vo_cocoa_state *s = _vo->cocoa; + if (self.videoOutput) { + struct vo_cocoa_state *s = self.videoOutput->cocoa; s->did_resize = YES; } } - - (void)fullscreen { - struct vo_cocoa_state *s = _vo->cocoa; - struct mp_vo_opts *opts = _vo->opts; + struct vo_cocoa_state *s = self.videoOutput->cocoa; + struct mp_vo_opts *opts = self.videoOutput->opts; + if (!opts->fs) { - update_screen_info(_vo); - if (current_screen_has_dock_or_menubar(_vo)) + update_screen_info(self.videoOutput); + if (current_screen_has_dock_or_menubar(self.videoOutput)) [NSApp setPresentationOptions:NSApplicationPresentationHideDock| NSApplicationPresentationHideMenuBar]; s->windowed_frame = [self frame]; [self setHasShadow:NO]; [self setStyleMask:s->fullscreen_mask]; [self setFrame:s->fsscreen_frame display:YES animate:NO]; - opts->fs = true; - vo_cocoa_display_cursor(_vo, 0); + opts->fs = VO_TRUE; + vo_cocoa_display_cursor(self.videoOutput, 0); [self setMovableByWindowBackground: NO]; } else { [NSApp setPresentationOptions:NSApplicationPresentationDefault]; @@ -608,9 +710,11 @@ int vo_cocoa_cgl_color_size(struct vo *vo) } [self setContentAspectRatio:s->current_video_size]; opts->fs = false; - vo_cocoa_display_cursor(_vo, 1); + vo_cocoa_display_cursor(self.videoOutput, 1); [self setMovableByWindowBackground: YES]; } + + resize_window(self.videoOutput); } - (BOOL)canBecomeMainWindow { return YES; } @@ -620,7 +724,8 @@ int vo_cocoa_cgl_color_size(struct vo *vo) - (BOOL)resignFirstResponder { return YES; } - (BOOL)windowShouldClose:(id)sender { - mplayer_put_key(_vo->key_fifo, MP_KEY_CLOSE_WIN); + struct vo_cocoa_state *s = self.videoOutput->cocoa; + cocoa_async_put_key(s->input_queue, MP_KEY_CLOSE_WIN); // We have to wait for MPlayer to handle this, // otherwise we are in trouble if the // MP_KEY_CLOSE_WIN handler is disabled @@ -631,8 +736,8 @@ int vo_cocoa_cgl_color_size(struct vo *vo) { // this is only valid as a starting value. it will be rewritten in the // -fullscreen method. - if (_vo) { - return !_vo->opts->fs; + if (self.videoOutput) { + return !self.videoOutput->opts->fs; } else { return NO; } @@ -640,6 +745,7 @@ int vo_cocoa_cgl_color_size(struct vo *vo) - (void)keyDown:(NSEvent *)theEvent { + struct vo_cocoa_state *s = self.videoOutput->cocoa; NSString *chars; if (RightAltPressed(theEvent)) @@ -658,14 +764,15 @@ int vo_cocoa_cgl_color_size(struct vo *vo) key |= MP_KEY_MODIFIER_ALT; if ([theEvent modifierFlags] & NSCommandKeyMask) key |= MP_KEY_MODIFIER_META; - mplayer_put_key(_vo->key_fifo, key); + + cocoa_async_put_key(s->input_queue, key); } } - (void)mouseMoved: (NSEvent *) theEvent { - if (_vo->opts->fs) - vo_cocoa_display_cursor(_vo, 1); + if (self.videoOutput->opts->fs) + vo_cocoa_display_cursor(self.videoOutput, 1); } - (void)mouseDragged:(NSEvent *)theEvent @@ -705,7 +812,7 @@ int vo_cocoa_cgl_color_size(struct vo *vo) - (void)scrollWheel:(NSEvent *)theEvent { - struct vo_cocoa_state *s = _vo->cocoa; + struct vo_cocoa_state *s = self.videoOutput->cocoa; CGFloat delta; // Use the dimention with the most delta as the scrolling one @@ -721,23 +828,24 @@ int vo_cocoa_cgl_color_size(struct vo *vo) static const CGFloat threshold = 10; while (s->accumulated_scroll >= threshold) { s->accumulated_scroll -= threshold; - mplayer_put_key(_vo->key_fifo, MP_MOUSE_BTN3); + cocoa_async_put_key(s->input_queue, MP_MOUSE_BTN3); } while (s->accumulated_scroll <= -threshold) { s->accumulated_scroll += threshold; - mplayer_put_key(_vo->key_fifo, MP_MOUSE_BTN4); + cocoa_async_put_key(s->input_queue, MP_MOUSE_BTN4); } } else { if (delta > 0) - mplayer_put_key(_vo->key_fifo, MP_MOUSE_BTN3); + cocoa_async_put_key(s->input_queue, MP_MOUSE_BTN3); else - mplayer_put_key(_vo->key_fifo, MP_MOUSE_BTN4); + cocoa_async_put_key(s->input_queue, MP_MOUSE_BTN4); } } - (void)mouseEvent:(NSEvent *)theEvent { if ([theEvent buttonNumber] >= 0 && [theEvent buttonNumber] <= 9) { + struct vo_cocoa_state *s = self.videoOutput->cocoa; int buttonNumber = [theEvent buttonNumber]; // Fix to mplayer defined button order: left, middle, right if (buttonNumber == 1) buttonNumber = 2; @@ -746,18 +854,21 @@ int vo_cocoa_cgl_color_size(struct vo *vo) case NSLeftMouseDown: case NSRightMouseDown: case NSOtherMouseDown: - mplayer_put_key(_vo->key_fifo, - (MP_MOUSE_BTN0 + buttonNumber) | MP_KEY_STATE_DOWN); + cocoa_async_put_key( + s->input_queue, + (MP_MOUSE_BTN0 + buttonNumber) | MP_KEY_STATE_DOWN); // Looks like Cocoa doesn't create MouseUp events when we are // doing the second click in a double click. Put in the key_fifo // the key that would be put from the MouseUp handling code. if([theEvent clickCount] == 2) - mplayer_put_key(_vo->key_fifo, MP_MOUSE_BTN0 + buttonNumber); + cocoa_async_put_key(s->input_queue, + MP_MOUSE_BTN0 + buttonNumber); break; case NSLeftMouseUp: case NSRightMouseUp: case NSOtherMouseUp: - mplayer_put_key(_vo->key_fifo, MP_MOUSE_BTN0 + buttonNumber); + cocoa_async_put_key(s->input_queue, + MP_MOUSE_BTN0 + buttonNumber); break; } } @@ -771,10 +882,10 @@ int vo_cocoa_cgl_color_size(struct vo *vo) - (void)mulSize:(float)multiplier { - if (!_vo->opts->fs) { + if (!self.videoOutput->opts->fs) { NSSize size = { - .width = _vo->aspdat.prew * multiplier, - .height = _vo->aspdat.preh * multiplier + .width = self.videoOutput->cocoa->aspdat.prew * multiplier, + .height = self.videoOutput->cocoa->aspdat.preh * multiplier }; [self setContentSize:size keepCentered:YES]; } @@ -847,7 +958,14 @@ int vo_cocoa_cgl_color_size(struct vo *vo) @implementation GLMPlayerOpenGLView - (void)drawRect: (NSRect)rect { - [[NSColor clearColor] set]; - NSRectFill([self bounds]); + GLMPlayerWindow *window = (GLMPlayerWindow *)[self window]; + struct vo *vo = [window videoOutput]; + if (vo && resize_callback_registered(vo)) { + NSSize size = to_pixels(vo, [self bounds]).size; + resize_redraw(vo, size.width, size.height); + } else { + [[NSColor clearColor] set]; + NSRectFill([self bounds]); + } } @end diff --git a/video/out/gl_cocoa.c b/video/out/gl_cocoa.c index 81be21da58..dd8b5a865a 100644 --- a/video/out/gl_cocoa.c +++ b/video/out/gl_cocoa.c @@ -51,6 +51,11 @@ static void swapGlBuffers_cocoa(MPGLContext *ctx) vo_cocoa_swap_buffers(ctx->vo); } +static void set_current_cocoa(MPGLContext *ctx, bool current) +{ + vo_cocoa_set_current_context(ctx->vo, current); +} + void mpgl_set_backend_cocoa(MPGLContext *ctx) { ctx->config_window = config_window_cocoa; @@ -63,5 +68,8 @@ void mpgl_set_backend_cocoa(MPGLContext *ctx) ctx->vo_init = vo_cocoa_init; ctx->pause = vo_cocoa_pause; ctx->resume = vo_cocoa_resume; + ctx->register_resize_callback = vo_cocoa_register_resize_callback; ctx->vo_uninit = vo_cocoa_uninit; + ctx->set_current = set_current_cocoa; + ctx->set_current = set_current_cocoa; } diff --git a/video/out/gl_common.h b/video/out/gl_common.h index 18d1cf8879..1956b73616 100644 --- a/video/out/gl_common.h +++ b/video/out/gl_common.h @@ -131,6 +131,13 @@ typedef struct MPGLContext { void (*border)(struct vo *vo); void (*update_xinerama_info)(struct vo *vo); + // An optional function to register a resize callback in the backend that + // can be called on separate thread to handle resize events immediately + // (without waiting for vo_check_events, which will come later for the + // proper resize) + void (*register_resize_callback)(struct vo *vo, + void (*cb)(struct vo *vo, int w, int h)); + // For free use by the backend. void *priv; } MPGLContext; diff --git a/video/out/vo_opengl.c b/video/out/vo_opengl.c index 5d59912856..b5cdca7a82 100644 --- a/video/out/vo_opengl.c +++ b/video/out/vo_opengl.c @@ -156,6 +156,13 @@ static bool config_window(struct gl_priv *p, uint32_t d_width, return mpgl_config_window(p->glctx, mpgl_caps, d_width, d_height, flags); } +static void video_resize_redraw_callback(struct vo *vo, int w, int h) +{ + struct gl_priv *p = vo->priv; + gl_video_resize_redraw(p->renderer, w, h); + +} + static int config(struct vo *vo, uint32_t width, uint32_t height, uint32_t d_width, uint32_t d_height, uint32_t flags, uint32_t format) @@ -169,6 +176,10 @@ static int config(struct vo *vo, uint32_t width, uint32_t height, return -1; } + if (p->glctx->register_resize_callback) { + p->glctx->register_resize_callback(vo, video_resize_redraw_callback); + } + gl_video_config(p->renderer, format, width, height, p->vo->aspdat.prew, p->vo->aspdat.preh); @@ -353,6 +364,8 @@ static int preinit(struct vo *vo, const char *arg) if (!config_window(p, 320, 200, VOFLAG_HIDDEN)) goto err_out; + mpgl_set_context(p->glctx); + if (p->gl->SwapInterval) p->gl->SwapInterval(p->swap_interval); -- cgit v1.2.3