diff --git a/src/Windows/Avalonia.Win32/DirectX/DxgiConnection.cs b/src/Windows/Avalonia.Win32/DirectX/DxgiConnection.cs
index 1482a5cc62..c1e77aab76 100644
--- a/src/Windows/Avalonia.Win32/DirectX/DxgiConnection.cs
+++ b/src/Windows/Avalonia.Win32/DirectX/DxgiConnection.cs
@@ -1,13 +1,20 @@
using System;
+using System.Collections.Generic;
using System.Diagnostics;
+using System.Runtime.InteropServices;
using System.Threading.Tasks;
using Avalonia.Logging;
using Avalonia.OpenGL.Egl;
using Avalonia.Rendering;
-using static Avalonia.Win32.Interop.UnmanagedMethods;
-using static Avalonia.Win32.DirectX.DirectXUnmanagedMethods;
+
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
{
internal unsafe class DxgiConnection : IRenderTimer, IWindowsSurfaceFactory
@@ -111,6 +118,8 @@ namespace Avalonia.Win32.DirectX
ushort adapterIndex = 0;
+ Dictionary monitorFrequencies = GetAllMonitorFrequencies();
+
// this looks odd, but that's just how one enumerates adapters in DXGI
while (fact.EnumAdapters(adapterIndex, &adapterPointer) == 0)
{
@@ -122,8 +131,12 @@ namespace Avalonia.Win32.DirectX
using var output = MicroComRuntime.CreateProxyFor(outputPointer, true);
DXGI_OUTPUT_DESC outputDesc = output.Desc;
- var screen = Win32Platform.Instance.Screen.ScreenFromHMonitor((IntPtr)outputDesc.Monitor.Value);
- var frequency = screen?.Frequency ?? highestRefreshRate;
+ var hMonitor = new HMONITOR(outputDesc.Monitor.Value);
+
+ var frequency =
+ monitorFrequencies.TryGetValue(hMonitor, out uint frequencyValue) ?
+ frequencyValue :
+ highestRefreshRate;
if (highestRefreshRate < frequency)
{
@@ -145,6 +158,33 @@ namespace Avalonia.Win32.DirectX
}
+ private unsafe Dictionary GetAllMonitorFrequencies()
+ {
+ var monitorHandlers = ScreenImpl.GetAllDisplayMonitorHandlers();
+ var dictionary = new Dictionary(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()
+ };
+ 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
private static bool TryCreateAndRegisterCore()
{
diff --git a/src/Windows/Avalonia.Win32/ScreenImpl.cs b/src/Windows/Avalonia.Win32/ScreenImpl.cs
index 0f73d39249..b4bff3da35 100644
--- a/src/Windows/Avalonia.Win32/ScreenImpl.cs
+++ b/src/Windows/Avalonia.Win32/ScreenImpl.cs
@@ -15,6 +15,11 @@ internal unsafe class ScreenImpl : ScreensBase
protected override int GetScreenCount() => GetSystemMetrics(SystemMetric.SM_CMONITORS);
protected override IReadOnlyList GetAllScreenKeys()
+ {
+ return GetAllDisplayMonitorHandlers();
+ }
+
+ public static List GetAllDisplayMonitorHandlers()
{
var screens = new List();
var gcHandle = GCHandle.Alloc(screens);