From af6b49a47d7ef7f1c9d8065f1edd4bf63cce8f5e Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Wed, 7 Jun 2023 09:42:38 +0200 Subject: [PATCH] Simplify FemtoVG renderer API For wasm builds, just require the canvas element. --- internal/backends/winit/renderer/femtovg.rs | 13 +++++ .../winit/renderer/femtovg/glcontext.rs | 48 ++++--------------- internal/renderers/femtovg/lib.rs | 22 ++++++++- 3 files changed, 43 insertions(+), 40 deletions(-) diff --git a/internal/backends/winit/renderer/femtovg.rs b/internal/backends/winit/renderer/femtovg.rs index 7319b1b4054..2175300a080 100644 --- a/internal/backends/winit/renderer/femtovg.rs +++ b/internal/backends/winit/renderer/femtovg.rs @@ -9,6 +9,7 @@ use i_slint_renderer_femtovg::FemtoVGRenderer; #[cfg(target_arch = "wasm32")] use winit::platform::web::WindowExtWebSys; +#[cfg(not(target_arch = "wasm32"))] mod glcontext; pub struct GlutinFemtoVGRenderer { @@ -19,11 +20,23 @@ impl super::WinitCompatibleRenderer for GlutinFemtoVGRenderer { fn new( window_builder: winit::window::WindowBuilder, ) -> Result<(Self, winit::window::Window), PlatformError> { + #[cfg(not(target_arch = "wasm32"))] let (winit_window, opengl_context) = crate::event_loop::with_window_target(|event_loop| { glcontext::OpenGLContext::new_context(window_builder, event_loop.event_loop_target()) })?; + #[cfg(target_arch = "wasm32")] + let winit_window = crate::event_loop::with_window_target(|event_loop| { + window_builder.build(event_loop.event_loop_target()).map_err(|winit_os_err| { + format!( + "FemtoVG Renderer: Could not create winit window wrapper for DOM canvas: {}", + winit_os_err + ) + }) + })?; + let renderer = FemtoVGRenderer::new( + #[cfg(not(target_arch = "wasm32"))] opengl_context, #[cfg(target_arch = "wasm32")] winit_window.canvas(), diff --git a/internal/backends/winit/renderer/femtovg/glcontext.rs b/internal/backends/winit/renderer/femtovg/glcontext.rs index 483788d76f2..10f96ce3362 100644 --- a/internal/backends/winit/renderer/femtovg/glcontext.rs +++ b/internal/backends/winit/renderer/femtovg/glcontext.rs @@ -1,7 +1,6 @@ // Copyright © SixtyFPS GmbH // SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-commercial -#[cfg(not(target_arch = "wasm32"))] use glutin::{ context::{ContextApi, ContextAttributesBuilder}, display::GetGlDisplay, @@ -9,19 +8,15 @@ use glutin::{ surface::{SurfaceAttributesBuilder, WindowSurface}, }; use i_slint_core::{api::PhysicalSize, platform::PlatformError}; -#[cfg(not(target_arch = "wasm32"))] use raw_window_handle::HasRawWindowHandle; pub struct OpenGLContext { - #[cfg(not(target_arch = "wasm32"))] context: glutin::context::PossiblyCurrentContext, - #[cfg(not(target_arch = "wasm32"))] surface: glutin::surface::Surface, } unsafe impl i_slint_renderer_femtovg::OpenGLContextWrapper for OpenGLContext { fn ensure_current(&self) -> Result<(), PlatformError> { - #[cfg(not(target_arch = "wasm32"))] if !self.context.is_current() { self.context.make_current(&self.surface).map_err(|glutin_error| -> PlatformError { format!("FemtoVG: Error making context current: {glutin_error}").into() @@ -30,7 +25,6 @@ unsafe impl i_slint_renderer_femtovg::OpenGLContextWrapper for OpenGLContext { Ok(()) } fn swap_buffers(&self) -> Result<(), PlatformError> { - #[cfg(not(target_arch = "wasm32"))] self.surface.swap_buffers(&self.context).map_err(|glutin_error| -> PlatformError { format!("FemtoVG: Error swapping buffers: {glutin_error}").into() })?; @@ -39,35 +33,25 @@ unsafe impl i_slint_renderer_femtovg::OpenGLContextWrapper for OpenGLContext { } fn resize(&self, _size: PhysicalSize) -> Result<(), PlatformError> { - #[cfg(not(target_arch = "wasm32"))] - { - let width = _size.width.try_into().map_err(|_| { - format!( - "Attempting to create window surface with an invalid width: {}", - _size.width - ) - })?; - let height = _size.height.try_into().map_err(|_| { - format!( - "Attempting to create window surface with an invalid height: {}", - _size.height - ) - })?; + let width = _size.width.try_into().map_err(|_| { + format!("Attempting to create window surface with an invalid width: {}", _size.width) + })?; + let height = _size.height.try_into().map_err(|_| { + format!("Attempting to create window surface with an invalid height: {}", _size.height) + })?; + + self.ensure_current()?; + self.surface.resize(&self.context, width, height); - self.ensure_current()?; - self.surface.resize(&self.context, width, height); - } Ok(()) } - #[cfg(not(target_arch = "wasm32"))] fn get_proc_address(&self, name: &std::ffi::CStr) -> *const std::ffi::c_void { self.context.display().get_proc_address(name) } } impl OpenGLContext { - #[cfg(not(target_arch = "wasm32"))] pub fn new_context( window_builder: winit::window::WindowBuilder, window_target: &winit::event_loop::EventLoopWindowTarget, @@ -181,18 +165,4 @@ impl OpenGLContext { Ok((window, Self { context, surface })) } - - #[cfg(target_arch = "wasm32")] - pub fn new_context( - window_builder: winit::window::WindowBuilder, - window_target: &winit::event_loop::EventLoopWindowTarget, - ) -> Result<(winit::window::Window, Self), PlatformError> { - let window = window_builder.build(window_target).map_err(|winit_os_err| { - format!( - "FemtoVG Renderer: Could not create winit window wrapper for DOM canvas: {}", - winit_os_err - ) - })?; - Ok((window, Self {})) - } } diff --git a/internal/renderers/femtovg/lib.rs b/internal/renderers/femtovg/lib.rs index 040321a6d71..26b4d33d564 100644 --- a/internal/renderers/femtovg/lib.rs +++ b/internal/renderers/femtovg/lib.rs @@ -49,6 +49,23 @@ pub unsafe trait OpenGLContextWrapper { fn get_proc_address(&self, name: &std::ffi::CStr) -> *const std::ffi::c_void; } +#[cfg(target_arch = "wasm32")] +struct WebGLNeedsNoCurrentContext; +#[cfg(target_arch = "wasm32")] +unsafe impl OpenGLContextWrapper for WebGLNeedsNoCurrentContext { + fn ensure_current(&self) -> Result<(), PlatformError> { + Ok(()) + } + + fn swap_buffers(&self) -> Result<(), PlatformError> { + Ok(()) + } + + fn resize(&self, _size: PhysicalWindowSize) -> Result<(), PlatformError> { + Ok(()) + } +} + /// Use the FemtoVG renderer when implementing a custom Slint platform where you deliver events to /// Slint and want the scene to be rendered using OpenGL and the FemtoVG renderer. pub struct FemtoVGRenderer { @@ -69,9 +86,12 @@ impl FemtoVGRenderer { /// over when the make the context current, how to retrieve the address of GL functions, and when /// to swap back and front buffers. pub fn new( - opengl_context: impl OpenGLContextWrapper + 'static, + #[cfg(not(target_arch = "wasm32"))] opengl_context: impl OpenGLContextWrapper + 'static, #[cfg(target_arch = "wasm32")] html_canvas: web_sys::HtmlCanvasElement, ) -> Result { + #[cfg(target_arch = "wasm32")] + let opengl_context = WebGLNeedsNoCurrentContext {}; + let opengl_context = Box::new(opengl_context); #[cfg(not(target_arch = "wasm32"))] let gl_renderer = unsafe {