|
|
@ -1,13 +1,20 @@ |
|
|
using System; |
|
|
using System; |
|
|
|
|
|
using System.Collections.Generic; |
|
|
using System.Diagnostics; |
|
|
using System.Diagnostics; |
|
|
|
|
|
using System.Runtime.InteropServices; |
|
|
using System.Threading.Tasks; |
|
|
using System.Threading.Tasks; |
|
|
using Avalonia.Logging; |
|
|
using Avalonia.Logging; |
|
|
using Avalonia.OpenGL.Egl; |
|
|
using Avalonia.OpenGL.Egl; |
|
|
using Avalonia.Rendering; |
|
|
using Avalonia.Rendering; |
|
|
using static Avalonia.Win32.Interop.UnmanagedMethods; |
|
|
|
|
|
using static Avalonia.Win32.DirectX.DirectXUnmanagedMethods; |
|
|
|
|
|
using MicroCom.Runtime; |
|
|
using MicroCom.Runtime; |
|
|
|
|
|
|
|
|
|
|
|
using Windows.Win32; |
|
|
|
|
|
using Windows.Win32.Graphics.Gdi; |
|
|
|
|
|
|
|
|
|
|
|
using static Avalonia.Win32.DirectX.DirectXUnmanagedMethods; |
|
|
|
|
|
using static Avalonia.Win32.Interop.UnmanagedMethods; |
|
|
|
|
|
|
|
|
namespace Avalonia.Win32.DirectX |
|
|
namespace Avalonia.Win32.DirectX |
|
|
{ |
|
|
{ |
|
|
internal unsafe class DxgiConnection : IRenderTimer, IWindowsSurfaceFactory |
|
|
internal unsafe class DxgiConnection : IRenderTimer, IWindowsSurfaceFactory |
|
|
@ -111,6 +118,8 @@ namespace Avalonia.Win32.DirectX |
|
|
|
|
|
|
|
|
ushort adapterIndex = 0; |
|
|
ushort adapterIndex = 0; |
|
|
|
|
|
|
|
|
|
|
|
Dictionary<HMONITOR /*MonitorHandler*/, uint /*Frequency*/> monitorFrequencies = GetAllMonitorFrequencies(); |
|
|
|
|
|
|
|
|
// this looks odd, but that's just how one enumerates adapters in DXGI
|
|
|
// this looks odd, but that's just how one enumerates adapters in DXGI
|
|
|
while (fact.EnumAdapters(adapterIndex, &adapterPointer) == 0) |
|
|
while (fact.EnumAdapters(adapterIndex, &adapterPointer) == 0) |
|
|
{ |
|
|
{ |
|
|
@ -122,8 +131,12 @@ namespace Avalonia.Win32.DirectX |
|
|
using var output = MicroComRuntime.CreateProxyFor<IDXGIOutput>(outputPointer, true); |
|
|
using var output = MicroComRuntime.CreateProxyFor<IDXGIOutput>(outputPointer, true); |
|
|
DXGI_OUTPUT_DESC outputDesc = output.Desc; |
|
|
DXGI_OUTPUT_DESC outputDesc = output.Desc; |
|
|
|
|
|
|
|
|
var screen = Win32Platform.Instance.Screen.ScreenFromHMonitor((IntPtr)outputDesc.Monitor.Value); |
|
|
var hMonitor = new HMONITOR(outputDesc.Monitor.Value); |
|
|
var frequency = screen?.Frequency ?? highestRefreshRate; |
|
|
|
|
|
|
|
|
var frequency = |
|
|
|
|
|
monitorFrequencies.TryGetValue(hMonitor, out uint frequencyValue) ? |
|
|
|
|
|
frequencyValue : |
|
|
|
|
|
highestRefreshRate; |
|
|
|
|
|
|
|
|
if (highestRefreshRate < frequency) |
|
|
if (highestRefreshRate < frequency) |
|
|
{ |
|
|
{ |
|
|
@ -145,6 +158,33 @@ namespace Avalonia.Win32.DirectX |
|
|
|
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private unsafe Dictionary<HMONITOR /*MonitorHandler*/, uint /*Frequency*/> GetAllMonitorFrequencies() |
|
|
|
|
|
{ |
|
|
|
|
|
var monitorHandlers = ScreenImpl.GetAllDisplayMonitorHandlers(); |
|
|
|
|
|
var dictionary = new Dictionary<HMONITOR /*MonitorHandler*/, uint /*Frequency*/>(monitorHandlers.Count); |
|
|
|
|
|
|
|
|
|
|
|
foreach (var monitorHandler in monitorHandlers) |
|
|
|
|
|
{ |
|
|
|
|
|
var info = MONITORINFOEX.Create(); |
|
|
|
|
|
var hMonitor = new HMONITOR(monitorHandler); |
|
|
|
|
|
PInvoke.GetMonitorInfo(hMonitor, (MONITORINFO*)&info); |
|
|
|
|
|
|
|
|
|
|
|
var deviceMode = new DEVMODEW |
|
|
|
|
|
{ |
|
|
|
|
|
dmFields = DEVMODE_FIELD_FLAGS.DM_DISPLAYORIENTATION | DEVMODE_FIELD_FLAGS.DM_DISPLAYFREQUENCY, |
|
|
|
|
|
dmSize = (ushort)Marshal.SizeOf<DEVMODEW>() |
|
|
|
|
|
}; |
|
|
|
|
|
PInvoke.EnumDisplaySettings(info.szDevice.ToString(), ENUM_DISPLAY_SETTINGS_MODE.ENUM_CURRENT_SETTINGS, |
|
|
|
|
|
ref deviceMode); |
|
|
|
|
|
|
|
|
|
|
|
var frequency = deviceMode.dmDisplayFrequency; |
|
|
|
|
|
|
|
|
|
|
|
dictionary[hMonitor] = frequency; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return dictionary; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
// Used the windows composition as a blueprint for this startup/creation
|
|
|
// Used the windows composition as a blueprint for this startup/creation
|
|
|
private static bool TryCreateAndRegisterCore() |
|
|
private static bool TryCreateAndRegisterCore() |
|
|
{ |
|
|
{ |
|
|
|