diff options
Diffstat (limited to 'video/out/cocoa_common.m')
-rw-r--r-- | video/out/cocoa_common.m | 65 |
1 files changed, 51 insertions, 14 deletions
diff --git a/video/out/cocoa_common.m b/video/out/cocoa_common.m index 58b0df518f..0b10217f80 100644 --- a/video/out/cocoa_common.m +++ b/video/out/cocoa_common.m @@ -87,6 +87,11 @@ struct vo_cocoa_state { uint32_t old_dwidth; uint32_t old_dheight; + CVDisplayLinkRef link; + pthread_mutex_t sync_lock; + pthread_cond_t sync_wakeup; + uint64_t sync_counter; + pthread_mutex_t lock; pthread_cond_t wakeup; @@ -305,6 +310,26 @@ static void vo_cocoa_update_screen_info(struct vo *vo) } } +static void vo_cocoa_init_displaylink(struct vo *vo) +{ + struct vo_cocoa_state *s = vo->cocoa; + + NSDictionary* sinfo = [s->current_screen deviceDescription]; + NSNumber* sid = [sinfo objectForKey:@"NSScreenNumber"]; + CGDirectDisplayID did = [sid longValue]; + + CVDisplayLinkCreateWithCGDisplay(did, &s->link); + CVDisplayLinkSetOutputCallback(s->link, &displayLinkCallback, vo); + CVDisplayLinkStart(s->link); +} + +static void vo_cocoa_uninit_displaylink(struct vo_cocoa_state *s) +{ + if (CVDisplayLinkIsRunning(s->link)) + CVDisplayLinkStop(s->link); + CVDisplayLinkRelease(s->link); +} + void vo_cocoa_init(struct vo *vo) { struct vo_cocoa_state *s = talloc_zero(NULL, struct vo_cocoa_state); @@ -321,6 +346,8 @@ void vo_cocoa_init(struct vo *vo) } pthread_mutex_init(&s->lock, NULL); pthread_cond_init(&s->wakeup, NULL); + pthread_mutex_init(&s->sync_lock, NULL); + pthread_cond_init(&s->sync_wakeup, NULL); vo->cocoa = s; vo_cocoa_update_screen_info(vo); cocoa_init_light_sensor(vo); @@ -362,6 +389,10 @@ void vo_cocoa_uninit(struct vo *vo) run_on_main_thread(vo, ^{ enable_power_management(s); + vo_cocoa_uninit_displaylink(s); + pthread_mutex_lock(&s->sync_lock); + pthread_cond_signal(&s->sync_wakeup); + pthread_mutex_unlock(&s->sync_lock); cocoa_uninit_light_sensor(s); cocoa_rm_screen_reconfiguration_observer(vo); @@ -384,6 +415,8 @@ void vo_cocoa_uninit(struct vo *vo) if (!s->embedded) [s->blankCursor release]; + pthread_cond_destroy(&s->sync_wakeup); + pthread_mutex_destroy(&s->sync_lock); pthread_cond_destroy(&s->wakeup); pthread_mutex_destroy(&s->lock); talloc_free(s); @@ -398,30 +431,19 @@ static void vo_cocoa_update_screen_fps(struct vo *vo) NSNumber* sid = [sinfo objectForKey:@"NSScreenNumber"]; CGDirectDisplayID did = [sid longValue]; - CVDisplayLinkRef link; - CVDisplayLinkCreateWithCGDisplay(did, &link); - CVDisplayLinkSetOutputCallback(link, &displayLinkCallback, NULL); - CVDisplayLinkStart(link); - CVDisplayLinkSetCurrentCGDisplay(link, did); - - double display_period = CVDisplayLinkGetActualOutputVideoRefreshPeriod(link); + CVDisplayLinkSetCurrentCGDisplay(s->link, did); + double display_period = CVDisplayLinkGetActualOutputVideoRefreshPeriod(s->link); if (display_period > 0) { s->screen_fps = 1/display_period; } else { - // Fallback to using Nominal refresh rate from DisplayLink, - // CVDisplayLinkGet *Actual* OutputVideoRefreshPeriod seems to - // return 0 on some Apple devices. Use the nominal refresh period - // instead. - const CVTime t = CVDisplayLinkGetNominalOutputVideoRefreshPeriod(link); + const CVTime t = CVDisplayLinkGetNominalOutputVideoRefreshPeriod(s->link); if (!(t.flags & kCVTimeIsIndefinite)) { s->screen_fps = (t.timeScale / (double) t.timeValue); MP_VERBOSE(vo, "Falling back to %f for display sync.\n", s->screen_fps); } } - CVDisplayLinkRelease(link); - flag_events(vo, VO_EVENT_WIN_STATE); } @@ -429,6 +451,13 @@ static CVReturn displayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeSt const CVTimeStamp* outputTime, CVOptionFlags flagsIn, CVOptionFlags* flagsOut, void* displayLinkContext) { + struct vo *vo = displayLinkContext; + struct vo_cocoa_state *s = vo->cocoa; + + pthread_mutex_lock(&s->sync_lock); + s->sync_counter += 1; + pthread_cond_signal(&s->sync_wakeup); + pthread_mutex_unlock(&s->sync_lock); return kCVReturnSuccess; } @@ -603,6 +632,7 @@ int vo_cocoa_config_window(struct vo *vo) struct mp_vo_opts *opts = vo->opts; run_on_main_thread(vo, ^{ + vo_cocoa_init_displaylink(vo); vo_cocoa_update_screen_fps(vo); NSRect r = [s->current_screen frame]; @@ -700,6 +730,13 @@ void vo_cocoa_swap_buffers(struct vo *vo) if (skip) return; + pthread_mutex_lock(&s->sync_lock); + uint64_t old_counter = s->sync_counter; + while(old_counter == s->sync_counter) { + pthread_cond_wait(&s->sync_wakeup, &s->sync_lock); + } + pthread_mutex_unlock(&s->sync_lock); + pthread_mutex_lock(&s->lock); s->frame_w = vo->dwidth; s->frame_h = vo->dheight; |