Merge pull request #637 from VPeruS/macos-refresh-rate

Fix DisplayDevice.RefreshRate being 0 for some monitors on MacOS.

Use CoreVideo CVDisplayLink to get correct display refresh rate. Previous implementation can sometimes return 0 according to https://developer.apple.com/documentation/coregraphics/1454661-cgdisplaymodegetrefreshrate.
This commit is contained in:
Fraser Waters 2017-08-26 12:49:52 +01:00 committed by GitHub
commit ee7f578253
3 changed files with 49 additions and 0 deletions

View file

@ -780,6 +780,7 @@
<None Include="OpenTK.csproj.paket.template" />
<None Include="paket.references" />
<Compile Include="Platform\MacOS\Cocoa\NSDragOperation.cs" />
<Compile Include="Platform\MacOS\CoreVideo.cs" />
</ItemGroup>
<ItemGroup>
<AdditionalFiles Include="$(SolutionDir)\stylecop.json">

View file

@ -0,0 +1,34 @@
// See License.txt file for copyright details
using System;
using System.Runtime.InteropServices;
namespace OpenTK.Platform.MacOS
{
[StructLayout(LayoutKind.Sequential)]
internal struct CVTime
{
public Int64 timeValue;
public Int32 timeScale;
public Int32 flags;
}
internal class CV
{
private const string LibPath = "/System/Library/Frameworks/CoreVideo.framework/Versions/Current/CoreVideo";
internal enum TimeFlags : Int32
{
TimeIsIndefinite = 1 << 0
}
[DllImport(LibPath, EntryPoint = "CVDisplayLinkCreateWithCGDisplay")]
public extern static IntPtr DisplayLinkCreateWithCGDisplay(IntPtr currentDisplay, out IntPtr displayLink);
[DllImport(LibPath, EntryPoint = "CVDisplayLinkGetNominalOutputVideoRefreshPeriod")]
public extern static CVTime DisplayLinkGetNominalOutputVideoRefreshPeriod(IntPtr displayLink);
[DllImport(LibPath, EntryPoint = "CVDisplayLinkRelease")]
public extern static void DisplayLinkRelease(IntPtr displayLink);
}
}

View file

@ -94,6 +94,20 @@ namespace OpenTK.Platform.MacOS
double freq = dict.GetNumberValue("RefreshRate");
bool current = currentMode.Ref == dict.Ref;
if (freq <= 0)
{
IntPtr displayLink;
CV.DisplayLinkCreateWithCGDisplay(currentDisplay, out displayLink);
CVTime t = CV.DisplayLinkGetNominalOutputVideoRefreshPeriod(displayLink);
if ((t.flags & (Int32)CV.TimeFlags.TimeIsIndefinite) != (Int32)CV.TimeFlags.TimeIsIndefinite)
{
freq = (double)t.timeScale / t.timeValue;
}
CV.DisplayLinkRelease(displayLink);
}
//if (current) Debug.Write(" * ");
//else Debug.Write(" ");