summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--video/out/cocoa_common.m65
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;