public void Init(IntPtr windowHandle, Win32Platform platform) { _platform = platform; // This is how you request a context version from MESA - lol // This needs to be pInvoked as Environment.SetEnvironmentVariable doesn't affect native getenv calls. _putenv_s("MESA_GL_VERSION_OVERRIDE", "3.3FC"); // Unload old OpenGL, if any. IntPtr loadedOpenGl = Kernel32.GetModuleHandle("opengl32.dll"); var counter = 0; if (loadedOpenGl != IntPtr.Zero) { Engine.Log.Info("OpenGL32.dll is already loaded. Attempting to unload...", MessageSource.WGallium); } while (loadedOpenGl != IntPtr.Zero) { Kernel32.FreeLibrary(loadedOpenGl); loadedOpenGl = Kernel32.GetModuleHandle("opengl32.dll"); counter++; if (counter < 100) { continue; } Engine.Log.Error("Couldn't unload the loaded OpenGL32.dll. Gallium context couldn't be created.", MessageSource.WGallium); return; } if (counter > 0) { Engine.Log.Info($"OpenGL32.dll was unloaded after {counter} attempts.", MessageSource.WGallium); } // Load library. _openGlLibrary = _platform.LoadLibrary("mesa"); if (_openGlLibrary == IntPtr.Zero) { Engine.Log.Error("Couldn't load mesa.", MessageSource.WGallium); return; } var createContext = _platform.GetFunctionByName <WglFunctions.WglCreateContext>(_openGlLibrary, "wglCreateContext"); _deleteContext = _platform.GetFunctionByName <WglFunctions.WglDeleteContext>(_openGlLibrary, "wglDeleteContext"); _getProcAddress = _platform.GetFunctionByName <WglFunctions.WglGetProcAddress>(_openGlLibrary, "wglGetProcAddress"); _makeCurrent = _platform.GetFunctionByName <WglFunctions.WglMakeCurrent>(_openGlLibrary, "wglMakeCurrent"); _swapIntervalExt = NativeHelpers.GetFunctionByPtr <WglFunctions.SwapInternalExt>(_getProcAddress("wglSwapIntervalEXT")); // Setup context. _dc = User32.GetDC(windowHandle); if (_dc == IntPtr.Zero) { Win32Platform.CheckError("WGL: Could not get window dc.", true); } int pixelFormatIdx = SupportedPixelFormat(_dc); if (pixelFormatIdx == 0) { return; } var pfd = new PixelFormatDescriptor(); pfd.NSize = (ushort)Marshal.SizeOf(pfd); if (Gdi32.DescribePixelFormat(_dc, pixelFormatIdx, (uint)sizeof(PixelFormatDescriptor), ref pfd) == 0) { Win32Platform.CheckError("WGL: Failed to retrieve PFD for the selected pixel format.", true); return; } if (!Gdi32.SetPixelFormat(_dc, pixelFormatIdx, ref pfd)) { Win32Platform.CheckError("WGL: Could not set pixel format.", true); } const string contextName = "Gallium-OpenGL"; _contextHandle = createContext(_dc); if (_contextHandle == IntPtr.Zero) { Win32Platform.CheckError(contextName, true); } Win32Platform.CheckError("Checking if context creation passed."); Engine.Log.Trace($"Requested {contextName} using pixel format id {pixelFormatIdx}", MessageSource.Win32); Valid = true; }
/// <summary> /// Initialize the conflict from the Windows window handle and platform reference. /// </summary> public void Init(IntPtr nativeDeviceHandle, IntPtr windowHandle, Win32Platform platform) { _platform = platform; // Load WGL. _openGlLibrary = _platform.LoadLibrary("opengl32.dll"); if (_openGlLibrary == IntPtr.Zero) { Engine.Log.Error("opengl32.dll not found.", MessageSource.WGallium); return; } var createContext = _platform.GetFunctionByName <WglFunctions.WglCreateContext>(_openGlLibrary, "wglCreateContext"); _deleteContext = _platform.GetFunctionByName <WglFunctions.WglDeleteContext>(_openGlLibrary, "wglDeleteContext"); _getProcAddress = _platform.GetFunctionByName <WglFunctions.WglGetProcAddress>(_openGlLibrary, "wglGetProcAddress"); _getCurrentDc = _platform.GetFunctionByName <WglFunctions.WglGetCurrentDc>(_openGlLibrary, "wglGetCurrentDC"); _getCurrentContext = _platform.GetFunctionByName <WglFunctions.WglGetCurrentContext>(_openGlLibrary, "wglGetCurrentContext"); _makeCurrent = _platform.GetFunctionByName <WglFunctions.WglMakeCurrent>(_openGlLibrary, "wglMakeCurrent"); // A dummy context has to be created for opengl32.dll to load the. OpenGL ICD, from which we can then query WGL extensions. // This code will accept the Microsoft GDI ICD; Debug.Assert(nativeDeviceHandle != IntPtr.Zero); var pfd = new PixelFormatDescriptor(); pfd.NSize = (ushort)Marshal.SizeOf(pfd); pfd.NVersion = 1; pfd.DwFlags = PixelFormatFlags.DrawToWindow | PixelFormatFlags.SupportOpenGl | PixelFormatFlags.DoubleBuffer; pfd.PixelType = (byte)PixelFormatFlags.RGBA; pfd.CColorBits = 24; if (!Gdi32.SetPixelFormat(nativeDeviceHandle, Gdi32.ChoosePixelFormat(nativeDeviceHandle, ref pfd), ref pfd)) { Win32Platform.CheckError("WGL: Could not set pixel format on dummy context.", true); } // Establish dummy context. IntPtr rc = createContext(nativeDeviceHandle); if (rc == IntPtr.Zero) { Win32Platform.CheckError("WGL: Could not create dummy context.", true); } if (!_makeCurrent(nativeDeviceHandle, rc)) { _deleteContext(rc); Win32Platform.CheckError("Could not make dummy context current.", true); return; } // Check supported version. KhronosVersion glGetString = Gl.QueryVersionExternal(GetProcAddress); if (glGetString != null) { if (glGetString.Major < 3) { _deleteContext(rc); Engine.Log.Error("Wgl support is lower than 3.0", MessageSource.Wgl); return; } } else { Engine.Log.Warning("Couldn't verify context version.", MessageSource.Wgl); } Engine.Log.Trace("Loaded functions.", MessageSource.Wgl); // Functions must be loaded first as they're needed to retrieve the extension string that tells us whether the functions are supported _getExtensionsStringExt = NativeHelpers.GetFunctionByPtr <WglFunctions.GetExtensionsStringExt>(_getProcAddress("wglGetExtensionsStringEXT")); _getExtensionsStringArb = NativeHelpers.GetFunctionByPtr <WglFunctions.GetExtensionsStringArb>(_getProcAddress("wglGetExtensionsStringARB")); _createContextAttribs = NativeHelpers.GetFunctionByPtr <WglFunctions.CreateContextAttribs>(_getProcAddress("wglCreateContextAttribsARB")); _swapIntervalExt = NativeHelpers.GetFunctionByPtr <WglFunctions.SwapInternalExt>(_getProcAddress("wglSwapIntervalEXT")); _getPixelFormatAttribivArb = NativeHelpers.GetFunctionByPtr <WglFunctions.GetPixelFormatAttributes>(_getProcAddress("wglGetPixelFormatAttribivARB")); WglGetSupportedExtensions(); _arbMultisample = WglSupportedExtension("WGL_ARB_multisample"); _arbFramebufferSRgb = WglSupportedExtension("WGL_ARB_framebuffer_sRGB"); _extFramebufferSRgb = WglSupportedExtension("WGL_EXT_framebuffer_sRGB"); _arbCreateContextProfile = WglSupportedExtension("WGL_ARB_create_context_profile"); _arbPixelFormat = WglSupportedExtension("WGL_ARB_pixel_format"); _autoVSyncExtension = WglSupportedExtension("WGL_EXT_swap_control_tear"); bool arbCreateContext = WglSupportedExtension("WGL_ARB_create_context"); // Dispose of dummy context. _deleteContext(rc); Engine.Log.Trace("Extensions loaded.", MessageSource.Wgl); // Start creating actual context. _dc = User32.GetDC(windowHandle); if (_dc == IntPtr.Zero) { Win32Platform.CheckError("WGL: Could not get window dc.", true); } int pixelFormatIdx = SupportedPixelFormat(_dc); if (pixelFormatIdx == 0) { return; } if (Gdi32.DescribePixelFormat(_dc, pixelFormatIdx, (uint)sizeof(PixelFormatDescriptor), ref pfd) == 0) { Win32Platform.CheckError("WGL: Failed to retrieve PFD for the selected pixel format.", true); return; } if (!Gdi32.SetPixelFormat(_dc, pixelFormatIdx, ref pfd)) { Win32Platform.CheckError("WGL: Could not set pixel format.", true); return; } Engine.Log.Trace($"Context ARB: {arbCreateContext}, Profile ARB: {_arbCreateContextProfile}", MessageSource.Wgl); if (arbCreateContext) { // Context configurations to try. var contextFactory = new List <GLContextDescription>(2) { new GLContextDescription { Profile = GLProfile.Core, Debug = Engine.Configuration.GlDebugMode }, new GLContextDescription { Profile = GLProfile.Any } }; for (var i = 0; i < contextFactory.Count; i++) { GLContextDescription current = contextFactory[i]; IntPtr handle = CreateContextArb(current); if (handle == IntPtr.Zero) { continue; } _contextHandle = handle; Engine.Log.Info($"Created WGL context - {current}", MessageSource.Wgl); break; } // If that failed too, look for errors. // Fallback to legacy creation. if (_contextHandle == IntPtr.Zero) { Win32Platform.CheckError("Creating WGL context"); } } if (_contextHandle == IntPtr.Zero) { _contextHandle = createContext(_dc); if (_contextHandle == IntPtr.Zero) { Win32Platform.CheckError("Creating WGL legacy context", true); } Engine.Log.Info("WGL legacy context created.", MessageSource.Wgl); } Win32Platform.CheckError("Checking if context creation passed."); Valid = true; }