From e918031201924f3fe262da04098df45702488bbb Mon Sep 17 00:00:00 2001 From: Zoxc Date: Fri, 20 Oct 2023 21:45:43 +0200 Subject: [PATCH] Use the device OpenGL context for WGL surfaces (#4271) --- wgpu-hal/src/gles/wgl.rs | 166 ++++++++++++--------------------------- 1 file changed, 52 insertions(+), 114 deletions(-) diff --git a/wgpu-hal/src/gles/wgl.rs b/wgpu-hal/src/gles/wgl.rs index 4d17b07c3..d46665c18 100644 --- a/wgpu-hal/src/gles/wgl.rs +++ b/wgpu-hal/src/gles/wgl.rs @@ -26,9 +26,9 @@ use winapi::{ libloaderapi::{GetModuleHandleA, GetProcAddress, LoadLibraryA}, wingdi::{ wglCreateContext, wglDeleteContext, wglGetCurrentContext, wglGetProcAddress, - wglMakeCurrent, wglShareLists, ChoosePixelFormat, DescribePixelFormat, GetPixelFormat, - SetPixelFormat, SwapBuffers, PFD_DOUBLEBUFFER, PFD_DRAW_TO_WINDOW, PFD_SUPPORT_OPENGL, - PFD_TYPE_RGBA, PIXELFORMATDESCRIPTOR, + wglMakeCurrent, ChoosePixelFormat, DescribePixelFormat, GetPixelFormat, SetPixelFormat, + SwapBuffers, PFD_DOUBLEBUFFER, PFD_DRAW_TO_WINDOW, PFD_SUPPORT_OPENGL, PFD_TYPE_RGBA, + PIXELFORMATDESCRIPTOR, }, winuser::{ CreateWindowExA, DefWindowProcA, GetDC, RegisterClassExA, ReleaseDC, CS_OWNDC, @@ -133,7 +133,6 @@ unsafe impl Send for WglContext {} unsafe impl Sync for WglContext {} struct Inner { - opengl_module: HMODULE, gl: glow::Context, device: HDC, context: WglContext, @@ -421,7 +420,6 @@ impl crate::Instance for Instance { Ok(Instance { inner: Arc::new(Mutex::new(Inner { device: dc, - opengl_module, gl, context, })), @@ -476,12 +474,12 @@ impl Drop for DeviceContextHandle { } pub struct Swapchain { - surface_context: WglContext, - surface_gl: glow::Context, framebuffer: glow::Framebuffer, renderbuffer: glow::Renderbuffer, + /// Extent because the window lies extent: wgt::Extent3d, + format: wgt::TextureFormat, format_desc: super::TextureFormatDesc, #[allow(unused)] @@ -520,17 +518,19 @@ impl Surface { window: self.window, }; - // Hold the lock for the shared context as we're using resources from there. - let _inner = context.inner.lock(); + let inner = context.inner.lock(); - if let Err(e) = sc.surface_context.make_current(dc.device) { - log::error!("unable to make the surface OpenGL context current: {e}",); + if let Err(e) = inner.context.make_current(dc.device) { + log::error!("unable to make the OpenGL context current for surface: {e}",); return Err(crate::SurfaceError::Other( - "unable to make the surface OpenGL context current", + "unable to make the OpenGL context current for surface", )); } - let gl = &sc.surface_gl; + let gl = &inner.gl; + + unsafe { gl.bind_framebuffer(glow::DRAW_FRAMEBUFFER, None) }; + unsafe { gl.bind_framebuffer(glow::READ_FRAMEBUFFER, Some(sc.framebuffer)) }; // Note the Y-flipping here. GL's presentation is not flipped, // but main rendering is. Therefore, we Y-flip the output positions @@ -550,6 +550,9 @@ impl Surface { ) }; + unsafe { gl.bind_renderbuffer(glow::RENDERBUFFER, None) }; + unsafe { gl.bind_framebuffer(glow::READ_FRAMEBUFFER, None) }; + if unsafe { SwapBuffers(dc.device) } == FALSE { log::error!("unable to swap buffers: {}", Error::last_os_error()); return Err(crate::SurfaceError::Other("unable to swap buffers")); @@ -572,33 +575,6 @@ impl crate::Surface for Surface { // Remove the old configuration. unsafe { self.unconfigure(device) }; - let format_desc = device.shared.describe_texture_format(config.format); - let inner = &device.shared.context.inner.lock(); - - if let Err(e) = inner.context.make_current(inner.device) { - log::error!("unable to make the shared OpenGL context current: {e}",); - return Err(crate::SurfaceError::Other( - "unable to make the shared OpenGL context current", - )); - } - - let gl = &inner.gl; - let renderbuffer = unsafe { gl.create_renderbuffer() }.map_err(|error| { - log::error!("Internal swapchain renderbuffer creation failed: {error}"); - crate::DeviceError::OutOfMemory - })?; - unsafe { gl.bind_renderbuffer(glow::RENDERBUFFER, Some(renderbuffer)) }; - unsafe { - gl.renderbuffer_storage( - glow::RENDERBUFFER, - format_desc.internal, - config.extent.width as _, - config.extent.height as _, - ) - }; - - // Create the swap chain OpenGL context - let dc = unsafe { GetDC(self.window) }; if dc.is_null() { log::error!( @@ -621,35 +597,48 @@ impl crate::Surface for Surface { )); } - let context = unsafe { wglCreateContext(dc.device) }; - if context.is_null() { - log::error!( - "unable to create surface OpenGL context: {}", - Error::last_os_error() - ); - return Err(crate::SurfaceError::Other( - "unable to create surface OpenGL context", - )); - } - let surface_context = WglContext { context }; + let format_desc = device.shared.describe_texture_format(config.format); + let inner = &device.shared.context.inner.lock(); - if unsafe { wglShareLists(inner.context.context, surface_context.context) } == FALSE { - log::error!( - "unable to share objects between OpenGL contexts: {}", - Error::last_os_error() - ); + if let Err(e) = inner.context.make_current(dc.device) { + log::error!("unable to make the OpenGL context current for surface: {e}",); return Err(crate::SurfaceError::Other( - "unable to share objects between OpenGL contexts", + "unable to make the OpenGL context current for surface", )); } - if let Err(e) = surface_context.make_current(dc.device) { - log::error!("unable to make the surface OpengL context current: {e}",); - return Err(crate::SurfaceError::Other( - "unable to make the surface OpengL context current", - )); - } + let gl = &inner.gl; + let renderbuffer = unsafe { gl.create_renderbuffer() }.map_err(|error| { + log::error!("Internal swapchain renderbuffer creation failed: {error}"); + crate::DeviceError::OutOfMemory + })?; + unsafe { gl.bind_renderbuffer(glow::RENDERBUFFER, Some(renderbuffer)) }; + unsafe { + gl.renderbuffer_storage( + glow::RENDERBUFFER, + format_desc.internal, + config.extent.width as _, + config.extent.height as _, + ) + }; + let framebuffer = unsafe { gl.create_framebuffer() }.map_err(|error| { + log::error!("Internal swapchain framebuffer creation failed: {error}"); + crate::DeviceError::OutOfMemory + })?; + unsafe { gl.bind_framebuffer(glow::READ_FRAMEBUFFER, Some(framebuffer)) }; + unsafe { + gl.framebuffer_renderbuffer( + glow::READ_FRAMEBUFFER, + glow::COLOR_ATTACHMENT0, + glow::RENDERBUFFER, + Some(renderbuffer), + ) + }; + unsafe { gl.bind_renderbuffer(glow::RENDERBUFFER, None) }; + unsafe { gl.bind_framebuffer(glow::READ_FRAMEBUFFER, None) }; + + // Setup presentation mode let extra = Wgl::load_with(|name| load_gl_func(name, None)); let extentions = extensions(&extra, dc.device); if !(extentions.contains("WGL_EXT_swap_control") && extra.SwapIntervalEXT.is_loaded()) { @@ -673,58 +662,7 @@ impl crate::Surface for Surface { return Err(crate::SurfaceError::Other("unable to set swap interval")); } - let surface_gl = unsafe { - glow::Context::from_loader_function(|name| { - load_gl_func(name, Some(inner.opengl_module)) - }) - }; - - // Check that the surface context OpenGL is new enough to support framebuffers. - let version = unsafe { gl.get_parameter_string(glow::VERSION) }; - let version = super::Adapter::parse_full_version(&version); - match version { - Ok(version) => { - if version < (3, 0) { - log::error!( - "surface context OpenGL version ({}.{}) too old", - version.0, - version.1 - ); - return Err(crate::SurfaceError::Other( - "surface context OpenGL version too old", - )); - } - } - Err(e) => { - log::error!("unable to parse surface context OpenGL version: {e}",); - return Err(crate::SurfaceError::Other( - "unable to parse surface context OpenGL version", - )); - } - } - - let framebuffer = unsafe { surface_gl.create_framebuffer() }.map_err(|error| { - log::error!("Internal swapchain framebuffer creation failed: {error}"); - crate::DeviceError::OutOfMemory - })?; - unsafe { surface_gl.bind_framebuffer(glow::READ_FRAMEBUFFER, Some(framebuffer)) }; - unsafe { - surface_gl.framebuffer_renderbuffer( - glow::READ_FRAMEBUFFER, - glow::COLOR_ATTACHMENT0, - glow::RENDERBUFFER, - Some(renderbuffer), - ) - }; - unsafe { surface_gl.bind_renderbuffer(glow::RENDERBUFFER, None) }; - unsafe { surface_gl.bind_framebuffer(glow::READ_FRAMEBUFFER, None) }; - - unsafe { surface_gl.bind_framebuffer(glow::DRAW_FRAMEBUFFER, None) }; - unsafe { surface_gl.bind_framebuffer(glow::READ_FRAMEBUFFER, Some(framebuffer)) }; - self.swapchain = Some(Swapchain { - surface_context, - surface_gl, renderbuffer, framebuffer, extent: config.extent,