From fa904150bfb7467b66e7fc0a7c709e61cb3dd9fc Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Sat, 18 Oct 2014 18:30:22 +0200 Subject: cocoa: reintroduce async resize After removing synchronous libdispatch calls, this looks like it doesn't deadlock anymore. I also experimented with pthread_mutex_trylock liek wm4 suggested, but it leads to some annoying black flickering. I will fallback to that only if some new deadlocks are discovered. --- video/out/cocoa/mpvadapter.h | 3 +-- video/out/cocoa/video_view.m | 6 ++++++ video/out/cocoa_common.m | 46 +++++++++++++++++++++++++++++++++++++------- video/out/gl_cocoa.c | 1 + video/out/gl_video.c | 12 ++++++++++++ video/out/gl_video.h | 1 + video/out/vo_opengl.c | 11 +++++++++++ 7 files changed, 71 insertions(+), 9 deletions(-) diff --git a/video/out/cocoa/mpvadapter.h b/video/out/cocoa/mpvadapter.h index 30e2d572d8..8829abd096 100644 --- a/video/out/cocoa/mpvadapter.h +++ b/video/out/cocoa/mpvadapter.h @@ -19,8 +19,6 @@ #include "video/out/vo.h" @interface MpvCocoaAdapter : NSObject -- (void)lock; -- (void)unlock; - (void)setNeedsResize; - (void)signalMouseMovement:(NSPoint)point; - (void)putKeyEvent:(NSEvent*)event; @@ -29,6 +27,7 @@ - (void)putCommand:(char*)cmd; - (void)handleFilesArray:(NSArray *)files; - (void)didChangeWindowedScreenProfile:(NSScreen *)screen; +- (void)performAsyncResize:(NSSize)size; - (BOOL)isInFullScreenMode; - (BOOL)keyboardEnabled; diff --git a/video/out/cocoa/video_view.m b/video/out/cocoa/video_view.m index 07db876534..786c6ef4da 100644 --- a/video/out/cocoa/video_view.m +++ b/video/out/cocoa/video_view.m @@ -40,4 +40,10 @@ { return [self convertRectToBacking:[self frame]]; } + + +- (void)drawRect:(NSRect)rect +{ + [self.adapter performAsyncResize:[self frameInPixels].size]; +} @end diff --git a/video/out/cocoa_common.m b/video/out/cocoa_common.m index 28a642f0df..12a3fc5f67 100644 --- a/video/out/cocoa_common.m +++ b/video/out/cocoa_common.m @@ -70,6 +70,7 @@ struct vo_cocoa_state { int pending_events; bool waiting_frame; + bool skip_swap_buffer; bool embedded; // wether we are embedding in another GUI IOPMAssertionID power_mgmt_assertion; @@ -83,6 +84,8 @@ struct vo_cocoa_state { char *icc_wnd_profile_path; char *icc_fs_profile_path; id fs_icc_changed_ns_observer; + + void (*resize_redraw)(struct vo *vo, int w, int h); }; static void with_cocoa_lock(struct vo *vo, void(^block)(void)) @@ -175,6 +178,13 @@ static int vo_cocoa_set_cursor_visibility(struct vo *vo, bool *visible) return VO_TRUE; } +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; +} + void vo_cocoa_uninit(struct vo *vo) { with_cocoa_lock(vo, ^{ @@ -456,6 +466,26 @@ void vo_cocoa_set_current_context(struct vo *vo, bool current) } } +static void vo_cocoa_resize_redraw(struct vo *vo, int width, int height) +{ + struct vo_cocoa_state *s = vo->cocoa; + + if (!s->gl_ctx) + return; + + if (!s->resize_redraw) + return; + + vo_cocoa_set_current_context(vo, true); + + [s->gl_ctx update]; + s->resize_redraw(vo, width, height); + s->skip_swap_buffer = true; + + [s->gl_ctx flushBuffer]; + vo_cocoa_set_current_context(vo, false); +} + static void draw_changes_after_next_frame(struct vo *vo) { struct vo_cocoa_state *s = vo->cocoa; @@ -468,7 +498,13 @@ static void draw_changes_after_next_frame(struct vo *vo) void vo_cocoa_swap_buffers(struct vo *vo) { struct vo_cocoa_state *s = vo->cocoa; - [s->gl_ctx flushBuffer]; + if (s->skip_swap_buffer) { + s->skip_swap_buffer = false; + return; + } else { + [s->gl_ctx flushBuffer]; + } + if (s->waiting_frame) { s->waiting_frame = false; NSEnableScreenUpdates(); @@ -687,12 +723,8 @@ void *vo_cocoa_cgl_pixel_format(struct vo *vo) @implementation MpvCocoaAdapter @synthesize vout = _video_output; -- (void)lock { - vo_cocoa_set_current_context(self.vout, true); -} - -- (void)unlock { - vo_cocoa_set_current_context(self.vout, false); +- (void)performAsyncResize:(NSSize)size { + vo_cocoa_resize_redraw(self.vout, size.width, size.height); } - (BOOL)keyboardEnabled { diff --git a/video/out/gl_cocoa.c b/video/out/gl_cocoa.c index 4c07806c77..32c66675f0 100644 --- a/video/out/gl_cocoa.c +++ b/video/out/gl_cocoa.c @@ -149,6 +149,7 @@ void mpgl_set_backend_cocoa(MPGLContext *ctx) ctx->releaseGlContext = releaseGlContext_cocoa; ctx->swapGlBuffers = swapGlBuffers_cocoa; ctx->vo_init = vo_cocoa_init; + ctx->register_resize_callback = vo_cocoa_register_resize_callback; ctx->vo_uninit = vo_cocoa_uninit; ctx->vo_control = vo_cocoa_control; ctx->set_current = set_current_cocoa; diff --git a/video/out/gl_video.c b/video/out/gl_video.c index c66021ee76..7e416a61c2 100644 --- a/video/out/gl_video.c +++ b/video/out/gl_video.c @@ -2388,6 +2388,18 @@ static int validate_scaler_opt(struct mp_log *log, const m_option_t *opt, return handle_scaler_opt(s) ? 1 : M_OPT_INVALID; } +// Resize and redraw the contents of the window without further configuration. +// Intended to be used in situations where the frontend can't really be +// involved with reconfiguring the VO properly. +// gl_video_resize() should be called when user interaction is done. +void gl_video_resize_redraw(struct gl_video *p, int w, int h) +{ + p->gl->Viewport(p->vp_x, p->vp_y, w, h); + p->vp_w = w; + p->vp_h = h; + gl_video_render_frame(p); +} + void gl_video_set_hwdec(struct gl_video *p, struct gl_hwdec *hwdec) { p->hwdec = hwdec; diff --git a/video/out/gl_video.h b/video/out/gl_video.h index 47d09d7f57..8ea5d3420f 100644 --- a/video/out/gl_video.h +++ b/video/out/gl_video.h @@ -74,6 +74,7 @@ bool gl_video_set_equalizer(struct gl_video *p, const char *name, int val); bool gl_video_get_equalizer(struct gl_video *p, const char *name, int *val); void gl_video_set_debug(struct gl_video *p, bool enable); +void gl_video_resize_redraw(struct gl_video *p, int w, int h); struct gl_hwdec; void gl_video_set_hwdec(struct gl_video *p, struct gl_hwdec *hwdec); diff --git a/video/out/vo_opengl.c b/video/out/vo_opengl.c index 1acd6ef466..3b6e3a2e43 100644 --- a/video/out/vo_opengl.c +++ b/video/out/vo_opengl.c @@ -203,6 +203,13 @@ static bool config_window(struct gl_priv *p, int flags) return mpgl_config_window(p->glctx, mpgl_caps, 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 reconfig(struct vo *vo, struct mp_image_params *params, int flags) { struct gl_priv *p = vo->priv; @@ -214,6 +221,10 @@ static int reconfig(struct vo *vo, struct mp_image_params *params, int flags) return -1; } + if (p->glctx->register_resize_callback) { + p->glctx->register_resize_callback(vo, video_resize_redraw_callback); + } + gl_video_config(p->renderer, params); p->vo_flipped = !!(flags & VOFLAG_FLIPPING); -- cgit v1.2.3