protected override void SetupInternal(Configurator config) { bool initSuccess = Glfw.Init(); if (!initSuccess) { Engine.Log.Error("Couldn't initialize glfw.", MessageSource.Glfw); return; } _errorCallback = ErrorCallback; Glfw.SetErrorCallback(_errorCallback); #if ANGLE LoadLibrary("libEGL"); LoadLibrary("libGLESv2"); Glfw.WindowHint(Glfw.Hint.ClientApi, Glfw.ClientApi.OpenGLES); Glfw.WindowHint(Glfw.Hint.ContextCreationApi, Glfw.ContextApi.EGL); Glfw.WindowHint(Glfw.Hint.ContextVersionMajor, 3); if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && Kernel32Methods.GetModuleHandle("renderdoc.dll") != IntPtr.Zero) { Glfw.WindowHint(Glfw.Hint.ContextVersionMinor, 1); } #endif if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { // Macs need a very specific context to be requested. Glfw.WindowHint(Glfw.Hint.ContextVersionMajor, 3); Glfw.WindowHint(Glfw.Hint.ContextVersionMinor, 2); Glfw.WindowHint(Glfw.Hint.OpenglForwardCompat, true); Glfw.WindowHint(Glfw.Hint.OpenglProfile, Glfw.OpenGLProfile.Core); } else { // Version set by the angle ifdef shouldn't be overwritten. #if !ANGLE Glfw.WindowHint(Glfw.Hint.ContextVersionMajor, 3); Glfw.WindowHint(Glfw.Hint.ContextVersionMinor, 3); Glfw.WindowHint(Glfw.Hint.OpenglForwardCompat, true); Glfw.WindowHint(Glfw.Hint.OpenglProfile, Glfw.OpenGLProfile.Core); #endif } Glfw.Window?win = Glfw.CreateWindow((int)config.HostSize.X, (int)config.HostSize.Y, config.HostTitle); if (win == null || win.Value.Ptr == IntPtr.Zero) { Engine.Log.Error("Couldn't create window.", MessageSource.Glfw); return; } _win = win.Value; Glfw.SetWindowSizeLimits(_win, (int)config.RenderSize.X, (int)config.RenderSize.Y, -1, -1); _focusCallback = FocusCallback; Glfw.SetWindowFocusCallback(_win, _focusCallback); _resizeCallback = ResizeCallback; Glfw.SetFramebufferSizeCallback(_win, _resizeCallback); Context = new GlfwGraphicsContext(_win); Context.MakeCurrent(); _keyInputCallback = KeyInput; Glfw.SetKeyCallback(_win, _keyInputCallback); _mouseButtonFunc = MouseButtonKeyInput; Glfw.SetMouseButtonCallback(_win, _mouseButtonFunc); _mouseScrollFunc = MouseScrollInput; Glfw.SetScrollCallback(_win, _mouseScrollFunc); void TextInputRedirect(Glfw.Window _, uint codePoint) { UpdateTextInput((char)codePoint); } _textInputCallback = TextInputRedirect; Glfw.SetCharCallback(_win, _textInputCallback); Glfw.Monitor[] monitors = Glfw.GetMonitors(); for (var i = 0; i < monitors.Length; i++) { Glfw.GetMonitorPos(monitors[i], out int x, out int y); Glfw.VideoMode videoMode = Glfw.GetVideoMode(monitors[i]); var mon = new GlfwMonitor(new Vector2(x, y), new Vector2(videoMode.Width, videoMode.Height)); UpdateMonitor(mon, true, i == 0); } FocusChanged(true); Glfw.FocusWindow(_win); #if OpenAL Audio = OpenALAudioAdapter.TryCreate(this) ?? (AudioContext) new NullAudioContext(); #else Audio = new NullAudioContext(); #endif }
/// <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; }