/// <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; }
private IntPtr CreateContextArb(GLContextDescription contextDescription) { WglContextFlags mask = 0; WglContextFlags flags = 0; var attributes = new List <int>(); if (contextDescription.Major != 1) { attributes.Add((int)WglContextAttributes.MajorVersionArb); attributes.Add(contextDescription.Major); } if (contextDescription.Major != 1 && contextDescription.Minor != 0) { attributes.Add((int)WglContextAttributes.MinorVersionArb); attributes.Add(contextDescription.Minor); } // ArbCreateContextProfile is required to set a profile if (_arbCreateContextProfile && contextDescription.Profile != GLProfile.Any) { if (contextDescription.Profile == GLProfile.Core) { mask |= WglContextFlags.CoreProfileBitArb; } else { mask |= WglContextFlags.CompatibilityProfileBitArb; } } if (contextDescription.Debug) { flags |= WglContextFlags.DebugBitArb; } if (contextDescription.ForwardCompat) { flags |= WglContextFlags.ForwardCompatibleBitArb; } // Add flags and mask if any. (there mostly isn't) // Context creation in Wgl is mostly default and trusts(tm) the other side. if (flags != 0) { attributes.Add((int)WglContextAttributes.FlagsArb); attributes.Add((int)flags); } if (mask != 0) { attributes.Add((int)WglContextAttributes.ProfileMaskArb); attributes.Add((int)mask); } attributes.Add(0); IntPtr handle; int[] attArr = attributes.ToArray(); fixed(int *attPtr = &attArr[0]) { handle = _createContextAttribs(_dc, IntPtr.Zero, attPtr); } return(handle); }