cocoa: automatically fetch display-fps from the monitor

Comment explains why I have been so doubtful at adding this. The Apple docs
say CGDisplayModeGetRefreshRate is supposed to work only for CRTs, but it
doesn't, and actually works for LCD TVs connected over HDMI and external
displays (at least that's what I'm told, I don't have the hardware to test).
Maybe Apple docs are incorrect.

Since AFAIK Apple doesn't want to give us a better API – maybe in the fear we
might be able to actually write some useful software instead of "apps" –
I decided not to care as well and commit this.
This commit is contained in:
Stefano Pigozzi 2015-02-03 21:43:20 +01:00
parent a33b46194c
commit aeb1fca0d4
2 changed files with 28 additions and 2 deletions

View File

@ -600,8 +600,8 @@ Available video output drivers are:
can lead to bad results. If the framerate is close to or over the
display refresh rate, results can be bad as well.
.. note:: On systems other than Linux, you currently must set the
``--display-fps`` option, or the results will be bad.
.. note:: On systems other than Linux or OS X, you currently must set
the ``--display-fps`` option, or the results will be bad.
``smoothmotion-threshold=<0.0-0.5>``
Mix threshold at which interpolation is skipped (default: 0.0 never

View File

@ -62,6 +62,7 @@ struct vo_cocoa_state {
NSScreen *current_screen;
NSScreen *fs_screen;
double screen_fps;
NSInteger window_level;
@ -256,6 +257,27 @@ static void vo_cocoa_update_screens_pointers(struct vo *vo)
get_screen_handle(vo, opts->fsscreen_id, s->window, &s->fs_screen);
}
static void vo_cocoa_update_screen_fps(struct vo *vo)
{
struct vo_cocoa_state *s = vo->cocoa;
NSScreen *screen = vo->opts->fullscreen ? s->fs_screen : s->current_screen;
NSDictionary* sinfo = [screen deviceDescription];
NSNumber* sid = [sinfo objectForKey:@"NSScreenNumber"];
CGDirectDisplayID did = [sid longValue];
CGDisplayModeRef mode = CGDisplayCopyDisplayMode(did);
s->screen_fps = CGDisplayModeGetRefreshRate(mode);
CGDisplayModeRelease(mode);
if (s->screen_fps == 0.0) {
// Most internal Apple monitors and laptop monitors report 0 instead
// of 60fps. Assume them to be 60hz. This is technically incorrect but
// works most of the time, and seems to be used in most open source
// software for lack of a better Apple API.
MP_VERBOSE(vo, "CoreGraphics reports a 0fps display. Assuming internal "
"Apple monitor @ 60fps instead.\n");
s->screen_fps = 60.0;
}
}
static void vo_cocoa_update_screen_info(struct vo *vo, struct mp_rect *out_rc)
{
struct vo_cocoa_state *s = vo->cocoa;
@ -264,6 +286,7 @@ static void vo_cocoa_update_screen_info(struct vo *vo, struct mp_rect *out_rc)
return;
vo_cocoa_update_screens_pointers(vo);
vo_cocoa_update_screen_fps(vo);
if (out_rc) {
NSRect r = [s->current_screen frame];
@ -649,6 +672,9 @@ int vo_cocoa_control(struct vo *vo, int *events, int request, void *arg)
case VOCTRL_GET_ICC_PROFILE:
vo_cocoa_control_get_icc_profile(vo, arg);
return VO_TRUE;
case VOCTRL_GET_DISPLAY_FPS:
*(double *)arg = vo->cocoa->screen_fps;
return VO_TRUE;
}
return VO_NOTIMPL;
}