diff --git a/CHANGELOG.md b/CHANGELOG.md index d5e83c8a3d..7383f37627 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ - `Config` doesn't force OpenGL `Api` by default. - `Display::create_context` now uses the most recent available `Api` from the `Config` when `ContextApi` is not specified in `ContextAttributes`. +- `PossiblyCurrentGlContext::get_proc_address` method was moved to `GlDisplay::get_proc_address`. # Version 0.30.0-beta.2 (2022-09-03) diff --git a/glutin/src/api/cgl/context.rs b/glutin/src/api/cgl/context.rs index 1d91a5512c..5aa8e74c25 100644 --- a/glutin/src/api/cgl/context.rs +++ b/glutin/src/api/cgl/context.rs @@ -1,6 +1,5 @@ //! Everything related to `NSOpenGLContext`. -use std::ffi::{self, CStr}; use std::fmt; use std::marker::PhantomData; use std::ops::Deref; @@ -8,9 +7,7 @@ use std::ops::Deref; use cgl::CGLSetParameter; use cocoa::appkit::{NSOpenGLContext, NSOpenGLContextParameter}; use cocoa::base::{id, nil}; -use core_foundation::base::TCFType; -use core_foundation::bundle::{CFBundleGetBundleWithIdentifier, CFBundleGetFunctionPointerForName}; -use core_foundation::string::CFString; + use objc::rc::autoreleasepool; use objc::runtime::{BOOL, NO}; @@ -158,15 +155,6 @@ impl PossiblyCurrentGlContext for PossiblyCurrentContext { } }) } - - fn get_proc_address(&self, addr: &CStr) -> *const ffi::c_void { - let symbol_name = CFString::new(addr.to_str().unwrap()); - let framework_name = CFString::new("com.apple.opengl"); - unsafe { - let framework = CFBundleGetBundleWithIdentifier(framework_name.as_concrete_TypeRef()); - CFBundleGetFunctionPointerForName(framework, symbol_name.as_concrete_TypeRef()).cast() - } - } } impl PossiblyCurrentContextGlSurfaceAccessor for PossiblyCurrentContext { diff --git a/glutin/src/api/cgl/display.rs b/glutin/src/api/cgl/display.rs index 73dae4e02d..210a0d01a2 100644 --- a/glutin/src/api/cgl/display.rs +++ b/glutin/src/api/cgl/display.rs @@ -1,7 +1,11 @@ //! A CGL display. +use std::ffi::{self, CStr}; use std::marker::PhantomData; +use core_foundation::base::TCFType; +use core_foundation::bundle::{CFBundleGetBundleWithIdentifier, CFBundleGetFunctionPointerForName}; +use core_foundation::string::CFString; use raw_window_handle::RawDisplayHandle; use crate::config::ConfigTemplate; @@ -81,6 +85,15 @@ impl GlDisplay for Display { ) -> Result { unsafe { Self::create_pixmap_surface(self, config, surface_attributes) } } + + fn get_proc_address(&self, addr: &CStr) -> *const ffi::c_void { + let symbol_name = CFString::new(addr.to_str().unwrap()); + let framework_name = CFString::new("com.apple.opengl"); + unsafe { + let framework = CFBundleGetBundleWithIdentifier(framework_name.as_concrete_TypeRef()); + CFBundleGetFunctionPointerForName(framework, symbol_name.as_concrete_TypeRef()).cast() + } + } } impl AsRawDisplay for Display { diff --git a/glutin/src/api/egl/context.rs b/glutin/src/api/egl/context.rs index 49d74f12a6..50555f3898 100644 --- a/glutin/src/api/egl/context.rs +++ b/glutin/src/api/egl/context.rs @@ -1,6 +1,5 @@ //! Everything related to `EGLContext` management. -use std::ffi::{self, CStr}; use std::fmt; use std::marker::PhantomData; use std::ops::Deref; @@ -228,10 +227,6 @@ impl PossiblyCurrentGlContext for PossiblyCurrentContext { self.inner.display.inner.egl.GetCurrentContext() == *self.inner.raw } } - - fn get_proc_address(&self, addr: &CStr) -> *const ffi::c_void { - unsafe { self.inner.display.inner.egl.GetProcAddress(addr.as_ptr()) as *const _ } - } } impl PossiblyCurrentContextGlSurfaceAccessor for PossiblyCurrentContext { diff --git a/glutin/src/api/egl/display.rs b/glutin/src/api/egl/display.rs index bb4530cd49..a529c724be 100644 --- a/glutin/src/api/egl/display.rs +++ b/glutin/src/api/egl/display.rs @@ -1,7 +1,7 @@ //! Everything related to `EGLDisplay`. use std::collections::HashSet; -use std::ffi::CStr; +use std::ffi::{self, CStr}; use std::fmt; use std::ops::Deref; use std::sync::Arc; @@ -271,6 +271,10 @@ impl GlDisplay for Display { ) -> Result { unsafe { Self::create_pixmap_surface(self, config, surface_attributes) } } + + fn get_proc_address(&self, addr: &CStr) -> *const ffi::c_void { + unsafe { self.inner.egl.GetProcAddress(addr.as_ptr()) as *const _ } + } } impl AsRawDisplay for Display { diff --git a/glutin/src/api/glx/context.rs b/glutin/src/api/glx/context.rs index 0f0b777d62..cd4f2b583d 100644 --- a/glutin/src/api/glx/context.rs +++ b/glutin/src/api/glx/context.rs @@ -1,6 +1,5 @@ //! Everything related to `GLXContext`. -use std::ffi::{self, CStr}; use std::fmt; use std::marker::PhantomData; use std::ops::Deref; @@ -296,12 +295,6 @@ impl PossiblyCurrentGlContext for PossiblyCurrentContext { fn is_current(&self) -> bool { unsafe { self.inner.display.inner.glx.GetCurrentContext() == *self.inner.raw } } - - fn get_proc_address(&self, addr: &CStr) -> *const ffi::c_void { - unsafe { - self.inner.display.inner.glx.GetProcAddress(addr.as_ptr() as *const _) as *const _ - } - } } impl PossiblyCurrentContextGlSurfaceAccessor for PossiblyCurrentContext { diff --git a/glutin/src/api/glx/display.rs b/glutin/src/api/glx/display.rs index 4581baa622..6b7b822a26 100644 --- a/glutin/src/api/glx/display.rs +++ b/glutin/src/api/glx/display.rs @@ -1,7 +1,7 @@ //! GLX object creation. use std::collections::HashSet; -use std::ffi::CStr; +use std::ffi::{self, CStr}; use std::fmt; use std::ops::Deref; use std::sync::atomic::Ordering; @@ -153,6 +153,10 @@ impl GlDisplay for Display { ) -> Result { unsafe { Self::create_pixmap_surface(self, config, surface_attributes) } } + + fn get_proc_address(&self, addr: &CStr) -> *const ffi::c_void { + unsafe { self.inner.glx.GetProcAddress(addr.as_ptr() as *const _) as *const _ } + } } impl AsRawDisplay for Display { diff --git a/glutin/src/api/wgl/context.rs b/glutin/src/api/wgl/context.rs index 93403e24d5..aba8fd9e2c 100644 --- a/glutin/src/api/wgl/context.rs +++ b/glutin/src/api/wgl/context.rs @@ -1,6 +1,5 @@ //! WGL context handling. -use std::ffi::{self, CStr}; use std::fmt; use std::io::Error as IoError; use std::marker::PhantomData; @@ -11,7 +10,6 @@ use glutin_wgl_sys::wgl::types::HGLRC; use glutin_wgl_sys::{wgl, wgl_extra}; use raw_window_handle::RawWindowHandle; use windows_sys::Win32::Graphics::Gdi::{self as gdi, HDC}; -use windows_sys::Win32::System::LibraryLoader as dll_loader; use crate::config::GetGlConfig; use crate::context::{ @@ -293,19 +291,6 @@ impl PossiblyCurrentGlContext for PossiblyCurrentContext { fn is_current(&self) -> bool { unsafe { wgl::GetCurrentContext() == *self.inner.raw } } - - fn get_proc_address(&self, addr: &CStr) -> *const ffi::c_void { - unsafe { - let addr = addr.as_ptr(); - let fn_ptr = wgl::GetProcAddress(addr); - if !fn_ptr.is_null() { - fn_ptr.cast() - } else { - dll_loader::GetProcAddress(self.inner.display.inner.lib_opengl32, addr.cast()) - .map_or(std::ptr::null(), |fn_ptr| fn_ptr as *const _) - } - } - } } impl NotCurrentGlContext for NotCurrentContext { diff --git a/glutin/src/api/wgl/display.rs b/glutin/src/api/wgl/display.rs index 1e5e6a4591..6bea98a755 100644 --- a/glutin/src/api/wgl/display.rs +++ b/glutin/src/api/wgl/display.rs @@ -1,11 +1,12 @@ //! WGL display initialization and extension loading. use std::collections::HashSet; -use std::ffi::{CStr, OsStr}; +use std::ffi::{self, CStr, OsStr}; use std::fmt; use std::os::windows::ffi::OsStrExt; use std::sync::Arc; +use glutin_wgl_sys::wgl; use raw_window_handle::{RawDisplayHandle, RawWindowHandle}; use windows_sys::Win32::Foundation::HINSTANCE; use windows_sys::Win32::Graphics::Gdi::HDC; @@ -117,6 +118,19 @@ impl GlDisplay for Display { ) -> Result { unsafe { Self::create_pixmap_surface(self, config, surface_attributes) } } + + fn get_proc_address(&self, addr: &CStr) -> *const ffi::c_void { + unsafe { + let addr = addr.as_ptr(); + let fn_ptr = wgl::GetProcAddress(addr); + if !fn_ptr.is_null() { + fn_ptr.cast() + } else { + dll_loader::GetProcAddress(self.inner.lib_opengl32, addr.cast()) + .map_or(std::ptr::null(), |fn_ptr| fn_ptr as *const _) + } + } + } } impl AsRawDisplay for Display { diff --git a/glutin/src/context.rs b/glutin/src/context.rs index e49273d116..f0ff72a85e 100644 --- a/glutin/src/context.rs +++ b/glutin/src/context.rs @@ -1,7 +1,7 @@ //! OpenGL context creation and initialization. #![allow(unreachable_patterns)] -use std::ffi::{self, CStr}; +use std::ffi::{self}; use raw_window_handle::RawWindowHandle; @@ -77,10 +77,6 @@ pub trait PossiblyCurrentGlContext: Sealed { /// [`Self::NotCurrentContext`] to indicate that the context is a not /// current to allow sending it to the different thread. fn make_not_current(self) -> Result; - - /// Returns the address of an OpenGL function. The context must be current - /// when doing so. - fn get_proc_address(&self, addr: &CStr) -> *const ffi::c_void; } /// A trait that splits the methods accessing [`crate::surface::Surface`]. @@ -506,10 +502,6 @@ impl PossiblyCurrentGlContext for PossiblyCurrentContext { gl_api_dispatch!(self; Self(context) => context.make_not_current()?; as NotCurrentContext), ) } - - fn get_proc_address(&self, addr: &CStr) -> *const ffi::c_void { - gl_api_dispatch!(self; Self(context) => context.get_proc_address(addr)) - } } impl PossiblyCurrentContextGlSurfaceAccessor for PossiblyCurrentContext { diff --git a/glutin/src/display.rs b/glutin/src/display.rs index 5a3d677329..027fad397d 100644 --- a/glutin/src/display.rs +++ b/glutin/src/display.rs @@ -1,6 +1,7 @@ //! The OpenGL platform display selection and creation. #![allow(unreachable_patterns)] +use std::ffi::{self, CStr}; use std::fmt; use raw_window_handle::RawDisplayHandle; @@ -102,6 +103,15 @@ pub trait GlDisplay: Sealed { config: &Self::Config, surface_attributes: &SurfaceAttributes, ) -> Result; + + /// Return the address of an OpenGL function. + /// + /// # Api-specific + /// + /// **WGL:** - To load all the functions you must have a current context on + /// the calling thread, otherwise only limited set of functions will be + /// loaded. + fn get_proc_address(&self, addr: &CStr) -> *const ffi::c_void; } /// Get the [`Display`]. @@ -350,6 +360,10 @@ impl GlDisplay for Display { _ => unreachable!(), } } + + fn get_proc_address(&self, addr: &CStr) -> *const ffi::c_void { + gl_api_dispatch!(self; Self(display) => display.get_proc_address(addr)) + } } impl AsRawDisplay for Display { diff --git a/glutin_examples/examples/window.rs b/glutin_examples/examples/window.rs index 0b09a8afea..d8a4513d3a 100644 --- a/glutin_examples/examples/window.rs +++ b/glutin_examples/examples/window.rs @@ -48,9 +48,12 @@ fn main() { // Make it current and load symbols. let gl_context = gl_context.make_current(&gl_window.surface).unwrap(); + // WGL requires current context on the calling thread to load symbols properly, + // so the call here is for portability reasons. In case you don't target WGL + // you can call it right after display creation. gl::load_with(|symbol| { let symbol = CString::new(symbol).unwrap(); - gl_context.get_proc_address(symbol.as_c_str()) as *const _ + gl_display.get_proc_address(symbol.as_c_str()) as *const _ }); // Try setting vsync.