/ src / Ryujinx.Common / SystemInterop / GdiPlusHelper.cs
GdiPlusHelper.cs
 1  using System;
 2  using System.Runtime.InteropServices;
 3  using System.Runtime.Versioning;
 4  
 5  namespace Ryujinx.Common.SystemInterop
 6  {
 7      [SupportedOSPlatform("windows")]
 8      public static partial class GdiPlusHelper
 9      {
10          private const string LibraryName = "gdiplus.dll";
11  
12          private static readonly IntPtr _initToken;
13  
14          static GdiPlusHelper()
15          {
16              CheckStatus(GdiplusStartup(out _initToken, StartupInputEx.Default, out _));
17          }
18  
19          private static void CheckStatus(int gdiStatus)
20          {
21              if (gdiStatus != 0)
22              {
23                  throw new Exception($"GDI Status Error: {gdiStatus}");
24              }
25          }
26  
27          private struct StartupInputEx
28          {
29              public int GdiplusVersion;
30  
31  #pragma warning disable CS0649 // Field is never assigned to
32              public IntPtr DebugEventCallback;
33              public int SuppressBackgroundThread;
34              public int SuppressExternalCodecs;
35              public int StartupParameters;
36  #pragma warning restore CS0649
37  
38              public static StartupInputEx Default => new()
39              {
40                  // We assume Windows 8 and upper
41                  GdiplusVersion = 2,
42                  DebugEventCallback = IntPtr.Zero,
43                  SuppressBackgroundThread = 0,
44                  SuppressExternalCodecs = 0,
45                  StartupParameters = 0,
46              };
47          }
48  
49          private struct StartupOutput
50          {
51              public IntPtr NotificationHook;
52              public IntPtr NotificationUnhook;
53          }
54  
55          [LibraryImport(LibraryName)]
56          private static partial int GdiplusStartup(out IntPtr token, in StartupInputEx input, out StartupOutput output);
57  
58          [LibraryImport(LibraryName)]
59          private static partial int GdipCreateFromHWND(IntPtr hwnd, out IntPtr graphics);
60  
61          [LibraryImport(LibraryName)]
62          private static partial int GdipDeleteGraphics(IntPtr graphics);
63  
64          [LibraryImport(LibraryName)]
65          private static partial int GdipGetDpiX(IntPtr graphics, out float dpi);
66  
67          public static float GetDpiX(IntPtr hwnd)
68          {
69              CheckStatus(GdipCreateFromHWND(hwnd, out IntPtr graphicsHandle));
70              CheckStatus(GdipGetDpiX(graphicsHandle, out float result));
71              CheckStatus(GdipDeleteGraphics(graphicsHandle));
72  
73              return result;
74          }
75      }
76  }