protected override void MakeCurrent() { // Waits until window reference is known SpinWait.SpinUntil(() => _window != null); // Makes context current on calling thread Glfw.MakeContextCurrent(_window.Handle); // Configure swap interval Glfw.SetSwapInterval(_vsync ? 1 : 0); // Enable quality MSAA if (Screen.Surface.Multisample > MultisampleQuality.None) { // Load glMinSampleShading, this could be cached... but this way makes it pretty // seamless to include. var glMinSampleShader = LoadFunction <MinSampleShading>("glMinSampleShading"); // Enable multisampling explicity. From what I've read this is // should already be enabled but I thought it good to enable it myself. GL.Enable((EnableCap)0x809D); // GL_MULTISAMPLE // If we are running a version that can support sample shading // enable it and set the rate to 100%. This allows multisampling // to affect every pixel instead of just the geometry edges. if (glMinSampleShader != null) { GL.Enable((EnableCap)0x8C36); // GL_SAMPLE_SHADING glMinSampleShader(1F); } } }
private static void InitializeGraphicsAdapter() { // Set GLFW hints to use OpenGL 3.2 core (forward compatible) // We are assuming OpenGL is the only implementation relevant here. Sorry Vulkan! // In the future if a Vulkan implementation is introduced to Heirloom, we will have to rewrite this // initialization procedure. Glfw.SetWindowCreationHint(WindowAttribute.ClientApi, (int)ClientApi.OpenGL); Glfw.SetWindowCreationHint(WindowAttribute.OpenGLProfile, (int)OpenGLProfile.Core); Glfw.SetWindowCreationHint(WindowAttribute.OpenGLForwardCompatibility, true); Glfw.SetWindowCreationHint(WindowAttribute.ContextVersionMajor, 3); Glfw.SetWindowCreationHint(WindowAttribute.ContextVersionMinor, 2); // Creates the "sharing window" that is permanently hidden to the user. // It is used to query window capabilities and assist with sharing OpenGL resources. // It is also used when shaders or other OpenGL resources that need to be created // on an OGL bound thread but do not have a clear context available to them. Glfw.SetWindowCreationHint(WindowAttribute.TransparentFramebuffer, true); Glfw.SetWindowCreationHint(WindowAttribute.Visible, false); ShareContext = Glfw.CreateWindow(256, 256, "GLFW Background Window"); // Use share context temporarily to load the GL functions and construct the graphics adapter object... Glfw.MakeContextCurrent(ShareContext); { // Loads the GL functions via GLFW lookup GL.LoadFunctions(Glfw.GetProcAddress); // On the desktop we actually use GL 3.2, but the implementation is limited to GLES 3.0 features. // This is to help make a uniform implementation for supportd on mobile platforms. This however, // does allow the user to create incompatible shaders between platforms. As mobile is currently not // a supported project, this is not yet a concern. GraphicsAdapter = new OpenGLWindowGraphicsAdapter(); GraphicsFactory = GraphicsAdapter as IWindowGraphicsFactory; GraphicsAdapter.Initialize(); } Glfw.MakeContextCurrent(WindowHandle.None); // Reset default window creation hints Glfw.SetWindowCreationHint(WindowAttribute.FocusOnShow, true); Glfw.SetWindowCreationHint(WindowAttribute.Visible, true); }
protected internal override void Invoke(Action function) { if (Adapter?.IsDisposed ?? false) { Log.Error("Unable to schedule action on GL thread. Adapter has been disposed."); } lock (_graphics) { // Try to invoke on an existing graphics thread foreach (var gfx in _graphics) { // If graphics context is still initialized... if (gfx.IsInitialized) { // Invoke action on that thread and exit gfx.Invoke(function); return; } } } // Was unable to invoke on a graphics thread, so we will temporarily make the window // events thread a graphics thread to invoke the function. Application.Invoke(() => { // Make the share context current here Glfw.MakeContextCurrent(Application.ShareContext); // Execute function and keep return value function(); // Release context from thread. We want it not associated with any thread. Glfw.MakeContextCurrent(WindowHandle.None); }); }