/// <inheritdoc /> protected override void SetupPlatform(Configurator config) { // todo: load libraries - if any // probably XInput // Initialize audio - Try to create WasApi - otherwise return the fake context so execution can go on. Audio = WasApiAudioContext.TryCreate() ?? (AudioContext) new NullAudioContext(); Engine.Log.Trace("Audio init complete.", MessageSource.Win32); PopulateKeyNames(); if (IsWindows10CreatorsUpdateOrGreaterWin32) { User32.SetProcessDpiAwarenessContext(DpiAwarenessContext.DpiAwarenessContextPerMonitorAwareV2); } else if (IsWindows81OrGreater) { User32.SetProcessDpiAwareness(ProcessDpiAwareness.ProcessPerMonitorDpiAware); } else { User32.SetProcessDPIAware(); } RegisterWindowClass(); CreateHelperWindow(); PollMonitors(); Engine.Log.Trace("Platform init complete.", MessageSource.Win32); var windowInitialSize = new Rect { Right = (int)config.HostSize.X, Bottom = (int)config.HostSize.Y }; Win32Window.GetFullWindowRect(Win32Window.DEFAULT_WINDOW_STYLE, Win32Window.DEFAULT_WINDOW_STYLE_EX, DEFAULT_DPI, ref windowInitialSize); int initialWidth = windowInitialSize.Right - windowInitialSize.Left; int initialHeight = windowInitialSize.Bottom - windowInitialSize.Top; IntPtr handle = User32.CreateWindowEx( Win32Window.DEFAULT_WINDOW_STYLE_EX, CLASS_NAME, config.HostTitle, Win32Window.DEFAULT_WINDOW_STYLE, (int)CreateWindowFlags.CW_USEDEFAULT, (int)CreateWindowFlags.CW_USEDEFAULT, // Position - default initialWidth, initialHeight, // Size - initial IntPtr.Zero, // No parent window IntPtr.Zero, // No window menu Kernel32.GetModuleHandle(null), IntPtr.Zero ); if (handle == IntPtr.Zero) { CheckError("Couldn't create window.", true); return; } Engine.Log.Trace("Window created.", MessageSource.Win32); // Create graphics context - OpenGL. GraphicsContext context = null; try { var wgl = new WglGraphicsContext(); wgl.Init(handle, this); if (wgl.Valid) { context = wgl; } } catch (Exception ex) { Engine.Log.Warning($"Couldn't create WGL context, falling back to MESA if possible.\n{ex}", MessageSource.Win32); } if (context == null) { try { var gallium = new GalliumGraphicsContext(); gallium.Init(handle, this); if (gallium.Valid) { context = gallium; } } catch (Exception ex) { Engine.SubmitError(new Exception("Couldn't create MESA context.", ex)); } } if (context == null) { Engine.SubmitError(new Exception("Couldn't create graphics context!")); return; } // Create Emotion representation of the window. var windowInstance = new Win32Window(handle, context, this); // Adjust window size to account for DPI scaling of the window frame and optionally DPI scaling of the content area. // This cannot be done until we know what monitor it was placed on - so it's done post creation. var rect = new Rect { Right = (int)config.HostSize.X, Bottom = (int)config.HostSize.Y }; rect.ClientToScreen(windowInstance.Handle); windowInstance.GetFullWindowRect(ref rect); User32.SetWindowPos(windowInstance.Handle, IntPtr.Zero, rect.Left, rect.Top, rect.Right - rect.Left, rect.Bottom - rect.Top, WindowPositionFlags.SWP_NOACTIVATE | WindowPositionFlags.SWP_NOZORDER); Window = windowInstance; }
/// <inheritdoc /> protected override void SetupInternal(Configurator config) { IsWindows7OrGreater = IsWindowsVersionOrGreaterWin32( NativeHelpers.HiByte((ushort)NtDll.WinVer.Win32WinNTWin7), NativeHelpers.LoByte((ushort)NtDll.WinVer.Win32WinNTWin7), 0); IsWindows8OrGreater = IsWindowsVersionOrGreaterWin32( NativeHelpers.HiByte((ushort)NtDll.WinVer.Win32WinNTWin8), NativeHelpers.LoByte((ushort)NtDll.WinVer.Win32WinNTWin8), 0); IsWindows81OrGreater = IsWindowsVersionOrGreaterWin32( NativeHelpers.HiByte((ushort)NtDll.WinVer.Win32WinNTWinBlue), NativeHelpers.LoByte((ushort)NtDll.WinVer.Win32WinNTWinBlue), 0); IsWindows10AnniversaryUpdateOrGreaterWin32 = IsWindows10BuildOrGreaterWin32(14393); IsWindows10CreatorsUpdateOrGreaterWin32 = IsWindows10BuildOrGreaterWin32(15063); var windowsVersionFlags = new List <string>(); if (IsWindows7OrGreater) { windowsVersionFlags.Add(nameof(IsWindows7OrGreater)); } if (IsWindows8OrGreater) { windowsVersionFlags.Add(nameof(IsWindows8OrGreater)); } if (IsWindows81OrGreater) { windowsVersionFlags.Add(nameof(IsWindows81OrGreater)); } if (IsWindows10AnniversaryUpdateOrGreaterWin32) { windowsVersionFlags.Add(nameof(IsWindows10AnniversaryUpdateOrGreaterWin32)); } if (IsWindows10CreatorsUpdateOrGreaterWin32) { windowsVersionFlags.Add(nameof(IsWindows10CreatorsUpdateOrGreaterWin32)); } Engine.Log.Trace(string.Join(", ", windowsVersionFlags), MessageSource.Win32); if (IsWindows10CreatorsUpdateOrGreaterWin32) { User32.SetProcessDpiAwarenessContext(DpiAwarenessContext.DpiAwarenessContextPerMonitorAwareV2); } else if (IsWindows81OrGreater) { User32.SetProcessDpiAwareness(ProcessDpiAwareness.ProcessPerMonitorDpiAware); } else { User32.SetProcessDPIAware(); } // todo: load libraries - if any, probably XInput? // Initialize audio. AudioContext ctx = null; #if OpenAL ctx ??= OpenALAudioAdapter.TryCreate(this); #endif ctx ??= WasApiAudioContext.TryCreate(this); ctx ??= new NullAudioContext(); Audio = ctx; Engine.Log.Trace("Audio init complete.", MessageSource.Win32); PopulateKeyCodes(); RegisterWindowClass(); CreateHelperWindow(); PollMonitors(); Engine.Log.Trace("Platform helpers created.", MessageSource.Win32); var windowInitialSize = new Rect { Right = (int)config.HostSize.X, Bottom = (int)config.HostSize.Y }; GetFullWindowRect(DEFAULT_WINDOW_STYLE, DEFAULT_WINDOW_STYLE_EX, DEFAULT_DPI, ref windowInitialSize); int initialWidth = windowInitialSize.Right - windowInitialSize.Left; int initialHeight = windowInitialSize.Bottom - windowInitialSize.Top; WindowStyles windowStyle = DEFAULT_WINDOW_STYLE; if (config.HiddenWindow) { windowStyle &= ~WindowStyles.WS_VISIBLE; windowStyle &= ~WindowStyles.WS_MINIMIZE; // This will override the hide otherwise config.InitialDisplayMode = DisplayMode.Initial; } IntPtr windowHandle = User32.CreateWindowEx( DEFAULT_WINDOW_STYLE_EX, CLASS_NAME, config.HostTitle, windowStyle, (int)CreateWindowFlags.CW_USEDEFAULT, (int)CreateWindowFlags.CW_USEDEFAULT, // Position - default initialWidth, initialHeight, // Size - initial IntPtr.Zero, // No parent window IntPtr.Zero, // No window menu Kernel32.GetModuleHandle(null), IntPtr.Zero ); if (windowHandle == IntPtr.Zero) { CheckError("Couldn't create window.", true); return; } Engine.Log.Trace("Window created.", MessageSource.Win32); string[] args = Environment.GetCommandLineArgs(); bool forceAngle = CommandLineParser.FindArgument(args, "angle", out string _); bool forceMesa = CommandLineParser.FindArgument(args, "software", out string _); // Create graphics context. if (!forceAngle && !forceMesa) { try { var wgl = new WglGraphicsContext(); wgl.Init(User32.GetDC(_helperWindowHandle), windowHandle, this); if (wgl.Valid) { Context = wgl; } } catch (Exception ex) { Engine.Log.Warning($"Couldn't create WGL context, falling back if possible.\n{ex}", MessageSource.Win32); } } #if ANGLE if (Context == null && !forceMesa) { try { var egl = new EglGraphicsContext(); egl.Init(User32.GetDC(windowHandle), windowHandle, this); if (egl.Valid) { Context = egl; } } catch (Exception ex) { Engine.Log.Warning($"Couldn't create EGL context, falling back if possible.\n{ex}", MessageSource.Win32); } } #endif if (Context == null) { try { var gallium = new GalliumGraphicsContext(); gallium.Init(windowHandle, this); if (gallium.Valid) { Context = gallium; } } catch (Exception ex) { Engine.CriticalError(new Exception("Couldn't create MESA context.", ex)); } } if (Context == null) { Engine.CriticalError(new Exception("Couldn't create graphics context!")); return; } // Adjust window size to account for DPI scaling of the window frame and optionally DPI scaling of the content area. // This cannot be done until we know what monitor it was placed on - so it's done post creation. var rect = new Rect { Right = (int)config.HostSize.X, Bottom = (int)config.HostSize.Y }; rect.ClientToScreen(windowHandle); GetFullWindowRect(ref rect); User32.SetWindowPos(_windowHandle, IntPtr.Zero, rect.Left, rect.Top, rect.Right - rect.Left, rect.Bottom - rect.Top, WindowPositionFlags.SWP_NOACTIVATE | WindowPositionFlags.SWP_NOZORDER); _windowHandle = windowHandle; }